diff --git a/src/examples/nfc-list.c b/src/examples/nfc-list.c index 2e80fd3..967a5fa 100644 --- a/src/examples/nfc-list.c +++ b/src/examples/nfc-list.c @@ -121,5 +121,5 @@ int main(int argc, const char* argv[]) } nfc_disconnect(pnd); - return 1; + return 0; } diff --git a/src/lib/chips/pn53x.c b/src/lib/chips/pn53x.c index f4b841f..e0b9bd3 100644 --- a/src/lib/chips/pn53x.c +++ b/src/lib/chips/pn53x.c @@ -21,6 +21,8 @@ * @brief PN531, PN532 and PN533 common functions */ +#include + #include "pn53x.h" #include "bitutils.h" diff --git a/src/lib/drivers.h b/src/lib/drivers.h index dbaf9f8..716a8a9 100644 --- a/src/lib/drivers.h +++ b/src/lib/drivers.h @@ -42,16 +42,16 @@ #define MAX_FRAME_LEN 264 const static struct driver_callbacks drivers_callbacks_list[] = { -// Driver Name Connect Transceive Disconnect +// Driver Name List Devices Connect Transceive Disconnect #ifdef HAVE_PCSC_LITE - { "ACR122", acr122_connect, acr122_transceive, acr122_disconnect }, + { ACR122_DRIVER_NAME, acr122_list_devices, acr122_connect, acr122_transceive, acr122_disconnect }, #endif /* HAVE_PCSC_LITE */ #ifdef HAVE_LIBUSB - { "PN531USB", pn531_usb_connect, pn531_usb_transceive, pn531_usb_disconnect }, - { "PN533USB", pn533_usb_connect, pn533_usb_transceive, pn533_usb_disconnect }, + { PN531_USB_DRIVER_NAME, NULL, pn531_usb_connect, pn531_usb_transceive, pn531_usb_disconnect }, + { PN533_USB_DRIVER_NAME, NULL, pn533_usb_connect, pn533_usb_transceive, pn533_usb_disconnect }, #endif /* HAVE_LIBUSB */ - { "PN532_UART", pn532_uart_connect, pn532_uart_transceive, pn532_uart_disconnect }, - { "ARYGON", arygon_connect, arygon_transceive, arygon_disconnect } + { PN532_UART_DRIVER_NAME, NULL, pn532_uart_connect, pn532_uart_transceive, pn532_uart_disconnect }, + { ARYGON_DRIVER_NAME, NULL, arygon_connect, arygon_transceive, arygon_disconnect } }; #endif // __NFC_DRIVERS_H__ diff --git a/src/lib/drivers/acr122.c b/src/lib/drivers/acr122.c index 646e555..841665b 100644 --- a/src/lib/drivers/acr122.c +++ b/src/lib/drivers/acr122.c @@ -21,15 +21,15 @@ * @brief */ -#include "acr122.h" - #include #include #include #include +#include "acr122.h" #include "../drivers.h" + // Bus #include @@ -61,109 +61,165 @@ typedef struct { SCARD_IO_REQUEST ioCard; } acr122_spec_t; -nfc_device_t* acr122_connect(const nfc_device_desc_t* pndd) +nfc_device_desc_t * +acr122_pick_device (void) { - char* pacReaders[DRIVERS_MAX_DEVICES]; - char acList[256+64*DRIVERS_MAX_DEVICES]; - size_t szListLen = sizeof(acList); - size_t szPos; - uint32_t uiReaderCount; - uint32_t uiReader; - uint32_t uiDevIndex; - nfc_device_t* pnd; - acr122_spec_t* pas; + nfc_device_desc_t *pndd; + + if ((pndd = malloc (sizeof (*pndd)))) { + size_t szN; + + if (!acr122_list_devices (&pndd, 1, &szN)) { + ERR("acr122_list_devices failed"); + return NULL; + } + + if (szN == 0) { + ERR("No device found"); + return NULL; + } + } + + return pndd; +} + +/** + * @fn bool acr122_list_devices(nfc_device_desc_t *pnddDevices[], size_t szDevices, size_t *pszDeviceFound) + * @brief List connected devices + * + * Probe PCSC to find NFC capable hardware. + * + * @param pnddDevices Array of nfc_device_desc_t previously allocated by the caller. + * @param szDevices size of the pnddDevices array. + * @param pszDeviceFound number of devices found. + * @return true if succeeded, false otherwise. + */ +bool +acr122_list_devices(nfc_device_desc_t *pnddDevices[], size_t szDevices, size_t *pszDeviceFound) +{ + size_t szPos = 0; + char acDeviceNames[256+64*DRIVERS_MAX_DEVICES]; + size_t szDeviceNamesLen = sizeof(acDeviceNames); acr122_spec_t as; - char* pcFirmware; + uint32_t uiBusIndex = 0; + char *pcFirmware; // Clear the reader list - memset(acList,0x00,szListLen); + memset(acDeviceNames, '\0', szDeviceNamesLen); + + *pszDeviceFound = 0; // Test if context succeeded - if (SCardEstablishContext(SCARD_SCOPE_USER,NULL,NULL,&(as.hCtx)) != SCARD_S_SUCCESS) return NULL; + if (SCardEstablishContext(SCARD_SCOPE_USER,NULL,NULL,&(as.hCtx)) != SCARD_S_SUCCESS) return false; // Retrieve the string array of all available pcsc readers - if (SCardListReaders(as.hCtx,NULL,acList,(void*)&szListLen) != SCARD_S_SUCCESS) return NULL; + if (SCardListReaders(as.hCtx,NULL,acDeviceNames,(void*)&szDeviceNamesLen) != SCARD_S_SUCCESS) return false; DBG("PCSC reports following device(s):"); - DBG("- %s",acList); - pacReaders[0] = acList; - uiReaderCount = 1; - for (szPos=0; szPosuiIndex; - } - - // Iterate through all readers and try to find the ACR122 on requested index - for (uiReader=0; uiReader2.0 - if (SCardConnect(as.hCtx,pacReaders[uiReader],SCARD_SHARE_DIRECT,0,&(as.hCard),(void*)&(as.ioCard.dwProtocol)) != SCARD_S_SUCCESS) - { - // We can not connect to this device, we will just ignore it - continue; - } - } - // Configure I/O settings for card communication - as.ioCard.cbPciLength = sizeof(SCARD_IO_REQUEST); + // Configure I/O settings for card communication + as.ioCard.cbPciLength = sizeof(SCARD_IO_REQUEST); - // Retrieve the current firmware version - pcFirmware = acr122_firmware((nfc_device_t*)&as); - if (strstr(pcFirmware,FIRMWARE_TEXT) != NULL) + // Retrieve the current firmware version + pcFirmware = acr122_firmware((nfc_device_t*)&as); + if (strstr(pcFirmware,FIRMWARE_TEXT) != NULL) + { + // Supported ACR122 device found + strncpy(pnddDevices[*pszDeviceFound]->acDevice, acDeviceNames + szPos, BUFSIZ - 1); + pnddDevices[*pszDeviceFound]->acDevice[BUFSIZ - 1] = '\0'; + pnddDevices[*pszDeviceFound]->pcDriver = ACR122_DRIVER_NAME; + pnddDevices[*pszDeviceFound]->uiBusIndex = uiBusIndex; + (*pszDeviceFound)++; + } + else + { + DBG("Firmware version mismatch"); + } + SCardDisconnect(as.hCard,SCARD_LEAVE_CARD); + SCardReleaseContext(as.hCtx); + } + else { - // We found a occurence, test if it has the right index - if (uiDevIndex != 0) - { - // Let's look for the next reader - uiDevIndex--; - continue; - } - - // Allocate memory and store the device specification - pas = malloc(sizeof(acr122_spec_t)); - *pas = as; - - // Done, we found the reader we are looking for - pnd = malloc(sizeof(nfc_device_t)); - strcpy(pnd->acName,pcFirmware); - pnd->nc = NC_PN532; - pnd->nds = (nfc_device_spec_t)pas; - pnd->bActive = true; - pnd->bCrc = true; - pnd->bPar = true; - pnd->ui8TxBits = 0; - return pnd; + DBG("Can't contact emulator card"); } + + // Find next device name position + while (acDeviceNames[szPos++] != '\0'); } - // Too bad, the reader could not be located; - return NULL; + return true; +} + +nfc_device_t* acr122_connect(const nfc_device_desc_t* pndd) +{ + nfc_device_t* pnd = NULL; + acr122_spec_t as; + acr122_spec_t* pas; + char* pcFirmware; + + bool bPnddLocallyAllocated = false; + + // If no description is provided, pick a device automagically. + if (pndd == NULL) + { + pndd = acr122_pick_device(); + if (pndd == NULL) return NULL; + + bPnddLocallyAllocated = true; + } + + // Test if context succeeded + if (SCardEstablishContext(SCARD_SCOPE_USER,NULL,NULL,&(as.hCtx)) != SCARD_S_SUCCESS) + { + if (bPnddLocallyAllocated == true) free (pndd); + return NULL; + } + + // Test if we were able to connect to the "emulator" card + if (SCardConnect(as.hCtx,pndd->acDevice,SCARD_SHARE_EXCLUSIVE,SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,&(as.hCard),(void*)&(as.ioCard.dwProtocol)) != SCARD_S_SUCCESS) + { + // Connect to ACR122 firmware version >2.0 + if (SCardConnect(as.hCtx,pndd->acDevice,SCARD_SHARE_DIRECT,0,&(as.hCard),(void*)&(as.ioCard.dwProtocol)) != SCARD_S_SUCCESS) + { + // We can not connect to this device. + if (bPnddLocallyAllocated == true) free (pndd); + return NULL; + } + } + // Configure I/O settings for card communication + as.ioCard.cbPciLength = sizeof(SCARD_IO_REQUEST); + + // Retrieve the current firmware version + pcFirmware = acr122_firmware((nfc_device_t*)&as); + if (strstr(pcFirmware,FIRMWARE_TEXT) != NULL) + { + // Allocate memory and store the device specification + pas = malloc(sizeof(acr122_spec_t)); + *pas = as; + + // Done, we found the reader we are looking for + pnd = malloc(sizeof(nfc_device_t)); + strncpy(pnd->acName,pcFirmware, DEVICE_NAME_LENGTH - 1); + pnd->acName[DEVICE_NAME_LENGTH - 1] = '\0'; + pnd->nc = NC_PN532; + pnd->nds = (nfc_device_spec_t)pas; + pnd->bActive = true; + pnd->bCrc = true; + pnd->bPar = true; + pnd->ui8TxBits = 0; + } + + if (bPnddLocallyAllocated == true) free (pndd); + + return pnd; } void acr122_disconnect(nfc_device_t* pnd) diff --git a/src/lib/drivers/acr122.h b/src/lib/drivers/acr122.h index e5982c3..b2278f6 100644 --- a/src/lib/drivers/acr122.h +++ b/src/lib/drivers/acr122.h @@ -21,8 +21,8 @@ * @brief */ -#ifndef _LIBNFC_DEV_ACR122_H_ -#define _LIBNFC_DEV_ACR122_H_ +#ifndef __NFC_DRIVER_ACR122_H__ +#define __NFC_DRIVER_ACR122_H__ #include #include @@ -30,6 +30,11 @@ #include "nfc-types.h" +#define ACR122_DRIVER_NAME "ACR122" + +nfc_device_desc_t* acr122_pick_device(void); +bool acr122_list_devices(nfc_device_desc_t *pnddDevices[], size_t szDevices, size_t *pszDeviceFound); + // Functions used by developer to handle connection to this device nfc_device_t* acr122_connect(const nfc_device_desc_t* pndd); void acr122_disconnect(nfc_device_t* pnd); @@ -41,5 +46,5 @@ bool acr122_transceive(const nfc_device_spec_t nds, const byte_t* pbtTx, const s char* acr122_firmware(const nfc_device_spec_t nds); bool acr122_led_red(const nfc_device_spec_t nds, bool bOn); -#endif // _LIBNFC_DEV_ACR122_H_ +#endif // ! __NFC_DRIVER_ACR122_H__ diff --git a/src/lib/drivers/arygon.c b/src/lib/drivers/arygon.c index 2b329a5..094af68 100644 --- a/src/lib/drivers/arygon.c +++ b/src/lib/drivers/arygon.c @@ -21,6 +21,8 @@ * @brief */ +#include + #include "arygon.h" #include "nfc-messages.h" diff --git a/src/lib/drivers/arygon.h b/src/lib/drivers/arygon.h index d84eeae..b6fffc9 100644 --- a/src/lib/drivers/arygon.h +++ b/src/lib/drivers/arygon.h @@ -21,12 +21,13 @@ * @brief */ -#ifndef _LIBNFC_DEV_ARYGON_H_ -#define _LIBNFC_DEV_ARYGON_H_ - +#ifndef __NFC_DRIVER_ARYGON_H__ +#define __NFC_DRIVER_ARYGON_H__ #include "nfc-types.h" +#define ARYGON_DRIVER_NAME "ARYGON" + // Functions used by developer to handle connection to this device nfc_device_t* arygon_connect(const nfc_device_desc_t* pndd); void arygon_disconnect(nfc_device_t* pnd); @@ -34,5 +35,5 @@ void arygon_disconnect(nfc_device_t* pnd); // Callback function used by libnfc to transmit commands to the PN53X chip bool arygon_transceive(const nfc_device_spec_t nds, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); -#endif // _LIBNFC_DEV_ARYGON_H_ +#endif // ! __NFC_DRIVER_ARYGON_H__ diff --git a/src/lib/drivers/pn531_usb.c b/src/lib/drivers/pn531_usb.c index 69cdcec..b3c3392 100644 --- a/src/lib/drivers/pn531_usb.c +++ b/src/lib/drivers/pn531_usb.c @@ -24,18 +24,20 @@ /* Thanks to d18c7db and Okko for example code */ -#include "pn531_usb.h" +#include #include #include #include +#include "pn531_usb.h" #include "../drivers.h" // Bus #include #include "nfc-messages.h" +#include "../bitutils.h" #define BUFFER_LENGTH 256 #define USB_TIMEOUT 30000 @@ -107,7 +109,7 @@ nfc_device_t* pn531_usb_connect(const nfc_device_desc_t* pndd) if( pndd == NULL ) { uiDevIndex = 0; } else { - uiDevIndex = pndd->uiIndex; + uiDevIndex = pndd->uiBusIndex; } for (bus = usb_get_busses(); bus; bus = bus->next) diff --git a/src/lib/drivers/pn531_usb.h b/src/lib/drivers/pn531_usb.h index 8cc1c24..e7b0a45 100644 --- a/src/lib/drivers/pn531_usb.h +++ b/src/lib/drivers/pn531_usb.h @@ -21,15 +21,16 @@ * @brief */ -#ifndef _LIBNFC_DEV_PN531_H_ -#define _LIBNFC_DEV_PN531_H_ +#ifndef __NFC_DRIVER_PN531_USB_H__ +#define __NFC_DRIVER_PN531_USB_H__ #include #include - #include "nfc-types.h" +#define PN531_USB_DRIVER_NAME "PN531_USB" + // Functions used by developer to handle connection to this device nfc_device_t* pn531_usb_connect(const nfc_device_desc_t* pndd); void pn531_usb_disconnect(nfc_device_t* pnd); @@ -37,5 +38,5 @@ void pn531_usb_disconnect(nfc_device_t* pnd); // Callback function used by libnfc to transmit commands to the PN53X chip bool pn531_usb_transceive(const nfc_device_spec_t nds, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); -#endif // _LIBNFC_DEV_PN531_H_ +#endif // ! __NFC_DRIVER_PN531_USB_H__ diff --git a/src/lib/drivers/pn532_uart.c b/src/lib/drivers/pn532_uart.c index c49b317..10843b0 100644 --- a/src/lib/drivers/pn532_uart.c +++ b/src/lib/drivers/pn532_uart.c @@ -21,6 +21,8 @@ * @brief */ +#include + #include "pn532_uart.h" #include "nfc-messages.h" diff --git a/src/lib/drivers/pn532_uart.h b/src/lib/drivers/pn532_uart.h index 5392107..944058c 100644 --- a/src/lib/drivers/pn532_uart.h +++ b/src/lib/drivers/pn532_uart.h @@ -21,12 +21,13 @@ * @brief */ -#ifndef _LIBNFC_DEV_PN532_UART_H_ -#define _LIBNFC_DEV_PN532_UART_H_ - +#ifndef __NFC_DRIVER_PN532_UART_H__ +#define __NFC_DRIVER_PN532_UART_H__ #include "nfc-types.h" +#define PN532_UART_DRIVER_NAME "PN532_UART" + // Functions used by developer to handle connection to this device nfc_device_t* pn532_uart_connect(const nfc_device_desc_t* pndd); void pn532_uart_disconnect(nfc_device_t* pnd); @@ -34,5 +35,5 @@ void pn532_uart_disconnect(nfc_device_t* pnd); // Callback function used by libnfc to transmit commands to the PN53X chip bool pn532_uart_transceive(const nfc_device_spec_t nds, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); -#endif // _LIBNFC_DEV_PN532_UART_H_ +#endif // ! __NFC_DRIVER_PN532_UART_H__ diff --git a/src/lib/drivers/pn533_usb.c b/src/lib/drivers/pn533_usb.c index ae770b2..d4041d5 100644 --- a/src/lib/drivers/pn533_usb.c +++ b/src/lib/drivers/pn533_usb.c @@ -24,11 +24,12 @@ /* Thanks to d18c7db and Okko for example code */ -#include "pn533_usb.h" +#include #include #include +#include "pn533_usb.h" #include "../drivers.h" // Bus @@ -104,7 +105,7 @@ nfc_device_t* pn533_usb_connect(const nfc_device_desc_t* pndd) if( pndd == NULL ) { uiDevIndex = 0; } else { - uiDevIndex = pndd->uiIndex; + uiDevIndex = pndd->uiBusIndex; } for (bus = usb_get_busses(); bus; bus = bus->next) diff --git a/src/lib/drivers/pn533_usb.h b/src/lib/drivers/pn533_usb.h index 7db9801..ce662f2 100644 --- a/src/lib/drivers/pn533_usb.h +++ b/src/lib/drivers/pn533_usb.h @@ -21,12 +21,13 @@ * @brief */ -#ifndef _LIBNFC_DEV_PN533_H_ -#define _LIBNFC_DEV_PN533_H_ - +#ifndef __NFC_DRIVER_PN533_USB_H__ +#define __NFC_DRIVER_PN533_USB_H__ #include "nfc-types.h" +#define PN533_USB_DRIVER_NAME "PN533_USB" + // Functions used by developer to handle connection to this device nfc_device_t* pn533_usb_connect(const nfc_device_desc_t* pndd); void pn533_usb_disconnect(nfc_device_t* pnd); @@ -34,5 +35,5 @@ void pn533_usb_disconnect(nfc_device_t* pnd); // Callback function used by libnfc to transmit commands to the PN53X chip bool pn533_usb_transceive(const nfc_device_spec_t nds, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); -#endif // _LIBNFC_DEV_PN533_H_ +#endif // ! __NFC_DRIVER_PN533_USB_H__ diff --git a/src/lib/nfc-types.h b/src/lib/nfc-types.h index d02ec46..83f4d76 100644 --- a/src/lib/nfc-types.h +++ b/src/lib/nfc-types.h @@ -78,14 +78,16 @@ typedef struct { * This struct is used to try to connect to a specified nfc device when nfc_connect(...) */ typedef struct { - /** Driver name (ie. PN532)*/ + /** Device name (e.g. "ACS ACR 38U-CCID 00 00") */ + char acDevice[BUFSIZ]; + /** Driver name (e.g. "PN532_UART")*/ char* pcDriver; - /** Port (ie. /dev/ttyUSB0) */ + /** Port (e.g. "/dev/ttyUSB0") */ char* pcPort; - /** Port speed (ie. 115200) */ + /** Port speed (e.g. "115200") */ uint32_t uiSpeed; /** Device index for backward compatibility (used to choose one specific device in USB or PSCS devices list) */ - uint32_t uiIndex; + uint32_t uiBusIndex; } nfc_device_desc_t; /** @@ -95,6 +97,8 @@ typedef struct { struct driver_callbacks { /** Driver name */ const char* acDriver; + /** List devices callback */ + bool (*list_devices)(nfc_device_desc_t *pnddDevices[], size_t szDevices, size_t *pszDeviceFound); /** Connect callback */ nfc_device_t* (*connect)(const nfc_device_desc_t* pndd); /** Transceive callback */ @@ -148,7 +152,7 @@ typedef enum { /** Active DEP */ NM_ACTIVE_DEP = 0x05, /** Passive DEP */ - NM_PASSIVE_DEP = 0x06, + NM_PASSIVE_DEP = 0x06 } nfc_modulation_t; /** @@ -235,7 +239,7 @@ typedef enum { MC_TRANSFER = 0xB0, MC_DECREMENT = 0xC0, MC_INCREMENT = 0xC1, - MC_STORE = 0xC2, + MC_STORE = 0xC2 }mifare_cmd; // MIFARE Classic command params diff --git a/src/lib/nfc.c b/src/lib/nfc.c index 793582d..d9dcc0b 100644 --- a/src/lib/nfc.c +++ b/src/lib/nfc.c @@ -21,12 +21,13 @@ * @brief NFC library implementation */ -#include "nfc.h" #include #include #include +#include "nfc.h" + #include "chips.h" #include "drivers.h"