// Closes the interface. // This routine is not thread safe. static void cleanup(void) { if (has_cleaned_up) { ALOGW("%s Already cleaned up for this session\n", __func__); return; } BTHCDBG("cleanup"); if (hc_cb.worker_thread) { if (fwcfg_acked) { epilog_wait_timer(); // Stop reading thread userial_close_reader(); thread_post(hc_cb.worker_thread, event_epilog, NULL); } thread_free(hc_cb.worker_thread); pthread_mutex_lock(&hc_cb.worker_thread_lock); hc_cb.worker_thread = NULL; pthread_mutex_unlock(&hc_cb.worker_thread_lock); if (hc_cb.epilog_timer_created) { timer_delete(hc_cb.epilog_timer_id); hc_cb.epilog_timer_created = false; } } BTHCDBG("%s Finalizing cleanup\n", __func__); lpm_cleanup(); userial_close(); p_hci_if->cleanup(); utils_cleanup(); set_power(BT_VND_PWR_OFF); vendor_close(); pthread_mutex_destroy(&hc_cb.worker_thread_lock); fwcfg_acked = false; bt_hc_cbacks = NULL; has_cleaned_up = true; }
/** Closes the interface */ static void cleanup( void ) { BTHCDBG("cleanup"); if (lib_running) { if (fwcfg_acked == TRUE) { epilog_wait_timer(); bthc_signal_event(HC_EVENT_EPILOG); } else { bthc_signal_event(HC_EVENT_EXIT); } 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(); p_userial_if->close(); p_hci_if->cleanup(); utils_cleanup(); /* Calling vendor-specific part */ if (bt_vnd_if) bt_vnd_if->cleanup(); fwcfg_acked = FALSE; bt_hc_cbacks = NULL; }