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