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