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

Commit cb9a5e04 authored by YK Jeffrey Chao's avatar YK Jeffrey Chao Committed by Matthew Xie
Browse files

New call-in/-back functions for Controller to do vendor-specific shutdown (1/2)

A pair of asynchronous call-in and call-back API are added into the Host
Controller Vendor Lib interface (bt_vendor_lib.h). The caller calls this new
call-in function to inform the vendor module to perform vendor-specific
shutdown process (e.g. send HCI_RESET to BT Controller) before the caller calls
for interface cleanup() function. The vendor module is responsible for calling
call-back function to notify the caller completion of vendor-specific shutdown
process.
bug 7390787

Change-Id: I29e3c94ff78e17cdd7a06b44ae537e3b0ad1516d
parent bf1ccdfc
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -86,6 +86,7 @@
#define HC_EVENT_LPM_ALLOW_SLEEP       0x0080
#define HC_EVENT_LPM_IDLE_TIMEOUT      0x0100
#define HC_EVENT_EXIT                  0x0200
#define HC_EVENT_EPILOG                0x0400

/* Message event mask across Host/Controller lib and stack */
#define MSG_EVT_MASK                    0xFF00 /* eq. BT_EVT_MASK */
+21 −4
Original line number Diff line number Diff line
@@ -141,6 +141,20 @@ typedef enum {
 *      None.
 */
    BT_VND_OP_LPM_WAKE_SET_STATE,

/*  [operation]
 *      The epilog call to the vendor module so that it can perform any
 *      vendor-specific processes (e.g. send a HCI_RESET to BT Controller)
 *      before the caller calls for cleanup().
 *  [input param]
 *      None.
 *  [return]
 *      0 - default, don't care.
 *  [callback]
 *      Must call epilog_cb to notify the stack of the completion of vendor
 *      specific epilog process once it has been done.
 */
    BT_VND_OP_EPILOG,
} bt_vendor_opcode_t;

/** Power on/off control states */
@@ -280,6 +294,9 @@ typedef struct {

    /* hci command packet transmit request */
    cmd_xmit_cb xmit_cb;

    /* notifies caller completion of epilog process */
    cfg_result_cb epilog_cb;
} bt_vendor_callbacks_t;

/*
+87 −2
Original line number Diff line number Diff line
@@ -47,6 +47,11 @@
#define BTHCDBG(param, ...) {}
#endif

/* Vendor epilog process timeout period  */
#ifndef EPILOG_TIMEOUT_MS
#define EPILOG_TIMEOUT_MS 3000  // 3 seconds
#endif

/******************************************************************************
**  Externs
******************************************************************************/
@@ -81,6 +86,8 @@ typedef struct
    pthread_t       worker_thread;
    pthread_mutex_t mutex;
    pthread_cond_t  cond;
    uint8_t         epilog_timer_created;
    timer_t         epilog_timer_id;
} bt_hc_cb_t;

/******************************************************************************
@@ -106,6 +113,63 @@ void bthc_signal_event(uint16_t event)
    pthread_mutex_unlock(&hc_cb.mutex);
}

/*******************************************************************************
**
** Function        epilog_wait_timeout
**
** Description     Timeout thread of epilog watchdog timer
**
** Returns         None
**
*******************************************************************************/
static void epilog_wait_timeout(union sigval arg)
{
    ALOGI("...epilog_wait_timeout...");
    bthc_signal_event(HC_EVENT_EXIT);
}

/*******************************************************************************
**
** Function        epilog_wait_timer
**
** Description     Launch epilog watchdog timer
**
** Returns         None
**
*******************************************************************************/
static void epilog_wait_timer(void)
{
    int status;
    struct itimerspec ts;
    struct sigevent se;
    uint32_t timeout_ms = EPILOG_TIMEOUT_MS;

    se.sigev_notify = SIGEV_THREAD;
    se.sigev_value.sival_ptr = &hc_cb.epilog_timer_id;
    se.sigev_notify_function = epilog_wait_timeout;
    se.sigev_notify_attributes = NULL;

    status = timer_create(CLOCK_MONOTONIC, &se, &hc_cb.epilog_timer_id);

    if (status == 0)
    {
        hc_cb.epilog_timer_created = 1;
        ts.it_value.tv_sec = timeout_ms/1000;
        ts.it_value.tv_nsec = 1000000*(timeout_ms%1000);
        ts.it_interval.tv_sec = 0;
        ts.it_interval.tv_nsec = 0;

        status = timer_settime(hc_cb.epilog_timer_id, 0, &ts, 0);
        if (status == -1)
            ALOGE("Failed to fire epilog watchdog timer");
    }
    else
    {
        ALOGE("Failed to create epilog watchdog timer");
        hc_cb.epilog_timer_created = 0;
    }
}

/*****************************************************************************
**
**   BLUETOOTH HOST/CONTROLLER INTERFACE LIBRARY FUNCTIONS
@@ -126,6 +190,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;

    /* store reference to user callbacks */
    bt_hc_cbacks = (bt_hc_callbacks_t *) p_cb;

@@ -295,11 +361,20 @@ static void cleanup( void )

    if (lib_running)
    {
        lib_running = 0;
        bthc_signal_event(HC_EVENT_EXIT);
        epilog_wait_timer();

        bthc_signal_event(HC_EVENT_EPILOG);
        pthread_join(hc_cb.worker_thread, NULL);

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

    lib_running = 0;

    lpm_cleanup();
    userial_close();
    p_hci_if->cleanup();
@@ -480,11 +555,21 @@ static void *bt_hc_worker_thread(void *arg)
            lpm_wake_assert();
        }

        if (events & HC_EVENT_EPILOG)
        {
            /* Calling vendor-specific part */
            if (bt_vnd_if)
                bt_vnd_if->op(BT_VND_OP_EPILOG, NULL);
            else
                break;  // equivalent to HC_EVENT_EXIT
        }

        if (events & HC_EVENT_EXIT)
            break;
    }

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

    pthread_exit(NULL);

+18 −1
Original line number Diff line number Diff line
@@ -162,6 +162,22 @@ static uint8_t xmit_cb(uint16_t opcode, void *p_buf, tINT_CMD_CBACK p_cback)
    return p_hci_if->send_int_cmd(opcode, (HC_BT_HDR *)p_buf, p_cback);
}

/******************************************************************************
**
** Function         epilog_cb
**
** Description      HOST/CONTROLLER VENDOR LIB CALLBACK API - This function is
**                  called back from the libbt-vendor to indicate the result of
**                  previous epilog call.
**
** Returns          None
**
******************************************************************************/
static void epilog_cb(bt_vendor_op_result_t result)
{
    bthc_signal_event(HC_EVENT_EXIT);
}

/*****************************************************************************
**   The libbt-vendor Callback Functions Table
*****************************************************************************/
@@ -172,7 +188,8 @@ static const bt_vendor_callbacks_t vnd_callbacks = {
    lpm_vnd_cb,
    alloc,
    dealloc,
    xmit_cb
    xmit_cb,
    epilog_cb
};

/******************************************************************************