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