libnfc  1.4.2
nfc-anticol.c
Go to the documentation of this file.
1 /*-
2  * Public platform independent Near Field Communication (NFC) library examples
3  *
4  * Copyright (C) 2009, Roel Verdult
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  * 1) Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  * 2 )Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
18  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  * POSSIBILITY OF SUCH DAMAGE.
25  *
26  * Note that this license only applies on the examples, NFC library itself is under LGPL
27  *
28  */
29 
35 #ifdef HAVE_CONFIG_H
36 # include "config.h"
37 #endif // HAVE_CONFIG_H
38 
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <stddef.h>
42 #include <stdint.h>
43 #include <stdbool.h>
44 #include <string.h>
45 
46 #include <nfc/nfc.h>
47 
48 #include <nfc/nfc-messages.h>
49 #include "nfc-utils.h"
50 
51 #define SAK_FLAG_ATS_SUPPORTED 0x20
52 
53 #define MAX_FRAME_LEN 264
54 
55 static byte_t abtRx[MAX_FRAME_LEN];
56 static size_t szRxBits;
57 static size_t szRx;
58 static byte_t abtRawUid[12];
59 static byte_t abtAtqa[2];
60 static byte_t abtSak;
61 static size_t szCL = 1;//Always start with Cascade Level 1 (CL1)
62 static nfc_device_t *pnd;
63 
64 bool quiet_output = false;
65 
66 // ISO14443A Anti-Collision Commands
67 byte_t abtReqa[1] = { 0x26 };
68 byte_t abtSelectAll[2] = { 0x93, 0x20 };
69 byte_t abtSelectTag[9] = { 0x93, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
70 byte_t abtRats[4] = { 0xe0, 0x50, 0x00, 0x00 };
71 byte_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 };
72 #define CASCADE_BIT 0x04
73 
74 static bool
75 transmit_bits (const byte_t * pbtTx, const size_t szTxBits)
76 {
77  // Show transmitted command
78  if (!quiet_output) {
79  printf ("Sent bits: ");
80  print_hex_bits (pbtTx, szTxBits);
81  }
82  // Transmit the bit frame command, we don't use the arbitrary parity feature
83  if (!nfc_initiator_transceive_bits (pnd, pbtTx, szTxBits, NULL, abtRx, &szRxBits, NULL))
84  return false;
85 
86  // Show received answer
87  if (!quiet_output) {
88  printf ("Received bits: ");
89  print_hex_bits (abtRx, szRxBits);
90  }
91  // Succesful transfer
92  return true;
93 }
94 
95 
96 static bool
97 transmit_bytes (const byte_t * pbtTx, const size_t szTx)
98 {
99  // Show transmitted command
100  if (!quiet_output) {
101  printf ("Sent bits: ");
102  print_hex (pbtTx, szTx);
103  }
104  // Transmit the command bytes
105  if (!nfc_initiator_transceive_bytes (pnd, pbtTx, szTx, abtRx, &szRx))
106  return false;
107 
108  // Show received answer
109  if (!quiet_output) {
110  printf ("Received bits: ");
111  print_hex (abtRx, szRx);
112  }
113  // Succesful transfer
114  return true;
115 }
116 
117 static void
118 print_usage (char *argv[])
119 {
120  printf ("Usage: %s [OPTIONS]\n", argv[0]);
121  printf ("Options:\n");
122  printf ("\t-h\tHelp. Print this message.\n");
123  printf ("\t-q\tQuiet mode. Suppress output of READER and EMULATOR data (improves timing).\n");
124 }
125 
126 int
127 main (int argc, char *argv[])
128 {
129  int arg;
130 
131  // Get commandline options
132  for (arg = 1; arg < argc; arg++) {
133  if (0 == strcmp (argv[arg], "-h")) {
134  print_usage (argv);
135  exit(EXIT_SUCCESS);
136  } else if (0 == strcmp (argv[arg], "-q")) {
137  quiet_output = true;
138  } else {
139  ERR ("%s is not supported option.", argv[arg]);
140  print_usage (argv);
141  exit(EXIT_FAILURE);
142  }
143  }
144 
145  // Try to open the NFC reader
146  pnd = nfc_connect (NULL);
147 
148  if (!pnd) {
149  printf ("Error connecting NFC reader\n");
150  exit(EXIT_FAILURE);
151  }
152 
153  // Initialise NFC device as "initiator"
154  nfc_initiator_init (pnd);
155 
156  // Drop the field for a while
157  if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) {
158  nfc_perror (pnd, "nfc_configure");
159  exit (EXIT_FAILURE);
160  }
161 
162  // Configure the CRC
163  if (!nfc_configure (pnd, NDO_HANDLE_CRC, false)) {
164  nfc_perror (pnd, "nfc_configure");
165  exit (EXIT_FAILURE);
166  }
167  // Configure parity settings
168  if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true)) {
169  nfc_perror (pnd, "nfc_configure");
170  exit (EXIT_FAILURE);
171  }
172  // Use raw send/receive methods
173  if (!nfc_configure (pnd, NDO_EASY_FRAMING, false)) {
174  nfc_perror (pnd, "nfc_configure");
175  exit (EXIT_FAILURE);
176  }
177  // Disable 14443-4 autoswitching
178  if (!nfc_configure (pnd, NDO_AUTO_ISO14443_4, false)) {
179  nfc_perror (pnd, "nfc_configure");
180  exit (EXIT_FAILURE);
181  }
182  // Force 14443-A mode
183  if (!nfc_configure (pnd, NDO_FORCE_ISO14443_A, true)) {
184  nfc_perror (pnd, "nfc_configure");
185  exit (EXIT_FAILURE);
186  }
187 
188  // Enable field so more power consuming cards can power themselves up
189  if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) {
190  nfc_perror (pnd, "nfc_configure");
191  exit (EXIT_FAILURE);
192  }
193 
194  printf ("Connected to NFC reader: %s\n\n", pnd->acName);
195 
196  // Send the 7 bits request command specified in ISO 14443A (0x26)
197  if (!transmit_bits (abtReqa, 7)) {
198  printf ("Error: No tag available\n");
199  nfc_disconnect (pnd);
200  return 1;
201  }
202  memcpy (abtAtqa, abtRx, 2);
203 
204  // Anti-collision
205  transmit_bytes (abtSelectAll, 2);
206 
207  // Check answer
208  if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) {
209  printf("WARNING: BCC check failed!\n");
210  }
211 
212  // Save the UID CL1
213  memcpy (abtRawUid, abtRx, 4);
214 
215  //Prepare and send CL1 Select-Command
216  memcpy (abtSelectTag + 2, abtRx, 5);
217  iso14443a_crc_append (abtSelectTag, 7);
218  transmit_bytes (abtSelectTag, 9);
219  abtSak = abtRx[0];
220 
221  // Test if we are dealing with a CL2
222  if (abtSak & CASCADE_BIT) {
223  szCL = 2;//or more
224  // Check answer
225  if (abtRawUid[0] != 0x88) {
226  printf("WARNING: Cascade bit set but CT != 0x88!\n");
227  }
228  }
229 
230  if(szCL == 2) {
231  // We have to do the anti-collision for cascade level 2
232 
233  // Prepare CL2 commands
234  abtSelectAll[0] = 0x95;
235 
236  // Anti-collision
237  transmit_bytes (abtSelectAll, 2);
238 
239  // Check answer
240  if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) {
241  printf("WARNING: BCC check failed!\n");
242  }
243 
244  // Save UID CL2
245  memcpy (abtRawUid + 4, abtRx, 4);
246 
247  // Selection
248  abtSelectTag[0] = 0x95;
249  memcpy (abtSelectTag + 2, abtRx, 5);
250  iso14443a_crc_append (abtSelectTag, 7);
251  transmit_bytes (abtSelectTag, 9);
252  abtSak = abtRx[0];
253 
254  // Test if we are dealing with a CL3
255  if (abtSak & CASCADE_BIT) {
256  szCL = 3;
257  // Check answer
258  if (abtRawUid[0] != 0x88) {
259  printf("WARNING: Cascade bit set but CT != 0x88!\n");
260  }
261  }
262 
263  if ( szCL == 3) {
264  // We have to do the anti-collision for cascade level 3
265 
266  // Prepare and send CL3 AC-Command
267  abtSelectAll[0] = 0x97;
268  transmit_bytes (abtSelectAll, 2);
269 
270  // Check answer
271  if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) {
272  printf("WARNING: BCC check failed!\n");
273  }
274 
275  // Save UID CL3
276  memcpy (abtRawUid + 8, abtRx, 4);
277 
278  // Prepare and send final Select-Command
279  abtSelectTag[0] = 0x97;
280  memcpy (abtSelectTag + 2, abtRx, 5);
281  iso14443a_crc_append (abtSelectTag, 7);
282  transmit_bytes (abtSelectTag, 9);
283  abtSak = abtRx[0];
284  }
285  }
286 
287  // Request ATS, this only applies to tags that support ISO 14443A-4
288  if (abtRx[0] & SAK_FLAG_ATS_SUPPORTED) {
289  iso14443a_crc_append(abtRats, 2);
290  transmit_bytes (abtRats, 4);
291  }
292 
293  // Done, halt the tag now
294  iso14443a_crc_append(abtHalt, 2);
295  transmit_bytes (abtHalt, 4);
296 
297  printf ("\nFound tag with\n UID: ");
298  switch (szCL) {
299  case 1:
300  printf ("%02x%02x%02x%02x", abtRawUid[0], abtRawUid[1], abtRawUid[2], abtRawUid[3]);
301  break;
302  case 2:
303  printf ("%02x%02x%02x", abtRawUid[1], abtRawUid[2], abtRawUid[3]);
304  printf ("%02x%02x%02x%02x", abtRawUid[4], abtRawUid[5], abtRawUid[6], abtRawUid[7]);
305  break;
306  case 3:
307  printf ("%02x%02x%02x", abtRawUid[1], abtRawUid[2], abtRawUid[3]);
308  printf ("%02x%02x%02x", abtRawUid[5], abtRawUid[6], abtRawUid[7]);
309  printf ("%02x%02x%02x%02x", abtRawUid[8], abtRawUid[9], abtRawUid[10], abtRawUid[11]);
310  break;
311  }
312  printf("\n");
313  printf("ATQA: %02x%02x\n SAK: %02x\n", abtAtqa[1], abtAtqa[0], abtSak);
314 
315  nfc_disconnect (pnd);
316  return 0;
317 }