Home | History | Annotate | Download | only in sys
      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 *******************************************************************************/
    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 
    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 *******************************************************************************/
    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 
    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 
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 
    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 
    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 
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    747 UINT16 bta_sys_get_sys_features (void)
    748 {
    749     return bta_sys_cb.sys_features;
    750 }
    751