1 /****************************************************************************** 2 * 3 * Copyright (C) 2009-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 * Filename: bt_hci_bdroid.c 22 * 23 * Description: Bluedroid Bluetooth Host/Controller interface library 24 * implementation 25 * 26 ******************************************************************************/ 27 28 #define LOG_TAG "bt_hci_bdroid" 29 30 #include <utils/Log.h> 31 #include <pthread.h> 32 #include "bt_hci_bdroid.h" 33 #include "bt_vendor_lib.h" 34 #include "utils.h" 35 #include "hci.h" 36 #include "userial.h" 37 #include "bt_utils.h" 38 #include <sys/prctl.h> 39 40 #ifndef BTHC_DBG 41 #define BTHC_DBG FALSE 42 #endif 43 44 #if (BTHC_DBG == TRUE) 45 #define BTHCDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);} 46 #else 47 #define BTHCDBG(param, ...) {} 48 #endif 49 50 /* Vendor epilog process timeout period */ 51 #ifndef EPILOG_TIMEOUT_MS 52 #define EPILOG_TIMEOUT_MS 3000 // 3 seconds 53 #endif 54 55 /****************************************************************************** 56 ** Externs 57 ******************************************************************************/ 58 59 extern bt_vendor_interface_t *bt_vnd_if; 60 extern int num_hci_cmd_pkts; 61 void lpm_init(void); 62 void lpm_cleanup(void); 63 void lpm_enable(uint8_t turn_on); 64 void lpm_wake_deassert(void); 65 void lpm_allow_bt_device_sleep(void); 66 void lpm_wake_assert(void); 67 void init_vnd_if(unsigned char *local_bdaddr); 68 void btsnoop_open(char *p_path); 69 void btsnoop_close(void); 70 71 /****************************************************************************** 72 ** Variables 73 ******************************************************************************/ 74 75 bt_hc_callbacks_t *bt_hc_cbacks = NULL; 76 BUFFER_Q tx_q; 77 tHCI_IF *p_hci_if; 78 volatile uint8_t fwcfg_acked; 79 80 /****************************************************************************** 81 ** Local type definitions 82 ******************************************************************************/ 83 84 /* Host/Controller lib thread control block */ 85 typedef struct 86 { 87 pthread_t worker_thread; 88 pthread_mutex_t mutex; 89 pthread_cond_t cond; 90 uint8_t epilog_timer_created; 91 timer_t epilog_timer_id; 92 } bt_hc_cb_t; 93 94 /****************************************************************************** 95 ** Static Variables 96 ******************************************************************************/ 97 98 static bt_hc_cb_t hc_cb; 99 static volatile uint8_t lib_running = 0; 100 static volatile uint16_t ready_events = 0; 101 static volatile uint8_t tx_cmd_pkts_pending = FALSE; 102 103 /****************************************************************************** 104 ** Functions 105 ******************************************************************************/ 106 107 static void *bt_hc_worker_thread(void *arg); 108 109 void bthc_signal_event(uint16_t event) 110 { 111 pthread_mutex_lock(&hc_cb.mutex); 112 ready_events |= event; 113 pthread_cond_signal(&hc_cb.cond); 114 pthread_mutex_unlock(&hc_cb.mutex); 115 } 116 117 /******************************************************************************* 118 ** 119 ** Function epilog_wait_timeout 120 ** 121 ** Description Timeout thread of epilog watchdog timer 122 ** 123 ** Returns None 124 ** 125 *******************************************************************************/ 126 static void epilog_wait_timeout(union sigval arg) 127 { 128 ALOGI("...epilog_wait_timeout..."); 129 bthc_signal_event(HC_EVENT_EXIT); 130 } 131 132 /******************************************************************************* 133 ** 134 ** Function epilog_wait_timer 135 ** 136 ** Description Launch epilog watchdog timer 137 ** 138 ** Returns None 139 ** 140 *******************************************************************************/ 141 static void epilog_wait_timer(void) 142 { 143 int status; 144 struct itimerspec ts; 145 struct sigevent se; 146 uint32_t timeout_ms = EPILOG_TIMEOUT_MS; 147 148 se.sigev_notify = SIGEV_THREAD; 149 se.sigev_value.sival_ptr = &hc_cb.epilog_timer_id; 150 se.sigev_notify_function = epilog_wait_timeout; 151 se.sigev_notify_attributes = NULL; 152 153 status = timer_create(CLOCK_MONOTONIC, &se, &hc_cb.epilog_timer_id); 154 155 if (status == 0) 156 { 157 hc_cb.epilog_timer_created = 1; 158 ts.it_value.tv_sec = timeout_ms/1000; 159 ts.it_value.tv_nsec = 1000000*(timeout_ms%1000); 160 ts.it_interval.tv_sec = 0; 161 ts.it_interval.tv_nsec = 0; 162 163 status = timer_settime(hc_cb.epilog_timer_id, 0, &ts, 0); 164 if (status == -1) 165 ALOGE("Failed to fire epilog watchdog timer"); 166 } 167 else 168 { 169 ALOGE("Failed to create epilog watchdog timer"); 170 hc_cb.epilog_timer_created = 0; 171 } 172 } 173 174 /***************************************************************************** 175 ** 176 ** BLUETOOTH HOST/CONTROLLER INTERFACE LIBRARY FUNCTIONS 177 ** 178 *****************************************************************************/ 179 180 static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr) 181 { 182 pthread_attr_t thread_attr; 183 struct sched_param param; 184 int policy, result; 185 186 ALOGI("init"); 187 188 if (p_cb == NULL) 189 { 190 ALOGE("init failed with no user callbacks!"); 191 return BT_HC_STATUS_FAIL; 192 } 193 194 hc_cb.epilog_timer_created = 0; 195 fwcfg_acked = FALSE; 196 197 /* store reference to user callbacks */ 198 bt_hc_cbacks = (bt_hc_callbacks_t *) p_cb; 199 200 init_vnd_if(local_bdaddr); 201 202 utils_init(); 203 #ifdef HCI_USE_MCT 204 extern tHCI_IF hci_mct_func_table; 205 p_hci_if = &hci_mct_func_table; 206 #else 207 extern tHCI_IF hci_h4_func_table; 208 p_hci_if = &hci_h4_func_table; 209 #endif 210 211 p_hci_if->init(); 212 213 userial_init(); 214 lpm_init(); 215 216 utils_queue_init(&tx_q); 217 218 if (lib_running) 219 { 220 ALOGW("init has been called repeatedly without calling cleanup ?"); 221 } 222 223 lib_running = 1; 224 ready_events = 0; 225 pthread_mutex_init(&hc_cb.mutex, NULL); 226 pthread_cond_init(&hc_cb.cond, NULL); 227 pthread_attr_init(&thread_attr); 228 229 if (pthread_create(&hc_cb.worker_thread, &thread_attr, \ 230 bt_hc_worker_thread, NULL) != 0) 231 { 232 ALOGE("pthread_create failed!"); 233 lib_running = 0; 234 return BT_HC_STATUS_FAIL; 235 } 236 237 if(pthread_getschedparam(hc_cb.worker_thread, &policy, ¶m)==0) 238 { 239 policy = BTHC_LINUX_BASE_POLICY; 240 #if (BTHC_LINUX_BASE_POLICY!=SCHED_NORMAL) 241 param.sched_priority = BTHC_MAIN_THREAD_PRIORITY; 242 #endif 243 result = pthread_setschedparam(hc_cb.worker_thread, policy, ¶m); 244 if (result != 0) 245 { 246 ALOGW("libbt-hci init: pthread_setschedparam failed (%s)", \ 247 strerror(result)); 248 } 249 } 250 251 return BT_HC_STATUS_SUCCESS; 252 } 253 254 255 /** Chip power control */ 256 static void set_power(bt_hc_chip_power_state_t state) 257 { 258 int pwr_state; 259 260 BTHCDBG("set_power %d", state); 261 262 /* Calling vendor-specific part */ 263 pwr_state = (state == BT_HC_CHIP_PWR_ON) ? BT_VND_PWR_ON : BT_VND_PWR_OFF; 264 265 if (bt_vnd_if) 266 bt_vnd_if->op(BT_VND_OP_POWER_CTRL, &pwr_state); 267 else 268 ALOGE("vendor lib is missing!"); 269 } 270 271 272 /** Configure low power mode wake state */ 273 static int lpm(bt_hc_low_power_event_t event) 274 { 275 uint8_t status = TRUE; 276 277 switch (event) 278 { 279 case BT_HC_LPM_DISABLE: 280 bthc_signal_event(HC_EVENT_LPM_DISABLE); 281 break; 282 283 case BT_HC_LPM_ENABLE: 284 bthc_signal_event(HC_EVENT_LPM_ENABLE); 285 break; 286 287 case BT_HC_LPM_WAKE_ASSERT: 288 bthc_signal_event(HC_EVENT_LPM_WAKE_DEVICE); 289 break; 290 291 case BT_HC_LPM_WAKE_DEASSERT: 292 bthc_signal_event(HC_EVENT_LPM_ALLOW_SLEEP); 293 break; 294 } 295 296 return(status == TRUE) ? BT_HC_STATUS_SUCCESS : BT_HC_STATUS_FAIL; 297 } 298 299 300 /** Called prio to stack initialization */ 301 static void preload(TRANSAC transac) 302 { 303 BTHCDBG("preload"); 304 bthc_signal_event(HC_EVENT_PRELOAD); 305 } 306 307 308 /** Called post stack initialization */ 309 static void postload(TRANSAC transac) 310 { 311 BTHCDBG("postload"); 312 bthc_signal_event(HC_EVENT_POSTLOAD); 313 } 314 315 316 /** Transmit frame */ 317 static int transmit_buf(TRANSAC transac, char *p_buf, int len) 318 { 319 utils_enqueue(&tx_q, (void *) transac); 320 321 bthc_signal_event(HC_EVENT_TX); 322 323 return BT_HC_STATUS_SUCCESS; 324 } 325 326 327 /** Controls receive flow */ 328 static int set_rxflow(bt_rx_flow_state_t state) 329 { 330 BTHCDBG("set_rxflow %d", state); 331 332 userial_ioctl(\ 333 ((state == BT_RXFLOW_ON) ? USERIAL_OP_RXFLOW_ON : USERIAL_OP_RXFLOW_OFF), \ 334 NULL); 335 336 return BT_HC_STATUS_SUCCESS; 337 } 338 339 340 /** Controls HCI logging on/off */ 341 static int logging(bt_hc_logging_state_t state, char *p_path) 342 { 343 BTHCDBG("logging %d", state); 344 345 if (state == BT_HC_LOGGING_ON) 346 { 347 if (p_path != NULL) 348 btsnoop_open(p_path); 349 } 350 else 351 { 352 btsnoop_close(); 353 } 354 355 return BT_HC_STATUS_SUCCESS; 356 } 357 358 359 /** Closes the interface */ 360 static void cleanup( void ) 361 { 362 BTHCDBG("cleanup"); 363 364 if (lib_running) 365 { 366 if (fwcfg_acked == TRUE) 367 { 368 epilog_wait_timer(); 369 bthc_signal_event(HC_EVENT_EPILOG); 370 } 371 else 372 { 373 bthc_signal_event(HC_EVENT_EXIT); 374 } 375 376 pthread_join(hc_cb.worker_thread, NULL); 377 378 if (hc_cb.epilog_timer_created == 1) 379 { 380 timer_delete(hc_cb.epilog_timer_id); 381 hc_cb.epilog_timer_created = 0; 382 } 383 } 384 385 lib_running = 0; 386 387 lpm_cleanup(); 388 userial_close(); 389 p_hci_if->cleanup(); 390 utils_cleanup(); 391 392 /* Calling vendor-specific part */ 393 if (bt_vnd_if) 394 bt_vnd_if->cleanup(); 395 396 fwcfg_acked = FALSE; 397 bt_hc_cbacks = NULL; 398 } 399 400 401 static const bt_hc_interface_t bluetoothHCLibInterface = { 402 sizeof(bt_hc_interface_t), 403 init, 404 set_power, 405 lpm, 406 preload, 407 postload, 408 transmit_buf, 409 set_rxflow, 410 logging, 411 cleanup 412 }; 413 414 415 /******************************************************************************* 416 ** 417 ** Function bt_hc_worker_thread 418 ** 419 ** Description Mian worker thread 420 ** 421 ** Returns void * 422 ** 423 *******************************************************************************/ 424 static void *bt_hc_worker_thread(void *arg) 425 { 426 uint16_t events; 427 HC_BT_HDR *p_msg, *p_next_msg; 428 429 ALOGI("bt_hc_worker_thread started"); 430 prctl(PR_SET_NAME, (unsigned long)"bt_hc_worker", 0, 0, 0); 431 tx_cmd_pkts_pending = FALSE; 432 433 raise_priority_a2dp(TASK_HIGH_HCI_WORKER); 434 435 while (lib_running) 436 { 437 pthread_mutex_lock(&hc_cb.mutex); 438 while (ready_events == 0) 439 { 440 pthread_cond_wait(&hc_cb.cond, &hc_cb.mutex); 441 } 442 events = ready_events; 443 ready_events = 0; 444 pthread_mutex_unlock(&hc_cb.mutex); 445 446 #ifndef HCI_USE_MCT 447 if (events & HC_EVENT_RX) 448 { 449 p_hci_if->rcv(); 450 451 if ((tx_cmd_pkts_pending == TRUE) && (num_hci_cmd_pkts > 0)) 452 { 453 /* Got HCI Cmd Credits from Controller. 454 * Prepare to send prior pending Cmd packets in the 455 * following HC_EVENT_TX session. 456 */ 457 events |= HC_EVENT_TX; 458 } 459 } 460 #endif 461 462 if (events & HC_EVENT_PRELOAD) 463 { 464 userial_open(USERIAL_PORT_1); 465 466 /* Calling vendor-specific part */ 467 if (bt_vnd_if) 468 { 469 bt_vnd_if->op(BT_VND_OP_FW_CFG, NULL); 470 } 471 else 472 { 473 if (bt_hc_cbacks) 474 bt_hc_cbacks->preload_cb(NULL, BT_HC_PRELOAD_FAIL); 475 } 476 } 477 478 if (events & HC_EVENT_POSTLOAD) 479 { 480 /* Start from SCO related H/W configuration, if SCO configuration 481 * is required. Then, follow with reading requests of getting 482 * ACL data length for both BR/EDR and LE. 483 */ 484 int result = -1; 485 486 /* Calling vendor-specific part */ 487 if (bt_vnd_if) 488 result = bt_vnd_if->op(BT_VND_OP_SCO_CFG, NULL); 489 490 if (result == -1) 491 p_hci_if->get_acl_max_len(); 492 } 493 494 if (events & HC_EVENT_TX) 495 { 496 /* 497 * We will go through every packets in the tx queue. 498 * Fine to clear tx_cmd_pkts_pending. 499 */ 500 tx_cmd_pkts_pending = FALSE; 501 HC_BT_HDR * sending_msg_que[64]; 502 int sending_msg_count = 0; 503 int sending_hci_cmd_pkts_count = 0; 504 utils_lock(); 505 p_next_msg = tx_q.p_first; 506 while (p_next_msg && sending_msg_count < 507 (int)sizeof(sending_msg_que)/sizeof(sending_msg_que[0])) 508 { 509 if ((p_next_msg->event & MSG_EVT_MASK)==MSG_STACK_TO_HC_HCI_CMD) 510 { 511 /* 512 * if we have used up controller's outstanding HCI command 513 * credits (normally is 1), skip all HCI command packets in 514 * the queue. 515 * The pending command packets will be sent once controller 516 * gives back us credits through CommandCompleteEvent or 517 * CommandStatusEvent. 518 */ 519 if ((tx_cmd_pkts_pending == TRUE) || 520 (sending_hci_cmd_pkts_count >= num_hci_cmd_pkts)) 521 { 522 tx_cmd_pkts_pending = TRUE; 523 p_next_msg = utils_getnext(p_next_msg); 524 continue; 525 } 526 sending_hci_cmd_pkts_count++; 527 } 528 529 p_msg = p_next_msg; 530 p_next_msg = utils_getnext(p_msg); 531 utils_remove_from_queue_unlocked(&tx_q, p_msg); 532 sending_msg_que[sending_msg_count++] = p_msg; 533 } 534 utils_unlock(); 535 int i; 536 for(i = 0; i < sending_msg_count; i++) 537 p_hci_if->send(sending_msg_que[i]); 538 if (tx_cmd_pkts_pending == TRUE) 539 BTHCDBG("Used up Tx Cmd credits"); 540 541 } 542 543 if (events & HC_EVENT_LPM_ENABLE) 544 { 545 lpm_enable(TRUE); 546 } 547 548 if (events & HC_EVENT_LPM_DISABLE) 549 { 550 lpm_enable(FALSE); 551 } 552 553 if (events & HC_EVENT_LPM_IDLE_TIMEOUT) 554 { 555 lpm_wake_deassert(); 556 } 557 558 if (events & HC_EVENT_LPM_ALLOW_SLEEP) 559 { 560 lpm_allow_bt_device_sleep(); 561 } 562 563 if (events & HC_EVENT_LPM_WAKE_DEVICE) 564 { 565 lpm_wake_assert(); 566 } 567 568 if (events & HC_EVENT_EPILOG) 569 { 570 /* Calling vendor-specific part */ 571 if (bt_vnd_if) 572 bt_vnd_if->op(BT_VND_OP_EPILOG, NULL); 573 else 574 break; // equivalent to HC_EVENT_EXIT 575 } 576 577 if (events & HC_EVENT_EXIT) 578 break; 579 } 580 581 ALOGI("bt_hc_worker_thread exiting"); 582 lib_running = 0; 583 584 pthread_exit(NULL); 585 586 return NULL; // compiler friendly 587 } 588 589 590 /******************************************************************************* 591 ** 592 ** Function bt_hc_get_interface 593 ** 594 ** Description Caller calls this function to get API instance 595 ** 596 ** Returns API table 597 ** 598 *******************************************************************************/ 599 const bt_hc_interface_t *bt_hc_get_interface(void) 600 { 601 return &bluetoothHCLibInterface; 602 } 603 604