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