libnfc  1.4.2
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 
00034 #include <stdio.h>
00035 #include <string.h>
00036 #ifdef HAVE_STRINGS_H
00037 #  include <strings.h>
00038 #endif
00039 
00040 #include "arygon.h"
00041 
00042 #include <nfc/nfc-messages.h>
00043 
00044 // Bus
00045 #include "uart.h"
00046 
00047 #include <sys/param.h>
00048 
00052 #define DEV_ARYGON_PROTOCOL_ARYGON_ASCII        '0'
00053 
00056 #define DEV_ARYGON_PROTOCOL_ARYGON_BINARY_WAB   '1'
00057 
00060 #define DEV_ARYGON_PROTOCOL_TAMA                '2'
00061 
00064 #define DEV_ARYGON_PROTOCOL_TAMA_WAB            '3'
00065 
00066 #define SERIAL_DEFAULT_PORT_SPEED 9600
00067 
00068 // TODO Move this one level up for libnfc-1.6
00069 static const byte_t pn53x_ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
00070 // XXX It seems that sending arygon_ack_frame to cancel current command is not allowed by ARYGON µC (see arygon_ack())
00071 // static const byte_t arygon_ack_frame[] = { DEV_ARYGON_PROTOCOL_TAMA, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
00072 
00073 static const byte_t arygon_error_none[] = "FF000000\x0d\x0a";
00074 static const byte_t arygon_error_incomplete_command[] = "FF0C0000\x0d\x0a";
00075 static const byte_t arygon_error_unknown_mode[] = "FF060000\x0d\x0a";
00076 
00077 // void    arygon_ack (const nfc_device_spec_t nds);
00078 bool    arygon_reset_tama (const nfc_device_spec_t nds);
00079 void    arygon_firmware (const nfc_device_spec_t nds, char * str);
00080 
00081 bool    arygon_check_communication (const nfc_device_spec_t nds);
00082 
00083 nfc_device_desc_t *
00084 arygon_pick_device (void)
00085 {
00086   nfc_device_desc_t *pndd;
00087 
00088   if ((pndd = malloc (sizeof (*pndd)))) {
00089     size_t  szN;
00090 
00091     if (!arygon_list_devices (pndd, 1, &szN)) {
00092       DBG ("%s", "arygon_list_devices failed");
00093       free (pndd);
00094       return NULL;
00095     }
00096 
00097     if (szN == 0) {
00098       DBG ("%s", "No device found");
00099       free (pndd);
00100       return NULL;
00101     }
00102   }
00103   return pndd;
00104 }
00105 
00106 bool
00107 arygon_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound)
00108 {
00112 #ifndef SERIAL_AUTOPROBE_ENABLED
00113   (void) pnddDevices;
00114   (void) szDevices;
00115   *pszDeviceFound = 0;
00116   DBG ("%s", "Serial auto-probing have been disabled at compile time. Skipping autoprobe.");
00117   return false;
00118 #else /* SERIAL_AUTOPROBE_ENABLED */
00119   *pszDeviceFound = 0;
00120 
00121   serial_port sp;
00122   const char *pcPorts[] = DEFAULT_SERIAL_PORTS;
00123   const char *pcPort;
00124   int     iDevice = 0;
00125 
00126   while ((pcPort = pcPorts[iDevice++])) {
00127     sp = uart_open (pcPort);
00128     DBG ("Trying to find ARYGON device on serial port: %s at %d bauds.", pcPort, SERIAL_DEFAULT_PORT_SPEED);
00129 
00130     if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) {
00131       uart_set_speed (sp, SERIAL_DEFAULT_PORT_SPEED);
00132 
00133       if (!arygon_reset_tama((nfc_device_spec_t) sp))
00134         continue;
00135       uart_close (sp);
00136 
00137       // ARYGON reader is found
00138       strncpy (pnddDevices[*pszDeviceFound].acDevice, "ARYGON", DEVICE_NAME_LENGTH - 1);
00139       pnddDevices[*pszDeviceFound].acDevice[DEVICE_NAME_LENGTH - 1] = '\0';
00140       pnddDevices[*pszDeviceFound].pcDriver = ARYGON_DRIVER_NAME;
00141       pnddDevices[*pszDeviceFound].pcPort = strdup (pcPort);
00142       pnddDevices[*pszDeviceFound].uiSpeed = SERIAL_DEFAULT_PORT_SPEED;
00143       DBG ("Device found: %s (%s)", pnddDevices[*pszDeviceFound].acDevice, pcPort);
00144       (*pszDeviceFound)++;
00145 
00146       // Test if we reach the maximum "wanted" devices
00147       if ((*pszDeviceFound) >= szDevices)
00148         break;
00149     }
00150 #  ifdef DEBUG
00151     if (sp == INVALID_SERIAL_PORT)
00152       DBG ("Invalid serial port: %s", pcPort);
00153     if (sp == CLAIMED_SERIAL_PORT)
00154       DBG ("Serial port already claimed: %s", pcPort);
00155 #  endif
00156        /* DEBUG */
00157   }
00158 #endif /* SERIAL_AUTOPROBE_ENABLED */
00159   return true;
00160 }
00161 
00162 nfc_device_t *
00163 arygon_connect (const nfc_device_desc_t * pndd)
00164 {
00165   serial_port sp;
00166   nfc_device_t *pnd = NULL;
00167 
00168   DBG ("Attempt to connect to: %s at %d bauds.", pndd->pcPort, pndd->uiSpeed);
00169   sp = uart_open (pndd->pcPort);
00170 
00171   if (sp == INVALID_SERIAL_PORT)
00172     ERR ("Invalid serial port: %s", pndd->pcPort);
00173   if (sp == CLAIMED_SERIAL_PORT)
00174     ERR ("Serial port already claimed: %s", pndd->pcPort);
00175   if ((sp == CLAIMED_SERIAL_PORT) || (sp == INVALID_SERIAL_PORT))
00176     return NULL;
00177 
00178   uart_set_speed (sp, pndd->uiSpeed);
00179   if (!arygon_reset_tama((nfc_device_spec_t) sp)) {
00180     return NULL;
00181   }
00182 
00183   DBG ("Successfully connected to: %s", pndd->pcPort);
00184 
00185   // We have a connection
00186   pnd = malloc (sizeof (nfc_device_t));
00187   char acFirmware[10];
00188   arygon_firmware((nfc_device_spec_t) sp, acFirmware);
00189   snprintf (pnd->acName, DEVICE_NAME_LENGTH - 1, "%s %s (%s)", pndd->acDevice, acFirmware, pndd->pcPort);
00190   pnd->acName[DEVICE_NAME_LENGTH - 1] = '\0';
00191   pnd->nc = NC_PN532;
00192   pnd->nds = (nfc_device_spec_t) sp;
00193   pnd->bActive = true;
00194 
00195   return pnd;
00196 }
00197 
00198 void
00199 arygon_disconnect (nfc_device_t * pnd)
00200 {
00201   uart_close ((serial_port) pnd->nds);
00202   free (pnd);
00203 }
00204 
00205 #define TX_BUFFER_LENGTH (300)
00206 #define RX_BUFFER_LENGTH (PN53x_EXTENDED_FRAME_MAX_LEN + PN53x_EXTENDED_FRAME_OVERHEAD + sizeof(pn53x_ack_frame))
00207 bool
00208 arygon_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx, size_t * pszRx)
00209 {
00210   byte_t  abtTxBuf[TX_BUFFER_LENGTH] = { DEV_ARYGON_PROTOCOL_TAMA, 0x00, 0x00, 0xff };     // Every packet must start with "0x32 0x00 0x00 0xff"
00211   byte_t  abtRxBuf[RX_BUFFER_LENGTH];
00212   size_t  szRxBufLen;
00213   size_t  szReplyMaxLen = MIN(RX_BUFFER_LENGTH, *pszRx);
00214   size_t  szPos;
00215   int     res;
00216 
00217   // Packet length = data length (len) + checksum (1) + end of stream marker (1)
00218   abtTxBuf[4] = szTx;
00219   // Packet length checksum
00220   abtTxBuf[5] = 256 - abtTxBuf[4];
00221   // Copy the PN53X command into the packet buffer
00222   memmove (abtTxBuf + 6, pbtTx, szTx);
00223 
00224   // Calculate data payload checksum
00225   abtTxBuf[szTx + 6] = 0;
00226   for (szPos = 0; szPos < szTx; szPos++) {
00227     abtTxBuf[szTx + 6] -= abtTxBuf[szPos + 6];
00228   }
00229 
00230   // End of stream marker
00231   abtTxBuf[szTx + 7] = 0;
00232 
00233 #ifdef DEBUG
00234   PRINT_HEX ("TX", abtTxBuf, szTx + 8);
00235 #endif
00236   res = uart_send ((serial_port) pnd->nds, abtTxBuf, szTx + 8);
00237   if (res != 0) {
00238     ERR ("%s", "Unable to transmit data. (TX)");
00239     pnd->iLastError = res;
00240     return false;
00241   }
00242 #ifdef DEBUG
00243   memset (abtRxBuf, 0x00, sizeof (abtRxBuf));
00244 #endif
00245   szRxBufLen = szReplyMaxLen;
00246   res = uart_receive ((serial_port) pnd->nds, abtRxBuf, &szRxBufLen);
00247   if (res != 0) {
00248     ERR ("%s", "Unable to receive data. (RX)");
00249     pnd->iLastError = res;
00250     return false;
00251   }
00252 #ifdef DEBUG
00253   PRINT_HEX ("RX", abtRxBuf, szRxBufLen);
00254 #endif
00255 
00256   // WARN: UART is a per byte reception, so you usually receive ACK and next frame the same time
00257   if (!pn53x_check_ack_frame_callback (pnd, abtRxBuf, szRxBufLen))
00258     return false;
00259 
00260   szRxBufLen -= sizeof (pn53x_ack_frame);
00261   memmove (abtRxBuf, abtRxBuf + sizeof (pn53x_ack_frame), szRxBufLen);
00262   szReplyMaxLen -= sizeof (pn53x_ack_frame);
00263 
00264   if (szRxBufLen == 0) {
00265     do {
00266       delay_ms (10);
00267       szRxBufLen = szReplyMaxLen;
00268       res = uart_receive ((serial_port) pnd->nds, abtRxBuf, &szRxBufLen);
00269     } while (res != 0);
00270 #ifdef DEBUG
00271     PRINT_HEX ("RX", abtRxBuf, szRxBufLen);
00272 #endif
00273   }
00274 
00275   if (!pn53x_check_error_frame_callback (pnd, abtRxBuf, szRxBufLen))
00276     return false;
00277 
00278   // When the answer should be ignored, just return a successful result
00279   if (pbtRx == NULL || pszRx == NULL)
00280     return true;
00281 
00282   // Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable)
00283   if (szRxBufLen < 9)
00284     return false;
00285 
00286   // Remove the preceding and appending bytes 00 00 ff 00 ff 00 00 00 FF xx Fx .. .. .. xx 00 (x = variable)
00287   *pszRx = szRxBufLen - 9;
00288   memcpy (pbtRx, abtRxBuf + 7, *pszRx);
00289 
00290   return true;
00291 }
00292 
00293 void
00294 arygon_firmware (const nfc_device_spec_t nds, char * str)
00295 {
00296   const byte_t arygon_firmware_version_cmd[] = { DEV_ARYGON_PROTOCOL_ARYGON_ASCII, 'a', 'v' }; 
00297   byte_t abtRx[RX_BUFFER_LENGTH];
00298   size_t szRx = 16;
00299   int res;
00300 
00301 #ifdef DEBUG
00302   PRINT_HEX ("TX", arygon_firmware_version_cmd, sizeof (arygon_firmware_version_cmd));
00303 #endif
00304   uart_send ((serial_port) nds, arygon_firmware_version_cmd, sizeof (arygon_firmware_version_cmd));
00305 
00306   res = uart_receive ((serial_port) nds, abtRx, &szRx);
00307   if (res != 0) {
00308     DBG ("Unable to retrieve ARYGON firmware version.");
00309     return;
00310   }
00311 #ifdef DEBUG
00312   PRINT_HEX ("RX", abtRx, szRx);
00313 #endif
00314   if ( 0 == memcmp (abtRx, arygon_error_none, 6)) {
00315     byte_t * p = abtRx + 6;
00316     unsigned int szData;
00317     sscanf ((const char*)p, "%02x%s", &szData, p);
00318     memcpy (str, p, szData);
00319     *(str + szData) = '\0';
00320   }
00321 }
00322 
00323 bool
00324 arygon_reset_tama (const nfc_device_spec_t nds)
00325 {
00326   const byte_t arygon_reset_tama_cmd[] = { DEV_ARYGON_PROTOCOL_ARYGON_ASCII, 'a', 'r' };
00327   byte_t abtRx[RX_BUFFER_LENGTH];
00328   size_t szRx = 10; // Attempted response is 10 bytes long
00329   int res;
00330 
00331   // Sometimes the first byte we send is not well-transmited (ie. a previously sent data on a wrong baud rate can put some junk in buffer)
00332 #ifdef DEBUG
00333   PRINT_HEX ("TX", arygon_reset_tama_cmd, sizeof (arygon_reset_tama_cmd));
00334 #endif
00335   uart_send ((serial_port) nds, arygon_reset_tama_cmd, sizeof (arygon_reset_tama_cmd));
00336 
00337   // Two reply are possible from ARYGON device: arygon_error_none (ie. in case the byte is well-sent)
00338   // or arygon_error_unknown_mode (ie. in case of the first byte was bad-transmitted)
00339   res = uart_receive ((serial_port) nds, abtRx, &szRx);
00340   if (res != 0) {
00341     DBG ("No reply to 'reset TAMA' command.");
00342     return false;
00343   }
00344 #ifdef DEBUG
00345   PRINT_HEX ("RX", abtRx, szRx);
00346 #endif
00347   if ( 0 == memcmp (abtRx, arygon_error_unknown_mode, sizeof (arygon_error_unknown_mode) - 1)) {
00348     // HACK Here we are... the first byte wasn't sent as expected, so we resend the same command
00349 #ifdef DEBUG
00350       PRINT_HEX ("TX", arygon_reset_tama_cmd, sizeof (arygon_reset_tama_cmd));
00351 #endif
00352       uart_send ((serial_port) nds, arygon_reset_tama_cmd, sizeof (arygon_reset_tama_cmd));
00353       res = uart_receive ((serial_port) nds, abtRx, &szRx);
00354       if (res != 0) {
00355         return false;
00356       }
00357 #ifdef DEBUG
00358       PRINT_HEX ("RX", abtRx, szRx);
00359 #endif
00360   }
00361   if (0 != memcmp (abtRx, arygon_error_none, sizeof (arygon_error_none) - 1)) {
00362     return false;
00363   }
00364 
00365   return true;
00366 }
00367 
00368 /*
00369 void
00370 arygon_ack (const nfc_device_spec_t nds)
00371 {
00372   byte_t abtRx[BUFFER_LENGTH];
00373   size_t szRx;
00374 #ifdef DEBUG
00375   PRINT_HEX ("TX", arygon_ack_frame, sizeof (arygon_ack_frame));
00376 #endif
00377   uart_send ((serial_port) nds, arygon_ack_frame, sizeof (arygon_ack_frame));
00378   uart_receive ((serial_port) nds, abtRx, &szRx);
00379 #ifdef DEBUG
00380   PRINT_HEX ("RX", abtRx, szRx);
00381 #endif
00382   // ARYGON device will send an arygon_error_incomplete_command when sending an
00383   // ACK frame, and I (Romuald) don't know if the command is sent to PN or not
00384   if (0 != memcmp (abtRx, arygon_error_incomplete_command, sizeof (arygon_error_incomplete_command) - 1)) {
00385     return false;
00386   }
00387 }
00388 */
00389 
00390 bool
00391 arygon_check_communication (const nfc_device_spec_t nds)
00392 {
00393   byte_t  abtRx[RX_BUFFER_LENGTH];
00394   size_t  szRx;
00395   const byte_t attempted_result[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, // ACK
00396     0x00, 0x00, 0xff, 0x09, 0xf7, 0xd5, 0x01, 0x00, 'l', 'i', 'b', 'n', 'f', 'c', 0xbc, 0x00 }; // Reply
00397   int     res;
00398 
00400   const byte_t pncmd_communication_test[] =
00401     { DEV_ARYGON_PROTOCOL_TAMA, // Header to passthrough front ARYGON µC (== directly talk to PN53x)
00402       0x00, 0x00, 0xff, 0x09, 0xf7, 0xd4, 0x00, 0x00, 'l', 'i', 'b', 'n', 'f', 'c', 0xbe, 0x00 };
00403 
00404 #ifdef DEBUG
00405   PRINT_HEX ("TX", pncmd_communication_test, sizeof (pncmd_communication_test));
00406 #endif
00407   res = uart_send ((serial_port) nds, pncmd_communication_test, sizeof (pncmd_communication_test));
00408   if (res != 0) {
00409     ERR ("%s", "Unable to transmit data. (TX)");
00410     return false;
00411   }
00412 
00413   res = uart_receive ((serial_port) nds, abtRx, &szRx);
00414   if (res != 0) {
00415     ERR ("%s", "Unable to receive data. (RX)");
00416     return false;
00417   }
00418 #ifdef DEBUG
00419   PRINT_HEX ("RX", abtRx, szRx);
00420 #endif
00421 
00422   if (0 != memcmp (abtRx, attempted_result, sizeof (attempted_result))) {
00423     DBG ("%s", "Communication test failed, result doesn't match to attempted one.");
00424     return false;
00425   }
00426   return true;
00427 }