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