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