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 *******************************************************************************/
nfc_start_timer(TIMER_LIST_ENT * p_tle,uint16_t type,uint32_t timeout)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 == nullptr) {
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 != nullptr) {
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 *******************************************************************************/
nfc_remaining_time(TIMER_LIST_ENT * p_tle)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 *******************************************************************************/
nfc_process_timer_evt(void)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 == nullptr) {
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 *******************************************************************************/
nfc_stop_timer(TIMER_LIST_ENT * p_tle)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 == nullptr) {
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 *******************************************************************************/
nfc_start_quick_timer(TIMER_LIST_ENT * p_tle,uint16_t type,uint32_t timeout)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 == nullptr) {
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 != nullptr) {
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 *******************************************************************************/
nfc_stop_quick_timer(TIMER_LIST_ENT * p_tle)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 == nullptr) {
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 *******************************************************************************/
nfc_process_quick_timer_evt(void)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       case NFC_TTYPE_RW_MFC_RESPONSE:
274         rw_mfc_process_timeout(p_tle);
275         break;
276 
277 #if (NFC_RW_ONLY == FALSE)
278       case NFC_TTYPE_CE_T4T_UPDATE:
279         ce_t4t_process_timeout(p_tle);
280         break;
281 #endif
282       default:
283         DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
284             "nfc_process_quick_timer_evt: unhandled timer event (0x%04x)",
285             p_tle->event);
286         break;
287     }
288   }
289 
290   /* if timer list is empty stop periodic GKI timer */
291   if (nfc_cb.quick_timer_queue.p_first == nullptr) {
292     GKI_stop_timer(NFC_QUICK_TIMER_ID);
293   }
294 }
295 
296 /*******************************************************************************
297 **
298 ** Function         nfc_task_shutdown_nfcc
299 **
300 ** Description      Handle NFC shutdown
301 **
302 ** Returns          nothing
303 **
304 *******************************************************************************/
nfc_task_shutdown_nfcc(void)305 void nfc_task_shutdown_nfcc(void) {
306   NFC_HDR* p_msg;
307 
308   /* Free any messages still in the mbox */
309   while ((p_msg = (NFC_HDR*)GKI_read_mbox(NFC_MBOX_ID)) != nullptr) {
310     GKI_freebuf(p_msg);
311   }
312 
313   nfc_gen_cleanup();
314 
315   if (nfc_cb.flags & NFC_FL_POWER_OFF_SLEEP) {
316     nfc_set_state(NFC_STATE_W4_HAL_CLOSE);
317     nfc_cb.p_hal->close();
318   } else if (nfc_cb.flags & NFC_FL_POWER_CYCLE_NFCC) {
319     nfc_set_state(NFC_STATE_W4_HAL_OPEN);
320     nfc_cb.p_hal->power_cycle();
321   } else {
322     nfc_set_state(NFC_STATE_W4_HAL_CLOSE);
323     nfc_cb.p_hal->close();
324 
325     /* Perform final clean up */
326     llcp_cleanup();
327 
328     /* Stop the timers */
329     GKI_stop_timer(NFC_TIMER_ID);
330     GKI_stop_timer(NFC_QUICK_TIMER_ID);
331     GKI_stop_timer(NFA_TIMER_ID);
332   }
333 }
334 
335 /*******************************************************************************
336 **
337 ** Function         nfc_task
338 **
339 ** Description      NFC event processing task
340 **
341 ** Returns          nothing
342 **
343 *******************************************************************************/
nfc_task(uint32_t arg)344 uint32_t nfc_task(__attribute__((unused)) uint32_t arg) {
345   uint16_t event;
346   NFC_HDR* p_msg;
347   bool free_buf;
348 
349   /* Initialize the nfc control block */
350   memset(&nfc_cb, 0, sizeof(tNFC_CB));
351 
352   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("NFC_TASK started.");
353 
354   /* main loop */
355   while (true) {
356     event = GKI_wait(0xFFFF, 0);
357     if (event == EVENT_MASK(GKI_SHUTDOWN_EVT)) {
358       break;
359     }
360     /* Handle NFC_TASK_EVT_TRANSPORT_READY from NFC HAL */
361     if (event & NFC_TASK_EVT_TRANSPORT_READY) {
362       DLOG_IF(INFO, nfc_debug_enabled)
363           << StringPrintf("NFC_TASK got NFC_TASK_EVT_TRANSPORT_READY.");
364 
365       /* Reset the NFC controller. */
366       nfc_set_state(NFC_STATE_CORE_INIT);
367       nci_snd_core_reset(NCI_RESET_TYPE_RESET_CFG);
368     }
369 
370     if (event & NFC_MBOX_EVT_MASK) {
371       /* Process all incoming NCI messages */
372       while ((p_msg = (NFC_HDR*)GKI_read_mbox(NFC_MBOX_ID)) != nullptr) {
373         free_buf = true;
374 
375         /* Determine the input message type. */
376         switch (p_msg->event & NFC_EVT_MASK) {
377           case BT_EVT_TO_NFC_NCI:
378             free_buf = nfc_ncif_process_event(p_msg);
379             break;
380 
381           case BT_EVT_TO_START_TIMER:
382             /* Start nfc_task 1-sec resolution timer */
383             GKI_start_timer(NFC_TIMER_ID, GKI_SECS_TO_TICKS(1), true);
384             break;
385 
386           case BT_EVT_TO_START_QUICK_TIMER:
387             /* Quick-timer is required for LLCP */
388             GKI_start_timer(
389                 NFC_QUICK_TIMER_ID,
390                 ((GKI_SECS_TO_TICKS(1) / QUICK_TIMER_TICKS_PER_SEC)), true);
391             break;
392 
393           case BT_EVT_TO_NFC_MSGS:
394             nfc_main_handle_hal_evt((tNFC_HAL_EVT_MSG*)p_msg);
395             break;
396 
397           default:
398             DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
399                 "nfc_task: unhandle mbox message, event=%04x", p_msg->event);
400             break;
401         }
402 
403         if (free_buf) {
404           GKI_freebuf(p_msg);
405         }
406       }
407     }
408 
409     /* Process gki timer tick */
410     if (event & NFC_TIMER_EVT_MASK) {
411       nfc_process_timer_evt();
412     }
413 
414     /* Process quick timer tick */
415     if (event & NFC_QUICK_TIMER_EVT_MASK) {
416       nfc_process_quick_timer_evt();
417     }
418 
419     if (event & NFA_MBOX_EVT_MASK) {
420       while ((p_msg = (NFC_HDR*)GKI_read_mbox(NFA_MBOX_ID)) != nullptr) {
421         nfa_sys_event(p_msg);
422       }
423     }
424 
425     if (event & NFA_TIMER_EVT_MASK) {
426       nfa_sys_timer_update();
427     }
428   }
429 
430   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("nfc_task terminated");
431 
432   GKI_exit_task(GKI_get_taskid());
433   return 0;
434 }
435