Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d467290a authored by Sharvil Nanavati's avatar Sharvil Nanavati Committed by Android (Google) Code Review
Browse files

Merge "Revert "Revert "Clean up messy dispatch in bt_hci_bdroid by using new...

Merge "Revert "Revert "Clean up messy dispatch in bt_hci_bdroid by using new primitives.""" into lmp-dev
parents f2768e15 196019e6
Loading
Loading
Loading
Loading
+24 −51
Original line number Diff line number Diff line
@@ -27,8 +27,7 @@
 *
 ******************************************************************************/

#ifndef BT_HCI_BDROID_H
#define BT_HCI_BDROID_H
#pragma once

#include "bt_hci_lib.h"

@@ -40,48 +39,30 @@
**  Constants & Macros
******************************************************************************/

#if __STDC_VERSION__ < 199901L
#  ifndef FALSE
#    define FALSE 0
#  endif

#  ifndef TRUE
#    define TRUE (!FALSE)
#  endif

#ifndef BTHC_LINUX_BASE_POLICY
#define BTHC_LINUX_BASE_POLICY SCHED_NORMAL
#endif

#if (BTHC_LINUX_BASE_POLICY != SCHED_NORMAL)
#ifndef BTHC_LINUX_BASE_PRIORITY
#define BTHC_LINUX_BASE_PRIORITY 30
#else
#  include <stdbool.h>
#  ifndef FALSE
#    define FALSE  false
#  endif

#ifndef BTHC_USERIAL_READ_THREAD_PRIORITY
#define BTHC_USERIAL_READ_THREAD_PRIORITY (BTHC_LINUX_BASE_PRIORITY)
#  ifndef TRUE
#    define TRUE   true
#  endif

#ifndef BTHC_MAIN_THREAD_PRIORITY
#define BTHC_MAIN_THREAD_PRIORITY (BTHC_LINUX_BASE_PRIORITY-1)
#endif
#endif  // (BTHC_LINUX_BASE_POLICY != SCHED_NORMAL)

#define HCI_ACL_MAX_SIZE 1024
#define HCI_MAX_FRAME_SIZE (HCI_ACL_MAX_SIZE + 4)

/* Host/Controller lib internal event ID */
#define HC_EVENT_PRELOAD               0x0001
#define HC_EVENT_POSTLOAD              0x0002
#define HC_EVENT_RX                    0x0004
#define HC_EVENT_TX                    0x0008
#define HC_EVENT_LPM_ENABLE            0x0010
#define HC_EVENT_LPM_DISABLE           0x0020
#define HC_EVENT_LPM_WAKE_DEVICE       0x0040
#define HC_EVENT_LPM_ALLOW_SLEEP       0x0080
#define HC_EVENT_LPM_IDLE_TIMEOUT      0x0100
#define HC_EVENT_EXIT                  0x0200
#define HC_EVENT_EPILOG                0x0400
#define HC_EVENT_TX_CMD                0x0800
typedef enum {
  HC_EVENT_LPM_IDLE_TIMEOUT,
} bthc_event_t;

#define MSG_CTRL_TO_HC_CMD             0x0100 /* evt mask used by HC_EVENT_TX_CMD */

@@ -126,7 +107,6 @@ typedef struct

#define BT_HC_HDR_SIZE (sizeof(HC_BT_HDR))


