1

We would like to read NDEF records as well as Tag ID from our tags coming from production using any suitable .Net library. But as far as I saw this kind of NXP ICode SLIX seems to be poorly supported in the .Net community.

Below are a couple of sample data screenshot from one of our tag, the first one helps to identify which kind of tag it is, the second one shows data we want to read underlined in red:

enter image description here enter image description here

We tried using several PC/SC lib like pcsc-sharp and Smart Card API from Cardwerk as well as sample code from UWP but our Identiv Multi-ISO reader seems to not operate APDU command to the card.

EDIT:

We have successfully tried an other RFID reader: an HID OmnyKey 5022 as suggested by a Cardwerk Engineer and NXP Support. It is working fine but only support Read Simple Block Command using pcsc-sharp.

However If you could share some experience in reading NXP ICode Slix memory tag, and in particular NDEDF message using any .Net library with a proper RFID Reader it will be much appreciated.

P.S.: This is an adapted version of a question asked at Software Recommendations and hesitate a bit before posting here because it may be too broad.

Guillaume Raymond
  • 1,726
  • 1
  • 20
  • 33

1 Answers1

1

To get things done I asked directly to NXP Support. So they advise me to choose from their known RFID hardware partner. HID and FEIG.

HID Ominkey with pcsc-sharp

First I successfully achieved reading memory using an HID Omnikey 5022 reader and this PC/SC .Net Lib from Github which is meanly a wrapper on winscard.dll. This combination is working great as there is a built-in support of event like card detection. The only inconvenient is it only supports read single block (4 bytes) so I had to code a kind memory parser like following :

    private const Byte RADIOID_BLOCK_START = 0x03;
    private const Byte RADIOID_BLOCK_START_OFFSET = 0x01;
    private const Byte RADIOID_LENGHT = 0x08;

    private const Byte MACADDRESS_BLOCK_START = 0x07;
    private const Byte MACADDRESS_BLOCK_START_OFFSET = 0x00;
    private const Byte MACADDRESS_LENGHT = 0x11;
    private const String MACADDRESS_EMPTYVALUE = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";


    private String GetRadioId(IIsoReader isoReader)
    {
        Byte[] radioId = ReadMultipleBlock(isoReader, RADIOID_BLOCK_START, RADIOID_BLOCK_START_OFFSET,RADIOID_LENGHT);
        String strData = Encoding.UTF8.GetString(radioId, 0, radioId.Length);

        Debug.WriteLine($"RadioId Data :{strData}");

        return strData;
    }


    private String GetMacAdress(IIsoReader isoReader)
    {
        Byte[] data = ReadMultipleBlock(isoReader,MACADDRESS_BLOCK_START, MACADDRESS_BLOCK_START_OFFSET, MACADDRESS_LENGHT);
        String strData = Encoding.UTF8.GetString(data, 0, data.Length);
        Debug.WriteLine($"MAC Data :{strData}");
        return strData;
    }


    private Byte[] ReadMultipleBlock(IIsoReader isoReader, Byte blockStart, Byte offset, Byte dataLength)
    {
        Byte[] dataRead = new Byte[dataLength];
        Byte currentBlock = blockStart;
        Byte index = 0;

        while (index < dataLength)
        {
            // Build a READ Single Binary Block command 
            CommandApdu cmdApdu = new CommandApdu(IsoCase.Case2Short, SCardProtocol.Any)
            {
                CLA = 0xFF,
                INS = 0xB0,
                P1 = 0x00,
                P2 = currentBlock,
                Le = 0x04
            };

            Debug.WriteLine($"<-- { BitConverter.ToString(cmdApdu.ToArray())}");
            Response response = isoReader.Transmit(cmdApdu);

            if (!response.HasData)
            {
                Debug.WriteLine(String.Format("No data. (Card does not understand \"ReadBinary\")"));
                return dataRead;
            }
            else
            {
                Byte[] data = response.GetData();
                Debug.WriteLine($"--> {Encoding.UTF8.GetString(data, 0, data.Length)}");
                Byte responseIndex = 0;

                if (currentBlock == blockStart)
                {
                    responseIndex = offset;
                }

                while (responseIndex <= 0x03 && index < dataLength)
                {
                    dataRead[index++] = data[responseIndex++];
                }
                currentBlock++;
            }
        }

        return dataRead;
    }

ISO 15693 using FEIG Reader API

We tested with success a Feig RFID reader which comes with a .Net API. Even if the documentation is still in "preliminary" stage it is working fine. It allows Read Multiple Block Command but does not come with event like card detection buit-in. So for the moment we loop infinitely over inventory to produce a kind of "Tag Inserted event" using their so called "Host Mode". There is a "Scan Mode" which might act as an event producer but didn't had time yet to dig deeper with it. So I read several memory blocks in a single call and then parsed them by code. I do not show you the code as I'm not sure I am allowed to put sample code of this copyrighted API but it is very similar to the previous above except of course I didn't loop to get several block of data.

I wish there will come a native NDEF message in some API one day to avoid parsing code ...

Guillaume Raymond
  • 1,726
  • 1
  • 20
  • 33