• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
bthc_signal_event(uint16_t event)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 *******************************************************************************/
epilog_wait_timeout(union sigval arg)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 *******************************************************************************/
epilog_wait_timer(void)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 
init(const bt_hc_callbacks_t * p_cb,unsigned char * local_bdaddr)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 */
set_power(bt_hc_chip_power_state_t state)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 */
lpm(bt_hc_low_power_event_t event)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 */
preload(TRANSAC transac)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 */
postload(TRANSAC transac)309 static void postload(TRANSAC transac)
310 {
311     BTHCDBG("postload");
312     bthc_signal_event(HC_EVENT_POSTLOAD);
313 }
314 
315 
316 /** Transmit frame */
transmit_buf(TRANSAC transac,char * p_buf,int len)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 */
set_rxflow(bt_rx_flow_state_t state)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 */
logging(bt_hc_logging_state_t state,char * p_path)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 */
cleanup(void)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 *******************************************************************************/
bt_hc_worker_thread(void * arg)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 *******************************************************************************/
bt_hc_get_interface(void)599 const bt_hc_interface_t *bt_hc_get_interface(void)
600 {
601     return &bluetoothHCLibInterface;
602 }
603 
604