Search code examples
node.jsnfcsmartcard-readerpcscnode-usb

Talking to ACR1252U NFC Card Reader via Node.js


I am trying to communicate with an ACR1252U NFC card reader (http://www.acs.com.hk/en/products/342/acr1252u-usb-nfc-reader-iii-nfc-forum-certified-reader/) using Node.js and the https://github.com/nonolith/node-usb NPM module.

I have created a simple script to get the reader USB device and listen for events.

When an NFC card comes in contact with the reader I receive a buffer:

<Buffer 50 03>

When the NFC card is taken away from the read I receive a buffer:

<Buffer 50 02>

This indicates that I am at least able to get some basic communication with the reader working.

My problem now is I am trying to get information about the NFC card when it comes in contact with the reader. I have tried to send data to the reader but cannot get a consistent response (sometimes I get a buffer response and sometimes I don't, running the same command over and over).

I decided to simplify the command I was sending to just turn on and off the reader's internal buzzer so I looked at the API documentation (http://www.acs.com.hk/download-manual/6402/API-ACR1252U-A1-1.07.pdf) which says that to activate the buzzer you send through:

E0h 00h 00h 28h 01h + 1 byte to determine duration of buzzer activation

With that in mind I created a buffer:

var buf = new Buffer(6);
buf.write('e00000280108', 'hex');

Then used the USB module's out endpoint to send the data:

outEndpoint.transfer(buf, function (err) {
    console.log('out transfer', err);
});

The console logs "out transfer" with no error but nothing is received from the "in" endpoint.

If I create a 64 byte buffer instead:

var buf = new Buffer(64);
buf.write('e00000280108', 'hex');

outEndpoint.transfer(buf, function (err) {
    console.log('out transfer', err);
});

I receive a response from the "in" endpoint:

<Buffer e0 00 00 00 00 01 00 42 ff 00>

This doesn't seem to correspond to what is expect from the manual and doesn't activate the buzzer at all.

I'm very new to directly communicating with USB devices like this and my last experience of this type was sending AT commands to modems back in the day :)

Could anyone shed any light on what I am doing wrong? I figure that sending 64 bytes instead of 6 has something to do with the USB standard requiring a set length or something like that?!? Has anyone else had experience communicating with an NFC reader (non-HID) with Node.js? Ultimately all I want to do is be able to write some data to an NFC tag and read it back later on when the tag is presented.

I thought it would be a pretty simple process but I'm stumped! Maybe I should be encoded the data differently? Maybe I'm not terminating the data properly? I just don't know!

I tried increasing the buffer size by 1 and adding a \0 terminator to the buffer via:

buf.write('\0', 6, 'utf-8');

But that didn't make any difference at all.

Thanks!


Solution

  • The commands described in the API specification are (pseudo) APDU commands to be exchange with the reader over PC/SC. When you access the reader directly through USB without a PS/SC abstraction layer (see http://www.pcscworkgroup.com/specifications/overview.php), you have to implement that abstraction yourself. Therefore, you have to implement the USB CCID (chip card interface device) class interface yourself. Essentially, this means that you have to encapsulate APDU commands in the CCID protocol. You can fin the specification here: http://www.usb.org/developers/docs/devclass_docs/