libnfc  1.4.2
pn532_uart.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 
00025 #ifdef HAVE_CONFIG_H
00026 #  include "config.h"
00027 #endif // HAVE_CONFIG_H
00028 
00029 #include "../drivers.h"
00030 
00031 #include <stdio.h>
00032 #include <string.h>
00033 
00034 #include "pn532_uart.h"
00035 
00036 #include <nfc/nfc.h>
00037 #include <nfc/nfc-messages.h>
00038 
00039 // Bus
00040 #include "uart.h"
00041 
00042 #define SERIAL_DEFAULT_PORT_SPEED 115200
00043 
00044 // TODO Move this one level up for libnfc-1.6
00045 static const byte_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
00046 
00047 void    pn532_uart_ack (const nfc_device_spec_t nds);
00048 void    pn532_uart_wakeup (const nfc_device_spec_t nds);
00049 bool    pn532_uart_check_communication (const nfc_device_spec_t nds, bool * success);
00050 
00051 nfc_device_desc_t *
00052 pn532_uart_pick_device (void)
00053 {
00054   nfc_device_desc_t *pndd;
00055 
00056   if ((pndd = malloc (sizeof (*pndd)))) {
00057     size_t  szN;
00058 
00059     if (!pn532_uart_list_devices (pndd, 1, &szN)) {
00060       DBG ("%s", "pn532_uart_list_devices failed");
00061       free (pndd);
00062       return NULL;
00063     }
00064 
00065     if (szN == 0) {
00066       DBG ("%s", "No device found");
00067       free (pndd);
00068       return NULL;
00069     }
00070   }
00071 
00072   return pndd;
00073 }
00074 
00075 bool
00076 pn532_uart_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound)
00077 {
00081 #ifndef SERIAL_AUTOPROBE_ENABLED
00082   (void) pnddDevices;
00083   (void) szDevices;
00084   *pszDeviceFound = 0;
00085   DBG ("%s", "Serial auto-probing have been disabled at compile time. Skipping autoprobe.");
00086   return false;
00087 #else /* SERIAL_AUTOPROBE_ENABLED */
00088   *pszDeviceFound = 0;
00089 
00090   serial_port sp;
00091   const char *pcPorts[] = DEFAULT_SERIAL_PORTS;
00092   const char *pcPort;
00093   int     iDevice = 0;
00094 
00095   while ((pcPort = pcPorts[iDevice++])) {
00096     sp = uart_open (pcPort);
00097     DBG ("Trying to find PN532 device on serial port: %s at %d bauds.", pcPort, SERIAL_DEFAULT_PORT_SPEED);
00098 
00099     if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) {
00100       bool    bComOk;
00101       // Serial port claimed but we need to check if a PN532_UART is connected.
00102       uart_set_speed (sp, SERIAL_DEFAULT_PORT_SPEED);
00103       // PN532 could be powered down, we need to wake it up before line testing.
00104       pn532_uart_wakeup ((nfc_device_spec_t) sp);
00105       // Check communication using "Diagnose" command, with "Communication test" (0x00)
00106       if (!pn532_uart_check_communication ((nfc_device_spec_t) sp, &bComOk))
00107         continue;
00108       if (!bComOk)
00109         continue;
00110       uart_close (sp);
00111 
00112       snprintf (pnddDevices[*pszDeviceFound].acDevice, DEVICE_NAME_LENGTH - 1, "%s (%s)", "PN532", pcPort);
00113       pnddDevices[*pszDeviceFound].acDevice[DEVICE_NAME_LENGTH - 1] = '\0';
00114       pnddDevices[*pszDeviceFound].pcDriver = PN532_UART_DRIVER_NAME;
00115       pnddDevices[*pszDeviceFound].pcPort = strdup (pcPort);
00116       pnddDevices[*pszDeviceFound].uiSpeed = SERIAL_DEFAULT_PORT_SPEED;
00117       DBG ("Device found: %s.", pnddDevices[*pszDeviceFound].acDevice);
00118       (*pszDeviceFound)++;
00119 
00120       // Test if we reach the maximum "wanted" devices
00121       if ((*pszDeviceFound) >= szDevices)
00122         break;
00123     }
00124 #  ifdef DEBUG
00125     if (sp == INVALID_SERIAL_PORT)
00126       DBG ("Invalid serial port: %s", pcPort);
00127     if (sp == CLAIMED_SERIAL_PORT)
00128       DBG ("Serial port already claimed: %s", pcPort);
00129 #  endif
00130        /* DEBUG */
00131   }
00132 #endif /* SERIAL_AUTOPROBE_ENABLED */
00133   return true;
00134 }
00135 
00136 nfc_device_t *
00137 pn532_uart_connect (const nfc_device_desc_t * pndd)
00138 {
00139   serial_port sp;
00140   nfc_device_t *pnd = NULL;
00141   bool    bComOk;
00142 
00143   DBG ("Attempt to connect to: %s at %d bauds.", pndd->pcPort, pndd->uiSpeed);
00144   sp = uart_open (pndd->pcPort);
00145 
00146   if (sp == INVALID_SERIAL_PORT)
00147     ERR ("Invalid serial port: %s", pndd->pcPort);
00148   if (sp == CLAIMED_SERIAL_PORT)
00149     ERR ("Serial port already claimed: %s", pndd->pcPort);
00150   if ((sp == CLAIMED_SERIAL_PORT) || (sp == INVALID_SERIAL_PORT))
00151     return NULL;
00152 
00153   uart_set_speed (sp, pndd->uiSpeed);
00154 
00155   // PN532 could be powered down, we need to wake it up before line testing.
00156   pn532_uart_wakeup ((nfc_device_spec_t) sp);
00157   // Check communication using "Diagnose" command, with "Communication test" (0x00)
00158   if (!pn532_uart_check_communication ((nfc_device_spec_t) sp, &bComOk))
00159     return NULL;
00160   if (!bComOk)
00161     return NULL;
00162 
00163   DBG ("Successfully connected to: %s", pndd->pcPort);
00164 
00165   // We have a connection
00166   pnd = malloc (sizeof (nfc_device_t));
00167   strncpy (pnd->acName, pndd->acDevice, DEVICE_NAME_LENGTH - 1);
00168   pnd->acName[DEVICE_NAME_LENGTH - 1] = '\0';
00169 
00170   pnd->nc = NC_PN532;
00171   pnd->nds = (nfc_device_spec_t) sp;
00172   pnd->bActive = true;
00173 
00174   return pnd;
00175 }
00176 
00177 void
00178 pn532_uart_disconnect (nfc_device_t * pnd)
00179 {
00180   uart_close ((serial_port) pnd->nds);
00181   free (pnd);
00182 }
00183 
00184 #define TX_BUFFER_LEN (256)
00185 #define RX_BUFFER_LEN (PN53x_EXTENDED_FRAME_MAX_LEN + PN53x_EXTENDED_FRAME_OVERHEAD)
00186 bool
00187 pn532_uart_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx,
00188                        size_t * pszRx)
00189 {
00190   byte_t  abtTxBuf[TX_BUFFER_LEN] = { 0x00, 0x00, 0xff };       // Every packet must start with "00 00 ff"
00191   byte_t  abtRxBuf[RX_BUFFER_LEN];
00192   size_t  szRxBufLen = MIN( RX_BUFFER_LEN, *pszRx );
00193   size_t  szPos;
00194   int     res;
00195 
00196   // Packet length = data length (len) + checksum (1) + end of stream marker (1)
00197   abtTxBuf[3] = szTx;
00198   // Packet length checksum
00199   abtTxBuf[4] = 256 - abtTxBuf[3];
00200   // Copy the PN53X command into the packet buffer
00201   memmove (abtTxBuf + 5, pbtTx, szTx);
00202 
00203   // Calculate data payload checksum
00204   abtTxBuf[szTx + 5] = 0;
00205   for (szPos = 0; szPos < szTx; szPos++) {
00206     abtTxBuf[szTx + 5] -= abtTxBuf[szPos + 5];
00207   }
00208 
00209   // End of stream marker
00210   abtTxBuf[szTx + 6] = 0;
00211 
00212 #ifdef DEBUG
00213   PRINT_HEX ("TX", abtTxBuf, szTx + 7);
00214 #endif
00215   res = uart_send ((serial_port) pnd->nds, abtTxBuf, szTx + 7);
00216   if (res != 0) {
00217     ERR ("%s", "Unable to transmit data. (TX)");
00218     pnd->iLastError = res;
00219     return false;
00220   }
00221 
00222   res = uart_receive ((serial_port) pnd->nds, abtRxBuf, &szRxBufLen);
00223   if (res != 0) {
00224     ERR ("%s", "Unable to receive data. (RX)");
00225     pnd->iLastError = res;
00226     return false;
00227   }
00228 #ifdef DEBUG
00229   PRINT_HEX ("RX", abtRxBuf, szRxBufLen);
00230 #endif
00231 
00232   // WARN: UART is a per byte reception, so you usually receive ACK and next frame the same time
00233   if (!pn53x_check_ack_frame_callback (pnd, abtRxBuf, szRxBufLen))
00234     return false;
00235   szRxBufLen -= sizeof (ack_frame);
00236   memmove (abtRxBuf, abtRxBuf + sizeof (ack_frame), szRxBufLen);
00237 
00238   if (szRxBufLen == 0) {
00239     szRxBufLen = RX_BUFFER_LEN;
00240     do {
00241       delay_ms (10);
00242       res = uart_receive ((serial_port) pnd->nds, abtRxBuf, &szRxBufLen);
00243     } while (res != 0);
00244 #ifdef DEBUG
00245     PRINT_HEX ("RX", abtRxBuf, szRxBufLen);
00246 #endif
00247   }
00248 
00249 #ifdef DEBUG
00250   PRINT_HEX ("TX", ack_frame, sizeof(ack_frame));
00251 #endif
00252   res = uart_send ((serial_port) pnd->nds, ack_frame, sizeof(ack_frame));
00253   if (res != 0) {
00254     ERR ("%s", "Unable to transmit data. (TX)");
00255     pnd->iLastError = res;
00256     return false;
00257   }
00258 
00259   if (!pn53x_check_error_frame_callback (pnd, abtRxBuf, szRxBufLen))
00260     return false;
00261 
00262   // When the answer should be ignored, just return a successful result
00263   if (pbtRx == NULL || pszRx == NULL)
00264     return true;
00265 
00266   // Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable)
00267   if (szRxBufLen < 9) {
00268     pnd->iLastError = DEINVAL;
00269     return false;
00270   }
00271   // Remove the preceding and appending bytes 00 00 ff 00 ff 00 00 00 FF xx Fx .. .. .. xx 00 (x = variable)
00272   *pszRx = szRxBufLen - 9;
00273   memcpy (pbtRx, abtRxBuf + 7, *pszRx);
00274 
00275   return true;
00276 }
00277 
00278 void
00279 pn532_uart_ack (const nfc_device_spec_t nds)
00280 {
00281 #ifdef DEBUG
00282   PRINT_HEX ("TX", ack_frame, sizeof (ack_frame));
00283 #endif
00284   uart_send ((serial_port) nds, ack_frame, sizeof (ack_frame));
00285 }
00286 
00287 bool
00288 pn532_uart_wait_for_ack(const nfc_device_spec_t nds)
00289 {
00290   byte_t  abtRx[RX_BUFFER_LEN];
00291   size_t  szRx = sizeof(ack_frame);
00292   if (0 == uart_receive ((serial_port) nds, abtRx, &szRx)) {
00293 #ifdef DEBUG           
00294     PRINT_HEX ("RX", abtRx, szRx);
00295 #endif
00296   } else {
00297     ERR ("No ACK.");
00298     return false;
00299   }
00300   if (0 != memcmp (ack_frame, abtRx, szRx))
00301     return false;
00302   return true;
00303 }
00304 
00305 #define PN53X_RX_OVERHEAD 6
00306 void
00307 pn532_uart_wakeup (const nfc_device_spec_t nds)
00308 {
00309   byte_t  abtRx[RX_BUFFER_LEN];
00310   size_t  szRx = PN53x_NORMAL_FRAME_OVERHEAD + 2;
00314   const byte_t pncmd_pn532c106_wakeup_preamble[] = 
00315     { 0x55, 0x55, 0x00, 0x00, 0x00, 
00316       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00317       0x00, 0x00, 0xff, 0x03, 0xfd, 0xd4, 0x14, 0x01, 0x17, 0x00 }; // Here we send a SAMConfiguration command (Normal mode, the SAM is not used; this is the default mode)
00318 #ifdef DEBUG
00319   PRINT_HEX ("TX", pncmd_pn532c106_wakeup_preamble, sizeof (pncmd_pn532c106_wakeup_preamble));
00320 #endif
00321   uart_send ((serial_port) nds, pncmd_pn532c106_wakeup_preamble, sizeof (pncmd_pn532c106_wakeup_preamble));
00322 
00323   pn532_uart_wait_for_ack(nds);
00324 
00325   if (0 == uart_receive ((serial_port) nds, abtRx, &szRx)) {
00326 #ifdef DEBUG
00327     PRINT_HEX ("RX", abtRx, szRx);
00328 #endif
00329   } else {
00330     ERR ("Unable to wakeup the PN532.");
00331   }
00332 }
00333 
00334 bool
00335 pn532_uart_check_communication (const nfc_device_spec_t nds, bool * success)
00336 {
00337   byte_t  abtRx[RX_BUFFER_LEN];
00338   const byte_t attempted_result[] =
00339     { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x09, 0xf7, 0xD5, 0x01, 0x00, 'l', 'i', 'b', 'n', 'f', 'c',
00340 0xbc, 0x00 };
00341   size_t  szRx = sizeof(attempted_result);
00342   int     res;
00343 
00345   const byte_t pncmd_communication_test[] =
00346     { 0x00, 0x00, 0xff, 0x09, 0xf7, 0xd4, 0x00, 0x00, 'l', 'i', 'b', 'n', 'f', 'c', 0xbe, 0x00 };
00347 
00348   *success = false;
00349 
00350 #ifdef DEBUG
00351   PRINT_HEX ("TX", pncmd_communication_test, sizeof (pncmd_communication_test));
00352 #endif
00353   res = uart_send ((serial_port) nds, pncmd_communication_test, sizeof (pncmd_communication_test));
00354   if (res != 0) {
00355     ERR ("%s", "Unable to transmit data. (TX)");
00356     return false;
00357   }
00358 
00359   res = uart_receive ((serial_port) nds, abtRx, &szRx);
00360   if (res != 0) {
00361     ERR ("%s", "Unable to receive data. (RX)");
00362     return false;
00363   }
00364 #ifdef DEBUG
00365   PRINT_HEX ("RX", abtRx, szRx);
00366 #endif
00367 
00368   if (0 == memcmp (abtRx, attempted_result, sizeof (attempted_result)))
00369     *success = true;
00370 
00371   return true;
00372 }