• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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