diff --git a/examples/nfc-dep-target.c b/examples/nfc-dep-target.c index d902c56..031db8f 100644 --- a/examples/nfc-dep-target.c +++ b/examples/nfc-dep-target.c @@ -66,16 +66,16 @@ main (int argc, const char *argv[]) size_t szDeviceFound; byte_t abtTx[] = "Hello Mars!"; #define MAX_DEVICE_COUNT 2 - nfc_device_desc_t pnddDevices[MAX_DEVICE_COUNT]; - nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szDeviceFound); + nfc_connstring connstrings[MAX_DEVICE_COUNT]; + nfc_list_devices (connstrings, MAX_DEVICE_COUNT, &szDeviceFound); // Little hack to allow using nfc-dep-initiator & nfc-dep-target from // the same machine: if there is more than one readers connected // nfc-dep-target will connect to the second reader // (we hope they're always detected in the same order) if (szDeviceFound == 1) { - pnd = nfc_connect (&(pnddDevices[0])); + pnd = nfc_connect (connstrings[0]); } else if (szDeviceFound > 1) { - pnd = nfc_connect (&(pnddDevices[1])); + pnd = nfc_connect (connstrings[1]); } else { printf("No device found."); return EXIT_FAILURE; diff --git a/examples/nfc-poll.c b/examples/nfc-poll.c index 2843654..a5c27f1 100644 --- a/examples/nfc-poll.c +++ b/examples/nfc-poll.c @@ -65,15 +65,10 @@ void stop_polling (int sig) int main (int argc, const char *argv[]) { - size_t szFound; - size_t i; bool verbose = false; - nfc_device_desc_t *pnddDevices; signal (SIGINT, stop_polling); - pnddDevices = parse_args (argc, argv, &szFound, &verbose); - // Display libnfc version const char *acLibnfcVersion = nfc_version (); @@ -83,59 +78,43 @@ main (int argc, const char *argv[]) printf ("%s uses libnfc %s\n", argv[0], acLibnfcVersion); - if (szFound == 0) { - if (!(pnddDevices = malloc (MAX_DEVICE_COUNT * sizeof (*pnddDevices)))) { - fprintf (stderr, "malloc() failed\n"); - exit (EXIT_FAILURE); - } + const uint8_t uiPollNr = 20; + const uint8_t uiPeriod = 2; + const nfc_modulation_t nmModulations[5] = { + { .nmt = NMT_ISO14443A, .nbr = NBR_106 }, + { .nmt = NMT_ISO14443B, .nbr = NBR_106 }, + { .nmt = NMT_FELICA, .nbr = NBR_212 }, + { .nmt = NMT_FELICA, .nbr = NBR_424 }, + { .nmt = NMT_JEWEL, .nbr = NBR_106 }, + }; + const size_t szModulations = 5; + + nfc_target_t nt; + bool res; + + pnd = nfc_connect (NULL); + + if (pnd == NULL) { + ERR ("%s", "Unable to connect to NFC device."); + exit (EXIT_FAILURE); } - nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szFound); + nfc_initiator_init (pnd); - if (szFound == 0) { - printf ("No NFC device found.\n"); - } - - for (i = 0; i < szFound; i++) { - const uint8_t uiPollNr = 20; - const uint8_t uiPeriod = 2; - const nfc_modulation_t nmModulations[5] = { - { .nmt = NMT_ISO14443A, .nbr = NBR_106 }, - { .nmt = NMT_ISO14443B, .nbr = NBR_106 }, - { .nmt = NMT_FELICA, .nbr = NBR_212 }, - { .nmt = NMT_FELICA, .nbr = NBR_424 }, - { .nmt = NMT_JEWEL, .nbr = NBR_106 }, - }; - const size_t szModulations = 5; - - nfc_target_t nt; - bool res; - - pnd = nfc_connect (&(pnddDevices[i])); - - if (pnd == NULL) { - ERR ("%s", "Unable to connect to NFC device."); + printf ("Connected to NFC reader: %s\n", pnd->acName); + printf ("NFC device will poll during %ld ms (%u pollings of %lu ms for %zd modulations)\n", (unsigned long) uiPollNr * szModulations * uiPeriod * 150, uiPollNr, (unsigned long) uiPeriod * 150, szModulations); + res = nfc_initiator_poll_target (pnd, nmModulations, szModulations, uiPollNr, uiPeriod, &nt); + if (res) { + print_nfc_target ( nt, verbose ); + } else { + if (pnd->iLastError) { + nfc_perror (pnd, "nfc_initiator_poll_targets"); + nfc_disconnect (pnd); exit (EXIT_FAILURE); - } - nfc_initiator_init (pnd); - - printf ("Connected to NFC reader: %s\n", pnd->acName); - printf ("NFC device will poll during %ld ms (%u pollings of %lu ms for %zd modulations)\n", (unsigned long) uiPollNr * szModulations * uiPeriod * 150, uiPollNr, (unsigned long) uiPeriod * 150, szModulations); - res = nfc_initiator_poll_target (pnd, nmModulations, szModulations, uiPollNr, uiPeriod, &nt); - if (res) { - print_nfc_target ( nt, verbose ); } else { - if (pnd->iLastError) { - nfc_perror (pnd, "nfc_initiator_poll_targets"); - nfc_disconnect (pnd); - exit (EXIT_FAILURE); - } else { - printf ("No target found.\n"); - } + printf ("No target found.\n"); } - nfc_disconnect (pnd); } - - free (pnddDevices); + nfc_disconnect (pnd); exit (EXIT_SUCCESS); } diff --git a/examples/nfc-relay.c b/examples/nfc-relay.c index 720b094..7ec4ec5 100644 --- a/examples/nfc-relay.c +++ b/examples/nfc-relay.c @@ -83,7 +83,6 @@ main (int argc, char *argv[]) int arg; bool quiet_output = false; size_t szFound; - nfc_device_desc_t *pnddDevices; const char *acLibnfcVersion = nfc_version (); // Get commandline options @@ -109,20 +108,16 @@ main (int argc, char *argv[]) signal (SIGINT, (void (*)()) intr_hdlr); #endif - // Allocate memory to put the result of available devices listing - if (!(pnddDevices = malloc (MAX_DEVICE_COUNT * sizeof (*pnddDevices)))) { - fprintf (stderr, "malloc() failed\n"); - return EXIT_FAILURE; - } + nfc_connstring connstrings[MAX_DEVICE_COUNT]; // List available devices - nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szFound); + nfc_list_devices (connstrings, MAX_DEVICE_COUNT, &szFound); if (szFound < 2) { ERR ("%zd device found but two connected devices are needed to relay NFC.", szFound); return EXIT_FAILURE; } // Try to open the NFC emulator device - pndTag = nfc_connect (&(pnddDevices[0])); + pndTag = nfc_connect (connstrings[0]); if (pndTag == NULL) { printf ("Error connecting NFC emulator device\n"); return EXIT_FAILURE; @@ -165,7 +160,7 @@ main (int argc, char *argv[]) printf ("%s", "Done, emulated tag is initialized"); // Try to open the NFC reader - pndReader = nfc_connect (&(pnddDevices[1])); + pndReader = nfc_connect (connstrings[1]); printf ("Connected to the NFC reader device: %s", pndReader->acName); printf ("%s", "Configuring NFC reader settings..."); diff --git a/examples/pn53x-diagnose.c b/examples/pn53x-diagnose.c index c11a236..bc28be0 100644 --- a/examples/pn53x-diagnose.c +++ b/examples/pn53x-diagnose.c @@ -55,7 +55,6 @@ main (int argc, const char *argv[]) size_t szFound; size_t i; nfc_device_t *pnd; - nfc_device_desc_t *pnddDevices; const char *acLibnfcVersion; bool result; @@ -72,19 +71,15 @@ main (int argc, const char *argv[]) acLibnfcVersion = nfc_version (); printf ("%s uses libnfc %s\n", argv[0], acLibnfcVersion); - if (!(pnddDevices = malloc (MAX_DEVICE_COUNT * sizeof (*pnddDevices)))) { - fprintf (stderr, "malloc() failed\n"); - return EXIT_FAILURE; - } - - nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szFound); + nfc_connstring connstrings[MAX_DEVICE_COUNT]; + nfc_list_devices (connstrings, MAX_DEVICE_COUNT, &szFound); if (szFound == 0) { printf ("No NFC device found.\n"); } for (i = 0; i < szFound; i++) { - pnd = nfc_connect (&(pnddDevices[i])); + pnd = nfc_connect (connstrings[i]); if (pnd == NULL) { ERR ("%s", "Unable to connect to NFC device."); diff --git a/include/nfc/nfc-types.h b/include/nfc/nfc-types.h index 04b2120..15b9367 100644 --- a/include/nfc/nfc-types.h +++ b/include/nfc/nfc-types.h @@ -71,24 +71,7 @@ typedef struct { int iLastError; } nfc_device_t; -/** - * @struct nfc_device_desc_t - * @brief NFC device description - * - * This struct is used to try to connect to a specified nfc device when nfc_connect(...) - */ -typedef struct { - /** Device name (e.g. "ACS ACR 38U-CCID 00 00") */ - char acDevice[DEVICE_NAME_LENGTH]; - /** Driver name (e.g. "PN532_UART")*/ - char *pcDriver; - /** Port (e.g. "/dev/ttyUSB0") */ - char acPort[DEVICE_PORT_LENGTH]; - /** 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 uiBusIndex; -} nfc_device_desc_t; +typedef char nfc_connstring[1024]; // Compiler directive, set struct alignment to 1 byte_t for compatibility # pragma pack(1) diff --git a/include/nfc/nfc.h b/include/nfc/nfc.h index 051f691..011e475 100644 --- a/include/nfc/nfc.h +++ b/include/nfc/nfc.h @@ -63,10 +63,11 @@ extern "C" { # endif // __cplusplus /* NFC Device/Hardware manipulation */ - NFC_EXPORT nfc_device_t *nfc_connect (nfc_device_desc_t * pndd); + NFC_EXPORT bool nfc_get_default_device (nfc_connstring *connstring); + NFC_EXPORT nfc_device_t *nfc_connect (const nfc_connstring connstring); NFC_EXPORT void nfc_disconnect (nfc_device_t * pnd); NFC_EXPORT bool nfc_abort_command (nfc_device_t * pnd); - NFC_EXPORT void nfc_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound); + NFC_EXPORT void nfc_list_devices (nfc_connstring connstrings[], size_t connstrings_len, size_t * pszDeviceFound); NFC_EXPORT bool nfc_configure (nfc_device_t * pnd, const nfc_device_option_t ndo, const bool bEnable); NFC_EXPORT bool nfc_idle (nfc_device_t * pnd); diff --git a/libnfc/drivers/acr122.c b/libnfc/drivers/acr122.c index 0732275..419f7ad 100644 --- a/libnfc/drivers/acr122.c +++ b/libnfc/drivers/acr122.c @@ -40,7 +40,7 @@ // Bus #include -# define ACR122_DRIVER_NAME "ACR122" +#define ACR122_DRIVER_NAME "acr122" #if defined (_WIN32) # define IOCTL_CCID_ESCAPE_SCARD_CTL_CODE SCARD_CTL_CODE(3500) @@ -133,7 +133,7 @@ acr122_free_scardcontext (void) * @return true if succeeded, false otherwise. */ bool -acr122_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound) +acr122_probe (nfc_connstring connstrings[], size_t connstrings_len, size_t * pszDeviceFound) { size_t szPos = 0; char acDeviceNames[256 + 64 * PCSC_MAX_DEVICES]; @@ -158,9 +158,7 @@ acr122_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDev if (SCardListReaders (*pscc, NULL, acDeviceNames, &dwDeviceNamesLen) != SCARD_S_SUCCESS) return false; - // DBG("%s", "PCSC reports following device(s):"); - - while ((acDeviceNames[szPos] != '\0') && ((*pszDeviceFound) < szDevices)) { + while ((acDeviceNames[szPos] != '\0') && ((*pszDeviceFound) < connstrings_len)) { uiBusIndex++; // DBG("- %s (pos=%ld)", acDeviceNames + szPos, (unsigned long) szPos); @@ -173,9 +171,7 @@ acr122_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDev if (bSupported) { // Supported ACR122 device found - strncpy (pnddDevices[*pszDeviceFound].acDevice, acDeviceNames + szPos, DEVICE_NAME_LENGTH - 1); - pnddDevices[*pszDeviceFound].pcDriver = ACR122_DRIVER_NAME; - pnddDevices[*pszDeviceFound].uiBusIndex = uiBusIndex; + snprintf (connstrings[*pszDeviceFound], sizeof(nfc_connstring), "%s:%s:%"PRIu32, ACR122_DRIVER_NAME, acDeviceNames + szPos, uiBusIndex); (*pszDeviceFound)++; } else { log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "PCSC device [%s] is not NFC capable or not supported by libnfc.", acDeviceNames + szPos); @@ -189,9 +185,71 @@ acr122_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDev return true; } -nfc_device_t * -acr122_connect (const nfc_device_desc_t * pndd) +struct acr122_descriptor { + char pcsc_device_name[512]; + int bus_index; +}; + +int +acr122_connstring_decode (const nfc_connstring connstring, struct acr122_descriptor *desc) { + char *cs = malloc (strlen (connstring) + 1); + if (!cs) { + perror ("malloc"); + return -1; + } + strcpy (cs, connstring); + const char *driver_name = strtok (cs, ":"); + if (!driver_name) { + // Parse error + free (cs); + return -1; + } + + if (0 != strcmp (driver_name, ACR122_DRIVER_NAME)) { + // Driver name does not match. + free (cs); + return 0; + } + + const char *device_name = strtok (NULL, ":"); + if (!device_name) { + // Only driver name was specified (or parsing error) + free (cs); + return 1; + } + strncpy (desc->pcsc_device_name, device_name, sizeof(desc->pcsc_device_name)-1); + desc->pcsc_device_name[sizeof(desc->pcsc_device_name)-1] = '\0'; + + const char *bus_index_s = strtok (NULL, ":"); + if (!bus_index_s) { + // bus index not specified (or parsing error) + free (cs); + return 2; + } + unsigned long bus_index; + if (sscanf (bus_index_s, "%lu", &bus_index) != 1) { + // bus_index_s is not a number + free (cs); + return 2; + } + desc->bus_index = bus_index; + + free (cs); + return 3; +} + +nfc_device_t * +acr122_connect (const nfc_connstring connstring) +{ + struct acr122_descriptor ndd; + int connstring_decode_level = acr122_connstring_decode (connstring, &ndd); + + if (connstring_decode_level < 2) { + return NULL; + } + // FIXME: acr122_connect() does not take care about bus index + char *pcFirmware; nfc_device_t *pnd = nfc_device_new (); pnd->driver_data = malloc (sizeof (struct acr122_data)); @@ -200,15 +258,15 @@ acr122_connect (const nfc_device_desc_t * pndd) pn53x_data_new (pnd, &acr122_io); SCARDCONTEXT *pscc; - - log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Attempt to connect to %s", pndd->acDevice); + + log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Attempt to connect to %s", ndd.pcsc_device_name); // Test if context succeeded if (!(pscc = acr122_get_scardcontext ())) goto error; // Test if we were able to connect to the "emulator" card - if (SCardConnect (*pscc, pndd->acDevice, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &(DRIVER_DATA (pnd)->hCard), (void *) &(DRIVER_DATA (pnd)->ioCard.dwProtocol)) != SCARD_S_SUCCESS) { + if (SCardConnect (*pscc, ndd.pcsc_device_name, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &(DRIVER_DATA (pnd)->hCard), (void *) &(DRIVER_DATA (pnd)->ioCard.dwProtocol)) != SCARD_S_SUCCESS) { // Connect to ACR122 firmware version >2.0 - if (SCardConnect (*pscc, pndd->acDevice, SCARD_SHARE_DIRECT, 0, &(DRIVER_DATA (pnd)->hCard), (void *) &(DRIVER_DATA (pnd)->ioCard.dwProtocol)) != SCARD_S_SUCCESS) { + if (SCardConnect (*pscc, ndd.pcsc_device_name, SCARD_SHARE_DIRECT, 0, &(DRIVER_DATA (pnd)->hCard), (void *) &(DRIVER_DATA (pnd)->ioCard.dwProtocol)) != SCARD_S_SUCCESS) { // We can not connect to this device. log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "%s", "PCSC connect failed"); goto error; @@ -222,7 +280,7 @@ acr122_connect (const nfc_device_desc_t * pndd) if (strstr (pcFirmware, FIRMWARE_TEXT) != NULL) { // Done, we found the reader we are looking for - snprintf (pnd->acName, sizeof (pnd->acName), "%s / %s", pndd->acDevice, pcFirmware); + snprintf (pnd->acName, sizeof (pnd->acName), "%s / %s", ndd.pcsc_device_name, pcFirmware); // 50: empirical tuning on Touchatag // 46: empirical tuning on ACR122U @@ -407,11 +465,11 @@ const struct pn53x_io acr122_io = { }; const struct nfc_driver_t acr122_driver = { - .name = ACR122_DRIVER_NAME, - .probe = acr122_probe, - .connect = acr122_connect, - .disconnect = acr122_disconnect, - .strerror = pn53x_strerror, + .name = ACR122_DRIVER_NAME, + .probe = acr122_probe, + .connect = acr122_connect, + .disconnect = acr122_disconnect, + .strerror = pn53x_strerror, .initiator_init = pn53x_initiator_init, .initiator_select_passive_target = pn53x_initiator_select_passive_target, @@ -431,7 +489,7 @@ const struct nfc_driver_t acr122_driver = { .configure = pn53x_configure, - .abort_command = NULL, - .idle = NULL, + .abort_command = NULL, // FIXME: abort is not supported in this driver + .idle = NULL, // FIXME: idle is not supported in this driver }; diff --git a/libnfc/drivers/acr122.h b/libnfc/drivers/acr122.h index db05e2f..0a2c087 100644 --- a/libnfc/drivers/acr122.h +++ b/libnfc/drivers/acr122.h @@ -26,10 +26,10 @@ # include -bool acr122_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound); +bool acr122_probe (nfc_connstring connstrings[], size_t connstrings_len, size_t * pszDeviceFound); // Functions used by developer to handle connection to this device -nfc_device_t *acr122_connect (const nfc_device_desc_t * pndd); +nfc_device_t *acr122_connect (const nfc_connstring connstring); bool acr122_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData, struct timeval *timeout); int acr122_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szData, struct timeval *timeout); void acr122_disconnect (nfc_device_t * pnd); diff --git a/libnfc/drivers/arygon.c b/libnfc/drivers/arygon.c index 537ff29..2ff78c6 100644 --- a/libnfc/drivers/arygon.c +++ b/libnfc/drivers/arygon.c @@ -26,6 +26,9 @@ * This driver can handle ARYGON readers that use UART as bus. * UART connection can be direct (host<->arygon_uc) or could be provided by internal USB to serial interface (e.g. host<->ftdi_chip<->arygon_uc) */ + +/* vim: set ts=2 sw=2 et: */ + #ifdef HAVE_CONFIG_H # include "config.h" #endif // HAVE_CONFIG_H @@ -33,6 +36,7 @@ #include "arygon.h" #include +#include #include #include #include @@ -64,7 +68,7 @@ #define DEV_ARYGON_PROTOCOL_TAMA_WAB '3' #define ARYGON_DEFAULT_SPEED 9600 -#define ARYGON_DRIVER_NAME "ARYGON" +#define ARYGON_DRIVER_NAME "arygon" #define LOG_CATEGORY "libnfc.driver.arygon" #define DRIVER_DATA(pnd) ((struct arygon_data*)(pnd->driver_data)) @@ -88,16 +92,16 @@ bool arygon_reset_tama (nfc_device_t * pnd); void arygon_firmware (nfc_device_t * pnd, char * str); bool -arygon_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound) +arygon_probe (nfc_connstring connstrings[], size_t connstrings_len, size_t * pszDeviceFound) { /** @note: Due to UART bus we can't know if its really an ARYGON without * sending some commands. But using this way to probe devices, we can * have serious problem with other device on this bus */ #ifndef SERIAL_AUTOPROBE_ENABLED - (void) pnddDevices; - (void) szDevices; + (void) connstrings; + (void) connstrings_len; *pszDeviceFound = 0; - log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "%s", "Serial auto-probing have been disabled at compile time. Skipping autoprobe."); + log_put (LOG_CATEGORY, NFC_PRIORITY_INFO, "Serial auto-probing have been disabled at compile time. Skipping autoprobe."); return false; #else /* SERIAL_AUTOPROBE_ENABLED */ *pszDeviceFound = 0; @@ -135,24 +139,18 @@ arygon_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDev pn53x_data_free (pnd); nfc_device_free (pnd); uart_close (sp); - if(!res) + if(!res) { continue; + } // ARYGON reader is found - snprintf (pnddDevices[*pszDeviceFound].acDevice, DEVICE_NAME_LENGTH - 1, "%s (%s)", "Arygon", acPort); - pnddDevices[*pszDeviceFound].pcDriver = ARYGON_DRIVER_NAME; - strncpy (pnddDevices[*pszDeviceFound].acPort, acPort, DEVICE_PORT_LENGTH - 1); pnddDevices[*pszDeviceFound].acPort[DEVICE_PORT_LENGTH - 1] = '\0'; - pnddDevices[*pszDeviceFound].uiSpeed = ARYGON_DEFAULT_SPEED; + snprintf (connstrings[*pszDeviceFound], sizeof(nfc_connstring), "%s:%s:%"PRIu32, ARYGON_DRIVER_NAME, acPort, ARYGON_DEFAULT_SPEED); (*pszDeviceFound)++; // Test if we reach the maximum "wanted" devices - if ((*pszDeviceFound) >= szDevices) + if ((*pszDeviceFound) >= connstrings_len) break; } - if (sp == INVALID_SERIAL_PORT) - log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Invalid serial port: %s", acPort); - if (sp == CLAIMED_SERIAL_PORT) - log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Serial port already claimed: %s", acPort); } iDevice = 0; while ((acPort = acPorts[iDevice++])) { @@ -163,33 +161,96 @@ arygon_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDev return true; } -nfc_device_t * -arygon_connect (const nfc_device_desc_t * pndd) +struct arygon_descriptor { + char port[128]; + uint32_t speed; +}; + +int +arygon_connstring_decode (const nfc_connstring connstring, struct arygon_descriptor *desc) { + char *cs = malloc (strlen (connstring) + 1); + if (!cs) { + perror ("malloc"); + return -1; + } + strcpy (cs, connstring); + const char *driver_name = strtok (cs, ":"); + if (!driver_name) { + // Parse error + free (cs); + return -1; + } + + if (0 != strcmp (driver_name, ARYGON_DRIVER_NAME)) { + // Driver name does not match. + free (cs); + return 0; + } + + const char *port = strtok (NULL, ":"); + if (!port) { + // Only driver name was specified (or parsing error) + free (cs); + return 1; + } + strncpy (desc->port, port, sizeof(desc->port)-1); + desc->port[sizeof(desc->port)-1] = '\0'; + + const char* speed_s = strtok (NULL, ":"); + if (!speed_s) { + // speed not specified (or parsing error) + free (cs); + return 2; + } + unsigned long speed; + if (sscanf (speed_s, "%lu", &speed) != 1) { + // speed_s is not a number + free (cs); + return 2; + } + desc->speed = speed; + + free (cs); + return 3; +} + +nfc_device_t * +arygon_connect (const nfc_connstring connstring) +{ + struct arygon_descriptor ndd; + int connstring_decode_level = arygon_connstring_decode (connstring, &ndd); + + if (connstring_decode_level < 2) { + return NULL; + } + if (connstring_decode_level < 3) { + ndd.speed = ARYGON_DEFAULT_SPEED; + } serial_port sp; nfc_device_t *pnd = NULL; - log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Attempt to connect to: %s at %d bauds.", pndd->acPort, pndd->uiSpeed); - sp = uart_open (pndd->acPort); + log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Attempt to connect to: %s at %d bauds.", ndd.port, ndd.speed); + sp = uart_open (ndd.port); if (sp == INVALID_SERIAL_PORT) - log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Invalid serial port: %s", pndd->acPort); + log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Invalid serial port: %s", ndd.port); if (sp == CLAIMED_SERIAL_PORT) - log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Serial port already claimed: %s", pndd->acPort); + log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Serial port already claimed: %s", ndd.port); if ((sp == CLAIMED_SERIAL_PORT) || (sp == INVALID_SERIAL_PORT)) return NULL; // We need to flush input to be sure first reply does not comes from older byte transceive uart_flush_input (sp); - uart_set_speed (sp, pndd->uiSpeed); + uart_set_speed (sp, ndd.speed); // We have a connection pnd = nfc_device_new (); - strncpy (pnd->acName, pndd->acDevice, sizeof (pnd->acName)); + snprintf (pnd->acName, sizeof (pnd->acName), "%s:%s", ARYGON_DRIVER_NAME, ndd.port); pnd->driver_data = malloc(sizeof(struct arygon_data)); DRIVER_DATA (pnd)->port = sp; - + // Alloc and init chip's data pn53x_data_new (pnd, &arygon_tama_io); @@ -209,7 +270,7 @@ arygon_connect (const nfc_device_desc_t * pndd) // Check communication using "Reset TAMA" command if (!arygon_reset_tama(pnd)) { - nfc_device_free (pnd); + arygon_disconnect (pnd); return NULL; } @@ -314,7 +375,7 @@ arygon_tama_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLe #ifndef WIN32 abort_p = &(DRIVER_DATA (pnd)->iAbortFds[1]); #else - abort_p = &(DRIVER_DATA (pnd)->abort_flag); + abort_p = (void*)&(DRIVER_DATA (pnd)->abort_flag); #endif pnd->iLastError = uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, 5, abort_p, timeout); @@ -500,11 +561,11 @@ const struct pn53x_io arygon_tama_io = { }; const struct nfc_driver_t arygon_driver = { - .name = ARYGON_DRIVER_NAME, - .probe = arygon_probe, - .connect = arygon_connect, - .disconnect = arygon_disconnect, - .strerror = pn53x_strerror, + .name = ARYGON_DRIVER_NAME, + .probe = arygon_probe, + .connect = arygon_connect, + .disconnect = arygon_disconnect, + .strerror = pn53x_strerror, .initiator_init = pn53x_initiator_init, .initiator_select_passive_target = pn53x_initiator_select_passive_target, @@ -525,7 +586,6 @@ const struct nfc_driver_t arygon_driver = { .configure = pn53x_configure, .abort_command = arygon_abort_command, - // FIXME Implement me - .idle = NULL, + .idle = NULL, // FIXME arygon driver does not support idle() }; diff --git a/libnfc/drivers/arygon.h b/libnfc/drivers/arygon.h index 11318b8..6ef6ff3 100644 --- a/libnfc/drivers/arygon.h +++ b/libnfc/drivers/arygon.h @@ -30,9 +30,9 @@ # include -bool arygon_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound); +bool arygon_probe (nfc_connstring connstrings[], size_t connstrings_len, size_t * pszDeviceFound); -nfc_device_t *arygon_connect (const nfc_device_desc_t * pndd); +nfc_device_t *arygon_connect (const nfc_connstring connstring); void arygon_disconnect (nfc_device_t * pnd); bool arygon_tama_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData, struct timeval *timeout); diff --git a/libnfc/drivers/pn532_uart.c b/libnfc/drivers/pn532_uart.c index 83c2a80..688323d 100644 --- a/libnfc/drivers/pn532_uart.c +++ b/libnfc/drivers/pn532_uart.c @@ -32,6 +32,7 @@ #include "pn532_uart.h" #include +#include #include #include @@ -44,7 +45,7 @@ #include "uart.h" #define PN532_UART_DEFAULT_SPEED 115200 -#define PN532_UART_DRIVER_NAME "PN532_UART" +#define PN532_UART_DRIVER_NAME "pn532_uart" #define LOG_CATEGORY "libnfc.driver.pn532_uart" int pn532_uart_ack (nfc_device_t * pnd); @@ -64,14 +65,14 @@ struct pn532_uart_data { #define DRIVER_DATA(pnd) ((struct pn532_uart_data*)(pnd->driver_data)) bool -pn532_uart_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound) +pn532_uart_probe (nfc_connstring connstrings[], size_t connstrings_len, size_t * pszDeviceFound) { /** @note: Due to UART bus we can't know if its really a pn532 without * sending some PN53x commands. But using this way to probe devices, we can * have serious problem with other device on this bus */ #ifndef SERIAL_AUTOPROBE_ENABLED - (void) pnddDevices; - (void) szDevices; + (void) connstrings; + (void) connstrings_len; *pszDeviceFound = 0; log_put (LOG_CATEGORY, NFC_PRIORITY_INFO, "Serial auto-probing have been disabled at compile time. Skipping autoprobe."); return false; @@ -124,18 +125,14 @@ pn532_uart_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * ps continue; } - snprintf (pnddDevices[*pszDeviceFound].acDevice, DEVICE_NAME_LENGTH - 1, "%s (%s)", "PN532", acPort); - pnddDevices[*pszDeviceFound].pcDriver = PN532_UART_DRIVER_NAME; - strncpy (pnddDevices[*pszDeviceFound].acPort, acPort, DEVICE_PORT_LENGTH - 1); pnddDevices[*pszDeviceFound].acPort[DEVICE_PORT_LENGTH - 1] = '\0'; - pnddDevices[*pszDeviceFound].uiSpeed = PN532_UART_DEFAULT_SPEED; + snprintf (connstrings[*pszDeviceFound], sizeof(nfc_connstring), "%s:%s:%"PRIu32, PN532_UART_DRIVER_NAME, acPort, PN532_UART_DEFAULT_SPEED); (*pszDeviceFound)++; // Test if we reach the maximum "wanted" devices - if ((*pszDeviceFound) >= szDevices) + if ((*pszDeviceFound) >= connstrings_len) break; } } - iDevice = 0; while ((acPort = acPorts[iDevice++])) { free ((void*)acPort); @@ -145,33 +142,96 @@ pn532_uart_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * ps return true; } -nfc_device_t * -pn532_uart_connect (const nfc_device_desc_t * pndd) +struct pn532_uart_descriptor { + char port[128]; + uint32_t speed; +}; + +int +pn532_connstring_decode (const nfc_connstring connstring, struct pn532_uart_descriptor *desc) { + char *cs = malloc (strlen (connstring) + 1); + if (!cs) { + perror ("malloc"); + return -1; + } + strcpy (cs, connstring); + const char *driver_name = strtok (cs, ":"); + if (!driver_name) { + // Parse error + free (cs); + return -1; + } + + if (0 != strcmp (driver_name, PN532_UART_DRIVER_NAME)) { + // Driver name does not match. + free (cs); + return 0; + } + + const char *port = strtok (NULL, ":"); + if (!port) { + // Only driver name was specified (or parsing error) + free (cs); + return 1; + } + strncpy (desc->port, port, sizeof(desc->port)-1); + desc->port[sizeof(desc->port)-1] = '\0'; + + const char* speed_s = strtok (NULL, ":"); + if (!speed_s) { + // speed not specified (or parsing error) + free (cs); + return 2; + } + unsigned long speed; + if (sscanf (speed_s, "%lu", &speed) != 1) { + // speed_s is not a number + free (cs); + return 2; + } + desc->speed = speed; + + free (cs); + return 3; +} + +nfc_device_t * +pn532_uart_connect (const nfc_connstring connstring) +{ + struct pn532_uart_descriptor ndd; + int connstring_decode_level = pn532_connstring_decode (connstring, &ndd); + + if (connstring_decode_level < 2) { + return NULL; + } + if (connstring_decode_level < 3) { + ndd.speed = PN532_UART_DEFAULT_SPEED; + } serial_port sp; nfc_device_t *pnd = NULL; - log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Attempt to connect to: %s at %d bauds.", pndd->acPort, pndd->uiSpeed); - sp = uart_open (pndd->acPort); + log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Attempt to connect to: %s at %d bauds.", ndd.port, ndd.speed); + sp = uart_open (ndd.port); if (sp == INVALID_SERIAL_PORT) - log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Invalid serial port: %s", pndd->acPort); + log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Invalid serial port: %s", ndd.port); if (sp == CLAIMED_SERIAL_PORT) - log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Serial port already claimed: %s", pndd->acPort); + log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Serial port already claimed: %s", ndd.port); if ((sp == CLAIMED_SERIAL_PORT) || (sp == INVALID_SERIAL_PORT)) return NULL; // We need to flush input to be sure first reply does not comes from older byte transceive uart_flush_input (sp); - uart_set_speed (sp, pndd->uiSpeed); + uart_set_speed (sp, ndd.speed); // We have a connection pnd = nfc_device_new (); - strncpy (pnd->acName, pndd->acDevice, DEVICE_NAME_LENGTH - 1); - pnd->acName[DEVICE_NAME_LENGTH - 1] = '\0'; + snprintf (pnd->acName, sizeof (pnd->acName), "%s:%s", PN532_UART_DRIVER_NAME, ndd.port); pnd->driver_data = malloc(sizeof(struct pn532_uart_data)); - DRIVER_DATA(pnd)->port = sp; + DRIVER_DATA (pnd)->port = sp; + // Alloc and init chip's data pn53x_data_new (pnd, &pn532_uart_io); // SAMConfiguration command if needed to wakeup the chip and pn53x_SAMConfiguration check if the chip is a PN532 @@ -193,7 +253,7 @@ pn532_uart_connect (const nfc_device_desc_t * pndd) // Check communication using "Diagnose" command, with "Communication test" (0x00) if (!pn53x_check_communication (pnd)) { nfc_perror (pnd, "pn53x_check_communication"); - pn532_uart_disconnect(pnd); + pn532_uart_disconnect (pnd); return NULL; } @@ -304,7 +364,7 @@ pn532_uart_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen abort_p = (void*)&(DRIVER_DATA (pnd)->abort_flag); #endif - pnd->iLastError = uart_receive (DRIVER_DATA(pnd)->port, abtRxBuf, 5, abort_p, timeout); + pnd->iLastError = uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, 5, abort_p, timeout); if (abort_p && (EOPABORT == pnd->iLastError)) { pn532_uart_ack (pnd); @@ -325,7 +385,7 @@ pn532_uart_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen if ((0x01 == abtRxBuf[3]) && (0xff == abtRxBuf[4])) { // Error frame - uart_receive (DRIVER_DATA(pnd)->port, abtRxBuf, 3, 0, timeout); + uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, 3, 0, timeout); log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Application level error detected"); pnd->iLastError = EFRAISERRFRAME; return -1; @@ -362,7 +422,7 @@ pn532_uart_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen } // TFI + PD0 (CC+1) - pnd->iLastError = uart_receive (DRIVER_DATA(pnd)->port, abtRxBuf, 2, 0, timeout); + pnd->iLastError = uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, 2, 0, timeout); if (pnd->iLastError != 0) { log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)"); return -1; @@ -381,14 +441,14 @@ pn532_uart_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen } if (len) { - pnd->iLastError = uart_receive (DRIVER_DATA(pnd)->port, pbtData, len, 0, timeout); + pnd->iLastError = uart_receive (DRIVER_DATA (pnd)->port, pbtData, len, 0, timeout); if (pnd->iLastError != 0) { log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)"); return -1; } } - pnd->iLastError = uart_receive (DRIVER_DATA(pnd)->port, abtRxBuf, 2, 0, timeout); + pnd->iLastError = uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, 2, 0, timeout); if (pnd->iLastError != 0) { log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)"); return -1; @@ -446,11 +506,11 @@ const struct pn53x_io pn532_uart_io = { }; const struct nfc_driver_t pn532_uart_driver = { - .name = PN532_UART_DRIVER_NAME, - .probe = pn532_uart_probe, - .connect = pn532_uart_connect, - .disconnect = pn532_uart_disconnect, - .strerror = pn53x_strerror, + .name = PN532_UART_DRIVER_NAME, + .probe = pn532_uart_probe, + .connect = pn532_uart_connect, + .disconnect = pn532_uart_disconnect, + .strerror = pn53x_strerror, .initiator_init = pn53x_initiator_init, .initiator_select_passive_target = pn53x_initiator_select_passive_target, diff --git a/libnfc/drivers/pn532_uart.h b/libnfc/drivers/pn532_uart.h index 5ecb21c..5f8f344 100644 --- a/libnfc/drivers/pn532_uart.h +++ b/libnfc/drivers/pn532_uart.h @@ -29,9 +29,9 @@ # include -bool pn532_uart_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound); +bool pn532_uart_probe (nfc_connstring connstrings[], size_t connstrings_len, size_t * pszDeviceFound); -nfc_device_t *pn532_uart_connect (const nfc_device_desc_t * pndd); +nfc_device_t *pn532_uart_connect (const nfc_connstring connstring); void pn532_uart_disconnect (nfc_device_t * pnd); bool pn532_uart_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData, struct timeval *timeout); int pn532_uart_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szData, struct timeval *timeout); diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index f4f3e81..aae9203 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -32,10 +32,11 @@ Thanks to d18c7db and Okko for example code */ -#include -#include #include #include +#include +#include +#include #ifndef _WIN32 // Under POSIX system, we use libusb (>= 0.1.12) @@ -58,7 +59,7 @@ Thanks to d18c7db and Okko for example code #include "chips/pn53x-internal.h" #include "drivers/pn53x_usb.h" -#define PN53X_USB_DRIVER_NAME "PN53x USB" +#define PN53X_USB_DRIVER_NAME "pn53x_usb" #define LOG_CATEGORY "libnfc.driver.pn53x_usb" #define USB_INFINITE_TIMEOUT 0 @@ -222,7 +223,7 @@ pn53x_usb_get_end_points (struct usb_device *dev, struct pn53x_usb_data *data) } bool -pn53x_usb_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound) +pn53x_usb_probe (nfc_connstring connstrings[], size_t connstrings_len, size_t * pszDeviceFound) { usb_init (); @@ -275,13 +276,13 @@ pn53x_usb_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * psz continue; } - pn53x_usb_get_usb_device_name (dev, udev, pnddDevices[*pszDeviceFound].acDevice, sizeof (pnddDevices[*pszDeviceFound].acDevice)); + // pn53x_usb_get_usb_device_name (dev, udev, pnddDevices[*pszDeviceFound].acDevice, sizeof (pnddDevices[*pszDeviceFound].acDevice)); + log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "device found: Bus %s Device %s", bus->dirname, dev->filename); usb_close (udev); - pnddDevices[*pszDeviceFound].pcDriver = PN53X_USB_DRIVER_NAME; - pnddDevices[*pszDeviceFound].uiBusIndex = uiBusIndex; + snprintf (connstrings[*pszDeviceFound], sizeof(nfc_connstring), "%s:%s:%s", PN53X_USB_DRIVER_NAME, bus->dirname, dev->filename); (*pszDeviceFound)++; // Test if we reach the maximum "wanted" devices - if ((*pszDeviceFound) == szDevices) { + if ((*pszDeviceFound) == connstrings_len) { return true; } } @@ -292,6 +293,64 @@ pn53x_usb_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * psz return true; } +struct pn53x_usb_descriptor { + uint16_t bus; + uint16_t dev; +}; + +int +pn53x_usb_connstring_decode (const nfc_connstring connstring, struct pn53x_usb_descriptor *desc) +{ + char *cs = malloc (strlen (connstring) + 1); + if (!cs) { + perror ("malloc"); + return -1; + } + strcpy (cs, connstring); + const char *driver_name = strtok (cs, ":"); + if (!driver_name) { + // Parse error + free (cs); + return -1; + } + + if (0 != strcmp (driver_name, PN53X_USB_DRIVER_NAME)) { + // Driver name does not match. + free (cs); + return 0; + } + + const char *bus_s = strtok (NULL, ":"); + if (!bus_s) { + // bus not specified (or parsing error) + free (cs); + return 1; + } + unsigned int bus; + if (sscanf (bus_s, "%u", &bus) != 1) { + // bus_s is not a number + free (cs); + return 1; + } + desc->bus = bus; + + const char *dev_s = strtok (NULL, ":"); + if (!dev_s) { + // dev not specified (or parsing error) + free (cs); + return 2; + } + unsigned int dev; + if (sscanf (dev_s, "%u", &dev) != 1) { + // dev_s is not a number + free (cs); + return 2; + } + desc->dev = dev; + free (cs); + return 3; +} + bool pn53x_usb_get_usb_device_name (struct usb_device *dev, usb_dev_handle *udev, char *buffer, size_t len) { @@ -320,8 +379,15 @@ pn53x_usb_get_usb_device_name (struct usb_device *dev, usb_dev_handle *udev, cha } nfc_device_t * -pn53x_usb_connect (const nfc_device_desc_t *pndd) +pn53x_usb_connect (const nfc_connstring connstring) { + struct pn53x_usb_descriptor desc; + int connstring_decode_level = pn53x_usb_connstring_decode (connstring, &desc); + log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "%d element(s) have been decoded from \"%s\"", connstring_decode_level, connstring); + if (connstring_decode_level < 1) { + return NULL; + } + nfc_device_t *pnd = NULL; struct pn53x_usb_data data = { .pudh = NULL, @@ -330,82 +396,90 @@ pn53x_usb_connect (const nfc_device_desc_t *pndd) }; struct usb_bus *bus; struct usb_device *dev; - uint32_t uiBusIndex; usb_init (); - uiBusIndex = pndd->uiBusIndex; - for (bus = usb_get_busses (); bus; bus = bus->next) { - for (dev = bus->devices; dev; dev = dev->next, uiBusIndex--) { - log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Checking device %04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct); - if (uiBusIndex == 0) { - // Open the USB device - data.pudh = usb_open (dev); - // Retrieve end points - pn53x_usb_get_end_points (dev, &data); - // Set configuration - int res = usb_set_configuration (data.pudh, 1); - if (res < 0) { - log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Unable to set USB configuration (%s)", _usb_strerror (res)); - if (EPERM == -res) { - log_put (LOG_CATEGORY, NFC_PRIORITY_WARN, "Please double check USB permissions for device %04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct); - } - usb_close (data.pudh); - // we failed to use the specified device - return NULL; - } - - res = usb_claim_interface (data.pudh, 0); - if (res < 0) { - log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Unable to claim USB interface (%s)", _usb_strerror (res)); - usb_close (data.pudh); - // we failed to use the specified device - return NULL; - } - data.model = pn53x_usb_get_device_model (dev->descriptor.idVendor, dev->descriptor.idProduct); - // Allocate memory for the device info and specification, fill it and return the info - pnd = nfc_device_new (); - pn53x_usb_get_usb_device_name (dev, data.pudh, pnd->acName, sizeof (pnd->acName)); - - pnd->driver_data = malloc(sizeof(struct pn53x_usb_data)); - *DRIVER_DATA (pnd) = data; - - // Alloc and init chip's data - pn53x_data_new (pnd, &pn53x_usb_io); - - switch (DRIVER_DATA (pnd)->model) { - // empirical tuning - case ASK_LOGO: - CHIP_DATA (pnd)->timer_correction = 50; - break; - case SCM_SCL3711: - case NXP_PN533: - CHIP_DATA (pnd)->timer_correction = 46; - break; - case NXP_PN531: - CHIP_DATA (pnd)->timer_correction = 50; - break; - case SONY_PN531: - CHIP_DATA (pnd)->timer_correction = 54; - break; - default: - break; - } - pnd->driver = &pn53x_usb_driver; - - // HACK1: Send first an ACK as Abort command, to reset chip before talking to it: - pn53x_usb_ack (pnd); - - // HACK2: Then send a GetFirmware command to resync USB toggle bit between host & device - // in case host used set_configuration and expects the device to have reset its toggle bit, which PN53x doesn't do - if (!pn53x_usb_init (pnd)) { - usb_close (data.pudh); - goto error; - } - DRIVER_DATA (pnd)->abort_flag = false; - return pnd; + if (connstring_decode_level > 1) { + // A specific bus have been specified + unsigned int bus_current; + sscanf (bus->dirname, "%u", &bus_current); + if (bus_current != desc.bus) + continue; + } + for (dev = bus->devices; dev; dev = dev->next) { + if (connstring_decode_level > 2) { + // A specific dev have been specified + unsigned int dev_current; + sscanf (dev->filename, "%u", &dev_current); + if (dev_current != desc.dev) + continue; } + // Open the USB device + data.pudh = usb_open (dev); + // Retrieve end points + pn53x_usb_get_end_points (dev, &data); + // Set configuration + int res = usb_set_configuration (data.pudh, 1); + if (res < 0) { + log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Unable to set USB configuration (%s)", _usb_strerror (res)); + if (EPERM == -res) { + log_put (LOG_CATEGORY, NFC_PRIORITY_WARN, "Please double check USB permissions for device %04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct); + } + usb_close (data.pudh); + // we failed to use the specified device + return NULL; + } + + res = usb_claim_interface (data.pudh, 0); + if (res < 0) { + log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Unable to claim USB interface (%s)", _usb_strerror (res)); + usb_close (data.pudh); + // we failed to use the specified device + return NULL; + } + data.model = pn53x_usb_get_device_model (dev->descriptor.idVendor, dev->descriptor.idProduct); + // Allocate memory for the device info and specification, fill it and return the info + pnd = nfc_device_new (); + pn53x_usb_get_usb_device_name (dev, data.pudh, pnd->acName, sizeof (pnd->acName)); + + pnd->driver_data = malloc(sizeof(struct pn53x_usb_data)); + *DRIVER_DATA (pnd) = data; + + // Alloc and init chip's data + pn53x_data_new (pnd, &pn53x_usb_io); + + switch (DRIVER_DATA (pnd)->model) { + // empirical tuning + case ASK_LOGO: + CHIP_DATA (pnd)->timer_correction = 50; + break; + case SCM_SCL3711: + case NXP_PN533: + CHIP_DATA (pnd)->timer_correction = 46; + break; + case NXP_PN531: + CHIP_DATA (pnd)->timer_correction = 50; + break; + case SONY_PN531: + CHIP_DATA (pnd)->timer_correction = 54; + break; + default: + break; + } + pnd->driver = &pn53x_usb_driver; + + // HACK1: Send first an ACK as Abort command, to reset chip before talking to it: + pn53x_usb_ack (pnd); + + // HACK2: Then send a GetFirmware command to resync USB toggle bit between host & device + // in case host used set_configuration and expects the device to have reset its toggle bit, which PN53x doesn't do + if (!pn53x_usb_init (pnd)) { + usb_close (data.pudh); + goto error; + } + DRIVER_DATA (pnd)->abort_flag = false; + return pnd; } } // We ran out of devices before the index required @@ -744,11 +818,11 @@ const struct pn53x_io pn53x_usb_io = { }; const struct nfc_driver_t pn53x_usb_driver = { - .name = PN53X_USB_DRIVER_NAME, - .probe = pn53x_usb_probe, - .connect = pn53x_usb_connect, - .disconnect = pn53x_usb_disconnect, - .strerror = pn53x_strerror, + .name = PN53X_USB_DRIVER_NAME, + .probe = pn53x_usb_probe, + .connect = pn53x_usb_connect, + .disconnect = pn53x_usb_disconnect, + .strerror = pn53x_strerror, .initiator_init = pn53x_initiator_init, .initiator_select_passive_target = pn53x_initiator_select_passive_target, diff --git a/libnfc/drivers/pn53x_usb.h b/libnfc/drivers/pn53x_usb.h index b2bff4c..2450ea5 100644 --- a/libnfc/drivers/pn53x_usb.h +++ b/libnfc/drivers/pn53x_usb.h @@ -29,8 +29,8 @@ # include -bool pn53x_usb_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound); -nfc_device_t *pn53x_usb_connect (const nfc_device_desc_t * pndd); +bool pn53x_usb_probe (nfc_connstring connstrings[], size_t connstrings_len, size_t * pszDeviceFound); +nfc_device_t *pn53x_usb_connect (const nfc_connstring connstring); bool pn53x_usb_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData, struct timeval *timeout); int pn53x_usb_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szData, struct timeval *timeout); void pn53x_usb_disconnect (nfc_device_t * pnd); diff --git a/libnfc/nfc-internal.h b/libnfc/nfc-internal.h index 9abc8ba..425c341 100644 --- a/libnfc/nfc-internal.h +++ b/libnfc/nfc-internal.h @@ -126,10 +126,10 @@ struct nfc_driver_t { const char *name; - bool (*probe)(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound); - nfc_device_t * (*connect)(const nfc_device_desc_t * pndd); - void (*disconnect)(nfc_device_t * pnd); - const char *(*strerror)(const nfc_device_t * pnd); + bool (*probe)(nfc_connstring connstrings[], size_t connstrings_len, size_t * pszDeviceFound); + nfc_device_t * (*connect) (const nfc_connstring connstring); + void (*disconnect) (nfc_device_t * pnd); + const char *(*strerror) (const nfc_device_t * pnd); bool (*initiator_init) (nfc_device_t * pnd); bool (*initiator_select_passive_target) (nfc_device_t * pnd, const nfc_modulation_t nm, const byte_t * pbtInitData, const size_t szInitData, nfc_target_t * pnt); diff --git a/libnfc/nfc.c b/libnfc/nfc.c index a6cc66a..5f1810f 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -61,63 +61,98 @@ const struct nfc_driver_t *nfc_drivers[] = { NULL }; +/** + * @brief Get the defaut NFC device + * @param connstring \a nfc_connstring pointer where the default connection string will be stored + * @return \e true on success + * + * This function fill \e connstring with the LIBNFC_DEFAULT_DEVICE environment variable content + * if is set otherwise it will search for the first available device, and fill + * \e connstring with the corresponding \a nfc_connstring value. + * + * This function returns true when LIBNFC_DEFAULT_DEVICE is set or an available device is found. + * + * @note The \e connstring content can be invalid if LIBNFC_DEFAULT_DEVICE is + * set with incorrect value. + */ +bool +nfc_get_default_device (nfc_connstring *connstring) +{ + char * env_default_connstring = getenv ("LIBNFC_DEFAULT_DEVICE"); + if (NULL == env_default_connstring) { + // LIBNFC_DEFAULT_DEVICE is not set, we fallback on probing for the first available device + size_t szDeviceFound; + nfc_connstring listed_cs[1]; + nfc_list_devices (listed_cs, 1, &szDeviceFound); + if (szDeviceFound) { + strncpy (*connstring, listed_cs[0], sizeof(nfc_connstring)); + } else { + return false; + } + } else { + strncpy (*connstring, env_default_connstring, sizeof(nfc_connstring)); + } + return true; +} + /** * @brief Connect to a NFC device - * @param pndd device description if specific device is wanted, \c NULL otherwise + * @param connstring The device connection string if specific device is wanted, \c NULL otherwise * @return Returns pointer to a \a nfc_device_t struct if successfull; otherwise returns \c NULL value. * - * If \e pndd is \c NULL, the first available NFC device is claimed. - * It will automatically search the system using all available drivers to determine a device is NFC-enabled. + * If \e connstring is \c NULL, the \a nfc_get_default_device() function is used. + * + * If \e connstring is set, this function will try to claim the right device using information provided by \e connstring. * - * If \e pndd is passed then this function will try to claim the right device using information provided by the \a nfc_device_desc_t struct. - * - * When it has successfully claimed a NFC device, memory is allocated to save the device information. It will return a pointer to a \a nfc_device_t struct. + * When it has successfully claimed a NFC device, memory is allocated to save the device information. + * It will return a pointer to a \a nfc_device_t struct. * This pointer should be supplied by every next functions of libnfc that should perform an action with this device. * - * @note Depending on the desired operation mode, the device needs to be configured - * by using nfc_initiator_init() or nfc_target_init(), optionally followed by manual tuning of the parameters if the default parameters are not suiting your goals. + * @note Depending on the desired operation mode, the device needs to be configured by using nfc_initiator_init() or nfc_target_init(), + * optionally followed by manual tuning of the parameters if the default parameters are not suiting your goals. */ nfc_device_t * -nfc_connect (nfc_device_desc_t * pndd) +nfc_connect (const nfc_connstring connstring) { + log_init (); nfc_device_t *pnd = NULL; - if (pndd == NULL) { - size_t szDeviceFound; - nfc_device_desc_t ndd[1]; - nfc_list_devices (ndd, 1, &szDeviceFound); - if (szDeviceFound) { - pndd = &ndd[0]; - } - } - - if (pndd == NULL) + nfc_connstring ncs; + if (connstring == NULL) { + if (!nfc_get_default_device (&ncs)) { + log_fini (); return NULL; - - log_init (); + } + } else { + strncpy (ncs, connstring, sizeof (nfc_connstring)); + } + // Search through the device list for an available device const struct nfc_driver_t *ndr; const struct nfc_driver_t **pndr = nfc_drivers; while ((ndr = *pndr)) { - // Specific device is requested: using device description pndd - if (0 != strcmp (ndr->name, pndd->pcDriver)) { + // Specific device is requested: using device description + if (0 != strncmp (ndr->name, ncs, strlen(ndr->name))) { pndr++; continue; - } else { - pnd = ndr->connect (pndd); } + pnd = ndr->connect (ncs); // Test if the connection was successful - if (pnd != NULL) { - log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "[%s] has been claimed.", pnd->acName); + if (pnd == NULL) { + log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Unable to connect to \"%s\".", ncs); + log_fini (); return pnd; - } else { - log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "No device found using driver: %s", ndr->name); } - pndr++; + + log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "[%s] has been claimed.", pnd->acName); + log_fini (); + return pnd; } + + // Too bad, no driver can decode connstring + log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "No driver available to handle \"%s\".", ncs); log_fini (); - // Too bad, no reader is ready to be claimed return NULL; } @@ -147,7 +182,7 @@ nfc_disconnect (nfc_device_t * pnd) * @param[out] pszDeviceFound number of devices found. */ void -nfc_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound) +nfc_list_devices (nfc_connstring connstrings[] , size_t szDevices, size_t * pszDeviceFound) { size_t szN; *pszDeviceFound = 0; @@ -157,7 +192,7 @@ nfc_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * ps log_init (); while ((ndr = *pndr)) { szN = 0; - if (ndr->probe (pnddDevices + (*pszDeviceFound), szDevices - (*pszDeviceFound), &szN)) { + if (ndr->probe (connstrings + (*pszDeviceFound), szDevices - (*pszDeviceFound), &szN)) { *pszDeviceFound += szN; log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "%ld device(s) found using %s driver", (unsigned long) szN, ndr->name); if (*pszDeviceFound == szDevices) diff --git a/utils/nfc-list.c b/utils/nfc-list.c index 8925f26..342b5f2 100644 --- a/utils/nfc-list.c +++ b/utils/nfc-list.c @@ -62,18 +62,16 @@ static nfc_device_t *pnd; int main (int argc, const char *argv[]) { + (void) argc; const char *acLibnfcVersion; - size_t szDeviceFound; size_t szTargetFound; size_t i; bool verbose = false; - nfc_device_desc_t *pnddDevices; // Display libnfc version acLibnfcVersion = nfc_version (); printf ("%s uses libnfc %s\n", argv[0], acLibnfcVersion); - pnddDevices = parse_args (argc, argv, &szDeviceFound, &verbose); #ifdef HAVE_LIBUSB # ifdef DEBUG usb_set_debug (4); @@ -101,15 +99,9 @@ main (int argc, const char *argv[]) strcpy(ndd.acDevice, "SCM Micro / SCL3711-NFC&RW"); pnd = nfc_connect (&ndd); #endif - - if (szDeviceFound == 0) { - if (!(pnddDevices = malloc (MAX_DEVICE_COUNT * sizeof (*pnddDevices)))) { - fprintf (stderr, "malloc() failed\n"); - return EXIT_FAILURE; - } - - nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szDeviceFound); - } + size_t szDeviceFound; + nfc_connstring connstrings[MAX_DEVICE_COUNT]; + nfc_list_devices (connstrings, MAX_DEVICE_COUNT, &szDeviceFound); if (szDeviceFound == 0) { printf ("No NFC device found.\n"); @@ -117,7 +109,7 @@ main (int argc, const char *argv[]) for (i = 0; i < szDeviceFound; i++) { nfc_target_t ant[MAX_TARGET_COUNT]; - pnd = nfc_connect (&(pnddDevices[i])); + pnd = nfc_connect (connstrings[i]); if (pnd == NULL) { ERR ("%s", "Unable to connect to NFC device."); @@ -243,6 +235,5 @@ main (int argc, const char *argv[]) nfc_disconnect (pnd); } - free (pnddDevices); return 0; } diff --git a/utils/nfc-relay-picc.c b/utils/nfc-relay-picc.c index 614e787..cbf27b7 100644 --- a/utils/nfc-relay-picc.c +++ b/utils/nfc-relay-picc.c @@ -150,7 +150,6 @@ main (int argc, char *argv[]) { int arg; size_t szFound; - nfc_device_desc_t *pnddDevices; const char *acLibnfcVersion = nfc_version (); nfc_target_t ntRealTarget; @@ -192,13 +191,9 @@ main (int argc, char *argv[]) signal (SIGINT, (void (*)()) intr_hdlr); #endif - // Allocate memory to put the result of available devices listing - if (!(pnddDevices = malloc (MAX_DEVICE_COUNT * sizeof (*pnddDevices)))) { - fprintf (stderr, "malloc() failed\n"); - return EXIT_FAILURE; - } + nfc_connstring connstrings[MAX_DEVICE_COUNT]; // List available devices - nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szFound); + nfc_list_devices (connstrings, MAX_DEVICE_COUNT, &szFound); if (initiator_only_mode || target_only_mode) { if (szFound < 1) { @@ -222,9 +217,9 @@ main (int argc, char *argv[]) // if there is more than one readers connected we connect to the second reader // (we hope they're always detected in the same order) if (szFound == 1) { - pndInitiator = nfc_connect (&(pnddDevices[0])); + pndInitiator = nfc_connect (connstrings[0]); } else { - pndInitiator = nfc_connect (&(pnddDevices[1])); + pndInitiator = nfc_connect (connstrings[1]); } if (!pndInitiator) { @@ -348,7 +343,7 @@ main (int argc, char *argv[]) print_nfc_iso14443a_info (ntEmulatedTarget.nti.nai, false); // Try to open the NFC emulator device - pndTarget = nfc_connect (&(pnddDevices[0])); + pndTarget = nfc_connect (connstrings[0]); if (pndTarget == NULL) { printf ("Error connecting NFC emulator device\n"); if (!target_only_mode) { diff --git a/utils/nfc-utils.c b/utils/nfc-utils.c index a3416e4..4321169 100644 --- a/utils/nfc-utils.c +++ b/utils/nfc-utils.c @@ -670,51 +670,6 @@ print_nfc_dep_info (const nfc_dep_info_t ndi, bool verbose) } } -/** - * @brief Tries to parse arguments to find device descriptions. - * @return Returns the list of found device descriptions. - */ -nfc_device_desc_t * -parse_args (int argc, const char *argv[], size_t * szFound, bool * verbose) -{ - nfc_device_desc_t *pndd = 0; - int arg; - *szFound = 0; - - // Get commandline options - for (arg = 1; arg < argc; arg++) { - - if (0 == strcmp (argv[arg], "--device")) { - // FIXME: this device selection by command line options is terrible & does not support USB/PCSC drivers - if (argc > arg + 1) { - char buffer[256]; - - pndd = malloc (sizeof (nfc_device_desc_t)); - - strncpy (buffer, argv[++arg], 256); - - // Driver. - pndd->pcDriver = (char *) malloc (256); - strcpy (pndd->pcDriver, strtok (buffer, ":")); - - // Port. - strcpy (pndd->acPort, strtok (NULL, ":")); - - // Speed. - sscanf (strtok (NULL, ":"), "%u", &pndd->uiSpeed); - - *szFound = 1; - } else { - errx (1, "usage: %s [--device driver:port:speed]", argv[0]); - } - } - if ((0 == strcmp (argv[arg], "-v")) || (0 == strcmp (argv[arg], "--verbose"))) { - *verbose = true; - } - } - return pndd; -} - const char * str_nfc_baud_rate (const nfc_baud_rate_t nbr) { diff --git a/utils/nfc-utils.h b/utils/nfc-utils.h index 3f08177..ace6473 100644 --- a/utils/nfc-utils.h +++ b/utils/nfc-utils.h @@ -97,6 +97,4 @@ void print_nfc_dep_info (const nfc_dep_info_t ndi, bool verbose); void print_nfc_target (const nfc_target_t nt, bool verbose); -nfc_device_desc_t *parse_args (int argc, const char *argv[], size_t * szFound, bool * verbose); - #endif