Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android NFC writeNdefMessage throws IOException Tag is not ndef

Tags:

android

nfc

ndef

I'm developing a NFC environment consisting of a tag (AS3953 chip + microcontroller) and a smartphone (Samsung Galaxy Fame runnung Android 4.1.2).

While reading a NDEF message works I'm stuck on writing the message to the tag. I copied most of the code from http://tapintonfc.blogspot.de/2012/07/the-above-footage-from-our-nfc-workshop.html and modified it to accept ISO14443A Tag Type 4 by searching the tag techlist for IsoDep, NfcA and Ndef in supportedTechs(). Since all of them are listed the app continues to writeTag():

public WriteResponse writeTag(NdefMessage message, Tag tag) {
try {
    Ndef ndef = Ndef.get(tag);
    if (ndef != null) {
        Log.d(TAG, "writeTag: tag type: "+ndef.getType());
        ndef.connect();
        Log.d(TAG, "writeTag: connected!");
        if (!ndef.isWritable()) {
            return new WriteResponse(0, "Tag is read-only");
        }
        if (ndef.getMaxSize() < message.toByteArray().length) {
            return new WriteResponse(0, "size error");
        }
        Log.d(TAG, "writeTag: write ndef...");
        ndef.writeNdefMessage(message);
        Log.d(TAG, "writeTag: wrote ndef!");
        if (writeProtect)
            ndef.makeReadOnly();
        return new WriteResponse(1, "Wrote message to pre-formatted tag.");
    } else {
        Log.d(TAG, "writeTag: ndef==null!");
        return new WriteResponse(0, "writeTag: ndef==null!");
    }
} catch (Exception e) {
    Log.d(TAG, "writeTag: exception: " + e.toString());
    return new WriteResponse(0, "Failed to write tag");
}
}

LogCat shows:

11:08:46.400: onNewIntent
11:08:46.400: supportedTechs: techlist: android.nfc.tech.IsoDep,android.nfc.tech.NfcA,android.nfc.tech.Ndef,
11:08:46.400: supportedTechs: tech is supported!
11:08:46.400: writeTag: tag type: org.nfcforum.ndef.type4
11:08:46.410: writeTag: connected!
11:08:46.410: writeTag: write ndef...
11:08:46.490: writeTag: exception: java.io.IOException: Tag is not ndef

As you can see an IOException is thrown saying the Tag is not ndef which contradicts the techlist. Looking further into the android code writeNdefMessage() tries to get a TagService and a ServiceHandle from the tag to match them against. This fails so the exception is thrown (no message written up to now):

public void writeNdefMessage(NdefMessage msg) throws IOException, FormatException {
...
INfcTag tagService = mTag.getTagService();
...
int serviceHandle = mTag.getServiceHandle();
if (tagService.isNdef(serviceHandle)) {
    ...
}
else {
    throw new IOException("Tag is not ndef");
}
...
}

Is there a workaround for that or is it not possible at all with my kind of tag? As I'm also programming the tag the error might be on the other side, but it seems to be a Java problem.


Edit 1:

I don't connect to any technology before so there shouldn't be any opened connection. If I open an connection before ndef.connect() there is IllegalStateException: Close other technology first!

I configured AS3953 to ISO14443A Level-4 so only Tag Type 4 Blocks are forwarded to the microcontroller. Only I-Blocks are handled but even if there are other commands the µC has to read it out over the SPI port which isn't the case by logic analysis. As I said reading the ndef file works and I tested it for a 4KB file. Looking at the logic analysis the following steps are made (all returning a positive 9000-code):

(c=command, r=response) (corrected due to renaming mistake)
select by name:
c: 02 00 a4 04 00 07 d2 76 00 00 85 01 01 00
r: 02 90 00
select by id - select cc file
c: 03 00 a4 00 0c 02 e1 03
r: 03 90 00
read 0x0f bytes of cc file
c: 02 00 b0 00 00 0f
r: 02 00 0f 20 00 3b 00 34 04 06 e1 04 0f ff 00 00 90 00
select by id - select ndef file
c: 03 00 a4 00 0c 02 e1 04
r: 03 90 00
read 0x02 bytes (first 2 bytes are apdu-size)
c: 02 00 b0 00 00 02
r: 02 0f d3 90 00
read 0x3b bytes (frame size) of first part of ndef file (external type, jpeg image as payload)
c: 03 00 b0 00 02 3b
r: 03 c4 0c 00 00 0f c1 64 65 2e 74 65 73 74 61 70 70 3a 61 01 ff d8 ff e0 00 10 4a 46 49 46 00 01 01 01 00 60 00 60 00 00 ff db 00 43 00 49 32 36 40 36 2d 49 40 3b 40 52 4d 49 56 6d 90 00
[ndef file]
read 0x26 bytes of last part of ndef file
c: 03 00 b0 0f ae 27
r: 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 FF D9 00 00 90 00

Using the same app for writing I start the activity which filters NfcAdapter.ACTION_TAG_DISCOVERED intents. Just as in the linked example the phone touches the tag calling onResume() doing mNfcAdapter.enableForegroundDispatch(...);

When I log the SPI communication the same reading procedure as above is done. Since LogCat shows a working intent dispatcher I guess the app stops at the IOException, closing the connection and immediately going over to read out as android found the tag again.


Edit 2:

There might be a hint as one of the first interrupts issue a deselect command which is handled by AS3953 itself:

(count * interrupt)
3 * power up 
1 * Wake-up IRQ at entry in ACTIVE(*) state 
1 * Deselect command
1 * Wake-up IRQ at entry in ACTIVE(*) state 
1 * IRQ due to start of receive
like image 227
Eric Avatar asked Apr 14 '14 09:04

Eric


1 Answers

It works now. I figured out that a startup routine which checks and sets the configuration word was transmitted with a too high baud rate for the AS3953. This worked for reading but something must have been mixed up for writing to the tag.

I cannot tell for sure if this is the only reason why it didn't work. There is also a problem with slow reading of the 32Byte FIFO as waterlevel interrupts are handled too late - I simply expected the problem to be on the android side since I couldn't find the write command in the logic analysis and the exception didn't describe the reason enough.

Thanks a lot to Michael Roland for further debugging, I still don't unterstand why the tag is read at first if I want to write to it but well - there should be a workaround reading an empty ndef message so the writing process will be done quickly.

For now I have to work on the firmware and cannot forecast any further problems but the actual issue (ndef.writeNdefMessage()) returns successfully.

like image 184
Eric Avatar answered Nov 10 '22 11:11

Eric