I made a simple test application for quick debugging. I send some bytes, print what I sent on the phones screen and print what I receive.
When I send WRONG commands I get the corresponding error codes in the two byte SW1SW2. I can also call my own command and override SW1SW2 with my own values and I can get them.
Here's the problem: When I send a CORRECT command the transceive command fails with the informative exception "Transceive failed".
If I send the correct command, but override SW1SW2 to something other than 90 00 then I get the SW value I set, but NO response data. (likely because the card does not send ODATA when SW1SW2 <> 90 00)
So how come I'm so sure I sent correct commands? Well other than messing with my own test command I called the GetAppId command - which failed saying I have to define AppId in the card. So I define it in the card, send the same command and transceive fails.
So I'm pretty sure the problem is that transceiving fails when there is ODATA, but I do not understand WHY or how to FIX it.. help please!
EDIT: My card is the 7.5 D contactless basiccard from ZeitControl.
EDIT2: I have set the timeout to 2000ms with no change in behavior. I'm trying to return a single byte of data and the system command I called also doesn't sound heavy.
Then I downloaded and attached the Android source and debugged. There was some segments it would still not go into - but the card seems to return null on valid commands unless I return some manually set SW1SW2 in which case that is the only thing received.
EDIT3: The system command I tried was: 192 14 0 0 0 (or C0 0E 00 00 00) (or CLA INS P1 P2 Lc) I'm not 100% sure I'm doing that one correctly, but I have tried with various lengths (up to 22) of Le and without Le as above and only without does it not give me 6700 (wrong Le/Lc) Of course instead of 6700 it returns null it seems...
The other command is my own defined as 20 0A (value as Byte) and no P1/P2 specified in the .BAS file. I call that one with: 32 10 1 0 1 (or 20 0A 01 00 01) (or CLA INS Lc IDATA Le) This should mean 1 byte data in, set to 0, and 1 byte expected out (+ SW1/SW2 as always). (Setting P1/P2 gives 6700 so unless defined in the command declaration I dont think they should be there) This also returns null. I Expect 00 90 00 to be returned here. (if I set "value" to 00 that is)
I'm using a HTC One X.
EDIT4: MinSdk version = 14 and target 18.
if(bitcoinCard != null){
try {
String sentmsg, receivedmsg;
byte[] send = getBytes(commandBytes.getText().toString());
byte[] data = null;
if(send != null){
bitcoinCard.setTimeout(2000);
data = bitcoinCard.transceive(send);
}
//bitcoinCard.close();
/*if(data != null && data.length == 2)
{
mainLabel.setText("SW1SW2: " + (data[0] < 0 ? -data[0] +
128 : data[0]) + " " + (data[1] < 0 ? -data[1] + 128 : data[1]));
}else */if (data != null && send != null)
{
sentmsg = "" + (send[0] < 0 ? send[0] + 256 : send[0]);
for(int i = 1; i < send.length; i++)
{
sentmsg = sentmsg + " " + (send[i] < 0 ? send[i] +
256 : send[i]);
}
receivedmsg = "" + (data[0] < 0 ? data[0] + 256 : data[0]);
for(int i = 1; i < data.length; i++)
{
receivedmsg = receivedmsg + " " + (data[i] < 0 ? data[i] + 256 : data[i]);
}
mainLabel.setText("Sent: " + sentmsg + "\n" +
"Response: " +
receivedmsg);
}else
{
mainLabel.setText("Sent or received null.");
}
} catch (IOException e) {
mainLabel.setText("Tried to talk to card, but had error: " +
e.getMessage());
}
}
First, when you send APDUs you should use an
IsoDep
object (and notNfcA
). Android should show both tag technologies as available for your card. The problem here is that Android will typically only activate the card in ISO 14443-4 protocol mode if you useIsoDep
. Thus, wehn usingNfcA
, your card will not be ready to accept APDUs.I just tested and this is at least the case on a Nexus S with Android 4.1.2. In fact trying to transceive using the
NfcA
object leads toTagLostException
s with some cards and to some other really odd behavior with another card I tried.Second, if you send
I would expect the card to return the actual application ID. However, the answer to this command (i.e.
<data> <SW1=61> <SW2=len>
) does not comply to ISO 7816-4 (no data should be returned for a 61xx status code) so this might cause a problem.UPDATE: I just tested this with a Nexus S (Android 4.1.2) and receiving such responses was not a problem.
Last, your other command (
20 0A
) is not what you expect it to be:0x00
or0x80
unless you know what you are doing (use of secure messaging, use of logical channels, ...). Though, Android (at least with NXP's NFC chipset) does not care about the structure of the APDU, but your card might!<CLA> <INS> <P1> <P2> [Lc [DATA]] <Le>
(with the special case of<CLA> <INS> <P1> <P2>
). So this means you cannot simply omit P1 and P2.