typedef struct _hc_buffer_hdr
{
    struct _hc_buffer_hdr *p_next;   /* next buffer in the queue */
@@ -148,15 +128,8 @@ extern bt_hc_callbacks_t *bt_hc_cbacks;
**  Functions
******************************************************************************/

/*******************************************************************************
**
** Function        bthc_signal_event
**
** Description     Perform context switch to bt_hc main thread
**
** Returns         None
**
*******************************************************************************/
extern void bthc_signal_event(uint16_t event);

#endif /* BT_HCI_BDROID_H */
// Called when a buffer has been produced by the serial layer and should be
// processed by the HCI layer.
void bthc_rx_ready(void);
void bthc_tx(HC_BT_HDR *buf);
void bthc_idle_timeout(void);
+2 −0
Original line number Diff line number Diff line
@@ -2,6 +2,8 @@

#include <stdbool.h>

#include "bt_hci_bdroid.h"

void btsnoop_open(const char *p_path);
void btsnoop_close(void);

+184 −328
Original line number Diff line number Diff line
@@ -29,16 +29,17 @@

#include <assert.h>
#include <utils/Log.h>
#include <pthread.h>

#include "btsnoop.h"
#include "bt_hci_bdroid.h"
#include "bt_utils.h"
#include "bt_vendor_lib.h"
#include "utils.h"
#include "hci.h"
#include "osi.h"
#include "thread.h"
#include "userial.h"
#include "utils.h"
#include "vendor.h"
#include "bt_utils.h"
#include "btsnoop.h"
#include <sys/prctl.h>

#ifndef BTHC_DBG
#define BTHC_DBG FALSE
@@ -51,9 +52,7 @@
#endif

/* Vendor epilog process timeout period  */
#ifndef EPILOG_TIMEOUT_MS
#define EPILOG_TIMEOUT_MS 3000  // 3 seconds
#endif
static const uint32_t EPILOG_TIMEOUT_MS = 3000;

/******************************************************************************
**  Externs
@@ -73,9 +72,8 @@ void init_vnd_if(unsigned char *local_bdaddr);
******************************************************************************/

bt_hc_callbacks_t *bt_hc_cbacks = NULL;
BUFFER_Q tx_q;
tHCI_IF *p_hci_if;
volatile uint8_t fwcfg_acked;
volatile bool fwcfg_acked;

/******************************************************************************
**  Local type definitions
@@ -84,11 +82,8 @@ volatile uint8_t fwcfg_acked;
/* Host/Controller lib thread control block */
typedef struct
{
    pthread_t       worker_thread;
    pthread_mutex_t mutex;
    pthread_cond_t  cond;
    BUFFER_Q        cmd_q;
    uint8_t         epilog_timer_created;
    thread_t        *worker_thread;
    bool            epilog_timer_created;
    timer_t         epilog_timer_id;
} bt_hc_cb_t;

@@ -97,22 +92,138 @@ typedef struct
******************************************************************************/

static bt_hc_cb_t hc_cb;
static volatile uint8_t lib_running = 0;
static volatile uint16_t ready_events = 0;
static volatile uint8_t tx_cmd_pkts_pending = FALSE;
static bool tx_cmd_pkts_pending = false;
static BUFFER_Q tx_q;

/******************************************************************************
**  Functions
******************************************************************************/

static void *bt_hc_worker_thread(void *arg);
static void event_preload(UNUSED_ATTR void *context) {
  userial_open(USERIAL_PORT_1);
  vendor_send_command(BT_VND_OP_FW_CFG, NULL);
}

static void event_postload(UNUSED_ATTR void *context) {
  /* Start from SCO related H/W configuration, if SCO configuration
   * is required. Then, follow with reading requests of getting
   * ACL data length for both BR/EDR and LE.
   */
  int result = vendor_send_command(BT_VND_OP_SCO_CFG, NULL);
  if (result == -1)
    p_hci_if->get_acl_max_len();
}

void bthc_signal_event(uint16_t event)
static void event_tx(UNUSED_ATTR void *context) {
  /*
   *  We will go through every packets in the tx queue.
   *  Fine to clear tx_cmd_pkts_pending.
   */
  tx_cmd_pkts_pending = false;
  HC_BT_HDR *sending_msg_que[64];
  size_t sending_msg_count = 0;
  int sending_hci_cmd_pkts_count = 0;
  utils_lock();
  HC_BT_HDR *p_next_msg = tx_q.p_first;
  while (p_next_msg && sending_msg_count < ARRAY_SIZE(sending_msg_que))
  {
    if ((p_next_msg->event & MSG_EVT_MASK)==MSG_STACK_TO_HC_HCI_CMD)
    {
    pthread_mutex_lock(&hc_cb.mutex);
    ready_events |= event;
    pthread_cond_signal(&hc_cb.cond);
    pthread_mutex_unlock(&hc_cb.mutex);
      /*
       *  if we have used up controller's outstanding HCI command
       *  credits (normally is 1), skip all HCI command packets in
       *  the queue.
       *  The pending command packets will be sent once controller
       *  gives back us credits through CommandCompleteEvent or
       *  CommandStatusEvent.
       */
      if (tx_cmd_pkts_pending ||
          (sending_hci_cmd_pkts_count >= num_hci_cmd_pkts))
      {
        tx_cmd_pkts_pending = true;
        p_next_msg = utils_getnext(p_next_msg);
        continue;
      }
      sending_hci_cmd_pkts_count++;
    }

    HC_BT_HDR *p_msg = p_next_msg;
    p_next_msg = utils_getnext(p_msg);
    utils_remove_from_queue_unlocked(&tx_q, p_msg);
    sending_msg_que[sending_msg_count++] = p_msg;
  }
  utils_unlock();
  for(size_t i = 0; i < sending_msg_count; i++)
    p_hci_if->send(sending_msg_que[i]);
  if (tx_cmd_pkts_pending)
    BTHCDBG("Used up Tx Cmd credits");
}

static void event_rx(UNUSED_ATTR void *context) {
#ifndef HCI_USE_MCT
  p_hci_if->rcv();

  if (tx_cmd_pkts_pending && num_hci_cmd_pkts > 0) {
    // Got HCI Cmd credits from controller. Send whatever data
    // we have in our tx queue. We can call |event_tx| directly
    // here since we're already on the worker thread.
    event_tx(NULL);
  }
#endif
}

static void event_lpm_enable(UNUSED_ATTR void *context) {
  lpm_enable(true);
}

static void event_lpm_disable(UNUSED_ATTR void *context) {
  lpm_enable(false);
}

static void event_lpm_wake_device(UNUSED_ATTR void *context) {
  lpm_wake_assert();
}

static void event_lpm_allow_sleep(UNUSED_ATTR void *context) {
  lpm_allow_bt_device_sleep();
}

static void event_lpm_idle_timeout(UNUSED_ATTR void *context) {
  lpm_wake_deassert();
}

static void event_epilog(UNUSED_ATTR void *context) {
  vendor_send_command(BT_VND_OP_EPILOG, NULL);
}

static void event_tx_cmd(void *msg) {
  HC_BT_HDR *p_msg = (HC_BT_HDR *)msg;

  BTHCDBG("%s: p_msg: %p, event: 0x%x", __func__, p_msg, p_msg->event);

  int event = p_msg->event & MSG_EVT_MASK;
  int sub_event = p_msg->event & MSG_SUB_EVT_MASK;
  if (event == MSG_CTRL_TO_HC_CMD && sub_event == BT_HC_AUDIO_STATE) {
    vendor_send_command(BT_VND_OP_SET_AUDIO_STATE, p_msg->data);
  } else {
    ALOGW("%s (event: 0x%x, sub_event: 0x%x) not supported", __func__, event, sub_event);
  }

  bt_hc_cbacks->dealloc(msg);
}

void bthc_rx_ready(void) {
  thread_post(hc_cb.worker_thread, event_rx, NULL);
}

void bthc_tx(HC_BT_HDR *buf) {
  if (buf)
    utils_enqueue(&tx_q, buf);
  thread_post(hc_cb.worker_thread, event_tx, NULL);
}

void bthc_idle_timeout(void) {
  thread_post(hc_cb.worker_thread, event_lpm_idle_timeout, NULL);
}

/*******************************************************************************
@@ -124,11 +235,11 @@ void bthc_signal_event(uint16_t event)
** Returns         None
**
*******************************************************************************/
static void epilog_wait_timeout(union sigval arg)
static void epilog_wait_timeout(UNUSED_ATTR union sigval arg)
{
    UNUSED(arg);
    ALOGI("...epilog_wait_timeout...");
    bthc_signal_event(HC_EVENT_EXIT);
    thread_free(hc_cb.worker_thread);
    hc_cb.worker_thread = NULL;
}

/*******************************************************************************
@@ -156,7 +267,7 @@ static void epilog_wait_timer(void)

    if (status == 0)
    {
        hc_cb.epilog_timer_created = 1;
        hc_cb.epilog_timer_created = true;
        ts.it_value.tv_sec = timeout_ms/1000;
        ts.it_value.tv_nsec = 1000000*(timeout_ms%1000);
        ts.it_interval.tv_sec = 0;
@@ -169,7 +280,7 @@ static void epilog_wait_timer(void)
    else
    {
        ALOGE("Failed to create epilog watchdog timer");
        hc_cb.epilog_timer_created = 0;
        hc_cb.epilog_timer_created = false;
    }
}

@@ -181,9 +292,7 @@ static void epilog_wait_timer(void)

static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr)
{
    pthread_attr_t thread_attr;
    struct sched_param param;
    int policy, result;
    int result;

    ALOGI("init");

@@ -193,8 +302,8 @@ static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr)
        return BT_HC_STATUS_FAIL;
    }

    hc_cb.epilog_timer_created = 0;
    fwcfg_acked = FALSE;
    hc_cb.epilog_timer_created = false;
    fwcfg_acked = false;

    /* store reference to user callbacks */
    bt_hc_cbacks = (bt_hc_callbacks_t *) p_cb;
@@ -217,41 +326,18 @@ static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr)

    utils_queue_init(&tx_q);

    if (lib_running)
    if (hc_cb.worker_thread)
    {
        ALOGW("init has been called repeatedly without calling cleanup ?");
    }

    lib_running = 1;
    ready_events = 0;
    utils_queue_init(&hc_cb.cmd_q);
    pthread_mutex_init(&hc_cb.mutex, NULL);
    pthread_cond_init(&hc_cb.cond, NULL);
    pthread_attr_init(&thread_attr);

    if (pthread_create(&hc_cb.worker_thread, &thread_attr, \
                       bt_hc_worker_thread, NULL) != 0)
    {
        ALOGE("pthread_create failed!");
        lib_running = 0;
    hc_cb.worker_thread = thread_new("bt_hc_worker");
    if (!hc_cb.worker_thread) {
        ALOGE("%s unable to create worker thread.", __func__);
        return BT_HC_STATUS_FAIL;
    }

    if(pthread_getschedparam(hc_cb.worker_thread, &policy, &param)==0)
    {
        policy = BTHC_LINUX_BASE_POLICY;
#if (BTHC_LINUX_BASE_POLICY != SCHED_NORMAL)
        param.sched_priority = BTHC_MAIN_THREAD_PRIORITY;
#else
        param.sched_priority = 0;
#endif
        result = pthread_setschedparam(hc_cb.worker_thread, policy, &param);
        if (result != 0)
        {
            ALOGW("libbt-hci init: pthread_setschedparam failed (%s)", \
                  strerror(result));
        }
    }
    // TODO(sharvil): increase thread priority (raise_priority_a2dp)

    return BT_HC_STATUS_SUCCESS;
}
@@ -274,122 +360,67 @@ static void set_power(bt_hc_chip_power_state_t state)
/** Configure low power mode wake state */
static int lpm(bt_hc_low_power_event_t event)
{
    uint8_t status = TRUE;

    switch (event)
    {
        case BT_HC_LPM_DISABLE:
            bthc_signal_event(HC_EVENT_LPM_DISABLE);
            thread_post(hc_cb.worker_thread, event_lpm_disable, NULL);
            break;

        case BT_HC_LPM_ENABLE:
            bthc_signal_event(HC_EVENT_LPM_ENABLE);
            thread_post(hc_cb.worker_thread, event_lpm_enable, NULL);
            break;

        case BT_HC_LPM_WAKE_ASSERT:
            bthc_signal_event(HC_EVENT_LPM_WAKE_DEVICE);
            thread_post(hc_cb.worker_thread, event_lpm_wake_device, NULL);
            break;

        case BT_HC_LPM_WAKE_DEASSERT:
            bthc_signal_event(HC_EVENT_LPM_ALLOW_SLEEP);
            thread_post(hc_cb.worker_thread, event_lpm_allow_sleep, NULL);
            break;
    }

    return(status == TRUE) ? BT_HC_STATUS_SUCCESS : BT_HC_STATUS_FAIL;
    return BT_HC_STATUS_SUCCESS;
}


