Allow to connect to a device using a connection string:

- Provide a nfc_get_default_device() that allow to grab the connstring stored
   in LIBNFC_DEFAULT_DEVICE environnement variable or returns the first
   available device if not set;
 - nfc_connect(NULL) now takes the default device (see
   nfc_get_default_device());
 - Removes nfc_driver_desc_t from public types
 - Defines nfc_connstring as char[1024]
 - examples/*: use nfc_connstring
 - examples/nfc-poll: now uses only the default device (instead of all devices
   availables)
 - Removes parse_args() from nfc-utils.[hc]
This commit is contained in:
Romuald Conty 2011-10-17 13:03:56 +00:00
parent dc842a844c
commit 55daa29a7c
20 changed files with 559 additions and 380 deletions

View file

@ -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;

View file

@ -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);
}

View file

@ -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...");

View file

@ -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.");

View file

@ -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)

View file

@ -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);

View file

@ -40,7 +40,7 @@
// Bus
#include <winscard.h>
# 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
};

View file

@ -26,10 +26,10 @@
# include <nfc/nfc-types.h>
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);

View file

@ -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 <stdio.h>
#include <inttypes.h>
#include <string.h>
#include <sys/param.h>
#include <string.h>
@ -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()
};

View file

@ -30,9 +30,9 @@
# include <nfc/nfc-types.h>
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);

View file

@ -32,6 +32,7 @@
#include "pn532_uart.h"
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
#include <unistd.h>
@ -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,

View file

@ -29,9 +29,9 @@
# include <nfc/nfc-types.h>
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);

View file

@ -32,10 +32,11 @@
Thanks to d18c7db and Okko for example code
*/
#include <sys/select.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <sys/select.h>
#include <errno.h>
#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,

View file

@ -29,8 +29,8 @@
# include <nfc/nfc-types.h>
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);

View file

@ -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);

View file

@ -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)

View file

@ -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;
}

View file

@ -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) {

View file

@ -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)
{

View file

@ -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