• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 == 1)
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 #include "esp_log.h"
48 
49 #define TAG "BTASYS"
50 /* system manager control block definition */
51 #if BTA_DYNAMIC_MEMORY == 0
52 tBTA_SYS_CB bta_sys_cb;
53 #else
54 tBTA_SYS_CB *bta_sys_cb_ptr;
55 #endif
56 // tBTA_SYS_CB bta_sys_cb = {0};
57 hash_map_t *bta_alarm_hash_map;
58 size_t BTA_ALARM_HASH_MAP_SIZE = 17;
59 osi_mutex_t bta_alarm_lock;
60 // extern thread_t *bt_workqueue_thread;
61 
62 /* trace level */
63 /* TODO Bluedroid - Hard-coded trace levels -  Needs to be configurable */
64 UINT8 appl_trace_level = APPL_INITIAL_TRACE_LEVEL;
65 UINT8 btif_trace_level = BTIF_INITIAL_TRACE_LEVEL;
66 
67 void btu_bta_alarm_ready(fixed_queue_t *queue);
68 
69 tBTA_SYS_REG bta_sys_hw_reg = {
70     bta_sys_sm_execute,
71     NULL
72 };
73 
74 
75 /* type for action functions */
76 typedef void (*tBTA_SYS_ACTION)(tBTA_SYS_HW_MSG *p_data);
77 
78 /* action function list */
79 tBTA_SYS_ACTION bta_sys_action[] = {
80     /* device manager local device API events - cf bta/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     /* device manager local device API events */
92     BTA_SYS_HW_API_ENABLE,
93     BTA_SYS_HW_EVT_ENABLED,
94     BTA_SYS_HW_EVT_STACK_ENABLED,
95     BTA_SYS_HW_API_DISABLE,
96     BTA_SYS_HW_EVT_DISABLED,
97     BTA_SYS_HW_ERROR
98 };
99 
100 #define BTA_SYS_NUM_ACTIONS  (BTA_SYS_MAX_EVT & 0x00ff)
101 #define BTA_SYS_IGNORE       BTA_SYS_NUM_ACTIONS
102 
103 /* state table information */
104 #define BTA_SYS_ACTIONS              2       /* number of actions */
105 #define BTA_SYS_NEXT_STATE           2       /* position of next state */
106 #define BTA_SYS_NUM_COLS             3       /* number of columns in state tables */
107 
108 
109 /* state table for OFF state */
110 UINT8 bta_sys_hw_off[][BTA_SYS_NUM_COLS] = {
111     /* Event                    Action 1               Action 2             Next State */
112     /* API_ENABLE    */  {BTA_SYS_HW_API_ENABLE,    BTA_SYS_IGNORE,     BTA_SYS_HW_STARTING},
113     /* EVT_ENABLED   */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_STARTING},
114     /* STACK_ENABLED */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_ON},
115     /* API_DISABLE   */  {BTA_SYS_HW_EVT_DISABLED,  BTA_SYS_IGNORE,     BTA_SYS_HW_OFF},
116     /* EVT_DISABLED  */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_OFF},
117     /* EVT_ERROR     */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_OFF}
118 };
119 
120 UINT8 bta_sys_hw_starting[][BTA_SYS_NUM_COLS] = {
121     /* Event                    Action 1                   Action 2               Next State */
122     /* API_ENABLE    */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_STARTING}, /* wait for completion event */
123     /* EVT_ENABLED   */  {BTA_SYS_HW_EVT_ENABLED,       BTA_SYS_IGNORE,         BTA_SYS_HW_STARTING},
124     /* STACK_ENABLED */  {BTA_SYS_HW_EVT_STACK_ENABLED, BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
125     /* API_DISABLE   */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_STOPPING}, /* successive disable/enable: change state wait for completion to disable */
126     /* EVT_DISABLED  */  {BTA_SYS_HW_EVT_DISABLED,      BTA_SYS_HW_API_ENABLE,  BTA_SYS_HW_STARTING}, /* successive enable/disable: notify, then restart HW */
127     /* EVT_ERROR */      {BTA_SYS_HW_ERROR,             BTA_SYS_IGNORE,         BTA_SYS_HW_ON}
128 };
129 
130 UINT8 bta_sys_hw_on[][BTA_SYS_NUM_COLS] = {
131     /* Event                    Action 1                   Action 2               Next State */
132     /* API_ENABLE    */  {BTA_SYS_HW_API_ENABLE,        BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
133     /* EVT_ENABLED   */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
134     /* STACK_ENABLED */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
135     /* 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 */
136     /* EVT_DISABLED */   {BTA_SYS_HW_ERROR,             BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
137     /* EVT_ERROR */      {BTA_SYS_HW_ERROR,             BTA_SYS_IGNORE,         BTA_SYS_HW_ON}
138 };
139 
140 UINT8 bta_sys_hw_stopping[][BTA_SYS_NUM_COLS] = {
141     /* Event                    Action 1                   Action 2               Next State */
142     /* API_ENABLE    */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_STARTING}, /* change state, and wait for completion event to enable */
143     /* EVT_ENABLED   */  {BTA_SYS_HW_EVT_ENABLED,       BTA_SYS_IGNORE,         BTA_SYS_HW_STOPPING}, /* successive enable/disable: finish the enable before disabling */
144     /* STACK_ENABLED */  {BTA_SYS_HW_EVT_STACK_ENABLED, BTA_SYS_HW_API_DISABLE, BTA_SYS_HW_STOPPING}, /* successive enable/disable: notify, then stop */
145     /* API_DISABLE   */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_STOPPING}, /* wait for completion event */
146     /* EVT_DISABLED  */  {BTA_SYS_HW_EVT_DISABLED,      BTA_SYS_IGNORE,         BTA_SYS_HW_OFF},
147     /* EVT_ERROR     */  {BTA_SYS_HW_API_DISABLE,       BTA_SYS_IGNORE,         BTA_SYS_HW_STOPPING}
148 };
149 
150 typedef UINT8 (*tBTA_SYS_ST_TBL)[BTA_SYS_NUM_COLS];
151 
152 /* state table */
153 tBTA_SYS_ST_TBL bta_sys_st_tbl[] = {
154     bta_sys_hw_off,
155     bta_sys_hw_starting,
156     bta_sys_hw_on,
157     bta_sys_hw_stopping
158 };
159 
160 /*******************************************************************************
161 **
162 ** Function         bta_sys_init
163 **
164 ** Description      BTA initialization; called from task initialization.
165 **
166 **
167 ** Returns          void
168 **
169 *******************************************************************************/
bta_sys_init(void)170 void bta_sys_init(void)
171 {
172     memset(&bta_sys_cb, 0, sizeof(tBTA_SYS_CB));
173     osi_mutex_new(&bta_alarm_lock);
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     appl_trace_level = APPL_INITIAL_TRACE_LEVEL;
177     // LOS_TaskDelay(1);
178     /* register BTA SYS message handler */
179     bta_sys_register( BTA_ID_SYS,  &bta_sys_hw_reg);
180     /* register for BTM notifications */
181     BTM_RegisterForDeviceStatusNotif ((tBTM_DEV_STATUS_CB *)&bta_sys_hw_btm_cback );
182 
183 #if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == 1)
184     bta_ar_init();
185 #endif
186 
187 }
188 
bta_sys_free(void)189 void bta_sys_free(void)
190 {
191     hash_map_free(bta_alarm_hash_map);
192     osi_mutex_free(&bta_alarm_lock);
193 #if BTA_DYNAMIC_MEMORY
194     FREE_AND_RESET(bta_sys_cb_ptr);
195 #endif
196 }
197 
198 /*******************************************************************************
199 **
200 ** Function         bta_sys_sm_execute
201 **
202 ** Description      State machine event handling function for DM
203 **
204 **
205 ** Returns          void
206 **
207 *******************************************************************************/
bta_sys_sm_execute(BT_HDR * p_msg)208 BOOLEAN bta_sys_sm_execute(BT_HDR *p_msg)
209 {
210     BOOLEAN freebuf = 1;
211     tBTA_SYS_ST_TBL      state_table;
212     UINT8               action;
213     int                 i;
214 
215     APPL_TRACE_EVENT("bta_sys_sm_execute state:%d, event:0x%x\n",  bta_sys_cb.state, p_msg->event);
216 
217     /* look up the state table for the current state */
218     state_table = bta_sys_st_tbl[bta_sys_cb.state];
219     /* update state */
220     bta_sys_cb.state = state_table[p_msg->event & 0x00ff][BTA_SYS_NEXT_STATE];
221 
222     /* execute action functions */
223     for (i = 0; i < BTA_SYS_ACTIONS; i++) {
224         if ((action = state_table[p_msg->event & 0x00ff][i]) != BTA_SYS_IGNORE) {
225             (*bta_sys_action[action])( (tBTA_SYS_HW_MSG *) p_msg);
226         } else {
227             break;
228         }
229     }
230     return freebuf;
231 
232 }
233 
234 
bta_sys_hw_register(tBTA_SYS_HW_MODULE module,tBTA_SYS_HW_CBACK * cback)235 void bta_sys_hw_register( tBTA_SYS_HW_MODULE module, tBTA_SYS_HW_CBACK *cback)
236 {
237     bta_sys_cb.sys_hw_cback[module] = cback;
238 }
239 
240 
bta_sys_hw_unregister(tBTA_SYS_HW_MODULE module)241 void bta_sys_hw_unregister( tBTA_SYS_HW_MODULE module )
242 {
243     bta_sys_cb.sys_hw_cback[module] = NULL;
244 }
245 
246 /*******************************************************************************
247 **
248 ** Function         bta_sys_hw_btm_cback
249 **
250 ** Description     This function is registered by BTA SYS to BTM in order to get status notifications
251 **
252 **
253 ** Returns
254 **
255 *******************************************************************************/
bta_sys_hw_btm_cback(tBTM_DEV_STATUS status)256 void bta_sys_hw_btm_cback( tBTM_DEV_STATUS status )
257 {
258 
259     tBTA_SYS_HW_MSG *sys_event;
260 
261     APPL_TRACE_DEBUG(" bta_sys_hw_btm_cback was called with parameter: %i" , status );
262 
263     /* send a message to BTA SYS */
264     if ((sys_event = (tBTA_SYS_HW_MSG *) osi_malloc(sizeof(tBTA_SYS_HW_MSG))) != NULL) {
265         if (status == BTM_DEV_STATUS_UP) {
266             sys_event->hdr.event = BTA_SYS_EVT_STACK_ENABLED_EVT;
267         } else if (status == BTM_DEV_STATUS_DOWN) {
268             sys_event->hdr.event = BTA_SYS_ERROR_EVT;
269         } else {
270             /* BTM_DEV_STATUS_CMD_TOUT is ignored for now. */
271             osi_free (sys_event);
272             sys_event = NULL;
273         }
274 
275         if (sys_event) {
276             bta_sys_sendmsg(sys_event);
277         }
278     } else {
279         APPL_TRACE_DEBUG("ERROR bta_sys_hw_btm_cback couldn't send msg" );
280     }
281 }
282 
283 
284 
285 /*******************************************************************************
286 **
287 ** Function         bta_sys_hw_error
288 **
289 ** Description     In case the HW device stops answering... Try to turn it off, then re-enable all
290 **                      previously active SW modules.
291 **
292 ** Returns          success or failure
293 **
294 *******************************************************************************/
bta_sys_hw_error(tBTA_SYS_HW_MSG * p_sys_hw_msg)295 void bta_sys_hw_error(tBTA_SYS_HW_MSG *p_sys_hw_msg)
296 {
297     UINT8 module_index;
298     UNUSED(p_sys_hw_msg);
299 
300     APPL_TRACE_DEBUG("%s\n", __FUNCTION__);
301 
302     for (module_index = 0; module_index < BTA_SYS_MAX_HW_MODULES; module_index++) {
303         if ( bta_sys_cb.sys_hw_module_active &  ((UINT32)1 << module_index )) {
304             switch ( module_index) {
305             case BTA_SYS_HW_BLUETOOTH:
306                 /* Send BTA_SYS_HW_ERROR_EVT to DM */
307                 if (bta_sys_cb.sys_hw_cback[module_index] != NULL) {
308                     bta_sys_cb.sys_hw_cback[module_index] (BTA_SYS_HW_ERROR_EVT);
309                 }
310                 break;
311             default:
312                 /* not yet supported */
313                 break;
314             }
315         }
316     }
317 }
318 
319 
320 
321 /*******************************************************************************
322 **
323 ** Function         bta_sys_hw_enable
324 **
325 ** Description     this function is called after API enable and HW has been turned on
326 **
327 **
328 ** Returns          success or failure
329 **
330 *******************************************************************************/
331 
bta_sys_hw_api_enable(tBTA_SYS_HW_MSG * p_sys_hw_msg)332 void bta_sys_hw_api_enable( tBTA_SYS_HW_MSG *p_sys_hw_msg )
333 {
334     if ((!bta_sys_cb.sys_hw_module_active) && (bta_sys_cb.state != BTA_SYS_HW_ON)) {
335         /* register which HW module was turned on */
336         bta_sys_cb.sys_hw_module_active |=  ((UINT32)1 << p_sys_hw_msg->hw_module );
337 
338         tBTA_SYS_HW_MSG *p_msg;
339         if ((p_msg = (tBTA_SYS_HW_MSG *) osi_malloc(sizeof(tBTA_SYS_HW_MSG))) != NULL) {
340             p_msg->hdr.event = BTA_SYS_EVT_ENABLED_EVT;
341             p_msg->hw_module = p_sys_hw_msg->hw_module;
342 
343             bta_sys_sendmsg(p_msg);
344         }
345     } else {
346         /* register which HW module was turned on */
347         bta_sys_cb.sys_hw_module_active |=  ((UINT32)1 << p_sys_hw_msg->hw_module );
348 
349         /* HW already in use, so directly notify the caller */
350         if (bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module ] != NULL ) {
351             bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module ](  BTA_SYS_HW_ON_EVT   );
352         }
353     }
354 
355     APPL_TRACE_EVENT ("bta_sys_hw_api_enable for %d, active modules 0x%04X\n",
356                       p_sys_hw_msg->hw_module, bta_sys_cb.sys_hw_module_active);
357 
358 }
359 
360 /*******************************************************************************
361 **
362 ** Function         bta_sys_hw_disable
363 **
364 ** Description     if no other module is using the HW, this function will call ( if defined ) a user-macro to turn off the HW
365 **
366 **
367 ** Returns          success or failure
368 **
369 *******************************************************************************/
bta_sys_hw_api_disable(tBTA_SYS_HW_MSG * p_sys_hw_msg)370 void bta_sys_hw_api_disable(tBTA_SYS_HW_MSG *p_sys_hw_msg)
371 {
372     APPL_TRACE_DEBUG("bta_sys_hw_api_disable for %d, active modules: 0x%04X\n",
373                      p_sys_hw_msg->hw_module, bta_sys_cb.sys_hw_module_active );
374 
375     /* make sure the related SW blocks were stopped */
376     bta_sys_disable( p_sys_hw_msg->hw_module );
377 
378 
379     /* register which module we turn off */
380     bta_sys_cb.sys_hw_module_active &=  ~((UINT32)1 << p_sys_hw_msg->hw_module );
381 
382 
383     /* if there are still some SW modules using the HW, just provide an answer to the calling */
384     if ( bta_sys_cb.sys_hw_module_active != 0  ) {
385         /*  if there are still some SW modules using the HW,  directly notify the caller */
386         if ( bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module ] != NULL ) {
387             bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module ](  BTA_SYS_HW_OFF_EVT   );
388         }
389     } else {
390         /* manually update the state of our system */
391         bta_sys_cb.state = BTA_SYS_HW_STOPPING;
392 
393         tBTA_SYS_HW_MSG *p_msg;
394         if ((p_msg = (tBTA_SYS_HW_MSG *) osi_malloc(sizeof(tBTA_SYS_HW_MSG))) != NULL) {
395             p_msg->hdr.event = BTA_SYS_EVT_DISABLED_EVT;
396             p_msg->hw_module = p_sys_hw_msg->hw_module;
397 
398             bta_sys_sendmsg(p_msg);
399         }
400     }
401 
402 }
403 
404 
405 /*******************************************************************************
406 **
407 ** Function         bta_sys_hw_event_enabled
408 **
409 ** Description
410 **
411 **
412 ** Returns          success or failure
413 **
414 *******************************************************************************/
bta_sys_hw_evt_enabled(tBTA_SYS_HW_MSG * p_sys_hw_msg)415 void bta_sys_hw_evt_enabled(tBTA_SYS_HW_MSG *p_sys_hw_msg)
416 {
417     APPL_TRACE_EVENT("bta_sys_hw_evt_enabled for %i\n", p_sys_hw_msg->hw_module);
418     BTM_DeviceReset( NULL );
419 }
420 
421 
422 /*******************************************************************************
423 **
424 ** Function         bta_sys_hw_event_disabled
425 **
426 ** Description
427 **
428 **
429 ** Returns          success or failure
430 **
431 *******************************************************************************/
bta_sys_hw_evt_disabled(tBTA_SYS_HW_MSG * p_sys_hw_msg)432 void bta_sys_hw_evt_disabled(tBTA_SYS_HW_MSG *p_sys_hw_msg)
433 {
434     UINT8 hw_module_index;
435 
436     APPL_TRACE_DEBUG("bta_sys_hw_evt_disabled - module 0x%X\n", p_sys_hw_msg->hw_module);
437 
438     for (hw_module_index = 0; hw_module_index < BTA_SYS_MAX_HW_MODULES; hw_module_index++) {
439         if (bta_sys_cb.sys_hw_cback[hw_module_index] != NULL) {
440             bta_sys_cb.sys_hw_cback[hw_module_index] (BTA_SYS_HW_OFF_EVT);
441         }
442     }
443 }
444 
445 /*******************************************************************************
446 **
447 ** Function         bta_sys_hw_event_stack_enabled
448 **
449 ** Description     we receive this event once the SW side is ready ( stack, FW download,... ),
450 **                       i.e. we can really start using the device. So notify the app.
451 **
452 ** Returns          success or failure
453 **
454 *******************************************************************************/
bta_sys_hw_evt_stack_enabled(tBTA_SYS_HW_MSG * p_sys_hw_msg)455 void bta_sys_hw_evt_stack_enabled(tBTA_SYS_HW_MSG *p_sys_hw_msg)
456 {
457     UINT8 hw_module_index;
458     UNUSED(p_sys_hw_msg);
459 
460     APPL_TRACE_DEBUG(" bta_sys_hw_evt_stack_enabled!notify the callers\n");
461 
462     for (hw_module_index = 0; hw_module_index < BTA_SYS_MAX_HW_MODULES; hw_module_index++ ) {
463         if (bta_sys_cb.sys_hw_cback[hw_module_index] != NULL) {
464             bta_sys_cb.sys_hw_cback[hw_module_index] (BTA_SYS_HW_ON_EVT);
465         }
466     }
467 }
468 
469 
470 
471 
472 /*******************************************************************************
473 **
474 ** Function         bta_sys_event
475 **
476 ** Description      BTA event handler; called from task event handler.
477 **
478 **
479 ** Returns          void
480 **
481 *******************************************************************************/
bta_sys_event(void * param)482 void bta_sys_event(void * param)
483 {
484     BT_HDR *p_msg = (BT_HDR *)param;
485 
486     UINT8       id;
487     BOOLEAN     freebuf = 1;
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         //esp_rom_printf("\n bta_sys_event: %p!\n", *bta_sys_cb.reg[id]->evt_hdlr);
497         freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);
498     } else {
499         APPL_TRACE_WARNING("BTA got unregistered event id %d\n", id);
500     }
501 
502     if (freebuf) {
503         osi_free(p_msg);
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 *******************************************************************************/
bta_sys_register(UINT8 id,tBTA_SYS_REG * p_reg)518 void bta_sys_register(UINT8 id, tBTA_SYS_REG *p_reg)
519 {
520     bta_sys_cb.reg[id] = (tBTA_SYS_REG *) p_reg;
521     bta_sys_cb.is_reg[id] = 1;
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 *******************************************************************************/
bta_sys_deregister(UINT8 id)535 void bta_sys_deregister(UINT8 id)
536 {
537     bta_sys_cb.is_reg[id] = 0;
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 *******************************************************************************/
bta_sys_is_register(UINT8 id)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 *******************************************************************************/
bta_sys_sendmsg(void * p_msg)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, OSI_THREAD_MAX_TIMEOUT) == false) {
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 *******************************************************************************/
bta_alarm_cb(void * data)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, OSI_THREAD_MAX_TIMEOUT);
595 }
596 
bta_sys_start_timer(TIMER_LIST_ENT * p_tle,UINT16 type,INT32 timeout_ms)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         APPL_TRACE_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 
hash_iter_ro_cb(hash_map_entry_t * hash_map_entry,void * context)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 
bta_sys_get_remaining_ticks(TIMER_LIST_ENT * p_target_tle)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 *******************************************************************************/
bta_sys_stop_timer(TIMER_LIST_ENT * p_tle)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         APPL_TRACE_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_free_timer
663 **
664 ** Description      Stop and free a BTA timer.
665 **
666 ** Returns          void
667 **
668 *******************************************************************************/
bta_sys_free_timer(TIMER_LIST_ENT * p_tle)669 void bta_sys_free_timer(TIMER_LIST_ENT *p_tle)
670 {
671     assert(p_tle != NULL);
672 
673     osi_alarm_t *alarm = hash_map_get(bta_alarm_hash_map, p_tle);
674     if (alarm == NULL) {
675         APPL_TRACE_DEBUG("%s expected alarm was not in bta alarm hash map.", __func__);
676         return;
677     }
678     osi_alarm_cancel(alarm);
679     hash_map_erase(bta_alarm_hash_map, p_tle);
680 }
681 
682 /*******************************************************************************
683 **
684 ** Function         bta_sys_disable
685 **
686 ** Description      For each registered subsystem execute its disable function.
687 **
688 ** Returns          void
689 **
690 *******************************************************************************/
bta_sys_disable(tBTA_SYS_HW_MODULE module)691 void bta_sys_disable(tBTA_SYS_HW_MODULE module)
692 {
693     int bta_id = 0;
694     int bta_id_max = 0;
695 
696     APPL_TRACE_DEBUG("bta_sys_disable: module %i", module);
697 
698     switch ( module ) {
699     case BTA_SYS_HW_BLUETOOTH:
700         bta_id = BTA_ID_DM;
701         bta_id_max = BTA_ID_BLUETOOTH_MAX;
702         break;
703     default:
704         APPL_TRACE_WARNING("bta_sys_disable: unkown module");
705         return;
706     }
707 
708     for ( ; bta_id <= bta_id_max; bta_id++) {
709         if (bta_sys_cb.reg[bta_id] != NULL) {
710             if (bta_sys_cb.is_reg[bta_id] == true  &&  bta_sys_cb.reg[bta_id]->disable != NULL) {
711                 (*bta_sys_cb.reg[bta_id]->disable)();
712             }
713         }
714     }
715 }
716 
717 /*******************************************************************************
718 **
719 ** Function         bta_sys_set_trace_level
720 **
721 ** Description      Set trace level for BTA
722 **
723 ** Returns          void
724 **
725 *******************************************************************************/
bta_sys_set_trace_level(UINT8 level)726 void bta_sys_set_trace_level(UINT8 level)
727 {
728     appl_trace_level = level;
729 }
730 
731 /*******************************************************************************
732 **
733 ** Function         bta_sys_get_sys_features
734 **
735 ** Description      Returns sys_features to other BTA modules.
736 **
737 ** Returns          sys_features
738 **
739 *******************************************************************************/
bta_sys_get_sys_features(void)740 UINT16 bta_sys_get_sys_features (void)
741 {
742     return bta_sys_cb.sys_features;
743 }
744