libnfc 1.3.9
|
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 <stddef.h> 00032 #include <stdint.h> 00033 #include <stdbool.h> 00034 #include <string.h> 00035 00036 #include <nfc/nfc.h> 00037 00038 #include <nfc/nfc-messages.h> 00039 #include "nfc-utils.h" 00040 00041 #define SAK_FLAG_ATS_SUPPORTED 0x20 00042 00043 #define MAX_FRAME_LEN 264 00044 00045 static byte_t abtRx[MAX_FRAME_LEN]; 00046 static size_t szRxBits; 00047 static size_t szRxLen; 00048 static byte_t abtUid[10]; 00049 static size_t szUidLen = 4; 00050 static nfc_device_t *pnd; 00051 00052 bool quiet_output = false; 00053 00054 // ISO14443A Anti-Collision Commands 00055 byte_t abtReqa[1] = { 0x26 }; 00056 byte_t abtSelectAll[2] = { 0x93, 0x20 }; 00057 byte_t abtSelectTag[9] = { 0x93, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 00058 byte_t abtRats[4] = { 0xe0, 0x50, 0xbc, 0xa5 }; 00059 byte_t abtHalt[4] = { 0x50, 0x00, 0x57, 0xcd }; 00060 00061 static bool 00062 transmit_bits (const byte_t * pbtTx, const size_t szTxBits) 00063 { 00064 // Show transmitted command 00065 if (!quiet_output) { 00066 printf ("R: "); 00067 print_hex_bits (pbtTx, szTxBits); 00068 } 00069 // Transmit the bit frame command, we don't use the arbitrary parity feature 00070 if (!nfc_initiator_transceive_bits (pnd, pbtTx, szTxBits, NULL, abtRx, &szRxBits, NULL)) 00071 return false; 00072 00073 // Show received answer 00074 if (!quiet_output) { 00075 printf ("T: "); 00076 print_hex_bits (abtRx, szRxBits); 00077 } 00078 // Succesful transfer 00079 return true; 00080 } 00081 00082 00083 static bool 00084 transmit_bytes (const byte_t * pbtTx, const size_t szTxLen) 00085 { 00086 // Show transmitted command 00087 if (!quiet_output) { 00088 printf ("R: "); 00089 print_hex (pbtTx, szTxLen); 00090 } 00091 // Transmit the command bytes 00092 if (!nfc_initiator_transceive_bytes (pnd, pbtTx, szTxLen, abtRx, &szRxLen)) 00093 return false; 00094 00095 // Show received answer 00096 if (!quiet_output) { 00097 printf ("T: "); 00098 print_hex (abtRx, szRxLen); 00099 } 00100 // Succesful transfer 00101 return true; 00102 } 00103 00104 static void 00105 print_usage (char *argv[]) 00106 { 00107 printf ("Usage: %s [OPTIONS]\n", argv[0]); 00108 printf ("Options:\n"); 00109 printf ("\t-h\tHelp. Print this message.\n"); 00110 printf ("\t-q\tQuiet mode. Suppress output of READER and EMULATOR data (improves timing).\n"); 00111 } 00112 00113 int 00114 main (int argc, char *argv[]) 00115 { 00116 int arg; 00117 00118 // Get commandline options 00119 for (arg = 1; arg < argc; arg++) { 00120 if (0 == strcmp (argv[arg], "-h")) { 00121 print_usage (argv); 00122 return 0; 00123 } else if (0 == strcmp (argv[arg], "-q")) { 00124 INFO ("%s", "Quiet mode."); 00125 quiet_output = true; 00126 } else { 00127 ERR ("%s is not supported option.", argv[arg]); 00128 print_usage (argv); 00129 return -1; 00130 } 00131 } 00132 00133 // Try to open the NFC reader 00134 pnd = nfc_connect (NULL); 00135 00136 if (!pnd) { 00137 printf ("Error connecting NFC reader\n"); 00138 return 1; 00139 } 00140 nfc_initiator_init (pnd); 00141 00142 // Drop the field for a while 00143 if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) { 00144 nfc_perror (pnd, "nfc_configure"); 00145 exit (EXIT_FAILURE); 00146 } 00147 // Configure the CRC 00148 if (!nfc_configure (pnd, NDO_HANDLE_CRC, false)) { 00149 nfc_perror (pnd, "nfc_configure"); 00150 exit (EXIT_FAILURE); 00151 } 00152 // Configure parity settings 00153 if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true)) { 00154 nfc_perror (pnd, "nfc_configure"); 00155 exit (EXIT_FAILURE); 00156 } 00157 // Enable field so more power consuming cards can power themselves up 00158 if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) { 00159 nfc_perror (pnd, "nfc_configure"); 00160 exit (EXIT_FAILURE); 00161 } 00162 00163 if (!nfc_configure (pnd, NDO_EASY_FRAMING, false)) { 00164 nfc_perror (pnd, "nfc_configure"); 00165 exit (EXIT_FAILURE); 00166 } 00167 00168 printf ("\nConnected to NFC reader: %s\n\n", pnd->acName); 00169 00170 // Send the 7 bits request command specified in ISO 14443A (0x26) 00171 if (!transmit_bits (abtReqa, 7)) { 00172 printf ("Error: No tag available\n"); 00173 nfc_disconnect (pnd); 00174 return 1; 00175 } 00176 // Anti-collision 00177 transmit_bytes (abtSelectAll, 2); 00178 00179 // Save the UID 00180 memcpy (abtUid, abtRx, 4); 00181 memcpy (abtSelectTag + 2, abtRx, 5); 00182 append_iso14443a_crc (abtSelectTag, 7); 00183 transmit_bytes (abtSelectTag, 9); 00184 00185 // Test if we are dealing with a 4 bytes uid 00186 if (abtUid[0] != 0x88) { 00187 szUidLen = 4; 00188 } else { 00189 // We have to do the anti-collision for cascade level 2 00190 abtSelectAll[0] = 0x95; 00191 abtSelectTag[0] = 0x95; 00192 00193 // Anti-collision 00194 transmit_bytes (abtSelectAll, 2); 00195 00196 // Save the UID 00197 memcpy (abtUid + 4, abtRx, 4); 00198 memcpy (abtSelectTag + 2, abtRx, 5); 00199 append_iso14443a_crc (abtSelectTag, 7); 00200 transmit_bytes (abtSelectTag, 9); 00201 szUidLen = 7; 00202 } 00203 00204 // Request ATS, this only applies to tags that support ISO 14443A-4 00205 if (abtRx[0] & SAK_FLAG_ATS_SUPPORTED) 00206 transmit_bytes (abtRats, 4); 00207 00208 // Done, halt the tag now 00209 transmit_bytes (abtHalt, 4); 00210 00211 printf ("\nFound tag with UID: "); 00212 if (szUidLen == 7) { 00213 printf ("%02x%02x%02x", abtUid[6], abtUid[5], abtUid[4]); 00214 } 00215 printf ("%02x%02x%02x%02x\n", abtUid[3], abtUid[2], abtUid[1], abtUid[0]); 00216 00217 nfc_disconnect (pnd); 00218 return 0; 00219 }