/*******************************************************************************
**
** Function         rw_t2t_select
**
** Description      This function selects type 2 tag.
**
** Returns          Tag selection status
**
*******************************************************************************/
tNFC_STATUS rw_t2t_select (void)
{
    tRW_T2T_CB    *p_t2t = &rw_cb.tcb.t2t;

    p_t2t->state       = RW_T2T_STATE_IDLE;
    p_t2t->ndef_status = T2T_NDEF_NOT_DETECTED;


    /* Alloc cmd buf for retransmissions */
    if (p_t2t->p_cur_cmd_buf ==  NULL)
    {
        if ((p_t2t->p_cur_cmd_buf = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) == NULL)
        {
            RW_TRACE_ERROR0 ("rw_t2t_select: unable to allocate buffer for retransmission");
            return (NFC_STATUS_FAILED);
        }
    }
    /* Alloc cmd buf for holding a command untill sector changes */
    if (p_t2t->p_sec_cmd_buf ==  NULL)
    {
        if ((p_t2t->p_sec_cmd_buf = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) == NULL)
        {
            RW_TRACE_ERROR0 ("rw_t2t_select: unable to allocate buffer used during sector change");
            return (NFC_STATUS_FAILED);
        }
    }

    NFC_SetStaticRfCback (rw_t2t_conn_cback);
    rw_t2t_handle_op_complete ();
    p_t2t->check_tag_halt = FALSE;

    return NFC_STATUS_OK;
}
/*******************************************************************************
**
** Function         rw_t1t_select
**
** Description      This function will set the callback function to
**                  receive data from lower layers and also send rid command
**
** Returns          none
**
*******************************************************************************/
tNFC_STATUS rw_t1t_select (UINT8 hr[T1T_HR_LEN], UINT8 uid[T1T_CMD_UID_LEN])
{
    tNFC_STATUS status  = NFC_STATUS_FAILED;
    tRW_T1T_CB  *p_t1t  = &rw_cb.tcb.t1t;

    p_t1t->state = RW_T1T_STATE_NOT_ACTIVATED;

    /* Alloc cmd buf for retransmissions */
    if (p_t1t->p_cur_cmd_buf ==  NULL)
    {
        if ((p_t1t->p_cur_cmd_buf = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) == NULL)
        {
            RW_TRACE_ERROR0 ("rw_t1t_select: unable to allocate buffer for retransmission");
            return status;
        }
    }

    memcpy (p_t1t->hr, hr, T1T_HR_LEN);
    memcpy (p_t1t->mem, uid, T1T_CMD_UID_LEN);

    NFC_SetStaticRfCback (rw_t1t_conn_cback);

    p_t1t->state    = RW_T1T_STATE_IDLE;

    return NFC_STATUS_OK;
}
Beispiel #3
0
/*******************************************************************************
**
** Function         ce_select_t4t
**
** Description      Select Type 4 Tag
**
** Returns          NFC_STATUS_OK if success
**
*******************************************************************************/
tNFC_STATUS ce_select_t4t (void)
{
    tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t;

    CE_TRACE_DEBUG0 ("ce_select_t4t ()");

    nfc_stop_quick_timer (&p_t4t->timer);

    /* clear other than read-only flag */
    p_t4t->status &= CE_T4T_STATUS_NDEF_FILE_READ_ONLY;

    NFC_SetStaticRfCback (ce_t4t_data_cback);

    return NFC_STATUS_OK;
}
Beispiel #4
0
/*******************************************************************************
**
** Function         nfa_rw_sys_disable
**
** Description      Clean up rw sub-system
**
**
** Returns          void
**
*******************************************************************************/
void nfa_rw_sys_disable (void)
{
    /* Return to idle */
    NFC_SetStaticRfCback (NULL);

    /* Stop presence check timer (if started) */
    nfa_rw_stop_presence_check_timer ();

    /* Free scratch buffer if any */
    nfa_rw_free_ndef_rx_buf ();

    /* Free pending command if any */
    if (nfa_rw_cb.p_pending_msg)
    {
        GKI_freebuf (nfa_rw_cb.p_pending_msg);
        nfa_rw_cb.p_pending_msg = NULL;
    }

    nfa_sys_deregister (NFA_ID_RW);
}
Beispiel #5
0
/*******************************************************************************
**
** Function         rw_t4t_select
**
** Description      Initialise T4T
**
** Returns          NFC_STATUS_OK if success
**
*******************************************************************************/
tNFC_STATUS rw_t4t_select (void)
{
    tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;

    RW_TRACE_DEBUG0 ("rw_t4t_select ()");

    NFC_SetStaticRfCback (rw_t4t_data_cback);

    p_t4t->state   = RW_T4T_STATE_IDLE;
    p_t4t->version = T4T_MY_VERSION;

    /* set it min of max R-APDU data size before reading CC file */
    p_t4t->cc_file.max_le = T4T_MIN_MLE;

    /* These will be udated during NDEF detection */
    p_t4t->max_read_size   = T4T_MAX_LENGTH_LE;
    p_t4t->max_update_size = T4T_MAX_LENGTH_LC;

    return NFC_STATUS_OK;
}
/*******************************************************************************
**
** Function         CE_SetActivatedTagType
**
** Description      This function selects the tag type for CE mode.
**
** Returns          tNFC_STATUS
**
*******************************************************************************/
tNFC_STATUS CE_SetActivatedTagType (tNFC_ACTIVATE_DEVT *p_activate_params, UINT16 t3t_system_code, tCE_CBACK *p_cback)
{
    tNFC_STATUS status = NFC_STATUS_FAILED;
    tNFC_PROTOCOL protocol = p_activate_params->protocol;

    CE_TRACE_API1 ("CE_SetActivatedTagType protocol:%d", protocol);

    switch (protocol)
    {
    case NFC_PROTOCOL_T1T:
    case NFC_PROTOCOL_T2T:
        return NFC_STATUS_FAILED;

    case NFC_PROTOCOL_T3T:   /* Type3Tag    - NFC-F */
        /* store callback function before NFC_SetStaticRfCback () */
        ce_cb.p_cback  = p_cback;
        status = ce_select_t3t (t3t_system_code, p_activate_params->rf_tech_param.param.lf.nfcid2);
        break;

    case NFC_PROTOCOL_ISO_DEP:     /* ISODEP/4A,4B- NFC-A or NFC-B */
        /* store callback function before NFC_SetStaticRfCback () */
        ce_cb.p_cback  = p_cback;
        status = ce_select_t4t ();
        break;

    default:
        CE_TRACE_ERROR0 ("CE_SetActivatedTagType Invalid protocol");
        return NFC_STATUS_FAILED;
    }

    if (status != NFC_STATUS_OK)
    {
        NFC_SetStaticRfCback (NULL);
        ce_cb.p_cback  = NULL;
    }
    return status;
}
Beispiel #7
0
/*******************************************************************************
**
** Function         ce_t4t_data_cback
**
** Description      This callback function receives the data from NFCC.
**
** Returns          none
**
*******************************************************************************/
static void ce_t4t_data_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data)
{
    BT_HDR  *p_c_apdu;
    UINT8   *p_cmd;
    UINT8    cla, instruct, select_type = 0, length;
    UINT16   offset, max_file_size;
    tCE_DATA ce_data;

    if (event == NFC_DEACTIVATE_CEVT)
    {
        NFC_SetStaticRfCback (NULL);
        return;
    }
    if (event != NFC_DATA_CEVT)
    {
        return;
    }

    p_c_apdu = (BT_HDR *) p_data->data.p_data;

#if (BT_TRACE_PROTOCOL == TRUE)
    DispCET4Tags (p_c_apdu, TRUE);
#endif

    CE_TRACE_DEBUG1 ("ce_t4t_data_cback (): conn_id = 0x%02X", conn_id);

    p_cmd = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;

    /* Class Byte */
    BE_STREAM_TO_UINT8 (cla, p_cmd);

    /* Don't check class if registered AID has been selected */
    if (  (cla != T4T_CMD_CLASS)
        &&((ce_cb.mem.t4t.status & CE_T4T_STATUS_REG_AID_SELECTED) == 0)
        &&((ce_cb.mem.t4t.status & CE_T4T_STATUS_WILDCARD_AID_SELECTED) == 0)  )
    {
        GKI_freebuf (p_c_apdu);
        ce_t4t_send_status (T4T_RSP_CLASS_NOT_SUPPORTED);
        return;
    }

    /* Instruction Byte */
    BE_STREAM_TO_UINT8 (instruct, p_cmd);

    if ((cla == T4T_CMD_CLASS) && (instruct == T4T_CMD_INS_SELECT))
    {
        /* P1 Byte */
        BE_STREAM_TO_UINT8 (select_type, p_cmd);

        if (select_type == T4T_CMD_P1_SELECT_BY_NAME)
        {
            ce_t4t_process_select_app_cmd (p_cmd, p_c_apdu);
            return;
        }
    }

    /* if registered AID is selected */
    if (ce_cb.mem.t4t.status & CE_T4T_STATUS_REG_AID_SELECTED)
    {
        CE_TRACE_DEBUG0 ("CET4T: Forward raw frame to registered AID");

        /* forward raw frame to upper layer */
        if (ce_cb.mem.t4t.selected_aid_idx < CE_T4T_MAX_REG_AID)
        {
            ce_data.raw_frame.status = p_data->data.status;
            ce_data.raw_frame.p_data = p_c_apdu;
            ce_data.raw_frame.aid_handle = ce_cb.mem.t4t.selected_aid_idx;
            p_c_apdu = NULL;

            (*(ce_cb.mem.t4t.reg_aid[ce_cb.mem.t4t.selected_aid_idx].p_cback)) (CE_T4T_RAW_FRAME_EVT, &ce_data);
        }
        else
        {
            GKI_freebuf (p_c_apdu);
            ce_t4t_send_status (T4T_RSP_NOT_FOUND);
        }
    }
    else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_WILDCARD_AID_SELECTED)
    {
        CE_TRACE_DEBUG0 ("CET4T: Forward raw frame to wildcard AID handler");

        /* forward raw frame to upper layer */
        ce_data.raw_frame.status = p_data->data.status;
        ce_data.raw_frame.p_data = p_c_apdu;
        ce_data.raw_frame.aid_handle = CE_T4T_WILDCARD_AID_HANDLE;
        p_c_apdu = NULL;

        (*(ce_cb.mem.t4t.p_wildcard_aid_cback)) (CE_T4T_RAW_FRAME_EVT, &ce_data);
    }
    else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_T4T_APP_SELECTED)
    {
        if (instruct == T4T_CMD_INS_SELECT)
        {
            /* P1 Byte is already parsed */
            if (select_type == T4T_CMD_P1_SELECT_BY_FILE_ID)
            {
                ce_t4t_process_select_file_cmd (p_cmd);
            }
            else
            {
                CE_TRACE_ERROR1 ("CET4T: Bad P1 byte (0x%02X)", select_type);
                ce_t4t_send_status (T4T_RSP_WRONG_PARAMS);
            }
        }
        else if (instruct == T4T_CMD_INS_READ_BINARY)
        {
            if (  (ce_cb.mem.t4t.status & CE_T4T_STATUS_CC_FILE_SELECTED)
                ||(ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_SELECTED)  )
            {
                if (ce_cb.mem.t4t.status & CE_T4T_STATUS_CC_FILE_SELECTED)
                {
                    max_file_size = T4T_FC_TLV_OFFSET_IN_CC + T4T_FILE_CONTROL_TLV_SIZE;
                }
                else
                {
                    max_file_size = ce_cb.mem.t4t.max_file_size;
                }

                BE_STREAM_TO_UINT16 (offset, p_cmd); /* Offset */
                BE_STREAM_TO_UINT8 (length, p_cmd); /* Le     */

                /* check if valid parameters */
                if (length <= CE_T4T_MAX_LE)
                {
                    /* CE allows to read more than current file size but not max file size */
                    if (length + offset > max_file_size)
                    {
                        if (offset < max_file_size)
                        {
                            length = (UINT8) (max_file_size - offset);

                            CE_TRACE_DEBUG2 ("CET4T: length is reduced to %d by max_file_size (%d)",
                                              length, max_file_size);
                        }
                        else
                        {
                            CE_TRACE_ERROR2 ("CET4T: offset (%d) must be less than max_file_size (%d)",
                                              offset, max_file_size);
                            length = 0;
                        }
                    }
                }
                else
                {
                    CE_TRACE_ERROR2 ("CET4T: length (%d) must be less than MLe (%d)",
                                      length, CE_T4T_MAX_LE);
                    length = 0;
                }

                if (length > 0)
                    ce_t4t_read_binary (offset, length);
                else
                    ce_t4t_send_status (T4T_RSP_WRONG_PARAMS);
            }
            else
            {
                CE_TRACE_ERROR0 ("CET4T: File has not been selected");
                ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED);
            }
        }
        else if (instruct == T4T_CMD_INS_UPDATE_BINARY)
        {
            if (ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_FILE_READ_ONLY)
            {
                CE_TRACE_ERROR0 ("CET4T: No access right");
                ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED);
            }
            else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_SELECTED)
            {
                BE_STREAM_TO_UINT16 (offset, p_cmd); /* Offset */
                BE_STREAM_TO_UINT8 (length, p_cmd); /* Lc     */

                /* check if valid parameters */
                if (length <= CE_T4T_MAX_LC)
                {
                    if (length + offset > ce_cb.mem.t4t.max_file_size)
                    {
                        CE_TRACE_ERROR3 ("CET4T: length (%d) + offset (%d) must be less than max_file_size (%d)",
                                          length, offset, ce_cb.mem.t4t.max_file_size);
                        length = 0;
                    }
                }
                else
                {
                    CE_TRACE_ERROR2 ("CET4T: length (%d) must be less than MLc (%d)",
                                      length, CE_T4T_MAX_LC);
                    length = 0;
                }

                if (length > 0)
                    ce_t4t_update_binary (offset, length, p_cmd);
                else
                    ce_t4t_send_status (T4T_RSP_WRONG_PARAMS);
            }
            else
            {
                CE_TRACE_ERROR0 ("CET4T: NDEF File has not been selected");
                ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED);
            }
        }
        else
        {
            CE_TRACE_ERROR1 ("CET4T: Unsupported Instruction byte (0x%02X)", instruct);
            ce_t4t_send_status (T4T_RSP_INSTR_NOT_SUPPORTED);
        }
    }
    else
    {
        CE_TRACE_ERROR0 ("CET4T: Application has not been selected");
        ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED);
    }

    if (p_c_apdu)
        GKI_freebuf (p_c_apdu);
}
/*******************************************************************************
**
** Function         rw_t2t_conn_cback
**
** Description      This callback function receives events/data from NFCC.
**
** Returns          none
**
*******************************************************************************/
void rw_t2t_conn_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data)
{
    tRW_T2T_CB  *p_t2t  = &rw_cb.tcb.t2t;
    tRW_READ_DATA       evt_data;

    RW_TRACE_DEBUG2 ("rw_t2t_conn_cback: conn_id=%i, evt=%i", conn_id, event);
    /* Only handle static conn_id */
    if (conn_id != NFC_RF_CONN_ID)
    {
        return;
    }

    switch (event)
    {
    case NFC_CONN_CREATE_CEVT:
    case NFC_CONN_CLOSE_CEVT:
        break;

    case NFC_DEACTIVATE_CEVT:
#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
        /* Display stats */
        rw_main_log_stats ();
#endif
        /* Stop t2t timer (if started) */
        nfc_stop_quick_timer (&p_t2t->t2_timer);

        /* Free cmd buf for retransmissions */
        if (p_t2t->p_cur_cmd_buf)
        {
            GKI_freebuf (p_t2t->p_cur_cmd_buf);
            p_t2t->p_cur_cmd_buf = NULL;
        }
        /* Free cmd buf used to hold command before sector change */
        if (p_t2t->p_sec_cmd_buf)
        {
            GKI_freebuf (p_t2t->p_sec_cmd_buf);
            p_t2t->p_sec_cmd_buf = NULL;
        }

        p_t2t->state = RW_T2T_STATE_NOT_ACTIVATED;
        NFC_SetStaticRfCback (NULL);
        break;

    case NFC_DATA_CEVT:
        if (  (p_data != NULL)
            &&(  (p_data->data.status == NFC_STATUS_OK)
               ||(p_data->data.status == NFC_STATUS_CONTINUE)  )  )
        {
            rw_t2t_proc_data (conn_id, &(p_data->data));
            break;
        }
        /* Data event with error status...fall through to NFC_ERROR_CEVT case */

    case NFC_ERROR_CEVT:
        if (  (p_t2t->state == RW_T2T_STATE_NOT_ACTIVATED)
            ||(p_t2t->state == RW_T2T_STATE_IDLE)
            ||(p_t2t->state == RW_T2T_STATE_HALT)  )
        {
#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
            rw_main_update_trans_error_stats ();
#endif  /* RW_STATS_INCLUDED */
            if (event == NFC_ERROR_CEVT)
                evt_data.status = (tNFC_STATUS) (*(UINT8*) p_data);
            else if (p_data)
                evt_data.status = p_data->status;
            else
                evt_data.status = NFC_STATUS_FAILED;

            evt_data.p_data = NULL;
            (*rw_cb.p_cback) (RW_T2T_INTF_ERROR_EVT, (tRW_DATA *) &evt_data);
            break;
        }
        nfc_stop_quick_timer (&p_t2t->t2_timer);
#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
        rw_main_update_trans_error_stats ();
#endif
        if (p_t2t->state == RW_T2T_STATE_CHECK_PRESENCE)
        {
            if (p_t2t->check_tag_halt)
            {
                p_t2t->state = RW_T2T_STATE_HALT;
                rw_t2t_handle_presence_check_rsp (NFC_STATUS_REJECTED);
            }
            else
            {
                /* Move back to idle state */
                rw_t2t_handle_presence_check_rsp (NFC_STATUS_FAILED);
            }
        }
        else
        {
            rw_t2t_process_error ();
        }
#if(NFC_NXP_NOT_OPEN_INCLUDED == TRUE)
        /* Free the response buffer in case of invalid response*/
        if (p_data != NULL) {
                GKI_freebuf((BT_HDR *) (p_data->data.p_data));
        }
#endif
        break;

    default:
        break;

    }
}
Beispiel #9
0
/*******************************************************************************
**
** Function         rw_t1t_conn_cback
**
** Description      This callback function receives the events/data from NFCC.
**
** Returns          none
**
*******************************************************************************/
void rw_t1t_conn_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data)
{
    tRW_T1T_CB          *p_t1t  = &rw_cb.tcb.t1t;
    tRW_READ_DATA       evt_data;

    RW_TRACE_DEBUG2 ("rw_t1t_conn_cback: conn_id=%i, evt=0x%x", conn_id, event);
    /* Only handle static conn_id */
    if (conn_id != NFC_RF_CONN_ID)
    {
        RW_TRACE_WARNING1 ("rw_t1t_conn_cback - Not static connection id: =%i", conn_id);
        return;
    }

    switch (event)
    {
    case NFC_CONN_CREATE_CEVT:
    case NFC_CONN_CLOSE_CEVT:
        break;

    case NFC_DEACTIVATE_CEVT:
#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
        /* Display stats */
        rw_main_log_stats ();
#endif  /* RW_STATS_INCLUDED */

        /* Stop t1t timer (if started) */
        nfc_stop_quick_timer (&p_t1t->timer);

        /* Free cmd buf for retransmissions */
        if (p_t1t->p_cur_cmd_buf)
        {
            GKI_freebuf (p_t1t->p_cur_cmd_buf);
            p_t1t->p_cur_cmd_buf = NULL;
        }

        p_t1t->state = RW_T1T_STATE_NOT_ACTIVATED;
        NFC_SetStaticRfCback (NULL);
        break;

    case NFC_DATA_CEVT:
        if (  (p_data != NULL)
            &&(p_data->data.status == NFC_STATUS_OK)  )
        {
            rw_t1t_data_cback (conn_id, event, p_data);
            break;
        }
        /* Data event with error status...fall through to NFC_ERROR_CEVT case */

    case NFC_ERROR_CEVT:
        if (  (p_t1t->state == RW_T1T_STATE_NOT_ACTIVATED)
            ||(p_t1t->state == RW_T1T_STATE_IDLE)  )
        {
#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
            rw_main_update_trans_error_stats ();
#endif  /* RW_STATS_INCLUDED */

            if (event == NFC_ERROR_CEVT)
                evt_data.status = (tNFC_STATUS) (*(UINT8*) p_data);
            else if (p_data)
                evt_data.status = p_data->status;
            else
                evt_data.status = NFC_STATUS_FAILED;

            evt_data.p_data = NULL;
            (*rw_cb.p_cback) (RW_T1T_INTF_ERROR_EVT, (tRW_DATA *) &evt_data);
            break;
        }
        nfc_stop_quick_timer (&p_t1t->timer);

#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
        rw_main_update_trans_error_stats ();
#endif  /* RW_STATS_INCLUDED */

        if (p_t1t->state == RW_T1T_STATE_CHECK_PRESENCE)
        {
            rw_t1t_handle_presence_check_rsp (NFC_STATUS_FAILED);
        }
        else
        {
            rw_t1t_process_error ();
        }
        break;

    default:
        break;

    }
}
Beispiel #10
0
/*******************************************************************************
**
** Function         rw_t4t_data_cback
**
** Description      This callback function receives the data from NFCC.
**
** Returns          none
**
*******************************************************************************/
static void rw_t4t_data_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data)
{
    tRW_T4T_CB *p_t4t    = &rw_cb.tcb.t4t;
    BT_HDR     *p_r_apdu = (BT_HDR *) p_data->data.p_data;
    tRW_DATA    rw_data;

#if (BT_TRACE_VERBOSE == TRUE)
    UINT8  begin_state   = p_t4t->state;
#endif

    RW_TRACE_DEBUG1 ("rw_t4t_data_cback () event = 0x%X", event);
    nfc_stop_quick_timer (&p_t4t->timer);

    switch (event)
    {
    case NFC_DEACTIVATE_CEVT:
        NFC_SetStaticRfCback (NULL);
        p_t4t->state = RW_T4T_STATE_NOT_ACTIVATED;
        return;

    case NFC_ERROR_CEVT:
        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
        {
            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;

    case NFC_DATA_CEVT:
        break;

    default:
        return;
    }

#if (BT_TRACE_PROTOCOL == TRUE)
    DispRWT4Tags (p_r_apdu, TRUE);
#endif

#if (BT_TRACE_VERBOSE == TRUE)
    RW_TRACE_DEBUG2 ("RW T4T state: <%s (%d)>",
                        rw_t4t_get_state_name (p_t4t->state), p_t4t->state);
#else
    RW_TRACE_DEBUG1 ("RW T4T state: %d", p_t4t->state);
#endif

    switch (p_t4t->state)
    {
    case RW_T4T_STATE_IDLE:
        /* Unexpected R-APDU, it should be raw frame response */
        /* forward to upper layer without parsing */
        if (rw_cb.p_cback)
        {
            rw_data.raw_frame.status = NFC_STATUS_OK;
            rw_data.raw_frame.p_data = p_r_apdu;
            (*(rw_cb.p_cback)) (RW_T4T_RAW_FRAME_EVT, &rw_data);
            p_r_apdu = NULL;
        }
        else
        {
            GKI_freebuf (p_r_apdu);
        }
        break;
    case RW_T4T_STATE_DETECT_NDEF:
        rw_t4t_sm_detect_ndef (p_r_apdu);
        GKI_freebuf (p_r_apdu);
        break;
    case RW_T4T_STATE_READ_NDEF:
        rw_t4t_sm_read_ndef (p_r_apdu);
        /* p_r_apdu may send upper lyaer */
        break;
    case RW_T4T_STATE_UPDATE_NDEF:
        rw_t4t_sm_update_ndef (p_r_apdu);
        GKI_freebuf (p_r_apdu);
        break;
    case RW_T4T_STATE_PRESENCE_CHECK:
        /* if any response, send presence check with ok */
        rw_data.status = NFC_STATUS_OK;
        p_t4t->state = RW_T4T_STATE_IDLE;
        (*(rw_cb.p_cback)) (RW_T4T_PRESENCE_CHECK_EVT, &rw_data);
        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);
        break;
    }

#if (BT_TRACE_VERBOSE == TRUE)
    if (begin_state != p_t4t->state)
    {
        RW_TRACE_DEBUG2 ("RW T4T state changed:<%s> -> <%s>",
                          rw_t4t_get_state_name (begin_state),
                          rw_t4t_get_state_name (p_t4t->state));
    }
#endif
}