Home | History | Annotate | Download | only in src
      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 <assert.h>
     31 #include <utils/Log.h>
     32 
     33 #include "btsnoop.h"
     34 #include "bt_hci_bdroid.h"
     35 #include "bt_utils.h"
     36 #include "bt_vendor_lib.h"
     37 #include "hci.h"
     38 #include "osi.h"
     39 #include "thread.h"
     40 #include "userial.h"
     41 #include "utils.h"
     42 #include "vendor.h"
     43 
     44 #ifndef BTHC_DBG
     45 #define BTHC_DBG FALSE
     46 #endif
     47 
     48 #if (BTHC_DBG == TRUE)
     49 #define BTHCDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
     50 #else
     51 #define BTHCDBG(param, ...) {}
     52 #endif
     53 
     54 /* Vendor epilog process timeout period  */
     55 static const uint32_t EPILOG_TIMEOUT_MS = 3000;
     56 
     57 /******************************************************************************
     58 **  Externs
     59 ******************************************************************************/
     60 
     61 extern int num_hci_cmd_pkts;
     62 void lpm_init(void);
     63 void lpm_cleanup(void);
     64 void lpm_enable(uint8_t turn_on);
     65 void lpm_wake_deassert(void);
     66 void lpm_allow_bt_device_sleep(void);
     67 void lpm_wake_assert(void);
     68 void init_vnd_if(unsigned char *local_bdaddr);
     69 
     70 /******************************************************************************
     71 **  Variables
     72 ******************************************************************************/
     73 
     74 bt_hc_callbacks_t *bt_hc_cbacks = NULL;
     75 tHCI_IF *p_hci_if;
     76 volatile bool fwcfg_acked;
     77 // Cleanup state indication.
     78 volatile bool has_cleaned_up = false;
     79 
     80 /******************************************************************************
     81 **  Local type definitions
     82 ******************************************************************************/
     83 
     84 /* Host/Controller lib thread control block */
     85 typedef struct
     86 {
     87     thread_t        *worker_thread;
     88     pthread_mutex_t worker_thread_lock;
     89     bool            epilog_timer_created;
     90     timer_t         epilog_timer_id;
     91 } bt_hc_cb_t;
     92 
     93 /******************************************************************************
     94 **  Static Variables
     95 ******************************************************************************/
     96 
     97 static bt_hc_cb_t hc_cb;
     98 static bool tx_cmd_pkts_pending = false;
     99 static BUFFER_Q tx_q;
    100 
    101 /******************************************************************************
    102 **  Functions
    103 ******************************************************************************/
    104 
    105 static void event_preload(UNUSED_ATTR void *context) {
    106   userial_open(USERIAL_PORT_1);
    107   vendor_send_command(BT_VND_OP_FW_CFG, NULL);
    108 }
    109 
    110 static void event_postload(UNUSED_ATTR void *context) {
    111   /* Start from SCO related H/W configuration, if SCO configuration
    112    * is required. Then, follow with reading requests of getting
    113    * ACL data length for both BR/EDR and LE.
    114    */
    115   int result = vendor_send_command(BT_VND_OP_SCO_CFG, NULL);
    116   if (result == -1)
    117     p_hci_if->get_acl_max_len();
    118 }
    119 
    120 static void event_tx(UNUSED_ATTR void *context) {
    121   /*
    122    *  We will go through every packets in the tx queue.
    123    *  Fine to clear tx_cmd_pkts_pending.
    124    */
    125   tx_cmd_pkts_pending = false;
    126   HC_BT_HDR *sending_msg_que[64];
    127   size_t sending_msg_count = 0;
    128   int sending_hci_cmd_pkts_count = 0;
    129   utils_lock();
    130   HC_BT_HDR *p_next_msg = tx_q.p_first;
    131   while (p_next_msg && sending_msg_count < ARRAY_SIZE(sending_msg_que))
    132   {
    133     if ((p_next_msg->event & MSG_EVT_MASK)==MSG_STACK_TO_HC_HCI_CMD)
    134     {
    135       /*
    136        *  if we have used up controller's outstanding HCI command
    137        *  credits (normally is 1), skip all HCI command packets in
    138        *  the queue.
    139        *  The pending command packets will be sent once controller
    140        *  gives back us credits through CommandCompleteEvent or
    141        *  CommandStatusEvent.
    142        */
    143       if (tx_cmd_pkts_pending ||
    144           (sending_hci_cmd_pkts_count >= num_hci_cmd_pkts))
    145       {
    146         tx_cmd_pkts_pending = true;
    147         p_next_msg = utils_getnext(p_next_msg);
    148         continue;
    149       }
    150       sending_hci_cmd_pkts_count++;
    151     }
    152 
    153     HC_BT_HDR *p_msg = p_next_msg;
    154     p_next_msg = utils_getnext(p_msg);
    155     utils_remove_from_queue_unlocked(&tx_q, p_msg);
    156     sending_msg_que[sending_msg_count++] = p_msg;
    157   }
    158   utils_unlock();
    159   for(size_t i = 0; i < sending_msg_count; i++)
    160     p_hci_if->send(sending_msg_que[i]);
    161   if (tx_cmd_pkts_pending)
    162     BTHCDBG("Used up Tx Cmd credits");
    163 }
    164 
    165 static void event_rx(UNUSED_ATTR void *context) {
    166 #ifndef HCI_USE_MCT
    167   p_hci_if->rcv();
    168 
    169   if (tx_cmd_pkts_pending && num_hci_cmd_pkts > 0) {
    170     // Got HCI Cmd credits from controller. Send whatever data
    171     // we have in our tx queue. We can call |event_tx| directly
    172     // here since we're already on the worker thread.
    173     event_tx(NULL);
    174   }
    175 #endif
    176 }
    177 
    178 static void event_lpm_enable(UNUSED_ATTR void *context) {
    179   lpm_enable(true);
    180 }
    181 
    182 static void event_lpm_disable(UNUSED_ATTR void *context) {
    183   lpm_enable(false);
    184 }
    185 
    186 static void event_lpm_wake_device(UNUSED_ATTR void *context) {
    187   lpm_wake_assert();
    188 }
    189 
    190 static void event_lpm_allow_sleep(UNUSED_ATTR void *context) {
    191   lpm_allow_bt_device_sleep();
    192 }
    193 
    194 static void event_lpm_idle_timeout(UNUSED_ATTR void *context) {
    195   lpm_wake_deassert();
    196 }
    197 
    198 static void event_epilog(UNUSED_ATTR void *context) {
    199   vendor_send_command(BT_VND_OP_EPILOG, NULL);
    200 }
    201 
    202 static void event_tx_cmd(void *msg) {
    203   HC_BT_HDR *p_msg = (HC_BT_HDR *)msg;
    204 
    205   BTHCDBG("%s: p_msg: %p, event: 0x%x", __func__, p_msg, p_msg->event);
    206 
    207   int event = p_msg->event & MSG_EVT_MASK;
    208   int sub_event = p_msg->event & MSG_SUB_EVT_MASK;
    209   if (event == MSG_CTRL_TO_HC_CMD && sub_event == BT_HC_AUDIO_STATE) {
    210     vendor_send_command(BT_VND_OP_SET_AUDIO_STATE, p_msg->data);
    211   } else {
    212     ALOGW("%s (event: 0x%x, sub_event: 0x%x) not supported", __func__, event, sub_event);
    213   }
    214 
    215   bt_hc_cbacks->dealloc(msg);
    216 }
    217 
    218 void bthc_rx_ready(void) {
    219   pthread_mutex_lock(&hc_cb.worker_thread_lock);
    220 
    221   if (hc_cb.worker_thread)
    222     thread_post(hc_cb.worker_thread, event_rx, NULL);
    223 
    224   pthread_mutex_unlock(&hc_cb.worker_thread_lock);
    225 }
    226 
    227 void bthc_tx(HC_BT_HDR *buf) {
    228   pthread_mutex_lock(&hc_cb.worker_thread_lock);
    229 
    230   if (hc_cb.worker_thread) {
    231     if (buf)
    232       utils_enqueue(&tx_q, buf);
    233     thread_post(hc_cb.worker_thread, event_tx, NULL);
    234   }
    235 
    236   pthread_mutex_unlock(&hc_cb.worker_thread_lock);
    237 }
    238 
    239 void bthc_idle_timeout(void) {
    240   pthread_mutex_lock(&hc_cb.worker_thread_lock);
    241 
    242   if (hc_cb.worker_thread)
    243     thread_post(hc_cb.worker_thread, event_lpm_idle_timeout, NULL);
    244 
    245   pthread_mutex_unlock(&hc_cb.worker_thread_lock);
    246 }
    247 
    248 /*******************************************************************************
    249 **
    250 ** Function        epilog_wait_timeout
    251 **
    252 ** Description     Timeout thread of epilog watchdog timer
    253 **
    254 ** Returns         None
    255 **
    256 *******************************************************************************/
    257 static void epilog_wait_timeout(UNUSED_ATTR union sigval arg)
    258 {
    259     ALOGI("...epilog_wait_timeout...");
    260 
    261     thread_free(hc_cb.worker_thread);
    262 
    263     pthread_mutex_lock(&hc_cb.worker_thread_lock);
    264     hc_cb.worker_thread = NULL;
    265     pthread_mutex_unlock(&hc_cb.worker_thread_lock);
    266 }
    267 
    268 /*******************************************************************************
    269 **
    270 ** Function        epilog_wait_timer
    271 **
    272 ** Description     Launch epilog watchdog timer
    273 **
    274 ** Returns         None
    275 **
    276 *******************************************************************************/
    277 static void epilog_wait_timer(void)
    278 {
    279     int status;
    280     struct itimerspec ts;
    281     struct sigevent se;
    282     uint32_t timeout_ms = EPILOG_TIMEOUT_MS;
    283 
    284     se.sigev_notify = SIGEV_THREAD;
    285     se.sigev_value.sival_ptr = &hc_cb.epilog_timer_id;
    286     se.sigev_notify_function = epilog_wait_timeout;
    287     se.sigev_notify_attributes = NULL;
    288 
    289     status = timer_create(CLOCK_MONOTONIC, &se, &hc_cb.epilog_timer_id);
    290 
    291     if (status == 0)
    292     {
    293         hc_cb.epilog_timer_created = true;
    294         ts.it_value.tv_sec = timeout_ms/1000;
    295         ts.it_value.tv_nsec = 1000000*(timeout_ms%1000);
    296         ts.it_interval.tv_sec = 0;
    297         ts.it_interval.tv_nsec = 0;
    298 
    299         status = timer_settime(hc_cb.epilog_timer_id, 0, &ts, 0);
    300         if (status == -1)
    301             ALOGE("Failed to fire epilog watchdog timer");
    302     }
    303     else
    304     {
    305         ALOGE("Failed to create epilog watchdog timer");
    306         hc_cb.epilog_timer_created = false;
    307     }
    308 }
    309 
    310 /*****************************************************************************
    311 **
    312 **   BLUETOOTH HOST/CONTROLLER INTERFACE LIBRARY FUNCTIONS
    313 **
    314 *****************************************************************************/
    315 
    316 static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr)
    317 {
    318     int result;
    319 
    320     ALOGI("init");
    321 
    322     if (p_cb == NULL)
    323     {
    324         ALOGE("init failed with no user callbacks!");
    325         return BT_HC_STATUS_FAIL;
    326     }
    327 
    328     hc_cb.epilog_timer_created = false;
    329     fwcfg_acked = false;
    330     has_cleaned_up = false;
    331 
    332     pthread_mutex_init(&hc_cb.worker_thread_lock, NULL);
    333 
    334     /* store reference to user callbacks */
    335     bt_hc_cbacks = (bt_hc_callbacks_t *) p_cb;
    336 
    337     vendor_open(local_bdaddr);
    338 
    339     utils_init();
    340 #ifdef HCI_USE_MCT
    341     extern tHCI_IF hci_mct_func_table;
    342     p_hci_if = &hci_mct_func_table;
    343 #else
    344     extern tHCI_IF hci_h4_func_table;
    345     p_hci_if = &hci_h4_func_table;
    346 #endif
    347 
    348     p_hci_if->init();
    349 
    350     userial_init();
    351     lpm_init();
    352 
    353     utils_queue_init(&tx_q);
    354 
    355     if (hc_cb.worker_thread)
    356     {
    357         ALOGW("init has been called repeatedly without calling cleanup ?");
    358     }
    359 
    360     // Set prio here and let hci worker thread inherit prio
    361     // remove once new thread api (thread_set_priority() ?)
    362     // can switch prio
    363     raise_priority_a2dp(TASK_HIGH_HCI_WORKER);
    364 
    365     hc_cb.worker_thread = thread_new("bt_hc_worker");
    366     if (!hc_cb.worker_thread) {
    367         ALOGE("%s unable to create worker thread.", __func__);
    368         return BT_HC_STATUS_FAIL;
    369     }
    370 
    371     return BT_HC_STATUS_SUCCESS;
    372 }
    373 
    374 
    375 /** Chip power control */
    376 static void set_power(bt_hc_chip_power_state_t state)
    377 {
    378     int pwr_state;
    379 
    380     BTHCDBG("set_power %d", state);
    381 
    382     /* Calling vendor-specific part */
    383     pwr_state = (state == BT_HC_CHIP_PWR_ON) ? BT_VND_PWR_ON : BT_VND_PWR_OFF;
    384 
    385     vendor_send_command(BT_VND_OP_POWER_CTRL, &pwr_state);
    386 }
    387 
    388 
    389 /** Configure low power mode wake state */
    390 static int lpm(bt_hc_low_power_event_t event)
    391 {
    392     switch (event)
    393     {
    394         case BT_HC_LPM_DISABLE:
    395             thread_post(hc_cb.worker_thread, event_lpm_disable, NULL);
    396             break;
    397 
    398         case BT_HC_LPM_ENABLE:
    399             thread_post(hc_cb.worker_thread, event_lpm_enable, NULL);
    400             break;
    401 
    402         case BT_HC_LPM_WAKE_ASSERT:
    403             thread_post(hc_cb.worker_thread, event_lpm_wake_device, NULL);
    404             break;
    405 
    406         case BT_HC_LPM_WAKE_DEASSERT:
    407             thread_post(hc_cb.worker_thread, event_lpm_allow_sleep, NULL);
    408             break;
    409     }
    410     return BT_HC_STATUS_SUCCESS;
    411 }
    412 
    413 
    414 /** Called prior to stack initialization */
    415 static void preload(UNUSED_ATTR TRANSAC transac) {
    416   BTHCDBG("preload");
    417   thread_post(hc_cb.worker_thread, event_preload, NULL);
    418 }
    419 
    420 /** Called post stack initialization */
    421 static void postload(UNUSED_ATTR TRANSAC transac) {
    422   BTHCDBG("postload");
    423   thread_post(hc_cb.worker_thread, event_postload, NULL);
    424 }
    425 
    426 /** Transmit frame */
    427 static int transmit_buf(TRANSAC transac, UNUSED_ATTR char *p_buf, UNUSED_ATTR int len) {
    428   bthc_tx((HC_BT_HDR *)transac);
    429   return BT_HC_STATUS_SUCCESS;
    430 }
    431 
    432 /** Controls HCI logging on/off */
    433 static int logging(bt_hc_logging_state_t state, char *p_path, bool save_existing) {
    434   BTHCDBG("logging %d", state);
    435 
    436   if (state != BT_HC_LOGGING_ON)
    437     btsnoop_close();
    438   else if (p_path != NULL)
    439     btsnoop_open(p_path, save_existing);
    440 
    441   return BT_HC_STATUS_SUCCESS;
    442 }
    443 
    444 /** sends command HC controller to configure platform specific behaviour */
    445 static int tx_hc_cmd(TRANSAC transac, char *p_buf, int len) {
    446   BTHCDBG("tx_hc_cmd: transac %p", transac);
    447 
    448   if (!transac)
    449     return BT_HC_STATUS_FAIL;
    450 
    451   thread_post(hc_cb.worker_thread, event_tx_cmd, transac);
    452   return BT_HC_STATUS_SUCCESS;
    453 }
    454 
    455 // Closes the interface.
    456 // This routine is not thread safe.
    457 static void cleanup(void)
    458 {
    459     if (has_cleaned_up) {
    460         ALOGW("%s Already cleaned up for this session\n", __func__);
    461         return;
    462     }
    463 
    464     BTHCDBG("cleanup");
    465 
    466     if (hc_cb.worker_thread)
    467     {
    468         if (fwcfg_acked)
    469         {
    470             epilog_wait_timer();
    471             // Stop reading thread
    472             userial_close_reader();
    473 
    474             thread_post(hc_cb.worker_thread, event_epilog, NULL);
    475         }
    476         thread_free(hc_cb.worker_thread);
    477 
    478         pthread_mutex_lock(&hc_cb.worker_thread_lock);
    479         hc_cb.worker_thread = NULL;
    480         pthread_mutex_unlock(&hc_cb.worker_thread_lock);
    481 
    482         if (hc_cb.epilog_timer_created)
    483         {
    484             timer_delete(hc_cb.epilog_timer_id);
    485             hc_cb.epilog_timer_created = false;
    486         }
    487     }
    488     BTHCDBG("%s Finalizing cleanup\n", __func__);
    489 
    490     lpm_cleanup();
    491     userial_close();
    492     p_hci_if->cleanup();
    493     utils_cleanup();
    494 
    495     set_power(BT_VND_PWR_OFF);
    496     vendor_close();
    497 
    498     pthread_mutex_destroy(&hc_cb.worker_thread_lock);
    499 
    500     fwcfg_acked = false;
    501     bt_hc_cbacks = NULL;
    502     has_cleaned_up = true;
    503 }
    504 
    505 static const bt_hc_interface_t bluetoothHCLibInterface = {
    506     sizeof(bt_hc_interface_t),
    507     init,
    508     set_power,
    509     lpm,
    510     preload,
    511     postload,
    512     transmit_buf,
    513     logging,
    514     cleanup,
    515     tx_hc_cmd,
    516 };
    517 
    518 /*******************************************************************************
    519 **
    520 ** Function        bt_hc_get_interface
    521 **
    522 ** Description     Caller calls this function to get API instance
    523 **
    524 ** Returns         API table
    525 **
    526 *******************************************************************************/
    527 const bt_hc_interface_t *bt_hc_get_interface(void)
    528 {
    529     return &bluetoothHCLibInterface;
    530 }
    531