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 *******************************************************************************/
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
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 *******************************************************************************/
nfc_remaining_time(TIMER_LIST_ENT * p_tle)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 *******************************************************************************/
nfc_process_timer_evt(void)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 *******************************************************************************/
nfc_stop_timer(TIMER_LIST_ENT * p_tle)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 *******************************************************************************/
nfc_start_quick_timer(TIMER_LIST_ENT * p_tle,uint16_t type,uint32_t timeout)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 *******************************************************************************/
nfc_stop_quick_timer(TIMER_LIST_ENT * p_tle)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 *******************************************************************************/
nfc_process_quick_timer_evt(void)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 *******************************************************************************/
nfc_task_shutdown_nfcc(void)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 *******************************************************************************/
nfc_task(uint32_t param)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