btu_task.c revision 24ff5af9e40aaebc236bb6a16849c63bff0f23ba
1/****************************************************************************** 2 * 3 * Copyright (C) 1999-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#define LOG_TAG "btu_task" 20 21#include <assert.h> 22#include <stdlib.h> 23#include <stdio.h> 24#include <string.h> 25 26#include "alarm.h" 27#include "bt_target.h" 28#include "bt_trace.h" 29#include "bt_types.h" 30#include "bt_utils.h" 31#include "btif_common.h" 32#include "btm_api.h" 33#include "btm_int.h" 34#include "btu.h" 35#include "fixed_queue.h" 36#include "future.h" 37#include "gki.h" 38#include "hash_map.h" 39#include "hcimsgs.h" 40#include "l2c_int.h" 41#include "module.h" 42#include "osi.h" 43#include "osi/include/log.h" 44#include "sdpint.h" 45#include "thread.h" 46 47#include "port_api.h" 48#include "port_ext.h" 49 50#include "gap_int.h" 51 52#if (defined(BNEP_INCLUDED) && BNEP_INCLUDED == TRUE) 53#include "bnep_int.h" 54#endif 55 56#if (defined(PAN_INCLUDED) && PAN_INCLUDED == TRUE) 57#include "pan_int.h" 58#endif 59 60#if (defined(HID_HOST_INCLUDED) && HID_HOST_INCLUDED == TRUE ) 61#include "hidh_int.h" 62#endif 63 64#if (defined(AVDT_INCLUDED) && AVDT_INCLUDED == TRUE) 65#include "avdt_int.h" 66#else 67extern void avdt_rcv_sync_info (BT_HDR *p_buf); /* this is for hci_test */ 68#endif 69 70#if (defined(MCA_INCLUDED) && MCA_INCLUDED == TRUE) 71#include "mca_api.h" 72#include "mca_defs.h" 73#include "mca_int.h" 74#endif 75 76#include "bta_sys.h" 77 78#if (BLE_INCLUDED == TRUE) 79#include "gatt_int.h" 80#if (SMP_INCLUDED == TRUE) 81#include "smp_int.h" 82#endif 83#include "btm_ble_int.h" 84#endif 85 86extern void BTE_InitStack(void); 87 88/* Define BTU storage area 89*/ 90#if BTU_DYNAMIC_MEMORY == FALSE 91tBTU_CB btu_cb; 92#endif 93 94// Communication queue between btu_task and bta. 95extern fixed_queue_t *btu_bta_msg_queue; 96 97// Communication queue between btu_task and hci. 98extern fixed_queue_t *btu_hci_msg_queue; 99 100// General timer queue. 101extern fixed_queue_t *btu_general_alarm_queue; 102extern hash_map_t *btu_general_alarm_hash_map; 103extern pthread_mutex_t btu_general_alarm_lock; 104 105// Oneshot timer queue. 106extern fixed_queue_t *btu_oneshot_alarm_queue; 107extern hash_map_t *btu_oneshot_alarm_hash_map; 108extern pthread_mutex_t btu_oneshot_alarm_lock; 109 110// l2cap timer queue. 111extern fixed_queue_t *btu_l2cap_alarm_queue; 112extern hash_map_t *btu_l2cap_alarm_hash_map; 113extern pthread_mutex_t btu_l2cap_alarm_lock; 114 115extern fixed_queue_t *event_queue; 116extern fixed_queue_t *btif_msg_queue; 117 118extern thread_t *bt_workqueue_thread; 119 120/* Define a function prototype to allow a generic timeout handler */ 121typedef void (tUSER_TIMEOUT_FUNC) (TIMER_LIST_ENT *p_tle); 122 123static void btu_l2cap_alarm_process(TIMER_LIST_ENT *p_tle); 124static void btu_general_alarm_process(TIMER_LIST_ENT *p_tle); 125static void btu_bta_alarm_process(TIMER_LIST_ENT *p_tle); 126static void btu_hci_msg_process(BT_HDR *p_msg); 127 128void btu_hci_msg_ready(fixed_queue_t *queue, UNUSED_ATTR void *context) { 129 BT_HDR *p_msg = (BT_HDR *)fixed_queue_dequeue(queue); 130 btu_hci_msg_process(p_msg); 131} 132 133void btu_general_alarm_ready(fixed_queue_t *queue, UNUSED_ATTR void *context) { 134 TIMER_LIST_ENT *p_tle = (TIMER_LIST_ENT *)fixed_queue_dequeue(queue); 135 btu_general_alarm_process(p_tle); 136} 137 138void btu_oneshot_alarm_ready(fixed_queue_t *queue, UNUSED_ATTR void *context) { 139 TIMER_LIST_ENT *p_tle = (TIMER_LIST_ENT *)fixed_queue_dequeue(queue); 140 btu_general_alarm_process(p_tle); 141 142 switch (p_tle->event) { 143#if (defined(BLE_INCLUDED) && BLE_INCLUDED == TRUE) 144 case BTU_TTYPE_BLE_RANDOM_ADDR: 145 btm_ble_timeout(p_tle); 146 break; 147#endif 148 149 case BTU_TTYPE_USER_FUNC: 150 { 151 tUSER_TIMEOUT_FUNC *p_uf = (tUSER_TIMEOUT_FUNC *)p_tle->param; 152 (*p_uf)(p_tle); 153 } 154 break; 155 156 default: 157 // FAIL 158 BTM_TRACE_WARNING("Received unexpected oneshot timer event:0x%x\n", 159 p_tle->event); 160 break; 161 } 162} 163 164void btu_l2cap_alarm_ready(fixed_queue_t *queue, UNUSED_ATTR void *context) { 165 TIMER_LIST_ENT *p_tle = (TIMER_LIST_ENT *)fixed_queue_dequeue(queue); 166 btu_l2cap_alarm_process(p_tle); 167} 168 169void btu_bta_msg_ready(fixed_queue_t *queue, UNUSED_ATTR void *context) { 170 BT_HDR *p_msg = (BT_HDR *)fixed_queue_dequeue(queue); 171 bta_sys_event(p_msg); 172} 173 174void btu_bta_alarm_ready(fixed_queue_t *queue, UNUSED_ATTR void *context) { 175 TIMER_LIST_ENT *p_tle = (TIMER_LIST_ENT *)fixed_queue_dequeue(queue); 176 btu_bta_alarm_process(p_tle); 177} 178 179static void btu_hci_msg_process(BT_HDR *p_msg) { 180 /* Determine the input message type. */ 181 switch (p_msg->event & BT_EVT_MASK) 182 { 183 case BTU_POST_TO_TASK_NO_GOOD_HORRIBLE_HACK: // TODO(zachoverflow): remove this 184 ((post_to_task_hack_t *)(&p_msg->data[0]))->callback(p_msg); 185 break; 186 case BT_EVT_TO_BTU_HCI_ACL: 187 /* All Acl Data goes to L2CAP */ 188 l2c_rcv_acl_data (p_msg); 189 break; 190 191 case BT_EVT_TO_BTU_L2C_SEG_XMIT: 192 /* L2CAP segment transmit complete */ 193 l2c_link_segments_xmitted (p_msg); 194 break; 195 196 case BT_EVT_TO_BTU_HCI_SCO: 197#if BTM_SCO_INCLUDED == TRUE 198 btm_route_sco_data (p_msg); 199 break; 200#endif 201 202 case BT_EVT_TO_BTU_HCI_EVT: 203 btu_hcif_process_event ((UINT8)(p_msg->event & BT_SUB_EVT_MASK), p_msg); 204 GKI_freebuf(p_msg); 205 206#if (defined(HCILP_INCLUDED) && HCILP_INCLUDED == TRUE) 207 /* If host receives events which it doesn't response to, */ 208 /* host should start idle timer to enter sleep mode. */ 209 btu_check_bt_sleep (); 210#endif 211 break; 212 213 case BT_EVT_TO_BTU_HCI_CMD: 214 btu_hcif_send_cmd ((UINT8)(p_msg->event & BT_SUB_EVT_MASK), p_msg); 215 break; 216 217 default:; 218 int i = 0; 219 uint16_t mask = (UINT16) (p_msg->event & BT_EVT_MASK); 220 BOOLEAN handled = FALSE; 221 222 for (; !handled && i < BTU_MAX_REG_EVENT; i++) 223 { 224 if (btu_cb.event_reg[i].event_cb == NULL) 225 continue; 226 227 if (mask == btu_cb.event_reg[i].event_range) 228 { 229 if (btu_cb.event_reg[i].event_cb) 230 { 231 btu_cb.event_reg[i].event_cb(p_msg); 232 handled = TRUE; 233 } 234 } 235 } 236 237 if (handled == FALSE) 238 GKI_freebuf (p_msg); 239 240 break; 241 } 242 243} 244 245static void btu_bta_alarm_process(TIMER_LIST_ENT *p_tle) { 246 /* call timer callback */ 247 if (p_tle->p_cback) { 248 (*p_tle->p_cback)(p_tle); 249 } else if (p_tle->event) { 250 BT_HDR *p_msg; 251 if ((p_msg = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) { 252 p_msg->event = p_tle->event; 253 p_msg->layer_specific = 0; 254 bta_sys_sendmsg(p_msg); 255 } 256 } 257} 258 259void btu_task_start_up(UNUSED_ATTR void *context) { 260 BT_TRACE(TRACE_LAYER_BTU, TRACE_TYPE_API, 261 "btu_task pending for preload complete event"); 262 263 LOG_INFO("Bluetooth chip preload is complete"); 264 265 BT_TRACE(TRACE_LAYER_BTU, TRACE_TYPE_API, 266 "btu_task received preload complete event"); 267 268 /* Initialize the mandatory core stack control blocks 269 (BTU, BTM, L2CAP, and SDP) 270 */ 271 btu_init_core(); 272 273 /* Initialize any optional stack components */ 274 BTE_InitStack(); 275 276 bta_sys_init(); 277 278 /* Initialise platform trace levels at this point as BTE_InitStack() and bta_sys_init() 279 * reset the control blocks and preset the trace level with XXX_INITIAL_TRACE_LEVEL 280 */ 281#if ( BT_USE_TRACES==TRUE ) 282 module_init(get_module(BTE_LOGMSG_MODULE)); 283#endif 284 285 // Inform the bt jni thread initialization is ok. 286 btif_transfer_context(btif_init_ok, 0, NULL, 0, NULL); 287 288 fixed_queue_register_dequeue(btu_bta_msg_queue, 289 thread_get_reactor(bt_workqueue_thread), 290 btu_bta_msg_ready, 291 NULL); 292 293 fixed_queue_register_dequeue(btu_hci_msg_queue, 294 thread_get_reactor(bt_workqueue_thread), 295 btu_hci_msg_ready, 296 NULL); 297 298 fixed_queue_register_dequeue(btu_general_alarm_queue, 299 thread_get_reactor(bt_workqueue_thread), 300 btu_general_alarm_ready, 301 NULL); 302 303 fixed_queue_register_dequeue(btu_oneshot_alarm_queue, 304 thread_get_reactor(bt_workqueue_thread), 305 btu_oneshot_alarm_ready, 306 NULL); 307 308 fixed_queue_register_dequeue(btu_l2cap_alarm_queue, 309 thread_get_reactor(bt_workqueue_thread), 310 btu_l2cap_alarm_ready, 311 NULL); 312} 313 314void btu_task_shut_down(UNUSED_ATTR void *context) { 315 fixed_queue_unregister_dequeue(btu_bta_msg_queue); 316 fixed_queue_unregister_dequeue(btu_hci_msg_queue); 317 fixed_queue_unregister_dequeue(btu_general_alarm_queue); 318 fixed_queue_unregister_dequeue(btu_oneshot_alarm_queue); 319 fixed_queue_unregister_dequeue(btu_l2cap_alarm_queue); 320 321#if ( BT_USE_TRACES==TRUE ) 322 module_clean_up(get_module(BTE_LOGMSG_MODULE)); 323#endif 324 325 bta_sys_free(); 326 btu_free_core(); 327} 328 329/******************************************************************************* 330** 331** Function btu_start_timer 332** 333** Description Start a timer for the specified amount of time. 334** NOTE: The timeout resolution is in SECONDS! (Even 335** though the timer structure field is ticks) 336** 337** Returns void 338** 339*******************************************************************************/ 340static void btu_general_alarm_process(TIMER_LIST_ENT *p_tle) { 341 assert(p_tle != NULL); 342 343 switch (p_tle->event) { 344 case BTU_TTYPE_BTM_DEV_CTL: 345 btm_dev_timeout(p_tle); 346 break; 347 348 case BTU_TTYPE_L2CAP_LINK: 349 case BTU_TTYPE_L2CAP_CHNL: 350 case BTU_TTYPE_L2CAP_HOLD: 351 case BTU_TTYPE_L2CAP_INFO: 352 case BTU_TTYPE_L2CAP_FCR_ACK: 353 l2c_process_timeout (p_tle); 354 break; 355 356 case BTU_TTYPE_SDP: 357 sdp_conn_timeout ((tCONN_CB *)p_tle->param); 358 break; 359 360 case BTU_TTYPE_BTM_RMT_NAME: 361 btm_inq_rmt_name_failed(); 362 break; 363 364 case BTU_TTYPE_RFCOMM_MFC: 365 case BTU_TTYPE_RFCOMM_PORT: 366 rfcomm_process_timeout (p_tle); 367 break; 368 369#if ((defined(BNEP_INCLUDED) && BNEP_INCLUDED == TRUE)) 370 case BTU_TTYPE_BNEP: 371 bnep_process_timeout(p_tle); 372 break; 373#endif 374 375 376#if (defined(AVDT_INCLUDED) && AVDT_INCLUDED == TRUE) 377 case BTU_TTYPE_AVDT_CCB_RET: 378 case BTU_TTYPE_AVDT_CCB_RSP: 379 case BTU_TTYPE_AVDT_CCB_IDLE: 380 case BTU_TTYPE_AVDT_SCB_TC: 381 avdt_process_timeout(p_tle); 382 break; 383#endif 384 385#if (defined(HID_HOST_INCLUDED) && HID_HOST_INCLUDED == TRUE) 386 case BTU_TTYPE_HID_HOST_REPAGE_TO : 387 hidh_proc_repage_timeout(p_tle); 388 break; 389#endif 390 391#if (defined(BLE_INCLUDED) && BLE_INCLUDED == TRUE) 392 case BTU_TTYPE_BLE_INQUIRY: 393 case BTU_TTYPE_BLE_GAP_LIM_DISC: 394 case BTU_TTYPE_BLE_RANDOM_ADDR: 395 case BTU_TTYPE_BLE_GAP_FAST_ADV: 396 case BTU_TTYPE_BLE_OBSERVE: 397 btm_ble_timeout(p_tle); 398 break; 399 400 case BTU_TTYPE_ATT_WAIT_FOR_RSP: 401 gatt_rsp_timeout(p_tle); 402 break; 403 404 case BTU_TTYPE_ATT_WAIT_FOR_IND_ACK: 405 gatt_ind_ack_timeout(p_tle); 406 break; 407#if (defined(SMP_INCLUDED) && SMP_INCLUDED == TRUE) 408 case BTU_TTYPE_SMP_PAIRING_CMD: 409 smp_rsp_timeout(p_tle); 410 break; 411#endif 412 413#endif 414 415#if (MCA_INCLUDED == TRUE) 416 case BTU_TTYPE_MCA_CCB_RSP: 417 mca_process_timeout(p_tle); 418 break; 419#endif 420 case BTU_TTYPE_USER_FUNC: 421 { 422 tUSER_TIMEOUT_FUNC *p_uf = (tUSER_TIMEOUT_FUNC *)p_tle->param; 423 (*p_uf)(p_tle); 424 } 425 break; 426 427 default:; 428 int i = 0; 429 BOOLEAN handled = FALSE; 430 431 for (; !handled && i < BTU_MAX_REG_TIMER; i++) 432 { 433 if (btu_cb.timer_reg[i].timer_cb == NULL) 434 continue; 435 if (btu_cb.timer_reg[i].p_tle == p_tle) 436 { 437 btu_cb.timer_reg[i].timer_cb(p_tle); 438 handled = TRUE; 439 } 440 } 441 break; 442 } 443} 444 445void btu_general_alarm_cb(void *data) { 446 assert(data != NULL); 447 TIMER_LIST_ENT *p_tle = (TIMER_LIST_ENT *)data; 448 449 fixed_queue_enqueue(btu_general_alarm_queue, p_tle); 450 GKI_send_event(BTU_TASK, TIMER_0_EVT_MASK); 451} 452 453void btu_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_sec) { 454 assert(p_tle != NULL); 455 456 // Get the alarm for the timer list entry. 457 pthread_mutex_lock(&btu_general_alarm_lock); 458 if (!hash_map_has_key(btu_general_alarm_hash_map, p_tle)) { 459 hash_map_set(btu_general_alarm_hash_map, p_tle, alarm_new()); 460 } 461 pthread_mutex_unlock(&btu_general_alarm_lock); 462 463 alarm_t *alarm = hash_map_get(btu_general_alarm_hash_map, p_tle); 464 if (alarm == NULL) { 465 LOG_ERROR("%s Unable to create alarm", __func__); 466 return; 467 } 468 alarm_cancel(alarm); 469 470 p_tle->event = type; 471 // NOTE: This value is in seconds but stored in a ticks field. 472 p_tle->ticks = timeout_sec; 473 p_tle->in_use = TRUE; 474 alarm_set(alarm, (period_ms_t)(timeout_sec * 1000), btu_general_alarm_cb, (void *)p_tle); 475} 476 477/******************************************************************************* 478** 479** Function btu_remaining_time 480** 481** Description Return amount of time to expire 482** 483** Returns time in second 484** 485*******************************************************************************/ 486UINT32 btu_remaining_time (TIMER_LIST_ENT *p_tle) 487{ 488 return(GKI_get_remaining_ticks (&btu_cb.timer_queue, p_tle)); 489} 490 491/******************************************************************************* 492** 493** Function btu_stop_timer 494** 495** Description Stop a timer. 496** 497** Returns void 498** 499*******************************************************************************/ 500void btu_stop_timer(TIMER_LIST_ENT *p_tle) { 501 assert(p_tle != NULL); 502 503 if (p_tle->in_use == FALSE) 504 return; 505 p_tle->in_use = FALSE; 506 507 // Get the alarm for the timer list entry. 508 alarm_t *alarm = hash_map_get(btu_general_alarm_hash_map, p_tle); 509 if (alarm == NULL) { 510 LOG_WARN("%s Unable to find expected alarm in hashmap", __func__); 511 return; 512 } 513 alarm_cancel(alarm); 514} 515 516#if defined(QUICK_TIMER_TICKS_PER_SEC) && (QUICK_TIMER_TICKS_PER_SEC > 0) 517/******************************************************************************* 518** 519** Function btu_start_quick_timer 520** 521** Description Start a timer for the specified amount of time in ticks. 522** 523** Returns void 524** 525*******************************************************************************/ 526static void btu_l2cap_alarm_process(TIMER_LIST_ENT *p_tle) { 527 assert(p_tle != NULL); 528 529 switch (p_tle->event) { 530 case BTU_TTYPE_L2CAP_CHNL: /* monitor or retransmission timer */ 531 case BTU_TTYPE_L2CAP_FCR_ACK: /* ack timer */ 532 l2c_process_timeout (p_tle); 533 break; 534 535 default: 536 break; 537 } 538} 539 540static void btu_l2cap_alarm_cb(void *data) { 541 assert(data != NULL); 542 TIMER_LIST_ENT *p_tle = (TIMER_LIST_ENT *)data; 543 544 fixed_queue_enqueue(btu_l2cap_alarm_queue, p_tle); 545 GKI_send_event(BTU_TASK, TIMER_2_EVT_MASK); 546} 547 548void btu_start_quick_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_ticks) { 549 assert(p_tle != NULL); 550 551 // Get the alarm for the timer list entry. 552 pthread_mutex_lock(&btu_l2cap_alarm_lock); 553 if (!hash_map_has_key(btu_l2cap_alarm_hash_map, p_tle)) { 554 hash_map_set(btu_l2cap_alarm_hash_map, p_tle, alarm_new()); 555 } 556 pthread_mutex_unlock(&btu_l2cap_alarm_lock); 557 558 alarm_t *alarm = hash_map_get(btu_l2cap_alarm_hash_map, p_tle); 559 if (alarm == NULL) { 560 LOG_ERROR("%s Unable to create alarm", __func__); 561 return; 562 } 563 alarm_cancel(alarm); 564 565 p_tle->event = type; 566 p_tle->ticks = timeout_ticks; 567 p_tle->in_use = TRUE; 568 // The quick timer ticks are 100ms long. 569 alarm_set(alarm, (period_ms_t)(timeout_ticks * 100), btu_l2cap_alarm_cb, (void *)p_tle); 570} 571 572/******************************************************************************* 573** 574** Function btu_stop_quick_timer 575** 576** Description Stop a timer. 577** 578** Returns void 579** 580*******************************************************************************/ 581void btu_stop_quick_timer(TIMER_LIST_ENT *p_tle) { 582 assert(p_tle != NULL); 583 584 if (p_tle->in_use == FALSE) 585 return; 586 p_tle->in_use = FALSE; 587 588 // Get the alarm for the timer list entry. 589 alarm_t *alarm = hash_map_get(btu_l2cap_alarm_hash_map, p_tle); 590 if (alarm == NULL) { 591 LOG_WARN("%s Unable to find expected alarm in hashmap", __func__); 592 return; 593 } 594 alarm_cancel(alarm); 595} 596#endif /* defined(QUICK_TIMER_TICKS_PER_SEC) && (QUICK_TIMER_TICKS_PER_SEC > 0) */ 597 598void btu_oneshot_alarm_cb(void *data) { 599 assert(data != NULL); 600 TIMER_LIST_ENT *p_tle = (TIMER_LIST_ENT *)data; 601 602 btu_stop_timer_oneshot(p_tle); 603 604 fixed_queue_enqueue(btu_oneshot_alarm_queue, p_tle); 605 GKI_send_event(BTU_TASK, TIMER_3_EVT_MASK); 606} 607 608/* 609 * Starts a oneshot timer with a timeout in seconds. 610 */ 611void btu_start_timer_oneshot(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_sec) { 612 assert(p_tle != NULL); 613 614 // Get the alarm for the timer list entry. 615 pthread_mutex_lock(&btu_oneshot_alarm_lock); 616 if (!hash_map_has_key(btu_oneshot_alarm_hash_map, p_tle)) { 617 hash_map_set(btu_oneshot_alarm_hash_map, p_tle, alarm_new()); 618 } 619 pthread_mutex_unlock(&btu_oneshot_alarm_lock); 620 621 alarm_t *alarm = hash_map_get(btu_oneshot_alarm_hash_map, p_tle); 622 if (alarm == NULL) { 623 LOG_ERROR("%s Unable to create alarm", __func__); 624 return; 625 } 626 alarm_cancel(alarm); 627 628 p_tle->event = type; 629 p_tle->in_use = TRUE; 630 // NOTE: This value is in seconds but stored in a ticks field. 631 p_tle->ticks = timeout_sec; 632 alarm_set(alarm, (period_ms_t)(timeout_sec * 1000), btu_oneshot_alarm_cb, (void *)p_tle); 633} 634 635void btu_stop_timer_oneshot(TIMER_LIST_ENT *p_tle) { 636 assert(p_tle != NULL); 637 638 if (p_tle->in_use == FALSE) 639 return; 640 p_tle->in_use = FALSE; 641 642 // Get the alarm for the timer list entry. 643 alarm_t *alarm = hash_map_get(btu_oneshot_alarm_hash_map, p_tle); 644 if (alarm == NULL) { 645 LOG_WARN("%s Unable to find expected alarm in hashmap", __func__); 646 return; 647 } 648 alarm_cancel(alarm); 649} 650 651#if (defined(HCILP_INCLUDED) && HCILP_INCLUDED == TRUE) 652/******************************************************************************* 653** 654** Function btu_check_bt_sleep 655** 656** Description This function is called to check if controller can go to sleep. 657** 658** Returns void 659** 660*******************************************************************************/ 661void btu_check_bt_sleep (void) 662{ 663 // TODO(zachoverflow) take pending commands into account? 664 if (l2cb.controller_xmit_window == l2cb.num_lm_acl_bufs) 665 { 666 bte_main_lpm_allow_bt_device_sleep(); 667 } 668} 669#endif 670