00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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 #include "../bitutils.h"
00037
00038
00039 #include <winscard.h>
00040
00041 #ifdef __APPLE__
00042 #include <wintypes.h>
00043 #endif
00044
00045
00046 #include <nfc/nfc-messages.h>
00047
00048
00049 #define IOCTL_CCID_ESCAPE_SCARD_CTL_CODE (((0x31) << 16) | ((3500) << 2))
00050 #define SCARD_OPERATION_SUCCESS 0x61
00051 #define SCARD_OPERATION_ERROR 0x63
00052
00053 #ifndef SCARD_PROTOCOL_UNDEFINED
00054 #define SCARD_PROTOCOL_UNDEFINED SCARD_PROTOCOL_UNSET
00055 #endif
00056
00057 #define FIRMWARE_TEXT "ACR122U" // Tested on: ACR122U101(ACS), ACR122U102(Tikitag), ACR122U203(ACS)
00058
00059 #define ACR122_WRAP_LEN 5
00060 #define ACR122_COMMAND_LEN 266
00061 #define ACR122_RESPONSE_LEN 268
00062
00063 const char *supported_devices[] = {
00064 "ACS ACR122",
00065 "ACS ACR 38U-CCID",
00066 " CCID USB",
00067 NULL
00068 };
00069
00070 typedef struct {
00071 SCARDHANDLE hCard;
00072 SCARD_IO_REQUEST ioCard;
00073 } acr122_spec_t;
00074
00075 static SCARDCONTEXT _SCardContext;
00076 static int _iSCardContextRefCount = 0;
00077
00078 SCARDCONTEXT*
00079 acr122_get_scardcontext(void)
00080 {
00081 if ( _iSCardContextRefCount == 0 )
00082 {
00083 if (SCardEstablishContext(SCARD_SCOPE_USER,NULL,NULL,&_SCardContext) != SCARD_S_SUCCESS) return NULL;
00084 }
00085 _iSCardContextRefCount++;
00086
00087 return &_SCardContext;
00088 }
00089
00090 void
00091 acr122_free_scardcontext(void)
00092 {
00093 if (_iSCardContextRefCount)
00094 {
00095 _iSCardContextRefCount--;
00096 if (!_iSCardContextRefCount)
00097 {
00098 SCardReleaseContext(_SCardContext);
00099 }
00100 }
00101 }
00102
00103
00104 nfc_device_desc_t *
00105 acr122_pick_device (void)
00106 {
00107 nfc_device_desc_t *pndd;
00108
00109 if ((pndd = malloc (sizeof (*pndd)))) {
00110 size_t szN;
00111
00112 if (!acr122_list_devices (pndd, 1, &szN)) {
00113 DBG("%s", "acr122_list_devices failed");
00114 return NULL;
00115 }
00116
00117 if (szN == 0) {
00118 DBG("%s", "No device found");
00119 return NULL;
00120 }
00121 }
00122
00123 return pndd;
00124 }
00125
00136 bool
00137 acr122_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *pszDeviceFound)
00138 {
00139 size_t szPos = 0;
00140 char acDeviceNames[256+64*DRIVERS_MAX_DEVICES];
00141 size_t szDeviceNamesLen = sizeof(acDeviceNames);
00142 uint32_t uiBusIndex = 0;
00143 SCARDCONTEXT *pscc;
00144 bool bSupported;
00145 int i;
00146
00147
00148 memset(acDeviceNames, '\0', szDeviceNamesLen);
00149
00150 *pszDeviceFound = 0;
00151
00152
00153 if (!(pscc = acr122_get_scardcontext ()))
00154 {
00155 DBG("%s","PCSC context not found");
00156 return false;
00157 }
00158
00159
00160 if (SCardListReaders(*pscc,NULL,acDeviceNames,(void*)&szDeviceNamesLen) != SCARD_S_SUCCESS) return false;
00161
00162 DBG("%s", "PCSC reports following device(s):");
00163
00164 while ((acDeviceNames[szPos] != '\0') && ((*pszDeviceFound) < szDevices)) {
00165 uiBusIndex++;
00166
00167 DBG("- %s (pos=%d)", acDeviceNames + szPos, szPos);
00168
00169 bSupported = false;
00170 for (i = 0; supported_devices[i] && !bSupported; i++) {
00171 int l = strlen(supported_devices[i]);
00172 bSupported = 0 == strncmp(supported_devices[i], acDeviceNames + szPos, l);
00173 }
00174
00175 if (bSupported)
00176 {
00177
00178 strncpy(pnddDevices[*pszDeviceFound].acDevice, acDeviceNames + szPos, DEVICE_NAME_LENGTH - 1);
00179 pnddDevices[*pszDeviceFound].acDevice[DEVICE_NAME_LENGTH - 1] = '\0';
00180 pnddDevices[*pszDeviceFound].pcDriver = ACR122_DRIVER_NAME;
00181 pnddDevices[*pszDeviceFound].uiBusIndex = uiBusIndex;
00182 (*pszDeviceFound)++;
00183 }
00184 else
00185 {
00186 DBG("PCSC device [%s] is not NFC capable or not supported by libnfc.", acDeviceNames + szPos);
00187 }
00188
00189
00190 while (acDeviceNames[szPos++] != '\0');
00191 }
00192 acr122_free_scardcontext ();
00193
00194 if(*pszDeviceFound)
00195 return true;
00196 return false;
00197 }
00198
00199 nfc_device_t* acr122_connect(const nfc_device_desc_t* pndd)
00200 {
00201 nfc_device_t* pnd = NULL;
00202 acr122_spec_t as;
00203 acr122_spec_t* pas;
00204 char* pcFirmware;
00205
00206 SCARDCONTEXT *pscc;
00207
00208 DBG("Connecting to %s",pndd->acDevice);
00209
00210 if(pndd == NULL) return NULL;
00211
00212 if (!(pscc = acr122_get_scardcontext ())) return NULL;
00213
00214 if (SCardConnect(*pscc,pndd->acDevice,SCARD_SHARE_EXCLUSIVE,SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,&(as.hCard),(void*)&(as.ioCard.dwProtocol)) != SCARD_S_SUCCESS)
00215 {
00216
00217 if (SCardConnect(*pscc,pndd->acDevice,SCARD_SHARE_DIRECT,0,&(as.hCard),(void*)&(as.ioCard.dwProtocol)) != SCARD_S_SUCCESS)
00218 {
00219
00220 DBG("%s","PCSC connect failed");
00221 return NULL;
00222 }
00223 }
00224
00225 as.ioCard.cbPciLength = sizeof(SCARD_IO_REQUEST);
00226
00227
00228 pcFirmware = acr122_firmware((nfc_device_t*)&as);
00229 if (strstr(pcFirmware,FIRMWARE_TEXT) != NULL)
00230 {
00231
00232 pas = malloc(sizeof(acr122_spec_t));
00233 *pas = as;
00234
00235
00236 pnd = malloc(sizeof(nfc_device_t));
00237 strcpy(pnd->acName,pndd->acDevice);
00238 strcpy(pnd->acName + strlen(pnd->acName)," / ");
00239 strcpy(pnd->acName + strlen(pnd->acName),pcFirmware);
00240 pnd->nc = NC_PN532;
00241 pnd->nds = (nfc_device_spec_t)pas;
00242 pnd->bActive = true;
00243 pnd->bCrc = true;
00244 pnd->bPar = true;
00245 pnd->ui8TxBits = 0;
00246 return pnd;
00247 }
00248
00249 return NULL;
00250 }
00251
00252 void acr122_disconnect(nfc_device_t* pnd)
00253 {
00254 acr122_spec_t* pas = (acr122_spec_t*)pnd->nds;
00255 SCardDisconnect(pas->hCard,SCARD_LEAVE_CARD);
00256 acr122_free_scardcontext ();
00257 free(pas);
00258 free(pnd);
00259 }
00260
00261 bool acr122_transceive(const nfc_device_spec_t nds, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen)
00262 {
00263 byte_t abtRxCmd[5] = { 0xFF,0xC0,0x00,0x00 };
00264 size_t szRxCmdLen = sizeof(abtRxCmd);
00265 byte_t abtRxBuf[ACR122_RESPONSE_LEN];
00266 size_t szRxBufLen;
00267 byte_t abtTxBuf[ACR122_WRAP_LEN+ACR122_COMMAND_LEN] = { 0xFF, 0x00, 0x00, 0x00 };
00268 acr122_spec_t* pas = (acr122_spec_t*)nds;
00269
00270
00271 if (szTxLen > ACR122_COMMAND_LEN) return false;
00272
00273
00274 abtTxBuf[4] = szTxLen;
00275
00276
00277 memcpy(abtTxBuf+5,pbtTx,szTxLen);
00278 szRxBufLen = sizeof(abtRxBuf);
00279 #ifdef DEBUG
00280 printf(" TX: ");
00281 print_hex(abtTxBuf,szTxLen+5);
00282 #endif
00283
00284 if (pas->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED)
00285 {
00286 if (SCardControl(pas->hCard,IOCTL_CCID_ESCAPE_SCARD_CTL_CODE,abtTxBuf,szTxLen+5,abtRxBuf,szRxBufLen,(void*)&szRxBufLen) != SCARD_S_SUCCESS) return false;
00287 } else {
00288 if (SCardTransmit(pas->hCard,&(pas->ioCard),abtTxBuf,szTxLen+5,NULL,abtRxBuf,(void*)&szRxBufLen) != SCARD_S_SUCCESS) return false;
00289 }
00290
00291 if (pas->ioCard.dwProtocol == SCARD_PROTOCOL_T0)
00292 {
00293
00294 if (szRxBufLen != 2) return false;
00295
00296
00297 if (*abtRxBuf == SCARD_OPERATION_ERROR) return false;
00298
00299
00300 abtRxCmd[4] = abtRxBuf[1];
00301 szRxBufLen = sizeof(abtRxBuf);
00302 if (SCardTransmit(pas->hCard,&(pas->ioCard),abtRxCmd,szRxCmdLen,NULL,abtRxBuf,(void*)&szRxBufLen) != SCARD_S_SUCCESS) return false;
00303 }
00304
00305 #ifdef DEBUG
00306 printf(" RX: ");
00307 print_hex(abtRxBuf,szRxBufLen);
00308 #endif
00309
00310
00311 if (pbtRx == NULL || pszRxLen == NULL) return true;
00312
00313
00314 if (szRxBufLen < 4 || (szRxBufLen-4) > *pszRxLen) return false;
00315
00316 *pszRxLen = ((size_t)szRxBufLen)-4;
00317 memcpy(pbtRx,abtRxBuf+2,*pszRxLen);
00318
00319
00320 return true;
00321 }
00322
00323 char* acr122_firmware(const nfc_device_spec_t nds)
00324 {
00325 byte_t abtGetFw[5] = { 0xFF,0x00,0x48,0x00,0x00 };
00326 uint32_t uiResult;
00327
00328 acr122_spec_t* pas = (acr122_spec_t*)nds;
00329 static char abtFw[11];
00330 size_t szFwLen = sizeof(abtFw);
00331 memset(abtFw,0x00,szFwLen);
00332 if (pas->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED)
00333 {
00334 uiResult = SCardControl(pas->hCard,IOCTL_CCID_ESCAPE_SCARD_CTL_CODE,abtGetFw,sizeof(abtGetFw),abtFw,szFwLen,(void*)&szFwLen);
00335 } else {
00336 uiResult = SCardTransmit(pas->hCard,&(pas->ioCard),abtGetFw,sizeof(abtGetFw),NULL,(byte_t*)abtFw,(void*)&szFwLen);
00337 }
00338
00339 #ifdef DEBUG
00340 if (uiResult != SCARD_S_SUCCESS)
00341 {
00342 printf("No ACR122 firmware received, Error: %08x\n",uiResult);
00343 }
00344 #endif
00345
00346 return abtFw;
00347 }
00348
00349 bool acr122_led_red(const nfc_device_spec_t nds, bool bOn)
00350 {
00351 byte_t abtLed[9] = { 0xFF,0x00,0x40,0x05,0x04,0x00,0x00,0x00,0x00 };
00352 acr122_spec_t* pas = (acr122_spec_t*)nds;
00353 byte_t abtBuf[2];
00354 size_t szBufLen = sizeof(abtBuf);
00355 if (pas->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED)
00356 {
00357 return (SCardControl(pas->hCard,IOCTL_CCID_ESCAPE_SCARD_CTL_CODE,abtLed,sizeof(abtLed),abtBuf,szBufLen,(void*)&szBufLen) == SCARD_S_SUCCESS);
00358 } else {
00359 return (SCardTransmit(pas->hCard,&(pas->ioCard),abtLed,sizeof(abtLed),NULL,(byte_t*)abtBuf,(void*)&szBufLen) == SCARD_S_SUCCESS);
00360 }
00361 }
00362