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