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