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