简体   繁体   中英

How to Control LED on ACR122 using smartcardio and Java?

I am trying to use the smartcardio library in Java (JDK 8, NetBeans 7.4, Windows 10). I have tried many other libraries with no success.

The card reader (ACS ACR122U) came with an SDK CDROM but the necessary.DLL is not on the CD so I cannot use the ACS library.

Since my NFC device uses an EEPROM that is not supported by the nfctools library I cannot use nfctools.

My code is as follows:

package myPackage;

import java.util.List;
import javax.smartcardio.*;

public class Blog {
 public static void main(String[] args) {
  try {
   // Display the list of terminals
   TerminalFactory factory = TerminalFactory.getDefault();
   List<CardTerminal> terminals = factory.terminals().list();
   System.out.println("Terminals: " + terminals);

   // Use the first terminal
   CardTerminal terminal = terminals.get(0);

   // Connect with the card
   Card card = terminal.connect("*");
   System.out.println("card: " + card);
   CardChannel channel = card.getBasicChannel();

   // Send Red and Green LED ON command
   byte[] cmd1 = {(byte)0xFF, // Pseudo-APDU class
                        0x00, // INS
                        0x00, // P1
                        0x00, // P2
                        9,    // Lc - number of bytes in Payload
                        (byte)0xFF, // First byte of payload - LED/Buzzer cntrl
                        0x00, // INS
                        0x40, // P1
                        0x0F, // P2 - LED state control
                        0x04, // Lc
                        0x00, // 4 byte blink duration control
                        0x00, 
                        0x00, 
                        0x00 };
   CommandAPDU apdu1 = new CommandAPDU( cmd1,   // Byte array to use
                                           0,   // index to start of msg
                                           14 );// msg length
   System.out.println( "apdu1: " + apdu1.toString() );

   ResponseAPDU answer1 = channel.transmit( apdu1 );
   System.out.println("answer1: " + answer1.toString());

   // Get Firmware Version of the reader
   byte[] cmd2 = {(byte)0xFF, 0x00, 0x00, 0x00, 5, (byte)0xFF, 0x00, 0x48, 0x00, 0x00 };
   CommandAPDU apdu2 = new CommandAPDU( cmd2, 0, 10 );
   System.out.println( "apdu2: " + apdu2.toString() );
   ResponseAPDU answer2 = channel.transmit( apdu2 );
   System.out.println("answer2: " + answer2.toString());
   System.out.println();

   // Disconnect the card
   card.disconnect(false);
  } catch(CardException e) 
  {
   System.out.println("Problem: " + e.toString());
  }
 }
}

It fails with an error about the "apdu must be a least 2 bytes long".

run:
Terminals: [PC/SC terminal ACS ACR122 0]
card: PC/SC card in ACS ACR122 0, protocol T=1, state OK
apdu1: CommmandAPDU: 14 bytes, nc=9, ne=0
Exception in thread "main" java.lang.IllegalArgumentException: apdu must be at least 2 bytes long
    at javax.smartcardio.ResponseAPDU.check(ResponseAPDU.java:73)
    at javax.smartcardio.ResponseAPDU.<init>(ResponseAPDU.java:67)
    at sun.security.smartcardio.ChannelImpl.transmit(ChannelImpl.java:91)
    at myPackage.Blog.main(Blog.java:43)
Java Result: 1
BUILD SUCCESSFUL (total time: 0 seconds)

The object apdu1 is 14 bytes long so I'm not sure what the error message means.

Line 43 is ResponseAPDU answer1 = channel.transmit( apdu1 );

As in the comments 0xff class of APDU command is not valid for cards, this is used to get the reader to interpret the APDU instead of send it to the card.

Not the same reader but this diagram make it clear

在此处输入图像描述

So don't try and wrap an APDU inside another APDU by duplicating the INS, P1, P2 and Lc fields

// Send Red and Green LED ON command
   byte[] cmd1 = {(byte)0xFF, // First byte of payload - LED/Buzzer cntrl
                        0x00, // INS
                        0x40, // P1
                        0x0F, // P2 - LED state control
                        0x04, // Lc
                        0x00, // 4 byte blink duration control
                        0x00, 
                        0x00, 
                        0x00 };
   CommandAPDU apdu1 = new CommandAPDU( cmd1,   // Byte array to use
                                           0,   // index to start of msg
                                           9 );// msg length

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM