nfa_hci_utils.c revision e9df6ba5a8fcccf306a80b1670b423be8fe7746a
1/******************************************************************************
2 *
3 *  Copyright (C) 2010-2012 Broadcom Corporation
4 *
5 *  Licensed under the Apache License, Version 2.0 (the "License");
6 *  you may not use this file except in compliance with the License.
7 *  You may obtain a copy of the License at:
8 *
9 *  http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 *
17 ******************************************************************************/
18
19/******************************************************************************
20 *
21 *  This file contains the utility functions for the NFA HCI.
22 *
23 ******************************************************************************/
24#include <string.h>
25#include "trace_api.h"
26#include "nfc_api.h"
27#include "nfa_sys.h"
28#include "nfa_sys_int.h"
29#include "nfa_hci_api.h"
30#include "nfa_hci_int.h"
31#include "nfa_nv_co.h"
32#include "nfa_mem_co.h"
33#include "nfa_hci_defs.h"
34
35static void handle_debug_loopback (BT_HDR *p_buf, UINT8 pipe, UINT8 type, UINT8 instruction);
36BOOLEAN HCI_LOOPBACK_DEBUG = FALSE;
37
38/*******************************************************************************
39**
40** Function         nfa_hciu_find_pipe_by_pid
41**
42** Description      look for the pipe control block based on pipe id
43**
44** Returns          pointer to the pipe control block, or NULL if not found
45**
46*******************************************************************************/
47tNFA_HCI_DYN_PIPE *nfa_hciu_find_pipe_by_pid (UINT8 pipe_id)
48{
49    tNFA_HCI_DYN_PIPE   *pp = nfa_hci_cb.cfg.dyn_pipes;
50    int                 xx  = 0;
51
52    /* Loop through looking for a match */
53    for ( ; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++)
54    {
55        if (pp->pipe_id == pipe_id)
56            return (pp);
57    }
58
59    /* If here, not found */
60    return (NULL);
61}
62
63/*******************************************************************************
64**
65** Function         nfa_hciu_find_gate_by_gid
66**
67** Description      Find the gate control block for the given gate id
68**
69** Returns          pointer to the gate control block, or NULL if not found
70**
71*******************************************************************************/
72tNFA_HCI_DYN_GATE *nfa_hciu_find_gate_by_gid (UINT8 gate_id)
73{
74    tNFA_HCI_DYN_GATE *pg = nfa_hci_cb.cfg.dyn_gates;
75    int               xx  = 0;
76
77    for ( ; xx < NFA_HCI_MAX_GATE_CB; xx++, pg++)
78    {
79        if (pg->gate_id == gate_id)
80            return (pg);
81    }
82
83    return (NULL);
84}
85
86/*******************************************************************************
87**
88** Function         nfa_hciu_find_gate_by_owner
89**
90** Description      Find the the first gate control block for the given owner
91**
92** Returns          pointer to the gate control block, or NULL if not found
93**
94*******************************************************************************/
95tNFA_HCI_DYN_GATE *nfa_hciu_find_gate_by_owner (tNFA_HANDLE app_handle)
96{
97    tNFA_HCI_DYN_GATE *pg = nfa_hci_cb.cfg.dyn_gates;
98    int               xx  = 0;
99
100    for ( ; xx < NFA_HCI_MAX_GATE_CB; xx++, pg++)
101    {
102        if (pg->gate_owner == app_handle)
103            return (pg);
104    }
105
106    return (NULL);
107}
108
109/*******************************************************************************
110**
111** Function         nfa_hciu_find_gate_with_nopipes_by_owner
112**
113** Description      Find the the first gate control block with no pipes
114**                  for the given owner
115**
116** Returns          pointer to the gate control block, or NULL if not found
117**
118*******************************************************************************/
119tNFA_HCI_DYN_GATE *nfa_hciu_find_gate_with_nopipes_by_owner (tNFA_HANDLE app_handle)
120{
121    tNFA_HCI_DYN_GATE *pg = nfa_hci_cb.cfg.dyn_gates;
122    int               xx  = 0;
123
124    for ( ; xx < NFA_HCI_MAX_GATE_CB; xx++, pg++)
125    {
126        if (  (pg->gate_owner    == app_handle)
127            &&(pg->pipe_inx_mask == 0)  )
128            return (pg);
129    }
130
131    return (NULL);
132}
133
134/*******************************************************************************
135**
136** Function         nfa_hciu_count_pipes_on_gate
137**
138** Description      Count the number of pipes on the given gate
139**
140** Returns          the number of pipes on the gate
141**
142*******************************************************************************/
143UINT8 nfa_hciu_count_pipes_on_gate (tNFA_HCI_DYN_GATE *p_gate)
144{
145    int               xx    = 0;
146    UINT32            mask  = 1;
147    UINT8             count = 0;
148
149    for ( ; xx < NFA_HCI_MAX_PIPE_CB; xx++)
150    {
151        if ( p_gate->pipe_inx_mask & mask )
152            count++;
153
154        mask = mask << 1;
155    }
156
157    return (count);
158}
159
160/*******************************************************************************
161**
162** Function         nfa_hciu_count_open_pipes_on_gate
163**
164** Description      Count the number of opened pipes on the given gate
165**
166** Returns          the number of pipes in OPENED state on the gate
167**
168*******************************************************************************/
169UINT8 nfa_hciu_count_open_pipes_on_gate (tNFA_HCI_DYN_GATE *p_gate)
170{
171    tNFA_HCI_DYN_PIPE *pp   = nfa_hci_cb.cfg.dyn_pipes;
172    int               xx    = 0;
173    UINT32            mask  = 1;
174    UINT8             count = 0;
175
176    for ( ; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++)
177    {
178        /* For each pipe on this gate, check if it is open */
179        if ((p_gate->pipe_inx_mask & mask) && (pp->pipe_state == NFA_HCI_PIPE_OPENED))
180            count++;
181
182        mask = mask << 1;
183    }
184
185    return (count);
186}
187
188/*******************************************************************************
189**
190** Function         nfa_hciu_get_gate_owner
191**
192** Description      Find the application that owns a gate
193**
194** Returns          application handle
195**
196*******************************************************************************/
197tNFA_HANDLE nfa_hciu_get_gate_owner (UINT8 gate_id)
198{
199    tNFA_HCI_DYN_GATE   *pg;
200
201    if ((pg = nfa_hciu_find_gate_by_gid (gate_id)) == NULL)
202        return (NFA_HANDLE_INVALID);
203
204    return (pg->gate_owner);
205}
206
207/*******************************************************************************
208**
209** Function         nfa_hciu_get_pipe_owner
210**
211** Description      Find the application that owns a pipe
212**
213** Returns          application handle
214**
215*******************************************************************************/
216tNFA_HANDLE nfa_hciu_get_pipe_owner (UINT8 pipe_id)
217{
218    tNFA_HCI_DYN_PIPE   *pp;
219    tNFA_HCI_DYN_GATE   *pg;
220
221    if ((pp = nfa_hciu_find_pipe_by_pid (pipe_id)) == NULL)
222        return (NFA_HANDLE_INVALID);
223
224    if ((pg = nfa_hciu_find_gate_by_gid (pp->local_gate)) == NULL)
225        return (NFA_HANDLE_INVALID);
226
227    return (pg->gate_owner);
228}
229
230
231/*******************************************************************************
232**
233** Function         nfa_hciu_alloc_gate
234**
235** Description      Allocate an gate control block
236**
237** Returns          pointer to the allocated gate, or NULL if cannot allocate
238**
239*******************************************************************************/
240tNFA_HCI_DYN_GATE *nfa_hciu_alloc_gate (UINT8 gate_id, tNFA_HANDLE app_handle)
241{
242    tNFA_HCI_DYN_GATE   *pg;
243    int                 xx;
244    UINT8               app_inx = app_handle & NFA_HANDLE_MASK;
245
246
247    /* First, check if the application handle is valid */
248    if ((gate_id != NFA_HCI_CONNECTIVITY_GATE)
249                    &&
250        (  ((app_handle & NFA_HANDLE_GROUP_MASK) != NFA_HANDLE_GROUP_HCI)
251         ||(app_inx >= NFA_HCI_MAX_APP_CB)
252         ||(nfa_hci_cb.p_app_cback[app_inx] == NULL)  ))
253    {
254        return (NULL);
255    }
256
257    if (gate_id != 0)
258    {
259        if ((pg = nfa_hciu_find_gate_by_gid (gate_id)) != NULL)
260            return (pg);
261    }
262    else
263    {
264        /* If gate_id is 0, we need to assign a free one */
265        /* Loop through all possible gate IDs checking if they are already used */
266        for (gate_id = NFA_HCI_FIRST_HOST_SPECIFIC_GENERIC_GATE; gate_id < NFA_HCI_LAST_PROP_GATE; gate_id++)
267        {
268            /* Skip connectivity gate */
269            if (gate_id == NFA_HCI_CONNECTIVITY_GATE) gate_id++;
270
271            /* Check if the gate is already allocated */
272            for (xx = 0, pg = nfa_hci_cb.cfg.dyn_gates; xx < NFA_HCI_MAX_GATE_CB; xx++, pg++)
273                if (pg->gate_id == gate_id)
274                    break;
275            /* If the gate is not allocated, use the gate */
276            if (xx == NFA_HCI_MAX_GATE_CB)
277                break;
278        }
279        if (gate_id == NFA_HCI_LAST_PROP_GATE)
280        {
281            NFA_TRACE_ERROR2 ("nfa_hci_alloc_gate - no free Gate ID: %u  App Handle: 0x%04x", gate_id, app_handle);
282            return (NULL);
283        }
284    }
285
286    /* Now look for a free control block */
287    for (xx = 0, pg = nfa_hci_cb.cfg.dyn_gates; xx < NFA_HCI_MAX_GATE_CB; xx++, pg++)
288    {
289        if (pg->gate_id == 0)
290        {
291            /* Found a free gate control block */
292            pg->gate_id       = gate_id;
293            pg->gate_owner    = app_handle;
294            pg->pipe_inx_mask = 0;
295
296            NFA_TRACE_DEBUG2 ("nfa_hciu_alloc_gate id:%d  app_handle: 0x%04x", gate_id, app_handle);
297
298            nfa_hci_cb.nv_write_needed = TRUE;
299            return (pg);
300        }
301    }
302
303    /* If here, no free gate control block */
304    NFA_TRACE_ERROR2 ("nfa_hci_alloc_gate - no CB  Gate ID: %u  App Handle: 0x%04x", gate_id, app_handle);
305    return (NULL);
306}
307
308/*******************************************************************************
309**
310** Function         nfa_hciu_send_msg
311**
312** Description      This function will fragment the given packet, if necessary
313**                  and send it on the given pipe.
314**
315** Returns          status
316**
317*******************************************************************************/
318tNFA_STATUS nfa_hciu_send_msg (UINT8 pipe_id, UINT8 type, UINT8 instruction, UINT16 msg_len, UINT8 *p_msg)
319{
320    BT_HDR          *p_buf;
321    UINT8           *p_data;
322    BOOLEAN          first_pkt = TRUE;
323    UINT16          data_len;
324    tNFA_STATUS     status = NFA_STATUS_OK;
325    UINT16          max_seg_hcp_pkt_size = nfa_hci_cb.buff_size - NCI_DATA_HDR_SIZE;
326
327#if (BT_TRACE_VERBOSE == TRUE)
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), 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, NFA_HCI_CMD_RSP_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_find_pipe_by_owner
633**
634** Description      Find the first pipe associated with the given app
635**
636** Returns          pointer to pipe, or NULL if none found
637**
638*******************************************************************************/
639tNFA_HCI_DYN_PIPE *nfa_hciu_find_pipe_by_owner (tNFA_HANDLE app_handle)
640{
641    tNFA_HCI_DYN_GATE   *pg;
642    tNFA_HCI_DYN_PIPE   *pp;
643    int                 xx;
644
645    NFA_TRACE_DEBUG1 ("nfa_hciu_find_pipe_by_owner () app_handle:0x%x", app_handle);
646
647    /* Loop through all pipes looking for the owner */
648    for (xx = 0, pp = nfa_hci_cb.cfg.dyn_pipes; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++)
649    {
650        if (pp->pipe_id != 0)
651        {
652            if (  ((pg = nfa_hciu_find_gate_by_gid (pp->local_gate)) != NULL)
653                &&(pg->gate_owner == app_handle) )
654                return (pp);
655        }
656    }
657
658    /* If here, not found */
659    return (NULL);
660}
661
662/*******************************************************************************
663**
664** Function         nfa_hciu_find_pipe_on_gate
665**
666** Description      Find the first pipe associated with the given gate
667**
668** Returns          pointer to pipe, or NULL if none found
669**
670*******************************************************************************/
671tNFA_HCI_DYN_PIPE *nfa_hciu_find_pipe_on_gate (UINT8 gate_id)
672{
673    tNFA_HCI_DYN_GATE   *pg;
674    tNFA_HCI_DYN_PIPE   *pp;
675    int                 xx;
676
677    NFA_TRACE_DEBUG1 ("nfa_hciu_find_pipe_on_gate () Gate:0x%x", gate_id);
678
679    /* Loop through all pipes looking for the owner */
680    for (xx = 0, pp = nfa_hci_cb.cfg.dyn_pipes; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++)
681    {
682        if (pp->pipe_id != 0)
683        {
684            if (  ((pg = nfa_hciu_find_gate_by_gid (pp->local_gate)) != NULL)
685                &&(pg->gate_id == gate_id) )
686                return (pp);
687        }
688    }
689
690    /* If here, not found */
691    return (NULL);
692}
693
694/*******************************************************************************
695**
696** Function         nfa_hciu_is_active_host
697**
698** Description      Check if the host is currently active
699**
700** Returns          TRUE, if the host is active in the host network
701**                  FALSE, if the host is not active in the host network
702**
703*******************************************************************************/
704BOOLEAN nfa_hciu_is_active_host (UINT8 host_id)
705{
706    UINT8   xx;
707
708    for (xx = 0; xx < NFA_HCI_MAX_HOST_IN_NETWORK; xx++)
709    {
710        if (nfa_hci_cb.inactive_host[xx] == host_id)
711            return FALSE;
712    }
713
714    return TRUE;
715}
716
717/*******************************************************************************
718**
719** Function         nfa_hciu_is_host_reseting
720**
721** Description      Check if the host is currently reseting
722**
723** Returns          TRUE, if the host is reseting
724**                  FALSE, if the host is not reseting
725**
726*******************************************************************************/
727BOOLEAN nfa_hciu_is_host_reseting (UINT8 host_id)
728{
729    UINT8   xx;
730
731    for (xx = 0; xx < NFA_HCI_MAX_HOST_IN_NETWORK; xx++)
732    {
733        if (nfa_hci_cb.reset_host[xx] == host_id)
734            return TRUE;
735    }
736
737    return FALSE;
738}
739
740/*******************************************************************************
741**
742** Function         nfa_hciu_is_no_host_resetting
743**
744** Description      Check if no host is reseting
745**
746** Returns          TRUE, if no host is resetting at this time
747**                  FALSE, if one or more host is resetting
748**
749*******************************************************************************/
750BOOLEAN nfa_hciu_is_no_host_resetting (void)
751{
752    UINT8   xx;
753
754    for (xx = 0; xx < NFA_HCI_MAX_HOST_IN_NETWORK; xx++)
755    {
756        if (nfa_hci_cb.reset_host[xx] != 0)
757            return FALSE;
758    }
759
760    return TRUE;
761}
762
763/*******************************************************************************
764**
765** Function         nfa_hciu_find_active_pipe_on_gate
766**
767** Description      Find the first active pipe associated with the given gate
768**
769** Returns          pointer to pipe, or NULL if none found
770**
771*******************************************************************************/
772tNFA_HCI_DYN_PIPE *nfa_hciu_find_active_pipe_on_gate (UINT8 gate_id)
773{
774    tNFA_HCI_DYN_GATE   *pg;
775    tNFA_HCI_DYN_PIPE   *pp;
776    int                 xx;
777
778    NFA_TRACE_DEBUG1 ("nfa_hciu_find_active_pipe_on_gate () Gate:0x%x", gate_id);
779
780    /* Loop through all pipes looking for the owner */
781    for (xx = 0, pp = nfa_hci_cb.cfg.dyn_pipes; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++)
782    {
783        if (  (pp->pipe_id != 0)
784            &&(pp->pipe_id >= NFA_HCI_FIRST_DYNAMIC_PIPE)
785            &&(pp->pipe_id <= NFA_HCI_LAST_DYNAMIC_PIPE)
786            &&(nfa_hciu_is_active_host (pp->dest_host))  )
787        {
788            if (  ((pg = nfa_hciu_find_gate_by_gid (pp->local_gate)) != NULL)
789                &&(pg->gate_id == gate_id) )
790                return (pp);
791        }
792    }
793
794    /* If here, not found */
795    return (NULL);
796}
797
798/*******************************************************************************
799**
800** Function         nfa_hciu_release_pipe
801**
802** Description      remove the specified pipe
803**
804** Returns          NFA_HCI_ANY_OK, if removed
805**                  NFA_HCI_ANY_E_NOK, if otherwise
806**
807*******************************************************************************/
808tNFA_HCI_RESPONSE nfa_hciu_release_pipe (UINT8 pipe_id)
809{
810    tNFA_HCI_DYN_GATE   *p_gate;
811    tNFA_HCI_DYN_PIPE   *p_pipe;
812    UINT8               pipe_index;
813
814    NFA_TRACE_EVENT1 ("nfa_hciu_release_pipe: %u", pipe_id);
815
816    if ((p_pipe = nfa_hciu_find_pipe_by_pid (pipe_id)) == NULL)
817        return (NFA_HCI_ANY_E_NOK);
818
819    if (pipe_id > NFA_HCI_LAST_DYNAMIC_PIPE)
820    {
821        NFA_TRACE_DEBUG1 ("ignore pipe: %d", pipe_id);
822        return (NFA_HCI_ANY_E_NOK);
823    }
824
825    pipe_index = (UINT8) (p_pipe - nfa_hci_cb.cfg.dyn_pipes);
826
827    if (p_pipe->local_gate == NFA_HCI_IDENTITY_MANAGEMENT_GATE)
828    {
829        /* Remove pipe from ID management gate */
830        nfa_hci_cb.cfg.id_mgmt_gate.pipe_inx_mask &= ~ (UINT32) (1 << pipe_index);
831    }
832    else
833    {
834        if ((p_gate = nfa_hciu_find_gate_by_gid (p_pipe->local_gate)) == NULL)
835        {
836            /* Mark the pipe control block as free */
837            p_pipe->pipe_id = 0;
838            return (NFA_HCI_ANY_E_NOK);
839        }
840
841        /* Remove pipe from gate */
842        p_gate->pipe_inx_mask &= ~ (UINT32) (1 << pipe_index);
843    }
844
845    /* Reset pipe control block */
846    memset (p_pipe,0,sizeof (tNFA_HCI_DYN_PIPE));
847    nfa_hci_cb.nv_write_needed = TRUE;
848    return NFA_HCI_ANY_OK;
849}
850
851/*******************************************************************************
852**
853** Function         nfa_hciu_remove_all_pipes_from_host
854**
855** Description      remove all the pipes that are connected to a specific host
856**
857** Returns          None
858**
859*******************************************************************************/
860void nfa_hciu_remove_all_pipes_from_host (UINT8 host)
861{
862    tNFA_HCI_DYN_GATE   *pg;
863    tNFA_HCI_DYN_PIPE   *pp;
864    int                 xx;
865    tNFA_HCI_EVT_DATA   evt_data;
866
867    NFA_TRACE_EVENT1 ("nfa_hciu_remove_all_pipes_from_host (0x%02x)", host);
868
869    /* Remove all pipes from the specified host connected to all generic gates */
870    for (xx = 0, pp = nfa_hci_cb.cfg.dyn_pipes; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++)
871    {
872        if (  (pp->pipe_id == 0)
873                    ||
874              (  (host != 0)
875               &&((pp->dest_host != host) || (pp->pipe_id > NFA_HCI_LAST_DYNAMIC_PIPE)))  )
876            continue;
877
878        if ((pg = nfa_hciu_find_gate_by_gid (pp->local_gate)) != NULL)
879        {
880            evt_data.deleted.status = NFA_STATUS_OK;
881            evt_data.deleted.pipe   = pp->pipe_id;
882
883            nfa_hciu_send_to_app (NFA_HCI_DELETE_PIPE_EVT, &evt_data, pg->gate_owner);
884        }
885        nfa_hciu_release_pipe (pp->pipe_id);
886    }
887}
888
889/*******************************************************************************
890**
891** Function         nfa_hciu_send_create_pipe_cmd
892**
893** Description      Create dynamic pipe between the specified gates
894**
895** Returns          status
896**
897*******************************************************************************/
898tNFA_STATUS nfa_hciu_send_create_pipe_cmd (UINT8 source_gate, UINT8 dest_host, UINT8 dest_gate)
899{
900    tNFA_STATUS         status;
901    UINT8               data[3];
902
903    data[0] = source_gate;
904    data[1] = dest_host;
905    data[2] = dest_gate;
906
907    NFA_TRACE_DEBUG3 ("nfa_hciu_send_create_pipe_cmd source_gate:%d, dest_host:%d, dest_gate:%d", source_gate, dest_host, dest_gate);
908
909    status = nfa_hciu_send_msg (NFA_HCI_ADMIN_PIPE, NFA_HCI_COMMAND_TYPE, NFA_HCI_ADM_CREATE_PIPE, 3, data);
910
911    return status;
912}
913
914/*******************************************************************************
915**
916** Function         nfa_hciu_send_delete_pipe_cmd
917**
918** Description      Delete the dynamic pipe
919**
920** Returns          None
921**
922*******************************************************************************/
923tNFA_STATUS nfa_hciu_send_delete_pipe_cmd (UINT8 pipe)
924{
925    tNFA_STATUS status;
926
927    NFA_TRACE_DEBUG1 ("nfa_hciu_send_delete_pipe_cmd: %d", pipe);
928
929    if (pipe > NFA_HCI_LAST_DYNAMIC_PIPE)
930    {
931        NFA_TRACE_DEBUG1 ("ignore pipe: %d", pipe);
932        return (NFA_HCI_ANY_E_NOK);
933    }
934    nfa_hci_cb.pipe_in_use = pipe;
935
936    status = nfa_hciu_send_msg (NFA_HCI_ADMIN_PIPE, NFA_HCI_COMMAND_TYPE, NFA_HCI_ADM_DELETE_PIPE, 1, &pipe);
937
938    return status;
939}
940
941
942/*******************************************************************************
943**
944** Function         nfa_hciu_send_clear_all_pipe_cmd
945**
946** Description      delete all the dynamic pipe connected to device host,
947**                  to close all static pipes connected to device host,
948**                  and to set registry values related to static pipes to
949**                  theri default values.
950**
951** Returns          None
952**
953*******************************************************************************/
954tNFA_STATUS nfa_hciu_send_clear_all_pipe_cmd (void)
955{
956    tNFA_STATUS status;
957    UINT16      id_ref_data = 0x0102;
958
959    NFA_TRACE_DEBUG0 ("nfa_hciu_send_clear_all_pipe_cmd");
960
961    status = nfa_hciu_send_msg (NFA_HCI_ADMIN_PIPE, NFA_HCI_COMMAND_TYPE, NFA_HCI_ADM_CLEAR_ALL_PIPE, 2, (UINT8 *) &id_ref_data);
962
963    return status;
964}
965
966/*******************************************************************************
967**
968** Function         nfa_hciu_send_open_pipe_cmd
969**
970** Description      Open a closed pipe
971**
972** Returns          status
973**
974*******************************************************************************/
975tNFA_STATUS nfa_hciu_send_open_pipe_cmd (UINT8 pipe)
976{
977    tNFA_STATUS status;
978
979    nfa_hci_cb.pipe_in_use = pipe;
980
981    status = nfa_hciu_send_msg (pipe, NFA_HCI_COMMAND_TYPE, NFA_HCI_ANY_OPEN_PIPE, 0, NULL);
982
983    return status;
984}
985
986/*******************************************************************************
987**
988** Function         nfa_hciu_send_close_pipe_cmd
989**
990** Description      Close an opened pipe
991**
992** Returns          status
993**
994*******************************************************************************/
995tNFA_STATUS nfa_hciu_send_close_pipe_cmd (UINT8 pipe)
996{
997    tNFA_STATUS status;
998
999    nfa_hci_cb.pipe_in_use = pipe;
1000
1001    status = nfa_hciu_send_msg (pipe, NFA_HCI_COMMAND_TYPE, NFA_HCI_ANY_CLOSE_PIPE, 0, NULL);
1002
1003    return status;
1004}
1005
1006/*******************************************************************************
1007**
1008** Function         nfa_hciu_send_get_param_cmd
1009**
1010** Description      Read a parameter value from gate registry
1011**
1012** Returns          None
1013**
1014*******************************************************************************/
1015tNFA_STATUS nfa_hciu_send_get_param_cmd (UINT8 pipe, UINT8 index)
1016{
1017    tNFA_STATUS status;
1018
1019    if ((status = nfa_hciu_send_msg (pipe, NFA_HCI_COMMAND_TYPE, NFA_HCI_ANY_GET_PARAMETER, 1, &index)) == NFC_STATUS_OK)
1020        nfa_hci_cb.param_in_use = index;
1021
1022    return status;
1023}
1024
1025/*******************************************************************************
1026**
1027** Function         nfa_hciu_send_set_param_cmd
1028**
1029** Description      Set a parameter value in a gate registry
1030**
1031** Returns          None
1032**
1033*******************************************************************************/
1034tNFA_STATUS nfa_hciu_send_set_param_cmd (UINT8 pipe, UINT8 index, UINT8 length, UINT8 *p_data)
1035{
1036    tNFA_STATUS status;
1037    UINT8       data[255];
1038
1039    data[0] = index;
1040
1041    memcpy (&data[1], p_data, length);
1042
1043    if ((status = nfa_hciu_send_msg (pipe, NFA_HCI_COMMAND_TYPE, NFA_HCI_ANY_SET_PARAMETER, (UINT16) (length + 1), data)) == NFC_STATUS_OK)
1044        nfa_hci_cb.param_in_use = index;
1045
1046    return status;
1047}
1048
1049
1050/*******************************************************************************
1051**
1052** Function         nfa_hciu_send_to_app
1053**
1054** Description      Send an event back to an application
1055**
1056** Returns          none
1057**
1058*******************************************************************************/
1059void nfa_hciu_send_to_app (tNFA_HCI_EVT event, tNFA_HCI_EVT_DATA *p_evt, tNFA_HANDLE app_handle)
1060{
1061    UINT8   app_inx = app_handle & NFA_HANDLE_MASK;
1062
1063    /* First, check if the application handle is valid */
1064    if (  ((app_handle & NFA_HANDLE_GROUP_MASK) == NFA_HANDLE_GROUP_HCI)
1065        &&(app_inx < NFA_HCI_MAX_APP_CB) )
1066    {
1067        if (nfa_hci_cb.p_app_cback[app_inx] != NULL)
1068        {
1069            nfa_hci_cb.p_app_cback[app_inx] (event, p_evt);
1070            return;
1071        }
1072    }
1073
1074    if (app_handle != NFA_HANDLE_INVALID)
1075    {
1076        NFA_TRACE_WARNING2 ("nfa_hciu_send_to_app no callback,  event: 0x%04x  app_handle: 0x%04x",
1077                            event, app_handle);
1078    }
1079}
1080
1081/*******************************************************************************
1082**
1083** Function         nfa_hciu_send_to_all_apps
1084**
1085** Description      Send an event back to all applications
1086**
1087** Returns          none
1088**
1089*******************************************************************************/
1090void nfa_hciu_send_to_all_apps (tNFA_HCI_EVT event, tNFA_HCI_EVT_DATA *p_evt)
1091{
1092    UINT8   app_inx;
1093
1094    for (app_inx = 0; app_inx < NFA_HCI_MAX_APP_CB; app_inx++)
1095    {
1096        if (nfa_hci_cb.p_app_cback[app_inx] != NULL)
1097            nfa_hci_cb.p_app_cback[app_inx] (event, p_evt);
1098    }
1099
1100}
1101
1102/*******************************************************************************
1103**
1104** Function         nfa_hciu_send_to_apps_handling_connectivity_evts
1105**
1106** Description      Send a connectivity event to all the application interested
1107**                  in connectivity events
1108**
1109** Returns          none
1110**
1111*******************************************************************************/
1112void nfa_hciu_send_to_apps_handling_connectivity_evts (tNFA_HCI_EVT event, tNFA_HCI_EVT_DATA *p_evt)
1113{
1114    UINT8   app_inx;
1115
1116    for (app_inx = 0; app_inx < NFA_HCI_MAX_APP_CB; app_inx++)
1117    {
1118        if (  (nfa_hci_cb.p_app_cback[app_inx] != NULL)
1119            &&(nfa_hci_cb.cfg.b_send_conn_evts[app_inx]))
1120
1121            nfa_hci_cb.p_app_cback[app_inx] (event, p_evt);
1122    }
1123
1124}
1125
1126#if (BT_TRACE_VERBOSE == TRUE)
1127/*******************************************************************************
1128**
1129** Function         nfa_hciu_get_response_name
1130**
1131** Description      This function returns the error code name.
1132**
1133** NOTE             conditionally compiled to save memory.
1134**
1135** Returns          pointer to the name
1136**
1137*******************************************************************************/
1138char *nfa_hciu_get_response_name (UINT8 rsp_code)
1139{
1140    static char unknown[50];
1141
1142    switch (rsp_code)
1143    {
1144    case NFA_HCI_ANY_OK:
1145        return ("ANY_OK");
1146    case NFA_HCI_ANY_E_NOT_CONNECTED:
1147        return ("ANY_E_NOT_CONNECTED");
1148    case NFA_HCI_ANY_E_CMD_PAR_UNKNOWN:
1149        return ("ANY_E_CMD_PAR_UNKNOWN");
1150    case NFA_HCI_ANY_E_NOK:
1151        return ("ANY_E_NOK");
1152    case NFA_HCI_ADM_E_NO_PIPES_AVAILABLE:
1153        return ("ADM_E_NO_PIPES_AVAILABLE");
1154    case NFA_HCI_ANY_E_REG_PAR_UNKNOWN:
1155        return ("ANY_E_REG_PAR_UNKNOWN");
1156    case NFA_HCI_ANY_E_PIPE_NOT_OPENED:
1157        return ("ANY_E_PIPE_NOT_OPENED");
1158    case NFA_HCI_ANY_E_CMD_NOT_SUPPORTED:
1159        return ("ANY_E_CMD_NOT_SUPPORTED");
1160    case NFA_HCI_ANY_E_INHIBITED:
1161        return ("ANY_E_INHIBITED");
1162    case NFA_HCI_ANY_E_TIMEOUT:
1163        return ("ANY_E_TIMEOUT");
1164    case NFA_HCI_ANY_E_REG_ACCESS_DENIED:
1165        return ("ANY_E_REG_ACCESS_DENIED");
1166    case NFA_HCI_ANY_E_PIPE_ACCESS_DENIED:
1167        return ("ANY_E_PIPE_ACCESS_DENIED");
1168    default:
1169        sprintf (unknown, "?? Unknown: %u ?? ", rsp_code);
1170        return (unknown);
1171    }
1172}
1173
1174/*******************************************************************************
1175**
1176** Function         nfa_hciu_type_2_str
1177**
1178** Description      This function returns the type name.
1179**
1180** Returns          pointer to the name
1181**
1182*******************************************************************************/
1183char *nfa_hciu_type_2_str(UINT8 type)
1184{
1185    static char unknown[40];
1186
1187    switch (type)
1188    {
1189    case NFA_HCI_COMMAND_TYPE:
1190        return ("COMMAND");
1191    case NFA_HCI_EVENT_TYPE:
1192        return ("EVENT");
1193    case NFA_HCI_RESPONSE_TYPE:
1194        return ("RESPONSE");
1195    default:
1196        sprintf (unknown, "?? Unknown: %u ?? ", type);
1197        return (unknown);
1198    }
1199}
1200
1201/*******************************************************************************
1202**
1203** Function         nfa_hciu_instr_2_str
1204**
1205** Description      This function returns the instruction name.
1206**
1207** Returns          pointer to the name
1208**
1209*******************************************************************************/
1210char *nfa_hciu_instr_2_str (UINT8 instruction)
1211{
1212    static char unknown[40];
1213
1214    switch (instruction)
1215    {
1216    case NFA_HCI_ANY_SET_PARAMETER:
1217        return ("ANY_SET_PARAMETER");
1218    case NFA_HCI_ANY_GET_PARAMETER:
1219        return ("ANY_GET_PARAMETER");
1220    case NFA_HCI_ANY_OPEN_PIPE:
1221        return ("ANY_OPEN_PIPE");
1222    case NFA_HCI_ANY_CLOSE_PIPE:
1223        return ("ANY_CLOSE_PIPE");
1224    case NFA_HCI_ADM_CREATE_PIPE:
1225        return ("ADM_CREATE_PIPE");
1226    case NFA_HCI_ADM_DELETE_PIPE:
1227        return ("ADM_DELETE_PIPE");
1228    case NFA_HCI_ADM_NOTIFY_PIPE_CREATED:
1229        return ("ADM_NOTIFY_PIPE_CREATED");
1230    case NFA_HCI_ADM_NOTIFY_PIPE_DELETED:
1231        return ("ADM_NOTIFY_PIPE_DELETED");
1232    case NFA_HCI_ADM_CLEAR_ALL_PIPE:
1233        return ("ADM_CLEAR_ALL_PIPE");
1234    case NFA_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED:
1235        return ("ADM_NOTIFY_ALL_PIPE_CLEARED");
1236    default:
1237        sprintf (unknown, "?? Unknown: %u ?? ", instruction);
1238        return (unknown);
1239    }
1240}
1241
1242
1243/*******************************************************************************
1244**
1245** Function         nfa_hciu_get_event_name
1246**
1247** Description      This function returns the event code name.
1248**
1249** Returns          pointer to the name
1250**
1251*******************************************************************************/
1252char *nfa_hciu_get_event_name (UINT16 event)
1253{
1254    static char unknown[40];
1255
1256    switch (event)
1257    {
1258    case NFA_HCI_API_REGISTER_APP_EVT:        return ("API_REGISTER");
1259    case NFA_HCI_API_DEREGISTER_APP_EVT:      return ("API_DEREGISTER");
1260    case NFA_HCI_API_GET_APP_GATE_PIPE_EVT:   return ("API_GET_GATE_LIST");
1261    case NFA_HCI_API_ALLOC_GATE_EVT:          return ("API_ALLOC_GATE");
1262    case NFA_HCI_API_DEALLOC_GATE_EVT:        return ("API_DEALLOC_GATE");
1263    case NFA_HCI_API_GET_HOST_LIST_EVT:       return ("API_GET_HOST_LIST");
1264    case NFA_HCI_API_GET_REGISTRY_EVT:        return ("API_GET_REG_VALUE");
1265    case NFA_HCI_API_SET_REGISTRY_EVT:        return ("API_SET_REG_VALUE");
1266    case NFA_HCI_API_CREATE_PIPE_EVT:         return ("API_CREATE_PIPE");
1267    case NFA_HCI_API_OPEN_PIPE_EVT:           return ("API_OPEN_PIPE");
1268    case NFA_HCI_API_CLOSE_PIPE_EVT:          return ("API_CLOSE_PIPE");
1269    case NFA_HCI_API_DELETE_PIPE_EVT:         return ("API_DELETE_PIPE");
1270    case NFA_HCI_API_SEND_CMD_EVT:            return ("API_SEND_COMMAND_EVT");
1271    case NFA_HCI_API_SEND_RSP_EVT:            return ("API_SEND_RESPONSE_EVT");
1272    case NFA_HCI_API_SEND_EVENT_EVT:          return ("API_SEND_EVENT_EVT");
1273    case NFA_HCI_RSP_NV_READ_EVT:             return ("NV_READ_EVT");
1274    case NFA_HCI_RSP_NV_WRITE_EVT:            return ("NV_WRITE_EVT");
1275    case NFA_HCI_RSP_TIMEOUT_EVT:             return ("RESPONSE_TIMEOUT_EVT");
1276    case NFA_HCI_CHECK_QUEUE_EVT:             return ("CHECK_QUEUE");
1277
1278    default:
1279        sprintf (unknown, "?? Unknown: %u ?? ", event);
1280        return (unknown);
1281    }
1282}
1283
1284/*******************************************************************************
1285**
1286** Function         nfa_hciu_get_state_name
1287**
1288** Description      This function returns the state name.
1289**
1290** Returns          pointer to the name
1291**
1292*******************************************************************************/
1293char *nfa_hciu_get_state_name (UINT8 state)
1294{
1295    static char unknown[40];
1296
1297    switch (state)
1298    {
1299    case NFA_HCI_STATE_DISABLED:            return ("DISABLED");
1300    case NFA_HCI_STATE_STARTUP:             return ("STARTUP");
1301    case NFA_HCI_STATE_IDLE:                return ("IDLE");
1302    case NFA_HCI_STATE_WAIT_RSP:            return ("WAIT_RSP");
1303    case NFA_HCI_STATE_REMOVE_GATE:         return ("REMOVE_GATE");
1304    case NFA_HCI_STATE_APP_DEREGISTER:      return ("APP_DEREGISTER");
1305    case NFA_HCI_STATE_RESTORE:             return ("RESTORE");
1306
1307
1308    default:
1309        sprintf (unknown, "?? Unknown: %u ?? ", state);
1310        return (unknown);
1311    }
1312}
1313
1314/*******************************************************************************
1315**
1316** Function         nfa_hciu_get_type_inst_names
1317**
1318** Description      This function returns command/response/event name.
1319**
1320** Returns          pointer to the name
1321**
1322*******************************************************************************/
1323char *nfa_hciu_get_type_inst_names (UINT8 pipe, UINT8 type, UINT8 inst)
1324{
1325    static char buff[100];
1326    int   xx;
1327
1328    xx = sprintf (buff, "Type: %s  ", nfa_hciu_type_2_str (type));
1329
1330    switch (type)
1331    {
1332    case NFA_HCI_COMMAND_TYPE:
1333        sprintf (&buff[xx], "Inst: %s ", nfa_hciu_instr_2_str (inst));
1334        break;
1335    case NFA_HCI_EVENT_TYPE:
1336        sprintf (&buff[xx], "Evt: %s ", nfa_hciu_evt_2_str (pipe, inst));
1337        break;
1338    case NFA_HCI_RESPONSE_TYPE:
1339        sprintf (&buff[xx], "Resp: %s ", nfa_hciu_get_response_name (inst));
1340        break;
1341    default:
1342        sprintf (&buff[xx], "Inst: %u ", inst);
1343        break;
1344    }
1345    return (buff);
1346}
1347
1348
1349
1350/*******************************************************************************
1351**
1352** Function         nfa_hciu_instr_2_str
1353**
1354** Description      This function returns the instruction name.
1355**
1356** Returns          pointer to the name
1357**
1358*******************************************************************************/
1359char *nfa_hciu_evt_2_str (UINT8 pipe_id, UINT8 evt)
1360{
1361    static char         unknown[40];
1362    tNFA_HCI_DYN_PIPE   *p_pipe;
1363
1364    if (  (pipe_id != NFA_HCI_ADMIN_PIPE)
1365        &&(pipe_id != NFA_HCI_LINK_MANAGEMENT_PIPE)
1366        &&((p_pipe = nfa_hciu_find_pipe_by_pid (pipe_id)) != NULL)  )
1367    {
1368        if (p_pipe->local_gate == NFA_HCI_CONNECTIVITY_GATE)
1369        {
1370            switch (evt)
1371            {
1372            case NFA_HCI_EVT_CONNECTIVITY:
1373                return ("EVT_CONNECTIVITY");
1374            case NFA_HCI_EVT_TRANSACTION:
1375                return ("EVT_TRANSACTION");
1376            case NFA_HCI_EVT_OPERATION_ENDED:
1377                return ("EVT_OPERATION_ENDED");
1378            default:
1379                break;
1380            }
1381        }
1382    }
1383
1384    switch (evt)
1385    {
1386    case NFA_HCI_EVT_HCI_END_OF_OPERATION:
1387        return ("EVT_END_OF_OPERATION");
1388    case NFA_HCI_EVT_POST_DATA:
1389        return ("EVT_POST_DATA");
1390    case NFA_HCI_EVT_HOT_PLUG:
1391        return ("EVT_HOT_PLUG");
1392    default:
1393        sprintf (unknown, "?? Unknown: %u ?? ", evt);
1394        return (unknown);
1395    }
1396}
1397#endif
1398
1399
1400static void handle_debug_loopback (BT_HDR *p_buf, UINT8 pipe, UINT8 type, UINT8 instruction)
1401{
1402    UINT8 *p = (UINT8 *) (p_buf + 1) + p_buf->offset;
1403    static UINT8  next_pipe = 0x10;
1404
1405    if (type == NFA_HCI_COMMAND_TYPE)
1406    {
1407        switch (instruction)
1408        {
1409        case NFA_HCI_ADM_CREATE_PIPE:
1410            p[6] = next_pipe++;
1411            p[5] = p[4];
1412            p[4] = p[3];
1413            p[3] = p[2];
1414            p[2] = 3;
1415            p[1] = (NFA_HCI_RESPONSE_TYPE << 6) | NFA_HCI_ANY_OK;
1416            p_buf->len = p_buf->offset + 7;
1417            break;
1418
1419        case NFA_HCI_ANY_GET_PARAMETER:
1420            p[1] = (NFA_HCI_RESPONSE_TYPE << 6) | NFA_HCI_ANY_OK;
1421            memcpy (&p[2], (UINT8 *) nfa_hci_cb.cfg.admin_gate.session_id, NFA_HCI_SESSION_ID_LEN);
1422            p_buf->len = p_buf->offset + 2 + NFA_HCI_SESSION_ID_LEN;
1423            break;
1424
1425        default:
1426            p[1] = (NFA_HCI_RESPONSE_TYPE << 6) | NFA_HCI_ANY_OK;
1427            p_buf->len = p_buf->offset + 2;
1428            break;
1429        }
1430    }
1431    else if (type == NFA_HCI_RESPONSE_TYPE)
1432    {
1433        GKI_freebuf (p_buf);
1434        return;
1435    }
1436
1437    p_buf->event = NFA_HCI_CHECK_QUEUE_EVT;
1438    nfa_sys_sendmsg (p_buf);
1439}
1440
1441