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