0
votes

I'm working on an application about NFC writing. Lets call it Writer... I am writing data to a NfcV tag.

The string I am trying to write is String test = "this is\ta real\ttestcase\tyou tag";

To write data I'm using NfcV's transceive method. So this is my writer-method:

public static String bytesToHex(byte[] bytes) {
    StringBuilder sb = new StringBuilder(bytes.length * 2);
    Formatter formatter = new Formatter(sb);
    for (byte b : bytes) {
        formatter.format("%02X", b);
    }
    formatter.close();
    return sb.toString();
}

public void write(View v) {
    try {
        String[] tagInfoArray = new String[tagData.size()];
        for (int i = 0; i < tagData.size(); i++)
            tagInfoArray[i] = tagData.get(i).getText().toString();

        String tagInfo = join(tagInfoArray, "\t");
        //String test = "this is\ta real\ttestcase\tyou tag";
        writeTag(tag, tagInfo);
    } catch (NullPointerException e) {
        Toast.makeText(this, "How about providing a tag!",
                Toast.LENGTH_LONG).show();
    } finally {
        write.setBackgroundResource(R.layout.bluebutton);
    }
}

public String join(String[] input, String delim) {
    String output = "";
    if (input.length > 0)
        output += input[0];
    if (input.length > 1)
        for (int i = 1; i < input.length; i++)
            output += delim + input[i];
    return output;
}

public void exitButton(View v) {
    this.foreground.disableForeground();
    System.exit(0);
}

public void writeTag(Tag tag, String data) {
    NfcV myTag = NfcV.get(tag);
    try {
        myTag.connect();
        if (myTag.isConnected()) {
            byte[] info = data.getBytes();
            int dataLength = info.length;
            if (data.length()/4 <= 64){ 
                byte[] args = new byte[15];
                args[0] = 0x20;
                args[1] = 0x21;
                byte[] id = tag.getId();
                for (int o=0; o<8; o++)
                    args[o+2] = id[o];
                for (int i = 0; i<64; i++) {
                    args[10] = (byte) i;
                    args[11] = 0x00;
                    args[12] = 0x00;
                    args[13] = 0x00;
                    args[14] = 0x00;
                    byte[] out = myTag.transceive(args);
                    String out2 = bytesToHex(out);
                    System.out.println("1:.. " + printHex(out2));
                }
                for (int i = 0; i<=dataLength/4; i++) {
                    args[10] = (byte) i;
                    args[11] = getByte(info, (i*4)+0);
                    args[12] = getByte(info, (i*4)+1);
                    args[13] = getByte(info, (i*4)+2);
                    args[14] = getByte(info, (i*4)+3);
                    byte[] out = myTag.transceive(args);
                    String out2 = bytesToHex(out);
                    System.out.println("2:.. " + printHex(out2));
                }
            }
        }
    } catch (IOException e) {
        System.out.println(e.getMessage());
    } finally {
        if (myTag != null) {
            try {
                myTag.close();
            } catch (IOException e) {
                System.out.println(e.getMessage());
            }
        }
    }
}

public static byte getByte(byte[] input, int key){
    try {
        return input[key];
    } catch (Exception e){
        return (byte)0x00;
    }
}

