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