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 <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, &param)==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, &param);
    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