From 877176c98fb13ce874344938b2417755ce9999bb Mon Sep 17 00:00:00 2001 From: Romuald Conty <romuald@libnfc.org> Date: Fri, 20 Nov 2009 11:27:07 +0000 Subject: [PATCH] Attempt to extract PN53x related code for nfc.c. multichip> chips sub-folder introduction with pn53x.h/c. --- configure.ac | 1 + src/lib/CMakeLists.txt | 6 +- src/lib/Makefile.am | 3 +- src/lib/chips.h | 32 +++++ src/lib/chips/Makefile.am | 10 ++ src/lib/chips/pn53x.c | 231 +++++++++++++++++++++++++++++++++ src/lib/chips/pn53x.h | 80 ++++++++++++ src/lib/drivers.h | 7 +- src/lib/nfc.c | 260 ++++---------------------------------- 9 files changed, 387 insertions(+), 243 deletions(-) create mode 100644 src/lib/chips.h create mode 100644 src/lib/chips/Makefile.am create mode 100644 src/lib/chips/pn53x.c create mode 100644 src/lib/chips/pn53x.h diff --git a/configure.ac b/configure.ac index cdf4713..7dd3326 100644 --- a/configure.ac +++ b/configure.ac @@ -167,6 +167,7 @@ fi AC_CONFIG_FILES([ Makefile + src/lib/chips/Makefile src/lib/buses/Makefile src/lib/drivers/Makefile src/lib/Makefile diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 1db7046..21c637b 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -1,3 +1,7 @@ +# Library's chips +SET(CHIPS_SOURCES chips/pn53x) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/chips) + # Library's buses SET(BUSES_SOURCES buses/uart) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/buses) @@ -24,7 +28,7 @@ ENDIF(LIBNFC_USB) # Library -SET(LIBRARY_SOURCES nfc bitutils ${DRIVERS_SOURCES} ${BUSES_SOURCES}) +SET(LIBRARY_SOURCES nfc bitutils ${DRIVERS_SOURCES} ${BUSES_SOURCES} ${CHIPS_SOURCES}) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) ADD_LIBRARY(nfc SHARED ${LIBRARY_SOURCES}) TARGET_LINK_LIBRARIES(nfc ${LIBUSB_LIBRARIES} ${PCSC_LIBRARIES}) diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 47e143b..f031c1b 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = buses drivers . +SUBDIRS = chips buses drivers . # set the include path found by configure INCLUDES= $(all_includes) @@ -11,6 +11,7 @@ libnfc_la_SOURCES = nfc.c bitutils.c libnfc_la_LDFLAGS = -no-undefined -version-info=0:0:0 libnfc_la_CFLAGS = libnfc_la_LIBADD = \ + $(top_builddir)/src/lib/chips/libnfcchips.la \ $(top_builddir)/src/lib/buses/libnfcbuses.la \ $(top_builddir)/src/lib/drivers/libnfcdrivers.la diff --git a/src/lib/chips.h b/src/lib/chips.h new file mode 100644 index 0000000..109d015 --- /dev/null +++ b/src/lib/chips.h @@ -0,0 +1,32 @@ +/** + * Public platform independent Near Field Communication (NFC) library + * + * Copyright (C) 2009, Roel Verdult + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + * + * @file chips.h + * @brief NFC chips header + */ + +#ifndef __NFC_CHIPS_H__ +#define __NFC_CHIPS_H__ + +#include "nfc-types.h" + +#include "chips/pn53x.h" + +#endif // __NFC_CHIPS_H__ + diff --git a/src/lib/chips/Makefile.am b/src/lib/chips/Makefile.am new file mode 100644 index 0000000..5ab4d16 --- /dev/null +++ b/src/lib/chips/Makefile.am @@ -0,0 +1,10 @@ + +# set the include path found by configure +INCLUDES= $(all_includes) + +noinst_HEADERS = pn53x.h +noinst_LTLIBRARIES = libnfcchips.la +libnfcchips_la_SOURCES = pn53x.c +libnfcchips_la_CFLAGS = -I$(top_srcdir)/src/lib + +DISTCLEANFILES = Makefile.in diff --git a/src/lib/chips/pn53x.c b/src/lib/chips/pn53x.c new file mode 100644 index 0000000..f4b841f --- /dev/null +++ b/src/lib/chips/pn53x.c @@ -0,0 +1,231 @@ +/** + * Public platform independent Near Field Communication (NFC) library + * + * Copyright (C) 2009, Roel Verdult + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + * + * @file pn53x.h + * @brief PN531, PN532 and PN533 common functions + */ + +#include "pn53x.h" + +#include "bitutils.h" + +// PN53X configuration +const byte_t pncmd_get_firmware_version [ 2] = { 0xD4,0x02 }; +const byte_t pncmd_get_general_status [ 2] = { 0xD4,0x04 }; +const byte_t pncmd_get_register [ 4] = { 0xD4,0x06 }; +const byte_t pncmd_set_register [ 5] = { 0xD4,0x08 }; +const byte_t pncmd_set_parameters [ 3] = { 0xD4,0x12 }; +const byte_t pncmd_rf_configure [ 14] = { 0xD4,0x32 }; + +// Reader +const byte_t pncmd_initiator_list_passive [264] = { 0xD4,0x4A }; +const byte_t pncmd_initiator_jump_for_dep [ 68] = { 0xD4,0x56 }; +const byte_t pncmd_initiator_select [ 3] = { 0xD4,0x54 }; +const byte_t pncmd_initiator_deselect [ 3] = { 0xD4,0x44,0x00 }; +const byte_t pncmd_initiator_release [ 3] = { 0xD4,0x52,0x00 }; +const byte_t pncmd_initiator_set_baud_rate [ 5] = { 0xD4,0x4E }; +const byte_t pncmd_initiator_exchange_data [265] = { 0xD4,0x40 }; +const byte_t pncmd_initiator_exchange_raw_data [266] = { 0xD4,0x42 }; +const byte_t pncmd_initiator_auto_poll [ 5] = { 0xD4,0x60 }; + +// Target +const byte_t pncmd_target_get_data [ 2] = { 0xD4,0x86 }; +const byte_t pncmd_target_set_data [264] = { 0xD4,0x8E }; +const byte_t pncmd_target_init [ 39] = { 0xD4,0x8C }; +const byte_t pncmd_target_virtual_card [ 4] = { 0xD4,0x14 }; +const byte_t pncmd_target_receive [ 2] = { 0xD4,0x88 }; +const byte_t pncmd_target_send [264] = { 0xD4,0x90 }; +const byte_t pncmd_target_get_status [ 2] = { 0xD4,0x8A }; + + +bool pn53x_transceive(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) +{ + byte_t abtRx[MAX_FRAME_LEN]; + size_t szRxLen; + + // Check if receiving buffers are available, if not, replace them + if (!pszRxLen || !pbtRx) + { + pbtRx = abtRx; + pszRxLen = &szRxLen; + } + + *pszRxLen = MAX_FRAME_LEN; + // Call the tranceive callback function of the current device + if (!pnd->pdc->transceive(pnd->nds,pbtTx,szTxLen,pbtRx,pszRxLen)) return false; + + // Make sure there was no failure reported by the PN53X chip (0x00 == OK) + if (pbtRx[0] != 0) return false; + + // Succesful transmission + return true; +} + +byte_t pn53x_get_reg(const nfc_device_t* pnd, uint16_t ui16Reg) +{ + uint8_t ui8Value; + size_t szValueLen = 1; + byte_t abtCmd[sizeof(pncmd_get_register)]; + memcpy(abtCmd,pncmd_get_register,sizeof(pncmd_get_register)); + + abtCmd[2] = ui16Reg >> 8; + abtCmd[3] = ui16Reg & 0xff; + // We can not use pn53x_transceive() because abtRx[0] gives no status info + pnd->pdc->transceive(pnd->nds,abtCmd,4,&ui8Value,&szValueLen); + return ui8Value; +} + +bool pn53x_set_reg(const nfc_device_t* pnd, uint16_t ui16Reg, uint8_t ui8SybmolMask, uint8_t ui8Value) +{ + byte_t abtCmd[sizeof(pncmd_set_register)]; + memcpy(abtCmd,pncmd_set_register,sizeof(pncmd_set_register)); + + abtCmd[2] = ui16Reg >> 8; + abtCmd[3] = ui16Reg & 0xff; + abtCmd[4] = ui8Value | (pn53x_get_reg(pnd,ui16Reg) & (~ui8SybmolMask)); + // We can not use pn53x_transceive() because abtRx[0] gives no status info + return pnd->pdc->transceive(pnd->nds,abtCmd,5,NULL,NULL); +} + +bool pn53x_set_parameters(const nfc_device_t* pnd, uint8_t ui8Value) +{ + byte_t abtCmd[sizeof(pncmd_set_parameters)]; + memcpy(abtCmd,pncmd_set_parameters,sizeof(pncmd_set_parameters)); + + abtCmd[2] = ui8Value; + // We can not use pn53x_transceive() because abtRx[0] gives no status info + return pnd->pdc->transceive(pnd->nds,abtCmd,3,NULL,NULL); +} + +bool pn53x_set_tx_bits(const nfc_device_t* pnd, uint8_t ui8Bits) +{ + // Test if we need to update the transmission bits register setting + if (pnd->ui8TxBits != ui8Bits) + { + // Set the amount of transmission bits in the PN53X chip register + if (!pn53x_set_reg(pnd,REG_CIU_BIT_FRAMING,SYMBOL_TX_LAST_BITS,ui8Bits)) return false; + + // Store the new setting + ((nfc_device_t*)pnd)->ui8TxBits = ui8Bits; + } + return true; +} + +bool pn53x_wrap_frame(const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar, byte_t* pbtFrame, size_t* pszFrameBits) +{ + byte_t btFrame; + byte_t btData; + uint32_t uiBitPos; + uint32_t uiDataPos = 0; + size_t szBitsLeft = szTxBits; + + // Make sure we should frame at least something + if (szBitsLeft == 0) return false; + + // Handle a short response (1byte) as a special case + if (szBitsLeft < 9) + { + *pbtFrame = *pbtTx; + *pszFrameBits = szTxBits; + return true; + } + + // We start by calculating the frame length in bits + *pszFrameBits = szTxBits + (szTxBits/8); + + // Parse the data bytes and add the parity bits + // This is really a sensitive process, mirror the frame bytes and append parity bits + // buffer = mirror(frame-byte) + parity + mirror(frame-byte) + parity + ... + // split "buffer" up in segments of 8 bits again and mirror them + // air-bytes = mirror(buffer-byte) + mirror(buffer-byte) + mirror(buffer-byte) + .. + while(true) + { + // Reset the temporary frame byte; + btFrame = 0; + + for (uiBitPos=0; uiBitPos<8; uiBitPos++) + { + // Copy as much data that fits in the frame byte + btData = mirror(pbtTx[uiDataPos]); + btFrame |= (btData >> uiBitPos); + // Save this frame byte + *pbtFrame = mirror(btFrame); + // Set the remaining bits of the date in the new frame byte and append the parity bit + btFrame = (btData << (8-uiBitPos)); + btFrame |= ((pbtTxPar[uiDataPos] & 0x01) << (7-uiBitPos)); + // Backup the frame bits we have so far + pbtFrame++; + *pbtFrame = mirror(btFrame); + // Increase the data (without parity bit) position + uiDataPos++; + // Test if we are done + if (szBitsLeft < 9) return true; + szBitsLeft -= 8; + } + // Every 8 data bytes we lose one frame byte to the parities + pbtFrame++; + } +} + +bool pn53x_unwrap_frame(const byte_t* pbtFrame, const size_t szFrameBits, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar) +{ + byte_t btFrame; + byte_t btData; + uint8_t uiBitPos; + uint32_t uiDataPos = 0; + byte_t* pbtFramePos = (byte_t*) pbtFrame; + size_t szBitsLeft = szFrameBits; + + // Make sure we should frame at least something + if (szBitsLeft == 0) return false; + + // Handle a short response (1byte) as a special case + if (szBitsLeft < 9) + { + *pbtRx = *pbtFrame; + *pszRxBits = szFrameBits; + return true; + } + + // Calculate the data length in bits + *pszRxBits = szFrameBits - (szFrameBits/9); + + // Parse the frame bytes, remove the parity bits and store them in the parity array + // This process is the reverse of WrapFrame(), look there for more info + while(true) + { + for (uiBitPos=0; uiBitPos<8; uiBitPos++) + { + btFrame = mirror(pbtFramePos[uiDataPos]); + btData = (btFrame << uiBitPos); + btFrame = mirror(pbtFramePos[uiDataPos+1]); + btData |= (btFrame >> (8-uiBitPos)); + pbtRx[uiDataPos] = mirror(btData); + if(pbtRxPar != NULL) pbtRxPar[uiDataPos] = ((btFrame >> (7-uiBitPos)) & 0x01); + // Increase the data (without parity bit) position + uiDataPos++; + // Test if we are done + if (szBitsLeft < 9) return true; + szBitsLeft -= 9; + } + // Every 8 data bytes we lose one frame byte to the parities + pbtFramePos++; + } +} + diff --git a/src/lib/chips/pn53x.h b/src/lib/chips/pn53x.h new file mode 100644 index 0000000..e151d95 --- /dev/null +++ b/src/lib/chips/pn53x.h @@ -0,0 +1,80 @@ +/** + * Public platform independent Near Field Communication (NFC) library + * + * Copyright (C) 2009, Roel Verdult + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + * + * @file pn53x.h + * @brief PN531, PN532 and PN533 common functions + */ + +#ifndef __NFC_CHIPS_PN53X_H__ +#define __NFC_CHIPS_PN53X_H__ + +#include "nfc-types.h" + +#define MAX_FRAME_LEN 264 + +// Registers and symbols masks used to covers parts within a register +#define REG_CIU_TX_MODE 0x6302 + #define SYMBOL_TX_CRC_ENABLE 0x80 +#define REG_CIU_RX_MODE 0x6303 + #define SYMBOL_RX_CRC_ENABLE 0x80 + #define SYMBOL_RX_NO_ERROR 0x08 + #define SYMBOL_RX_MULTIPLE 0x04 +#define REG_CIU_TX_AUTO 0x6305 + #define SYMBOL_FORCE_100_ASK 0x40 + #define SYMBOL_AUTO_WAKE_UP 0x20 + #define SYMBOL_INITIAL_RF_ON 0x04 +#define REG_CIU_MANUAL_RCV 0x630D + #define SYMBOL_PARITY_DISABLE 0x10 +#define REG_CIU_STATUS2 0x6338 + #define SYMBOL_MF_CRYPTO1_ON 0x08 +#define REG_CIU_CONTROL 0x633C + #define SYMBOL_INITIATOR 0x10 + #define SYMBOL_RX_LAST_BITS 0x07 +#define REG_CIU_BIT_FRAMING 0x633D + #define SYMBOL_TX_LAST_BITS 0x07 + +// Internal parameters flags +#define PARAM_NONE 0x00 +#define PARAM_NAD_USED 0x01 +#define PARAM_DID_USED 0x02 +#define PARAM_AUTO_ATR_RES 0x04 +#define PARAM_AUTO_RATS 0x10 +#define PARAM_14443_4_PICC 0x20 +#define PARAM_NO_AMBLE 0x40 + +// Radio Field Configure Items // Configuration Data length +#define RFCI_FIELD 0x01 // 1 +#define RFCI_TIMING 0x02 // 3 +#define RFCI_RETRY_DATA 0x04 // 1 +#define RFCI_RETRY_SELECT 0x05 // 3 +#define RFCI_ANALOG_TYPE_A_106 0x0A // 11 +#define RFCI_ANALOG_TYPE_A_212_424 0x0B // 8 +#define RFCI_ANALOG_TYPE_B 0x0C // 3 +#define RFCI_ANALOG_TYPE_14443_4 0x0D // 9 + +bool pn53x_transceive(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); +byte_t pn53x_get_reg(const nfc_device_t* pnd, uint16_t ui16Reg); +bool pn53x_set_reg(const nfc_device_t* pnd, uint16_t ui16Reg, uint8_t ui8SybmolMask, uint8_t ui8Value); +bool pn53x_set_parameters(const nfc_device_t* pnd, uint8_t ui8Value); +bool pn53x_set_tx_bits(const nfc_device_t* pnd, 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); + +#endif // __NFC_CHIPS_PN53X_H__ + diff --git a/src/lib/drivers.h b/src/lib/drivers.h index b20778e..dbaf9f8 100644 --- a/src/lib/drivers.h +++ b/src/lib/drivers.h @@ -21,9 +21,8 @@ * @brief */ -#ifndef _LIBNFC_DEVICES_H_ -#define _LIBNFC_DEVICES_H_ - +#ifndef __NFC_DRIVERS_H__ +#define __NFC_DRIVERS_H__ #include "nfc-types.h" @@ -55,5 +54,5 @@ const static struct driver_callbacks drivers_callbacks_list[] = { { "ARYGON", arygon_connect, arygon_transceive, arygon_disconnect } }; -#endif // _LIBNFC_DEVICES_H_ +#endif // __NFC_DRIVERS_H__ diff --git a/src/lib/nfc.c b/src/lib/nfc.c index 43df5c6..964a0b4 100644 --- a/src/lib/nfc.c +++ b/src/lib/nfc.c @@ -27,254 +27,40 @@ #include <stddef.h> #include <string.h> +#include "chips.h" #include "drivers.h" #include "nfc-messages.h" #include "../../config.h" -// Registers and symbols masks used to covers parts within a register -#define REG_CIU_TX_MODE 0x6302 - #define SYMBOL_TX_CRC_ENABLE 0x80 -#define REG_CIU_RX_MODE 0x6303 - #define SYMBOL_RX_CRC_ENABLE 0x80 - #define SYMBOL_RX_NO_ERROR 0x08 - #define SYMBOL_RX_MULTIPLE 0x04 -#define REG_CIU_TX_AUTO 0x6305 - #define SYMBOL_FORCE_100_ASK 0x40 - #define SYMBOL_AUTO_WAKE_UP 0x20 - #define SYMBOL_INITIAL_RF_ON 0x04 -#define REG_CIU_MANUAL_RCV 0x630D - #define SYMBOL_PARITY_DISABLE 0x10 -#define REG_CIU_STATUS2 0x6338 - #define SYMBOL_MF_CRYPTO1_ON 0x08 -#define REG_CIU_CONTROL 0x633C - #define SYMBOL_INITIATOR 0x10 - #define SYMBOL_RX_LAST_BITS 0x07 -#define REG_CIU_BIT_FRAMING 0x633D - #define SYMBOL_TX_LAST_BITS 0x07 - -// Internal parameters flags -#define PARAM_NONE 0x00 -#define PARAM_NAD_USED 0x01 -#define PARAM_DID_USED 0x02 -#define PARAM_AUTO_ATR_RES 0x04 -#define PARAM_AUTO_RATS 0x10 -#define PARAM_14443_4_PICC 0x20 -#define PARAM_NO_AMBLE 0x40 - -// Radio Field Configure Items // Configuration Data length -#define RFCI_FIELD 0x01 // 1 -#define RFCI_TIMING 0x02 // 3 -#define RFCI_RETRY_DATA 0x04 // 1 -#define RFCI_RETRY_SELECT 0x05 // 3 -#define RFCI_ANALOG_TYPE_A_106 0x0A // 11 -#define RFCI_ANALOG_TYPE_A_212_424 0x0B // 8 -#define RFCI_ANALOG_TYPE_B 0x0C // 3 -#define RFCI_ANALOG_TYPE_14443_4 0x0D // 9 - // PN53X configuration -const byte_t pncmd_get_firmware_version [ 2] = { 0xD4,0x02 }; -const byte_t pncmd_get_general_status [ 2] = { 0xD4,0x04 }; -const byte_t pncmd_get_register [ 4] = { 0xD4,0x06 }; -const byte_t pncmd_set_register [ 5] = { 0xD4,0x08 }; -const byte_t pncmd_set_parameters [ 3] = { 0xD4,0x12 }; -const byte_t pncmd_rf_configure [ 14] = { 0xD4,0x32 }; +extern const byte_t pncmd_get_firmware_version [ 2]; +extern const byte_t pncmd_get_general_status [ 2]; +extern const byte_t pncmd_get_register [ 4]; +extern const byte_t pncmd_set_register [ 5]; +extern const byte_t pncmd_set_parameters [ 3]; +extern const byte_t pncmd_rf_configure [ 14]; // Reader -const byte_t pncmd_initiator_list_passive [264] = { 0xD4,0x4A }; -const byte_t pncmd_initiator_jump_for_dep [ 68] = { 0xD4,0x56 }; -const byte_t pncmd_initiator_select [ 3] = { 0xD4,0x54 }; -const byte_t pncmd_initiator_deselect [ 3] = { 0xD4,0x44,0x00 }; -const byte_t pncmd_initiator_release [ 3] = { 0xD4,0x52,0x00 }; -const byte_t pncmd_initiator_set_baud_rate [ 5] = { 0xD4,0x4E }; -const byte_t pncmd_initiator_exchange_data [265] = { 0xD4,0x40 }; -const byte_t pncmd_initiator_exchange_raw_data [266] = { 0xD4,0x42 }; -const byte_t pncmd_initiator_auto_poll [ 5] = { 0xD4,0x60 }; +extern const byte_t pncmd_initiator_list_passive [264]; +extern const byte_t pncmd_initiator_jump_for_dep [ 68]; +extern const byte_t pncmd_initiator_select [ 3]; +extern const byte_t pncmd_initiator_deselect [ 3]; +extern const byte_t pncmd_initiator_release [ 3]; +extern const byte_t pncmd_initiator_set_baud_rate [ 5]; +extern const byte_t pncmd_initiator_exchange_data [265]; +extern const byte_t pncmd_initiator_exchange_raw_data [266]; +extern const byte_t pncmd_initiator_auto_poll [ 5]; // Target -const byte_t pncmd_target_get_data [ 2] = { 0xD4,0x86 }; -const byte_t pncmd_target_set_data [264] = { 0xD4,0x8E }; -const byte_t pncmd_target_init [ 39] = { 0xD4,0x8C }; -const byte_t pncmd_target_virtual_card [ 4] = { 0xD4,0x14 }; -const byte_t pncmd_target_receive [ 2] = { 0xD4,0x88 }; -const byte_t pncmd_target_send [264] = { 0xD4,0x90 }; -const byte_t pncmd_target_get_status [ 2] = { 0xD4,0x8A }; - -bool pn53x_transceive(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) -{ - byte_t abtRx[MAX_FRAME_LEN]; - size_t szRxLen; - - // Check if receiving buffers are available, if not, replace them - if (!pszRxLen || !pbtRx) - { - pbtRx = abtRx; - pszRxLen = &szRxLen; - } - - *pszRxLen = MAX_FRAME_LEN; - // Call the tranceive callback function of the current device - if (!pnd->pdc->transceive(pnd->nds,pbtTx,szTxLen,pbtRx,pszRxLen)) return false; - - // Make sure there was no failure reported by the PN53X chip (0x00 == OK) - if (pbtRx[0] != 0) return false; - - // Succesful transmission - return true; -} - -byte_t pn53x_get_reg(const nfc_device_t* pnd, uint16_t ui16Reg) -{ - uint8_t ui8Value; - size_t szValueLen = 1; - byte_t abtCmd[sizeof(pncmd_get_register)]; - memcpy(abtCmd,pncmd_get_register,sizeof(pncmd_get_register)); - - abtCmd[2] = ui16Reg >> 8; - abtCmd[3] = ui16Reg & 0xff; - // We can not use pn53x_transceive() because abtRx[0] gives no status info - pnd->pdc->transceive(pnd->nds,abtCmd,4,&ui8Value,&szValueLen); - return ui8Value; -} - -bool pn53x_set_reg(const nfc_device_t* pnd, uint16_t ui16Reg, uint8_t ui8SybmolMask, uint8_t ui8Value) -{ - byte_t abtCmd[sizeof(pncmd_set_register)]; - memcpy(abtCmd,pncmd_set_register,sizeof(pncmd_set_register)); - - abtCmd[2] = ui16Reg >> 8; - abtCmd[3] = ui16Reg & 0xff; - abtCmd[4] = ui8Value | (pn53x_get_reg(pnd,ui16Reg) & (~ui8SybmolMask)); - // We can not use pn53x_transceive() because abtRx[0] gives no status info - return pnd->pdc->transceive(pnd->nds,abtCmd,5,NULL,NULL); -} - -bool pn53x_set_parameters(const nfc_device_t* pnd, uint8_t ui8Value) -{ - byte_t abtCmd[sizeof(pncmd_set_parameters)]; - memcpy(abtCmd,pncmd_set_parameters,sizeof(pncmd_set_parameters)); - - abtCmd[2] = ui8Value; - // We can not use pn53x_transceive() because abtRx[0] gives no status info - return pnd->pdc->transceive(pnd->nds,abtCmd,3,NULL,NULL); -} - -bool pn53x_set_tx_bits(const nfc_device_t* pnd, uint8_t ui8Bits) -{ - // Test if we need to update the transmission bits register setting - if (pnd->ui8TxBits != ui8Bits) - { - // Set the amount of transmission bits in the PN53X chip register - if (!pn53x_set_reg(pnd,REG_CIU_BIT_FRAMING,SYMBOL_TX_LAST_BITS,ui8Bits)) return false; - - // Store the new setting - ((nfc_device_t*)pnd)->ui8TxBits = ui8Bits; - } - return true; -} - -bool pn53x_wrap_frame(const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar, byte_t* pbtFrame, size_t* pszFrameBits) -{ - byte_t btFrame; - byte_t btData; - uint32_t uiBitPos; - uint32_t uiDataPos = 0; - size_t szBitsLeft = szTxBits; - - // Make sure we should frame at least something - if (szBitsLeft == 0) return false; - - // Handle a short response (1byte) as a special case - if (szBitsLeft < 9) - { - *pbtFrame = *pbtTx; - *pszFrameBits = szTxBits; - return true; - } - - // We start by calculating the frame length in bits - *pszFrameBits = szTxBits + (szTxBits/8); - - // Parse the data bytes and add the parity bits - // This is really a sensitive process, mirror the frame bytes and append parity bits - // buffer = mirror(frame-byte) + parity + mirror(frame-byte) + parity + ... - // split "buffer" up in segments of 8 bits again and mirror them - // air-bytes = mirror(buffer-byte) + mirror(buffer-byte) + mirror(buffer-byte) + .. - while(true) - { - // Reset the temporary frame byte; - btFrame = 0; - - for (uiBitPos=0; uiBitPos<8; uiBitPos++) - { - // Copy as much data that fits in the frame byte - btData = mirror(pbtTx[uiDataPos]); - btFrame |= (btData >> uiBitPos); - // Save this frame byte - *pbtFrame = mirror(btFrame); - // Set the remaining bits of the date in the new frame byte and append the parity bit - btFrame = (btData << (8-uiBitPos)); - btFrame |= ((pbtTxPar[uiDataPos] & 0x01) << (7-uiBitPos)); - // Backup the frame bits we have so far - pbtFrame++; - *pbtFrame = mirror(btFrame); - // Increase the data (without parity bit) position - uiDataPos++; - // Test if we are done - if (szBitsLeft < 9) return true; - szBitsLeft -= 8; - } - // Every 8 data bytes we lose one frame byte to the parities - pbtFrame++; - } -} - -bool pn53x_unwrap_frame(const byte_t* pbtFrame, const size_t szFrameBits, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar) -{ - byte_t btFrame; - byte_t btData; - uint8_t uiBitPos; - uint32_t uiDataPos = 0; - byte_t* pbtFramePos = (byte_t*) pbtFrame; - size_t szBitsLeft = szFrameBits; - - // Make sure we should frame at least something - if (szBitsLeft == 0) return false; - - // Handle a short response (1byte) as a special case - if (szBitsLeft < 9) - { - *pbtRx = *pbtFrame; - *pszRxBits = szFrameBits; - return true; - } - - // Calculate the data length in bits - *pszRxBits = szFrameBits - (szFrameBits/9); - - // Parse the frame bytes, remove the parity bits and store them in the parity array - // This process is the reverse of WrapFrame(), look there for more info - while(true) - { - for (uiBitPos=0; uiBitPos<8; uiBitPos++) - { - btFrame = mirror(pbtFramePos[uiDataPos]); - btData = (btFrame << uiBitPos); - btFrame = mirror(pbtFramePos[uiDataPos+1]); - btData |= (btFrame >> (8-uiBitPos)); - pbtRx[uiDataPos] = mirror(btData); - if(pbtRxPar != NULL) pbtRxPar[uiDataPos] = ((btFrame >> (7-uiBitPos)) & 0x01); - // Increase the data (without parity bit) position - uiDataPos++; - // Test if we are done - if (szBitsLeft < 9) return true; - szBitsLeft -= 9; - } - // Every 8 data bytes we lose one frame byte to the parities - pbtFramePos++; - } -} +extern const byte_t pncmd_target_get_data [ 2]; +extern const byte_t pncmd_target_set_data [264]; +extern const byte_t pncmd_target_init [ 39]; +extern const byte_t pncmd_target_virtual_card [ 4]; +extern const byte_t pncmd_target_receive [ 2]; +extern const byte_t pncmd_target_send [264]; +extern const byte_t pncmd_target_get_status [ 2]; nfc_device_t* nfc_connect(nfc_device_desc_t* pndd) {