【问题标题】:Frequent Disconnection ACR122U NFC Reader频繁断线 ACR122U NFC读写器
【发布时间】:2014-02-13 14:47:36
【问题描述】:

当我将 SIII (Android 4.3) 放在 ACR122U NFC 阅读器上时,LED 一直闪烁绿色。当我将三星 S4 (Android 4.3) LED 变为绿色时,直到手机在读卡器上。在这两种情况下,NFC 都已打开并且设备处于解锁状态。 此行为转化为 SIII 中的频繁断开连接和 S4 上的稳定连接。为什么两部手机的行为不同?我知道两部手机都有来自 NXP 和 Broadcom 这两家不同供应商的 NFC 芯片组。

我的问题是这些设备之间这种不一致行为的根源是什么?

另一个问题是为什么手机会给出 ATR?

【问题讨论】:

  • 你用的是什么模式?手机使用的是读写器模式、卡模拟模式还是点对点模式?
  • 我只是用默认设置连接阅读器,没有 PC 应用程序。手机上没有安装其他应用程序,唯一更改的设置是 NFC 开启。
  • 因此您在读写器模式下使用一个 NFC 设备(ACR122U),在点对点模式下使用第二个 NFC 设备(Android 手机)(或者您使用的是支持 NFC 的 SIM卡?在那种情况下,至少 S4 也会激活卡模拟模式...)虽然点对点模式(在某些条件下)对读卡器来说就像一张非接触式卡,但你不能指望他们与由于不同的操作模式和协议。因此,您尝试做的事情没有多大意义(除了启用 NFC 的 SIM 卡的情况),也不会产生任何有用的结果。
  • 我们没有使用 NFC SIM 卡。当我使用 PC/SC 库向阅读器的 NFC 控制器发送 TginitTarget 命令以将其置于 PICC 仿真模式时,真正的问题出现了。在算法上,我们选择一个读卡器,然后连接到读卡器并发送用 ACR122U 规定的特殊 APDU 包装的控制器命令。如果 S4 连接到读卡器成功,因为手机提供 ATR 并且连接保持稳定,而在 S3 连接失败并且 TginitTarget 失败并显示 6300。code.google.com/p/ismb-snep-java/issues/detail?id=1
  • 那么你能解释一下你现在在做什么吗?如果您使用TgInitAsTarget,那么您不是在读/写模式下使用 ACR122U,而是在卡模拟模式下使用。在这种情况下,Android 设备将以读/写模式运行。您能否解释一下为什么您认为手机会发送 ATR? (顺便说一句。在这两种情况下都不涉及 ATR,因为 ATR 特定于接触式智能卡。)

标签: android nfc smartcard hce acr122


【解决方案1】:

使用 ACR122U/PN532 进行软件卡仿真的命令序列可以在this answer 中找到。

除此之外,还有不同版本的ACR122U:

  • 有些总是表明存在智能卡。在这种情况下,可以使用

    连接到“模拟”卡
    // SCardConnect with SCARD_SHARE_SHARED, SCARD_PROTOCOL_ANY
    Card card = cardTerminal.connect("*");
    CardChannel cardChannel = card.getBasicChannel();
    

    之后,可以使用 APDU wrapping 发送 PN532 命令:

    > FF000000 Lc PN532-COMMAND
    < PN532-RESPONSE 9000
    

    使用cardChannel.transmit 方法:

    CommandAPDU commandAPDU = ...
    // SCardTransmit
    Response responseAPDU = cardChannel.transmit(commandAPDU);
    
  • 其他版本的 ACR122U 并不总是“模拟”智能卡的存在。相反,它们会自动轮询非接触式卡片,并且仅在将实际卡片呈现给读卡器时才指示卡片存在。在这种情况下,只有在存在实际卡的情况下才能使用cardTerminal.connect("*");。但是,在软件卡仿真模式下使用 ACR122U 的情况下通常不会出现这种情况。在这种情况下,仍然可以使用直接模式与阅读器建立连接

    // SCardConnect with SCARD_SHARE_DIRECT
    Card card = cardTerminal.connect("direct");
    

    之后,可以使用转义命令与阅读器交换相同的 APDU 包装的 PN532 命令(如果转义命令适用于您的阅读器版本,您可能需要查看手册):

    final int IOCTL_SMARTCARD_ACR122_ESCAPE_COMMAND = 0x003136B0; //IOCTL(3500) for Windows
    //final int IOCTL_SMARTCARD_ACR122_ESCAPE_COMMAND = 0x42000DAC; //IOCTL(3500) for Linux
    byte[] commandAPDU = ...
    // SCardControl
    byte[] responseAPDU  = card.transmitControlCommand(IOCTL_SMARTCARD_ACR122_ESCAPE_COMMAND, commandAPDU);
    

【讨论】:

  • 此详细信息非常有用且内容丰富。需要注意的一件事,我们使用单个 ACR 读卡器和主机应用程序,但两部不同的手机产生不同的结果。现在,我明白没有必要将手机放在读卡器上将其设置为卡模拟。
  • 区别在于手机对阅读器的轮询命令的反应。如果手机以读取器解释为检测到智能卡的方式响应轮询,读取器将显示“插入的智能卡”,并且可以使用cardTerminal.connect("*"); 连接到读取器。
  • 我们在“直接”模式下尝试了 card.transmitControlCommand(IOCTL_SMARTCARD_ACR122_ESCAPE_COMMAND, commandAPDU),因为我们的读卡器版本不模拟卡。我们注意到 card.transmitControlCommand(IOCTL_SMARTCARD_ACR122_ESCAPE_COMMAND, commandAPDU) 在没有卡时返回 0x9900,但在有卡时返回 D58D xx ... 9000。我想在不将手机放在读卡器上的情况下将读卡器置于卡仿真模式。这里的命令APDU是TagInitAsTarget FF00000027D48C05040012345620000000000000000000000000000000000000000000000000000000000000
  • 这很奇怪。除了 TgInitAsTarget 之外的其他命令(例如 Read/WriteRegister)是否有效?
  • 一切正常,但我们必须将手机放在阅读器上才能成功执行 TgInitAsTarget。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多