1 /****************************************************************************** 2 * 3 * Copyright (C) 2010-2012 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 * Functions for handling NFC HAL NCI Transport events 22 * 23 ******************************************************************************/ 24 #include <string.h> 25 #include "nfc_hal_int.h" 26 #include "userial.h" 27 #include "upio.h" 28 29 /**************************************************************************** 30 ** Definitions 31 ****************************************************************************/ 32 33 /* Default NFC HAL NCI port configuration */ 34 NFC_HAL_TRANS_CFG_QUALIFIER tNFC_HAL_TRANS_CFG nfc_hal_trans_cfg = 35 { 36 NFC_HAL_SHARED_TRANSPORT_ENABLED, /* bSharedTransport */ 37 USERIAL_BAUD_115200, /* Baud rate */ 38 USERIAL_FC_HW /* Flow control */ 39 }; 40 41 /* Control block for NFC HAL NCI transport */ 42 #if NFC_DYNAMIC_MEMORY == FALSE 43 tNFC_HAL_CB nfc_hal_cb; 44 #endif 45 46 /**************************************************************************** 47 ** Internal function prototypes 48 ****************************************************************************/ 49 static void nfc_hal_main_userial_cback (tUSERIAL_PORT port, tUSERIAL_EVT evt, tUSERIAL_EVT_DATA *p_data); 50 static void nfc_hal_main_handle_terminate (void); 51 52 53 #if (NFC_HAL_DEBUG == TRUE) 54 const char * const nfc_hal_init_state_str[] = 55 { 56 "IDLE", /* Initialization is done */ 57 "W4_XTAL_SET", /* Waiting for crystal setting rsp */ 58 "W4_RESET", /* Waiting for reset rsp */ 59 "W4_BUILD_INFO", /* Waiting for build info rsp */ 60 "W4_PATCH_INFO", /* Waiting for patch info rsp */ 61 "W4_APP_COMPL", /* Waiting for complete from application */ 62 "W4_POST_INIT", /* Waiting for complete of post init */ 63 "W4_CONTROL", /* Waiting for control release */ 64 "W4_PREDISC", /* Waiting for complete of prediscover */ 65 "W4_RE_INIT", /* Waiting for reset rsp on ReInit */ 66 "CLOSING" /* Shutting down */ 67 }; 68 #endif 69 70 /******************************************************************************* 71 ** 72 ** Function nfc_hal_main_init 73 ** 74 ** Description This function initializes control block for NFC HAL 75 ** 76 ** Returns nothing 77 ** 78 *******************************************************************************/ 79 void nfc_hal_main_init (void) 80 { 81 /* Clear control block */ 82 memset (&nfc_hal_cb, 0, sizeof (tNFC_HAL_CB)); 83 84 nfc_hal_cb.ncit_cb.nci_ctrl_size = NFC_HAL_NCI_INIT_CTRL_PAYLOAD_SIZE; 85 nfc_hal_cb.trace_level = NFC_HAL_INITIAL_TRACE_LEVEL; 86 } 87 88 /******************************************************************************* 89 ** 90 ** Function nfc_hal_main_open_transport 91 ** 92 ** Description Open transport and prepare for new incoming message; 93 ** 94 ** Returns nothing 95 ** 96 *******************************************************************************/ 97 static void nfc_hal_main_open_transport (void) 98 { 99 tUSERIAL_OPEN_CFG open_cfg; 100 101 /* Initialize control block */ 102 nfc_hal_cb.ncit_cb.rcv_state = NFC_HAL_RCV_IDLE_ST; /* to process packet type */ 103 104 if (nfc_hal_cb.ncit_cb.p_rcv_msg) 105 { 106 GKI_freebuf (nfc_hal_cb.ncit_cb.p_rcv_msg); 107 nfc_hal_cb.ncit_cb.p_rcv_msg = NULL; 108 } 109 110 /* open transport */ 111 open_cfg.fmt = (USERIAL_DATABITS_8 | USERIAL_PARITY_NONE | USERIAL_STOPBITS_1); 112 open_cfg.baud = nfc_hal_trans_cfg.userial_baud; 113 open_cfg.fc = nfc_hal_trans_cfg.userial_fc; 114 open_cfg.buf = USERIAL_BUF_BYTE; 115 116 USERIAL_Open (USERIAL_NFC_PORT, &open_cfg, nfc_hal_main_userial_cback); 117 118 /* notify transport openned */ 119 nfc_hal_dm_pre_init_nfcc (); 120 } 121 122 /******************************************************************************* 123 ** 124 ** Function nfc_hal_main_send_error 125 ** 126 ** Description send an Error event to NFC stack 127 ** 128 ** Returns nothing 129 ** 130 *******************************************************************************/ 131 void nfc_hal_main_send_error (tHAL_NFC_STATUS status) 132 { 133 /* Notify stack */ 134 nfc_hal_cb.p_stack_cback(HAL_NFC_ERROR_EVT, status); 135 } 136 137 /******************************************************************************* 138 ** 139 ** Function nfc_hal_main_userial_cback 140 ** 141 ** Description USERIAL callback for NCI transport 142 ** 143 ** Returns nothing 144 ** 145 *******************************************************************************/ 146 static void nfc_hal_main_userial_cback (tUSERIAL_PORT port, tUSERIAL_EVT evt, tUSERIAL_EVT_DATA *p_data) 147 { 148 if (evt == USERIAL_RX_READY_EVT) 149 { 150 /* Notify transport task of serial port event */ 151 GKI_send_event (NFC_HAL_TASK, NFC_HAL_TASK_EVT_DATA_RDY); 152 } 153 else if (evt == USERIAL_TX_DONE_EVT) 154 { 155 /* Serial driver has finshed sending data from USERIAL_Write */ 156 /* Currently, no action is needed for this event */ 157 } 158 else if (evt == USERIAL_ERR_EVT) 159 { 160 NCI_TRACE_ERROR0 ("nfc_hal_main_userial_cback: USERIAL_ERR_EVT. Notifying NFC_TASK of transport error"); 161 if (nfc_hal_cb.ncit_cb.nci_wait_rsp != NFC_HAL_WAIT_RSP_NONE) 162 { 163 nfc_hal_main_stop_quick_timer (&nfc_hal_cb.ncit_cb.nci_wait_rsp_timer); 164 nfc_hal_nci_cmd_timeout_cback ((void *)&nfc_hal_cb.ncit_cb.nci_wait_rsp_timer); 165 } 166 else 167 { 168 nfc_hal_main_send_error (HAL_NFC_STATUS_ERR_TRANSPORT); 169 } 170 } 171 else if (evt == USERIAL_WAKEUP_EVT) 172 { 173 NCI_TRACE_DEBUG1 ("nfc_hal_main_userial_cback: USERIAL_WAKEUP_EVT: %d", p_data->sigs); 174 } 175 else 176 { 177 NCI_TRACE_DEBUG1 ("nfc_hal_main_userial_cback: unhandled userial evt: %i", evt); 178 } 179 } 180 181 /******************************************************************************* 182 ** 183 ** Function nfc_hal_main_pre_init_done 184 ** 185 ** Description notify complete of pre-initialization 186 ** 187 ** Returns nothing 188 ** 189 *******************************************************************************/ 190 void nfc_hal_main_pre_init_done (tHAL_NFC_STATUS status) 191 { 192 NCI_TRACE_DEBUG1 ("nfc_hal_main_pre_init_done () status = %d", status); 193 194 if (status != HAL_NFC_STATUS_OK) 195 { 196 nfc_hal_main_handle_terminate (); 197 198 /* Close uart */ 199 USERIAL_Close (USERIAL_NFC_PORT); 200 } 201 202 /* Notify NFC Task the status of initialization */ 203 nfc_hal_cb.p_stack_cback (HAL_NFC_OPEN_CPLT_EVT, status); 204 } 205 206 /******************************************************************************* 207 ** 208 ** Function nfc_hal_main_timeout_cback 209 ** 210 ** Description callback function for timeout 211 ** 212 ** Returns void 213 ** 214 *******************************************************************************/ 215 static void nfc_hal_main_timeout_cback (void *p_tle) 216 { 217 TIMER_LIST_ENT *p_tlent = (TIMER_LIST_ENT *) p_tle; 218 219 NCI_TRACE_DEBUG0 ("nfc_hal_main_timeout_cback ()"); 220 221 switch (p_tlent->event) 222 { 223 case NFC_HAL_TTYPE_POWER_CYCLE: 224 nfc_hal_main_open_transport (); 225 break; 226 227 default: 228 NCI_TRACE_DEBUG1 ("nfc_hal_main_timeout_cback: unhandled timer event (0x%04x)", p_tlent->event); 229 break; 230 } 231 } 232 233 /******************************************************************************* 234 ** 235 ** Function nfc_hal_main_handle_terminate 236 ** 237 ** Description Handle NFI transport shutdown 238 ** 239 ** Returns nothing 240 ** 241 *******************************************************************************/ 242 static void nfc_hal_main_handle_terminate (void) 243 { 244 NFC_HDR *p_msg; 245 246 /* dequeue and free buffer */ 247 if (nfc_hal_cb.ncit_cb.p_pend_cmd != NULL) 248 { 249 GKI_freebuf (nfc_hal_cb.ncit_cb.p_pend_cmd); 250 nfc_hal_cb.ncit_cb.p_pend_cmd = NULL; 251 } 252 253 /* Free unsent nfc rx buffer */ 254 if (nfc_hal_cb.ncit_cb.p_rcv_msg) 255 { 256 GKI_freebuf (nfc_hal_cb.ncit_cb.p_rcv_msg); 257 nfc_hal_cb.ncit_cb.p_rcv_msg = NULL; 258 } 259 260 /* Free buffer for pending fragmented response/notification */ 261 if (nfc_hal_cb.ncit_cb.p_frag_msg) 262 { 263 GKI_freebuf (nfc_hal_cb.ncit_cb.p_frag_msg); 264 nfc_hal_cb.ncit_cb.p_frag_msg = NULL; 265 } 266 267 /* Free buffers in the tx mbox */ 268 while ((p_msg = (NFC_HDR *) GKI_read_mbox (NFC_HAL_TASK_MBOX)) != NULL) 269 { 270 GKI_freebuf (p_msg); 271 } 272 273 /* notify closing transport */ 274 nfc_hal_dm_shutting_down_nfcc (); 275 } 276 277 /******************************************************************************* 278 ** 279 ** Function nfc_hal_main_start_quick_timer 280 ** 281 ** Description Start a timer for the specified amount of time. 282 ** NOTE: The timeout resolution depends on including modules. 283 ** QUICK_TIMER_TICKS_PER_SEC should be used to convert from 284 ** time to ticks. 285 ** 286 ** 287 ** Returns void 288 ** 289 *******************************************************************************/ 290 void nfc_hal_main_start_quick_timer (TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout) 291 { 292 NFC_HDR *p_msg; 293 294 /* if timer list is currently empty, start periodic GKI timer */ 295 if (nfc_hal_cb.quick_timer_queue.p_first == NULL) 296 { 297 /* if timer starts on other than NCIT task (script wrapper) */ 298 if(GKI_get_taskid () != NFC_HAL_TASK) 299 { 300 /* post event to start timer in NCIT task */ 301 if ((p_msg = (NFC_HDR *) GKI_getbuf (NFC_HDR_SIZE)) != NULL) 302 { 303 p_msg->event = NFC_HAL_EVT_TO_START_QUICK_TIMER; 304 GKI_send_msg (NFC_HAL_TASK, NFC_HAL_TASK_MBOX, p_msg); 305 } 306 } 307 else 308 { 309 GKI_start_timer (NFC_HAL_QUICK_TIMER_ID, ((GKI_SECS_TO_TICKS (1) / QUICK_TIMER_TICKS_PER_SEC)), TRUE); 310 } 311 } 312 313 GKI_remove_from_timer_list (&nfc_hal_cb.quick_timer_queue, p_tle); 314 315 p_tle->event = type; 316 p_tle->ticks = timeout; /* Save the number of ticks for the timer */ 317 318 GKI_add_to_timer_list (&nfc_hal_cb.quick_timer_queue, p_tle); 319 } 320 321 /******************************************************************************* 322 ** 323 ** Function nfc_hal_main_stop_quick_timer 324 ** 325 ** Description Stop a timer. 326 ** 327 ** Returns void 328 ** 329 *******************************************************************************/ 330 void nfc_hal_main_stop_quick_timer (TIMER_LIST_ENT *p_tle) 331 { 332 GKI_remove_from_timer_list (&nfc_hal_cb.quick_timer_queue, p_tle); 333 334 /* if timer list is empty stop periodic GKI timer */ 335 if (nfc_hal_cb.quick_timer_queue.p_first == NULL) 336 { 337 GKI_stop_timer (NFC_HAL_QUICK_TIMER_ID); 338 } 339 } 340 341 /******************************************************************************* 342 ** 343 ** Function nfc_hal_main_process_quick_timer_evt 344 ** 345 ** Description Process quick timer event 346 ** 347 ** Returns void 348 ** 349 *******************************************************************************/ 350 static void nfc_hal_main_process_quick_timer_evt (void) 351 { 352 TIMER_LIST_ENT *p_tle; 353 354 GKI_update_timer_list (&nfc_hal_cb.quick_timer_queue, 1); 355 356 while ((nfc_hal_cb.quick_timer_queue.p_first) && (!nfc_hal_cb.quick_timer_queue.p_first->ticks)) 357 { 358 p_tle = nfc_hal_cb.quick_timer_queue.p_first; 359 GKI_remove_from_timer_list (&nfc_hal_cb.quick_timer_queue, p_tle); 360 361 if (p_tle->p_cback) 362 { 363 (*p_tle->p_cback) (p_tle); 364 } 365 } 366 367 /* if timer list is empty stop periodic GKI timer */ 368 if (nfc_hal_cb.quick_timer_queue.p_first == NULL) 369 { 370 GKI_stop_timer (NFC_HAL_QUICK_TIMER_ID); 371 } 372 } 373 374 /******************************************************************************* 375 ** 376 ** Function nfc_hal_main_send_message 377 ** 378 ** Description This function is calledto send an NCI message. 379 ** 380 ** Returns void 381 ** 382 *******************************************************************************/ 383 static void nfc_hal_main_send_message (NFC_HDR *p_msg) 384 { 385 UINT8 *ps; 386 UINT16 len = p_msg->len; 387 #ifdef DISP_NCI 388 UINT8 delta; 389 #endif 390 391 NCI_TRACE_DEBUG1 ("nfc_hal_main_send_message() ls:0x%x", p_msg->layer_specific); 392 if ( (p_msg->layer_specific == NFC_HAL_WAIT_RSP_CMD) 393 ||(p_msg->layer_specific == NFC_HAL_WAIT_RSP_VSC) ) 394 { 395 nfc_hal_nci_send_cmd (p_msg); 396 } 397 else 398 { 399 /* NFC task has fragmented the data packet to the appropriate size 400 * and data credit is available; just send it */ 401 402 /* add NCI packet type in front of message */ 403 nfc_hal_nci_add_nfc_pkt_type (p_msg); 404 405 /* send this packet to transport */ 406 ps = (UINT8 *) (p_msg + 1) + p_msg->offset; 407 #ifdef DISP_NCI 408 delta = p_msg->len - len; 409 DISP_NCI (ps + delta, (UINT16) (p_msg->len - delta), FALSE); 410 #endif 411 USERIAL_Write (USERIAL_NFC_PORT, ps, p_msg->len); 412 GKI_freebuf (p_msg); 413 } 414 } 415 416 /******************************************************************************* 417 ** 418 ** Function nfc_hal_main_task 419 ** 420 ** Description NFC HAL NCI transport event processing task 421 ** 422 ** Returns 0 423 ** 424 *******************************************************************************/ 425 UINT32 nfc_hal_main_task (UINT32 param) 426 { 427 UINT16 event; 428 UINT8 byte; 429 UINT8 num_interfaces; 430 UINT8 *p; 431 NFC_HDR *p_msg; 432 BOOLEAN free_msg; 433 434 NCI_TRACE_DEBUG0 ("NFC_HAL_TASK started"); 435 436 /* Main loop */ 437 while (TRUE) 438 { 439 event = GKI_wait (0xFFFF, 0); 440 441 /* Handle NFC_HAL_TASK_EVT_INITIALIZE (for initializing NCI transport) */ 442 if (event & NFC_HAL_TASK_EVT_INITIALIZE) 443 { 444 NCI_TRACE_DEBUG0 ("NFC_HAL_TASK got NFC_HAL_TASK_EVT_INITIALIZE signal. Opening NFC transport..."); 445 446 nfc_hal_main_open_transport (); 447 } 448 449 /* Check for terminate event */ 450 if (event & NFC_HAL_TASK_EVT_TERMINATE) 451 { 452 NCI_TRACE_DEBUG0 ("NFC_HAL_TASK got NFC_HAL_TASK_EVT_TERMINATE"); 453 nfc_hal_main_handle_terminate (); 454 455 /* Close uart */ 456 USERIAL_Close (USERIAL_NFC_PORT); 457 458 nfc_hal_cb.p_stack_cback (HAL_NFC_CLOSE_CPLT_EVT, HAL_NFC_STATUS_OK); 459 nfc_hal_cb.p_stack_cback = NULL; 460 continue; 461 } 462 463 /* Check for power cycle event */ 464 if (event & NFC_HAL_TASK_EVT_POWER_CYCLE) 465 { 466 NCI_TRACE_DEBUG0 ("NFC_HAL_TASK got NFC_HAL_TASK_EVT_POWER_CYCLE"); 467 nfc_hal_main_handle_terminate (); 468 469 /* Close uart */ 470 USERIAL_Close (USERIAL_NFC_PORT); 471 472 /* power cycle timeout */ 473 nfc_hal_cb.timer.p_cback = nfc_hal_main_timeout_cback; 474 nfc_hal_main_start_quick_timer (&nfc_hal_cb.timer, NFC_HAL_TTYPE_POWER_CYCLE, 475 (NFC_HAL_POWER_CYCLE_DELAY*QUICK_TIMER_TICKS_PER_SEC)/1000); 476 continue; 477 } 478 479 /* NCI message ready to be sent to NFCC */ 480 if (event & NFC_HAL_TASK_EVT_MBOX) 481 { 482 while ((p_msg = (NFC_HDR *) GKI_read_mbox (NFC_HAL_TASK_MBOX)) != NULL) 483 { 484 free_msg = TRUE; 485 switch (p_msg->event & NFC_EVT_MASK) 486 { 487 case NFC_HAL_EVT_TO_NFC_NCI: 488 nfc_hal_main_send_message (p_msg); 489 /* do not free buffer. NCI VS code may keep it for processing later */ 490 free_msg = FALSE; 491 break; 492 493 case NFC_HAL_EVT_POST_CORE_RESET: 494 NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_W4_POST_INIT_DONE); 495 496 /* set NCI Control packet size from CORE_INIT_RSP */ 497 p = (UINT8 *) (p_msg + 1) + p_msg->offset + NCI_MSG_HDR_SIZE; 498 p += 5; 499 STREAM_TO_UINT8 (num_interfaces, p); 500 p += (num_interfaces + 3); 501 nfc_hal_cb.ncit_cb.nci_ctrl_size = *p; 502 503 /* start post initialization */ 504 nfc_hal_cb.dev_cb.next_dm_config = NFC_HAL_DM_CONFIG_LPTD; 505 nfc_hal_cb.dev_cb.next_startup_vsc = 1; 506 507 nfc_hal_dm_config_nfcc (); 508 break; 509 510 case NFC_HAL_EVT_TO_START_QUICK_TIMER: 511 GKI_start_timer (NFC_HAL_QUICK_TIMER_ID, ((GKI_SECS_TO_TICKS (1) / QUICK_TIMER_TICKS_PER_SEC)), TRUE); 512 break; 513 514 case NFC_HAL_EVT_HCI: 515 nfc_hal_hci_evt_hdlr ((tNFC_HAL_HCI_EVENT_DATA *) p_msg); 516 break; 517 518 519 case NFC_HAL_EVT_CONTROL_GRANTED: 520 nfc_hal_dm_send_pend_cmd (); 521 break; 522 523 default: 524 break; 525 } 526 527 if (free_msg) 528 GKI_freebuf (p_msg); 529 } 530 } 531 532 /* Data waiting to be read from serial port */ 533 if (event & NFC_HAL_TASK_EVT_DATA_RDY) 534 { 535 while (TRUE) 536 { 537 /* Read one byte to see if there is anything waiting to be read */ 538 if (USERIAL_Read (USERIAL_NFC_PORT, &byte, 1) == 0) 539 { 540 break; 541 } 542 543 if (nfc_hal_nci_receive_msg (byte)) 544 { 545 /* complete of receiving NCI message */ 546 nfc_hal_nci_assemble_nci_msg (); 547 if (nfc_hal_cb.ncit_cb.p_rcv_msg) 548 { 549 if (nfc_hal_nci_preproc_rx_nci_msg (nfc_hal_cb.ncit_cb.p_rcv_msg)) 550 { 551 /* Send NCI message to the stack */ 552 nfc_hal_cb.p_data_cback(nfc_hal_cb.ncit_cb.p_rcv_msg->len, (UINT8 *)((nfc_hal_cb.ncit_cb.p_rcv_msg + 1) 553 + nfc_hal_cb.ncit_cb.p_rcv_msg->offset)); 554 555 } 556 } 557 558 if (nfc_hal_cb.ncit_cb.p_rcv_msg) 559 { 560 GKI_freebuf(nfc_hal_cb.ncit_cb.p_rcv_msg); 561 nfc_hal_cb.ncit_cb.p_rcv_msg = NULL; 562 } 563 } 564 } /* while (TRUE) */ 565 } 566 567 /* Process quick timer tick */ 568 if (event & NFC_HAL_QUICK_TIMER_EVT_MASK) 569 { 570 nfc_hal_main_process_quick_timer_evt (); 571 } 572 } 573 574 NCI_TRACE_DEBUG0 ("nfc_hal_main_task terminated"); 575 576 GKI_exit_task (GKI_get_taskid ()); 577 return 0; 578 } 579 580 /******************************************************************************* 581 ** 582 ** Function HAL_NfcSetTraceLevel 583 ** 584 ** Description This function sets the trace level for HAL. If called with 585 ** a value of 0xFF, it simply returns the current trace level. 586 ** 587 ** Returns The new or current trace level 588 ** 589 *******************************************************************************/ 590 UINT8 HAL_NfcSetTraceLevel (UINT8 new_level) 591 { 592 if (new_level != 0xFF) 593 nfc_hal_cb.trace_level = new_level; 594 595 return (nfc_hal_cb.trace_level); 596 } 597