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