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
25#define LOG_TAG "bt_bta_sys_main"
26
27#include <base/logging.h>
28#include <pthread.h>
29#include <string.h>
30
31#include "bt_common.h"
32#include "bta_api.h"
33#include "bta_closure_int.h"
34#include "bta_sys.h"
35#include "bta_sys_int.h"
36#include "btm_api.h"
37#include "osi/include/alarm.h"
38#include "osi/include/fixed_queue.h"
39#include "osi/include/log.h"
40#include "osi/include/osi.h"
41#include "osi/include/thread.h"
42#include "utl.h"
43
44#if (defined BTA_AR_INCLUDED) && (BTA_AR_INCLUDED == true)
45#include "bta_ar_api.h"
46#endif
47
48/* system manager control block definition */
49tBTA_SYS_CB bta_sys_cb;
50
51fixed_queue_t* btu_bta_alarm_queue;
52extern thread_t* bt_workqueue_thread;
53
54/* trace level */
55/* TODO Hard-coded trace levels -  Needs to be configurable */
56uint8_t appl_trace_level = BT_TRACE_LEVEL_WARNING;  // APPL_INITIAL_TRACE_LEVEL;
57uint8_t btif_trace_level = BT_TRACE_LEVEL_WARNING;
58
59// Communication queue between btu_task and bta.
60extern fixed_queue_t* btu_bta_msg_queue;
61
62static const tBTA_SYS_REG bta_sys_hw_reg = {bta_sys_sm_execute, NULL};
63
64/* type for action functions */
65typedef void (*tBTA_SYS_ACTION)(tBTA_SYS_HW_MSG* p_data);
66
67/* action function list */
68const tBTA_SYS_ACTION bta_sys_action[] = {
69    /* device manager local device API events - cf bta_sys.h for events */
70    bta_sys_hw_api_enable,        /* 0  BTA_SYS_HW_API_ENABLE_EVT    */
71    bta_sys_hw_evt_enabled,       /* 1  BTA_SYS_HW_EVT_ENABLED_EVT */
72    bta_sys_hw_evt_stack_enabled, /* 2  BTA_SYS_HW_EVT_STACK_ENABLED_EVT */
73    bta_sys_hw_api_disable,       /* 3  BTA_SYS_HW_API_DISABLE_EVT     */
74    bta_sys_hw_evt_disabled,      /* 4  BTA_SYS_HW_EVT_DISABLED_EVT  */
75    bta_sys_hw_error              /* 5   BTA_SYS_HW_ERROR_EVT  */
76};
77
78/* state machine action enumeration list */
79enum {
80  /* device manager local device API events */
81  BTA_SYS_HW_API_ENABLE,
82  BTA_SYS_HW_EVT_ENABLED,
83  BTA_SYS_HW_EVT_STACK_ENABLED,
84  BTA_SYS_HW_API_DISABLE,
85  BTA_SYS_HW_EVT_DISABLED,
86  BTA_SYS_HW_ERROR
87};
88
89#define BTA_SYS_NUM_ACTIONS (BTA_SYS_MAX_EVT & 0x00ff)
90#define BTA_SYS_IGNORE BTA_SYS_NUM_ACTIONS
91
92/* state table information */
93#define BTA_SYS_ACTIONS 2    /* number of actions */
94#define BTA_SYS_NEXT_STATE 2 /* position of next state */
95#define BTA_SYS_NUM_COLS 3   /* number of columns in state tables */
96
97/* state table for OFF state */
98const uint8_t bta_sys_hw_off[][BTA_SYS_NUM_COLS] = {
99    /* Event                    Action 1               Action 2
100       Next State */
101    /* API_ENABLE    */ {BTA_SYS_HW_API_ENABLE, BTA_SYS_IGNORE,
102                         BTA_SYS_HW_STARTING},
103    /* EVT_ENABLED   */ {BTA_SYS_IGNORE, BTA_SYS_IGNORE, BTA_SYS_HW_STARTING},
104    /* STACK_ENABLED */ {BTA_SYS_IGNORE, BTA_SYS_IGNORE, BTA_SYS_HW_ON},
105    /* API_DISABLE   */ {BTA_SYS_HW_EVT_DISABLED, BTA_SYS_IGNORE,
106                         BTA_SYS_HW_OFF},
107    /* EVT_DISABLED  */ {BTA_SYS_IGNORE, BTA_SYS_IGNORE, BTA_SYS_HW_OFF},
108    /* EVT_ERROR     */ {BTA_SYS_IGNORE, BTA_SYS_IGNORE, BTA_SYS_HW_OFF}};
109
110const uint8_t bta_sys_hw_starting[][BTA_SYS_NUM_COLS] = {
111    /* Event                    Action 1                   Action 2
112       Next State */
113    /* API_ENABLE    */ {BTA_SYS_IGNORE, BTA_SYS_IGNORE,
114                         BTA_SYS_HW_STARTING}, /* wait for completion event */
115    /* EVT_ENABLED   */ {BTA_SYS_HW_EVT_ENABLED, BTA_SYS_IGNORE,
116                         BTA_SYS_HW_STARTING},
117    /* STACK_ENABLED */ {BTA_SYS_HW_EVT_STACK_ENABLED, BTA_SYS_IGNORE,
118                         BTA_SYS_HW_ON},
119    /* API_DISABLE   */ {BTA_SYS_IGNORE, BTA_SYS_IGNORE,
120                         BTA_SYS_HW_STOPPING}, /* successive disable/enable:
121                                                  change state wait for
122                                                  completion to disable */
123    /* EVT_DISABLED  */ {BTA_SYS_HW_EVT_DISABLED, BTA_SYS_HW_API_ENABLE,
124                         BTA_SYS_HW_STARTING}, /* successive enable/disable:
125                                                  notify, then restart HW */
126    /* EVT_ERROR */ {BTA_SYS_HW_ERROR, BTA_SYS_IGNORE, BTA_SYS_HW_ON}};
127
128const uint8_t bta_sys_hw_on[][BTA_SYS_NUM_COLS] = {
129    /* Event                    Action 1                   Action 2
130       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   */
135    {BTA_SYS_HW_API_DISABLE, BTA_SYS_IGNORE,
136     BTA_SYS_HW_ON}, /* don't change the state here, as some
137                        other modules might be active */
138    /* EVT_DISABLED */ {BTA_SYS_HW_ERROR, BTA_SYS_IGNORE, BTA_SYS_HW_ON},
139    /* EVT_ERROR */ {BTA_SYS_HW_ERROR, BTA_SYS_IGNORE, BTA_SYS_HW_ON}};
140
141const uint8_t bta_sys_hw_stopping[][BTA_SYS_NUM_COLS] = {
142    /* Event                    Action 1                   Action 2
143       Next State */
144    /* API_ENABLE    */ {BTA_SYS_IGNORE, BTA_SYS_IGNORE,
145                         BTA_SYS_HW_STARTING}, /* change state, and wait for
146                                                  completion event to enable */
147    /* EVT_ENABLED   */ {BTA_SYS_HW_EVT_ENABLED, BTA_SYS_IGNORE,
148                         BTA_SYS_HW_STOPPING}, /* successive enable/disable:
149                                                  finish the enable before
150                                                  disabling */
151    /* STACK_ENABLED */ {BTA_SYS_HW_EVT_STACK_ENABLED, BTA_SYS_HW_API_DISABLE,
152                         BTA_SYS_HW_STOPPING}, /* successive enable/disable:
153                                                  notify, then stop */
154    /* API_DISABLE   */ {BTA_SYS_IGNORE, BTA_SYS_IGNORE,
155                         BTA_SYS_HW_STOPPING}, /* wait for completion event */
156    /* EVT_DISABLED  */ {BTA_SYS_HW_EVT_DISABLED, BTA_SYS_IGNORE,
157                         BTA_SYS_HW_OFF},
158    /* EVT_ERROR     */ {BTA_SYS_HW_API_DISABLE, BTA_SYS_IGNORE,
159                         BTA_SYS_HW_STOPPING}};
160
161typedef const uint8_t (*tBTA_SYS_ST_TBL)[BTA_SYS_NUM_COLS];
162
163/* state table */
164const tBTA_SYS_ST_TBL bta_sys_st_tbl[] = {bta_sys_hw_off, bta_sys_hw_starting,
165                                          bta_sys_hw_on, bta_sys_hw_stopping};
166
167/*******************************************************************************
168 *
169 * Function         bta_sys_init
170 *
171 * Description      BTA initialization; called from task initialization.
172 *
173 *
174 * Returns          void
175 *
176 ******************************************************************************/
177void bta_sys_init(void) {
178  memset(&bta_sys_cb, 0, sizeof(tBTA_SYS_CB));
179
180  btu_bta_alarm_queue = fixed_queue_new(SIZE_MAX);
181
182  alarm_register_processing_queue(btu_bta_alarm_queue, bt_workqueue_thread);
183
184  appl_trace_level = APPL_INITIAL_TRACE_LEVEL;
185
186  /* register BTA SYS message handler */
187  bta_sys_register(BTA_ID_SYS, &bta_sys_hw_reg);
188
189  /* register for BTM notifications */
190  BTM_RegisterForDeviceStatusNotif((tBTM_DEV_STATUS_CB*)&bta_sys_hw_btm_cback);
191
192#if (defined BTA_AR_INCLUDED) && (BTA_AR_INCLUDED == true)
193  bta_ar_init();
194#endif
195
196  bta_closure_init(bta_sys_register, bta_sys_sendmsg);
197}
198
199void bta_sys_free(void) {
200  alarm_unregister_processing_queue(btu_bta_alarm_queue);
201  fixed_queue_free(btu_bta_alarm_queue, NULL);
202  btu_bta_alarm_queue = NULL;
203}
204
205/*******************************************************************************
206 *
207 * Function         bta_dm_sm_execute
208 *
209 * Description      State machine event handling function for DM
210 *
211 *
212 * Returns          void
213 *
214 ******************************************************************************/
215bool bta_sys_sm_execute(BT_HDR* p_msg) {
216  bool freebuf = true;
217  tBTA_SYS_ST_TBL state_table;
218  uint8_t action;
219  int i;
220
221  APPL_TRACE_EVENT("bta_sys_sm_execute state:%d, event:0x%x", bta_sys_cb.state,
222                   p_msg->event);
223
224  /* look up the state table for the current state */
225  state_table = bta_sys_st_tbl[bta_sys_cb.state];
226  /* update state */
227  bta_sys_cb.state = state_table[p_msg->event & 0x00ff][BTA_SYS_NEXT_STATE];
228
229  /* execute action functions */
230  for (i = 0; i < BTA_SYS_ACTIONS; i++) {
231    action = state_table[p_msg->event & 0x00ff][i];
232    if (action != BTA_SYS_IGNORE) {
233      (*bta_sys_action[action])((tBTA_SYS_HW_MSG*)p_msg);
234    } else {
235      break;
236    }
237  }
238  return freebuf;
239}
240
241void bta_sys_hw_register(tBTA_SYS_HW_MODULE module, tBTA_SYS_HW_CBACK* cback) {
242  bta_sys_cb.sys_hw_cback[module] = cback;
243}
244
245void bta_sys_hw_unregister(tBTA_SYS_HW_MODULE module) {
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
254 *                 status notifications
255 *
256 *
257 * Returns
258 *
259 ******************************************************************************/
260void bta_sys_hw_btm_cback(tBTM_DEV_STATUS status) {
261  tBTA_SYS_HW_MSG* sys_event =
262      (tBTA_SYS_HW_MSG*)osi_malloc(sizeof(tBTA_SYS_HW_MSG));
263
264  APPL_TRACE_DEBUG("%s was called with parameter: %i", __func__, status);
265
266  /* send a message to BTA SYS */
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_and_reset((void**)&sys_event);
274  }
275
276  if (sys_event) bta_sys_sendmsg(sys_event);
277}
278
279/*******************************************************************************
280 *
281 * Function         bta_sys_hw_error
282 *
283 * Description     In case the HW device stops answering... Try to turn it off,
284 *                 then re-enable all
285 *                      previously active SW modules.
286 *
287 * Returns          success or failure
288 *
289 ******************************************************************************/
290void bta_sys_hw_error(UNUSED_ATTR tBTA_SYS_HW_MSG* p_sys_hw_msg) {
291  uint8_t module_index;
292
293  APPL_TRACE_DEBUG("%s", __func__);
294
295  for (module_index = 0; module_index < BTA_SYS_MAX_HW_MODULES;
296       module_index++) {
297    if (bta_sys_cb.sys_hw_module_active & ((uint32_t)1 << module_index)) {
298      switch (module_index) {
299        case BTA_SYS_HW_BLUETOOTH:
300          /* Send BTA_SYS_HW_ERROR_EVT to DM */
301          if (bta_sys_cb.sys_hw_cback[module_index] != NULL)
302            bta_sys_cb.sys_hw_cback[module_index](BTA_SYS_HW_ERROR_EVT);
303          break;
304        default:
305          /* not yet supported */
306          break;
307      }
308    }
309  }
310}
311
312/*******************************************************************************
313 *
314 * Function         bta_sys_hw_enable
315 *
316 * Description     this function is called after API enable and HW has been
317 *                 turned on
318 *
319 *
320 * Returns          success or failure
321 *
322 ******************************************************************************/
323
324void bta_sys_hw_api_enable(tBTA_SYS_HW_MSG* p_sys_hw_msg) {
325  if ((!bta_sys_cb.sys_hw_module_active) &&
326      (bta_sys_cb.state != BTA_SYS_HW_ON)) {
327    /* register which HW module was turned on */
328    bta_sys_cb.sys_hw_module_active |= ((uint32_t)1 << p_sys_hw_msg->hw_module);
329
330    tBTA_SYS_HW_MSG* p_msg =
331        (tBTA_SYS_HW_MSG*)osi_malloc(sizeof(tBTA_SYS_HW_MSG));
332    p_msg->hdr.event = BTA_SYS_EVT_ENABLED_EVT;
333    p_msg->hw_module = p_sys_hw_msg->hw_module;
334
335    bta_sys_sendmsg(p_msg);
336  } else {
337    /* register which HW module was turned on */
338    bta_sys_cb.sys_hw_module_active |= ((uint32_t)1 << p_sys_hw_msg->hw_module);
339
340    /* HW already in use, so directly notify the caller */
341    if (bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module] != NULL)
342      bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module](BTA_SYS_HW_ON_EVT);
343  }
344
345  APPL_TRACE_EVENT("bta_sys_hw_api_enable for %d, active modules 0x%04X",
346                   p_sys_hw_msg->hw_module, bta_sys_cb.sys_hw_module_active);
347}
348
349/*******************************************************************************
350 *
351 * Function         bta_sys_hw_disable
352 *
353 * Description     if no other module is using the HW, this function will call
354 *                 (if defined) a user-macro to turn off the HW
355 *
356 *
357 * Returns          success or failure
358 *
359 ******************************************************************************/
360void bta_sys_hw_api_disable(tBTA_SYS_HW_MSG* p_sys_hw_msg) {
361  APPL_TRACE_DEBUG("bta_sys_hw_api_disable for %d, active modules: 0x%04X",
362                   p_sys_hw_msg->hw_module, bta_sys_cb.sys_hw_module_active);
363
364  /* make sure the related SW blocks were stopped */
365  bta_sys_disable(p_sys_hw_msg->hw_module);
366
367  /* register which module we turn off */
368  bta_sys_cb.sys_hw_module_active &= ~((uint32_t)1 << p_sys_hw_msg->hw_module);
369
370  /* if there are still some SW modules using the HW, just provide an answer to
371   * the calling */
372  if (bta_sys_cb.sys_hw_module_active != 0) {
373    /*  if there are still some SW modules using the HW,  directly notify the
374     * caller */
375    if (bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module] != NULL)
376      bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module](BTA_SYS_HW_OFF_EVT);
377  } else {
378    /* manually update the state of our system */
379    bta_sys_cb.state = BTA_SYS_HW_STOPPING;
380
381    tBTA_SYS_HW_MSG* p_msg =
382        (tBTA_SYS_HW_MSG*)osi_malloc(sizeof(tBTA_SYS_HW_MSG));
383    p_msg->hdr.event = BTA_SYS_EVT_DISABLED_EVT;
384    p_msg->hw_module = p_sys_hw_msg->hw_module;
385
386    bta_sys_sendmsg(p_msg);
387  }
388}
389
390/*******************************************************************************
391 *
392 * Function         bta_sys_hw_event_enabled
393 *
394 * Description
395 *
396 *
397 * Returns          success or failure
398 *
399 ******************************************************************************/
400void bta_sys_hw_evt_enabled(tBTA_SYS_HW_MSG* p_sys_hw_msg) {
401  APPL_TRACE_EVENT("bta_sys_hw_evt_enabled for %i", p_sys_hw_msg->hw_module);
402  BTM_DeviceReset(NULL);
403}
404
405/*******************************************************************************
406 *
407 * Function         bta_sys_hw_event_disabled
408 *
409 * Description
410 *
411 *
412 * Returns          success or failure
413 *
414 ******************************************************************************/
415void bta_sys_hw_evt_disabled(tBTA_SYS_HW_MSG* p_sys_hw_msg) {
416  uint8_t hw_module_index;
417
418  APPL_TRACE_DEBUG("bta_sys_hw_evt_disabled - module 0x%X",
419                   p_sys_hw_msg->hw_module);
420
421  for (hw_module_index = 0; hw_module_index < BTA_SYS_MAX_HW_MODULES;
422       hw_module_index++) {
423    if (bta_sys_cb.sys_hw_cback[hw_module_index] != NULL)
424      bta_sys_cb.sys_hw_cback[hw_module_index](BTA_SYS_HW_OFF_EVT);
425  }
426}
427
428/*******************************************************************************
429 *
430 * Function         bta_sys_hw_event_stack_enabled
431 *
432 * Description     we receive this event once the SW side is ready (stack, FW
433 *                 download,... ), i.e. we can really start using the device. So
434 *                 notify the app.
435 *
436 * Returns          success or failure
437 *
438 ******************************************************************************/
439void bta_sys_hw_evt_stack_enabled(UNUSED_ATTR tBTA_SYS_HW_MSG* p_sys_hw_msg) {
440  uint8_t hw_module_index;
441
442  APPL_TRACE_DEBUG(" bta_sys_hw_evt_stack_enabled!notify the callers");
443
444  for (hw_module_index = 0; hw_module_index < BTA_SYS_MAX_HW_MODULES;
445       hw_module_index++) {
446    if (bta_sys_cb.sys_hw_cback[hw_module_index] != NULL)
447      bta_sys_cb.sys_hw_cback[hw_module_index](BTA_SYS_HW_ON_EVT);
448  }
449}
450
451/*******************************************************************************
452 *
453 * Function         bta_sys_event
454 *
455 * Description      BTA event handler; called from task event handler.
456 *
457 *
458 * Returns          void
459 *
460 ******************************************************************************/
461void bta_sys_event(BT_HDR* p_msg) {
462  uint8_t id;
463  bool freebuf = true;
464
465  APPL_TRACE_EVENT("%s: Event 0x%x", __func__, p_msg->event);
466
467  /* get subsystem id from event */
468  id = (uint8_t)(p_msg->event >> 8);
469
470  /* verify id and call subsystem event handler */
471  if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL)) {
472    freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);
473  } else {
474    APPL_TRACE_WARNING("%s: Received unregistered event id %d", __func__, id);
475  }
476
477  if (freebuf) {
478    osi_free(p_msg);
479  }
480}
481
482/*******************************************************************************
483 *
484 * Function         bta_sys_register
485 *
486 * Description      Called by other BTA subsystems to register their event
487 *                  handler.
488 *
489 *
490 * Returns          void
491 *
492 ******************************************************************************/
493void bta_sys_register(uint8_t id, const tBTA_SYS_REG* p_reg) {
494  bta_sys_cb.reg[id] = (tBTA_SYS_REG*)p_reg;
495  bta_sys_cb.is_reg[id] = true;
496}
497
498/*******************************************************************************
499 *
500 * Function         bta_sys_deregister
501 *
502 * Description      Called by other BTA subsystems to de-register
503 *                  handler.
504 *
505 *
506 * Returns          void
507 *
508 ******************************************************************************/
509void bta_sys_deregister(uint8_t id) { bta_sys_cb.is_reg[id] = false; }
510
511/*******************************************************************************
512 *
513 * Function         bta_sys_is_register
514 *
515 * Description      Called by other BTA subsystems to get registeration
516 *                  status.
517 *
518 *
519 * Returns          void
520 *
521 ******************************************************************************/
522bool bta_sys_is_register(uint8_t id) { return bta_sys_cb.is_reg[id]; }
523
524/*******************************************************************************
525 *
526 * Function         bta_sys_sendmsg
527 *
528 * Description      Send a GKI message to BTA.  This function is designed to
529 *                  optimize sending of messages to BTA.  It is called by BTA
530 *                  API functions and call-in functions.
531 *
532 *
533 * Returns          void
534 *
535 ******************************************************************************/
536void bta_sys_sendmsg(void* p_msg) {
537  // There is a race condition that occurs if the stack is shut down while
538  // there is a procedure in progress that can schedule a task via this
539  // message queue. This causes |btu_bta_msg_queue| to get cleaned up before
540  // it gets used here; hence we check for NULL before using it.
541  if (btu_bta_msg_queue) fixed_queue_enqueue(btu_bta_msg_queue, p_msg);
542}
543
544/*******************************************************************************
545 *
546 * Function         bta_sys_start_timer
547 *
548 * Description      Start a protocol timer for the specified amount
549 *                  of time in milliseconds.
550 *
551 * Returns          void
552 *
553 ******************************************************************************/
554void bta_sys_start_timer(alarm_t* alarm, period_ms_t interval, uint16_t event,
555                         uint16_t layer_specific) {
556  BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
557
558  p_buf->event = event;
559  p_buf->layer_specific = layer_specific;
560  alarm_set_on_queue(alarm, interval, bta_sys_sendmsg, p_buf,
561                     btu_bta_alarm_queue);
562}
563
564/*******************************************************************************
565 *
566 * Function         bta_sys_disable
567 *
568 * Description      For each registered subsystem execute its disable function.
569 *
570 * Returns          void
571 *
572 ******************************************************************************/
573void bta_sys_disable(tBTA_SYS_HW_MODULE module) {
574  int bta_id = 0;
575  int bta_id_max = 0;
576
577  APPL_TRACE_DEBUG("bta_sys_disable: module %i", module);
578
579  switch (module) {
580    case BTA_SYS_HW_BLUETOOTH:
581      bta_id = BTA_ID_DM;
582      bta_id_max = BTA_ID_BLUETOOTH_MAX;
583      break;
584    default:
585      APPL_TRACE_WARNING("bta_sys_disable: unkown module");
586      return;
587  }
588
589  for (; bta_id <= bta_id_max; bta_id++) {
590    if (bta_sys_cb.reg[bta_id] != NULL) {
591      if (bta_sys_cb.is_reg[bta_id] == true &&
592          bta_sys_cb.reg[bta_id]->disable != NULL) {
593        (*bta_sys_cb.reg[bta_id]->disable)();
594      }
595    }
596  }
597}
598
599/*******************************************************************************
600 *
601 * Function         bta_sys_set_trace_level
602 *
603 * Description      Set trace level for BTA
604 *
605 * Returns          void
606 *
607 ******************************************************************************/
608void bta_sys_set_trace_level(uint8_t level) { appl_trace_level = level; }
609
610/*******************************************************************************
611 *
612 * Function         bta_sys_get_sys_features
613 *
614 * Description      Returns sys_features to other BTA modules.
615 *
616 * Returns          sys_features
617 *
618 ******************************************************************************/
619uint16_t bta_sys_get_sys_features(void) { return bta_sys_cb.sys_features; }
620