我不确定您要在这里实现什么。无论您使用 IsoPcdA 的收发方法收发什么都是完整的 APDU(如 ISO/IEC 7816-4 中定义的,或者更确切地说是 ISO-DEP 传输协议中的任何 PDU)。所以transceive的返回值是一个完整的C-APDU(命令APDU),而transceive的字节数组参数是一个完整的R-APDU(响应APDU),包括两个字节的状态字(SW1 | SW2)。因此,该参数的最后两个字节是状态字。在您的示例中,SW1 为 02,SW2 为 03。
您在 PN532 NFC 控制器的 InDataExchange 命令中看到的状态字节不是 APDU 的状态字,而是 PN532 NFC 控制器内命令执行的状态。此状态字节为您提供有关缓冲区溢出、通信超时等的信息,而不是卡端返回的信息。
编辑:示例代码+测试命令:
在 Galaxy Nexus (CM 10) 上运行的示例代码:
try {
Class isoPcdA = Class.forName("android.nfc.tech.IsoPcdA");
Method isoPcdA_get = isoPcdA.getDeclaredMethod("get", Tag.class);
final IsoPcdA techIsoPcdA = (IsoPcdA)isoPcdA_get.invoke(null, tag);
if (techIsoPcdA != null) {
if (mWorker != null) {
mInterrupt = true;
mWorker.interrupt();
try {
mWorker.join();
} catch (Exception e) {}
}
mInterrupt = false;
mWorker = new Thread(new Runnable() {
public void run () {
try {
techIsoPcdA.connect();
byte[] command = techIsoPcdA.transceive(new byte[]{ (byte)0x90, (byte)0x00 });
Log.d(CardEmulationTest.class.getName(), "Connected.");
while (!mInterrupt) {
Log.d(CardEmulationTest.class.getName(), "C-APDU=" + StringUtils.convertByteArrayToHexString(command));
command = techIsoPcdA.transceive(command);
}
} catch (Exception e) {
Log.e(CardEmulationTest.class.getName(), "Exception while communicating on IsoPcdA object", e);
} finally {
try {
techIsoPcdA.close();
} catch (Exception e) {}
}
}
});
mWorker.start();
}
} catch (Exception e) {
Log.e(CardEmulationTest.class.getName(), "Exception while processing IsoPcdA object", e);
}
测试(使用 ACR122U):
InListPassivTargets(1 个目标,106kbps)
> FF00000004 D44A 0100 00
< D54B 010100046004088821310578338800 9000
InDataExchange 与 DATA = 0x01
> FF00000004 D440 01 01 00
< D541 00 01 9000
所以我们从读卡器得到一个错误代码 0x00(InDataExchange 命令的状态;不是实际响应 APDU 的一部分),我们得到 0x01 作为响应(这是 IsoDepA 响应 APDU),我们得到 0x9000 作为状态码读卡器包装 APDU(不是实际响应 APDU 的一部分)。
InDataExchange 与 DATA = 0x01 0x02
> FF00000005 D440 01 0102 00
< D541 00 0102 9000
所以我们从读卡器得到一个错误代码 0x00(InDataExchange 命令的状态;不是实际响应 APDU 的一部分),我们得到 0x01 0x02 作为响应(这是 IsoDepA 响应 APDU),我们得到 0x9000 作为状态代码用于读卡器包装 APDU(不是实际响应 APDU 的一部分)。
InDataExchange 与 DATA = 0x01 0x02 0x03
> FF00000006 D440 01 010203 00
< D541 00 010203 9000
所以我们从读卡器得到一个错误代码 0x00(InDataExchange 命令的状态;不是实际响应 APDU 的一部分),我们得到 0x01 0x02 0x03 作为响应(这是 IsoDepA 响应 APDU),我们得到 0x9000 作为状态读卡器包装 APDU 的代码(不是实际响应 APDU 的一部分)。
InDataExchange 与 DATA = 0x01 0x02 0x03 0x04
> FF00000007 D440 01 01020304 00
< D541 00 01020304 9000
所以我们从读卡器得到一个错误代码 0x00(InDataExchange 命令的状态;不是实际响应 APDU 的一部分),我们得到 0x01 0x02 0x03 0x04 作为响应(这是 IsoDepA 响应 APDU),我们得到 0x9000 作为读卡器包装 APDU 的状态代码(不是实际响应 APDU 的一部分)。
因此,我们得到了作为命令 APDU 作为响应 APDU 发送的确切数据(请注意,这些 APDU 都不是根据 ISO 7816-4 格式化的,但这并不重要,因为 IsoPcdA 卡模拟适用于任何 ISO 14443-4 传输协议格式)。
状态码0x9000属于读卡器 APDU 封装(CLA=FF INS=00 P1P2=0000 Lc [PN542 COMMAND] Le=00),这是通过 CCID(PC/SC)接口访问 ACR122U 的 PN532 所需的。这些是纯粹的阅读器命令封装,与通过 ISO-DEP 进行的通信无关。
D440 01 [DATA]是通过 ISO-DEP 交换数据(例如 APDU)的PN532 命令,而D541 00 [DATA]是相关响应。