2

I'm developing an application in Java, where I want to send a URL in an NDEF message, which then gets opened on a mobile device. I was able to do this through the acr1252u's Card Emulation Mode with Mifare Ultralight for a URL for example "http://www.google.com" since this fits in the emulated card's memory, which if I understand correctly is 52 bytes, but I would like to send a much longer URL (around 350-550 bytes), which probably is not possible with HCE on this device. The acr1252 supports peer-to-peer comms as well, but not sure how I could use it to serve the task. Could anyone please point me in a direction that could help me in this persuit?

The code I used for shorter URL using HCE:

public static void main(String[] args) throws CardException {
        TerminalFactory factory = TerminalFactory.getDefault();
        List<CardTerminal> terminals = factory.terminals().list();
        System.out.println("Terminals: " + terminals);

        CardTerminal terminal = terminals.get(0);
        Card device = terminal.connect("DIRECT");
        enterHostCardEmulation(device);

        byte[] ndef = new byte[] {(byte) 0xE1, 0x10, 0x06, 0x00,
                                         0x03, 0x0F, (byte) 0xD1, 0x01,
                                         0x0B, 0x55, 0x01, 0x67,
                                         0x6F, 0x6F, 0x67, 0x6C,
                                         0x65, 0x2E, 0x63, 0x6F,
                                         0x6D, (byte) 0xFE, 0x00, 0x00};


        byte[] response = writeCardEmulationData(device, (byte) 0x01, (byte) 0x00, ndef);
        System.out.println("response: " + byteArrayToHex(response));
}

private static byte[] writeCardEmulationData(Card device, byte nfcMode, byte startOffset, byte[] dataToWrite) {
        byte[] command = new byte[9+dataToWrite.length];
        command[0] = (byte) 0xE0;                         // Class
        command[1] = 0x00;                                // INS
        command[2] = 0x00;                                // P1
        command[3] = 0x60;                                // P2
        command[4] = (byte) (dataToWrite.length + 0x04);  // Length + 4
        command[5] = 0x01;
        command[6] = nfcMode;
        command[7] = startOffset;
        command[8] = (byte) dataToWrite.length;
        System.arraycopy(dataToWrite, 0, command, 9, dataToWrite.length);
        System.out.println(byteArrayToHex(command));
        try {
            return device.transmitControlCommand(SCARD_CTL_CODE(3500), command);
        } catch (CardException e) {
            e.printStackTrace();
            return null;
        }
}

private static void enterHostCardEmulation(Card device) {
        try {
            System.out.println("NFC device: " + device);
            byte[] hceCommand = new byte[] {(byte) 0xE0, 0x00, 0x00, 0x40, 0x03, 0x01, 0x00, 0x00};
            byte[] hceResponse = device.transmitControlCommand(SCARD_CTL_CODE(3500), hceCommand);
            System.out.println("enter HCE response: " + byteArrayToHex(hceResponse));
        } catch (CardException e) {
            e.printStackTrace();
        }
}

private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
public static String byteArrayToHex(byte[] byteArr) {
        char[] hexChars = new char[byteArr.length * 2];
        for (int j = 0; j < byteArr.length; j++) {
            int v = byteArr[j] & 0xFF;
            hexChars[j * 2] = HEX_ARRAY[v >>> 4];
            hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
        }
        return new String(hexChars);
}

public static int SCARD_CTL_CODE(int command) {
        boolean isWindows = System.getProperty("os.name").startsWith("Windows");
        if (isWindows) {
            return 0x00310000 | (command << 2);
        } else {
            return 0x42000000 | command;
        }
}
  • I believe that reader also support FeliCa Type 3 Card emulation with 160 bytes of data. see https://www.acs.com.hk/download-manual/6402/API-ACR1252U-1.16.pdf – Andrew Nov 20 '20 at 15:52
  • Yes, that is right. Thanks for the reply. I failed to mention that I also tried that approach. Nevertheless, my URLs would be around 350-500 bytes long. So neither Type 2 nor Type 3 card emulation is satisfactory for my case with this reader. – tapsomilian Nov 20 '20 at 16:17

1 Answers1

1

Peer to Peer Nfc mode is not the answer.

iOS does not support Nfc peer to peer so you won't be able to send data to iPhones.

Android did support Nfc Peer to Peer (Called Android Beam) but it has been deprecated and removed from Android 10 onwards, one of the reason it was removed was that is was so unreliable so send even small amounts of data.

Andrew
  • 8,198
  • 2
  • 15
  • 35
  • Okay, this is as expected, but still, would I be able to do something similar as through an Android HostApduService, where when you receive an APDU command (for example SELECT AID) you can define and send a response accordingly, through the software? So that I could send the message in multiple "chunks", not having to worry about storing it on the device's memory. – tapsomilian Nov 21 '20 at 10:06
  • I've not seen any USB reader with a "direct" mode, probably because there are time limits to responding to the low level commands that might not be possible over USB. I believe the type of thing can be done with direct access to a pn532 chip via IC2 or SPI from something like an Arduino or Raspberry Pi – Andrew Nov 21 '20 at 10:54
  • Through [this](https://stackoverflow.com/questions/14854933/how-to-card-emulate-with-acr122u-a9/23197444#23197444) method it looks like it is possible even over USB. Could this be applicable to my reader? In the datasheet I found no mention of what NFC chip the acr1252 has. – tapsomilian Nov 22 '20 at 08:40