Merge "Fix stuck issue on Kovio barcode"
diff --git a/halimpl/pn54x/hal/phNxpNciHal_ext.c b/halimpl/pn54x/hal/phNxpNciHal_ext.c
index b2c5b74..def2b2d 100644
--- a/halimpl/pn54x/hal/phNxpNciHal_ext.c
+++ b/halimpl/pn54x/hal/phNxpNciHal_ext.c
@@ -304,6 +304,10 @@
p_ntf[2]--;
(*p_len)--;
}
+ else
+ {
+ p_ntf[p_ntf[2]+ 2] |= 0x01;
+ }
}
else if (p_ntf[2] == 0x02 &&
p_ntf[1] == 0x00 && icode_detected == 1)
diff --git a/src/nfa/rw/nfa_rw_act.c b/src/nfa/rw/nfa_rw_act.c
index dd1e624..5a1091d 100644
--- a/src/nfa/rw/nfa_rw_act.c
+++ b/src/nfa/rw/nfa_rw_act.c
@@ -1036,6 +1036,17 @@
nfa_rw_handle_ndef_detect(event, p_rw_data);
break;
+ case RW_T4T_NDEF_FORMAT_CPLT_EVT:
+ /* Command complete - perform cleanup, notify the app */
+ nfa_rw_command_complete ();
+ nfa_rw_cb.cur_op = NFA_RW_OP_MAX;
+ nfa_rw_cb.ndef_cur_size = p_rw_data->ndef.cur_size;
+ nfa_rw_cb.ndef_max_size = p_rw_data->ndef.max_size;
+ conn_evt_data.status = (p_rw_data->status == NFC_STATUS_OK) ? NFA_STATUS_OK : NFA_STATUS_FAILED;
+
+ nfa_dm_act_conn_cback_notify (NFA_FORMAT_CPLT_EVT, &conn_evt_data);
+ break;
+
case RW_T4T_NDEF_READ_EVT: /* Segment of data received from type 4 tag */
if (nfa_rw_cb.cur_op == NFA_RW_OP_READ_NDEF)
{
@@ -2013,6 +2024,10 @@
{
status = RW_I93FormatNDef();
}
+ else if (protocol == NFC_PROTOCOL_ISO_DEP)
+ {
+ status = RW_T4tFormatNDef ();
+ }
/* If unable to format NDEF, notify the app */
if (status != NFC_STATUS_OK)
diff --git a/src/nfc/include/rw_api.h b/src/nfc/include/rw_api.h
index 6522417..879e9b7 100644
--- a/src/nfc/include/rw_api.h
+++ b/src/nfc/include/rw_api.h
@@ -102,6 +102,7 @@
RW_T4T_PRESENCE_CHECK_EVT, /* Response to RW_T4tPresenceCheck */
RW_T4T_RAW_FRAME_EVT, /* Response of raw frame sent */
RW_T4T_INTF_ERROR_EVT, /* RF Interface error event */
+ RW_T4T_NDEF_FORMAT_CPLT_EVT, /* Format operation completed */
RW_T4T_MAX_EVT,
/* ISO 15693 tag events for tRW_CBACK */
@@ -840,6 +841,22 @@
*****************************************************************************/
NFC_API extern tNFC_STATUS RW_T3tGetSystemCodes (void);
+/*****************************************************************************
+**
+** Function RW_T4tFormatNDef
+**
+** Description
+** Format a type-4 tag for NDEF.
+**
+** Only Desifire tags are supported by this API. The
+** RW_T4T_FORMAT_CPLT_EVT is used to notify the status of the operation.
+**
+** Returns
+** NFC_STATUS_OK: if success
+** NFC_STATUS_FAILED: other error
+*****************************************************************************/
+NFC_API extern tNFC_STATUS RW_T4tFormatNDef (void);
+
/*******************************************************************************
**
** Function RW_T4tDetectNDef
diff --git a/src/nfc/include/tags_defs.h b/src/nfc/include/tags_defs.h
index 1ef48be..14d2859 100644
--- a/src/nfc/include/tags_defs.h
+++ b/src/nfc/include/tags_defs.h
@@ -335,6 +335,12 @@
#define T4T_CMD_INS_SELECT 0xA4
#define T4T_CMD_INS_READ_BINARY 0xB0
#define T4T_CMD_INS_UPDATE_BINARY 0xD6
+#define T4T_CMD_DES_CLASS 0x90
+#define T4T_CMD_INS_GET_HW_VERSION 0x60
+#define T4T_CMD_CREATE_AID 0xCA
+#define T4T_CMD_SELECT_APP 0x5A
+#define T4T_CMD_CREATE_DATAFILE 0xCD
+#define T4T_CMD_DES_WRITE 0x3D
#define T4T_CMD_P1_SELECT_BY_NAME 0x04
#define T4T_CMD_P1_SELECT_BY_FILE_ID 0x00
#define T4T_CMD_P2_FIRST_OR_ONLY_00H 0x00
@@ -377,6 +383,16 @@
#define T4T_FC_NO_WRITE_ACCESS 0xFF /* no write access granted at all (read-only) */
#define T4T_FILE_LENGTH_SIZE 0x02
+#define T4T_ADDI_FRAME_RESP 0xAFU
+#define T4T_SIZE_IDENTIFIER_2K 0x16U
+#define T4T_SIZE_IDENTIFIER_4K 0x18U
+#define T4T_SIZE_IDENTIFIER_8K 0x1AU
+#define T4T_DESEV1_MAJOR_VERSION 0x01U
+#define T4T_TYPE_DESFIRE_EV1 0x01U
+#define T4T_DESEV0_MAJOR_VERSION 0x00U
+#define T4T_DESEV0_MINOR_VERSION 0x06U
+#define T4T_DES_EV1_NFC_APP_ID 0x010000
+#define T4T_DES_EV0_NFC_APP_ID 0x10EEEE
/*
**
diff --git a/src/nfc/int/rw_int.h b/src/nfc/int/rw_int.h
index 879f7a1..908fd09 100644
--- a/src/nfc/int/rw_int.h
+++ b/src/nfc/int/rw_int.h
@@ -465,6 +465,8 @@
UINT16 max_read_size; /* max reading size per a command */
UINT16 max_update_size; /* max updating size per a command */
+ UINT16 card_size;
+ UINT8 card_type;
} tRW_T4T_CB;
/* RW retransmission statistics */
diff --git a/src/nfc/nfc/nfc_ncif.c b/src/nfc/nfc/nfc_ncif.c
index ad64930..1b0fb15 100644
--- a/src/nfc/nfc/nfc_ncif.c
+++ b/src/nfc/nfc/nfc_ncif.c
@@ -741,7 +741,8 @@
evt_data.result.rf_tech_param.mode = *p++;
p = nfc_ncif_decode_rf_params (&evt_data.result.rf_tech_param, p);
- evt_data.result.more = *p++;
+ evt_data.result.more = (*p == NCI_DISCOVER_NTF_MORE) ? TRUE : FALSE;
+ p++;
(*nfc_cb.p_discv_cback) (NFC_RESULT_DEVT, &evt_data);
}
}
diff --git a/src/nfc/tags/rw_t4t.c b/src/nfc/tags/rw_t4t.c
index 6e2b4ad..c634591 100644
--- a/src/nfc/tags/rw_t4t.c
+++ b/src/nfc/tags/rw_t4t.c
@@ -46,6 +46,8 @@
#define RW_T4T_STATE_PRESENCE_CHECK 0x05 /* checking presence of tag */
#define RW_T4T_STATE_SET_READ_ONLY 0x06 /* convert tag to read only */
+#define RW_T4T_STATE_NDEF_FORMAT 0x07 /* performing NDEF format */
+
/* sub state */
#define RW_T4T_SUBSTATE_WAIT_SELECT_APP 0x00 /* waiting for response of selecting AID */
#define RW_T4T_SUBSTATE_WAIT_SELECT_CC 0x01 /* waiting for response of selecting CC */
@@ -57,6 +59,15 @@
#define RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN 0x07 /* waiting for response of updating NLEN */
#define RW_T4T_SUBSTATE_WAIT_UPDATE_CC 0x08 /* waiting for response of updating CC */
+#define RW_T4T_SUBSTATE_WAIT_GET_HW_VERSION 0x09
+#define RW_T4T_SUBSTATE_WAIT_GET_SW_VERSION 0x0A
+#define RW_T4T_SUBSTATE_WAIT_GET_UID 0x0B
+#define RW_T4T_SUBSTATE_WAIT_CREATE_APP 0x0C
+#define RW_T4T_SUBSTATE_WAIT_CREATE_CC 0x0D
+#define RW_T4T_SUBSTATE_WAIT_CREATE_NDEF 0x0E
+#define RW_T4T_SUBSTATE_WAIT_WRITE_CC 0x0F
+#define RW_T4T_SUBSTATE_WAIT_WRITE_NDEF 0x10
+
#if (BT_TRACE_VERBOSE == TRUE)
static char *rw_t4t_get_state_name (UINT8 state);
static char *rw_t4t_get_sub_state_name (UINT8 sub_state);
@@ -70,12 +81,22 @@
static BOOLEAN rw_t4t_update_cc_to_readonly (void);
static BOOLEAN rw_t4t_select_application (UINT8 version);
static BOOLEAN rw_t4t_validate_cc_file (void);
+
+static BOOLEAN rw_t4t_get_hw_version (void);
+static BOOLEAN rw_t4t_get_sw_version (void);
+static BOOLEAN rw_t4t_create_app (void);
+static BOOLEAN rw_t4t_select_app (void);
+static BOOLEAN rw_t4t_create_ccfile (void);
+static BOOLEAN rw_t4t_create_ndef (void);
+static BOOLEAN rw_t4t_write_cc (void);
+static BOOLEAN rw_t4t_write_ndef (void);
static void rw_t4t_handle_error (tNFC_STATUS status, UINT8 sw1, UINT8 sw2);
static void rw_t4t_sm_detect_ndef (BT_HDR *p_r_apdu);
static void rw_t4t_sm_read_ndef (BT_HDR *p_r_apdu);
static void rw_t4t_sm_update_ndef (BT_HDR *p_r_apdu);
static void rw_t4t_sm_set_readonly (BT_HDR *p_r_apdu);
static void rw_t4t_data_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data);
+static void rw_t4t_sm_ndef_format (BT_HDR *p_r_apdu);
/*******************************************************************************
**
@@ -99,7 +120,510 @@
}
nfc_start_quick_timer (&rw_cb.tcb.t4t.timer, NFC_TTYPE_RW_T4T_RESPONSE,
- (RW_T4T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000);
+ (RW_T4T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000);
+
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function rw_t4t_get_hw_version
+**
+** Description Send get hw version cmd to peer
+**
+** Returns TRUE if success
+**
+*******************************************************************************/
+static BOOLEAN rw_t4t_get_hw_version (void)
+{
+ BT_HDR *p_c_apdu;
+ UINT8 *p;
+
+ p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
+
+ if (!p_c_apdu)
+ {
+ RW_TRACE_ERROR0 ("rw_t4t_get_hw_version (): Cannot allocate buffer");
+ return FALSE;
+ }
+
+ p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+ p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
+
+ UINT8_TO_BE_STREAM (p, T4T_CMD_DES_CLASS);
+ UINT8_TO_BE_STREAM (p, T4T_CMD_INS_GET_HW_VERSION);
+ UINT16_TO_BE_STREAM (p, 0x0000);
+ UINT8_TO_BE_FIELD (p, 0x00);
+
+ p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE;
+
+ if (!rw_t4t_send_to_lower (p_c_apdu))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function rw_t4t_get_sw_version
+**
+** Description Send get sw version cmd to peer
+**
+** Returns TRUE if success
+**
+*******************************************************************************/
+static BOOLEAN rw_t4t_get_sw_version (void)
+{
+ BT_HDR *p_c_apdu;
+ UINT8 *p;
+
+ p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
+
+ if (!p_c_apdu)
+ {
+ RW_TRACE_ERROR0 ("rw_t4t_get_sw_version (): Cannot allocate buffer");
+ return FALSE;
+ }
+
+ p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+ p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
+
+ UINT8_TO_BE_STREAM (p, T4T_CMD_DES_CLASS);
+ UINT8_TO_BE_STREAM (p, T4T_ADDI_FRAME_RESP);
+ UINT16_TO_BE_STREAM (p, 0x0000);
+ UINT8_TO_BE_FIELD (p, 0x00);
+
+ p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE;
+
+ if (!rw_t4t_send_to_lower (p_c_apdu))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function rw_t4t_update_version_details
+**
+** Description Updates the size of the card
+**
+** Returns TRUE if success
+**
+*******************************************************************************/
+static BOOLEAN rw_t4t_update_version_details (BT_HDR *p_r_apdu)
+{
+ tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t;
+ UINT8 *p;
+ UINT16 major_version, minor_version;
+
+ p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
+ major_version = *(p + 3);
+ minor_version = *(p + 4);
+
+ if ((T4T_DESEV0_MAJOR_VERSION == major_version) &&
+ (T4T_DESEV0_MINOR_VERSION == minor_version))
+ {
+ p_t4t->card_size = 0xEDE;
+ }
+ else if (major_version >= T4T_DESEV1_MAJOR_VERSION)
+ {
+ p_t4t->card_type = T4T_TYPE_DESFIRE_EV1;
+ switch (*(p + 5))
+ {
+ case T4T_SIZE_IDENTIFIER_2K:
+ p_t4t->card_size = 2048;
+ break;
+ case T4T_SIZE_IDENTIFIER_4K:
+ p_t4t->card_size = 4096;
+ break;
+ case T4T_SIZE_IDENTIFIER_8K:
+ p_t4t->card_size = 7680;
+ break;
+ default:
+ return FALSE;
+ }
+ }
+ else
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function rw_t4t_get_uid_details
+**
+** Description Send get uid cmd to peer
+**
+** Returns TRUE if success
+**
+*******************************************************************************/
+static BOOLEAN rw_t4t_get_uid_details (void)
+{
+ BT_HDR *p_c_apdu;
+ UINT8 *p;
+
+ p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
+
+ if (!p_c_apdu)
+ {
+ RW_TRACE_ERROR0 ("rw_t4t_get_uid_details (): Cannot allocate buffer");
+ return FALSE;
+ }
+
+ p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+ p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
+
+ UINT8_TO_BE_STREAM (p, T4T_CMD_DES_CLASS);
+ UINT8_TO_BE_STREAM (p, T4T_ADDI_FRAME_RESP);
+ UINT16_TO_BE_STREAM (p, 0x0000);
+ UINT8_TO_BE_FIELD (p, 0x00);
+
+ p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE;
+
+ if (!rw_t4t_send_to_lower (p_c_apdu))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function rw_t4t_create_app
+**
+** Description Send create application cmd to peer
+**
+** Returns TRUE if success
+**
+*******************************************************************************/
+static BOOLEAN rw_t4t_create_app (void)
+{
+ tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t;
+ BT_HDR *p_c_apdu;
+ UINT8 *p;
+ UINT8 df_name[] = {0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01};
+
+ p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
+
+ if (!p_c_apdu)
+ {
+ RW_TRACE_ERROR0 ("rw_t4t_create_app (): Cannot allocate buffer");
+ return FALSE;
+ }
+
+ p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+ p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
+
+ UINT8_TO_BE_STREAM (p, T4T_CMD_DES_CLASS);
+ UINT8_TO_BE_STREAM (p, T4T_CMD_CREATE_AID);
+ UINT16_TO_BE_STREAM (p, 0x0000);
+ if (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1)
+ {
+ UINT8_TO_BE_STREAM (p, (T4T_CMD_MAX_HDR_SIZE + sizeof(df_name) + 2));
+ UINT24_TO_BE_STREAM (p, T4T_DES_EV1_NFC_APP_ID);
+ UINT16_TO_BE_STREAM (p, 0x0F21); /*Key settings and no.of keys */
+ UINT16_TO_BE_STREAM (p, 0x05E1); /* ISO file ID */
+ ARRAY_TO_BE_STREAM (p, df_name, sizeof(df_name)); /*DF file name */
+ UINT8_TO_BE_STREAM (p, 0x00); /* Le */
+ p_c_apdu->len = 20;
+ }
+ else
+ {
+ UINT8_TO_BE_STREAM (p, T4T_CMD_MAX_HDR_SIZE);
+ UINT24_TO_BE_STREAM (p, T4T_DES_EV0_NFC_APP_ID);
+ UINT16_TO_BE_STREAM (p, 0x0F01); /*Key settings and no.of keys */
+ UINT8_TO_BE_STREAM (p, 0x00); /* Le */
+ p_c_apdu->len = 11;
+ }
+
+ if (!rw_t4t_send_to_lower (p_c_apdu))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function rw_t4t_select_app
+**
+** Description Select application cmd to peer
+**
+** Returns TRUE if success
+**
+*******************************************************************************/
+static BOOLEAN rw_t4t_select_app (void)
+{
+ tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t;
+ BT_HDR *p_c_apdu;
+ UINT8 *p;
+
+ p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
+
+ if (!p_c_apdu)
+ {
+ RW_TRACE_ERROR0 ("rw_t4t_select_app (): Cannot allocate buffer");
+ return FALSE;
+ }
+
+ p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+ p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
+
+ UINT8_TO_BE_STREAM (p, T4T_CMD_DES_CLASS);
+ UINT8_TO_BE_STREAM (p, T4T_CMD_SELECT_APP);
+ UINT16_TO_BE_STREAM (p, 0x0000);
+ UINT8_TO_BE_STREAM (p, 0x03); /* Lc: length of wrapped data */
+ if (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1)
+ {
+ UINT24_TO_BE_STREAM (p, T4T_DES_EV1_NFC_APP_ID);
+ }
+ else
+ {
+ UINT24_TO_BE_STREAM(p, T4T_DES_EV0_NFC_APP_ID);
+ }
+
+ UINT8_TO_BE_STREAM (p, 0x00); /* Le */
+
+ p_c_apdu->len = 9;
+
+ if (!rw_t4t_send_to_lower (p_c_apdu))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function rw_t4t_create_ccfile
+**
+** Description create capability container file cmd to peer
+**
+** Returns TRUE if success
+**
+*******************************************************************************/
+static BOOLEAN rw_t4t_create_ccfile (void)
+{
+ tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t;
+ BT_HDR *p_c_apdu;
+ UINT8 *p;
+
+ p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
+
+ if (!p_c_apdu)
+ {
+ RW_TRACE_ERROR0 ("rw_t4t_create_ccfile (): Cannot allocate buffer");
+ return FALSE;
+ }
+
+ p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+ p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
+
+ UINT8_TO_BE_STREAM (p, T4T_CMD_DES_CLASS);
+ UINT8_TO_BE_STREAM (p, T4T_CMD_CREATE_DATAFILE);
+ UINT16_TO_BE_STREAM (p, 0x0000);
+ if (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1)
+ {
+ UINT8_TO_BE_STREAM (p, 0x09); /* Lc: length of wrapped data */
+ UINT8_TO_BE_STREAM (p, 0x01); /* EV1 CC file id */
+ UINT16_TO_BE_STREAM (p, 0x03E1); /* ISO file id */
+ }
+ else
+ {
+ UINT8_TO_BE_STREAM (p, 0x07); /* Lc: length of wrapped data */
+ UINT8_TO_BE_STREAM (p, 0x03); /* DESFire CC file id */
+ }
+
+ UINT8_TO_BE_STREAM (p, 0x00); /* COMM settings */
+ UINT16_TO_BE_STREAM (p, 0xEEEE); /* Access rights */
+ UINT24_TO_BE_STREAM (p, 0x0F0000); /* Set file size */
+ UINT8_TO_BE_STREAM (p, 0x00); /* Le */
+
+ p_c_apdu->len = (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1) ? 15 : 13;
+
+ if (!rw_t4t_send_to_lower (p_c_apdu))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function rw_t4t_create_ndef
+**
+** Description creates an ndef file cmd to peer
+**
+** Returns TRUE if success
+**
+*******************************************************************************/
+static BOOLEAN rw_t4t_create_ndef (void)
+{
+ tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t;
+ BT_HDR *p_c_apdu;
+ UINT8 *p;
+
+ p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
+
+ if (!p_c_apdu)
+ {
+ RW_TRACE_ERROR0 ("rw_t4t_create_ndef (): Cannot allocate buffer");
+ return FALSE;
+ }
+
+ p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+ p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
+
+ UINT8_TO_BE_STREAM (p, T4T_CMD_DES_CLASS);
+ UINT8_TO_BE_STREAM (p, T4T_CMD_CREATE_DATAFILE);
+ UINT16_TO_BE_STREAM (p, 0x0000);
+ if (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1)
+ {
+ UINT8_TO_BE_STREAM (p, 0x09); /* Lc: length of wrapped data */
+ UINT8_TO_BE_STREAM (p, 0x02); /* DESFEv1 NDEF file id */
+ UINT16_TO_BE_STREAM (p, 0x04E1); /* ISO file id */
+ }
+ else
+ {
+ UINT8_TO_BE_STREAM (p, 0x07);
+ UINT8_TO_BE_STREAM (p, 0x04); /* DESF4 NDEF file id */
+ }
+
+ UINT8_TO_BE_STREAM (p, 0x00); /* COMM settings */
+ UINT16_TO_BE_STREAM (p, 0xEEEE); /* Access rights */
+ UINT16_TO_STREAM (p, p_t4t->card_size);
+ UINT8_TO_BE_STREAM (p, 0x00); /* Set card size */
+ UINT8_TO_BE_STREAM (p, 0x00); /* Le */
+
+ p_c_apdu->len = (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1) ? 15 : 13;
+
+ if (!rw_t4t_send_to_lower (p_c_apdu))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function rw_t4t_write_cc
+**
+** Description sends write cc file cmd to peer
+**
+** Returns TRUE if success
+**
+*******************************************************************************/
+static BOOLEAN rw_t4t_write_cc (void)
+{
+ tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t;
+ BT_HDR *p_c_apdu;
+ UINT8 *p;
+ UINT8 CCFileBytes[] = {0x00, 0x0F, 0x10, 0x00, 0x3B, 0x00, 0x34, 0x04, 0x06, 0xE1, 0x04, 0x04, 0x00, 0x00, 0x00};
+
+ p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
+
+ if (!p_c_apdu)
+ {
+ RW_TRACE_ERROR0 ("rw_t4t_write_cc (): Cannot allocate buffer");
+ return FALSE;
+ }
+
+ p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+ p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
+
+ UINT8_TO_BE_STREAM (p, T4T_CMD_DES_CLASS);
+ UINT8_TO_BE_STREAM (p, T4T_CMD_DES_WRITE);
+ UINT16_TO_BE_STREAM (p, 0x0000);
+ UINT8_TO_BE_STREAM (p, 0x16); /* Lc: length of wrapped data */
+ if (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1)
+ {
+ CCFileBytes[2] = 0x20;
+ CCFileBytes[11] = p_t4t->card_size >> 8;
+ CCFileBytes[12] = (UINT8) p_t4t->card_size;
+ UINT8_TO_BE_STREAM (p, 0x01); /* CC file id */
+ }
+ else
+ {
+ UINT8_TO_BE_STREAM (p, 0x03);
+ }
+
+ UINT24_TO_BE_STREAM (p, 0x000000); /* Set the offset */
+ UINT24_TO_BE_STREAM (p, 0x0F0000); /* Set available length */
+ ARRAY_TO_BE_STREAM (p, CCFileBytes, sizeof(CCFileBytes));
+ UINT8_TO_BE_STREAM (p, 0x00); /* Le */
+
+ p_c_apdu->len = 28;
+
+ if (!rw_t4t_send_to_lower (p_c_apdu))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function rw_t4t_write_ndef
+**
+** Description sends write ndef file cmd to peer
+**
+** Returns TRUE if success
+**
+*******************************************************************************/
+static BOOLEAN rw_t4t_write_ndef (void)
+{
+ tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t;
+ BT_HDR *p_c_apdu;
+ UINT8 *p;
+
+ p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
+
+ if (!p_c_apdu)
+ {
+ RW_TRACE_ERROR0 ("rw_t4t_write_ndef (): Cannot allocate buffer");
+ return FALSE;
+ }
+
+ p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+ p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
+
+ UINT8_TO_BE_STREAM (p, T4T_CMD_DES_CLASS);
+ UINT8_TO_BE_STREAM (p, T4T_CMD_DES_WRITE);
+ UINT16_TO_BE_STREAM (p, 0x0000);
+ UINT8_TO_BE_STREAM (p, 0x09); /* Lc: length of wrapped data */
+ if (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1)
+ {
+ UINT8_TO_BE_STREAM (p, 0x02); /* DESFEv1 Ndef file id */
+ }
+ else
+ {
+ UINT8_TO_BE_STREAM (p, 0x04);
+ }
+
+ UINT24_TO_BE_STREAM (p, 0x000000); /* Set the offset */
+ UINT24_TO_BE_STREAM (p, 0x020000); /* Set available length */
+ UINT16_TO_BE_STREAM (p, 0x0000); /* Ndef file bytes */
+ UINT8_TO_BE_STREAM (p, 0x00); /* Le */
+
+ p_c_apdu->len = 15;
+
+ if (!rw_t4t_send_to_lower (p_c_apdu))
+ {
+ return FALSE;
+ }
return TRUE;
}
@@ -571,6 +1095,11 @@
event = RW_T4T_SET_TO_RO_EVT;
break;
+ case RW_T4T_STATE_NDEF_FORMAT:
+ event = RW_T4T_NDEF_FORMAT_CPLT_EVT;
+ rw_data.status = NFC_STATUS_FAILED;
+ break;
+
default:
event = RW_T4T_MAX_EVT;
break;
@@ -591,6 +1120,243 @@
/*******************************************************************************
**
+** Function rw_t4t_sm_ndef_format
+**
+** Description State machine for NDEF format procedure
+**
+** Returns none
+**
+*******************************************************************************/
+static void rw_t4t_sm_ndef_format (BT_HDR *p_r_apdu)
+{
+ tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t;
+ UINT8 *p, type, length;
+ UINT16 status_words, nlen;
+ tRW_DATA rw_data;
+
+#if (BT_TRACE_VERBOSE == TRUE)
+ RW_TRACE_DEBUG2 ("rw_t4t_sm_ndef_format (): sub_state:%s (%d)",
+ rw_t4t_get_sub_state_name (p_t4t->sub_state), p_t4t->sub_state);
+#else
+ RW_TRACE_DEBUG1 ("rw_t4t_sm_ndef_format (): sub_state=%d", p_t4t->sub_state);
+#endif
+
+ /* get status words */
+ p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
+
+ switch (p_t4t->sub_state)
+ {
+ case RW_T4T_SUBSTATE_WAIT_GET_HW_VERSION:
+ p += (p_r_apdu->len - 1);
+ if (*(p) == T4T_ADDI_FRAME_RESP)
+ {
+ if (!rw_t4t_get_sw_version ())
+ {
+ rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
+ }
+ else
+ {
+ p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_GET_SW_VERSION;
+ }
+ }
+ else
+ {
+ rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
+ }
+ break;
+
+ case RW_T4T_SUBSTATE_WAIT_GET_SW_VERSION:
+ p += (p_r_apdu->len - 1);
+ if (*(p) == T4T_ADDI_FRAME_RESP)
+ {
+ if (!rw_t4t_update_version_details (p_r_apdu))
+ {
+ rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
+ }
+
+ if (!rw_t4t_get_uid_details ())
+ {
+ rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
+ }
+
+ p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_GET_UID;
+ }
+ else
+ {
+ rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
+ }
+ break;
+
+ case RW_T4T_SUBSTATE_WAIT_GET_UID:
+ p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
+ BE_STREAM_TO_UINT16 (status_words, p);
+ if (status_words != 0x9100)
+ {
+ rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
+ }
+ else
+ {
+ if (!rw_t4t_create_app ())
+ {
+ rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
+ }
+ else
+ {
+ p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_CREATE_APP;
+ }
+
+ }
+ break;
+
+ case RW_T4T_SUBSTATE_WAIT_CREATE_APP:
+ p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
+ BE_STREAM_TO_UINT16 (status_words, p);
+ if (status_words == 0x91DE) /* DUPLICATE_ERROR, file already exist*/
+ {
+ status_words = 0x9100;
+ }
+
+ if (status_words != 0x9100)
+ {
+ rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
+ }
+ else
+ {
+ if (!rw_t4t_select_app ())
+ {
+ rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
+ }
+ else
+ {
+ p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_APP;
+ }
+ }
+ break;
+
+ case RW_T4T_SUBSTATE_WAIT_SELECT_APP:
+ p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
+ BE_STREAM_TO_UINT16 (status_words, p);
+ if (status_words != 0x9100)
+ {
+ rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
+ }
+ else
+ {
+ if (!rw_t4t_create_ccfile ())
+ {
+ rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
+ }
+ else
+ {
+ p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_CREATE_CC;
+ }
+
+ }
+ break;
+
+ case RW_T4T_SUBSTATE_WAIT_CREATE_CC:
+ p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
+ BE_STREAM_TO_UINT16 (status_words, p);
+ if (status_words == 0x91DE) /* DUPLICATE_ERROR, file already exist*/
+ {
+ status_words = 0x9100;
+ }
+
+ if (status_words != 0x9100)
+ {
+ rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
+ }
+ else
+ {
+ if (!rw_t4t_create_ndef ())
+ {
+ rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
+ }
+ else
+ {
+ p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_CREATE_NDEF;
+ }
+ }
+ break;
+
+ case RW_T4T_SUBSTATE_WAIT_CREATE_NDEF:
+ p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
+ BE_STREAM_TO_UINT16 (status_words, p);
+ if (status_words == 0x91DE) /* DUPLICATE_ERROR, file already exist*/
+ {
+ status_words = 0x9100;
+ }
+
+ if (status_words != 0x9100)
+ {
+ rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
+ }
+ else
+ {
+ if (!rw_t4t_write_cc ())
+ {
+ rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
+ }
+ else
+ {
+ p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_WRITE_CC;
+ }
+ }
+ break;
+
+ case RW_T4T_SUBSTATE_WAIT_WRITE_CC:
+ p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
+ BE_STREAM_TO_UINT16 (status_words, p);
+ if (status_words != 0x9100)
+ {
+ rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
+ }
+ else
+ {
+ if (!rw_t4t_write_ndef ())
+ {
+ rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
+ }
+ else
+ {
+ p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_WRITE_NDEF;
+ }
+ }
+ break;
+
+ case RW_T4T_SUBSTATE_WAIT_WRITE_NDEF:
+ p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
+ BE_STREAM_TO_UINT16 (status_words, p);
+ if (status_words != 0x9100)
+ {
+ rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
+ }
+ else
+ {
+ p_t4t->state = RW_T4T_STATE_IDLE;
+ if (rw_cb.p_cback)
+ {
+ rw_data.ndef.status = NFC_STATUS_OK;
+ rw_data.ndef.protocol = NFC_PROTOCOL_ISO_DEP;
+ rw_data.ndef.max_size = p_t4t->card_size;
+ rw_data.ndef.cur_size = 0x00;
+
+ (*(rw_cb.p_cback)) (RW_T4T_NDEF_FORMAT_CPLT_EVT, &rw_data);
+
+ RW_TRACE_DEBUG0 ("rw_t4t_ndef_format (): Sent RW_T4T_NDEF_FORMAT_CPLT_EVT");
+ }
+ }
+ break;
+
+ default:
+ RW_TRACE_ERROR1 ("rw_t4t_sm_ndef_format (): unknown sub_state=%d", p_t4t->sub_state);
+ rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
+ break;
+ }
+}
+
+/*******************************************************************************
+**
** Function rw_t4t_sm_detect_ndef
**
** Description State machine for NDEF detection procedure
@@ -1168,14 +1934,26 @@
return;
case NFC_ERROR_CEVT:
- rw_data.status = (tNFC_STATUS) (*(UINT8*) p_data);
-
- if (p_t4t->state != RW_T4T_STATE_IDLE)
+ if (p_t4t->state == RW_T4T_STATE_PRESENCE_CHECK)
+ {
+ p_t4t->state = RW_T4T_STATE_IDLE;
+ rw_data.status = NFC_STATUS_FAILED;
+ (*(rw_cb.p_cback)) (RW_T4T_PRESENCE_CHECK_EVT, &rw_data);
+ }
+ else if (p_t4t->state == RW_T4T_STATE_NDEF_FORMAT)
+ {
+ p_t4t->state = RW_T4T_STATE_IDLE;
+ rw_data.status = NFC_STATUS_FAILED;
+ (*(rw_cb.p_cback)) (RW_T4T_NDEF_FORMAT_CPLT_EVT, &rw_data);
+ }
+ else if (p_t4t->state != RW_T4T_STATE_IDLE)
{
rw_t4t_handle_error (rw_data.status, 0, 0);
}
else
{
+ p_t4t->state = RW_T4T_STATE_IDLE;
+ rw_data.status = (tNFC_STATUS) (*(UINT8*) p_data);
(*(rw_cb.p_cback)) (RW_T4T_INTF_ERROR_EVT, &rw_data);
}
return;
@@ -1245,6 +2023,10 @@
rw_t4t_sm_set_readonly (p_r_apdu);
GKI_freebuf (p_r_apdu);
break;
+ case RW_T4T_STATE_NDEF_FORMAT:
+ rw_t4t_sm_ndef_format (p_r_apdu);
+ GKI_freebuf (p_r_apdu);
+ break;
default:
RW_TRACE_ERROR1 ("rw_t4t_data_cback (): invalid state=%d", p_t4t->state);
GKI_freebuf (p_r_apdu);
@@ -1261,6 +2043,38 @@
#endif
}
+/*******************************************************************************
+**
+** Function RW_T4tFormatNDef
+**
+** Description format T4T tag
+**
+** Returns NFC_STATUS_OK if success
+**
+*******************************************************************************/
+tNFC_STATUS RW_T4tFormatNDef (void)
+{
+ RW_TRACE_API0 ("RW_T4tFormatNDef ()");
+
+ if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE)
+ {
+ RW_TRACE_ERROR1 ("RW_T4tFormatNDef ():Unable to start command at state (0x%X)",
+ rw_cb.tcb.t4t.state);
+ return NFC_STATUS_FAILED;
+ }
+
+ rw_cb.tcb.t4t.card_type = 0x00;
+
+ if (!rw_t4t_get_hw_version ())
+ {
+ return NFC_STATUS_FAILED;
+ }
+
+ rw_cb.tcb.t4t.state = RW_T4T_STATE_NDEF_FORMAT;
+ rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_GET_HW_VERSION;
+
+ return NFC_STATUS_OK;
+}
/*******************************************************************************
**
@@ -1663,6 +2477,22 @@
return ("WAIT_UPDATE_RESP");
case RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN:
return ("WAIT_UPDATE_NLEN");
+ case RW_T4T_SUBSTATE_WAIT_GET_HW_VERSION:
+ return ("WAIT_GET_HW_VERSION");
+ case RW_T4T_SUBSTATE_WAIT_GET_SW_VERSION :
+ return ("WAIT_GET_SW_VERSION");
+ case RW_T4T_SUBSTATE_WAIT_GET_UID:
+ return ("WAIT_GET_UID");
+ case RW_T4T_SUBSTATE_WAIT_CREATE_APP:
+ return ("WAIT_CREATE_APP");
+ case RW_T4T_SUBSTATE_WAIT_CREATE_CC:
+ return ("WAIT_CREATE_CC");
+ case RW_T4T_SUBSTATE_WAIT_CREATE_NDEF:
+ return ("WAIT_CREATE_NDEF");
+ case RW_T4T_SUBSTATE_WAIT_WRITE_CC :
+ return ("WAIT_WRITE_CC");
+ case RW_T4T_SUBSTATE_WAIT_WRITE_NDEF:
+ return ("WAIT_WRITE_NDEF");
default:
return ("???? UNKNOWN SUBSTATE");
}