首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >取消智能卡读取器访问上的错误0x16

取消智能卡读取器访问上的错误0x16
EN

Stack Overflow用户
提问于 2017-01-25 12:20:50
回答 2查看 2.7K关注 0票数 3

我试图改变蜂鸣器在ACR1252U上的持续时间。

指向API:http://www.acs.com.hk/download-manual/6402/API-ACR1252U-1.09.pdf的链接

根据API文档,我需要'E0000028010A‘命令来更改蜂鸣器状态,其中'0A’将持续时间标记为0A*10 as (第44页)。

使用以下Java代码:

代码语言:javascript
复制
public static void main(String[] args) {
    try {
        byte[] send = new byte[6];

        send[0] = (byte) 0xE0; // Commandclass
        send[1] = (byte) 0x00; // Protocoll
        send[2] = (byte) 0x00; // Param 1
        send[3] = (byte) 0x28; // Param 2: Buzzerstatus
        send[4] = (byte) 0x01; // Change Flag
        send[5] = (byte) 0x0A; // Duration: 0A*10ms => 100ms

        Card card = getCard("DIRECT"); // Works!
        CardChannel channel = card.getBasicChannel(); // Works!
        CommandAPDU command = new CommandAPDU(send); // Works!
        channel.transmit(command); // EXCEPTION!
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

public static Card getCard(String target) throws Exception {
    TerminalFactory factory = TerminalFactory.getDefault();
    List<CardTerminal> terminals = factory.terminals().list();
    for (CardTerminal t : terminals) {
        if (t.getName().equals("ACS ACR1252 Dual Reader PICC 0")) {
            Card card = t.connect(target);
            return card;
        }
    }
    throw new Exception();
}

但是,这会导致下面的堆栈跟踪,表示"unkown error 0x16":

代码语言:javascript
复制
javax.smartcardio.CardException: sun.security.smartcardio.PCSCException: Unknown error 0x16
    at sun.security.smartcardio.ChannelImpl.doTransmit(ChannelImpl.java:219)
    at sun.security.smartcardio.ChannelImpl.transmit(ChannelImpl.java:90)
    at readerconfig.TagConfig.main(TagConfig.java:24)
Caused by: sun.security.smartcardio.PCSCException: Unknown error 0x16
    at sun.security.smartcardio.PCSC.SCardTransmit(Native Method)
    at sun.security.smartcardio.ChannelImpl.doTransmit(ChannelImpl.java:188)
    ... 2 more

我花了好几个小时在这个方向上寻找任何东西,但是我什么也找不到。我甚至尝试过另一个设备,它仍然产生了这个错误。

要么是我完全失明了,要么是我的电脑设置不正确。我所能说的就是,我已经成功地使用这个阅读器从NFC标记中编写和读取了。但我只是不能改变阅读器本身的配置。

编辑:

我还找到了另一种发送命令的方法:

代码语言:javascript
复制
byte[] send = new byte[5];
send[0] = (byte) 0xE0;
send[1] = (byte) 0x0;
send[2] = (byte) 0x0;
send[3] = (byte) 0x18; // Tries to read firmware version
send[4] = (byte) 0x0;

Card card = CardUtils.getCard("DIRECT"); // Works!
card.transmitControlCommand(3500, send);

但这会导致“未知错误0x1":

代码语言:javascript
复制
javax.smartcardio.CardException: transmitControlCommand() failed
    at sun.security.smartcardio.CardImpl.transmitControlCommand(CardImpl.java:236)
    at readerconfig.ReaderConfig.main(ReaderConfig.java:28)
Caused by: sun.security.smartcardio.PCSCException: Unknown error 0x1
    at sun.security.smartcardio.PCSC.SCardControl(Native Method)
    at sun.security.smartcardio.CardImpl.transmitControlCommand(CardImpl.java:232)
    ... 1 more
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-02-03 17:44:14

有两种方法可以通过Java Smartcard IO与此读取器交互:

  1. 第一种方法是打开一个常规的APDU传输通道(从PC/SC的角度来看,这将映射到T=0或T=1协议)。你可以用 卡片= getCard("*"); 然而,这将要求读者报告卡的存在。否则你就不能以那种方式打开连接。 然后,您可以将APDU命令发送到卡(在基本通道或逻辑通道上),并且可以在基本通道上向读取器发送特殊命令。这些特殊命令的类字节设置为0xFF,以指示命令的意图是由读取器解释(而不是转发给卡片)。因此,这不适用于以0xE0开头的“外围设备控制”命令。
  2. 这些“外围设备控制”命令必须使用控制代码SCARD_CTL_CODE(3500)的控制命令发送给读取器。与打开与卡片的连接一样,如果读取器上有卡片,则可以使用getCard("*")。但是,如果您希望能够将这些命令发送到读取器,即使没有卡片,则必须以“直接”模式打开连接: 卡片=getCard(“直接”); 然后可以使用card.transmitControlCommand()方法发送控制命令。该方法将控制代码作为第一个参数,命令(作为字节数组)作为第二个参数。使用channel.transmit()在基本通道或任何逻辑通道上交换命令通常不会在“直接”模式下工作(因此出现了错误代码0x16)。 控制代码计算为 公共静态最终int SCARD_CTL_CODE(int命令){ boolean =SCARD_CTL_CODE if ( isWindows ) {返回0x00310000 (命令<< 2);}isWindows{返回0x42000000 \x} 注意Windows和其他平台之间的区别。 例如,要发送蜂鸣器控制命令,您可以使用 card.transmitControlCommand(SCARD_CTL_CODE(3500),命令=新byte[] {(字节)0xE0,(字节)0x00,(字节)0x00,(字节)0x28,(字节)0x01,(字节)0x0A };byte[] response = byte[]命令); 最后,请注意,通过PC/SC发送IOCTL控制代码需要特殊的驱动程序支持。具体来说,微软提供的标准CCID驱动程序在默认情况下不支持发送转义命令(参见USB类驱动程序详细信息 )。只有在通过注册表值"EscapeCommandEnable“启用转义命令之后,此驱动程序才支持转义命令。您在问题中显示的错误0x1是缺少对转义命令的支持的典型结果。 要可靠地支持读取器的所有功能(包括转义命令),您需要使用在他们的网站上提供的"PC/SC驱动程序“包。
票数 5
EN

Stack Overflow用户

发布于 2017-01-31 14:01:00

试着使用

代码语言:javascript
复制
card.transmitControlCommand(int controlCode, byte[] command)

而不是传送。根据5.8节(您链接到的pdf的第41页),控制代码是3500,虽然我不清楚,这是一个十六进制还是一个int,所以与SCARD_CTL_CODE相比,如果你能够。至少,我是这样解释文档的。

通常,您使用transmitControlCommand与读取器交谈,并与卡片进行通信。

修正了ControlCode中的错误。感谢托尔汉·巴特尔告诉我。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41851527

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档