From 7eae55e92970e880ddd6ee52f9c84269df70b101 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 6 Oct 2016 17:40:48 +0200 Subject: [PATCH 01/12] Adding pn71xx NXP's NFC Controllers through Linux Libnfc-nci --- libnfc/drivers/Makefile.am | 5 + libnfc/drivers/libnfc_nci_support.h | 134 ++++++++ libnfc/drivers/pn71xx.c | 473 ++++++++++++++++++++++++++++ libnfc/drivers/pn71xx.h | 14 + libnfc/nfc.c | 10 + m4/libnfc_drivers.m4 | 11 +- 6 files changed, 645 insertions(+), 2 deletions(-) create mode 100644 libnfc/drivers/libnfc_nci_support.h create mode 100644 libnfc/drivers/pn71xx.c create mode 100644 libnfc/drivers/pn71xx.h diff --git a/libnfc/drivers/Makefile.am b/libnfc/drivers/Makefile.am index 1ac65b2..4432c5c 100644 --- a/libnfc/drivers/Makefile.am +++ b/libnfc/drivers/Makefile.am @@ -39,6 +39,11 @@ if DRIVER_PN532_I2C_ENABLED libnfcdrivers_la_SOURCES += pn532_i2c.c pn532_i2c.h endif +if DRIVER_PN71XX_ENABLED +libnfcdrivers_la_LIBADD += -lnfc_nci_linux +libnfcdrivers_la_SOURCES += pn71xx.c pn71xx.h +endif + if PCSC_ENABLED libnfcdrivers_la_CFLAGS += @libpcsclite_CFLAGS@ libnfcdrivers_la_LIBADD += @libpcsclite_LIBS@ diff --git a/libnfc/drivers/libnfc_nci_support.h b/libnfc/drivers/libnfc_nci_support.h new file mode 100644 index 0000000..9c57c46 --- /dev/null +++ b/libnfc/drivers/libnfc_nci_support.h @@ -0,0 +1,134 @@ + +#ifndef __NFC_DRIVER_LIBNFC_NCI_H__ +#define __NFC_DRIVER_LIBNFC_NCI_H__ + +#include "linux_nfc_api.h" + +#define LOG_CATEGORY "libnfc.driver.pn71xx" +#define LOG_GROUP NFC_LOG_GROUP_DRIVER + +static bool IsTechnology(nfc_tag_info_t *TagInfo, nfc_modulation_type nmt) +{ + switch (nmt) { + case NMT_ISO14443A: + if (TagInfo->technology == TARGET_TYPE_ISO14443_4 + || TagInfo->technology == TARGET_TYPE_ISO14443_3A + || TagInfo->technology == TARGET_TYPE_MIFARE_CLASSIC + || TagInfo->technology == TARGET_TYPE_MIFARE_UL) + return true; + break; + + case NMT_ISO14443B: + case NMT_ISO14443BI: + case NMT_ISO14443B2SR: + case NMT_ISO14443B2CT: + if (TagInfo->technology == TARGET_TYPE_ISO14443_3B) + return true; + break; + + case NMT_FELICA: + if (TagInfo->technology == TARGET_TYPE_FELICA) + return true; + break; + + case NMT_JEWEL: + if (TagInfo->technology == TARGET_TYPE_ISO14443_3A) + return true; + break; + + default: + return false; + } + return false; +} + +static void BufferPrintBytes(char* buffer, unsigned int buflen, unsigned char* data, unsigned int datalen) +{ + int cx = 0; + for(int i = 0x00; i < datalen; i++) { + cx += snprintf(buffer + cx, buflen - cx, "%02X ", data[i]); + } +} + +static void PrintTagInfo (nfc_tag_info_t *TagInfo) +{ + switch (TagInfo->technology) + { + case TARGET_TYPE_UNKNOWN: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type Unknown'"); + } break; + case TARGET_TYPE_ISO14443_3A: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type A'"); + } break; + case TARGET_TYPE_ISO14443_3B: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type 4B'"); + } break; + case TARGET_TYPE_ISO14443_4: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type 4A'"); + } break; + case TARGET_TYPE_FELICA: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type F'"); + } break; + case TARGET_TYPE_ISO15693: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type V'"); + } break; + case TARGET_TYPE_NDEF: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type NDEF'"); + } break; + case TARGET_TYPE_NDEF_FORMATABLE: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type Formatable'"); + } break; + case TARGET_TYPE_MIFARE_CLASSIC: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type A - Mifare Classic'"); + } break; + case TARGET_TYPE_MIFARE_UL: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type A - Mifare Ul'"); + } break; + case TARGET_TYPE_KOVIO_BARCODE: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type A - Kovio Barcode'"); + } break; + case TARGET_TYPE_ISO14443_3A_3B: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type A/B'"); + } break; + default: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type %d (Unknown or not supported)'\n", TagInfo->technology); + } break; + } + /*32 is max UID len (Kovio tags)*/ + if((0x00 != TagInfo->uid_length) && (32 >= TagInfo->uid_length)) + { + char buffer [100]; + int cx = 0; + + if(4 == TagInfo->uid_length || 7 == TagInfo->uid_length || 10 == TagInfo->uid_length) + { + cx += snprintf(buffer + cx, sizeof(buffer) - cx, "NFCID1 : \t'"); + } + else if(8 == TagInfo->uid_length) + { + cx += snprintf(buffer + cx, sizeof(buffer) - cx, "NFCID2 : \t'"); + } + else + { + cx += snprintf(buffer + cx, sizeof(buffer) - cx, "UID : \t'"); + } + + BufferPrintBytes(buffer + cx, sizeof(buffer) - cx, (unsigned char*) TagInfo->uid, TagInfo->uid_length); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s'", buffer); + } +} + +#endif diff --git a/libnfc/drivers/pn71xx.c b/libnfc/drivers/pn71xx.c new file mode 100644 index 0000000..0f1efdb --- /dev/null +++ b/libnfc/drivers/pn71xx.c @@ -0,0 +1,473 @@ + +/** + * @file pn71xx.h + * @brief Driver for PN71XX using libnfc-nci library + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif // HAVE_CONFIG_H + +#include "pn71xx.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include "drivers.h" +#include "nfc-internal.h" + +#include "libnfc_nci_support.h" +#include "linux_nfc_api.h" + +#define PN71XX_DRIVER_NAME "pn71xx" + +#define LOG_CATEGORY "libnfc.driver.pn71xx" +#define LOG_GROUP NFC_LOG_GROUP_DRIVER + +const nfc_modulation_type pn71xx_supported_modulation_as_target[] = {NMT_ISO14443A, NMT_FELICA, NMT_ISO14443B, NMT_ISO14443BI, NMT_ISO14443B2SR, NMT_ISO14443B2CT, NMT_JEWEL, NMT_DEP, 0}; +const nfc_modulation_type pn71xx_supported_modulation_as_initiator[] = {NMT_ISO14443A, NMT_FELICA, NMT_ISO14443B, NMT_ISO14443BI, NMT_ISO14443B2SR, NMT_ISO14443B2CT, NMT_JEWEL, NMT_DEP, 0}; + +const nfc_baud_rate pn71xx_iso14443a_supported_baud_rates[] = { NBR_847, NBR_424, NBR_212, NBR_106, 0 }; +const nfc_baud_rate pn71xx_felica_supported_baud_rates[] = { NBR_424, NBR_212, 0 }; +const nfc_baud_rate pn71xx_dep_supported_baud_rates[] = { NBR_424, NBR_212, NBR_106, 0 }; +const nfc_baud_rate pn71xx_jewel_supported_baud_rates[] = { NBR_847, NBR_424, NBR_212, NBR_106, 0 }; +const nfc_baud_rate pn71xx_iso14443b_supported_baud_rates[] = { NBR_847, NBR_424, NBR_212, NBR_106, 0 }; + +static nfcTagCallback_t TagCB; +static nfc_tag_info_t *TagInfo = NULL; + + + +/** ------------------------------------------------------------------------ */ +/** ------------------------------------------------------------------------ */ + +static void onTagArrival(nfc_tag_info_t *pTagInfo) +{ + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "tag found"); + + TagInfo = malloc(sizeof(nfc_tag_info_t)); + memcpy(TagInfo, pTagInfo, sizeof(nfc_tag_info_t)); + + PrintTagInfo(TagInfo); +} + +static void onTagDeparture(void) +{ + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "tag lost"); + + free(TagInfo); + TagInfo = NULL; +} + +/** ------------------------------------------------------------------------ */ +/** ------------------------------------------------------------------------ */ + + +/** + * @brief Scan all available I2C buses to find PN532 devices. + * + * @param context NFC context. + * @param connstrings array of 'nfc_connstring' buffer (allocated by caller). It is used to store the + * connection info strings of all I2C PN532 devices found. + * @param connstrings_len length of the connstrings array. + * @return number of PN532 devices found on all I2C buses. + */ +static size_t +pn71xx_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len) +{ + size_t device_found = 0; + + if (nfcManager_doInitialize() == 0) { + nfc_connstring connstring = "pn71xx"; + memcpy(connstrings[device_found++], connstring, sizeof(nfc_connstring)); + } + + return device_found; +} + +/** + * @brief Close I2C connection to the PN532 device. + * + * @param pnd pointer on the device to close. + */ +static void +pn71xx_close(nfc_device *pnd) +{ + nfcManager_disableDiscovery(); + nfcManager_deregisterTagCallback(); + nfcManager_doDeinitialize(); + + nfc_device_free(pnd); +} + +/** + * @brief Open an I2C connection to the PN532 device. + * + * @param context NFC context. + * @param connstring connection info to the device + * @return pointer to the device, or NULL in case of error. + */ +static nfc_device * +pn71xx_open(const nfc_context *context, const nfc_connstring connstring) +{ + nfc_device *pnd; + + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "open: %s", connstring); + + pnd = nfc_device_new(context, connstring); + if (!pnd) { + perror("malloc"); + return NULL; + } + + pnd->driver = &pn71xx_driver; + strcpy(pnd->name, "pn71xx-device"); + strcpy(pnd->connstring, connstring); + + + TagCB.onTagArrival = onTagArrival; + TagCB.onTagDeparture = onTagDeparture; + nfcManager_registerTagCallback(&TagCB); + + nfcManager_enableDiscovery(DEFAULT_NFA_TECH_MASK, 1, 0, 0); + + + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "wait 2 seconds for polling"); + sleep(2); + + return pnd; +} + + + +/** ------------------------------------------------------------------------ */ +/** ------------------------------------------------------------------------ */ + + +static int +pn71xx_initiator_init(struct nfc_device *pnd) +{ + return NFC_SUCCESS; +} + +static int +pn71xx_initiator_select_passive_target(struct nfc_device *pnd, + const nfc_modulation nm, + const uint8_t *pbtInitData, const size_t szInitData, + nfc_target *pnt) +{ + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "select_passive_target"); + + if (TagInfo) { + + nfc_target nttmp; + memset(&nttmp, 0x00, sizeof(nfc_target)); + nttmp.nm = nm; + + void* uidPtr = NULL; + int maxLen = 0; + + switch (nm.nmt) { + case NMT_ISO14443A: + if (IsTechnology(TagInfo, nm.nmt)) { + maxLen = 10; + uidPtr = nttmp.nti.nai.abtUid; + + if (TagInfo->technology == TARGET_TYPE_MIFARE_CLASSIC) { + nttmp.nti.nai.btSak = 0x08; + } else { + // make hardcoded desfire for freefare lib check + nttmp.nti.nai.btSak = 0x20; + nttmp.nti.nai.szAtsLen = 5; + memcpy (nttmp.nti.nai.abtAts, "\x75\x77\x81\x02", 4); + } + } + break; + + case NMT_ISO14443B: + if (IsTechnology(TagInfo, nm.nmt)) { + maxLen = 4; + uidPtr = nttmp.nti.nbi.abtPupi; + } + break; + + case NMT_ISO14443BI: + if (IsTechnology(TagInfo, nm.nmt)) { + maxLen = 4; + uidPtr = nttmp.nti.nii.abtDIV; + } + break; + + case NMT_ISO14443B2SR: + if (IsTechnology(TagInfo, nm.nmt)) { + maxLen = 8; + uidPtr = nttmp.nti.nsi.abtUID; + } + break; + + case NMT_ISO14443B2CT: + if (IsTechnology(TagInfo, nm.nmt)) { + maxLen = 4; + uidPtr = nttmp.nti.nci.abtUID; + } + break; + + case NMT_FELICA: + if (IsTechnology(TagInfo, nm.nmt)) { + maxLen = 8; + uidPtr = nttmp.nti.nfi.abtId; + } + break; + + case NMT_JEWEL: + if (IsTechnology(TagInfo, nm.nmt)) { + maxLen = 4; + uidPtr = nttmp.nti.nji.btId; + } + break; + + default: + return 0; + } + + if (uidPtr && TagInfo->uid_length) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "target found"); + int len = TagInfo->uid_length > maxLen ? maxLen : TagInfo->uid_length; + memcpy(uidPtr, TagInfo->uid, len); + if (nm.nmt == NMT_ISO14443A) + nttmp.nti.nai.szUidLen = len; + + // Is a tag info struct available + if (pnt) { + memcpy(pnt, &nttmp, sizeof(nfc_target)); + } + return 1; + } + } + + return 0; +} + +static int +pn71xx_initiator_deselect_target(struct nfc_device *pnd) +{ + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "deselect_passive_target"); + return NFC_SUCCESS; +} + + +static int +pn71xx_initiator_transceive_bytes(struct nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, uint8_t *pbtRx, +const size_t szRx, int timeout) +{ + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "transceive_bytes timeout=%d", timeout); + + if (!TagInfo) + return NFC_EINVARG; + + char buffer[500]; + BufferPrintBytes(buffer, sizeof(buffer), pbtTx, szTx); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "===> %s", buffer); + + int received = nfcTag_transceive(TagInfo->handle, pbtTx, szTx, pbtRx, szRx, 500); + if (received <= 0) + return NFC_EIO; + + BufferPrintBytes(buffer, sizeof(buffer), pbtRx, received); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "<=== %s", buffer); + + return received; +} + +static int +pn71xx_initiator_poll_target(struct nfc_device *pnd, + const nfc_modulation *pnmModulations, const size_t szModulations, + const uint8_t uiPollNr, const uint8_t uiPeriod, + nfc_target *pnt) +{ + static int periodFactor = 150000; + int period = uiPeriod * periodFactor; + + for (int j = 0; j < uiPollNr; j++) { + for (int i = 0; i < szModulations; i++) { + const nfc_modulation nm = pnmModulations[i]; + + //log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "check %s", str_nfc_modulation_type(nm.nmt)); + + nfc_target nt; + int res = pn71xx_initiator_select_passive_target(pnd, nm, 0, 0, &nt); + if (res > 0 && pnt) { + memcpy(pnt, &nt, sizeof(nfc_target)); + return res; + } + } + usleep(period); + } + + return 0; +} + +static int +pn71xx_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) +{ + if (pnt) { + + } + + // 0 = true + return !TagInfo; +} + + +/** ------------------------------------------------------------------------ */ +/** ------------------------------------------------------------------------ */ + + +static int +pn71xx_get_supported_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type **const supported_mt) +{ + //log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "get_supported_modulation mode=%d", mode); + switch (mode) { + case N_TARGET: + *supported_mt = (nfc_modulation_type *)pn71xx_supported_modulation_as_target; + break; + case N_INITIATOR: + *supported_mt = (nfc_modulation_type *)pn71xx_supported_modulation_as_initiator; + break; + default: + return NFC_EINVARG; + } + return NFC_SUCCESS; +} + +static int +pn71xx_get_supported_baud_rate(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br) +{ + switch (nmt) { + case NMT_FELICA: + *supported_br = (nfc_baud_rate *)pn71xx_felica_supported_baud_rates; + break; + case NMT_ISO14443A: + *supported_br = (nfc_baud_rate *)pn71xx_iso14443a_supported_baud_rates; + break; + case NMT_ISO14443B: + case NMT_ISO14443BI: + case NMT_ISO14443B2SR: + case NMT_ISO14443B2CT: + *supported_br = (nfc_baud_rate *)pn71xx_iso14443b_supported_baud_rates; + break; + case NMT_JEWEL: + *supported_br = (nfc_baud_rate *)pn71xx_jewel_supported_baud_rates; + break; + case NMT_DEP: + *supported_br = (nfc_baud_rate *)pn71xx_dep_supported_baud_rates; + break; + default: + return NFC_EINVARG; + } + return NFC_SUCCESS; +} + +/** ------------------------------------------------------------------------ */ +/** ------------------------------------------------------------------------ */ + +static int +pn71xx_set_property_bool(struct nfc_device *pnd, const nfc_property property, const bool bEnable) +{ + //log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "set_property_bool"); + return NFC_SUCCESS; +} + +static int +pn71xx_set_property_int(struct nfc_device *pnd, const nfc_property property, const int value) +{ + //log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "set_property_int"); + return NFC_SUCCESS; +} + +static int +pn71xx_get_information_about(nfc_device *pnd, char **pbuf) +{ + static const char* info = "PN71XX nfc driver using libnfc-nci userspace library"; + size_t buflen = strlen(info) + 1; + + *pbuf = malloc(buflen); + memcpy(*pbuf, info, buflen); + + return buflen; +} +/** + * @brief Abort any pending operation + * + * @param pnd pointer on the NFC device. + * @return NFC_SUCCESS + */ +static int +pn71xx_abort_command(nfc_device *pnd) +{ + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "abort_command"); + return NFC_SUCCESS; +} + +static int +pn71xx_idle(struct nfc_device *pnd) +{ + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "idle"); + return NFC_SUCCESS; +} + +static int +pn71xx_PowerDown(struct nfc_device *pnd) +{ + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "PowerDown"); + return NFC_SUCCESS; +} + +/** ------------------------------------------------------------------------ */ +/** ------------------------------------------------------------------------ */ + + + +const struct nfc_driver pn71xx_driver = { + .name = PN71XX_DRIVER_NAME, + .scan_type = INTRUSIVE, + .scan = pn71xx_scan, + .open = pn71xx_open, + .close = pn71xx_close, + .strerror = NULL, + + .initiator_init = pn71xx_initiator_init, + .initiator_init_secure_element = NULL, + .initiator_select_passive_target = pn71xx_initiator_select_passive_target, + .initiator_poll_target = pn71xx_initiator_poll_target, + .initiator_select_dep_target = NULL, + .initiator_deselect_target = pn71xx_initiator_deselect_target, + .initiator_transceive_bytes = pn71xx_initiator_transceive_bytes, + .initiator_transceive_bits = NULL, + .initiator_transceive_bytes_timed = NULL, + .initiator_transceive_bits_timed = NULL, + .initiator_target_is_present = pn71xx_initiator_target_is_present, + + .target_init = NULL, + .target_send_bytes = NULL, + .target_receive_bytes = NULL, + .target_send_bits = NULL, + .target_receive_bits = NULL, + + .device_set_property_bool = pn71xx_set_property_bool, + .device_set_property_int = pn71xx_set_property_int, + .get_supported_modulation = pn71xx_get_supported_modulation, + .get_supported_baud_rate = pn71xx_get_supported_baud_rate, + .device_get_information_about = pn71xx_get_information_about, + + .abort_command = pn71xx_abort_command, + .idle = pn71xx_idle, + .powerdown = pn71xx_PowerDown, +}; + diff --git a/libnfc/drivers/pn71xx.h b/libnfc/drivers/pn71xx.h new file mode 100644 index 0000000..43c5ff6 --- /dev/null +++ b/libnfc/drivers/pn71xx.h @@ -0,0 +1,14 @@ +/** + * @file pn71xx.h + * @brief Driver for PN71XX using libnfc-nci library + */ + +#ifndef __NFC_DRIVER_PN71XX_H__ +#define __NFC_DRIVER_PN71XX_H__ + +#include + +/* Reference to the driver structure */ +extern const struct nfc_driver pn71xx_driver; + +#endif // ! __NFC_DRIVER_7120_H__ diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 404786a..df739c5 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -118,6 +118,10 @@ # include "drivers/pn532_i2c.h" #endif /* DRIVER_PN532_I2C_ENABLED */ +#if defined (DRIVER_PN71XX_ENABLED) +# include "drivers/pn71xx.h" +#endif /* DRIVER_PN71XX_ENABLED */ + #define LOG_CATEGORY "libnfc.general" #define LOG_GROUP NFC_LOG_GROUP_GENERAL @@ -156,6 +160,9 @@ nfc_drivers_init(void) #if defined (DRIVER_ARYGON_ENABLED) nfc_register_driver(&arygon_driver); #endif /* DRIVER_ARYGON_ENABLED */ +#if defined (DRIVER_PN71XX_ENABLED) + nfc_register_driver(&pn71xx_driver); +#endif /* DRIVER_PN71XX_ENABLED */ } static int @@ -319,8 +326,10 @@ size_t nfc_list_devices(nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len) { size_t device_found = 0; + printf("nfc_list_devices()\n"); #ifdef CONFFILES + printf("nfc_list_devices()- context->user_defined_device_count=%d\n", context->user_defined_device_count); // Load manually configured devices (from config file and env variables) // TODO From env var... for (uint32_t i = 0; i < context->user_defined_device_count; i++) { @@ -342,6 +351,7 @@ nfc_list_devices(nfc_context *context, nfc_connstring connstrings[], const size_ setenv("LIBNFC_LOG_LEVEL", "0", 1); #endif // ENVVARS + printf("nfc_list_devices()- open\n"); pnd = nfc_open(context, context->user_defined_devices[i].connstring); #ifdef ENVVARS diff --git a/m4/libnfc_drivers.m4 b/m4/libnfc_drivers.m4 index 4672539..54be7e7 100644 --- a/m4/libnfc_drivers.m4 +++ b/m4/libnfc_drivers.m4 @@ -4,7 +4,7 @@ AC_DEFUN([LIBNFC_ARG_WITH_DRIVERS], [ AC_MSG_CHECKING(which drivers to build) AC_ARG_WITH(drivers, - AS_HELP_STRING([--with-drivers=DRIVERS], [Use a custom driver set, where DRIVERS is a coma-separated list of drivers to build support for. Available drivers are: 'acr122_pcsc', 'acr122_usb', 'acr122s', 'arygon', 'pn532_i2c', 'pn532_spi', 'pn532_uart' and 'pn53x_usb'. Default drivers set is 'acr122_usb,acr122s,arygon,pn532_i2c,pn532_spi,pn532_uart,pn53x_usb'. The special driver set 'all' compile all available drivers.]), + AS_HELP_STRING([--with-drivers=DRIVERS], [Use a custom driver set, where DRIVERS is a coma-separated list of drivers to build support for. Available drivers are: 'acr122_pcsc', 'acr122_usb', 'acr122s', 'arygon', 'pn532_i2c', 'pn532_spi', 'pn532_uart', 'pn53x_usb' and 'pn71xx'. Default drivers set is 'acr122_usb,acr122s,arygon,pn532_i2c,pn532_spi,pn532_uart,pn53x_usb'. The special driver set 'all' compile all available drivers.]), [ case "${withval}" in yes | no) dnl ignore calls without any arguments @@ -36,7 +36,7 @@ AC_DEFUN([LIBNFC_ARG_WITH_DRIVERS], fi ;; all) - DRIVER_BUILD_LIST="acr122_pcsc acr122_usb acr122s arygon pn53x_usb pn532_uart" + DRIVER_BUILD_LIST="acr122_pcsc acr122_usb acr122s arygon pn53x_usb pn532_uart pn71xx" if test x"$spi_available" = x"yes" then DRIVER_BUILD_LIST="$DRIVER_BUILD_LIST pn532_spi" @@ -58,6 +58,7 @@ AC_DEFUN([LIBNFC_ARG_WITH_DRIVERS], driver_pn532_uart_enabled="no" driver_pn532_spi_enabled="no" driver_pn532_i2c_enabled="no" + driver_pn71xx_enabled="no" for driver in ${DRIVER_BUILD_LIST} do @@ -102,6 +103,10 @@ AC_DEFUN([LIBNFC_ARG_WITH_DRIVERS], driver_pn532_i2c_enabled="yes" DRIVERS_CFLAGS="$DRIVERS_CFLAGS -DDRIVER_PN532_I2C_ENABLED" ;; + pn71xx) + driver_pn71xx_enabled="yes" + DRIVERS_CFLAGS="$DRIVERS_CFLAGS -DDRIVER_PN71XX_ENABLED" + ;; *) AC_MSG_ERROR([Unknow driver: $driver]) ;; @@ -116,6 +121,7 @@ AC_DEFUN([LIBNFC_ARG_WITH_DRIVERS], AM_CONDITIONAL(DRIVER_PN532_UART_ENABLED, [test x"$driver_pn532_uart_enabled" = xyes]) AM_CONDITIONAL(DRIVER_PN532_SPI_ENABLED, [test x"$driver_pn532_spi_enabled" = xyes]) AM_CONDITIONAL(DRIVER_PN532_I2C_ENABLED, [test x"$driver_pn532_i2c_enabled" = xyes]) + AM_CONDITIONAL(DRIVER_PN71XX_ENABLED, [test x"$driver_pn71xx_enabled" = xyes]) ]) AC_DEFUN([LIBNFC_DRIVERS_SUMMARY],[ @@ -129,4 +135,5 @@ echo " pn53x_usb........ $driver_pn53x_usb_enabled" echo " pn532_uart....... $driver_pn532_uart_enabled" echo " pn532_spi....... $driver_pn532_spi_enabled" echo " pn532_i2c........ $driver_pn532_i2c_enabled" +echo " pn71xx........... $driver_pn71xx_enabled" ]) From 4a10d0f21bbcd2d6bc378b8b4c9094efe1e8ac56 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Mon, 10 Oct 2016 17:36:55 +0200 Subject: [PATCH 02/12] Cosmetics changes --- libnfc/drivers/libnfc_nci_support.h | 134 --------- libnfc/drivers/pn71xx.c | 427 ++++++++++++++++++---------- 2 files changed, 275 insertions(+), 286 deletions(-) delete mode 100644 libnfc/drivers/libnfc_nci_support.h diff --git a/libnfc/drivers/libnfc_nci_support.h b/libnfc/drivers/libnfc_nci_support.h deleted file mode 100644 index 9c57c46..0000000 --- a/libnfc/drivers/libnfc_nci_support.h +++ /dev/null @@ -1,134 +0,0 @@ - -#ifndef __NFC_DRIVER_LIBNFC_NCI_H__ -#define __NFC_DRIVER_LIBNFC_NCI_H__ - -#include "linux_nfc_api.h" - -#define LOG_CATEGORY "libnfc.driver.pn71xx" -#define LOG_GROUP NFC_LOG_GROUP_DRIVER - -static bool IsTechnology(nfc_tag_info_t *TagInfo, nfc_modulation_type nmt) -{ - switch (nmt) { - case NMT_ISO14443A: - if (TagInfo->technology == TARGET_TYPE_ISO14443_4 - || TagInfo->technology == TARGET_TYPE_ISO14443_3A - || TagInfo->technology == TARGET_TYPE_MIFARE_CLASSIC - || TagInfo->technology == TARGET_TYPE_MIFARE_UL) - return true; - break; - - case NMT_ISO14443B: - case NMT_ISO14443BI: - case NMT_ISO14443B2SR: - case NMT_ISO14443B2CT: - if (TagInfo->technology == TARGET_TYPE_ISO14443_3B) - return true; - break; - - case NMT_FELICA: - if (TagInfo->technology == TARGET_TYPE_FELICA) - return true; - break; - - case NMT_JEWEL: - if (TagInfo->technology == TARGET_TYPE_ISO14443_3A) - return true; - break; - - default: - return false; - } - return false; -} - -static void BufferPrintBytes(char* buffer, unsigned int buflen, unsigned char* data, unsigned int datalen) -{ - int cx = 0; - for(int i = 0x00; i < datalen; i++) { - cx += snprintf(buffer + cx, buflen - cx, "%02X ", data[i]); - } -} - -static void PrintTagInfo (nfc_tag_info_t *TagInfo) -{ - switch (TagInfo->technology) - { - case TARGET_TYPE_UNKNOWN: - { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type Unknown'"); - } break; - case TARGET_TYPE_ISO14443_3A: - { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type A'"); - } break; - case TARGET_TYPE_ISO14443_3B: - { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type 4B'"); - } break; - case TARGET_TYPE_ISO14443_4: - { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type 4A'"); - } break; - case TARGET_TYPE_FELICA: - { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type F'"); - } break; - case TARGET_TYPE_ISO15693: - { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type V'"); - } break; - case TARGET_TYPE_NDEF: - { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type NDEF'"); - } break; - case TARGET_TYPE_NDEF_FORMATABLE: - { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type Formatable'"); - } break; - case TARGET_TYPE_MIFARE_CLASSIC: - { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type A - Mifare Classic'"); - } break; - case TARGET_TYPE_MIFARE_UL: - { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type A - Mifare Ul'"); - } break; - case TARGET_TYPE_KOVIO_BARCODE: - { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type A - Kovio Barcode'"); - } break; - case TARGET_TYPE_ISO14443_3A_3B: - { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type A/B'"); - } break; - default: - { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type %d (Unknown or not supported)'\n", TagInfo->technology); - } break; - } - /*32 is max UID len (Kovio tags)*/ - if((0x00 != TagInfo->uid_length) && (32 >= TagInfo->uid_length)) - { - char buffer [100]; - int cx = 0; - - if(4 == TagInfo->uid_length || 7 == TagInfo->uid_length || 10 == TagInfo->uid_length) - { - cx += snprintf(buffer + cx, sizeof(buffer) - cx, "NFCID1 : \t'"); - } - else if(8 == TagInfo->uid_length) - { - cx += snprintf(buffer + cx, sizeof(buffer) - cx, "NFCID2 : \t'"); - } - else - { - cx += snprintf(buffer + cx, sizeof(buffer) - cx, "UID : \t'"); - } - - BufferPrintBytes(buffer + cx, sizeof(buffer) - cx, (unsigned char*) TagInfo->uid, TagInfo->uid_length); - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s'", buffer); - } -} - -#endif diff --git a/libnfc/drivers/pn71xx.c b/libnfc/drivers/pn71xx.c index 0f1efdb..8245908 100644 --- a/libnfc/drivers/pn71xx.c +++ b/libnfc/drivers/pn71xx.c @@ -22,7 +22,6 @@ #include "drivers.h" #include "nfc-internal.h" -#include "libnfc_nci_support.h" #include "linux_nfc_api.h" #define PN71XX_DRIVER_NAME "pn71xx" @@ -42,7 +41,212 @@ const nfc_baud_rate pn71xx_iso14443b_supported_baud_rates[] = { NBR_847, NBR_424 static nfcTagCallback_t TagCB; static nfc_tag_info_t *TagInfo = NULL; +static void onTagArrival(nfc_tag_info_t *pTagInfo); +static void onTagDeparture(void); +/** ------------------------------------------------------------------------ */ +/** ------------------------------------------------------------------------ */ +/** + * @brief Initialize libnfc_nci library to verify presence of PN71xx device. + * + * @param context NFC context. + * @param connstrings array of 'nfc_connstring' buffer (allocated by caller). It is used to store the + * connection info strings of devices found. + * @param connstrings_len length of the connstrings array. + * @return number of devices found. + */ +static size_t +pn71xx_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len) +{ + size_t device_found = 0; + + if ((context == NULL) || (connstrings_len == 0)) return 0; + + if (nfcManager_doInitialize() == 0) { + nfc_connstring connstring = "pn71xx"; + memcpy(connstrings[device_found++], connstring, sizeof(nfc_connstring)); + } + + return device_found; +} + +/** + * @brief Close connection to PN71xx by stopping the discovery loop and deinitializing the libnfc_nci library. + * + * @param pnd pointer on the device to close. + */ +static void +pn71xx_close(nfc_device *pnd) +{ + nfcManager_disableDiscovery(); + nfcManager_deregisterTagCallback(); + nfcManager_doDeinitialize(); + nfc_device_free(pnd); + pnd = NULL; +} + +/** + * @brief Open a connection to PN71xx, starting the discovery loop for tag detection. + * + * @param context NFC context. + * @param connstring connection info to the device + * @return pointer to the device, or NULL in case of error. + */ +static nfc_device * +pn71xx_open(const nfc_context *context, const nfc_connstring connstring) +{ + nfc_device *pnd; + + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "open: %s", connstring); + + pnd = nfc_device_new(context, connstring); + if (!pnd) { + perror("malloc"); + return NULL; + } + + pnd->driver = &pn71xx_driver; + strcpy(pnd->name, "pn71xx-device"); + strcpy(pnd->connstring, connstring); + + TagCB.onTagArrival = onTagArrival; + TagCB.onTagDeparture = onTagDeparture; + nfcManager_registerTagCallback(&TagCB); + + nfcManager_enableDiscovery(DEFAULT_NFA_TECH_MASK, 1, 0, 0); + + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "wait 1 seconds for polling"); + sleep(1); + + return pnd; +} + +/** ------------------------------------------------------------------------ */ +/** ------------------------------------------------------------------------ */ +static bool IsTechnology(nfc_tag_info_t *TagInfo, nfc_modulation_type nmt) +{ + switch (nmt) { + case NMT_ISO14443A: + if (TagInfo->technology == TARGET_TYPE_ISO14443_4 + || TagInfo->technology == TARGET_TYPE_ISO14443_3A + || TagInfo->technology == TARGET_TYPE_MIFARE_CLASSIC + || TagInfo->technology == TARGET_TYPE_MIFARE_UL) + return true; + break; + + case NMT_ISO14443B: + case NMT_ISO14443BI: + case NMT_ISO14443B2SR: + case NMT_ISO14443B2CT: + if (TagInfo->technology == TARGET_TYPE_ISO14443_3B) + return true; + break; + + case NMT_FELICA: + if (TagInfo->technology == TARGET_TYPE_FELICA) + return true; + break; + + case NMT_JEWEL: + if (TagInfo->technology == TARGET_TYPE_ISO14443_3A + && TagInfo->protocol == NFA_PROTOCOL_T1T) + return true; + break; + + default: + return false; + } + return false; +} + +static void BufferPrintBytes(char* buffer, unsigned int buflen, const uint8_t *data, unsigned int datalen) +{ + int cx = 0; + for(unsigned int i = 0x00; i < datalen; i++) { + cx += snprintf(buffer + cx, buflen - cx, "%02X ", data[i]); + } +} + +static void PrintTagInfo (nfc_tag_info_t *TagInfo) +{ + switch (TagInfo->technology) + { + case TARGET_TYPE_UNKNOWN: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type Unknown'"); + } break; + case TARGET_TYPE_ISO14443_3A: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type 3A'"); + } break; + case TARGET_TYPE_ISO14443_3B: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type 3B'"); + } break; + case TARGET_TYPE_ISO14443_4: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type 4A'"); + } break; + case TARGET_TYPE_FELICA: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type F'"); + } break; + case TARGET_TYPE_ISO15693: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type V'"); + } break; + case TARGET_TYPE_NDEF: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type NDEF'"); + } break; + case TARGET_TYPE_NDEF_FORMATABLE: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type Formatable'"); + } break; + case TARGET_TYPE_MIFARE_CLASSIC: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type A - Mifare Classic'"); + } break; + case TARGET_TYPE_MIFARE_UL: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type A - Mifare Ul'"); + } break; + case TARGET_TYPE_KOVIO_BARCODE: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type A - Kovio Barcode'"); + } break; + case TARGET_TYPE_ISO14443_3A_3B: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type A/B'"); + } break; + default: + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type %d (Unknown or not supported)'\n", TagInfo->technology); + } break; + } + /*32 is max UID len (Kovio tags)*/ + if((0x00 != TagInfo->uid_length) && (32 >= TagInfo->uid_length)) + { + char buffer [100]; + int cx = 0; + + if(4 == TagInfo->uid_length || 7 == TagInfo->uid_length || 10 == TagInfo->uid_length) + { + cx += snprintf(buffer + cx, sizeof(buffer) - cx, "NFCID1 : \t'"); + } + else if(8 == TagInfo->uid_length) + { + cx += snprintf(buffer + cx, sizeof(buffer) - cx, "NFCID2 : \t'"); + } + else + { + cx += snprintf(buffer + cx, sizeof(buffer) - cx, "UID : \t'"); + } + + BufferPrintBytes(buffer + cx, sizeof(buffer) - cx, (unsigned char*) TagInfo->uid, TagInfo->uid_length); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s'", buffer); + } +} /** ------------------------------------------------------------------------ */ /** ------------------------------------------------------------------------ */ @@ -65,94 +269,10 @@ static void onTagDeparture(void) TagInfo = NULL; } -/** ------------------------------------------------------------------------ */ -/** ------------------------------------------------------------------------ */ - - -/** - * @brief Scan all available I2C buses to find PN532 devices. - * - * @param context NFC context. - * @param connstrings array of 'nfc_connstring' buffer (allocated by caller). It is used to store the - * connection info strings of all I2C PN532 devices found. - * @param connstrings_len length of the connstrings array. - * @return number of PN532 devices found on all I2C buses. - */ -static size_t -pn71xx_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len) -{ - size_t device_found = 0; - - if (nfcManager_doInitialize() == 0) { - nfc_connstring connstring = "pn71xx"; - memcpy(connstrings[device_found++], connstring, sizeof(nfc_connstring)); - } - - return device_found; -} - -/** - * @brief Close I2C connection to the PN532 device. - * - * @param pnd pointer on the device to close. - */ -static void -pn71xx_close(nfc_device *pnd) -{ - nfcManager_disableDiscovery(); - nfcManager_deregisterTagCallback(); - nfcManager_doDeinitialize(); - - nfc_device_free(pnd); -} - -/** - * @brief Open an I2C connection to the PN532 device. - * - * @param context NFC context. - * @param connstring connection info to the device - * @return pointer to the device, or NULL in case of error. - */ -static nfc_device * -pn71xx_open(const nfc_context *context, const nfc_connstring connstring) -{ - nfc_device *pnd; - - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "open: %s", connstring); - - pnd = nfc_device_new(context, connstring); - if (!pnd) { - perror("malloc"); - return NULL; - } - - pnd->driver = &pn71xx_driver; - strcpy(pnd->name, "pn71xx-device"); - strcpy(pnd->connstring, connstring); - - - TagCB.onTagArrival = onTagArrival; - TagCB.onTagDeparture = onTagDeparture; - nfcManager_registerTagCallback(&TagCB); - - nfcManager_enableDiscovery(DEFAULT_NFA_TECH_MASK, 1, 0, 0); - - - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "wait 2 seconds for polling"); - sleep(2); - - return pnd; -} - - - -/** ------------------------------------------------------------------------ */ -/** ------------------------------------------------------------------------ */ - - static int pn71xx_initiator_init(struct nfc_device *pnd) { + if (pnd == NULL) return NFC_EIO; return NFC_SUCCESS; } @@ -162,6 +282,8 @@ pn71xx_initiator_select_passive_target(struct nfc_device *pnd, const uint8_t *pbtInitData, const size_t szInitData, nfc_target *pnt) { + if (pnd == NULL) return NFC_EIO; + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "select_passive_target"); if (TagInfo) { @@ -171,7 +293,7 @@ pn71xx_initiator_select_passive_target(struct nfc_device *pnd, nttmp.nm = nm; void* uidPtr = NULL; - int maxLen = 0; + unsigned int maxLen = 0; switch (nm.nmt) { case NMT_ISO14443A: @@ -257,6 +379,7 @@ pn71xx_initiator_select_passive_target(struct nfc_device *pnd, static int pn71xx_initiator_deselect_target(struct nfc_device *pnd) { + if (pnd == NULL) return NFC_EIO; log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "deselect_passive_target"); return NFC_SUCCESS; } @@ -266,16 +389,16 @@ static int pn71xx_initiator_transceive_bytes(struct nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, uint8_t *pbtRx, const size_t szRx, int timeout) { + if (pnd == NULL) return NFC_EIO; log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "transceive_bytes timeout=%d", timeout); - if (!TagInfo) - return NFC_EINVARG; + if (!TagInfo) return NFC_EINVARG; char buffer[500]; BufferPrintBytes(buffer, sizeof(buffer), pbtTx, szTx); log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "===> %s", buffer); - int received = nfcTag_transceive(TagInfo->handle, pbtTx, szTx, pbtRx, szRx, 500); + int received = nfcTag_transceive(TagInfo->handle, (uint8_t *) pbtTx, szTx, pbtRx, szRx, 500); if (received <= 0) return NFC_EIO; @@ -294,12 +417,12 @@ pn71xx_initiator_poll_target(struct nfc_device *pnd, static int periodFactor = 150000; int period = uiPeriod * periodFactor; + if (pnd == NULL) return 0; + for (int j = 0; j < uiPollNr; j++) { - for (int i = 0; i < szModulations; i++) { + for (unsigned int i = 0; i < szModulations; i++) { const nfc_modulation nm = pnmModulations[i]; - //log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "check %s", str_nfc_modulation_type(nm.nmt)); - nfc_target nt; int res = pn71xx_initiator_select_passive_target(pnd, nm, 0, 0, &nt); if (res > 0 && pnt) { @@ -316,32 +439,27 @@ pn71xx_initiator_poll_target(struct nfc_device *pnd, static int pn71xx_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) { - if (pnt) { - - } - - // 0 = true + if ((pnd == NULL) || (pnt == NULL)) return 1; return !TagInfo; } /** ------------------------------------------------------------------------ */ /** ------------------------------------------------------------------------ */ - - static int pn71xx_get_supported_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type **const supported_mt) { - //log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "get_supported_modulation mode=%d", mode); - switch (mode) { - case N_TARGET: - *supported_mt = (nfc_modulation_type *)pn71xx_supported_modulation_as_target; - break; - case N_INITIATOR: - *supported_mt = (nfc_modulation_type *)pn71xx_supported_modulation_as_initiator; - break; - default: - return NFC_EINVARG; + if (pnd == NULL) return NFC_EIO; + + switch (mode) { + case N_TARGET: + *supported_mt = (nfc_modulation_type *)pn71xx_supported_modulation_as_target; + break; + case N_INITIATOR: + *supported_mt = (nfc_modulation_type *)pn71xx_supported_modulation_as_initiator; + break; + default: + return NFC_EINVARG; } return NFC_SUCCESS; } @@ -349,29 +467,32 @@ pn71xx_get_supported_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_ static int pn71xx_get_supported_baud_rate(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br) { - switch (nmt) { - case NMT_FELICA: - *supported_br = (nfc_baud_rate *)pn71xx_felica_supported_baud_rates; - break; - case NMT_ISO14443A: - *supported_br = (nfc_baud_rate *)pn71xx_iso14443a_supported_baud_rates; - break; - case NMT_ISO14443B: - case NMT_ISO14443BI: - case NMT_ISO14443B2SR: - case NMT_ISO14443B2CT: - *supported_br = (nfc_baud_rate *)pn71xx_iso14443b_supported_baud_rates; - break; - case NMT_JEWEL: - *supported_br = (nfc_baud_rate *)pn71xx_jewel_supported_baud_rates; - break; - case NMT_DEP: - *supported_br = (nfc_baud_rate *)pn71xx_dep_supported_baud_rates; - break; - default: - return NFC_EINVARG; - } - return NFC_SUCCESS; + if (pnd == NULL) return NFC_EIO; + if (mode) {} + + switch (nmt) { + case NMT_FELICA: + *supported_br = (nfc_baud_rate *)pn71xx_felica_supported_baud_rates; + break; + case NMT_ISO14443A: + *supported_br = (nfc_baud_rate *)pn71xx_iso14443a_supported_baud_rates; + break; + case NMT_ISO14443B: + case NMT_ISO14443BI: + case NMT_ISO14443B2SR: + case NMT_ISO14443B2CT: + *supported_br = (nfc_baud_rate *)pn71xx_iso14443b_supported_baud_rates; + break; + case NMT_JEWEL: + *supported_br = (nfc_baud_rate *)pn71xx_jewel_supported_baud_rates; + break; + case NMT_DEP: + *supported_br = (nfc_baud_rate *)pn71xx_dep_supported_baud_rates; + break; + default: + return NFC_EINVARG; + } + return NFC_SUCCESS; } /** ------------------------------------------------------------------------ */ @@ -380,14 +501,14 @@ pn71xx_get_supported_baud_rate(nfc_device *pnd, const nfc_mode mode, const nfc_m static int pn71xx_set_property_bool(struct nfc_device *pnd, const nfc_property property, const bool bEnable) { - //log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "set_property_bool"); + if (pnd == NULL) return NFC_EIO; return NFC_SUCCESS; } static int pn71xx_set_property_int(struct nfc_device *pnd, const nfc_property property, const int value) { - //log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "set_property_int"); + if (pnd == NULL) return NFC_EIO; return NFC_SUCCESS; } @@ -396,6 +517,8 @@ pn71xx_get_information_about(nfc_device *pnd, char **pbuf) { static const char* info = "PN71XX nfc driver using libnfc-nci userspace library"; size_t buflen = strlen(info) + 1; + + if (pnd == NULL) return NFC_EIO; *pbuf = malloc(buflen); memcpy(*pbuf, info, buflen); @@ -411,32 +534,32 @@ pn71xx_get_information_about(nfc_device *pnd, char **pbuf) static int pn71xx_abort_command(nfc_device *pnd) { + if (pnd == NULL) return NFC_EIO; log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "abort_command"); - return NFC_SUCCESS; + return NFC_SUCCESS; } static int pn71xx_idle(struct nfc_device *pnd) { + if (pnd == NULL) return NFC_EIO; log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "idle"); - return NFC_SUCCESS; + return NFC_SUCCESS; } static int pn71xx_PowerDown(struct nfc_device *pnd) { + if (pnd == NULL) return NFC_EIO; log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "PowerDown"); - return NFC_SUCCESS; + return NFC_SUCCESS; } /** ------------------------------------------------------------------------ */ /** ------------------------------------------------------------------------ */ - - - const struct nfc_driver pn71xx_driver = { .name = PN71XX_DRIVER_NAME, - .scan_type = INTRUSIVE, + .scan_type = NOT_INTRUSIVE, .scan = pn71xx_scan, .open = pn71xx_open, .close = pn71xx_close, @@ -454,17 +577,17 @@ const struct nfc_driver pn71xx_driver = { .initiator_transceive_bits_timed = NULL, .initiator_target_is_present = pn71xx_initiator_target_is_present, - .target_init = NULL, - .target_send_bytes = NULL, - .target_receive_bytes = NULL, - .target_send_bits = NULL, - .target_receive_bits = NULL, + .target_init = NULL, + .target_send_bytes = NULL, + .target_receive_bytes = NULL, + .target_send_bits = NULL, + .target_receive_bits = NULL, - .device_set_property_bool = pn71xx_set_property_bool, - .device_set_property_int = pn71xx_set_property_int, - .get_supported_modulation = pn71xx_get_supported_modulation, - .get_supported_baud_rate = pn71xx_get_supported_baud_rate, - .device_get_information_about = pn71xx_get_information_about, + .device_set_property_bool = pn71xx_set_property_bool, + .device_set_property_int = pn71xx_set_property_int, + .get_supported_modulation = pn71xx_get_supported_modulation, + .get_supported_baud_rate = pn71xx_get_supported_baud_rate, + .device_get_information_about = pn71xx_get_information_about, .abort_command = pn71xx_abort_command, .idle = pn71xx_idle, From f9f03fa7fade3738a6ac8160268920994001a63f Mon Sep 17 00:00:00 2001 From: jgeslin Date: Thu, 12 Jan 2017 09:53:40 +0100 Subject: [PATCH 03/12] Debug dedicated implementation removed --- libnfc/nfc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libnfc/nfc.c b/libnfc/nfc.c index df739c5..968a3ef 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -326,10 +326,8 @@ size_t nfc_list_devices(nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len) { size_t device_found = 0; - printf("nfc_list_devices()\n"); #ifdef CONFFILES - printf("nfc_list_devices()- context->user_defined_device_count=%d\n", context->user_defined_device_count); // Load manually configured devices (from config file and env variables) // TODO From env var... for (uint32_t i = 0; i < context->user_defined_device_count; i++) { @@ -351,7 +349,6 @@ nfc_list_devices(nfc_context *context, nfc_connstring connstrings[], const size_ setenv("LIBNFC_LOG_LEVEL", "0", 1); #endif // ENVVARS - printf("nfc_list_devices()- open\n"); pnd = nfc_open(context, context->user_defined_devices[i].connstring); #ifdef ENVVARS From 7a0a469c8a0f75e564beff2e1b0168454b7e6f3f Mon Sep 17 00:00:00 2001 From: Hanno Heinrichs Date: Sun, 17 Sep 2017 19:55:53 +0200 Subject: [PATCH 04/12] add more verbosity to RATS handling --- utils/nfc-mfclassic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index bc3fe6c..847f553 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -683,6 +683,7 @@ main(int argc, const char *argv[]) // Testing RATS int res; if ((res = get_rats()) > 0) { + printf("RATS support: yes\n"); if ((res >= 10) && (abtRx[5] == 0xc1) && (abtRx[6] == 0x05) && (abtRx[7] == 0x2f) && (abtRx[8] == 0x2f) && ((nt.nti.nai.abtAtqa[1] & 0x02) == 0x00)) { @@ -694,7 +695,8 @@ main(int argc, const char *argv[]) && (abtRx[7] == 0x19) && (abtRx[8] == 0x10)) { magic2 = true; } - } + } else + printf("RATS support: no\n"); printf("Guessing size: seems to be a %lu-byte card\n", (uiBlocks + 1) * sizeof(mifare_classic_block)); if (bUseKeyFile) { From 793d5adde60e96e0d24845ae34992aec19a3ede6 Mon Sep 17 00:00:00 2001 From: Mikolaj Stawiski <26871388+stawiski@users.noreply.github.com> Date: Sun, 25 Nov 2018 13:48:04 +1100 Subject: [PATCH 05/12] Fixed format warnings. --- libnfc/target-subr.c | 2 +- utils/nfc-mfclassic.c | 2 +- utils/nfc-mfultralight.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libnfc/target-subr.c b/libnfc/target-subr.c index 97e2882..61cedfd 100644 --- a/libnfc/target-subr.c +++ b/libnfc/target-subr.c @@ -503,7 +503,7 @@ snprint_nfc_barcode_info(char *dst, size_t size, const nfc_barcode_info *pnti, b { (void) verbose; int off = 0; - off += snprintf(dst + off, size - off, " Size (bits): %lu\n", pnti->szDataLen * 8); + off += snprintf(dst + off, size - off, " Size (bits): %lu\n", (unsigned long)(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]); diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index bc3fe6c..3f22c61 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -695,7 +695,7 @@ main(int argc, const char *argv[]) magic2 = true; } } - printf("Guessing size: seems to be a %lu-byte card\n", (uiBlocks + 1) * sizeof(mifare_classic_block)); + printf("Guessing size: seems to be a %lu-byte card\n", (unsigned long)((uiBlocks + 1) * sizeof(mifare_classic_block))); if (bUseKeyFile) { FILE *pfKeys = fopen(argv[5], "rb"); diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 3fe2100..5e71a3a 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -714,7 +714,7 @@ main(int argc, const char *argv[]) size_t szDump; if (((szDump = fread(&mtDump, 1, sizeof(mtDump), pfDump)) != iDumpSize && !bPart) || szDump <= 0) { - ERR("Could not read from dump file or size mismatch: %s (read %lu, expected %lu)\n", argv[2], szDump, iDumpSize); + ERR("Could not read from dump file or size mismatch: %s (read %lu, expected %lu)\n", argv[2], (unsigned long)szDump, (unsigned long)iDumpSize); fclose(pfDump); exit(EXIT_FAILURE); } From a4af2be66c85b1846327b2ab73bb4c63c7b3b40f Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 17 Jul 2019 22:29:09 +0200 Subject: [PATCH 06/12] Fix PN533 hardcoded ednpoints table --- libnfc/drivers/pn53x_usb.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index 18c51fc..56c6eba 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -132,13 +132,13 @@ struct pn53x_usb_supported_device { }; const struct pn53x_usb_supported_device pn53x_usb_supported_devices[] = { - { 0x04CC, 0x0531, NXP_PN531, "Philips / PN531", 0, 0, 0 }, - { 0x04CC, 0x2533, NXP_PN533, "NXP / PN533", 0x04, 0x84, 40 }, - { 0x04E6, 0x5591, SCM_SCL3711, "SCM Micro / SCL3711-NFC&RW", 0x04, 0x84, 40 }, - { 0x04E6, 0x5594, SCM_SCL3712, "SCM Micro / SCL3712-NFC&RW", 0, 0, 0 }, - { 0x054c, 0x0193, SONY_PN531, "Sony / PN531", 0, 0, 0 }, - { 0x1FD3, 0x0608, ASK_LOGO, "ASK / LoGO", 0x04, 0x84, 40 }, - { 0x054C, 0x02E1, SONY_RCS360, "Sony / FeliCa S360 [PaSoRi]", 0, 0, 0 } + { 0x04CC, 0x0531, NXP_PN531, "Philips / PN531", 0x84, 0x04, 0x40 }, + { 0x04CC, 0x2533, NXP_PN533, "NXP / PN533", 0x84, 0x04, 0x40 }, + { 0x04E6, 0x5591, SCM_SCL3711, "SCM Micro / SCL3711-NFC&RW", 0x84, 0x04, 0x40 }, + { 0x04E6, 0x5594, SCM_SCL3712, "SCM Micro / SCL3712-NFC&RW", 0, 0, 0 }, // to check on real device + { 0x054c, 0x0193, SONY_PN531, "Sony / PN531", 0x84, 0x04, 0x40 }, + { 0x1FD3, 0x0608, ASK_LOGO, "ASK / LoGO", 0x84, 0x04, 0x40 }, + { 0x054C, 0x02E1, SONY_RCS360, "Sony / FeliCa S360 [PaSoRi]", 0x84, 0x04, 0x40 } }; // PN533 USB descriptors backup buffers @@ -421,6 +421,11 @@ pn53x_usb_open(const nfc_context *context, const nfc_connstring connstring) // Open the USB device if ((data.pudh = usb_open(dev)) == NULL) continue; + + //To retrieve real USB endpoints configuration: + //pn53x_usb_get_end_points(dev, &data); + //printf("DEBUG ENDPOINTS In:0x%x Out:0x%x Size:0x%x\n", data.uiEndPointIn, data.uiEndPointOut, data.uiMaxPacketSize); + // Retrieve end points, using hardcoded defaults if available // or using the descriptors otherwise. if (pn53x_usb_get_end_points_default(dev, &data) == false) { From 48d5f6b666a3453b822316b56442d2f86d94c640 Mon Sep 17 00:00:00 2001 From: Adam Oleksy Date: Fri, 19 Jul 2019 14:34:17 +0200 Subject: [PATCH 07/12] Generate config.h into build instead source directory. --- CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ad92d7..576f6e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,14 +18,15 @@ SET(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") # config.h IF(WIN32) - CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake/config_windows.h.cmake ${CMAKE_CURRENT_SOURCE_DIR}/config.h) + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake/config_windows.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) SET(LIBNFC_SYSCONFDIR "${CMAKE_INSTALL_PREFIX}/config" CACHE PATH "libnfc configuration directory") INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/contrib/win32) ELSE(WIN32) SET(_XOPEN_SOURCE 600) SET(SYSCONFDIR "/etc" CACHE PATH "System configuration directory") - CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake/config_posix.h.cmake ${CMAKE_CURRENT_SOURCE_DIR}/config.h) + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake/config_posix.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) ENDIF(WIN32) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) ADD_DEFINITIONS("-DHAVE_CONFIG_H") From c109d37783c0401c324631a53370a07a7c4fa093 Mon Sep 17 00:00:00 2001 From: quantum-x Date: Mon, 19 Aug 2019 19:04:52 +0200 Subject: [PATCH 08/12] Update nfc-mfultralight.c Adding support for "DirectWrite" Ultralight tags. - The latest generation of "Magic" Ultralight tags support DirectWrite to B0. - Several versions of these cards are bricked if the older 'unlock' command is issued to the card. - To avoid this, when detecting if a card is magic, we attempt to modify B0 directly. If this fails, we proceed with an unlock command. --- utils/nfc-mfultralight.c | 84 ++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 3fe2100..8ae641f 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -10,6 +10,7 @@ * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: * Copyright (C) 2013-2018 Adam Laurie + * Copyright (C) 2018-2019 Daniele Bruneo * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -290,50 +291,48 @@ unlock_card(void) return true; } -static bool check_magic() -{ - bool bFailure = false; - int uid_data; +static bool check_magic() { + // Firstly try to directly read and re-write the first three pages + // if this fail try to unlock with chinese magic backdoor - for (uint32_t page = 0; page <= 1; page++) { - // Show if the readout went well - if (bFailure) { - // When a failure occured we need to redo the anti-collision - if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { - ERR("tag was removed"); - return false; - } - bFailure = false; - } - - uid_data = 0x00000000; - - memcpy(mp.mpd.abtData, &uid_data, sizeof uid_data); - memset(mp.mpd.abtData + 4, 0, 12); - - //Force the write without checking for errors - otherwise the writes to the sector 0 seem to complain - nfc_initiator_mifare_cmd(pnd, MC_WRITE, page, &mp); - } - - //Check that the ID is now set to 0x000000000000 + bool directWrite = true; + // Try to read pages 0, 1, 2 + uint8_t original_b0[12]; + printf("Checking if UL badge is DirectWrite...\n"); if (nfc_initiator_mifare_cmd(pnd, MC_READ, 0, &mp)) { - //printf("%u", mp.mpd.abtData); - bool result = true; - for (int i = 0; i <= 7; i++) { - if (mp.mpd.abtData[i] != 0x00) result = false; + memcpy(original_b0, mp.mpd.abtData, 12); + printf(" Original Block 0 (Pages 0-2): "); + for(int i=0;i<12;i++){ + printf("%02x", original_b0[i]); } - - if (result) { - return true; - } - + printf("\n"); + printf(" Original UID: %02x%02x%02x%02x%02x%02x%02x\n", + original_b0[0], original_b0[1], original_b0[2], original_b0[4], original_b0[5], original_b0[6], original_b0[7]); + } else { + printf("!\nError: unable to read block 0x%02x\n", 0); + directWrite = false; } - - //Initially check if we can unlock via the MF method - if (unlock_card()) { + printf(" Attempt to write Block 0 (pages 0-2) ...\n"); + for (uint32_t page = 0; page <= 2; page++) { + printf(" Writing Page %i:", page); + memcpy(mp.mpd.abtData, original_b0 + page*4, 4); + for(int i=0;i<4;i++){ + printf(" %02x", mp.mpd.abtData[i]); + } + printf("\n"); + if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, page, &mp)) { + printf(" Failure writing Page %i\n", page); + directWrite = false; + break; + } + } + if(directWrite){ + printf(" Block 0 written successfully\n"); + printf("Card is DirectWrite\n"); return true; } else { - return false; + printf("Card is not DirectWrite\n"); + return unlock_card(); } } @@ -383,9 +382,9 @@ write_card(bool write_otp, bool write_lock, bool write_dyn_lock, bool write_uid) write_uid = ((buffer[0] == 'y') || (buffer[0] == 'Y')); } - printf("Writing %d pages |", uiBlocks); /* We may need to skip 2 first pages. */ if (!write_uid) { + printf("Writing %d pages |", uiBlocks); printf("ss"); uiSkippedPages = 2; } else { @@ -393,6 +392,7 @@ write_card(bool write_otp, bool write_lock, bool write_dyn_lock, bool write_uid) printf("\nUnable to unlock card - are you sure the card is magic?\n"); return false; } + printf("Writing %d pages |", uiBlocks); } for (uint32_t page = uiSkippedPages; page < uiBlocks; page++) { @@ -527,7 +527,7 @@ main(int argc, const char *argv[]) bool bFilename = false; FILE *pfDump; - if (argc < 3) { + if (argc == 0) { print_usage(argv); exit(EXIT_FAILURE); } @@ -580,7 +580,7 @@ main(int argc, const char *argv[]) } } } - if (! bFilename) { + if (iAction != 3 && !bFilename) { ERR("Please supply a Mifare Dump filename"); exit(EXIT_FAILURE); } @@ -650,7 +650,7 @@ main(int argc, const char *argv[]) if (get_ev1_version()) { if (!bPWD) printf("WARNING: Tag is EV1 or NTAG - PASSWORD may be required\n"); - if (abtRx[6] == 0x0b) { + if (abtRx[6] == 0x0b || abtRx[6] == 0x00) { printf("EV1 type: MF0UL11 (48 bytes)\n"); uiBlocks = 20; // total number of 4 byte 'pages' iDumpSize = uiBlocks * 4; From fbdbe6eff32ae5c01a6ea707a4e908c0cb1a4ebe Mon Sep 17 00:00:00 2001 From: quantum-x Date: Mon, 19 Aug 2019 19:07:18 +0200 Subject: [PATCH 09/12] Update nfc-mfclassic.c Adding support for extended Magic cards: - DirectWrite cards - One Time Write cards Direct Write cards support modification of B0 directly, without any unlock codes. When we are attempting to detect if a card is 'magic', we will attempt to modify B0 directly as an initial check. One Time Write cards support modification of B0 directly, one time only. They do not respond to magic commands, but have a fixed UID coming out of the factory. We now detect this UID, and if so, deem the card 'magic'. --- utils/nfc-mfclassic.c | 251 +++++++++++++++++++++++++++++++++++------- 1 file changed, 210 insertions(+), 41 deletions(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index bc3fe6c..ba07b6f 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -10,6 +10,7 @@ * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: * Copyright (C) 2011-2013 Adam Laurie + * Copyright (C) 2018-2019 Danielle Bruneo * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -70,7 +71,9 @@ static bool bForceKeyFile; static bool bTolerateFailures; static bool bFormatCard; static bool magic2 = false; +static bool magic3 = false; static bool unlocked = false; +static bool bForceSizeMismatch; static uint8_t uiBlocks; static uint8_t keys[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -208,10 +211,18 @@ authenticate(uint32_t uiBlock) // Try to authenticate for the current sector if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) return true; - } + } else if (magic3) { + //If it's a One Time Write card, we're gonna authenticate with the default keys + memcpy(mp.mpa.abtKey, default_key, sizeof(default_key)); + + + // Try to authenticate for the current sector + if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) { + return true; + } // If formatting or not using key file, try to guess the right key - if (bFormatCard || !bUseKeyFile) { + } else if (bFormatCard || !bUseKeyFile) { for (size_t key_index = 0; key_index < num_keys; key_index++) { memcpy(mp.mpa.abtKey, keys + (key_index * 6), 6); if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) { @@ -352,10 +363,17 @@ read_card(int read_unlocked) if (read_unlocked) { memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, sizeof(mtDump.amb[iBlock].mbd.abtData)); } else { - // Copy the keys over from our key dump and store the retrieved access bits - memcpy(mtDump.amb[iBlock].mbt.abtKeyA, mtKeys.amb[iBlock].mbt.abtKeyA, sizeof(mtDump.amb[iBlock].mbt.abtKeyA)); - memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits, sizeof(mtDump.amb[iBlock].mbt.abtAccessBits)); - memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, sizeof(mtDump.amb[iBlock].mbt.abtKeyB)); + //If we're using a One Time Write ('Magic 3') Badge - we'll use default keys + ACL + if (magic3) { + memcpy(mtDump.amb[iBlock].mbt.abtKeyA, default_key, sizeof(default_key)); + memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits, sizeof(mtDump.amb[iBlock].mbt.abtAccessBits)); + memcpy(mtDump.amb[iBlock].mbt.abtKeyB, default_key, sizeof(default_key)); + } else { + // Copy the keys over from our key dump and store the retrieved access bits + memcpy(mtDump.amb[iBlock].mbt.abtKeyA, mtKeys.amb[iBlock].mbt.abtKeyA, sizeof(mtDump.amb[iBlock].mbt.abtKeyA)); + memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits, sizeof(mtDump.amb[iBlock].mbt.abtAccessBits)); + memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, sizeof(mtDump.amb[iBlock].mbt.abtKeyB)); + } } } else { printf("!\nfailed to read trailer block 0x%02x\n", iBlock); @@ -392,6 +410,7 @@ write_card(int write_block_zero) bool bFailure = false; uint32_t uiWriteBlocks = 0; + //Determine if we have to unlock the card if (write_block_zero) { //If the user is attempting an unlocked write, but has a direct-write type magic card, they don't //need to use the W mode. We'll trigger a warning and let them proceed. @@ -407,8 +426,8 @@ write_card(int write_block_zero) } printf("Writing %d blocks |", uiBlocks + 1); - // Write the card from begin to end; - for (uiBlock = 0; uiBlock <= uiBlocks; uiBlock++) { + // Completely write the card, end to start, but skipping block 0 + for (uiBlock = 4; uiBlock <= uiBlocks; uiBlock++) { // Authenticate everytime we reach the first sector of a new block if (is_first_block(uiBlock)) { if (bFailure) { @@ -423,44 +442,116 @@ write_card(int write_block_zero) fflush(stdout); // Try to authenticate for the current sector - if (!write_block_zero && !authenticate(uiBlock) && !bTolerateFailures) { - printf("!\nError: authentication failed for block %02x\n", uiBlock); - return false; + // If we are are writing to a chinese magic card, we've already unlocked + // If we're writing to a One Time Write card, we need to authenticate + // If we're writing something else, we'll need to authenticate + if ((write_block_zero && magic3) || !write_block_zero) { + if (!authenticate(uiBlock) && !bTolerateFailures) { + printf("!\nError: authentication failed for block %02x\n", uiBlock); + return false; + } + } + + if (is_trailer_block(uiBlock)) { + if (bFormatCard) { + // Copy the default key and reset the access bits + memcpy(mp.mpt.abtKeyA, default_key, sizeof(mp.mpt.abtKeyA)); + memcpy(mp.mpt.abtAccessBits, default_acl, sizeof(mp.mpt.abtAccessBits)); + memcpy(mp.mpt.abtKeyB, default_key, sizeof(mp.mpt.abtKeyB)); + } else { + // Copy the keys over from our key dump and store the retrieved access bits + memcpy(mp.mpt.abtKeyA, mtDump.amb[uiBlock].mbt.abtKeyA, sizeof(mp.mpt.abtKeyA)); + memcpy(mp.mpt.abtAccessBits, mtDump.amb[uiBlock].mbt.abtAccessBits, sizeof(mp.mpt.abtAccessBits)); + memcpy(mp.mpt.abtKeyB, mtDump.amb[uiBlock].mbt.abtKeyB, sizeof(mp.mpt.abtKeyB)); + } + + // Try to write the trailer + if (nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp) == false) { + printf("failed to write trailer block %d \n", uiBlock); + bFailure = true; + } + } else { + // The first block 0x00 is read only, skip this + if (uiBlock == 0 && !write_block_zero && !magic2) + continue; + + // Make sure a earlier write did not fail + if (!bFailure) { + // Try to write the data block + if (bFormatCard && uiBlock) + + memset(mp.mpd.abtData, 0x00, sizeof(mp.mpd.abtData)); + else + memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData)); + // do not write a block 0 with incorrect BCC - card will be made invalid! + if (uiBlock == 0) { + if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) { + printf("!\nError: incorrect BCC in MFD file!\n"); + printf("Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]); + return false; + } + } + if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp)) { + bFailure = true; + printf("Failure to write to data block %i\n", uiBlock); + } + + } else { + printf("Failure during write process.\n"); + } } } + // Show if the write went well for each block + print_success_or_failure(bFailure, &uiWriteBlocks); + if ((! bTolerateFailures) && bFailure) + return false; + } - if (is_trailer_block(uiBlock)) { - if (bFormatCard) { - // Copy the default key and reset the access bits - memcpy(mp.mpt.abtKeyA, default_key, sizeof(mp.mpt.abtKeyA)); - memcpy(mp.mpt.abtAccessBits, default_acl, sizeof(mp.mpt.abtAccessBits)); - memcpy(mp.mpt.abtKeyB, default_key, sizeof(mp.mpt.abtKeyB)); - } else { - // Copy the keys over from our key dump and store the retrieved access bits - memcpy(mp.mpt.abtKeyA, mtDump.amb[uiBlock].mbt.abtKeyA, sizeof(mp.mpt.abtKeyA)); - memcpy(mp.mpt.abtAccessBits, mtDump.amb[uiBlock].mbt.abtAccessBits, sizeof(mp.mpt.abtAccessBits)); - memcpy(mp.mpt.abtKeyB, mtDump.amb[uiBlock].mbt.abtKeyB, sizeof(mp.mpt.abtKeyB)); + //Write Block 0 if necessary + if (write_block_zero || magic2 || magic3) { + for (uiBlock = 0; uiBlock < 4; uiBlock++) { + + // The first block 0x00 is read only, skip this + if (uiBlock == 0) { + //If the card is not magic, we're gonna skip over + if (write_block_zero || magic2 || magic3) { + //NOP + } else { + continue; + } + } + + if (is_first_block(uiBlock)) { + if (bFailure) { + // When a failure occured we need to redo the anti-collision + if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { + printf("!\nError: tag was removed\n"); + return false; + } + bFailure = false; + } + + fflush(stdout); + // Try to authenticate for the current sector + // If we are are writing to a chinese magic card, we've already unlocked + // If we're writing to a One Time Write, we need to authenticate + // If we're writing something else, we'll need to authenticate + if ((write_block_zero && magic3) || !write_block_zero) { + if (!authenticate(uiBlock) && !bTolerateFailures) { + printf("!\nError: authentication failed for block %02x\n", uiBlock); + return false; + } + } } - // Try to write the trailer - if (nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp) == false) { - printf("failed to write trailer block %d \n", uiBlock); - bFailure = true; - } - } else { - // The first block 0x00 is read only, skip this - if (uiBlock == 0 && !write_block_zero && !magic2) - continue; - - - // Make sure a earlier write did not fail + // Make sure a earlier write did not fail if (!bFailure) { - // Try to write the data block + // Try to write the data block if (bFormatCard && uiBlock) memset(mp.mpd.abtData, 0x00, sizeof(mp.mpd.abtData)); else memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData)); - // do not write a block 0 with incorrect BCC - card will be made invalid! + // do not write a block 0 with incorrect BCC - card will be made invalid! if (uiBlock == 0) { if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) { printf("!\nError: incorrect BCC in MFD file!\n"); @@ -468,15 +559,24 @@ write_card(int write_block_zero) return false; } } - if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp)) + if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp)) { bFailure = true; + printf("Failure to write to data block %i\n", uiBlock); + } + + } else { + printf("Failure during write process.\n"); } + + // Show if the write went well for each block + print_success_or_failure(bFailure, &uiWriteBlocks); + if ((! bTolerateFailures) && bFailure) + return false; + } - // Show if the write went well for each block - print_success_or_failure(bFailure, &uiWriteBlocks); - if ((!bTolerateFailures) && bFailure) - return false; + } + printf("|\n"); printf("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1); fflush(stdout); @@ -505,6 +605,7 @@ print_usage(const char *pcProgramName) printf(" - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n"); printf(" - MiFare Dump (MFD) that contain the keys (optional)\n"); printf(" f - Force using the keyfile even if UID does not match (optional)\n"); + printf("Examples: \n\n"); printf(" Read card to file, using key A:\n\n"); printf(" %s r a u mycard.mfd\n\n", pcProgramName); @@ -519,6 +620,54 @@ print_usage(const char *pcProgramName) printf(" %s r a U01ab23cd mycard.mfd\n\n", pcProgramName); } + +bool is_directwrite(){ + printf("Checking if Badge is DirectWrite...\n"); + + // Set default keys + memcpy(mtDump.amb[0].mbt.abtKeyA, default_key, sizeof(default_key)); + memcpy(mtDump.amb[0].mbt.abtAccessBits, default_acl, sizeof(mp.mpt.abtAccessBits)); + memcpy(mtDump.amb[0].mbt.abtKeyB, default_key, sizeof(default_key)); + + // Temporarly override bUseKeyFile + bool orig_bUseKeyFile=bUseKeyFile; + bUseKeyFile=false; + // Try to authenticate for the current sector + if (!authenticate(0)) { + printf("!\nError: authentication failed for block 0x%02x\n", 0); + bUseKeyFile=orig_bUseKeyFile; + return false; + } + // restore bUseKeyFile + bUseKeyFile=orig_bUseKeyFile; + + // Try to read block 0 + uint8_t original_b0[16]; + if (nfc_initiator_mifare_cmd(pnd, MC_READ, 0, &mp)) { + memcpy(original_b0, mp.mpd.abtData, sizeof(mp.mpd.abtData)); + printf(" Original Block 0: "); + for(int i=0;i<16;i++){ + printf("%02x", original_b0[i]); + } + printf("\n"); + printf(" Original UID: %02x%02x%02x%02x\n", + original_b0[0], original_b0[1], original_b0[2], original_b0[3]); + } else { + printf("!\nError: unable to read block 0x%02x\n", 0); + return false; + } + + printf(" Attempt to write Block 0 ...\n"); + memcpy(mp.mpd.abtData, original_b0, sizeof(original_b0)); + if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, 0, &mp)) { + printf("Failure to write to data block %i\n", 0); + return false; + } + printf(" Block 0 written successfully\n"); + + return true; +} + int main(int argc, const char *argv[]) { @@ -697,6 +846,26 @@ main(int argc, const char *argv[]) } printf("Guessing size: seems to be a %lu-byte card\n", (uiBlocks + 1) * sizeof(mifare_classic_block)); + //If size is 4k check for direct-write card + if (uiBlocks == 0xff) { + if (is_directwrite()){ + printf("Card is DirectWrite\n"); + magic3=true; + unlock=0; + } else { + printf("Card is not DirectWrite\n"); + } + } + + //Check to see if we have a One Time Write badge (magic3) + if (pbtUID[0] == 0xaa && pbtUID[1] == 0x55 && + pbtUID[2] == 0xc3 && pbtUID[3] == 0x96) { + printf("Card appears to be a One Time Write Card..\n"); + magic3 = true; + unlock = 0; + } + + if (bUseKeyFile) { FILE *pfKeys = fopen(argv[5], "rb"); if (pfKeys == NULL) { From 454a8c4d70d14e9fc5fdc625e11c9f6769cd5e83 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 19 Aug 2019 19:48:16 +0200 Subject: [PATCH 10/12] remove libcutter from travis as it's not available anymore in the repos --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2198598..b331309 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,6 @@ addons: - libusb-dev - doxygen - cmake - - libcutter-dev script: - if [ $BLD == autoconf ]; then autoreconf -vfi && mkdir build && cd build && ../configure --prefix=$HOME/.local/ && make -j2 && make install; fi From ad695d0a1818e935f011b8b06df7ac78d201aa1e Mon Sep 17 00:00:00 2001 From: quantum-x Date: Wed, 21 Aug 2019 10:06:19 +0200 Subject: [PATCH 11/12] Update .travis.yml --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2198598..b331309 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,6 @@ addons: - libusb-dev - doxygen - cmake - - libcutter-dev script: - if [ $BLD == autoconf ]; then autoreconf -vfi && mkdir build && cd build && ../configure --prefix=$HOME/.local/ && make -j2 && make install; fi From 2a6a8e6e298f999d2ca78db439d496dc5983595c Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Sat, 4 Apr 2020 15:10:02 +0100 Subject: [PATCH 12/12] add debugging for high level config requests --- libnfc/nfc.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 636697d..f239ba2 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -130,6 +130,25 @@ struct nfc_driver_list { const struct nfc_driver_list *nfc_drivers = NULL; +// descritions for debugging +const char * nfc_property_name[] = { + "NP_TIMEOUT_COMMAND", + "NP_TIMEOUT_ATR", + "NP_TIMEOUT_COM", + "NP_HANDLE_CRC", + "NP_HANDLE_PARITY", + "NP_ACTIVATE_FIELD", + "NP_ACTIVATE_CRYPTO1", + "NP_INFINITE_SELECT", + "NP_ACCEPT_INVALID_FRAMES", + "NP_ACCEPT_MULTIPLE_FRAMES", + "NP_AUTO_ISO14443_4", + "NP_EASY_FRAMING", + "NP_FORCE_ISO14443_A", + "NP_FORCE_ISO14443_B", + "NP_FORCE_SPEED_106" +}; + static void nfc_drivers_init(void) { @@ -409,6 +428,7 @@ nfc_list_devices(nfc_context *context, nfc_connstring connstrings[], const size_ int nfc_device_set_property_int(nfc_device *pnd, const nfc_property property, const int value) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "set_property_int %s %s", nfc_property_name[property], value ? "True" : "False"); HAL(device_set_property_int, pnd, property, value); } @@ -428,6 +448,7 @@ nfc_device_set_property_int(nfc_device *pnd, const nfc_property property, const int nfc_device_set_property_bool(nfc_device *pnd, const nfc_property property, const bool bEnable) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "set_property_bool %s %s", nfc_property_name[property], bEnable ? "True" : "False"); HAL(device_set_property_bool, pnd, property, bEnable); }