我不太确定你想要达到什么目的。你使用IsoPcdA的transceive方法传输的是完整的APDU(如ISO/IEC 7816-4中定义的,或者是ISO-DEP传输协议中的任何PDU)。因此,transceive的返回值是完整的C-APDU(命令APDU),而transceive的字节数组参数是包括状态字(SW1 | SW2)在内的完整R-APDU(响应APDU)。因此,该参数的最后两个字节是状态字。在你的示例中,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
使用数据为0x01的InDataExchange函数
> FF00000004 D440 01 01 00
< D541 00 01 9000
当我们从卡片读取器收到错误代码0x00时(InDataExchange命令的状态;不是实际响应APDU的一部分),我们得到响应0x01(这是IsoDepA响应APDU),并且我们得到卡片读取器封装APDU的状态码0x9000(不是实际响应APDU的一部分)。
InDataExchange带有数据0x01 0x02。
> FF00000005 D440 01 0102 00
< D541 00 0102 9000
当读卡器返回错误代码0x00时(InDataExchange命令的状态,不是实际响应APDU的一部分),我们得到响应0x01 0x02(这是IsoDepA响应APDU),并且我们得到卡片读取器包装APDU的状态码为0x9000(不是实际响应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)。
使用DATA = 0x01 0x02 0x03 0x04进行InDataExchange。
> FF00000007 D440 01 01020304 00
< D541 00 01020304 9000
因此,我们从读卡器收到了错误代码0x00(InDataExchange命令的状态;不是实际响应APDU的一部分),我们得到了响应为0x01 0x02 0x03 0x04的数据(这是IsoDepA响应APDU),并且我们从读卡器封装APDU的状态代码中获得了0x9000(不是实际响应APDU的一部分)。
因此,我们恰好可以得到与我们发送的命令APDU相同的数据作为响应APDU(请注意,这些APDU都没有按照ISO 7816-4格式进行格式化,但对于IsoPcdA卡模拟,任何ISO 14443-4传输协议格式都可以使用)。
状态码
0x9000属于读卡器APDU封装(
CLA=FF INS=00 P1P2=0000 Lc [PN542 COMMAND] Le=00),这是必需的,因为ACR122U的PN532是通过CCID(PC/SC)接口访问的。这些是纯阅读器命令封装,与ISO-DEP通信无关。
D440 01 [DATA]是PN532用于在ISO-DEP上交换数据(例如APDU)的命令,而
D541 00 [DATA]则是相应的响应。