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
00037
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
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
00145 memset (acDeviceNames, '\0', szDeviceNamesLen);
00146
00147 *pszDeviceFound = 0;
00148
00149
00150 if (!(pscc = acr122_get_scardcontext ())) {
00151 DBG ("%s", "PCSC context not found");
00152 return false;
00153 }
00154
00155 if (SCardListReaders (*pscc, NULL, acDeviceNames, (void *) &szDeviceNamesLen) != SCARD_S_SUCCESS)
00156 return false;
00157
00158
00159
00160 while ((acDeviceNames[szPos] != '\0') && ((*pszDeviceFound) < szDevices)) {
00161 uiBusIndex++;
00162
00163
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
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
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
00204 if (!(pscc = acr122_get_scardcontext ()))
00205 return NULL;
00206
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
00211 if (SCardConnect (*pscc, pndd->acDevice, SCARD_SHARE_DIRECT, 0, &(as.hCard), (void *) &(as.ioCard.dwProtocol)) !=
00212 SCARD_S_SUCCESS) {
00213
00214 DBG ("%s", "PCSC connect failed");
00215 return NULL;
00216 }
00217 }
00218
00219 as.ioCard.cbPciLength = sizeof (SCARD_IO_REQUEST);
00220
00221
00222 pcFirmware = acr122_firmware ((nfc_device_t *) & as);
00223 if (strstr (pcFirmware, FIRMWARE_TEXT) != NULL) {
00224
00225 pas = malloc (sizeof (acr122_spec_t));
00226 *pas = as;
00227
00228
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
00266
00267 if (szTxLen > ACR122_COMMAND_LEN) {
00268 pnd->iLastError = DEIO;
00269 return false;
00270 }
00271
00272 abtTxBuf[4] = szTxLen;
00273
00274
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
00298 if (szRxBufLen != 2) {
00299 pnd->iLastError = DEIO;
00300 return false;
00301 }
00302
00303 if (*abtRxBuf == SCARD_OPERATION_ERROR) {
00304 pnd->iLastError = DEISERRFRAME;
00305 return false;
00306 }
00307
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
00321 if (pbtRx == NULL || pszRxLen == NULL)
00322 return true;
00323
00324
00325 if (szRxBufLen < 4 || (szRxBufLen - 4) > *pszRxLen) {
00326 pnd->iLastError = DEIO;
00327 return false;
00328 }
00329
00330 *pszRxLen = ((size_t) szRxBufLen) - 4;
00331 memcpy (pbtRx, abtRxBuf + 2, *pszRxLen);
00332
00333
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 }