From b16bc5302533ed157f67004eed352467965217c7 Mon Sep 17 00:00:00 2001
From: Romuald Conty <romuald@libnfc.org>
Date: Fri, 28 Aug 2009 16:54:04 +0000
Subject: [PATCH] Attempt to support ARYGON APDB (APDB1UA33N and APDB2UA33).
 Code clean up.

---
 src/dev_arygon.c | 85 +++++++++++++++++++++++++++++-------------------
 src/libnfc.c     |  8 ++---
 src/list.c       | 34 +++++++++----------
 src/rs232.c      | 34 ++++++++++++++-----
 4 files changed, 99 insertions(+), 62 deletions(-)

diff --git a/src/dev_arygon.c b/src/dev_arygon.c
index 997ac41..df25eee 100644
--- a/src/dev_arygon.c
+++ b/src/dev_arygon.c
@@ -34,7 +34,25 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>
 
 #define BUFFER_LENGTH 256
 #define USB_TIMEOUT   30000
-static byte_t abtTxBuf[BUFFER_LENGTH] = { 0x32, 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
+
+/** @def DEV_ARYGON_PROTOCOL_ARYGON_ASCII
+ * @brief High level language in ASCII format. (Common µC commands and Mifare® commands) 
+ */
+#define DEV_ARYGON_PROTOCOL_ARYGON_ASCII        '0'
+/** @def DEV_ARYGON_MODE_HL_ASCII
+ * @brief High level language in Binary format With AddressingByte for party line. (Common µC commands and Mifare® commands) 
+ */
+#define DEV_ARYGON_PROTOCOL_ARYGON_BINARY_WAB   '1'
+/** @def DEV_ARYGON_PROTOCOL_TAMA
+ * @brief Philips protocol (TAMA language) in binary format.
+ */
+#define DEV_ARYGON_PROTOCOL_TAMA                '2'
+/** @def DEV_ARYGON_PROTOCOL_TAMA_WAB
+ * @brief Philips protocol (TAMA language) in binary With AddressingByte for party line.
+ */
+#define DEV_ARYGON_PROTOCOL_TAMA_WAB            '3'
+
+static byte_t abtTxBuf[BUFFER_LENGTH] = { DEV_ARYGON_PROTOCOL_TAMA, 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
 
 dev_info* dev_arygon_connect(const uint32_t uiIndex)
 {
@@ -42,11 +60,9 @@ dev_info* dev_arygon_connect(const uint32_t uiIndex)
   serial_port sp;
   char acConnect[BUFFER_LENGTH];
   dev_info* pdi = INVALID_DEVICE_INFO;
-  
-#ifdef DEBUG
-  printf("Trying to find ARYGON device on serial port: %s#\n",SERIAL_STRING);
-#endif
-  
+
+  DBG("Trying to find ARYGON device on serial port: %s#",SERIAL_STRING);
+
   // I have no idea how MAC OS X deals with multiple devices, so a quick workaround
   for (uiDevNr=0; uiDevNr<MAX_DEVICES; uiDevNr++)
   {
@@ -59,17 +75,15 @@ dev_info* dev_arygon_connect(const uint32_t uiIndex)
     #endif
     if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) break;
     #ifdef DEBUG
-      if (sp == INVALID_SERIAL_PORT) printf("invalid serial port: %s\n",acConnect);
-      if (sp == CLAIMED_SERIAL_PORT) printf("serial port already claimed: %s\n",acConnect);
+      if (sp == INVALID_SERIAL_PORT) DBG("Invalid serial port: %s",acConnect);
+      if (sp == CLAIMED_SERIAL_PORT) DBG("Serial port already claimed: %s",acConnect);
     #endif
   }
   // Test if we have found a device
   if (uiDevNr == MAX_DEVICES) return INVALID_DEVICE_INFO;
-  
-#ifdef DEBUG
-  printf("Succesfully connected to: %s\n",acConnect);
-#endif
-  
+
+  DBG("Successfully connected to: %s",acConnect);
+
   // We have a connection
   pdi = malloc(sizeof(dev_info));
   strcpy(pdi->acName,"ARYGON");
@@ -80,60 +94,65 @@ dev_info* dev_arygon_connect(const uint32_t uiIndex)
   pdi->bPar = true;
   pdi->ui8TxBits = 0;
   return pdi;
-}                                                                                          
+}
 
 void dev_arygon_disconnect(dev_info* pdi)
 {
   rs232_close((serial_port)pdi->ds);
   free(pdi);
-}                                        
+}
 
 bool dev_arygon_transceive(const dev_spec ds, const byte_t* pbtTx, const uint32_t uiTxLen, byte_t* pbtRx, uint32_t* puiRxLen)
 {
   byte_t abtRxBuf[BUFFER_LENGTH];
   uint32_t uiRxBufLen = BUFFER_LENGTH;
   uint32_t uiPos;
-    
+
   // Packet length = data length (len) + checksum (1) + end of stream marker (1)
-  abtTxBuf[4] = uiTxLen;                                                                
-  // Packet length checksum 
-  abtTxBuf[5] = BUFFER_LENGTH - abtTxBuf[4];                                                  
+  abtTxBuf[4] = uiTxLen;
+  // Packet length checksum
+  abtTxBuf[5] = BUFFER_LENGTH - abtTxBuf[4];
   // Copy the PN53X command into the packet buffer
   memmove(abtTxBuf+6,pbtTx,uiTxLen);
-  
+
   // Calculate data payload checksum
-  abtTxBuf[uiTxLen+6] = 0;                   
+  abtTxBuf[uiTxLen+6] = 0;
   for(uiPos=0; uiPos < uiTxLen; uiPos++) 
   {
     abtTxBuf[uiTxLen+6] -= abtTxBuf[uiPos+6];
   }
-  
+
   // End of stream marker
-  abtTxBuf[uiTxLen+7] = 0;        
-  
+  abtTxBuf[uiTxLen+7] = 0;
+
 #ifdef DEBUG
-  printf("Tx: ");
+  printf(" TX: ");
   print_hex(abtTxBuf,uiTxLen+8);
 #endif
-  if (!rs232_send((serial_port)ds,abtTxBuf,uiTxLen+8)) return false;
+  if (!rs232_send((serial_port)ds,abtTxBuf,uiTxLen+8)) {
+    ERR("Unable to transmit data. (TX)");
+    return false;
+  }
 
-  if (!rs232_receive((serial_port)ds,abtRxBuf,&uiRxBufLen)) return false;
-  
+  if (!rs232_receive((serial_port)ds,abtRxBuf,&uiRxBufLen)) {
+    ERR("Unable to receive data. (RX)");
+    return false;
+  }
 
 #ifdef DEBUG
-  printf("Rx: ");
+  printf(" RX: ");
   print_hex(abtRxBuf,uiRxBufLen);
 #endif
-  
-  // When the answer should be ignored, just return a succesful result    
+
+  // When the answer should be ignored, just return a successful result
   if(pbtRx == NULL || puiRxLen == NULL) return true;
 
   // Only succeed when the result is at least 00 00 ff 00 ff 00 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable)
   if(uiRxBufLen < 15) return false;
-  
+
   // Remove the preceding and appending bytes 00 00 ff 00 ff 00 00 00 FF xx Fx .. .. .. xx 00 (x = variable)
   *puiRxLen = uiRxBufLen - 15;
   memcpy(pbtRx, abtRxBuf+13, *puiRxLen);
-  
+
   return true;
 }
