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  *  NFA interface to HCI
22  *
23  ******************************************************************************/
24 #include <android-base/stringprintf.h>
25 #include <base/logging.h>
26 
27 #include "nfa_hci_api.h"
28 #include "nfa_hci_defs.h"
29 #include "nfa_hci_int.h"
30 
31 using android::base::StringPrintf;
32 
33 extern bool nfc_debug_enabled;
34 
35 /*******************************************************************************
36 **
37 ** Function         NFA_HciRegister
38 **
39 ** Description      This function will register an application with hci and
40 **                  returns an application handle and provides a mechanism to
41 **                  register a callback with HCI to receive NFA HCI event
42 **                  notification. When the application is registered (or if an
43 **                  error occurs), the app will be notified with
44 **                  NFA_HCI_REGISTER_EVT. Previous session information including
45 **                  allocated gates, created pipes and pipes states will be
46 **                  returned as part of tNFA_HCI_REGISTER data.
47 **
48 ** Returns          NFA_STATUS_OK if successfully initiated
49 **                  NFA_STATUS_FAILED otherwise
50 **
51 *******************************************************************************/
NFA_HciRegister(char * p_app_name,tNFA_HCI_CBACK * p_cback,bool b_send_conn_evts)52 tNFA_STATUS NFA_HciRegister(char* p_app_name, tNFA_HCI_CBACK* p_cback,
53                             bool b_send_conn_evts) {
54   tNFA_HCI_API_REGISTER_APP* p_msg;
55   uint8_t app_name_len;
56 
57   if (p_app_name == nullptr) {
58     DLOG_IF(INFO, nfc_debug_enabled)
59         << StringPrintf("Invalid Application name");
60     return (NFA_STATUS_FAILED);
61   }
62 
63   if (p_cback == nullptr) {
64     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
65         "Application should provide callback function to "
66         "register!");
67     return (NFA_STATUS_FAILED);
68   }
69 
70   DLOG_IF(INFO, nfc_debug_enabled)
71       << StringPrintf("Application Name: %s", p_app_name);
72 
73   app_name_len = (uint8_t)strlen(p_app_name);
74 
75   /* Register the application with HCI */
76   if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
77       (p_app_name != nullptr) && (app_name_len <= NFA_MAX_HCI_APP_NAME_LEN) &&
78       ((p_msg = (tNFA_HCI_API_REGISTER_APP*)GKI_getbuf(
79             sizeof(tNFA_HCI_API_REGISTER_APP))) != nullptr)) {
80     p_msg->hdr.event = NFA_HCI_API_REGISTER_APP_EVT;
81 
82     /* Save application name and callback */
83     memset(p_msg->app_name, 0, sizeof(p_msg->app_name));
84     strlcpy(p_msg->app_name, p_app_name, NFA_MAX_HCI_APP_NAME_LEN);
85     p_msg->p_cback = p_cback;
86     p_msg->b_send_conn_evts = b_send_conn_evts;
87 
88     nfa_sys_sendmsg(p_msg);
89     return (NFA_STATUS_OK);
90   }
91 
92   return (NFA_STATUS_FAILED);
93 }
94 
95 /*******************************************************************************
96 **
97 ** Function         NFA_HciGetGateAndPipeList
98 **
99 ** Description      This function will get the list of gates allocated to the
100 **                  application and list of dynamic pipes created by the
101 **                  application. The app will be notified with
102 **                  NFA_HCI_GET_GATE_PIPE_LIST_EVT. List of allocated dynamic
103 **                  gates to the application and list of pipes created by the
104 **                  application will be returned as part of
105 **                  tNFA_HCI_GET_GATE_PIPE_LIST data.
106 **
107 ** Returns          NFA_STATUS_OK if successfully initiated
108 **                  NFA_STATUS_FAILED otherwise
109 **
110 *******************************************************************************/
NFA_HciGetGateAndPipeList(tNFA_HANDLE hci_handle)111 tNFA_STATUS NFA_HciGetGateAndPipeList(tNFA_HANDLE hci_handle) {
112   tNFA_HCI_API_GET_APP_GATE_PIPE* p_msg;
113 
114   if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
115     DLOG_IF(INFO, nfc_debug_enabled)
116         << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
117     return (NFA_STATUS_FAILED);
118   }
119 
120   DLOG_IF(INFO, nfc_debug_enabled)
121       << StringPrintf("hci_handle:0x%04x", hci_handle);
122 
123   /* Register the application with HCI */
124   if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
125       ((p_msg = (tNFA_HCI_API_GET_APP_GATE_PIPE*)GKI_getbuf(
126             sizeof(tNFA_HCI_API_GET_APP_GATE_PIPE))) != nullptr)) {
127     p_msg->hdr.event = NFA_HCI_API_GET_APP_GATE_PIPE_EVT;
128     p_msg->hci_handle = hci_handle;
129 
130     nfa_sys_sendmsg(p_msg);
131     return (NFA_STATUS_OK);
132   }
133 
134   return (NFA_STATUS_FAILED);
135 }
136 
137 /*******************************************************************************
138 **
139 ** Function         NFA_HciDeregister
140 **
141 ** Description      This function is called to deregister an application
142 **                  from HCI. The app will be notified by NFA_HCI_DEREGISTER_EVT
143 **                  after deleting all the pipes owned by the app and
144 **                  deallocating all the gates allocated to the app or if an
145 **                  error occurs. Even if deregistration fails, the app has to
146 **                  register again to provide a new cback function.
147 **
148 ** Returns          NFA_STATUS_OK if the application is deregistered
149 **                  successfully
150 **                  NFA_STATUS_FAILED otherwise
151 
152 *******************************************************************************/
NFA_HciDeregister(char * p_app_name)153 tNFA_STATUS NFA_HciDeregister(char* p_app_name) {
154   tNFA_HCI_API_DEREGISTER_APP* p_msg;
155   int xx;
156   uint8_t app_name_len;
157 
158   if (p_app_name == nullptr) {
159     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("Invalid Application");
160     return (NFA_STATUS_FAILED);
161   }
162 
163   DLOG_IF(INFO, nfc_debug_enabled)
164       << StringPrintf("Application Name: %s", p_app_name);
165   app_name_len = (uint8_t)strlen(p_app_name);
166 
167   if (app_name_len > NFA_MAX_HCI_APP_NAME_LEN) return (NFA_STATUS_FAILED);
168 
169   /* Find the application registration */
170   for (xx = 0; xx < NFA_HCI_MAX_APP_CB; xx++) {
171     if ((nfa_hci_cb.cfg.reg_app_names[xx][0] != 0) &&
172         (!strncmp(p_app_name, &nfa_hci_cb.cfg.reg_app_names[xx][0],
173                   app_name_len)))
174       break;
175   }
176 
177   if (xx == NFA_HCI_MAX_APP_CB) {
178     LOG(ERROR) << StringPrintf("Application Name: %s  NOT FOUND", p_app_name);
179     return (NFA_STATUS_FAILED);
180   }
181 
182   /* Deregister the application with HCI */
183   if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
184       ((p_msg = (tNFA_HCI_API_DEREGISTER_APP*)GKI_getbuf(
185             sizeof(tNFA_HCI_API_DEREGISTER_APP))) != nullptr)) {
186     p_msg->hdr.event = NFA_HCI_API_DEREGISTER_APP_EVT;
187 
188     memset(p_msg->app_name, 0, sizeof(p_msg->app_name));
189     strlcpy(p_msg->app_name, p_app_name, NFA_MAX_HCI_APP_NAME_LEN);
190 
191     nfa_sys_sendmsg(p_msg);
192     return (NFA_STATUS_OK);
193   }
194 
195   return (NFA_STATUS_FAILED);
196 }
197 
198 /*******************************************************************************
199 **
200 ** Function         NFA_HciAllocGate
201 **
202 ** Description      This function will allocate the gate if any specified or an
203 **                  available generic gate for the app to provide an entry point
204 **                  for a particular service to other host or to establish
205 **                  communication with other host. When the gate is
206 **                  allocated (or if an error occurs), the app will be notified
207 **                  with NFA_HCI_ALLOCATE_GATE_EVT with the gate id. The
208 **                  allocated Gate information will be stored in non volatile
209 **                  memory.
210 **
211 ** Returns          NFA_STATUS_OK if this API started
212 **                  NFA_STATUS_FAILED if no generic gate is available
213 **
214 *******************************************************************************/
NFA_HciAllocGate(tNFA_HANDLE hci_handle,uint8_t gate)215 tNFA_STATUS NFA_HciAllocGate(tNFA_HANDLE hci_handle, uint8_t gate) {
216   tNFA_HCI_API_ALLOC_GATE* p_msg;
217 
218   if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
219     DLOG_IF(INFO, nfc_debug_enabled)
220         << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
221     return (NFA_STATUS_FAILED);
222   }
223 
224   if ((gate) && ((gate < NFA_HCI_FIRST_HOST_SPECIFIC_GENERIC_GATE) ||
225                  (gate > NFA_HCI_LAST_PROP_GATE) ||
226                  (gate == NFA_HCI_CONNECTIVITY_GATE))) {
227     DLOG_IF(INFO, nfc_debug_enabled)
228         << StringPrintf("Cannot allocate gate:0x%02x", gate);
229     return (NFA_STATUS_FAILED);
230   }
231 
232   DLOG_IF(INFO, nfc_debug_enabled)
233       << StringPrintf("hci_handle:0x%04x, Gate:0x%02x", hci_handle, gate);
234 
235   /* Request HCI to allocate gate to the application */
236   if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
237       ((p_msg = (tNFA_HCI_API_ALLOC_GATE*)GKI_getbuf(
238             sizeof(tNFA_HCI_API_ALLOC_GATE))) != nullptr)) {
239     p_msg->hdr.event = NFA_HCI_API_ALLOC_GATE_EVT;
240     p_msg->hci_handle = hci_handle;
241     p_msg->gate = gate;
242 
243     nfa_sys_sendmsg(p_msg);
244     return (NFA_STATUS_OK);
245   }
246   return (NFA_STATUS_FAILED);
247 }
248 
249 /*******************************************************************************
250 **
251 ** Function         NFA_HciDeallocGate
252 **
253 ** Description      This function will release the specified gate that was
254 **                  previously allocated to the application. When the generic
255 **                  gate is released (or if an error occurs), the app will be
256 **                  notified with NFA_HCI_DEALLOCATE_GATE_EVT with the gate id.
257 **
258 ** Returns          NFA_STATUS_OK if successfully initiated
259 **                  NFA_STATUS_FAILED otherwise
260 **
261 *******************************************************************************/
NFA_HciDeallocGate(tNFA_HANDLE hci_handle,uint8_t gate)262 tNFA_STATUS NFA_HciDeallocGate(tNFA_HANDLE hci_handle, uint8_t gate) {
263   tNFA_HCI_API_DEALLOC_GATE* p_msg;
264 
265   if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
266     DLOG_IF(INFO, nfc_debug_enabled)
267         << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
268     return (NFA_STATUS_FAILED);
269   }
270 
271   if ((gate < NFA_HCI_FIRST_HOST_SPECIFIC_GENERIC_GATE) ||
272       (gate > NFA_HCI_LAST_PROP_GATE) || (gate == NFA_HCI_CONNECTIVITY_GATE)) {
273     DLOG_IF(INFO, nfc_debug_enabled)
274         << StringPrintf("Cannot deallocate the gate:0x%02x", gate);
275     return (NFA_STATUS_FAILED);
276   }
277 
278   DLOG_IF(INFO, nfc_debug_enabled)
279       << StringPrintf("hci_handle:0x%04x, gate:0x%02X", hci_handle, gate);
280 
281   /* Request HCI to deallocate the gate that was previously allocated to the
282    * application */
283   if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
284       ((p_msg = (tNFA_HCI_API_DEALLOC_GATE*)GKI_getbuf(
285             sizeof(tNFA_HCI_API_DEALLOC_GATE))) != nullptr)) {
286     p_msg->hdr.event = NFA_HCI_API_DEALLOC_GATE_EVT;
287     p_msg->hci_handle = hci_handle;
288     p_msg->gate = gate;
289 
290     nfa_sys_sendmsg(p_msg);
291     return (NFA_STATUS_OK);
292   }
293   return (NFA_STATUS_FAILED);
294 }
295 
296 /*******************************************************************************
297 **
298 ** Function         NFA_HciGetHostList
299 **
300 ** Description      This function will request the host controller to return the
301 **                  list of hosts that are present in the host network. When
302 **                  host controller responds with the host list (or if an error
303 **                  occurs), the app will be notified with NFA_HCI_HOST_LIST_EVT
304 **
305 ** Returns          NFA_STATUS_OK if successfully initiated
306 **                  NFA_STATUS_FAILED otherwise
307 **
308 *******************************************************************************/
NFA_HciGetHostList(tNFA_HANDLE hci_handle)309 tNFA_STATUS NFA_HciGetHostList(tNFA_HANDLE hci_handle) {
310   tNFA_HCI_API_GET_HOST_LIST* p_msg;
311 
312   if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
313     DLOG_IF(INFO, nfc_debug_enabled)
314         << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
315     return (NFA_STATUS_FAILED);
316   }
317 
318   DLOG_IF(INFO, nfc_debug_enabled)
319       << StringPrintf("hci_handle:0x%04x", hci_handle);
320 
321   /* Request HCI to get list of host in the hci network */
322   if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
323       ((p_msg = (tNFA_HCI_API_GET_HOST_LIST*)GKI_getbuf(
324             sizeof(tNFA_HCI_API_GET_HOST_LIST))) != nullptr)) {
325     p_msg->hdr.event = NFA_HCI_API_GET_HOST_LIST_EVT;
326     p_msg->hci_handle = hci_handle;
327 
328     nfa_sys_sendmsg(p_msg);
329     return (NFA_STATUS_OK);
330   }
331 
332   return (NFA_STATUS_FAILED);
333 }
334 
335 /*******************************************************************************
336 **
337 ** Function         NFA_HciCreatePipe
338 **
339 ** Description      This function is called to create a dynamic pipe with the
340 **                  specified host. When the dynamic pipe is created (or
341 **                  if an error occurs), the app will be notified with
342 **                  NFA_HCI_CREATE_PIPE_EVT with the pipe id. If a pipe exists
343 **                  between the two gates passed as argument and if it was
344 **                  created earlier by the calling application then the pipe
345 **                  id of the existing pipe will be returned and a new pipe
346 **                  will not be created. After successful creation of pipe,
347 **                  registry entry will be created for the dynamic pipe and
348 **                  all information related to the pipe will be stored in non
349 **                  volatile memory.
350 **
351 ** Returns          NFA_STATUS_OK if successfully initiated
352 **                  NFA_STATUS_FAILED otherwise
353 **
354 *******************************************************************************/
NFA_HciCreatePipe(tNFA_HANDLE hci_handle,uint8_t source_gate_id,uint8_t dest_host,uint8_t dest_gate)355 tNFA_STATUS NFA_HciCreatePipe(tNFA_HANDLE hci_handle, uint8_t source_gate_id,
356                               uint8_t dest_host, uint8_t dest_gate) {
357   tNFA_HCI_API_CREATE_PIPE_EVT* p_msg;
358 
359   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
360       "hci_handle:0x%04x, source gate:0x%02X, "
361       "destination host:0x%02X , destination gate:0x%02X",
362       hci_handle, source_gate_id, dest_host, dest_gate);
363 
364   if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
365     DLOG_IF(INFO, nfc_debug_enabled)
366         << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
367     return (NFA_STATUS_FAILED);
368   }
369 
370   if ((source_gate_id < NFA_HCI_FIRST_HOST_SPECIFIC_GENERIC_GATE) ||
371       (source_gate_id > NFA_HCI_LAST_PROP_GATE)) {
372     DLOG_IF(INFO, nfc_debug_enabled)
373         << StringPrintf("Invalid local Gate:0x%02x", source_gate_id);
374     return (NFA_STATUS_FAILED);
375   }
376 
377   if (((dest_gate < NFA_HCI_FIRST_HOST_SPECIFIC_GENERIC_GATE) &&
378        (dest_gate != NFA_HCI_LOOP_BACK_GATE) &&
379        (dest_gate != NFA_HCI_IDENTITY_MANAGEMENT_GATE)) ||
380       (dest_gate > NFA_HCI_LAST_PROP_GATE)) {
381     DLOG_IF(INFO, nfc_debug_enabled)
382         << StringPrintf("Invalid Destination Gate:0x%02x", dest_gate);
383     return (NFA_STATUS_FAILED);
384   }
385 
386   if (!nfa_hciu_is_active_host(dest_host)) {
387     DLOG_IF(INFO, nfc_debug_enabled)
388         << StringPrintf("Host not active: 0x%02x", dest_host);
389     return (NFA_STATUS_FAILED);
390   }
391 
392   /* Request HCI to create a pipe between two specified gates */
393   if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
394       (!nfa_hci_cb.b_low_power_mode) &&
395       ((p_msg = (tNFA_HCI_API_CREATE_PIPE_EVT*)GKI_getbuf(
396             sizeof(tNFA_HCI_API_CREATE_PIPE_EVT))) != nullptr)) {
397     p_msg->hdr.event = NFA_HCI_API_CREATE_PIPE_EVT;
398     p_msg->hci_handle = hci_handle;
399     p_msg->source_gate = source_gate_id;
400     p_msg->dest_host = dest_host; /* Host id of the destination host */
401     p_msg->dest_gate = dest_gate; /* Gate id of the destination gate */
402 
403     nfa_sys_sendmsg(p_msg);
404     return (NFA_STATUS_OK);
405   }
406   return (NFA_STATUS_FAILED);
407 }
408 
409 /*******************************************************************************
410 **
411 ** Function         NFA_HciOpenPipe
412 **
413 ** Description      This function is called to open a dynamic pipe.
414 **                  When the dynamic pipe is opened (or
415 **                  if an error occurs), the app will be notified with
416 **                  NFA_HCI_OPEN_PIPE_EVT with the pipe id.
417 **
418 ** Returns          NFA_STATUS_OK if successfully initiated
419 **                  NFA_STATUS_FAILED otherwise
420 **
421 *******************************************************************************/
NFA_HciOpenPipe(tNFA_HANDLE hci_handle,uint8_t pipe)422 tNFA_STATUS NFA_HciOpenPipe(tNFA_HANDLE hci_handle, uint8_t pipe) {
423   tNFA_HCI_API_OPEN_PIPE_EVT* p_msg;
424 
425   if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
426     DLOG_IF(INFO, nfc_debug_enabled)
427         << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
428     return (NFA_STATUS_FAILED);
429   }
430 
431   if ((pipe < NFA_HCI_FIRST_DYNAMIC_PIPE) ||
432       (pipe > NFA_HCI_LAST_DYNAMIC_PIPE)) {
433     DLOG_IF(INFO, nfc_debug_enabled)
434         << StringPrintf("Invalid Pipe:0x%02x", pipe);
435     return (NFA_STATUS_FAILED);
436   }
437 
438   DLOG_IF(INFO, nfc_debug_enabled)
439       << StringPrintf("hci_handle:0x%04x, pipe:0x%02X", hci_handle, pipe);
440 
441   /* Request HCI to open a pipe if it is in closed state */
442   if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
443       (!nfa_hci_cb.b_low_power_mode) &&
444       ((p_msg = (tNFA_HCI_API_OPEN_PIPE_EVT*)GKI_getbuf(
445             sizeof(tNFA_HCI_API_OPEN_PIPE_EVT))) != nullptr)) {
446     p_msg->hdr.event = NFA_HCI_API_OPEN_PIPE_EVT;
447     p_msg->hci_handle = hci_handle;
448     p_msg->pipe = pipe; /* Pipe ID of the pipe to open */
449 
450     nfa_sys_sendmsg(p_msg);
451     return (NFA_STATUS_OK);
452   }
453   return (NFA_STATUS_FAILED);
454 }
455 
456 /*******************************************************************************
457 **
458 ** Function         NFA_HciGetRegistry
459 **
460 ** Description      This function requests a peer host to return the desired
461 **                  registry field value for the gate that the pipe is on.
462 **
463 **                  When the peer host responds,the app is notified with
464 **                  NFA_HCI_GET_REG_RSP_EVT or
465 **                  if an error occurs in sending the command the app will be
466 **                  notified by NFA_HCI_CMD_SENT_EVT
467 **
468 ** Returns          NFA_STATUS_OK if successfully initiated
469 **                  NFA_STATUS_FAILED otherwise
470 **
471 *******************************************************************************/
NFA_HciGetRegistry(tNFA_HANDLE hci_handle,uint8_t pipe,uint8_t reg_inx)472 tNFA_STATUS NFA_HciGetRegistry(tNFA_HANDLE hci_handle, uint8_t pipe,
473                                uint8_t reg_inx) {
474   tNFA_HCI_API_GET_REGISTRY* p_msg;
475 
476   if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
477     DLOG_IF(INFO, nfc_debug_enabled)
478         << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
479     return (NFA_STATUS_FAILED);
480   }
481 
482   if (pipe < NFA_HCI_FIRST_DYNAMIC_PIPE) {
483     DLOG_IF(INFO, nfc_debug_enabled)
484         << StringPrintf("Invalid Pipe:0x%02x", pipe);
485     return (NFA_STATUS_FAILED);
486   }
487 
488   DLOG_IF(INFO, nfc_debug_enabled)
489       << StringPrintf("hci_handle:0x%04x  Pipe: 0x%02x", hci_handle, pipe);
490 
491   /* Request HCI to get list of gates supported by the specified host */
492   if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
493       ((p_msg = (tNFA_HCI_API_GET_REGISTRY*)GKI_getbuf(
494             sizeof(tNFA_HCI_API_GET_REGISTRY))) != nullptr)) {
495     p_msg->hdr.event = NFA_HCI_API_GET_REGISTRY_EVT;
496     p_msg->hci_handle = hci_handle;
497     p_msg->pipe = pipe;
498     p_msg->reg_inx = reg_inx;
499 
500     nfa_sys_sendmsg(p_msg);
501     return (NFA_STATUS_OK);
502   }
503 
504   return (NFA_STATUS_FAILED);
505 }
506 
507 /*******************************************************************************
508 **
509 ** Function         NFA_HciSendCommand
510 **
511 ** Description      This function is called to send a command on a pipe created
512 **                  by the application.
513 **                  The app will be notified by NFA_HCI_CMD_SENT_EVT if an error
514 **                  occurs.
515 **                  When the peer host responds,the app is notified with
516 **                  NFA_HCI_RSP_RCVD_EVT
517 **
518 ** Returns          NFA_STATUS_OK if successfully initiated
519 **                  NFA_STATUS_FAILED otherwise
520 **
521 *******************************************************************************/
NFA_HciSendCommand(tNFA_HANDLE hci_handle,uint8_t pipe,uint8_t cmd_code,uint16_t cmd_size,uint8_t * p_data)522 tNFA_STATUS NFA_HciSendCommand(tNFA_HANDLE hci_handle, uint8_t pipe,
523                                uint8_t cmd_code, uint16_t cmd_size,
524                                uint8_t* p_data) {
525   tNFA_HCI_API_SEND_CMD_EVT* p_msg;
526 
527   if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
528     DLOG_IF(INFO, nfc_debug_enabled)
529         << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
530     return (NFA_STATUS_FAILED);
531   }
532 
533   if (pipe < NFA_HCI_FIRST_DYNAMIC_PIPE) {
534     DLOG_IF(INFO, nfc_debug_enabled)
535         << StringPrintf("Invalid Pipe:0x%02x", pipe);
536     return (NFA_STATUS_FAILED);
537   }
538 
539   if ((cmd_size && (p_data == nullptr)) || (cmd_size > NFA_MAX_HCI_CMD_LEN)) {
540     DLOG_IF(INFO, nfc_debug_enabled)
541         << StringPrintf("Invalid cmd size:0x%02x", cmd_size);
542     return (NFA_STATUS_FAILED);
543   }
544 
545   DLOG_IF(INFO, nfc_debug_enabled)
546       << StringPrintf("hci_handle:0x%04x, pipe:0x%02x  Code: 0x%02x",
547                       hci_handle, pipe, cmd_code);
548 
549   /* Request HCI to post event data on a particular pipe */
550   if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
551       ((p_msg = (tNFA_HCI_API_SEND_CMD_EVT*)GKI_getbuf(
552             sizeof(tNFA_HCI_API_SEND_CMD_EVT))) != nullptr)) {
553     p_msg->hdr.event = NFA_HCI_API_SEND_CMD_EVT;
554     p_msg->hci_handle = hci_handle;
555     p_msg->pipe = pipe;
556     p_msg->cmd_code = cmd_code;
557     p_msg->cmd_len = cmd_size;
558 
559     if (cmd_size) memcpy(p_msg->data, p_data, cmd_size);
560 
561     nfa_sys_sendmsg(p_msg);
562     return (NFA_STATUS_OK);
563   }
564 
565   return (NFA_STATUS_FAILED);
566 }
567 
568 /*******************************************************************************
569 **
570 ** Function         NFA_HciSendEvent
571 **
572 ** Description      This function is called to send any event on a pipe created
573 **                  by the application.
574 **                  The app will be notified by NFA_HCI_EVENT_SENT_EVT
575 **                  after successfully sending the event on the specified pipe
576 **                  or if an error occurs. The application should wait for this
577 **                  event before releasing event buffer passed as argument.
578 **                  If the app is expecting a response to the event then it can
579 **                  provide response buffer for collecting the response. If it
580 **                  provides a response buffer it can also provide response
581 **                  timeout indicating maximum timeout for the response.
582 **                  Maximum of NFA_MAX_HCI_EVENT_LEN bytes APDU can be received
583 **                  using internal buffer if no response buffer is provided by
584 **                  the application. The app will be notified by
585 **                  NFA_HCI_EVENT_RCVD_EVT after receiving the response event
586 **                  or on timeout if app provided response buffer and response
587 **                  timeout. If response buffer and response timeout is provided
588 **                  by the application, it should wait for this event before
589 **                  releasing the response buffer. If the application did not
590 **                  provide response timeout then it should not release the
591 **                  response buffer until it receives NFA_HCI_EVENT_RCVD_EVT or
592 **                  after timeout it sends next event on the same pipe
593 **                  and receives NFA_HCI_EVENT_SENT_EVT for that event.
594 **
595 ** Returns          NFA_STATUS_OK if successfully initiated
596 **                  NFA_STATUS_FAILED otherwise
597 **
598 *******************************************************************************/
NFA_HciSendEvent(tNFA_HANDLE hci_handle,uint8_t pipe,uint8_t evt_code,uint16_t evt_size,uint8_t * p_data,uint16_t rsp_size,uint8_t * p_rsp_buf,uint16_t rsp_timeout)599 tNFA_STATUS NFA_HciSendEvent(tNFA_HANDLE hci_handle, uint8_t pipe,
600                              uint8_t evt_code, uint16_t evt_size,
601                              uint8_t* p_data, uint16_t rsp_size,
602                              uint8_t* p_rsp_buf, uint16_t rsp_timeout) {
603   tNFA_HCI_API_SEND_EVENT_EVT* p_msg;
604 
605   DLOG_IF(INFO, nfc_debug_enabled)
606       << StringPrintf("hci_handle:0x%04x, pipe:0x%02x  Code: 0x%02x",
607                       hci_handle, pipe, evt_code);
608 
609   if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
610     DLOG_IF(INFO, nfc_debug_enabled)
611         << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
612     return (NFA_STATUS_FAILED);
613   }
614 
615   if (pipe < NFA_HCI_FIRST_DYNAMIC_PIPE) {
616     DLOG_IF(INFO, nfc_debug_enabled)
617         << StringPrintf("Invalid Pipe:0x%02x", pipe);
618     return (NFA_STATUS_FAILED);
619   }
620 
621   if (evt_size && (p_data == nullptr)) {
622     DLOG_IF(INFO, nfc_debug_enabled)
623         << StringPrintf("Invalid Event size:0x%02x", evt_size);
624     return (NFA_STATUS_FAILED);
625   }
626 
627   if (rsp_size && (p_rsp_buf == nullptr)) {
628     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
629         "No Event buffer, but invalid event buffer size "
630         ":%u",
631         rsp_size);
632     return (NFA_STATUS_FAILED);
633   }
634 
635   /* Request HCI to post event data on a particular pipe */
636   if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
637       ((p_msg = (tNFA_HCI_API_SEND_EVENT_EVT*)GKI_getbuf(
638             sizeof(tNFA_HCI_API_SEND_EVENT_EVT))) != nullptr)) {
639     p_msg->hdr.event = NFA_HCI_API_SEND_EVENT_EVT;
640     p_msg->hci_handle = hci_handle;
641     p_msg->pipe = pipe;
642     p_msg->evt_code = evt_code;
643     p_msg->evt_len = evt_size;
644     p_msg->p_evt_buf = p_data;
645     p_msg->rsp_len = rsp_size;
646     p_msg->p_rsp_buf = p_rsp_buf;
647     p_msg->rsp_timeout = rsp_timeout;
648 
649     nfa_sys_sendmsg(p_msg);
650     return (NFA_STATUS_OK);
651   }
652 
653   return (NFA_STATUS_FAILED);
654 }
655 
656 /*******************************************************************************
657 **
658 ** Function         NFA_HciClosePipe
659 **
660 ** Description      This function is called to close a dynamic pipe.
661 **                  When the dynamic pipe is closed (or
662 **                  if an error occurs), the app will be notified with
663 **                  NFA_HCI_CLOSE_PIPE_EVT with the pipe id.
664 **
665 ** Returns          NFA_STATUS_OK if successfully initiated
666 **                  NFA_STATUS_FAILED otherwise
667 **
668 *******************************************************************************/
NFA_HciClosePipe(tNFA_HANDLE hci_handle,uint8_t pipe)669 tNFA_STATUS NFA_HciClosePipe(tNFA_HANDLE hci_handle, uint8_t pipe) {
670   tNFA_HCI_API_CLOSE_PIPE_EVT* p_msg;
671 
672   DLOG_IF(INFO, nfc_debug_enabled)
673       << StringPrintf("hci_handle:0x%04x, pipe:0x%02X", hci_handle, pipe);
674 
675   if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
676     DLOG_IF(INFO, nfc_debug_enabled)
677         << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
678     return (NFA_STATUS_FAILED);
679   }
680 
681   if ((pipe < NFA_HCI_FIRST_DYNAMIC_PIPE) ||
682       (pipe > NFA_HCI_LAST_DYNAMIC_PIPE)) {
683     DLOG_IF(INFO, nfc_debug_enabled)
684         << StringPrintf("Invalid Pipe:0x%02x", pipe);
685     return (NFA_STATUS_FAILED);
686   }
687 
688   /* Request HCI to close a pipe if it is in opened state */
689   if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
690       (!nfa_hci_cb.b_low_power_mode) &&
691       ((p_msg = (tNFA_HCI_API_CLOSE_PIPE_EVT*)GKI_getbuf(
692             sizeof(tNFA_HCI_API_CLOSE_PIPE_EVT))) != nullptr)) {
693     p_msg->hdr.event = NFA_HCI_API_CLOSE_PIPE_EVT;
694     p_msg->hci_handle = hci_handle;
695     p_msg->pipe = pipe;
696 
697     nfa_sys_sendmsg(p_msg);
698     return (NFA_STATUS_OK);
699   }
700   return (NFA_STATUS_FAILED);
701 }
702 
703 /*******************************************************************************
704 **
705 ** Function         NFA_HciDeletePipe
706 **
707 ** Description      This function is called to delete a particular dynamic pipe.
708 **                  When the dynamic pipe is deleted (or if an error occurs),
709 **                  the app will be notified with NFA_HCI_DELETE_PIPE_EVT with
710 **                  the pipe id. After successful deletion of pipe, registry
711 **                  entry will be deleted for the dynamic pipe and all
712 **                  information related to the pipe will be deleted from non
713 **                  volatile memory.
714 **
715 ** Returns          NFA_STATUS_OK if successfully initiated
716 **                  NFA_STATUS_FAILED otherwise
717 **
718 *******************************************************************************/
NFA_HciDeletePipe(tNFA_HANDLE hci_handle,uint8_t pipe)719 tNFA_STATUS NFA_HciDeletePipe(tNFA_HANDLE hci_handle, uint8_t pipe) {
720   tNFA_HCI_API_DELETE_PIPE_EVT* p_msg;
721 
722   if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
723     DLOG_IF(INFO, nfc_debug_enabled)
724         << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
725     return (NFA_STATUS_FAILED);
726   }
727 
728   if ((pipe < NFA_HCI_FIRST_DYNAMIC_PIPE) ||
729       (pipe > NFA_HCI_LAST_DYNAMIC_PIPE)) {
730     DLOG_IF(INFO, nfc_debug_enabled)
731         << StringPrintf("Invalid Pipe:0x%02x", pipe);
732     return (NFA_STATUS_FAILED);
733   }
734 
735   DLOG_IF(INFO, nfc_debug_enabled)
736       << StringPrintf("hci_handle:0x%04x, pipe:0x%02X", hci_handle, pipe);
737 
738   /* Request HCI to delete a pipe created by the application identified by hci
739    * handle */
740   if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
741       (!nfa_hci_cb.b_low_power_mode) &&
742       ((p_msg = (tNFA_HCI_API_DELETE_PIPE_EVT*)GKI_getbuf(
743             sizeof(tNFA_HCI_API_DELETE_PIPE_EVT))) != nullptr)) {
744     p_msg->hdr.event = NFA_HCI_API_DELETE_PIPE_EVT;
745     p_msg->hci_handle = hci_handle;
746     p_msg->pipe = pipe;
747 
748     nfa_sys_sendmsg(p_msg);
749     return (NFA_STATUS_OK);
750   }
751   return (NFA_STATUS_FAILED);
752 }
753 
754 /*******************************************************************************
755 **
756 ** Function         NFA_HciAddStaticPipe
757 **
758 ** Description      This function is called to add a static pipe for sending
759 **                  7816 APDUs. When the static pipe is added (or if an error
760 **                  occurs), the app will be notified with
761 **                  NFA_HCI_ADD_STATIC_PIPE_EVT with the status.
762 **
763 ** Returns          NFA_STATUS_OK if successfully initiated
764 **                  NFA_STATUS_FAILED otherwise
765 **
766 *******************************************************************************/
NFA_HciAddStaticPipe(tNFA_HANDLE hci_handle,uint8_t host,uint8_t gate,uint8_t pipe)767 tNFA_STATUS NFA_HciAddStaticPipe(tNFA_HANDLE hci_handle, uint8_t host,
768                                  uint8_t gate, uint8_t pipe) {
769   tNFA_HCI_API_ADD_STATIC_PIPE_EVT* p_msg;
770 
771   if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
772     DLOG_IF(INFO, nfc_debug_enabled)
773         << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
774     return (NFA_STATUS_FAILED);
775   }
776 
777   if (!nfa_hciu_is_active_host(host)) {
778     DLOG_IF(INFO, nfc_debug_enabled)
779         << StringPrintf("Host not active: 0x%02x", host);
780     return (NFA_STATUS_FAILED);
781   }
782 
783   if (gate <= NFA_HCI_LAST_HOST_SPECIFIC_GATE) {
784     DLOG_IF(INFO, nfc_debug_enabled)
785         << StringPrintf("Invalid Gate:0x%02x", gate);
786     return (NFA_STATUS_FAILED);
787   }
788 
789   if (pipe <= NFA_HCI_LAST_DYNAMIC_PIPE) {
790     DLOG_IF(INFO, nfc_debug_enabled)
791         << StringPrintf("Invalid Pipe:0x%02x", pipe);
792     return (NFA_STATUS_FAILED);
793   }
794 
795   DLOG_IF(INFO, nfc_debug_enabled)
796       << StringPrintf("hci_handle:0x%04x, pipe:0x%02X", hci_handle, pipe);
797 
798   /* Request HCI to delete a pipe created by the application identified by hci
799    * handle */
800   if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
801       ((p_msg = (tNFA_HCI_API_ADD_STATIC_PIPE_EVT*)GKI_getbuf(
802             sizeof(tNFA_HCI_API_ADD_STATIC_PIPE_EVT))) != nullptr)) {
803     p_msg->hdr.event = NFA_HCI_API_ADD_STATIC_PIPE_EVT;
804     p_msg->hci_handle = hci_handle;
805     p_msg->host = host;
806     p_msg->gate = gate;
807     p_msg->pipe = pipe;
808 
809     nfa_sys_sendmsg(p_msg);
810     return (NFA_STATUS_OK);
811   }
812   /* Unable to add static pipe */
813   return (NFA_STATUS_FAILED);
814 }
815 
816 /*******************************************************************************
817 **
818 ** Function         NFA_HciDebug
819 **
820 ** Description      Debug function.
821 **
822 *******************************************************************************/
NFA_HciDebug(uint8_t action,uint8_t size,uint8_t * p_data)823 void NFA_HciDebug(uint8_t action, uint8_t size, uint8_t* p_data) {
824   int xx;
825   tNFA_HCI_DYN_GATE* pg = nfa_hci_cb.cfg.dyn_gates;
826   tNFA_HCI_DYN_PIPE* pp = nfa_hci_cb.cfg.dyn_pipes;
827   NFC_HDR* p_msg;
828   uint8_t* p;
829 
830   switch (action) {
831     case NFA_HCI_DEBUG_DISPLAY_CB:
832       DLOG_IF(INFO, nfc_debug_enabled)
833           << StringPrintf("NFA_HciDebug  Host List:");
834       for (xx = 0; xx < NFA_HCI_MAX_APP_CB; xx++) {
835         if (nfa_hci_cb.cfg.reg_app_names[xx][0] != 0) {
836           DLOG_IF(INFO, nfc_debug_enabled)
837               << StringPrintf("              Host Inx:  %u   Name: %s", xx,
838                               &nfa_hci_cb.cfg.reg_app_names[xx][0]);
839         }
840       }
841 
842       DLOG_IF(INFO, nfc_debug_enabled)
843           << StringPrintf("NFA_HciDebug  Gate List:");
844       for (xx = 0; xx < NFA_HCI_MAX_GATE_CB; xx++, pg++) {
845         if (pg->gate_id != 0) {
846           DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
847               "              Gate Inx: %x  ID: 0x%02x  Owner: 0x%04x  "
848               "PipeInxMask: 0x%08x",
849               xx, pg->gate_id, pg->gate_owner, pg->pipe_inx_mask);
850         }
851       }
852 
853       DLOG_IF(INFO, nfc_debug_enabled)
854           << StringPrintf("NFA_HciDebug  Pipe List:");
855       for (xx = 0; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++) {
856         if (pp->pipe_id != 0) {
857           DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
858               "              Pipe Inx: %x  ID: 0x%02x  State: %u  "
859               "LocalGate: "
860               "0x%02x  Dest Gate: 0x%02x  Host: 0x%02x",
861               xx, pp->pipe_id, pp->pipe_state, pp->local_gate, pp->dest_gate,
862               pp->dest_host);
863         }
864       }
865       break;
866 
867     case NFA_HCI_DEBUG_SIM_HCI_EVENT:
868       p_msg = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
869       if (p_msg != nullptr) {
870         p = (uint8_t*)(p_msg + 1);
871 
872         p_msg->event = NFA_HCI_CHECK_QUEUE_EVT;
873         p_msg->len = size;
874         p_msg->offset = 0;
875 
876         memcpy(p, p_data, size);
877 
878         nfa_sys_sendmsg(p_msg);
879       }
880       break;
881 
882     case NFA_HCI_DEBUG_ENABLE_LOOPBACK:
883       DLOG_IF(INFO, nfc_debug_enabled)
884           << StringPrintf("NFA_HciDebug  HCI_LOOPBACK_DEBUG = TRUE");
885       HCI_LOOPBACK_DEBUG = NFA_HCI_DEBUG_ON;
886       break;
887 
888     case NFA_HCI_DEBUG_DISABLE_LOOPBACK:
889       DLOG_IF(INFO, nfc_debug_enabled)
890           << StringPrintf("NFA_HciDebug  HCI_LOOPBACK_DEBUG = FALSE");
891       HCI_LOOPBACK_DEBUG = NFA_HCI_DEBUG_OFF;
892       break;
893   }
894 }
895