| /****************************************************************************** |
| * |
| * Copyright (C) 2010-2013 Broadcom Corporation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at: |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| ******************************************************************************/ |
| |
| |
| /****************************************************************************** |
| * |
| * This file contains the action functions for the NFA HCI. |
| * |
| ******************************************************************************/ |
| #include <string.h> |
| #include "trace_api.h" |
| #include "nfc_api.h" |
| #include "nfa_sys.h" |
| #include "nfa_sys_int.h" |
| #include "nfa_hci_api.h" |
| #include "nfa_hci_int.h" |
| #include "nfa_dm_int.h" |
| #include "nfa_nv_co.h" |
| #include "nfa_mem_co.h" |
| #include "nfa_hci_defs.h" |
| |
| |
| /* Static local functions */ |
| static void nfa_hci_api_register (tNFA_HCI_EVENT_DATA *p_evt_data); |
| static void nfa_hci_api_get_gate_pipe_list (tNFA_HCI_EVENT_DATA *p_evt_data); |
| static void nfa_hci_api_alloc_gate (tNFA_HCI_EVENT_DATA *p_evt_data); |
| static void nfa_hci_api_get_host_list (tNFA_HCI_EVENT_DATA *p_evt_data); |
| static BOOLEAN nfa_hci_api_get_reg_value (tNFA_HCI_EVENT_DATA *p_evt_data); |
| static BOOLEAN nfa_hci_api_set_reg_value (tNFA_HCI_EVENT_DATA *p_evt_data); |
| static BOOLEAN nfa_hci_api_create_pipe (tNFA_HCI_EVENT_DATA *p_evt_data); |
| static void nfa_hci_api_open_pipe (tNFA_HCI_EVENT_DATA *p_evt_data); |
| static void nfa_hci_api_close_pipe (tNFA_HCI_EVENT_DATA *p_evt_data); |
| static void nfa_hci_api_delete_pipe (tNFA_HCI_EVENT_DATA *p_evt_data); |
| static BOOLEAN nfa_hci_api_send_event (tNFA_HCI_EVENT_DATA *p_evt_data); |
| static BOOLEAN nfa_hci_api_send_cmd (tNFA_HCI_EVENT_DATA *p_evt_data); |
| static void nfa_hci_api_send_rsp (tNFA_HCI_EVENT_DATA *p_evt_data); |
| static void nfa_hci_api_add_static_pipe (tNFA_HCI_EVENT_DATA *p_evt_data); |
| |
| static void nfa_hci_handle_identity_mgmt_gate_pkt (UINT8 *p_data, tNFA_HCI_DYN_PIPE *p_pipe); |
| static void nfa_hci_handle_loopback_gate_pkt (UINT8 *p_data, UINT16 data_len, tNFA_HCI_DYN_PIPE *p_pipe); |
| static void nfa_hci_handle_connectivity_gate_pkt (UINT8 *p_data, UINT16 data_len, tNFA_HCI_DYN_PIPE *p_pipe); |
| static void nfa_hci_handle_generic_gate_cmd (UINT8 *p_data, UINT8 data_len, tNFA_HCI_DYN_GATE *p_gate, tNFA_HCI_DYN_PIPE *p_pipe); |
| static void nfa_hci_handle_generic_gate_rsp (UINT8 *p_data, UINT8 data_len, tNFA_HCI_DYN_GATE *p_gate, tNFA_HCI_DYN_PIPE *p_pipe); |
| static void nfa_hci_handle_generic_gate_evt (UINT8 *p_data, UINT16 data_len, tNFA_HCI_DYN_GATE *p_gate, tNFA_HCI_DYN_PIPE *p_pipe); |
| |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_check_pending_api_requests |
| ** |
| ** Description This function handles pending API requests |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| void nfa_hci_check_pending_api_requests (void) |
| { |
| BT_HDR *p_msg; |
| tNFA_HCI_EVENT_DATA *p_evt_data; |
| BOOLEAN b_free; |
| |
| /* If busy, or API queue is empty, then exit */ |
| if ( (nfa_hci_cb.hci_state != NFA_HCI_STATE_IDLE) |
| ||((p_msg = (BT_HDR *) GKI_dequeue (&nfa_hci_cb.hci_host_reset_api_q)) == NULL) ) |
| return; |
| |
| /* Process API request */ |
| p_evt_data = (tNFA_HCI_EVENT_DATA *)p_msg; |
| |
| /* Save the application handle */ |
| nfa_hci_cb.app_in_use = p_evt_data->comm.hci_handle; |
| |
| b_free = TRUE; |
| switch (p_msg->event) |
| { |
| case NFA_HCI_API_CREATE_PIPE_EVT: |
| if (nfa_hci_api_create_pipe (p_evt_data) == FALSE) |
| b_free = FALSE; |
| break; |
| |
| case NFA_HCI_API_GET_REGISTRY_EVT: |
| if (nfa_hci_api_get_reg_value (p_evt_data) == FALSE) |
| b_free = FALSE; |
| break; |
| |
| case NFA_HCI_API_SET_REGISTRY_EVT: |
| if (nfa_hci_api_set_reg_value (p_evt_data) == FALSE) |
| b_free = FALSE; |
| break; |
| |
| case NFA_HCI_API_SEND_CMD_EVT: |
| if (nfa_hci_api_send_cmd (p_evt_data) == FALSE) |
| b_free = FALSE; |
| break; |
| case NFA_HCI_API_SEND_EVENT_EVT: |
| if (nfa_hci_api_send_event (p_evt_data) == FALSE) |
| b_free = FALSE; |
| break; |
| } |
| |
| if (b_free) |
| GKI_freebuf (p_msg); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_check_api_requests |
| ** |
| ** Description This function handles API requests |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| void nfa_hci_check_api_requests (void) |
| { |
| BT_HDR *p_msg; |
| tNFA_HCI_EVENT_DATA *p_evt_data; |
| |
| for ( ; ; ) |
| { |
| /* If busy, or API queue is empty, then exit */ |
| if ( (nfa_hci_cb.hci_state != NFA_HCI_STATE_IDLE) |
| ||((p_msg = (BT_HDR *) GKI_dequeue (&nfa_hci_cb.hci_api_q)) == NULL) ) |
| break; |
| |
| /* Process API request */ |
| p_evt_data = (tNFA_HCI_EVENT_DATA *)p_msg; |
| |
| /* Save the application handle */ |
| nfa_hci_cb.app_in_use = p_evt_data->comm.hci_handle; |
| |
| switch (p_msg->event) |
| { |
| case NFA_HCI_API_REGISTER_APP_EVT: |
| nfa_hci_api_register (p_evt_data); |
| break; |
| |
| case NFA_HCI_API_DEREGISTER_APP_EVT: |
| nfa_hci_api_deregister (p_evt_data); |
| break; |
| |
| case NFA_HCI_API_GET_APP_GATE_PIPE_EVT: |
| nfa_hci_api_get_gate_pipe_list (p_evt_data); |
| break; |
| |
| case NFA_HCI_API_ALLOC_GATE_EVT: |
| nfa_hci_api_alloc_gate (p_evt_data); |
| break; |
| |
| case NFA_HCI_API_DEALLOC_GATE_EVT: |
| nfa_hci_api_dealloc_gate (p_evt_data); |
| break; |
| |
| case NFA_HCI_API_GET_HOST_LIST_EVT: |
| nfa_hci_api_get_host_list (p_evt_data); |
| break; |
| |
| case NFA_HCI_API_GET_REGISTRY_EVT: |
| if (nfa_hci_api_get_reg_value (p_evt_data) == FALSE) |
| continue; |
| break; |
| |
| case NFA_HCI_API_SET_REGISTRY_EVT: |
| if (nfa_hci_api_set_reg_value (p_evt_data) == FALSE) |
| continue; |
| break; |
| |
| case NFA_HCI_API_CREATE_PIPE_EVT: |
| if (nfa_hci_api_create_pipe (p_evt_data) == FALSE) |
| continue; |
| break; |
| |
| case NFA_HCI_API_OPEN_PIPE_EVT: |
| nfa_hci_api_open_pipe (p_evt_data); |
| break; |
| |
| case NFA_HCI_API_CLOSE_PIPE_EVT: |
| nfa_hci_api_close_pipe (p_evt_data); |
| break; |
| |
| case NFA_HCI_API_DELETE_PIPE_EVT: |
| nfa_hci_api_delete_pipe (p_evt_data); |
| break; |
| |
| case NFA_HCI_API_SEND_CMD_EVT: |
| if (nfa_hci_api_send_cmd (p_evt_data) == FALSE) |
| continue; |
| break; |
| |
| case NFA_HCI_API_SEND_RSP_EVT: |
| nfa_hci_api_send_rsp (p_evt_data); |
| break; |
| |
| case NFA_HCI_API_SEND_EVENT_EVT: |
| if (nfa_hci_api_send_event (p_evt_data) == FALSE) |
| continue; |
| break; |
| |
| case NFA_HCI_API_ADD_STATIC_PIPE_EVT: |
| nfa_hci_api_add_static_pipe (p_evt_data); |
| break; |
| |
| default: |
| NFA_TRACE_ERROR1 ("nfa_hci_check_api_requests () Unknown event: 0x%04x", p_msg->event); |
| break; |
| } |
| |
| GKI_freebuf (p_msg); |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_api_register |
| ** |
| ** Description action function to register the events for the given AID |
| ** |
| ** Returns None |
| ** |
| *******************************************************************************/ |
| static void nfa_hci_api_register (tNFA_HCI_EVENT_DATA *p_evt_data) |
| { |
| tNFA_HCI_EVT_DATA evt_data; |
| char *p_app_name = p_evt_data->app_info.app_name; |
| tNFA_HCI_CBACK *p_cback = p_evt_data->app_info.p_cback; |
| int xx,yy; |
| UINT8 num_gates = 0,num_pipes = 0; |
| tNFA_HCI_DYN_GATE *pg = nfa_hci_cb.cfg.dyn_gates; |
| |
| /* First, see if the application was already registered */ |
| for (xx = 0; xx < NFA_HCI_MAX_APP_CB; xx++) |
| { |
| if ( (nfa_hci_cb.cfg.reg_app_names[xx][0] != 0) |
| && !strncmp (p_app_name, &nfa_hci_cb.cfg.reg_app_names[xx][0], strlen (p_app_name)) ) |
| { |
| NFA_TRACE_EVENT2 ("nfa_hci_api_register (%s) Reusing: %u", p_app_name, xx); |
| break; |
| } |
| } |
| |
| if (xx != NFA_HCI_MAX_APP_CB) |
| { |
| nfa_hci_cb.app_in_use = (tNFA_HANDLE) (xx | NFA_HANDLE_GROUP_HCI); |
| /* The app was registered, find the number of gates and pipes associated to the app */ |
| |
| for ( yy = 0; yy < NFA_HCI_MAX_GATE_CB; yy++, pg++) |
| { |
| if (pg->gate_owner == nfa_hci_cb.app_in_use) |
| { |
| num_gates++; |
| num_pipes += nfa_hciu_count_pipes_on_gate (pg); |
| } |
| } |
| } |
| else |
| { |
| /* Not registered, look for a free entry */ |
| for (xx = 0; xx < NFA_HCI_MAX_APP_CB; xx++) |
| { |
| if (nfa_hci_cb.cfg.reg_app_names[xx][0] == 0) |
| { |
| memset (&nfa_hci_cb.cfg.reg_app_names[xx][0], 0, sizeof (nfa_hci_cb.cfg.reg_app_names[xx])); |
| BCM_STRNCPY_S (&nfa_hci_cb.cfg.reg_app_names[xx][0], sizeof (nfa_hci_cb.cfg.reg_app_names[xx]), p_app_name, NFA_MAX_HCI_APP_NAME_LEN); |
| nfa_hci_cb.nv_write_needed = TRUE; |
| NFA_TRACE_EVENT2 ("nfa_hci_api_register (%s) Allocated: %u", p_app_name, xx); |
| break; |
| } |
| } |
| |
| if (xx == NFA_HCI_MAX_APP_CB) |
| { |
| NFA_TRACE_ERROR1 ("nfa_hci_api_register (%s) NO ENTRIES", p_app_name); |
| |
| evt_data.hci_register.status = NFA_STATUS_FAILED; |
| p_evt_data->app_info.p_cback (NFA_HCI_REGISTER_EVT, &evt_data); |
| return; |
| } |
| } |
| |
| evt_data.hci_register.num_pipes = num_pipes; |
| evt_data.hci_register.num_gates = num_gates; |
| nfa_hci_cb.p_app_cback[xx] = p_cback; |
| |
| nfa_hci_cb.cfg.b_send_conn_evts[xx] = p_evt_data->app_info.b_send_conn_evts; |
| |
| evt_data.hci_register.hci_handle = (tNFA_HANDLE) (xx | NFA_HANDLE_GROUP_HCI); |
| |
| evt_data.hci_register.status = NFA_STATUS_OK; |
| |
| /* notify NFA_HCI_REGISTER_EVT to the application */ |
| p_evt_data->app_info.p_cback (NFA_HCI_REGISTER_EVT, &evt_data); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_api_deregister |
| ** |
| ** Description action function to deregister the given application |
| ** |
| ** Returns None |
| ** |
| *******************************************************************************/ |
| void nfa_hci_api_deregister (tNFA_HCI_EVENT_DATA *p_evt_data) |
| { |
| tNFA_HCI_EVT_DATA evt_data; |
| tNFA_HCI_CBACK *p_cback = NULL; |
| int xx; |
| tNFA_HCI_DYN_PIPE *p_pipe; |
| tNFA_HCI_DYN_GATE *p_gate; |
| |
| /* If needed, find the application registration handle */ |
| if (p_evt_data != NULL) |
| { |
| for (xx = 0; xx < NFA_HCI_MAX_APP_CB; xx++) |
| { |
| if ( (nfa_hci_cb.cfg.reg_app_names[xx][0] != 0) |
| && !strncmp (p_evt_data->app_info.app_name, &nfa_hci_cb.cfg.reg_app_names[xx][0], strlen (p_evt_data->app_info.app_name)) ) |
| { |
| NFA_TRACE_EVENT2 ("nfa_hci_api_deregister (%s) inx: %u", p_evt_data->app_info.app_name, xx); |
| break; |
| } |
| } |
| |
| if (xx == NFA_HCI_MAX_APP_CB) |
| { |
| NFA_TRACE_WARNING1 ("nfa_hci_api_deregister () Unknown app: %s", p_evt_data->app_info.app_name); |
| return; |
| } |
| nfa_hci_cb.app_in_use = (tNFA_HANDLE) (xx | NFA_HANDLE_GROUP_HCI); |
| p_cback = nfa_hci_cb.p_app_cback[xx]; |
| } |
| else |
| { |
| nfa_sys_stop_timer (&nfa_hci_cb.timer); |
| /* We are recursing through deleting all the app's pipes and gates */ |
| p_cback = nfa_hci_cb.p_app_cback[nfa_hci_cb.app_in_use & NFA_HANDLE_MASK]; |
| } |
| |
| /* See if any pipe is owned by this app */ |
| if (nfa_hciu_find_pipe_by_owner (nfa_hci_cb.app_in_use) == NULL) |
| { |
| /* No pipes, release all gates owned by this app */ |
| while ((p_gate = nfa_hciu_find_gate_by_owner (nfa_hci_cb.app_in_use)) != NULL) |
| nfa_hciu_release_gate (p_gate->gate_id); |
| |
| memset (&nfa_hci_cb.cfg.reg_app_names[nfa_hci_cb.app_in_use & NFA_HANDLE_MASK][0], 0, NFA_MAX_HCI_APP_NAME_LEN + 1); |
| nfa_hci_cb.p_app_cback[nfa_hci_cb.app_in_use & NFA_HANDLE_MASK] = NULL; |
| |
| nfa_hci_cb.nv_write_needed = TRUE; |
| |
| evt_data.hci_deregister.status = NFC_STATUS_OK; |
| |
| if (nfa_hci_cb.hci_state == NFA_HCI_STATE_APP_DEREGISTER) |
| nfa_hci_cb.hci_state = NFA_HCI_STATE_IDLE; |
| |
| /* notify NFA_HCI_DEREGISTER_EVT to the application */ |
| if (p_cback) |
| p_cback (NFA_HCI_DEREGISTER_EVT, &evt_data); |
| } |
| else if ((p_pipe = nfa_hciu_find_active_pipe_by_owner (nfa_hci_cb.app_in_use)) == NULL) |
| { |
| /* No pipes, release all gates owned by this app */ |
| while ((p_gate = nfa_hciu_find_gate_with_nopipes_by_owner (nfa_hci_cb.app_in_use)) != NULL) |
| nfa_hciu_release_gate (p_gate->gate_id); |
| |
| nfa_hci_cb.p_app_cback[nfa_hci_cb.app_in_use & NFA_HANDLE_MASK] = NULL; |
| |
| nfa_hci_cb.nv_write_needed = TRUE; |
| |
| evt_data.hci_deregister.status = NFC_STATUS_FAILED; |
| |
| if (nfa_hci_cb.hci_state == NFA_HCI_STATE_APP_DEREGISTER) |
| nfa_hci_cb.hci_state = NFA_HCI_STATE_IDLE; |
| |
| /* notify NFA_HCI_DEREGISTER_EVT to the application */ |
| if (p_cback) |
| p_cback (NFA_HCI_DEREGISTER_EVT, &evt_data); |
| } |
| else |
| { |
| /* Delete all active pipes created for the application before de registering |
| **/ |
| nfa_hci_cb.hci_state = NFA_HCI_STATE_APP_DEREGISTER; |
| |
| nfa_hciu_send_delete_pipe_cmd (p_pipe->pipe_id); |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_api_get_gate_pipe_list |
| ** |
| ** Description action function to get application allocated gates and |
| ** application created pipes |
| ** |
| ** Returns None |
| ** |
| *******************************************************************************/ |
| static void nfa_hci_api_get_gate_pipe_list (tNFA_HCI_EVENT_DATA *p_evt_data) |
| { |
| tNFA_HCI_EVT_DATA evt_data; |
| int xx,yy; |
| tNFA_HCI_DYN_GATE *pg = nfa_hci_cb.cfg.dyn_gates; |
| tNFA_HCI_DYN_PIPE *pp = nfa_hci_cb.cfg.dyn_pipes; |
| |
| evt_data.gates_pipes.num_gates = 0; |
| evt_data.gates_pipes.num_pipes = 0; |
| |
| for ( xx = 0; xx < NFA_HCI_MAX_GATE_CB; xx++, pg++) |
| { |
| if (pg->gate_owner == p_evt_data->get_gate_pipe_list.hci_handle) |
| { |
| evt_data.gates_pipes.gate[evt_data.gates_pipes.num_gates++] = pg->gate_id; |
| |
| pp = nfa_hci_cb.cfg.dyn_pipes; |
| |
| /* Loop through looking for a match */ |
| for ( yy = 0; yy < NFA_HCI_MAX_PIPE_CB; yy++, pp++) |
| { |
| if (pp->local_gate == pg->gate_id) |
| evt_data.gates_pipes.pipe[evt_data.gates_pipes.num_pipes++] = *(tNFA_HCI_PIPE_INFO*)pp; |
| } |
| } |
| } |
| |
| evt_data.gates_pipes.num_uicc_created_pipes = 0; |
| /* Loop through all pipes that are connected to connectivity gate */ |
| for (xx = 0, pp = nfa_hci_cb.cfg.dyn_pipes; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++) |
| { |
| if (pp->pipe_id != 0 && pp->local_gate == NFA_HCI_CONNECTIVITY_GATE) |
| { |
| memcpy (&evt_data.gates_pipes.uicc_created_pipe [evt_data.gates_pipes.num_uicc_created_pipes++], pp, sizeof (tNFA_HCI_PIPE_INFO)); |
| } |
| else if (pp->pipe_id != 0 && pp->local_gate == NFA_HCI_LOOP_BACK_GATE) |
| { |
| memcpy (&evt_data.gates_pipes.uicc_created_pipe [evt_data.gates_pipes.num_uicc_created_pipes++], pp, sizeof (tNFA_HCI_PIPE_INFO)); |
| } |
| } |
| |
| evt_data.gates_pipes.status = NFA_STATUS_OK; |
| |
| /* notify NFA_HCI_GET_GATE_PIPE_LIST_EVT to the application */ |
| nfa_hciu_send_to_app (NFA_HCI_GET_GATE_PIPE_LIST_EVT, &evt_data, p_evt_data->get_gate_pipe_list.hci_handle); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_api_alloc_gate |
| ** |
| ** Description action function to allocate a generic gate |
| ** |
| ** Returns None |
| ** |
| *******************************************************************************/ |
| static void nfa_hci_api_alloc_gate (tNFA_HCI_EVENT_DATA *p_evt_data) |
| { |
| tNFA_HANDLE app_handle = p_evt_data->comm.hci_handle; |
| tNFA_HCI_EVT_DATA evt_data; |
| tNFA_HCI_DYN_GATE *p_gate; |
| |
| p_gate = nfa_hciu_alloc_gate (0, app_handle); |
| |
| evt_data.allocated.gate = p_gate ? p_gate->gate_id : 0; |
| evt_data.allocated.status = p_gate ? NFA_STATUS_OK : NFA_STATUS_FAILED; |
| |
| /* notify NFA_HCI_ALLOCATE_GATE_EVT to the application */ |
| nfa_hciu_send_to_app (NFA_HCI_ALLOCATE_GATE_EVT, &evt_data, app_handle); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_api_dealloc_gate |
| ** |
| ** Description action function to deallocate the given generic gate |
| ** |
| ** Returns None |
| ** |
| *******************************************************************************/ |
| void nfa_hci_api_dealloc_gate (tNFA_HCI_EVENT_DATA *p_evt_data) |
| { |
| tNFA_HCI_EVT_DATA evt_data; |
| UINT8 gate_id; |
| tNFA_HCI_DYN_GATE *p_gate; |
| tNFA_HCI_DYN_PIPE *p_pipe; |
| tNFA_HANDLE app_handle; |
| |
| /* p_evt_data may be NULL if we are recursively deleting pipes */ |
| if (p_evt_data) |
| { |
| gate_id = p_evt_data->gate_dealloc.gate; |
| app_handle = p_evt_data->gate_dealloc.hci_handle; |
| |
| } |
| else |
| { |
| nfa_sys_stop_timer (&nfa_hci_cb.timer); |
| gate_id = nfa_hci_cb.local_gate_in_use; |
| app_handle = nfa_hci_cb.app_in_use; |
| } |
| |
| evt_data.deallocated.gate = gate_id;; |
| |
| p_gate = nfa_hciu_find_gate_by_gid (gate_id); |
| |
| if (p_gate == NULL) |
| { |
| evt_data.deallocated.status = NFA_STATUS_UNKNOWN_GID; |
| } |
| else if (p_gate->gate_owner != app_handle) |
| { |
| evt_data.deallocated.status = NFA_STATUS_FAILED; |
| } |
| else |
| { |
| /* See if any pipe is owned by this app */ |
| if (nfa_hciu_find_pipe_on_gate (p_gate->gate_id) == NULL) |
| { |
| nfa_hciu_release_gate (p_gate->gate_id); |
| |
| nfa_hci_cb.nv_write_needed = TRUE; |
| evt_data.deallocated.status = NFA_STATUS_OK; |
| |
| if (nfa_hci_cb.hci_state == NFA_HCI_STATE_REMOVE_GATE) |
| nfa_hci_cb.hci_state = NFA_HCI_STATE_IDLE; |
| } |
| else if ((p_pipe = nfa_hciu_find_active_pipe_on_gate (p_gate->gate_id)) == NULL) |
| { |
| /* UICC is not active at the moment and cannot delete the pipe */ |
| nfa_hci_cb.nv_write_needed = TRUE; |
| evt_data.deallocated.status = NFA_STATUS_FAILED; |
| |
| if (nfa_hci_cb.hci_state == NFA_HCI_STATE_REMOVE_GATE) |
| nfa_hci_cb.hci_state = NFA_HCI_STATE_IDLE; |
| } |
| else |
| { |
| /* Delete pipes on the gate */ |
| nfa_hci_cb.local_gate_in_use = gate_id; |
| nfa_hci_cb.app_in_use = app_handle; |
| nfa_hci_cb.hci_state = NFA_HCI_STATE_REMOVE_GATE; |
| |
| nfa_hciu_send_delete_pipe_cmd (p_pipe->pipe_id); |
| return; |
| } |
| } |
| |
| nfa_hciu_send_to_app (NFA_HCI_DEALLOCATE_GATE_EVT, &evt_data, app_handle); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_api_get_host_list |
| ** |
| ** Description action function to get the host list from HCI network |
| ** |
| ** Returns None |
| ** |
| *******************************************************************************/ |
| static void nfa_hci_api_get_host_list (tNFA_HCI_EVENT_DATA *p_evt_data) |
| { |
| UINT8 app_inx = p_evt_data->get_host_list.hci_handle & NFA_HANDLE_MASK; |
| |
| nfa_hci_cb.app_in_use = p_evt_data->get_host_list.hci_handle; |
| |
| /* Send Get Host List command on "Internal request" or requested by registered application with valid handle and callback function */ |
| if ( (nfa_hci_cb.app_in_use == NFA_HANDLE_INVALID) |
| ||((app_inx < NFA_HCI_MAX_APP_CB) && (nfa_hci_cb.p_app_cback[app_inx] != NULL)) ) |
| { |
| nfa_hciu_send_get_param_cmd (NFA_HCI_ADMIN_PIPE, NFA_HCI_HOST_LIST_INDEX); |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_api_create_pipe |
| ** |
| ** Description action function to create a pipe |
| ** |
| ** Returns TRUE, if the command is processed |
| ** FALSE, if command is queued for processing later |
| ** |
| *******************************************************************************/ |
| static BOOLEAN nfa_hci_api_create_pipe (tNFA_HCI_EVENT_DATA *p_evt_data) |
| { |
| tNFA_HCI_DYN_GATE *p_gate = nfa_hciu_find_gate_by_gid (p_evt_data->create_pipe.source_gate); |
| tNFA_HCI_EVT_DATA evt_data; |
| |
| /* Verify that the app owns the gate that the pipe is being created on */ |
| if ((p_gate == NULL) || (p_gate->gate_owner != p_evt_data->create_pipe.hci_handle)) |
| { |
| evt_data.created.source_gate = p_evt_data->create_pipe.source_gate; |
| evt_data.created.status = NFA_STATUS_FAILED; |
| |
| NFA_TRACE_ERROR2 ("nfa_hci_api_create_pipe Cannot create pipe! APP: 0x%02x does not own the gate:0x%x", p_evt_data->create_pipe.hci_handle, p_evt_data->create_pipe.source_gate); |
| nfa_hciu_send_to_app (NFA_HCI_CREATE_PIPE_EVT, &evt_data, p_evt_data->open_pipe.hci_handle); |
| } |
| else |
| { |
| if (nfa_hciu_is_host_reseting (p_evt_data->create_pipe.dest_gate)) |
| { |
| GKI_enqueue (&nfa_hci_cb.hci_host_reset_api_q, (BT_HDR *) p_evt_data); |
| return FALSE; |
| } |
| |
| nfa_hci_cb.local_gate_in_use = p_evt_data->create_pipe.source_gate; |
| nfa_hci_cb.remote_gate_in_use = p_evt_data->create_pipe.dest_gate; |
| nfa_hci_cb.remote_host_in_use = p_evt_data->create_pipe.dest_host; |
| nfa_hci_cb.app_in_use = p_evt_data->create_pipe.hci_handle; |
| |
| nfa_hciu_send_create_pipe_cmd (p_evt_data->create_pipe.source_gate, p_evt_data->create_pipe.dest_host, p_evt_data->create_pipe.dest_gate); |
| } |
| return TRUE; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_api_open_pipe |
| ** |
| ** Description action function to open a pipe |
| ** |
| ** Returns None |
| ** |
| *******************************************************************************/ |
| static void nfa_hci_api_open_pipe (tNFA_HCI_EVENT_DATA *p_evt_data) |
| { |
| tNFA_HCI_EVT_DATA evt_data; |
| tNFA_HCI_DYN_PIPE *p_pipe = nfa_hciu_find_pipe_by_pid (p_evt_data->open_pipe.pipe); |
| tNFA_HCI_DYN_GATE *p_gate = NULL; |
| |
| if (p_pipe != NULL) |
| p_gate = nfa_hciu_find_gate_by_gid (p_pipe->local_gate); |
| |
| if ( (p_pipe != NULL) |
| &&(p_gate != NULL) |
| &&(nfa_hciu_is_active_host (p_pipe->dest_host)) |
| &&(p_gate->gate_owner == p_evt_data->open_pipe.hci_handle)) |
| { |
| if (p_pipe->pipe_state == NFA_HCI_PIPE_CLOSED) |
| { |
| nfa_hciu_send_open_pipe_cmd (p_evt_data->open_pipe.pipe); |
| } |
| else |
| { |
| evt_data.opened.pipe = p_evt_data->open_pipe.pipe; |
| evt_data.opened.status = NFA_STATUS_OK; |
| |
| nfa_hciu_send_to_app (NFA_HCI_OPEN_PIPE_EVT, &evt_data, p_evt_data->open_pipe.hci_handle); |
| } |
| } |
| else |
| { |
| evt_data.opened.pipe = p_evt_data->open_pipe.pipe; |
| evt_data.opened.status = NFA_STATUS_FAILED; |
| |
| nfa_hciu_send_to_app (NFA_HCI_OPEN_PIPE_EVT, &evt_data, p_evt_data->open_pipe.hci_handle); |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_api_get_reg_value |
| ** |
| ** Description action function to get the reg value of the specified index |
| ** |
| ** Returns TRUE, if the command is processed |
| ** FALSE, if command is queued for processing later |
| ** |
| *******************************************************************************/ |
| static BOOLEAN nfa_hci_api_get_reg_value (tNFA_HCI_EVENT_DATA *p_evt_data) |
| { |
| tNFA_HCI_DYN_PIPE *p_pipe = nfa_hciu_find_pipe_by_pid (p_evt_data->get_registry.pipe); |
| tNFA_HCI_DYN_GATE *p_gate; |
| tNFA_STATUS status = NFA_STATUS_FAILED; |
| tNFA_HCI_EVT_DATA evt_data; |
| |
| if (p_pipe != NULL) |
| { |
| p_gate = nfa_hciu_find_gate_by_gid (p_pipe->local_gate); |
| |
| if ((p_gate != NULL) && (nfa_hciu_is_active_host (p_pipe->dest_host)) && (p_gate->gate_owner == p_evt_data->get_registry.hci_handle)) |
| { |
| nfa_hci_cb.app_in_use = p_evt_data->get_registry.hci_handle; |
| |
| if (nfa_hciu_is_host_reseting (p_pipe->dest_host)) |
| { |
| GKI_enqueue (&nfa_hci_cb.hci_host_reset_api_q, (BT_HDR *) p_evt_data); |
| return FALSE; |
| } |
| |
| if (p_pipe->pipe_state == NFA_HCI_PIPE_CLOSED) |
| { |
| NFA_TRACE_WARNING1 ("nfa_hci_api_get_reg_value pipe:%d not open", p_evt_data->get_registry.pipe); |
| } |
| else |
| { |
| if ((status = nfa_hciu_send_get_param_cmd (p_evt_data->get_registry.pipe, p_evt_data->get_registry.reg_inx)) == NFA_STATUS_OK) |
| return TRUE; |
| } |
| } |
| } |
| |
| evt_data.cmd_sent.status = status; |
| |
| /* Send NFA_HCI_CMD_SENT_EVT to notify failure */ |
| nfa_hciu_send_to_app (NFA_HCI_CMD_SENT_EVT, &evt_data, p_evt_data->get_registry.hci_handle); |
| return TRUE; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_api_set_reg_value |
| ** |
| ** Description action function to set the reg value at specified index |
| ** |
| ** Returns TRUE, if the command is processed |
| ** FALSE, if command is queued for processing later |
| ** |
| *******************************************************************************/ |
| static BOOLEAN nfa_hci_api_set_reg_value (tNFA_HCI_EVENT_DATA *p_evt_data) |
| { |
| tNFA_HCI_DYN_PIPE *p_pipe = nfa_hciu_find_pipe_by_pid (p_evt_data->set_registry.pipe); |
| tNFA_HCI_DYN_GATE *p_gate; |
| tNFA_STATUS status = NFA_STATUS_FAILED; |
| tNFA_HCI_EVT_DATA evt_data; |
| |
| if (p_pipe != NULL) |
| { |
| p_gate = nfa_hciu_find_gate_by_gid (p_pipe->local_gate); |
| |
| if ((p_gate != NULL) && (nfa_hciu_is_active_host (p_pipe->dest_host)) && (p_gate->gate_owner == p_evt_data->set_registry.hci_handle)) |
| { |
| nfa_hci_cb.app_in_use = p_evt_data->set_registry.hci_handle; |
| |
| if (nfa_hciu_is_host_reseting (p_pipe->dest_host)) |
| { |
| GKI_enqueue (&nfa_hci_cb.hci_host_reset_api_q, (BT_HDR *) p_evt_data); |
| return FALSE; |
| } |
| |
| if (p_pipe->pipe_state == NFA_HCI_PIPE_CLOSED) |
| { |
| NFA_TRACE_WARNING1 ("nfa_hci_api_set_reg_value pipe:%d not open", p_evt_data->set_registry.pipe); |
| } |
| else |
| { |
| if ((status = nfa_hciu_send_set_param_cmd (p_evt_data->set_registry.pipe, p_evt_data->set_registry.reg_inx, p_evt_data->set_registry.size, p_evt_data->set_registry.data)) == NFA_STATUS_OK) |
| return TRUE; |
| } |
| } |
| } |
| evt_data.cmd_sent.status = status; |
| |
| /* Send NFA_HCI_CMD_SENT_EVT to notify failure */ |
| nfa_hciu_send_to_app (NFA_HCI_CMD_SENT_EVT, &evt_data, p_evt_data->set_registry.hci_handle); |
| return TRUE; |
| |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_api_close_pipe |
| ** |
| ** Description action function to close a pipe |
| ** |
| ** Returns None |
| ** |
| *******************************************************************************/ |
| static void nfa_hci_api_close_pipe (tNFA_HCI_EVENT_DATA *p_evt_data) |
| { |
| tNFA_HCI_EVT_DATA evt_data; |
| tNFA_HCI_DYN_PIPE *p_pipe = nfa_hciu_find_pipe_by_pid (p_evt_data->close_pipe.pipe); |
| tNFA_HCI_DYN_GATE *p_gate = NULL; |
| |
| if (p_pipe != NULL) |
| p_gate = nfa_hciu_find_gate_by_gid (p_pipe->local_gate); |
| |
| if ( (p_pipe != NULL) |
| &&(p_gate != NULL) |
| &&(nfa_hciu_is_active_host (p_pipe->dest_host)) |
| &&(p_gate->gate_owner == p_evt_data->close_pipe.hci_handle) ) |
| { |
| if (p_pipe->pipe_state == NFA_HCI_PIPE_OPENED) |
| { |
| nfa_hciu_send_close_pipe_cmd (p_evt_data->close_pipe.pipe); |
| } |
| else |
| { |
| evt_data.closed.status = NFA_STATUS_OK; |
| evt_data.closed.pipe = p_evt_data->close_pipe.pipe; |
| |
| nfa_hciu_send_to_app (NFA_HCI_CLOSE_PIPE_EVT, &evt_data, p_evt_data->close_pipe.hci_handle); |
| } |
| } |
| else |
| { |
| evt_data.closed.status = NFA_STATUS_FAILED; |
| evt_data.closed.pipe = 0x00; |
| |
| nfa_hciu_send_to_app (NFA_HCI_CLOSE_PIPE_EVT, &evt_data, p_evt_data->close_pipe.hci_handle); |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_api_delete_pipe |
| ** |
| ** Description action function to delete a pipe |
| ** |
| ** Returns None |
| ** |
| *******************************************************************************/ |
| static void nfa_hci_api_delete_pipe (tNFA_HCI_EVENT_DATA *p_evt_data) |
| { |
| tNFA_HCI_EVT_DATA evt_data; |
| tNFA_HCI_DYN_PIPE *p_pipe = nfa_hciu_find_pipe_by_pid (p_evt_data->delete_pipe.pipe); |
| tNFA_HCI_DYN_GATE *p_gate = NULL; |
| |
| if (p_pipe != NULL) |
| { |
| p_gate = nfa_hciu_find_gate_by_gid (p_pipe->local_gate); |
| if ( (p_gate != NULL) |
| &&(p_gate->gate_owner == p_evt_data->delete_pipe.hci_handle) |
| &&(nfa_hciu_is_active_host (p_pipe->dest_host)) ) |
| { |
| nfa_hciu_send_delete_pipe_cmd (p_evt_data->delete_pipe.pipe); |
| return; |
| } |
| } |
| |
| evt_data.deleted.status = NFA_STATUS_FAILED; |
| evt_data.deleted.pipe = 0x00; |
| nfa_hciu_send_to_app (NFA_HCI_DELETE_PIPE_EVT, &evt_data, p_evt_data->close_pipe.hci_handle); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_api_send_cmd |
| ** |
| ** Description action function to send command on the given pipe |
| ** |
| ** Returns TRUE, if the command is processed |
| ** FALSE, if command is queued for processing later |
| ** |
| *******************************************************************************/ |
| static BOOLEAN nfa_hci_api_send_cmd (tNFA_HCI_EVENT_DATA *p_evt_data) |
| { |
| tNFA_STATUS status = NFA_STATUS_FAILED; |
| tNFA_HCI_DYN_PIPE *p_pipe; |
| tNFA_HCI_EVT_DATA evt_data; |
| tNFA_HANDLE app_handle; |
| |
| if ((p_pipe = nfa_hciu_find_pipe_by_pid (p_evt_data->send_cmd.pipe)) != NULL) |
| { |
| app_handle = nfa_hciu_get_pipe_owner (p_evt_data->send_cmd.pipe); |
| |
| if ( (nfa_hciu_is_active_host (p_pipe->dest_host)) |
| &&((app_handle == p_evt_data->send_cmd.hci_handle || p_pipe->local_gate == NFA_HCI_CONNECTIVITY_GATE)) ) |
| { |
| if (nfa_hciu_is_host_reseting (p_pipe->dest_host)) |
| { |
| GKI_enqueue (&nfa_hci_cb.hci_host_reset_api_q, (BT_HDR *) p_evt_data); |
| return FALSE; |
| } |
| |
| if (p_pipe->pipe_state == NFA_HCI_PIPE_OPENED) |
| { |
| nfa_hci_cb.pipe_in_use = p_evt_data->send_cmd.pipe; |
| if ((status = nfa_hciu_send_msg (p_pipe->pipe_id, NFA_HCI_COMMAND_TYPE, p_evt_data->send_cmd.cmd_code, |
| p_evt_data->send_cmd.cmd_len, p_evt_data->send_cmd.data)) == NFA_STATUS_OK) |
| return TRUE; |
| } |
| else |
| { |
| NFA_TRACE_WARNING1 ("nfa_hci_api_send_cmd pipe:%d not open", p_pipe->pipe_id); |
| } |
| } |
| else |
| { |
| NFA_TRACE_WARNING1 ("nfa_hci_api_send_cmd pipe:%d Owned by different application or Destination host is not active", |
| p_pipe->pipe_id); |
| } |
| } |
| else |
| { |
| NFA_TRACE_WARNING1 ("nfa_hci_api_send_cmd pipe:%d not found", p_evt_data->send_cmd.pipe); |
| } |
| |
| evt_data.cmd_sent.status = status; |
| |
| /* Send NFA_HCI_CMD_SENT_EVT to notify failure */ |
| nfa_hciu_send_to_app (NFA_HCI_CMD_SENT_EVT, &evt_data, p_evt_data->send_cmd.hci_handle); |
| return TRUE; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_api_send_rsp |
| ** |
| ** Description action function to send response on the given pipe |
| ** |
| ** Returns None |
| ** |
| *******************************************************************************/ |
| static void nfa_hci_api_send_rsp (tNFA_HCI_EVENT_DATA *p_evt_data) |
| { |
| tNFA_STATUS status = NFA_STATUS_FAILED; |
| tNFA_HCI_DYN_PIPE *p_pipe; |
| tNFA_HCI_EVT_DATA evt_data; |
| tNFA_HANDLE app_handle; |
| |
| if ((p_pipe = nfa_hciu_find_pipe_by_pid (p_evt_data->send_rsp.pipe)) != NULL) |
| { |
| app_handle = nfa_hciu_get_pipe_owner (p_evt_data->send_rsp.pipe); |
| |
| if ( (nfa_hciu_is_active_host (p_pipe->dest_host)) |
| &&((app_handle == p_evt_data->send_rsp.hci_handle || p_pipe->local_gate == NFA_HCI_CONNECTIVITY_GATE)) ) |
| { |
| if (p_pipe->pipe_state == NFA_HCI_PIPE_OPENED) |
| { |
| if ((status = nfa_hciu_send_msg (p_pipe->pipe_id, NFA_HCI_RESPONSE_TYPE, p_evt_data->send_rsp.response, |
| p_evt_data->send_rsp.size, p_evt_data->send_rsp.data)) == NFA_STATUS_OK) |
| return; |
| } |
| else |
| { |
| NFA_TRACE_WARNING1 ("nfa_hci_api_send_rsp pipe:%d not open", p_pipe->pipe_id); |
| } |
| } |
| else |
| { |
| NFA_TRACE_WARNING1 ("nfa_hci_api_send_rsp pipe:%d Owned by different application or Destination host is not active", |
| p_pipe->pipe_id); |
| } |
| } |
| else |
| { |
| NFA_TRACE_WARNING1 ("nfa_hci_api_send_rsp pipe:%d not found", p_evt_data->send_rsp.pipe); |
| } |
| |
| evt_data.rsp_sent.status = status; |
| |
| /* Send NFA_HCI_RSP_SENT_EVT to notify failure */ |
| nfa_hciu_send_to_app (NFA_HCI_RSP_SENT_EVT, &evt_data, p_evt_data->send_rsp.hci_handle); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_api_send_event |
| ** |
| ** Description action function to send an event to the given pipe |
| ** |
| ** Returns TRUE, if the event is processed |
| ** FALSE, if event is queued for processing later |
| ** |
| *******************************************************************************/ |
| static BOOLEAN nfa_hci_api_send_event (tNFA_HCI_EVENT_DATA *p_evt_data) |
| { |
| tNFA_STATUS status = NFA_STATUS_FAILED; |
| tNFA_HCI_DYN_PIPE *p_pipe; |
| tNFA_HCI_EVT_DATA evt_data; |
| tNFA_HANDLE app_handle; |
| |
| if ((p_pipe = nfa_hciu_find_pipe_by_pid (p_evt_data->send_evt.pipe)) != NULL) |
| { |
| app_handle = nfa_hciu_get_pipe_owner (p_evt_data->send_evt.pipe); |
| |
| if ( (nfa_hciu_is_active_host (p_pipe->dest_host)) |
| &&((app_handle == p_evt_data->send_evt.hci_handle || p_pipe->local_gate == NFA_HCI_CONNECTIVITY_GATE)) ) |
| { |
| if (nfa_hciu_is_host_reseting (p_pipe->dest_host)) |
| { |
| GKI_enqueue (&nfa_hci_cb.hci_host_reset_api_q, (BT_HDR *) p_evt_data); |
| return FALSE; |
| } |
| |
| if (p_pipe->pipe_state == NFA_HCI_PIPE_OPENED) |
| { |
| status = nfa_hciu_send_msg (p_pipe->pipe_id, NFA_HCI_EVENT_TYPE, p_evt_data->send_evt.evt_code, |
| p_evt_data->send_evt.evt_len, p_evt_data->send_evt.p_evt_buf); |
| |
| if (status == NFA_STATUS_OK) |
| { |
| if (p_pipe->local_gate == NFA_HCI_LOOP_BACK_GATE) |
| { |
| nfa_hci_cb.w4_rsp_evt = TRUE; |
| nfa_hci_cb.hci_state = NFA_HCI_STATE_WAIT_RSP; |
| } |
| |
| if (p_evt_data->send_evt.rsp_len) |
| { |
| nfa_hci_cb.pipe_in_use = p_evt_data->send_evt.pipe; |
| nfa_hci_cb.rsp_buf_size = p_evt_data->send_evt.rsp_len; |
| nfa_hci_cb.p_rsp_buf = p_evt_data->send_evt.p_rsp_buf; |
| if (p_evt_data->send_evt.rsp_timeout) |
| { |
| nfa_hci_cb.w4_rsp_evt = TRUE; |
| nfa_hci_cb.hci_state = NFA_HCI_STATE_WAIT_RSP; |
| nfa_sys_start_timer (&nfa_hci_cb.timer, NFA_HCI_RSP_TIMEOUT_EVT, p_evt_data->send_evt.rsp_timeout); |
| } |
| else if (p_pipe->local_gate == NFA_HCI_LOOP_BACK_GATE) |
| { |
| nfa_sys_start_timer (&nfa_hci_cb.timer, NFA_HCI_RSP_TIMEOUT_EVT, p_nfa_hci_cfg->hcp_response_timeout); |
| } |
| } |
| else |
| { |
| if (p_pipe->local_gate == NFA_HCI_LOOP_BACK_GATE) |
| { |
| nfa_hci_cb.pipe_in_use = p_evt_data->send_evt.pipe; |
| nfa_sys_start_timer (&nfa_hci_cb.timer, NFA_HCI_RSP_TIMEOUT_EVT, p_nfa_hci_cfg->hcp_response_timeout); |
| } |
| nfa_hci_cb.rsp_buf_size = 0; |
| nfa_hci_cb.p_rsp_buf = NULL; |
| } |
| } |
| } |
| else |
| { |
| NFA_TRACE_WARNING1 ("nfa_hci_api_send_event pipe:%d not open", p_pipe->pipe_id); |
| } |
| } |
| else |
| { |
| NFA_TRACE_WARNING1 ("nfa_hci_api_send_event pipe:%d Owned by different application or Destination host is not active", |
| p_pipe->pipe_id); |
| } |
| } |
| else |
| { |
| NFA_TRACE_WARNING1 ("nfa_hci_api_send_event pipe:%d not found", p_evt_data->send_evt.pipe); |
| } |
| |
| evt_data.evt_sent.status = status; |
| |
| /* Send NFC_HCI_EVENT_SENT_EVT to notify status */ |
| nfa_hciu_send_to_app (NFA_HCI_EVENT_SENT_EVT, &evt_data, p_evt_data->send_evt.hci_handle); |
| return TRUE; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_api_add_static_pipe |
| ** |
| ** Description action function to add static pipe |
| ** |
| ** Returns None |
| ** |
| *******************************************************************************/ |
| static void nfa_hci_api_add_static_pipe (tNFA_HCI_EVENT_DATA *p_evt_data) |
| { |
| tNFA_HCI_DYN_GATE *pg; |
| tNFA_HCI_DYN_PIPE *pp; |
| tNFA_HCI_EVT_DATA evt_data; |
| |
| /* Allocate a proprietary gate */ |
| if ((pg = nfa_hciu_alloc_gate (p_evt_data->add_static_pipe.gate, p_evt_data->add_static_pipe.hci_handle)) != NULL) |
| { |
| /* Assign new owner to the gate */ |
| pg->gate_owner = p_evt_data->add_static_pipe.hci_handle; |
| |
| /* Add the dynamic pipe to the proprietary gate */ |
| if (nfa_hciu_add_pipe_to_gate (p_evt_data->add_static_pipe.pipe,pg->gate_id, p_evt_data->add_static_pipe.host, p_evt_data->add_static_pipe.gate) != NFA_HCI_ANY_OK) |
| { |
| /* Unable to add the dynamic pipe, so release the gate */ |
| nfa_hciu_release_gate (pg->gate_id); |
| evt_data.pipe_added.status = NFA_STATUS_FAILED; |
| nfa_hciu_send_to_app (NFA_HCI_ADD_STATIC_PIPE_EVT, &evt_data, p_evt_data->add_static_pipe.hci_handle); |
| return; |
| } |
| if ((pp = nfa_hciu_find_pipe_by_pid (p_evt_data->add_static_pipe.pipe)) != NULL) |
| { |
| /* This pipe is always opened */ |
| pp->pipe_state = NFA_HCI_PIPE_OPENED; |
| evt_data.pipe_added.status = NFA_STATUS_OK; |
| nfa_hciu_send_to_app (NFA_HCI_ADD_STATIC_PIPE_EVT, &evt_data, p_evt_data->add_static_pipe.hci_handle); |
| return; |
| } |
| } |
| /* Unable to add static pipe */ |
| evt_data.pipe_added.status = NFA_STATUS_FAILED; |
| nfa_hciu_send_to_app (NFA_HCI_ADD_STATIC_PIPE_EVT, &evt_data, p_evt_data->add_static_pipe.hci_handle); |
| |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_handle_link_mgm_gate_cmd |
| ** |
| ** Description This function handles incoming link management gate hci |
| ** commands |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| void nfa_hci_handle_link_mgm_gate_cmd (UINT8 *p_data) |
| { |
| UINT8 index; |
| UINT8 data[2]; |
| UINT8 rsp_len = 0; |
| UINT8 response = NFA_HCI_ANY_OK; |
| |
| if ( (nfa_hci_cb.cfg.link_mgmt_gate.pipe00_state != NFA_HCI_PIPE_OPENED) |
| &&(nfa_hci_cb.inst != NFA_HCI_ANY_OPEN_PIPE) ) |
| { |
| nfa_hciu_send_msg (NFA_HCI_LINK_MANAGEMENT_PIPE, NFA_HCI_RESPONSE_TYPE, NFA_HCI_ANY_E_PIPE_NOT_OPENED, 0, NULL); |
| return; |
| } |
| |
| switch (nfa_hci_cb.inst) |
| { |
| case NFA_HCI_ANY_SET_PARAMETER: |
| STREAM_TO_UINT8 (index, p_data); |
| |
| if (index == 1) |
| { |
| STREAM_TO_UINT16 (nfa_hci_cb.cfg.link_mgmt_gate.rec_errors, p_data); |
| } |
| else |
| response = NFA_HCI_ANY_E_REG_PAR_UNKNOWN; |
| break; |
| |
| case NFA_HCI_ANY_GET_PARAMETER: |
| STREAM_TO_UINT8 (index, p_data); |
| if (index == 1) |
| { |
| data[0] = (UINT8) ((nfa_hci_cb.cfg.link_mgmt_gate.rec_errors >> 8) & 0x00FF); |
| data[1] = (UINT8) (nfa_hci_cb.cfg.link_mgmt_gate.rec_errors & 0x000F); |
| rsp_len = 2; |
| } |
| else |
| response = NFA_HCI_ANY_E_REG_PAR_UNKNOWN; |
| break; |
| |
| case NFA_HCI_ANY_OPEN_PIPE: |
| data[0] = 0; |
| rsp_len = 1; |
| nfa_hci_cb.cfg.link_mgmt_gate.pipe00_state = NFA_HCI_PIPE_OPENED; |
| break; |
| |
| case NFA_HCI_ANY_CLOSE_PIPE: |
| nfa_hci_cb.cfg.link_mgmt_gate.pipe00_state = NFA_HCI_PIPE_CLOSED; |
| break; |
| |
| default: |
| response = NFA_HCI_ANY_E_CMD_NOT_SUPPORTED; |
| break; |
| } |
| |
| nfa_hciu_send_msg (NFA_HCI_LINK_MANAGEMENT_PIPE, NFA_HCI_RESPONSE_TYPE, response, rsp_len, data); |
| } |
| |
| |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_handle_pipe_open_close_cmd |
| ** |
| ** Description This function handles all generic gates (excluding |
| ** connectivity gate) commands |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| void nfa_hci_handle_pipe_open_close_cmd (tNFA_HCI_DYN_PIPE *p_pipe) |
| { |
| UINT8 data[1]; |
| UINT8 rsp_len = 0; |
| tNFA_HCI_RESPONSE response = NFA_HCI_ANY_OK; |
| tNFA_HCI_DYN_GATE *p_gate; |
| |
| if (nfa_hci_cb.inst == NFA_HCI_ANY_OPEN_PIPE) |
| { |
| if ((p_gate = nfa_hciu_find_gate_by_gid(p_pipe->local_gate)) != NULL) |
| data[0] = nfa_hciu_count_open_pipes_on_gate (p_gate); |
| else |
| data[0] = 0; |
| |
| p_pipe->pipe_state = NFA_HCI_PIPE_OPENED; |
| rsp_len = 1; |
| } |
| else if (nfa_hci_cb.inst == NFA_HCI_ANY_CLOSE_PIPE) |
| { |
| p_pipe->pipe_state = NFA_HCI_PIPE_CLOSED; |
| } |
| |
| nfa_hciu_send_msg (p_pipe->pipe_id, NFA_HCI_RESPONSE_TYPE, response, rsp_len, data); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_handle_admin_gate_cmd |
| ** |
| ** Description This function handles incoming commands on ADMIN gate |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| void nfa_hci_handle_admin_gate_cmd (UINT8 *p_data) |
| { |
| UINT8 source_host, source_gate, dest_host, dest_gate, pipe; |
| UINT8 data = 0; |
| UINT8 rsp_len = 0; |
| tNFA_HCI_RESPONSE response = NFA_HCI_ANY_OK; |
| tNFA_HCI_DYN_GATE *pgate; |
| tNFA_HCI_EVT_DATA evt_data; |
| |
| switch (nfa_hci_cb.inst) |
| { |
| case NFA_HCI_ANY_OPEN_PIPE: |
| nfa_hci_cb.cfg.admin_gate.pipe01_state = NFA_HCI_PIPE_OPENED; |
| data = 0; |
| rsp_len = 1; |
| break; |
| |
| case NFA_HCI_ANY_CLOSE_PIPE: |
| nfa_hci_cb.cfg.admin_gate.pipe01_state = NFA_HCI_PIPE_CLOSED; |
| /* Reopen the pipe immediately */ |
| nfa_hciu_send_msg (NFA_HCI_ADMIN_PIPE, NFA_HCI_RESPONSE_TYPE, response, rsp_len, &data); |
| nfa_hci_cb.app_in_use = NFA_HANDLE_INVALID; |
| nfa_hciu_send_open_pipe_cmd (NFA_HCI_ADMIN_PIPE); |
| return; |
| break; |
| |
| case NFA_HCI_ADM_NOTIFY_PIPE_CREATED: |
| STREAM_TO_UINT8 (source_host, p_data); |
| STREAM_TO_UINT8 (source_gate, p_data); |
| STREAM_TO_UINT8 (dest_host, p_data); |
| STREAM_TO_UINT8 (dest_gate, p_data); |
| STREAM_TO_UINT8 (pipe, p_data); |
| |
| if ( (dest_gate == NFA_HCI_IDENTITY_MANAGEMENT_GATE) |
| ||(dest_gate == NFA_HCI_LOOP_BACK_GATE) ) |
| { |
| response = nfa_hciu_add_pipe_to_static_gate (dest_gate, pipe, source_host, source_gate); |
| } |
| else |
| { |
| if ((pgate = nfa_hciu_find_gate_by_gid (dest_gate)) != NULL) |
| { |
| /* If the gate is valid, add the pipe to it */ |
| if ((response = nfa_hciu_add_pipe_to_gate (pipe, dest_gate, source_host, source_gate)) == NFA_HCI_ANY_OK) |
| { |
| /* Tell the application a pipe was created with its gate */ |
| |
| evt_data.created.status = NFA_STATUS_OK; |
| evt_data.created.pipe = pipe; |
| evt_data.created.source_gate = dest_gate; |
| evt_data.created.dest_host = source_host; |
| evt_data.created.dest_gate = source_gate; |
| |
| nfa_hciu_send_to_app (NFA_HCI_CREATE_PIPE_EVT, &evt_data, pgate->gate_owner); |
| } |
| } |
| else |
| response = NFA_HCI_ANY_E_NOK; |
| } |
| break; |
| |
| case NFA_HCI_ADM_NOTIFY_PIPE_DELETED: |
| STREAM_TO_UINT8 (pipe, p_data); |
| response = nfa_hciu_release_pipe (pipe); |
| break; |
| |
| case NFA_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED: |
| STREAM_TO_UINT8 (source_host, p_data); |
| |
| nfa_hciu_remove_all_pipes_from_host (source_host); |
| |
| if (source_host == NFA_HCI_HOST_CONTROLLER) |
| { |
| nfa_hci_cb.cfg.link_mgmt_gate.pipe00_state = NFA_HCI_PIPE_CLOSED; |
| nfa_hci_cb.cfg.admin_gate.pipe01_state = NFA_HCI_PIPE_CLOSED; |
| |
| /* Reopen the admin pipe immediately */ |
| nfa_hci_cb.app_in_use = NFA_HANDLE_INVALID; |
| nfa_hciu_send_open_pipe_cmd (NFA_HCI_ADMIN_PIPE); |
| return; |
| } |
| else |
| { |
| if ( (source_host >= NFA_HCI_HOST_ID_UICC0) |
| &&(source_host < (NFA_HCI_HOST_ID_UICC0 + NFA_HCI_MAX_HOST_IN_NETWORK)) ) |
| { |
| nfa_hci_cb.reset_host[source_host - NFA_HCI_HOST_ID_UICC0] = source_host; |
| } |
| } |
| break; |
| |
| default: |
| response = NFA_HCI_ANY_E_CMD_NOT_SUPPORTED; |
| break; |
| } |
| |
| nfa_hciu_send_msg (NFA_HCI_ADMIN_PIPE, NFA_HCI_RESPONSE_TYPE, response, rsp_len, &data); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_handle_admin_gate_rsp |
| ** |
| ** Description This function handles response received on admin gate |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| void nfa_hci_handle_admin_gate_rsp (UINT8 *p_data, UINT8 data_len) |
| { |
| UINT8 hosts[2] = {NFA_HCI_HOST_ID_UICC0, (NFA_HCI_HOST_ID_UICC0 + 1)}; |
| UINT8 source_host; |
| UINT8 source_gate = nfa_hci_cb.local_gate_in_use; |
| UINT8 dest_host = nfa_hci_cb.remote_host_in_use; |
| UINT8 dest_gate = nfa_hci_cb.remote_gate_in_use; |
| UINT8 pipe = 0; |
| tNFA_STATUS status; |
| tNFA_HCI_EVT_DATA evt_data; |
| UINT8 default_session[NFA_HCI_SESSION_ID_LEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; |
| UINT8 host_count = 0; |
| UINT8 host_id = 0; |
| UINT32 os_tick; |
| |
| #if (BT_TRACE_VERBOSE == TRUE) |
| NFA_TRACE_DEBUG4 ("nfa_hci_handle_admin_gate_rsp - LastCmdSent: %s App: 0x%04x Gate: 0x%02x Pipe: 0x%02x", |
| nfa_hciu_instr_2_str(nfa_hci_cb.cmd_sent), nfa_hci_cb.app_in_use, nfa_hci_cb.local_gate_in_use, nfa_hci_cb.pipe_in_use); |
| #else |
| NFA_TRACE_DEBUG4 ("nfa_hci_handle_admin_gate_rsp LastCmdSent: %u App: 0x%04x Gate: 0x%02x Pipe: 0x%02x", |
| nfa_hci_cb.cmd_sent, nfa_hci_cb.app_in_use, nfa_hci_cb.local_gate_in_use, nfa_hci_cb.pipe_in_use); |
| #endif |
| |
| if (nfa_hci_cb.inst == NFA_HCI_ANY_E_PIPE_NOT_OPENED) |
| { |
| nfa_hciu_send_open_pipe_cmd (NFA_HCI_ADMIN_PIPE); |
| return; |
| } |
| |
| /* If starting up, handle events here */ |
| if ( (nfa_hci_cb.hci_state == NFA_HCI_STATE_STARTUP) |
| ||(nfa_hci_cb.hci_state == NFA_HCI_STATE_RESTORE) |
| ||(nfa_hci_cb.hci_state == NFA_HCI_STATE_WAIT_NETWK_ENABLE) |
| ||(nfa_hci_cb.hci_state == NFA_HCI_STATE_RESTORE_NETWK_ENABLE)) |
| { |
| if (nfa_hci_cb.inst != NFA_HCI_ANY_OK) |
| { |
| NFA_TRACE_ERROR0 ("nfa_hci_handle_admin_gate_rsp - Initialization failed"); |
| nfa_hci_startup_complete (NFA_STATUS_FAILED); |
| return; |
| } |
| |
| switch (nfa_hci_cb.cmd_sent) |
| { |
| case NFA_HCI_ANY_SET_PARAMETER: |
| if (nfa_hci_cb.param_in_use == NFA_HCI_SESSION_IDENTITY_INDEX) |
| { |
| /* Set WHITELIST */ |
| nfa_hciu_send_set_param_cmd (NFA_HCI_ADMIN_PIPE, NFA_HCI_WHITELIST_INDEX, 0x02, hosts); |
| } |
| else if (nfa_hci_cb.param_in_use == NFA_HCI_WHITELIST_INDEX) |
| { |
| if ( (nfa_hci_cb.hci_state == NFA_HCI_STATE_STARTUP) |
| ||(nfa_hci_cb.hci_state == NFA_HCI_STATE_RESTORE) ) |
| nfa_hci_dh_startup_complete (); |
| } |
| break; |
| |
| case NFA_HCI_ANY_GET_PARAMETER: |
| if (nfa_hci_cb.param_in_use == NFA_HCI_HOST_LIST_INDEX) |
| { |
| host_count = 0; |
| while (host_count < NFA_HCI_MAX_HOST_IN_NETWORK) |
| { |
| nfa_hci_cb.inactive_host[host_count] = NFA_HCI_HOST_ID_UICC0 + host_count; |
| host_count++; |
| } |
| |
| host_count = 0; |
| /* Collect active host in the Host Network */ |
| while (host_count < data_len) |
| { |
| host_id = (UINT8) *p_data++; |
| |
| if ( (host_id >= NFA_HCI_HOST_ID_UICC0) |
| &&(host_id < NFA_HCI_HOST_ID_UICC0 + NFA_HCI_MAX_HOST_IN_NETWORK) ) |
| { |
| nfa_hci_cb.inactive_host[host_id - NFA_HCI_HOST_ID_UICC0] = 0x00; |
| nfa_hci_cb.reset_host[host_id - NFA_HCI_HOST_ID_UICC0] = 0x00; |
| } |
| |
| host_count++; |
| } |
| nfa_hci_startup_complete (NFA_STATUS_OK); |
| } |
| else if (nfa_hci_cb.param_in_use == NFA_HCI_SESSION_IDENTITY_INDEX) |
| { |
| /* The only parameter we get when initializing is the session ID. Check for match. */ |
| if (!memcmp ((UINT8 *) nfa_hci_cb.cfg.admin_gate.session_id, p_data, NFA_HCI_SESSION_ID_LEN) ) |
| { |
| /* Session has not changed. Set the WHITELIST */ |
| nfa_hciu_send_set_param_cmd (NFA_HCI_ADMIN_PIPE, NFA_HCI_WHITELIST_INDEX, 0x02, hosts); |
| } |
| else |
| { |
| /* Something wrong, NVRAM data could be corrupt or first start with default session id */ |
| nfa_hciu_send_clear_all_pipe_cmd (); |
| nfa_hci_cb.b_hci_netwk_reset = TRUE; |
| } |
| } |
| break; |
| |
| case NFA_HCI_ANY_OPEN_PIPE: |
| nfa_hci_cb.cfg.admin_gate.pipe01_state = NFA_HCI_PIPE_OPENED; |
| |
| if (nfa_hci_cb.b_hci_netwk_reset) |
| { |
| nfa_hci_cb.b_hci_netwk_reset = FALSE; |
| /* Session ID is reset, Set New session id */ |
| memcpy (&nfa_hci_cb.cfg.admin_gate.session_id[NFA_HCI_SESSION_ID_LEN / 2], nfa_hci_cb.cfg.admin_gate.session_id, (NFA_HCI_SESSION_ID_LEN / 2)); |
| os_tick = GKI_get_os_tick_count (); |
| memcpy (nfa_hci_cb.cfg.admin_gate.session_id, (UINT8 *)&os_tick, (NFA_HCI_SESSION_ID_LEN / 2)); |
| nfa_hciu_send_set_param_cmd (NFA_HCI_ADMIN_PIPE, NFA_HCI_SESSION_IDENTITY_INDEX, NFA_HCI_SESSION_ID_LEN, (UINT8 *) nfa_hci_cb.cfg.admin_gate.session_id); |
| } |
| else |
| { |
| /* First thing is to get the session ID */ |
| nfa_hciu_send_get_param_cmd (NFA_HCI_ADMIN_PIPE, NFA_HCI_SESSION_IDENTITY_INDEX); |
| } |
| break; |
| |
| case NFA_HCI_ADM_CLEAR_ALL_PIPE: |
| nfa_hciu_remove_all_pipes_from_host (0); |
| nfa_hci_cb.cfg.admin_gate.pipe01_state = NFA_HCI_PIPE_CLOSED; |
| nfa_hci_cb.cfg.link_mgmt_gate.pipe00_state = NFA_HCI_PIPE_CLOSED; |
| nfa_hci_cb.nv_write_needed = TRUE; |
| |
| /* Open admin */ |
| nfa_hciu_send_open_pipe_cmd (NFA_HCI_ADMIN_PIPE); |
| break; |
| } |
| } |
| else |
| { |
| status = (nfa_hci_cb.inst == NFA_HCI_ANY_OK) ? NFA_STATUS_OK : NFA_STATUS_FAILED; |
| |
| switch (nfa_hci_cb.cmd_sent) |
| { |
| case NFA_HCI_ANY_SET_PARAMETER: |
| if (nfa_hci_cb.hci_state == NFA_HCI_STATE_APP_DEREGISTER) |
| nfa_hci_api_deregister (NULL); |
| else if (nfa_hci_cb.hci_state == NFA_HCI_STATE_REMOVE_GATE) |
| nfa_hci_api_dealloc_gate (NULL); |
| break; |
| |
| case NFA_HCI_ANY_GET_PARAMETER: |
| if (nfa_hci_cb.param_in_use == NFA_HCI_SESSION_IDENTITY_INDEX) |
| { |
| if (!memcmp ((UINT8 *) default_session, p_data , NFA_HCI_SESSION_ID_LEN)) |
| { |
| memcpy (&nfa_hci_cb.cfg.admin_gate.session_id[(NFA_HCI_SESSION_ID_LEN / 2)], nfa_hci_cb.cfg.admin_gate.session_id, (NFA_HCI_SESSION_ID_LEN / 2)); |
| os_tick = GKI_get_os_tick_count (); |
| memcpy (nfa_hci_cb.cfg.admin_gate.session_id, (UINT8 *) &os_tick, (NFA_HCI_SESSION_ID_LEN / 2)); |
| nfa_hci_cb.nv_write_needed = TRUE; |
| nfa_hciu_send_set_param_cmd (NFA_HCI_ADMIN_PIPE, NFA_HCI_SESSION_IDENTITY_INDEX, NFA_HCI_SESSION_ID_LEN, (UINT8 *) nfa_hci_cb.cfg.admin_gate.session_id); |
| } |
| else |
| { |
| if (nfa_hci_cb.hci_state == NFA_HCI_STATE_APP_DEREGISTER) |
| nfa_hci_api_deregister (NULL); |
| else if (nfa_hci_cb.hci_state == NFA_HCI_STATE_REMOVE_GATE) |
| nfa_hci_api_dealloc_gate (NULL); |
| } |
| } |
| else if (nfa_hci_cb.param_in_use == NFA_HCI_HOST_LIST_INDEX) |
| { |
| evt_data.hosts.status = status; |
| evt_data.hosts.num_hosts = data_len; |
| memcpy (evt_data.hosts.host, p_data, data_len); |
| |
| host_count = 0; |
| while (host_count < NFA_HCI_MAX_HOST_IN_NETWORK) |
| { |
| nfa_hci_cb.inactive_host[host_count] = NFA_HCI_HOST_ID_UICC0 + host_count; |
| host_count++; |
| } |
| |
| host_count = 0; |
| /* Collect active host in the Host Network */ |
| while (host_count < data_len) |
| { |
| host_id = (UINT8) *p_data++; |
| |
| if ( (host_id >= NFA_HCI_HOST_ID_UICC0) |
| &&(host_id < NFA_HCI_HOST_ID_UICC0 + NFA_HCI_MAX_HOST_IN_NETWORK) ) |
| { |
| nfa_hci_cb.inactive_host[host_id - NFA_HCI_HOST_ID_UICC0] = 0x00; |
| nfa_hci_cb.reset_host[host_id - NFA_HCI_HOST_ID_UICC0] = 0x00; |
| } |
| host_count++; |
| } |
| if (nfa_hciu_is_no_host_resetting ()) |
| nfa_hci_check_pending_api_requests (); |
| nfa_hciu_send_to_app (NFA_HCI_HOST_LIST_EVT, &evt_data, nfa_hci_cb.app_in_use); |
| } |
| break; |
| |
| case NFA_HCI_ADM_CREATE_PIPE: |
| if (status == NFA_STATUS_OK) |
| { |
| STREAM_TO_UINT8 (source_host, p_data); |
| STREAM_TO_UINT8 (source_gate, p_data); |
| STREAM_TO_UINT8 (dest_host, p_data); |
| STREAM_TO_UINT8 (dest_gate, p_data); |
| STREAM_TO_UINT8 (pipe, p_data); |
| |
| /* Sanity check */ |
| if (source_gate != nfa_hci_cb.local_gate_in_use) |
| { |
| NFA_TRACE_WARNING2 ("nfa_hci_handle_admin_gate_rsp sent create pipe with gate: %u got back: %u", |
| nfa_hci_cb.local_gate_in_use, source_gate); |
| break; |
| } |
| |
| nfa_hciu_add_pipe_to_gate (pipe, source_gate, dest_host, dest_gate); |
| |
| } |
| |
| /* Tell the application his pipe was created or not */ |
| evt_data.created.status = status; |
| evt_data.created.pipe = pipe; |
| evt_data.created.source_gate = source_gate; |
| evt_data.created.dest_host = dest_host; |
| evt_data.created.dest_gate = dest_gate; |
| |
| nfa_hciu_send_to_app (NFA_HCI_CREATE_PIPE_EVT, &evt_data, nfa_hci_cb.app_in_use); |
| break; |
| |
| case NFA_HCI_ADM_DELETE_PIPE: |
| if (status == NFA_STATUS_OK) |
| { |
| nfa_hciu_release_pipe (nfa_hci_cb.pipe_in_use); |
| |
| /* If only deleting one pipe, tell the app we are done */ |
| if (nfa_hci_cb.hci_state == NFA_HCI_STATE_IDLE) |
| { |
| evt_data.deleted.status = status; |
| evt_data.deleted.pipe = nfa_hci_cb.pipe_in_use; |
| |
| nfa_hciu_send_to_app (NFA_HCI_DELETE_PIPE_EVT, &evt_data, nfa_hci_cb.app_in_use); |
| } |
| else if (nfa_hci_cb.hci_state == NFA_HCI_STATE_APP_DEREGISTER) |
| nfa_hci_api_deregister (NULL); |
| else if (nfa_hci_cb.hci_state == NFA_HCI_STATE_REMOVE_GATE) |
| nfa_hci_api_dealloc_gate (NULL); |
| } |
| else |
| { |
| /* If only deleting one pipe, tell the app we are done */ |
| if (nfa_hci_cb.hci_state == NFA_HCI_STATE_IDLE) |
| { |
| evt_data.deleted.status = status; |
| evt_data.deleted.pipe = nfa_hci_cb.pipe_in_use; |
| |
| nfa_hciu_send_to_app (NFA_HCI_DELETE_PIPE_EVT, &evt_data, nfa_hci_cb.app_in_use); |
| } |
| else if (nfa_hci_cb.hci_state == NFA_HCI_STATE_APP_DEREGISTER) |
| { |
| nfa_hciu_release_pipe (nfa_hci_cb.pipe_in_use); |
| nfa_hci_api_deregister (NULL); |
| } |
| else if (nfa_hci_cb.hci_state == NFA_HCI_STATE_REMOVE_GATE) |
| { |
| nfa_hciu_release_pipe (nfa_hci_cb.pipe_in_use); |
| nfa_hci_api_dealloc_gate (NULL); |
| } |
| } |
| break; |
| |
| case NFA_HCI_ANY_OPEN_PIPE: |
| nfa_hci_cb.cfg.admin_gate.pipe01_state = status ? NFA_HCI_PIPE_CLOSED:NFA_HCI_PIPE_OPENED; |
| nfa_hci_cb.nv_write_needed = TRUE; |
| if (nfa_hci_cb.cfg.admin_gate.pipe01_state == NFA_HCI_PIPE_OPENED) |
| { |
| /* First thing is to get the session ID */ |
| nfa_hciu_send_get_param_cmd (NFA_HCI_ADMIN_PIPE, NFA_HCI_SESSION_IDENTITY_INDEX); |
| } |
| break; |
| |
| case NFA_HCI_ADM_CLEAR_ALL_PIPE: |
| nfa_hciu_remove_all_pipes_from_host (0); |
| nfa_hci_cb.cfg.admin_gate.pipe01_state = NFA_HCI_PIPE_CLOSED; |
| nfa_hci_cb.cfg.link_mgmt_gate.pipe00_state = NFA_HCI_PIPE_CLOSED; |
| nfa_hci_cb.nv_write_needed = TRUE; |
| /* Open admin */ |
| nfa_hciu_send_open_pipe_cmd (NFA_HCI_ADMIN_PIPE); |
| break; |
| |
| } |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_handle_admin_gate_evt |
| ** |
| ** Description This function handles events received on admin gate |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| void nfa_hci_handle_admin_gate_evt (UINT8 *p_data) |
| { |
| tNFA_HCI_EVT_DATA evt_data; |
| tNFA_HCI_API_GET_HOST_LIST *p_msg; |
| |
| if (nfa_hci_cb.inst != NFA_HCI_EVT_HOT_PLUG) |
| { |
| NFA_TRACE_ERROR0 ("nfa_hci_handle_admin_gate_evt - Unknown event on ADMIN Pipe"); |
| return; |
| } |
| |
| NFA_TRACE_DEBUG0 ("nfa_hci_handle_admin_gate_evt - HOT PLUG EVT event on ADMIN Pipe"); |
| nfa_hci_cb.num_hot_plug_evts++; |
| |
| if ( (nfa_hci_cb.hci_state == NFA_HCI_STATE_WAIT_NETWK_ENABLE) |
| ||(nfa_hci_cb.hci_state == NFA_HCI_STATE_RESTORE_NETWK_ENABLE) ) |
| { |
| /* Received Hot Plug evt while waiting for other Host in the network to bootup after DH host bootup is complete */ |
| if ( (nfa_hci_cb.ee_disable_disc) |
| &&(nfa_hci_cb.num_hot_plug_evts == (nfa_hci_cb.num_nfcee - 1)) |
| &&(nfa_hci_cb.num_ee_dis_req_ntf < (nfa_hci_cb.num_nfcee - 1)) ) |
| { |
| /* Received expected number of Hot Plug event(s) before as many number of EE DISC REQ Ntf(s) are received */ |
| nfa_sys_stop_timer (&nfa_hci_cb.timer); |
| /* Received HOT PLUG EVT(s), now wait some more time for EE DISC REQ Ntf(s) */ |
| nfa_sys_start_timer (&nfa_hci_cb.timer, NFA_HCI_RSP_TIMEOUT_EVT, p_nfa_hci_cfg->hci_netwk_enable_timeout); |
| } |
| } |
| else if ( (nfa_hci_cb.hci_state == NFA_HCI_STATE_STARTUP) |
| ||(nfa_hci_cb.hci_state == NFA_HCI_STATE_RESTORE) ) |
| { |
| /* Received Hot Plug evt during DH host bootup */ |
| if ( (nfa_hci_cb.ee_disable_disc) |
| &&(nfa_hci_cb.num_hot_plug_evts == (nfa_hci_cb.num_nfcee - 1)) |
| &&(nfa_hci_cb.num_ee_dis_req_ntf < (nfa_hci_cb.num_nfcee - 1)) ) |
| { |
| /* Received expected number of Hot Plug event(s) before as many number of EE DISC REQ Ntf(s) are received */ |
| nfa_hci_cb.w4_hci_netwk_init = FALSE; |
| } |
| } |
| else |
| { |
| /* Received Hot Plug evt on UICC self reset */ |
| evt_data.rcvd_evt.evt_code = nfa_hci_cb.inst; |
| /* Notify all registered application with the HOT_PLUG_EVT */ |
| nfa_hciu_send_to_all_apps (NFA_HCI_EVENT_RCVD_EVT, &evt_data); |
| |
| /* Send Get Host List after receiving any pending response */ |
| if ((p_msg = (tNFA_HCI_API_GET_HOST_LIST *) GKI_getbuf (sizeof (tNFA_HCI_API_GET_HOST_LIST))) != NULL) |
| { |
| p_msg->hdr.event = NFA_HCI_API_GET_HOST_LIST_EVT; |
| /* Set Invalid handle to identify this Get Host List command is internal */ |
| p_msg->hci_handle = NFA_HANDLE_INVALID; |
| |
| nfa_sys_sendmsg (p_msg); |
| } |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_handle_dyn_pipe_pkt |
| ** |
| ** Description This function handles data received via dynamic pipe |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| void nfa_hci_handle_dyn_pipe_pkt (UINT8 pipe_id, UINT8 *p_data, UINT16 data_len) |
| { |
| tNFA_HCI_DYN_PIPE *p_pipe = nfa_hciu_find_pipe_by_pid (pipe_id); |
| tNFA_HCI_DYN_GATE *p_gate; |
| |
| if (p_pipe == NULL) |
| { |
| /* Invalid pipe ID */ |
| NFA_TRACE_ERROR1 ("nfa_hci_handle_dyn_pipe_pkt - Unknown pipe %d",pipe_id); |
| if (nfa_hci_cb.type == NFA_HCI_COMMAND_TYPE) |
| nfa_hciu_send_msg (pipe_id, NFA_HCI_RESPONSE_TYPE, NFA_HCI_ANY_E_NOK, 0, NULL); |
| return; |
| } |
| |
| if (p_pipe->local_gate == NFA_HCI_IDENTITY_MANAGEMENT_GATE) |
| { |
| nfa_hci_handle_identity_mgmt_gate_pkt (p_data, p_pipe); |
| } |
| else if (p_pipe->local_gate == NFA_HCI_LOOP_BACK_GATE) |
| { |
| nfa_hci_handle_loopback_gate_pkt (p_data, data_len, p_pipe); |
| } |
| else if (p_pipe->local_gate == NFA_HCI_CONNECTIVITY_GATE) |
| { |
| nfa_hci_handle_connectivity_gate_pkt (p_data, data_len, p_pipe); |
| } |
| else |
| { |
| p_gate = nfa_hciu_find_gate_by_gid (p_pipe->local_gate); |
| if (p_gate == NULL) |
| { |
| NFA_TRACE_ERROR1 ("nfa_hci_handle_dyn_pipe_pkt - Pipe's gate %d is corrupt",p_pipe->local_gate); |
| if (nfa_hci_cb.type == NFA_HCI_COMMAND_TYPE) |
| nfa_hciu_send_msg (pipe_id, NFA_HCI_RESPONSE_TYPE, NFA_HCI_ANY_E_NOK, 0, NULL); |
| return; |
| } |
| |
| /* Check if data packet is a command, response or event */ |
| switch (nfa_hci_cb.type) |
| { |
| case NFA_HCI_COMMAND_TYPE: |
| nfa_hci_handle_generic_gate_cmd (p_data, (UINT8) data_len, p_gate, p_pipe); |
| break; |
| |
| case NFA_HCI_RESPONSE_TYPE: |
| nfa_hci_handle_generic_gate_rsp (p_data, (UINT8) data_len, p_gate, p_pipe); |
| break; |
| |
| case NFA_HCI_EVENT_TYPE: |
| nfa_hci_handle_generic_gate_evt (p_data, data_len, p_gate, p_pipe); |
| break; |
| } |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_handle_identity_mgmt_gate_pkt |
| ** |
| ** Description This function handles incoming Identity Management gate hci |
| ** commands |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| static void nfa_hci_handle_identity_mgmt_gate_pkt (UINT8 *p_data, tNFA_HCI_DYN_PIPE *p_pipe) |
| { |
| UINT8 data[20]; |
| UINT8 index; |
| UINT8 gate_rsp[3 + NFA_HCI_MAX_GATE_CB], num_gates; |
| UINT16 rsp_len = 0; |
| UINT8 *p_rsp = data; |
| tNFA_HCI_RESPONSE response = NFA_HCI_ANY_OK; |
| |
| /* We never send commands on a pipe where the local gate is the identity management |
| * gate, so only commands should be processed. |
| */ |
| if (nfa_hci_cb.type != NFA_HCI_COMMAND_TYPE) |
| return; |
| |
| switch (nfa_hci_cb.inst) |
| { |
| case NFA_HCI_ANY_GET_PARAMETER: |
| index = *(p_data++); |
| if (p_pipe->pipe_state == NFA_HCI_PIPE_OPENED) |
| { |
| switch (index) |
| { |
| case NFA_HCI_VERSION_SW_INDEX: |
| data[0] = (UINT8) ((NFA_HCI_VERSION_SW >> 16 ) & 0xFF); |
| data[1] = (UINT8) ((NFA_HCI_VERSION_SW >> 8 ) & 0xFF); |
| data[2] = (UINT8) ((NFA_HCI_VERSION_SW ) & 0xFF); |
| rsp_len = 3; |
| break; |
| |
| case NFA_HCI_HCI_VERSION_INDEX: |
| data[0] = NFA_HCI_VERSION; |
| rsp_len = 1; |
| break; |
| |
| case NFA_HCI_VERSION_HW_INDEX: |
| data[0] = (UINT8) ((NFA_HCI_VERSION_HW >> 16 ) & 0xFF); |
| data[1] = (UINT8) ((NFA_HCI_VERSION_HW >> 8 ) & 0xFF); |
| data[2] = (UINT8) ((NFA_HCI_VERSION_HW ) & 0xFF); |
| rsp_len = 3; |
| break; |
| |
| case NFA_HCI_VENDOR_NAME_INDEX: |
| memcpy (data,NFA_HCI_VENDOR_NAME,strlen (NFA_HCI_VENDOR_NAME)); |
| rsp_len = (UINT8) strlen (NFA_HCI_VENDOR_NAME); |
| break; |
| |
| case NFA_HCI_MODEL_ID_INDEX: |
| data[0] = NFA_HCI_MODEL_ID; |
| rsp_len = 1; |
| break; |
| |
| case NFA_HCI_GATES_LIST_INDEX: |
| gate_rsp[0] = NFA_HCI_LOOP_BACK_GATE; |
| gate_rsp[1] = NFA_HCI_IDENTITY_MANAGEMENT_GATE; |
| gate_rsp[2] = NFA_HCI_CONNECTIVITY_GATE; |
| num_gates = nfa_hciu_get_allocated_gate_list (&gate_rsp[3]); |
| rsp_len = num_gates + 3; |
| p_rsp = gate_rsp; |
| break; |
| |
| default: |
| response = NFA_HCI_ANY_E_NOK; |
| break; |
| } |
| } |
| else |
| { |
| response = NFA_HCI_ANY_E_PIPE_NOT_OPENED; |
| } |
| break; |
| |
| case NFA_HCI_ANY_OPEN_PIPE: |
| data[0] = 0; |
| rsp_len = 1; |
| p_pipe->pipe_state = NFA_HCI_PIPE_OPENED; |
| break; |
| |
| case NFA_HCI_ANY_CLOSE_PIPE: |
| p_pipe->pipe_state = NFA_HCI_PIPE_CLOSED; |
| break; |
| |
| default: |
| response = NFA_HCI_ANY_E_CMD_NOT_SUPPORTED; |
| break; |
| } |
| |
| nfa_hciu_send_msg (p_pipe->pipe_id, NFA_HCI_RESPONSE_TYPE, response, rsp_len, p_rsp); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_handle_generic_gate_cmd |
| ** |
| ** Description This function handles all generic gates (excluding |
| ** connectivity gate) commands |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| static void nfa_hci_handle_generic_gate_cmd (UINT8 *p_data, UINT8 data_len, tNFA_HCI_DYN_GATE *p_gate, tNFA_HCI_DYN_PIPE *p_pipe) |
| { |
| tNFA_HCI_EVT_DATA evt_data; |
| tNFA_HANDLE app_handle = nfa_hciu_get_pipe_owner (p_pipe->pipe_id); |
| |
| switch (nfa_hci_cb.inst) |
| { |
| case NFA_HCI_ANY_SET_PARAMETER: |
| evt_data.registry.pipe = p_pipe->pipe_id; |
| evt_data.registry.index = *p_data++; |
| if (data_len > 0) |
| data_len--; |
| evt_data.registry.data_len = data_len; |
| |
| memcpy (evt_data.registry.reg_data, p_data, data_len); |
| |
| nfa_hciu_send_to_app (NFA_HCI_SET_REG_CMD_EVT, &evt_data, app_handle); |
| break; |
| |
| case NFA_HCI_ANY_GET_PARAMETER: |
| evt_data.registry.pipe = p_pipe->pipe_id; |
| evt_data.registry.index = *p_data; |
| evt_data.registry.data_len = 0; |
| |
| nfa_hciu_send_to_app (NFA_HCI_GET_REG_CMD_EVT, &evt_data, app_handle); |
| break; |
| |
| case NFA_HCI_ANY_OPEN_PIPE: |
| nfa_hci_handle_pipe_open_close_cmd (p_pipe); |
| |
| evt_data.opened.pipe = p_pipe->pipe_id; |
| evt_data.opened.status = NFA_STATUS_OK; |
| |
| nfa_hciu_send_to_app (NFA_HCI_OPEN_PIPE_EVT, &evt_data, app_handle); |
| break; |
| |
| case NFA_HCI_ANY_CLOSE_PIPE: |
| nfa_hci_handle_pipe_open_close_cmd (p_pipe); |
| |
| evt_data.closed.pipe = p_pipe->pipe_id; |
| evt_data.opened.status = NFA_STATUS_OK; |
| |
| nfa_hciu_send_to_app (NFA_HCI_CLOSE_PIPE_EVT, &evt_data, app_handle); |
| break; |
| |
| default: |
| /* Could be application specific command, pass it on */ |
| evt_data.cmd_rcvd.status = NFA_STATUS_OK; |
| evt_data.cmd_rcvd.pipe = p_pipe->pipe_id;; |
| evt_data.cmd_rcvd.cmd_code = nfa_hci_cb.inst; |
| evt_data.cmd_rcvd.cmd_len = data_len; |
| |
| if (data_len <= NFA_MAX_HCI_CMD_LEN) |
| memcpy (evt_data.cmd_rcvd.cmd_data, p_data, data_len); |
| |
| nfa_hciu_send_to_app (NFA_HCI_CMD_RCVD_EVT, &evt_data, app_handle); |
| break; |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_handle_generic_gate_rsp |
| ** |
| ** Description This function handles all generic gates (excluding |
| ** connectivity) response |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| static void nfa_hci_handle_generic_gate_rsp (UINT8 *p_data, UINT8 data_len, tNFA_HCI_DYN_GATE *p_gate, tNFA_HCI_DYN_PIPE *p_pipe) |
| { |
| tNFA_HCI_EVT_DATA evt_data; |
| tNFA_STATUS status = NFA_STATUS_OK; |
| |
| if (nfa_hci_cb.inst != NFA_HCI_ANY_OK) |
| status = NFA_STATUS_FAILED; |
| |
| if (nfa_hci_cb.cmd_sent == NFA_HCI_ANY_OPEN_PIPE) |
| { |
| if (status == NFA_STATUS_OK) |
| p_pipe->pipe_state = NFA_HCI_PIPE_OPENED; |
| |
| nfa_hci_cb.nv_write_needed = TRUE; |
| /* Tell application */ |
| evt_data.opened.status = status; |
| evt_data.opened.pipe = p_pipe->pipe_id; |
| |
| nfa_hciu_send_to_app (NFA_HCI_OPEN_PIPE_EVT, &evt_data, nfa_hci_cb.app_in_use); |
| } |
| else if (nfa_hci_cb.cmd_sent == NFA_HCI_ANY_CLOSE_PIPE) |
| { |
| p_pipe->pipe_state = NFA_HCI_PIPE_CLOSED; |
| |
| nfa_hci_cb.nv_write_needed = TRUE; |
| /* Tell application */ |
| evt_data.opened.status = status;; |
| evt_data.opened.pipe = p_pipe->pipe_id; |
| |
| nfa_hciu_send_to_app (NFA_HCI_CLOSE_PIPE_EVT, &evt_data, nfa_hci_cb.app_in_use); |
| } |
| else if (nfa_hci_cb.cmd_sent == NFA_HCI_ANY_GET_PARAMETER) |
| { |
| /* Tell application */ |
| evt_data.registry.status = status; |
| evt_data.registry.pipe = p_pipe->pipe_id; |
| evt_data.registry.data_len = data_len; |
| evt_data.registry.index = nfa_hci_cb.param_in_use; |
| |
| memcpy (evt_data.registry.reg_data, p_data, data_len); |
| |
| nfa_hciu_send_to_app (NFA_HCI_GET_REG_RSP_EVT, &evt_data, nfa_hci_cb.app_in_use); |
| } |
| else if (nfa_hci_cb.cmd_sent == NFA_HCI_ANY_SET_PARAMETER) |
| { |
| /* Tell application */ |
| evt_data.registry.status = status;; |
| evt_data.registry.pipe = p_pipe->pipe_id; |
| |
| nfa_hciu_send_to_app (NFA_HCI_SET_REG_RSP_EVT, &evt_data, nfa_hci_cb.app_in_use); |
| } |
| else |
| { |
| /* Could be a response to application specific command sent, pass it on */ |
| evt_data.rsp_rcvd.status = NFA_STATUS_OK; |
| evt_data.rsp_rcvd.pipe = p_pipe->pipe_id;; |
| evt_data.rsp_rcvd.rsp_code = nfa_hci_cb.inst; |
| evt_data.rsp_rcvd.rsp_len = data_len; |
| |
| if (data_len <= NFA_MAX_HCI_RSP_LEN) |
| memcpy (evt_data.rsp_rcvd.rsp_data, p_data, data_len); |
| |
| nfa_hciu_send_to_app (NFA_HCI_RSP_RCVD_EVT, &evt_data, nfa_hci_cb.app_in_use); |
| } |
| |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_handle_connectivity_gate_pkt |
| ** |
| ** Description This function handles incoming connectivity gate packets |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| static void nfa_hci_handle_connectivity_gate_pkt (UINT8 *p_data, UINT16 data_len, tNFA_HCI_DYN_PIPE *p_pipe) |
| { |
| tNFA_HCI_EVT_DATA evt_data; |
| |
| if (nfa_hci_cb.type == NFA_HCI_COMMAND_TYPE) |
| { |
| switch (nfa_hci_cb.inst) |
| { |
| case NFA_HCI_ANY_OPEN_PIPE: |
| case NFA_HCI_ANY_CLOSE_PIPE: |
| nfa_hci_handle_pipe_open_close_cmd (p_pipe); |
| break; |
| |
| case NFA_HCI_CON_PRO_HOST_REQUEST: |
| /* A request to the DH to activate another host. This is not supported for */ |
| /* now, we will implement it when the spec is clearer and UICCs need it. */ |
| nfa_hciu_send_msg (p_pipe->pipe_id, NFA_HCI_RESPONSE_TYPE, NFA_HCI_ANY_E_CMD_NOT_SUPPORTED, 0, NULL); |
| break; |
| |
| default: |
| nfa_hciu_send_msg (p_pipe->pipe_id, NFA_HCI_RESPONSE_TYPE, NFA_HCI_ANY_E_CMD_NOT_SUPPORTED, 0, NULL); |
| break; |
| } |
| } |
| else if (nfa_hci_cb.type == NFA_HCI_RESPONSE_TYPE) |
| { |
| if ((nfa_hci_cb.cmd_sent == NFA_HCI_ANY_OPEN_PIPE) && (nfa_hci_cb.inst == NFA_HCI_ANY_OK)) |
| p_pipe->pipe_state = NFA_HCI_PIPE_OPENED; |
| else if (nfa_hci_cb.cmd_sent == NFA_HCI_ANY_CLOSE_PIPE) |
| p_pipe->pipe_state = NFA_HCI_PIPE_CLOSED; |
| |
| /* Could be a response to application specific command sent, pass it on */ |
| evt_data.rsp_rcvd.status = NFA_STATUS_OK; |
| evt_data.rsp_rcvd.pipe = p_pipe->pipe_id;; |
| evt_data.rsp_rcvd.rsp_code = nfa_hci_cb.inst; |
| evt_data.rsp_rcvd.rsp_len = data_len; |
| |
| if (data_len <= NFA_MAX_HCI_RSP_LEN) |
| memcpy (evt_data.rsp_rcvd.rsp_data, p_data, data_len); |
| |
| nfa_hciu_send_to_app (NFA_HCI_RSP_RCVD_EVT, &evt_data, nfa_hci_cb.app_in_use); |
| } |
| else if (nfa_hci_cb.type == NFA_HCI_EVENT_TYPE) |
| { |
| evt_data.rcvd_evt.pipe = p_pipe->pipe_id; |
| evt_data.rcvd_evt.evt_code = nfa_hci_cb.inst; |
| evt_data.rcvd_evt.evt_len = data_len; |
| evt_data.rcvd_evt.p_evt_buf = p_data; |
| |
| /* notify NFA_HCI_EVENT_RCVD_EVT to the application */ |
| nfa_hciu_send_to_apps_handling_connectivity_evts (NFA_HCI_EVENT_RCVD_EVT, &evt_data); |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_handle_loopback_gate_pkt |
| ** |
| ** Description This function handles incoming loopback gate hci events |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| static void nfa_hci_handle_loopback_gate_pkt (UINT8 *p_data, UINT16 data_len, tNFA_HCI_DYN_PIPE *p_pipe) |
| { |
| UINT8 data[1]; |
| UINT8 rsp_len = 0; |
| tNFA_HCI_RESPONSE response = NFA_HCI_ANY_OK; |
| tNFA_HCI_EVT_DATA evt_data; |
| |
| /* Check if data packet is a command, response or event */ |
| if (nfa_hci_cb.type == NFA_HCI_COMMAND_TYPE) |
| { |
| if (nfa_hci_cb.inst == NFA_HCI_ANY_OPEN_PIPE) |
| { |
| data[0] = 0; |
| rsp_len = 1; |
| p_pipe->pipe_state = NFA_HCI_PIPE_OPENED; |
| } |
| else if (nfa_hci_cb.inst == NFA_HCI_ANY_CLOSE_PIPE) |
| { |
| p_pipe->pipe_state = NFA_HCI_PIPE_CLOSED; |
| } |
| else |
| response = NFA_HCI_ANY_E_CMD_NOT_SUPPORTED; |
| |
| nfa_hciu_send_msg (p_pipe->pipe_id, NFA_HCI_RESPONSE_TYPE, response, rsp_len, data); |
| } |
| else if (nfa_hci_cb.type == NFA_HCI_RESPONSE_TYPE) |
| { |
| if ((nfa_hci_cb.cmd_sent == NFA_HCI_ANY_OPEN_PIPE) && (nfa_hci_cb.inst == NFA_HCI_ANY_OK)) |
| p_pipe->pipe_state = NFA_HCI_PIPE_OPENED; |
| else if (nfa_hci_cb.cmd_sent == NFA_HCI_ANY_CLOSE_PIPE) |
| p_pipe->pipe_state = NFA_HCI_PIPE_CLOSED; |
| |
| /* Could be a response to application specific command sent, pass it on */ |
| evt_data.rsp_rcvd.status = NFA_STATUS_OK; |
| evt_data.rsp_rcvd.pipe = p_pipe->pipe_id;; |
| evt_data.rsp_rcvd.rsp_code = nfa_hci_cb.inst; |
| evt_data.rsp_rcvd.rsp_len = data_len; |
| |
| if (data_len <= NFA_MAX_HCI_RSP_LEN) |
| memcpy (evt_data.rsp_rcvd.rsp_data, p_data, data_len); |
| |
| nfa_hciu_send_to_app (NFA_HCI_RSP_RCVD_EVT, &evt_data, nfa_hci_cb.app_in_use); |
| } |
| else if (nfa_hci_cb.type == NFA_HCI_EVENT_TYPE) |
| { |
| if (nfa_hci_cb.w4_rsp_evt) |
| { |
| evt_data.rcvd_evt.pipe = p_pipe->pipe_id; |
| evt_data.rcvd_evt.evt_code = nfa_hci_cb.inst; |
| evt_data.rcvd_evt.evt_len = data_len; |
| evt_data.rcvd_evt.p_evt_buf = p_data; |
| |
| nfa_hciu_send_to_app (NFA_HCI_EVENT_RCVD_EVT, &evt_data, nfa_hci_cb.app_in_use); |
| } |
| else if (nfa_hci_cb.inst == NFA_HCI_EVT_POST_DATA) |
| { |
| /* Send back the same data we got */ |
| nfa_hciu_send_msg (p_pipe->pipe_id, NFA_HCI_EVENT_TYPE, NFA_HCI_EVT_POST_DATA, data_len, p_data); |
| } |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfa_hci_handle_generic_gate_evt |
| ** |
| ** Description This function handles incoming Generic gate hci events |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| static void nfa_hci_handle_generic_gate_evt (UINT8 *p_data, UINT16 data_len, tNFA_HCI_DYN_GATE *p_gate, tNFA_HCI_DYN_PIPE *p_pipe) |
| { |
| tNFA_HCI_EVT_DATA evt_data; |
| |
| evt_data.rcvd_evt.pipe = p_pipe->pipe_id; |
| evt_data.rcvd_evt.evt_code = nfa_hci_cb.inst; |
| evt_data.rcvd_evt.evt_len = data_len; |
| |
| if (nfa_hci_cb.assembly_failed) |
| evt_data.rcvd_evt.status = NFA_STATUS_BUFFER_FULL; |
| else |
| evt_data.rcvd_evt.status = NFA_STATUS_OK; |
| |
| evt_data.rcvd_evt.p_evt_buf = p_data; |
| nfa_hci_cb.rsp_buf_size = 0; |
| nfa_hci_cb.p_rsp_buf = NULL; |
| |
| /* notify NFA_HCI_EVENT_RCVD_EVT to the application */ |
| nfa_hciu_send_to_app (NFA_HCI_EVENT_RCVD_EVT, &evt_data, p_gate->gate_owner); |
| } |
| |