• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2010-2014 Broadcom Corporation
4  *..Copyright 2018-2020 NXP
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at:
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  ******************************************************************************/
19 
20 /******************************************************************************
21  *
22  *  Entry point for UWB_TASK
23  *
24  ******************************************************************************/
25 #include <string.h>
26 
27 #include "uci_hmsgs.h"
28 #include "uci_log.h"
29 #include "uwa_dm_int.h"
30 #include "uwa_sys.h"
31 #include "uwb_api.h"
32 #include "uwb_gki.h"
33 #include "uwb_hal_api.h"
34 #include "uwb_int.h"
35 #include "uwb_osal_common.h"
36 #include "uwb_target.h"
37 
38 /*******************************************************************************
39 **
40 ** Function         uwb_start_timer
41 **
42 ** Description      Start a timer for the specified amount of time.
43 **                  NOTE: The timeout resolution is in SECONDS! (Even
44 **                          though the timer structure field is ticks)
45 **
46 ** Returns          void
47 **
48 *******************************************************************************/
uwb_start_timer(TIMER_LIST_ENT * p_tle,uint16_t type,uint32_t timeout)49 void uwb_start_timer(TIMER_LIST_ENT* p_tle, uint16_t type, uint32_t timeout) {
50   UWB_HDR* p_msg;
51 
52   /* if timer list is currently empty, start periodic GKI timer */
53   if (uwb_cb.timer_queue.p_first == NULL) {
54     /* if timer starts on other than UWB task (scritp wrapper) */
55     if (phUwb_GKI_get_taskid() != UWB_TASK) {
56       /* post event to start timer in UWB task */
57       p_msg = (UWB_HDR*)phUwb_GKI_getbuf(UWB_HDR_SIZE);
58       if (p_msg != NULL) {
59         p_msg->event = BT_EVT_TO_START_TIMER;
60         phUwb_GKI_send_msg(UWB_TASK, UWB_MBOX_ID, p_msg);
61       }
62     } else {
63       /* Start uwb_task 1-sec resolution timer */
64       phUwb_GKI_start_timer(UWB_TIMER_ID, GKI_SECS_TO_TICKS(1), true);
65     }
66   }
67 
68   phUwb_GKI_remove_from_timer_list(&uwb_cb.timer_queue, p_tle);
69 
70   p_tle->event = type;
71   p_tle->ticks = timeout; /* Save the number of seconds for the timer */
72 
73   phUwb_GKI_add_to_timer_list(&uwb_cb.timer_queue, p_tle);
74 }
75 
76 /*******************************************************************************
77 **
78 ** Function         uwb_remaining_time
79 **
80 ** Description      Return amount of time to expire
81 **
82 ** Returns          time in second
83 **
84 *******************************************************************************/
uwb_remaining_time(TIMER_LIST_ENT * p_tle)85 uint32_t uwb_remaining_time(TIMER_LIST_ENT* p_tle) {
86   return (phUwb_GKI_get_remaining_ticks(&uwb_cb.timer_queue, p_tle));
87 }
88 
89 /*******************************************************************************
90 **
91 ** Function         uwb_process_timer_evt
92 **
93 ** Description      Process uwb GKI timer event
94 **
95 ** Returns          void
96 **
97 *******************************************************************************/
uwb_process_timer_evt(void)98 void uwb_process_timer_evt(void) {
99   TIMER_LIST_ENT* p_tle;
100 
101   phUwb_GKI_update_timer_list(&uwb_cb.timer_queue, 1);
102 
103   while ((uwb_cb.timer_queue.p_first) && (!uwb_cb.timer_queue.p_first->ticks)) {
104     p_tle = uwb_cb.timer_queue.p_first;
105     phUwb_GKI_remove_from_timer_list(&uwb_cb.timer_queue, p_tle);
106 
107     if (uwb_cb.uwb_state == UWB_STATE_W4_HAL_CLOSE ||
108         uwb_cb.uwb_state == UWB_STATE_NONE) {
109       return;
110     }
111     switch (p_tle->event) {
112       default:
113         UCI_TRACE_I("uwb_process_timer_evt: timer:0x%p event (0x%04x)", p_tle,
114                     p_tle->event);
115         UCI_TRACE_W("uwb_process_timer_evt: unhandled timer event (0x%04x)",
116                     p_tle->event);
117     }
118   }
119 
120   /* if timer list is empty stop periodic GKI timer */
121   if (uwb_cb.timer_queue.p_first == NULL) {
122     phUwb_GKI_stop_timer(UWB_TIMER_ID, 0);
123   }
124 }
125 
126 /*******************************************************************************
127 **
128 ** Function         uwb_stop_timer
129 **
130 ** Description      Stop a timer.
131 **
132 ** Returns          void
133 **
134 *******************************************************************************/
uwb_stop_timer(TIMER_LIST_ENT * p_tle)135 void uwb_stop_timer(TIMER_LIST_ENT* p_tle) {
136   phUwb_GKI_remove_from_timer_list(&uwb_cb.timer_queue, p_tle);
137 
138   /* if timer list is empty stop periodic GKI timer */
139   if (uwb_cb.timer_queue.p_first == NULL) {
140     phUwb_GKI_stop_timer(UWB_TIMER_ID, 0);
141   }
142 }
143 
144 /*******************************************************************************
145 **
146 ** Function         uwb_start_quick_timer
147 **
148 ** Description      Start a timer for the specified amount of time.
149 **                  NOTE: The timeout resolution depends on including modules.
150 **                  QUICK_TIMER_TICKS_PER_SEC should be used to convert from
151 **                  time to ticks.
152 **
153 **
154 ** Returns          void
155 **
156 *******************************************************************************/
uwb_start_quick_timer(TIMER_LIST_ENT * p_tle,uint16_t type,uint32_t timeout)157 void uwb_start_quick_timer(TIMER_LIST_ENT* p_tle, uint16_t type,
158                            uint32_t timeout) {
159   UCI_TRACE_I("uwb_start_quick_timer enter: timeout: %d", timeout);
160   UWB_HDR* p_msg;
161 
162   /* if timer list is currently empty, start periodic GKI timer */
163   if (uwb_cb.quick_timer_queue.p_first == NULL) {
164     /* if timer starts on other than UWB task (scritp wrapper) */
165     if (phUwb_GKI_get_taskid() != UWB_TASK) {
166       /* post event to start timer in UWB task */
167       p_msg = (UWB_HDR*)phUwb_GKI_getbuf(UWB_HDR_SIZE);
168       if (p_msg != NULL) {
169         p_msg->event = BT_EVT_TO_START_QUICK_TIMER;
170         phUwb_GKI_send_msg(UWB_TASK, UWB_MBOX_ID, p_msg);
171       }
172     } else {
173       /* Quick-timer is required for LLCP */
174       phUwb_GKI_start_timer(
175           UWB_QUICK_TIMER_ID,
176           ((GKI_SECS_TO_TICKS(1) / QUICK_TIMER_TICKS_PER_SEC)), true);
177     }
178   }
179 
180   phUwb_GKI_remove_from_timer_list(&uwb_cb.quick_timer_queue, p_tle);
181 
182   p_tle->event = type;
183   p_tle->ticks = timeout; /* Save the number of ticks for the timer */
184 
185   phUwb_GKI_add_to_timer_list(&uwb_cb.quick_timer_queue, p_tle);
186 }
187 
188 /*******************************************************************************
189 **
190 ** Function         uwb_stop_quick_timer
191 **
192 ** Description      Stop a timer.
193 **
194 ** Returns          void
195 **
196 *******************************************************************************/
uwb_stop_quick_timer(TIMER_LIST_ENT * p_tle)197 void uwb_stop_quick_timer(TIMER_LIST_ENT* p_tle) {
198   UCI_TRACE_I("uwb_stop_quick_timer: enter");
199   phUwb_GKI_remove_from_timer_list(&uwb_cb.quick_timer_queue, p_tle);
200 
201   /* if timer list is empty stop periodic GKI timer */
202   if (uwb_cb.quick_timer_queue.p_first == NULL) {
203     phUwb_GKI_stop_timer(UWB_QUICK_TIMER_ID, 0);
204   }
205 }
206 
207 /*******************************************************************************
208 **
209 ** Function         uwb_process_quick_timer_evt
210 **
211 ** Description      Process quick timer event
212 **
213 ** Returns          void
214 **
215 *******************************************************************************/
uwb_process_quick_timer_evt(void)216 void uwb_process_quick_timer_evt(void) {
217   TIMER_LIST_ENT* p_tle;
218 
219   if (uwb_cb.uwb_state == UWB_STATE_W4_HAL_CLOSE ||
220       uwb_cb.uwb_state == UWB_STATE_NONE) {
221     return;
222   }
223 
224   phUwb_GKI_update_timer_list(&uwb_cb.quick_timer_queue, 1);
225 
226   while ((uwb_cb.quick_timer_queue.p_first) &&
227          (!uwb_cb.quick_timer_queue.p_first->ticks)) {
228     p_tle = uwb_cb.quick_timer_queue.p_first;
229     phUwb_GKI_remove_from_timer_list(&uwb_cb.quick_timer_queue, p_tle);
230 
231     switch (p_tle->event) {
232       case UWB_TTYPE_UCI_WAIT_RSP:
233         uwb_ucif_cmd_timeout();
234         break;
235       default:
236         UCI_TRACE_I(
237             "uwb_process_quick_timer_evt: unhandled timer event (0x%04x)",
238             p_tle->event);
239         break;
240     }
241   }
242 
243   /* if timer list is empty stop periodic GKI timer */
244   if (uwb_cb.quick_timer_queue.p_first == NULL) {
245     phUwb_GKI_stop_timer(UWB_QUICK_TIMER_ID, 0);
246   }
247 }
248 
249 /*******************************************************************************
250 **
251 ** Function         uwb_task_shutdown_uwbc
252 **
253 ** Description      Handle UWB shutdown
254 **
255 ** Returns          nothing
256 **
257 *******************************************************************************/
uwb_task_shutdown_uwbc(void)258 void uwb_task_shutdown_uwbc(void) {
259   UWB_HDR* p_msg;
260 
261   /* Free any messages still in the mbox */
262   while ((p_msg = (UWB_HDR*)phUwb_GKI_read_mbox(UWB_MBOX_ID)) != NULL) {
263     phUwb_GKI_freebuf(p_msg);
264   }
265   uwb_gen_cleanup();
266 
267   uwb_set_state(UWB_STATE_W4_HAL_CLOSE);
268   uwb_cb.p_hal->close();
269 
270   /* Stop the timers */
271   phUwb_GKI_stop_timer(UWB_TIMER_ID, 0);
272   phUwb_GKI_stop_timer(UWB_QUICK_TIMER_ID, 0);
273   phUwb_GKI_stop_timer(UWA_TIMER_ID, 0);
274 }
275 
276 #define UWB_TASK_ARGS __attribute__((unused)) uint32_t arg
277 
uwb_task(uint32_t arg)278 uint32_t uwb_task(__attribute__((unused)) uint32_t arg) {
279   uint16_t event;
280   UWB_HDR* p_msg;
281   bool free_buf;
282   /* Initialize the uwb control block */
283   memset(&uwb_cb, 0, sizeof(tUWB_CB));
284 
285   UCI_TRACE_I("UWB_TASK started.");
286 
287   /* main loop */
288   while (true) {
289     event = phUwb_GKI_wait(0xFFFF, 0);
290     if (event == EVENT_MASK(GKI_SHUTDOWN_EVT)) {
291       break;
292     }
293     /* Handle UWB_TASK_EVT_TRANSPORT_READY from UWB HAL */
294     if (event & UWB_TASK_EVT_TRANSPORT_READY) {
295       UCI_TRACE_I("UWB_TASK got UWB_TASK_EVT_TRANSPORT_READY.");
296 
297       /* Reset the UWB controller. */
298       uwb_set_state(UWB_STATE_IDLE);
299       uwb_enabled(UWB_STATUS_OK, NULL);
300     }
301 
302     if (event & UWB_MBOX_EVT_MASK) {
303       /* Process all incoming UCI messages */
304       while ((p_msg = (UWB_HDR*)phUwb_GKI_read_mbox(UWB_MBOX_ID)) != NULL) {
305         free_buf = true;
306 
307         /* Determine the input message type. */
308         switch (p_msg->event & UWB_EVT_MASK) {
309           case BT_EVT_TO_UWB_UCI:
310             free_buf = uwb_ucif_process_event(p_msg);
311             break;
312 
313           case BT_EVT_TO_START_TIMER:
314             /* Start uwb_task 1-sec resolution timer */
315             phUwb_GKI_start_timer(UWB_TIMER_ID, GKI_SECS_TO_TICKS(1), true);
316             break;
317 
318           case BT_EVT_TO_START_QUICK_TIMER:
319             /* Quick-timer is required for LLCP */
320             phUwb_GKI_start_timer(
321                 UWB_QUICK_TIMER_ID,
322                 ((GKI_SECS_TO_TICKS(1) / QUICK_TIMER_TICKS_PER_SEC)), true);
323             break;
324 
325           case BT_EVT_TO_UWB_MSGS:
326             uwb_main_handle_hal_evt((tUWB_HAL_EVT_MSG*)p_msg);
327             break;
328 
329           default:
330             UCI_TRACE_E("uwb_task: unhandle mbox message, event=%04x",
331                         p_msg->event);
332             break;
333         }
334 
335         if (free_buf) {
336           phUwb_GKI_freebuf(p_msg);
337         }
338       }
339     }
340 
341     /* Process gki timer tick */
342     if (event & UWB_TIMER_EVT_MASK) {
343       uwb_process_timer_evt();
344     }
345 
346     /* Process quick timer tick */
347     if (event & UWB_QUICK_TIMER_EVT_MASK) {
348       uwb_process_quick_timer_evt();
349     }
350 
351     if (event & UWA_MBOX_EVT_MASK) {
352       while ((p_msg = (UWB_HDR*)phUwb_GKI_read_mbox(UWA_MBOX_ID)) != NULL) {
353         uwa_sys_event(p_msg);
354       }
355     }
356 
357     if (event & UWA_TIMER_EVT_MASK) {
358       uwa_sys_timer_update();
359     }
360   }
361 
362   UCI_TRACE_I("uwb_task terminated");
363 
364   phUwb_GKI_exit_task(phUwb_GKI_get_taskid());
365   return 0;
366 }
367