Android NfcA Transceive не удается в случае успеха
Я сделал простое тестовое приложение для быстрой отладки. Я отправляю несколько байтов, печатаю то, что отправляю, на экране телефона и печатаю то, что получаю.
Когда я посылаю НЕПРАВИЛЬНЫЕ команды, я получаю соответствующие коды ошибок в двухбайтовом SW1SW2. Я также могу вызвать свою собственную команду и переопределить SW1SW2 своими собственными значениями, и я могу получить их.
Вот проблема: Когда я отправляю ПРАВИЛЬНУЮ команду, команда transceive завершается неудачей с информативным исключением "Transceive fail".
Если я посылаю правильную команду, но переопределяю SW1SW2 на что-то, отличное от 90 00, тогда я получаю значение SW, которое я установил, но НЕТ данных ответа. (вероятно, потому что карта не отправляет ODATA, когда SW1SW2 <> 90 00)
Так почему же я уверен, что отправил правильные команды? Ну, кроме как возиться с моей собственной тестовой командой, я вызвал команду GetAppId, которая не смогла сказать, что я должен определить AppId в карте. Поэтому я определяю это в карточке, отправляю ту же команду и получаю сбой.
Так что я почти уверен, что проблема в том, что трансивер не работает, когда есть ODATA, но я не понимаю, ПОЧЕМУ или как это исправить.. помогите, пожалуйста!
РЕДАКТИРОВАТЬ: Моя карта представляет собой 7,5 D бесконтактную базовую карту от ZeitControl.
РЕДАКТИРОВАТЬ 2: Я установил время ожидания 2000 мс без изменений в поведении. Я пытаюсь вернуть один байт данных, и системная команда, которую я вызвал, тоже не выглядит тяжелой.
Затем я скачал и прикрепил исходник Android и отладил. Существовали некоторые сегменты, в которые он все равно не попадал бы - но карта, по-видимому, возвращает нулевое значение при действительных командах, если я не верну какой-то вручную установленный SW1SW2, и в этом случае это единственное полученное сообщение.
EDIT3: системная команда, которую я пробовал, была: 192 14 0 0 0 (или C0 0E 00 00 00) (или CLA INS P1 P2 Lc) Я не уверен на 100%, что делаю это правильно, но я пробовал с Различные длины (до 22) Le и без Le, как указано выше, и только без этого не дает мне 6700 (неправильно Le/Lc) Конечно, вместо 6700 он возвращает ноль, кажется...
Другая моя команда определена как 20 0A (значение в байтах), и P1/P2 не указан в файле.BAS. Я называю это с: 32 10 1 0 1 (или 20 0A 01 00 01) (или CLA INS Lc IDATA Le) Это должно означать 1-байтовые данные, установленные в 0, и 1-байтовый ожидаемый (+ SW1/SW2 как всегда). (Установка P1/P2 дает 6700, поэтому, если не определено в объявлении команды, я не думаю, что они должны быть там). Это также возвращает ноль. Я ожидаю, что 00 90 00 будет возвращен здесь. (если я установлю "значение" на 00, то есть)
Я использую HTC One X.
EDIT4: версия MinSdk = 14 и цель 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());
}
}
1 ответ
Во-первых, когда вы отправляете APDU, вы должны использовать IsoDep
объект (а не NfcA
). Android должен показывать обе технологии тегов как доступные для вашей карты. Проблема в том, что Android обычно активирует карту только в режиме протокола ISO 14443-4, если вы используете IsoDep
, Таким образом, используя NfcA
Ваша карта не будет готова к приему APDU.
Я только что проверил, и это по крайней мере так на Nexus S с Android 4.1.2. На самом деле пытается передать с помощью NfcA
объект ведет к TagLostException
с некоторыми картами и с другим действительно странным поведением с другой картой, которую я попробовал.
Во-вторых, если вы отправите
byte[] cmd = { (byte)0xC0, (byte)0x0E, (byte)0x00, (byte)0x00, (byte)0x00 };
Я ожидаю, что карта вернет фактический идентификатор приложения. Тем не менее, ответ на эту команду (т.е. <data> <SW1=61> <SW2=len>
) не соответствует стандарту ISO 7816-4 (данные для кода состояния 61xx не возвращаются), поэтому это может вызвать проблемы.
ОБНОВЛЕНИЕ: я только что проверил это с Nexus S (Android 4.1.2), и получение таких ответов не было проблемой.
Последняя ваша другая команда (20 0A
) это не то, что вы ожидаете
- Я настоятельно рекомендую вам использовать только байты CLA, установленные на
0x00
или же0x80
если вы не знаете, что делаете (использование безопасного обмена сообщениями, использование логических каналов,...). Тем не менее, Android (по крайней мере с NXP чипсетом NFC) не заботится о структуре APDU, но ваша карта может! - APDU всегда имеет форму
<CLA> <INS> <P1> <P2> [Lc [DATA]] <Le>
(с особым случаем<CLA> <INS> <P1> <P2>
). Таким образом, это означает, что вы не можете просто опустить P1 и P2. - Вы правы в том, что BasicCard будет отбрасывать ODATA, если SW<>9000 и SW1<>61.