2

My coworkers and I are trying to create a Java program to read cards with a HID OMNIKEY 5427 CK. We have no previous experience with RFID and checked: https://support.impinj.com/hc/communities/public/questions/201883748-How-do-I-create-RFID-applications-with-Java-

for some sample code (we haven't been able to find much sample code apart from this), which we have adapted and used, but when running our code we get

java.nio.channels.UnresolvedAddressException
at sun.nio.ch.Net.checkAddress(Unknown Source)
at sun.nio.ch.SocketChannelImpl.connect(Unknown Source)
at org.apache.mina.transport.socket.nio.SocketConnector.connect(SocketConnector.java:187)
at org.apache.mina.transport.socket.nio.SocketConnector.connect(SocketConnector.java:137)
at org.apache.mina.common.support.BaseIoConnector.connect(BaseIoConnector.java:40)
at org.llrp.ltk.net.LLRPConnector.connect(LLRPConnector.java:135)
at org.llrp.ltk.net.LLRPConnector.connect(LLRPConnector.java:116)
at hellojavaltk.HelloJavaLtk.connect(HelloJavaLtk.java:212)
at hellojavaltk.HelloJavaLtk.run(HelloJavaLtk.java:227)
at hellojavaltk.HelloJavaLtkMain.main(HelloJavaLtkMain.java:9)​

code is basically:

public class HelloJavaLtkMain
{
public static void main(String[] args) throws InterruptedException
{
HelloJavaLtk app = new HelloJavaLtk();

System.out.println("Starting reader.");
app.run("HID-OMNIKEY-5427-CK");
Thread.sleep(30000);
System.out.println("Stopping reader.");
app.stop();
System.out.println("Exiting application.");
System.exit(0);
}
}

and HelloJavaLtk is a class that implements the LLRPEndpoint interface, basically copy-pasted form the link above.

So we don't know if we are just not addressing the device correctly with that run("HID-OMNIKEY-5427-CK") or if we should be doing something completely different when trying to reach that Endpoint.

We would appreciate any help if somebody has been able to use the OMNIKEY-5427-CK (or other card readers) with Java code, could point us to other code examples or give us further insights on what are we doing wrong.

Thanks all.

Michael Roland
  • 39,663
  • 10
  • 99
  • 206
Diego
  • 462
  • 10
  • 26

3 Answers3

3

The HID OMNIKEY 5427 CK is a PC/SC (CCID) compliant smartcard reader. The library you are trying to use is intended for EPC RFID readers. This Omnikey reader is accessed through PC/SC, however. Current Oracle Java has built in support for access to PC/SC smartcard readers using the Java SmartcardIO API.

Michael Roland
  • 39,663
  • 10
  • 99
  • 206
  • Thanks. javax.smartcardio.* worked! we successfully connected to the RFID reader and sent APDU commands that returned tag UID. – Diego Aug 28 '14 at 20:30
  • @Diego Alonso can you add some more information on your solution? I am trying to send `transmitAPDU(new CommandAPDU(new byte[]{(byte)0x80, (byte)0xA6, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00}));` but receiving `sun.security.smartcardio.PCSCException: Unknown error 0x1f` – bvdb Dec 04 '15 at 15:21
  • @Diego : Would you mind sharing your solution. I am having problem in finding the correct APDU for omnikey 5427CK. – SK. Feb 01 '18 at 13:13
  • Skumar, It's been a long time since I got involved in this. I believe that the source code was shared [here](https://github.com/dbagshaw). I can't remember if it was the DDSsmartcardio or the SampleLoginWindow. This was some sort of experiment and the guy coding it was a biomedical engineer. I hope it helps you, but I can't promise you'll find a solution for your problem there. Best of luck. – Diego Feb 01 '18 at 14:04
2

I know this is very old question, Since I didn't find a working example anywhere with command, With the below code you can get the ATR and UID of the card.

TerminalFactory factory = TerminalFactory.getDefault(); 
List<CardTerminal> terminals = factory.terminals().list();
System.out.println("Terminals: " + terminals);
// get the first terminal
CardTerminal terminal = terminals.get(0);

// establish a connection with the card
Card card = terminal.connect("*");
System.out.println("card: " + card);
ATR atr = card.getATR();
System.out.println("Card ATR: " + DatatypeConverter.printHexBinary(atr.getBytes()));
CardChannel channel = card.getBasicChannel();
CommandAPDU commandAPDU;
commandAPDU = new CommandAPDU(new byte[]{(byte) 0xFF,(byte) 0xCA,(byte) 0x00,(byte) 0x00,(byte) 0x00});             
ResponseAPDU r = channel.transmit(commandAPDU);
System.out.println("Response: " + r.toString() + ", NR: " + r.getNr());
String hex = DatatypeConverter.printHexBinary(r.getBytes());
System.out.println("Response: " + hex);
System.out.println("Card UID: " + DatatypeConverter.printHexBinary(r.getData()));
byte[] copyOf = Arrays.copyOf(r.getBytes(), r.getNr());
System.out.println("Card UID from bytes: " + DatatypeConverter.printHexBinary(copyOf));
// disconnect
card.disconnect(false);
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
jan_kiran
  • 301
  • 3
  • 16
1

I think the code you are using is not compatible, as it looks to work with LLRP protocol and your device supports CCID and keyboard wedge.

CCID:

I couldn't find the documentation for your device, however it looks like CCID might work using a serial connection, if that's the case you can use RXTX to connect to the device (http://mfizz.com/oss/rxtx-for-java), and then send commands and read responses from it.

This is a small example:

// change to right port
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier("/dev/ttyS0"); 
    if (portIdentifier.isCurrentlyOwned()) {
        throw new RfidReaderUnavailableException();
    } else {
        CommPort commPort = portIdentifier.open(this.getClass().getName(), 2000);
        if (commPort instanceof SerialPort) {
            SerialPort serialPort = (SerialPort) commPort;
            // This details have to match your device configuration or it won't work
            serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
            serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN | SerialPort.FLOWCONTROL_RTSCTS_OUT);

            in = serialPort.getInputStream();
            out = serialPort.getOutputStream();

            <-- Here you write the commands on out and read the responses from in -->

        } else {
            System.out.println("Error: Only serial ports are handled by this.");
        }
   }

In case CCID doesn't support serial communication they will have to provide a driver for it. If the driver doesn't come with Java compatibility then you will need to write a JNI wrapper to use it from your Java code.

Keyboard wedge:

The functionality on this mode will be probably reduced to write the card id as if it was a keyboard, much like barcode scanners. you won't be able to tell from keyboard input and the reader and you wont be able to read or write data from the card memory either, however it might work for you depending of what your app has to achieve.

Adrian Lopez
  • 1,776
  • 1
  • 17
  • 35
  • Thanks, although our reader doesn't appear to have the ability to communicate over serial. – Diego Aug 28 '14 at 20:30