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