/******************************************************************************* ** ** Function nfa_hciu_find_active_pipe_on_gate ** ** Description Find the first active pipe associated with the given gate ** ** Returns pointer to pipe, or NULL if none found ** *******************************************************************************/ tNFA_HCI_DYN_PIPE *nfa_hciu_find_active_pipe_on_gate (UINT8 gate_id) { tNFA_HCI_DYN_GATE *pg; tNFA_HCI_DYN_PIPE *pp; int xx; NFA_TRACE_DEBUG1 ("nfa_hciu_find_active_pipe_on_gate () Gate:0x%x", gate_id); /* Loop through all pipes looking for the owner */ for (xx = 0, pp = nfa_hci_cb.cfg.dyn_pipes; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++) { if ( (pp->pipe_id != 0) &&(pp->pipe_id >= NFA_HCI_FIRST_DYNAMIC_PIPE) &&(pp->pipe_id <= NFA_HCI_LAST_DYNAMIC_PIPE) &&(nfa_hciu_is_active_host (pp->dest_host)) ) { if ( ((pg = nfa_hciu_find_gate_by_gid (pp->local_gate)) != NULL) &&(pg->gate_id == gate_id) ) return (pp); } } /* If here, not found */ return (NULL); }
/******************************************************************************* ** ** Function nfa_hciu_add_pipe_to_gate ** ** Description Add pipe to generic gate ** ** Returns NFA_STATUS_OK, if successfully add the pipe on to the gate ** NFA_HCI_ADM_E_NO_PIPES_AVAILABLE, otherwise ** *******************************************************************************/ tNFA_HCI_RESPONSE nfa_hciu_add_pipe_to_gate (UINT8 pipe_id, UINT8 local_gate, UINT8 dest_host, UINT8 dest_gate) { tNFA_HCI_DYN_GATE *p_gate; tNFA_HCI_DYN_PIPE *p_pipe; UINT8 pipe_index; p_gate = nfa_hciu_find_gate_by_gid (local_gate); if (p_gate != NULL) { /* Allocate a pipe control block */ if ((p_pipe = nfa_hciu_alloc_pipe (pipe_id)) != NULL) { p_pipe->pipe_id = pipe_id; p_pipe->pipe_state = NFA_HCI_PIPE_CLOSED; p_pipe->dest_host = dest_host; p_pipe->dest_gate = dest_gate; p_pipe->local_gate = local_gate; /* Save the pipe in the gate that it belongs to */ pipe_index = (UINT8) (p_pipe - nfa_hci_cb.cfg.dyn_pipes); p_gate->pipe_inx_mask |= (UINT32) (1 << pipe_index); NFA_TRACE_DEBUG4 ("nfa_hciu_add_pipe_to_gate Gate ID: 0x%02x Pipe ID: 0x%02x pipe_index: %u App Handle: 0x%08x", local_gate, pipe_id, pipe_index, p_gate->gate_owner); return (NFA_HCI_ANY_OK); } } NFA_TRACE_DEBUG1 ("nfa_hciu_add_pipe_to_gate: 0x%02x NOT FOUND", local_gate); return (NFA_HCI_ADM_E_NO_PIPES_AVAILABLE); }
/******************************************************************************* ** ** Function nfa_hciu_alloc_pipe ** ** Description Allocate a pipe control block ** ** Returns pointer to the pipe control block, or NULL if ** cannot allocate ** *******************************************************************************/ tNFA_HCI_DYN_PIPE *nfa_hciu_alloc_pipe (UINT8 pipe_id) { UINT8 xx; tNFA_HCI_DYN_PIPE *pp; /* If we already have a pipe of the same ID, release it first it */ if ((pp = nfa_hciu_find_pipe_by_pid (pipe_id)) != NULL) { if (pipe_id > NFA_HCI_LAST_DYNAMIC_PIPE) return pp; nfa_hciu_release_pipe (pipe_id); } /* Look for a free pipe control block */ for (xx = 0, pp = nfa_hci_cb.cfg.dyn_pipes ; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++) { if (pp->pipe_id == 0) { NFA_TRACE_DEBUG2 ("nfa_hciu_alloc_pipe:%d, index:%d", pipe_id, xx); pp->pipe_id = pipe_id; nfa_hci_cb.nv_write_needed = TRUE; return (pp); } } NFA_TRACE_DEBUG1 ("nfa_hciu_alloc_pipe:%d, NO free entries !!", pipe_id); return (NULL); }
/******************************************************************************* ** ** Function nfa_sys_ptim_timer_update ** ** Description Update the protocol timer list and handle expired timers. ** This function is called from the task running the protocol ** timers when the periodic GKI timer expires. ** ** Returns void ** *******************************************************************************/ void nfa_sys_ptim_timer_update (tPTIM_CB *p_cb) { TIMER_LIST_ENT *p_tle; BT_HDR *p_msg; UINT32 new_ticks_count; INT32 period_in_ticks; /* To handle the case when the function is called less frequently than the period we must convert determine the number of ticks since the last update, then convert back to milliseconds before updating timer list */ new_ticks_count = GKI_get_tick_count (); /* Check for wrapped condition */ if (new_ticks_count >= p_cb->last_gki_ticks) { period_in_ticks = (INT32) (new_ticks_count - p_cb->last_gki_ticks); } else { period_in_ticks = (INT32) (((UINT32) 0xffffffff - p_cb->last_gki_ticks) + new_ticks_count + 1); } /* update timer list */ GKI_update_timer_list (&p_cb->timer_queue, GKI_TICKS_TO_MS (period_in_ticks)); p_cb->last_gki_ticks = new_ticks_count; /* while there are expired timers */ while ((p_cb->timer_queue.p_first) && (p_cb->timer_queue.p_first->ticks <= 0)) { /* removed expired timer from list */ p_tle = p_cb->timer_queue.p_first; NFA_TRACE_DEBUG1 ("nfa_sys_ptim_timer_update expired: %08x", p_tle); GKI_remove_from_timer_list (&p_cb->timer_queue, p_tle); /* call timer callback */ if (p_tle->p_cback) { (*p_tle->p_cback) (p_tle); } else if (p_tle->event) { if ((p_msg = (BT_HDR *) GKI_getbuf (sizeof (BT_HDR))) != NULL) { p_msg->event = p_tle->event; p_msg->layer_specific = 0; nfa_sys_sendmsg (p_msg); } } } /* if timer list is empty stop periodic GKI timer */ if (p_cb->timer_queue.p_first == NULL) { NFA_TRACE_DEBUG0 ("ptim timer stop"); GKI_stop_timer (p_cb->timer_id); } }
/******************************************************************************* ** ** Function nfa_hciu_send_delete_pipe_cmd ** ** Description Delete the dynamic pipe ** ** Returns None ** *******************************************************************************/ tNFA_STATUS nfa_hciu_send_delete_pipe_cmd (UINT8 pipe) { tNFA_STATUS status; NFA_TRACE_DEBUG1 ("nfa_hciu_send_delete_pipe_cmd: %d", pipe); if (pipe > NFA_HCI_LAST_DYNAMIC_PIPE) { NFA_TRACE_DEBUG1 ("ignore pipe: %d", pipe); return (NFA_HCI_ANY_E_NOK); } nfa_hci_cb.pipe_in_use = pipe; status = nfa_hciu_send_msg (NFA_HCI_ADMIN_PIPE, NFA_HCI_COMMAND_TYPE, NFA_HCI_ADM_DELETE_PIPE, 1, &pipe); return status; }
/******************************************************************************* ** ** Function nfa_dm_is_active ** ** Description check if all modules of NFA is done with enable process and ** NFA is not restoring NFCC. ** ** Returns TRUE, if NFA_DM_ENABLE_EVT is reported and it is not restoring NFCC ** *******************************************************************************/ BOOLEAN nfa_dm_is_active (void) { NFA_TRACE_DEBUG1 ("nfa_dm_is_active () flags:0x%x", nfa_dm_cb.flags); if ( (nfa_dm_cb.flags & NFA_DM_FLAGS_DM_IS_ACTIVE) &&((nfa_dm_cb.flags & (NFA_DM_FLAGS_ENABLE_EVT_PEND | NFA_DM_FLAGS_NFCC_IS_RESTORING | NFA_DM_FLAGS_POWER_OFF_SLEEP)) == 0) ) { return TRUE; } else return FALSE; }
/******************************************************************************* ** ** Function nfa_ee_proc_nfcc_power_mode ** ** Description Restore NFA EE sub-module ** ** Returns None ** *******************************************************************************/ void nfa_ee_proc_nfcc_power_mode (UINT8 nfcc_power_mode) { UINT32 xx; tNFA_EE_ECB *p_cb; BOOLEAN proc_complete = TRUE; NFA_TRACE_DEBUG1 ("nfa_ee_proc_nfcc_power_mode (): nfcc_power_mode=%d", nfcc_power_mode); /* if NFCC power state is change to full power */ if (nfcc_power_mode == NFA_DM_PWR_MODE_FULL) { if (nfa_ee_max_ee_cfg) { p_cb = nfa_ee_cb.ecb; for (xx = 0; xx < NFA_EE_MAX_EE_SUPPORTED; xx++, p_cb++) { p_cb->ee_old_status = 0; if (xx >= nfa_ee_cb.cur_ee) p_cb->nfcee_id = NFA_EE_INVALID; if ((p_cb->nfcee_id != NFA_EE_INVALID) && (p_cb->ee_interface[0] != NFC_NFCEE_INTERFACE_HCI_ACCESS) && (p_cb->ee_status != NFA_EE_STATUS_REMOVED)) { proc_complete = FALSE; /* NFA_EE_STATUS_RESTORING bit makes sure the ee_status restore to ee_old_status * NFA_EE_STATUS_RESTORING bit is cleared in ee_status at NFCEE_DISCOVER NTF. * NFA_EE_STATUS_RESTORING bit is cleared in ee_old_status at restoring the activate/inactive status after NFCEE_DISCOVER NTF */ p_cb->ee_status |= NFA_EE_STATUS_RESTORING; p_cb->ee_old_status = p_cb->ee_status; /* NFA_EE_FLAGS_RESTORE bit makes sure the routing/nci logical connection is restore to prior to entering low power mode */ p_cb->ecb_flags |= NFA_EE_ECB_FLAGS_RESTORE; } } nfa_ee_cb.em_state = NFA_EE_EM_STATE_RESTORING; nfa_ee_cb.num_ee_expecting = 0; if (nfa_sys_is_register (NFA_ID_HCI)) { nfa_ee_cb.ee_flags |= NFA_EE_FLAG_WAIT_HCI; nfa_ee_cb.ee_flags |= NFA_EE_FLAG_NOTIFY_HCI; } NFC_NfceeDiscover (TRUE); nfa_sys_start_timer (&nfa_ee_cb.discv_timer, NFA_EE_DISCV_TIMEOUT_EVT, NFA_EE_DISCV_TIMEOUT_VAL); } } else { nfa_sys_stop_timer (&nfa_ee_cb.timer); nfa_sys_stop_timer (&nfa_ee_cb.discv_timer); nfa_ee_cb.num_ee_expecting = 0; } if (proc_complete) nfa_sys_cback_notify_nfcc_power_mode_proc_complete (NFA_ID_EE); }
/******************************************************************************* ** ** Function nfa_sys_ptim_stop_timer ** ** Description Stop a protocol timer. ** ** Returns void ** *******************************************************************************/ void nfa_sys_ptim_stop_timer (tPTIM_CB *p_cb, TIMER_LIST_ENT *p_tle) { NFA_TRACE_DEBUG1 ("nfa_sys_ptim_stop_timer %08x", p_tle); GKI_remove_from_timer_list (&p_cb->timer_queue, p_tle); /* if timer list is empty stop periodic GKI timer */ if (p_cb->timer_queue.p_first == NULL) { NFA_TRACE_DEBUG0 ("ptim timer stop"); GKI_stop_timer (p_cb->timer_id); } }
/******************************************************************************* ** ** Function NFA_EeGetInfo ** ** Description This function retrieves the NFCEE information from NFA. ** The actual number of NFCEE is returned in p_num_nfcee ** and NFCEE information is returned in p_info ** ** Returns NFA_STATUS_OK if information is retrieved successfully ** NFA_STATUS_FAILED If wrong state (retry later) ** NFA_STATUS_INVALID_PARAM If bad parameter ** *******************************************************************************/ tNFA_STATUS NFA_EeGetInfo(UINT8 *p_num_nfcee, tNFA_EE_INFO *p_info) { int xx, ret = nfa_ee_cb.cur_ee; tNFA_EE_ECB *p_cb = nfa_ee_cb.ecb; UINT8 max_ret; UINT8 num_ret = 0; NFA_TRACE_DEBUG2 ("NFA_EeGetInfo em_state:%d cur_ee:%d", nfa_ee_cb.em_state, nfa_ee_cb.cur_ee); /* validate parameters */ if (p_info == NULL || p_num_nfcee == NULL) { NFA_TRACE_ERROR0 ("NFA_EeGetInfo bad parameter"); return (NFA_STATUS_INVALID_PARAM); } max_ret = *p_num_nfcee; *p_num_nfcee = 0; if (nfa_ee_cb.em_state == NFA_EE_EM_STATE_INIT) { NFA_TRACE_ERROR1 ("NFA_EeGetInfo bad em state: %d", nfa_ee_cb.em_state); return (NFA_STATUS_FAILED); } /* compose output */ for (xx = 0; (xx < ret) && (num_ret < max_ret); xx++, p_cb++) { NFA_TRACE_DEBUG4 ("xx:%d max_ret:%d, num_ret:%d ee_status:0x%x", xx, max_ret, num_ret, p_cb->ee_status); if ((p_cb->ee_status & NFA_EE_STATUS_INT_MASK) || (p_cb->ee_status == NFA_EE_STATUS_REMOVED)) { continue; } p_info->ee_handle = NFA_HANDLE_GROUP_EE | (tNFA_HANDLE)p_cb->nfcee_id; p_info->ee_status = p_cb->ee_status; p_info->num_interface = p_cb->num_interface; p_info->num_tlvs = p_cb->num_tlvs; memcpy(p_info->ee_interface, p_cb->ee_interface, p_cb->num_interface); memcpy(p_info->ee_tlv, p_cb->ee_tlv, p_cb->num_tlvs * sizeof(tNFA_EE_TLV)); p_info++; num_ret++; } NFA_TRACE_DEBUG1 ("num_ret:%d", num_ret); *p_num_nfcee = num_ret; return (NFA_STATUS_OK); }
/******************************************************************************* ** ** Function nfa_hciu_get_allocated_gate_list ** ** Description fills in a list of allocated gates ** ** Returns the number of gates ** *******************************************************************************/ UINT8 nfa_hciu_get_allocated_gate_list (UINT8 *p_gate_list) { tNFA_HCI_DYN_GATE *p_cb; int xx; UINT8 count = 0; for (xx = 0, p_cb = nfa_hci_cb.cfg.dyn_gates; xx < NFA_HCI_MAX_GATE_CB; xx++, p_cb++) { if (p_cb->gate_id != 0) { *p_gate_list++ = p_cb->gate_id; count++; } } NFA_TRACE_DEBUG1 ("nfa_hciu_get_allocated_gate_list () returns: %u", count); return (count); }
/******************************************************************************* ** ** Function nfa_sys_ptim_start_timer ** ** Description Start a protocol timer for the specified amount ** of time in seconds. ** ** Returns void ** *******************************************************************************/ void nfa_sys_ptim_start_timer (tPTIM_CB *p_cb, TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout) { NFA_TRACE_DEBUG1 ("nfa_sys_ptim_start_timer %08x", p_tle); /* if timer list is currently empty, start periodic GKI timer */ if (p_cb->timer_queue.p_first == NULL) { NFA_TRACE_DEBUG0 ("ptim timer start"); p_cb->last_gki_ticks = GKI_get_tick_count (); GKI_start_timer (p_cb->timer_id, GKI_MS_TO_TICKS (p_cb->period), TRUE); } GKI_remove_from_timer_list (&p_cb->timer_queue, p_tle); p_tle->event = type; p_tle->ticks = timeout; GKI_add_to_timer_list (&p_cb->timer_queue, p_tle); }
/******************************************************************************* ** ** Function nfa_hciu_release_pipe ** ** Description remove the specified pipe ** ** Returns NFA_HCI_ANY_OK, if removed ** NFA_HCI_ANY_E_NOK, if otherwise ** *******************************************************************************/ tNFA_HCI_RESPONSE nfa_hciu_release_pipe (UINT8 pipe_id) { tNFA_HCI_DYN_GATE *p_gate; tNFA_HCI_DYN_PIPE *p_pipe; UINT8 pipe_index; NFA_TRACE_EVENT1 ("nfa_hciu_release_pipe: %u", pipe_id); if ((p_pipe = nfa_hciu_find_pipe_by_pid (pipe_id)) == NULL) return (NFA_HCI_ANY_E_NOK); if (pipe_id > NFA_HCI_LAST_DYNAMIC_PIPE) { NFA_TRACE_DEBUG1 ("ignore pipe: %d", pipe_id); return (NFA_HCI_ANY_E_NOK); } pipe_index = (UINT8) (p_pipe - nfa_hci_cb.cfg.dyn_pipes); if (p_pipe->local_gate == NFA_HCI_IDENTITY_MANAGEMENT_GATE) { /* Remove pipe from ID management gate */ nfa_hci_cb.cfg.id_mgmt_gate.pipe_inx_mask &= ~ (UINT32) (1 << pipe_index); } else { if ((p_gate = nfa_hciu_find_gate_by_gid (p_pipe->local_gate)) == NULL) { /* Mark the pipe control block as free */ p_pipe->pipe_id = 0; return (NFA_HCI_ANY_E_NOK); } /* Remove pipe from gate */ p_gate->pipe_inx_mask &= ~ (UINT32) (1 << pipe_index); } /* Reset pipe control block */ memset (p_pipe,0,sizeof (tNFA_HCI_DYN_PIPE)); nfa_hci_cb.nv_write_needed = TRUE; return NFA_HCI_ANY_OK; }
/******************************************************************************* ** ** Function nfa_hciu_find_pipe_by_owner ** ** Description Find the first pipe associated with the given app ** ** Returns pointer to pipe, or NULL if none found ** *******************************************************************************/ tNFA_HCI_DYN_PIPE *nfa_hciu_find_pipe_by_owner (tNFA_HANDLE app_handle) { tNFA_HCI_DYN_GATE *pg; tNFA_HCI_DYN_PIPE *pp; int xx; NFA_TRACE_DEBUG1 ("nfa_hciu_find_pipe_by_owner () app_handle:0x%x", app_handle); /* Loop through all pipes looking for the owner */ for (xx = 0, pp = nfa_hci_cb.cfg.dyn_pipes; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++) { if (pp->pipe_id != 0) { if ( ((pg = nfa_hciu_find_gate_by_gid (pp->local_gate)) != NULL) &&(pg->gate_owner == app_handle) ) return (pp); } } /* If here, not found */ return (NULL); }