nfc-sam.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 <stdio.h>
00030 #include <stdlib.h>
00031 #include <time.h>
00032 
00033 #ifndef _WIN32
00034 // Needed by sleep() under Unix
00035 #  include <unistd.h>
00036 #  define sleep sleep
00037 #  define SUSP_TIME 1           // secs.
00038 #else
00039 // Needed by Sleep() under Windows
00040 #  include <winbase.h>
00041 #  define sleep Sleep
00042 #  define SUSP_TIME 1000        // msecs.
00043 #endif
00044 
00045 #include <nfc/nfc.h>
00046 #include <nfc/nfc-messages.h>
00047 #include "nfc-utils.h"
00048 // FIXME: Remove me
00049 #include "chips/pn53x.h"
00050 
00051 #define MAX_FRAME_LEN 264
00052 #define TIMEOUT 60              // secs.
00053 
00054 #define NORMAL_MODE 1
00055 #define VIRTUAL_CARD_MODE 2
00056 #define WIRED_CARD_MODE 3
00057 #define DUAL_CARD_MODE 4
00058 
00059 bool
00060 sam_connection (nfc_device_t * pnd, int mode)
00061 {
00062   byte_t  pncmd_sam_config[] = { 0xD4, 0x14, 0x00, 0x00 };
00063   size_t  szCmd = 0;
00064 
00065   byte_t  abtRx[MAX_FRAME_LEN];
00066   size_t  szRxLen;
00067 
00068   pncmd_sam_config[2] = mode;
00069 
00070   switch (mode) {
00071   case VIRTUAL_CARD_MODE:
00072     {
00073       // Only the VIRTUAL_CARD_MODE requires 4 bytes.
00074       szCmd = sizeof (pncmd_sam_config);
00075     }
00076     break;
00077 
00078   default:
00079     {
00080       szCmd = sizeof (pncmd_sam_config) - 1;
00081     }
00082     break;
00083   }
00084 
00085   // FIXME: Direct call
00086   if (!pn53x_transceive (pnd, pncmd_sam_config, szCmd, abtRx, &szRxLen)) {
00087     ERR ("%s %d", "Unable to execute SAMConfiguration command with mode byte:", mode);
00088     return false;
00089   }
00090 
00091   return true;
00092 }
00093 
00094 void
00095 wait_one_minute ()
00096 {
00097   int     secs = 0;
00098 
00099   printf ("|");
00100   fflush (stdout);
00101 
00102   while (secs < TIMEOUT) {
00103     sleep (SUSP_TIME);
00104     secs++;
00105     printf (".");
00106     fflush (stdout);
00107   }
00108 
00109   printf ("|\n");
00110 }
00111 
00112 int
00113 main (int argc, const char *argv[])
00114 {
00115   nfc_device_t *pnd;
00116 
00117   (void) argc;
00118   (void) argv;
00119 
00120   // Display libnfc version
00121   const char *acLibnfcVersion = nfc_version ();
00122   printf ("%s use libnfc %s\n", argv[0], acLibnfcVersion);
00123 
00124   // Connect using the first available NFC device
00125   pnd = nfc_connect (NULL);
00126 
00127   if (pnd == NULL) {
00128     ERR ("%s", "Unable to connect to NFC device.");
00129     return EXIT_FAILURE;
00130   }
00131 
00132   printf ("Connected to NFC reader: %s\n", pnd->acName);
00133 
00134   // Print the example's menu
00135   printf ("\nSelect the comunication mode:\n");
00136   printf ("[1] Virtual card mode.\n");
00137   printf ("[2] Wired card mode.\n");
00138   printf ("[3] Dual card mode.\n");
00139   printf (">> ");
00140 
00141   // Take user's choice
00142   char    input = getchar ();
00143   int     mode = input - '0' + 1;
00144   printf ("\n");
00145   if (mode < VIRTUAL_CARD_MODE || mode > DUAL_CARD_MODE) {
00146     ERR ("%s", "Invalid selection.");
00147     return EXIT_FAILURE;
00148   }
00149   // Connect with the SAM
00150   sam_connection (pnd, mode);
00151 
00152   switch (mode) {
00153   case VIRTUAL_CARD_MODE:
00154     {
00155       // FIXME: after the loop the reader doesn't respond to host commands...
00156       printf ("Now the SAM is readable for 1 minute from an external reader.\n");
00157       wait_one_minute ();
00158     }
00159     break;
00160 
00161   case WIRED_CARD_MODE:
00162     {
00163       nfc_target_info_t nti;
00164 
00165       // Set connected NFC device to initiator mode
00166       nfc_initiator_init (pnd);
00167 
00168       // Drop the field for a while
00169       if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) {
00170         nfc_perror (pnd, "nfc_configure");
00171         exit (EXIT_FAILURE);
00172       }
00173       // Let the reader only try once to find a tag
00174       if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) {
00175         nfc_perror (pnd, "nfc_configure");
00176         exit (EXIT_FAILURE);
00177       }
00178       // Configure the CRC and Parity settings
00179       if (!nfc_configure (pnd, NDO_HANDLE_CRC, true)) {
00180         nfc_perror (pnd, "nfc_configure");
00181         exit (EXIT_FAILURE);
00182       }
00183       if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true)) {
00184         nfc_perror (pnd, "nfc_configure");
00185         exit (EXIT_FAILURE);
00186       }
00187       // Enable field so more power consuming cards can power themselves up
00188       if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) {
00189         nfc_perror (pnd, "nfc_configure");
00190         exit (EXIT_FAILURE);
00191       }
00192       // Read the SAM's info
00193       if (!nfc_initiator_select_passive_target (pnd, NM_ISO14443A_106, NULL, 0, &nti)) {
00194         ERR ("%s", "Reading of SAM info failed.");
00195         return EXIT_FAILURE;
00196       }
00197 
00198       printf ("The following ISO14443A tag (SAM) was found:\n\n");
00199       print_nfc_iso14443a_info (nti.nai);
00200     }
00201     break;
00202 
00203   case DUAL_CARD_MODE:
00204     {
00205       byte_t  abtRx[MAX_FRAME_LEN];
00206       size_t  szRxLen;
00207 
00208       // FIXME: it does not work as expected...Probably the issue is in "nfc_target_init"
00209       // which doesn't provide a way to set custom data for SENS_RES, NFCID1, SEL_RES, etc.
00210       if (!nfc_target_init (pnd, abtRx, &szRxLen))
00211         return EXIT_FAILURE;
00212 
00213       printf ("Now both the NFC reader and SAM are readable for 1 minute from an external reader.\n");
00214       wait_one_minute ();
00215     }
00216     break;
00217   }
00218 
00219   // Disconnect from the SAM
00220   sam_connection (pnd, NORMAL_MODE);
00221 
00222   // Disconnect from NFC device
00223   nfc_disconnect (pnd);
00224 
00225   return EXIT_SUCCESS;
00226 }