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
35using android::base::StringPrintf;
36
37extern bool nfc_debug_enabled;
38
39static void handle_debug_loopback(NFC_HDR* p_buf, uint8_t type,
40                                  uint8_t instruction);
41uint8_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*******************************************************************************/
52tNFA_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*******************************************************************************/
74tNFA_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*******************************************************************************/
94tNFA_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*******************************************************************************/
115tNFA_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*******************************************************************************/
136uint8_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*******************************************************************************/
159uint8_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*******************************************************************************/
186tNFA_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*******************************************************************************/
204tNFA_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*******************************************************************************/
226tNFA_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*******************************************************************************/
297tNFA_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*******************************************************************************/
389uint8_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*******************************************************************************/
417tNFA_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*******************************************************************************/
455void 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*******************************************************************************/
483tNFA_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*******************************************************************************/
530tNFA_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*******************************************************************************/
572tNFA_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*******************************************************************************/
607bool 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*******************************************************************************/
641tNFA_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*******************************************************************************/
672tNFA_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*******************************************************************************/
703bool 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*******************************************************************************/
723bool 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*******************************************************************************/
743bool 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*******************************************************************************/
762tNFA_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*******************************************************************************/
795tNFA_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*******************************************************************************/
844void 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*******************************************************************************/
881tNFA_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*******************************************************************************/
911tNFA_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*******************************************************************************/
941tNFA_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*******************************************************************************/
964tNFA_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*******************************************************************************/
984tNFA_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*******************************************************************************/
1004tNFA_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*******************************************************************************/
1023tNFA_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*******************************************************************************/
1049void 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*******************************************************************************/
1078void 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*******************************************************************************/
1097void 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*******************************************************************************/
1120static 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*******************************************************************************/
1160static 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*******************************************************************************/
1182std::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*******************************************************************************/
1218std::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*******************************************************************************/
1272std::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*******************************************************************************/
1306char* 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*******************************************************************************/
1342std::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
1371static 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