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