libnfc 1.4.2

nfc-utils.c

00001 /*-
00002  * Public platform independent Near Field Communication (NFC) library examples
00003  * 
00004  * Copyright (C) 2009, Roel Verdult
00005  * Copyright (C) 2010, Romuald Conty, Romain Tartière
00006  * 
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions are met:
00009  *  1) Redistributions of source code must retain the above copyright notice,
00010  *  this list of conditions and the following disclaimer. 
00011  *  2 )Redistributions in binary form must reproduce the above copyright
00012  *  notice, this list of conditions and the following disclaimer in the
00013  *  documentation and/or other materials provided with the distribution.
00014  *
00015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00025  * POSSIBILITY OF SUCH DAMAGE.
00026  * 
00027  * Note that this license only applies on the examples, NFC library itself is under LGPL
00028  *
00029  */
00030 
00031 #include <nfc/nfc.h>
00032 #include <err.h>
00033 
00034 #include "nfc-utils.h"
00035 
00036 static const byte_t OddParity[256] = {
00037   1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
00038   0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
00039   0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
00040   1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
00041   0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
00042   1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
00043   1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
00044   0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
00045   0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
00046   1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
00047   1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
00048   0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
00049   1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
00050   0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
00051   0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
00052   1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
00053 };
00054 
00055 byte_t
00056 oddparity (const byte_t bt)
00057 {
00058   return OddParity[bt];
00059 }
00060 
00061 void
00062 oddparity_bytes_ts (const byte_t * pbtData, const size_t szLen, byte_t * pbtPar)
00063 {
00064   size_t  szByteNr;
00065   // Calculate the parity bits for the command
00066   for (szByteNr = 0; szByteNr < szLen; szByteNr++) {
00067     pbtPar[szByteNr] = OddParity[pbtData[szByteNr]];
00068   }
00069 }
00070 
00071 void
00072 print_hex (const byte_t * pbtData, const size_t szBytes)
00073 {
00074   size_t  szPos;
00075 
00076   for (szPos = 0; szPos < szBytes; szPos++) {
00077     printf ("%02x  ", pbtData[szPos]);
00078   }
00079   printf ("\n");
00080 }
00081 
00082 void
00083 print_hex_bits (const byte_t * pbtData, const size_t szBits)
00084 {
00085   uint8_t uRemainder;
00086   size_t  szPos;
00087   size_t  szBytes = szBits / 8;
00088 
00089   for (szPos = 0; szPos < szBytes; szPos++) {
00090     printf ("%02x  ", pbtData[szPos]);
00091   }
00092 
00093   uRemainder = szBits % 8;
00094   // Print the rest bits
00095   if (uRemainder != 0) {
00096     if (uRemainder < 5)
00097       printf ("%01x (%d bits)", pbtData[szBytes], uRemainder);
00098     else
00099       printf ("%02x (%d bits)", pbtData[szBytes], uRemainder);
00100   }
00101   printf ("\n");
00102 }
00103 
00104 void
00105 print_hex_par (const byte_t * pbtData, const size_t szBits, const byte_t * pbtDataPar)
00106 {
00107   uint8_t uRemainder;
00108   size_t  szPos;
00109   size_t  szBytes = szBits / 8;
00110 
00111   for (szPos = 0; szPos < szBytes; szPos++) {
00112     printf ("%02x", pbtData[szPos]);
00113     if (OddParity[pbtData[szPos]] != pbtDataPar[szPos]) {
00114       printf ("! ");
00115     } else {
00116       printf ("  ");
00117     }
00118   }
00119 
00120   uRemainder = szBits % 8;
00121   // Print the rest bits, these cannot have parity bit
00122   if (uRemainder != 0) {
00123     if (uRemainder < 5)
00124       printf ("%01x (%d bits)", pbtData[szBytes], uRemainder);
00125     else
00126       printf ("%02x (%d bits)", pbtData[szBytes], uRemainder);
00127   }
00128   printf ("\n");
00129 }
00130 
00131 #define SAK_UID_NOT_COMPLETE     0x04
00132 #define SAK_ISO14443_4_COMPLIANT 0x20
00133 #define SAK_ISO18092_COMPLIANT   0x40
00134 
00135 void
00136 print_nfc_iso14443a_info (const nfc_iso14443a_info_t nai, bool verbose)
00137 {
00138   printf ("    ATQA (SENS_RES): ");
00139   print_hex (nai.abtAtqa, 2);
00140   if (verbose) {
00141     printf("* UID size: ");
00142     switch ((nai.abtAtqa[1] & 0xc0)>>6) {
00143       case 0:
00144         printf("single\n");
00145       break;
00146       case 1:
00147         printf("double\n");
00148       break;
00149       case 2:
00150         printf("triple\n");
00151       break;
00152       case 3:
00153         printf("RFU\n");
00154       break;
00155     }
00156     printf("* bit frame anticollision ");
00157     switch (nai.abtAtqa[1] & 0x1f) {
00158       case 0x01:
00159       case 0x02:
00160       case 0x04:
00161       case 0x08:
00162       case 0x10:
00163         printf("supported\n");
00164       break;
00165       default:
00166         printf("not supported\n");
00167       break;
00168     }
00169   }
00170   printf ("       UID (NFCID%c): ", (nai.abtUid[0] == 0x08 ? '3' : '1'));
00171   print_hex (nai.abtUid, nai.szUidLen);
00172   if (verbose) {
00173     if (nai.abtUid[0] == 0x08) {
00174       printf ("* Random UID\n");
00175     }
00176   }
00177   printf ("      SAK (SEL_RES): ");
00178   print_hex (&nai.btSak, 1);
00179   if (verbose) {
00180     if (nai.btSak & SAK_UID_NOT_COMPLETE) {
00181       printf ("* Warning! Cascade bit set: UID not complete\n");
00182     }
00183     if (nai.btSak & SAK_ISO14443_4_COMPLIANT) {
00184       printf ("* Compliant with ISO/IEC 14443-4\n");
00185     } else {
00186       printf ("* Not compliant with ISO/IEC 14443-4\n");
00187     }
00188     if (nai.btSak & SAK_ISO18092_COMPLIANT) {
00189       printf ("* Compliant with ISO/IEC 18092\n");
00190     } else {
00191       printf ("* Not compliant with ISO/IEC 18092\n");
00192     }
00193   }
00194   if (nai.szAtsLen) {
00195     printf ("                ATS: ");
00196     print_hex (nai.abtAts, nai.szAtsLen);
00197   }
00198   if (nai.szAtsLen && verbose) {
00199     // Decode ATS according to ISO/IEC 14443-4 (5.2 Answer to select)
00200     const int iMaxFrameSizes[] = { 16, 24, 32, 40, 48, 64, 96, 128, 256 };
00201     printf ("* Max Frame Size accepted by PICC: %d bytes\n", iMaxFrameSizes[nai.abtAts[0] & 0x0F]);
00202 
00203     size_t offset = 1;
00204     if (nai.abtAts[0] & 0x10) { // TA(1) present
00205       byte_t TA = nai.abtAts[offset];
00206       offset++;
00207       printf ("* Bit Rate Capability:\n");
00208       if (TA == 0) {
00209         printf ("  * PICC supports only 106 kbits/s in both directions\n");
00210       }
00211       if (TA & 1<<7) {
00212         printf ("  * Same bitrate in both directions mandatory\n");
00213       }
00214       if (TA & 1<<4) {
00215         printf ("  * PICC to PCD, DS=2, bitrate 212 kbits/s supported\n");
00216       }
00217       if (TA & 1<<5) {
00218         printf ("  * PICC to PCD, DS=4, bitrate 424 kbits/s supported\n");
00219       }
00220       if (TA & 1<<6) {
00221         printf ("  * PICC to PCD, DS=8, bitrate 847 kbits/s supported\n");
00222       }
00223       if (TA & 1<<0) {
00224         printf ("  * PCD to PICC, DR=2, bitrate 212 kbits/s supported\n");
00225       }
00226       if (TA & 1<<1) {
00227         printf ("  * PCD to PICC, DR=4, bitrate 424 kbits/s supported\n");
00228       }
00229       if (TA & 1<<2) {
00230         printf ("  * PCD to PICC, DR=8, bitrate 847 kbits/s supported\n");
00231       }
00232       if (TA & 1<<3) {
00233         printf ("  * ERROR unknown value\n");
00234       }
00235     }
00236     if (nai.abtAts[0] & 0x20) { // TB(1) present
00237       byte_t TB= nai.abtAts[offset];
00238       offset++;
00239       printf ("* Frame Waiting Time: %.4g ms\n",256.0*16.0*(1<<((TB & 0xf0) >> 4))/13560.0);
00240       if ((TB & 0x0f) == 0) {
00241         printf ("* No Start-up Frame Guard Time required\n");
00242       } else {
00243         printf ("* Start-up Frame Guard Time: %.4g ms\n",256.0*16.0*(1<<(TB & 0x0f))/13560.0);
00244       }
00245     }
00246     if (nai.abtAts[0] & 0x40) { // TC(1) present
00247       byte_t TC = nai.abtAts[offset];
00248       offset++;
00249       if (TC & 0x1) {
00250         printf("* Node ADdress supported\n");
00251       } else {
00252         printf("* Node ADdress not supported\n");
00253       }
00254       if (TC & 0x2) {
00255         printf("* Card IDentifier supported\n");
00256       } else {
00257         printf("* Card IDentifier not supported\n");
00258       }
00259     }
00260     if (nai.szAtsLen > offset) {
00261       printf ("* Historical bytes Tk: " );
00262       print_hex (nai.abtAts + offset, (nai.szAtsLen - offset));
00263       byte_t CIB = nai.abtAts[offset];
00264       offset++;
00265       if (CIB != 0x00 && CIB != 0x10 && (CIB & 0xf0) != 0x80) {
00266         printf("  * Proprietary format\n");
00267         if (CIB == 0xc1) {
00268           printf("    * Tag byte: Mifare or virtual cards of various types\n");
00269           byte_t L = nai.abtAts[offset];
00270           offset++;
00271           if (L != (nai.szAtsLen - offset)) {
00272             printf("    * Warning: Type Identification Coding length (%i)", L);
00273             printf(" not matching Tk length (%zi)\n", (nai.szAtsLen - offset));
00274           }
00275           if ((nai.szAtsLen - offset - 2) > 0) { // Omit 2 CRC bytes
00276             byte_t CTC = nai.abtAts[offset];
00277             offset++;
00278             printf("    * Chip Type: ");
00279             switch (CTC & 0xf0) {
00280               case 0x00:
00281                 printf("(Multiple) Virtual Cards\n");
00282               break;
00283               case 0x10:
00284                 printf("Mifare DESFire\n");
00285               break;
00286               case 0x20:
00287                 printf("Mifare Plus\n");
00288               break;
00289               default:
00290                 printf("RFU\n");
00291               break;
00292             }
00293             printf("    * Memory size: ");
00294             switch (CTC & 0x0f) {
00295               case 0x00:
00296                 printf("<1 kbyte\n");
00297               break;
00298               case 0x01:
00299                 printf("1 kbyte\n");
00300               break;
00301               case 0x02:
00302                 printf("2 kbyte\n");
00303               break;
00304               case 0x03:
00305                 printf("4 kbyte\n");
00306               break;
00307               case 0x04:
00308                 printf("8 kbyte\n");
00309               break;
00310               case 0x0f:
00311                 printf("Unspecified\n");
00312               break;
00313               default:
00314                 printf("RFU\n");
00315               break;
00316             }
00317           }
00318           if ((nai.szAtsLen - offset) > 0) { // Omit 2 CRC bytes
00319             byte_t CVC = nai.abtAts[offset];
00320             offset++;
00321             printf("    * Chip Status: ");
00322             switch (CVC & 0xf0) {
00323               case 0x00:
00324                 printf("Engineering sample\n");
00325               break;
00326               case 0x20:
00327                 printf("Released\n");
00328               break;
00329               default:
00330                 printf("RFU\n");
00331               break;
00332             }
00333             printf("    * Chip Generation: ");
00334             switch (CVC & 0x0f) {
00335               case 0x00:
00336                 printf("Generation 1\n");
00337               break;
00338               case 0x01:
00339                 printf("Generation 2\n");
00340               break;
00341               case 0x02:
00342                 printf("Generation 3\n");
00343               break;
00344               case 0x0f:
00345                 printf("Unspecified\n");
00346               break;
00347               default:
00348                 printf("RFU\n");
00349               break;
00350             }
00351           }
00352           if ((nai.szAtsLen - offset) > 0) { // Omit 2 CRC bytes
00353             byte_t VCS = nai.abtAts[offset];
00354             offset++;
00355             printf("    * Specifics (Virtual Card Selection):\n");
00356             if ((VCS & 0x09) == 0x00) {
00357               printf("      * Only VCSL supported\n");
00358             } else if ((VCS & 0x09) == 0x01) {
00359               printf("      * VCS, VCSL and SVC supported\n");
00360             }
00361             if ((VCS & 0x0e) == 0x00) {
00362               printf("      * SL1, SL2(?), SL3 supported\n");
00363             } else if ((VCS & 0x0e) == 0x02) {
00364               printf("      * SL3 only card\n");
00365             } else if ((VCS & 0x0f) == 0x0e) {
00366               printf("      * No VCS command supported\n");
00367             } else if ((VCS & 0x0f) == 0x0f) {
00368               printf("      * Unspecified\n");
00369             } else {
00370               printf("      * RFU\n");
00371             }
00372           }
00373         }
00374       } else {
00375         if (CIB == 0x00) {
00376           printf("  * Tk after 0x00 consist of optional consecutive COMPACT-TLV data objects\n");
00377           printf("    followed by a mandatory status indicator (the last three bytes, not in TLV)\n");
00378           printf("    See ISO/IEC 7816-4 8.1.1.3 for more info\n");
00379         }
00380         if (CIB == 0x10) {
00381           printf("  * DIR data reference: %02x\n", nai.abtAts[offset]);
00382         }
00383         if (CIB == 0x80) {
00384           if (nai.szAtsLen == offset) {
00385             printf("  * No COMPACT-TLV objects found, no status found\n");
00386           } else {
00387             printf("  * Tk after 0x80 consist of optional consecutive COMPACT-TLV data objects;\n");
00388             printf("    the last data object may carry a status indicator of one, two or three bytes.\n");
00389             printf("    See ISO/IEC 7816-4 8.1.1.3 for more info\n");
00390           }
00391         }
00392       }
00393     }
00394   }
00395   if (verbose) {
00396     printf("Fingerprinting based on ATQA & SAK values:\n");
00397     uint32_t atqasak = 0;
00398     atqasak += (((uint32_t)nai.abtAtqa[0] & 0xff)<<16);
00399     atqasak += (((uint32_t)nai.abtAtqa[1] & 0xff)<<8);
00400     atqasak += ((uint32_t)nai.btSak & 0xff);
00401     bool found_possible_match = false;
00402     switch (atqasak) {
00403       case 0x000218:
00404         printf("* Mifare Classic 4K\n");
00405         found_possible_match = true;
00406       break;
00407       case 0x000408:
00408         printf("* Mifare Classic 1K\n");
00409         printf("* Mifare Plus (4-byte UID) 2K SL1\n");
00410         found_possible_match = true;
00411       break;
00412       case 0x000409:
00413         printf("* Mifare MINI\n");
00414         found_possible_match = true;
00415       break;
00416       case 0x000410:
00417         printf("* Mifare Plus (4-byte UID) 2K SL2\n");
00418         found_possible_match = true;
00419       break;
00420       case 0x000411:
00421         printf("* Mifare Plus (4-byte UID) 4K SL2\n");
00422         found_possible_match = true;
00423       break;
00424       case 0x000418:
00425         printf("* Mifare Plus (4-byte UID) 4K SL1\n");
00426         found_possible_match = true;
00427       break;
00428       case 0x000420:
00429         printf("* Mifare Plus (4-byte UID) 2K/4K SL3\n");
00430         found_possible_match = true;
00431       break;
00432       case 0x004400:
00433         printf("* Mifare Ultralight\n");
00434         printf("* Mifare UltralightC\n");
00435         found_possible_match = true;
00436       break;
00437       case 0x004208:
00438       case 0x004408:
00439         printf("* Mifare Plus (7-byte UID) 2K SL1\n");
00440         found_possible_match = true;
00441       break;
00442       case 0x004218:
00443       case 0x004418:
00444         printf("* Mifare Plus (7-byte UID) 4K SL1\n");
00445         found_possible_match = true;
00446       break;
00447       case 0x004210:
00448       case 0x004410:
00449         printf("* Mifare Plus (7-byte UID) 2K SL2\n");
00450         found_possible_match = true;
00451       break;
00452       case 0x004211:
00453       case 0x004411:
00454         printf("* Mifare Plus (7-byte UID) 4K SL2\n");
00455         found_possible_match = true;
00456       break;
00457       case 0x004220:
00458       case 0x004420:
00459         printf("* Mifare Plus (7-byte UID) 2K/4K SL3\n");
00460         found_possible_match = true;
00461       break;
00462       case 0x034420:
00463         printf("* Mifare DESFire / Desfire EV1\n");
00464         found_possible_match = true;
00465       break;
00466     }
00467 
00468     // Other matches not described in
00469     // AN MIFARE Type Identification Procedure
00470     // but seen in the field:
00471     switch (atqasak) {
00472       case 0x000488:
00473         printf("* Mifare Classic 1K Infineon\n");
00474         found_possible_match = true;
00475       break;
00476       case 0x000298:
00477         printf("* Gemplus MPCOS\n");
00478         found_possible_match = true;
00479       break;
00480       case 0x030428:
00481         printf("* JCOP31\n");
00482         found_possible_match = true;
00483       break;
00484       case 0x004820:
00485         printf("* JCOP31 v2.4.1\n");
00486         printf("* JCOP31 v2.2\n");
00487         found_possible_match = true;
00488       break;
00489       case 0x000428:
00490         printf("* JCOP31 v2.3.1\n");
00491         found_possible_match = true;
00492       break;
00493       case 0x000453:
00494         printf("* Fudan FM1208SH01\n");
00495         found_possible_match = true;
00496       break;
00497       case 0x000820:
00498         printf("* Fudan FM1208\n");
00499         found_possible_match = true;
00500       break;
00501       case 0x000238:
00502         printf("* MFC 4K emulated by Nokia 6212 Classic\n");
00503         found_possible_match = true;
00504       break;
00505       case 0x000838:
00506         printf("* MFC 4K emulated by Nokia 6131 NFC\n");
00507         found_possible_match = true;
00508       break;
00509     }
00510     if ((nai.abtAtqa[0] & 0xf0) == 0) {
00511       switch (nai.abtAtqa[1]) {
00512         case 0x02:
00513           printf("* SmartMX with Mifare 4K emulation\n");
00514           found_possible_match = true;
00515         break;
00516         case 0x04:
00517           printf("* SmartMX with Mifare 1K emulation\n");
00518           found_possible_match = true;
00519         break;
00520         case 0x48:
00521           printf("* SmartMX with 7-byte UID\n");
00522           found_possible_match = true;
00523         break;
00524       }
00525     }
00526     if (! found_possible_match) {
00527       printf("* Unknown card, sorry\n");
00528     }
00529   }
00530 }
00531 
00532 void
00533 print_nfc_felica_info (const nfc_felica_info_t nfi, bool verbose)
00534 {
00535   printf ("        ID (NFCID2): ");
00536   print_hex (nfi.abtId, 8);
00537   printf ("    Parameter (PAD): ");
00538   print_hex (nfi.abtPad, 8);
00539 }
00540 
00541 void
00542 print_nfc_jewel_info (const nfc_jewel_info_t nji, bool verbose)
00543 {
00544   printf ("    ATQA (SENS_RES): ");
00545   print_hex (nji.btSensRes, 2);
00546   printf ("      4-LSB JEWELID: ");
00547   print_hex (nji.btId, 4);
00548 }
00549 
00550 #define PI_ISO14443_4_SUPPORTED 0x01
00551 #define PI_NAD_SUPPORTED        0x01
00552 #define PI_CID_SUPPORTED        0x02
00553 void
00554 print_nfc_iso14443b_info (const nfc_iso14443b_info_t nbi, bool verbose)
00555 {
00556   const int iMaxFrameSizes[] = { 16, 24, 32, 40, 48, 64, 96, 128, 256 };
00557   printf ("               PUPI: ");
00558   print_hex (nbi.abtPupi, 4);
00559   printf ("   Application Data: ");
00560   print_hex (nbi.abtApplicationData, 4);
00561   printf ("      Protocol Info: ");
00562   print_hex (nbi.abtProtocolInfo, 3);
00563   if (verbose) {
00564     printf ("* Bit Rate Capability:\n");
00565     if (nbi.abtProtocolInfo[0] == 0) {
00566       printf (" * PICC supports only 106 kbits/s in both directions\n");
00567     }
00568     if (nbi.abtProtocolInfo[0] & 1<<7) {
00569       printf (" * Same bitrate in both directions mandatory\n");
00570     }
00571     if (nbi.abtProtocolInfo[0] & 1<<4) {
00572       printf (" * PICC to PCD, 1etu=64/fc, bitrate 212 kbits/s supported\n");
00573     }
00574     if (nbi.abtProtocolInfo[0] & 1<<5) {
00575       printf (" * PICC to PCD, 1etu=32/fc, bitrate 424 kbits/s supported\n");
00576     }
00577     if (nbi.abtProtocolInfo[0] & 1<<6) {
00578       printf (" * PICC to PCD, 1etu=16/fc, bitrate 847 kbits/s supported\n");
00579     }
00580     if (nbi.abtProtocolInfo[0] & 1<<0) {
00581       printf (" * PCD to PICC, 1etu=64/fc, bitrate 212 kbits/s supported\n");
00582     }
00583     if (nbi.abtProtocolInfo[0] & 1<<1) {
00584       printf (" * PCD to PICC, 1etu=32/fc, bitrate 424 kbits/s supported\n");
00585     }
00586     if (nbi.abtProtocolInfo[0] & 1<<2) {
00587       printf (" * PCD to PICC, 1etu=16/fc, bitrate 847 kbits/s supported\n");
00588     }
00589     if (nbi.abtProtocolInfo[0] & 1<<3) {
00590       printf (" * ERROR unknown value\n");
00591     }
00592     if( (nbi.abtProtocolInfo[1] & 0xf0) <= 0x80 ) {
00593       printf ("* Maximum frame sizes: %d bytes\n", iMaxFrameSizes[((nbi.abtProtocolInfo[1] & 0xf0) >> 4)]);
00594     }
00595     if((nbi.abtProtocolInfo[1] & 0x0f) == PI_ISO14443_4_SUPPORTED) {
00596       printf ("* Protocol types supported: ISO/IEC 14443-4\n");
00597     }
00598     printf ("* Frame Waiting Time: %.4g ms\n",256.0*16.0*(1<<((nbi.abtProtocolInfo[2] & 0xf0) >> 4))/13560.0);
00599     if((nbi.abtProtocolInfo[2] & (PI_NAD_SUPPORTED|PI_CID_SUPPORTED)) != 0) {
00600       printf ("* Frame options supported: ");
00601       if ((nbi.abtProtocolInfo[2] & PI_NAD_SUPPORTED) != 0) printf ("NAD ");
00602       if ((nbi.abtProtocolInfo[2] & PI_CID_SUPPORTED) != 0) printf ("CID ");
00603       printf("\n");
00604     }
00605   }
00606 }
00607 
00608 void
00609 print_nfc_dep_info (const nfc_dep_info_t ndi, bool verbose)
00610 {
00611   printf ("       NFCID3: ");
00612   print_hex (ndi.abtNFCID3, 10);
00613   printf ("           BS: %02x\n", ndi.btBS);
00614   printf ("           BR: %02x\n", ndi.btBR);
00615   printf ("           TO: %02x\n", ndi.btTO);
00616   printf ("           PP: %02x\n", ndi.btPP);
00617   if (ndi.szGB) {
00618     printf ("General Bytes: ");
00619     print_hex (ndi.abtGB, ndi.szGB);
00620   }
00621 }
00622 
00627 nfc_device_desc_t *
00628 parse_args (int argc, const char *argv[], size_t * szFound, bool * verbose)
00629 {
00630   nfc_device_desc_t *pndd = 0;
00631   int     arg;
00632   *szFound = 0;
00633 
00634   // Get commandline options
00635   for (arg = 1; arg < argc; arg++) {
00636 
00637     if (0 == strcmp (argv[arg], "--device")) {
00638       // FIXME: this device selection by command line options is terrible & does not support USB/PCSC drivers
00639       if (argc > arg + 1) {
00640         char    buffer[256];
00641 
00642         pndd = malloc (sizeof (nfc_device_desc_t));
00643 
00644         strncpy (buffer, argv[++arg], 256);
00645 
00646         // Driver.
00647         pndd->pcDriver = (char *) malloc (256);
00648         strcpy (pndd->pcDriver, strtok (buffer, ":"));
00649 
00650         // Port.
00651         pndd->pcPort = (char *) malloc (256);
00652         strcpy (pndd->pcPort, strtok (NULL, ":"));
00653 
00654         // Speed.
00655         sscanf (strtok (NULL, ":"), "%u", &pndd->uiSpeed);
00656 
00657         *szFound = 1;
00658       } else {
00659         errx (1, "usage: %s [--device driver:port:speed]", argv[0]);
00660       }
00661     }
00662     if ((0 == strcmp (argv[arg], "-v")) || (0 == strcmp (argv[arg], "--verbose"))) {
00663       *verbose = true;
00664     }
00665   }
00666   return pndd;
00667 }
00668 
00669 const char *
00670 str_nfc_baud_rate (const nfc_baud_rate_t nbr)
00671 {
00672   switch(nbr) {
00673     case NBR_UNDEFINED:
00674       return "undefined baud rate";
00675     break;
00676     case NBR_106:
00677       return "106 kbps";
00678     break;
00679     case NBR_212:
00680       return "212 kbps";
00681     break;
00682     case NBR_424:
00683       return "424 kbps";
00684     break;
00685     case NBR_847:
00686       return "847 kbps";
00687     break;
00688   }
00689   return "";
00690 }
00691 
00692 void
00693 print_nfc_target (const nfc_target_t nt, bool verbose)
00694 {
00695   switch(nt.nm.nmt) {
00696     case NMT_ISO14443A:
00697       printf ("ISO/IEC 14443A (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
00698       print_nfc_iso14443a_info (nt.nti.nai, verbose);
00699     break;
00700     case NMT_JEWEL:
00701       printf ("Innovision Jewel (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
00702       print_nfc_jewel_info (nt.nti.nji, verbose);
00703     break;
00704     case NMT_FELICA:
00705       printf ("FeliCa (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
00706       print_nfc_felica_info (nt.nti.nfi, verbose);
00707     break;
00708     case NMT_ISO14443B:
00709       printf ("ISO/IEC 14443-4B (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
00710       print_nfc_iso14443b_info (nt.nti.nbi, verbose);
00711     break;
00712     case NMT_DEP:
00713       printf ("D.E.P. (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
00714       print_nfc_dep_info (nt.nti.ndi, verbose);
00715     break;
00716   }
00717 }
00718