Merge libnfc-1.5-new-api branch to trunk (r1168:1303).
This commit is contained in:
commit
26245add73
82 changed files with 4481 additions and 3212 deletions
|
|
@ -18,7 +18,7 @@ libnfc_la_SOURCES = \
|
|||
nfc-emulation.c \
|
||||
nfc-internal.c
|
||||
|
||||
libnfc_la_LDFLAGS = -no-undefined -version-info 2:0:0
|
||||
libnfc_la_LDFLAGS = -no-undefined -version-info 2:0:0 -export-symbols-regex '^nfc_|^iso14443a_|pn53x_transceive|pn53x_SAMConfiguration'
|
||||
libnfc_la_CFLAGS = @DRIVERS_CFLAGS@
|
||||
libnfc_la_LIBADD = \
|
||||
$(top_builddir)/libnfc/chips/libnfcchips.la \
|
||||
|
|
@ -35,11 +35,11 @@ if LIBUSB_ENABLED
|
|||
libnfc_la_LIBADD += @libusb_LIBS@
|
||||
endif
|
||||
|
||||
if HAS_LOG4C
|
||||
libnfc_la_CFLAGS += @log4c_CFLAGS@
|
||||
libnfc_la_LIBADD += @log4c_LIBS@
|
||||
|
||||
libnfc_la_SOURCES += log.c
|
||||
if WITH_DEBUG
|
||||
libnfc_la_SOURCES += log-printf.c
|
||||
endif
|
||||
|
||||
EXTRA_DIST = CMakeLists.txt
|
||||
EXTRA_DIST = \
|
||||
CMakeLists.txt \
|
||||
log-printf.c
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,3 @@ libnfcbuses_la_CFLAGS = -I$(top_srcdir)/libnfc
|
|||
|
||||
EXTRA_DIST = uart_posix.c uart_win32.c
|
||||
|
||||
if HAS_LOG4C
|
||||
libnfcbuses_la_CFLAGS += @log4c_CFLAGS@
|
||||
libnfcbuses_la_LIBADD = @log4c_LIBS@
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -49,8 +49,8 @@ void uart_flush_input (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, const size_t szRx, void * abort_p, struct timeval *timeout);
|
||||
int uart_send (serial_port sp, const byte_t * pbtTx, const size_t szTx, struct timeval *timeout);
|
||||
int uart_receive (serial_port sp, uint8_t *pbtRx, const size_t szRx, void *abort_p, int timeout);
|
||||
int uart_send (serial_port sp, const uint8_t *pbtTx, const size_t szTx, int timeout);
|
||||
|
||||
char **uart_list_ports (void);
|
||||
|
||||
|
|
|
|||
|
|
@ -61,18 +61,20 @@ char *serial_ports_device_radix[] = { "ttyUSB", "ttyS", NULL };
|
|||
// Work-around to claim uart interface using the c_iflag (software input processing) from the termios struct
|
||||
# define CCLAIMED 0x80000000
|
||||
|
||||
typedef struct {
|
||||
struct serial_port_unix{
|
||||
int fd; // Serial port file descriptor
|
||||
struct termios termios_backup; // Terminal info before using the port
|
||||
struct termios termios_new; // Terminal info during the transaction
|
||||
} serial_port_unix;
|
||||
};
|
||||
|
||||
#define UART_DATA( X ) ((struct serial_port_unix *) X)
|
||||
|
||||
void uart_close_ext (const serial_port sp, const bool restore_termios);
|
||||
|
||||
serial_port
|
||||
uart_open (const char *pcPortName)
|
||||
{
|
||||
serial_port_unix *sp = malloc (sizeof (serial_port_unix));
|
||||
struct serial_port_unix *sp = malloc (sizeof (struct serial_port_unix));
|
||||
|
||||
if (sp == 0)
|
||||
return INVALID_SERIAL_PORT;
|
||||
|
|
@ -114,12 +116,12 @@ void
|
|||
uart_flush_input (serial_port sp)
|
||||
{
|
||||
// This line seems to produce absolutely no effect on my system (GNU/Linux 2.6.35)
|
||||
tcflush (((serial_port_unix *) sp)->fd, TCIFLUSH);
|
||||
tcflush (UART_DATA(sp)->fd, TCIFLUSH);
|
||||
// So, I wrote this byte-eater
|
||||
// Retrieve the count of the incoming bytes
|
||||
int available_bytes_count = 0;
|
||||
int res;
|
||||
res = ioctl (((serial_port_unix *) sp)->fd, FIONREAD, &available_bytes_count);
|
||||
res = ioctl (UART_DATA(sp)->fd, FIONREAD, &available_bytes_count);
|
||||
if (res != 0) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -128,7 +130,7 @@ uart_flush_input (serial_port sp)
|
|||
}
|
||||
char* rx = malloc (available_bytes_count);
|
||||
// There is something available, read the data
|
||||
res = read (((serial_port_unix *) sp)->fd, rx, available_bytes_count);
|
||||
res = read (UART_DATA(sp)->fd, rx, available_bytes_count);
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "%d bytes have eatten.", available_bytes_count);
|
||||
free (rx);
|
||||
}
|
||||
|
|
@ -137,8 +139,7 @@ void
|
|||
uart_set_speed (serial_port sp, const uint32_t uiPortSpeed)
|
||||
{
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Serial port speed requested to be set to %d bauds.", uiPortSpeed);
|
||||
serial_port_unix *spu = (serial_port_unix *) sp;
|
||||
|
||||
|
||||
// Portability note: on some systems, B9600 != 9600 so we have to do
|
||||
// uint32_t <=> speed_t associations by hand.
|
||||
speed_t stPortSpeed = B9600;
|
||||
|
|
@ -179,9 +180,9 @@ uart_set_speed (serial_port sp, const uint32_t uiPortSpeed)
|
|||
};
|
||||
|
||||
// Set port speed (Input and Output)
|
||||
cfsetispeed (&(spu->termios_new), stPortSpeed);
|
||||
cfsetospeed (&(spu->termios_new), stPortSpeed);
|
||||
if (tcsetattr (spu->fd, TCSADRAIN, &(spu->termios_new)) == -1) {
|
||||
cfsetispeed (&(UART_DATA(sp)->termios_new), stPortSpeed);
|
||||
cfsetospeed (&(UART_DATA(sp)->termios_new), stPortSpeed);
|
||||
if (tcsetattr (UART_DATA(sp)->fd, TCSADRAIN, &(UART_DATA(sp)->termios_new)) == -1) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Unable to apply new speed settings.");
|
||||
}
|
||||
}
|
||||
|
|
@ -190,8 +191,7 @@ uint32_t
|
|||
uart_get_speed (serial_port sp)
|
||||
{
|
||||
uint32_t uiPortSpeed = 0;
|
||||
const serial_port_unix *spu = (serial_port_unix *) sp;
|
||||
switch (cfgetispeed (&spu->termios_new)) {
|
||||
switch (cfgetispeed (&UART_DATA(sp)->termios_new)) {
|
||||
case B9600:
|
||||
uiPortSpeed = 9600;
|
||||
break;
|
||||
|
|
@ -229,10 +229,10 @@ uart_get_speed (serial_port sp)
|
|||
void
|
||||
uart_close_ext (const serial_port sp, const bool restore_termios)
|
||||
{
|
||||
if (((serial_port_unix *) sp)->fd >= 0) {
|
||||
if (UART_DATA(sp)->fd >= 0) {
|
||||
if (restore_termios)
|
||||
tcsetattr (((serial_port_unix *) sp)->fd, TCSANOW, &((serial_port_unix *) sp)->termios_backup);
|
||||
close (((serial_port_unix *) sp)->fd);
|
||||
tcsetattr (UART_DATA(sp)->fd, TCSANOW, &UART_DATA(sp)->termios_backup);
|
||||
close (UART_DATA(sp)->fd);
|
||||
}
|
||||
free (sp);
|
||||
}
|
||||
|
|
@ -249,7 +249,7 @@ uart_close (const serial_port sp)
|
|||
* @return 0 on success, otherwise driver error code
|
||||
*/
|
||||
int
|
||||
uart_receive (serial_port sp, byte_t * pbtRx, const size_t szRx, void * abort_p, struct timeval *timeout)
|
||||
uart_receive (serial_port sp, uint8_t *pbtRx, const size_t szRx, void *abort_p, int timeout)
|
||||
{
|
||||
int iAbortFd = abort_p ? *((int*)abort_p) : 0;
|
||||
int received_bytes_count = 0;
|
||||
|
|
@ -261,23 +261,19 @@ uart_receive (serial_port sp, byte_t * pbtRx, const size_t szRx, void * abort_p,
|
|||
select:
|
||||
// Reset file descriptor
|
||||
FD_ZERO (&rfds);
|
||||
FD_SET (((serial_port_unix *) sp)->fd, &rfds);
|
||||
FD_SET (UART_DATA(sp)->fd, &rfds);
|
||||
|
||||
if (iAbortFd) {
|
||||
FD_SET (iAbortFd, &rfds);
|
||||
}
|
||||
|
||||
/*
|
||||
* Some implementations (e.g. Linux) of select(2) will update *timeout.
|
||||
* Make a copy so that it will be updated on these systems,
|
||||
*/
|
||||
struct timeval fixed_timeout;
|
||||
if (timeout) {
|
||||
fixed_timeout = *timeout;
|
||||
timeout = &fixed_timeout;
|
||||
struct timeval timeout_tv;
|
||||
if (timeout > 0) {
|
||||
timeout_tv.tv_sec = (timeout / 1000);
|
||||
timeout_tv.tv_usec = ((timeout % 1000) * 1000);
|
||||
}
|
||||
|
||||
res = select (MAX(((serial_port_unix *) sp)->fd, iAbortFd) + 1, &rfds, NULL, NULL, timeout);
|
||||
res = select (MAX(UART_DATA(sp)->fd, iAbortFd) + 1, &rfds, NULL, NULL, timeout ? &timeout_tv : NULL);
|
||||
|
||||
if ((res < 0) && (EINTR == errno)) {
|
||||
// The system call was interupted by a signal and a signal handler was
|
||||
|
|
@ -287,38 +283,38 @@ select:
|
|||
|
||||
// Read error
|
||||
if (res < 0) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "%s", "RX error.");
|
||||
return ECOMIO;
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Error: %s", strerror(errno));
|
||||
return NFC_EIO;
|
||||
}
|
||||
// Read time-out
|
||||
if (res == 0) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Timeout!");
|
||||
return ECOMTIMEOUT;
|
||||
return NFC_ETIMEOUT;
|
||||
}
|
||||
|
||||
if (FD_ISSET (iAbortFd, &rfds)) {
|
||||
// Abort requested
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Abort!");
|
||||
close (iAbortFd);
|
||||
return EOPABORT;
|
||||
return NFC_EOPABORTED;
|
||||
}
|
||||
|
||||
// Retrieve the count of the incoming bytes
|
||||
res = ioctl (((serial_port_unix *) sp)->fd, FIONREAD, &available_bytes_count);
|
||||
res = ioctl (UART_DATA(sp)->fd, FIONREAD, &available_bytes_count);
|
||||
if (res != 0) {
|
||||
return ECOMIO;
|
||||
return NFC_EIO;
|
||||
}
|
||||
// There is something available, read the data
|
||||
res = read (((serial_port_unix *) sp)->fd, pbtRx + received_bytes_count, MIN(available_bytes_count, (expected_bytes_count - received_bytes_count)));
|
||||
res = read (UART_DATA(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 ECOMIO;
|
||||
return NFC_EIO;
|
||||
}
|
||||
received_bytes_count += res;
|
||||
|
||||
} while (expected_bytes_count > received_bytes_count);
|
||||
LOG_HEX ("RX", pbtRx, szRx);
|
||||
return 0;
|
||||
return NFC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -327,14 +323,14 @@ select:
|
|||
* @return 0 on success, otherwise a driver error is returned
|
||||
*/
|
||||
int
|
||||
uart_send (serial_port sp, const byte_t * pbtTx, const size_t szTx, struct timeval *timeout)
|
||||
uart_send (serial_port sp, const uint8_t *pbtTx, const size_t szTx, int timeout)
|
||||
{
|
||||
(void) timeout;
|
||||
LOG_HEX ("TX", pbtTx, szTx);
|
||||
if ((int) szTx == write (((serial_port_unix *) sp)->fd, pbtTx, szTx))
|
||||
return 0;
|
||||
if ((int) szTx == write (UART_DATA(sp)->fd, pbtTx, szTx))
|
||||
return NFC_SUCCESS;
|
||||
else
|
||||
return ECOMIO;
|
||||
return NFC_EIO;
|
||||
}
|
||||
|
||||
char **
|
||||
|
|
|
|||
|
|
@ -31,17 +31,17 @@
|
|||
#include "contrib/windows.h"
|
||||
#define delay_ms( X ) Sleep( X )
|
||||
|
||||
typedef struct {
|
||||
struct serial_port_windows {
|
||||
HANDLE hPort; // Serial port handle
|
||||
DCB dcb; // Device control settings
|
||||
COMMTIMEOUTS ct; // Serial port time-out configuration
|
||||
} serial_port_windows;
|
||||
};
|
||||
|
||||
serial_port
|
||||
uart_open (const char *pcPortName)
|
||||
{
|
||||
char acPortName[255];
|
||||
serial_port_windows *sp = malloc (sizeof (serial_port_windows));
|
||||
struct serial_port_windows *sp = malloc (sizeof (struct serial_port_windows));
|
||||
|
||||
// Copy the input "com?" to "\\.\COM?" format
|
||||
sprintf (acPortName, "\\\\.\\%s", pcPortName);
|
||||
|
|
@ -85,8 +85,8 @@ uart_open (const char *pcPortName)
|
|||
void
|
||||
uart_close (const serial_port sp)
|
||||
{
|
||||
if (((serial_port_windows *) sp)->hPort != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle (((serial_port_windows *) sp)->hPort);
|
||||
if (((struct serial_port_windows *) sp)->hPort != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle (((struct serial_port_windows *) sp)->hPort);
|
||||
}
|
||||
free (sp);
|
||||
}
|
||||
|
|
@ -94,13 +94,13 @@ uart_close (const serial_port sp)
|
|||
void
|
||||
uart_flush_input (const serial_port sp)
|
||||
{
|
||||
PurgeComm(((serial_port_windows *) sp)->hPort, PURGE_RXABORT | PURGE_RXCLEAR);
|
||||
PurgeComm(((struct serial_port_windows *) sp)->hPort, PURGE_RXABORT | PURGE_RXCLEAR);
|
||||
}
|
||||
|
||||
void
|
||||
uart_set_speed (serial_port sp, const uint32_t uiPortSpeed)
|
||||
{
|
||||
serial_port_windows *spw;
|
||||
struct serial_port_windows *spw;
|
||||
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Serial port speed requested to be set to %d bauds.", uiPortSpeed);
|
||||
// Set port speed (Input and Output)
|
||||
|
|
@ -117,7 +117,7 @@ uart_set_speed (serial_port sp, const uint32_t uiPortSpeed)
|
|||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Unable to set serial port speed to %d bauds. Speed value must be one of these constants: 9600 (default), 19200, 38400, 57600, 115200, 230400 or 460800.", uiPortSpeed);
|
||||
return;
|
||||
};
|
||||
spw = (serial_port_windows *) sp;
|
||||
spw = (struct serial_port_windows *) sp;
|
||||
|
||||
// Set baud rate
|
||||
spw->dcb.BaudRate = uiPortSpeed;
|
||||
|
|
@ -131,7 +131,7 @@ uart_set_speed (serial_port sp, const uint32_t uiPortSpeed)
|
|||
uint32_t
|
||||
uart_get_speed (const serial_port sp)
|
||||
{
|
||||
const serial_port_windows *spw = (serial_port_windows *) sp;
|
||||
const struct serial_port_windows *spw = (struct serial_port_windows *) sp;
|
||||
if (!GetCommState (spw->hPort, (serial_port) & spw->dcb))
|
||||
return spw->dcb.BaudRate;
|
||||
|
||||
|
|
@ -139,7 +139,7 @@ uart_get_speed (const serial_port sp)
|
|||
}
|
||||
|
||||
int
|
||||
uart_receive (serial_port sp, byte_t * pbtRx, const size_t szRx, void * abort_p, struct timeval *timeout)
|
||||
uart_receive (serial_port sp, uint8_t * pbtRx, const size_t szRx, void * abort_p, int timeout)
|
||||
{
|
||||
DWORD dwBytesToGet = (DWORD)szRx;
|
||||
DWORD dwBytesReceived = 0;
|
||||
|
|
@ -147,7 +147,7 @@ uart_receive (serial_port sp, byte_t * pbtRx, const size_t szRx, void * abort_p,
|
|||
BOOL res;
|
||||
|
||||
// XXX Put this part into uart_win32_timeouts () ?
|
||||
DWORD timeout_ms = timeout ? ((timeout->tv_sec * 1000) + (timeout->tv_usec / 1000)) : 0;
|
||||
DWORD timeout_ms = timeout;
|
||||
COMMTIMEOUTS timeouts;
|
||||
timeouts.ReadIntervalTimeout = 0;
|
||||
timeouts.ReadTotalTimeoutMultiplier = 0;
|
||||
|
|
@ -155,7 +155,7 @@ uart_receive (serial_port sp, byte_t * pbtRx, const size_t szRx, void * abort_p,
|
|||
timeouts.WriteTotalTimeoutMultiplier = 0;
|
||||
timeouts.WriteTotalTimeoutConstant = timeout_ms;
|
||||
|
||||
if (!SetCommTimeouts (((serial_port_windows *) sp)->hPort, &timeouts)) {
|
||||
if (!SetCommTimeouts (((struct serial_port_windows *) sp)->hPort, &timeouts)) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Unable to apply new timeout settings.");
|
||||
return ECOMIO;
|
||||
}
|
||||
|
|
@ -166,7 +166,7 @@ uart_receive (serial_port sp, byte_t * pbtRx, const size_t szRx, void * abort_p,
|
|||
volatile bool * abort_flag_p = (volatile bool *)abort_p;
|
||||
do {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "ReadFile");
|
||||
res = ReadFile (((serial_port_windows *) sp)->hPort, pbtRx + dwTotalBytesReceived,
|
||||
res = ReadFile (((struct serial_port_windows *) sp)->hPort, pbtRx + dwTotalBytesReceived,
|
||||
dwBytesToGet,
|
||||
&dwBytesReceived, NULL);
|
||||
|
||||
|
|
@ -194,24 +194,24 @@ uart_receive (serial_port sp, byte_t * pbtRx, const size_t szRx, void * abort_p,
|
|||
}
|
||||
|
||||
int
|
||||
uart_send (serial_port sp, const byte_t * pbtTx, const size_t szTx, struct timeval *timeout)
|
||||
uart_send (serial_port sp, const uint8_t * pbtTx, const size_t szTx, int timeout)
|
||||
{
|
||||
DWORD dwTxLen = 0;
|
||||
|
||||
COMMTIMEOUTS timeouts;
|
||||
timeouts.ReadIntervalTimeout = 0;
|
||||
timeouts.ReadTotalTimeoutMultiplier = 0;
|
||||
timeouts.ReadTotalTimeoutConstant = timeout ? ((timeout->tv_sec * 1000) + (timeout->tv_usec / 1000)) : 0;
|
||||
timeouts.ReadTotalTimeoutConstant = timeout;
|
||||
timeouts.WriteTotalTimeoutMultiplier = 0;
|
||||
timeouts.WriteTotalTimeoutConstant = timeout ? ((timeout->tv_sec * 1000) + (timeout->tv_usec / 1000)) : 0;
|
||||
timeouts.WriteTotalTimeoutConstant = timeout;
|
||||
|
||||
if (!SetCommTimeouts (((serial_port_windows *) sp)->hPort, &timeouts)) {
|
||||
if (!SetCommTimeouts (((struct serial_port_windows *) sp)->hPort, &timeouts)) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Unable to apply new timeout settings.");
|
||||
return ECOMIO;
|
||||
}
|
||||
|
||||
LOG_HEX ("TX", pbtTx, szTx);
|
||||
if (!WriteFile (((serial_port_windows *) sp)->hPort, pbtTx, szTx, &dwTxLen, NULL)) {
|
||||
if (!WriteFile (((struct serial_port_windows *) sp)->hPort, pbtTx, szTx, &dwTxLen, NULL)) {
|
||||
return ECOMIO;
|
||||
}
|
||||
if (!dwTxLen)
|
||||
|
|
@ -238,7 +238,7 @@ BOOL is_port_available(int nPort)
|
|||
char **
|
||||
uart_list_ports (void)
|
||||
{
|
||||
char ** availablePorts = malloc((1 + MAX_SERIAL_PORT_WIN) * sizeof(char*));
|
||||
char **availablePorts = malloc((1 + MAX_SERIAL_PORT_WIN) * sizeof(char*));
|
||||
int curIndex = 0;
|
||||
int i;
|
||||
for (i = 1; i <= MAX_SERIAL_PORT_WIN; i++) {
|
||||
|
|
|
|||
|
|
@ -7,9 +7,3 @@ noinst_LTLIBRARIES = libnfcchips.la
|
|||
libnfcchips_la_SOURCES = pn53x.c
|
||||
libnfcchips_la_CFLAGS = -I$(top_srcdir)/libnfc
|
||||
|
||||
|
||||
if HAS_LOG4C
|
||||
libnfcchips_la_CFLAGS += @log4c_CFLAGS@
|
||||
libnfcchips_la_LIBADD = @log4c_LIBS@
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ typedef struct {
|
|||
uint8_t ui8Code;
|
||||
uint8_t ui8CompatFlags;
|
||||
#ifdef LOGGING
|
||||
const char * abtCommandText;
|
||||
const char *abtCommandText;
|
||||
#endif
|
||||
} pn53x_command;
|
||||
|
||||
|
|
@ -203,8 +203,8 @@ static const pn53x_command pn53x_commands[] = {
|
|||
#ifdef LOGGING
|
||||
typedef struct {
|
||||
uint16_t ui16Address;
|
||||
const char * abtRegisterText;
|
||||
const char * abtRegisterDescription;
|
||||
const char *abtRegisterText;
|
||||
const char *abtRegisterDescription;
|
||||
} pn53x_register;
|
||||
|
||||
# define PNREG( X, Y ) { X , #X, Y }
|
||||
|
|
@ -299,6 +299,34 @@ typedef struct {
|
|||
#define PN53X_SFR_P7CFGB 0xFFF5
|
||||
#define PN53X_SFR_P7 0xFFF7
|
||||
|
||||
/* PN53x specific errors */
|
||||
#define ETIMEOUT 0x01
|
||||
#define ECRC 0x02
|
||||
#define EPARITY 0x03
|
||||
#define EBITCOUNT 0x04
|
||||
#define EFRAMING 0x05
|
||||
#define EBITCOLL 0x06
|
||||
#define ESMALLBUF 0x07
|
||||
#define EBUFOVF 0x09
|
||||
#define ERFTIMEOUT 0x0a
|
||||
#define ERFPROTO 0x0b
|
||||
#define EOVHEAT 0x0d
|
||||
#define EINBUFOVF 0x0e
|
||||
#define EINVPARAM 0x10
|
||||
#define EDEPUNKCMD 0x12
|
||||
#define EINVRXFRAM 0x13
|
||||
#define EMFAUTH 0x14
|
||||
#define ENSECNOTSUPP 0x18 // PN533 only
|
||||
#define EBCC 0x23
|
||||
#define EDEPINVSTATE 0x25
|
||||
#define EOPNOTALL 0x26
|
||||
#define ECMD 0x27
|
||||
#define ETGREL 0x29
|
||||
#define ECID 0x2a
|
||||
#define ECDISCARDED 0x2b
|
||||
#define ENFCID3 0x2c
|
||||
#define EOVCURRENT 0x2d
|
||||
#define ENAD 0x2e
|
||||
|
||||
#ifdef LOGGING
|
||||
static const pn53x_register pn53x_registers[] = {
|
||||
|
|
|
|||
1471
libnfc/chips/pn53x.c
1471
libnfc/chips/pn53x.c
File diff suppressed because it is too large
Load diff
|
|
@ -127,8 +127,8 @@ typedef enum {
|
|||
} pn53x_operating_mode;
|
||||
|
||||
struct pn53x_io {
|
||||
bool (*send)(nfc_device_t * pnd, const byte_t * pbtData, const size_t szData, struct timeval *timeout);
|
||||
int (*receive)(nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen, struct timeval *timeout);
|
||||
int (*send)(struct nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int timeout);
|
||||
int (*receive)(struct nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, int timeout);
|
||||
};
|
||||
|
||||
/* defines */
|
||||
|
|
@ -143,15 +143,17 @@ struct pn53x_data {
|
|||
/** Current operating mode */
|
||||
pn53x_operating_mode operating_mode;
|
||||
/** Current emulated target */
|
||||
nfc_target_t* current_target;
|
||||
nfc_target *current_target;
|
||||
/** PN53x I/O functions stored in struct */
|
||||
const struct pn53x_io * io;
|
||||
const struct pn53x_io *io;
|
||||
/** Last status byte returned by PN53x */
|
||||
uint8_t last_status_byte;
|
||||
/** Register cache for REG_CIU_BIT_FRAMING, SYMBOL_TX_LAST_BITS: The last TX bits setting, we need to reset this if it does not apply anymore */
|
||||
uint8_t ui8TxBits;
|
||||
/** Register cache for SetParameters function. */
|
||||
uint8_t ui8Parameters;
|
||||
/** Last sent command */
|
||||
uint8_t ui8LastCommand;
|
||||
uint8_t last_command;
|
||||
/** Interframe timer correction */
|
||||
int16_t timer_correction;
|
||||
/** Timer prescaler */
|
||||
|
|
@ -160,12 +162,18 @@ struct pn53x_data {
|
|||
uint8_t wb_data[PN53X_CACHE_REGISTER_SIZE];
|
||||
uint8_t wb_mask[PN53X_CACHE_REGISTER_SIZE];
|
||||
bool wb_trigged;
|
||||
/** Command timeout */
|
||||
int timeout_command;
|
||||
/** ATR timeout */
|
||||
int timeout_atr;
|
||||
/** Communication timeout */
|
||||
int timeout_communication;
|
||||
};
|
||||
|
||||
#define CHIP_DATA(pnd) ((struct pn53x_data*)(pnd->chip_data))
|
||||
|
||||
/**
|
||||
* @enum pn53x_modulation_t
|
||||
* @enum pn53x_modulation
|
||||
* @brief NFC modulation
|
||||
*/
|
||||
typedef enum {
|
||||
|
|
@ -187,10 +195,10 @@ typedef enum {
|
|||
PM_ISO14443B_424 = 0x07,
|
||||
/** ISO14443-B http://en.wikipedia.org/wiki/ISO/IEC_14443 (Not supported by PN531 nor PN532) */
|
||||
PM_ISO14443B_847 = 0x08,
|
||||
} pn53x_modulation_t;
|
||||
} pn53x_modulation;
|
||||
|
||||
/**
|
||||
* @enum pn53x_target_type_t
|
||||
* @enum pn53x_target_type
|
||||
* @brief NFC target type enumeration
|
||||
*/
|
||||
typedef enum {
|
||||
|
|
@ -228,7 +236,7 @@ typedef enum {
|
|||
PTT_DEP_ACTIVE_212 = 0x81,
|
||||
/** DEP active 424 kbps */
|
||||
PTT_DEP_ACTIVE_424 = 0x82,
|
||||
} pn53x_target_type_t;
|
||||
} pn53x_target_type;
|
||||
|
||||
typedef enum {
|
||||
PSM_NORMAL = 0x01,
|
||||
|
|
@ -238,7 +246,7 @@ typedef enum {
|
|||
} pn532_sam_mode;
|
||||
|
||||
/**
|
||||
* @enum pn53x_target_mode_t
|
||||
* @enum pn53x_target_mode
|
||||
* @brief PN53x target mode enumeration
|
||||
*/
|
||||
typedef enum {
|
||||
|
|
@ -250,104 +258,104 @@ typedef enum {
|
|||
PTM_DEP_ONLY = 0x02,
|
||||
/** Configure the PN532 to accept to be initialized only as ISO/IEC14443-4 PICC */
|
||||
PTM_ISO14443_4_PICC_ONLY = 0x04
|
||||
} pn53x_target_mode_t;
|
||||
} pn53x_target_mode;
|
||||
|
||||
extern const byte_t pn53x_ack_frame[6];
|
||||
extern const byte_t pn53x_nack_frame[6];
|
||||
extern const uint8_t pn53x_ack_frame[6];
|
||||
extern const uint8_t pn53x_nack_frame[6];
|
||||
|
||||
bool pn53x_init(nfc_device_t * pnd);
|
||||
bool pn53x_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx, size_t *pszRx, struct timeval *timeout);
|
||||
int pn53x_init(struct nfc_device *pnd);
|
||||
int pn53x_transceive (struct nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, uint8_t *pbtRx, const size_t szRxLen, int timeout);
|
||||
|
||||
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,
|
||||
pn53x_type chip_type, nfc_modulation_type_t nmt,
|
||||
nfc_target_info_t * pnti);
|
||||
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_get_firmware_version (nfc_device_t * pnd, char abtFirmwareText[22]);
|
||||
bool pn53x_configure (nfc_device_t * pnd, const nfc_device_option_t ndo, const bool bEnable);
|
||||
bool pn53x_check_communication (nfc_device_t *pnd);
|
||||
bool pn53x_idle (nfc_device_t * pnd);
|
||||
int pn53x_set_parameters (struct nfc_device *pnd, const uint8_t ui8Value, const bool bEnable);
|
||||
int pn53x_set_tx_bits (struct nfc_device *pnd, const uint8_t ui8Bits);
|
||||
int pn53x_wrap_frame (const uint8_t *pbtTx, const size_t szTxBits, const uint8_t *pbtTxPar, uint8_t *pbtFrame);
|
||||
int pn53x_unwrap_frame (const uint8_t *pbtFrame, const size_t szFrameBits, uint8_t *pbtRx, uint8_t *pbtRxPar);
|
||||
int pn53x_decode_target_data (const uint8_t *pbtRawData, size_t szRawData,
|
||||
pn53x_type chip_type, nfc_modulation_type nmt,
|
||||
nfc_target_info *pnti);
|
||||
int pn53x_read_register (struct nfc_device *pnd, uint16_t ui16Reg, uint8_t *ui8Value);
|
||||
int pn53x_write_register (struct nfc_device *pnd, uint16_t ui16Reg, uint8_t ui8SymbolMask, uint8_t ui8Value);
|
||||
int pn53x_get_firmware_version (struct nfc_device *pnd, char abtFirmwareText[22]);
|
||||
int pn53x_set_property_int (struct nfc_device *pnd, const nfc_property property, const int value);
|
||||
int pn53x_set_property_bool (struct nfc_device *pnd, const nfc_property property, const bool bEnable);
|
||||
|
||||
int pn53x_check_communication (struct nfc_device *pnd);
|
||||
int pn53x_idle (struct nfc_device *pnd);
|
||||
|
||||
// NFC device as Initiator functions
|
||||
bool pn53x_initiator_init (nfc_device_t * pnd);
|
||||
bool pn53x_initiator_select_passive_target (nfc_device_t * pnd,
|
||||
const nfc_modulation_t nm,
|
||||
const byte_t * pbtInitData, const size_t szInitData,
|
||||
nfc_target_t * pnt);
|
||||
bool pn53x_initiator_poll_target (nfc_device_t * pnd,
|
||||
const nfc_modulation_t * pnmModulations, const size_t szModulations,
|
||||
int pn53x_initiator_init (struct nfc_device *pnd);
|
||||
int pn53x_initiator_select_passive_target (struct nfc_device *pnd,
|
||||
const nfc_modulation nm,
|
||||
const uint8_t *pbtInitData, const size_t szInitData,
|
||||
nfc_target *pnt);
|
||||
int pn53x_initiator_poll_target (struct nfc_device *pnd,
|
||||
const nfc_modulation *pnmModulations, const size_t szModulations,
|
||||
const uint8_t uiPollNr, const uint8_t uiPeriod,
|
||||
nfc_target_t * pnt);
|
||||
bool pn53x_initiator_select_dep_target (nfc_device_t * pnd,
|
||||
const nfc_dep_mode_t ndm, const nfc_baud_rate_t nbr,
|
||||
const nfc_dep_info_t * pndiInitiator,
|
||||
nfc_target_t * pnt);
|
||||
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);
|
||||
bool pn53x_initiator_transceive_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx,
|
||||
byte_t * pbtRx, size_t * pszRx, struct timeval *timeout);
|
||||
bool pn53x_initiator_transceive_bits_timed (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, uint32_t * cycles);
|
||||
bool pn53x_initiator_transceive_bytes_timed (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx,
|
||||
byte_t * pbtRx, size_t * pszRx, uint32_t * cycles);
|
||||
bool pn53x_initiator_deselect_target (nfc_device_t * pnd);
|
||||
nfc_target *pnt);
|
||||
int pn53x_initiator_select_dep_target (struct nfc_device *pnd,
|
||||
const nfc_dep_mode ndm, const nfc_baud_rate nbr,
|
||||
const nfc_dep_info *pndiInitiator,
|
||||
nfc_target *pnt,
|
||||
const int timeout);
|
||||
int pn53x_initiator_transceive_bits (struct nfc_device *pnd, const uint8_t *pbtTx, const size_t szTxBits,
|
||||
const uint8_t *pbtTxPar, uint8_t *pbtRx, uint8_t *pbtRxPar);
|
||||
int pn53x_initiator_transceive_bytes (struct nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx,
|
||||
uint8_t *pbtRx, size_t *pszRx, int timeout);
|
||||
int pn53x_initiator_transceive_bits_timed (struct nfc_device *pnd, const uint8_t *pbtTx, const size_t szTxBits,
|
||||
const uint8_t *pbtTxPar, uint8_t *pbtRx, uint8_t *pbtRxPar, uint32_t *cycles);
|
||||
int pn53x_initiator_transceive_bytes_timed (struct nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx,
|
||||
uint8_t *pbtRx, uint32_t *cycles);
|
||||
int pn53x_initiator_deselect_target (struct nfc_device *pnd);
|
||||
|
||||
// NFC device as Target functions
|
||||
bool pn53x_target_init (nfc_device_t * pnd, nfc_target_t * pnt, byte_t * pbtRx, size_t * pszRx);
|
||||
bool pn53x_target_receive_bits (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBits, byte_t * pbtRxPar);
|
||||
bool pn53x_target_receive_bytes (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRx, struct timeval *timeout);
|
||||
bool pn53x_target_send_bits (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxBits, const byte_t * pbtTxPar);
|
||||
bool pn53x_target_send_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, struct timeval *timeout);
|
||||
int pn53x_target_init (struct nfc_device *pnd, nfc_target *pnt, uint8_t *pbtRx, const size_t szRxLen, int timeout);
|
||||
int pn53x_target_receive_bits (struct nfc_device *pnd, uint8_t *pbtRx, const size_t szRxLen, uint8_t *pbtRxPar);
|
||||
int pn53x_target_receive_bytes (struct nfc_device *pnd, uint8_t *pbtRx, const size_t szRxLen, int timeout);
|
||||
int pn53x_target_send_bits (struct nfc_device *pnd, const uint8_t *pbtTx, const size_t szTxBits, const uint8_t *pbtTxPar);
|
||||
int pn53x_target_send_bytes (struct nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, int timeout);
|
||||
|
||||
// Error handling functions
|
||||
const char *pn53x_strerror (const nfc_device_t * pnd);
|
||||
const char *pn53x_strerror (const struct nfc_device *pnd);
|
||||
|
||||
// C wrappers for PN53x commands
|
||||
bool pn53x_SetParameters (nfc_device_t * pnd, const uint8_t ui8Value);
|
||||
bool pn53x_SAMConfiguration (nfc_device_t * pnd, const pn532_sam_mode mode, struct timeval *timeout);
|
||||
bool pn53x_PowerDown (nfc_device_t * pnd);
|
||||
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,
|
||||
struct timeval *timeout);
|
||||
bool pn53x_InDeselect (nfc_device_t * pnd, const uint8_t ui8Target);
|
||||
bool pn53x_InRelease (nfc_device_t * pnd, const uint8_t ui8Target);
|
||||
bool 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);
|
||||
bool pn53x_InJumpForDEP (nfc_device_t * pnd,
|
||||
const nfc_dep_mode_t ndm, const nfc_baud_rate_t nbr,
|
||||
const byte_t * pbtPassiveInitiatorData,
|
||||
const byte_t * pbtNFCID3i,
|
||||
const byte_t * pbtGB, const size_t szGB,
|
||||
nfc_target_t * pnt);
|
||||
bool pn53x_TgInitAsTarget (nfc_device_t * pnd, pn53x_target_mode_t ptm,
|
||||
const byte_t * pbtMifareParams,
|
||||
const byte_t * pbtTkt, size_t szTkt,
|
||||
const byte_t * pbtFeliCaParams,
|
||||
const byte_t * pbtNFCID3t, const byte_t * pbtGB, const size_t szGB,
|
||||
byte_t * pbtRx, size_t * pszRx, byte_t * pbtModeByte);
|
||||
int pn53x_SetParameters (struct nfc_device *pnd, const uint8_t ui8Value);
|
||||
int pn53x_SAMConfiguration (struct nfc_device *pnd, const pn532_sam_mode mode, int timeout);
|
||||
int pn53x_PowerDown (struct nfc_device *pnd);
|
||||
int pn53x_InListPassiveTarget (struct nfc_device *pnd, const pn53x_modulation pmInitModulation,
|
||||
const uint8_t szMaxTargets, const uint8_t *pbtInitiatorData,
|
||||
const size_t szInitiatorDataLen, uint8_t *pbtTargetsData, size_t *pszTargetsData,
|
||||
int timeout);
|
||||
int pn53x_InDeselect (struct nfc_device *pnd, const uint8_t ui8Target);
|
||||
int pn53x_InRelease (struct nfc_device *pnd, const uint8_t ui8Target);
|
||||
int pn53x_InAutoPoll (struct nfc_device *pnd, const pn53x_target_type *ppttTargetTypes, const size_t szTargetTypes,
|
||||
const uint8_t btPollNr, const uint8_t btPeriod, nfc_target *pntTargets,
|
||||
const int timeout);
|
||||
int pn53x_InJumpForDEP (struct nfc_device *pnd,
|
||||
const nfc_dep_mode ndm, const nfc_baud_rate nbr,
|
||||
const uint8_t *pbtPassiveInitiatorData,
|
||||
const uint8_t *pbtNFCID3i,
|
||||
const uint8_t *pbtGB, const size_t szGB,
|
||||
nfc_target *pnt,
|
||||
const int timeout);
|
||||
int pn53x_TgInitAsTarget (struct nfc_device *pnd, pn53x_target_mode ptm,
|
||||
const uint8_t *pbtMifareParams,
|
||||
const uint8_t *pbtTkt, size_t szTkt,
|
||||
const uint8_t *pbtFeliCaParams,
|
||||
const uint8_t *pbtNFCID3t, const uint8_t *pbtGB, const size_t szGB,
|
||||
uint8_t *pbtRx, const size_t szRxLen, uint8_t *pbtModeByte, int timeout);
|
||||
|
||||
// RFConfiguration
|
||||
bool pn53x_RFConfiguration__RF_field (nfc_device_t * pnd, bool bEnable);
|
||||
bool pn53x_RFConfiguration__Various_timings (nfc_device_t * pnd, const uint8_t fATR_RES_Timeout, const uint8_t fRetryTimeout);
|
||||
bool pn53x_RFConfiguration__MaxRtyCOM (nfc_device_t * pnd, const uint8_t MaxRtyCOM);
|
||||
bool pn53x_RFConfiguration__MaxRetries (nfc_device_t * pnd, const uint8_t MxRtyATR, const uint8_t MxRtyPSL, const uint8_t MxRtyPassiveActivation);
|
||||
int pn53x_RFConfiguration__RF_field (struct nfc_device *pnd, bool bEnable);
|
||||
int pn53x_RFConfiguration__Various_timings (struct nfc_device *pnd, const uint8_t fATR_RES_Timeout, const uint8_t fRetryTimeout);
|
||||
int pn53x_RFConfiguration__MaxRtyCOM (struct nfc_device *pnd, const uint8_t MaxRtyCOM);
|
||||
int pn53x_RFConfiguration__MaxRetries (struct nfc_device *pnd, const uint8_t MxRtyATR, const uint8_t MxRtyPSL, const uint8_t MxRtyPassiveActivation);
|
||||
|
||||
// Misc
|
||||
bool pn53x_check_ack_frame (nfc_device_t * pnd, const byte_t * pbtRxFrame, const size_t szRxFrameLen);
|
||||
bool pn53x_check_error_frame (nfc_device_t * pnd, const byte_t * pbtRxFrame, const size_t szRxFrameLen);
|
||||
bool pn53x_build_frame (byte_t * pbtFrame, size_t * pszFrame, const byte_t * pbtData, const size_t szData);
|
||||
int pn53x_check_ack_frame (struct nfc_device *pnd, const uint8_t *pbtRxFrame, const size_t szRxFrameLen);
|
||||
int pn53x_check_error_frame (struct nfc_device *pnd, const uint8_t *pbtRxFrame, const size_t szRxFrameLen);
|
||||
int pn53x_build_frame (uint8_t *pbtFrame, size_t *pszFrame, const uint8_t *pbtData, const size_t szData);
|
||||
|
||||
void pn53x_data_new (nfc_device_t * pnd, const struct pn53x_io* io);
|
||||
void pn53x_data_free (nfc_device_t * pnd);
|
||||
void pn53x_data_new (struct nfc_device *pnd, const struct pn53x_io *io);
|
||||
void pn53x_data_free (struct nfc_device *pnd);
|
||||
|
||||
#endif // __NFC_CHIPS_PN53X_H__
|
||||
|
|
|
|||
|
|
@ -50,6 +50,6 @@
|
|||
|
||||
# define DRIVERS_MAX_DEVICES 16
|
||||
|
||||
extern const struct nfc_driver_t *nfc_drivers[];
|
||||
extern const struct nfc_driver *nfc_drivers[];
|
||||
|
||||
#endif // __NFC_DRIVERS_H__
|
||||
|
|
|
|||
|
|
@ -38,8 +38,3 @@ if LIBUSB_ENABLED
|
|||
libnfcdrivers_la_LIBADD += @libusb_LIBS@
|
||||
endif
|
||||
|
||||
if HAS_LOG4C
|
||||
libnfcdrivers_la_CFLAGS += @log4c_CFLAGS@
|
||||
libnfcdrivers_la_LIBADD += @log4c_LIBS@
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
# include "config.h"
|
||||
#endif // HAVE_CONFIG_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
|
@ -40,7 +41,7 @@
|
|||
// Bus
|
||||
#include <winscard.h>
|
||||
|
||||
# define ACR122_DRIVER_NAME "ACR122"
|
||||
#define ACR122_DRIVER_NAME "acr122"
|
||||
|
||||
#if defined (_WIN32)
|
||||
# define IOCTL_CCID_ESCAPE_SCARD_CTL_CODE SCARD_CTL_CODE(3500)
|
||||
|
|
@ -76,7 +77,7 @@
|
|||
|
||||
const struct pn53x_io acr122_io;
|
||||
|
||||
char *acr122_firmware (nfc_device_t *pnd);
|
||||
char *acr122_firmware (nfc_device *pnd);
|
||||
|
||||
const char *supported_devices[] = {
|
||||
"ACS ACR122", // ACR122U & Touchatag, last version
|
||||
|
|
@ -89,7 +90,7 @@ const char *supported_devices[] = {
|
|||
struct acr122_data {
|
||||
SCARDHANDLE hCard;
|
||||
SCARD_IO_REQUEST ioCard;
|
||||
byte_t abtRx[ACR122_RESPONSE_LEN];
|
||||
uint8_t abtRx[ACR122_RESPONSE_LEN];
|
||||
size_t szRx;
|
||||
};
|
||||
|
||||
|
|
@ -123,7 +124,7 @@ acr122_free_scardcontext (void)
|
|||
|
||||
#define PCSC_MAX_DEVICES 16
|
||||
/**
|
||||
* @brief List connected devices
|
||||
* @brief List opened devices
|
||||
*
|
||||
* Probe PCSC to find NFC capable hardware.
|
||||
*
|
||||
|
|
@ -133,7 +134,7 @@ acr122_free_scardcontext (void)
|
|||
* @return true if succeeded, false otherwise.
|
||||
*/
|
||||
bool
|
||||
acr122_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound)
|
||||
acr122_probe (nfc_connstring connstrings[], size_t connstrings_len, size_t *pszDeviceFound)
|
||||
{
|
||||
size_t szPos = 0;
|
||||
char acDeviceNames[256 + 64 * PCSC_MAX_DEVICES];
|
||||
|
|
@ -158,9 +159,7 @@ acr122_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDev
|
|||
if (SCardListReaders (*pscc, NULL, acDeviceNames, &dwDeviceNamesLen) != SCARD_S_SUCCESS)
|
||||
return false;
|
||||
|
||||
// DBG("%s", "PCSC reports following device(s):");
|
||||
|
||||
while ((acDeviceNames[szPos] != '\0') && ((*pszDeviceFound) < szDevices)) {
|
||||
while ((acDeviceNames[szPos] != '\0') && ((*pszDeviceFound) < connstrings_len)) {
|
||||
uiBusIndex++;
|
||||
|
||||
// DBG("- %s (pos=%ld)", acDeviceNames + szPos, (unsigned long) szPos);
|
||||
|
|
@ -173,9 +172,7 @@ acr122_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDev
|
|||
|
||||
if (bSupported) {
|
||||
// Supported ACR122 device found
|
||||
strncpy (pnddDevices[*pszDeviceFound].acDevice, acDeviceNames + szPos, DEVICE_NAME_LENGTH - 1);
|
||||
pnddDevices[*pszDeviceFound].pcDriver = ACR122_DRIVER_NAME;
|
||||
pnddDevices[*pszDeviceFound].uiBusIndex = uiBusIndex;
|
||||
snprintf (connstrings[*pszDeviceFound], sizeof(nfc_connstring), "%s:%s:%"PRIu32, ACR122_DRIVER_NAME, acDeviceNames + szPos, uiBusIndex);
|
||||
(*pszDeviceFound)++;
|
||||
} else {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "PCSC device [%s] is not NFC capable or not supported by libnfc.", acDeviceNames + szPos);
|
||||
|
|
@ -189,26 +186,88 @@ acr122_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDev
|
|||
return true;
|
||||
}
|
||||
|
||||
nfc_device_t *
|
||||
acr122_connect (const nfc_device_desc_t * pndd)
|
||||
struct acr122_descriptor {
|
||||
char pcsc_device_name[512];
|
||||
int bus_index;
|
||||
};
|
||||
|
||||
int
|
||||
acr122_connstring_decode (const nfc_connstring connstring, struct acr122_descriptor *desc)
|
||||
{
|
||||
char *cs = malloc (strlen (connstring) + 1);
|
||||
if (!cs) {
|
||||
perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
strcpy (cs, connstring);
|
||||
const char *driver_name = strtok (cs, ":");
|
||||
if (!driver_name) {
|
||||
// Parse error
|
||||
free (cs);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 != strcmp (driver_name, ACR122_DRIVER_NAME)) {
|
||||
// Driver name does not match.
|
||||
free (cs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *device_name = strtok (NULL, ":");
|
||||
if (!device_name) {
|
||||
// Only driver name was specified (or parsing error)
|
||||
free (cs);
|
||||
return 1;
|
||||
}
|
||||
strncpy (desc->pcsc_device_name, device_name, sizeof(desc->pcsc_device_name)-1);
|
||||
desc->pcsc_device_name[sizeof(desc->pcsc_device_name)-1] = '\0';
|
||||
|
||||
const char *bus_index_s = strtok (NULL, ":");
|
||||
if (!bus_index_s) {
|
||||
// bus index not specified (or parsing error)
|
||||
free (cs);
|
||||
return 2;
|
||||
}
|
||||
unsigned long bus_index;
|
||||
if (sscanf (bus_index_s, "%lu", &bus_index) != 1) {
|
||||
// bus_index_s is not a number
|
||||
free (cs);
|
||||
return 2;
|
||||
}
|
||||
desc->bus_index = bus_index;
|
||||
|
||||
free (cs);
|
||||
return 3;
|
||||
}
|
||||
|
||||
nfc_device *
|
||||
acr122_open (const nfc_connstring connstring)
|
||||
{
|
||||
struct acr122_descriptor ndd;
|
||||
int connstring_decode_level = acr122_connstring_decode (connstring, &ndd);
|
||||
|
||||
if (connstring_decode_level < 2) {
|
||||
return NULL;
|
||||
}
|
||||
// FIXME: acr122_open() does not take care about bus index
|
||||
|
||||
char *pcFirmware;
|
||||
nfc_device_t *pnd = nfc_device_new ();
|
||||
nfc_device *pnd = nfc_device_new (connstring);
|
||||
pnd->driver_data = malloc (sizeof (struct acr122_data));
|
||||
|
||||
// Alloc and init chip's data
|
||||
pn53x_data_new (pnd, &acr122_io);
|
||||
|
||||
SCARDCONTEXT *pscc;
|
||||
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Attempt to connect to %s", pndd->acDevice);
|
||||
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Attempt to open %s", ndd.pcsc_device_name);
|
||||
// Test if context succeeded
|
||||
if (!(pscc = acr122_get_scardcontext ()))
|
||||
goto error;
|
||||
// Test if we were able to connect to the "emulator" card
|
||||
if (SCardConnect (*pscc, pndd->acDevice, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &(DRIVER_DATA (pnd)->hCard), (void *) &(DRIVER_DATA (pnd)->ioCard.dwProtocol)) != SCARD_S_SUCCESS) {
|
||||
if (SCardConnect (*pscc, ndd.pcsc_device_name, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &(DRIVER_DATA (pnd)->hCard), (void *) &(DRIVER_DATA (pnd)->ioCard.dwProtocol)) != SCARD_S_SUCCESS) {
|
||||
// Connect to ACR122 firmware version >2.0
|
||||
if (SCardConnect (*pscc, pndd->acDevice, SCARD_SHARE_DIRECT, 0, &(DRIVER_DATA (pnd)->hCard), (void *) &(DRIVER_DATA (pnd)->ioCard.dwProtocol)) != SCARD_S_SUCCESS) {
|
||||
if (SCardConnect (*pscc, ndd.pcsc_device_name, SCARD_SHARE_DIRECT, 0, &(DRIVER_DATA (pnd)->hCard), (void *) &(DRIVER_DATA (pnd)->ioCard.dwProtocol)) != SCARD_S_SUCCESS) {
|
||||
// We can not connect to this device.
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "%s", "PCSC connect failed");
|
||||
goto error;
|
||||
|
|
@ -222,7 +281,7 @@ acr122_connect (const nfc_device_desc_t * pndd)
|
|||
if (strstr (pcFirmware, FIRMWARE_TEXT) != NULL) {
|
||||
|
||||
// Done, we found the reader we are looking for
|
||||
snprintf (pnd->acName, sizeof (pnd->acName), "%s / %s", pndd->acDevice, pcFirmware);
|
||||
snprintf (pnd->name, sizeof (pnd->name), "%s / %s", ndd.pcsc_device_name, pcFirmware);
|
||||
|
||||
// 50: empirical tuning on Touchatag
|
||||
// 46: empirical tuning on ACR122U
|
||||
|
|
@ -242,7 +301,7 @@ error:
|
|||
}
|
||||
|
||||
void
|
||||
acr122_disconnect (nfc_device_t * pnd)
|
||||
acr122_close (nfc_device *pnd)
|
||||
{
|
||||
SCardDisconnect (DRIVER_DATA (pnd)->hCard, SCARD_LEAVE_CARD);
|
||||
acr122_free_scardcontext ();
|
||||
|
|
@ -251,21 +310,21 @@ acr122_disconnect (nfc_device_t * pnd)
|
|||
nfc_device_free (pnd);
|
||||
}
|
||||
|
||||
bool
|
||||
acr122_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData, struct timeval *timeout)
|
||||
int
|
||||
acr122_send (nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int timeout)
|
||||
{
|
||||
// FIXME: timeout is not handled
|
||||
(void) timeout;
|
||||
|
||||
// Make sure the command does not overflow the send buffer
|
||||
if (szData > ACR122_COMMAND_LEN) {
|
||||
pnd->iLastError = EINVALARG;
|
||||
return false;
|
||||
pnd->last_error = NFC_EINVARG;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
// Prepare and transmit the send buffer
|
||||
const size_t szTxBuf = szData + 6;
|
||||
byte_t abtTxBuf[ACR122_WRAP_LEN + ACR122_COMMAND_LEN] = { 0xFF, 0x00, 0x00, 0x00, szData + 1, 0xD4 };
|
||||
uint8_t abtTxBuf[ACR122_WRAP_LEN + ACR122_COMMAND_LEN] = { 0xFF, 0x00, 0x00, 0x00, szData + 1, 0xD4 };
|
||||
memcpy (abtTxBuf + 6, pbtData, szData);
|
||||
LOG_HEX ("TX", abtTxBuf, szTxBuf);
|
||||
|
||||
|
|
@ -286,8 +345,8 @@ acr122_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData, st
|
|||
* field.
|
||||
*/
|
||||
if (SCardControl (DRIVER_DATA (pnd)->hCard, IOCTL_CCID_ESCAPE_SCARD_CTL_CODE, abtTxBuf, szTxBuf, DRIVER_DATA (pnd)->abtRx, ACR122_RESPONSE_LEN, &dwRxLen) != SCARD_S_SUCCESS) {
|
||||
pnd->iLastError = ECOMIO;
|
||||
return false;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
|
|
@ -295,8 +354,8 @@ acr122_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData, st
|
|||
* receive the response from the PN532.
|
||||
*/
|
||||
if (SCardTransmit (DRIVER_DATA (pnd)->hCard, &(DRIVER_DATA (pnd)->ioCard), abtTxBuf, szTxBuf, NULL, DRIVER_DATA (pnd)->abtRx, &dwRxLen) != SCARD_S_SUCCESS) {
|
||||
pnd->iLastError = ECOMIO;
|
||||
return false;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -307,29 +366,29 @@ acr122_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData, st
|
|||
|
||||
// Make sure we received the byte-count we expected
|
||||
if (dwRxLen != 2) {
|
||||
pnd->iLastError = ECOMIO;
|
||||
return false;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
// Check if the operation was successful, so an answer is available
|
||||
if (DRIVER_DATA (pnd)->abtRx[0] == SCARD_OPERATION_ERROR) {
|
||||
pnd->iLastError = EFRAISERRFRAME;
|
||||
return false;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
} else {
|
||||
DRIVER_DATA (pnd)->szRx = dwRxLen;
|
||||
}
|
||||
|
||||
return true;
|
||||
return NFC_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
acr122_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szData, struct timeval *timeout)
|
||||
acr122_receive (nfc_device *pnd, uint8_t *pbtData, const size_t szData, int timeout)
|
||||
{
|
||||
// FIXME: timeout is not handled
|
||||
(void) timeout;
|
||||
|
||||
int len;
|
||||
byte_t abtRxCmd[5] = { 0xFF, 0xC0, 0x00, 0x00 };
|
||||
uint8_t abtRxCmd[5] = { 0xFF, 0xC0, 0x00, 0x00 };
|
||||
|
||||
if (DRIVER_DATA (pnd)->ioCard.dwProtocol == SCARD_PROTOCOL_T0) {
|
||||
/*
|
||||
|
|
@ -338,8 +397,8 @@ acr122_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szData, struc
|
|||
DWORD dwRxLen = sizeof (DRIVER_DATA (pnd)->abtRx);
|
||||
abtRxCmd[4] = DRIVER_DATA (pnd)->abtRx[1];
|
||||
if (SCardTransmit (DRIVER_DATA (pnd)->hCard, &(DRIVER_DATA (pnd)->ioCard), abtRxCmd, sizeof (abtRxCmd), NULL, DRIVER_DATA (pnd)->abtRx, &dwRxLen) != SCARD_S_SUCCESS) {
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
DRIVER_DATA (pnd)->szRx = dwRxLen;
|
||||
} else {
|
||||
|
|
@ -351,31 +410,29 @@ acr122_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szData, struc
|
|||
|
||||
// Make sure we have an emulated answer that fits the return buffer
|
||||
if (DRIVER_DATA (pnd)->szRx < 4 || (DRIVER_DATA (pnd)->szRx - 4) > szData) {
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
// Wipe out the 4 APDU emulation bytes: D5 4B .. .. .. 90 00
|
||||
len = DRIVER_DATA (pnd)->szRx - 4;
|
||||
memcpy (pbtData, DRIVER_DATA (pnd)->abtRx + 2, len);
|
||||
|
||||
// Transmission went successful
|
||||
pnd->iLastError = 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
char *
|
||||
acr122_firmware (nfc_device_t *pnd)
|
||||
acr122_firmware (nfc_device *pnd)
|
||||
{
|
||||
byte_t abtGetFw[5] = { 0xFF, 0x00, 0x48, 0x00, 0x00 };
|
||||
uint8_t abtGetFw[5] = { 0xFF, 0x00, 0x48, 0x00, 0x00 };
|
||||
uint32_t uiResult;
|
||||
|
||||
static char abtFw[11];
|
||||
DWORD dwFwLen = sizeof (abtFw);
|
||||
memset (abtFw, 0x00, sizeof (abtFw));
|
||||
if (DRIVER_DATA (pnd)->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED) {
|
||||
uiResult = SCardControl (DRIVER_DATA (pnd)->hCard, IOCTL_CCID_ESCAPE_SCARD_CTL_CODE, abtGetFw, sizeof (abtGetFw), (byte_t *) abtFw, dwFwLen-1, &dwFwLen);
|
||||
uiResult = SCardControl (DRIVER_DATA (pnd)->hCard, IOCTL_CCID_ESCAPE_SCARD_CTL_CODE, abtGetFw, sizeof (abtGetFw), (uint8_t *) abtFw, dwFwLen-1, &dwFwLen);
|
||||
} else {
|
||||
uiResult = SCardTransmit (DRIVER_DATA (pnd)->hCard, &(DRIVER_DATA (pnd)->ioCard), abtGetFw, sizeof (abtGetFw), NULL, (byte_t *) abtFw, &dwFwLen);
|
||||
uiResult = SCardTransmit (DRIVER_DATA (pnd)->hCard, &(DRIVER_DATA (pnd)->ioCard), abtGetFw, sizeof (abtGetFw), NULL, (uint8_t *) abtFw, &dwFwLen);
|
||||
}
|
||||
|
||||
if (uiResult != SCARD_S_SUCCESS) {
|
||||
|
|
@ -387,10 +444,10 @@ acr122_firmware (nfc_device_t *pnd)
|
|||
|
||||
#if 0
|
||||
bool
|
||||
acr122_led_red (nfc_device_t *pnd, bool bOn)
|
||||
acr122_led_red (nfc_device *pnd, bool bOn)
|
||||
{
|
||||
byte_t abtLed[9] = { 0xFF, 0x00, 0x40, 0x05, 0x04, 0x00, 0x00, 0x00, 0x00 };
|
||||
byte_t abtBuf[2];
|
||||
uint8_t abtLed[9] = { 0xFF, 0x00, 0x40, 0x05, 0x04, 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t abtBuf[2];
|
||||
DWORD dwBufLen = sizeof (abtBuf);
|
||||
(void) bOn;
|
||||
if (DRIVER_DATA (pnd)->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED) {
|
||||
|
|
@ -406,12 +463,12 @@ const struct pn53x_io acr122_io = {
|
|||
.receive = acr122_receive,
|
||||
};
|
||||
|
||||
const struct nfc_driver_t acr122_driver = {
|
||||
.name = ACR122_DRIVER_NAME,
|
||||
.probe = acr122_probe,
|
||||
.connect = acr122_connect,
|
||||
.disconnect = acr122_disconnect,
|
||||
.strerror = pn53x_strerror,
|
||||
const struct nfc_driver acr122_driver = {
|
||||
.name = ACR122_DRIVER_NAME,
|
||||
.probe = acr122_probe,
|
||||
.open = acr122_open,
|
||||
.close = acr122_close,
|
||||
.strerror = pn53x_strerror,
|
||||
|
||||
.initiator_init = pn53x_initiator_init,
|
||||
.initiator_select_passive_target = pn53x_initiator_select_passive_target,
|
||||
|
|
@ -429,9 +486,10 @@ const struct nfc_driver_t acr122_driver = {
|
|||
.target_send_bits = pn53x_target_send_bits,
|
||||
.target_receive_bits = pn53x_target_receive_bits,
|
||||
|
||||
.configure = pn53x_configure,
|
||||
.device_set_property_bool = pn53x_set_property_bool,
|
||||
.device_set_property_int = pn53x_set_property_int,
|
||||
|
||||
.abort_command = NULL,
|
||||
.idle = NULL,
|
||||
.abort_command = NULL, // FIXME: abort is not supported in this driver
|
||||
.idle = NULL, // FIXME: idle is not supported in this driver
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -26,14 +26,14 @@
|
|||
|
||||
# include <nfc/nfc-types.h>
|
||||
|
||||
bool acr122_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound);
|
||||
bool acr122_probe (nfc_connstring connstrings[], size_t connstrings_len, size_t *pszDeviceFound);
|
||||
|
||||
// Functions used by developer to handle connection to this device
|
||||
nfc_device_t *acr122_connect (const nfc_device_desc_t * pndd);
|
||||
bool acr122_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData, struct timeval *timeout);
|
||||
int acr122_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szData, struct timeval *timeout);
|
||||
void acr122_disconnect (nfc_device_t * pnd);
|
||||
nfc_device *acr122_open (const nfc_connstring connstring);
|
||||
int acr122_send (nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int timeout);
|
||||
int acr122_receive (nfc_device *pnd, uint8_t *pbtData, const size_t szData, int timeout);
|
||||
void acr122_close (nfc_device *pnd);
|
||||
|
||||
extern const struct nfc_driver_t acr122_driver;
|
||||
extern const struct nfc_driver acr122_driver;
|
||||
|
||||
#endif // ! __NFC_DRIVER_ACR122_H__
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@
|
|||
#include "acr122s.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
|
@ -46,7 +49,7 @@
|
|||
|
||||
struct acr122s_data {
|
||||
serial_port port;
|
||||
byte_t seq;
|
||||
uint8_t seq;
|
||||
#ifndef WIN32
|
||||
int abort_fds[2];
|
||||
#else
|
||||
|
|
@ -84,74 +87,74 @@ enum {
|
|||
#pragma pack(push, 1)
|
||||
|
||||
struct icc_power_on_req {
|
||||
byte_t message_type;
|
||||
uint8_t message_type;
|
||||
uint32_t length;
|
||||
byte_t slot;
|
||||
byte_t seq;
|
||||
byte_t power_select;
|
||||
byte_t rfu[2];
|
||||
uint8_t slot;
|
||||
uint8_t seq;
|
||||
uint8_t power_select;
|
||||
uint8_t rfu[2];
|
||||
};
|
||||
|
||||
struct icc_power_on_res {
|
||||
byte_t message_type;
|
||||
uint8_t message_type;
|
||||
uint32_t length;
|
||||
byte_t slot;
|
||||
byte_t seq;
|
||||
byte_t status;
|
||||
byte_t error;
|
||||
byte_t chain_parameter;
|
||||
uint8_t slot;
|
||||
uint8_t seq;
|
||||
uint8_t status;
|
||||
uint8_t error;
|
||||
uint8_t chain_parameter;
|
||||
};
|
||||
|
||||
struct icc_power_off_req {
|
||||
byte_t message_type;
|
||||
uint8_t message_type;
|
||||
uint32_t length;
|
||||
byte_t slot;
|
||||
byte_t seq;
|
||||
byte_t rfu[3];
|
||||
uint8_t slot;
|
||||
uint8_t seq;
|
||||
uint8_t rfu[3];
|
||||
};
|
||||
|
||||
struct icc_power_off_res {
|
||||
byte_t message_type;
|
||||
uint8_t message_type;
|
||||
uint32_t length;
|
||||
byte_t slot;
|
||||
byte_t seq;
|
||||
byte_t status;
|
||||
byte_t error;
|
||||
byte_t clock_status;
|
||||
uint8_t slot;
|
||||
uint8_t seq;
|
||||
uint8_t status;
|
||||
uint8_t error;
|
||||
uint8_t clock_status;
|
||||
};
|
||||
|
||||
struct xfr_block_req {
|
||||
byte_t message_type;
|
||||
uint8_t message_type;
|
||||
uint32_t length;
|
||||
byte_t slot;
|
||||
byte_t seq;
|
||||
byte_t bwi;
|
||||
byte_t rfu[2];
|
||||
uint8_t slot;
|
||||
uint8_t seq;
|
||||
uint8_t bwi;
|
||||
uint8_t rfu[2];
|
||||
};
|
||||
|
||||
struct xfr_block_res {
|
||||
byte_t message_type;
|
||||
uint8_t message_type;
|
||||
uint32_t length;
|
||||
byte_t slot;
|
||||
byte_t seq;
|
||||
byte_t status;
|
||||
byte_t error;
|
||||
byte_t chain_parameter;
|
||||
uint8_t slot;
|
||||
uint8_t seq;
|
||||
uint8_t status;
|
||||
uint8_t error;
|
||||
uint8_t chain_parameter;
|
||||
};
|
||||
|
||||
struct apdu_header {
|
||||
byte_t class;
|
||||
byte_t ins;
|
||||
byte_t p1;
|
||||
byte_t p2;
|
||||
byte_t length;
|
||||
uint8_t class;
|
||||
uint8_t ins;
|
||||
uint8_t p1;
|
||||
uint8_t p2;
|
||||
uint8_t length;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#define TRACE do { printf("%s:%d\n", __func__, __LINE__); } while (0)
|
||||
|
||||
#define DRIVER_DATA(dev) ((struct acr122s_data *) (dev->driver_data))
|
||||
#define DRIVER_DATA(pnd) ((struct acr122s_data *) (pnd->driver_data))
|
||||
|
||||
/**
|
||||
* Print a debuggin hex string to stdout.
|
||||
|
|
@ -162,7 +165,7 @@ struct apdu_header {
|
|||
*/
|
||||
#if 0
|
||||
static void
|
||||
print_hex(const char *caption, byte_t *buf, size_t buf_len)
|
||||
print_hex(const char *caption, uint8_t *buf, size_t buf_len)
|
||||
{
|
||||
printf("%s:", caption);
|
||||
for (size_t i = 0; i < buf_len; i++) {
|
||||
|
|
@ -179,53 +182,55 @@ print_hex(const char *caption, byte_t *buf, size_t buf_len)
|
|||
* @note command frame length (uint32_t at offset 2) should be valid
|
||||
*/
|
||||
static void
|
||||
acr122s_fix_frame(byte_t *frame)
|
||||
acr122s_fix_frame(uint8_t *frame)
|
||||
{
|
||||
size_t frame_size = FRAME_SIZE(frame);
|
||||
frame[0] = STX;
|
||||
frame[frame_size - 1] = ETX;
|
||||
|
||||
byte_t *csum = frame + frame_size - 2;
|
||||
uint8_t *csum = frame + frame_size - 2;
|
||||
*csum = 0;
|
||||
for (byte_t *p = frame + 1; p < csum; p++)
|
||||
for (uint8_t *p = frame + 1; p < csum; p++)
|
||||
*csum ^= *p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a command frame to ACR122S and check its ACK status.
|
||||
*
|
||||
* @param: dev is target nfc device
|
||||
* @param: pnd is target nfc device
|
||||
* @param: cmd is command frame to send
|
||||
* @param: timeout
|
||||
* @return 0 if success
|
||||
*/
|
||||
static int
|
||||
acr122s_send_frame(nfc_device_t *dev, byte_t *frame, struct timeval *timeout)
|
||||
acr122s_send_frame(nfc_device *pnd, uint8_t *frame, int timeout)
|
||||
{
|
||||
size_t frame_size = FRAME_SIZE(frame);
|
||||
byte_t ack[4];
|
||||
byte_t positive_ack[4] = { STX, 0, 0, ETX };
|
||||
serial_port port = DRIVER_DATA(dev)->port;
|
||||
uint8_t ack[4];
|
||||
uint8_t positive_ack[4] = { STX, 0, 0, ETX };
|
||||
serial_port port = DRIVER_DATA(pnd)->port;
|
||||
int ret;
|
||||
void *abort_p;
|
||||
|
||||
#ifndef WIN32
|
||||
abort_p = &(DRIVER_DATA(dev)->abort_fds[1]);
|
||||
abort_p = &(DRIVER_DATA(pnd)->abort_fds[1]);
|
||||
#else
|
||||
abort_p = &(DRIVER_DATA(dev)->abort_flag);
|
||||
abort_p = &(DRIVER_DATA(pnd)->abort_flag);
|
||||
#endif
|
||||
|
||||
if ((ret = uart_send(port, frame, frame_size, timeout)) != 0)
|
||||
if ((ret = uart_send(port, frame, frame_size, timeout)) < 0)
|
||||
return ret;
|
||||
|
||||
if ((ret = uart_receive(port, ack, 4, abort_p, timeout)) != 0)
|
||||
if ((ret = uart_receive(port, ack, 4, abort_p, timeout)) < 0)
|
||||
return ret;
|
||||
|
||||
if (memcmp(ack, positive_ack, 4) != 0)
|
||||
return ECOMIO;
|
||||
if (memcmp(ack, positive_ack, 4) != 0){
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
struct xfr_block_req *req = (struct xfr_block_req *) &frame[1];
|
||||
DRIVER_DATA(dev)->seq = req->seq + 1;
|
||||
DRIVER_DATA(pnd)->seq = req->seq + 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -233,7 +238,7 @@ acr122s_send_frame(nfc_device_t *dev, byte_t *frame, struct timeval *timeout)
|
|||
/**
|
||||
* Receive response frame after a successfull acr122s_send_command().
|
||||
*
|
||||
* @param: dev is target nfc device
|
||||
* @param: pnd is target nfc device
|
||||
* @param: frame is buffer where received response frame will be stored
|
||||
* @param: frame_size is frame size
|
||||
* @param: abort_p
|
||||
|
|
@ -243,29 +248,33 @@ acr122s_send_frame(nfc_device_t *dev, byte_t *frame, struct timeval *timeout)
|
|||
* @return 0 if success
|
||||
*/
|
||||
static int
|
||||
acr122s_recv_frame(nfc_device_t *dev, byte_t *frame, size_t frame_size, void *abort_p, struct timeval *timeout)
|
||||
acr122s_recv_frame(nfc_device *pnd, uint8_t *frame, size_t frame_size, void *abort_p, int timeout)
|
||||
{
|
||||
if (frame_size < 13)
|
||||
return EINVALARG;
|
||||
pnd->last_error = NFC_EINVARG;
|
||||
return pnd->last_error;
|
||||
|
||||
int ret;
|
||||
serial_port port = DRIVER_DATA(dev)->port;
|
||||
serial_port port = DRIVER_DATA(pnd)->port;
|
||||
|
||||
if ((ret = uart_receive(port, frame, 11, abort_p, timeout)) != 0)
|
||||
return ret;
|
||||
|
||||
// Is buffer sufficient to store response?
|
||||
if (frame_size < FRAME_SIZE(frame))
|
||||
return ECOMIO;
|
||||
if (frame_size < FRAME_SIZE(frame)){
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
size_t remaining = FRAME_SIZE(frame) - 11;
|
||||
if ((ret = uart_receive(port, frame + 11, remaining, abort_p, timeout)) != 0)
|
||||
return ret;
|
||||
|
||||
struct xfr_block_res *res = (struct xfr_block_res *) &frame[1];
|
||||
if ((byte_t) (res->seq + 1) != DRIVER_DATA(dev)->seq) {
|
||||
if ((uint8_t) (res->seq + 1) != DRIVER_DATA(pnd)->seq) {
|
||||
log_put(LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Invalid response sequence number.");
|
||||
return ECOMIO;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -279,7 +288,7 @@ acr122s_recv_frame(nfc_device_t *dev, byte_t *frame, size_t frame_size, void *ab
|
|||
static uint32_t
|
||||
le32(uint32_t val) {
|
||||
uint32_t res;
|
||||
byte_t *p = (byte_t *) &res;
|
||||
uint8_t *p = (uint8_t *) &res;
|
||||
p[0] = val;
|
||||
p[1] = val >> 8;
|
||||
p[2] = val >> 16;
|
||||
|
|
@ -290,7 +299,7 @@ le32(uint32_t val) {
|
|||
/**
|
||||
* Build an ACR122S command frame from a PN532 command.
|
||||
*
|
||||
* @param dev is device for which the command frame will be generated
|
||||
* @param pnd is device for which the command frame will be generated
|
||||
* @param frame is where the resulting command frame will be generated
|
||||
* @param frame_size is the passed command frame size
|
||||
* @param p1
|
||||
|
|
@ -302,9 +311,9 @@ le32(uint32_t val) {
|
|||
* @return true if frame built successfully
|
||||
*/
|
||||
static bool
|
||||
acr122s_build_frame(nfc_device_t *dev,
|
||||
byte_t *frame, size_t frame_size, byte_t p1, byte_t p2,
|
||||
const byte_t *data, size_t data_size, int should_prefix)
|
||||
acr122s_build_frame(nfc_device *pnd,
|
||||
uint8_t *frame, size_t frame_size, uint8_t p1, uint8_t p2,
|
||||
const uint8_t *data, size_t data_size, int should_prefix)
|
||||
{
|
||||
if (frame_size < data_size + APDU_OVERHEAD + should_prefix)
|
||||
return false;
|
||||
|
|
@ -315,7 +324,7 @@ acr122s_build_frame(nfc_device_t *dev,
|
|||
req->message_type = XFR_BLOCK_REQ_MSG;
|
||||
req->length = le32(5 + data_size + should_prefix);
|
||||
req->slot = 0;
|
||||
req->seq = DRIVER_DATA(dev)->seq;
|
||||
req->seq = DRIVER_DATA(pnd)->seq;
|
||||
req->bwi = 0;
|
||||
req->rfu[0] = 0;
|
||||
req->rfu[1] = 0;
|
||||
|
|
@ -327,7 +336,7 @@ acr122s_build_frame(nfc_device_t *dev,
|
|||
header->p2 = p2;
|
||||
header->length = data_size + should_prefix;
|
||||
|
||||
byte_t *buf = (byte_t *) &frame[16];
|
||||
uint8_t *buf = (uint8_t *) &frame[16];
|
||||
if (should_prefix)
|
||||
*buf++ = 0xD4;
|
||||
memcpy(buf, data, data_size);
|
||||
|
|
@ -337,61 +346,61 @@ acr122s_build_frame(nfc_device_t *dev,
|
|||
}
|
||||
|
||||
static int
|
||||
acr122s_activate_sam(nfc_device_t *dev)
|
||||
acr122s_activate_sam(nfc_device *pnd)
|
||||
{
|
||||
byte_t cmd[13];
|
||||
uint8_t cmd[13];
|
||||
memset(cmd, 0, sizeof(cmd));
|
||||
cmd[1] = ICC_POWER_ON_REQ_MSG;
|
||||
acr122s_fix_frame(cmd);
|
||||
|
||||
byte_t resp[MAX_FRAME_SIZE];
|
||||
uint8_t resp[MAX_FRAME_SIZE];
|
||||
int ret;
|
||||
|
||||
if ((ret = acr122s_send_frame(dev, cmd, 0)) != 0)
|
||||
if ((ret = acr122s_send_frame(pnd, cmd, 0)) != 0)
|
||||
return ret;
|
||||
|
||||
if ((ret = acr122s_recv_frame(dev, resp, MAX_FRAME_SIZE, 0, 0)) != 0)
|
||||
if ((ret = acr122s_recv_frame(pnd, resp, MAX_FRAME_SIZE, 0, 0)) != 0)
|
||||
return ret;
|
||||
|
||||
CHIP_DATA(dev)->power_mode = NORMAL;
|
||||
CHIP_DATA(pnd)->power_mode = NORMAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
acr122s_deactivate_sam(nfc_device_t *dev)
|
||||
acr122s_deactivate_sam(nfc_device *pnd)
|
||||
{
|
||||
byte_t cmd[13];
|
||||
uint8_t cmd[13];
|
||||
memset(cmd, 0, sizeof(cmd));
|
||||
cmd[1] = ICC_POWER_OFF_REQ_MSG;
|
||||
acr122s_fix_frame(cmd);
|
||||
|
||||
byte_t resp[MAX_FRAME_SIZE];
|
||||
uint8_t resp[MAX_FRAME_SIZE];
|
||||
int ret;
|
||||
|
||||
if ((ret = acr122s_send_frame(dev, cmd, 0)) != 0)
|
||||
if ((ret = acr122s_send_frame(pnd, cmd, 0)) != 0)
|
||||
return ret;
|
||||
|
||||
if ((ret = acr122s_recv_frame(dev, resp, MAX_FRAME_SIZE, 0, 0)) != 0)
|
||||
if ((ret = acr122s_recv_frame(pnd, resp, MAX_FRAME_SIZE, 0, 0)) != 0)
|
||||
return ret;
|
||||
|
||||
CHIP_DATA(dev)->power_mode = LOWVBAT;
|
||||
CHIP_DATA(pnd)->power_mode = LOWVBAT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
acr122s_get_firmware_version(nfc_device_t *dev, char *version, size_t length)
|
||||
acr122s_get_firmware_version(nfc_device *pnd, char *version, size_t length)
|
||||
{
|
||||
int ret;
|
||||
byte_t cmd[MAX_FRAME_SIZE];
|
||||
uint8_t cmd[MAX_FRAME_SIZE];
|
||||
|
||||
acr122s_build_frame(dev, cmd, sizeof(cmd), 0x48, 0, NULL, 0, 0);
|
||||
acr122s_build_frame(pnd, cmd, sizeof(cmd), 0x48, 0, NULL, 0, 0);
|
||||
|
||||
if ((ret = acr122s_send_frame(dev, cmd, 0)) != 0)
|
||||
if ((ret = acr122s_send_frame(pnd, cmd, 0)) != 0)
|
||||
return ret;
|
||||
|
||||
if ((ret = acr122s_recv_frame(dev, cmd, sizeof(cmd), 0, 0)) != 0)
|
||||
if ((ret = acr122s_recv_frame(pnd, cmd, sizeof(cmd), 0, 0)) != 0)
|
||||
return ret;
|
||||
|
||||
size_t len = APDU_SIZE(cmd);
|
||||
|
|
@ -403,208 +412,277 @@ acr122s_get_firmware_version(nfc_device_t *dev, char *version, size_t length)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct acr122s_descriptor {
|
||||
char port[128];
|
||||
uint32_t speed;
|
||||
};
|
||||
|
||||
int
|
||||
acr122s_connstring_decode (const nfc_connstring connstring, struct acr122s_descriptor *desc)
|
||||
{
|
||||
char *cs = malloc (strlen (connstring) + 1);
|
||||
if (!cs) {
|
||||
perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
strcpy (cs, connstring);
|
||||
const char *driver_name = strtok (cs, ":");
|
||||
if (!driver_name) {
|
||||
// Parse error
|
||||
free (cs);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 != strcmp (driver_name, ACR122S_DRIVER_NAME)) {
|
||||
// Driver name does not match.
|
||||
free (cs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *port = strtok (NULL, ":");
|
||||
if (!port) {
|
||||
// Only driver name was specified (or parsing error)
|
||||
free (cs);
|
||||
return 1;
|
||||
}
|
||||
strncpy (desc->port, port, sizeof(desc->port)-1);
|
||||
desc->port[sizeof(desc->port)-1] = '\0';
|
||||
|
||||
const char *speed_s = strtok (NULL, ":");
|
||||
if (!speed_s) {
|
||||
// speed not specified (or parsing error)
|
||||
free (cs);
|
||||
return 2;
|
||||
}
|
||||
unsigned long speed;
|
||||
if (sscanf (speed_s, "%lu", &speed) != 1) {
|
||||
// speed_s is not a number
|
||||
free (cs);
|
||||
return 2;
|
||||
}
|
||||
desc->speed = speed;
|
||||
|
||||
free (cs);
|
||||
return 3;
|
||||
}
|
||||
|
||||
bool
|
||||
acr122s_probe(nfc_device_desc_t descs[], size_t desc_count, size_t *dev_found)
|
||||
acr122s_probe(nfc_connstring connstrings[], size_t connstrings_len, size_t *pszDeviceFound)
|
||||
{
|
||||
/** @note: Due to UART bus we can't know if its really an ACR122S without
|
||||
* sending some commands. But using this way to probe devices, we can
|
||||
* have serious problem with other device on this bus */
|
||||
#ifndef SERIAL_AUTOPROBE_ENABLED
|
||||
(void) descs;
|
||||
(void) desc_count;
|
||||
*dev_found = 0;
|
||||
(void) connstrings;
|
||||
(void) connstrings_len;
|
||||
*pszDeviceFound = 0;
|
||||
log_put(LOG_CATEGORY, NFC_PRIORITY_INFO, "Serial auto-probing have been disabled at compile time. Skipping autoprobe.");
|
||||
return false;
|
||||
#else /* SERIAL_AUTOPROBE_ENABLED */
|
||||
*dev_found = 0;
|
||||
char **ports = uart_list_ports();
|
||||
for (int i = 0; ports[i]; i++) {
|
||||
char *port = ports[i];
|
||||
serial_port sp = uart_open(port);
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Trying to find ACR122S device on serial port: %s at %d bauds.", port, ACR122S_DEFAULT_SPEED);
|
||||
*pszDeviceFound = 0;
|
||||
|
||||
serial_port sp;
|
||||
char **acPorts = uart_list_ports ();
|
||||
const char *acPort;
|
||||
int iDevice = 0;
|
||||
|
||||
while ((acPort = acPorts[iDevice++])) {
|
||||
sp = uart_open (acPort);
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Trying to find ACR122S device on serial port: %s at %d bauds.", acPort, ACR122S_DEFAULT_SPEED);
|
||||
|
||||
if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) {
|
||||
uart_flush_input(sp);
|
||||
uart_set_speed(sp, ACR122S_DEFAULT_SPEED);
|
||||
// We need to flush input to be sure first reply does not comes from older byte transceive
|
||||
uart_flush_input (sp);
|
||||
uart_set_speed (sp, ACR122S_DEFAULT_SPEED);
|
||||
|
||||
nfc_device_t *dev = nfc_device_new();
|
||||
dev->driver = &acr122s_driver;
|
||||
nfc_connstring connstring;
|
||||
snprintf (connstring, sizeof(nfc_connstring), "%s:%s:%"PRIu32, ACR122S_DRIVER_NAME, acPort, ACR122S_DEFAULT_SPEED);
|
||||
nfc_device *pnd = nfc_device_new (connstring);
|
||||
|
||||
dev->driver_data = malloc(sizeof(struct acr122s_data));
|
||||
DRIVER_DATA(dev)->port = sp;
|
||||
DRIVER_DATA(dev)->seq = 0;
|
||||
pnd->driver = &acr122s_driver;
|
||||
pnd->driver_data = malloc(sizeof(struct acr122s_data));
|
||||
DRIVER_DATA (pnd)->port = sp;
|
||||
DRIVER_DATA(pnd)->seq = 0;
|
||||
|
||||
#ifndef WIN32
|
||||
pipe(DRIVER_DATA(dev)->abort_fds);
|
||||
pipe(DRIVER_DATA(pnd)->abort_fds);
|
||||
#else
|
||||
DRIVER_DATA(dev)->abort_flag = false;
|
||||
DRIVER_DATA(pnd)->abort_flag = false;
|
||||
#endif
|
||||
|
||||
pn53x_data_new(dev, &acr122s_io);
|
||||
CHIP_DATA(dev)->type = PN532;
|
||||
CHIP_DATA(dev)->power_mode = NORMAL;
|
||||
|
||||
pn53x_data_new(pnd, &acr122s_io);
|
||||
CHIP_DATA(pnd)->type = PN532;
|
||||
CHIP_DATA(pnd)->power_mode = NORMAL;
|
||||
|
||||
char version[32];
|
||||
int ret = acr122s_get_firmware_version(dev, version, sizeof(version));
|
||||
int ret = acr122s_get_firmware_version(pnd, version, sizeof(version));
|
||||
if (ret == 0 && strncmp("ACR122S", version, 7) != 0) {
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
pn53x_data_free(dev);
|
||||
nfc_device_free(dev);
|
||||
pn53x_data_free(pnd);
|
||||
nfc_device_free(pnd);
|
||||
uart_close(sp);
|
||||
|
||||
if (ret != 0)
|
||||
continue;
|
||||
|
||||
nfc_device_desc_t *desc = &descs[(*dev_found)++];
|
||||
snprintf(desc->acDevice, DEVICE_NAME_LENGTH - 1, "%s (%s)", ACR122S_DRIVER_NAME, port);
|
||||
desc->pcDriver = ACR122S_DRIVER_NAME;
|
||||
strncpy(desc->acPort, port, DEVICE_PORT_LENGTH - 1);
|
||||
desc->acPort[DEVICE_PORT_LENGTH - 1] = '\0';
|
||||
desc->uiSpeed = ACR122S_DEFAULT_SPEED;
|
||||
|
||||
|
||||
// ACR122S reader is found
|
||||
memcpy (connstrings[*pszDeviceFound], connstring, sizeof(nfc_connstring));
|
||||
(*pszDeviceFound)++;
|
||||
|
||||
// Test if we reach the maximum "wanted" devices
|
||||
if (*dev_found >= desc_count)
|
||||
if (*pszDeviceFound >= connstrings_len)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; ports[i]; i++)
|
||||
free(ports[i]);
|
||||
free(ports);
|
||||
|
||||
return true;
|
||||
iDevice = 0;
|
||||
while ((acPort = acPorts[iDevice++])) {
|
||||
free ((void*)acPort);
|
||||
}
|
||||
free (acPorts);
|
||||
#endif /* SERIAL_AUTOPROBE_ENABLED */
|
||||
return true;
|
||||
}
|
||||
|
||||
nfc_device_t *
|
||||
acr122s_connect(const nfc_device_desc_t *desc)
|
||||
nfc_device *
|
||||
acr122s_open(const nfc_connstring connstring)
|
||||
{
|
||||
serial_port sp;
|
||||
nfc_device_t *dev;
|
||||
nfc_device *pnd;
|
||||
struct acr122s_descriptor ndd;
|
||||
int connstring_decode_level = acr122s_connstring_decode (connstring, &ndd);
|
||||
|
||||
if (connstring_decode_level < 2) {
|
||||
return NULL;
|
||||
}
|
||||
if (connstring_decode_level < 3) {
|
||||
ndd.speed = ACR122S_DEFAULT_SPEED;
|
||||
}
|
||||
|
||||
log_put(LOG_CATEGORY, NFC_PRIORITY_TRACE,
|
||||
"Attempt to connect to: %s at %d bauds.", desc->acPort, desc->uiSpeed);
|
||||
"Attempt to connect to: %s at %d bauds.", ndd.port, ndd.speed);
|
||||
|
||||
sp = uart_open(desc->acPort);
|
||||
sp = uart_open(ndd.port);
|
||||
if (sp == INVALID_SERIAL_PORT) {
|
||||
log_put(LOG_CATEGORY, NFC_PRIORITY_ERROR,
|
||||
"Invalid serial port: %s", desc->acPort);
|
||||
"Invalid serial port: %s", ndd.port);
|
||||
return NULL;
|
||||
}
|
||||
if (sp == CLAIMED_SERIAL_PORT) {
|
||||
log_put(LOG_CATEGORY, NFC_PRIORITY_ERROR,
|
||||
"Serial port already claimed: %s", desc->acPort);
|
||||
"Serial port already claimed: %s", ndd.port);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uart_flush_input(sp);
|
||||
uart_set_speed(sp, desc->uiSpeed);
|
||||
uart_set_speed(sp, ndd.speed);
|
||||
|
||||
dev = nfc_device_new();
|
||||
dev->driver = &acr122s_driver;
|
||||
strcpy(dev->acName, ACR122S_DRIVER_NAME);
|
||||
pnd = nfc_device_new(connstring);
|
||||
pnd->driver = &acr122s_driver;
|
||||
strcpy(pnd->name, ACR122S_DRIVER_NAME);
|
||||
|
||||
dev->driver_data = malloc(sizeof(struct acr122s_data));
|
||||
DRIVER_DATA(dev)->port = sp;
|
||||
DRIVER_DATA(dev)->seq = 0;
|
||||
pnd->driver_data = malloc(sizeof(struct acr122s_data));
|
||||
DRIVER_DATA(pnd)->port = sp;
|
||||
DRIVER_DATA(pnd)->seq = 0;
|
||||
|
||||
#ifndef WIN32
|
||||
pipe(DRIVER_DATA(dev)->abort_fds);
|
||||
pipe(DRIVER_DATA(pnd)->abort_fds);
|
||||
#else
|
||||
DRIVER_DATA(dev)->abort_flag = false;
|
||||
DRIVER_DATA(pnd)->abort_flag = false;
|
||||
#endif
|
||||
|
||||
pn53x_data_new(dev, &acr122s_io);
|
||||
CHIP_DATA(dev)->type = PN532;
|
||||
pn53x_data_new(pnd, &acr122s_io);
|
||||
CHIP_DATA(pnd)->type = PN532;
|
||||
|
||||
#if 1
|
||||
// Retrieve firmware version
|
||||
char version[DEVICE_NAME_LENGTH];
|
||||
if (acr122s_get_firmware_version(dev, version, sizeof(version)) != 0) {
|
||||
if (acr122s_get_firmware_version(pnd, version, sizeof(version)) != 0) {
|
||||
log_put(LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Cannot get reader firmware.");
|
||||
acr122s_disconnect(dev);
|
||||
acr122s_close(pnd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strncmp(version, "ACR122S", 7) != 0) {
|
||||
log_put(LOG_CATEGORY, NFC_PRIORITY_ERROR, "Invalid firmware version: %s",
|
||||
version);
|
||||
acr122s_disconnect(dev);
|
||||
acr122s_close(pnd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snprintf(dev->acName, sizeof(dev->acName), "%s", version);
|
||||
snprintf(pnd->name, sizeof(pnd->name), "%s", version);
|
||||
|
||||
// Activate SAM before operating
|
||||
if (acr122s_activate_sam(dev) != 0) {
|
||||
if (acr122s_activate_sam(pnd) != 0) {
|
||||
log_put(LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Cannot activate SAM.");
|
||||
acr122s_disconnect(dev);
|
||||
acr122s_close(pnd);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!pn53x_init(dev)) {
|
||||
if (!pn53x_init(pnd)) {
|
||||
log_put(LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Failed initializing PN532 chip.");
|
||||
acr122s_disconnect(dev);
|
||||
acr122s_close(pnd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dev;
|
||||
return pnd;
|
||||
}
|
||||
|
||||
void
|
||||
acr122s_disconnect (nfc_device_t *dev)
|
||||
acr122s_close (nfc_device *pnd)
|
||||
{
|
||||
acr122s_deactivate_sam(dev);
|
||||
uart_close(DRIVER_DATA(dev)->port);
|
||||
acr122s_deactivate_sam(pnd);
|
||||
uart_close(DRIVER_DATA(pnd)->port);
|
||||
|
||||
#ifndef WIN32
|
||||
// Release file descriptors used for abort mecanism
|
||||
close (DRIVER_DATA(dev)->abort_fds[0]);
|
||||
close (DRIVER_DATA(dev)->abort_fds[1]);
|
||||
close (DRIVER_DATA(pnd)->abort_fds[0]);
|
||||
close (DRIVER_DATA(pnd)->abort_fds[1]);
|
||||
#endif
|
||||
|
||||
pn53x_data_free(dev);
|
||||
nfc_device_free(dev);
|
||||
}
|
||||
|
||||
bool
|
||||
acr122s_send(nfc_device_t *dev, const byte_t *buf, const size_t buf_len, struct timeval *timeout)
|
||||
{
|
||||
uart_flush_input(DRIVER_DATA(dev)->port);
|
||||
|
||||
byte_t cmd[MAX_FRAME_SIZE];
|
||||
acr122s_build_frame(dev, cmd, sizeof(cmd), 0, 0, buf, buf_len, 1);
|
||||
int ret;
|
||||
if ((ret = acr122s_send_frame(dev, cmd, timeout)) != 0) {
|
||||
log_put(LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Unable to transmit data. (TX)");
|
||||
dev->iLastError = ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
pn53x_data_free(pnd);
|
||||
nfc_device_free(pnd);
|
||||
}
|
||||
|
||||
int
|
||||
acr122s_receive(nfc_device_t *dev, byte_t *buf, size_t buf_len, struct timeval *timeout)
|
||||
acr122s_send(nfc_device *pnd, const uint8_t *buf, const size_t buf_len, int timeout)
|
||||
{
|
||||
uart_flush_input(DRIVER_DATA(pnd)->port);
|
||||
|
||||
uint8_t cmd[MAX_FRAME_SIZE];
|
||||
acr122s_build_frame(pnd, cmd, sizeof(cmd), 0, 0, buf, buf_len, 1);
|
||||
int ret;
|
||||
if ((ret = acr122s_send_frame(pnd, cmd, timeout)) != 0) {
|
||||
log_put(LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Unable to transmit data. (TX)");
|
||||
pnd->last_error = ret;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
return NFC_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
acr122s_receive(nfc_device *pnd, uint8_t *buf, size_t buf_len, int timeout)
|
||||
{
|
||||
void *abort_p;
|
||||
|
||||
#ifndef WIN32
|
||||
abort_p = &(DRIVER_DATA(dev)->abort_fds[1]);
|
||||
abort_p = &(DRIVER_DATA(pnd)->abort_fds[1]);
|
||||
#else
|
||||
abort_p = &(DRIVER_DATA(dev)->abort_flag);
|
||||
abort_p = &(DRIVER_DATA(pnd)->abort_flag);
|
||||
#endif
|
||||
|
||||
byte_t tmp[MAX_FRAME_SIZE];
|
||||
dev->iLastError = acr122s_recv_frame(dev, tmp, sizeof(tmp), abort_p, timeout);
|
||||
uint8_t tmp[MAX_FRAME_SIZE];
|
||||
pnd->last_error = acr122s_recv_frame(pnd, tmp, sizeof(tmp), abort_p, timeout);
|
||||
|
||||
if (abort_p && (EOPABORT == dev->iLastError))
|
||||
return -1;
|
||||
if (abort_p && (NFC_EOPABORTED == pnd->last_error)) {
|
||||
pnd->last_error = NFC_EOPABORTED;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
if (dev->iLastError != 0) {
|
||||
if (pnd->last_error < 0) {
|
||||
log_put(LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)");
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -612,27 +690,27 @@ acr122s_receive(nfc_device_t *dev, byte_t *buf, size_t buf_len, struct timeval *
|
|||
size_t data_len = FRAME_SIZE(tmp) - 17;
|
||||
if (data_len > buf_len) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Receive buffer too small. (buf_len: %zu, data_len: %zu)", buf_len, data_len);
|
||||
dev->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
memcpy(buf, tmp + 13, data_len);
|
||||
return data_len;
|
||||
}
|
||||
|
||||
bool
|
||||
acr122s_abort_command(nfc_device_t *dev)
|
||||
int
|
||||
acr122s_abort_command(nfc_device *pnd)
|
||||
{
|
||||
if (dev) {
|
||||
if (pnd) {
|
||||
#ifndef WIN32
|
||||
close(DRIVER_DATA(dev)->abort_fds[0]);
|
||||
close(DRIVER_DATA(dev)->abort_fds[1]);
|
||||
pipe(DRIVER_DATA(dev)->abort_fds);
|
||||
close(DRIVER_DATA(pnd)->abort_fds[0]);
|
||||
close(DRIVER_DATA(pnd)->abort_fds[1]);
|
||||
pipe(DRIVER_DATA(pnd)->abort_fds);
|
||||
#else
|
||||
DRIVER_DATA(dev)->abort_flag = true;
|
||||
DRIVER_DATA(pnd)->abort_flag = true;
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
return NFC_SUCCESS;
|
||||
}
|
||||
|
||||
const struct pn53x_io acr122s_io = {
|
||||
|
|
@ -640,11 +718,11 @@ const struct pn53x_io acr122s_io = {
|
|||
.receive = acr122s_receive,
|
||||
};
|
||||
|
||||
const struct nfc_driver_t acr122s_driver = {
|
||||
const struct nfc_driver acr122s_driver = {
|
||||
.name = ACR122S_DRIVER_NAME,
|
||||
.probe = acr122s_probe,
|
||||
.connect = acr122s_connect,
|
||||
.disconnect = acr122s_disconnect,
|
||||
.open = acr122s_open,
|
||||
.close = acr122s_close,
|
||||
.strerror = pn53x_strerror,
|
||||
|
||||
.initiator_init = pn53x_initiator_init,
|
||||
|
|
@ -663,7 +741,8 @@ const struct nfc_driver_t acr122s_driver = {
|
|||
.target_send_bits = pn53x_target_send_bits,
|
||||
.target_receive_bits = pn53x_target_receive_bits,
|
||||
|
||||
.configure = pn53x_configure,
|
||||
.device_set_property_bool = pn53x_set_property_bool,
|
||||
.device_set_property_int = pn53x_set_property_int,
|
||||
|
||||
.abort_command = acr122s_abort_command,
|
||||
.idle = NULL,
|
||||
|
|
|
|||
|
|
@ -28,14 +28,14 @@
|
|||
#include <sys/time.h>
|
||||
#include <nfc/nfc-types.h>
|
||||
|
||||
bool acr122s_probe(nfc_device_desc_t descs[], size_t desc_count, size_t *dev_found);
|
||||
bool acr122s_probe(nfc_connstring connstrings[], size_t connstrings_len, size_t *pszDeviceFound);
|
||||
|
||||
nfc_device_t *acr122s_connect(const nfc_device_desc_t *desc);
|
||||
void acr122s_disconnect(nfc_device_t *dev);
|
||||
nfc_device *acr122s_open(const nfc_connstring connstring);
|
||||
void acr122s_close(nfc_device *pnd);
|
||||
|
||||
bool acr122s_send(nfc_device_t *dev, const byte_t *buf, size_t buf_len, struct timeval *timeout);
|
||||
int acr122s_receive(nfc_device_t *dev, byte_t *buf, size_t buf_len, struct timeval *timeout);
|
||||
int acr122s_send(nfc_device *pnd, const uint8_t *buf, size_t buf_len, int timeout);
|
||||
int acr122s_receive(nfc_device *pnd, uint8_t *buf, size_t buf_len, int timeout);
|
||||
|
||||
extern const struct nfc_driver_t acr122s_driver;
|
||||
extern const struct nfc_driver acr122s_driver;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@
|
|||
* This driver can handle ARYGON readers that use UART as bus.
|
||||
* UART connection can be direct (host<->arygon_uc) or could be provided by internal USB to serial interface (e.g. host<->ftdi_chip<->arygon_uc)
|
||||
*/
|
||||
|
||||
/* vim: set ts=2 sw=2 et: */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif // HAVE_CONFIG_H
|
||||
|
|
@ -33,6 +36,7 @@
|
|||
#include "arygon.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include <string.h>
|
||||
|
|
@ -64,7 +68,7 @@
|
|||
#define DEV_ARYGON_PROTOCOL_TAMA_WAB '3'
|
||||
|
||||
#define ARYGON_DEFAULT_SPEED 9600
|
||||
#define ARYGON_DRIVER_NAME "ARYGON"
|
||||
#define ARYGON_DRIVER_NAME "arygon"
|
||||
#define LOG_CATEGORY "libnfc.driver.arygon"
|
||||
|
||||
#define DRIVER_DATA(pnd) ((struct arygon_data*)(pnd->driver_data))
|
||||
|
|
@ -80,24 +84,24 @@ struct arygon_data {
|
|||
#endif
|
||||
};
|
||||
|
||||
static const byte_t arygon_error_none[] = "FF000000\x0d\x0a";
|
||||
static const byte_t arygon_error_incomplete_command[] = "FF0C0000\x0d\x0a";
|
||||
static const byte_t arygon_error_unknown_mode[] = "FF060000\x0d\x0a";
|
||||
static const uint8_t arygon_error_none[] = "FF000000\x0d\x0a";
|
||||
static const uint8_t arygon_error_incomplete_command[] = "FF0C0000\x0d\x0a";
|
||||
static const uint8_t arygon_error_unknown_mode[] = "FF060000\x0d\x0a";
|
||||
|
||||
bool arygon_reset_tama (nfc_device_t * pnd);
|
||||
void arygon_firmware (nfc_device_t * pnd, char * str);
|
||||
int arygon_reset_tama (nfc_device *pnd);
|
||||
void arygon_firmware (nfc_device *pnd, char *str);
|
||||
|
||||
bool
|
||||
arygon_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound)
|
||||
arygon_probe (nfc_connstring connstrings[], size_t connstrings_len, size_t *pszDeviceFound)
|
||||
{
|
||||
/** @note: Due to UART bus we can't know if its really an ARYGON without
|
||||
* sending some commands. But using this way to probe devices, we can
|
||||
* have serious problem with other device on this bus */
|
||||
#ifndef SERIAL_AUTOPROBE_ENABLED
|
||||
(void) pnddDevices;
|
||||
(void) szDevices;
|
||||
(void) connstrings;
|
||||
(void) connstrings_len;
|
||||
*pszDeviceFound = 0;
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "%s", "Serial auto-probing have been disabled at compile time. Skipping autoprobe.");
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_INFO, "Serial auto-probing have been disabled at compile time. Skipping autoprobe.");
|
||||
return false;
|
||||
#else /* SERIAL_AUTOPROBE_ENABLED */
|
||||
*pszDeviceFound = 0;
|
||||
|
|
@ -116,7 +120,10 @@ arygon_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDev
|
|||
uart_flush_input (sp);
|
||||
uart_set_speed (sp, ARYGON_DEFAULT_SPEED);
|
||||
|
||||
nfc_device_t *pnd = nfc_device_new ();
|
||||
nfc_connstring connstring;
|
||||
snprintf (connstring, sizeof(nfc_connstring), "%s:%s:%"PRIu32, ARYGON_DRIVER_NAME, acPort, ARYGON_DEFAULT_SPEED);
|
||||
nfc_device *pnd = nfc_device_new (connstring);
|
||||
|
||||
pnd->driver = &arygon_driver;
|
||||
pnd->driver_data = malloc(sizeof(struct arygon_data));
|
||||
DRIVER_DATA (pnd)->port = sp;
|
||||
|
|
@ -131,28 +138,22 @@ arygon_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDev
|
|||
DRIVER_DATA (pnd)->abort_flag = false;
|
||||
#endif
|
||||
|
||||
bool res = arygon_reset_tama (pnd);
|
||||
int res = arygon_reset_tama (pnd);
|
||||
pn53x_data_free (pnd);
|
||||
nfc_device_free (pnd);
|
||||
uart_close (sp);
|
||||
if(!res)
|
||||
if(res < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// ARYGON reader is found
|
||||
snprintf (pnddDevices[*pszDeviceFound].acDevice, DEVICE_NAME_LENGTH - 1, "%s (%s)", "Arygon", acPort);
|
||||
pnddDevices[*pszDeviceFound].pcDriver = ARYGON_DRIVER_NAME;
|
||||
strncpy (pnddDevices[*pszDeviceFound].acPort, acPort, DEVICE_PORT_LENGTH - 1); pnddDevices[*pszDeviceFound].acPort[DEVICE_PORT_LENGTH - 1] = '\0';
|
||||
pnddDevices[*pszDeviceFound].uiSpeed = ARYGON_DEFAULT_SPEED;
|
||||
memcpy (connstrings[*pszDeviceFound], connstring, sizeof(nfc_connstring));
|
||||
(*pszDeviceFound)++;
|
||||
|
||||
// Test if we reach the maximum "wanted" devices
|
||||
if ((*pszDeviceFound) >= szDevices)
|
||||
if ((*pszDeviceFound) >= connstrings_len)
|
||||
break;
|
||||
}
|
||||
if (sp == INVALID_SERIAL_PORT)
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Invalid serial port: %s", acPort);
|
||||
if (sp == CLAIMED_SERIAL_PORT)
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Serial port already claimed: %s", acPort);
|
||||
}
|
||||
iDevice = 0;
|
||||
while ((acPort = acPorts[iDevice++])) {
|
||||
|
|
@ -163,37 +164,100 @@ arygon_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDev
|
|||
return true;
|
||||
}
|
||||
|
||||
nfc_device_t *
|
||||
arygon_connect (const nfc_device_desc_t * pndd)
|
||||
{
|
||||
serial_port sp;
|
||||
nfc_device_t *pnd = NULL;
|
||||
struct arygon_descriptor {
|
||||
char port[128];
|
||||
uint32_t speed;
|
||||
};
|
||||
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Attempt to connect to: %s at %d bauds.", pndd->acPort, pndd->uiSpeed);
|
||||
sp = uart_open (pndd->acPort);
|
||||
int
|
||||
arygon_connstring_decode (const nfc_connstring connstring, struct arygon_descriptor *desc)
|
||||
{
|
||||
char *cs = malloc (strlen (connstring) + 1);
|
||||
if (!cs) {
|
||||
perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
strcpy (cs, connstring);
|
||||
const char *driver_name = strtok (cs, ":");
|
||||
if (!driver_name) {
|
||||
// Parse error
|
||||
free (cs);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 != strcmp (driver_name, ARYGON_DRIVER_NAME)) {
|
||||
// Driver name does not match.
|
||||
free (cs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *port = strtok (NULL, ":");
|
||||
if (!port) {
|
||||
// Only driver name was specified (or parsing error)
|
||||
free (cs);
|
||||
return 1;
|
||||
}
|
||||
strncpy (desc->port, port, sizeof(desc->port)-1);
|
||||
desc->port[sizeof(desc->port)-1] = '\0';
|
||||
|
||||
const char *speed_s = strtok (NULL, ":");
|
||||
if (!speed_s) {
|
||||
// speed not specified (or parsing error)
|
||||
free (cs);
|
||||
return 2;
|
||||
}
|
||||
unsigned long speed;
|
||||
if (sscanf (speed_s, "%lu", &speed) != 1) {
|
||||
// speed_s is not a number
|
||||
free (cs);
|
||||
return 2;
|
||||
}
|
||||
desc->speed = speed;
|
||||
|
||||
free (cs);
|
||||
return 3;
|
||||
}
|
||||
|
||||
nfc_device *
|
||||
arygon_open (const nfc_connstring connstring)
|
||||
{
|
||||
struct arygon_descriptor ndd;
|
||||
int connstring_decode_level = arygon_connstring_decode (connstring, &ndd);
|
||||
|
||||
if (connstring_decode_level < 2) {
|
||||
return NULL;
|
||||
}
|
||||
if (connstring_decode_level < 3) {
|
||||
ndd.speed = ARYGON_DEFAULT_SPEED;
|
||||
}
|
||||
serial_port sp;
|
||||
nfc_device *pnd = NULL;
|
||||
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Attempt to open: %s at %d bauds.", ndd.port, ndd.speed);
|
||||
sp = uart_open (ndd.port);
|
||||
|
||||
if (sp == INVALID_SERIAL_PORT)
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Invalid serial port: %s", pndd->acPort);
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Invalid serial port: %s", ndd.port);
|
||||
if (sp == CLAIMED_SERIAL_PORT)
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Serial port already claimed: %s", pndd->acPort);
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Serial port already claimed: %s", ndd.port);
|
||||
if ((sp == CLAIMED_SERIAL_PORT) || (sp == INVALID_SERIAL_PORT))
|
||||
return NULL;
|
||||
|
||||
// We need to flush input to be sure first reply does not comes from older byte transceive
|
||||
uart_flush_input (sp);
|
||||
uart_set_speed (sp, pndd->uiSpeed);
|
||||
uart_set_speed (sp, ndd.speed);
|
||||
|
||||
// We have a connection
|
||||
pnd = nfc_device_new ();
|
||||
strncpy (pnd->acName, pndd->acDevice, sizeof (pnd->acName));
|
||||
pnd = nfc_device_new (connstring);
|
||||
snprintf (pnd->name, sizeof (pnd->name), "%s:%s", ARYGON_DRIVER_NAME, ndd.port);
|
||||
|
||||
pnd->driver_data = malloc(sizeof(struct arygon_data));
|
||||
DRIVER_DATA (pnd)->port = sp;
|
||||
|
||||
|
||||
// Alloc and init chip's data
|
||||
pn53x_data_new (pnd, &arygon_tama_io);
|
||||
|
||||
// The PN53x chip connected to ARYGON MCU doesn't seems to be in LowVBat mode
|
||||
// The PN53x chip opened to ARYGON MCU doesn't seems to be in LowVBat mode
|
||||
CHIP_DATA (pnd)->power_mode = NORMAL;
|
||||
|
||||
// empirical tuning
|
||||
|
|
@ -208,16 +272,16 @@ arygon_connect (const nfc_device_desc_t * pndd)
|
|||
#endif
|
||||
|
||||
// Check communication using "Reset TAMA" command
|
||||
if (!arygon_reset_tama(pnd)) {
|
||||
nfc_device_free (pnd);
|
||||
if (arygon_reset_tama(pnd) < 0) {
|
||||
arygon_close (pnd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char arygon_firmware_version[10];
|
||||
arygon_firmware (pnd, arygon_firmware_version);
|
||||
char *pcName;
|
||||
pcName = strdup (pnd->acName);
|
||||
snprintf (pnd->acName, sizeof (pnd->acName), "%s %s", pcName, arygon_firmware_version);
|
||||
pcName = strdup (pnd->name);
|
||||
snprintf (pnd->name, sizeof (pnd->name), "%s %s", pcName, arygon_firmware_version);
|
||||
free (pcName);
|
||||
|
||||
pn53x_init(pnd);
|
||||
|
|
@ -225,7 +289,7 @@ arygon_connect (const nfc_device_desc_t * pndd)
|
|||
}
|
||||
|
||||
void
|
||||
arygon_disconnect (nfc_device_t * pnd)
|
||||
arygon_close (nfc_device *pnd)
|
||||
{
|
||||
// Release UART port
|
||||
uart_close (DRIVER_DATA (pnd)->port);
|
||||
|
|
@ -242,109 +306,108 @@ arygon_disconnect (nfc_device_t * pnd)
|
|||
|
||||
#define ARYGON_TX_BUFFER_LEN (PN53x_NORMAL_FRAME__DATA_MAX_LEN + PN53x_NORMAL_FRAME__OVERHEAD + 1)
|
||||
#define ARYGON_RX_BUFFER_LEN (PN53x_EXTENDED_FRAME__DATA_MAX_LEN + PN53x_EXTENDED_FRAME__OVERHEAD)
|
||||
bool
|
||||
arygon_tama_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData, struct timeval *timeout)
|
||||
int
|
||||
arygon_tama_send (nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int timeout)
|
||||
{
|
||||
int res = 0;
|
||||
// Before sending anything, we need to discard from any junk bytes
|
||||
uart_flush_input (DRIVER_DATA(pnd)->port);
|
||||
|
||||
byte_t abtFrame[ARYGON_TX_BUFFER_LEN] = { DEV_ARYGON_PROTOCOL_TAMA, 0x00, 0x00, 0xff }; // Every packet must start with "0x32 0x00 0x00 0xff"
|
||||
uint8_t abtFrame[ARYGON_TX_BUFFER_LEN] = { DEV_ARYGON_PROTOCOL_TAMA, 0x00, 0x00, 0xff }; // Every packet must start with "0x32 0x00 0x00 0xff"
|
||||
|
||||
size_t szFrame = 0;
|
||||
if (szData > PN53x_NORMAL_FRAME__DATA_MAX_LEN) {
|
||||
// ARYGON Reader with PN532 equipped does not support extended frame (bug in ARYGON firmware?)
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "ARYGON device does not support more than %d bytes as payload (requested: %zd)", PN53x_NORMAL_FRAME__DATA_MAX_LEN, szData);
|
||||
pnd->iLastError = EDEVNOTSUP;
|
||||
return false;
|
||||
pnd->last_error = NFC_EDEVNOTSUPP;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
if (!pn53x_build_frame (abtFrame + 1, &szFrame, pbtData, szData)) {
|
||||
pnd->iLastError = EINVALARG;
|
||||
return false;
|
||||
if ((res = pn53x_build_frame (abtFrame + 1, &szFrame, pbtData, szData)) < 0) {
|
||||
pnd->last_error = res;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
int res = uart_send (DRIVER_DATA (pnd)->port, abtFrame, szFrame + 1, timeout);
|
||||
if (res != 0) {
|
||||
if ((res = uart_send (DRIVER_DATA (pnd)->port, abtFrame, szFrame + 1, timeout)) != 0) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Unable to transmit data. (TX)");
|
||||
pnd->iLastError = res;
|
||||
return false;
|
||||
pnd->last_error = res;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
byte_t abtRxBuf[6];
|
||||
res = uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, sizeof (abtRxBuf), 0, timeout);
|
||||
if (res != 0) {
|
||||
uint8_t abtRxBuf[6];
|
||||
if ((res = uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, sizeof (abtRxBuf), 0, timeout)) != 0) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Unable to read ACK");
|
||||
pnd->iLastError = res;
|
||||
return false;
|
||||
pnd->last_error = res;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
if (pn53x_check_ack_frame (pnd, abtRxBuf, sizeof(abtRxBuf))) {
|
||||
if (pn53x_check_ack_frame (pnd, abtRxBuf, sizeof(abtRxBuf)) == 0) {
|
||||
// The PN53x is running the sent command
|
||||
} else if (0 == memcmp(arygon_error_unknown_mode, abtRxBuf, sizeof(abtRxBuf))) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Bad frame format." );
|
||||
// We have already read 6 bytes and arygon_error_unknown_mode is 10 bytes long
|
||||
// so we have to read 4 remaining bytes to be synchronized at the next receiving pass.
|
||||
uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, 4, 0, timeout);
|
||||
return false;
|
||||
pnd->last_error = uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, 4, 0, timeout);
|
||||
return pnd->last_error;
|
||||
} else {
|
||||
return false;
|
||||
return pnd->last_error;
|
||||
}
|
||||
return true;
|
||||
return NFC_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
arygon_abort (nfc_device_t *pnd)
|
||||
arygon_abort (nfc_device *pnd)
|
||||
{
|
||||
// Send a valid TAMA packet to wakup the PN53x (we will not have an answer, according to Arygon manual)
|
||||
byte_t dummy[] = { 0x32, 0x00, 0x00, 0xff, 0x09, 0xf7, 0xd4, 0x00, 0x00, 0x6c, 0x69, 0x62, 0x6e, 0x66, 0x63, 0xbe, 0x00 };
|
||||
uint8_t dummy[] = { 0x32, 0x00, 0x00, 0xff, 0x09, 0xf7, 0xd4, 0x00, 0x00, 0x6c, 0x69, 0x62, 0x6e, 0x66, 0x63, 0xbe, 0x00 };
|
||||
|
||||
uart_send (DRIVER_DATA (pnd)->port, dummy, sizeof (dummy), NULL);
|
||||
uart_send (DRIVER_DATA (pnd)->port, dummy, sizeof (dummy), 0);
|
||||
|
||||
// Using Arygon device we can't send ACK frame to abort the running command
|
||||
return (pn53x_check_communication (pnd)) ? 0 : -1;
|
||||
return pn53x_check_communication (pnd);
|
||||
}
|
||||
|
||||
int
|
||||
arygon_tama_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen, struct timeval *timeout)
|
||||
arygon_tama_receive (nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, int timeout)
|
||||
{
|
||||
byte_t abtRxBuf[5];
|
||||
uint8_t abtRxBuf[5];
|
||||
size_t len;
|
||||
void * abort_p = NULL;
|
||||
void *abort_p = NULL;
|
||||
|
||||
#ifndef WIN32
|
||||
abort_p = &(DRIVER_DATA (pnd)->iAbortFds[1]);
|
||||
#else
|
||||
abort_p = &(DRIVER_DATA (pnd)->abort_flag);
|
||||
abort_p = (void*)&(DRIVER_DATA (pnd)->abort_flag);
|
||||
#endif
|
||||
|
||||
pnd->iLastError = uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, 5, abort_p, timeout);
|
||||
pnd->last_error = uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, 5, abort_p, timeout);
|
||||
|
||||
if (abort_p && (EOPABORT == pnd->iLastError)) {
|
||||
if (abort_p && (NFC_EOPABORTED == pnd->last_error)) {
|
||||
arygon_abort (pnd);
|
||||
|
||||
/* iLastError got reset by arygon_abort() */
|
||||
pnd->iLastError = EOPABORT;
|
||||
return -1;
|
||||
/* last_error got reset by arygon_abort() */
|
||||
pnd->last_error = NFC_EOPABORTED;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
if (pnd->iLastError != 0) {
|
||||
if (pnd->last_error != 0) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)");
|
||||
return -1;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
const byte_t pn53x_preamble[3] = { 0x00, 0x00, 0xff };
|
||||
const uint8_t pn53x_preamble[3] = { 0x00, 0x00, 0xff };
|
||||
if (0 != (memcmp (abtRxBuf, pn53x_preamble, 3))) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Frame preamble+start code mismatch");
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
if ((0x01 == abtRxBuf[3]) && (0xff == abtRxBuf[4])) {
|
||||
// Error frame
|
||||
uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, 3, 0, timeout);
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Application level error detected");
|
||||
pnd->iLastError = EFRAISERRFRAME;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
} else if ((0xff == abtRxBuf[3]) && (0xff == abtRxBuf[4])) {
|
||||
// Extended frame
|
||||
// ARYGON devices does not support extended frame sending
|
||||
|
|
@ -354,8 +417,8 @@ arygon_tama_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLe
|
|||
if (256 != (abtRxBuf[3] + abtRxBuf[4])) {
|
||||
// TODO: Retry
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Length checksum mismatch");
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
// abtRxBuf[3] (LEN) include TFI + (CC+1)
|
||||
|
|
@ -364,85 +427,85 @@ arygon_tama_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLe
|
|||
|
||||
if (len > szDataLen) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Unable to receive data: buffer too small. (szDataLen: %zu, len: %zu)", szDataLen, len);
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
// TFI + PD0 (CC+1)
|
||||
pnd->iLastError = uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, 2, 0, timeout);
|
||||
if (pnd->iLastError != 0) {
|
||||
pnd->last_error = uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, 2, 0, timeout);
|
||||
if (pnd->last_error != 0) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)");
|
||||
return -1;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
if (abtRxBuf[0] != 0xD5) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "TFI Mismatch");
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
if (abtRxBuf[1] != CHIP_DATA (pnd)->ui8LastCommand + 1) {
|
||||
if (abtRxBuf[1] != CHIP_DATA (pnd)->last_command + 1) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Command Code verification failed");
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
if (len) {
|
||||
pnd->iLastError = uart_receive (DRIVER_DATA (pnd)->port, pbtData, len, 0, timeout);
|
||||
if (pnd->iLastError != 0) {
|
||||
pnd->last_error = uart_receive (DRIVER_DATA (pnd)->port, pbtData, len, 0, timeout);
|
||||
if (pnd->last_error != 0) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)");
|
||||
return -1;
|
||||
return pnd->last_error;
|
||||
}
|
||||
}
|
||||
|
||||
pnd->iLastError = uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, 2, 0, timeout);
|
||||
if (pnd->iLastError != 0) {
|
||||
pnd->last_error = uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, 2, 0, timeout);
|
||||
if (pnd->last_error != 0) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)");
|
||||
return -1;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
byte_t btDCS = (256 - 0xD5);
|
||||
btDCS -= CHIP_DATA (pnd)->ui8LastCommand + 1;
|
||||
uint8_t btDCS = (256 - 0xD5);
|
||||
btDCS -= CHIP_DATA (pnd)->last_command + 1;
|
||||
for (size_t szPos = 0; szPos < len; szPos++) {
|
||||
btDCS -= pbtData[szPos];
|
||||
}
|
||||
|
||||
if (btDCS != abtRxBuf[0]) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Data checksum mismatch");
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
if (0x00 != abtRxBuf[1]) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Frame postamble mismatch");
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
// The PN53x command is done and we successfully received the reply
|
||||
return len;
|
||||
}
|
||||
|
||||
void
|
||||
arygon_firmware (nfc_device_t * pnd, char * str)
|
||||
arygon_firmware (nfc_device *pnd, char *str)
|
||||
{
|
||||
const byte_t arygon_firmware_version_cmd[] = { DEV_ARYGON_PROTOCOL_ARYGON_ASCII, 'a', 'v' };
|
||||
byte_t abtRx[16];
|
||||
const uint8_t arygon_firmware_version_cmd[] = { DEV_ARYGON_PROTOCOL_ARYGON_ASCII, 'a', 'v' };
|
||||
uint8_t abtRx[16];
|
||||
size_t szRx = sizeof(abtRx);
|
||||
|
||||
|
||||
int res = uart_send (DRIVER_DATA (pnd)->port, arygon_firmware_version_cmd, sizeof (arygon_firmware_version_cmd), NULL);
|
||||
int res = uart_send (DRIVER_DATA (pnd)->port, arygon_firmware_version_cmd, sizeof (arygon_firmware_version_cmd), 0);
|
||||
if (res != 0) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Unable to send ARYGON firmware command.");
|
||||
return;
|
||||
}
|
||||
res = uart_receive (DRIVER_DATA (pnd)->port, abtRx, szRx, 0, NULL);
|
||||
res = uart_receive (DRIVER_DATA (pnd)->port, abtRx, szRx, 0, 0);
|
||||
if (res != 0) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Unable to retrieve ARYGON firmware version.");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 0 == memcmp (abtRx, arygon_error_none, 6)) {
|
||||
byte_t * p = abtRx + 6;
|
||||
uint8_t *p = abtRx + 6;
|
||||
unsigned int szData;
|
||||
sscanf ((const char*)p, "%02x%s", &szData, p);
|
||||
memcpy (str, p, szData);
|
||||
|
|
@ -450,37 +513,35 @@ arygon_firmware (nfc_device_t * pnd, char * str)
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
arygon_reset_tama (nfc_device_t * pnd)
|
||||
int
|
||||
arygon_reset_tama (nfc_device *pnd)
|
||||
{
|
||||
const byte_t arygon_reset_tama_cmd[] = { DEV_ARYGON_PROTOCOL_ARYGON_ASCII, 'a', 'r' };
|
||||
byte_t abtRx[10]; // Attempted response is 10 bytes long
|
||||
const uint8_t arygon_reset_tama_cmd[] = { DEV_ARYGON_PROTOCOL_ARYGON_ASCII, 'a', 'r' };
|
||||
uint8_t abtRx[10]; // Attempted response is 10 bytes long
|
||||
size_t szRx = sizeof(abtRx);
|
||||
int res;
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
uart_send (DRIVER_DATA (pnd)->port, arygon_reset_tama_cmd, sizeof (arygon_reset_tama_cmd), &tv);
|
||||
uart_send (DRIVER_DATA (pnd)->port, arygon_reset_tama_cmd, sizeof (arygon_reset_tama_cmd), 500);
|
||||
|
||||
// Two reply are possible from ARYGON device: arygon_error_none (ie. in case the byte is well-sent)
|
||||
// or arygon_error_unknown_mode (ie. in case of the first byte was bad-transmitted)
|
||||
res = uart_receive (DRIVER_DATA (pnd)->port, abtRx, szRx, 0, &tv);
|
||||
res = uart_receive (DRIVER_DATA (pnd)->port, abtRx, szRx, 0, 1000);
|
||||
if (res != 0) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "No reply to 'reset TAMA' command.");
|
||||
return false;
|
||||
pnd->last_error = res;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
if (0 != memcmp (abtRx, arygon_error_none, sizeof (arygon_error_none) - 1)) {
|
||||
return false;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
return true;
|
||||
return NFC_SUCCESS;
|
||||
}
|
||||
|
||||
bool
|
||||
arygon_abort_command (nfc_device_t * pnd)
|
||||
int
|
||||
arygon_abort_command (nfc_device *pnd)
|
||||
{
|
||||
if (pnd) {
|
||||
#ifndef WIN32
|
||||
|
|
@ -490,7 +551,7 @@ arygon_abort_command (nfc_device_t * pnd)
|
|||
DRIVER_DATA (pnd)->abort_flag = true;
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
return NFC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -499,12 +560,12 @@ const struct pn53x_io arygon_tama_io = {
|
|||
.receive = arygon_tama_receive,
|
||||
};
|
||||
|
||||
const struct nfc_driver_t arygon_driver = {
|
||||
.name = ARYGON_DRIVER_NAME,
|
||||
.probe = arygon_probe,
|
||||
.connect = arygon_connect,
|
||||
.disconnect = arygon_disconnect,
|
||||
.strerror = pn53x_strerror,
|
||||
const struct nfc_driver arygon_driver = {
|
||||
.name = ARYGON_DRIVER_NAME,
|
||||
.probe = arygon_probe,
|
||||
.open = arygon_open,
|
||||
.close = arygon_close,
|
||||
.strerror = pn53x_strerror,
|
||||
|
||||
.initiator_init = pn53x_initiator_init,
|
||||
.initiator_select_passive_target = pn53x_initiator_select_passive_target,
|
||||
|
|
@ -522,10 +583,10 @@ const struct nfc_driver_t arygon_driver = {
|
|||
.target_send_bits = pn53x_target_send_bits,
|
||||
.target_receive_bits = pn53x_target_receive_bits,
|
||||
|
||||
.configure = pn53x_configure,
|
||||
.device_set_property_bool = pn53x_set_property_bool,
|
||||
.device_set_property_int = pn53x_set_property_int,
|
||||
|
||||
.abort_command = arygon_abort_command,
|
||||
// FIXME Implement me
|
||||
.idle = NULL,
|
||||
.idle = NULL, // FIXME arygon driver does not support idle()
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -30,14 +30,14 @@
|
|||
|
||||
# include <nfc/nfc-types.h>
|
||||
|
||||
bool arygon_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound);
|
||||
bool arygon_probe (nfc_connstring connstrings[], size_t connstrings_len, size_t *pszDeviceFound);
|
||||
|
||||
nfc_device_t *arygon_connect (const nfc_device_desc_t * pndd);
|
||||
void arygon_disconnect (nfc_device_t * pnd);
|
||||
nfc_device *arygon_open (const nfc_connstring connstring);
|
||||
void arygon_close (nfc_device *pnd);
|
||||
|
||||
bool arygon_tama_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData, struct timeval *timeout);
|
||||
int arygon_tama_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDat, struct timeval *timeouta);
|
||||
int arygon_tama_send (nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int timeout);
|
||||
int arygon_tama_receive (nfc_device *pnd, uint8_t *pbtData, const size_t szDat, int timeouta);
|
||||
|
||||
extern const struct nfc_driver_t arygon_driver;
|
||||
extern const struct nfc_driver arygon_driver;
|
||||
|
||||
#endif // ! __NFC_DRIVER_ARYGON_H__
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "pn532_uart.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
|
@ -44,11 +45,11 @@
|
|||
#include "uart.h"
|
||||
|
||||
#define PN532_UART_DEFAULT_SPEED 115200
|
||||
#define PN532_UART_DRIVER_NAME "PN532_UART"
|
||||
#define PN532_UART_DRIVER_NAME "pn532_uart"
|
||||
#define LOG_CATEGORY "libnfc.driver.pn532_uart"
|
||||
|
||||
int pn532_uart_ack (nfc_device_t * pnd);
|
||||
int pn532_uart_wakeup (nfc_device_t * pnd);
|
||||
int pn532_uart_ack (nfc_device *pnd);
|
||||
int pn532_uart_wakeup (nfc_device *pnd);
|
||||
|
||||
const struct pn53x_io pn532_uart_io;
|
||||
|
||||
|
|
@ -64,14 +65,14 @@ struct pn532_uart_data {
|
|||
#define DRIVER_DATA(pnd) ((struct pn532_uart_data*)(pnd->driver_data))
|
||||
|
||||
bool
|
||||
pn532_uart_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound)
|
||||
pn532_uart_probe (nfc_connstring connstrings[], size_t connstrings_len, size_t *pszDeviceFound)
|
||||
{
|
||||
/** @note: Due to UART bus we can't know if its really a pn532 without
|
||||
* sending some PN53x commands. But using this way to probe devices, we can
|
||||
* have serious problem with other device on this bus */
|
||||
#ifndef SERIAL_AUTOPROBE_ENABLED
|
||||
(void) pnddDevices;
|
||||
(void) szDevices;
|
||||
(void) connstrings;
|
||||
(void) connstrings_len;
|
||||
*pszDeviceFound = 0;
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_INFO, "Serial auto-probing have been disabled at compile time. Skipping autoprobe.");
|
||||
return false;
|
||||
|
|
@ -90,10 +91,12 @@ pn532_uart_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * ps
|
|||
if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) {
|
||||
// We need to flush input to be sure first reply does not comes from older byte transceive
|
||||
uart_flush_input (sp);
|
||||
// Serial port claimed but we need to check if a PN532_UART is connected.
|
||||
// Serial port claimed but we need to check if a PN532_UART is opened.
|
||||
uart_set_speed (sp, PN532_UART_DEFAULT_SPEED);
|
||||
|
||||
nfc_device_t *pnd = nfc_device_new ();
|
||||
nfc_connstring connstring;
|
||||
snprintf (connstring, sizeof(nfc_connstring), "%s:%s:%"PRIu32, PN532_UART_DRIVER_NAME, acPort, PN532_UART_DEFAULT_SPEED);
|
||||
nfc_device *pnd = nfc_device_new (connstring);
|
||||
pnd->driver = &pn532_uart_driver;
|
||||
pnd->driver_data = malloc(sizeof(struct pn532_uart_data));
|
||||
DRIVER_DATA (pnd)->port = sp;
|
||||
|
|
@ -113,29 +116,22 @@ pn532_uart_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * ps
|
|||
#endif
|
||||
|
||||
// Check communication using "Diagnose" command, with "Communication test" (0x00)
|
||||
bool res = pn53x_check_communication (pnd);
|
||||
if(!res) {
|
||||
nfc_perror (pnd, "pn53x_check_communication");
|
||||
}
|
||||
int res = pn53x_check_communication (pnd);
|
||||
pn53x_data_free (pnd);
|
||||
nfc_device_free (pnd);
|
||||
uart_close (sp);
|
||||
if(!res) {
|
||||
if(res < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
snprintf (pnddDevices[*pszDeviceFound].acDevice, DEVICE_NAME_LENGTH - 1, "%s (%s)", "PN532", acPort);
|
||||
pnddDevices[*pszDeviceFound].pcDriver = PN532_UART_DRIVER_NAME;
|
||||
strncpy (pnddDevices[*pszDeviceFound].acPort, acPort, DEVICE_PORT_LENGTH - 1); pnddDevices[*pszDeviceFound].acPort[DEVICE_PORT_LENGTH - 1] = '\0';
|
||||
pnddDevices[*pszDeviceFound].uiSpeed = PN532_UART_DEFAULT_SPEED;
|
||||
memcpy (connstrings[*pszDeviceFound], connstring, sizeof (nfc_connstring));
|
||||
(*pszDeviceFound)++;
|
||||
|
||||
// Test if we reach the maximum "wanted" devices
|
||||
if ((*pszDeviceFound) >= szDevices)
|
||||
if ((*pszDeviceFound) >= connstrings_len)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
iDevice = 0;
|
||||
while ((acPort = acPorts[iDevice++])) {
|
||||
free ((void*)acPort);
|
||||
|
|
@ -145,33 +141,96 @@ pn532_uart_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * ps
|
|||
return true;
|
||||
}
|
||||
|
||||
nfc_device_t *
|
||||
pn532_uart_connect (const nfc_device_desc_t * pndd)
|
||||
{
|
||||
serial_port sp;
|
||||
nfc_device_t *pnd = NULL;
|
||||
struct pn532_uart_descriptor {
|
||||
char port[128];
|
||||
uint32_t speed;
|
||||
};
|
||||
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Attempt to connect to: %s at %d bauds.", pndd->acPort, pndd->uiSpeed);
|
||||
sp = uart_open (pndd->acPort);
|
||||
int
|
||||
pn532_connstring_decode (const nfc_connstring connstring, struct pn532_uart_descriptor *desc)
|
||||
{
|
||||
char *cs = malloc (strlen (connstring) + 1);
|
||||
if (!cs) {
|
||||
perror ("malloc");
|
||||
return -1;
|
||||
}
|
||||
strcpy (cs, connstring);
|
||||
const char *driver_name = strtok (cs, ":");
|
||||
if (!driver_name) {
|
||||
// Parse error
|
||||
free (cs);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 != strcmp (driver_name, PN532_UART_DRIVER_NAME)) {
|
||||
// Driver name does not match.
|
||||
free (cs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *port = strtok (NULL, ":");
|
||||
if (!port) {
|
||||
// Only driver name was specified (or parsing error)
|
||||
free (cs);
|
||||
return 1;
|
||||
}
|
||||
strncpy (desc->port, port, sizeof(desc->port)-1);
|
||||
desc->port[sizeof(desc->port)-1] = '\0';
|
||||
|
||||
const char *speed_s = strtok (NULL, ":");
|
||||
if (!speed_s) {
|
||||
// speed not specified (or parsing error)
|
||||
free (cs);
|
||||
return 2;
|
||||
}
|
||||
unsigned long speed;
|
||||
if (sscanf (speed_s, "%lu", &speed) != 1) {
|
||||
// speed_s is not a number
|
||||
free (cs);
|
||||
return 2;
|
||||
}
|
||||
desc->speed = speed;
|
||||
|
||||
free (cs);
|
||||
return 3;
|
||||
}
|
||||
|
||||
nfc_device *
|
||||
pn532_uart_open (const nfc_connstring connstring)
|
||||
{
|
||||
struct pn532_uart_descriptor ndd;
|
||||
int connstring_decode_level = pn532_connstring_decode (connstring, &ndd);
|
||||
|
||||
if (connstring_decode_level < 2) {
|
||||
return NULL;
|
||||
}
|
||||
if (connstring_decode_level < 3) {
|
||||
ndd.speed = PN532_UART_DEFAULT_SPEED;
|
||||
}
|
||||
serial_port sp;
|
||||
nfc_device *pnd = NULL;
|
||||
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Attempt to open: %s at %d bauds.", ndd.port, ndd.speed);
|
||||
sp = uart_open (ndd.port);
|
||||
|
||||
if (sp == INVALID_SERIAL_PORT)
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Invalid serial port: %s", pndd->acPort);
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Invalid serial port: %s", ndd.port);
|
||||
if (sp == CLAIMED_SERIAL_PORT)
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Serial port already claimed: %s", pndd->acPort);
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Serial port already claimed: %s", ndd.port);
|
||||
if ((sp == CLAIMED_SERIAL_PORT) || (sp == INVALID_SERIAL_PORT))
|
||||
return NULL;
|
||||
|
||||
// We need to flush input to be sure first reply does not comes from older byte transceive
|
||||
uart_flush_input (sp);
|
||||
uart_set_speed (sp, pndd->uiSpeed);
|
||||
uart_set_speed (sp, ndd.speed);
|
||||
|
||||
// We have a connection
|
||||
pnd = nfc_device_new ();
|
||||
strncpy (pnd->acName, pndd->acDevice, DEVICE_NAME_LENGTH - 1);
|
||||
pnd->acName[DEVICE_NAME_LENGTH - 1] = '\0';
|
||||
pnd = nfc_device_new (connstring);
|
||||
snprintf (pnd->name, sizeof (pnd->name), "%s:%s", PN532_UART_DRIVER_NAME, ndd.port);
|
||||
|
||||
pnd->driver_data = malloc(sizeof(struct pn532_uart_data));
|
||||
DRIVER_DATA(pnd)->port = sp;
|
||||
DRIVER_DATA (pnd)->port = sp;
|
||||
|
||||
// Alloc and init chip's data
|
||||
pn53x_data_new (pnd, &pn532_uart_io);
|
||||
// SAMConfiguration command if needed to wakeup the chip and pn53x_SAMConfiguration check if the chip is a PN532
|
||||
|
|
@ -191,9 +250,9 @@ pn532_uart_connect (const nfc_device_desc_t * pndd)
|
|||
#endif
|
||||
|
||||
// Check communication using "Diagnose" command, with "Communication test" (0x00)
|
||||
if (!pn53x_check_communication (pnd)) {
|
||||
if (pn53x_check_communication (pnd) < 0) {
|
||||
nfc_perror (pnd, "pn53x_check_communication");
|
||||
pn532_uart_disconnect(pnd);
|
||||
pn532_uart_close (pnd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -202,7 +261,7 @@ pn532_uart_connect (const nfc_device_desc_t * pndd)
|
|||
}
|
||||
|
||||
void
|
||||
pn532_uart_disconnect (nfc_device_t * pnd)
|
||||
pn532_uart_close (nfc_device *pnd)
|
||||
{
|
||||
// Release UART port
|
||||
uart_close (DRIVER_DATA(pnd)->port);
|
||||
|
|
@ -218,40 +277,38 @@ pn532_uart_disconnect (nfc_device_t * pnd)
|
|||
}
|
||||
|
||||
int
|
||||
pn532_uart_wakeup (nfc_device_t * pnd)
|
||||
pn532_uart_wakeup (nfc_device *pnd)
|
||||
{
|
||||
/* 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 };
|
||||
int res = uart_send (DRIVER_DATA(pnd)->port, pn532_wakeup_preamble, sizeof (pn532_wakeup_preamble), NULL);
|
||||
const uint8_t pn532_wakeup_preamble[] = { 0x55, 0x55, 0x00, 0x00, 0x00 };
|
||||
int res = uart_send (DRIVER_DATA(pnd)->port, pn532_wakeup_preamble, sizeof (pn532_wakeup_preamble), 0);
|
||||
CHIP_DATA(pnd)->power_mode = NORMAL; // PN532 should now be awake
|
||||
return res;
|
||||
}
|
||||
|
||||
#define PN532_BUFFER_LEN (PN53x_EXTENDED_FRAME__DATA_MAX_LEN + PN53x_EXTENDED_FRAME__OVERHEAD)
|
||||
bool
|
||||
pn532_uart_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData, struct timeval *timeout)
|
||||
int
|
||||
pn532_uart_send (nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int timeout)
|
||||
{
|
||||
int res = 0;
|
||||
// Before sending anything, we need to discard from any junk bytes
|
||||
uart_flush_input (DRIVER_DATA(pnd)->port);
|
||||
|
||||
switch (CHIP_DATA(pnd)->power_mode) {
|
||||
case LOWVBAT: {
|
||||
/** PN532C106 wakeup. */
|
||||
if (-1 == pn532_uart_wakeup(pnd)) {
|
||||
return false;
|
||||
if ((res = pn532_uart_wakeup(pnd)) < 0) {
|
||||
return res;
|
||||
}
|
||||
// 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
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
if (!pn53x_SAMConfiguration (pnd, 0x01, &tv)) {
|
||||
return false;
|
||||
if ((res = pn53x_SAMConfiguration (pnd, 0x01, 1000)) < 0) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case POWERDOWN: {
|
||||
if (-1 == pn532_uart_wakeup(pnd)) {
|
||||
return false;
|
||||
if ((res = pn532_uart_wakeup(pnd)) < 0) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -260,43 +317,43 @@ pn532_uart_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData
|
|||
break;
|
||||
};
|
||||
|
||||
byte_t abtFrame[PN532_BUFFER_LEN] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
|
||||
uint8_t abtFrame[PN532_BUFFER_LEN] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
|
||||
size_t szFrame = 0;
|
||||
|
||||
if (!pn53x_build_frame (abtFrame, &szFrame, pbtData, szData)) {
|
||||
pnd->iLastError = EINVALARG;
|
||||
return false;
|
||||
if ((res = pn53x_build_frame (abtFrame, &szFrame, pbtData, szData)) < 0) {
|
||||
pnd->last_error = res;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
int res = uart_send (DRIVER_DATA(pnd)->port, abtFrame, szFrame, timeout);
|
||||
res = uart_send (DRIVER_DATA(pnd)->port, abtFrame, szFrame, timeout);
|
||||
if (res != 0) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Unable to transmit data. (TX)");
|
||||
pnd->iLastError = res;
|
||||
return false;
|
||||
pnd->last_error = res;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
byte_t abtRxBuf[6];
|
||||
uint8_t abtRxBuf[6];
|
||||
res = uart_receive (DRIVER_DATA(pnd)->port, abtRxBuf, 6, 0, timeout);
|
||||
if (res != 0) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Unable to read ACK");
|
||||
pnd->iLastError = res;
|
||||
return false;
|
||||
pnd->last_error = res;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
if (pn53x_check_ack_frame (pnd, abtRxBuf, sizeof(abtRxBuf))) {
|
||||
if (pn53x_check_ack_frame (pnd, abtRxBuf, sizeof(abtRxBuf)) == 0) {
|
||||
// The PN53x is running the sent command
|
||||
} else {
|
||||
return false;
|
||||
return pnd->last_error;
|
||||
}
|
||||
return true;
|
||||
return NFC_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
pn532_uart_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen, struct timeval *timeout)
|
||||
pn532_uart_receive (nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, int timeout)
|
||||
{
|
||||
byte_t abtRxBuf[5];
|
||||
uint8_t abtRxBuf[5];
|
||||
size_t len;
|
||||
void * abort_p = NULL;
|
||||
void *abort_p = NULL;
|
||||
|
||||
#ifndef WIN32
|
||||
abort_p = &(DRIVER_DATA (pnd)->iAbortFds[1]);
|
||||
|
|
@ -304,51 +361,50 @@ pn532_uart_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen
|
|||
abort_p = (void*)&(DRIVER_DATA (pnd)->abort_flag);
|
||||
#endif
|
||||
|
||||
pnd->iLastError = uart_receive (DRIVER_DATA(pnd)->port, abtRxBuf, 5, abort_p, timeout);
|
||||
pnd->last_error = uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, 5, abort_p, timeout);
|
||||
|
||||
if (abort_p && (EOPABORT == pnd->iLastError)) {
|
||||
pn532_uart_ack (pnd);
|
||||
return -1;
|
||||
if (abort_p && (NFC_EOPABORTED == pnd->last_error)) {
|
||||
return pn532_uart_ack (pnd);
|
||||
}
|
||||
|
||||
if (pnd->iLastError != 0) {
|
||||
if (pnd->last_error != 0) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)");
|
||||
return -1;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
const byte_t pn53x_preamble[3] = { 0x00, 0x00, 0xff };
|
||||
const uint8_t pn53x_preamble[3] = { 0x00, 0x00, 0xff };
|
||||
if (0 != (memcmp (abtRxBuf, pn53x_preamble, 3))) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Frame preamble+start code mismatch");
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
if ((0x01 == abtRxBuf[3]) && (0xff == abtRxBuf[4])) {
|
||||
// Error frame
|
||||
uart_receive (DRIVER_DATA(pnd)->port, abtRxBuf, 3, 0, timeout);
|
||||
uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, 3, 0, timeout);
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Application level error detected");
|
||||
pnd->iLastError = EFRAISERRFRAME;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
} else if ((0xff == abtRxBuf[3]) && (0xff == abtRxBuf[4])) {
|
||||
// Extended frame
|
||||
pnd->iLastError = uart_receive (DRIVER_DATA(pnd)->port, abtRxBuf, 3, 0, timeout);
|
||||
if (pnd->iLastError) return -1;
|
||||
pnd->last_error = uart_receive (DRIVER_DATA(pnd)->port, abtRxBuf, 3, 0, timeout);
|
||||
if (pnd->last_error) return pnd->last_error;
|
||||
|
||||
// (abtRxBuf[0] << 8) + abtRxBuf[1] (LEN) include TFI + (CC+1)
|
||||
len = (abtRxBuf[0] << 8) + abtRxBuf[1] - 2;
|
||||
if (((abtRxBuf[0] + abtRxBuf[1] + abtRxBuf[2]) % 256) != 0) {
|
||||
// TODO: Retry
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Length checksum mismatch");
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
} else {
|
||||
// Normal frame
|
||||
if (256 != (abtRxBuf[3] + abtRxBuf[4])) {
|
||||
// TODO: Retry
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Length checksum mismatch");
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
// abtRxBuf[3] (LEN) include TFI + (CC+1)
|
||||
|
|
@ -357,77 +413,78 @@ pn532_uart_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen
|
|||
|
||||
if (len > szDataLen) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Unable to receive data: buffer too small. (szDataLen: %zu, len: %zu)", szDataLen, len);
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
// TFI + PD0 (CC+1)
|
||||
pnd->iLastError = uart_receive (DRIVER_DATA(pnd)->port, abtRxBuf, 2, 0, timeout);
|
||||
if (pnd->iLastError != 0) {
|
||||
pnd->last_error = uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, 2, 0, timeout);
|
||||
if (pnd->last_error != 0) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)");
|
||||
return -1;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
if (abtRxBuf[0] != 0xD5) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "TFI Mismatch");
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
if (abtRxBuf[1] != CHIP_DATA (pnd)->ui8LastCommand + 1) {
|
||||
if (abtRxBuf[1] != CHIP_DATA (pnd)->last_command + 1) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Command Code verification failed");
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
if (len) {
|
||||
pnd->iLastError = uart_receive (DRIVER_DATA(pnd)->port, pbtData, len, 0, timeout);
|
||||
if (pnd->iLastError != 0) {
|
||||
pnd->last_error = uart_receive (DRIVER_DATA (pnd)->port, pbtData, len, 0, timeout);
|
||||
if (pnd->last_error != 0) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)");
|
||||
return -1;
|
||||
return pnd->last_error;
|
||||
}
|
||||
}
|
||||
|
||||
pnd->iLastError = uart_receive (DRIVER_DATA(pnd)->port, abtRxBuf, 2, 0, timeout);
|
||||
if (pnd->iLastError != 0) {
|
||||
pnd->last_error = uart_receive (DRIVER_DATA (pnd)->port, abtRxBuf, 2, 0, timeout);
|
||||
if (pnd->last_error != 0) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)");
|
||||
return -1;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
byte_t btDCS = (256 - 0xD5);
|
||||
btDCS -= CHIP_DATA (pnd)->ui8LastCommand + 1;
|
||||
uint8_t btDCS = (256 - 0xD5);
|
||||
btDCS -= CHIP_DATA (pnd)->last_command + 1;
|
||||
for (size_t szPos = 0; szPos < len; szPos++) {
|
||||
btDCS -= pbtData[szPos];
|
||||
}
|
||||
|
||||
if (btDCS != abtRxBuf[0]) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Data checksum mismatch");
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
if (0x00 != abtRxBuf[1]) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Frame postamble mismatch");
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
// The PN53x command is done and we successfully received the reply
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
pn532_uart_ack (nfc_device_t * pnd)
|
||||
pn532_uart_ack (nfc_device *pnd)
|
||||
{
|
||||
int res = 0;
|
||||
if (POWERDOWN == CHIP_DATA(pnd)->power_mode) {
|
||||
if (-1 == pn532_uart_wakeup(pnd)) {
|
||||
return -1;
|
||||
if ((res = pn532_uart_wakeup(pnd)) < 0) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return (0 == uart_send (DRIVER_DATA(pnd)->port, pn53x_ack_frame, sizeof (pn53x_ack_frame), NULL)) ? 0 : -1;
|
||||
return (uart_send (DRIVER_DATA(pnd)->port, pn53x_ack_frame, sizeof (pn53x_ack_frame), 0));
|
||||
}
|
||||
|
||||
bool
|
||||
pn532_uart_abort_command (nfc_device_t * pnd)
|
||||
int
|
||||
pn532_uart_abort_command (nfc_device *pnd)
|
||||
{
|
||||
if (pnd) {
|
||||
#ifndef WIN32
|
||||
|
|
@ -437,7 +494,7 @@ pn532_uart_abort_command (nfc_device_t * pnd)
|
|||
DRIVER_DATA (pnd)->abort_flag = true;
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
return NFC_SUCCESS;
|
||||
}
|
||||
|
||||
const struct pn53x_io pn532_uart_io = {
|
||||
|
|
@ -445,12 +502,12 @@ const struct pn53x_io pn532_uart_io = {
|
|||
.receive = pn532_uart_receive,
|
||||
};
|
||||
|
||||
const struct nfc_driver_t pn532_uart_driver = {
|
||||
.name = PN532_UART_DRIVER_NAME,
|
||||
.probe = pn532_uart_probe,
|
||||
.connect = pn532_uart_connect,
|
||||
.disconnect = pn532_uart_disconnect,
|
||||
.strerror = pn53x_strerror,
|
||||
const struct nfc_driver pn532_uart_driver = {
|
||||
.name = PN532_UART_DRIVER_NAME,
|
||||
.probe = pn532_uart_probe,
|
||||
.open = pn532_uart_open,
|
||||
.close = pn532_uart_close,
|
||||
.strerror = pn53x_strerror,
|
||||
|
||||
.initiator_init = pn53x_initiator_init,
|
||||
.initiator_select_passive_target = pn53x_initiator_select_passive_target,
|
||||
|
|
@ -468,7 +525,8 @@ const struct nfc_driver_t pn532_uart_driver = {
|
|||
.target_send_bits = pn53x_target_send_bits,
|
||||
.target_receive_bits = pn53x_target_receive_bits,
|
||||
|
||||
.configure = pn53x_configure,
|
||||
.device_set_property_bool = pn53x_set_property_bool,
|
||||
.device_set_property_int = pn53x_set_property_int,
|
||||
|
||||
.abort_command = pn532_uart_abort_command,
|
||||
.idle = pn53x_idle,
|
||||
|
|
|
|||
|
|
@ -29,13 +29,13 @@
|
|||
|
||||
# include <nfc/nfc-types.h>
|
||||
|
||||
bool pn532_uart_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound);
|
||||
bool pn532_uart_probe (nfc_connstring connstrings[], size_t connstrings_len, size_t *pszDeviceFound);
|
||||
|
||||
nfc_device_t *pn532_uart_connect (const nfc_device_desc_t * pndd);
|
||||
void pn532_uart_disconnect (nfc_device_t * pnd);
|
||||
bool pn532_uart_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData, struct timeval *timeout);
|
||||
int pn532_uart_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szData, struct timeval *timeout);
|
||||
nfc_device *pn532_uart_open (const nfc_connstring connstring);
|
||||
void pn532_uart_close (nfc_device *pnd);
|
||||
int pn532_uart_send (nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int timeout);
|
||||
int pn532_uart_receive (nfc_device *pnd, uint8_t *pbtData, const size_t szData, int timeout);
|
||||
|
||||
extern const struct nfc_driver_t pn532_uart_driver;
|
||||
extern const struct nfc_driver pn532_uart_driver;
|
||||
|
||||
#endif // ! __NFC_DRIVER_PN532_UART_H__
|
||||
|
|
|
|||
|
|
@ -32,10 +32,11 @@
|
|||
Thanks to d18c7db and Okko for example code
|
||||
*/
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/select.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
// Under POSIX system, we use libusb (>= 0.1.12)
|
||||
|
|
@ -58,44 +59,13 @@ Thanks to d18c7db and Okko for example code
|
|||
#include "chips/pn53x-internal.h"
|
||||
#include "drivers/pn53x_usb.h"
|
||||
|
||||
#define PN53X_USB_DRIVER_NAME "PN53x USB"
|
||||
#define PN53X_USB_DRIVER_NAME "pn53x_usb"
|
||||
#define LOG_CATEGORY "libnfc.driver.pn53x_usb"
|
||||
|
||||
#define USB_INFINITE_TIMEOUT 0
|
||||
|
||||
#define DRIVER_DATA(pnd) ((struct pn53x_usb_data*)(pnd->driver_data))
|
||||
|
||||
/* This modified from some GNU example _not_ to overwrite y */
|
||||
int timeval_subtract(struct timeval *result,
|
||||
const struct timeval *x,
|
||||
const struct timeval *y)
|
||||
{
|
||||
struct timeval tmp;
|
||||
|
||||
tmp.tv_sec = y->tv_sec;
|
||||
tmp.tv_usec = y->tv_usec;
|
||||
|
||||
/* Perform the carry for the later subtraction */
|
||||
if (x->tv_usec < y->tv_usec) {
|
||||
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
|
||||
tmp.tv_usec -= 1000000 * nsec;
|
||||
tmp.tv_sec += nsec;
|
||||
}
|
||||
if (x->tv_usec - y->tv_usec > 1000000) {
|
||||
int nsec = (x->tv_usec - y->tv_usec) / 1000000;
|
||||
tmp.tv_usec += 1000000 * nsec;
|
||||
tmp.tv_sec -= nsec;
|
||||
}
|
||||
|
||||
/* Compute the time remaining to wait.
|
||||
tv_usec is certainly positive. */
|
||||
result->tv_sec = x->tv_sec - tmp.tv_sec;
|
||||
result->tv_usec = x->tv_usec - tmp.tv_usec;
|
||||
|
||||
/* Return 1 if result is negative. */
|
||||
return x->tv_sec < tmp.tv_sec;
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
UNKNOWN,
|
||||
NXP_PN531,
|
||||
|
|
@ -117,21 +87,12 @@ struct pn53x_usb_data {
|
|||
|
||||
const struct pn53x_io pn53x_usb_io;
|
||||
bool pn53x_usb_get_usb_device_name (struct usb_device *dev, usb_dev_handle *udev, char *buffer, size_t len);
|
||||
bool pn53x_usb_init (nfc_device_t *pnd);
|
||||
int pn53x_usb_init (nfc_device *pnd);
|
||||
|
||||
int
|
||||
pn53x_usb_bulk_read (struct pn53x_usb_data *data, byte_t abtRx[], const size_t szRx, struct timeval *timeout)
|
||||
pn53x_usb_bulk_read (struct pn53x_usb_data *data, uint8_t abtRx[], const size_t szRx, const int timeout)
|
||||
{
|
||||
int timeout_ms = USB_INFINITE_TIMEOUT;
|
||||
if (timeout) {
|
||||
timeout_ms = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
|
||||
if (timeout_ms == USB_INFINITE_TIMEOUT) {
|
||||
// timeout < 1 ms
|
||||
timeout_ms++;
|
||||
}
|
||||
}
|
||||
|
||||
int res = usb_bulk_read (data->pudh, data->uiEndPointIn, (char *) abtRx, szRx, timeout_ms);
|
||||
int res = usb_bulk_read (data->pudh, data->uiEndPointIn, (char *) abtRx, szRx, timeout);
|
||||
if (res > 0) {
|
||||
LOG_HEX ("RX", abtRx, res);
|
||||
} else if (res < 0) {
|
||||
|
|
@ -142,18 +103,14 @@ pn53x_usb_bulk_read (struct pn53x_usb_data *data, byte_t abtRx[], const size_t s
|
|||
}
|
||||
|
||||
int
|
||||
pn53x_usb_bulk_write (struct pn53x_usb_data *data, byte_t abtTx[], const size_t szTx, struct timeval *timeout)
|
||||
pn53x_usb_bulk_write (struct pn53x_usb_data *data, uint8_t abtTx[], const size_t szTx, const int timeout)
|
||||
{
|
||||
LOG_HEX ("TX", abtTx, szTx);
|
||||
int timeout_ms = USB_INFINITE_TIMEOUT;
|
||||
if (timeout)
|
||||
timeout_ms = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
|
||||
|
||||
int res = usb_bulk_write (data->pudh, data->uiEndPointOut, (char *) abtTx, szTx, timeout_ms);
|
||||
int res = usb_bulk_write (data->pudh, data->uiEndPointOut, (char *) abtTx, szTx, timeout);
|
||||
if (res > 0) {
|
||||
// HACK This little hack is a well know problem of USB, see http://www.libusb.org/ticket/6 for more details
|
||||
if ((res % data->uiMaxPacketSize) == 0) {
|
||||
usb_bulk_write (data->pudh, data->uiEndPointOut, "\0", 0, timeout_ms);
|
||||
usb_bulk_write (data->pudh, data->uiEndPointOut, "\0", 0, timeout);
|
||||
}
|
||||
} else {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Unable to write to USB (%s)", _usb_strerror (res));
|
||||
|
|
@ -189,7 +146,7 @@ pn53x_usb_get_device_model (uint16_t vendor_id, uint16_t product_id)
|
|||
return UNKNOWN;
|
||||
}
|
||||
|
||||
int pn53x_usb_ack (nfc_device_t * pnd);
|
||||
int pn53x_usb_ack (nfc_device *pnd);
|
||||
|
||||
// Find transfer endpoints for bulk transfers
|
||||
void
|
||||
|
|
@ -222,7 +179,7 @@ pn53x_usb_get_end_points (struct usb_device *dev, struct pn53x_usb_data *data)
|
|||
}
|
||||
|
||||
bool
|
||||
pn53x_usb_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound)
|
||||
pn53x_usb_probe (nfc_connstring connstrings[], size_t connstrings_len, size_t *pszDeviceFound)
|
||||
{
|
||||
usb_init ();
|
||||
|
||||
|
|
@ -275,13 +232,13 @@ pn53x_usb_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * psz
|
|||
continue;
|
||||
}
|
||||
|
||||
pn53x_usb_get_usb_device_name (dev, udev, pnddDevices[*pszDeviceFound].acDevice, sizeof (pnddDevices[*pszDeviceFound].acDevice));
|
||||
// pn53x_usb_get_usb_device_name (dev, udev, pnddDevices[*pszDeviceFound].acDevice, sizeof (pnddDevices[*pszDeviceFound].acDevice));
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "device found: Bus %s Device %s", bus->dirname, dev->filename);
|
||||
usb_close (udev);
|
||||
pnddDevices[*pszDeviceFound].pcDriver = PN53X_USB_DRIVER_NAME;
|
||||
pnddDevices[*pszDeviceFound].uiBusIndex = uiBusIndex;
|
||||
snprintf (connstrings[*pszDeviceFound], sizeof(nfc_connstring), "%s:%s:%s", PN53X_USB_DRIVER_NAME, bus->dirname, dev->filename);
|
||||
(*pszDeviceFound)++;
|
||||
// Test if we reach the maximum "wanted" devices
|
||||
if ((*pszDeviceFound) == szDevices) {
|
||||
if ((*pszDeviceFound) == connstrings_len) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -292,6 +249,38 @@ pn53x_usb_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * psz
|
|||
return true;
|
||||
}
|
||||
|
||||
struct pn53x_usb_descriptor {
|
||||
char *dirname;
|
||||
char *filename;
|
||||
};
|
||||
|
||||
int
|
||||
pn53x_usb_connstring_decode (const nfc_connstring connstring, struct pn53x_usb_descriptor *desc)
|
||||
{
|
||||
int n = strlen (connstring) + 1;
|
||||
char *driver_name = malloc (n);
|
||||
char *dirname = malloc (n);
|
||||
char *filename = malloc (n);
|
||||
|
||||
driver_name[0] = '\0';
|
||||
|
||||
int res = sscanf (connstring, "%[^:]:%[^:]:%[^:]", driver_name, dirname, filename);
|
||||
|
||||
if (!res || (0 != strcmp (driver_name, PN53X_USB_DRIVER_NAME))) {
|
||||
// Driver name does not match.
|
||||
res = 0;
|
||||
} else {
|
||||
desc->dirname = strdup (dirname);
|
||||
desc->filename = strdup (filename);
|
||||
}
|
||||
|
||||
free (driver_name);
|
||||
free (dirname);
|
||||
free (filename);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool
|
||||
pn53x_usb_get_usb_device_name (struct usb_device *dev, usb_dev_handle *udev, char *buffer, size_t len)
|
||||
{
|
||||
|
|
@ -319,10 +308,17 @@ pn53x_usb_get_usb_device_name (struct usb_device *dev, usb_dev_handle *udev, cha
|
|||
return false;
|
||||
}
|
||||
|
||||
nfc_device_t *
|
||||
pn53x_usb_connect (const nfc_device_desc_t *pndd)
|
||||
nfc_device *
|
||||
pn53x_usb_open (const nfc_connstring connstring)
|
||||
{
|
||||
nfc_device_t *pnd = NULL;
|
||||
nfc_device *pnd = NULL;
|
||||
struct pn53x_usb_descriptor desc = { NULL, NULL } ;
|
||||
int connstring_decode_level = pn53x_usb_connstring_decode (connstring, &desc);
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "%d element(s) have been decoded from \"%s\"", connstring_decode_level, connstring);
|
||||
if (connstring_decode_level < 1) {
|
||||
goto free_mem;
|
||||
}
|
||||
|
||||
struct pn53x_usb_data data = {
|
||||
.pudh = NULL,
|
||||
.uiEndPointIn = 0,
|
||||
|
|
@ -330,95 +326,118 @@ pn53x_usb_connect (const nfc_device_desc_t *pndd)
|
|||
};
|
||||
struct usb_bus *bus;
|
||||
struct usb_device *dev;
|
||||
uint32_t uiBusIndex;
|
||||
|
||||
usb_init ();
|
||||
|
||||
uiBusIndex = pndd->uiBusIndex;
|
||||
int res;
|
||||
// usb_find_busses will find all of the busses on the system. Returns the
|
||||
// number of changes since previous call to this function (total of new
|
||||
// busses and busses removed).
|
||||
if ((res = usb_find_busses () < 0)) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Unable to find USB busses (%s)", _usb_strerror (res));
|
||||
goto free_mem;
|
||||
}
|
||||
// usb_find_devices will find all of the devices on each bus. This should be
|
||||
// called after usb_find_busses. Returns the number of changes since the
|
||||
// previous call to this function (total of new device and devices removed).
|
||||
if ((res = usb_find_devices () < 0)) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Unable to find USB devices (%s)", _usb_strerror (res));
|
||||
goto free_mem;
|
||||
}
|
||||
|
||||
for (bus = usb_get_busses (); bus; bus = bus->next) {
|
||||
for (dev = bus->devices; dev; dev = dev->next, uiBusIndex--) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Checking device %04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct);
|
||||
if (uiBusIndex == 0) {
|
||||
// Open the USB device
|
||||
data.pudh = usb_open (dev);
|
||||
// Retrieve end points
|
||||
pn53x_usb_get_end_points (dev, &data);
|
||||
// Set configuration
|
||||
int res = usb_set_configuration (data.pudh, 1);
|
||||
if (res < 0) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Unable to set USB configuration (%s)", _usb_strerror (res));
|
||||
if (EPERM == -res) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_WARN, "Please double check USB permissions for device %04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct);
|
||||
}
|
||||
usb_close (data.pudh);
|
||||
// we failed to use the specified device
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res = usb_claim_interface (data.pudh, 0);
|
||||
if (res < 0) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Unable to claim USB interface (%s)", _usb_strerror (res));
|
||||
usb_close (data.pudh);
|
||||
// we failed to use the specified device
|
||||
return NULL;
|
||||
}
|
||||
data.model = pn53x_usb_get_device_model (dev->descriptor.idVendor, dev->descriptor.idProduct);
|
||||
// Allocate memory for the device info and specification, fill it and return the info
|
||||
pnd = nfc_device_new ();
|
||||
pn53x_usb_get_usb_device_name (dev, data.pudh, pnd->acName, sizeof (pnd->acName));
|
||||
|
||||
pnd->driver_data = malloc(sizeof(struct pn53x_usb_data));
|
||||
*DRIVER_DATA (pnd) = data;
|
||||
|
||||
// Alloc and init chip's data
|
||||
pn53x_data_new (pnd, &pn53x_usb_io);
|
||||
|
||||
switch (DRIVER_DATA (pnd)->model) {
|
||||
// empirical tuning
|
||||
case ASK_LOGO:
|
||||
CHIP_DATA (pnd)->timer_correction = 50;
|
||||
break;
|
||||
case SCM_SCL3711:
|
||||
case NXP_PN533:
|
||||
CHIP_DATA (pnd)->timer_correction = 46;
|
||||
break;
|
||||
case NXP_PN531:
|
||||
CHIP_DATA (pnd)->timer_correction = 50;
|
||||
break;
|
||||
case SONY_PN531:
|
||||
CHIP_DATA (pnd)->timer_correction = 54;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pnd->driver = &pn53x_usb_driver;
|
||||
|
||||
// HACK1: Send first an ACK as Abort command, to reset chip before talking to it:
|
||||
pn53x_usb_ack (pnd);
|
||||
|
||||
// HACK2: Then send a GetFirmware command to resync USB toggle bit between host & device
|
||||
// in case host used set_configuration and expects the device to have reset its toggle bit, which PN53x doesn't do
|
||||
if (!pn53x_usb_init (pnd)) {
|
||||
usb_close (data.pudh);
|
||||
goto error;
|
||||
}
|
||||
DRIVER_DATA (pnd)->abort_flag = false;
|
||||
return pnd;
|
||||
if (connstring_decode_level > 1) {
|
||||
// A specific bus have been specified
|
||||
if (0 != strcmp (bus->dirname, desc.dirname))
|
||||
continue;
|
||||
}
|
||||
for (dev = bus->devices; dev; dev = dev->next) {
|
||||
if (connstring_decode_level > 2) {
|
||||
// A specific dev have been specified
|
||||
if (0 != strcmp (dev->filename, desc.filename))
|
||||
continue;
|
||||
}
|
||||
// Open the USB device
|
||||
data.pudh = usb_open (dev);
|
||||
// Retrieve end points
|
||||
pn53x_usb_get_end_points (dev, &data);
|
||||
// Set configuration
|
||||
int res = usb_set_configuration (data.pudh, 1);
|
||||
if (res < 0) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Unable to set USB configuration (%s)", _usb_strerror (res));
|
||||
if (EPERM == -res) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_WARN, "Please double check USB permissions for device %04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct);
|
||||
}
|
||||
usb_close (data.pudh);
|
||||
// we failed to use the specified device
|
||||
goto free_mem;
|
||||
}
|
||||
|
||||
res = usb_claim_interface (data.pudh, 0);
|
||||
if (res < 0) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Unable to claim USB interface (%s)", _usb_strerror (res));
|
||||
usb_close (data.pudh);
|
||||
// we failed to use the specified device
|
||||
goto free_mem;
|
||||
}
|
||||
data.model = pn53x_usb_get_device_model (dev->descriptor.idVendor, dev->descriptor.idProduct);
|
||||
// Allocate memory for the device info and specification, fill it and return the info
|
||||
pnd = nfc_device_new (connstring);
|
||||
pn53x_usb_get_usb_device_name (dev, data.pudh, pnd->name, sizeof (pnd->name));
|
||||
|
||||
pnd->driver_data = malloc(sizeof(struct pn53x_usb_data));
|
||||
*DRIVER_DATA (pnd) = data;
|
||||
|
||||
// Alloc and init chip's data
|
||||
pn53x_data_new (pnd, &pn53x_usb_io);
|
||||
|
||||
switch (DRIVER_DATA (pnd)->model) {
|
||||
// empirical tuning
|
||||
case ASK_LOGO:
|
||||
CHIP_DATA (pnd)->timer_correction = 50;
|
||||
break;
|
||||
case SCM_SCL3711:
|
||||
case NXP_PN533:
|
||||
CHIP_DATA (pnd)->timer_correction = 46;
|
||||
break;
|
||||
case NXP_PN531:
|
||||
CHIP_DATA (pnd)->timer_correction = 50;
|
||||
break;
|
||||
case SONY_PN531:
|
||||
CHIP_DATA (pnd)->timer_correction = 54;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pnd->driver = &pn53x_usb_driver;
|
||||
|
||||
// HACK1: Send first an ACK as Abort command, to reset chip before talking to it:
|
||||
pn53x_usb_ack (pnd);
|
||||
|
||||
// HACK2: Then send a GetFirmware command to resync USB toggle bit between host & device
|
||||
// in case host used set_configuration and expects the device to have reset its toggle bit, which PN53x doesn't do
|
||||
if (pn53x_usb_init (pnd) < 0) {
|
||||
usb_close (data.pudh);
|
||||
goto error;
|
||||
}
|
||||
DRIVER_DATA (pnd)->abort_flag = false;
|
||||
goto free_mem;
|
||||
}
|
||||
}
|
||||
// We ran out of devices before the index required
|
||||
return NULL;
|
||||
goto free_mem;
|
||||
|
||||
error:
|
||||
// Free allocated structure on error.
|
||||
nfc_device_free (pnd);
|
||||
return NULL;
|
||||
free_mem:
|
||||
free (desc.dirname);
|
||||
free (desc.filename);
|
||||
return pnd;
|
||||
}
|
||||
|
||||
void
|
||||
pn53x_usb_disconnect (nfc_device_t * pnd)
|
||||
pn53x_usb_close (nfc_device *pnd)
|
||||
{
|
||||
pn53x_usb_ack (pnd);
|
||||
|
||||
|
|
@ -444,31 +463,29 @@ pn53x_usb_disconnect (nfc_device_t * pnd)
|
|||
|
||||
#define PN53X_USB_BUFFER_LEN (PN53x_EXTENDED_FRAME__DATA_MAX_LEN + PN53x_EXTENDED_FRAME__OVERHEAD)
|
||||
|
||||
bool
|
||||
pn53x_usb_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData, struct timeval *timeout)
|
||||
int
|
||||
pn53x_usb_send (nfc_device *pnd, const uint8_t *pbtData, const size_t szData, const int timeout)
|
||||
{
|
||||
byte_t abtFrame[PN53X_USB_BUFFER_LEN] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
|
||||
uint8_t abtFrame[PN53X_USB_BUFFER_LEN] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
|
||||
size_t szFrame = 0;
|
||||
int res = 0;
|
||||
|
||||
pn53x_build_frame (abtFrame, &szFrame, pbtData, szData);
|
||||
|
||||
int res = pn53x_usb_bulk_write (DRIVER_DATA (pnd), abtFrame, szFrame, timeout);
|
||||
|
||||
if (res < 0) {
|
||||
pnd->iLastError = ECOMIO;
|
||||
return false;
|
||||
if ((res = pn53x_usb_bulk_write (DRIVER_DATA (pnd), abtFrame, szFrame, timeout)) < 0) {
|
||||
pnd->last_error = res;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
byte_t abtRxBuf[PN53X_USB_BUFFER_LEN];
|
||||
res = pn53x_usb_bulk_read (DRIVER_DATA (pnd), abtRxBuf, sizeof (abtRxBuf), timeout);
|
||||
if (res < 0) {
|
||||
pnd->iLastError = ECOMIO;
|
||||
uint8_t abtRxBuf[PN53X_USB_BUFFER_LEN];
|
||||
if ((res = pn53x_usb_bulk_read (DRIVER_DATA (pnd), abtRxBuf, sizeof (abtRxBuf), timeout)) < 0) {
|
||||
pnd->last_error = res;
|
||||
// try to interrupt current device state
|
||||
pn53x_usb_ack(pnd);
|
||||
return false;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
if (pn53x_check_ack_frame (pnd, abtRxBuf, res)) {
|
||||
if (pn53x_check_ack_frame (pnd, abtRxBuf, res) == 0) {
|
||||
// The PN53x is running the sent command
|
||||
} else {
|
||||
// For some reasons (eg. send another command while a previous one is
|
||||
|
|
@ -478,94 +495,80 @@ pn53x_usb_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData,
|
|||
// pn53x_usb_receive()) will be able to retreive the correct response
|
||||
// packet.
|
||||
// FIXME Sony reader is also affected by this bug but NACK is not supported
|
||||
int res = pn53x_usb_bulk_write (DRIVER_DATA (pnd), (byte_t *)pn53x_nack_frame, sizeof(pn53x_nack_frame), timeout);
|
||||
if (res < 0) {
|
||||
pnd->iLastError = ECOMIO;
|
||||
if ((res = pn53x_usb_bulk_write (DRIVER_DATA (pnd), (uint8_t *)pn53x_nack_frame, sizeof(pn53x_nack_frame), timeout)) < 0) {
|
||||
pnd->last_error = res;
|
||||
// try to interrupt current device state
|
||||
pn53x_usb_ack(pnd);
|
||||
return false;
|
||||
return pnd->last_error;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return NFC_SUCCESS;
|
||||
}
|
||||
|
||||
#define USB_TIMEOUT_PER_PASS 200
|
||||
int
|
||||
pn53x_usb_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen, struct timeval *timeout)
|
||||
pn53x_usb_receive (nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, const int timeout)
|
||||
{
|
||||
size_t len;
|
||||
off_t offset = 0;
|
||||
|
||||
byte_t abtRxBuf[PN53X_USB_BUFFER_LEN];
|
||||
uint8_t abtRxBuf[PN53X_USB_BUFFER_LEN];
|
||||
int res;
|
||||
|
||||
/*
|
||||
* If no timeout is specified but the command is blocking, force a 250ms
|
||||
* If no timeout is specified but the command is blocking, force a 200ms (USB_TIMEOUT_PER_PASS)
|
||||
* timeout to allow breaking the loop if the user wants to stop it.
|
||||
*/
|
||||
const struct timeval fixed_timeout = {
|
||||
.tv_sec = 0,
|
||||
.tv_usec = 250000,
|
||||
};
|
||||
|
||||
struct timeval remaining_time, usb_timeout;
|
||||
if (timeout) {
|
||||
remaining_time = *timeout;
|
||||
}
|
||||
int usb_timeout;
|
||||
int remaining_time = timeout;
|
||||
read:
|
||||
if (timeout) {
|
||||
// A user-provided timeout is set, we have to cut it in multiple chunk to be able to keep an nfc_abort_command() mecanism
|
||||
struct timeval tmp;
|
||||
if (1 == timeval_subtract (&tmp, &remaining_time, &fixed_timeout)) {
|
||||
// The subtraction result is negative
|
||||
usb_timeout = remaining_time;
|
||||
remaining_time.tv_sec = 0;
|
||||
remaining_time.tv_usec = 0;
|
||||
} else {
|
||||
usb_timeout = fixed_timeout;
|
||||
remaining_time = tmp;
|
||||
}
|
||||
if (timeout == USB_INFINITE_TIMEOUT) {
|
||||
usb_timeout = USB_TIMEOUT_PER_PASS;
|
||||
} else {
|
||||
// No user-provided timeout, we will wait infinitely but we need nfc_abort_command() mecanism.
|
||||
usb_timeout = fixed_timeout;
|
||||
// A user-provided timeout is set, we have to cut it in multiple chunk to be able to keep an nfc_abort_command() mecanism
|
||||
remaining_time -= USB_TIMEOUT_PER_PASS;
|
||||
if (remaining_time <= 0) {
|
||||
pnd->last_error = NFC_ETIMEOUT;
|
||||
return pnd->last_error;
|
||||
} else {
|
||||
usb_timeout = MIN(remaining_time, USB_TIMEOUT_PER_PASS);
|
||||
}
|
||||
}
|
||||
if ((usb_timeout.tv_sec == 0) && (usb_timeout.tv_usec == 0)) {
|
||||
pnd->iLastError = ECOMTIMEOUT;
|
||||
return -1;
|
||||
}
|
||||
res = pn53x_usb_bulk_read (DRIVER_DATA (pnd), abtRxBuf, sizeof (abtRxBuf), &usb_timeout);
|
||||
|
||||
res = pn53x_usb_bulk_read (DRIVER_DATA (pnd), abtRxBuf, sizeof (abtRxBuf), usb_timeout);
|
||||
|
||||
if (res == -USB_TIMEDOUT) {
|
||||
if (DRIVER_DATA (pnd)->abort_flag) {
|
||||
DRIVER_DATA (pnd)->abort_flag = false;
|
||||
pn53x_usb_ack (pnd);
|
||||
pnd->iLastError = EOPABORT;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EOPABORTED;
|
||||
return pnd->last_error;
|
||||
} else {
|
||||
goto read;
|
||||
}
|
||||
}
|
||||
|
||||
if (res < 0) {
|
||||
pnd->iLastError = ECOMIO;
|
||||
pnd->last_error = res;
|
||||
// try to interrupt current device state
|
||||
pn53x_usb_ack(pnd);
|
||||
return -1;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
const byte_t pn53x_preamble[3] = { 0x00, 0x00, 0xff };
|
||||
const uint8_t pn53x_preamble[3] = { 0x00, 0x00, 0xff };
|
||||
if (0 != (memcmp (abtRxBuf, pn53x_preamble, 3))) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Frame preamble+start code mismatch");
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
offset += 3;
|
||||
|
||||
if ((0x01 == abtRxBuf[offset]) && (0xff == abtRxBuf[offset + 1])) {
|
||||
// Error frame
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Application level error detected");
|
||||
pnd->iLastError = EFRAISERRFRAME;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
} else if ((0xff == abtRxBuf[offset]) && (0xff == abtRxBuf[offset + 1])) {
|
||||
// Extended frame
|
||||
offset += 2;
|
||||
|
|
@ -575,8 +578,8 @@ read:
|
|||
if (((abtRxBuf[offset] + abtRxBuf[offset + 1] + abtRxBuf[offset + 2]) % 256) != 0) {
|
||||
// TODO: Retry
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Length checksum mismatch");
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
offset += 3;
|
||||
} else {
|
||||
|
|
@ -584,8 +587,8 @@ read:
|
|||
if (256 != (abtRxBuf[offset] + abtRxBuf[offset + 1])) {
|
||||
// TODO: Retry
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Length checksum mismatch");
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
// abtRxBuf[3] (LEN) include TFI + (CC+1)
|
||||
|
|
@ -595,75 +598,76 @@ read:
|
|||
|
||||
if (len > szDataLen) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "Unable to receive data: buffer too small. (szDataLen: %zu, len: %zu)", szDataLen, len);
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
|
||||
// TFI + PD0 (CC+1)
|
||||
if (abtRxBuf[offset] != 0xD5) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "TFI Mismatch");
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
offset += 1;
|
||||
|
||||
if (abtRxBuf[offset] != CHIP_DATA (pnd)->ui8LastCommand + 1) {
|
||||
if (abtRxBuf[offset] != CHIP_DATA (pnd)->last_command + 1) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Command Code verification failed");
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
offset += 1;
|
||||
|
||||
memcpy (pbtData, abtRxBuf + offset, len);
|
||||
offset += len;
|
||||
|
||||
byte_t btDCS = (256 - 0xD5);
|
||||
btDCS -= CHIP_DATA (pnd)->ui8LastCommand + 1;
|
||||
uint8_t btDCS = (256 - 0xD5);
|
||||
btDCS -= CHIP_DATA (pnd)->last_command + 1;
|
||||
for (size_t szPos = 0; szPos < len; szPos++) {
|
||||
btDCS -= pbtData[szPos];
|
||||
}
|
||||
|
||||
if (btDCS != abtRxBuf[offset]) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Data checksum mismatch");
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
offset += 1;
|
||||
|
||||
if (0x00 != abtRxBuf[offset]) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_ERROR, "%s", "Frame postamble mismatch");
|
||||
pnd->iLastError = ECOMIO;
|
||||
return -1;
|
||||
pnd->last_error = NFC_EIO;
|
||||
return pnd->last_error;
|
||||
}
|
||||
// The PN53x command is done and we successfully received the reply
|
||||
pnd->iLastError = 0;
|
||||
pnd->last_error = 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
pn53x_usb_ack (nfc_device_t * pnd)
|
||||
pn53x_usb_ack (nfc_device *pnd)
|
||||
{
|
||||
return pn53x_usb_bulk_write (DRIVER_DATA (pnd), (byte_t *) pn53x_ack_frame, sizeof (pn53x_ack_frame), NULL);
|
||||
return pn53x_usb_bulk_write (DRIVER_DATA (pnd), (uint8_t *) pn53x_ack_frame, sizeof (pn53x_ack_frame), 0);
|
||||
}
|
||||
|
||||
bool
|
||||
pn53x_usb_init (nfc_device_t *pnd)
|
||||
int
|
||||
pn53x_usb_init (nfc_device *pnd)
|
||||
{
|
||||
int res = 0;
|
||||
// Sometimes PN53x USB doesn't reply ACK one the first frame, so we need to send a dummy one...
|
||||
//pn53x_check_communication (pnd); // Sony RC-S360 doesn't support this command for now so let's use a get_firmware_version instead:
|
||||
const byte_t abtCmd[] = { GetFirmwareVersion };
|
||||
pn53x_transceive (pnd, abtCmd, sizeof (abtCmd), NULL, NULL, NULL);
|
||||
const uint8_t abtCmd[] = { GetFirmwareVersion };
|
||||
pn53x_transceive (pnd, abtCmd, sizeof (abtCmd), NULL, 0, 0);
|
||||
// ...and we don't care about error
|
||||
pnd->iLastError = 0;
|
||||
pnd->last_error = 0;
|
||||
if (SONY_RCS360 == DRIVER_DATA (pnd)->model) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "SONY RC-S360 initialization.");
|
||||
const byte_t abtCmd2[] = { 0x18, 0x01 };
|
||||
pn53x_transceive (pnd, abtCmd2, sizeof (abtCmd2), NULL, NULL, NULL);
|
||||
const uint8_t abtCmd2[] = { 0x18, 0x01 };
|
||||
pn53x_transceive (pnd, abtCmd2, sizeof (abtCmd2), NULL, 0, 0);
|
||||
pn53x_usb_ack (pnd);
|
||||
}
|
||||
|
||||
if (!pn53x_init (pnd))
|
||||
return false;
|
||||
if ((res = pn53x_init (pnd)) < 0)
|
||||
return res;
|
||||
|
||||
if (ASK_LOGO == DRIVER_DATA (pnd)->model) {
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "ASK LoGO initialization.");
|
||||
|
|
@ -700,42 +704,43 @@ On ASK LoGO hardware:
|
|||
pn53x_write_register (pnd, PN53X_SFR_P3, 0xFF, _BV (P30) | _BV (P31) | _BV (P33) | _BV (P35));
|
||||
}
|
||||
|
||||
return true;
|
||||
return NFC_SUCCESS;
|
||||
}
|
||||
|
||||
bool
|
||||
pn53x_usb_configure (nfc_device_t * pnd, const nfc_device_option_t ndo, const bool bEnable)
|
||||
int
|
||||
pn53x_usb_set_property_bool (nfc_device *pnd, const nfc_property property, const bool bEnable)
|
||||
{
|
||||
if (!pn53x_configure (pnd, ndo, bEnable))
|
||||
return false;
|
||||
int res = 0;
|
||||
if ((res = pn53x_set_property_bool (pnd, property, bEnable)) < 0)
|
||||
return res;
|
||||
|
||||
switch (DRIVER_DATA (pnd)->model) {
|
||||
case ASK_LOGO:
|
||||
if (NDO_ACTIVATE_FIELD == ndo) {
|
||||
if (NP_ACTIVATE_FIELD == property) {
|
||||
/* Switch on/off LED2 and Progressive Field GPIO according to ACTIVATE_FIELD option */
|
||||
log_put (LOG_CATEGORY, NFC_PRIORITY_TRACE, "Switch progressive field %s", bEnable ? "On" : "Off");
|
||||
if (!pn53x_write_register (pnd, PN53X_SFR_P3, _BV(P31) | _BV(P34), bEnable ? _BV (P34) : _BV (P31)))
|
||||
return false;
|
||||
if ((res = pn53x_write_register (pnd, PN53X_SFR_P3, _BV(P31) | _BV(P34), bEnable ? _BV (P34) : _BV (P31))) < 0)
|
||||
return NFC_ECHIP;
|
||||
}
|
||||
break;
|
||||
case SCM_SCL3711:
|
||||
if (NDO_ACTIVATE_FIELD == ndo) {
|
||||
if (NP_ACTIVATE_FIELD == property) {
|
||||
// Switch on/off LED according to ACTIVATE_FIELD option
|
||||
if (!pn53x_write_register (pnd, PN53X_SFR_P3, _BV (P32), bEnable ? 0 : _BV (P32)))
|
||||
return false;
|
||||
if ((res = pn53x_write_register (pnd, PN53X_SFR_P3, _BV (P32), bEnable ? 0 : _BV (P32))) < 0)
|
||||
return res;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
return NFC_SUCCESS;
|
||||
}
|
||||
|
||||
bool
|
||||
pn53x_usb_abort_command (nfc_device_t * pnd)
|
||||
int
|
||||
pn53x_usb_abort_command (nfc_device *pnd)
|
||||
{
|
||||
DRIVER_DATA (pnd)->abort_flag = true;
|
||||
return true;
|
||||
return NFC_SUCCESS;
|
||||
}
|
||||
|
||||
const struct pn53x_io pn53x_usb_io = {
|
||||
|
|
@ -743,12 +748,12 @@ const struct pn53x_io pn53x_usb_io = {
|
|||
.receive = pn53x_usb_receive,
|
||||
};
|
||||
|
||||
const struct nfc_driver_t pn53x_usb_driver = {
|
||||
.name = PN53X_USB_DRIVER_NAME,
|
||||
.probe = pn53x_usb_probe,
|
||||
.connect = pn53x_usb_connect,
|
||||
.disconnect = pn53x_usb_disconnect,
|
||||
.strerror = pn53x_strerror,
|
||||
const struct nfc_driver pn53x_usb_driver = {
|
||||
.name = PN53X_USB_DRIVER_NAME,
|
||||
.probe = pn53x_usb_probe,
|
||||
.open = pn53x_usb_open,
|
||||
.close = pn53x_usb_close,
|
||||
.strerror = pn53x_strerror,
|
||||
|
||||
.initiator_init = pn53x_initiator_init,
|
||||
.initiator_select_passive_target = pn53x_initiator_select_passive_target,
|
||||
|
|
@ -766,7 +771,8 @@ const struct nfc_driver_t pn53x_usb_driver = {
|
|||
.target_send_bits = pn53x_target_send_bits,
|
||||
.target_receive_bits = pn53x_target_receive_bits,
|
||||
|
||||
.configure = pn53x_usb_configure,
|
||||
.device_set_property_bool = pn53x_usb_set_property_bool,
|
||||
.device_set_property_int = pn53x_set_property_int,
|
||||
|
||||
.abort_command = pn53x_usb_abort_command,
|
||||
.idle = pn53x_idle,
|
||||
|
|
|
|||
|
|
@ -23,18 +23,20 @@
|
|||
*/
|
||||
|
||||
#ifndef __NFC_DRIVER_PN53X_USB_H__
|
||||
# define __NFC_DRIVER_PN53X_USB_H__
|
||||
#define __NFC_DRIVER_PN53X_USB_H__
|
||||
|
||||
# include <sys/time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
# include <nfc/nfc-types.h>
|
||||
#include <nfc/nfc-types.h>
|
||||
|
||||
bool pn53x_usb_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound);
|
||||
nfc_device_t *pn53x_usb_connect (const nfc_device_desc_t * pndd);
|
||||
bool pn53x_usb_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData, struct timeval *timeout);
|
||||
int pn53x_usb_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szData, struct timeval *timeout);
|
||||
void pn53x_usb_disconnect (nfc_device_t * pnd);
|
||||
#include "nfc-internal.h"
|
||||
|
||||
extern const struct nfc_driver_t pn53x_usb_driver;
|
||||
bool pn53x_usb_probe (nfc_connstring connstrings[], size_t connstrings_len, size_t *pszDeviceFound);
|
||||
nfc_device *pn53x_usb_open (const nfc_connstring connstring);
|
||||
int pn53x_usb_send (nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int timeout);
|
||||
int pn53x_usb_receive (nfc_device *pnd, uint8_t *pbtData, const size_t szData, int timeout);
|
||||
void pn53x_usb_close (nfc_device *pnd);
|
||||
|
||||
extern const struct nfc_driver pn53x_usb_driver;
|
||||
|
||||
#endif // ! __NFC_DRIVER_PN53X_USB_H__
|
||||
|
|
|
|||
|
|
@ -32,30 +32,30 @@
|
|||
#include <nfc/nfc.h>
|
||||
|
||||
void
|
||||
iso14443a_crc (byte_t * pbtData, size_t szLen, byte_t * pbtCrc)
|
||||
iso14443a_crc (uint8_t *pbtData, size_t szLen, uint8_t *pbtCrc)
|
||||
{
|
||||
byte_t bt;
|
||||
uint8_t bt;
|
||||
uint32_t wCrc = 0x6363;
|
||||
|
||||
do {
|
||||
bt = *pbtData++;
|
||||
bt = (bt ^ (byte_t) (wCrc & 0x00FF));
|
||||
bt = (bt ^ (uint8_t) (wCrc & 0x00FF));
|
||||
bt = (bt ^ (bt << 4));
|
||||
wCrc = (wCrc >> 8) ^ ((uint32_t) bt << 8) ^ ((uint32_t) bt << 3) ^ ((uint32_t) bt >> 4);
|
||||
} while (--szLen);
|
||||
|
||||
*pbtCrc++ = (byte_t) (wCrc & 0xFF);
|
||||
*pbtCrc = (byte_t) ((wCrc >> 8) & 0xFF);
|
||||
*pbtCrc++ = (uint8_t) (wCrc & 0xFF);
|
||||
*pbtCrc = (uint8_t) ((wCrc >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
void
|
||||
iso14443a_crc_append (byte_t * pbtData, size_t szLen)
|
||||
iso14443a_crc_append (uint8_t *pbtData, size_t szLen)
|
||||
{
|
||||
iso14443a_crc (pbtData, szLen, pbtData + szLen);
|
||||
}
|
||||
|
||||
byte_t *
|
||||
iso14443a_locate_historical_bytes (byte_t * pbtAts, size_t szAts, size_t * pszTk)
|
||||
uint8_t *
|
||||
iso14443a_locate_historical_bytes (uint8_t *pbtAts, size_t szAts, size_t *pszTk)
|
||||
{
|
||||
if (szAts) {
|
||||
size_t offset = 1;
|
||||
|
|
@ -82,7 +82,7 @@ iso14443a_locate_historical_bytes (byte_t * pbtAts, size_t szAts, size_t * pszTk
|
|||
* @see ISO/IEC 14443-3 (6.4.4 UID contents and cascade levels)
|
||||
*/
|
||||
void
|
||||
iso14443_cascade_uid (const byte_t abtUID[], const size_t szUID, byte_t * pbtCascadedUID, size_t * pszCascadedUID)
|
||||
iso14443_cascade_uid (const uint8_t abtUID[], const size_t szUID, uint8_t *pbtCascadedUID, size_t *pszCascadedUID)
|
||||
{
|
||||
switch (szUID) {
|
||||
case 7:
|
||||
|
|
|
|||
|
|
@ -17,9 +17,10 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
#include <log4c.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
|
|
@ -31,7 +32,7 @@ log_init (void)
|
|||
int res = 0;
|
||||
|
||||
if (__log_init_counter == 0) {
|
||||
res = log4c_init ();
|
||||
res = 0;
|
||||
}
|
||||
if (!res) {
|
||||
__log_init_counter++;
|
||||
|
|
@ -45,7 +46,7 @@ log_fini (void)
|
|||
int res = 0;
|
||||
if (__log_init_counter >= 1) {
|
||||
if (__log_init_counter == 1) {
|
||||
res = log4c_fini ();
|
||||
res = 0;
|
||||
}
|
||||
__log_init_counter--;
|
||||
} else {
|
||||
|
|
@ -55,12 +56,12 @@ log_fini (void)
|
|||
}
|
||||
|
||||
void
|
||||
log_put (char *category, int priority, char *format, ...)
|
||||
log_put (char *category, char *priority, char *format, ...)
|
||||
{
|
||||
const log4c_category_t *cat = log4c_category_get (category);
|
||||
if (log4c_category_is_priority_enabled (cat, priority)) {
|
||||
va_list va;
|
||||
va_start (va, format);
|
||||
log4c_category_vlog (cat, priority, format, va);
|
||||
}
|
||||
va_list va;
|
||||
va_start (va, format);
|
||||
printf ("%s\t%s\t", priority, category);
|
||||
vprintf (format, va);
|
||||
printf ("\n");
|
||||
va_end (va);
|
||||
}
|
||||
99
libnfc/log.h
99
libnfc/log.h
|
|
@ -18,69 +18,44 @@
|
|||
#ifndef __LOG_H__
|
||||
#define __LOG_H__
|
||||
|
||||
#if defined(HAS_LOG4C) && HAS_LOG4C /* log4c have been detected */
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif // HAVE_CONFIG_H
|
||||
|
||||
#define LOGGING 1
|
||||
|
||||
#include <log4c.h>
|
||||
|
||||
int log_init (void);
|
||||
int log_fini (void);
|
||||
void log_put (char *category, int priority, char *format, ...);
|
||||
|
||||
#define NFC_PRIORITY_FATAL LOG4C_PRIORITY_FATAL
|
||||
#define NFC_PRIORITY_ALERT LOG4C_PRIORITY_ALERT
|
||||
#define NFC_PRIORITY_CRIT LOG4C_PRIORITY_CRIT
|
||||
#define NFC_PRIORITY_ERROR LOG4C_PRIORITY_ERROR
|
||||
#define NFC_PRIORITY_WARN LOG4C_PRIORITY_WARN
|
||||
#define NFC_PRIORITY_NOTICE LOG4C_PRIORITY_NOTICE
|
||||
#define NFC_PRIORITY_INFO LOG4C_PRIORITY_INFO
|
||||
#define NFC_PRIORITY_DEBUG LOG4C_PRIORITY_DEBUG
|
||||
#define NFC_PRIORITY_TRACE LOG4C_PRIORITY_TRACE
|
||||
|
||||
#elif defined(DEBUG) /* no available log4c but debug is enabled */
|
||||
|
||||
#define LOGGING 1
|
||||
|
||||
#define log_init() (0)
|
||||
#define log_fini() (0)
|
||||
#define log_msg(category, priority, message) do {} while (0)
|
||||
#define log_set_appender(category, appender) do {} while (0)
|
||||
#define log_put(category, priority, format, ...) do { \
|
||||
fprintf(stderr, "%s - ", category); \
|
||||
fprintf(stderr, format, ##__VA_ARGS__); \
|
||||
fprintf(stderr, "\n"); \
|
||||
} while (0)
|
||||
|
||||
#define NFC_PRIORITY_FATAL 8
|
||||
#define NFC_PRIORITY_ALERT 7
|
||||
#define NFC_PRIORITY_CRIT 6
|
||||
#define NFC_PRIORITY_ERROR 5
|
||||
#define NFC_PRIORITY_WARN 4
|
||||
#define NFC_PRIORITY_NOTICE 3
|
||||
#define NFC_PRIORITY_INFO 2
|
||||
#define NFC_PRIORITY_DEBUG 1
|
||||
#define NFC_PRIORITY_TRACE 0
|
||||
|
||||
#else /* no available log4c and debug is disabled */
|
||||
|
||||
#define log_init() (0)
|
||||
#define log_fini() (0)
|
||||
#define log_msg(category, priority, message) do {} while (0)
|
||||
#define log_set_appender(category, appender) do {} while (0)
|
||||
#define log_put(category, priority, format, ...) do {} while (0)
|
||||
|
||||
#define NFC_PRIORITY_FATAL 8
|
||||
#define NFC_PRIORITY_ALERT 7
|
||||
#define NFC_PRIORITY_CRIT 6
|
||||
#define NFC_PRIORITY_ERROR 5
|
||||
#define NFC_PRIORITY_WARN 4
|
||||
#define NFC_PRIORITY_NOTICE 3
|
||||
#define NFC_PRIORITY_INFO 2
|
||||
#define NFC_PRIORITY_DEBUG 1
|
||||
#define NFC_PRIORITY_TRACE 0
|
||||
|
||||
#endif
|
||||
#if defined DEBUG
|
||||
// User want debug features
|
||||
#define LOGGING 1
|
||||
int log_init (void);
|
||||
int log_fini (void);
|
||||
void log_put (char *category, char *priority, char *format, ...);
|
||||
|
||||
#define NFC_PRIORITY_FATAL "fatal"
|
||||
#define NFC_PRIORITY_ALERT "alert"
|
||||
#define NFC_PRIORITY_CRIT "critical"
|
||||
#define NFC_PRIORITY_ERROR "error"
|
||||
#define NFC_PRIORITY_WARN "warning"
|
||||
#define NFC_PRIORITY_NOTICE "notice"
|
||||
#define NFC_PRIORITY_INFO "info"
|
||||
#define NFC_PRIORITY_DEBUG "debug"
|
||||
#define NFC_PRIORITY_TRACE "trace"
|
||||
#else
|
||||
// No logging
|
||||
#define log_init() (0)
|
||||
#define log_fini() (0)
|
||||
#define log_msg(category, priority, message) do {} while (0)
|
||||
#define log_set_appender(category, appender) do {} while (0)
|
||||
#define log_put(category, priority, format, ...) do {} while (0)
|
||||
|
||||
#define NFC_PRIORITY_FATAL 8
|
||||
#define NFC_PRIORITY_ALERT 7
|
||||
#define NFC_PRIORITY_CRIT 6
|
||||
#define NFC_PRIORITY_ERROR 5
|
||||
#define NFC_PRIORITY_WARN 4
|
||||
#define NFC_PRIORITY_NOTICE 3
|
||||
#define NFC_PRIORITY_INFO 2
|
||||
#define NFC_PRIORITY_DEBUG 1
|
||||
#define NFC_PRIORITY_TRACE 0
|
||||
#endif /* HAS_LOG4C, DEBUG */
|
||||
|
||||
/**
|
||||
* @macro LOG_HEX
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
#include "mirror-subr.h"
|
||||
|
||||
static const byte_t ByteMirror[256] = {
|
||||
static const uint8_t ByteMirror[256] = {
|
||||
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30,
|
||||
0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98,
|
||||
0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64,
|
||||
|
|
@ -53,14 +53,14 @@ static const byte_t ByteMirror[256] = {
|
|||
0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
|
||||
};
|
||||
|
||||
byte_t
|
||||
mirror (byte_t bt)
|
||||
uint8_t
|
||||
mirror (uint8_t bt)
|
||||
{
|
||||
return ByteMirror[bt];
|
||||
}
|
||||
|
||||
void
|
||||
mirror_bytes (byte_t * pbts, size_t szLen)
|
||||
mirror_bytes (uint8_t *pbts, size_t szLen)
|
||||
{
|
||||
size_t szByteNr;
|
||||
|
||||
|
|
@ -73,13 +73,13 @@ mirror_bytes (byte_t * pbts, size_t szLen)
|
|||
uint32_t
|
||||
mirror32 (uint32_t ui32Bits)
|
||||
{
|
||||
mirror_bytes ((byte_t *) & ui32Bits, 4);
|
||||
mirror_bytes ((uint8_t *) & ui32Bits, 4);
|
||||
return ui32Bits;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
mirror64 (uint64_t ui64Bits)
|
||||
{
|
||||
mirror_bytes ((byte_t *) & ui64Bits, 8);
|
||||
mirror_bytes ((uint8_t *) & ui64Bits, 8);
|
||||
return ui64Bits;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@
|
|||
# include <nfc/nfc-types.h>
|
||||
|
||||
|
||||
byte_t mirror (byte_t bt);
|
||||
uint8_t mirror (uint8_t bt);
|
||||
uint32_t mirror32 (uint32_t ui32Bits);
|
||||
uint64_t mirror64 (uint64_t ui64Bits);
|
||||
void mirror_byte_ts (byte_t * pbts, size_t szLen);
|
||||
void mirror_uint8_ts (uint8_t *pbts, size_t szLen);
|
||||
|
||||
#endif // _LIBNFC_MIRROR_SUBR_H_
|
||||
|
|
|
|||
|
|
@ -19,12 +19,13 @@
|
|||
|
||||
/**
|
||||
* @file nfc-device.c
|
||||
* @brief Provide internal function to manipulate nfc_device_t type
|
||||
* @brief Provide internal function to manipulate nfc_device type
|
||||
*/
|
||||
|
||||
/* vim:set et sw=2 ts=2: */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
|
|
@ -32,10 +33,10 @@
|
|||
|
||||
#include "nfc-internal.h"
|
||||
|
||||
nfc_device_t *
|
||||
nfc_device_new (void)
|
||||
nfc_device *
|
||||
nfc_device_new (const nfc_connstring connstring)
|
||||
{
|
||||
nfc_device_t *res = malloc (sizeof (*res));
|
||||
nfc_device *res = malloc (sizeof (*res));
|
||||
|
||||
if (!res) {
|
||||
err (EXIT_FAILURE, "nfc_device_new: malloc");
|
||||
|
|
@ -49,7 +50,8 @@ nfc_device_new (void)
|
|||
res->bPar = false;
|
||||
res->bEasyFraming = false;
|
||||
res->bAutoIso14443_4 = false;
|
||||
res->iLastError = 0;
|
||||
res->last_error = 0;
|
||||
memcpy (res->connstring, connstring, sizeof (res->connstring));
|
||||
res->driver_data = NULL;
|
||||
res->chip_data = NULL;
|
||||
|
||||
|
|
@ -57,7 +59,7 @@ nfc_device_new (void)
|
|||
}
|
||||
|
||||
void
|
||||
nfc_device_free (nfc_device_t *nfc_device)
|
||||
nfc_device_free (nfc_device *nfc_device)
|
||||
{
|
||||
if (nfc_device) {
|
||||
free (nfc_device->driver_data);
|
||||
|
|
|
|||
|
|
@ -28,26 +28,26 @@
|
|||
#include "iso7816.h"
|
||||
|
||||
int
|
||||
nfc_emulate_target (nfc_device_t* pnd, struct nfc_emulator *emulator)
|
||||
nfc_emulate_target (nfc_device *pnd, struct nfc_emulator *emulator)
|
||||
{
|
||||
byte_t abtRx[ISO7816_SHORT_R_APDU_MAX_LEN];
|
||||
size_t szRx = sizeof(abtRx);
|
||||
byte_t abtTx[ISO7816_SHORT_C_APDU_MAX_LEN];
|
||||
uint8_t abtRx[ISO7816_SHORT_R_APDU_MAX_LEN];
|
||||
int szRx;
|
||||
uint8_t abtTx[ISO7816_SHORT_C_APDU_MAX_LEN];
|
||||
int res = 0;
|
||||
|
||||
if (!nfc_target_init (pnd, emulator->target, abtRx, &szRx)) {
|
||||
if ((szRx = nfc_target_init (pnd, emulator->target, abtRx, sizeof(abtRx), 0)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (res >= 0) {
|
||||
res = emulator->state_machine->io (emulator, abtRx, szRx, abtTx, sizeof (abtTx));
|
||||
res = emulator->state_machine->io (emulator, abtRx, (size_t) szRx, abtTx, sizeof (abtTx));
|
||||
if (res > 0) {
|
||||
if (!nfc_target_send_bytes(pnd, abtTx, res, NULL)) {
|
||||
if (nfc_target_send_bytes(pnd, abtTx, res, 0) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (res >= 0) {
|
||||
if (!nfc_target_receive_bytes(pnd, abtRx, &szRx, NULL)) {
|
||||
if ((res = nfc_target_receive_bytes(pnd, abtRx, (size_t) szRx, 0)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,39 +23,38 @@
|
|||
*/
|
||||
|
||||
#include <nfc/nfc.h>
|
||||
#include <nfc/nfc-emulation.h>
|
||||
|
||||
void
|
||||
prepare_initiator_data (const nfc_modulation_t nm, byte_t **ppbtInitiatorData, size_t * pszInitiatorData)
|
||||
prepare_initiator_data (const nfc_modulation nm, uint8_t **ppbtInitiatorData, size_t * pszInitiatorData)
|
||||
{
|
||||
switch (nm.nmt) {
|
||||
case NMT_ISO14443B: {
|
||||
// Application Family Identifier (AFI) must equals 0x00 in order to wakeup all ISO14443-B PICCs (see ISO/IEC 14443-3)
|
||||
*ppbtInitiatorData = (byte_t *) "\x00";
|
||||
*ppbtInitiatorData = (uint8_t *) "\x00";
|
||||
*pszInitiatorData = 1;
|
||||
}
|
||||
break;
|
||||
case NMT_ISO14443BI: {
|
||||
// APGEN
|
||||
*ppbtInitiatorData = (byte_t *) "\x01\x0b\x3f\x80";
|
||||
*ppbtInitiatorData = (uint8_t *) "\x01\x0b\x3f\x80";
|
||||
*pszInitiatorData = 4;
|
||||
}
|
||||
break;
|
||||
case NMT_ISO14443B2SR: {
|
||||
// Get_UID
|
||||
*ppbtInitiatorData = (byte_t *) "\x0b";
|
||||
*ppbtInitiatorData = (uint8_t *) "\x0b";
|
||||
*pszInitiatorData = 1;
|
||||
}
|
||||
break;
|
||||
case NMT_ISO14443B2CT: {
|
||||
// SELECT-ALL
|
||||
*ppbtInitiatorData = (byte_t *) "\x9F\xFF\xFF";
|
||||
*ppbtInitiatorData = (uint8_t *) "\x9F\xFF\xFF";
|
||||
*pszInitiatorData = 3;
|
||||
}
|
||||
break;
|
||||
case NMT_FELICA: {
|
||||
// polling payload must be present (see ISO/IEC 18092 11.2.2.5)
|
||||
*ppbtInitiatorData = (byte_t *) "\x00\xff\xff\x01\x00";
|
||||
*ppbtInitiatorData = (uint8_t *) "\x00\xff\xff\x01\x00";
|
||||
*pszInitiatorData = 5;
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -23,24 +23,25 @@
|
|||
*/
|
||||
|
||||
#ifndef __NFC_INTERNAL_H__
|
||||
# define __NFC_INTERNAL_H__
|
||||
#define __NFC_INTERNAL_H__
|
||||
|
||||
# include <nfc/nfc-types.h>
|
||||
# include <stdbool.h>
|
||||
# include <err.h>
|
||||
#include <stdbool.h>
|
||||
#include <err.h>
|
||||
# include <sys/time.h>
|
||||
|
||||
#include "nfc/nfc.h"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
/**
|
||||
* @macro HAL
|
||||
* @brief Execute corresponding driver function if exists.
|
||||
*/
|
||||
#define HAL( FUNCTION, ... ) pnd->iLastError = 0; \
|
||||
#define HAL( FUNCTION, ... ) pnd->last_error = 0; \
|
||||
if (pnd->driver->FUNCTION) { \
|
||||
return pnd->driver->FUNCTION( __VA_ARGS__ ); \
|
||||
} else { \
|
||||
pnd->iLastError = EDEVNOTSUP; \
|
||||
pnd->last_error = NFC_EDEVNOTSUPP; \
|
||||
return false; \
|
||||
}
|
||||
|
||||
|
|
@ -125,40 +126,72 @@
|
|||
#endif
|
||||
|
||||
|
||||
struct nfc_driver_t {
|
||||
struct nfc_driver {
|
||||
const char *name;
|
||||
bool (*probe)(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound);
|
||||
nfc_device_t * (*connect)(const nfc_device_desc_t * pndd);
|
||||
void (*disconnect)(nfc_device_t * pnd);
|
||||
const char *(*strerror)(const nfc_device_t * pnd);
|
||||
bool (*probe)(nfc_connstring connstrings[], size_t connstrings_len, size_t * pszDeviceFound);
|
||||
struct nfc_device *(*open) (const nfc_connstring connstring);
|
||||
void (*close) (struct nfc_device *pnd);
|
||||
const char *(*strerror) (const struct nfc_device *pnd);
|
||||
|
||||
bool (*initiator_init) (nfc_device_t * pnd);
|
||||
bool (*initiator_select_passive_target) (nfc_device_t * pnd, const nfc_modulation_t nm, const byte_t * pbtInitData, const size_t szInitData, nfc_target_t * pnt);
|
||||
bool (*initiator_poll_target) (nfc_device_t * pnd, const nfc_modulation_t * pnmModulations, const size_t szModulations, const uint8_t uiPollNr, const uint8_t btPeriod, nfc_target_t * pnt);
|
||||
bool (*initiator_select_dep_target) (nfc_device_t * pnd, const nfc_dep_mode_t ndm, const nfc_baud_rate_t nbr, const nfc_dep_info_t * pndiInitiator, nfc_target_t * pnt);
|
||||
bool (*initiator_deselect_target) (nfc_device_t * pnd);
|
||||
bool (*initiator_transceive_bytes) (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx, size_t * pszRx, struct timeval *timeout);
|
||||
bool (*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);
|
||||
bool (*initiator_transceive_bytes_timed) (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx, size_t * pszRx, uint32_t * cycles);
|
||||
bool (*initiator_transceive_bits_timed) (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, uint32_t * cycles);
|
||||
int (*initiator_init) (struct nfc_device *pnd);
|
||||
int (*initiator_select_passive_target) (struct nfc_device *pnd, const nfc_modulation nm, const uint8_t * pbtInitData, const size_t szInitData, nfc_target * pnt);
|
||||
int (*initiator_poll_target) (struct nfc_device *pnd, const nfc_modulation * pnmModulations, const size_t szModulations, const uint8_t uiPollNr, const uint8_t btPeriod, nfc_target * pnt);
|
||||
int (*initiator_select_dep_target) (struct nfc_device *pnd, const nfc_dep_mode ndm, const nfc_baud_rate nbr, const nfc_dep_info * pndiInitiator, nfc_target * pnt, const int timeout);
|
||||
int (*initiator_deselect_target) (struct nfc_device *pnd);
|
||||
int (*initiator_transceive_bytes) (struct nfc_device *pnd, const uint8_t * pbtTx, const size_t szTx, uint8_t * pbtRx, size_t * pszRx, int timeout);
|
||||
int (*initiator_transceive_bits) (struct nfc_device *pnd, const uint8_t * pbtTx, const size_t szTxBits, const uint8_t * pbtTxPar, uint8_t * pbtRx, uint8_t * pbtRxPar);
|
||||
int (*initiator_transceive_bytes_timed) (struct nfc_device *pnd, const uint8_t * pbtTx, const size_t szTx, uint8_t * pbtRx, uint32_t * cycles);
|
||||
int (*initiator_transceive_bits_timed) (struct nfc_device *pnd, const uint8_t * pbtTx, const size_t szTxBits, const uint8_t * pbtTxPar, uint8_t * pbtRx, uint8_t * pbtRxPar, uint32_t * cycles);
|
||||
|
||||
bool (*target_init) (nfc_device_t * pnd, nfc_target_t * pnt, byte_t * pbtRx, size_t * pszRx);
|
||||
bool (*target_send_bytes) (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, struct timeval *timeout);
|
||||
bool (*target_receive_bytes) (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRx, struct timeval *timeout);
|
||||
bool (*target_send_bits) (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxBits, const byte_t * pbtTxPar);
|
||||
bool (*target_receive_bits) (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBits, byte_t * pbtRxPar);
|
||||
int (*target_init) (struct nfc_device *pnd, nfc_target * pnt, uint8_t * pbtRx, const size_t szRx, int timeout);
|
||||
int (*target_send_bytes) (struct nfc_device *pnd, const uint8_t * pbtTx, const size_t szTx, int timeout);
|
||||
int (*target_receive_bytes) (struct nfc_device *pnd, uint8_t * pbtRx, const size_t szRxLen, int timeout);
|
||||
int (*target_send_bits) (struct nfc_device *pnd, const uint8_t * pbtTx, const size_t szTxBits, const uint8_t * pbtTxPar);
|
||||
int (*target_receive_bits) (struct nfc_device *pnd, uint8_t * pbtRx, const size_t szRxLen, uint8_t * pbtRxPar);
|
||||
|
||||
bool (*configure) (nfc_device_t * pnd, const nfc_device_option_t ndo, const bool bEnable);
|
||||
int (*device_set_property_bool) (struct nfc_device *pnd, const nfc_property property, const bool bEnable);
|
||||
int (*device_set_property_int) (struct nfc_device *pnd, const nfc_property property, const int value);
|
||||
|
||||
bool (*abort_command) (nfc_device_t * pnd);
|
||||
bool (*idle) (nfc_device_t * pnd);
|
||||
int (*abort_command) (struct nfc_device *pnd);
|
||||
int (*idle) (struct nfc_device *pnd);
|
||||
};
|
||||
|
||||
nfc_device_t *nfc_device_new (void);
|
||||
void nfc_device_free (nfc_device_t *nfc_device);
|
||||
# define DEVICE_NAME_LENGTH 256
|
||||
# define DEVICE_PORT_LENGTH 64
|
||||
|
||||
void iso14443_cascade_uid (const byte_t abtUID[], const size_t szUID, byte_t * pbtCascadedUID, size_t * pszCascadedUID);
|
||||
/**
|
||||
* @struct nfc_device
|
||||
* @brief NFC device information
|
||||
*/
|
||||
struct nfc_device {
|
||||
const struct nfc_driver *driver;
|
||||
void *driver_data;
|
||||
void *chip_data;
|
||||
|
||||
void prepare_initiator_data (const nfc_modulation_t nm, byte_t **ppbtInitiatorData, size_t * pszInitiatorData);
|
||||
/** Device name string, including device wrapper firmware */
|
||||
char name[DEVICE_NAME_LENGTH];
|
||||
/** Device connection string */
|
||||
nfc_connstring connstring;
|
||||
/** Is the CRC automaticly added, checked and removed from the frames */
|
||||
bool bCrc;
|
||||
/** Does the chip handle parity bits, all parities are handled as data */
|
||||
bool bPar;
|
||||
/** Should the chip handle frames encapsulation and chaining */
|
||||
bool bEasyFraming;
|
||||
/** Should the chip switch automatically activate ISO14443-4 when
|
||||
selecting tags supporting it? */
|
||||
bool bAutoIso14443_4;
|
||||
/** Supported modulation encoded in a byte */
|
||||
uint8_t btSupportByte;
|
||||
/** Last reported error */
|
||||
int last_error;
|
||||
};
|
||||
|
||||
nfc_device *nfc_device_new (const nfc_connstring connstring);
|
||||
void nfc_device_free (nfc_device *dev);
|
||||
|
||||
void iso14443_cascade_uid (const uint8_t abtUID[], const size_t szUID, uint8_t * pbtCascadedUID, size_t * pszCascadedUID);
|
||||
|
||||
void prepare_initiator_data (const nfc_modulation nm, uint8_t **ppbtInitiatorData, size_t * pszInitiatorData);
|
||||
|
||||
#endif // __NFC_INTERNAL_H__
|
||||
|
|
|
|||
667
libnfc/nfc.c
667
libnfc/nfc.c
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue