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