You can use PC_to_RDR_Escape (note that that's only available if you installed the original ACR driver package for the reader). Assuming that you are using the Java Smartcard IO API, you would do that using the method Card.transmitControlCommand()
:
byte[] response = card.transmitControlCommand(SCARD_CTL_CODE(3500), command);
The definition of the method SCARD_CTL_CODE
can be found in this post.
The command
needs to be a byte array that contains an APDU header for the pseudo-APDU that passes raw commands to the contactless frontend chip and the actual command for the contactless frontend chip. Since the ACR1222L is based on an NXP PN532(?), the command for the contactless frontend chip would be the InDataExchange command (see the user manual):
byte[] interfaceCommandHeader = new byte[] { (byte)0xD4, (byte)0x40, (byte)0x01 };
byte[] interfaceCommand = Arrays.copyOf(interfaceCommandHeader, interfaceCommandHeader.length + tagCommand.length);
System.arraycopy(tagCommand, 0, interfaceCommand, interfaceCommandHeader.length, tagCommand.length);
Depending on how the reader actually activates the card, you might need to use the InCommunicateThru command instead of InDataExchange:
byte[] interfaceCommandHeader = new byte[] { (byte)0xD4, (byte)0x42 };
byte[] interfaceCommand = Arrays.copyOf(interfaceCommandHeader, interfaceCommandHeader.length + tagCommand.length);
System.arraycopy(tagCommand, 0, interfaceCommand, interfaceCommandHeader.length, tagCommand.length);
The pseudo APDU header can be added by:
byte[] commandHeader = new byte[] { (byte)0xE0, (byte)0x00, (byte)0x00, (byte)0x24, (byte)0x00 };
byte[] command = Arrays.copyOf(commandHeader, commandHeader.length + interfaceCommand.length);
System.arraycopy(interfaceCommand, 0, command, commandHeader.length, interfaceCommand.length);
command[4] = (byte)(interfaceCommand.length & 0x0FF); // update Lc field
Another option is to send commands directly using PC_to_RDR_XfrBlock. This maps to CardChannel.transmit()
in the Java Smartcard IO API:
ResponseAPDU responseApdu = cardChannel.transmit(commandAPDU);
The manual of your reader is not quite clear if the same pseudo APDU header can be used over that interface. However, if you look into appendix H, you'll find a different header from wrapping into a pseudo APDU (the ACR122U legacy mode). So you could use the following:
CommandAPDU commandAPDU = new CommandAPDU(0xFF, 0x00, 0x00, 0x00, interfaceCommand);
Note that, again, you have to wrap the tag command into the InDataExchange command for the contactless frontend chip.