From fb398c387faf4373601822a4150340f969975106 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 4 Apr 2011 14:16:36 +0000 Subject: [PATCH] pn53x: add timed versions of transceive_bytes/bits --- include/nfc/nfc.h | 2 + libnfc/chips/pn53x.c | 149 ++++++++++++++++++++++++++++++++++++ libnfc/chips/pn53x.h | 51 ++++++++++-- libnfc/drivers/acr122.c | 12 +++ libnfc/drivers/arygon.c | 10 +++ libnfc/drivers/pn532_uart.c | 10 +++ libnfc/drivers/pn53x_usb.c | 32 +++++++- libnfc/nfc-internal.h | 2 + libnfc/nfc.c | 40 ++++++++++ 9 files changed, 299 insertions(+), 9 deletions(-) diff --git a/include/nfc/nfc.h b/include/nfc/nfc.h index 9c5b37a..0f42e36 100644 --- a/include/nfc/nfc.h +++ b/include/nfc/nfc.h @@ -76,6 +76,8 @@ extern "C" { NFC_EXPORT bool nfc_initiator_deselect_target (nfc_device_t * pnd); NFC_EXPORT bool nfc_initiator_transceive_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx, size_t * pszRx); NFC_EXPORT bool nfc_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); + NFC_EXPORT bool nfc_initiator_transceive_bytes_timed (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx, size_t * pszRx, uint16_t * cycles); + NFC_EXPORT bool nfc_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, uint16_t * cycles); /* NFC target: act as tag (i.e. MIFARE Classic) or NFC target device. */ NFC_EXPORT bool nfc_target_init (nfc_device_t * pnd, nfc_target_t * pnt, byte_t * pbtRx, size_t * pszRx); diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index e8f6d3d..7e3dc1f 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1138,6 +1138,81 @@ pn53x_initiator_transceive_bits (nfc_device_t * pnd, const byte_t * pbtTx, const return true; } +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, uint16_t * cycles) +{ + unsigned int i; + uint8_t sz, parity; + uint16_t prescaler = 0; + uint16_t reloadval = 0xFFFF; + uint8_t counter_hi, counter_lo; + uint16_t counter; + + // We can not just send bytes without parity while the PN53X expects we handled them + if (!pnd->bPar) + return false; + // Sorry, no easy framing support + // TODO: to be changed once we'll provide easy framing support from libnfc itself... + if (pnd->bEasyFraming) + return false; + // Sorry, no CRC support + // TODO: to be changed once we'll provide easy CRC support from libnfc itself... + if (pnd->bCrc) + return false; + + // Initialize timer + pn53x_write_register (pnd, REG_CIU_TMODE, 0xFF, SYMBOL_TAUTO | ((prescaler >> 8) & SYMBOL_TPRESCALERHI)); + pn53x_write_register (pnd, REG_CIU_TPRESCALER, 0xFF, (prescaler & SYMBOL_TPRESCALERLO)); + pn53x_write_register (pnd, REG_CIU_TRELOADVALHI, 0xFF, (reloadval >> 8) & 0xFF); + pn53x_write_register (pnd, REG_CIU_TRELOADVALLO, 0xFF, reloadval & 0xFF); + + // Once timer is started, we cannot use Tama commands anymore. + // E.g. on SCL3711 timer settings are reset by 0x42 InCommunicateThru command to: + // 631a=82 631b=a5 631c=02 631d=00 + // Prepare FIFO + pn53x_write_register (pnd, REG_CIU_COMMAND, 0xFF, SYMBOL_COMMAND & SYMBOL_COMMAND_TRANSCEIVE); + pn53x_write_register (pnd, REG_CIU_FIFOLEVEL, 0xFF, SYMBOL_FLUSH_BUFFER); + for (i=0; i< ((szTxBits / 8) + 1); i++) { + pn53x_write_register (pnd, REG_CIU_FIFODATA, 0xFF, pbtTx[i]); + } + + // Send data + pn53x_write_register (pnd, REG_CIU_BIT_FRAMING, 0xFF, SYMBOL_START_SEND | ((szTxBits % 8) & SYMBOL_TX_LAST_BITS)); + + // Recv data + pn53x_read_register (pnd, REG_CIU_FIFOLEVEL, &sz); + *pszRxBits = (sz & SYMBOL_FIFO_LEVEL) * 8; + for (i=0; i< sz; i++) { + pn53x_read_register (pnd, REG_CIU_FIFODATA, &(pbtRx[i])); + } + + // Read timer + pn53x_read_register (pnd, REG_CIU_TCOUNTERVALHI, &counter_hi); + pn53x_read_register (pnd, REG_CIU_TCOUNTERVALLO, &counter_lo); + counter = counter_hi; + counter = (counter << 8) + counter_lo; + if (counter == 0) { + // counter saturated + *cycles = 0xFFFF; + } else { + *cycles = 0xFFFF - counter + 1; + // Correction, depending on last parity bit sent + sz = pbtTx[szTxBits / 8]; + parity = (sz >> 7) ^ ((sz >> 6) & 1) ^ ((sz >> 5) & 1) ^ ((sz >> 4) & 1) ^ ((sz >> 3) & 1) ^ ((sz >> 2) & 1) ^ ((sz >> 1) & 1) ^ (sz & 1); + parity = parity ? 0:1; + if (parity) { + *cycles += CHIP_DATA(pnd)->timer_correction_yy; + } else { + *cycles += CHIP_DATA(pnd)->timer_correction_zy; + } + } + + return true; + + +} + bool pn53x_initiator_transceive_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx, size_t * pszRx) @@ -1182,6 +1257,80 @@ pn53x_initiator_transceive_bytes (nfc_device_t * pnd, const byte_t * pbtTx, cons return true; } +bool +pn53x_initiator_transceive_bytes_timed (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx, + size_t * pszRx, uint16_t * cycles) +{ + unsigned int i; + uint8_t sz, parity; + uint16_t prescaler = 0; + uint16_t reloadval = 0xFFFF; + uint8_t counter_hi, counter_lo; + uint16_t counter; + + // We can not just send bytes without parity while the PN53X expects we handled them + if (!pnd->bPar) + return false; + // Sorry, no easy framing support + // TODO: to be changed once we'll provide easy framing support from libnfc itself... + if (pnd->bEasyFraming) + return false; + // Sorry, no CRC support + // TODO: to be changed once we'll provide easy CRC support from libnfc itself... + if (pnd->bCrc) + return false; + + // Initialize timer + pn53x_write_register (pnd, REG_CIU_TMODE, 0xFF, SYMBOL_TAUTO | ((prescaler >> 8) & SYMBOL_TPRESCALERHI)); + pn53x_write_register (pnd, REG_CIU_TPRESCALER, 0xFF, (prescaler & SYMBOL_TPRESCALERLO)); + pn53x_write_register (pnd, REG_CIU_TRELOADVALHI, 0xFF, (reloadval >> 8) & 0xFF); + pn53x_write_register (pnd, REG_CIU_TRELOADVALLO, 0xFF, reloadval & 0xFF); + + // Once timer is started, we cannot use Tama commands anymore. + // E.g. on SCL3711 timer settings are reset by 0x42 InCommunicateThru command to: + // 631a=82 631b=a5 631c=02 631d=00 + // Prepare FIFO + pn53x_write_register (pnd, REG_CIU_COMMAND, 0xFF, SYMBOL_COMMAND & SYMBOL_COMMAND_TRANSCEIVE); + pn53x_write_register (pnd, REG_CIU_FIFOLEVEL, 0xFF, SYMBOL_FLUSH_BUFFER); + for (i=0; i< szTx; i++) { + pn53x_write_register (pnd, REG_CIU_FIFODATA, 0xFF, pbtTx[i]); + } + + // Send data + pn53x_write_register (pnd, REG_CIU_BIT_FRAMING, 0xFF, SYMBOL_START_SEND); + + // Recv data + pn53x_read_register (pnd, REG_CIU_FIFOLEVEL, &sz); + *pszRx = sz & SYMBOL_FIFO_LEVEL; + for (i=0; i< sz; i++) { + pn53x_read_register (pnd, REG_CIU_FIFODATA, &(pbtRx[i])); + } + + // Read timer + pn53x_read_register (pnd, REG_CIU_TCOUNTERVALHI, &counter_hi); + pn53x_read_register (pnd, REG_CIU_TCOUNTERVALLO, &counter_lo); + counter = counter_hi; + counter = (counter << 8) + counter_lo; + if (counter == 0) { + // counter saturated + *cycles = 0xFFFF; + } else { + *cycles = 0xFFFF - counter + 1; + // Correction, depending on last parity bit sent + sz = pbtTx[szTx -1]; + parity = (sz >> 7) ^ ((sz >> 6) & 1) ^ ((sz >> 5) & 1) ^ ((sz >> 4) & 1) ^ ((sz >> 3) & 1) ^ ((sz >> 2) & 1) ^ ((sz >> 1) & 1) ^ (sz & 1); + parity = parity ? 0:1; + if (parity) { + *cycles += CHIP_DATA(pnd)->timer_correction_yy; + } else { + *cycles += CHIP_DATA(pnd)->timer_correction_zy; + } + } + + return true; +} + + #define SAK_ISO14443_4_COMPLIANT 0x20 bool pn53x_target_init (nfc_device_t * pnd, nfc_target_t * pnt, byte_t * pbtRx, size_t * pszRx) diff --git a/libnfc/chips/pn53x.h b/libnfc/chips/pn53x.h index 54e0f8a..4dd2186 100644 --- a/libnfc/chips/pn53x.h +++ b/libnfc/chips/pn53x.h @@ -39,6 +39,11 @@ // 11 : ISO/IEC 14443B # define SYMBOL_TX_FRAMING 0x03 +# define REG_CONTROL_SWITCH_RNG 0x6106 +# define SYMBOL_CURLIMOFF 0x08 /* When set to 1, the 100 mA current limitations is desactivated. */ +# define SYMBOL_SIC_SWITCH_EN 0x10 /* When set to logic 1, the SVDD switch is enabled and the SVDD output delivers power to secure IC and internal pads (SIGIN, SIGOUT and P34). */ +# define SYMBOL_RANDOM_DATAREADY 0x02 /* When set to logic 1, a new random number is available. */ + # define REG_CIU_RX_MODE 0x6303 # define SYMBOL_RX_CRC_ENABLE 0x80 # define SYMBOL_RX_NO_ERROR 0x08 @@ -51,29 +56,50 @@ # define SYMBOL_AUTO_WAKE_UP 0x20 # define SYMBOL_INITIAL_RF_ON 0x04 +# define REG_CIU_TXSEL 0x6306 + # define REG_CIU_MANUAL_RCV 0x630D # define SYMBOL_PARITY_DISABLE 0x10 +# define REG_CIU_TMODE 0x631A +# define SYMBOL_TAUTO 0x80 +# define SYMBOL_TPRESCALERHI 0x0F + +# define REG_CIU_TPRESCALER 0x631B +# define SYMBOL_TPRESCALERLO 0xFF + +# define REG_CIU_TRELOADVALHI 0x631C + +# define REG_CIU_TRELOADVALLO 0x631D + +# define REG_CIU_TCOUNTERVALHI 0x631E + +# define REG_CIU_TCOUNTERVALLO 0x631F + +# define REG_CIU_COMMAND 0x6331 +# define SYMBOL_COMMAND 0x0F +# define SYMBOL_COMMAND_TRANSCEIVE 0xC + # define REG_CIU_STATUS2 0x6338 # define SYMBOL_MF_CRYPTO1_ON 0x08 +# define REG_CIU_FIFODATA 0x6339 + +# define REG_CIU_FIFOLEVEL 0x633A +# define SYMBOL_FLUSH_BUFFER 0x80 +# define SYMBOL_FIFO_LEVEL 0x7F + # define REG_CIU_CONTROL 0x633C # define SYMBOL_INITIATOR 0x10 # define SYMBOL_RX_LAST_BITS 0x07 # define REG_CIU_BIT_FRAMING 0x633D +# define SYMBOL_START_SEND 0x80 +# define SYMBOL_RX_ALIGN 0x70 # define SYMBOL_TX_LAST_BITS 0x07 -# define REG_CONTROL_SWITCH_RNG 0x6106 -# define SYMBOL_CURLIMOFF 0x08 /* When set to 1, the 100 mA current limitations is desactivated. */ -# define SYMBOL_SIC_SWITCH_EN 0x10 /* When set to logic 1, the SVDD switch is enabled and the SVDD output delivers power to secure IC and internal pads (SIGIN, SIGOUT and P34). */ -# define SYMBOL_RANDOM_DATAREADY 0x02 /* When set to logic 1, a new random number is available. */ - -# define REG_CIU_TXSEL 0x6306 - # define SFR_P3CFGB 0xFFFD # define SFR_P3 0xFFB0 - // PN53X Support Byte flags #define SUPPORT_ISO14443A 0x01 #define SUPPORT_ISO14443B 0x02 @@ -131,6 +157,10 @@ struct pn53x_data { uint8_t ui8Parameters; /** Last sent command */ uint8_t ui8LastCommand; +/** Interframe correction for commands ending with logic "1" */ + int16_t timer_correction_yy; +/** Interframe correction for commands ending with logic "0" */ + int16_t timer_correction_zy; }; #define CHIP_DATA(pnd) ((struct pn53x_data*)(pnd->chip_data)) @@ -254,6 +284,11 @@ bool pn53x_initiator_transceive_bits (nfc_device_t * pnd, const byte_t * pbtT 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); +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, uint16_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, uint16_t * cycles); bool pn53x_initiator_deselect_target (nfc_device_t * pnd); // NFC device as Target functions diff --git a/libnfc/drivers/acr122.c b/libnfc/drivers/acr122.c index 2270339..f08f9d9 100644 --- a/libnfc/drivers/acr122.c +++ b/libnfc/drivers/acr122.c @@ -222,6 +222,16 @@ acr122_connect (const nfc_device_desc_t * pndd) CHIP_DATA (pnd)->state = NORMAL; CHIP_DATA (pnd)->io = &acr122_io; + + // Timer stops only after 5 bits are received => 5*128 cycles + // When sent ...ZY (cmd ends with logical 0): + // 50: empirical tuning on Touchatag + // 46: empirical tuning on ACR122U + CHIP_DATA (pnd)->timer_correction_zy = 50 - (5 * 128); + // When sent ...YY (cmd ends with logical 1): + // a ...ZY signal finishes 64us later than a ...YY signal + CHIP_DATA (pnd)->timer_correction_yy = CHIP_DATA (pnd)->timer_correction_zy + 64; + pnd->driver = &acr122_driver; pn53x_init (pnd); @@ -410,6 +420,8 @@ const struct nfc_driver_t acr122_driver = { .initiator_deselect_target = pn53x_initiator_deselect_target, .initiator_transceive_bytes = pn53x_initiator_transceive_bytes, .initiator_transceive_bits = pn53x_initiator_transceive_bits, + .initiator_transceive_bytes_timed = pn53x_initiator_transceive_bytes_timed, + .initiator_transceive_bits_timed = pn53x_initiator_transceive_bits_timed, .target_init = NULL, .target_send_bytes = NULL, diff --git a/libnfc/drivers/arygon.c b/libnfc/drivers/arygon.c index 7b8d3f1..43380a7 100644 --- a/libnfc/drivers/arygon.c +++ b/libnfc/drivers/arygon.c @@ -115,6 +115,14 @@ arygon_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDev CHIP_DATA (pnd)->type = PN532; CHIP_DATA (pnd)->state = NORMAL; CHIP_DATA (pnd)->io = &arygon_tama_io; + // Timer stops only after 5 bits are received => 5*128 cycles + // When sent ...ZY (cmd ends with logical 0): + // TODO: calibration + // 50: empirical tuning + CHIP_DATA (pnd)->timer_correction_zy = 50 - (5 * 128); + // When sent ...YY (cmd ends with logical 1): + // a ...ZY signal finishes 64us later than a ...YY signal + CHIP_DATA (pnd)->timer_correction_yy = CHIP_DATA (pnd)->timer_correction_zy + 64; bool res = arygon_reset_tama (pnd); nfc_device_free (pnd); @@ -439,6 +447,8 @@ const struct nfc_driver_t arygon_driver = { .initiator_deselect_target = pn53x_initiator_deselect_target, .initiator_transceive_bytes = pn53x_initiator_transceive_bytes, .initiator_transceive_bits = pn53x_initiator_transceive_bits, + .initiator_transceive_bytes_timed = pn53x_initiator_transceive_bytes_timed, + .initiator_transceive_bits_timed = pn53x_initiator_transceive_bits_timed, .target_init = pn53x_target_init, .target_send_bytes = pn53x_target_send_bytes, diff --git a/libnfc/drivers/pn532_uart.c b/libnfc/drivers/pn532_uart.c index 5f1c823..dc23f7c 100644 --- a/libnfc/drivers/pn532_uart.c +++ b/libnfc/drivers/pn532_uart.c @@ -96,6 +96,14 @@ pn532_uart_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * ps CHIP_DATA (pnd)->type = PN532; CHIP_DATA (pnd)->state = SLEEP; CHIP_DATA (pnd)->io = &pn532_uart_io; + // Timer stops only after 5 bits are received => 5*128 cycles + // When sent ...ZY (cmd ends with logical 0): + // TODO: calibration + // 50: empirical tuning + CHIP_DATA (pnd)->timer_correction_zy = 50 - (5 * 128); + // When sent ...YY (cmd ends with logical 1): + // a ...ZY signal finishes 64us later than a ...YY signal + CHIP_DATA (pnd)->timer_correction_yy = CHIP_DATA (pnd)->timer_correction_zy + 64; // Check communication using "Diagnose" command, with "Communication test" (0x00) bool res = pn53x_check_communication (pnd); @@ -370,6 +378,8 @@ const struct nfc_driver_t pn532_uart_driver = { .initiator_deselect_target = pn53x_initiator_deselect_target, .initiator_transceive_bytes = pn53x_initiator_transceive_bytes, .initiator_transceive_bits = pn53x_initiator_transceive_bits, + .initiator_transceive_bytes_timed = pn53x_initiator_transceive_bytes_timed, + .initiator_transceive_bits_timed = pn53x_initiator_transceive_bits_timed, .target_init = pn53x_target_init, .target_send_bytes = pn53x_target_send_bytes, diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index 05a6fe6..9abe685 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -54,6 +54,7 @@ Thanks to d18c7db and Okko for example code typedef enum { UNKNOWN, NXP_PN531, + SONY_PN531, NXP_PN533, ASK_LOGO, SCM_SCL3711 @@ -105,7 +106,7 @@ const struct pn53x_usb_supported_device pn53x_usb_supported_devices[] = { { 0x04CC, 0x0531, NXP_PN531, "Philips / PN531" }, { 0x04CC, 0x2533, NXP_PN533, "NXP / PN533" }, { 0x04E6, 0x5591, SCM_SCL3711, "SCM Micro / SCL3711-NFC&RW" }, - { 0x054c, 0x0193, NXP_PN531, "Sony / PN531" }, + { 0x054c, 0x0193, SONY_PN531, "Sony / PN531" }, { 0x1FD3, 0x0608, ASK_LOGO, "ASK / LoGO" } }; @@ -285,6 +286,33 @@ pn53x_usb_connect (const nfc_device_desc_t *pndd) CHIP_DATA (pnd)->state = NORMAL; CHIP_DATA (pnd)->io = &pn53x_usb_io; + + switch (DRIVER_DATA (pnd)->model) { + case ASK_LOGO: + // Timer stops only after 5 bits are received => 5*128 cycles + // When sent ...ZY (cmd ends with logical 0): + // 50: empirical tuning + CHIP_DATA (pnd)->timer_correction_zy = 50 - (5 * 128); + // When sent ...YY (cmd ends with logical 1): + // a ...ZY signal finishes 64us later than a ...YY signal + CHIP_DATA (pnd)->timer_correction_yy = CHIP_DATA (pnd)->timer_correction_zy + 64; + break; + case SCM_SCL3711: + case NXP_PN533: + CHIP_DATA (pnd)->timer_correction_zy = 46 - (5 * 128); + CHIP_DATA (pnd)->timer_correction_yy = CHIP_DATA (pnd)->timer_correction_zy + 64; + break; + case NXP_PN531: + CHIP_DATA (pnd)->timer_correction_zy = 50 - (2 * 128); + CHIP_DATA (pnd)->timer_correction_yy = CHIP_DATA (pnd)->timer_correction_zy + 64; + break; + case SONY_PN531: + CHIP_DATA (pnd)->timer_correction_zy = 54 - (2 * 128); + CHIP_DATA (pnd)->timer_correction_yy = CHIP_DATA (pnd)->timer_correction_zy + 64; + break; + default: + break; + } pnd->driver = &pn53x_usb_driver; // HACK1: Send first an ACK as Abort command, to reset chip before talking to it: @@ -591,6 +619,8 @@ const struct nfc_driver_t pn53x_usb_driver = { .initiator_deselect_target = pn53x_initiator_deselect_target, .initiator_transceive_bytes = pn53x_initiator_transceive_bytes, .initiator_transceive_bits = pn53x_initiator_transceive_bits, + .initiator_transceive_bytes_timed = pn53x_initiator_transceive_bytes_timed, + .initiator_transceive_bits_timed = pn53x_initiator_transceive_bits_timed, .target_init = pn53x_target_init, .target_send_bytes = pn53x_target_send_bytes, diff --git a/libnfc/nfc-internal.h b/libnfc/nfc-internal.h index 70d00db..03aad1b 100644 --- a/libnfc/nfc-internal.h +++ b/libnfc/nfc-internal.h @@ -114,6 +114,8 @@ struct nfc_driver_t { 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); 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, uint16_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, uint16_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); diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 9297f37..95d31b8 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -535,6 +535,46 @@ nfc_initiator_transceive_bits (nfc_device_t * pnd, const byte_t * pbtTx, const s HAL (initiator_transceive_bits, pnd, pbtTx, szTxBits, pbtTxPar, pbtRx, pszRxBits, pbtRxPar); } +/** + * @brief Send data to target then retrieve data from target + * @return Returns \c true if action was successfully performed; otherwise returns \c false. + * + * This function is similar to nfc_initiator_transceive_bytes() with the following differences: + * - A precise cycles counter will indicate the number of cycles between emission & reception of frames. + * - It only supports mode with \a NDO_EASY_FRAMING option disabled and CRC must be handled manually. + * - Overall communication with the host is heavier and slower. + * + * @warning The configuration option \a NDO_EASY_FRAMING must be set to \c false. + * @warning The configuration option \a NDO_HANDLE_CRC must be set to \c false. + * @warning The configuration option \a NDO_HANDLE_PARITY must be set to \c true (the default value). + */ +bool +nfc_initiator_transceive_bytes_timed (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx, + size_t * pszRx, uint16_t * cycles) +{ + HAL (initiator_transceive_bytes_timed, pnd, pbtTx, szTx, pbtRx, pszRx, cycles) +} + +/** + * @brief Transceive raw bit-frames to a target + * @return Returns \c true if action was successfully performed; otherwise returns \c false. + * + * This function is similar to nfc_initiator_transceive_bits() with the following differences: + * - A precise cycles counter will indicate the number of cycles between emission & reception of frames. + * - It only supports mode with \a NDO_EASY_FRAMING option disabled and CRC must be handled manually. + * - Overall communication with the host is heavier and slower. + * + * @warning The configuration option \a NDO_EASY_FRAMING must be set to \c false. + * @warning The configuration option \a NDO_HANDLE_CRC must be set to \c false. + * @warning The configuration option \a NDO_HANDLE_PARITY must be set to \c true (the default value). + */ +bool +nfc_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, uint16_t * cycles) +{ + HAL (initiator_transceive_bits_timed, pnd, pbtTx, szTxBits, pbtTxPar, pbtRx, pszRxBits, pbtRxPar, cycles); +} + /** * @brief Initialize NFC device as an emulated tag * @return Returns \c true if action was successfully performed; otherwise returns \c false.