/** Closes the interface */ static void cleanup( void ) { BTHCDBG("cleanup"); if (lib_running) { lib_running = 0; bthc_signal_event(HC_EVENT_EXIT); pthread_join(hc_cb.worker_thread, NULL); } userial_close(); p_hci_if->cleanup(); utils_cleanup(); /* Calling vendor-specific part */ if (bt_vnd_if) bt_vnd_if->cleanup(); pthread_cond_destroy(&hc_cb.cond); pthread_mutex_destroy(&hc_cb.mutex); bt_hc_cbacks = NULL; }
// 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(); userial_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; }
/******************************************************************************* ** ** Function userial_open ** ** Description Open Bluetooth device with the port ID ** ** Returns TRUE/FALSE ** *******************************************************************************/ uint8_t userial_open(uint8_t port) { struct sched_param param; int policy, result; pthread_attr_t thread_attr; USERIALDBG("userial_open(port:%d)", port); if (userial_running) { /* Userial is open; close it first */ userial_close(); utils_delay(50); } if (port >= MAX_SERIAL_PORT) { ALOGE("Port > MAX_SERIAL_PORT"); return FALSE; } /* Calling vendor-specific part */ if (bt_vnd_if) { result = bt_vnd_if->op(BT_VND_OP_USERIAL_OPEN, &userial_cb.fd); if ((result != 2) && (result != 4)) { ALOGE("userial_open: wrong numbers of open fd in vendor lib [%d]!", result); ALOGE("userial_open: HCI MCT expects 2 or 4 open file descriptors"); bt_vnd_if->op(BT_VND_OP_USERIAL_CLOSE, NULL); return FALSE; } } else { ALOGE("userial_open: missing vendor lib interface !!!"); ALOGE("userial_open: unable to open BT transport"); return FALSE; } ALOGI("CMD=%d, EVT=%d, ACL_Out=%d, ACL_In=%d", \ userial_cb.fd[CH_CMD], userial_cb.fd[CH_EVT], \ userial_cb.fd[CH_ACL_OUT], userial_cb.fd[CH_ACL_IN]); if ((userial_cb.fd[CH_CMD] == -1) || (userial_cb.fd[CH_EVT] == -1) || (userial_cb.fd[CH_ACL_OUT] == -1) || (userial_cb.fd[CH_ACL_IN] == -1)) { ALOGE("userial_open: failed to open BT transport"); bt_vnd_if->op(BT_VND_OP_USERIAL_CLOSE, NULL); return FALSE; } userial_cb.port = port; /* Start listening thread */ pthread_attr_init(&thread_attr); if (pthread_create(&(userial_cb.read_thread), &thread_attr, \ userial_read_thread, NULL) != 0 ) { ALOGE("pthread_create failed!"); bt_vnd_if->op(BT_VND_OP_USERIAL_CLOSE, NULL); return FALSE; } if(pthread_getschedparam(userial_cb.read_thread, &policy, ¶m)==0) { policy = BTHC_LINUX_BASE_POLICY; #if (BTHC_LINUX_BASE_POLICY != SCHED_NORMAL) param.sched_priority = BTHC_USERIAL_READ_THREAD_PRIORITY; #else param.sched_priority = 0; #endif result = pthread_setschedparam(userial_cb.read_thread, policy, ¶m); if (result != 0) { ALOGW("userial_open: pthread_setschedparam failed (%s)", \ strerror(result)); } } return TRUE; }
/******************************************************************************* ** ** Function userial_open ** ** Description Open Bluetooth device with the port ID ** ** Returns TRUE/FALSE ** *******************************************************************************/ uint8_t userial_open(uint8_t port) { struct sched_param param; int policy, result; pthread_attr_t thread_attr; int fd_array[CH_MAX]; USERIALDBG("userial_open(port:%d)", port); if (userial_running) { /* Userial is open; close it first */ userial_close(); utils_delay(50); } if (port >= MAX_SERIAL_PORT) { ALOGE("Port > MAX_SERIAL_PORT"); return FALSE; } /* Calling vendor-specific part */ if (bt_vnd_if) { result = bt_vnd_if->op(BT_VND_OP_USERIAL_OPEN, &fd_array); if (result != 1) { ALOGE("userial_open: wrong numbers of open fd in vendor lib [%d]!", result); ALOGE("userial_open: HCI UART expects only one open fd"); bt_vnd_if->op(BT_VND_OP_USERIAL_CLOSE, NULL); return FALSE; } userial_cb.fd = fd_array[0]; } else { ALOGE("userial_open: missing vendor lib interface !!!"); ALOGE("userial_open: unable to open UART port"); return FALSE; } if (userial_cb.fd == -1) { ALOGE("userial_open: failed to open UART port"); return FALSE; } USERIALDBG( "fd = %d", userial_cb.fd); userial_cb.port = port; pthread_attr_init(&thread_attr); if (pthread_create(&(userial_cb.read_thread), &thread_attr, \ userial_read_thread, NULL) != 0 ) { ALOGE("pthread_create failed!"); return FALSE; } if(pthread_getschedparam(userial_cb.read_thread, &policy, ¶m)==0) { policy = BTHC_LINUX_BASE_POLICY; #if (BTHC_LINUX_BASE_POLICY!=SCHED_NORMAL) param.sched_priority = BTHC_USERIAL_READ_THREAD_PRIORITY; #endif result = pthread_setschedparam(userial_cb.read_thread, policy, ¶m); if (result != 0) { ALOGW("userial_open: pthread_setschedparam failed (%s)", \ strerror(result)); } } return TRUE; }