libnfc  1.4.2
nfc-utils.c
1 /*-
2  * Public platform independent Near Field Communication (NFC) library examples
3  *
4  * Copyright (C) 2009, Roel Verdult
5  * Copyright (C) 2010, Romuald Conty, Romain Tartière
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  * 1) Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  * 2 )Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  *
27  * Note that this license only applies on the examples, NFC library itself is under LGPL
28  *
29  */
30 
31 #include <nfc/nfc.h>
32 #include <err.h>
33 
34 #include "nfc-utils.h"
35 
36 static const byte_t OddParity[256] = {
37  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
38  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
39  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
40  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
41  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
42  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
43  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
44  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
45  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
46  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
47  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
48  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
49  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
50  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
51  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
52  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
53 };
54 
55 byte_t
56 oddparity (const byte_t bt)
57 {
58  return OddParity[bt];
59 }
60 
61 void
62 oddparity_bytes_ts (const byte_t * pbtData, const size_t szLen, byte_t * pbtPar)
63 {
64  size_t szByteNr;
65  // Calculate the parity bits for the command
66  for (szByteNr = 0; szByteNr < szLen; szByteNr++) {
67  pbtPar[szByteNr] = OddParity[pbtData[szByteNr]];
68  }
69 }
70 
71 void
72 print_hex (const byte_t * pbtData, const size_t szBytes)
73 {
74  size_t szPos;
75 
76  for (szPos = 0; szPos < szBytes; szPos++) {
77  printf ("%02x ", pbtData[szPos]);
78  }
79  printf ("\n");
80 }
81 
82 void
83 print_hex_bits (const byte_t * pbtData, const size_t szBits)
84 {
85  uint8_t uRemainder;
86  size_t szPos;
87  size_t szBytes = szBits / 8;
88 
89  for (szPos = 0; szPos < szBytes; szPos++) {
90  printf ("%02x ", pbtData[szPos]);
91  }
92 
93  uRemainder = szBits % 8;
94  // Print the rest bits
95  if (uRemainder != 0) {
96  if (uRemainder < 5)
97  printf ("%01x (%d bits)", pbtData[szBytes], uRemainder);
98  else
99  printf ("%02x (%d bits)", pbtData[szBytes], uRemainder);
100  }
101  printf ("\n");
102 }
103 
104 void
105 print_hex_par (const byte_t * pbtData, const size_t szBits, const byte_t * pbtDataPar)
106 {
107  uint8_t uRemainder;
108  size_t szPos;
109  size_t szBytes = szBits / 8;
110 
111  for (szPos = 0; szPos < szBytes; szPos++) {
112  printf ("%02x", pbtData[szPos]);
113  if (OddParity[pbtData[szPos]] != pbtDataPar[szPos]) {
114  printf ("! ");
115  } else {
116  printf (" ");
117  }
118  }
119 
120  uRemainder = szBits % 8;
121  // Print the rest bits, these cannot have parity bit
122  if (uRemainder != 0) {
123  if (uRemainder < 5)
124  printf ("%01x (%d bits)", pbtData[szBytes], uRemainder);
125  else
126  printf ("%02x (%d bits)", pbtData[szBytes], uRemainder);
127  }
128  printf ("\n");
129 }
130 
131 #define SAK_UID_NOT_COMPLETE 0x04
132 #define SAK_ISO14443_4_COMPLIANT 0x20
133 #define SAK_ISO18092_COMPLIANT 0x40
134 
135 void
136 print_nfc_iso14443a_info (const nfc_iso14443a_info_t nai, bool verbose)
137 {
138  printf (" ATQA (SENS_RES): ");
139  print_hex (nai.abtAtqa, 2);
140  if (verbose) {
141  printf("* UID size: ");
142  switch ((nai.abtAtqa[1] & 0xc0)>>6) {
143  case 0:
144  printf("single\n");
145  break;
146  case 1:
147  printf("double\n");
148  break;
149  case 2:
150  printf("triple\n");
151  break;
152  case 3:
153  printf("RFU\n");
154  break;
155  }
156  printf("* bit frame anticollision ");
157  switch (nai.abtAtqa[1] & 0x1f) {
158  case 0x01:
159  case 0x02:
160  case 0x04:
161  case 0x08:
162  case 0x10:
163  printf("supported\n");
164  break;
165  default:
166  printf("not supported\n");
167  break;
168  }
169  }
170  printf (" UID (NFCID%c): ", (nai.abtUid[0] == 0x08 ? '3' : '1'));
171  print_hex (nai.abtUid, nai.szUidLen);
172  if (verbose) {
173  if (nai.abtUid[0] == 0x08) {
174  printf ("* Random UID\n");
175  }
176  }
177  printf (" SAK (SEL_RES): ");
178  print_hex (&nai.btSak, 1);
179  if (verbose) {
180  if (nai.btSak & SAK_UID_NOT_COMPLETE) {
181  printf ("* Warning! Cascade bit set: UID not complete\n");
182  }
183  if (nai.btSak & SAK_ISO14443_4_COMPLIANT) {
184  printf ("* Compliant with ISO/IEC 14443-4\n");
185  } else {
186  printf ("* Not compliant with ISO/IEC 14443-4\n");
187  }
188  if (nai.btSak & SAK_ISO18092_COMPLIANT) {
189  printf ("* Compliant with ISO/IEC 18092\n");
190  } else {
191  printf ("* Not compliant with ISO/IEC 18092\n");
192  }
193  }
194  if (nai.szAtsLen) {
195  printf (" ATS: ");
196  print_hex (nai.abtAts, nai.szAtsLen);
197  }
198  if (nai.szAtsLen && verbose) {
199  // Decode ATS according to ISO/IEC 14443-4 (5.2 Answer to select)
200  const int iMaxFrameSizes[] = { 16, 24, 32, 40, 48, 64, 96, 128, 256 };
201  printf ("* Max Frame Size accepted by PICC: %d bytes\n", iMaxFrameSizes[nai.abtAts[0] & 0x0F]);
202 
203  size_t offset = 1;
204  if (nai.abtAts[0] & 0x10) { // TA(1) present
205  byte_t TA = nai.abtAts[offset];
206  offset++;
207  printf ("* Bit Rate Capability:\n");
208  if (TA == 0) {
209  printf (" * PICC supports only 106 kbits/s in both directions\n");
210  }
211  if (TA & 1<<7) {
212  printf (" * Same bitrate in both directions mandatory\n");
213  }
214  if (TA & 1<<4) {
215  printf (" * PICC to PCD, DS=2, bitrate 212 kbits/s supported\n");
216  }
217  if (TA & 1<<5) {
218  printf (" * PICC to PCD, DS=4, bitrate 424 kbits/s supported\n");
219  }
220  if (TA & 1<<6) {
221  printf (" * PICC to PCD, DS=8, bitrate 847 kbits/s supported\n");
222  }
223  if (TA & 1<<0) {
224  printf (" * PCD to PICC, DR=2, bitrate 212 kbits/s supported\n");
225  }
226  if (TA & 1<<1) {
227  printf (" * PCD to PICC, DR=4, bitrate 424 kbits/s supported\n");
228  }
229  if (TA & 1<<2) {
230  printf (" * PCD to PICC, DR=8, bitrate 847 kbits/s supported\n");
231  }
232  if (TA & 1<<3) {
233  printf (" * ERROR unknown value\n");
234  }
235  }
236  if (nai.abtAts[0] & 0x20) { // TB(1) present
237  byte_t TB= nai.abtAts[offset];
238  offset++;
239  printf ("* Frame Waiting Time: %.4g ms\n",256.0*16.0*(1<<((TB & 0xf0) >> 4))/13560.0);
240  if ((TB & 0x0f) == 0) {
241  printf ("* No Start-up Frame Guard Time required\n");
242  } else {
243  printf ("* Start-up Frame Guard Time: %.4g ms\n",256.0*16.0*(1<<(TB & 0x0f))/13560.0);
244  }
245  }
246  if (nai.abtAts[0] & 0x40) { // TC(1) present
247  byte_t TC = nai.abtAts[offset];
248  offset++;
249  if (TC & 0x1) {
250  printf("* Node ADdress supported\n");
251  } else {
252  printf("* Node ADdress not supported\n");
253  }
254  if (TC & 0x2) {
255  printf("* Card IDentifier supported\n");
256  } else {
257  printf("* Card IDentifier not supported\n");
258  }
259  }
260  if (nai.szAtsLen > offset) {
261  printf ("* Historical bytes Tk: " );
262  print_hex (nai.abtAts + offset, (nai.szAtsLen - offset));
263  byte_t CIB = nai.abtAts[offset];
264  offset++;
265  if (CIB != 0x00 && CIB != 0x10 && (CIB & 0xf0) != 0x80) {
266  printf(" * Proprietary format\n");
267  if (CIB == 0xc1) {
268  printf(" * Tag byte: Mifare or virtual cards of various types\n");
269  byte_t L = nai.abtAts[offset];
270  offset++;
271  if (L != (nai.szAtsLen - offset)) {
272  printf(" * Warning: Type Identification Coding length (%i)", L);
273  printf(" not matching Tk length (%zi)\n", (nai.szAtsLen - offset));
274  }
275  if ((nai.szAtsLen - offset - 2) > 0) { // Omit 2 CRC bytes
276  byte_t CTC = nai.abtAts[offset];
277  offset++;
278  printf(" * Chip Type: ");
279  switch (CTC & 0xf0) {
280  case 0x00:
281  printf("(Multiple) Virtual Cards\n");
282  break;
283  case 0x10:
284  printf("Mifare DESFire\n");
285  break;
286  case 0x20:
287  printf("Mifare Plus\n");
288  break;
289  default:
290  printf("RFU\n");
291  break;
292  }
293  printf(" * Memory size: ");
294  switch (CTC & 0x0f) {
295  case 0x00:
296  printf("<1 kbyte\n");
297  break;
298  case 0x01:
299  printf("1 kbyte\n");
300  break;
301  case 0x02:
302  printf("2 kbyte\n");
303  break;
304  case 0x03:
305  printf("4 kbyte\n");
306  break;
307  case 0x04:
308  printf("8 kbyte\n");
309  break;
310  case 0x0f:
311  printf("Unspecified\n");
312  break;
313  default:
314  printf("RFU\n");
315  break;
316  }
317  }
318  if ((nai.szAtsLen - offset) > 0) { // Omit 2 CRC bytes
319  byte_t CVC = nai.abtAts[offset];
320  offset++;
321  printf(" * Chip Status: ");
322  switch (CVC & 0xf0) {
323  case 0x00:
324  printf("Engineering sample\n");
325  break;
326  case 0x20:
327  printf("Released\n");
328  break;
329  default:
330  printf("RFU\n");
331  break;
332  }
333  printf(" * Chip Generation: ");
334  switch (CVC & 0x0f) {
335  case 0x00:
336  printf("Generation 1\n");
337  break;
338  case 0x01:
339  printf("Generation 2\n");
340  break;
341  case 0x02:
342  printf("Generation 3\n");
343  break;
344  case 0x0f:
345  printf("Unspecified\n");
346  break;
347  default:
348  printf("RFU\n");
349  break;
350  }
351  }
352  if ((nai.szAtsLen - offset) > 0) { // Omit 2 CRC bytes
353  byte_t VCS = nai.abtAts[offset];
354  offset++;
355  printf(" * Specifics (Virtual Card Selection):\n");
356  if ((VCS & 0x09) == 0x00) {
357  printf(" * Only VCSL supported\n");
358  } else if ((VCS & 0x09) == 0x01) {
359  printf(" * VCS, VCSL and SVC supported\n");
360  }
361  if ((VCS & 0x0e) == 0x00) {
362  printf(" * SL1, SL2(?), SL3 supported\n");
363  } else if ((VCS & 0x0e) == 0x02) {
364  printf(" * SL3 only card\n");
365  } else if ((VCS & 0x0f) == 0x0e) {
366  printf(" * No VCS command supported\n");
367  } else if ((VCS & 0x0f) == 0x0f) {
368  printf(" * Unspecified\n");
369  } else {
370  printf(" * RFU\n");
371  }
372  }
373  }
374  } else {
375  if (CIB == 0x00) {
376  printf(" * Tk after 0x00 consist of optional consecutive COMPACT-TLV data objects\n");
377  printf(" followed by a mandatory status indicator (the last three bytes, not in TLV)\n");
378  printf(" See ISO/IEC 7816-4 8.1.1.3 for more info\n");
379  }
380  if (CIB == 0x10) {
381  printf(" * DIR data reference: %02x\n", nai.abtAts[offset]);
382  }
383  if (CIB == 0x80) {
384  if (nai.szAtsLen == offset) {
385  printf(" * No COMPACT-TLV objects found, no status found\n");
386  } else {
387  printf(" * Tk after 0x80 consist of optional consecutive COMPACT-TLV data objects;\n");
388  printf(" the last data object may carry a status indicator of one, two or three bytes.\n");
389  printf(" See ISO/IEC 7816-4 8.1.1.3 for more info\n");
390  }
391  }
392  }
393  }
394  }
395  if (verbose) {
396  printf("Fingerprinting based on ATQA & SAK values:\n");
397  uint32_t atqasak = 0;
398  atqasak += (((uint32_t)nai.abtAtqa[0] & 0xff)<<16);
399  atqasak += (((uint32_t)nai.abtAtqa[1] & 0xff)<<8);
400  atqasak += ((uint32_t)nai.btSak & 0xff);
401  bool found_possible_match = false;
402  switch (atqasak) {
403  case 0x000218:
404  printf("* Mifare Classic 4K\n");
405  found_possible_match = true;
406  break;
407  case 0x000408:
408  printf("* Mifare Classic 1K\n");
409  printf("* Mifare Plus (4-byte UID) 2K SL1\n");
410  found_possible_match = true;
411  break;
412  case 0x000409:
413  printf("* Mifare MINI\n");
414  found_possible_match = true;
415  break;
416  case 0x000410:
417  printf("* Mifare Plus (4-byte UID) 2K SL2\n");
418  found_possible_match = true;
419  break;
420  case 0x000411:
421  printf("* Mifare Plus (4-byte UID) 4K SL2\n");
422  found_possible_match = true;
423  break;
424  case 0x000418:
425  printf("* Mifare Plus (4-byte UID) 4K SL1\n");
426  found_possible_match = true;
427  break;
428  case 0x000420:
429  printf("* Mifare Plus (4-byte UID) 2K/4K SL3\n");
430  found_possible_match = true;
431  break;
432  case 0x004400:
433  printf("* Mifare Ultralight\n");
434  printf("* Mifare UltralightC\n");
435  found_possible_match = true;
436  break;
437  case 0x004208:
438  case 0x004408:
439  printf("* Mifare Plus (7-byte UID) 2K SL1\n");
440  found_possible_match = true;
441  break;
442  case 0x004218:
443  case 0x004418:
444  printf("* Mifare Plus (7-byte UID) 4K SL1\n");
445  found_possible_match = true;
446  break;
447  case 0x004210:
448  case 0x004410:
449  printf("* Mifare Plus (7-byte UID) 2K SL2\n");
450  found_possible_match = true;
451  break;
452  case 0x004211:
453  case 0x004411:
454  printf("* Mifare Plus (7-byte UID) 4K SL2\n");
455  found_possible_match = true;
456  break;
457  case 0x004220:
458  case 0x004420:
459  printf("* Mifare Plus (7-byte UID) 2K/4K SL3\n");
460  found_possible_match = true;
461  break;
462  case 0x034420:
463  printf("* Mifare DESFire / Desfire EV1\n");
464  found_possible_match = true;
465  break;
466  }
467 
468  // Other matches not described in
469  // AN MIFARE Type Identification Procedure
470  // but seen in the field:
471  switch (atqasak) {
472  case 0x000488:
473  printf("* Mifare Classic 1K Infineon\n");
474  found_possible_match = true;
475  break;
476  case 0x000298:
477  printf("* Gemplus MPCOS\n");
478  found_possible_match = true;
479  break;
480  case 0x030428:
481  printf("* JCOP31\n");
482  found_possible_match = true;
483  break;
484  case 0x004820:
485  printf("* JCOP31 v2.4.1\n");
486  printf("* JCOP31 v2.2\n");
487  found_possible_match = true;
488  break;
489  case 0x000428:
490  printf("* JCOP31 v2.3.1\n");
491  found_possible_match = true;
492  break;
493  case 0x000453:
494  printf("* Fudan FM1208SH01\n");
495  found_possible_match = true;
496  break;
497  case 0x000820:
498  printf("* Fudan FM1208\n");
499  found_possible_match = true;
500  break;
501  case 0x000238:
502  printf("* MFC 4K emulated by Nokia 6212 Classic\n");
503  found_possible_match = true;
504  break;
505  case 0x000838:
506  printf("* MFC 4K emulated by Nokia 6131 NFC\n");
507  found_possible_match = true;
508  break;
509  }
510  if ((nai.abtAtqa[0] & 0xf0) == 0) {
511  switch (nai.abtAtqa[1]) {
512  case 0x02:
513  printf("* SmartMX with Mifare 4K emulation\n");
514  found_possible_match = true;
515  break;
516  case 0x04:
517  printf("* SmartMX with Mifare 1K emulation\n");
518  found_possible_match = true;
519  break;
520  case 0x48:
521  printf("* SmartMX with 7-byte UID\n");
522  found_possible_match = true;
523  break;
524  }
525  }
526  if (! found_possible_match) {
527  printf("* Unknown card, sorry\n");
528  }
529  }
530 }
531 
532 void
533 print_nfc_felica_info (const nfc_felica_info_t nfi, bool verbose)
534 {
535  printf (" ID (NFCID2): ");
536  print_hex (nfi.abtId, 8);
537  printf (" Parameter (PAD): ");
538  print_hex (nfi.abtPad, 8);
539 }
540 
541 void
542 print_nfc_jewel_info (const nfc_jewel_info_t nji, bool verbose)
543 {
544  printf (" ATQA (SENS_RES): ");
545  print_hex (nji.btSensRes, 2);
546  printf (" 4-LSB JEWELID: ");
547  print_hex (nji.btId, 4);
548 }
549 
550 #define PI_ISO14443_4_SUPPORTED 0x01
551 #define PI_NAD_SUPPORTED 0x01
552 #define PI_CID_SUPPORTED 0x02
553 void
554 print_nfc_iso14443b_info (const nfc_iso14443b_info_t nbi, bool verbose)
555 {
556  const int iMaxFrameSizes[] = { 16, 24, 32, 40, 48, 64, 96, 128, 256 };
557  printf (" PUPI: ");
558  print_hex (nbi.abtPupi, 4);
559  printf (" Application Data: ");
560  print_hex (nbi.abtApplicationData, 4);
561  printf (" Protocol Info: ");
562  print_hex (nbi.abtProtocolInfo, 3);
563  if (verbose) {
564  printf ("* Bit Rate Capability:\n");
565  if (nbi.abtProtocolInfo[0] == 0) {
566  printf (" * PICC supports only 106 kbits/s in both directions\n");
567  }
568  if (nbi.abtProtocolInfo[0] & 1<<7) {
569  printf (" * Same bitrate in both directions mandatory\n");
570  }
571  if (nbi.abtProtocolInfo[0] & 1<<4) {
572  printf (" * PICC to PCD, 1etu=64/fc, bitrate 212 kbits/s supported\n");
573  }
574  if (nbi.abtProtocolInfo[0] & 1<<5) {
575  printf (" * PICC to PCD, 1etu=32/fc, bitrate 424 kbits/s supported\n");
576  }
577  if (nbi.abtProtocolInfo[0] & 1<<6) {
578  printf (" * PICC to PCD, 1etu=16/fc, bitrate 847 kbits/s supported\n");
579  }
580  if (nbi.abtProtocolInfo[0] & 1<<0) {
581  printf (" * PCD to PICC, 1etu=64/fc, bitrate 212 kbits/s supported\n");
582  }
583  if (nbi.abtProtocolInfo[0] & 1<<1) {
584  printf (" * PCD to PICC, 1etu=32/fc, bitrate 424 kbits/s supported\n");
585  }
586  if (nbi.abtProtocolInfo[0] & 1<<2) {
587  printf (" * PCD to PICC, 1etu=16/fc, bitrate 847 kbits/s supported\n");
588  }
589  if (nbi.abtProtocolInfo[0] & 1<<3) {
590  printf (" * ERROR unknown value\n");
591  }
592  if( (nbi.abtProtocolInfo[1] & 0xf0) <= 0x80 ) {
593  printf ("* Maximum frame sizes: %d bytes\n", iMaxFrameSizes[((nbi.abtProtocolInfo[1] & 0xf0) >> 4)]);
594  }
595  if((nbi.abtProtocolInfo[1] & 0x0f) == PI_ISO14443_4_SUPPORTED) {
596  printf ("* Protocol types supported: ISO/IEC 14443-4\n");
597  }
598  printf ("* Frame Waiting Time: %.4g ms\n",256.0*16.0*(1<<((nbi.abtProtocolInfo[2] & 0xf0) >> 4))/13560.0);
599  if((nbi.abtProtocolInfo[2] & (PI_NAD_SUPPORTED|PI_CID_SUPPORTED)) != 0) {
600  printf ("* Frame options supported: ");
601  if ((nbi.abtProtocolInfo[2] & PI_NAD_SUPPORTED) != 0) printf ("NAD ");
602  if ((nbi.abtProtocolInfo[2] & PI_CID_SUPPORTED) != 0) printf ("CID ");
603  printf("\n");
604  }
605  }
606 }
607 
608 void
609 print_nfc_dep_info (const nfc_dep_info_t ndi, bool verbose)
610 {
611  printf (" NFCID3: ");
612  print_hex (ndi.abtNFCID3, 10);
613  printf (" BS: %02x\n", ndi.btBS);
614  printf (" BR: %02x\n", ndi.btBR);
615  printf (" TO: %02x\n", ndi.btTO);
616  printf (" PP: %02x\n", ndi.btPP);
617  if (ndi.szGB) {
618  printf ("General Bytes: ");
619  print_hex (ndi.abtGB, ndi.szGB);
620  }
621 }
622 
628 parse_args (int argc, const char *argv[], size_t * szFound, bool * verbose)
629 {
630  nfc_device_desc_t *pndd = 0;
631  int arg;
632  *szFound = 0;
633 
634  // Get commandline options
635  for (arg = 1; arg < argc; arg++) {
636 
637  if (0 == strcmp (argv[arg], "--device")) {
638  // FIXME: this device selection by command line options is terrible & does not support USB/PCSC drivers
639  if (argc > arg + 1) {
640  char buffer[256];
641 
642  pndd = malloc (sizeof (nfc_device_desc_t));
643 
644  strncpy (buffer, argv[++arg], 256);
645 
646  // Driver.
647  pndd->pcDriver = (char *) malloc (256);
648  strcpy (pndd->pcDriver, strtok (buffer, ":"));
649 
650  // Port.
651  pndd->pcPort = (char *) malloc (256);
652  strcpy (pndd->pcPort, strtok (NULL, ":"));
653 
654  // Speed.
655  sscanf (strtok (NULL, ":"), "%u", &pndd->uiSpeed);
656 
657  *szFound = 1;
658  } else {
659  errx (1, "usage: %s [--device driver:port:speed]", argv[0]);
660  }
661  }
662  if ((0 == strcmp (argv[arg], "-v")) || (0 == strcmp (argv[arg], "--verbose"))) {
663  *verbose = true;
664  }
665  }
666  return pndd;
667 }
668 
669 const char *
670 str_nfc_baud_rate (const nfc_baud_rate_t nbr)
671 {
672  switch(nbr) {
673  case NBR_UNDEFINED:
674  return "undefined baud rate";
675  break;
676  case NBR_106:
677  return "106 kbps";
678  break;
679  case NBR_212:
680  return "212 kbps";
681  break;
682  case NBR_424:
683  return "424 kbps";
684  break;
685  case NBR_847:
686  return "847 kbps";
687  break;
688  }
689  return "";
690 }
691 
692 void
693 print_nfc_target (const nfc_target_t nt, bool verbose)
694 {
695  switch(nt.nm.nmt) {
696  case NMT_ISO14443A:
697  printf ("ISO/IEC 14443A (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
698  print_nfc_iso14443a_info (nt.nti.nai, verbose);
699  break;
700  case NMT_JEWEL:
701  printf ("Innovision Jewel (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
702  print_nfc_jewel_info (nt.nti.nji, verbose);
703  break;
704  case NMT_FELICA:
705  printf ("FeliCa (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
706  print_nfc_felica_info (nt.nti.nfi, verbose);
707  break;
708  case NMT_ISO14443B:
709  printf ("ISO/IEC 14443-4B (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
710  print_nfc_iso14443b_info (nt.nti.nbi, verbose);
711  break;
712  case NMT_DEP:
713  printf ("D.E.P. (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
714  print_nfc_dep_info (nt.nti.ndi, verbose);
715  break;
716  }
717 }
718