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