diff --git a/src/libnfc.c b/src/libnfc.c
index cdb8524..8fa477a 100644
--- a/src/libnfc.c
+++ b/src/libnfc.c
@@ -256,18 +256,18 @@ dev_info* nfc_connect()
   uint32_t uiDev;
   byte_t abtFw[4];
   uint32_t uiFwLen = sizeof(abtFw);
-  
+
   // Search through the device list for an available device
   for (uiDev=0; uiDev<sizeof(dev_callbacks_list)/sizeof(dev_callbacks_list[0]); uiDev++)
   {
-	  // Try to claim the device
+    // Try to claim the device
     pdi = dev_callbacks_list[uiDev].connect(0);
-	  
+
     // Test if the connection was successful
     if (pdi != INVALID_DEVICE_INFO)
     {
       // Great we have claimed a device
-		  pdi->pdc = &(dev_callbacks_list[uiDev]);
+      pdi->pdc = &(dev_callbacks_list[uiDev]);
       pdi->pdc->transceive(pdi->ds,pncmd_get_register,4,NULL,NULL);
 
       // Try to retrieve PN53x chip revision
diff --git a/src/list.c b/src/list.c
index cb3dc71..ec94bc2 100644
--- a/src/list.c
+++ b/src/list.c
@@ -30,15 +30,15 @@ static dev_info* pdi;
 static byte_t abtFelica[5] = { 0x00, 0xff, 0xff, 0x00, 0x00 };
 
 int main(int argc, const char* argv[])
-{			
+{
   tag_info ti;
 
   // Try to open the NFC reader
   pdi = nfc_connect();
-  
+
   if (pdi == INVALID_DEVICE_INFO)
   {
-    printf("Error connecting NFC reader\n");
+    ERR("Unable to connect to NFC device.");
     return 1;
   }
   nfc_initiator_init(pdi);
@@ -57,7 +57,7 @@ int main(int argc, const char* argv[])
   nfc_configure(pdi,DCO_ACTIVATE_FIELD,true);
 
   printf("\nConnected to NFC reader: %s\n\n",pdi->acName);
-  
+
   // Poll for a ISO14443A (MIFARE) tag
   if (nfc_initiator_select_tag(pdi,IM_ISO14443A_106,NULL,0,&ti))
   {
@@ -80,19 +80,19 @@ int main(int argc, const char* argv[])
     printf("%18s","Parameter (PAD): "); print_hex(ti.tif.abtPad,8);
   }
 
-  // Poll for a ISO14443B tag
-  if (nfc_initiator_select_tag(pdi,IM_ISO14443B_106,"\x00",1,&ti))
-  {
-    printf("The following (NFC) ISO14443-B tag was found:\n\n");
-    printf("  ATQB: "); print_hex(ti.tib.abtAtqb,12);
-    printf("    ID: "); print_hex(ti.tib.abtId,4);
-    printf("   CID: %02x\n",ti.tib.btCid);
-    if (ti.tib.uiInfLen>0)
-    {
-      printf("   INF: "); print_hex(ti.tib.abtInf,ti.tib.uiInfLen);
-    }
-    printf("PARAMS: %02x %02x %02x %02x\n",ti.tib.btParam1,ti.tib.btParam2,ti.tib.btParam3,ti.tib.btParam4);
-  }
+  // Poll for a ISO14443B tag
+  if (nfc_initiator_select_tag(pdi,IM_ISO14443B_106,"\x00",1,&ti))
+  {
+    printf("The following (NFC) ISO14443-B tag was found:\n\n");
+    printf("  ATQB: "); print_hex(ti.tib.abtAtqb,12);
+    printf("    ID: "); print_hex(ti.tib.abtId,4);
+    printf("   CID: %02x\n",ti.tib.btCid);
+    if (ti.tib.uiInfLen>0)
+    {
+      printf("   INF: "); print_hex(ti.tib.abtInf,ti.tib.uiInfLen);
+    }
+    printf("PARAMS: %02x %02x %02x %02x\n",ti.tib.btParam1,ti.tib.btParam2,ti.tib.btParam3,ti.tib.btParam4);
+  }
 
   // Poll for a Jewel tag
   if (nfc_initiator_select_tag(pdi,IM_JEWEL_106,NULL,0,&ti))
diff --git a/src/rs232.c b/src/rs232.c
index 6ea30a7..06bc30d 100644
--- a/src/rs232.c
+++ b/src/rs232.c
@@ -73,12 +73,24 @@ serial_port rs232_open(const char* pcPortName)
   
   // Copy the old terminal info struct
   sp->tiNew = sp->tiOld;
+
+  /** @todo provide this settings dynamically using model provide in configuration file */
   sp->tiNew.c_cflag = CS8 | CLOCAL | CREAD;
   sp->tiNew.c_iflag = CCLAIMED | IGNPAR;
   sp->tiNew.c_oflag = 0;
   sp->tiNew.c_lflag = 0;
-  sp->tiNew.c_cc[VMIN] = 0;      // block untill n bytes are received
-  sp->tiNew.c_cc[VTIME] = 0;     // block untill a timer expires (n * 100 mSec.)
+
+  /**
+   * @note ARYGON-ADRA (PN531): ???,n,8,1
+   * @note ARYGON-ADRB (PN532): ???,n,8,1
+   * @note ARYGON-APDA (PN531): 9600,n,8,1
+   * @note ARYGON-APDB (PN532): 115200,n,8,1
+   */
+  cfsetispeed(&(sp->tiNew), B115200);
+  cfsetospeed(&(sp->tiNew), B115200);
+
+  sp->tiNew.c_cc[VMIN] = 0;      // block until n bytes are received
+  sp->tiNew.c_cc[VTIME] = 0;     // block until a timer expires (n * 100 mSec.)
   if(tcsetattr(sp->fd,TCSANOW,&sp->tiNew) == -1)
   {
     rs232_close(sp);
@@ -106,7 +118,7 @@ bool rs232_receive(const serial_port sp, byte_t* pbtRx, uint32_t* puiRxLen)
   int iResult;
   uint32_t uiCount = 0;
   fd_set rfds;
-  
+
   while (true)
   {
     // Reset file descriptor
@@ -115,18 +127,24 @@ bool rs232_receive(const serial_port sp, byte_t* pbtRx, uint32_t* puiRxLen)
     iResult = select(((serial_port_unix*)sp)->fd+1, &rfds, NULL, NULL, &tv);
 
     // Read error
-    if (iResult < 0) return false;
-  
+    if (iResult < 0) {
+      DBG("RX error.");
+      return false;
+    }
+
     // Read time-out
     if (iResult == 0)
     {
       // Test if we at least have received something
       if (uiCount == 0) return false;
+
+      DBG("RX time-out.");
+
       // Store the received byte count and return succesful
       *puiRxLen = uiCount;
       return true;
     }
-    
+
     // There is something available, read the data
     uiCount += read(((serial_port_unix*)sp)->fd,pbtRx+uiCount,*puiRxLen-uiCount);
   }
@@ -139,7 +157,7 @@ bool rs232_send(const serial_port sp, const byte_t* pbtTx, const uint32_t uiTxLe
   return (iResult >= 0);
 }
 
-#else         
+#else
 // The windows serial port implementation
 
 typedef struct { 
@@ -186,7 +204,7 @@ serial_port rs232_open(const char* pcPortName)
   sp->ct.ReadTotalTimeoutConstant    = 30;
   sp->ct.WriteTotalTimeoutMultiplier = 0;
   sp->ct.WriteTotalTimeoutConstant   = 30;
-  
+
   if(!SetCommTimeouts(sp->hPort,&sp->ct))
   {
     rs232_close(sp);