/******************************************************************************* ** ** Function rw_t2t_send_cmd ** ** Description This function composes a Type 2 Tag command and send it via ** NCI to NFCC. ** ** Returns NFC_STATUS_OK if the command is successfuly sent to NCI ** otherwise, error status ** *******************************************************************************/ tNFC_STATUS rw_t2t_send_cmd (UINT8 opcode, UINT8 *p_dat) { tNFC_STATUS status = NFC_STATUS_FAILED; tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t; const tT2T_CMD_RSP_INFO *p_cmd_rsp_info = t2t_cmd_to_rsp_info (opcode); BT_HDR *p_data; UINT8 *p; if (p_cmd_rsp_info) { /* a valid opcode for RW */ p_data = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID); if (p_data) { p_t2t->p_cmd_rsp_info = (tT2T_CMD_RSP_INFO *) p_cmd_rsp_info; p_data->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; p = (UINT8 *) (p_data + 1) + p_data->offset; UINT8_TO_STREAM (p, opcode); if (p_dat) { ARRAY_TO_STREAM (p, p_dat, (p_cmd_rsp_info->cmd_len - 1)); } p_data->len = p_cmd_rsp_info->cmd_len; /* Indicate first attempt to send command, back up cmd buffer in case needed for retransmission */ rw_cb.cur_retry = 0; memcpy (p_t2t->p_cur_cmd_buf, p_data, sizeof (BT_HDR) + p_data->offset + p_data->len); #if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE)) /* Update stats */ rw_main_update_tx_stats (p_data->len, FALSE); #endif RW_TRACE_EVENT2 ("RW SENT [%s]:0x%x CMD", t2t_info_to_str (p_cmd_rsp_info), p_cmd_rsp_info->opcode); if ((status = NFC_SendData (NFC_RF_CONN_ID, p_data)) == NFC_STATUS_OK) { nfc_start_quick_timer (&p_t2t->t2_timer, NFC_TTYPE_RW_T2T_RESPONSE, (RW_T2T_TOUT_RESP*QUICK_TIMER_TICKS_PER_SEC) / 1000); } else { #if (BT_TRACE_VERBOSE == TRUE) RW_TRACE_ERROR2 ("T2T NFC Send data failed. state=%s substate=%s ", rw_t2t_get_state_name (p_t2t->state), rw_t2t_get_substate_name (p_t2t->substate)); #else RW_TRACE_ERROR2 ("T2T NFC Send data failed. state=0x%02X substate=0x%02X ", p_t2t->state, p_t2t->substate); #endif } } else { status = NFC_STATUS_NO_BUFFERS; } } return status; }
/******************************************************************************* ** ** Function rw_t1t_send_dyn_cmd ** ** Description This function composes a Type 1 Tag command for dynamic memory ** and send through NCI to NFCC. ** ** Returns NFC_STATUS_OK if the command is successfuly sent to NCI ** otherwise, error status ** *******************************************************************************/ tNFC_STATUS rw_t1t_send_dyn_cmd (UINT8 opcode, UINT8 add, UINT8 *p_dat) { tNFC_STATUS status = NFC_STATUS_FAILED; tRW_T1T_CB *p_t1t = &rw_cb.tcb.t1t; const tT1T_CMD_RSP_INFO *p_cmd_rsp_info = t1t_cmd_to_rsp_info (opcode); BT_HDR *p_data; UINT8 *p; if (p_cmd_rsp_info) { /* a valid opcode for RW */ p_data = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID); if (p_data) { p_t1t->p_cmd_rsp_info = (tT1T_CMD_RSP_INFO *) p_cmd_rsp_info; p_t1t->addr = add; p_data->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; p = (UINT8 *) (p_data + 1) + p_data->offset; UINT8_TO_BE_STREAM (p, opcode); UINT8_TO_BE_STREAM (p, add); if (p_dat) { ARRAY_TO_STREAM (p, p_dat, 8); } else { memset (p, 0, 8); p += 8; } ARRAY_TO_STREAM (p, p_t1t->mem, T1T_CMD_UID_LEN); p_data->len = p_cmd_rsp_info->cmd_len; /* Indicate first attempt to send command, back up cmd buffer in case needed for retransmission */ rw_cb.cur_retry = 0; memcpy (p_t1t->p_cur_cmd_buf, p_data, sizeof (BT_HDR) + p_data->offset + p_data->len); #if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE)) /* Update stats */ rw_main_update_tx_stats (p_data->len, FALSE); #endif /* RW_STATS_INCLUDED */ RW_TRACE_EVENT2 ("RW SENT [%s]:0x%x CMD", t1t_info_to_str (p_cmd_rsp_info), p_cmd_rsp_info->opcode); if ((status = NFC_SendData (NFC_RF_CONN_ID, p_data)) == NFC_STATUS_OK) { nfc_start_quick_timer (&p_t1t->timer, NFC_TTYPE_RW_T1T_RESPONSE, (RW_T1T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000); } } else { status = NFC_STATUS_NO_BUFFERS; } } return status; }
/******************************************************************************* ** ** Function rw_t4t_send_to_lower ** ** Description Send C-APDU to lower layer ** ** Returns TRUE if success ** *******************************************************************************/ static BOOLEAN rw_t4t_send_to_lower (BT_HDR *p_c_apdu) { #if (BT_TRACE_PROTOCOL == TRUE) DispRWT4Tags (p_c_apdu, FALSE); #endif if (NFC_SendData (NFC_RF_CONN_ID, p_c_apdu) != NFC_STATUS_OK) { RW_TRACE_ERROR0 ("rw_t4t_send_to_lower (): NFC_SendData () failed"); return FALSE; } nfc_start_quick_timer (&rw_cb.tcb.t4t.timer, NFC_TTYPE_RW_T4T_RESPONSE, (RW_T4T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000); return TRUE; }
/******************************************************************************* ** ** Function rw_t2t_resume_op ** ** Description This function will continue operation after moving to new ** sector ** ** Returns tNFC_STATUS ** *******************************************************************************/ static void rw_t2t_resume_op (void) { tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t; tRW_READ_DATA evt_data; BT_HDR *p_cmd_buf; tRW_EVENT event; const tT2T_CMD_RSP_INFO *p_cmd_rsp_info = (tT2T_CMD_RSP_INFO *) rw_cb.tcb.t2t.p_cmd_rsp_info; UINT8 *p; /* Move back to the substate where we were before changing sector */ p_t2t->substate = p_t2t->prev_substate; p = (UINT8 *) (p_t2t->p_sec_cmd_buf + 1) + p_t2t->p_sec_cmd_buf->offset; p_cmd_rsp_info = t2t_cmd_to_rsp_info ((UINT8) *p); p_t2t->p_cmd_rsp_info = (tT2T_CMD_RSP_INFO *) p_cmd_rsp_info; /* 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_sec_cmd_buf, sizeof (BT_HDR) + p_t2t->p_sec_cmd_buf->offset + p_t2t->p_sec_cmd_buf->len); memcpy (p_t2t->p_cur_cmd_buf, p_t2t->p_sec_cmd_buf, sizeof (BT_HDR) + p_t2t->p_sec_cmd_buf->offset + p_t2t->p_sec_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); } else { /* failure - could not send buffer */ evt_data.p_data = NULL; evt_data.status = NFC_STATUS_FAILED; event = rw_t2t_info_to_event (p_cmd_rsp_info); rw_t2t_handle_op_complete (); (*rw_cb.p_cback) (event, (tRW_DATA *) &evt_data); } } }
/******************************************************************************* ** ** Function rw_t2t_sector_change ** ** Description This function issues Type 2 Tag SECTOR-SELECT command ** packet 1. ** ** Returns tNFC_STATUS ** *******************************************************************************/ tNFC_STATUS rw_t2t_sector_change (UINT8 sector) { tNFC_STATUS status; BT_HDR *p_data; UINT8 *p; tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t; if ((p_data = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) == NULL) { RW_TRACE_ERROR0 ("rw_t2t_sector_change - No buffer"); return (NFC_STATUS_NO_BUFFERS); } p_data->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; p = (UINT8 *) (p_data + 1) + p_data->offset; UINT8_TO_BE_STREAM (p, sector); UINT8_TO_BE_STREAM (p, 0x00); UINT8_TO_BE_STREAM (p, 0x00); UINT8_TO_BE_STREAM (p, 0x00); p_data->len = 4; if ((status = NFC_SendData (NFC_RF_CONN_ID , p_data)) == NFC_STATUS_OK) { /* Passive rsp command and suppose not to get response to this command */ p_t2t->p_cmd_rsp_info = NULL; p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR; RW_TRACE_EVENT0 ("rw_t2t_sector_change Sent Second Command"); nfc_start_quick_timer (&p_t2t->t2_timer, NFC_TTYPE_RW_T2T_RESPONSE, (RW_T2T_SEC_SEL_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000); } else { RW_TRACE_ERROR1 ("rw_t2t_sector_change Send failed at rw_t2t_send_cmd, error: %u", status); } return status; }
/******************************************************************************* ** ** Function ce_t4t_update_binary ** ** Description Update file and send R-APDU to peer ** ** Returns TRUE if success ** *******************************************************************************/ static BOOLEAN ce_t4t_update_binary (UINT16 offset, UINT8 length, UINT8 *p_data) { tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t; UINT8 *p; UINT8 file_length[2]; UINT16 starting_offset; tCE_DATA ce_data; CE_TRACE_DEBUG3 ("ce_t4t_update_binary (): Offset:0x%04X, Length:0x%04X, selected status = 0x%02X", offset, length, p_t4t->status); starting_offset = offset; /* update file size (NLEN) */ if ((offset < T4T_FILE_LENGTH_SIZE) && (length > 0)) { p = file_length; UINT16_TO_BE_STREAM (p, p_t4t->nlen); while ((offset < T4T_FILE_LENGTH_SIZE) && (length > 0)) { *(file_length + offset++) = *(p_data++); length--; } p = file_length; BE_STREAM_TO_UINT16 (p_t4t->nlen, p); } if (length > 0) memcpy (p_t4t->p_scratch_buf + offset - T4T_FILE_LENGTH_SIZE, p_data, length); /* if this is the last step: writing non-zero length in NLEN */ if ((starting_offset == 0) && (p_t4t->nlen > 0)) { nfc_stop_quick_timer (&p_t4t->timer); if (ce_cb.p_cback) { ce_data.update_info.status = NFC_STATUS_OK; ce_data.update_info.length = p_t4t->nlen; ce_data.update_info.p_data = p_t4t->p_scratch_buf; (*ce_cb.p_cback) (CE_T4T_NDEF_UPDATE_CPLT_EVT, &ce_data); CE_TRACE_DEBUG0 ("ce_t4t_update_binary (): Sent CE_T4T_NDEF_UPDATE_CPLT_EVT"); } p_t4t->status &= ~ (CE_T4T_STATUS_NDEF_FILE_UPDATING); } else if (!(p_t4t->status & CE_T4T_STATUS_NDEF_FILE_UPDATING)) { /* starting of updating */ p_t4t->status |= CE_T4T_STATUS_NDEF_FILE_UPDATING; nfc_start_quick_timer (&p_t4t->timer, NFC_TTYPE_CE_T4T_UPDATE, (CE_T4T_TOUT_UPDATE * QUICK_TIMER_TICKS_PER_SEC) / 1000); if (ce_cb.p_cback) (*ce_cb.p_cback) (CE_T4T_NDEF_UPDATE_START_EVT, NULL); } if (!ce_t4t_send_status (T4T_RSP_CMD_CMPLTED)) { return FALSE; } else { return TRUE; } }
/******************************************************************************* ** ** 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); } }
/******************************************************************************* ** ** Function rw_t1t_process_error ** ** Description process timeout event ** ** Returns none ** *******************************************************************************/ static void rw_t1t_process_error (void) { tRW_READ_DATA evt_data; tRW_EVENT rw_event; BT_HDR *p_cmd_buf; tRW_T1T_CB *p_t1t = &rw_cb.tcb.t1t; tT1T_CMD_RSP_INFO *p_cmd_rsp_info = (tT1T_CMD_RSP_INFO *) rw_cb.tcb.t1t.p_cmd_rsp_info; tRW_DETECT_NDEF_DATA ndef_data; RW_TRACE_DEBUG1 ("rw_t1t_process_error () State: %u", p_t1t->state); /* Retry sending command if retry-count < max */ if (rw_cb.cur_retry < RW_MAX_RETRIES) { /* retry sending the command */ rw_cb.cur_retry++; RW_TRACE_DEBUG2 ("T1T 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_t1t->p_cur_cmd_buf, sizeof (BT_HDR) + p_t1t->p_cur_cmd_buf->offset + p_t1t->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 /* RW_STATS_INCLUDED */ if (NFC_SendData (NFC_RF_CONN_ID, p_cmd_buf) == NFC_STATUS_OK) { /* Start timer for waiting for response */ nfc_start_quick_timer (&p_t1t->timer, NFC_TTYPE_RW_T1T_RESPONSE, (RW_T1T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC)/1000); return; } } } else { /* we might get response later to all or some of the retrasnmission * of the current command, update previous command response information */ RW_TRACE_DEBUG1 ("T1T maximum retransmission attempts reached (%i)", RW_MAX_RETRIES); p_t1t->prev_cmd_rsp_info.addr = ((p_cmd_rsp_info->opcode != T1T_CMD_RALL) && (p_cmd_rsp_info->opcode != T1T_CMD_RID))? p_t1t->addr:0; p_t1t->prev_cmd_rsp_info.rsp_len = p_cmd_rsp_info->rsp_len; p_t1t->prev_cmd_rsp_info.op_code = p_cmd_rsp_info->opcode; p_t1t->prev_cmd_rsp_info.pend_retx_rsp = RW_MAX_RETRIES; } #if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE)) /* update failure count */ rw_main_update_fail_stats (); #endif /* RW_STATS_INCLUDED */ rw_event = rw_t1t_info_to_event (p_cmd_rsp_info); if (p_t1t->state != RW_T1T_STATE_NOT_ACTIVATED) rw_t1t_handle_op_complete (); 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_T1T; ndef_data.flags = RW_NDEF_FL_UNKNOWN; ndef_data.max_size = 0; ndef_data.cur_size = 0; (*rw_cb.p_cback) (rw_event, (tRW_DATA *) &ndef_data); } else { evt_data.p_data = NULL; (*rw_cb.p_cback) (rw_event, (tRW_DATA *) &evt_data); } }