libnfc/utils/nfc-utils.c

718 lines
22 KiB
C
Raw Normal View History

/*-
* Public platform independent Near Field Communication (NFC) library examples
*
* Copyright (C) 2009, Roel Verdult
2012-09-17 15:47:43 +02:00
* Copyright (C) 2010-2011, Romain Tartière
* Copyright (C) 2009-2012, Romuald Conty
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2 )Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Note that this license only applies on the examples, NFC library itself is under LGPL
*
*/
/**
* @file nfc-utils.c
* @brief Provide some examples shared functions like print, parity calculation, options parsing.
*/
#include <nfc/nfc.h>
#include <err.h>
#include "nfc-utils.h"
struct card_atqa {
uint16_t atqa;
uint16_t mask;
char type[128];
// list of up to 8 SAK values compatible with this ATQA
int saklist[8];
};
struct card_sak {
uint8_t sak;
uint8_t mask;
char type[128];
};
struct card_atqa const_ca[] = {
{
0x0044, 0xffff, "MIFARE Ultralight",
{0, -1}
},
{
0x0044, 0xffff, "MIFARE Ultralight C",
{0, -1}
},
{
0x0004, 0xff0f, "MIFARE Mini 0.3K",
{1, -1}
},
{
0x0004, 0xff0f, "MIFARE Classic 1K",
{2, -1}
},
{
0x0002, 0xff0f, "MIFARE Classic 4K",
{3, -1}
},
{
0x0004, 0xffff, "MIFARE Plus (4 Byte UID or 4 Byte RID)",
{4, 5, 6, 7, 8, 9, -1}
},
{
0x0002, 0xffff, "MIFARE Plus (4 Byte UID or 4 Byte RID)",
{4, 5, 6, 7, 8, 9, -1}
},
{
0x0044, 0xffff, "MIFARE Plus (7 Byte UID)",
{4, 5, 6, 7, 8, 9, -1}
},
{
0x0042, 0xffff, "MIFARE Plus (7 Byte UID)",
{4, 5, 6, 7, 8, 9, -1}
},
{
0x0344, 0xffff, "MIFARE DESFire",
{10, 11, -1}
},
{
0x0044, 0xffff, "P3SR008",
{ -1}
}, // TODO we need SAK info
{
0x0004, 0xf0ff, "SmartMX with MIFARE 1K emulation",
{12, -1}
},
{
0x0002, 0xf0ff, "SmartMX with MIFARE 4K emulation",
{12, -1}
},
{
0x0048, 0xf0ff, "SmartMX with 7 Byte UID",
{12, -1}
}
};
struct card_sak const_cs[] = {
{0x00, 0xff, "" }, // 00 MIFARE Ultralight / Ultralight C
{0x09, 0xff, "" }, // 01 MIFARE Mini 0.3K
{0x08, 0xff, "" }, // 02 MIFARE Classic 1K
{0x18, 0xff, "" }, // 03 MIFARE Classik 4K
{0x08, 0xff, " 2K, Security level 1" }, // 04 MIFARE Plus
{0x18, 0xff, " 4K, Security level 1" }, // 05 MIFARE Plus
{0x10, 0xff, " 2K, Security level 2" }, // 06 MIFARE Plus
{0x11, 0xff, " 4K, Security level 2" }, // 07 MIFARE Plus
{0x20, 0xff, " 2K, Security level 3" }, // 08 MIFARE Plus
{0x20, 0xff, " 4K, Security level 3" }, // 09 MIFARE Plus
{0x20, 0xff, " 4K" }, // 10 MIFARE DESFire
{0x20, 0xff, " EV1 2K/4K/8K" }, // 11 MIFARE DESFire
{0x00, 0x00, "" }, // 12 SmartMX
};
uint8_t
oddparity(const uint8_t bt)
{
2012-05-02 12:02:56 +02:00
// cf http://graphics.stanford.edu/~seander/bithacks.html#ParityParallel
return (0x9669 >> ((bt ^(bt >> 4)) & 0xF)) & 1;
}
void
oddparity_bytes_ts(const uint8_t *pbtData, const size_t szLen, uint8_t *pbtPar)
{
size_t szByteNr;
// Calculate the parity bits for the command
for (szByteNr = 0; szByteNr < szLen; szByteNr++) {
pbtPar[szByteNr] = oddparity(pbtData[szByteNr]);
}
}
void
print_hex(const uint8_t *pbtData, const size_t szBytes)
{
size_t szPos;
for (szPos = 0; szPos < szBytes; szPos++) {
printf("%02x ", pbtData[szPos]);
}
printf("\n");
}
void
print_hex_bits(const uint8_t *pbtData, const size_t szBits)
{
uint8_t uRemainder;
size_t szPos;
size_t szBytes = szBits / 8;
for (szPos = 0; szPos < szBytes; szPos++) {
printf("%02x ", pbtData[szPos]);
}
uRemainder = szBits % 8;
// Print the rest bits
if (uRemainder != 0) {
if (uRemainder < 5)
printf("%01x (%d bits)", pbtData[szBytes], uRemainder);
else
printf("%02x (%d bits)", pbtData[szBytes], uRemainder);
}
printf("\n");
}
void
print_hex_par(const uint8_t *pbtData, const size_t szBits, const uint8_t *pbtDataPar)
{
uint8_t uRemainder;
size_t szPos;
size_t szBytes = szBits / 8;
for (szPos = 0; szPos < szBytes; szPos++) {
printf("%02x", pbtData[szPos]);
if (oddparity(pbtData[szPos]) != pbtDataPar[szPos]) {
printf("! ");
} else {
printf(" ");
}
}
uRemainder = szBits % 8;
// Print the rest bits, these cannot have parity bit
if (uRemainder != 0) {
if (uRemainder < 5)
printf("%01x (%d bits)", pbtData[szBytes], uRemainder);
else
printf("%02x (%d bits)", pbtData[szBytes], uRemainder);
}
printf("\n");
}
#define SAK_UID_NOT_COMPLETE 0x04
#define SAK_ISO14443_4_COMPLIANT 0x20
#define SAK_ISO18092_COMPLIANT 0x40
void
print_nfc_iso14443a_info(const nfc_iso14443a_info nai, bool verbose)
{
printf(" ATQA (SENS_RES): ");
print_hex(nai.abtAtqa, 2);
if (verbose) {
printf("* UID size: ");
switch ((nai.abtAtqa[1] & 0xc0) >> 6) {
case 0:
printf("single\n");
break;
case 1:
printf("double\n");
break;
case 2:
printf("triple\n");
break;
case 3:
printf("RFU\n");
break;
}
printf("* bit frame anticollision ");
switch (nai.abtAtqa[1] & 0x1f) {
case 0x01:
case 0x02:
case 0x04:
case 0x08:
case 0x10:
printf("supported\n");
break;
default:
printf("not supported\n");
break;
}
}
printf(" UID (NFCID%c): ", (nai.abtUid[0] == 0x08 ? '3' : '1'));
print_hex(nai.abtUid, nai.szUidLen);
if (verbose) {
if (nai.abtUid[0] == 0x08) {
printf("* Random UID\n");
}
}
printf(" SAK (SEL_RES): ");
print_hex(&nai.btSak, 1);
if (verbose) {
if (nai.btSak & SAK_UID_NOT_COMPLETE) {
printf("* Warning! Cascade bit set: UID not complete\n");
}
if (nai.btSak & SAK_ISO14443_4_COMPLIANT) {
printf("* Compliant with ISO/IEC 14443-4\n");
} else {
printf("* Not compliant with ISO/IEC 14443-4\n");
}
if (nai.btSak & SAK_ISO18092_COMPLIANT) {
printf("* Compliant with ISO/IEC 18092\n");
} else {
printf("* Not compliant with ISO/IEC 18092\n");
}
}
if (nai.szAtsLen) {
printf(" ATS: ");
print_hex(nai.abtAts, nai.szAtsLen);
}
if (nai.szAtsLen && verbose) {
// Decode ATS according to ISO/IEC 14443-4 (5.2 Answer to select)
const int iMaxFrameSizes[] = { 16, 24, 32, 40, 48, 64, 96, 128, 256 };
printf("* Max Frame Size accepted by PICC: %d bytes\n", iMaxFrameSizes[nai.abtAts[0] & 0x0F]);
size_t offset = 1;
if (nai.abtAts[0] & 0x10) { // TA(1) present
uint8_t TA = nai.abtAts[offset];
offset++;
printf("* Bit Rate Capability:\n");
if (TA == 0) {
printf(" * PICC supports only 106 kbits/s in both directions\n");
}
if (TA & 1 << 7) {
printf(" * Same bitrate in both directions mandatory\n");
}
if (TA & 1 << 4) {
printf(" * PICC to PCD, DS=2, bitrate 212 kbits/s supported\n");
}
if (TA & 1 << 5) {
printf(" * PICC to PCD, DS=4, bitrate 424 kbits/s supported\n");
}
if (TA & 1 << 6) {
printf(" * PICC to PCD, DS=8, bitrate 847 kbits/s supported\n");
}
if (TA & 1 << 0) {
printf(" * PCD to PICC, DR=2, bitrate 212 kbits/s supported\n");
}
if (TA & 1 << 1) {
printf(" * PCD to PICC, DR=4, bitrate 424 kbits/s supported\n");
}
if (TA & 1 << 2) {
printf(" * PCD to PICC, DR=8, bitrate 847 kbits/s supported\n");
}
if (TA & 1 << 3) {
printf(" * ERROR unknown value\n");
}
}
if (nai.abtAts[0] & 0x20) { // TB(1) present
uint8_t TB = nai.abtAts[offset];
offset++;
printf("* Frame Waiting Time: %.4g ms\n", 256.0 * 16.0 * (1 << ((TB & 0xf0) >> 4)) / 13560.0);
if ((TB & 0x0f) == 0) {
printf("* No Start-up Frame Guard Time required\n");
} else {
printf("* Start-up Frame Guard Time: %.4g ms\n", 256.0 * 16.0 * (1 << (TB & 0x0f)) / 13560.0);
}
}
if (nai.abtAts[0] & 0x40) { // TC(1) present
uint8_t TC = nai.abtAts[offset];
offset++;
if (TC & 0x1) {
printf("* Node ADdress supported\n");
} else {
printf("* Node ADdress not supported\n");
}
if (TC & 0x2) {
printf("* Card IDentifier supported\n");
} else {
printf("* Card IDentifier not supported\n");
}
}
if (nai.szAtsLen > offset) {
printf("* Historical bytes Tk: ");
print_hex(nai.abtAts + offset, (nai.szAtsLen - offset));
uint8_t CIB = nai.abtAts[offset];
offset++;
if (CIB != 0x00 && CIB != 0x10 && (CIB & 0xf0) != 0x80) {
printf(" * Proprietary format\n");
if (CIB == 0xc1) {
printf(" * Tag byte: Mifare or virtual cards of various types\n");
uint8_t L = nai.abtAts[offset];
offset++;
if (L != (nai.szAtsLen - offset)) {
printf(" * Warning: Type Identification Coding length (%i)", L);
printf(" not matching Tk length (%zi)\n", (nai.szAtsLen - offset));
}
if ((nai.szAtsLen - offset - 2) > 0) { // Omit 2 CRC bytes
uint8_t CTC = nai.abtAts[offset];
offset++;
printf(" * Chip Type: ");
switch (CTC & 0xf0) {
case 0x00:
printf("(Multiple) Virtual Cards\n");
break;
case 0x10:
printf("Mifare DESFire\n");
break;
case 0x20:
printf("Mifare Plus\n");
break;
default:
printf("RFU\n");
break;
}
printf(" * Memory size: ");
switch (CTC & 0x0f) {
case 0x00:
printf("<1 kbyte\n");
break;
case 0x01:
printf("1 kbyte\n");
break;
case 0x02:
printf("2 kbyte\n");
break;
case 0x03:
printf("4 kbyte\n");
break;
case 0x04:
printf("8 kbyte\n");
break;
case 0x0f:
printf("Unspecified\n");
break;
default:
printf("RFU\n");
break;
}
}
if ((nai.szAtsLen - offset) > 0) { // Omit 2 CRC bytes
uint8_t CVC = nai.abtAts[offset];
offset++;
printf(" * Chip Status: ");
switch (CVC & 0xf0) {
case 0x00:
printf("Engineering sample\n");
break;
case 0x20:
printf("Released\n");
break;
default:
printf("RFU\n");
break;
}
printf(" * Chip Generation: ");
switch (CVC & 0x0f) {
case 0x00:
printf("Generation 1\n");
break;
case 0x01:
printf("Generation 2\n");
break;
case 0x02:
printf("Generation 3\n");
break;
case 0x0f:
printf("Unspecified\n");
break;
default:
printf("RFU\n");
break;
}
}
if ((nai.szAtsLen - offset) > 0) { // Omit 2 CRC bytes
uint8_t VCS = nai.abtAts[offset];
offset++;
printf(" * Specifics (Virtual Card Selection):\n");
if ((VCS & 0x09) == 0x00) {
printf(" * Only VCSL supported\n");
} else if ((VCS & 0x09) == 0x01) {
printf(" * VCS, VCSL and SVC supported\n");
}
if ((VCS & 0x0e) == 0x00) {
printf(" * SL1, SL2(?), SL3 supported\n");
} else if ((VCS & 0x0e) == 0x02) {
printf(" * SL3 only card\n");
} else if ((VCS & 0x0f) == 0x0e) {
printf(" * No VCS command supported\n");
} else if ((VCS & 0x0f) == 0x0f) {
printf(" * Unspecified\n");
} else {
printf(" * RFU\n");
}
}
}
} else {
if (CIB == 0x00) {
printf(" * Tk after 0x00 consist of optional consecutive COMPACT-TLV data objects\n");
printf(" followed by a mandatory status indicator (the last three bytes, not in TLV)\n");
printf(" See ISO/IEC 7816-4 8.1.1.3 for more info\n");
}
if (CIB == 0x10) {
printf(" * DIR data reference: %02x\n", nai.abtAts[offset]);
}
if (CIB == 0x80) {
if (nai.szAtsLen == offset) {
printf(" * No COMPACT-TLV objects found, no status found\n");
} else {
printf(" * Tk after 0x80 consist of optional consecutive COMPACT-TLV data objects;\n");
printf(" the last data object may carry a status indicator of one, two or three bytes.\n");
printf(" See ISO/IEC 7816-4 8.1.1.3 for more info\n");
}
}
}
}
}
if (verbose) {
printf("\nFingerprinting based on MIFARE type Identification Procedure:\n"); // AN10833
uint16_t atqa = 0;
uint8_t sak = 0;
uint8_t i, j;
bool found_possible_match = false;
atqa = (((uint16_t)nai.abtAtqa[0] & 0xff) << 8);
atqa += (((uint16_t)nai.abtAtqa[1] & 0xff));
sak = ((uint8_t)nai.btSak & 0xff);
for (i = 0; i < sizeof(const_ca) / sizeof(const_ca[0]); i++) {
if ((atqa & const_ca[i].mask) == const_ca[i].atqa) {
for (j = 0; (j < sizeof(const_ca[i].saklist)) && (const_ca[i].saklist[j] >= 0); j++) {
int sakindex = const_ca[i].saklist[j];
if ((sak & const_cs[sakindex].mask) == const_cs[sakindex].sak) {
printf("* %s%s\n", const_ca[i].type, const_cs[sakindex].type);
found_possible_match = true;
}
}
}
}
// Other matches not described in
// AN10833 MIFARE Type Identification Procedure
// but seen in the field:
printf("Other possible matches based on ATQA & SAK values:\n");
uint32_t atqasak = 0;
atqasak += (((uint32_t)nai.abtAtqa[0] & 0xff) << 16);
atqasak += (((uint32_t)nai.abtAtqa[1] & 0xff) << 8);
atqasak += ((uint32_t)nai.btSak & 0xff);
switch (atqasak) {
case 0x000488:
printf("* Mifare Classic 1K Infineon\n");
found_possible_match = true;
break;
case 0x000298:
printf("* Gemplus MPCOS\n");
found_possible_match = true;
break;
case 0x030428:
printf("* JCOP31\n");
found_possible_match = true;
break;
case 0x004820:
printf("* JCOP31 v2.4.1\n");
printf("* JCOP31 v2.2\n");
found_possible_match = true;
break;
case 0x000428:
printf("* JCOP31 v2.3.1\n");
found_possible_match = true;
break;
case 0x000453:
printf("* Fudan FM1208SH01\n");
found_possible_match = true;
break;
case 0x000820:
printf("* Fudan FM1208\n");
found_possible_match = true;
break;
case 0x000238:
printf("* MFC 4K emulated by Nokia 6212 Classic\n");
found_possible_match = true;
break;
case 0x000838:
printf("* MFC 4K emulated by Nokia 6131 NFC\n");
found_possible_match = true;
break;
}
if (! found_possible_match) {
printf("* Unknown card, sorry\n");
}
}
}
void
print_nfc_felica_info(const nfc_felica_info nfi, bool verbose)
{
(void) verbose;
printf(" ID (NFCID2): ");
print_hex(nfi.abtId, 8);
printf(" Parameter (PAD): ");
print_hex(nfi.abtPad, 8);
printf(" System Code (SC): ");
print_hex(nfi.abtSysCode, 2);
}
void
print_nfc_jewel_info(const nfc_jewel_info nji, bool verbose)
{
(void) verbose;
printf(" ATQA (SENS_RES): ");
print_hex(nji.btSensRes, 2);
printf(" 4-LSB JEWELID: ");
print_hex(nji.btId, 4);
}
#define PI_ISO14443_4_SUPPORTED 0x01
#define PI_NAD_SUPPORTED 0x01
#define PI_CID_SUPPORTED 0x02
void
print_nfc_iso14443b_info(const nfc_iso14443b_info nbi, bool verbose)
{
const int iMaxFrameSizes[] = { 16, 24, 32, 40, 48, 64, 96, 128, 256 };
printf(" PUPI: ");
print_hex(nbi.abtPupi, 4);
printf(" Application Data: ");
print_hex(nbi.abtApplicationData, 4);
printf(" Protocol Info: ");
print_hex(nbi.abtProtocolInfo, 3);
if (verbose) {
printf("* Bit Rate Capability:\n");
if (nbi.abtProtocolInfo[0] == 0) {
printf(" * PICC supports only 106 kbits/s in both directions\n");
}
if (nbi.abtProtocolInfo[0] & 1 << 7) {
printf(" * Same bitrate in both directions mandatory\n");
}
if (nbi.abtProtocolInfo[0] & 1 << 4) {
printf(" * PICC to PCD, 1etu=64/fc, bitrate 212 kbits/s supported\n");
}
if (nbi.abtProtocolInfo[0] & 1 << 5) {
printf(" * PICC to PCD, 1etu=32/fc, bitrate 424 kbits/s supported\n");
}
if (nbi.abtProtocolInfo[0] & 1 << 6) {
printf(" * PICC to PCD, 1etu=16/fc, bitrate 847 kbits/s supported\n");
}
if (nbi.abtProtocolInfo[0] & 1 << 0) {
printf(" * PCD to PICC, 1etu=64/fc, bitrate 212 kbits/s supported\n");
}
if (nbi.abtProtocolInfo[0] & 1 << 1) {
printf(" * PCD to PICC, 1etu=32/fc, bitrate 424 kbits/s supported\n");
}
if (nbi.abtProtocolInfo[0] & 1 << 2) {
printf(" * PCD to PICC, 1etu=16/fc, bitrate 847 kbits/s supported\n");
}
if (nbi.abtProtocolInfo[0] & 1 << 3) {
printf(" * ERROR unknown value\n");
}
if ((nbi.abtProtocolInfo[1] & 0xf0) <= 0x80) {
printf("* Maximum frame sizes: %d bytes\n", iMaxFrameSizes[((nbi.abtProtocolInfo[1] & 0xf0) >> 4)]);
}
if ((nbi.abtProtocolInfo[1] & 0x0f) == PI_ISO14443_4_SUPPORTED) {
printf("* Protocol types supported: ISO/IEC 14443-4\n");
}
printf("* Frame Waiting Time: %.4g ms\n", 256.0 * 16.0 * (1 << ((nbi.abtProtocolInfo[2] & 0xf0) >> 4)) / 13560.0);
if ((nbi.abtProtocolInfo[2] & (PI_NAD_SUPPORTED | PI_CID_SUPPORTED)) != 0) {
printf("* Frame options supported: ");
if ((nbi.abtProtocolInfo[2] & PI_NAD_SUPPORTED) != 0) printf("NAD ");
if ((nbi.abtProtocolInfo[2] & PI_CID_SUPPORTED) != 0) printf("CID ");
printf("\n");
}
}
}
void
print_nfc_iso14443bi_info(const nfc_iso14443bi_info nii, bool verbose)
{
printf(" DIV: ");
print_hex(nii.abtDIV, 4);
if (verbose) {
int version = (nii.btVerLog & 0x1e) >> 1;
printf(" Software Version: ");
if (version == 15) {
printf("Undefined\n");
} else {
printf("%i\n", version);
}
if ((nii.btVerLog & 0x80) && (nii.btConfig & 0x80)) {
printf(" Wait Enable: yes");
}
}
if ((nii.btVerLog & 0x80) && (nii.btConfig & 0x40)) {
printf(" ATS: ");
print_hex(nii.abtAtr, nii.szAtrLen);
}
}
void
print_nfc_iso14443b2sr_info(const nfc_iso14443b2sr_info nsi, bool verbose)
{
2011-05-18 20:53:00 +02:00
(void) verbose;
printf(" UID: ");
print_hex(nsi.abtUID, 8);
}
void
print_nfc_iso14443b2ct_info(const nfc_iso14443b2ct_info nci, bool verbose)
{
2011-05-18 20:53:00 +02:00
(void) verbose;
uint32_t uid;
uid = (nci.abtUID[3] << 24) + (nci.abtUID[2] << 16) + (nci.abtUID[1] << 8) + nci.abtUID[0];
printf(" UID: ");
print_hex(nci.abtUID, sizeof(nci.abtUID));
printf(" UID (decimal): %010u\n", uid);
printf(" Product Code: %02X\n", nci.btProdCode);
printf(" Fab Code: %02X\n", nci.btFabCode);
}
void
print_nfc_dep_info(const nfc_dep_info ndi, bool verbose)
{
(void) verbose;
printf(" NFCID3: ");
print_hex(ndi.abtNFCID3, 10);
printf(" BS: %02x\n", ndi.btBS);
printf(" BR: %02x\n", ndi.btBR);
printf(" TO: %02x\n", ndi.btTO);
printf(" PP: %02x\n", ndi.btPP);
if (ndi.szGB) {
printf("General Bytes: ");
print_hex(ndi.abtGB, ndi.szGB);
}
}
2010-10-13 19:43:23 +02:00
void
print_nfc_target(const nfc_target nt, bool verbose)
2010-10-13 19:43:23 +02:00
{
printf("%s (%s%s) target:\n", str_nfc_modulation_type(nt.nm.nmt), str_nfc_baud_rate(nt.nm.nbr), (nt.nm.nmt != NMT_DEP) ? "" : (nt.nti.ndi.ndm == NDM_ACTIVE) ? "active mode" : "passive mode");
switch (nt.nm.nmt) {
2010-10-13 19:43:23 +02:00
case NMT_ISO14443A:
print_nfc_iso14443a_info(nt.nti.nai, verbose);
break;
2010-10-13 19:43:23 +02:00
case NMT_JEWEL:
print_nfc_jewel_info(nt.nti.nji, verbose);
break;
2010-10-13 19:43:23 +02:00
case NMT_FELICA:
print_nfc_felica_info(nt.nti.nfi, verbose);
break;
2010-10-13 19:43:23 +02:00
case NMT_ISO14443B:
print_nfc_iso14443b_info(nt.nti.nbi, verbose);
break;
case NMT_ISO14443BI:
print_nfc_iso14443bi_info(nt.nti.nii, verbose);
break;
case NMT_ISO14443B2SR:
print_nfc_iso14443b2sr_info(nt.nti.nsi, verbose);
break;
case NMT_ISO14443B2CT:
print_nfc_iso14443b2ct_info(nt.nti.nci, verbose);
break;
2010-10-13 19:43:23 +02:00
case NMT_DEP:
print_nfc_dep_info(nt.nti.ndi, verbose);
break;
2010-10-13 19:43:23 +02:00
}
}