libnfc 1.4.2
|
00001 /*- 00002 * Public platform independent Near Field Communication (NFC) library examples 00003 * 00004 * Copyright (C) 2010, Emanuele Bertoldi 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions are met: 00008 * 1) Redistributions of source code must retain the above copyright notice, 00009 * this list of conditions and the following disclaimer. 00010 * 2 )Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 00014 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00015 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00016 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00017 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00018 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00019 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00020 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00021 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00022 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00023 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00024 * POSSIBILITY OF SUCH DAMAGE. 00025 * 00026 * Note that this license only applies on the examples, NFC library itself is under LGPL 00027 * 00028 */ 00029 00035 #ifdef HAVE_CONFIG_H 00036 # include "config.h" 00037 #endif // HAVE_CONFIG_H 00038 00039 #include <stdio.h> 00040 #include <stdlib.h> 00041 #include <time.h> 00042 00043 #ifndef _WIN32 00044 // Needed by sleep() under Unix 00045 # include <unistd.h> 00046 # define sleep sleep 00047 # define SUSP_TIME 1 // secs. 00048 #else 00049 // Needed by Sleep() under Windows 00050 # include "../contrib/windows.h" 00051 # include <winbase.h> 00052 # define sleep Sleep 00053 # define SUSP_TIME 1000 // msecs. 00054 #endif 00055 00056 #include <nfc/nfc.h> 00057 #include <nfc/nfc-messages.h> 00058 #include "nfc-utils.h" 00059 00060 #include "chips/pn53x.h" 00061 00062 #define MAX_FRAME_LEN 264 00063 #define TIMEOUT 60 // secs. 00064 00065 #define NORMAL_MODE 1 00066 #define VIRTUAL_CARD_MODE 2 00067 #define WIRED_CARD_MODE 3 00068 #define DUAL_CARD_MODE 4 00069 00070 bool 00071 sam_connection (nfc_device_t * pnd, int mode) 00072 { 00073 byte_t pncmd_sam_config[] = { 0xD4, 0x14, 0x00, 0x00 }; 00074 size_t szCmd = 0; 00075 00076 byte_t abtRx[MAX_FRAME_LEN]; 00077 size_t szRx; 00078 00079 pncmd_sam_config[2] = mode; 00080 00081 switch (mode) { 00082 case VIRTUAL_CARD_MODE: 00083 { 00084 // Only the VIRTUAL_CARD_MODE requires 4 bytes. 00085 szCmd = sizeof (pncmd_sam_config); 00086 } 00087 break; 00088 00089 default: 00090 { 00091 szCmd = sizeof (pncmd_sam_config) - 1; 00092 } 00093 break; 00094 } 00095 00096 if (!pn53x_transceive (pnd, pncmd_sam_config, szCmd, abtRx, &szRx)) { 00097 nfc_perror(pnd, "pn53x_transceive"); 00098 ERR ("%s %d", "Unable to execute SAMConfiguration command with mode byte:", mode); 00099 return false; 00100 } 00101 00102 return true; 00103 } 00104 00105 void 00106 wait_one_minute () 00107 { 00108 int secs = 0; 00109 00110 printf ("|"); 00111 fflush (stdout); 00112 00113 while (secs < TIMEOUT) { 00114 sleep (SUSP_TIME); 00115 secs++; 00116 printf ("."); 00117 fflush (stdout); 00118 } 00119 00120 printf ("|\n"); 00121 } 00122 00123 int 00124 main (int argc, const char *argv[]) 00125 { 00126 nfc_device_t *pnd; 00127 00128 (void) argc; 00129 (void) argv; 00130 00131 // Display libnfc version 00132 const char *acLibnfcVersion = nfc_version (); 00133 printf ("%s use libnfc %s\n", argv[0], acLibnfcVersion); 00134 00135 // Connect using the first available NFC device 00136 pnd = nfc_connect (NULL); 00137 00138 if (pnd == NULL) { 00139 ERR ("%s", "Unable to connect to NFC device."); 00140 return EXIT_FAILURE; 00141 } 00142 00143 printf ("Connected to NFC device: %s\n", pnd->acName); 00144 00145 // Print the example's menu 00146 printf ("\nSelect the communication mode:\n"); 00147 printf ("[1] Virtual card mode.\n"); 00148 printf ("[2] Wired card mode.\n"); 00149 printf ("[3] Dual card mode.\n"); 00150 printf (">> "); 00151 00152 // Take user's choice 00153 char input = getchar (); 00154 int mode = input - '0' + 1; 00155 printf ("\n"); 00156 if (mode < VIRTUAL_CARD_MODE || mode > DUAL_CARD_MODE) { 00157 ERR ("%s", "Invalid selection."); 00158 return EXIT_FAILURE; 00159 } 00160 // Connect with the SAM 00161 sam_connection (pnd, mode); 00162 00163 switch (mode) { 00164 case VIRTUAL_CARD_MODE: 00165 { 00166 // FIXME after the loop the device doesn't respond to host commands... 00167 printf ("Now the SAM is readable for 1 minute from an external reader.\n"); 00168 wait_one_minute (); 00169 } 00170 break; 00171 00172 case WIRED_CARD_MODE: 00173 { 00174 nfc_target_t nt; 00175 00176 // Set connected NFC device to initiator mode 00177 nfc_initiator_init (pnd); 00178 00179 // Drop the field for a while 00180 if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) { 00181 nfc_perror (pnd, "nfc_configure"); 00182 exit (EXIT_FAILURE); 00183 } 00184 // Let the reader only try once to find a tag 00185 if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) { 00186 nfc_perror (pnd, "nfc_configure"); 00187 exit (EXIT_FAILURE); 00188 } 00189 // Enable field so more power consuming cards can power themselves up 00190 if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) { 00191 nfc_perror (pnd, "nfc_configure"); 00192 exit (EXIT_FAILURE); 00193 } 00194 // Read the SAM's info 00195 const nfc_modulation_t nmSAM = { 00196 .nmt = NMT_ISO14443A, 00197 .nbr = NBR_106, 00198 }; 00199 if (!nfc_initiator_select_passive_target (pnd, nmSAM, NULL, 0, &nt)) { 00200 nfc_perror (pnd, "nfc_initiator_select_passive_target"); 00201 ERR ("%s", "Reading of SAM info failed."); 00202 return EXIT_FAILURE; 00203 } 00204 00205 printf ("The following ISO14443A tag (SAM) was found:\n\n"); 00206 print_nfc_iso14443a_info (nt.nti.nai, true); 00207 } 00208 break; 00209 00210 case DUAL_CARD_MODE: 00211 { 00212 byte_t abtRx[MAX_FRAME_LEN]; 00213 size_t szRx; 00214 00215 nfc_target_t nt = { 00216 .nm.nmt = NMT_ISO14443A, 00217 .nm.nbr = NBR_UNDEFINED, 00218 .nti.nai.abtAtqa = { 0x04, 0x00 }, 00219 .nti.nai.abtUid = { 0x08, 0xad, 0xbe, 0xef }, 00220 .nti.nai.btSak = 0x20, 00221 .nti.nai.szUidLen = 4, 00222 .nti.nai.szAtsLen = 0, 00223 }; 00224 printf ("Now both, NFC device (configured as target) and SAM are readables from an external NFC initiator.\n"); 00225 printf ("Please note that NFC device (configured as target) stay in target mode until it receive RATS, ATR_REQ or proprietary command.\n"); 00226 if (!nfc_target_init (pnd, &nt, abtRx, &szRx)) { 00227 nfc_perror(pnd, "nfc_target_init"); 00228 return EXIT_FAILURE; 00229 } 00230 // wait_one_minute (); 00231 } 00232 break; 00233 } 00234 00235 // Disconnect from the SAM 00236 sam_connection (pnd, NORMAL_MODE); 00237 00238 // Disconnect from NFC device 00239 nfc_disconnect (pnd); 00240 00241 return EXIT_SUCCESS; 00242 }