nfc.c

Go to the documentation of this file.
00001 /*-
00002  * Public platform independent Near Field Communication (NFC) library
00003  * 
00004  * Copyright (C) 2009, 2010, Roel Verdult, Romuald Conty
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 <stdio.h>
00030 #include <stdlib.h>
00031 #include <stddef.h>
00032 #include <string.h>
00033 
00034 #include <nfc/nfc.h>
00035 
00036 #ifdef _WIN32
00037 #  include <windows.h>
00038 
00039 #  define snprintf sprintf_s
00040 #endif
00041 
00042 #include "chips.h"
00043 #include "drivers.h"
00044 
00045 #include <nfc/nfc-messages.h>
00046 
00047 nfc_device_desc_t *nfc_pick_device (void);
00048 
00053 nfc_device_desc_t *
00054 nfc_pick_device (void)
00055 {
00056   uint32_t uiDriver;
00057   nfc_device_desc_t *nddRes;
00058 
00059   for (uiDriver = 0; uiDriver < sizeof (drivers_callbacks_list) / sizeof (drivers_callbacks_list[0]); uiDriver++) {
00060     if (drivers_callbacks_list[uiDriver].pick_device != NULL) {
00061       nddRes = drivers_callbacks_list[uiDriver].pick_device ();
00062       if (nddRes != NULL)
00063         return nddRes;
00064     }
00065   }
00066 
00067   return NULL;
00068 }
00069 
00076 void
00077 nfc_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound)
00078 {
00079   uint32_t uiDriver;
00080   size_t  szN;
00081 
00082   *pszDeviceFound = 0;
00083 
00084   for (uiDriver = 0; uiDriver < sizeof (drivers_callbacks_list) / sizeof (drivers_callbacks_list[0]); uiDriver++) {
00085     if (drivers_callbacks_list[uiDriver].list_devices != NULL) {
00086       szN = 0;
00087       if (drivers_callbacks_list[uiDriver].
00088           list_devices (pnddDevices + (*pszDeviceFound), szDevices - (*pszDeviceFound), &szN)) {
00089         *pszDeviceFound += szN;
00090         DBG ("%ld device(s) found using %s driver", (unsigned long) szN, drivers_callbacks_list[uiDriver].acDriver);
00091       }
00092     } else {
00093       DBG ("No listing function avaible for %s driver", drivers_callbacks_list[uiDriver].acDriver);
00094     }
00095   }
00096 }
00097 
00111 nfc_device_t *
00112 nfc_connect (nfc_device_desc_t * pndd)
00113 {
00114   nfc_device_t *pnd = NULL;
00115   uint32_t uiDriver;
00116 
00117   // Search through the device list for an available device
00118   for (uiDriver = 0; uiDriver < sizeof (drivers_callbacks_list) / sizeof (drivers_callbacks_list[0]); uiDriver++) {
00119     if (pndd == NULL) {
00120       // No device description specified: try to automatically claim a device
00121       if (drivers_callbacks_list[uiDriver].pick_device != NULL) {
00122         DBG ("Autodetecting available devices using %s driver.", drivers_callbacks_list[uiDriver].acDriver);
00123         pndd = drivers_callbacks_list[uiDriver].pick_device ();
00124 
00125         if (pndd != NULL) {
00126           DBG ("Auto-connecting to %s using %s driver", pndd->acDevice, drivers_callbacks_list[uiDriver].acDriver);
00127           pnd = drivers_callbacks_list[uiDriver].connect (pndd);
00128           if (pnd == NULL) {
00129             DBG ("No device available using %s driver", drivers_callbacks_list[uiDriver].acDriver);
00130             pndd = NULL;
00131           }
00132 
00133           free (pndd);
00134         }
00135       }
00136     } else {
00137       // Specific device is requested: using device description pndd
00138       if (0 != strcmp (drivers_callbacks_list[uiDriver].acDriver, pndd->pcDriver)) {
00139         continue;
00140       } else {
00141         pnd = drivers_callbacks_list[uiDriver].connect (pndd);
00142       }
00143     }
00144 
00145     // Test if the connection was successful
00146     if (pnd != NULL) {
00147       DBG ("[%s] has been claimed.", pnd->acName);
00148       // Great we have claimed a device
00149       pnd->pdc = &(drivers_callbacks_list[uiDriver]);
00150 
00151       if (!pn53x_get_firmware_version (pnd))
00152         return NULL;
00153 
00154       // Reset the ending transmission bits register, it is unknown what the last tranmission used there
00155       if (!pn53x_set_reg (pnd, REG_CIU_BIT_FRAMING, SYMBOL_TX_LAST_BITS, 0x00))
00156         return NULL;
00157 
00158       // Set default configuration options
00159       // Make sure we reset the CRC and parity to chip handling.
00160       if (!nfc_configure (pnd, NDO_HANDLE_CRC, true))
00161         return NULL;
00162       if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true))
00163         return NULL;
00164 
00165       // Deactivate the CRYPTO1 chiper, it may could cause problems when still active
00166       if (!nfc_configure (pnd, NDO_ACTIVATE_CRYPTO1, false))
00167         return NULL;
00168 
00169       // Activate "easy framing" feature by default
00170       if (!nfc_configure (pnd, NDO_EASY_FRAMING, true))
00171         return NULL;
00172 
00173       // Activate auto ISO14443-4 switching by default
00174       if (!nfc_configure (pnd, NDO_AUTO_ISO14443_4, true))
00175         return NULL;
00176 
00177       // Disallow invalid frame
00178       if (!nfc_configure (pnd, NDO_ACCEPT_INVALID_FRAMES, false))
00179         return NULL;
00180 
00181       // Disallow multiple frames
00182       if (!nfc_configure (pnd, NDO_ACCEPT_MULTIPLE_FRAMES, false))
00183         return NULL;
00184 
00185       return pnd;
00186     } else {
00187       DBG ("No device found using driver: %s", drivers_callbacks_list[uiDriver].acDriver);
00188     }
00189   }
00190   // Too bad, no reader is ready to be claimed
00191   return NULL;
00192 }
00193 
00200 void
00201 nfc_disconnect (nfc_device_t * pnd)
00202 {
00203   if (pnd) {
00204     // Release and deselect all active communications
00205     nfc_initiator_deselect_target (pnd);
00206     // Disable RF field to avoid heating
00207     nfc_configure (pnd, NDO_ACTIVATE_FIELD, false);
00208     // Disconnect, clean up and release the device 
00209     pnd->pdc->disconnect (pnd);
00210   }
00211 }
00212 
00224 bool
00225 nfc_configure (nfc_device_t * pnd, const nfc_device_option_t ndo, const bool bEnable)
00226 {
00227   pnd->iLastError = 0;
00228 
00229   return pn53x_configure (pnd, ndo, bEnable);
00230 }
00231 
00232 
00242 bool
00243 nfc_initiator_init (nfc_device_t * pnd)
00244 {
00245   pnd->iLastError = 0;
00246 
00247   // Make sure we are dealing with a active device
00248   if (!pnd->bActive)
00249     return false;
00250 
00251   // Set the PN53X to force 100% ASK Modified miller decoding (default for 14443A cards)
00252   if (!pn53x_set_reg (pnd, REG_CIU_TX_AUTO, SYMBOL_FORCE_100_ASK, 0x40))
00253     return false;
00254 
00255   // Configure the PN53X to be an Initiator or Reader/Writer
00256   if (!pn53x_set_reg (pnd, REG_CIU_CONTROL, SYMBOL_INITIATOR, 0x10))
00257     return false;
00258 
00259   return true;
00260 }
00261 
00278 bool
00279 nfc_initiator_select_dep_target (nfc_device_t * pnd, const nfc_modulation_t nmInitModulation, const byte_t * pbtPidData,
00280                                  const size_t szPidDataLen, const byte_t * pbtNFCID3i, const size_t szNFCID3iDataLen,
00281                                  const byte_t * pbtGbData, const size_t szGbDataLen, nfc_target_info_t * pnti)
00282 {
00283   pnd->iLastError = 0;
00284 
00285   return pn53x_initiator_select_dep_target (pnd, nmInitModulation, pbtPidData, szPidDataLen, pbtNFCID3i,
00286                                             szNFCID3iDataLen, pbtGbData, szGbDataLen, pnti);
00287 }
00288 
00303 bool
00304 nfc_initiator_select_passive_target (nfc_device_t * pnd,
00305                                      const nfc_modulation_t nmInitModulation,
00306                                      const byte_t * pbtInitData, const size_t szInitDataLen, nfc_target_info_t * pnti)
00307 {
00308   byte_t  abtInit[MAX_FRAME_LEN];
00309   size_t  szInitLen;
00310 
00311   size_t  szTargetsData;
00312   byte_t  abtTargetsData[MAX_FRAME_LEN];
00313 
00314   pnd->iLastError = 0;
00315 
00316   // Make sure we are dealing with a active device
00317   if (!pnd->bActive)
00318     return false;
00319   // TODO Put this in a function
00320   switch (nmInitModulation) {
00321   case NM_ISO14443A_106:
00322     switch (szInitDataLen) {
00323     case 7:
00324       abtInit[0] = 0x88;
00325       memcpy (abtInit + 1, pbtInitData, 7);
00326       szInitLen = 8;
00327       break;
00328 
00329     case 10:
00330       abtInit[0] = 0x88;
00331       memcpy (abtInit + 1, pbtInitData, 3);
00332       abtInit[4] = 0x88;
00333       memcpy (abtInit + 5, pbtInitData + 3, 7);
00334       szInitLen = 12;
00335       break;
00336 
00337     case 4:
00338     default:
00339       memcpy (abtInit, pbtInitData, szInitDataLen);
00340       szInitLen = szInitDataLen;
00341       break;
00342     }
00343     break;
00344 
00345   default:
00346     memcpy (abtInit, pbtInitData, szInitDataLen);
00347     szInitLen = szInitDataLen;
00348     break;
00349   }
00350 
00351   if (!pn53x_InListPassiveTarget (pnd, nmInitModulation, 1, abtInit, szInitLen, abtTargetsData, &szTargetsData))
00352     return false;
00353 
00354   // Make sure one tag has been found, the PN53X returns 0x00 if none was available
00355   if (abtTargetsData[0] == 0)
00356     return false;
00357 
00358   // Is a tag info struct available
00359   if (pnti) {
00360     // Fill the tag info struct with the values corresponding to this init modulation
00361     switch (nmInitModulation) {
00362     case NM_ISO14443A_106:
00363       if (!pn53x_decode_target_data (abtTargetsData + 1, szTargetsData - 1, pnd->nc, NTT_GENERIC_PASSIVE_106, pnti)) {
00364         return false;
00365       }
00366       break;
00367 
00368     case NM_FELICA_212:
00369       if (!pn53x_decode_target_data (abtTargetsData + 1, szTargetsData - 1, pnd->nc, NTT_FELICA_212, pnti)) {
00370         return false;
00371       }
00372       break;
00373     case NM_FELICA_424:
00374       if (!pn53x_decode_target_data (abtTargetsData + 1, szTargetsData - 1, pnd->nc, NTT_FELICA_424, pnti)) {
00375         return false;
00376       }
00377       break;
00378 
00379     case NM_ISO14443B_106:
00380       if (!pn53x_decode_target_data (abtTargetsData + 1, szTargetsData - 1, pnd->nc, NTT_ISO14443B_106, pnti)) {
00381         return false;
00382       }
00383       break;
00384 
00385     case NM_JEWEL_106:
00386       if (!pn53x_decode_target_data (abtTargetsData + 1, szTargetsData - 1, pnd->nc, NTT_JEWEL_106, pnti)) {
00387         return false;
00388       }
00389       break;
00390 
00391     default:
00392       // Should not be possible, so whatever...
00393       break;
00394     }
00395   }
00396   return true;
00397 }
00398 
00399 bool
00400 nfc_initiator_list_passive_targets (nfc_device_t * pnd, const nfc_modulation_t nmInitModulation,
00401                                     nfc_target_info_t anti[], const size_t szTargets, size_t * pszTargetFound)
00402 {
00403   nfc_target_info_t nti;
00404   size_t  szTargetFound = 0;
00405   byte_t *pbtInitData = NULL;
00406   size_t  szInitDataLen = 0;
00407 
00408   pnd->iLastError = 0;
00409 
00410   // Let the reader only try once to find a target
00411   nfc_configure (pnd, NDO_INFINITE_SELECT, false);
00412 
00413   if (nmInitModulation == NM_ISO14443B_106) {
00414     // Application Family Identifier (AFI) must equals 0x00 in order to wakeup all ISO14443-B PICCs (see ISO/IEC 14443-3)
00415     pbtInitData = (byte_t *) "\x00";
00416     szInitDataLen = 1;
00417   }
00418   while (nfc_initiator_select_passive_target (pnd, nmInitModulation, pbtInitData, szInitDataLen, &nti)) {
00419     nfc_initiator_deselect_target (pnd);
00420 
00421     if (szTargets > szTargetFound) {
00422       memcpy (&(anti[szTargetFound]), &nti, sizeof (nfc_target_info_t));
00423     }
00424     szTargetFound++;
00425   }
00426   *pszTargetFound = szTargetFound;
00427 
00428   return true;
00429 }
00430 
00438 bool
00439 nfc_initiator_deselect_target (nfc_device_t * pnd)
00440 {
00441   pnd->iLastError = 0;
00442 
00443   return (pn53x_InDeselect (pnd, 0));   // 0 mean deselect all selected targets
00444 }
00445 
00457 bool
00458 nfc_initiator_poll_targets (nfc_device_t * pnd,
00459                             const nfc_target_type_t * pnttTargetTypes, const size_t szTargetTypes,
00460                             const byte_t btPollNr, const byte_t btPeriod,
00461                             nfc_target_t * pntTargets, size_t * pszTargetFound)
00462 {
00463   pnd->iLastError = 0;
00464 
00465   return pn53x_InAutoPoll (pnd, pnttTargetTypes, szTargetTypes, btPollNr, btPeriod, pntTargets, pszTargetFound);
00466 }
00467 
00480 bool
00481 nfc_initiator_transceive_bits (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxBits, const byte_t * pbtTxPar,
00482                                byte_t * pbtRx, size_t * pszRxBits, byte_t * pbtRxPar)
00483 {
00484   pnd->iLastError = 0;
00485 
00486   return pn53x_initiator_transceive_bits (pnd, pbtTx, szTxBits, pbtTxPar, pbtRx, pszRxBits, pbtRxPar);
00487 }
00488 
00502 bool
00503 nfc_initiator_transceive_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen, byte_t * pbtRx,
00504                                 size_t * pszRxLen)
00505 {
00506   pnd->iLastError = 0;
00507 
00508   return pn53x_initiator_transceive_bytes (pnd, pbtTx, szTxLen, pbtRx, pszRxLen);
00509 }
00510 
00519 bool
00520 nfc_target_init (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBits)
00521 {
00522   pnd->iLastError = 0;
00523 
00524   return pn53x_target_init (pnd, pbtRx, pszRxBits);
00525 }
00526 
00533 bool
00534 nfc_target_receive_bits (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxBits, byte_t * pbtRxPar)
00535 {
00536   pnd->iLastError = 0;
00537 
00538   return pn53x_target_receive_bits (pnd, pbtRx, pszRxBits, pbtRxPar);
00539 }
00540 
00547 bool
00548 nfc_target_receive_bytes (nfc_device_t * pnd, byte_t * pbtRx, size_t * pszRxLen)
00549 {
00550   pnd->iLastError = 0;
00551 
00552   return pn53x_target_receive_bytes (pnd, pbtRx, pszRxLen);
00553 }
00554 
00561 bool
00562 nfc_target_send_bits (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxBits, const byte_t * pbtTxPar)
00563 {
00564   pnd->iLastError = 0;
00565 
00566   return pn53x_target_send_bits (pnd, pbtTx, szTxBits, pbtTxPar);
00567 }
00568 
00569 
00576 bool
00577 nfc_target_send_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen)
00578 {
00579   pnd->iLastError = 0;
00580 
00581   return pn53x_target_send_bytes (pnd, pbtTx, szTxLen);
00582 }
00583 
00588 const char *
00589 nfc_strerror (const nfc_device_t * pnd)
00590 {
00591   return pnd->pdc->pcc->strerror (pnd);
00592 }
00593 
00598 int
00599 nfc_strerror_r (const nfc_device_t * pnd, char *pcStrErrBuf, size_t szBufLen)
00600 {
00601   return (snprintf (pcStrErrBuf, szBufLen, "%s", nfc_strerror (pnd)) < 0) ? -1 : 0;
00602 }
00603 
00607 void
00608 nfc_perror (const nfc_device_t * pnd, const char *pcString)
00609 {
00610   fprintf (stderr, "%s: %s\n", pcString, nfc_strerror (pnd));
00611 }
00612 
00613 /* Special data accessors */
00614 
00619 const char *
00620 nfc_device_name (nfc_device_t * pnd)
00621 {
00622   return pnd->acName;
00623 }
00624 
00625 /* Misc. functions */
00626 
00631 const char *
00632 nfc_version (void)
00633 {
00634 #ifdef SVN_REVISION
00635   return PACKAGE_VERSION " (r" SVN_REVISION ")";
00636 #else
00637   return PACKAGE_VERSION;
00638 #endif // SVN_REVISION
00639 }