Special communication units, called application protocol data units (APDUs), are used when exchanging data with a Type 4 Tag platform. Command APDUs (C-APDUs) are the commands sent from the NFC reader, while the response APDUs (R-APDUs) are the responses to a specific command received by NFC reader from the tag.
The APDU reader/writer module provides functions to encode a C-APDU according to its descriptor and to decode a raw R-APDU data into the appropriate descriptor. For the API documentation of this module, refer to APDU reader/writer .
APDU types
There are three types of APDU that are relevant for the Type 4 Tag platform:
| APDU type | Description |
|---|---|
| Select | Selection of applications or files. |
| ReadBinary | Reading data from a file. |
| UpdateBinary | Writing data to a file. |
C-APDU and R-APDU format
A C-APDU consists of the following fields:
| Field | Length | Required | Description |
|---|---|---|---|
| CLA | 1 byte | yes | Specifies the security level of the message. |
| INS | 1 byte | yes | Specifies the command type to process. See APDU types . |
| P1 | 1 byte | yes | Specifies the first parameter for the chosen command type. |
| P2 | 1 byte | yes | Specifies the second parameter for the chosen command type. |
| Lc | 1 or 3 bytes | no | Specifies the data length. |
| Data | Lc bytes | no | Required if LC field is present. Contains payload of C-APDU. |
| Le | 1 or 2 bytes | no | Specifies the expected response body length of R-APDU. |
An R-APDU consists of the following fields:
| Field | Length | Required | Description |
|---|---|---|---|
| Response Body | variable | no | Carries the data of the R-APDU. |
| SW1 | 1 byte | yes | Specifies the first status word. |
| SW2 | 1 byte | yes | Specifies the second status word. |
Generating C-APDU and decoding R-APDU
The following code example shows how to build a C-APDU which can be used in CC/NDEF select procedure (see Type 4 Tag NDEF detection procedure ):
ret_code_t err_code;
nfc_t4t_comm_apdu_t capdu;
uint8_t apdu_buff[APDU_BUFF_SIZE];
uint8_t file_id_buff[] = ...; // 2-byte long File Identifier, for example: {0xE1, 0x04}
nfc_t4t_comm_apdu_clear(&capdu);
capdu.instruction = NFC_T4T_CAPDU_SELECT_INS;
capdu.parameter = SELECT_BY_FILE_ID;
uint16_t apdu_buff_len = APDU_BUFF_SIZE;
ret_code_t err_code = nfc_t4t_comm_apdu_encode(&capdu,
apdu_buff,
&apdu_buff_len);
if (err_code != NRF_SUCCESS)
{
//Error during C-APDU generation.
return err_code;
}
Note that the Le field is not present in this case.
The following code example shows how to create a C-APDU descriptor which can be used in CC/NDEF read procedure (see Type 4 Tag NDEF detection procedure ):
uint16_t file_offset = ...; // File offset where to start reading data.
uint16_t file_bytes_to_read = ...; // The number of bytes to be read from file.
nfc_t4t_comm_apdu_clear(&capdu);
capdu.instruction = NFC_T4T_CAPDU_READ_INS;
capdu.parameter = file_offset;
capdu.resp_len = file_bytes_to_read;
Note that Lc and Data fields are not present in this case. You must also ensure that the number of bytes to write (the value carried by the Le field) is not greater than the MLe (Maximum R-APDU data) field, which is located in the CC file.
The following code example shows how to create a C-APDU descriptor which can be used in the NDEF update procedure (see Type 4 Tag NDEF detection procedure ):
uint8_t ndef_file_buff = ...; // NDEF file buffer.
uint16_t file_offset = ...; // File offset where to start writing data.
uint16_t file_bytes_to_write = ...; // The number of bytes to be written to the file.
nfc_t4t_comm_apdu_clear(&capdu);
capdu.instruction = NFC_T4T_CAPDU_UPDATE_INS;
capdu.parameter = file_offset;
Note that the Le field is not present in this case. You also need to ensure that the number of bytes to read (value carried by the Lc field) is not greater than the MLc (Maximum C-APDU data) field, which is located in the CC file.
The last code example shows how to decode a raw R-APDU data to its descriptor:
ret_code_t err_code;
nfc_t4t_resp_apdu_t rapdu;
uint8_t rapdu_buff[] = ...; // Buffer with raw R-APDU data.
err_code = nfc_t4t_resp_apdu_decode(&rapdu, rapdu_buff, sizeof(rapdu_buff));
if (err_code != NRF_SUCCESS)
{
//Error during R-APDU decoding.
return err_code;
}
//Print R-APDU descriptor.
nfc_t4t_resp_apdu_printout(p_rapdu);
Note that if the Response Body field is not present in the R-APDU, the data field in the R-APDU descriptor is equal to NULL .