nfc-anticol.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 <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 }