Как управлять светодиодом на ACR122 с помощью смарт-карт и Java? - PullRequest
0 голосов
/ 23 апреля 2020

Я пытаюсь использовать библиотеку smartcardio в Java (JDK 8, NetBeans 7.4, Windows 10). Я пробовал много других библиотек без успеха.

Устройство чтения карт (ACS ACR122U) поставлялось с компакт-диском SDK, но необходимого файла .DLL нет на компакт-диске, поэтому я не могу использовать библиотеку ACS.

Поскольку мое устройство NF C использует EEPROM, который не поддерживается библиотекой nfctools, я не могу использовать 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 должен иметь длину не менее 2 байтов».

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

1 Ответ

0 голосов
/ 24 апреля 2020

Так как в комментариях класс 0xff команды APDU недопустим для карт, он используется, чтобы заставить читателя интерпретировать APDU вместо отправки его на карту.

Не тот же читатель, но эта диаграмма проясните это

enter image description here

Поэтому не пытайтесь обернуть APDU внутри другого APDU, дублируя поля INS, P1, P2 и L c

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

...