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