diff --git a/examples/mifare.c b/examples/mifare.c
index c828dce..9fcc47e 100644
--- a/examples/mifare.c
+++ b/examples/mifare.c
@@ -56,10 +56,6 @@ nfc_initiator_mifare_cmd (nfc_device_t * pnd, const mifare_cmd mc, const uint8_t
byte_t abtCmd[265];
bool bEasyFraming;
- // Make sure we are dealing with a active device
- if (!pnd->bActive)
- return false;
-
abtCmd[0] = mc; // The MIFARE Classic command
abtCmd[1] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff)
diff --git a/examples/pn53x-diagnose.c b/examples/pn53x-diagnose.c
index f5995aa..735f21a 100644
--- a/examples/pn53x-diagnose.c
+++ b/examples/pn53x-diagnose.c
@@ -40,10 +40,10 @@
#include "nfc-utils.h"
#include "chips/pn53x.h"
+#include "chips/pn53x-internal.h"
#define MAX_DEVICE_COUNT 16
-
int
main (int argc, const char *argv[])
{
@@ -54,7 +54,7 @@ main (int argc, const char *argv[])
const char *acLibnfcVersion;
bool result;
- byte_t abtRx[PN53x_EXTENDED_FRAME_MAX_LEN];
+ byte_t abtRx[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
size_t szRx;
const byte_t pncmd_diagnose_communication_line_test[] = { 0xD4, 0x00, 0x00, 0x06, 'l', 'i', 'b', 'n', 'f', 'c' };
const byte_t pncmd_diagnose_rom_test[] = { 0xD4, 0x00, 0x01 };
@@ -88,19 +88,19 @@ main (int argc, const char *argv[])
printf ("NFC device [%s] connected.\n", pnd->acName);
- result = pn53x_transceive (pnd, pncmd_diagnose_communication_line_test, sizeof (pncmd_diagnose_communication_line_test), abtRx, &szRx);
+ result = pn53x_transceive (pnd, pncmd_diagnose_communication_line_test, sizeof (pncmd_diagnose_communication_line_test), abtRx, &szRx, false);
if (result) {
result = (memcmp (pncmd_diagnose_communication_line_test + 2, abtRx, sizeof (pncmd_diagnose_communication_line_test) - 2) == 0);
}
printf (" Communication line test: %s\n", result ? "OK" : "Failed");
- result = pn53x_transceive (pnd, pncmd_diagnose_rom_test, sizeof (pncmd_diagnose_rom_test), abtRx, &szRx);
+ result = pn53x_transceive (pnd, pncmd_diagnose_rom_test, sizeof (pncmd_diagnose_rom_test), abtRx, &szRx, false);
if (result) {
result = ((szRx == 1) && (abtRx[0] == 0x00));
}
printf (" ROM test: %s\n", result ? "OK" : "Failed");
- result = pn53x_transceive (pnd, pncmd_diagnose_ram_test, sizeof (pncmd_diagnose_ram_test), abtRx, &szRx);
+ result = pn53x_transceive (pnd, pncmd_diagnose_ram_test, sizeof (pncmd_diagnose_ram_test), abtRx, &szRx, false);
if (result) {
result = ((szRx == 1) && (abtRx[0] == 0x00));
}
diff --git a/examples/pn53x-sam.c b/examples/pn53x-sam.c
index a9925be..e981dd3 100644
--- a/examples/pn53x-sam.c
+++ b/examples/pn53x-sam.c
@@ -93,7 +93,7 @@ sam_connection (nfc_device_t * pnd, int mode)
break;
}
- if (!pn53x_transceive (pnd, pncmd_sam_config, szCmd, abtRx, &szRx)) {
+ if (!pn53x_transceive (pnd, pncmd_sam_config, szCmd, abtRx, &szRx, false)) {
nfc_perror(pnd, "pn53x_transceive");
ERR ("%s %d", "Unable to execute SAMConfiguration command with mode byte:", mode);
return false;
diff --git a/examples/pn53x-tamashell.c b/examples/pn53x-tamashell.c
index b09d4da..4a0410d 100644
--- a/examples/pn53x-tamashell.c
+++ b/examples/pn53x-tamashell.c
@@ -167,7 +167,7 @@ int main(int argc, const char* argv[])
printf("Tx: ");
print_hex((byte_t*)abtTx+1,szTx-1);
- if (!pn53x_transceive (pnd, abtTx, szTx, abtRx, &szRx)) {
+ if (!pn53x_transceive (pnd, abtTx, szTx, abtRx, &szRx, false)) {
free(cmd);
nfc_perror (pnd, "Rx");
continue;
diff --git a/include/nfc/nfc-types.h b/include/nfc/nfc-types.h
index 1d9e50c..1663c06 100644
--- a/include/nfc/nfc-types.h
+++ b/include/nfc/nfc-types.h
@@ -3,6 +3,7 @@
*
* Copyright (C) 2009, Roel Verdult
* Copyright (C) 2010, Romain Tartière, Romuald Conty
+ * Copyright (C) 2011, Romain Tartière, Romuald Conty
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
@@ -16,8 +17,9 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see
- *
- *
+ */
+
+/**
* @file nfc-types.h
* @brief Define NFC types
*/
@@ -25,12 +27,6 @@
#ifndef __NFC_TYPES_H__
# define __NFC_TYPES_H__
-/**
- * @file types.h
- * @brief libnfc-defined types
- *
- * Define libnfc specific types: typedef, enum, struct, etc.
- */
# include
# include
# include
@@ -38,32 +34,19 @@
typedef uint8_t byte_t;
-typedef enum {
- NC_PN531 = 0x10,
- NC_PN532 = 0x20,
- NC_PN533 = 0x30,
-} nfc_chip_t;
-
-struct driver_callbacks; // Prototype the callback struct
-
-typedef void *nfc_device_spec_t; // Device connection specification
-
# define DEVICE_NAME_LENGTH 256
/**
* @struct nfc_device_t
* @brief NFC device information
*/
typedef struct {
-/** Callback functions for handling device specific wrapping */
- const struct driver_callbacks *pdc;
+/** Driver's functions for handling device specific wrapping */
+ const struct nfc_driver_t *driver;
+ void* driver_data;
+ void* chip_data;
+
/** Device name string, including device wrapper firmware */
char acName[DEVICE_NAME_LENGTH];
-/** PN53X chip type, this is useful for some "bug" work-arounds */
- nfc_chip_t nc;
-/** Pointer to the device connection specification */
- nfc_device_spec_t nds;
-/** This represents if the PN53X device was initialized succesful */
- bool bActive;
/** Is the crc automaticly added, checked and removed from the frames */
bool bCrc;
/** Does the PN53x chip handles parity bits, all parities are handled as data */
@@ -87,8 +70,10 @@ typedef struct {
* +----------- Driver-level general error (common to all drivers)
*/
int iLastError;
+/** Last sent command */
+ int iLastCommand;
} nfc_device_t;
-
+// TODO: Move chip's specifics in a chips structure (e.g. iLastCommand, ui8Parameters, ui8TxBits)
/**
* @struct nfc_device_desc_t
@@ -118,29 +103,6 @@ struct chip_callbacks {
const char *(*strerror) (const nfc_device_t * pnd);
};
-/**
- * @struct driver_callbacks
- * @brief Generic structure to handle NFC device functions.
- */
-struct driver_callbacks {
- /** Driver name */
- const char *acDriver;
- /** Chip specific callback functions */
- const struct chip_callbacks *pcc;
- /** Pick devices callback */
- nfc_device_desc_t *(*pick_device) (void);
- /** List devices callback */
- bool (*list_devices) (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound);
- /** Connect callback */
- nfc_device_t *(*connect) (const nfc_device_desc_t * pndd);
- /** Init callback */
- void (*init) (nfc_device_t * pnd);
- /** Transceive callback */
- bool (*transceive) (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx, size_t * pszRx);
- /** Disconnect callback */
- void (*disconnect) (nfc_device_t * pnd);
-};
-
// Compiler directive, set struct alignment to 1 byte_t for compatibility
# pragma pack(1)
diff --git a/libnfc/Makefile.am b/libnfc/Makefile.am
index 7e129ec..d6602ed 100644
--- a/libnfc/Makefile.am
+++ b/libnfc/Makefile.am
@@ -3,7 +3,7 @@ SUBDIRS = chips buses drivers .
# set the include path found by configure
INCLUDES = $(all_includes) $(LIBNFC_CFLAGS)
-noinst_HEADERS = chips.h buses.h drivers.h mirror-subr.h
+noinst_HEADERS = chips.h buses.h drivers.h mirror-subr.h nfc-internal.h
lib_LTLIBRARIES = libnfc.la
libnfc_la_SOURCES = nfc.c iso14443-subr.c mirror-subr.c
libnfc_la_LDFLAGS = -no-undefined -version-info 1:0:0
diff --git a/libnfc/buses/uart.h b/libnfc/buses/uart.h
index 15bb3f0..9745477 100644
--- a/libnfc/buses/uart.h
+++ b/libnfc/buses/uart.h
@@ -1,7 +1,9 @@
/*-
* Public platform independent Near Field Communication (NFC) library
*
- * Copyright (C) 2009, 2010, Roel Verdult, Romuald Conty
+ * Copyright (C) 2009, Roel Verdult, Romuald Conty
+ * Copyright (C) 2010, Roel Verdult, Romuald Conty
+ * Copyright (C) 2011, Romuald Conty, Romain Tartière
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
@@ -54,17 +56,7 @@
// Try to guess what we should use.
# if defined (_WIN32)
# define DEFAULT_SERIAL_PORTS { "COM1", "COM2", "COM3", "COM4", NULL }
-# elif defined(__APPLE__)
- // XXX: find UART connection string for PN53X device on Mac OS X when multiples devices are used
-# define DEFAULT_SERIAL_PORTS { "/dev/tty.SLAB_USBtoUART", NULL }
-# elif defined (__FreeBSD__) || defined (__OpenBSD__)
- // XXX: Not tested
-# define DEFAULT_SERIAL_PORTS { "/dev/cuau0", "/dev/cuau1", "/dev/cuau2", "/dev/cuau3", NULL }
-# elif defined (__linux__)
-# define DEFAULT_SERIAL_PORTS { "/dev/ttyUSB0", "/dev/ttyUSB1", "/dev/ttyUSB2", "/dev/ttyUSB3", "/dev/ttyS0", "/dev/ttyS1", "/dev/ttyS2", "/dev/ttyS3", NULL }
-# else
-# error "Can't determine serial string for your system"
-# endif
+# endif
// Define shortcut to types to make code more readable
typedef void *serial_port;
@@ -77,7 +69,9 @@ void uart_close (const serial_port sp);
void uart_set_speed (serial_port sp, const uint32_t uiPortSpeed);
uint32_t uart_get_speed (const serial_port sp);
-int uart_receive (serial_port sp, byte_t * pbtRx, size_t * pszRx);
+int uart_receive (serial_port sp, byte_t * pbtRx, const size_t szRx);
int uart_send (serial_port sp, const byte_t * pbtTx, const size_t szTx);
+char **uart_list_ports (void);
+
#endif // __NFC_BUS_UART_H__
diff --git a/libnfc/buses/uart_posix.c b/libnfc/buses/uart_posix.c
index 07b8de9..2bfad25 100644
--- a/libnfc/buses/uart_posix.c
+++ b/libnfc/buses/uart_posix.c
@@ -2,6 +2,8 @@
* Public platform independent Near Field Communication (NFC) library
*
* Copyright (C) 2009, 2010, Roel Verdult, Romuald Conty
+ * Copyright (C) 2010, Roel Verdult, Romuald Conty
+ * Copyright (C) 2011, Romuald Conty, Romain Tartière
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
@@ -23,9 +25,29 @@
* @brief POSIX UART driver
*/
+/* vim: set ts=2 sw=2 et: */
+
+# include
# include
# include
+# include
# include
+# include
+# include
+
+# include "nfc-internal.h"
+
+# if defined(__APPLE__)
+ // FIXME: find UART connection string for PN53X device on Mac OS X when multiples devices are used
+char *serial_ports_device_radix[] = { "tty.SLAB_USBtoUART", NULL };
+# elif defined (__FreeBSD__) || defined (__OpenBSD__)
+char *serial_ports_device_radix[] = { "cuaU", "cuau", NULL };
+# elif defined (__linux__)
+char *serial_ports_device_radix[] = { "ttyUSB", "ttyS", NULL };
+# else
+# error "Can't determine serial string for your system"
+# endif
+
typedef struct termios term_info;
typedef struct {
int fd; // Serial port file descriptor
@@ -33,12 +55,6 @@ typedef struct {
term_info tiNew; // Terminal info during the transaction
} serial_port_unix;
-// timeval struct that define timeout delay for serial port:
-// first is constant and currently related to PN53x response delay
-static const unsigned long int uiTimeoutStatic = 15000; // 15 ms to allow device to respond
-// second is a per-byte timeout (sets when setting baudrate)
-static unsigned long int uiTimeoutPerByte = 0;
-
// Work-around to claim uart interface using the c_iflag (software input processing) from the termios struct
# define CCLAIMED 0x80000000
@@ -85,25 +101,10 @@ uart_open (const char *pcPortName)
return sp;
}
-/**
- * @note This define convert a Baud rate in a per-byte duration (in µs)
- * Bauds are "symbols per second", so each symbol is bit here.
- * We want to convert Bd to bytes/s in first time,
- * 1 serial-transmitted byte is (in 8N1):
- * - 1 start bit,
- * - 8 data bits,
- * - 1 stop bit.
- *
- * In 8N1 mode, byte-rate = baud-rate / 10
- */
-#define UART_BAUDRATE_T0_BYTE_DURATION(X) ((1000000 * 10)/ X)
-
void
uart_set_speed (serial_port sp, const uint32_t uiPortSpeed)
{
- // Set per-byte timeout
- uiTimeoutPerByte = UART_BAUDRATE_T0_BYTE_DURATION(uiPortSpeed);
- DBG ("Serial port speed requested to be set to %d bauds (%lu µs).", uiPortSpeed, uiTimeoutPerByte);
+ DBG ("Serial port speed requested to be set to %d bauds.", uiPortSpeed);
const serial_port_unix *spu = (serial_port_unix *) sp;
// Portability note: on some systems, B9600 != 9600 so we have to do
@@ -203,28 +204,26 @@ uart_close (const serial_port sp)
free (sp);
}
+static const struct timeval tvTimeout = {
+ .tv_sec = 1,
+ .tv_usec = 0
+};
+
/**
* @brief Receive data from UART and copy data to \a pbtRx
*
* @return 0 on success, otherwise driver error code
*/
int
-uart_receive (serial_port sp, byte_t * pbtRx, size_t * pszRx)
+uart_receive (serial_port sp, byte_t * pbtRx, const size_t szRx)
{
- int res;
- int byteCount;
- fd_set rfds;
- int iExpectedByteCount = (int)*pszRx;
- DBG ("iExpectedByteCount == %d", iExpectedByteCount);
- struct timeval tvTimeout = {
- .tv_sec = 0,
- .tv_usec = uiTimeoutStatic + (uiTimeoutPerByte * iExpectedByteCount),
- };
struct timeval tv = tvTimeout;
-
- // Reset the output count
- *pszRx = 0;
+ int received_bytes_count = 0;
+ int available_bytes_count = 0;
+ const int expected_bytes_count = (int)szRx;
+ int res;
+ fd_set rfds;
do {
// Reset file descriptor
FD_ZERO (&rfds);
@@ -238,35 +237,25 @@ uart_receive (serial_port sp, byte_t * pbtRx, size_t * pszRx)
}
// Read time-out
if (res == 0) {
- if (*pszRx == 0) {
- // Error, we received no data
- // DBG ("RX time-out (%lu µs), buffer empty.", tvTimeout.tv_usec);
- return DETIMEOUT;
- } else {
- // We received some data, but nothing more is available
- return 0;
- }
+ DBG ("Timeout!");
+ return DETIMEOUT;
}
// Retrieve the count of the incoming bytes
- res = ioctl (((serial_port_unix *) sp)->fd, FIONREAD, &byteCount);
- if (res < 0) {
+ res = ioctl (((serial_port_unix *) sp)->fd, FIONREAD, &available_bytes_count);
+ if (res != 0) {
return DEIO;
}
// There is something available, read the data
- res = read (((serial_port_unix *) sp)->fd, pbtRx + (*pszRx), MIN(byteCount, iExpectedByteCount));
- iExpectedByteCount -= MIN (byteCount, iExpectedByteCount);
-
+ // DBG ("expected bytes: %zu, received bytes: %d, available bytes: %d", szRx, received_bytes_count, available_bytes_count);
+ res = read (((serial_port_unix *) sp)->fd, pbtRx + received_bytes_count, MIN(available_bytes_count, (expected_bytes_count - received_bytes_count)));
// Stop if the OS has some troubles reading the data
if (res <= 0) {
return DEIO;
}
+ received_bytes_count += res;
- *pszRx += res;
- // Reload timeout with a low value to prevent from waiting too long on slow devices (16x is enought to took at least 1 byte)
- tv.tv_usec = uiTimeoutPerByte * MIN( iExpectedByteCount, 16 );
- // DBG("Timeout reloaded at: %d µs", tv.tv_usec);
- } while (byteCount && (iExpectedByteCount > 0));
- DBG ("byteCount == %d, iExpectedByteCount == %d", byteCount, iExpectedByteCount);
+ } while (expected_bytes_count > received_bytes_count);
+ PRINT_HEX ("RX", pbtRx, szRx);
return 0;
}
@@ -278,13 +267,16 @@ uart_receive (serial_port sp, byte_t * pbtRx, size_t * pszRx)
int
uart_send (serial_port sp, const byte_t * pbtTx, const size_t szTx)
{
+ PRINT_HEX ("TX", pbtTx, szTx);
+#if 0
+ if ((int) szTx == write (((serial_port_unix *) sp)->fd, pbtTx, szTx))
+ return 0;
+ else
+ return DEIO;
+#endif
int32_t res;
size_t szPos = 0;
fd_set rfds;
- struct timeval tvTimeout = {
- .tv_sec = 0,
- .tv_usec = uiTimeoutStatic + (uiTimeoutPerByte * szTx),
- };
struct timeval tv = tvTimeout;
while (szPos < szTx) {
@@ -312,10 +304,45 @@ uart_send (serial_port sp, const byte_t * pbtTx, const size_t szTx)
}
szPos += res;
-
- // Reload timeout with a low value to prevent from waiting too long on slow devices (16x is enought to took at least 1 byte)
- tv.tv_usec = uiTimeoutStatic + uiTimeoutPerByte * MIN( szTx - szPos, 16 );
}
return 0;
}
+char **
+uart_list_ports (void)
+{
+ char **res = malloc (sizeof (char *));
+ size_t szRes = 1;
+
+ res[0] = NULL;
+
+ DIR *pdDir = opendir("/dev");
+ struct dirent *pdDirEnt;
+ while ((pdDirEnt = readdir(pdDir)) != NULL) {
+ if (!isdigit (pdDirEnt->d_name[strlen (pdDirEnt->d_name) - 1]))
+ continue;
+
+ char **p = serial_ports_device_radix;
+ while (*p) {
+ if (!strncmp(pdDirEnt->d_name, *p, strlen (*p))) {
+ char **res2 = realloc (res, (szRes+1) * sizeof (char *));
+ if (!res2)
+ goto oom;
+
+ res = res2;
+ if (!(res[szRes-1] = malloc (6 + strlen (pdDirEnt->d_name))))
+ goto oom;
+
+ sprintf (res[szRes-1], "/dev/%s", pdDirEnt->d_name);
+
+ szRes++;
+ res[szRes-1] = NULL;
+ }
+ p++;
+ }
+ }
+oom:
+ closedir (pdDir);
+
+ return res;
+}
diff --git a/libnfc/chips/Makefile.am b/libnfc/chips/Makefile.am
index 2b8b9ee..94be1fa 100644
--- a/libnfc/chips/Makefile.am
+++ b/libnfc/chips/Makefile.am
@@ -2,8 +2,7 @@
# set the include path found by configure
INCLUDES= $(all_includes) $(LIBNFC_CFLAGS)
-noinst_HEADERS = pn53x.h
+noinst_HEADERS = pn53x.h pn53x-internal.h
noinst_LTLIBRARIES = libnfcchips.la
libnfcchips_la_SOURCES = pn53x.c
libnfcchips_la_CFLAGS = -I$(top_srcdir)/libnfc
-
diff --git a/libnfc/chips/pn53x-internal.h b/libnfc/chips/pn53x-internal.h
new file mode 100644
index 0000000..18e911b
--- /dev/null
+++ b/libnfc/chips/pn53x-internal.h
@@ -0,0 +1,190 @@
+/*-
+ * Public platform independent Near Field Communication (NFC) library
+ *
+ * Copyright (C) 2011, Romuald Conty, Romain Tartière
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see
+ */
+
+/**
+ * @file pn53x-internal.h
+ * @brief PN531, PN532 and PN533 defines and compatibility
+ */
+
+#ifndef __PN53X_INTERNAL_H__
+#define __PN53X_INTERNAL_H__
+
+#include "pn53x.h"
+
+// Miscellaneous
+#define Diagnose 0x00
+#define GetFirmwareVersion 0x02
+#define GetGeneralStatus 0x04
+#define ReadRegister 0x06
+#define WriteRegister 0x08
+#define ReadGPIO 0x0C
+#define WriteGPIO 0x0E
+#define SetSerialBaudRate 0x10
+#define SetParameters 0x12
+#define SAMConfiguration 0x14
+#define PowerDown 0x16
+#define AlparCommandForTDA 0x18
+
+// RF communication
+#define RFConfiguration 0x32
+#define RFRegulationTest 0x58
+
+// Initiator
+#define InJumpForDEP 0x56
+#define InJumpForPSL 0x46
+#define InListPassiveTarget 0x4A
+#define InATR 0x50
+#define InPSL 0x4E
+#define InDataExchange 0x40
+#define InCommunicateThru 0x42
+#define InQuartetByteExchange 0x38
+#define InDeselect 0x44
+#define InRelease 0x52
+#define InSelect 0x54
+#define InActivateDeactivatePaypass 0x48
+#define InAutoPoll 0x60
+
+// Target
+#define TgInitAsTarget 0x8C
+#define TgSetGeneralBytes 0x92
+#define TgGetData 0x86
+#define TgSetData 0x8E
+#define TgSetDataSecure 0x96
+#define TgSetMetaData 0x94
+#define TgSetMetaDataSecure 0x98
+#define TgGetInitiatorCommand 0x88
+#define TgResponseToInitiator 0x90
+#define TgGetTargetStatus 0x8A
+
+/** @note PN53x's normal frame:
+ *
+ * .-- Start
+ * | .-- Packet lenght
+ * | | .-- Lenght checksum
+ * | | | .-- Direction (D4 Host to PN, D5 PN to Host)
+ * | | | | .-- Code
+ * | | | | | .-- Packet checksum
+ * | | | | | | .-- Postamble
+ * V | | | | | |
+ * ----- V V V V V V
+ * 00 FF 02 FE D4 02 2A 00
+ */
+
+/** @note PN53x's extended frame:
+ *
+ * .-- Start
+ * | .-- Fixed to FF to enable extended frame
+ * | | .-- Packet lenght
+ * | | | .-- Lenght checksum
+ * | | | | .-- Direction (D4 Host to PN, D5 PN to Host)
+ * | | | | | .-- Code
+ * | | | | | | .-- Packet checksum
+ * | | | | | | | .-- Postamble
+ * V V V | | | | |
+ * ----- ----- ----- V V V V V
+ * 00 FF FF FF 00 02 FE D4 02 2A 00
+ */
+
+/**
+ * Start bytes, packet lenght, lenght checksum, direction, packet checksum and postamble are overhead
+ */
+// The TFI is considered part of the overhead
+# define PN53x_NORMAL_FRAME__DATA_MAX_LEN 254
+# define PN53x_NORMAL_FRAME__OVERHEAD 8
+# define PN53x_EXTENDED_FRAME__DATA_MAX_LEN 264
+# define PN53x_EXTENDED_FRAME__OVERHEAD 11
+
+typedef struct {
+ uint8_t ui8Code;
+ uint8_t ui8CompatFlags;
+#ifdef DEBUG
+ const char * abtCommandText;
+#endif
+} pn53x_command;
+
+/*
+#define PN531 0x01
+#define PN532 0x02
+#define PN533 0X04
+*/
+
+#ifndef DEBUG
+# define PNCMD( X, Y ) { X , Y }
+# define PNCMD_DBG( X ) do { \
+ } while(0)
+#else
+# define PNCMD( X, Y ) { X , Y, #X }
+# define PNCMD_DBG( X ) do { \
+ for (size_t i=0; i<(sizeof(pn53x_commands)/sizeof(pn53x_command)); i++) { \
+ if ( X == pn53x_commands[i].ui8Code ) { \
+ DBG( "%s", pn53x_commands[i].abtCommandText ); \
+ break; \
+ } \
+ } \
+ } while(0)
+#endif
+
+static const pn53x_command pn53x_commands[] = {
+ // Miscellaneous
+ PNCMD( Diagnose, PN531|PN532|PN533 ),
+ PNCMD( GetFirmwareVersion, PN531|PN532|PN533 ),
+ PNCMD( GetGeneralStatus, PN531|PN532|PN533 ),
+ PNCMD( ReadRegister, PN531|PN532|PN533 ),
+ PNCMD( WriteRegister, PN531|PN532|PN533 ),
+ PNCMD( ReadGPIO, PN531|PN532|PN533 ),
+ PNCMD( WriteGPIO, PN531|PN532|PN533 ),
+ PNCMD( SetSerialBaudRate, PN531|PN532|PN533 ),
+ PNCMD( SetParameters, PN531|PN532|PN533 ),
+ PNCMD( SAMConfiguration, PN531|PN532 ),
+ PNCMD( PowerDown, PN531|PN532 ),
+ PNCMD( AlparCommandForTDA, PN533 ),
+
+ // RF communication
+ PNCMD( RFConfiguration, PN531|PN532|PN533 ),
+ PNCMD( RFRegulationTest, PN531|PN532|PN533 ),
+
+ // Initiator
+ PNCMD( InJumpForDEP, PN531|PN532|PN533 ),
+ PNCMD( InJumpForPSL, PN531|PN532|PN533 ),
+ PNCMD( InListPassiveTarget, PN531|PN532|PN533 ),
+ PNCMD( InATR, PN531|PN532|PN533 ),
+ PNCMD( InPSL, PN531|PN532|PN533 ),
+ PNCMD( InDataExchange, PN531|PN532|PN533 ),
+ PNCMD( InCommunicateThru, PN531|PN532|PN533 ),
+ PNCMD( InQuartetByteExchange, PN533 ),
+ PNCMD( InDeselect, PN531|PN532|PN533 ),
+ PNCMD( InRelease, PN531|PN532|PN533 ),
+ PNCMD( InSelect, PN531|PN532|PN533 ),
+ PNCMD( InAutoPoll, PN532 ),
+ PNCMD( InActivateDeactivatePaypass, PN533 ),
+
+ // Target
+ PNCMD( TgInitAsTarget, PN531|PN532|PN533 ),
+ PNCMD( TgSetGeneralBytes, PN531|PN532|PN533 ),
+ PNCMD( TgGetData, PN531|PN532|PN533 ),
+ PNCMD( TgSetData, PN531|PN532|PN533 ),
+ PNCMD( TgSetDataSecure, PN533 ),
+ PNCMD( TgSetMetaData, PN531|PN532|PN533 ),
+ PNCMD( TgSetMetaDataSecure, PN533 ),
+ PNCMD( TgGetInitiatorCommand, PN531|PN532|PN533 ),
+ PNCMD( TgResponseToInitiator, PN531|PN532|PN533 ),
+ PNCMD( TgGetTargetStatus, PN531|PN532|PN533 ),
+};
+
+#endif /* __PN53X_INTERNAL_H__ */
diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c
index 7b437f4..6493f90 100644
--- a/libnfc/chips/pn53x.c
+++ b/libnfc/chips/pn53x.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2009, Roel Verdult, Romuald Conty
* Copyright (C) 2010, Roel Verdult, Romuald Conty, Romain Tartière
+ * Copyright (C) 2011, Romuald Conty, Romain Tartière
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
@@ -36,52 +37,27 @@
#include
#include "pn53x.h"
-#include "../mirror-subr.h"
+#include "pn53x-internal.h"
+#include "libnfc/mirror-subr.h"
+#include "libnfc/nfc-internal.h"
#ifdef _WIN32
-# include "../../contrib/windows.h"
+# include "contrib/windows.h"
#endif
#include
-// PN53X configuration
-const byte_t pncmd_get_firmware_version[2] = { 0xD4, 0x02 };
-const byte_t pncmd_get_general_status[2] = { 0xD4, 0x04 };
-const byte_t pncmd_get_register[4] = { 0xD4, 0x06 };
-const byte_t pncmd_set_register[5] = { 0xD4, 0x08 };
-const byte_t pncmd_set_parameters[3] = { 0xD4, 0x12 };
-const byte_t pncmd_rf_configure[14] = { 0xD4, 0x32 };
-
-// Reader
-const byte_t pncmd_initiator_list_passive[264] = { 0xD4, 0x4A };
+// TODO: Count max bytes for InJumpForDEP reply
const byte_t pncmd_initiator_jump_for_dep[68] = { 0xD4, 0x56 };
-const byte_t pncmd_initiator_select[3] = { 0xD4, 0x54 };
-const byte_t pncmd_initiator_deselect[3] = { 0xD4, 0x44, 0x00 };
-const byte_t pncmd_initiator_release[3] = { 0xD4, 0x52, 0x00 };
-const byte_t pncmd_initiator_set_baud_rate[5] = { 0xD4, 0x4E };
-const byte_t pncmd_initiator_exchange_data[265] = { 0xD4, 0x40 };
-const byte_t pncmd_initiator_exchange_raw_data[266] = { 0xD4, 0x42 };
-const byte_t pncmd_initiator_auto_poll[5] = { 0xD4, 0x60 };
-
-// Target
-const byte_t pncmd_target_get_data[2] = { 0xD4, 0x86 };
-const byte_t pncmd_target_set_data[264] = { 0xD4, 0x8E };
-const byte_t pncmd_target_init[2] = { 0xD4, 0x8C };
-//Example of default values for PN532 or PN533:
-//const byte_t pncmd_target_init[39] = { 0xD4, 0x8C, 0x00, 0x08, 0x00, 0x12, 0x34, 0x56, 0x40, 0x01, 0xFE, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xFF, 0xFF, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, 0x00 };
-const byte_t pncmd_target_virtual_card[4] = { 0xD4, 0x14 };
-const byte_t pncmd_target_get_initiator_command[2] = { 0xD4, 0x88 };
-const byte_t pncmd_target_response_to_initiator[264] = { 0xD4, 0x90 };
-const byte_t pncmd_target_get_status[2] = { 0xD4, 0x8A };
static const byte_t pn53x_ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
static const byte_t pn53x_nack_frame[] = { 0x00, 0x00, 0xff, 0xff, 0x00, 0x00 };
static const byte_t pn53x_error_frame[] = { 0x00, 0x00, 0xff, 0x01, 0xff, 0x7f, 0x81, 0x00 };
/* prototypes */
-const nfc_modulation_t pn53x_ptt_to_nm( const pn53x_target_type_t ptt );
-const pn53x_modulation_t pn53x_nm_to_pm(const nfc_modulation_t nm);
-const pn53x_target_type_t pn53x_nm_to_ptt(const nfc_modulation_t nm);
+nfc_modulation_t pn53x_ptt_to_nm (const pn53x_target_type_t ptt);
+pn53x_modulation_t pn53x_nm_to_pm (const nfc_modulation_t nm);
+pn53x_target_type_t pn53x_nm_to_ptt (const nfc_modulation_t nm);
bool
pn53x_init(nfc_device_t * pnd)
@@ -93,7 +69,7 @@ pn53x_init(nfc_device_t * pnd)
// Reset the ending transmission bits register, it is unknown what the last tranmission used there
pnd->ui8TxBits = 0;
- if (!pn53x_set_reg (pnd, REG_CIU_BIT_FRAMING, SYMBOL_TX_LAST_BITS, 0x00)) {
+ if (!pn53x_write_register (pnd, REG_CIU_BIT_FRAMING, SYMBOL_TX_LAST_BITS, 0x00)) {
return false;
}
@@ -125,8 +101,7 @@ pn53x_check_ack_frame_callback (nfc_device_t * pnd, const byte_t * pbtRxFrame, c
return true;
} else if (0 == memcmp (pbtRxFrame, pn53x_nack_frame, sizeof (pn53x_nack_frame))) {
DBG ("%s", "PN53x NACKed");
- // TODO Try to recover when PN53x NACKs !
- // A counter could allow the command to be sent again (e.g. max 3 times)
+ // TODO Double check in user manual if no PN53x replies NACK then remove this
pnd->iLastError = DENACK;
return false;
}
@@ -150,16 +125,16 @@ pn53x_check_error_frame_callback (nfc_device_t * pnd, const byte_t * pbtRxFrame,
return false;
}
}
-
return true;
}
-#define PN53x_REPLY_FRAME_MAX_LEN (PN53x_EXTENDED_FRAME_MAX_LEN + PN53x_EXTENDED_FRAME_OVERHEAD + sizeof(pn53x_ack_frame))
bool
-pn53x_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx, size_t * pszRx)
+pn53x_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx, size_t *pszRx, bool toto)
{
- byte_t abtRx[PN53x_REPLY_FRAME_MAX_LEN];
- size_t szRx = PN53x_EXTENDED_FRAME_MAX_LEN;
+ (void) toto;
+ PNCMD_DBG (pbtTx[0]);
+ byte_t abtRx[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
+ size_t szRx = sizeof(abtRx);
// Check if receiving buffers are available, if not, replace them
if (!pszRx || !pbtRx) {
@@ -167,46 +142,40 @@ pn53x_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, b
pszRx = &szRx;
}
-#if defined(DEBUG)
- if(*pszRx > PN53x_EXTENDED_FRAME_MAX_LEN) {
- DBG( "Expected reply bytes count (*pszRx=%zu) is greater than MAX (PN53x_EXTENDED_FRAME_MAX_LEN=%d)", *pszRx, PN53x_EXTENDED_FRAME_MAX_LEN );
- *pszRx=MIN(*pszRx, PN53x_EXTENDED_FRAME_MAX_LEN);
-// abort();
- }
-#endif
-
- *pszRx += sizeof(pn53x_ack_frame) + PN53x_EXTENDED_FRAME_OVERHEAD;
-
- // Call the transceive callback function of the current device
- if (!pnd->pdc->transceive (pnd, pbtTx, szTx, pbtRx, pszRx))
+ // Call the send/receice callback functions of the current driver
+ if (!pnd->driver->send (pnd, pbtTx, szTx))
return false;
- // TODO Put all these hex-coded command behind a human-readable #define (1.6.x)
- // Should be proceed while we will fix Issue 110 (Rework the way that pn53x commands are built)
- switch (pbtTx[1]) {
- case 0x16: // PowerDown
- case 0x40: // InDataExchange
- case 0x42: // InCommunicateThru
- case 0x44: // InDeselect
- case 0x46: // InJumpForPSL
- case 0x4e: // InPSL
- case 0x50: // InATR
- case 0x52: // InRelease
- case 0x54: // InSelect
- case 0x56: // InJumpForDEP
- case 0x86: // TgGetData
- case 0x88: // TgGetInitiatorCommand
- case 0x8e: // TgSetData
- case 0x90: // TgResponseToInitiator
- case 0x92: // TgSetGeneralBytes
- case 0x94: // TgSetMetaData
+ int res = pnd->driver->receive (pnd, pbtRx, *pszRx);
+ if (res < 0) {
+ return false;
+ }
+
+ *pszRx = (size_t) res;
+
+ switch (pbtTx[0]) {
+ case PowerDown:
+ case InDataExchange:
+ case InCommunicateThru:
+ case InDeselect:
+ case InJumpForPSL:
+ case InPSL:
+ case InATR:
+ case InRelease:
+ case InSelect:
+ case InJumpForDEP:
+ case TgGetData:
+ case TgGetInitiatorCommand:
+ case TgSetData:
+ case TgResponseToInitiator:
+ case TgSetGeneralBytes:
+ case TgSetMetaData:
pnd->iLastError = pbtRx[0] & 0x3f;
break;
default:
pnd->iLastError = 0;
}
- if (pnd->nc == NC_PN533) {
- if ((pbtTx[1] == 0x06) // ReadRegister
- || (pbtTx[1] == 0x08)) { // WriteRegister
+ if (((struct pn53x_data*)(pnd->chip_data))->type == PN533) {
+ if ((pbtTx[0] == ReadRegister) || (pbtTx[0] == WriteRegister)) {
// PN533 prepends its answer by a status byte
pnd->iLastError = pbtRx[0] & 0x3f;
}
@@ -215,20 +184,16 @@ pn53x_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, b
}
bool
-pn53x_get_reg (nfc_device_t * pnd, uint16_t ui16Reg, uint8_t * ui8Value)
+pn53x_read_register (nfc_device_t * pnd, uint16_t ui16Reg, uint8_t * ui8Value)
{
- byte_t abtCmd[sizeof (pncmd_get_register)];
- memcpy (abtCmd, pncmd_get_register, sizeof (pncmd_get_register));
-
- abtCmd[2] = ui16Reg >> 8;
- abtCmd[3] = ui16Reg & 0xff;
+ byte_t abtCmd[] = { ReadRegister, ui16Reg >> 8, ui16Reg & 0xff };
byte_t abtRegValue[2];
- size_t szValueLen = 3 + PN53x_NORMAL_FRAME_OVERHEAD;
- if (pn53x_transceive (pnd, abtCmd, sizeof (pncmd_get_register), abtRegValue, &szValueLen)) {
- if (pnd->nc == NC_PN533) {
+ size_t szRegValue = sizeof (abtRegValue);
+ if (pn53x_transceive (pnd, abtCmd, sizeof (abtCmd), abtRegValue, &szRegValue, true)) {
+ if (((struct pn53x_data*)(pnd->chip_data))->type == PN533) {
// PN533 prepends its answer by a status byte
- if (abtRegValue[0] == 0) { // 0x00
+ if (abtRegValue[0] == 0x00) {
*ui8Value = abtRegValue[1];
} else {
return false;
@@ -242,27 +207,24 @@ pn53x_get_reg (nfc_device_t * pnd, uint16_t ui16Reg, uint8_t * ui8Value)
}
bool
-pn53x_set_reg (nfc_device_t * pnd, uint16_t ui16Reg, uint8_t ui8SymbolMask, uint8_t ui8Value)
+pn53x_write_register (nfc_device_t * pnd, const uint16_t ui16Reg, const uint8_t ui8SymbolMask, const uint8_t ui8Value)
{
uint8_t ui8Current;
- byte_t abtCmd[sizeof (pncmd_set_register)];
- memcpy (abtCmd, pncmd_set_register, sizeof (pncmd_set_register));
+ byte_t abtCmd[] = { WriteRegister, ui16Reg >> 8, ui16Reg & 0xff, 0x00 };
- abtCmd[2] = ui16Reg >> 8;
- abtCmd[3] = ui16Reg & 0xff;
if (ui8SymbolMask != 0xff) {
- if (!pn53x_get_reg (pnd, ui16Reg, &ui8Current))
+ if (!pn53x_read_register (pnd, ui16Reg, &ui8Current))
return false;
- abtCmd[4] = ui8Value | (ui8Current & (~ui8SymbolMask));
- return (abtCmd[4] != ui8Current) ? pn53x_transceive (pnd, abtCmd, sizeof (pncmd_set_register), NULL, NULL) : true;
+ abtCmd[3] = ui8Value | (ui8Current & (~ui8SymbolMask));
+ return (abtCmd[3] != ui8Current) ? pn53x_transceive (pnd, abtCmd, sizeof (abtCmd), NULL, NULL, false) : true;
} else {
- abtCmd[4] = ui8Value;
- return pn53x_transceive (pnd, abtCmd, sizeof (pncmd_set_register), NULL, NULL);
+ abtCmd[3] = ui8Value;
+ return pn53x_transceive (pnd, abtCmd, sizeof (abtCmd), NULL, NULL, false);
}
}
bool
-pn53x_set_parameter (nfc_device_t * pnd, const uint8_t ui8Parameter, const bool bEnable)
+pn53x_set_parameters (nfc_device_t * pnd, const uint8_t ui8Parameter, const bool bEnable)
{
uint8_t ui8Value = (bEnable) ? (pnd->ui8Parameters | ui8Parameter) : (pnd->ui8Parameters & ~(ui8Parameter));
if (ui8Value != pnd->ui8Parameters) {
@@ -274,11 +236,9 @@ pn53x_set_parameter (nfc_device_t * pnd, const uint8_t ui8Parameter, const bool
bool
pn53x_SetParameters (nfc_device_t * pnd, const uint8_t ui8Value)
{
- byte_t abtCmd[sizeof (pncmd_set_parameters)];
- memcpy (abtCmd, pncmd_set_parameters, sizeof (pncmd_set_parameters));
+ byte_t abtCmd[] = { SetParameters, ui8Value };
- abtCmd[2] = ui8Value;
- if(!pn53x_transceive (pnd, abtCmd, sizeof (pncmd_set_parameters), NULL, NULL)) {
+ if(!pn53x_transceive (pnd, abtCmd, sizeof (abtCmd), NULL, NULL, false)) {
return false;
}
// We save last parameters in register cache
@@ -292,7 +252,7 @@ pn53x_set_tx_bits (nfc_device_t * pnd, const uint8_t ui8Bits)
// Test if we need to update the transmission bits register setting
if (pnd->ui8TxBits != ui8Bits) {
// Set the amount of transmission bits in the PN53X chip register
- if (!pn53x_set_reg (pnd, REG_CIU_BIT_FRAMING, SYMBOL_TX_LAST_BITS, ui8Bits))
+ if (!pn53x_write_register (pnd, REG_CIU_BIT_FRAMING, SYMBOL_TX_LAST_BITS, ui8Bits))
return false;
// Store the new setting
@@ -405,7 +365,7 @@ pn53x_unwrap_frame (const byte_t * pbtFrame, const size_t szFrameBits, byte_t *
}
bool
-pn53x_decode_target_data (const byte_t * pbtRawData, size_t szRawData, nfc_chip_t nc, nfc_modulation_type_t nmt,
+pn53x_decode_target_data (const byte_t * pbtRawData, size_t szRawData, pn53x_type type, nfc_modulation_type_t nmt,
nfc_target_info_t * pnti)
{
uint8_t szAttribRes;
@@ -416,7 +376,7 @@ pn53x_decode_target_data (const byte_t * pbtRawData, size_t szRawData, nfc_chip_
pbtRawData++;
// Somehow they switched the lower and upper ATQA bytes around for the PN531 chipset
- if (nc == NC_PN531) {
+ if (type == PN531) {
pnti->nai.abtAtqa[1] = *(pbtRawData++);
pnti->nai.abtAtqa[0] = *(pbtRawData++);
} else {
@@ -515,8 +475,8 @@ pn53x_initiator_select_passive_target (nfc_device_t * pnd,
const byte_t * pbtInitData, const size_t szInitData,
nfc_target_t * pnt)
{
- size_t szTargetsData;
- byte_t abtTargetsData[PN53x_EXTENDED_FRAME_MAX_LEN];
+ byte_t abtTargetsData[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
+ size_t szTargetsData = sizeof(abtTargetsData);
const pn53x_modulation_t pm = pn53x_nm_to_pm(nm);
if (PM_UNDEFINED == pm) {
@@ -534,7 +494,7 @@ pn53x_initiator_select_passive_target (nfc_device_t * pnd,
if (pnt) {
pnt->nm = nm;
// Fill the tag info struct with the values corresponding to this init modulation
- if (!pn53x_decode_target_data (abtTargetsData + 1, szTargetsData - 1, pnd->nc, nm.nmt, &(pnt->nti))) {
+ if (!pn53x_decode_target_data (abtTargetsData + 1, szTargetsData - 1, ((struct pn53x_data*)(pnd->chip_data))->type, nm.nmt, &(pnt->nti))) {
return false;
}
}
@@ -588,13 +548,11 @@ pn53x_InListPassiveTarget (nfc_device_t * pnd,
const byte_t * pbtInitiatorData, const size_t szInitiatorData,
byte_t * pbtTargetsData, size_t * pszTargetsData)
{
- size_t szRx;
- byte_t abtCmd[sizeof (pncmd_initiator_list_passive)];
- memcpy (abtCmd, pncmd_initiator_list_passive, sizeof (pncmd_initiator_list_passive));
+ byte_t abtCmd[15] = { InListPassiveTarget };
- abtCmd[2] = szMaxTargets; // MaxTg
+ abtCmd[1] = szMaxTargets; // MaxTg
- // XXX Is there is a better way to do handle supported modulations ?
+ // XXX Is there a better way to do handle supported modulations ?
switch(pmInitModulation) {
case PM_ISO14443A_106:
case PM_FELICA_212:
@@ -609,7 +567,7 @@ pn53x_InListPassiveTarget (nfc_device_t * pnd,
}
break;
case PM_JEWEL_106:
- if(pnd->nc == NC_PN531) {
+ if(((struct pn53x_data*)(pnd->chip_data))->type == PN531) {
// These modulations are not supported by pn531
pnd->iLastError = DENOTSUP;
return false;
@@ -618,7 +576,7 @@ pn53x_InListPassiveTarget (nfc_device_t * pnd,
case PM_ISO14443B_212:
case PM_ISO14443B_424:
case PM_ISO14443B_847:
- if((pnd->nc != NC_PN533) || (!(pnd->btSupportByte & SUPPORT_ISO14443B))) {
+ if((((struct pn53x_data*)(pnd->chip_data))->type != PN533) || (!(pnd->btSupportByte & SUPPORT_ISO14443B))) {
// These modulations are not supported by pn531 neither pn532
pnd->iLastError = DENOTSUP;
return false;
@@ -628,40 +586,50 @@ pn53x_InListPassiveTarget (nfc_device_t * pnd,
pnd->iLastError = DENOTSUP;
return false;
}
- abtCmd[3] = pmInitModulation; // BrTy, the type of init modulation used for polling a passive tag
+ abtCmd[2] = pmInitModulation; // BrTy, the type of init modulation used for polling a passive tag
// Set the optional initiator data (used for Felica, ISO14443B, Topaz Polling or for ISO14443A selecting a specific UID).
if (pbtInitiatorData)
- memcpy (abtCmd + 4, pbtInitiatorData, szInitiatorData);
+ memcpy (abtCmd + 3, pbtInitiatorData, szInitiatorData);
- // Try to find a tag, call the tranceive callback function of the current device
- szRx = PN53x_EXTENDED_FRAME_MAX_LEN;
- if (pn53x_transceive (pnd, abtCmd, 4 + szInitiatorData, pbtTargetsData, &szRx)) {
- *pszTargetsData = szRx;
- return true;
- } else {
- return false;
- }
+ return pn53x_transceive (pnd, abtCmd, 3 + szInitiatorData, pbtTargetsData, pszTargetsData, false);
}
bool
pn53x_InDeselect (nfc_device_t * pnd, const uint8_t ui8Target)
{
- byte_t abtCmd[sizeof (pncmd_initiator_deselect)];
- memcpy (abtCmd, pncmd_initiator_deselect, sizeof (pncmd_initiator_deselect));
- abtCmd[2] = ui8Target;
+ byte_t abtCmd[] = { InDeselect, ui8Target };
- return (pn53x_transceive (pnd, abtCmd, sizeof (abtCmd), NULL, NULL));
+ return (pn53x_transceive (pnd, abtCmd, sizeof (abtCmd), NULL, NULL, false));
+}
+
+bool
+pn53x_SAMConfiguration (nfc_device_t * pnd, const uint8_t ui8Mode)
+{
+ byte_t abtCmd[] = { SAMConfiguration, ui8Mode, 0x00, 0x00 };
+ size_t szCmd = sizeof(abtCmd);
+ switch (ui8Mode) {
+ case 0x01: // Normal mode
+ szCmd = 2;
+ break;
+ case 0x02: // Virtual card mode
+ case 0x03: // Wired card mode
+ case 0x04: // Dual card mode
+ // TODO: Handle these SAM mode
+ break;
+ default:
+ pnd->iLastError = DENOTSUP;
+ return false;
+ }
+ return (pn53x_transceive (pnd, abtCmd, sizeof (abtCmd), NULL, NULL, false));
}
bool
pn53x_InRelease (nfc_device_t * pnd, const uint8_t ui8Target)
{
- byte_t abtCmd[sizeof (pncmd_initiator_release)];
- memcpy (abtCmd, pncmd_initiator_release, sizeof (pncmd_initiator_release));
- abtCmd[2] = ui8Target;
+ byte_t abtCmd[] = { InRelease, ui8Target };
- return (pn53x_transceive (pnd, abtCmd, sizeof (abtCmd), NULL, NULL));
+ return (pn53x_transceive (pnd, abtCmd, sizeof (abtCmd), NULL, NULL, false));
}
bool
@@ -669,31 +637,22 @@ pn53x_InAutoPoll (nfc_device_t * pnd,
const pn53x_target_type_t * ppttTargetTypes, const size_t szTargetTypes,
const byte_t btPollNr, const byte_t btPeriod, nfc_target_t * pntTargets, size_t * pszTargetFound)
{
- size_t szTxInAutoPoll,
- n;
- byte_t abtRx[PN53x_EXTENDED_FRAME_MAX_LEN];
- size_t szRx = PN53x_EXTENDED_FRAME_MAX_LEN;
- bool res;
- byte_t *pbtTxInAutoPoll;
-
- if (pnd->nc != NC_PN532) {
+ if (((struct pn53x_data*)(pnd->chip_data))->type != PN532) {
// This function is not supported by pn531 neither pn533
pnd->iLastError = DENOTSUP;
return false;
}
+
// InAutoPoll frame looks like this { 0xd4, 0x60, 0x0f, 0x01, 0x00 } => { direction, command, pollnr, period, types... }
- szTxInAutoPoll = 4 + szTargetTypes;
- pbtTxInAutoPoll = malloc (szTxInAutoPoll);
- pbtTxInAutoPoll[0] = 0xd4;
- pbtTxInAutoPoll[1] = 0x60;
- pbtTxInAutoPoll[2] = btPollNr;
- pbtTxInAutoPoll[3] = btPeriod;
- for (n = 0; n < szTargetTypes; n++) {
- pbtTxInAutoPoll[4 + n] = ppttTargetTypes[n];
+ size_t szTxInAutoPoll = 3 + szTargetTypes;
+ byte_t abtCmd[3+15] = { InAutoPoll, btPollNr, btPeriod };
+ for (size_t n = 0; n < szTargetTypes; n++) {
+ abtCmd[3 + n] = ppttTargetTypes[n];
}
- szRx = PN53x_EXTENDED_FRAME_MAX_LEN;
- res = pn53x_transceive (pnd, pbtTxInAutoPoll, szTxInAutoPoll, abtRx, &szRx);
+ byte_t abtRx[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
+ size_t szRx = sizeof(abtRx);
+ bool res = pn53x_transceive (pnd, abtCmd, szTxInAutoPoll, abtRx, &szRx, false);
if ((szRx == 0) || (res == false)) {
return false;
@@ -708,7 +667,7 @@ pn53x_InAutoPoll (nfc_device_t * pnd,
pntTargets[0].nm = pn53x_ptt_to_nm(ptt);
// AutoPollTargetData length
ln = *(pbt++);
- pn53x_decode_target_data (pbt, ln, pnd->nc, pntTargets[0].nm.nmt, &(pntTargets[0].nti));
+ pn53x_decode_target_data (pbt, ln, ((struct pn53x_data*)(pnd->chip_data))->type, pntTargets[0].nm.nmt, &(pntTargets[0].nti));
pbt += ln;
if (abtRx[0] > 1) {
@@ -718,7 +677,7 @@ pn53x_InAutoPoll (nfc_device_t * pnd,
pntTargets[1].nm = pn53x_ptt_to_nm(ptt);
// AutoPollTargetData length
ln = *(pbt++);
- pn53x_decode_target_data (pbt, ln, pnd->nc, pntTargets[1].nm.nmt, &(pntTargets[1].nti));
+ pn53x_decode_target_data (pbt, ln, ((struct pn53x_data*)(pnd->chip_data))->type, pntTargets[1].nm.nmt, &(pntTargets[1].nti));
}
}
}
@@ -797,30 +756,30 @@ pn53x_strerror (const nfc_device_t * pnd)
bool
pn53x_get_firmware_version (nfc_device_t * pnd, char abtFirmwareText[18])
{
+ const byte_t abtCmd[] = { GetFirmwareVersion };
byte_t abtFw[4];
size_t szFwLen = sizeof (abtFw);
- if (!pn53x_transceive (pnd, pncmd_get_firmware_version, 2, abtFw, &szFwLen)) {
+ if (!pn53x_transceive (pnd, abtCmd, sizeof (abtCmd), abtFw, &szFwLen, false)) {
// Failed to get firmware revision??, whatever...let's disconnect and clean up and return err
- pnd->pdc->disconnect (pnd);
+ // FIXME: Wtf?
+ // pnd->pdc->disconnect (pnd);
return false;
}
// Convert firmware info in text, PN531 gives 2 bytes info, but PN532 and PN533 gives 4
- switch (pnd->nc) {
- case NC_PN531:
+ switch (((struct pn53x_data*)(pnd->chip_data))->type) {
+ case PN531:
snprintf (abtFirmwareText, 18, "PN531 v%d.%d", abtFw[0], abtFw[1]);
pnd->btSupportByte = SUPPORT_ISO14443A | SUPPORT_ISO18092;
break;
- case NC_PN532:
+ case PN532:
snprintf (abtFirmwareText, 18, "PN532 v%d.%d (0x%02x)", abtFw[1], abtFw[2], abtFw[3]);
pnd->btSupportByte = abtFw[3];
break;
- case NC_PN533:
+ case PN533:
snprintf (abtFirmwareText, 18, "PN533 v%d.%d (0x%02x)", abtFw[1], abtFw[2], abtFw[3]);
pnd->btSupportByte = abtFw[3];
break;
}
- // Be sure to have a null end of string
- abtFirmwareText[17] = '\0';
return true;
}
@@ -828,22 +787,15 @@ bool
pn53x_configure (nfc_device_t * pnd, const nfc_device_option_t ndo, const bool bEnable)
{
byte_t btValue;
- byte_t abtCmd[sizeof (pncmd_rf_configure)];
-
- memcpy (abtCmd, pncmd_rf_configure, sizeof (pncmd_rf_configure));
-
- // Make sure we are dealing with a active device
- if (!pnd->bActive)
- return false;
switch (ndo) {
case NDO_HANDLE_CRC:
// Enable or disable automatic receiving/sending of CRC bytes
// TX and RX are both represented by the symbol 0x80
btValue = (bEnable) ? 0x80 : 0x00;
- if (!pn53x_set_reg (pnd, REG_CIU_TX_MODE, SYMBOL_TX_CRC_ENABLE, btValue))
+ if (!pn53x_write_register (pnd, REG_CIU_TX_MODE, SYMBOL_TX_CRC_ENABLE, btValue))
return false;
- if (!pn53x_set_reg (pnd, REG_CIU_RX_MODE, SYMBOL_RX_CRC_ENABLE, btValue))
+ if (!pn53x_write_register (pnd, REG_CIU_RX_MODE, SYMBOL_RX_CRC_ENABLE, btValue))
return false;
pnd->bCrc = bEnable;
break;
@@ -851,7 +803,7 @@ pn53x_configure (nfc_device_t * pnd, const nfc_device_option_t ndo, const bool b
case NDO_HANDLE_PARITY:
// Handle parity bit by PN53X chip or parse it as data bit
btValue = (bEnable) ? 0x00 : SYMBOL_PARITY_DISABLE;
- if (!pn53x_set_reg (pnd, REG_CIU_MANUAL_RCV, SYMBOL_PARITY_DISABLE, btValue))
+ if (!pn53x_write_register (pnd, REG_CIU_MANUAL_RCV, SYMBOL_PARITY_DISABLE, btValue))
return false;
pnd->bPar = bEnable;
break;
@@ -861,41 +813,47 @@ pn53x_configure (nfc_device_t * pnd, const nfc_device_option_t ndo, const bool b
break;
case NDO_ACTIVATE_FIELD:
- abtCmd[2] = RFCI_FIELD;
- abtCmd[3] = (bEnable) ? 1 : 0;
- if (!pn53x_transceive (pnd, abtCmd, 4, NULL, NULL))
- return false;
+ {
+ byte_t abtCmd[] = { RFConfiguration, RFCI_FIELD, (bEnable) ? 0x01 : 0x00 };
+ if (!pn53x_transceive (pnd, abtCmd, sizeof (abtCmd), NULL, NULL, false))
+ return false;
+ }
break;
case NDO_ACTIVATE_CRYPTO1:
btValue = (bEnable) ? SYMBOL_MF_CRYPTO1_ON : 0x00;
- if (!pn53x_set_reg (pnd, REG_CIU_STATUS2, SYMBOL_MF_CRYPTO1_ON, btValue))
+ if (!pn53x_write_register (pnd, REG_CIU_STATUS2, SYMBOL_MF_CRYPTO1_ON, btValue))
return false;
break;
case NDO_INFINITE_SELECT:
- // TODO Made some research around this point:
- // timings could be tweak better than this, and maybe we can tweak timings
- // to "gain" a sort-of hardware polling (ie. like PN532 does)
-
- // Retry format: 0x00 means only 1 try, 0xff means infinite
- abtCmd[2] = RFCI_RETRY_SELECT;
- abtCmd[3] = (bEnable) ? 0xff : 0x00; // MxRtyATR, default: active = 0xff, passive = 0x02
- abtCmd[4] = (bEnable) ? 0xff : 0x00; // MxRtyPSL, default: 0x01
- abtCmd[5] = (bEnable) ? 0xff : 0x00; // MxRtyPassiveActivation, default: 0xff
- if (!pn53x_transceive (pnd, abtCmd, 6, NULL, NULL))
- return false;
+ {
+ // TODO Made some research around this point:
+ // timings could be tweak better than this, and maybe we can tweak timings
+ // to "gain" a sort-of hardware polling (ie. like PN532 does)
+
+ // Retry format: 0x00 means only 1 try, 0xff means infinite
+ byte_t abtCmd[] = {
+ RFConfiguration,
+ RFCI_RETRY_SELECT,
+ (bEnable) ? 0xff : 0x00, // MxRtyATR, default: active = 0xff, passive = 0x02
+ (bEnable) ? 0xff : 0x00, // MxRtyPSL, default: 0x01
+ (bEnable) ? 0xff : 0x00 // MxRtyPassiveActivation, default: 0xff
+ };
+ if (!pn53x_transceive (pnd, abtCmd, sizeof (abtCmd), NULL, NULL, false))
+ return false;
+ }
break;
case NDO_ACCEPT_INVALID_FRAMES:
btValue = (bEnable) ? SYMBOL_RX_NO_ERROR : 0x00;
- if (!pn53x_set_reg (pnd, REG_CIU_RX_MODE, SYMBOL_RX_NO_ERROR, btValue))
+ if (!pn53x_write_register (pnd, REG_CIU_RX_MODE, SYMBOL_RX_NO_ERROR, btValue))
return false;
break;
case NDO_ACCEPT_MULTIPLE_FRAMES:
btValue = (bEnable) ? SYMBOL_RX_MULTIPLE : 0x00;
- if (!pn53x_set_reg (pnd, REG_CIU_RX_MODE, SYMBOL_RX_MULTIPLE, btValue))
+ if (!pn53x_write_register (pnd, REG_CIU_RX_MODE, SYMBOL_RX_MULTIPLE, btValue))
return false;
return true;
break;
@@ -903,7 +861,7 @@ pn53x_configure (nfc_device_t * pnd, const nfc_device_option_t ndo, const bool b
case NDO_AUTO_ISO14443_4:
// TODO Cache activated/disactivated options
pnd->bAutoIso14443_4 = bEnable;
- return pn53x_set_parameter(pnd, PARAM_AUTO_RATS, bEnable);
+ return pn53x_set_parameters (pnd, PARAM_AUTO_RATS, bEnable);
break;
case NDO_FORCE_ISO14443_A:
@@ -912,10 +870,10 @@ pn53x_configure (nfc_device_t * pnd, const nfc_device_option_t ndo, const bool b
return true;
}
// Force pn53x to be in ISO14443-A mode
- if (!pn53x_set_reg (pnd, REG_CIU_TX_MODE, SYMBOL_TX_FRAMING, 0x00)) {
+ if (!pn53x_write_register (pnd, REG_CIU_TX_MODE, SYMBOL_TX_FRAMING, 0x00)) {
return false;
}
- if (!pn53x_set_reg (pnd, REG_CIU_RX_MODE, SYMBOL_RX_FRAMING, 0x00)) {
+ if (!pn53x_write_register (pnd, REG_CIU_RX_MODE, SYMBOL_RX_FRAMING, 0x00)) {
return false;
}
return true;
@@ -932,7 +890,7 @@ pn53x_initiator_select_dep_target(nfc_device_t * pnd,
const nfc_dep_info_t * pndiInitiator,
nfc_target_t * pnt)
{
- const byte_t abtPassiveInitiatorData[5] = { 0x00, 0xff, 0xff, 0x00, 0x00 }; // Only for 212/424 kpbs: First 4 bytes shall be set like this according to NFCIP-1, last byte is TSN (Time Slot Number)
+ const byte_t abtPassiveInitiatorData[] = { 0x00, 0xff, 0xff, 0x00, 0x00 }; // Only for 212/424 kpbs: First 4 bytes shall be set like this according to NFCIP-1, last byte is TSN (Time Slot Number)
const byte_t * pbtPassiveInitiatorData = NULL;
switch (nbr) {
@@ -973,25 +931,19 @@ pn53x_InJumpForDEP (nfc_device_t * pnd,
const byte_t * pbtGBi, const size_t szGBi,
nfc_target_t * pnt)
{
- byte_t abtRx[PN53x_EXTENDED_FRAME_MAX_LEN];
- size_t szRx;
- size_t offset;
- byte_t abtCmd[sizeof (pncmd_initiator_jump_for_dep)];
+ byte_t abtCmd[PN53x_EXTENDED_FRAME__DATA_MAX_LEN] = { InJumpForDEP, (ndm == NDM_ACTIVE) ? 0x01 : 0x00 };
- memcpy (abtCmd, pncmd_initiator_jump_for_dep, sizeof (pncmd_initiator_jump_for_dep));
-
- offset = 5; // 2 bytes for command, 1 byte for DEP mode (Active/Passive), 1 byte for baud rate, 1 byte for following parameters flag
- abtCmd[2] = (ndm == NDM_ACTIVE) ? 0x01 : 0x00;
+ size_t offset = 4; // 1 byte for command, 1 byte for DEP mode (Active/Passive), 1 byte for baud rate, 1 byte for following parameters flag
switch (nbr) {
case NBR_106:
- abtCmd[3] = 0x00; // baud rate is 106 kbps
+ abtCmd[2] = 0x00; // baud rate is 106 kbps
break;
case NBR_212:
- abtCmd[3] = 0x01; // baud rate is 212 kbps
+ abtCmd[2] = 0x01; // baud rate is 212 kbps
break;
case NBR_424:
- abtCmd[3] = 0x02; // baud rate is 424 kbps
+ abtCmd[2] = 0x02; // baud rate is 424 kbps
break;
case NBR_847:
case NBR_UNDEFINED:
@@ -1004,13 +956,13 @@ pn53x_InJumpForDEP (nfc_device_t * pnd,
if (pbtPassiveInitiatorData && (ndm == NDM_PASSIVE)) { /* can't have passive initiator data when using active mode */
switch (nbr) {
case NBR_106:
- abtCmd[4] |= 0x01;
+ abtCmd[3] |= 0x01;
memcpy (abtCmd + offset, pbtPassiveInitiatorData, 4);
offset += 4;
break;
case NBR_212:
case NBR_424:
- abtCmd[4] |= 0x01;
+ abtCmd[3] |= 0x01;
memcpy (abtCmd + offset, pbtPassiveInitiatorData, 5);
offset += 5;
break;
@@ -1024,18 +976,21 @@ pn53x_InJumpForDEP (nfc_device_t * pnd,
}
if (pbtNFCID3i) {
- abtCmd[4] |= 0x02;
+ abtCmd[3] |= 0x02;
memcpy (abtCmd + offset, pbtNFCID3i, 10);
offset += 10;
}
if (szGBi && pbtGBi) {
- abtCmd[4] |= 0x04;
+ abtCmd[3] |= 0x04;
memcpy (abtCmd + offset, pbtGBi, szGBi);
offset += szGBi;
}
+
+ byte_t abtRx[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
+ size_t szRx = sizeof (abtRx);
// Try to find a target, call the transceive callback function of the current device
- if (!pn53x_transceive (pnd, abtCmd, offset, abtRx, &szRx))
+ if (!pn53x_transceive (pnd, abtCmd, offset, abtRx, &szRx, false))
return false;
// Make sure one target has been found, the PN53X returns 0x00 if none was available
@@ -1066,20 +1021,16 @@ bool
pn53x_initiator_transceive_bits (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxBits,
const byte_t * pbtTxPar, byte_t * pbtRx, size_t * pszRxBits, byte_t * pbtRxPar)
{
- byte_t abtRx[PN53x_EXTENDED_FRAME_MAX_LEN];
- size_t szRx = PN53x_EXTENDED_FRAME_MAX_LEN;
size_t szFrameBits = 0;
size_t szFrameBytes = 0;
uint8_t ui8rcc;
uint8_t ui8Bits = 0;
- byte_t abtCmd[sizeof (pncmd_initiator_exchange_raw_data)];
-
- memcpy (abtCmd, pncmd_initiator_exchange_raw_data, sizeof (pncmd_initiator_exchange_raw_data));
+ byte_t abtCmd[PN53x_EXTENDED_FRAME__DATA_MAX_LEN] = { InCommunicateThru };
// Check if we should prepare the parity bits ourself
if (!pnd->bPar) {
// Convert data with parity to a frame
- pn53x_wrap_frame (pbtTx, szTxBits, pbtTxPar, abtCmd + 2, &szFrameBits);
+ pn53x_wrap_frame (pbtTx, szTxBits, pbtTxPar, abtCmd + 1, &szFrameBits);
} else {
szFrameBits = szTxBits;
}
@@ -1092,19 +1043,21 @@ pn53x_initiator_transceive_bits (nfc_device_t * pnd, const byte_t * pbtTx, const
// When the parity is handled before us, we just copy the data
if (pnd->bPar)
- memcpy (abtCmd + 2, pbtTx, szFrameBytes);
+ memcpy (abtCmd + 1, pbtTx, szFrameBytes);
// Set the amount of transmission bits in the PN53X chip register
if (!pn53x_set_tx_bits (pnd, ui8Bits))
return false;
// Send the frame to the PN53X chip and get the answer
- // We have to give the amount of bytes + (the two command bytes 0xD4, 0x42)
- if (!pn53x_transceive (pnd, abtCmd, szFrameBytes + 2, abtRx, &szRx))
+ // We have to give the amount of bytes + (the command byte 0x42)
+ byte_t abtRx[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
+ size_t szRx = sizeof(abtRx);
+ if (!pn53x_transceive (pnd, abtCmd, szFrameBytes + 1, abtRx, &szRx, false))
return false;
// Get the last bit-count that is stored in the received byte
- if (!pn53x_get_reg (pnd, REG_CIU_CONTROL, &ui8rcc))
+ if (!pn53x_read_register (pnd, REG_CIU_CONTROL, &ui8rcc))
return false;
ui8Bits = ui8rcc & SYMBOL_RX_LAST_BITS;
@@ -1131,10 +1084,8 @@ bool
pn53x_initiator_transceive_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx,
size_t * pszRx)
{
- byte_t abtRx[PN53x_EXTENDED_FRAME_MAX_LEN];
- size_t szRx = PN53x_EXTENDED_FRAME_MAX_LEN;
size_t szExtraTxLen;
- byte_t abtCmd[sizeof (pncmd_initiator_exchange_raw_data)];
+ byte_t abtCmd[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
// We can not just send bytes without parity if while the PN53X expects we handled them
if (!pnd->bPar)
@@ -1142,14 +1093,14 @@ pn53x_initiator_transceive_bytes (nfc_device_t * pnd, const byte_t * pbtTx, cons
// Copy the data into the command frame
if (pnd->bEasyFraming) {
- memcpy (abtCmd, pncmd_initiator_exchange_data, sizeof (pncmd_initiator_exchange_data));
- abtCmd[2] = 1; /* target number */
- memcpy (abtCmd + 3, pbtTx, szTx);
- szExtraTxLen = 3;
- } else {
- memcpy (abtCmd, pncmd_initiator_exchange_raw_data, sizeof (pncmd_initiator_exchange_raw_data));
+ abtCmd[0] = InDataExchange;
+ abtCmd[1] = 1; /* target number */
memcpy (abtCmd + 2, pbtTx, szTx);
szExtraTxLen = 2;
+ } else {
+ abtCmd[0] = InCommunicateThru;
+ memcpy (abtCmd + 1, pbtTx, szTx);
+ szExtraTxLen = 1;
}
// To transfer command frames bytes we can not have any leading bits, reset this to zero
@@ -1158,7 +1109,9 @@ pn53x_initiator_transceive_bytes (nfc_device_t * pnd, const byte_t * pbtTx, cons
// Send the frame to the PN53X chip and get the answer
// We have to give the amount of bytes + (the two command bytes 0xD4, 0x42)
- if (!pn53x_transceive (pnd, abtCmd, szTx + szExtraTxLen, abtRx, &szRx))
+ byte_t abtRx[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
+ size_t szRx = sizeof(abtRx);
+ if (!pn53x_transceive (pnd, abtCmd, szTx + szExtraTxLen, abtRx, &szRx, false))
return false;
// Save the received byte count
@@ -1187,14 +1140,14 @@ pn53x_target_init (nfc_device_t * pnd, nfc_target_t * pnt, byte_t * pbtRx, size_
pnd->iLastError = ETGUIDNOTSUP;
return false;
}
- pn53x_set_parameter(pnd, PARAM_AUTO_ATR_RES, false);
- if (pnd->nc == NC_PN532) { // We have a PN532
+ pn53x_set_parameters (pnd, PARAM_AUTO_ATR_RES, false);
+ if (((struct pn53x_data*)(pnd->chip_data))->type == PN532) { // We have a PN532
if ((pnt->nti.nai.btSak & SAK_ISO14443_4_COMPLIANT) && (pnd->bAutoIso14443_4)) {
// We have a ISO14443-4 tag to emulate and NDO_AUTO_14443_4A option is enabled
ptm |= PTM_ISO14443_4_PICC_ONLY; // We add ISO14443-4 restriction
- pn53x_set_parameter(pnd, PARAM_14443_4_PICC, true);
+ pn53x_set_parameters (pnd, PARAM_14443_4_PICC, true);
} else {
- pn53x_set_parameter(pnd, PARAM_14443_4_PICC, false);
+ pn53x_set_parameters (pnd, PARAM_14443_4_PICC, false);
}
}
break;
@@ -1202,7 +1155,7 @@ pn53x_target_init (nfc_device_t * pnd, nfc_target_t * pnt, byte_t * pbtRx, size_
ptm = PTM_PASSIVE_ONLY;
break;
case NMT_DEP:
- pn53x_set_parameter(pnd, PARAM_AUTO_ATR_RES, true);
+ pn53x_set_parameters (pnd, PARAM_AUTO_ATR_RES, true);
ptm = PTM_DEP_ONLY;
if (pnt->nti.ndi.ndm == NDM_PASSIVE) {
ptm |= PTM_PASSIVE_ONLY; // We add passive mode restriction
@@ -1217,12 +1170,12 @@ pn53x_target_init (nfc_device_t * pnd, nfc_target_t * pnt, byte_t * pbtRx, size_
// Make sure the CRC & parity are handled by the device, this is needed for target_init to work properly
if (!bCrc)
- pn53x_configure ((nfc_device_t *) pnd, NDO_HANDLE_CRC, true);
+ pn53x_configure (pnd, NDO_HANDLE_CRC, true);
if (!bPar)
- pn53x_configure ((nfc_device_t *) pnd, NDO_HANDLE_PARITY, true);
+ pn53x_configure (pnd, NDO_HANDLE_PARITY, true);
// Let the PN53X be activated by the RF level detector from power down mode
- if (!pn53x_set_reg (pnd, REG_CIU_TX_AUTO, SYMBOL_INITIAL_RF_ON, 0x04))
+ if (!pn53x_write_register (pnd, REG_CIU_TX_AUTO, SYMBOL_INITIAL_RF_ON, 0x04))
return false;
byte_t abtMifareParams[6];
@@ -1283,16 +1236,17 @@ pn53x_target_init (nfc_device_t * pnd, nfc_target_t * pnt, byte_t * pbtRx, size_
bool targetActivated = false;
while (!targetActivated) {
- nfc_modulation_t nm;
- nfc_dep_mode_t ndm = NDM_UNDEFINED;
byte_t btActivatedMode;
- nm.nbr = NBR_UNDEFINED;
-
if(!pn53x_TgInitAsTarget(pnd, ptm, pbtMifareParams, pbtTkt, szTkt, pbtFeliCaParams, pbtNFCID3t, pbtGBt, szGBt, pbtRx, pszRx, &btActivatedMode)) {
return false;
}
+ nfc_modulation_t nm = {
+ .nmt = NMT_DEP, // Silent compilation warnings
+ .nbr = NBR_UNDEFINED
+ };
+ nfc_dep_mode_t ndm = NDM_UNDEFINED;
// Decode activated "mode"
switch(btActivatedMode & 0x70) { // Baud rate
case 0x00: // 106kbps
@@ -1354,57 +1308,53 @@ pn53x_TgInitAsTarget (nfc_device_t * pnd, pn53x_target_mode_t ptm,
const byte_t * pbtNFCID3t, const byte_t * pbtGBt, const size_t szGBt,
byte_t * pbtRx, size_t * pszRx, byte_t * pbtModeByte)
{
- byte_t abtRx[PN53x_EXTENDED_FRAME_MAX_LEN];
- size_t szRx;
- byte_t abtCmd[39 + 47 + 48]; // Worst case: 39-byte base, 47 bytes max. for General Bytes, 48 bytes max. for Historical Bytes
+ byte_t abtCmd[39 + 47 + 48] = { TgInitAsTarget }; // Worst case: 39-byte base, 47 bytes max. for General Bytes, 48 bytes max. for Historical Bytes
size_t szOptionalBytes = 0;
- memcpy (abtCmd, pncmd_target_init, sizeof (pncmd_target_init));
-
// Clear the target init struct, reset to all zeros
- memset (abtCmd + sizeof (pncmd_target_init), 0x00, sizeof (abtCmd) - sizeof (pncmd_target_init));
+ memset (abtCmd + 1, 0x00, sizeof (abtCmd) - 1);
// Store the target mode in the initialization params
- abtCmd[2] = ptm;
+ abtCmd[1] = ptm;
// MIFARE part
if (pbtMifareParams) {
- memcpy (abtCmd+3, pbtMifareParams, 6);
+ memcpy (abtCmd+2, pbtMifareParams, 6);
}
// FeliCa part
if (pbtFeliCaParams) {
- memcpy (abtCmd+9, pbtFeliCaParams, 18);
+ memcpy (abtCmd+8, pbtFeliCaParams, 18);
}
// DEP part
if (pbtNFCID3t) {
- memcpy(abtCmd+27, pbtNFCID3t, 10);
+ memcpy(abtCmd+26, pbtNFCID3t, 10);
}
// General Bytes (ISO/IEC 18092)
- if (pnd->nc == NC_PN531) {
+ if (((struct pn53x_data*)(pnd->chip_data))->type == PN531) {
if (szGBt) {
- memcpy (abtCmd+37, pbtGBt, szGBt);
+ memcpy (abtCmd+36, pbtGBt, szGBt);
szOptionalBytes = szGBt;
}
} else {
- abtCmd[37] = (byte_t)(szGBt);
+ abtCmd[36] = (byte_t)(szGBt);
if (szGBt) {
- memcpy (abtCmd+38, pbtGBt, szGBt);
+ memcpy (abtCmd+37, pbtGBt, szGBt);
}
szOptionalBytes = szGBt + 1;
}
// Historical bytes (ISO/IEC 14443-4)
- if (pnd->nc != NC_PN531) { // PN531 does not handle Historical Bytes
- abtCmd[37+szOptionalBytes] = (byte_t)(szTkt);
+ if (((struct pn53x_data*)(pnd->chip_data))->type != PN531) { // PN531 does not handle Historical Bytes
+ abtCmd[36+szOptionalBytes] = (byte_t)(szTkt);
if (szTkt) {
- memcpy (abtCmd+38+szOptionalBytes, pbtTkt, szTkt);
+ memcpy (abtCmd+37+szOptionalBytes, pbtTkt, szTkt);
}
szOptionalBytes += szTkt + 1;
}
// Request the initialization as a target
- szRx = PN53x_EXTENDED_FRAME_MAX_LEN;
-
- if (!pn53x_transceive (pnd, abtCmd, 37 + szOptionalBytes, abtRx, &szRx))
+ byte_t abtRx[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
+ size_t szRx = sizeof (abtRx);
+ if (!pn53x_transceive (pnd, abtCmd, 36 + szOptionalBytes, abtRx, &szRx, false))
return false;
// Note: the first byte is skip:
@@ -1424,23 +1374,22 @@ pn53x_TgInitAsTarget (nfc_device_t * pnd, pn53x_target_mode_t ptm,
bool
pn53x_target_receive_bits (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBits, byte_t * pbtRxPar)
{
- byte_t abtRx[PN53x_EXTENDED_FRAME_MAX_LEN];
- size_t szRx;
- size_t szFrameBits;
- uint8_t ui8rcc;
- uint8_t ui8Bits;
+ byte_t abtCmd[] = { TgGetInitiatorCommand };
+ byte_t abtRx[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
+ size_t szRx = sizeof (abtRx);
// Try to gather a received frame from the reader
- if (!pn53x_transceive (pnd, pncmd_target_get_initiator_command, 2, abtRx, &szRx))
+ if (!pn53x_transceive (pnd, abtCmd, sizeof (abtCmd), abtRx, &szRx, false))
return false;
// Get the last bit-count that is stored in the received byte
- if (!pn53x_get_reg (pnd, REG_CIU_CONTROL, &ui8rcc))
+ uint8_t ui8rcc;
+ if (!pn53x_read_register (pnd, REG_CIU_CONTROL, &ui8rcc))
return false;
- ui8Bits = ui8rcc & SYMBOL_RX_LAST_BITS;
+ uint8_t ui8Bits = ui8rcc & SYMBOL_RX_LAST_BITS;
// Recover the real frame length in bits
- szFrameBits = ((szRx - 1 - ((ui8Bits == 0) ? 0 : 1)) * 8) + ui8Bits;
+ size_t szFrameBits = ((szRx - 1 - ((ui8Bits == 0) ? 0 : 1)) * 8) + ui8Bits;
// Ignore the status byte from the PN53X here, it was checked earlier in pn53x_transceive()
// Check if we should recover the parity bits ourself
@@ -1460,18 +1409,18 @@ pn53x_target_receive_bits (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBit
bool
pn53x_target_receive_bytes (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRx)
{
- byte_t const *pbtTx;
- byte_t abtRx[PN53x_EXTENDED_FRAME_MAX_LEN];
- size_t szRx;
+ byte_t abtCmd[1];
if (pnd->bEasyFraming) {
- pbtTx = pncmd_target_get_data;
+ abtCmd[0] = TgGetData;
} else {
- pbtTx = pncmd_target_get_initiator_command;
+ abtCmd[0] = TgGetInitiatorCommand;
}
// Try to gather a received frame from the reader
- if (!pn53x_transceive (pnd, pbtTx, 2, abtRx, &szRx))
+ byte_t abtRx[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
+ size_t szRx = sizeof (abtRx);
+ if (!pn53x_transceive (pnd, abtCmd, sizeof (abtCmd), abtRx, &szRx, false))
return false;
// Save the received byte count
@@ -1490,14 +1439,12 @@ pn53x_target_send_bits (nfc_device_t * pnd, const byte_t * pbtTx, const size_t s
size_t szFrameBits = 0;
size_t szFrameBytes = 0;
uint8_t ui8Bits = 0;
- byte_t abtCmd[sizeof (pncmd_target_response_to_initiator)];
-
- memcpy (abtCmd, pncmd_target_response_to_initiator, sizeof (pncmd_target_response_to_initiator));
+ byte_t abtCmd[PN53x_EXTENDED_FRAME__DATA_MAX_LEN] = { TgResponseToInitiator };
// Check if we should prepare the parity bits ourself
if (!pnd->bPar) {
// Convert data with parity to a frame
- pn53x_wrap_frame (pbtTx, szTxBits, pbtTxPar, abtCmd + 2, &szFrameBits);
+ pn53x_wrap_frame (pbtTx, szTxBits, pbtTxPar, abtCmd + 1, &szFrameBits);
} else {
szFrameBits = szTxBits;
}
@@ -1510,14 +1457,14 @@ pn53x_target_send_bits (nfc_device_t * pnd, const byte_t * pbtTx, const size_t s
// When the parity is handled before us, we just copy the data
if (pnd->bPar)
- memcpy (abtCmd + 2, pbtTx, szFrameBytes);
+ memcpy (abtCmd + 1, pbtTx, szFrameBytes);
// Set the amount of transmission bits in the PN53X chip register
if (!pn53x_set_tx_bits (pnd, ui8Bits))
return false;
// Try to send the bits to the reader
- if (!pn53x_transceive (pnd, abtCmd, szFrameBytes + 2, NULL, NULL))
+ if (!pn53x_transceive (pnd, abtCmd, szFrameBytes + 1, NULL, NULL, false))
return false;
// Everyting seems ok, return true
@@ -1527,31 +1474,30 @@ pn53x_target_send_bits (nfc_device_t * pnd, const byte_t * pbtTx, const size_t s
bool
pn53x_target_send_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx)
{
- byte_t abtCmd[MAX (sizeof (pncmd_target_response_to_initiator), sizeof (pncmd_target_set_data))];
-
+ byte_t abtCmd[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
// We can not just send bytes without parity if while the PN53X expects we handled them
if (!pnd->bPar)
return false;
if (pnd->bEasyFraming) {
- memcpy (abtCmd, pncmd_target_set_data, sizeof (pncmd_target_set_data));
+ abtCmd[0] = TgSetData;
} else {
- memcpy (abtCmd, pncmd_target_response_to_initiator, sizeof (pncmd_target_response_to_initiator));
+ abtCmd[0] = TgResponseToInitiator;
}
// Copy the data into the command frame
- memcpy (abtCmd + 2, pbtTx, szTx);
+ memcpy (abtCmd + 1, pbtTx, szTx);
// Try to send the bits to the reader
- if (!pn53x_transceive (pnd, abtCmd, szTx + 2, NULL, NULL))
+ if (!pn53x_transceive (pnd, abtCmd, szTx + 1, NULL, NULL, false))
return false;
// Everyting seems ok, return true
return true;
}
-const pn53x_modulation_t
+pn53x_modulation_t
pn53x_nm_to_pm(const nfc_modulation_t nm)
{
switch(nm.nmt) {
@@ -1605,7 +1551,7 @@ pn53x_nm_to_pm(const nfc_modulation_t nm)
return PM_UNDEFINED;
}
-const nfc_modulation_t
+nfc_modulation_t
pn53x_ptt_to_nm( const pn53x_target_type_t ptt )
{
switch (ptt) {
@@ -1654,7 +1600,7 @@ pn53x_ptt_to_nm( const pn53x_target_type_t ptt )
return (const nfc_modulation_t){ .nmt = NMT_ISO14443A, .nbr = NBR_106 };
}
-const pn53x_target_type_t
+pn53x_target_type_t
pn53x_nm_to_ptt(const nfc_modulation_t nm)
{
switch(nm.nmt) {
diff --git a/libnfc/chips/pn53x.h b/libnfc/chips/pn53x.h
index 822c4bc..7352ad9 100644
--- a/libnfc/chips/pn53x.h
+++ b/libnfc/chips/pn53x.h
@@ -1,7 +1,9 @@
/*-
* Public platform independent Near Field Communication (NFC) library
*
- * Copyright (C) 2009, 2010, Roel Verdult, Romuald Conty
+ * Copyright (C) 2009, Roel Verdult, Romuald Conty
+ * Copyright (C) 2010, Roel Verdult, Romuald Conty, Romain Tartière
+ * Copyright (C) 2011, Romuald Conty, Romain Tartière
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
@@ -27,11 +29,6 @@
# include
-# define PN53x_NORMAL_FRAME_MAX_LEN 255
-# define PN53x_NORMAL_FRAME_OVERHEAD 7
-# define PN53x_EXTENDED_FRAME_MAX_LEN 264
-# define PN53x_EXTENDED_FRAME_OVERHEAD 10
-
// Registers and symbols masks used to covers parts within a register
# define REG_CIU_TX_MODE 0x6302
# define SYMBOL_TX_CRC_ENABLE 0x80
@@ -98,6 +95,24 @@
# define DEISERRFRAME 0x0300/* Error frame */
# define DENOTSUP 0x0400/* Not supported */
+typedef enum {
+ PN531 = 0x01,
+ PN532 = 0x02,
+ PN533 = 0x04
+} pn53x_type;
+
+typedef enum {
+ SLEEP = 0x00, // Need to be wake up to process commands
+ NORMAL = 0x01, // Ready to process command
+ EXECUTE = 0x02, // Need to cancel the running command to process new one
+} pn53x_state;
+
+struct pn53x_data {
+ pn53x_type type;
+ pn53x_state state;
+};
+
+
/* PN53x specific types */
/**
* @enum pn53x_modulation_t
@@ -185,18 +200,17 @@ bool pn53x_check_ack_frame_callback (nfc_device_t * pnd, const byte_t * pbtRx
const size_t szRxFrameLen);
bool pn53x_check_error_frame_callback (nfc_device_t * pnd, const byte_t * pbtRxFrame,
const size_t szRxFrameLen);
-bool pn53x_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx,
- size_t * pszRx);
-bool pn53x_get_reg (nfc_device_t * pnd, uint16_t ui16Reg, uint8_t * ui8Value);
-bool pn53x_set_reg (nfc_device_t * pnd, uint16_t ui16Reg, uint8_t ui8SymbolMask, uint8_t ui8Value);
-bool pn53x_set_parameter (nfc_device_t * pnd, const uint8_t ui8Value, const bool bEnable);
+bool pn53x_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx, size_t *pszRx, bool toto);
+bool pn53x_read_register (nfc_device_t * pnd, uint16_t ui16Reg, uint8_t * ui8Value);
+bool pn53x_write_register (nfc_device_t * pnd, uint16_t ui16Reg, uint8_t ui8SymbolMask, uint8_t ui8Value);
+bool pn53x_set_parameters (nfc_device_t * pnd, const uint8_t ui8Value, const bool bEnable);
bool pn53x_set_tx_bits (nfc_device_t * pnd, const uint8_t ui8Bits);
bool pn53x_wrap_frame (const byte_t * pbtTx, const size_t szTxBits, const byte_t * pbtTxPar, byte_t * pbtFrame,
size_t * pszFrameBits);
bool pn53x_unwrap_frame (const byte_t * pbtFrame, const size_t szFrameBits, byte_t * pbtRx, size_t * pszRxBits,
byte_t * pbtRxPar);
bool pn53x_decode_target_data (const byte_t * pbtRawData, size_t szRawData,
- nfc_chip_t nc, nfc_modulation_type_t nmt,
+ pn53x_type chip_type, nfc_modulation_type_t nmt,
nfc_target_info_t * pnti);
bool pn53x_get_firmware_version (nfc_device_t * pnd, char abtFirmwareText[18]);
bool pn53x_configure (nfc_device_t * pnd, const nfc_device_option_t ndo, const bool bEnable);
@@ -234,6 +248,7 @@ static const struct chip_callbacks pn53x_callbacks_list = {
// C wrappers for PN53x commands
bool pn53x_SetParameters (nfc_device_t * pnd, const uint8_t ui8Value);
+bool pn53x_SAMConfiguration (nfc_device_t * pnd, const uint8_t ui8Mode);
bool pn53x_InListPassiveTarget (nfc_device_t * pnd, const pn53x_modulation_t pmInitModulation,
const byte_t szMaxTargets, const byte_t * pbtInitiatorData,
const size_t szInitiatorDataLen, byte_t * pbtTargetsData, size_t * pszTargetsData);
diff --git a/libnfc/drivers.h b/libnfc/drivers.h
index 14c5891..7dccd74 100644
--- a/libnfc/drivers.h
+++ b/libnfc/drivers.h
@@ -2,6 +2,7 @@
* Public platform independent Near Field Communication (NFC) library
*
* Copyright (C) 2009, Roel Verdult
+ * Copyright (C) 2011, Romuald Conty, Romain Tartière
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
@@ -27,8 +28,6 @@
# include
-# include "chips/pn53x.h"
-
# if defined (DRIVER_ACR122_ENABLED)
# include "drivers/acr122.h"
# endif /* DRIVER_ACR122_ENABLED */
@@ -54,46 +53,7 @@
# endif /* DRIVER_PN532_UART_ENABLED */
# define DRIVERS_MAX_DEVICES 16
-# define MAX_FRAME_LEN 264
-static const struct driver_callbacks drivers_callbacks_list[] = {
-// Driver Name Chip callbacks Pick Device List Devices Connect Transceive Disconnect
-# if defined (DRIVER_PN531_USB_ENABLED)
- {PN531_USB_DRIVER_NAME, &pn53x_callbacks_list, pn531_usb_pick_device, pn531_usb_list_devices, pn531_usb_connect,
- NULL, pn53x_usb_transceive, pn53x_usb_disconnect},
-# endif /* DRIVER_PN531_USB_ENABLED */
-# if defined (DRIVER_PN533_USB_ENABLED)
- {PN533_USB_DRIVER_NAME, &pn53x_callbacks_list, pn533_usb_pick_device, pn533_usb_list_devices, pn533_usb_connect,
- pn533_usb_init, pn53x_usb_transceive, pn53x_usb_disconnect},
-# endif /* DRIVER_PN533_USB_ENABLED */
-# if defined (DRIVER_ACR122_ENABLED)
- {ACR122_DRIVER_NAME, &pn53x_callbacks_list, acr122_pick_device, acr122_list_devices, acr122_connect,
- NULL, acr122_transceive, acr122_disconnect},
-# endif /* DRIVER_ACR122_ENABLED */
-# if defined (DRIVER_ARYGON_ENABLED)
- {ARYGON_DRIVER_NAME, &pn53x_callbacks_list, arygon_pick_device, arygon_list_devices, arygon_connect,
- NULL, arygon_transceive, arygon_disconnect},
-# endif /* DRIVER_ARYGON_ENABLED */
-# if defined (DRIVER_PN532_UART_ENABLED)
- {PN532_UART_DRIVER_NAME, &pn53x_callbacks_list, pn532_uart_pick_device, pn532_uart_list_devices, pn532_uart_connect,
- NULL, pn532_uart_transceive, pn532_uart_disconnect},
-# endif /* DRIVER_PN532_UART_ENABLED */
-};
-
-# ifdef DEBUG
- /*
- * TODO Move this helper macro for dumping drivers messages.
- * Here is not the best place for such a macro, however, I
- * can't see any convenient place ATM.
- */
-# define PRINT_HEX(pcTag, pbtData, szBytes) do { \
- size_t __szPos; \
- printf(" %s: ", pcTag); \
- for (__szPos=0; __szPos < (size_t)(szBytes); __szPos++) { \
- printf("%02x ",pbtData[__szPos]); \
- } \
- printf("\n"); \
- } while (0);
-# endif
+extern const struct nfc_driver_t *nfc_drivers[];
#endif // __NFC_DRIVERS_H__
diff --git a/libnfc/drivers/arygon.c b/libnfc/drivers/arygon.c
index 7bdc974..eb868df 100644
--- a/libnfc/drivers/arygon.c
+++ b/libnfc/drivers/arygon.c
@@ -119,7 +119,7 @@ arygon_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *
*pszDeviceFound = 0;
serial_port sp;
- const char *pcPorts[] = DEFAULT_SERIAL_PORTS;
+ char **pcPorts = uart_list_ports ();
const char *pcPort;
int iDevice = 0;
@@ -155,6 +155,7 @@ arygon_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *
# endif
/* DEBUG */
}
+ free (pcPorts);
#endif /* SERIAL_AUTOPROBE_ENABLED */
return true;
}
diff --git a/libnfc/drivers/pn532_uart.c b/libnfc/drivers/pn532_uart.c
index 73190cd..21cdebe 100644
--- a/libnfc/drivers/pn532_uart.c
+++ b/libnfc/drivers/pn532_uart.c
@@ -1,7 +1,8 @@
/*-
* Public platform independent Near Field Communication (NFC) library
*
- * Copyright (C) 2009, Roel Verdult
+ * Copyright (C) 2010, Roel Verdult, Romuald Conty
+ * Copyright (C) 2011, Romuald Conty, Romain Tartière
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
@@ -22,11 +23,13 @@
* @brief PN532 driver using UART bus (UART, RS232, etc.)
*/
+/* vim: set ts=2 sw=2 et: */
+
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif // HAVE_CONFIG_H
-#include "../drivers.h"
+#include "libnfc/drivers.h"
#include
#include
@@ -36,44 +39,26 @@
#include
#include
-// Bus
#include "uart.h"
+#include "libnfc/nfc-internal.h"
+#include "libnfc/chips/pn53x.h"
+#include "libnfc/chips/pn53x-internal.h"
#define SERIAL_DEFAULT_PORT_SPEED 115200
// TODO Move this one level up for libnfc-1.6
static const byte_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
-void pn532_uart_ack (const nfc_device_spec_t nds);
-void pn532_uart_wakeup (const nfc_device_spec_t nds);
-bool pn532_uart_check_communication (const nfc_device_spec_t nds, bool * success);
-
-nfc_device_desc_t *
-pn532_uart_pick_device (void)
-{
- nfc_device_desc_t *pndd;
-
- if ((pndd = malloc (sizeof (*pndd)))) {
- size_t szN;
-
- if (!pn532_uart_list_devices (pndd, 1, &szN)) {
- DBG ("%s", "pn532_uart_list_devices failed");
- free (pndd);
- return NULL;
- }
-
- if (szN == 0) {
- DBG ("%s", "No device found");
- free (pndd);
- return NULL;
- }
- }
-
- return pndd;
-}
+void pn532_uart_ack (nfc_device_t * pnd);
+// void pn532_uart_wakeup (const nfc_device_spec_t nds);
+bool pn532_uart_check_communication (nfc_device_t *pnd);
+struct pn532_uart_data {
+ serial_port port;
+};
+
bool
-pn532_uart_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound)
+pn532_uart_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, 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
@@ -88,7 +73,7 @@ pn532_uart_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size
*pszDeviceFound = 0;
serial_port sp;
- const char *pcPorts[] = DEFAULT_SERIAL_PORTS;
+ char **pcPorts = uart_list_ports ();
const char *pcPort;
int iDevice = 0;
@@ -97,15 +82,24 @@ pn532_uart_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size
DBG ("Trying to find PN532 device on serial port: %s at %d bauds.", pcPort, SERIAL_DEFAULT_PORT_SPEED);
if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) {
- bool bComOk;
// Serial port claimed but we need to check if a PN532_UART is connected.
uart_set_speed (sp, SERIAL_DEFAULT_PORT_SPEED);
+
+ nfc_device_t nd;
+ nd.driver = &pn532_uart_driver;
+ nd.driver_data = malloc(sizeof(struct pn532_uart_data));
+ ((struct pn532_uart_data*)(nd.driver_data))->port = sp;
+ nd.chip_data = malloc(sizeof(struct pn53x_data));
+ ((struct pn53x_data*)(nd.chip_data))->type = PN532;
+ ((struct pn53x_data*)(nd.chip_data))->state = SLEEP;
+
// PN532 could be powered down, we need to wake it up before line testing.
- pn532_uart_wakeup ((nfc_device_spec_t) sp);
+ // TODO pn532_uart_wakeup ((nfc_device_spec_t) sp);
// Check communication using "Diagnose" command, with "Communication test" (0x00)
- if (!pn532_uart_check_communication ((nfc_device_spec_t) sp, &bComOk))
- continue;
- if (!bComOk)
+ bool res = pn532_uart_check_communication (&nd);
+ free(nd.driver_data);
+ free(nd.chip_data);
+ if(!res)
continue;
uart_close (sp);
@@ -129,6 +123,7 @@ pn532_uart_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size
# endif
/* DEBUG */
}
+ free (pcPorts);
#endif /* SERIAL_AUTOPROBE_ENABLED */
return true;
}
@@ -138,7 +133,6 @@ pn532_uart_connect (const nfc_device_desc_t * pndd)
{
serial_port sp;
nfc_device_t *pnd = NULL;
- bool bComOk;
DBG ("Attempt to connect to: %s at %d bauds.", pndd->pcPort, pndd->uiSpeed);
sp = uart_open (pndd->pcPort);
@@ -152,24 +146,23 @@ pn532_uart_connect (const nfc_device_desc_t * pndd)
uart_set_speed (sp, pndd->uiSpeed);
- // PN532 could be powered down, we need to wake it up before line testing.
- pn532_uart_wakeup ((nfc_device_spec_t) sp);
- // Check communication using "Diagnose" command, with "Communication test" (0x00)
- if (!pn532_uart_check_communication ((nfc_device_spec_t) sp, &bComOk))
- return NULL;
- if (!bComOk)
- return NULL;
-
- DBG ("Successfully connected to: %s", pndd->pcPort);
-
// We have a connection
pnd = malloc (sizeof (nfc_device_t));
strncpy (pnd->acName, pndd->acDevice, DEVICE_NAME_LENGTH - 1);
pnd->acName[DEVICE_NAME_LENGTH - 1] = '\0';
- pnd->nc = NC_PN532;
- pnd->nds = (nfc_device_spec_t) sp;
- pnd->bActive = true;
+ pnd->driver_data = malloc(sizeof(struct pn532_uart_data));
+ ((struct pn532_uart_data*)(pnd->driver_data))->port = sp;
+ pnd->chip_data = malloc(sizeof(struct pn53x_data));
+ ((struct pn53x_data*)(pnd->chip_data))->type = PN532;
+ ((struct pn53x_data*)(pnd->chip_data))->state = SLEEP;
+ pnd->driver = &pn532_uart_driver;
+
+ // Check communication using "Diagnose" command, with "Communication test" (0x00)
+ if (!pn532_uart_check_communication (pnd))
+ return NULL;
+
+ DBG ("Successfully connected to: %s", pndd->pcPort);
return pnd;
}
@@ -177,196 +170,220 @@ pn532_uart_connect (const nfc_device_desc_t * pndd)
void
pn532_uart_disconnect (nfc_device_t * pnd)
{
- uart_close ((serial_port) pnd->nds);
+ uart_close (((struct pn532_uart_data*)(pnd->driver_data))->port);
+ free (pnd->driver_data);
+ free (pnd->chip_data);
free (pnd);
}
-#define TX_BUFFER_LEN (256)
-#define RX_BUFFER_LEN (PN53x_EXTENDED_FRAME_MAX_LEN + PN53x_EXTENDED_FRAME_OVERHEAD)
+#define PN532_BUFFER_LEN (PN53x_EXTENDED_FRAME__DATA_MAX_LEN + PN53x_EXTENDED_FRAME__OVERHEAD)
bool
-pn532_uart_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx,
- size_t * pszRx)
+pn532_uart_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData)
{
- byte_t abtTxBuf[TX_BUFFER_LEN] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
- byte_t abtRxBuf[RX_BUFFER_LEN];
- size_t szRxBufLen = MIN( RX_BUFFER_LEN, *pszRx );
- size_t szPos;
- int res;
-
- // Packet length = data length (len) + checksum (1) + end of stream marker (1)
- abtTxBuf[3] = szTx;
- // Packet length checksum
- abtTxBuf[4] = 256 - abtTxBuf[3];
- // Copy the PN53X command into the packet buffer
- memmove (abtTxBuf + 5, pbtTx, szTx);
-
- // Calculate data payload checksum
- abtTxBuf[szTx + 5] = 0;
- for (szPos = 0; szPos < szTx; szPos++) {
- abtTxBuf[szTx + 5] -= abtTxBuf[szPos + 5];
+ DBG ("state: %d (SLEEP: %d, NORMAL: %d, EXECUTE: %d)", ((struct pn53x_data*)(pnd->chip_data))->state, SLEEP, NORMAL, EXECUTE);
+ if (((struct pn53x_data*)(pnd->chip_data))->state == SLEEP) {
+// if (1) {
+ /** PN532C106 wakeup. */
+ /** High Speed Unit (HSU) wake up consist to send 0x55 and wait a "long" delay for PN532 being wakeup. */
+ const byte_t pn532_wakeup_preamble[] = { 0x55, 0x55, 0x00, 0x00, 0x00 };
+//, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ uart_send (((struct pn532_uart_data*)(pnd->driver_data))->port, pn532_wakeup_preamble, sizeof (pn532_wakeup_preamble));
+ ((struct pn53x_data*)(pnd->chip_data))->state = NORMAL; // PN532 should now be awake
+ // According to PN532 application note, C106 appendix: to go out Low Vbat mode and enter in normal mode we need to send a SAMConfiguration command
+ if (!pn53x_SAMConfiguration (pnd, 0x01)) {
+ return false;
+ }
}
- // End of stream marker
- abtTxBuf[szTx + 6] = 0;
+ byte_t abtTxBuf[PN532_BUFFER_LEN] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
-#ifdef DEBUG
- PRINT_HEX ("TX", abtTxBuf, szTx + 7);
-#endif
- res = uart_send ((serial_port) pnd->nds, abtTxBuf, szTx + 7);
+ pnd->iLastCommand = pbtData[0];
+ size_t szFrame = 0;
+
+ if (szData <= PN53x_NORMAL_FRAME__DATA_MAX_LEN) {
+ // LEN - Packet length = data length (len) + checksum (1) + end of stream marker (1)
+ abtTxBuf[3] = szData + 1;
+ // LCS - Packet length checksum
+ abtTxBuf[4] = 256 - (szData + 1);
+ // TFI
+ abtTxBuf[5] = 0xD4;
+ // DATA - Copy the PN53X command into the packet buffer
+ memcpy (abtTxBuf + 6, pbtData, szData);
+
+ // DCS - Calculate data payload checksum
+ byte_t btDCS = (256 - 0xD4);
+ for (size_t szPos = 0; szPos < szData; szPos++) {
+ btDCS -= pbtData[szPos];
+ }
+ abtTxBuf[6 + szData] = btDCS;
+
+ // 0x00 - End of stream marker
+ abtTxBuf[szData + 7] = 0x00;
+
+ szFrame = szData + PN53x_NORMAL_FRAME__OVERHEAD;
+ } else {
+ // FIXME: Build extended frame
+ abort();
+ }
+
+ int res = uart_send (((struct pn532_uart_data*)(pnd->driver_data))->port, abtTxBuf, szFrame);
if (res != 0) {
ERR ("%s", "Unable to transmit data. (TX)");
pnd->iLastError = res;
return false;
}
- res = uart_receive ((serial_port) pnd->nds, abtRxBuf, &szRxBufLen);
+ byte_t abtRxBuf[6];
+ res = uart_receive (((struct pn532_uart_data*)(pnd->driver_data))->port, abtRxBuf, 6);
+ if (res != 0) {
+ ERR ("%s", "Unable to read ACK");
+ pnd->iLastError = res;
+ return false;
+ }
+
+ if (pn53x_check_ack_frame_callback (pnd, abtRxBuf, sizeof(abtRxBuf))) {
+ ((struct pn53x_data*)(pnd->chip_data))->state = EXECUTE;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+int
+pn532_uart_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen)
+{
+ byte_t abtRxBuf[5];
+ size_t len;
+
+ int res = uart_receive (((struct pn532_uart_data*)(pnd->driver_data))->port, abtRxBuf, 5);
if (res != 0) {
ERR ("%s", "Unable to receive data. (RX)");
pnd->iLastError = res;
- return false;
- }
-#ifdef DEBUG
- PRINT_HEX ("RX", abtRxBuf, szRxBufLen);
-#endif
-
- // WARN: UART is a per byte reception, so you usually receive ACK and next frame the same time
- if (!pn53x_check_ack_frame_callback (pnd, abtRxBuf, szRxBufLen))
- return false;
- szRxBufLen -= sizeof (ack_frame);
- memmove (abtRxBuf, abtRxBuf + sizeof (ack_frame), szRxBufLen);
-
- if (szRxBufLen == 0) {
- szRxBufLen = RX_BUFFER_LEN;
- do {
- delay_ms (10);
- res = uart_receive ((serial_port) pnd->nds, abtRxBuf, &szRxBufLen);
- } while (res != 0);
-#ifdef DEBUG
- PRINT_HEX ("RX", abtRxBuf, szRxBufLen);
-#endif
+ return -1;
}
-#ifdef DEBUG
- PRINT_HEX ("TX", ack_frame, sizeof(ack_frame));
-#endif
- res = uart_send ((serial_port) pnd->nds, ack_frame, sizeof(ack_frame));
- if (res != 0) {
- ERR ("%s", "Unable to transmit data. (TX)");
- pnd->iLastError = res;
- return false;
+ const byte_t pn53x_preamble[3] = { 0x00, 0x00, 0xff };
+ if (0 != (memcmp (abtRxBuf, pn53x_preamble, 3))) {
+ ERR ("%s", "Frame preamble+start code mismatch");
+ pnd->iLastError = DEIO;
+ return -1;
}
- if (!pn53x_check_error_frame_callback (pnd, abtRxBuf, szRxBufLen))
- return false;
-
- // When the answer should be ignored, just return a successful result
- if (pbtRx == NULL || pszRx == NULL)
- return true;
-
- // Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable)
- if (szRxBufLen < 9) {
- pnd->iLastError = DEINVAL;
- return false;
- }
- // Remove the preceding and appending bytes 00 00 ff 00 ff 00 00 00 FF xx Fx .. .. .. xx 00 (x = variable)
- *pszRx = szRxBufLen - 9;
- memcpy (pbtRx, abtRxBuf + 7, *pszRx);
-
- return true;
-}
-
-void
-pn532_uart_ack (const nfc_device_spec_t nds)
-{
-#ifdef DEBUG
- PRINT_HEX ("TX", ack_frame, sizeof (ack_frame));
-#endif
- uart_send ((serial_port) nds, ack_frame, sizeof (ack_frame));
-}
-
-bool
-pn532_uart_wait_for_ack(const nfc_device_spec_t nds)
-{
- byte_t abtRx[RX_BUFFER_LEN];
- size_t szRx = sizeof(ack_frame);
- if (0 == uart_receive ((serial_port) nds, abtRx, &szRx)) {
-#ifdef DEBUG
- PRINT_HEX ("RX", abtRx, szRx);
-#endif
+ if ((0x01 == abtRxBuf[3]) && (0xff == abtRxBuf[4])) {
+ // Error frame
+ uart_receive (((struct pn532_uart_data*)(pnd->driver_data))->port, abtRxBuf, 3);
+ ERR ("%s", "Application level error detected");
+ pnd->iLastError = DEISERRFRAME;
+ return -1;
+ } else if ((0xff == abtRxBuf[3]) && (0xff == abtRxBuf[4])) {
+ // Extended frame
+ // FIXME: Code this
+ abort ();
} else {
- ERR ("No ACK.");
- return false;
- }
- if (0 != memcmp (ack_frame, abtRx, szRx))
- return false;
- return true;
-}
+ // Normal frame
+ if (256 != (abtRxBuf[3] + abtRxBuf[4])) {
+ // TODO: Retry
+ ERR ("%s", "Length checksum mismatch");
+ pnd->iLastError = DEIO;
+ return -1;
+ }
-#define PN53X_RX_OVERHEAD 6
-void
-pn532_uart_wakeup (const nfc_device_spec_t nds)
-{
- byte_t abtRx[RX_BUFFER_LEN];
- size_t szRx = PN53x_NORMAL_FRAME_OVERHEAD + 2;
- /** PN532C106 wakeup. */
- /** High Speed Unit (HSU) wake up consist to send 0x55 and wait a "long" delay for PN532 being wakeup. */
- /** After the preamble we request the PN532C106 chip to switch to "normal" mode (SAM is not used) */
- const byte_t pncmd_pn532c106_wakeup_preamble[] =
- { 0x55, 0x55, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xff, 0x03, 0xfd, 0xd4, 0x14, 0x01, 0x17, 0x00 }; // Here we send a SAMConfiguration command (Normal mode, the SAM is not used; this is the default mode)
-#ifdef DEBUG
- PRINT_HEX ("TX", pncmd_pn532c106_wakeup_preamble, sizeof (pncmd_pn532c106_wakeup_preamble));
-#endif
- uart_send ((serial_port) nds, pncmd_pn532c106_wakeup_preamble, sizeof (pncmd_pn532c106_wakeup_preamble));
-
- pn532_uart_wait_for_ack(nds);
-
- if (0 == uart_receive ((serial_port) nds, abtRx, &szRx)) {
-#ifdef DEBUG
- PRINT_HEX ("RX", abtRx, szRx);
-#endif
- } else {
- ERR ("Unable to wakeup the PN532.");
- }
-}
-
-bool
-pn532_uart_check_communication (const nfc_device_spec_t nds, bool * success)
-{
- byte_t abtRx[RX_BUFFER_LEN];
- const byte_t attempted_result[] =
- { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x09, 0xf7, 0xD5, 0x01, 0x00, 'l', 'i', 'b', 'n', 'f', 'c',
-0xbc, 0x00 };
- size_t szRx = sizeof(attempted_result);
- int res;
-
- /** To be sure that PN532 is alive, we have put a "Diagnose" command to execute a "Communication Line Test" */
- const byte_t pncmd_communication_test[] =
- { 0x00, 0x00, 0xff, 0x09, 0xf7, 0xd4, 0x00, 0x00, 'l', 'i', 'b', 'n', 'f', 'c', 0xbe, 0x00 };
-
- *success = false;
-
-#ifdef DEBUG
- PRINT_HEX ("TX", pncmd_communication_test, sizeof (pncmd_communication_test));
-#endif
- res = uart_send ((serial_port) nds, pncmd_communication_test, sizeof (pncmd_communication_test));
- if (res != 0) {
- ERR ("%s", "Unable to transmit data. (TX)");
- return false;
+ // abtRxBuf[3] (LEN) include TFI + (CC+1)
+ len = abtRxBuf[3] - 2;
}
- res = uart_receive ((serial_port) nds, abtRx, &szRx);
+ if (len > szDataLen) {
+ ERR ("Unable to receive data: buffer too small. (szDataLen: %zu, len: %zu)", szDataLen, len);
+ pnd->iLastError = DEIO;
+ return -1;
+ }
+
+ // TFI + PD0 (CC+1)
+ res = uart_receive (((struct pn532_uart_data*)(pnd->driver_data))->port, abtRxBuf, 2);
if (res != 0) {
ERR ("%s", "Unable to receive data. (RX)");
- return false;
+ pnd->iLastError = res;
+ return -1;
}
-#ifdef DEBUG
- PRINT_HEX ("RX", abtRx, szRx);
-#endif
- if (0 == memcmp (abtRx, attempted_result, sizeof (attempted_result)))
- *success = true;
+ if (abtRxBuf[0] != 0xD5) {
+ ERR ("%s", "TFI Mismatch");
+ pnd->iLastError = DEIO;
+ return -1;
+ }
- return true;
+ if (abtRxBuf[1] != pnd->iLastCommand + 1) {
+ ERR ("%s", "Command Code verification failed");
+ pnd->iLastError = DEIO;
+ return -1;
+ }
+
+ if (len) {
+ res = uart_receive (((struct pn532_uart_data*)(pnd->driver_data))->port, pbtData, len);
+ if (res != 0) {
+ ERR ("%s", "Unable to receive data. (RX)");
+ pnd->iLastError = res;
+ return -1;
+ }
+ }
+
+ res = uart_receive (((struct pn532_uart_data*)(pnd->driver_data))->port, abtRxBuf, 2);
+ if (res != 0) {
+ ERR ("%s", "Unable to receive data. (RX)");
+ pnd->iLastError = res;
+ return -1;
+ }
+
+ byte_t btDCS = (256 - 0xD5);
+ btDCS -= pnd->iLastCommand + 1;
+ for (size_t szPos = 0; szPos < len; szPos++) {
+ btDCS -= pbtData[szPos];
+ }
+
+ if (btDCS != abtRxBuf[0]) {
+ ERR ("%s", "Data checksum mismatch");
+ pnd->iLastError = DEIO;
+ return -1;
+ }
+
+ if (0x00 != abtRxBuf[1]) {
+ ERR ("%s", "Frame postamble mismatch");
+ pnd->iLastError = DEIO;
+ return -1;
+ }
+ ((struct pn53x_data*)(pnd->chip_data))->state = NORMAL;
+ return len;
}
+
+void
+pn532_uart_ack (nfc_device_t * pnd)
+{
+ uart_send (((struct pn532_uart_data*)(pnd->driver_data))->port, ack_frame, sizeof (ack_frame));
+}
+
+bool
+pn532_uart_check_communication (nfc_device_t *pnd)
+{
+ const byte_t abtMsg[] = { Diagnose, 0x00, 'l', 'i', 'b', 'n', 'f', 'c' };
+ if (!pn532_uart_send (pnd, abtMsg, sizeof (abtMsg)))
+ return false;
+
+ const byte_t abtExpectedRes[] = { 0x00, 'l', 'i', 'b', 'n', 'f', 'c' };
+
+ byte_t abtRes[sizeof(abtExpectedRes)];
+ int res;
+ if ((res = pn532_uart_receive (pnd, abtRes, sizeof(abtRes))) < 0)
+ return false;
+
+ return ((sizeof(abtRes) == res) && (0 == memcmp (abtRes, abtExpectedRes, sizeof(abtExpectedRes))));
+}
+
+const struct nfc_driver_t pn532_uart_driver = {
+ .name = PN532_UART_DRIVER_NAME,
+ .probe = pn532_uart_probe,
+ .connect = pn532_uart_connect,
+ .send = pn532_uart_send,
+ .receive = pn532_uart_receive,
+ .disconnect = pn532_uart_disconnect,
+ .strerror = pn53x_strerror,
+};
diff --git a/libnfc/drivers/pn532_uart.h b/libnfc/drivers/pn532_uart.h
index aa912f1..36d684f 100644
--- a/libnfc/drivers/pn532_uart.h
+++ b/libnfc/drivers/pn532_uart.h
@@ -1,7 +1,8 @@
/**
* Public platform independent Near Field Communication (NFC) library
*
- * Copyright (C) 2009, Roel Verdult
+ * Copyright (C) 2010, Roel Verdult, Romuald Conty
+ * Copyright (C) 2011, Romuald Conty, Romain Tartière
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
@@ -30,13 +31,15 @@
// Functions used by developer to handle connection to this device
nfc_device_desc_t *pn532_uart_pick_device (void);
-bool pn532_uart_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound);
+bool pn532_uart_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound);
nfc_device_t *pn532_uart_connect (const nfc_device_desc_t * pndd);
void pn532_uart_disconnect (nfc_device_t * pnd);
// Callback function used by libnfc to transmit commands to the PN53X chip
-bool pn532_uart_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx,
- size_t * pszRx);
+bool pn532_uart_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData);
+int pn532_uart_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen);
+
+extern const struct nfc_driver_t pn532_uart_driver;
#endif // ! __NFC_DRIVER_PN532_UART_H__
diff --git a/libnfc/nfc-internal.h b/libnfc/nfc-internal.h
new file mode 100644
index 0000000..d0c08ac
--- /dev/null
+++ b/libnfc/nfc-internal.h
@@ -0,0 +1,56 @@
+/*-
+ * Public platform independent Near Field Communication (NFC) library
+ *
+ * Copyright (C) 2011, Romain Tartière, Romuald Conty
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see
+ */
+
+/**
+ * @file nfc-internal.h
+ * @brief Internal defines and macros
+ */
+
+#ifndef __NFC_INTERNAL_H__
+# define __NFC_INTERNAL_H__
+
+# ifdef DEBUG
+//# if 1
+# define PRINT_HEX(pcTag, pbtData, szBytes) do { \
+ size_t __szPos; \
+ printf(" %s: ", pcTag); \
+ for (__szPos=0; __szPos < (size_t)(szBytes); __szPos++) { \
+ printf("%02x ",pbtData[__szPos]); \
+ } \
+ printf("\n"); \
+ } while (0);
+# else
+# define PRINT_HEX(pcTag, pbtData, szBytes) do { \
+ (void) pcTag; \
+ (void) pbtData; \
+ (void) szBytes; \
+ } while (0);
+# endif
+
+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);
+ bool (*send)(nfc_device_t * pnd, const byte_t * pbtData, const size_t szData);
+ int (*receive)(nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen);
+ void (*disconnect)(nfc_device_t * pnd);
+ const char *(*strerror)(const nfc_device_t * pnd);
+};
+
+#endif // __NFC_INTERNAL_H__
diff --git a/libnfc/nfc.c b/libnfc/nfc.c
index 0cc85a2..5fa3f81 100644
--- a/libnfc/nfc.c
+++ b/libnfc/nfc.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2009, Roel Verdult, Romuald Conty
* Copyright (C) 2010, Roel Verdult, Romuald Conty, Romain Tartière
+ * Copyright (C) 2011, Romuald Conty, Romain Tartière
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
@@ -23,6 +24,8 @@
* @brief NFC library implementation
*/
+/* vim:set ts=2 sw=2 et: */
+
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif // HAVE_CONFIG_H
@@ -40,11 +43,19 @@
#include "chips.h"
#include "drivers.h"
+#include "nfc-internal.h"
#include
nfc_device_desc_t *nfc_pick_device (void);
+const struct nfc_driver_t *nfc_drivers[] = {
+# if defined (DRIVER_PN532_UART_ENABLED)
+ &pn532_uart_driver,
+# endif /* DRIVER_PN532_UART_ENABLED */
+ NULL
+};
+
/**
* @brief Connect to a NFC device
* @param pndd device description if specific device is wanted, \c NULL otherwise
@@ -71,50 +82,32 @@ nfc_device_t *
nfc_connect (nfc_device_desc_t * pndd)
{
nfc_device_t *pnd = NULL;
- uint32_t uiDriver;
+
+ if (pndd == NULL)
+ pndd = nfc_pick_device ();
+
+ if (pndd == NULL)
+ return NULL;
// Search through the device list for an available device
- for (uiDriver = 0; uiDriver < sizeof (drivers_callbacks_list) / sizeof (drivers_callbacks_list[0]); uiDriver++) {
- if (pndd == NULL) {
- // No device description specified: try to automatically claim a device
- if (drivers_callbacks_list[uiDriver].pick_device != NULL) {
- DBG ("Autodetecting available devices using %s driver.", drivers_callbacks_list[uiDriver].acDriver);
- pndd = drivers_callbacks_list[uiDriver].pick_device ();
-
- if (pndd != NULL) {
- DBG ("Auto-connecting to %s using %s driver", pndd->acDevice, drivers_callbacks_list[uiDriver].acDriver);
- pnd = drivers_callbacks_list[uiDriver].connect (pndd);
- if (pnd == NULL) {
- DBG ("No device available using %s driver", drivers_callbacks_list[uiDriver].acDriver);
- pndd = NULL;
- }
-
- free (pndd);
- }
- }
+ 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)) {
+ continue;
} else {
- // Specific device is requested: using device description pndd
- if (0 != strcmp (drivers_callbacks_list[uiDriver].acDriver, pndd->pcDriver)) {
- continue;
- } else {
- pnd = drivers_callbacks_list[uiDriver].connect (pndd);
- }
+ pnd = ndr->connect (pndd);
}
// Test if the connection was successful
if (pnd != NULL) {
DBG ("[%s] has been claimed.", pnd->acName);
- // Great we have claimed a device
- pnd->pdc = &(drivers_callbacks_list[uiDriver]);
// TODO: Put this pn53x related in driver_init()
if (!pn53x_init (pnd))
return NULL;
- if (pnd->pdc->init) {
- pnd->pdc->init (pnd);
- }
-
// Set default configuration options
// Make sure we reset the CRC and parity to chip handling.
if (!nfc_configure (pnd, NDO_HANDLE_CRC, true))
@@ -144,8 +137,9 @@ nfc_connect (nfc_device_desc_t * pndd)
return pnd;
} else {
- DBG ("No device found using driver: %s", drivers_callbacks_list[uiDriver].acDriver);
+ DBG ("No device found using driver: %s", ndr->name);
}
+ pndr++;
}
// Too bad, no reader is ready to be claimed
return NULL;
@@ -166,7 +160,7 @@ nfc_disconnect (nfc_device_t * pnd)
// Disable RF field to avoid heating
nfc_configure (pnd, NDO_ACTIVATE_FIELD, false);
// Disconnect, clean up and release the device
- pnd->pdc->disconnect (pnd);
+ pnd->driver->disconnect (pnd);
}
}
@@ -177,17 +171,31 @@ nfc_disconnect (nfc_device_t * pnd)
nfc_device_desc_t *
nfc_pick_device (void)
{
- uint32_t uiDriver;
- nfc_device_desc_t *nddRes;
+ const struct nfc_driver_t *ndr;
+ const struct nfc_driver_t **pndr = nfc_drivers;
+ while ((ndr = *pndr)) {
+ nfc_device_desc_t *pndd;
- for (uiDriver = 0; uiDriver < sizeof (drivers_callbacks_list) / sizeof (drivers_callbacks_list[0]); uiDriver++) {
- if (drivers_callbacks_list[uiDriver].pick_device != NULL) {
- nddRes = drivers_callbacks_list[uiDriver].pick_device ();
- if (nddRes != NULL)
- return nddRes;
+ if ((pndd = malloc (sizeof (*pndd)))) {
+ size_t szN;
+
+ if (!ndr->probe (pndd, 1, &szN)) {
+ DBG ("%s probe failed", ndr->name);
+ free (pndd);
+ return NULL;
+ }
+
+ if (szN == 0) {
+ DBG ("No %s device found", ndr->name);
+ free (pndd);
+ } else {
+ return pndd;
+ }
}
+ pndr++;
}
+ DBG ("%s", "No device found with any driver :-(");
return NULL;
}
@@ -200,22 +208,19 @@ nfc_pick_device (void)
void
nfc_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound)
{
- uint32_t uiDriver;
size_t szN;
*pszDeviceFound = 0;
- for (uiDriver = 0; uiDriver < sizeof (drivers_callbacks_list) / sizeof (drivers_callbacks_list[0]); uiDriver++) {
- if (drivers_callbacks_list[uiDriver].list_devices != NULL) {
- szN = 0;
- if (drivers_callbacks_list[uiDriver].list_devices
- (pnddDevices + (*pszDeviceFound), szDevices - (*pszDeviceFound), &szN)) {
- *pszDeviceFound += szN;
- DBG ("%ld device(s) found using %s driver", (unsigned long) szN, drivers_callbacks_list[uiDriver].acDriver);
- }
- } else {
- DBG ("No listing function avaible for %s driver", drivers_callbacks_list[uiDriver].acDriver);
+ const struct nfc_driver_t *ndr;
+ const struct nfc_driver_t **pndr = nfc_drivers;
+ while ((ndr = *pndr)) {
+ szN = 0;
+ if (ndr->probe (pnddDevices + (*pszDeviceFound), szDevices - (*pszDeviceFound), &szN)) {
+ *pszDeviceFound += szN;
+ DBG ("%ld device(s) found using %s driver", (unsigned long) szN, ndr->name);
}
+ pndr++;
}
}
@@ -253,16 +258,12 @@ nfc_initiator_init (nfc_device_t * pnd)
{
pnd->iLastError = 0;
- // Make sure we are dealing with a active device
- if (!pnd->bActive)
- return false;
-
// Set the PN53X to force 100% ASK Modified miller decoding (default for 14443A cards)
- if (!pn53x_set_reg (pnd, REG_CIU_TX_AUTO, SYMBOL_FORCE_100_ASK, 0x40))
+ if (!pn53x_write_register (pnd, REG_CIU_TX_AUTO, SYMBOL_FORCE_100_ASK, 0x40))
return false;
// Configure the PN53X to be an Initiator or Reader/Writer
- if (!pn53x_set_reg (pnd, REG_CIU_CONTROL, SYMBOL_INITIATOR, 0x10))
+ if (!pn53x_write_register (pnd, REG_CIU_CONTROL, SYMBOL_INITIATOR, 0x10))
return false;
return true;
@@ -294,14 +295,11 @@ nfc_initiator_select_passive_target (nfc_device_t * pnd,
const byte_t * pbtInitData, const size_t szInitData,
nfc_target_t * pnt)
{
- byte_t abtInit[MAX_FRAME_LEN];
+ byte_t abtInit[MAX(12, szInitData)];
size_t szInit;
pnd->iLastError = 0;
- // Make sure we are dealing with a active device
- if (!pnd->bActive)
- return false;
// TODO Put this in a function: this part is defined by ISO14443-3 (UID and Cascade levels)
switch (nm.nmt) {
case NMT_ISO14443A:
@@ -662,7 +660,7 @@ nfc_target_receive_bits (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBits,
const char *
nfc_strerror (const nfc_device_t * pnd)
{
- return pnd->pdc->pcc->strerror (pnd);
+ return pnd->driver->strerror (pnd);
}
/**
diff --git a/test/test_register_access.c b/test/test_register_access.c
index b2b5941..90aafb9 100644
--- a/test/test_register_access.c
+++ b/test/test_register_access.c
@@ -1,13 +1,11 @@
#include
#include
-#include "../libnfc/chips/pn53x.h"
+#include "libnfc/chips/pn53x.h"
#define MAX_DEVICE_COUNT 1
#define MAX_TARGET_COUNT 1
-bool pn53x_get_reg(nfc_device_t* pnd, uint16_t ui16Reg, uint8_t* ui8Value);
-
void
test_register_endianness (void)
{
@@ -27,21 +25,21 @@ test_register_endianness (void)
uint8_t value;
/* Set a 0xAA test value in writable register memory to test register access */
- res = pn53x_set_reg (device, REG_CIU_TX_MODE, 0xFF, 0xAA);
- cut_assert_true (res, cut_message ("set a register value to 0xAA"));
+ res = pn53x_write_register (device, REG_CIU_TX_MODE, 0xFF, 0xAA);
+ cut_assert_true (res, cut_message ("write register value to 0xAA"));
/* Get test value from register memory */
- res = pn53x_get_reg (device, REG_CIU_TX_MODE, &value);
- cut_assert_true (res, cut_message ("get register value"));
+ res = pn53x_read_register (device, REG_CIU_TX_MODE, &value);
+ cut_assert_true (res, cut_message ("read register value"));
cut_assert_equal_uint (0xAA, value, cut_message ("check register value"));
/* Set a 0x55 test value in writable register memory to test register access */
- res = pn53x_set_reg (device, REG_CIU_TX_MODE, 0xFF, 0x55);
- cut_assert_true (res, cut_message ("set a register value to 0x55"));
+ res = pn53x_write_register (device, REG_CIU_TX_MODE, 0xFF, 0x55);
+ cut_assert_true (res, cut_message ("write register value to 0x55"));
/* Get test value from register memory */
- res = pn53x_get_reg (device, REG_CIU_TX_MODE, &value);
- cut_assert_true (res, cut_message ("get register value"));
+ res = pn53x_read_register (device, REG_CIU_TX_MODE, &value);
+ cut_assert_true (res, cut_message ("read register value"));
cut_assert_equal_uint (0x55, value, cut_message ("check register value"));
nfc_disconnect (device);
diff --git a/test/test_register_endianness.c b/test/test_register_endianness.c
index 6cae3e5..d227825 100644
--- a/test/test_register_endianness.c
+++ b/test/test_register_endianness.c
@@ -5,7 +5,7 @@
#define MAX_DEVICE_COUNT 1
#define MAX_TARGET_COUNT 1
-bool pn53x_get_reg(nfc_device_t* pnd, uint16_t ui16Reg, uint8_t* ui8Value);
+#include "libnfc/chips/pn53x.h"
void
test_register_endianness (void)
@@ -26,11 +26,11 @@ test_register_endianness (void)
uint8_t value;
/* Read valid XRAM memory */
- res = pn53x_get_reg (device, 0xF0FF, &value);
+ res = pn53x_read_register (device, 0xF0FF, &value);
cut_assert_true (res, cut_message ("read register 0xF0FF"));
/* Read invalid SFR register */
- res = pn53x_get_reg (device, 0xFFF0, &value);
+ res = pn53x_read_register (device, 0xFFF0, &value);
cut_assert_false (res, cut_message ("read register 0xFFF0"));
nfc_disconnect (device);