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