diff --git a/examples/nfc-poll.c b/examples/nfc-poll.c index f8f30ba..4cea5d6 100644 --- a/examples/nfc-poll.c +++ b/examples/nfc-poll.c @@ -9,6 +9,7 @@ * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: + * Copyright (C) 2020 Adam Laurie * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -101,14 +102,15 @@ main(int argc, const char *argv[]) const uint8_t uiPollNr = 20; const uint8_t uiPeriod = 2; - const nfc_modulation nmModulations[5] = { + const nfc_modulation nmModulations[6] = { { .nmt = NMT_ISO14443A, .nbr = NBR_106 }, { .nmt = NMT_ISO14443B, .nbr = NBR_106 }, { .nmt = NMT_FELICA, .nbr = NBR_212 }, { .nmt = NMT_FELICA, .nbr = NBR_424 }, { .nmt = NMT_JEWEL, .nbr = NBR_106 }, + { .nmt = NMT_ISO14443BICLASS, .nbr = NBR_106 }, }; - const size_t szModulations = 5; + const size_t szModulations = 6; nfc_target nt; int res = 0; diff --git a/include/nfc/nfc-types.h b/include/nfc/nfc-types.h index 89ad397..5817e7c 100644 --- a/include/nfc/nfc-types.h +++ b/include/nfc/nfc-types.h @@ -9,6 +9,7 @@ * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: + * Copyright (C) 2020 Adam Laurie * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the @@ -234,6 +235,14 @@ typedef struct { uint8_t abtAtr[33]; } nfc_iso14443bi_info; +/** + * @struct nfc_iso14443biclass_info + * @brief NFC ISO14443BiClass tag information + */ +typedef struct { + uint8_t abtUID[8]; +} nfc_iso14443biclass_info; + /** * @struct nfc_iso14443b2sr_info * @brief NFC ISO14443-2B ST SRx tag information @@ -284,6 +293,7 @@ typedef union { nfc_jewel_info nji; nfc_barcode_info nti; // "t" for Thinfilm, "b" already used nfc_dep_info ndi; + nfc_iso14443biclass_info nhi; // hid iclass / picopass - nii already used } nfc_target_info; /** @@ -311,7 +321,9 @@ typedef enum { NMT_ISO14443B2SR, // ISO14443-2B ST SRx NMT_ISO14443B2CT, // ISO14443-2B ASK CTx NMT_FELICA, - NMT_DEP, // DEP should be kept last one as it's used as end-of-enum + NMT_DEP, + NMT_ISO14443BICLASS, // HID iClass 14443B mode + NMT_END_ENUM = NMT_ISO14443BICLASS, // dummy for sizing - always should alias last } nfc_modulation_type; /** diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 89af830..4dc2a15 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -9,6 +9,7 @@ * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: + * Copyright (C) 2020 Adam Laurie * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the @@ -85,7 +86,7 @@ pn53x_init(struct nfc_device *pnd) } if (!CHIP_DATA(pnd)->supported_modulation_as_initiator) { - CHIP_DATA(pnd)->supported_modulation_as_initiator = malloc(sizeof(nfc_modulation_type) * (NMT_DEP + 1)); + CHIP_DATA(pnd)->supported_modulation_as_initiator = malloc(sizeof(nfc_modulation_type) * (NMT_END_ENUM + 1)); if (! CHIP_DATA(pnd)->supported_modulation_as_initiator) return NFC_ESOFT; int nbSupportedModulation = 0; @@ -104,6 +105,8 @@ pn53x_init(struct nfc_device *pnd) nbSupportedModulation++; CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_ISO14443B2CT; nbSupportedModulation++; + CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_ISO14443BICLASS; + nbSupportedModulation++; } if (CHIP_DATA(pnd)->type != PN531) { CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_JEWEL; @@ -575,6 +578,12 @@ pn53x_decode_target_data(const uint8_t *pbtRawData, size_t szRawData, pn53x_type memcpy(pnti->nsi.abtUID, pbtRawData, 8); break; + case NMT_ISO14443BICLASS: + // Store the UID + for(uint8_t i= 0 ; i < 8 ; ++i) + pnti->nhi.abtUID[7 - i]= pbtRawData[i]; + break; + case NMT_ISO14443B2CT: // Store UID LSB memcpy(pnti->nci.abtUID, pbtRawData, 2); @@ -1048,6 +1057,56 @@ pn53x_initiator_init(struct nfc_device *pnd) return NFC_SUCCESS; } +// iclass requires special modulation settings +void pn53x_initiator_init_iclass_modulation(struct nfc_device *pnd) +{ + // send a bunch of low level commands reverse engineered from a working iClass reader + // original device was using a PN512 + // + // // TxModeReg - Defines the data rate and framing during transmission. + //// set bit 4 for target mode? - RxWaitRF Set to logic 1, the counter for RxWait starts only if an external RF field is detected in Target mode for NFCIP-1 or in Card Communication mode + //pn512_write_register(0x12, "\x03", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_TxMode, 0x03); + // + // // RxModeReg - Defines the data rate and framing during reception. + //pn512_write_register(0x13, "\x03", 1, false); + // addy changed to set bit 3 - RxNoErr (put data in fifo before flagging read end) + //pn512_write_register(0x13, "\x0B", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_RxMode, 0x0B); + + // ManualRCVReg - Allows manual fine tuning of the internal receiver. + //pn512_write_register(0x1d, "\x10", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_ManualRCV, 0x10); + + // RFCfgReg - Configures the receiver gain and RF level detector sensitivity. + //pn512_write_register(0x26, "\x70", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_RFCfg, 0x70); + + // GsNOffReg - Selects the conductance for the N-driver of the antenna driver pins TX1 and TX2 when the driver is switched off. + //pn512_write_register(0x23, "\x88", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_GsNOFF, 0x88); + + // GsNOnReg - Selects the conductance for the N-driver of the antenna driver pins TX1 and TX2 when the driver is switched on. + //pn512_write_register(0x27, "\xf8", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_GsNOn, 0xf8); + + // CWGsPReg - Defines the conductance of the P-driver during times of no modulation. + //pn512_write_register(0x28, "\x3f", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_CWGsP, 0x3f); + + // ModGsPReg - Defines the driver P-output conductance during modulation. + //pn512_write_register(0x29, "\x10", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_ModGsP, 0x10); + + // TReloadReg (MSB) - Describes the MSB of the 16-bit long timer reload value. + //pn512_write_register(0x2c, "\x69", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_TReloadVal_hi, 0x69); + + // TReloadReg (LSB) - Describes the LSB of the 16-bit long timer reload value. + //pn512_write_register(0x2d, "\xf0", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_TReloadVal_lo, 0xf0); +} + int pn532_initiator_init_secure_element(struct nfc_device *pnd) { @@ -1067,7 +1126,7 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, nfc_target nttmp; memset(&nttmp, 0x00, sizeof(nfc_target)); - if (nm.nmt == NMT_ISO14443BI || nm.nmt == NMT_ISO14443B2SR || nm.nmt == NMT_ISO14443B2CT) { + if (nm.nmt == NMT_ISO14443BI || nm.nmt == NMT_ISO14443B2SR || nm.nmt == NMT_ISO14443B2CT || nm.nmt == NMT_ISO14443BICLASS) { if (CHIP_DATA(pnd)->type == RCS360) { // TODO add support for RC-S360, at the moment it refuses to send raw frames without a first select pnd->last_error = NFC_ENOTIMPL; @@ -1094,6 +1153,8 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, size_t szInitiateLen = 2; uint8_t abtSelect[] = { 0x0e, 0x00 }; uint8_t abtRx[1]; + uint8_t *pbtInitData = (uint8_t *) "\x0b"; + size_t szInitData = 1; // Getting random Chip_ID if ((res = pn53x_initiator_transceive_bytes(pnd, abtInitiate, szInitiateLen, abtRx, sizeof(abtRx), timeout)) < 0) { if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout @@ -1106,9 +1167,18 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, return res; } szTargetsData = (size_t)res; + if ((res = pn53x_initiator_transceive_bytes(pnd, pbtInitData, szInitData, abtTargetsData, sizeof(abtTargetsData), timeout)) < 0) { + if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout + continue; + } else + return res; + } + szTargetsData = (size_t)res; } else if (nm.nmt == NMT_ISO14443B2CT) { // Some work to do before getting the UID... const uint8_t abtReqt[] = { 0x10 }; + uint8_t *pbtInitData = (uint8_t *) "\x9F\xFF\xFF"; + size_t szInitData = 3; // Getting product code / fab code & store it in output buffer after the serial nr we'll obtain later if ((res = pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), abtTargetsData + 2, sizeof(abtTargetsData) - 2, timeout)) < 0) { if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout @@ -1117,7 +1187,53 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, return res; } szTargetsData = (size_t)res; + if ((res = pn53x_initiator_transceive_bytes(pnd, pbtInitData, szInitData, abtTargetsData, sizeof(abtTargetsData), timeout)) < 0) { + if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout + continue; + } else + return res; + } + szTargetsData = (size_t)res; + if (szTargetsData != 2) + return 0; // Target is not ISO14443B2CT + uint8_t abtRead[] = { 0xC4 }; // Reading UID_MSB (Read address 4) + if ((res = pn53x_initiator_transceive_bytes(pnd, abtRead, sizeof(abtRead), abtTargetsData + 4, sizeof(abtTargetsData) - 4, timeout)) < 0) { + return res; + } + szTargetsData = 6; // u16 UID_LSB, u8 prod code, u8 fab code, u16 UID_MSB + } else if (nm.nmt == NMT_ISO14443BICLASS) { + pn53x_initiator_init_iclass_modulation(pnd); + // + // Some work to do before getting the UID... + // send ICLASS_ACTIVATE_ALL command - will get timeout as we don't expect response + uint8_t abtReqt[] = { 0x0a }; // iClass ACTIVATE_ALL + uint8_t abtAnticol[11]; + if ((res = pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), NULL, 0, timeout)) < 0) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "got expected timeout on iClass activate all"); + //if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout + // continue; + //} else + // return res; + } + // do select - returned anticol contains 'handle' for tag if present + abtReqt[0]= 0x0c; // iClass SELECT + abtAnticol[0]= 0x81; // iClass ANTICOL + if ((res = pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), &abtAnticol[1], sizeof(abtAnticol) - 1, timeout)) < 0) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "timeout on iClass anticol"); + return res; + } + // write back anticol handle to get UID + if ((res = pn53x_initiator_transceive_bytes(pnd, abtAnticol, 9, abtTargetsData, 10, timeout)) < 0) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "timeout on iClass get UID"); + return res; + } + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "iClass raw UID: %02x %02x %02x %02x %02x %02x %02x %02x", abtTargetsData[0], abtTargetsData[1], abtTargetsData[2], abtTargetsData[3], abtTargetsData[4], abtTargetsData[5], abtTargetsData[6], abtTargetsData[7]); + szTargetsData = 8; + nttmp.nm = nm; + if ((res = pn53x_decode_target_data(abtTargetsData, szTargetsData, CHIP_DATA(pnd)->type, nm.nmt, &(nttmp.nti))) < 0) { + return res; } + } else { if ((res = pn53x_initiator_transceive_bytes(pnd, pbtInitData, szInitData, abtTargetsData, sizeof(abtTargetsData), timeout)) < 0) { if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout @@ -1126,15 +1242,8 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, return res; } szTargetsData = (size_t)res; - if (nm.nmt == NMT_ISO14443B2CT) { - if (szTargetsData != 2) - return 0; // Target is not ISO14443B2CT - uint8_t abtRead[] = { 0xC4 }; // Reading UID_MSB (Read address 4) - if ((res = pn53x_initiator_transceive_bytes(pnd, abtRead, sizeof(abtRead), abtTargetsData + 4, sizeof(abtTargetsData) - 4, timeout)) < 0) { - return res; - } - szTargetsData = 6; // u16 UID_LSB, u8 prod code, u8 fab code, u16 UID_MSB - } + } + nttmp.nm = nm; if ((res = pn53x_decode_target_data(abtTargetsData, szTargetsData, CHIP_DATA(pnd)->type, nm.nmt, &(nttmp.nti))) < 0) { return res; @@ -2138,6 +2247,29 @@ static int pn53x_ISO14443B_SR_is_present(struct nfc_device *pnd) return ret; } +static int pn53x_ISO14443B_ICLASS_is_present(struct nfc_device *pnd) +{ + int timeout= 300; + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping B iClass"); + pn53x_initiator_init_iclass_modulation(pnd); + // + // Some work to do before getting the UID... + // send ICLASS_ACTIVATE_ALL command - will get timeout as we don't expect response + uint8_t abtReqt[] = { 0x0a }; // iClass ACTIVATE_ALL + uint8_t abtAnticol[11]; + if (pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), NULL, 0, timeout) < 0) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "got expected timeout on iClass activate all"); + } + // do select - returned anticol contains 'handle' for tag if present + abtReqt[0]= 0x0c; // iClass SELECT + abtAnticol[0]= 0x81; // iClass ANTICOL + if (pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), &abtAnticol[1], sizeof(abtAnticol) - 1, timeout) < 0) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "timeout on iClass anticol"); + return NFC_ETGRELEASED;; + } + return NFC_SUCCESS; +} + static int pn53x_ISO14443B_CT_is_present(struct nfc_device *pnd) { int ret; @@ -2218,6 +2350,9 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) case NMT_ISO14443B2CT: ret = pn53x_ISO14443B_CT_is_present(pnd); break; + case NMT_ISO14443BICLASS: + ret = pn53x_ISO14443B_ICLASS_is_present(pnd); + break; } if (ret == NFC_ETGRELEASED) pn53x_current_target_free(pnd); @@ -2268,6 +2403,7 @@ pn53x_target_init(struct nfc_device *pnd, nfc_target *pnt, uint8_t *pbtRx, const case NMT_ISO14443BI: case NMT_ISO14443B2SR: case NMT_ISO14443B2CT: + case NMT_ISO14443BICLASS: case NMT_JEWEL: case NMT_BARCODE: pnd->last_error = NFC_EDEVNOTSUPP; @@ -2370,6 +2506,7 @@ pn53x_target_init(struct nfc_device *pnd, nfc_target *pnt, uint8_t *pbtRx, const case NMT_ISO14443BI: case NMT_ISO14443B2SR: case NMT_ISO14443B2CT: + case NMT_ISO14443BICLASS: case NMT_JEWEL: case NMT_BARCODE: pnd->last_error = NFC_EDEVNOTSUPP; @@ -2525,6 +2662,7 @@ pn53x_target_receive_bytes(struct nfc_device *pnd, uint8_t *pbtRx, const size_t case NMT_ISO14443BI: case NMT_ISO14443B2SR: case NMT_ISO14443B2CT: + case NMT_ISO14443BICLASS: case NMT_FELICA: abtCmd[0] = TgGetInitiatorCommand; break; @@ -2631,6 +2769,7 @@ pn53x_target_send_bytes(struct nfc_device *pnd, const uint8_t *pbtTx, const size case NMT_ISO14443BI: case NMT_ISO14443B2SR: case NMT_ISO14443B2CT: + case NMT_ISO14443BICLASS: case NMT_FELICA: abtCmd[0] = TgResponseToInitiator; break; @@ -3253,6 +3392,7 @@ pn53x_nm_to_pm(const nfc_modulation nm) return PM_ISO14443A_106; case NMT_ISO14443B: + case NMT_ISO14443BICLASS: switch (nm.nbr) { case NBR_106: return PM_ISO14443B_106; @@ -3351,6 +3491,7 @@ pn53x_nm_to_ptt(const nfc_modulation nm) // return PTT_ISO14443_4A_106; case NMT_ISO14443B: + case NMT_ISO14443BICLASS: switch (nm.nbr) { case NBR_106: return PTT_ISO14443_4B_106; @@ -3436,6 +3577,7 @@ pn53x_get_supported_baud_rate(nfc_device *pnd, const nfc_mode mode, const nfc_mo case NMT_ISO14443BI: case NMT_ISO14443B2SR: case NMT_ISO14443B2CT: + case NMT_ISO14443BICLASS: *supported_br = (nfc_baud_rate *)pn532_iso14443b_supported_baud_rates; break; case NMT_JEWEL: diff --git a/libnfc/chips/pn53x.h b/libnfc/chips/pn53x.h index f236930..4d769f8 100644 --- a/libnfc/chips/pn53x.h +++ b/libnfc/chips/pn53x.h @@ -9,6 +9,7 @@ * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: + * Copyright (C) 2020 Adam Laurie * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the @@ -322,6 +323,7 @@ int pn53x_idle(struct nfc_device *pnd); // NFC device as Initiator functions int pn53x_initiator_init(struct nfc_device *pnd); +void pn53x_initiator_init_iclass_modulation(struct nfc_device *pnd); int pn532_initiator_init_secure_element(struct nfc_device *pnd); int pn53x_initiator_select_passive_target(struct nfc_device *pnd, const nfc_modulation nm, diff --git a/libnfc/nfc-internal.c b/libnfc/nfc-internal.c index d90bb87..b57b97c 100644 --- a/libnfc/nfc-internal.c +++ b/libnfc/nfc-internal.c @@ -9,6 +9,7 @@ * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: + * Copyright (C) 2020 Adam Laurie * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the @@ -169,37 +170,25 @@ void prepare_initiator_data(const nfc_modulation nm, uint8_t **ppbtInitiatorData, size_t *pszInitiatorData) { switch (nm.nmt) { - case NMT_ISO14443B: { + case NMT_ISO14443B: // Application Family Identifier (AFI) must equals 0x00 in order to wakeup all ISO14443-B PICCs (see ISO/IEC 14443-3) *ppbtInitiatorData = (uint8_t *) "\x00"; *pszInitiatorData = 1; - } break; - case NMT_ISO14443BI: { + case NMT_ISO14443BI: // APGEN *ppbtInitiatorData = (uint8_t *) "\x01\x0b\x3f\x80"; *pszInitiatorData = 4; - } break; - case NMT_ISO14443B2SR: { - // Get_UID - *ppbtInitiatorData = (uint8_t *) "\x0b"; - *pszInitiatorData = 1; - } - break; - case NMT_ISO14443B2CT: { - // SELECT-ALL - *ppbtInitiatorData = (uint8_t *) "\x9F\xFF\xFF"; - *pszInitiatorData = 3; - } - break; - case NMT_FELICA: { + case NMT_FELICA: // polling payload must be present (see ISO/IEC 18092 11.2.2.5) *ppbtInitiatorData = (uint8_t *) "\x00\xff\xff\x01\x00"; *pszInitiatorData = 5; - } break; case NMT_ISO14443A: + case NMT_ISO14443B2CT: + case NMT_ISO14443B2SR: + case NMT_ISO14443BICLASS: case NMT_JEWEL: case NMT_BARCODE: case NMT_DEP: diff --git a/libnfc/nfc.c b/libnfc/nfc.c index c06da0e..8c12578 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -9,6 +9,7 @@ * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: + * Copyright (C) 2020 Adam Laurie * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the @@ -206,7 +207,10 @@ int nfc_register_driver(const struct nfc_driver *ndr) { if (!ndr) + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "nfc_register_driver returning NFC_EINVARG"); return NFC_EINVARG; + } struct nfc_driver_list *pndl = (struct nfc_driver_list *)malloc(sizeof(struct nfc_driver_list)); if (!pndl) @@ -1296,9 +1300,11 @@ nfc_device_validate_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_m if (nbr[j] == nm->nbr) return NFC_SUCCESS; } + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "nfc_device_validate_modulation returning NFC_EINVARG"); return NFC_EINVARG; } } + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "nfc_device_validate_modulation returning NFC_EINVARG"); return NFC_EINVARG; } @@ -1384,6 +1390,8 @@ str_nfc_modulation_type(const nfc_modulation_type nmt) return "ISO/IEC 14443-4B"; case NMT_ISO14443BI: return "ISO/IEC 14443-4B'"; + case NMT_ISO14443BICLASS: + return "ISO/IEC 14443-2B-3B iClass (Picopass)"; case NMT_ISO14443B2CT: return "ISO/IEC 14443-2B ASK CTx"; case NMT_ISO14443B2SR: diff --git a/libnfc/target-subr.c b/libnfc/target-subr.c index 61cedfd..e3f09c5 100644 --- a/libnfc/target-subr.c +++ b/libnfc/target-subr.c @@ -9,6 +9,7 @@ * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: + * Copyright (C) 2020 Adam Laurie * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the @@ -609,6 +610,15 @@ snprint_nfc_iso14443b2sr_info(char *dst, size_t size, const nfc_iso14443b2sr_inf snprint_hex(dst + off, size - off, pnsi->abtUID, 8); } +void +snprint_nfc_iso14443biclass_info(char *dst, size_t size, const nfc_iso14443biclass_info *pnic, bool verbose) +{ + (void) verbose; + int off = 0; + off += snprintf(dst + off, size - off, " UID: "); + snprint_hex(dst + off, size - off, pnic->abtUID, 8); +} + void snprint_nfc_iso14443b2ct_info(char *dst, size_t size, const nfc_iso14443b2ct_info *pnci, bool verbose) { @@ -668,6 +678,9 @@ snprint_nfc_target(char *dst, size_t size, const nfc_target *pnt, bool verbose) case NMT_ISO14443B2SR: snprint_nfc_iso14443b2sr_info(dst + off, size - off, &pnt->nti.nsi, verbose); break; + case NMT_ISO14443BICLASS: + snprint_nfc_iso14443biclass_info(dst + off, size - off, &pnt->nti.nhi, verbose); + break; case NMT_ISO14443B2CT: snprint_nfc_iso14443b2ct_info(dst + off, size - off, &pnt->nti.nci, verbose); break; diff --git a/libnfc/target-subr.h b/libnfc/target-subr.h index 9205d6f..633d20d 100644 --- a/libnfc/target-subr.h +++ b/libnfc/target-subr.h @@ -9,6 +9,7 @@ * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: + * Copyright (C) 2020 Adam Laurie * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the @@ -37,6 +38,7 @@ void snprint_nfc_iso14443a_info(char *dst, size_t size, const nfc_iso14443a_i void snprint_nfc_iso14443b_info(char *dst, size_t size, const nfc_iso14443b_info *pnbi, bool verbose); void snprint_nfc_iso14443bi_info(char *dst, size_t size, const nfc_iso14443bi_info *pnii, bool verbose); void snprint_nfc_iso14443b2sr_info(char *dst, size_t size, const nfc_iso14443b2sr_info *pnsi, bool verbose); +void snprint_nfc_iso14443biclass_info(char *dst, size_t size, const nfc_iso14443biclass_info *pnic, bool verbose); void snprint_nfc_iso14443b2ct_info(char *dst, size_t size, const nfc_iso14443b2ct_info *pnci, bool verbose); void snprint_nfc_felica_info(char *dst, size_t size, const nfc_felica_info *pnfi, bool verbose); void snprint_nfc_jewel_info(char *dst, size_t size, const nfc_jewel_info *pnji, bool verbose); diff --git a/utils/nfc-list.c b/utils/nfc-list.c index 55e4224..9b20517 100644 --- a/utils/nfc-list.c +++ b/utils/nfc-list.c @@ -9,6 +9,7 @@ * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: + * Copyright (C) 2020 Adam Laurie * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -71,10 +72,11 @@ print_usage(const char *progname) printf("\t 16: ISO14443B'\n"); printf("\t 32: ISO14443B-2 ST SRx\n"); printf("\t 64: ISO14443B-2 ASK CTx\n"); - printf("\t 128: ISO14443A-3 Jewel\n"); - printf("\t 256: ISO14443A-2 NFC Barcode\n"); - printf("\tSo 511 (default) polls for all types.\n"); - printf("\tNote that if 16, 32 or 64 then 8 is selected too.\n"); + printf("\t 128: ISO14443B iClass\n"); + printf("\t 256: ISO14443A-3 Jewel\n"); + printf("\t 512: ISO14443A-2 NFC Barcode\n"); + printf("\tSo 1023 (default) polls for all types.\n"); + printf("\tNote that if 16, 32, 64 or 128 then 8 is selected too.\n"); } int @@ -85,7 +87,7 @@ main(int argc, const char *argv[]) size_t i; bool verbose = false; int res = 0; - int mask = 0x1ff; + int mask = 0x3ff; int arg; nfc_context *context; @@ -109,13 +111,13 @@ main(int argc, const char *argv[]) } else if ((0 == strcmp(argv[arg], "-t")) && (arg + 1 < argc)) { arg++; mask = atoi(argv[arg]); - if ((mask < 1) || (mask > 0x1ff)) { + if ((mask < 1) || (mask > 0x3ff)) { ERR("%i is invalid value for type bitfield.", mask); print_usage(argv[0]); exit(EXIT_FAILURE); } // Force TypeB for all derivatives of B - if (mask & 0x70) + if (mask & 0xf0) mask |= 0x08; } else { ERR("%s is not supported option.", argv[arg]); @@ -272,6 +274,22 @@ main(int argc, const char *argv[]) } if (mask & 0x80) { + nm.nmt = NMT_ISO14443BICLASS; + nm.nbr = NBR_106; + // List ISO14443B iClass targets + if ((res = nfc_initiator_list_passive_targets(pnd, nm, ant, MAX_TARGET_COUNT)) >= 0) { + int n; + if (verbose || (res > 0)) { + printf("%d ISO14443B iClass passive target(s) found%s\n", res, (res == 0) ? ".\n" : ":"); + } + for (n = 0; n < res; n++) { + print_nfc_target(&ant[n], verbose); + printf("\n"); + } + } + } + + if (mask & 0x100) { nm.nmt = NMT_JEWEL; nm.nbr = NBR_106; // List Jewel targets @@ -287,7 +305,7 @@ main(int argc, const char *argv[]) } } - if (mask & 0x100) { + if (mask & 0x200) { nm.nmt = NMT_BARCODE; nm.nbr = NBR_106; // List NFC Barcode targets @@ -302,6 +320,7 @@ main(int argc, const char *argv[]) } } } + nfc_close(pnd); }