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