Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android responds to PN532 InListPassiveTarget

I have a weird situation where I'm trying to toggle my PN532 between tag emulation and tag reader mode. The reader goes for ~70ms and the tag emulation runs for ~600ms.

What I want to happen is that when I put my Android device near the antenna, that it reads the emulated tag. When I hold an NFC tag to the PN532, it's supposed to read the tag.

The solution I have is somewhat working but I'm seeing a weird situation where when I call readPassiveTargetID to test for the presence of passive tags, Android is responding. This would be fine but I think that Android is spinning up a service which blocks it from reading the emulated tag.

When testing this out, sometimes the devices don't communicate at all with the PN532 but when they do it's most often with the reader mode. Here is the output I get when this happens:

Nexus 5x (Android 6):

<< 4A 1 0
>> 4B 1 1 0 4 60 4 1 2 3 4 5 78 80 71 0

Galaxy S4 (Android 5.0.1):

<< 4A 1 0
>> 4B 1 1 0 4 20 4 8 87 F6 62 5 78 B3 70 2

The 5x will often read the emulated tag after a second or so but the S4 rarely reads the tag when I am toggling between the two modes. When I just run tag emulation both devices work flawlessly.

I'm thinking that there might be a few problems with what I'm doing.

  1. Do I need to do something special to toggle between the modes? I don't actually reset or reinitialize the PN532 when I toggle.
  2. Is there a command I can send to tell the devices to stop listening or a setting I can send that will fix this?
like image 686
John Kalberer Avatar asked Oct 31 '22 03:10

John Kalberer


1 Answers

The solution I have is somewhat working but I'm seeing a weird situation where when I call readPassiveTargetID (InListPassiveTarget) Android is responding.

That's not a weird situation but something that is to be expected when you try to access an NFC device from any ISO/IEC 14443A reader. An NFC device typically supports

  • reader/writer mode (i.e. it polls for passive tags),
  • peer-to-peer mode (i.e. it polls and listens for other peer-to-peer mode targets), and
  • (sometimes) card emulation mode (i.e. it listens for activation by other reader/writer devices).

When the NFC device polls for tags, this is usually similar to what InListPassiveTarget does, with the difference that it will typically test for various different tag technologies (NFC-A = ISO/IEC 14443A, NFC-B = ISO/IEC 14443B, NFC-F = JIS X 6319-4, and NFC-V = ISO/IEC 15693). Since passive peer-to-peer mode is based on ISO/IEC 14443A and JIS X 6319-4, it will also automatically discover passive peer-to-peer targets with the tests for NFC-A and NFC-F. Moreover, it will test for other peer-to-peer devices (ISO/IEC 18092 active mode).

When the NFC device listens for activation by other devices (peer-to-peer or reader/writer mode), it will allow activation with the various options defined in ISO/IEC 18092. Since these sub-protocols are based on NFC-A and NFC-F, an NFC device that supports both passive peer-to-peer mode and card emulation mode will typically combine the listening "phases" for both into a single activatable target.

And that is exactly what you see: A device that that supports ISO/IEC 14443A and ISO/IEC 18092 passive mode at 106kbps. Both of these protocols use the anticollision and selection procedure from ISO/IEC 14443A. In order to simplify discovery, the NFC device combines both, card emulation mode and peer-to-peer mode into one single visible target (i.e. one "card" with one UID).

You can see this clearly from the parameter values received during activation (specifically the SAK/SEL_RES byte). This byte is 0x60 for the Nexus 5X which indicates that this target supports ISO/IEC 14443-4 (Type A) with bit 5 set and ISO/IEC 18092 passive at 106kbps with bit 6 set.

Note that Samsung on their Galaxy S4 decided not to announce peer-to-peer mode support in the SAK byte (0x20), probably due to problems with some credit card payment terminals.

This would be fine but I think that Android is spinning up a service which blocks it from reading the emulated tag.

It's actually not a service spinning up but Android intentially introducing a timeout. Once an Android device was activated in peer-to-peer or card emulation mode, an Android device will wait for approximately 4 seconds after the external reader turned off its HF field, before it re-starts polling for tags. This is at least what we measured for Nexus devices using libnfc-nci. Samsung is known for extensively modifying the NFC stack implementation (usually introducing a lot of additional bugs (features?)), thus this might be slightly different on the S4.

Do I need to do something special to toggle between the modes? I don't actually reset or reinitialize the PN532 when I toggle.

You are probably doing what you should/could do. It's an intentional timeout (4 seconds after field-off) on the Android side that causes what you experience.

Is there a command I can send to tell the devices to stop listening or a setting I can send that will fix this?

Unfortunately, that's usually not that easy. A few things that you could do:

  • Do you really need reader/writer mode on the Android phone? If you could implement all the functionality that you need on the Android side with host-card emulation (HCE), you could implement your PN532 side to only operate in reader/writer mode. This would eliminate the switching between two modes and you would no longer be affected by the timeout. Unfortunately, this would limit you to devices that support Android HCE (Android 4.4+ and certain newer NFC chipsets). Moreover, some things like automatically installing the app if missing (through an Android Application Record, AAR) is not possible then. You could still launch an activity of your app when a reader communicates with your HCE service though (see How can I send message from HostApduService to an activity?).

  • You could increase the time that the PN532 is in card emulation mode to ~5 seconds (some value significantly larger than the timeout mentioned above). Then Android should (quite) reliably detect the emulated tag even if it was activated in card emulation mode/as passive peer-to-peer mode target before. Unfortunately, a 5 second wait time before the PN532 is capable of detecting a passive tag is typically not acceptable in terms of user-experience for the case where the PN532 should read NFC tags/contactless-smartcards.

  • If your app only needs to be able to communicate with the PN532 while an activity of your app is in the foreground (i.e. when users manually open the app before they try to interact with the PN532 side), you could disable P2P mode using the reader-mode API (see NfcAdapter.enableReaderMode(). This again restricts you to devices running Android 4.4+ (though supported across all NFC chipsets). I doubt that this would be much of a benefit over using HCE on the Android side though since the problems are back there when a user tries to tap the PN532-side with their phone in order to automatically open the app or to get the app installed (through an AAR).

like image 164
Michael Roland Avatar answered Nov 11 '22 12:11

Michael Roland