| /****************************************************************************** |
| * |
| * Copyright (C) 2010-2014 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 <android-base/stringprintf.h> |
| #include <base/logging.h> |
| #include <log/log.h> |
| |
| #include "nfa_dm_int.h" |
| #include "nfa_hci_api.h" |
| #include "nfa_hci_defs.h" |
| #include "nfa_hci_int.h" |
| |
| using android::base::StringPrintf; |
| |
| extern bool nfc_debug_enabled; |
| |
| /* 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 bool nfa_hci_api_get_reg_value(tNFA_HCI_EVENT_DATA* p_evt_data); |
| static bool nfa_hci_api_set_reg_value(tNFA_HCI_EVENT_DATA* p_evt_data); |
| static bool 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 bool nfa_hci_api_send_event(tNFA_HCI_EVENT_DATA* p_evt_data); |
| static bool 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_t* p_data, |
| tNFA_HCI_DYN_PIPE* p_pipe); |
| static void nfa_hci_handle_loopback_gate_pkt(uint8_t* p_data, uint16_t data_len, |
| tNFA_HCI_DYN_PIPE* p_pipe); |
| static void nfa_hci_handle_connectivity_gate_pkt(uint8_t* p_data, |
| uint16_t data_len, |
| tNFA_HCI_DYN_PIPE* p_pipe); |
| static void nfa_hci_handle_generic_gate_cmd(uint8_t* p_data, uint8_t data_len, |
| tNFA_HCI_DYN_PIPE* p_pipe); |
| static void nfa_hci_handle_generic_gate_rsp(uint8_t* p_data, uint8_t data_len, |
| tNFA_HCI_DYN_PIPE* p_pipe); |
| static void nfa_hci_handle_generic_gate_evt(uint8_t* p_data, uint16_t 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) { |
| NFC_HDR* p_msg; |
| tNFA_HCI_EVENT_DATA* p_evt_data; |
| bool b_free; |
| |
| /* If busy, or API queue is empty, then exit */ |
| if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_IDLE) || |
| ((p_msg = (NFC_HDR*)GKI_dequeue(&nfa_hci_cb.hci_host_reset_api_q)) == |
| nullptr)) |
| 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) { |
| NFC_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 = (NFC_HDR*)GKI_dequeue(&nfa_hci_cb.hci_api_q)) == nullptr)) |
| 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: |
| LOG(ERROR) << StringPrintf("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_t 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))) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "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])); |
| strncpy(&nfa_hci_cb.cfg.reg_app_names[xx][0], p_app_name, |
| NFA_MAX_HCI_APP_NAME_LEN); |
| nfa_hci_cb.nv_write_needed = true; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "nfa_hci_api_register (%s) Allocated: %u", p_app_name, xx); |
| break; |
| } |
| } |
| |
| if (xx == NFA_HCI_MAX_APP_CB) { |
| LOG(ERROR) << StringPrintf("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 = nullptr; |
| 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 != nullptr) { |
| 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))) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("nfa_hci_api_deregister (%s) inx: %u", |
| p_evt_data->app_info.app_name, xx); |
| break; |
| } |
| } |
| |
| if (xx == NFA_HCI_MAX_APP_CB) { |
| LOG(WARNING) << StringPrintf("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) == nullptr) { |
| /* No pipes, release all gates owned by this app */ |
| while ((p_gate = nfa_hciu_find_gate_by_owner(nfa_hci_cb.app_in_use)) != |
| nullptr) |
| 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] = nullptr; |
| |
| 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)) == nullptr) { |
| /* 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)) != nullptr) |
| nfa_hciu_release_gate(p_gate->gate_id); |
| |
| nfa_hci_cb.p_app_cback[nfa_hci_cb.app_in_use & NFA_HANDLE_MASK] = nullptr; |
| |
| 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)); |
| } else if (pp->pipe_id >= NFA_HCI_FIRST_DYNAMIC_PIPE && |
| pp->pipe_id <= NFA_HCI_LAST_DYNAMIC_PIPE && pp->pipe_id && |
| pp->local_gate >= NFA_HCI_FIRST_PROP_GATE && |
| pp->local_gate <= NFA_HCI_LAST_PROP_GATE) { |
| for (yy = 0, pg = nfa_hci_cb.cfg.dyn_gates; yy < NFA_HCI_MAX_GATE_CB; |
| yy++, pg++) { |
| if (pp->local_gate == pg->gate_id) { |
| if (!pg->gate_owner) |
| memcpy(&evt_data.gates_pipes.uicc_created_pipe |
| [evt_data.gates_pipes.num_uicc_created_pipes++], |
| pp, sizeof(tNFA_HCI_PIPE_INFO)); |
| break; |
| } |
| } |
| } |
| } |
| |
| 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 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(p_evt_data->gate_info.gate, app_handle); |
| |
| if (p_gate) { |
| if (!p_gate->gate_owner) { |
| /* No app owns the gate yet */ |
| p_gate->gate_owner = app_handle; |
| } else if (p_gate->gate_owner != app_handle) { |
| /* Some other app owns the gate */ |
| p_gate = nullptr; |
| LOG(ERROR) << StringPrintf("The Gate (0X%02x) already taken!", |
| p_evt_data->gate_info.gate); |
| } |
| } |
| |
| 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_t 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 == nullptr) { |
| 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) == nullptr) { |
| 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)) == |
| nullptr) { |
| /* 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_t 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] != nullptr))) { |
| 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 bool 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; |
| bool report_failed = false; |
| |
| /* Verify that the app owns the gate that the pipe is being created on */ |
| if ((p_gate == nullptr) || |
| (p_gate->gate_owner != p_evt_data->create_pipe.hci_handle)) { |
| report_failed = true; |
| LOG(ERROR) << StringPrintf( |
| "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); |
| } else if (nfa_hciu_check_pipe_between_gates( |
| p_evt_data->create_pipe.source_gate, |
| p_evt_data->create_pipe.dest_host, |
| p_evt_data->create_pipe.dest_gate)) { |
| report_failed = true; |
| LOG(ERROR) << StringPrintf( |
| "nfa_hci_api_create_pipe : Cannot create multiple pipe between the " |
| "same two gates!"); |
| } |
| |
| if (report_failed) { |
| evt_data.created.source_gate = p_evt_data->create_pipe.source_gate; |
| evt_data.created.status = NFA_STATUS_FAILED; |
| |
| 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, (NFC_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 = nullptr; |
| |
| if (p_pipe != nullptr) p_gate = nfa_hciu_find_gate_by_gid(p_pipe->local_gate); |
| |
| if ((p_pipe != nullptr) && (p_gate != nullptr) && |
| (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 bool 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 != nullptr) { |
| p_gate = nfa_hciu_find_gate_by_gid(p_pipe->local_gate); |
| |
| if ((p_gate != nullptr) && (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, (NFC_HDR*)p_evt_data); |
| return false; |
| } |
| |
| if (p_pipe->pipe_state == NFA_HCI_PIPE_CLOSED) { |
| LOG(WARNING) << StringPrintf( |
| "nfa_hci_api_get_reg_value pipe:%d not open", |
| p_evt_data->get_registry.pipe); |
| } else { |
| status = nfa_hciu_send_get_param_cmd(p_evt_data->get_registry.pipe, |
| p_evt_data->get_registry.reg_inx); |
| if (status == 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 bool 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 != nullptr) { |
| p_gate = nfa_hciu_find_gate_by_gid(p_pipe->local_gate); |
| |
| if ((p_gate != nullptr) && (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, (NFC_HDR*)p_evt_data); |
| return false; |
| } |
| |
| if (p_pipe->pipe_state == NFA_HCI_PIPE_CLOSED) { |
| LOG(WARNING) << StringPrintf( |
| "nfa_hci_api_set_reg_value pipe:%d not open", |
| p_evt_data->set_registry.pipe); |
| } else { |
| 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); |
| if (status == 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 = nullptr; |
| |
| if (p_pipe != nullptr) p_gate = nfa_hciu_find_gate_by_gid(p_pipe->local_gate); |
| |
| if ((p_pipe != nullptr) && (p_gate != nullptr) && |
| (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 = nullptr; |
| |
| if (p_pipe != nullptr) { |
| p_gate = nfa_hciu_find_gate_by_gid(p_pipe->local_gate); |
| if ((p_gate != nullptr) && |
| (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 bool 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)) != nullptr) { |
| 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, (NFC_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; |
| 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); |
| if (status == NFA_STATUS_OK) return true; |
| } else { |
| LOG(WARNING) << StringPrintf("nfa_hci_api_send_cmd pipe:%d not open", |
| p_pipe->pipe_id); |
| } |
| } else { |
| LOG(WARNING) << StringPrintf( |
| "nfa_hci_api_send_cmd pipe:%d Owned by different application or " |
| "Destination host is not active", |
| p_pipe->pipe_id); |
| } |
| } else { |
| LOG(WARNING) << StringPrintf("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)) != nullptr) { |
| 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) { |
| 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); |
| if (status == NFA_STATUS_OK) return; |
| } else { |
| LOG(WARNING) << StringPrintf("nfa_hci_api_send_rsp pipe:%d not open", |
| p_pipe->pipe_id); |
| } |
| } else { |
| LOG(WARNING) << StringPrintf( |
| "nfa_hci_api_send_rsp pipe:%d Owned by different application or " |
| "Destination host is not active", |
| p_pipe->pipe_id); |
| } |
| } else { |
| LOG(WARNING) << StringPrintf("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 bool 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)) != nullptr) { |
| 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, (NFC_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 = nullptr; |
| } |
| } |
| } else { |
| LOG(WARNING) << StringPrintf("nfa_hci_api_send_event pipe:%d not open", |
| p_pipe->pipe_id); |
| } |
| } else { |
| LOG(WARNING) << StringPrintf( |
| "nfa_hci_api_send_event pipe:%d Owned by different application or " |
| "Destination host is not active", |
| p_pipe->pipe_id); |
| } |
| } else { |
| LOG(WARNING) << StringPrintf("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 */ |
| pg = nfa_hciu_alloc_gate(p_evt_data->add_static_pipe.gate, |
| p_evt_data->add_static_pipe.hci_handle); |
| if (pg != nullptr) { |
| /* 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; |
| } |
| pp = nfa_hciu_find_pipe_by_pid(p_evt_data->add_static_pipe.pipe); |
| if (pp != nullptr) { |
| /* 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_t* p_data) { |
| uint8_t index; |
| uint8_t data[2]; |
| uint8_t rsp_len = 0; |
| uint8_t 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, nullptr); |
| 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_t)((nfa_hci_cb.cfg.link_mgmt_gate.rec_errors >> 8) & 0x00FF); |
| data[1] = (uint8_t)(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_t data[1]; |
| uint8_t 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)) != nullptr) |
| 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_t* p_data) { |
| uint8_t source_host, source_gate, dest_host, dest_gate, pipe; |
| uint8_t data = 0; |
| uint8_t 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)) != nullptr) { |
| /* If the gate is valid, add the pipe to it */ |
| if (nfa_hciu_check_pipe_between_gates(dest_gate, source_host, |
| source_gate)) { |
| /* Already, there is a pipe between these two gates, so will reject |
| */ |
| response = NFA_HCI_ANY_E_NOK; |
| } else { |
| response = nfa_hciu_add_pipe_to_gate(pipe, dest_gate, source_host, |
| source_gate); |
| if (response == 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; |
| if ((dest_gate >= NFA_HCI_FIRST_PROP_GATE) && |
| (dest_gate <= NFA_HCI_LAST_PROP_GATE)) { |
| if (nfa_hciu_alloc_gate(dest_gate, 0)) |
| response = nfa_hciu_add_pipe_to_gate(pipe, dest_gate, source_host, |
| source_gate); |
| } |
| } |
| } |
| 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 { |
| uint8_t host_index = 0; |
| |
| if ((source_host == NFA_HCI_HOST_ID_UICC0) || |
| (source_host >= NFA_HCI_HOST_ID_FIRST_DYNAMICALLY_ALLOCATED)) { |
| while (host_index < NFA_HCI_MAX_HOST_IN_NETWORK) { |
| if (nfa_hci_cb.reset_host[host_index] == 0x0) { |
| nfa_hci_cb.reset_host[host_index] = source_host; |
| break; |
| } |
| host_index++; |
| } |
| } |
| } |
| 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_t* p_data, uint8_t data_len) { |
| uint8_t source_host; |
| uint8_t source_gate = nfa_hci_cb.local_gate_in_use; |
| uint8_t dest_host = nfa_hci_cb.remote_host_in_use; |
| uint8_t dest_gate = nfa_hci_cb.remote_gate_in_use; |
| uint8_t pipe = 0; |
| tNFA_STATUS status; |
| tNFA_HCI_EVT_DATA evt_data; |
| uint8_t default_session[NFA_HCI_SESSION_ID_LEN] = {0xFF, 0xFF, 0xFF, 0xFF, |
| 0xFF, 0xFF, 0xFF, 0xFF}; |
| uint8_t host_count = 0; |
| uint8_t host_id = 0; |
| uint32_t os_tick; |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "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).c_str(), nfa_hci_cb.app_in_use, |
| nfa_hci_cb.local_gate_in_use, nfa_hci_cb.pipe_in_use); |
| |
| /* 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_E_PIPE_NOT_OPENED) { |
| nfa_hciu_send_open_pipe_cmd(NFA_HCI_ADMIN_PIPE); |
| return; |
| } |
| |
| if (nfa_hci_cb.inst != NFA_HCI_ANY_OK) { |
| LOG(ERROR) << StringPrintf( |
| "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, |
| p_nfa_hci_cfg->num_whitelist_host, p_nfa_hci_cfg->p_whitelist); |
| } 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(); |
| if (NFA_GetNCIVersion() == NCI_VERSION_2_0) { |
| nfa_hci_cb.hci_state = NFA_HCI_STATE_WAIT_NETWK_ENABLE; |
| NFA_EeGetInfo(&nfa_hci_cb.num_nfcee, nfa_hci_cb.ee_info); |
| nfa_hci_enable_one_nfcee(); |
| } |
| } |
| break; |
| |
| case NFA_HCI_ANY_GET_PARAMETER: |
| if (nfa_hci_cb.param_in_use == NFA_HCI_HOST_LIST_INDEX) { |
| uint8_t host_index = 0; |
| |
| memset(nfa_hci_cb.active_host, 0x0, NFA_HCI_MAX_HOST_IN_NETWORK); |
| |
| host_count = 0; |
| |
| /* Collect active host in the Host Network */ |
| while ((host_count < data_len) && |
| (host_count < NFA_HCI_MAX_HOST_IN_NETWORK)) { |
| host_id = (uint8_t)*p_data++; |
| |
| if ((host_id == NFA_HCI_HOST_ID_UICC0) || |
| (host_id >= NFA_HCI_HOST_ID_FIRST_DYNAMICALLY_ALLOCATED)) { |
| nfa_hci_cb.active_host[host_index] = host_id; |
| uint8_t index = 0; |
| while (index < NFA_HCI_MAX_HOST_IN_NETWORK) { |
| if (nfa_hci_cb.reset_host[index] == host_id) { |
| nfa_hci_cb.reset_host[index] = 0x0; |
| break; |
| } |
| index++; |
| } |
| host_index++; |
| } |
| 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 (data_len >= NFA_HCI_SESSION_ID_LEN && |
| !memcmp((uint8_t*)nfa_hci_cb.cfg.admin_gate.session_id, p_data, |
| NFA_HCI_SESSION_ID_LEN)) { |
| /* Session has not changed, Set WHITELIST */ |
| nfa_hciu_send_set_param_cmd( |
| NFA_HCI_ADMIN_PIPE, NFA_HCI_WHITELIST_INDEX, |
| p_nfa_hci_cfg->num_whitelist_host, p_nfa_hci_cfg->p_whitelist); |
| } 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; |
| if (data_len < NFA_HCI_SESSION_ID_LEN) { |
| android_errorWriteLog(0x534e4554, "124524315"); |
| } |
| } |
| } |
| 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_t*)&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_t*)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(nullptr); |
| else if (nfa_hci_cb.hci_state == NFA_HCI_STATE_REMOVE_GATE) |
| nfa_hci_api_dealloc_gate(nullptr); |
| break; |
| |
| case NFA_HCI_ANY_GET_PARAMETER: |
| if (nfa_hci_cb.param_in_use == NFA_HCI_SESSION_IDENTITY_INDEX) { |
| if (data_len >= NFA_HCI_SESSION_ID_LEN && |
| !memcmp((uint8_t*)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_t*)&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_t*)nfa_hci_cb.cfg.admin_gate.session_id); |
| } else { |
| if (data_len < NFA_HCI_SESSION_ID_LEN) { |
| android_errorWriteLog(0x534e4554, "124524315"); |
| } |
| if (nfa_hci_cb.hci_state == NFA_HCI_STATE_APP_DEREGISTER) |
| nfa_hci_api_deregister(nullptr); |
| else if (nfa_hci_cb.hci_state == NFA_HCI_STATE_REMOVE_GATE) |
| nfa_hci_api_dealloc_gate(nullptr); |
| } |
| } else if (nfa_hci_cb.param_in_use == NFA_HCI_HOST_LIST_INDEX) { |
| evt_data.hosts.status = status; |
| if (data_len > NFA_HCI_MAX_HOST_IN_NETWORK) { |
| data_len = NFA_HCI_MAX_HOST_IN_NETWORK; |
| android_errorWriteLog(0x534e4554, "124524315"); |
| } |
| evt_data.hosts.num_hosts = data_len; |
| memcpy(evt_data.hosts.host, p_data, data_len); |
| |
| uint8_t host_index = 0; |
| |
| memset(nfa_hci_cb.active_host, 0x0, NFA_HCI_MAX_HOST_IN_NETWORK); |
| |
| host_count = 0; |
| /* Collect active host in the Host Network */ |
| while ((host_count < data_len) && |
| (host_count < NFA_HCI_MAX_HOST_IN_NETWORK)) { |
| host_id = (uint8_t)*p_data++; |
| |
| if ((host_id == NFA_HCI_HOST_ID_UICC0) || |
| (host_id >= NFA_HCI_HOST_ID_FIRST_DYNAMICALLY_ALLOCATED)) { |
| nfa_hci_cb.active_host[host_index] = host_id; |
| uint8_t index = 0; |
| while (index < NFA_HCI_MAX_HOST_IN_NETWORK) { |
| if (nfa_hci_cb.reset_host[index] == host_id) { |
| nfa_hci_cb.reset_host[index] = 0x0; |
| break; |
| } |
| index++; |
| } |
| host_index++; |
| } |
| 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: |
| // p_data should have at least 5 bytes length for pipe info |
| if (data_len >= 5 && 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) { |
| LOG(WARNING) << StringPrintf( |
| "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); |
| } else if (data_len < 5 && status == NFA_STATUS_OK) { |
| android_errorWriteLog(0x534e4554, "124524315"); |
| status = NFA_STATUS_FAILED; |
| } |
| |
| /* 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(nullptr); |
| else if (nfa_hci_cb.hci_state == NFA_HCI_STATE_REMOVE_GATE) |
| nfa_hci_api_dealloc_gate(nullptr); |
| } 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(nullptr); |
| } 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(nullptr); |
| } |
| } |
| 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() { |
| tNFA_HCI_EVT_DATA evt_data; |
| tNFA_HCI_API_GET_HOST_LIST* p_msg; |
| |
| if (nfa_hci_cb.inst != NFA_HCI_EVT_HOT_PLUG) { |
| LOG(ERROR) << StringPrintf( |
| "nfa_hci_handle_admin_gate_evt - Unknown event on ADMIN Pipe"); |
| return; |
| } |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "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 */ |
| p_msg = (tNFA_HCI_API_GET_HOST_LIST*)GKI_getbuf( |
| sizeof(tNFA_HCI_API_GET_HOST_LIST)); |
| if (p_msg != nullptr) { |
| 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_t pipe_id, uint8_t* p_data, |
| uint16_t 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 == nullptr) { |
| /* Invalid pipe ID */ |
| LOG(ERROR) << StringPrintf("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, |
| nullptr); |
| 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 == nullptr) { |
| LOG(ERROR) << StringPrintf( |
| "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, |
| nullptr); |
| 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_t)data_len, p_pipe); |
| break; |
| |
| case NFA_HCI_RESPONSE_TYPE: |
| nfa_hci_handle_generic_gate_rsp(p_data, (uint8_t)data_len, 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_t* p_data, |
| tNFA_HCI_DYN_PIPE* p_pipe) { |
| uint8_t data[20]; |
| uint8_t index; |
| uint8_t gate_rsp[3 + NFA_HCI_MAX_GATE_CB], num_gates; |
| uint16_t rsp_len = 0; |
| uint8_t* 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_t)((NFA_HCI_VERSION_SW >> 16) & 0xFF); |
| data[1] = (uint8_t)((NFA_HCI_VERSION_SW >> 8) & 0xFF); |
| data[2] = (uint8_t)((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_t)((NFA_HCI_VERSION_HW >> 16) & 0xFF); |
| data[1] = (uint8_t)((NFA_HCI_VERSION_HW >> 8) & 0xFF); |
| data[2] = (uint8_t)((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_t)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_t* p_data, uint8_t data_len, |
| 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_t* p_data, uint8_t data_len, |
| 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_t* p_data, |
| uint16_t 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, nullptr); |
| break; |
| |
| default: |
| nfa_hciu_send_msg(p_pipe->pipe_id, NFA_HCI_RESPONSE_TYPE, |
| NFA_HCI_ANY_E_CMD_NOT_SUPPORTED, 0, nullptr); |
| 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_t* p_data, uint16_t data_len, |
| tNFA_HCI_DYN_PIPE* p_pipe) { |
| uint8_t data[1]; |
| uint8_t 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_t* p_data, uint16_t 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 = nullptr; |
| |
| /* 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); |
| } |