如何使用 smartcardio 和 Java 控制 ACR122 上的 LED?

Posted

技术标签:

【中文标题】如何使用 smartcardio 和 Java 控制 ACR122 上的 LED?【英文标题】:How to Control LED on ACR122 using smartcardio and Java? 【发布时间】:2020-04-23 19:44:08 【问题描述】:

我正在尝试使用 Java 中的 smartcardio 库(JDK 8、NetBeans 7.4、Windows 10)。我尝试了许多其他库,但都没有成功。

读卡器 (ACS ACR122U) 附带一个 SDK CDROM,但 CD 上没有必要的 .DLL,因此我无法使用 ACS 库。

由于我的 NFC 设备使用 nfctools 库不支持的 EEPROM,我无法使用 nfctools。

我的代码如下:

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());
  
 

它失败并出现“apdu must be at 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)

对象 apdu1 的长度为 14 个字节,所以我不确定错误消息的含义。

第 43 行是ResponseAPDU answer1 = channel.transmit( apdu1 );

【问题讨论】:

您似乎复制了命令中的 INS、P1、P2 和 Lc 字段,删除第一组这些值 我以为第一部分是Pseudo-APDU的一部分,第二部分是指令到读卡器中的控制器芯片的部分。我是从 ACR122U NFC 阅读器 API 文档的阅读器第 6.1 节得到的。 我已经阅读了相同的文档,还检查了***.com/questions/38676069/acr122u-led-controlling 0xff 不是有效的普通类代码,这表示伪 APDU 【参考方案1】:

由于 APDU 命令的 cmets 0xff 类对卡无效,这用于让读卡器解释 APDU 而不是将其发送到卡。

不是同一个读者,但这张图很清楚

所以不要尝试通过复制 INS、P1、P2 和 Lc 字段来将 APDU 包装到另一个 APDU 中

// 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

【讨论】:

以上是关于如何使用 smartcardio 和 Java 控制 ACR122 上的 LED?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 RFID 读卡器 (javax.smartcardio) 识别德国身份证?

带有 Java 9 和 ClassPath 的 javax.smartcardio

javax.smartcardio:如何将本机命令发送到 Desfire 卡?

在 Android 上使用 javax.smartcardio 包?

Ultralight C、Smartcardio 和 ACR122

通过 javax.smartcardio 连接到 micro SD