* 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.
*/
* 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 */
/* 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;
/*
#define BTHCDBG(param, ...) {}
#endif
+/* Vendor epilog process timeout period */
+#ifndef EPILOG_TIMEOUT_MS
+#define EPILOG_TIMEOUT_MS 3000 // 3 seconds
+#endif
+
/******************************************************************************
** Externs
******************************************************************************/
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;
/******************************************************************************
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
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;
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();
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);
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
*****************************************************************************/
lpm_vnd_cb,
alloc,
dealloc,
- xmit_cb
+ xmit_cb,
+ epilog_cb
};
/******************************************************************************