Question

I'm trying to implement different NfcV-commands on an Android phone (Nexus 4). Currently, I'm using these tags. According to the datasheet, they should support the "Be Quiet"-command.

Unfortunately, I can't get the source code below to work correctly. I'd expect the "Inventory" and "Read Single Block" commands after the "Stay Quiet" command to fail because both commands are unaddressed, which a tag in the Quiet state should ignore. But I still get the correct answer containing UID or payload from the tag.

Also, I get a "Tag was lost" exception by executing the "Stay Quiet" command. However, according to ISO 15693-3 the tag should give no response to this command, which could lead to this exception, anyway.

Still, I'm guessing something's wrong with the "Stay Quiet" command in this code but I can't figure out what.

Any help is appreciated.

Source Code:

            NfcV nfcv = NfcV.get(mtag);


                try{
                    nfcv.connect();                                                             //Connect
                } catch(IOException e){
                    mUIDs = mUIDs + "\nConnection Error 1";
                }


                byte[] response1 = {(byte) 0x00};
                try{
                    byte[] UIDreq1 = InventoryRequest();                                        //Inventory Request
                    response1 = nfcv.transceive(UIDreq1);
                } catch(IOException e){
                    mUIDs = mUIDs + "\nInventory Error 1";
                }
                mUIDs = mUIDs +"\n" + bytesToHex(response1);
                byte[] UID = response2UID(response1);
                mUIDs = mUIDs + "\n" + bytesToHex(UID);


                try{
                    byte[] command = ReadSingleBlockUnadressed((byte) 0x04);                    //Reading Single Block
                    byte[] data = nfcv.transceive(command);
                    mUIDs = mUIDs +"\n"+bytesToHex(data);
                }catch(IOException e){
                    Log.e("Reading Single Block", e.getMessage());
                    mUIDs = mUIDs + "\nReading Error";
                }


                try{
                    try{
                        byte[] command = StayQuiet(UID);                                        //Stay Quiet, SHOULD FAIL
                        nfcv.transceive(command);
                    }catch(TagLostException e){
                        Log.e("Stay Quiet", e.getMessage());
                        mUIDs = mUIDs + "\nTag was lost.";
                    }
                    }catch(IOException x){
                    mUIDs = mUIDs + "\nStay Quiet Error";
                }


                try{
                    byte[] command = ReadSingleBlockUnadressed((byte) 0x04);                    //Reading Single Block
                    byte[] data = nfcv.transceive(command);
                    mUIDs = mUIDs +"\n"+bytesToHex(data);
                }catch(IOException e){
                    Log.e("Reading Single Block", e.getMessage());
                    mUIDs = mUIDs + "\nReading Error";
                }

                try{
                    byte[] UIDreq2 = InventoryRequest();                                        //Inventory Request, SHOULD FAIL
                    byte[] response2 = nfcv.transceive(UIDreq2);
                    mUIDs = mUIDs +"\n" + bytesToHex(response2);
                } catch(IOException e){
                    mUIDs = mUIDs + "\nInventory Error 2";
                }


                try{
                    nfcv.close();                                                               //Disconnect
                } catch(IOException x){
                    mUIDs = mUIDs + "\nDisconnection Error 1";
                }


                mTagTextView.setText(mUIDs);

With the following functions:

final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
    char[] hexChars = new char[bytes.length * 2];
    int v;
    for ( int j = 0; j < bytes.length; j++ ) {
        v = bytes[j] & 0xFF;
        hexChars[j * 2] = hexArray[v >>> 4];
        hexChars[j * 2 + 1] = hexArray[v & 0x0F];
    }
    return new String(hexChars);
}
private byte[] response2UID(byte[] response){
    byte[] UID = new byte[response.length-2];
    for(int i = 2; i < response.length; i++){
        UID[i-2]=response[i];
    }
    return UID;
}

private byte[] ReadSingleBlockUnadressed(byte blocknumber){
    return new byte[] {(byte) 0x00, (byte) 0x20, blocknumber};
}
private byte[] StayQuiet(byte[] UID){
    byte[] beQuiet = new byte[] {(byte) 0x04, (byte) 0x02}; 
    byte[] command = combine(beQuiet, UID);
    return command;
}

private byte[] InventoryRequest(){
    return new byte[] { (byte) 0x24, (byte) 0x01, (byte) 0x00};
}
Was it helpful?

Solution

When you're sending the STAY QUITE command you bring the tag from selected to unselected state.

Then you're sending out the READ SINGLE BLOCK command with a flag value of 0x00.

According to the ISO/IEC 15693-3 standard this means that the Select_flag (Bit 5) is zero. The standard defines the usage of this bit as follows:

Bit 5 = 0: Request shall be executed by any VICC according to the
setting of Address_flag

Bit 5 = 1: Request shall be executed only by VICC in selected state

The Address_flag is defined here (it value is zero):

Bit 6 = 0: Request is not addressed. UID field is not present. It shall be
executed by any VICC.

Bit 6 = 1: Request is addressed. UID field is present. It shall be
executed only by the VICC whose UID matches the UID
specified in the request.

With the flags that you've used in your READ SINGLE BLOCK command you have instructed the tag to answer even if it is not selected. That's why it works.

For your use-case you want the Select_flag (Bit 5) to be one and the Address_flag zero.

I suggest that you take a look at the ISO/IEC 15693-3 standard. A copy of it can be found online here: http://www.waazaa.org/download/fcd-15693-3.pdf

Btw, you get the "Tag was lost" exception because the NFC Service is constantly checking for the presence of the tag. In the case of ISO15693 it probably does so by sending out an INVENTORY command behind your back since INVENTORY is one of the few commands that all ISO15693 tags understand.

You have no control about this, so it is likely that it will interfere with your tries to silence out the tag.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top