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 * Entry point for NFC_TASK 22 * 23 ******************************************************************************/ 24 #include <string.h> 25 #include "bt_types.h" 26 #include "gki.h" 27 #include "nfc_target.h" 28 29 #include "ce_int.h" 30 #include "nci_hmsgs.h" 31 #include "nfc_api.h" 32 #include "nfc_hal_api.h" 33 #include "nfc_int.h" 34 #include "rw_int.h" 35 #if (NFC_RW_ONLY == FALSE) 36 #include "llcp_int.h" 37 #else 38 #define llcp_cleanup() 39 #endif 40 41 #include "nfa_dm_int.h" 42 #include "nfa_sys.h" 43 44 /******************************************************************************* 45 ** 46 ** Function nfc_start_timer 47 ** 48 ** Description Start a timer for the specified amount of time. 49 ** NOTE: The timeout resolution is in SECONDS! (Even 50 ** though the timer structure field is ticks) 51 ** 52 ** Returns void 53 ** 54 *******************************************************************************/ 55 void nfc_start_timer(TIMER_LIST_ENT* p_tle, uint16_t type, uint32_t timeout) { 56 NFC_HDR* p_msg; 57 58 /* if timer list is currently empty, start periodic GKI timer */ 59 if (nfc_cb.timer_queue.p_first == NULL) { 60 /* if timer starts on other than NFC task (scritp wrapper) */ 61 if (GKI_get_taskid() != NFC_TASK) { 62 /* post event to start timer in NFC task */ 63 p_msg = (NFC_HDR*)GKI_getbuf(NFC_HDR_SIZE); 64 if (p_msg != NULL) { 65 p_msg->event = BT_EVT_TO_START_TIMER; 66 GKI_send_msg(NFC_TASK, NFC_MBOX_ID, p_msg); 67 } 68 } else { 69 /* Start nfc_task 1-sec resolution timer */ 70 GKI_start_timer(NFC_TIMER_ID, GKI_SECS_TO_TICKS(1), true); 71 } 72 } 73 74 GKI_remove_from_timer_list(&nfc_cb.timer_queue, p_tle); 75 76 p_tle->event = type; 77 p_tle->ticks = timeout; /* Save the number of seconds for the timer */ 78 79 GKI_add_to_timer_list(&nfc_cb.timer_queue, p_tle); 80 } 81 82 /******************************************************************************* 83 ** 84 ** Function nfc_remaining_time 85 ** 86 ** Description Return amount of time to expire 87 ** 88 ** Returns time in second 89 ** 90 *******************************************************************************/ 91 uint32_t nfc_remaining_time(TIMER_LIST_ENT* p_tle) { 92 return (GKI_get_remaining_ticks(&nfc_cb.timer_queue, p_tle)); 93 } 94 95 /******************************************************************************* 96 ** 97 ** Function nfc_process_timer_evt 98 ** 99 ** Description Process nfc GKI timer event 100 ** 101 ** Returns void 102 ** 103 *******************************************************************************/ 104 void nfc_process_timer_evt(void) { 105 TIMER_LIST_ENT* p_tle; 106 107 GKI_update_timer_list(&nfc_cb.timer_queue, 1); 108 109 while ((nfc_cb.timer_queue.p_first) && (!nfc_cb.timer_queue.p_first->ticks)) { 110 p_tle = nfc_cb.timer_queue.p_first; 111 GKI_remove_from_timer_list(&nfc_cb.timer_queue, p_tle); 112 113 switch (p_tle->event) { 114 case NFC_TTYPE_NCI_WAIT_RSP: 115 nfc_ncif_cmd_timeout(); 116 break; 117 118 case NFC_TTYPE_WAIT_2_DEACTIVATE: 119 nfc_wait_2_deactivate_timeout(); 120 break; 121 122 default: 123 NFC_TRACE_DEBUG2("nfc_process_timer_evt: timer:0x%x event (0x%04x)", 124 p_tle, p_tle->event); 125 NFC_TRACE_DEBUG1( 126 "nfc_process_timer_evt: unhandled timer event (0x%04x)", 127 p_tle->event); 128 } 129 } 130 131 /* if timer list is empty stop periodic GKI timer */ 132 if (nfc_cb.timer_queue.p_first == NULL) { 133 GKI_stop_timer(NFC_TIMER_ID); 134 } 135 } 136 137 /******************************************************************************* 138 ** 139 ** Function nfc_stop_timer 140 ** 141 ** Description Stop a timer. 142 ** 143 ** Returns void 144 ** 145 *******************************************************************************/ 146 void nfc_stop_timer(TIMER_LIST_ENT* p_tle) { 147 GKI_remove_from_timer_list(&nfc_cb.timer_queue, p_tle); 148 149 /* if timer list is empty stop periodic GKI timer */ 150 if (nfc_cb.timer_queue.p_first == NULL) { 151 GKI_stop_timer(NFC_TIMER_ID); 152 } 153 } 154 155 /******************************************************************************* 156 ** 157 ** Function nfc_start_quick_timer 158 ** 159 ** Description Start a timer for the specified amount of time. 160 ** NOTE: The timeout resolution depends on including modules. 161 ** QUICK_TIMER_TICKS_PER_SEC should be used to convert from 162 ** time to ticks. 163 ** 164 ** 165 ** Returns void 166 ** 167 *******************************************************************************/ 168 void nfc_start_quick_timer(TIMER_LIST_ENT* p_tle, uint16_t type, 169 uint32_t timeout) { 170 NFC_HDR* p_msg; 171 172 /* if timer list is currently empty, start periodic GKI timer */ 173 if (nfc_cb.quick_timer_queue.p_first == NULL) { 174 /* if timer starts on other than NFC task (scritp wrapper) */ 175 if (GKI_get_taskid() != NFC_TASK) { 176 /* post event to start timer in NFC task */ 177 p_msg = (NFC_HDR*)GKI_getbuf(NFC_HDR_SIZE); 178 if (p_msg != NULL) { 179 p_msg->event = BT_EVT_TO_START_QUICK_TIMER; 180 GKI_send_msg(NFC_TASK, NFC_MBOX_ID, p_msg); 181 } 182 } else { 183 /* Quick-timer is required for LLCP */ 184 GKI_start_timer(NFC_QUICK_TIMER_ID, 185 ((GKI_SECS_TO_TICKS(1) / QUICK_TIMER_TICKS_PER_SEC)), 186 true); 187 } 188 } 189 190 GKI_remove_from_timer_list(&nfc_cb.quick_timer_queue, p_tle); 191 192 p_tle->event = type; 193 p_tle->ticks = timeout; /* Save the number of ticks for the timer */ 194 195 GKI_add_to_timer_list(&nfc_cb.quick_timer_queue, p_tle); 196 } 197 198 /******************************************************************************* 199 ** 200 ** Function nfc_stop_quick_timer 201 ** 202 ** Description Stop a timer. 203 ** 204 ** Returns void 205 ** 206 *******************************************************************************/ 207 void nfc_stop_quick_timer(TIMER_LIST_ENT* p_tle) { 208 GKI_remove_from_timer_list(&nfc_cb.quick_timer_queue, p_tle); 209 210 /* if timer list is empty stop periodic GKI timer */ 211 if (nfc_cb.quick_timer_queue.p_first == NULL) { 212 GKI_stop_timer(NFC_QUICK_TIMER_ID); 213 } 214 } 215 216 /******************************************************************************* 217 ** 218 ** Function nfc_process_quick_timer_evt 219 ** 220 ** Description Process quick timer event 221 ** 222 ** Returns void 223 ** 224 *******************************************************************************/ 225 void nfc_process_quick_timer_evt(void) { 226 TIMER_LIST_ENT* p_tle; 227 228 GKI_update_timer_list(&nfc_cb.quick_timer_queue, 1); 229 230 while ((nfc_cb.quick_timer_queue.p_first) && 231 (!nfc_cb.quick_timer_queue.p_first->ticks)) { 232 p_tle = nfc_cb.quick_timer_queue.p_first; 233 GKI_remove_from_timer_list(&nfc_cb.quick_timer_queue, p_tle); 234 235 switch (p_tle->event) { 236 #if (NFC_RW_ONLY == FALSE) 237 case NFC_TTYPE_LLCP_LINK_MANAGER: 238 case NFC_TTYPE_LLCP_LINK_INACT: 239 case NFC_TTYPE_LLCP_DATA_LINK: 240 case NFC_TTYPE_LLCP_DELAY_FIRST_PDU: 241 llcp_process_timeout(p_tle); 242 break; 243 #endif 244 case NFC_TTYPE_RW_T1T_RESPONSE: 245 rw_t1t_process_timeout(p_tle); 246 break; 247 case NFC_TTYPE_RW_T2T_RESPONSE: 248 rw_t2t_process_timeout(p_tle); 249 break; 250 case NFC_TTYPE_RW_T3T_RESPONSE: 251 rw_t3t_process_timeout(p_tle); 252 break; 253 case NFC_TTYPE_RW_T4T_RESPONSE: 254 rw_t4t_process_timeout(p_tle); 255 break; 256 case NFC_TTYPE_RW_I93_RESPONSE: 257 rw_i93_process_timeout(p_tle); 258 break; 259 case NFC_TTYPE_P2P_PRIO_RESPONSE: 260 nfa_dm_p2p_timer_event(); 261 break; 262 case NFC_TTYPE_P2P_PRIO_LOGIC_CLEANUP: 263 nfa_dm_p2p_prio_logic_cleanup(); 264 break; 265 #if (NFC_RW_ONLY == FALSE) 266 case NFC_TTYPE_CE_T4T_UPDATE: 267 ce_t4t_process_timeout(p_tle); 268 break; 269 #endif 270 default: 271 NFC_TRACE_DEBUG1( 272 "nfc_process_quick_timer_evt: unhandled timer event (0x%04x)", 273 p_tle->event); 274 break; 275 } 276 } 277 278 /* if timer list is empty stop periodic GKI timer */ 279 if (nfc_cb.quick_timer_queue.p_first == NULL) { 280 GKI_stop_timer(NFC_QUICK_TIMER_ID); 281 } 282 } 283 284 /******************************************************************************* 285 ** 286 ** Function nfc_task_shutdown_nfcc 287 ** 288 ** Description Handle NFC shutdown 289 ** 290 ** Returns nothing 291 ** 292 *******************************************************************************/ 293 void nfc_task_shutdown_nfcc(void) { 294 NFC_HDR* p_msg; 295 296 /* Free any messages still in the mbox */ 297 while ((p_msg = (NFC_HDR*)GKI_read_mbox(NFC_MBOX_ID)) != NULL) { 298 GKI_freebuf(p_msg); 299 } 300 301 nfc_gen_cleanup(); 302 303 if (nfc_cb.flags & NFC_FL_POWER_OFF_SLEEP) { 304 nfc_set_state(NFC_STATE_W4_HAL_CLOSE); 305 nfc_cb.p_hal->close(); 306 } else if (nfc_cb.flags & NFC_FL_POWER_CYCLE_NFCC) { 307 nfc_set_state(NFC_STATE_W4_HAL_OPEN); 308 nfc_cb.p_hal->power_cycle(); 309 } else { 310 nfc_set_state(NFC_STATE_W4_HAL_CLOSE); 311 nfc_cb.p_hal->close(); 312 313 /* Perform final clean up */ 314 llcp_cleanup(); 315 316 /* Stop the timers */ 317 GKI_stop_timer(NFC_TIMER_ID); 318 GKI_stop_timer(NFC_QUICK_TIMER_ID); 319 GKI_stop_timer(NFA_TIMER_ID); 320 } 321 } 322 323 /******************************************************************************* 324 ** 325 ** Function nfc_task 326 ** 327 ** Description NFC event processing task 328 ** 329 ** Returns nothing 330 ** 331 *******************************************************************************/ 332 uint32_t nfc_task(uint32_t param) { 333 uint16_t event; 334 NFC_HDR* p_msg; 335 bool free_buf; 336 337 /* Initialize the nfc control block */ 338 memset(&nfc_cb, 0, sizeof(tNFC_CB)); 339 nfc_cb.trace_level = NFC_INITIAL_TRACE_LEVEL; 340 341 NFC_TRACE_DEBUG0("NFC_TASK started."); 342 343 /* main loop */ 344 while (true) { 345 event = GKI_wait(0xFFFF, 0); 346 347 /* Handle NFC_TASK_EVT_TRANSPORT_READY from NFC HAL */ 348 if (event & NFC_TASK_EVT_TRANSPORT_READY) { 349 NFC_TRACE_DEBUG0("NFC_TASK got NFC_TASK_EVT_TRANSPORT_READY."); 350 351 /* Reset the NFC controller. */ 352 nfc_set_state(NFC_STATE_CORE_INIT); 353 nci_snd_core_reset(NCI_RESET_TYPE_RESET_CFG); 354 } 355 356 if (event & NFC_MBOX_EVT_MASK) { 357 /* Process all incoming NCI messages */ 358 while ((p_msg = (NFC_HDR*)GKI_read_mbox(NFC_MBOX_ID)) != NULL) { 359 free_buf = true; 360 361 /* Determine the input message type. */ 362 switch (p_msg->event & NFC_EVT_MASK) { 363 case BT_EVT_TO_NFC_NCI: 364 free_buf = nfc_ncif_process_event(p_msg); 365 break; 366 367 case BT_EVT_TO_START_TIMER: 368 /* Start nfc_task 1-sec resolution timer */ 369 GKI_start_timer(NFC_TIMER_ID, GKI_SECS_TO_TICKS(1), true); 370 break; 371 372 case BT_EVT_TO_START_QUICK_TIMER: 373 /* Quick-timer is required for LLCP */ 374 GKI_start_timer( 375 NFC_QUICK_TIMER_ID, 376 ((GKI_SECS_TO_TICKS(1) / QUICK_TIMER_TICKS_PER_SEC)), true); 377 break; 378 379 case BT_EVT_TO_NFC_MSGS: 380 nfc_main_handle_hal_evt((tNFC_HAL_EVT_MSG*)p_msg); 381 break; 382 383 default: 384 NFC_TRACE_DEBUG1("nfc_task: unhandle mbox message, event=%04x", 385 p_msg->event); 386 break; 387 } 388 389 if (free_buf) { 390 GKI_freebuf(p_msg); 391 } 392 } 393 } 394 395 /* Process gki timer tick */ 396 if (event & NFC_TIMER_EVT_MASK) { 397 nfc_process_timer_evt(); 398 } 399 400 /* Process quick timer tick */ 401 if (event & NFC_QUICK_TIMER_EVT_MASK) { 402 nfc_process_quick_timer_evt(); 403 } 404 405 if (event & NFA_MBOX_EVT_MASK) { 406 while ((p_msg = (NFC_HDR*)GKI_read_mbox(NFA_MBOX_ID)) != NULL) { 407 nfa_sys_event(p_msg); 408 } 409 } 410 411 if (event & NFA_TIMER_EVT_MASK) { 412 nfa_sys_timer_update(); 413 } 414 } 415 416 NFC_TRACE_DEBUG0("nfc_task terminated"); 417 418 GKI_exit_task(GKI_get_taskid()); 419 return 0; 420 } 421