Search code examples
javaclib-nfc

Does libNFC only support READ, WRITE and COMP_WRITE


A Week ago I bought a NFC Reader (PN532 I2C) and 5 NFC Tags (NTAG216), the goal was to create an interface for Java, so I can use Java for my project. The interface is working as expected, but when I tried all the commands that the NTAG216 supports (NTAG216 data sheet page 32), only READ, WRITE and COMP_WRITE are working. This is not caused by the interface, I also tried it in C, but same results. So, are there any mistakes in my commands or does libNFC in any way prevent these commands from being executed?
I'm sorry for the possibly bad english, I hope my problem is still understandable.

Thanks for your answers,
Jakob


The Code:

public class Main {

  public static void main(String[] args) {
    System.load(new File("libNFC-JavaInterface.so").getAbsolutePath());
    Context context = new Context();
    Device device = new Device(context);
    Target target = new Target();
    device.selectPassiveTarget(new Modulation(ModulationType.NMT_ISO14443A, BaudRate.NBR_106), null,
        target);
    int[] response;

    System.out.print("UID: ");
    try {
      System.out.printf("%014X", getUID(device));
    } catch (NFCException e) {
      device.selectPassiveTarget(new Modulation(ModulationType.NMT_ISO14443A, BaudRate.NBR_106),
          null, target);
      System.out.print("FAILED");
    }
    System.out.println();

    System.out.print("Version: ");
    try {
      response = getVersion(device);
      for (int i = 0; i < response.length; i++) {
        System.out.printf("%02X", response[i]);
      }
    } catch (NFCException e) {
      device.selectPassiveTarget(new Modulation(ModulationType.NMT_ISO14443A, BaudRate.NBR_106),
          null, target);
      System.out.print("FAILED");
    }
    System.out.println();

    System.out.print("Read: ");
    try {
      response = read(device, 0x08);
      for (int i = 0; i < response.length; i++) {
        System.out.printf("%02X", response[i]);
      }
    } catch (NFCException e) {
      device.selectPassiveTarget(new Modulation(ModulationType.NMT_ISO14443A, BaudRate.NBR_106),
          null, target);
      System.out.print("FAILED");
    }
    System.out.println();

    System.out.print("Fast Read: ");
    try {
      response = fastRead(device, 0x08, 0x11);
      for (int i = 0; i < response.length; i++) {
        System.out.printf("%02X", response[i]);
      }
    } catch (NFCException e) {
      device.selectPassiveTarget(new Modulation(ModulationType.NMT_ISO14443A, BaudRate.NBR_106),
          null, target);
      System.out.print("FAILED");
    }
    System.out.println();

    System.out.print("Write: ");
    try {
      write(device, 0x08, new int[] {0x41, 0x42, 0x43, 0x44});
      System.out.print("SUCCESSFUL");
    } catch (NFCException e) {
      device.selectPassiveTarget(new Modulation(ModulationType.NMT_ISO14443A, BaudRate.NBR_106),
          null, target);
      System.out.print("FAILED");
    }
    System.out.println();

    System.out.print("Compatibility Write: ");
    try {
      compatibilityWrite(device, 0x09, new int[] {0x45, 0x46, 0x47, 0x48});
      System.out.print("SUCCESSFUL");
    } catch (NFCException e) {
      device.selectPassiveTarget(new Modulation(ModulationType.NMT_ISO14443A, BaudRate.NBR_106),
          null, target);
      System.out.print("FAILED");
    }
    System.out.println();

    System.out.print("Read cnt: ");
    try {
      response = readCnt(device);
      for (int i = 0; i < response.length; i++) {
        System.out.printf("%02X", response[i]);
      }
    } catch (NFCException e) {
      device.selectPassiveTarget(new Modulation(ModulationType.NMT_ISO14443A, BaudRate.NBR_106),
          null, target);
      System.out.print("FAILED");
    }
    System.out.println();

    System.out.print("Read sig: ");
    try {
      response = readSig(device);
      for (int i = 0; i < response.length; i++) {
        System.out.printf("%02X", response[i]);
      }
    } catch (NFCException e) {
      device.selectPassiveTarget(new Modulation(ModulationType.NMT_ISO14443A, BaudRate.NBR_106),
          null, target);
      System.out.print("FAILED");
    }
    System.out.println();

    target.free();
    device.close();
    context.exit();
  }

  public static long getUID(Device device) throws NFCException {
    int[] response = read(device, 0x00);
    return (long) response[0] << 48 | (long) response[1] << 40 | (long) response[2] << 32
        | (long) response[4] << 24 | (long) response[5] << 16 | (long) response[6] << 8
        | (long) response[7] << 0;
  }

  public static int[] getVersion(Device device) throws NFCException {
    int[] response = new int[8];
    device.transceiveBytes(new int[] {0x60}, response, -1);
    return response;
  }

  public static int[] read(Device device, int startPage) throws NFCException {
    int[] response = new int[16];
    device.transceiveBytes(new int[] {0x30, startPage & 0xFF}, response, -1);
    return response;
  }

  public static int[] fastRead(Device device, int startPage, int endPage) throws NFCException {
    int[] response = new int[((endPage &= 0xFF) - (startPage &= 0xFF) + 1) * 4];
    device.transceiveBytes(new int[] {0x3A, startPage, endPage}, response, -1);
    return response;
  }

  public static void write(Device device, int startPage, int[] data) throws NFCException {
    int[] command = new int[6];
    command[0] = 0xA2;
    command[1] = startPage & 0xFF;
    for (int i = 0; i < data.length; i++) {
      command[2 + i] = data[i] & 0xFF;
    }
    device.transceiveBytes(command, new int[0], -1);
  }

  public static void compatibilityWrite(Device device, int startPage, int[] data)
      throws NFCException {
    int[] command = new int[18];
    command[0] = 0xA0;
    command[1] = startPage & 0xFF;
    for (int i = 0; i < data.length; i++) {
      command[2 + i] = data[i] & 0xFF;
    }
    device.transceiveBytes(command, new int[0], -1);
  }

  public static int[] readCnt(Device device) throws NFCException {
    int[] response = new int[3];
    device.transceiveBytes(new int[] {0x39, 0x02}, response, -1);
    return response;
  }

  public static int[] readSig(Device device) throws NFCException {
    int[] response = new int[32];
    device.transceiveBytes(new int[] {0x3C, 0x00}, response, -1);
    return response;
  }
}

And following the output:

UID: 04675362D55681
Version: error  libnfc.driver.pn532_i2c Application level error detected  (127)
FAILED
Read: 41424344454647480000000000000000
Fast Read: error    libnfc.driver.pn532_i2c Application level error detected  (127)
FAILED
Write: SUCCESSFUL
Compatibility Write: SUCCESSFUL
Read cnt: error libnfc.driver.pn532_i2c Application level error detected  (127)
FAILED
Read sig: error libnfc.driver.pn532_i2c Application level error detected  (127)
FAILED

Solution

  • I didn't try with libNFC, but I had the same issue with my code, so it is probably the same fix...

    For the NTAG2xx specific functions (GET_VERSION, FAST_READ, READ_CNT, READ_SIG), you need to use the PN532 function "InCommunicateThru" (0x42) and not "InDataExchange" (0x40). This one works only for standard NFC forum functions (READ, WRITE).