1 /******************************************************************************
2  *
3  *  Copyright (C) 2003-2012 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  *  This is the main implementation file for the BTA system manager.
22  *
23  ******************************************************************************/
24 #define LOG_TAG "bt_bta_sys_main"
25 
26 #include <assert.h>
27 #include <string.h>
28 
29 #include "osi/include/alarm.h"
30 #include "btm_api.h"
31 #include "bta_api.h"
32 #include "bta_sys.h"
33 #include "bta_sys_int.h"
34 
35 #include "osi/include/fixed_queue.h"
36 #include "gki.h"
37 #include "osi/include/hash_map.h"
38 #include "osi/include/osi.h"
39 #include "osi/include/hash_functions.h"
40 #include "osi/include/log.h"
41 #include "osi/include/thread.h"
42 #if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
43 #include "bta_ar_api.h"
44 #endif
45 #include "utl.h"
46 
47 /* system manager control block definition */
48 #if BTA_DYNAMIC_MEMORY == FALSE
49 tBTA_SYS_CB bta_sys_cb;
50 #endif
51 
52 fixed_queue_t *btu_bta_alarm_queue;
53 static hash_map_t *bta_alarm_hash_map;
54 static const size_t BTA_ALARM_HASH_MAP_SIZE = 17;
55 static pthread_mutex_t bta_alarm_lock;
56 extern thread_t *bt_workqueue_thread;
57 
58 /* trace level */
59 /* TODO Bluedroid - Hard-coded trace levels -  Needs to be configurable */
60 UINT8 appl_trace_level = BT_TRACE_LEVEL_WARNING; //APPL_INITIAL_TRACE_LEVEL;
61 UINT8 btif_trace_level = BT_TRACE_LEVEL_WARNING;
62 
63 // Communication queue between btu_task and bta.
64 extern fixed_queue_t *btu_bta_msg_queue;
65 void btu_bta_alarm_ready(fixed_queue_t *queue, UNUSED_ATTR void *context);
66 
67 static const tBTA_SYS_REG bta_sys_hw_reg =
68 {
69     bta_sys_sm_execute,
70     NULL
71 };
72 
73 
74 /* type for action functions */
75 typedef void (*tBTA_SYS_ACTION)(tBTA_SYS_HW_MSG *p_data);
76 
77 /* action function list */
78 const tBTA_SYS_ACTION bta_sys_action[] =
79 {
80     /* device manager local device API events - cf bta_sys.h for events */
81     bta_sys_hw_api_enable,             /* 0  BTA_SYS_HW_API_ENABLE_EVT    */
82     bta_sys_hw_evt_enabled,           /* 1  BTA_SYS_HW_EVT_ENABLED_EVT */
83     bta_sys_hw_evt_stack_enabled,       /* 2  BTA_SYS_HW_EVT_STACK_ENABLED_EVT */
84     bta_sys_hw_api_disable,             /* 3  BTA_SYS_HW_API_DISABLE_EVT     */
85     bta_sys_hw_evt_disabled,           /* 4  BTA_SYS_HW_EVT_DISABLED_EVT  */
86     bta_sys_hw_error                        /* 5   BTA_SYS_HW_ERROR_EVT  */
87 };
88 
89 /* state machine action enumeration list */
90 enum
91 {
92     /* device manager local device API events */
93     BTA_SYS_HW_API_ENABLE,
94     BTA_SYS_HW_EVT_ENABLED,
95     BTA_SYS_HW_EVT_STACK_ENABLED,
96     BTA_SYS_HW_API_DISABLE,
97     BTA_SYS_HW_EVT_DISABLED,
98     BTA_SYS_HW_ERROR
99 };
100 
101 #define BTA_SYS_NUM_ACTIONS  (BTA_SYS_MAX_EVT & 0x00ff)
102 #define BTA_SYS_IGNORE       BTA_SYS_NUM_ACTIONS
103 
104 /* state table information */
105 #define BTA_SYS_ACTIONS              2       /* number of actions */
106 #define BTA_SYS_NEXT_STATE           2       /* position of next state */
107 #define BTA_SYS_NUM_COLS             3       /* number of columns in state tables */
108 
109 
110 /* state table for OFF state */
111 const UINT8 bta_sys_hw_off[][BTA_SYS_NUM_COLS] =
112 {
113 /* Event                    Action 1               Action 2             Next State */
114 /* API_ENABLE    */  {BTA_SYS_HW_API_ENABLE,    BTA_SYS_IGNORE,     BTA_SYS_HW_STARTING},
115 /* EVT_ENABLED   */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_STARTING},
116 /* STACK_ENABLED */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_ON},
117 /* API_DISABLE   */  {BTA_SYS_HW_EVT_DISABLED,  BTA_SYS_IGNORE,     BTA_SYS_HW_OFF},
118 /* EVT_DISABLED  */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_OFF},
119 /* EVT_ERROR     */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_OFF}
120 };
121 
122 const UINT8 bta_sys_hw_starting[][BTA_SYS_NUM_COLS] =
123 {
124 /* Event                    Action 1                   Action 2               Next State */
125 /* API_ENABLE    */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_STARTING}, /* wait for completion event */
126 /* EVT_ENABLED   */  {BTA_SYS_HW_EVT_ENABLED,       BTA_SYS_IGNORE,         BTA_SYS_HW_STARTING},
127 /* STACK_ENABLED */  {BTA_SYS_HW_EVT_STACK_ENABLED, BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
128 /* API_DISABLE   */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_STOPPING}, /* successive disable/enable: change state wait for completion to disable */
129 /* EVT_DISABLED  */  {BTA_SYS_HW_EVT_DISABLED,      BTA_SYS_HW_API_ENABLE,  BTA_SYS_HW_STARTING}, /* successive enable/disable: notify, then restart HW */
130 /* EVT_ERROR */      {BTA_SYS_HW_ERROR,             BTA_SYS_IGNORE,         BTA_SYS_HW_ON}
131 };
132 
133 const UINT8 bta_sys_hw_on[][BTA_SYS_NUM_COLS] =
134 {
135 /* Event                    Action 1                   Action 2               Next State */
136 /* API_ENABLE    */  {BTA_SYS_HW_API_ENABLE,        BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
137 /* EVT_ENABLED   */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
138 /* STACK_ENABLED */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
139 /* API_DISABLE   */  {BTA_SYS_HW_API_DISABLE,       BTA_SYS_IGNORE,         BTA_SYS_HW_ON}, /* don't change the state here, as some other modules might be active */
140 /* EVT_DISABLED */   {BTA_SYS_HW_ERROR,             BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
141 /* EVT_ERROR */      {BTA_SYS_HW_ERROR,             BTA_SYS_IGNORE,         BTA_SYS_HW_ON}
142 };
143 
144 const UINT8 bta_sys_hw_stopping[][BTA_SYS_NUM_COLS] =
145 {
146 /* Event                    Action 1                   Action 2               Next State */
147 /* API_ENABLE    */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_STARTING}, /* change state, and wait for completion event to enable */
148 /* EVT_ENABLED   */  {BTA_SYS_HW_EVT_ENABLED,       BTA_SYS_IGNORE,         BTA_SYS_HW_STOPPING}, /* successive enable/disable: finish the enable before disabling */
149 /* STACK_ENABLED */  {BTA_SYS_HW_EVT_STACK_ENABLED, BTA_SYS_HW_API_DISABLE, BTA_SYS_HW_STOPPING}, /* successive enable/disable: notify, then stop */
150 /* API_DISABLE   */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_STOPPING}, /* wait for completion event */
151 /* EVT_DISABLED  */  {BTA_SYS_HW_EVT_DISABLED,      BTA_SYS_IGNORE,         BTA_SYS_HW_OFF},
152 /* EVT_ERROR     */  {BTA_SYS_HW_API_DISABLE,       BTA_SYS_IGNORE,         BTA_SYS_HW_STOPPING}
153 };
154 
155 typedef const UINT8 (*tBTA_SYS_ST_TBL)[BTA_SYS_NUM_COLS];
156 
157 /* state table */
158 const tBTA_SYS_ST_TBL bta_sys_st_tbl[] = {
159     bta_sys_hw_off,
160     bta_sys_hw_starting,
161     bta_sys_hw_on,
162     bta_sys_hw_stopping
163 };
164 
165 /*******************************************************************************
166 **
167 ** Function         bta_sys_init
168 **
169 ** Description      BTA initialization; called from task initialization.
170 **
171 **
172 ** Returns          void
173 **
174 *******************************************************************************/
bta_sys_init(void)175 void bta_sys_init(void)
176 {
177     memset(&bta_sys_cb, 0, sizeof(tBTA_SYS_CB));
178 
179     pthread_mutex_init(&bta_alarm_lock, NULL);
180 
181     bta_alarm_hash_map = hash_map_new(BTA_ALARM_HASH_MAP_SIZE,
182             hash_function_pointer, NULL, (data_free_fn)alarm_free, NULL);
183     btu_bta_alarm_queue = fixed_queue_new(SIZE_MAX);
184 
185     fixed_queue_register_dequeue(btu_bta_alarm_queue,
186         thread_get_reactor(bt_workqueue_thread),
187         btu_bta_alarm_ready,
188         NULL);
189 
190     appl_trace_level = APPL_INITIAL_TRACE_LEVEL;
191 
192     /* register BTA SYS message handler */
193     bta_sys_register( BTA_ID_SYS,  &bta_sys_hw_reg);
194 
195     /* register for BTM notifications */
196     BTM_RegisterForDeviceStatusNotif ((tBTM_DEV_STATUS_CB*)&bta_sys_hw_btm_cback );
197 
198 #if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
199     bta_ar_init();
200 #endif
201 
202 }
203 
bta_sys_free(void)204 void bta_sys_free(void) {
205     fixed_queue_free(btu_bta_alarm_queue, NULL);
206     hash_map_free(bta_alarm_hash_map);
207     pthread_mutex_destroy(&bta_alarm_lock);
208 }
209 
210 /*******************************************************************************
211 **
212 ** Function         bta_dm_sm_execute
213 **
214 ** Description      State machine event handling function for DM
215 **
216 **
217 ** Returns          void
218 **
219 *******************************************************************************/
bta_sys_sm_execute(BT_HDR * p_msg)220 BOOLEAN bta_sys_sm_execute(BT_HDR *p_msg)
221 {
222     BOOLEAN freebuf = TRUE;
223     tBTA_SYS_ST_TBL      state_table;
224     UINT8               action;
225     int                 i;
226 
227     APPL_TRACE_EVENT("bta_sys_sm_execute state:%d, event:0x%x",  bta_sys_cb.state, p_msg->event);
228 
229     /* look up the state table for the current state */
230     state_table = bta_sys_st_tbl[bta_sys_cb.state];
231     /* update state */
232     bta_sys_cb.state = state_table[p_msg->event & 0x00ff][BTA_SYS_NEXT_STATE];
233 
234     /* execute action functions */
235     for (i = 0; i < BTA_SYS_ACTIONS; i++)
236     {
237         if ((action = state_table[p_msg->event & 0x00ff][i]) != BTA_SYS_IGNORE)
238         {
239             (*bta_sys_action[action])( (tBTA_SYS_HW_MSG*) p_msg);
240         }
241         else
242         {
243             break;
244         }
245     }
246     return freebuf;
247 
248 }
249 
250 
bta_sys_hw_register(tBTA_SYS_HW_MODULE module,tBTA_SYS_HW_CBACK * cback)251 void bta_sys_hw_register( tBTA_SYS_HW_MODULE module, tBTA_SYS_HW_CBACK *cback)
252 {
253     bta_sys_cb.sys_hw_cback[module]=cback;
254 }
255 
256 
bta_sys_hw_unregister(tBTA_SYS_HW_MODULE module)257 void bta_sys_hw_unregister( tBTA_SYS_HW_MODULE module )
258 {
259     bta_sys_cb.sys_hw_cback[module]=NULL;
260 }
261 
262 /*******************************************************************************
263 **
264 ** Function         bta_sys_hw_btm_cback
265 **
266 ** Description     This function is registered by BTA SYS to BTM in order to get status notifications
267 **
268 **
269 ** Returns
270 **
271 *******************************************************************************/
bta_sys_hw_btm_cback(tBTM_DEV_STATUS status)272 void bta_sys_hw_btm_cback( tBTM_DEV_STATUS status )
273 {
274 
275     tBTA_SYS_HW_MSG *sys_event;
276 
277     APPL_TRACE_DEBUG(" bta_sys_hw_btm_cback was called with parameter: %i" , status );
278 
279     /* send a message to BTA SYS */
280     if ((sys_event = (tBTA_SYS_HW_MSG *) GKI_getbuf(sizeof(tBTA_SYS_HW_MSG))) != NULL)
281     {
282         if (status == BTM_DEV_STATUS_UP)
283             sys_event->hdr.event = BTA_SYS_EVT_STACK_ENABLED_EVT;
284         else if (status == BTM_DEV_STATUS_DOWN)
285             sys_event->hdr.event = BTA_SYS_ERROR_EVT;
286         else
287         {
288             /* BTM_DEV_STATUS_CMD_TOUT is ignored for now. */
289             GKI_freebuf (sys_event);
290             sys_event = NULL;
291         }
292 
293         if (sys_event)
294         {
295             bta_sys_sendmsg(sys_event);
296         }
297     }
298     else
299     {
300         APPL_TRACE_DEBUG("ERROR bta_sys_hw_btm_cback couldn't send msg" );
301     }
302 }
303 
304 
305 
306 /*******************************************************************************
307 **
308 ** Function         bta_sys_hw_error
309 **
310 ** Description     In case the HW device stops answering... Try to turn it off, then re-enable all
311 **                      previously active SW modules.
312 **
313 ** Returns          success or failure
314 **
315 *******************************************************************************/
bta_sys_hw_error(tBTA_SYS_HW_MSG * p_sys_hw_msg)316 void bta_sys_hw_error(tBTA_SYS_HW_MSG *p_sys_hw_msg)
317 {
318     UINT8 module_index;
319     UNUSED(p_sys_hw_msg);
320 
321     APPL_TRACE_DEBUG("%s", __FUNCTION__);
322 
323     for (module_index = 0; module_index < BTA_SYS_MAX_HW_MODULES; module_index++)
324     {
325         if( bta_sys_cb.sys_hw_module_active &  ((UINT32)1 << module_index )) {
326             switch( module_index)
327                 {
328                 case BTA_SYS_HW_BLUETOOTH:
329                    /* Send BTA_SYS_HW_ERROR_EVT to DM */
330                    if (bta_sys_cb.sys_hw_cback[module_index] != NULL)
331                        bta_sys_cb.sys_hw_cback[module_index] (BTA_SYS_HW_ERROR_EVT);
332                     break;
333                 default:
334                     /* not yet supported */
335                     break;
336                 }
337         }
338     }
339 }
340 
341 
342 
343 /*******************************************************************************
344 **
345 ** Function         bta_sys_hw_enable
346 **
347 ** Description     this function is called after API enable and HW has been turned on
348 **
349 **
350 ** Returns          success or failure
351 **
352 *******************************************************************************/
353 
bta_sys_hw_api_enable(tBTA_SYS_HW_MSG * p_sys_hw_msg)354 void bta_sys_hw_api_enable( tBTA_SYS_HW_MSG *p_sys_hw_msg )
355 {
356     if ((!bta_sys_cb.sys_hw_module_active) && (bta_sys_cb.state != BTA_SYS_HW_ON))
357     {
358         /* register which HW module was turned on */
359         bta_sys_cb.sys_hw_module_active |=  ((UINT32)1 << p_sys_hw_msg->hw_module );
360 
361         tBTA_SYS_HW_MSG *p_msg;
362         if ((p_msg = (tBTA_SYS_HW_MSG *) GKI_getbuf(sizeof(tBTA_SYS_HW_MSG))) != NULL)
363         {
364             p_msg->hdr.event = BTA_SYS_EVT_ENABLED_EVT;
365             p_msg->hw_module = p_sys_hw_msg->hw_module;
366 
367             bta_sys_sendmsg(p_msg);
368         }
369     }
370     else
371     {
372         /* register which HW module was turned on */
373         bta_sys_cb.sys_hw_module_active |=  ((UINT32)1 << p_sys_hw_msg->hw_module );
374 
375         /* HW already in use, so directly notify the caller */
376         if (bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module ]!= NULL )
377             bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module ](  BTA_SYS_HW_ON_EVT   );
378     }
379 
380     APPL_TRACE_EVENT ("bta_sys_hw_api_enable for %d, active modules 0x%04X",
381                     p_sys_hw_msg->hw_module, bta_sys_cb.sys_hw_module_active);
382 
383 }
384 
385 /*******************************************************************************
386 **
387 ** Function         bta_sys_hw_disable
388 **
389 ** Description     if no other module is using the HW, this function will call ( if defined ) a user-macro to turn off the HW
390 **
391 **
392 ** Returns          success or failure
393 **
394 *******************************************************************************/
bta_sys_hw_api_disable(tBTA_SYS_HW_MSG * p_sys_hw_msg)395 void bta_sys_hw_api_disable(tBTA_SYS_HW_MSG *p_sys_hw_msg)
396 {
397     APPL_TRACE_DEBUG("bta_sys_hw_api_disable for %d, active modules: 0x%04X",
398         p_sys_hw_msg->hw_module, bta_sys_cb.sys_hw_module_active );
399 
400     /* make sure the related SW blocks were stopped */
401     bta_sys_disable( p_sys_hw_msg->hw_module );
402 
403 
404     /* register which module we turn off */
405     bta_sys_cb.sys_hw_module_active &=  ~((UINT32)1 << p_sys_hw_msg->hw_module );
406 
407 
408     /* if there are still some SW modules using the HW, just provide an answer to the calling */
409     if( bta_sys_cb.sys_hw_module_active != 0  )
410     {
411         /*  if there are still some SW modules using the HW,  directly notify the caller */
412         if( bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module ]!= NULL )
413             bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module ](  BTA_SYS_HW_OFF_EVT   );
414     }
415     else
416     {
417         /* manually update the state of our system */
418         bta_sys_cb.state = BTA_SYS_HW_STOPPING;
419 
420         tBTA_SYS_HW_MSG *p_msg;
421         if ((p_msg = (tBTA_SYS_HW_MSG *) GKI_getbuf(sizeof(tBTA_SYS_HW_MSG))) != NULL)
422         {
423             p_msg->hdr.event = BTA_SYS_EVT_DISABLED_EVT;
424             p_msg->hw_module = p_sys_hw_msg->hw_module;
425 
426             bta_sys_sendmsg(p_msg);
427         }
428     }
429 
430 }
431 
432 
433 /*******************************************************************************
434 **
435 ** Function         bta_sys_hw_event_enabled
436 **
437 ** Description
438 **
439 **
440 ** Returns          success or failure
441 **
442 *******************************************************************************/
bta_sys_hw_evt_enabled(tBTA_SYS_HW_MSG * p_sys_hw_msg)443 void bta_sys_hw_evt_enabled(tBTA_SYS_HW_MSG *p_sys_hw_msg)
444 {
445     APPL_TRACE_EVENT("bta_sys_hw_evt_enabled for %i", p_sys_hw_msg->hw_module);
446     BTM_DeviceReset( NULL );
447 }
448 
449 
450 /*******************************************************************************
451 **
452 ** Function         bta_sys_hw_event_disabled
453 **
454 ** Description
455 **
456 **
457 ** Returns          success or failure
458 **
459 *******************************************************************************/
bta_sys_hw_evt_disabled(tBTA_SYS_HW_MSG * p_sys_hw_msg)460 void bta_sys_hw_evt_disabled(tBTA_SYS_HW_MSG *p_sys_hw_msg)
461 {
462     UINT8 hw_module_index;
463 
464     APPL_TRACE_DEBUG("bta_sys_hw_evt_disabled - module 0x%X", p_sys_hw_msg->hw_module);
465 
466     for (hw_module_index = 0; hw_module_index < BTA_SYS_MAX_HW_MODULES; hw_module_index++)
467     {
468         if (bta_sys_cb.sys_hw_cback[hw_module_index] != NULL)
469             bta_sys_cb.sys_hw_cback[hw_module_index] (BTA_SYS_HW_OFF_EVT);
470     }
471 }
472 
473 /*******************************************************************************
474 **
475 ** Function         bta_sys_hw_event_stack_enabled
476 **
477 ** Description     we receive this event once the SW side is ready ( stack, FW download,... ),
478 **                       i.e. we can really start using the device. So notify the app.
479 **
480 ** Returns          success or failure
481 **
482 *******************************************************************************/
bta_sys_hw_evt_stack_enabled(tBTA_SYS_HW_MSG * p_sys_hw_msg)483 void bta_sys_hw_evt_stack_enabled(tBTA_SYS_HW_MSG *p_sys_hw_msg)
484 {
485     UINT8 hw_module_index;
486     UNUSED(p_sys_hw_msg);
487 
488     APPL_TRACE_DEBUG(" bta_sys_hw_evt_stack_enabled!notify the callers");
489 
490     for (hw_module_index = 0; hw_module_index < BTA_SYS_MAX_HW_MODULES; hw_module_index++ )
491     {
492         if (bta_sys_cb.sys_hw_cback[hw_module_index] != NULL)
493             bta_sys_cb.sys_hw_cback[hw_module_index] (BTA_SYS_HW_ON_EVT);
494     }
495 }
496 
497 
498 
499 
500 /*******************************************************************************
501 **
502 ** Function         bta_sys_event
503 **
504 ** Description      BTA event handler; called from task event handler.
505 **
506 **
507 ** Returns          void
508 **
509 *******************************************************************************/
bta_sys_event(BT_HDR * p_msg)510 void bta_sys_event(BT_HDR *p_msg)
511 {
512     UINT8       id;
513     BOOLEAN     freebuf = TRUE;
514 
515     APPL_TRACE_EVENT("BTA got event 0x%x", p_msg->event);
516 
517     /* get subsystem id from event */
518     id = (UINT8) (p_msg->event >> 8);
519 
520     /* verify id and call subsystem event handler */
521     if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL))
522     {
523         freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);
524     }
525     else
526     {
527         APPL_TRACE_WARNING("BTA got unregistered event id %d", id);
528     }
529 
530     if (freebuf)
531     {
532         GKI_freebuf(p_msg);
533     }
534 
535 }
536 
537 /*******************************************************************************
538 **
539 ** Function         bta_sys_register
540 **
541 ** Description      Called by other BTA subsystems to register their event
542 **                  handler.
543 **
544 **
545 ** Returns          void
546 **
547 *******************************************************************************/
bta_sys_register(UINT8 id,const tBTA_SYS_REG * p_reg)548 void bta_sys_register(UINT8 id, const tBTA_SYS_REG *p_reg)
549 {
550     bta_sys_cb.reg[id] = (tBTA_SYS_REG *) p_reg;
551     bta_sys_cb.is_reg[id] = TRUE;
552 }
553 
554 /*******************************************************************************
555 **
556 ** Function         bta_sys_deregister
557 **
558 ** Description      Called by other BTA subsystems to de-register
559 **                  handler.
560 **
561 **
562 ** Returns          void
563 **
564 *******************************************************************************/
bta_sys_deregister(UINT8 id)565 void bta_sys_deregister(UINT8 id)
566 {
567     bta_sys_cb.is_reg[id] = FALSE;
568 }
569 
570 /*******************************************************************************
571 **
572 ** Function         bta_sys_is_register
573 **
574 ** Description      Called by other BTA subsystems to get registeration
575 **                  status.
576 **
577 **
578 ** Returns          void
579 **
580 *******************************************************************************/
bta_sys_is_register(UINT8 id)581 BOOLEAN bta_sys_is_register(UINT8 id)
582 {
583     return bta_sys_cb.is_reg[id];
584 }
585 
586 /*******************************************************************************
587 **
588 ** Function         bta_sys_sendmsg
589 **
590 ** Description      Send a GKI message to BTA.  This function is designed to
591 **                  optimize sending of messages to BTA.  It is called by BTA
592 **                  API functions and call-in functions.
593 **
594 **
595 ** Returns          void
596 **
597 *******************************************************************************/
bta_sys_sendmsg(void * p_msg)598 void bta_sys_sendmsg(void *p_msg)
599 {
600     // There is a race condition that occurs if the stack is shut down while
601     // there is a procedure in progress that can schedule a task via this
602     // message queue. This causes |btu_bta_msg_queue| to get cleaned up before
603     // it gets used here; hence we check for NULL before using it.
604     if (btu_bta_msg_queue)
605         fixed_queue_enqueue(btu_bta_msg_queue, p_msg);
606 }
607 
608 /*******************************************************************************
609 **
610 ** Function         bta_sys_start_timer
611 **
612 ** Description      Start a protocol timer for the specified amount
613 **                  of time in milliseconds.
614 **
615 ** Returns          void
616 **
617 *******************************************************************************/
bta_alarm_cb(void * data)618 void bta_alarm_cb(void *data) {
619   assert(data != NULL);
620   TIMER_LIST_ENT *p_tle = (TIMER_LIST_ENT *)data;
621 
622   fixed_queue_enqueue(btu_bta_alarm_queue, p_tle);
623 }
624 
bta_sys_start_timer(TIMER_LIST_ENT * p_tle,UINT16 type,INT32 timeout_ms)625 void bta_sys_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout_ms) {
626   assert(p_tle != NULL);
627 
628   // Get the alarm for this p_tle.
629   pthread_mutex_lock(&bta_alarm_lock);
630   if (!hash_map_has_key(bta_alarm_hash_map, p_tle)) {
631     hash_map_set(bta_alarm_hash_map, p_tle, alarm_new());
632   }
633   pthread_mutex_unlock(&bta_alarm_lock);
634 
635   alarm_t *alarm = hash_map_get(bta_alarm_hash_map, p_tle);
636   if (alarm == NULL) {
637     LOG_ERROR("%s unable to create alarm.", __func__);
638     return;
639   }
640 
641   p_tle->event = type;
642   p_tle->ticks = timeout_ms;
643   alarm_set(alarm, (period_ms_t)timeout_ms, bta_alarm_cb, p_tle);
644 }
645 
hash_iter_ro_cb(hash_map_entry_t * hash_map_entry,void * context)646 bool hash_iter_ro_cb(hash_map_entry_t *hash_map_entry, void *context)
647 {
648     alarm_t *alarm = (alarm_t *)hash_map_entry->data;
649     period_ms_t *p_remaining_ms = (period_ms_t*)context;
650     *p_remaining_ms += alarm_get_remaining_ms(alarm);
651     return true;
652 }
653 
bta_sys_get_remaining_ticks(TIMER_LIST_ENT * p_target_tle)654 UINT32 bta_sys_get_remaining_ticks(TIMER_LIST_ENT *p_target_tle)
655 {
656     period_ms_t remaining_ms = 0;
657     pthread_mutex_lock(&bta_alarm_lock);
658     // Get the alarm for this p_tle
659     hash_map_foreach(bta_alarm_hash_map, hash_iter_ro_cb, &remaining_ms);
660     pthread_mutex_unlock(&bta_alarm_lock);
661     return remaining_ms;
662 }
663 
664 
665 /*******************************************************************************
666 **
667 ** Function         bta_sys_stop_timer
668 **
669 ** Description      Stop a BTA timer.
670 **
671 ** Returns          void
672 **
673 *******************************************************************************/
bta_sys_stop_timer(TIMER_LIST_ENT * p_tle)674 void bta_sys_stop_timer(TIMER_LIST_ENT *p_tle) {
675   assert(p_tle != NULL);
676 
677   alarm_t *alarm = hash_map_get(bta_alarm_hash_map, p_tle);
678   if (alarm == NULL) {
679     LOG_DEBUG("%s expected alarm was not in bta alarm hash map.", __func__);
680     return;
681   }
682   alarm_cancel(alarm);
683 }
684 
685 /*******************************************************************************
686 **
687 ** Function         bta_sys_disable
688 **
689 ** Description      For each registered subsystem execute its disable function.
690 **
691 ** Returns          void
692 **
693 *******************************************************************************/
bta_sys_disable(tBTA_SYS_HW_MODULE module)694 void bta_sys_disable(tBTA_SYS_HW_MODULE module)
695 {
696     int bta_id = 0;
697     int bta_id_max = 0;
698 
699     APPL_TRACE_DEBUG("bta_sys_disable: module %i", module);
700 
701     switch( module )
702     {
703         case BTA_SYS_HW_BLUETOOTH:
704             bta_id = BTA_ID_DM;
705             bta_id_max = BTA_ID_BLUETOOTH_MAX;
706             break;
707         default:
708             APPL_TRACE_WARNING("bta_sys_disable: unkown module");
709             return;
710     }
711 
712     for ( ; bta_id <= bta_id_max; bta_id++)
713     {
714         if (bta_sys_cb.reg[bta_id] != NULL)
715         {
716             if (bta_sys_cb.is_reg[bta_id] == TRUE  &&  bta_sys_cb.reg[bta_id]->disable != NULL)
717             {
718                 (*bta_sys_cb.reg[bta_id]->disable)();
719             }
720         }
721     }
722 }
723 
724 /*******************************************************************************
725 **
726 ** Function         bta_sys_set_trace_level
727 **
728 ** Description      Set trace level for BTA
729 **
730 ** Returns          void
731 **
732 *******************************************************************************/
bta_sys_set_trace_level(UINT8 level)733 void bta_sys_set_trace_level(UINT8 level)
734 {
735     appl_trace_level = level;
736 }
737 
738 /*******************************************************************************
739 **
740 ** Function         bta_sys_get_sys_features
741 **
742 ** Description      Returns sys_features to other BTA modules.
743 **
744 ** Returns          sys_features
745 **
746 *******************************************************************************/
bta_sys_get_sys_features(void)747 UINT16 bta_sys_get_sys_features (void)
748 {
749     return bta_sys_cb.sys_features;
750 }
751