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