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 utility 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_dm_int.h"
31#include "nfa_hci_api.h"
32#include "nfa_hci_int.h"
33#include "nfa_nv_co.h"
34#include "nfa_mem_co.h"
35#include "nfa_hci_defs.h"
36
37static void handle_debug_loopback (BT_HDR *p_buf, UINT8 pipe, UINT8 type, UINT8 instruction);
38BOOLEAN HCI_LOOPBACK_DEBUG = FALSE;
39
40/*******************************************************************************
41**
42** Function         nfa_hciu_find_pipe_by_pid
43**
44** Description      look for the pipe control block based on pipe id
45**
46** Returns          pointer to the pipe control block, or NULL if not found
47**
48*******************************************************************************/
49tNFA_HCI_DYN_PIPE *nfa_hciu_find_pipe_by_pid (UINT8 pipe_id)
50{
51    tNFA_HCI_DYN_PIPE   *pp = nfa_hci_cb.cfg.dyn_pipes;
52    int                 xx  = 0;
53
54    /* Loop through looking for a match */
55    for ( ; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++)
56    {
57        if (pp->pipe_id == pipe_id)
58            return (pp);
59    }
60
61    /* If here, not found */
62    return (NULL);
63}
64
65/*******************************************************************************
66**
67** Function         nfa_hciu_find_gate_by_gid
68**
69** Description      Find the gate control block for the given gate id
70**
71** Returns          pointer to the gate control block, or NULL if not found
72**
73*******************************************************************************/
74tNFA_HCI_DYN_GATE *nfa_hciu_find_gate_by_gid (UINT8 gate_id)
75{
76    tNFA_HCI_DYN_GATE *pg = nfa_hci_cb.cfg.dyn_gates;
77    int               xx  = 0;
78
79    for ( ; xx < NFA_HCI_MAX_GATE_CB; xx++, pg++)
80    {
81        if (pg->gate_id == gate_id)
82            return (pg);
83    }
84
85    return (NULL);
86}
87
88/*******************************************************************************
89**
90** Function         nfa_hciu_find_gate_by_owner
91**
92** Description      Find the the first gate control block for the given owner
93**
94** Returns          pointer to the gate control block, or NULL if not found
95**
96*******************************************************************************/
97tNFA_HCI_DYN_GATE *nfa_hciu_find_gate_by_owner (tNFA_HANDLE app_handle)
98{
99    tNFA_HCI_DYN_GATE *pg = nfa_hci_cb.cfg.dyn_gates;
100    int               xx  = 0;
101
102    for ( ; xx < NFA_HCI_MAX_GATE_CB; xx++, pg++)
103    {
104        if (pg->gate_owner == app_handle)
105            return (pg);
106    }
107
108    return (NULL);
109}
110
111/*******************************************************************************
112**
113** Function         nfa_hciu_find_gate_with_nopipes_by_owner
114**
115** Description      Find the the first gate control block with no pipes
116**                  for the given owner
117**
118** Returns          pointer to the gate control block, or NULL if not found
119**
120*******************************************************************************/
121tNFA_HCI_DYN_GATE *nfa_hciu_find_gate_with_nopipes_by_owner (tNFA_HANDLE app_handle)
122{
123    tNFA_HCI_DYN_GATE *pg = nfa_hci_cb.cfg.dyn_gates;
124    int               xx  = 0;
125
126    for ( ; xx < NFA_HCI_MAX_GATE_CB; xx++, pg++)
127    {
128        if (  (pg->gate_owner    == app_handle)
129            &&(pg->pipe_inx_mask == 0)  )
130            return (pg);
131    }
132
133    return (NULL);
134}
135
136/*******************************************************************************
137**
138** Function         nfa_hciu_count_pipes_on_gate
139**
140** Description      Count the number of pipes on the given gate
141**
142** Returns          the number of pipes on the gate
143**
144*******************************************************************************/
145UINT8 nfa_hciu_count_pipes_on_gate (tNFA_HCI_DYN_GATE *p_gate)
146{
147    int               xx    = 0;
148    UINT32            mask  = 1;
149    UINT8             count = 0;
150
151    for ( ; xx < NFA_HCI_MAX_PIPE_CB; xx++)
152    {
153        if ( p_gate->pipe_inx_mask & mask )
154            count++;
155
156        mask = mask << 1;
157    }
158
159    return (count);
160}
161
162/*******************************************************************************
163**
164** Function         nfa_hciu_count_open_pipes_on_gate
165**
166** Description      Count the number of opened pipes on the given gate
167**
168** Returns          the number of pipes in OPENED state on the gate
169**
170*******************************************************************************/
171UINT8 nfa_hciu_count_open_pipes_on_gate (tNFA_HCI_DYN_GATE *p_gate)
172{
173    tNFA_HCI_DYN_PIPE *pp   = nfa_hci_cb.cfg.dyn_pipes;
174    int               xx    = 0;
175    UINT32            mask  = 1;
176    UINT8             count = 0;
177
178    for ( ; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++)
179    {
180        /* For each pipe on this gate, check if it is open */
181        if ((p_gate->pipe_inx_mask & mask) && (pp->pipe_state == NFA_HCI_PIPE_OPENED))
182            count++;
183
184        mask = mask << 1;
185    }
186
187    return (count);
188}
189
190/*******************************************************************************
191**
192** Function         nfa_hciu_get_gate_owner
193**
194** Description      Find the application that owns a gate
195**
196** Returns          application handle
197**
198*******************************************************************************/
199tNFA_HANDLE nfa_hciu_get_gate_owner (UINT8 gate_id)
200{
201    tNFA_HCI_DYN_GATE   *pg;
202
203    if ((pg = nfa_hciu_find_gate_by_gid (gate_id)) == NULL)
204        return (NFA_HANDLE_INVALID);
205
206    return (pg->gate_owner);
207}
208
209/*******************************************************************************
210**
211** Function         nfa_hciu_get_pipe_owner
212**
213** Description      Find the application that owns a pipe
214**
215** Returns          application handle
216**
217*******************************************************************************/
218tNFA_HANDLE nfa_hciu_get_pipe_owner (UINT8 pipe_id)
219{
220    tNFA_HCI_DYN_PIPE   *pp;
221    tNFA_HCI_DYN_GATE   *pg;
222
223    if ((pp = nfa_hciu_find_pipe_by_pid (pipe_id)) == NULL)
224        return (NFA_HANDLE_INVALID);
225
226    if ((pg = nfa_hciu_find_gate_by_gid (pp->local_gate)) == NULL)
227        return (NFA_HANDLE_INVALID);
228
229    return (pg->gate_owner);
230}
231
232
233/*******************************************************************************
234**
235** Function         nfa_hciu_alloc_gate
236**
237** Description      Allocate an gate control block
238**
239** Returns          pointer to the allocated gate, or NULL if cannot allocate
240**
241*******************************************************************************/
242tNFA_HCI_DYN_GATE *nfa_hciu_alloc_gate (UINT8 gate_id, tNFA_HANDLE app_handle)
243{
244    tNFA_HCI_DYN_GATE   *pg;
245    int                 xx;
246    UINT8               app_inx = app_handle & NFA_HANDLE_MASK;
247
248
249    /* First, check if the application handle is valid */
250    if (  (gate_id != NFA_HCI_CONNECTIVITY_GATE)
251        &&(gate_id < NFA_HCI_FIRST_PROP_GATE)
252        &&((  (app_handle & NFA_HANDLE_GROUP_MASK) != NFA_HANDLE_GROUP_HCI)
253            ||(app_inx >= NFA_HCI_MAX_APP_CB)
254            ||(nfa_hci_cb.p_app_cback[app_inx] == NULL))  )
255    {
256        return (NULL);
257    }
258
259    if (gate_id != 0)
260    {
261        if ((pg = nfa_hciu_find_gate_by_gid (gate_id)) != NULL)
262            return (pg);
263    }
264    else
265    {
266        /* If gate_id is 0, we need to assign a free one */
267        /* Loop through all possible gate IDs checking if they are already used */
268        for (gate_id = NFA_HCI_FIRST_HOST_SPECIFIC_GENERIC_GATE; gate_id <= NFA_HCI_LAST_PROP_GATE; gate_id++)
269        {
270            /* Skip connectivity gate */
271            if (gate_id == NFA_HCI_CONNECTIVITY_GATE) gate_id++;
272
273            /* Check if the gate is already allocated */
274            if (nfa_hciu_find_gate_by_gid (gate_id) == NULL)
275                break;
276        }
277        if (gate_id > NFA_HCI_LAST_PROP_GATE)
278        {
279            NFA_TRACE_ERROR2 ("nfa_hci_alloc_gate - no free Gate ID: %u  App Handle: 0x%04x", gate_id, app_handle);
280            return (NULL);
281        }
282    }
283
284    /* Now look for a free control block */
285    for (xx = 0, pg = nfa_hci_cb.cfg.dyn_gates; xx < NFA_HCI_MAX_GATE_CB; xx++, pg++)
286    {
287        if (pg->gate_id == 0)
288        {
289            /* Found a free gate control block */
290            pg->gate_id       = gate_id;
291            pg->gate_owner    = app_handle;
292            pg->pipe_inx_mask = 0;
293
294            NFA_TRACE_DEBUG2 ("nfa_hciu_alloc_gate id:%d  app_handle: 0x%04x", gate_id, app_handle);
295
296            nfa_hci_cb.nv_write_needed = TRUE;
297            return (pg);
298        }
299    }
300
301    /* If here, no free gate control block */
302    NFA_TRACE_ERROR2 ("nfa_hci_alloc_gate - no CB  Gate ID: %u  App Handle: 0x%04x", gate_id, app_handle);
303    return (NULL);
304}
305
306/*******************************************************************************
307**
308** Function         nfa_hciu_send_msg
309**
310** Description      This function will fragment the given packet, if necessary
311**                  and send it on the given pipe.
312**
313** Returns          status
314**
315*******************************************************************************/
316tNFA_STATUS nfa_hciu_send_msg (UINT8 pipe_id, UINT8 type, UINT8 instruction, UINT16 msg_len, UINT8 *p_msg)
317{
318    BT_HDR          *p_buf;
319    UINT8           *p_data;
320    BOOLEAN          first_pkt = TRUE;
321    UINT16          data_len;
322    tNFA_STATUS     status = NFA_STATUS_OK;
323    UINT16          max_seg_hcp_pkt_size = nfa_hci_cb.buff_size - NCI_DATA_HDR_SIZE;
324
325#if (BT_TRACE_VERBOSE == TRUE)
326    char    buff[100];
327
328    NFA_TRACE_DEBUG3 ("nfa_hciu_send_msg pipe_id:%d   %s  len:%d",
329                      pipe_id, nfa_hciu_get_type_inst_names (pipe_id, type, instruction, buff), msg_len);
330#else
331    NFA_TRACE_DEBUG4 ("nfa_hciu_send_msg pipe_id:%d   Type: %u  Inst: %u  len: %d",
332                      pipe_id, type, instruction, msg_len);
333#endif
334
335    if (instruction == NFA_HCI_ANY_GET_PARAMETER)
336        nfa_hci_cb.param_in_use = *p_msg;
337
338    while ((first_pkt == TRUE) || (msg_len != 0))
339    {
340        if ((p_buf = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) != NULL)
341        {
342            p_buf->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
343
344            /* First packet has a 2-byte header, subsequent fragments have a 1-byte header */
345            data_len = first_pkt ? (max_seg_hcp_pkt_size - 2) : (max_seg_hcp_pkt_size - 1);
346
347            p_data = (UINT8 *) (p_buf + 1) + p_buf->offset;
348
349            /* Last or only segment has "no fragmentation" bit set */
350            if (msg_len > data_len)
351            {
352                *p_data++ = (NFA_HCI_MESSAGE_FRAGMENTATION << 7) | (pipe_id & 0x7F);
353            }
354            else
355            {
356                data_len = msg_len;
357                *p_data++ = (NFA_HCI_NO_MESSAGE_FRAGMENTATION << 7) | (pipe_id & 0x7F);
358            }
359
360            p_buf->len = 1;
361
362            /* Message header only goes in the first segment */
363            if (first_pkt)
364            {
365                first_pkt = FALSE;
366                *p_data++ = (type << 6) | instruction;
367                p_buf->len++;
368            }
369
370            if (data_len != 0)
371            {
372                memcpy (p_data, p_msg, data_len);
373
374                p_buf->len += data_len;
375                msg_len    -= data_len;
376                if (msg_len > 0)
377                    p_msg      += data_len;
378            }
379
380#if (BT_TRACE_PROTOCOL == TRUE)
381            DispHcp (((UINT8 *) (p_buf + 1) + p_buf->offset), p_buf->len, FALSE, (BOOLEAN) ((p_buf->len - data_len) == 2));
382#endif
383
384            if (HCI_LOOPBACK_DEBUG)
385                handle_debug_loopback (p_buf, pipe_id, type, instruction);
386            else
387                status = NFC_SendData (nfa_hci_cb.conn_id, p_buf);
388        }
389        else
390        {
391            NFA_TRACE_ERROR0 ("nfa_hciu_send_data_packet no buffers");
392            status = NFA_STATUS_NO_BUFFERS;
393            break;
394        }
395    }
396
397    /* Start timer if response to wait for a particular time for the response  */
398    if (type == NFA_HCI_COMMAND_TYPE)
399    {
400        nfa_hci_cb.cmd_sent = instruction;
401
402        if (nfa_hci_cb.hci_state == NFA_HCI_STATE_IDLE)
403            nfa_hci_cb.hci_state = NFA_HCI_STATE_WAIT_RSP;
404
405        nfa_sys_start_timer (&nfa_hci_cb.timer, NFA_HCI_RSP_TIMEOUT_EVT, p_nfa_hci_cfg->hcp_response_timeout);
406    }
407
408    return status;
409}
410
411/*******************************************************************************
412**
413** Function         nfa_hciu_get_allocated_gate_list
414**
415** Description      fills in a list of allocated gates
416**
417** Returns          the number of gates
418**
419*******************************************************************************/
420UINT8 nfa_hciu_get_allocated_gate_list (UINT8 *p_gate_list)
421{
422    tNFA_HCI_DYN_GATE   *p_cb;
423    int                 xx;
424    UINT8               count = 0;
425
426    for (xx = 0, p_cb = nfa_hci_cb.cfg.dyn_gates; xx < NFA_HCI_MAX_GATE_CB; xx++, p_cb++)
427    {
428        if (p_cb->gate_id != 0)
429        {
430            *p_gate_list++ = p_cb->gate_id;
431            count++;
432        }
433    }
434
435    NFA_TRACE_DEBUG1 ("nfa_hciu_get_allocated_gate_list () returns: %u", count);
436
437    return (count);
438}
439
440/*******************************************************************************
441**
442** Function         nfa_hciu_alloc_pipe
443**
444** Description      Allocate a pipe control block
445**
446** Returns          pointer to the pipe control block, or NULL if
447**                  cannot allocate
448**
449*******************************************************************************/
450tNFA_HCI_DYN_PIPE *nfa_hciu_alloc_pipe (UINT8 pipe_id)
451{
452    UINT8               xx;
453    tNFA_HCI_DYN_PIPE   *pp;
454
455    /* If we already have a pipe of the same ID, release it first it */
456    if ((pp = nfa_hciu_find_pipe_by_pid (pipe_id)) != NULL)
457    {
458        if (pipe_id > NFA_HCI_LAST_DYNAMIC_PIPE)
459            return pp;
460        nfa_hciu_release_pipe (pipe_id);
461    }
462
463    /* Look for a free pipe control block */
464    for (xx = 0, pp = nfa_hci_cb.cfg.dyn_pipes ; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++)
465    {
466        if (pp->pipe_id == 0)
467        {
468            NFA_TRACE_DEBUG2 ("nfa_hciu_alloc_pipe:%d, index:%d", pipe_id, xx);
469            pp->pipe_id = pipe_id;
470
471            nfa_hci_cb.nv_write_needed = TRUE;
472            return (pp);
473        }
474    }
475
476    NFA_TRACE_DEBUG1 ("nfa_hciu_alloc_pipe:%d, NO free entries !!", pipe_id);
477    return (NULL);
478}
479
480/*******************************************************************************
481**
482** Function         nfa_hciu_release_gate
483**
484** Description      Remove a generic gate from gate list
485**
486** Returns          none
487**
488*******************************************************************************/
489void nfa_hciu_release_gate (UINT8 gate_id)
490{
491    tNFA_HCI_DYN_GATE   *p_gate = nfa_hciu_find_gate_by_gid (gate_id);
492
493    if (p_gate != NULL)
494    {
495        NFA_TRACE_DEBUG3 ("nfa_hciu_release_gate () ID: %d  owner: 0x%04x  pipe_inx_mask: 0x%04x",
496                          gate_id, p_gate->gate_owner, p_gate->pipe_inx_mask);
497
498        p_gate->gate_id       = 0;
499        p_gate->gate_owner    = 0;
500        p_gate->pipe_inx_mask = 0;
501
502        nfa_hci_cb.nv_write_needed = TRUE;
503    }
504    else
505    {
506        NFA_TRACE_WARNING1 ("nfa_hciu_release_gate () ID: %d  NOT FOUND", gate_id);
507    }
508}
509
510/*******************************************************************************
511**
512** Function         nfa_hciu_add_pipe_to_gate
513**
514** Description      Add pipe to generic gate
515**
516** Returns          NFA_STATUS_OK, if successfully add the pipe on to the gate
517**                  NFA_HCI_ADM_E_NO_PIPES_AVAILABLE, otherwise
518**
519*******************************************************************************/
520tNFA_HCI_RESPONSE nfa_hciu_add_pipe_to_gate (UINT8 pipe_id,   UINT8 local_gate,
521                                             UINT8 dest_host, UINT8 dest_gate)
522{
523    tNFA_HCI_DYN_GATE   *p_gate;
524    tNFA_HCI_DYN_PIPE   *p_pipe;
525    UINT8               pipe_index;
526
527    p_gate = nfa_hciu_find_gate_by_gid (local_gate);
528
529    if (p_gate != NULL)
530    {
531        /* Allocate a pipe control block */
532        if ((p_pipe = nfa_hciu_alloc_pipe (pipe_id)) != NULL)
533        {
534            p_pipe->pipe_id     = pipe_id;
535            p_pipe->pipe_state  = NFA_HCI_PIPE_CLOSED;
536            p_pipe->dest_host   = dest_host;
537            p_pipe->dest_gate   = dest_gate;
538            p_pipe->local_gate  = local_gate;
539
540            /* Save the pipe in the gate that it belongs to */
541            pipe_index = (UINT8) (p_pipe - nfa_hci_cb.cfg.dyn_pipes);
542            p_gate->pipe_inx_mask |= (UINT32) (1 << pipe_index);
543
544            NFA_TRACE_DEBUG4 ("nfa_hciu_add_pipe_to_gate  Gate ID: 0x%02x  Pipe ID: 0x%02x  pipe_index: %u  App Handle: 0x%08x",
545                              local_gate, pipe_id, pipe_index, p_gate->gate_owner);
546            return (NFA_HCI_ANY_OK);
547        }
548    }
549
550    NFA_TRACE_DEBUG1 ("nfa_hciu_add_pipe_to_gate: 0x%02x  NOT FOUND", local_gate);
551
552    return (NFA_HCI_ADM_E_NO_PIPES_AVAILABLE);
553}
554
555/*******************************************************************************
556**
557** Function         nfa_hciu_add_pipe_to_static_gate
558**
559** Description      Add pipe to identity management gate
560**
561** Returns          NFA_HCI_ANY_OK, if successfully add the pipe on to the gate
562**                  NFA_HCI_ADM_E_NO_PIPES_AVAILABLE, otherwise
563**
564*******************************************************************************/
565tNFA_HCI_RESPONSE nfa_hciu_add_pipe_to_static_gate (UINT8 local_gate, UINT8 pipe_id, UINT8 dest_host, UINT8 dest_gate)
566{
567    tNFA_HCI_DYN_PIPE   *p_pipe;
568    UINT8               pipe_index;
569
570    NFA_TRACE_EVENT4 ("nfa_hciu_add_pipe_to_static_gate (%u)  Pipe: 0x%02x  Dest Host: 0x%02x  Dest Gate: 0x%02x)",
571                      local_gate, pipe_id, dest_host, dest_gate);
572
573    /* Allocate a pipe control block */
574    if ((p_pipe = nfa_hciu_alloc_pipe (pipe_id)) != NULL)
575    {
576        p_pipe->pipe_id     = pipe_id;
577        p_pipe->pipe_state  = NFA_HCI_PIPE_CLOSED;
578        p_pipe->dest_host   = dest_host;
579        p_pipe->dest_gate   = dest_gate;
580        p_pipe->local_gate  = local_gate;
581
582        /* If this is the ID gate, save the pipe index in the ID gate info     */
583        /* block. Note that for loopback, it is enough to just create the pipe */
584        if (local_gate == NFA_HCI_IDENTITY_MANAGEMENT_GATE)
585        {
586            pipe_index = (UINT8) (p_pipe - nfa_hci_cb.cfg.dyn_pipes);
587            nfa_hci_cb.cfg.id_mgmt_gate.pipe_inx_mask  |= (UINT32) (1 << pipe_index);
588        }
589        return NFA_HCI_ANY_OK;
590    }
591
592    return NFA_HCI_ADM_E_NO_PIPES_AVAILABLE;
593}
594
595/*******************************************************************************
596**
597** Function         nfa_hciu_find_active_pipe_by_owner
598**
599** Description      Find the first pipe associated with the given app
600**
601** Returns          pointer to pipe, or NULL if none found
602**
603*******************************************************************************/
604tNFA_HCI_DYN_PIPE *nfa_hciu_find_active_pipe_by_owner (tNFA_HANDLE app_handle)
605{
606    tNFA_HCI_DYN_GATE   *pg;
607    tNFA_HCI_DYN_PIPE   *pp;
608    int                 xx;
609
610    NFA_TRACE_DEBUG1 ("nfa_hciu_find_pipe_by_owner () app_handle:0x%x", app_handle);
611
612    /* Loop through all pipes looking for the owner */
613    for (xx = 0, pp = nfa_hci_cb.cfg.dyn_pipes; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++)
614    {
615        if (  (pp->pipe_id != 0)
616            &&(pp->pipe_id >= NFA_HCI_FIRST_DYNAMIC_PIPE)
617            &&(pp->pipe_id <= NFA_HCI_LAST_DYNAMIC_PIPE)
618            &&(nfa_hciu_is_active_host (pp->dest_host))  )
619        {
620            if (  ((pg = nfa_hciu_find_gate_by_gid (pp->local_gate)) != NULL)
621                &&(pg->gate_owner == app_handle) )
622                return (pp);
623        }
624    }
625
626    /* If here, not found */
627    return (NULL);
628}
629
630/*******************************************************************************
631**
632** Function         nfa_hciu_check_pipe_between_gates
633**
634** Description      Check if there is a pipe between specified Terminal host
635**                  gate and and the specified UICC gate
636**
637** Returns          TRUE, if there exists a pipe between the two specified gated
638**                  FALSE, otherwise
639**
640*******************************************************************************/
641BOOLEAN nfa_hciu_check_pipe_between_gates (UINT8 local_gate, UINT8 dest_host, UINT8 dest_gate)
642{
643    tNFA_HCI_DYN_PIPE   *pp;
644    int                 xx;
645
646    NFA_TRACE_DEBUG3 ("nfa_hciu_check_pipe_between_gates () Local gate: 0x%02X, Host[0x%02X] gate: 0x%02X", local_gate, dest_host, dest_gate);
647
648    /* Loop through all pipes looking for the owner */
649    for (xx = 0, pp = nfa_hci_cb.cfg.dyn_pipes; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++)
650    {
651        if (  (pp->pipe_id != 0)
652            &&(pp->pipe_id >= NFA_HCI_FIRST_DYNAMIC_PIPE)
653            &&(pp->pipe_id <= NFA_HCI_LAST_DYNAMIC_PIPE)
654            &&(pp->local_gate == local_gate)
655            &&(pp->dest_host  == dest_host)
656            &&(pp->dest_gate  == dest_gate)  )
657        {
658            return (TRUE);
659        }
660    }
661
662    /* If here, not found */
663    return (FALSE);
664}
665
666/*******************************************************************************
667**
668** Function         nfa_hciu_find_pipe_by_owner
669**
670** Description      Find the first pipe associated with the given app
671**
672** Returns          pointer to pipe, or NULL if none found
673**
674*******************************************************************************/
675tNFA_HCI_DYN_PIPE *nfa_hciu_find_pipe_by_owner (tNFA_HANDLE app_handle)
676{
677    tNFA_HCI_DYN_GATE   *pg;
678    tNFA_HCI_DYN_PIPE   *pp;
679    int                 xx;
680
681    NFA_TRACE_DEBUG1 ("nfa_hciu_find_pipe_by_owner () app_handle:0x%x", app_handle);
682
683    /* Loop through all pipes looking for the owner */
684    for (xx = 0, pp = nfa_hci_cb.cfg.dyn_pipes; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++)
685    {
686        if (pp->pipe_id != 0)
687        {
688            if (  ((pg = nfa_hciu_find_gate_by_gid (pp->local_gate)) != NULL)
689                &&(pg->gate_owner == app_handle) )
690                return (pp);
691        }
692    }
693
694    /* If here, not found */
695    return (NULL);
696}
697
698/*******************************************************************************
699**
700** Function         nfa_hciu_find_pipe_on_gate
701**
702** Description      Find the first pipe associated with the given gate
703**
704** Returns          pointer to pipe, or NULL if none found
705**
706*******************************************************************************/
707tNFA_HCI_DYN_PIPE *nfa_hciu_find_pipe_on_gate (UINT8 gate_id)
708{
709    tNFA_HCI_DYN_GATE   *pg;
710    tNFA_HCI_DYN_PIPE   *pp;
711    int                 xx;
712
713    NFA_TRACE_DEBUG1 ("nfa_hciu_find_pipe_on_gate () Gate:0x%x", gate_id);
714
715    /* Loop through all pipes looking for the owner */
716    for (xx = 0, pp = nfa_hci_cb.cfg.dyn_pipes; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++)
717    {
718        if (pp->pipe_id != 0)
719        {
720            if (  ((pg = nfa_hciu_find_gate_by_gid (pp->local_gate)) != NULL)
721                &&(pg->gate_id == gate_id) )
722                return (pp);
723        }
724    }
725
726    /* If here, not found */
727    return (NULL);
728}
729
730/*******************************************************************************
731**
732** Function         nfa_hciu_is_active_host
733**
734** Description      Check if the host is currently active
735**
736** Returns          TRUE, if the host is active in the host network
737**                  FALSE, if the host is not active in the host network
738**
739*******************************************************************************/
740BOOLEAN nfa_hciu_is_active_host (UINT8 host_id)
741{
742    UINT8   xx;
743
744    for (xx = 0; xx < NFA_HCI_MAX_HOST_IN_NETWORK; xx++)
745    {
746        if (nfa_hci_cb.inactive_host[xx] == host_id)
747            return FALSE;
748    }
749
750    return TRUE;
751}
752
753/*******************************************************************************
754**
755** Function         nfa_hciu_is_host_reseting
756**
757** Description      Check if the host is currently reseting
758**
759** Returns          TRUE, if the host is reseting
760**                  FALSE, if the host is not reseting
761**
762*******************************************************************************/
763BOOLEAN nfa_hciu_is_host_reseting (UINT8 host_id)
764{
765    UINT8   xx;
766
767    for (xx = 0; xx < NFA_HCI_MAX_HOST_IN_NETWORK; xx++)
768    {
769        if (nfa_hci_cb.reset_host[xx] == host_id)
770            return TRUE;
771    }
772
773    return FALSE;
774}
775
776/*******************************************************************************
777**
778** Function         nfa_hciu_is_no_host_resetting
779**
780** Description      Check if no host is reseting
781**
782** Returns          TRUE, if no host is resetting at this time
783**                  FALSE, if one or more host is resetting
784**
785*******************************************************************************/
786BOOLEAN nfa_hciu_is_no_host_resetting (void)
787{
788    UINT8   xx;
789
790    for (xx = 0; xx < NFA_HCI_MAX_HOST_IN_NETWORK; xx++)
791    {
792        if (nfa_hci_cb.reset_host[xx] != 0)
793            return FALSE;
794    }
795
796    return TRUE;
797}
798
799/*******************************************************************************
800**
801** Function         nfa_hciu_find_active_pipe_on_gate
802**
803** Description      Find the first active pipe associated with the given gate
804**
805** Returns          pointer to pipe, or NULL if none found
806**
807*******************************************************************************/
808tNFA_HCI_DYN_PIPE *nfa_hciu_find_active_pipe_on_gate (UINT8 gate_id)
809{
810    tNFA_HCI_DYN_GATE   *pg;
811    tNFA_HCI_DYN_PIPE   *pp;
812    int                 xx;
813
814    NFA_TRACE_DEBUG1 ("nfa_hciu_find_active_pipe_on_gate () Gate:0x%x", gate_id);
815
816    /* Loop through all pipes looking for the owner */
817    for (xx = 0, pp = nfa_hci_cb.cfg.dyn_pipes; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++)
818    {
819        if (  (pp->pipe_id != 0)
820            &&(pp->pipe_id >= NFA_HCI_FIRST_DYNAMIC_PIPE)
821            &&(pp->pipe_id <= NFA_HCI_LAST_DYNAMIC_PIPE)
822            &&(nfa_hciu_is_active_host (pp->dest_host))  )
823        {
824            if (  ((pg = nfa_hciu_find_gate_by_gid (pp->local_gate)) != NULL)
825                &&(pg->gate_id == gate_id) )
826                return (pp);
827        }
828    }
829
830    /* If here, not found */
831    return (NULL);
832}
833
834/*******************************************************************************
835**
836** Function         nfa_hciu_release_pipe
837**
838** Description      remove the specified pipe
839**
840** Returns          NFA_HCI_ANY_OK, if removed
841**                  NFA_HCI_ANY_E_NOK, if otherwise
842**
843*******************************************************************************/
844tNFA_HCI_RESPONSE nfa_hciu_release_pipe (UINT8 pipe_id)
845{
846    tNFA_HCI_DYN_GATE   *p_gate;
847    tNFA_HCI_DYN_PIPE   *p_pipe;
848    UINT8               pipe_index;
849
850    NFA_TRACE_EVENT1 ("nfa_hciu_release_pipe: %u", pipe_id);
851
852    if ((p_pipe = nfa_hciu_find_pipe_by_pid (pipe_id)) == NULL)
853        return (NFA_HCI_ANY_E_NOK);
854
855    if (pipe_id > NFA_HCI_LAST_DYNAMIC_PIPE)
856    {
857        NFA_TRACE_DEBUG1 ("ignore pipe: %d", pipe_id);
858        return (NFA_HCI_ANY_E_NOK);
859    }
860
861    pipe_index = (UINT8) (p_pipe - nfa_hci_cb.cfg.dyn_pipes);
862
863    if (p_pipe->local_gate == NFA_HCI_IDENTITY_MANAGEMENT_GATE)
864    {
865        /* Remove pipe from ID management gate */
866        nfa_hci_cb.cfg.id_mgmt_gate.pipe_inx_mask &= ~ (UINT32) (1 << pipe_index);
867    }
868    else
869    {
870        if ((p_gate = nfa_hciu_find_gate_by_gid (p_pipe->local_gate)) == NULL)
871        {
872            /* Mark the pipe control block as free */
873            p_pipe->pipe_id = 0;
874            return (NFA_HCI_ANY_E_NOK);
875        }
876
877        /* Remove pipe from gate */
878        p_gate->pipe_inx_mask &= ~ (UINT32) (1 << pipe_index);
879    }
880
881    /* Reset pipe control block */
882    memset (p_pipe,0,sizeof (tNFA_HCI_DYN_PIPE));
883    nfa_hci_cb.nv_write_needed = TRUE;
884    return NFA_HCI_ANY_OK;
885}
886
887/*******************************************************************************
888**
889** Function         nfa_hciu_remove_all_pipes_from_host
890**
891** Description      remove all the pipes that are connected to a specific host
892**
893** Returns          None
894**
895*******************************************************************************/
896void nfa_hciu_remove_all_pipes_from_host (UINT8 host)
897{
898    tNFA_HCI_DYN_GATE   *pg;
899    tNFA_HCI_DYN_PIPE   *pp;
900    int                 xx;
901    tNFA_HCI_EVT_DATA   evt_data;
902
903    NFA_TRACE_EVENT1 ("nfa_hciu_remove_all_pipes_from_host (0x%02x)", host);
904
905    /* Remove all pipes from the specified host connected to all generic gates */
906    for (xx = 0, pp = nfa_hci_cb.cfg.dyn_pipes; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++)
907    {
908        if (  (pp->pipe_id == 0)
909                    ||
910              (  (host != 0)
911               &&((pp->dest_host != host) || (pp->pipe_id > NFA_HCI_LAST_DYNAMIC_PIPE)))  )
912            continue;
913
914        if ((pg = nfa_hciu_find_gate_by_gid (pp->local_gate)) != NULL)
915        {
916            evt_data.deleted.status = NFA_STATUS_OK;
917            evt_data.deleted.pipe   = pp->pipe_id;
918
919            nfa_hciu_send_to_app (NFA_HCI_DELETE_PIPE_EVT, &evt_data, pg->gate_owner);
920        }
921        nfa_hciu_release_pipe (pp->pipe_id);
922    }
923}
924
925/*******************************************************************************
926**
927** Function         nfa_hciu_send_create_pipe_cmd
928**
929** Description      Create dynamic pipe between the specified gates
930**
931** Returns          status
932**
933*******************************************************************************/
934tNFA_STATUS nfa_hciu_send_create_pipe_cmd (UINT8 source_gate, UINT8 dest_host, UINT8 dest_gate)
935{
936    tNFA_STATUS         status;
937    UINT8               data[3];
938
939    data[0] = source_gate;
940    data[1] = dest_host;
941    data[2] = dest_gate;
942
943    NFA_TRACE_DEBUG3 ("nfa_hciu_send_create_pipe_cmd source_gate:%d, dest_host:%d, dest_gate:%d", source_gate, dest_host, dest_gate);
944
945    status = nfa_hciu_send_msg (NFA_HCI_ADMIN_PIPE, NFA_HCI_COMMAND_TYPE, NFA_HCI_ADM_CREATE_PIPE, 3, data);
946
947    return status;
948}
949
950/*******************************************************************************
951**
952** Function         nfa_hciu_send_delete_pipe_cmd
953**
954** Description      Delete the dynamic pipe
955**
956** Returns          None
957**
958*******************************************************************************/
959tNFA_STATUS nfa_hciu_send_delete_pipe_cmd (UINT8 pipe)
960{
961    tNFA_STATUS status;
962
963    NFA_TRACE_DEBUG1 ("nfa_hciu_send_delete_pipe_cmd: %d", pipe);
964
965    if (pipe > NFA_HCI_LAST_DYNAMIC_PIPE)
966    {
967        NFA_TRACE_DEBUG1 ("ignore pipe: %d", pipe);
968        return (NFA_HCI_ANY_E_NOK);
969    }
970    nfa_hci_cb.pipe_in_use = pipe;
971
972    status = nfa_hciu_send_msg (NFA_HCI_ADMIN_PIPE, NFA_HCI_COMMAND_TYPE, NFA_HCI_ADM_DELETE_PIPE, 1, &pipe);
973
974    return status;
975}
976
977
978/*******************************************************************************
979**
980** Function         nfa_hciu_send_clear_all_pipe_cmd
981**
982** Description      delete all the dynamic pipe connected to device host,
983**                  to close all static pipes connected to device host,
984**                  and to set registry values related to static pipes to
985**                  theri default values.
986**
987** Returns          None
988**
989*******************************************************************************/
990tNFA_STATUS nfa_hciu_send_clear_all_pipe_cmd (void)
991{
992    tNFA_STATUS status;
993    UINT16      id_ref_data = 0x0102;
994
995    NFA_TRACE_DEBUG0 ("nfa_hciu_send_clear_all_pipe_cmd");
996
997    status = nfa_hciu_send_msg (NFA_HCI_ADMIN_PIPE, NFA_HCI_COMMAND_TYPE, NFA_HCI_ADM_CLEAR_ALL_PIPE, 2, (UINT8 *) &id_ref_data);
998
999    return status;
1000}
1001
1002/*******************************************************************************
1003**
1004** Function         nfa_hciu_send_open_pipe_cmd
1005**
1006** Description      Open a closed pipe
1007**
1008** Returns          status
1009**
1010*******************************************************************************/
1011tNFA_STATUS nfa_hciu_send_open_pipe_cmd (UINT8 pipe)
1012{
1013    tNFA_STATUS status;
1014
1015    nfa_hci_cb.pipe_in_use = pipe;
1016
1017    status = nfa_hciu_send_msg (pipe, NFA_HCI_COMMAND_TYPE, NFA_HCI_ANY_OPEN_PIPE, 0, NULL);
1018
1019    return status;
1020}
1021
1022/*******************************************************************************
1023**
1024** Function         nfa_hciu_send_close_pipe_cmd
1025**
1026** Description      Close an opened pipe
1027**
1028** Returns          status
1029**
1030*******************************************************************************/
1031tNFA_STATUS nfa_hciu_send_close_pipe_cmd (UINT8 pipe)
1032{
1033    tNFA_STATUS status;
1034
1035    nfa_hci_cb.pipe_in_use = pipe;
1036
1037    status = nfa_hciu_send_msg (pipe, NFA_HCI_COMMAND_TYPE, NFA_HCI_ANY_CLOSE_PIPE, 0, NULL);
1038
1039    return status;
1040}
1041
1042/*******************************************************************************
1043**
1044** Function         nfa_hciu_send_get_param_cmd
1045**
1046** Description      Read a parameter value from gate registry
1047**
1048** Returns          None
1049**
1050*******************************************************************************/
1051tNFA_STATUS nfa_hciu_send_get_param_cmd (UINT8 pipe, UINT8 index)
1052{
1053    tNFA_STATUS status;
1054
1055    if ((status = nfa_hciu_send_msg (pipe, NFA_HCI_COMMAND_TYPE, NFA_HCI_ANY_GET_PARAMETER, 1, &index)) == NFC_STATUS_OK)
1056        nfa_hci_cb.param_in_use = index;
1057
1058    return status;
1059}
1060
1061/*******************************************************************************
1062**
1063** Function         nfa_hciu_send_set_param_cmd
1064**
1065** Description      Set a parameter value in a gate registry
1066**
1067** Returns          None
1068**
1069*******************************************************************************/
1070tNFA_STATUS nfa_hciu_send_set_param_cmd (UINT8 pipe, UINT8 index, UINT8 length, UINT8 *p_data)
1071{
1072    tNFA_STATUS status;
1073    UINT8       data[255];
1074
1075    data[0] = index;
1076
1077    memcpy (&data[1], p_data, length);
1078
1079    if ((status = nfa_hciu_send_msg (pipe, NFA_HCI_COMMAND_TYPE, NFA_HCI_ANY_SET_PARAMETER, (UINT16) (length + 1), data)) == NFC_STATUS_OK)
1080        nfa_hci_cb.param_in_use = index;
1081
1082    return status;
1083}
1084
1085
1086/*******************************************************************************
1087**
1088** Function         nfa_hciu_send_to_app
1089**
1090** Description      Send an event back to an application
1091**
1092** Returns          none
1093**
1094*******************************************************************************/
1095void nfa_hciu_send_to_app (tNFA_HCI_EVT event, tNFA_HCI_EVT_DATA *p_evt, tNFA_HANDLE app_handle)
1096{
1097    UINT8   app_inx = app_handle & NFA_HANDLE_MASK;
1098
1099    /* First, check if the application handle is valid */
1100    if (  ((app_handle & NFA_HANDLE_GROUP_MASK) == NFA_HANDLE_GROUP_HCI)
1101        &&(app_inx < NFA_HCI_MAX_APP_CB) )
1102    {
1103        if (nfa_hci_cb.p_app_cback[app_inx] != NULL)
1104        {
1105            nfa_hci_cb.p_app_cback[app_inx] (event, p_evt);
1106            return;
1107        }
1108    }
1109
1110    if (app_handle != NFA_HANDLE_INVALID)
1111    {
1112        NFA_TRACE_WARNING2 ("nfa_hciu_send_to_app no callback,  event: 0x%04x  app_handle: 0x%04x",
1113                            event, app_handle);
1114    }
1115}
1116
1117/*******************************************************************************
1118**
1119** Function         nfa_hciu_send_to_all_apps
1120**
1121** Description      Send an event back to all applications
1122**
1123** Returns          none
1124**
1125*******************************************************************************/
1126void nfa_hciu_send_to_all_apps (tNFA_HCI_EVT event, tNFA_HCI_EVT_DATA *p_evt)
1127{
1128    UINT8   app_inx;
1129
1130    for (app_inx = 0; app_inx < NFA_HCI_MAX_APP_CB; app_inx++)
1131    {
1132        if (nfa_hci_cb.p_app_cback[app_inx] != NULL)
1133            nfa_hci_cb.p_app_cback[app_inx] (event, p_evt);
1134    }
1135
1136}
1137
1138/*******************************************************************************
1139**
1140** Function         nfa_hciu_send_to_apps_handling_connectivity_evts
1141**
1142** Description      Send a connectivity event to all the application interested
1143**                  in connectivity events
1144**
1145** Returns          none
1146**
1147*******************************************************************************/
1148void nfa_hciu_send_to_apps_handling_connectivity_evts (tNFA_HCI_EVT event, tNFA_HCI_EVT_DATA *p_evt)
1149{
1150    UINT8   app_inx;
1151
1152    for (app_inx = 0; app_inx < NFA_HCI_MAX_APP_CB; app_inx++)
1153    {
1154        if (  (nfa_hci_cb.p_app_cback[app_inx] != NULL)
1155            &&(nfa_hci_cb.cfg.b_send_conn_evts[app_inx]))
1156
1157            nfa_hci_cb.p_app_cback[app_inx] (event, p_evt);
1158    }
1159
1160}
1161
1162#if (BT_TRACE_VERBOSE == TRUE)
1163/*******************************************************************************
1164**
1165** Function         nfa_hciu_get_response_name
1166**
1167** Description      This function returns the error code name.
1168**
1169** NOTE             conditionally compiled to save memory.
1170**
1171** Returns          pointer to the name
1172**
1173*******************************************************************************/
1174char *nfa_hciu_get_response_name (UINT8 rsp_code)
1175{
1176    switch (rsp_code)
1177    {
1178    case NFA_HCI_ANY_OK:
1179        return ("ANY_OK");
1180    case NFA_HCI_ANY_E_NOT_CONNECTED:
1181        return ("ANY_E_NOT_CONNECTED");
1182    case NFA_HCI_ANY_E_CMD_PAR_UNKNOWN:
1183        return ("ANY_E_CMD_PAR_UNKNOWN");
1184    case NFA_HCI_ANY_E_NOK:
1185        return ("ANY_E_NOK");
1186    case NFA_HCI_ADM_E_NO_PIPES_AVAILABLE:
1187        return ("ADM_E_NO_PIPES_AVAILABLE");
1188    case NFA_HCI_ANY_E_REG_PAR_UNKNOWN:
1189        return ("ANY_E_REG_PAR_UNKNOWN");
1190    case NFA_HCI_ANY_E_PIPE_NOT_OPENED:
1191        return ("ANY_E_PIPE_NOT_OPENED");
1192    case NFA_HCI_ANY_E_CMD_NOT_SUPPORTED:
1193        return ("ANY_E_CMD_NOT_SUPPORTED");
1194    case NFA_HCI_ANY_E_INHIBITED:
1195        return ("ANY_E_INHIBITED");
1196    case NFA_HCI_ANY_E_TIMEOUT:
1197        return ("ANY_E_TIMEOUT");
1198    case NFA_HCI_ANY_E_REG_ACCESS_DENIED:
1199        return ("ANY_E_REG_ACCESS_DENIED");
1200    case NFA_HCI_ANY_E_PIPE_ACCESS_DENIED:
1201        return ("ANY_E_PIPE_ACCESS_DENIED");
1202    default:
1203        return ("UNKNOWN");
1204    }
1205}
1206
1207/*******************************************************************************
1208**
1209** Function         nfa_hciu_type_2_str
1210**
1211** Description      This function returns the type name.
1212**
1213** Returns          pointer to the name
1214**
1215*******************************************************************************/
1216char *nfa_hciu_type_2_str(UINT8 type)
1217{
1218    switch (type)
1219    {
1220    case NFA_HCI_COMMAND_TYPE:
1221        return ("COMMAND");
1222    case NFA_HCI_EVENT_TYPE:
1223        return ("EVENT");
1224    case NFA_HCI_RESPONSE_TYPE:
1225        return ("RESPONSE");
1226    default:
1227        return ("UNKNOWN");
1228    }
1229}
1230
1231/*******************************************************************************
1232**
1233** Function         nfa_hciu_instr_2_str
1234**
1235** Description      This function returns the instruction name.
1236**
1237** Returns          pointer to the name
1238**
1239*******************************************************************************/
1240char *nfa_hciu_instr_2_str (UINT8 instruction)
1241{
1242    switch (instruction)
1243    {
1244    case NFA_HCI_ANY_SET_PARAMETER:
1245        return ("ANY_SET_PARAMETER");
1246    case NFA_HCI_ANY_GET_PARAMETER:
1247        return ("ANY_GET_PARAMETER");
1248    case NFA_HCI_ANY_OPEN_PIPE:
1249        return ("ANY_OPEN_PIPE");
1250    case NFA_HCI_ANY_CLOSE_PIPE:
1251        return ("ANY_CLOSE_PIPE");
1252    case NFA_HCI_ADM_CREATE_PIPE:
1253        return ("ADM_CREATE_PIPE");
1254    case NFA_HCI_ADM_DELETE_PIPE:
1255        return ("ADM_DELETE_PIPE");
1256    case NFA_HCI_ADM_NOTIFY_PIPE_CREATED:
1257        return ("ADM_NOTIFY_PIPE_CREATED");
1258    case NFA_HCI_ADM_NOTIFY_PIPE_DELETED:
1259        return ("ADM_NOTIFY_PIPE_DELETED");
1260    case NFA_HCI_ADM_CLEAR_ALL_PIPE:
1261        return ("ADM_CLEAR_ALL_PIPE");
1262    case NFA_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED:
1263        return ("ADM_NOTIFY_ALL_PIPE_CLEARED");
1264    default:
1265        return ("UNKNOWN");
1266    }
1267}
1268
1269
1270/*******************************************************************************
1271**
1272** Function         nfa_hciu_get_event_name
1273**
1274** Description      This function returns the event code name.
1275**
1276** Returns          pointer to the name
1277**
1278*******************************************************************************/
1279char *nfa_hciu_get_event_name (UINT16 event)
1280{
1281    switch (event)
1282    {
1283    case NFA_HCI_API_REGISTER_APP_EVT:        return ("API_REGISTER");
1284    case NFA_HCI_API_DEREGISTER_APP_EVT:      return ("API_DEREGISTER");
1285    case NFA_HCI_API_GET_APP_GATE_PIPE_EVT:   return ("API_GET_GATE_LIST");
1286    case NFA_HCI_API_ALLOC_GATE_EVT:          return ("API_ALLOC_GATE");
1287    case NFA_HCI_API_DEALLOC_GATE_EVT:        return ("API_DEALLOC_GATE");
1288    case NFA_HCI_API_GET_HOST_LIST_EVT:       return ("API_GET_HOST_LIST");
1289    case NFA_HCI_API_GET_REGISTRY_EVT:        return ("API_GET_REG_VALUE");
1290    case NFA_HCI_API_SET_REGISTRY_EVT:        return ("API_SET_REG_VALUE");
1291    case NFA_HCI_API_CREATE_PIPE_EVT:         return ("API_CREATE_PIPE");
1292    case NFA_HCI_API_OPEN_PIPE_EVT:           return ("API_OPEN_PIPE");
1293    case NFA_HCI_API_CLOSE_PIPE_EVT:          return ("API_CLOSE_PIPE");
1294    case NFA_HCI_API_DELETE_PIPE_EVT:         return ("API_DELETE_PIPE");
1295    case NFA_HCI_API_SEND_CMD_EVT:            return ("API_SEND_COMMAND_EVT");
1296    case NFA_HCI_API_SEND_RSP_EVT:            return ("API_SEND_RESPONSE_EVT");
1297    case NFA_HCI_API_SEND_EVENT_EVT:          return ("API_SEND_EVENT_EVT");
1298    case NFA_HCI_RSP_NV_READ_EVT:             return ("NV_READ_EVT");
1299    case NFA_HCI_RSP_NV_WRITE_EVT:            return ("NV_WRITE_EVT");
1300    case NFA_HCI_RSP_TIMEOUT_EVT:             return ("RESPONSE_TIMEOUT_EVT");
1301    case NFA_HCI_CHECK_QUEUE_EVT:             return ("CHECK_QUEUE");
1302
1303    default:
1304        return ("UNKNOWN");
1305    }
1306}
1307
1308/*******************************************************************************
1309**
1310** Function         nfa_hciu_get_state_name
1311**
1312** Description      This function returns the state name.
1313**
1314** Returns          pointer to the name
1315**
1316*******************************************************************************/
1317char *nfa_hciu_get_state_name (UINT8 state)
1318{
1319    switch (state)
1320    {
1321    case NFA_HCI_STATE_DISABLED:             return ("DISABLED");
1322    case NFA_HCI_STATE_STARTUP:              return ("STARTUP");
1323    case NFA_HCI_STATE_WAIT_NETWK_ENABLE:    return ("WAIT_NETWK_ENABLE");
1324    case NFA_HCI_STATE_IDLE:                 return ("IDLE");
1325    case NFA_HCI_STATE_WAIT_RSP:             return ("WAIT_RSP");
1326    case NFA_HCI_STATE_REMOVE_GATE:          return ("REMOVE_GATE");
1327    case NFA_HCI_STATE_APP_DEREGISTER:       return ("APP_DEREGISTER");
1328    case NFA_HCI_STATE_RESTORE:              return ("RESTORE");
1329    case NFA_HCI_STATE_RESTORE_NETWK_ENABLE: return ("WAIT_NETWK_ENABLE_AFTER_RESTORE");
1330
1331    default:
1332        return ("UNKNOWN");
1333    }
1334}
1335
1336/*******************************************************************************
1337**
1338** Function         nfa_hciu_get_type_inst_names
1339**
1340** Description      This function returns command/response/event name.
1341**
1342** Returns          none
1343**
1344*******************************************************************************/
1345char *nfa_hciu_get_type_inst_names (UINT8 pipe, UINT8 type, UINT8 inst, char *p_buff)
1346{
1347    int   xx;
1348
1349    xx = sprintf (p_buff, "Type: %s [0x%02x] ", nfa_hciu_type_2_str (type), type);
1350
1351    switch (type)
1352    {
1353    case NFA_HCI_COMMAND_TYPE:
1354        sprintf (&p_buff[xx], "Inst: %s [0x%02x] ", nfa_hciu_instr_2_str (inst), inst);
1355        break;
1356    case NFA_HCI_EVENT_TYPE:
1357        sprintf (&p_buff[xx], "Evt: %s [0x%02x] ", nfa_hciu_evt_2_str (pipe, inst), inst);
1358        break;
1359    case NFA_HCI_RESPONSE_TYPE:
1360        sprintf (&p_buff[xx], "Resp: %s [0x%02x] ", nfa_hciu_get_response_name (inst), inst);
1361        break;
1362    default:
1363        sprintf (&p_buff[xx], "Inst: %u ", inst);
1364        break;
1365    }
1366    return (p_buff);
1367}
1368
1369/*******************************************************************************
1370**
1371** Function         nfa_hciu_evt_2_str
1372**
1373** Description      This function returns the event name.
1374**
1375** Returns          pointer to the name
1376**
1377*******************************************************************************/
1378char *nfa_hciu_evt_2_str (UINT8 pipe_id, UINT8 evt)
1379{
1380    tNFA_HCI_DYN_PIPE   *p_pipe;
1381
1382    if (  (pipe_id != NFA_HCI_ADMIN_PIPE)
1383        &&(pipe_id != NFA_HCI_LINK_MANAGEMENT_PIPE)
1384        &&((p_pipe = nfa_hciu_find_pipe_by_pid (pipe_id)) != NULL)  )
1385    {
1386        if (p_pipe->local_gate == NFA_HCI_CONNECTIVITY_GATE)
1387        {
1388            switch (evt)
1389            {
1390            case NFA_HCI_EVT_CONNECTIVITY:
1391                return ("EVT_CONNECTIVITY");
1392            case NFA_HCI_EVT_TRANSACTION:
1393                return ("EVT_TRANSACTION");
1394            case NFA_HCI_EVT_OPERATION_ENDED:
1395                return ("EVT_OPERATION_ENDED");
1396            default:
1397                return ("UNKNOWN");
1398            }
1399        }
1400    }
1401
1402    switch (evt)
1403    {
1404    case NFA_HCI_EVT_HCI_END_OF_OPERATION:
1405        return ("EVT_END_OF_OPERATION");
1406    case NFA_HCI_EVT_POST_DATA:
1407        return ("EVT_POST_DATA");
1408    case NFA_HCI_EVT_HOT_PLUG:
1409        return ("EVT_HOT_PLUG");
1410    default:
1411        return ("UNKNOWN");
1412    }
1413}
1414#endif
1415
1416
1417static void handle_debug_loopback (BT_HDR *p_buf, UINT8 pipe, UINT8 type, UINT8 instruction)
1418{
1419    UINT8 *p = (UINT8 *) (p_buf + 1) + p_buf->offset;
1420    static UINT8  next_pipe = 0x10;
1421
1422    if (type == NFA_HCI_COMMAND_TYPE)
1423    {
1424        switch (instruction)
1425        {
1426        case NFA_HCI_ADM_CREATE_PIPE:
1427            p[6] = next_pipe++;
1428            p[5] = p[4];
1429            p[4] = p[3];
1430            p[3] = p[2];
1431            p[2] = 3;
1432            p[1] = (NFA_HCI_RESPONSE_TYPE << 6) | NFA_HCI_ANY_OK;
1433            p_buf->len = p_buf->offset + 7;
1434            break;
1435
1436        case NFA_HCI_ANY_GET_PARAMETER:
1437            p[1] = (NFA_HCI_RESPONSE_TYPE << 6) | NFA_HCI_ANY_OK;
1438            memcpy (&p[2], (UINT8 *) nfa_hci_cb.cfg.admin_gate.session_id, NFA_HCI_SESSION_ID_LEN);
1439            p_buf->len = p_buf->offset + 2 + NFA_HCI_SESSION_ID_LEN;
1440            break;
1441
1442        default:
1443            p[1] = (NFA_HCI_RESPONSE_TYPE << 6) | NFA_HCI_ANY_OK;
1444            p_buf->len = p_buf->offset + 2;
1445            break;
1446        }
1447    }
1448    else if (type == NFA_HCI_RESPONSE_TYPE)
1449    {
1450        GKI_freebuf (p_buf);
1451        return;
1452    }
1453
1454    p_buf->event = NFA_HCI_CHECK_QUEUE_EVT;
1455    nfa_sys_sendmsg (p_buf);
1456}
1457
1458