1 /******************************************************************************
3 * Copyright (C) 1999-2012 Broadcom Corporation
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************************/
23 #include "bt_target.h"
26 #include "allocator.h"
30 #include "fixed_queue.h"
36 #if (defined(SDP_INCLUDED) && SDP_INCLUDED == TRUE)
40 #if (defined(RFCOMM_INCLUDED) && RFCOMM_INCLUDED == TRUE)
45 #if (defined(GAP_INCLUDED) && GAP_INCLUDED == TRUE)
49 #if (defined(BNEP_INCLUDED) && BNEP_INCLUDED == TRUE)
53 #if (defined(PAN_INCLUDED) && PAN_INCLUDED == TRUE)
57 #if (defined(HID_HOST_INCLUDED) && HID_HOST_INCLUDED == TRUE )
61 #if (defined(AVDT_INCLUDED) && AVDT_INCLUDED == TRUE)
64 extern void avdt_rcv_sync_info (BT_HDR *p_buf);
67 #if (defined(MCA_INCLUDED) && MCA_INCLUDED == TRUE)
73 #if (defined(BTA_INCLUDED) && BTA_INCLUDED == TRUE)
77 #if (BLE_INCLUDED == TRUE)
79 #if (SMP_INCLUDED == TRUE)
82 #include "btm_ble_int.h"
85 //#if (defined(BT_APP_DEMO) && BT_APP_DEMO == TRUE)
86 //#include "bt_app_common.h"
89 extern void BTE_InitStack(void);
91 /* Define BTU storage area
93 #if BTU_DYNAMIC_MEMORY == FALSE
97 // Communication queue between btu_task and bta.
98 extern fixed_queue_t *btu_bta_msg_queue;
100 // alarm queue between btu_task and bta
101 extern fixed_queue_t *btu_bta_alarm_queue;
103 // Communication queue between btu_task and hci.
104 extern fixed_queue_t *btu_hci_msg_queue;
106 // General timer queue.
107 extern fixed_queue_t *btu_general_alarm_queue;
108 extern hash_map_t *btu_general_alarm_hash_map;
109 extern pthread_mutex_t btu_general_alarm_lock;
111 // Oneshot timer queue.
112 extern fixed_queue_t *btu_oneshot_alarm_queue;
113 extern hash_map_t *btu_oneshot_alarm_hash_map;
114 extern pthread_mutex_t btu_oneshot_alarm_lock;
116 // l2cap timer queue.
117 extern fixed_queue_t *btu_l2cap_alarm_queue;
118 extern hash_map_t *btu_l2cap_alarm_hash_map;
119 extern pthread_mutex_t btu_l2cap_alarm_lock;
121 extern fixed_queue_t *event_queue;
122 //extern fixed_queue_t *btif_msg_queue;
124 //extern thread_t *bt_workqueue_thread;
125 extern xTaskHandle xBtuTaskHandle;
126 extern xQueueHandle xBtuQueue;
127 extern bluedroid_init_done_cb_t bluedroid_init_done_cb;
129 /* Define a function prototype to allow a generic timeout handler */
130 typedef void (tUSER_TIMEOUT_FUNC) (TIMER_LIST_ENT *p_tle);
132 static void btu_l2cap_alarm_process(TIMER_LIST_ENT *p_tle);
133 static void btu_general_alarm_process(TIMER_LIST_ENT *p_tle);
134 static void btu_hci_msg_process(BT_HDR *p_msg);
136 #if (defined(BTA_INCLUDED) && BTA_INCLUDED == TRUE)
137 static void btu_bta_alarm_process(TIMER_LIST_ENT *p_tle);
140 void btu_hci_msg_ready(fixed_queue_t *queue) {
143 while (!fixed_queue_is_empty(queue)) {
144 p_msg = (BT_HDR *)fixed_queue_dequeue(queue);
145 btu_hci_msg_process(p_msg);
149 void btu_general_alarm_ready(fixed_queue_t *queue) {
150 TIMER_LIST_ENT *p_tle;
152 while (!fixed_queue_is_empty(queue)) {
153 p_tle = (TIMER_LIST_ENT *)fixed_queue_dequeue(queue);
154 btu_general_alarm_process(p_tle);
158 void btu_oneshot_alarm_ready(fixed_queue_t *queue) {
159 TIMER_LIST_ENT *p_tle;
161 while (!fixed_queue_is_empty(queue)) {
162 p_tle = (TIMER_LIST_ENT *)fixed_queue_dequeue(queue);
163 btu_general_alarm_process(p_tle);
165 switch (p_tle->event) {
166 #if (defined(BLE_INCLUDED) && BLE_INCLUDED == TRUE)
167 case BTU_TTYPE_BLE_RANDOM_ADDR:
168 btm_ble_timeout(p_tle);
171 case BTU_TTYPE_USER_FUNC:
173 tUSER_TIMEOUT_FUNC *p_uf = (tUSER_TIMEOUT_FUNC *)p_tle->param;
180 LOG_ERROR("Received unexpected oneshot timer event:0x%x\n",
187 void btu_l2cap_alarm_ready(fixed_queue_t *queue) {
188 TIMER_LIST_ENT *p_tle;
190 while (!fixed_queue_is_empty(queue)) {
191 p_tle = (TIMER_LIST_ENT *)fixed_queue_dequeue(queue);
192 btu_l2cap_alarm_process(p_tle);
196 #if (defined(BTA_INCLUDED) && BTA_INCLUDED == TRUE)
197 void btu_bta_msg_ready(fixed_queue_t *queue) {
200 while (!fixed_queue_is_empty(queue)) {
201 p_msg = (BT_HDR *)fixed_queue_dequeue(queue);
202 bta_sys_event(p_msg);
206 void btu_bta_alarm_ready(fixed_queue_t *queue) {
207 TIMER_LIST_ENT *p_tle;
209 while (!fixed_queue_is_empty(queue)) {
210 p_tle = (TIMER_LIST_ENT *)fixed_queue_dequeue(queue);
211 btu_bta_alarm_process(p_tle);
216 static void btu_hci_msg_process(BT_HDR *p_msg) {
217 /* Determine the input message type. */
218 switch (p_msg->event & BT_EVT_MASK)
220 case BTU_POST_TO_TASK_NO_GOOD_HORRIBLE_HACK: // TODO(zachoverflow): remove this
221 ((post_to_task_hack_t *)(&p_msg->data[0]))->callback(p_msg);
223 case BT_EVT_TO_BTU_HCI_ACL:
224 /* All Acl Data goes to L2CAP */
225 l2c_rcv_acl_data (p_msg);
228 case BT_EVT_TO_BTU_L2C_SEG_XMIT:
229 /* L2CAP segment transmit complete */
230 l2c_link_segments_xmitted (p_msg);
233 case BT_EVT_TO_BTU_HCI_SCO:
234 #if BTM_SCO_INCLUDED == TRUE
235 btm_route_sco_data (p_msg);
239 case BT_EVT_TO_BTU_HCI_EVT:
240 btu_hcif_process_event ((UINT8)(p_msg->event & BT_SUB_EVT_MASK), p_msg);
243 #if (defined(HCILP_INCLUDED) && HCILP_INCLUDED == TRUE)
244 /* If host receives events which it doesn't response to, */
245 /* host should start idle timer to enter sleep mode. */
246 btu_check_bt_sleep ();
250 case BT_EVT_TO_BTU_HCI_CMD:
251 btu_hcif_send_cmd ((UINT8)(p_msg->event & BT_SUB_EVT_MASK), p_msg);
256 uint16_t mask = (UINT16) (p_msg->event & BT_EVT_MASK);
257 BOOLEAN handled = FALSE;
259 for (; !handled && i < BTU_MAX_REG_EVENT; i++)
261 if (btu_cb.event_reg[i].event_cb == NULL)
264 if (mask == btu_cb.event_reg[i].event_range)
266 if (btu_cb.event_reg[i].event_cb)
268 btu_cb.event_reg[i].event_cb(p_msg);
274 if (handled == FALSE)
282 #if (defined(BTA_INCLUDED) && BTA_INCLUDED == TRUE)
283 static void btu_bta_alarm_process(TIMER_LIST_ENT *p_tle) {
284 // call timer callback
285 if (p_tle->p_cback) {
286 (*p_tle->p_cback)(p_tle);
287 } else if (p_tle->event) {
289 if ((p_msg = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) {
290 p_msg->event = p_tle->event;
291 p_msg->layer_specific = 0;
292 //GKI_freebuf(p_msg);
293 bta_sys_sendmsg(p_msg);
299 /*****************************************************************************
301 ** Function btu_task_thread_handler
303 ** Description Process BTU Task Thread.
304 ******************************************************************************/
305 void btu_task_thread_handler(void *arg)
310 if (pdTRUE == xQueueReceive(xBtuQueue, &e, (portTickType)portMAX_DELAY)) {
312 if (e.sig == SIG_BTU_WORK) {
313 fixed_queue_process(btu_hci_msg_queue);
314 #if (defined(BTA_INCLUDED) && BTA_INCLUDED == TRUE)
315 fixed_queue_process(btu_bta_msg_queue);
316 fixed_queue_process(btu_bta_alarm_queue);
318 fixed_queue_process(btu_general_alarm_queue);
319 fixed_queue_process(btu_oneshot_alarm_queue);
320 fixed_queue_process(btu_l2cap_alarm_queue);
322 else if (e.sig == SIG_BTU_START_UP) {
330 void btu_task_post(uint32_t sig)
337 if (xQueueSend(xBtuQueue, &evt, 10/portTICK_RATE_MS) != pdTRUE) {
338 LOG_ERROR("xBtuQueue failed\n");
342 void btu_task_start_up(void) {
344 #if (defined(BTA_INCLUDED) && BTA_INCLUDED == TRUE)
345 fixed_queue_register_dequeue(btu_bta_msg_queue, btu_bta_msg_ready);
348 fixed_queue_register_dequeue(btu_hci_msg_queue, btu_hci_msg_ready);
349 fixed_queue_register_dequeue(btu_general_alarm_queue, btu_general_alarm_ready);
350 fixed_queue_register_dequeue(btu_oneshot_alarm_queue, btu_oneshot_alarm_ready);
351 fixed_queue_register_dequeue(btu_l2cap_alarm_queue, btu_l2cap_alarm_ready);
353 /* Initialize the mandatory core stack control blocks
354 (BTU, BTM, L2CAP, and SDP)
358 /* Initialize any optional stack components */
361 #if (defined(BTA_INCLUDED) && BTA_INCLUDED == TRUE)
365 // Inform the bt jni thread initialization is ok.
366 // btif_transfer_context(btif_init_ok, 0, NULL, 0, NULL);
367 #if(defined(BT_APP_DEMO) && BT_APP_DEMO == TRUE)
368 if (bluedroid_init_done_cb)
369 bluedroid_init_done_cb();
373 void btu_task_shut_down(void) {
374 fixed_queue_unregister_dequeue(btu_hci_msg_queue);
375 fixed_queue_unregister_dequeue(btu_general_alarm_queue);
376 fixed_queue_unregister_dequeue(btu_oneshot_alarm_queue);
377 fixed_queue_unregister_dequeue(btu_l2cap_alarm_queue);
379 #if (defined(BTA_INCLUDED) && BTA_INCLUDED == TRUE)
380 fixed_queue_unregister_dequeue(btu_bta_msg_queue);
387 /*******************************************************************************
389 ** Function btu_start_timer
391 ** Description Start a timer for the specified amount of time.
392 ** NOTE: The timeout resolution is in SECONDS! (Even
393 ** though the timer structure field is ticks)
397 *******************************************************************************/
398 static void btu_general_alarm_process(TIMER_LIST_ENT *p_tle) {
399 assert(p_tle != NULL);
401 switch (p_tle->event) {
402 case BTU_TTYPE_BTM_DEV_CTL:
403 btm_dev_timeout(p_tle);
406 case BTU_TTYPE_L2CAP_LINK:
407 case BTU_TTYPE_L2CAP_CHNL:
408 case BTU_TTYPE_L2CAP_HOLD:
409 case BTU_TTYPE_L2CAP_INFO:
410 case BTU_TTYPE_L2CAP_FCR_ACK:
411 l2c_process_timeout (p_tle);
413 #if (defined(SDP_INCLUDED) && SDP_INCLUDED == TRUE)
415 sdp_conn_timeout ((tCONN_CB *)p_tle->param);
418 case BTU_TTYPE_BTM_RMT_NAME:
419 btm_inq_rmt_name_failed();
421 #if (defined(RFCOMM_INCLUDED) && RFCOMM_INCLUDED == TRUE)
422 case BTU_TTYPE_RFCOMM_MFC:
423 case BTU_TTYPE_RFCOMM_PORT:
424 rfcomm_process_timeout (p_tle);
427 #if ((defined(BNEP_INCLUDED) && BNEP_INCLUDED == TRUE))
429 bnep_process_timeout(p_tle);
434 #if (defined(AVDT_INCLUDED) && AVDT_INCLUDED == TRUE)
435 case BTU_TTYPE_AVDT_CCB_RET:
436 case BTU_TTYPE_AVDT_CCB_RSP:
437 case BTU_TTYPE_AVDT_CCB_IDLE:
438 case BTU_TTYPE_AVDT_SCB_TC:
439 avdt_process_timeout(p_tle);
443 #if (defined(HID_HOST_INCLUDED) && HID_HOST_INCLUDED == TRUE)
444 case BTU_TTYPE_HID_HOST_REPAGE_TO :
445 hidh_proc_repage_timeout(p_tle);
449 #if (defined(BLE_INCLUDED) && BLE_INCLUDED == TRUE)
450 case BTU_TTYPE_BLE_INQUIRY:
451 case BTU_TTYPE_BLE_GAP_LIM_DISC:
452 case BTU_TTYPE_BLE_RANDOM_ADDR:
453 case BTU_TTYPE_BLE_GAP_FAST_ADV:
454 case BTU_TTYPE_BLE_OBSERVE:
455 btm_ble_timeout(p_tle);
458 case BTU_TTYPE_ATT_WAIT_FOR_RSP:
459 gatt_rsp_timeout(p_tle);
462 case BTU_TTYPE_ATT_WAIT_FOR_IND_ACK:
463 gatt_ind_ack_timeout(p_tle);
465 #if (defined(SMP_INCLUDED) && SMP_INCLUDED == TRUE)
466 case BTU_TTYPE_SMP_PAIRING_CMD:
467 smp_rsp_timeout(p_tle);
473 #if (MCA_INCLUDED == TRUE)
474 case BTU_TTYPE_MCA_CCB_RSP:
475 mca_process_timeout(p_tle);
478 case BTU_TTYPE_USER_FUNC:
480 tUSER_TIMEOUT_FUNC *p_uf = (tUSER_TIMEOUT_FUNC *)p_tle->param;
487 BOOLEAN handled = FALSE;
489 for (; !handled && i < BTU_MAX_REG_TIMER; i++)
491 if (btu_cb.timer_reg[i].timer_cb == NULL)
493 if (btu_cb.timer_reg[i].p_tle == p_tle)
495 btu_cb.timer_reg[i].timer_cb(p_tle);
503 void btu_general_alarm_cb(void *data) {
504 assert(data != NULL);
505 TIMER_LIST_ENT *p_tle = (TIMER_LIST_ENT *)data;
507 fixed_queue_enqueue(btu_general_alarm_queue, p_tle);
508 //ke_event_set(KE_EVENT_BTU_TASK_THREAD);
509 btu_task_post(SIG_BTU_WORK);
512 void btu_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_sec) {
513 osi_alarm_t *alarm = NULL;
515 assert(p_tle != NULL);
517 // Get the alarm for the timer list entry.
518 pthread_mutex_lock(&btu_general_alarm_lock);
519 if (!hash_map_has_key(btu_general_alarm_hash_map, p_tle)) {
520 alarm = osi_alarm_new("btu_gen", btu_general_alarm_cb, (void *)p_tle, 0, false);
521 hash_map_set(btu_general_alarm_hash_map, p_tle, alarm);
523 pthread_mutex_unlock(&btu_general_alarm_lock);
525 alarm = hash_map_get(btu_general_alarm_hash_map, p_tle);
527 LOG_ERROR("%s Unable to create alarm", __func__);
530 osi_alarm_cancel(alarm);
533 // NOTE: This value is in seconds but stored in a ticks field.
534 p_tle->ticks = timeout_sec;
535 p_tle->in_use = TRUE;
536 osi_alarm_set(alarm, (period_ms_t)(timeout_sec * 1000));
539 /*******************************************************************************
541 ** Function btu_stop_timer
543 ** Description Stop a timer.
547 *******************************************************************************/
548 void btu_stop_timer(TIMER_LIST_ENT *p_tle) {
549 assert(p_tle != NULL);
551 if (p_tle->in_use == FALSE)
553 p_tle->in_use = FALSE;
555 // Get the alarm for the timer list entry.
556 osi_alarm_t *alarm = hash_map_get(btu_general_alarm_hash_map, p_tle);
558 LOG_WARN("%s Unable to find expected alarm in hashmap", __func__);
561 osi_alarm_cancel(alarm);
564 #if defined(QUICK_TIMER_TICKS_PER_SEC) && (QUICK_TIMER_TICKS_PER_SEC > 0)
565 /*******************************************************************************
567 ** Function btu_start_quick_timer
569 ** Description Start a timer for the specified amount of time in ticks.
573 *******************************************************************************/
574 static void btu_l2cap_alarm_process(TIMER_LIST_ENT *p_tle) {
575 assert(p_tle != NULL);
577 switch (p_tle->event) {
578 case BTU_TTYPE_L2CAP_CHNL: /* monitor or retransmission timer */
579 case BTU_TTYPE_L2CAP_FCR_ACK: /* ack timer */
580 l2c_process_timeout (p_tle);
588 static void btu_l2cap_alarm_cb(void *data) {
589 assert(data != NULL);
590 TIMER_LIST_ENT *p_tle = (TIMER_LIST_ENT *)data;
592 fixed_queue_enqueue(btu_l2cap_alarm_queue, p_tle);
593 //ke_event_set(KE_EVENT_BTU_TASK_THREAD);
594 btu_task_post(SIG_BTU_WORK);
597 void btu_start_quick_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_ticks) {
598 osi_alarm_t *alarm = NULL;
600 assert(p_tle != NULL);
602 // Get the alarm for the timer list entry.
603 pthread_mutex_lock(&btu_l2cap_alarm_lock);
604 if (!hash_map_has_key(btu_l2cap_alarm_hash_map, p_tle)) {
605 alarm = osi_alarm_new("btu_l2cap", btu_l2cap_alarm_cb, (void *)p_tle, 0, false);
606 hash_map_set(btu_l2cap_alarm_hash_map, p_tle, (void *)alarm);
608 pthread_mutex_unlock(&btu_l2cap_alarm_lock);
610 alarm = hash_map_get(btu_l2cap_alarm_hash_map, p_tle);
612 LOG_ERROR("%s Unable to create alarm", __func__);
615 osi_alarm_cancel(alarm);
618 p_tle->ticks = timeout_ticks;
619 p_tle->in_use = TRUE;
620 // The quick timer ticks are 100ms long.
621 osi_alarm_set(alarm, (period_ms_t)(timeout_ticks * 100));
624 /*******************************************************************************
626 ** Function btu_stop_quick_timer
628 ** Description Stop a timer.
632 *******************************************************************************/
633 void btu_stop_quick_timer(TIMER_LIST_ENT *p_tle) {
634 assert(p_tle != NULL);
636 if (p_tle->in_use == FALSE)
638 p_tle->in_use = FALSE;
640 // Get the alarm for the timer list entry.
641 osi_alarm_t *alarm = hash_map_get(btu_l2cap_alarm_hash_map, p_tle);
643 LOG_WARN("%s Unable to find expected alarm in hashmap", __func__);
646 osi_alarm_cancel(alarm);
648 #endif /* defined(QUICK_TIMER_TICKS_PER_SEC) && (QUICK_TIMER_TICKS_PER_SEC > 0) */
650 void btu_oneshot_alarm_cb(void *data) {
651 assert(data != NULL);
652 TIMER_LIST_ENT *p_tle = (TIMER_LIST_ENT *)data;
654 btu_stop_timer_oneshot(p_tle);
656 fixed_queue_enqueue(btu_oneshot_alarm_queue, p_tle);
657 //ke_event_set(KE_EVENT_BTU_TASK_THREAD);
658 btu_task_post(SIG_BTU_WORK);
662 * Starts a oneshot timer with a timeout in seconds.
664 void btu_start_timer_oneshot(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_sec) {
665 osi_alarm_t *alarm = NULL;
667 assert(p_tle != NULL);
669 // Get the alarm for the timer list entry.
670 pthread_mutex_lock(&btu_oneshot_alarm_lock);
671 if (!hash_map_has_key(btu_oneshot_alarm_hash_map, p_tle)) {
672 alarm = osi_alarm_new("btu_oneshot", btu_oneshot_alarm_cb, (void *)p_tle, 0, false);
673 hash_map_set(btu_oneshot_alarm_hash_map, p_tle, alarm);
675 pthread_mutex_unlock(&btu_oneshot_alarm_lock);
677 alarm = hash_map_get(btu_oneshot_alarm_hash_map, p_tle);
679 LOG_ERROR("%s Unable to create alarm", __func__);
682 osi_alarm_cancel(alarm);
685 p_tle->in_use = TRUE;
686 // NOTE: This value is in seconds but stored in a ticks field.
687 p_tle->ticks = timeout_sec;
688 osi_alarm_set(alarm, (period_ms_t)(timeout_sec * 1000));
691 void btu_stop_timer_oneshot(TIMER_LIST_ENT *p_tle) {
692 assert(p_tle != NULL);
694 if (p_tle->in_use == FALSE)
696 p_tle->in_use = FALSE;
698 // Get the alarm for the timer list entry.
699 osi_alarm_t *alarm = hash_map_get(btu_oneshot_alarm_hash_map, p_tle);
701 LOG_WARN("%s Unable to find expected alarm in hashmap", __func__);
704 osi_alarm_cancel(alarm);
707 #if (defined(HCILP_INCLUDED) && HCILP_INCLUDED == TRUE)
708 /*******************************************************************************
710 ** Function btu_check_bt_sleep
712 ** Description This function is called to check if controller can go to sleep.
716 *******************************************************************************/
717 void btu_check_bt_sleep (void)
719 // TODO(zachoverflow) take pending commands into account?
720 if (l2cb.controller_xmit_window == l2cb.num_lm_acl_bufs)
722 bte_main_lpm_allow_bt_device_sleep();