OSDN Git Service

New call-in/-back functions for Controller to do vendor-specific shutdown (1/2)
authorYK Jeffrey Chao <jechao@broadcom.com>
Tue, 7 May 2013 23:28:52 +0000 (16:28 -0700)
committerMatthew Xie <mattx@google.com>
Thu, 9 May 2013 19:21:17 +0000 (12:21 -0700)
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

hci/include/bt_hci_bdroid.h
hci/include/bt_vendor_lib.h
hci/src/bt_hci_bdroid.c
hci/src/bt_hw.c

index 5681e85..7b23851 100644 (file)
@@ -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 */
index 054e317..f774a14 100644 (file)
@@ -80,10 +80,10 @@ typedef enum {
  *      Typecasting conversion: (int (*)[]) param.
  *  [return]
  *      Numbers of opened file descriptors.
    *      Valid number:
    *          1 - CMD/EVT/ACL-In/ACL-Out via the same fd (e.g. UART)
    *          2 - CMD/EVT on one fd, and ACL-In/ACL-Out on the other fd
    *          4 - CMD, EVT, ACL-In, ACL-Out are on their individual fd
+ *      Valid number:
+ *          1 - CMD/EVT/ACL-In/ACL-Out via the same fd (e.g. UART)
+ *          2 - CMD/EVT on one fd, and ACL-In/ACL-Out on the other fd
+ *          4 - CMD, EVT, ACL-In, ACL-Out are on their individual fd
  *  [callback]
  *      None.
  */
@@ -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;
 
 /*
index 8a04d47..90249aa 100644 (file)
 #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);
 
index b2a099f..fae296b 100644 (file)
@@ -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
 };
 
 /******************************************************************************