diff --git a/CMakeLists.txt b/CMakeLists.txt index 6bc4728..2e148c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,66 +1,66 @@ -PROJECT(libnfc C) -CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -SET(VERSION "1.2.2") - -SET(LIBNFC_VERBOSE_OUTPUT OFF CACHE BOOL "Verbose output of communication with the NFC chip") -SET(LIBNFC_LANG_C99 OFF CACHE BOOL "Use C99 language standard (GCC only)") - -IF(DEFINED CMAKE_INSTALL_LIBDIR) - SET(PKG_LIBDIR ${CMAKE_INSTALL_LIBDIR}) -ELSE(DEFINED CMAKE_INSTALL_LIBDIR) - SET(CMAKE_INSTALL_LIBDIR lib) - SET(PKG_LIBDIR ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) -ENDIF(DEFINED CMAKE_INSTALL_LIBDIR) - -IF(DEFINED INCLUDE_INSTALL_DIR) - SET(PKG_INCLUDE_DIR ${INCLUDE_INSTALL_DIR}) -ELSE(DEFINED INCLUDE_INSTALL_DIR) - SET(INCLUDE_INSTALL_DIR include) - SET(PKG_INCLUDE_DIR ${CMAKE_INSTALL_PREFIX}/${INCLUDE_INSTALL_DIR}) -ENDIF(DEFINED INCLUDE_INSTALL_DIR) - -IF(NOT DEFINED SHARE_INSTALL_PREFIX) - SET(SHARE_INSTALL_PREFIX share) -ENDIF(NOT DEFINED SHARE_INSTALL_PREFIX) - -IF(NOT MSVC) - INCLUDE(FindPkgConfig) - CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libnfc.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libnfc.pc @ONLY) - INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libnfc.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) -ENDIF(NOT MSVC) - -ADD_SUBDIRECTORY(src) - -# Binary Package -IF(MSVC) - SET(CPACK_GENERATOR "NSIS") -ELSE(MSVC) - SET(CPACK_GENERATOR "TGZ") -ENDIF(MSVC) -SET(CPACK_PACKAGE_FILE_NAME "libnfc-${VERSION}-bin") -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") -SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") -SET(CPACK_PACKAGE_VERSION_MAJOR "1") -SET(CPACK_PACKAGE_VERSION_MINOR "2") -SET(CPACK_PACKAGE_VERSION_PATCH "2") -SET(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "NFC Library") -SET(CPACK_COMPONENT_EXAMPLES_DISPLAY_NAME "Example Applications") -SET(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "Development Headers") -SET(CPACK_COMPONENT_MANUALS_DISPLAY_NAME "Example Applications Manuals") -SET(CPACK_COMPONENT_HEADERS_DISABLED TRUE) -SET(CPACK_COMPONENT_MANUALS_DISABLED TRUE) -SET(CPACK_COMPONENT_HEADERS_DEPENDS libraries) -SET(CPACK_COMPONENT_EXAMPLES_DEPENDS libraries) -SET(CPACK_COMPONENT_MANUALS_DEPENDS examples) - -# Source Package -IF(MSVC) - SET(CPACK_SOURCE_GENERATOR "ZIP") -ELSE(MSVC) - SET(CPACK_SOURCE_GENERATOR "ZIP;TBZ2") -ENDIF(MSVC) -SET(CPACK_SOURCE_PACKAGE_FILE_NAME "libnfc-${VERSION}") -SET(CPACK_SOURCE_IGNORE_FILES "~$" "/\\\\.svn/" "bin/") -INCLUDE(CPack) +PROJECT(libnfc C) +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +SET(VERSION "1.2.2") + +SET(LIBNFC_VERBOSE_OUTPUT OFF CACHE BOOL "Verbose output of communication with the NFC chip") +SET(LIBNFC_LANG_C99 OFF CACHE BOOL "Use C99 language standard (GCC only)") + +IF(DEFINED CMAKE_INSTALL_LIBDIR) + SET(PKG_LIBDIR ${CMAKE_INSTALL_LIBDIR}) +ELSE(DEFINED CMAKE_INSTALL_LIBDIR) + SET(CMAKE_INSTALL_LIBDIR lib) + SET(PKG_LIBDIR ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) +ENDIF(DEFINED CMAKE_INSTALL_LIBDIR) + +IF(DEFINED INCLUDE_INSTALL_DIR) + SET(PKG_INCLUDE_DIR ${INCLUDE_INSTALL_DIR}) +ELSE(DEFINED INCLUDE_INSTALL_DIR) + SET(INCLUDE_INSTALL_DIR include) + SET(PKG_INCLUDE_DIR ${CMAKE_INSTALL_PREFIX}/${INCLUDE_INSTALL_DIR}) +ENDIF(DEFINED INCLUDE_INSTALL_DIR) + +IF(NOT DEFINED SHARE_INSTALL_PREFIX) + SET(SHARE_INSTALL_PREFIX share) +ENDIF(NOT DEFINED SHARE_INSTALL_PREFIX) + +IF(NOT MSVC) + INCLUDE(FindPkgConfig) + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libnfc.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libnfc.pc @ONLY) + INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libnfc.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) +ENDIF(NOT MSVC) + +ADD_SUBDIRECTORY(src) + +# Binary Package +IF(MSVC) + SET(CPACK_GENERATOR "NSIS") +ELSE(MSVC) + SET(CPACK_GENERATOR "TGZ") +ENDIF(MSVC) +SET(CPACK_PACKAGE_FILE_NAME "libnfc-${VERSION}-bin") +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") +SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") +SET(CPACK_PACKAGE_VERSION_MAJOR "1") +SET(CPACK_PACKAGE_VERSION_MINOR "2") +SET(CPACK_PACKAGE_VERSION_PATCH "2") +SET(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "NFC Library") +SET(CPACK_COMPONENT_EXAMPLES_DISPLAY_NAME "Example Applications") +SET(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "Development Headers") +SET(CPACK_COMPONENT_MANUALS_DISPLAY_NAME "Example Applications Manuals") +SET(CPACK_COMPONENT_HEADERS_DISABLED TRUE) +SET(CPACK_COMPONENT_MANUALS_DISABLED TRUE) +SET(CPACK_COMPONENT_HEADERS_DEPENDS libraries) +SET(CPACK_COMPONENT_EXAMPLES_DEPENDS libraries) +SET(CPACK_COMPONENT_MANUALS_DEPENDS examples) + +# Source Package +IF(MSVC) + SET(CPACK_SOURCE_GENERATOR "ZIP") +ELSE(MSVC) + SET(CPACK_SOURCE_GENERATOR "ZIP;TBZ2") +ENDIF(MSVC) +SET(CPACK_SOURCE_PACKAGE_FILE_NAME "libnfc-${VERSION}") +SET(CPACK_SOURCE_IGNORE_FILES "~$" "/\\\\.svn/" "bin/") +INCLUDE(CPack) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index db56646..69c8b92 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,76 +1,76 @@ -SET(LIBRARY-SOURCES libnfc dev_pn531 dev_pn533 dev_acr122 rs232 bitutils dev_arygon) -SET(TOOLS-SOURCES list mftool mfultool) - -ADD_DEFINITIONS("-DHAVE_PCSC_LITE=1") - -IF(LIBNFC_VERBOSE_OUTPUT) - ADD_DEFINITIONS("-DDEBUG") -ENDIF(LIBNFC_VERBOSE_OUTPUT) - -IF(LIBNFC_LANG_C99 AND NOT MSVC) - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") -ENDIF(LIBNFC_LANG_C99 AND NOT MSVC) - -IF(MSVC) - # Hide some warnings, this should be fixed in the code instead! - ADD_DEFINITIONS("-D_CRT_SECURE_NO_WARNINGS") -ENDIF(MSVC) - -IF(MSVC) - # Include the stdint headers, because MSVC does not have them - INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/msvc) - - # This is from libusb-win32.sourceforge.net - SET(LIBUSB_INCLUDE_DIRS $ENV{ProgramFiles}/LibUSB-Win32/include) - SET(LIBUSB_LIBRARIES $ENV{ProgramFiles}/LibUSB-Win32/lib/msvc/libusb.lib) - - # This is included with Visual Studio Express 2008, we should really use - # something that finds this library, whatever the MSVC version - SET(LIBPCSCLITE_LIBRARIES "$ENV{ProgramFiles}/Microsoft SDKs/Windows/v6.0A/Lib/WinSCard.Lib") - # On MSVC we don't need the winscard.h header in the include path because - # it already is there... -ELSE(MSVC) - # On Unix we just use pkg-config - PKG_CHECK_MODULES(LIBUSB REQUIRED libusb) - PKG_CHECK_MODULES(LIBPCSCLITE REQUIRED libpcsclite) -ENDIF(MSVC) - -INCLUDE_DIRECTORIES(${LIBUSB_INCLUDE_DIRS} ${LIBPCSCLITE_INCLUDE_DIRS}) - -# Library -ADD_LIBRARY(nfc SHARED ${LIBRARY-SOURCES}) -TARGET_LINK_LIBRARIES(nfc ${LIBUSB_LIBRARIES} ${LIBPCSCLITE_LIBRARIES}) -SET_TARGET_PROPERTIES(nfc PROPERTIES SOVERSION 0 VERSION 0.0.0) - -IF(MSVC) - # On Windows the shared (runtime) library should be either in the same - # directory as the excutables or in the path, we add it to same directory - INSTALL(TARGETS nfc RUNTIME DESTINATION bin COMPONENT libraries) - - # At compile time we need the .LIB file, we place it in the lib directory - INSTALL(TARGETS nfc ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT headers) -ELSE(MSVC) - INSTALL(TARGETS nfc LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries) -ENDIF(MSVC) - -# Headers -FILE(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h") -INSTALL(FILES ${headers} DESTINATION ${INCLUDE_INSTALL_DIR}/libnfc COMPONENT headers) -IF(MSVC) - # On Windows we also install the stdint headers, without it programs using it - # can't compile (like if we want to compile the included examples "out of - # tree") - #FILE(GLOB stdint "${CMAKE_CURRENT_SOURCE_DIR}/msvc/*.h") - #INSTALL(FILES ${stdint} DESTINATION ${INCLUDE_INSTALL_DIR}/libnfc COMPONENT headers) -ENDIF(MSVC) - -# Examples -FOREACH(source ${TOOLS-SOURCES}) - ADD_EXECUTABLE(nfc-${source} ${source}.c) - TARGET_LINK_LIBRARIES(nfc-${source} nfc) - INSTALL(TARGETS nfc-${source} RUNTIME DESTINATION bin COMPONENT examples) -ENDFOREACH(source) - -# Manuals for the examples -FILE(GLOB manuals "${CMAKE_CURRENT_SOURCE_DIR}/*.1") -INSTALL(FILES ${manuals} DESTINATION ${SHARE_INSTALL_PREFIX}/man/man1 COMPONENT manuals) +SET(LIBRARY-SOURCES libnfc dev_pn531 dev_pn533 dev_acr122 rs232 bitutils dev_arygon) +SET(TOOLS-SOURCES list mftool mfultool) + +ADD_DEFINITIONS("-DHAVE_PCSC_LITE=1") + +IF(LIBNFC_VERBOSE_OUTPUT) + ADD_DEFINITIONS("-DDEBUG") +ENDIF(LIBNFC_VERBOSE_OUTPUT) + +IF(LIBNFC_LANG_C99 AND NOT MSVC) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") +ENDIF(LIBNFC_LANG_C99 AND NOT MSVC) + +IF(MSVC) + # Hide some warnings, this should be fixed in the code instead! + ADD_DEFINITIONS("-D_CRT_SECURE_NO_WARNINGS") +ENDIF(MSVC) + +IF(MSVC) + # Include the stdint headers, because MSVC does not have them + INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/msvc) + + # This is from libusb-win32.sourceforge.net + SET(LIBUSB_INCLUDE_DIRS $ENV{ProgramFiles}/LibUSB-Win32/include) + SET(LIBUSB_LIBRARIES $ENV{ProgramFiles}/LibUSB-Win32/lib/msvc/libusb.lib) + + # This is included with Visual Studio Express 2008, we should really use + # something that finds this library, whatever the MSVC version + SET(LIBPCSCLITE_LIBRARIES "$ENV{ProgramFiles}/Microsoft SDKs/Windows/v6.0A/Lib/WinSCard.Lib") + # On MSVC we don't need the winscard.h header in the include path because + # it already is there... +ELSE(MSVC) + # On Unix we just use pkg-config + PKG_CHECK_MODULES(LIBUSB REQUIRED libusb) + PKG_CHECK_MODULES(LIBPCSCLITE REQUIRED libpcsclite) +ENDIF(MSVC) + +INCLUDE_DIRECTORIES(${LIBUSB_INCLUDE_DIRS} ${LIBPCSCLITE_INCLUDE_DIRS}) + +# Library +ADD_LIBRARY(nfc SHARED ${LIBRARY-SOURCES}) +TARGET_LINK_LIBRARIES(nfc ${LIBUSB_LIBRARIES} ${LIBPCSCLITE_LIBRARIES}) +SET_TARGET_PROPERTIES(nfc PROPERTIES SOVERSION 0 VERSION 0.0.0) + +IF(MSVC) + # On Windows the shared (runtime) library should be either in the same + # directory as the excutables or in the path, we add it to same directory + INSTALL(TARGETS nfc RUNTIME DESTINATION bin COMPONENT libraries) + + # At compile time we need the .LIB file, we place it in the lib directory + INSTALL(TARGETS nfc ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT headers) +ELSE(MSVC) + INSTALL(TARGETS nfc LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries) +ENDIF(MSVC) + +# Headers +FILE(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h") +INSTALL(FILES ${headers} DESTINATION ${INCLUDE_INSTALL_DIR}/libnfc COMPONENT headers) +IF(MSVC) + # On Windows we also install the stdint headers, without it programs using it + # can't compile (like if we want to compile the included examples "out of + # tree") + #FILE(GLOB stdint "${CMAKE_CURRENT_SOURCE_DIR}/msvc/*.h") + #INSTALL(FILES ${stdint} DESTINATION ${INCLUDE_INSTALL_DIR}/libnfc COMPONENT headers) +ENDIF(MSVC) + +# Examples +FOREACH(source ${TOOLS-SOURCES}) + ADD_EXECUTABLE(nfc-${source} ${source}.c) + TARGET_LINK_LIBRARIES(nfc-${source} nfc) + INSTALL(TARGETS nfc-${source} RUNTIME DESTINATION bin COMPONENT examples) +ENDFOREACH(source) + +# Manuals for the examples +FILE(GLOB manuals "${CMAKE_CURRENT_SOURCE_DIR}/*.1") +INSTALL(FILES ${manuals} DESTINATION ${SHARE_INSTALL_PREFIX}/man/man1 COMPONENT manuals) diff --git a/src/mfultool.c b/src/mfultool.c index 93adcab..c394482 100644 --- a/src/mfultool.c +++ b/src/mfultool.c @@ -1,220 +1,220 @@ -/* - -Public platform independent Near Field Communication (NFC) library -Copyright (C) 2009, Roel Verdult - -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 - -*/ - -#include -#include -#include -#include -#include - -#include -#include - -#include "libnfc.h" -#include "mifareultag.h" - -static dev_info* pdi; -static tag_info ti; -static mifare_param mp; -static mifareul_tag mtDump; - -bool read_card() -{ - int page; - bool bSuccess = true; - - // these are pages of 4 bytes each; we can read 4 pages at once. - for (page = 0; page <= 0xF; page += 4){ - // Try to read out the data block - if (nfc_initiator_mifare_cmd(pdi,MC_READ,page,&mp)) - { - memcpy(mtDump.amb[page / 4].mbd.abtData, mp.mpd.abtData, 16); - } else { - bSuccess = false; - break; - } - } - return bSuccess; -} - -bool write_card() -{ - uint32_t uiBlock = 0; - int page; - bool bFailure = false; - - for (page = 0x4; page <= 0xF; page++) { - - // Show if the readout went well - if (bFailure) - { - printf("x"); - // When a failure occured we need to redo the anti-collision - if (!nfc_initiator_select_tag(pdi,IM_ISO14443A_106,NULL,0,&ti)) - { - printf("!\nError: tag was removed\n"); - return false; - } - bFailure = false; - } else { - // Skip this the first time, bFailure it means nothing (yet) - if (uiBlock != 0) - { - printf("."); - } - } - fflush(stdout); - - // Make sure a earlier write did not fail - if (!bFailure) - { - // For the Mifare Ultralight, this write command can be used - // in compatibility mode, which only actually writes the first - // 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); - if (!nfc_initiator_mifare_cmd(pdi, MC_WRITE, page, &mp)) bFailure = true; - } - } - printf("%c|\n",(bFailure)?'x':'.'); - fflush(stdout); - - return true; -} - -int main(int argc, const char* argv[]) -{ - bool bReadAction; - byte_t* pbtUID; - FILE* pfDump; - - if (argc < 3) - { - printf("\n"); - printf("mfultool \n"); - printf("\n"); - printf(" - Perform (read from) or (write to) card\n"); - printf(" - Used to write (card to file) or (file to card)\n"); - printf("\n"); - return 1; - } - - printf("\nChecking arguments and settings\n"); - - bReadAction = (tolower(*(argv[1])) == 'r'); - - if (bReadAction) - { - memset(&mtDump,0x00,sizeof(mtDump)); - } else { - pfDump = fopen(argv[2],"rb"); - - if (pfDump == NULL) - { - printf("Could not open dump file: %s\n",argv[2]); - return 1; - } - - if (fread(&mtDump,1,sizeof(mtDump),pfDump) != sizeof(mtDump)) - { - printf("Could not read from dump file: %s\n",argv[2]); - fclose(pfDump); - return 1; - } - fclose(pfDump); - } - printf("Succesful opened the dump file\n"); - - // Try to open the NFC reader - pdi = nfc_connect(); - if (pdi == INVALID_DEVICE_INFO) - { - printf("Error connecting NFC reader\n"); - return 1; - } - - nfc_initiator_init(pdi); - - // Drop the field for a while - nfc_configure(pdi,DCO_ACTIVATE_FIELD,false); - - // Let the reader only try once to find a tag - nfc_configure(pdi,DCO_INFINITE_SELECT,false); - nfc_configure(pdi,DCO_HANDLE_CRC,true); - nfc_configure(pdi,DCO_HANDLE_PARITY,true); - - // Enable field so more power consuming cards can power themselves up - nfc_configure(pdi,DCO_ACTIVATE_FIELD,true); - - printf("Connected to NFC reader: %s\n",pdi->acName); - - // Try to find a MIFARE Ultralight tag - if (!nfc_initiator_select_tag(pdi,IM_ISO14443A_106,NULL,0,&ti)) - { - printf("Error: no tag was found\n"); - nfc_disconnect(pdi); - return 1; - } - - // Test if we are dealing with a MIFARE compatible tag - - if (ti.tia.abtAtqa[1] != 0x44){ - printf("Error: tag is not a MIFARE Ultralight card\n"); - nfc_disconnect(pdi); - return 1; - } - - - // Get the info from the current tag - pbtUID = ti.tia.abtUid; - printf("Found MIFARE Ultralight card with uid: %08x\n", swap_endian32(pbtUID)); - - if (bReadAction) - { - if (read_card()) - { - printf("Writing data to file: %s\n",argv[2]); - fflush(stdout); - pfDump = fopen(argv[2],"wb"); - if (pfDump == NULL) - { - printf("Could not open file: %s\n",argv[2]); - return 1; - } - if (fwrite(&mtDump,1,sizeof(mtDump),pfDump) != sizeof(mtDump)) - { - printf("Could not write to file: %s\n",argv[2]); - return 1; - } - fclose(pfDump); - printf("Done, all bytes dumped to file!\n"); - } - } else { - if (write_card()) - { - printf("Done, all data is written to the card!\n"); - } - } - - nfc_disconnect(pdi); - - return 0; -} +/* + +Public platform independent Near Field Communication (NFC) library +Copyright (C) 2009, Roel Verdult + +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 + +*/ + +#include +#include +#include +#include +#include + +#include +#include + +#include "libnfc.h" +#include "mifareultag.h" + +static dev_info* pdi; +static tag_info ti; +static mifare_param mp; +static mifareul_tag mtDump; + +bool read_card() +{ + int page; + bool bSuccess = true; + + // these are pages of 4 bytes each; we can read 4 pages at once. + for (page = 0; page <= 0xF; page += 4){ + // Try to read out the data block + if (nfc_initiator_mifare_cmd(pdi,MC_READ,page,&mp)) + { + memcpy(mtDump.amb[page / 4].mbd.abtData, mp.mpd.abtData, 16); + } else { + bSuccess = false; + break; + } + } + return bSuccess; +} + +bool write_card() +{ + uint32_t uiBlock = 0; + int page; + bool bFailure = false; + + for (page = 0x4; page <= 0xF; page++) { + + // Show if the readout went well + if (bFailure) + { + printf("x"); + // When a failure occured we need to redo the anti-collision + if (!nfc_initiator_select_tag(pdi,IM_ISO14443A_106,NULL,0,&ti)) + { + printf("!\nError: tag was removed\n"); + return false; + } + bFailure = false; + } else { + // Skip this the first time, bFailure it means nothing (yet) + if (uiBlock != 0) + { + printf("."); + } + } + fflush(stdout); + + // Make sure a earlier write did not fail + if (!bFailure) + { + // For the Mifare Ultralight, this write command can be used + // in compatibility mode, which only actually writes the first + // 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); + if (!nfc_initiator_mifare_cmd(pdi, MC_WRITE, page, &mp)) bFailure = true; + } + } + printf("%c|\n",(bFailure)?'x':'.'); + fflush(stdout); + + return true; +} + +int main(int argc, const char* argv[]) +{ + bool bReadAction; + byte_t* pbtUID; + FILE* pfDump; + + if (argc < 3) + { + printf("\n"); + printf("mfultool \n"); + printf("\n"); + printf(" - Perform (read from) or (write to) card\n"); + printf(" - Used to write (card to file) or (file to card)\n"); + printf("\n"); + return 1; + } + + printf("\nChecking arguments and settings\n"); + + bReadAction = (tolower(*(argv[1])) == 'r'); + + if (bReadAction) + { + memset(&mtDump,0x00,sizeof(mtDump)); + } else { + pfDump = fopen(argv[2],"rb"); + + if (pfDump == NULL) + { + printf("Could not open dump file: %s\n",argv[2]); + return 1; + } + + if (fread(&mtDump,1,sizeof(mtDump),pfDump) != sizeof(mtDump)) + { + printf("Could not read from dump file: %s\n",argv[2]); + fclose(pfDump); + return 1; + } + fclose(pfDump); + } + printf("Succesful opened the dump file\n"); + + // Try to open the NFC reader + pdi = nfc_connect(); + if (pdi == INVALID_DEVICE_INFO) + { + printf("Error connecting NFC reader\n"); + return 1; + } + + nfc_initiator_init(pdi); + + // Drop the field for a while + nfc_configure(pdi,DCO_ACTIVATE_FIELD,false); + + // Let the reader only try once to find a tag + nfc_configure(pdi,DCO_INFINITE_SELECT,false); + nfc_configure(pdi,DCO_HANDLE_CRC,true); + nfc_configure(pdi,DCO_HANDLE_PARITY,true); + + // Enable field so more power consuming cards can power themselves up + nfc_configure(pdi,DCO_ACTIVATE_FIELD,true); + + printf("Connected to NFC reader: %s\n",pdi->acName); + + // Try to find a MIFARE Ultralight tag + if (!nfc_initiator_select_tag(pdi,IM_ISO14443A_106,NULL,0,&ti)) + { + printf("Error: no tag was found\n"); + nfc_disconnect(pdi); + return 1; + } + + // Test if we are dealing with a MIFARE compatible tag + + if (ti.tia.abtAtqa[1] != 0x44){ + printf("Error: tag is not a MIFARE Ultralight card\n"); + nfc_disconnect(pdi); + return 1; + } + + + // Get the info from the current tag + pbtUID = ti.tia.abtUid; + printf("Found MIFARE Ultralight card with uid: %08x\n", swap_endian32(pbtUID)); + + if (bReadAction) + { + if (read_card()) + { + printf("Writing data to file: %s\n",argv[2]); + fflush(stdout); + pfDump = fopen(argv[2],"wb"); + if (pfDump == NULL) + { + printf("Could not open file: %s\n",argv[2]); + return 1; + } + if (fwrite(&mtDump,1,sizeof(mtDump),pfDump) != sizeof(mtDump)) + { + printf("Could not write to file: %s\n",argv[2]); + return 1; + } + fclose(pfDump); + printf("Done, all bytes dumped to file!\n"); + } + } else { + if (write_card()) + { + printf("Done, all data is written to the card!\n"); + } + } + + nfc_disconnect(pdi); + + return 0; +}