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 
     26 #include <android-base/stringprintf.h>
     27 #include <base/logging.h>
     28 
     29 #include "nfa_dm_int.h"
     30 #include "nfa_hci_api.h"
     31 #include "nfa_hci_defs.h"
     32 #include "nfa_hci_int.h"
     33 
     34 using android::base::StringPrintf;
     35 
     36 extern bool nfc_debug_enabled;
     37 
     38 /* Static local functions       */
     39 static void nfa_hci_api_register(tNFA_HCI_EVENT_DATA* p_evt_data);
     40 static void nfa_hci_api_get_gate_pipe_list(tNFA_HCI_EVENT_DATA* p_evt_data);
     41 static void nfa_hci_api_alloc_gate(tNFA_HCI_EVENT_DATA* p_evt_data);
     42 static void nfa_hci_api_get_host_list(tNFA_HCI_EVENT_DATA* p_evt_data);
     43 static bool nfa_hci_api_get_reg_value(tNFA_HCI_EVENT_DATA* p_evt_data);
     44 static bool nfa_hci_api_set_reg_value(tNFA_HCI_EVENT_DATA* p_evt_data);
     45 static bool nfa_hci_api_create_pipe(tNFA_HCI_EVENT_DATA* p_evt_data);
     46 static void nfa_hci_api_open_pipe(tNFA_HCI_EVENT_DATA* p_evt_data);
     47 static void nfa_hci_api_close_pipe(tNFA_HCI_EVENT_DATA* p_evt_data);
     48 static void nfa_hci_api_delete_pipe(tNFA_HCI_EVENT_DATA* p_evt_data);
     49 static bool nfa_hci_api_send_event(tNFA_HCI_EVENT_DATA* p_evt_data);
     50 static bool nfa_hci_api_send_cmd(tNFA_HCI_EVENT_DATA* p_evt_data);
     51 static void nfa_hci_api_send_rsp(tNFA_HCI_EVENT_DATA* p_evt_data);
     52 static void nfa_hci_api_add_static_pipe(tNFA_HCI_EVENT_DATA* p_evt_data);
     53 
     54 static void nfa_hci_handle_identity_mgmt_gate_pkt(uint8_t* p_data,
     55                                                   tNFA_HCI_DYN_PIPE* p_pipe);
     56 static void nfa_hci_handle_loopback_gate_pkt(uint8_t* p_data, uint16_t data_len,
     57                                              tNFA_HCI_DYN_PIPE* p_pipe);
     58 static void nfa_hci_handle_connectivity_gate_pkt(uint8_t* p_data,
     59                                                  uint16_t data_len,
     60                                                  tNFA_HCI_DYN_PIPE* p_pipe);
     61 static void nfa_hci_handle_generic_gate_cmd(uint8_t* p_data, uint8_t data_len,
     62                                             tNFA_HCI_DYN_PIPE* p_pipe);
     63 static void nfa_hci_handle_generic_gate_rsp(uint8_t* p_data, uint8_t data_len,
     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         LOG(ERROR) << StringPrintf("Unknown event: 0x%04x", p_msg->event);
    212         break;
    213     }
    214 
    215     GKI_freebuf(p_msg);
    216   }
    217 }
    218 
    219 /*******************************************************************************
    220 **
    221 ** Function         nfa_hci_api_register
    222 **
    223 ** Description      action function to register the events for the given AID
    224 **
    225 ** Returns          None
    226 **
    227 *******************************************************************************/
    228 static void nfa_hci_api_register(tNFA_HCI_EVENT_DATA* p_evt_data) {
    229   tNFA_HCI_EVT_DATA evt_data;
    230   char* p_app_name = p_evt_data->app_info.app_name;
    231   tNFA_HCI_CBACK* p_cback = p_evt_data->app_info.p_cback;
    232   int xx, yy;
    233   uint8_t num_gates = 0, num_pipes = 0;
    234   tNFA_HCI_DYN_GATE* pg = nfa_hci_cb.cfg.dyn_gates;
    235 
    236   /* First, see if the application was already registered */
    237   for (xx = 0; xx < NFA_HCI_MAX_APP_CB; xx++) {
    238     if ((nfa_hci_cb.cfg.reg_app_names[xx][0] != 0) &&
    239         !strncmp(p_app_name, &nfa_hci_cb.cfg.reg_app_names[xx][0],
    240                  strlen(p_app_name))) {
    241       DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    242           "nfa_hci_api_register (%s)  Reusing: %u", p_app_name, xx);
    243       break;
    244     }
    245   }
    246 
    247   if (xx != NFA_HCI_MAX_APP_CB) {
    248     nfa_hci_cb.app_in_use = (tNFA_HANDLE)(xx | NFA_HANDLE_GROUP_HCI);
    249     /* The app was registered, find the number of gates and pipes associated to
    250      * the app */
    251 
    252     for (yy = 0; yy < NFA_HCI_MAX_GATE_CB; yy++, pg++) {
    253       if (pg->gate_owner == nfa_hci_cb.app_in_use) {
    254         num_gates++;
    255         num_pipes += nfa_hciu_count_pipes_on_gate(pg);
    256       }
    257     }
    258   } else {
    259     /* Not registered, look for a free entry */
    260     for (xx = 0; xx < NFA_HCI_MAX_APP_CB; xx++) {
    261       if (nfa_hci_cb.cfg.reg_app_names[xx][0] == 0) {
    262         memset(&nfa_hci_cb.cfg.reg_app_names[xx][0], 0,
    263                sizeof(nfa_hci_cb.cfg.reg_app_names[xx]));
    264         strncpy(&nfa_hci_cb.cfg.reg_app_names[xx][0], p_app_name,
    265                 NFA_MAX_HCI_APP_NAME_LEN);
    266         nfa_hci_cb.nv_write_needed = true;
    267         DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    268             "nfa_hci_api_register (%s)  Allocated: %u", p_app_name, xx);
    269         break;
    270       }
    271     }
    272 
    273     if (xx == NFA_HCI_MAX_APP_CB) {
    274       LOG(ERROR) << StringPrintf("nfa_hci_api_register (%s)  NO ENTRIES",
    275                                  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         DLOG_IF(INFO, nfc_debug_enabled)
    321             << StringPrintf("nfa_hci_api_deregister (%s) inx: %u",
    322                             p_evt_data->app_info.app_name, xx);
    323         break;
    324       }
    325     }
    326 
    327     if (xx == NFA_HCI_MAX_APP_CB) {
    328       LOG(WARNING) << StringPrintf("Unknown app: %s",
    329                                    p_evt_data->app_info.app_name);
    330       return;
    331     }
    332     nfa_hci_cb.app_in_use = (tNFA_HANDLE)(xx | NFA_HANDLE_GROUP_HCI);
    333     p_cback = nfa_hci_cb.p_app_cback[xx];
    334   } else {
    335     nfa_sys_stop_timer(&nfa_hci_cb.timer);
    336     /* We are recursing through deleting all the app's pipes and gates */
    337     p_cback = nfa_hci_cb.p_app_cback[nfa_hci_cb.app_in_use & NFA_HANDLE_MASK];
    338   }
    339 
    340   /* See if any pipe is owned by this app */
    341   if (nfa_hciu_find_pipe_by_owner(nfa_hci_cb.app_in_use) == NULL) {
    342     /* No pipes, release all gates owned by this app */
    343     while ((p_gate = nfa_hciu_find_gate_by_owner(nfa_hci_cb.app_in_use)) !=
    344            NULL)
    345       nfa_hciu_release_gate(p_gate->gate_id);
    346 
    347     memset(&nfa_hci_cb.cfg
    348                 .reg_app_names[nfa_hci_cb.app_in_use & NFA_HANDLE_MASK][0],
    349            0, NFA_MAX_HCI_APP_NAME_LEN + 1);
    350     nfa_hci_cb.p_app_cback[nfa_hci_cb.app_in_use & NFA_HANDLE_MASK] = NULL;
    351 
    352     nfa_hci_cb.nv_write_needed = true;
    353 
    354     evt_data.hci_deregister.status = NFC_STATUS_OK;
    355 
    356     if (nfa_hci_cb.hci_state == NFA_HCI_STATE_APP_DEREGISTER)
    357       nfa_hci_cb.hci_state = NFA_HCI_STATE_IDLE;
    358 
    359     /* notify NFA_HCI_DEREGISTER_EVT to the application */
    360     if (p_cback) p_cback(NFA_HCI_DEREGISTER_EVT, &evt_data);
    361   } else if ((p_pipe = nfa_hciu_find_active_pipe_by_owner(
    362                   nfa_hci_cb.app_in_use)) == NULL) {
    363     /* No pipes, release all gates owned by this app */
    364     while ((p_gate = nfa_hciu_find_gate_with_nopipes_by_owner(
    365                 nfa_hci_cb.app_in_use)) != NULL)
    366       nfa_hciu_release_gate(p_gate->gate_id);
    367 
    368     nfa_hci_cb.p_app_cback[nfa_hci_cb.app_in_use & NFA_HANDLE_MASK] = NULL;
    369 
    370     nfa_hci_cb.nv_write_needed = true;
    371 
    372     evt_data.hci_deregister.status = NFC_STATUS_FAILED;
    373 
    374     if (nfa_hci_cb.hci_state == NFA_HCI_STATE_APP_DEREGISTER)
    375       nfa_hci_cb.hci_state = NFA_HCI_STATE_IDLE;
    376 
    377     /* notify NFA_HCI_DEREGISTER_EVT to the application */
    378     if (p_cback) p_cback(NFA_HCI_DEREGISTER_EVT, &evt_data);
    379   } else {
    380     /* Delete all active pipes created for the application before de registering
    381     **/
    382     nfa_hci_cb.hci_state = NFA_HCI_STATE_APP_DEREGISTER;
    383 
    384     nfa_hciu_send_delete_pipe_cmd(p_pipe->pipe_id);
    385   }
    386 }
    387 
    388 /*******************************************************************************
    389 **
    390 ** Function         nfa_hci_api_get_gate_pipe_list
    391 **
    392 ** Description      action function to get application allocated gates and
    393 **                  application created pipes
    394 **
    395 ** Returns          None
    396 **
    397 *******************************************************************************/
    398 static void nfa_hci_api_get_gate_pipe_list(tNFA_HCI_EVENT_DATA* p_evt_data) {
    399   tNFA_HCI_EVT_DATA evt_data;
    400   int xx, yy;
    401   tNFA_HCI_DYN_GATE* pg = nfa_hci_cb.cfg.dyn_gates;
    402   tNFA_HCI_DYN_PIPE* pp = nfa_hci_cb.cfg.dyn_pipes;
    403 
    404   evt_data.gates_pipes.num_gates = 0;
    405   evt_data.gates_pipes.num_pipes = 0;
    406 
    407   for (xx = 0; xx < NFA_HCI_MAX_GATE_CB; xx++, pg++) {
    408     if (pg->gate_owner == p_evt_data->get_gate_pipe_list.hci_handle) {
    409       evt_data.gates_pipes.gate[evt_data.gates_pipes.num_gates++] = pg->gate_id;
    410 
    411       pp = nfa_hci_cb.cfg.dyn_pipes;
    412 
    413       /* Loop through looking for a match */
    414       for (yy = 0; yy < NFA_HCI_MAX_PIPE_CB; yy++, pp++) {
    415         if (pp->local_gate == pg->gate_id)
    416           evt_data.gates_pipes.pipe[evt_data.gates_pipes.num_pipes++] =
    417               *(tNFA_HCI_PIPE_INFO*)pp;
    418       }
    419     }
    420   }
    421 
    422   evt_data.gates_pipes.num_uicc_created_pipes = 0;
    423   /* Loop through all pipes that are connected to connectivity gate */
    424   for (xx = 0, pp = nfa_hci_cb.cfg.dyn_pipes; xx < NFA_HCI_MAX_PIPE_CB;
    425        xx++, pp++) {
    426     if (pp->pipe_id != 0 && pp->local_gate == NFA_HCI_CONNECTIVITY_GATE) {
    427       memcpy(&evt_data.gates_pipes.uicc_created_pipe
    428                   [evt_data.gates_pipes.num_uicc_created_pipes++],
    429              pp, sizeof(tNFA_HCI_PIPE_INFO));
    430     } else if (pp->pipe_id != 0 && pp->local_gate == NFA_HCI_LOOP_BACK_GATE) {
    431       memcpy(&evt_data.gates_pipes.uicc_created_pipe
    432                   [evt_data.gates_pipes.num_uicc_created_pipes++],
    433              pp, sizeof(tNFA_HCI_PIPE_INFO));
    434     } else if (pp->pipe_id >= NFA_HCI_FIRST_DYNAMIC_PIPE &&
    435                pp->pipe_id <= NFA_HCI_LAST_DYNAMIC_PIPE && pp->pipe_id &&
    436                pp->local_gate >= NFA_HCI_FIRST_PROP_GATE &&
    437                pp->local_gate <= NFA_HCI_LAST_PROP_GATE) {
    438       for (xx = 0, pg = nfa_hci_cb.cfg.dyn_gates; xx < NFA_HCI_MAX_GATE_CB;
    439            xx++, pg++) {
    440         if (pp->local_gate == pg->gate_id) {
    441           if (!pg->gate_owner)
    442             memcpy(&evt_data.gates_pipes.uicc_created_pipe
    443                         [evt_data.gates_pipes.num_uicc_created_pipes++],
    444                    pp, sizeof(tNFA_HCI_PIPE_INFO));
    445           break;
    446         }
    447       }
    448     }
    449   }
    450 
    451   evt_data.gates_pipes.status = NFA_STATUS_OK;
    452 
    453   /* notify NFA_HCI_GET_GATE_PIPE_LIST_EVT to the application */
    454   nfa_hciu_send_to_app(NFA_HCI_GET_GATE_PIPE_LIST_EVT, &evt_data,
    455                        p_evt_data->get_gate_pipe_list.hci_handle);
    456 }
    457 
    458 /*******************************************************************************
    459 **
    460 ** Function         nfa_hci_api_alloc_gate
    461 **
    462 ** Description      action function to allocate gate
    463 **
    464 ** Returns          None
    465 **
    466 *******************************************************************************/
    467 static void nfa_hci_api_alloc_gate(tNFA_HCI_EVENT_DATA* p_evt_data) {
    468   tNFA_HANDLE app_handle = p_evt_data->comm.hci_handle;
    469   tNFA_HCI_EVT_DATA evt_data;
    470   tNFA_HCI_DYN_GATE* p_gate;
    471 
    472   p_gate = nfa_hciu_alloc_gate(p_evt_data->gate_info.gate, app_handle);
    473 
    474   if (p_gate) {
    475     if (!p_gate->gate_owner) {
    476       /* No app owns the gate yet */
    477       p_gate->gate_owner = app_handle;
    478     } else if (p_gate->gate_owner != app_handle) {
    479       /* Some other app owns the gate */
    480       p_gate = NULL;
    481       LOG(ERROR) << StringPrintf("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     LOG(ERROR) << StringPrintf(
    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     LOG(ERROR) << StringPrintf(
    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         LOG(WARNING) << StringPrintf(
    712             "nfa_hci_api_get_reg_value pipe:%d not open",
    713             p_evt_data->get_registry.pipe);
    714       } else {
    715         status = nfa_hciu_send_get_param_cmd(p_evt_data->get_registry.pipe,
    716                                              p_evt_data->get_registry.reg_inx);
    717         if (status == NFA_STATUS_OK) return true;
    718       }
    719     }
    720   }
    721 
    722   evt_data.cmd_sent.status = status;
    723 
    724   /* Send NFA_HCI_CMD_SENT_EVT to notify failure */
    725   nfa_hciu_send_to_app(NFA_HCI_CMD_SENT_EVT, &evt_data,
    726                        p_evt_data->get_registry.hci_handle);
    727   return true;
    728 }
    729 
    730 /*******************************************************************************
    731 **
    732 ** Function         nfa_hci_api_set_reg_value
    733 **
    734 ** Description      action function to set the reg value at specified index
    735 **
    736 ** Returns          TRUE, if the command is processed
    737 **                  FALSE, if command is queued for processing later
    738 **
    739 *******************************************************************************/
    740 static bool nfa_hci_api_set_reg_value(tNFA_HCI_EVENT_DATA* p_evt_data) {
    741   tNFA_HCI_DYN_PIPE* p_pipe =
    742       nfa_hciu_find_pipe_by_pid(p_evt_data->set_registry.pipe);
    743   tNFA_HCI_DYN_GATE* p_gate;
    744   tNFA_STATUS status = NFA_STATUS_FAILED;
    745   tNFA_HCI_EVT_DATA evt_data;
    746 
    747   if (p_pipe != NULL) {
    748     p_gate = nfa_hciu_find_gate_by_gid(p_pipe->local_gate);
    749 
    750     if ((p_gate != NULL) && (nfa_hciu_is_active_host(p_pipe->dest_host)) &&
    751         (p_gate->gate_owner == p_evt_data->set_registry.hci_handle)) {
    752       nfa_hci_cb.app_in_use = p_evt_data->set_registry.hci_handle;
    753 
    754       if (nfa_hciu_is_host_reseting(p_pipe->dest_host)) {
    755         GKI_enqueue(&nfa_hci_cb.hci_host_reset_api_q, (NFC_HDR*)p_evt_data);
    756         return false;
    757       }
    758 
    759       if (p_pipe->pipe_state == NFA_HCI_PIPE_CLOSED) {
    760         LOG(WARNING) << StringPrintf(
    761             "nfa_hci_api_set_reg_value pipe:%d not open",
    762             p_evt_data->set_registry.pipe);
    763       } else {
    764         status = nfa_hciu_send_set_param_cmd(
    765             p_evt_data->set_registry.pipe, p_evt_data->set_registry.reg_inx,
    766             p_evt_data->set_registry.size, p_evt_data->set_registry.data);
    767         if (status == NFA_STATUS_OK) return true;
    768       }
    769     }
    770   }
    771   evt_data.cmd_sent.status = status;
    772 
    773   /* Send NFA_HCI_CMD_SENT_EVT to notify failure */
    774   nfa_hciu_send_to_app(NFA_HCI_CMD_SENT_EVT, &evt_data,
    775                        p_evt_data->set_registry.hci_handle);
    776   return true;
    777 }
    778 
    779 /*******************************************************************************
    780 **
    781 ** Function         nfa_hci_api_close_pipe
    782 **
    783 ** Description      action function to close a pipe
    784 **
    785 ** Returns          None
    786 **
    787 *******************************************************************************/
    788 static void nfa_hci_api_close_pipe(tNFA_HCI_EVENT_DATA* p_evt_data) {
    789   tNFA_HCI_EVT_DATA evt_data;
    790   tNFA_HCI_DYN_PIPE* p_pipe =
    791       nfa_hciu_find_pipe_by_pid(p_evt_data->close_pipe.pipe);
    792   tNFA_HCI_DYN_GATE* p_gate = NULL;
    793 
    794   if (p_pipe != NULL) p_gate = nfa_hciu_find_gate_by_gid(p_pipe->local_gate);
    795 
    796   if ((p_pipe != NULL) && (p_gate != NULL) &&
    797       (nfa_hciu_is_active_host(p_pipe->dest_host)) &&
    798       (p_gate->gate_owner == p_evt_data->close_pipe.hci_handle)) {
    799     if (p_pipe->pipe_state == NFA_HCI_PIPE_OPENED) {
    800       nfa_hciu_send_close_pipe_cmd(p_evt_data->close_pipe.pipe);
    801     } else {
    802       evt_data.closed.status = NFA_STATUS_OK;
    803       evt_data.closed.pipe = p_evt_data->close_pipe.pipe;
    804 
    805       nfa_hciu_send_to_app(NFA_HCI_CLOSE_PIPE_EVT, &evt_data,
    806                            p_evt_data->close_pipe.hci_handle);
    807     }
    808   } else {
    809     evt_data.closed.status = NFA_STATUS_FAILED;
    810     evt_data.closed.pipe = 0x00;
    811 
    812     nfa_hciu_send_to_app(NFA_HCI_CLOSE_PIPE_EVT, &evt_data,
    813                          p_evt_data->close_pipe.hci_handle);
    814   }
    815 }
    816 
    817 /*******************************************************************************
    818 **
    819 ** Function         nfa_hci_api_delete_pipe
    820 **
    821 ** Description      action function to delete a pipe
    822 **
    823 ** Returns          None
    824 **
    825 *******************************************************************************/
    826 static void nfa_hci_api_delete_pipe(tNFA_HCI_EVENT_DATA* p_evt_data) {
    827   tNFA_HCI_EVT_DATA evt_data;
    828   tNFA_HCI_DYN_PIPE* p_pipe =
    829       nfa_hciu_find_pipe_by_pid(p_evt_data->delete_pipe.pipe);
    830   tNFA_HCI_DYN_GATE* p_gate = NULL;
    831 
    832   if (p_pipe != NULL) {
    833     p_gate = nfa_hciu_find_gate_by_gid(p_pipe->local_gate);
    834     if ((p_gate != NULL) &&
    835         (p_gate->gate_owner == p_evt_data->delete_pipe.hci_handle) &&
    836         (nfa_hciu_is_active_host(p_pipe->dest_host))) {
    837       nfa_hciu_send_delete_pipe_cmd(p_evt_data->delete_pipe.pipe);
    838       return;
    839     }
    840   }
    841 
    842   evt_data.deleted.status = NFA_STATUS_FAILED;
    843   evt_data.deleted.pipe = 0x00;
    844   nfa_hciu_send_to_app(NFA_HCI_DELETE_PIPE_EVT, &evt_data,
    845                        p_evt_data->close_pipe.hci_handle);
    846 }
    847 
    848 /*******************************************************************************
    849 **
    850 ** Function         nfa_hci_api_send_cmd
    851 **
    852 ** Description      action function to send command on the given pipe
    853 **
    854 ** Returns          TRUE, if the command is processed
    855 **                  FALSE, if command is queued for processing later
    856 **
    857 *******************************************************************************/
    858 static bool nfa_hci_api_send_cmd(tNFA_HCI_EVENT_DATA* p_evt_data) {
    859   tNFA_STATUS status = NFA_STATUS_FAILED;
    860   tNFA_HCI_DYN_PIPE* p_pipe;
    861   tNFA_HCI_EVT_DATA evt_data;
    862   tNFA_HANDLE app_handle;
    863 
    864   if ((p_pipe = nfa_hciu_find_pipe_by_pid(p_evt_data->send_cmd.pipe)) != NULL) {
    865     app_handle = nfa_hciu_get_pipe_owner(p_evt_data->send_cmd.pipe);
    866 
    867     if ((nfa_hciu_is_active_host(p_pipe->dest_host)) &&
    868         ((app_handle == p_evt_data->send_cmd.hci_handle ||
    869           p_pipe->local_gate == NFA_HCI_CONNECTIVITY_GATE))) {
    870       if (nfa_hciu_is_host_reseting(p_pipe->dest_host)) {
    871         GKI_enqueue(&nfa_hci_cb.hci_host_reset_api_q, (NFC_HDR*)p_evt_data);
    872         return false;
    873       }
    874 
    875       if (p_pipe->pipe_state == NFA_HCI_PIPE_OPENED) {
    876         nfa_hci_cb.pipe_in_use = p_evt_data->send_cmd.pipe;
    877         status = nfa_hciu_send_msg(p_pipe->pipe_id, NFA_HCI_COMMAND_TYPE,
    878                                    p_evt_data->send_cmd.cmd_code,
    879                                    p_evt_data->send_cmd.cmd_len,
    880                                    p_evt_data->send_cmd.data);
    881         if (status == NFA_STATUS_OK) return true;
    882       } else {
    883         LOG(WARNING) << StringPrintf("nfa_hci_api_send_cmd pipe:%d not open",
    884                                      p_pipe->pipe_id);
    885       }
    886     } else {
    887       LOG(WARNING) << StringPrintf(
    888           "nfa_hci_api_send_cmd pipe:%d Owned by different application or "
    889           "Destination host is not active",
    890           p_pipe->pipe_id);
    891     }
    892   } else {
    893     LOG(WARNING) << StringPrintf("nfa_hci_api_send_cmd pipe:%d not found",
    894                                  p_evt_data->send_cmd.pipe);
    895   }
    896 
    897   evt_data.cmd_sent.status = status;
    898 
    899   /* Send NFA_HCI_CMD_SENT_EVT to notify failure */
    900   nfa_hciu_send_to_app(NFA_HCI_CMD_SENT_EVT, &evt_data,
    901                        p_evt_data->send_cmd.hci_handle);
    902   return true;
    903 }
    904 
    905 /*******************************************************************************
    906 **
    907 ** Function         nfa_hci_api_send_rsp
    908 **
    909 ** Description      action function to send response on the given pipe
    910 **
    911 ** Returns          None
    912 **
    913 *******************************************************************************/
    914 static void nfa_hci_api_send_rsp(tNFA_HCI_EVENT_DATA* p_evt_data) {
    915   tNFA_STATUS status = NFA_STATUS_FAILED;
    916   tNFA_HCI_DYN_PIPE* p_pipe;
    917   tNFA_HCI_EVT_DATA evt_data;
    918   tNFA_HANDLE app_handle;
    919 
    920   if ((p_pipe = nfa_hciu_find_pipe_by_pid(p_evt_data->send_rsp.pipe)) != NULL) {
    921     app_handle = nfa_hciu_get_pipe_owner(p_evt_data->send_rsp.pipe);
    922 
    923     if ((nfa_hciu_is_active_host(p_pipe->dest_host)) &&
    924         ((app_handle == p_evt_data->send_rsp.hci_handle ||
    925           p_pipe->local_gate == NFA_HCI_CONNECTIVITY_GATE))) {
    926       if (p_pipe->pipe_state == NFA_HCI_PIPE_OPENED) {
    927         status = nfa_hciu_send_msg(p_pipe->pipe_id, NFA_HCI_RESPONSE_TYPE,
    928                                    p_evt_data->send_rsp.response,
    929                                    p_evt_data->send_rsp.size,
    930                                    p_evt_data->send_rsp.data);
    931         if (status == NFA_STATUS_OK) return;
    932       } else {
    933         LOG(WARNING) << StringPrintf("nfa_hci_api_send_rsp pipe:%d not open",
    934                                      p_pipe->pipe_id);
    935       }
    936     } else {
    937       LOG(WARNING) << StringPrintf(
    938           "nfa_hci_api_send_rsp pipe:%d Owned by different application or "
    939           "Destination host is not active",
    940           p_pipe->pipe_id);
    941     }
    942   } else {
    943     LOG(WARNING) << StringPrintf("nfa_hci_api_send_rsp pipe:%d not found",
    944                                  p_evt_data->send_rsp.pipe);
    945   }
    946 
    947   evt_data.rsp_sent.status = status;
    948 
    949   /* Send NFA_HCI_RSP_SENT_EVT to notify failure */
    950   nfa_hciu_send_to_app(NFA_HCI_RSP_SENT_EVT, &evt_data,
    951                        p_evt_data->send_rsp.hci_handle);
    952 }
    953 
    954 /*******************************************************************************
    955 **
    956 ** Function         nfa_hci_api_send_event
    957 **
    958 ** Description      action function to send an event to the given pipe
    959 **
    960 ** Returns          TRUE, if the event is processed
    961 **                  FALSE, if event is queued for processing later
    962 **
    963 *******************************************************************************/
    964 static bool nfa_hci_api_send_event(tNFA_HCI_EVENT_DATA* p_evt_data) {
    965   tNFA_STATUS status = NFA_STATUS_FAILED;
    966   tNFA_HCI_DYN_PIPE* p_pipe;
    967   tNFA_HCI_EVT_DATA evt_data;
    968   tNFA_HANDLE app_handle;
    969 
    970   if ((p_pipe = nfa_hciu_find_pipe_by_pid(p_evt_data->send_evt.pipe)) != NULL) {
    971     app_handle = nfa_hciu_get_pipe_owner(p_evt_data->send_evt.pipe);
    972 
    973     if ((nfa_hciu_is_active_host(p_pipe->dest_host)) &&
    974         ((app_handle == p_evt_data->send_evt.hci_handle ||
    975           p_pipe->local_gate == NFA_HCI_CONNECTIVITY_GATE))) {
    976       if (nfa_hciu_is_host_reseting(p_pipe->dest_host)) {
    977         GKI_enqueue(&nfa_hci_cb.hci_host_reset_api_q, (NFC_HDR*)p_evt_data);
    978         return false;
    979       }
    980 
    981       if (p_pipe->pipe_state == NFA_HCI_PIPE_OPENED) {
    982         status = nfa_hciu_send_msg(
    983             p_pipe->pipe_id, NFA_HCI_EVENT_TYPE, p_evt_data->send_evt.evt_code,
    984             p_evt_data->send_evt.evt_len, p_evt_data->send_evt.p_evt_buf);
    985 
    986         if (status == NFA_STATUS_OK) {
    987           if (p_pipe->local_gate == NFA_HCI_LOOP_BACK_GATE) {
    988             nfa_hci_cb.w4_rsp_evt = true;
    989             nfa_hci_cb.hci_state = NFA_HCI_STATE_WAIT_RSP;
    990           }
    991 
    992           if (p_evt_data->send_evt.rsp_len) {
    993             nfa_hci_cb.pipe_in_use = p_evt_data->send_evt.pipe;
    994             nfa_hci_cb.rsp_buf_size = p_evt_data->send_evt.rsp_len;
    995             nfa_hci_cb.p_rsp_buf = p_evt_data->send_evt.p_rsp_buf;
    996             if (p_evt_data->send_evt.rsp_timeout) {
    997               nfa_hci_cb.w4_rsp_evt = true;
    998               nfa_hci_cb.hci_state = NFA_HCI_STATE_WAIT_RSP;
    999               nfa_sys_start_timer(&nfa_hci_cb.timer, NFA_HCI_RSP_TIMEOUT_EVT,
   1000                                   p_evt_data->send_evt.rsp_timeout);
   1001             } else if (p_pipe->local_gate == NFA_HCI_LOOP_BACK_GATE) {
   1002               nfa_sys_start_timer(&nfa_hci_cb.timer, NFA_HCI_RSP_TIMEOUT_EVT,
   1003                                   p_nfa_hci_cfg->hcp_response_timeout);
   1004             }
   1005           } else {
   1006             if (p_pipe->local_gate == NFA_HCI_LOOP_BACK_GATE) {
   1007               nfa_hci_cb.pipe_in_use = p_evt_data->send_evt.pipe;
   1008               nfa_sys_start_timer(&nfa_hci_cb.timer, NFA_HCI_RSP_TIMEOUT_EVT,
   1009                                   p_nfa_hci_cfg->hcp_response_timeout);
   1010             }
   1011             nfa_hci_cb.rsp_buf_size = 0;
   1012             nfa_hci_cb.p_rsp_buf = NULL;
   1013           }
   1014         }
   1015       } else {
   1016         LOG(WARNING) << StringPrintf("nfa_hci_api_send_event pipe:%d not open",
   1017                                      p_pipe->pipe_id);
   1018       }
   1019     } else {
   1020       LOG(WARNING) << StringPrintf(
   1021           "nfa_hci_api_send_event pipe:%d Owned by different application or "
   1022           "Destination host is not active",
   1023           p_pipe->pipe_id);
   1024     }
   1025   } else {
   1026     LOG(WARNING) << StringPrintf("nfa_hci_api_send_event pipe:%d not found",
   1027                                  p_evt_data->send_evt.pipe);
   1028   }
   1029 
   1030   evt_data.evt_sent.status = status;
   1031 
   1032   /* Send NFC_HCI_EVENT_SENT_EVT to notify status */
   1033   nfa_hciu_send_to_app(NFA_HCI_EVENT_SENT_EVT, &evt_data,
   1034                        p_evt_data->send_evt.hci_handle);
   1035   return true;
   1036 }
   1037 
   1038 /*******************************************************************************
   1039 **
   1040 ** Function         nfa_hci_api_add_static_pipe
   1041 **
   1042 ** Description      action function to add static pipe
   1043 **
   1044 ** Returns          None
   1045 **
   1046 *******************************************************************************/
   1047 static void nfa_hci_api_add_static_pipe(tNFA_HCI_EVENT_DATA* p_evt_data) {
   1048   tNFA_HCI_DYN_GATE* pg;
   1049   tNFA_HCI_DYN_PIPE* pp;
   1050   tNFA_HCI_EVT_DATA evt_data;
   1051 
   1052   /* Allocate a proprietary gate */
   1053   pg = nfa_hciu_alloc_gate(p_evt_data->add_static_pipe.gate,
   1054                            p_evt_data->add_static_pipe.hci_handle);
   1055   if (pg != NULL) {
   1056     /* Assign new owner to the gate */
   1057     pg->gate_owner = p_evt_data->add_static_pipe.hci_handle;
   1058 
   1059     /* Add the dynamic pipe to the proprietary gate */
   1060     if (nfa_hciu_add_pipe_to_gate(p_evt_data->add_static_pipe.pipe, pg->gate_id,
   1061                                   p_evt_data->add_static_pipe.host,
   1062                                   p_evt_data->add_static_pipe.gate) !=
   1063         NFA_HCI_ANY_OK) {
   1064       /* Unable to add the dynamic pipe, so release the gate */
   1065       nfa_hciu_release_gate(pg->gate_id);
   1066       evt_data.pipe_added.status = NFA_STATUS_FAILED;
   1067       nfa_hciu_send_to_app(NFA_HCI_ADD_STATIC_PIPE_EVT, &evt_data,
   1068                            p_evt_data->add_static_pipe.hci_handle);
   1069       return;
   1070     }
   1071     pp = nfa_hciu_find_pipe_by_pid(p_evt_data->add_static_pipe.pipe);
   1072     if (pp != NULL) {
   1073       /* This pipe is always opened */
   1074       pp->pipe_state = NFA_HCI_PIPE_OPENED;
   1075       evt_data.pipe_added.status = NFA_STATUS_OK;
   1076       nfa_hciu_send_to_app(NFA_HCI_ADD_STATIC_PIPE_EVT, &evt_data,
   1077                            p_evt_data->add_static_pipe.hci_handle);
   1078       return;
   1079     }
   1080   }
   1081   /* Unable to add static pipe */
   1082   evt_data.pipe_added.status = NFA_STATUS_FAILED;
   1083   nfa_hciu_send_to_app(NFA_HCI_ADD_STATIC_PIPE_EVT, &evt_data,
   1084                        p_evt_data->add_static_pipe.hci_handle);
   1085 }
   1086 
   1087 /*******************************************************************************
   1088 **
   1089 ** Function         nfa_hci_handle_link_mgm_gate_cmd
   1090 **
   1091 ** Description      This function handles incoming link management gate hci
   1092 **                  commands
   1093 **
   1094 ** Returns          none
   1095 **
   1096 *******************************************************************************/
   1097 void nfa_hci_handle_link_mgm_gate_cmd(uint8_t* p_data) {
   1098   uint8_t index;
   1099   uint8_t data[2];
   1100   uint8_t rsp_len = 0;
   1101   uint8_t response = NFA_HCI_ANY_OK;
   1102 
   1103   if ((nfa_hci_cb.cfg.link_mgmt_gate.pipe00_state != NFA_HCI_PIPE_OPENED) &&
   1104       (nfa_hci_cb.inst != NFA_HCI_ANY_OPEN_PIPE)) {
   1105     nfa_hciu_send_msg(NFA_HCI_LINK_MANAGEMENT_PIPE, NFA_HCI_RESPONSE_TYPE,
   1106                       NFA_HCI_ANY_E_PIPE_NOT_OPENED, 0, NULL);
   1107     return;
   1108   }
   1109 
   1110   switch (nfa_hci_cb.inst) {
   1111     case NFA_HCI_ANY_SET_PARAMETER:
   1112       STREAM_TO_UINT8(index, p_data);
   1113 
   1114       if (index == 1) {
   1115         STREAM_TO_UINT16(nfa_hci_cb.cfg.link_mgmt_gate.rec_errors, p_data);
   1116       } else
   1117         response = NFA_HCI_ANY_E_REG_PAR_UNKNOWN;
   1118       break;
   1119 
   1120     case NFA_HCI_ANY_GET_PARAMETER:
   1121       STREAM_TO_UINT8(index, p_data);
   1122       if (index == 1) {
   1123         data[0] =
   1124             (uint8_t)((nfa_hci_cb.cfg.link_mgmt_gate.rec_errors >> 8) & 0x00FF);
   1125         data[1] = (uint8_t)(nfa_hci_cb.cfg.link_mgmt_gate.rec_errors & 0x000F);
   1126         rsp_len = 2;
   1127       } else
   1128         response = NFA_HCI_ANY_E_REG_PAR_UNKNOWN;
   1129       break;
   1130 
   1131     case NFA_HCI_ANY_OPEN_PIPE:
   1132       data[0] = 0;
   1133       rsp_len = 1;
   1134       nfa_hci_cb.cfg.link_mgmt_gate.pipe00_state = NFA_HCI_PIPE_OPENED;
   1135       break;
   1136 
   1137     case NFA_HCI_ANY_CLOSE_PIPE:
   1138       nfa_hci_cb.cfg.link_mgmt_gate.pipe00_state = NFA_HCI_PIPE_CLOSED;
   1139       break;
   1140 
   1141     default:
   1142       response = NFA_HCI_ANY_E_CMD_NOT_SUPPORTED;
   1143       break;
   1144   }
   1145 
   1146   nfa_hciu_send_msg(NFA_HCI_LINK_MANAGEMENT_PIPE, NFA_HCI_RESPONSE_TYPE,
   1147                     response, rsp_len, data);
   1148 }
   1149 
   1150 /*******************************************************************************
   1151 **
   1152 ** Function         nfa_hci_handle_pipe_open_close_cmd
   1153 **
   1154 ** Description      This function handles all generic gates (excluding
   1155 **                  connectivity gate) commands
   1156 **
   1157 ** Returns          none
   1158 **
   1159 *******************************************************************************/
   1160 void nfa_hci_handle_pipe_open_close_cmd(tNFA_HCI_DYN_PIPE* p_pipe) {
   1161   uint8_t data[1];
   1162   uint8_t rsp_len = 0;
   1163   tNFA_HCI_RESPONSE response = NFA_HCI_ANY_OK;
   1164   tNFA_HCI_DYN_GATE* p_gate;
   1165 
   1166   if (nfa_hci_cb.inst == NFA_HCI_ANY_OPEN_PIPE) {
   1167     if ((p_gate = nfa_hciu_find_gate_by_gid(p_pipe->local_gate)) != NULL)
   1168       data[0] = nfa_hciu_count_open_pipes_on_gate(p_gate);
   1169     else
   1170       data[0] = 0;
   1171 
   1172     p_pipe->pipe_state = NFA_HCI_PIPE_OPENED;
   1173     rsp_len = 1;
   1174   } else if (nfa_hci_cb.inst == NFA_HCI_ANY_CLOSE_PIPE) {
   1175     p_pipe->pipe_state = NFA_HCI_PIPE_CLOSED;
   1176   }
   1177 
   1178   nfa_hciu_send_msg(p_pipe->pipe_id, NFA_HCI_RESPONSE_TYPE, response, rsp_len,
   1179                     data);
   1180 }
   1181 
   1182 /*******************************************************************************
   1183 **
   1184 ** Function         nfa_hci_handle_admin_gate_cmd
   1185 **
   1186 ** Description      This function handles incoming commands on ADMIN gate
   1187 **
   1188 ** Returns          none
   1189 **
   1190 *******************************************************************************/
   1191 void nfa_hci_handle_admin_gate_cmd(uint8_t* p_data) {
   1192   uint8_t source_host, source_gate, dest_host, dest_gate, pipe;
   1193   uint8_t data = 0;
   1194   uint8_t rsp_len = 0;
   1195   tNFA_HCI_RESPONSE response = NFA_HCI_ANY_OK;
   1196   tNFA_HCI_DYN_GATE* pgate;
   1197   tNFA_HCI_EVT_DATA evt_data;
   1198 
   1199   switch (nfa_hci_cb.inst) {
   1200     case NFA_HCI_ANY_OPEN_PIPE:
   1201       nfa_hci_cb.cfg.admin_gate.pipe01_state = NFA_HCI_PIPE_OPENED;
   1202       data = 0;
   1203       rsp_len = 1;
   1204       break;
   1205 
   1206     case NFA_HCI_ANY_CLOSE_PIPE:
   1207       nfa_hci_cb.cfg.admin_gate.pipe01_state = NFA_HCI_PIPE_CLOSED;
   1208       /* Reopen the pipe immediately */
   1209       nfa_hciu_send_msg(NFA_HCI_ADMIN_PIPE, NFA_HCI_RESPONSE_TYPE, response,
   1210                         rsp_len, &data);
   1211       nfa_hci_cb.app_in_use = NFA_HANDLE_INVALID;
   1212       nfa_hciu_send_open_pipe_cmd(NFA_HCI_ADMIN_PIPE);
   1213       return;
   1214       break;
   1215 
   1216     case NFA_HCI_ADM_NOTIFY_PIPE_CREATED:
   1217       STREAM_TO_UINT8(source_host, p_data);
   1218       STREAM_TO_UINT8(source_gate, p_data);
   1219       STREAM_TO_UINT8(dest_host, p_data);
   1220       STREAM_TO_UINT8(dest_gate, p_data);
   1221       STREAM_TO_UINT8(pipe, p_data);
   1222 
   1223       if ((dest_gate == NFA_HCI_IDENTITY_MANAGEMENT_GATE) ||
   1224           (dest_gate == NFA_HCI_LOOP_BACK_GATE)) {
   1225         response = nfa_hciu_add_pipe_to_static_gate(dest_gate, pipe,
   1226                                                     source_host, source_gate);
   1227       } else {
   1228         if ((pgate = nfa_hciu_find_gate_by_gid(dest_gate)) != NULL) {
   1229           /* If the gate is valid, add the pipe to it  */
   1230           if (nfa_hciu_check_pipe_between_gates(dest_gate, source_host,
   1231                                                 source_gate)) {
   1232             /* Already, there is a pipe between these two gates, so will reject
   1233              */
   1234             response = NFA_HCI_ANY_E_NOK;
   1235           } else {
   1236             response = nfa_hciu_add_pipe_to_gate(pipe, dest_gate, source_host,
   1237                                                  source_gate);
   1238             if (response == NFA_HCI_ANY_OK) {
   1239               /* Tell the application a pipe was created with its gate */
   1240 
   1241               evt_data.created.status = NFA_STATUS_OK;
   1242               evt_data.created.pipe = pipe;
   1243               evt_data.created.source_gate = dest_gate;
   1244               evt_data.created.dest_host = source_host;
   1245               evt_data.created.dest_gate = source_gate;
   1246 
   1247               nfa_hciu_send_to_app(NFA_HCI_CREATE_PIPE_EVT, &evt_data,
   1248                                    pgate->gate_owner);
   1249             }
   1250           }
   1251         } else {
   1252           response = NFA_HCI_ANY_E_NOK;
   1253           if ((dest_gate >= NFA_HCI_FIRST_PROP_GATE) &&
   1254               (dest_gate <= NFA_HCI_LAST_PROP_GATE)) {
   1255             if (nfa_hciu_alloc_gate(dest_gate, 0))
   1256               response = nfa_hciu_add_pipe_to_gate(pipe, dest_gate, source_host,
   1257                                                    source_gate);
   1258           }
   1259         }
   1260       }
   1261       break;
   1262 
   1263     case NFA_HCI_ADM_NOTIFY_PIPE_DELETED:
   1264       STREAM_TO_UINT8(pipe, p_data);
   1265       response = nfa_hciu_release_pipe(pipe);
   1266       break;
   1267 
   1268     case NFA_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED:
   1269       STREAM_TO_UINT8(source_host, p_data);
   1270 
   1271       nfa_hciu_remove_all_pipes_from_host(source_host);
   1272 
   1273       if (source_host == NFA_HCI_HOST_CONTROLLER) {
   1274         nfa_hci_cb.cfg.link_mgmt_gate.pipe00_state = NFA_HCI_PIPE_CLOSED;
   1275         nfa_hci_cb.cfg.admin_gate.pipe01_state = NFA_HCI_PIPE_CLOSED;
   1276 
   1277         /* Reopen the admin pipe immediately */
   1278         nfa_hci_cb.app_in_use = NFA_HANDLE_INVALID;
   1279         nfa_hciu_send_open_pipe_cmd(NFA_HCI_ADMIN_PIPE);
   1280         return;
   1281       } else {
   1282         if ((source_host >= NFA_HCI_HOST_ID_UICC0) &&
   1283             (source_host <
   1284              (NFA_HCI_HOST_ID_UICC0 + NFA_HCI_MAX_HOST_IN_NETWORK))) {
   1285           nfa_hci_cb.reset_host[source_host - NFA_HCI_HOST_ID_UICC0] =
   1286               source_host;
   1287         }
   1288       }
   1289       break;
   1290 
   1291     default:
   1292       response = NFA_HCI_ANY_E_CMD_NOT_SUPPORTED;
   1293       break;
   1294   }
   1295 
   1296   nfa_hciu_send_msg(NFA_HCI_ADMIN_PIPE, NFA_HCI_RESPONSE_TYPE, response,
   1297                     rsp_len, &data);
   1298 }
   1299 
   1300 /*******************************************************************************
   1301 **
   1302 ** Function         nfa_hci_handle_admin_gate_rsp
   1303 **
   1304 ** Description      This function handles response received on admin gate
   1305 **
   1306 ** Returns          none
   1307 **
   1308 *******************************************************************************/
   1309 void nfa_hci_handle_admin_gate_rsp(uint8_t* p_data, uint8_t data_len) {
   1310   uint8_t source_host;
   1311   uint8_t source_gate = nfa_hci_cb.local_gate_in_use;
   1312   uint8_t dest_host = nfa_hci_cb.remote_host_in_use;
   1313   uint8_t dest_gate = nfa_hci_cb.remote_gate_in_use;
   1314   uint8_t pipe = 0;
   1315   tNFA_STATUS status;
   1316   tNFA_HCI_EVT_DATA evt_data;
   1317   uint8_t default_session[NFA_HCI_SESSION_ID_LEN] = {0xFF, 0xFF, 0xFF, 0xFF,
   1318                                                      0xFF, 0xFF, 0xFF, 0xFF};
   1319   uint8_t host_count = 0;
   1320   uint8_t host_id = 0;
   1321   uint32_t os_tick;
   1322 
   1323   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1324       "nfa_hci_handle_admin_gate_rsp - LastCmdSent: %s  App: 0x%04x  Gate: "
   1325       "0x%02x  Pipe: 0x%02x",
   1326       nfa_hciu_instr_2_str(nfa_hci_cb.cmd_sent).c_str(), nfa_hci_cb.app_in_use,
   1327       nfa_hci_cb.local_gate_in_use, nfa_hci_cb.pipe_in_use);
   1328 
   1329   /* If starting up, handle events here */
   1330   if ((nfa_hci_cb.hci_state == NFA_HCI_STATE_STARTUP) ||
   1331       (nfa_hci_cb.hci_state == NFA_HCI_STATE_RESTORE) ||
   1332       (nfa_hci_cb.hci_state == NFA_HCI_STATE_WAIT_NETWK_ENABLE) ||
   1333       (nfa_hci_cb.hci_state == NFA_HCI_STATE_RESTORE_NETWK_ENABLE)) {
   1334     if (nfa_hci_cb.inst == NFA_HCI_ANY_E_PIPE_NOT_OPENED) {
   1335       nfa_hciu_send_open_pipe_cmd(NFA_HCI_ADMIN_PIPE);
   1336       return;
   1337     }
   1338 
   1339     if (nfa_hci_cb.inst != NFA_HCI_ANY_OK) {
   1340       LOG(ERROR) << StringPrintf(
   1341           "nfa_hci_handle_admin_gate_rsp - Initialization failed");
   1342       nfa_hci_startup_complete(NFA_STATUS_FAILED);
   1343       return;
   1344     }
   1345 
   1346     switch (nfa_hci_cb.cmd_sent) {
   1347       case NFA_HCI_ANY_SET_PARAMETER:
   1348         if (nfa_hci_cb.param_in_use == NFA_HCI_SESSION_IDENTITY_INDEX) {
   1349           /* Set WHITELIST */
   1350           nfa_hciu_send_set_param_cmd(
   1351               NFA_HCI_ADMIN_PIPE, NFA_HCI_WHITELIST_INDEX,
   1352               p_nfa_hci_cfg->num_whitelist_host, p_nfa_hci_cfg->p_whitelist);
   1353         } else if (nfa_hci_cb.param_in_use == NFA_HCI_WHITELIST_INDEX) {
   1354           if ((nfa_hci_cb.hci_state == NFA_HCI_STATE_STARTUP) ||
   1355               (nfa_hci_cb.hci_state == NFA_HCI_STATE_RESTORE))
   1356             nfa_hci_dh_startup_complete();
   1357           if (NFA_GetNCIVersion() == NCI_VERSION_2_0) {
   1358             nfa_hci_cb.hci_state = NFA_HCI_STATE_WAIT_NETWK_ENABLE;
   1359             NFA_EeGetInfo(&nfa_hci_cb.num_nfcee, nfa_hci_cb.ee_info);
   1360             nfa_hci_enable_one_nfcee();
   1361           }
   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             LOG(WARNING) << StringPrintf(
   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() {
   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     LOG(ERROR) << StringPrintf(
   1609         "nfa_hci_handle_admin_gate_evt - Unknown event on ADMIN Pipe");
   1610     return;
   1611   }
   1612 
   1613   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   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     LOG(ERROR) << StringPrintf("nfa_hci_handle_dyn_pipe_pkt - Unknown pipe %d",
   1679                                pipe_id);
   1680     if (nfa_hci_cb.type == NFA_HCI_COMMAND_TYPE)
   1681       nfa_hciu_send_msg(pipe_id, NFA_HCI_RESPONSE_TYPE, NFA_HCI_ANY_E_NOK, 0,
   1682                         NULL);
   1683     return;
   1684   }
   1685 
   1686   if (p_pipe->local_gate == NFA_HCI_IDENTITY_MANAGEMENT_GATE) {
   1687     nfa_hci_handle_identity_mgmt_gate_pkt(p_data, p_pipe);
   1688   } else if (p_pipe->local_gate == NFA_HCI_LOOP_BACK_GATE) {
   1689     nfa_hci_handle_loopback_gate_pkt(p_data, data_len, p_pipe);
   1690   } else if (p_pipe->local_gate == NFA_HCI_CONNECTIVITY_GATE) {
   1691     nfa_hci_handle_connectivity_gate_pkt(p_data, data_len, p_pipe);
   1692   } else {
   1693     p_gate = nfa_hciu_find_gate_by_gid(p_pipe->local_gate);
   1694     if (p_gate == NULL) {
   1695       LOG(ERROR) << StringPrintf(
   1696           "nfa_hci_handle_dyn_pipe_pkt - Pipe's gate %d is corrupt",
   1697           p_pipe->local_gate);
   1698       if (nfa_hci_cb.type == NFA_HCI_COMMAND_TYPE)
   1699         nfa_hciu_send_msg(pipe_id, NFA_HCI_RESPONSE_TYPE, NFA_HCI_ANY_E_NOK, 0,
   1700                           NULL);
   1701       return;
   1702     }
   1703 
   1704     /* Check if data packet is a command, response or event */
   1705     switch (nfa_hci_cb.type) {
   1706       case NFA_HCI_COMMAND_TYPE:
   1707         nfa_hci_handle_generic_gate_cmd(p_data, (uint8_t)data_len, 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_pipe);
   1712         break;
   1713 
   1714       case NFA_HCI_EVENT_TYPE:
   1715         nfa_hci_handle_generic_gate_evt(p_data, data_len, p_gate, p_pipe);
   1716         break;
   1717     }
   1718   }
   1719 }
   1720 
   1721 /*******************************************************************************
   1722 **
   1723 ** Function         nfa_hci_handle_identity_mgmt_gate_pkt
   1724 **
   1725 ** Description      This function handles incoming Identity Management gate hci
   1726 **                  commands
   1727 **
   1728 ** Returns          none
   1729 **
   1730 *******************************************************************************/
   1731 static void nfa_hci_handle_identity_mgmt_gate_pkt(uint8_t* p_data,
   1732                                                   tNFA_HCI_DYN_PIPE* p_pipe) {
   1733   uint8_t data[20];
   1734   uint8_t index;
   1735   uint8_t gate_rsp[3 + NFA_HCI_MAX_GATE_CB], num_gates;
   1736   uint16_t rsp_len = 0;
   1737   uint8_t* p_rsp = data;
   1738   tNFA_HCI_RESPONSE response = NFA_HCI_ANY_OK;
   1739 
   1740   /* We never send commands on a pipe where the local gate is the identity
   1741    * management
   1742    * gate, so only commands should be processed.
   1743    */
   1744   if (nfa_hci_cb.type != NFA_HCI_COMMAND_TYPE) return;
   1745 
   1746   switch (nfa_hci_cb.inst) {
   1747     case NFA_HCI_ANY_GET_PARAMETER:
   1748       index = *(p_data++);
   1749       if (p_pipe->pipe_state == NFA_HCI_PIPE_OPENED) {
   1750         switch (index) {
   1751           case NFA_HCI_VERSION_SW_INDEX:
   1752             data[0] = (uint8_t)((NFA_HCI_VERSION_SW >> 16) & 0xFF);
   1753             data[1] = (uint8_t)((NFA_HCI_VERSION_SW >> 8) & 0xFF);
   1754             data[2] = (uint8_t)((NFA_HCI_VERSION_SW)&0xFF);
   1755             rsp_len = 3;
   1756             break;
   1757 
   1758           case NFA_HCI_HCI_VERSION_INDEX:
   1759             data[0] = NFA_HCI_VERSION;
   1760             rsp_len = 1;
   1761             break;
   1762 
   1763           case NFA_HCI_VERSION_HW_INDEX:
   1764             data[0] = (uint8_t)((NFA_HCI_VERSION_HW >> 16) & 0xFF);
   1765             data[1] = (uint8_t)((NFA_HCI_VERSION_HW >> 8) & 0xFF);
   1766             data[2] = (uint8_t)((NFA_HCI_VERSION_HW)&0xFF);
   1767             rsp_len = 3;
   1768             break;
   1769 
   1770           case NFA_HCI_VENDOR_NAME_INDEX:
   1771             memcpy(data, NFA_HCI_VENDOR_NAME, strlen(NFA_HCI_VENDOR_NAME));
   1772             rsp_len = (uint8_t)strlen(NFA_HCI_VENDOR_NAME);
   1773             break;
   1774 
   1775           case NFA_HCI_MODEL_ID_INDEX:
   1776             data[0] = NFA_HCI_MODEL_ID;
   1777             rsp_len = 1;
   1778             break;
   1779 
   1780           case NFA_HCI_GATES_LIST_INDEX:
   1781             gate_rsp[0] = NFA_HCI_LOOP_BACK_GATE;
   1782             gate_rsp[1] = NFA_HCI_IDENTITY_MANAGEMENT_GATE;
   1783             gate_rsp[2] = NFA_HCI_CONNECTIVITY_GATE;
   1784             num_gates = nfa_hciu_get_allocated_gate_list(&gate_rsp[3]);
   1785             rsp_len = num_gates + 3;
   1786             p_rsp = gate_rsp;
   1787             break;
   1788 
   1789           default:
   1790             response = NFA_HCI_ANY_E_NOK;
   1791             break;
   1792         }
   1793       } else {
   1794         response = NFA_HCI_ANY_E_PIPE_NOT_OPENED;
   1795       }
   1796       break;
   1797 
   1798     case NFA_HCI_ANY_OPEN_PIPE:
   1799       data[0] = 0;
   1800       rsp_len = 1;
   1801       p_pipe->pipe_state = NFA_HCI_PIPE_OPENED;
   1802       break;
   1803 
   1804     case NFA_HCI_ANY_CLOSE_PIPE:
   1805       p_pipe->pipe_state = NFA_HCI_PIPE_CLOSED;
   1806       break;
   1807 
   1808     default:
   1809       response = NFA_HCI_ANY_E_CMD_NOT_SUPPORTED;
   1810       break;
   1811   }
   1812 
   1813   nfa_hciu_send_msg(p_pipe->pipe_id, NFA_HCI_RESPONSE_TYPE, response, rsp_len,
   1814                     p_rsp);
   1815 }
   1816 
   1817 /*******************************************************************************
   1818 **
   1819 ** Function         nfa_hci_handle_generic_gate_cmd
   1820 **
   1821 ** Description      This function handles all generic gates (excluding
   1822 **                  connectivity gate) commands
   1823 **
   1824 ** Returns          none
   1825 **
   1826 *******************************************************************************/
   1827 static void nfa_hci_handle_generic_gate_cmd(uint8_t* p_data, uint8_t data_len,
   1828                                             tNFA_HCI_DYN_PIPE* p_pipe) {
   1829   tNFA_HCI_EVT_DATA evt_data;
   1830   tNFA_HANDLE app_handle = nfa_hciu_get_pipe_owner(p_pipe->pipe_id);
   1831 
   1832   switch (nfa_hci_cb.inst) {
   1833     case NFA_HCI_ANY_SET_PARAMETER:
   1834       evt_data.registry.pipe = p_pipe->pipe_id;
   1835       evt_data.registry.index = *p_data++;
   1836       if (data_len > 0) data_len--;
   1837       evt_data.registry.data_len = data_len;
   1838 
   1839       memcpy(evt_data.registry.reg_data, p_data, data_len);
   1840 
   1841       nfa_hciu_send_to_app(NFA_HCI_SET_REG_CMD_EVT, &evt_data, app_handle);
   1842       break;
   1843 
   1844     case NFA_HCI_ANY_GET_PARAMETER:
   1845       evt_data.registry.pipe = p_pipe->pipe_id;
   1846       evt_data.registry.index = *p_data;
   1847       evt_data.registry.data_len = 0;
   1848 
   1849       nfa_hciu_send_to_app(NFA_HCI_GET_REG_CMD_EVT, &evt_data, app_handle);
   1850       break;
   1851 
   1852     case NFA_HCI_ANY_OPEN_PIPE:
   1853       nfa_hci_handle_pipe_open_close_cmd(p_pipe);
   1854 
   1855       evt_data.opened.pipe = p_pipe->pipe_id;
   1856       evt_data.opened.status = NFA_STATUS_OK;
   1857 
   1858       nfa_hciu_send_to_app(NFA_HCI_OPEN_PIPE_EVT, &evt_data, app_handle);
   1859       break;
   1860 
   1861     case NFA_HCI_ANY_CLOSE_PIPE:
   1862       nfa_hci_handle_pipe_open_close_cmd(p_pipe);
   1863 
   1864       evt_data.closed.pipe = p_pipe->pipe_id;
   1865       evt_data.opened.status = NFA_STATUS_OK;
   1866 
   1867       nfa_hciu_send_to_app(NFA_HCI_CLOSE_PIPE_EVT, &evt_data, app_handle);
   1868       break;
   1869 
   1870     default:
   1871       /* Could be application specific command, pass it on */
   1872       evt_data.cmd_rcvd.status = NFA_STATUS_OK;
   1873       evt_data.cmd_rcvd.pipe = p_pipe->pipe_id;
   1874       ;
   1875       evt_data.cmd_rcvd.cmd_code = nfa_hci_cb.inst;
   1876       evt_data.cmd_rcvd.cmd_len = data_len;
   1877 
   1878       if (data_len <= NFA_MAX_HCI_CMD_LEN)
   1879         memcpy(evt_data.cmd_rcvd.cmd_data, p_data, data_len);
   1880 
   1881       nfa_hciu_send_to_app(NFA_HCI_CMD_RCVD_EVT, &evt_data, app_handle);
   1882       break;
   1883   }
   1884 }
   1885 
   1886 /*******************************************************************************
   1887 **
   1888 ** Function         nfa_hci_handle_generic_gate_rsp
   1889 **
   1890 ** Description      This function handles all generic gates (excluding
   1891 **                  connectivity) response
   1892 **
   1893 ** Returns          none
   1894 **
   1895 *******************************************************************************/
   1896 static void nfa_hci_handle_generic_gate_rsp(uint8_t* p_data, uint8_t data_len,
   1897                                             tNFA_HCI_DYN_PIPE* p_pipe) {
   1898   tNFA_HCI_EVT_DATA evt_data;
   1899   tNFA_STATUS status = NFA_STATUS_OK;
   1900 
   1901   if (nfa_hci_cb.inst != NFA_HCI_ANY_OK) status = NFA_STATUS_FAILED;
   1902 
   1903   if (nfa_hci_cb.cmd_sent == NFA_HCI_ANY_OPEN_PIPE) {
   1904     if (status == NFA_STATUS_OK) p_pipe->pipe_state = NFA_HCI_PIPE_OPENED;
   1905 
   1906     nfa_hci_cb.nv_write_needed = true;
   1907     /* Tell application */
   1908     evt_data.opened.status = status;
   1909     evt_data.opened.pipe = p_pipe->pipe_id;
   1910 
   1911     nfa_hciu_send_to_app(NFA_HCI_OPEN_PIPE_EVT, &evt_data,
   1912                          nfa_hci_cb.app_in_use);
   1913   } else if (nfa_hci_cb.cmd_sent == NFA_HCI_ANY_CLOSE_PIPE) {
   1914     p_pipe->pipe_state = NFA_HCI_PIPE_CLOSED;
   1915 
   1916     nfa_hci_cb.nv_write_needed = true;
   1917     /* Tell application */
   1918     evt_data.opened.status = status;
   1919     ;
   1920     evt_data.opened.pipe = p_pipe->pipe_id;
   1921 
   1922     nfa_hciu_send_to_app(NFA_HCI_CLOSE_PIPE_EVT, &evt_data,
   1923                          nfa_hci_cb.app_in_use);
   1924   } else if (nfa_hci_cb.cmd_sent == NFA_HCI_ANY_GET_PARAMETER) {
   1925     /* Tell application */
   1926     evt_data.registry.status = status;
   1927     evt_data.registry.pipe = p_pipe->pipe_id;
   1928     evt_data.registry.data_len = data_len;
   1929     evt_data.registry.index = nfa_hci_cb.param_in_use;
   1930 
   1931     memcpy(evt_data.registry.reg_data, p_data, data_len);
   1932 
   1933     nfa_hciu_send_to_app(NFA_HCI_GET_REG_RSP_EVT, &evt_data,
   1934                          nfa_hci_cb.app_in_use);
   1935   } else if (nfa_hci_cb.cmd_sent == NFA_HCI_ANY_SET_PARAMETER) {
   1936     /* Tell application */
   1937     evt_data.registry.status = status;
   1938     ;
   1939     evt_data.registry.pipe = p_pipe->pipe_id;
   1940 
   1941     nfa_hciu_send_to_app(NFA_HCI_SET_REG_RSP_EVT, &evt_data,
   1942                          nfa_hci_cb.app_in_use);
   1943   } else {
   1944     /* Could be a response to application specific command sent, pass it on */
   1945     evt_data.rsp_rcvd.status = NFA_STATUS_OK;
   1946     evt_data.rsp_rcvd.pipe = p_pipe->pipe_id;
   1947     ;
   1948     evt_data.rsp_rcvd.rsp_code = nfa_hci_cb.inst;
   1949     evt_data.rsp_rcvd.rsp_len = data_len;
   1950 
   1951     if (data_len <= NFA_MAX_HCI_RSP_LEN)
   1952       memcpy(evt_data.rsp_rcvd.rsp_data, p_data, data_len);
   1953 
   1954     nfa_hciu_send_to_app(NFA_HCI_RSP_RCVD_EVT, &evt_data,
   1955                          nfa_hci_cb.app_in_use);
   1956   }
   1957 }
   1958 
   1959 /*******************************************************************************
   1960 **
   1961 ** Function         nfa_hci_handle_connectivity_gate_pkt
   1962 **
   1963 ** Description      This function handles incoming connectivity gate packets
   1964 **
   1965 ** Returns          none
   1966 **
   1967 *******************************************************************************/
   1968 static void nfa_hci_handle_connectivity_gate_pkt(uint8_t* p_data,
   1969                                                  uint16_t data_len,
   1970                                                  tNFA_HCI_DYN_PIPE* p_pipe) {
   1971   tNFA_HCI_EVT_DATA evt_data;
   1972 
   1973   if (nfa_hci_cb.type == NFA_HCI_COMMAND_TYPE) {
   1974     switch (nfa_hci_cb.inst) {
   1975       case NFA_HCI_ANY_OPEN_PIPE:
   1976       case NFA_HCI_ANY_CLOSE_PIPE:
   1977         nfa_hci_handle_pipe_open_close_cmd(p_pipe);
   1978         break;
   1979 
   1980       case NFA_HCI_CON_PRO_HOST_REQUEST:
   1981         /* A request to the DH to activate another host. This is not supported
   1982          * for */
   1983         /* now, we will implement it when the spec is clearer and UICCs need it.
   1984          */
   1985         nfa_hciu_send_msg(p_pipe->pipe_id, NFA_HCI_RESPONSE_TYPE,
   1986                           NFA_HCI_ANY_E_CMD_NOT_SUPPORTED, 0, NULL);
   1987         break;
   1988 
   1989       default:
   1990         nfa_hciu_send_msg(p_pipe->pipe_id, NFA_HCI_RESPONSE_TYPE,
   1991                           NFA_HCI_ANY_E_CMD_NOT_SUPPORTED, 0, NULL);
   1992         break;
   1993     }
   1994   } else if (nfa_hci_cb.type == NFA_HCI_RESPONSE_TYPE) {
   1995     if ((nfa_hci_cb.cmd_sent == NFA_HCI_ANY_OPEN_PIPE) &&
   1996         (nfa_hci_cb.inst == NFA_HCI_ANY_OK))
   1997       p_pipe->pipe_state = NFA_HCI_PIPE_OPENED;
   1998     else if (nfa_hci_cb.cmd_sent == NFA_HCI_ANY_CLOSE_PIPE)
   1999       p_pipe->pipe_state = NFA_HCI_PIPE_CLOSED;
   2000 
   2001     /* Could be a response to application specific command sent, pass it on */
   2002     evt_data.rsp_rcvd.status = NFA_STATUS_OK;
   2003     evt_data.rsp_rcvd.pipe = p_pipe->pipe_id;
   2004     ;
   2005     evt_data.rsp_rcvd.rsp_code = nfa_hci_cb.inst;
   2006     evt_data.rsp_rcvd.rsp_len = data_len;
   2007 
   2008     if (data_len <= NFA_MAX_HCI_RSP_LEN)
   2009       memcpy(evt_data.rsp_rcvd.rsp_data, p_data, data_len);
   2010 
   2011     nfa_hciu_send_to_app(NFA_HCI_RSP_RCVD_EVT, &evt_data,
   2012                          nfa_hci_cb.app_in_use);
   2013   } else if (nfa_hci_cb.type == NFA_HCI_EVENT_TYPE) {
   2014     evt_data.rcvd_evt.pipe = p_pipe->pipe_id;
   2015     evt_data.rcvd_evt.evt_code = nfa_hci_cb.inst;
   2016     evt_data.rcvd_evt.evt_len = data_len;
   2017     evt_data.rcvd_evt.p_evt_buf = p_data;
   2018 
   2019     /* notify NFA_HCI_EVENT_RCVD_EVT to the application */
   2020     nfa_hciu_send_to_apps_handling_connectivity_evts(NFA_HCI_EVENT_RCVD_EVT,
   2021                                                      &evt_data);
   2022   }
   2023 }
   2024 
   2025 /*******************************************************************************
   2026 **
   2027 ** Function         nfa_hci_handle_loopback_gate_pkt
   2028 **
   2029 ** Description      This function handles incoming loopback gate hci events
   2030 **
   2031 ** Returns          none
   2032 **
   2033 *******************************************************************************/
   2034 static void nfa_hci_handle_loopback_gate_pkt(uint8_t* p_data, uint16_t data_len,
   2035                                              tNFA_HCI_DYN_PIPE* p_pipe) {
   2036   uint8_t data[1];
   2037   uint8_t rsp_len = 0;
   2038   tNFA_HCI_RESPONSE response = NFA_HCI_ANY_OK;
   2039   tNFA_HCI_EVT_DATA evt_data;
   2040 
   2041   /* Check if data packet is a command, response or event */
   2042   if (nfa_hci_cb.type == NFA_HCI_COMMAND_TYPE) {
   2043     if (nfa_hci_cb.inst == NFA_HCI_ANY_OPEN_PIPE) {
   2044       data[0] = 0;
   2045       rsp_len = 1;
   2046       p_pipe->pipe_state = NFA_HCI_PIPE_OPENED;
   2047     } else if (nfa_hci_cb.inst == NFA_HCI_ANY_CLOSE_PIPE) {
   2048       p_pipe->pipe_state = NFA_HCI_PIPE_CLOSED;
   2049     } else
   2050       response = NFA_HCI_ANY_E_CMD_NOT_SUPPORTED;
   2051 
   2052     nfa_hciu_send_msg(p_pipe->pipe_id, NFA_HCI_RESPONSE_TYPE, response, rsp_len,
   2053                       data);
   2054   } else if (nfa_hci_cb.type == NFA_HCI_RESPONSE_TYPE) {
   2055     if ((nfa_hci_cb.cmd_sent == NFA_HCI_ANY_OPEN_PIPE) &&
   2056         (nfa_hci_cb.inst == NFA_HCI_ANY_OK))
   2057       p_pipe->pipe_state = NFA_HCI_PIPE_OPENED;
   2058     else if (nfa_hci_cb.cmd_sent == NFA_HCI_ANY_CLOSE_PIPE)
   2059       p_pipe->pipe_state = NFA_HCI_PIPE_CLOSED;
   2060 
   2061     /* Could be a response to application specific command sent, pass it on */
   2062     evt_data.rsp_rcvd.status = NFA_STATUS_OK;
   2063     evt_data.rsp_rcvd.pipe = p_pipe->pipe_id;
   2064     ;
   2065     evt_data.rsp_rcvd.rsp_code = nfa_hci_cb.inst;
   2066     evt_data.rsp_rcvd.rsp_len = data_len;
   2067 
   2068     if (data_len <= NFA_MAX_HCI_RSP_LEN)
   2069       memcpy(evt_data.rsp_rcvd.rsp_data, p_data, data_len);
   2070 
   2071     nfa_hciu_send_to_app(NFA_HCI_RSP_RCVD_EVT, &evt_data,
   2072                          nfa_hci_cb.app_in_use);
   2073   } else if (nfa_hci_cb.type == NFA_HCI_EVENT_TYPE) {
   2074     if (nfa_hci_cb.w4_rsp_evt) {
   2075       evt_data.rcvd_evt.pipe = p_pipe->pipe_id;
   2076       evt_data.rcvd_evt.evt_code = nfa_hci_cb.inst;
   2077       evt_data.rcvd_evt.evt_len = data_len;
   2078       evt_data.rcvd_evt.p_evt_buf = p_data;
   2079 
   2080       nfa_hciu_send_to_app(NFA_HCI_EVENT_RCVD_EVT, &evt_data,
   2081                            nfa_hci_cb.app_in_use);
   2082     } else if (nfa_hci_cb.inst == NFA_HCI_EVT_POST_DATA) {
   2083       /* Send back the same data we got */
   2084       nfa_hciu_send_msg(p_pipe->pipe_id, NFA_HCI_EVENT_TYPE,
   2085                         NFA_HCI_EVT_POST_DATA, data_len, p_data);
   2086     }
   2087   }
   2088 }
   2089 
   2090 /*******************************************************************************
   2091 **
   2092 ** Function         nfa_hci_handle_generic_gate_evt
   2093 **
   2094 ** Description      This function handles incoming Generic gate hci events
   2095 **
   2096 ** Returns          none
   2097 **
   2098 *******************************************************************************/
   2099 static void nfa_hci_handle_generic_gate_evt(uint8_t* p_data, uint16_t data_len,
   2100                                             tNFA_HCI_DYN_GATE* p_gate,
   2101                                             tNFA_HCI_DYN_PIPE* p_pipe) {
   2102   tNFA_HCI_EVT_DATA evt_data;
   2103 
   2104   evt_data.rcvd_evt.pipe = p_pipe->pipe_id;
   2105   evt_data.rcvd_evt.evt_code = nfa_hci_cb.inst;
   2106   evt_data.rcvd_evt.evt_len = data_len;
   2107 
   2108   if (nfa_hci_cb.assembly_failed)
   2109     evt_data.rcvd_evt.status = NFA_STATUS_BUFFER_FULL;
   2110   else
   2111     evt_data.rcvd_evt.status = NFA_STATUS_OK;
   2112 
   2113   evt_data.rcvd_evt.p_evt_buf = p_data;
   2114   nfa_hci_cb.rsp_buf_size = 0;
   2115   nfa_hci_cb.p_rsp_buf = NULL;
   2116 
   2117   /* notify NFA_HCI_EVENT_RCVD_EVT to the application */
   2118   nfa_hciu_send_to_app(NFA_HCI_EVENT_RCVD_EVT, &evt_data, p_gate->gate_owner);
   2119 }
   2120