/** Called prior to stack initialization */
static void preload(TRANSAC transac)
{
    UNUSED(transac);
static void preload(UNUSED_ATTR TRANSAC transac) {
  BTHCDBG("preload");
    bthc_signal_event(HC_EVENT_PRELOAD);
  thread_post(hc_cb.worker_thread, event_preload, NULL);
}


/** Called post stack initialization */
static void postload(TRANSAC transac)
{
    UNUSED(transac);
static void postload(UNUSED_ATTR TRANSAC transac) {
  BTHCDBG("postload");
    bthc_signal_event(HC_EVENT_POSTLOAD);
  thread_post(hc_cb.worker_thread, event_postload, NULL);
}


/** Transmit frame */
static int transmit_buf(TRANSAC transac, char * p_buf, int len)
{
    UNUSED(p_buf);
    UNUSED(len);
    utils_enqueue(&tx_q, (void *) transac);

    bthc_signal_event(HC_EVENT_TX);

static int transmit_buf(TRANSAC transac, UNUSED_ATTR char *p_buf, UNUSED_ATTR int len) {
  bthc_tx((HC_BT_HDR *)transac);
  return BT_HC_STATUS_SUCCESS;
}


/** Controls HCI logging on/off */
static int logging(bt_hc_logging_state_t state, char *p_path)
{
static int logging(bt_hc_logging_state_t state, char *p_path) {
  BTHCDBG("logging %d", state);

    if (state == BT_HC_LOGGING_ON)
    {
        if (p_path != NULL)
            btsnoop_open(p_path);
    }
    else
    {
  if (state != BT_HC_LOGGING_ON)
    btsnoop_close();
    }
  else if (p_path != NULL)
    btsnoop_open(p_path);

  return BT_HC_STATUS_SUCCESS;
}

/** sends command HC controller to configure platform specific behaviour */
static int tx_hc_cmd(TRANSAC transac, char *p_buf, int len)
{
static int tx_hc_cmd(TRANSAC transac, char *p_buf, int len) {
  BTHCDBG("tx_hc_cmd: transac %p", transac);
    if ((TRANSAC)0 != transac)
   {
        utils_enqueue(&hc_cb.cmd_q, (void *)transac);
        bthc_signal_event(HC_EVENT_TX_CMD);
        return BT_HC_STATUS_SUCCESS;
    }
    return BT_HC_STATUS_FAIL;
}

/** handle HC controller command to configure platform specific behaviour */
static int tx_hc_msg(HC_BT_HDR *p_msg)
{
    int ret_val = 0;
    int event, sub_event;
    BTHCDBG("tx_hc_msg: p_msg %p, event: 0x%x", (void *)p_msg, p_msg->event);
  if (!transac)
    return BT_HC_STATUS_FAIL;

    event = p_msg->event & MSG_EVT_MASK;
    sub_event = p_msg->event & MSG_SUB_EVT_MASK;
    switch (event)
    {
    case MSG_CTRL_TO_HC_CMD:
        {
            switch (sub_event)
            {
            case BT_HC_AUDIO_STATE:
                vendor_send_command(BT_VND_OP_SET_AUDIO_STATE, (p_msg+1));
                break;
            default:
                ALOGW("tx_hc_msg(sub_event: 0x%x) not supported", sub_event);
                break;
            }
        }
         break;
      default:
        ALOGW("tx_hc_msg(event: 0x%x) not supported", event);
        break;
   }
    return ret_val;
  thread_post(hc_cb.worker_thread, event_tx_cmd, transac);
  return BT_HC_STATUS_SUCCESS;
}

/** Closes the interface */
@@ -397,29 +428,24 @@ static void cleanup( void )
{
    BTHCDBG("cleanup");

    if (lib_running)
    if (hc_cb.worker_thread)
    {
        if (fwcfg_acked == TRUE)
        if (fwcfg_acked)
        {
            epilog_wait_timer();
            bthc_signal_event(HC_EVENT_EPILOG);
        }
        else
        {
            bthc_signal_event(HC_EVENT_EXIT);
            thread_post(hc_cb.worker_thread, event_epilog, NULL);
        }

        pthread_join(hc_cb.worker_thread, NULL);
        thread_free(hc_cb.worker_thread);
        hc_cb.worker_thread = NULL;

        if (hc_cb.epilog_timer_created == 1)
        if (hc_cb.epilog_timer_created)
        {
            timer_delete(hc_cb.epilog_timer_id);
            hc_cb.epilog_timer_created = 0;
            hc_cb.epilog_timer_created = false;
        }
    }

    lib_running = 0;

    lpm_cleanup();
    userial_close();
    p_hci_if->cleanup();
@@ -428,11 +454,10 @@ static void cleanup( void )
    set_power(BT_VND_PWR_OFF);
    vendor_close();

    fwcfg_acked = FALSE;
    fwcfg_acked = false;
    bt_hc_cbacks = NULL;
}


static const bt_hc_interface_t bluetoothHCLibInterface = {
    sizeof(bt_hc_interface_t),
    init,
@@ -446,174 +471,6 @@ static const bt_hc_interface_t bluetoothHCLibInterface = {
    tx_hc_cmd,
};


/*******************************************************************************
**
** Function        bt_hc_worker_thread
**
** Description     Mian worker thread
**
** Returns         void *
**
*******************************************************************************/
static void *bt_hc_worker_thread(void *arg)
{
    uint16_t events;
    HC_BT_HDR *p_msg, *p_next_msg;
    UNUSED(arg);

    ALOGI("bt_hc_worker_thread started");
    prctl(PR_SET_NAME, (unsigned long)"bt_hc_worker", 0, 0, 0);
    tx_cmd_pkts_pending = FALSE;

    raise_priority_a2dp(TASK_HIGH_HCI_WORKER);

    while (lib_running)
    {
        pthread_mutex_lock(&hc_cb.mutex);
        while (ready_events == 0)
        {
            pthread_cond_wait(&hc_cb.cond, &hc_cb.mutex);
        }
        events = ready_events;
        ready_events = 0;
        pthread_mutex_unlock(&hc_cb.mutex);

#ifndef HCI_USE_MCT
        if (events & HC_EVENT_RX)
        {
            p_hci_if->rcv();

            if ((tx_cmd_pkts_pending == TRUE) && (num_hci_cmd_pkts > 0))
            {
                /* Got HCI Cmd Credits from Controller.
                 * Prepare to send prior pending Cmd packets in the
                 * following HC_EVENT_TX session.
                 */
                events |= HC_EVENT_TX;
            }
        }
#endif

        if (events & HC_EVENT_PRELOAD)
        {
            userial_open(USERIAL_PORT_1);
            vendor_send_command(BT_VND_OP_FW_CFG, NULL);
        }

        if (events & HC_EVENT_POSTLOAD)
        {
            /* Start from SCO related H/W configuration, if SCO configuration
             * is required. Then, follow with reading requests of getting
             * ACL data length for both BR/EDR and LE.
             */
            int result = vendor_send_command(BT_VND_OP_SCO_CFG, NULL);
            if (result == -1)
                p_hci_if->get_acl_max_len();
        }

        if (events & HC_EVENT_TX)
        {
            /*
             *  We will go through every packets in the tx queue.
             *  Fine to clear tx_cmd_pkts_pending.
             */
            tx_cmd_pkts_pending = FALSE;
            HC_BT_HDR * sending_msg_que[64];
            int sending_msg_count = 0;
            int sending_hci_cmd_pkts_count = 0;
            utils_lock();
            p_next_msg = tx_q.p_first;
            while (p_next_msg && sending_msg_count <
		   (int)(sizeof(sending_msg_que)/sizeof(sending_msg_que[0])))
            {
                if ((p_next_msg->event & MSG_EVT_MASK)==MSG_STACK_TO_HC_HCI_CMD)
                {
                    /*
                     *  if we have used up controller's outstanding HCI command
                     *  credits (normally is 1), skip all HCI command packets in
                     *  the queue.
                     *  The pending command packets will be sent once controller
                     *  gives back us credits through CommandCompleteEvent or
                     *  CommandStatusEvent.
                     */
                    if ((tx_cmd_pkts_pending == TRUE) ||
                        (sending_hci_cmd_pkts_count >= num_hci_cmd_pkts))
                    {
                        tx_cmd_pkts_pending = TRUE;
                        p_next_msg = utils_getnext(p_next_msg);
                        continue;
                    }
                    sending_hci_cmd_pkts_count++;
                }

                p_msg = p_next_msg;
                p_next_msg = utils_getnext(p_msg);
                utils_remove_from_queue_unlocked(&tx_q, p_msg);
                sending_msg_que[sending_msg_count++] = p_msg;
            }
            utils_unlock();
            int i;
            for(i = 0; i < sending_msg_count; i++)
                p_hci_if->send(sending_msg_que[i]);
            if (tx_cmd_pkts_pending == TRUE)
                BTHCDBG("Used up Tx Cmd credits");

        }

        if (events & HC_EVENT_LPM_ENABLE)
        {
            lpm_enable(TRUE);
        }

        if (events & HC_EVENT_LPM_DISABLE)
        {
            lpm_enable(FALSE);
        }

        if (events & HC_EVENT_LPM_IDLE_TIMEOUT)
        {
            lpm_wake_deassert();
        }

        if (events & HC_EVENT_LPM_ALLOW_SLEEP)
        {
            lpm_allow_bt_device_sleep();
        }

        if (events & HC_EVENT_LPM_WAKE_DEVICE)
        {
            lpm_wake_assert();
        }

        if (events & HC_EVENT_TX_CMD)
        {
            HC_BT_HDR *p_cmd_msg;
            while ((p_cmd_msg = utils_dequeue(&hc_cb.cmd_q)) != NULL)
            {
                if ((0 >= tx_hc_msg(p_cmd_msg)) && bt_hc_cbacks)
                    bt_hc_cbacks->dealloc(p_cmd_msg);
            }
        }

        if (events & HC_EVENT_EPILOG)
        {
            vendor_send_command(BT_VND_OP_EPILOG, NULL);
        }

        if (events & HC_EVENT_EXIT)
            break;
    }

    ALOGI("bt_hc_worker_thread exiting");
    lib_running = 0;

    pthread_exit(NULL);

    return NULL;    // compiler friendly
}


/*******************************************************************************
**
** Function        bt_hc_get_interface
@@ -627,4 +484,3 @@ const bt_hc_interface_t *bt_hc_get_interface(void)
{
    return &bluetoothHCLibInterface;
}
+1 −5
Original line number Diff line number Diff line
@@ -152,8 +152,6 @@ typedef struct
**  Externs
******************************************************************************/

extern BUFFER_Q tx_q;

uint8_t hci_h4_send_int_cmd(uint16_t opcode, HC_BT_HDR *p_buf, \
                                  tINT_CMD_CBACK p_cback);
void lpm_wake_assert(void);
@@ -994,9 +992,7 @@ uint8_t hci_h4_send_int_cmd(uint16_t opcode, HC_BT_HDR *p_buf, \
    /* stamp signature to indicate an internal command */
    p_buf->layer_specific = opcode;

    utils_enqueue(&tx_q, (void *) p_buf);
    bthc_signal_event(HC_EVENT_TX);

    bthc_tx(p_buf);
    return TRUE;
}

+3 −7
Original line number Diff line number Diff line
@@ -136,8 +136,6 @@ typedef struct
**  Externs
******************************************************************************/

extern BUFFER_Q tx_q;

uint8_t hci_mct_send_int_cmd(uint16_t opcode, HC_BT_HDR *p_buf, \
                                  tINT_CMD_CBACK p_cback);
void lpm_wake_assert(void);
@@ -253,7 +251,7 @@ uint8_t internal_event_intercept(void)

        // Signal TX event so the worker thread can check if it has anything
        // to send
        bthc_signal_event(HC_EVENT_TX);
        bthc_tx(NULL);

        if (p_cb->int_cmd_rsp_pending > 0)
        {
@@ -292,7 +290,7 @@ uint8_t internal_event_intercept(void)

        // Signal TX event so the worker thread can check if it has anything
        // to send
        bthc_signal_event(HC_EVENT_TX);
        bthc_tx(NULL);
    }

    return FALSE;
@@ -1097,9 +1095,7 @@ uint8_t hci_mct_send_int_cmd(uint16_t opcode, HC_BT_HDR *p_buf, \
    /* stamp signature to indicate an internal command */
    p_buf->layer_specific = opcode;

    utils_enqueue(&tx_q, (void *) p_buf);
    bthc_signal_event(HC_EVENT_TX);

    bthc_tx(p_buf);
    return TRUE;
}

Loading