diff --git a/ChangeLog b/ChangeLog index fe49567..89f3608 100644 --- a/ChangeLog +++ b/ChangeLog @@ -43,11 +43,12 @@ Improvements: - nfc-mfultralight: add automatic modes and --check-magic - nfc-mfultralight: add support for magic gen2 cards - nfc-mfultralight: add option to specify UID - - nfc-barcode: new command to read NFC Barcodes (Tag-Talks-First) + - nfc-barcode: new command to read and decode NFC Barcodes (Tag-Talks-First) Changes: - nfc_get_supported_baud_rate() takes now a "mode" parameter - New nfc_get_supported_baud_rate_target_mode() + - New NFC modulation type NMT_BARCODE to support Thinfilm NFC Barcode protocol Special thanks to: - Jim Anastassiou, Frédéric Bourgeois, Dario Carluccio, Emmanuel Dreyfus, diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 3f8fb87..35a852b 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,6 +1,5 @@ SET(EXAMPLES-SOURCES nfc-anticol - nfc-barcode nfc-dep-initiator nfc-dep-target nfc-emulate-forum-tag2 diff --git a/examples/Makefile.am b/examples/Makefile.am index 42baa29..c767532 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -2,7 +2,6 @@ SUBDIRS = pn53x-tamashell-scripts bin_PROGRAMS = \ nfc-anticol \ - nfc-barcode \ nfc-dep-initiator \ nfc-dep-target \ nfc-emulate-forum-tag2 \ @@ -36,10 +35,6 @@ nfc_anticol_SOURCES = nfc-anticol.c nfc_anticol_LDADD = $(top_builddir)/libnfc/libnfc.la \ $(top_builddir)/utils/libnfcutils.la -nfc_barcode_SOURCES = nfc-barcode.c -nfc_barcode_LDADD = $(top_builddir)/libnfc/libnfc.la \ - $(top_builddir)/utils/libnfcutils.la - nfc_relay_SOURCES = nfc-relay.c nfc_relay_LDADD = $(top_builddir)/libnfc/libnfc.la \ $(top_builddir)/utils/libnfcutils.la @@ -92,7 +87,6 @@ quick_start_example2_LDADD = $(top_builddir)/libnfc/libnfc.la \ dist_man_MANS = \ nfc-anticol.1 \ - nfc-barcode.1 \ nfc-dep-initiator.1 \ nfc-dep-target.1 \ nfc-emulate-tag.1 \ diff --git a/include/nfc/nfc-types.h b/include/nfc/nfc-types.h index 8c726a1..a18e4aa 100644 --- a/include/nfc/nfc-types.h +++ b/include/nfc/nfc-types.h @@ -261,6 +261,15 @@ typedef struct { uint8_t btId[4]; } nfc_jewel_info; +/** + * @struct nfc_barcode_info + * @brief Thinfilm NFC Barcode information + */ +typedef struct { + size_t szDataLen; + uint8_t abtData[32]; +} nfc_barcode_info; + /** * @union nfc_target_info * @brief Union between all kind of tags information structures. @@ -273,6 +282,7 @@ typedef union { nfc_iso14443b2sr_info nsi; nfc_iso14443b2ct_info nci; nfc_jewel_info nji; + nfc_barcode_info nti; // "t" for Thinfilm, "b" already used nfc_dep_info ndi; } nfc_target_info; @@ -295,6 +305,7 @@ typedef enum { typedef enum { NMT_ISO14443A = 1, NMT_JEWEL, + NMT_BARCODE, // Thinfilm NFC Barcode NMT_ISO14443B, NMT_ISO14443BI, // pre-ISO14443B aka ISO/IEC 14443 B' or Type B' NMT_ISO14443B2SR, // ISO14443-2B ST SRx diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index a83d3f0..5c19767 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -57,6 +57,7 @@ const nfc_baud_rate pn533_iso14443a_supported_baud_rates[] = { NBR_847, NBR_424, const nfc_baud_rate pn53x_felica_supported_baud_rates[] = { NBR_424, NBR_212, 0 }; const nfc_baud_rate pn53x_dep_supported_baud_rates[] = { NBR_424, NBR_212, NBR_106, 0 }; const nfc_baud_rate pn53x_jewel_supported_baud_rates[] = { NBR_106, 0 }; +const nfc_baud_rate pn53x_barcode_supported_baud_rates[] = { NBR_106, 0 }; const nfc_baud_rate pn532_iso14443b_supported_baud_rates[] = { NBR_106, 0 }; const nfc_baud_rate pn533_iso14443b_supported_baud_rates[] = { NBR_847, NBR_424, NBR_212, NBR_106, 0 }; const nfc_modulation_type pn53x_supported_modulation_as_target[] = {NMT_ISO14443A, NMT_FELICA, NMT_DEP, 0}; @@ -107,6 +108,8 @@ pn53x_init(struct nfc_device *pnd) if (CHIP_DATA(pnd)->type != PN531) { CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_JEWEL; nbSupportedModulation++; + CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_BARCODE; + nbSupportedModulation++; } CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_DEP; nbSupportedModulation++; @@ -610,6 +613,10 @@ pn53x_decode_target_data(const uint8_t *pbtRawData, size_t szRawData, pn53x_type pbtRawData += 2; memcpy(pnti->nji.btId, pbtRawData, 4); break; + case NMT_BARCODE: + pnti->nti.szDataLen = szRawData; + memcpy(pnti->nti.abtData, pbtRawData, szRawData); + break; // Should not happend... case NMT_DEP: return NFC_ECHIP; @@ -1147,6 +1154,87 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, } while (pnd->bInfiniteSelect); if (! found) return 0; + } else if (nm.nmt == NMT_BARCODE) { + 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; + return pnd->last_error; + } + // No native support in InListPassiveTarget so we do discovery by hand + + // We turn RF field off first for a better detection rate but this doesn't work well with ASK LoGO + if ((! CHIP_DATA(pnd)->progressive_field) && (res = nfc_device_set_property_bool(pnd, NP_ACTIVATE_FIELD, false)) < 0) { + return res; + } + if ((res = nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false)) < 0) { + return res; + } + if ((res = nfc_device_set_property_bool(pnd, NP_HANDLE_PARITY, false)) < 0) { + return res; + } + + bool found = false; + do { + uint8_t abtRx[PN53x_EXTENDED_FRAME__DATA_MAX_LEN]; + uint8_t abtRxPar[PN53x_EXTENDED_FRAME__DATA_MAX_LEN]; + if ((res = nfc_initiator_transceive_bits(pnd, NULL, 0, NULL, abtRx, sizeof(abtRx), abtRxPar)) < 0) { + if ((res == NFC_ERFTRANS) || (res == NFC_ECHIP)) { // Broken reception + continue; + } else { + nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true); + nfc_device_set_property_bool(pnd, NP_HANDLE_PARITY, true); + return res; + } + } + + // Shuffle bits to produce NFC Barcode bitstream + uint8_t uRemainder; + size_t szPos; + size_t szBytes = res / 8; + size_t off = 0; + uint8_t i; + memset(abtTargetsData, 0x00, sizeof(abtTargetsData)); + // Reinject S bit + abtTargetsData[off / 8] |= 1 << (7 - (off % 8)); + off++; + + for (szPos = 0; szPos < szBytes; szPos++) { + for (i = 0; i < 8; i++) { + abtTargetsData[off / 8] |= ((abtRx[szPos] >> i) & 1) << (7 - (off % 8)); + off++; + } + abtTargetsData[off / 8] |= abtRxPar[szPos] << (7 - (off % 8)); + off++; + } + uRemainder = res % 8; + for (i = 0; i < uRemainder; i++) { + abtTargetsData[off / 8] |= ((abtRx[szPos] >> i) & 1) << (7 - (off % 8)); + off++; + } + + if (off % 128 != 0) { + // NFC Barcode seems incomplete + continue; + } + + szTargetsData = (size_t)off / 8; + + // validate CRC + uint8_t pbtCrc[2]; + iso14443a_crc(abtTargetsData, szTargetsData - 2, pbtCrc); + if ((pbtCrc[1] != abtTargetsData[szTargetsData - 2]) || (pbtCrc[0] != abtTargetsData[szTargetsData - 1])) { + continue; + } + nttmp.nm = nm; + if ((res = pn53x_decode_target_data(abtTargetsData, szTargetsData, CHIP_DATA(pnd)->type, nm.nmt, &(nttmp.nti))) < 0) { + return res; + } + found = true; + break; + } while (pnd->bInfiniteSelect); + if (! found) { + return 0; + } } else { const pn53x_modulation pm = pn53x_nm_to_pm(nm); if ((PM_UNDEFINED == pm) || (NBR_UNDEFINED == nm.nbr)) { @@ -1846,6 +1934,40 @@ static int pn53x_ISO14443A_Jewel_is_present(struct nfc_device *pnd) return ret; } +static int pn53x_ISO14443A_Barcode_is_present(struct nfc_device *pnd) +{ + int ret; + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping Barcode"); + + // We turn RF field off first for a better detection rate but this doesn't work well with ASK LoGO + if ((! CHIP_DATA(pnd)->progressive_field) && (ret = nfc_device_set_property_bool(pnd, NP_ACTIVATE_FIELD, false)) < 0) { + return ret; + } + if ((ret = nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false)) < 0) + return ret; + if ((ret = nfc_device_set_property_bool(pnd, NP_HANDLE_PARITY, false)) < 0) + return ret; + + int failures = 0; + while (failures < 3) { + if ((! CHIP_DATA(pnd)->progressive_field) && (ret = nfc_device_set_property_bool(pnd, NP_ACTIVATE_FIELD, false)) < 0) { + return ret; + } + uint8_t abtRx[PN53x_EXTENDED_FRAME__DATA_MAX_LEN]; + uint8_t abtRxPar[PN53x_EXTENDED_FRAME__DATA_MAX_LEN]; + if ((ret = nfc_initiator_transceive_bits(pnd, NULL, 0, NULL, abtRx, sizeof(abtRx), abtRxPar)) < 1) { + failures++; + } else { + nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true); + nfc_device_set_property_bool(pnd, NP_HANDLE_PARITY, true); + return NFC_SUCCESS; + } + } + nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true); + nfc_device_set_property_bool(pnd, NP_HANDLE_PARITY, true); + return NFC_ETGRELEASED; +} + static int pn53x_ISO14443A_MFUL_is_present(struct nfc_device *pnd) { int ret; @@ -2081,6 +2203,9 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) case NMT_JEWEL: ret = pn53x_ISO14443A_Jewel_is_present(pnd); break; + case NMT_BARCODE: + ret = pn53x_ISO14443A_Barcode_is_present(pnd); + break; case NMT_ISO14443B: ret = pn53x_ISO14443B_4_is_present(pnd); break; @@ -2144,6 +2269,7 @@ pn53x_target_init(struct nfc_device *pnd, nfc_target *pnt, uint8_t *pbtRx, const case NMT_ISO14443B2SR: case NMT_ISO14443B2CT: case NMT_JEWEL: + case NMT_BARCODE: pnd->last_error = NFC_EDEVNOTSUPP; return pnd->last_error; } @@ -2245,6 +2371,7 @@ pn53x_target_init(struct nfc_device *pnd, nfc_target *pnt, uint8_t *pbtRx, const case NMT_ISO14443B2SR: case NMT_ISO14443B2CT: case NMT_JEWEL: + case NMT_BARCODE: pnd->last_error = NFC_EDEVNOTSUPP; return pnd->last_error; } @@ -2393,6 +2520,7 @@ pn53x_target_receive_bytes(struct nfc_device *pnd, uint8_t *pbtRx, const size_t } // NO BREAK case NMT_JEWEL: + case NMT_BARCODE: case NMT_ISO14443B: case NMT_ISO14443BI: case NMT_ISO14443B2SR: @@ -2498,6 +2626,7 @@ pn53x_target_send_bytes(struct nfc_device *pnd, const uint8_t *pbtTx, const size } // NO BREAK case NMT_JEWEL: + case NMT_BARCODE: case NMT_ISO14443B: case NMT_ISO14443BI: case NMT_ISO14443B2SR: @@ -2714,6 +2843,7 @@ pn53x_InListPassiveTarget(struct nfc_device *pnd, } break; case PM_JEWEL_106: + case PM_BARCODE_106: if (CHIP_DATA(pnd)->type == PN531) { // These modulations are not supported by pn531 pnd->last_error = NFC_EDEVNOTSUPP; @@ -3141,6 +3271,9 @@ pn53x_nm_to_pm(const nfc_modulation nm) case NMT_JEWEL: return PM_JEWEL_106; + case NMT_BARCODE: + return PM_BARCODE_106; + case NMT_FELICA: switch (nm.nbr) { case NBR_212: @@ -3253,6 +3386,7 @@ pn53x_nm_to_ptt(const nfc_modulation nm) case NMT_ISO14443BI: case NMT_ISO14443B2SR: case NMT_ISO14443B2CT: + case NMT_BARCODE: case NMT_DEP: // Nothing to do... break; @@ -3307,6 +3441,9 @@ pn53x_get_supported_baud_rate(nfc_device *pnd, const nfc_mode mode, const nfc_mo case NMT_JEWEL: *supported_br = (nfc_baud_rate *)pn53x_jewel_supported_baud_rates; break; + case NMT_BARCODE: + *supported_br = (nfc_baud_rate *)pn53x_barcode_supported_baud_rates; + break; case NMT_DEP: *supported_br = (nfc_baud_rate *)pn53x_dep_supported_baud_rates; break; @@ -3560,6 +3697,9 @@ pn53x_data_new(struct nfc_device *pnd, const struct pn53x_io *io) CHIP_DATA(pnd)->supported_modulation_as_target = NULL; + // Set default progressive field flag + CHIP_DATA(pnd)->progressive_field = false; + return pnd->chip_data; } diff --git a/libnfc/chips/pn53x.h b/libnfc/chips/pn53x.h index bb5d6e3..f236930 100644 --- a/libnfc/chips/pn53x.h +++ b/libnfc/chips/pn53x.h @@ -210,6 +210,7 @@ struct pn53x_data { /** Supported modulation type */ nfc_modulation_type *supported_modulation_as_initiator; nfc_modulation_type *supported_modulation_as_target; + bool progressive_field; }; #define CHIP_DATA(pnd) ((struct pn53x_data*)(pnd->chip_data)) @@ -231,6 +232,8 @@ typedef enum { PM_ISO14443B_106 = 0x03, /** Jewel Topaz (Innovision Research & Development) (Not supported by PN531) */ PM_JEWEL_106 = 0x04, + /** Thinfilm NFC Barcode (Not supported by PN531) */ + PM_BARCODE_106 = 0x05, /** ISO14443-B http://en.wikipedia.org/wiki/ISO/IEC_14443 (Not supported by PN531 nor PN532) */ PM_ISO14443B_212 = 0x06, /** ISO14443-B http://en.wikipedia.org/wiki/ISO/IEC_14443 (Not supported by PN531 nor PN532) */ diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index 30f3b6f..807e98e 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -474,6 +474,7 @@ pn53x_usb_open(const nfc_context *context, const nfc_connstring connstring) // empirical tuning case ASK_LOGO: CHIP_DATA(pnd)->timer_correction = 50; + CHIP_DATA(pnd)->progressive_field = true; break; case SCM_SCL3711: case SCM_SCL3712: diff --git a/libnfc/nfc-internal.c b/libnfc/nfc-internal.c index 68ecd34..d90bb87 100644 --- a/libnfc/nfc-internal.c +++ b/libnfc/nfc-internal.c @@ -201,6 +201,7 @@ prepare_initiator_data(const nfc_modulation nm, uint8_t **ppbtInitiatorData, siz break; case NMT_ISO14443A: case NMT_JEWEL: + case NMT_BARCODE: case NMT_DEP: *ppbtInitiatorData = NULL; *pszInitiatorData = 0; diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 70312b8..636697d 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -602,9 +602,10 @@ nfc_initiator_list_passive_targets(nfc_device *pnd, break; } nfc_initiator_deselect_target(pnd); - // deselect has no effect on FeliCa and Jewel cards so we'll stop after one... + // deselect has no effect on FeliCa, Jewel and Thinfilm cards so we'll stop after one... // ISO/IEC 14443 B' cards are polled at 100% probability so it's not possible to detect correctly two cards at the same time - if ((nm.nmt == NMT_FELICA) || (nm.nmt == NMT_JEWEL) || (nm.nmt == NMT_ISO14443BI) || (nm.nmt == NMT_ISO14443B2SR) || (nm.nmt == NMT_ISO14443B2CT)) { + if ((nm.nmt == NMT_FELICA) || (nm.nmt == NMT_JEWEL) || (nm.nmt == NMT_BARCODE) || + (nm.nmt == NMT_ISO14443BI) || (nm.nmt == NMT_ISO14443B2SR) || (nm.nmt == NMT_ISO14443B2CT)) { break; } } @@ -1356,6 +1357,8 @@ str_nfc_modulation_type(const nfc_modulation_type nmt) return "FeliCa"; case NMT_JEWEL: return "Innovision Jewel"; + case NMT_BARCODE: + return "Thinfilm NFC Barcode"; case NMT_DEP: return "D.E.P."; } diff --git a/libnfc/target-subr.c b/libnfc/target-subr.c index ea35e77..97e2882 100644 --- a/libnfc/target-subr.c +++ b/libnfc/target-subr.c @@ -498,6 +498,22 @@ snprint_nfc_jewel_info(char *dst, size_t size, const nfc_jewel_info *pnji, bool snprint_hex(dst + off, size - off, pnji->btId, 4); } +void +snprint_nfc_barcode_info(char *dst, size_t size, const nfc_barcode_info *pnti, bool verbose) +{ + (void) verbose; + int off = 0; + off += snprintf(dst + off, size - off, " Size (bits): %lu\n", pnti->szDataLen * 8); + off += snprintf(dst + off, size - off, " Content: "); + for (uint8_t i = 0; i < pnti->szDataLen; i++) { + off += snprintf(dst + off, size - off, "%02X", pnti->abtData[i]); + if ((i % 8 == 7) && (i < (pnti->szDataLen - 1))) { + off += snprintf(dst + off, size - off, "\n "); + } + } + snprintf(dst + off, size - off, "\n"); +} + #define PI_ISO14443_4_SUPPORTED 0x01 #define PI_NAD_SUPPORTED 0x01 #define PI_CID_SUPPORTED 0x02 @@ -637,6 +653,9 @@ snprint_nfc_target(char *dst, size_t size, const nfc_target *pnt, bool verbose) case NMT_JEWEL: snprint_nfc_jewel_info(dst + off, size - off, &pnt->nti.nji, verbose); break; + case NMT_BARCODE: + snprint_nfc_barcode_info(dst + off, size - off, &pnt->nti.nti, verbose); + break; case NMT_FELICA: snprint_nfc_felica_info(dst + off, size - off, &pnt->nti.nfi, verbose); break; diff --git a/libnfc/target-subr.h b/libnfc/target-subr.h index 528a3ab..9205d6f 100644 --- a/libnfc/target-subr.h +++ b/libnfc/target-subr.h @@ -40,6 +40,7 @@ void snprint_nfc_iso14443b2sr_info(char *dst, size_t size, const nfc_iso14443 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); +void snprint_nfc_barcode_info(char *dst, size_t size, const nfc_barcode_info *pnti, bool verbose); void snprint_nfc_dep_info(char *dst, size_t size, const nfc_dep_info *pndi, bool verbose); void snprint_nfc_target(char *dst, size_t size, const nfc_target *pnt, bool verbose); diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index dc7bac9..0e03880 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -1,4 +1,5 @@ SET(UTILS-SOURCES + nfc-barcode nfc-emulate-forum-tag4 nfc-jewel nfc-list diff --git a/utils/Makefile.am b/utils/Makefile.am index 2555bcd..11cfe12 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -1,4 +1,5 @@ bin_PROGRAMS = \ + nfc-barcode \ nfc-emulate-forum-tag4 \ nfc-jewel \ nfc-list \ @@ -16,6 +17,10 @@ noinst_LTLIBRARIES = libnfcutils.la libnfcutils_la_SOURCES = nfc-utils.c libnfcutils_la_LIBADD = -lnfc +nfc_barcode_SOURCES = nfc-barcode.c +nfc_barcode_LDADD = $(top_builddir)/libnfc/libnfc.la \ + $(top_builddir)/utils/libnfcutils.la + nfc_emulate_forum_tag4_SOURCES = nfc-emulate-forum-tag4.c nfc-utils.h nfc_emulate_forum_tag4_LDADD = $(top_builddir)/libnfc/libnfc.la \ libnfcutils.la @@ -47,6 +52,7 @@ nfc_scan_device_LDADD = $(top_builddir)/libnfc/libnfc.la \ libnfcutils.la dist_man_MANS = \ + nfc-barcode.1 \ nfc-emulate-forum-tag4.1 \ nfc-jewel.1 \ nfc-list.1 \ diff --git a/examples/nfc-barcode.1 b/utils/nfc-barcode.1 similarity index 83% rename from examples/nfc-barcode.1 rename to utils/nfc-barcode.1 index 0677094..5f4760e 100644 --- a/examples/nfc-barcode.1 +++ b/utils/nfc-barcode.1 @@ -5,7 +5,7 @@ nfc-barcode \- NFC Barcode (Tag-Talks-First) reader .B nfc-barcode .SH DESCRIPTION .B nfc-barcode -is a utility to read NFC Barcodes +is a utility to read and decode NFC Barcodes .SH OPTIONS .B -d @@ -14,14 +14,6 @@ Decode content, if possible. .B -v Verbose. -.B -r -Keep RF field on (for slow devices such as ASK LoGO). - -.B -n N -Try up to -.B N -times (default=1, max 255). - .SH BUGS Please report any bugs on the .B libnfc diff --git a/examples/nfc-barcode.c b/utils/nfc-barcode.c similarity index 55% rename from examples/nfc-barcode.c rename to utils/nfc-barcode.c index fcc013a..766a683 100644 --- a/examples/nfc-barcode.c +++ b/utils/nfc-barcode.c @@ -55,9 +55,6 @@ static nfc_device *pnd; bool verbose = false; -bool decode = false; -bool rfoff = true; -uint8_t n = 1; static void print_usage(char *argv[]) @@ -66,64 +63,12 @@ print_usage(char *argv[]) printf("Options:\n"); printf("\t-h\tHelp. Print this message.\n"); printf("\t-q\tVerbose mode.\n"); - printf("\t-d\tDecode content.\n"); - printf("\t-r\tKeep RF field on (for slow devices such as ASK LoGO).\n"); - printf("\t-n\tTry up to n times (default=1, max 255).\n"); } -static int -bits2barcode(const uint8_t *pbtData, const size_t szBits, const uint8_t *pbtDataPar, uint8_t *pbtBarcode, const size_t szBarcode) -{ - uint8_t uRemainder; - size_t szPos; - size_t szBytes = szBits / 8; - size_t off = 0; - uint8_t i; - for (i = 0; i < szBarcode; i++) { - pbtBarcode[i] = 0; - } - - // Reinject S bit - pbtBarcode[off / 8] |= 1 << (7 - (off % 8)); - off++; - - for (szPos = 0; szPos < szBytes; szPos++) { - for (i = 0; i < 8; i++) { - pbtBarcode[off / 8] |= ((pbtData[szPos] >> i) & 1) << (7 - (off % 8)); - off++; - } - pbtBarcode[off / 8] |= pbtDataPar[szPos] << (7 - (off % 8)); - off++; - } - uRemainder = szBits % 8; - for (i = 0; i < uRemainder; i++) { - pbtBarcode[off / 8] |= ((pbtData[szPos] >> i) & 1) << (7 - (off % 8)); - off++; - } - return off; -} - -static bool -validate_crc(uint8_t *pbtBarcode, const size_t szBarcode) -{ - if (szBarcode % 128 != 0) { - printf("Warning, NFC Barcode seems incomplete, skipping CRC\n"); - return false; - } - uint8_t pbtCrc[2]; - iso14443a_crc(pbtBarcode, (szBarcode / 8) - 2, pbtCrc); - if (verbose) - printf("Computed CRC: %02X %02X\n", pbtCrc[1], pbtCrc[0]); - return (pbtCrc[1] == pbtBarcode[(szBarcode / 8) - 2]) && (pbtCrc[0] == pbtBarcode[(szBarcode / 8) - 1]); -} static bool decode_barcode(uint8_t *pbtBarcode, const size_t szBarcode) { - if (szBarcode % 128 != 0) { - printf("Warning, NFC Barcode seems incomplete, skipping decoding\n"); - return false; - } if (verbose) { printf("Manufacturer ID field: %02X\n", pbtBarcode[0]); switch (pbtBarcode[0]) { @@ -180,7 +125,7 @@ decode_barcode(uint8_t *pbtBarcode, const size_t szBarcode) default: printf("Data Format Field: unknown (%02X)\n", pbtBarcode[1]); printf("Data:"); - for (uint8_t i = 2; i < (szBarcode / 8) - 2; i++) { + for (uint8_t i = 2; i < szBarcode - 2; i++) { printf("%02x", pbtBarcode[i]); } printf("\n"); @@ -193,9 +138,6 @@ int main(int argc, char *argv[]) { int arg; - uint8_t abtRx[MAX_FRAME_LEN]; - uint8_t abtRxPar[MAX_FRAME_LEN]; - uint8_t pbtBarcode[64]; // Get commandline options for (arg = 1; arg < argc; arg++) { @@ -204,16 +146,6 @@ main(int argc, char *argv[]) exit(EXIT_SUCCESS); } else if (0 == strcmp(argv[arg], "-v")) { verbose = true; - } else if (0 == strcmp(argv[arg], "-d")) { - decode = true; - } else if (0 == strcmp(argv[arg], "-r")) { - rfoff = false; - } else if (0 == strcmp(argv[arg], "-n")) { - arg++; - int tmpn = atoi(argv[arg]); - if ((tmpn > 0) && (tmpn < 256)) { - n = tmpn; - } } else { ERR("%s is not supported option.", argv[arg]); print_usage(argv); @@ -247,72 +179,19 @@ main(int argc, char *argv[]) printf("NFC reader: %s opened\n\n", nfc_device_get_name(pnd)); - if ((rfoff && (nfc_device_set_property_bool(pnd, NP_ACTIVATE_FIELD, false) < 0)) || - (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) || - (nfc_device_set_property_bool(pnd, NP_HANDLE_PARITY, false) < 0)) { - nfc_perror(pnd, "nfc_device_set_property_bool"); - nfc_close(pnd); - nfc_exit(context); - exit(EXIT_FAILURE); - } - - for (; n > 0; n--) { - int res; - if ((res = nfc_initiator_transceive_bits(pnd, NULL, 0, NULL, abtRx, sizeof(abtRx), abtRxPar)) < 0) { - if (verbose) - nfc_perror(pnd, "nfc_initiator_transceive_bits"); - if (n == 1) { - printf("No NFC Barcode found\n"); - nfc_close(pnd); - nfc_exit(context); - exit(EXIT_FAILURE); - } - continue; - } - if (verbose) - print_hex_par(abtRx, res, abtRxPar); - res = bits2barcode(abtRx, res, abtRxPar, pbtBarcode, sizeof(pbtBarcode)); - - if (res % 128 != 0) { - if (verbose) { - printf("Error, NFC Barcode seems incomplete, received %u bits\n", res); - print_hex_bits(pbtBarcode, res); - } - if (n == 1) { - printf("Error, NFC Barcode seems incomplete, received %u bits\n", res); - nfc_close(pnd); - nfc_exit(context); - exit(EXIT_FAILURE); - } - continue; - } - if (validate_crc(pbtBarcode, res)) { - if (verbose) { - printf("CRC correct\n"); - } - } else { - if (n == 1) { - printf("CRC error\n"); - if (verbose) { - print_hex_bits(pbtBarcode, res); - } - nfc_close(pnd); - nfc_exit(context); - exit(EXIT_FAILURE); - } - continue; - } - - if (verbose || ! decode) { - for (uint8_t i = 0; i < res / 8; i++) { - printf("%02x", pbtBarcode[i]); + nfc_modulation nm; + nm.nmt = NMT_BARCODE; + nm.nbr = NBR_106; + nfc_target ant[1]; + // List NFC Barcode targets + if ((nfc_initiator_list_passive_targets(pnd, nm, ant, 1)) == 1) { + if (verbose) { + for (uint8_t i = 0; i < (&ant[0])->nti.nti.szDataLen; i++) { + printf("%02x", (&ant[0])->nti.nti.abtData[i]); } printf("\n"); } - if (decode) { - decode_barcode(pbtBarcode, res); - } - break; + decode_barcode((&ant[0])->nti.nti.abtData, (&ant[0])->nti.nti.szDataLen); } nfc_close(pnd); nfc_exit(context); diff --git a/utils/nfc-list.c b/utils/nfc-list.c index 62bb3d7..55e4224 100644 --- a/utils/nfc-list.c +++ b/utils/nfc-list.c @@ -71,8 +71,9 @@ 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: Jewel\n"); - printf("\tSo 255 (default) polls for all types.\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"); } @@ -84,7 +85,7 @@ main(int argc, const char *argv[]) size_t i; bool verbose = false; int res = 0; - int mask = 0xff; + int mask = 0x1ff; int arg; nfc_context *context; @@ -108,7 +109,7 @@ 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 > 255)) { + if ((mask < 1) || (mask > 0x1ff)) { ERR("%i is invalid value for type bitfield.", mask); print_usage(argv[0]); exit(EXIT_FAILURE); @@ -277,7 +278,23 @@ main(int argc, const char *argv[]) if ((res = nfc_initiator_list_passive_targets(pnd, nm, ant, MAX_TARGET_COUNT)) >= 0) { int n; if (verbose || (res > 0)) { - printf("%d Jewel passive target(s) found%s\n", res, (res == 0) ? ".\n" : ":"); + printf("%d ISO14443A-3 Jewel 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_BARCODE; + nm.nbr = NBR_106; + // List NFC Barcode targets + if ((res = nfc_initiator_list_passive_targets(pnd, nm, ant, MAX_TARGET_COUNT)) >= 0) { + int n; + if (verbose || (res > 0)) { + printf("%d ISO14443A-2 NFC Barcode passive target(s) found%s\n", res, (res == 0) ? ".\n" : ":"); } for (n = 0; n < res; n++) { print_nfc_target(&ant[n], verbose);