arygon.c

Go to the documentation of this file.
00001 /*-
00002  * Public platform independent Near Field Communication (NFC) library
00003  * 
00004  * Copyright (C) 2009, Roel Verdult
00005  * 
00006  * This program is free software: you can redistribute it and/or modify it
00007  * under the terms of the GNU Lesser General Public License as published by the
00008  * Free Software Foundation, either version 3 of the License, or (at your
00009  * option) any later version.
00010  * 
00011  * This program is distributed in the hope that it will be useful, but WITHOUT
00012  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00013  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
00014  * more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public License
00017  * along with this program.  If not, see <http://www.gnu.org/licenses/>
00018  */
00019 
00028 #ifdef HAVE_CONFIG_H
00029   #include "config.h"
00030 #endif // HAVE_CONFIG_H
00031 
00032 #include "../drivers.h"
00033 #include "../bitutils.h"
00034 
00035 #include <stdio.h>
00036 
00037 #include "arygon.h"
00038 
00039 #include <nfc/nfc-messages.h>
00040 
00041 // Bus
00042 #include "../buses/uart.h"
00043 
00044 #ifdef _WIN32
00045   #define SERIAL_STRING "COM"
00046   #define delay_ms( X ) Sleep( X )
00047 #else
00048   // unistd.h is needed for usleep() fct.
00049   #include <unistd.h>
00050   #define delay_ms( X ) usleep( X * 1000 )
00051 
00052   #ifdef __APPLE__
00053     // MacOS
00054     #define SERIAL_STRING "/dev/tty.SLAB_USBtoUART"
00055   #else
00056     // *BSD, Linux, other POSIX systems
00057     #define SERIAL_STRING "/dev/ttyUSB"
00058   #endif
00059 #endif
00060 
00061 #define BUFFER_LENGTH 256
00062 
00066 #define DEV_ARYGON_PROTOCOL_ARYGON_ASCII        '0'
00067 
00070 #define DEV_ARYGON_PROTOCOL_ARYGON_BINARY_WAB   '1'
00071 
00074 #define DEV_ARYGON_PROTOCOL_TAMA                '2'
00075 
00078 #define DEV_ARYGON_PROTOCOL_TAMA_WAB            '3'
00079 
00080 #define SERIAL_DEFAULT_PORT_SPEED 9600
00081 
00090 nfc_device_t* arygon_connect(const nfc_device_desc_t* pndd)
00091 {
00092   uint32_t uiDevNr;
00093   serial_port sp;
00094   char acConnect[BUFFER_LENGTH];
00095   nfc_device_t* pnd = NULL;
00096 
00097   if( pndd == NULL ) {
00098 #ifndef SERIAL_AUTOPROBE_ENABLED
00099     INFO("%s", "Sorry, serial auto-probing have been disabled at compile time.");
00100     return NULL;
00101 #else /* SERIAL_AUTOPROBE_ENABLED */
00102     DBG("Trying to find ARYGON device on serial port: %s# at %d bauds.",SERIAL_STRING, SERIAL_DEFAULT_PORT_SPEED);
00103     // I have no idea how MAC OS X deals with multiple devices, so a quick workaround
00104     for (uiDevNr=0; uiDevNr<DRIVERS_MAX_DEVICES; uiDevNr++)
00105     {
00106 #ifdef __APPLE__
00107       strcpy(acConnect,SERIAL_STRING);
00108 #else
00109       sprintf(acConnect,"%s%d",SERIAL_STRING,uiDevNr);
00110 #endif /* __APPLE__ */
00111 
00112       sp = uart_open(acConnect);
00113       if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT))
00114       {
00115         uart_set_speed(sp, SERIAL_DEFAULT_PORT_SPEED);
00116         break;
00117       }
00118 #ifdef DEBUG
00119       if (sp == INVALID_SERIAL_PORT) DBG("Invalid serial port: %s",acConnect);
00120       if (sp == CLAIMED_SERIAL_PORT) DBG("Serial port already claimed: %s",acConnect);
00121 #endif /* DEBUG */
00122     }
00123 #endif /* SERIAL_AUTOPROBE_ENABLED */
00124 
00125     // Test if we have found a device
00126     if (uiDevNr == DRIVERS_MAX_DEVICES) return NULL;
00127   } else {
00128     DBG("Connecting to: %s at %d bauds.",pndd->pcPort, pndd->uiSpeed);
00129     strcpy(acConnect,pndd->pcPort);
00130     sp = uart_open(acConnect);
00131     if (sp == INVALID_SERIAL_PORT) ERR("Invalid serial port: %s",acConnect);
00132     if (sp == CLAIMED_SERIAL_PORT) ERR("Serial port already claimed: %s",acConnect);
00133     if ((sp == CLAIMED_SERIAL_PORT) || (sp == INVALID_SERIAL_PORT)) return NULL;
00134 
00135     uart_set_speed(sp, pndd->uiSpeed);
00136   }
00137 
00138   DBG("Successfully connected to: %s",acConnect);
00139 
00140   // We have a connection
00141   pnd = malloc(sizeof(nfc_device_t));
00142   strcpy(pnd->acName,"ARYGON");
00143   pnd->nc = NC_PN532;
00144   pnd->nds = (nfc_device_spec_t)sp;
00145   pnd->bActive = true;
00146   pnd->bCrc = true;
00147   pnd->bPar = true;
00148   pnd->ui8TxBits = 0;
00149   return pnd;
00150 }
00151 
00152 void arygon_disconnect(nfc_device_t* pnd)
00153 {
00154   uart_close((serial_port)pnd->nds);
00155   free(pnd);
00156 }
00157 
00158 bool arygon_transceive(const nfc_device_spec_t nds, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen)
00159 {
00160   byte_t abtTxBuf[BUFFER_LENGTH] = { DEV_ARYGON_PROTOCOL_TAMA, 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
00161   byte_t abtRxBuf[BUFFER_LENGTH];
00162   size_t szRxBufLen = BUFFER_LENGTH;
00163   size_t szPos;
00164 
00165   // Packet length = data length (len) + checksum (1) + end of stream marker (1)
00166   abtTxBuf[4] = szTxLen;
00167   // Packet length checksum
00168   abtTxBuf[5] = BUFFER_LENGTH - abtTxBuf[4];
00169   // Copy the PN53X command into the packet buffer
00170   memmove(abtTxBuf+6,pbtTx,szTxLen);
00171 
00172   // Calculate data payload checksum
00173   abtTxBuf[szTxLen+6] = 0;
00174   for(szPos=0; szPos < szTxLen; szPos++) 
00175   {
00176     abtTxBuf[szTxLen+6] -= abtTxBuf[szPos+6];
00177   }
00178 
00179   // End of stream marker
00180   abtTxBuf[szTxLen+7] = 0;
00181 
00182 #ifdef DEBUG
00183   printf(" TX: ");
00184   print_hex(abtTxBuf,szTxLen+8);
00185 #endif
00186   if (!uart_send((serial_port)nds,abtTxBuf,szTxLen+8)) {
00187     ERR("%s", "Unable to transmit data. (TX)");
00188     return false;
00189   }
00190 
00194   delay_ms(20);
00195 
00199   delay_ms(30);
00200 
00206   if (!uart_receive((serial_port)nds,abtRxBuf,&szRxBufLen)) {
00207     ERR("%s", "Unable to receive data. (RX)");
00208     return false;
00209   }
00210 
00211 #ifdef DEBUG
00212   printf(" RX: ");
00213   print_hex(abtRxBuf,szRxBufLen);
00214 #endif
00215 
00216   // When the answer should be ignored, just return a successful result
00217   if(pbtRx == NULL || pszRxLen == NULL) return true;
00218 
00219   // 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)
00220   if(szRxBufLen < 15) return false;
00221 
00222   // Remove the preceding and appending bytes 00 00 ff 00 ff 00 00 00 FF xx Fx .. .. .. xx 00 (x = variable)
00223   *pszRxLen = szRxBufLen - 15;
00224   memcpy(pbtRx, abtRxBuf+13, *pszRxLen);
00225 
00226   return true;
00227 }
Generated by  doxygen 1.6.2-20100208