diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index b00411f..dc7bac9 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 29fd17e..9637d25 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 0000000..cf9bf41 --- /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 0000000..18f39b9 --- /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 0000000..c043103 --- /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 0000000..19bd3cd --- /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); +}