libnfc
1.4.2
|
00001 /*- 00002 * Public platform independent Near Field Communication (NFC) library examples 00003 * 00004 * Copyright (C) 2009, Roel Verdult 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 <stddef.h> 00042 #include <stdint.h> 00043 #include <stdbool.h> 00044 #include <string.h> 00045 00046 #include <nfc/nfc.h> 00047 00048 #include <nfc/nfc-messages.h> 00049 #include "nfc-utils.h" 00050 00051 #define SAK_FLAG_ATS_SUPPORTED 0x20 00052 00053 #define MAX_FRAME_LEN 264 00054 00055 static byte_t abtRx[MAX_FRAME_LEN]; 00056 static size_t szRxBits; 00057 static size_t szRx; 00058 static byte_t abtRawUid[12]; 00059 static byte_t abtAtqa[2]; 00060 static byte_t abtSak; 00061 static size_t szCL = 1;//Always start with Cascade Level 1 (CL1) 00062 static nfc_device_t *pnd; 00063 00064 bool quiet_output = false; 00065 00066 // ISO14443A Anti-Collision Commands 00067 byte_t abtReqa[1] = { 0x26 }; 00068 byte_t abtSelectAll[2] = { 0x93, 0x20 }; 00069 byte_t abtSelectTag[9] = { 0x93, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 00070 byte_t abtRats[4] = { 0xe0, 0x50, 0x00, 0x00 }; 00071 byte_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 }; 00072 #define CASCADE_BIT 0x04 00073 00074 static bool 00075 transmit_bits (const byte_t * pbtTx, const size_t szTxBits) 00076 { 00077 // Show transmitted command 00078 if (!quiet_output) { 00079 printf ("Sent bits: "); 00080 print_hex_bits (pbtTx, szTxBits); 00081 } 00082 // Transmit the bit frame command, we don't use the arbitrary parity feature 00083 if (!nfc_initiator_transceive_bits (pnd, pbtTx, szTxBits, NULL, abtRx, &szRxBits, NULL)) 00084 return false; 00085 00086 // Show received answer 00087 if (!quiet_output) { 00088 printf ("Received bits: "); 00089 print_hex_bits (abtRx, szRxBits); 00090 } 00091 // Succesful transfer 00092 return true; 00093 } 00094 00095 00096 static bool 00097 transmit_bytes (const byte_t * pbtTx, const size_t szTx) 00098 { 00099 // Show transmitted command 00100 if (!quiet_output) { 00101 printf ("Sent bits: "); 00102 print_hex (pbtTx, szTx); 00103 } 00104 // Transmit the command bytes 00105 if (!nfc_initiator_transceive_bytes (pnd, pbtTx, szTx, abtRx, &szRx)) 00106 return false; 00107 00108 // Show received answer 00109 if (!quiet_output) { 00110 printf ("Received bits: "); 00111 print_hex (abtRx, szRx); 00112 } 00113 // Succesful transfer 00114 return true; 00115 } 00116 00117 static void 00118 print_usage (char *argv[]) 00119 { 00120 printf ("Usage: %s [OPTIONS]\n", argv[0]); 00121 printf ("Options:\n"); 00122 printf ("\t-h\tHelp. Print this message.\n"); 00123 printf ("\t-q\tQuiet mode. Suppress output of READER and EMULATOR data (improves timing).\n"); 00124 } 00125 00126 int 00127 main (int argc, char *argv[]) 00128 { 00129 int arg; 00130 00131 // Get commandline options 00132 for (arg = 1; arg < argc; arg++) { 00133 if (0 == strcmp (argv[arg], "-h")) { 00134 print_usage (argv); 00135 exit(EXIT_SUCCESS); 00136 } else if (0 == strcmp (argv[arg], "-q")) { 00137 quiet_output = true; 00138 } else { 00139 ERR ("%s is not supported option.", argv[arg]); 00140 print_usage (argv); 00141 exit(EXIT_FAILURE); 00142 } 00143 } 00144 00145 // Try to open the NFC reader 00146 pnd = nfc_connect (NULL); 00147 00148 if (!pnd) { 00149 printf ("Error connecting NFC reader\n"); 00150 exit(EXIT_FAILURE); 00151 } 00152 00153 // Initialise NFC device as "initiator" 00154 nfc_initiator_init (pnd); 00155 00156 // Drop the field for a while 00157 if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) { 00158 nfc_perror (pnd, "nfc_configure"); 00159 exit (EXIT_FAILURE); 00160 } 00161 00162 // Configure the CRC 00163 if (!nfc_configure (pnd, NDO_HANDLE_CRC, false)) { 00164 nfc_perror (pnd, "nfc_configure"); 00165 exit (EXIT_FAILURE); 00166 } 00167 // Configure parity settings 00168 if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true)) { 00169 nfc_perror (pnd, "nfc_configure"); 00170 exit (EXIT_FAILURE); 00171 } 00172 // Use raw send/receive methods 00173 if (!nfc_configure (pnd, NDO_EASY_FRAMING, false)) { 00174 nfc_perror (pnd, "nfc_configure"); 00175 exit (EXIT_FAILURE); 00176 } 00177 // Disable 14443-4 autoswitching 00178 if (!nfc_configure (pnd, NDO_AUTO_ISO14443_4, false)) { 00179 nfc_perror (pnd, "nfc_configure"); 00180 exit (EXIT_FAILURE); 00181 } 00182 // Force 14443-A mode 00183 if (!nfc_configure (pnd, NDO_FORCE_ISO14443_A, true)) { 00184 nfc_perror (pnd, "nfc_configure"); 00185 exit (EXIT_FAILURE); 00186 } 00187 00188 // Enable field so more power consuming cards can power themselves up 00189 if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) { 00190 nfc_perror (pnd, "nfc_configure"); 00191 exit (EXIT_FAILURE); 00192 } 00193 00194 printf ("Connected to NFC reader: %s\n\n", pnd->acName); 00195 00196 // Send the 7 bits request command specified in ISO 14443A (0x26) 00197 if (!transmit_bits (abtReqa, 7)) { 00198 printf ("Error: No tag available\n"); 00199 nfc_disconnect (pnd); 00200 return 1; 00201 } 00202 memcpy (abtAtqa, abtRx, 2); 00203 00204 // Anti-collision 00205 transmit_bytes (abtSelectAll, 2); 00206 00207 // Check answer 00208 if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) { 00209 printf("WARNING: BCC check failed!\n"); 00210 } 00211 00212 // Save the UID CL1 00213 memcpy (abtRawUid, abtRx, 4); 00214 00215 //Prepare and send CL1 Select-Command 00216 memcpy (abtSelectTag + 2, abtRx, 5); 00217 iso14443a_crc_append (abtSelectTag, 7); 00218 transmit_bytes (abtSelectTag, 9); 00219 abtSak = abtRx[0]; 00220 00221 // Test if we are dealing with a CL2 00222 if (abtSak & CASCADE_BIT) { 00223 szCL = 2;//or more 00224 // Check answer 00225 if (abtRawUid[0] != 0x88) { 00226 printf("WARNING: Cascade bit set but CT != 0x88!\n"); 00227 } 00228 } 00229 00230 if(szCL == 2) { 00231 // We have to do the anti-collision for cascade level 2 00232 00233 // Prepare CL2 commands 00234 abtSelectAll[0] = 0x95; 00235 00236 // Anti-collision 00237 transmit_bytes (abtSelectAll, 2); 00238 00239 // Check answer 00240 if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) { 00241 printf("WARNING: BCC check failed!\n"); 00242 } 00243 00244 // Save UID CL2 00245 memcpy (abtRawUid + 4, abtRx, 4); 00246 00247 // Selection 00248 abtSelectTag[0] = 0x95; 00249 memcpy (abtSelectTag + 2, abtRx, 5); 00250 iso14443a_crc_append (abtSelectTag, 7); 00251 transmit_bytes (abtSelectTag, 9); 00252 abtSak = abtRx[0]; 00253 00254 // Test if we are dealing with a CL3 00255 if (abtSak & CASCADE_BIT) { 00256 szCL = 3; 00257 // Check answer 00258 if (abtRawUid[0] != 0x88) { 00259 printf("WARNING: Cascade bit set but CT != 0x88!\n"); 00260 } 00261 } 00262 00263 if ( szCL == 3) { 00264 // We have to do the anti-collision for cascade level 3 00265 00266 // Prepare and send CL3 AC-Command 00267 abtSelectAll[0] = 0x97; 00268 transmit_bytes (abtSelectAll, 2); 00269 00270 // Check answer 00271 if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) { 00272 printf("WARNING: BCC check failed!\n"); 00273 } 00274 00275 // Save UID CL3 00276 memcpy (abtRawUid + 8, abtRx, 4); 00277 00278 // Prepare and send final Select-Command 00279 abtSelectTag[0] = 0x97; 00280 memcpy (abtSelectTag + 2, abtRx, 5); 00281 iso14443a_crc_append (abtSelectTag, 7); 00282 transmit_bytes (abtSelectTag, 9); 00283 abtSak = abtRx[0]; 00284 } 00285 } 00286 00287 // Request ATS, this only applies to tags that support ISO 14443A-4 00288 if (abtRx[0] & SAK_FLAG_ATS_SUPPORTED) { 00289 iso14443a_crc_append(abtRats, 2); 00290 transmit_bytes (abtRats, 4); 00291 } 00292 00293 // Done, halt the tag now 00294 iso14443a_crc_append(abtHalt, 2); 00295 transmit_bytes (abtHalt, 4); 00296 00297 printf ("\nFound tag with\n UID: "); 00298 switch (szCL) { 00299 case 1: 00300 printf ("%02x%02x%02x%02x", abtRawUid[0], abtRawUid[1], abtRawUid[2], abtRawUid[3]); 00301 break; 00302 case 2: 00303 printf ("%02x%02x%02x", abtRawUid[1], abtRawUid[2], abtRawUid[3]); 00304 printf ("%02x%02x%02x%02x", abtRawUid[4], abtRawUid[5], abtRawUid[6], abtRawUid[7]); 00305 break; 00306 case 3: 00307 printf ("%02x%02x%02x", abtRawUid[1], abtRawUid[2], abtRawUid[3]); 00308 printf ("%02x%02x%02x", abtRawUid[5], abtRawUid[6], abtRawUid[7]); 00309 printf ("%02x%02x%02x%02x", abtRawUid[8], abtRawUid[9], abtRawUid[10], abtRawUid[11]); 00310 break; 00311 } 00312 printf("\n"); 00313 printf("ATQA: %02x%02x\n SAK: %02x\n", abtAtqa[1], abtAtqa[0], abtSak); 00314 00315 nfc_disconnect (pnd); 00316 return 0; 00317 }