From 250068462bd3b733474734621b503abc3ac87972 Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Mon, 11 Nov 2013 22:03:09 +0000 Subject: [PATCH 001/318] add format/wipe command to nfc-mfclassic --- utils/nfc-mfclassic.c | 50 +++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 8eefa858..e6630c46 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -9,7 +9,7 @@ * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: - * Copyright (C) 2011 Adam Laurie + * Copyright (C) 2011-2013 Adam Laurie * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -68,6 +68,7 @@ static bool bUseKeyA; static bool bUseKeyFile; static bool bForceKeyFile; static bool bTolerateFailures; +static bool bFormatCard; static bool magic2 = false; static uint8_t uiBlocks; static uint8_t keys[] = { @@ -81,6 +82,8 @@ static uint8_t keys[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56 }; +static uint8_t default_key[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +static uint8_t default_acl[] = {0xff, 0x07, 0x80, 0x69}; static const nfc_modulation nmMifare = { .nmt = NMT_ISO14443A, @@ -204,8 +207,10 @@ authenticate(uint32_t uiBlock) // Try to authenticate for the current sector if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) return true; - } else { - // Try to guess the right key + } + + // If formatting or not using key file, try to guess the right key + 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)) { @@ -407,10 +412,17 @@ write_card(int write_block_zero) } if (is_trailer_block(uiBlock)) { - // Copy the keys over from our key dump and store the retrieved access bits - memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbt.abtKeyA, 6); - memcpy(mp.mpd.abtData + 6, mtDump.amb[uiBlock].mbt.abtAccessBits, 4); - memcpy(mp.mpd.abtData + 10, mtDump.amb[uiBlock].mbt.abtKeyB, 6); + if (bFormatCard) { + // Copy the default key and reset the access bits + memcpy(mp.mpd.abtData, default_key, 6); + memcpy(mp.mpd.abtData + 6, default_acl, 4); + memcpy(mp.mpd.abtData + 10, default_key, 6); + } else { + // Copy the keys over from our key dump and store the retrieved access bits + memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbt.abtKeyA, 6); + memcpy(mp.mpd.abtData + 6, mtDump.amb[uiBlock].mbt.abtAccessBits, 4); + memcpy(mp.mpd.abtData + 10, mtDump.amb[uiBlock].mbt.abtKeyB, 6); + } // Try to write the trailer if (nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp) == false) { @@ -426,7 +438,10 @@ write_card(int write_block_zero) // Make sure a earlier write did not fail if (!bFailure) { // Try to write the data block - memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, 16); + if(bFormatCard && uiBlock) + memset(mp.mpd.abtData, 0x00, 16); + else + memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, 16); // 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) { @@ -462,14 +477,25 @@ print_usage(const char *pcProgramName) { printf("Usage: "); printf("%s r|R|w|W a|b [ [f]]\n", pcProgramName); - printf(" r|R|w|W - Perform read from (r) or unlocked read from (R) or write to (w) or unlocked write to (W) card\n"); - printf(" *** note that unlocked write will attempt to overwrite block 0 including UID\n"); + printf(" f|r|R|w|W - Perform format (f) or read from (r) or unlocked read from (R) or write to (w) or unlocked write to (W) card\n"); + printf(" *** format will reset all keys to FFFFFFFFFFFF and all data to 00 and all ACLs to default\n"); printf(" *** unlocked read does not require authentication and will reveal A and B keys\n"); + printf(" *** note that unlocked write will attempt to overwrite block 0 including UID\n"); printf(" *** unlocking only works with special Mifare 1K cards (Chinese clones)\n"); printf(" a|A|b|B - Use A or B keys for action; Halt on errors (a|b) or tolerate errors (A|B)\n"); 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 mycard.mfd\n\n", pcProgramName); + printf(" Write file to blank card, using key A:\n\n"); + printf(" %s w a mycard.mfd\n\n", pcProgramName); + printf(" Write new data and/or keys to previously written card, using key A:\n\n"); + printf(" %s w a newdata.mfd mycard.mfd\n\n", pcProgramName); + printf(" Format/wipe card (note two passes required to ensure writes for all ACL cases):\n\n"); + printf(" %s f A dummy.mfd keyfile.mfd f\n", pcProgramName); + printf(" %s f B dummy.mfd keyfile.mfd f\n\n", pcProgramName); } int @@ -497,7 +523,7 @@ main(int argc, const char *argv[]) bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2])); bUseKeyFile = (argc > 4); bForceKeyFile = ((argc > 5) && (strcmp((char *)argv[5], "f") == 0)); - } else if (strcmp(command, "w") == 0 || strcmp(command, "W") == 0) { + } else if (strcmp(command, "w") == 0 || strcmp(command, "W") == 0 || strcmp(command, "f") == 0) { if (argc < 4) { print_usage(argv[0]); exit(EXIT_FAILURE); @@ -505,6 +531,8 @@ main(int argc, const char *argv[]) atAction = ACTION_WRITE; if (strcmp(command, "W") == 0) unlock = 1; + if (strcmp(command, "f") == 0) + bFormatCard = 1; bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a'; bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2])); bUseKeyFile = (argc > 4); From b8e0eec91d12bf4104fbe5e4a790a683203a001a Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 12 Nov 2013 00:28:24 +0100 Subject: [PATCH 002/318] nfc-mfclassic: initialize always bFormatCard --- utils/nfc-mfclassic.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index e6630c46..c481a5ab 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -531,8 +531,7 @@ main(int argc, const char *argv[]) atAction = ACTION_WRITE; if (strcmp(command, "W") == 0) unlock = 1; - if (strcmp(command, "f") == 0) - bFormatCard = 1; + bFormatCard = (strcmp(command, "f") == 0); bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a'; bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2])); bUseKeyFile = (argc > 4); From a1ef3299621dccac15e1b27a258205d02579a197 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 12 Nov 2013 00:28:38 +0100 Subject: [PATCH 003/318] Fix use after free pn532_uart.c:293:5: warning: Use of memory after it is freed log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "pn53x_check_communication error on %s", ndd.port); ^ ~~~~~~~~ --- libnfc/drivers/pn532_uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnfc/drivers/pn532_uart.c b/libnfc/drivers/pn532_uart.c index 1047078b..d89b5f43 100644 --- a/libnfc/drivers/pn532_uart.c +++ b/libnfc/drivers/pn532_uart.c @@ -290,7 +290,7 @@ pn532_uart_open(const nfc_context *context, const nfc_connstring connstring) // Check communication using "Diagnose" command, with "Communication test" (0x00) if (pn53x_check_communication(pnd) < 0) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "pn53x_check_communication error on %s", ndd.port); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "pn53x_check_communication error"); pn532_uart_close(pnd); return NULL; } From 4817a6e5c943a3b8e5e6faf2471c69f75ba493b1 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 2 Dec 2013 22:55:10 +0100 Subject: [PATCH 004/318] make style --- utils/nfc-mfclassic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index c481a5ab..c206fc35 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -438,7 +438,7 @@ write_card(int write_block_zero) // Make sure a earlier write did not fail if (!bFailure) { // Try to write the data block - if(bFormatCard && uiBlock) + if (bFormatCard && uiBlock) memset(mp.mpd.abtData, 0x00, 16); else memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, 16); From a7fc1bddafab6518ee300e6ba81f5bd2e4542098 Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Fri, 6 Dec 2013 16:03:00 +0100 Subject: [PATCH 005/318] Fix nfc_target_init() timeout return This patch prevent from returning a successfull error code while timeout occurred. Thanks to blck on forum: http://www.libnfc.org/community/post/4913/#p4913 --- libnfc/chips/pn53x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 0cedca84..edd9ecf4 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1911,7 +1911,7 @@ pn53x_target_init(struct nfc_device *pnd, nfc_target *pnt, uint8_t *pbtRx, const if ((res = pn53x_TgInitAsTarget(pnd, ptm, pbtMifareParams, pbtTkt, szTkt, pbtFeliCaParams, pbtNFCID3t, pbtGBt, szGBt, pbtRx, szRxLen, &btActivatedMode, timeout)) < 0) { if (res == NFC_ETIMEOUT) { - return pn53x_idle(pnd); + pn53x_idle(pnd); } return res; } From 0ee6dcad4b2a1afa9de73509fac74464b28d2118 Mon Sep 17 00:00:00 2001 From: Jiapeng Li Date: Sun, 8 Dec 2013 14:09:50 +0100 Subject: [PATCH 006/318] Cmake: add CONFFILES define like available in autotools build system --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 90825f31..06ec8b95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,11 @@ ELSE(LIBNFC_DEBUG_MODE) SET(WIN32_MODE "release") ENDIF(LIBNFC_DEBUG_MODE) +SET(LIBNFC_CONFFILES_MODE ON CACHE BOOL "Enable configuration files") +IF(LIBNFC_CONFFILES_MODE) + ADD_DEFINITIONS(-DCONFFILES) +ENDIF(LIBNFC_CONFFILES_MODE) + # Doxygen SET(builddir "${CMAKE_BINARY_DIR}") SET(top_srcdir "${CMAKE_SOURCE_DIR}") From 76a85ce84b9b54056abde35eea41773977f38387 Mon Sep 17 00:00:00 2001 From: Jiapeng Li Date: Sun, 8 Dec 2013 14:12:06 +0100 Subject: [PATCH 007/318] CMake: remove tailing newline from date under Windows This patch prevents from having a newline (\n) within date result in generated RC file --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 06ec8b95..c4cf7fe3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -139,6 +139,7 @@ IF(WIN32) # Date for filling in rc file information MACRO (GET_CURRENT_YEAR RESULT) EXECUTE_PROCESS(COMMAND "cmd" " /C date /T" OUTPUT_VARIABLE ${RESULT}) + STRING(REGEX REPLACE "\n" "" ${RESULT} ${${RESULT}}) STRING(REGEX REPLACE ".*(..)/(..)/(....).*" "\\3" ${RESULT} ${${RESULT}}) ENDMACRO (GET_CURRENT_YEAR) GET_CURRENT_YEAR(CURRENT_YEAR) From d89affd819a285675746830cba028abaafd08d3c Mon Sep 17 00:00:00 2001 From: Jiapeng Li Date: Sun, 8 Dec 2013 14:15:36 +0100 Subject: [PATCH 008/318] UART (Windows): fix uart_flush_input format This patch allow uart files to be compiled under Windows, it adds a 'wait' parameter but do not use it. Please note that patch fixes compilation but do not add any feature to Windows support --- contrib/win32/libnfc/buses/uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/win32/libnfc/buses/uart.c b/contrib/win32/libnfc/buses/uart.c index 06508695..bfb20c01 100644 --- a/contrib/win32/libnfc/buses/uart.c +++ b/contrib/win32/libnfc/buses/uart.c @@ -113,7 +113,7 @@ uart_close(const serial_port sp) } void -uart_flush_input(const serial_port sp) +uart_flush_input(const serial_port sp, bool wait) { PurgeComm(((struct serial_port_windows *) sp)->hPort, PURGE_RXABORT | PURGE_RXCLEAR); } From aa2c1c47cd2c695bf971d76c1966e50b3e61bfa1 Mon Sep 17 00:00:00 2001 From: Jiapeng Li Date: Sun, 8 Dec 2013 14:17:39 +0100 Subject: [PATCH 009/318] Config: bring configuration feature to Windows --- libnfc/conf.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libnfc/conf.c b/libnfc/conf.c index 7bda47d5..bf68defd 100644 --- a/libnfc/conf.c +++ b/libnfc/conf.c @@ -177,10 +177,14 @@ conf_devices_load(const char *dirname, nfc_context *context) log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Unable to open directory: %s", dirname); } else { struct dirent *de; + #ifdef WIN32 + while ((de = readdir(d)) != NULL ) { + #else struct dirent entry; struct dirent *result; while ((readdir_r(d, &entry, &result) == 0) && (result != NULL)) { de = &entry; + #endif if (de->d_name[0] != '.') { const size_t filename_len = strlen(de->d_name); const size_t extension_len = strlen(".conf"); From 8026d6c0472cb751cea838658691c3c6020d6455 Mon Sep 17 00:00:00 2001 From: Jiapeng Li Date: Sun, 8 Dec 2013 14:24:48 +0100 Subject: [PATCH 010/318] CMake: find and use pcre3.dll when looking for PCRE --- cmake/FixBundle.cmake.in | 2 +- cmake/modules/FindPCRE.cmake | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/cmake/FixBundle.cmake.in b/cmake/FixBundle.cmake.in index 6e8f843d..d11dc8fb 100644 --- a/cmake/FixBundle.cmake.in +++ b/cmake/FixBundle.cmake.in @@ -6,6 +6,6 @@ SET(bundle "${CMAKE_INSTALL_PREFIX}/bin/nfc-list@CMAKE_EXECUTABLE_SUFFIX@") # set other_libs to a list of additional libs that cannot be reached by dependency analysis SET(other_libs "") -SET(dirs "@LIBUSB_LIBRARY_DIR@") +SET(dirs "@LIBUSB_LIBRARY_DIR@" "@PCRE_BIN_DIRS@") fixup_bundle("${bundle}" "${other_libs}" "${dirs}") diff --git a/cmake/modules/FindPCRE.cmake b/cmake/modules/FindPCRE.cmake index 0b83defc..3d043aa4 100644 --- a/cmake/modules/FindPCRE.cmake +++ b/cmake/modules/FindPCRE.cmake @@ -15,15 +15,16 @@ IF(WIN32) IF(NOT PCRE_FOUND) FIND_PATH(PCRE_INCLUDE_DIRS regex.h) FIND_LIBRARY(PCRE_LIBRARIES NAMES PCRE pcre) - - IF(PCRE_INCLUDE_DIRS AND PCRE_LIBRARIES) + FIND_PATH(PCRE_BIN_DIRS pcre3.dll) + + IF(PCRE_INCLUDE_DIRS AND PCRE_LIBRARIES AND PCRE_BIN_DIRS) SET(PCRE_FOUND TRUE) - ENDIF(PCRE_INCLUDE_DIRS AND PCRE_LIBRARIES) + ENDIF(PCRE_INCLUDE_DIRS AND PCRE_LIBRARIES AND PCRE_BIN_DIRS) ENDIF(NOT PCRE_FOUND) IF(PCRE_FOUND) IF(NOT PCRE_FIND_QUIETLY) - MESSAGE(STATUS "Found PCRE: ${PCRE_LIBRARIES} ${PCRE_INCLUDE_DIRS}") + MESSAGE(STATUS "Found PCRE: ${PCRE_LIBRARIES} ${PCRE_INCLUDE_DIRS} ${PCRE_BIN_DIRS}") ENDIF (NOT PCRE_FIND_QUIETLY) ELSE(PCRE_FOUND) IF(PCRE_FIND_REQUIRED) @@ -35,6 +36,7 @@ IF(WIN32) FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE DEFAULT_MSG PCRE_LIBRARIES PCRE_INCLUDE_DIRS + PCRE_BIN_DIRS ) ENDIF(WIN32) From 7b7f5061427b5456835dd48923a8cc0563cfd1e9 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sun, 8 Dec 2013 19:51:01 +0100 Subject: [PATCH 011/318] make style --- libnfc/conf.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libnfc/conf.c b/libnfc/conf.c index bf68defd..2319a752 100644 --- a/libnfc/conf.c +++ b/libnfc/conf.c @@ -177,14 +177,14 @@ conf_devices_load(const char *dirname, nfc_context *context) log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Unable to open directory: %s", dirname); } else { struct dirent *de; - #ifdef WIN32 - while ((de = readdir(d)) != NULL ) { - #else +#ifdef WIN32 + while ((de = readdir(d)) != NULL) { +#else struct dirent entry; struct dirent *result; while ((readdir_r(d, &entry, &result) == 0) && (result != NULL)) { de = &entry; - #endif +#endif if (de->d_name[0] != '.') { const size_t filename_len = strlen(de->d_name); const size_t extension_len = strlen(".conf"); From d47623319d8afba9467af650c04d53acd743dfa2 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 27 Jan 2014 16:07:24 +0100 Subject: [PATCH 012/318] nfc_initiator_target_is_present() allows pnt==NULL --- libnfc/chips/pn53x.c | 2 +- libnfc/nfc.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index edd9ecf4..690c0d1e 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1729,7 +1729,7 @@ int pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) { // Check if the argument target nt is equals to current saved target - if (!pn53x_current_target_is(pnd, pnt)) { + if ((pnt != NULL) && (!pn53x_current_target_is(pnd, pnt))) { return NFC_ETGRELEASED; } diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 37fa413c..dcfd409c 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -836,7 +836,9 @@ nfc_initiator_transceive_bytes_timed(nfc_device *pnd, * @brief Check target presence * @return Returns 0 on success, otherwise returns libnfc's error code. * - * This function tests if \a nfc_target is currently present on NFC device. + * @param pnd \a nfc_device struct pointer that represent currently used device + * @param pnt a \a nfc_target struct pointer where desired target information was stored (optionnal, can be \e NULL). + * This function tests if \a nfc_target (or last selected tag if \e NULL) is currently present on NFC device. * @warning The target have to be selected before check its presence * @warning To run the test, one or more commands will be sent to target */ From 7a30e354966ac1f6a8e68e43d2585f99dd0e03ea Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 28 Jan 2014 00:22:33 +0100 Subject: [PATCH 013/318] nfc-mfclassic: update help & man page --- utils/nfc-mfclassic.1 | 22 ++++++++++++++++++---- utils/nfc-mfclassic.c | 2 +- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/utils/nfc-mfclassic.1 b/utils/nfc-mfclassic.1 index d1f91171..bfef5e3c 100644 --- a/utils/nfc-mfclassic.1 +++ b/utils/nfc-mfclassic.1 @@ -3,10 +3,13 @@ nfc-mfclassic \- MIFARE Classic command line tool .SH SYNOPSIS .B nfc-mfclassic -.RI \fR\fBr\fR|\fR\fBR\fR|\fBw\fR\fR|\fBW\fR +.RI \fR\fBf\fR|\fR\fBr\fR|\fR\fBR\fR|\fBw\fR\fR|\fBW\fR .RI \fR\fBa\fR|\fR\fBA\fR|\fBb\fR\fR|\fBB\fR .IR DUMP -.IR [KEYS] +.RI [ +.IR KEYS +.RI [\fR\fBf\fR] +.RI ] .SH DESCRIPTION .B nfc-mfclassic @@ -27,6 +30,10 @@ to store the keys and data for all sectors. Be cautious that some parts of a MIFARE Classic memory are used for r/w access of the rest of the memory, so please read the tag documentation before experimenting too much! +The +.B f +option to format the card will reset all keys to FFFFFFFFFFFF, all data to 00 and all ACLs to default. + The .B W option allows writing of special MIFARE cards that can be 'unlocked' to allow block 0 @@ -57,8 +64,10 @@ options only work on special versions of MIFARE 1K cards (Chinese clones). .SH OPTIONS .TP -.BR r " | " R " | " w " | " W -Perform read from ( +.BR f " | " r " | " R " | " w " | " W +Perform format ( +.B f +) or read from ( .B r ) or unlocked read from ( .B R @@ -86,6 +95,11 @@ MiFare Dump (MFD) used to write (card to MFD) or (MFD to card) .TP .IR KEYS MiFare Dump (MFD) that contains the keys (optional). Data part of the dump is ignored. +.TP +.B f +Force using the keyfile +.IR KEYS +even if UID does not match (optional). .SH BUGS Please report any bugs on the diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index c206fc35..12428867 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -476,7 +476,7 @@ static void print_usage(const char *pcProgramName) { printf("Usage: "); - printf("%s r|R|w|W a|b [ [f]]\n", pcProgramName); + printf("%s f|r|R|w|W a|b [ [f]]\n", pcProgramName); printf(" f|r|R|w|W - Perform format (f) or read from (r) or unlocked read from (R) or write to (w) or unlocked write to (W) card\n"); printf(" *** format will reset all keys to FFFFFFFFFFFF and all data to 00 and all ACLs to default\n"); printf(" *** unlocked read does not require authentication and will reveal A and B keys\n"); From 9a0a10826bd811b181669ae9eb4544c5c4136bff Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Tue, 28 Jan 2014 10:25:29 +0100 Subject: [PATCH 014/318] Fix pn53x_initiator_target_is_present() when saved target is NULL This patch prevents from running any command to check target presence when none have been saved --- libnfc/chips/pn53x.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 690c0d1e..56679ea8 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1728,6 +1728,11 @@ pn53x_initiator_deselect_target(struct nfc_device *pnd) int pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) { + // Check if there is a saved target + if (CHIP_DATA(pnd)->current_target == NULL) { + return NFC_ETGRELEASED; + } + // Check if the argument target nt is equals to current saved target if ((pnt != NULL) && (!pn53x_current_target_is(pnd, pnt))) { return NFC_ETGRELEASED; From b7f590acc8f322066d9e02d8c74b299e8f576f52 Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Tue, 28 Jan 2014 10:40:18 +0100 Subject: [PATCH 015/318] Set correctly last_error when running pn53x_initiator_target_is_present() --- libnfc/chips/pn53x.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 56679ea8..0631322d 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1730,12 +1730,12 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) { // Check if there is a saved target if (CHIP_DATA(pnd)->current_target == NULL) { - return NFC_ETGRELEASED; + return pnd->last_error = NFC_ETGRELEASED; } // Check if the argument target nt is equals to current saved target if ((pnt != NULL) && (!pn53x_current_target_is(pnd, pnt))) { - return NFC_ETGRELEASED; + return pnd->last_error = NFC_ETGRELEASED; } // Send Card Presence command @@ -1749,12 +1749,12 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) if ((res = pn53x_transceive(pnd, abtCmd, sizeof(abtCmd), abtRx, sizeof(abtRx), 700)) < 0) return res; if (res == 1) { - return NFC_SUCCESS; + return pnd->last_error = NFC_SUCCESS; } // Target is not reachable anymore pn53x_current_target_free(pnd); - return NFC_ETGRELEASED; + return pnd->last_error = NFC_ETGRELEASED; } #define SAK_ISO14443_4_COMPLIANT 0x20 From e5c732e18125a4f16ef98a50143fc7ffad7d66e7 Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Tue, 28 Jan 2014 10:45:05 +0100 Subject: [PATCH 016/318] Fix internal current target when using nfc_initiator_poll_target() (Thanks to Bjoern Kinscher) Fixes Issue 265. --- libnfc/chips/pn53x.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 0631322d..8331662d 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1209,10 +1209,16 @@ pn53x_initiator_poll_target(struct nfc_device *pnd, switch (res) { case 1: *pnt = ntTargets[0]; + if (pn53x_current_target_new(pnd, pnt) == NULL) { + return pnd->last_error = NFC_ESOFT; + } return res; break; case 2: *pnt = ntTargets[1]; // We keep the selected one + if (pn53x_current_target_new(pnd, pnt) == NULL) { + return pnd->last_error = NFC_ESOFT; + } return res; break; default: From 65ad186109682bbf1f77863d181d4f0eb5fb9f6d Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 28 Jan 2014 13:09:33 +0100 Subject: [PATCH 017/318] make style --- libnfc/chips/pn53x.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 8331662d..49456da1 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1736,12 +1736,12 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) { // Check if there is a saved target if (CHIP_DATA(pnd)->current_target == NULL) { - return pnd->last_error = NFC_ETGRELEASED; + return pnd->last_error = NFC_ETGRELEASED; } // Check if the argument target nt is equals to current saved target if ((pnt != NULL) && (!pn53x_current_target_is(pnd, pnt))) { - return pnd->last_error = NFC_ETGRELEASED; + return pnd->last_error = NFC_ETGRELEASED; } // Send Card Presence command @@ -1755,12 +1755,12 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) if ((res = pn53x_transceive(pnd, abtCmd, sizeof(abtCmd), abtRx, sizeof(abtRx), 700)) < 0) return res; if (res == 1) { - return pnd->last_error = NFC_SUCCESS; + return pnd->last_error = NFC_SUCCESS; } // Target is not reachable anymore pn53x_current_target_free(pnd); - return pnd->last_error = NFC_ETGRELEASED; + return pnd->last_error = NFC_ETGRELEASED; } #define SAK_ISO14443_4_COMPLIANT 0x20 From 744e052fbefe30c2b30c040d2b1409f5b344bdcf Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 28 Jan 2014 13:20:03 +0100 Subject: [PATCH 018/318] update ChangeLog --- ChangeLog | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 6a481ec3..d38882d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,6 +7,11 @@ Fixes: - More robust when several conflicting uart drivers are in the config - Fix racing condition with uart_flush_input() - Silent pn53x_check_communication error messages when scanning + - Fix nfc_target_init(), was returning success in case of timeout + - Windows: fix several compilation issues + - Fix nfc_initiator_target_is_present() usage after nfc_initiator_poll_target() + - Fix nfc_initiator_target_is_present() set correctly last_error + - Fix nfc_initiator_target_is_present() if no saved target Improvements: - nfc-list: New option to choose which technologies to poll for @@ -14,6 +19,9 @@ Improvements: - New LIBNFC_DEVICE env var to use one reader and exclude all other readers while LIBNFC_DEFAULT_DEVICE only prepends it to the configured devices list - New LIBNFC_AUTO_SCAN env var to enable(default)/disable auto scan + - nfc-mfclassic: add format/wipe command + - nfc_initiator_target_is_present() allows NULL pointer to tag + Sep 03, 2013 - 1.7.0 -------------------- From 1a3acdadc42a341d93b13a75a9fb681140924e31 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 29 Jan 2014 01:53:41 +0100 Subject: [PATCH 019/318] Prepare nfc_initiator_target_is_present() to support more cases and return NFC_EDEVNOTSUPP for cases not yet supported, depending on the chipset. Little helper to debug future additions to that function: // LIBNFC_LOG_LEVEL=193 ./nfc-testing int main(void) { nfc_device *pnd; nfc_modulation nm = { .nmt = NMT_ISO14443A, .nbr = NBR_106, }; nfc_context *context; nfc_init(&context); pnd = nfc_open(context, NULL); nfc_initiator_init(pnd); nfc_target nt; nfc_initiator_select_passive_target(pnd, nm, NULL, 0, &nt); while (nfc_initiator_target_is_present(pnd, NULL) == NFC_SUCCESS); nfc_close(pnd); nfc_exit(context); } --- libnfc/chips/pn53x.c | 110 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 96 insertions(+), 14 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 49456da1..540e39d3 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1731,19 +1731,8 @@ pn53x_initiator_deselect_target(struct nfc_device *pnd) return pn53x_InDeselect(pnd, 0); // 0 mean deselect all selected targets } -int -pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) +static int pn53x_Diagnose06(struct nfc_device *pnd) { - // Check if there is a saved target - if (CHIP_DATA(pnd)->current_target == NULL) { - return pnd->last_error = NFC_ETGRELEASED; - } - - // Check if the argument target nt is equals to current saved target - if ((pnt != NULL) && (!pn53x_current_target_is(pnd, pnt))) { - return pnd->last_error = NFC_ETGRELEASED; - } - // Send Card Presence command const uint8_t abtCmd[] = { Diagnose, 0x06 }; uint8_t abtRx[1]; @@ -1755,12 +1744,105 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) if ((res = pn53x_transceive(pnd, abtCmd, sizeof(abtCmd), abtRx, sizeof(abtRx), 700)) < 0) return res; if (res == 1) { - return pnd->last_error = NFC_SUCCESS; + return NFC_SUCCESS; } // Target is not reachable anymore pn53x_current_target_free(pnd); - return pnd->last_error = NFC_ETGRELEASED; + return NFC_ETGRELEASED; +} + +int +pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) +{ + // Check if there is a saved target + if (CHIP_DATA(pnd)->current_target == NULL) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): no saved target"); +// TODO pnt is optional for select_passive_target() and internal nt struct is saved +// only if pnt is provided but it's not intuitive that +// nfc_initiator_select_passive_target(pnt=NULL) + target_is_present(pnt=NULL) fails +// Maybe we should have an internal copy of nt, no matter if a pnt was provided + return pnd->last_error = NFC_ETGRELEASED; + } + + // Check if the argument target nt is equals to current saved target + if ((pnt != NULL) && (!pn53x_current_target_is(pnd, pnt))) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): another target"); + return pnd->last_error = NFC_ETGRELEASED; + } + + // Ping target + int ret; + switch (CHIP_DATA(pnd)->current_target->nm.nmt) { + case NMT_ISO14443A: + if (CHIP_DATA(pnd)->current_target->nti.nai.btSak & 0x20) { + // -4A + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping -4A"); + if ((CHIP_DATA(pnd)->type == PN532) || (CHIP_DATA(pnd)->type == PN533)) { + ret = pn53x_Diagnose06(pnd); + } else { + ret = NFC_EDEVNOTSUPP; + } + } else if ((CHIP_DATA(pnd)->current_target->nti.nai.abtAtqa[0] == 0x00) && + (CHIP_DATA(pnd)->current_target->nti.nai.abtAtqa[1] == 0x44) && + (CHIP_DATA(pnd)->current_target->nti.nai.btSak == 0x00)) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping MFUL"); + // MFUL + if (CHIP_DATA(pnd)->type == PN533) { + ret = pn53x_Diagnose06(pnd); + } else { + ret = NFC_EDEVNOTSUPP; + } + } else if (CHIP_DATA(pnd)->current_target->nti.nai.btSak & 0x08) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping MFC"); + // MFC + if (CHIP_DATA(pnd)->type == PN533) { +//TODO MFC Mini (atqa0004/sak09) fails on PN533 + ret = pn53x_Diagnose06(pnd); + } else { + ret = NFC_EDEVNOTSUPP; + } + } else { + // unknown + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): card type A not supported"); + ret = NFC_EDEVNOTSUPP; + } +// TODO what about dual mode cards: MFP, JCOP etc? (MFC + -4) +// we've to detect them and it depends in which state they are + break; + case NMT_DEP: + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping DEP"); + if ((CHIP_DATA(pnd)->type == PN531) || (CHIP_DATA(pnd)->type == PN532) || (CHIP_DATA(pnd)->type == PN533)) + ret = pn53x_Diagnose06(pnd); + else + ret = NFC_EDEVNOTSUPP; + break; + case NMT_FELICA: + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping Felica"); + if (CHIP_DATA(pnd)->type == PN533) { + ret = pn53x_Diagnose06(pnd); + } else { + ret = NFC_EDEVNOTSUPP; + } + break; + case NMT_ISO14443B: + // -4B + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping -4B"); + if ((CHIP_DATA(pnd)->type == PN532) || (CHIP_DATA(pnd)->type == PN533)) { + ret = pn53x_Diagnose06(pnd); + } else { + ret = NFC_EDEVNOTSUPP; + } + case NMT_JEWEL: + case NMT_ISO14443BI: + case NMT_ISO14443B2SR: + case NMT_ISO14443B2CT: + default: + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): card type not supported"); + ret = NFC_EDEVNOTSUPP; + break; + } + return pnd->last_error = ret; } #define SAK_ISO14443_4_COMPLIANT 0x20 From 7b5ab234523ad536be500456a5d6c8246cda1bc0 Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Wed, 29 Jan 2014 11:36:12 +0100 Subject: [PATCH 020/318] Partial MFC support while checking target presence on PN532/PN531 Goal is to implement "ping" on MFC the same as PN533 does. This patch implements MFC re-selection, but do not take care about authentication; this means this will have side effect while you are authenticated on a MFC block. --- examples/nfc-poll.c | 6 ++++++ libnfc/chips/pn53x.c | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/examples/nfc-poll.c b/examples/nfc-poll.c index cb1afa90..6d64c325 100644 --- a/examples/nfc-poll.c +++ b/examples/nfc-poll.c @@ -148,6 +148,12 @@ main(int argc, const char *argv[]) } else { printf("No target found.\n"); } + + printf("Waiting for card removing..."); + while (0 == (res = nfc_initiator_target_is_present(pnd, NULL))) {} + nfc_perror(pnd, "nfc_initiator_target_is_present"); + printf("done.\n"); + nfc_close(pnd); nfc_exit(context); exit(EXIT_SUCCESS); diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 540e39d3..7d4d5de0 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1800,7 +1800,11 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) //TODO MFC Mini (atqa0004/sak09) fails on PN533 ret = pn53x_Diagnose06(pnd); } else { - ret = NFC_EDEVNOTSUPP; + if((ret = pn53x_initiator_select_passive_target_ext(pnd, CHIP_DATA(pnd)->current_target->nm, CHIP_DATA(pnd)->current_target->nti.nai.abtUid, CHIP_DATA(pnd)->current_target->nti.nai.szUidLen, NULL, 50)) == 1) { + ret = NFC_SUCCESS; + } else if ((ret == 0) || (ret == NFC_ETIMEOUT)) { + ret = NFC_ETGRELEASED; + } } } else { // unknown From 94f4e001f42feab0cfe5cf8ec0f708cbab17e5cc Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 29 Jan 2014 23:02:36 +0100 Subject: [PATCH 021/318] nfc_initiator_target_is_present(): support MFUL on PN532 too --- libnfc/chips/pn53x.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 7d4d5de0..4e75a26e 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1788,10 +1788,16 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) (CHIP_DATA(pnd)->current_target->nti.nai.btSak == 0x00)) { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping MFUL"); // MFUL + // Limitation: test on MFULC non-authenticated with read of first sector forbidden will fail if (CHIP_DATA(pnd)->type == PN533) { ret = pn53x_Diagnose06(pnd); } else { - ret = NFC_EDEVNOTSUPP; + uint8_t abtCmd[2] = {0x30, 0x00}; + if (nfc_initiator_transceive_bytes(pnd, abtCmd, sizeof(abtCmd), NULL, 0, -1) > 0) { + ret = NFC_SUCCESS; + } else { + ret = NFC_ETGRELEASED; + } } } else if (CHIP_DATA(pnd)->current_target->nti.nai.btSak & 0x08) { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping MFC"); @@ -1800,7 +1806,7 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) //TODO MFC Mini (atqa0004/sak09) fails on PN533 ret = pn53x_Diagnose06(pnd); } else { - if((ret = pn53x_initiator_select_passive_target_ext(pnd, CHIP_DATA(pnd)->current_target->nm, CHIP_DATA(pnd)->current_target->nti.nai.abtUid, CHIP_DATA(pnd)->current_target->nti.nai.szUidLen, NULL, 50)) == 1) { + if ((ret = pn53x_initiator_select_passive_target_ext(pnd, CHIP_DATA(pnd)->current_target->nm, CHIP_DATA(pnd)->current_target->nti.nai.abtUid, CHIP_DATA(pnd)->current_target->nti.nai.szUidLen, NULL, 50)) == 1) { ret = NFC_SUCCESS; } else if ((ret == 0) || (ret == NFC_ETIMEOUT)) { ret = NFC_ETGRELEASED; From 9d63a93dd821ff48a6a269cac23ea8ad70f0dc86 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 29 Jan 2014 23:30:44 +0100 Subject: [PATCH 022/318] nfc_initiator_target_is_present(): improve MFC support Increase timeout to support Tikitag & PN533 Fix support for MFC Mini on PN533 --- libnfc/chips/pn53x.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 4e75a26e..00d127d2 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1802,11 +1802,13 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) } else if (CHIP_DATA(pnd)->current_target->nti.nai.btSak & 0x08) { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping MFC"); // MFC - if (CHIP_DATA(pnd)->type == PN533) { -//TODO MFC Mini (atqa0004/sak09) fails on PN533 + if ((CHIP_DATA(pnd)->type == PN533) && (CHIP_DATA(pnd)->current_target->nti.nai.btSak != 0x09)) { + // MFC Mini (atqa0004/sak09) fails on PN533, so we exclude it ret = pn53x_Diagnose06(pnd); } else { - if ((ret = pn53x_initiator_select_passive_target_ext(pnd, CHIP_DATA(pnd)->current_target->nm, CHIP_DATA(pnd)->current_target->nti.nai.abtUid, CHIP_DATA(pnd)->current_target->nti.nai.szUidLen, NULL, 50)) == 1) { + // Limitation: re-select will lose authentication of already authenticated sector + // TODO: buggy when card is removed on Tikitag + if ((ret = pn53x_initiator_select_passive_target_ext(pnd, CHIP_DATA(pnd)->current_target->nm, CHIP_DATA(pnd)->current_target->nti.nai.abtUid, CHIP_DATA(pnd)->current_target->nti.nai.szUidLen, NULL, 300)) == 1) { ret = NFC_SUCCESS; } else if ((ret == 0) || (ret == NFC_ETIMEOUT)) { ret = NFC_ETGRELEASED; From 095f94522419fea5c98c2d472d575473b9c952b1 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 30 Jan 2014 00:09:03 +0100 Subject: [PATCH 023/318] nfc_initiator_target_is_present(): improve MFC support for 7-byte UID --- libnfc/chips/pn53x.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 00d127d2..2e5482e6 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1808,7 +1808,27 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) } else { // Limitation: re-select will lose authentication of already authenticated sector // TODO: buggy when card is removed on Tikitag - if ((ret = pn53x_initiator_select_passive_target_ext(pnd, CHIP_DATA(pnd)->current_target->nm, CHIP_DATA(pnd)->current_target->nti.nai.abtUid, CHIP_DATA(pnd)->current_target->nti.nai.szUidLen, NULL, 300)) == 1) { + uint8_t pbtInitiatorData[12]; + uint8_t szInitiatorData = 0; + switch (CHIP_DATA(pnd)->current_target->nti.nai.szUidLen) { + case 4: + memcpy(pbtInitiatorData, CHIP_DATA(pnd)->current_target->nti.nai.abtUid, 4); + szInitiatorData = 4; + break; + case 7: + pbtInitiatorData[0] = 0x88; + memcpy(&pbtInitiatorData[1], CHIP_DATA(pnd)->current_target->nti.nai.abtUid, 7); + szInitiatorData = 8; + break; + case 10: + pbtInitiatorData[0] = 0x88; + memcpy(&pbtInitiatorData[1], CHIP_DATA(pnd)->current_target->nti.nai.abtUid, 3); + pbtInitiatorData[4] = 0x88; + memcpy(&pbtInitiatorData[5], &CHIP_DATA(pnd)->current_target->nti.nai.abtUid[3], 7); + szInitiatorData = 12; + break; + } + if ((ret = pn53x_initiator_select_passive_target_ext(pnd, CHIP_DATA(pnd)->current_target->nm, pbtInitiatorData, szInitiatorData, NULL, 300)) == 1) { ret = NFC_SUCCESS; } else if ((ret == 0) || (ret == NFC_ETIMEOUT)) { ret = NFC_ETGRELEASED; From ade71ee8a6967913f8730468a8c8592c199a7ad5 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 30 Jan 2014 00:24:06 +0100 Subject: [PATCH 024/318] nfc_initiator_target_is_present(): reuse iso14443_cascade_uid() --- libnfc/chips/pn53x.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 2e5482e6..40708a34 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1809,25 +1809,8 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) // Limitation: re-select will lose authentication of already authenticated sector // TODO: buggy when card is removed on Tikitag uint8_t pbtInitiatorData[12]; - uint8_t szInitiatorData = 0; - switch (CHIP_DATA(pnd)->current_target->nti.nai.szUidLen) { - case 4: - memcpy(pbtInitiatorData, CHIP_DATA(pnd)->current_target->nti.nai.abtUid, 4); - szInitiatorData = 4; - break; - case 7: - pbtInitiatorData[0] = 0x88; - memcpy(&pbtInitiatorData[1], CHIP_DATA(pnd)->current_target->nti.nai.abtUid, 7); - szInitiatorData = 8; - break; - case 10: - pbtInitiatorData[0] = 0x88; - memcpy(&pbtInitiatorData[1], CHIP_DATA(pnd)->current_target->nti.nai.abtUid, 3); - pbtInitiatorData[4] = 0x88; - memcpy(&pbtInitiatorData[5], &CHIP_DATA(pnd)->current_target->nti.nai.abtUid[3], 7); - szInitiatorData = 12; - break; - } + size_t szInitiatorData = 0; + iso14443_cascade_uid(CHIP_DATA(pnd)->current_target->nti.nai.abtUid, CHIP_DATA(pnd)->current_target->nti.nai.szUidLen, pbtInitiatorData, &szInitiatorData); if ((ret = pn53x_initiator_select_passive_target_ext(pnd, CHIP_DATA(pnd)->current_target->nm, pbtInitiatorData, szInitiatorData, NULL, 300)) == 1) { ret = NFC_SUCCESS; } else if ((ret == 0) || (ret == NFC_ETIMEOUT)) { From d893e4398cdd86dd7c0a07abb3a78ef95aee3f44 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 30 Jan 2014 00:32:21 +0100 Subject: [PATCH 025/318] nfc_initiator_target_is_present(): fix ISO14443B-4 support --- libnfc/chips/pn53x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 40708a34..cd9d2c6d 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1848,6 +1848,7 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) } else { ret = NFC_EDEVNOTSUPP; } + break; case NMT_JEWEL: case NMT_ISO14443BI: case NMT_ISO14443B2SR: From 5fe3fbdb5d39ff3cf5f1b7a7e45f26c6a5a1f609 Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Thu, 30 Jan 2014 11:10:18 +0100 Subject: [PATCH 026/318] Fix nfc_target_is_present() when removing a ISO14443-4A target from a PN532-based device --- libnfc/chips/pn53x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index cd9d2c6d..36a4720c 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1780,6 +1780,8 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping -4A"); if ((CHIP_DATA(pnd)->type == PN532) || (CHIP_DATA(pnd)->type == PN533)) { ret = pn53x_Diagnose06(pnd); + // When pn53x_Diagnose06() fails with a timeout (0x01) chip error, it means the target is not reacheable anymore + if ((ret == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) ret = NFC_ETGRELEASED; } else { ret = NFC_EDEVNOTSUPP; } From 70f5c234861819d38a841e4bafbd02ff99def52c Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Thu, 30 Jan 2014 11:11:54 +0100 Subject: [PATCH 027/318] Git: ignore generated examples/doc/.deps directory --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3beab642..318dcfc8 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,7 @@ examples/.deps/ examples/.libs/ examples/Makefile examples/Makefile.in +examples/doc/.deps/ examples/nfc-anticol examples/nfc-dep-initiator examples/nfc-dep-target From 05579fde097ff7c98f76d91c5e5093bc170671ef Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 30 Jan 2014 11:19:02 +0100 Subject: [PATCH 028/318] nfc_initiator_target_is_present(): better Felica support --- libnfc/chips/pn53x.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 36a4720c..bf10933c 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1836,10 +1836,21 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) break; case NMT_FELICA: log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping Felica"); - if (CHIP_DATA(pnd)->type == PN533) { - ret = pn53x_Diagnose06(pnd); - } else { - ret = NFC_EDEVNOTSUPP; + // if (CHIP_DATA(pnd)->type == PN533) { ret = pn53x_Diagnose06(pnd); } else... + // Because ping fails now & then, better not to use Diagnose at all + // Limitation: does not work on Felica Lite cards (neither Diagnose nor our method) + uint8_t abtCmd[10] = {0x0A, 0x04}; + memcpy(abtCmd + 2, CHIP_DATA(pnd)->current_target->nti.nfi.abtId, 8); + int failures = 0; + ret = NFC_ETGRELEASED; + // Sometimes ping fails so we want to give the card some more chances... + while (failures < 3) { + if (nfc_initiator_transceive_bytes(pnd, abtCmd, sizeof(abtCmd), NULL, 0, 300) == 11) { + ret = NFC_SUCCESS; + break; + } else { + failures++; + } } break; case NMT_ISO14443B: From d6330a55d08148058d51273f5e1a074cae24cb08 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 30 Jan 2014 11:37:37 +0100 Subject: [PATCH 029/318] nfc_initiator_target_is_present(): better error handling --- libnfc/chips/pn53x.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index bf10933c..c9ac7391 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1736,20 +1736,20 @@ static int pn53x_Diagnose06(struct nfc_device *pnd) // Send Card Presence command const uint8_t abtCmd[] = { Diagnose, 0x06 }; uint8_t abtRx[1]; - int res = 0; + int ret = 0; // Card Presence command can take more time than default one: when a card is // removed from the field, the PN53x took few hundred ms more to reply // correctly. (ie. 700 ms should be enough to detect all tested cases) - if ((res = pn53x_transceive(pnd, abtCmd, sizeof(abtCmd), abtRx, sizeof(abtRx), 700)) < 0) - return res; - if (res == 1) { - return NFC_SUCCESS; + if ((ret = pn53x_transceive(pnd, abtCmd, sizeof(abtCmd), abtRx, sizeof(abtRx), 700)) != 1) { + // When it fails with a timeout (0x01) chip error, it means the target is not reacheable anymore + if ((ret == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { + ret = NFC_ETGRELEASED; + } + } else { + ret = NFC_SUCCESS; } - - // Target is not reachable anymore - pn53x_current_target_free(pnd); - return NFC_ETGRELEASED; + return ret; } int @@ -1780,8 +1780,6 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping -4A"); if ((CHIP_DATA(pnd)->type == PN532) || (CHIP_DATA(pnd)->type == PN533)) { ret = pn53x_Diagnose06(pnd); - // When pn53x_Diagnose06() fails with a timeout (0x01) chip error, it means the target is not reacheable anymore - if ((ret == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) ret = NFC_ETGRELEASED; } else { ret = NFC_EDEVNOTSUPP; } @@ -1871,6 +1869,8 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) ret = NFC_EDEVNOTSUPP; break; } + if (ret == NFC_ETGRELEASED) + pn53x_current_target_free(pnd); return pnd->last_error = ret; } From 62e78ab5828312702bd95b8eca5e9493cf84bca8 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 30 Jan 2014 12:55:51 +0100 Subject: [PATCH 030/318] nfc_initiator_target_is_present(): support -4B on PN532 --- libnfc/chips/pn53x.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index c9ac7391..ca507eac 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1854,10 +1854,21 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) case NMT_ISO14443B: // -4B log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping -4B"); - if ((CHIP_DATA(pnd)->type == PN532) || (CHIP_DATA(pnd)->type == PN533)) { + if (CHIP_DATA(pnd)->type == PN533) { // Not supported on PN532 even if the doc is same as for PN533 ret = pn53x_Diagnose06(pnd); } else { - ret = NFC_EDEVNOTSUPP; + // Sending R(NACK) in raw: + if ((ret = pn53x_set_property_bool(pnd, NP_EASY_FRAMING, false)) < 0) + break; + // uint8_t abtCmd[1] = {0xb2}; // if on PN533, CID=0 + uint8_t abtCmd[2] = {0xba, 0x01}; // if on PN532, CID=1 + if (nfc_initiator_transceive_bytes(pnd, abtCmd, sizeof(abtCmd), NULL, 0, 300) > 0) + ret = NFC_SUCCESS; + else + ret = NFC_ETGRELEASED; + int ret2; + if ((ret2 = pn53x_set_property_bool(pnd, NP_EASY_FRAMING, true)) < 0) + ret = ret2; } break; case NMT_JEWEL: From 9a84bb0ba0d4984d6e55d1e47485039e4b020290 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 30 Jan 2014 18:10:30 +0100 Subject: [PATCH 031/318] Split pn53x_initiator_target_is_present() for readability --- libnfc/chips/pn53x.c | 192 +++++++++++++++++++++++++------------------ 1 file changed, 112 insertions(+), 80 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index ca507eac..8518641e 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1752,6 +1752,112 @@ static int pn53x_Diagnose06(struct nfc_device *pnd) return ret; } +static int pn53x_ISO14443A_4_is_present(struct nfc_device *pnd) +{ + int ret; + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping -4A"); + if ((CHIP_DATA(pnd)->type == PN532) || (CHIP_DATA(pnd)->type == PN533)) { + ret = pn53x_Diagnose06(pnd); + } else { + ret = NFC_EDEVNOTSUPP; + } + return ret; +} + +static int pn53x_ISO14443A_MFUL_is_present(struct nfc_device *pnd) +{ + int ret; + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping MFUL"); + // Limitation: test on MFULC non-authenticated with read of first sector forbidden will fail + if (CHIP_DATA(pnd)->type == PN533) { + ret = pn53x_Diagnose06(pnd); + } else { + uint8_t abtCmd[2] = {0x30, 0x00}; + if (nfc_initiator_transceive_bytes(pnd, abtCmd, sizeof(abtCmd), NULL, 0, -1) > 0) { + ret = NFC_SUCCESS; + } else { + ret = NFC_ETGRELEASED; + } + } + return ret; +} + +static int pn53x_ISO14443A_MFC_is_present(struct nfc_device *pnd) +{ + int ret; + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping MFC"); + if ((CHIP_DATA(pnd)->type == PN533) && (CHIP_DATA(pnd)->current_target->nti.nai.btSak != 0x09)) { + // MFC Mini (atqa0004/sak09) fails on PN533, so we exclude it + ret = pn53x_Diagnose06(pnd); + } else { + // Limitation: re-select will lose authentication of already authenticated sector + // TODO: buggy when card is removed on Tikitag + uint8_t pbtInitiatorData[12]; + size_t szInitiatorData = 0; + iso14443_cascade_uid(CHIP_DATA(pnd)->current_target->nti.nai.abtUid, CHIP_DATA(pnd)->current_target->nti.nai.szUidLen, pbtInitiatorData, &szInitiatorData); + if ((ret = pn53x_initiator_select_passive_target_ext(pnd, CHIP_DATA(pnd)->current_target->nm, pbtInitiatorData, szInitiatorData, NULL, 300)) == 1) { + ret = NFC_SUCCESS; + } else if ((ret == 0) || (ret == NFC_ETIMEOUT)) { + ret = NFC_ETGRELEASED; + } + } + return ret; +} + +static int pn53x_DEP_is_present(struct nfc_device *pnd) +{ + int ret; + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping DEP"); + if ((CHIP_DATA(pnd)->type == PN531) || (CHIP_DATA(pnd)->type == PN532) || (CHIP_DATA(pnd)->type == PN533)) + ret = pn53x_Diagnose06(pnd); + else + ret = NFC_EDEVNOTSUPP; + return ret; +} + +static int pn53x_Felica_is_present(struct nfc_device *pnd) +{ + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping Felica"); + // if (CHIP_DATA(pnd)->type == PN533) { ret = pn53x_Diagnose06(pnd); } else... + // Because ping fails now & then, better not to use Diagnose at all + // Limitation: does not work on Felica Lite cards (neither Diagnose nor our method) + uint8_t abtCmd[10] = {0x0A, 0x04}; + memcpy(abtCmd + 2, CHIP_DATA(pnd)->current_target->nti.nfi.abtId, 8); + int failures = 0; + // Sometimes ping fails so we want to give the card some more chances... + while (failures < 3) { + if (nfc_initiator_transceive_bytes(pnd, abtCmd, sizeof(abtCmd), NULL, 0, 300) == 11) { + return NFC_SUCCESS; + } else { + failures++; + } + } + return NFC_ETGRELEASED; +} + +static int pn53x_ISO14443B_4_is_present(struct nfc_device *pnd) +{ + int ret; + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping -4B"); + if (CHIP_DATA(pnd)->type == PN533) { // Not supported on PN532 even if the doc is same as for PN533 + ret = pn53x_Diagnose06(pnd); + } else { + // Sending R(NACK) in raw: + if ((ret = pn53x_set_property_bool(pnd, NP_EASY_FRAMING, false)) < 0) + return ret; + // uint8_t abtCmd[1] = {0xb2}; // if on PN533, CID=0 + uint8_t abtCmd[2] = {0xba, 0x01}; // if on PN532, CID=1 + if (nfc_initiator_transceive_bytes(pnd, abtCmd, sizeof(abtCmd), NULL, 0, 300) > 0) + ret = NFC_SUCCESS; + else + ret = NFC_ETGRELEASED; + int ret2; + if ((ret2 = pn53x_set_property_bool(pnd, NP_EASY_FRAMING, true)) < 0) + ret = ret2; + } + return ret; +} + int pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) { @@ -1776,100 +1882,26 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) switch (CHIP_DATA(pnd)->current_target->nm.nmt) { case NMT_ISO14443A: if (CHIP_DATA(pnd)->current_target->nti.nai.btSak & 0x20) { - // -4A - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping -4A"); - if ((CHIP_DATA(pnd)->type == PN532) || (CHIP_DATA(pnd)->type == PN533)) { - ret = pn53x_Diagnose06(pnd); - } else { - ret = NFC_EDEVNOTSUPP; - } + ret = pn53x_ISO14443A_4_is_present(pnd); } else if ((CHIP_DATA(pnd)->current_target->nti.nai.abtAtqa[0] == 0x00) && (CHIP_DATA(pnd)->current_target->nti.nai.abtAtqa[1] == 0x44) && (CHIP_DATA(pnd)->current_target->nti.nai.btSak == 0x00)) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping MFUL"); - // MFUL - // Limitation: test on MFULC non-authenticated with read of first sector forbidden will fail - if (CHIP_DATA(pnd)->type == PN533) { - ret = pn53x_Diagnose06(pnd); - } else { - uint8_t abtCmd[2] = {0x30, 0x00}; - if (nfc_initiator_transceive_bytes(pnd, abtCmd, sizeof(abtCmd), NULL, 0, -1) > 0) { - ret = NFC_SUCCESS; - } else { - ret = NFC_ETGRELEASED; - } - } + ret = pn53x_ISO14443A_MFUL_is_present(pnd); } else if (CHIP_DATA(pnd)->current_target->nti.nai.btSak & 0x08) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping MFC"); - // MFC - if ((CHIP_DATA(pnd)->type == PN533) && (CHIP_DATA(pnd)->current_target->nti.nai.btSak != 0x09)) { - // MFC Mini (atqa0004/sak09) fails on PN533, so we exclude it - ret = pn53x_Diagnose06(pnd); - } else { - // Limitation: re-select will lose authentication of already authenticated sector - // TODO: buggy when card is removed on Tikitag - uint8_t pbtInitiatorData[12]; - size_t szInitiatorData = 0; - iso14443_cascade_uid(CHIP_DATA(pnd)->current_target->nti.nai.abtUid, CHIP_DATA(pnd)->current_target->nti.nai.szUidLen, pbtInitiatorData, &szInitiatorData); - if ((ret = pn53x_initiator_select_passive_target_ext(pnd, CHIP_DATA(pnd)->current_target->nm, pbtInitiatorData, szInitiatorData, NULL, 300)) == 1) { - ret = NFC_SUCCESS; - } else if ((ret == 0) || (ret == NFC_ETIMEOUT)) { - ret = NFC_ETGRELEASED; - } - } + ret = pn53x_ISO14443A_MFC_is_present(pnd); } else { - // unknown log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): card type A not supported"); ret = NFC_EDEVNOTSUPP; } -// TODO what about dual mode cards: MFP, JCOP etc? (MFC + -4) -// we've to detect them and it depends in which state they are break; case NMT_DEP: - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping DEP"); - if ((CHIP_DATA(pnd)->type == PN531) || (CHIP_DATA(pnd)->type == PN532) || (CHIP_DATA(pnd)->type == PN533)) - ret = pn53x_Diagnose06(pnd); - else - ret = NFC_EDEVNOTSUPP; + ret = pn53x_DEP_is_present(pnd); break; case NMT_FELICA: - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping Felica"); - // if (CHIP_DATA(pnd)->type == PN533) { ret = pn53x_Diagnose06(pnd); } else... - // Because ping fails now & then, better not to use Diagnose at all - // Limitation: does not work on Felica Lite cards (neither Diagnose nor our method) - uint8_t abtCmd[10] = {0x0A, 0x04}; - memcpy(abtCmd + 2, CHIP_DATA(pnd)->current_target->nti.nfi.abtId, 8); - int failures = 0; - ret = NFC_ETGRELEASED; - // Sometimes ping fails so we want to give the card some more chances... - while (failures < 3) { - if (nfc_initiator_transceive_bytes(pnd, abtCmd, sizeof(abtCmd), NULL, 0, 300) == 11) { - ret = NFC_SUCCESS; - break; - } else { - failures++; - } - } + ret = pn53x_Felica_is_present(pnd); break; case NMT_ISO14443B: - // -4B - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping -4B"); - if (CHIP_DATA(pnd)->type == PN533) { // Not supported on PN532 even if the doc is same as for PN533 - ret = pn53x_Diagnose06(pnd); - } else { - // Sending R(NACK) in raw: - if ((ret = pn53x_set_property_bool(pnd, NP_EASY_FRAMING, false)) < 0) - break; - // uint8_t abtCmd[1] = {0xb2}; // if on PN533, CID=0 - uint8_t abtCmd[2] = {0xba, 0x01}; // if on PN532, CID=1 - if (nfc_initiator_transceive_bytes(pnd, abtCmd, sizeof(abtCmd), NULL, 0, 300) > 0) - ret = NFC_SUCCESS; - else - ret = NFC_ETGRELEASED; - int ret2; - if ((ret2 = pn53x_set_property_bool(pnd, NP_EASY_FRAMING, true)) < 0) - ret = ret2; - } + ret = pn53x_ISO14443B_4_is_present(pnd); break; case NMT_JEWEL: case NMT_ISO14443BI: From 7d41ed34a3c77eab9ff84d3b729cacc4835a5d9c Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 30 Jan 2014 18:30:45 +0100 Subject: [PATCH 032/318] *_is_present(): more robust detection of tag gone --- libnfc/chips/pn53x.c | 51 ++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 8518641e..9781a2ae 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1737,17 +1737,23 @@ static int pn53x_Diagnose06(struct nfc_device *pnd) const uint8_t abtCmd[] = { Diagnose, 0x06 }; uint8_t abtRx[1]; int ret = 0; + int failures = 0; // Card Presence command can take more time than default one: when a card is // removed from the field, the PN53x took few hundred ms more to reply // correctly. (ie. 700 ms should be enough to detect all tested cases) - if ((ret = pn53x_transceive(pnd, abtCmd, sizeof(abtCmd), abtRx, sizeof(abtRx), 700)) != 1) { - // When it fails with a timeout (0x01) chip error, it means the target is not reacheable anymore - if ((ret == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { - ret = NFC_ETGRELEASED; + + while (failures < 2) { + if ((ret = pn53x_transceive(pnd, abtCmd, sizeof(abtCmd), abtRx, sizeof(abtRx), 700)) != 1) { + // When it fails with a timeout (0x01) chip error, it means the target is not reacheable anymore + if ((ret == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { + return NFC_ETGRELEASED; + } else { // Other errors can appear when card is tired-off, let's try again + failures++; + } + } else { + return NFC_SUCCESS; } - } else { - ret = NFC_SUCCESS; } return ret; } @@ -1773,10 +1779,17 @@ static int pn53x_ISO14443A_MFUL_is_present(struct nfc_device *pnd) ret = pn53x_Diagnose06(pnd); } else { uint8_t abtCmd[2] = {0x30, 0x00}; - if (nfc_initiator_transceive_bytes(pnd, abtCmd, sizeof(abtCmd), NULL, 0, -1) > 0) { - ret = NFC_SUCCESS; - } else { - ret = NFC_ETGRELEASED; + int failures = 0; + while (failures < 2) { + if ((ret = nfc_initiator_transceive_bytes(pnd, abtCmd, sizeof(abtCmd), NULL, 0, -1)) < 1) { + if ((ret == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Timeout + return NFC_ETGRELEASED; + } else { // Other errors can appear when card is tired-off, let's try again + failures++; + } + } else { + return NFC_SUCCESS; + } } } return ret; @@ -1847,10 +1860,20 @@ static int pn53x_ISO14443B_4_is_present(struct nfc_device *pnd) return ret; // uint8_t abtCmd[1] = {0xb2}; // if on PN533, CID=0 uint8_t abtCmd[2] = {0xba, 0x01}; // if on PN532, CID=1 - if (nfc_initiator_transceive_bytes(pnd, abtCmd, sizeof(abtCmd), NULL, 0, 300) > 0) - ret = NFC_SUCCESS; - else - ret = NFC_ETGRELEASED; + int failures = 0; + while (failures < 2) { + if ((ret = nfc_initiator_transceive_bytes(pnd, abtCmd, sizeof(abtCmd), NULL, 0, 300)) < 1) { + if ((ret == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Timeout + ret = NFC_ETGRELEASED; + break; + } else { // Other errors can appear when card is tired-off, let's try again + failures++; + } + } else { + ret = NFC_SUCCESS; + break; + } + } int ret2; if ((ret2 = pn53x_set_property_bool(pnd, NP_EASY_FRAMING, true)) < 0) ret = ret2; From 71eda315c70c9acdd69b84bcea9e83c5edacfde0 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 31 Jan 2014 22:33:05 +0100 Subject: [PATCH 033/318] nfc_initiator_target_is_present(): Fix MFC support on PN532 --- libnfc/chips/pn53x.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 9781a2ae..df0aec1e 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1804,10 +1804,12 @@ static int pn53x_ISO14443A_MFC_is_present(struct nfc_device *pnd) ret = pn53x_Diagnose06(pnd); } else { // Limitation: re-select will lose authentication of already authenticated sector - // TODO: buggy when card is removed on Tikitag + // Limitation: NP_INFINITE_SELECT will be left as FALSE (we cannot restore as we don't know what was the original state) uint8_t pbtInitiatorData[12]; size_t szInitiatorData = 0; iso14443_cascade_uid(CHIP_DATA(pnd)->current_target->nti.nai.abtUid, CHIP_DATA(pnd)->current_target->nti.nai.szUidLen, pbtInitiatorData, &szInitiatorData); + if ((ret = pn53x_set_property_bool(pnd, NP_INFINITE_SELECT, false)) < 0) + return ret; if ((ret = pn53x_initiator_select_passive_target_ext(pnd, CHIP_DATA(pnd)->current_target->nm, pbtInitiatorData, szInitiatorData, NULL, 300)) == 1) { ret = NFC_SUCCESS; } else if ((ret == 0) || (ret == NFC_ETIMEOUT)) { From 81e1dd715d1d32c624abfd0deec372bcac086a6b Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 31 Jan 2014 23:19:04 +0100 Subject: [PATCH 034/318] nfc_initiator_target_is_present(): Fix error type in case no target is selected yet --- libnfc/chips/pn53x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index df0aec1e..d0e888fa 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1893,7 +1893,7 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) // only if pnt is provided but it's not intuitive that // nfc_initiator_select_passive_target(pnt=NULL) + target_is_present(pnt=NULL) fails // Maybe we should have an internal copy of nt, no matter if a pnt was provided - return pnd->last_error = NFC_ETGRELEASED; + return pnd->last_error = NFC_EINVARG; } // Check if the argument target nt is equals to current saved target From e11c5254af891191fda8d0f13f2e2fe4b9f0f4a8 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 31 Jan 2014 23:53:29 +0100 Subject: [PATCH 035/318] nfc_initiator_select_passive_target(): save current target info also for ISO14443B* --- libnfc/chips/pn53x.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index d0e888fa..b543c31a 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1127,6 +1127,10 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, if ((res = pn53x_decode_target_data(abtTargetsData, szTargetsData, CHIP_DATA(pnd)->type, nm.nmt, &(pnt->nti))) < 0) { return res; } + if (pn53x_current_target_new(pnd, pnt) == NULL) { + pnd->last_error = NFC_ESOFT; + return pnd->last_error; + } } if (nm.nmt == NMT_ISO14443BI) { // Select tag From 510228b6e08d28a9019266190658847cbfbe2d13 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 1 Feb 2014 00:56:08 +0100 Subject: [PATCH 036/318] nfc_initiator_select_passive_target(): save current target info even if pnt=NULL --- libnfc/chips/pn53x.c | 58 ++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 34 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index b543c31a..779045d8 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1066,6 +1066,7 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, uint8_t abtTargetsData[PN53x_EXTENDED_FRAME__DATA_MAX_LEN]; size_t szTargetsData = sizeof(abtTargetsData); int res = 0; + nfc_target nttmp; if (nm.nmt == NMT_ISO14443BI || nm.nmt == NMT_ISO14443B2SR || nm.nmt == NMT_ISO14443B2CT) { if (CHIP_DATA(pnd)->type == RCS360) { @@ -1121,16 +1122,9 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, } szTargetsData = 6; // u16 UID_LSB, u8 prod code, u8 fab code, u16 UID_MSB } - if (pnt) { - pnt->nm = nm; - // Fill the tag info struct with the values corresponding to this init modulation - if ((res = pn53x_decode_target_data(abtTargetsData, szTargetsData, CHIP_DATA(pnd)->type, nm.nmt, &(pnt->nti))) < 0) { - return res; - } - if (pn53x_current_target_new(pnd, pnt) == NULL) { - pnd->last_error = NFC_ESOFT; - return pnd->last_error; - } + nttmp.nm = nm; + if ((res = pn53x_decode_target_data(abtTargetsData, szTargetsData, CHIP_DATA(pnd)->type, nm.nmt, &(nttmp.nti))) < 0) { + return res; } if (nm.nmt == NMT_ISO14443BI) { // Select tag @@ -1142,32 +1136,32 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, } szTargetsData = (size_t)res; } - return abtTargetsData[0]; - } // else: + } else { - const pn53x_modulation pm = pn53x_nm_to_pm(nm); - if (PM_UNDEFINED == pm) { - pnd->last_error = NFC_EINVARG; - return pnd->last_error; - } + const pn53x_modulation pm = pn53x_nm_to_pm(nm); + if (PM_UNDEFINED == pm) { + pnd->last_error = NFC_EINVARG; + return pnd->last_error; + } - if ((res = pn53x_InListPassiveTarget(pnd, pm, 1, pbtInitData, szInitData, abtTargetsData, &szTargetsData, timeout)) <= 0) - return res; + if ((res = pn53x_InListPassiveTarget(pnd, pm, 1, pbtInitData, szInitData, abtTargetsData, &szTargetsData, timeout)) <= 0) + return res; - if (szTargetsData <= 1) // For Coverity to know szTargetsData is always > 1 if res > 0 - return 0; + if (szTargetsData <= 1) // For Coverity to know szTargetsData is always > 1 if res > 0 + return 0; - // Is a tag info struct available - if (pnt) { - pnt->nm = nm; - // Fill the tag info struct with the values corresponding to this init modulation - if ((res = pn53x_decode_target_data(abtTargetsData + 1, szTargetsData - 1, CHIP_DATA(pnd)->type, nm.nmt, &(pnt->nti))) < 0) { + nttmp.nm = nm; + if ((res = pn53x_decode_target_data(abtTargetsData + 1, szTargetsData - 1, CHIP_DATA(pnd)->type, nm.nmt, &(nttmp.nti))) < 0) { return res; } - if (pn53x_current_target_new(pnd, pnt) == NULL) { - pnd->last_error = NFC_ESOFT; - return pnd->last_error; - } + } + if (pn53x_current_target_new(pnd, &nttmp) == NULL) { + pnd->last_error = NFC_ESOFT; + return pnd->last_error; + } + // Is a tag info struct available + if (pnt) { + memcpy(pnt, &nttmp, sizeof(nfc_target)); } return abtTargetsData[0]; } @@ -1893,10 +1887,6 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) // Check if there is a saved target if (CHIP_DATA(pnd)->current_target == NULL) { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): no saved target"); -// TODO pnt is optional for select_passive_target() and internal nt struct is saved -// only if pnt is provided but it's not intuitive that -// nfc_initiator_select_passive_target(pnt=NULL) + target_is_present(pnt=NULL) fails -// Maybe we should have an internal copy of nt, no matter if a pnt was provided return pnd->last_error = NFC_EINVARG; } From 69c4d0768a9720f7365c8dade0d4ca80f1ce5c88 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 1 Feb 2014 02:01:10 +0100 Subject: [PATCH 037/318] nfc_initiator_select_passive_target(): grant NP_INFINITE_SELECT also for ISO14443B* --- libnfc/chips/pn53x.c | 110 +++++++++++++++++++++++++----------------- libnfc/nfc-device.c | 1 + libnfc/nfc-internal.h | 2 + 3 files changed, 68 insertions(+), 45 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 779045d8..21affef7 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -895,6 +895,7 @@ pn53x_set_property_bool(struct nfc_device *pnd, const nfc_property property, con // TODO Made some research around this point: // timings could be tweak better than this, and maybe we can tweak timings // to "gain" a sort-of hardware polling (ie. like PN532 does) + pnd->bInfiniteSelect = bEnable; return pn53x_RFConfiguration__MaxRetries(pnd, (bEnable) ? 0xff : 0x00, // MxRtyATR, default: active = 0xff, passive = 0x02 (bEnable) ? 0xff : 0x01, // MxRtyPSL, default: 0x01 @@ -1084,58 +1085,77 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, if ((res = nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true)) < 0) { return res; } - pnd->bEasyFraming = false; - if (nm.nmt == NMT_ISO14443B2SR) { - // Some work to do before getting the UID... - uint8_t abtInitiate[] = "\x06\x00"; - size_t szInitiateLen = 2; - uint8_t abtSelect[] = { 0x0e, 0x00 }; - uint8_t abtRx[1]; - // Getting random Chip_ID - if ((res = pn53x_initiator_transceive_bytes(pnd, abtInitiate, szInitiateLen, abtRx, sizeof(abtRx), timeout)) < 0) { - return res; + if ((res = nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, false)) < 0) { + return res; + } + bool found = false; + do { + if (nm.nmt == NMT_ISO14443B2SR) { + // Some work to do before getting the UID... + uint8_t abtInitiate[] = "\x06\x00"; + size_t szInitiateLen = 2; + uint8_t abtSelect[] = { 0x0e, 0x00 }; + uint8_t abtRx[1]; + // Getting random Chip_ID + if ((res = pn53x_initiator_transceive_bytes(pnd, abtInitiate, szInitiateLen, abtRx, sizeof(abtRx), timeout)) < 0) { + if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout + continue; + } else + return res; + } + abtSelect[1] = abtRx[0]; + if ((res = pn53x_initiator_transceive_bytes(pnd, abtSelect, sizeof(abtSelect), abtRx, sizeof(abtRx), timeout)) < 0) { + return res; + } + szTargetsData = (size_t)res; + } else if (nm.nmt == NMT_ISO14443B2CT) { + // Some work to do before getting the UID... + const uint8_t abtReqt[] = { 0x10 }; + // Getting product code / fab code & store it in output buffer after the serial nr we'll obtain later + if ((res = pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), abtTargetsData + 2, sizeof(abtTargetsData) - 2, timeout)) < 0) { + if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout + continue; + } else + return res; + } + szTargetsData = (size_t)res; } - abtSelect[1] = abtRx[0]; - if ((res = pn53x_initiator_transceive_bytes(pnd, abtSelect, sizeof(abtSelect), abtRx, sizeof(abtRx), timeout)) < 0) { - return res; + + if ((res = pn53x_initiator_transceive_bytes(pnd, pbtInitData, szInitData, abtTargetsData, sizeof(abtTargetsData), timeout)) < 0) { + if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout + continue; + } else + return res; } szTargetsData = (size_t)res; - } else if (nm.nmt == NMT_ISO14443B2CT) { - // Some work to do before getting the UID... - const uint8_t abtReqt[] = { 0x10 }; - // Getting product code / fab code & store it in output buffer after the serial nr we'll obtain later - if ((res = pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), abtTargetsData + 2, sizeof(abtTargetsData) - 2, timeout)) < 0) { - return res; + if (nm.nmt == NMT_ISO14443B2CT) { + if (szTargetsData != 2) + return 0; // Target is not ISO14443B2CT + uint8_t abtRead[] = { 0xC4 }; // Reading UID_MSB (Read address 4) + if ((res = pn53x_initiator_transceive_bytes(pnd, abtRead, sizeof(abtRead), abtTargetsData + 4, sizeof(abtTargetsData) - 4, timeout)) < 0) { + return res; + } + szTargetsData = 6; // u16 UID_LSB, u8 prod code, u8 fab code, u16 UID_MSB } - szTargetsData = (size_t)res; - } - if ((res = pn53x_initiator_transceive_bytes(pnd, pbtInitData, szInitData, abtTargetsData, sizeof(abtTargetsData), timeout)) < 0) { - return res; - } - szTargetsData = (size_t)res; - if (nm.nmt == NMT_ISO14443B2CT) { - if (szTargetsData != 2) - return 0; // Target is not ISO14443B2CT - uint8_t abtRead[] = { 0xC4 }; // Reading UID_MSB (Read address 4) - if ((res = pn53x_initiator_transceive_bytes(pnd, abtRead, sizeof(abtRead), abtTargetsData + 4, sizeof(abtTargetsData) - 4, timeout)) < 0) { + nttmp.nm = nm; + if ((res = pn53x_decode_target_data(abtTargetsData, szTargetsData, CHIP_DATA(pnd)->type, nm.nmt, &(nttmp.nti))) < 0) { return res; } - szTargetsData = 6; // u16 UID_LSB, u8 prod code, u8 fab code, u16 UID_MSB - } - nttmp.nm = nm; - if ((res = pn53x_decode_target_data(abtTargetsData, szTargetsData, CHIP_DATA(pnd)->type, nm.nmt, &(nttmp.nti))) < 0) { - return res; - } - if (nm.nmt == NMT_ISO14443BI) { - // Select tag - uint8_t abtAttrib[6]; - memcpy(abtAttrib, abtTargetsData, sizeof(abtAttrib)); - abtAttrib[1] = 0x0f; // ATTRIB - if ((res = pn53x_initiator_transceive_bytes(pnd, abtAttrib, sizeof(abtAttrib), NULL, 0, timeout)) < 0) { - return res; + if (nm.nmt == NMT_ISO14443BI) { + // Select tag + uint8_t abtAttrib[6]; + memcpy(abtAttrib, abtTargetsData, sizeof(abtAttrib)); + abtAttrib[1] = 0x0f; // ATTRIB + if ((res = pn53x_initiator_transceive_bytes(pnd, abtAttrib, sizeof(abtAttrib), NULL, 0, timeout)) < 0) { + return res; + } + szTargetsData = (size_t)res; } - szTargetsData = (size_t)res; - } + found = true; + break; + } while (pnd->bInfiniteSelect); + if (! found) + return 0; } else { const pn53x_modulation pm = pn53x_nm_to_pm(nm); diff --git a/libnfc/nfc-device.c b/libnfc/nfc-device.c index 39969552..563f6872 100644 --- a/libnfc/nfc-device.c +++ b/libnfc/nfc-device.c @@ -57,6 +57,7 @@ nfc_device_new(const nfc_context *context, const nfc_connstring connstring) res->bCrc = false; res->bPar = false; res->bEasyFraming = false; + res->bInfiniteSelect = false; res->bAutoIso14443_4 = false; res->last_error = 0; memcpy(res->connstring, connstring, sizeof(res->connstring)); diff --git a/libnfc/nfc-internal.h b/libnfc/nfc-internal.h index cfe77b44..0e63c936 100644 --- a/libnfc/nfc-internal.h +++ b/libnfc/nfc-internal.h @@ -203,6 +203,8 @@ struct nfc_device { bool bPar; /** Should the chip handle frames encapsulation and chaining */ bool bEasyFraming; + /** Should the chip try forever on select? */ + bool bInfiniteSelect; /** Should the chip switch automatically activate ISO14443-4 when selecting tags supporting it? */ bool bAutoIso14443_4; From 827d9792dd13ac42939e56fd5d2a4c5b2bda990a Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 1 Feb 2014 02:32:57 +0100 Subject: [PATCH 038/318] Save & restore NP_INFINITE_SELECT status when changing it internally --- libnfc/chips/pn53x.c | 22 ++++++++++++++++++---- libnfc/nfc.c | 28 +++++++++++++++++++++++----- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 21affef7..4a950f01 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1244,6 +1244,8 @@ pn53x_initiator_poll_target(struct nfc_device *pnd, break; } } else { + bool bInfiniteSelect = pnd->bInfiniteSelect; + int result = 0; if ((res = pn53x_set_property_bool(pnd, NP_INFINITE_SELECT, true)) < 0) return res; // FIXME It does not support DEP targets @@ -1257,16 +1259,23 @@ pn53x_initiator_poll_target(struct nfc_device *pnd, if ((res = pn53x_initiator_select_passive_target_ext(pnd, pnmModulations[n], pbtInitiatorData, szInitiatorData, pnt, timeout_ms)) < 0) { if (pnd->last_error != NFC_ETIMEOUT) { - return pnd->last_error; + result = pnd->last_error; + goto end; } } else { - return res; + result = res; + goto end; } } } } while (uiPollNr == 0xff); // uiPollNr==0xff means infinite polling // We reach this point when each listing give no result, we simply have to return 0 - return 0; +end: + if (! bInfiniteSelect) { + if ((res = pn53x_set_property_bool(pnd, NP_INFINITE_SELECT, false)) < 0) + return res; + } + return result; } return NFC_ECHIP; } @@ -1822,7 +1831,7 @@ static int pn53x_ISO14443A_MFC_is_present(struct nfc_device *pnd) ret = pn53x_Diagnose06(pnd); } else { // Limitation: re-select will lose authentication of already authenticated sector - // Limitation: NP_INFINITE_SELECT will be left as FALSE (we cannot restore as we don't know what was the original state) + bool bInfiniteSelect = pnd->bInfiniteSelect; uint8_t pbtInitiatorData[12]; size_t szInitiatorData = 0; iso14443_cascade_uid(CHIP_DATA(pnd)->current_target->nti.nai.abtUid, CHIP_DATA(pnd)->current_target->nti.nai.szUidLen, pbtInitiatorData, &szInitiatorData); @@ -1833,6 +1842,11 @@ static int pn53x_ISO14443A_MFC_is_present(struct nfc_device *pnd) } else if ((ret == 0) || (ret == NFC_ETIMEOUT)) { ret = NFC_ETGRELEASED; } + if (bInfiniteSelect) { + int ret2; + if ((ret2 = pn53x_set_property_bool(pnd, NP_INFINITE_SELECT, true)) < 0) + return ret2; + } } return ret; } diff --git a/libnfc/nfc.c b/libnfc/nfc.c index dcfd409c..dce7ffd4 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -573,6 +573,7 @@ nfc_initiator_list_passive_targets(nfc_device *pnd, pnd->last_error = 0; // Let the reader only try once to find a tag + bool bInfiniteSelect = pnd->bInfiniteSelect; if ((res = nfc_device_set_property_bool(pnd, NP_INFINITE_SELECT, false)) < 0) { return res; } @@ -603,6 +604,11 @@ nfc_initiator_list_passive_targets(nfc_device *pnd, break; } } + if (bInfiniteSelect) { + if ((res = nfc_device_set_property_bool(pnd, NP_INFINITE_SELECT, true)) < 0) { + return res; + } + } return szTargetFound; } @@ -684,18 +690,30 @@ nfc_initiator_poll_dep_target(struct nfc_device *pnd, const int period = 300; int remaining_time = timeout; int res; + int result = 0; + bool bInfiniteSelect = pnd->bInfiniteSelect; if ((res = nfc_device_set_property_bool(pnd, NP_INFINITE_SELECT, true)) < 0) return res; while (remaining_time > 0) { if ((res = nfc_initiator_select_dep_target(pnd, ndm, nbr, pndiInitiator, pnt, period)) < 0) { - if (res != NFC_ETIMEOUT) - return res; + if (res != NFC_ETIMEOUT) { + result = res; + goto end; + } + } + if (res == 1) { + result = res; + goto end; } - if (res == 1) - return res; remaining_time -= period; } - return 0; +end: + if (! bInfiniteSelect) { + if ((res = nfc_device_set_property_bool(pnd, NP_INFINITE_SELECT, false)) < 0) { + return res; + } + } + return result; } /** @ingroup initiator From ef81f0634457f171495eee3d7df208cfdba46c38 Mon Sep 17 00:00:00 2001 From: Pim 't Hart Date: Mon, 3 Feb 2014 00:04:08 +0100 Subject: [PATCH 039/318] Adding nfc-jewel util --- utils/CMakeLists.txt | 5 + utils/Makefile.am | 5 + utils/jewel.c | 109 +++++++++++++++ utils/jewel.h | 216 +++++++++++++++++++++++++++++ utils/nfc-jewel.1 | 54 ++++++++ utils/nfc-jewel.c | 315 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 704 insertions(+) create mode 100644 utils/jewel.c create mode 100644 utils/jewel.h create mode 100644 utils/nfc-jewel.1 create mode 100644 utils/nfc-jewel.c diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index b00411f6..dc7bac93 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -1,5 +1,6 @@ SET(UTILS-SOURCES nfc-emulate-forum-tag4 + nfc-jewel nfc-list nfc-mfclassic nfc-mfultralight @@ -26,6 +27,10 @@ FOREACH(source ${UTILS-SOURCES}) LIST(APPEND TARGETS ${CMAKE_CURRENT_BINARY_DIR}/../windows/${source}.rc) ENDIF(WIN32) + IF(${source} MATCHES "nfc-jewel") + LIST(APPEND TARGETS jewel) + ENDIF(${source} MATCHES "nfc-jewel") + IF((${source} MATCHES "nfc-mfultralight") OR (${source} MATCHES "nfc-mfclassic")) LIST(APPEND TARGETS mifare) ENDIF((${source} MATCHES "nfc-mfultralight") OR (${source} MATCHES "nfc-mfclassic")) diff --git a/utils/Makefile.am b/utils/Makefile.am index 29fd17ed..9637d254 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -1,5 +1,6 @@ bin_PROGRAMS = \ nfc-emulate-forum-tag4 \ + nfc-jewel \ nfc-list \ nfc-mfclassic \ nfc-mfultralight \ @@ -18,6 +19,9 @@ 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 +nfc_jewel_SOURCES = nfc-jewel.c jewel.c jewel.h nfc-utils.h +nfc_jewel_LDADD = $(top_builddir)/libnfc/libnfc.la + nfc_list_SOURCES = nfc-list.c nfc-utils.h nfc_list_LDADD = $(top_builddir)/libnfc/libnfc.la \ libnfcutils.la @@ -43,6 +47,7 @@ nfc_scan_device_LDADD = $(top_builddir)/libnfc/libnfc.la \ dist_man_MANS = \ nfc-emulate-forum-tag4.1 \ + nfc-jewel.1 \ nfc-list.1 \ nfc-mfclassic.1 \ nfc-mfultralight.1 \ diff --git a/utils/jewel.c b/utils/jewel.c new file mode 100644 index 00000000..cf9bf417 --- /dev/null +++ b/utils/jewel.c @@ -0,0 +1,109 @@ +/*- + * Free/Libre Near Field Communication (NFC) library + * + * Libnfc historical contributors: + * Copyright (C) 2009 Roel Verdult + * Copyright (C) 2009-2013 Romuald Conty + * Copyright (C) 2010-2012 Romain Tartière + * Copyright (C) 2010-2013 Philippe Teuwen + * Copyright (C) 2012-2013 Ludovic Rousseau + * See AUTHORS file for a more comprehensive list of contributors. + * Additional contributors of this file: + * Copyright (C) 2014 Pim 't Hart + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1) Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2 )Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Note that this license only applies on the examples, NFC library itself is under LGPL + * + */ +/** + * @file jewel.c + * @brief provide samples structs and functions to manipulate Jewel Topaz tags using libnfc + */ +#include "jewel.h" + +#include + +#include + +/** + * @brief Execute a Jewel Topaz Command + * @return Returns true if action was successfully performed; otherwise returns false. + * @param req The request + * @param res The response + * + */ + +bool +nfc_initiator_jewel_cmd(nfc_device *pnd, const jewel_req req, jewel_res *pres) +{ + size_t nLenReq; + size_t nLenRes; + + switch (req.rid.btCmd) { + case TC_RID: + nLenReq = sizeof(jewel_req_rid); + nLenRes = sizeof(jewel_res_rid); + break; + case TC_RALL: + nLenReq = sizeof(jewel_req_rall); + nLenRes = sizeof(jewel_res_rall); + break; + case TC_READ: + nLenReq = sizeof(jewel_req_read); + nLenRes = sizeof(jewel_res_read); + break; + case TC_WRITEE: + nLenReq = sizeof(jewel_req_writee); + nLenRes = sizeof(jewel_res_writee); + break; + case TC_WRITENE: + nLenReq = sizeof(jewel_req_writene); + nLenRes = sizeof(jewel_res_writene); + break; + case TC_RSEG: + nLenReq = sizeof(jewel_req_rseg); + nLenRes = sizeof(jewel_res_rseg); + break; + case TC_READ8: + nLenReq = sizeof(jewel_req_read8); + nLenRes = sizeof(jewel_res_read8); + break; + case TC_WRITEE8: + nLenReq = sizeof(jewel_req_writee8); + nLenRes = sizeof(jewel_res_writee8); + break; + case TC_WRITENE8: + nLenReq = sizeof(jewel_req_writene8); + nLenRes = sizeof(jewel_res_writene8); + break; + default: + return false; + break; + } + + if (nfc_initiator_transceive_bytes(pnd, (uint8_t *)&req, nLenReq, (uint8_t *)pres, nLenRes, -1) < 0) { + nfc_perror(pnd, "nfc_initiator_transceive_bytes"); + return false; + } + + return true; +} diff --git a/utils/jewel.h b/utils/jewel.h new file mode 100644 index 00000000..18f39b92 --- /dev/null +++ b/utils/jewel.h @@ -0,0 +1,216 @@ +/*- + * Free/Libre Near Field Communication (NFC) library + * + * Libnfc historical contributors: + * Copyright (C) 2009 Roel Verdult + * Copyright (C) 2009-2013 Romuald Conty + * Copyright (C) 2010-2012 Romain Tartière + * Copyright (C) 2010-2013 Philippe Teuwen + * Copyright (C) 2012-2013 Ludovic Rousseau + * See AUTHORS file for a more comprehensive list of contributors. + * Additional contributors of this file: + * Copyright (C) 2014 Pim 't Hart + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1) Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2 )Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Note that this license only applies on the examples, NFC library itself is under LGPL + * + */ + +/** + * @file jewel.h + * @brief provide samples structs and functions to manipulate Jewel Topaz tags using libnfc + */ + +#ifndef _LIBNFC_JEWEL_H_ +# define _LIBNFC_JEWEL_H_ + +# include + +// Compiler directive, set struct alignment to 1 uint8_t for compatibility +# pragma pack(1) + +typedef enum { + TC_RID = 0x78, // Read ID + // List of commands (Static memory model) + TC_RALL = 0x00, // Real All + TC_READ = 0x01, // Read (single byte) + TC_WRITEE = 0x53, // Write-with-Erase (single byte) + TC_WRITENE = 0x1A, // Write-without-Erase (single byte) + // List of commands (Dynamic memory model) + TC_RSEG = 0x10, // Read segment + TC_READ8 = 0x02, // Read (8-bytes) + TC_WRITEE8 = 0x54, // Write-with-Erase (8 bytes) + TC_WRITENE8 = 0x1B // Write-without-Erase (8 byes) +} jewel_cmd; + +// Jewel request +typedef struct { + uint8_t btCmd; +} jewel_req_rid; + +typedef struct { + uint8_t btCmd; +} jewel_req_rall; + +typedef struct { + uint8_t btCmd; + uint8_t btAdd; +} jewel_req_read; + +typedef struct { + uint8_t btCmd; + uint8_t btAdd; + uint8_t btDat; +} jewel_req_writee; + +typedef struct { + uint8_t btCmd; + uint8_t btAdd; + uint8_t btDat; +} jewel_req_writene; + +typedef struct { + uint8_t btCmd; + uint8_t btAddS; +} jewel_req_rseg; + +typedef struct { + uint8_t btCmd; + uint8_t btAdd8; +} jewel_req_read8; + +typedef struct { + uint8_t btCmd; + uint8_t btAdd8; + uint8_t abtDat[8]; +} jewel_req_writee8; + +typedef struct { + uint8_t btCmd; + uint8_t btAdd8; + uint8_t abtDat[8]; +} jewel_req_writene8; + +typedef union { + jewel_req_rid rid; + jewel_req_rall rall; + jewel_req_read read; + jewel_req_writee writee; + jewel_req_writene writene; + jewel_req_rseg rseg; + jewel_req_read8 read8; + jewel_req_writee8 writee8; + jewel_req_writene8 writene8; +} jewel_req; + +// Jewel responses +typedef struct { + uint8_t abtHr[2]; + uint8_t abtUid[4]; // 4-LSB from UID +} jewel_res_rid; + +typedef struct { + uint8_t abtHr[2]; + uint8_t abtDat[104]; // Block 0 - E, but not block D (reserved) +} jewel_res_rall; + +typedef struct { + uint8_t btDat; +} jewel_res_read; + +typedef struct { + uint8_t btDat; +} jewel_res_writee; + +typedef struct { + uint8_t btDat; +} jewel_res_writene; + +typedef struct { + uint8_t abtDat[128]; +} jewel_res_rseg; + +typedef struct { + uint8_t abtDat[8]; +} jewel_res_read8; + +typedef struct { + uint8_t abtDat[8]; +} jewel_res_writee8; + +typedef struct { + uint8_t abtDat[8]; +} jewel_res_writene8; + +typedef union { + jewel_res_rid rid; + jewel_res_rall rall; + jewel_res_read read; + jewel_res_writee writee; + jewel_res_writene writene; + jewel_res_rseg rseg; + jewel_res_read8 read8; + jewel_res_writee8 writee8; + jewel_res_writene8 writene8; +} jewel_res; + +// Jewel tag +typedef struct { + uint8_t abtUid[7]; + uint8_t btReserved; +} jewel_block_uid; + +typedef struct { + uint8_t abtData[8]; +} jewel_block_data; + +typedef struct { + uint8_t abtReserved[8]; +} jewel_block_reserved; + +typedef struct { + uint8_t abtLock[2]; + uint8_t abtOtp[6]; +} jewel_block_lockotp; + +typedef struct { + jewel_block_uid bu; + jewel_block_data abd[12]; + jewel_block_reserved br; + jewel_block_lockotp bl; +} jewel_tag_blocks; + +typedef struct { + uint8_t abtData[112]; +} jewel_tag_data; + +typedef union { + jewel_tag_blocks ttb; + jewel_tag_data ttd; +} jewel_tag; + +// Reset struct alignment to default +# pragma pack() + +bool nfc_initiator_jewel_cmd(nfc_device *pnd, const jewel_req req, jewel_res *pres); + +#endif // _LIBNFC_JEWEL_H_ diff --git a/utils/nfc-jewel.1 b/utils/nfc-jewel.1 new file mode 100644 index 00000000..c0431035 --- /dev/null +++ b/utils/nfc-jewel.1 @@ -0,0 +1,54 @@ +.TH nfc-jewel 1 "Feb 02, 2014" "libnfc" "NFC Utilities" +.SH NAME +nfc-jewel \- Jewel command line tool +.SH SYNOPSIS +.B nfc-jewel +.RI \fR\fBr\fR|\fBw\fR +.IR DUMP + +.SH DESCRIPTION +.B nfc-jewel +is a Jewel tool that allows one to read or write +a tag data to/from a +.IR DUMP +file. + +Jewel tag by Broadcom, previously Innovision, uses a binary Dump file to store data for all sectors. + +Be cautious that some parts of a Jewel memory can be written only once +and some parts are used as lock bits, so please read the tag documentation +before experimenting too much! + +.SH OPTIONS +.BR r " | " w +Perform read from ( +.B r +) or write to ( +.B w +) card. +.TP +.IR DUMP +JeWel Dump (JWD) used to write (card to JWD) or (JWD to card) + +.SH BUGS +Please report any bugs on the +.B libnfc +issue tracker at: +.br +.BR http://code.google.com/p/libnfc/issues +.SH LICENCE +.B libnfc +is licensed under the GNU Lesser General Public License (LGPL), version 3. +.br +.B libnfc-utils +and +.B libnfc-examples +are covered by the the BSD 2-Clause license. + +.SH AUTHORS +Roel Verdult , +.br +Romuald Conty . +.PP +This manual page was written by Romuald Conty . +It is licensed under the terms of the GNU GPL (version 2 or later). diff --git a/utils/nfc-jewel.c b/utils/nfc-jewel.c new file mode 100644 index 00000000..19bd3cd8 --- /dev/null +++ b/utils/nfc-jewel.c @@ -0,0 +1,315 @@ +/*- + * Free/Libre Near Field Communication (NFC) library + * + * Libnfc historical contributors: + * Copyright (C) 2009 Roel Verdult + * Copyright (C) 2009-2013 Romuald Conty + * Copyright (C) 2010-2012 Romain Tartière + * Copyright (C) 2010-2013 Philippe Teuwen + * Copyright (C) 2012-2013 Ludovic Rousseau + * See AUTHORS file for a more comprehensive list of contributors. + * Additional contributors of this file: + * Copyright (C) 2014 Pim 't Hart + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1) Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2 )Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Note that this license only applies on the examples, NFC library itself is under LGPL + * + */ + +/** + * @file nfc-jewel.c + * @brief Jewel dump/restore tool + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif // HAVE_CONFIG_H + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "nfc-utils.h" +#include "jewel.h" + +static nfc_device *pnd; +static nfc_target nt; +static jewel_req req; +static jewel_res res; +static jewel_tag ttDump; +static uint32_t uiBlocks = 0x0E; +static uint32_t uiBytesPerBlock = 0x08; + +static const nfc_modulation nmJewel = { + .nmt = NMT_JEWEL, + .nbr = NBR_106, +}; + +static void +print_success_or_failure(bool bFailure, uint32_t *uiCounter) +{ + printf("%c", (bFailure) ? 'x' : '.'); + if (uiCounter) + *uiCounter += (bFailure) ? 0 : 1; +} + +static bool +read_card(void) +{ + uint32_t block; + uint32_t byte; + bool bFailure = false; + uint32_t uiReadBlocks = 0; + + printf("Reading %d blocks |", uiBlocks + 1); + + for (block = 0; block <= uiBlocks; block++) { + for (byte = 0; byte < uiBytesPerBlock; byte++) { + + // Try to read the byte + req.read.btCmd = TC_READ; + req.read.btAdd = (block << 3) + byte; + if (nfc_initiator_jewel_cmd(pnd, req, &res)) { + ttDump.ttd.abtData[(block << 3) + byte] = res.read.btDat; + } else { + bFailure = true; + break; + } + } + + print_success_or_failure(bFailure, &uiReadBlocks); + fflush(stdout); + } + printf("|\n"); + printf("Done, %d of %d blocks read.\n", uiReadBlocks, uiBlocks + 1); + + return (!bFailure); +} + +static bool +write_card(void) +{ + uint32_t block; + uint32_t byte; + bool bFailure = false; + uint32_t uiWrittenBlocks = 0; + uint32_t uiSkippedBlocks = 0; + uint32_t uiPartialBlocks = 0; + + char buffer[BUFSIZ]; + bool write_otp; + bool write_lock; + + printf("Write Lock bytes ? [yN] "); + if (!fgets(buffer, BUFSIZ, stdin)) { + ERR("Unable to read standard input."); + } + write_lock = ((buffer[0] == 'y') || (buffer[0] == 'Y')); + + printf("Write OTP bytes ? [yN] "); + if (!fgets(buffer, BUFSIZ, stdin)) { + ERR("Unable to read standard input."); + } + write_otp = ((buffer[0] == 'y') || (buffer[0] == 'Y')); + + printf("Writing %d pages |", uiBlocks + 1); + + // Skip block 0 - as far as I know there are no Jewel tags with block 0 writeable + printf("s"); + uiSkippedBlocks++; + + for (block = uiSkippedBlocks; block <= uiBlocks; block++) { + // Skip block 0x0D - it is reserved for internal use and can't be written + if ((block == 0x0D)) { + printf("s"); + uiSkippedBlocks++; + continue; + } + // Skip block 0X0E if lock-bits and OTP shouldn't be written + if ((block == 0x0E) && (!write_lock) && (!write_otp)) { + printf("s"); + uiSkippedBlocks++; + continue; + } + // Write block 0x0E partially if lock-bits or OTP shouldn't be written + if ((block == 0x0E) && (!write_lock || !write_otp)) { + printf("p"); + uiPartialBlocks++; + } + + for (byte = 0; byte < uiBytesPerBlock; byte++) { + if ((block == 0x0E) && (byte == 0 || byte == 1) && (!write_lock)) { + continue; + } + if ((block == 0x0E) && (byte > 1) && (!write_otp)) { + continue; + } + + // 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, nmJewel, NULL, 0, &nt) <= 0) { + ERR("tag was removed"); + return false; + } + bFailure = false; + } + + req.writee.btCmd = TC_WRITEE; + req.writee.btAdd = (block << 3) + byte; + req.writee.btDat = ttDump.ttd.abtData[(block << 3) + byte]; + if (!nfc_initiator_jewel_cmd(pnd, req, &res)) { + bFailure = true; + } + } + print_success_or_failure(bFailure, &uiWrittenBlocks); + fflush(stdout); + } + printf("|\n"); + printf("Done, %d of %d blocks written (%d blocks partial, %d blocks skipped).\n", uiWrittenBlocks, uiBlocks + 1, uiPartialBlocks, uiSkippedBlocks); + + return true; +} + +int +main(int argc, const char *argv[]) +{ + bool bReadAction; + FILE *pfDump; + + if (argc < 3) { + printf("\n"); + printf("%s r|w \n", argv[0]); + printf("\n"); + printf("r|w - Perform read from or write to card\n"); + printf(" - JeWel Dump (JWD) used to write (card to JWD) or (JWD to card)\n"); + printf("\n"); + exit(EXIT_FAILURE); + } + + DBG("\nChecking arguments and settings\n"); + + bReadAction = tolower((int)((unsigned char) * (argv[1])) == 'r'); + + if (bReadAction) { + memset(&ttDump, 0x00, sizeof(ttDump)); + } else { + pfDump = fopen(argv[2], "rb"); + + if (pfDump == NULL) { + ERR("Could not open dump file: %s\n", argv[2]); + exit(EXIT_FAILURE); + } + + if (fread(&ttDump, 1, sizeof(ttDump), pfDump) != sizeof(ttDump)) { + ERR("Could not read from dump file: %s\n", argv[2]); + fclose(pfDump); + exit(EXIT_FAILURE); + } + fclose(pfDump); + } + DBG("Successfully opened the dump file\n"); + + nfc_context *context; + nfc_init(&context); + if (context == NULL) { + ERR("Unable to init libnfc (malloc)"); + exit(EXIT_FAILURE); + } + + // Try to open the NFC device + pnd = nfc_open(context, NULL); + if (pnd == NULL) { + ERR("Error opening NFC device"); + nfc_exit(context); + exit(EXIT_FAILURE); + } + + if (nfc_initiator_init(pnd) < 0) { + nfc_perror(pnd, "nfc_initiator_init"); + nfc_close(pnd); + nfc_exit(context); + exit(EXIT_FAILURE); + } + + // Let the device only try once to find a tag + if (nfc_device_set_property_bool(pnd, NP_INFINITE_SELECT, false) < 0) { + nfc_perror(pnd, "nfc_device_set_property_bool"); + nfc_close(pnd); + nfc_exit(context); + exit(EXIT_FAILURE); + } + + printf("NFC device: %s opened\n", nfc_device_get_name(pnd)); + + // Try to find a Jewel tag + if (nfc_initiator_select_passive_target(pnd, nmJewel, NULL, 0, &nt) <= 0) { + ERR("no tag was found\n"); + nfc_close(pnd); + nfc_exit(context); + exit(EXIT_FAILURE); + } + + // Get the info from the current tag + printf("Found Jewel card with UID: "); + size_t szPos; + for (szPos = 0; szPos < 4; szPos++) { + printf("%02x", nt.nti.nji.btId[szPos]); + } + printf("\n"); + + if (bReadAction) { + if (read_card()) { + printf("Writing data to file: %s ... ", argv[2]); + fflush(stdout); + pfDump = fopen(argv[2], "wb"); + if (pfDump == NULL) { + printf("Could not open file: %s\n", argv[2]); + nfc_close(pnd); + nfc_exit(context); + exit(EXIT_FAILURE); + } + if (fwrite(&ttDump, 1, sizeof(ttDump), pfDump) != sizeof(ttDump)) { + printf("Could not write to file: %s\n", argv[2]); + fclose(pfDump); + nfc_close(pnd); + nfc_exit(context); + exit(EXIT_FAILURE); + } + fclose(pfDump); + printf("Done.\n"); + } + } else { + write_card(); + } + + nfc_close(pnd); + nfc_exit(context); + exit(EXIT_SUCCESS); +} From 7254e1b2eac5814ceea72dcb903beaa6e977a96f Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 3 Feb 2014 00:24:23 +0100 Subject: [PATCH 040/318] nfc_initiator_target_is_present(): Support Jewel --- libnfc/chips/pn53x.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 4a950f01..2cda23ed 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1797,6 +1797,26 @@ static int pn53x_ISO14443A_4_is_present(struct nfc_device *pnd) return ret; } +static int pn53x_ISO14443A_Jewel_is_present(struct nfc_device *pnd) +{ + int ret; + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping Jewel"); + uint8_t abtCmd[1] = {0x78}; + int failures = 0; + while (failures < 2) { + if ((ret = nfc_initiator_transceive_bytes(pnd, abtCmd, sizeof(abtCmd), NULL, 0, -1)) < 1) { + if ((ret == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Timeout + return NFC_ETGRELEASED; + } else { // Other errors can appear when card is tired-off, let's try again + failures++; + } + } else { + return NFC_SUCCESS; + } + } + return ret; +} + static int pn53x_ISO14443A_MFUL_is_present(struct nfc_device *pnd) { int ret; @@ -1957,6 +1977,8 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) ret = pn53x_ISO14443B_4_is_present(pnd); break; case NMT_JEWEL: + ret = pn53x_ISO14443A_Jewel_is_present(pnd); + break; case NMT_ISO14443BI: case NMT_ISO14443B2SR: case NMT_ISO14443B2CT: From a3a7111210a1fc510a946490ded5823a14b1fcc1 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 7 Feb 2014 00:31:31 +0100 Subject: [PATCH 041/318] nfc_initiator_target_is_present(): Support B' --- libnfc/chips/pn53x.c | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 2cda23ed..bc7994f2 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1935,6 +1935,35 @@ static int pn53x_ISO14443B_4_is_present(struct nfc_device *pnd) return ret; } +static int pn53x_ISO14443B_I_is_present(struct nfc_device *pnd) +{ + int ret; + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping B'"); + // Sending R(NACK) in raw: + if ((ret = pn53x_set_property_bool(pnd, NP_EASY_FRAMING, false)) < 0) + return ret; + uint8_t abtCmd[6] = {0x01, 0x0f}; // ATTRIB + memcpy(abtCmd+2, CHIP_DATA(pnd)->current_target->nti.nii.abtDIV, 4); + int failures = 0; + while (failures < 2) { + if ((ret = nfc_initiator_transceive_bytes(pnd, abtCmd, sizeof(abtCmd), NULL, 0, 300)) < 1) { + if ((ret == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Timeout + ret = NFC_ETGRELEASED; + break; + } else { // Other errors can appear when card is tired-off, let's try again + failures++; + } + } else { + ret = NFC_SUCCESS; + break; + } + } + int ret2; + if ((ret2 = pn53x_set_property_bool(pnd, NP_EASY_FRAMING, true)) < 0) + ret = ret2; + return ret; +} + int pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) { @@ -1973,13 +2002,15 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) case NMT_FELICA: ret = pn53x_Felica_is_present(pnd); break; - case NMT_ISO14443B: - ret = pn53x_ISO14443B_4_is_present(pnd); - break; case NMT_JEWEL: ret = pn53x_ISO14443A_Jewel_is_present(pnd); break; + case NMT_ISO14443B: + ret = pn53x_ISO14443B_4_is_present(pnd); + break; case NMT_ISO14443BI: + ret = pn53x_ISO14443B_I_is_present(pnd); + break; case NMT_ISO14443B2SR: case NMT_ISO14443B2CT: default: From 9fd11d331bebe0f79e58487bf63a63f24776232a Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 7 Feb 2014 00:53:35 +0100 Subject: [PATCH 042/318] nfc_initiator_target_is_present(): Support B2 ASK CT --- libnfc/chips/pn53x.c | 66 ++++++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 20 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index bc7994f2..a90b5bff 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1939,28 +1939,52 @@ static int pn53x_ISO14443B_I_is_present(struct nfc_device *pnd) { int ret; log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping B'"); - // Sending R(NACK) in raw: - if ((ret = pn53x_set_property_bool(pnd, NP_EASY_FRAMING, false)) < 0) - return ret; - uint8_t abtCmd[6] = {0x01, 0x0f}; // ATTRIB - memcpy(abtCmd+2, CHIP_DATA(pnd)->current_target->nti.nii.abtDIV, 4); - int failures = 0; - while (failures < 2) { - if ((ret = nfc_initiator_transceive_bytes(pnd, abtCmd, sizeof(abtCmd), NULL, 0, 300)) < 1) { - if ((ret == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Timeout - ret = NFC_ETGRELEASED; - break; - } else { // Other errors can appear when card is tired-off, let's try again - failures++; - } - } else { - ret = NFC_SUCCESS; + // Sending ATTRIB in raw: + if ((ret = pn53x_set_property_bool(pnd, NP_EASY_FRAMING, false)) < 0) + return ret; + uint8_t abtCmd[6] = {0x01, 0x0f}; + memcpy(abtCmd + 2, CHIP_DATA(pnd)->current_target->nti.nii.abtDIV, 4); + int failures = 0; + while (failures < 2) { + if ((ret = nfc_initiator_transceive_bytes(pnd, abtCmd, sizeof(abtCmd), NULL, 0, 300)) < 1) { + if ((ret == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Timeout + ret = NFC_ETGRELEASED; break; + } else { // Other errors can appear when card is tired-off, let's try again + failures++; } + } else { + ret = NFC_SUCCESS; + break; } - int ret2; - if ((ret2 = pn53x_set_property_bool(pnd, NP_EASY_FRAMING, true)) < 0) - ret = ret2; + } + int ret2; + if ((ret2 = pn53x_set_property_bool(pnd, NP_EASY_FRAMING, true)) < 0) + ret = ret2; + return ret; +} + +static int pn53x_ISO14443B_CT_is_present(struct nfc_device *pnd) +{ + int ret; + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping B2 ASK CT"); + // Sending SELECT in raw: (EASY_FRAMING is already supposed to be false) + uint8_t abtCmd[3] = {0x9f}; + memcpy(abtCmd + 1, CHIP_DATA(pnd)->current_target->nti.nci.abtUID, 2); + int failures = 0; + while (failures < 2) { + if ((ret = nfc_initiator_transceive_bytes(pnd, abtCmd, sizeof(abtCmd), NULL, 0, 300)) < 1) { + if ((ret == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Timeout + ret = NFC_ETGRELEASED; + break; + } else { // Other errors can appear when card is tired-off, let's try again + failures++; + } + } else { + ret = NFC_SUCCESS; + break; + } + } return ret; } @@ -2011,8 +2035,10 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) case NMT_ISO14443BI: ret = pn53x_ISO14443B_I_is_present(pnd); break; - case NMT_ISO14443B2SR: case NMT_ISO14443B2CT: + ret = pn53x_ISO14443B_CT_is_present(pnd); + break; + case NMT_ISO14443B2SR: default: log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): card type not supported"); ret = NFC_EDEVNOTSUPP; From 1e4fe3bd2793042c6f176295070cbdc6f718c797 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 7 Feb 2014 01:11:19 +0100 Subject: [PATCH 043/318] nfc_initiator_target_is_present(): Support B2 ST SRx --- libnfc/chips/pn53x.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index a90b5bff..157cbd74 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1964,10 +1964,33 @@ static int pn53x_ISO14443B_I_is_present(struct nfc_device *pnd) return ret; } +static int pn53x_ISO14443B_SR_is_present(struct nfc_device *pnd) +{ + int ret; + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping B2 ST SRx"); + // Sending Get_UID in raw: (EASY_FRAMING is already supposed to be false) + uint8_t abtCmd[1] = {0x0b}; + int failures = 0; + while (failures < 2) { + if ((ret = nfc_initiator_transceive_bytes(pnd, abtCmd, sizeof(abtCmd), NULL, 0, 300)) < 1) { + if ((ret == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Timeout + ret = NFC_ETGRELEASED; + break; + } else { // Other errors can appear when card is tired-off, let's try again + failures++; + } + } else { + ret = NFC_SUCCESS; + break; + } + } + return ret; +} + static int pn53x_ISO14443B_CT_is_present(struct nfc_device *pnd) { int ret; - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping B2 ASK CT"); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping B2 ASK CTx"); // Sending SELECT in raw: (EASY_FRAMING is already supposed to be false) uint8_t abtCmd[3] = {0x9f}; memcpy(abtCmd + 1, CHIP_DATA(pnd)->current_target->nti.nci.abtUID, 2); @@ -2035,10 +2058,12 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) case NMT_ISO14443BI: ret = pn53x_ISO14443B_I_is_present(pnd); break; + case NMT_ISO14443B2SR: + ret = pn53x_ISO14443B_SR_is_present(pnd); + break; case NMT_ISO14443B2CT: ret = pn53x_ISO14443B_CT_is_present(pnd); break; - case NMT_ISO14443B2SR: default: log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): card type not supported"); ret = NFC_EDEVNOTSUPP; From a38279793abb080a3a1910817d231e2a35046623 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 7 Feb 2014 01:22:27 +0100 Subject: [PATCH 044/318] cppcheck on nfc-pool: Variable 'res' is assigned a value that is never used --- examples/nfc-poll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/nfc-poll.c b/examples/nfc-poll.c index 6d64c325..a42c41a3 100644 --- a/examples/nfc-poll.c +++ b/examples/nfc-poll.c @@ -150,7 +150,7 @@ main(int argc, const char *argv[]) } printf("Waiting for card removing..."); - while (0 == (res = nfc_initiator_target_is_present(pnd, NULL))) {} + while (0 == nfc_initiator_target_is_present(pnd, NULL)) {} nfc_perror(pnd, "nfc_initiator_target_is_present"); printf("done.\n"); From 1f5e14f8625994efedea7a1e5ce099a3acf8103d Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 7 Feb 2014 01:29:42 +0100 Subject: [PATCH 045/318] cppcheck on pn53x.c: Array 'apttTargetTypes' is filled incompletely --- libnfc/chips/pn53x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 157cbd74..807504fa 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1206,7 +1206,7 @@ pn53x_initiator_poll_target(struct nfc_device *pnd, if (CHIP_DATA(pnd)->type == PN532) { size_t szTargetTypes = 0; pn53x_target_type apttTargetTypes[32]; - memset(apttTargetTypes, PTT_UNDEFINED, 32); + memset(apttTargetTypes, PTT_UNDEFINED, 32 * sizeof(pn53x_target_type)); for (size_t n = 0; n < szModulations; n++) { const pn53x_target_type ptt = pn53x_nm_to_ptt(pnmModulations[n]); if (PTT_UNDEFINED == ptt) { From 85bef737348d3ab381e7dc5a5446c32e442c5e7d Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 7 Feb 2014 14:00:25 +0100 Subject: [PATCH 046/318] nfc_initiator_target_is_present(): Fixes issue #267 Fixes some -4A cards removal on PN533 but fixes also same -4A cards on PN532 --- libnfc/chips/pn53x.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 807504fa..4e22cf36 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1768,10 +1768,10 @@ static int pn53x_Diagnose06(struct nfc_device *pnd) // Card Presence command can take more time than default one: when a card is // removed from the field, the PN53x took few hundred ms more to reply - // correctly. (ie. 700 ms should be enough to detect all tested cases) - + // correctly. Longest delay observed was with a JCOP31 on a PN532. + // 1000 ms should be enough to detect all tested cases while (failures < 2) { - if ((ret = pn53x_transceive(pnd, abtCmd, sizeof(abtCmd), abtRx, sizeof(abtRx), 700)) != 1) { + if ((ret = pn53x_transceive(pnd, abtCmd, sizeof(abtCmd), abtRx, sizeof(abtRx), 1000)) != 1) { // When it fails with a timeout (0x01) chip error, it means the target is not reacheable anymore if ((ret == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { return NFC_ETGRELEASED; @@ -1789,8 +1789,37 @@ static int pn53x_ISO14443A_4_is_present(struct nfc_device *pnd) { int ret; log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping -4A"); - if ((CHIP_DATA(pnd)->type == PN532) || (CHIP_DATA(pnd)->type == PN533)) { + if (CHIP_DATA(pnd)->type == PN533) { ret = pn53x_Diagnose06(pnd); + if ((ret == NFC_ETIMEOUT) && (CHIP_DATA(pnd)->type == PN533)) { + // This happens e.g. when a JCOP31 is removed from PN533 + // InRelease takes an abnormal time to reply so let's take care of it now with large timeout: + const uint8_t abtCmd[] = { InRelease, 0x00 }; + pn53x_transceive(pnd, abtCmd, sizeof(abtCmd), NULL, 0, 2000); + ret = NFC_ETGRELEASED; + } + } else if (CHIP_DATA(pnd)->type == PN532) { + // Diagnose06 failed completely with a JCOP31 on a PN532 so let's do it manually + if ((ret = pn53x_set_property_bool(pnd, NP_EASY_FRAMING, false)) < 0) + return ret; + uint8_t abtCmd[1] = {0xb2}; // CID=0 + int failures = 0; + while (failures < 2) { + if ((ret = nfc_initiator_transceive_bytes(pnd, abtCmd, sizeof(abtCmd), NULL, 0, 300)) < 1) { + if ((ret == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Timeout + ret = NFC_ETGRELEASED; + break; + } else { // Other errors can appear when card is tired-off, let's try again + failures++; + } + } else { + ret = NFC_SUCCESS; + break; + } + } + int ret2; + if ((ret2 = pn53x_set_property_bool(pnd, NP_EASY_FRAMING, true)) < 0) + ret = ret2; } else { ret = NFC_EDEVNOTSUPP; } From 2d584baa9bdf38ba37392c2dcacf4edd5ce462fb Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 7 Feb 2014 14:39:44 +0100 Subject: [PATCH 047/318] Update ChangeLog --- ChangeLog | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index d38882d7..1abbec61 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,9 +9,7 @@ Fixes: - Silent pn53x_check_communication error messages when scanning - Fix nfc_target_init(), was returning success in case of timeout - Windows: fix several compilation issues - - Fix nfc_initiator_target_is_present() usage after nfc_initiator_poll_target() - - Fix nfc_initiator_target_is_present() set correctly last_error - - Fix nfc_initiator_target_is_present() if no saved target + - On tag selection, save current target info also for ISO14443B* Improvements: - nfc-list: New option to choose which technologies to poll for @@ -19,9 +17,25 @@ Improvements: - New LIBNFC_DEVICE env var to use one reader and exclude all other readers while LIBNFC_DEFAULT_DEVICE only prepends it to the configured devices list - New LIBNFC_AUTO_SCAN env var to enable(default)/disable auto scan - - nfc-mfclassic: add format/wipe command - - nfc_initiator_target_is_present() allows NULL pointer to tag - + - On tag selection, save current target info even if pnt=NULL + - On tag selection, grant NP_INFINITE_SELECT also for ISO14443B* + - Save & restore NP_INFINITE_SELECT status when changing it internally + - nfc-mfclassic: add format/wipe command (thanks to Adam Laurie) + - nfc-jewel: new utility to read/write Topaz/Jewel tags (thanks to Pim 't Hart) + +Fixes & improvements specific to nfc_initiator_target_is_present(): + - Supports fully PN532 & PN533, not tested on other chips + - Fix usage after nfc_initiator_poll_target() + - Set correctly last_error + - Fix issue when there was no saved target + - Allow NULL pointer to tag + - Fix issues in case of tear off conditions + - Now works with: + * MFUL, MFC, MFC Mini, MFC 7-byte (re-selection: you'll need to auth again) + * ISO14443-4A, ISO14443-4B + * ISO14443-4B', ASK CTx, ST SRx + * Jewel + * FeliCa Sep 03, 2013 - 1.7.0 -------------------- From 766ed55c79e70a7dbca7393a3b7f838a3a231afe Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 7 Feb 2014 23:09:34 +0100 Subject: [PATCH 048/318] nfc-jewel: fix out-of-bounds array access Defect(s) Reported-by: Coverity Scan ** CID 1169884: Out-of-bounds read (OVERRUN) /utils/nfc-jewel.c: 186 in write_card() --- utils/jewel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/jewel.h b/utils/jewel.h index 18f39b92..2e529b4b 100644 --- a/utils/jewel.h +++ b/utils/jewel.h @@ -200,7 +200,7 @@ typedef struct { } jewel_tag_blocks; typedef struct { - uint8_t abtData[112]; + uint8_t abtData[120]; } jewel_tag_data; typedef union { From fd30e63b800801ba203a64c08e8f027b7a992164 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 10 Feb 2014 00:01:34 +0100 Subject: [PATCH 049/318] nfc_initiator_target_is_present(): Fixes issue #267, second attempt --- libnfc/chips/pn53x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 4e22cf36..2243278f 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1791,7 +1791,7 @@ static int pn53x_ISO14443A_4_is_present(struct nfc_device *pnd) log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping -4A"); if (CHIP_DATA(pnd)->type == PN533) { ret = pn53x_Diagnose06(pnd); - if ((ret == NFC_ETIMEOUT) && (CHIP_DATA(pnd)->type == PN533)) { + if ((ret == NFC_ETIMEOUT) || (ret == NFC_ETGRELEASED)) { // This happens e.g. when a JCOP31 is removed from PN533 // InRelease takes an abnormal time to reply so let's take care of it now with large timeout: const uint8_t abtCmd[] = { InRelease, 0x00 }; From 415ad7cbac0263e726524ee9fb82efa879022a45 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 10 Feb 2014 01:07:11 +0100 Subject: [PATCH 050/318] nfc_initiator_select_passive_target() accepts NULL pbtInitData and provides default values --- ChangeLog | 1 + libnfc/nfc.c | 40 +++++++++++++++++++--------------------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1abbec61..2e1998bf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -22,6 +22,7 @@ Improvements: - Save & restore NP_INFINITE_SELECT status when changing it internally - nfc-mfclassic: add format/wipe command (thanks to Adam Laurie) - nfc-jewel: new utility to read/write Topaz/Jewel tags (thanks to Pim 't Hart) + - nfc_initiator_select_passive_target() provides defaults if pbtInitData=NULL Fixes & improvements specific to nfc_initiator_target_is_present(): - Supports fully PN532 & PN533, not tested on other chips diff --git a/libnfc/nfc.c b/libnfc/nfc.c index dce7ffd4..f9d0c298 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -500,12 +500,15 @@ nfc_initiator_init_secure_element(nfc_device *pnd) * * @param pnd \a nfc_device struct pointer that represent currently used device * @param nm desired modulation - * @param pbtInitData optional initiator data used for Felica, ISO14443B, Topaz polling or to select a specific UID in ISO14443A. + * @param pbtInitData optional initiator data, NULL for using the default values. * @param szInitData length of initiator data \a pbtInitData. * @note pbtInitData is used with different kind of data depending on modulation type: * - for an ISO/IEC 14443 type A modulation, pbbInitData contains the UID you want to select; - * - for an ISO/IEC 14443 type B modulation, pbbInitData contains Application Family Identifier (AFI) (see ISO/IEC 14443-3); - * - for a FeliCa modulation, pbbInitData contains polling payload (see ISO/IEC 18092 11.2.2.5). + * - for an ISO/IEC 14443 type B modulation, pbbInitData contains Application Family Identifier (AFI) (see ISO/IEC 14443-3) + and optionally a second byte = 0x01 if you want to use probabilistic approach instead of timeslot approach; + * - for a FeliCa modulation, pbbInitData contains a 5-byte polling payload (see ISO/IEC 18092 11.2.2.5). + * - for ISO14443B', ASK CTx and ST SRx, see corresponding standards + * - if NULL, default values adequate for the chosen modulation will be used. * * @param[out] pnt \a nfc_target struct pointer which will filled if available * @@ -520,24 +523,19 @@ nfc_initiator_select_passive_target(nfc_device *pnd, const uint8_t *pbtInitData, const size_t szInitData, nfc_target *pnt) { - uint8_t abtInit[MAX(12, szInitData)]; - size_t szInit; - - switch (nm.nmt) { - case NMT_ISO14443A: - iso14443_cascade_uid(pbtInitData, szInitData, abtInit, &szInit); - break; - - case NMT_JEWEL: - case NMT_ISO14443B: - case NMT_ISO14443BI: - case NMT_ISO14443B2SR: - case NMT_ISO14443B2CT: - case NMT_FELICA: - case NMT_DEP: - memcpy(abtInit, pbtInitData, szInitData); - szInit = szInitData; - break; + uint8_t *abtInit = NULL; + uint8_t abtTmpInit[MAX(12, szInitData)]; + size_t szInit = 0; + if (szInitData == 0) { + // Provide default values, if any + prepare_initiator_data(nm, &abtInit, &szInit); + } else if (nm.nmt == NMT_ISO14443A) { + abtInit = abtTmpInit; + iso14443_cascade_uid(pbtInitData, szInitData, abtInit, &szInit); + } else { + abtInit = abtTmpInit; + memcpy(abtInit, pbtInitData, szInitData); + szInit = szInitData; } HAL(initiator_select_passive_target, pnd, nm, abtInit, szInit, pnt); From 491db20d54026acf312812d674a7ed6f653ae93e Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 11 Feb 2014 23:23:42 +0100 Subject: [PATCH 051/318] nfc-jewel: remove extraneous parentheses to silence warning --- utils/nfc-jewel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/nfc-jewel.c b/utils/nfc-jewel.c index 19bd3cd8..d8920833 100644 --- a/utils/nfc-jewel.c +++ b/utils/nfc-jewel.c @@ -146,7 +146,7 @@ write_card(void) for (block = uiSkippedBlocks; block <= uiBlocks; block++) { // Skip block 0x0D - it is reserved for internal use and can't be written - if ((block == 0x0D)) { + if (block == 0x0D) { printf("s"); uiSkippedBlocks++; continue; From 73c84c214dd0dd3fbf225db2479d8d0124daf4a8 Mon Sep 17 00:00:00 2001 From: Pim 't Hart Date: Mon, 17 Feb 2014 23:09:15 +0100 Subject: [PATCH 052/318] nfc-read-forum-tag3: fix incomplete NDEF retrieval and size of output file --- utils/nfc-read-forum-tag3.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/utils/nfc-read-forum-tag3.c b/utils/nfc-read-forum-tag3.c index 7fa01acb..32288add 100644 --- a/utils/nfc-read-forum-tag3.c +++ b/utils/nfc-read-forum-tag3.c @@ -130,6 +130,7 @@ nfc_forum_tag_type3_check(nfc_device *dev, const nfc_target *nt, const uint16_t if ((res = nfc_initiator_transceive_bytes(dev, frame, frame_len, rx, sizeof(rx), 0)) < 0) { return res; } + const int res_overhead = 1 + 1 + 8 + 2; // 1+1+8+2: LEN + CMD + NFCID2 + STATUS if (res < res_overhead) { // Not enough data @@ -326,7 +327,7 @@ main(int argc, char *argv[]) const uint16_t block_count_to_check = (ndef_data_len / 16) + 1; data_len = 0; - for (uint16_t b = 0; b < (block_count_to_check / block_max_per_check); b += block_max_per_check) { + for (uint16_t b = 0; b < ((block_count_to_check - 1) / block_max_per_check + 1); b += block_max_per_check) { size_t size = sizeof(data) - data_len; if (!nfc_forum_tag_type3_check(pnd, &nt, 1 + b, MIN(block_max_per_check, (block_count_to_check - (b * block_max_per_check))), data + data_len, &size)) { nfc_perror(pnd, "nfc_forum_tag_type3_check"); @@ -337,7 +338,8 @@ main(int argc, char *argv[]) } data_len += size; } - if (fwrite(data, 1, data_len, ndef_stream) != data_len) { + + if (fwrite(data, 1, ndef_data_len, ndef_stream) != ndef_data_len) { fprintf(stderr, "Could not write to file.\n"); fclose(ndef_stream); nfc_close(pnd); From 2aa4b99b7bbb75ac6930cbdba2cd07b74b7aad86 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 17 Feb 2014 23:57:59 +0100 Subject: [PATCH 053/318] nfc-read-forum-tag3: full parsing of NDEF Attribute Block --- utils/nfc-read-forum-tag3.c | 55 ++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/utils/nfc-read-forum-tag3.c b/utils/nfc-read-forum-tag3.c index 32288add..3e18a79a 100644 --- a/utils/nfc-read-forum-tag3.c +++ b/utils/nfc-read-forum-tag3.c @@ -292,15 +292,50 @@ main(int argc, char *argv[]) exit(EXIT_FAILURE); } + fprintf(message_stream, "NDEF Attribute Block:\n"); const int ndef_major_version = (data[0] & 0xf0) >> 4; const int ndef_minor_version = (data[0] & 0x0f); - fprintf(message_stream, "NDEF Mapping version: %d.%d\n", ndef_major_version, ndef_minor_version); + fprintf(message_stream, "* Mapping version: %d.%d\n", ndef_major_version, ndef_minor_version); + + const int ndef_nbr = data[1]; + fprintf(message_stream, "* Maximum nr of blocks to read by Check Command: %3d block%s\n", ndef_nbr, ndef_nbr > 1 ? "s" : ""); + + const int ndef_nbw = data[2]; + fprintf(message_stream, "* Maximum nr of blocks to write by Update Command: %3d block%s\n", ndef_nbw, ndef_nbw > 1 ? "s" : ""); + + const int ndef_nmaxb = (data[3] << 8) + data[4]; + fprintf(message_stream, "* Maximum nr of blocks available for NDEF data: %3d block%s (%d bytes)\n", ndef_nmaxb, ndef_nmaxb > 1 ? "s" : "", ndef_nmaxb * 16); + + const int ndef_writeflag = data[9]; + fprintf(message_stream, "* NDEF writing state: "); + switch (ndef_writeflag) { + case 0x00: + fprintf(message_stream, "finished (0x00)\n"); + break; + case 0x0f: + fprintf(message_stream, "in progress (0x0F)\n"); + break; + default: + fprintf(message_stream, "invalid (0x%02X)\n", ndef_writeflag); + break; + } - const int available_block_count = (data[3] << 8) + data[4]; - fprintf(message_stream, "NFC Forum Tag Type 3 capacity: %d bytes\n", available_block_count * 16); + const int ndef_rwflag = data[10]; + fprintf(message_stream, "* NDEF Access Attribute: "); + switch (ndef_rwflag) { + case 0x00: + fprintf(message_stream, "Read only (0x00)\n"); + break; + case 0x01: + fprintf(message_stream, "Read/Write (0x01)\n"); + break; + default: + fprintf(message_stream, "invalid (0x%02X)\n", ndef_rwflag); + break; + } uint32_t ndef_data_len = (data[11] << 16) + (data[12] << 8) + data[13]; - fprintf(message_stream, "NDEF data length: %d bytes\n", ndef_data_len); + fprintf(message_stream, "* NDEF message length: %d bytes\n", ndef_data_len); uint16_t ndef_calculated_checksum = 0; for (size_t n = 0; n < 14; n++) @@ -308,15 +343,13 @@ main(int argc, char *argv[]) const uint16_t ndef_checksum = (data[14] << 8) + data[15]; if (ndef_calculated_checksum != ndef_checksum) { - fprintf(stderr, "NDEF CRC does not match with calculated one\n"); - fclose(ndef_stream); - nfc_close(pnd); - nfc_exit(context); - exit(EXIT_FAILURE); + fprintf(message_stream, "* Checksum: fail (0x%04X != 0x%04X)\n", ndef_calculated_checksum, ndef_checksum); + } else { + fprintf(message_stream, "* Checksum: ok (0x%04X)\n", ndef_checksum); } if (!ndef_data_len) { - fprintf(stderr, "Empty NFC Forum Tag Type 3\n"); + fprintf(stderr, "Error: empty NFC Forum Tag Type 3, nothing to read!\n"); fclose(ndef_stream); nfc_close(pnd); nfc_exit(context); @@ -345,6 +378,8 @@ main(int argc, char *argv[]) nfc_close(pnd); nfc_exit(context); exit(EXIT_FAILURE); + } else { + fprintf(stderr, "%i bytes written to %s\n", ndef_data_len, ndef_output); } fclose(ndef_stream); From a7649da2b0d57013ff9353ce14b38866f273c713 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 18 Feb 2014 00:01:43 +0100 Subject: [PATCH 054/318] nfc-read-forum-tag3: add -q and document -o - --- utils/nfc-read-forum-tag3.1 | 12 +++- utils/nfc-read-forum-tag3.c | 112 ++++++++++++++++++++---------------- 2 files changed, 75 insertions(+), 49 deletions(-) diff --git a/utils/nfc-read-forum-tag3.1 b/utils/nfc-read-forum-tag3.1 index 61404bc3..63a15367 100644 --- a/utils/nfc-read-forum-tag3.1 +++ b/utils/nfc-read-forum-tag3.1 @@ -3,6 +3,9 @@ nfc-read-forum-tag3 \- Extract NDEF Message from a NFC Forum Tag Type 3 .SH SYNOPSIS .B nfc-read-forum-tag3 +.RI [ +.RI \fR\fB\-q\fR +.RI ] .RI \fR\fB\-o\fR .IR FILE .SH DESCRIPTION @@ -12,8 +15,15 @@ This utility extracts (if available) NDEF Messages contained in a NFC Forum Tag . .SH OPTIONS \fR\fB\-o\fR -output extracted NDEF Message to .IR FILE +: output extracted NDEF Message to +.IR FILE +(use +\fR\fB\-o \-\fR +to output to stdout) + +\fR\fB\-q\fR +: be quiet, don't display Attribute Block parsing info .SH BUGS Please report any bugs on the diff --git a/utils/nfc-read-forum-tag3.c b/utils/nfc-read-forum-tag3.c index 3e18a79a..c9bae9a0 100644 --- a/utils/nfc-read-forum-tag3.c +++ b/utils/nfc-read-forum-tag3.c @@ -72,9 +72,11 @@ static nfc_context *context; static void print_usage(char *progname) { - fprintf(stderr, "usage: %s -o FILE\n", progname); + fprintf(stderr, "usage: %s [-q] -o FILE\n", progname); fprintf(stderr, "\nOptions:\n"); - fprintf(stderr, " -o Extract NDEF message if available in FILE\n"); + fprintf(stderr, " -o FILE Extract NDEF message if available in FILE\n"); + fprintf(stderr, " -o - Extract NDEF message if available to stdout\n"); + fprintf(stderr, " -q Be quiet, don't display Attribute Block parsing info\n"); } static void stop_select(int sig) @@ -169,13 +171,17 @@ main(int argc, char *argv[]) (void)argv; int ch; + bool quiet = false; char *ndef_output = NULL; - while ((ch = getopt(argc, argv, "ho:")) != -1) { + while ((ch = getopt(argc, argv, "hqo:")) != -1) { switch (ch) { case 'h': print_usage(argv[0]); exit(EXIT_SUCCESS); break; + case 'q': + quiet = true; + break; case 'o': ndef_output = optarg; break; @@ -219,7 +225,9 @@ main(int argc, char *argv[]) exit(EXIT_FAILURE); } - fprintf(message_stream, "NFC device: %s opened\n", nfc_device_get_name(pnd)); + if (!quiet) { + fprintf(message_stream, "NFC device: %s opened\n", nfc_device_get_name(pnd)); + } nfc_modulation nm = { .nmt = NMT_FELICA, @@ -237,7 +245,10 @@ main(int argc, char *argv[]) nfc_exit(context); exit(EXIT_FAILURE); } - fprintf(message_stream, "Place your NFC Forum Tag Type 3 in the field...\n"); + + if (!quiet) { + fprintf(message_stream, "Place your NFC Forum Tag Type 3 in the field...\n"); + } // Polling payload (SENSF_REQ) must be present (see NFC Digital Protol) const uint8_t *pbtSensfReq = (uint8_t *)"\x00\xff\xff\x01\x00"; @@ -292,60 +303,63 @@ main(int argc, char *argv[]) exit(EXIT_FAILURE); } - fprintf(message_stream, "NDEF Attribute Block:\n"); const int ndef_major_version = (data[0] & 0xf0) >> 4; const int ndef_minor_version = (data[0] & 0x0f); - fprintf(message_stream, "* Mapping version: %d.%d\n", ndef_major_version, ndef_minor_version); - const int ndef_nbr = data[1]; - fprintf(message_stream, "* Maximum nr of blocks to read by Check Command: %3d block%s\n", ndef_nbr, ndef_nbr > 1 ? "s" : ""); - const int ndef_nbw = data[2]; - fprintf(message_stream, "* Maximum nr of blocks to write by Update Command: %3d block%s\n", ndef_nbw, ndef_nbw > 1 ? "s" : ""); - const int ndef_nmaxb = (data[3] << 8) + data[4]; - fprintf(message_stream, "* Maximum nr of blocks available for NDEF data: %3d block%s (%d bytes)\n", ndef_nmaxb, ndef_nmaxb > 1 ? "s" : "", ndef_nmaxb * 16); - const int ndef_writeflag = data[9]; - fprintf(message_stream, "* NDEF writing state: "); - switch (ndef_writeflag) { - case 0x00: - fprintf(message_stream, "finished (0x00)\n"); - break; - case 0x0f: - fprintf(message_stream, "in progress (0x0F)\n"); - break; - default: - fprintf(message_stream, "invalid (0x%02X)\n", ndef_writeflag); - break; - } - const int ndef_rwflag = data[10]; - fprintf(message_stream, "* NDEF Access Attribute: "); - switch (ndef_rwflag) { - case 0x00: - fprintf(message_stream, "Read only (0x00)\n"); - break; - case 0x01: - fprintf(message_stream, "Read/Write (0x01)\n"); - break; - default: - fprintf(message_stream, "invalid (0x%02X)\n", ndef_rwflag); - break; - } - uint32_t ndef_data_len = (data[11] << 16) + (data[12] << 8) + data[13]; - fprintf(message_stream, "* NDEF message length: %d bytes\n", ndef_data_len); - uint16_t ndef_calculated_checksum = 0; for (size_t n = 0; n < 14; n++) ndef_calculated_checksum += data[n]; - const uint16_t ndef_checksum = (data[14] << 8) + data[15]; + + if (!quiet) { + fprintf(message_stream, "NDEF Attribute Block:\n"); + fprintf(message_stream, "* Mapping version: %d.%d\n", ndef_major_version, ndef_minor_version); + fprintf(message_stream, "* Maximum nr of blocks to read by Check Command: %3d block%s\n", ndef_nbr, ndef_nbr > 1 ? "s" : ""); + fprintf(message_stream, "* Maximum nr of blocks to write by Update Command: %3d block%s\n", ndef_nbw, ndef_nbw > 1 ? "s" : ""); + fprintf(message_stream, "* Maximum nr of blocks available for NDEF data: %3d block%s (%d bytes)\n", ndef_nmaxb, ndef_nmaxb > 1 ? "s" : "", ndef_nmaxb * 16); + fprintf(message_stream, "* NDEF writing state: "); + switch (ndef_writeflag) { + case 0x00: + fprintf(message_stream, "finished (0x00)\n"); + break; + case 0x0f: + fprintf(message_stream, "in progress (0x0F)\n"); + break; + default: + fprintf(message_stream, "invalid (0x%02X)\n", ndef_writeflag); + break; + } + fprintf(message_stream, "* NDEF Access Attribute: "); + switch (ndef_rwflag) { + case 0x00: + fprintf(message_stream, "Read only (0x00)\n"); + break; + case 0x01: + fprintf(message_stream, "Read/Write (0x01)\n"); + break; + default: + fprintf(message_stream, "invalid (0x%02X)\n", ndef_rwflag); + break; + } + fprintf(message_stream, "* NDEF message length: %d bytes\n", ndef_data_len); + if (ndef_calculated_checksum != ndef_checksum) { + fprintf(message_stream, "* Checksum: fail (0x%04X != 0x%04X)\n", ndef_calculated_checksum, ndef_checksum); + } else { + fprintf(message_stream, "* Checksum: ok (0x%04X)\n", ndef_checksum); + } + } + if (ndef_calculated_checksum != ndef_checksum) { - fprintf(message_stream, "* Checksum: fail (0x%04X != 0x%04X)\n", ndef_calculated_checksum, ndef_checksum); - } else { - fprintf(message_stream, "* Checksum: ok (0x%04X)\n", ndef_checksum); + fprintf(stderr, "Error: Checksum failed! Exiting now.\n"); + fclose(ndef_stream); + nfc_close(pnd); + nfc_exit(context); + exit(EXIT_FAILURE); } if (!ndef_data_len) { @@ -373,13 +387,15 @@ main(int argc, char *argv[]) } if (fwrite(data, 1, ndef_data_len, ndef_stream) != ndef_data_len) { - fprintf(stderr, "Could not write to file.\n"); + fprintf(stderr, "Error: could not write to file.\n"); fclose(ndef_stream); nfc_close(pnd); nfc_exit(context); exit(EXIT_FAILURE); } else { - fprintf(stderr, "%i bytes written to %s\n", ndef_data_len, ndef_output); + if (!quiet) { + fprintf(stderr, "%i bytes written to %s\n", ndef_data_len, ndef_output); + } } fclose(ndef_stream); From c0b9db68600d992fc0e069f06c508e7c7f0c35e1 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 18 Feb 2014 15:40:22 +0100 Subject: [PATCH 055/318] Update ChangeLog & AUTHORS --- AUTHORS | 6 ++++++ ChangeLog | 2 ++ 2 files changed, 8 insertions(+) diff --git a/AUTHORS b/AUTHORS index 98fcbe15..1ebb8359 100644 --- a/AUTHORS +++ b/AUTHORS @@ -7,11 +7,17 @@ Audrey Diacre Emanuele Bertoldi Eugeny Boger Francois Kooman +Jiapeng Li Julien Schueller Laurent Latil Ludovic Rousseau +Marcello Morena +Mike Auty Nobuhiro Iwamatsu +Peter Meerwald Philippe Teuwen +Pim 't Hart Roel Verdult Romain Tartiere Romuald Conty +lego diff --git a/ChangeLog b/ChangeLog index 2e1998bf..0ce40458 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,7 @@ Fixes: - Fix nfc_target_init(), was returning success in case of timeout - Windows: fix several compilation issues - On tag selection, save current target info also for ISO14443B* + - nfc-read-forum-tag3: fix incomplete NDEF retrieval and size of output file Improvements: - nfc-list: New option to choose which technologies to poll for @@ -23,6 +24,7 @@ Improvements: - nfc-mfclassic: add format/wipe command (thanks to Adam Laurie) - nfc-jewel: new utility to read/write Topaz/Jewel tags (thanks to Pim 't Hart) - nfc_initiator_select_passive_target() provides defaults if pbtInitData=NULL + - nfc-read-forum-tag3: add -q option, add full parsing of NDEF Attribute Block Fixes & improvements specific to nfc_initiator_target_is_present(): - Supports fully PN532 & PN533, not tested on other chips From 78b827aa33c255621fac718dee3cc85cfa4a6675 Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Mon, 24 Feb 2014 15:50:49 +0100 Subject: [PATCH 056/318] Bump library revision According to https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html --- libnfc/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnfc/Makefile.am b/libnfc/Makefile.am index af3dbf10..d7f3f7ef 100644 --- a/libnfc/Makefile.am +++ b/libnfc/Makefile.am @@ -22,7 +22,7 @@ libnfc_la_SOURCES = \ nfc-internal.h \ target-subr.h -libnfc_la_LDFLAGS = -no-undefined -version-info 5:0:0 -export-symbols-regex '^nfc_|^iso14443a_|^str_nfc_|pn53x_transceive|pn532_SAMConfiguration|pn53x_read_register|pn53x_write_register' +libnfc_la_LDFLAGS = -no-undefined -version-info 5:1:0 -export-symbols-regex '^nfc_|^iso14443a_|^str_nfc_|pn53x_transceive|pn532_SAMConfiguration|pn53x_read_register|pn53x_write_register' libnfc_la_CFLAGS = @DRIVERS_CFLAGS@ libnfc_la_LIBADD = \ $(top_builddir)/libnfc/chips/libnfcchips.la \ From 101245a4a61cce49b0ad01ca17e20e8e8eba1d63 Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Mon, 24 Feb 2014 15:55:41 +0100 Subject: [PATCH 057/318] NEWS: add API changes for upcomming 1.7.1 --- NEWS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/NEWS b/NEWS index 5595858c..83b7d91e 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,10 @@ +New in 1.7.1: + +API Changes: + + * nfc_initiator_select_passive_target() provides defaults if pbtInitData=NULL + * nfc_initiator_target_is_present() allow NULL pointer to tag + New in 1.7.0: Drivers: From 2d4543673e9b76c02679ca8b89259659f1afd932 Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Mon, 24 Feb 2014 15:56:33 +0100 Subject: [PATCH 058/318] Prepare 1.7.1 version --- CMakeLists.txt | 2 +- ChangeLog | 2 +- configure.ac | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c4cf7fe3..d543b061 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ PROJECT(libnfc C) CMAKE_MINIMUM_REQUIRED(VERSION 2.6) SET(VERSION_MAJOR "1") SET(VERSION_MINOR "7") -SET(VERSION_PATCH "0") +SET(VERSION_PATCH "1") SET(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") diff --git a/ChangeLog b/ChangeLog index 0ce40458..a0619b24 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,4 @@ -TBD - 1.7.0.99~rc1 +Feb 24, 2014 - 1.7.1 ------------------ Fixes: diff --git a/configure.ac b/configure.ac index ac233e72..804aacd8 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ # General init # /!\ Don't forget to update 'CMakeLists.txt' too /!\ -AC_INIT([libnfc],[1.7.0],[nfc-tools@googlegroups.com]) +AC_INIT([libnfc],[1.7.1],[nfc-tools@googlegroups.com]) AC_CONFIG_MACRO_DIR([m4]) From 7adad098c35118b6eae65404fed6cfe8b9091e1e Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 4 Mar 2014 01:33:44 +0100 Subject: [PATCH 059/318] Document -Wunreachable-code in HACKING file --- HACKING | 1 + 1 file changed, 1 insertion(+) diff --git a/HACKING b/HACKING index 48ad35a8..56930af2 100644 --- a/HACKING +++ b/HACKING @@ -34,6 +34,7 @@ Here are some directions to get you started: $ make clean $ make 2.2.2 Using clang: + You can use same CFLAGS but also "-Wunreachable-code" $ scan-build ./configure $ make clean $ scan-build make From db4fae9c2ce88879e45b7daca8245d99d2d5ec21 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 4 Mar 2014 01:27:01 +0100 Subject: [PATCH 060/318] Remove unreachable statements As seen with clang -Wunreachable-code --- libnfc/chips/pn53x.c | 50 +++++-------------------------------- libnfc/nfc.c | 17 ------------- utils/jewel.c | 1 - utils/mifare.c | 1 - utils/nfc-read-forum-tag3.c | 1 - 5 files changed, 6 insertions(+), 64 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 2243278f..4109602c 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -607,7 +607,6 @@ pn53x_decode_target_data(const uint8_t *pbtRawData, size_t szRawData, pn53x_type // Should not happend... case NMT_DEP: return NFC_ECHIP; - break; } return NFC_SUCCESS; } @@ -820,11 +819,9 @@ pn53x_set_property_int(struct nfc_device *pnd, const nfc_property property, cons case NP_TIMEOUT_ATR: CHIP_DATA(pnd)->timeout_atr = value; return pn53x_RFConfiguration__Various_timings(pnd, pn53x_int_to_timeout(CHIP_DATA(pnd)->timeout_atr), pn53x_int_to_timeout(CHIP_DATA(pnd)->timeout_communication)); - break; case NP_TIMEOUT_COM: CHIP_DATA(pnd)->timeout_communication = value; return pn53x_RFConfiguration__Various_timings(pnd, pn53x_int_to_timeout(CHIP_DATA(pnd)->timeout_atr), pn53x_int_to_timeout(CHIP_DATA(pnd)->timeout_communication)); - break; // Following properties are invalid (not integer) case NP_HANDLE_CRC: case NP_HANDLE_PARITY: @@ -863,7 +860,6 @@ pn53x_set_property_bool(struct nfc_device *pnd, const nfc_property property, con return res; pnd->bCrc = bEnable; return NFC_SUCCESS; - break; case NP_HANDLE_PARITY: // Handle parity bit by PN53X chip or parse it as data bit @@ -875,21 +871,17 @@ pn53x_set_property_bool(struct nfc_device *pnd, const nfc_property property, con return res; pnd->bPar = bEnable; return NFC_SUCCESS; - break; case NP_EASY_FRAMING: pnd->bEasyFraming = bEnable; return NFC_SUCCESS; - break; case NP_ACTIVATE_FIELD: return pn53x_RFConfiguration__RF_field(pnd, bEnable); - break; case NP_ACTIVATE_CRYPTO1: btValue = (bEnable) ? SYMBOL_MF_CRYPTO1_ON : 0x00; return pn53x_write_register(pnd, PN53X_REG_CIU_Status2, SYMBOL_MF_CRYPTO1_ON, btValue); - break; case NP_INFINITE_SELECT: // TODO Made some research around this point: @@ -901,17 +893,14 @@ pn53x_set_property_bool(struct nfc_device *pnd, const nfc_property property, con (bEnable) ? 0xff : 0x01, // MxRtyPSL, default: 0x01 (bEnable) ? 0xff : 0x02 // MxRtyPassiveActivation, default: 0xff (0x00 leads to problems with PN531) ); - break; case NP_ACCEPT_INVALID_FRAMES: btValue = (bEnable) ? SYMBOL_RX_NO_ERROR : 0x00; return pn53x_write_register(pnd, PN53X_REG_CIU_RxMode, SYMBOL_RX_NO_ERROR, btValue); - break; case NP_ACCEPT_MULTIPLE_FRAMES: btValue = (bEnable) ? SYMBOL_RX_MULTIPLE : 0x00; return pn53x_write_register(pnd, PN53X_REG_CIU_RxMode, SYMBOL_RX_MULTIPLE, btValue); - break; case NP_AUTO_ISO14443_4: if (bEnable == pnd->bAutoIso14443_4) @@ -919,7 +908,6 @@ pn53x_set_property_bool(struct nfc_device *pnd, const nfc_property property, con return NFC_SUCCESS; pnd->bAutoIso14443_4 = bEnable; return pn53x_set_parameters(pnd, PARAM_AUTO_RATS, bEnable); - break; case NP_FORCE_ISO14443_A: if (!bEnable) { @@ -935,7 +923,6 @@ pn53x_set_property_bool(struct nfc_device *pnd, const nfc_property property, con } // Set the PN53X to force 100% ASK Modified miller decoding (default for 14443A cards) return pn53x_write_register(pnd, PN53X_REG_CIU_TxAuto, SYMBOL_FORCE_100_ASK, 0x40); - break; case NP_FORCE_ISO14443_B: if (!bEnable) { @@ -947,7 +934,6 @@ pn53x_set_property_bool(struct nfc_device *pnd, const nfc_property property, con return res; } return pn53x_write_register(pnd, PN53X_REG_CIU_RxMode, SYMBOL_RX_FRAMING, 0x03); - break; case NP_FORCE_SPEED_106: if (!bEnable) { @@ -959,13 +945,11 @@ pn53x_set_property_bool(struct nfc_device *pnd, const nfc_property property, con return res; } return pn53x_write_register(pnd, PN53X_REG_CIU_RxMode, SYMBOL_RX_SPEED, 0x00); - break; // Following properties are invalid (not boolean) case NP_TIMEOUT_COMMAND: case NP_TIMEOUT_ATR: case NP_TIMEOUT_COM: return NFC_EINVARG; - break; } return NFC_EINVARG; @@ -1231,17 +1215,14 @@ pn53x_initiator_poll_target(struct nfc_device *pnd, return pnd->last_error = NFC_ESOFT; } return res; - break; case 2: *pnt = ntTargets[1]; // We keep the selected one if (pn53x_current_target_new(pnd, pnt) == NULL) { return pnd->last_error = NFC_ESOFT; } return res; - break; default: return NFC_ECHIP; - break; } } else { bool bInfiniteSelect = pnd->bInfiniteSelect; @@ -1303,7 +1284,6 @@ pn53x_initiator_select_dep_target(struct nfc_device *pnd, case NBR_847: case NBR_UNDEFINED: return NFC_EINVARG; - break; } pn53x_current_target_free(pnd); @@ -2150,7 +2130,6 @@ pn53x_target_init(struct nfc_device *pnd, nfc_target *pnt, uint8_t *pbtRx, const case NMT_JEWEL: pnd->last_error = NFC_EDEVNOTSUPP; return pnd->last_error; - break; } // Let the PN53X be activated by the RF level detector from power down mode @@ -2252,7 +2231,6 @@ pn53x_target_init(struct nfc_device *pnd, nfc_target *pnt, uint8_t *pbtRx, const case NMT_JEWEL: pnd->last_error = NFC_EDEVNOTSUPP; return pnd->last_error; - break; } bool targetActivated = false; @@ -2911,7 +2889,6 @@ pn53x_InJumpForDEP(struct nfc_device *pnd, case NBR_UNDEFINED: pnd->last_error = NFC_EINVARG; return pnd->last_error; - break; } if (pbtNFCID3i) { @@ -3128,22 +3105,17 @@ pn53x_nm_to_pm(const nfc_modulation nm) switch (nm.nmt) { case NMT_ISO14443A: return PM_ISO14443A_106; - break; case NMT_ISO14443B: switch (nm.nbr) { case NBR_106: return PM_ISO14443B_106; - break; case NBR_212: return PM_ISO14443B_212; - break; case NBR_424: return PM_ISO14443B_424; - break; case NBR_847: return PM_ISO14443B_847; - break; case NBR_UNDEFINED: // Nothing to do... break; @@ -3152,16 +3124,13 @@ pn53x_nm_to_pm(const nfc_modulation nm) case NMT_JEWEL: return PM_JEWEL_106; - break; case NMT_FELICA: switch (nm.nbr) { case NBR_212: return PM_FELICA_212; - break; case NBR_424: return PM_FELICA_424; - break; case NBR_106: case NBR_847: case NBR_UNDEFINED: @@ -3194,36 +3163,31 @@ pn53x_ptt_to_nm(const pn53x_target_type ptt) case PTT_MIFARE: case PTT_ISO14443_4A_106: return (const nfc_modulation) { .nmt = NMT_ISO14443A, .nbr = NBR_106 }; - break; case PTT_ISO14443_4B_106: case PTT_ISO14443_4B_TCL_106: return (const nfc_modulation) { .nmt = NMT_ISO14443B, .nbr = NBR_106 }; - break; case PTT_JEWEL_106: return (const nfc_modulation) { .nmt = NMT_JEWEL, .nbr = NBR_106 }; - break; case PTT_FELICA_212: return (const nfc_modulation) { .nmt = NMT_FELICA, .nbr = NBR_212 }; - break; + case PTT_FELICA_424: return (const nfc_modulation) { .nmt = NMT_FELICA, .nbr = NBR_424 }; - break; case PTT_DEP_PASSIVE_106: case PTT_DEP_ACTIVE_106: return (const nfc_modulation) { .nmt = NMT_DEP, .nbr = NBR_106 }; - break; + case PTT_DEP_PASSIVE_212: case PTT_DEP_ACTIVE_212: return (const nfc_modulation) { .nmt = NMT_DEP, .nbr = NBR_212 }; - break; + case PTT_DEP_PASSIVE_424: case PTT_DEP_ACTIVE_424: return (const nfc_modulation) { .nmt = NMT_DEP, .nbr = NBR_424 }; - break; } // We should never be here, this line silent compilation warning return (const nfc_modulation) { .nmt = NMT_ISO14443A, .nbr = NBR_106 }; @@ -3236,13 +3200,12 @@ pn53x_nm_to_ptt(const nfc_modulation nm) case NMT_ISO14443A: return PTT_MIFARE; // return PTT_ISO14443_4A_106; - break; case NMT_ISO14443B: switch (nm.nbr) { case NBR_106: return PTT_ISO14443_4B_106; - break; + case NBR_UNDEFINED: case NBR_212: case NBR_424: @@ -3254,16 +3217,15 @@ pn53x_nm_to_ptt(const nfc_modulation nm) case NMT_JEWEL: return PTT_JEWEL_106; - break; case NMT_FELICA: switch (nm.nbr) { case NBR_212: return PTT_FELICA_212; - break; + case NBR_424: return PTT_FELICA_424; - break; + case NBR_UNDEFINED: case NBR_106: case NBR_847: diff --git a/libnfc/nfc.c b/libnfc/nfc.c index f9d0c298..7ca4c240 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -1260,22 +1260,15 @@ str_nfc_baud_rate(const nfc_baud_rate nbr) switch (nbr) { case NBR_UNDEFINED: return "undefined baud rate"; - break; case NBR_106: return "106 kbps"; - break; case NBR_212: return "212 kbps"; - break; case NBR_424: return "424 kbps"; - break; case NBR_847: return "847 kbps"; - break; } - // Should never go there.. - return ""; } /** @ingroup string-converter @@ -1289,31 +1282,21 @@ str_nfc_modulation_type(const nfc_modulation_type nmt) switch (nmt) { case NMT_ISO14443A: return "ISO/IEC 14443A"; - break; case NMT_ISO14443B: return "ISO/IEC 14443-4B"; - break; case NMT_ISO14443BI: return "ISO/IEC 14443-4B'"; - break; case NMT_ISO14443B2CT: return "ISO/IEC 14443-2B ASK CTx"; - break; case NMT_ISO14443B2SR: return "ISO/IEC 14443-2B ST SRx"; - break; case NMT_FELICA: return "FeliCa"; - break; case NMT_JEWEL: return "Innovision Jewel"; - break; case NMT_DEP: return "D.E.P."; - break; } - // Should never go there.. - return ""; } /** @ingroup string-converter diff --git a/utils/jewel.c b/utils/jewel.c index cf9bf417..11434b80 100644 --- a/utils/jewel.c +++ b/utils/jewel.c @@ -97,7 +97,6 @@ nfc_initiator_jewel_cmd(nfc_device *pnd, const jewel_req req, jewel_res *pres) break; default: return false; - break; } if (nfc_initiator_transceive_bytes(pnd, (uint8_t *)&req, nLenReq, (uint8_t *)pres, nLenRes, -1) < 0) { diff --git a/utils/mifare.c b/utils/mifare.c index a84bfa85..5e368fce 100644 --- a/utils/mifare.c +++ b/utils/mifare.c @@ -95,7 +95,6 @@ nfc_initiator_mifare_cmd(nfc_device *pnd, const mifare_cmd mc, const uint8_t ui8 // Please fix your code, you never should reach this statement default: return false; - break; } // When available, copy the parameter bytes diff --git a/utils/nfc-read-forum-tag3.c b/utils/nfc-read-forum-tag3.c index c9bae9a0..bfa372be 100644 --- a/utils/nfc-read-forum-tag3.c +++ b/utils/nfc-read-forum-tag3.c @@ -178,7 +178,6 @@ main(int argc, char *argv[]) case 'h': print_usage(argv[0]); exit(EXIT_SUCCESS); - break; case 'q': quiet = true; break; From 6ab3c368b8cc05a001bdc5bde1cb588f283533d8 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 4 Mar 2014 01:41:01 +0100 Subject: [PATCH 061/318] nfc-emulate-uid: remove unreachable code and add proper cleaning when interrupted --- examples/nfc-emulate-uid.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/nfc-emulate-uid.c b/examples/nfc-emulate-uid.c index a744e518..690388ed 100644 --- a/examples/nfc-emulate-uid.c +++ b/examples/nfc-emulate-uid.c @@ -79,7 +79,10 @@ intr_hdlr(int sig) if (pnd != NULL) { printf("\nAborting current command...\n"); nfc_abort_command(pnd); + nfc_close(pnd); } + nfc_exit(context); + exit(EXIT_SUCCESS); } static void @@ -237,7 +240,4 @@ main(int argc, char *argv[]) } } } - nfc_close(pnd); - nfc_exit(context); - exit(EXIT_SUCCESS); } From 6b743233695199355328b75d3b4c2a71a7c72e93 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 4 Mar 2014 01:47:42 +0100 Subject: [PATCH 062/318] target_is_present(): remove unreachable code --- libnfc/chips/pn53x.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 4109602c..31c6da78 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -2036,7 +2036,7 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) } // Ping target - int ret; + int ret = NFC_EDEVNOTSUPP; switch (CHIP_DATA(pnd)->current_target->nm.nmt) { case NMT_ISO14443A: if (CHIP_DATA(pnd)->current_target->nti.nai.btSak & 0x20) { @@ -2073,10 +2073,6 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) case NMT_ISO14443B2CT: ret = pn53x_ISO14443B_CT_is_present(pnd); break; - default: - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): card type not supported"); - ret = NFC_EDEVNOTSUPP; - break; } if (ret == NFC_ETGRELEASED) pn53x_current_target_free(pnd); From 108de27c1b45585392d8e2d4bef76b4317e81502 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 5 Mar 2014 17:48:55 +0100 Subject: [PATCH 063/318] Fix typo baud<>bauds thanks to Polluks --- contrib/win32/libnfc/buses/uart.c | 4 ++-- libnfc/buses/uart.c | 4 ++-- libnfc/drivers/acr122s.c | 4 ++-- libnfc/drivers/arygon.c | 4 ++-- libnfc/drivers/pn532_uart.c | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/contrib/win32/libnfc/buses/uart.c b/contrib/win32/libnfc/buses/uart.c index bfb20c01..a109d5e2 100644 --- a/contrib/win32/libnfc/buses/uart.c +++ b/contrib/win32/libnfc/buses/uart.c @@ -123,7 +123,7 @@ uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) { struct serial_port_windows *spw; - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Serial port speed requested to be set to %d bauds.", uiPortSpeed); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Serial port speed requested to be set to %d baud.", uiPortSpeed); // Set port speed (Input and Output) switch (uiPortSpeed) { case 9600: @@ -135,7 +135,7 @@ uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) case 460800: break; default: - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set serial port speed to %d bauds. Speed value must be one of these constants: 9600 (default), 19200, 38400, 57600, 115200, 230400 or 460800.", uiPortSpeed); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set serial port speed to %d baud. Speed value must be one of these constants: 9600 (default), 19200, 38400, 57600, 115200, 230400 or 460800.", uiPortSpeed); return; }; spw = (struct serial_port_windows *) sp; diff --git a/libnfc/buses/uart.c b/libnfc/buses/uart.c index 0c6227be..953c1264 100644 --- a/libnfc/buses/uart.c +++ b/libnfc/buses/uart.c @@ -179,7 +179,7 @@ uart_flush_input(serial_port sp, bool wait) void uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Serial port speed requested to be set to %d bauds.", uiPortSpeed); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Serial port speed requested to be set to %d baud.", uiPortSpeed); // Portability note: on some systems, B9600 != 9600 so we have to do // uint32_t <=> speed_t associations by hand. @@ -215,7 +215,7 @@ uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) break; # endif default: - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set serial port speed to %d bauds. Speed value must be one of those defined in termios(3).", + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set serial port speed to %d baud. Speed value must be one of those defined in termios(3).", uiPortSpeed); return; }; diff --git a/libnfc/drivers/acr122s.c b/libnfc/drivers/acr122s.c index 2f6ec1dd..322a26c7 100644 --- a/libnfc/drivers/acr122s.c +++ b/libnfc/drivers/acr122s.c @@ -422,7 +422,7 @@ acr122s_scan(const nfc_context *context, nfc_connstring connstrings[], const siz while ((acPort = acPorts[iDevice++])) { sp = uart_open(acPort); - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Trying to find ACR122S device on serial port: %s at %d bauds.", acPort, ACR122S_DEFAULT_SPEED); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Trying to find ACR122S device on serial port: %s at %d baud.", acPort, ACR122S_DEFAULT_SPEED); if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) { // We need to flush input to be sure first reply does not comes from older byte transceive @@ -562,7 +562,7 @@ acr122s_open(const nfc_context *context, const nfc_connstring connstring) } log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, - "Attempt to connect to: %s at %d bauds.", ndd.port, ndd.speed); + "Attempt to connect to: %s at %d baud.", ndd.port, ndd.speed); sp = uart_open(ndd.port); if (sp == INVALID_SERIAL_PORT) { diff --git a/libnfc/drivers/arygon.c b/libnfc/drivers/arygon.c index 1ff38f4f..b69b1295 100644 --- a/libnfc/drivers/arygon.c +++ b/libnfc/drivers/arygon.c @@ -109,7 +109,7 @@ arygon_scan(const nfc_context *context, nfc_connstring connstrings[], const size while ((acPort = acPorts[iDevice++])) { sp = uart_open(acPort); - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Trying to find ARYGON device on serial port: %s at %d bauds.", acPort, ARYGON_DEFAULT_SPEED); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Trying to find ARYGON device on serial port: %s at %d baud.", acPort, ARYGON_DEFAULT_SPEED); if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) { // We need to flush input to be sure first reply does not comes from older byte transceive @@ -253,7 +253,7 @@ arygon_open(const nfc_context *context, const nfc_connstring connstring) serial_port sp; nfc_device *pnd = NULL; - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Attempt to open: %s at %d bauds.", ndd.port, ndd.speed); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Attempt to open: %s at %d baud.", ndd.port, ndd.speed); sp = uart_open(ndd.port); if (sp == INVALID_SERIAL_PORT) diff --git a/libnfc/drivers/pn532_uart.c b/libnfc/drivers/pn532_uart.c index d89b5f43..6dd4a21a 100644 --- a/libnfc/drivers/pn532_uart.c +++ b/libnfc/drivers/pn532_uart.c @@ -82,7 +82,7 @@ pn532_uart_scan(const nfc_context *context, nfc_connstring connstrings[], const while ((acPort = acPorts[iDevice++])) { sp = uart_open(acPort); - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Trying to find PN532 device on serial port: %s at %d bauds.", acPort, PN532_UART_DEFAULT_SPEED); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Trying to find PN532 device on serial port: %s at %d baud.", acPort, PN532_UART_DEFAULT_SPEED); if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) { // We need to flush input to be sure first reply does not comes from older byte transceive @@ -225,7 +225,7 @@ pn532_uart_open(const nfc_context *context, const nfc_connstring connstring) serial_port sp; nfc_device *pnd = NULL; - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Attempt to open: %s at %d bauds.", ndd.port, ndd.speed); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Attempt to open: %s at %d baud.", ndd.port, ndd.speed); sp = uart_open(ndd.port); if (sp == INVALID_SERIAL_PORT) From ddde2dd8f2749e2c2a9302f60e9dd747f0da46e9 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 11 Mar 2014 00:13:26 +0100 Subject: [PATCH 064/318] initiator_select_passive_target(): now supports all speeds for ISO14443-4A tags --- libnfc/chips/pn53x.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 31c6da78..d85c7d0a 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1143,7 +1143,7 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, } else { const pn53x_modulation pm = pn53x_nm_to_pm(nm); - if (PM_UNDEFINED == pm) { + if ((PM_UNDEFINED == pm)||(NBR_UNDEFINED == nm.nbr)) { pnd->last_error = NFC_EINVARG; return pnd->last_error; } @@ -1158,6 +1158,14 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, if ((res = pn53x_decode_target_data(abtTargetsData + 1, szTargetsData - 1, CHIP_DATA(pnd)->type, nm.nmt, &(nttmp.nti))) < 0) { return res; } + if (nm.nbr != NBR_106) { + uint8_t pncmd_inpsl[4] = { InPSL, 0x01 }; + pncmd_inpsl[2] = nm.nbr - 1; + pncmd_inpsl[3] = nm.nbr - 1; + if ((res = pn53x_transceive(pnd, pncmd_inpsl, sizeof(pncmd_inpsl), NULL, 0, 0)) < 0) { + return res; + } + } } if (pn53x_current_target_new(pnd, &nttmp) == NULL) { pnd->last_error = NFC_ESOFT; From 89fc6a723edb17c118a5a6cdc659e08bf0fa6573 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 11 Mar 2014 00:25:33 +0100 Subject: [PATCH 065/318] make style --- libnfc/chips/pn53x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index d85c7d0a..38417820 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1143,7 +1143,7 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, } else { const pn53x_modulation pm = pn53x_nm_to_pm(nm); - if ((PM_UNDEFINED == pm)||(NBR_UNDEFINED == nm.nbr)) { + if ((PM_UNDEFINED == pm) || (NBR_UNDEFINED == nm.nbr)) { pnd->last_error = NFC_EINVARG; return pnd->last_error; } From e57dc8a746d5d4257a70f87aaae80bab87f20b8a Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 11 Mar 2014 23:52:47 +0100 Subject: [PATCH 066/318] Better list of supported modulations & baud rates * Extend supported baud rates for TypeA * Extend supported modulations B->BI,B2SR,B2CT * Use InPSL only on TypeA * Add mode to nfc_get_supported_baud_rate() (API change!) * Fix supported baud rates for BI,B2SR,B2CT * Remove supported modulations as target for ASK LoGO Before: $ nfc-scan-device -v 3 NFC device(s) found: - ACS / ACR122U PICC Interface: acr122_usb:002:024 chip: PN532 v1.4 initator mode modulations: ISO/IEC 14443A (106 kbps), FeliCa (424 kbps, 212 kbps), ISO/IEC 14443-4B (106 kbps), Innovision Jewel (106 kbps), D.E.P. (424 kbps, 212 kbps, 106 kbps) target mode modulations: ISO/IEC 14443A (106 kbps), FeliCa (424 kbps, 212 kbps), D.E.P. (424 kbps, 212 kbps, 106 kbps) - SCM Micro / SCL3711-NFC&RW: pn53x_usb:002:028 chip: PN533 v2.7 initator mode modulations: ISO/IEC 14443A (106 kbps), FeliCa (424 kbps, 212 kbps), ISO/IEC 14443-4B (847 kbps, 424 kbps, 212 kbps, 106 kbps), Innovision Jewel (106 kbps), D.E.P. (424 kbps, 212 kbps, 106 kbps) target mode modulations: ISO/IEC 14443A (106 kbps), FeliCa (424 kbps, 212 kbps), D.E.P. (424 kbps, 212 kbps, 106 kbps) - ASK / LoGO: pn53x_usb:002:023 chip: PN533 v2.7 initator mode modulations: ISO/IEC 14443A (106 kbps), FeliCa (424 kbps, 212 kbps), ISO/IEC 14443-4B (847 kbps, 424 kbps, 212 kbps, 106 kbps), Innovision Jewel (106 kbps), D.E.P. (424 kbps, 212 kbps, 106 kbps) target mode modulations: ISO/IEC 14443A (106 kbps), FeliCa (424 kbps, 212 kbps), D.E.P. (424 kbps, 212 kbps, 106 kbps) After: $ nfc-scan-device -v 3 NFC device(s) found: - ACS / ACR122U PICC Interface: acr122_usb:002:024 chip: PN532 v1.4 initator mode modulations: ISO/IEC 14443A (424 kbps, 212 kbps, 106 kbps), FeliCa (424 kbps, 212 kbps), ISO/IEC 14443-4B (106 kbps), ISO/IEC 14443-4B' (106 kbps), ISO/IEC 14443-2B ST SRx (106 kbps), ISO/IEC 14443-2B ASK CTx (106 kbps), Innovision Jewel (106 kbps), D.E.P. (424 kbps, 212 kbps, 106 kbps) target mode modulations: ISO/IEC 14443A (424 kbps, 212 kbps, 106 kbps), FeliCa (424 kbps, 212 kbps), D.E.P. (424 kbps, 212 kbps, 106 kbps) - SCM Micro / SCL3711-NFC&RW: pn53x_usb:002:025 chip: PN533 v2.7 initator mode modulations: ISO/IEC 14443A (847 kbps, 424 kbps, 212 kbps, 106 kbps), FeliCa (424 kbps, 212 kbps), ISO/IEC 14443-4B (847 kbps, 424 kbps, 212 kbps, 106 kbps), ISO/IEC 14443-4B' (106 kbps), ISO/IEC 14443-2B ST SRx (106 kbps), ISO/IEC 14443-2B ASK CTx (106 kbps), Innovision Jewel (106 kbps), D.E.P. (424 kbps, 212 kbps, 106 kbps) target mode modulations: ISO/IEC 14443A (424 kbps, 212 kbps, 106 kbps), FeliCa (424 kbps, 212 kbps), D.E.P. (424 kbps, 212 kbps, 106 kbps) - ASK / LoGO: pn53x_usb:002:023 chip: PN533 v2.7 initator mode modulations: ISO/IEC 14443A (847 kbps, 424 kbps, 212 kbps, 106 kbps), FeliCa (424 kbps, 212 kbps), ISO/IEC 14443-4B (847 kbps, 424 kbps, 212 kbps, 106 kbps), ISO/IEC 14443-4B' (106 kbps), ISO/IEC 14443-2B ST SRx (106 kbps), ISO/IEC 14443-2B ASK CTx (106 kbps), Innovision Jewel (106 kbps), D.E.P. (424 kbps, 212 kbps, 106 kbps) target mode modulations: --- NEWS | 6 ++++++ include/nfc/nfc.h | 2 +- libnfc/chips/pn53x.c | 39 +++++++++++++++++++++++++------------- libnfc/chips/pn53x.h | 2 +- libnfc/drivers/pn53x_usb.c | 14 +++++++++++++- libnfc/nfc-internal.h | 2 +- libnfc/nfc.c | 5 +++-- 7 files changed, 51 insertions(+), 19 deletions(-) diff --git a/NEWS b/NEWS index 83b7d91e..e3f5411d 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,9 @@ +New in 1.7.x: + +API Changes: + + * nfc_device_get_supported_baud_rate() now takes also "mode" as argument + New in 1.7.1: API Changes: diff --git a/include/nfc/nfc.h b/include/nfc/nfc.h index 44f92d99..9e9e78cf 100644 --- a/include/nfc/nfc.h +++ b/include/nfc/nfc.h @@ -126,7 +126,7 @@ NFC_EXPORT int nfc_device_get_last_error(const nfc_device *pnd); NFC_EXPORT const char *nfc_device_get_name(nfc_device *pnd); NFC_EXPORT const char *nfc_device_get_connstring(nfc_device *pnd); NFC_EXPORT int nfc_device_get_supported_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type **const supported_mt); -NFC_EXPORT int nfc_device_get_supported_baud_rate(nfc_device *pnd, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br); +NFC_EXPORT int nfc_device_get_supported_baud_rate(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br); /* Properties accessors */ NFC_EXPORT int nfc_device_set_property_int(nfc_device *pnd, const nfc_property property, const int value); diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 38417820..41142310 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -52,7 +52,8 @@ const uint8_t pn53x_ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 }; const uint8_t pn53x_nack_frame[] = { 0x00, 0x00, 0xff, 0xff, 0x00, 0x00 }; static const uint8_t pn53x_error_frame[] = { 0x00, 0x00, 0xff, 0x01, 0xff, 0x7f, 0x81, 0x00 }; -const nfc_baud_rate pn53x_iso14443a_supported_baud_rates[] = { NBR_106, 0 }; +const nfc_baud_rate pn532_iso14443a_supported_baud_rates[] = { NBR_424, NBR_212, NBR_106, 0 }; +const nfc_baud_rate pn533_iso14443a_supported_baud_rates[] = { NBR_847, NBR_424, NBR_212, NBR_106, 0 }; 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 }; @@ -96,6 +97,12 @@ pn53x_init(struct nfc_device *pnd) if (pnd->btSupportByte & SUPPORT_ISO14443B) { CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_ISO14443B; nbSupportedModulation++; + CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_ISO14443BI; + nbSupportedModulation++; + CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_ISO14443B2SR; + nbSupportedModulation++; + CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_ISO14443B2CT; + nbSupportedModulation++; } if (CHIP_DATA(pnd)->type != PN531) { CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_JEWEL; @@ -1158,7 +1165,7 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, if ((res = pn53x_decode_target_data(abtTargetsData + 1, szTargetsData - 1, CHIP_DATA(pnd)->type, nm.nmt, &(nttmp.nti))) < 0) { return res; } - if (nm.nbr != NBR_106) { + if ((nm.nmt == NMT_ISO14443A) && (nm.nbr != NBR_106)) { uint8_t pncmd_inpsl[4] = { InPSL, 0x01 }; pncmd_inpsl[2] = nm.nbr - 1; pncmd_inpsl[3] = nm.nbr - 1; @@ -3265,19 +3272,21 @@ pn53x_get_supported_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_m } int -pn53x_get_supported_baud_rate(nfc_device *pnd, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br) +pn53x_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 *)pn53x_felica_supported_baud_rates; break; - case NMT_ISO14443A: - *supported_br = (nfc_baud_rate *)pn53x_iso14443a_supported_baud_rates; - break; - case NMT_ISO14443B: - case NMT_ISO14443BI: - case NMT_ISO14443B2SR: - case NMT_ISO14443B2CT: { + case NMT_ISO14443A: { + if ((CHIP_DATA(pnd)->type != PN533) || (mode == N_TARGET)) { + *supported_br = (nfc_baud_rate *)pn532_iso14443a_supported_baud_rates; + } else { + *supported_br = (nfc_baud_rate *)pn533_iso14443a_supported_baud_rates; + } + } + break; + case NMT_ISO14443B: { if ((CHIP_DATA(pnd)->type != PN533)) { *supported_br = (nfc_baud_rate *)pn532_iso14443b_supported_baud_rates; } else { @@ -3285,6 +3294,11 @@ pn53x_get_supported_baud_rate(nfc_device *pnd, const nfc_modulation_type nmt, co } } break; + case NMT_ISO14443BI: + case NMT_ISO14443B2SR: + case NMT_ISO14443B2CT: + *supported_br = (nfc_baud_rate *)pn532_iso14443b_supported_baud_rates; + break; case NMT_JEWEL: *supported_br = (nfc_baud_rate *)pn53x_jewel_supported_baud_rates; break; @@ -3347,7 +3361,7 @@ pn53x_get_information_about(nfc_device *pnd, char **pbuf) } buflen -= res; const nfc_baud_rate *nbr; - if ((res = nfc_device_get_supported_baud_rate(pnd, nmt[i], &nbr)) < 0) { + if ((res = nfc_device_get_supported_baud_rate(pnd, N_INITIATOR, nmt[i], &nbr)) < 0) { free(*pbuf); return res; } @@ -3400,7 +3414,6 @@ pn53x_get_information_about(nfc_device *pnd, char **pbuf) free(*pbuf); return res; } - for (int i = 0; nmt[i]; i++) { if ((res = snprintf(buf, buflen, "%s%s (", (i == 0) ? "" : ", ", str_nfc_modulation_type(nmt[i]))) < 0) { free(*pbuf); @@ -3413,7 +3426,7 @@ pn53x_get_information_about(nfc_device *pnd, char **pbuf) } buflen -= res; const nfc_baud_rate *nbr; - if ((res = nfc_device_get_supported_baud_rate(pnd, nmt[i], &nbr)) < 0) { + if ((res = nfc_device_get_supported_baud_rate(pnd, N_TARGET, nmt[i], &nbr)) < 0) { free(*pbuf); return res; } diff --git a/libnfc/chips/pn53x.h b/libnfc/chips/pn53x.h index b45f1c5b..bb5d6e30 100644 --- a/libnfc/chips/pn53x.h +++ b/libnfc/chips/pn53x.h @@ -392,7 +392,7 @@ int pn53x_check_ack_frame(struct nfc_device *pnd, const uint8_t *pbtRxFrame, int pn53x_check_error_frame(struct nfc_device *pnd, const uint8_t *pbtRxFrame, const size_t szRxFrameLen); int pn53x_build_frame(uint8_t *pbtFrame, size_t *pszFrame, const uint8_t *pbtData, const size_t szData); int pn53x_get_supported_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type **const supported_mt); -int pn53x_get_supported_baud_rate(nfc_device *pnd, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br); +int pn53x_get_supported_baud_rate(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br); int pn53x_get_information_about(nfc_device *pnd, char **pbuf); void *pn53x_data_new(struct nfc_device *pnd, const struct pn53x_io *io); diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index e75a0863..b4dbe89a 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -60,6 +60,8 @@ Thanks to d18c7db and Okko for example code #define DRIVER_DATA(pnd) ((struct pn53x_usb_data*)(pnd->driver_data)) +const nfc_modulation_type no_target_support[] = {0}; + typedef enum { UNKNOWN, NXP_PN531, @@ -709,6 +711,16 @@ pn53x_usb_abort_command(nfc_device *pnd) return NFC_SUCCESS; } +static int +pn53x_usb_get_supported_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type **const supported_mt) +{ + if ((DRIVER_DATA(pnd)->model != ASK_LOGO) || (mode != N_TARGET)) + return pn53x_get_supported_modulation(pnd, mode, supported_mt); + else // ASK_LOGO has no N_TARGET support + *supported_mt = no_target_support; + return NFC_SUCCESS; +} + const struct pn53x_io pn53x_usb_io = { .send = pn53x_usb_send, .receive = pn53x_usb_receive, @@ -742,7 +754,7 @@ const struct nfc_driver pn53x_usb_driver = { .device_set_property_bool = pn53x_usb_set_property_bool, .device_set_property_int = pn53x_set_property_int, - .get_supported_modulation = pn53x_get_supported_modulation, + .get_supported_modulation = pn53x_usb_get_supported_modulation, .get_supported_baud_rate = pn53x_get_supported_baud_rate, .device_get_information_about = pn53x_get_information_about, diff --git a/libnfc/nfc-internal.h b/libnfc/nfc-internal.h index 0e63c936..4fa2fc2d 100644 --- a/libnfc/nfc-internal.h +++ b/libnfc/nfc-internal.h @@ -148,7 +148,7 @@ struct nfc_driver { int (*device_set_property_bool)(struct nfc_device *pnd, const nfc_property property, const bool bEnable); int (*device_set_property_int)(struct nfc_device *pnd, const nfc_property property, const int value); int (*get_supported_modulation)(struct nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type **const supported_mt); - int (*get_supported_baud_rate)(struct nfc_device *pnd, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br); + int (*get_supported_baud_rate)(struct nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br); int (*device_get_information_about)(struct nfc_device *pnd, char **buf); int (*abort_command)(struct nfc_device *pnd); diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 7ca4c240..2094765a 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -1196,14 +1196,15 @@ nfc_device_get_supported_modulation(nfc_device *pnd, const nfc_mode mode, const * @brief Get supported baud rates. * @return Returns 0 on success, otherwise returns libnfc's error code (negative value) * @param pnd \a nfc_device struct pointer that represent currently used device + * @param mode \a nfc_mode. * @param nmt \a nfc_modulation_type. * @param supported_br pointer of \a nfc_baud_rate array. * */ int -nfc_device_get_supported_baud_rate(nfc_device *pnd, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br) +nfc_device_get_supported_baud_rate(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br) { - HAL(get_supported_baud_rate, pnd, nmt, supported_br); + HAL(get_supported_baud_rate, pnd, mode, nmt, supported_br); } /* Misc. functions */ From 9a254712b58fa075a60581ac0f5ec7222738c2a0 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 12 Mar 2014 00:28:39 +0100 Subject: [PATCH 067/318] nfc_initiator_select_passive_target(): validate modulation and baud rate --- libnfc/nfc.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 2094765a..4294367c 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -158,6 +158,8 @@ nfc_drivers_init(void) #endif /* DRIVER_ARYGON_ENABLED */ } +static int +nfc_device_validate_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_modulation *nm); /** @ingroup lib * @brief Register an NFC device driver with libnfc. @@ -526,6 +528,9 @@ nfc_initiator_select_passive_target(nfc_device *pnd, uint8_t *abtInit = NULL; uint8_t abtTmpInit[MAX(12, szInitData)]; size_t szInit = 0; + int res; + if ((res = nfc_device_validate_modulation(pnd, N_INITIATOR, &nm)) != NFC_SUCCESS) + return res; if (szInitData == 0) { // Provide default values, if any prepare_initiator_data(nm, &abtInit, &szInit); @@ -1207,6 +1212,38 @@ nfc_device_get_supported_baud_rate(nfc_device *pnd, const nfc_mode mode, const n HAL(get_supported_baud_rate, pnd, mode, nmt, supported_br); } +/** @ingroup data + * @brief Validate combination of modulation and baud rate on the currently used device. + * @return Returns 0 on success, otherwise returns libnfc's error code (negative value) + * @param pnd \a nfc_device struct pointer that represent currently used device + * @param mode \a nfc_mode. + * @param nm \a nfc_modulation. + * + */ +static int +nfc_device_validate_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_modulation *nm) +{ + int res; + const nfc_modulation_type *nmt; + if ((res = nfc_device_get_supported_modulation(pnd, mode, &nmt)) < 0) { + return res; + } + for (int i = 0; nmt[i]; i++) { + if (nmt[i] == nm->nmt) { + const nfc_baud_rate *nbr; + if ((res = nfc_device_get_supported_baud_rate(pnd, mode, nmt[i], &nbr)) < 0) { + return res; + } + for (int j = 0; nbr[j]; j++) { + if (nbr[j] == nm->nbr) + return NFC_SUCCESS; + } + return NFC_EINVARG; + } + } + return NFC_EINVARG; +} + /* Misc. functions */ /** @ingroup misc From bd92f74a585d377d3ff952c3ca9d0aeb4aa64aca Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 12 Mar 2014 00:35:43 +0100 Subject: [PATCH 068/318] Update ChangeLog --- ChangeLog | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index a0619b24..a2c6bb34 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,20 @@ +TBD - 1.7.x +----------- +Fixes: + - Remove unreachable code + - nfc_emulate_uid: cleaner exit on interrupt + - Fix reporting of modulations and baud rates by nfc-scan-device -v + +Improvements: + - Allow ISO14443A to be used at higher baud rates + - nfc_initiator_select_passive_target() now checks against + reported modulations and baud rates for current device + +Changes: + - nfc_get_supported_baud_rate() takes now a "mode" parameter + Feb 24, 2014 - 1.7.1 ------------------- +-------------------- Fixes: - Fix several issues reported by Coverity Scan From bb9babbedab84663d8739ef5e4deec6f61320be6 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 14 Apr 2014 23:26:44 +0200 Subject: [PATCH 069/318] Fix out-of-bounds access in nfc-mfultralight unveiled by coverity scan: *** CID 1090333: Out-of-bounds access (OVERRUN) --- ChangeLog | 1 + utils/nfc-mfultralight.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index a2c6bb34..2a2fe64e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ Fixes: - Remove unreachable code - nfc_emulate_uid: cleaner exit on interrupt - Fix reporting of modulations and baud rates by nfc-scan-device -v + - Fix out-of-bounds access in nfc-mfultralight Improvements: - Allow ISO14443A to be used at higher baud rates diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 2a856262..31d6b82d 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -168,7 +168,8 @@ write_card(void) // page (4 bytes). The Ultralight-specific Write command only // writes one page at a time. uiBlock = page / 4; - memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData + ((page % 4) * 4), 16); + memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData + ((page % 4) * 4), 4); + memset(mp.mpd.abtData + 4, 0, 12); if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, page, &mp)) bFailure = true; From b978c45a11a71a502f26ca416381492124d62162 Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Sun, 25 May 2014 16:39:47 +0100 Subject: [PATCH 070/318] tolerate errors when writing as well as reading --- utils/nfc-mfclassic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 12428867..55809fc9 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -405,7 +405,7 @@ write_card(int write_block_zero) fflush(stdout); // Try to authenticate for the current sector - if (!write_block_zero && !authenticate(uiBlock)) { + if (!write_block_zero && !authenticate(uiBlock) && !bTolerateFailures) { printf("!\nError: authentication failed for block %02x\n", uiBlock); return false; } From b6a8745838673e96c9215f4b73781cde0ac2f3b6 Mon Sep 17 00:00:00 2001 From: Marcos Vives Del Sol Date: Sat, 21 Feb 2015 22:57:36 +0100 Subject: [PATCH 071/318] Fix compilation under Cygwin --- libnfc/buses/uart.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libnfc/buses/uart.c b/libnfc/buses/uart.c index 953c1264..72594b0d 100644 --- a/libnfc/buses/uart.c +++ b/libnfc/buses/uart.c @@ -77,12 +77,17 @@ const char *serial_ports_device_radix[] = { "tty.SLAB_USBtoUART", "tty.usbserial-", NULL }; # elif defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__FreeBSD_kernel__) const char *serial_ports_device_radix[] = { "cuaU", "cuau", NULL }; -# elif defined (__linux__) +# elif defined (__linux__) || defined (__CYGWIN__) const char *serial_ports_device_radix[] = { "ttyUSB", "ttyS", "ttyACM", "ttyAMA", "ttyO", NULL }; # else # error "Can't determine serial string for your system" # endif +#ifdef __CYGWIN__ +// Under Cygwin, FIONREAD is defined in this file +# include +#endif + // Work-around to claim uart interface using the c_iflag (software input processing) from the termios struct # define CCLAIMED 0x80000000 From 9d82d598f051d154e03cf87b4f3c880b7c8e56a4 Mon Sep 17 00:00:00 2001 From: Marcos Vives Del Sol Date: Sat, 21 Feb 2015 23:04:06 +0100 Subject: [PATCH 072/318] Fix "missing return" compiler warnings --- libnfc/nfc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 4294367c..2820a143 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -1307,6 +1307,8 @@ str_nfc_baud_rate(const nfc_baud_rate nbr) case NBR_847: return "847 kbps"; } + + return "???"; } /** @ingroup string-converter @@ -1335,6 +1337,8 @@ str_nfc_modulation_type(const nfc_modulation_type nmt) case NMT_DEP: return "D.E.P."; } + + return "???"; } /** @ingroup string-converter From 5a08fcf2bc8699d89f741e94c25a47eeb04cc5be Mon Sep 17 00:00:00 2001 From: Marcos Vives Del Sol Date: Sun, 22 Feb 2015 13:27:13 +0100 Subject: [PATCH 073/318] Fix "undefined reference"s --- utils/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/Makefile.am b/utils/Makefile.am index 9637d254..2555bcd7 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -14,6 +14,7 @@ AM_CPPFLAGS = $(all_includes) $(LIBNFC_CFLAGS) noinst_LTLIBRARIES = libnfcutils.la libnfcutils_la_SOURCES = nfc-utils.c +libnfcutils_la_LIBADD = -lnfc nfc_emulate_forum_tag4_SOURCES = nfc-emulate-forum-tag4.c nfc-utils.h nfc_emulate_forum_tag4_LDADD = $(top_builddir)/libnfc/libnfc.la \ From 92c5bd864bad54f8a96c7fed0f7b49f8e6b14d80 Mon Sep 17 00:00:00 2001 From: Marcos Vives Del Sol Date: Sun, 22 Feb 2015 13:29:07 +0100 Subject: [PATCH 074/318] Added Windows-specific files to .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 318dcfc8..170b8ea5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *~ +*.exe Doxyfile INSTALL Makefile @@ -11,6 +12,7 @@ cmake/Makefile cmake/Makefile.in cmake/modules/Makefile cmake/modules/Makefile.in +compile config.guess config.h config.h.in @@ -102,6 +104,7 @@ test/.deps/ test/.libs/ test/Makefile test/Makefile.in +test-driver utils/*.la utils/*.lo utils/*.o From 4e823d8db01570c216b6941341b623dcbef52cd5 Mon Sep 17 00:00:00 2001 From: Marcos Vives Del Sol Date: Sun, 22 Feb 2015 20:41:59 +0100 Subject: [PATCH 075/318] Use TIOCINQ instead of FIONREAD in Cygwin --- libnfc/buses/uart.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libnfc/buses/uart.c b/libnfc/buses/uart.c index 72594b0d..3f41e19b 100644 --- a/libnfc/buses/uart.c +++ b/libnfc/buses/uart.c @@ -83,9 +83,11 @@ const char *serial_ports_device_radix[] = { "ttyUSB", "ttyS", "ttyACM", "ttyAMA" # error "Can't determine serial string for your system" # endif +// As of 2015/Feb/22, Cygwin does not handle FIONREAD on physical serial devices. +// We'll use TIOCINQ instead which is pretty much the same. #ifdef __CYGWIN__ -// Under Cygwin, FIONREAD is defined in this file -# include +# include +# define FIONREAD TIOCINQ #endif // Work-around to claim uart interface using the c_iflag (software input processing) from the termios struct From 1785ac14c2eab7e66877456845dff29e8b51cb94 Mon Sep 17 00:00:00 2001 From: David Kreitschmann Date: Sat, 4 Apr 2015 22:37:03 +0200 Subject: [PATCH 076/318] Use more serial devices on Mac OS X Some USB-serial adapters just use tty.usbserial or tty.usbmodem as a device name. (e.g. Prolific). Currently part of a patch for homebrew here: https://github.com/Homebrew/homebrew/blob/master/Library/Formula/libnfc. rb --- libnfc/buses/uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnfc/buses/uart.c b/libnfc/buses/uart.c index 953c1264..c0980367 100644 --- a/libnfc/buses/uart.c +++ b/libnfc/buses/uart.c @@ -74,7 +74,7 @@ #endif # if defined(__APPLE__) -const char *serial_ports_device_radix[] = { "tty.SLAB_USBtoUART", "tty.usbserial-", NULL }; +const char *serial_ports_device_radix[] = { "tty.SLAB_USBtoUART", "tty.usbserial", "tty.usbmodem", NULL }; # elif defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__FreeBSD_kernel__) const char *serial_ports_device_radix[] = { "cuaU", "cuau", NULL }; # elif defined (__linux__) From fce491c8299c0b680834e1f243e3d74a24e902ae Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Wed, 15 Apr 2015 17:11:11 +0200 Subject: [PATCH 077/318] README: add a section to help to configure libnfc --- README | 22 +++++++++++++++++++++- libnfc/conf.c | 1 + 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/README b/README index bb4d7c06..2a54d869 100644 --- a/README +++ b/README @@ -3,7 +3,7 @@ * * Libnfc historical contributors: * Copyright (C) 2009 Roel Verdult -* Copyright (C) 2009-2013 Romuald Conty +* Copyright (C) 2009-2015 Romuald Conty * Copyright (C) 2010-2012 Romain Tartière * Copyright (C) 2010-2013 Philippe Teuwen * Copyright (C) 2012-2013 Ludovic Rousseau @@ -55,6 +55,26 @@ Under GNU/Linux systems, if you use udev, you could use the provided udev rules. Under FreeBSD, if you use devd, there is also a rules file: contrib/devd/pn53x.conf. +Configuration +============= + +In order to change the default behavior of the library, the libnfc uses a +configuration file located in sysconfdir (as provided to ./configure). + +A sample commented file is available in sources: libnfc.conf.sample + +If you have compiled using: + ./configure --prefix=/usr --sysconfdir=/etc +you can make configuration directory and copy the sample file: + sudo mkdir /etc/nfc + sudo cp libnfc.conf.sample /etc/nfc/libnfc.conf + +To configure multiple devices, you can either modify libnfc.conf or create a +file per device in a nfc/devices.d directory: + sudo mkdir -p /etc/nfc/devices.d + printf 'name = "My first device"\nconnstring = "pn532_uart:/dev/ttyACM0"\n' | sudo tee /etc/nfc/devices.d/first.conf + printf 'name = "My second device"\nconnstring = "pn532_uart:/dev/ttyACM1"\n' | sudo tee /etc/nfc/devices.d/second.conf + How to report bugs ================== diff --git a/libnfc/conf.c b/libnfc/conf.c index 2319a752..47b2d031 100644 --- a/libnfc/conf.c +++ b/libnfc/conf.c @@ -185,6 +185,7 @@ conf_devices_load(const char *dirname, nfc_context *context) while ((readdir_r(d, &entry, &result) == 0) && (result != NULL)) { de = &entry; #endif + // FIXME add a way to sort devices if (de->d_name[0] != '.') { const size_t filename_len = strlen(de->d_name); const size_t extension_len = strlen(".conf"); From 1fe7c00e485dcdf23ec0a5fcc82b9c36c84ccefa Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Wed, 15 Apr 2015 17:13:54 +0200 Subject: [PATCH 078/318] Git: ignore utils/nfc-jewel --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 170b8ea5..772b3649 100644 --- a/.gitignore +++ b/.gitignore @@ -113,6 +113,7 @@ utils/.libs/ utils/Makefile utils/Makefile.in utils/nfc-emulate-forum-tag4 +utils/nfc-jewel utils/nfc-list utils/nfc-mfclassic utils/nfc-mfultralight From 0f77565a3cf5395c3b58e9f83635134281da82e3 Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Wed, 15 Apr 2015 17:19:42 +0200 Subject: [PATCH 079/318] Fix cmake soversion (doesn't match autotools) Thanks to Julien Schueller --- libnfc/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnfc/CMakeLists.txt b/libnfc/CMakeLists.txt index 66d21240..7a51bb0d 100644 --- a/libnfc/CMakeLists.txt +++ b/libnfc/CMakeLists.txt @@ -89,7 +89,7 @@ IF(LIBUSB_FOUND) TARGET_LINK_LIBRARIES(nfc ${LIBUSB_LIBRARIES}) ENDIF(LIBUSB_FOUND) -SET_TARGET_PROPERTIES(nfc PROPERTIES SOVERSION 0) +SET_TARGET_PROPERTIES(nfc PROPERTIES SOVERSION 5 VERSION 5.0.1) IF(WIN32) # Libraries that are windows specific From c31f8bd9be63419218f614b05690660285a3fd0d Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Tue, 28 Apr 2015 19:22:16 +0200 Subject: [PATCH 080/318] Doc: minor documentation fixes --- libnfc/nfc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 2820a143..a43d9daf 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -482,13 +482,13 @@ nfc_initiator_init(nfc_device *pnd) } /** @ingroup initiator - * @brief Initialize NFC device as initiator with its secure element initiator (reader) + * @brief Initialize NFC device as initiator with its secure element as target (reader) * @return Returns 0 on success, otherwise returns libnfc's error code (negative value) * @param pnd \a nfc_device struct pointer that represent currently used device * * The NFC device is configured to function as secure element reader. * After initialization it can be used to communicate with the secure element. - * @note RF field is desactvated in order to some power + * @note RF field is deactivated in order to save some power */ int nfc_initiator_init_secure_element(nfc_device *pnd) @@ -1290,7 +1290,7 @@ nfc_device_get_information_about(nfc_device *pnd, char **buf) /** @ingroup string-converter * @brief Convert \a nfc_baud_rate value to string * @return Returns nfc baud rate - * @param \a nfc_baud_rate to convert + * @param nbr \a nfc_baud_rate to convert */ const char * str_nfc_baud_rate(const nfc_baud_rate nbr) @@ -1314,7 +1314,7 @@ str_nfc_baud_rate(const nfc_baud_rate nbr) /** @ingroup string-converter * @brief Convert \a nfc_modulation_type value to string * @return Returns nfc modulation type - * @param \a nfc_modulation_type to convert + * @param nmt \a nfc_modulation_type to convert */ const char * str_nfc_modulation_type(const nfc_modulation_type nmt) From 8fbedb87f5c70dc1353b4e159f7e69f95926565b Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Thu, 30 Apr 2015 14:19:03 +0200 Subject: [PATCH 081/318] Update links from googlecode to github. --- README | 8 +++----- examples/nfc-anticol.1 | 2 +- examples/nfc-dep-initiator.1 | 2 +- examples/nfc-dep-target.1 | 2 +- examples/nfc-emulate-forum-tag2.1 | 2 +- examples/nfc-emulate-tag.1 | 2 +- examples/nfc-emulate-uid.1 | 2 +- examples/nfc-mfsetuid.1 | 2 +- examples/nfc-poll.1 | 2 +- examples/nfc-relay.1 | 2 +- examples/pn53x-diagnose.1 | 2 +- examples/pn53x-sam.1 | 2 +- examples/pn53x-tamashell.1 | 2 +- utils/nfc-emulate-forum-tag4.1 | 2 +- utils/nfc-jewel.1 | 2 +- utils/nfc-list.1 | 2 +- utils/nfc-mfclassic.1 | 2 +- utils/nfc-mfultralight.1 | 2 +- utils/nfc-read-forum-tag3.1 | 2 +- utils/nfc-relay-picc.1 | 2 +- utils/nfc-scan-device.1 | 2 +- 21 files changed, 23 insertions(+), 25 deletions(-) diff --git a/README b/README index 2a54d869..d557d4fb 100644 --- a/README +++ b/README @@ -23,7 +23,7 @@ The official forum site is: http://www.libnfc.org/community/ The official development site is: - http://libnfc.googlecode.com/ + https://github.com/nfc-tools/libnfc Important note: this file covers POSIX systems, for Windows please read README-Windows.txt @@ -78,7 +78,7 @@ file per device in a nfc/devices.d directory: How to report bugs ================== -To report a bug, visit http://code.google.com/p/libnfc/issues/list and fill +To report a bug, visit https://github.com/nfc-tools/libnfc/issues and fill out a bug report form. If you have questions, remarks, we encourage you to post this in the developers @@ -118,9 +118,7 @@ Please make sure to include: Patches ======= -Patches can be posted to http://code.google.com/p/libnfc/issues/list or -can be sent directly to libnfc's developers: -http://nfc-tools.org/index.php?title=Contact +Patches can be posted to https://github.com/nfc-tools/libnfc/issues If the patch fixes a bug, it is usually a good idea to include all the information described in "How to Report Bugs". diff --git a/examples/nfc-anticol.1 b/examples/nfc-anticol.1 index 2b048b9c..578f1d5b 100644 --- a/examples/nfc-anticol.1 +++ b/examples/nfc-anticol.1 @@ -23,7 +23,7 @@ Please report any bugs on the .B libnfc issue tracker at: .br -.BR http://code.google.com/p/libnfc/issues +.BR https://github.com/nfc-tools/libnfc/issues .SH LICENCE .B libnfc is licensed under the GNU Lesser General Public License (LGPL), version 3. diff --git a/examples/nfc-dep-initiator.1 b/examples/nfc-dep-initiator.1 index 9c2e710e..3383901f 100644 --- a/examples/nfc-dep-initiator.1 +++ b/examples/nfc-dep-initiator.1 @@ -18,7 +18,7 @@ Please report any bugs on the .B libnfc issue tracker at: .br -.BR http://code.google.com/p/libnfc/issues +.BR https://github.com/nfc-tools/libnfc/issues .SH LICENCE .B libnfc is licensed under the GNU Lesser General Public License (LGPL), version 3. diff --git a/examples/nfc-dep-target.1 b/examples/nfc-dep-target.1 index 414ff57c..9cf70a16 100644 --- a/examples/nfc-dep-target.1 +++ b/examples/nfc-dep-target.1 @@ -18,7 +18,7 @@ Please report any bugs on the .B libnfc issue tracker at: .br -.BR http://code.google.com/p/libnfc/issues +.BR https://github.com/nfc-tools/libnfc/issues .SH LICENCE .B libnfc is licensed under the GNU Lesser General Public License (LGPL), version 3. diff --git a/examples/nfc-emulate-forum-tag2.1 b/examples/nfc-emulate-forum-tag2.1 index fc5f82e6..9b5fc1de 100644 --- a/examples/nfc-emulate-forum-tag2.1 +++ b/examples/nfc-emulate-forum-tag2.1 @@ -35,7 +35,7 @@ bug, this problem is due to ACR122's internal MCU in front of NFC chip (PN532). Please report any bugs on the .Em libnfc issue tracker at: -.Em http://code.google.com/p/libnfc/issues +.Em https://github.com/nfc-tools/libnfc/issues .Sh LICENCE .Em libnfc is licensed under the GNU Lesser General Public License (LGPL), version 3. diff --git a/examples/nfc-emulate-tag.1 b/examples/nfc-emulate-tag.1 index 8271a8f4..a8dc07ee 100644 --- a/examples/nfc-emulate-tag.1 +++ b/examples/nfc-emulate-tag.1 @@ -39,7 +39,7 @@ Please report any bugs on the .B libnfc issue tracker at: .br -.BR http://code.google.com/p/libnfc/issues +.BR https://github.com/nfc-tools/libnfc/issues .SH LICENCE .B libnfc is licensed under the GNU Lesser General Public License (LGPL), version 3. diff --git a/examples/nfc-emulate-uid.1 b/examples/nfc-emulate-uid.1 index f98908bd..f0e21640 100644 --- a/examples/nfc-emulate-uid.1 +++ b/examples/nfc-emulate-uid.1 @@ -54,7 +54,7 @@ Please report any bugs on the .B libnfc issue tracker at: .br -.BR http://code.google.com/p/libnfc/issues +.BR https://github.com/nfc-tools/libnfc/issues .SH LICENCE .B libnfc is licensed under the GNU Lesser General Public License (LGPL), version 3. diff --git a/examples/nfc-mfsetuid.1 b/examples/nfc-mfsetuid.1 index 370bf91f..d0d7df10 100644 --- a/examples/nfc-mfsetuid.1 +++ b/examples/nfc-mfsetuid.1 @@ -24,7 +24,7 @@ Please report any bugs on the .B libnfc issue tracker at: .br -.BR http://code.google.com/p/libnfc/issues +.BR https://github.com/nfc-tools/libnfc/issues .SH LICENCE .B libnfc is licensed under the GNU Lesser General Public License (LGPL), version 3. diff --git a/examples/nfc-poll.1 b/examples/nfc-poll.1 index 682c99c3..a34c88bc 100644 --- a/examples/nfc-poll.1 +++ b/examples/nfc-poll.1 @@ -42,7 +42,7 @@ Please report any bugs on the .B libnfc issue tracker at: .br -.BR http://code.google.com/p/libnfc/issues +.BR https://github.com/nfc-tools/libnfc/issues .SH LICENCE .B libnfc is licensed under the GNU Lesser General Public License (LGPL), version 3. diff --git a/examples/nfc-relay.1 b/examples/nfc-relay.1 index 1681d53c..f95b05f4 100644 --- a/examples/nfc-relay.1 +++ b/examples/nfc-relay.1 @@ -22,7 +22,7 @@ Please report any bugs on the .B libnfc issue tracker at: .br -.BR http://code.google.com/p/libnfc/issues +.BR https://github.com/nfc-tools/libnfc/issues .SH LICENCE .B libnfc is licensed under the GNU Lesser General Public License (LGPL), version 3. diff --git a/examples/pn53x-diagnose.1 b/examples/pn53x-diagnose.1 index 8487df4a..378e7aae 100644 --- a/examples/pn53x-diagnose.1 +++ b/examples/pn53x-diagnose.1 @@ -13,7 +13,7 @@ Please report any bugs on the .B libnfc issue tracker at: .br -.BR http://code.google.com/p/libnfc/issues +.BR https://github.com/nfc-tools/libnfc/issues .SH LICENCE .B libnfc is licensed under the GNU Lesser General Public License (LGPL), version 3. diff --git a/examples/pn53x-sam.1 b/examples/pn53x-sam.1 index 4c96d683..2f0b482d 100644 --- a/examples/pn53x-sam.1 +++ b/examples/pn53x-sam.1 @@ -19,7 +19,7 @@ Please report any bugs on the .B libnfc issue tracker at: .br -.BR http://code.google.com/p/libnfc/issues +.BR https://github.com/nfc-tools/libnfc/issues .SH LICENCE .B libnfc is licensed under the GNU Lesser General Public License (LGPL), version 3. diff --git a/examples/pn53x-tamashell.1 b/examples/pn53x-tamashell.1 index d2e4a3a9..d8c1ef14 100644 --- a/examples/pn53x-tamashell.1 +++ b/examples/pn53x-tamashell.1 @@ -68,7 +68,7 @@ Please report any bugs on the .B libnfc issue tracker at: .br -.BR http://code.google.com/p/libnfc/issues +.BR https://github.com/nfc-tools/libnfc/issues .SH LICENCE .B libnfc is licensed under the GNU Lesser General Public License (LGPL), version 3. diff --git a/utils/nfc-emulate-forum-tag4.1 b/utils/nfc-emulate-forum-tag4.1 index e289cdf8..4d896abb 100644 --- a/utils/nfc-emulate-forum-tag4.1 +++ b/utils/nfc-emulate-forum-tag4.1 @@ -46,7 +46,7 @@ bug, this problem is due to ACR122's internal MCU in front of NFC chip (PN532). Please report any bugs on the .Em libnfc issue tracker at: -.Em http://code.google.com/p/libnfc/issues +.Em https://github.com/nfc-tools/libnfc/issues .Sh LICENCE .Em libnfc is licensed under the GNU Lesser General Public License (LGPL), version 3. diff --git a/utils/nfc-jewel.1 b/utils/nfc-jewel.1 index c0431035..cb2c5d38 100644 --- a/utils/nfc-jewel.1 +++ b/utils/nfc-jewel.1 @@ -35,7 +35,7 @@ Please report any bugs on the .B libnfc issue tracker at: .br -.BR http://code.google.com/p/libnfc/issues +.BR https://github.com/nfc-tools/libnfc/issues .SH LICENCE .B libnfc is licensed under the GNU Lesser General Public License (LGPL), version 3. diff --git a/utils/nfc-list.1 b/utils/nfc-list.1 index 23591ed0..69eb12e1 100644 --- a/utils/nfc-list.1 +++ b/utils/nfc-list.1 @@ -53,7 +53,7 @@ Please report any bugs on the .B libnfc issue tracker at: .br -.BR http://code.google.com/p/libnfc/issues +.BR https://github.com/nfc-tools/libnfc/issues .SH LICENCE .B libnfc is licensed under the GNU Lesser General Public License (LGPL), version 3. diff --git a/utils/nfc-mfclassic.1 b/utils/nfc-mfclassic.1 index bfef5e3c..34083c6a 100644 --- a/utils/nfc-mfclassic.1 +++ b/utils/nfc-mfclassic.1 @@ -106,7 +106,7 @@ Please report any bugs on the .B libnfc issue tracker at: .br -.BR http://code.google.com/p/libnfc/issues +.BR https://github.com/nfc-tools/libnfc/issues .SH LICENCE .B libnfc is licensed under the GNU Lesser General Public License (LGPL), version 3. diff --git a/utils/nfc-mfultralight.1 b/utils/nfc-mfultralight.1 index dc78658f..6eea67b5 100644 --- a/utils/nfc-mfultralight.1 +++ b/utils/nfc-mfultralight.1 @@ -39,7 +39,7 @@ Please report any bugs on the .B libnfc issue tracker at: .br -.BR http://code.google.com/p/libnfc/issues +.BR https://github.com/nfc-tools/libnfc/issues .SH LICENCE .B libnfc is licensed under the GNU Lesser General Public License (LGPL), version 3. diff --git a/utils/nfc-read-forum-tag3.1 b/utils/nfc-read-forum-tag3.1 index 63a15367..366f5a7d 100644 --- a/utils/nfc-read-forum-tag3.1 +++ b/utils/nfc-read-forum-tag3.1 @@ -30,7 +30,7 @@ Please report any bugs on the .B libnfc issue tracker at: .br -.BR http://code.google.com/p/libnfc/issues +.BR https://github.com/nfc-tools/libnfc/issues .SH LICENCE .B libnfc is licensed under the GNU Lesser General Public License (LGPL), version 3. diff --git a/utils/nfc-relay-picc.1 b/utils/nfc-relay-picc.1 index a4a8be0b..f95db28f 100644 --- a/utils/nfc-relay-picc.1 +++ b/utils/nfc-relay-picc.1 @@ -65,7 +65,7 @@ Please report any bugs on the .B libnfc issue tracker at: .br -.BR http://code.google.com/p/libnfc/issues +.BR https://github.com/nfc-tools/libnfc/issues .SH LICENCE .B libnfc is licensed under the GNU Lesser General Public License (LGPL), version 3. diff --git a/utils/nfc-scan-device.1 b/utils/nfc-scan-device.1 index 347674ed..4b3c5508 100644 --- a/utils/nfc-scan-device.1 +++ b/utils/nfc-scan-device.1 @@ -39,7 +39,7 @@ Please report any bugs on the .B libnfc issue tracker at: .br -.BR http://code.google.com/p/libnfc/issues +.BR https://github.com/nfc-tools/libnfc/issues .SH LICENCE .B libnfc is licensed under the GNU Lesser General Public License (LGPL), version 3. From 33ce39ff7176b24417e4f99034c3a835e8ec0ad7 Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Thu, 30 Apr 2015 14:33:59 +0200 Subject: [PATCH 082/318] nfc-relay-picc: fix wrong open mode for file descriptor Fixes #280 --- utils/nfc-relay-picc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/nfc-relay-picc.c b/utils/nfc-relay-picc.c index 41f8c58e..802372b0 100644 --- a/utils/nfc-relay-picc.c +++ b/utils/nfc-relay-picc.c @@ -226,7 +226,7 @@ main(int argc, char *argv[]) nfc_exit(context); exit(EXIT_FAILURE); } - if ((fd4 = fdopen(4, "r")) == NULL) { + if ((fd4 = fdopen(4, "w")) == NULL) { ERR("Could not open file descriptor 4"); nfc_exit(context); exit(EXIT_FAILURE); From e96061e44bf8180e58717851bf79d15169d3e5c6 Mon Sep 17 00:00:00 2001 From: Dario Carluccio Date: Thu, 30 Apr 2015 14:45:05 +0200 Subject: [PATCH 083/318] nfc-mfsetuid: allow to write complete Block0, instead of only UID Fixes #282 --- examples/nfc-mfsetuid.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/examples/nfc-mfsetuid.c b/examples/nfc-mfsetuid.c index 91bf66e2..dd1e6483 100644 --- a/examples/nfc-mfsetuid.c +++ b/examples/nfc-mfsetuid.c @@ -10,6 +10,7 @@ * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: * Copyright (C) 2011 Adam Laurie + * Copyright (C) 2014 Dario Carluccio * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -140,12 +141,13 @@ transmit_bytes(const uint8_t *pbtTx, const size_t szTx) static void print_usage(char *argv[]) { - printf("Usage: %s [OPTIONS] [UID]\n", argv[0]); + printf("Usage: %s [OPTIONS] [UID|BLOCK0]\n", argv[0]); printf("Options:\n"); printf("\t-h\tHelp. Print this message.\n"); printf("\t-f\tFormat. Delete all data (set to 0xFF) and reset ACLs to default.\n"); printf("\t-q\tQuiet mode. Suppress output of READER and CARD data (improves timing).\n"); printf("\n\tSpecify UID (4 HEX bytes) to set UID, or leave blank for default '01234567'.\n"); + printf("\n\tSpecify BLOCK0 (16 HEX bytes) to set content of Block0. CRC (Byte 4) is recalculated an overwritten'.\n"); printf("\tThis utility can be used to recover cards that have been damaged by writing bad\n"); printf("\tdata (e.g. wrong BCC), thus making them non-selectable by most tools/readers.\n"); printf("\n\t*** Note: this utility only works with special Mifare 1K cards (Chinese clones).\n\n"); @@ -177,6 +179,14 @@ main(int argc, char *argv[]) } abtData[4] = abtData[0] ^ abtData[1] ^ abtData[2] ^ abtData[3]; iso14443a_crc_append(abtData, 16); + } else if (strlen(argv[arg]) == 32) { + for (i = 0 ; i < 16 ; ++i) { + memcpy(tmp, argv[arg] + i * 2, 2); + sscanf(tmp, "%02x", &c); + abtData[i] = (char) c; + } + abtData[4] = abtData[0] ^ abtData[1] ^ abtData[2] ^ abtData[3]; + iso14443a_crc_append(abtData, 16); } else { ERR("%s is not supported option.", argv[arg]); print_usage(argv); From ef74d81a8b24898cb686510b6fec76dcfdc149d2 Mon Sep 17 00:00:00 2001 From: xantares Date: Fri, 27 Jun 2014 20:37:50 +0200 Subject: [PATCH 084/318] Added config files --- CMakeLists.txt | 55 ++++++++++++++++++++++++++++++ cmake/LibNFCConfig.cmake.in | 34 ++++++++++++++++++ cmake/LibNFCConfigVersion.cmake.in | 31 +++++++++++++++++ cmake/UseLibNFC.cmake | 5 +++ 4 files changed, 125 insertions(+) create mode 100644 cmake/LibNFCConfig.cmake.in create mode 100644 cmake/LibNFCConfigVersion.cmake.in create mode 100644 cmake/UseLibNFC.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index d543b061..0b4aaa86 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -157,6 +157,61 @@ ADD_SUBDIRECTORY(include) ADD_SUBDIRECTORY(utils) ADD_SUBDIRECTORY(examples) +if (NOT MSVC) + # config script install path + if ( NOT DEFINED LIBNFC_CMAKE_CONFIG_DIR ) + set ( LIBNFC_CMAKE_CONFIG_DIR lib${LIB_SUFFIX}/cmake/libnfc ) + endif () + + set ( LIBNFC_INCLUDE_DIR ${includedir} ) + set ( LIBNFC_INCLUDE_DIRS ${LIBNFC_INCLUDE_DIR} ) + list ( APPEND LIBNFC_INCLUDE_DIRS ${LIBUSB_INCLUDE_DIRS} ) + set ( LIBNFC_LIBRARY nfc ) + set ( LIBNFC_LIBRARIES ${LIBNFC_LIBRARY} ) + list ( APPEND LIBNFC_LIBRARIES ${LIBUSB_LIBRARIES} ) + set ( LIBNFC_LIBRARY_DIRS ${libdir} ) + set ( LIBNFC_ROOT_DIR ${prefix} ) + set ( LIBNFC_VERSION_STRING ${VERSION} ) + set ( LIBNFC_VERSION_MAJOR ${VERSION_MAJOR} ) + set ( LIBNFC_VERSION_MINOR ${VERSION_MINOR} ) + set ( LIBNFC_VERSION_PATCH ${VERSION_PATCH} ) + + set ( LIBNFC_USE_FILE ${CMAKE_INSTALL_PREFIX}/${LIBNFC_CMAKE_CONFIG_DIR}/UseLibNFC.cmake ) + + + + if(CMAKE_VERSION VERSION_LESS 2.8.8) + configure_file ( cmake/LibNFCConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/LibNFCConfig.cmake @ONLY ) + configure_file ( cmake/LibNFCConfigVersion.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/LibNFCConfigVersion.cmake @ONLY ) + else () + include(CMakePackageConfigHelpers) + configure_package_config_file ( + cmake/LibNFCConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/LibNFCConfig.cmake + INSTALL_DESTINATION ${LIBNFC_CMAKE_CONFIG_DIR} + PATH_VARS + LIBNFC_USE_FILE + LIBNFC_ROOT_DIR + LIBNFC_INCLUDE_DIR + LIBNFC_INCLUDE_DIRS + LIBNFC_LIBRARY_DIRS + NO_CHECK_REQUIRED_COMPONENTS_MACRO + ) + write_basic_package_version_file ( + LibNFCConfigVersion.cmake + VERSION ${LIBNFC_VERSION_STRING} + COMPATIBILITY AnyNewerVersion + ) + endif () + + install ( FILES ${CMAKE_CURRENT_BINARY_DIR}/LibNFCConfig.cmake + ${CMAKE_CURRENT_BINARY_DIR}/LibNFCConfigVersion.cmake + cmake/UseLibNFC.cmake + DESTINATION ${LIBNFC_CMAKE_CONFIG_DIR} + ) + +endif () + # Binary Package IF(WIN32) SET(CPACK_GENERATOR "ZIP") diff --git a/cmake/LibNFCConfig.cmake.in b/cmake/LibNFCConfig.cmake.in new file mode 100644 index 00000000..c2375df1 --- /dev/null +++ b/cmake/LibNFCConfig.cmake.in @@ -0,0 +1,34 @@ +# -*- cmake -*- + + +# Use the following variables to compile and link against LibNFC: +# LIBNFC_FOUND - True if LibNFC was found on your system +# LIBNFC_USE_FILE - The file making LibNFC usable +# LIBNFC_DEFINITIONS - Definitions needed to build with LibNFC +# LIBNFC_INCLUDE_DIR - Directory where nfc/nfc.h can be found +# LIBNFC_INCLUDE_DIRS - List of directories of LibNFC and it's dependencies +# LIBNFC_LIBRARY - LibNFC library location +# LIBNFC_LIBRARIES - List of libraries to link against LibNFC library +# LIBNFC_LIBRARY_DIRS - List of directories containing LibNFC' libraries +# LIBNFC_ROOT_DIR - The base directory of LibNFC +# LIBNFC_VERSION_STRING - A human-readable string containing the version +# LIBNFC_VERSION_MAJOR - The major version of LibNFC +# LIBNFC_VERSION_MINOR - The minor version of LibNFC +# LIBNFC_VERSION_PATCH - The patch version of LibNFC + +set ( LIBNFC_FOUND 1 ) +set ( LIBNFC_USE_FILE "@LIBNFC_USE_FILE@" ) + +set ( LIBNFC_DEFINITIONS "@LIBNFC_DEFINITIONS@" ) +set ( LIBNFC_INCLUDE_DIR "@LIBNFC_INCLUDE_DIR@" ) +set ( LIBNFC_INCLUDE_DIRS "@LIBNFC_INCLUDE_DIRS@" ) +set ( LIBNFC_LIBRARY "@LIBNFC_LIBRARY@" ) +set ( LIBNFC_LIBRARIES "@LIBNFC_LIBRARIES@" ) +set ( LIBNFC_LIBRARY_DIRS "@LIBNFC_LIBRARY_DIRS@" ) +set ( LIBNFC_ROOT_DIR "@LIBNFC_ROOT_DIR@" ) + +set ( LIBNFC_VERSION_STRING "@LIBNFC_VERSION_STRING@" ) +set ( LIBNFC_VERSION_MAJOR "@LIBNFC_VERSION_MAJOR@" ) +set ( LIBNFC_VERSION_MINOR "@LIBNFC_VERSION_MINOR@" ) +set ( LIBNFC_VERSION_PATCH "@LIBNFC_VERSION_PATCH@" ) + diff --git a/cmake/LibNFCConfigVersion.cmake.in b/cmake/LibNFCConfigVersion.cmake.in new file mode 100644 index 00000000..dcbeaedc --- /dev/null +++ b/cmake/LibNFCConfigVersion.cmake.in @@ -0,0 +1,31 @@ +# This is a basic version file for the Config-mode of find_package(). +# It is used by write_basic_package_version_file() as input file for configure_file() +# to create a version-file which can be installed along a config.cmake file. +# +# The created file sets PACKAGE_VERSION_EXACT if the current version string and +# the requested version string are exactly the same and it sets +# PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version. +# The variable CVF_VERSION must be set before calling configure_file(). + +set(PACKAGE_VERSION "@LIBNFC_VERSION_STRING@") + +if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() + +# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: +if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "") + return() +endif() + +# check that the installed version has the same 32/64bit-ness as the one which is currently searching: +if(NOT "${CMAKE_SIZEOF_VOID_P}" STREQUAL "8") + math(EXPR installedBits "8 * 8") + set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") + set(PACKAGE_VERSION_UNSUITABLE TRUE) +endif() diff --git a/cmake/UseLibNFC.cmake b/cmake/UseLibNFC.cmake new file mode 100644 index 00000000..f31469ec --- /dev/null +++ b/cmake/UseLibNFC.cmake @@ -0,0 +1,5 @@ +# -*- cmake -*- + +add_definitions ( ${LIBNFC_DEFINITIONS} ) +include_directories ( ${LIBNFC_INCLUDE_DIRS} ) +link_directories ( ${LIBNFC_LIBRARY_DIRS} ) From 22078a8509d2dc2404201386015cbffa00ccfe00 Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Mon, 18 May 2015 20:08:33 +0200 Subject: [PATCH 085/318] Documentation: fix str_nfc_target() explanation --- libnfc/nfc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libnfc/nfc.c b/libnfc/nfc.c index a43d9daf..c7745040 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -1342,10 +1342,11 @@ str_nfc_modulation_type(const nfc_modulation_type nmt) } /** @ingroup string-converter - * @brief Convert \a nfc_modulation_type value to string + * @brief Convert \a nfc_target content to string * @return Upon successful return, this function returns the number of characters printed (excluding the null byte used to end output to strings), otherwise returns libnfc's error code (negative value) - * @param nt \a nfc_target struct to print + * @param pnt \a nfc_target struct pointer to print * @param buf pointer where string will be allocated, then nfc target information printed + * @param verbose false for essential, true for detailed, human-readable, information * * @warning *buf must be freed using nfc_free() */ From d028bc725d058e9db9d25340ea3f586526b718b9 Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Mon, 18 May 2015 20:14:18 +0200 Subject: [PATCH 086/318] Fix comparison when nfc_initiator_target_is_present() with a specified target --- libnfc/chips/pn53x.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 41142310..a5b69c89 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1059,6 +1059,7 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, size_t szTargetsData = sizeof(abtTargetsData); int res = 0; nfc_target nttmp; + memset(&nttmp, 0x00, sizeof(nfc_target)); if (nm.nmt == NMT_ISO14443BI || nm.nmt == NMT_ISO14443B2SR || nm.nmt == NMT_ISO14443B2CT) { if (CHIP_DATA(pnd)->type == RCS360) { @@ -1148,7 +1149,6 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, if (! found) return 0; } else { - const pn53x_modulation pm = pn53x_nm_to_pm(nm); if ((PM_UNDEFINED == pm) || (NBR_UNDEFINED == nm.nbr)) { pnd->last_error = NFC_EINVARG; @@ -1221,6 +1221,8 @@ pn53x_initiator_poll_target(struct nfc_device *pnd, szTargetTypes++; } nfc_target ntTargets[2]; + memset(ntTargets, 0x00, sizeof(nfc_target) * 2); + if ((res = pn53x_InAutoPoll(pnd, apttTargetTypes, szTargetTypes, uiPollNr, uiPeriod, ntTargets, 0)) < 0) return res; switch (res) { From af8fe86b0d5ab2da60c554f4c8c15c7d755df5ba Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Mon, 18 May 2015 20:26:23 +0200 Subject: [PATCH 087/318] Git: ignore generated files --- .gitignore | 82 ++++++++---------------------------------------------- 1 file changed, 11 insertions(+), 71 deletions(-) diff --git a/.gitignore b/.gitignore index 772b3649..3a497836 100644 --- a/.gitignore +++ b/.gitignore @@ -1,17 +1,18 @@ -*~ +**/.deps/ +**/.libs/ +**/Makefile +**/Makefile.in *.exe +*.la +*.lo +*.o +*~ Doxyfile INSTALL -Makefile -Makefile.in aclocal.m4 ar-lib autom4te.cache/ build -cmake/Makefile -cmake/Makefile.in -cmake/modules/Makefile -cmake/modules/Makefile.in compile config.guess config.h @@ -20,24 +21,8 @@ config.log config.status config.sub configure -contrib/Makefile -contrib/Makefile.in -contrib/devd/Makefile -contrib/devd/Makefile.in -contrib/udev/Makefile -contrib/udev/Makefile.in -contrib/win32/Makefile -contrib/win32/Makefile.in -contrib/win32/sys/Makefile -contrib/win32/sys/Makefile.in debian/ depcomp -examples/*.o -examples/.deps/ -examples/.libs/ -examples/Makefile -examples/Makefile.in -examples/doc/.deps/ examples/nfc-anticol examples/nfc-dep-initiator examples/nfc-dep-target @@ -50,44 +35,10 @@ examples/nfc-relay examples/pn53x-diagnose examples/pn53x-sam examples/pn53x-tamashell -examples/pn53x-tamashell-scripts/Makefile -examples/pn53x-tamashell-scripts/Makefile.in examples/quick_start_example1 examples/quick_start_example2 -include/Makefile -include/Makefile.in -include/nfc/Makefile -include/nfc/Makefile.in install-sh libnfc.pc -libnfc/*.lo -libnfc/*.o -libnfc/.deps/ -libnfc/.libs/ -libnfc/Makefile -libnfc/Makefile.in -libnfc/buses/*.la -libnfc/buses/*.lo -libnfc/buses/*.o -libnfc/buses/.deps/ -libnfc/buses/.libs/ -libnfc/buses/Makefile -libnfc/buses/Makefile.in -libnfc/chips/*.la -libnfc/chips/*.lo -libnfc/chips/*.o -libnfc/chips/.deps/ -libnfc/chips/.libs/ -libnfc/chips/Makefile -libnfc/chips/Makefile.in -libnfc/drivers/*.la -libnfc/drivers/*.lo -libnfc/drivers/*.o -libnfc/drivers/.deps/ -libnfc/drivers/.libs/ -libnfc/drivers/Makefile -libnfc/drivers/Makefile.in -libnfc/libnfc.la libtool ltmain.sh m4/libtool.m4 @@ -97,21 +48,10 @@ m4/ltversion.m4 m4/lt~obsolete.m4 missing stamp-h1 -test/*.la -test/*.lo -test/*.o -test/.deps/ -test/.libs/ -test/Makefile -test/Makefile.in test-driver -utils/*.la -utils/*.lo -utils/*.o -utils/.deps/ -utils/.libs/ -utils/Makefile -utils/Makefile.in +test/run-test.sh.log +test/run-test.sh.trs +test/test-suite.log utils/nfc-emulate-forum-tag4 utils/nfc-jewel utils/nfc-list From 11a4e3cd7f915d0054cd31827c0403faf4276641 Mon Sep 17 00:00:00 2001 From: Boris Moiseev Date: Mon, 25 May 2015 17:22:25 +0300 Subject: [PATCH 088/318] Fix nfc_initiator_poll_target without tag on PN532 When there is no tag on PN532 reader, the library incorrectly processed call result and returned NFC_ECHIP (chip error) instead of 0 (no targets found). --- libnfc/chips/pn53x.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index a5b69c89..e91b3bd7 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1226,6 +1226,9 @@ pn53x_initiator_poll_target(struct nfc_device *pnd, if ((res = pn53x_InAutoPoll(pnd, apttTargetTypes, szTargetTypes, uiPollNr, uiPeriod, ntTargets, 0)) < 0) return res; switch (res) { + case 0: + return pnd->last_error = NFC_SUCCESS; + break; case 1: *pnt = ntTargets[0]; if (pn53x_current_target_new(pnd, pnt) == NULL) { From 68094b4f6d9d9f68ded22ca8fd1ace56e6751885 Mon Sep 17 00:00:00 2001 From: Mati Vait Date: Wed, 27 May 2015 23:01:48 +0300 Subject: [PATCH 089/318] export iso14443b* symbol --- libnfc/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnfc/Makefile.am b/libnfc/Makefile.am index d7f3f7ef..dc3f27f2 100644 --- a/libnfc/Makefile.am +++ b/libnfc/Makefile.am @@ -22,7 +22,7 @@ libnfc_la_SOURCES = \ nfc-internal.h \ target-subr.h -libnfc_la_LDFLAGS = -no-undefined -version-info 5:1:0 -export-symbols-regex '^nfc_|^iso14443a_|^str_nfc_|pn53x_transceive|pn532_SAMConfiguration|pn53x_read_register|pn53x_write_register' +libnfc_la_LDFLAGS = -no-undefined -version-info 5:1:0 -export-symbols-regex '^nfc_|^iso14443a_|^iso14443b_|^str_nfc_|pn53x_transceive|pn532_SAMConfiguration|pn53x_read_register|pn53x_write_register' libnfc_la_CFLAGS = @DRIVERS_CFLAGS@ libnfc_la_LIBADD = \ $(top_builddir)/libnfc/chips/libnfcchips.la \ From 04a51df7967a4711b5779493aec39569e9d01195 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 8 Jun 2015 11:34:16 +0200 Subject: [PATCH 090/318] nfc_get_supported_baud_rate() proposal to reverse API cf issue #298 nfc_get_supported_baud_rate() would be the one for "initiator mode" and we add nfc_get_supported_baud_rate_target_mode() --- include/nfc/nfc.h | 3 ++- libnfc/chips/pn53x.c | 4 ++-- libnfc/nfc.c | 31 +++++++++++++++++++++++++------ 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/include/nfc/nfc.h b/include/nfc/nfc.h index 9e9e78cf..2f377e50 100644 --- a/include/nfc/nfc.h +++ b/include/nfc/nfc.h @@ -126,7 +126,8 @@ NFC_EXPORT int nfc_device_get_last_error(const nfc_device *pnd); NFC_EXPORT const char *nfc_device_get_name(nfc_device *pnd); NFC_EXPORT const char *nfc_device_get_connstring(nfc_device *pnd); NFC_EXPORT int nfc_device_get_supported_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type **const supported_mt); -NFC_EXPORT int nfc_device_get_supported_baud_rate(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br); +NFC_EXPORT int nfc_device_get_supported_baud_rate(nfc_device *pnd, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br); +NFC_EXPORT int nfc_device_get_supported_baud_rate_target_mode(nfc_device *pnd, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br); /* Properties accessors */ NFC_EXPORT int nfc_device_set_property_int(nfc_device *pnd, const nfc_property property, const int value); diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index e91b3bd7..4abfefc2 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -3366,7 +3366,7 @@ pn53x_get_information_about(nfc_device *pnd, char **pbuf) } buflen -= res; const nfc_baud_rate *nbr; - if ((res = nfc_device_get_supported_baud_rate(pnd, N_INITIATOR, nmt[i], &nbr)) < 0) { + if ((res = nfc_device_get_supported_baud_rate(pnd, nmt[i], &nbr)) < 0) { free(*pbuf); return res; } @@ -3431,7 +3431,7 @@ pn53x_get_information_about(nfc_device *pnd, char **pbuf) } buflen -= res; const nfc_baud_rate *nbr; - if ((res = nfc_device_get_supported_baud_rate(pnd, N_TARGET, nmt[i], &nbr)) < 0) { + if ((res = nfc_device_get_supported_baud_rate_target_mode(pnd, nmt[i], &nbr)) < 0) { free(*pbuf); return res; } diff --git a/libnfc/nfc.c b/libnfc/nfc.c index c7745040..114d5e87 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -1198,18 +1198,31 @@ nfc_device_get_supported_modulation(nfc_device *pnd, const nfc_mode mode, const } /** @ingroup data - * @brief Get supported baud rates. + * @brief Get supported baud rates (initiator mode). * @return Returns 0 on success, otherwise returns libnfc's error code (negative value) * @param pnd \a nfc_device struct pointer that represent currently used device - * @param mode \a nfc_mode. * @param nmt \a nfc_modulation_type. * @param supported_br pointer of \a nfc_baud_rate array. * */ int -nfc_device_get_supported_baud_rate(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br) +nfc_device_get_supported_baud_rate(nfc_device *pnd, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br) { - HAL(get_supported_baud_rate, pnd, mode, nmt, supported_br); + HAL(get_supported_baud_rate, pnd, N_INITIATOR, nmt, supported_br); +} + +/** @ingroup data + * @brief Get supported baud rates for target mode. + * @return Returns 0 on success, otherwise returns libnfc's error code (negative value) + * @param pnd \a nfc_device struct pointer that represent currently used device + * @param nmt \a nfc_modulation_type. + * @param supported_br pointer of \a nfc_baud_rate array. + * + */ +int +nfc_device_get_supported_baud_rate_target_mode(nfc_device *pnd, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br) +{ + HAL(get_supported_baud_rate, pnd, N_TARGET, nmt, supported_br); } /** @ingroup data @@ -1231,8 +1244,14 @@ nfc_device_validate_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_m for (int i = 0; nmt[i]; i++) { if (nmt[i] == nm->nmt) { const nfc_baud_rate *nbr; - if ((res = nfc_device_get_supported_baud_rate(pnd, mode, nmt[i], &nbr)) < 0) { - return res; + if (mode == N_INITIATOR) { + if ((res = nfc_device_get_supported_baud_rate(pnd, nmt[i], &nbr)) < 0) { + return res; + } + } else { + if ((res = nfc_device_get_supported_baud_rate_target_mode(pnd, nmt[i], &nbr)) < 0) { + return res; + } } for (int j = 0; nbr[j]; j++) { if (nbr[j] == nm->nbr) From 59f6c5de540c9ce841cd9754527cbebecaad4e37 Mon Sep 17 00:00:00 2001 From: xantares Date: Mon, 22 Jun 2015 20:47:04 +0200 Subject: [PATCH 091/318] fix drivers include ``` cc1: warning: /home/xantares/projects/libnfc/drivers: No such file or directory [-Wmissing-include-dirs] ``` --- cmake/modules/LibnfcDrivers.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/modules/LibnfcDrivers.cmake b/cmake/modules/LibnfcDrivers.cmake index 7a2a11d7..a79c2295 100644 --- a/cmake/modules/LibnfcDrivers.cmake +++ b/cmake/modules/LibnfcDrivers.cmake @@ -61,4 +61,4 @@ IF(LIBNFC_DRIVER_PN53X_USB) SET(USB_REQUIRED TRUE) ENDIF(LIBNFC_DRIVER_PN53X_USB) -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/drivers) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/libnfc/drivers) From 17ed36a7a54520e640849103f83fc1bc54e8c009 Mon Sep 17 00:00:00 2001 From: xaqq Date: Wed, 22 Jul 2015 15:47:36 +0200 Subject: [PATCH 092/318] Drop PCRE dependency. The config file is now manually parsed instead of using regex. While this is less beautifull, it allows us to drop PCRE as a dependency on Windows. --- CMakeLists.txt | 9 -- README-Windows.txt | 2 - cmake/FixBundle.cmake.in | 2 +- cmake/modules/FindPCRE.cmake | 42 ---------- cmake/modules/Makefile.am | 1 - libnfc/CMakeLists.txt | 13 --- libnfc/conf.c | 154 +++++++++++++++++++++++++++-------- 7 files changed, 122 insertions(+), 101 deletions(-) delete mode 100644 cmake/modules/FindPCRE.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b4aaa86..cf43cbe5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,15 +112,6 @@ IF(NOT WIN32) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libnfc.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) ENDIF(NOT WIN32) -# Require PCRE for Win32 -IF (WIN32) - FIND_PACKAGE(PCRE REQUIRED) - IF(PCRE_INCLUDE_DIRS) - INCLUDE_DIRECTORIES(${PCRE_INCLUDE_DIRS}) - LINK_DIRECTORIES(${PCRE_LIBRARY_DIRS}) - ENDIF(PCRE_INCLUDE_DIRS) -ENDIF(WIN32) - INCLUDE(LibnfcDrivers) IF(PCSC_INCLUDE_DIRS) diff --git a/README-Windows.txt b/README-Windows.txt index 06b9efc9..bf4ba69c 100644 --- a/README-Windows.txt +++ b/README-Windows.txt @@ -18,7 +18,6 @@ Requirements - MinGW-w64 compiler toolchain [1] - LibUsb-Win32 1.2.5.0 (or greater) [2] - CMake 2.8 [3] -- PCRE for Windows [4] This was tested on Windows 7 64 bit, but should work on Windows Vista and Windows XP and 32 bit as well. @@ -65,4 +64,3 @@ References http://sourceforge.net/projects/tdm-gcc/files/TDM-GCC%20Installer/tdm64-gcc-4.5.1.exe/download [2] http://sourceforge.net/projects/libusb-win32/files/ [3] http://www.cmake.org -[4] http://gnuwin32.sourceforge.net/packages/pcre.htm \ No newline at end of file diff --git a/cmake/FixBundle.cmake.in b/cmake/FixBundle.cmake.in index d11dc8fb..6e8f843d 100644 --- a/cmake/FixBundle.cmake.in +++ b/cmake/FixBundle.cmake.in @@ -6,6 +6,6 @@ SET(bundle "${CMAKE_INSTALL_PREFIX}/bin/nfc-list@CMAKE_EXECUTABLE_SUFFIX@") # set other_libs to a list of additional libs that cannot be reached by dependency analysis SET(other_libs "") -SET(dirs "@LIBUSB_LIBRARY_DIR@" "@PCRE_BIN_DIRS@") +SET(dirs "@LIBUSB_LIBRARY_DIR@") fixup_bundle("${bundle}" "${other_libs}" "${dirs}") diff --git a/cmake/modules/FindPCRE.cmake b/cmake/modules/FindPCRE.cmake deleted file mode 100644 index 3d043aa4..00000000 --- a/cmake/modules/FindPCRE.cmake +++ /dev/null @@ -1,42 +0,0 @@ -# This CMake script wants to use pcre functionality needed for windows -# compilation. However, since PCRE isn't really a default install location -# there isn't much to search. -# -# Operating Systems Supported: -# - Windows (requires MinGW) -# Tested with Windows XP/Windows 7 -# -# This should work for both 32 bit and 64 bit systems. -# -# Author: A. Lian -# - -IF(WIN32) - IF(NOT PCRE_FOUND) - FIND_PATH(PCRE_INCLUDE_DIRS regex.h) - FIND_LIBRARY(PCRE_LIBRARIES NAMES PCRE pcre) - FIND_PATH(PCRE_BIN_DIRS pcre3.dll) - - IF(PCRE_INCLUDE_DIRS AND PCRE_LIBRARIES AND PCRE_BIN_DIRS) - SET(PCRE_FOUND TRUE) - ENDIF(PCRE_INCLUDE_DIRS AND PCRE_LIBRARIES AND PCRE_BIN_DIRS) - ENDIF(NOT PCRE_FOUND) - - IF(PCRE_FOUND) - IF(NOT PCRE_FIND_QUIETLY) - MESSAGE(STATUS "Found PCRE: ${PCRE_LIBRARIES} ${PCRE_INCLUDE_DIRS} ${PCRE_BIN_DIRS}") - ENDIF (NOT PCRE_FIND_QUIETLY) - ELSE(PCRE_FOUND) - IF(PCRE_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find PCRE") - ENDIF(PCRE_FIND_REQUIRED) - ENDIF(PCRE_FOUND) - - INCLUDE(FindPackageHandleStandardArgs) - FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE DEFAULT_MSG - PCRE_LIBRARIES - PCRE_INCLUDE_DIRS - PCRE_BIN_DIRS - ) - -ENDIF(WIN32) diff --git a/cmake/modules/Makefile.am b/cmake/modules/Makefile.am index 55334caa..52fd92da 100644 --- a/cmake/modules/Makefile.am +++ b/cmake/modules/Makefile.am @@ -2,6 +2,5 @@ EXTRA_DIST = \ COPYING-CMAKE-SCRIPTS \ FindLIBUSB.cmake \ FindPCSC.cmake \ - FindPCRE.cmake \ UseDoxygen.cmake \ LibnfcDrivers.cmake diff --git a/libnfc/CMakeLists.txt b/libnfc/CMakeLists.txt index 7a51bb0d..d4a4ec12 100644 --- a/libnfc/CMakeLists.txt +++ b/libnfc/CMakeLists.txt @@ -47,16 +47,6 @@ ENDIF(SPI_REQUIRED) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/buses) -IF(WIN32) - # Windows now requires regex, so we utilize PCRE - # since Windows doesn't get the benefit of finding in CMake - # it has to be added manually - IF(PCRE_FOUND) - INCLUDE_DIRECTORIES(${PCRE_INCLUDE_DIRS}) - LINK_DIRECTORIES(${PCRE_LIBRARY_DIRS}) - ENDIF(PCRE_FOUND) -ENDIF(WIN32) - IF(PCSC_FOUND) INCLUDE_DIRECTORIES(${PCSC_INCLUDE_DIRS}) LINK_DIRECTORIES(${PCSC_LIBRARY_DIRS}) @@ -94,9 +84,6 @@ SET_TARGET_PROPERTIES(nfc PROPERTIES SOVERSION 5 VERSION 5.0.1) IF(WIN32) # Libraries that are windows specific TARGET_LINK_LIBRARIES(nfc wsock32) - IF(PCRE_FOUND) - TARGET_LINK_LIBRARIES(nfc ${PCRE_LIBRARIES}) - ENDIF(PCRE_FOUND) ADD_CUSTOM_COMMAND( OUTPUT libnfc.lib diff --git a/libnfc/conf.c b/libnfc/conf.c index 47b2d031..981e272e 100644 --- a/libnfc/conf.c +++ b/libnfc/conf.c @@ -33,9 +33,9 @@ #ifdef CONFFILES #include #include +#include #include #include -#include #include #include @@ -56,8 +56,122 @@ #define LIBNFC_CONFFILE LIBNFC_SYSCONFDIR"/libnfc.conf" #define LIBNFC_DEVICECONFDIR LIBNFC_SYSCONFDIR"/devices.d" +static int +escaped_value(const char line[BUFSIZ], int i, char **value) +{ + if (line[i] != '"') + goto FAIL; + i++; + if (line[i] == 0 || line[i] == '\n') + goto FAIL; + int c = 0; + while (line[i] && line[i] != '"') { + i++; + c++; + } + if (line[i] != '"') + goto FAIL; + *value = malloc(c + 1); + if (!*value) + goto FAIL; + memset(*value, 0, c + 1); + memcpy(*value, &line[i - c], c); + i++; + while (line[i] && isspace(line[i])) + i++; + if (line[i] != 0 && line[i] != '\n') + goto FAIL; + return 0; + +FAIL: + free(*value); + *value = NULL; + return -1; +} + +static int +non_escaped_value(const char line[BUFSIZ], int i, char **value) +{ + int c = 0; + while (line[i] && !isspace(line[i])) { + i++; + c++; + } + *value = malloc(c + 1); + if (!*value) + goto FAIL; + memset(*value, 0, c + 1); + memcpy(*value, &line[i - c], c); + i++; + while (line[i] && isspace(line[i])) + i++; + if (line[i] != 0) + goto FAIL; + return 0; + +FAIL: + free(*value); + *value = NULL; + return -1; +} + +static int +parse_line(const char line[BUFSIZ], char **key, char **value) +{ + *key = NULL; + *value = NULL; + int i = 0; + int c = 0; + + // optional initial spaces + while (isspace(line[i])) + i++; + if (line[i] == 0 || line[i] == '\n') + return -1; + + // key + while (isalnum(line[i]) || line[i] == '_' || line[i] == '.') { + i++; + c++; + } + if (c == 0 || line[i] == 0 || line[i] == '\n') // key is empty + return -1; + *key = malloc(c + 1); + if (!*key) + return -1; + memset(*key, 0, c + 1); + memcpy(*key, &line[i - c], c); + + // space before '=' + while (isspace(line[i])) + i++; + if (line[i] != '=') + return -1; + i++; + if (line[i] == 0 || line[i] == '\n') + return -1; + // space after '=' + while (isspace(line[i])) + i++; + if (line[i] == 0 || line[i] == '\n') + return -1; + if (escaped_value(line, i, value) == 0) + return 0; + else if (non_escaped_value(line, i, value) == 0) + return 0; + + // Extracting key or value failed + free(*key); + *key = NULL; + free(*value); + *value = NULL; + return -1; +} + static bool -conf_parse_file(const char *filename, void (*conf_keyvalue)(void *data, const char *key, const char *value), void *data) +conf_parse_file(const char *filename, + void (*conf_keyvalue)(void *data, const char *key, const char *value), + void *data) { FILE *f = fopen(filename, "r"); if (!f) { @@ -65,21 +179,6 @@ conf_parse_file(const char *filename, void (*conf_keyvalue)(void *data, const ch return false; } char line[BUFSIZ]; - const char *str_regex = "^[[:space:]]*([[:alnum:]_.]+)[[:space:]]*=[[:space:]]*(\"(.+)\"|([^[:space:]]+))[[:space:]]*$"; - regex_t preg; - if (regcomp(&preg, str_regex, REG_EXTENDED | REG_NOTEOL) != 0) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Regular expression used for configuration file parsing is not valid."); - fclose(f); - return false; - } - size_t nmatch = preg.re_nsub + 1; - regmatch_t *pmatch = malloc(sizeof(*pmatch) * nmatch); - if (!pmatch) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Not enough memory: malloc failed."); - regfree(&preg); - fclose(f); - return false; - } int lineno = 0; while (fgets(line, BUFSIZ, f) != NULL) { @@ -89,29 +188,18 @@ conf_parse_file(const char *filename, void (*conf_keyvalue)(void *data, const ch case '\n': break; default: { - int match; - if ((match = regexec(&preg, line, nmatch, pmatch, 0)) == 0) { - const size_t key_size = pmatch[1].rm_eo - pmatch[1].rm_so; - const off_t value_pmatch = pmatch[3].rm_eo != -1 ? 3 : 4; - const size_t value_size = pmatch[value_pmatch].rm_eo - pmatch[value_pmatch].rm_so; - char key[key_size + 1]; - char value[value_size + 1]; - strncpy(key, line + (pmatch[1].rm_so), key_size); - key[key_size] = '\0'; - strncpy(value, line + (pmatch[value_pmatch].rm_so), value_size); - value[value_size] = '\0'; + char *key; + char *value; + if (parse_line(line, &key, &value) == 0) { conf_keyvalue(data, key, value); + free(key); + free(value); } else { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Parse error on line #%d: %s", lineno, line); } } - break; } } - - free(pmatch); - regfree(&preg); - fclose(f); return false; } From 7ae5a0c3330b91d9d4eec32252a750fcb71e36a4 Mon Sep 17 00:00:00 2001 From: Julien Ehrhart Date: Sun, 2 Aug 2015 16:16:19 +0000 Subject: [PATCH 093/318] Fix nfc-poll card removing check (should be done only if a target has been found). --- examples/nfc-poll.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/examples/nfc-poll.c b/examples/nfc-poll.c index a42c41a3..fde8ea86 100644 --- a/examples/nfc-poll.c +++ b/examples/nfc-poll.c @@ -145,15 +145,14 @@ main(int argc, const char *argv[]) if (res > 0) { print_nfc_target(&nt, verbose); + printf("Waiting for card removing..."); + while (0 == nfc_initiator_target_is_present(pnd, NULL)) {} + nfc_perror(pnd, "nfc_initiator_target_is_present"); + printf("done.\n"); } else { printf("No target found.\n"); } - printf("Waiting for card removing..."); - while (0 == nfc_initiator_target_is_present(pnd, NULL)) {} - nfc_perror(pnd, "nfc_initiator_target_is_present"); - printf("done.\n"); - nfc_close(pnd); nfc_exit(context); exit(EXIT_SUCCESS); From e72fe468a46be9b209a30d15af91d2e76018d697 Mon Sep 17 00:00:00 2001 From: Ray Lee Date: Sun, 16 Aug 2015 16:34:35 +0800 Subject: [PATCH 094/318] Bugfix:function setenv()and unsetenv() The original setenv() and unsetenv() function is invalid,I have rewrited to fix. --- contrib/win32/stdlib.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/contrib/win32/stdlib.c b/contrib/win32/stdlib.c index 95e3a1d2..fc27042a 100644 --- a/contrib/win32/stdlib.c +++ b/contrib/win32/stdlib.c @@ -34,21 +34,24 @@ // Handle platform specific includes #include "contrib/windows.h" +//There is no setenv()and unsetenv() in windows,but we can use putenv() instead. int setenv(const char *name, const char *value, int overwrite) { - int exists = GetEnvironmentVariableA(name, NULL, 0); - if ((exists && overwrite) || (!exists)) { - if (!SetEnvironmentVariableA(name, value)) { - // Set errno here correctly - return -1; - } - return 0; + char* env = getenv(name); + if ((env && overwrite) || (!env)) { + char* str[32]; + strcpy(str,name); + strcat(str,"="); + strcat(str,value); + return putenv(str); } - // Exists and overwrite is 0. return -1; } void unsetenv(const char *name) { - SetEnvironmentVariableA(name, NULL); + char* str[32]; + strcpy(str,name); + strcat(str,"="); + putenv(str); } From 09ce2233ce6e4bec5c03ae8b5fcef500a45143d6 Mon Sep 17 00:00:00 2001 From: Ray Lee Date: Sun, 16 Aug 2015 18:22:15 +0800 Subject: [PATCH 095/318] Bugfix:Set variable "prefix" for WIN32 --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index cf43cbe5..736cf8d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -136,6 +136,7 @@ IF(WIN32) GET_CURRENT_YEAR(CURRENT_YEAR) MESSAGE("Year for copyright is " ${CURRENT_YEAR}) + SET(prefix ${CMAKE_INSTALL_PREFIX}) SET(RC_COMMENT "${PACKAGE_NAME} library") SET(RC_INTERNAL_NAME "${PACKAGE_NAME} ${WIN32_MODE}") SET(RC_ORIGINAL_NAME ${PACKAGE_NAME}.dll) From 13fee61e87460faa4535071cdd718544e4170435 Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Wed, 19 Aug 2015 11:44:23 +0200 Subject: [PATCH 096/318] Fix typo Closes #309 --- contrib/win32/nfc.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/win32/nfc.def b/contrib/win32/nfc.def index efee4757..085b2f71 100644 --- a/contrib/win32/nfc.def +++ b/contrib/win32/nfc.def @@ -6,7 +6,7 @@ EXPORTS nfc_exit nfc_open nfc_close - nfc_abbort_command + nfc_abort_command nfc_list_devices nfc_idle nfc_initiator_init From 792e3d9cbdd6d743977f633ad38bc63c8d93882f Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Wed, 19 Aug 2015 11:47:22 +0200 Subject: [PATCH 097/318] Do not include extra header in nfc.h Fixes #310 --- include/nfc/nfc.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/nfc/nfc.h b/include/nfc/nfc.h index 2f377e50..4ebc6ff9 100644 --- a/include/nfc/nfc.h +++ b/include/nfc/nfc.h @@ -34,8 +34,6 @@ #ifndef _LIBNFC_H_ # define _LIBNFC_H_ -# include - # include # include From 555f9ce4cfb892939cb3ef7a2a1af4c7cdd6c1ae Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Wed, 19 Aug 2015 11:50:52 +0200 Subject: [PATCH 098/318] Fixes #286: udev rule was executed to early --- contrib/udev/{42-pn53x.rules => 93-pn53x.rules} | 0 contrib/udev/Makefile.am | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename contrib/udev/{42-pn53x.rules => 93-pn53x.rules} (100%) diff --git a/contrib/udev/42-pn53x.rules b/contrib/udev/93-pn53x.rules similarity index 100% rename from contrib/udev/42-pn53x.rules rename to contrib/udev/93-pn53x.rules diff --git a/contrib/udev/Makefile.am b/contrib/udev/Makefile.am index 86655ae3..6f8fe456 100644 --- a/contrib/udev/Makefile.am +++ b/contrib/udev/Makefile.am @@ -1,2 +1,2 @@ EXTRA_DIST = \ - 42-pn53x.rules + 93-pn53x.rules From 5d2052e77fb21d1c948a4e9be7b2bd44033aa9dd Mon Sep 17 00:00:00 2001 From: xantares Date: Tue, 1 Sep 2015 08:55:53 +0200 Subject: [PATCH 099/318] set default cmake build type --- CMakeLists.txt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cf43cbe5..b6514e18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,11 @@ -PROJECT(libnfc C) -CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +cmake_minimum_required (VERSION 2.6) + +if (NOT DEFINED CMAKE_BUILD_TYPE) + set (CMAKE_BUILD_TYPE Release CACHE STRING "Build type") +endif () + +project (libnfc C) + SET(VERSION_MAJOR "1") SET(VERSION_MINOR "7") SET(VERSION_PATCH "1") From 141e99959e51ec71eacedde8b90b200907966d3f Mon Sep 17 00:00:00 2001 From: xantares Date: Tue, 1 Sep 2015 08:57:11 +0200 Subject: [PATCH 100/318] use options --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cf43cbe5..b4d3a38c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,12 +29,12 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/incl SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/") # Options -SET(LIBNFC_LOG ON CACHE BOOL "Enable log facility (errors, warning, info and debug messages)") +option (LIBNFC_LOG "Enable log facility (errors, warning, info and debug messages)" ON) IF(LIBNFC_LOG) ADD_DEFINITIONS(-DLOG) ENDIF(LIBNFC_LOG) -SET(LIBNFC_ENVVARS ON CACHE BOOL "Enable envvars facility") +option (LIBNFC_ENVVARS "Enable envvars facility" ON) IF(LIBNFC_ENVVARS) ADD_DEFINITIONS(-DENVVARS) ENDIF(LIBNFC_ENVVARS) @@ -49,7 +49,7 @@ ELSE(LIBNFC_DEBUG_MODE) SET(WIN32_MODE "release") ENDIF(LIBNFC_DEBUG_MODE) -SET(LIBNFC_CONFFILES_MODE ON CACHE BOOL "Enable configuration files") +option (LIBNFC_CONFFILES_MODE "Enable configuration files" ON) IF(LIBNFC_CONFFILES_MODE) ADD_DEFINITIONS(-DCONFFILES) ENDIF(LIBNFC_CONFFILES_MODE) From b7f620fdab1bb124d34f7ddf1d1c842486bd950c Mon Sep 17 00:00:00 2001 From: xantares Date: Tue, 1 Sep 2015 08:58:35 +0200 Subject: [PATCH 101/318] options to disable samples --- CMakeLists.txt | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cf43cbe5..40341f2f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,6 +54,10 @@ IF(LIBNFC_CONFFILES_MODE) ADD_DEFINITIONS(-DCONFFILES) ENDIF(LIBNFC_CONFFILES_MODE) +option (BUILD_EXAMPLES "build examples ON/OFF" ON) +option (BUILD_UTILS "build utils ON/OFF" ON) + + # Doxygen SET(builddir "${CMAKE_BINARY_DIR}") SET(top_srcdir "${CMAKE_SOURCE_DIR}") @@ -145,8 +149,14 @@ ENDIF(WIN32) ADD_SUBDIRECTORY(libnfc) ADD_SUBDIRECTORY(include) -ADD_SUBDIRECTORY(utils) -ADD_SUBDIRECTORY(examples) + +if (BUILD_UTILS) + add_subdirectory (utils) +endif () + +if (BUILD_EXAMPLES) + add_subdirectory (examples) +endif () if (NOT MSVC) # config script install path From e7feb6587d59adcea89c67ace466cc00e7805f5a Mon Sep 17 00:00:00 2001 From: xantares Date: Tue, 1 Sep 2015 09:33:06 +0200 Subject: [PATCH 102/318] Add travis config file --- .travis.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..108298f1 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,17 @@ +language: cpp + +addons: + apt: + packages: + - libusb-dev + - doxygen + - cmake + - libcutter-dev + +script: + - autoreconf -vfi + - ./configure --prefix=$HOME/.local/ + - make -j2 + - make install + - cmake -DCMAKE_INSTALL_PREFIX=~/.local . + - make install -j2 From 87c6053d6feb5ea4c90b25585e410a0724dfbbe6 Mon Sep 17 00:00:00 2001 From: quantum-x Date: Tue, 3 Nov 2015 18:11:51 +0100 Subject: [PATCH 103/318] Updating nfc-mfclassic.c Modifying behavior relating to magic cards. If a user has a 'magic2' card (IE, direct-write, not a 'fully magic' card) - we'll warn them that they don't need to use the W / R modes, and then proceed with the unlock operation, instead of exiting. --- utils/nfc-mfclassic.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 55809fc9..4ddc4a3d 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -233,11 +233,6 @@ authenticate(uint32_t uiBlock) static bool unlock_card(void) { - if (magic2) { - printf("Don't use R/W with this card, this is not required!\n"); - return false; - } - // Configure the CRC if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) { nfc_perror(pnd, "nfc_configure"); @@ -314,9 +309,17 @@ read_card(int read_unlocked) bool bFailure = false; uint32_t uiReadBlocks = 0; - if (read_unlocked) - if (!unlock_card()) - return false; + if (read_unlocke) { + //If the user is attempting an unlocked read, but has a direct-write type magic card, they don't + //need to use the R mode. We'll trigger a warning and let them proceed. + if (magic2) { + printf("Note: This card does not require an unlocked write (R) \n"); + } else { + //If User has requested an unlocked read, but we're unable to unlock the card, we'll error out. + if (!unlock_card()) { + return false; + } + } printf("Reading out %d blocks |", uiBlocks + 1); // Read the card from end to begin @@ -384,9 +387,17 @@ write_card(int write_block_zero) bool bFailure = false; uint32_t uiWriteBlocks = 0; - if (write_block_zero) - if (!unlock_card()) - return false; + 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. + if (magic2) { + printf("Note: This card does not require an unlocked write (W) \n"); + } else { + //If User has requested an unlocked write, but we're unable to unlock the card, we'll error out. + if (!unlock_card()) { + return false; + } + } printf("Writing %d blocks |", uiBlocks + 1); // Write the card from begin to end; From b5684c1755d48dae170f4f454bd9b95a5021879f Mon Sep 17 00:00:00 2001 From: quantum-x Date: Tue, 3 Nov 2015 18:33:53 +0100 Subject: [PATCH 104/318] Removing typo Removing typo --- utils/nfc-mfclassic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 4ddc4a3d..31ad2a65 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -309,7 +309,7 @@ read_card(int read_unlocked) bool bFailure = false; uint32_t uiReadBlocks = 0; - if (read_unlocke) { + if (read_unlocked) { //If the user is attempting an unlocked read, but has a direct-write type magic card, they don't //need to use the R mode. We'll trigger a warning and let them proceed. if (magic2) { From 20f22b97e7a5de12fdc8f3f21eb880cda6635dff Mon Sep 17 00:00:00 2001 From: quantum-x Date: Tue, 3 Nov 2015 18:39:03 +0100 Subject: [PATCH 105/318] Updating nesting typo --- utils/nfc-mfclassic.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 31ad2a65..86112f79 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -318,9 +318,10 @@ read_card(int read_unlocked) //If User has requested an unlocked read, but we're unable to unlock the card, we'll error out. if (!unlock_card()) { return false; + } } } - + printf("Reading out %d blocks |", uiBlocks + 1); // Read the card from end to begin for (iBlock = uiBlocks; iBlock >= 0; iBlock--) { @@ -396,9 +397,10 @@ write_card(int write_block_zero) //If User has requested an unlocked write, but we're unable to unlock the card, we'll error out. if (!unlock_card()) { return false; + } } } - + printf("Writing %d blocks |", uiBlocks + 1); // Write the card from begin to end; for (uiBlock = 0; uiBlock <= uiBlocks; uiBlock++) { From c71d7267ac12f50b5177381494fdca40ef68a154 Mon Sep 17 00:00:00 2001 From: quantum-x Date: Tue, 3 Nov 2015 18:48:22 +0100 Subject: [PATCH 106/318] Update nfc-mfclassic.c Tweaking back the unlocked_read / write_block_zero after magic2 card discovered --- utils/nfc-mfclassic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 86112f79..7ecdfa71 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -314,6 +314,7 @@ read_card(int read_unlocked) //need to use the R mode. We'll trigger a warning and let them proceed. if (magic2) { printf("Note: This card does not require an unlocked write (R) \n"); + read_unlocked = 0; } else { //If User has requested an unlocked read, but we're unable to unlock the card, we'll error out. if (!unlock_card()) { @@ -393,6 +394,7 @@ write_card(int write_block_zero) //need to use the W mode. We'll trigger a warning and let them proceed. if (magic2) { printf("Note: This card does not require an unlocked write (W) \n"); + write_block_zero = 0 } else { //If User has requested an unlocked write, but we're unable to unlock the card, we'll error out. if (!unlock_card()) { From 758cb0cc05ef976acf73c866db131caa36dc00e2 Mon Sep 17 00:00:00 2001 From: quantum-x Date: Tue, 3 Nov 2015 18:52:39 +0100 Subject: [PATCH 107/318] Update nfc-mfclassic.c --- utils/nfc-mfclassic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 7ecdfa71..333f7104 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -394,7 +394,7 @@ write_card(int write_block_zero) //need to use the W mode. We'll trigger a warning and let them proceed. if (magic2) { printf("Note: This card does not require an unlocked write (W) \n"); - write_block_zero = 0 + write_block_zero = 0; } else { //If User has requested an unlocked write, but we're unable to unlock the card, we'll error out. if (!unlock_card()) { From 1d4720671e07ba660a03b1025689341bb615b58f Mon Sep 17 00:00:00 2001 From: bhack Date: Wed, 4 Nov 2015 20:15:56 +0100 Subject: [PATCH 108/318] Add SCM_SCL3712 support --- contrib/udev/93-pn53x.rules | 1 + libnfc/drivers/pn53x_usb.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/contrib/udev/93-pn53x.rules b/contrib/udev/93-pn53x.rules index 3118b4b1..99058af5 100644 --- a/contrib/udev/93-pn53x.rules +++ b/contrib/udev/93-pn53x.rules @@ -11,6 +11,7 @@ ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0193", MODE="0664", GROUP="plugdev" # PN533 ATTRS{idVendor}=="04cc", ATTRS{idProduct}=="2533", MODE="0664", GROUP="plugdev" ATTRS{idVendor}=="04e6", ATTRS{idProduct}=="5591", MODE="0664", GROUP="plugdev" +ATTRS{idVendor}=="04e6", ATTRS{idProduct}=="5594", MODE="0664", GROUP="plugdev" ATTRS{idVendor}=="1fd3", ATTRS{idProduct}=="0608", MODE="0664", GROUP="plugdev" ATTRS{idVendor}=="054c", ATTRS{idProduct}=="02e1", MODE="0664", GROUP="plugdev" diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index b4dbe89a..d0c9adf1 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -69,6 +69,7 @@ typedef enum { NXP_PN533, ASK_LOGO, SCM_SCL3711, + SCM_SCL3712, SONY_RCS360 } pn53x_usb_model; @@ -129,6 +130,7 @@ const struct pn53x_usb_supported_device pn53x_usb_supported_devices[] = { { 0x04CC, 0x0531, NXP_PN531, "Philips / PN531" }, { 0x04CC, 0x2533, NXP_PN533, "NXP / PN533" }, { 0x04E6, 0x5591, SCM_SCL3711, "SCM Micro / SCL3711-NFC&RW" }, + { 0x04E6, 0x5594, SCM_SCL3712, "SCM Micro / SCL3712-NFC&RW" }, { 0x054c, 0x0193, SONY_PN531, "Sony / PN531" }, { 0x1FD3, 0x0608, ASK_LOGO, "ASK / LoGO" }, { 0x054C, 0x02E1, SONY_RCS360, "Sony / FeliCa S360 [PaSoRi]" } @@ -354,6 +356,7 @@ pn53x_usb_open(const nfc_context *context, const nfc_connstring connstring) CHIP_DATA(pnd)->timer_correction = 50; break; case SCM_SCL3711: + case SCM_SCL3712: case NXP_PN533: CHIP_DATA(pnd)->timer_correction = 46; break; @@ -693,6 +696,13 @@ pn53x_usb_set_property_bool(nfc_device *pnd, const nfc_property property, const return res; } break; + case SCM_SCL3712: + if (NP_ACTIVATE_FIELD == property) { + // Switch on/off LED according to ACTIVATE_FIELD option + if ((res = pn53x_write_register(pnd, PN53X_SFR_P3, _BV(P32), bEnable ? 0 : _BV(P32))) < 0) + return res; + } + break; case NXP_PN531: case NXP_PN533: case SONY_PN531: From 3aa2d46588a82c4232bb0e19c21666ff76191a80 Mon Sep 17 00:00:00 2001 From: Simon Yorkston Date: Wed, 18 Nov 2015 08:56:48 +0100 Subject: [PATCH 109/318] Added automatic mode to nfc-mfultralight --- utils/nfc-mfultralight.c | 93 +++++++++++++++++++++++++++++----------- 1 file changed, 67 insertions(+), 26 deletions(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 31d6b82d..2f065d02 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -101,14 +101,14 @@ read_card(void) print_success_or_failure(bFailure, &uiReadedPages); } printf("|\n"); - printf("Done, %d of %d pages readed.\n", uiReadedPages, uiBlocks + 1); + printf("Done, %d of %d pages read.\n", uiReadedPages, uiBlocks + 1); fflush(stdout); return (!bFailure); } static bool -write_card(void) +write_card(bool write_otp, bool write_lock, bool write_uid) { uint32_t uiBlock = 0; bool bFailure = false; @@ -116,25 +116,30 @@ write_card(void) uint32_t uiSkippedPages = 0; char buffer[BUFSIZ]; - bool write_otp; - bool write_lock; - bool write_uid; - printf("Write OTP bytes ? [yN] "); - if (!fgets(buffer, BUFSIZ, stdin)) { - ERR("Unable to read standard input."); + if (!write_otp) { + printf("Write OTP bytes ? [yN] "); + if (!fgets(buffer, BUFSIZ, stdin)) { + ERR("Unable to read standard input."); + } + write_otp = ((buffer[0] == 'y') || (buffer[0] == 'Y')); } - write_otp = ((buffer[0] == 'y') || (buffer[0] == 'Y')); - printf("Write Lock bytes ? [yN] "); - if (!fgets(buffer, BUFSIZ, stdin)) { - ERR("Unable to read standard input."); + + if (!write_lock) { + printf("Write Lock bytes ? [yN] "); + if (!fgets(buffer, BUFSIZ, stdin)) { + ERR("Unable to read standard input."); + } + write_lock = ((buffer[0] == 'y') || (buffer[0] == 'Y')); } - write_lock = ((buffer[0] == 'y') || (buffer[0] == 'Y')); - printf("Write UID bytes (only for special writeable UID cards) ? [yN] "); - if (!fgets(buffer, BUFSIZ, stdin)) { - ERR("Unable to read standard input."); + + if (!write_uid) { + printf("Write UID bytes (only for special writeable UID cards) ? [yN] "); + if (!fgets(buffer, BUFSIZ, stdin)) { + ERR("Unable to read standard input."); + } + write_uid = ((buffer[0] == 'y') || (buffer[0] == 'Y')); } - write_uid = ((buffer[0] == 'y') || (buffer[0] == 'Y')); printf("Writing %d pages |", uiBlocks + 1); /* We may need to skip 2 first pages. */ @@ -181,25 +186,61 @@ write_card(void) return true; } +static void +print_usage(const char *argv[]) +{ + printf("Usage: %s r|w [OPTIONS]\n", argv[0]); + printf("Options:\n"); + printf("\tr|w\t\t - Perform read or write\n"); + printf("\t\t - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n"); + printf("\t--otp\t\t - Don't prompt for OTP writing (Assume yes)\n"); + printf("\t--lock\t\t - Don't prompt for Lockbit writing (Assume yes)\n"); + printf("\t--uid\t\t - Don't prompt for UID writing (Assume yes)\n"); + printf("\t--full\t\t - Assume full card write (UID + OTP + Lockbit)\n"); +} + int main(int argc, const char *argv[]) { bool bReadAction; + bool bOTP; + bool bLock; + bool bUID; FILE *pfDump; if (argc < 3) { - printf("\n"); - printf("%s r|w \n", argv[0]); - printf("\n"); - printf("r|w - Perform read from or write to card\n"); - printf(" - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n"); - printf("\n"); - exit(EXIT_FAILURE); + print_usage(argv); + exit(EXIT_FAILURE); } DBG("\nChecking arguments and settings\n"); - bReadAction = tolower((int)((unsigned char) * (argv[1])) == 'r'); + // Get commandline options + for (int arg = 1; arg < argc; arg++) { + if (0 == strcmp(argv[arg], "r")) { + bReadAction = true; + } else if (0 == strcmp(argv[arg], "w")) { + bReadAction = false; + } else if (0 == strcmp(argv[arg], "--full")) { + bOTP = true; + bLock = true; + bUID = true; + } else if (0 == strcmp(argv[arg], "--otp")) { + bOTP = true; + } else if (0 == strcmp(argv[arg], "--lock")) { + bLock = true; + } else if (0 == strcmp(argv[arg], "--uid")) { + bUID = true; + } else { + //Skip validation of the filename + if (arg != 2) { + ERR("%s is not supported option.", argv[arg]); + print_usage(argv); + exit(EXIT_FAILURE); + } + } + } + if (bReadAction) { memset(&mtDump, 0x00, sizeof(mtDump)); @@ -297,7 +338,7 @@ main(int argc, const char *argv[]) printf("Done.\n"); } } else { - write_card(); + write_card(bOTP, bLock, bUID); } nfc_close(pnd); From 0cece94778a9594e3df5c1696dd5d1b37b7be013 Mon Sep 17 00:00:00 2001 From: Simon Yorkston Date: Wed, 18 Nov 2015 23:03:36 +0100 Subject: [PATCH 110/318] Adds --check-magic flag to nfc-mfultralight --- utils/nfc-mfultralight.c | 78 ++++++++++++++++++++++++++++++++-------- 1 file changed, 64 insertions(+), 14 deletions(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 2f065d02..3fab03e9 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -107,6 +107,43 @@ read_card(void) return (!bFailure); } +static bool check_magic() { + bool bFailure = false; + int uid_data; + + 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 + if (nfc_initiator_mifare_cmd(pnd, MC_READ, 0, &mp)) { + //printf("%u", mp.mpd.abtData); + for(int i = 0; i <= 7; i++) { + if (mp.mpd.abtData[i] != 0x00) return false; + } + } else { + return false; + } + + return true; +} + static bool write_card(bool write_otp, bool write_lock, bool write_uid) { @@ -202,13 +239,13 @@ print_usage(const char *argv[]) int main(int argc, const char *argv[]) { - bool bReadAction; - bool bOTP; - bool bLock; - bool bUID; + int iAction = 0; + bool bOTP = false; + bool bLock = false; + bool bUID = false; FILE *pfDump; - if (argc < 3) { + if (argc == 0) { print_usage(argv); exit(EXIT_FAILURE); } @@ -218,9 +255,9 @@ main(int argc, const char *argv[]) // Get commandline options for (int arg = 1; arg < argc; arg++) { if (0 == strcmp(argv[arg], "r")) { - bReadAction = true; + iAction = 1; } else if (0 == strcmp(argv[arg], "w")) { - bReadAction = false; + iAction = 2; } else if (0 == strcmp(argv[arg], "--full")) { bOTP = true; bLock = true; @@ -231,6 +268,8 @@ main(int argc, const char *argv[]) bLock = true; } else if (0 == strcmp(argv[arg], "--uid")) { bUID = true; + } else if (0 == strcmp(argv[arg], "--check-magic")) { + iAction = 3; } else { //Skip validation of the filename if (arg != 2) { @@ -241,10 +280,9 @@ main(int argc, const char *argv[]) } } - - if (bReadAction) { + if (iAction == 1) { memset(&mtDump, 0x00, sizeof(mtDump)); - } else { + } else if (iAction == 2) { pfDump = fopen(argv[2], "rb"); if (pfDump == NULL) { @@ -258,9 +296,14 @@ main(int argc, const char *argv[]) exit(EXIT_FAILURE); } fclose(pfDump); + DBG("Successfully opened the dump file\n"); + } else if (iAction == 3) { + DBG("Switching to Check Magic Mode\n"); + } else { + ERR("Unable to determine operating mode"); + exit(EXIT_FAILURE); } - DBG("Successfully opened the dump file\n"); - + nfc_context *context; nfc_init(&context); if (context == NULL) { @@ -316,7 +359,7 @@ main(int argc, const char *argv[]) } printf("\n"); - if (bReadAction) { + if (iAction == 1) { if (read_card()) { printf("Writing data to file: %s ... ", argv[2]); fflush(stdout); @@ -337,8 +380,15 @@ main(int argc, const char *argv[]) fclose(pfDump); printf("Done.\n"); } - } else { + } else if (iAction == 2) { write_card(bOTP, bLock, bUID); + } else if (iAction == 3) { + if (!check_magic()) { + printf("Card is not magic\n"); + exit(EXIT_FAILURE); + } else { + printf("Card is magic\n"); + } } nfc_close(pnd); From 619b476028bf68b3fc2ed0da278203b34fad455f Mon Sep 17 00:00:00 2001 From: Simon Yorkston Date: Wed, 18 Nov 2015 23:11:59 +0100 Subject: [PATCH 111/318] Cleaned non-magic exit --- utils/nfc-mfultralight.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 3fab03e9..4d251146 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -385,6 +385,8 @@ main(int argc, const char *argv[]) } else if (iAction == 3) { if (!check_magic()) { printf("Card is not magic\n"); + nfc_close(pnd); + nfc_exit(context); exit(EXIT_FAILURE); } else { printf("Card is magic\n"); From c7f386dbcffaadff2e118cf05ad8728451fe4558 Mon Sep 17 00:00:00 2001 From: Paul Menzel Date: Fri, 4 Dec 2015 13:59:59 +0100 Subject: [PATCH 112/318] README: Fix typo in *is a registered* --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index d557d4fb..74f03a09 100644 --- a/README +++ b/README @@ -177,7 +177,7 @@ them in a modprobe conf file. This file is provided within libnfc archive: Proprietary Notes ================= -FeliCa is s registered trademark of the Sony Corporation. +FeliCa is a registered trademark of the Sony Corporation. MIFARE is a trademark of NXP Semiconductors. Jewel Topaz is a trademark of Innovision Research & Technology. All other trademarks are the property of their respective owners. From 10398b6bd92a70be0735dbe9aa0c56503f2078ce Mon Sep 17 00:00:00 2001 From: Alexander Inyukhin Date: Sat, 19 Mar 2016 08:08:38 +0300 Subject: [PATCH 113/318] =?UTF-8?q?=D0=90=20typo=20leads=20to=20improper?= =?UTF-8?q?=20pnd->name=20initialization?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A for loop condition is always false so pnd->name is not initialized. This results in garbage when printing device name. --- libnfc/nfc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 114d5e87..404786a4 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -276,7 +276,7 @@ nfc_open(nfc_context *context, const nfc_connstring connstring) log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Unable to open \"%s\".", ncs); return NULL; } - for (uint32_t i = 0; i > context->user_defined_device_count; i++) { + for (uint32_t i = 0; i < context->user_defined_device_count; i++) { if (strcmp(ncs, context->user_defined_devices[i].connstring) == 0) { // This is a device sets by user, we use the device name given by user strcpy(pnd->name, context->user_defined_devices[i].name); From b1a81b385ddabb704b4cea64fda56abb9928c3c3 Mon Sep 17 00:00:00 2001 From: Hidde Wieringa Date: Thu, 7 Apr 2016 13:52:12 +0200 Subject: [PATCH 114/318] Changed a few README Markdown files to the .md extension so GitHub interprets it as Markdown --- HACKING => HACKING.md | 0 NEWS => NEWS.md | 0 README-Windows.txt => README-Windows.md | 0 README => README.md | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename HACKING => HACKING.md (100%) rename NEWS => NEWS.md (100%) rename README-Windows.txt => README-Windows.md (100%) rename README => README.md (100%) diff --git a/HACKING b/HACKING.md similarity index 100% rename from HACKING rename to HACKING.md diff --git a/NEWS b/NEWS.md similarity index 100% rename from NEWS rename to NEWS.md diff --git a/README-Windows.txt b/README-Windows.md similarity index 100% rename from README-Windows.txt rename to README-Windows.md diff --git a/README b/README.md similarity index 100% rename from README rename to README.md From 62159a33ef9176fbe34e434def6ea714b7845983 Mon Sep 17 00:00:00 2001 From: Hidde Wieringa Date: Fri, 8 Apr 2016 10:49:28 +0200 Subject: [PATCH 115/318] Added more Markdown formatting to README --- README.md | 62 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 74f03a09..b03551fd 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ +``` *- * Free/Libre Near Field Communication (NFC) library -* +* * Libnfc historical contributors: * Copyright (C) 2009 Roel Verdult * Copyright (C) 2009-2015 Romuald Conty @@ -10,6 +11,7 @@ * Additional contributors: * See AUTHORS file -* +``` General Information =================== @@ -46,11 +48,12 @@ http://cutter.sf.net Installation ============ -See the file 'INSTALL' for configure, build and install details. +See the file `INSTALL` for configure, build and install details. Additionnally, you may need to grant permissions to your user to drive your device. Under GNU/Linux systems, if you use udev, you could use the provided udev rules. e.g. under Debian, Ubuntu, etc. + sudo cp contrib/udev/42-pn53x.rules /lib/udev/rules.d/ Under FreeBSD, if you use devd, there is also a rules file: contrib/devd/pn53x.conf. @@ -64,16 +67,20 @@ configuration file located in sysconfdir (as provided to ./configure). A sample commented file is available in sources: libnfc.conf.sample If you have compiled using: - ./configure --prefix=/usr --sysconfdir=/etc + + ./configure --prefix=/usr --sysconfdir=/etc + you can make configuration directory and copy the sample file: - sudo mkdir /etc/nfc - sudo cp libnfc.conf.sample /etc/nfc/libnfc.conf + + sudo mkdir /etc/nfc + sudo cp libnfc.conf.sample /etc/nfc/libnfc.conf To configure multiple devices, you can either modify libnfc.conf or create a file per device in a nfc/devices.d directory: - sudo mkdir -p /etc/nfc/devices.d - printf 'name = "My first device"\nconnstring = "pn532_uart:/dev/ttyACM0"\n' | sudo tee /etc/nfc/devices.d/first.conf - printf 'name = "My second device"\nconnstring = "pn532_uart:/dev/ttyACM1"\n' | sudo tee /etc/nfc/devices.d/second.conf + + sudo mkdir -p /etc/nfc/devices.d + printf 'name = "My first device"\nconnstring = "pn532_uart:/dev/ttyACM0"\n' | sudo tee /etc/nfc/devices.d/first.conf + printf 'name = "My second device"\nconnstring = "pn532_uart:/dev/ttyACM1"\n' | sudo tee /etc/nfc/devices.d/second.conf How to report bugs ================== @@ -82,7 +89,7 @@ To report a bug, visit https://github.com/nfc-tools/libnfc/issues and fill out a bug report form. If you have questions, remarks, we encourage you to post this in the developers -community: +community: http://www.libnfc.org/community Please make sure to include: @@ -99,14 +106,17 @@ Please make sure to include: * A trace with debug activated. Reproduce the bug with debug, e.g. if it was: - $ nfc-list -v + + $ nfc-list -v + run it as: - $ LIBNFC_LOG_LEVEL=3 nfc-list -v + + $ LIBNFC_LOG_LEVEL=3 nfc-list -v * How to reproduce the bug. - Please include a short test program that exhibits the behavior. - As a last resort, you can also provide a pointer to a larger piece + Please include a short test program that exhibits the behavior. + As a last resort, you can also provide a pointer to a larger piece of software that can be downloaded. * If the bug was a crash, the exact text that was printed out @@ -128,8 +138,8 @@ Building It should be as simple as running these two commands: -./configure -make + ./configure + make Troubleshooting =============== @@ -137,27 +147,27 @@ Troubleshooting Touchatag/ACR122: ----------------- If your Touchatag or ACR122 device fails being detected by libnfc, make sure -that PCSC-lite daemon (pcscd) is installed and is running. +that PCSC-lite daemon (`pcscd`) is installed and is running. If your Touchatag or ACR122 device fails being detected by PCSC-lite daemon -(pcsc_scan doesn't see anything) then try removing the bogus firmware detection +(`pcsc_scan` doesn't see anything) then try removing the bogus firmware detection of libccid: edit libccid_Info.plist configuration file (usually -/etc/libccid_Info.plist) and locate "ifdDriverOptions", turn -"0x0000" value into 0x0004 to allow bogus devices and restart +`/etc/libccid_Info.plist`) and locate `ifdDriverOptions`, turn +`0x0000` value into `0x0004` to allow bogus devices and restart pcscd daemon. ACR122: ------- Using an ACR122 device with libnfc and without tag (e.g. to use NFCIP modes or card emulation) needs yet another PCSC-lite tweak: You need to allow usage of -CCID Exchange command. To do this, edit libccid_Info.plist configuration file -(usually /etc/libccid_Info.plist) and locate "ifdDriverOptions", -turn "0x0000" value into 0x0001 to allow CCID exchange or -0x0005 to allow CCID exchange and bogus devices (cf previous remark) and +CCID Exchange command. To do this, edit `libccid_Info.plist` configuration file +(usually `/etc/libccid_Info.plist`) and locate `ifdDriverOptions`, +turn `0x0000` value into `0x0001` to allow CCID exchange or +`0x0005` to allow CCID exchange and bogus devices (cf previous remark) and restart pcscd daemon. Warning: if you use ACS CCID drivers (acsccid), configuration file is located -in something like: /usr/lib/pcsc/drivers/ifd-acsccid.bundle/Contents/Info.plist +in something like: `/usr/lib/pcsc/drivers/ifd-acsccid.bundle/Contents/Info.plist` SCL3711: -------- @@ -172,7 +182,8 @@ Since Linux kernel version 3.1, two kernel-modules must not be loaded in order to use libnfc : "nfc" and "pn533". To prevent kernel from loading automatically these modules, you can blacklist them in a modprobe conf file. This file is provided within libnfc archive: - sudo cp contrib/linux/blacklist-libnfc.conf /etc/modprobe.d/blacklist-libnfc.conf + + sudo cp contrib/linux/blacklist-libnfc.conf /etc/modprobe.d/blacklist-libnfc.conf Proprietary Notes ================= @@ -181,4 +192,3 @@ FeliCa is a registered trademark of the Sony Corporation. MIFARE is a trademark of NXP Semiconductors. Jewel Topaz is a trademark of Innovision Research & Technology. All other trademarks are the property of their respective owners. - From 291f70edeef6ca072f331402e90fba81edd651bb Mon Sep 17 00:00:00 2001 From: Hidde Wieringa Date: Fri, 8 Apr 2016 10:56:12 +0200 Subject: [PATCH 116/318] Updated README-Windows for Markdown --- README-Windows.md | 52 +++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/README-Windows.md b/README-Windows.md index bf4ba69c..2f3a254f 100644 --- a/README-Windows.md +++ b/README-Windows.md @@ -1,16 +1,16 @@ -*- -* Free/Libre Near Field Communication (NFC) library -* -* Libnfc historical contributors: -* Copyright (C) 2009 Roel Verdult -* Copyright (C) 2009-2013 Romuald Conty -* Copyright (C) 2010-2012 Romain Tartière -* Copyright (C) 2010-2013 Philippe Teuwen -* Copyright (C) 2012-2013 Ludovic Rousseau -* Additional contributors of Windows-specific parts: -* Copyright (C) 2010 Glenn Ergeerts -* Copyright (C) 2013 Alex Lian --* + *- + * Free/Libre Near Field Communication (NFC) library + * + * Libnfc historical contributors: + * Copyright (C) 2009 Roel Verdult + * Copyright (C) 2009-2013 Romuald Conty + * Copyright (C) 2010-2012 Romain Tartière + * Copyright (C) 2010-2013 Philippe Teuwen + * Copyright (C) 2012-2013 Ludovic Rousseau + * Additional contributors of Windows-specific parts: + * Copyright (C) 2010 Glenn Ergeerts + * Copyright (C) 2013 Alex Lian + -* Requirements ============ @@ -20,7 +20,7 @@ Requirements - CMake 2.8 [3] This was tested on Windows 7 64 bit, but should work on Windows Vista and -Windows XP and 32 bit as well. +Windows XP and 32 bit as well. Only the ACS ACR122 and the ASK Logo readers are tested at the moment, so any feedback about other devices is very welcome. Community forum: http://www.libnfc.org/community/ @@ -33,34 +33,38 @@ is an example of how to generate a distribution with the above mentioned requirements fulfilled (it is assumed the CMake binaries are in the system path, this is optional during installation of CMake): -- Add the following directories to your PATH : c:\MinGW64\bin;c:\MinGW64\x86_64-w64-mingw32\lib32;c:\MinGW64\x86_64-w64-mingw32\include +- Add the following directories to your PATH: + + c:\MinGW64\bin;c:\MinGW64\x86_64-w64-mingw32\lib32;c:\MinGW64\x86_64-w64-mingw32\include - Now it is possible to run CMake and mingw32-make: - C:\dev\libnfc-read-only> mkdir ..\libnfc-build - C:\dev\libnfc-read-only> cd ..\libnfc-build - C:\dev\libnfc-build> cmake-gui . - + C:\dev\libnfc-read-only> mkdir ..\libnfc-build + C:\dev\libnfc-read-only> cd ..\libnfc-build + C:\dev\libnfc-build> cmake-gui . + Now you can configure the build. Press "Configure", specify "MinGW32 Makefiles" and then you have the opportunity to set some configuration variables. If you don't want a Debug build change the variable CMAKE_BUILD_TYPE to "Release". If a non-GUI solution is preferred one can use: - C:\dev\libnfc-build> cmake -G "MinGW Makefiles" + C:\dev\libnfc-build> cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release ..\libnfc-read-only Now run mingw32-make to build: - C:\dev\libnfc-read-only\bin> mingw32-make - + C:\dev\libnfc-read-only\bin> mingw32-make + The build will create a shared library for Windows (nfc.dll) to link your applications against. It will compile -the tools against this shared library. +the tools against this shared library. References ========== -[1] the easiest way is to use the TDM-GCC installer. +[1] the easiest way is to use the TDM-GCC installer. Make sure to select MinGW-w64 in the installer, the regular MinGW does not contain headers for PCSC. http://sourceforge.net/projects/tdm-gcc/files/TDM-GCC%20Installer/tdm64-gcc-4.5.1.exe/download + [2] http://sourceforge.net/projects/libusb-win32/files/ + [3] http://www.cmake.org From 1f688880200395f9c1e8678e052b95483ee50f0b Mon Sep 17 00:00:00 2001 From: Hidde Wieringa Date: Fri, 8 Apr 2016 11:02:40 +0200 Subject: [PATCH 117/318] Added Markdown to HACKING file --- HACKING.md | 57 +++++++++++++++++++++++++++++------------------ README-Windows.md | 4 ++-- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/HACKING.md b/HACKING.md index 56930af2..da1b244b 100644 --- a/HACKING.md +++ b/HACKING.md @@ -15,41 +15,54 @@ Here are some directions to get you started: Helper script to get some uniformity in the style: $ make style - If you use vim see the "Vim: How to prevent trailing whitespaces" - http://www.carbon-project.org/Vim__How_to_prevent_trailing_whitespaces.html + If you use vim see the [Vim: How to prevent trailing whitespaces](http://www.carbon-project.org/Vim__How_to_prevent_trailing_whitespaces.html). 2. Chase warnings: no warning should be introduced by your changes Depending what you touch, you can check with: + 2.1 When using autotools - $ autoreconf -Wall -vis + + $ autoreconf -Wall -vis + 2.2 When compiling + 2.2.1 Using extra flags: - $ export CFLAGS="-Wall -g -O2 -Wextra -pipe -funsigned-char -fstrict-aliasing \ - -Wchar-subscripts -Wundef -Wshadow -Wcast-align -Wwrite-strings -Wunused \ - -Wuninitialized -Wpointer-arith -Wredundant-decls -Winline -Wformat \ - -Wformat-security -Wswitch-enum -Winit-self -Wmissing-include-dirs \ - -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition \ - -Wbad-function-cast -Wnested-externs -Wmissing-declarations" - $ ./configure - $ make clean - $ make + + $ export CFLAGS="-Wall -g -O2 -Wextra -pipe -funsigned-char -fstrict-aliasing \ + -Wchar-subscripts -Wundef -Wshadow -Wcast-align -Wwrite-strings -Wunused \ + -Wuninitialized -Wpointer-arith -Wredundant-decls -Winline -Wformat \ + -Wformat-security -Wswitch-enum -Winit-self -Wmissing-include-dirs \ + -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition \ + -Wbad-function-cast -Wnested-externs -Wmissing-declarations" + $ ./configure + $ make clean + $ make + 2.2.2 Using clang: - You can use same CFLAGS but also "-Wunreachable-code" - $ scan-build ./configure - $ make clean - $ scan-build make - 2.2.3 Using cppcheck (v1.58 or higher): - $ make cppcheck + + You can use same CFLAGS but also `-Wunreachable-code` + + $ scan-build ./configure + $ make clean + $ scan-build make + + 2.2.3 Using `cppcheck` (v1.58 or higher): + + $ make cppcheck + 2.3 When Debianizing - $ lintian --info --display-info --display-experimental *deb - or (shorter version) - $ lintian -iIE *deb + + $ lintian --info --display-info --display-experimental *deb + or (shorter version) + $ lintian -iIE *deb 3. Preserve cross-platform compatility + The source code should remain compilable across various platforms, including some you probably cannot test alone so keep it in mind. Supported platforms: + - Linux - FreeBSD - Mac OS X - - Windows with Mingw + - Windows with MinGW diff --git a/README-Windows.md b/README-Windows.md index 2f3a254f..8b22bf2f 100644 --- a/README-Windows.md +++ b/README-Windows.md @@ -40,8 +40,8 @@ path, this is optional during installation of CMake): - Now it is possible to run CMake and mingw32-make: C:\dev\libnfc-read-only> mkdir ..\libnfc-build - C:\dev\libnfc-read-only> cd ..\libnfc-build - C:\dev\libnfc-build> cmake-gui . + C:\dev\libnfc-read-only> cd ..\libnfc-build + C:\dev\libnfc-build> cmake-gui . Now you can configure the build. Press "Configure", specify "MinGW32 Makefiles" and then you have the opportunity to set some configuration variables. If you From 8de7ce3899b442b8b083bbebc209e32ac116ac04 Mon Sep 17 00:00:00 2001 From: Simon Yorkston Date: Sat, 9 Apr 2016 01:32:14 +1000 Subject: [PATCH 118/318] Adding support for UL Gen 2 Badges --- utils/nfc-mfultralight.c | 86 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 4d251146..01752ef5 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -64,6 +64,18 @@ static mifare_param mp; static mifareul_tag mtDump; static uint32_t uiBlocks = 0xF; +// special unlock command +uint8_t abtUnlock1[1] = { 0x40 }; +uint8_t abtUnlock2[1] = { 0x43 }; + +//Halt command +uint8_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 }; + +#define MAX_FRAME_LEN 264 + +static uint8_t abtRx[MAX_FRAME_LEN]; +static int szRxBits; + static const nfc_modulation nmMifare = { .nmt = NMT_ISO14443A, .nbr = NBR_106, @@ -107,10 +119,77 @@ read_card(void) return (!bFailure); } +static bool +transmit_bits(const uint8_t *pbtTx, const size_t szTxBits) +{ + // Transmit the bit frame command, we don't use the arbitrary parity feature + if ((szRxBits = nfc_initiator_transceive_bits(pnd, pbtTx, szTxBits, NULL, abtRx, sizeof(abtRx), NULL)) < 0) + return false; + + return true; +} + + +static bool +transmit_bytes(const uint8_t *pbtTx, const size_t szTx) +{ + int res; + if ((res = nfc_initiator_transceive_bytes(pnd, pbtTx, szTx, abtRx, sizeof(abtRx), 0)) < 0) + return false; + + return true; +} + +static bool +unlock_card(void) +{ + // Configure the CRC + if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) { + nfc_perror(pnd, "nfc_configure"); + return false; + } + // Use raw send/receive methods + if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, false) < 0) { + nfc_perror(pnd, "nfc_configure"); + return false; + } + + iso14443a_crc_append(abtHalt, 2); + transmit_bytes(abtHalt, 4); + // now send unlock + if (!transmit_bits(abtUnlock1, 7)) { + printf("unlock failure!\n"); + return false; + } + if (!transmit_bytes(abtUnlock2, 1)) { + printf("unlock failure!\n"); + return false; + } + + // reset reader + // Configure the CRC + if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true) < 0) { + nfc_perror(pnd, "nfc_device_set_property_bool"); + return false; + } + // Switch off raw send/receive methods + if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, true) < 0) { + nfc_perror(pnd, "nfc_device_set_property_bool"); + return false; + } + return true; +} + static bool check_magic() { bool bFailure = false; int uid_data; - + + //Initially check if we can unlock via the MF method + if (unlock_card()) { + printf("Ultralight Magic Gen 2 Detected\n"); + return true; + } + for (uint32_t page = 0; page <= 1; page++) { // Show if the readout went well if (bFailure) { @@ -140,7 +219,8 @@ static bool check_magic() { } else { return false; } - + + printf("Ultralight Magic Gen 1 Detected\n"); return true; } @@ -183,6 +263,8 @@ write_card(bool write_otp, bool write_lock, bool write_uid) if (!write_uid) { printf("ss"); uiSkippedPages = 2; + } else { + unlock_card(); } for (int page = uiSkippedPages; page <= 0xF; page++) { From e37de54e18e03b65b123a5ba81bccc7cde355939 Mon Sep 17 00:00:00 2001 From: Simon Yorkston Date: Sat, 9 Apr 2016 03:42:01 +1000 Subject: [PATCH 119/318] Updated to remove bugs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - For cards that aren’t magic, system will refuse to attempt writing to block 0 / 1 - Tested on Gen 1 & Gen 2 cards: Gen 1 $ ./nfc-mfultralight w ul-test.dmp --full NFC device: SCM Micro / SCL3711-NFC&RW opened Found MIFARE Ultralight card with UID: 044e075ad42184 Writing 16 pages |................| Done, 16 of 16 pages written (0 pages skipped). Gen 2 $ ./nfc-mfultralight w ul-test.dmp --full NFC device: SCM Micro / SCL3711-NFC&RW opened Found MIFARE Ultralight card with UID: 044e075ad42184 Writing 16 pages |................| Done, 16 of 16 pages written (0 pages skipped). Non-magic $ ./nfc-mfultralight w ul-test.dmp --full NFC device: SCM Micro / SCL3711-NFC&RW opened Found MIFARE Ultralight card with UID: 044e075ad42184 Writing 16 pages | Unable to unlock card - are you sure the card is magic? $ --- utils/nfc-mfultralight.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 01752ef5..615833f5 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -158,11 +158,9 @@ unlock_card(void) transmit_bytes(abtHalt, 4); // now send unlock if (!transmit_bits(abtUnlock1, 7)) { - printf("unlock failure!\n"); return false; } if (!transmit_bytes(abtUnlock2, 1)) { - printf("unlock failure!\n"); return false; } @@ -184,12 +182,6 @@ static bool check_magic() { bool bFailure = false; int uid_data; - //Initially check if we can unlock via the MF method - if (unlock_card()) { - printf("Ultralight Magic Gen 2 Detected\n"); - return true; - } - for (uint32_t page = 0; page <= 1; page++) { // Show if the readout went well if (bFailure) { @@ -213,15 +205,24 @@ static bool check_magic() { //Check that the ID is now set to 0x000000000000 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) return false; + if (mp.mpd.abtData[i] != 0x00) result = false; } + + if (result) { + return true; + } + + } + + //Initially check if we can unlock via the MF method + if (unlock_card()) { + return true; } else { - return false; + return false; } - printf("Ultralight Magic Gen 1 Detected\n"); - return true; } static bool @@ -264,7 +265,11 @@ write_card(bool write_otp, bool write_lock, bool write_uid) printf("ss"); uiSkippedPages = 2; } else { - unlock_card(); + if (!check_magic()) { + printf("\nUnable to unlock card - are you sure the card is magic?\n"); + return false; + bFailure = false; + } } for (int page = uiSkippedPages; page <= 0xF; page++) { From 7d4352dc9871cf6085ef2ba079607370923fe359 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 3 May 2016 10:53:55 +0200 Subject: [PATCH 120/318] tell Automake that we will not follow GNU Standards NEWS and README are mandatory for autoconf. Fixes problem introduced in b1a81b385ddabb704b4cea64fda56abb9928c3c3 closes https://github.com/nfc-tools/libnfc/pull/346 fixes https://github.com/nfc-tools/libnfc/issues/347 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 804aacd8..0e635a55 100644 --- a/configure.ac +++ b/configure.ac @@ -13,7 +13,7 @@ if test x"$GIT_REVISION" != x""; then AC_DEFINE_UNQUOTED([GIT_REVISION], ["$GIT_REVISION"], [GIT revision]) fi -AM_INIT_AUTOMAKE(subdir-objects dist-bzip2 no-dist-gzip) +AM_INIT_AUTOMAKE(subdir-objects dist-bzip2 no-dist-gzip foreign) m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) From 898f3a4d2f804b8b0fc0976d2b17dcde18118c42 Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Thu, 18 Feb 2016 17:09:04 +0100 Subject: [PATCH 121/318] nfc-mfclassic: check argc < 4 only once Currently the check on argc is done twice, once in each if branch. This is silly and we can just check once and fail right away. Signed-off-by: Olliver Schinagl --- utils/nfc-mfclassic.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 333f7104..f9a27b53 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -526,11 +526,11 @@ main(int argc, const char *argv[]) } const char *command = argv[1]; + if (argc < 4) { + print_usage(argv[0]); + exit(EXIT_FAILURE); + } if (strcmp(command, "r") == 0 || strcmp(command, "R") == 0) { - if (argc < 4) { - print_usage(argv[0]); - exit(EXIT_FAILURE); - } atAction = ACTION_READ; if (strcmp(command, "R") == 0) unlock = 1; @@ -539,10 +539,6 @@ main(int argc, const char *argv[]) bUseKeyFile = (argc > 4); bForceKeyFile = ((argc > 5) && (strcmp((char *)argv[5], "f") == 0)); } else if (strcmp(command, "w") == 0 || strcmp(command, "W") == 0 || strcmp(command, "f") == 0) { - if (argc < 4) { - print_usage(argv[0]); - exit(EXIT_FAILURE); - } atAction = ACTION_WRITE; if (strcmp(command, "W") == 0) unlock = 1; From e1a25a82036e2d8725eeb1e2f9465f3776de3b3f Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Thu, 18 Feb 2016 18:28:08 +0100 Subject: [PATCH 122/318] nfc-mfclassic: Add option to specify key The nfc-mfclassic utility will pick a seemingly random (the libnfc default which seems to be the lowest UID). With the new (u|U) options it is now possible to force a UID and thus write a specific tag, which can be very useful if there are more then one tag visible. Signed-off-by: Olliver Schinagl --- utils/nfc-mfclassic.1 | 17 ++++++++++ utils/nfc-mfclassic.c | 77 +++++++++++++++++++++++++++++-------------- 2 files changed, 69 insertions(+), 25 deletions(-) diff --git a/utils/nfc-mfclassic.1 b/utils/nfc-mfclassic.1 index 34083c6a..0be3871c 100644 --- a/utils/nfc-mfclassic.1 +++ b/utils/nfc-mfclassic.1 @@ -5,6 +5,7 @@ nfc-mfclassic \- MIFARE Classic command line tool .B nfc-mfclassic .RI \fR\fBf\fR|\fR\fBr\fR|\fR\fBR\fR|\fBw\fR\fR|\fBW\fR .RI \fR\fBa\fR|\fR\fBA\fR|\fBb\fR\fR|\fBB\fR +.RI \fR\fBu\fR\fR|\fBU\fR<\fBuid\fR>\fR .IR DUMP .RI [ .IR KEYS @@ -56,6 +57,15 @@ or .B B ). +When using multiple tags infront of a reader, the +.B U +option can be used to supply the UID of tag to be read or written. Append the +hexadecimal UID to the U option. For example U01ab23cd for the 4 byte UID +0x01 0xab 0x23 0xcd. Using the +.B u +parameter instead will use whatever libnfc decides which generally is the lowest +UID. + *** Note that .B W and @@ -90,6 +100,13 @@ Halt on errors ( B ). .TP +.BR u " | " U +Use the default UID ( +.B u +) or supply a valid 4 byte UID ( +.B U +). +.TP .IR DUMP MiFare Dump (MFD) used to write (card to MFD) or (MFD to card) .TP diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index f9a27b53..56d5717c 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -491,26 +491,29 @@ static void print_usage(const char *pcProgramName) { printf("Usage: "); - printf("%s f|r|R|w|W a|b [ [f]]\n", pcProgramName); + printf("%s f|r|R|w|W a|b u|U<01ab23cd> [ [f]]\n", pcProgramName); printf(" f|r|R|w|W - Perform format (f) or read from (r) or unlocked read from (R) or write to (w) or unlocked write to (W) card\n"); printf(" *** format will reset all keys to FFFFFFFFFFFF and all data to 00 and all ACLs to default\n"); printf(" *** unlocked read does not require authentication and will reveal A and B keys\n"); printf(" *** note that unlocked write will attempt to overwrite block 0 including UID\n"); printf(" *** unlocking only works with special Mifare 1K cards (Chinese clones)\n"); printf(" a|A|b|B - Use A or B keys for action; Halt on errors (a|b) or tolerate errors (A|B)\n"); + printf(" u|U - Use any (u) uid or supply a uid specifically as U01ab23cd.\n"); 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 mycard.mfd\n\n", pcProgramName); + printf(" %s r a u mycard.mfd\n\n", pcProgramName); printf(" Write file to blank card, using key A:\n\n"); - printf(" %s w a mycard.mfd\n\n", pcProgramName); + printf(" %s w a u mycard.mfd\n\n", pcProgramName); printf(" Write new data and/or keys to previously written card, using key A:\n\n"); - printf(" %s w a newdata.mfd mycard.mfd\n\n", pcProgramName); + printf(" %s w a u newdata.mfd mycard.mfd\n\n", pcProgramName); printf(" Format/wipe card (note two passes required to ensure writes for all ACL cases):\n\n"); - printf(" %s f A dummy.mfd keyfile.mfd f\n", pcProgramName); - printf(" %s f B dummy.mfd keyfile.mfd f\n\n", pcProgramName); + printf(" %s f A u dummy.mfd keyfile.mfd f\n", pcProgramName); + printf(" %s f B u dummy.mfd keyfile.mfd f\n\n", pcProgramName); + printf(" Read card to file, using key A and uid 0x01 0xab 0x23 0xcd:\n\n"); + printf(" %s r a U01ab23cd mycard.mfd\n\n", pcProgramName); } int @@ -518,6 +521,9 @@ main(int argc, const char *argv[]) { action_t atAction = ACTION_USAGE; uint8_t *pbtUID; + uint8_t _tag_uid[4]; + uint8_t *tag_uid = _tag_uid; + int unlock = 0; if (argc < 2) { @@ -526,7 +532,7 @@ main(int argc, const char *argv[]) } const char *command = argv[1]; - if (argc < 4) { + if (argc < 5) { print_usage(argv[0]); exit(EXIT_FAILURE); } @@ -536,8 +542,8 @@ main(int argc, const char *argv[]) unlock = 1; bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a'; bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2])); - bUseKeyFile = (argc > 4); - bForceKeyFile = ((argc > 5) && (strcmp((char *)argv[5], "f") == 0)); + bUseKeyFile = (argc > 5); + bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0)); } else if (strcmp(command, "w") == 0 || strcmp(command, "W") == 0 || strcmp(command, "f") == 0) { atAction = ACTION_WRITE; if (strcmp(command, "W") == 0) @@ -545,8 +551,26 @@ main(int argc, const char *argv[]) bFormatCard = (strcmp(command, "f") == 0); bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a'; bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2])); - bUseKeyFile = (argc > 4); - bForceKeyFile = ((argc > 5) && (strcmp((char *)argv[5], "f") == 0)); + bUseKeyFile = (argc > 5); + bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0)); + } + if (argv[3][0] == 'U') { + unsigned long int _uid; + + if (strlen(argv[3]) != 9) { + printf("Error, illegal tag specification, use U01ab23cd for example.\n"); + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + _uid = strtoul(argv[3] + 1, NULL, 16); + tag_uid[0] = (_uid & 0xff000000UL) >> 24; + tag_uid[1] = (_uid & 0x00ff0000UL) >> 16; + tag_uid[2] = (_uid & 0x0000ff00UL) >> 8; + tag_uid[3] = (_uid & 0x000000ffUL); + printf("Attempting to use specific UID: 0x%2x 0x%2x 0x%2x 0x%2x\n", + tag_uid[0], tag_uid[1], tag_uid[2], tag_uid[3]); + } else { + tag_uid = NULL; } if (atAction == ACTION_USAGE) { @@ -555,13 +579,13 @@ main(int argc, const char *argv[]) } // We don't know yet the card size so let's read only the UID from the keyfile for the moment if (bUseKeyFile) { - FILE *pfKeys = fopen(argv[4], "rb"); + FILE *pfKeys = fopen(argv[5], "rb"); if (pfKeys == NULL) { - printf("Could not open keys file: %s\n", argv[4]); + printf("Could not open keys file: %s\n", argv[5]); exit(EXIT_FAILURE); } if (fread(&mtKeys, 1, 4, pfKeys) != 4) { - printf("Could not read UID from key file: %s\n", argv[4]); + printf("Could not read UID from key file: %s\n", argv[5]); fclose(pfKeys); exit(EXIT_FAILURE); } @@ -606,7 +630,10 @@ main(int argc, const char *argv[]) printf("NFC reader: %s opened\n", nfc_device_get_name(pnd)); // Try to find a MIFARE Classic tag - if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { + int tags; + + tags = nfc_initiator_select_passive_target(pnd, nmMifare, tag_uid, tag_uid == NULL ? 0 : 4, &nt); + if (tags <= 0) { printf("Error: no tag was found\n"); nfc_close(pnd); nfc_exit(context); @@ -668,13 +695,13 @@ main(int argc, const char *argv[]) printf("Guessing size: seems to be a %i-byte card\n", (uiBlocks + 1) * 16); if (bUseKeyFile) { - FILE *pfKeys = fopen(argv[4], "rb"); + FILE *pfKeys = fopen(argv[5], "rb"); if (pfKeys == NULL) { - printf("Could not open keys file: %s\n", argv[4]); + printf("Could not open keys file: %s\n", argv[5]); exit(EXIT_FAILURE); } if (fread(&mtKeys, 1, (uiBlocks + 1) * sizeof(mifare_classic_block), pfKeys) != (uiBlocks + 1) * sizeof(mifare_classic_block)) { - printf("Could not read keys file: %s\n", argv[4]); + printf("Could not read keys file: %s\n", argv[5]); fclose(pfKeys); exit(EXIT_FAILURE); } @@ -684,16 +711,16 @@ main(int argc, const char *argv[]) if (atAction == ACTION_READ) { memset(&mtDump, 0x00, sizeof(mtDump)); } else { - FILE *pfDump = fopen(argv[3], "rb"); + FILE *pfDump = fopen(argv[4], "rb"); if (pfDump == NULL) { - printf("Could not open dump file: %s\n", argv[3]); + printf("Could not open dump file: %s\n", argv[4]); exit(EXIT_FAILURE); } if (fread(&mtDump, 1, (uiBlocks + 1) * sizeof(mifare_classic_block), pfDump) != (uiBlocks + 1) * sizeof(mifare_classic_block)) { - printf("Could not read dump file: %s\n", argv[3]); + printf("Could not read dump file: %s\n", argv[4]); fclose(pfDump); exit(EXIT_FAILURE); } @@ -703,17 +730,17 @@ main(int argc, const char *argv[]) if (atAction == ACTION_READ) { if (read_card(unlock)) { - printf("Writing data to file: %s ...", argv[3]); + printf("Writing data to file: %s ...", argv[4]); fflush(stdout); - FILE *pfDump = fopen(argv[3], "wb"); + FILE *pfDump = fopen(argv[4], "wb"); if (pfDump == NULL) { - printf("Could not open dump file: %s\n", argv[3]); + printf("Could not open dump file: %s\n", argv[4]); nfc_close(pnd); nfc_exit(context); exit(EXIT_FAILURE); } if (fwrite(&mtDump, 1, (uiBlocks + 1) * sizeof(mifare_classic_block), pfDump) != ((uiBlocks + 1) * sizeof(mifare_classic_block))) { - printf("\nCould not write to file: %s\n", argv[3]); + printf("\nCould not write to file: %s\n", argv[4]); fclose(pfDump); nfc_close(pnd); nfc_exit(context); From 7b1ff70a521ec3db2302efd22db84b3cfb678b0c Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Wed, 11 May 2016 09:13:31 +0200 Subject: [PATCH 123/318] nfc-mfultralight: Show help when no arguments are supplied For some reason, 0cece94778 changed the argc count check to only show the help if argc is 0. Obviously, argc is never zero, as the first argument in argv is always the binary itself. Revert that and show usage if there is no arguments supplied to the binary. Signed-off-by: Olliver Schinagl --- utils/nfc-mfultralight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 615833f5..b676d281 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -332,7 +332,7 @@ main(int argc, const char *argv[]) bool bUID = false; FILE *pfDump; - if (argc == 0) { + if (argc < 2) { print_usage(argv); exit(EXIT_FAILURE); } From ecd0e59b5c905a60fa4e4a5f4b486fce69e4f7ff Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Wed, 11 May 2016 09:20:42 +0200 Subject: [PATCH 124/318] nfc-mfultralight: Add option to specify UID When several tags are in range, nfc-mfultralight uses the lowest ID it finds by default. This patch adds some code from nfc-list that lists the tags in range whenever an operation is performed (r/w). Further more it adds the --with-uid option to force reading/writing of a specific tag. The UID can be up to 10 bytes long and can be optionally separated by colons or hyphens (MAC address style). Signed-off-by: Olliver Schinagl --- utils/nfc-mfultralight.c | 79 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 5 deletions(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index b676d281..3b901ac9 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -58,6 +58,9 @@ #include "nfc-utils.h" #include "mifare.h" +#define MAX_TARGET_COUNT 16 +#define MAX_UID_LEN 10 + static nfc_device *pnd; static nfc_target nt; static mifare_param mp; @@ -310,6 +313,57 @@ write_card(bool write_otp, bool write_lock, bool write_uid) return true; } +static int list_passive_targets(nfc_device *_pnd) +{ + int res = 0; + + nfc_target ant[MAX_TARGET_COUNT]; + + if (nfc_initiator_init(_pnd) < 0) { + return -EXIT_FAILURE; + } + + if ((res = nfc_initiator_list_passive_targets(_pnd, nmMifare, ant, MAX_TARGET_COUNT)) >= 0) { + int i; + + if (res > 0) + printf("%d ISO14443A passive target(s) found:\n", res); + + for (i = 0; i < res; i++) { + size_t szPos; + + printf("\t"); + for (szPos = 0; szPos < ant[i].nti.nai.szUidLen; szPos++) { + printf("%02x", ant[i].nti.nai.abtUid[szPos]); + } + printf("\n"); + } + + } + + return 0; +} + +static size_t str_to_uid(const char *str, uint8_t *uid) +{ + uint8_t i; + + memset(uid, 0x0, MAX_UID_LEN); + i = 0; + while ((*str != '\0') && ((i >> 1) < MAX_UID_LEN) ) { + char nibble[2] = { 0x00, '\n' }; /* for strtol */ + + nibble[0] = *str++; + if (isxdigit(nibble[0])) { + if (isupper(nibble[0])) + nibble[0] = tolower(nibble[0]); + uid[i >> 1] |= strtol(nibble, NULL, 16) << ((i % 2) ? 0 : 4) & ((i % 2) ? 0x0f : 0xf0); + i++; + } + } + return i >> 1; +} + static void print_usage(const char *argv[]) { @@ -321,12 +375,15 @@ print_usage(const char *argv[]) printf("\t--lock\t\t - Don't prompt for Lockbit writing (Assume yes)\n"); printf("\t--uid\t\t - Don't prompt for UID writing (Assume yes)\n"); printf("\t--full\t\t - Assume full card write (UID + OTP + Lockbit)\n"); + printf("\t--with-uid \t\t - Specify UID to read/write from\n"); } int main(int argc, const char *argv[]) { int iAction = 0; + uint8_t iUID[MAX_UID_LEN] = { 0x0 }; + size_t szUID = 0; bool bOTP = false; bool bLock = false; bool bUID = false; @@ -345,6 +402,12 @@ main(int argc, const char *argv[]) iAction = 1; } else if (0 == strcmp(argv[arg], "w")) { iAction = 2; + } else if (0 == strcmp(argv[arg], "--with-uid")) { + if (argc < 5) { + ERR("Please supply a UID of 4, 7 or 10 bytes long. Ex: a1:b2:c3:d4"); + exit(EXIT_FAILURE); + } + szUID = str_to_uid(argv[4], iUID); } else if (0 == strcmp(argv[arg], "--full")) { bOTP = true; bLock = true; @@ -359,7 +422,7 @@ main(int argc, const char *argv[]) iAction = 3; } else { //Skip validation of the filename - if (arg != 2) { + if ((arg != 2) && (arg != 4)) { ERR("%s is not supported option.", argv[arg]); print_usage(argv); exit(EXIT_FAILURE); @@ -405,6 +468,14 @@ main(int argc, const char *argv[]) nfc_exit(context); exit(EXIT_FAILURE); } + printf("NFC device: %s opened\n", nfc_device_get_name(pnd)); + + if (list_passive_targets(pnd)) { + nfc_perror(pnd, "nfc_device_set_property_bool"); + nfc_close(pnd); + nfc_exit(context); + exit(EXIT_FAILURE); + } if (nfc_initiator_init(pnd) < 0) { nfc_perror(pnd, "nfc_initiator_init"); @@ -421,10 +492,8 @@ main(int argc, const char *argv[]) exit(EXIT_FAILURE); } - printf("NFC device: %s opened\n", nfc_device_get_name(pnd)); - // Try to find a MIFARE Ultralight tag - if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { + if (nfc_initiator_select_passive_target(pnd, nmMifare, (szUID) ? iUID : NULL, szUID, &nt) <= 0) { ERR("no tag was found\n"); nfc_close(pnd); nfc_exit(context); @@ -439,7 +508,7 @@ main(int argc, const char *argv[]) exit(EXIT_FAILURE); } // Get the info from the current tag - printf("Found MIFARE Ultralight card with UID: "); + printf("Using MIFARE Ultralight card with UID: "); size_t szPos; for (szPos = 0; szPos < nt.nti.nai.szUidLen; szPos++) { printf("%02x", nt.nti.nai.abtUid[szPos]); From 4b8871fd8f2183508d677a80f349e92cc51f0a26 Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Wed, 11 May 2016 09:35:48 +0200 Subject: [PATCH 125/318] nfc-mfultralight: Remove whitespaces Clean up some stray unintended whitespaces. This patch does not introduce any binary changes. Signed-off-by: Olliver Schinagl --- utils/nfc-mfultralight.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 3b901ac9..ea0f7dc9 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -183,7 +183,7 @@ unlock_card(void) static bool check_magic() { bool bFailure = false; - int uid_data; + int uid_data; for (uint32_t page = 0; page <= 1; page++) { // Show if the readout went well @@ -197,27 +197,27 @@ static bool check_magic() { } 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 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; - } + } - if (result) { + if (result) { return true; } - } + } //Initially check if we can unlock via the MF method if (unlock_card()) { @@ -238,7 +238,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid) char buffer[BUFSIZ]; - if (!write_otp) { + if (!write_otp) { printf("Write OTP bytes ? [yN] "); if (!fgets(buffer, BUFSIZ, stdin)) { ERR("Unable to read standard input."); @@ -246,7 +246,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid) write_otp = ((buffer[0] == 'y') || (buffer[0] == 'Y')); } - if (!write_lock) { + if (!write_lock) { printf("Write Lock bytes ? [yN] "); if (!fgets(buffer, BUFSIZ, stdin)) { ERR("Unable to read standard input."); @@ -254,7 +254,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid) write_lock = ((buffer[0] == 'y') || (buffer[0] == 'Y')); } - if (!write_uid) { + if (!write_uid) { printf("Write UID bytes (only for special writeable UID cards) ? [yN] "); if (!fgets(buffer, BUFSIZ, stdin)) { ERR("Unable to read standard input."); @@ -453,7 +453,7 @@ main(int argc, const char *argv[]) ERR("Unable to determine operating mode"); exit(EXIT_FAILURE); } - + nfc_context *context; nfc_init(&context); if (context == NULL) { From ed62b01a0f0ecc279c8146065462d1b03095e029 Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Wed, 11 May 2016 14:24:59 +0200 Subject: [PATCH 126/318] nfc-mfultralight: write uiBlocks, as we read We use a variable, uiBlocks, to determine how many blocks to read/write. Reading is actually done via a hardcoded 0xF value however. Additionally, make uiblocks a const, as we use it as a constant and change the page variable to uint32_t for consistency sake. Signed-off-by: Olliver Schinagl --- utils/nfc-mfultralight.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index ea0f7dc9..82707a93 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -60,12 +60,13 @@ #define MAX_TARGET_COUNT 16 #define MAX_UID_LEN 10 +#define BLOCK_COUNT 0xf static nfc_device *pnd; static nfc_target nt; static mifare_param mp; static mifareul_tag mtDump; -static uint32_t uiBlocks = 0xF; +static const uint32_t uiBlocks = BLOCK_COUNT; // special unlock command uint8_t abtUnlock1[1] = { 0x40 }; @@ -275,7 +276,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid) } } - for (int page = uiSkippedPages; page <= 0xF; page++) { + for (uint32_t page = uiSkippedPages; page <= ((uiBlocks / 4) * 4); page++) { if ((page == 0x2) && (!write_lock)) { printf("s"); uiSkippedPages++; From a4bc1b9f6c62491d6b1f102707a7adf8cc2195da Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Wed, 11 May 2016 16:27:52 +0200 Subject: [PATCH 127/318] nfc-mfultralight: also set failure state on uid write error Currently, we return false, and after turning set the bFailure state. This is of course not possible. Signed-off-by: Olliver Schinagl --- utils/nfc-mfultralight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 82707a93..4b9f39d0 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -271,8 +271,8 @@ write_card(bool write_otp, bool write_lock, bool write_uid) } else { if (!check_magic()) { printf("\nUnable to unlock card - are you sure the card is magic?\n"); - return false; bFailure = false; + return false; } } From 41d694013c7062ab22b21a051536f5cd8cf0c4a2 Mon Sep 17 00:00:00 2001 From: yerzhanm Date: Thu, 23 Jun 2016 18:20:39 +0600 Subject: [PATCH 128/318] added support for ACR1222U-C1 added ACR1222U-C1 ACS ACR1222 1SAM PICC Reader in supported devices --- libnfc/drivers/acr122_usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libnfc/drivers/acr122_usb.c b/libnfc/drivers/acr122_usb.c index 8a169202..a6392e8d 100644 --- a/libnfc/drivers/acr122_usb.c +++ b/libnfc/drivers/acr122_usb.c @@ -262,6 +262,7 @@ struct acr122_usb_supported_device { const struct acr122_usb_supported_device acr122_usb_supported_devices[] = { { 0x072F, 0x2200, "ACS ACR122" }, { 0x072F, 0x90CC, "Touchatag" }, + { 0x072F, 0x2214, "ACS ACR1222" }, }; // Find transfer endpoints for bulk transfers From 4076046a66b22c067432a050d329f94f5a9ed01f Mon Sep 17 00:00:00 2001 From: Jim Anastassiou Date: Fri, 19 Aug 2016 18:36:48 -0400 Subject: [PATCH 129/318] Create pn532_uart_on_rpi3.conf.sample --- contrib/libnfc/pn532_uart_on_rpi3.conf.sample | 1 + 1 file changed, 1 insertion(+) create mode 100644 contrib/libnfc/pn532_uart_on_rpi3.conf.sample diff --git a/contrib/libnfc/pn532_uart_on_rpi3.conf.sample b/contrib/libnfc/pn532_uart_on_rpi3.conf.sample new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/contrib/libnfc/pn532_uart_on_rpi3.conf.sample @@ -0,0 +1 @@ + From 35cc69dffb1b661e9ba0f0ca92e9705c69404850 Mon Sep 17 00:00:00 2001 From: Jim Anastassiou Date: Fri, 19 Aug 2016 18:37:04 -0400 Subject: [PATCH 130/318] Rename pn532_uart_on_rpi3.conf.sample to pn532_uart_on_rpi_3.conf.sample --- ...2_uart_on_rpi3.conf.sample => pn532_uart_on_rpi_3.conf.sample} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename contrib/libnfc/{pn532_uart_on_rpi3.conf.sample => pn532_uart_on_rpi_3.conf.sample} (100%) diff --git a/contrib/libnfc/pn532_uart_on_rpi3.conf.sample b/contrib/libnfc/pn532_uart_on_rpi_3.conf.sample similarity index 100% rename from contrib/libnfc/pn532_uart_on_rpi3.conf.sample rename to contrib/libnfc/pn532_uart_on_rpi_3.conf.sample From 27ed3acc1aced88a48d9e5d22b9e4f883e1d4476 Mon Sep 17 00:00:00 2001 From: Jim Anastassiou Date: Fri, 19 Aug 2016 18:38:19 -0400 Subject: [PATCH 131/318] Update pn532_uart_on_rpi_3.conf.sample --- contrib/libnfc/pn532_uart_on_rpi_3.conf.sample | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/contrib/libnfc/pn532_uart_on_rpi_3.conf.sample b/contrib/libnfc/pn532_uart_on_rpi_3.conf.sample index 8b137891..ae969d72 100644 --- a/contrib/libnfc/pn532_uart_on_rpi_3.conf.sample +++ b/contrib/libnfc/pn532_uart_on_rpi_3.conf.sample @@ -1 +1,6 @@ +## Typical configuration file for PN532 device on R-Pi connected using UART +## Note: to use UART port on R-Pi, you have to disable linux serial console: +## http://learn.adafruit.com/adafruit-nfc-rfid-on-raspberry-pi/freeing-uart-on-the-pi +name = "PN532 board via UART" +connstring = pn532_uart:/dev/ttyS0 From 0d3d5c13ff221a1286ba353ab2d5846d800eb1ee Mon Sep 17 00:00:00 2001 From: Jim Anastassiou Date: Fri, 19 Aug 2016 19:22:06 -0400 Subject: [PATCH 132/318] Add R-Pi 3 conf sample. There have been changes to the Raspberry Pi 3's usage of serial ports with the addition of a Bluetooth LE module. This configuration uses the mini UART without disabling any devices except for the linux serial console. --- .../libnfc/pn532_uart_on_rpi_3.conf.sample | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/contrib/libnfc/pn532_uart_on_rpi_3.conf.sample b/contrib/libnfc/pn532_uart_on_rpi_3.conf.sample index ae969d72..fc1ad1b1 100644 --- a/contrib/libnfc/pn532_uart_on_rpi_3.conf.sample +++ b/contrib/libnfc/pn532_uart_on_rpi_3.conf.sample @@ -1,6 +1,22 @@ -## Typical configuration file for PN532 device on R-Pi connected using UART -## Note: to use UART port on R-Pi, you have to disable linux serial console: -## http://learn.adafruit.com/adafruit-nfc-rfid-on-raspberry-pi/freeing-uart-on-the-pi +## Typical configuration file for PN532 device on R-Pi 3 connected using miniUART +## Note: Changes have been made to R-Pi 3 with the addition of Bluetooth LE +## The UART is now being used by the BLE module. Instead of disabling it, you can +## use the PN532 device with the "mini UART", which is still hijacked by the linux kernel +## as a serial console +## +## Tested recipe with PN532 breakout from Adafruit +## +## To enable uart on GPIO, add this line to bottom of /boot/config.txt +## enable_uart=1 +## +## Stop and disable serial console: +## $ sudo systemctl stop serial-getty@ttyS0.service +## $ sudo systemctl disable serial-getty@ttyS0.service +## +## Remove console from /boot/cmdline.txt by removing: +## console=serial0,115200 Save and reboot for changes to take effect. +## name = "PN532 board via UART" connstring = pn532_uart:/dev/ttyS0 +allow_intrusive_scan = true From 7eae55e92970e880ddd6ee52f9c84269df70b101 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 6 Oct 2016 17:40:48 +0200 Subject: [PATCH 133/318] 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 1ac65b22..4432c5c1 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 00000000..9c57c460 --- /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 00000000..0f1efdb1 --- /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 00000000..43c5ff67 --- /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 404786a4..df739c5e 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 46725391..54be7e7d 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 134/318] Cosmetics changes --- libnfc/drivers/libnfc_nci_support.h | 134 ----------- libnfc/drivers/pn71xx.c | 329 +++++++++++++++++++--------- 2 files changed, 226 insertions(+), 237 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 9c57c460..00000000 --- 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 0f1efdb1..82459081 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,47 +41,27 @@ 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); /** ------------------------------------------------------------------------ */ /** ------------------------------------------------------------------------ */ - -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. + * @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 all I2C PN532 devices found. + * connection info strings of devices found. * @param connstrings_len length of the connstrings array. - * @return number of PN532 devices found on all I2C buses. + * @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)); @@ -92,7 +71,7 @@ pn71xx_scan(const nfc_context *context, nfc_connstring connstrings[], const size } /** - * @brief Close I2C connection to the PN532 device. + * @brief Close connection to PN71xx by stopping the discovery loop and deinitializing the libnfc_nci library. * * @param pnd pointer on the device to close. */ @@ -102,12 +81,12 @@ pn71xx_close(nfc_device *pnd) nfcManager_disableDiscovery(); nfcManager_deregisterTagCallback(); nfcManager_doDeinitialize(); - nfc_device_free(pnd); + pnd = NULL; } /** - * @brief Open an I2C connection to the PN532 device. + * @brief Open a connection to PN71xx, starting the discovery loop for tag detection. * * @param context NFC context. * @param connstring connection info to the device @@ -117,7 +96,7 @@ 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); @@ -130,29 +109,170 @@ pn71xx_open(const nfc_context *context, const nfc_connstring connstring) 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); + 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); + } +} /** ------------------------------------------------------------------------ */ /** ------------------------------------------------------------------------ */ +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; +} 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, - - .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, + .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, From 61b42396d916f6ceea267dcb55e34868526cf662 Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Fri, 21 Oct 2016 14:17:23 +0200 Subject: [PATCH 135/318] CMake: allow building of debian packages This patch allows for using the CMakefile to generate debian packages. While CPack is far from perfect for generating debian packages, it is a minimal change and quite helpful for quick deployment on debian based systems. Signed-off-by: Olliver Schinagl --- CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 21ee9e76..cd8183fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,6 +63,8 @@ ENDIF(LIBNFC_CONFFILES_MODE) option (BUILD_EXAMPLES "build examples ON/OFF" ON) option (BUILD_UTILS "build utils ON/OFF" ON) +option (BUILD_DEBPKG "build debian package ON/OFF" OFF) + # Doxygen SET(builddir "${CMAKE_BINARY_DIR}") @@ -224,10 +226,14 @@ IF(WIN32) SET(CPACK_GENERATOR "ZIP") ELSE(WIN32) SET(CPACK_GENERATOR "TBZ2") + IF(BUILD_DEBPKG) + SET(CPACK_GENERATOR "DEB") + ENDIF(BUILD_DEBPKG) ENDIF(WIN32) SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Near Field Communication (NFC) library") SET(CPACK_PACKAGE_VENDOR "Roel Verdult") +SET(CPACK_PACKAGE_CONTACT "Roel Verdul ") SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README") SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING") SET(CPACK_PACKAGE_INSTALL_DIRECTORY "libnfc") From 512be897009cfd9a4213e1bd1093845780a31005 Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Fri, 21 Oct 2016 13:46:26 +0200 Subject: [PATCH 136/318] busses: i2c: improve logging Currently we only inform the user with the error logging mechanism that we received a different number of bytes than expected. Thus in case of an error, we say that we sent/received -1 bytes. However -1 indicates an error and errno is set to indicate the error state. This patch extends the logging to also print the actual error. Additionally the same debugging printing was added to read, which is now silently returned to the caller. Signed-off-by: Olliver Schinagl --- libnfc/buses/i2c.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libnfc/buses/i2c.c b/libnfc/buses/i2c.c index a0ee1894..a37372d7 100644 --- a/libnfc/buses/i2c.c +++ b/libnfc/buses/i2c.c @@ -135,6 +135,8 @@ i2c_read(i2c_device id, uint8_t *pbtRx, const size_t szRx) if (recCount < 0) { res = NFC_EIO; + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, + "Error: read only %d bytes (%d expected) (%s).", (int)recCount, (int) szRx, strerror(errno)); } else { if (recCount < (ssize_t)szRx) { res = NFC_EINVARG; @@ -167,7 +169,7 @@ i2c_write(i2c_device id, const uint8_t *pbtTx, const size_t szTx) return NFC_SUCCESS; } else { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, - "Error: wrote only %d bytes (%d expected).", (int)writeCount, (int) szTx); + "Error: wrote only %d bytes (%d expected) (%s).", (int)writeCount, (int) szTx, strerror(errno)); return NFC_EIO; } } From b953002f8f917b96139f198a2628ba3d36d0a0db Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Thu, 20 Oct 2016 17:36:04 +0200 Subject: [PATCH 137/318] drivers: pn532_i2c: Clarify preamble and start byte The pn532 documentation differs slightly from the included ascii art documentation on how a packet looks like. The preamble was omitted however the postamble is mentioned. This patch adds the Preamble to the ascii frame documentation. The code later refers incorrectly to the start byte as the preamble. This variable was renamed to more descriptively state that it is the preambe and the start bytes. Signed-off-by: Olliver Schinagl --- libnfc/chips/pn53x-internal.h | 48 ++++++++++++++++++++--------------- libnfc/drivers/pn532_i2c.c | 11 +++++--- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/libnfc/chips/pn53x-internal.h b/libnfc/chips/pn53x-internal.h index c43934a0..e4869cd9 100644 --- a/libnfc/chips/pn53x-internal.h +++ b/libnfc/chips/pn53x-internal.h @@ -81,32 +81,38 @@ #define TgGetTargetStatus 0x8A /** @note PN53x's normal frame: + * See the PN532 (firmware) user manual, section 6.2.1.1: Normal information + * frame, figure 13. Normal information frame, page 28 rev. 02 - 2007-11-07. * - * .-- Start - * | .-- Packet length - * | | .-- Length checksum - * | | | .-- Direction (D4 Host to PN, D5 PN to Host) - * | | | | .-- Code - * | | | | | .-- Packet checksum - * | | | | | | .-- Postamble - * V | | | | | | - * ----- V V V V V V - * 00 FF 02 FE D4 02 2A 00 + * .-- Preamble + * | .-- Start + * | | .-- Packet length + * | | | .-- Length checksum + * | | | | .-- Direction (D4 Host to PN, D5 PN to Host) + * | | | | | .-- Code + * | | | | | | .-- Packet checksum + * | | | | | | | .-- Postamble + * | V | | | | | | + * V ----- V V V V V V + * 00 00 FF 02 FE D4 02 2A 00 */ /** @note PN53x's extended frame: + * See the PN532 (firmware) user manual, section 6.2.1.2: Extended information + * frame, figure 14. Normal information frame, page 29 rev. 02 - 2007-11-07. * - * .-- Start - * | .-- Fixed to FF to enable extended frame - * | | .-- Packet length - * | | | .-- Length checksum - * | | | | .-- Direction (D4 Host to PN, D5 PN to Host) - * | | | | | .-- Code - * | | | | | | .-- Packet checksum - * | | | | | | | .-- Postamble - * V V V | | | | | - * ----- ----- ----- V V V V V - * 00 FF FF FF 00 02 FE D4 02 2A 00 + * .-- Preamble + * | .-- Start + * | | .-- Fixed to FF to enable extended frame + * | | | .-- Packet length + * | | | | .-- Length checksum + * | | | | | .-- Direction (D4 Host to PN, D5 PN to Host) + * | | | | | | .-- Code + * | | | | | | | .-- Packet checksum + * | | | | | | | | .-- Postamble + * | V V V | | | | | + * V ----- ----- ----- V V V V V + * 00 00 FF FF FF 00 02 FE D4 02 2A 00 */ /** diff --git a/libnfc/drivers/pn532_i2c.c b/libnfc/drivers/pn532_i2c.c index b62c7dea..fe3345c3 100644 --- a/libnfc/drivers/pn532_i2c.c +++ b/libnfc/drivers/pn532_i2c.c @@ -75,6 +75,10 @@ const struct timespec rdyDelay = { .tv_nsec = PN532_RDY_LOOP_DELAY * 1000 * 1000 }; +/* preamble and start bytes, see pn532-internal.h for details */ +const uint8_t pn53x_preamble_and_start[] = { 0x00, 0x00, 0xff }; +#define PN53X_PREAMBLE_AND_START_LEN (sizeof(pn53x_preamble_and_start) / sizeof(pn53x_preamble_and_start[0])) + /* Private Functions Prototypes */ static nfc_device *pn532_i2c_open(const nfc_context *context, const nfc_connstring connstring); @@ -334,9 +338,10 @@ pn532_i2c_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int break; }; - uint8_t abtFrame[PN532_BUFFER_LEN] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff" + uint8_t abtFrame[PN532_BUFFER_LEN]; size_t szFrame = 0; + memcpy(abtFrame, pn53x_preamble_and_start, PN53X_PREAMBLE_AND_START_LEN); // Every packet must start with the preamble and start bytes. if ((res = pn53x_build_frame(abtFrame, &szFrame, pbtData, szData)) < 0) { pnd->last_error = res; return pnd->last_error; @@ -477,9 +482,7 @@ pn532_i2c_receive(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, int goto error; } - const uint8_t pn53x_preamble[3] = { 0x00, 0x00, 0xff }; - - if (0 != (memcmp(frameBuf, pn53x_preamble, 3))) { + if (0 != (memcmp(frameBuf, pn53x_preamble_and_start, PN53X_PREAMBLE_AND_START_LEN))) { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Frame preamble+start code mismatch"); pnd->last_error = NFC_EIO; goto error; From 8f8f780c2bdd95b8609b43d37f9f4982825851d4 Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Fri, 21 Oct 2016 10:48:56 +0200 Subject: [PATCH 138/318] drivers: pn532_i2c: Respect proper timing specifications The pn532 user manual states that after a i2c stop condition and before a i2c start condition there should be a delay of minimally 1.3 milliseconds. This is probably a limitation of the i2c peripheral or the firmware. In any case, each i2c_read and i2c_write creates the packets which are complemented with start/stop markers. It is thus required to take care of timing in these two functions. We solve this by wrapping the lower i2c_read and i2c_write functions for the pn532, as this requirement is not for all chips. Currently, we keep time using local variable, and thus the code is not thread-safe. With libnfc being single threaded and only one instances of libnfc can open a bus anyway, this is not yet a problem. Signed-off-by: Olliver Schinagl --- libnfc/drivers/pn532_i2c.c | 81 +++++++++++++++++++++++++++++++------- 1 file changed, 67 insertions(+), 14 deletions(-) diff --git a/libnfc/drivers/pn532_i2c.c b/libnfc/drivers/pn532_i2c.c index fe3345c3..6315954d 100644 --- a/libnfc/drivers/pn532_i2c.c +++ b/libnfc/drivers/pn532_i2c.c @@ -67,14 +67,6 @@ struct pn532_i2c_data { volatile bool abort_flag; }; -/* Delay for the loop waiting for READY frame (in ms) */ -#define PN532_RDY_LOOP_DELAY 90 - -const struct timespec rdyDelay = { - .tv_sec = 0, - .tv_nsec = PN532_RDY_LOOP_DELAY * 1000 * 1000 -}; - /* preamble and start bytes, see pn532-internal.h for details */ const uint8_t pn53x_preamble_and_start[] = { 0x00, 0x00, 0xff }; #define PN53X_PREAMBLE_AND_START_LEN (sizeof(pn53x_preamble_and_start) / sizeof(pn53x_preamble_and_start[0])) @@ -100,6 +92,70 @@ static size_t pn532_i2c_scan(const nfc_context *context, nfc_connstring connstri #define DRIVER_DATA(pnd) ((struct pn532_i2c_data*)(pnd->driver_data)) +/* + * Bus free time (in ms) between a STOP condition and START condition. See + * tBuf in the PN532 data sheet, section 12.25: Timing for the I2C interface, + * table 320. I2C timing specification, page 211, rev. 3.2 - 2007-12-07. + */ +#define PN532_BUS_FREE_TIME 1.3 +static struct timespec __transaction_stop; + +/** + * @brief Wrapper around i2c_read to ensure proper timing by respecting the + * minimal free bus time between a STOP condition and a START condition. + * + * @note This is not thread safe, but since libnfc is single threaded + * this should be okay. + * + * @param id I2C device + * @param buf pointer on buffer used to store data + * @param len length of the buffer + * @return length (in bytes) of read data, or driver error code (negative value) + */ +static ssize_t pn532_i2c_read(const i2c_device id, + uint8_t *buf, const size_t len) +{ + struct timespec transaction_start, bus_free_time = { 0 }; + ssize_t ret; + + clock_gettime(CLOCK_MONOTONIC, &transaction_start); + bus_free_time.tv_nsec = (PN532_BUS_FREE_TIME * 1000 * 1000) - + (transaction_start.tv_nsec - __transaction_stop.tv_nsec); + nanosleep(&bus_free_time, NULL); + + ret = i2c_read(id, buf, len); + clock_gettime(CLOCK_MONOTONIC, &__transaction_stop); + return ret; +} + +/** + * @brief Wrapper around i2c_write to ensure proper timing by respecting the + * minimal free bus time between a STOP condition and a START condition. + * + * @note This is not thread safe, but since libnfc is single threaded + * this should be okay. + * + * @param id I2C device + * @param buf pointer on buffer containing data + * @param len length of the buffer + * @return NFC_SUCCESS on success, otherwise driver error code + */ +static ssize_t pn532_i2c_write(const i2c_device id, + const uint8_t *buf, const size_t len) +{ + struct timespec transaction_start, bus_free_time = { 0 }; + ssize_t ret; + + clock_gettime(CLOCK_MONOTONIC, &transaction_start); + bus_free_time.tv_nsec = (PN532_BUS_FREE_TIME * 1000 * 1000) - + (transaction_start.tv_nsec - __transaction_stop.tv_nsec); + nanosleep(&bus_free_time, NULL); + + ret = i2c_write(id, buf, len); + clock_gettime(CLOCK_MONOTONIC, &__transaction_stop); + return ret; +} + /** * @brief Scan all available I2C buses to find PN532 devices. * @@ -347,7 +403,7 @@ pn532_i2c_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int return pnd->last_error; } - res = i2c_write(DRIVER_DATA(pnd)->dev, abtFrame, szFrame); + res = pn532_i2c_write(DRIVER_DATA(pnd)->dev, abtFrame, szFrame); if (res < 0) { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to transmit data. (TX)"); @@ -405,10 +461,7 @@ pn532_i2c_wait_rdyframe(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLe } do { - // Wait a little bit before reading - nanosleep(&rdyDelay, (struct timespec *) NULL); - - int recCount = i2c_read(DRIVER_DATA(pnd)->dev, i2cRx, szDataLen + 1); + int recCount = pn532_i2c_read(DRIVER_DATA(pnd)->dev, i2cRx, szDataLen + 1); if (DRIVER_DATA(pnd)->abort_flag) { // Reset abort flag @@ -575,7 +628,7 @@ pn532_i2c_receive(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, int int pn532_i2c_ack(nfc_device *pnd) { - return i2c_write(DRIVER_DATA(pnd)->dev, pn53x_ack_frame, sizeof(pn53x_ack_frame)); + return pn532_i2c_write(DRIVER_DATA(pnd)->dev, pn53x_ack_frame, sizeof(pn53x_ack_frame)); } /** From d960673681db074f99078a946c663d6d3e58c751 Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Mon, 24 Oct 2016 09:34:19 +0200 Subject: [PATCH 139/318] drivers: pn532_i2c: Add retry on error mechanism Currently, we very occasionally can EXNIO errors from pn532_i2c_write() -> i2c_write() -> write(). This may happen about once every 30 seconds. Based from the kernel sources, EXNIO happens if the chip no longer responds to its own address. To make sure we do not loose any sent packets, we retry to send PN532_SEND_RETRIES number of times. Since we miss 1 every 30 or so seconds, doing 1 retry should be fine. This might be considered a hack as the failure may be some other timing related issue. Signed-off-by: Olliver Schinagl --- libnfc/drivers/pn532_i2c.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/libnfc/drivers/pn532_i2c.c b/libnfc/drivers/pn532_i2c.c index 6315954d..6d9e3fde 100644 --- a/libnfc/drivers/pn532_i2c.c +++ b/libnfc/drivers/pn532_i2c.c @@ -59,6 +59,13 @@ // I2C address of the PN532 chip. #define PN532_I2C_ADDR 0x24 +/* + * When sending lots of data, the pn532 occasionally fails to respond in time. + * Since it happens so rarely, lets try to fix it by re-sending the data. This + * define allows for fine tuning the number of retries. + */ +#define PN532_SEND_RETRIES 3 + // Internal data structs const struct pn53x_io pn532_i2c_io; @@ -368,6 +375,7 @@ static int pn532_i2c_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int timeout) { int res = 0; + uint8_t retries; // Discard any existing data ? @@ -403,7 +411,13 @@ pn532_i2c_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int return pnd->last_error; } - res = pn532_i2c_write(DRIVER_DATA(pnd)->dev, abtFrame, szFrame); + for (retries = PN532_SEND_RETRIES; retries > 0; retries--) { + res = pn532_i2c_write(DRIVER_DATA(pnd)->dev, abtFrame, szFrame); + if (res >= 0) + break; + + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Failed to transmit data. Retries left: %d.", retries - 1); + } if (res < 0) { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to transmit data. (TX)"); From a625d6a02d19c89a0542cd0a2058218eb163f06d Mon Sep 17 00:00:00 2001 From: timzi Date: Sun, 20 Nov 2016 18:48:00 +0300 Subject: [PATCH 140/318] Fixed file name "README" in cmakelists.txt --- CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 21ee9e76..3e23c6ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -228,7 +228,14 @@ ENDIF(WIN32) SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Near Field Communication (NFC) library") SET(CPACK_PACKAGE_VENDOR "Roel Verdult") -SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README") + +#Readme file +IF(WIN32) + SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README-Windows.md") +ELSE(WIN32) + SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md") +ENDIF(WIN32) + SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING") SET(CPACK_PACKAGE_INSTALL_DIRECTORY "libnfc") SET(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR}) From 65477eea5e8de714b6992ed5ad363faf8f1f9391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Bourgeois?= Date: Mon, 5 Dec 2016 13:11:45 +0100 Subject: [PATCH 141/318] Match nfc.h Synchronized with nfc.h with all API functions --- contrib/win32/nfc.def | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/contrib/win32/nfc.def b/contrib/win32/nfc.def index 085b2f71..5ed4097c 100644 --- a/contrib/win32/nfc.def +++ b/contrib/win32/nfc.def @@ -4,6 +4,7 @@ VERSION 1.7 EXPORTS nfc_init nfc_exit + nfc_register_driver nfc_open nfc_close nfc_abort_command @@ -17,7 +18,6 @@ EXPORTS nfc_initiator_select_dep_target nfc_initiator_poll_dep_target nfc_initiator_deselect_target - nfc_initiator_poll_targets nfc_initiator_transceive_bytes nfc_initiator_transceive_bits nfc_initiator_transceive_bytes_timed @@ -36,11 +36,15 @@ EXPORTS nfc_device_get_connstring nfc_device_get_supported_modulation nfc_device_get_supported_baud_rate + nfc_device_get_supported_baud_rate_target_mode nfc_device_set_property_int nfc_device_set_property_bool iso14443a_crc iso14443a_crc_append + iso14443b_crc + iso14443b_crc_append iso14443a_locate_historical_bytes + nfc_free nfc_version nfc_device_get_information_about str_nfc_modulation_type From e946f7a97a38eb3145cd3105f2343ca5716e7b4e Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Tue, 6 Dec 2016 11:40:54 +0100 Subject: [PATCH 142/318] drivers: pn532_i2c: Errata on i2c timing The datasheet is wrong for the pn532_i2c. After having constant issues with the device failing to respond on the bus and after contacting NXP about this, it turns out 1.3 ms is too tight. The official timing spec is unknown for now, but we tested 4 and 5 ms without problems. Thus we have choosen 5 ms as a safe delay. Signed-off-by: Olliver Schinagl --- libnfc/drivers/pn532_i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnfc/drivers/pn532_i2c.c b/libnfc/drivers/pn532_i2c.c index 6d9e3fde..d242df94 100644 --- a/libnfc/drivers/pn532_i2c.c +++ b/libnfc/drivers/pn532_i2c.c @@ -104,7 +104,7 @@ static size_t pn532_i2c_scan(const nfc_context *context, nfc_connstring connstri * tBuf in the PN532 data sheet, section 12.25: Timing for the I2C interface, * table 320. I2C timing specification, page 211, rev. 3.2 - 2007-12-07. */ -#define PN532_BUS_FREE_TIME 1.3 +#define PN532_BUS_FREE_TIME 5 static struct timespec __transaction_stop; /** From b29332a3095de036b0f08b6f1cd526e8a441d384 Mon Sep 17 00:00:00 2001 From: Maxim Martyanov Date: Tue, 6 Dec 2016 20:43:08 +0400 Subject: [PATCH 143/318] Update Makefile.am README-Windows.txt -> README-Windows.md --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index a1604a3c..413b6de4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,7 +10,7 @@ pkgconfig_DATA = libnfc.pc EXTRA_DIST = \ CMakeLists.txt \ Doxyfile \ - README-Windows.txt \ + README-Windows.md \ libnfc.conf.sample CLEANFILES = Doxygen.log coverage.info libnfc.pc From e32cc068ec55eb78b24b83b676d8366e5b013282 Mon Sep 17 00:00:00 2001 From: Maxim Martyanov Date: Tue, 6 Dec 2016 20:44:31 +0400 Subject: [PATCH 144/318] Update README.md README-Windows.txt => README-Windows.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b03551fd..d68508ff 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ The official forum site is: The official development site is: https://github.com/nfc-tools/libnfc -Important note: this file covers POSIX systems, for Windows please read README-Windows.txt +Important note: this file covers POSIX systems, for Windows please read README-Windows.md Requirements ============ From b38597f1e08a2dccd9f8fb80d2b84a0e15400191 Mon Sep 17 00:00:00 2001 From: John Galt Date: Wed, 7 Dec 2016 06:17:04 -0500 Subject: [PATCH 145/318] Fix typo in nfc.h --- include/nfc/nfc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/nfc/nfc.h b/include/nfc/nfc.h index 4ebc6ff9..bbbde943 100644 --- a/include/nfc/nfc.h +++ b/include/nfc/nfc.h @@ -28,7 +28,7 @@ * @file nfc.h * @brief libnfc interface * - * Provide all usefull functions (API) to handle NFC devices. + * Provide all useful functions (API) to handle NFC devices. */ #ifndef _LIBNFC_H_ From 9c7b9eda8ca69b46cc6f039ff21e080881b24d93 Mon Sep 17 00:00:00 2001 From: John Galt Date: Wed, 7 Dec 2016 07:22:27 -0500 Subject: [PATCH 146/318] Fix typo in nfc.c --- libnfc/nfc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 404786a4..97451a1f 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -972,7 +972,7 @@ nfc_target_init(nfc_device *pnd, nfc_target *pnt, uint8_t *pbtRx, const size_t s * @param pnd \a nfc_device struct pointer that represent currently used device * * This function switch the device in idle mode. - * In initiator mode, the RF field is turned off and the device is set to low power mode (if avaible); + * In initiator mode, the RF field is turned off and the device is set to low power mode (if available); * In target mode, the emulation is stoped (no target available from external initiator) and the device is set to low power mode (if avaible). */ int From f9f03fa7fade3738a6ac8160268920994001a63f Mon Sep 17 00:00:00 2001 From: jgeslin Date: Thu, 12 Jan 2017 09:53:40 +0100 Subject: [PATCH 147/318] Debug dedicated implementation removed --- libnfc/nfc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libnfc/nfc.c b/libnfc/nfc.c index df739c5e..968a3ef5 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 11a2da281132b08d470eb22835837d75e7b15175 Mon Sep 17 00:00:00 2001 From: Christoph Gritschenberger Date: Wed, 25 Jan 2017 11:05:58 +0100 Subject: [PATCH 148/318] allow to cross-compile 32 and 64 bit versions of the library for windows --- CMakeLists.txt | 51 +++++++++++++++++----- libnfc/CMakeLists.txt | 2 +- mingw-cross-compile.sh | 34 +++++++++++++++ mingw-cross-configure.sh | 91 ---------------------------------------- 4 files changed, 75 insertions(+), 103 deletions(-) create mode 100644 mingw-cross-compile.sh delete mode 100644 mingw-cross-configure.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e23c6ca..49422a3d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,12 +97,34 @@ ENDIF(CMAKE_COMPILER_IS_GNUCC) ADD_DEFINITIONS(-Du_int8_t=uint8_t -Du_int16_t=uint16_t) IF(MINGW) - # force MinGW-w64 in 32bit mode - SET(CMAKE_C_FLAGS "-m32 ${CMAKE_C_FLAGS}") - SET(CMAKE_MODULE_LINKER_FLAGS "-m32 -Wl,--enable-stdcall-fixup ${CMAKE_SHARED_LINKER_FLAGS}") - SET(CMAKE_SHARED_LINKER_FLAGS "-m32 -Wl,--enable-stdcall-fixup ${CMAKE_SHARED_LINKER_FLAGS}") - SET(CMAKE_EXE_LINKER_FLAGS "-m32 -Wl,--enable-stdcall-fixup ${CMAKE_EXE_LINKER_FLAGS}") - SET(CMAKE_RC_FLAGS "--target=pe-i386 --output-format=coff ${CMAKE_RC_FLAGS}") + IF (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + # force MinGW-w64 in 32bit mode + SET(CMAKE_C_FLAGS "-m32 ${CMAKE_C_FLAGS}") + SET(CMAKE_MODULE_LINKER_FLAGS "-m32 -Wl,--enable-stdcall-fixup ${CMAKE_SHARED_LINKER_FLAGS}") + SET(CMAKE_SHARED_LINKER_FLAGS "-m32 -Wl,--enable-stdcall-fixup ${CMAKE_SHARED_LINKER_FLAGS}") + SET(CMAKE_EXE_LINKER_FLAGS "-m32 -Wl,--enable-stdcall-fixup ${CMAKE_EXE_LINKER_FLAGS}") + SET(CMAKE_RC_FLAGS "--target=pe-i386 --output-format=coff ${CMAKE_RC_FLAGS}") + ELSE(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86") + # force MinGW-w64 in 32bit mode + MESSAGE("Building 32-bit Windows DLL") + #SET(CMAKE_C_FLAGS "-m32 ${CMAKE_C_FLAGS}") + #SET(CMAKE_MODULE_LINKER_FLAGS "--Wl,--enable-stdcall-fixup ${CMAKE_SHARED_LINKER_FLAGS}") + #SET(CMAKE_SHARED_LINKER_FLAGS "--Wl,--enable-stdcall-fixup ${CMAKE_SHARED_LINKER_FLAGS}") + #SET(CMAKE_EXE_LINKER_FLAGS "--Wl,--enable-stdcall-fixup ${CMAKE_EXE_LINKER_FLAGS}") + SET(CMAKE_RC_FLAGS "--target=pe-i386 --output-format=coff ${CMAKE_RC_FLAGS}") + ELSEIF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") + MESSAGE("Building 64-bit Windows DLL") + SET(CMAKE_RC_FLAGS "--target=pe-x86-64 --output-format=coff ${CMAKE_RC_FLAGS}") + ELSE(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86") + MESSAGE(FATAL_ERROR "Unknown Processor: ${CMAKE_SYSTEM_PROCESSOR}") + ENDIF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86") + ENDIF(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + + FIND_PROGRAM(DLLTOOL dlltool CMAKE_FIND_ROOT_PATH_BOTH) + IF (NOT DLLTOOL) + MESSAGE(FATAL_ERROR "Could not find dlltool command") + ENDIF (NOT DLLTOOL) ENDIF(MINGW) IF(NOT WIN32) @@ -138,11 +160,18 @@ ENDIF(LIBUSB_INCLUDE_DIRS) # version.rc for Windows IF(WIN32) # Date for filling in rc file information - MACRO (GET_CURRENT_YEAR RESULT) - EXECUTE_PROCESS(COMMAND "cmd" " /C date /T" OUTPUT_VARIABLE ${RESULT}) - STRING(REGEX REPLACE "\n" "" ${RESULT} ${${RESULT}}) - STRING(REGEX REPLACE ".*(..)/(..)/(....).*" "\\3" ${RESULT} ${${RESULT}}) - ENDMACRO (GET_CURRENT_YEAR) + IF (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + MACRO (GET_CURRENT_YEAR RESULT) + EXECUTE_PROCESS(COMMAND "cmd" " /C date /T" OUTPUT_VARIABLE ${RESULT}) + STRING(REGEX REPLACE "\n" "" ${RESULT} ${${RESULT}}) + STRING(REGEX REPLACE ".*(..)/(..)/(....).*" "\\3" ${RESULT} ${${RESULT}}) + ENDMACRO (GET_CURRENT_YEAR) + ELSE(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + MACRO (GET_CURRENT_YEAR RESULT) + EXECUTE_PROCESS(COMMAND "date" "+%Y" OUTPUT_VARIABLE ${RESULT}) + STRING(REGEX REPLACE "\n" "" ${RESULT} ${${RESULT}}) + ENDMACRO (GET_CURRENT_YEAR) + ENDIF(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") GET_CURRENT_YEAR(CURRENT_YEAR) MESSAGE("Year for copyright is " ${CURRENT_YEAR}) diff --git a/libnfc/CMakeLists.txt b/libnfc/CMakeLists.txt index d4a4ec12..e69f6141 100644 --- a/libnfc/CMakeLists.txt +++ b/libnfc/CMakeLists.txt @@ -87,7 +87,7 @@ IF(WIN32) ADD_CUSTOM_COMMAND( OUTPUT libnfc.lib - COMMAND dlltool -d ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/nfc.def -l ${CMAKE_CURRENT_BINARY_DIR}/libnfc.lib ${CMAKE_CURRENT_BINARY_DIR}/libnfc.dll + COMMAND ${DLLTOOL} -d ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/nfc.def -l ${CMAKE_CURRENT_BINARY_DIR}/libnfc.lib ${CMAKE_CURRENT_BINARY_DIR}/libnfc.dll DEPENDS nfc ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/nfc.def ) ADD_CUSTOM_TARGET(win32lib ALL DEPENDS libnfc.lib) diff --git a/mingw-cross-compile.sh b/mingw-cross-compile.sh new file mode 100644 index 00000000..a985770c --- /dev/null +++ b/mingw-cross-compile.sh @@ -0,0 +1,34 @@ +#!/bin/sh +PROJECT_DIR=$(readlink -e $(dirname $0)) +cd "$PROJECT_DIR" + +WITH_USB=1 + +LIBUSB_WIN32_BIN_VERSION="1.2.6.0" +LIBUSB_WIN32_BIN_ARCHIVE="libusb-win32-bin-$LIBUSB_WIN32_BIN_VERSION.zip" +LIBUSB_WIN32_BIN_URL="http://freefr.dl.sourceforge.net/project/libusb-win32/libusb-win32-releases/$LIBUSB_WIN32_BIN_VERSION/$LIBUSB_WIN32_BIN_ARCHIVE" +LIBUSB_WIN32_BIN_DIR="libusb-win32-bin-$LIBUSB_WIN32_BIN_VERSION" + +if [ "$WITH_USB" = "1" ]; then + if [ ! -d $LIBUSB_WIN32_BIN_DIR ]; then + wget -c $LIBUSB_WIN32_BIN_URL + unzip $LIBUSB_WIN32_BIN_ARCHIVE + fi +fi + + +rm -rf build +mkdir build +cd build + + +case $1 in +32*) + mingw32-cmake .. -DLIBUSB_INCLUDE_DIRS="$PROJECT_DIR"/libusb-win32-bin-1.2.6.0/include -DLIBUSB_LIBRARIES="$PROJECT_DIR"/libusb-win32-bin-1.2.6.0/bin/x86/libusb0_x86.dll -DLIBNFC_ROOT_DIR=$PWD/.. -DLIBNFC_SYSCONFDIR='C:\\Program Files (x86)\\libnfc\\config' + mingw32-make;; +64*) + mingw64-cmake .. -DLIBUSB_INCLUDE_DIRS="$PROJECT_DIR"/libusb-win32-bin-1.2.6.0/include -DLIBUSB_LIBRARIES="$PROJECT_DIR"/libusb-win32-bin-1.2.6.0/bin/amd64/libusb0.dll -DLIBNFC_ROOT_DIR=.. -DLIBNFC_SYSCONFDIR='C:\\Program Files\\libnfc\\config' + mingw64-make;; +*) + echo "specify whether to build 32-bit or 64-bit version by supplying 32 or 64 as parameter";; +esac diff --git a/mingw-cross-configure.sh b/mingw-cross-configure.sh deleted file mode 100644 index 13c68451..00000000 --- a/mingw-cross-configure.sh +++ /dev/null @@ -1,91 +0,0 @@ -#!/bin/sh - -WITH_USB=1 - -LIBUSB_WIN32_BIN_VERSION="1.2.6.0" -LIBUSB_WIN32_BIN_ARCHIVE="libusb-win32-bin-$LIBUSB_WIN32_BIN_VERSION.zip" -LIBUSB_WIN32_BIN_URL="http://freefr.dl.sourceforge.net/project/libusb-win32/libusb-win32-releases/$LIBUSB_WIN32_BIN_VERSION/$LIBUSB_WIN32_BIN_ARCHIVE" -LIBUSB_WIN32_BIN_DIR="libusb-win32-bin-$LIBUSB_WIN32_BIN_VERSION" - -if [ "$WITH_USB" = "1" ]; then - if [ ! -d $LIBUSB_WIN32_BIN_DIR ]; then - wget -c $LIBUSB_WIN32_BIN_URL - unzip $LIBUSB_WIN32_BIN_ARCHIVE - fi -fi - -MINGW="${MINGW:=i686-w64-mingw32}" -MINGW_DIR="/usr/$MINGW" - -# Use MinGW binaries before others -#export PATH=$MINGW_DIR/bin:$PATH - -# Set CPATH to MinGW include files -export CPATH=$MINGW_DIR/include -export LD_LIBRARY_PATH=$MINGW_DIR/lib -export LD_RUN_PATH=$MINGW_DIR/lib - -# Force pkg-config to search in cross environement directory -export PKG_CONFIG_LIBDIR=$MINGW_DIR/lib/pkgconfig - -# Stop compilation on first error -export CFLAGS="-Wfatal-errors" - -# Include default MinGW include directory, and libnfc's win32 files -export CFLAGS="$CFLAGS -I$MINGW_DIR/include -I$PWD/contrib/win32" - -if [ "$MINGW" = "i686-w64-mingw32" ]; then - # mingw-64 includes winscard.a and winscard.h - # - # It is not enough to set libpcsclite_LIBS to "-lwinscard", because it is - # forgotten when libnfc is created with libtool. That's why we are setting - # LIBS. - export LIBS="-lwinscard" - - echo "MinGW-w64 ships all requirements libnfc." - echo "Unfortunately the MinGW-w64 header are currently" - echo "buggy. Also, Libtool doesn't support MinGW-w64" - echo "very well." - echo "" - echo "Warning ________________________________________" - echo "You will only be able to compile libnfc.dll, but" - echo "none of the executables (see utils and examples)." - echo "" - # You can fix winbase.h by adding the following lines: - # #include - # #include - # But the problem with Libtool remains. -else - if [ -z "$libpcsclite_LIBS$libpcsclite_CFLAGS" ]; then - echo "Error __________________________________________" - echo "You need to get the PC/SC library from a Windows" - echo "machine and the appropriate header files. Then" - echo "specify libpcsclite_LIBS=.../WinScard.dll and" - echo "libpcsclite_CFLAGS=-I..." - fi - exit 1 -fi - -## Configure to cross-compile using mingw32msvc -if [ "$WITH_USB" = "1" ]; then - # with direct-USB drivers (use libusb-win32) - DRIVERS="all" -else - # with UART divers only (can be tested under wine) - DRIVERS="pn532_uart,arygon" -fi - -if [ ! -x configure ]; then - autoreconf -is -fi - -./configure --target=$MINGW --host=$MINGW \ - --with-drivers=$DRIVERS \ - --with-libusb-win32=$PWD/$LIBUSB_WIN32_BIN_DIR \ - $* - -if [ "$MINGW" = "i686-w64-mingw32" ]; then - # due to the buggy headers from MINGW-64 we always add "contrib/windows.h", - # otherwise some windows types won't be available. - echo "#include \"contrib/windows.h\"" >> config.h -fi From 84c3e8a3baa2b767364803f4238e43aa050feaf0 Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Mon, 30 Jan 2017 21:47:06 +0000 Subject: [PATCH 149/318] Fix number of blocks written. Fix number of written blocks reported. --- utils/nfc-mfultralight.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 4b9f39d0..eeea304c 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -276,7 +276,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid) } } - for (uint32_t page = uiSkippedPages; page <= ((uiBlocks / 4) * 4); page++) { + for (uint32_t page = uiSkippedPages; page <= (((uiBlocks + 1) / 4) * 4); page++) { if ((page == 0x2) && (!write_lock)) { printf("s"); uiSkippedPages++; @@ -309,7 +309,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid) print_success_or_failure(bFailure, &uiWritenPages); } printf("|\n"); - printf("Done, %d of %d pages written (%d pages skipped).\n", uiWritenPages, uiBlocks + 1, uiSkippedPages); + printf("Done, %d of %d pages written (%d pages skipped).\n", uiWritenPages - 1, uiBlocks + 1, uiSkippedPages); return true; } From 7991c7d60ceec0aec3fcbc7a1818e9441951e680 Mon Sep 17 00:00:00 2001 From: Jairo Andres Suarez Date: Tue, 14 Feb 2017 18:47:27 -0500 Subject: [PATCH 150/318] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b03551fd..8cf3c118 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Additionnally, you may need to grant permissions to your user to drive your devi Under GNU/Linux systems, if you use udev, you could use the provided udev rules. e.g. under Debian, Ubuntu, etc. - sudo cp contrib/udev/42-pn53x.rules /lib/udev/rules.d/ + sudo cp contrib/udev/93-pn53x.rules /lib/udev/rules.d/ Under FreeBSD, if you use devd, there is also a rules file: contrib/devd/pn53x.conf. From 295c70911a8f49725b78d6ef1018dda6d1836ca7 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 16 Feb 2017 22:31:10 +0100 Subject: [PATCH 151/318] Restrict MFC Mini detection according to AN10833 --- utils/nfc-mfclassic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 56d5717c..9a8f8b65 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -671,7 +671,7 @@ main(int argc, const char *argv[]) if ((nt.nti.nai.abtAtqa[1] & 0x02) == 0x02) // 4K uiBlocks = 0xff; - else if ((nt.nti.nai.btSak & 0x01) == 0x01) + else if (nt.nti.nai.btSak == 0x09) // 320b uiBlocks = 0x13; else From 372bf37eec1fa35c65cef57d5dcbdb9369134aa3 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 16 Feb 2017 22:32:16 +0100 Subject: [PATCH 152/318] Blacklist pn533_usb to fix issue #391 --- contrib/linux/blacklist-libnfc.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/linux/blacklist-libnfc.conf b/contrib/linux/blacklist-libnfc.conf index e9382b18..40f406fe 100644 --- a/contrib/linux/blacklist-libnfc.conf +++ b/contrib/linux/blacklist-libnfc.conf @@ -1,2 +1,3 @@ blacklist nfc blacklist pn533 +blacklist pm533_usb From e50b18848fee8e079235602dd0701ca5567a49ac Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 16 Feb 2017 23:00:37 +0100 Subject: [PATCH 153/318] Remove spurious mirror_uint8_ts declaration, fix issue #375 --- libnfc/mirror-subr.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libnfc/mirror-subr.h b/libnfc/mirror-subr.h index 2f53bc90..4410bdeb 100644 --- a/libnfc/mirror-subr.h +++ b/libnfc/mirror-subr.h @@ -39,6 +39,5 @@ uint8_t mirror(uint8_t bt); uint32_t mirror32(uint32_t ui32Bits); uint64_t mirror64(uint64_t ui64Bits); -void mirror_uint8_ts(uint8_t *pbts, size_t szLen); #endif // _LIBNFC_MIRROR_SUBR_H_ From 968f59a988323e9cc42c05ea9bf83ac168912375 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 16 Feb 2017 23:05:02 +0100 Subject: [PATCH 154/318] Remove unneeded test, fix issue #376 --- libnfc/nfc-internal.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libnfc/nfc-internal.c b/libnfc/nfc-internal.c index b0beae13..68ecd341 100644 --- a/libnfc/nfc-internal.c +++ b/libnfc/nfc-internal.c @@ -242,7 +242,6 @@ connstring_decode(const nfc_connstring connstring, const char *driver_name, cons int res = sscanf(connstring, format, param0, param1, param2); if (res < 1 || ((0 != strcmp(param0, driver_name)) && - (bus_name != NULL) && (0 != strcmp(param0, bus_name)))) { // Driver name does not match. res = 0; From 20a1b978f356c0601ee0151ec38cf589f0bd68ee Mon Sep 17 00:00:00 2001 From: Emmanuel Dreyfus Date: Tue, 20 Dec 2016 16:46:46 +0100 Subject: [PATCH 155/318] NetBSD definition for CCID ioctl --- libnfc/drivers/acr122_pcsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnfc/drivers/acr122_pcsc.c b/libnfc/drivers/acr122_pcsc.c index 6d7c9e6f..93af3aa2 100644 --- a/libnfc/drivers/acr122_pcsc.c +++ b/libnfc/drivers/acr122_pcsc.c @@ -59,7 +59,7 @@ # define IOCTL_CCID_ESCAPE_SCARD_CTL_CODE SCARD_CTL_CODE(3500) #elif defined(__APPLE__) # define IOCTL_CCID_ESCAPE_SCARD_CTL_CODE (((0x31) << 16) | ((3500) << 2)) -#elif defined (__FreeBSD__) || defined (__OpenBSD__) +#elif defined (__FreeBSD__) || defined (__OpenBSD__) || defined (__NetBSD__) # define IOCTL_CCID_ESCAPE_SCARD_CTL_CODE (((0x31) << 16) | ((3500) << 2)) #elif defined (__linux__) # include From e26fe912fdef38064bd01228c91567466bc2f367 Mon Sep 17 00:00:00 2001 From: Emmanuel Dreyfus Date: Tue, 20 Dec 2016 16:48:06 +0100 Subject: [PATCH 156/318] NetBSD serial ports --- libnfc/buses/uart.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libnfc/buses/uart.c b/libnfc/buses/uart.c index 7f14532c..b9b61218 100644 --- a/libnfc/buses/uart.c +++ b/libnfc/buses/uart.c @@ -77,6 +77,8 @@ const char *serial_ports_device_radix[] = { "tty.SLAB_USBtoUART", "tty.usbserial", "tty.usbmodem", NULL }; # elif defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__FreeBSD_kernel__) const char *serial_ports_device_radix[] = { "cuaU", "cuau", NULL }; +# elif defined (__NetBSD__) +const char *serial_ports_device_radix[] = { "tty0", "ttyC", "ttyS", "ttyU", "ttyY" , NULL }; # elif defined (__linux__) || defined (__CYGWIN__) const char *serial_ports_device_radix[] = { "ttyUSB", "ttyS", "ttyACM", "ttyAMA", "ttyO", NULL }; # else From 11bcf05a75c5ff539dfd0ab008aed583f70c307f Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 16 Feb 2017 23:12:38 +0100 Subject: [PATCH 157/318] Fix typo. Fix issue #377 --- libnfc/nfc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 97451a1f..42d4ab7a 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -645,7 +645,7 @@ nfc_initiator_poll_target(nfc_device *pnd, * @param pnd \a nfc_device struct pointer that represent currently used device * @param ndm desired D.E.P. mode (\a NDM_ACTIVE or \a NDM_PASSIVE for active, respectively passive mode) * @param nbr desired baud rate - * @param ndiInitiator pointer \a nfc_dep_info struct that contains \e NFCID3 and \e General \e Bytes to set to the initiator device (optionnal, can be \e NULL) + * @param pndiInitiator pointer \a nfc_dep_info struct that contains \e NFCID3 and \e General \e Bytes to set to the initiator device (optionnal, can be \e NULL) * @param[out] pnt is a \a nfc_target struct pointer where target information will be put. * @param timeout in milliseconds * @@ -673,7 +673,7 @@ nfc_initiator_select_dep_target(nfc_device *pnd, * @param pnd \a nfc_device struct pointer that represent currently used device * @param ndm desired D.E.P. mode (\a NDM_ACTIVE or \a NDM_PASSIVE for active, respectively passive mode) * @param nbr desired baud rate - * @param ndiInitiator pointer \a nfc_dep_info struct that contains \e NFCID3 and \e General \e Bytes to set to the initiator device (optionnal, can be \e NULL) + * @param pndiInitiator pointer \a nfc_dep_info struct that contains \e NFCID3 and \e General \e Bytes to set to the initiator device (optionnal, can be \e NULL) * @param[out] pnt is a \a nfc_target struct pointer where target information will be put. * @param timeout in milliseconds * From b86b7efb10273e4a53915c3c797757fbf53050ca Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 17 Feb 2017 09:56:31 +0100 Subject: [PATCH 158/318] Fix number of blocks written A strange move changed the way written pages are bound in commit ed62b01a. As a result the last 3 blocks weren't written anymore. --- utils/nfc-mfultralight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 4b9f39d0..cfafad0c 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -276,7 +276,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid) } } - for (uint32_t page = uiSkippedPages; page <= ((uiBlocks / 4) * 4); page++) { + for (uint32_t page = uiSkippedPages; page <= uiBlocks; page++) { if ((page == 0x2) && (!write_lock)) { printf("s"); uiSkippedPages++; From d808802b16f476c3960ffa1b6f4d1cadb7bb389d Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 17 Feb 2017 10:11:34 +0100 Subject: [PATCH 159/318] typos --- utils/nfc-mfultralight.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index cfafad0c..63ea2153 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -98,7 +98,7 @@ read_card(void) { uint32_t page; bool bFailure = false; - uint32_t uiReadedPages = 0; + uint32_t uiReadPages = 0; printf("Reading %d pages |", uiBlocks + 1); @@ -111,13 +111,13 @@ read_card(void) break; } - print_success_or_failure(bFailure, &uiReadedPages); - print_success_or_failure(bFailure, &uiReadedPages); - print_success_or_failure(bFailure, &uiReadedPages); - print_success_or_failure(bFailure, &uiReadedPages); + print_success_or_failure(bFailure, &uiReadPages); + print_success_or_failure(bFailure, &uiReadPages); + print_success_or_failure(bFailure, &uiReadPages); + print_success_or_failure(bFailure, &uiReadPages); } printf("|\n"); - printf("Done, %d of %d pages read.\n", uiReadedPages, uiBlocks + 1); + printf("Done, %d of %d pages read.\n", uiReadPages, uiBlocks + 1); fflush(stdout); return (!bFailure); @@ -234,7 +234,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid) { uint32_t uiBlock = 0; bool bFailure = false; - uint32_t uiWritenPages = 0; + uint32_t uiWrittenPages = 0; uint32_t uiSkippedPages = 0; char buffer[BUFSIZ]; @@ -306,10 +306,10 @@ write_card(bool write_otp, bool write_lock, bool write_uid) if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, page, &mp)) bFailure = true; - print_success_or_failure(bFailure, &uiWritenPages); + print_success_or_failure(bFailure, &uiWrittenPages); } printf("|\n"); - printf("Done, %d of %d pages written (%d pages skipped).\n", uiWritenPages, uiBlocks + 1, uiSkippedPages); + printf("Done, %d of %d pages written (%d pages skipped).\n", uiWrittenPages, uiBlocks + 1, uiSkippedPages); return true; } From db4433f116abb39f0452ac1af077dba5d3a57090 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 17 Feb 2017 10:28:53 +0100 Subject: [PATCH 160/318] CMake: set policy CMP0045 --- cmake/modules/UseDoxygen.cmake | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmake/modules/UseDoxygen.cmake b/cmake/modules/UseDoxygen.cmake index b5c7de15..55584167 100644 --- a/cmake/modules/UseDoxygen.cmake +++ b/cmake/modules/UseDoxygen.cmake @@ -91,8 +91,7 @@ if(DOXYGEN_FOUND AND DOXYFILE_IN) configure_file(${DOXYFILE_IN} Doxyfile ESCAPE_QUOTES IMMEDIATE @ONLY) - get_target_property(DOC_TARGET doc TYPE) - if(NOT DOC_TARGET) + if(NOT TARGET doc) add_custom_target(doc) endif() From 646ab57aceac11bffbb82f6c289a5923577113f6 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 17 Feb 2017 10:31:25 +0100 Subject: [PATCH 161/318] fix typo --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a88c5fe..75966a7e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -233,7 +233,7 @@ ENDIF(WIN32) SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Near Field Communication (NFC) library") SET(CPACK_PACKAGE_VENDOR "Roel Verdult") -SET(CPACK_PACKAGE_CONTACT "Roel Verdul ") +SET(CPACK_PACKAGE_CONTACT "Roel Verdult ") #Readme file IF(WIN32) From c5e8adc1691fb4f7f89e865476a41c80212e9306 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 17 Feb 2017 11:31:13 +0100 Subject: [PATCH 162/318] mfclassic: avoid hardcoded offsets & sizes --- utils/mifare.h | 7 +++++++ utils/nfc-mfclassic.c | 36 ++++++++++++++++++------------------ 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/utils/mifare.h b/utils/mifare.h index f350191e..0e13e6b4 100644 --- a/utils/mifare.h +++ b/utils/mifare.h @@ -72,10 +72,17 @@ struct mifare_param_value { uint8_t abtValue[4]; }; +struct mifare_param_trailer { + uint8_t abtKeyA[6]; + uint8_t abtAccessBits[4]; + uint8_t abtKeyB[6]; +}; + typedef union { struct mifare_param_auth mpa; struct mifare_param_data mpd; struct mifare_param_value mpv; + struct mifare_param_trailer mpt; } mifare_param; // Reset struct alignment to default diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 9a8f8b65..19ef1eb7 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -200,9 +200,9 @@ authenticate(uint32_t uiBlock) // Extract the right key from dump file if (bUseKeyA) - memcpy(mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyA, 6); + memcpy(mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyA, sizeof(mp.mpa.abtKey)); else - memcpy(mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyB, 6); + memcpy(mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyB, sizeof(mp.mpa.abtKey)); // Try to authenticate for the current sector if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) @@ -215,9 +215,9 @@ authenticate(uint32_t uiBlock) memcpy(mp.mpa.abtKey, keys + (key_index * 6), 6); if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) { if (bUseKeyA) - memcpy(mtKeys.amb[uiBlock].mbt.abtKeyA, &mp.mpa.abtKey, 6); + memcpy(mtKeys.amb[uiBlock].mbt.abtKeyA, &mp.mpa.abtKey, sizeof(mtKeys.amb[uiBlock].mbt.abtKeyA)); else - memcpy(mtKeys.amb[uiBlock].mbt.abtKeyB, &mp.mpa.abtKey, 6); + memcpy(mtKeys.amb[uiBlock].mbt.abtKeyB, &mp.mpa.abtKey, sizeof(mtKeys.amb[uiBlock].mbt.abtKeyB)); return true; } if (nfc_initiator_select_passive_target(pnd, nmMifare, nt.nti.nai.abtUid, nt.nti.nai.szUidLen, NULL) <= 0) { @@ -347,12 +347,12 @@ read_card(int read_unlocked) // Try to read out the trailer if (nfc_initiator_mifare_cmd(pnd, MC_READ, iBlock, &mp)) { if (read_unlocked) { - memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, 16); + 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, 6); - memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpd.abtData + 6, 4); - memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, 6); + 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); @@ -363,7 +363,7 @@ read_card(int read_unlocked) if (!bFailure) { // Try to read out the data block if (nfc_initiator_mifare_cmd(pnd, MC_READ, iBlock, &mp)) { - memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, 16); + memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, sizeof(mtDump.amb[iBlock].mbd.abtData)); } else { printf("!\nError: unable to read block 0x%02x\n", iBlock); bFailure = true; @@ -429,14 +429,14 @@ write_card(int write_block_zero) if (is_trailer_block(uiBlock)) { if (bFormatCard) { // Copy the default key and reset the access bits - memcpy(mp.mpd.abtData, default_key, 6); - memcpy(mp.mpd.abtData + 6, default_acl, 4); - memcpy(mp.mpd.abtData + 10, default_key, 6); + 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.mpd.abtData, mtDump.amb[uiBlock].mbt.abtKeyA, 6); - memcpy(mp.mpd.abtData + 6, mtDump.amb[uiBlock].mbt.abtAccessBits, 4); - memcpy(mp.mpd.abtData + 10, mtDump.amb[uiBlock].mbt.abtKeyB, 6); + 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 @@ -454,9 +454,9 @@ write_card(int write_block_zero) if (!bFailure) { // Try to write the data block if (bFormatCard && uiBlock) - memset(mp.mpd.abtData, 0x00, 16); + memset(mp.mpd.abtData, 0x00, sizeof(mp.mpd.abtData)); else - memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, 16); + 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) { @@ -692,7 +692,7 @@ main(int argc, const char *argv[]) magic2 = true; } } - printf("Guessing size: seems to be a %i-byte card\n", (uiBlocks + 1) * 16); + printf("Guessing size: seems to be a %lu-byte card\n", (uiBlocks + 1) * sizeof(mifare_classic_block)); if (bUseKeyFile) { FILE *pfKeys = fopen(argv[5], "rb"); From ff37cdb2be43ae5d381bdbea50c8d8d2b1c7672e Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 17 Feb 2017 12:10:30 +0100 Subject: [PATCH 163/318] Replace deprecated readdir_r by readdir This reverts 262555d5, 7fb53873 and a0b859b2 --- libnfc/buses/i2c.c | 18 ++++++++---------- libnfc/buses/spi.c | 5 +---- libnfc/buses/uart.c | 19 +++++++++---------- libnfc/conf.c | 7 ------- 4 files changed, 18 insertions(+), 31 deletions(-) diff --git a/libnfc/buses/i2c.c b/libnfc/buses/i2c.c index a37372d7..dc1ad1f0 100644 --- a/libnfc/buses/i2c.c +++ b/libnfc/buses/i2c.c @@ -191,29 +191,27 @@ i2c_list_ports(void) size_t szRes = 1; res[0] = NULL; - DIR *dir; - if ((dir = opendir("/dev")) == NULL) { + DIR *pdDir; + if ((pdDir = opendir("/dev")) == NULL) { perror("opendir error: /dev"); return res; } - struct dirent entry; - struct dirent *result; - - while ((readdir_r(dir, &entry, &result) == 0) && (result != NULL)) { + struct dirent *pdDirEnt; + while ((pdDirEnt = readdir(pdDir)) != NULL) { const char **p = i2c_ports_device_radix; while (*p) { - if (!strncmp(entry.d_name, *p, strlen(*p))) { + if (!strncmp(pdDirEnt->d_name, *p, strlen(*p))) { char **res2 = realloc(res, (szRes + 1) * sizeof(char *)); if (!res2) { perror("malloc"); goto oom; } res = res2; - if (!(res[szRes - 1] = malloc(6 + strlen(entry.d_name)))) { + if (!(res[szRes - 1] = malloc(6 + strlen(pdDirEnt->d_name)))) { perror("malloc"); goto oom; } - sprintf(res[szRes - 1], "/dev/%s", entry.d_name); + sprintf(res[szRes - 1], "/dev/%s", pdDirEnt->d_name); szRes++; res[szRes - 1] = NULL; @@ -222,7 +220,7 @@ i2c_list_ports(void) } } oom: - closedir(dir); + closedir(pdDir); return res; } diff --git a/libnfc/buses/spi.c b/libnfc/buses/spi.c index b81c92b7..3d29fd31 100644 --- a/libnfc/buses/spi.c +++ b/libnfc/buses/spi.c @@ -283,10 +283,7 @@ spi_list_ports(void) DIR *pdDir = opendir("/dev"); struct dirent *pdDirEnt; - struct dirent entry; - struct dirent *result; - while ((readdir_r(pdDir, &entry, &result) == 0) && (result != NULL)) { - pdDirEnt = &entry; + while ((pdDirEnt = readdir(pdDir)) != NULL) { #if !defined(__APPLE__) if (!isdigit(pdDirEnt->d_name[strlen(pdDirEnt->d_name) - 1])) continue; diff --git a/libnfc/buses/uart.c b/libnfc/buses/uart.c index b9b61218..61ad87d4 100644 --- a/libnfc/buses/uart.c +++ b/libnfc/buses/uart.c @@ -394,32 +394,31 @@ uart_list_ports(void) size_t szRes = 1; res[0] = NULL; - DIR *dir; - if ((dir = opendir("/dev")) == NULL) { + DIR *pdDir; + if ((pdDir = opendir("/dev")) == NULL) { perror("opendir error: /dev"); return res; } - struct dirent entry; - struct dirent *result; - while ((readdir_r(dir, &entry, &result) == 0) && (result != NULL)) { + struct dirent *pdDirEnt; + while ((pdDirEnt = readdir(pdDir)) != NULL) { #if !defined(__APPLE__) - if (!isdigit(entry.d_name[strlen(entry.d_name) - 1])) + if (!isdigit(pdDirEnt->d_name[strlen(pdDirEnt->d_name) - 1])) continue; #endif const char **p = serial_ports_device_radix; while (*p) { - if (!strncmp(entry.d_name, *p, strlen(*p))) { + if (!strncmp(pdDirEnt->d_name, *p, strlen(*p))) { char **res2 = realloc(res, (szRes + 1) * sizeof(char *)); if (!res2) { perror("malloc"); goto oom; } res = res2; - if (!(res[szRes - 1] = malloc(6 + strlen(entry.d_name)))) { + if (!(res[szRes - 1] = malloc(6 + strlen(pdDirEnt->d_name)))) { perror("malloc"); goto oom; } - sprintf(res[szRes - 1], "/dev/%s", entry.d_name); + sprintf(res[szRes - 1], "/dev/%s", pdDirEnt->d_name); szRes++; res[szRes - 1] = NULL; @@ -428,7 +427,7 @@ uart_list_ports(void) } } oom: - closedir(dir); + closedir(pdDir); return res; } diff --git a/libnfc/conf.c b/libnfc/conf.c index 981e272e..590ca6e3 100644 --- a/libnfc/conf.c +++ b/libnfc/conf.c @@ -265,14 +265,7 @@ conf_devices_load(const char *dirname, nfc_context *context) log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Unable to open directory: %s", dirname); } else { struct dirent *de; -#ifdef WIN32 while ((de = readdir(d)) != NULL) { -#else - struct dirent entry; - struct dirent *result; - while ((readdir_r(d, &entry, &result) == 0) && (result != NULL)) { - de = &entry; -#endif // FIXME add a way to sort devices if (de->d_name[0] != '.') { const size_t filename_len = strlen(de->d_name); From 02c06c8e28c4cce78d8a9daa8588350238a90424 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 18 Feb 2017 01:44:42 +0100 Subject: [PATCH 164/318] Update ChangeLog --- ChangeLog | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/ChangeLog b/ChangeLog index 2a2fe64e..f30964e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,14 +5,54 @@ Fixes: - nfc_emulate_uid: cleaner exit on interrupt - Fix reporting of modulations and baud rates by nfc-scan-device -v - Fix out-of-bounds access in nfc-mfultralight + - Several Cygwin compilation fixes + - Fix comparison when nfc_initiator_target_is_present() with a specified target + - Fix nfc_initiator_poll_target without tag on PN532 + - Export iso14443b* symbols + - Fix udev rule which was executed too early + - Fix improper device name initialization + - Fix setenv()/unsetenv() for Windows + - Fix win32/nfc.def according to nfc.h + - nfc-mfclassic: fix option to tolerate write errors + - nfc-poll: fix card removing check + - nfc-relay-picc: fix wrong open mode for file descriptor Improvements: - Allow ISO14443A to be used at higher baud rates - nfc_initiator_select_passive_target() now checks against reported modulations and baud rates for current device + - More serial devices on MAC OS X + - Add section to README to help to configure libnfc + - Various cmake improvements + - Drop PCRE dependency on Windows + - Remove deprecated readdir_r + - Markdown conversion of the text files + - Add support for SCL3712 + - Add support for ACR1222U-C1 + - Add support for NetBSD + - Add support for PN532 on RPi3 UART + - Add support for cross-compilation of 32b & 64b versions of the library for Windows + - Add pn533_usb to the kernel modules blacklist + - driver i2c: respect proper timing specifications + - driver i2c: add retry on error mechanism + - nfc-mfclassic: improvements fo magic cards + - nfc-mfclassic: add option to specify UID + - nfc-mfsetuid: allow to write complete Block0, instead of only UID + - nfc-mfultralight: add automatic modes and --check-magic + - nfc-mfultralight: add support for magic gen2 cards + - nfc-mfultralight: add option to specify UID Changes: - nfc_get_supported_baud_rate() takes now a "mode" parameter + - New nfc_get_supported_baud_rate_target_mode() + +Special thanks to: + - Jim Anastassiou, Frédéric Bourgeois, Dario Carluccio, Emmanuel Dreyfus, + Julien Ehrhart, S. Fabri, John Galt, Christoph Gritschenberger, + Alexander Inyukhin, Arnaud Kapp, David Kreitschmann, Adam Laurie, Ray Lee, + Maxim Martyanov, Paul Menzel, Boris Moiseev, Yerzhan Mukhamejan, + Olliver Shinagl, Jairo Andres Suarez, Mati Vait, Marcos Vives Del Sol, + Hidde Wieringa, Simon Yorkston, timzi, usk-johnny-s, xantares Feb 24, 2014 - 1.7.1 -------------------- From 4e4438435d53633dd0400122b6167ac5e9d93963 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 18 Feb 2017 01:59:27 +0100 Subject: [PATCH 165/318] Update README about pn533_usb --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a032165f..e8341f51 100644 --- a/README.md +++ b/README.md @@ -178,8 +178,8 @@ Two possible solutions: PN533 USB device on Linux >= 3.1: --------------------------------- -Since Linux kernel version 3.1, two kernel-modules must not be loaded in order -to use libnfc : "nfc" and "pn533". +Since Linux kernel version 3.1, a few kernel-modules must not be loaded in order +to use libnfc : "nfc", "pn533" and "pn533_usb". To prevent kernel from loading automatically these modules, you can blacklist them in a modprobe conf file. This file is provided within libnfc archive: From e8d44f1ee8c83af989776adaabb578f321351b3c Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 18 Feb 2017 13:05:02 +0100 Subject: [PATCH 166/318] typo --- HACKING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HACKING.md b/HACKING.md index da1b244b..27304240 100644 --- a/HACKING.md +++ b/HACKING.md @@ -56,7 +56,7 @@ Here are some directions to get you started: or (shorter version) $ lintian -iIE *deb - 3. Preserve cross-platform compatility + 3. Preserve cross-platform compatibility The source code should remain compilable across various platforms, including some you probably cannot test alone so keep it in mind. From f184407cc57b5cbb8429da39cef640114efd2d60 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 18 Feb 2017 13:05:45 +0100 Subject: [PATCH 167/318] Makefile: fix option for recent astyle --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 413b6de4..6bd9f4cd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -34,7 +34,7 @@ style: find . -name "*.[ch]" -exec astyle --formatted --mode=c --suffix=none \ --indent=spaces=2 --indent-switches --indent-preprocessor \ --keep-one-line-blocks --max-instatement-indent=60 \ - --brackets=linux --pad-oper --unpad-paren --pad-header \ + --style=linux --pad-oper --unpad-paren --pad-header \ --align-pointer=name {} \; cppcheck: From e4df2f33343f6cb1763ff157cfddee275d0dbba2 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 18 Feb 2017 13:05:59 +0100 Subject: [PATCH 168/318] astyle --- contrib/win32/stdlib.c | 16 ++++----- libnfc/buses/spi.c | 2 +- libnfc/buses/uart.c | 2 +- libnfc/chips/pn53x.c | 12 +++---- libnfc/conf.c | 2 +- libnfc/drivers/pn532_i2c.c | 40 +++++++++++------------ libnfc/drivers/pn532_spi.c | 2 +- libnfc/drivers/pn53x_usb.c | 14 ++++---- libnfc/nfc.c | 2 +- test/test_access_storm.c | 2 +- test/test_dep_active.c | 12 +++---- test/test_dep_passive.c | 42 ++++++++++++------------ test/test_device_modes_as_dep.c | 14 ++++---- utils/mifare.c | 10 +++--- utils/nfc-mfclassic.c | 12 +++---- utils/nfc-mfultralight.c | 57 +++++++++++++++++---------------- 16 files changed, 121 insertions(+), 120 deletions(-) diff --git a/contrib/win32/stdlib.c b/contrib/win32/stdlib.c index fc27042a..5a1bd560 100644 --- a/contrib/win32/stdlib.c +++ b/contrib/win32/stdlib.c @@ -37,12 +37,12 @@ //There is no setenv()and unsetenv() in windows,but we can use putenv() instead. int setenv(const char *name, const char *value, int overwrite) { - char* env = getenv(name); + char *env = getenv(name); if ((env && overwrite) || (!env)) { - char* str[32]; - strcpy(str,name); - strcat(str,"="); - strcat(str,value); + char *str[32]; + strcpy(str, name); + strcat(str, "="); + strcat(str, value); return putenv(str); } return -1; @@ -50,8 +50,8 @@ int setenv(const char *name, const char *value, int overwrite) void unsetenv(const char *name) { - char* str[32]; - strcpy(str,name); - strcat(str,"="); + char *str[32]; + strcpy(str, name); + strcat(str, "="); putenv(str); } diff --git a/libnfc/buses/spi.c b/libnfc/buses/spi.c index 3d29fd31..0e68f9b4 100644 --- a/libnfc/buses/spi.c +++ b/libnfc/buses/spi.c @@ -196,7 +196,7 @@ spi_send_receive(spi_port sp, const uint8_t *pbtTx, const size_t szTx, uint8_t * struct spi_ioc_transfer tr_send = { .tx_buf = (unsigned long) pbtTx, .rx_buf = 0, - .len = szTx , + .len = szTx, .delay_usecs = 0, .speed_hz = 0, .bits_per_word = 0, diff --git a/libnfc/buses/uart.c b/libnfc/buses/uart.c index 61ad87d4..ffe64aa5 100644 --- a/libnfc/buses/uart.c +++ b/libnfc/buses/uart.c @@ -78,7 +78,7 @@ const char *serial_ports_device_radix[] = { "tty.SLAB_USBtoUART", "tty.usbserial # elif defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__FreeBSD_kernel__) const char *serial_ports_device_radix[] = { "cuaU", "cuau", NULL }; # elif defined (__NetBSD__) -const char *serial_ports_device_radix[] = { "tty0", "ttyC", "ttyS", "ttyU", "ttyY" , NULL }; +const char *serial_ports_device_radix[] = { "tty0", "ttyC", "ttyS", "ttyU", "ttyY", NULL }; # elif defined (__linux__) || defined (__CYGWIN__) const char *serial_ports_device_radix[] = { "ttyUSB", "ttyS", "ttyACM", "ttyAMA", "ttyO", NULL }; # else diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 4abfefc2..f48fd485 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -611,7 +611,7 @@ pn53x_decode_target_data(const uint8_t *pbtRawData, size_t szRawData, pn53x_type pbtRawData += 2; memcpy(pnti->nji.btId, pbtRawData, 4); break; - // Should not happend... + // Should not happend... case NMT_DEP: return NFC_ECHIP; } @@ -829,7 +829,7 @@ pn53x_set_property_int(struct nfc_device *pnd, const nfc_property property, cons case NP_TIMEOUT_COM: CHIP_DATA(pnd)->timeout_communication = value; return pn53x_RFConfiguration__Various_timings(pnd, pn53x_int_to_timeout(CHIP_DATA(pnd)->timeout_atr), pn53x_int_to_timeout(CHIP_DATA(pnd)->timeout_communication)); - // Following properties are invalid (not integer) + // Following properties are invalid (not integer) case NP_HANDLE_CRC: case NP_HANDLE_PARITY: case NP_ACTIVATE_FIELD: @@ -952,7 +952,7 @@ pn53x_set_property_bool(struct nfc_device *pnd, const nfc_property property, con return res; } return pn53x_write_register(pnd, PN53X_REG_CIU_RxMode, SYMBOL_RX_SPEED, 0x00); - // Following properties are invalid (not boolean) + // Following properties are invalid (not boolean) case NP_TIMEOUT_COMMAND: case NP_TIMEOUT_ATR: case NP_TIMEOUT_COM: @@ -2391,7 +2391,7 @@ pn53x_target_receive_bytes(struct nfc_device *pnd, uint8_t *pbtRx, const size_t return pnd->last_error; } } - // NO BREAK + // NO BREAK case NMT_JEWEL: case NMT_ISO14443B: case NMT_ISO14443BI: @@ -2496,7 +2496,7 @@ pn53x_target_send_bytes(struct nfc_device *pnd, const uint8_t *pbtTx, const size return pnd->last_error; } } - // NO BREAK + // NO BREAK case NMT_JEWEL: case NMT_ISO14443B: case NMT_ISO14443BI: @@ -3215,7 +3215,7 @@ pn53x_nm_to_ptt(const nfc_modulation nm) switch (nm.nmt) { case NMT_ISO14443A: return PTT_MIFARE; - // return PTT_ISO14443_4A_106; + // return PTT_ISO14443_4A_106; case NMT_ISO14443B: switch (nm.nbr) { diff --git a/libnfc/conf.c b/libnfc/conf.c index 590ca6e3..149173a7 100644 --- a/libnfc/conf.c +++ b/libnfc/conf.c @@ -60,7 +60,7 @@ static int escaped_value(const char line[BUFSIZ], int i, char **value) { if (line[i] != '"') - goto FAIL; + goto FAIL; i++; if (line[i] == 0 || line[i] == '\n') goto FAIL; diff --git a/libnfc/drivers/pn532_i2c.c b/libnfc/drivers/pn532_i2c.c index d242df94..67762a11 100644 --- a/libnfc/drivers/pn532_i2c.c +++ b/libnfc/drivers/pn532_i2c.c @@ -120,19 +120,19 @@ static struct timespec __transaction_stop; * @return length (in bytes) of read data, or driver error code (negative value) */ static ssize_t pn532_i2c_read(const i2c_device id, - uint8_t *buf, const size_t len) + uint8_t *buf, const size_t len) { - struct timespec transaction_start, bus_free_time = { 0 }; - ssize_t ret; + struct timespec transaction_start, bus_free_time = { 0 }; + ssize_t ret; - clock_gettime(CLOCK_MONOTONIC, &transaction_start); - bus_free_time.tv_nsec = (PN532_BUS_FREE_TIME * 1000 * 1000) - - (transaction_start.tv_nsec - __transaction_stop.tv_nsec); - nanosleep(&bus_free_time, NULL); + clock_gettime(CLOCK_MONOTONIC, &transaction_start); + bus_free_time.tv_nsec = (PN532_BUS_FREE_TIME * 1000 * 1000) - + (transaction_start.tv_nsec - __transaction_stop.tv_nsec); + nanosleep(&bus_free_time, NULL); - ret = i2c_read(id, buf, len); - clock_gettime(CLOCK_MONOTONIC, &__transaction_stop); - return ret; + ret = i2c_read(id, buf, len); + clock_gettime(CLOCK_MONOTONIC, &__transaction_stop); + return ret; } /** @@ -148,19 +148,19 @@ static ssize_t pn532_i2c_read(const i2c_device id, * @return NFC_SUCCESS on success, otherwise driver error code */ static ssize_t pn532_i2c_write(const i2c_device id, - const uint8_t *buf, const size_t len) + const uint8_t *buf, const size_t len) { - struct timespec transaction_start, bus_free_time = { 0 }; - ssize_t ret; + struct timespec transaction_start, bus_free_time = { 0 }; + ssize_t ret; - clock_gettime(CLOCK_MONOTONIC, &transaction_start); - bus_free_time.tv_nsec = (PN532_BUS_FREE_TIME * 1000 * 1000) - - (transaction_start.tv_nsec - __transaction_stop.tv_nsec); - nanosleep(&bus_free_time, NULL); + clock_gettime(CLOCK_MONOTONIC, &transaction_start); + bus_free_time.tv_nsec = (PN532_BUS_FREE_TIME * 1000 * 1000) - + (transaction_start.tv_nsec - __transaction_stop.tv_nsec); + nanosleep(&bus_free_time, NULL); - ret = i2c_write(id, buf, len); - clock_gettime(CLOCK_MONOTONIC, &__transaction_stop); - return ret; + ret = i2c_write(id, buf, len); + clock_gettime(CLOCK_MONOTONIC, &__transaction_stop); + return ret; } /** diff --git a/libnfc/drivers/pn532_spi.c b/libnfc/drivers/pn532_spi.c index f9ed9db4..39a8b51a 100644 --- a/libnfc/drivers/pn532_spi.c +++ b/libnfc/drivers/pn532_spi.c @@ -433,7 +433,7 @@ pn532_spi_receive(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, int goto error; } - pnd->last_error = spi_send_receive(DRIVER_DATA(pnd)->port, &pn532_spi_cmd_dataread, 1, abtRxBuf , 4, true); + pnd->last_error = spi_send_receive(DRIVER_DATA(pnd)->port, &pn532_spi_cmd_dataread, 1, abtRxBuf, 4, true); if (pnd->last_error < 0) { goto error; diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index d0c9adf1..c9659de6 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -351,7 +351,7 @@ pn53x_usb_open(const nfc_context *context, const nfc_connstring connstring) } switch (DRIVER_DATA(pnd)->model) { - // empirical tuning + // empirical tuning case ASK_LOGO: CHIP_DATA(pnd)->timer_correction = 50; break; @@ -697,12 +697,12 @@ pn53x_usb_set_property_bool(nfc_device *pnd, const nfc_property property, const } break; case SCM_SCL3712: - if (NP_ACTIVATE_FIELD == property) { - // Switch on/off LED according to ACTIVATE_FIELD option - if ((res = pn53x_write_register(pnd, PN53X_SFR_P3, _BV(P32), bEnable ? 0 : _BV(P32))) < 0) - return res; - } - break; + if (NP_ACTIVATE_FIELD == property) { + // Switch on/off LED according to ACTIVATE_FIELD option + if ((res = pn53x_write_register(pnd, PN53X_SFR_P3, _BV(P32), bEnable ? 0 : _BV(P32))) < 0) + return res; + } + break; case NXP_PN531: case NXP_PN533: case SONY_PN531: diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 42d4ab7a..008d2e4d 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -388,7 +388,7 @@ nfc_list_devices(nfc_context *context, nfc_connstring connstrings[], const size_ pndl = pndl->next; } } else if (context->user_defined_device_count == 0) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "Warning: %s" , "user must specify device(s) manually when autoscan is disabled"); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "Warning: %s", "user must specify device(s) manually when autoscan is disabled"); } return device_found; diff --git a/test/test_access_storm.c b/test/test_access_storm.c index c86d855f..deff8021 100644 --- a/test/test_access_storm.c +++ b/test/test_access_storm.c @@ -45,7 +45,7 @@ test_access_storm(void) .nbr = NBR_106, }; res = nfc_initiator_list_passive_targets(device, nm, ant, MAX_TARGET_COUNT); - cut_assert_operator_int(res, >= , 0, cut_message("nfc_initiator_list_passive_targets")); + cut_assert_operator_int(res, >=, 0, cut_message("nfc_initiator_list_passive_targets")); nfc_close(device); } diff --git a/test/test_dep_active.c b/test/test_dep_active.c index ff87f6e1..68a873ca 100644 --- a/test/test_dep_active.c +++ b/test/test_dep_active.c @@ -86,18 +86,18 @@ target_thread(void *arg) uint8_t abtRx[1024]; int res = nfc_target_init(device, &nt, abtRx, sizeof(abtRx), 0); - cut_assert_operator_int(res, > , 0, cut_message("Can't initialize NFC device as target: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >, 0, cut_message("Can't initialize NFC device as target: %s", nfc_strerror(device))); if (res < 0) { thread_res = -1; return (void *) thread_res; } res = nfc_target_receive_bytes(device, abtRx, sizeof(abtRx), 500); - cut_assert_operator_int(res, > , 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >, 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device))); const uint8_t abtAttRx[] = "Hello DEP target!"; cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data")); if (res <= 0) { thread_res = -1; return (void *) thread_res; } const uint8_t abtTx[] = "Hello DEP initiator!"; res = nfc_target_send_bytes(device, abtTx, sizeof(abtTx), 500); - cut_assert_operator_int(res, > , 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >, 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device))); if (res <= 0) { thread_res = -1; return (void *) thread_res; } return (void *) thread_res; @@ -125,7 +125,7 @@ initiator_thread(void *arg) // Active mode printf("=========== INITIATOR %s (Active mode / %s Kbps) =========\n", nfc_device_get_name(device), str_nfc_baud_rate(nbr)); res = nfc_initiator_select_dep_target(device, NDM_ACTIVE, nbr, NULL, &nt, 1000); - cut_assert_operator_int(res, > , 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >, 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device))); cut_assert_equal_int(NMT_DEP, nt.nm.nmt, cut_message("Invalid target modulation")); cut_assert_equal_int(nbr, nt.nm.nbr, cut_message("Invalid target baud rate")); cut_assert_equal_memory("\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA", 10, nt.nti.ndi.abtNFCID3, 10, cut_message("Invalid target NFCID3")); @@ -136,13 +136,13 @@ initiator_thread(void *arg) const uint8_t abtTx[] = "Hello DEP target!"; uint8_t abtRx[1024]; res = nfc_initiator_transceive_bytes(device, abtTx, sizeof(abtTx), abtRx, sizeof(abtRx), 5000); - cut_assert_operator_int(res, >= , 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >=, 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device))); const uint8_t abtAttRx[] = "Hello DEP initiator!"; cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data (as initiator)")); if (res < 0) { thread_res = -1; return (void *) thread_res; } res = nfc_initiator_deselect_target(device); - cut_assert_operator_int(res, >= , 0, cut_message("Can't deselect target: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >=, 0, cut_message("Can't deselect target: %s", nfc_strerror(device))); if (res < 0) { thread_res = -1; return (void *) thread_res; } return (void *) thread_res; diff --git a/test/test_dep_passive.c b/test/test_dep_passive.c index 71d7e3a0..1f7a9276 100644 --- a/test/test_dep_passive.c +++ b/test/test_dep_passive.c @@ -86,12 +86,12 @@ target_thread(void *arg) uint8_t abtRx[1024]; size_t szRx = sizeof(abtRx); int res = nfc_target_init(device, &nt, abtRx, szRx, 0); - cut_assert_operator_int(res, > , 0, cut_message("Can't initialize NFC device as target: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >, 0, cut_message("Can't initialize NFC device as target: %s", nfc_strerror(device))); if (res < 0) { thread_res = -1; return (void *) thread_res; } // First pass res = nfc_target_receive_bytes(device, abtRx, sizeof(abtRx), 500); - cut_assert_operator_int(res, > , 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >, 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device))); const uint8_t abtAttRx[] = "Hello DEP target!"; cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data")); @@ -99,40 +99,40 @@ target_thread(void *arg) const uint8_t abtTx[] = "Hello DEP initiator!"; res = nfc_target_send_bytes(device, abtTx, sizeof(abtTx), 500); - cut_assert_operator_int(res, > , 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >, 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device))); if (res <= 0) { thread_res = -1; return (void *) thread_res; } // Second pass res = nfc_target_receive_bytes(device, abtRx, sizeof(abtRx), 500); - cut_assert_operator_int(res, > , 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >, 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device))); cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data")); if (res <= 0) { thread_res = -1; return (void *) thread_res; } res = nfc_target_send_bytes(device, abtTx, sizeof(abtTx), 500); - cut_assert_operator_int(res, > , 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >, 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device))); if (res <= 0) { thread_res = -1; return (void *) thread_res; } // Third pass res = nfc_target_receive_bytes(device, abtRx, sizeof(abtRx), 500); - cut_assert_operator_int(res, > , 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >, 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device))); cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data")); if (res <= 0) { thread_res = -1; return (void *) thread_res; } res = nfc_target_send_bytes(device, abtTx, sizeof(abtTx), 500); - cut_assert_operator_int(res, > , 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >, 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device))); if (res <= 0) { thread_res = -1; return (void *) thread_res; } // Fourth pass res = nfc_target_receive_bytes(device, abtRx, sizeof(abtRx), 500); - cut_assert_operator_int(res, > , 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >, 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device))); cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data")); if (res <= 0) { thread_res = -1; return (void *) thread_res; } res = nfc_target_send_bytes(device, abtTx, sizeof(abtTx), 500); - cut_assert_operator_int(res, > , 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >, 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device))); if (res <= 0) { thread_res = -1; return (void *) thread_res; } return (void *) thread_res; @@ -160,7 +160,7 @@ initiator_thread(void *arg) // Passive mode / 106Kbps printf("=========== INITIATOR %s (Passive mode / 106Kbps) =========\n", nfc_device_get_name(device)); res = nfc_initiator_select_dep_target(device, NDM_PASSIVE, NBR_106, NULL, &nt, 5000); - cut_assert_operator_int(res, > , 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >, 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device))); cut_assert_equal_int(NMT_DEP, nt.nm.nmt, cut_message("Invalid target modulation")); cut_assert_equal_int(NBR_106, nt.nm.nbr, cut_message("Invalid target baud rate")); cut_assert_equal_memory("\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA", 10, nt.nti.ndi.abtNFCID3, 10, cut_message("Invalid target NFCID3")); @@ -171,20 +171,20 @@ initiator_thread(void *arg) const uint8_t abtTx[] = "Hello DEP target!"; uint8_t abtRx[1024]; res = nfc_initiator_transceive_bytes(device, abtTx, sizeof(abtTx), abtRx, sizeof(abtRx), 500); - cut_assert_operator_int(res, >= , 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >=, 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device))); const uint8_t abtAttRx[] = "Hello DEP initiator!"; cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data")); if (res < 0) { thread_res = -1; return (void *) thread_res; } res = nfc_initiator_deselect_target(device); - cut_assert_operator_int(res, >= , 0, cut_message("Can't deselect target: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >=, 0, cut_message("Can't deselect target: %s", nfc_strerror(device))); if (res < 0) { thread_res = -1; return (void *) thread_res; } // Passive mode / 212Kbps (second pass) printf("=========== INITIATOR %s (Passive mode / 212Kbps) =========\n", nfc_device_get_name(device)); res = nfc_initiator_select_dep_target(device, NDM_PASSIVE, NBR_212, NULL, &nt, 1000); - cut_assert_operator_int(res, > , 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >, 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device))); cut_assert_equal_int(NMT_DEP, nt.nm.nmt, cut_message("Invalid target modulation")); cut_assert_equal_int(NBR_212, nt.nm.nbr, cut_message("Invalid target baud rate")); cut_assert_equal_memory("\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA", 10, nt.nti.ndi.abtNFCID3, 10, cut_message("Invalid target NFCID3")); @@ -193,19 +193,19 @@ initiator_thread(void *arg) if (res <= 0) { thread_res = -1; return (void *) thread_res; } res = nfc_initiator_transceive_bytes(device, abtTx, sizeof(abtTx), abtRx, sizeof(abtRx), 1000); - cut_assert_operator_int(res, >= , 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >=, 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device))); cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data")); if (res < 0) { thread_res = -1; return (void *) thread_res; } res = nfc_initiator_deselect_target(device); - cut_assert_operator_int(res, >= , 0, cut_message("Can't deselect target: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >=, 0, cut_message("Can't deselect target: %s", nfc_strerror(device))); if (res < 0) { thread_res = -1; return (void *) thread_res; } // Passive mode / 212Kbps printf("=========== INITIATOR %s (Passive mode / 212Kbps, second pass) =========\n", nfc_device_get_name(device)); res = nfc_initiator_select_dep_target(device, NDM_PASSIVE, NBR_212, NULL, &nt, 1000); - cut_assert_operator_int(res, > , 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >, 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device))); cut_assert_equal_int(NMT_DEP, nt.nm.nmt, cut_message("Invalid target modulation")); cut_assert_equal_int(NBR_212, nt.nm.nbr, cut_message("Invalid target baud rate")); cut_assert_equal_memory("\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA", 10, nt.nti.ndi.abtNFCID3, 10, cut_message("Invalid target NFCID3")); @@ -214,19 +214,19 @@ initiator_thread(void *arg) if (res <= 0) { thread_res = -1; return (void *) thread_res; } res = nfc_initiator_transceive_bytes(device, abtTx, sizeof(abtTx), abtRx, sizeof(abtRx), 5000); - cut_assert_operator_int(res, >= , 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >=, 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device))); cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data")); if (res < 0) { thread_res = -1; return (void *) thread_res; } res = nfc_initiator_deselect_target(device); - cut_assert_operator_int(res, >= , 0, cut_message("Can't deselect target: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >=, 0, cut_message("Can't deselect target: %s", nfc_strerror(device))); if (res < 0) { thread_res = -1; return (void *) thread_res; } // Passive mode / 424Kbps printf("=========== INITIATOR %s (Passive mode / 424Kbps) =========\n", nfc_device_get_name(device)); res = nfc_initiator_select_dep_target(device, NDM_PASSIVE, NBR_424, NULL, &nt, 1000); - cut_assert_operator_int(res, > , 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >, 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device))); cut_assert_equal_int(NMT_DEP, nt.nm.nmt, cut_message("Invalid target modulation")); cut_assert_equal_int(NBR_424, nt.nm.nbr, cut_message("Invalid target baud rate")); cut_assert_equal_memory("\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA", 10, nt.nti.ndi.abtNFCID3, 10, cut_message("Invalid target NFCID3")); @@ -235,13 +235,13 @@ initiator_thread(void *arg) if (res <= 0) { thread_res = -1; return (void *) thread_res; } res = nfc_initiator_transceive_bytes(device, abtTx, sizeof(abtTx), abtRx, sizeof(abtRx), 5000); - cut_assert_operator_int(res, >= , 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >=, 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device))); cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data")); if (res < 0) { thread_res = -1; return (void *) thread_res; } res = nfc_initiator_deselect_target(device); - cut_assert_operator_int(res, >= , 0, cut_message("Can't deselect target: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >=, 0, cut_message("Can't deselect target: %s", nfc_strerror(device))); if (res < 0) { thread_res = -1; return (void *) thread_res; } return (void *) thread_res; diff --git a/test/test_device_modes_as_dep.c b/test/test_device_modes_as_dep.c index 48ee9b95..7bfd5ef1 100644 --- a/test/test_device_modes_as_dep.c +++ b/test/test_device_modes_as_dep.c @@ -66,7 +66,7 @@ target_thread(void *arg) // 1) nfc_target_init should take target in idle mode int res = nfc_target_init(device, &nt, abtRx, sizeof(abtRx), 500); - cut_assert_operator_int(res, >= , 0, cut_message("Can't initialize NFC device as target: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >=, 0, cut_message("Can't initialize NFC device as target: %s", nfc_strerror(device))); if (res < 0) { thread_res = -1; return (void *) thread_res; } // 2) act as target @@ -92,11 +92,11 @@ target_thread(void *arg) }; sleep(6); res = nfc_target_init(device, &nt1, abtRx, sizeof(abtRx), 0); - cut_assert_operator_int(res, > , 0, cut_message("Can't initialize NFC device as target: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >, 0, cut_message("Can't initialize NFC device as target: %s", nfc_strerror(device))); if (res < 0) { thread_res = -1; return (void *) thread_res; } res = nfc_target_receive_bytes(device, abtRx, sizeof(abtRx), 500); - cut_assert_operator_int(res, > , 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >, 0, cut_message("Can't receive bytes from initiator: %s", nfc_strerror(device))); const uint8_t abtAttRx[] = "Hello DEP target!"; cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data")); @@ -104,7 +104,7 @@ target_thread(void *arg) const uint8_t abtTx[] = "Hello DEP initiator!"; res = nfc_target_send_bytes(device, abtTx, sizeof(abtTx), 500); - cut_assert_operator_int(res, > , 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >, 0, cut_message("Can't send bytes to initiator: %s", nfc_strerror(device))); if (res <= 0) { thread_res = -1; return (void *) thread_res; } // 3) idle mode @@ -144,7 +144,7 @@ initiator_thread(void *arg) // Passive mode / 106Kbps printf("=========== INITIATOR %s (Passive mode / 106Kbps) =========\n", nfc_device_get_name(device)); res = nfc_initiator_poll_dep_target(device, NDM_PASSIVE, NBR_106, NULL, &nt1, 5000); - cut_assert_operator_int(res, > , 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >, 0, cut_message("Can't select any DEP target: %s", nfc_strerror(device))); cut_assert_equal_int(NMT_DEP, nt1.nm.nmt, cut_message("Invalid target modulation")); cut_assert_equal_int(NBR_106, nt1.nm.nbr, cut_message("Invalid target baud rate")); cut_assert_equal_memory("\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA", 10, nt1.nti.ndi.abtNFCID3, 10, cut_message("Invalid target NFCID3")); @@ -155,14 +155,14 @@ initiator_thread(void *arg) const uint8_t abtTx[] = "Hello DEP target!"; uint8_t abtRx[1024]; res = nfc_initiator_transceive_bytes(device, abtTx, sizeof(abtTx), abtRx, sizeof(abtRx), 500); - cut_assert_operator_int(res, >= , 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >=, 0, cut_message("Can't transceive bytes to target: %s", nfc_strerror(device))); const uint8_t abtAttRx[] = "Hello DEP initiator!"; cut_assert_equal_memory(abtAttRx, sizeof(abtAttRx), abtRx, res, cut_message("Invalid received data")); if (res < 0) { thread_res = -1; return (void *) thread_res; } res = nfc_initiator_deselect_target(device); - cut_assert_operator_int(res, >= , 0, cut_message("Can't deselect target: %s", nfc_strerror(device))); + cut_assert_operator_int(res, >=, 0, cut_message("Can't deselect target: %s", nfc_strerror(device))); if (res < 0) { thread_res = -1; return (void *) thread_res; } // 3) As other device should be in idle mode, nfc_initiator_poll_dep_target should return 0 diff --git a/utils/mifare.c b/utils/mifare.c index 5e368fce..1cbf6b15 100644 --- a/utils/mifare.c +++ b/utils/mifare.c @@ -68,31 +68,31 @@ nfc_initiator_mifare_cmd(nfc_device *pnd, const mifare_cmd mc, const uint8_t ui8 abtCmd[1] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff) switch (mc) { - // Read and store command have no parameter + // Read and store command have no parameter case MC_READ: case MC_STORE: szParamLen = 0; break; - // Authenticate command + // Authenticate command case MC_AUTH_A: case MC_AUTH_B: szParamLen = sizeof(struct mifare_param_auth); break; - // Data command + // Data command case MC_WRITE: szParamLen = sizeof(struct mifare_param_data); break; - // Value command + // Value command case MC_DECREMENT: case MC_INCREMENT: case MC_TRANSFER: szParamLen = sizeof(struct mifare_param_value); break; - // Please fix your code, you never should reach this statement + // Please fix your code, you never should reach this statement default: return false; } diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 19ef1eb7..2e03e3f7 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -310,7 +310,7 @@ read_card(int read_unlocked) uint32_t uiReadBlocks = 0; if (read_unlocked) { - //If the user is attempting an unlocked read, but has a direct-write type magic card, they don't + //If the user is attempting an unlocked read, but has a direct-write type magic card, they don't //need to use the R mode. We'll trigger a warning and let them proceed. if (magic2) { printf("Note: This card does not require an unlocked write (R) \n"); @@ -318,11 +318,11 @@ read_card(int read_unlocked) } else { //If User has requested an unlocked read, but we're unable to unlock the card, we'll error out. if (!unlock_card()) { - return false; + return false; } } } - + printf("Reading out %d blocks |", uiBlocks + 1); // Read the card from end to begin for (iBlock = uiBlocks; iBlock >= 0; iBlock--) { @@ -390,7 +390,7 @@ write_card(int write_block_zero) uint32_t uiWriteBlocks = 0; if (write_block_zero) { - //If the user is attempting an unlocked write, but has a direct-write type magic card, they don't + //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. if (magic2) { printf("Note: This card does not require an unlocked write (W) \n"); @@ -398,11 +398,11 @@ write_card(int write_block_zero) } else { //If User has requested an unlocked write, but we're unable to unlock the card, we'll error out. if (!unlock_card()) { - return false; + return false; } } } - + printf("Writing %d blocks |", uiBlocks + 1); // Write the card from begin to end; for (uiBlock = 0; uiBlock <= uiBlocks; uiBlock++) { diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 63ea2153..b89bc43f 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -182,11 +182,12 @@ unlock_card(void) return true; } -static bool check_magic() { - bool bFailure = false; - int uid_data; +static bool check_magic() +{ + bool bFailure = false; + int uid_data; - for (uint32_t page = 0; page <= 1; page++) { + 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 @@ -206,27 +207,27 @@ static bool check_magic() { nfc_initiator_mifare_cmd(pnd, MC_WRITE, page, &mp); } - //Check that the ID is now set to 0x000000000000 - 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; - } - - if (result) { - return true; - } - + //Check that the ID is now set to 0x000000000000 + 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; } - //Initially check if we can unlock via the MF method - if (unlock_card()) { + if (result) { return true; - } else { - return false; } + } + + //Initially check if we can unlock via the MF method + if (unlock_card()) { + return true; + } else { + return false; + } + } static bool @@ -351,7 +352,7 @@ static size_t str_to_uid(const char *str, uint8_t *uid) memset(uid, 0x0, MAX_UID_LEN); i = 0; - while ((*str != '\0') && ((i >> 1) < MAX_UID_LEN) ) { + while ((*str != '\0') && ((i >> 1) < MAX_UID_LEN)) { char nibble[2] = { 0x00, '\n' }; /* for strtol */ nibble[0] = *str++; @@ -391,8 +392,8 @@ main(int argc, const char *argv[]) FILE *pfDump; if (argc < 2) { - print_usage(argv); - exit(EXIT_FAILURE); + print_usage(argv); + exit(EXIT_FAILURE); } DBG("\nChecking arguments and settings\n"); @@ -541,12 +542,12 @@ main(int argc, const char *argv[]) write_card(bOTP, bLock, bUID); } else if (iAction == 3) { if (!check_magic()) { - printf("Card is not magic\n"); - nfc_close(pnd); - nfc_exit(context); - exit(EXIT_FAILURE); + printf("Card is not magic\n"); + nfc_close(pnd); + nfc_exit(context); + exit(EXIT_FAILURE); } else { - printf("Card is magic\n"); + printf("Card is magic\n"); } } From 9a749e1a6671b374f90e178851a7b3168a28eae6 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 18 Feb 2017 16:27:53 +0100 Subject: [PATCH 169/318] arygon: remove unused variable arygon.c:94:22: warning: unused variable 'arygon_error_incomplete_command' [-Wunused-const-variable] static const uint8_t arygon_error_incomplete_command[] = "FF0C0000\x0d\x0a"; ^ --- libnfc/drivers/arygon.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libnfc/drivers/arygon.c b/libnfc/drivers/arygon.c index b69b1295..4eba6b29 100644 --- a/libnfc/drivers/arygon.c +++ b/libnfc/drivers/arygon.c @@ -91,7 +91,6 @@ struct arygon_data { // ARYGON frames static const uint8_t arygon_error_none[] = "FF000000\x0d\x0a"; -static const uint8_t arygon_error_incomplete_command[] = "FF0C0000\x0d\x0a"; static const uint8_t arygon_error_unknown_mode[] = "FF060000\x0d\x0a"; // Prototypes From c815c7a05944b20790495cbc9d650bc304bb872d Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 18 Feb 2017 16:28:22 +0100 Subject: [PATCH 170/318] nfc-mfultralight: remove dead assignment nfc-mfultralight.c:274:7: warning: Value stored to 'bFailure' is never read bFailure = false; ^ ~~~~~ --- utils/nfc-mfultralight.c | 1 - 1 file changed, 1 deletion(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index b89bc43f..a5991766 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -272,7 +272,6 @@ write_card(bool write_otp, bool write_lock, bool write_uid) } else { if (!check_magic()) { printf("\nUnable to unlock card - are you sure the card is magic?\n"); - bFailure = false; return false; } } From 05220537ea13fe37e12e75eafd0ea97e5859a17e Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 18 Feb 2017 17:23:22 +0100 Subject: [PATCH 171/318] i2c: fix struct initialization pn532_i2c.c:125:57: warning: missing field 'tv_nsec' initializer [-Wmissing-field-initializers] struct timespec transaction_start, bus_free_time = { 0 }; ^ pn532_i2c.c:153:57: warning: missing field 'tv_nsec' initializer [-Wmissing-field-initializers] struct timespec transaction_start, bus_free_time = { 0 }; --- libnfc/drivers/pn532_i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libnfc/drivers/pn532_i2c.c b/libnfc/drivers/pn532_i2c.c index 67762a11..a3c0cf46 100644 --- a/libnfc/drivers/pn532_i2c.c +++ b/libnfc/drivers/pn532_i2c.c @@ -122,7 +122,7 @@ static struct timespec __transaction_stop; static ssize_t pn532_i2c_read(const i2c_device id, uint8_t *buf, const size_t len) { - struct timespec transaction_start, bus_free_time = { 0 }; + struct timespec transaction_start, bus_free_time = { 0, 0 }; ssize_t ret; clock_gettime(CLOCK_MONOTONIC, &transaction_start); @@ -150,7 +150,7 @@ static ssize_t pn532_i2c_read(const i2c_device id, static ssize_t pn532_i2c_write(const i2c_device id, const uint8_t *buf, const size_t len) { - struct timespec transaction_start, bus_free_time = { 0 }; + struct timespec transaction_start, bus_free_time = { 0, 0 }; ssize_t ret; clock_gettime(CLOCK_MONOTONIC, &transaction_start); From f2c264d4ae88fab8317190fe7eb7d6eafbbe6832 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 18 Feb 2017 17:29:57 +0100 Subject: [PATCH 172/318] pn53x: avoid warning about uninitialized value (false positive) pn53x.c:1746:15: warning: Function call argument is an uninitialized value *cycles = __pn53x_get_timer(pnd, pbtTxRaw[szTx + 1]); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --- libnfc/chips/pn53x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index f48fd485..db7f741f 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1733,7 +1733,7 @@ pn53x_initiator_transceive_bytes_timed(struct nfc_device *pnd, const uint8_t *pb if (pnd->bCrc) { // We've to compute CRC ourselves to know last byte actually sent uint8_t *pbtTxRaw; - pbtTxRaw = (uint8_t *) malloc(szTx + 2); + pbtTxRaw = (uint8_t *) calloc(szTx + 2, 1); if (!pbtTxRaw) return NFC_ESOFT; memcpy(pbtTxRaw, pbtTx, szTx); From 2033519b0c76f8d78f06d3964805b54082a98226 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 18 Feb 2017 18:08:27 +0100 Subject: [PATCH 173/318] Add asserts to tell static analyzer we know what we're doing... nfc.c:1244:19: warning: Dereference of undefined pointer value for (int i = 0; nmt[i]; i++) { ^~~~~~ nfc.c:1256:23: warning: Dereference of undefined pointer value for (int j = 0; nbr[j]; j++) { ^~~~~~ --- libnfc/nfc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 008d2e4d..70312b88 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -79,6 +79,7 @@ #include #include #include +#include #include @@ -1237,13 +1238,14 @@ static int nfc_device_validate_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_modulation *nm) { int res; - const nfc_modulation_type *nmt; + const nfc_modulation_type *nmt = NULL; if ((res = nfc_device_get_supported_modulation(pnd, mode, &nmt)) < 0) { return res; } + assert(nmt != NULL); for (int i = 0; nmt[i]; i++) { if (nmt[i] == nm->nmt) { - const nfc_baud_rate *nbr; + const nfc_baud_rate *nbr = NULL; if (mode == N_INITIATOR) { if ((res = nfc_device_get_supported_baud_rate(pnd, nmt[i], &nbr)) < 0) { return res; @@ -1253,6 +1255,7 @@ nfc_device_validate_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_m return res; } } + assert(nbr != NULL); for (int j = 0; nbr[j]; j++) { if (nbr[j] == nm->nbr) return NFC_SUCCESS; From 04ef5ca90225aa3eb230d66bbd0717469d9cdf3d Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 18 Feb 2017 20:13:53 +0100 Subject: [PATCH 174/318] Reduce variables scopes --- libnfc/chips/pn53x.c | 8 ++++---- libnfc/drivers/acr122_pcsc.c | 3 +-- libnfc/iso14443-subr.c | 4 ++-- utils/nfc-mfclassic.c | 2 +- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index db7f741f..34cf4adf 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -371,7 +371,6 @@ int pn53x_wrap_frame(const uint8_t *pbtTx, const size_t szTxBits, const uint8_t *pbtTxPar, uint8_t *pbtFrame) { - uint8_t btFrame; uint8_t btData; uint32_t uiBitPos; uint32_t uiDataPos = 0; @@ -398,7 +397,7 @@ pn53x_wrap_frame(const uint8_t *pbtTx, const size_t szTxBits, const uint8_t *pbt // air-bytes = mirror(buffer-byte) + mirror(buffer-byte) + mirror(buffer-byte) + .. while (true) { // Reset the temporary frame byte; - btFrame = 0; + uint8_t btFrame = 0; for (uiBitPos = 0; uiBitPos < 8; uiBitPos++) { // Copy as much data that fits in the frame byte @@ -1466,9 +1465,8 @@ static void __pn53x_init_timer(struct nfc_device *pnd, const uint32_t max_cycles static uint32_t __pn53x_get_timer(struct nfc_device *pnd, const uint8_t last_cmd_byte) { - uint8_t parity; uint8_t counter_hi, counter_lo; - uint16_t counter, u16cycles; + uint16_t counter; uint32_t u32cycles; size_t off = 0; if (CHIP_DATA(pnd)->type == PN533) { @@ -1496,6 +1494,8 @@ static uint32_t __pn53x_get_timer(struct nfc_device *pnd, const uint8_t last_cmd // counter saturated u32cycles = 0xFFFFFFFF; } else { + uint8_t parity; + uint16_t u16cycles; u16cycles = 0xFFFF - counter; u32cycles = u16cycles; u32cycles *= (CHIP_DATA(pnd)->timer_prescaler * 2 + 1); diff --git a/libnfc/drivers/acr122_pcsc.c b/libnfc/drivers/acr122_pcsc.c index 93af3aa2..18751665 100644 --- a/libnfc/drivers/acr122_pcsc.c +++ b/libnfc/drivers/acr122_pcsc.c @@ -400,15 +400,14 @@ acr122_pcsc_receive(nfc_device *pnd, uint8_t *pbtData, const size_t szData, int { // FIXME: timeout is not handled (void) timeout; - int len; - uint8_t abtRxCmd[5] = { 0xFF, 0xC0, 0x00, 0x00 }; if (DRIVER_DATA(pnd)->ioCard.dwProtocol == SCARD_PROTOCOL_T0) { /* * Retrieve the PN532 response. */ DWORD dwRxLen = sizeof(DRIVER_DATA(pnd)->abtRx); + uint8_t abtRxCmd[5] = { 0xFF, 0xC0, 0x00, 0x00 }; abtRxCmd[4] = DRIVER_DATA(pnd)->abtRx[1]; if (SCardTransmit(DRIVER_DATA(pnd)->hCard, &(DRIVER_DATA(pnd)->ioCard), abtRxCmd, sizeof(abtRxCmd), NULL, DRIVER_DATA(pnd)->abtRx, &dwRxLen) != SCARD_S_SUCCESS) { pnd->last_error = NFC_EIO; diff --git a/libnfc/iso14443-subr.c b/libnfc/iso14443-subr.c index 27a1ba72..0f5b2e66 100644 --- a/libnfc/iso14443-subr.c +++ b/libnfc/iso14443-subr.c @@ -47,10 +47,10 @@ void iso14443a_crc(uint8_t *pbtData, size_t szLen, uint8_t *pbtCrc) { - uint8_t bt; uint32_t wCrc = 0x6363; do { + uint8_t bt; bt = *pbtData++; bt = (bt ^ (uint8_t)(wCrc & 0x00FF)); bt = (bt ^ (bt << 4)); @@ -78,10 +78,10 @@ iso14443a_crc_append(uint8_t *pbtData, size_t szLen) void iso14443b_crc(uint8_t *pbtData, size_t szLen, uint8_t *pbtCrc) { - uint8_t bt; uint32_t wCrc = 0xFFFF; do { + uint8_t bt; bt = *pbtData++; bt = (bt ^ (uint8_t)(wCrc & 0x00FF)); bt = (bt ^ (bt << 4)); diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 2e03e3f7..55c2bfe5 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -184,7 +184,6 @@ static bool authenticate(uint32_t uiBlock) { mifare_cmd mc; - uint32_t uiTrailerBlock; // Set the authentication information (uid) memcpy(mp.mpa.abtAuthUid, nt.nti.nai.abtUid + nt.nti.nai.szUidLen - 4, 4); @@ -196,6 +195,7 @@ authenticate(uint32_t uiBlock) if (bUseKeyFile) { // Locate the trailer (with the keys) used for this sector + uint32_t uiTrailerBlock; uiTrailerBlock = get_trailer_block(uiBlock); // Extract the right key from dump file From bf31594410e18b7761d5536d692ea6762871e833 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 18 Feb 2017 21:30:03 +0100 Subject: [PATCH 175/318] conf: close file --- libnfc/conf.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libnfc/conf.c b/libnfc/conf.c index 149173a7..85a49cf0 100644 --- a/libnfc/conf.c +++ b/libnfc/conf.c @@ -168,7 +168,7 @@ parse_line(const char line[BUFSIZ], char **key, char **value) return -1; } -static bool +static void conf_parse_file(const char *filename, void (*conf_keyvalue)(void *data, const char *key, const char *value), void *data) @@ -176,7 +176,7 @@ conf_parse_file(const char *filename, FILE *f = fopen(filename, "r"); if (!f) { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "Unable to open file: %s", filename); - return false; + return; } char line[BUFSIZ]; @@ -200,7 +200,8 @@ conf_parse_file(const char *filename, } } } - return false; + fclose(f); + return; } static void From e119296680fd90aa5f8072577abd57e7237cc72c Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Sun, 19 Feb 2017 12:42:30 +0000 Subject: [PATCH 176/318] Tidier fix for incorrect block write/count as per @doegox --- utils/nfc-mfultralight.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index eeea304c..cfafad0c 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -276,7 +276,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid) } } - for (uint32_t page = uiSkippedPages; page <= (((uiBlocks + 1) / 4) * 4); page++) { + for (uint32_t page = uiSkippedPages; page <= uiBlocks; page++) { if ((page == 0x2) && (!write_lock)) { printf("s"); uiSkippedPages++; @@ -309,7 +309,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid) print_success_or_failure(bFailure, &uiWritenPages); } printf("|\n"); - printf("Done, %d of %d pages written (%d pages skipped).\n", uiWritenPages - 1, uiBlocks + 1, uiSkippedPages); + printf("Done, %d of %d pages written (%d pages skipped).\n", uiWritenPages, uiBlocks + 1, uiSkippedPages); return true; } From c51caf424a6391e6a3014b699f246560ed083c0a Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 27 Feb 2017 17:22:42 +0100 Subject: [PATCH 177/318] nfc-mfultralight: fix failed read reporting and add failed pages count --- utils/nfc-mfultralight.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index a5991766..b12cc486 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -5,11 +5,11 @@ * Copyright (C) 2009 Roel Verdult * Copyright (C) 2009-2013 Romuald Conty * Copyright (C) 2010-2012 Romain Tartière - * Copyright (C) 2010-2013 Philippe Teuwen + * Copyright (C) 2010-2017 Philippe Teuwen * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: - * Copyright (C) 2013 Adam Laurie + * Copyright (C) 2013-2017 Adam Laurie * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -86,11 +86,13 @@ static const nfc_modulation nmMifare = { }; static void -print_success_or_failure(bool bFailure, uint32_t *uiCounter) +print_success_or_failure(bool bFailure, uint32_t *uiOkCounter, uint32_t *uiFailedCounter) { - printf("%c", (bFailure) ? 'x' : '.'); - if (uiCounter) - *uiCounter += (bFailure) ? 0 : 1; + printf("%c", (bFailure) ? 'f' : '.'); + if (uiOkCounter) + *uiOkCounter += (bFailure) ? 0 : 1; + if (uiFailedCounter) + *uiFailedCounter += (bFailure) ? 1 : 0; } static bool @@ -99,6 +101,7 @@ read_card(void) uint32_t page; bool bFailure = false; uint32_t uiReadPages = 0; + uint32_t uiFailedPages = 0; printf("Reading %d pages |", uiBlocks + 1); @@ -108,16 +111,15 @@ read_card(void) memcpy(mtDump.amb[page / 4].mbd.abtData, mp.mpd.abtData, 16); } else { bFailure = true; - break; } - print_success_or_failure(bFailure, &uiReadPages); - print_success_or_failure(bFailure, &uiReadPages); - print_success_or_failure(bFailure, &uiReadPages); - print_success_or_failure(bFailure, &uiReadPages); + print_success_or_failure(bFailure, &uiReadPages, &uiFailedPages); + print_success_or_failure(bFailure, &uiReadPages, &uiFailedPages); + print_success_or_failure(bFailure, &uiReadPages, &uiFailedPages); + print_success_or_failure(bFailure, &uiReadPages, &uiFailedPages); } printf("|\n"); - printf("Done, %d of %d pages read.\n", uiReadPages, uiBlocks + 1); + printf("Done, %d of %d pages read (%d pages failed).\n", uiReadPages, uiBlocks + 1, uiFailedPages); fflush(stdout); return (!bFailure); @@ -237,6 +239,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid) bool bFailure = false; uint32_t uiWrittenPages = 0; uint32_t uiSkippedPages = 0; + uint32_t uiFailedPages = 0; char buffer[BUFSIZ]; @@ -287,7 +290,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid) uiSkippedPages++; continue; } - // Show if the readout went well + // Check if the previous 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) { @@ -305,11 +308,10 @@ write_card(bool write_otp, bool write_lock, bool write_uid) memset(mp.mpd.abtData + 4, 0, 12); if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, page, &mp)) bFailure = true; - - print_success_or_failure(bFailure, &uiWrittenPages); + print_success_or_failure(bFailure, &uiWrittenPages, &uiFailedPages); } printf("|\n"); - printf("Done, %d of %d pages written (%d pages skipped).\n", uiWrittenPages, uiBlocks + 1, uiSkippedPages); + printf("Done, %d of %d pages written (%d pages skipped, %d pages failed).\n", uiWrittenPages, uiBlocks + 1, uiSkippedPages, uiFailedPages); return true; } From 6c44c20ffce6b4f2e725f13fbb3fc49f6ae6d1bf Mon Sep 17 00:00:00 2001 From: Simon Yorkston Date: Wed, 1 Mar 2017 18:41:16 +0100 Subject: [PATCH 178/318] Adding support for 4K magic cards --- examples/nfc-mfsetuid.c | 22 ++++++++++++++++------ utils/nfc-mfclassic.c | 17 ++++++++++------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/examples/nfc-mfsetuid.c b/examples/nfc-mfsetuid.c index dd1e6483..57ebd53e 100644 --- a/examples/nfc-mfsetuid.c +++ b/examples/nfc-mfsetuid.c @@ -365,13 +365,23 @@ main(int argc, char *argv[]) // now reset UID iso14443a_crc_append(abtHalt, 2); transmit_bytes(abtHalt, 4); - transmit_bits(abtUnlock1, 7); - if (format) { - transmit_bytes(abtWipe, 1); - transmit_bytes(abtHalt, 4); - transmit_bits(abtUnlock1, 7); + + if (!transmit_bits(abtUnlock1, 7)) { + printf("Warning: Unlock command [1/2]: failed / not acknowledged.\n"); + } else { + if (format) { + transmit_bytes(abtWipe, 1); + transmit_bytes(abtHalt, 4); + transmit_bits(abtUnlock1, 7); + } + + if (transmit_bytes(abtUnlock2, 1)) { + printf("Card unlocked\n"); + } else { + printf("Warning: Unlock command [2/2]: failed / not acknowledged.\n"); + } } - transmit_bytes(abtUnlock2, 1); + transmit_bytes(abtWrite, 4); transmit_bytes(abtData, 18); if (format) { diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 55c2bfe5..dfa53148 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -70,6 +70,7 @@ static bool bForceKeyFile; static bool bTolerateFailures; static bool bFormatCard; static bool magic2 = false; +static bool unlocked = false; static uint8_t uiBlocks; static uint8_t keys[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -248,12 +249,14 @@ unlock_card(void) transmit_bytes(abtHalt, 4); // now send unlock if (!transmit_bits(abtUnlock1, 7)) { - printf("unlock failure!\n"); - return false; - } - if (!transmit_bytes(abtUnlock2, 1)) { - printf("unlock failure!\n"); - return false; + printf("Warning: Unlock command [1/2]: failed / not acknowledged.\n"); + } else { + if (transmit_bytes(abtUnlock2, 1)) { + printf("Card unlocked\n"); + unlocked = true; + } else { + printf("Warning: Unlock command [2/2]: failed / not acknowledged.\n"); + } } // reset reader @@ -668,7 +671,7 @@ main(int argc, const char *argv[]) print_nfc_target(&nt, false); // Guessing size - if ((nt.nti.nai.abtAtqa[1] & 0x02) == 0x02) + if ((nt.nti.nai.abtAtqa[1] & 0x02) == 0x02 || nt.nti.nai.btSak == 0x18) // 4K uiBlocks = 0xff; else if (nt.nti.nai.btSak == 0x09) From 9ccfba21255521228805b79efb54d3f1d0fb1ea0 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 2 Mar 2017 16:00:51 +0100 Subject: [PATCH 179/318] Update changelog & authors --- AUTHORS | 26 ++++++++++++++++++++++++++ ChangeLog | 1 + 2 files changed, 27 insertions(+) diff --git a/AUTHORS b/AUTHORS index 1ebb8359..efc70744 100644 --- a/AUTHORS +++ b/AUTHORS @@ -2,22 +2,48 @@ Adam Laurie Ahti Legonkov Alex Lian +Alexander Inyukhin Anugrah Redja Kusuma Audrey Diacre +Boris Moiseev +Christoph Gritschenberger +Dario Carluccio +David Kreitschmann Emanuele Bertoldi +Emmanuel Dreyfus Eugeny Boger Francois Kooman +Frank Morgner +Frédéric Bourgeois +Hidde Wieringa +Jairo Andres Suarez Jiapeng Li +Jim Anastassiou +John Galt +Julien Ehrhart Julien Schueller Laurent Latil Ludovic Rousseau Marcello Morena +Marcos Vives Del Sol +Mati Vait +Maxim Martyanov Mike Auty Nobuhiro Iwamatsu +Olliver Schinagl +Paul Menzel Peter Meerwald Philippe Teuwen Pim 't Hart +Ray Lee Roel Verdult Romain Tartiere Romuald Conty +Simon Yorkston +bhack lego +quantum-x +timzi +xantares +xaqq +yerzhanm diff --git a/ChangeLog b/ChangeLog index f30964e2..497d5aa3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -37,6 +37,7 @@ Improvements: - driver i2c: add retry on error mechanism - nfc-mfclassic: improvements fo magic cards - nfc-mfclassic: add option to specify UID + - nfc-mfclassic/nfc-mfsetuid: add support for new gen (1b) of magic 4K cards - nfc-mfsetuid: allow to write complete Block0, instead of only UID - nfc-mfultralight: add automatic modes and --check-magic - nfc-mfultralight: add support for magic gen2 cards From 2d2a664f6ccd32e7dbb8d6a3040c143e9cee5cb5 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 2 Mar 2017 22:03:22 +0100 Subject: [PATCH 180/318] Some systems (e.g. glibc < 2.17) require librt to get clock_gettime --- configure.ac | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configure.ac b/configure.ac index 0e635a55..ad8d34cb 100644 --- a/configure.ac +++ b/configure.ac @@ -125,6 +125,10 @@ AM_CONDITIONAL(SPI_ENABLED, [test x"$spi_required" = x"yes"]) # Enable I2C if AM_CONDITIONAL(I2C_ENABLED, [test x"$i2c_required" = x"yes"]) +if test x"$i2c_required" = x"yes" +then + AC_SEARCH_LIBS([clock_gettime], [rt]) +fi # Documentation (default: no) AC_ARG_ENABLE([doc],AS_HELP_STRING([--enable-doc],[Enable documentation generation.]),[enable_doc=$enableval],[enable_doc="no"]) From b65674a8e3d533dd0b51ef58e7f7779d85c799c9 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 2 Mar 2017 23:42:36 +0100 Subject: [PATCH 181/318] Some systems (e.g. glibc < 2.17) require librt to get clock_gettime -> CMAKE --- CMakeLists.txt | 16 ++++++++++++++++ libnfc/CMakeLists.txt | 4 ++++ 2 files changed, 20 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index f5d1f7a7..76babf29 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,6 +148,22 @@ ENDIF(NOT WIN32) INCLUDE(LibnfcDrivers) +IF(UNIX AND NOT APPLE) + IF(I2C_REQUIRED) + # Inspired from http://cmake.3232098.n2.nabble.com/RFC-cmake-analog-to-AC-SEARCH-LIBS-td7585423.html + INCLUDE (CheckFunctionExists) + INCLUDE (CheckLibraryExists) + CHECK_FUNCTION_EXISTS (clock_gettime HAVE_CLOCK_GETTIME) + IF (NOT HAVE_CLOCK_GETTIME) + CHECK_LIBRARY_EXISTS (rt clock_gettime "" HAVE_CLOCK_GETTIME_IN_RT) + IF (HAVE_CLOCK_GETTIME_IN_RT) + SET(LIBRT_FOUND TRUE) + SET(LIBRT_LIBRARIES "rt") + ENDIF (HAVE_CLOCK_GETTIME_IN_RT) + ENDIF (NOT HAVE_CLOCK_GETTIME) + ENDIF(I2C_REQUIRED) +ENDIF(UNIX AND NOT APPLE) + IF(PCSC_INCLUDE_DIRS) INCLUDE_DIRECTORIES(${PCSC_INCLUDE_DIRS}) LINK_DIRECTORIES(${PCSC_LIBRARY_DIRS}) diff --git a/libnfc/CMakeLists.txt b/libnfc/CMakeLists.txt index e69f6141..79bab5dc 100644 --- a/libnfc/CMakeLists.txt +++ b/libnfc/CMakeLists.txt @@ -79,6 +79,10 @@ IF(LIBUSB_FOUND) TARGET_LINK_LIBRARIES(nfc ${LIBUSB_LIBRARIES}) ENDIF(LIBUSB_FOUND) +IF(LIBRT_FOUND) + TARGET_LINK_LIBRARIES(nfc ${LIBRT_LIBRARIES}) +ENDIF(LIBRT_FOUND) + SET_TARGET_PROPERTIES(nfc PROPERTIES SOVERSION 5 VERSION 5.0.1) IF(WIN32) From 86ce8dff523ef4c5977c1a9dd8afb9eadea374cf Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 3 Mar 2017 18:41:13 +0100 Subject: [PATCH 182/318] Test Travis builds --- .travis.yml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 108298f1..948c756b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,12 @@ -language: cpp +language: c + +compiler: + - clang + - gcc + +env: + - BLD=cmake + - BLD=autoconf addons: apt: @@ -9,9 +17,5 @@ addons: - libcutter-dev script: - - autoreconf -vfi - - ./configure --prefix=$HOME/.local/ - - make -j2 - - make install - - cmake -DCMAKE_INSTALL_PREFIX=~/.local . - - make install -j2 + - if [ $BLD == autoconf ]; then autoreconf -vfi && ./configure --prefix=$HOME/.local/ && make -j2 && make install; fi + - if [ $BLD == cmake ]; then cmake -DCMAKE_INSTALL_PREFIX=~/.local . && make -j2 && make install; fi From 32bb6271083dddcf59f21df3dfe583dc818fd839 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 7 Mar 2017 10:49:25 +0100 Subject: [PATCH 183/318] Fix typo in drivers blacklist, thanks Godfrey Chung --- NEWS.md | 1 + contrib/linux/blacklist-libnfc.conf | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index e3f5411d..0263ccae 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,6 +3,7 @@ New in 1.7.x: API Changes: * nfc_device_get_supported_baud_rate() now takes also "mode" as argument + * New nfc_get_supported_baud_rate_target_mode() New in 1.7.1: diff --git a/contrib/linux/blacklist-libnfc.conf b/contrib/linux/blacklist-libnfc.conf index 40f406fe..343ab942 100644 --- a/contrib/linux/blacklist-libnfc.conf +++ b/contrib/linux/blacklist-libnfc.conf @@ -1,3 +1,3 @@ blacklist nfc blacklist pn533 -blacklist pm533_usb +blacklist pn533_usb From ca96e50e9be0d4c4e461e4a54c089c9cd7660439 Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Wed, 22 Mar 2017 23:05:48 +0000 Subject: [PATCH 184/318] add EV1 password auth to nfc-mfultralight --- utils/nfc-mfultralight.c | 109 ++++++++++++++++++++++++++++++++++----- 1 file changed, 95 insertions(+), 14 deletions(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index b12cc486..cb5e880d 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -72,6 +72,10 @@ static const uint32_t uiBlocks = BLOCK_COUNT; uint8_t abtUnlock1[1] = { 0x40 }; uint8_t abtUnlock2[1] = { 0x43 }; +// EV1 commands +uint8_t abtEV1[3] = { 0x60, 0x00, 0x00 }; +uint8_t abtPWAuth[7] = { 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + //Halt command uint8_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 }; @@ -79,6 +83,7 @@ uint8_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 }; static uint8_t abtRx[MAX_FRAME_LEN]; static int szRxBits; +static int szRx; static const nfc_modulation nmMifare = { .nmt = NMT_ISO14443A, @@ -139,15 +144,14 @@ transmit_bits(const uint8_t *pbtTx, const size_t szTxBits) static bool transmit_bytes(const uint8_t *pbtTx, const size_t szTx) { - int res; - if ((res = nfc_initiator_transceive_bytes(pnd, pbtTx, szTx, abtRx, sizeof(abtRx), 0)) < 0) + if ((szRx = nfc_initiator_transceive_bytes(pnd, pbtTx, szTx, abtRx, sizeof(abtRx), 0)) < 0) return false; return true; } static bool -unlock_card(void) +raw_mode_start(void) { // Configure the CRC if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) { @@ -159,17 +163,12 @@ unlock_card(void) nfc_perror(pnd, "nfc_configure"); return false; } + return true; +} - iso14443a_crc_append(abtHalt, 2); - transmit_bytes(abtHalt, 4); - // now send unlock - if (!transmit_bits(abtUnlock1, 7)) { - return false; - } - if (!transmit_bytes(abtUnlock2, 1)) { - return false; - } - +static bool +raw_mode_end(void) +{ // reset reader // Configure the CRC if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true) < 0) { @@ -184,6 +183,65 @@ unlock_card(void) return true; } +static bool +get_ev1_version(void) +{ + if (!raw_mode_start()) + return false; + iso14443a_crc_append(abtEV1, 1); + if(!transmit_bytes(abtEV1, 3)){ + raw_mode_end(); + return false; + } + if (!raw_mode_end()) + return false; + if(!szRx) + return false; + return true; +} + +static bool +ev1_load_pwd(uint8_t target[4], const char *pwd) +{ + if(sscanf(pwd, "%2x%2x%2x%2x", (unsigned int *) &target[0], (unsigned int *) &target[1], (unsigned int *) &target[2], (unsigned int *) &target[3]) != 4) + return false; + return true; +} + +static bool +ev1_pwd_auth(uint8_t *pwd) +{ + if (!raw_mode_start()) + return false; + memcpy(&abtPWAuth[1], pwd, 4); + iso14443a_crc_append(abtPWAuth, 5); + if(!transmit_bytes(abtPWAuth, 7)) + return false; + if (!raw_mode_end()) + return false; + return true; +} + +static bool +unlock_card(void) +{ + if (!raw_mode_start()) + return false; + iso14443a_crc_append(abtHalt, 2); + transmit_bytes(abtHalt, 4); + // now send unlock + if (!transmit_bits(abtUnlock1, 7)) { + return false; + } + if (!transmit_bytes(abtUnlock2, 1)) { + return false; + } + + if (!raw_mode_end()) + return false; + return true; +} + static bool check_magic() { bool bFailure = false; @@ -379,6 +437,7 @@ print_usage(const char *argv[]) printf("\t--uid\t\t - Don't prompt for UID writing (Assume yes)\n"); printf("\t--full\t\t - Assume full card write (UID + OTP + Lockbit)\n"); printf("\t--with-uid \t\t - Specify UID to read/write from\n"); + printf("\t--pw \t\t - Specify 8 HEX digit PASSWORD for EV1\n"); } int @@ -386,10 +445,12 @@ main(int argc, const char *argv[]) { int iAction = 0; uint8_t iUID[MAX_UID_LEN] = { 0x0 }; + uint8_t iPWD[4] = { 0x0 }; size_t szUID = 0; bool bOTP = false; bool bLock = false; bool bUID = false; + bool bPWD = false; FILE *pfDump; if (argc < 2) { @@ -410,7 +471,7 @@ main(int argc, const char *argv[]) ERR("Please supply a UID of 4, 7 or 10 bytes long. Ex: a1:b2:c3:d4"); exit(EXIT_FAILURE); } - szUID = str_to_uid(argv[4], iUID); + szUID = str_to_uid(argv[++arg], iUID); } else if (0 == strcmp(argv[arg], "--full")) { bOTP = true; bLock = true; @@ -423,6 +484,12 @@ main(int argc, const char *argv[]) bUID = true; } else if (0 == strcmp(argv[arg], "--check-magic")) { iAction = 3; + } else if (0 == strcmp(argv[arg], "--pw")) { + bPWD= true; + if(strlen(argv[++arg]) != 8 || ! ev1_load_pwd(iPWD, argv[arg])) { + ERR("Please supply a PASSWORD of 8 HEX digits"); + exit(EXIT_FAILURE); + } } else { //Skip validation of the filename if ((arg != 2) && (arg != 4)) { @@ -518,6 +585,20 @@ main(int argc, const char *argv[]) } printf("\n"); + // test if tag is EV1 + if(!bPWD) + if(get_ev1_version()) + printf("Tag is EV1 - PASSWORD may be required\n"); + + // EV1 login required + if(bPWD){ + printf("Authing with PWD: %02x%02x%02x%02x\n", iPWD[0], iPWD[1], iPWD[2], iPWD[3]); + if(!ev1_pwd_auth(iPWD)){ + ERR("AUTH failed!\n"); + exit(EXIT_FAILURE); + } + } + if (iAction == 1) { if (read_card()) { printf("Writing data to file: %s ... ", argv[2]); From 3f8bb59f1ef0452cf0241cc2af772320fb9b5367 Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Thu, 23 Mar 2017 11:05:00 +0000 Subject: [PATCH 185/318] show EV1 storage size --- utils/nfc-mfultralight.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index cb5e880d..aaa3206c 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -586,9 +586,17 @@ main(int argc, const char *argv[]) printf("\n"); // test if tag is EV1 - if(!bPWD) - if(get_ev1_version()) + if(get_ev1_version()) { + if(!bPWD) printf("Tag is EV1 - PASSWORD may be required\n"); + printf("EV1 storage size: "); + if(abtRx[6] == 0x0b) + printf("48 bytes\n"); + else if(abtRx[6] == 0x0e) + printf("128 bytes\n"); + else + printf("unknown!\n"); + } // EV1 login required if(bPWD){ From fe04b856788ccb395d43c1e26859b1efd13973c5 Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Thu, 23 Mar 2017 12:03:34 +0000 Subject: [PATCH 186/318] show EV1 auth PACK (tag/reader trust secret) --- utils/nfc-mfultralight.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index aaa3206c..090f3b62 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -600,11 +600,14 @@ main(int argc, const char *argv[]) // EV1 login required if(bPWD){ - printf("Authing with PWD: %02x%02x%02x%02x\n", iPWD[0], iPWD[1], iPWD[2], iPWD[3]); + printf("Authing with PWD: %02x%02x%02x%02x ", iPWD[0], iPWD[1], iPWD[2], iPWD[3]); if(!ev1_pwd_auth(iPWD)){ + printf("\n"); ERR("AUTH failed!\n"); exit(EXIT_FAILURE); } + else + printf("Success - PACK: %02x%02x\n", abtRx[0], abtRx[1]); } if (iAction == 1) { From c04dd91e98977b5581abbfb4e75e26e14d563899 Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Thu, 23 Mar 2017 16:04:02 +0000 Subject: [PATCH 187/318] read extra mf-ul EV1 blocks --- utils/mifare.h | 26 ++++++++++++ utils/nfc-mfultralight.c | 91 ++++++++++++++++++++++++++++------------ 2 files changed, 91 insertions(+), 26 deletions(-) diff --git a/utils/mifare.h b/utils/mifare.h index 0e13e6b4..564b94b0 100644 --- a/utils/mifare.h +++ b/utils/mifare.h @@ -9,6 +9,7 @@ * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: + * Copyright (C) 2017 Adam Laurie * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -133,6 +134,19 @@ typedef struct { uint8_t otp[4]; } mifareul_block_manufacturer; +// MIFARE Ultralight EV1 Config Pages +typedef struct { + uint8_t mod; + uint8_t rfui[2]; + uint8_t auth0; + uint8_t access; + uint8_t vctid; + uint8_t rfui1[2]; + uint8_t pwd[4]; + uint8_t pack[2]; + uint8_t rfui2[2]; +} mifareul_block_config; + typedef struct { uint8_t abtData[16]; } mifareul_block_data; @@ -140,12 +154,24 @@ typedef struct { typedef union { mifareul_block_manufacturer mbm; mifareul_block_data mbd; + mifareul_block_config mbc; } mifareul_block; +// standard UL tag - 1 manuf block + 3 user blocks typedef struct { mifareul_block amb[4]; } mifareul_tag; +// UL EV1 MF0UL11 tag - 1 manuf block + 3 user blocks + 1 config block +typedef struct { + mifareul_block amb[5]; +} mifareul_ev1_mf0ul11_tag; + +// UL EV1 MF0UL21 tag - 1 manuf block + 8 user blocks + 1 config block +typedef struct { + mifareul_block amb[10]; +} mifareul_ev1_mf0ul21_tag; + // Reset struct alignment to default # pragma pack() diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 090f3b62..b4459dbc 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -62,11 +62,19 @@ #define MAX_UID_LEN 10 #define BLOCK_COUNT 0xf +#define EV1_NONE 0 +#define EV1_UL11 1 +#define EV1_UL21 2 + static nfc_device *pnd; static nfc_target nt; static mifare_param mp; -static mifareul_tag mtDump; -static const uint32_t uiBlocks = BLOCK_COUNT; +static mifareul_ev1_mf0ul21_tag mtDump; // use the largest tag type for internal storage +static uint32_t uiBlocks = BLOCK_COUNT; +static uint32_t uiReadPages = 0; +static uint8_t iPWD[4] = { 0x0 }; +static uint8_t iPACK[2] = { 0x0 }; +static uint8_t iEV1Type= EV1_NONE; // special unlock command uint8_t abtUnlock1[1] = { 0x40 }; @@ -105,7 +113,6 @@ read_card(void) { uint32_t page; bool bFailure = false; - uint32_t uiReadPages = 0; uint32_t uiFailedPages = 0; printf("Reading %d pages |", uiBlocks + 1); @@ -127,6 +134,21 @@ read_card(void) printf("Done, %d of %d pages read (%d pages failed).\n", uiReadPages, uiBlocks + 1, uiFailedPages); fflush(stdout); + // copy EV1 secrets to dump data + switch(iEV1Type) { + case EV1_UL11: + memcpy(mtDump.amb[4].mbc.pwd, iPWD, 4); + memcpy(mtDump.amb[4].mbc.pack, iPACK, 2); + break; + case EV1_UL21: + memcpy(mtDump.amb[9].mbc.pwd, iPWD, 4); + memcpy(mtDump.amb[9].mbc.pack, iPACK, 2); + break; + case EV1_NONE: + default: + break; + } + return (!bFailure); } @@ -445,7 +467,6 @@ main(int argc, const char *argv[]) { int iAction = 0; uint8_t iUID[MAX_UID_LEN] = { 0x0 }; - uint8_t iPWD[4] = { 0x0 }; size_t szUID = 0; bool bOTP = false; bool bLock = false; @@ -569,8 +590,8 @@ main(int argc, const char *argv[]) nfc_exit(context); exit(EXIT_FAILURE); } - // Test if we are dealing with a MIFARE compatible tag + // Test if we are dealing with a MIFARE compatible tag if (nt.nti.nai.abtAtqa[1] != 0x44) { ERR("tag is not a MIFARE Ultralight card\n"); nfc_close(pnd); @@ -590,13 +611,28 @@ main(int argc, const char *argv[]) if(!bPWD) printf("Tag is EV1 - PASSWORD may be required\n"); printf("EV1 storage size: "); - if(abtRx[6] == 0x0b) + if(abtRx[6] == 0x0b) { printf("48 bytes\n"); - else if(abtRx[6] == 0x0e) + uiBlocks= 0x13; + iEV1Type= EV1_UL11; + } + else if(abtRx[6] == 0x0e) { printf("128 bytes\n"); + uiBlocks= 0x28; + iEV1Type= EV1_UL21; + } else printf("unknown!\n"); } + else { + // re-init non EV1 tag + if (nfc_initiator_select_passive_target(pnd, nmMifare, (szUID) ? iUID : NULL, szUID, &nt) <= 0) { + ERR("no tag was found\n"); + nfc_close(pnd); + nfc_exit(context); + exit(EXIT_FAILURE); + } + } // EV1 login required if(bPWD){ @@ -606,31 +642,34 @@ main(int argc, const char *argv[]) ERR("AUTH failed!\n"); exit(EXIT_FAILURE); } - else + else { printf("Success - PACK: %02x%02x\n", abtRx[0], abtRx[1]); + memcpy(iPACK, abtRx, 2); + } } if (iAction == 1) { - if (read_card()) { - printf("Writing data to file: %s ... ", argv[2]); - fflush(stdout); - pfDump = fopen(argv[2], "wb"); - if (pfDump == NULL) { - printf("Could not open file: %s\n", argv[2]); - nfc_close(pnd); - nfc_exit(context); - exit(EXIT_FAILURE); - } - if (fwrite(&mtDump, 1, sizeof(mtDump), pfDump) != sizeof(mtDump)) { - printf("Could not write to file: %s\n", argv[2]); - fclose(pfDump); - nfc_close(pnd); - nfc_exit(context); - exit(EXIT_FAILURE); - } + bool bRF= read_card(); + printf("Writing data to file: %s ... ", argv[2]); + fflush(stdout); + pfDump = fopen(argv[2], "wb"); + if (pfDump == NULL) { + printf("Could not open file: %s\n", argv[2]); + nfc_close(pnd); + nfc_exit(context); + exit(EXIT_FAILURE); + } + if (fwrite(&mtDump, 1, uiReadPages * 4, pfDump) != uiReadPages * 4) { + printf("Could not write to file: %s\n", argv[2]); fclose(pfDump); - printf("Done.\n"); + nfc_close(pnd); + nfc_exit(context); + exit(EXIT_FAILURE); } + fclose(pfDump); + printf("Done.\n"); + if(!bRF) + printf("Warning! Read failed - partial data written to file!\n"); } else if (iAction == 2) { write_card(bOTP, bLock, bUID); } else if (iAction == 3) { From 963eb074ecc623506ba68d92879dcb15bf5a8c47 Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Thu, 23 Mar 2017 16:42:10 +0000 Subject: [PATCH 188/318] vary expected dump size based on tag type --- utils/nfc-mfultralight.c | 51 +++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index b4459dbc..72629cab 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -466,6 +466,7 @@ int main(int argc, const char *argv[]) { int iAction = 0; + uint8_t iDumpSize= sizeof(mifareul_tag); uint8_t iUID[MAX_UID_LEN] = { 0x0 }; size_t szUID = 0; bool bOTP = false; @@ -521,30 +522,6 @@ main(int argc, const char *argv[]) } } - if (iAction == 1) { - memset(&mtDump, 0x00, sizeof(mtDump)); - } else if (iAction == 2) { - pfDump = fopen(argv[2], "rb"); - - if (pfDump == NULL) { - ERR("Could not open dump file: %s\n", argv[2]); - exit(EXIT_FAILURE); - } - - if (fread(&mtDump, 1, sizeof(mtDump), pfDump) != sizeof(mtDump)) { - ERR("Could not read from dump file: %s\n", argv[2]); - fclose(pfDump); - exit(EXIT_FAILURE); - } - fclose(pfDump); - DBG("Successfully opened the dump file\n"); - } else if (iAction == 3) { - DBG("Switching to Check Magic Mode\n"); - } else { - ERR("Unable to determine operating mode"); - exit(EXIT_FAILURE); - } - nfc_context *context; nfc_init(&context); if (context == NULL) { @@ -615,11 +592,13 @@ main(int argc, const char *argv[]) printf("48 bytes\n"); uiBlocks= 0x13; iEV1Type= EV1_UL11; + iDumpSize= sizeof(mifareul_ev1_mf0ul11_tag); } else if(abtRx[6] == 0x0e) { printf("128 bytes\n"); uiBlocks= 0x28; iEV1Type= EV1_UL21; + iDumpSize= sizeof(mifareul_ev1_mf0ul21_tag); } else printf("unknown!\n"); @@ -648,6 +627,30 @@ main(int argc, const char *argv[]) } } + if (iAction == 1) { + memset(&mtDump, 0x00, sizeof(mtDump)); + } else if (iAction == 2) { + pfDump = fopen(argv[2], "rb"); + + if (pfDump == NULL) { + ERR("Could not open dump file: %s\n", argv[2]); + exit(EXIT_FAILURE); + } + + if (fread(&mtDump, 1, sizeof(mtDump), pfDump) != iDumpSize) { + ERR("Could not read from dump file or size mismatch: %s\n", argv[2]); + fclose(pfDump); + exit(EXIT_FAILURE); + } + fclose(pfDump); + DBG("Successfully opened the dump file\n"); + } else if (iAction == 3) { + DBG("Switching to Check Magic Mode\n"); + } else { + ERR("Unable to determine operating mode"); + exit(EXIT_FAILURE); + } + if (iAction == 1) { bool bRF= read_card(); printf("Writing data to file: %s ... ", argv[2]); From a9f3e3a2acdea80a7f9790227e1104d146296336 Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Thu, 23 Mar 2017 18:19:59 +0000 Subject: [PATCH 189/318] allow partial writes. tidy up usage. --- utils/nfc-mfultralight.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 72629cab..146f207e 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -451,15 +451,17 @@ static void print_usage(const char *argv[]) { printf("Usage: %s r|w [OPTIONS]\n", argv[0]); + printf("Arguments:\n"); + printf("\tr|w - Perform read or write\n"); + printf("\t - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n"); printf("Options:\n"); - printf("\tr|w\t\t - Perform read or write\n"); - printf("\t\t - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n"); - printf("\t--otp\t\t - Don't prompt for OTP writing (Assume yes)\n"); - printf("\t--lock\t\t - Don't prompt for Lockbit writing (Assume yes)\n"); - printf("\t--uid\t\t - Don't prompt for UID writing (Assume yes)\n"); - printf("\t--full\t\t - Assume full card write (UID + OTP + Lockbit)\n"); - printf("\t--with-uid \t\t - Specify UID to read/write from\n"); - printf("\t--pw \t\t - Specify 8 HEX digit PASSWORD for EV1\n"); + printf("\t--otp - Don't prompt for OTP writing (Assume yes)\n"); + printf("\t--lock - Don't prompt for Lockbit writing (Assume yes)\n"); + printf("\t--uid - Don't prompt for UID writing (Assume yes)\n"); + printf("\t--full - Assume full card write (UID + OTP + Lockbit)\n"); + printf("\t--with-uid - Specify UID to read/write from\n"); + printf("\t--pw - Specify 8 HEX digit PASSWORD for EV1\n"); + printf("\t--partial - Allow source data size to be other than tag capacity\n"); } int @@ -473,6 +475,7 @@ main(int argc, const char *argv[]) bool bLock = false; bool bUID = false; bool bPWD = false; + bool bPart = false; FILE *pfDump; if (argc < 2) { @@ -506,6 +509,8 @@ main(int argc, const char *argv[]) bUID = true; } else if (0 == strcmp(argv[arg], "--check-magic")) { iAction = 3; + } else if (0 == strcmp(argv[arg], "--partial")) { + bPart= true; } else if (0 == strcmp(argv[arg], "--pw")) { bPWD= true; if(strlen(argv[++arg]) != 8 || ! ev1_load_pwd(iPWD, argv[arg])) { @@ -637,11 +642,14 @@ main(int argc, const char *argv[]) exit(EXIT_FAILURE); } - if (fread(&mtDump, 1, sizeof(mtDump), pfDump) != iDumpSize) { + 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\n", argv[2]); fclose(pfDump); exit(EXIT_FAILURE); } + if(szDump != iDumpSize) + printf("Performing partial write\n"); fclose(pfDump); DBG("Successfully opened the dump file\n"); } else if (iAction == 3) { From f2457d0559ef1ab04607c7762477e247faf88987 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 31 Mar 2017 22:46:11 +0200 Subject: [PATCH 190/318] Add pn53x-* to CMakeLists --- examples/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 4c8cf0ba..35a852b3 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -8,6 +8,9 @@ SET(EXAMPLES-SOURCES nfc-mfsetuid nfc-poll nfc-relay + pn53x-diagnose + pn53x-sam + pn53x-tamashell ) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../libnfc) From 560f6a6413c9e6ace8d1cf00205c4b34fe3fd85d Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 31 Mar 2017 23:21:17 +0200 Subject: [PATCH 191/318] nfc-mfultralight: better parameters checks --- utils/nfc-mfultralight.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 146f207e..7b73a8d4 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -476,9 +476,10 @@ main(int argc, const char *argv[]) bool bUID = false; bool bPWD = false; bool bPart = false; + bool bFilename = false; FILE *pfDump; - if (argc < 2) { + if (argc < 3) { print_usage(argv); exit(EXIT_FAILURE); } @@ -492,7 +493,7 @@ main(int argc, const char *argv[]) } else if (0 == strcmp(argv[arg], "w")) { iAction = 2; } else if (0 == strcmp(argv[arg], "--with-uid")) { - if (argc < 5) { + if (arg+1 == argc) { ERR("Please supply a UID of 4, 7 or 10 bytes long. Ex: a1:b2:c3:d4"); exit(EXIT_FAILURE); } @@ -513,19 +514,25 @@ main(int argc, const char *argv[]) bPart= true; } else if (0 == strcmp(argv[arg], "--pw")) { bPWD= true; - if(strlen(argv[++arg]) != 8 || ! ev1_load_pwd(iPWD, argv[arg])) { + if(arg+1 == argc || strlen(argv[++arg]) != 8 || ! ev1_load_pwd(iPWD, argv[arg])) { ERR("Please supply a PASSWORD of 8 HEX digits"); exit(EXIT_FAILURE); } } else { //Skip validation of the filename - if ((arg != 2) && (arg != 4)) { - ERR("%s is not supported option.", argv[arg]); + if (arg != 2) { + ERR("%s is not a supported option.", argv[arg]); print_usage(argv); exit(EXIT_FAILURE); + } else { + bFilename = true; } } } + if (! bFilename) { + ERR("Please supply a Mifare Dump filename"); + exit(EXIT_FAILURE); + } nfc_context *context; nfc_init(&context); From 3ec9ecf8000b326327eb3069399f692c0b3783ea Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 1 Apr 2017 00:25:14 +0200 Subject: [PATCH 192/318] nfc-mfultralight: fix support for MF0UL21 --- utils/mifare.h | 36 +++++++++++++++++++++++++++++------- utils/nfc-mfultralight.c | 37 +++++++++++++++++-------------------- 2 files changed, 46 insertions(+), 27 deletions(-) diff --git a/utils/mifare.h b/utils/mifare.h index 564b94b0..cd6c6f62 100644 --- a/utils/mifare.h +++ b/utils/mifare.h @@ -134,18 +134,38 @@ typedef struct { uint8_t otp[4]; } mifareul_block_manufacturer; -// MIFARE Ultralight EV1 Config Pages +// MIFARE Ultralight EV1 MF0UL11 Config Pages typedef struct { uint8_t mod; - uint8_t rfui[2]; + uint8_t rfui1[2]; uint8_t auth0; uint8_t access; uint8_t vctid; - uint8_t rfui1[2]; + uint8_t rfui2[2]; uint8_t pwd[4]; uint8_t pack[2]; + uint8_t rfui3[2]; +} mifareul_block_config11; + +// MIFARE Ultralight EV1 MF0UL21 ConfigA Pages +typedef struct { + uint8_t lock[3]; + uint8_t rfui0; + uint8_t mod; + uint8_t rfui1[2]; + uint8_t auth0; + uint8_t access; + uint8_t vctid; uint8_t rfui2[2]; -} mifareul_block_config; + uint8_t pwd[4]; +} mifareul_block_config21A; + +// MIFARE Ultralight EV1 MF0UL21 ConfigB Pages +typedef struct { + uint8_t pack[2]; + uint8_t rfui3[2]; + uint8_t dummy[12]; +} mifareul_block_config21B; typedef struct { uint8_t abtData[16]; @@ -154,7 +174,9 @@ typedef struct { typedef union { mifareul_block_manufacturer mbm; mifareul_block_data mbd; - mifareul_block_config mbc; + mifareul_block_config11 mbc11; + mifareul_block_config21A mbc21a; + mifareul_block_config21B mbc21b; } mifareul_block; // standard UL tag - 1 manuf block + 3 user blocks @@ -167,9 +189,9 @@ typedef struct { mifareul_block amb[5]; } mifareul_ev1_mf0ul11_tag; -// UL EV1 MF0UL21 tag - 1 manuf block + 8 user blocks + 1 config block +// UL EV1 MF0UL21 tag - 1 manuf block + 8 user blocks + 1/4 lock block + 1 config block typedef struct { - mifareul_block amb[10]; + mifareul_block amb[11]; } mifareul_ev1_mf0ul21_tag; // Reset struct alignment to default diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 7b73a8d4..737a892c 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -60,7 +60,6 @@ #define MAX_TARGET_COUNT 16 #define MAX_UID_LEN 10 -#define BLOCK_COUNT 0xf #define EV1_NONE 0 #define EV1_UL11 1 @@ -70,7 +69,7 @@ static nfc_device *pnd; static nfc_target nt; static mifare_param mp; static mifareul_ev1_mf0ul21_tag mtDump; // use the largest tag type for internal storage -static uint32_t uiBlocks = BLOCK_COUNT; +static uint32_t uiBlocks = 0x10; static uint32_t uiReadPages = 0; static uint8_t iPWD[4] = { 0x0 }; static uint8_t iPACK[2] = { 0x0 }; @@ -115,34 +114,32 @@ read_card(void) bool bFailure = false; uint32_t uiFailedPages = 0; - printf("Reading %d pages |", uiBlocks + 1); + printf("Reading %d pages |", uiBlocks); - for (page = 0; page <= uiBlocks; page += 4) { + for (page = 0; page < uiBlocks; page += 4) { // Try to read out the data block if (nfc_initiator_mifare_cmd(pnd, MC_READ, page, &mp)) { - memcpy(mtDump.amb[page / 4].mbd.abtData, mp.mpd.abtData, 16); + memcpy(mtDump.amb[page / 4].mbd.abtData, mp.mpd.abtData, uiBlocks - page < 4 ? (uiBlocks - page) * 4 : 16); } else { bFailure = true; } - - print_success_or_failure(bFailure, &uiReadPages, &uiFailedPages); - print_success_or_failure(bFailure, &uiReadPages, &uiFailedPages); - print_success_or_failure(bFailure, &uiReadPages, &uiFailedPages); - print_success_or_failure(bFailure, &uiReadPages, &uiFailedPages); + for (uint8_t i=0; i < (uiBlocks - page < 4 ? uiBlocks - page : 4); i++) { + print_success_or_failure(bFailure, &uiReadPages, &uiFailedPages); + } } printf("|\n"); - printf("Done, %d of %d pages read (%d pages failed).\n", uiReadPages, uiBlocks + 1, uiFailedPages); + printf("Done, %d of %d pages read (%d pages failed).\n", uiReadPages, uiBlocks, uiFailedPages); fflush(stdout); // copy EV1 secrets to dump data switch(iEV1Type) { case EV1_UL11: - memcpy(mtDump.amb[4].mbc.pwd, iPWD, 4); - memcpy(mtDump.amb[4].mbc.pack, iPACK, 2); + memcpy(mtDump.amb[4].mbc11.pwd, iPWD, 4); + memcpy(mtDump.amb[4].mbc11.pack, iPACK, 2); break; case EV1_UL21: - memcpy(mtDump.amb[9].mbc.pwd, iPWD, 4); - memcpy(mtDump.amb[9].mbc.pack, iPACK, 2); + memcpy(mtDump.amb[9].mbc21a.pwd, iPWD, 4); + memcpy(mtDump.amb[9].mbc21b.pack, iPACK, 2); break; case EV1_NONE: default: @@ -347,7 +344,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid) write_uid = ((buffer[0] == 'y') || (buffer[0] == 'Y')); } - printf("Writing %d pages |", uiBlocks + 1); + printf("Writing %d pages |", uiBlocks); /* We may need to skip 2 first pages. */ if (!write_uid) { printf("ss"); @@ -359,7 +356,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid) } } - for (uint32_t page = uiSkippedPages; page <= uiBlocks; page++) { + for (uint32_t page = uiSkippedPages; page < uiBlocks; page++) { if ((page == 0x2) && (!write_lock)) { printf("s"); uiSkippedPages++; @@ -391,7 +388,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid) print_success_or_failure(bFailure, &uiWrittenPages, &uiFailedPages); } printf("|\n"); - printf("Done, %d of %d pages written (%d pages skipped, %d pages failed).\n", uiWrittenPages, uiBlocks + 1, uiSkippedPages, uiFailedPages); + printf("Done, %d of %d pages written (%d pages skipped, %d pages failed).\n", uiWrittenPages, uiBlocks, uiSkippedPages, uiFailedPages); return true; } @@ -602,13 +599,13 @@ main(int argc, const char *argv[]) printf("EV1 storage size: "); if(abtRx[6] == 0x0b) { printf("48 bytes\n"); - uiBlocks= 0x13; + uiBlocks= 0x14; iEV1Type= EV1_UL11; iDumpSize= sizeof(mifareul_ev1_mf0ul11_tag); } else if(abtRx[6] == 0x0e) { printf("128 bytes\n"); - uiBlocks= 0x28; + uiBlocks= 0x29; iEV1Type= EV1_UL21; iDumpSize= sizeof(mifareul_ev1_mf0ul21_tag); } From 024fca9cb7d640223a0734ef1a526894a3c8333c Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 1 Apr 2017 00:46:12 +0200 Subject: [PATCH 193/318] make style --- examples/nfc-mfsetuid.c | 18 +++++------ utils/nfc-mfclassic.c | 12 +++---- utils/nfc-mfultralight.c | 70 +++++++++++++++++++--------------------- 3 files changed, 48 insertions(+), 52 deletions(-) diff --git a/examples/nfc-mfsetuid.c b/examples/nfc-mfsetuid.c index 57ebd53e..3248c6f5 100644 --- a/examples/nfc-mfsetuid.c +++ b/examples/nfc-mfsetuid.c @@ -370,16 +370,16 @@ main(int argc, char *argv[]) printf("Warning: Unlock command [1/2]: failed / not acknowledged.\n"); } else { if (format) { - transmit_bytes(abtWipe, 1); - transmit_bytes(abtHalt, 4); - transmit_bits(abtUnlock1, 7); + transmit_bytes(abtWipe, 1); + transmit_bytes(abtHalt, 4); + transmit_bits(abtUnlock1, 7); + } + + if (transmit_bytes(abtUnlock2, 1)) { + printf("Card unlocked\n"); + } else { + printf("Warning: Unlock command [2/2]: failed / not acknowledged.\n"); } - - if (transmit_bytes(abtUnlock2, 1)) { - printf("Card unlocked\n"); - } else { - printf("Warning: Unlock command [2/2]: failed / not acknowledged.\n"); - } } transmit_bytes(abtWrite, 4); diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index dfa53148..36973ed7 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -251,12 +251,12 @@ unlock_card(void) if (!transmit_bits(abtUnlock1, 7)) { printf("Warning: Unlock command [1/2]: failed / not acknowledged.\n"); } else { - if (transmit_bytes(abtUnlock2, 1)) { - printf("Card unlocked\n"); - unlocked = true; - } else { - printf("Warning: Unlock command [2/2]: failed / not acknowledged.\n"); - } + if (transmit_bytes(abtUnlock2, 1)) { + printf("Card unlocked\n"); + unlocked = true; + } else { + printf("Warning: Unlock command [2/2]: failed / not acknowledged.\n"); + } } // reset reader diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 737a892c..93cbdc11 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -73,7 +73,7 @@ static uint32_t uiBlocks = 0x10; static uint32_t uiReadPages = 0; static uint8_t iPWD[4] = { 0x0 }; static uint8_t iPACK[2] = { 0x0 }; -static uint8_t iEV1Type= EV1_NONE; +static uint8_t iEV1Type = EV1_NONE; // special unlock command uint8_t abtUnlock1[1] = { 0x40 }; @@ -123,7 +123,7 @@ read_card(void) } else { bFailure = true; } - for (uint8_t i=0; i < (uiBlocks - page < 4 ? uiBlocks - page : 4); i++) { + for (uint8_t i = 0; i < (uiBlocks - page < 4 ? uiBlocks - page : 4); i++) { print_success_or_failure(bFailure, &uiReadPages, &uiFailedPages); } } @@ -132,7 +132,7 @@ read_card(void) fflush(stdout); // copy EV1 secrets to dump data - switch(iEV1Type) { + switch (iEV1Type) { case EV1_UL11: memcpy(mtDump.amb[4].mbc11.pwd, iPWD, 4); memcpy(mtDump.amb[4].mbc11.pack, iPACK, 2); @@ -208,21 +208,21 @@ get_ev1_version(void) if (!raw_mode_start()) return false; iso14443a_crc_append(abtEV1, 1); - if(!transmit_bytes(abtEV1, 3)){ + if (!transmit_bytes(abtEV1, 3)) { raw_mode_end(); return false; } if (!raw_mode_end()) return false; - if(!szRx) - return false; + if (!szRx) + return false; return true; } static bool ev1_load_pwd(uint8_t target[4], const char *pwd) { - if(sscanf(pwd, "%2x%2x%2x%2x", (unsigned int *) &target[0], (unsigned int *) &target[1], (unsigned int *) &target[2], (unsigned int *) &target[3]) != 4) + if (sscanf(pwd, "%2x%2x%2x%2x", (unsigned int *) &target[0], (unsigned int *) &target[1], (unsigned int *) &target[2], (unsigned int *) &target[3]) != 4) return false; return true; } @@ -234,7 +234,7 @@ ev1_pwd_auth(uint8_t *pwd) return false; memcpy(&abtPWAuth[1], pwd, 4); iso14443a_crc_append(abtPWAuth, 5); - if(!transmit_bytes(abtPWAuth, 7)) + if (!transmit_bytes(abtPWAuth, 7)) return false; if (!raw_mode_end()) return false; @@ -465,7 +465,7 @@ int main(int argc, const char *argv[]) { int iAction = 0; - uint8_t iDumpSize= sizeof(mifareul_tag); + uint8_t iDumpSize = sizeof(mifareul_tag); uint8_t iUID[MAX_UID_LEN] = { 0x0 }; size_t szUID = 0; bool bOTP = false; @@ -490,7 +490,7 @@ main(int argc, const char *argv[]) } else if (0 == strcmp(argv[arg], "w")) { iAction = 2; } else if (0 == strcmp(argv[arg], "--with-uid")) { - if (arg+1 == argc) { + if (arg + 1 == argc) { ERR("Please supply a UID of 4, 7 or 10 bytes long. Ex: a1:b2:c3:d4"); exit(EXIT_FAILURE); } @@ -508,10 +508,10 @@ main(int argc, const char *argv[]) } else if (0 == strcmp(argv[arg], "--check-magic")) { iAction = 3; } else if (0 == strcmp(argv[arg], "--partial")) { - bPart= true; + bPart = true; } else if (0 == strcmp(argv[arg], "--pw")) { - bPWD= true; - if(arg+1 == argc || strlen(argv[++arg]) != 8 || ! ev1_load_pwd(iPWD, argv[arg])) { + bPWD = true; + if (arg + 1 == argc || strlen(argv[++arg]) != 8 || ! ev1_load_pwd(iPWD, argv[arg])) { ERR("Please supply a PASSWORD of 8 HEX digits"); exit(EXIT_FAILURE); } @@ -593,27 +593,24 @@ main(int argc, const char *argv[]) printf("\n"); // test if tag is EV1 - if(get_ev1_version()) { - if(!bPWD) + if (get_ev1_version()) { + if (!bPWD) printf("Tag is EV1 - PASSWORD may be required\n"); printf("EV1 storage size: "); - if(abtRx[6] == 0x0b) { + if (abtRx[6] == 0x0b) { printf("48 bytes\n"); - uiBlocks= 0x14; - iEV1Type= EV1_UL11; - iDumpSize= sizeof(mifareul_ev1_mf0ul11_tag); - } - else if(abtRx[6] == 0x0e) { + uiBlocks = 0x14; + iEV1Type = EV1_UL11; + iDumpSize = sizeof(mifareul_ev1_mf0ul11_tag); + } else if (abtRx[6] == 0x0e) { printf("128 bytes\n"); - uiBlocks= 0x29; - iEV1Type= EV1_UL21; - iDumpSize= sizeof(mifareul_ev1_mf0ul21_tag); - } - else + uiBlocks = 0x29; + iEV1Type = EV1_UL21; + iDumpSize = sizeof(mifareul_ev1_mf0ul21_tag); + } else printf("unknown!\n"); - } - else { - // re-init non EV1 tag + } else { + // re-init non EV1 tag if (nfc_initiator_select_passive_target(pnd, nmMifare, (szUID) ? iUID : NULL, szUID, &nt) <= 0) { ERR("no tag was found\n"); nfc_close(pnd); @@ -623,14 +620,13 @@ main(int argc, const char *argv[]) } // EV1 login required - if(bPWD){ + if (bPWD) { printf("Authing with PWD: %02x%02x%02x%02x ", iPWD[0], iPWD[1], iPWD[2], iPWD[3]); - if(!ev1_pwd_auth(iPWD)){ + if (!ev1_pwd_auth(iPWD)) { printf("\n"); ERR("AUTH failed!\n"); exit(EXIT_FAILURE); - } - else { + } else { printf("Success - PACK: %02x%02x\n", abtRx[0], abtRx[1]); memcpy(iPACK, abtRx, 2); } @@ -647,12 +643,12 @@ main(int argc, const char *argv[]) } size_t szDump; - if (((szDump= fread(&mtDump, 1, sizeof(mtDump), pfDump)) != iDumpSize && !bPart) || szDump <= 0) { + if (((szDump = fread(&mtDump, 1, sizeof(mtDump), pfDump)) != iDumpSize && !bPart) || szDump <= 0) { ERR("Could not read from dump file or size mismatch: %s\n", argv[2]); fclose(pfDump); exit(EXIT_FAILURE); } - if(szDump != iDumpSize) + if (szDump != iDumpSize) printf("Performing partial write\n"); fclose(pfDump); DBG("Successfully opened the dump file\n"); @@ -664,7 +660,7 @@ main(int argc, const char *argv[]) } if (iAction == 1) { - bool bRF= read_card(); + bool bRF = read_card(); printf("Writing data to file: %s ... ", argv[2]); fflush(stdout); pfDump = fopen(argv[2], "wb"); @@ -683,7 +679,7 @@ main(int argc, const char *argv[]) } fclose(pfDump); printf("Done.\n"); - if(!bRF) + if (!bRF) printf("Warning! Read failed - partial data written to file!\n"); } else if (iAction == 2) { write_card(bOTP, bLock, bUID); From e41a42cf968f9cd2c21473dd6f3217a28acf99ac Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 1 Apr 2017 01:03:41 +0200 Subject: [PATCH 194/318] nfc-mfultralight: avoid compilation warning --- utils/nfc-mfultralight.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 93cbdc11..f77ac6c2 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -222,8 +222,13 @@ get_ev1_version(void) static bool ev1_load_pwd(uint8_t target[4], const char *pwd) { - if (sscanf(pwd, "%2x%2x%2x%2x", (unsigned int *) &target[0], (unsigned int *) &target[1], (unsigned int *) &target[2], (unsigned int *) &target[3]) != 4) + unsigned int tmp[4]; + if (sscanf(pwd, "%2x%2x%2x%2x", &tmp[0], &tmp[1], &tmp[2], &tmp[3]) != 4) return false; + target[0] = tmp[0]; + target[1] = tmp[1]; + target[2] = tmp[2]; + target[3] = tmp[3]; return true; } From fead8d6849fdff315e15992ff90a24f68802ce4a Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 4 Apr 2017 11:10:46 +0200 Subject: [PATCH 195/318] Add missing files to autotools release process --- Makefile.am | 3 +++ cmake/Makefile.am | 5 ++++- contrib/libnfc/Makefile.am | 9 ++++++--- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index 6bd9f4cd..65993c98 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,6 +10,9 @@ pkgconfig_DATA = libnfc.pc EXTRA_DIST = \ CMakeLists.txt \ Doxyfile \ + HACKING.md \ + NEWS.md \ + README.md \ README-Windows.md \ libnfc.conf.sample diff --git a/cmake/Makefile.am b/cmake/Makefile.am index 72c4712c..904f6325 100644 --- a/cmake/Makefile.am +++ b/cmake/Makefile.am @@ -3,4 +3,7 @@ SUBDIRS = modules EXTRA_DIST = \ FixBundle.cmake.in \ config_posix.h.cmake \ - config_windows.h.cmake + config_windows.h.cmake \ + LibNFCConfig.cmake.in \ + LibNFCConfigVersion.cmake.in \ + UseLibNFC.cmake diff --git a/contrib/libnfc/Makefile.am b/contrib/libnfc/Makefile.am index 249f7a12..c2fe16f4 100644 --- a/contrib/libnfc/Makefile.am +++ b/contrib/libnfc/Makefile.am @@ -1,4 +1,7 @@ EXTRA_DIST = \ - pn532_via_uart2usb.conf.sample \ - arygon.conf.sample \ - pn532_uart_on_rpi.conf.sample + arygon.conf.sample \ + pn532_i2c_on_rpi.conf.sample \ + pn532_spi_on_rpi.conf.sample \ + pn532_uart_on_rpi_3.conf.sample \ + pn532_uart_on_rpi.conf.sample \ + pn532_via_uart2usb.conf.sample From b59f8fb3b440f51b8b7d20fbeed39fa71ad3c26e Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 4 Apr 2017 13:31:39 +0200 Subject: [PATCH 196/318] Add more missing files --- Makefile.am | 3 ++- libnfc/Makefile.am | 3 ++- test/Makefile.am | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 65993c98..d2f6fc8e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -14,7 +14,8 @@ EXTRA_DIST = \ NEWS.md \ README.md \ README-Windows.md \ - libnfc.conf.sample + libnfc.conf.sample \ + mingw-cross-compile.sh CLEANFILES = Doxygen.log coverage.info libnfc.pc diff --git a/libnfc/Makefile.am b/libnfc/Makefile.am index dc3f27f2..8ab41916 100644 --- a/libnfc/Makefile.am +++ b/libnfc/Makefile.am @@ -44,4 +44,5 @@ if WITH_LOG endif EXTRA_DIST = \ - CMakeLists.txt + CMakeLists.txt \ + additional-pages.dox diff --git a/test/Makefile.am b/test/Makefile.am index a25af9b3..15cca4c3 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -45,7 +45,7 @@ test_register_endianness_la_LIBADD = $(top_builddir)/libnfc/libnfc.la echo-cutter: @echo $(CUTTER) -EXTRA_DIST = run-test.sh CLEANFILES = *.gcno endif +EXTRA_DIST = run-test.sh From 6235a8a26b412ca60deed6798a5f544a55c2c438 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sun, 16 Apr 2017 00:05:21 +0200 Subject: [PATCH 197/318] Update example script to support PCard --- examples/pn53x-tamashell-scripts/ReadMobib.sh | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/examples/pn53x-tamashell-scripts/ReadMobib.sh b/examples/pn53x-tamashell-scripts/ReadMobib.sh index c4dd43c9..0b90a3c4 100755 --- a/examples/pn53x-tamashell-scripts/ReadMobib.sh +++ b/examples/pn53x-tamashell-scripts/ReadMobib.sh @@ -1,8 +1,10 @@ #!/bin/sh +#DEBUG='//;' + cat << EOF | \ pn53x-tamashell |\ - awk '\ + awk $DEBUG'\ /^> #.*:/{ sub(/^> #/,"") n=$0 @@ -21,27 +23,33 @@ cat << EOF | \ # Select one typeB target 4A010300 +# SELECT AID "1TIC.ICA" +4001 00a4 0400 08 315449432e494341 + # Select ICC file -4001 80a4 0800 04 3f00 0002 +4001 00a4 0000 02 3f00 +4001 00a4 0000 02 0002 #ICC: -4001 80b2 0104 1d +4001 00b2 0104 1d # Select Holder file -4001 80a4 0800 04 3f00 3f1c +4001 00a4 0000 02 3f1c #Holder1: -4001 80b2 0104 1d +4001 00b2 0104 1d #Holder2: -4001 80b2 0204 1d +4001 00b2 0204 1d # Select EnvHol file -4001 00a4 0800 04 2000 2001 +4001 00a4 0000 00 +4001 00a4 0000 02 2000 +4001 00a4 0000 02 2001 #EnvHol1: 4001 00b2 0104 1d #EnvHol2: 4001 00b2 0204 1d # Select EvLog file -4001 00a4 0800 04 2000 2010 +4001 00a4 0000 02 2010 #EvLog1: 4001 00b2 0104 1d #EvLog2: @@ -50,12 +58,12 @@ cat << EOF | \ 4001 00b2 0304 1d # Select ConList file -4001 00a4 0800 04 2000 2050 +4001 00a4 0000 02 2050 #ConList: 4001 00b2 0104 1d # Select Contra file -4001 00a4 0800 04 2000 2020 +4001 00a4 0000 02 2020 #Contra1: 4001 00b2 0104 1d #Contra2: @@ -82,17 +90,19 @@ cat << EOF | \ 4001 00b2 0c04 1d # Select Counter file -4001 00a4 0800 04 2000 2069 +4001 00a4 0000 02 2069 #Counter: 4001 00b2 0104 1d # Select LoadLog file -4001 00a4 0800 04 1000 1014 +4001 00a4 0000 00 +4001 00a4 0000 02 1000 +4001 00a4 0000 02 1014 #LoadLog: 4001 00b2 0104 1d # Select Purcha file -4001 00a4 08 0004 1000 1015 +4001 00a4 0000 02 1015 #Purcha1: 4001 00b2 0104 1d #Purcha2: @@ -101,7 +111,9 @@ cat << EOF | \ 4001 00b2 0304 1d # Select SpecEv file -4001 00a4 08 0004 2000 2040 +4001 00a4 0000 00 +4001 00a4 0000 02 2000 +4001 00a4 0000 02 2040 #SpecEv1: 4001 00b2 0104 1d #SpecEv2: From a06bfe50a59ddde13fd5eb1b76785403afdd80d5 Mon Sep 17 00:00:00 2001 From: Emmanuel Dreyfus Date: Wed, 19 Apr 2017 01:33:40 +0200 Subject: [PATCH 198/318] Workaround missing USB config After a DESfire operation SCL3711 will sometimes enter a state where libusb-0.x is unable to fill config field in struct usb_device. The USB device has to be power-cycled to restore a sane state. This introduce a work around, by using hardcoded values for endpoints and packet size when they are unavailable. --- libnfc/drivers/pn53x_usb.c | 65 ++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index c9659de6..f2327f2f 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -124,16 +124,20 @@ struct pn53x_usb_supported_device { uint16_t product_id; pn53x_usb_model model; const char *name; + /* hardcoded known values for buggy hardware whose configuration vanishes */ + uint32_t uiEndPointIn; + uint32_t uiEndPointOut; + uint32_t uiMaxPacketSize; }; const struct pn53x_usb_supported_device pn53x_usb_supported_devices[] = { - { 0x04CC, 0x0531, NXP_PN531, "Philips / PN531" }, - { 0x04CC, 0x2533, NXP_PN533, "NXP / PN533" }, - { 0x04E6, 0x5591, SCM_SCL3711, "SCM Micro / SCL3711-NFC&RW" }, - { 0x04E6, 0x5594, SCM_SCL3712, "SCM Micro / SCL3712-NFC&RW" }, - { 0x054c, 0x0193, SONY_PN531, "Sony / PN531" }, - { 0x1FD3, 0x0608, ASK_LOGO, "ASK / LoGO" }, - { 0x054C, 0x02E1, SONY_RCS360, "Sony / FeliCa S360 [PaSoRi]" } + { 0x04CC, 0x0531, NXP_PN531, "Philips / PN531", 0, 0, 0 }, + { 0x04CC, 0x2533, NXP_PN533, "NXP / PN533", 0, 0, 0 }, + { 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", 0, 0, 0 }, + { 0x054C, 0x02E1, SONY_RCS360, "Sony / FeliCa S360 [PaSoRi]", 0, 0, 0 } }; static pn53x_usb_model @@ -148,6 +152,25 @@ pn53x_usb_get_device_model(uint16_t vendor_id, uint16_t product_id) return UNKNOWN; } +static void +pn53x_usb_get_end_points_default(struct usb_device *dev, struct pn53x_usb_data *data) +{ + for (size_t n = 0; n < sizeof(pn53x_usb_supported_devices) / sizeof(struct pn53x_usb_supported_device); n++) { + if ((dev->descriptor.idVendor == pn53x_usb_supported_devices[n].vendor_id) && + (dev->descriptor.idProduct == pn53x_usb_supported_devices[n].product_id)) { + if (pn53x_usb_supported_devices[n].uiMaxPacketSize != 0) { + data->uiEndPointIn = pn53x_usb_supported_devices[n].uiEndPointIn; + data->uiEndPointOut = pn53x_usb_supported_devices[n].uiEndPointOut; + data->uiMaxPacketSize = pn53x_usb_supported_devices[n].uiMaxPacketSize; + } + + return; + } + } + + return; +} + int pn53x_usb_ack(nfc_device *pnd); // Find transfer endpoints for bulk transfers @@ -199,13 +222,20 @@ pn53x_usb_scan(const nfc_context *context, nfc_connstring connstrings[], const s (pn53x_usb_supported_devices[n].product_id == dev->descriptor.idProduct)) { // Make sure there are 2 endpoints available // with libusb-win32 we got some null pointers so be robust before looking at endpoints: - if (dev->config == NULL || dev->config->interface == NULL || dev->config->interface->altsetting == NULL) { - // Nope, we maybe want the next one, let's try to find another - continue; - } - if (dev->config->interface->altsetting->bNumEndpoints < 2) { - // Nope, we maybe want the next one, let's try to find another - continue; + if (dev->config == NULL) { + // We tolerate null config if we have defaults + if (pn53x_usb_supported_devices[n].uiMaxPacketSize == 0) + // Nope, we maybe want the next one, let's try to find another + continue; + } else { + if (dev->config->interface == NULL || dev->config->interface->altsetting == NULL) { + // Nope, we maybe want the next one, let's try to find another + continue; + } + if (dev->config->interface->altsetting->bNumEndpoints < 2) { + // Nope, we maybe want the next one, let's try to find another + continue; + } } usb_dev_handle *udev = usb_open(dev); @@ -307,8 +337,11 @@ pn53x_usb_open(const nfc_context *context, const nfc_connstring connstring) // Open the USB device if ((data.pudh = usb_open(dev)) == NULL) continue; - // Retrieve end points - pn53x_usb_get_end_points(dev, &data); + // Retrieve end points, using default if dev->config is broken + if (dev->config == NULL) + pn53x_usb_get_end_points_default(dev, &data); + else + pn53x_usb_get_end_points(dev, &data); // Set configuration int res = usb_set_configuration(data.pudh, 1); if (res < 0) { From c958b2c25d8230a285758a58282cbb7512a6485d Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 19 Apr 2017 20:24:55 +0200 Subject: [PATCH 199/318] Enable missing USB desc workaround for NXP_PN533 too --- libnfc/drivers/pn53x_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index f2327f2f..1c329e1a 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -132,7 +132,7 @@ 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", 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 }, From 38164c49ef085823378716c9c117b3a92ad4c615 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 20 Apr 2017 01:11:28 +0200 Subject: [PATCH 200/318] Fix USB descriptors in SCL3711, NXP_PN533 and ASK LoGO if needed when closing device The problem occurs in the following succession of events: * Emit commands larger than 17 bytes * Re-enumerate USB devices without power cycle, e.g. a warm reboot of the PC The bug can be reproduced for testing purposes with usbreset.c from https://askubuntu.com/questions/645/how-do-you-reset-a-usb-device-from-the-command-line#661 $ lsusb|grep NFC Bus 001 Device 010: ID 04e6:5591 SCM Microsystems, Inc. SCL3711-NFC&RW $ sudo ./usbreset /dev/bus/usb/001/010 Resetting USB device /dev/bus/usb/001/010 Reset successful $ echo 06000000000000000000000000000000000000 |pn53x-tamashell $ sudo ./usbreset /dev/bus/usb/001/010 Resetting USB device /dev/bus/usb/001/010 Error in ioctl: No such device $ lsusb|grep NFC ... device disappeared --- libnfc/drivers/pn53x_usb.c | 114 ++++++++++++++++++++++++++++++++++--- 1 file changed, 107 insertions(+), 7 deletions(-) diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index 1c329e1a..bc4e2bc5 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -5,7 +5,7 @@ * Copyright (C) 2009 Roel Verdult * Copyright (C) 2009-2013 Romuald Conty * Copyright (C) 2010-2012 Romain Tartière - * Copyright (C) 2010-2013 Philippe Teuwen + * Copyright (C) 2010-2017 Philippe Teuwen * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: @@ -81,6 +81,7 @@ struct pn53x_usb_data { uint32_t uiEndPointOut; uint32_t uiMaxPacketSize; volatile bool abort_flag; + bool possibly_corrupted_usbdesc; }; // Internal io struct @@ -136,10 +137,101 @@ const struct pn53x_usb_supported_device pn53x_usb_supported_devices[] = { { 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", 0, 0, 0 }, + { 0x1FD3, 0x0608, ASK_LOGO, "ASK / LoGO", 0x04, 0x84, 40 }, { 0x054C, 0x02E1, SONY_RCS360, "Sony / FeliCa S360 [PaSoRi]", 0, 0, 0 } }; +// PN533 USB descriptors backup buffers + +const uint8_t btXramUsbDesc_scl3711[] = { + 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0x80, 0x32, 0x09, 0x04, 0x00, + 0x00, 0x02, 0xff, 0xff, 0xff, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00, + 0x04, 0x07, 0x05, 0x84, 0x02, 0x40, 0x00, 0x04, 0x1e, 0x03, 0x53, 0x00, + 0x43, 0x00, 0x4c, 0x00, 0x33, 0x00, 0x37, 0x00, 0x31, 0x00, 0x31, 0x00, + 0x2d, 0x00, 0x4e, 0x00, 0x46, 0x00, 0x43, 0x00, 0x26, 0x00, 0x52, 0x00, + 0x57, +}; +const uint8_t btXramUsbDesc_nxppn533[] = { + 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0x80, 0x32, 0x09, 0x04, 0x00, + 0x00, 0x02, 0xff, 0xff, 0xff, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00, + 0x04, 0x07, 0x05, 0x84, 0x02, 0x40, 0x00, 0x04, 0x0c, 0x03, 0x50, 0x00, + 0x4e, 0x00, 0x35, 0x00, 0x33, 0x00, 0x33, 0x00, 0x04, 0x03, 0x09, 0x04, + 0x08, 0x03, 0x4e, 0x00, 0x58, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, +}; +const uint8_t btXramUsbDesc_asklogo[] = { + 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0x80, 0x96, 0x09, 0x04, 0x00, + 0x00, 0x02, 0xff, 0xff, 0xff, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00, + 0x04, 0x07, 0x05, 0x84, 0x02, 0x40, 0x00, 0x04, 0x0a, 0x03, 0x4c, 0x00, + 0x6f, 0x00, 0x47, 0x00, 0x4f, 0x00, 0x04, 0x03, 0x09, 0x04, 0x08, 0x03, + 0x41, 0x00, 0x53, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, +}; + +static void pn533_fix_usbdesc(nfc_device *pnd) +{ + // PN533 USB descriptors may have been corrupted by large commands/responses + // so they need to be restored before closing usb connection. + // cf PN5331B3HNC270 Release Note + uint32_t szXramUsbDesc = 0; + uint8_t *btXramUsbDesc = NULL; + if (DRIVER_DATA(pnd)->model == NXP_PN533) { + btXramUsbDesc = (uint8_t *)btXramUsbDesc_nxppn533; + szXramUsbDesc = sizeof(btXramUsbDesc_nxppn533); + } else if (DRIVER_DATA(pnd)->model == SCM_SCL3711) { + btXramUsbDesc = (uint8_t *)btXramUsbDesc_scl3711; + szXramUsbDesc = sizeof(btXramUsbDesc_scl3711); + } else if (DRIVER_DATA(pnd)->model == ASK_LOGO) { + btXramUsbDesc = (uint8_t *)btXramUsbDesc_asklogo; + szXramUsbDesc = sizeof(btXramUsbDesc_asklogo); + } + if (szXramUsbDesc == 0) + return; + /* + // Debug routine to check if corruption occurred: + // Don't read more regs at once or it will trigger the bug and corrupt what we're busy reading! + uint8_t abtCmdRR[] = { ReadRegister, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t nRRreg = ((sizeof(abtCmdRR) - 1) / 2); + uint8_t abtRxRR[1 + nRRreg]; + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "%s", "Checking USB descriptors corruption in XRAM"); + for (uint8_t i = 0x19, j = 0; i < 0x19 + szXramUsbDesc;) { + for (uint8_t k = 0; k < nRRreg; k++) { + abtCmdRR[(2 * k) + 2] = i++; + } + if (pn53x_transceive(pnd, abtCmdRR, sizeof(abtCmdRR), abtRxRR, sizeof(abtRxRR), -1) < 0) { + return; // void + } + for (int k = 0; (k < nRRreg) && (j < szXramUsbDesc); k++) { + //printf("0x%02x, ", abtRxRR[1 + k]); + if (btXramUsbDesc[j] != abtRxRR[1 + k]) + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "XRAM corruption @ addr 0x00%02X: got %02x, expected %02x", 0x0019 + (j - 1), abtRxRR[1 + k], btXramUsbDesc[j]); + j++; + } + } + */ + // Restore USB descriptors + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "%s", "Fixing USB descriptors corruption"); + // Don't write more regs at once or it will trigger the bug and corrupt what we're busy reading! + uint8_t abtCmdWR[] = { WriteRegister, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + size_t szCmdWR = sizeof(abtCmdWR); + uint8_t nWRreg = ((sizeof(abtCmdWR) - 1) / 3); + uint8_t abtRxWR[1]; + for (uint8_t i = 0x19, j = 0; i < 0x19 + szXramUsbDesc;) { + if (j == szXramUsbDesc) + break; + for (uint8_t k = 0; (k < nWRreg) && (j < szXramUsbDesc); k++) { + abtCmdWR[(3 * k) + 2] = i++; + abtCmdWR[(3 * k) + 3] = btXramUsbDesc[j++]; + } + if (j == szXramUsbDesc) + szCmdWR = ((((szXramUsbDesc - 1) % nWRreg) + 1) * 3) + 1; + if (pn53x_transceive(pnd, abtCmdWR, szCmdWR, abtRxWR, sizeof(abtRxWR), -1) < 0) { + return; // void + } + } + DRIVER_DATA(pnd)->possibly_corrupted_usbdesc = false; +} + static pn53x_usb_model pn53x_usb_get_device_model(uint16_t vendor_id, uint16_t product_id) { @@ -316,6 +408,7 @@ pn53x_usb_open(const nfc_context *context, const nfc_connstring connstring) .pudh = NULL, .uiEndPointIn = 0, .uiEndPointOut = 0, + .possibly_corrupted_usbdesc = false, }; struct usb_bus *bus; struct usb_device *dev; @@ -338,10 +431,12 @@ pn53x_usb_open(const nfc_context *context, const nfc_connstring connstring) if ((data.pudh = usb_open(dev)) == NULL) continue; // Retrieve end points, using default if dev->config is broken - if (dev->config == NULL) + if (dev->config == NULL) { pn53x_usb_get_end_points_default(dev, &data); - else + data.possibly_corrupted_usbdesc = true; + } else { pn53x_usb_get_end_points(dev, &data); + } // Set configuration int res = usb_set_configuration(data.pudh, 1); if (res < 0) { @@ -443,6 +538,9 @@ pn53x_usb_close(nfc_device *pnd) pn53x_write_register(pnd, PN53X_SFR_P3, 0xFF, _BV(P30) | _BV(P31) | _BV(P32) | _BV(P33) | _BV(P35)); } + if (DRIVER_DATA(pnd)->possibly_corrupted_usbdesc) + pn533_fix_usbdesc(pnd); + pn53x_idle(pnd); int res; @@ -471,6 +569,7 @@ pn53x_usb_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, con return pnd->last_error; } + DRIVER_DATA(pnd)->possibly_corrupted_usbdesc |= szData > 17; if ((res = pn53x_usb_bulk_write(DRIVER_DATA(pnd), abtFrame, szFrame, timeout)) < 0) { pnd->last_error = res; return pnd->last_error; @@ -490,8 +589,8 @@ pn53x_usb_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, con // For some reasons (eg. send another command while a previous one is // running), the PN533 sometimes directly replies the response packet // instead of ACK frame, so we send a NACK frame to force PN533 to resend - // response packet. With this hack, the nextly executed function (ie. - // pn53x_usb_receive()) will be able to retreive the correct response + // response packet. With this hack, the next executed function (ie. + // pn53x_usb_receive()) will be able to retrieve the correct response // packet. // FIXME Sony reader is also affected by this bug but NACK is not supported if ((res = pn53x_usb_bulk_write(DRIVER_DATA(pnd), (uint8_t *)pn53x_nack_frame, sizeof(pn53x_nack_frame), timeout)) < 0) { @@ -501,7 +600,6 @@ pn53x_usb_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, con return pnd->last_error; } } - return NFC_SUCCESS; } @@ -702,6 +800,8 @@ pn53x_usb_init(nfc_device *pnd) /* ie. Switch LED1 on and turn off progressive field */ pn53x_write_register(pnd, PN53X_SFR_P3, 0xFF, _BV(P30) | _BV(P31) | _BV(P33) | _BV(P35)); } + if (DRIVER_DATA(pnd)->possibly_corrupted_usbdesc) + pn533_fix_usbdesc(pnd); return NFC_SUCCESS; } From 767abe50e2c487958a741ecc4d80276bd9013b09 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 20 Apr 2017 08:35:13 +0200 Subject: [PATCH 201/318] PN533: Abuse the overflow bug to restore USB descriptors in one go --- libnfc/drivers/pn53x_usb.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index bc4e2bc5..43d09f2e 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -185,7 +185,8 @@ static void pn533_fix_usbdesc(nfc_device *pnd) btXramUsbDesc = (uint8_t *)btXramUsbDesc_asklogo; szXramUsbDesc = sizeof(btXramUsbDesc_asklogo); } - if (szXramUsbDesc == 0) +#define MAXSZXRAMUSBDESC 61 + if ((szXramUsbDesc == 0) || (MAXSZXRAMUSBDESC > 61)) return; /* // Debug routine to check if corruption occurred: @@ -209,25 +210,16 @@ static void pn533_fix_usbdesc(nfc_device *pnd) } } */ - // Restore USB descriptors + // Abuse the overflow bug to restore USB descriptors in one go log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "%s", "Fixing USB descriptors corruption"); - // Don't write more regs at once or it will trigger the bug and corrupt what we're busy reading! - uint8_t abtCmdWR[] = { WriteRegister, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t abtCmdWR[19 + MAXSZXRAMUSBDESC] = { GetFirmwareVersion }; + for (uint8_t i = 0; i < szXramUsbDesc; i++) { + abtCmdWR[i + 19] = btXramUsbDesc[i]; + } size_t szCmdWR = sizeof(abtCmdWR); - uint8_t nWRreg = ((sizeof(abtCmdWR) - 1) / 3); - uint8_t abtRxWR[1]; - for (uint8_t i = 0x19, j = 0; i < 0x19 + szXramUsbDesc;) { - if (j == szXramUsbDesc) - break; - for (uint8_t k = 0; (k < nWRreg) && (j < szXramUsbDesc); k++) { - abtCmdWR[(3 * k) + 2] = i++; - abtCmdWR[(3 * k) + 3] = btXramUsbDesc[j++]; - } - if (j == szXramUsbDesc) - szCmdWR = ((((szXramUsbDesc - 1) % nWRreg) + 1) * 3) + 1; - if (pn53x_transceive(pnd, abtCmdWR, szCmdWR, abtRxWR, sizeof(abtRxWR), -1) < 0) { - return; // void - } + uint8_t abtRxWR[4]; + if (pn53x_transceive(pnd, abtCmdWR, szCmdWR, abtRxWR, sizeof(abtRxWR), -1) < 0) { + return; // void } DRIVER_DATA(pnd)->possibly_corrupted_usbdesc = false; } From 1bf542b9e261f091426537157920d47c14d01b30 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 20 Apr 2017 09:06:41 +0200 Subject: [PATCH 202/318] cosmetic --- libnfc/drivers/pn53x_usb.c | 42 +++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index 43d09f2e..184e5780 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -188,28 +188,28 @@ static void pn533_fix_usbdesc(nfc_device *pnd) #define MAXSZXRAMUSBDESC 61 if ((szXramUsbDesc == 0) || (MAXSZXRAMUSBDESC > 61)) return; - /* - // Debug routine to check if corruption occurred: - // Don't read more regs at once or it will trigger the bug and corrupt what we're busy reading! - uint8_t abtCmdRR[] = { ReadRegister, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t nRRreg = ((sizeof(abtCmdRR) - 1) / 2); - uint8_t abtRxRR[1 + nRRreg]; - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "%s", "Checking USB descriptors corruption in XRAM"); - for (uint8_t i = 0x19, j = 0; i < 0x19 + szXramUsbDesc;) { - for (uint8_t k = 0; k < nRRreg; k++) { - abtCmdRR[(2 * k) + 2] = i++; - } - if (pn53x_transceive(pnd, abtCmdRR, sizeof(abtCmdRR), abtRxRR, sizeof(abtRxRR), -1) < 0) { - return; // void - } - for (int k = 0; (k < nRRreg) && (j < szXramUsbDesc); k++) { - //printf("0x%02x, ", abtRxRR[1 + k]); - if (btXramUsbDesc[j] != abtRxRR[1 + k]) - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "XRAM corruption @ addr 0x00%02X: got %02x, expected %02x", 0x0019 + (j - 1), abtRxRR[1 + k], btXramUsbDesc[j]); - j++; - } +#if 0 + // Debug routine to check if corruption occurred: + // Don't read more regs at once or it will trigger the bug and corrupt what we're busy reading! + uint8_t abtCmdRR[] = { ReadRegister, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t nRRreg = ((sizeof(abtCmdRR) - 1) / 2); + uint8_t abtRxRR[1 + nRRreg]; + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "%s", "Checking USB descriptors corruption in XRAM"); + for (uint8_t i = 0x19, j = 0; i < 0x19 + szXramUsbDesc;) { + for (uint8_t k = 0; k < nRRreg; k++) { + abtCmdRR[(2 * k) + 2] = i++; } - */ + if (pn53x_transceive(pnd, abtCmdRR, sizeof(abtCmdRR), abtRxRR, sizeof(abtRxRR), -1) < 0) { + return; // void + } + for (int k = 0; (k < nRRreg) && (j < szXramUsbDesc); k++) { + //printf("0x%02x, ", abtRxRR[1 + k]); + if (btXramUsbDesc[j] != abtRxRR[1 + k]) + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "XRAM corruption @ addr 0x00%02X: got %02x, expected %02x", 0x0019 + (j - 1), abtRxRR[1 + k], btXramUsbDesc[j]); + j++; + } + } +#endif // Abuse the overflow bug to restore USB descriptors in one go log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "%s", "Fixing USB descriptors corruption"); uint8_t abtCmdWR[19 + MAXSZXRAMUSBDESC] = { GetFirmwareVersion }; From c9ac17c9f5e793d1cba877a33e4d8353beff94e6 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 20 Apr 2017 09:06:47 +0200 Subject: [PATCH 203/318] Fix USB descriptors in SCL3711, NXP_PN533 and ASK LoGO also when corrupted by received data The problem occurs in the following succession of events: * Emit commands returning an answer larger than 16 bytes * Re-enumerate USB devices without power cycle, e.g. a warm reboot of the PC The bug can be reproduced for testing purposes with usbreset.c from https://askubuntu.com/questions/645/how-do-you-reset-a-usb-device-from-the-command-line#661 $ lsusb|grep NFC Bus 001 Device 010: ID 04e6:5591 SCM Microsystems, Inc. SCL3711-NFC&RW $ sudo ./usbreset /dev/bus/usb/001/010 Resetting USB device /dev/bus/usb/001/010 Reset successful $ echo -e "4a 01 00\n423000" |pn53x-tamashell $ sudo ./usbreset /dev/bus/usb/001/010 Resetting USB device /dev/bus/usb/001/010 Error in ioctl: No such device $ lsusb|grep NFC ... device disappeared In the example above, reading 4 pages of a MFUL corrupted one single byte. The entire buffer can be corrupted e.g. with fast-reading a MFUL EV1: $ echo -e "4a 01 00\n423a0013"|pn53x-tamashell --- libnfc/drivers/pn53x_usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index 184e5780..30f3b6fc 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -729,6 +729,7 @@ pn53x_usb_receive(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, con } // The PN53x command is done and we successfully received the reply pnd->last_error = 0; + DRIVER_DATA(pnd)->possibly_corrupted_usbdesc |= len > 16; return len; } From 9f4290b61b53b2ef6ce5981f3e8959c501970091 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 16 May 2017 13:22:30 +0200 Subject: [PATCH 204/318] Add nfc-barcode --- ChangeLog | 2 + examples/CMakeLists.txt | 1 + examples/Makefile.am | 6 + examples/nfc-barcode.1 | 35 +++++ examples/nfc-barcode.c | 291 ++++++++++++++++++++++++++++++++++++++++ libnfc/chips/pn53x.c | 2 +- 6 files changed, 336 insertions(+), 1 deletion(-) create mode 100644 examples/nfc-barcode.1 create mode 100644 examples/nfc-barcode.c diff --git a/ChangeLog b/ChangeLog index 497d5aa3..fe495673 100644 --- a/ChangeLog +++ b/ChangeLog @@ -33,6 +33,7 @@ Improvements: - Add support for PN532 on RPi3 UART - Add support for cross-compilation of 32b & 64b versions of the library for Windows - Add pn533_usb to the kernel modules blacklist + - Allows for sending empty data in nfc_initiator_transceive_bits - driver i2c: respect proper timing specifications - driver i2c: add retry on error mechanism - nfc-mfclassic: improvements fo magic cards @@ -42,6 +43,7 @@ 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) Changes: - nfc_get_supported_baud_rate() takes now a "mode" parameter diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 35a852b3..3f8fb87b 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,5 +1,6 @@ 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 c767532c..42baa29d 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -2,6 +2,7 @@ SUBDIRS = pn53x-tamashell-scripts bin_PROGRAMS = \ nfc-anticol \ + nfc-barcode \ nfc-dep-initiator \ nfc-dep-target \ nfc-emulate-forum-tag2 \ @@ -35,6 +36,10 @@ 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 @@ -87,6 +92,7 @@ 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/examples/nfc-barcode.1 b/examples/nfc-barcode.1 new file mode 100644 index 00000000..84190e3e --- /dev/null +++ b/examples/nfc-barcode.1 @@ -0,0 +1,35 @@ +.TH nfc-barcode 1 "May, 2017" "libnfc" "libnfc's examples" +.SH NAME +nfc-barcode \- NFC Barcode (Tag-Talks-First) reader +.SH SYNOPSIS +.B nfc-barcode +.SH DESCRIPTION +.B nfc-barcode +is a utility to read NFC Barcodes + +.SH OPTIONS +.B -d +Decode content, if possible. + +.B -v +Verbose. + +.SH BUGS +Please report any bugs on the +.B libnfc +issue tracker at: +.br +.BR https://github.com/nfc-tools/libnfc/issues +.SH LICENCE +.B libnfc +is licensed under the GNU Lesser General Public License (LGPL), version 3. +.br +.B libnfc-utils +and +.B libnfc-examples +are covered by the the BSD 2-Clause license. +.SH AUTHORS +Philippe Teuwen +.PP +This manual page was written by Philippe Teuwen . +It is licensed under the terms of the GNU GPL (version 2 or later). diff --git a/examples/nfc-barcode.c b/examples/nfc-barcode.c new file mode 100644 index 00000000..b4d299b5 --- /dev/null +++ b/examples/nfc-barcode.c @@ -0,0 +1,291 @@ +/*- + * Free/Libre Near Field Communication (NFC) library + * + * Libnfc historical contributors: + * Copyright (C) 2017 Philippe Teuwen + * See AUTHORS file for a more comprehensive list of contributors. + * Additional contributors of this file: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1) Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2 )Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Note that this license only applies on the examples, NFC library itself is under LGPL + * + */ + +/** + * @file nfc-barcode.c + * @brief Reads a NFC Barcode tag + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif // HAVE_CONFIG_H + +#include +#include +#include +#include +#include +#include + +#include + +#include "utils/nfc-utils.h" + +#define MAX_FRAME_LEN 264 + +static nfc_device *pnd; + +bool verbose = false; +bool decode = false; + +static void +print_usage(char *argv[]) +{ + printf("Usage: %s [OPTIONS]\n", argv[0]); + printf("Options:\n"); + printf("\t-h\tHelp. Print this message.\n"); + printf("\t-q\tVerbose mode.\n"); + printf("\t-d\tDecode content.\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]) { + case 0xb7: + printf("Manufacturer: Thinfilm\n"); + break; + default: + printf("Manufacturer: unknown\n"); + break; + } + } + if (verbose) { + printf("Data Format Field: %02X\n", pbtBarcode[1]); + } + switch (pbtBarcode[1]) { + case 0: + printf("Data Format Field: Reserved for allocation by tag manufacturer\n"); + return false; + break; + case 1: + case 2: + case 3: + case 4: + switch (pbtBarcode[1]) { + case 1: + printf("http://www."); + break; + case 2: + printf("https://www."); + break; + case 3: + printf("http://"); + break; + case 4: + printf("https://"); + break; + } + for (uint8_t i = 2; i < 15; i++) { + if ((pbtBarcode[i] == 0xfe) || (i == 14)) { + pbtBarcode[i] = '\n'; + pbtBarcode[i + 1] = 0; + break; + } + } + printf("%s", (char *)pbtBarcode + 2); + break; + case 5: + printf("EPC: "); + for (uint8_t i = 0; i < 12; i++) { + printf("%02x", pbtBarcode[i + 2]); + } + printf("\n"); + break; + default: + printf("Data Format Field: unknown (%02X)\n", pbtBarcode[1]); + printf("Data:"); + for (uint8_t i = 2; i < (szBarcode / 8) - 2; i++) { + printf("%02x", pbtBarcode[i]); + } + printf("\n"); + break; + } + return true; +} + +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++) { + if (0 == strcmp(argv[arg], "-h")) { + print_usage(argv); + exit(EXIT_SUCCESS); + } else if (0 == strcmp(argv[arg], "-v")) { + verbose = true; + } else if (0 == strcmp(argv[arg], "-d")) { + decode = true; + } else { + ERR("%s is not supported option.", argv[arg]); + print_usage(argv); + exit(EXIT_FAILURE); + } + } + + nfc_context *context; + nfc_init(&context); + if (context == NULL) { + ERR("Unable to init libnfc (malloc)"); + exit(EXIT_FAILURE); + } + + // Try to open the NFC reader + pnd = nfc_open(context, NULL); + + if (pnd == NULL) { + ERR("Error opening NFC reader"); + nfc_exit(context); + exit(EXIT_FAILURE); + } + + // Initialise NFC device as "initiator" + if (nfc_initiator_init(pnd) < 0) { + nfc_perror(pnd, "nfc_initiator_init"); + nfc_close(pnd); + nfc_exit(context); + exit(EXIT_FAILURE); + } + + printf("NFC reader: %s opened\n\n", nfc_device_get_name(pnd)); + + if ((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); + } + 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"); + printf("No NFC Barcode found\n"); + nfc_close(pnd); + nfc_exit(context); + exit(EXIT_FAILURE); + } + nfc_close(pnd); + nfc_exit(context); + if (verbose) + print_hex_par(abtRx, res, abtRxPar); + res = bits2barcode(abtRx, res, abtRxPar, pbtBarcode, sizeof(pbtBarcode)); + + if (res % 128 != 0) { + printf("Error, NFC Barcode seems incomplete, received %u bits\n", res); + if (verbose) { + print_hex_bits(pbtBarcode, res); + } + exit(EXIT_FAILURE); + } + + if (validate_crc(pbtBarcode, res)) { + if (verbose) { + printf("CRC correct\n"); + } + } else { + printf("CRC error\n"); + if (verbose) { + print_hex_bits(pbtBarcode, res); + } + exit(EXIT_FAILURE); + } + + if (verbose || ! decode) { + for (uint8_t i = 0; i < res / 8; i++) { + printf("%02x", pbtBarcode[i]); + } + printf("\n"); + } + if (decode) { + decode_barcode(pbtBarcode, res); + } + exit(EXIT_SUCCESS); +} diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 34cf4adf..a83d3f05 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1333,7 +1333,7 @@ pn53x_initiator_transceive_bits(struct nfc_device *pnd, const uint8_t *pbtTx, co uint8_t abtCmd[PN53x_EXTENDED_FRAME__DATA_MAX_LEN] = { InCommunicateThru }; // Check if we should prepare the parity bits ourself - if (!pnd->bPar) { + if ((!pnd->bPar) && (szTxBits > 0)) { // Convert data with parity to a frame if ((res = pn53x_wrap_frame(pbtTx, szTxBits, pbtTxPar, abtCmd + 1)) < 0) return res; From 9f1a68530a2b681254cdef2ef0668fbd689d8be0 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 16 May 2017 14:35:58 +0200 Subject: [PATCH 205/318] nfc-barcode: add options -r & -n --- examples/nfc-barcode.1 | 8 ++++ examples/nfc-barcode.c | 103 ++++++++++++++++++++++++++--------------- 2 files changed, 74 insertions(+), 37 deletions(-) diff --git a/examples/nfc-barcode.1 b/examples/nfc-barcode.1 index 84190e3e..0677094d 100644 --- a/examples/nfc-barcode.1 +++ b/examples/nfc-barcode.1 @@ -14,6 +14,14 @@ 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/examples/nfc-barcode.c index b4d299b5..fcc013ab 100644 --- a/examples/nfc-barcode.c +++ b/examples/nfc-barcode.c @@ -56,6 +56,8 @@ static nfc_device *pnd; bool verbose = false; bool decode = false; +bool rfoff = true; +uint8_t n = 1; static void print_usage(char *argv[]) @@ -65,6 +67,8 @@ print_usage(char *argv[]) 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 @@ -202,6 +206,14 @@ main(int argc, char *argv[]) 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); @@ -235,7 +247,7 @@ main(int argc, char *argv[]) printf("NFC reader: %s opened\n\n", nfc_device_get_name(pnd)); - if ((nfc_device_set_property_bool(pnd, NP_ACTIVATE_FIELD, false) < 0) || + 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"); @@ -243,49 +255,66 @@ main(int argc, char *argv[]) nfc_exit(context); exit(EXIT_FAILURE); } - 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"); - printf("No NFC Barcode found\n"); - nfc_close(pnd); - nfc_exit(context); - exit(EXIT_FAILURE); - } - nfc_close(pnd); - nfc_exit(context); - if (verbose) - print_hex_par(abtRx, res, abtRxPar); - res = bits2barcode(abtRx, res, abtRxPar, pbtBarcode, sizeof(pbtBarcode)); - if (res % 128 != 0) { - printf("Error, NFC Barcode seems incomplete, received %u bits\n", res); - if (verbose) { - print_hex_bits(pbtBarcode, res); + 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; } - exit(EXIT_FAILURE); - } + if (verbose) + print_hex_par(abtRx, res, abtRxPar); + res = bits2barcode(abtRx, res, abtRxPar, pbtBarcode, sizeof(pbtBarcode)); - if (validate_crc(pbtBarcode, res)) { - if (verbose) { - printf("CRC correct\n"); + 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; } - } else { - printf("CRC error\n"); - if (verbose) { - print_hex_bits(pbtBarcode, res); + 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; } - exit(EXIT_FAILURE); - } - if (verbose || ! decode) { - for (uint8_t i = 0; i < res / 8; i++) { - printf("%02x", pbtBarcode[i]); + if (verbose || ! decode) { + for (uint8_t i = 0; i < res / 8; i++) { + printf("%02x", pbtBarcode[i]); + } + printf("\n"); } - printf("\n"); - } - if (decode) { - decode_barcode(pbtBarcode, res); + if (decode) { + decode_barcode(pbtBarcode, res); + } + break; } + nfc_close(pnd); + nfc_exit(context); exit(EXIT_SUCCESS); } From dcdbff0705c8eabb8f055e8e7b9ef237430d6577 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 17 May 2017 13:38:20 +0200 Subject: [PATCH 206/318] New NFC modulation type NMT_BARCODE --- ChangeLog | 3 +- examples/CMakeLists.txt | 1 - examples/Makefile.am | 6 -- include/nfc/nfc-types.h | 11 +++ libnfc/chips/pn53x.c | 140 +++++++++++++++++++++++++++++ libnfc/chips/pn53x.h | 3 + libnfc/drivers/pn53x_usb.c | 1 + libnfc/nfc-internal.c | 1 + libnfc/nfc.c | 7 +- libnfc/target-subr.c | 19 ++++ libnfc/target-subr.h | 1 + utils/CMakeLists.txt | 1 + utils/Makefile.am | 6 ++ {examples => utils}/nfc-barcode.1 | 10 +-- {examples => utils}/nfc-barcode.c | 143 +++--------------------------- utils/nfc-list.c | 27 ++++-- 16 files changed, 224 insertions(+), 156 deletions(-) rename {examples => utils}/nfc-barcode.1 (83%) rename {examples => utils}/nfc-barcode.c (55%) diff --git a/ChangeLog b/ChangeLog index fe495673..89f3608d 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 3f8fb87b..35a852b3 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 42baa29d..c767532c 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 8c726a11..a18e4aaf 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 a83d3f05..5c197674 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 bb5d6e30..f236930f 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 30f3b6fc..807e98e8 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 68ecd341..d90bb877 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 70312b88..636697de 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 ea35e77a..97e2882b 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 528a3abb..9205d6fd 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 dc7bac93..0e038801 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 2555bcd7..11cfe120 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 0677094d..5f4760ef 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 fcc013ab..766a683c 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 62bb3d7b..55e42249 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); From 00700bc66daa3ee23a5af5d21d023dea87d778ff Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 17 May 2017 15:56:41 +0200 Subject: [PATCH 207/318] Make Travis happy --- utils/Makefile.am | 2 +- utils/nfc-barcode.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/Makefile.am b/utils/Makefile.am index 11cfe120..cd182d03 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -19,7 +19,7 @@ libnfcutils_la_LIBADD = -lnfc nfc_barcode_SOURCES = nfc-barcode.c nfc_barcode_LDADD = $(top_builddir)/libnfc/libnfc.la \ - $(top_builddir)/utils/libnfcutils.la + 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 \ diff --git a/utils/nfc-barcode.c b/utils/nfc-barcode.c index 766a683c..3c6e12c8 100644 --- a/utils/nfc-barcode.c +++ b/utils/nfc-barcode.c @@ -48,7 +48,7 @@ #include -#include "utils/nfc-utils.h" +#include "nfc-utils.h" #define MAX_FRAME_LEN 264 From 14f48d012281f495904566ffd93305623017cbfa Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 18 May 2017 10:40:46 +0200 Subject: [PATCH 208/318] Fix mem leak --- include/nfc/nfc-types.h | 2 +- libnfc/chips/pn53x.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/nfc/nfc-types.h b/include/nfc/nfc-types.h index a18e4aaf..89ad3978 100644 --- a/include/nfc/nfc-types.h +++ b/include/nfc/nfc-types.h @@ -311,7 +311,7 @@ typedef enum { NMT_ISO14443B2SR, // ISO14443-2B ST SRx NMT_ISO14443B2CT, // ISO14443-2B ASK CTx NMT_FELICA, - NMT_DEP, + NMT_DEP, // DEP should be kept last one as it's used as end-of-enum } nfc_modulation_type; /** diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 5c197674..03642486 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -85,7 +85,7 @@ pn53x_init(struct nfc_device *pnd) } if (!CHIP_DATA(pnd)->supported_modulation_as_initiator) { - CHIP_DATA(pnd)->supported_modulation_as_initiator = malloc(sizeof(nfc_modulation_type) * 9); + CHIP_DATA(pnd)->supported_modulation_as_initiator = malloc(sizeof(nfc_modulation_type) * (NMT_DEP + 1)); if (! CHIP_DATA(pnd)->supported_modulation_as_initiator) return NFC_ESOFT; int nbSupportedModulation = 0; From f9417586c0c8e23058e463a1d30e47659dbe5519 Mon Sep 17 00:00:00 2001 From: Michal Suchanek Date: Fri, 14 Jul 2017 16:19:26 +0200 Subject: [PATCH 209/318] nfc-poll: print "Waiting for card removing..." before waiting --- examples/nfc-poll.c | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/nfc-poll.c b/examples/nfc-poll.c index fde8ea86..f8f30ba3 100644 --- a/examples/nfc-poll.c +++ b/examples/nfc-poll.c @@ -146,6 +146,7 @@ main(int argc, const char *argv[]) if (res > 0) { print_nfc_target(&nt, verbose); printf("Waiting for card removing..."); + fflush(stdout); while (0 == nfc_initiator_target_is_present(pnd, NULL)) {} nfc_perror(pnd, "nfc_initiator_target_is_present"); printf("done.\n"); From 2b96c9f3c559df8e20b9d5258300b9d29692ccaf Mon Sep 17 00:00:00 2001 From: rocco8620 Date: Sun, 3 Sep 2017 21:53:17 +0200 Subject: [PATCH 210/318] Wrong variable names Wrong variable names (missing dots) on line 269, 270, 271 --- examples/nfc-emulate-tag.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/nfc-emulate-tag.c b/examples/nfc-emulate-tag.c index 3192095a..a2adbe67 100644 --- a/examples/nfc-emulate-tag.c +++ b/examples/nfc-emulate-tag.c @@ -266,9 +266,9 @@ main(int argc, char *argv[]) }, .nti = { .nai = { - abtAtqa = { 0x03, 0x44 }, - abtUid = { 0x08, 0xab, 0xcd, 0xef }, - btSak = 0x20, + .abtAtqa = { 0x03, 0x44 }, + .abtUid = { 0x08, 0xab, 0xcd, 0xef }, + .btSak = 0x20, .szUidLen = 4, .abtAts = { 0x75, 0x77, 0x81, 0x02, 0x80 }, .szAtsLen = 5, From e4ca7f45d212f436b6435a4c4b47dcfaa38429ad Mon Sep 17 00:00:00 2001 From: Hanno Heinrichs Date: Sun, 17 Sep 2017 20:27:38 +0200 Subject: [PATCH 211/318] remove redundant blanks --- utils/nfc-mfclassic.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 36973ed7..fb09a838 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -98,13 +98,13 @@ static size_t num_keys = sizeof(keys) / 6; static uint8_t abtRx[MAX_FRAME_LEN]; static int szRxBits; -uint8_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 }; +uint8_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 }; // special unlock command -uint8_t abtUnlock1[1] = { 0x40 }; -uint8_t abtUnlock2[1] = { 0x43 }; +uint8_t abtUnlock1[1] = { 0x40 }; +uint8_t abtUnlock2[1] = { 0x43 }; -static bool +static bool transmit_bits(const uint8_t *pbtTx, const size_t szTxBits) { // Show transmitted command @@ -122,7 +122,7 @@ transmit_bits(const uint8_t *pbtTx, const size_t szTxBits) } -static bool +static bool transmit_bytes(const uint8_t *pbtTx, const size_t szTx) { // Show transmitted command @@ -148,7 +148,7 @@ print_success_or_failure(bool bFailure, uint32_t *uiBlockCounter) *uiBlockCounter += 1; } -static bool +static bool is_first_block(uint32_t uiBlock) { // Test if we are in the small or big sectors @@ -158,7 +158,7 @@ is_first_block(uint32_t uiBlock) return ((uiBlock) % 16 == 0); } -static bool +static bool is_trailer_block(uint32_t uiBlock) { // Test if we are in the small or big sectors @@ -168,7 +168,7 @@ is_trailer_block(uint32_t uiBlock) return ((uiBlock + 1) % 16 == 0); } -static uint32_t +static uint32_t get_trailer_block(uint32_t uiFirstBlock) { // Test if we are in the small or big sectors @@ -181,7 +181,7 @@ get_trailer_block(uint32_t uiFirstBlock) return trailer_block; } -static bool +static bool authenticate(uint32_t uiBlock) { mifare_cmd mc; @@ -277,7 +277,7 @@ static int get_rats(void) { int res; - uint8_t abtRats[2] = { 0xe0, 0x50}; + uint8_t abtRats[2] = { 0xe0, 0x50}; // Use raw send/receive methods if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, false) < 0) { nfc_perror(pnd, "nfc_configure"); @@ -305,11 +305,11 @@ get_rats(void) return res; } -static bool +static bool read_card(int read_unlocked) { int32_t iBlock; - bool bFailure = false; + bool bFailure = false; uint32_t uiReadBlocks = 0; if (read_unlocked) { @@ -375,7 +375,7 @@ read_card(int read_unlocked) } // Show if the readout went well for each block print_success_or_failure(bFailure, &uiReadBlocks); - if ((! bTolerateFailures) && bFailure) + if ((!bTolerateFailures) && bFailure) return false; } printf("|\n"); @@ -385,11 +385,11 @@ read_card(int read_unlocked) return true; } -static bool +static bool write_card(int write_block_zero) { uint32_t uiBlock; - bool bFailure = false; + bool bFailure = false; uint32_t uiWriteBlocks = 0; if (write_block_zero) { @@ -449,7 +449,7 @@ write_card(int write_block_zero) } } else { // The first block 0x00 is read only, skip this - if (uiBlock == 0 && ! write_block_zero && ! magic2) + if (uiBlock == 0 && !write_block_zero && !magic2) continue; @@ -474,7 +474,7 @@ write_card(int write_block_zero) } // Show if the write went well for each block print_success_or_failure(bFailure, &uiWriteBlocks); - if ((! bTolerateFailures) && bFailure) + if ((!bTolerateFailures) && bFailure) return false; } printf("|\n"); @@ -659,7 +659,7 @@ main(int argc, const char *argv[]) fileUid[0], fileUid[1], fileUid[2], fileUid[3]); printf("Got card with UID starting as: %02x%02x%02x%02x\n", pbtUID[0], pbtUID[1], pbtUID[2], pbtUID[3]); - if (! bForceKeyFile) { + if (!bForceKeyFile) { printf("Aborting!\n"); nfc_close(pnd); nfc_exit(context); From df4f9c0fbdda9c0b65b2e9d93a73d156119ac71a Mon Sep 17 00:00:00 2001 From: Hanno Heinrichs Date: Sun, 17 Sep 2017 19:08:31 +0200 Subject: [PATCH 212/318] fix typo --- utils/nfc-mfclassic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index fb09a838..bc3fe6c5 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -316,7 +316,7 @@ read_card(int read_unlocked) //If the user is attempting an unlocked read, but has a direct-write type magic card, they don't //need to use the R mode. We'll trigger a warning and let them proceed. if (magic2) { - printf("Note: This card does not require an unlocked write (R) \n"); + printf("Note: This card does not require an unlocked read (R) \n"); read_unlocked = 0; } else { //If User has requested an unlocked read, but we're unable to unlock the card, we'll error out. From 7a0a469c8a0f75e564beff2e1b0168454b7e6f3f Mon Sep 17 00:00:00 2001 From: Hanno Heinrichs Date: Sun, 17 Sep 2017 19:55:53 +0200 Subject: [PATCH 213/318] 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 bc3fe6c5..847f5531 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 62f27c1c5834a65501f08a415e0726c7233e871e Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Sat, 15 Sep 2018 16:19:35 +0100 Subject: [PATCH 214/318] Add support for Ultralight NTAG213/215/216 --- utils/mifare.h | 91 +++++++++++++++++++++++++++++++++++++++- utils/nfc-mfultralight.c | 64 +++++++++++++++++++++------- 2 files changed, 138 insertions(+), 17 deletions(-) diff --git a/utils/mifare.h b/utils/mifare.h index cd6c6f62..4a354a71 100644 --- a/utils/mifare.h +++ b/utils/mifare.h @@ -9,7 +9,7 @@ * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: - * Copyright (C) 2017 Adam Laurie + * Copyright (C) 2017-2018 Adam Laurie * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -167,10 +167,62 @@ typedef struct { uint8_t dummy[12]; } mifareul_block_config21B; +// MIFARE NTAG21[3/5/6] Manufacturer Pages +typedef struct { + uint8_t sn0[4]; +} mifarentag_block_manuf21356A; +typedef struct { + uint8_t sn1[4]; +} mifarentag_block_manuf21356B; +typedef struct { + uint8_t sn2; + uint8_t internal; + uint8_t lock[2]; +} mifarentag_block_manuf21356C; +typedef struct { + uint8_t cc[4]; +} mifarentag_block_manuf21356D; + +// MIFARE NTAG21[3/5/6] Config Pages +typedef struct { + uint8_t dynlock[3]; + uint8_t rfui0; +} mifarentag_block_config21356A; +typedef struct { + uint8_t cfg0[4]; +} mifarentag_block_config21356B; +typedef struct { + uint8_t cfg1[4]; +} mifarentag_block_config21356C; +typedef struct { + uint8_t pwd[4]; +} mifarentag_block_config21356D; +typedef struct { + uint8_t pack[2]; + uint8_t rfui1[2]; +} mifarentag_block_config21356E; + typedef struct { uint8_t abtData[16]; } mifareul_block_data; +typedef struct { + uint8_t abtData[4]; +} mifarentag_block_data; + +typedef union { + mifarentag_block_manuf21356A mbm21356a; + mifarentag_block_manuf21356B mbm21356b; + mifarentag_block_manuf21356C mbm21356c; + mifarentag_block_manuf21356D mbm21356d; + mifarentag_block_data mbd; + mifarentag_block_config21356A mbc21356a; + mifarentag_block_config21356B mbc21356b; + mifarentag_block_config21356C mbc21356c; + mifarentag_block_config21356D mbc21356d; + mifarentag_block_config21356E mbc21356e; +} mifarentag_block; + typedef union { mifareul_block_manufacturer mbm; mifareul_block_data mbd; @@ -194,6 +246,43 @@ typedef struct { mifareul_block amb[11]; } mifareul_ev1_mf0ul21_tag; +// NOT really UL but so similar we can re-use this code +// if Edwin van Andel doesn't distract us... +// https://www.nxp.com/docs/en/data-sheet/NTAG213_215_216.pdf + +// NTAG213 EEPROM: 180 bytes, organized in 45 pages of 4 byte per page. +// 26 bytes reserved for manufacturer and configuration data +// 34 bits used for the read-only locking mechanism +// 4 bytes available as capability container +// 144 bytes user programmable read/write memory +typedef struct { + mifarentag_block amb[45]; +} mifarentag_213_tag; + +// NTAG215 EEPROM: 540 bytes, organized in 135 pages of 4 byte per page. +// 26 bytes reserved for manufacturer and configuration data +// 28 bits used for the read-only locking mechanism +// 4 bytes available as capability container +// 504 bytes user programmable read/write memory +typedef struct { + mifarentag_block amb[135]; +} mifarentag_215_tag; + +// NTAG216 EEPROM: 924 bytes, organized in 231 pages of 4 byte per page. +// 26 bytes reserved for manufacturer and configuration data +// 37 bits used for the read-only locking mechanism +// 4 bytes available as capability container +// 888 bytes user programmable read/write memory +typedef struct { + mifarentag_block amb[231]; +} mifarentag_216_tag; + +// dummy max size with all structures in it for reading, rounded up to a multiple of 16 bytes +typedef union { + mifareul_block ul[58]; + mifarentag_block nt[232]; +} maxtag; + // Reset struct alignment to default # pragma pack() diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index f77ac6c2..018af51a 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -9,7 +9,7 @@ * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: - * Copyright (C) 2013-2017 Adam Laurie + * Copyright (C) 2013-2018 Adam Laurie * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -64,11 +64,14 @@ #define EV1_NONE 0 #define EV1_UL11 1 #define EV1_UL21 2 +#define EV1_NTAG213 3 +#define EV1_NTAG215 4 +#define EV1_NTAG216 5 static nfc_device *pnd; static nfc_target nt; static mifare_param mp; -static mifareul_ev1_mf0ul21_tag mtDump; // use the largest tag type for internal storage +static maxtag mtDump; // use the largest tag type for internal storage static uint32_t uiBlocks = 0x10; static uint32_t uiReadPages = 0; static uint8_t iPWD[4] = { 0x0 }; @@ -119,7 +122,7 @@ read_card(void) for (page = 0; page < uiBlocks; page += 4) { // Try to read out the data block if (nfc_initiator_mifare_cmd(pnd, MC_READ, page, &mp)) { - memcpy(mtDump.amb[page / 4].mbd.abtData, mp.mpd.abtData, uiBlocks - page < 4 ? (uiBlocks - page) * 4 : 16); + memcpy(mtDump.ul[page / 4].mbd.abtData, mp.mpd.abtData, uiBlocks - page < 4 ? (uiBlocks - page) * 4 : 16); } else { bFailure = true; } @@ -134,12 +137,24 @@ read_card(void) // copy EV1 secrets to dump data switch (iEV1Type) { case EV1_UL11: - memcpy(mtDump.amb[4].mbc11.pwd, iPWD, 4); - memcpy(mtDump.amb[4].mbc11.pack, iPACK, 2); + memcpy(mtDump.ul[4].mbc11.pwd, iPWD, 4); + memcpy(mtDump.ul[4].mbc11.pack, iPACK, 2); break; case EV1_UL21: - memcpy(mtDump.amb[9].mbc21a.pwd, iPWD, 4); - memcpy(mtDump.amb[9].mbc21b.pack, iPACK, 2); + memcpy(mtDump.ul[9].mbc21a.pwd, iPWD, 4); + memcpy(mtDump.ul[9].mbc21b.pack, iPACK, 2); + break; + case EV1_NTAG213: + memcpy(mtDump.nt[43].mbc21356d.pwd, iPWD, 4); + memcpy(mtDump.nt[44].mbc21356e.pack, iPACK, 2); + break; + case EV1_NTAG215: + memcpy(mtDump.nt[133].mbc21356d.pwd, iPWD, 4); + memcpy(mtDump.nt[134].mbc21356e.pack, iPACK, 2); + break; + case EV1_NTAG216: + memcpy(mtDump.nt[229].mbc21356d.pwd, iPWD, 4); + memcpy(mtDump.nt[230].mbc21356e.pack, iPACK, 2); break; case EV1_NONE: default: @@ -386,7 +401,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid) // page (4 bytes). The Ultralight-specific Write command only // writes one page at a time. uiBlock = page / 4; - memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData + ((page % 4) * 4), 4); + memcpy(mp.mpd.abtData, mtDump.ul[uiBlock].mbd.abtData + ((page % 4) * 4), 4); memset(mp.mpd.abtData + 4, 0, 12); if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, page, &mp)) bFailure = true; @@ -470,7 +485,7 @@ int main(int argc, const char *argv[]) { int iAction = 0; - uint8_t iDumpSize = sizeof(mifareul_tag); + size_t iDumpSize = sizeof(mifareul_tag); uint8_t iUID[MAX_UID_LEN] = { 0x0 }; size_t szUID = 0; bool bOTP = false; @@ -601,19 +616,36 @@ main(int argc, const char *argv[]) if (get_ev1_version()) { if (!bPWD) printf("Tag is EV1 - PASSWORD may be required\n"); - printf("EV1 storage size: "); + printf("EV1 type: "); if (abtRx[6] == 0x0b) { - printf("48 bytes\n"); - uiBlocks = 0x14; + printf("MF0UL11 (48 bytes)\n"); + uiBlocks = 20; // total number of 4 byte 'pages' iEV1Type = EV1_UL11; iDumpSize = sizeof(mifareul_ev1_mf0ul11_tag); } else if (abtRx[6] == 0x0e) { - printf("128 bytes\n"); - uiBlocks = 0x29; + printf("MF0UL21 (128 user bytes)\n"); + uiBlocks = 41; iEV1Type = EV1_UL21; iDumpSize = sizeof(mifareul_ev1_mf0ul21_tag); - } else - printf("unknown!\n"); + } else if (abtRx[6] == 0x0f) { + printf("NTAG213 (144 user bytes)\n"); + uiBlocks = 45; + iEV1Type = EV1_NTAG213; + iDumpSize = sizeof(mifarentag_213_tag); + } else if (abtRx[6] == 0x11) { + printf("NTAG215 (504 user bytes)\n"); + uiBlocks = 135; + iEV1Type = EV1_NTAG215; + iDumpSize = sizeof(mifarentag_215_tag); + } else if (abtRx[6] == 0x13) { + printf("NTAG216 (888 user bytes)\n"); + uiBlocks = 231; + iEV1Type = EV1_NTAG216; + iDumpSize = sizeof(mifarentag_216_tag); + } else { + printf("unknown! (0x%02x)\n", abtRx[6]); + exit(EXIT_FAILURE); + } } else { // re-init non EV1 tag if (nfc_initiator_select_passive_target(pnd, nmMifare, (szUID) ? iUID : NULL, szUID, &nt) <= 0) { From 4c914e67e5b6dee6634b95f5d2438802873a5c1a Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Mon, 17 Sep 2018 14:37:09 +0100 Subject: [PATCH 215/318] Fix handling of NTAG OTP and LOCK bytes --- utils/nfc-mfultralight.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 018af51a..e75fe6e3 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -61,13 +61,18 @@ #define MAX_TARGET_COUNT 16 #define MAX_UID_LEN 10 -#define EV1_NONE 0 -#define EV1_UL11 1 -#define EV1_UL21 2 +#define EV1_NONE 0 +#define EV1_UL11 1 +#define EV1_UL21 2 #define EV1_NTAG213 3 #define EV1_NTAG215 4 #define EV1_NTAG216 5 +#define NTAG_NONE 0 +#define NTAG_213 1 +#define NTAG_215 2 +#define NTAG_216 3 + static nfc_device *pnd; static nfc_target nt; static mifare_param mp; @@ -77,6 +82,7 @@ static uint32_t uiReadPages = 0; static uint8_t iPWD[4] = { 0x0 }; static uint8_t iPACK[2] = { 0x0 }; static uint8_t iEV1Type = EV1_NONE; +static uint8_t iNTAGType = NTAG_NONE; // special unlock command uint8_t abtUnlock1[1] = { 0x40 }; @@ -341,7 +347,10 @@ write_card(bool write_otp, bool write_lock, bool write_uid) char buffer[BUFSIZ]; if (!write_otp) { - printf("Write OTP bytes ? [yN] "); + if (iNTAGType == NTAG_NONE) + printf("Write OTP bytes ? [yN] "); + else + printf("Write OTP Static Lock bytes ? [yN] "); if (!fgets(buffer, BUFSIZ, stdin)) { ERR("Unable to read standard input."); } @@ -349,7 +358,10 @@ write_card(bool write_otp, bool write_lock, bool write_uid) } if (!write_lock) { - printf("Write Lock bytes ? [yN] "); + if (iNTAGType == NTAG_NONE) + printf("Write Lock bytes ? [yN] "); + else + printf("Write Dynamic Lock bytes ? [yN] "); if (!fgets(buffer, BUFSIZ, stdin)) { ERR("Unable to read standard input."); } @@ -376,13 +388,19 @@ write_card(bool write_otp, bool write_lock, bool write_uid) } } + // NTAG Dynamic Lock Bytes are in different locations for each type for (uint32_t page = uiSkippedPages; page < uiBlocks; page++) { - if ((page == 0x2) && (!write_lock)) { + if (((iNTAGType == NTAG_NONE && page == 0x2) || \ + (iNTAGType == NTAG_213 && page == 0x28) || \ + (iNTAGType == NTAG_215 && page == 0x82) || \ + (iNTAGType == NTAG_216 && page == 0xe2)) && (!write_lock)) { printf("s"); uiSkippedPages++; continue; } - if ((page == 0x3) && (!write_otp)) { + // NTAG doesn't have OTP blocks but Static Lock Bytes are OTP + if (((iNTAGType == NTAG_NONE && page == 0x3) || \ + (iNTAGType && page == 0x2)) && (!write_otp)) { printf("s"); uiSkippedPages++; continue; @@ -631,16 +649,19 @@ main(int argc, const char *argv[]) printf("NTAG213 (144 user bytes)\n"); uiBlocks = 45; iEV1Type = EV1_NTAG213; + iNTAGType = NTAG_213; iDumpSize = sizeof(mifarentag_213_tag); } else if (abtRx[6] == 0x11) { printf("NTAG215 (504 user bytes)\n"); uiBlocks = 135; iEV1Type = EV1_NTAG215; + iNTAGType = NTAG_215; iDumpSize = sizeof(mifarentag_215_tag); } else if (abtRx[6] == 0x13) { printf("NTAG216 (888 user bytes)\n"); uiBlocks = 231; iEV1Type = EV1_NTAG216; + iNTAGType = NTAG_216; iDumpSize = sizeof(mifarentag_216_tag); } else { printf("unknown! (0x%02x)\n", abtRx[6]); From 40b54a10d756563eed02cd6f17b81be5ccc3d492 Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Mon, 17 Sep 2018 16:58:49 +0100 Subject: [PATCH 216/318] Fix NTAG OTP and LOCK BYTES (Dynamic LOCK also applies to MF0UL21). Fix MF0UL21 sizing issue. --- utils/mifare.h | 1 + utils/nfc-mfultralight.c | 70 ++++++++++++++++++++++++---------------- 2 files changed, 43 insertions(+), 28 deletions(-) diff --git a/utils/mifare.h b/utils/mifare.h index 4a354a71..75d65dec 100644 --- a/utils/mifare.h +++ b/utils/mifare.h @@ -242,6 +242,7 @@ typedef struct { } mifareul_ev1_mf0ul11_tag; // UL EV1 MF0UL21 tag - 1 manuf block + 8 user blocks + 1/4 lock block + 1 config block +// (note that tag is actually 3 bytes smaller due to 1/4 block, so don't rely on this for sizing!) typedef struct { mifareul_block amb[11]; } mifareul_ev1_mf0ul21_tag; diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index e75fe6e3..c54dcd9e 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -336,7 +336,7 @@ static bool check_magic() } static bool -write_card(bool write_otp, bool write_lock, bool write_uid) +write_card(bool write_otp, bool write_lock, bool write_dyn_lock, bool write_uid) { uint32_t uiBlock = 0; bool bFailure = false; @@ -346,28 +346,33 @@ write_card(bool write_otp, bool write_lock, bool write_uid) char buffer[BUFSIZ]; - if (!write_otp) { - if (iNTAGType == NTAG_NONE) - printf("Write OTP bytes ? [yN] "); - else - printf("Write OTP Static Lock bytes ? [yN] "); + // NTAG does not have explicit OTP bytes + if (!write_otp && iNTAGType == NTAG_NONE) { + printf("Write OTP Bytes ? [yN] "); if (!fgets(buffer, BUFSIZ, stdin)) { ERR("Unable to read standard input."); } write_otp = ((buffer[0] == 'y') || (buffer[0] == 'Y')); } + // Lock Bytes are OTP if set, so warn if (!write_lock) { - if (iNTAGType == NTAG_NONE) - printf("Write Lock bytes ? [yN] "); - else - printf("Write Dynamic Lock bytes ? [yN] "); + printf("Write Lock Bytes (Warning: OTP if set) ? [yN] "); if (!fgets(buffer, BUFSIZ, stdin)) { ERR("Unable to read standard input."); } write_lock = ((buffer[0] == 'y') || (buffer[0] == 'Y')); } + // NTAG and MF0UL21 have additional lock bytes + if (!write_dyn_lock && (iNTAGType != NTAG_NONE || iEV1Type == EV1_UL21)) { + printf("Write Dynamic Lock Bytes ? [yN] "); + if (!fgets(buffer, BUFSIZ, stdin)) { + ERR("Unable to read standard input."); + } + write_dyn_lock = ((buffer[0] == 'y') || (buffer[0] == 'Y')); + } + if (!write_uid) { printf("Write UID bytes (only for special writeable UID cards) ? [yN] "); if (!fgets(buffer, BUFSIZ, stdin)) { @@ -388,19 +393,23 @@ write_card(bool write_otp, bool write_lock, bool write_uid) } } - // NTAG Dynamic Lock Bytes are in different locations for each type for (uint32_t page = uiSkippedPages; page < uiBlocks; page++) { - if (((iNTAGType == NTAG_NONE && page == 0x2) || \ - (iNTAGType == NTAG_213 && page == 0x28) || \ - (iNTAGType == NTAG_215 && page == 0x82) || \ - (iNTAGType == NTAG_216 && page == 0xe2)) && (!write_lock)) { + if ((!write_lock) && page == 0x2) { + printf("s"); + uiSkippedPages++; + continue; + } + // NTAG doesn't have OTP blocks + if ((iNTAGType == NTAG_NONE && page == 0x3) && (!write_otp)) { printf("s"); uiSkippedPages++; continue; } - // NTAG doesn't have OTP blocks but Static Lock Bytes are OTP - if (((iNTAGType == NTAG_NONE && page == 0x3) || \ - (iNTAGType && page == 0x2)) && (!write_otp)) { + // NTAG and MF0UL21 have Dynamic Lock Bytes + if (((iEV1Type == EV1_UL21 && page == 0x24) || \ + (iNTAGType == NTAG_213 && page == 0x28) || \ + (iNTAGType == NTAG_215 && page == 0x82) || \ + (iNTAGType == NTAG_216 && page == 0xe2)) && (!write_dyn_lock)) { printf("s"); uiSkippedPages++; continue; @@ -490,10 +499,11 @@ print_usage(const char *argv[]) printf("\tr|w - Perform read or write\n"); printf("\t - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n"); printf("Options:\n"); - printf("\t--otp - Don't prompt for OTP writing (Assume yes)\n"); - printf("\t--lock - Don't prompt for Lockbit writing (Assume yes)\n"); + printf("\t--otp - Don't prompt for OTP Bytes writing (Assume yes)\n"); + printf("\t--lock - Don't prompt for Lock Bytes (OTP) writing (Assume yes)\n"); + printf("\t--dynlock - Don't prompt for Dynamic Lock Bytes writing (Assume yes)\n"); printf("\t--uid - Don't prompt for UID writing (Assume yes)\n"); - printf("\t--full - Assume full card write (UID + OTP + Lockbit)\n"); + printf("\t--full - Assume full card write (UID + OTP + Lockbytes + Dynamic Lockbytes)\n"); printf("\t--with-uid - Specify UID to read/write from\n"); printf("\t--pw - Specify 8 HEX digit PASSWORD for EV1\n"); printf("\t--partial - Allow source data size to be other than tag capacity\n"); @@ -508,6 +518,7 @@ main(int argc, const char *argv[]) size_t szUID = 0; bool bOTP = false; bool bLock = false; + bool bDynLock = false; bool bUID = false; bool bPWD = false; bool bPart = false; @@ -536,11 +547,14 @@ main(int argc, const char *argv[]) } else if (0 == strcmp(argv[arg], "--full")) { bOTP = true; bLock = true; + bDynLock = true; bUID = true; } else if (0 == strcmp(argv[arg], "--otp")) { bOTP = true; } else if (0 == strcmp(argv[arg], "--lock")) { bLock = true; + } else if (0 == strcmp(argv[arg], "--dynlock")) { + bDynLock = true; } else if (0 == strcmp(argv[arg], "--uid")) { bUID = true; } else if (0 == strcmp(argv[arg], "--check-magic")) { @@ -638,31 +652,31 @@ main(int argc, const char *argv[]) if (abtRx[6] == 0x0b) { printf("MF0UL11 (48 bytes)\n"); uiBlocks = 20; // total number of 4 byte 'pages' + iDumpSize = uiBlocks * 4; iEV1Type = EV1_UL11; - iDumpSize = sizeof(mifareul_ev1_mf0ul11_tag); } else if (abtRx[6] == 0x0e) { printf("MF0UL21 (128 user bytes)\n"); uiBlocks = 41; + iDumpSize = uiBlocks * 4; iEV1Type = EV1_UL21; - iDumpSize = sizeof(mifareul_ev1_mf0ul21_tag); } else if (abtRx[6] == 0x0f) { printf("NTAG213 (144 user bytes)\n"); uiBlocks = 45; + iDumpSize = uiBlocks * 4; iEV1Type = EV1_NTAG213; iNTAGType = NTAG_213; - iDumpSize = sizeof(mifarentag_213_tag); } else if (abtRx[6] == 0x11) { printf("NTAG215 (504 user bytes)\n"); uiBlocks = 135; + iDumpSize = uiBlocks * 4; iEV1Type = EV1_NTAG215; iNTAGType = NTAG_215; - iDumpSize = sizeof(mifarentag_215_tag); } else if (abtRx[6] == 0x13) { printf("NTAG216 (888 user bytes)\n"); uiBlocks = 231; + iDumpSize = uiBlocks * 4; iEV1Type = EV1_NTAG216; iNTAGType = NTAG_216; - iDumpSize = sizeof(mifarentag_216_tag); } else { printf("unknown! (0x%02x)\n", abtRx[6]); exit(EXIT_FAILURE); @@ -702,7 +716,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\n", argv[2]); + ERR("Could not read from dump file or size mismatch: %s (read %lu, expected %lu)\n", argv[2], szDump, iDumpSize); fclose(pfDump); exit(EXIT_FAILURE); } @@ -740,7 +754,7 @@ main(int argc, const char *argv[]) if (!bRF) printf("Warning! Read failed - partial data written to file!\n"); } else if (iAction == 2) { - write_card(bOTP, bLock, bUID); + write_card(bOTP, bLock, bDynLock, bUID); } else if (iAction == 3) { if (!check_magic()) { printf("Card is not magic\n"); From 3ba065f00bc87255ae53d8d1b2ccc077b4d72033 Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Mon, 17 Sep 2018 21:40:48 +0100 Subject: [PATCH 217/318] Remove redundant EV1 types and rely on NTAG types instead --- utils/nfc-mfultralight.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index c54dcd9e..99916a2f 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -64,9 +64,6 @@ #define EV1_NONE 0 #define EV1_UL11 1 #define EV1_UL21 2 -#define EV1_NTAG213 3 -#define EV1_NTAG215 4 -#define EV1_NTAG216 5 #define NTAG_NONE 0 #define NTAG_213 1 @@ -150,19 +147,25 @@ read_card(void) memcpy(mtDump.ul[9].mbc21a.pwd, iPWD, 4); memcpy(mtDump.ul[9].mbc21b.pack, iPACK, 2); break; - case EV1_NTAG213: + case EV1_NONE: + default: + break; + } + // copy NTAG secrets to dump data + switch (iNTAGType) { + case NTAG_213: memcpy(mtDump.nt[43].mbc21356d.pwd, iPWD, 4); memcpy(mtDump.nt[44].mbc21356e.pack, iPACK, 2); break; - case EV1_NTAG215: + case NTAG_215: memcpy(mtDump.nt[133].mbc21356d.pwd, iPWD, 4); memcpy(mtDump.nt[134].mbc21356e.pack, iPACK, 2); break; - case EV1_NTAG216: + case NTAG_216: memcpy(mtDump.nt[229].mbc21356d.pwd, iPWD, 4); memcpy(mtDump.nt[230].mbc21356e.pack, iPACK, 2); break; - case EV1_NONE: + case NTAG_NONE: default: break; } @@ -644,7 +647,7 @@ main(int argc, const char *argv[]) } printf("\n"); - // test if tag is EV1 + // test if tag is EV1 or NTAG if (get_ev1_version()) { if (!bPWD) printf("Tag is EV1 - PASSWORD may be required\n"); @@ -663,19 +666,16 @@ main(int argc, const char *argv[]) printf("NTAG213 (144 user bytes)\n"); uiBlocks = 45; iDumpSize = uiBlocks * 4; - iEV1Type = EV1_NTAG213; iNTAGType = NTAG_213; } else if (abtRx[6] == 0x11) { printf("NTAG215 (504 user bytes)\n"); uiBlocks = 135; iDumpSize = uiBlocks * 4; - iEV1Type = EV1_NTAG215; iNTAGType = NTAG_215; } else if (abtRx[6] == 0x13) { printf("NTAG216 (888 user bytes)\n"); uiBlocks = 231; iDumpSize = uiBlocks * 4; - iEV1Type = EV1_NTAG216; iNTAGType = NTAG_216; } else { printf("unknown! (0x%02x)\n", abtRx[6]); From 25ee3a2f762433b15d1a9008fe9e2240c31c8222 Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Tue, 18 Sep 2018 11:14:08 +0100 Subject: [PATCH 218/318] Add OTP/Capability Bytes handling to NTAG --- utils/mifare.h | 2 +- utils/nfc-mfultralight.c | 22 ++++++++++------------ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/utils/mifare.h b/utils/mifare.h index 75d65dec..627cc598 100644 --- a/utils/mifare.h +++ b/utils/mifare.h @@ -247,7 +247,7 @@ typedef struct { mifareul_block amb[11]; } mifareul_ev1_mf0ul21_tag; -// NOT really UL but so similar we can re-use this code +// NTAG is a range of NXP tags some of which are essentially Ultralights so we can support them here // if Edwin van Andel doesn't distract us... // https://www.nxp.com/docs/en/data-sheet/NTAG213_215_216.pdf diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 99916a2f..3fe21003 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -349,9 +349,8 @@ write_card(bool write_otp, bool write_lock, bool write_dyn_lock, bool write_uid) char buffer[BUFSIZ]; - // NTAG does not have explicit OTP bytes - if (!write_otp && iNTAGType == NTAG_NONE) { - printf("Write OTP Bytes ? [yN] "); + if (!write_otp) { + printf("Write OTP/Capability Bytes ? [yN] "); if (!fgets(buffer, BUFSIZ, stdin)) { ERR("Unable to read standard input."); } @@ -402,8 +401,8 @@ write_card(bool write_otp, bool write_lock, bool write_dyn_lock, bool write_uid) uiSkippedPages++; continue; } - // NTAG doesn't have OTP blocks - if ((iNTAGType == NTAG_NONE && page == 0x3) && (!write_otp)) { + // OTP/Capability blocks + if ((page == 0x3) && (!write_otp)) { printf("s"); uiSkippedPages++; continue; @@ -650,30 +649,29 @@ main(int argc, const char *argv[]) // test if tag is EV1 or NTAG if (get_ev1_version()) { if (!bPWD) - printf("Tag is EV1 - PASSWORD may be required\n"); - printf("EV1 type: "); + printf("WARNING: Tag is EV1 or NTAG - PASSWORD may be required\n"); if (abtRx[6] == 0x0b) { - printf("MF0UL11 (48 bytes)\n"); + printf("EV1 type: MF0UL11 (48 bytes)\n"); uiBlocks = 20; // total number of 4 byte 'pages' iDumpSize = uiBlocks * 4; iEV1Type = EV1_UL11; } else if (abtRx[6] == 0x0e) { - printf("MF0UL21 (128 user bytes)\n"); + printf("EV1 type: MF0UL21 (128 user bytes)\n"); uiBlocks = 41; iDumpSize = uiBlocks * 4; iEV1Type = EV1_UL21; } else if (abtRx[6] == 0x0f) { - printf("NTAG213 (144 user bytes)\n"); + printf("NTAG Type: NTAG213 (144 user bytes)\n"); uiBlocks = 45; iDumpSize = uiBlocks * 4; iNTAGType = NTAG_213; } else if (abtRx[6] == 0x11) { - printf("NTAG215 (504 user bytes)\n"); + printf("NTAG Type: NTAG215 (504 user bytes)\n"); uiBlocks = 135; iDumpSize = uiBlocks * 4; iNTAGType = NTAG_215; } else if (abtRx[6] == 0x13) { - printf("NTAG216 (888 user bytes)\n"); + printf("NTAG Type: NTAG216 (888 user bytes)\n"); uiBlocks = 231; iDumpSize = uiBlocks * 4; iNTAGType = NTAG_216; From d11db46ddd168bc0182f7fba843d9c1c5d526c4d Mon Sep 17 00:00:00 2001 From: Markus Werle Date: Tue, 2 Oct 2018 12:14:29 +0200 Subject: [PATCH 219/318] fix CMAKE_MODULE_PATH for libnfc as a submodule This fixes #496 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 76babf29..2ad92d79 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,7 @@ ADD_DEFINITIONS("-DHAVE_CONFIG_H") INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include) # make it easy to locate CMake modules for finding libraries -SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/") +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/modules/") # Options option (LIBNFC_LOG "Enable log facility (errors, warning, info and debug messages)" ON) From c52cdb10c8aa40556d08bf82c981c1dff8924c32 Mon Sep 17 00:00:00 2001 From: Stean Date: Sun, 4 Nov 2018 21:22:46 +0100 Subject: [PATCH 220/318] Add undocumented option -s to usage listing --- utils/nfc-relay-picc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/nfc-relay-picc.c b/utils/nfc-relay-picc.c index 802372b0..d694f8a6 100644 --- a/utils/nfc-relay-picc.c +++ b/utils/nfc-relay-picc.c @@ -99,6 +99,7 @@ print_usage(char *argv[]) printf("\t-q\tQuiet mode. Suppress printing of relayed data (improves timing).\n"); printf("\t-t\tTarget mode only (the one on reader side). Data expected from FD3 to FD4.\n"); printf("\t-i\tInitiator mode only (the one on tag side). Data expected from FD3 to FD4.\n"); + printf("\t-s\tSwap roles of found devices.\n"); printf("\t-n N\tAdds a waiting time of N seconds (integer) in the relay to mimic long distance.\n"); } From f93169feb48af829685c716d2475cbbc7b41b343 Mon Sep 17 00:00:00 2001 From: Stean Date: Sun, 4 Nov 2018 21:30:35 +0100 Subject: [PATCH 221/318] Add undocumented option -s to nfc-relay-picc man page --- utils/nfc-relay-picc.1 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/utils/nfc-relay-picc.1 b/utils/nfc-relay-picc.1 index f95db28f..e622752a 100644 --- a/utils/nfc-relay-picc.1 +++ b/utils/nfc-relay-picc.1 @@ -34,6 +34,11 @@ tag <---> initiator (relay) <---> target (relay) <---> original reader Commands are read from file descriptor 3 Responses are sent to file descriptor 4 +\fB-s\fP + Swap roles of found devices + Usually the first found device is used as target (emulator) and the second + as initiator (reader). Using this option these roles are inversed. + \fB-n\fP \fIN\fP Adds a waiting time of \fIN\fP seconds (integer) in the loop From 2418d946a31aa518495fa6c0c3929804a870b76b Mon Sep 17 00:00:00 2001 From: Emmanuel Dreyfus Date: Mon, 12 Nov 2018 14:46:31 +0000 Subject: [PATCH 222/318] Add missing timeout Add a tiemout in pn53x_initiator_select_passive_target() so that we do not get stuck forever when pn533 misses a toggle bit change. --- libnfc/chips/pn53x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 03642486..89af830f 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1278,7 +1278,7 @@ pn53x_initiator_select_passive_target(struct nfc_device *pnd, const uint8_t *pbtInitData, const size_t szInitData, nfc_target *pnt) { - return pn53x_initiator_select_passive_target_ext(pnd, nm, pbtInitData, szInitData, pnt, 0); + return pn53x_initiator_select_passive_target_ext(pnd, nm, pbtInitData, szInitData, pnt, 300); } int From 85100c0aaee728a3c254d4feed6ed5d8035bbd4a Mon Sep 17 00:00:00 2001 From: Emmanuel Dreyfus Date: Mon, 12 Nov 2018 15:26:43 +0000 Subject: [PATCH 223/318] Prefer hardcoded PN533 descriptors to the real ones PN533 easily corrupts its USB descriptors. We know that and we already try to detect and even repair them. However there are situations where lower software layers get confused before libnfc can help. On Windows, libusb may set dev->config to NULL, but we can also have a non NULL dev->config referencing corrupted data. In order to get more robust, let us replace the Windows libusb specific (dev->config == NULL) test by an inconditionnal use of hardcoded descriptors when they are available. --- libnfc/drivers/pn53x_usb.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index 807e98e8..d0014089 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -236,7 +236,7 @@ pn53x_usb_get_device_model(uint16_t vendor_id, uint16_t product_id) return UNKNOWN; } -static void +static bool pn53x_usb_get_end_points_default(struct usb_device *dev, struct pn53x_usb_data *data) { for (size_t n = 0; n < sizeof(pn53x_usb_supported_devices) / sizeof(struct pn53x_usb_supported_device); n++) { @@ -246,13 +246,13 @@ pn53x_usb_get_end_points_default(struct usb_device *dev, struct pn53x_usb_data * data->uiEndPointIn = pn53x_usb_supported_devices[n].uiEndPointIn; data->uiEndPointOut = pn53x_usb_supported_devices[n].uiEndPointOut; data->uiMaxPacketSize = pn53x_usb_supported_devices[n].uiMaxPacketSize; - } - return; + return true; + } } } - return; + return false; } int pn53x_usb_ack(nfc_device *pnd); @@ -305,13 +305,12 @@ pn53x_usb_scan(const nfc_context *context, nfc_connstring connstrings[], const s if ((pn53x_usb_supported_devices[n].vendor_id == dev->descriptor.idVendor) && (pn53x_usb_supported_devices[n].product_id == dev->descriptor.idProduct)) { // Make sure there are 2 endpoints available - // with libusb-win32 we got some null pointers so be robust before looking at endpoints: - if (dev->config == NULL) { - // We tolerate null config if we have defaults - if (pn53x_usb_supported_devices[n].uiMaxPacketSize == 0) - // Nope, we maybe want the next one, let's try to find another - continue; - } else { + // libusb-win32 may return a NULL dev->config, + // or the descriptoes may be corrupted, hence + // let us assume we will use hardcoded defaults + // from n53x_usb_supported_devices if available. + // otherwise get data from the descriptors. + if (pn53x_usb_supported_devices[n].uiMaxPacketSize == 0) { if (dev->config->interface == NULL || dev->config->interface->altsetting == NULL) { // Nope, we maybe want the next one, let's try to find another continue; @@ -422,11 +421,9 @@ pn53x_usb_open(const nfc_context *context, const nfc_connstring connstring) // Open the USB device if ((data.pudh = usb_open(dev)) == NULL) continue; - // Retrieve end points, using default if dev->config is broken - if (dev->config == NULL) { - pn53x_usb_get_end_points_default(dev, &data); - data.possibly_corrupted_usbdesc = true; - } else { + // Retrieve end points, using hardcoded defaults if available + // or using the descriptors otherwise. + if (pn53x_usb_get_end_points_default(dev, &data) == false) { pn53x_usb_get_end_points(dev, &data); } // Set configuration From 7ca85a02de3baeef6b4b6f457b899cb848325aee Mon Sep 17 00:00:00 2001 From: Emmanuel Dreyfus Date: Tue, 13 Nov 2018 12:50:19 +0000 Subject: [PATCH 224/318] Fix typos --- libnfc/drivers/pn53x_usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index d0014089..18c51fc6 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -306,9 +306,9 @@ pn53x_usb_scan(const nfc_context *context, nfc_connstring connstrings[], const s (pn53x_usb_supported_devices[n].product_id == dev->descriptor.idProduct)) { // Make sure there are 2 endpoints available // libusb-win32 may return a NULL dev->config, - // or the descriptoes may be corrupted, hence + // or the descriptors may be corrupted, hence // let us assume we will use hardcoded defaults - // from n53x_usb_supported_devices if available. + // from pn53x_usb_supported_devices if available. // otherwise get data from the descriptors. if (pn53x_usb_supported_devices[n].uiMaxPacketSize == 0) { if (dev->config->interface == NULL || dev->config->interface->altsetting == NULL) { 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 225/318] 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 97e2882b..61cedfd5 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 bc3fe6c5..3f22c61d 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 3fe21003..5e71a3aa 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 a9e4c915f266316096295ba77f9815fb0cdc6b0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Tarti=C3=A8re?= Date: Tue, 5 Feb 2019 08:15:52 -1000 Subject: [PATCH 226/318] Add missing INCLUDES CC pn53x-tamashell.o pn53x-tamashell.c:48:12: fatal error: 'readline/readline.h' file not found # include ^~~~~~~~~~~~~~~~~~~~~ 1 error generated. --- examples/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/Makefile.am b/examples/Makefile.am index c767532c..8048b9f1 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -74,6 +74,7 @@ pn53x_sam_LDADD = $(top_builddir)/libnfc/libnfc.la \ pn53x_tamashell_SOURCES = pn53x-tamashell.c pn53x_tamashell_LDADD = $(top_builddir)/libnfc/libnfc.la \ $(top_builddir)/utils/libnfcutils.la +pn53x_tamashell_CFLAGS = @READLINE_INCLUDES@ pn53x_tamashell_LDFLAGS = @READLINE_LIBS@ quick_start_example1_SOURCES = doc/quick_start_example1.c From ae5618800587185b7153544f58c29785f2433cbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Tarti=C3=A8re?= Date: Fri, 8 Feb 2019 07:25:55 -1000 Subject: [PATCH 227/318] Fix outsource build with the autotools --- examples/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Makefile.am b/examples/Makefile.am index 8048b9f1..d7018ac4 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -74,7 +74,7 @@ pn53x_sam_LDADD = $(top_builddir)/libnfc/libnfc.la \ pn53x_tamashell_SOURCES = pn53x-tamashell.c pn53x_tamashell_LDADD = $(top_builddir)/libnfc/libnfc.la \ $(top_builddir)/utils/libnfcutils.la -pn53x_tamashell_CFLAGS = @READLINE_INCLUDES@ +pn53x_tamashell_CFLAGS = @READLINE_INCLUDES@ -I$(top_srcdir) pn53x_tamashell_LDFLAGS = @READLINE_LIBS@ quick_start_example1_SOURCES = doc/quick_start_example1.c From c59219905c7fa136205d4f65edd3f9dfc4efe239 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Tarti=C3=A8re?= Date: Fri, 8 Feb 2019 07:29:42 -1000 Subject: [PATCH 228/318] Do outsource builds on CI This helps figurig-out missing -I more easily. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 948c756b..2198598c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,5 +17,5 @@ addons: - libcutter-dev script: - - if [ $BLD == autoconf ]; then autoreconf -vfi && ./configure --prefix=$HOME/.local/ && make -j2 && make install; fi - - if [ $BLD == cmake ]; then cmake -DCMAKE_INSTALL_PREFIX=~/.local . && make -j2 && make install; fi + - if [ $BLD == autoconf ]; then autoreconf -vfi && mkdir build && cd build && ../configure --prefix=$HOME/.local/ && make -j2 && make install; fi + - if [ $BLD == cmake ]; then mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX=~/.local .. && make -j2 && make install; fi From c42e2502d4627d3ea62f83c32677b100bb3cebdc Mon Sep 17 00:00:00 2001 From: rstular Date: Sun, 28 Apr 2019 09:41:04 +0200 Subject: [PATCH 229/318] Fixed a typo in examples/nfc-emulate-uid.1 --- examples/nfc-emulate-uid.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/nfc-emulate-uid.1 b/examples/nfc-emulate-uid.1 index f0e21640..a731bfc0 100644 --- a/examples/nfc-emulate-uid.1 +++ b/examples/nfc-emulate-uid.1 @@ -14,7 +14,7 @@ fully customized UID but only of "random" UIDs, which always start with 0x08. The nfc-emulate-uid tool demonstrates that this can still be done using transmission of raw frames, and the desired UID can be optionally specified. -This makes it a serious thread for security systems that rely only on the +This makes it a serious threat for security systems that rely only on the uniqueness of the UID. Unfortunately, this example can't directly start in fully customisable From ebb13d8965114bac431a95a89576be35a0cf45f8 Mon Sep 17 00:00:00 2001 From: rstular Date: Mon, 29 Apr 2019 09:49:09 +0200 Subject: [PATCH 230/318] Updated function declaration in utils/nfc-mfultralight.c Updated a function declaration in utils/nfc-mfultralight.c to match the new style of C function declarations. --- utils/nfc-mfultralight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 3fe21003..8c6859af 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -290,7 +290,7 @@ unlock_card(void) return true; } -static bool check_magic() +static bool check_magic(void) { bool bFailure = false; int uid_data; From 91f7db5b4de3c984d84206902b5486183a075607 Mon Sep 17 00:00:00 2001 From: Khem Raj Date: Mon, 20 May 2019 22:10:05 -0700 Subject: [PATCH 231/318] usbbus: Include stdint.h for uintX_t stdint.h is needed for uintX_t typedefs which are used to replace u_intX_t in libusb API headers in the cmake files Signed-off-by: Khem Raj --- libnfc/buses/usbbus.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libnfc/buses/usbbus.h b/libnfc/buses/usbbus.h index 87f6a85f..3c0381a8 100644 --- a/libnfc/buses/usbbus.h +++ b/libnfc/buses/usbbus.h @@ -35,6 +35,7 @@ #ifndef _WIN32 // Under POSIX system, we use libusb (>= 0.1.12) +#include #include #define USB_TIMEDOUT ETIMEDOUT #define _usb_strerror( X ) strerror(-X) From a4af2be66c85b1846327b2ab73bb4c63c7b3b40f Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 17 Jul 2019 22:29:09 +0200 Subject: [PATCH 232/318] 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 18c51fc6..56c6ebab 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 233/318] 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 2ad92d79..576f6e70 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 234/318] 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 | 82 ++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 3fe21003..8ae641f7 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; - - 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; +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 - 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; + } + 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; } - } - - //Initially check if we can unlock via the MF method - if (unlock_card()) { + 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 235/318] 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 | 247 +++++++++++++++++++++++++++++++++++------- 1 file changed, 208 insertions(+), 39 deletions(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index bc3fe6c5..ba07b6f8 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)); + 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 { - // 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)); + // 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; + } - // 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; + //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; + } + } - // Make sure a earlier write did not fail + 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; + } + } + } + + // 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 236/318] 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 2198598c..b3313098 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 237/318] Update .travis.yml --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2198598c..b3313098 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 75e5e23c8194a016dabe0876361e1b3db65eed10 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 2 Sep 2019 11:05:48 +0200 Subject: [PATCH 238/318] Added driver for contactless PC/SC readers - only initiator mode is supported - properties are choosen as they are available via PC/SC, the rest of the defaults are chosen to be compatible with Mifare DESFire - This commit allows reading Mifare DESFire via PC/SC with libfreefare --- libnfc/drivers/Makefile.am | 4 + libnfc/drivers/acr122_pcsc.c | 2 +- libnfc/drivers/pcsc.c | 751 +++++++++++++++++++++++++++++++++++ libnfc/drivers/pcsc.h | 35 ++ libnfc/nfc.c | 7 + m4/libnfc_drivers.m4 | 12 +- 6 files changed, 808 insertions(+), 3 deletions(-) create mode 100644 libnfc/drivers/pcsc.c create mode 100644 libnfc/drivers/pcsc.h diff --git a/libnfc/drivers/Makefile.am b/libnfc/drivers/Makefile.am index 1ac65b22..6550af29 100644 --- a/libnfc/drivers/Makefile.am +++ b/libnfc/drivers/Makefile.am @@ -7,6 +7,10 @@ libnfcdrivers_la_SOURCES = libnfcdrivers_la_CFLAGS = @DRIVERS_CFLAGS@ -I$(top_srcdir)/libnfc -I$(top_srcdir)/libnfc/buses libnfcdrivers_la_LIBADD = +if DRIVER_PCSC_ENABLED +libnfcdrivers_la_SOURCES += pcsc.c pcsc.h +endif + if DRIVER_ACR122_PCSC_ENABLED libnfcdrivers_la_SOURCES += acr122_pcsc.c acr122_pcsc.h endif diff --git a/libnfc/drivers/acr122_pcsc.c b/libnfc/drivers/acr122_pcsc.c index 18751665..f5cc02e2 100644 --- a/libnfc/drivers/acr122_pcsc.c +++ b/libnfc/drivers/acr122_pcsc.c @@ -93,7 +93,7 @@ const struct pn53x_io acr122_pcsc_io; // Prototypes char *acr122_pcsc_firmware(nfc_device *pnd); -const char *supported_devices[] = { +static const char *supported_devices[] = { "ACS ACR122", // ACR122U & Touchatag, last version "ACS ACR 38U-CCID", // Touchatag, early version "ACS ACR38U-CCID", // Touchatag, early version, under MacOSX diff --git a/libnfc/drivers/pcsc.c b/libnfc/drivers/pcsc.c new file mode 100644 index 00000000..06480a93 --- /dev/null +++ b/libnfc/drivers/pcsc.c @@ -0,0 +1,751 @@ +/*- + * Free/Libre Near Field Communication (NFC) library + * + * Libnfc historical contributors: + * Copyright (C) 2019 Frank Morgner + * See AUTHORS file for a more comprehensive list of contributors. + * Additional contributors of this file: + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see + */ + +/** + * @file pcsc.c + * @brief Driver for non-ACR122 devices behind PC/SC + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif // HAVE_CONFIG_H + +#include +#include +#include +#include +#include + +#include + +#include "drivers/pcsc.h" +#include "nfc-internal.h" + +// Bus +#ifdef __APPLE__ +#include +#include +#else +#ifndef _Win32 +#include +#endif +#include +#endif + +#define PCSC_DRIVER_NAME "pcsc" + +#include + +#define LOG_GROUP NFC_LOG_GROUP_DRIVER +#define LOG_CATEGORY "libnfc.driver.pcsc" + +static const char *supported_devices[] = { + "ACS ACR122", // ACR122U & Touchatag, last version + "ACS ACR 38U-CCID", // Touchatag, early version + "ACS ACR38U-CCID", // Touchatag, early version, under MacOSX + "ACS AET65", // Touchatag using CCID driver version >= 1.4.6 + " CCID USB", // ?? + NULL +}; + +struct pcsc_data { + SCARDHANDLE hCard; + SCARD_IO_REQUEST ioCard; + DWORD dwShareMode; + DWORD last_error; +}; + +#define DRIVER_DATA(pnd) ((struct pcsc_data*)(pnd->driver_data)) + +static SCARDCONTEXT _SCardContext; +static int _iSCardContextRefCount = 0; + +const nfc_baud_rate pcsc_supported_brs[] = {NBR_106, NBR_424, 0}; +const nfc_modulation_type pcsc_supported_mts[] = {NMT_ISO14443A, NMT_ISO14443B, 0}; + +SCARDCONTEXT * +pcsc_get_scardcontext(void) +{ + if (_iSCardContextRefCount == 0) { + if (SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &_SCardContext) != SCARD_S_SUCCESS) + return NULL; + } + _iSCardContextRefCount++; + + return &_SCardContext; +} + +void +pcsc_free_scardcontext(void) +{ + if (_iSCardContextRefCount) { + _iSCardContextRefCount--; + if (!_iSCardContextRefCount) { + SCardReleaseContext(_SCardContext); + } + } +} + +#define ICC_TYPE_UNKNOWN 0 +#define ICC_TYPE_14443A 5 +#define ICC_TYPE_14443B 6 + +uint8_t pcsc_get_icc_type(struct nfc_device *pnd) +{ + uint8_t it = 0; + DWORD dwItLen = sizeof it; + DRIVER_DATA(pnd)->last_error = SCardGetAttrib(DRIVER_DATA(pnd)->hCard, SCARD_ATTR_ICC_TYPE_PER_ATR, &it, &dwItLen); + return it; +} + +int pcsc_get_uid(struct nfc_device *pnd, uint8_t *puid, size_t szuid) +{ + uint8_t get_data[] = {0xFF, 0xCA, 0x00, 0x00, 0x00}, data[256 + 2]; + DWORD dwRxLen = sizeof data; + + LOG_HEX(NFC_LOG_GROUP_COM, "TX", get_data, sizeof get_data); + DRIVER_DATA(pnd)->last_error = SCardTransmit(DRIVER_DATA(pnd)->hCard, &(DRIVER_DATA(pnd)->ioCard), get_data, sizeof get_data, NULL, data, &dwRxLen); + if ((DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS) + || dwRxLen < 2) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reader doesn't support request for UID"); + pnd->last_error = NFC_EIO; + return pnd->last_error; + } + LOG_HEX(NFC_LOG_GROUP_COM, "RX", data, dwRxLen); + if (szuid < (size_t) dwRxLen - 2) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Malformed response code"); + pnd->last_error = NFC_EINVARG; + return pnd->last_error; + } + memcpy(puid, data, dwRxLen - 2); + return dwRxLen - 2; +} + +int pcsc_props_to_target(uint8_t it, const uint8_t *patr, size_t szatr, const uint8_t *puid, int szuid, const nfc_modulation_type nmt, nfc_target *pnt) +{ + if (NULL != pnt) { + switch (nmt) { + case NMT_ISO14443A: + if ((it == ICC_TYPE_UNKNOWN || it == ICC_TYPE_14443A) + && (szuid <= 0 || szuid == 4 || szuid == 7 || szuid == 10) + && NULL != patr && szatr >= 5 + && patr[0] == 0x3B + && patr[1] == (0x80 | ((uint8_t)(szatr - 5))) + && patr[2] == 0x80 + && patr[3] == 0x01) { + memset(pnt, 0, sizeof * pnt); + pnt->nm.nmt = NMT_ISO14443A; + pnt->nm.nbr = pcsc_supported_brs[0]; + if (szuid > 0) { + memcpy(pnt->nti.nai.abtUid, puid, szuid); + pnt->nti.nai.szUidLen = szuid; + } + /* SAK_ISO14443_4_COMPLIANT */ + pnt->nti.nai.btSak = 0x20; + /* Choose TL, TA, TB, TC according to Mifare DESFire */ + memcpy(pnt->nti.nai.abtAts, "\x75\x77\x81\x02", 4); + /* copy historical bytes */ + memcpy(pnt->nti.nai.abtAts + 4, patr + 4, (uint8_t)(szatr - 5)); + pnt->nti.nai.szAtsLen = 4 + (uint8_t)(szatr - 5); + return NFC_SUCCESS; + } + break; + case NMT_ISO14443B: + if ((ICC_TYPE_UNKNOWN == 0 || ICC_TYPE_14443B == 6) + && (szuid <= 0 || szuid == 8) + && NULL != patr && szatr == 5 + 8 + && patr[0] == 0x3B + && patr[1] == (0x80 | 0x08) + && patr[2] == 0x80 + && patr[3] == 0x01) { + memset(pnt, 0, sizeof * pnt); + pnt->nm.nmt = NMT_ISO14443B; + pnt->nm.nbr = pcsc_supported_brs[0]; + memcpy(pnt->nti.nbi.abtApplicationData, patr + 4, 4); + memcpy(pnt->nti.nbi.abtProtocolInfo, patr + 8, 3); + /* PI_ISO14443_4_SUPPORTED */ + pnt->nti.nbi.abtProtocolInfo[1] = 0x01; + return NFC_SUCCESS; + } + break; + default: + break; + } + } + return NFC_EINVARG; +} + +#define PCSC_MAX_DEVICES 16 +/** + * @brief List opened devices + * + * Probe PCSC to find any reader but the ACR122 devices (ACR122U and Touchatag/Tikitag). + * + * @param connstring array of nfc_connstring where found device's connection strings will be stored. + * @param connstrings_len size of connstrings array. + * @return number of devices found. + */ +static size_t +pcsc_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len) +{ + (void) context; + size_t szPos = 0; + char acDeviceNames[256 + 64 * PCSC_MAX_DEVICES]; + size_t szDeviceNamesLen = sizeof(acDeviceNames); + SCARDCONTEXT *pscc; + int i; + + // Clear the reader list + memset(acDeviceNames, '\0', szDeviceNamesLen); + + // Test if context succeeded + if (!(pscc = pcsc_get_scardcontext())) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "Warning: %s", "PCSC context not found (make sure PCSC daemon is running)."); + return 0; + } + // Retrieve the string array of all available pcsc readers + DWORD dwDeviceNamesLen = szDeviceNamesLen; + if (SCardListReaders(*pscc, NULL, acDeviceNames, &dwDeviceNamesLen) != SCARD_S_SUCCESS) + return 0; + + size_t device_found = 0; + while ((acDeviceNames[szPos] != '\0') && (device_found < connstrings_len)) { + bool bSupported = false; + for (i = 0; supported_devices[i] && !bSupported; i++) { + int l = strlen(supported_devices[i]); + bSupported = 0 == !strncmp(supported_devices[i], acDeviceNames + szPos, l); + } + + if (bSupported) { + // Supported non-ACR122 device found + snprintf(connstrings[device_found], sizeof(nfc_connstring), "%s:%s", PCSC_DRIVER_NAME, acDeviceNames + szPos); + device_found++; + } else { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Skipping PCSC device [%s] as it is supported by acr122_pcsc driver.", acDeviceNames + szPos); + } + + // Find next device name position + while (acDeviceNames[szPos++] != '\0'); + } + pcsc_free_scardcontext(); + + return device_found; +} + +struct pcsc_descriptor { + char *pcsc_device_name; +}; + +static nfc_device * +pcsc_open(const nfc_context *context, const nfc_connstring connstring) +{ + struct pcsc_descriptor ndd; + int connstring_decode_level = connstring_decode(connstring, PCSC_DRIVER_NAME, "pcsc", &ndd.pcsc_device_name, NULL); + + if (connstring_decode_level < 1) { + return NULL; + } + + nfc_connstring fullconnstring; + if (connstring_decode_level == 1) { + // Device was not specified, take the first one we can find + size_t szDeviceFound = pcsc_scan(context, &fullconnstring, 1); + if (szDeviceFound < 1) + return NULL; + connstring_decode_level = connstring_decode(fullconnstring, PCSC_DRIVER_NAME, "pcsc", &ndd.pcsc_device_name, NULL); + if (connstring_decode_level < 2) { + return NULL; + } + } else { + memcpy(fullconnstring, connstring, sizeof(nfc_connstring)); + } + if (strlen(ndd.pcsc_device_name) < 5) { // We can assume it's a reader ID as pcsc_name always ends with "NN NN" + // Device was not specified, only ID, retrieve it + size_t index; + if (sscanf(ndd.pcsc_device_name, "%4" SCNuPTR, &index) != 1) { + free(ndd.pcsc_device_name); + return NULL; + } + nfc_connstring *ncs = malloc(sizeof(nfc_connstring) * (index + 1)); + if (!ncs) { + perror("malloc"); + free(ndd.pcsc_device_name); + return NULL; + } + size_t szDeviceFound = pcsc_scan(context, ncs, index + 1); + if (szDeviceFound < index + 1) { + free(ncs); + free(ndd.pcsc_device_name); + return NULL; + } + strncpy(fullconnstring, ncs[index], sizeof(nfc_connstring)); + fullconnstring[sizeof(nfc_connstring) - 1] = '\0'; + free(ncs); + connstring_decode_level = connstring_decode(fullconnstring, PCSC_DRIVER_NAME, "pcsc", &ndd.pcsc_device_name, NULL); + + if (connstring_decode_level < 2) { + free(ndd.pcsc_device_name); + return NULL; + } + } + + nfc_device *pnd = nfc_device_new(context, fullconnstring); + if (!pnd) { + perror("malloc"); + goto error; + } + pnd->driver_data = malloc(sizeof(struct pcsc_data)); + if (!pnd->driver_data) { + perror("malloc"); + goto error; + } + + SCARDCONTEXT *pscc; + + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Attempt to open %s", ndd.pcsc_device_name); + // Test if context succeeded + if (!(pscc = pcsc_get_scardcontext())) + goto error; + DRIVER_DATA(pnd)->last_error = SCardConnect(*pscc, ndd.pcsc_device_name, SCARD_SHARE_DIRECT, 0, &(DRIVER_DATA(pnd)->hCard), (void *) & (DRIVER_DATA(pnd)->ioCard.dwProtocol)); + if (DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS) { + // We can not connect to this device. + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC connect failed"); + goto error; + } + // Configure I/O settings for card communication + DRIVER_DATA(pnd)->ioCard.cbPciLength = sizeof(SCARD_IO_REQUEST); + DRIVER_DATA(pnd)->dwShareMode = SCARD_SHARE_DIRECT; + + // Done, we found the reader we are looking for + snprintf(pnd->name, sizeof(pnd->name), "%s", ndd.pcsc_device_name); + + pnd->driver = &pcsc_driver; + + free(ndd.pcsc_device_name); + return pnd; + +error: + free(ndd.pcsc_device_name); + nfc_device_free(pnd); + return NULL; +} + +static void +pcsc_close(nfc_device *pnd) +{ + SCardDisconnect(DRIVER_DATA(pnd)->hCard, SCARD_LEAVE_CARD); + pcsc_free_scardcontext(); + + nfc_device_free(pnd); +} + +static const char *stringify_error(const LONG pcscError) +{ + static char strError[75]; + const char *msg = NULL; + + switch (pcscError) { + case SCARD_S_SUCCESS: + msg = "Command successful."; + break; + case SCARD_F_INTERNAL_ERROR: + msg = "Internal error."; + break; + case SCARD_E_CANCELLED: + msg = "Command cancelled."; + break; + case SCARD_E_INVALID_HANDLE: + msg = "Invalid handle."; + break; + case SCARD_E_INVALID_PARAMETER: + msg = "Invalid parameter given."; + break; + case SCARD_E_INVALID_TARGET: + msg = "Invalid target given."; + break; + case SCARD_E_NO_MEMORY: + msg = "Not enough memory."; + break; + case SCARD_F_WAITED_TOO_LONG: + msg = "Waited too long."; + break; + case SCARD_E_INSUFFICIENT_BUFFER: + msg = "Insufficient buffer."; + break; + case SCARD_E_UNKNOWN_READER: + msg = "Unknown reader specified."; + break; + case SCARD_E_TIMEOUT: + msg = "Command timeout."; + break; + case SCARD_E_SHARING_VIOLATION: + msg = "Sharing violation."; + break; + case SCARD_E_NO_SMARTCARD: + msg = "No smart card inserted."; + break; + case SCARD_E_UNKNOWN_CARD: + msg = "Unknown card."; + break; + case SCARD_E_CANT_DISPOSE: + msg = "Cannot dispose handle."; + break; + case SCARD_E_PROTO_MISMATCH: + msg = "Card protocol mismatch."; + break; + case SCARD_E_NOT_READY: + msg = "Subsystem not ready."; + break; + case SCARD_E_INVALID_VALUE: + msg = "Invalid value given."; + break; + case SCARD_E_SYSTEM_CANCELLED: + msg = "System cancelled."; + break; + case SCARD_F_COMM_ERROR: + msg = "RPC transport error."; + break; + case SCARD_F_UNKNOWN_ERROR: + msg = "Unknown error."; + break; + case SCARD_E_INVALID_ATR: + msg = "Invalid ATR."; + break; + case SCARD_E_NOT_TRANSACTED: + msg = "Transaction failed."; + break; + case SCARD_E_READER_UNAVAILABLE: + msg = "Reader is unavailable."; + break; + /* case SCARD_P_SHUTDOWN: */ + case SCARD_E_PCI_TOO_SMALL: + msg = "PCI struct too small."; + break; + case SCARD_E_READER_UNSUPPORTED: + msg = "Reader is unsupported."; + break; + case SCARD_E_DUPLICATE_READER: + msg = "Reader already exists."; + break; + case SCARD_E_CARD_UNSUPPORTED: + msg = "Card is unsupported."; + break; + case SCARD_E_NO_SERVICE: + msg = "Service not available."; + break; + case SCARD_E_SERVICE_STOPPED: + msg = "Service was stopped."; + break; + /* case SCARD_E_UNEXPECTED: */ + /* case SCARD_E_ICC_CREATEORDER: */ + /* case SCARD_E_UNSUPPORTED_FEATURE: */ + /* case SCARD_E_DIR_NOT_FOUND: */ + /* case SCARD_E_NO_DIR: */ + /* case SCARD_E_NO_FILE: */ + /* case SCARD_E_NO_ACCESS: */ + /* case SCARD_E_WRITE_TOO_MANY: */ + /* case SCARD_E_BAD_SEEK: */ + /* case SCARD_E_INVALID_CHV: */ + /* case SCARD_E_UNKNOWN_RES_MNG: */ + /* case SCARD_E_NO_SUCH_CERTIFICATE: */ + /* case SCARD_E_CERTIFICATE_UNAVAILABLE: */ + case SCARD_E_NO_READERS_AVAILABLE: + msg = "Cannot find a smart card reader."; + break; + /* case SCARD_E_COMM_DATA_LOST: */ + /* case SCARD_E_NO_KEY_CONTAINER: */ + /* case SCARD_E_SERVER_TOO_BUSY: */ + case SCARD_W_UNSUPPORTED_CARD: + msg = "Card is not supported."; + break; + case SCARD_W_UNRESPONSIVE_CARD: + msg = "Card is unresponsive."; + break; + case SCARD_W_UNPOWERED_CARD: + msg = "Card is unpowered."; + break; + case SCARD_W_RESET_CARD: + msg = "Card was reset."; + break; + case SCARD_W_REMOVED_CARD: + msg = "Card was removed."; + break; + /* case SCARD_W_SECURITY_VIOLATION: */ + /* case SCARD_W_WRONG_CHV: */ + /* case SCARD_W_CHV_BLOCKED: */ + /* case SCARD_W_EOF: */ + /* case SCARD_W_CANCELLED_BY_USER: */ + /* case SCARD_W_CARD_NOT_AUTHENTICATED: */ + + case SCARD_E_UNSUPPORTED_FEATURE: + msg = "Feature not supported."; + break; + default: + (void)snprintf(strError, sizeof(strError) - 1, "Unknown error: 0x%08lX", + pcscError); + }; + + if (msg) + (void)strncpy(strError, msg, sizeof(strError)); + else + (void)snprintf(strError, sizeof(strError) - 1, "Unknown error: 0x%08lX", + pcscError); + + /* add a null byte */ + strError[sizeof(strError) - 1] = '\0'; + + return strError; +} + +const char * +pcsc_strerror(const struct nfc_device *pnd) +{ + return stringify_error(DRIVER_DATA(pnd)->last_error); +} + +int pcsc_initiator_init(struct nfc_device *pnd) +{ + (void) pnd; + return NFC_SUCCESS; +} + +int pcsc_initiator_select_passive_target(struct nfc_device *pnd, const nfc_modulation nm, const uint8_t *pbtInitData, const size_t szInitData, nfc_target *pnt) +{ + uint8_t pbAtr[MAX_ATR_SIZE]; + uint8_t uid[10]; + DWORD dwState, dwProtocol, dwReaderLen, dwAtrLen = sizeof pbAtr; + + (void) pbtInitData; + (void) szInitData; + + if (nm.nbr != pcsc_supported_brs[0] && nm.nbr != pcsc_supported_brs[1]) + return NFC_EINVARG; + DRIVER_DATA(pnd)->last_error = SCardStatus(DRIVER_DATA(pnd)->hCard, NULL, &dwReaderLen, &dwState, &dwProtocol, pbAtr, &dwAtrLen); + if ((DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS + && DRIVER_DATA(pnd)->last_error != SCARD_W_RESET_CARD) + || !(dwState & SCARD_PRESENT)) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "No target present"); + return NFC_ENOTSUCHDEV; + } + uint8_t it = pcsc_get_icc_type(pnd); + int szuid = pcsc_get_uid(pnd, uid, sizeof uid); + if (pcsc_props_to_target(it, pbAtr, dwAtrLen, uid, szuid, nm.nmt, pnt) != NFC_SUCCESS + || (DRIVER_DATA(pnd)->last_error = SCardReconnect((DRIVER_DATA(pnd)->hCard), SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_LEAVE_CARD, (void *) & (DRIVER_DATA(pnd)->ioCard.dwProtocol))) != SCARD_S_SUCCESS) { + // We can not reconnect to this device. + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC reconnect failed"); + return NFC_EIO; + } + DRIVER_DATA(pnd)->dwShareMode = SCARD_SHARE_SHARED; + return 1; +} + +int pcsc_initiator_deselect_target(struct nfc_device *pnd) +{ + DRIVER_DATA(pnd)->last_error = SCardReconnect((DRIVER_DATA(pnd)->hCard), SCARD_SHARE_DIRECT, 0, SCARD_LEAVE_CARD, (void *) & (DRIVER_DATA(pnd)->ioCard.dwProtocol)); + if (DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS + && DRIVER_DATA(pnd)->last_error != SCARD_W_RESET_CARD) { + // We can not reconnect to this device. + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC reconnect failed"); + return NFC_EIO; + } + DRIVER_DATA(pnd)->dwShareMode = SCARD_SHARE_DIRECT; + return NFC_SUCCESS; +} + +int pcsc_initiator_transceive_bytes(struct nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, uint8_t *pbtRx, const size_t szRx, int timeout) +{ + // FIXME: timeout is not handled + (void) timeout; + + DWORD dwRxLen = szRx; + + LOG_HEX(NFC_LOG_GROUP_COM, "TX", pbtTx, szTx); + DRIVER_DATA(pnd)->last_error = SCardTransmit(DRIVER_DATA(pnd)->hCard, &(DRIVER_DATA(pnd)->ioCard), pbtTx, szTx, NULL, pbtRx, &dwRxLen); + if (DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC transmit failed"); + pnd->last_error = NFC_EIO; + return pnd->last_error; + } + LOG_HEX(NFC_LOG_GROUP_COM, "RX", pbtRx, dwRxLen); + + return dwRxLen; +} + +int pcsc_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) +{ + uint8_t pbAtr[MAX_ATR_SIZE]; + DWORD dwState, dwProtocol, dwReaderLen, dwAtrLen = sizeof pbAtr; + nfc_target nt; + + DRIVER_DATA(pnd)->last_error = SCardStatus(DRIVER_DATA(pnd)->hCard, NULL, &dwReaderLen, &dwState, &dwProtocol, pbAtr, &dwAtrLen); + if ((DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS + && DRIVER_DATA(pnd)->last_error != SCARD_W_RESET_CARD) + || !(dwState & SCARD_PRESENT)) { + pnd->last_error = NFC_EIO; + return pnd->last_error; + } + if (pnt) { + if (pcsc_props_to_target(ICC_TYPE_UNKNOWN, pbAtr, dwAtrLen, NULL, 0, pnt->nm.nmt, &nt) != NFC_SUCCESS + || pnt->nm.nmt != nt.nm.nmt || pnt->nm.nbr != nt.nm.nbr) { + pnd->last_error = NFC_EINVARG; + return pnd->last_error; + } + } + return NFC_SUCCESS; +} + +int pcsc_device_set_property_bool(struct nfc_device *pnd, const nfc_property property, const bool bEnable) +{ + (void) pnd; + switch (property) { + case NP_INFINITE_SELECT: + // ignore + return NFC_SUCCESS; + case NP_AUTO_ISO14443_4: + case NP_EASY_FRAMING: + case NP_FORCE_ISO14443_A: + case NP_HANDLE_CRC: + case NP_HANDLE_PARITY: + case NP_FORCE_SPEED_106: + if (bEnable == true) + return NFC_SUCCESS; + break; + case NP_ACCEPT_INVALID_FRAMES: + case NP_ACCEPT_MULTIPLE_FRAMES: + if (bEnable == false) + return NFC_SUCCESS; + break; + case NP_ACTIVATE_FIELD: + if (bEnable == false) { + SCardReconnect(DRIVER_DATA(pnd)->hCard, DRIVER_DATA(pnd)->dwShareMode, DRIVER_DATA(pnd)->ioCard.dwProtocol, SCARD_RESET_CARD, (void *) & (DRIVER_DATA(pnd)->ioCard.dwProtocol)); + } + return NFC_SUCCESS; + default: + break; + } + return NFC_EDEVNOTSUPP; +} + +int pcsc_get_supported_modulation(struct nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type **const supported_mt) +{ + (void) pnd; + if (mode == N_TARGET || NULL == supported_mt) + return NFC_EINVARG; + *supported_mt = pcsc_supported_mts; + return NFC_SUCCESS; +} + +int pcsc_get_supported_baud_rate(struct nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br) +{ + (void) pnd; + (void) nmt; + if (mode == N_TARGET || NULL == supported_br) + return NFC_EINVARG; + *supported_br = pcsc_supported_brs; + return NFC_SUCCESS; +} + +int +pcsc_get_information_about(nfc_device *pnd, char **pbuf) +{ + LPBYTE name = NULL, version = NULL, type = NULL, serial = NULL; + DWORD name_len = SCARD_AUTOALLOCATE, version_len = SCARD_AUTOALLOCATE, + type_len = SCARD_AUTOALLOCATE, serial_len = SCARD_AUTOALLOCATE; + int res = NFC_SUCCESS; + SCARDCONTEXT *pscc; + + if (!(pscc = pcsc_get_scardcontext())) { + pnd->last_error = NFC_ESOFT; + return pnd->last_error; + } + + SCardGetAttrib(DRIVER_DATA(pnd)->hCard, SCARD_ATTR_VENDOR_NAME, (LPBYTE)&name, &name_len); + SCardGetAttrib(DRIVER_DATA(pnd)->hCard, SCARD_ATTR_VENDOR_IFD_TYPE, (LPBYTE)&type, &type_len); + SCardGetAttrib(DRIVER_DATA(pnd)->hCard, SCARD_ATTR_VENDOR_IFD_VERSION, (LPBYTE)&version, &version_len); + SCardGetAttrib(DRIVER_DATA(pnd)->hCard, SCARD_ATTR_VENDOR_IFD_SERIAL_NO, (LPBYTE)&serial, &serial_len); + + *pbuf = malloc(name_len + type_len + version_len + serial_len + 30); + if (! *pbuf) { + res = NFC_ESOFT; + goto error; + } + sprintf((char *) *pbuf, + "%s" // model + "%s%s" // version + " (%s)" // vendor + "%s%s\n" // serial + , + name && name_len > 0 && name[0] != '\0' + ? (char *)name : "unknown model", + version && version_len > 0 && version[0] != '\0' + ? " " : "", version_len > 0 ? (char *)version : "", + type && type_len > 0 && type[0] != '\0' + ? (char *)type : "unknown vendor", + serial && serial_len > 0 && serial[0] != '\0' + ? "\nserial: " : "", serial_len > 0 ? (char *)serial : ""); + +error: + SCardFreeMemory(*pscc, name); + SCardFreeMemory(*pscc, type); + SCardFreeMemory(*pscc, version); + SCardFreeMemory(*pscc, serial); + + pnd->last_error = res; + return pnd->last_error; +} + +const struct nfc_driver pcsc_driver = { + .name = PCSC_DRIVER_NAME, + .scan = pcsc_scan, + .open = pcsc_open, + .close = pcsc_close, + .strerror = pcsc_strerror, + + .initiator_init = pcsc_initiator_init, + .initiator_init_secure_element = NULL, // No secure-element support + .initiator_select_passive_target = pcsc_initiator_select_passive_target, + .initiator_poll_target = NULL, + .initiator_select_dep_target = NULL, + .initiator_deselect_target = NULL, + .initiator_transceive_bytes = pcsc_initiator_transceive_bytes, + .initiator_transceive_bits = NULL, + .initiator_transceive_bytes_timed = NULL, + .initiator_transceive_bits_timed = NULL, + .initiator_target_is_present = pcsc_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 = pcsc_device_set_property_bool, + .device_set_property_int = NULL, + .get_supported_modulation = pcsc_get_supported_modulation, + .get_supported_baud_rate = pcsc_get_supported_baud_rate, + .device_get_information_about = pcsc_get_information_about, + + .abort_command = NULL, // Abort is not supported in this driver + .idle = NULL, + .powerdown = NULL, +}; + diff --git a/libnfc/drivers/pcsc.h b/libnfc/drivers/pcsc.h new file mode 100644 index 00000000..f96030da --- /dev/null +++ b/libnfc/drivers/pcsc.h @@ -0,0 +1,35 @@ +/*- + * Free/Libre Near Field Communication (NFC) library + * + * Libnfc historical contributors: + * Copyright (C) 2019 Frank Morgner + * See AUTHORS file for a more comprehensive list of contributors. + * Additional contributors of this file: + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see + */ + +/** + * @file pcsc.h + * @brief Driver for non-ACR122 devices (behind PC/SC daemon) + */ + +#ifndef __NFC_DRIVER_PCSC_H__ +#define __NFC_DRIVER_PCSC_H__ + +#include + +extern const struct nfc_driver pcsc_driver; + +#endif // ! __NFC_DRIVER_PCSC_H__ diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 636697de..46d49c03 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -87,6 +87,10 @@ #include "target-subr.h" #include "drivers.h" +#if defined (DRIVER_PCSC_ENABLED) +# include "drivers/pcsc.h" +#endif /* DRIVER_PCSC_ENABLED */ + #if defined (DRIVER_ACR122_PCSC_ENABLED) # include "drivers/acr122_pcsc.h" #endif /* DRIVER_ACR122_PCSC_ENABLED */ @@ -136,6 +140,9 @@ nfc_drivers_init(void) #if defined (DRIVER_PN53X_USB_ENABLED) nfc_register_driver(&pn53x_usb_driver); #endif /* DRIVER_PN53X_USB_ENABLED */ +#if defined (DRIVER_PCSC_ENABLED) + nfc_register_driver(&pcsc_driver); +#endif /* DRIVER_ACR122_PCSC_ENABLED */ #if defined (DRIVER_ACR122_PCSC_ENABLED) nfc_register_driver(&acr122_pcsc_driver); #endif /* DRIVER_ACR122_PCSC_ENABLED */ diff --git a/m4/libnfc_drivers.m4 b/m4/libnfc_drivers.m4 index 46725391..a7219b9d 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: 'pcsc', '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.]), [ 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="pcsc acr122_pcsc acr122_usb acr122s arygon pn53x_usb pn532_uart" if test x"$spi_available" = x"yes" then DRIVER_BUILD_LIST="$DRIVER_BUILD_LIST pn532_spi" @@ -50,6 +50,7 @@ AC_DEFUN([LIBNFC_ARG_WITH_DRIVERS], DRIVERS_CFLAGS="" + driver_pcsc_enabled="no" driver_acr122_pcsc_enabled="no" driver_acr122_usb_enabled="no" driver_acr122s_enabled="no" @@ -62,6 +63,11 @@ AC_DEFUN([LIBNFC_ARG_WITH_DRIVERS], for driver in ${DRIVER_BUILD_LIST} do case "${driver}" in + pcsc) + pcsc_required="yes" + driver_pcsc_enabled="yes" + DRIVERS_CFLAGS="$DRIVERS_CFLAGS -DDRIVER_PCSC_ENABLED" + ;; acr122_pcsc) pcsc_required="yes" driver_acr122_pcsc_enabled="yes" @@ -109,6 +115,7 @@ AC_DEFUN([LIBNFC_ARG_WITH_DRIVERS], done AC_SUBST(DRIVERS_CFLAGS) AM_CONDITIONAL(DRIVER_ACR122_PCSC_ENABLED, [test x"$driver_acr122_pcsc_enabled" = xyes]) + AM_CONDITIONAL(DRIVER_PCSC_ENABLED, [test x"$driver_pcsc_enabled" = xyes]) AM_CONDITIONAL(DRIVER_ACR122_USB_ENABLED, [test x"$driver_acr122_usb_enabled" = xyes]) AM_CONDITIONAL(DRIVER_ACR122S_ENABLED, [test x"$driver_acr122s_enabled" = xyes]) AM_CONDITIONAL(DRIVER_PN53X_USB_ENABLED, [test x"$driver_pn53x_usb_enabled" = xyes]) @@ -121,6 +128,7 @@ AC_DEFUN([LIBNFC_ARG_WITH_DRIVERS], AC_DEFUN([LIBNFC_DRIVERS_SUMMARY],[ echo echo "Selected drivers:" +echo " pcsc............. $driver_pcsc_enabled" echo " acr122_pcsc...... $driver_acr122_pcsc_enabled" echo " acr122_usb....... $driver_acr122_usb_enabled" echo " acr122s.......... $driver_acr122s_enabled" From 959a992a81c48112e6e0df5fcf9a38eadeb15cd1 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 3 Sep 2019 15:50:28 +0200 Subject: [PATCH 239/318] added PC/SC driver to cmake --- CMakeLists.txt | 3 +++ cmake/modules/LibnfcDrivers.cmake | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 576f6e70..03097ead 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -138,6 +138,9 @@ IF(NOT WIN32) IF(LIBNFC_DRIVER_PN53X_USB) SET(PKG_REQ ${PKG_REQ} "libusb") ENDIF(LIBNFC_DRIVER_PN53X_USB) + IF(LIBNFC_DRIVER_PCSC) + SET(PKG_REQ ${PKG_REQ} "libpcsclite") + ENDIF(LIBNFC_DRIVER_ACR122) IF(LIBNFC_DRIVER_ACR122) SET(PKG_REQ ${PKG_REQ} "libpcsclite") ENDIF(LIBNFC_DRIVER_ACR122) diff --git a/cmake/modules/LibnfcDrivers.cmake b/cmake/modules/LibnfcDrivers.cmake index a79c2295..e3806d4e 100644 --- a/cmake/modules/LibnfcDrivers.cmake +++ b/cmake/modules/LibnfcDrivers.cmake @@ -1,3 +1,4 @@ +SET(LIBNFC_DRIVER_PCSC OFF CACHE BOOL "Enable PC/SC reader support (Depends on PC/SC)") SET(LIBNFC_DRIVER_ACR122_PCSC OFF CACHE BOOL "Enable ACR122 support (Depends on PC/SC)") SET(LIBNFC_DRIVER_ACR122_USB ON CACHE BOOL "Enable ACR122 support (Direct USB connection)") SET(LIBNFC_DRIVER_ACR122S ON CACHE BOOL "Enable ACR122S support (Use serial port)") @@ -12,6 +13,12 @@ ENDIF(WIN32) SET(LIBNFC_DRIVER_PN532_UART ON CACHE BOOL "Enable PN532 UART support (Use serial port)") SET(LIBNFC_DRIVER_PN53X_USB ON CACHE BOOL "Enable PN531 and PN531 USB support (Depends on libusb)") +IF(LIBNFC_DRIVER_PCSC) + FIND_PACKAGE(PCSC REQUIRED) + ADD_DEFINITIONS("-DDRIVER_PCSC_ENABLED") + SET(DRIVERS_SOURCES ${DRIVERS_SOURCES} "drivers/pcsc") +ENDIF(LIBNFC_DRIVER_PCSC) + IF(LIBNFC_DRIVER_ACR122_PCSC) FIND_PACKAGE(PCSC REQUIRED) ADD_DEFINITIONS("-DDRIVER_ACR122_PCSC_ENABLED") From 8e7a8e1b61c72a19e5d0d70ef43a16919bbdf3ca Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 3 Sep 2019 15:51:38 +0200 Subject: [PATCH 240/318] cmake: fixed pcsc requirement for acr122_pcsc --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 03097ead..5d8b5a82 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -141,9 +141,9 @@ IF(NOT WIN32) IF(LIBNFC_DRIVER_PCSC) SET(PKG_REQ ${PKG_REQ} "libpcsclite") ENDIF(LIBNFC_DRIVER_ACR122) - IF(LIBNFC_DRIVER_ACR122) + IF(LIBNFC_DRIVER_ACR122_PCSC) SET(PKG_REQ ${PKG_REQ} "libpcsclite") - ENDIF(LIBNFC_DRIVER_ACR122) + ENDIF(LIBNFC_DRIVER_ACR122_PCSC) # CMake lists are separated by a semi colon, replace with colon STRING(REPLACE ";" "," PKG_CONFIG_REQUIRES "${PKG_REQ}") CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libnfc.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libnfc.pc @ONLY) From 6f793da1c139fb71c483fefad036a189c76369dc Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 3 Sep 2019 22:44:44 +0200 Subject: [PATCH 241/318] cleanup --- libnfc/drivers/pcsc.c | 182 +++++++++++++++++++++++++++--------------- 1 file changed, 119 insertions(+), 63 deletions(-) diff --git a/libnfc/drivers/pcsc.c b/libnfc/drivers/pcsc.c index 06480a93..d89ae7ea 100644 --- a/libnfc/drivers/pcsc.c +++ b/libnfc/drivers/pcsc.c @@ -109,35 +109,92 @@ pcsc_free_scardcontext(void) #define ICC_TYPE_14443A 5 #define ICC_TYPE_14443B 6 +int pcsc_transmit(struct nfc_device *pnd, const uint8_t *tx, const size_t tx_len, uint8_t *rx, size_t *rx_len) +{ + struct pcsc_data *data = pnd->driver_data; + DWORD dw_rx_len = *rx_len; + + LOG_HEX(NFC_LOG_GROUP_COM, "TX", tx, tx_len); + + data->last_error = SCardTransmit(data->hCard, &data->ioCard, tx, tx_len, + NULL, rx, &dw_rx_len); + if (data->last_error != SCARD_S_SUCCESS) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC transmit failed"); + return NFC_EIO; + } + *rx_len = dw_rx_len; + + LOG_HEX(NFC_LOG_GROUP_COM, "RX", rx, *rx_len); + + return NFC_SUCCESS; +} + +int pcsc_get_status(struct nfc_device *pnd, int *target_present, uint8_t *atr, size_t *atr_len) +{ + struct pcsc_data *data = pnd->driver_data; + DWORD dw_atr_len = *atr_len, reader_len, state, protocol; + + data->last_error = SCardStatus(data->hCard, NULL, &reader_len, &state, &protocol, atr, &dw_atr_len); + if (data->last_error != SCARD_S_SUCCESS + && data->last_error != SCARD_W_RESET_CARD) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Get status failed"); + return NFC_EIO; + } + + *target_present = state & SCARD_PRESENT; + *atr_len = dw_atr_len; + + return NFC_SUCCESS; +} + +int pcsc_reconnect(struct nfc_device *pnd, DWORD share_mode, DWORD protocol, DWORD disposition) +{ + struct pcsc_data *data = pnd->driver_data; + + data->last_error = SCardReconnect(data->hCard, share_mode, protocol, disposition, &data->ioCard.dwProtocol); + if (data->last_error != SCARD_S_SUCCESS + && data->last_error != SCARD_W_RESET_CARD) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reconnect failed"); + return NFC_EIO; + } + + data->dwShareMode = share_mode; + + return NFC_SUCCESS; +} + uint8_t pcsc_get_icc_type(struct nfc_device *pnd) { + struct pcsc_data *data = pnd->driver_data; uint8_t it = 0; DWORD dwItLen = sizeof it; - DRIVER_DATA(pnd)->last_error = SCardGetAttrib(DRIVER_DATA(pnd)->hCard, SCARD_ATTR_ICC_TYPE_PER_ATR, &it, &dwItLen); + data->last_error = SCardGetAttrib(data->hCard, SCARD_ATTR_ICC_TYPE_PER_ATR, &it, &dwItLen); return it; } -int pcsc_get_uid(struct nfc_device *pnd, uint8_t *puid, size_t szuid) +int pcsc_get_uid(struct nfc_device *pnd, uint8_t *uid, size_t uid_len) { - uint8_t get_data[] = {0xFF, 0xCA, 0x00, 0x00, 0x00}, data[256 + 2]; - DWORD dwRxLen = sizeof data; + const uint8_t get_data[] = {0xFF, 0xCA, 0x00, 0x00, 0x00}; + uint8_t resp[256 + 2]; + size_t resp_len = sizeof resp; + + pnd->last_error = pcsc_transmit(pnd, get_data, sizeof get_data, resp, &resp_len); + if (pnd->last_error != NFC_SUCCESS) + return pnd->last_error; - LOG_HEX(NFC_LOG_GROUP_COM, "TX", get_data, sizeof get_data); - DRIVER_DATA(pnd)->last_error = SCardTransmit(DRIVER_DATA(pnd)->hCard, &(DRIVER_DATA(pnd)->ioCard), get_data, sizeof get_data, NULL, data, &dwRxLen); - if ((DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS) - || dwRxLen < 2) { + if (resp_len < 2) { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reader doesn't support request for UID"); - pnd->last_error = NFC_EIO; + pnd->last_error = NFC_EDEVNOTSUPP; return pnd->last_error; } - LOG_HEX(NFC_LOG_GROUP_COM, "RX", data, dwRxLen); - if (szuid < (size_t) dwRxLen - 2) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Malformed response code"); - pnd->last_error = NFC_EINVARG; + if (uid_len < resp_len - 2) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "UID too big"); + pnd->last_error = NFC_ESOFT; return pnd->last_error; } - memcpy(puid, data, dwRxLen - 2); - return dwRxLen - 2; + + memcpy(uid, resp, resp_len - 2); + return resp_len - 2; } int pcsc_props_to_target(uint8_t it, const uint8_t *patr, size_t szatr, const uint8_t *puid, int szuid, const nfc_modulation_type nmt, nfc_target *pnt) @@ -530,84 +587,81 @@ int pcsc_initiator_init(struct nfc_device *pnd) int pcsc_initiator_select_passive_target(struct nfc_device *pnd, const nfc_modulation nm, const uint8_t *pbtInitData, const size_t szInitData, nfc_target *pnt) { - uint8_t pbAtr[MAX_ATR_SIZE]; + uint8_t atr[MAX_ATR_SIZE]; uint8_t uid[10]; - DWORD dwState, dwProtocol, dwReaderLen, dwAtrLen = sizeof pbAtr; + int target_present; + size_t atr_len = sizeof atr; (void) pbtInitData; (void) szInitData; if (nm.nbr != pcsc_supported_brs[0] && nm.nbr != pcsc_supported_brs[1]) return NFC_EINVARG; - DRIVER_DATA(pnd)->last_error = SCardStatus(DRIVER_DATA(pnd)->hCard, NULL, &dwReaderLen, &dwState, &dwProtocol, pbAtr, &dwAtrLen); - if ((DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS - && DRIVER_DATA(pnd)->last_error != SCARD_W_RESET_CARD) - || !(dwState & SCARD_PRESENT)) { + + pnd->last_error = pcsc_get_status(pnd, &target_present, atr, &atr_len); + if (pnd->last_error != NFC_SUCCESS) + return pnd->last_error; + + if (!target_present) { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "No target present"); return NFC_ENOTSUCHDEV; } - uint8_t it = pcsc_get_icc_type(pnd); - int szuid = pcsc_get_uid(pnd, uid, sizeof uid); - if (pcsc_props_to_target(it, pbAtr, dwAtrLen, uid, szuid, nm.nmt, pnt) != NFC_SUCCESS - || (DRIVER_DATA(pnd)->last_error = SCardReconnect((DRIVER_DATA(pnd)->hCard), SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_LEAVE_CARD, (void *) & (DRIVER_DATA(pnd)->ioCard.dwProtocol))) != SCARD_S_SUCCESS) { - // We can not reconnect to this device. - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC reconnect failed"); - return NFC_EIO; + + uint8_t icc_type = pcsc_get_icc_type(pnd); + int uid_len = pcsc_get_uid(pnd, uid, sizeof uid); + if (pcsc_props_to_target(icc_type, atr, atr_len, uid, uid_len, nm.nmt, pnt) != NFC_SUCCESS) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Type of target not supported"); + return NFC_EDEVNOTSUPP; } - DRIVER_DATA(pnd)->dwShareMode = SCARD_SHARE_SHARED; + + pnd->last_error = pcsc_reconnect(pnd, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_LEAVE_CARD); + if (pnd->last_error != NFC_SUCCESS) + return pnd->last_error; + return 1; } int pcsc_initiator_deselect_target(struct nfc_device *pnd) { - DRIVER_DATA(pnd)->last_error = SCardReconnect((DRIVER_DATA(pnd)->hCard), SCARD_SHARE_DIRECT, 0, SCARD_LEAVE_CARD, (void *) & (DRIVER_DATA(pnd)->ioCard.dwProtocol)); - if (DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS - && DRIVER_DATA(pnd)->last_error != SCARD_W_RESET_CARD) { - // We can not reconnect to this device. - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC reconnect failed"); - return NFC_EIO; - } - DRIVER_DATA(pnd)->dwShareMode = SCARD_SHARE_DIRECT; - return NFC_SUCCESS; + pnd->last_error = pcsc_reconnect(pnd, SCARD_SHARE_DIRECT, 0, SCARD_LEAVE_CARD); + return pnd->last_error; } int pcsc_initiator_transceive_bytes(struct nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, uint8_t *pbtRx, const size_t szRx, int timeout) { + size_t resp_len = szRx; + // FIXME: timeout is not handled (void) timeout; - DWORD dwRxLen = szRx; - - LOG_HEX(NFC_LOG_GROUP_COM, "TX", pbtTx, szTx); - DRIVER_DATA(pnd)->last_error = SCardTransmit(DRIVER_DATA(pnd)->hCard, &(DRIVER_DATA(pnd)->ioCard), pbtTx, szTx, NULL, pbtRx, &dwRxLen); - if (DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC transmit failed"); - pnd->last_error = NFC_EIO; + pnd->last_error = pcsc_transmit(pnd, pbtTx, szTx, pbtRx, &resp_len); + if (pnd->last_error != NFC_SUCCESS) return pnd->last_error; - } - LOG_HEX(NFC_LOG_GROUP_COM, "RX", pbtRx, dwRxLen); - return dwRxLen; + return resp_len; } int pcsc_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) { - uint8_t pbAtr[MAX_ATR_SIZE]; - DWORD dwState, dwProtocol, dwReaderLen, dwAtrLen = sizeof pbAtr; + uint8_t atr[MAX_ATR_SIZE]; + int target_present; + size_t atr_len = sizeof atr; nfc_target nt; - DRIVER_DATA(pnd)->last_error = SCardStatus(DRIVER_DATA(pnd)->hCard, NULL, &dwReaderLen, &dwState, &dwProtocol, pbAtr, &dwAtrLen); - if ((DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS - && DRIVER_DATA(pnd)->last_error != SCARD_W_RESET_CARD) - || !(dwState & SCARD_PRESENT)) { - pnd->last_error = NFC_EIO; + pnd->last_error = pcsc_get_status(pnd, &target_present, atr, &atr_len); + if (pnd->last_error != NFC_SUCCESS) return pnd->last_error; + + if (!target_present) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "No target present"); + return NFC_ENOTSUCHDEV; } + if (pnt) { - if (pcsc_props_to_target(ICC_TYPE_UNKNOWN, pbAtr, dwAtrLen, NULL, 0, pnt->nm.nmt, &nt) != NFC_SUCCESS + if (pcsc_props_to_target(ICC_TYPE_UNKNOWN, atr, atr_len, NULL, 0, pnt->nm.nmt, &nt) != NFC_SUCCESS || pnt->nm.nmt != nt.nm.nmt || pnt->nm.nbr != nt.nm.nbr) { - pnd->last_error = NFC_EINVARG; - return pnd->last_error; + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Target doesn't meet requirements"); + return NFC_ENOTSUCHDEV; } } return NFC_SUCCESS; @@ -636,7 +690,8 @@ int pcsc_device_set_property_bool(struct nfc_device *pnd, const nfc_property pro break; case NP_ACTIVATE_FIELD: if (bEnable == false) { - SCardReconnect(DRIVER_DATA(pnd)->hCard, DRIVER_DATA(pnd)->dwShareMode, DRIVER_DATA(pnd)->ioCard.dwProtocol, SCARD_RESET_CARD, (void *) & (DRIVER_DATA(pnd)->ioCard.dwProtocol)); + struct pcsc_data *data = pnd->driver_data; + pcsc_reconnect(pnd, data->dwShareMode, data->ioCard.dwProtocol, SCARD_RESET_CARD); } return NFC_SUCCESS; default: @@ -667,6 +722,7 @@ int pcsc_get_supported_baud_rate(struct nfc_device *pnd, const nfc_mode mode, co int pcsc_get_information_about(nfc_device *pnd, char **pbuf) { + struct pcsc_data *data = pnd->driver_data; LPBYTE name = NULL, version = NULL, type = NULL, serial = NULL; DWORD name_len = SCARD_AUTOALLOCATE, version_len = SCARD_AUTOALLOCATE, type_len = SCARD_AUTOALLOCATE, serial_len = SCARD_AUTOALLOCATE; @@ -678,10 +734,10 @@ pcsc_get_information_about(nfc_device *pnd, char **pbuf) return pnd->last_error; } - SCardGetAttrib(DRIVER_DATA(pnd)->hCard, SCARD_ATTR_VENDOR_NAME, (LPBYTE)&name, &name_len); - SCardGetAttrib(DRIVER_DATA(pnd)->hCard, SCARD_ATTR_VENDOR_IFD_TYPE, (LPBYTE)&type, &type_len); - SCardGetAttrib(DRIVER_DATA(pnd)->hCard, SCARD_ATTR_VENDOR_IFD_VERSION, (LPBYTE)&version, &version_len); - SCardGetAttrib(DRIVER_DATA(pnd)->hCard, SCARD_ATTR_VENDOR_IFD_SERIAL_NO, (LPBYTE)&serial, &serial_len); + SCardGetAttrib(data->hCard, SCARD_ATTR_VENDOR_NAME, (LPBYTE)&name, &name_len); + SCardGetAttrib(data->hCard, SCARD_ATTR_VENDOR_IFD_TYPE, (LPBYTE)&type, &type_len); + SCardGetAttrib(data->hCard, SCARD_ATTR_VENDOR_IFD_VERSION, (LPBYTE)&version, &version_len); + SCardGetAttrib(data->hCard, SCARD_ATTR_VENDOR_IFD_SERIAL_NO, (LPBYTE)&serial, &serial_len); *pbuf = malloc(name_len + type_len + version_len + serial_len + 30); if (! *pbuf) { From a77a2a84971f4c588a6377b30975bbe3b15d5ab4 Mon Sep 17 00:00:00 2001 From: jpwidera Date: Thu, 5 Sep 2019 21:59:46 +0200 Subject: [PATCH 242/318] Removed USB alternate setting. Quick and dirty fix for https://github.com/nfc-tools/libnfc/issues/535 --- libnfc/drivers/acr122_usb.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/libnfc/drivers/acr122_usb.c b/libnfc/drivers/acr122_usb.c index a6392e8d..609a4953 100644 --- a/libnfc/drivers/acr122_usb.c +++ b/libnfc/drivers/acr122_usb.c @@ -427,14 +427,6 @@ acr122_usb_open(const nfc_context *context, const nfc_connstring connstring) goto free_mem; } - res = usb_set_altinterface(data.pudh, 0); - if (res < 0) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set alternate setting on USB interface (%s)", _usb_strerror(res)); - usb_close(data.pudh); - // we failed to use the specified device - goto free_mem; - } - // Allocate memory for the device info and specification, fill it and return the info pnd = nfc_device_new(context, connstring); if (!pnd) { From 6e035c33f3fd6e14963c884ad6bab680a0848795 Mon Sep 17 00:00:00 2001 From: jpwidera Date: Thu, 5 Sep 2019 22:32:03 +0200 Subject: [PATCH 243/318] Re-enabled claim If there are alternative interfaces, claim interface 0. Otherwise skip this step. --- libnfc/drivers/acr122_usb.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libnfc/drivers/acr122_usb.c b/libnfc/drivers/acr122_usb.c index 609a4953..8931aabc 100644 --- a/libnfc/drivers/acr122_usb.c +++ b/libnfc/drivers/acr122_usb.c @@ -427,6 +427,17 @@ acr122_usb_open(const nfc_context *context, const nfc_connstring connstring) goto free_mem; } + // Check if there are more than 0 alternative interfaces and claim the first one + if (dev->config->interface->altsetting->bAlternateSetting > 0) { + res = usb_set_altinterface(data.pudh, 0); + if (res < 0) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set alternate setting on USB interface (%s)", _usb_strerror(res)); + usb_close(data.pudh); + // we failed to use the specified device + goto free_mem; + } + } + // Allocate memory for the device info and specification, fill it and return the info pnd = nfc_device_new(context, connstring); if (!pnd) { From 07f918283b51869e7d5255bfa23f3e26656d8178 Mon Sep 17 00:00:00 2001 From: jpwidera Date: Thu, 5 Sep 2019 22:33:33 +0200 Subject: [PATCH 244/318] Fixed missing whitespaces --- libnfc/drivers/acr122_usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libnfc/drivers/acr122_usb.c b/libnfc/drivers/acr122_usb.c index 8931aabc..4a88c61f 100644 --- a/libnfc/drivers/acr122_usb.c +++ b/libnfc/drivers/acr122_usb.c @@ -428,7 +428,7 @@ acr122_usb_open(const nfc_context *context, const nfc_connstring connstring) } // Check if there are more than 0 alternative interfaces and claim the first one - if (dev->config->interface->altsetting->bAlternateSetting > 0) { + if (dev->config->interface->altsetting->bAlternateSetting > 0) { res = usb_set_altinterface(data.pudh, 0); if (res < 0) { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set alternate setting on USB interface (%s)", _usb_strerror(res)); @@ -436,7 +436,7 @@ acr122_usb_open(const nfc_context *context, const nfc_connstring connstring) // we failed to use the specified device goto free_mem; } - } + } // Allocate memory for the device info and specification, fill it and return the info pnd = nfc_device_new(context, connstring); From 2a6a8e6e298f999d2ca78db439d496dc5983595c Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Sat, 4 Apr 2020 15:10:02 +0100 Subject: [PATCH 245/318] 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 636697de..f239ba2a 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); } From cbc4e7b5c495433665347df2f1d79539a449c15c Mon Sep 17 00:00:00 2001 From: "hongbin@ftsafe.com" Date: Thu, 9 Apr 2020 11:29:11 +0800 Subject: [PATCH 246/318] Update readme and add Feitian R502 and bR500 support into pcsc driver 1. Modify pcsc.c code, add R502 and bR500 support into PCSC driver 2. Update readme, tell user how to build with pcsc driver 3. Add FAQ for bR500 and R502 in readme --- README.md | 72 +++++++++++++++++++++++++++++++++--------- libnfc/drivers/pcsc.c | 73 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 129 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index e8341f51..6fb33835 100644 --- a/README.md +++ b/README.md @@ -35,12 +35,15 @@ Requirements Some NFC drivers depend on third party software: * pn53x_usb & acr122_usb: - - - libusb-0.1 http://libusb.sf.net + + - libusb-0.1 http://libusb.sf.net * acr122_pcsc: - - - pcsc-lite http://pcsclite.alioth.debian.org/ + + - pcsc-lite http://pcsclite.alioth.debian.org/ +- pcsc: + + - Support build with pcsc driver, which can be using all compatible readers, Feitian R502 and bR500 already passed the test. The regression test suite depends on the cutter framework: http://cutter.sf.net @@ -97,32 +100,36 @@ Please make sure to include: * The version of libnfc * Information about your system. For instance: - - - What operating system and version - - For Linux, what version of the C library - + + - What operating system and version + - For Linux, what version of the C library + And anything else you think is relevant. * A trace with debug activated. - + Reproduce the bug with debug, e.g. if it was: - + $ nfc-list -v - + run it as: - + $ LIBNFC_LOG_LEVEL=3 nfc-list -v * How to reproduce the bug. - + Please include a short test program that exhibits the behavior. + As a last resort, you can also provide a pointer to a larger piece + of software that can be downloaded. * If the bug was a crash, the exact text that was printed out + when the crash occured. * Further information such as stack traces may be useful, but + is not necessary. Patches @@ -136,16 +143,27 @@ all the information described in "How to Report Bugs". Building ======== -It should be as simple as running these two commands: +It should be as simple as running these three commands: + autoreconf -vis ./configure make +Build with specific driver, like pcsc driver for compatible readers, go with below commands, tested on linux and macOS: + +``` +git clone --recursive https://github.com/nfc-tools/libnfc +autoreconf -vis +./configure --with-drivers=pcsc +make +``` + Troubleshooting =============== Touchatag/ACR122: ----------------- + If your Touchatag or ACR122 device fails being detected by libnfc, make sure that PCSC-lite daemon (`pcscd`) is installed and is running. @@ -158,6 +176,7 @@ pcscd daemon. ACR122: ------- + Using an ACR122 device with libnfc and without tag (e.g. to use NFCIP modes or card emulation) needs yet another PCSC-lite tweak: You need to allow usage of CCID Exchange command. To do this, edit `libccid_Info.plist` configuration file @@ -171,13 +190,16 @@ in something like: `/usr/lib/pcsc/drivers/ifd-acsccid.bundle/Contents/Info.plist SCL3711: -------- + Libnfc cannot be used concurrently with the PCSC proprietary driver of SCL3711. Two possible solutions: + * Either you don't install SCL3711 driver at all * Or you stop the PCSC daemon when you want to use libnfc-based tools PN533 USB device on Linux >= 3.1: --------------------------------- + Since Linux kernel version 3.1, a few kernel-modules must not be loaded in order to use libnfc : "nfc", "pn533" and "pn533_usb". To prevent kernel from loading automatically these modules, you can blacklist @@ -185,9 +207,29 @@ them in a modprobe conf file. This file is provided within libnfc archive: sudo cp contrib/linux/blacklist-libnfc.conf /etc/modprobe.d/blacklist-libnfc.conf +## FEITIAN bR500 and R502: + +Libnfc can work with PCSC proprietary driver of bR500 and R502 through USB port, most linux already installed PCSC proprietary, then just plug in play, to have pcsc driver support, you may need build with "--with-drivers=pcsc" to re-build libnfc, below reader tested: + +- Feitian bR500 +- Feitian R502 Dual interface reader +- Feitian R502 CL(Contactless) reader + +These reader support by CCID from 1.4.25, make sure your CCID driver version higher than 1.4.25. + +Using macOS, use below command check your version, to install latest CCID driver from [https://github.com/martinpaljak/osx-ccid-installer/releases](https://github.com/martinpaljak/osx-ccid-installer/releases) + +``` +grep -A 1 CFBundleShortVersionString /usr/local/libexec/SmartCardServices/drivers/ifd-ccid.bundle/Contents/Info.plist +``` + +Using linux, use below command check your version, to install latest CCID driver from [https://ccid.apdu.fr/](https://ccid.apdu.fr/) + +``` +grep -A 1 CFBundleShortVersionString /usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist +``` Proprietary Notes ================= - FeliCa is a registered trademark of the Sony Corporation. MIFARE is a trademark of NXP Semiconductors. Jewel Topaz is a trademark of Innovision Research & Technology. diff --git a/libnfc/drivers/pcsc.c b/libnfc/drivers/pcsc.c index d89ae7ea..8c0cb720 100644 --- a/libnfc/drivers/pcsc.c +++ b/libnfc/drivers/pcsc.c @@ -76,6 +76,18 @@ struct pcsc_data { #define DRIVER_DATA(pnd) ((struct pcsc_data*)(pnd->driver_data)) +//Doesn't have define in macOS, so define from reader.h +#define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag))) +#define SCARD_CLASS_VENDOR_INFO 1 +#define SCARD_ATTR_VENDOR_NAME SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0100) +#define SCARD_ATTR_ICC_TYPE_PER_ATR SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0304) +#define SCARD_CLASS_ICC_STATE 9 +#define SCARD_AUTOALLOCATE (DWORD)(-1) +#define SCARD_ATTR_VENDOR_NAME SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0100) +#define SCARD_ATTR_VENDOR_IFD_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0101) +#define SCARD_ATTR_VENDOR_IFD_VERSION SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0102) +#define SCARD_ATTR_VENDOR_IFD_SERIAL_NO SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0103) + static SCARDCONTEXT _SCardContext; static int _iSCardContextRefCount = 0; @@ -291,6 +303,40 @@ pcsc_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t int l = strlen(supported_devices[i]); bSupported = 0 == !strncmp(supported_devices[i], acDeviceNames + szPos, l); } + // Supported Feitian Contactless Reader +#if defined (__APPLE__) + // Feitian R502 + if (strstr(acDeviceNames + szPos, "Feitian R502") != NULL) + { + bSupported = true; + } + // Feitian 502-CL + if (strstr(acDeviceNames + szPos, "Feitian 502-CL") != NULL) + { + bSupported = true; + } + // Feitian bR500 + if (strstr(acDeviceNames + szPos, "Feitian bR500") != NULL) + { + bSupported = true; + } +#else + // Feitian R502 + if (strstr(acDeviceNames + szPos, "Feitian R502 [R502 Contact Reader]") != NULL) + { + bSupported = true; + } + // Feitian 502-CL + if (strstr(acDeviceNames + szPos, "Feitian 502-CL [R502 Contactless Reader]") != NULL) + { + bSupported = true; + } + // Feitian bR500 + if (strstr(acDeviceNames + szPos, "Feitian bR500") != NULL) + { + bSupported = true; + } +#endif if (bSupported) { // Supported non-ACR122 device found @@ -382,7 +428,8 @@ pcsc_open(const nfc_context *context, const nfc_connstring connstring) // Test if context succeeded if (!(pscc = pcsc_get_scardcontext())) goto error; - DRIVER_DATA(pnd)->last_error = SCardConnect(*pscc, ndd.pcsc_device_name, SCARD_SHARE_DIRECT, 0, &(DRIVER_DATA(pnd)->hCard), (void *) & (DRIVER_DATA(pnd)->ioCard.dwProtocol)); + // T1 or T0 protocol. + DRIVER_DATA(pnd)->last_error = SCardConnect(*pscc, ndd.pcsc_device_name, SCARD_SHARE_DIRECT, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &(DRIVER_DATA(pnd)->hCard), (void *) & (DRIVER_DATA(pnd)->ioCard.dwProtocol)); if (DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS) { // We can not connect to this device. log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC connect failed"); @@ -760,10 +807,34 @@ pcsc_get_information_about(nfc_device *pnd, char **pbuf) ? "\nserial: " : "", serial_len > 0 ? (char *)serial : ""); error: +// SCardFreeMemory function not supported in macOS. +#if defined(__APPLE__) + if (name != NULL){ + free(name); + name = NULL; + } + if (type != NULL){ + free(type); + type = NULL; + } + if (version != NULL){ + free(version); + version = NULL; + } + if (serial != NULL){ + free(serial); + serial = NULL; + } + if (pscc != NULL){ + SCardReleaseContext(pscc); + } +#else SCardFreeMemory(*pscc, name); SCardFreeMemory(*pscc, type); SCardFreeMemory(*pscc, version); SCardFreeMemory(*pscc, serial); +#endif + pnd->last_error = res; return pnd->last_error; From 19a51dc2bda460d4da5b75fec3178d9673bc20e9 Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Mon, 11 May 2020 11:45:28 +0100 Subject: [PATCH 247/318] first cut iClass support - get nfc-list to see UID --- examples/nfc-poll.c | 6 +- include/nfc/nfc-types.h | 14 +++- libnfc/chips/pn53x.c | 148 +++++++++++++++++++++++++++++++++++++--- libnfc/chips/pn53x.h | 2 + libnfc/nfc-internal.c | 3 + libnfc/nfc.c | 8 +++ libnfc/target-subr.c | 15 ++++ libnfc/target-subr.h | 2 + utils/nfc-list.c | 18 +++++ 9 files changed, 204 insertions(+), 12 deletions(-) diff --git a/examples/nfc-poll.c b/examples/nfc-poll.c index f8f30ba3..4cea5d63 100644 --- a/examples/nfc-poll.c +++ b/examples/nfc-poll.c @@ -9,6 +9,7 @@ * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: + * Copyright (C) 2020 Adam Laurie * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -101,14 +102,15 @@ main(int argc, const char *argv[]) const uint8_t uiPollNr = 20; const uint8_t uiPeriod = 2; - const nfc_modulation nmModulations[5] = { + const nfc_modulation nmModulations[6] = { { .nmt = NMT_ISO14443A, .nbr = NBR_106 }, { .nmt = NMT_ISO14443B, .nbr = NBR_106 }, { .nmt = NMT_FELICA, .nbr = NBR_212 }, { .nmt = NMT_FELICA, .nbr = NBR_424 }, { .nmt = NMT_JEWEL, .nbr = NBR_106 }, + { .nmt = NMT_ISO14443BICLASS, .nbr = NBR_106 }, }; - const size_t szModulations = 5; + const size_t szModulations = 6; nfc_target nt; int res = 0; diff --git a/include/nfc/nfc-types.h b/include/nfc/nfc-types.h index 89ad3978..6ca57a41 100644 --- a/include/nfc/nfc-types.h +++ b/include/nfc/nfc-types.h @@ -9,6 +9,7 @@ * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: + * Copyright (C) 2020 Adam Laurie * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the @@ -234,6 +235,14 @@ typedef struct { uint8_t abtAtr[33]; } nfc_iso14443bi_info; +/** + * @struct nfc_iso14443biclass_info + * @brief NFC ISO14443BiClass tag information + */ +typedef struct { + uint8_t abtUID[8]; +} nfc_iso14443biclass_info; + /** * @struct nfc_iso14443b2sr_info * @brief NFC ISO14443-2B ST SRx tag information @@ -284,6 +293,7 @@ typedef union { nfc_jewel_info nji; nfc_barcode_info nti; // "t" for Thinfilm, "b" already used nfc_dep_info ndi; + nfc_iso14443biclass_info nic; // iclass - nbi already used } nfc_target_info; /** @@ -311,7 +321,9 @@ typedef enum { NMT_ISO14443B2SR, // ISO14443-2B ST SRx NMT_ISO14443B2CT, // ISO14443-2B ASK CTx NMT_FELICA, - NMT_DEP, // DEP should be kept last one as it's used as end-of-enum + NMT_DEP, + NMT_ISO14443BICLASS, // HID iClass 14443B mode + NMT_END_ENUM, // dummy for sizing - always should be last } nfc_modulation_type; /** diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 89af830f..44b862c5 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -9,6 +9,7 @@ * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: + * Copyright (C) 2020 Adam Laurie * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the @@ -85,7 +86,7 @@ pn53x_init(struct nfc_device *pnd) } if (!CHIP_DATA(pnd)->supported_modulation_as_initiator) { - CHIP_DATA(pnd)->supported_modulation_as_initiator = malloc(sizeof(nfc_modulation_type) * (NMT_DEP + 1)); + CHIP_DATA(pnd)->supported_modulation_as_initiator = malloc(sizeof(nfc_modulation_type) * (NMT_END_ENUM)); if (! CHIP_DATA(pnd)->supported_modulation_as_initiator) return NFC_ESOFT; int nbSupportedModulation = 0; @@ -104,6 +105,8 @@ pn53x_init(struct nfc_device *pnd) nbSupportedModulation++; CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_ISO14443B2CT; nbSupportedModulation++; + CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_ISO14443BICLASS; + nbSupportedModulation++; } if (CHIP_DATA(pnd)->type != PN531) { CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_JEWEL; @@ -575,6 +578,12 @@ pn53x_decode_target_data(const uint8_t *pbtRawData, size_t szRawData, pn53x_type memcpy(pnti->nsi.abtUID, pbtRawData, 8); break; + case NMT_ISO14443BICLASS: + // Store the UID + for(uint8_t i= 0 ; i < 8 ; ++i) + pnti->nic.abtUID[7 - i]= pbtRawData[i]; + break; + case NMT_ISO14443B2CT: // Store UID LSB memcpy(pnti->nci.abtUID, pbtRawData, 2); @@ -620,6 +629,8 @@ pn53x_decode_target_data(const uint8_t *pbtRawData, size_t szRawData, pn53x_type // Should not happend... case NMT_DEP: return NFC_ECHIP; + case NMT_END_ENUM: + break; } return NFC_SUCCESS; } @@ -1048,6 +1059,56 @@ pn53x_initiator_init(struct nfc_device *pnd) return NFC_SUCCESS; } +// iclass requires special modulation settings +void pn53x_initiator_init_iclass_modulation(struct nfc_device *pnd) +{ + // send a bunch of low level commands I reverse engineered from a working iClass reader + // original device was using a PN512 + // + // // TxModeReg - Defines the data rate and framing during transmission. + //// set bit 4 for target mode? - RxWaitRF Set to logic 1, the counter for RxWait starts only if an external RF field is detected in Target mode for NFCIP-1 or in Card Communication mode + //pn512_write_register(0x12, "\x03", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_TxMode, 0x03); + // + // // RxModeReg - Defines the data rate and framing during reception. + //pn512_write_register(0x13, "\x03", 1, false); + // addy changed to set bit 3 - RxNoErr (put data in fifo before flagging read end) + //pn512_write_register(0x13, "\x0B", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_RxMode, 0x0B); + + // ManualRCVReg - Allows manual fine tuning of the internal receiver. + //pn512_write_register(0x1d, "\x10", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_ManualRCV, 0x10); + + // RFCfgReg - Configures the receiver gain and RF level detector sensitivity. + //pn512_write_register(0x26, "\x70", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_RFCfg, 0x70); + + // GsNOffReg - Selects the conductance for the N-driver of the antenna driver pins TX1 and TX2 when the driver is switched off. + //pn512_write_register(0x23, "\x88", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_GsNOFF, 0x88); + + // GsNOnReg - Selects the conductance for the N-driver of the antenna driver pins TX1 and TX2 when the driver is switched on. + //pn512_write_register(0x27, "\xf8", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_GsNOn, 0xf8); + + // CWGsPReg - Defines the conductance of the P-driver during times of no modulation. + //pn512_write_register(0x28, "\x3f", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_CWGsP, 0x3f); + + // ModGsPReg - Defines the driver P-output conductance during modulation. + //pn512_write_register(0x29, "\x10", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_ModGsP, 0x10); + + // TReloadReg (MSB) - Describes the MSB of the 16-bit long timer reload value. + //pn512_write_register(0x2c, "\x69", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_TReloadVal_hi, 0x69); + + // TReloadReg (LSB) - Describes the LSB of the 16-bit long timer reload value. + //pn512_write_register(0x2d, "\xf0", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_TReloadVal_lo, 0xf0); +} + int pn532_initiator_init_secure_element(struct nfc_device *pnd) { @@ -1067,7 +1128,7 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, nfc_target nttmp; memset(&nttmp, 0x00, sizeof(nfc_target)); - if (nm.nmt == NMT_ISO14443BI || nm.nmt == NMT_ISO14443B2SR || nm.nmt == NMT_ISO14443B2CT) { + if (nm.nmt == NMT_ISO14443BI || nm.nmt == NMT_ISO14443B2SR || nm.nmt == NMT_ISO14443B2CT || nm.nmt == NMT_ISO14443BICLASS) { if (CHIP_DATA(pnd)->type == RCS360) { // TODO add support for RC-S360, at the moment it refuses to send raw frames without a first select pnd->last_error = NFC_ENOTIMPL; @@ -1117,15 +1178,40 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, return res; } szTargetsData = (size_t)res; - } - - if ((res = pn53x_initiator_transceive_bytes(pnd, pbtInitData, szInitData, abtTargetsData, sizeof(abtTargetsData), timeout)) < 0) { - if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout - continue; - } else + } else if (nm.nmt == NMT_ISO14443BICLASS) { + pn53x_initiator_init_iclass_modulation(pnd); + // + // Some work to do before getting the UID... + // send ICLASS_ACTIVATE_ALL command - will get timeout as we don't expect response + uint8_t abtReqt[] = { 0x0a }; // iClass ACTIVATE_ALL + uint8_t abtAnticol[11]; + if ((res = pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), NULL, 0, timeout)) < 0) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "got expected timeout on iClass activate all"); + //if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout + // continue; + //} else + // return res; + } + // do select - returned anticol contains 'handle' for tag if present + abtReqt[0]= 0x0c; // iClass SELECT + abtAnticol[0]= 0x81; // iClass ANTICOL + if ((res = pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), &abtAnticol[1], sizeof(abtAnticol) - 1, timeout)) < 0) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "timeout on iClass anticol"); return res; + } + // write back anticol handle to get UID + if ((res = pn53x_initiator_transceive_bytes(pnd, abtAnticol, 9, abtTargetsData, 10, timeout)) < 0) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "timeout on iClass get UID"); + return res; + } + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "iClass raw UID: %02x %02x %02x %02x %02x %02x %02x %02x", abtTargetsData[0], abtTargetsData[1], abtTargetsData[2], abtTargetsData[3], abtTargetsData[4], abtTargetsData[5], abtTargetsData[6], abtTargetsData[7]); + szTargetsData = 8; + nttmp.nm = nm; + if ((res = pn53x_decode_target_data(abtTargetsData, szTargetsData, CHIP_DATA(pnd)->type, nm.nmt, &(nttmp.nti))) < 0) { + return res; } - szTargetsData = (size_t)res; + } + if (nm.nmt == NMT_ISO14443B2CT) { if (szTargetsData != 2) return 0; // Target is not ISO14443B2CT @@ -2138,6 +2224,29 @@ static int pn53x_ISO14443B_SR_is_present(struct nfc_device *pnd) return ret; } +static int pn53x_ISO14443B_ICLASS_is_present(struct nfc_device *pnd) +{ + int timeout= 300; + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping B iClass"); + pn53x_initiator_init_iclass_modulation(pnd); + // + // Some work to do before getting the UID... + // send ICLASS_ACTIVATE_ALL command - will get timeout as we don't expect response + uint8_t abtReqt[] = { 0x0a }; // iClass ACTIVATE_ALL + uint8_t abtAnticol[11]; + if (pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), NULL, 0, timeout) < 0) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "got expected timeout on iClass activate all"); + } + // do select - returned anticol contains 'handle' for tag if present + abtReqt[0]= 0x0c; // iClass SELECT + abtAnticol[0]= 0x81; // iClass ANTICOL + if (pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), &abtAnticol[1], sizeof(abtAnticol) - 1, timeout) < 0) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "timeout on iClass anticol"); + return NFC_ETGRELEASED;; + } + return NFC_SUCCESS; +} + static int pn53x_ISO14443B_CT_is_present(struct nfc_device *pnd) { int ret; @@ -2218,6 +2327,11 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) case NMT_ISO14443B2CT: ret = pn53x_ISO14443B_CT_is_present(pnd); break; + case NMT_ISO14443BICLASS: + ret = pn53x_ISO14443B_ICLASS_is_present(pnd); + break; + case NMT_END_ENUM: + break; } if (ret == NFC_ETGRELEASED) pn53x_current_target_free(pnd); @@ -2268,8 +2382,10 @@ pn53x_target_init(struct nfc_device *pnd, nfc_target *pnt, uint8_t *pbtRx, const case NMT_ISO14443BI: case NMT_ISO14443B2SR: case NMT_ISO14443B2CT: + case NMT_ISO14443BICLASS: case NMT_JEWEL: case NMT_BARCODE: + case NMT_END_ENUM: pnd->last_error = NFC_EDEVNOTSUPP; return pnd->last_error; } @@ -2370,8 +2486,10 @@ pn53x_target_init(struct nfc_device *pnd, nfc_target *pnt, uint8_t *pbtRx, const case NMT_ISO14443BI: case NMT_ISO14443B2SR: case NMT_ISO14443B2CT: + case NMT_ISO14443BICLASS: case NMT_JEWEL: case NMT_BARCODE: + case NMT_END_ENUM: pnd->last_error = NFC_EDEVNOTSUPP; return pnd->last_error; } @@ -2525,9 +2643,12 @@ pn53x_target_receive_bytes(struct nfc_device *pnd, uint8_t *pbtRx, const size_t case NMT_ISO14443BI: case NMT_ISO14443B2SR: case NMT_ISO14443B2CT: + case NMT_ISO14443BICLASS: case NMT_FELICA: abtCmd[0] = TgGetInitiatorCommand; break; + case NMT_END_ENUM: + break; } } else { abtCmd[0] = TgGetInitiatorCommand; @@ -2631,9 +2752,12 @@ pn53x_target_send_bytes(struct nfc_device *pnd, const uint8_t *pbtTx, const size case NMT_ISO14443BI: case NMT_ISO14443B2SR: case NMT_ISO14443B2CT: + case NMT_ISO14443BICLASS: case NMT_FELICA: abtCmd[0] = TgResponseToInitiator; break; + case NMT_END_ENUM: + break; } } else { abtCmd[0] = TgResponseToInitiator; @@ -3253,6 +3377,7 @@ pn53x_nm_to_pm(const nfc_modulation nm) return PM_ISO14443A_106; case NMT_ISO14443B: + case NMT_ISO14443BICLASS: switch (nm.nbr) { case NBR_106: return PM_ISO14443B_106; @@ -3292,6 +3417,7 @@ pn53x_nm_to_pm(const nfc_modulation nm) case NMT_ISO14443B2SR: case NMT_ISO14443B2CT: case NMT_DEP: + case NMT_END_ENUM: // Nothing to do... break; } @@ -3351,6 +3477,7 @@ pn53x_nm_to_ptt(const nfc_modulation nm) // return PTT_ISO14443_4A_106; case NMT_ISO14443B: + case NMT_ISO14443BICLASS: switch (nm.nbr) { case NBR_106: return PTT_ISO14443_4B_106; @@ -3388,6 +3515,7 @@ pn53x_nm_to_ptt(const nfc_modulation nm) case NMT_ISO14443B2CT: case NMT_BARCODE: case NMT_DEP: + case NMT_END_ENUM: // Nothing to do... break; } @@ -3436,6 +3564,7 @@ pn53x_get_supported_baud_rate(nfc_device *pnd, const nfc_mode mode, const nfc_mo case NMT_ISO14443BI: case NMT_ISO14443B2SR: case NMT_ISO14443B2CT: + case NMT_ISO14443BICLASS: *supported_br = (nfc_baud_rate *)pn532_iso14443b_supported_baud_rates; break; case NMT_JEWEL: @@ -3447,6 +3576,7 @@ pn53x_get_supported_baud_rate(nfc_device *pnd, const nfc_mode mode, const nfc_mo case NMT_DEP: *supported_br = (nfc_baud_rate *)pn53x_dep_supported_baud_rates; break; + case NMT_END_ENUM: default: return NFC_EINVARG; } diff --git a/libnfc/chips/pn53x.h b/libnfc/chips/pn53x.h index f236930f..4d769f8b 100644 --- a/libnfc/chips/pn53x.h +++ b/libnfc/chips/pn53x.h @@ -9,6 +9,7 @@ * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: + * Copyright (C) 2020 Adam Laurie * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the @@ -322,6 +323,7 @@ int pn53x_idle(struct nfc_device *pnd); // NFC device as Initiator functions int pn53x_initiator_init(struct nfc_device *pnd); +void pn53x_initiator_init_iclass_modulation(struct nfc_device *pnd); int pn532_initiator_init_secure_element(struct nfc_device *pnd); int pn53x_initiator_select_passive_target(struct nfc_device *pnd, const nfc_modulation nm, diff --git a/libnfc/nfc-internal.c b/libnfc/nfc-internal.c index d90bb877..0200aa40 100644 --- a/libnfc/nfc-internal.c +++ b/libnfc/nfc-internal.c @@ -9,6 +9,7 @@ * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: + * Copyright (C) 2020 Adam Laurie * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the @@ -206,6 +207,8 @@ prepare_initiator_data(const nfc_modulation nm, uint8_t **ppbtInitiatorData, siz *ppbtInitiatorData = NULL; *pszInitiatorData = 0; break; + case NMT_END_ENUM: + break; } } diff --git a/libnfc/nfc.c b/libnfc/nfc.c index c06da0eb..55e8926e 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -9,6 +9,7 @@ * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: + * Copyright (C) 2020 Adam Laurie * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the @@ -206,7 +207,10 @@ int nfc_register_driver(const struct nfc_driver *ndr) { if (!ndr) + { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "nfc_register_driver returning NFC_EINVARG"); return NFC_EINVARG; + } struct nfc_driver_list *pndl = (struct nfc_driver_list *)malloc(sizeof(struct nfc_driver_list)); if (!pndl) @@ -1296,9 +1300,11 @@ nfc_device_validate_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_m if (nbr[j] == nm->nbr) return NFC_SUCCESS; } + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "nfc_device_validate_modulation returning NFC_EINVARG"); return NFC_EINVARG; } } + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "nfc_device_validate_modulation returning NFC_EINVARG"); return NFC_EINVARG; } @@ -1396,6 +1402,8 @@ str_nfc_modulation_type(const nfc_modulation_type nmt) return "Thinfilm NFC Barcode"; case NMT_DEP: return "D.E.P."; + case NMT_END_ENUM: + break; } return "???"; diff --git a/libnfc/target-subr.c b/libnfc/target-subr.c index 61cedfd5..e6b143c8 100644 --- a/libnfc/target-subr.c +++ b/libnfc/target-subr.c @@ -9,6 +9,7 @@ * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: + * Copyright (C) 2020 Adam Laurie * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the @@ -609,6 +610,15 @@ snprint_nfc_iso14443b2sr_info(char *dst, size_t size, const nfc_iso14443b2sr_inf snprint_hex(dst + off, size - off, pnsi->abtUID, 8); } +void +snprint_nfc_iso14443biclass_info(char *dst, size_t size, const nfc_iso14443biclass_info *pnic, bool verbose) +{ + (void) verbose; + int off = 0; + off += snprintf(dst + off, size - off, " UID: "); + snprint_hex(dst + off, size - off, pnic->abtUID, 8); +} + void snprint_nfc_iso14443b2ct_info(char *dst, size_t size, const nfc_iso14443b2ct_info *pnci, bool verbose) { @@ -668,12 +678,17 @@ snprint_nfc_target(char *dst, size_t size, const nfc_target *pnt, bool verbose) case NMT_ISO14443B2SR: snprint_nfc_iso14443b2sr_info(dst + off, size - off, &pnt->nti.nsi, verbose); break; + case NMT_ISO14443BICLASS: + snprint_nfc_iso14443biclass_info(dst + off, size - off, &pnt->nti.nic, verbose); + break; case NMT_ISO14443B2CT: snprint_nfc_iso14443b2ct_info(dst + off, size - off, &pnt->nti.nci, verbose); break; case NMT_DEP: snprint_nfc_dep_info(dst + off, size - off, &pnt->nti.ndi, verbose); break; + case NMT_END_ENUM: + break; } } } diff --git a/libnfc/target-subr.h b/libnfc/target-subr.h index 9205d6fd..633d20db 100644 --- a/libnfc/target-subr.h +++ b/libnfc/target-subr.h @@ -9,6 +9,7 @@ * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: + * Copyright (C) 2020 Adam Laurie * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the @@ -37,6 +38,7 @@ void snprint_nfc_iso14443a_info(char *dst, size_t size, const nfc_iso14443a_i void snprint_nfc_iso14443b_info(char *dst, size_t size, const nfc_iso14443b_info *pnbi, bool verbose); void snprint_nfc_iso14443bi_info(char *dst, size_t size, const nfc_iso14443bi_info *pnii, bool verbose); void snprint_nfc_iso14443b2sr_info(char *dst, size_t size, const nfc_iso14443b2sr_info *pnsi, bool verbose); +void snprint_nfc_iso14443biclass_info(char *dst, size_t size, const nfc_iso14443biclass_info *pnic, bool verbose); void snprint_nfc_iso14443b2ct_info(char *dst, size_t size, const nfc_iso14443b2ct_info *pnci, bool verbose); void snprint_nfc_felica_info(char *dst, size_t size, const nfc_felica_info *pnfi, bool verbose); void snprint_nfc_jewel_info(char *dst, size_t size, const nfc_jewel_info *pnji, bool verbose); diff --git a/utils/nfc-list.c b/utils/nfc-list.c index 55e42249..db8b3958 100644 --- a/utils/nfc-list.c +++ b/utils/nfc-list.c @@ -9,6 +9,7 @@ * Copyright (C) 2012-2013 Ludovic Rousseau * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: + * Copyright (C) 2020 Adam Laurie * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -71,6 +72,7 @@ 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 96: ISO14443B iClass\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"); @@ -271,6 +273,22 @@ main(int argc, const char *argv[]) } } + if (mask & 0x60) { + nm.nmt = NMT_ISO14443BICLASS; + nm.nbr = NBR_106; + // List ISO14443B iClass targets + if ((res = nfc_initiator_list_passive_targets(pnd, nm, ant, MAX_TARGET_COUNT)) >= 0) { + int n; + if (verbose || (res > 0)) { + printf("%d ISO14443B iClass passive target(s) found%s\n", res, (res == 0) ? ".\n" : ":"); + } + for (n = 0; n < res; n++) { + print_nfc_target(&ant[n], verbose); + printf("\n"); + } + } + } + if (mask & 0x80) { nm.nmt = NMT_JEWEL; nm.nbr = NBR_106; From dcc52cd4d5d0bcae2462402ed67d326bb9731087 Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Mon, 11 May 2020 18:04:57 +0100 Subject: [PATCH 248/318] updates as per @goedox comments --- include/nfc/nfc-types.h | 2 +- libnfc/chips/pn53x.c | 17 +++++++++++++---- libnfc/nfc-internal.c | 16 ++++++---------- libnfc/nfc.c | 2 ++ libnfc/target-subr.c | 2 +- 5 files changed, 23 insertions(+), 16 deletions(-) diff --git a/include/nfc/nfc-types.h b/include/nfc/nfc-types.h index 6ca57a41..2a9af340 100644 --- a/include/nfc/nfc-types.h +++ b/include/nfc/nfc-types.h @@ -293,7 +293,7 @@ typedef union { nfc_jewel_info nji; nfc_barcode_info nti; // "t" for Thinfilm, "b" already used nfc_dep_info ndi; - nfc_iso14443biclass_info nic; // iclass - nbi already used + nfc_iso14443biclass_info nhi; // hid iclass / picopass - nii already used } nfc_target_info; /** diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 44b862c5..12b01fa4 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -581,7 +581,7 @@ pn53x_decode_target_data(const uint8_t *pbtRawData, size_t szRawData, pn53x_type case NMT_ISO14443BICLASS: // Store the UID for(uint8_t i= 0 ; i < 8 ; ++i) - pnti->nic.abtUID[7 - i]= pbtRawData[i]; + pnti->nhi.abtUID[7 - i]= pbtRawData[i]; break; case NMT_ISO14443B2CT: @@ -1062,7 +1062,7 @@ pn53x_initiator_init(struct nfc_device *pnd) // iclass requires special modulation settings void pn53x_initiator_init_iclass_modulation(struct nfc_device *pnd) { - // send a bunch of low level commands I reverse engineered from a working iClass reader + // send a bunch of low level commands reverse engineered from a working iClass reader // original device was using a PN512 // // // TxModeReg - Defines the data rate and framing during transmission. @@ -1196,12 +1196,12 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, abtReqt[0]= 0x0c; // iClass SELECT abtAnticol[0]= 0x81; // iClass ANTICOL if ((res = pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), &abtAnticol[1], sizeof(abtAnticol) - 1, timeout)) < 0) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "timeout on iClass anticol"); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "timeout on iClass anticol"); return res; } // write back anticol handle to get UID if ((res = pn53x_initiator_transceive_bytes(pnd, abtAnticol, 9, abtTargetsData, 10, timeout)) < 0) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "timeout on iClass get UID"); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "timeout on iClass get UID"); return res; } log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "iClass raw UID: %02x %02x %02x %02x %02x %02x %02x %02x", abtTargetsData[0], abtTargetsData[1], abtTargetsData[2], abtTargetsData[3], abtTargetsData[4], abtTargetsData[5], abtTargetsData[6], abtTargetsData[7]); @@ -1210,6 +1210,15 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, if ((res = pn53x_decode_target_data(abtTargetsData, szTargetsData, CHIP_DATA(pnd)->type, nm.nmt, &(nttmp.nti))) < 0) { return res; } + } else { + + if ((res = pn53x_initiator_transceive_bytes(pnd, pbtInitData, szInitData, abtTargetsData, sizeof(abtTargetsData), timeout)) < 0) { + if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout + continue; + } else + return res; + } + szTargetsData = (size_t)res; } if (nm.nmt == NMT_ISO14443B2CT) { diff --git a/libnfc/nfc-internal.c b/libnfc/nfc-internal.c index 0200aa40..07a3698d 100644 --- a/libnfc/nfc-internal.c +++ b/libnfc/nfc-internal.c @@ -170,37 +170,33 @@ void prepare_initiator_data(const nfc_modulation nm, uint8_t **ppbtInitiatorData, size_t *pszInitiatorData) { switch (nm.nmt) { - case NMT_ISO14443B: { + case NMT_ISO14443B: // Application Family Identifier (AFI) must equals 0x00 in order to wakeup all ISO14443-B PICCs (see ISO/IEC 14443-3) *ppbtInitiatorData = (uint8_t *) "\x00"; *pszInitiatorData = 1; - } break; - case NMT_ISO14443BI: { + case NMT_ISO14443BI: // APGEN *ppbtInitiatorData = (uint8_t *) "\x01\x0b\x3f\x80"; *pszInitiatorData = 4; - } break; - case NMT_ISO14443B2SR: { + case NMT_ISO14443B2SR: // Get_UID *ppbtInitiatorData = (uint8_t *) "\x0b"; *pszInitiatorData = 1; - } break; - case NMT_ISO14443B2CT: { + case NMT_ISO14443B2CT: // SELECT-ALL *ppbtInitiatorData = (uint8_t *) "\x9F\xFF\xFF"; *pszInitiatorData = 3; - } break; - case NMT_FELICA: { + case NMT_FELICA: // polling payload must be present (see ISO/IEC 18092 11.2.2.5) *ppbtInitiatorData = (uint8_t *) "\x00\xff\xff\x01\x00"; *pszInitiatorData = 5; - } break; case NMT_ISO14443A: + case NMT_ISO14443BICLASS: case NMT_JEWEL: case NMT_BARCODE: case NMT_DEP: diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 55e8926e..8e003c22 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -1390,6 +1390,8 @@ str_nfc_modulation_type(const nfc_modulation_type nmt) return "ISO/IEC 14443-4B"; case NMT_ISO14443BI: return "ISO/IEC 14443-4B'"; + case NMT_ISO14443BICLASS: + return "ISO/IEC 14443-2B-3B iClass (Picopass)"; case NMT_ISO14443B2CT: return "ISO/IEC 14443-2B ASK CTx"; case NMT_ISO14443B2SR: diff --git a/libnfc/target-subr.c b/libnfc/target-subr.c index e6b143c8..3bd97e48 100644 --- a/libnfc/target-subr.c +++ b/libnfc/target-subr.c @@ -679,7 +679,7 @@ snprint_nfc_target(char *dst, size_t size, const nfc_target *pnt, bool verbose) snprint_nfc_iso14443b2sr_info(dst + off, size - off, &pnt->nti.nsi, verbose); break; case NMT_ISO14443BICLASS: - snprint_nfc_iso14443biclass_info(dst + off, size - off, &pnt->nti.nic, verbose); + snprint_nfc_iso14443biclass_info(dst + off, size - off, &pnt->nti.nhi, verbose); break; case NMT_ISO14443B2CT: snprint_nfc_iso14443b2ct_info(dst + off, size - off, &pnt->nti.nci, verbose); From 96568a1023ce4568f9dc8d8c94b47b024781a2ee Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 11 May 2020 19:46:46 +0200 Subject: [PATCH 249/318] fix nfc-list for types B --- libnfc/chips/pn53x.c | 34 +++++++++++++++++++++++++--------- libnfc/nfc-internal.c | 12 ++---------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 12b01fa4..3689adb7 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1155,6 +1155,8 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, size_t szInitiateLen = 2; uint8_t abtSelect[] = { 0x0e, 0x00 }; uint8_t abtRx[1]; + uint8_t *pbtInitData = (uint8_t *) "\x0b"; + size_t szInitData = 1; // Getting random Chip_ID if ((res = pn53x_initiator_transceive_bytes(pnd, abtInitiate, szInitiateLen, abtRx, sizeof(abtRx), timeout)) < 0) { if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout @@ -1167,9 +1169,18 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, return res; } szTargetsData = (size_t)res; + if ((res = pn53x_initiator_transceive_bytes(pnd, pbtInitData, szInitData, abtTargetsData, sizeof(abtTargetsData), timeout)) < 0) { + if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout + continue; + } else + return res; + } + szTargetsData = (size_t)res; } else if (nm.nmt == NMT_ISO14443B2CT) { // Some work to do before getting the UID... const uint8_t abtReqt[] = { 0x10 }; + uint8_t *pbtInitData = (uint8_t *) "\x9F\xFF\xFF"; + size_t szInitData = 3; // Getting product code / fab code & store it in output buffer after the serial nr we'll obtain later if ((res = pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), abtTargetsData + 2, sizeof(abtTargetsData) - 2, timeout)) < 0) { if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout @@ -1178,6 +1189,20 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, return res; } szTargetsData = (size_t)res; + if ((res = pn53x_initiator_transceive_bytes(pnd, pbtInitData, szInitData, abtTargetsData, sizeof(abtTargetsData), timeout)) < 0) { + if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout + continue; + } else + return res; + } + szTargetsData = (size_t)res; + if (szTargetsData != 2) + return 0; // Target is not ISO14443B2CT + uint8_t abtRead[] = { 0xC4 }; // Reading UID_MSB (Read address 4) + if ((res = pn53x_initiator_transceive_bytes(pnd, abtRead, sizeof(abtRead), abtTargetsData + 4, sizeof(abtTargetsData) - 4, timeout)) < 0) { + return res; + } + szTargetsData = 6; // u16 UID_LSB, u8 prod code, u8 fab code, u16 UID_MSB } else if (nm.nmt == NMT_ISO14443BICLASS) { pn53x_initiator_init_iclass_modulation(pnd); // @@ -1221,15 +1246,6 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, szTargetsData = (size_t)res; } - if (nm.nmt == NMT_ISO14443B2CT) { - if (szTargetsData != 2) - return 0; // Target is not ISO14443B2CT - uint8_t abtRead[] = { 0xC4 }; // Reading UID_MSB (Read address 4) - if ((res = pn53x_initiator_transceive_bytes(pnd, abtRead, sizeof(abtRead), abtTargetsData + 4, sizeof(abtTargetsData) - 4, timeout)) < 0) { - return res; - } - szTargetsData = 6; // u16 UID_LSB, u8 prod code, u8 fab code, u16 UID_MSB - } nttmp.nm = nm; if ((res = pn53x_decode_target_data(abtTargetsData, szTargetsData, CHIP_DATA(pnd)->type, nm.nmt, &(nttmp.nti))) < 0) { return res; diff --git a/libnfc/nfc-internal.c b/libnfc/nfc-internal.c index 07a3698d..e78a288e 100644 --- a/libnfc/nfc-internal.c +++ b/libnfc/nfc-internal.c @@ -180,22 +180,14 @@ prepare_initiator_data(const nfc_modulation nm, uint8_t **ppbtInitiatorData, siz *ppbtInitiatorData = (uint8_t *) "\x01\x0b\x3f\x80"; *pszInitiatorData = 4; break; - case NMT_ISO14443B2SR: - // Get_UID - *ppbtInitiatorData = (uint8_t *) "\x0b"; - *pszInitiatorData = 1; - break; - case NMT_ISO14443B2CT: - // SELECT-ALL - *ppbtInitiatorData = (uint8_t *) "\x9F\xFF\xFF"; - *pszInitiatorData = 3; - break; case NMT_FELICA: // polling payload must be present (see ISO/IEC 18092 11.2.2.5) *ppbtInitiatorData = (uint8_t *) "\x00\xff\xff\x01\x00"; *pszInitiatorData = 5; break; case NMT_ISO14443A: + case NMT_ISO14443B2CT: + case NMT_ISO14443B2SR: case NMT_ISO14443BICLASS: case NMT_JEWEL: case NMT_BARCODE: From 10f880374ca8b712b7600d87470fb7e4bceb6ab0 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 11 May 2020 19:55:44 +0200 Subject: [PATCH 250/318] nfc-list bitfield --- utils/nfc-list.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/utils/nfc-list.c b/utils/nfc-list.c index db8b3958..9b20517a 100644 --- a/utils/nfc-list.c +++ b/utils/nfc-list.c @@ -72,11 +72,11 @@ print_usage(const char *progname) printf("\t 16: ISO14443B'\n"); printf("\t 32: ISO14443B-2 ST SRx\n"); printf("\t 64: ISO14443B-2 ASK CTx\n"); - printf("\t 96: ISO14443B iClass\n"); - printf("\t 128: ISO14443A-3 Jewel\n"); - printf("\t 256: ISO14443A-2 NFC Barcode\n"); - printf("\tSo 511 (default) polls for all types.\n"); - printf("\tNote that if 16, 32 or 64 then 8 is selected too.\n"); + printf("\t 128: ISO14443B iClass\n"); + printf("\t 256: ISO14443A-3 Jewel\n"); + printf("\t 512: ISO14443A-2 NFC Barcode\n"); + printf("\tSo 1023 (default) polls for all types.\n"); + printf("\tNote that if 16, 32, 64 or 128 then 8 is selected too.\n"); } int @@ -87,7 +87,7 @@ main(int argc, const char *argv[]) size_t i; bool verbose = false; int res = 0; - int mask = 0x1ff; + int mask = 0x3ff; int arg; nfc_context *context; @@ -111,13 +111,13 @@ main(int argc, const char *argv[]) } else if ((0 == strcmp(argv[arg], "-t")) && (arg + 1 < argc)) { arg++; mask = atoi(argv[arg]); - if ((mask < 1) || (mask > 0x1ff)) { + if ((mask < 1) || (mask > 0x3ff)) { ERR("%i is invalid value for type bitfield.", mask); print_usage(argv[0]); exit(EXIT_FAILURE); } // Force TypeB for all derivatives of B - if (mask & 0x70) + if (mask & 0xf0) mask |= 0x08; } else { ERR("%s is not supported option.", argv[arg]); @@ -273,7 +273,7 @@ main(int argc, const char *argv[]) } } - if (mask & 0x60) { + if (mask & 0x80) { nm.nmt = NMT_ISO14443BICLASS; nm.nbr = NBR_106; // List ISO14443B iClass targets @@ -289,7 +289,7 @@ main(int argc, const char *argv[]) } } - if (mask & 0x80) { + if (mask & 0x100) { nm.nmt = NMT_JEWEL; nm.nbr = NBR_106; // List Jewel targets @@ -305,7 +305,7 @@ main(int argc, const char *argv[]) } } - if (mask & 0x100) { + if (mask & 0x200) { nm.nmt = NMT_BARCODE; nm.nbr = NBR_106; // List NFC Barcode targets @@ -320,6 +320,7 @@ main(int argc, const char *argv[]) } } } + nfc_close(pnd); } From a07d879496aac4dc154fffc8b540a299bb536538 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 11 May 2020 20:00:04 +0200 Subject: [PATCH 251/318] rework NMT_END_ENUM --- include/nfc/nfc-types.h | 2 +- libnfc/chips/pn53x.c | 15 +-------------- libnfc/nfc-internal.c | 2 -- libnfc/nfc.c | 2 -- libnfc/target-subr.c | 2 -- 5 files changed, 2 insertions(+), 21 deletions(-) diff --git a/include/nfc/nfc-types.h b/include/nfc/nfc-types.h index 2a9af340..5817e7c8 100644 --- a/include/nfc/nfc-types.h +++ b/include/nfc/nfc-types.h @@ -323,7 +323,7 @@ typedef enum { NMT_FELICA, NMT_DEP, NMT_ISO14443BICLASS, // HID iClass 14443B mode - NMT_END_ENUM, // dummy for sizing - always should be last + NMT_END_ENUM = NMT_ISO14443BICLASS, // dummy for sizing - always should alias last } nfc_modulation_type; /** diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 3689adb7..4dc2a154 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -86,7 +86,7 @@ pn53x_init(struct nfc_device *pnd) } if (!CHIP_DATA(pnd)->supported_modulation_as_initiator) { - CHIP_DATA(pnd)->supported_modulation_as_initiator = malloc(sizeof(nfc_modulation_type) * (NMT_END_ENUM)); + CHIP_DATA(pnd)->supported_modulation_as_initiator = malloc(sizeof(nfc_modulation_type) * (NMT_END_ENUM + 1)); if (! CHIP_DATA(pnd)->supported_modulation_as_initiator) return NFC_ESOFT; int nbSupportedModulation = 0; @@ -629,8 +629,6 @@ pn53x_decode_target_data(const uint8_t *pbtRawData, size_t szRawData, pn53x_type // Should not happend... case NMT_DEP: return NFC_ECHIP; - case NMT_END_ENUM: - break; } return NFC_SUCCESS; } @@ -2355,8 +2353,6 @@ pn53x_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt) case NMT_ISO14443BICLASS: ret = pn53x_ISO14443B_ICLASS_is_present(pnd); break; - case NMT_END_ENUM: - break; } if (ret == NFC_ETGRELEASED) pn53x_current_target_free(pnd); @@ -2410,7 +2406,6 @@ pn53x_target_init(struct nfc_device *pnd, nfc_target *pnt, uint8_t *pbtRx, const case NMT_ISO14443BICLASS: case NMT_JEWEL: case NMT_BARCODE: - case NMT_END_ENUM: pnd->last_error = NFC_EDEVNOTSUPP; return pnd->last_error; } @@ -2514,7 +2509,6 @@ pn53x_target_init(struct nfc_device *pnd, nfc_target *pnt, uint8_t *pbtRx, const case NMT_ISO14443BICLASS: case NMT_JEWEL: case NMT_BARCODE: - case NMT_END_ENUM: pnd->last_error = NFC_EDEVNOTSUPP; return pnd->last_error; } @@ -2672,8 +2666,6 @@ pn53x_target_receive_bytes(struct nfc_device *pnd, uint8_t *pbtRx, const size_t case NMT_FELICA: abtCmd[0] = TgGetInitiatorCommand; break; - case NMT_END_ENUM: - break; } } else { abtCmd[0] = TgGetInitiatorCommand; @@ -2781,8 +2773,6 @@ pn53x_target_send_bytes(struct nfc_device *pnd, const uint8_t *pbtTx, const size case NMT_FELICA: abtCmd[0] = TgResponseToInitiator; break; - case NMT_END_ENUM: - break; } } else { abtCmd[0] = TgResponseToInitiator; @@ -3442,7 +3432,6 @@ pn53x_nm_to_pm(const nfc_modulation nm) case NMT_ISO14443B2SR: case NMT_ISO14443B2CT: case NMT_DEP: - case NMT_END_ENUM: // Nothing to do... break; } @@ -3540,7 +3529,6 @@ pn53x_nm_to_ptt(const nfc_modulation nm) case NMT_ISO14443B2CT: case NMT_BARCODE: case NMT_DEP: - case NMT_END_ENUM: // Nothing to do... break; } @@ -3601,7 +3589,6 @@ pn53x_get_supported_baud_rate(nfc_device *pnd, const nfc_mode mode, const nfc_mo case NMT_DEP: *supported_br = (nfc_baud_rate *)pn53x_dep_supported_baud_rates; break; - case NMT_END_ENUM: default: return NFC_EINVARG; } diff --git a/libnfc/nfc-internal.c b/libnfc/nfc-internal.c index e78a288e..b57b97cb 100644 --- a/libnfc/nfc-internal.c +++ b/libnfc/nfc-internal.c @@ -195,8 +195,6 @@ prepare_initiator_data(const nfc_modulation nm, uint8_t **ppbtInitiatorData, siz *ppbtInitiatorData = NULL; *pszInitiatorData = 0; break; - case NMT_END_ENUM: - break; } } diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 8e003c22..8c12578e 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -1404,8 +1404,6 @@ str_nfc_modulation_type(const nfc_modulation_type nmt) return "Thinfilm NFC Barcode"; case NMT_DEP: return "D.E.P."; - case NMT_END_ENUM: - break; } return "???"; diff --git a/libnfc/target-subr.c b/libnfc/target-subr.c index 3bd97e48..e3f09c5f 100644 --- a/libnfc/target-subr.c +++ b/libnfc/target-subr.c @@ -687,8 +687,6 @@ snprint_nfc_target(char *dst, size_t size, const nfc_target *pnt, bool verbose) case NMT_DEP: snprint_nfc_dep_info(dst + off, size - off, &pnt->nti.ndi, verbose); break; - case NMT_END_ENUM: - break; } } } From 17e615e8b1109afd8934f485da351c776fa6b875 Mon Sep 17 00:00:00 2001 From: Dan Church Date: Mon, 11 May 2020 13:10:48 -0500 Subject: [PATCH 252/318] Add check for Libnfc-NCI before enabling pn71xx If the user specifically requests the driver, throw an error if it cannot find libnfc-nci. Also use the value from pkg-config to determine the library name, instead of hard-coding it. --- configure.ac | 11 +++++++++++ libnfc/drivers/Makefile.am | 2 +- m4/libnfc_drivers.m4 | 7 ++++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index ad8d34cb..47bbf8db 100644 --- a/configure.ac +++ b/configure.ac @@ -47,6 +47,7 @@ AC_HEADER_STDBOOL AC_CHECK_HEADERS([fcntl.h limits.h stdio.h stdlib.h stdint.h stddef.h stdbool.h sys/ioctl.h sys/param.h sys/time.h termios.h]) AC_CHECK_HEADERS([linux/spi/spidev.h], [spi_available="yes"]) AC_CHECK_HEADERS([linux/i2c-dev.h], [i2c_available="yes"]) +AC_CHECK_HEADERS([linux_nfc_api.h], [nfc_nci_available="yes"]) AC_CHECK_FUNCS([memmove memset select strdup strerror strstr strtol usleep], [AC_DEFINE([_XOPEN_SOURCE], [600], [Enable POSIX extensions if present])]) @@ -130,6 +131,16 @@ then AC_SEARCH_LIBS([clock_gettime], [rt]) fi +# Enable Libnfc-NCI if required +if test x"$nfc_nci_required" = x"yes" +then + PKG_CHECK_MODULES([LIBNFC_NCI], [libnfc-nci], + [AC_MSG_NOTICE([libnfc-nci present])], + [AC_MSG_ERROR([libnfc-nci not present but required for some drivers configuration])] + ) + CFLAGS="$CPPFLAGS $LIBNFC_NCI_CFLAGS" +fi + # Documentation (default: no) AC_ARG_ENABLE([doc],AS_HELP_STRING([--enable-doc],[Enable documentation generation.]),[enable_doc=$enableval],[enable_doc="no"]) diff --git a/libnfc/drivers/Makefile.am b/libnfc/drivers/Makefile.am index 3f4d7682..2e6ad451 100644 --- a/libnfc/drivers/Makefile.am +++ b/libnfc/drivers/Makefile.am @@ -44,7 +44,7 @@ libnfcdrivers_la_SOURCES += pn532_i2c.c pn532_i2c.h endif if DRIVER_PN71XX_ENABLED -libnfcdrivers_la_LIBADD += -lnfc_nci_linux +libnfcdrivers_la_LIBADD += @LIBNFC_NCI_LIBS@ libnfcdrivers_la_SOURCES += pn71xx.c pn71xx.h endif diff --git a/m4/libnfc_drivers.m4 b/m4/libnfc_drivers.m4 index c8a75fff..901f9d32 100644 --- a/m4/libnfc_drivers.m4 +++ b/m4/libnfc_drivers.m4 @@ -37,7 +37,7 @@ AC_DEFUN([LIBNFC_ARG_WITH_DRIVERS], fi ;; all) - DRIVER_BUILD_LIST="acr122_pcsc acr122_usb acr122s arygon pn53x_usb pn532_uart pn71xx pcsc" + DRIVER_BUILD_LIST="acr122_pcsc acr122_usb acr122s arygon pn53x_usb pn532_uart pcsc" if test x"$spi_available" = x"yes" then @@ -47,6 +47,10 @@ AC_DEFUN([LIBNFC_ARG_WITH_DRIVERS], then DRIVER_BUILD_LIST="$DRIVER_BUILD_LIST pn532_i2c" fi + if test x"$nfc_nci_available" = x"yes" + then + DRIVER_BUILD_LIST="$DRIVER_BUILD_LIST pn71xx" + fi ;; esac @@ -112,6 +116,7 @@ AC_DEFUN([LIBNFC_ARG_WITH_DRIVERS], DRIVERS_CFLAGS="$DRIVERS_CFLAGS -DDRIVER_PN532_I2C_ENABLED" ;; pn71xx) + nfc_nci_required="yes" driver_pn71xx_enabled="yes" DRIVERS_CFLAGS="$DRIVERS_CFLAGS -DDRIVER_PN71XX_ENABLED" ;; From 66176016ed2cbc37713c77e1d75cc4356e3403c7 Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Tue, 12 May 2020 16:52:47 +0100 Subject: [PATCH 253/318] bring nfc-list man page up to date --- utils/nfc-list.1 | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/utils/nfc-list.1 b/utils/nfc-list.1 index 69eb12e1..74714617 100644 --- a/utils/nfc-list.1 +++ b/utils/nfc-list.1 @@ -27,6 +27,7 @@ This includes SAK decoding and fingerprinting is available. .TP \fB-t\fP \fIX\fP Polls only for types according to bitfield value of \fIX\fP: + 1: ISO14443A 2: Felica (212 kbps) 4: Felica (424 kbps) @@ -34,11 +35,12 @@ Polls only for types according to bitfield value of \fIX\fP: 16: ISO14443B' 32: ISO14443B-2 ST SRx 64: ISO14443B-2 ASK CTx - 128: Jewel - -So 255 (default) polls for all types. + 128: ISO14443B iClass + 256: ISO14443A-3 Jewel + 512: ISO14443A-2 NFC Barcode -Note that if 16, 32 or 64 then 8 is selected too. +So 1023 (default) polls for all types. +Note that if 16, 32, 64 or 128 then 8 is selected too. .SH EXAMPLE For an ISO/IEC 14443-A tag (i.e.Mifare DESFire): From 8352c806798d047eaf1a63ff76c438721784897d Mon Sep 17 00:00:00 2001 From: "hongbin@ftsafe.com" Date: Wed, 13 May 2020 12:15:28 +0800 Subject: [PATCH 254/318] Modify pcsc.c to have support for Mifare classic and Ultralight card Modify pcsc.c and mifare.c files. 1. add code into pcsc.c to have support Mifare classic card. 2. The PCSC reader has SW value, add response data length for PCSC reader --- libnfc/drivers/pcsc.c | 326 +++++++++++++++++++++++++++++++++--------- utils/mifare.c | 4 +- 2 files changed, 259 insertions(+), 71 deletions(-) diff --git a/libnfc/drivers/pcsc.c b/libnfc/drivers/pcsc.c index 8c0cb720..fc818ddf 100644 --- a/libnfc/drivers/pcsc.c +++ b/libnfc/drivers/pcsc.c @@ -44,6 +44,27 @@ #ifdef __APPLE__ #include #include +// define from pcsclite for apple +#define SCARD_AUTOALLOCATE (DWORD)(-1) + +#define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag))) + +#define SCARD_CLASS_VENDOR_INFO 1 /**< Vendor information definitions */ +#define SCARD_CLASS_COMMUNICATIONS 2 /**< Communication definitions */ +#define SCARD_CLASS_PROTOCOL 3 /**< Protocol definitions */ +#define SCARD_CLASS_POWER_MGMT 4 /**< Power Management definitions */ +#define SCARD_CLASS_SECURITY 5 /**< Security Assurance definitions */ +#define SCARD_CLASS_MECHANICAL 6 /**< Mechanical characteristic definitions */ +#define SCARD_CLASS_VENDOR_DEFINED 7 /**< Vendor specific definitions */ +#define SCARD_CLASS_IFD_PROTOCOL 8 /**< Interface Device Protocol options */ +#define SCARD_CLASS_ICC_STATE 9 /**< ICC State specific definitions */ +#define SCARD_CLASS_SYSTEM 0x7fff /**< System-specific definitions */ + +#define SCARD_ATTR_VENDOR_NAME SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0100) /**< Vendor name. */ +#define SCARD_ATTR_VENDOR_IFD_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0101) /**< Vendor-supplied interface device type (model designation of reader). */ +#define SCARD_ATTR_VENDOR_IFD_VERSION SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0102) /**< Vendor-supplied interface device version (DWORD in the form 0xMMmmbbbb where MM = major version, mm = minor version, and bbbb = build number). */ +#define SCARD_ATTR_VENDOR_IFD_SERIAL_NO SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0103) /**< Vendor-supplied interface device serial number. */ +#define SCARD_ATTR_ICC_TYPE_PER_ATR SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0304) /**< Single byte indicating smart card type */ #else #ifndef _Win32 #include @@ -76,18 +97,6 @@ struct pcsc_data { #define DRIVER_DATA(pnd) ((struct pcsc_data*)(pnd->driver_data)) -//Doesn't have define in macOS, so define from reader.h -#define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag))) -#define SCARD_CLASS_VENDOR_INFO 1 -#define SCARD_ATTR_VENDOR_NAME SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0100) -#define SCARD_ATTR_ICC_TYPE_PER_ATR SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0304) -#define SCARD_CLASS_ICC_STATE 9 -#define SCARD_AUTOALLOCATE (DWORD)(-1) -#define SCARD_ATTR_VENDOR_NAME SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0100) -#define SCARD_ATTR_VENDOR_IFD_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0101) -#define SCARD_ATTR_VENDOR_IFD_VERSION SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0102) -#define SCARD_ATTR_VENDOR_IFD_SERIAL_NO SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0103) - static SCARDCONTEXT _SCardContext; static int _iSCardContextRefCount = 0; @@ -184,6 +193,118 @@ uint8_t pcsc_get_icc_type(struct nfc_device *pnd) return it; } +char* pcsc_get_vendor_name(struct nfc_device *pnd){ + struct pcsc_data *data = pnd->driver_data; + LPBYTE vendor_name = NULL; + DWORD vendor_name_len = SCARD_AUTOALLOCATE; + + int res = SCardGetAttrib(data->hCard, SCARD_ATTR_VENDOR_NAME, (LPBYTE)&vendor_name, &vendor_name_len); + if (!res && vendor_name && vendor_name_len > 0 && vendor_name[0] != '\0') { + char *psVendorName = (char *)malloc(sizeof(char) * vendor_name_len); + memcpy(psVendorName, vendor_name, vendor_name_len); + return psVendorName; + } + return NULL; +} + +bool is_pcsc_reader_vendor(struct nfc_device *pnd, const char * target_vendor_name) +{ + bool isTarget = false; + char * sReaderVendorName = pcsc_get_vendor_name(pnd); + if (sReaderVendorName) + { + isTarget = (strstr(sReaderVendorName, target_vendor_name)) ? true:false; + free(sReaderVendorName); + sReaderVendorName = NULL; + } + + return isTarget; +} + +bool is_pcsc_reader_vendor_feitian(struct nfc_device *pnd) +{ + return is_pcsc_reader_vendor(pnd, "Feitian") || is_pcsc_reader_vendor(pnd, "FeiTian") ||is_pcsc_reader_vendor(pnd, "feitian"); +} + +//get atqa by send apdu +int pcsc_get_atqa(struct nfc_device *pnd, uint8_t *atqa, size_t atqa_len) +{ + const uint8_t get_data[] = {0xFF, 0xCA, 0x03, 0x00, 0x00}; + uint8_t resp[256 + 2]; + size_t resp_len = sizeof resp; + + pnd->last_error = pcsc_transmit(pnd, get_data, sizeof get_data, resp, &resp_len); + if (pnd->last_error != NFC_SUCCESS) + return pnd->last_error; + + if (resp_len < 2) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reader doesn't support request for ATQA"); + pnd->last_error = NFC_EDEVNOTSUPP; + return pnd->last_error; + } + if (atqa_len < resp_len - 2) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "ATQA length is wrong"); + pnd->last_error = NFC_ESOFT; + return pnd->last_error; + } + + memcpy(atqa, resp, resp_len - 2); + return resp_len - 2; +} + +//get ats by send apdu +int pcsc_get_ats(struct nfc_device *pnd, uint8_t *ats, size_t ats_len) +{ + const uint8_t get_data[] = {0xFF, 0xCA, 0x01, 0x00, 0x00}; + uint8_t resp[256 + 2]; + size_t resp_len = sizeof resp; + + pnd->last_error = pcsc_transmit(pnd, get_data, sizeof get_data, resp, &resp_len); + if (pnd->last_error != NFC_SUCCESS) + return pnd->last_error; + + if (resp_len < 2) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reader doesn't support request for ATS"); + pnd->last_error = NFC_EDEVNOTSUPP; + return pnd->last_error; + } + if (ats_len < resp_len - 2) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "ATS length is wrong"); + pnd->last_error = NFC_ESOFT; + return pnd->last_error; + } + + //memcpy(ats, resp + 1, resp_len - 2 - 1); + memcpy(ats, resp + 1, resp[0] - 1); + return resp_len - 2 - 1; +} + +//get sak by send apdu +int pcsc_get_sak(struct nfc_device *pnd, uint8_t *sak, size_t sak_len) +{ + const uint8_t get_data[] = {0xFF, 0xCA, 0x02, 0x00, 0x00}; + uint8_t resp[256 + 2]; + size_t resp_len = sizeof resp; + + pnd->last_error = pcsc_transmit(pnd, get_data, sizeof get_data, resp, &resp_len); + if (pnd->last_error != NFC_SUCCESS) + return pnd->last_error; + + if (resp_len < 2) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reader doesn't support request for SAK"); + pnd->last_error = NFC_EDEVNOTSUPP; + return pnd->last_error; + } + if (sak_len < resp_len - 2) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "SAK length is wrong"); + pnd->last_error = NFC_ESOFT; + return pnd->last_error; + } + + memcpy(sak, resp, resp_len - 2); + return resp_len - 2; +} + int pcsc_get_uid(struct nfc_device *pnd, uint8_t *uid, size_t uid_len) { const uint8_t get_data[] = {0xFF, 0xCA, 0x00, 0x00, 0x00}; @@ -209,7 +330,7 @@ int pcsc_get_uid(struct nfc_device *pnd, uint8_t *uid, size_t uid_len) return resp_len - 2; } -int pcsc_props_to_target(uint8_t it, const uint8_t *patr, size_t szatr, const uint8_t *puid, int szuid, const nfc_modulation_type nmt, nfc_target *pnt) +int pcsc_props_to_target(const struct nfc_device *pnd, uint8_t it, const uint8_t *patr, size_t szatr, const uint8_t *puid, int szuid, const nfc_modulation_type nmt, nfc_target *pnt) { if (NULL != pnt) { switch (nmt) { @@ -228,13 +349,31 @@ int pcsc_props_to_target(uint8_t it, const uint8_t *patr, size_t szatr, const ui memcpy(pnt->nti.nai.abtUid, puid, szuid); pnt->nti.nai.szUidLen = szuid; } - /* SAK_ISO14443_4_COMPLIANT */ - pnt->nti.nai.btSak = 0x20; - /* Choose TL, TA, TB, TC according to Mifare DESFire */ - memcpy(pnt->nti.nai.abtAts, "\x75\x77\x81\x02", 4); - /* copy historical bytes */ - memcpy(pnt->nti.nai.abtAts + 4, patr + 4, (uint8_t)(szatr - 5)); - pnt->nti.nai.szAtsLen = 4 + (uint8_t)(szatr - 5); + if (is_pcsc_reader_vendor_feitian(pnd)) + { + uint8_t atqa[2]; + pcsc_get_atqa(pnd,atqa,sizeof(atqa)); + //memcpy(pnt->nti.nai.abtAtqa,atqa,2); + pnt->nti.nai.abtAtqa[0] = atqa[1]; + pnt->nti.nai.abtAtqa[1] = atqa[0]; + uint8_t sak[1]; + pcsc_get_sak(pnd,sak,sizeof(sak)); + pnt->nti.nai.btSak = sak[0]; + uint8_t ats[256]; + int ats_len = pcsc_get_ats(pnd, ats, sizeof(ats)); + memcpy(pnt->nti.nai.abtAts, ats, ats_len); + //memcpy(pnt->nti.nai.abtAts + ats_len, patr + 4, (uint8_t)(szatr - 5)); + pnt->nti.nai.szAtsLen = ats_len;// + szatr - 5; + } else { + /* SAK_ISO14443_4_COMPLIANT */ + pnt->nti.nai.btSak = 0x20; + /* Choose TL, TA, TB, TC according to Mifare DESFire */ + memcpy(pnt->nti.nai.abtAts, "\x75\x77\x81\x02", 4); + /* copy historical bytes */ + memcpy(pnt->nti.nai.abtAts + 4, patr + 4, (uint8_t)(szatr - 5)); + pnt->nti.nai.szAtsLen = 4 + (uint8_t)(szatr - 5); + } + return NFC_SUCCESS; } break; @@ -303,40 +442,6 @@ pcsc_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t int l = strlen(supported_devices[i]); bSupported = 0 == !strncmp(supported_devices[i], acDeviceNames + szPos, l); } - // Supported Feitian Contactless Reader -#if defined (__APPLE__) - // Feitian R502 - if (strstr(acDeviceNames + szPos, "Feitian R502") != NULL) - { - bSupported = true; - } - // Feitian 502-CL - if (strstr(acDeviceNames + szPos, "Feitian 502-CL") != NULL) - { - bSupported = true; - } - // Feitian bR500 - if (strstr(acDeviceNames + szPos, "Feitian bR500") != NULL) - { - bSupported = true; - } -#else - // Feitian R502 - if (strstr(acDeviceNames + szPos, "Feitian R502 [R502 Contact Reader]") != NULL) - { - bSupported = true; - } - // Feitian 502-CL - if (strstr(acDeviceNames + szPos, "Feitian 502-CL [R502 Contactless Reader]") != NULL) - { - bSupported = true; - } - // Feitian bR500 - if (strstr(acDeviceNames + szPos, "Feitian bR500") != NULL) - { - bSupported = true; - } -#endif if (bSupported) { // Supported non-ACR122 device found @@ -428,8 +533,7 @@ pcsc_open(const nfc_context *context, const nfc_connstring connstring) // Test if context succeeded if (!(pscc = pcsc_get_scardcontext())) goto error; - // T1 or T0 protocol. - DRIVER_DATA(pnd)->last_error = SCardConnect(*pscc, ndd.pcsc_device_name, SCARD_SHARE_DIRECT, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &(DRIVER_DATA(pnd)->hCard), (void *) & (DRIVER_DATA(pnd)->ioCard.dwProtocol)); + DRIVER_DATA(pnd)->last_error = SCardConnect(*pscc, ndd.pcsc_device_name, SCARD_SHARE_DIRECT, 0, &(DRIVER_DATA(pnd)->hCard), (void *) & (DRIVER_DATA(pnd)->ioCard.dwProtocol)); if (DRIVER_DATA(pnd)->last_error != SCARD_S_SUCCESS) { // We can not connect to this device. log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "PCSC connect failed"); @@ -656,7 +760,7 @@ int pcsc_initiator_select_passive_target(struct nfc_device *pnd, const nfc_modu uint8_t icc_type = pcsc_get_icc_type(pnd); int uid_len = pcsc_get_uid(pnd, uid, sizeof uid); - if (pcsc_props_to_target(icc_type, atr, atr_len, uid, uid_len, nm.nmt, pnt) != NFC_SUCCESS) { + if (pcsc_props_to_target(pnd, icc_type, atr, atr_len, uid, uid_len, nm.nmt, pnt) != NFC_SUCCESS) { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Type of target not supported"); return NFC_EDEVNOTSUPP; } @@ -681,7 +785,75 @@ int pcsc_initiator_transceive_bytes(struct nfc_device *pnd, const uint8_t *pbtTx // FIXME: timeout is not handled (void) timeout; - pnd->last_error = pcsc_transmit(pnd, pbtTx, szTx, pbtRx, &resp_len); + if (is_pcsc_reader_vendor_feitian(pnd)){ + LOG_HEX(NFC_LOG_GROUP_COM, "not feitian reader pcsc apdu send", pbtTx, szTx); + + uint8_t apdu_data[256]; + uint8_t resp[256 + 2]; + size_t send_size = 0; + if (pbtTx[0] == 0x30) {//read data + apdu_data[0] = 0xFF; + apdu_data[1] = 0xB0; + apdu_data[2] = 0x00; + apdu_data[3] = pbtTx[1]; + apdu_data[4] = 0x10; + send_size = 5; + } else if (pbtTx[0] == 0xA0 || pbtTx[0] == 0xA2) {//write data + apdu_data[0] = 0xFF; + apdu_data[1] = 0xD6; + apdu_data[2] = 0x00; + apdu_data[3] = pbtTx[1]; + apdu_data[4] = szTx - 2; + memcpy(apdu_data + 5, pbtTx + 2, szTx - 2); + send_size = 5 + szTx - 2; + } else if (pbtTx[0] == 0x60 || pbtTx[0] == 0x61 || pbtTx[0] == 0x1A){//Auth command + apdu_data[0] = 0xFF; + apdu_data[1] = 0x86; + apdu_data[2] = 0x00; + apdu_data[3] = 0x00; + apdu_data[4] = 0x05; + apdu_data[5] = 0x01; + apdu_data[6] = 0x00; + apdu_data[7] = pbtTx[1];//block index + apdu_data[8] = pbtTx[0];//type a or type b + apdu_data[9] = 0x01; + send_size = 10; + } else if (pbtTx[0] == 0xC0){//DECREMENT cmd + apdu_data[0] = 0xFF; + apdu_data[1] = 0xD7; + apdu_data[2] = 0x00; + apdu_data[3] = pbtTx[1];//block index + apdu_data[4] = 0x05; + memcpy(apdu_data + 5, pbtTx + 2, szTx - 2); + send_size = 5 + szTx - 2; + } else if (pbtTx[0] == 0xC1){//INCREMENT cmd + apdu_data[0] = 0xFF; + apdu_data[1] = 0xD7; + apdu_data[2] = 0x00; + apdu_data[3] = pbtTx[1];//block index + apdu_data[4] = 0x05; + memcpy(apdu_data + 5, pbtTx + 2, szTx - 2); + send_size = 5 + szTx - 2; + } else if (pbtTx[0] == 0xC2){//STORE cmd + apdu_data[0] = 0xFF; + apdu_data[1] = 0xD8; + apdu_data[2] = 0x00; + apdu_data[3] = pbtTx[1]; + apdu_data[4] = szTx - 2; + memcpy(apdu_data + 5, pbtTx + 2, szTx - 2); + send_size = 5 + szTx - 2; + } else {//other cmd + memcpy(apdu_data, pbtTx, szTx); + send_size = szTx; + } + LOG_HEX(NFC_LOG_GROUP_COM, "feitian reader pcsc apdu send:", apdu_data, send_size); + pnd->last_error = pcsc_transmit(pnd, apdu_data, send_size, resp, &resp_len); + LOG_HEX(NFC_LOG_GROUP_COM, "feitian reader pcsc apdu received:", resp, resp_len); + + memcpy(pbtRx, resp, resp_len); + } else { + pnd->last_error = pcsc_transmit(pnd, pbtTx, szTx, pbtRx, &resp_len); + } if (pnd->last_error != NFC_SUCCESS) return pnd->last_error; @@ -705,7 +877,7 @@ int pcsc_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *p } if (pnt) { - if (pcsc_props_to_target(ICC_TYPE_UNKNOWN, atr, atr_len, NULL, 0, pnt->nm.nmt, &nt) != NFC_SUCCESS + if (pcsc_props_to_target(pnd, ICC_TYPE_UNKNOWN, atr, atr_len, NULL, 0, pnt->nm.nmt, &nt) != NFC_SUCCESS || pnt->nm.nmt != nt.nm.nmt || pnt->nm.nbr != nt.nm.nbr) { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Target doesn't meet requirements"); return NFC_ENOTSUCHDEV; @@ -722,7 +894,21 @@ int pcsc_device_set_property_bool(struct nfc_device *pnd, const nfc_property pro // ignore return NFC_SUCCESS; case NP_AUTO_ISO14443_4: + { + if (is_pcsc_reader_vendor_feitian(pnd)) + { + //ignore + return NFC_SUCCESS; + } + } case NP_EASY_FRAMING: + { + if (is_pcsc_reader_vendor_feitian(pnd)) + { + //ignore + return NFC_SUCCESS; + } + } case NP_FORCE_ISO14443_A: case NP_HANDLE_CRC: case NP_HANDLE_PARITY: @@ -772,7 +958,7 @@ pcsc_get_information_about(nfc_device *pnd, char **pbuf) struct pcsc_data *data = pnd->driver_data; LPBYTE name = NULL, version = NULL, type = NULL, serial = NULL; DWORD name_len = SCARD_AUTOALLOCATE, version_len = SCARD_AUTOALLOCATE, - type_len = SCARD_AUTOALLOCATE, serial_len = SCARD_AUTOALLOCATE; + type_len = SCARD_AUTOALLOCATE, serial_len = SCARD_AUTOALLOCATE; int res = NFC_SUCCESS; SCARDCONTEXT *pscc; @@ -807,27 +993,28 @@ pcsc_get_information_about(nfc_device *pnd, char **pbuf) ? "\nserial: " : "", serial_len > 0 ? (char *)serial : ""); error: -// SCardFreeMemory function not supported in macOS. -#if defined(__APPLE__) - if (name != NULL){ +#ifdef __APPLE__ + SCardReleaseContext(*pscc); + if (name != NULL) + { free(name); name = NULL; } - if (type != NULL){ + if (type != NULL) + { free(type); type = NULL; } - if (version != NULL){ + if (version != NULL) + { free(version); version = NULL; } - if (serial != NULL){ + if (serial != NULL) + { free(serial); serial = NULL; } - if (pscc != NULL){ - SCardReleaseContext(pscc); - } #else SCardFreeMemory(*pscc, name); SCardFreeMemory(*pscc, type); @@ -835,7 +1022,6 @@ pcsc_get_information_about(nfc_device *pnd, char **pbuf) SCardFreeMemory(*pscc, serial); #endif - pnd->last_error = res; return pnd->last_error; } diff --git a/utils/mifare.c b/utils/mifare.c index 1cbf6b15..c28198f1 100644 --- a/utils/mifare.c +++ b/utils/mifare.c @@ -130,7 +130,9 @@ nfc_initiator_mifare_cmd(nfc_device *pnd, const mifare_cmd mc, const uint8_t ui8 // When we have executed a read command, copy the received bytes into the param if (mc == MC_READ) { - if (res == 16) { + + //Check the length of response data, with PCSC reader, there have 2 bytes for SW value + if (res == 16 || res == (16 + 2)) { memcpy(pmp->mpd.abtData, abtRx, 16); } else { return false; From 6f41ea3ad3a13dadbe327f9cd462ecf55c542cd1 Mon Sep 17 00:00:00 2001 From: Dan Church Date: Wed, 13 May 2020 09:05:27 -0500 Subject: [PATCH 255/318] Fix typo Introduced in #598 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 47bbf8db..49a660f2 100644 --- a/configure.ac +++ b/configure.ac @@ -138,7 +138,7 @@ then [AC_MSG_NOTICE([libnfc-nci present])], [AC_MSG_ERROR([libnfc-nci not present but required for some drivers configuration])] ) - CFLAGS="$CPPFLAGS $LIBNFC_NCI_CFLAGS" + CFLAGS="$CFLAGS $LIBNFC_NCI_CFLAGS" fi # Documentation (default: no) From beb8fdd75906af6293e1c516b60e8256e80c48e3 Mon Sep 17 00:00:00 2001 From: Feitian Technologies Date: Thu, 14 May 2020 11:08:23 +0800 Subject: [PATCH 256/318] Update pcsc.c Remove call pcsc_get_vendor_name, get the vendor name from struct nfc_device --- libnfc/drivers/pcsc.c | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/libnfc/drivers/pcsc.c b/libnfc/drivers/pcsc.c index fc818ddf..19e419b7 100644 --- a/libnfc/drivers/pcsc.c +++ b/libnfc/drivers/pcsc.c @@ -134,6 +134,12 @@ int pcsc_transmit(struct nfc_device *pnd, const uint8_t *tx, const size_t tx_len { struct pcsc_data *data = pnd->driver_data; DWORD dw_rx_len = *rx_len; + //in libfreefare, tx_len = 1, and it leads to 0x80100008 error, with PC/SC reader, the input tx_len at least two bytes for the SW value + //so if found the reader is Feitian reader, we set to 2 + if (dw_rx_len == 1 && is_pcsc_reader_vendor_feitian(pnd)) + { + dw_rx_len = 2; + } LOG_HEX(NFC_LOG_GROUP_COM, "TX", tx, tx_len); @@ -193,37 +199,20 @@ uint8_t pcsc_get_icc_type(struct nfc_device *pnd) return it; } -char* pcsc_get_vendor_name(struct nfc_device *pnd){ - struct pcsc_data *data = pnd->driver_data; - LPBYTE vendor_name = NULL; - DWORD vendor_name_len = SCARD_AUTOALLOCATE; - - int res = SCardGetAttrib(data->hCard, SCARD_ATTR_VENDOR_NAME, (LPBYTE)&vendor_name, &vendor_name_len); - if (!res && vendor_name && vendor_name_len > 0 && vendor_name[0] != '\0') { - char *psVendorName = (char *)malloc(sizeof(char) * vendor_name_len); - memcpy(psVendorName, vendor_name, vendor_name_len); - return psVendorName; - } - return NULL; -} - bool is_pcsc_reader_vendor(struct nfc_device *pnd, const char * target_vendor_name) { bool isTarget = false; - char * sReaderVendorName = pcsc_get_vendor_name(pnd); - if (sReaderVendorName) + if (pnd == NULL || strlen(pnd->name) == 0) { - isTarget = (strstr(sReaderVendorName, target_vendor_name)) ? true:false; - free(sReaderVendorName); - sReaderVendorName = NULL; + return isTarget; } - return isTarget; + return isTarget = (strstr(pnd->name, target_vendor_name)) ? true:false; } bool is_pcsc_reader_vendor_feitian(struct nfc_device *pnd) { - return is_pcsc_reader_vendor(pnd, "Feitian") || is_pcsc_reader_vendor(pnd, "FeiTian") ||is_pcsc_reader_vendor(pnd, "feitian"); + return is_pcsc_reader_vendor(pnd, "Feitian") || is_pcsc_reader_vendor(pnd, "FeiTian") || is_pcsc_reader_vendor(pnd, "feitian") || is_pcsc_reader_vendor(pnd, "FEITIAN"); } //get atqa by send apdu @@ -994,7 +983,10 @@ pcsc_get_information_about(nfc_device *pnd, char **pbuf) error: #ifdef __APPLE__ - SCardReleaseContext(*pscc); + if (pscc != NULL) + { + SCardReleaseContext(*pscc); + } if (name != NULL) { free(name); @@ -1061,4 +1053,3 @@ const struct nfc_driver pcsc_driver = { .idle = NULL, .powerdown = NULL, }; - From 4a2c764961d2ede7541abedfe0e7e0960803a36a Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Thu, 21 May 2020 12:05:38 +0100 Subject: [PATCH 257/318] Prepare 1.7.2 version --- CMakeLists.txt | 2 +- ChangeLog | 10 +++++++++- NEWS.md | 3 +++ configure.ac | 2 +- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d8b5a82..5a2b3e60 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ project (libnfc C) SET(VERSION_MAJOR "1") SET(VERSION_MINOR "7") -SET(VERSION_PATCH "1") +SET(VERSION_PATCH "2") SET(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") diff --git a/ChangeLog b/ChangeLog index 89f3608d..d0aabea0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -44,6 +44,12 @@ Improvements: - nfc-mfultralight: add support for magic gen2 cards - nfc-mfultralight: add option to specify UID - nfc-barcode: new command to read and decode NFC Barcodes (Tag-Talks-First) + - Add RATS support indicator to nfc-mfclassic + - Adding pn71xx NXP's NFC Controllers through Linux Libnfc-nci + - Added driver for contactless PC/SC readers + - add Feitian R502 and bR500 support into pcsc driver + - Add HID iClass (Picopass) support (nfc-iclass tool in external nfc-tools) + Changes: - nfc_get_supported_baud_rate() takes now a "mode" parameter @@ -56,7 +62,9 @@ Special thanks to: Alexander Inyukhin, Arnaud Kapp, David Kreitschmann, Adam Laurie, Ray Lee, Maxim Martyanov, Paul Menzel, Boris Moiseev, Yerzhan Mukhamejan, Olliver Shinagl, Jairo Andres Suarez, Mati Vait, Marcos Vives Del Sol, - Hidde Wieringa, Simon Yorkston, timzi, usk-johnny-s, xantares + Hidde Wieringa, Simon Yorkston, timzi, usk-johnny-s, xantares, Hanno + Heinrichs, jgeslin, Mikolaj Stawiski, rstular, Khem Raj, Frank Morgner, jpwidera, + Feitian Technologies Feb 24, 2014 - 1.7.1 -------------------- diff --git a/NEWS.md b/NEWS.md index 0263ccae..0cf19947 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,9 @@ API Changes: * nfc_device_get_supported_baud_rate() now takes also "mode" as argument * New nfc_get_supported_baud_rate_target_mode() + * added support for HID iClass (Picopass) (nfc-iclass tool can be found in external nfc-tools repo) + * added support for contacless PC/SC + * added support for Feitian R502 and bR500 PC/SC readers New in 1.7.1: diff --git a/configure.ac b/configure.ac index 49a660f2..67acc470 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ # General init # /!\ Don't forget to update 'CMakeLists.txt' too /!\ -AC_INIT([libnfc],[1.7.1],[nfc-tools@googlegroups.com]) +AC_INIT([libnfc],[1.7.2],[nfc-tools@googlegroups.com]) AC_CONFIG_MACRO_DIR([m4]) From d29b3170d9858cee4e75c72c96af995b38b10b3a Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 21 May 2020 14:14:43 +0200 Subject: [PATCH 258/318] update changelog --- ChangeLog | 27 ++++++++++++++++----------- NEWS.md | 15 ++++++++++----- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index d0aabea0..0f3eb1b5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ -TBD - 1.7.x ------------ +May 21, 2020 - 1.7.2 +-------------------- + Fixes: - Remove unreachable code - nfc_emulate_uid: cleaner exit on interrupt @@ -13,6 +14,7 @@ Fixes: - Fix improper device name initialization - Fix setenv()/unsetenv() for Windows - Fix win32/nfc.def according to nfc.h + - Fix missing timeout in pn53x_initiator_select_passive_target() - nfc-mfclassic: fix option to tolerate write errors - nfc-poll: fix card removing check - nfc-relay-picc: fix wrong open mode for file descriptor @@ -27,34 +29,37 @@ Improvements: - Drop PCRE dependency on Windows - Remove deprecated readdir_r - Markdown conversion of the text files + - Use hardcoded PN533 descriptors to be more robust on Windows - Add support for SCL3712 - Add support for ACR1222U-C1 - Add support for NetBSD - Add support for PN532 on RPi3 UART - Add support for cross-compilation of 32b & 64b versions of the library for Windows - Add pn533_usb to the kernel modules blacklist + - Add support for pn71xx NXP's NFC Controllers through Linux Libnfc-nci (untested) + - Add support for contactless PC/SC readers (only as initiator) + - Add support for Feitian R502 and bR500 into pcsc driver + - Add support for HID iClass (Picopass) support (nfc-iclass tool in external nfc-tools repo) - Allows for sending empty data in nfc_initiator_transceive_bits - driver i2c: respect proper timing specifications - driver i2c: add retry on error mechanism - nfc-mfclassic: improvements fo magic cards - nfc-mfclassic: add option to specify UID - nfc-mfclassic/nfc-mfsetuid: add support for new gen (1b) of magic 4K cards + - nfc-mfclassic: Add RATS support indicator - nfc-mfsetuid: allow to write complete Block0, instead of only UID - nfc-mfultralight: add automatic modes and --check-magic - nfc-mfultralight: add support for magic gen2 cards - nfc-mfultralight: add option to specify UID + - nfc-mfultralight: add support for Ultralight NTAG213/215/216 - nfc-barcode: new command to read and decode NFC Barcodes (Tag-Talks-First) - - Add RATS support indicator to nfc-mfclassic - - Adding pn71xx NXP's NFC Controllers through Linux Libnfc-nci - - Added driver for contactless PC/SC readers - - add Feitian R502 and bR500 support into pcsc driver - - Add HID iClass (Picopass) support (nfc-iclass tool in external nfc-tools) - 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 + - nfc_device_get_supported_baud_rate() takes now a "mode" parameter + - New nfc_device_get_supported_baud_rate_target_mode() + - New NFC modulation type NMT_BARCODE and nfc_barcode_info struct to support Thinfilm NFC Barcode protocol + - New NFC modulation type NMT_ISO14443BICLASS and NMT_ISO14443BICLASS struct to support HID iClass (Picopass) + - pn53x_transceive() is now part of public API Special thanks to: - Jim Anastassiou, Frédéric Bourgeois, Dario Carluccio, Emmanuel Dreyfus, diff --git a/NEWS.md b/NEWS.md index 0cf19947..93b395fe 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,12 +1,17 @@ -New in 1.7.x: +New in 1.7.2: + +Drivers: + + * New driver for pn71xx NXP's NFC Controllers through Linux Libnfc-nci (untested) + * New driver for contactless PC/SC readers (only as initiator) API Changes: * nfc_device_get_supported_baud_rate() now takes also "mode" as argument - * New nfc_get_supported_baud_rate_target_mode() - * added support for HID iClass (Picopass) (nfc-iclass tool can be found in external nfc-tools repo) - * added support for contacless PC/SC - * added support for Feitian R502 and bR500 PC/SC readers + * New nfc_device_get_supported_baud_rate_target_mode() + * New NFC modulation type NMT_BARCODE and nfc_barcode_info struct to support Thinfilm NFC Barcode protocol + * New NFC modulation type NMT_ISO14443BICLASS and NMT_ISO14443BICLASS struct to support HID iClass (Picopass) + * pn53x_transceive() is now part of public API New in 1.7.1: From 6b4f6249bd0d5c8834edf40bf4d93e9ae5711875 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 21 May 2020 14:27:13 +0200 Subject: [PATCH 259/318] rework README --- README.md | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 6fb33835..7a9bb447 100644 --- a/README.md +++ b/README.md @@ -143,20 +143,14 @@ all the information described in "How to Report Bugs". Building ======== -It should be as simple as running these three commands: +It should be as simple as running these two commands: - autoreconf -vis ./configure make -Build with specific driver, like pcsc driver for compatible readers, go with below commands, tested on linux and macOS: +To build with specific driver(s), see option `--with-drivers=...` detailed in `./configure --help`. -``` -git clone --recursive https://github.com/nfc-tools/libnfc -autoreconf -vis -./configure --with-drivers=pcsc -make -``` +Note: if you're using directly the development repository and not the release sources, you will have to execute firstly `autoreconf -vis`. Troubleshooting =============== @@ -207,27 +201,31 @@ them in a modprobe conf file. This file is provided within libnfc archive: sudo cp contrib/linux/blacklist-libnfc.conf /etc/modprobe.d/blacklist-libnfc.conf -## FEITIAN bR500 and R502: +FEITIAN bR500 and R502: +----------------------- -Libnfc can work with PCSC proprietary driver of bR500 and R502 through USB port, most linux already installed PCSC proprietary, then just plug in play, to have pcsc driver support, you may need build with "--with-drivers=pcsc" to re-build libnfc, below reader tested: +Libnfc can work with PCSC proprietary driver of bR500 and R502, which is already available on most Linux setups. +To activate the PCSC support: `./configure --with-drivers=pcsc`. +Readers known to work: - Feitian bR500 - Feitian R502 Dual interface reader - Feitian R502 CL(Contactless) reader -These reader support by CCID from 1.4.25, make sure your CCID driver version higher than 1.4.25. +These readers are support by CCID since v1.4.25, make sure your CCID driver version higher or equal to 1.4.25. -Using macOS, use below command check your version, to install latest CCID driver from [https://github.com/martinpaljak/osx-ccid-installer/releases](https://github.com/martinpaljak/osx-ccid-installer/releases) +On MacOS, you can check your CCID version with the following command, and if required, you can install latest CCID driver from [https://github.com/martinpaljak/osx-ccid-installer/releases](https://github.com/martinpaljak/osx-ccid-installer/releases) ``` grep -A 1 CFBundleShortVersionString /usr/local/libexec/SmartCardServices/drivers/ifd-ccid.bundle/Contents/Info.plist ``` -Using linux, use below command check your version, to install latest CCID driver from [https://ccid.apdu.fr/](https://ccid.apdu.fr/) +On Linux, you can check your CCID version with the following command, and if required, you can install latest CCID driver from [https://ccid.apdu.fr/](https://ccid.apdu.fr/) ``` grep -A 1 CFBundleShortVersionString /usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist ``` + Proprietary Notes ================= FeliCa is a registered trademark of the Sony Corporation. From 730f705c0d74398b2a22333d05421d4088a82c97 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 21 May 2020 14:42:31 +0200 Subject: [PATCH 260/318] pcsc.c: fix error and remove warnings --- libnfc/drivers/pcsc.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/libnfc/drivers/pcsc.c b/libnfc/drivers/pcsc.c index 19e419b7..09a4e62c 100644 --- a/libnfc/drivers/pcsc.c +++ b/libnfc/drivers/pcsc.c @@ -130,6 +130,8 @@ pcsc_free_scardcontext(void) #define ICC_TYPE_14443A 5 #define ICC_TYPE_14443B 6 +bool is_pcsc_reader_vendor_feitian(const struct nfc_device *pnd); + int pcsc_transmit(struct nfc_device *pnd, const uint8_t *tx, const size_t tx_len, uint8_t *rx, size_t *rx_len) { struct pcsc_data *data = pnd->driver_data; @@ -190,7 +192,7 @@ int pcsc_reconnect(struct nfc_device *pnd, DWORD share_mode, DWORD protocol, DWO return NFC_SUCCESS; } -uint8_t pcsc_get_icc_type(struct nfc_device *pnd) +uint8_t pcsc_get_icc_type(const struct nfc_device *pnd) { struct pcsc_data *data = pnd->driver_data; uint8_t it = 0; @@ -199,7 +201,7 @@ uint8_t pcsc_get_icc_type(struct nfc_device *pnd) return it; } -bool is_pcsc_reader_vendor(struct nfc_device *pnd, const char * target_vendor_name) +bool is_pcsc_reader_vendor(const struct nfc_device *pnd, const char * target_vendor_name) { bool isTarget = false; if (pnd == NULL || strlen(pnd->name) == 0) @@ -210,7 +212,7 @@ bool is_pcsc_reader_vendor(struct nfc_device *pnd, const char * target_vendor_na return isTarget = (strstr(pnd->name, target_vendor_name)) ? true:false; } -bool is_pcsc_reader_vendor_feitian(struct nfc_device *pnd) +bool is_pcsc_reader_vendor_feitian(const struct nfc_device *pnd) { return is_pcsc_reader_vendor(pnd, "Feitian") || is_pcsc_reader_vendor(pnd, "FeiTian") || is_pcsc_reader_vendor(pnd, "feitian") || is_pcsc_reader_vendor(pnd, "FEITIAN"); } @@ -319,7 +321,7 @@ int pcsc_get_uid(struct nfc_device *pnd, uint8_t *uid, size_t uid_len) return resp_len - 2; } -int pcsc_props_to_target(const struct nfc_device *pnd, uint8_t it, const uint8_t *patr, size_t szatr, const uint8_t *puid, int szuid, const nfc_modulation_type nmt, nfc_target *pnt) +int pcsc_props_to_target(struct nfc_device *pnd, uint8_t it, const uint8_t *patr, size_t szatr, const uint8_t *puid, int szuid, const nfc_modulation_type nmt, nfc_target *pnt) { if (NULL != pnt) { switch (nmt) { @@ -883,21 +885,10 @@ int pcsc_device_set_property_bool(struct nfc_device *pnd, const nfc_property pro // ignore return NFC_SUCCESS; case NP_AUTO_ISO14443_4: - { - if (is_pcsc_reader_vendor_feitian(pnd)) - { - //ignore - return NFC_SUCCESS; - } - } case NP_EASY_FRAMING: - { - if (is_pcsc_reader_vendor_feitian(pnd)) - { - //ignore + if ((bEnable == true) || (is_pcsc_reader_vendor_feitian(pnd))) return NFC_SUCCESS; - } - } + break; case NP_FORCE_ISO14443_A: case NP_HANDLE_CRC: case NP_HANDLE_PARITY: From 5a059db9016b26d779638e492cd82bb4c8cb6d13 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 21 May 2020 14:50:30 +0200 Subject: [PATCH 261/318] remove warnings --- libnfc/chips/pn53x.c | 6 ++++-- utils/nfc-mfclassic.c | 1 - 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 4dc2a154..90df2aba 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -2655,7 +2655,8 @@ pn53x_target_receive_bytes(struct nfc_device *pnd, uint8_t *pbtRx, const size_t return pnd->last_error; } } - // NO BREAK + abtCmd[0] = TgGetInitiatorCommand; + break; case NMT_JEWEL: case NMT_BARCODE: case NMT_ISO14443B: @@ -2762,7 +2763,8 @@ pn53x_target_send_bytes(struct nfc_device *pnd, const uint8_t *pbtTx, const size return pnd->last_error; } } - // NO BREAK + abtCmd[0] = TgResponseToInitiator; + break; case NMT_JEWEL: case NMT_BARCODE: case NMT_ISO14443B: diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 3b12cd8d..faa4dc54 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -73,7 +73,6 @@ 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, From f52d04e0a7659427f8ac51a97f7b84a2253b40f6 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 21 May 2020 15:05:48 +0200 Subject: [PATCH 262/318] remove warnings --- libnfc/drivers/acr122_usb.c | 5 ++++- libnfc/drivers/pn53x_usb.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libnfc/drivers/acr122_usb.c b/libnfc/drivers/acr122_usb.c index 4a88c61f..8620fe25 100644 --- a/libnfc/drivers/acr122_usb.c +++ b/libnfc/drivers/acr122_usb.c @@ -331,7 +331,10 @@ acr122_usb_scan(const nfc_context *context, nfc_connstring connstrings[], const // acr122_usb_get_usb_device_name (dev, udev, pnddDevices[device_found].acDevice, sizeof (pnddDevices[device_found].acDevice)); log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "device found: Bus %s Device %s Name %s", bus->dirname, dev->filename, acr122_usb_supported_devices[n].name); usb_close(udev); - snprintf(connstrings[device_found], sizeof(nfc_connstring), "%s:%s:%s", ACR122_USB_DRIVER_NAME, bus->dirname, dev->filename); + if(snprintf(connstrings[device_found], sizeof(nfc_connstring), "%s:%s:%s", ACR122_USB_DRIVER_NAME, bus->dirname, dev->filename) >= (int)sizeof(nfc_connstring)) { + // truncation occurred, skipping that one + continue; + } device_found++; // Test if we reach the maximum "wanted" devices if (device_found == connstrings_len) { diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index 56c6ebab..456fa6be 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -337,7 +337,10 @@ pn53x_usb_scan(const nfc_context *context, nfc_connstring connstrings[], const s // pn53x_usb_get_usb_device_name (dev, udev, pnddDevices[device_found].acDevice, sizeof (pnddDevices[device_found].acDevice)); log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "device found: Bus %s Device %s", bus->dirname, dev->filename); usb_close(udev); - snprintf(connstrings[device_found], sizeof(nfc_connstring), "%s:%s:%s", PN53X_USB_DRIVER_NAME, bus->dirname, dev->filename); + if(snprintf(connstrings[device_found], sizeof(nfc_connstring), "%s:%s:%s", PN53X_USB_DRIVER_NAME, bus->dirname, dev->filename) >= (int)sizeof(nfc_connstring)) { + // truncation occurred, skipping that one + continue; + } device_found++; // Test if we reach the maximum "wanted" devices if (device_found == connstrings_len) { From 4525cd1c32871e287500a384de283fb89d256738 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 21 May 2020 15:06:17 +0200 Subject: [PATCH 263/318] make style --- libnfc/chips/pn53x.c | 146 ++++---- libnfc/drivers/acr122_usb.c | 4 +- libnfc/drivers/pcsc.c | 46 +-- libnfc/drivers/pn53x_usb.c | 2 +- libnfc/drivers/pn71xx.c | 691 ++++++++++++++++++------------------ libnfc/nfc-internal.c | 6 +- libnfc/nfc.c | 5 +- utils/nfc-mfclassic.c | 77 ++-- utils/nfc-mfultralight.c | 18 +- 9 files changed, 490 insertions(+), 505 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 90df2aba..abf6682c 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -580,8 +580,8 @@ pn53x_decode_target_data(const uint8_t *pbtRawData, size_t szRawData, pn53x_type case NMT_ISO14443BICLASS: // Store the UID - for(uint8_t i= 0 ; i < 8 ; ++i) - pnti->nhi.abtUID[7 - i]= pbtRawData[i]; + for (uint8_t i = 0 ; i < 8 ; ++i) + pnti->nhi.abtUID[7 - i] = pbtRawData[i]; break; case NMT_ISO14443B2CT: @@ -1060,51 +1060,51 @@ pn53x_initiator_init(struct nfc_device *pnd) // iclass requires special modulation settings void pn53x_initiator_init_iclass_modulation(struct nfc_device *pnd) { - // send a bunch of low level commands reverse engineered from a working iClass reader - // original device was using a PN512 - // - // // TxModeReg - Defines the data rate and framing during transmission. - //// set bit 4 for target mode? - RxWaitRF Set to logic 1, the counter for RxWait starts only if an external RF field is detected in Target mode for NFCIP-1 or in Card Communication mode - //pn512_write_register(0x12, "\x03", 1, false); - pn53x_WriteRegister(pnd, PN53X_REG_CIU_TxMode, 0x03); - // - // // RxModeReg - Defines the data rate and framing during reception. - //pn512_write_register(0x13, "\x03", 1, false); - // addy changed to set bit 3 - RxNoErr (put data in fifo before flagging read end) - //pn512_write_register(0x13, "\x0B", 1, false); - pn53x_WriteRegister(pnd, PN53X_REG_CIU_RxMode, 0x0B); - - // ManualRCVReg - Allows manual fine tuning of the internal receiver. - //pn512_write_register(0x1d, "\x10", 1, false); - pn53x_WriteRegister(pnd, PN53X_REG_CIU_ManualRCV, 0x10); - - // RFCfgReg - Configures the receiver gain and RF level detector sensitivity. - //pn512_write_register(0x26, "\x70", 1, false); - pn53x_WriteRegister(pnd, PN53X_REG_CIU_RFCfg, 0x70); - - // GsNOffReg - Selects the conductance for the N-driver of the antenna driver pins TX1 and TX2 when the driver is switched off. - //pn512_write_register(0x23, "\x88", 1, false); - pn53x_WriteRegister(pnd, PN53X_REG_CIU_GsNOFF, 0x88); - - // GsNOnReg - Selects the conductance for the N-driver of the antenna driver pins TX1 and TX2 when the driver is switched on. - //pn512_write_register(0x27, "\xf8", 1, false); - pn53x_WriteRegister(pnd, PN53X_REG_CIU_GsNOn, 0xf8); - - // CWGsPReg - Defines the conductance of the P-driver during times of no modulation. - //pn512_write_register(0x28, "\x3f", 1, false); - pn53x_WriteRegister(pnd, PN53X_REG_CIU_CWGsP, 0x3f); - - // ModGsPReg - Defines the driver P-output conductance during modulation. - //pn512_write_register(0x29, "\x10", 1, false); - pn53x_WriteRegister(pnd, PN53X_REG_CIU_ModGsP, 0x10); - - // TReloadReg (MSB) - Describes the MSB of the 16-bit long timer reload value. - //pn512_write_register(0x2c, "\x69", 1, false); - pn53x_WriteRegister(pnd, PN53X_REG_CIU_TReloadVal_hi, 0x69); - - // TReloadReg (LSB) - Describes the LSB of the 16-bit long timer reload value. - //pn512_write_register(0x2d, "\xf0", 1, false); - pn53x_WriteRegister(pnd, PN53X_REG_CIU_TReloadVal_lo, 0xf0); + // send a bunch of low level commands reverse engineered from a working iClass reader + // original device was using a PN512 + // + // // TxModeReg - Defines the data rate and framing during transmission. + //// set bit 4 for target mode? - RxWaitRF Set to logic 1, the counter for RxWait starts only if an external RF field is detected in Target mode for NFCIP-1 or in Card Communication mode + //pn512_write_register(0x12, "\x03", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_TxMode, 0x03); + // + // // RxModeReg - Defines the data rate and framing during reception. + //pn512_write_register(0x13, "\x03", 1, false); + // addy changed to set bit 3 - RxNoErr (put data in fifo before flagging read end) + //pn512_write_register(0x13, "\x0B", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_RxMode, 0x0B); + + // ManualRCVReg - Allows manual fine tuning of the internal receiver. + //pn512_write_register(0x1d, "\x10", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_ManualRCV, 0x10); + + // RFCfgReg - Configures the receiver gain and RF level detector sensitivity. + //pn512_write_register(0x26, "\x70", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_RFCfg, 0x70); + + // GsNOffReg - Selects the conductance for the N-driver of the antenna driver pins TX1 and TX2 when the driver is switched off. + //pn512_write_register(0x23, "\x88", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_GsNOFF, 0x88); + + // GsNOnReg - Selects the conductance for the N-driver of the antenna driver pins TX1 and TX2 when the driver is switched on. + //pn512_write_register(0x27, "\xf8", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_GsNOn, 0xf8); + + // CWGsPReg - Defines the conductance of the P-driver during times of no modulation. + //pn512_write_register(0x28, "\x3f", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_CWGsP, 0x3f); + + // ModGsPReg - Defines the driver P-output conductance during modulation. + //pn512_write_register(0x29, "\x10", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_ModGsP, 0x10); + + // TReloadReg (MSB) - Describes the MSB of the 16-bit long timer reload value. + //pn512_write_register(0x2c, "\x69", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_TReloadVal_hi, 0x69); + + // TReloadReg (LSB) - Describes the LSB of the 16-bit long timer reload value. + //pn512_write_register(0x2d, "\xf0", 1, false); + pn53x_WriteRegister(pnd, PN53X_REG_CIU_TReloadVal_lo, 0xf0); } int @@ -1202,10 +1202,10 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, } szTargetsData = 6; // u16 UID_LSB, u8 prod code, u8 fab code, u16 UID_MSB } else if (nm.nmt == NMT_ISO14443BICLASS) { - pn53x_initiator_init_iclass_modulation(pnd); - // + pn53x_initiator_init_iclass_modulation(pnd); + // // Some work to do before getting the UID... - // send ICLASS_ACTIVATE_ALL command - will get timeout as we don't expect response + // send ICLASS_ACTIVATE_ALL command - will get timeout as we don't expect response uint8_t abtReqt[] = { 0x0a }; // iClass ACTIVATE_ALL uint8_t abtAnticol[11]; if ((res = pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), NULL, 0, timeout)) < 0) { @@ -1214,35 +1214,35 @@ pn53x_initiator_select_passive_target_ext(struct nfc_device *pnd, // continue; //} else // return res; - } - // do select - returned anticol contains 'handle' for tag if present - abtReqt[0]= 0x0c; // iClass SELECT - abtAnticol[0]= 0x81; // iClass ANTICOL + } + // do select - returned anticol contains 'handle' for tag if present + abtReqt[0] = 0x0c; // iClass SELECT + abtAnticol[0] = 0x81; // iClass ANTICOL if ((res = pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), &abtAnticol[1], sizeof(abtAnticol) - 1, timeout)) < 0) { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "timeout on iClass anticol"); return res; - } - // write back anticol handle to get UID + } + // write back anticol handle to get UID if ((res = pn53x_initiator_transceive_bytes(pnd, abtAnticol, 9, abtTargetsData, 10, timeout)) < 0) { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "timeout on iClass get UID"); return res; - } + } log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "iClass raw UID: %02x %02x %02x %02x %02x %02x %02x %02x", abtTargetsData[0], abtTargetsData[1], abtTargetsData[2], abtTargetsData[3], abtTargetsData[4], abtTargetsData[5], abtTargetsData[6], abtTargetsData[7]); - szTargetsData = 8; - nttmp.nm = nm; - if ((res = pn53x_decode_target_data(abtTargetsData, szTargetsData, CHIP_DATA(pnd)->type, nm.nmt, &(nttmp.nti))) < 0) { - return res; - } - } else { - - if ((res = pn53x_initiator_transceive_bytes(pnd, pbtInitData, szInitData, abtTargetsData, sizeof(abtTargetsData), timeout)) < 0) { - if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout - continue; - } else + szTargetsData = 8; + nttmp.nm = nm; + if ((res = pn53x_decode_target_data(abtTargetsData, szTargetsData, CHIP_DATA(pnd)->type, nm.nmt, &(nttmp.nti))) < 0) { return res; + } + } else { + + if ((res = pn53x_initiator_transceive_bytes(pnd, pbtInitData, szInitData, abtTargetsData, sizeof(abtTargetsData), timeout)) < 0) { + if ((res == NFC_ERFTRANS) && (CHIP_DATA(pnd)->last_status_byte == 0x01)) { // Chip timeout + continue; + } else + return res; + } + szTargetsData = (size_t)res; } - szTargetsData = (size_t)res; - } nttmp.nm = nm; if ((res = pn53x_decode_target_data(abtTargetsData, szTargetsData, CHIP_DATA(pnd)->type, nm.nmt, &(nttmp.nti))) < 0) { @@ -2249,7 +2249,7 @@ static int pn53x_ISO14443B_SR_is_present(struct nfc_device *pnd) static int pn53x_ISO14443B_ICLASS_is_present(struct nfc_device *pnd) { - int timeout= 300; + int timeout = 300; log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "target_is_present(): Ping B iClass"); pn53x_initiator_init_iclass_modulation(pnd); // @@ -2261,8 +2261,8 @@ static int pn53x_ISO14443B_ICLASS_is_present(struct nfc_device *pnd) log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "got expected timeout on iClass activate all"); } // do select - returned anticol contains 'handle' for tag if present - abtReqt[0]= 0x0c; // iClass SELECT - abtAnticol[0]= 0x81; // iClass ANTICOL + abtReqt[0] = 0x0c; // iClass SELECT + abtAnticol[0] = 0x81; // iClass ANTICOL if (pn53x_initiator_transceive_bytes(pnd, abtReqt, sizeof(abtReqt), &abtAnticol[1], sizeof(abtAnticol) - 1, timeout) < 0) { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "timeout on iClass anticol"); return NFC_ETGRELEASED;; diff --git a/libnfc/drivers/acr122_usb.c b/libnfc/drivers/acr122_usb.c index 8620fe25..b42af0e3 100644 --- a/libnfc/drivers/acr122_usb.c +++ b/libnfc/drivers/acr122_usb.c @@ -331,7 +331,7 @@ acr122_usb_scan(const nfc_context *context, nfc_connstring connstrings[], const // acr122_usb_get_usb_device_name (dev, udev, pnddDevices[device_found].acDevice, sizeof (pnddDevices[device_found].acDevice)); log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "device found: Bus %s Device %s Name %s", bus->dirname, dev->filename, acr122_usb_supported_devices[n].name); usb_close(udev); - if(snprintf(connstrings[device_found], sizeof(nfc_connstring), "%s:%s:%s", ACR122_USB_DRIVER_NAME, bus->dirname, dev->filename) >= (int)sizeof(nfc_connstring)) { + if (snprintf(connstrings[device_found], sizeof(nfc_connstring), "%s:%s:%s", ACR122_USB_DRIVER_NAME, bus->dirname, dev->filename) >= (int)sizeof(nfc_connstring)) { // truncation occurred, skipping that one continue; } @@ -430,7 +430,7 @@ acr122_usb_open(const nfc_context *context, const nfc_connstring connstring) goto free_mem; } - // Check if there are more than 0 alternative interfaces and claim the first one + // Check if there are more than 0 alternative interfaces and claim the first one if (dev->config->interface->altsetting->bAlternateSetting > 0) { res = usb_set_altinterface(data.pudh, 0); if (res < 0) { diff --git a/libnfc/drivers/pcsc.c b/libnfc/drivers/pcsc.c index 09a4e62c..231f869c 100644 --- a/libnfc/drivers/pcsc.c +++ b/libnfc/drivers/pcsc.c @@ -138,8 +138,7 @@ int pcsc_transmit(struct nfc_device *pnd, const uint8_t *tx, const size_t tx_len DWORD dw_rx_len = *rx_len; //in libfreefare, tx_len = 1, and it leads to 0x80100008 error, with PC/SC reader, the input tx_len at least two bytes for the SW value //so if found the reader is Feitian reader, we set to 2 - if (dw_rx_len == 1 && is_pcsc_reader_vendor_feitian(pnd)) - { + if (dw_rx_len == 1 && is_pcsc_reader_vendor_feitian(pnd)) { dw_rx_len = 2; } @@ -201,15 +200,14 @@ uint8_t pcsc_get_icc_type(const struct nfc_device *pnd) return it; } -bool is_pcsc_reader_vendor(const struct nfc_device *pnd, const char * target_vendor_name) +bool is_pcsc_reader_vendor(const struct nfc_device *pnd, const char *target_vendor_name) { bool isTarget = false; - if (pnd == NULL || strlen(pnd->name) == 0) - { + if (pnd == NULL || strlen(pnd->name) == 0) { return isTarget; } - return isTarget = (strstr(pnd->name, target_vendor_name)) ? true:false; + return isTarget = (strstr(pnd->name, target_vendor_name)) ? true : false; } bool is_pcsc_reader_vendor_feitian(const struct nfc_device *pnd) @@ -340,15 +338,14 @@ int pcsc_props_to_target(struct nfc_device *pnd, uint8_t it, const uint8_t *patr memcpy(pnt->nti.nai.abtUid, puid, szuid); pnt->nti.nai.szUidLen = szuid; } - if (is_pcsc_reader_vendor_feitian(pnd)) - { + if (is_pcsc_reader_vendor_feitian(pnd)) { uint8_t atqa[2]; - pcsc_get_atqa(pnd,atqa,sizeof(atqa)); + pcsc_get_atqa(pnd, atqa, sizeof(atqa)); //memcpy(pnt->nti.nai.abtAtqa,atqa,2); pnt->nti.nai.abtAtqa[0] = atqa[1]; pnt->nti.nai.abtAtqa[1] = atqa[0]; uint8_t sak[1]; - pcsc_get_sak(pnd,sak,sizeof(sak)); + pcsc_get_sak(pnd, sak, sizeof(sak)); pnt->nti.nai.btSak = sak[0]; uint8_t ats[256]; int ats_len = pcsc_get_ats(pnd, ats, sizeof(ats)); @@ -776,7 +773,7 @@ int pcsc_initiator_transceive_bytes(struct nfc_device *pnd, const uint8_t *pbtTx // FIXME: timeout is not handled (void) timeout; - if (is_pcsc_reader_vendor_feitian(pnd)){ + if (is_pcsc_reader_vendor_feitian(pnd)) { LOG_HEX(NFC_LOG_GROUP_COM, "not feitian reader pcsc apdu send", pbtTx, szTx); uint8_t apdu_data[256]; @@ -797,7 +794,7 @@ int pcsc_initiator_transceive_bytes(struct nfc_device *pnd, const uint8_t *pbtTx apdu_data[4] = szTx - 2; memcpy(apdu_data + 5, pbtTx + 2, szTx - 2); send_size = 5 + szTx - 2; - } else if (pbtTx[0] == 0x60 || pbtTx[0] == 0x61 || pbtTx[0] == 0x1A){//Auth command + } else if (pbtTx[0] == 0x60 || pbtTx[0] == 0x61 || pbtTx[0] == 0x1A) { //Auth command apdu_data[0] = 0xFF; apdu_data[1] = 0x86; apdu_data[2] = 0x00; @@ -809,7 +806,7 @@ int pcsc_initiator_transceive_bytes(struct nfc_device *pnd, const uint8_t *pbtTx apdu_data[8] = pbtTx[0];//type a or type b apdu_data[9] = 0x01; send_size = 10; - } else if (pbtTx[0] == 0xC0){//DECREMENT cmd + } else if (pbtTx[0] == 0xC0) { //DECREMENT cmd apdu_data[0] = 0xFF; apdu_data[1] = 0xD7; apdu_data[2] = 0x00; @@ -817,7 +814,7 @@ int pcsc_initiator_transceive_bytes(struct nfc_device *pnd, const uint8_t *pbtTx apdu_data[4] = 0x05; memcpy(apdu_data + 5, pbtTx + 2, szTx - 2); send_size = 5 + szTx - 2; - } else if (pbtTx[0] == 0xC1){//INCREMENT cmd + } else if (pbtTx[0] == 0xC1) { //INCREMENT cmd apdu_data[0] = 0xFF; apdu_data[1] = 0xD7; apdu_data[2] = 0x00; @@ -825,7 +822,7 @@ int pcsc_initiator_transceive_bytes(struct nfc_device *pnd, const uint8_t *pbtTx apdu_data[4] = 0x05; memcpy(apdu_data + 5, pbtTx + 2, szTx - 2); send_size = 5 + szTx - 2; - } else if (pbtTx[0] == 0xC2){//STORE cmd + } else if (pbtTx[0] == 0xC2) { //STORE cmd apdu_data[0] = 0xFF; apdu_data[1] = 0xD8; apdu_data[2] = 0x00; @@ -840,7 +837,7 @@ int pcsc_initiator_transceive_bytes(struct nfc_device *pnd, const uint8_t *pbtTx LOG_HEX(NFC_LOG_GROUP_COM, "feitian reader pcsc apdu send:", apdu_data, send_size); pnd->last_error = pcsc_transmit(pnd, apdu_data, send_size, resp, &resp_len); LOG_HEX(NFC_LOG_GROUP_COM, "feitian reader pcsc apdu received:", resp, resp_len); - + memcpy(pbtRx, resp, resp_len); } else { pnd->last_error = pcsc_transmit(pnd, pbtTx, szTx, pbtRx, &resp_len); @@ -938,7 +935,7 @@ pcsc_get_information_about(nfc_device *pnd, char **pbuf) struct pcsc_data *data = pnd->driver_data; LPBYTE name = NULL, version = NULL, type = NULL, serial = NULL; DWORD name_len = SCARD_AUTOALLOCATE, version_len = SCARD_AUTOALLOCATE, - type_len = SCARD_AUTOALLOCATE, serial_len = SCARD_AUTOALLOCATE; + type_len = SCARD_AUTOALLOCATE, serial_len = SCARD_AUTOALLOCATE; int res = NFC_SUCCESS; SCARDCONTEXT *pscc; @@ -974,27 +971,22 @@ pcsc_get_information_about(nfc_device *pnd, char **pbuf) error: #ifdef __APPLE__ - if (pscc != NULL) - { + if (pscc != NULL) { SCardReleaseContext(*pscc); } - if (name != NULL) - { + if (name != NULL) { free(name); name = NULL; } - if (type != NULL) - { + if (type != NULL) { free(type); type = NULL; } - if (version != NULL) - { + if (version != NULL) { free(version); version = NULL; } - if (serial != NULL) - { + if (serial != NULL) { free(serial); serial = NULL; } diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index 456fa6be..d1796663 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -337,7 +337,7 @@ pn53x_usb_scan(const nfc_context *context, nfc_connstring connstrings[], const s // pn53x_usb_get_usb_device_name (dev, udev, pnddDevices[device_found].acDevice, sizeof (pnddDevices[device_found].acDevice)); log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "device found: Bus %s Device %s", bus->dirname, dev->filename); usb_close(udev); - if(snprintf(connstrings[device_found], sizeof(nfc_connstring), "%s:%s:%s", PN53X_USB_DRIVER_NAME, bus->dirname, dev->filename) >= (int)sizeof(nfc_connstring)) { + if (snprintf(connstrings[device_found], sizeof(nfc_connstring), "%s:%s:%s", PN53X_USB_DRIVER_NAME, bus->dirname, dev->filename) >= (int)sizeof(nfc_connstring)) { // truncation occurred, skipping that one continue; } diff --git a/libnfc/drivers/pn71xx.c b/libnfc/drivers/pn71xx.c index 82459081..39e722db 100644 --- a/libnfc/drivers/pn71xx.c +++ b/libnfc/drivers/pn71xx.c @@ -58,16 +58,16 @@ static void onTagDeparture(void); static size_t pn71xx_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len) { - size_t device_found = 0; + size_t device_found = 0; - if ((context == NULL) || (connstrings_len == 0)) return 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)); - } + if (nfcManager_doInitialize() == 0) { + nfc_connstring connstring = "pn71xx"; + memcpy(connstrings[device_found++], connstring, sizeof(nfc_connstring)); + } - return device_found; + return device_found; } /** @@ -77,12 +77,12 @@ pn71xx_scan(const nfc_context *context, nfc_connstring connstrings[], const size */ static void pn71xx_close(nfc_device *pnd) -{ - nfcManager_disableDiscovery(); - nfcManager_deregisterTagCallback(); - nfcManager_doDeinitialize(); - nfc_device_free(pnd); - pnd = NULL; +{ + nfcManager_disableDiscovery(); + nfcManager_deregisterTagCallback(); + nfcManager_doDeinitialize(); + nfc_device_free(pnd); + pnd = NULL; } /** @@ -95,157 +95,150 @@ pn71xx_close(nfc_device *pnd) 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); + 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 = nfc_device_new(context, connstring); + if (!pnd) { + perror("malloc"); + return NULL; + } - pnd->driver = &pn71xx_driver; - strcpy(pnd->name, "pn71xx-device"); - strcpy(pnd->connstring, connstring); + pnd->driver = &pn71xx_driver; + strcpy(pnd->name, "pn71xx-device"); + strcpy(pnd->connstring, connstring); - TagCB.onTagArrival = onTagArrival; - TagCB.onTagDeparture = onTagDeparture; - nfcManager_registerTagCallback(&TagCB); + TagCB.onTagArrival = onTagArrival; + TagCB.onTagDeparture = onTagDeparture; + nfcManager_registerTagCallback(&TagCB); - nfcManager_enableDiscovery(DEFAULT_NFA_TECH_MASK, 1, 0, 0); + 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); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "wait 1 seconds for polling"); + sleep(1); - return pnd; + 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; + 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) +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]); - } + 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) +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); - } + 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); + } } /** ------------------------------------------------------------------------ */ @@ -253,194 +246,194 @@ static void PrintTagInfo (nfc_tag_info_t *TagInfo) static void onTagArrival(nfc_tag_info_t *pTagInfo) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "tag found"); + 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)); + TagInfo = malloc(sizeof(nfc_tag_info_t)); + memcpy(TagInfo, pTagInfo, sizeof(nfc_tag_info_t)); - PrintTagInfo(TagInfo); + PrintTagInfo(TagInfo); } static void onTagDeparture(void) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "tag lost"); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "tag lost"); - free(TagInfo); - TagInfo = NULL; + free(TagInfo); + TagInfo = NULL; } static int pn71xx_initiator_init(struct nfc_device *pnd) { - if (pnd == NULL) return NFC_EIO; - return NFC_SUCCESS; + if (pnd == NULL) return NFC_EIO; + 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) + const nfc_modulation nm, + 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) { - - nfc_target nttmp; - memset(&nttmp, 0x00, sizeof(nfc_target)); - nttmp.nm = nm; - - void* uidPtr = NULL; - unsigned 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; + if (pnd == NULL) return NFC_EIO; + + 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; + unsigned 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) { - if (pnd == NULL) return NFC_EIO; - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "deselect_passive_target"); - return NFC_SUCCESS; + if (pnd == NULL) return NFC_EIO; + 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) + 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 (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); - 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, (uint8_t *) pbtTx, szTx, pbtRx, szRx, 500); + if (received <= 0) + return NFC_EIO; - int received = nfcTag_transceive(TagInfo->handle, (uint8_t *) 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); - BufferPrintBytes(buffer, sizeof(buffer), pbtRx, received); - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "<=== %s", buffer); - - return received; + 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) + 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; - - if (pnd == NULL) return 0; - - for (int j = 0; j < uiPollNr; j++) { - for (unsigned int i = 0; i < szModulations; i++) { - const nfc_modulation nm = pnmModulations[i]; - - 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 periodFactor = 150000; + int period = uiPeriod * periodFactor; + + if (pnd == NULL) return 0; + + for (int j = 0; j < uiPollNr; j++) { + for (unsigned int i = 0; i < szModulations; i++) { + const nfc_modulation nm = pnmModulations[i]; + + 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 ((pnd == NULL) || (pnt == NULL)) return 1; - return !TagInfo; + if ((pnd == NULL) || (pnt == NULL)) return 1; + return !TagInfo; } @@ -449,17 +442,17 @@ pn71xx_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt static int pn71xx_get_supported_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type **const supported_mt) { - 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; + 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; } @@ -467,32 +460,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) { - 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; + 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; } /** ------------------------------------------------------------------------ */ @@ -501,29 +494,29 @@ 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) { - if (pnd == NULL) return NFC_EIO; - return NFC_SUCCESS; + 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) { - if (pnd == NULL) return NFC_EIO; - return NFC_SUCCESS; + if (pnd == NULL) return NFC_EIO; + 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; + static const char *info = "PN71XX nfc driver using libnfc-nci userspace library"; + size_t buflen = strlen(info) + 1; + + if (pnd == NULL) return NFC_EIO; - if (pnd == NULL) return NFC_EIO; - - *pbuf = malloc(buflen); - memcpy(*pbuf, info, buflen); + *pbuf = malloc(buflen); + memcpy(*pbuf, info, buflen); - return buflen; + return buflen; } /** * @brief Abort any pending operation @@ -534,25 +527,25 @@ 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; + if (pnd == NULL) return NFC_EIO; + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "abort_command"); + 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; + if (pnd == NULL) return NFC_EIO; + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "idle"); + 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; + if (pnd == NULL) return NFC_EIO; + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "PowerDown"); + return NFC_SUCCESS; } /** ------------------------------------------------------------------------ */ diff --git a/libnfc/nfc-internal.c b/libnfc/nfc-internal.c index b57b97cb..7ed834d2 100644 --- a/libnfc/nfc-internal.c +++ b/libnfc/nfc-internal.c @@ -174,17 +174,17 @@ prepare_initiator_data(const nfc_modulation nm, uint8_t **ppbtInitiatorData, siz // Application Family Identifier (AFI) must equals 0x00 in order to wakeup all ISO14443-B PICCs (see ISO/IEC 14443-3) *ppbtInitiatorData = (uint8_t *) "\x00"; *pszInitiatorData = 1; - break; + break; case NMT_ISO14443BI: // APGEN *ppbtInitiatorData = (uint8_t *) "\x01\x0b\x3f\x80"; *pszInitiatorData = 4; - break; + break; case NMT_FELICA: // polling payload must be present (see ISO/IEC 18092 11.2.2.5) *ppbtInitiatorData = (uint8_t *) "\x00\xff\xff\x01\x00"; *pszInitiatorData = 5; - break; + break; case NMT_ISO14443A: case NMT_ISO14443B2CT: case NMT_ISO14443B2SR: diff --git a/libnfc/nfc.c b/libnfc/nfc.c index 8c12578e..2d56bf60 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -140,7 +140,7 @@ struct nfc_driver_list { const struct nfc_driver_list *nfc_drivers = NULL; // descritions for debugging -const char * nfc_property_name[] = { +const char *nfc_property_name[] = { "NP_TIMEOUT_COMMAND", "NP_TIMEOUT_ATR", "NP_TIMEOUT_COM", @@ -206,8 +206,7 @@ nfc_device_validate_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_m int nfc_register_driver(const struct nfc_driver *ndr) { - if (!ndr) - { + if (!ndr) { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "nfc_register_driver returning NFC_EINVARG"); return NFC_EINVARG; } diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index faa4dc54..9c4cb2e8 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -10,7 +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 + * 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: @@ -218,9 +218,9 @@ authenticate(uint32_t uiBlock) // Try to authenticate for the current sector if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) { - return true; + return true; } - // If formatting or not using key file, try to guess the right key + // If formatting or not using key file, try to guess the right key } 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); @@ -494,7 +494,7 @@ write_card(int write_block_zero) bFailure = true; printf("Failure to write to data block %i\n", uiBlock); } - + } else { printf("Failure during write process.\n"); } @@ -510,19 +510,19 @@ write_card(int write_block_zero) if (write_block_zero || magic2 || magic3) { for (uiBlock = 0; uiBlock < 4; uiBlock++) { - // The first block 0x00 is read only, skip this + // The first block 0x00 is read only, skip this if (uiBlock == 0) { - //If the card is not magic, we're gonna skip over + //If the card is not magic, we're gonna skip over if (write_block_zero || magic2 || magic3) { - //NOP + //NOP } else { continue; } - } + } if (is_first_block(uiBlock)) { if (bFailure) { - // When a failure occured we need to redo the anti-collision + // 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; @@ -530,27 +530,27 @@ write_card(int write_block_zero) 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 + 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; - } - } + } + } } - // 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"); @@ -562,15 +562,15 @@ write_card(int write_block_zero) 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 + // Show if the write went well for each block print_success_or_failure(bFailure, &uiWriteBlocks); if ((! bTolerateFailures) && bFailure) - return false; + return false; } @@ -620,7 +620,8 @@ print_usage(const char *pcProgramName) } -bool is_directwrite(){ +bool is_directwrite() +{ printf("Checking if Badge is DirectWrite...\n"); // Set default keys @@ -629,28 +630,28 @@ bool is_directwrite(){ memcpy(mtDump.amb[0].mbt.abtKeyB, default_key, sizeof(default_key)); // Temporarly override bUseKeyFile - bool orig_bUseKeyFile=bUseKeyFile; - bUseKeyFile=false; + 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; + bUseKeyFile = orig_bUseKeyFile; return false; } // restore bUseKeyFile - bUseKeyFile=orig_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++){ + 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]); + 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; @@ -845,22 +846,22 @@ main(int argc, const char *argv[]) } } else printf("RATS support: no\n"); - printf("Guessing size: seems to be a %lu-byte card\n", (unsigned long) ((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 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"); - } + 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) { + pbtUID[2] == 0xc3 && pbtUID[3] == 0x96) { printf("Card appears to be a One Time Write Card..\n"); magic3 = true; unlock = 0; diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index d115fec0..b954c0e2 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -300,12 +300,12 @@ static bool check_magic(void) if (nfc_initiator_mifare_cmd(pnd, MC_READ, 0, &mp)) { memcpy(original_b0, mp.mpd.abtData, 12); printf(" Original Block 0 (Pages 0-2): "); - for(int i=0;i<12;i++){ + for (int i = 0; i < 12; i++) { printf("%02x", original_b0[i]); } 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]); + 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; @@ -313,8 +313,8 @@ static bool check_magic(void) 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++){ + memcpy(mp.mpd.abtData, original_b0 + page * 4, 4); + for (int i = 0; i < 4; i++) { printf(" %02x", mp.mpd.abtData[i]); } printf("\n"); @@ -324,7 +324,7 @@ static bool check_magic(void) break; } } - if(directWrite){ + if (directWrite) { printf(" Block 0 written successfully\n"); printf("Card is DirectWrite\n"); return true; @@ -407,9 +407,9 @@ write_card(bool write_otp, bool write_lock, bool write_dyn_lock, bool write_uid) } // NTAG and MF0UL21 have Dynamic Lock Bytes if (((iEV1Type == EV1_UL21 && page == 0x24) || \ - (iNTAGType == NTAG_213 && page == 0x28) || \ - (iNTAGType == NTAG_215 && page == 0x82) || \ - (iNTAGType == NTAG_216 && page == 0xe2)) && (!write_dyn_lock)) { + (iNTAGType == NTAG_213 && page == 0x28) || \ + (iNTAGType == NTAG_215 && page == 0x82) || \ + (iNTAGType == NTAG_216 && page == 0xe2)) && (!write_dyn_lock)) { printf("s"); uiSkippedPages++; continue; @@ -655,7 +655,7 @@ main(int argc, const char *argv[]) iEV1Type = EV1_UL11; } else if (abtRx[6] == 0x0e) { printf("EV1 type: MF0UL21 (128 user bytes)\n"); - uiBlocks = 41; + uiBlocks = 41; iDumpSize = uiBlocks * 4; iEV1Type = EV1_UL21; } else if (abtRx[6] == 0x0f) { From 91d7c5d32f2d6ed070167059d7162cb5fda39b4e Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Fri, 22 May 2020 09:50:26 +0200 Subject: [PATCH 264/318] Fix compiler warning: old-style function definition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nfc-mfclassic.c:623:6: warning: function declaration isn’t a prototype [-Wstrict-prototypes] bool is_directwrite() ^~~~~~~~~~~~~~ nfc-mfclassic.c: In function ‘is_directwrite’: nfc-mfclassic.c:623:6: warning: old-style function definition [-Wold-style-definition] --- utils/nfc-mfclassic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 9c4cb2e8..e019ddc2 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -620,7 +620,7 @@ print_usage(const char *pcProgramName) } -bool is_directwrite() +bool is_directwrite(void) { printf("Checking if Badge is DirectWrite...\n"); From c8692aa2396ad4e5ff986c4f7d551a89feed9f1b Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Fri, 22 May 2020 09:51:14 +0200 Subject: [PATCH 265/318] Fix compiler warning: no previous prototype MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nfc-mfclassic.c:623:6: warning: no previous prototype for ‘is_directwrite’ [-Wmissing-prototypes] bool is_directwrite(void) ^~~~~~~~~~~~~~ --- utils/nfc-mfclassic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index e019ddc2..6530224b 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -620,7 +620,7 @@ print_usage(const char *pcProgramName) } -bool is_directwrite(void) +static bool is_directwrite(void) { printf("Checking if Badge is DirectWrite...\n"); From 357ae384af07248b6017d664b2f213af73e3636a Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Fri, 22 May 2020 09:58:44 +0200 Subject: [PATCH 266/318] Doxygen: update Doxyfile.in to version 1.8.13 Fix warnings: warning: Tag `SYMBOL_CACHE_SIZE' at line 299 of file `./Doxyfile' has become obsolete. To avoid this warning please remove this line from your configuration file or upgrade it using "doxygen -u" warning: Tag `SHOW_DIRECTORIES' at line 487 of file `./Doxyfile' has become obsolete. To avoid this warning please remove this line from your configuration file or upgrade it using "doxygen -u" warning: Tag `HTML_ALIGN_MEMBERS' at line 823 of file `./Doxyfile' has become obsolete. To avoid this warning please remove this line from your configuration file or upgrade it using "doxygen -u" warning: Tag `USE_INLINE_TREES' at line 976 of file `./Doxyfile' has become obsolete. To avoid this warning please remove this line from your configuration file or upgrade it using "doxygen -u" warning: Tag `XML_SCHEMA' at line 1169 of file `./Doxyfile' has become obsolete. To avoid this warning please remove this line from your configuration file or upgrade it using "doxygen -u" warning: Tag `XML_DTD' at line 1175 of file `./Doxyfile' has become obsolete. To avoid this warning please remove this line from your configuration file or upgrade it using "doxygen -u" --- Doxyfile.in | 2476 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 1703 insertions(+), 773 deletions(-) diff --git a/Doxyfile.in b/Doxyfile.in index 75eba0f9..84d5bfc4 100644 --- a/Doxyfile.in +++ b/Doxyfile.in @@ -1,90 +1,122 @@ -# Doxyfile 1.6.1 +# Doxyfile 1.8.13 # This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project +# doxygen (www.doxygen.org) for a project. # -# All text after a hash (#) is considered a comment and will be ignored +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. # The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. PROJECT_NAME = libnfc -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. PROJECT_NUMBER = @VERSION@ -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. OUTPUT_DIRECTORY = @builddir@/doc -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. CREATE_SUBDIRS = NO +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. OUTPUT_LANGUAGE = English -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. BRIEF_MEMBER_DESC = YES -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. +# The default value is: YES. REPEAT_BRIEF = YES -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ @@ -99,8 +131,9 @@ ABBREVIATE_BRIEF = "The $name class" \ the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief +# doxygen will generate a detailed section even if there is only a brief # description. +# The default value is: NO. ALWAYS_DETAILED_SEC = NO @@ -108,506 +141,699 @@ ALWAYS_DETAILED_SEC = NO # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. +# The default value is: NO. INLINE_INHERITED_MEMB = NO -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. FULL_PATH_NAMES = NO -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. STRIP_FROM_INC_PATH = -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. SHORT_NAMES = NO -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. JAVADOC_AUTOBRIEF = NO -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. QT_AUTOBRIEF = NO -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. INHERIT_DOCS = YES -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. SEPARATE_MEMBER_PAGES = NO -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 2 -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. ALIASES = -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = YES -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO -# Doxygen selects the parser to use depending on the extension of the files it parses. -# With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this tag. -# The format is ext=language, where ext is a file extension, and language is one of -# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, -# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat -# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), -# use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. EXTENSION_MAPPING = +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 0. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 0 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also make the inheritance and collaboration +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. +# The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. +# The default value is: NO. CPP_CLI_SUPPORT = NO -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. SIP_SUPPORT = NO -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen to replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first +# tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. +# The default value is: NO. DISTRIBUTE_GROUP_DOC = NO -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. SUBGROUPING = YES -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. TYPEDEF_HIDES_STRUCT = NO -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penality. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will rougly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols - -SYMBOL_CACHE_SIZE = 0 +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. EXTRACT_ALL = NO -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. EXTRACT_PRIVATE = NO -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. EXTRACT_STATIC = YES -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. EXTRACT_LOCAL_CLASSES = YES -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespace are hidden. +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. EXTRACT_ANON_NSPACES = NO -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. HIDE_UNDOC_MEMBERS = YES -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. HIDE_UNDOC_CLASSES = YES -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. HIDE_FRIEND_COMPOUNDS = YES -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. HIDE_IN_BODY_DOCS = NO -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. INTERNAL_DOCS = NO -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. +# The default value is: system dependent. CASE_SENSE_NAMES = YES -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. HIDE_SCOPE_NAMES = NO -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. SHOW_INCLUDE_FILES = YES -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. INLINE_INFO = YES -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. SORT_MEMBER_DOCS = YES -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. SORT_BRIEF_DOCS = NO -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. SORT_GROUP_NAMES = NO -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. SORT_BY_SCOPE_NAME = NO -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. GENERATE_TODOLIST = YES -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. GENERATE_TESTLIST = YES -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. GENERATE_BUGLIST = YES -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. GENERATE_DEPRECATEDLIST= YES -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. ENABLED_SECTIONS = -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the # list will mention the files that were used to generate the documentation. +# The default value is: YES. SHOW_USED_FILES = YES -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = YES - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. SHOW_FILES = YES -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. FILE_VERSION_FILTER = -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by -# doxygen. The layout file controls the global structure of the generated output files -# in an output format independent way. The create the layout file that represents -# doxygen's defaults, run doxygen with the -l option. You can optionally specify a -# file name after the option, if omitted DoxygenLayout.xml will be used as the name -# of the layout file. +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. LAYOUT_FILE = +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + #--------------------------------------------------------------------------- -# configuration options related to warning and progress messages +# Configuration options related to warning and progress messages #--------------------------------------------------------------------------- -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. WARNINGS = YES -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. WARN_IF_UNDOCUMENTED = YES -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. WARN_IF_DOC_ERROR = YES -# This WARN_NO_PARAMDOC option can be abled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. +# The default value is: NO. WARN_NO_PARAMDOC = NO -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). WARN_LOGFILE = Doxygen.log #--------------------------------------------------------------------------- -# configuration options related to the input files +# Configuration options related to the input files #--------------------------------------------------------------------------- -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. -INPUT = @top_srcdir@/libnfc @top_srcdir@/examples @top_srcdir@/include/nfc @top_srcdir@/utils +INPUT = @top_srcdir@/libnfc \ + @top_srcdir@/examples \ + @top_srcdir@/include/nfc \ + @top_srcdir@/utils # This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. FILE_PATTERNS = *.c \ *.h \ *.dox -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. RECURSIVE = NO -# The EXCLUDE tag can be used to specify files and/or directories that should +# The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. EXCLUDE = @top_srcdir@/libnfc/drivers.h \ @top_srcdir@/libnfc/iso14443-subr.c \ @@ -615,19 +841,21 @@ EXCLUDE = @top_srcdir@/libnfc/drivers.h \ @top_srcdir@/libnfc/log-printf.c \ @top_srcdir@/libnfc/log.h \ @top_srcdir@/libnfc/mirror-subrc.c \ - @top_srcdir@/libnfc/mirror-subrc.h \ + @top_srcdir@/libnfc/mirror-subrc.h -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded # from the input. +# The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = .git/* @@ -636,595 +864,1151 @@ EXCLUDE_PATTERNS = .git/* # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). EXAMPLE_PATH = @top_srcdir@/ \ @top_srcdir@/src/examples/doc # If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. EXAMPLE_PATTERNS = ChangeLog \ *.c # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. EXAMPLE_RECURSIVE = NO -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be -# ignored. +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. FILTER_SOURCE_FILES = NO +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + #--------------------------------------------------------------------------- -# configuration options related to source browsing +# Configuration options related to source browsing #--------------------------------------------------------------------------- -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. SOURCE_BROWSER = YES -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. INLINE_SOURCES = NO -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. STRIP_CODE_COMMENTS = YES -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. REFERENCED_BY_RELATION = NO -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. REFERENCES_RELATION = NO -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. REFERENCES_LINK_SOURCE = YES -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. VERBATIM_HEADERS = YES +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse-libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + #--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index +# Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. ALPHABETICAL_INDEX = NO -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- -# configuration options related to the HTML output +# Configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. GENERATE_HTML = YES -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a # standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be # written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER -# are set, an additional index file will be generated that can be used as input for -# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated -# HTML documentation. +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. -# For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see -# Qt Help Project / Custom Filters. +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's -# filter section matches. -# Qt Help Project / Filter Attributes. +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NONE -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list. +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. -USE_INLINE_TREES = NO +ENUM_VALUES_PER_LINE = 4 -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 -# When the SEARCHENGINE tag is enable doxygen will generate a search box for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP) or Qt help (GENERATE_QHP) -# there is already a search function so this one should typically -# be disabled. +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /