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");
     }