libnfc 1.3.9
|
00001 /*- 00002 * Public platform independent Near Field Communication (NFC) library 00003 * 00004 * Copyright (C) 2009, Roel Verdult 00005 * 00006 * This program is free software: you can redistribute it and/or modify it 00007 * under the terms of the GNU Lesser General Public License as published by the 00008 * Free Software Foundation, either version 3 of the License, or (at your 00009 * option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, but WITHOUT 00012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 00014 * more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/> 00018 */ 00019 00025 #ifdef HAVE_CONFIG_H 00026 # include "config.h" 00027 #endif // HAVE_CONFIG_H 00028 00029 #include <stdio.h> 00030 #include <stdlib.h> 00031 #include <stddef.h> 00032 #include <string.h> 00033 00034 #include "acr122.h" 00035 #include "../drivers.h" 00036 00037 // Bus 00038 #include <winscard.h> 00039 00040 #ifdef __APPLE__ 00041 # include <wintypes.h> 00042 #endif 00043 00044 #include <nfc/nfc.h> 00045 #include <nfc/nfc-messages.h> 00046 00047 // WINDOWS: #define IOCTL_CCID_ESCAPE_SCARD_CTL_CODE SCARD_CTL_CODE(3500) 00048 #define IOCTL_CCID_ESCAPE_SCARD_CTL_CODE (((0x31) << 16) | ((3500) << 2)) 00049 #define SCARD_OPERATION_SUCCESS 0x61 00050 #define SCARD_OPERATION_ERROR 0x63 00051 00052 #ifndef SCARD_PROTOCOL_UNDEFINED 00053 # define SCARD_PROTOCOL_UNDEFINED SCARD_PROTOCOL_UNSET 00054 #endif 00055 00056 #define FIRMWARE_TEXT "ACR122U" // Tested on: ACR122U101(ACS), ACR122U102(Tikitag), ACR122U203(ACS) 00057 00058 #define ACR122_WRAP_LEN 5 00059 #define ACR122_COMMAND_LEN 266 00060 #define ACR122_RESPONSE_LEN 268 00061 00062 const char *supported_devices[] = { 00063 "ACS ACR122", 00064 "ACS ACR 38U-CCID", 00065 " CCID USB", 00066 NULL 00067 }; 00068 00069 typedef struct { 00070 SCARDHANDLE hCard; 00071 SCARD_IO_REQUEST ioCard; 00072 } acr122_spec_t; 00073 00074 static SCARDCONTEXT _SCardContext; 00075 static int _iSCardContextRefCount = 0; 00076 00077 SCARDCONTEXT * 00078 acr122_get_scardcontext (void) 00079 { 00080 if (_iSCardContextRefCount == 0) { 00081 if (SCardEstablishContext (SCARD_SCOPE_USER, NULL, NULL, &_SCardContext) != SCARD_S_SUCCESS) 00082 return NULL; 00083 } 00084 _iSCardContextRefCount++; 00085 00086 return &_SCardContext; 00087 } 00088 00089 void 00090 acr122_free_scardcontext (void) 00091 { 00092 if (_iSCardContextRefCount) { 00093 _iSCardContextRefCount--; 00094 if (!_iSCardContextRefCount) { 00095 SCardReleaseContext (_SCardContext); 00096 } 00097 } 00098 } 00099 00100 00101 nfc_device_desc_t * 00102 acr122_pick_device (void) 00103 { 00104 nfc_device_desc_t *pndd; 00105 00106 if ((pndd = malloc (sizeof (*pndd)))) { 00107 size_t szN; 00108 00109 if (!acr122_list_devices (pndd, 1, &szN)) { 00110 DBG ("%s", "acr122_list_devices failed"); 00111 return NULL; 00112 } 00113 00114 if (szN == 0) { 00115 DBG ("%s", "No device found"); 00116 return NULL; 00117 } 00118 } 00119 00120 return pndd; 00121 } 00122 00133 bool 00134 acr122_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound) 00135 { 00136 size_t szPos = 0; 00137 char acDeviceNames[256 + 64 * DRIVERS_MAX_DEVICES]; 00138 size_t szDeviceNamesLen = sizeof (acDeviceNames); 00139 uint32_t uiBusIndex = 0; 00140 SCARDCONTEXT *pscc; 00141 bool bSupported; 00142 int i; 00143 00144 // Clear the reader list 00145 memset (acDeviceNames, '\0', szDeviceNamesLen); 00146 00147 *pszDeviceFound = 0; 00148 00149 // Test if context succeeded 00150 if (!(pscc = acr122_get_scardcontext ())) { 00151 DBG ("%s", "PCSC context not found"); 00152 return false; 00153 } 00154 // Retrieve the string array of all available pcsc readers 00155 if (SCardListReaders (*pscc, NULL, acDeviceNames, (void *) &szDeviceNamesLen) != SCARD_S_SUCCESS) 00156 return false; 00157 00158 // DBG("%s", "PCSC reports following device(s):"); 00159 00160 while ((acDeviceNames[szPos] != '\0') && ((*pszDeviceFound) < szDevices)) { 00161 uiBusIndex++; 00162 00163 // DBG("- %s (pos=%ld)", acDeviceNames + szPos, (unsigned long) szPos); 00164 00165 bSupported = false; 00166 for (i = 0; supported_devices[i] && !bSupported; i++) { 00167 int l = strlen (supported_devices[i]); 00168 bSupported = 0 == strncmp (supported_devices[i], acDeviceNames + szPos, l); 00169 } 00170 00171 if (bSupported) { 00172 // Supported ACR122 device found 00173 strncpy (pnddDevices[*pszDeviceFound].acDevice, acDeviceNames + szPos, DEVICE_NAME_LENGTH - 1); 00174 pnddDevices[*pszDeviceFound].acDevice[DEVICE_NAME_LENGTH - 1] = '\0'; 00175 pnddDevices[*pszDeviceFound].pcDriver = ACR122_DRIVER_NAME; 00176 pnddDevices[*pszDeviceFound].uiBusIndex = uiBusIndex; 00177 (*pszDeviceFound)++; 00178 } else { 00179 DBG ("PCSC device [%s] is not NFC capable or not supported by libnfc.", acDeviceNames + szPos); 00180 } 00181 00182 // Find next device name position 00183 while (acDeviceNames[szPos++] != '\0'); 00184 } 00185 acr122_free_scardcontext (); 00186 00187 if (*pszDeviceFound) 00188 return true; 00189 return false; 00190 } 00191 00192 nfc_device_t * 00193 acr122_connect (const nfc_device_desc_t * pndd) 00194 { 00195 nfc_device_t *pnd = NULL; 00196 acr122_spec_t as; 00197 acr122_spec_t *pas; 00198 char *pcFirmware; 00199 00200 SCARDCONTEXT *pscc; 00201 00202 DBG ("Attempt to connect to %s", pndd->acDevice); 00203 // Test if context succeeded 00204 if (!(pscc = acr122_get_scardcontext ())) 00205 return NULL; 00206 // Test if we were able to connect to the "emulator" card 00207 if (SCardConnect 00208 (*pscc, pndd->acDevice, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &(as.hCard), 00209 (void *) &(as.ioCard.dwProtocol)) != SCARD_S_SUCCESS) { 00210 // Connect to ACR122 firmware version >2.0 00211 if (SCardConnect (*pscc, pndd->acDevice, SCARD_SHARE_DIRECT, 0, &(as.hCard), (void *) &(as.ioCard.dwProtocol)) != 00212 SCARD_S_SUCCESS) { 00213 // We can not connect to this device. 00214 DBG ("%s", "PCSC connect failed"); 00215 return NULL; 00216 } 00217 } 00218 // Configure I/O settings for card communication 00219 as.ioCard.cbPciLength = sizeof (SCARD_IO_REQUEST); 00220 00221 // Retrieve the current firmware version 00222 pcFirmware = acr122_firmware ((nfc_device_t *) & as); 00223 if (strstr (pcFirmware, FIRMWARE_TEXT) != NULL) { 00224 // Allocate memory and store the device specification 00225 pas = malloc (sizeof (acr122_spec_t)); 00226 *pas = as; 00227 00228 // Done, we found the reader we are looking for 00229 pnd = malloc (sizeof (nfc_device_t)); 00230 strcpy (pnd->acName, pndd->acDevice); 00231 strcpy (pnd->acName + strlen (pnd->acName), " / "); 00232 strcpy (pnd->acName + strlen (pnd->acName), pcFirmware); 00233 pnd->nc = NC_PN532; 00234 pnd->nds = (nfc_device_spec_t) pas; 00235 pnd->bActive = true; 00236 pnd->bCrc = true; 00237 pnd->bPar = true; 00238 pnd->ui8TxBits = 0; 00239 return pnd; 00240 } 00241 00242 return NULL; 00243 } 00244 00245 void 00246 acr122_disconnect (nfc_device_t * pnd) 00247 { 00248 acr122_spec_t *pas = (acr122_spec_t *) pnd->nds; 00249 SCardDisconnect (pas->hCard, SCARD_LEAVE_CARD); 00250 acr122_free_scardcontext (); 00251 free (pas); 00252 free (pnd); 00253 } 00254 00255 bool 00256 acr122_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen, byte_t * pbtRx, size_t * pszRxLen) 00257 { 00258 byte_t abtRxCmd[5] = { 0xFF, 0xC0, 0x00, 0x00 }; 00259 size_t szRxCmdLen = sizeof (abtRxCmd); 00260 byte_t abtRxBuf[ACR122_RESPONSE_LEN]; 00261 size_t szRxBufLen; 00262 byte_t abtTxBuf[ACR122_WRAP_LEN + ACR122_COMMAND_LEN] = { 0xFF, 0x00, 0x00, 0x00 }; 00263 acr122_spec_t *pas = (acr122_spec_t *) pnd->nds; 00264 00265 // FIXME: Should be handled by the library. 00266 // Make sure the command does not overflow the send buffer 00267 if (szTxLen > ACR122_COMMAND_LEN) { 00268 pnd->iLastError = DEIO; 00269 return false; 00270 } 00271 // Store the length of the command we are going to send 00272 abtTxBuf[4] = szTxLen; 00273 00274 // Prepare and transmit the send buffer 00275 memcpy (abtTxBuf + 5, pbtTx, szTxLen); 00276 szRxBufLen = sizeof (abtRxBuf); 00277 #ifdef DEBUG 00278 PRINT_HEX ("TX", abtTxBuf, szTxLen + 5); 00279 #endif 00280 00281 if (pas->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED) { 00282 if (SCardControl 00283 (pas->hCard, IOCTL_CCID_ESCAPE_SCARD_CTL_CODE, abtTxBuf, szTxLen + 5, abtRxBuf, szRxBufLen, 00284 (void *) &szRxBufLen) != SCARD_S_SUCCESS) { 00285 pnd->iLastError = DEIO; 00286 return false; 00287 } 00288 } else { 00289 if (SCardTransmit (pas->hCard, &(pas->ioCard), abtTxBuf, szTxLen + 5, NULL, abtRxBuf, (void *) &szRxBufLen) != 00290 SCARD_S_SUCCESS) { 00291 pnd->iLastError = DEIO; 00292 return false; 00293 } 00294 } 00295 00296 if (pas->ioCard.dwProtocol == SCARD_PROTOCOL_T0) { 00297 // Make sure we received the byte-count we expected 00298 if (szRxBufLen != 2) { 00299 pnd->iLastError = DEIO; 00300 return false; 00301 } 00302 // Check if the operation was successful, so an answer is available 00303 if (*abtRxBuf == SCARD_OPERATION_ERROR) { 00304 pnd->iLastError = DEISERRFRAME; 00305 return false; 00306 } 00307 // Retrieve the response bytes 00308 abtRxCmd[4] = abtRxBuf[1]; 00309 szRxBufLen = sizeof (abtRxBuf); 00310 if (SCardTransmit (pas->hCard, &(pas->ioCard), abtRxCmd, szRxCmdLen, NULL, abtRxBuf, (void *) &szRxBufLen) != 00311 SCARD_S_SUCCESS) { 00312 pnd->iLastError = DEIO; 00313 return false; 00314 } 00315 } 00316 #ifdef DEBUG 00317 PRINT_HEX ("RX", abtRxBuf, szRxBufLen); 00318 #endif 00319 00320 // When the answer should be ignored, just return a succesful result 00321 if (pbtRx == NULL || pszRxLen == NULL) 00322 return true; 00323 00324 // Make sure we have an emulated answer that fits the return buffer 00325 if (szRxBufLen < 4 || (szRxBufLen - 4) > *pszRxLen) { 00326 pnd->iLastError = DEIO; 00327 return false; 00328 } 00329 // Wipe out the 4 APDU emulation bytes: D5 4B .. .. .. 90 00 00330 *pszRxLen = ((size_t) szRxBufLen) - 4; 00331 memcpy (pbtRx, abtRxBuf + 2, *pszRxLen); 00332 00333 // Transmission went successful 00334 return true; 00335 } 00336 00337 char * 00338 acr122_firmware (const nfc_device_spec_t nds) 00339 { 00340 byte_t abtGetFw[5] = { 0xFF, 0x00, 0x48, 0x00, 0x00 }; 00341 uint32_t uiResult; 00342 00343 acr122_spec_t *pas = (acr122_spec_t *) nds; 00344 static char abtFw[11]; 00345 size_t szFwLen = sizeof (abtFw); 00346 memset (abtFw, 0x00, szFwLen); 00347 if (pas->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED) { 00348 uiResult = 00349 SCardControl (pas->hCard, IOCTL_CCID_ESCAPE_SCARD_CTL_CODE, abtGetFw, sizeof (abtGetFw), abtFw, szFwLen, 00350 (void *) &szFwLen); 00351 } else { 00352 uiResult = 00353 SCardTransmit (pas->hCard, &(pas->ioCard), abtGetFw, sizeof (abtGetFw), NULL, (byte_t *) abtFw, 00354 (void *) &szFwLen); 00355 } 00356 00357 #ifdef DEBUG 00358 if (uiResult != SCARD_S_SUCCESS) { 00359 printf ("No ACR122 firmware received, Error: %08x\n", uiResult); 00360 } 00361 #endif 00362 00363 return abtFw; 00364 } 00365 00366 bool 00367 acr122_led_red (const nfc_device_spec_t nds, bool bOn) 00368 { 00369 byte_t abtLed[9] = { 0xFF, 0x00, 0x40, 0x05, 0x04, 0x00, 0x00, 0x00, 0x00 }; 00370 acr122_spec_t *pas = (acr122_spec_t *) nds; 00371 byte_t abtBuf[2]; 00372 size_t szBufLen = sizeof (abtBuf); 00373 (void) bOn; 00374 if (pas->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED) { 00375 return (SCardControl 00376 (pas->hCard, IOCTL_CCID_ESCAPE_SCARD_CTL_CODE, abtLed, sizeof (abtLed), abtBuf, szBufLen, 00377 (void *) &szBufLen) == SCARD_S_SUCCESS); 00378 } else { 00379 return (SCardTransmit 00380 (pas->hCard, &(pas->ioCard), abtLed, sizeof (abtLed), NULL, (byte_t *) abtBuf, 00381 (void *) &szBufLen) == SCARD_S_SUCCESS); 00382 } 00383 }