Merge libnfc-1.5-new-api branch to trunk (r1168:1303).

This commit is contained in:
Audrey Diacre 2012-01-25 09:56:05 +00:00
commit 26245add73
82 changed files with 4481 additions and 3212 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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[] = {

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -26,6 +26,9 @@
* This driver can handle ARYGON readers that use UART as bus.
* UART connection can be direct (host<->arygon_uc) or could be provided by internal USB to serial interface (e.g. host<->ftdi_chip<->arygon_uc)
*/
/* vim: set ts=2 sw=2 et: */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif // HAVE_CONFIG_H
@ -33,6 +36,7 @@
#include "arygon.h"
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
#include <sys/param.h>
#include <string.h>
@ -64,7 +68,7 @@
#define DEV_ARYGON_PROTOCOL_TAMA_WAB '3'
#define ARYGON_DEFAULT_SPEED 9600
#define ARYGON_DRIVER_NAME "ARYGON"
#define ARYGON_DRIVER_NAME "arygon"
#define LOG_CATEGORY "libnfc.driver.arygon"
#define DRIVER_DATA(pnd) ((struct arygon_data*)(pnd->driver_data))
@ -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()
};

View file

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

View file

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

View file

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

View file

@ -32,10 +32,11 @@
Thanks to d18c7db and Okko for example code
*/
#include <sys/select.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <sys/select.h>
#include <errno.h>
#ifndef _WIN32
// Under POSIX system, we use libusb (>= 0.1.12)
@ -58,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,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff