Communication problems with NTAG213

Asked by Tomasz Koperski on 2014-10-21

Hi,

I'm working with NXP NTAG213 using nfcpy. I am able to perform basic READ and WRITE operations, but I'm not able to perform any other commands.

The two commands working are:

READ (\x30)
WRITE (\xA2)

the ones that do not seem to work:

GET_VERSION (\x60)
FAST_READ (\x3A)
READ_CNT (\x39)
PWD_AUTH (\x1B)
READ_SIG (\x3C)

I've tried the simplest way to communicate with the tag, mentioned here: https://answers.launchpad.net/nfcpy/+question/248114 by Stephen. Code available here: http://pastebin.com/nJNkgpMj

When I use this method to read 16 bytes starting at block 0 (\x30\x00) with this code:

def readdemo(tag):
        uid = tag.uid
        data = tag.transceive("\x30\x00", timeout=0.2)
        print hexlify(uid), hexlify(data)

I get this: http://pastebin.com/qaPMw7js
It looks OK - I get proper 16 bytes of data read from the tag.

now if I use the same method for any of the mentioned other functions, like READ_SIG with this code:

def readsign(tag):
        uid = tag.uid
        sig = tag.transceive("\x3C\x00", timeout=0.2)
        print hexlify(uid), hexlify(sig)

I get this: http://pastebin.com/ZM2yiWte

The same goes for any other method mentioned. It always ends with
<<< 8000000000000000fe00
transmited from USB reader.

My reader is: http://pastebin.com/DMAuH0YR

output for 'nfc-list':
nfc-list uses libnfc libnfc-1.7.1
NFC device: ACS / ACR122U PICC Interface opened
1 ISO14443A passive target(s) found:
ISO/IEC 14443A (106 kbps) target:
    ATQA (SENS_RES): 00 44
       UID (NFCID1): 04 01 1e 3a 98 37 81
      SAK (SEL_RES): 00

Any idea what might be the problem here?

Question information

Language:
English Edit question
Status:
Solved
For:
nfcpy Edit question
Assignee:
No assignee Edit question
Solved by:
Tomasz Koperski
Solved:
2014-10-21
Last query:
2014-10-21
Last reply:
Tomasz Koperski (t-koperski) said : #1

We've played with it and were able to get around it by modifying nfc/dev/pn53x.py

The problem was caused by the fact, that for the mentioned commands nfcpy uses
self.chipset.in_data_exchange method, while it should use self.chipset.in_communicate_through

This changed the cmd_code from 0x40 to 0x42 while sending commands line PWD_AUTH or READ_SIG, which fixed the problem.

For now we're selecting the right method basing on the cmd_data value, for the command marked with [2] here: https://www.dropbox.com/s/vsbc0twg10mlz13/Screenshot%202014-10-21%2016.57.46.png?dl=0 (screen from NTAG213 documentation by NXP).

Many thanks for spotting this problem with pn53x based readers. I'll work out an update to use in_communicate_thru for tag reading.

corzand (acorzani) said : #3

Hello Tomasz,

I think I have the same issue trying to read the signature of NXP NTAG212!
https://answers.launchpad.net/nfcpy/+question/248114

Is it possible to have the updated code of nfc/dev/pn53x.py ?

Thanks again

Tomasz Koperski (t-koperski) said : #4

Hi there,

I've ended up with a quick fix in the command methind inside nfc/dev/acr122.py (I use the ACR122U reader).
Here's the changed definition of this function:

    def command(self, cmd_code, cmd_data=None, timeout=100):
        """Send a chip command and return the chip response."""
        cmd_name = "PN53x "+self.CMD.get(cmd_code, "0x{0:02X}".format(cmd_code))
        log.debug("{0} called with timeout {1} ms".format(cmd_name, timeout))

        if cmd_data is None: cmd_data = ""
 if len(cmd_data) > 1 and bytearray(cmd_data)[1] in [0x1B, 0x3C, 0x60, 0x39]:
   cmd_code = 0x42
   cmd_data = cmd_data[1:]
        frame = bytearray([0xD4, cmd_code]) + bytearray(cmd_data)
 # Temporary fix, nfcpy problem described here: https://answers.launchpad.net/nfcpy/+question/255995
 # Manually overriding cmd_code value to 0x42
 ### end fix
        frame = bytearray([0xFF, 0x00, 0x00, 0x00, len(frame)]) + frame

        frame = self.ccid_xfr_block(frame, timeout)
        if not frame or len(frame) < 4:
            log.error("insufficient data for decoding chip response")
            raise IOError(errno.EIO, os.strerror(errno.EIO))
        if not (frame[0] == 0xD5 and frame[1] == cmd_code + 1):
            log.error("received invalid chip response")
            raise IOError(errno.EIO, os.strerror(errno.EIO))
        if not (frame[-2] == 0x90 and frame[-1] == 0x00):
            log.error("received pseudo apdu with error status")
            raise IOError(errno.EIO, os.strerror(errno.EIO))
        return frame[2:-2]

I manually change the method code to 0x42 if I detect specific NTAG213 (will also work with NTAG212).
This is definitely not the best way to implement this change, but it was enough in my case.

corzand (acorzani) said : #5

Thank you Tomasz, this solved my problem

A comprehensive fix is on the way. You can try the development version with "bzr branch lp:~stephen-tiedemann/nfcpy/dev-tags", it'll give you improved handling of type 2 tags, authenticate(...) and protect(...) for Ultralight C and NTAG21x plus the signature bytes accessible with just "sig = tag.signature". The tagtool.py got parameters authenticate and protect with password, see the commit message at http://bazaar.launchpad.net/~stephen-tiedemann/nfcpy/dev-tags/revision/232 for some usage explanantion.

Eventually this will merge into trunk but there's still some other tags to do and to test.