/*****************************************************************************
**
** Function         rw_t1t_handle_rid_rsp
**
** Description      Handles response to RID: Collects HR, UID, notify up the
**                  stack
**
** Returns          event to notify application
**
*****************************************************************************/
static tRW_EVENT rw_t1t_handle_rid_rsp (BT_HDR *p_pkt)
{
    tRW_T1T_CB  *p_t1t   = &rw_cb.tcb.t1t;
    tRW_DATA    evt_data;
    UINT8       *p_rid_rsp;

    evt_data.status      = NFC_STATUS_OK;
    evt_data.data.p_data = p_pkt;

    /* Assume the data is just the response byte sequence */
    p_rid_rsp = (UINT8 *) (p_pkt + 1) + p_pkt->offset;

    /* Response indicates tag is present */
    if (p_t1t->state == RW_T1T_STATE_CHECK_PRESENCE)
    {
        /* If checking for the presence of the tag then just notify */
        return RW_T1T_PRESENCE_CHECK_EVT;
    }

    /* Extract HR and UID from response */
    STREAM_TO_ARRAY (p_t1t->hr,  p_rid_rsp, T1T_HR_LEN);

#if (BT_TRACE_VERBOSE == TRUE)
    RW_TRACE_DEBUG2 ("hr0:0x%x, hr1:0x%x", p_t1t->hr[0], p_t1t->hr[1]);
    RW_TRACE_DEBUG4 ("rw_t1t_handle_rid_rsp (): UID0-3=%02x%02x%02x%02x", p_rid_rsp[0], p_rid_rsp[1], p_rid_rsp[2], p_rid_rsp[3]);
#else
    RW_TRACE_DEBUG0 ("rw_t1t_handle_rid_rsp ()");
#endif

    /* Fetch UID0-3 from RID response message */
    STREAM_TO_ARRAY (p_t1t->mem,  p_rid_rsp, T1T_CMD_UID_LEN);

    /* Notify RID response Event */
    return RW_T1T_RID_EVT;
}
Exemple #2
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         rw_t2t_process_error
**
** Description      Process error including Timeout, Frame error. This function
**                  will retry atleast till RW_MAX_RETRIES before give up and
**                  sending negative notification to upper layer
**
** Returns          none
**
*******************************************************************************/
static void rw_t2t_process_error (void)
{
    tRW_READ_DATA           evt_data;
    tRW_EVENT               rw_event;
    BT_HDR                  *p_cmd_buf;
    tRW_T2T_CB              *p_t2t          = &rw_cb.tcb.t2t;
    tT2T_CMD_RSP_INFO       *p_cmd_rsp_info = (tT2T_CMD_RSP_INFO *) rw_cb.tcb.t2t.p_cmd_rsp_info;
    tRW_DETECT_NDEF_DATA    ndef_data;

    RW_TRACE_DEBUG1 ("rw_t2t_process_error () State: %u", p_t2t->state);

    /* Retry sending command if retry-count < max */
    if (  (!p_t2t->check_tag_halt)
        &&(rw_cb.cur_retry < RW_MAX_RETRIES)  )
    {
        /* retry sending the command */
        rw_cb.cur_retry++;

        RW_TRACE_DEBUG2 ("T2T retransmission attempt %i of %i", rw_cb.cur_retry, RW_MAX_RETRIES);

        /* allocate a new buffer for message */
        if ((p_cmd_buf = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) != NULL)
        {
            memcpy (p_cmd_buf, p_t2t->p_cur_cmd_buf, sizeof (BT_HDR) + p_t2t->p_cur_cmd_buf->offset + p_t2t->p_cur_cmd_buf->len);
#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
            /* Update stats */
            rw_main_update_tx_stats (p_cmd_buf->len, TRUE);
#endif
            if (NFC_SendData (NFC_RF_CONN_ID, p_cmd_buf) == NFC_STATUS_OK)
            {
                /* Start timer for waiting for response */
                nfc_start_quick_timer (&p_t2t->t2_timer, NFC_TTYPE_RW_T2T_RESPONSE,
                                       (RW_T2T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000);

                return;
            }
        }
    }
    else
    {
        if (p_t2t->check_tag_halt)
        {
            RW_TRACE_DEBUG0 ("T2T Went to HALT State!");
        }
        else
        {
            RW_TRACE_DEBUG1 ("T2T maximum retransmission attempts reached (%i)", RW_MAX_RETRIES);
        }
    }
    rw_event = rw_t2t_info_to_event (p_cmd_rsp_info);
#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE))
    /* update failure count */
    rw_main_update_fail_stats ();
#endif
    if (p_t2t->check_tag_halt)
    {
        evt_data.status = NFC_STATUS_REJECTED;
        p_t2t->state    = RW_T2T_STATE_HALT;
    }
    else
    {
        evt_data.status = NFC_STATUS_TIMEOUT;
    }

    if (rw_event == RW_T2T_NDEF_DETECT_EVT)
    {
        ndef_data.status    = evt_data.status;
        ndef_data.protocol  = NFC_PROTOCOL_T2T;
        ndef_data.flags     = RW_NDEF_FL_UNKNOWN;
        if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_LOCKS)
            ndef_data.flags = RW_NDEF_FL_FORMATED;
        ndef_data.max_size  = 0;
        ndef_data.cur_size  = 0;
        /* If not Halt move to idle state */
        rw_t2t_handle_op_complete ();

        (*rw_cb.p_cback) (rw_event, (tRW_DATA *) &ndef_data);
    }
    else
    {
        evt_data.p_data = NULL;
        /* If activated and not Halt move to idle state */
        if (p_t2t->state != RW_T2T_STATE_NOT_ACTIVATED)
            rw_t2t_handle_op_complete ();

        p_t2t->substate = RW_T2T_SUBSTATE_NONE;
        (*rw_cb.p_cback) (rw_event, (tRW_DATA *) &evt_data);
    }
}
Exemple #4
0
/*******************************************************************************
**
** Function         rw_t4t_sm_update_ndef
**
** Description      State machine for NDEF update procedure
**
** Returns          none
**
*******************************************************************************/
static void rw_t4t_sm_update_ndef (BT_HDR  *p_r_apdu)
{
    tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
    UINT8       *p;
    UINT16      status_words;
    tRW_DATA    rw_data;

#if (BT_TRACE_VERBOSE == TRUE)
    RW_TRACE_DEBUG2 ("rw_t4t_sm_update_ndef (): 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_update_ndef (): sub_state=%d", p_t4t->sub_state);
#endif

    /* Get status words */
    p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
    p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
    BE_STREAM_TO_UINT16 (status_words, p);

    if (status_words != T4T_RSP_CMD_CMPLTED)
    {
        rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p-2), *(p-1));
        return;
    }

    switch (p_t4t->sub_state)
    {
    case RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN:

        /* NLEN has been updated */
        /* if need to update data */
        if (p_t4t->p_update_data)
        {
            p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_RESP;

            if (!rw_t4t_update_file ())
            {
                rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
                p_t4t->p_update_data = NULL;
            }
        }
        else
        {
            p_t4t->state = RW_T4T_STATE_IDLE;

            /* just finished last step of updating (updating NLEN) */
            if (rw_cb.p_cback)
            {
                rw_data.status = NFC_STATUS_OK;

                (*(rw_cb.p_cback)) (RW_T4T_NDEF_UPDATE_CPLT_EVT, &rw_data);
                RW_TRACE_DEBUG0 ("rw_t4t_sm_update_ndef (): Sent RW_T4T_NDEF_UPDATE_CPLT_EVT");
            }
        }
        break;

    case RW_T4T_SUBSTATE_WAIT_UPDATE_RESP:

        /* if updating is not completed */
        if (p_t4t->rw_length > 0)
        {
            if (!rw_t4t_update_file ())
            {
                rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
                p_t4t->p_update_data = NULL;
            }
        }
        else
        {
            p_t4t->p_update_data = NULL;

            /* update NLEN as last step of updating file */
            if (!rw_t4t_update_nlen (p_t4t->ndef_length))
            {
                rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
            }
            else
            {
                p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN;
            }
        }
        break;

    default:
        RW_TRACE_ERROR1 ("rw_t4t_sm_update_ndef (): unknown sub_state = %d", p_t4t->sub_state);
        rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
        break;
    }
}
Exemple #5
0
/*******************************************************************************
**
** Function         rw_t4t_sm_read_ndef
**
** Description      State machine for NDEF read procedure
**
** Returns          none
**
*******************************************************************************/
static void rw_t4t_sm_read_ndef (BT_HDR *p_r_apdu)
{
    tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
    UINT8       *p;
    UINT16      status_words;
    tRW_DATA    rw_data;

#if (BT_TRACE_VERBOSE == TRUE)
    RW_TRACE_DEBUG2 ("rw_t4t_sm_read_ndef (): 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_read_ndef (): sub_state=%d", p_t4t->sub_state);
#endif

    /* get status words */
    p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
    p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
    BE_STREAM_TO_UINT16 (status_words, p);

    if (status_words != T4T_RSP_CMD_CMPLTED)
    {
        rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p-2), *(p-1));
        GKI_freebuf (p_r_apdu);
        return;
    }

    switch (p_t4t->sub_state)
    {
    case RW_T4T_SUBSTATE_WAIT_READ_RESP:

        /* Read partial or complete data */
        p_r_apdu->len -= T4T_RSP_STATUS_WORDS_SIZE;

        if ((p_r_apdu->len > 0) && (p_r_apdu->len <= p_t4t->rw_length))
        {
            p_t4t->rw_length -= p_r_apdu->len;
            p_t4t->rw_offset += p_r_apdu->len;

            if (rw_cb.p_cback)
            {
                rw_data.data.status = NFC_STATUS_OK;
                rw_data.data.p_data = p_r_apdu;

                /* if need to read more data */
                if (p_t4t->rw_length > 0)
                {
                    (*(rw_cb.p_cback)) (RW_T4T_NDEF_READ_EVT, &rw_data);

                    if (!rw_t4t_read_file (p_t4t->rw_offset, p_t4t->rw_length, TRUE))
                    {
                        rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
                    }
                }
                else
                {
                    p_t4t->state = RW_T4T_STATE_IDLE;

                    (*(rw_cb.p_cback)) (RW_T4T_NDEF_READ_CPLT_EVT, &rw_data);

                    RW_TRACE_DEBUG0 ("rw_t4t_sm_read_ndef (): Sent RW_T4T_NDEF_READ_CPLT_EVT");

                }

                p_r_apdu = NULL;
            }
            else
            {
                p_t4t->rw_length = 0;
                p_t4t->state = RW_T4T_STATE_IDLE;
            }
        }
        else
        {
            RW_TRACE_ERROR2 ("rw_t4t_sm_read_ndef (): invalid payload length (%d), rw_length (%d)",
                             p_r_apdu->len, p_t4t->rw_length);
            rw_t4t_handle_error (NFC_STATUS_BAD_RESP, 0, 0);
        }
        break;

    default:
        RW_TRACE_ERROR1 ("rw_t4t_sm_read_ndef (): unknown sub_state = %d", p_t4t->sub_state);
        rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
        break;
    }

    if (p_r_apdu)
        GKI_freebuf (p_r_apdu);
}
Exemple #6
0
/*******************************************************************************
**
** Function         rw_t4t_sm_detect_ndef
**
** Description      State machine for NDEF detection procedure
**
** Returns          none
**
*******************************************************************************/
static void rw_t4t_sm_detect_ndef (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_detect_ndef (): 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_detect_ndef (): sub_state=%d", p_t4t->sub_state);
#endif

    /* get status words */
    p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
    p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
    BE_STREAM_TO_UINT16 (status_words, p);

    if (status_words != T4T_RSP_CMD_CMPLTED)
    {
        /* try V1.0 after failing of V2.0 */
        if (  (p_t4t->sub_state == RW_T4T_SUBSTATE_WAIT_SELECT_APP)
            &&(p_t4t->version   == T4T_VERSION_2_0)  )
        {
            p_t4t->version = T4T_VERSION_1_0;

            RW_TRACE_DEBUG1 ("rw_t4t_sm_detect_ndef (): retry with version=0x%02X",
                              p_t4t->version);

            if (!rw_t4t_select_application (T4T_VERSION_1_0))
            {
                rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
            }
            return;
        }

        p_t4t->ndef_status &= ~ (RW_T4T_NDEF_STATUS_NDEF_DETECTED);
        rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p-2), *(p-1));
        return;
    }

    switch (p_t4t->sub_state)
    {
    case RW_T4T_SUBSTATE_WAIT_SELECT_APP:

        /* NDEF Tag application has been selected then select CC file */
        if (!rw_t4t_select_file (T4T_CC_FILE_ID))
        {
            rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
        }
        else
        {
            p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC;
        }
        break;

    case RW_T4T_SUBSTATE_WAIT_SELECT_CC:

        /* CC file has been selected then read mandatory part of CC file */
        if (!rw_t4t_read_file (0x00, T4T_CC_FILE_MIN_LEN, FALSE))
        {
            rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
        }
        else
        {
            p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_CC_FILE;
        }
        break;

    case RW_T4T_SUBSTATE_WAIT_CC_FILE:

        /* CC file has been read then validate and select mandatory NDEF file */
        if (p_r_apdu->len >= T4T_CC_FILE_MIN_LEN + T4T_RSP_STATUS_WORDS_SIZE)
        {
            p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;

            BE_STREAM_TO_UINT16 (p_t4t->cc_file.cclen, p);
            BE_STREAM_TO_UINT8 (p_t4t->cc_file.version, p);
            BE_STREAM_TO_UINT16 (p_t4t->cc_file.max_le, p);
            BE_STREAM_TO_UINT16 (p_t4t->cc_file.max_lc, p);

            BE_STREAM_TO_UINT8 (type, p);
            BE_STREAM_TO_UINT8 (length, p);

            if (  (type == T4T_NDEF_FILE_CONTROL_TYPE)
                &&(length == T4T_FILE_CONTROL_LENGTH)  )
            {
                BE_STREAM_TO_UINT16 (p_t4t->cc_file.ndef_fc.file_id, p);
                BE_STREAM_TO_UINT16 (p_t4t->cc_file.ndef_fc.max_file_size, p);
                BE_STREAM_TO_UINT8 (p_t4t->cc_file.ndef_fc.read_access, p);
                BE_STREAM_TO_UINT8 (p_t4t->cc_file.ndef_fc.write_access, p);

#if (BT_TRACE_VERBOSE == TRUE)
                RW_TRACE_DEBUG0 ("Capability Container (CC) file");
                RW_TRACE_DEBUG1 ("  CCLEN:  0x%04X",    p_t4t->cc_file.cclen);
                RW_TRACE_DEBUG1 ("  Version:0x%02X",    p_t4t->cc_file.version);
                RW_TRACE_DEBUG1 ("  MaxLe:  0x%04X",    p_t4t->cc_file.max_le);
                RW_TRACE_DEBUG1 ("  MaxLc:  0x%04X",    p_t4t->cc_file.max_lc);
                RW_TRACE_DEBUG0 ("  NDEF File Control TLV");
                RW_TRACE_DEBUG1 ("    FileID:      0x%04X", p_t4t->cc_file.ndef_fc.file_id);
                RW_TRACE_DEBUG1 ("    MaxFileSize: 0x%04X", p_t4t->cc_file.ndef_fc.max_file_size);
                RW_TRACE_DEBUG1 ("    ReadAccess:  0x%02X", p_t4t->cc_file.ndef_fc.read_access);
                RW_TRACE_DEBUG1 ("    WriteAccess: 0x%02X", p_t4t->cc_file.ndef_fc.write_access);
#endif

                if (rw_t4t_validate_cc_file ())
                {
                    if (!rw_t4t_select_file (p_t4t->cc_file.ndef_fc.file_id))
                    {
                        rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
                    }
                    else
                    {
                        p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE;
                    }
                    break;
                }
            }
        }

        /* invalid response or CC file */
        p_t4t->ndef_status &= ~ (RW_T4T_NDEF_STATUS_NDEF_DETECTED);
        rw_t4t_handle_error (NFC_STATUS_BAD_RESP, 0, 0);
        break;

    case RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE:

        /* NDEF file has been selected then read the first 2 bytes (NLEN) */
        if (!rw_t4t_read_file (0, T4T_FILE_LENGTH_SIZE, FALSE))
        {
            rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
        }
        else
        {
            p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_READ_NLEN;
        }
        break;

    case RW_T4T_SUBSTATE_WAIT_READ_NLEN:

        /* NLEN has been read then report upper layer */
        if (p_r_apdu->len == T4T_FILE_LENGTH_SIZE + T4T_RSP_STATUS_WORDS_SIZE)
        {
            /* get length of NDEF */
            p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
            BE_STREAM_TO_UINT16 (nlen, p);

            if (nlen <= p_t4t->cc_file.ndef_fc.max_file_size - T4T_FILE_LENGTH_SIZE)
            {
                p_t4t->ndef_status = RW_T4T_NDEF_STATUS_NDEF_DETECTED;

                if (p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS)
                {
                    p_t4t->ndef_status |= RW_T4T_NDEF_STATUS_NDEF_READ_ONLY;
                }

                /* Get max bytes to read per command */
                if (p_t4t->cc_file.max_le >= RW_T4T_MAX_DATA_PER_READ)
                {
                    p_t4t->max_read_size = RW_T4T_MAX_DATA_PER_READ;
                }
                else
                {
                    p_t4t->max_read_size = p_t4t->cc_file.max_le;
                }

                /* Le: valid range is 0x01 to 0xFF */
                if (p_t4t->max_read_size >= T4T_MAX_LENGTH_LE)
                {
                    p_t4t->max_read_size = T4T_MAX_LENGTH_LE;
                }

                /* Get max bytes to update per command */
                if (p_t4t->cc_file.max_lc >= RW_T4T_MAX_DATA_PER_WRITE)
                {
                    p_t4t->max_update_size = RW_T4T_MAX_DATA_PER_WRITE;
                }
                else
                {
                    p_t4t->max_update_size = p_t4t->cc_file.max_lc;
                }

                /* Lc: valid range is 0x01 to 0xFF */
                if (p_t4t->max_update_size >= T4T_MAX_LENGTH_LC)
                {
                    p_t4t->max_update_size = T4T_MAX_LENGTH_LC;
                }

                p_t4t->ndef_length = nlen;
                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 = (UINT32) (p_t4t->cc_file.ndef_fc.max_file_size - (UINT16) T4T_FILE_LENGTH_SIZE);
                    rw_data.ndef.cur_size = nlen;
                    rw_data.ndef.flags    = RW_NDEF_FL_SUPPORTED | RW_NDEF_FL_FORMATED;
                    if (p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS)
                    {
                        rw_data.ndef.flags    |= RW_NDEF_FL_READ_ONLY;
                    }

                    (*(rw_cb.p_cback)) (RW_T4T_NDEF_DETECT_EVT, &rw_data);

                    RW_TRACE_DEBUG0 ("rw_t4t_sm_detect_ndef (): Sent RW_T4T_NDEF_DETECT_EVT");
                }
            }
            else
            {
                /* NLEN should be less than max file size */
                RW_TRACE_ERROR2 ("rw_t4t_sm_detect_ndef (): NLEN (%d) + 2 must be <= max file size (%d)",
                                 nlen, p_t4t->cc_file.ndef_fc.max_file_size);

                p_t4t->ndef_status &= ~ (RW_T4T_NDEF_STATUS_NDEF_DETECTED);
                rw_t4t_handle_error (NFC_STATUS_BAD_RESP, 0, 0);
            }
        }
        else
        {
            /* response payload size should be T4T_FILE_LENGTH_SIZE */
            RW_TRACE_ERROR2 ("rw_t4t_sm_detect_ndef (): Length (%d) of R-APDU must be %d",
                             p_r_apdu->len, T4T_FILE_LENGTH_SIZE + T4T_RSP_STATUS_WORDS_SIZE);

            p_t4t->ndef_status &= ~ (RW_T4T_NDEF_STATUS_NDEF_DETECTED);
            rw_t4t_handle_error (NFC_STATUS_BAD_RESP, 0, 0);
        }
        break;

    default:
        RW_TRACE_ERROR1 ("rw_t4t_sm_detect_ndef (): unknown sub_state=%d", p_t4t->sub_state);
        rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
        break;
    }
}
Exemple #7
0
/*******************************************************************************
**
** Function         rw_t4t_validate_cc_file
**
** Description      Validate CC file and mandatory NDEF TLV
**
** Returns          TRUE if success
**
*******************************************************************************/
static BOOLEAN rw_t4t_validate_cc_file (void)
{
    tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;

    RW_TRACE_DEBUG0 ("rw_t4t_validate_cc_file ()");

    if (p_t4t->cc_file.cclen < T4T_CC_FILE_MIN_LEN)
    {
        RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): CCLEN (%d) is too short",
                         p_t4t->cc_file.cclen);
        return FALSE;
    }

    if (T4T_GET_MAJOR_VERSION (p_t4t->cc_file.version) != T4T_GET_MAJOR_VERSION (p_t4t->version))
    {
        RW_TRACE_ERROR2 ("rw_t4t_validate_cc_file (): Peer version (0x%02X) is matched to ours (0x%02X)",
                         p_t4t->cc_file.version, p_t4t->version);
        return FALSE;
    }

    if (p_t4t->cc_file.max_le < 0x000F)
    {
        RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): MaxLe (%d) is too small",
                         p_t4t->cc_file.max_le);
        return FALSE;
    }

    if (p_t4t->cc_file.max_lc < 0x0001)
    {
        RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): MaxLc (%d) is too small",
                         p_t4t->cc_file.max_lc);
        return FALSE;
    }

    if (  (p_t4t->cc_file.ndef_fc.file_id == T4T_CC_FILE_ID)
        ||(p_t4t->cc_file.ndef_fc.file_id == 0xE102)
        ||(p_t4t->cc_file.ndef_fc.file_id == 0xE103)
        ||((p_t4t->cc_file.ndef_fc.file_id == 0x0000) && (p_t4t->cc_file.version == 0x20))
        ||(p_t4t->cc_file.ndef_fc.file_id == 0x3F00)
        ||(p_t4t->cc_file.ndef_fc.file_id == 0x3FFF)
        ||(p_t4t->cc_file.ndef_fc.file_id == 0xFFFF)  )
    {
        RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): File ID (0x%04X) is invalid",
                          p_t4t->cc_file.ndef_fc.file_id);
        return FALSE;
    }

    if (  (p_t4t->cc_file.ndef_fc.max_file_size < 0x0005)
        ||(p_t4t->cc_file.ndef_fc.max_file_size == 0xFFFF)  )
    {
        RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): max_file_size (%d) is reserved",
                         p_t4t->cc_file.ndef_fc.max_file_size);
        return FALSE;
    }

    if (p_t4t->cc_file.ndef_fc.read_access != T4T_FC_READ_ACCESS)
    {
        RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): Read Access (0x%02X) is invalid",
                          p_t4t->cc_file.ndef_fc.read_access);
        return FALSE;
    }

    if (  (p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS)
        &&(p_t4t->cc_file.ndef_fc.write_access != T4T_FC_NO_WRITE_ACCESS)  )
    {
        RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): Write Access (0x%02X) is invalid",
                          p_t4t->cc_file.ndef_fc.write_access);
        return FALSE;
    }

    return TRUE;
}