Home | History | Annotate | Download | only in hci
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2010-2014 Broadcom Corporation
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19 /******************************************************************************
     20  *
     21  *  This file contains the action functions for the NFA HCI.
     22  *
     23  ******************************************************************************/
     24 #include <string.h>
     25 #include "nfa_dm_int.h"
     26 #include "nfa_hci_api.h"
     27 #include "nfa_hci_defs.h"
     28 #include "nfa_hci_int.h"
     29 #include "nfa_mem_co.h"
     30 #include "nfa_nv_co.h"
     31 #include "nfa_sys.h"
     32 #include "nfa_sys_int.h"
     33 #include "nfc_api.h"
     34 #include "trace_api.h"
     35 
     36 /* Static local functions       */
     37 static void nfa_hci_api_register(tNFA_HCI_EVENT_DATA* p_evt_data);
     38 static void nfa_hci_api_get_gate_pipe_list(tNFA_HCI_EVENT_DATA* p_evt_data);
     39 static void nfa_hci_api_alloc_gate(tNFA_HCI_EVENT_DATA* p_evt_data);
     40 static void nfa_hci_api_get_host_list(tNFA_HCI_EVENT_DATA* p_evt_data);
     41 static bool nfa_hci_api_get_reg_value(tNFA_HCI_EVENT_DATA* p_evt_data);
     42 static bool nfa_hci_api_set_reg_value(tNFA_HCI_EVENT_DATA* p_evt_data);
     43 static bool nfa_hci_api_create_pipe(tNFA_HCI_EVENT_DATA* p_evt_data);
     44 static void nfa_hci_api_open_pipe(tNFA_HCI_EVENT_DATA* p_evt_data);
     45 static void nfa_hci_api_close_pipe(tNFA_HCI_EVENT_DATA* p_evt_data);
     46 static void nfa_hci_api_delete_pipe(tNFA_HCI_EVENT_DATA* p_evt_data);
     47 static bool nfa_hci_api_send_event(tNFA_HCI_EVENT_DATA* p_evt_data);
     48 static bool nfa_hci_api_send_cmd(tNFA_HCI_EVENT_DATA* p_evt_data);
     49 static void nfa_hci_api_send_rsp(tNFA_HCI_EVENT_DATA* p_evt_data);
     50 static void nfa_hci_api_add_static_pipe(tNFA_HCI_EVENT_DATA* p_evt_data);
     51 
     52 static void nfa_hci_handle_identity_mgmt_gate_pkt(uint8_t* p_data,
     53                                                   tNFA_HCI_DYN_PIPE* p_pipe);
     54 static void nfa_hci_handle_loopback_gate_pkt(uint8_t* p_data, uint16_t data_len,
     55                                              tNFA_HCI_DYN_PIPE* p_pipe);
     56 static void nfa_hci_handle_connectivity_gate_pkt(uint8_t* p_data,
     57                                                  uint16_t data_len,
     58                                                  tNFA_HCI_DYN_PIPE* p_pipe);
     59 static void nfa_hci_handle_generic_gate_cmd(uint8_t* p_data, uint8_t data_len,
     60                                             tNFA_HCI_DYN_GATE* p_gate,
     61                                             tNFA_HCI_DYN_PIPE* p_pipe);
     62 static void nfa_hci_handle_generic_gate_rsp(uint8_t* p_data, uint8_t data_len,
     63                                             tNFA_HCI_DYN_GATE* p_gate,
     64                                             tNFA_HCI_DYN_PIPE* p_pipe);
     65 static void nfa_hci_handle_generic_gate_evt(uint8_t* p_data, uint16_t data_len,
     66                                             tNFA_HCI_DYN_GATE* p_gate,
     67                                             tNFA_HCI_DYN_PIPE* p_pipe);
     68 
     69 /*******************************************************************************
     70 **
     71 ** Function         nfa_hci_check_pending_api_requests
     72 **
     73 ** Description      This function handles pending API requests
     74 **
     75 ** Returns          none
     76 **
     77 *******************************************************************************/
     78 void nfa_hci_check_pending_api_requests(void) {
     79   NFC_HDR* p_msg;
     80   tNFA_HCI_EVENT_DATA* p_evt_data;
     81   bool b_free;
     82 
     83   /* If busy, or API queue is empty, then exit */
     84   if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_IDLE) ||
     85       ((p_msg = (NFC_HDR*)GKI_dequeue(&nfa_hci_cb.hci_host_reset_api_q)) ==
     86        NULL))
     87     return;
     88 
     89   /* Process API request */
     90   p_evt_data = (tNFA_HCI_EVENT_DATA*)p_msg;
     91 
     92   /* Save the application handle */
     93   nfa_hci_cb.app_in_use = p_evt_data->comm.hci_handle;
     94 
     95   b_free = true;
     96   switch (p_msg->event) {
     97     case NFA_HCI_API_CREATE_PIPE_EVT:
     98       if (nfa_hci_api_create_pipe(p_evt_data) == false) b_free = false;
     99       break;
    100 
    101     case NFA_HCI_API_GET_REGISTRY_EVT:
    102       if (nfa_hci_api_get_reg_value(p_evt_data) == false) b_free = false;
    103       break;
    104 
    105     case NFA_HCI_API_SET_REGISTRY_EVT:
    106       if (nfa_hci_api_set_reg_value(p_evt_data) == false) b_free = false;
    107       break;
    108 
    109     case NFA_HCI_API_SEND_CMD_EVT:
    110       if (nfa_hci_api_send_cmd(p_evt_data) == false) b_free = false;
    111       break;
    112     case NFA_HCI_API_SEND_EVENT_EVT:
    113       if (nfa_hci_api_send_event(p_evt_data) == false) b_free = false;
    114       break;
    115   }
    116 
    117   if (b_free) GKI_freebuf(p_msg);
    118 }
    119 
    120 /*******************************************************************************
    121 **
    122 ** Function         nfa_hci_check_api_requests
    123 **
    124 ** Description      This function handles API requests
    125 **
    126 ** Returns          none
    127 **
    128 *******************************************************************************/
    129 void nfa_hci_check_api_requests(void) {
    130   NFC_HDR* p_msg;
    131   tNFA_HCI_EVENT_DATA* p_evt_data;
    132 
    133   for (;;) {
    134     /* If busy, or API queue is empty, then exit */
    135     if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_IDLE) ||
    136         ((p_msg = (NFC_HDR*)GKI_dequeue(&nfa_hci_cb.hci_api_q)) == NULL))
    137       break;
    138 
    139     /* Process API request */
    140     p_evt_data = (tNFA_HCI_EVENT_DATA*)p_msg;
    141 
    142     /* Save the application handle */
    143     nfa_hci_cb.app_in_use = p_evt_data->comm.hci_handle;
    144 
    145     switch (p_msg->event) {
    146       case NFA_HCI_API_REGISTER_APP_EVT:
    147         nfa_hci_api_register(p_evt_data);
    148         break;
    149 
    150       case NFA_HCI_API_DEREGISTER_APP_EVT:
    151         nfa_hci_api_deregister(p_evt_data);
    152         break;
    153 
    154       case NFA_HCI_API_GET_APP_GATE_PIPE_EVT:
    155         nfa_hci_api_get_gate_pipe_list(p_evt_data);
    156         break;
    157 
    158       case NFA_HCI_API_ALLOC_GATE_EVT:
    159         nfa_hci_api_alloc_gate(p_evt_data);
    160         break;
    161 
    162       case NFA_HCI_API_DEALLOC_GATE_EVT:
    163         nfa_hci_api_dealloc_gate(p_evt_data);
    164         break;
    165 
    166       case NFA_HCI_API_GET_HOST_LIST_EVT:
    167         nfa_hci_api_get_host_list(p_evt_data);
    168         break;
    169 
    170       case NFA_HCI_API_GET_REGISTRY_EVT:
    171         if (nfa_hci_api_get_reg_value(p_evt_data) == false) continue;
    172         break;
    173 
    174       case NFA_HCI_API_SET_REGISTRY_EVT:
    175         if (nfa_hci_api_set_reg_value(p_evt_data) == false) continue;
    176         break;
    177 
    178       case NFA_HCI_API_CREATE_PIPE_EVT:
    179         if (nfa_hci_api_create_pipe(p_evt_data) == false) continue;
    180         break;
    181 
    182       case NFA_HCI_API_OPEN_PIPE_EVT:
    183         nfa_hci_api_open_pipe(p_evt_data);
    184         break;
    185 
    186       case NFA_HCI_API_CLOSE_PIPE_EVT:
    187         nfa_hci_api_close_pipe(p_evt_data);
    188         break;
    189 
    190       case NFA_HCI_API_DELETE_PIPE_EVT:
    191         nfa_hci_api_delete_pipe(p_evt_data);
    192         break;
    193 
    194       case NFA_HCI_API_SEND_CMD_EVT:
    195         if (nfa_hci_api_send_cmd(p_evt_data) == false) continue;
    196         break;
    197 
    198       case NFA_HCI_API_SEND_RSP_EVT:
    199         nfa_hci_api_send_rsp(p_evt_data);
    200         break;
    201 
    202       case NFA_HCI_API_SEND_EVENT_EVT:
    203         if (nfa_hci_api_send_event(p_evt_data) == false) continue;
    204         break;
    205 
    206       case NFA_HCI_API_ADD_STATIC_PIPE_EVT:
    207         nfa_hci_api_add_static_pipe(p_evt_data);
    208         break;
    209 
    210       default:
    211         NFA_TRACE_ERROR1("nfa_hci_check_api_requests ()  Unknown event: 0x%04x",
    212                          p_msg->event);
    213         break;
    214     }
    215 
    216     GKI_freebuf(p_msg);
    217   }
    218 }
    219 
    220 /*******************************************************************************
    221 **
    222 ** Function         nfa_hci_api_register
    223 **
    224 ** Description      action function to register the events for the given AID
    225 **
    226 ** Returns          None
    227 **
    228 *******************************************************************************/
    229 static void nfa_hci_api_register(tNFA_HCI_EVENT_DATA* p_evt_data) {
    230   tNFA_HCI_EVT_DATA evt_data;
    231   char* p_app_name = p_evt_data->app_info.app_name;
    232   tNFA_HCI_CBACK* p_cback = p_evt_data->app_info.p_cback;
    233   int xx, yy;
    234   uint8_t num_gates = 0, num_pipes = 0;
    235   tNFA_HCI_DYN_GATE* pg = nfa_hci_cb.cfg.dyn_gates;
    236 
    237   /* First, see if the application was already registered */
    238   for (xx = 0; xx < NFA_HCI_MAX_APP_CB; xx++) {
    239     if ((nfa_hci_cb.cfg.reg_app_names[xx][0] != 0) &&
    240         !strncmp(p_app_name, &nfa_hci_cb.cfg.reg_app_names[xx][0],
    241                  strlen(p_app_name))) {
    242       NFA_TRACE_EVENT2("nfa_hci_api_register (%s)  Reusing: %u", p_app_name,
    243                        xx);
    244       break;
    245     }
    246   }
    247 
    248   if (xx != NFA_HCI_MAX_APP_CB) {
    249     nfa_hci_cb.app_in_use = (tNFA_HANDLE)(xx | NFA_HANDLE_GROUP_HCI);
    250     /* The app was registered, find the number of gates and pipes associated to
    251      * the app */
    252 
    253     for (yy = 0; yy < NFA_HCI_MAX_GATE_CB; yy++, pg++) {
    254       if (pg->gate_owner == nfa_hci_cb.app_in_use) {
    255         num_gates++;
    256         num_pipes += nfa_hciu_count_pipes_on_gate(pg);
    257       }
    258     }
    259   } else {
    260     /* Not registered, look for a free entry */
    261     for (xx = 0; xx < NFA_HCI_MAX_APP_CB; xx++) {
    262       if (nfa_hci_cb.cfg.reg_app_names[xx][0] == 0) {
    263         memset(&nfa_hci_cb.cfg.reg_app_names[xx][0], 0,
    264                sizeof(nfa_hci_cb.cfg.reg_app_names[xx]));
    265         strncpy(&nfa_hci_cb.cfg.reg_app_names[xx][0], p_app_name,
    266                 NFA_MAX_HCI_APP_NAME_LEN);
    267         nfa_hci_cb.nv_write_needed = true;
    268         NFA_TRACE_EVENT2("nfa_hci_api_register (%s)  Allocated: %u", p_app_name,
    269                          xx);
    270         break;
    271       }
    272     }
    273 
    274     if (xx == NFA_HCI_MAX_APP_CB) {
    275       NFA_TRACE_ERROR1("nfa_hci_api_register (%s)  NO ENTRIES", p_app_name);
    276 
    277       evt_data.hci_register.status = NFA_STATUS_FAILED;
    278       p_evt_data->app_info.p_cback(NFA_HCI_REGISTER_EVT, &evt_data);
    279       return;
    280     }
    281   }
    282 
    283   evt_data.hci_register.num_pipes = num_pipes;
    284   evt_data.hci_register.num_gates = num_gates;
    285   nfa_hci_cb.p_app_cback[xx] = p_cback;
    286 
    287   nfa_hci_cb.cfg.b_send_conn_evts[xx] = p_evt_data->app_info.b_send_conn_evts;
    288 
    289   evt_data.hci_register.hci_handle = (tNFA_HANDLE)(xx | NFA_HANDLE_GROUP_HCI);
    290 
    291   evt_data.hci_register.status = NFA_STATUS_OK;
    292 
    293   /* notify NFA_HCI_REGISTER_EVT to the application */
    294   p_evt_data->app_info.p_cback(NFA_HCI_REGISTER_EVT, &evt_data);
    295 }
    296 
    297 /*******************************************************************************
    298 **
    299 ** Function         nfa_hci_api_deregister
    300 **
    301 ** Description      action function to deregister the given application
    302 **
    303 ** Returns          None
    304 **
    305 *******************************************************************************/
    306 void nfa_hci_api_deregister(tNFA_HCI_EVENT_DATA* p_evt_data) {
    307   tNFA_HCI_EVT_DATA evt_data;
    308   tNFA_HCI_CBACK* p_cback = NULL;
    309   int xx;
    310   tNFA_HCI_DYN_PIPE* p_pipe;
    311   tNFA_HCI_DYN_GATE* p_gate;
    312 
    313   /* If needed, find the application registration handle */
    314   if (p_evt_data != NULL) {
    315     for (xx = 0; xx < NFA_HCI_MAX_APP_CB; xx++) {
    316       if ((nfa_hci_cb.cfg.reg_app_names[xx][0] != 0) &&
    317           !strncmp(p_evt_data->app_info.app_name,
    318                    &nfa_hci_cb.cfg.reg_app_names[xx][0],
    319                    strlen(p_evt_data->app_info.app_name))) {
    320         NFA_TRACE_EVENT2("nfa_hci_api_deregister (%s) inx: %u",
    321                          p_evt_data->app_info.app_name, xx);
    322         break;
    323       }
    324     }
    325 
    326     if (xx == NFA_HCI_MAX_APP_CB) {
    327       NFA_TRACE_WARNING1("nfa_hci_api_deregister () Unknown app: %s",
    328                          p_evt_data->app_info.app_name);
    329       return;
    330     }
    331     nfa_hci_cb.app_in_use = (tNFA_HANDLE)(xx | NFA_HANDLE_GROUP_HCI);
    332     p_cback = nfa_hci_cb.p_app_cback[xx];
    333   } else {
    334     nfa_sys_stop_timer(&nfa_hci_cb.timer);
    335     /* We are recursing through deleting all the app's pipes and gates */
    336     p_cback = nfa_hci_cb.p_app_cback[nfa_hci_cb.app_in_use & NFA_HANDLE_MASK];
    337   }
    338 
    339   /* See if any pipe is owned by this app */
    340   if (nfa_hciu_find_pipe_by_owner(nfa_hci_cb.app_in_use) == NULL) {
    341     /* No pipes, release all gates owned by this app */
    342     while ((p_gate = nfa_hciu_find_gate_by_owner(nfa_hci_cb.app_in_use)) !=
    343            NULL)
    344       nfa_hciu_release_gate(p_gate->gate_id);
    345 
    346     memset(&nfa_hci_cb.cfg
    347                 .reg_app_names[nfa_hci_cb.app_in_use & NFA_HANDLE_MASK][0],
    348            0, NFA_MAX_HCI_APP_NAME_LEN + 1);
    349     nfa_hci_cb.p_app_cback[nfa_hci_cb.app_in_use & NFA_HANDLE_MASK] = NULL;
    350 
    351     nfa_hci_cb.nv_write_needed = true;
    352 
    353     evt_data.hci_deregister.status = NFC_STATUS_OK;
    354 
    355     if (nfa_hci_cb.hci_state == NFA_HCI_STATE_APP_DEREGISTER)
    356       nfa_hci_cb.hci_state = NFA_HCI_STATE_IDLE;
    357 
    358     /* notify NFA_HCI_DEREGISTER_EVT to the application */
    359     if (p_cback) p_cback(NFA_HCI_DEREGISTER_EVT, &evt_data);
    360   } else if ((p_pipe = nfa_hciu_find_active_pipe_by_owner(
    361                   nfa_hci_cb.app_in_use)) == NULL) {
    362     /* No pipes, release all gates owned by this app */
    363     while ((p_gate = nfa_hciu_find_gate_with_nopipes_by_owner(
    364                 nfa_hci_cb.app_in_use)) != NULL)
    365       nfa_hciu_release_gate(p_gate->gate_id);
    366 
    367     nfa_hci_cb.p_app_cback[nfa_hci_cb.app_in_use & NFA_HANDLE_MASK] = NULL;
    368 
    369     nfa_hci_cb.nv_write_needed = true;
    370 
    371     evt_data.hci_deregister.status = NFC_STATUS_FAILED;
    372 
    373     if (nfa_hci_cb.hci_state == NFA_HCI_STATE_APP_DEREGISTER)
    374       nfa_hci_cb.hci_state = NFA_HCI_STATE_IDLE;
    375 
    376     /* notify NFA_HCI_DEREGISTER_EVT to the application */
    377     if (p_cback) p_cback(NFA_HCI_DEREGISTER_EVT, &evt_data);
    378   } else {
    379     /* Delete all active pipes created for the application before de registering
    380     **/
    381     nfa_hci_cb.hci_state = NFA_HCI_STATE_APP_DEREGISTER;
    382 
    383     nfa_hciu_send_delete_pipe_cmd(p_pipe->pipe_id);
    384   }
    385 }
    386 
    387 /*******************************************************************************
    388 **
    389 ** Function         nfa_hci_api_get_gate_pipe_list
    390 **
    391 ** Description      action function to get application allocated gates and
    392 **                  application created pipes
    393 **
    394 ** Returns          None
    395 **
    396 *******************************************************************************/
    397 static void nfa_hci_api_get_gate_pipe_list(tNFA_HCI_EVENT_DATA* p_evt_data) {
    398   tNFA_HCI_EVT_DATA evt_data;
    399   int xx, yy;
    400   tNFA_HCI_DYN_GATE* pg = nfa_hci_cb.cfg.dyn_gates;
    401   tNFA_HCI_DYN_PIPE* pp = nfa_hci_cb.cfg.dyn_pipes;
    402 
    403   evt_data.gates_pipes.num_gates = 0;
    404   evt_data.gates_pipes.num_pipes = 0;
    405 
    406   for (xx = 0; xx < NFA_HCI_MAX_GATE_CB; xx++, pg++) {
    407     if (pg->gate_owner == p_evt_data->get_gate_pipe_list.hci_handle) {
    408       evt_data.gates_pipes.gate[evt_data.gates_pipes.num_gates++] = pg->gate_id;
    409 
    410       pp = nfa_hci_cb.cfg.dyn_pipes;
    411 
    412       /* Loop through looking for a match */
    413       for (yy = 0; yy < NFA_HCI_MAX_PIPE_CB; yy++, pp++) {
    414         if (pp->local_gate == pg->gate_id)
    415           evt_data.gates_pipes.pipe[evt_data.gates_pipes.num_pipes++] =
    416               *(tNFA_HCI_PIPE_INFO*)pp;
    417       }
    418     }
    419   }
    420 
    421   evt_data.gates_pipes.num_uicc_created_pipes = 0;
    422   /* Loop through all pipes that are connected to connectivity gate */
    423   for (xx = 0, pp = nfa_hci_cb.cfg.dyn_pipes; xx < NFA_HCI_MAX_PIPE_CB;
    424        xx++, pp++) {
    425     if (pp->pipe_id != 0 && pp->local_gate == NFA_HCI_CONNECTIVITY_GATE) {
    426       memcpy(&evt_data.gates_pipes.uicc_created_pipe
    427                   [evt_data.gates_pipes.num_uicc_created_pipes++],
    428              pp, sizeof(tNFA_HCI_PIPE_INFO));
    429     } else if (pp->pipe_id != 0 && pp->local_gate == NFA_HCI_LOOP_BACK_GATE) {
    430       memcpy(&evt_data.gates_pipes.uicc_created_pipe
    431                   [evt_data.gates_pipes.num_uicc_created_pipes++],
    432              pp, sizeof(tNFA_HCI_PIPE_INFO));
    433     } else if (pp->pipe_id >= NFA_HCI_FIRST_DYNAMIC_PIPE &&
    434                pp->pipe_id <= NFA_HCI_LAST_DYNAMIC_PIPE && pp->pipe_id &&
    435                pp->local_gate >= NFA_HCI_FIRST_PROP_GATE &&
    436                pp->local_gate <= NFA_HCI_LAST_PROP_GATE) {
    437       for (xx = 0, pg = nfa_hci_cb.cfg.dyn_gates; xx < NFA_HCI_MAX_GATE_CB;
    438            xx++, pg++) {
    439         if (pp->local_gate == pg->gate_id) {
    440           if (!pg->gate_owner)
    441             memcpy(&evt_data.gates_pipes.uicc_created_pipe
    442                         [evt_data.gates_pipes.num_uicc_created_pipes++],
    443                    pp, sizeof(tNFA_HCI_PIPE_INFO));
    444           break;
    445         }
    446       }
    447     }
    448   }
    449 
    450   evt_data.gates_pipes.status = NFA_STATUS_OK;
    451 
    452   /* notify NFA_HCI_GET_GATE_PIPE_LIST_EVT to the application */
    453   nfa_hciu_send_to_app(NFA_HCI_GET_GATE_PIPE_LIST_EVT, &evt_data,
    454                        p_evt_data->get_gate_pipe_list.hci_handle);
    455 }
    456 
    457 /*******************************************************************************
    458 **
    459 ** Function         nfa_hci_api_alloc_gate
    460 **
    461 ** Description      action function to allocate gate
    462 **
    463 ** Returns          None
    464 **
    465 *******************************************************************************/
    466 static void nfa_hci_api_alloc_gate(tNFA_HCI_EVENT_DATA* p_evt_data) {
    467   tNFA_HANDLE app_handle = p_evt_data->comm.hci_handle;
    468   tNFA_HCI_EVT_DATA evt_data;
    469   tNFA_HCI_DYN_GATE* p_gate;
    470 
    471   p_gate = nfa_hciu_alloc_gate(p_evt_data->gate_info.gate, app_handle);
    472 
    473   if (p_gate) {
    474     if (!p_gate->gate_owner) {
    475       /* No app owns the gate yet */
    476       p_gate->gate_owner = app_handle;
    477     } else if (p_gate->gate_owner != app_handle) {
    478       /* Some other app owns the gate */
    479       p_gate = NULL;
    480       NFA_TRACE_ERROR1(
    481           "nfa_hci_api_alloc_gate (): The Gate (0X%02x) already taken!",
    482           p_evt_data->gate_info.gate);
    483     }
    484   }
    485 
    486   evt_data.allocated.gate = p_gate ? p_gate->gate_id : 0;
    487   evt_data.allocated.status = p_gate ? NFA_STATUS_OK : NFA_STATUS_FAILED;
    488 
    489   /* notify NFA_HCI_ALLOCATE_GATE_EVT to the application */
    490   nfa_hciu_send_to_app(NFA_HCI_ALLOCATE_GATE_EVT, &evt_data, app_handle);
    491 }
    492 
    493 /*******************************************************************************
    494 **
    495 ** Function         nfa_hci_api_dealloc_gate
    496 **
    497 ** Description      action function to deallocate the given generic gate
    498 **
    499 ** Returns          None
    500 **
    501 *******************************************************************************/
    502 void nfa_hci_api_dealloc_gate(tNFA_HCI_EVENT_DATA* p_evt_data) {
    503   tNFA_HCI_EVT_DATA evt_data;
    504   uint8_t gate_id;
    505   tNFA_HCI_DYN_GATE* p_gate;
    506   tNFA_HCI_DYN_PIPE* p_pipe;
    507   tNFA_HANDLE app_handle;
    508 
    509   /* p_evt_data may be NULL if we are recursively deleting pipes */
    510   if (p_evt_data) {
    511     gate_id = p_evt_data->gate_dealloc.gate;
    512     app_handle = p_evt_data->gate_dealloc.hci_handle;
    513 
    514   } else {
    515     nfa_sys_stop_timer(&nfa_hci_cb.timer);
    516     gate_id = nfa_hci_cb.local_gate_in_use;
    517     app_handle = nfa_hci_cb.app_in_use;
    518   }
    519 
    520   evt_data.deallocated.gate = gate_id;
    521   ;
    522 
    523   p_gate = nfa_hciu_find_gate_by_gid(gate_id);
    524 
    525   if (p_gate == NULL) {
    526     evt_data.deallocated.status = NFA_STATUS_UNKNOWN_GID;
    527   } else if (p_gate->gate_owner != app_handle) {
    528     evt_data.deallocated.status = NFA_STATUS_FAILED;
    529   } else {
    530     /* See if any pipe is owned by this app */
    531     if (nfa_hciu_find_pipe_on_gate(p_gate->gate_id) == NULL) {
    532       nfa_hciu_release_gate(p_gate->gate_id);
    533 
    534       nfa_hci_cb.nv_write_needed = true;
    535       evt_data.deallocated.status = NFA_STATUS_OK;
    536 
    537       if (nfa_hci_cb.hci_state == NFA_HCI_STATE_REMOVE_GATE)
    538         nfa_hci_cb.hci_state = NFA_HCI_STATE_IDLE;
    539     } else if ((p_pipe = nfa_hciu_find_active_pipe_on_gate(p_gate->gate_id)) ==
    540                NULL) {
    541       /* UICC is not active at the moment and cannot delete the pipe */
    542       nfa_hci_cb.nv_write_needed = true;
    543       evt_data.deallocated.status = NFA_STATUS_FAILED;
    544 
    545       if (nfa_hci_cb.hci_state == NFA_HCI_STATE_REMOVE_GATE)
    546         nfa_hci_cb.hci_state = NFA_HCI_STATE_IDLE;
    547     } else {
    548       /* Delete pipes on the gate */
    549       nfa_hci_cb.local_gate_in_use = gate_id;
    550       nfa_hci_cb.app_in_use = app_handle;
    551       nfa_hci_cb.hci_state = NFA_HCI_STATE_REMOVE_GATE;
    552 
    553       nfa_hciu_send_delete_pipe_cmd(p_pipe->pipe_id);
    554       return;
    555     }
    556   }
    557 
    558   nfa_hciu_send_to_app(NFA_HCI_DEALLOCATE_GATE_EVT, &evt_data, app_handle);
    559 }
    560 
    561 /*******************************************************************************
    562 **
    563 ** Function         nfa_hci_api_get_host_list
    564 **
    565 ** Description      action function to get the host list from HCI network
    566 **
    567 ** Returns          None
    568 **
    569 *******************************************************************************/
    570 static void nfa_hci_api_get_host_list(tNFA_HCI_EVENT_DATA* p_evt_data) {
    571   uint8_t app_inx = p_evt_data->get_host_list.hci_handle & NFA_HANDLE_MASK;
    572 
    573   nfa_hci_cb.app_in_use = p_evt_data->get_host_list.hci_handle;
    574 
    575   /* Send Get Host List command on "Internal request" or requested by registered
    576    * application with valid handle and callback function */
    577   if ((nfa_hci_cb.app_in_use == NFA_HANDLE_INVALID) ||
    578       ((app_inx < NFA_HCI_MAX_APP_CB) &&
    579        (nfa_hci_cb.p_app_cback[app_inx] != NULL))) {
    580     nfa_hciu_send_get_param_cmd(NFA_HCI_ADMIN_PIPE, NFA_HCI_HOST_LIST_INDEX);
    581   }
    582 }
    583 
    584 /*******************************************************************************
    585 **
    586 ** Function         nfa_hci_api_create_pipe
    587 **
    588 ** Description      action function to create a pipe
    589 **
    590 ** Returns          TRUE, if the command is processed
    591 **                  FALSE, if command is queued for processing later
    592 **
    593 *******************************************************************************/
    594 static bool nfa_hci_api_create_pipe(tNFA_HCI_EVENT_DATA* p_evt_data) {
    595   tNFA_HCI_DYN_GATE* p_gate =
    596       nfa_hciu_find_gate_by_gid(p_evt_data->create_pipe.source_gate);
    597   tNFA_HCI_EVT_DATA evt_data;
    598   bool report_failed = false;
    599 
    600   /* Verify that the app owns the gate that the pipe is being created on */
    601   if ((p_gate == NULL) ||
    602       (p_gate->gate_owner != p_evt_data->create_pipe.hci_handle)) {
    603     report_failed = true;
    604     NFA_TRACE_ERROR2(
    605         "nfa_hci_api_create_pipe Cannot create pipe! APP: 0x%02x does not own "
    606         "the gate:0x%x",
    607         p_evt_data->create_pipe.hci_handle,
    608         p_evt_data->create_pipe.source_gate);
    609   } else if (nfa_hciu_check_pipe_between_gates(
    610                  p_evt_data->create_pipe.source_gate,
    611                  p_evt_data->create_pipe.dest_host,
    612                  p_evt_data->create_pipe.dest_gate)) {
    613     report_failed = true;
    614     NFA_TRACE_ERROR0(
    615         "nfa_hci_api_create_pipe : Cannot create multiple pipe between the "
    616         "same two gates!");
    617   }
    618 
    619   if (report_failed) {
    620     evt_data.created.source_gate = p_evt_data->create_pipe.source_gate;
    621     evt_data.created.status = NFA_STATUS_FAILED;
    622 
    623     nfa_hciu_send_to_app(NFA_HCI_CREATE_PIPE_EVT, &evt_data,
    624                          p_evt_data->open_pipe.hci_handle);
    625   } else {
    626     if (nfa_hciu_is_host_reseting(p_evt_data->create_pipe.dest_gate)) {
    627       GKI_enqueue(&nfa_hci_cb.hci_host_reset_api_q, (NFC_HDR*)p_evt_data);
    628       return false;
    629     }
    630 
    631     nfa_hci_cb.local_gate_in_use = p_evt_data->create_pipe.source_gate;
    632     nfa_hci_cb.remote_gate_in_use = p_evt_data->create_pipe.dest_gate;
    633     nfa_hci_cb.remote_host_in_use = p_evt_data->create_pipe.dest_host;
    634     nfa_hci_cb.app_in_use = p_evt_data->create_pipe.hci_handle;
    635 
    636     nfa_hciu_send_create_pipe_cmd(p_evt_data->create_pipe.source_gate,
    637                                   p_evt_data->create_pipe.dest_host,
    638                                   p_evt_data->create_pipe.dest_gate);
    639   }
    640   return true;
    641 }
    642 
    643 /*******************************************************************************
    644 **
    645 ** Function         nfa_hci_api_open_pipe
    646 **
    647 ** Description      action function to open a pipe
    648 **
    649 ** Returns          None
    650 **
    651 *******************************************************************************/
    652 static void nfa_hci_api_open_pipe(tNFA_HCI_EVENT_DATA* p_evt_data) {
    653   tNFA_HCI_EVT_DATA evt_data;
    654   tNFA_HCI_DYN_PIPE* p_pipe =
    655       nfa_hciu_find_pipe_by_pid(p_evt_data->open_pipe.pipe);
    656   tNFA_HCI_DYN_GATE* p_gate = NULL;
    657 
    658   if (p_pipe != NULL) p_gate = nfa_hciu_find_gate_by_gid(p_pipe->local_gate);
    659 
    660   if ((p_pipe != NULL) && (p_gate != NULL) &&
    661       (nfa_hciu_is_active_host(p_pipe->dest_host)) &&
    662       (p_gate->gate_owner == p_evt_data->open_pipe.hci_handle)) {
    663     if (p_pipe->pipe_state == NFA_HCI_PIPE_CLOSED) {
    664       nfa_hciu_send_open_pipe_cmd(p_evt_data->open_pipe.pipe);
    665     } else {
    666       evt_data.opened.pipe = p_evt_data->open_pipe.pipe;
    667       evt_data.opened.status = NFA_STATUS_OK;
    668 
    669       nfa_hciu_send_to_app(NFA_HCI_OPEN_PIPE_EVT, &evt_data,
    670                            p_evt_data->open_pipe.hci_handle);
    671     }
    672   } else {
    673     evt_data.opened.pipe = p_evt_data->open_pipe.pipe;
    674     evt_data.opened.status = NFA_STATUS_FAILED;
    675 
    676     nfa_hciu_send_to_app(NFA_HCI_OPEN_PIPE_EVT, &evt_data,
    677                          p_evt_data->open_pipe.hci_handle);
    678   }
    679 }
    680 
    681 /*******************************************************************************
    682 **
    683 ** Function         nfa_hci_api_get_reg_value
    684 **
    685 ** Description      action function to get the reg value of the specified index
    686 **
    687 ** Returns          TRUE, if the command is processed
    688 **                  FALSE, if command is queued for processing later
    689 **
    690 *******************************************************************************/
    691 static bool nfa_hci_api_get_reg_value(tNFA_HCI_EVENT_DATA* p_evt_data) {
    692   tNFA_HCI_DYN_PIPE* p_pipe =
    693       nfa_hciu_find_pipe_by_pid(p_evt_data->get_registry.pipe);
    694   tNFA_HCI_DYN_GATE* p_gate;
    695   tNFA_STATUS status = NFA_STATUS_FAILED;
    696   tNFA_HCI_EVT_DATA evt_data;
    697 
    698   if (p_pipe != NULL) {
    699     p_gate = nfa_hciu_find_gate_by_gid(p_pipe->local_gate);
    700 
    701     if ((p_gate != NULL) && (nfa_hciu_is_active_host(p_pipe->dest_host)) &&
    702         (p_gate->gate_owner == p_evt_data->get_registry.hci_handle)) {
    703       nfa_hci_cb.app_in_use = p_evt_data->get_registry.hci_handle;
    704 
    705       if (nfa_hciu_is_host_reseting(p_pipe->dest_host)) {
    706         GKI_enqueue(&nfa_hci_cb.hci_host_reset_api_q, (NFC_HDR*)p_evt_data);
    707         return false;
    708       }
    709 
    710       if (p_pipe->pipe_state == NFA_HCI_PIPE_CLOSED) {
    711         NFA_TRACE_WARNING1("nfa_hci_api_get_reg_value pipe:%d not open",
    712                            p_evt_data->get_registry.pipe);
    713       } else {
    714         status = nfa_hciu_send_get_param_cmd(p_evt_data->get_registry.pipe,
    715                                              p_evt_data->get_registry.reg_inx);
    716         if (status == NFA_STATUS_OK) return true;
    717       }
    718     }
    719   }
    720 
    721   evt_data.cmd_sent.status = status;
    722 
    723   /* Send NFA_HCI_CMD_SENT_EVT to notify failure */
    724   nfa_hciu_send_to_app(NFA_HCI_CMD_SENT_EVT, &evt_data,
    725                        p_evt_data->get_registry.hci_handle);
    726   return true;
    727 }
    728 
    729 /*******************************************************************************
    730 **
    731 ** Function         nfa_hci_api_set_reg_value
    732 **
    733 ** Description      action function to set the reg value at specified index
    734 **
    735 ** Returns          TRUE, if the command is processed
    736 **                  FALSE, if command is queued for processing later
    737 **
    738 *******************************************************************************/
    739 static bool nfa_hci_api_set_reg_value(tNFA_HCI_EVENT_DATA* p_evt_data) {
    740   tNFA_HCI_DYN_PIPE* p_pipe =
    741       nfa_hciu_find_pipe_by_pid(p_evt_data->set_registry.pipe);
    742   tNFA_HCI_DYN_GATE* p_gate;
    743   tNFA_STATUS status = NFA_STATUS_FAILED;
    744   tNFA_HCI_EVT_DATA evt_data;
    745 
    746   if (p_pipe != NULL) {
    747     p_gate = nfa_hciu_find_gate_by_gid(p_pipe->local_gate);
    748 
    749     if ((p_gate != NULL) && (nfa_hciu_is_active_host(p_pipe->dest_host)) &&
    750         (p_gate->gate_owner == p_evt_data->set_registry.hci_handle)) {
    751       nfa_hci_cb.app_in_use = p_evt_data->set_registry.hci_handle;
    752 
    753       if (nfa_hciu_is_host_reseting(p_pipe->dest_host)) {
    754         GKI_enqueue(&nfa_hci_cb.hci_host_reset_api_q, (NFC_HDR*)p_evt_data);
    755         return false;
    756       }
    757 
    758       if (p_pipe->pipe_state == NFA_HCI_PIPE_CLOSED) {
    759         NFA_TRACE_WARNING1("nfa_hci_api_set_reg_value pipe:%d not open",
    760                            p_evt_data->set_registry.pipe);
    761       } else {
    762         status = nfa_hciu_send_set_param_cmd(
    763             p_evt_data->set_registry.pipe, p_evt_data->set_registry.reg_inx,
    764             p_evt_data->set_registry.size, p_evt_data->set_registry.data);
    765         if (status == NFA_STATUS_OK) return true;
    766       }
    767     }
    768   }
    769   evt_data.cmd_sent.status = status;
    770 
    771   /* Send NFA_HCI_CMD_SENT_EVT to notify failure */
    772   nfa_hciu_send_to_app(NFA_HCI_CMD_SENT_EVT, &evt_data,
    773                        p_evt_data->set_registry.hci_handle);
    774   return true;
    775 }
    776 
    777 /*******************************************************************************
    778 **
    779 ** Function         nfa_hci_api_close_pipe
    780 **
    781 ** Description      action function to close a pipe
    782 **
    783 ** Returns          None
    784 **
    785 *******************************************************************************/
    786 static void nfa_hci_api_close_pipe(tNFA_HCI_EVENT_DATA* p_evt_data) {
    787   tNFA_HCI_EVT_DATA evt_data;
    788   tNFA_HCI_DYN_PIPE* p_pipe =
    789       nfa_hciu_find_pipe_by_pid(p_evt_data->close_pipe.pipe);
    790   tNFA_HCI_DYN_GATE* p_gate = NULL;
    791 
    792   if (p_pipe != NULL) p_gate = nfa_hciu_find_gate_by_gid(p_pipe->local_gate);
    793 
    794   if ((p_pipe != NULL) && (p_gate != NULL) &&
    795       (nfa_hciu_is_active_host(p_pipe->dest_host)) &&
    796       (p_gate->gate_owner == p_evt_data->close_pipe.hci_handle)) {
    797     if (p_pipe->pipe_state == NFA_HCI_PIPE_OPENED) {
    798       nfa_hciu_send_close_pipe_cmd(p_evt_data->close_pipe.pipe);
    799     } else {
    800       evt_data.closed.status = NFA_STATUS_OK;
    801       evt_data.closed.pipe = p_evt_data->close_pipe.pipe;
    802 
    803       nfa_hciu_send_to_app(NFA_HCI_CLOSE_PIPE_EVT, &evt_data,
    804                            p_evt_data->close_pipe.hci_handle);
    805     }
    806   } else {
    807     evt_data.closed.status = NFA_STATUS_FAILED;
    808     evt_data.closed.pipe = 0x00;
    809 
    810     nfa_hciu_send_to_app(NFA_HCI_CLOSE_PIPE_EVT, &evt_data,
    811                          p_evt_data->close_pipe.hci_handle);
    812   }
    813 }
    814 
    815 /*******************************************************************************
    816 **
    817 ** Function         nfa_hci_api_delete_pipe
    818 **
    819 ** Description      action function to delete a pipe
    820 **
    821 ** Returns          None
    822 **
    823 *******************************************************************************/
    824 static void nfa_hci_api_delete_pipe(tNFA_HCI_EVENT_DATA* p_evt_data) {
    825   tNFA_HCI_EVT_DATA evt_data;
    826   tNFA_HCI_DYN_PIPE* p_pipe =
    827       nfa_hciu_find_pipe_by_pid(p_evt_data->delete_pipe.pipe);
    828   tNFA_HCI_DYN_GATE* p_gate = NULL;
    829 
    830   if (p_pipe != NULL) {
    831     p_gate = nfa_hciu_find_gate_by_gid(p_pipe->local_gate);
    832     if ((p_gate != NULL) &&
    833         (p_gate->gate_owner == p_evt_data->delete_pipe.hci_handle) &&
    834         (nfa_hciu_is_active_host(p_pipe->dest_host))) {
    835       nfa_hciu_send_delete_pipe_cmd(p_evt_data->delete_pipe.pipe);
    836       return;
    837     }
    838   }
    839 
    840   evt_data.deleted.status = NFA_STATUS_FAILED;
    841   evt_data.deleted.pipe = 0x00;
    842   nfa_hciu_send_to_app(NFA_HCI_DELETE_PIPE_EVT, &evt_data,
    843                        p_evt_data->close_pipe.hci_handle);
    844 }
    845 
    846 /*******************************************************************************
    847 **
    848 ** Function         nfa_hci_api_send_cmd
    849 **
    850 ** Description      action function to send command on the given pipe
    851 **
    852 ** Returns          TRUE, if the command is processed
    853 **                  FALSE, if command is queued for processing later
    854 **
    855 *******************************************************************************/
    856 static bool nfa_hci_api_send_cmd(tNFA_HCI_EVENT_DATA* p_evt_data) {
    857   tNFA_STATUS status = NFA_STATUS_FAILED;
    858   tNFA_HCI_DYN_PIPE* p_pipe;
    859   tNFA_HCI_EVT_DATA evt_data;
    860   tNFA_HANDLE app_handle;
    861 
    862   if ((p_pipe = nfa_hciu_find_pipe_by_pid(p_evt_data->send_cmd.pipe)) != NULL) {
    863     app_handle = nfa_hciu_get_pipe_owner(p_evt_data->send_cmd.pipe);
    864 
    865     if ((nfa_hciu_is_active_host(p_pipe->dest_host)) &&
    866         ((app_handle == p_evt_data->send_cmd.hci_handle ||
    867           p_pipe->local_gate == NFA_HCI_CONNECTIVITY_GATE))) {
    868       if (nfa_hciu_is_host_reseting(p_pipe->dest_host)) {
    869         GKI_enqueue(&nfa_hci_cb.hci_host_reset_api_q, (NFC_HDR*)p_evt_data);
    870         return false;
    871       }
    872 
    873       if (p_pipe->pipe_state == NFA_HCI_PIPE_OPENED) {
    874         nfa_hci_cb.pipe_in_use = p_evt_data->send_cmd.pipe;
    875         status = nfa_hciu_send_msg(p_pipe->pipe_id, NFA_HCI_COMMAND_TYPE,
    876                                    p_evt_data->send_cmd.cmd_code,
    877                                    p_evt_data->send_cmd.cmd_len,
    878                                    p_evt_data->send_cmd.data);
    879         if (status == NFA_STATUS_OK) return true;
    880       } else {
    881         NFA_TRACE_WARNING1("nfa_hci_api_send_cmd pipe:%d not open",
    882                            p_pipe->pipe_id);
    883       }
    884     } else {
    885       NFA_TRACE_WARNING1(
    886           "nfa_hci_api_send_cmd pipe:%d Owned by different application or "
    887           "Destination host is not active",
    888           p_pipe->pipe_id);
    889     }
    890   } else {
    891     NFA_TRACE_WARNING1("nfa_hci_api_send_cmd pipe:%d not found",
    892                        p_evt_data->send_cmd.pipe);
    893   }
    894 
    895   evt_data.cmd_sent.status = status;
    896 
    897   /* Send NFA_HCI_CMD_SENT_EVT to notify failure */
    898   nfa_hciu_send_to_app(NFA_HCI_CMD_SENT_EVT, &evt_data,
    899                        p_evt_data->send_cmd.hci_handle);
    900   return true;
    901 }
    902 
    903 /*******************************************************************************
    904 **
    905 ** Function         nfa_hci_api_send_rsp
    906 **
    907 ** Description      action function to send response on the given pipe
    908 **
    909 ** Returns          None
    910 **
    911 *******************************************************************************/
    912 static void nfa_hci_api_send_rsp(tNFA_HCI_EVENT_DATA* p_evt_data) {
    913   tNFA_STATUS status = NFA_STATUS_FAILED;
    914   tNFA_HCI_DYN_PIPE* p_pipe;
    915   tNFA_HCI_EVT_DATA evt_data;
    916   tNFA_HANDLE app_handle;
    917 
    918   if ((p_pipe = nfa_hciu_find_pipe_by_pid(p_evt_data->send_rsp.pipe)) != NULL) {
    919     app_handle = nfa_hciu_get_pipe_owner(p_evt_data->send_rsp.pipe);
    920 
    921     if ((nfa_hciu_is_active_host(p_pipe->dest_host)) &&
    922         ((app_handle == p_evt_data->send_rsp.hci_handle ||
    923           p_pipe->local_gate == NFA_HCI_CONNECTIVITY_GATE))) {
    924       if (p_pipe->pipe_state == NFA_HCI_PIPE_OPENED) {
    925         status = nfa_hciu_send_msg(p_pipe->pipe_id, NFA_HCI_RESPONSE_TYPE,
    926                                    p_evt_data->send_rsp.response,
    927                                    p_evt_data->send_rsp.size,
    928                                    p_evt_data->send_rsp.data);
    929         if (status == NFA_STATUS_OK) return;
    930       } else {
    931         NFA_TRACE_WARNING1("nfa_hci_api_send_rsp pipe:%d not open",
    932                            p_pipe->pipe_id);
    933       }
    934     } else {
    935       NFA_TRACE_WARNING1(
    936           "nfa_hci_api_send_rsp pipe:%d Owned by different application or "
    937           "Destination host is not active",
    938           p_pipe->pipe_id);
    939     }
    940   } else {
    941     NFA_TRACE_WARNING1("nfa_hci_api_send_rsp pipe:%d not found",
    942                        p_evt_data->send_rsp.pipe);
    943   }
    944 
    945   evt_data.rsp_sent.status = status;
    946 
    947   /* Send NFA_HCI_RSP_SENT_EVT to notify failure */
    948   nfa_hciu_send_to_app(NFA_HCI_RSP_SENT_EVT, &evt_data,
    949                        p_evt_data->send_rsp.hci_handle);
    950 }
    951 
    952 /*******************************************************************************
    953 **
    954 ** Function         nfa_hci_api_send_event
    955 **
    956 ** Description      action function to send an event to the given pipe
    957 **
    958 ** Returns          TRUE, if the event is processed
    959 **                  FALSE, if event is queued for processing later
    960 **
    961 *******************************************************************************/
    962 static bool nfa_hci_api_send_event(tNFA_HCI_EVENT_DATA* p_evt_data) {
    963   tNFA_STATUS status = NFA_STATUS_FAILED;
    964   tNFA_HCI_DYN_PIPE* p_pipe;
    965   tNFA_HCI_EVT_DATA evt_data;
    966   tNFA_HANDLE app_handle;
    967 
    968   if ((p_pipe = nfa_hciu_find_pipe_by_pid(p_evt_data->send_evt.pipe)) != NULL) {
    969     app_handle = nfa_hciu_get_pipe_owner(p_evt_data->send_evt.pipe);
    970 
    971     if ((nfa_hciu_is_active_host(p_pipe->dest_host)) &&
    972         ((app_handle == p_evt_data->send_evt.hci_handle ||
    973           p_pipe->local_gate == NFA_HCI_CONNECTIVITY_GATE))) {
    974       if (nfa_hciu_is_host_reseting(p_pipe->dest_host)) {
    975         GKI_enqueue(&nfa_hci_cb.hci_host_reset_api_q, (NFC_HDR*)p_evt_data);
    976         return false;
    977       }
    978 
    979       if (p_pipe->pipe_state == NFA_HCI_PIPE_OPENED) {
    980         status = nfa_hciu_send_msg(
    981             p_pipe->pipe_id, NFA_HCI_EVENT_TYPE, p_evt_data->send_evt.evt_code,
    982             p_evt_data->send_evt.evt_len, p_evt_data->send_evt.p_evt_buf);
    983 
    984         if (status == NFA_STATUS_OK) {
    985           if (p_pipe->local_gate == NFA_HCI_LOOP_BACK_GATE) {
    986             nfa_hci_cb.w4_rsp_evt = true;
    987             nfa_hci_cb.hci_state = NFA_HCI_STATE_WAIT_RSP;
    988           }
    989 
    990           if (p_evt_data->send_evt.rsp_len) {
    991             nfa_hci_cb.pipe_in_use = p_evt_data->send_evt.pipe;
    992             nfa_hci_cb.rsp_buf_size = p_evt_data->send_evt.rsp_len;
    993             nfa_hci_cb.p_rsp_buf = p_evt_data->send_evt.p_rsp_buf;
    994             if (p_evt_data->send_evt.rsp_timeout) {
    995               nfa_hci_cb.w4_rsp_evt = true;
    996               nfa_hci_cb.hci_state = NFA_HCI_STATE_WAIT_RSP;
    997               nfa_sys_start_timer(&nfa_hci_cb.timer, NFA_HCI_RSP_TIMEOUT_EVT,
    998                                   p_evt_data->send_evt.rsp_timeout);
    999             } else if (p_pipe->local_gate == NFA_HCI_LOOP_BACK_GATE) {
   1000               nfa_sys_start_timer(&nfa_hci_cb.timer, NFA_HCI_RSP_TIMEOUT_EVT,
   1001                                   p_nfa_hci_cfg->hcp_response_timeout);
   1002             }
   1003           } else {
   1004             if (p_pipe->local_gate == NFA_HCI_LOOP_BACK_GATE) {
   1005               nfa_hci_cb.pipe_in_use = p_evt_data->send_evt.pipe;
   1006               nfa_sys_start_timer(&nfa_hci_cb.timer, NFA_HCI_RSP_TIMEOUT_EVT,
   1007                                   p_nfa_hci_cfg->hcp_response_timeout);
   1008             }
   1009             nfa_hci_cb.rsp_buf_size = 0;
   1010             nfa_hci_cb.p_rsp_buf = NULL;
   1011           }
   1012         }
   1013       } else {
   1014         NFA_TRACE_WARNING1("nfa_hci_api_send_event pipe:%d not open",
   1015                            p_pipe->pipe_id);
   1016       }
   1017     } else {
   1018       NFA_TRACE_WARNING1(
   1019           "nfa_hci_api_send_event pipe:%d Owned by different application or "
   1020           "Destination host is not active",
   1021           p_pipe->pipe_id);
   1022     }
   1023   } else {
   1024     NFA_TRACE_WARNING1("nfa_hci_api_send_event pipe:%d not found",
   1025                        p_evt_data->send_evt.pipe);
   1026   }
   1027 
   1028   evt_data.evt_sent.status = status;
   1029 
   1030   /* Send NFC_HCI_EVENT_SENT_EVT to notify status */
   1031   nfa_hciu_send_to_app(NFA_HCI_EVENT_SENT_EVT, &evt_data,
   1032                        p_evt_data->send_evt.hci_handle);
   1033   return true;
   1034 }
   1035 
   1036 /*******************************************************************************
   1037 **
   1038 ** Function         nfa_hci_api_add_static_pipe
   1039 **
   1040 ** Description      action function to add static pipe
   1041 **
   1042 ** Returns          None
   1043 **
   1044 *******************************************************************************/
   1045 static void nfa_hci_api_add_static_pipe(tNFA_HCI_EVENT_DATA* p_evt_data) {
   1046   tNFA_HCI_DYN_GATE* pg;
   1047   tNFA_HCI_DYN_PIPE* pp;
   1048   tNFA_HCI_EVT_DATA evt_data;
   1049 
   1050   /* Allocate a proprietary gate */
   1051   pg = nfa_hciu_alloc_gate(p_evt_data->add_static_pipe.gate,
   1052                            p_evt_data->add_static_pipe.hci_handle);
   1053   if (pg != NULL) {
   1054     /* Assign new owner to the gate */
   1055     pg->gate_owner = p_evt_data->add_static_pipe.hci_handle;
   1056 
   1057     /* Add the dynamic pipe to the proprietary gate */
   1058     if (nfa_hciu_add_pipe_to_gate(p_evt_data->add_static_pipe.pipe, pg->gate_id,
   1059                                   p_evt_data->add_static_pipe.host,
   1060                                   p_evt_data->add_static_pipe.gate) !=
   1061         NFA_HCI_ANY_OK) {
   1062       /* Unable to add the dynamic pipe, so release the gate */
   1063       nfa_hciu_release_gate(pg->gate_id);
   1064       evt_data.pipe_added.status = NFA_STATUS_FAILED;
   1065       nfa_hciu_send_to_app(NFA_HCI_ADD_STATIC_PIPE_EVT, &evt_data,
   1066                            p_evt_data->add_static_pipe.hci_handle);
   1067       return;
   1068     }
   1069     pp = nfa_hciu_find_pipe_by_pid(p_evt_data->add_static_pipe.pipe);
   1070     if (pp != NULL) {
   1071       /* This pipe is always opened */
   1072       pp->pipe_state = NFA_HCI_PIPE_OPENED;
   1073       evt_data.pipe_added.status = NFA_STATUS_OK;
   1074       nfa_hciu_send_to_app(NFA_HCI_ADD_STATIC_PIPE_EVT, &evt_data,
   1075                            p_evt_data->add_static_pipe.hci_handle);
   1076       return;
   1077     }
   1078   }
   1079   /* Unable to add static pipe */
   1080   evt_data.pipe_added.status = NFA_STATUS_FAILED;
   1081   nfa_hciu_send_to_app(NFA_HCI_ADD_STATIC_PIPE_EVT, &evt_data,
   1082                        p_evt_data->add_static_pipe.hci_handle);
   1083 }
   1084 
   1085 /*******************************************************************************
   1086 **
   1087 ** Function         nfa_hci_handle_link_mgm_gate_cmd
   1088 **
   1089 ** Description      This function handles incoming link management gate hci
   1090 **                  commands
   1091 **
   1092 ** Returns          none
   1093 **
   1094 *******************************************************************************/
   1095 void nfa_hci_handle_link_mgm_gate_cmd(uint8_t* p_data) {
   1096   uint8_t index;
   1097   uint8_t data[2];
   1098   uint8_t rsp_len = 0;
   1099   uint8_t response = NFA_HCI_ANY_OK;
   1100 
   1101   if ((nfa_hci_cb.cfg.link_mgmt_gate.pipe00_state != NFA_HCI_PIPE_OPENED) &&
   1102       (nfa_hci_cb.inst != NFA_HCI_ANY_OPEN_PIPE)) {
   1103     nfa_hciu_send_msg(NFA_HCI_LINK_MANAGEMENT_PIPE, NFA_HCI_RESPONSE_TYPE,
   1104                       NFA_HCI_ANY_E_PIPE_NOT_OPENED, 0, NULL);
   1105     return;
   1106   }
   1107 
   1108   switch (nfa_hci_cb.inst) {
   1109     case NFA_HCI_ANY_SET_PARAMETER:
   1110       STREAM_TO_UINT8(index, p_data);
   1111 
   1112       if (index == 1) {
   1113         STREAM_TO_UINT16(nfa_hci_cb.cfg.link_mgmt_gate.rec_errors, p_data);
   1114       } else
   1115         response = NFA_HCI_ANY_E_REG_PAR_UNKNOWN;
   1116       break;
   1117 
   1118     case NFA_HCI_ANY_GET_PARAMETER:
   1119       STREAM_TO_UINT8(index, p_data);
   1120       if (index == 1) {
   1121         data[0] =
   1122             (uint8_t)((nfa_hci_cb.cfg.link_mgmt_gate.rec_errors >> 8) & 0x00FF);
   1123         data[1] = (uint8_t)(nfa_hci_cb.cfg.link_mgmt_gate.rec_errors & 0x000F);
   1124         rsp_len = 2;
   1125       } else
   1126         response = NFA_HCI_ANY_E_REG_PAR_UNKNOWN;
   1127       break;
   1128 
   1129     case NFA_HCI_ANY_OPEN_PIPE:
   1130       data[0] = 0;
   1131       rsp_len = 1;
   1132       nfa_hci_cb.cfg.link_mgmt_gate.pipe00_state = NFA_HCI_PIPE_OPENED;
   1133       break;
   1134 
   1135     case NFA_HCI_ANY_CLOSE_PIPE:
   1136       nfa_hci_cb.cfg.link_mgmt_gate.pipe00_state = NFA_HCI_PIPE_CLOSED;
   1137       break;
   1138 
   1139     default:
   1140       response = NFA_HCI_ANY_E_CMD_NOT_SUPPORTED;
   1141       break;
   1142   }
   1143 
   1144   nfa_hciu_send_msg(NFA_HCI_LINK_MANAGEMENT_PIPE, NFA_HCI_RESPONSE_TYPE,
   1145                     response, rsp_len, data);
   1146 }
   1147 
   1148 /*******************************************************************************
   1149 **
   1150 ** Function         nfa_hci_handle_pipe_open_close_cmd
   1151 **
   1152 ** Description      This function handles all generic gates (excluding
   1153 **                  connectivity gate) commands
   1154 **
   1155 ** Returns          none
   1156 **
   1157 *******************************************************************************/
   1158 void nfa_hci_handle_pipe_open_close_cmd(tNFA_HCI_DYN_PIPE* p_pipe) {
   1159   uint8_t data[1];
   1160   uint8_t rsp_len = 0;
   1161   tNFA_HCI_RESPONSE response = NFA_HCI_ANY_OK;
   1162   tNFA_HCI_DYN_GATE* p_gate;
   1163 
   1164   if (nfa_hci_cb.inst == NFA_HCI_ANY_OPEN_PIPE) {
   1165     if ((p_gate = nfa_hciu_find_gate_by_gid(p_pipe->local_gate)) != NULL)
   1166       data[0] = nfa_hciu_count_open_pipes_on_gate(p_gate);
   1167     else
   1168       data[0] = 0;
   1169 
   1170     p_pipe->pipe_state = NFA_HCI_PIPE_OPENED;
   1171     rsp_len = 1;
   1172   } else if (nfa_hci_cb.inst == NFA_HCI_ANY_CLOSE_PIPE) {
   1173     p_pipe->pipe_state = NFA_HCI_PIPE_CLOSED;
   1174   }
   1175 
   1176   nfa_hciu_send_msg(p_pipe->pipe_id, NFA_HCI_RESPONSE_TYPE, response, rsp_len,
   1177                     data);
   1178 }
   1179 
   1180 /*******************************************************************************
   1181 **
   1182 ** Function         nfa_hci_handle_admin_gate_cmd
   1183 **
   1184 ** Description      This function handles incoming commands on ADMIN gate
   1185 **
   1186 ** Returns          none
   1187 **
   1188 *******************************************************************************/
   1189 void nfa_hci_handle_admin_gate_cmd(uint8_t* p_data) {
   1190   uint8_t source_host, source_gate, dest_host, dest_gate, pipe;
   1191   uint8_t data = 0;
   1192   uint8_t rsp_len = 0;
   1193   tNFA_HCI_RESPONSE response = NFA_HCI_ANY_OK;
   1194   tNFA_HCI_DYN_GATE* pgate;
   1195   tNFA_HCI_EVT_DATA evt_data;
   1196 
   1197   switch (nfa_hci_cb.inst) {
   1198     case NFA_HCI_ANY_OPEN_PIPE:
   1199       nfa_hci_cb.cfg.admin_gate.pipe01_state = NFA_HCI_PIPE_OPENED;
   1200       data = 0;
   1201       rsp_len = 1;
   1202       break;
   1203 
   1204     case NFA_HCI_ANY_CLOSE_PIPE:
   1205       nfa_hci_cb.cfg.admin_gate.pipe01_state = NFA_HCI_PIPE_CLOSED;
   1206       /* Reopen the pipe immediately */
   1207       nfa_hciu_send_msg(NFA_HCI_ADMIN_PIPE, NFA_HCI_RESPONSE_TYPE, response,
   1208                         rsp_len, &data);
   1209       nfa_hci_cb.app_in_use = NFA_HANDLE_INVALID;
   1210       nfa_hciu_send_open_pipe_cmd(NFA_HCI_ADMIN_PIPE);
   1211       return;
   1212       break;
   1213 
   1214     case NFA_HCI_ADM_NOTIFY_PIPE_CREATED:
   1215       STREAM_TO_UINT8(source_host, p_data);
   1216       STREAM_TO_UINT8(source_gate, p_data);
   1217       STREAM_TO_UINT8(dest_host, p_data);
   1218       STREAM_TO_UINT8(dest_gate, p_data);
   1219       STREAM_TO_UINT8(pipe, p_data);
   1220 
   1221       if ((dest_gate == NFA_HCI_IDENTITY_MANAGEMENT_GATE) ||
   1222           (dest_gate == NFA_HCI_LOOP_BACK_GATE)) {
   1223         response = nfa_hciu_add_pipe_to_static_gate(dest_gate, pipe,
   1224                                                     source_host, source_gate);
   1225       } else {
   1226         if ((pgate = nfa_hciu_find_gate_by_gid(dest_gate)) != NULL) {
   1227           /* If the gate is valid, add the pipe to it  */
   1228           if (nfa_hciu_check_pipe_between_gates(dest_gate, source_host,
   1229                                                 source_gate)) {
   1230             /* Already, there is a pipe between these two gates, so will reject
   1231              */
   1232             response = NFA_HCI_ANY_E_NOK;
   1233           } else {
   1234             response = nfa_hciu_add_pipe_to_gate(pipe, dest_gate, source_host,
   1235                                                  source_gate);
   1236             if (response == NFA_HCI_ANY_OK) {
   1237               /* Tell the application a pipe was created with its gate */
   1238 
   1239               evt_data.created.status = NFA_STATUS_OK;
   1240               evt_data.created.pipe = pipe;
   1241               evt_data.created.source_gate = dest_gate;
   1242               evt_data.created.dest_host = source_host;
   1243               evt_data.created.dest_gate = source_gate;
   1244 
   1245               nfa_hciu_send_to_app(NFA_HCI_CREATE_PIPE_EVT, &evt_data,
   1246                                    pgate->gate_owner);
   1247             }
   1248           }
   1249         } else {
   1250           response = NFA_HCI_ANY_E_NOK;
   1251           if ((dest_gate >= NFA_HCI_FIRST_PROP_GATE) &&
   1252               (dest_gate <= NFA_HCI_LAST_PROP_GATE)) {
   1253             if (nfa_hciu_alloc_gate(dest_gate, 0))
   1254               response = nfa_hciu_add_pipe_to_gate(pipe, dest_gate, source_host,
   1255                                                    source_gate);
   1256           }
   1257         }
   1258       }
   1259       break;
   1260 
   1261     case NFA_HCI_ADM_NOTIFY_PIPE_DELETED:
   1262       STREAM_TO_UINT8(pipe, p_data);
   1263       response = nfa_hciu_release_pipe(pipe);
   1264       break;
   1265 
   1266     case NFA_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED:
   1267       STREAM_TO_UINT8(source_host, p_data);
   1268 
   1269       nfa_hciu_remove_all_pipes_from_host(source_host);
   1270 
   1271       if (source_host == NFA_HCI_HOST_CONTROLLER) {
   1272         nfa_hci_cb.cfg.link_mgmt_gate.pipe00_state = NFA_HCI_PIPE_CLOSED;
   1273         nfa_hci_cb.cfg.admin_gate.pipe01_state = NFA_HCI_PIPE_CLOSED;
   1274 
   1275         /* Reopen the admin pipe immediately */
   1276         nfa_hci_cb.app_in_use = NFA_HANDLE_INVALID;
   1277         nfa_hciu_send_open_pipe_cmd(NFA_HCI_ADMIN_PIPE);
   1278         return;
   1279       } else {
   1280         if ((source_host >= NFA_HCI_HOST_ID_UICC0) &&
   1281             (source_host <
   1282              (NFA_HCI_HOST_ID_UICC0 + NFA_HCI_MAX_HOST_IN_NETWORK))) {
   1283           nfa_hci_cb.reset_host[source_host - NFA_HCI_HOST_ID_UICC0] =
   1284               source_host;
   1285         }
   1286       }
   1287       break;
   1288 
   1289     default:
   1290       response = NFA_HCI_ANY_E_CMD_NOT_SUPPORTED;
   1291       break;
   1292   }
   1293 
   1294   nfa_hciu_send_msg(NFA_HCI_ADMIN_PIPE, NFA_HCI_RESPONSE_TYPE, response,
   1295                     rsp_len, &data);
   1296 }
   1297 
   1298 /*******************************************************************************
   1299 **
   1300 ** Function         nfa_hci_handle_admin_gate_rsp
   1301 **
   1302 ** Description      This function handles response received on admin gate
   1303 **
   1304 ** Returns          none
   1305 **
   1306 *******************************************************************************/
   1307 void nfa_hci_handle_admin_gate_rsp(uint8_t* p_data, uint8_t data_len) {
   1308   uint8_t source_host;
   1309   uint8_t source_gate = nfa_hci_cb.local_gate_in_use;
   1310   uint8_t dest_host = nfa_hci_cb.remote_host_in_use;
   1311   uint8_t dest_gate = nfa_hci_cb.remote_gate_in_use;
   1312   uint8_t pipe = 0;
   1313   tNFA_STATUS status;
   1314   tNFA_HCI_EVT_DATA evt_data;
   1315   uint8_t default_session[NFA_HCI_SESSION_ID_LEN] = {0xFF, 0xFF, 0xFF, 0xFF,
   1316                                                      0xFF, 0xFF, 0xFF, 0xFF};
   1317   uint8_t host_count = 0;
   1318   uint8_t host_id = 0;
   1319   uint32_t os_tick;
   1320 
   1321 #if (BT_TRACE_VERBOSE == TRUE)
   1322   NFA_TRACE_DEBUG4(
   1323       "nfa_hci_handle_admin_gate_rsp - LastCmdSent: %s  App: 0x%04x  Gate: "
   1324       "0x%02x  Pipe: 0x%02x",
   1325       nfa_hciu_instr_2_str(nfa_hci_cb.cmd_sent), nfa_hci_cb.app_in_use,
   1326       nfa_hci_cb.local_gate_in_use, nfa_hci_cb.pipe_in_use);
   1327 #else
   1328   NFA_TRACE_DEBUG4(
   1329       "nfa_hci_handle_admin_gate_rsp LastCmdSent: %u  App: 0x%04x  Gate: "
   1330       "0x%02x  Pipe: 0x%02x",
   1331       nfa_hci_cb.cmd_sent, nfa_hci_cb.app_in_use, nfa_hci_cb.local_gate_in_use,
   1332       nfa_hci_cb.pipe_in_use);
   1333 #endif
   1334 
   1335   /* If starting up, handle events here */
   1336   if ((nfa_hci_cb.hci_state == NFA_HCI_STATE_STARTUP) ||
   1337       (nfa_hci_cb.hci_state == NFA_HCI_STATE_RESTORE) ||
   1338       (nfa_hci_cb.hci_state == NFA_HCI_STATE_WAIT_NETWK_ENABLE) ||
   1339       (nfa_hci_cb.hci_state == NFA_HCI_STATE_RESTORE_NETWK_ENABLE)) {
   1340     if (nfa_hci_cb.inst == NFA_HCI_ANY_E_PIPE_NOT_OPENED) {
   1341       nfa_hciu_send_open_pipe_cmd(NFA_HCI_ADMIN_PIPE);
   1342       return;
   1343     }
   1344 
   1345     if (nfa_hci_cb.inst != NFA_HCI_ANY_OK) {
   1346       NFA_TRACE_ERROR0("nfa_hci_handle_admin_gate_rsp - Initialization failed");
   1347       nfa_hci_startup_complete(NFA_STATUS_FAILED);
   1348       return;
   1349     }
   1350 
   1351     switch (nfa_hci_cb.cmd_sent) {
   1352       case NFA_HCI_ANY_SET_PARAMETER:
   1353         if (nfa_hci_cb.param_in_use == NFA_HCI_SESSION_IDENTITY_INDEX) {
   1354           /* Set WHITELIST */
   1355           nfa_hciu_send_set_param_cmd(
   1356               NFA_HCI_ADMIN_PIPE, NFA_HCI_WHITELIST_INDEX,
   1357               p_nfa_hci_cfg->num_whitelist_host, p_nfa_hci_cfg->p_whitelist);
   1358         } else if (nfa_hci_cb.param_in_use == NFA_HCI_WHITELIST_INDEX) {
   1359           if ((nfa_hci_cb.hci_state == NFA_HCI_STATE_STARTUP) ||
   1360               (nfa_hci_cb.hci_state == NFA_HCI_STATE_RESTORE))
   1361             nfa_hci_dh_startup_complete();
   1362         }
   1363         break;
   1364 
   1365       case NFA_HCI_ANY_GET_PARAMETER:
   1366         if (nfa_hci_cb.param_in_use == NFA_HCI_HOST_LIST_INDEX) {
   1367           host_count = 0;
   1368           while (host_count < NFA_HCI_MAX_HOST_IN_NETWORK) {
   1369             nfa_hci_cb.inactive_host[host_count] =
   1370                 NFA_HCI_HOST_ID_UICC0 + host_count;
   1371             host_count++;
   1372           }
   1373 
   1374           host_count = 0;
   1375           /* Collect active host in the Host Network */
   1376           while (host_count < data_len) {
   1377             host_id = (uint8_t)*p_data++;
   1378 
   1379             if ((host_id >= NFA_HCI_HOST_ID_UICC0) &&
   1380                 (host_id <
   1381                  NFA_HCI_HOST_ID_UICC0 + NFA_HCI_MAX_HOST_IN_NETWORK)) {
   1382               nfa_hci_cb.inactive_host[host_id - NFA_HCI_HOST_ID_UICC0] = 0x00;
   1383               nfa_hci_cb.reset_host[host_id - NFA_HCI_HOST_ID_UICC0] = 0x00;
   1384             }
   1385 
   1386             host_count++;
   1387           }
   1388           nfa_hci_startup_complete(NFA_STATUS_OK);
   1389         } else if (nfa_hci_cb.param_in_use == NFA_HCI_SESSION_IDENTITY_INDEX) {
   1390           /* The only parameter we get when initializing is the session ID.
   1391            * Check for match. */
   1392           if (!memcmp((uint8_t*)nfa_hci_cb.cfg.admin_gate.session_id, p_data,
   1393                       NFA_HCI_SESSION_ID_LEN)) {
   1394             /* Session has not changed, Set WHITELIST */
   1395             nfa_hciu_send_set_param_cmd(
   1396                 NFA_HCI_ADMIN_PIPE, NFA_HCI_WHITELIST_INDEX,
   1397                 p_nfa_hci_cfg->num_whitelist_host, p_nfa_hci_cfg->p_whitelist);
   1398           } else {
   1399             /* Something wrong, NVRAM data could be corrupt or first start with
   1400              * default session id */
   1401             nfa_hciu_send_clear_all_pipe_cmd();
   1402             nfa_hci_cb.b_hci_netwk_reset = true;
   1403           }
   1404         }
   1405         break;
   1406 
   1407       case NFA_HCI_ANY_OPEN_PIPE:
   1408         nfa_hci_cb.cfg.admin_gate.pipe01_state = NFA_HCI_PIPE_OPENED;
   1409 
   1410         if (nfa_hci_cb.b_hci_netwk_reset) {
   1411           nfa_hci_cb.b_hci_netwk_reset = false;
   1412           /* Session ID is reset, Set New session id */
   1413           memcpy(
   1414               &nfa_hci_cb.cfg.admin_gate.session_id[NFA_HCI_SESSION_ID_LEN / 2],
   1415               nfa_hci_cb.cfg.admin_gate.session_id,
   1416               (NFA_HCI_SESSION_ID_LEN / 2));
   1417           os_tick = GKI_get_os_tick_count();
   1418           memcpy(nfa_hci_cb.cfg.admin_gate.session_id, (uint8_t*)&os_tick,
   1419                  (NFA_HCI_SESSION_ID_LEN / 2));
   1420           nfa_hciu_send_set_param_cmd(
   1421               NFA_HCI_ADMIN_PIPE, NFA_HCI_SESSION_IDENTITY_INDEX,
   1422               NFA_HCI_SESSION_ID_LEN,
   1423               (uint8_t*)nfa_hci_cb.cfg.admin_gate.session_id);
   1424         } else {
   1425           /* First thing is to get the session ID */
   1426           nfa_hciu_send_get_param_cmd(NFA_HCI_ADMIN_PIPE,
   1427                                       NFA_HCI_SESSION_IDENTITY_INDEX);
   1428         }
   1429         break;
   1430 
   1431       case NFA_HCI_ADM_CLEAR_ALL_PIPE:
   1432         nfa_hciu_remove_all_pipes_from_host(0);
   1433         nfa_hci_cb.cfg.admin_gate.pipe01_state = NFA_HCI_PIPE_CLOSED;
   1434         nfa_hci_cb.cfg.link_mgmt_gate.pipe00_state = NFA_HCI_PIPE_CLOSED;
   1435         nfa_hci_cb.nv_write_needed = true;
   1436 
   1437         /* Open admin */
   1438         nfa_hciu_send_open_pipe_cmd(NFA_HCI_ADMIN_PIPE);
   1439         break;
   1440     }
   1441   } else {
   1442     status =
   1443         (nfa_hci_cb.inst == NFA_HCI_ANY_OK) ? NFA_STATUS_OK : NFA_STATUS_FAILED;
   1444 
   1445     switch (nfa_hci_cb.cmd_sent) {
   1446       case NFA_HCI_ANY_SET_PARAMETER:
   1447         if (nfa_hci_cb.hci_state == NFA_HCI_STATE_APP_DEREGISTER)
   1448           nfa_hci_api_deregister(NULL);
   1449         else if (nfa_hci_cb.hci_state == NFA_HCI_STATE_REMOVE_GATE)
   1450           nfa_hci_api_dealloc_gate(NULL);
   1451         break;
   1452 
   1453       case NFA_HCI_ANY_GET_PARAMETER:
   1454         if (nfa_hci_cb.param_in_use == NFA_HCI_SESSION_IDENTITY_INDEX) {
   1455           if (!memcmp((uint8_t*)default_session, p_data,
   1456                       NFA_HCI_SESSION_ID_LEN)) {
   1457             memcpy(&nfa_hci_cb.cfg.admin_gate
   1458                         .session_id[(NFA_HCI_SESSION_ID_LEN / 2)],
   1459                    nfa_hci_cb.cfg.admin_gate.session_id,
   1460                    (NFA_HCI_SESSION_ID_LEN / 2));
   1461             os_tick = GKI_get_os_tick_count();
   1462             memcpy(nfa_hci_cb.cfg.admin_gate.session_id, (uint8_t*)&os_tick,
   1463                    (NFA_HCI_SESSION_ID_LEN / 2));
   1464             nfa_hci_cb.nv_write_needed = true;
   1465             nfa_hciu_send_set_param_cmd(
   1466                 NFA_HCI_ADMIN_PIPE, NFA_HCI_SESSION_IDENTITY_INDEX,
   1467                 NFA_HCI_SESSION_ID_LEN,
   1468                 (uint8_t*)nfa_hci_cb.cfg.admin_gate.session_id);
   1469           } else {
   1470             if (nfa_hci_cb.hci_state == NFA_HCI_STATE_APP_DEREGISTER)
   1471               nfa_hci_api_deregister(NULL);
   1472             else if (nfa_hci_cb.hci_state == NFA_HCI_STATE_REMOVE_GATE)
   1473               nfa_hci_api_dealloc_gate(NULL);
   1474           }
   1475         } else if (nfa_hci_cb.param_in_use == NFA_HCI_HOST_LIST_INDEX) {
   1476           evt_data.hosts.status = status;
   1477           evt_data.hosts.num_hosts = data_len;
   1478           memcpy(evt_data.hosts.host, p_data, data_len);
   1479 
   1480           host_count = 0;
   1481           while (host_count < NFA_HCI_MAX_HOST_IN_NETWORK) {
   1482             nfa_hci_cb.inactive_host[host_count] =
   1483                 NFA_HCI_HOST_ID_UICC0 + host_count;
   1484             host_count++;
   1485           }
   1486 
   1487           host_count = 0;
   1488           /* Collect active host in the Host Network */
   1489           while (host_count < data_len) {
   1490             host_id = (uint8_t)*p_data++;
   1491 
   1492             if ((host_id >= NFA_HCI_HOST_ID_UICC0) &&
   1493                 (host_id <
   1494                  NFA_HCI_HOST_ID_UICC0 + NFA_HCI_MAX_HOST_IN_NETWORK)) {
   1495               nfa_hci_cb.inactive_host[host_id - NFA_HCI_HOST_ID_UICC0] = 0x00;
   1496               nfa_hci_cb.reset_host[host_id - NFA_HCI_HOST_ID_UICC0] = 0x00;
   1497             }
   1498             host_count++;
   1499           }
   1500           if (nfa_hciu_is_no_host_resetting())
   1501             nfa_hci_check_pending_api_requests();
   1502           nfa_hciu_send_to_app(NFA_HCI_HOST_LIST_EVT, &evt_data,
   1503                                nfa_hci_cb.app_in_use);
   1504         }
   1505         break;
   1506 
   1507       case NFA_HCI_ADM_CREATE_PIPE:
   1508         if (status == NFA_STATUS_OK) {
   1509           STREAM_TO_UINT8(source_host, p_data);
   1510           STREAM_TO_UINT8(source_gate, p_data);
   1511           STREAM_TO_UINT8(dest_host, p_data);
   1512           STREAM_TO_UINT8(dest_gate, p_data);
   1513           STREAM_TO_UINT8(pipe, p_data);
   1514 
   1515           /* Sanity check */
   1516           if (source_gate != nfa_hci_cb.local_gate_in_use) {
   1517             NFA_TRACE_WARNING2(
   1518                 "nfa_hci_handle_admin_gate_rsp sent create pipe with gate: %u "
   1519                 "got back: %u",
   1520                 nfa_hci_cb.local_gate_in_use, source_gate);
   1521             break;
   1522           }
   1523 
   1524           nfa_hciu_add_pipe_to_gate(pipe, source_gate, dest_host, dest_gate);
   1525         }
   1526 
   1527         /* Tell the application his pipe was created or not */
   1528         evt_data.created.status = status;
   1529         evt_data.created.pipe = pipe;
   1530         evt_data.created.source_gate = source_gate;
   1531         evt_data.created.dest_host = dest_host;
   1532         evt_data.created.dest_gate = dest_gate;
   1533 
   1534         nfa_hciu_send_to_app(NFA_HCI_CREATE_PIPE_EVT, &evt_data,
   1535                              nfa_hci_cb.app_in_use);
   1536         break;
   1537 
   1538       case NFA_HCI_ADM_DELETE_PIPE:
   1539         if (status == NFA_STATUS_OK) {
   1540           nfa_hciu_release_pipe(nfa_hci_cb.pipe_in_use);
   1541 
   1542           /* If only deleting one pipe, tell the app we are done */
   1543           if (nfa_hci_cb.hci_state == NFA_HCI_STATE_IDLE) {
   1544             evt_data.deleted.status = status;
   1545             evt_data.deleted.pipe = nfa_hci_cb.pipe_in_use;
   1546 
   1547             nfa_hciu_send_to_app(NFA_HCI_DELETE_PIPE_EVT, &evt_data,
   1548                                  nfa_hci_cb.app_in_use);
   1549           } else if (nfa_hci_cb.hci_state == NFA_HCI_STATE_APP_DEREGISTER)
   1550             nfa_hci_api_deregister(NULL);
   1551           else if (nfa_hci_cb.hci_state == NFA_HCI_STATE_REMOVE_GATE)
   1552             nfa_hci_api_dealloc_gate(NULL);
   1553         } else {
   1554           /* If only deleting one pipe, tell the app we are done */
   1555           if (nfa_hci_cb.hci_state == NFA_HCI_STATE_IDLE) {
   1556             evt_data.deleted.status = status;
   1557             evt_data.deleted.pipe = nfa_hci_cb.pipe_in_use;
   1558 
   1559             nfa_hciu_send_to_app(NFA_HCI_DELETE_PIPE_EVT, &evt_data,
   1560                                  nfa_hci_cb.app_in_use);
   1561           } else if (nfa_hci_cb.hci_state == NFA_HCI_STATE_APP_DEREGISTER) {
   1562             nfa_hciu_release_pipe(nfa_hci_cb.pipe_in_use);
   1563             nfa_hci_api_deregister(NULL);
   1564           } else if (nfa_hci_cb.hci_state == NFA_HCI_STATE_REMOVE_GATE) {
   1565             nfa_hciu_release_pipe(nfa_hci_cb.pipe_in_use);
   1566             nfa_hci_api_dealloc_gate(NULL);
   1567           }
   1568         }
   1569         break;
   1570 
   1571       case NFA_HCI_ANY_OPEN_PIPE:
   1572         nfa_hci_cb.cfg.admin_gate.pipe01_state =
   1573             status ? NFA_HCI_PIPE_CLOSED : NFA_HCI_PIPE_OPENED;
   1574         nfa_hci_cb.nv_write_needed = true;
   1575         if (nfa_hci_cb.cfg.admin_gate.pipe01_state == NFA_HCI_PIPE_OPENED) {
   1576           /* First thing is to get the session ID */
   1577           nfa_hciu_send_get_param_cmd(NFA_HCI_ADMIN_PIPE,
   1578                                       NFA_HCI_SESSION_IDENTITY_INDEX);
   1579         }
   1580         break;
   1581 
   1582       case NFA_HCI_ADM_CLEAR_ALL_PIPE:
   1583         nfa_hciu_remove_all_pipes_from_host(0);
   1584         nfa_hci_cb.cfg.admin_gate.pipe01_state = NFA_HCI_PIPE_CLOSED;
   1585         nfa_hci_cb.cfg.link_mgmt_gate.pipe00_state = NFA_HCI_PIPE_CLOSED;
   1586         nfa_hci_cb.nv_write_needed = true;
   1587         /* Open admin */
   1588         nfa_hciu_send_open_pipe_cmd(NFA_HCI_ADMIN_PIPE);
   1589         break;
   1590     }
   1591   }
   1592 }
   1593 
   1594 /*******************************************************************************
   1595 **
   1596 ** Function         nfa_hci_handle_admin_gate_evt
   1597 **
   1598 ** Description      This function handles events received on admin gate
   1599 **
   1600 ** Returns          none
   1601 **
   1602 *******************************************************************************/
   1603 void nfa_hci_handle_admin_gate_evt(uint8_t* p_data) {
   1604   tNFA_HCI_EVT_DATA evt_data;
   1605   tNFA_HCI_API_GET_HOST_LIST* p_msg;
   1606 
   1607   if (nfa_hci_cb.inst != NFA_HCI_EVT_HOT_PLUG) {
   1608     NFA_TRACE_ERROR0(
   1609         "nfa_hci_handle_admin_gate_evt - Unknown event on ADMIN Pipe");
   1610     return;
   1611   }
   1612 
   1613   NFA_TRACE_DEBUG0(
   1614       "nfa_hci_handle_admin_gate_evt - HOT PLUG EVT event on ADMIN Pipe");
   1615   nfa_hci_cb.num_hot_plug_evts++;
   1616 
   1617   if ((nfa_hci_cb.hci_state == NFA_HCI_STATE_WAIT_NETWK_ENABLE) ||
   1618       (nfa_hci_cb.hci_state == NFA_HCI_STATE_RESTORE_NETWK_ENABLE)) {
   1619     /* Received Hot Plug evt while waiting for other Host in the network to
   1620      * bootup after DH host bootup is complete */
   1621     if ((nfa_hci_cb.ee_disable_disc) &&
   1622         (nfa_hci_cb.num_hot_plug_evts == (nfa_hci_cb.num_nfcee - 1)) &&
   1623         (nfa_hci_cb.num_ee_dis_req_ntf < (nfa_hci_cb.num_nfcee - 1))) {
   1624       /* Received expected number of Hot Plug event(s) before as many number of
   1625        * EE DISC REQ Ntf(s) are received */
   1626       nfa_sys_stop_timer(&nfa_hci_cb.timer);
   1627       /* Received HOT PLUG EVT(s), now wait some more time for EE DISC REQ
   1628        * Ntf(s) */
   1629       nfa_sys_start_timer(&nfa_hci_cb.timer, NFA_HCI_RSP_TIMEOUT_EVT,
   1630                           p_nfa_hci_cfg->hci_netwk_enable_timeout);
   1631     }
   1632   } else if ((nfa_hci_cb.hci_state == NFA_HCI_STATE_STARTUP) ||
   1633              (nfa_hci_cb.hci_state == NFA_HCI_STATE_RESTORE)) {
   1634     /* Received Hot Plug evt during DH host bootup */
   1635     if ((nfa_hci_cb.ee_disable_disc) &&
   1636         (nfa_hci_cb.num_hot_plug_evts == (nfa_hci_cb.num_nfcee - 1)) &&
   1637         (nfa_hci_cb.num_ee_dis_req_ntf < (nfa_hci_cb.num_nfcee - 1))) {
   1638       /* Received expected number of Hot Plug event(s) before as many number of
   1639        * EE DISC REQ Ntf(s) are received */
   1640       nfa_hci_cb.w4_hci_netwk_init = false;
   1641     }
   1642   } else {
   1643     /* Received Hot Plug evt on UICC self reset */
   1644     evt_data.rcvd_evt.evt_code = nfa_hci_cb.inst;
   1645     /* Notify all registered application with the HOT_PLUG_EVT */
   1646     nfa_hciu_send_to_all_apps(NFA_HCI_EVENT_RCVD_EVT, &evt_data);
   1647 
   1648     /* Send Get Host List after receiving any pending response */
   1649     p_msg = (tNFA_HCI_API_GET_HOST_LIST*)GKI_getbuf(
   1650         sizeof(tNFA_HCI_API_GET_HOST_LIST));
   1651     if (p_msg != NULL) {
   1652       p_msg->hdr.event = NFA_HCI_API_GET_HOST_LIST_EVT;
   1653       /* Set Invalid handle to identify this Get Host List command is internal
   1654        */
   1655       p_msg->hci_handle = NFA_HANDLE_INVALID;
   1656 
   1657       nfa_sys_sendmsg(p_msg);
   1658     }
   1659   }
   1660 }
   1661 
   1662 /*******************************************************************************
   1663 **
   1664 ** Function         nfa_hci_handle_dyn_pipe_pkt
   1665 **
   1666 ** Description      This function handles data received via dynamic pipe
   1667 **
   1668 ** Returns          none
   1669 **
   1670 *******************************************************************************/
   1671 void nfa_hci_handle_dyn_pipe_pkt(uint8_t pipe_id, uint8_t* p_data,
   1672                                  uint16_t data_len) {
   1673   tNFA_HCI_DYN_PIPE* p_pipe = nfa_hciu_find_pipe_by_pid(pipe_id);
   1674   tNFA_HCI_DYN_GATE* p_gate;
   1675 
   1676   if (p_pipe == NULL) {
   1677     /* Invalid pipe ID */
   1678     NFA_TRACE_ERROR1("nfa_hci_handle_dyn_pipe_pkt - Unknown pipe %d", pipe_id);
   1679     if (nfa_hci_cb.type == NFA_HCI_COMMAND_TYPE)
   1680       nfa_hciu_send_msg(pipe_id, NFA_HCI_RESPONSE_TYPE, NFA_HCI_ANY_E_NOK, 0,
   1681                         NULL);
   1682     return;
   1683   }
   1684 
   1685   if (p_pipe->local_gate == NFA_HCI_IDENTITY_MANAGEMENT_GATE) {
   1686     nfa_hci_handle_identity_mgmt_gate_pkt(p_data, p_pipe);
   1687   } else if (p_pipe->local_gate == NFA_HCI_LOOP_BACK_GATE) {
   1688     nfa_hci_handle_loopback_gate_pkt(p_data, data_len, p_pipe);
   1689   } else if (p_pipe->local_gate == NFA_HCI_CONNECTIVITY_GATE) {
   1690     nfa_hci_handle_connectivity_gate_pkt(p_data, data_len, p_pipe);
   1691   } else {
   1692     p_gate = nfa_hciu_find_gate_by_gid(p_pipe->local_gate);
   1693     if (p_gate == NULL) {
   1694       NFA_TRACE_ERROR1(
   1695           "nfa_hci_handle_dyn_pipe_pkt - Pipe's gate %d is corrupt",
   1696           p_pipe->local_gate);
   1697       if (nfa_hci_cb.type == NFA_HCI_COMMAND_TYPE)
   1698         nfa_hciu_send_msg(pipe_id, NFA_HCI_RESPONSE_TYPE, NFA_HCI_ANY_E_NOK, 0,
   1699                           NULL);
   1700       return;
   1701     }
   1702 
   1703     /* Check if data packet is a command, response or event */
   1704     switch (nfa_hci_cb.type) {
   1705       case NFA_HCI_COMMAND_TYPE:
   1706         nfa_hci_handle_generic_gate_cmd(p_data, (uint8_t)data_len, p_gate,
   1707                                         p_pipe);
   1708         break;
   1709 
   1710       case NFA_HCI_RESPONSE_TYPE:
   1711         nfa_hci_handle_generic_gate_rsp(p_data, (uint8_t)data_len, p_gate,
   1712                                         p_pipe);
   1713         break;
   1714 
   1715       case NFA_HCI_EVENT_TYPE:
   1716         nfa_hci_handle_generic_gate_evt(p_data, data_len, p_gate, p_pipe);
   1717         break;
   1718     }
   1719   }
   1720 }
   1721 
   1722 /*******************************************************************************
   1723 **
   1724 ** Function         nfa_hci_handle_identity_mgmt_gate_pkt
   1725 **
   1726 ** Description      This function handles incoming Identity Management gate hci
   1727 **                  commands
   1728 **
   1729 ** Returns          none
   1730 **
   1731 *******************************************************************************/
   1732 static void nfa_hci_handle_identity_mgmt_gate_pkt(uint8_t* p_data,
   1733                                                   tNFA_HCI_DYN_PIPE* p_pipe) {
   1734   uint8_t data[20];
   1735   uint8_t index;
   1736   uint8_t gate_rsp[3 + NFA_HCI_MAX_GATE_CB], num_gates;
   1737   uint16_t rsp_len = 0;
   1738   uint8_t* p_rsp = data;
   1739   tNFA_HCI_RESPONSE response = NFA_HCI_ANY_OK;
   1740 
   1741   /* We never send commands on a pipe where the local gate is the identity
   1742    * management
   1743    * gate, so only commands should be processed.
   1744    */
   1745   if (nfa_hci_cb.type != NFA_HCI_COMMAND_TYPE) return;
   1746 
   1747   switch (nfa_hci_cb.inst) {
   1748     case NFA_HCI_ANY_GET_PARAMETER:
   1749       index = *(p_data++);
   1750       if (p_pipe->pipe_state == NFA_HCI_PIPE_OPENED) {
   1751         switch (index) {
   1752           case NFA_HCI_VERSION_SW_INDEX:
   1753             data[0] = (uint8_t)((NFA_HCI_VERSION_SW >> 16) & 0xFF);
   1754             data[1] = (uint8_t)((NFA_HCI_VERSION_SW >> 8) & 0xFF);
   1755             data[2] = (uint8_t)((NFA_HCI_VERSION_SW)&0xFF);
   1756             rsp_len = 3;
   1757             break;
   1758 
   1759           case NFA_HCI_HCI_VERSION_INDEX:
   1760             data[0] = NFA_HCI_VERSION;
   1761             rsp_len = 1;
   1762             break;
   1763 
   1764           case NFA_HCI_VERSION_HW_INDEX:
   1765             data[0] = (uint8_t)((NFA_HCI_VERSION_HW >> 16) & 0xFF);
   1766             data[1] = (uint8_t)((NFA_HCI_VERSION_HW >> 8) & 0xFF);
   1767             data[2] = (uint8_t)((NFA_HCI_VERSION_HW)&0xFF);
   1768             rsp_len = 3;
   1769             break;
   1770 
   1771           case NFA_HCI_VENDOR_NAME_INDEX:
   1772             memcpy(data, NFA_HCI_VENDOR_NAME, strlen(NFA_HCI_VENDOR_NAME));
   1773             rsp_len = (uint8_t)strlen(NFA_HCI_VENDOR_NAME);
   1774             break;
   1775 
   1776           case NFA_HCI_MODEL_ID_INDEX:
   1777             data[0] = NFA_HCI_MODEL_ID;
   1778             rsp_len = 1;
   1779             break;
   1780 
   1781           case NFA_HCI_GATES_LIST_INDEX:
   1782             gate_rsp[0] = NFA_HCI_LOOP_BACK_GATE;
   1783             gate_rsp[1] = NFA_HCI_IDENTITY_MANAGEMENT_GATE;
   1784             gate_rsp[2] = NFA_HCI_CONNECTIVITY_GATE;
   1785             num_gates = nfa_hciu_get_allocated_gate_list(&gate_rsp[3]);
   1786             rsp_len = num_gates + 3;
   1787             p_rsp = gate_rsp;
   1788             break;
   1789 
   1790           default:
   1791             response = NFA_HCI_ANY_E_NOK;
   1792             break;
   1793         }
   1794       } else {
   1795         response = NFA_HCI_ANY_E_PIPE_NOT_OPENED;
   1796       }
   1797       break;
   1798 
   1799     case NFA_HCI_ANY_OPEN_PIPE:
   1800       data[0] = 0;
   1801       rsp_len = 1;
   1802       p_pipe->pipe_state = NFA_HCI_PIPE_OPENED;
   1803       break;
   1804 
   1805     case NFA_HCI_ANY_CLOSE_PIPE:
   1806       p_pipe->pipe_state = NFA_HCI_PIPE_CLOSED;
   1807       break;
   1808 
   1809     default:
   1810       response = NFA_HCI_ANY_E_CMD_NOT_SUPPORTED;
   1811       break;
   1812   }
   1813 
   1814   nfa_hciu_send_msg(p_pipe->pipe_id, NFA_HCI_RESPONSE_TYPE, response, rsp_len,
   1815                     p_rsp);
   1816 }
   1817 
   1818 /*******************************************************************************
   1819 **
   1820 ** Function         nfa_hci_handle_generic_gate_cmd
   1821 **
   1822 ** Description      This function handles all generic gates (excluding
   1823 **                  connectivity gate) commands
   1824 **
   1825 ** Returns          none
   1826 **
   1827 *******************************************************************************/
   1828 static void nfa_hci_handle_generic_gate_cmd(uint8_t* p_data, uint8_t data_len,
   1829                                             tNFA_HCI_DYN_GATE* p_gate,
   1830                                             tNFA_HCI_DYN_PIPE* p_pipe) {
   1831   tNFA_HCI_EVT_DATA evt_data;
   1832   tNFA_HANDLE app_handle = nfa_hciu_get_pipe_owner(p_pipe->pipe_id);
   1833 
   1834   switch (nfa_hci_cb.inst) {
   1835     case NFA_HCI_ANY_SET_PARAMETER:
   1836       evt_data.registry.pipe = p_pipe->pipe_id;
   1837       evt_data.registry.index = *p_data++;
   1838       if (data_len > 0) data_len--;
   1839       evt_data.registry.data_len = data_len;
   1840 
   1841       memcpy(evt_data.registry.reg_data, p_data, data_len);
   1842 
   1843       nfa_hciu_send_to_app(NFA_HCI_SET_REG_CMD_EVT, &evt_data, app_handle);
   1844       break;
   1845 
   1846     case NFA_HCI_ANY_GET_PARAMETER:
   1847       evt_data.registry.pipe = p_pipe->pipe_id;
   1848       evt_data.registry.index = *p_data;
   1849       evt_data.registry.data_len = 0;
   1850 
   1851       nfa_hciu_send_to_app(NFA_HCI_GET_REG_CMD_EVT, &evt_data, app_handle);
   1852       break;
   1853 
   1854     case NFA_HCI_ANY_OPEN_PIPE:
   1855       nfa_hci_handle_pipe_open_close_cmd(p_pipe);
   1856 
   1857       evt_data.opened.pipe = p_pipe->pipe_id;
   1858       evt_data.opened.status = NFA_STATUS_OK;
   1859 
   1860       nfa_hciu_send_to_app(NFA_HCI_OPEN_PIPE_EVT, &evt_data, app_handle);
   1861       break;
   1862 
   1863     case NFA_HCI_ANY_CLOSE_PIPE:
   1864       nfa_hci_handle_pipe_open_close_cmd(p_pipe);
   1865 
   1866       evt_data.closed.pipe = p_pipe->pipe_id;
   1867       evt_data.opened.status = NFA_STATUS_OK;
   1868 
   1869       nfa_hciu_send_to_app(NFA_HCI_CLOSE_PIPE_EVT, &evt_data, app_handle);
   1870       break;
   1871 
   1872     default:
   1873       /* Could be application specific command, pass it on */
   1874       evt_data.cmd_rcvd.status = NFA_STATUS_OK;
   1875       evt_data.cmd_rcvd.pipe = p_pipe->pipe_id;
   1876       ;
   1877       evt_data.cmd_rcvd.cmd_code = nfa_hci_cb.inst;
   1878       evt_data.cmd_rcvd.cmd_len = data_len;
   1879 
   1880       if (data_len <= NFA_MAX_HCI_CMD_LEN)
   1881         memcpy(evt_data.cmd_rcvd.cmd_data, p_data, data_len);
   1882 
   1883       nfa_hciu_send_to_app(NFA_HCI_CMD_RCVD_EVT, &evt_data, app_handle);
   1884       break;
   1885   }
   1886 }
   1887 
   1888 /*******************************************************************************
   1889 **
   1890 ** Function         nfa_hci_handle_generic_gate_rsp
   1891 **
   1892 ** Description      This function handles all generic gates (excluding
   1893 **                  connectivity) response
   1894 **
   1895 ** Returns          none
   1896 **
   1897 *******************************************************************************/
   1898 static void nfa_hci_handle_generic_gate_rsp(uint8_t* p_data, uint8_t data_len,
   1899                                             tNFA_HCI_DYN_GATE* p_gate,
   1900                                             tNFA_HCI_DYN_PIPE* p_pipe) {
   1901   tNFA_HCI_EVT_DATA evt_data;
   1902   tNFA_STATUS status = NFA_STATUS_OK;
   1903 
   1904   if (nfa_hci_cb.inst != NFA_HCI_ANY_OK) status = NFA_STATUS_FAILED;
   1905 
   1906   if (nfa_hci_cb.cmd_sent == NFA_HCI_ANY_OPEN_PIPE) {
   1907     if (status == NFA_STATUS_OK) p_pipe->pipe_state = NFA_HCI_PIPE_OPENED;
   1908 
   1909     nfa_hci_cb.nv_write_needed = true;
   1910     /* Tell application */
   1911     evt_data.opened.status = status;
   1912     evt_data.opened.pipe = p_pipe->pipe_id;
   1913 
   1914     nfa_hciu_send_to_app(NFA_HCI_OPEN_PIPE_EVT, &evt_data,
   1915                          nfa_hci_cb.app_in_use);
   1916   } else if (nfa_hci_cb.cmd_sent == NFA_HCI_ANY_CLOSE_PIPE) {
   1917     p_pipe->pipe_state = NFA_HCI_PIPE_CLOSED;
   1918 
   1919     nfa_hci_cb.nv_write_needed = true;
   1920     /* Tell application */
   1921     evt_data.opened.status = status;
   1922     ;
   1923     evt_data.opened.pipe = p_pipe->pipe_id;
   1924 
   1925     nfa_hciu_send_to_app(NFA_HCI_CLOSE_PIPE_EVT, &evt_data,
   1926                          nfa_hci_cb.app_in_use);
   1927   } else if (nfa_hci_cb.cmd_sent == NFA_HCI_ANY_GET_PARAMETER) {
   1928     /* Tell application */
   1929     evt_data.registry.status = status;
   1930     evt_data.registry.pipe = p_pipe->pipe_id;
   1931     evt_data.registry.data_len = data_len;
   1932     evt_data.registry.index = nfa_hci_cb.param_in_use;
   1933 
   1934     memcpy(evt_data.registry.reg_data, p_data, data_len);
   1935 
   1936     nfa_hciu_send_to_app(NFA_HCI_GET_REG_RSP_EVT, &evt_data,
   1937                          nfa_hci_cb.app_in_use);
   1938   } else if (nfa_hci_cb.cmd_sent == NFA_HCI_ANY_SET_PARAMETER) {
   1939     /* Tell application */
   1940     evt_data.registry.status = status;
   1941     ;
   1942     evt_data.registry.pipe = p_pipe->pipe_id;
   1943 
   1944     nfa_hciu_send_to_app(NFA_HCI_SET_REG_RSP_EVT, &evt_data,
   1945                          nfa_hci_cb.app_in_use);
   1946   } else {
   1947     /* Could be a response to application specific command sent, pass it on */
   1948     evt_data.rsp_rcvd.status = NFA_STATUS_OK;
   1949     evt_data.rsp_rcvd.pipe = p_pipe->pipe_id;
   1950     ;
   1951     evt_data.rsp_rcvd.rsp_code = nfa_hci_cb.inst;
   1952     evt_data.rsp_rcvd.rsp_len = data_len;
   1953 
   1954     if (data_len <= NFA_MAX_HCI_RSP_LEN)
   1955       memcpy(evt_data.rsp_rcvd.rsp_data, p_data, data_len);
   1956 
   1957     nfa_hciu_send_to_app(NFA_HCI_RSP_RCVD_EVT, &evt_data,
   1958                          nfa_hci_cb.app_in_use);
   1959   }
   1960 }
   1961 
   1962 /*******************************************************************************
   1963 **
   1964 ** Function         nfa_hci_handle_connectivity_gate_pkt
   1965 **
   1966 ** Description      This function handles incoming connectivity gate packets
   1967 **
   1968 ** Returns          none
   1969 **
   1970 *******************************************************************************/
   1971 static void nfa_hci_handle_connectivity_gate_pkt(uint8_t* p_data,
   1972                                                  uint16_t data_len,
   1973                                                  tNFA_HCI_DYN_PIPE* p_pipe) {
   1974   tNFA_HCI_EVT_DATA evt_data;
   1975 
   1976   if (nfa_hci_cb.type == NFA_HCI_COMMAND_TYPE) {
   1977     switch (nfa_hci_cb.inst) {
   1978       case NFA_HCI_ANY_OPEN_PIPE:
   1979       case NFA_HCI_ANY_CLOSE_PIPE:
   1980         nfa_hci_handle_pipe_open_close_cmd(p_pipe);
   1981         break;
   1982 
   1983       case NFA_HCI_CON_PRO_HOST_REQUEST:
   1984         /* A request to the DH to activate another host. This is not supported
   1985          * for */
   1986         /* now, we will implement it when the spec is clearer and UICCs need it.
   1987          */
   1988         nfa_hciu_send_msg(p_pipe->pipe_id, NFA_HCI_RESPONSE_TYPE,
   1989                           NFA_HCI_ANY_E_CMD_NOT_SUPPORTED, 0, NULL);
   1990         break;
   1991 
   1992       default:
   1993         nfa_hciu_send_msg(p_pipe->pipe_id, NFA_HCI_RESPONSE_TYPE,
   1994                           NFA_HCI_ANY_E_CMD_NOT_SUPPORTED, 0, NULL);
   1995         break;
   1996     }
   1997   } else if (nfa_hci_cb.type == NFA_HCI_RESPONSE_TYPE) {
   1998     if ((nfa_hci_cb.cmd_sent == NFA_HCI_ANY_OPEN_PIPE) &&
   1999         (nfa_hci_cb.inst == NFA_HCI_ANY_OK))
   2000       p_pipe->pipe_state = NFA_HCI_PIPE_OPENED;
   2001     else if (nfa_hci_cb.cmd_sent == NFA_HCI_ANY_CLOSE_PIPE)
   2002       p_pipe->pipe_state = NFA_HCI_PIPE_CLOSED;
   2003 
   2004     /* Could be a response to application specific command sent, pass it on */
   2005     evt_data.rsp_rcvd.status = NFA_STATUS_OK;
   2006     evt_data.rsp_rcvd.pipe = p_pipe->pipe_id;
   2007     ;
   2008     evt_data.rsp_rcvd.rsp_code = nfa_hci_cb.inst;
   2009     evt_data.rsp_rcvd.rsp_len = data_len;
   2010 
   2011     if (data_len <= NFA_MAX_HCI_RSP_LEN)
   2012       memcpy(evt_data.rsp_rcvd.rsp_data, p_data, data_len);
   2013 
   2014     nfa_hciu_send_to_app(NFA_HCI_RSP_RCVD_EVT, &evt_data,
   2015                          nfa_hci_cb.app_in_use);
   2016   } else if (nfa_hci_cb.type == NFA_HCI_EVENT_TYPE) {
   2017     evt_data.rcvd_evt.pipe = p_pipe->pipe_id;
   2018     evt_data.rcvd_evt.evt_code = nfa_hci_cb.inst;
   2019     evt_data.rcvd_evt.evt_len = data_len;
   2020     evt_data.rcvd_evt.p_evt_buf = p_data;
   2021 
   2022     /* notify NFA_HCI_EVENT_RCVD_EVT to the application */
   2023     nfa_hciu_send_to_apps_handling_connectivity_evts(NFA_HCI_EVENT_RCVD_EVT,
   2024                                                      &evt_data);
   2025   }
   2026 }
   2027 
   2028 /*******************************************************************************
   2029 **
   2030 ** Function         nfa_hci_handle_loopback_gate_pkt
   2031 **
   2032 ** Description      This function handles incoming loopback gate hci events
   2033 **
   2034 ** Returns          none
   2035 **
   2036 *******************************************************************************/
   2037 static void nfa_hci_handle_loopback_gate_pkt(uint8_t* p_data, uint16_t data_len,
   2038                                              tNFA_HCI_DYN_PIPE* p_pipe) {
   2039   uint8_t data[1];
   2040   uint8_t rsp_len = 0;
   2041   tNFA_HCI_RESPONSE response = NFA_HCI_ANY_OK;
   2042   tNFA_HCI_EVT_DATA evt_data;
   2043 
   2044   /* Check if data packet is a command, response or event */
   2045   if (nfa_hci_cb.type == NFA_HCI_COMMAND_TYPE) {
   2046     if (nfa_hci_cb.inst == NFA_HCI_ANY_OPEN_PIPE) {
   2047       data[0] = 0;
   2048       rsp_len = 1;
   2049       p_pipe->pipe_state = NFA_HCI_PIPE_OPENED;
   2050     } else if (nfa_hci_cb.inst == NFA_HCI_ANY_CLOSE_PIPE) {
   2051       p_pipe->pipe_state = NFA_HCI_PIPE_CLOSED;
   2052     } else
   2053       response = NFA_HCI_ANY_E_CMD_NOT_SUPPORTED;
   2054 
   2055     nfa_hciu_send_msg(p_pipe->pipe_id, NFA_HCI_RESPONSE_TYPE, response, rsp_len,
   2056                       data);
   2057   } else if (nfa_hci_cb.type == NFA_HCI_RESPONSE_TYPE) {
   2058     if ((nfa_hci_cb.cmd_sent == NFA_HCI_ANY_OPEN_PIPE) &&
   2059         (nfa_hci_cb.inst == NFA_HCI_ANY_OK))
   2060       p_pipe->pipe_state = NFA_HCI_PIPE_OPENED;
   2061     else if (nfa_hci_cb.cmd_sent == NFA_HCI_ANY_CLOSE_PIPE)
   2062       p_pipe->pipe_state = NFA_HCI_PIPE_CLOSED;
   2063 
   2064     /* Could be a response to application specific command sent, pass it on */
   2065     evt_data.rsp_rcvd.status = NFA_STATUS_OK;
   2066     evt_data.rsp_rcvd.pipe = p_pipe->pipe_id;
   2067     ;
   2068     evt_data.rsp_rcvd.rsp_code = nfa_hci_cb.inst;
   2069     evt_data.rsp_rcvd.rsp_len = data_len;
   2070 
   2071     if (data_len <= NFA_MAX_HCI_RSP_LEN)
   2072       memcpy(evt_data.rsp_rcvd.rsp_data, p_data, data_len);
   2073 
   2074     nfa_hciu_send_to_app(NFA_HCI_RSP_RCVD_EVT, &evt_data,
   2075                          nfa_hci_cb.app_in_use);
   2076   } else if (nfa_hci_cb.type == NFA_HCI_EVENT_TYPE) {
   2077     if (nfa_hci_cb.w4_rsp_evt) {
   2078       evt_data.rcvd_evt.pipe = p_pipe->pipe_id;
   2079       evt_data.rcvd_evt.evt_code = nfa_hci_cb.inst;
   2080       evt_data.rcvd_evt.evt_len = data_len;
   2081       evt_data.rcvd_evt.p_evt_buf = p_data;
   2082 
   2083       nfa_hciu_send_to_app(NFA_HCI_EVENT_RCVD_EVT, &evt_data,
   2084                            nfa_hci_cb.app_in_use);
   2085     } else if (nfa_hci_cb.inst == NFA_HCI_EVT_POST_DATA) {
   2086       /* Send back the same data we got */
   2087       nfa_hciu_send_msg(p_pipe->pipe_id, NFA_HCI_EVENT_TYPE,
   2088                         NFA_HCI_EVT_POST_DATA, data_len, p_data);
   2089     }
   2090   }
   2091 }
   2092 
   2093 /*******************************************************************************
   2094 **
   2095 ** Function         nfa_hci_handle_generic_gate_evt
   2096 **
   2097 ** Description      This function handles incoming Generic gate hci events
   2098 **
   2099 ** Returns          none
   2100 **
   2101 *******************************************************************************/
   2102 static void nfa_hci_handle_generic_gate_evt(uint8_t* p_data, uint16_t data_len,
   2103                                             tNFA_HCI_DYN_GATE* p_gate,
   2104                                             tNFA_HCI_DYN_PIPE* p_pipe) {
   2105   tNFA_HCI_EVT_DATA evt_data;
   2106 
   2107   evt_data.rcvd_evt.pipe = p_pipe->pipe_id;
   2108   evt_data.rcvd_evt.evt_code = nfa_hci_cb.inst;
   2109   evt_data.rcvd_evt.evt_len = data_len;
   2110 
   2111   if (nfa_hci_cb.assembly_failed)
   2112     evt_data.rcvd_evt.status = NFA_STATUS_BUFFER_FULL;
   2113   else
   2114     evt_data.rcvd_evt.status = NFA_STATUS_OK;
   2115 
   2116   evt_data.rcvd_evt.p_evt_buf = p_data;
   2117   nfa_hci_cb.rsp_buf_size = 0;
   2118   nfa_hci_cb.p_rsp_buf = NULL;
   2119 
   2120   /* notify NFA_HCI_EVENT_RCVD_EVT to the application */
   2121   nfa_hciu_send_to_app(NFA_HCI_EVENT_RCVD_EVT, &evt_data, p_gate->gate_owner);
   2122 }
   2123