/******************************************************************************* ** ** 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 ce_t4t_send_to_lower ** ** Description Send packet to lower layer ** ** Returns TRUE if success ** *******************************************************************************/ static BOOLEAN ce_t4t_send_to_lower (BT_HDR *p_r_apdu) { #if (BT_TRACE_PROTOCOL == TRUE) DispCET4Tags (p_r_apdu, FALSE); #endif if (NFC_SendData (NFC_RF_CONN_ID, p_r_apdu) != NFC_STATUS_OK) { CE_TRACE_ERROR0 ("ce_t4t_send_to_lower (): NFC_SendData () failed"); return FALSE; } return TRUE; }
/******************************************************************************* ** ** 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_SendRawFrame ** ** Description This function sends a raw frame to the peer device. ** ** Returns tNFC_STATUS ** *******************************************************************************/ tNFC_STATUS CE_SendRawFrame (UINT8 *p_raw_data, UINT16 data_len) { tNFC_STATUS status = NFC_STATUS_FAILED; BT_HDR *p_data; UINT8 *p; if (ce_cb.p_cback) { /* a valid opcode for RW */ p_data = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID); if (p_data) { p_data->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; p = (UINT8 *) (p_data + 1) + p_data->offset; memcpy (p, p_raw_data, data_len); p_data->len = data_len; CE_TRACE_EVENT1 ("CE SENT raw frame (0x%x)", data_len); status = NFC_SendData (NFC_RF_CONN_ID, p_data); } } return status; }
/******************************************************************************* ** ** Function nfa_hciu_send_msg ** ** Description This function will fragment the given packet, if necessary ** and send it on the given pipe. ** ** Returns status ** *******************************************************************************/ tNFA_STATUS nfa_hciu_send_msg (UINT8 pipe_id, UINT8 type, UINT8 instruction, UINT16 msg_len, UINT8 *p_msg) { BT_HDR *p_buf; UINT8 *p_data; BOOLEAN first_pkt = TRUE; UINT16 data_len; tNFA_STATUS status = NFA_STATUS_OK; UINT16 max_seg_hcp_pkt_size = nfa_hci_cb.buff_size; #if (BT_TRACE_VERBOSE == TRUE) char buff[100]; NFA_TRACE_DEBUG3 ("nfa_hciu_send_msg pipe_id:%d %s len:%d", pipe_id, nfa_hciu_get_type_inst_names (pipe_id, type, instruction, buff), msg_len); #else NFA_TRACE_DEBUG4 ("nfa_hciu_send_msg pipe_id:%d Type: %u Inst: %u len: %d", pipe_id, type, instruction, msg_len); #endif if (instruction == NFA_HCI_ANY_GET_PARAMETER) nfa_hci_cb.param_in_use = *p_msg; while ((first_pkt == TRUE) || (msg_len != 0)) { if ((p_buf = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) != NULL) { p_buf->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; /* First packet has a 2-byte header, subsequent fragments have a 1-byte header */ data_len = first_pkt ? (max_seg_hcp_pkt_size - 2) : (max_seg_hcp_pkt_size - 1); p_data = (UINT8 *) (p_buf + 1) + p_buf->offset; /* Last or only segment has "no fragmentation" bit set */ if (msg_len > data_len) { *p_data++ = (NFA_HCI_MESSAGE_FRAGMENTATION << 7) | (pipe_id & 0x7F); } else { data_len = msg_len; *p_data++ = (NFA_HCI_NO_MESSAGE_FRAGMENTATION << 7) | (pipe_id & 0x7F); } p_buf->len = 1; /* Message header only goes in the first segment */ if (first_pkt) { first_pkt = FALSE; *p_data++ = (type << 6) | instruction; p_buf->len++; } if (data_len != 0) { memcpy (p_data, p_msg, data_len); p_buf->len += data_len; msg_len -= data_len; if (msg_len > 0) p_msg += data_len; } #if (BT_TRACE_PROTOCOL == TRUE) DispHcp (((UINT8 *) (p_buf + 1) + p_buf->offset), p_buf->len, FALSE, (BOOLEAN) ((p_buf->len - data_len) == 2)); #endif if (HCI_LOOPBACK_DEBUG) handle_debug_loopback (p_buf, pipe_id, type, instruction); else status = NFC_SendData (nfa_hci_cb.conn_id, p_buf); } else { NFA_TRACE_ERROR0 ("nfa_hciu_send_data_packet no buffers"); status = NFA_STATUS_NO_BUFFERS; break; } } /* Start timer if response to wait for a particular time for the response */ if (type == NFA_HCI_COMMAND_TYPE) { nfa_hci_cb.cmd_sent = instruction; if (nfa_hci_cb.hci_state == NFA_HCI_STATE_IDLE) nfa_hci_cb.hci_state = NFA_HCI_STATE_WAIT_RSP; nfa_sys_start_timer (&nfa_hci_cb.timer, NFA_HCI_RSP_TIMEOUT_EVT, p_nfa_hci_cfg->hcp_response_timeout); } return status; }
/******************************************************************************* ** ** 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); } }