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