public String printByte(byte[] input){
    try {
        return new String(input, "UTF-8");
    } catch (UnsupportedEncodingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return "";
}

public String printHex(String input){
    return input;
}

So when im writing stuff the outcome is not what I am expecting it to be. It's either not writing at all, or just writing parts, while not overwriting, what has been on the tag before.

This is the output:

11-05 15:32:33.139: I/System.out(1390): 1:.. 00
11-05 15:32:33.249: I/System.out(1390): 1:.. 00
11-05 15:32:33.349: I/System.out(1390): 1:.. 00
11-05 15:32:33.449: I/System.out(1390): 1:.. 00
11-05 15:32:33.549: I/System.out(1390): 1:.. 00
11-05 15:32:33.649: I/System.out(1390): 1:.. 00 
11-05 15:32:33.759: I/System.out(1390): 1:.. 00
11-05 15:32:33.859: I/System.out(1390): 1:.. 00
11-05 15:32:33.959: I/System.out(1390): 1:.. 00
11-05 15:32:34.059: I/System.out(1390): 1:.. 00
11-05 15:32:34.159: I/System.out(1390): 1:.. 00
11-05 15:32:34.259: I/System.out(1390): 1:.. 00
11-05 15:32:34.359: I/System.out(1390): 1:.. 00
11-05 15:32:34.469: I/System.out(1390): 1:.. 00
11-05 15:32:34.569: I/System.out(1390): 1:.. 00
11-05 15:32:34.669: I/System.out(1390): 1:.. 00
11-05 15:32:34.769: I/System.out(1390): 1:.. 00
11-05 15:32:34.869: I/System.out(1390): 1:.. 00
11-05 15:32:34.979: I/System.out(1390): 1:.. 00
11-05 15:32:35.079: I/System.out(1390): 1:.. 00
11-05 15:32:35.179: I/System.out(1390): 1:.. 00
11-05 15:32:35.289: I/System.out(1390): 1:.. 00
11-05 15:32:35.389: I/System.out(1390): 1:.. 00
11-05 15:32:35.489: I/System.out(1390): 1:.. 00
11-05 15:32:35.589: I/System.out(1390): 1:.. 00
11-05 15:32:35.689: I/System.out(1390): 1:.. 00
11-05 15:32:35.789: I/System.out(1390): 1:.. 00
11-05 15:32:35.889: I/System.out(1390): 1:.. 00
11-05 15:32:35.989: I/System.out(1390): Transceive failed
2
What results do you receive for the transceive()-method? What tag (manufacturer, type) do you use? Does it support the write single block command with option_flag = 0? Is the memory programmable multiple times?Michael Roland
Result: "Transceive failed", tag:(Infineon Technologies Ag, Type V)Torhan Bartel
"Type V" is not really helpful. A product name would help...Michael Roland
Regarding the transceive failed error: does this happen while sending the first command or only after addressing a specific block?Michael Roland
Btw. myTag.getMaxTransceiveLength() does not provide the memory size of the tag but the transceive buffer size, so you definitely do not want to use it as the upper bound of that for-loop.Michael Roland

2 Answers

2
votes

To summarize the various issues in the initial post:

  • Reading or writing from/to blocks bejond the tag size will result in IOExceptions caused by the tag stopping to respond.
  • NfcV.getMaxTransceiveLength() returns information about the maximum number of bytes that can be exchanged in one command/one response. It does not provide information about the tag size!.
  • Unfortunately there is no one-for-all approach to detect the actual size of a tag. A possible approach would be to try to detect the type of tag (many NfcV tags encode the exact tag type into their ID, so you could use Tag.getId() to get the ID and parse it according to the tag manufacturers' data sheets). Another approach is to read until the first IOException and infer the tag size from that information. You can later reconnect the tag to continue reading/writing. However, keep in mind that any other interruptions in communication (e.g. the user not properly scanning the tag) may also lead to IOExceptions and may consequently falsify your estimated tag size.
  • The block index parameter of the ISO/IEC 15693 read/write single block commands is in blocks and not in bytes.
1
votes

Don't know for the Infineon Technologies, but for NXP ICODE and TI tags (ISO15693) exists the Get System Information command. I'll attach an image with the response bytes. In this example the number of blocks is 0x3F + 1. The 0x03 + 1 is the number of bytes per block. So 3f=63 and 03=3, total memory = (63+1)*(3+1) = 256bytes

Response to Get system information command

I use it like this (I'm sending an addressed command, with the tag id included in the command, but it's not necessary):

        nfcV = NfcV.get(tag);
        byte[] id = tag.getId();

        if (nfcV != null) {

            byte[] infoCmd = new byte[2 + id.length];
            // set "addressed" flag
            infoCmd[0] = 0x20; 
            // ISO 15693 Get System Information command byte
            infoCmd[1] = 0x2B;
            //adding the tag id
            System.arraycopy(id, 0, infoCmd, 2, id.length); 

            int memoryBlocks = null; 
            try {
                nfcV.connect();
                byte[] data = nfcV.transceive(infoCmd);

                memoryBlocks = Integer.parseInt(String.format("%02X", data[data.length-3]), 16);

            }
            catch (IOException e) {
                e.printStackTrace();
            } 
            finally {
                try {
                    nfcV.close();
                } 
                catch (IOException e) {
                    e.printStackTrace();
                }
            }