ibrahim
ibrahim

Reputation: 205

Reading ISO15693 RFID tag through Android NFC results in incorrect data output

We have some ISO15693 tags that we used to read using an RFID reader. Today I started working on a sample application on Android to read the same tags using NfcV with Android 6 (API 23).

I was able to read some data from the tag but the data has some unexpected characters. This is the code I used:

private void readTagData(Tag tag) throws Exception {
    byte[] id = tag.getId();
    String strTag = new String(id, "UTF-8");
    boolean techFound = false;
    for (String tech : tag.getTechList()) {
        if (tech.equals(NfcV.class.getName())) {
            techFound = true;
            NfcV nfcvTag = NfcV.get(tag);
            try {
                nfcvTag.connect();
            } catch (IOException e) {
                Toast.makeText(this, "IO Exception", Toast.LENGTH_LONG).show();
                return;
            }
            try {
                int offset = 0;  
                int blocks = 19;  
                byte[] cmd = new byte[]{
                        (byte)0x60,                  
                        (byte)0x23,                  
                        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,  // placeholder for tag UID
                        (byte)(offset & 0x0ff),      
                        (byte)((blocks - 1) & 0x0ff)
                };
                System.arraycopy(id, 0, cmd, 2, 8);
                byte[] response = nfcvTag.transceive(cmd);

                response = Arrays.copyOfRange(response, 0, 96);
                String strData = new String(response, "UTF-8");
                mTextView.setText("TAG:" + strTag + " DATA:" + strData);
            } catch (IOException e) {
                Toast.makeText(this, "An error occurred while reading", Toast.LENGTH_SHORT).show();
                return;
            }

            try {
                nfcvTag.close();
            } catch (IOException e) {
                Toast.makeText(getApplicationContext(), "Unable to close the connection!", Toast.LENGTH_SHORT).show();
                return;
            }
        }
    }
}

Output

Tag ID (UTF-8 decoded): {��WP�

Data (UTF-8 decoded): ����1ead��1234��5678��5000��00B1��2345��6181��5064��1602��2016��1603��2016��1602��2018��0011��8899��0002��0920��16����

Data bytes in hexadecimal representation:

0000316561640031 3233340035363738
0035303030003030 42310032333‌43500
363138310035303‌6 3400313630320032
303‌1360031363033 0032303‌136003136
30320032303‌13800 303031310038383‌9
3900303030320030 393‌​2300031360000

Now part of this data is correct but I am not sure why these "�" characters are there. Tag ID is also not correct.

Separately I tried to convert the byte array 'response' and Tag ID to hex string and then to ASCII with the same result.

Upvotes: 1

Views: 2404

Answers (1)

Michael Roland
Michael Roland

Reputation: 40831

The value that you receive is the expected response for the command that you send:

You send the command READ MULTIPLE BLOCKS (command code 0x23) parametrized to read 19 blocks starting at offset 0. The block size of your tag seems to be 4 bytes.

Moreover, you specify a flags byte of 0x60, which translates to the flags Address_flag and Option_flag. The Address_flag makes the command addressed (i.e. you have to specify the UID of the target tag, which you properly do). The Option_flag makes the tag return the block security status in addition to the block data itself. Consequently, the response from your tag looks like this:

+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-...-+--------+-------+-------+-------+-------+
| FLAGS | BSS_0 | BLOCK_DATA_0                  | BSS_1 | BLOCK_DATA_1                  | ... | BSS_18 | BLOCK_DATA_18                 | 
+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-...-+--------+-------+-------+-------+-------+

The first byte, the response flags, indicate the overall outcome of the command (e.g. 0x00, as in your case, means success). Due to the Option_flag, each block of data is prepended with a BSS_x byte (the block security status), which seems to be 0x00 for all of the blocks.

Since you don't seem to be interested in the block security status, you might just as well use the command without the Option_flag (flags = 0x20):

byte[] cmd = new byte[]{
        (byte)0x20,                  
        (byte)0x23,                  
        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,  // placeholder for tag UID
        (byte)(offset & 0x0ff),      
        (byte)((blocks - 1) & 0x0ff)
};

Then, the response will be:

+-------+-------+-------+-------+-------+-------+-------+-------+-------+-...-+-------+-------+-------+-------+
| FLAGS | BLOCK_DATA_0                  | BLOCK_DATA_1                  | ... | BLOCK_DATA_18                 | 
+-------+-------+-------+-------+-------+-------+-------+-------+-------+-...-+-------+-------+-------+-------+

Consequently, in order to extract the data blocks from the response, you could then use:

response = Arrays.copyOfRange(response, 1, 4 * blocks);

Finally, decoding the tag ID into UTF-8 does not make sense at all for ISO/IEC 15693 tags. I'm not sure what value you would expect there but probably you wanted to simply convert the bytes of the ID into their hexadecimal representation.

Upvotes: 3

Related Questions