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 == NULL) {
58 DLOG_IF(INFO, nfc_debug_enabled)
59 << StringPrintf("Invalid Application name");
60 return (NFA_STATUS_FAILED);
61 }
62
63 if (p_cback == NULL) {
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 != NULL) && (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))) != NULL)) {
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))) != NULL)) {
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 == NULL) {
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))) != NULL)) {
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))) != NULL)) {
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))) != NULL)) {
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))) != NULL)) {
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 uint8_t xx;
359
360 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
361 "hci_handle:0x%04x, source gate:0x%02X, "
362 "destination host:0x%02X , destination gate:0x%02X",
363 hci_handle, source_gate_id, dest_host, dest_gate);
364
365 if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
366 DLOG_IF(INFO, nfc_debug_enabled)
367 << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
368 return (NFA_STATUS_FAILED);
369 }
370
371 if ((source_gate_id < NFA_HCI_FIRST_HOST_SPECIFIC_GENERIC_GATE) ||
372 (source_gate_id > NFA_HCI_LAST_PROP_GATE)) {
373 DLOG_IF(INFO, nfc_debug_enabled)
374 << StringPrintf("Invalid local Gate:0x%02x", source_gate_id);
375 return (NFA_STATUS_FAILED);
376 }
377
378 if (((dest_gate < NFA_HCI_FIRST_HOST_SPECIFIC_GENERIC_GATE) &&
379 (dest_gate != NFA_HCI_LOOP_BACK_GATE) &&
380 (dest_gate != NFA_HCI_IDENTITY_MANAGEMENT_GATE)) ||
381 (dest_gate > NFA_HCI_LAST_PROP_GATE)) {
382 DLOG_IF(INFO, nfc_debug_enabled)
383 << StringPrintf("Invalid Destination Gate:0x%02x", dest_gate);
384 return (NFA_STATUS_FAILED);
385 }
386
387 for (xx = 0; xx < NFA_HCI_MAX_HOST_IN_NETWORK; xx++)
388 if (nfa_hci_cb.inactive_host[xx] == dest_host) break;
389
390 if (xx != NFA_HCI_MAX_HOST_IN_NETWORK) {
391 DLOG_IF(INFO, nfc_debug_enabled)
392 << StringPrintf("Host not active:0x%02x", dest_host);
393 return (NFA_STATUS_FAILED);
394 }
395
396 /* Request HCI to create a pipe between two specified gates */
397 if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
398 (!nfa_hci_cb.b_low_power_mode) &&
399 ((p_msg = (tNFA_HCI_API_CREATE_PIPE_EVT*)GKI_getbuf(
400 sizeof(tNFA_HCI_API_CREATE_PIPE_EVT))) != NULL)) {
401 p_msg->hdr.event = NFA_HCI_API_CREATE_PIPE_EVT;
402 p_msg->hci_handle = hci_handle;
403 p_msg->source_gate = source_gate_id;
404 p_msg->dest_host = dest_host; /* Host id of the destination host */
405 p_msg->dest_gate = dest_gate; /* Gate id of the destination gate */
406
407 nfa_sys_sendmsg(p_msg);
408 return (NFA_STATUS_OK);
409 }
410 return (NFA_STATUS_FAILED);
411 }
412
413 /*******************************************************************************
414 **
415 ** Function NFA_HciOpenPipe
416 **
417 ** Description This function is called to open a dynamic pipe.
418 ** When the dynamic pipe is opened (or
419 ** if an error occurs), the app will be notified with
420 ** NFA_HCI_OPEN_PIPE_EVT with the pipe id.
421 **
422 ** Returns NFA_STATUS_OK if successfully initiated
423 ** NFA_STATUS_FAILED otherwise
424 **
425 *******************************************************************************/
NFA_HciOpenPipe(tNFA_HANDLE hci_handle,uint8_t pipe)426 tNFA_STATUS NFA_HciOpenPipe(tNFA_HANDLE hci_handle, uint8_t pipe) {
427 tNFA_HCI_API_OPEN_PIPE_EVT* p_msg;
428
429 if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
430 DLOG_IF(INFO, nfc_debug_enabled)
431 << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
432 return (NFA_STATUS_FAILED);
433 }
434
435 if ((pipe < NFA_HCI_FIRST_DYNAMIC_PIPE) ||
436 (pipe > NFA_HCI_LAST_DYNAMIC_PIPE)) {
437 DLOG_IF(INFO, nfc_debug_enabled)
438 << StringPrintf("Invalid Pipe:0x%02x", pipe);
439 return (NFA_STATUS_FAILED);
440 }
441
442 DLOG_IF(INFO, nfc_debug_enabled)
443 << StringPrintf("hci_handle:0x%04x, pipe:0x%02X", hci_handle, pipe);
444
445 /* Request HCI to open a pipe if it is in closed state */
446 if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
447 (!nfa_hci_cb.b_low_power_mode) &&
448 ((p_msg = (tNFA_HCI_API_OPEN_PIPE_EVT*)GKI_getbuf(
449 sizeof(tNFA_HCI_API_OPEN_PIPE_EVT))) != NULL)) {
450 p_msg->hdr.event = NFA_HCI_API_OPEN_PIPE_EVT;
451 p_msg->hci_handle = hci_handle;
452 p_msg->pipe = pipe; /* Pipe ID of the pipe to open */
453
454 nfa_sys_sendmsg(p_msg);
455 return (NFA_STATUS_OK);
456 }
457 return (NFA_STATUS_FAILED);
458 }
459
460 /*******************************************************************************
461 **
462 ** Function NFA_HciGetRegistry
463 **
464 ** Description This function requests a peer host to return the desired
465 ** registry field value for the gate that the pipe is on.
466 **
467 ** When the peer host responds,the app is notified with
468 ** NFA_HCI_GET_REG_RSP_EVT or
469 ** if an error occurs in sending the command the app will be
470 ** notified by NFA_HCI_CMD_SENT_EVT
471 **
472 ** Returns NFA_STATUS_OK if successfully initiated
473 ** NFA_STATUS_FAILED otherwise
474 **
475 *******************************************************************************/
NFA_HciGetRegistry(tNFA_HANDLE hci_handle,uint8_t pipe,uint8_t reg_inx)476 tNFA_STATUS NFA_HciGetRegistry(tNFA_HANDLE hci_handle, uint8_t pipe,
477 uint8_t reg_inx) {
478 tNFA_HCI_API_GET_REGISTRY* p_msg;
479
480 if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
481 DLOG_IF(INFO, nfc_debug_enabled)
482 << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
483 return (NFA_STATUS_FAILED);
484 }
485
486 if (pipe < NFA_HCI_FIRST_DYNAMIC_PIPE) {
487 DLOG_IF(INFO, nfc_debug_enabled)
488 << StringPrintf("Invalid Pipe:0x%02x", pipe);
489 return (NFA_STATUS_FAILED);
490 }
491
492 DLOG_IF(INFO, nfc_debug_enabled)
493 << StringPrintf("hci_handle:0x%04x Pipe: 0x%02x", hci_handle, pipe);
494
495 /* Request HCI to get list of gates supported by the specified host */
496 if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
497 ((p_msg = (tNFA_HCI_API_GET_REGISTRY*)GKI_getbuf(
498 sizeof(tNFA_HCI_API_GET_REGISTRY))) != NULL)) {
499 p_msg->hdr.event = NFA_HCI_API_GET_REGISTRY_EVT;
500 p_msg->hci_handle = hci_handle;
501 p_msg->pipe = pipe;
502 p_msg->reg_inx = reg_inx;
503
504 nfa_sys_sendmsg(p_msg);
505 return (NFA_STATUS_OK);
506 }
507
508 return (NFA_STATUS_FAILED);
509 }
510
511 /*******************************************************************************
512 **
513 ** Function NFA_HciSendCommand
514 **
515 ** Description This function is called to send a command on a pipe created
516 ** by the application.
517 ** The app will be notified by NFA_HCI_CMD_SENT_EVT if an error
518 ** occurs.
519 ** When the peer host responds,the app is notified with
520 ** NFA_HCI_RSP_RCVD_EVT
521 **
522 ** Returns NFA_STATUS_OK if successfully initiated
523 ** NFA_STATUS_FAILED otherwise
524 **
525 *******************************************************************************/
NFA_HciSendCommand(tNFA_HANDLE hci_handle,uint8_t pipe,uint8_t cmd_code,uint16_t cmd_size,uint8_t * p_data)526 tNFA_STATUS NFA_HciSendCommand(tNFA_HANDLE hci_handle, uint8_t pipe,
527 uint8_t cmd_code, uint16_t cmd_size,
528 uint8_t* p_data) {
529 tNFA_HCI_API_SEND_CMD_EVT* p_msg;
530
531 if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
532 DLOG_IF(INFO, nfc_debug_enabled)
533 << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
534 return (NFA_STATUS_FAILED);
535 }
536
537 if (pipe < NFA_HCI_FIRST_DYNAMIC_PIPE) {
538 DLOG_IF(INFO, nfc_debug_enabled)
539 << StringPrintf("Invalid Pipe:0x%02x", pipe);
540 return (NFA_STATUS_FAILED);
541 }
542
543 if ((cmd_size && (p_data == NULL)) || (cmd_size > NFA_MAX_HCI_CMD_LEN)) {
544 DLOG_IF(INFO, nfc_debug_enabled)
545 << StringPrintf("Invalid cmd size:0x%02x", cmd_size);
546 return (NFA_STATUS_FAILED);
547 }
548
549 DLOG_IF(INFO, nfc_debug_enabled)
550 << StringPrintf("hci_handle:0x%04x, pipe:0x%02x Code: 0x%02x",
551 hci_handle, pipe, cmd_code);
552
553 /* Request HCI to post event data on a particular pipe */
554 if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
555 ((p_msg = (tNFA_HCI_API_SEND_CMD_EVT*)GKI_getbuf(
556 sizeof(tNFA_HCI_API_SEND_CMD_EVT))) != NULL)) {
557 p_msg->hdr.event = NFA_HCI_API_SEND_CMD_EVT;
558 p_msg->hci_handle = hci_handle;
559 p_msg->pipe = pipe;
560 p_msg->cmd_code = cmd_code;
561 p_msg->cmd_len = cmd_size;
562
563 if (cmd_size) memcpy(p_msg->data, p_data, cmd_size);
564
565 nfa_sys_sendmsg(p_msg);
566 return (NFA_STATUS_OK);
567 }
568
569 return (NFA_STATUS_FAILED);
570 }
571
572 /*******************************************************************************
573 **
574 ** Function NFA_HciSendEvent
575 **
576 ** Description This function is called to send any event on a pipe created
577 ** by the application.
578 ** The app will be notified by NFA_HCI_EVENT_SENT_EVT
579 ** after successfully sending the event on the specified pipe
580 ** or if an error occurs. The application should wait for this
581 ** event before releasing event buffer passed as argument.
582 ** If the app is expecting a response to the event then it can
583 ** provide response buffer for collecting the response. If it
584 ** provides a response buffer it can also provide response
585 ** timeout indicating maximum timeout for the response.
586 ** Maximum of NFA_MAX_HCI_EVENT_LEN bytes APDU can be received
587 ** using internal buffer if no response buffer is provided by
588 ** the application. The app will be notified by
589 ** NFA_HCI_EVENT_RCVD_EVT after receiving the response event
590 ** or on timeout if app provided response buffer and response
591 ** timeout. If response buffer and response timeout is provided
592 ** by the application, it should wait for this event before
593 ** releasing the response buffer. If the application did not
594 ** provide response timeout then it should not release the
595 ** response buffer until it receives NFA_HCI_EVENT_RCVD_EVT or
596 ** after timeout it sends next event on the same pipe
597 ** and receives NFA_HCI_EVENT_SENT_EVT for that event.
598 **
599 ** Returns NFA_STATUS_OK if successfully initiated
600 ** NFA_STATUS_FAILED otherwise
601 **
602 *******************************************************************************/
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)603 tNFA_STATUS NFA_HciSendEvent(tNFA_HANDLE hci_handle, uint8_t pipe,
604 uint8_t evt_code, uint16_t evt_size,
605 uint8_t* p_data, uint16_t rsp_size,
606 uint8_t* p_rsp_buf, uint16_t rsp_timeout) {
607 tNFA_HCI_API_SEND_EVENT_EVT* p_msg;
608
609 DLOG_IF(INFO, nfc_debug_enabled)
610 << StringPrintf("hci_handle:0x%04x, pipe:0x%02x Code: 0x%02x",
611 hci_handle, pipe, evt_code);
612
613 if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
614 DLOG_IF(INFO, nfc_debug_enabled)
615 << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
616 return (NFA_STATUS_FAILED);
617 }
618
619 if (pipe < NFA_HCI_FIRST_DYNAMIC_PIPE) {
620 DLOG_IF(INFO, nfc_debug_enabled)
621 << StringPrintf("Invalid Pipe:0x%02x", pipe);
622 return (NFA_STATUS_FAILED);
623 }
624
625 if (evt_size && (p_data == NULL)) {
626 DLOG_IF(INFO, nfc_debug_enabled)
627 << StringPrintf("Invalid Event size:0x%02x", evt_size);
628 return (NFA_STATUS_FAILED);
629 }
630
631 if (rsp_size && (p_rsp_buf == NULL)) {
632 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
633 "No Event buffer, but invalid event buffer size "
634 ":%u",
635 rsp_size);
636 return (NFA_STATUS_FAILED);
637 }
638
639 /* Request HCI to post event data on a particular pipe */
640 if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
641 ((p_msg = (tNFA_HCI_API_SEND_EVENT_EVT*)GKI_getbuf(
642 sizeof(tNFA_HCI_API_SEND_EVENT_EVT))) != NULL)) {
643 p_msg->hdr.event = NFA_HCI_API_SEND_EVENT_EVT;
644 p_msg->hci_handle = hci_handle;
645 p_msg->pipe = pipe;
646 p_msg->evt_code = evt_code;
647 p_msg->evt_len = evt_size;
648 p_msg->p_evt_buf = p_data;
649 p_msg->rsp_len = rsp_size;
650 p_msg->p_rsp_buf = p_rsp_buf;
651 p_msg->rsp_timeout = rsp_timeout;
652
653 nfa_sys_sendmsg(p_msg);
654 return (NFA_STATUS_OK);
655 }
656
657 return (NFA_STATUS_FAILED);
658 }
659
660 /*******************************************************************************
661 **
662 ** Function NFA_HciClosePipe
663 **
664 ** Description This function is called to close a dynamic pipe.
665 ** When the dynamic pipe is closed (or
666 ** if an error occurs), the app will be notified with
667 ** NFA_HCI_CLOSE_PIPE_EVT with the pipe id.
668 **
669 ** Returns NFA_STATUS_OK if successfully initiated
670 ** NFA_STATUS_FAILED otherwise
671 **
672 *******************************************************************************/
NFA_HciClosePipe(tNFA_HANDLE hci_handle,uint8_t pipe)673 tNFA_STATUS NFA_HciClosePipe(tNFA_HANDLE hci_handle, uint8_t pipe) {
674 tNFA_HCI_API_CLOSE_PIPE_EVT* p_msg;
675
676 DLOG_IF(INFO, nfc_debug_enabled)
677 << StringPrintf("hci_handle:0x%04x, pipe:0x%02X", hci_handle, pipe);
678
679 if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
680 DLOG_IF(INFO, nfc_debug_enabled)
681 << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
682 return (NFA_STATUS_FAILED);
683 }
684
685 if ((pipe < NFA_HCI_FIRST_DYNAMIC_PIPE) ||
686 (pipe > NFA_HCI_LAST_DYNAMIC_PIPE)) {
687 DLOG_IF(INFO, nfc_debug_enabled)
688 << StringPrintf("Invalid Pipe:0x%02x", pipe);
689 return (NFA_STATUS_FAILED);
690 }
691
692 /* Request HCI to close a pipe if it is in opened state */
693 if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
694 (!nfa_hci_cb.b_low_power_mode) &&
695 ((p_msg = (tNFA_HCI_API_CLOSE_PIPE_EVT*)GKI_getbuf(
696 sizeof(tNFA_HCI_API_CLOSE_PIPE_EVT))) != NULL)) {
697 p_msg->hdr.event = NFA_HCI_API_CLOSE_PIPE_EVT;
698 p_msg->hci_handle = hci_handle;
699 p_msg->pipe = pipe;
700
701 nfa_sys_sendmsg(p_msg);
702 return (NFA_STATUS_OK);
703 }
704 return (NFA_STATUS_FAILED);
705 }
706
707 /*******************************************************************************
708 **
709 ** Function NFA_HciDeletePipe
710 **
711 ** Description This function is called to delete a particular dynamic pipe.
712 ** When the dynamic pipe is deleted (or if an error occurs),
713 ** the app will be notified with NFA_HCI_DELETE_PIPE_EVT with
714 ** the pipe id. After successful deletion of pipe, registry
715 ** entry will be deleted for the dynamic pipe and all
716 ** information related to the pipe will be deleted from non
717 ** volatile memory.
718 **
719 ** Returns NFA_STATUS_OK if successfully initiated
720 ** NFA_STATUS_FAILED otherwise
721 **
722 *******************************************************************************/
NFA_HciDeletePipe(tNFA_HANDLE hci_handle,uint8_t pipe)723 tNFA_STATUS NFA_HciDeletePipe(tNFA_HANDLE hci_handle, uint8_t pipe) {
724 tNFA_HCI_API_DELETE_PIPE_EVT* p_msg;
725
726 if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
727 DLOG_IF(INFO, nfc_debug_enabled)
728 << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
729 return (NFA_STATUS_FAILED);
730 }
731
732 if ((pipe < NFA_HCI_FIRST_DYNAMIC_PIPE) ||
733 (pipe > NFA_HCI_LAST_DYNAMIC_PIPE)) {
734 DLOG_IF(INFO, nfc_debug_enabled)
735 << StringPrintf("Invalid Pipe:0x%02x", pipe);
736 return (NFA_STATUS_FAILED);
737 }
738
739 DLOG_IF(INFO, nfc_debug_enabled)
740 << StringPrintf("hci_handle:0x%04x, pipe:0x%02X", hci_handle, pipe);
741
742 /* Request HCI to delete a pipe created by the application identified by hci
743 * handle */
744 if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
745 (!nfa_hci_cb.b_low_power_mode) &&
746 ((p_msg = (tNFA_HCI_API_DELETE_PIPE_EVT*)GKI_getbuf(
747 sizeof(tNFA_HCI_API_DELETE_PIPE_EVT))) != NULL)) {
748 p_msg->hdr.event = NFA_HCI_API_DELETE_PIPE_EVT;
749 p_msg->hci_handle = hci_handle;
750 p_msg->pipe = pipe;
751
752 nfa_sys_sendmsg(p_msg);
753 return (NFA_STATUS_OK);
754 }
755 return (NFA_STATUS_FAILED);
756 }
757
758 /*******************************************************************************
759 **
760 ** Function NFA_HciAddStaticPipe
761 **
762 ** Description This function is called to add a static pipe for sending
763 ** 7816 APDUs. When the static pipe is added (or if an error
764 ** occurs), the app will be notified with
765 ** NFA_HCI_ADD_STATIC_PIPE_EVT with the status.
766 **
767 ** Returns NFA_STATUS_OK if successfully initiated
768 ** NFA_STATUS_FAILED otherwise
769 **
770 *******************************************************************************/
NFA_HciAddStaticPipe(tNFA_HANDLE hci_handle,uint8_t host,uint8_t gate,uint8_t pipe)771 tNFA_STATUS NFA_HciAddStaticPipe(tNFA_HANDLE hci_handle, uint8_t host,
772 uint8_t gate, uint8_t pipe) {
773 tNFA_HCI_API_ADD_STATIC_PIPE_EVT* p_msg;
774 uint8_t xx;
775
776 if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
777 DLOG_IF(INFO, nfc_debug_enabled)
778 << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
779 return (NFA_STATUS_FAILED);
780 }
781
782 for (xx = 0; xx < NFA_HCI_MAX_HOST_IN_NETWORK; xx++)
783 if (nfa_hci_cb.inactive_host[xx] == host) break;
784
785 if (xx != NFA_HCI_MAX_HOST_IN_NETWORK) {
786 DLOG_IF(INFO, nfc_debug_enabled)
787 << StringPrintf("Host not active:0x%02x", host);
788 return (NFA_STATUS_FAILED);
789 }
790
791 if (gate <= NFA_HCI_LAST_HOST_SPECIFIC_GATE) {
792 DLOG_IF(INFO, nfc_debug_enabled)
793 << StringPrintf("Invalid Gate:0x%02x", gate);
794 return (NFA_STATUS_FAILED);
795 }
796
797 if (pipe <= NFA_HCI_LAST_DYNAMIC_PIPE) {
798 DLOG_IF(INFO, nfc_debug_enabled)
799 << StringPrintf("Invalid Pipe:0x%02x", pipe);
800 return (NFA_STATUS_FAILED);
801 }
802
803 DLOG_IF(INFO, nfc_debug_enabled)
804 << StringPrintf("hci_handle:0x%04x, pipe:0x%02X", hci_handle, pipe);
805
806 /* Request HCI to delete a pipe created by the application identified by hci
807 * handle */
808 if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
809 ((p_msg = (tNFA_HCI_API_ADD_STATIC_PIPE_EVT*)GKI_getbuf(
810 sizeof(tNFA_HCI_API_ADD_STATIC_PIPE_EVT))) != NULL)) {
811 p_msg->hdr.event = NFA_HCI_API_ADD_STATIC_PIPE_EVT;
812 p_msg->hci_handle = hci_handle;
813 p_msg->host = host;
814 p_msg->gate = gate;
815 p_msg->pipe = pipe;
816
817 nfa_sys_sendmsg(p_msg);
818 return (NFA_STATUS_OK);
819 }
820 /* Unable to add static pipe */
821 return (NFA_STATUS_FAILED);
822 }
823
824 /*******************************************************************************
825 **
826 ** Function NFA_HciDebug
827 **
828 ** Description Debug function.
829 **
830 *******************************************************************************/
NFA_HciDebug(uint8_t action,uint8_t size,uint8_t * p_data)831 void NFA_HciDebug(uint8_t action, uint8_t size, uint8_t* p_data) {
832 int xx;
833 tNFA_HCI_DYN_GATE* pg = nfa_hci_cb.cfg.dyn_gates;
834 tNFA_HCI_DYN_PIPE* pp = nfa_hci_cb.cfg.dyn_pipes;
835 NFC_HDR* p_msg;
836 uint8_t* p;
837
838 switch (action) {
839 case NFA_HCI_DEBUG_DISPLAY_CB:
840 DLOG_IF(INFO, nfc_debug_enabled)
841 << StringPrintf("NFA_HciDebug Host List:");
842 for (xx = 0; xx < NFA_HCI_MAX_APP_CB; xx++) {
843 if (nfa_hci_cb.cfg.reg_app_names[xx][0] != 0) {
844 DLOG_IF(INFO, nfc_debug_enabled)
845 << StringPrintf(" Host Inx: %u Name: %s", xx,
846 &nfa_hci_cb.cfg.reg_app_names[xx][0]);
847 }
848 }
849
850 DLOG_IF(INFO, nfc_debug_enabled)
851 << StringPrintf("NFA_HciDebug Gate List:");
852 for (xx = 0; xx < NFA_HCI_MAX_GATE_CB; xx++, pg++) {
853 if (pg->gate_id != 0) {
854 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
855 " Gate Inx: %x ID: 0x%02x Owner: 0x%04x "
856 "PipeInxMask: 0x%08x",
857 xx, pg->gate_id, pg->gate_owner, pg->pipe_inx_mask);
858 }
859 }
860
861 DLOG_IF(INFO, nfc_debug_enabled)
862 << StringPrintf("NFA_HciDebug Pipe List:");
863 for (xx = 0; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++) {
864 if (pp->pipe_id != 0) {
865 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
866 " Pipe Inx: %x ID: 0x%02x State: %u "
867 "LocalGate: "
868 "0x%02x Dest Gate: 0x%02x Host: 0x%02x",
869 xx, pp->pipe_id, pp->pipe_state, pp->local_gate, pp->dest_gate,
870 pp->dest_host);
871 }
872 }
873 break;
874
875 case NFA_HCI_DEBUG_SIM_HCI_EVENT:
876 p_msg = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
877 if (p_msg != NULL) {
878 p = (uint8_t*)(p_msg + 1);
879
880 p_msg->event = NFA_HCI_CHECK_QUEUE_EVT;
881 p_msg->len = size;
882 p_msg->offset = 0;
883
884 memcpy(p, p_data, size);
885
886 nfa_sys_sendmsg(p_msg);
887 }
888 break;
889
890 case NFA_HCI_DEBUG_ENABLE_LOOPBACK:
891 DLOG_IF(INFO, nfc_debug_enabled)
892 << StringPrintf("NFA_HciDebug HCI_LOOPBACK_DEBUG = TRUE");
893 HCI_LOOPBACK_DEBUG = NFA_HCI_DEBUG_ON;
894 break;
895
896 case NFA_HCI_DEBUG_DISABLE_LOOPBACK:
897 DLOG_IF(INFO, nfc_debug_enabled)
898 << StringPrintf("NFA_HciDebug HCI_LOOPBACK_DEBUG = FALSE");
899 HCI_LOOPBACK_DEBUG = NFA_HCI_DEBUG_OFF;
900 break;
901 }
902 }
903