nfc.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, Romuald Conty
00005  * Copyright (C) 2010, Roel Verdult, Romuald Conty, Romain Tartière
00006  * 
00007  * This program is free software: you can redistribute it and/or modify it
00008  * under the terms of the GNU Lesser General Public License as published by the
00009  * Free Software Foundation, either version 3 of the License, or (at your
00010  * option) any later version.
00011  * 
00012  * This program is distributed in the hope that it will be useful, but WITHOUT
00013  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
00015  * more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public License
00018  * along with this program.  If not, see <http://www.gnu.org/licenses/>
00019  */
00020 
00026 #ifdef HAVE_CONFIG_H
00027 #  include "config.h"
00028 #endif // HAVE_CONFIG_H
00029 
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <stddef.h>
00033 #include <string.h>
00034 
00035 #include <nfc/nfc.h>
00036 
00037 #ifdef _WIN32
00038 #  include "../contrib/windows.h"
00039 #endif
00040 
00041 #include "chips.h"
00042 #include "drivers.h"
00043 
00044 #include <nfc/nfc-messages.h>
00045 
00046 nfc_device_desc_t *nfc_pick_device (void);
00047 
00070 nfc_device_t *
00071 nfc_connect (nfc_device_desc_t * pndd)
00072 {
00073   nfc_device_t *pnd = NULL;
00074   uint32_t uiDriver;
00075 
00076   // Search through the device list for an available device
00077   for (uiDriver = 0; uiDriver < sizeof (drivers_callbacks_list) / sizeof (drivers_callbacks_list[0]); uiDriver++) {
00078     if (pndd == NULL) {
00079       // No device description specified: try to automatically claim a device
00080       if (drivers_callbacks_list[uiDriver].pick_device != NULL) {
00081         DBG ("Autodetecting available devices using %s driver.", drivers_callbacks_list[uiDriver].acDriver);
00082         pndd = drivers_callbacks_list[uiDriver].pick_device ();
00083 
00084         if (pndd != NULL) {
00085           DBG ("Auto-connecting to %s using %s driver", pndd->acDevice, drivers_callbacks_list[uiDriver].acDriver);
00086           pnd = drivers_callbacks_list[uiDriver].connect (pndd);
00087           if (pnd == NULL) {
00088             DBG ("No device available using %s driver", drivers_callbacks_list[uiDriver].acDriver);
00089             pndd = NULL;
00090           }
00091 
00092           free (pndd);
00093         }
00094       }
00095     } else {
00096       // Specific device is requested: using device description pndd
00097       if (0 != strcmp (drivers_callbacks_list[uiDriver].acDriver, pndd->pcDriver)) {
00098         continue;
00099       } else {
00100         pnd = drivers_callbacks_list[uiDriver].connect (pndd);
00101       }
00102     }
00103 
00104     // Test if the connection was successful
00105     if (pnd != NULL) {
00106       DBG ("[%s] has been claimed.", pnd->acName);
00107       // Great we have claimed a device
00108       pnd->pdc = &(drivers_callbacks_list[uiDriver]);
00109 
00110       if (!pn53x_init (pnd))
00111         return NULL;
00112 
00113       // Set default configuration options
00114       // Make sure we reset the CRC and parity to chip handling.
00115       if (!nfc_configure (pnd, NDO_HANDLE_CRC, true))
00116         return NULL;
00117       if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true))
00118         return NULL;
00119 
00120       // Deactivate the CRYPTO1 cipher, it may could cause problems when still active
00121       if (!nfc_configure (pnd, NDO_ACTIVATE_CRYPTO1, false))
00122         return NULL;
00123 
00124       // Activate "easy framing" feature by default
00125       if (!nfc_configure (pnd, NDO_EASY_FRAMING, true))
00126         return NULL;
00127 
00128       // Activate auto ISO14443-4 switching by default
00129       if (!nfc_configure (pnd, NDO_AUTO_ISO14443_4, true))
00130         return NULL;
00131 
00132       // Disallow invalid frame
00133       if (!nfc_configure (pnd, NDO_ACCEPT_INVALID_FRAMES, false))
00134         return NULL;
00135 
00136       // Disallow multiple frames
00137       if (!nfc_configure (pnd, NDO_ACCEPT_MULTIPLE_FRAMES, false))
00138         return NULL;
00139 
00140       return pnd;
00141     } else {
00142       DBG ("No device found using driver: %s", drivers_callbacks_list[uiDriver].acDriver);
00143     }
00144   }
00145   // Too bad, no reader is ready to be claimed
00146   return NULL;
00147 }
00148 
00155 void
00156 nfc_disconnect (nfc_device_t * pnd)
00157 {
00158   if (pnd) {
00159     // Release and deselect all active communications
00160     nfc_initiator_deselect_target (pnd);
00161     // Disable RF field to avoid heating
00162     nfc_configure (pnd, NDO_ACTIVATE_FIELD, false);
00163     // Disconnect, clean up and release the device 
00164     pnd->pdc->disconnect (pnd);
00165   }
00166 }
00167 
00172 nfc_device_desc_t *
00173 nfc_pick_device (void)
00174 {
00175   uint32_t uiDriver;
00176   nfc_device_desc_t *nddRes;
00177 
00178   for (uiDriver = 0; uiDriver < sizeof (drivers_callbacks_list) / sizeof (drivers_callbacks_list[0]); uiDriver++) {
00179     if (drivers_callbacks_list[uiDriver].pick_device != NULL) {
00180       nddRes = drivers_callbacks_list[uiDriver].pick_device ();
00181       if (nddRes != NULL)
00182         return nddRes;
00183     }
00184   }
00185 
00186   return NULL;
00187 }
00188 
00195 void
00196 nfc_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound)
00197 {
00198   uint32_t uiDriver;
00199   size_t  szN;
00200 
00201   *pszDeviceFound = 0;
00202 
00203   for (uiDriver = 0; uiDriver < sizeof (drivers_callbacks_list) / sizeof (drivers_callbacks_list[0]); uiDriver++) {
00204     if (drivers_callbacks_list[uiDriver].list_devices != NULL) {
00205       szN = 0;
00206       if (drivers_callbacks_list[uiDriver].list_devices
00207           (pnddDevices + (*pszDeviceFound), szDevices - (*pszDeviceFound), &szN)) {
00208         *pszDeviceFound += szN;
00209         DBG ("%ld device(s) found using %s driver", (unsigned long) szN, drivers_callbacks_list[uiDriver].acDriver);
00210       }
00211     } else {
00212       DBG ("No listing function avaible for %s driver", drivers_callbacks_list[uiDriver].acDriver);
00213     }
00214   }
00215 }
00216 
00229 bool
00230 nfc_configure (nfc_device_t * pnd, const nfc_device_option_t ndo, const bool bEnable)
00231 {
00232   pnd->iLastError = 0;
00233 
00234   return pn53x_configure (pnd, ndo, bEnable);
00235 }
00236 
00246 bool
00247 nfc_initiator_init (nfc_device_t * pnd)
00248 {
00249   pnd->iLastError = 0;
00250 
00251   // Make sure we are dealing with a active device
00252   if (!pnd->bActive)
00253     return false;
00254 
00255   // Set the PN53X to force 100% ASK Modified miller decoding (default for 14443A cards)
00256   if (!pn53x_set_reg (pnd, REG_CIU_TX_AUTO, SYMBOL_FORCE_100_ASK, 0x40))
00257     return false;
00258 
00259   // Configure the PN53X to be an Initiator or Reader/Writer
00260   if (!pn53x_set_reg (pnd, REG_CIU_CONTROL, SYMBOL_INITIATOR, 0x10))
00261     return false;
00262 
00263   return true;
00264 }
00265 
00286 bool
00287 nfc_initiator_select_passive_target (nfc_device_t * pnd,
00288                                      const nfc_modulation_t nm,
00289                                      const byte_t * pbtInitData, const size_t szInitData,
00290                                      nfc_target_t * pnt)
00291 {
00292   byte_t  abtInit[MAX_FRAME_LEN];
00293   size_t  szInit;
00294 
00295   pnd->iLastError = 0;
00296 
00297   // Make sure we are dealing with a active device
00298   if (!pnd->bActive)
00299     return false;
00300   // TODO Put this in a function: this part is defined by ISO14443-3 (UID and Cascade levels)
00301   switch (nm.nmt) {
00302   case NMT_ISO14443A:
00303     switch (szInitData) {
00304     case 7:
00305       abtInit[0] = 0x88;
00306       memcpy (abtInit + 1, pbtInitData, 7);
00307       szInit = 8;
00308       break;
00309 
00310     case 10:
00311       abtInit[0] = 0x88;
00312       memcpy (abtInit + 1, pbtInitData, 3);
00313       abtInit[4] = 0x88;
00314       memcpy (abtInit + 5, pbtInitData + 3, 7);
00315       szInit = 12;
00316       break;
00317 
00318     case 4:
00319     default:
00320       memcpy (abtInit, pbtInitData, szInitData);
00321       szInit = szInitData;
00322       break;
00323     }
00324     break;
00325 
00326   default:
00327     memcpy (abtInit, pbtInitData, szInitData);
00328     szInit = szInitData;
00329     break;
00330   }
00331 
00332   return pn53x_initiator_select_passive_target (pnd, nm, abtInit, szInit, pnt);
00333 }
00334 
00352 bool
00353 nfc_initiator_list_passive_targets (nfc_device_t * pnd,
00354                                     const nfc_modulation_t nm,
00355                                     nfc_target_t ant[], const size_t szTargets, size_t * pszTargetFound)
00356 {
00357   nfc_target_t nt;
00358   size_t  szTargetFound = 0;
00359   byte_t *pbtInitData = NULL;
00360   size_t  szInitDataLen = 0;
00361 
00362   pnd->iLastError = 0;
00363 
00364   // Drop the field for a while
00365   if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) {
00366     return false;
00367   }
00368   // Let the reader only try once to find a tag
00369   if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) {
00370     return false;
00371   }
00372   // Enable field so more power consuming cards can power themselves up
00373   if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) {
00374     return false;
00375   }
00376 
00377   switch (nm.nmt) {
00378     case NMT_ISO14443B: {
00379       // Application Family Identifier (AFI) must equals 0x00 in order to wakeup all ISO14443-B PICCs (see ISO/IEC 14443-3)
00380       pbtInitData = (byte_t *) "\x00";
00381       szInitDataLen = 1;
00382     }
00383     break;
00384     case NMT_FELICA: {
00385       // polling payload must be present (see ISO/IEC 18092 11.2.2.5)
00386       pbtInitData = (byte_t *) "\x00\xff\xff\x01\x00";
00387       szInitDataLen = 5;
00388     }
00389     break;
00390     default:
00391       // nothing to do
00392     break;
00393   }
00394 
00395   while (nfc_initiator_select_passive_target (pnd, nm, pbtInitData, szInitDataLen, &nt)) {
00396     nfc_initiator_deselect_target (pnd);
00397 
00398     if (szTargets > szTargetFound) {
00399       memcpy (&(ant[szTargetFound]), &nt, sizeof (nfc_target_t));
00400     } else {
00401       break;
00402     }
00403     szTargetFound++;
00404     // deselect has no effect on FeliCa and Jewel cards so we'll stop after one...
00405     if ((nm.nmt == NMT_FELICA) || (nm.nmt == NMT_JEWEL)) {
00406         break;
00407     }
00408   }
00409   *pszTargetFound = szTargetFound;
00410 
00411   return true;
00412 }
00413 
00427 bool
00428 nfc_initiator_poll_targets (nfc_device_t * pnd,
00429                             const nfc_modulation_t * pnmModulations, const size_t szModulations,
00430                             const byte_t btPollNr, const byte_t btPeriod,
00431                             nfc_target_t * pntTargets, size_t * pszTargetFound)
00432 {
00433   pnd->iLastError = 0;
00434 
00435   return pn53x_initiator_poll_targets (pnd, pnmModulations, szModulations, btPollNr, btPeriod, pntTargets, pszTargetFound);
00436 }
00437 
00438 
00454 bool
00455 nfc_initiator_select_dep_target (nfc_device_t * pnd, 
00456                                  const nfc_dep_mode_t ndm, const nfc_baud_rate_t nbr,
00457                                  const nfc_dep_info_t * pndiInitiator, nfc_target_t * pnt)
00458 {
00459   pnd->iLastError = 0;
00460 
00461   return pn53x_initiator_select_dep_target (pnd, ndm, nbr, pndiInitiator, pnt);
00462 }
00463 
00476 bool
00477 nfc_initiator_deselect_target (nfc_device_t * pnd)
00478 {
00479   pnd->iLastError = 0;
00480 
00481   return (pn53x_InDeselect (pnd, 0));   // 0 mean deselect all selected targets
00482 }
00483 
00500 bool
00501 nfc_initiator_transceive_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx,
00502                                 size_t * pszRx)
00503 {
00504   pnd->iLastError = 0;
00505 
00506   return pn53x_initiator_transceive_bytes (pnd, pbtTx, szTx, pbtRx, pszRx);
00507 }
00508 
00544 bool
00545 nfc_initiator_transceive_bits (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxBits, const byte_t * pbtTxPar,
00546                                byte_t * pbtRx, size_t * pszRxBits, byte_t * pbtRxPar)
00547 {
00548   pnd->iLastError = 0;
00549 
00550   return pn53x_initiator_transceive_bits (pnd, pbtTx, szTxBits, pbtTxPar, pbtRx, pszRxBits, pbtRxPar);
00551 }
00552 
00575 bool
00576 nfc_target_init (nfc_device_t * pnd, nfc_target_t * pnt, byte_t * pbtRx, size_t * pszRx)
00577 {
00578   pnd->iLastError = 0;
00579 
00580   return pn53x_target_init (pnd, pnt, pbtRx, pszRx);
00581 }
00582 
00594 bool
00595 nfc_target_send_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx)
00596 {
00597   pnd->iLastError = 0;
00598 
00599   return pn53x_target_send_bytes (pnd, pbtTx, szTx);
00600 }
00601 
00611 bool
00612 nfc_target_receive_bytes (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRx)
00613 {
00614   pnd->iLastError = 0;
00615 
00616   return pn53x_target_receive_bytes (pnd, pbtRx, pszRx);
00617 }
00618 
00626 bool
00627 nfc_target_send_bits (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxBits, const byte_t * pbtTxPar)
00628 {
00629   pnd->iLastError = 0;
00630 
00631   return pn53x_target_send_bits (pnd, pbtTx, szTxBits, pbtTxPar);
00632 }
00633 
00645 bool
00646 nfc_target_receive_bits (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBits, byte_t * pbtRxPar)
00647 {
00648   pnd->iLastError = 0;
00649 
00650   return pn53x_target_receive_bits (pnd, pbtRx, pszRxBits, pbtRxPar);
00651 }
00652 
00657 const char *
00658 nfc_strerror (const nfc_device_t * pnd)
00659 {
00660   return pnd->pdc->pcc->strerror (pnd);
00661 }
00662 
00667 int
00668 nfc_strerror_r (const nfc_device_t * pnd, char *pcStrErrBuf, size_t szBufLen)
00669 {
00670   return (snprintf (pcStrErrBuf, szBufLen, "%s", nfc_strerror (pnd)) < 0) ? -1 : 0;
00671 }
00672 
00676 void
00677 nfc_perror (const nfc_device_t * pnd, const char *pcString)
00678 {
00679   fprintf (stderr, "%s: %s\n", pcString, nfc_strerror (pnd));
00680 }
00681 
00682 /* Special data accessors */
00683 
00688 const char *
00689 nfc_device_name (nfc_device_t * pnd)
00690 {
00691   return pnd->acName;
00692 }
00693 
00694 /* Misc. functions */
00695 
00700 const char *
00701 nfc_version (void)
00702 {
00703 #ifdef SVN_REVISION
00704   return PACKAGE_VERSION " (r" SVN_REVISION ")";
00705 #else
00706   return PACKAGE_VERSION;
00707 #endif // SVN_REVISION
00708 }