NFC with the Nexus S and ACR122 Reader

The norwegian Computerworld published an article about a project in which I am involved. The project is part of the current research of Mohammad Derawi, a PhD student from Gjøvik/Norway. The goal of the project is to combine biometric (gait) authentication and token based authentication via NFC.

I have been working on the NFC part in my spare time. We had access to a Google Nexus S smartphone (which is the first android phone with NFC technology) and an ACR122 NFC Reader from Advanced Card Systems Ltd. We used the latest android version (2.3.4) and SDK. On the desktop side we used libnfc and libnfc-llcp (which is a work in progress). The following section provides a short description of how to set up a one-way communication from the phone to the reader.

Google uses the NDEF Push Protocol (NPP) for communication between NFC devices. ANPP packet is wrapped as a NDEF Record in a NDEF packet, which itself is transmitted in a LLCP packet as the payload of the Information PDU (the LLCP and NDEF specifications are freely available on the specs pages of the NFCForum).

The android SDK provides a straight-forward way to create NDEF messages. First you need to add a “Use Permission” item to your manifest and if you want to publish your application on the android market a “Uses Feature” item:

<uses-feature android:name="android.hardware.nfc" android:required="true"/>
<uses-permission android:name="android.permission.NFC"/>

All you have to do now is to create a new NdefRecord and use it to initialize a NdefMessage. Google provides example code on how to create a standard text record (Type Name Format or TNF is well_known, the Record Type Definition or RTD is RTD_TEXT). The following example creates such a NdefMessage and initializes the foreground push feature with it:

NfcManager nfcm = (NfcManager) getSystemService(NFC_SERVICE);
mAdapter = nfcm.getDefaultAdapter();
myNdefMessage = new NdefMessage(new NdefRecord[] { newTextRecord("mymsg", Locale.ENGLISH, true) });
mAdapter.enableForegroundNdefPush(this, myNdefMessage);

The newTextRecord method converts the message to an appropriate encoding. The phone now automatically sends the NdefMessage as soon as a LLCP link is established. The activity which enabled the NdefPush feature has to be active in the foreground though. This restriction also applies to the reading of NFC tags.

On the desktop side we had to build and install libnfc, libnfc-llcp, the acsccid driver from ACS and the following dependencies/required packages (using apt-get and standard ubuntu repositories):

  • autotools (packages: autoconf, automake, libtool)
  • libusb-dev
  • libpcsclite-dev
  • opensc
Further you need to install PCSC-Lite. We had problems with the latest version, so use an older version if you experience the same (1.7.0 worked for us). As part of building the libnfc-llcp you also get a demo program which can be found in tools/llcp-test-server/ . The binary can be found in the .libs subfolder. We removed the reply code from the connected-echo-server.c file in the PDU_I case of the switch statement and parsed the information field of the PDU instead:
for(int i=19; i < pdu->information_size; i++)
{
	printf("%c",((char)pdu->information[i]));
}
As you might have noticed, there is an offset of 19 bytes, which corresponds to the cumulated size of the NdefRecord (Short Record Format in our case) and NPP headers. In the llcp-test-server.c file you have to change the URI of the new service as demonstrated here:
struct llc_service *co_echo_service = llc_service_new_with_uri (connected_echo_server_accept, connected_echo_server_thread, "com.android.npp ");
Put a comment around the service registration for the connectionless server and change the rest of the source to reflect that. Start the server with the following command:
./llcp-test-server --mode=target
We could not get the reader to work properly in initiator mode, which is due to the limited time available on this project. If you know how to do that or have suggestions or corrections, then please leave a comment. You should now be able to receive NDEF messages sent by the Nexus S. I hope you found this small tutorial helpful.

 

3 thoughts on “NFC with the Nexus S and ACR122 Reader

  1. Pingback: Derawi Biometrics » Open Door with a Smart-Phone and Fingerprint

  2. Hi,
    This is a great and helpfull guide!!

    What OS you used to do the build/installation of the necessary libnfc & libnfc-llcp ant their dependent packages?

    Could you please exlain a little bit more about this part “Put a comment around the service registration for the connectionless server and change the rest of the source to reflect that. “?

    Thanks a lot in advance.

    • Hi Franky,

      we used Ubuntu 11.04 with all the latest updates and patches.
      We’re using connection-oriented communication over LLCP, thus only registering the com.android.npp service for the connection oriented server. Just search for the llc_service_new_with_uri function call in the llcp-test-server.c file and look at the parameters to spot the line referencing the connectionless server thread.
      If you put a comment around the service registration for the connectionless server, you will get a compiler error because the llc_service struct is not defined then. You can fix that by removing all references to the cl_echo_service structure in the source.