Guest post by Martin Woolley
Today’s post is the fourth part of a si- part series on porting BlackBerry Java applications that use NFC to BlackBerry 10. So far, we’ve looked at Tag Reading, Tag Writing and Peer to Peer mode. This time, we’ll review the porting of code that deals with reading contactless NFC cards such as transportation tickets.
Here’s where we are in the series as a whole:
- Reading NFC Tags
- Writing NFC Tags
- Peer to Peer Mode
- Reading NFC Contactless Cards
- NFC Virtual Tag and Card Emulation
- NFC Card Emulation
Reading NFC Contactless Cards – Issues for Java Developers:
- Detecting the card: The application must implement the DetectionListener interface and register it with ReaderWriterManager.addDetectionListener(…). When a card comes into proximity with the device, there will be a callback to the DetectionListener.
- Exchange ISO7816-4 APDUs with the card: We then obtain an ISO14443Part4Connection object associated with the Target provided in the callback to the DetectionListener and use the connection object’s transceive method to exchange ISO7816-4 APDUs in byte array format.
The BlackBerry 10 Native approach:
We use BPS (BlackBerry Platform Services) to detect and then exchange ISO7816-4 APDUs with the card.
Detecting the card (“target”) is the same as for writing a tag and is explained elsewhere in this guide. Exchanging APDUs with the card is shown in the following code fragment which formulates and exchanges a SELECT command with the card:
<b>int</b> <b>NfcWorker::selectByAID</b>(uchar_t* the_aid, <b>int</b> aid_size, nfc_target_t* target)
<b>int</b> apdu_size = 5 + aid_size;
select_command = 0x00; // CLA
select_command = 0xA4; // INS
select_command = 0x04; // P1
select_command = 0x00; // P2
select_command = aid_size; // <span>Lc</span>
<b>int</b> j = 5;
<b>for</b> (<b>int</b> i = 0; i < aid_size; i++)
select_command[j] = the_aid[i];
<b>return</b> exchangeApdu(select_command, apdu_size, target);
<b>int</b> <b>NfcWorker::exchangeApdu</b>(uchar_t* the_apdu, <b>int</b> apdu_size, nfc_target_t* target)
QByteArray requestData = QByteArray::<b>fromRawData</b>(<b>reinterpret_cast</b><<b>const</b> <b>char</b> *>(the_apdu), apdu_size);
QString requestAsHex = QString::<b>fromAscii</b>(requestData.<b>toHex</b>());
<b>qDebug</b>() << "XXXX request:" << requestAsHex;
<b>int</b> MAX_RESPONSE_SIZE = 256;
// Allocate response buffer
// (max size determined by application)
<b>int</b> rc = <b>nfc_tag_transceive</b>(target, <i>TAG_TYPE_ISO_14443_4</i>, the_apdu, apdu_size, response, MAX_RESPONSE_SIZE, &rlength);
<b>if</b> (rc == <i>NFC_RESULT_SUCCESS</i>)
QByteArray responseData = QByteArray::<b>fromRawData</b>(<b>reinterpret_cast</b><<b>const</b> <b>char</b> *>(response), rlength);
QString responseAsHex = QString::<b>fromAscii</b>(responseData.<b>toHex</b>());
<b>qDebug</b>() << "XXXX response:" << responseAsHex;
<b>qDebug</b>() << "XXXX " << QString("ERROR transmitting APDU:%1:%2").<b>arg</b>(rc).<b>arg</b>(Utilities::<i>getOperationResultName</i>(rc));
Hopefully this was helpful and will make your porting work nice and easy!
- Exchanging APDUs with an external card (as opposed to secure element) is demonstrated in NfcTool from version 4.0.2.