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