From b7fc6cbc1f4b108569ece06e2539160a074739b0 Mon Sep 17 00:00:00 2001 From: lexon Date: Thu, 16 Jun 2016 21:13:42 +0000 Subject: [PATCH 1/6] Added write support for mifare-ultralight, blocking way --- binding.gyp | 3 +- src/mifare.h | 2 +- src/nfc.cc | 232 ++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 213 insertions(+), 24 deletions(-) diff --git a/binding.gyp b/binding.gyp index 43d01ea..4f91088 100644 --- a/binding.gyp +++ b/binding.gyp @@ -6,7 +6,8 @@ "include_dirs": [ "mpd.abtData, abtRx, 16); + } else { + return false; } } + // Command succesfully executed + return true; + } - nfc_device *pnd; - nfc_target nt; - nfc_context *context; - bool run; - bool claimed; + class NFC: public Nan::ObjectWrap { + public: + static NAN_METHOD(New); + static NAN_METHOD(Start); + static NAN_METHOD(Stop); + static NAN_METHOD(Write); + + void stop() { + run = false; + while(claimed); + if(pnd) { + nfc_abort_command(pnd); + nfc_close(pnd); + pnd = NULL; + } + if(context) { + nfc_exit(context); + context = NULL; + } + } + + nfc_device *pnd; + nfc_target nt; + nfc_context *context; + bool run; + bool claimed; }; + /* + * Write blocks to NFC card + * TODO: Refactor with `AsyncProcessWorker` + */ + NAN_METHOD(NFC::Write) { + Nan::HandleScope scope; + Isolate *isolate = info.GetIsolate(); + + NFC* baton = ObjectWrap::Unwrap(info.This()); + Local bufferObj = info[0]->ToObject(); + char *data = node::Buffer::Data(bufferObj); + + bool write_otp = false; + bool write_lock = false; + //bool write_uid = false; + + uint8_t uiBlocks = 0x0f; + uint8_t uiPages = uiBlocks; + uint32_t uiBlock = 0; + uint32_t uiSkippedPages = 0; + uint32_t uiPagesWritten = 0; + bool bFailure = false; + + mifare_param mp; // auth(10 bytes), data(16 bytes), value(4 bytes) + mifareul_tag mt; // 4 blocks (64 bytes) + + bzero(&mp, sizeof mp); + bzero(&mt, sizeof mt); + memcpy(&mt, data, sizeof mt); + + // TODO: figure out how to fix the error and remove the while loop + // error libnfc.driver.pn532_i2c Length checksum mismatch + // error libnfc.chip.pn53x Unexpected PN53x reply! + while (nfc_initiator_select_passive_target(baton->pnd, nmMifare, NULL, 0, &baton->nt) <= 0){ + printf("Selecting tag...\n"); + } + + switch (baton->nt.nti.nai.abtAtqa[1]) { + case 0x04: + {// TODO: Mifare classic + break; + } + case 0x44: + { // Mifare ultralight + uiSkippedPages = 2; + // TODO: only support write 8 pages (2 data blocks) in the first + // sector now, extend to support more sectors. + for (uint32_t page = uiSkippedPages; page < ((uiPages / 4) * 4); page++) { + if ((page == 0x2) && (!write_lock)) { + uiSkippedPages++; + continue; + } + if ((page == 0x3) && (!write_otp)) { + uiSkippedPages++; + 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(baton->pnd, nmMifare, NULL, 0, &baton->nt) <= 0) { + printf("Tag was removed \n"); + break; + } + bFailure = false; + } + // 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, mt.amb[uiBlock].mbd.abtData + ((page % 4) * 4), 4); + memset(mp.mpd.abtData + 4, 0, 12); + + uint8_t i =0; + uint8_t *bytes; + for (i=0, bytes=mp.mpd.abtData; i < (sizeof mp.mpd.abtData / sizeof mp.mpd.abtData[0]); i++) { + printf("%02x ", bytes[i]); + } + printf("\n"); + + + if (!nfc_initiator_mifare_cmd(baton->pnd, MC_WRITE, page, &mp)) { + bFailure = true; + printf("Failed at page: %d\n", page); + } + else + uiPagesWritten++; + + } // For loop for writing pages + + break; + } + default: + ; + } // switch card type + Local ret = Number::New(isolate, uiPagesWritten); + info.GetReturnValue().Set(ret); + } + class NFCCard { public: NFCCard() { @@ -116,6 +299,7 @@ namespace { this->data = (char*)malloc(data_size); memcpy(this->data, data, data_size); } + private: char *deviceID; char *name; @@ -342,7 +526,8 @@ namespace { break; } } - + + void HandleProgressCallback(const char *_tag, size_t size) { Nan::HandleScope scope; @@ -478,6 +663,8 @@ namespace { info.GetReturnValue().Set(object); } + + NAN_MODULE_INIT(init) { Local tpl = Nan::New(NFC::New); tpl->SetClassName(Nan::New("NFC").ToLocalChecked()); @@ -485,6 +672,7 @@ namespace { SetPrototypeMethod(tpl, "start", NFC::Start); SetPrototypeMethod(tpl, "stop", NFC::Stop); + SetPrototypeMethod(tpl, "write", NFC::Write); Nan::Export(target, "version", Version); Nan::Export(target, "scan", Scan); From c55b7c511aa5eaac8caa4c2f9e4d6c90f31b4c95 Mon Sep 17 00:00:00 2001 From: lexon Date: Thu, 16 Jun 2016 21:13:42 +0000 Subject: [PATCH 2/6] Added write support for mifare-ultralight, blocking way --- binding.gyp | 3 +- src/mifare.h | 2 +- src/nfc.cc | 232 ++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 213 insertions(+), 24 deletions(-) diff --git a/binding.gyp b/binding.gyp index 43d01ea..4f91088 100644 --- a/binding.gyp +++ b/binding.gyp @@ -6,7 +6,8 @@ "include_dirs": [ "mpd.abtData, abtRx, 16); + } else { + return false; } } + // Command succesfully executed + return true; + } - nfc_device *pnd; - nfc_target nt; - nfc_context *context; - bool run; - bool claimed; + class NFC: public Nan::ObjectWrap { + public: + static NAN_METHOD(New); + static NAN_METHOD(Start); + static NAN_METHOD(Stop); + static NAN_METHOD(Write); + + void stop() { + run = false; + while(claimed); + if(pnd) { + nfc_abort_command(pnd); + nfc_close(pnd); + pnd = NULL; + } + if(context) { + nfc_exit(context); + context = NULL; + } + } + + nfc_device *pnd; + nfc_target nt; + nfc_context *context; + bool run; + bool claimed; }; + /* + * Write blocks to NFC card + * TODO: Refactor with `AsyncProcessWorker` + */ + NAN_METHOD(NFC::Write) { + Nan::HandleScope scope; + Isolate *isolate = info.GetIsolate(); + + NFC* baton = ObjectWrap::Unwrap(info.This()); + Local bufferObj = info[0]->ToObject(); + char *data = node::Buffer::Data(bufferObj); + + bool write_otp = false; + bool write_lock = false; + //bool write_uid = false; + + uint8_t uiBlocks = 0x0f; + uint8_t uiPages = uiBlocks; + uint32_t uiBlock = 0; + uint32_t uiSkippedPages = 0; + uint32_t uiPagesWritten = 0; + bool bFailure = false; + + mifare_param mp; // auth(10 bytes), data(16 bytes), value(4 bytes) + mifareul_tag mt; // 4 blocks (64 bytes) + + bzero(&mp, sizeof mp); + bzero(&mt, sizeof mt); + memcpy(&mt, data, sizeof mt); + + // TODO: figure out how to fix the error and remove the while loop + // error libnfc.driver.pn532_i2c Length checksum mismatch + // error libnfc.chip.pn53x Unexpected PN53x reply! + while (nfc_initiator_select_passive_target(baton->pnd, nmMifare, NULL, 0, &baton->nt) <= 0){ + printf("Selecting tag...\n"); + } + + switch (baton->nt.nti.nai.abtAtqa[1]) { + case 0x04: + {// TODO: Mifare classic + break; + } + case 0x44: + { // Mifare ultralight + uiSkippedPages = 2; + // TODO: only support write 8 pages (2 data blocks) in the first + // sector now, extend to support more sectors. + for (uint32_t page = uiSkippedPages; page < ((uiPages / 4) * 4); page++) { + if ((page == 0x2) && (!write_lock)) { + uiSkippedPages++; + continue; + } + if ((page == 0x3) && (!write_otp)) { + uiSkippedPages++; + 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(baton->pnd, nmMifare, NULL, 0, &baton->nt) <= 0) { + printf("Tag was removed \n"); + break; + } + bFailure = false; + } + // 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, mt.amb[uiBlock].mbd.abtData + ((page % 4) * 4), 4); + memset(mp.mpd.abtData + 4, 0, 12); + + uint8_t i =0; + uint8_t *bytes; + for (i=0, bytes=mp.mpd.abtData; i < (sizeof mp.mpd.abtData / sizeof mp.mpd.abtData[0]); i++) { + printf("%02x ", bytes[i]); + } + printf("\n"); + + + if (!nfc_initiator_mifare_cmd(baton->pnd, MC_WRITE, page, &mp)) { + bFailure = true; + printf("Failed at page: %d\n", page); + } + else + uiPagesWritten++; + + } // For loop for writing pages + + break; + } + default: + ; + } // switch card type + Local ret = Number::New(isolate, uiPagesWritten); + info.GetReturnValue().Set(ret); + } + class NFCCard { public: NFCCard() { @@ -116,6 +299,7 @@ namespace { this->data = (char*)malloc(data_size); memcpy(this->data, data, data_size); } + private: char *deviceID; char *name; @@ -342,7 +526,8 @@ namespace { break; } } - + + void HandleProgressCallback(const char *_tag, size_t size) { Nan::HandleScope scope; @@ -478,6 +663,8 @@ namespace { info.GetReturnValue().Set(object); } + + NAN_MODULE_INIT(init) { Local tpl = Nan::New(NFC::New); tpl->SetClassName(Nan::New("NFC").ToLocalChecked()); @@ -485,6 +672,7 @@ namespace { SetPrototypeMethod(tpl, "start", NFC::Start); SetPrototypeMethod(tpl, "stop", NFC::Stop); + SetPrototypeMethod(tpl, "write", NFC::Write); Nan::Export(target, "version", Version); Nan::Export(target, "scan", Scan); From 5a5428b629c999bf8fce2d3675ee252bc70c0f5c Mon Sep 17 00:00:00 2001 From: lexon Date: Thu, 21 Jul 2016 16:49:33 -0400 Subject: [PATCH 3/6] Added sync read and write to mifare ultralight card (up to 16 sectors) --- src/nfc.cc | 322 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 220 insertions(+), 102 deletions(-) diff --git a/src/nfc.cc b/src/nfc.cc index 9472049..666ba40 100644 --- a/src/nfc.cc +++ b/src/nfc.cc @@ -117,6 +117,8 @@ namespace { static NAN_METHOD(Start); static NAN_METHOD(Stop); static NAN_METHOD(Write); + static NAN_METHOD(ReadSector); + static NAN_METHOD(StartReadWorker); void stop() { run = false; @@ -139,105 +141,10 @@ namespace { bool claimed; }; - /* - * Write blocks to NFC card - * TODO: Refactor with `AsyncProcessWorker` - */ - NAN_METHOD(NFC::Write) { - Nan::HandleScope scope; - Isolate *isolate = info.GetIsolate(); - - NFC* baton = ObjectWrap::Unwrap(info.This()); - Local bufferObj = info[0]->ToObject(); - char *data = node::Buffer::Data(bufferObj); - - bool write_otp = false; - bool write_lock = false; - //bool write_uid = false; - - uint8_t uiBlocks = 0x0f; - uint8_t uiPages = uiBlocks; - uint32_t uiBlock = 0; - uint32_t uiSkippedPages = 0; - uint32_t uiPagesWritten = 0; - bool bFailure = false; - - mifare_param mp; // auth(10 bytes), data(16 bytes), value(4 bytes) - mifareul_tag mt; // 4 blocks (64 bytes) - - bzero(&mp, sizeof mp); - bzero(&mt, sizeof mt); - memcpy(&mt, data, sizeof mt); - - // TODO: figure out how to fix the error and remove the while loop - // error libnfc.driver.pn532_i2c Length checksum mismatch - // error libnfc.chip.pn53x Unexpected PN53x reply! - while (nfc_initiator_select_passive_target(baton->pnd, nmMifare, NULL, 0, &baton->nt) <= 0){ - printf("Selecting tag...\n"); - } - - switch (baton->nt.nti.nai.abtAtqa[1]) { - case 0x04: - {// TODO: Mifare classic - break; - } - case 0x44: - { // Mifare ultralight - uiSkippedPages = 2; - // TODO: only support write 8 pages (2 data blocks) in the first - // sector now, extend to support more sectors. - for (uint32_t page = uiSkippedPages; page < ((uiPages / 4) * 4); page++) { - if ((page == 0x2) && (!write_lock)) { - uiSkippedPages++; - continue; - } - if ((page == 0x3) && (!write_otp)) { - uiSkippedPages++; - 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(baton->pnd, nmMifare, NULL, 0, &baton->nt) <= 0) { - printf("Tag was removed \n"); - break; - } - bFailure = false; - } - // 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, mt.amb[uiBlock].mbd.abtData + ((page % 4) * 4), 4); - memset(mp.mpd.abtData + 4, 0, 12); - uint8_t i =0; - uint8_t *bytes; - for (i=0, bytes=mp.mpd.abtData; i < (sizeof mp.mpd.abtData / sizeof mp.mpd.abtData[0]); i++) { - printf("%02x ", bytes[i]); - } - printf("\n"); - - - if (!nfc_initiator_mifare_cmd(baton->pnd, MC_WRITE, page, &mp)) { - bFailure = true; - printf("Failed at page: %d\n", page); - } - else - uiPagesWritten++; - - } // For loop for writing pages - - break; - } - default: - ; - } // switch card type - Local ret = Number::New(isolate, uiPagesWritten); - info.GetReturnValue().Set(ret); } + class NFCCard { public: NFCCard() { @@ -271,6 +178,7 @@ namespace { if(this->deviceID) delete this->deviceID; this->deviceID = strdup(deviceID); } + void SetName(const char *name) { if(this->name) delete this->name; this->name = strdup(name); @@ -300,7 +208,7 @@ namespace { memcpy(this->data, data, data_size); } - private: + public: char *deviceID; char *name; char *uid; @@ -506,6 +414,7 @@ namespace { command[0] = MC_READ; command[1] = n; res = nfc_initiator_transceive_bytes(baton->pnd, command, 2, dp, cnt, -1); + printf("Read page %ld with %d bytes\n", n, res); if (res >= 0) continue; if (res != NFC_ERFTRANS) { @@ -549,6 +458,206 @@ namespace { NFCCard *tag; }; + /* + * Read NTAG21x sector (4 blocks, 16 pages, or 64 bytes). + * + * NOTE: Device document: http://www.nxp.com/documents/data_sheet/NTAG213_215_216.pdf + */ + NAN_METHOD(NFC::ReadSector) { + NFC* baton = ObjectWrap::Unwrap(info.This()); + Isolate *isolate = info.GetIsolate(); + int sector = info[0]->Int32Value(); + + while(nfc_initiator_select_passive_target(baton->pnd, nmMifare, NULL, 0, &baton->nt) > 0) { + + NFCCard *tag = new NFCCard(); + + unsigned long cc, n; + char *bp, result[BUFSIZ]; + const char *sp; + + tag->SetDeviceID(nfc_device_get_connstring(baton->pnd)); + tag->SetName(nfc_device_get_name(baton->pnd)); + + + cc = baton->nt.nti.nai.szUidLen; + if (cc > sizeof baton->nt.nti.nai.abtUid) cc = sizeof baton->nt.nti.nai.abtUid; + char uid[3 * sizeof baton->nt.nti.nai.abtUid]; + bzero(uid, sizeof uid); + + for (n = 0, bp = uid, sp = ""; n < cc; n++, bp += strlen(bp), sp = ":") { + snprintf(bp, sizeof uid - (bp - uid), "%s%02x", sp, baton->nt.nti.nai.abtUid[n]); + } + tag->SetUID(uid); + tag->SetType(baton->nt.nti.nai.abtAtqa[1]); + + switch (baton->nt.nti.nai.abtAtqa[1]) { + case 0x44: + { + tag->SetTag("mifare-ultralight"); + + if (nfc_device_set_property_bool(baton->pnd, NP_EASY_FRAMING, true) < 0) { + snprintf(result, sizeof result, "nfc_device_set_property_bool easyFraming=false: %s", + nfc_strerror(baton->pnd)); + tag->SetError(result); + break; + } + + int cnt, len, res; + uint8_t command[2], data[64], *dp; + for (n = sector*16 + 0, cc = sector*16+0x0f, dp = data, cnt = sizeof data, len = 0, res=0; + n <= cc; + n += 4, dp += res, cnt -= res, len += res) { + + command[0] = MC_READ; + command[1] = n; + res = nfc_initiator_transceive_bytes(baton->pnd, command, 2, dp, cnt, -1); + //printf("Read page %ld with %d bytes\n", n, res); + + if (res >= 0) continue; + + if (res != NFC_ERFTRANS) { + snprintf(result, sizeof result, "nfc_initiator_transceive_bytes: %s", nfc_strerror(baton->pnd)); + tag->SetError(result); + } + break; + } + if (n < cc) break; + + tag->SetData(data, len); + int offset=0; + if (sector == 0) offset=16; + tag->SetOffset(offset); + break; + } + + default: + break; + } + //printf("Reading sector of device %s:%s with tag: %s\n", tag->deviceID, tag->name, tag->tag); + //printf("tag data: %s\n", tag->data); + + //Local ret = Object::New(isolate, tag); + Local object = Nan::New(); + tag->AddToNodeObject(object); + delete tag; + tag = NULL; + + info.GetReturnValue().Set(object); + break; + } + } + /* + * Write blocks to NFC card + * TODO: Refactor with `AsyncProcessWorker` + */ + NAN_METHOD(NFC::Write) { + Nan::HandleScope scope; + Isolate *isolate = info.GetIsolate(); + + NFC* baton = ObjectWrap::Unwrap(info.This()); + Local bufferObj = info[0]->ToObject(); + char *data = node::Buffer::Data(bufferObj); + size_t datalen = node::Buffer::Length(bufferObj); + /* + for(int i = 0; i < datalen; i++) { + printf("%02x ", data[i]); + } + printf("\n"); + */ + + bool write_otp = false; + bool write_lock = false; + //bool write_uid = false; + + uint8_t uiBlocks = 0x0f; + uint8_t uiPages = uiBlocks; + uint32_t uiBlock = 0; + uint32_t uiSkippedPages = 0; + uint32_t uiPagesWritten = 0; + bool bFailure = false; + + mifare_param mp; // auth(10 bytes), data(16 bytes), value(4 bytes) + mifareul_tag mt; // 4 blocks (64 bytes) + + bzero(&mp, sizeof mp); + bzero(&mt, sizeof mt); + memcpy(&mt, data, sizeof mt); + + // TODO: figure out how to fix the error and remove the while loop + // error libnfc.driver.pn532_i2c Length checksum mismatch + // error libnfc.chip.pn53x Unexpected PN53x reply! + while (nfc_initiator_select_passive_target(baton->pnd, nmMifare, NULL, 0, &baton->nt) <= 0){ + printf("Selecting tag...\n"); + } + + //-$- Calculate how many pages -$- + uiPages = datalen / 4; + + switch (baton->nt.nti.nai.abtAtqa[1]) { + case 0x04: + {// TODO: Mifare classic + break; + } + case 0x44: + { // Mifare ultralight + uiSkippedPages = 2; + // TODO: only support write 8 pages (2 data blocks) in the first + // sector now, extend to support more sectors. + char* dp = data; + for (uint32_t page = 4; page <= uiPages+4; 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(baton->pnd, nmMifare, NULL, 0, &baton->nt) <= 0) { + printf("Tag was removed \n"); + break; + } + bFailure = false; + } + // 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; + if (uiBlock % 4 == 3) { // Sector trailer + page += 3; + uiPages+=4; + continue; + } + */ + + memcpy(mp.mpd.abtData, dp, 4); + dp += 4; + memset(mp.mpd.abtData + 4, 0, 12); + + uint8_t i =0; + uint8_t *bytes; + for (i=0, bytes=mp.mpd.abtData; i < (sizeof mp.mpd.abtData / sizeof mp.mpd.abtData[0]); i++) { + printf("%02x ", bytes[i]); + } + printf("\n"); + + + if (!nfc_initiator_mifare_cmd(baton->pnd, MC_WRITE, page, &mp)) { + bFailure = true; + printf("Failed at page: %d\n", page); + } + else + uiPagesWritten++; + + } // For loop for writing pages + + break; + } + default: + ; + } // switch card type + Local ret = Number::New(isolate, uiPagesWritten); + info.GetReturnValue().Set(ret); + } NAN_METHOD(NFC::New) { Nan::HandleScope scope; @@ -603,14 +712,21 @@ namespace { baton->context = context; baton->pnd = pnd; - NFCReadWorker* readWorker = new NFCReadWorker(baton, info.This()); - Nan::AsyncQueueWorker(readWorker); - Local object = Nan::New(); object->Set(Nan::New("deviceID").ToLocalChecked(), Nan::New(nfc_device_get_connstring(baton->pnd)).ToLocalChecked()); object->Set(Nan::New("name").ToLocalChecked(), Nan::New(nfc_device_get_name(baton->pnd)).ToLocalChecked()); - info.GetReturnValue().Set(object); + info.GetReturnValue().Set(info.This()); + } + + NAN_METHOD(NFC::StartReadWorker) { + Nan::HandleScope scope; + NFC* baton = ObjectWrap::Unwrap(info.This()); + + NFCReadWorker* readWorker = new NFCReadWorker(baton, info.This()); + Nan::AsyncQueueWorker(readWorker); + + info.GetReturnValue().Set(info.This()); } NAN_METHOD(Scan) { @@ -673,11 +789,13 @@ namespace { SetPrototypeMethod(tpl, "start", NFC::Start); SetPrototypeMethod(tpl, "stop", NFC::Stop); SetPrototypeMethod(tpl, "write", NFC::Write); + SetPrototypeMethod(tpl, "readTagSector", NFC::ReadSector); + SetPrototypeMethod(tpl, "startReadWorker", NFC::StartReadWorker); Nan::Export(target, "version", Version); Nan::Export(target, "scan", Scan); Nan::Set(target, Nan::New("NFC").ToLocalChecked(), tpl->GetFunction()); }; -} + NODE_MODULE(nfc, init) From 913f5ae3a30ce5e34de5de611b4c763d829c2bff Mon Sep 17 00:00:00 2001 From: lexon Date: Thu, 21 Jul 2016 17:31:18 -0400 Subject: [PATCH 4/6] Removed unused variables to get rid of build warnings --- src/nfc.cc | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/src/nfc.cc b/src/nfc.cc index 666ba40..7b4b15f 100644 --- a/src/nfc.cc +++ b/src/nfc.cc @@ -141,10 +141,6 @@ namespace { bool claimed; }; - - } - - class NFCCard { public: NFCCard() { @@ -208,7 +204,7 @@ namespace { memcpy(this->data, data, data_size); } - public: + private: char *deviceID; char *name; char *uid; @@ -465,7 +461,6 @@ namespace { */ NAN_METHOD(NFC::ReadSector) { NFC* baton = ObjectWrap::Unwrap(info.This()); - Isolate *isolate = info.GetIsolate(); int sector = info[0]->Int32Value(); while(nfc_initiator_select_passive_target(baton->pnd, nmMifare, NULL, 0, &baton->nt) > 0) { @@ -566,14 +561,9 @@ namespace { printf("\n"); */ - bool write_otp = false; - bool write_lock = false; - //bool write_uid = false; - uint8_t uiBlocks = 0x0f; uint8_t uiPages = uiBlocks; - uint32_t uiBlock = 0; - uint32_t uiSkippedPages = 0; + uint32_t uiSkippedPages = 4; uint32_t uiPagesWritten = 0; bool bFailure = false; @@ -601,11 +591,10 @@ namespace { } case 0x44: { // Mifare ultralight - uiSkippedPages = 2; - // TODO: only support write 8 pages (2 data blocks) in the first - // sector now, extend to support more sectors. + char* dp = data; - for (uint32_t page = 4; page <= uiPages+4; page++) { + uiSkippedPages = 4; // -$- Never write to first block!! -$- + for (uint8_t page = uiSkippedPages; page <= uiPages+uiSkippedPages; page++) { // Show if the readout went well if (bFailure) { @@ -616,13 +605,11 @@ namespace { } bFailure = false; } - // 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; - if (uiBlock % 4 == 3) { // Sector trailer + // -$- Skip sector trailer -$- + uint8_t uiBlock = page / 4; + if (uiBlock % 4 == 3) { page += 3; uiPages+=4; continue; @@ -796,6 +783,6 @@ namespace { Nan::Export(target, "scan", Scan); Nan::Set(target, Nan::New("NFC").ToLocalChecked(), tpl->GetFunction()); }; - +} NODE_MODULE(nfc, init) From 99d2c66c4e69a15b97fd39891074db376bab3020 Mon Sep 17 00:00:00 2001 From: lexon Date: Thu, 21 Jul 2016 23:23:53 -0400 Subject: [PATCH 5/6] comments for functions --- src/nfc.cc | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/nfc.cc b/src/nfc.cc index 7b4b15f..37ec89f 100644 --- a/src/nfc.cc +++ b/src/nfc.cc @@ -203,7 +203,6 @@ namespace { this->data = (char*)malloc(data_size); memcpy(this->data, data, data_size); } - private: char *deviceID; char *name; @@ -410,7 +409,6 @@ namespace { command[0] = MC_READ; command[1] = n; res = nfc_initiator_transceive_bytes(baton->pnd, command, 2, dp, cnt, -1); - printf("Read page %ld with %d bytes\n", n, res); if (res >= 0) continue; if (res != NFC_ERFTRANS) { @@ -457,7 +455,15 @@ namespace { /* * Read NTAG21x sector (4 blocks, 16 pages, or 64 bytes). * - * NOTE: Device document: http://www.nxp.com/documents/data_sheet/NTAG213_215_216.pdf + * Args: + * start sector #: int + * + * Returns: + * tag object: dictionary + * + * NOTE: + * Device document: http://www.nxp.com/documents/data_sheet/NTAG213_215_216.pdf + * */ NAN_METHOD(NFC::ReadSector) { NFC* baton = ObjectWrap::Unwrap(info.This()); @@ -532,7 +538,6 @@ namespace { //printf("Reading sector of device %s:%s with tag: %s\n", tag->deviceID, tag->name, tag->tag); //printf("tag data: %s\n", tag->data); - //Local ret = Object::New(isolate, tag); Local object = Nan::New(); tag->AddToNodeObject(object); delete tag; @@ -542,9 +547,15 @@ namespace { break; } } + /* - * Write blocks to NFC card - * TODO: Refactor with `AsyncProcessWorker` + * Write tag data synchronously. + * + * Args: + * tag data: node buffer object. + * + * Returns: + * The number of pages written: int */ NAN_METHOD(NFC::Write) { Nan::HandleScope scope; @@ -767,7 +778,6 @@ namespace { info.GetReturnValue().Set(object); } - NAN_MODULE_INIT(init) { Local tpl = Nan::New(NFC::New); tpl->SetClassName(Nan::New("NFC").ToLocalChecked()); From 48a5cd311f8aebb5df2690f9129a1063f826c1a7 Mon Sep 17 00:00:00 2001 From: lexon Date: Fri, 22 Jul 2016 13:51:09 -0400 Subject: [PATCH 6/6] Added support for parsing manufacture block --- index.js | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/index.js b/index.js index 01536d1..f97070e 100644 --- a/index.js +++ b/index.js @@ -41,6 +41,45 @@ exports.nfc.parse = function(data) { return results; }; +//------------------------------------------------------------------------------ +// +// manublk (Buffer): the manufacture block. +//------------------------------------------------------------------------------ +exports.nfc.parseManufactureBlk = function(manublk) { + var i, manudata, uid, lock, cc; + manudata = {}; + uid = []; + lock= Array(2); // lock bytes + cc = []; // Capability container + + for (i=0; i<=2; i++) { + uid.push(manublk[i]); + } + for (i=4; i<=7; i++) { + uid.push(manublk[i]); + } + manudata.uid = uid; + + manudata.cb0 = manublk[3]; // Check byte 0: CT(0x88) ^ SN0 ^ SN1 ^ SN2 + manudata.cb1 = manublk [8]; // Check byte 1: SN3 ^ SN4 ^ SN5 ^ SN6 + + manudata.internal = manublk[9]; + + lock[0] = manublk[10]; + lock[1] = manublk[11]; + manudata.lock = lock; + + for (i=12; i<16; i++) { + cc.push(manublk[i]); + } + manudata.cc = cc; + + return manudata; + +} + + + exports.nfc.scan = function() { var device, devices, i, info, j, k, kv, mod, mods, prop, props, protocol, results, speeds, v, x;