LOCAL_MODULE := libbt-hcitests
LOCAL_MODULE_TAGS := tests
LOCAL_SHARED_LIBRARIES := liblog libdl
-LOCAL_STATIC_LIBRARIES := libbt-hci libosi
+LOCAL_STATIC_LIBRARIES := libbt-hci libosi libcutils
include $(BUILD_NATIVE_TEST)
#include "bt_types.h"
typedef struct btsnoop_t {
- // Open btsnoop, and dump captured packets to the file pointed to by |path|.
- void (*open)(const char *path);
+ // Sets the logging path for btsnoop to the provided |path|.
+ void (*set_logging_path)(const char *path);
- // Close btsnoop, so no more packets are captured.
- void (*close)(void);
+ // Turns btsnoop logging on or off, depending on |value|. If
+ // you are turning btsnoop on, you must have set a logging path.
+ void (*set_is_running)(bool value);
// Capture |packet| and dump it to the btsnoop logs. If |is_received| is
// true, the packet is marked as incoming. Otherwise, the packet is marked
LPM_WAKE_DEASSERT
} low_power_command_t;
-typedef void (*preload_finished_cb)(bool success);
+typedef void (*startup_finished_cb)(bool success);
typedef void (*transmit_finished_cb)(void *buffer, bool all_fragments_sent);
typedef void (*command_complete_cb)(BT_HDR *response, void *context);
typedef void (*command_status_cb)(uint8_t status, BT_HDR *command, void *context);
typedef struct {
// Called when the HCI layer finishes the preload sequence.
- preload_finished_cb preload_finished;
+ startup_finished_cb startup_finished;
// Called when the HCI layer finishes sending a packet.
transmit_finished_cb transmit_finished;
typedef struct hci_t {
// Start up the HCI layer, with the specified |local_bdaddr|.
- bool (*start_up)(
+ // |upper_callbacks->startup_finished| will be called when the full
+ // start up sequence is complete.
+ bool (*start_up_async)(
bdaddr_t local_bdaddr,
const hci_callbacks_t *upper_callbacks
);
// Tear down and relese all resources
void (*shut_down)(void);
- // Turn the Bluetooth chip on or off, depending on |value|.
- void (*set_chip_power_on)(bool value);
-
// Send a low power command, if supported and the low power manager is enabled.
void (*send_low_power_command)(low_power_command_t command);
- // Do the preload sequence (call before the rest of the BT stack initializes).
- void (*do_preload)(void);
-
// Do the postload sequence (call after the rest of the BT stack initializes).
void (*do_postload)(void);
- // Turn logging on, and log to the specified |path|.
- void (*turn_on_logging)(const char *path);
-
- void (*turn_off_logging)(void);
-
// Register with this data dispatcher to receive data flowing upward out of the HCI layer
data_dispatcher_t *upward_dispatcher;
// File descriptor for btsnoop file.
static int hci_btsnoop_fd = -1;
+static bool is_logging = false;
+static const char *logging_path;
void btsnoop_net_open();
void btsnoop_net_close();
btsnoop_net_close();
}
+static void btsnoop_set_logging_path(const char *path) {
+ assert(!is_logging);
+ logging_path = path;
+}
+
+static void btsnoop_set_is_running(bool should_log) {
+ if (should_log == is_logging)
+ return;
+
+ is_logging = should_log;
+ if (should_log) {
+ assert(logging_path != NULL);
+ btsnoop_open(logging_path);
+ } else {
+ btsnoop_close();
+ }
+}
+
static void btsnoop_capture(const BT_HDR *buffer, bool is_received) {
const uint8_t *p = buffer->data + buffer->offset;
}
static const btsnoop_t interface = {
- btsnoop_open,
- btsnoop_close,
+ btsnoop_set_logging_path,
+ btsnoop_set_is_running,
btsnoop_capture
};
#define LOG_TAG "hci_layer"
#include <assert.h>
+#include <cutils/properties.h>
#include <utils/Log.h>
#include "buffer_allocator.h"
BT_HDR *command;
} waiting_command_t;
+// Using a define here, because it can be stringified for the property lookup
+#define DEFAULT_STARTUP_TIMEOUT_MS 3000
+#define STRING_VALUE_OF(x) #x
+
static const uint32_t EPILOG_TIMEOUT_MS = 3000;
static const uint32_t COMMAND_PENDING_TIMEOUT = 8000;
static volatile bool firmware_is_configured = false;
static volatile bool has_shut_down = false;
static non_repeating_timer_t *epilog_timer;
+static non_repeating_timer_t *startup_timer;
// Outbound-related
static int command_credits = 1;
static pthread_mutex_t commands_pending_response_lock;
static packet_receive_data_t incoming_packets[INBOUND_PACKET_TYPE_COUNT];
-static void event_preload(void *context);
+static void event_finish_startup(void *context);
static void event_postload(void *context);
static void event_epilog(void *context);
static void event_command_ready(fixed_queue_t *queue, void *context);
static void command_timed_out(void *context);
static void hal_says_data_ready(serial_data_type_t type);
-static void epilog_wait_timer_expired(void *context);
+static void startup_timer_expired(void *context);
+static void epilog_timer_expired(void *context);
// Interface functions
-static bool start_up(bdaddr_t local_bdaddr, const hci_callbacks_t *upper_callbacks) {
+static bool start_up_async(bdaddr_t local_bdaddr, const hci_callbacks_t *upper_callbacks) {
assert(local_bdaddr != NULL);
assert(upper_callbacks != NULL);
pthread_mutex_init(&commands_pending_response_lock, NULL);
- epilog_timer = non_repeating_timer_new(EPILOG_TIMEOUT_MS, epilog_wait_timer_expired, NULL);
+ // Grab the override startup timeout ms, if present.
+ period_ms_t startup_timeout_ms;
+ char timeout_prop[PROPERTY_VALUE_MAX];
+ if (!property_get("bluetooth.enable_timeout_ms", timeout_prop, STRING_VALUE_OF(DEFAULT_STARTUP_TIMEOUT_MS))
+ || (startup_timeout_ms = atoi(timeout_prop)) < 100)
+ startup_timeout_ms = DEFAULT_STARTUP_TIMEOUT_MS;
+
+ startup_timer = non_repeating_timer_new(startup_timeout_ms, startup_timer_expired, NULL);
+ if (!startup_timer) {
+ ALOGE("%s unable to create startup timer.", __func__);
+ goto error;
+ }
+
+ // Make sure we run in a bounded amount of time
+ non_repeating_timer_restart(startup_timer);
+
+ epilog_timer = non_repeating_timer_new(EPILOG_TIMEOUT_MS, epilog_timer_expired, NULL);
if (!epilog_timer) {
ALOGE("%s unable to create epilog timer.", __func__);
goto error;
// TODO(sharvil): gracefully propagate failures from this layer.
}
+ int power_state = BT_VND_PWR_OFF;
+#if (defined (BT_CLEAN_TURN_ON_DISABLED) && BT_CLEAN_TURN_ON_DISABLED == TRUE)
+ ALOGW("%s not turning off the chip before turning on.", __func__);
+ // So apparently this hack was needed in the past because a Wingray kernel driver
+ // didn't handle power off commands in a powered off state correctly.
+
+ // The comment in the old code said the workaround should be removed when the
+ // problem was fixed. Sadly, I have no idea if said bug was fixed or if said
+ // kernel is still in use, so we must leave this here for posterity. #sadpanda
+#else
+ // cycle power on the chip to ensure it has been reset
+ vendor->send_command(VENDOR_CHIP_POWER_CONTROL, &power_state);
+#endif
+ power_state = BT_VND_PWR_ON;
+ vendor->send_command(VENDOR_CHIP_POWER_CONTROL, &power_state);
+
+ ALOGD("%s starting async portion", __func__);
+ thread_post(thread, event_finish_startup, NULL);
+
return true;
error:;
interface.shut_down();
non_repeating_timer_free(epilog_timer);
non_repeating_timer_free(command_response_timer);
+ non_repeating_timer_free(startup_timer);
+
+ epilog_timer = NULL;
+ command_response_timer = NULL;
low_power_manager->cleanup();
hal->close();
- interface.set_chip_power_on(false);
+ // Turn off the chip
+ int power_state = BT_VND_PWR_OFF;
+ vendor->send_command(VENDOR_CHIP_POWER_CONTROL, &power_state);
vendor->close();
thread_free(thread);
has_shut_down = true;
}
-static void set_chip_power_on(bool value) {
- ALOGD("%s setting bluetooth chip power on to: %d", __func__, value);
-
- int power_state = value ? BT_VND_PWR_ON : BT_VND_PWR_OFF;
- vendor->send_command(VENDOR_CHIP_POWER_CONTROL, &power_state);
-}
-
-static void do_preload() {
- ALOGD("%s posting preload work item", __func__);
- thread_post(thread, event_preload, NULL);
-}
-
static void do_postload() {
ALOGD("%s posting postload work item", __func__);
thread_post(thread, event_postload, NULL);
}
-static void turn_on_logging(const char *path) {
- ALOGD("%s", __func__);
-
- if (path != NULL)
- btsnoop->open(path);
- else
- ALOGW("%s wanted to start logging, but path was NULL", __func__);
-}
-
-static void turn_off_logging() {
- ALOGD("%s", __func__);
- btsnoop->close();
-}
-
static void transmit_command(
BT_HDR *command,
command_complete_cb complete_callback,
return true;
}
-static void on_controller_acl_size_fetch_finished(void) {
- ALOGI("%s postload finished.", __func__);
-}
+// Start up functions
-static void sco_config_callback(UNUSED_ATTR bool success) {
- controller->begin_acl_size_fetch(on_controller_acl_size_fetch_finished);
+static void event_finish_startup(UNUSED_ATTR void *context) {
+ ALOGI("%s", __func__);
+ hal->open();
+ vendor->send_async_command(VENDOR_CONFIGURE_FIRMWARE, NULL);
}
static void firmware_config_callback(UNUSED_ATTR bool success) {
firmware_is_configured = true;
- callbacks->preload_finished(true);
+ non_repeating_timer_cancel(startup_timer);
+ callbacks->startup_finished(true);
}
-static void epilog_finished_callback(UNUSED_ATTR bool success) {
- ALOGI("%s", __func__);
- thread_stop(thread);
+static void startup_timer_expired(UNUSED_ATTR void *context) {
+ callbacks->startup_finished(false);
}
-static void epilog_wait_timer_expired(UNUSED_ATTR void *context) {
- ALOGI("%s", __func__);
- thread_stop(thread);
-}
-
-static void event_preload(UNUSED_ATTR void *context) {
- ALOGI("%s", __func__);
- hal->open();
- vendor->send_async_command(VENDOR_CONFIGURE_FIRMWARE, NULL);
-}
+// Postload functions
static void event_postload(UNUSED_ATTR void *context) {
ALOGI("%s", __func__);
}
}
+static void on_controller_acl_size_fetch_finished(void) {
+ ALOGI("%s postload finished.", __func__);
+}
+
+static void sco_config_callback(UNUSED_ATTR bool success) {
+ controller->begin_acl_size_fetch(on_controller_acl_size_fetch_finished);
+}
+
+// Epilog functions
+
static void event_epilog(UNUSED_ATTR void *context) {
vendor->send_async_command(VENDOR_DO_EPILOG, NULL);
}
+static void epilog_finished_callback(UNUSED_ATTR bool success) {
+ ALOGI("%s", __func__);
+ thread_stop(thread);
+}
+
+static void epilog_timer_expired(UNUSED_ATTR void *context) {
+ ALOGI("%s", __func__);
+ thread_stop(thread);
+}
+
static void event_command_ready(fixed_queue_t *queue, UNUSED_ATTR void *context) {
if (command_credits > 0) {
waiting_command_t *wait_entry = fixed_queue_dequeue(queue);
static void init_layer_interface() {
if (!interface_created) {
- interface.start_up = start_up;
+ interface.start_up_async = start_up_async;
interface.shut_down = shut_down;
- interface.set_chip_power_on = set_chip_power_on;
interface.send_low_power_command = low_power_manager->post_command;
- interface.do_preload = do_preload;
interface.do_postload = do_postload;
- interface.turn_on_logging = turn_on_logging;
- interface.turn_off_logging = turn_off_logging;
// It's probably ok for this to live forever. It's small and
// there's only one instance of the hci interface.
}
DECLARE_TEST_MODES(
- start_up,
+ start_up_async,
shut_down,
- cycle_power,
- preload,
postload,
transmit_simple,
receive_simple,
transmit_command_no_callbacks,
transmit_command_command_status,
transmit_command_command_complete,
- turn_on_logging,
- turn_off_logging
);
static const char *small_sample_data = "\"It is easy to see,\" replied Don Quixote";
static unsigned int data_size_sum;
static BT_HDR *data_to_receive;
+static void signal_work_item(UNUSED_ATTR void *context) {
+ semaphore_post(done);
+}
+
+static void flush_thread(thread_t *thread) {
+ // Double flush to ensure we get the next reactor cycle
+ thread_post(thread, signal_work_item, NULL);
+ semaphore_wait(done);
+ thread_post(thread, signal_work_item, NULL);
+ semaphore_wait(done);
+}
+
// TODO move this to a common packet testing helper
static BT_HDR *manufacture_packet(uint16_t event, const char *data) {
uint16_t data_length = strlen(data);
}
STUB_FUNCTION(bool, hal_init, (const hci_hal_callbacks_t *callbacks, thread_t *working_thread))
- DURING(start_up) AT_CALL(0) {
+ DURING(start_up_async) AT_CALL(0) {
hal_callbacks = callbacks;
internal_thread = working_thread;
return true;
}
STUB_FUNCTION(bool, hal_open, ())
- DURING(preload) AT_CALL(0) return true;
+ DURING(start_up_async) AT_CALL(0) return true;
UNEXPECTED_CALL;
return false;
}
UNEXPECTED_CALL;
}
-STUB_FUNCTION(void, btsnoop_open, (const char *path))
- DURING(turn_on_logging) AT_CALL(0) {
- EXPECT_EQ(logging_path, path);
- return;
- }
-
- UNEXPECTED_CALL;
-}
-
-STUB_FUNCTION(void, btsnoop_close, ())
- DURING(turn_off_logging) AT_CALL(0) return;
- UNEXPECTED_CALL;
-}
-
STUB_FUNCTION(bool, hci_inject_open, (
UNUSED_ATTR const hci_t *hci_interface))
- DURING(start_up) AT_CALL(0) return true;
+ DURING(start_up_async) AT_CALL(0) return true;
UNEXPECTED_CALL;
return false;
}
}
STUB_FUNCTION(void, low_power_init, (UNUSED_ATTR thread_t *thread))
- DURING(start_up) AT_CALL(0) return;
+ DURING(start_up_async) AT_CALL(0) return;
UNEXPECTED_CALL;
}
}
STUB_FUNCTION(bool, vendor_open, (const uint8_t *addr, const hci_t *hci_interface))
- DURING(start_up) AT_CALL(0) {
+ DURING(start_up_async) AT_CALL(0) {
EXPECT_EQ(test_addr, addr);
EXPECT_EQ(hci, hci_interface);
return true;
}
STUB_FUNCTION(void, vendor_set_callback, (vendor_async_opcode_t opcode, UNUSED_ATTR vendor_cb callback))
- DURING(start_up) {
+ DURING(start_up_async) {
AT_CALL(0) {
EXPECT_EQ(VENDOR_CONFIGURE_FIRMWARE, opcode);
firmware_config_callback = callback;
}
STUB_FUNCTION(int, vendor_send_command, (vendor_opcode_t opcode, void *param))
- DURING(shut_down) AT_CALL(0) {
- EXPECT_EQ(VENDOR_CHIP_POWER_CONTROL, opcode);
- EXPECT_EQ(BT_VND_PWR_OFF, *(int *)param);
- return 0;
- }
-
- DURING(cycle_power) {
+ DURING(start_up_async) {
AT_CALL(0) {
EXPECT_EQ(VENDOR_CHIP_POWER_CONTROL, opcode);
- EXPECT_EQ(BT_VND_PWR_ON, *(int *)param);
+ EXPECT_EQ(BT_VND_PWR_OFF, *(int *)param);
return 0;
}
AT_CALL(1) {
EXPECT_EQ(VENDOR_CHIP_POWER_CONTROL, opcode);
- EXPECT_EQ(BT_VND_PWR_OFF, *(int *)param);
+ EXPECT_EQ(BT_VND_PWR_ON, *(int *)param);
return 0;
}
}
+ DURING(shut_down) AT_CALL(0) {
+ EXPECT_EQ(VENDOR_CHIP_POWER_CONTROL, opcode);
+ EXPECT_EQ(BT_VND_PWR_OFF, *(int *)param);
+ return 0;
+ }
+
UNEXPECTED_CALL;
return 0;
}
STUB_FUNCTION(int, vendor_send_async_command, (UNUSED_ATTR vendor_async_opcode_t opcode, UNUSED_ATTR void *param))
- DURING(preload) AT_CALL(0) {
+ DURING(start_up_async) AT_CALL(0) {
EXPECT_EQ(VENDOR_CONFIGURE_FIRMWARE, opcode);
+ firmware_config_callback(true);
return 0;
}
return 0;
}
+ DURING(shut_down) AT_CALL(0) {
+ EXPECT_EQ(VENDOR_DO_EPILOG, opcode);
+ epilog_callback(true);
+ return 0;
+ }
+
UNEXPECTED_CALL;
return 0;
}
+STUB_FUNCTION(void, callback_startup_finished, (bool success))
+ DURING(start_up_async) AT_CALL(0) {
+ EXPECT_EQ(true, success);
+ semaphore_post(done);
+ return;
+ }
+
+ UNEXPECTED_CALL;
+}
+
STUB_FUNCTION(void, callback_transmit_finished, (UNUSED_ATTR void *buffer, bool all_fragments_sent))
DURING(transmit_simple) AT_CALL(0) {
EXPECT_TRUE(all_fragments_sent);
}
STUB_FUNCTION(void, controller_init, (const hci_t *hci_interface))
- DURING(start_up) AT_CALL(0) {
+ DURING(start_up_async) AT_CALL(0) {
EXPECT_EQ(hci, hci_interface);
return;
}
RESET_CALL_COUNT(hal_read_data);
RESET_CALL_COUNT(hal_packet_finished);
RESET_CALL_COUNT(hal_transmit_data);
- RESET_CALL_COUNT(btsnoop_open);
- RESET_CALL_COUNT(btsnoop_close);
RESET_CALL_COUNT(btsnoop_capture);
RESET_CALL_COUNT(hci_inject_open);
RESET_CALL_COUNT(hci_inject_close);
RESET_CALL_COUNT(low_power_cleanup);
RESET_CALL_COUNT(low_power_wake_assert);
RESET_CALL_COUNT(low_power_transmit_done);
+ RESET_CALL_COUNT(callback_startup_finished);
RESET_CALL_COUNT(callback_transmit_finished);
RESET_CALL_COUNT(command_complete_callback);
RESET_CALL_COUNT(command_status_callback);
hal.read_data = hal_read_data;
hal.packet_finished = hal_packet_finished;
hal.transmit_data = hal_transmit_data;
- btsnoop.open = btsnoop_open;
- btsnoop.close = btsnoop_close;
btsnoop.capture = btsnoop_capture;
hci_inject.open = hci_inject_open;
hci_inject.close = hci_inject_close;
low_power_manager.cleanup = low_power_cleanup;
low_power_manager.wake_assert = low_power_wake_assert;
low_power_manager.transmit_done = low_power_transmit_done;
+ callbacks.startup_finished = callback_startup_finished;
callbacks.transmit_finished = callback_transmit_finished;
controller.init = controller_init;
controller.begin_acl_size_fetch = controller_begin_acl_size_fetch;
done = semaphore_new(0);
- reset_for(start_up);
- hci->start_up(test_addr, &callbacks);
+ reset_for(start_up_async);
+ hci->start_up_async(test_addr, &callbacks);
+ semaphore_wait(done);
EXPECT_CALL_COUNT(vendor_open, 1);
EXPECT_CALL_COUNT(hal_init, 1);
EXPECT_CALL_COUNT(low_power_init, 1);
EXPECT_CALL_COUNT(vendor_set_callback, 3);
EXPECT_CALL_COUNT(controller_init, 1);
+ EXPECT_CALL_COUNT(hal_open, 1);
+ EXPECT_CALL_COUNT(vendor_send_async_command, 1);
+ EXPECT_CALL_COUNT(callback_startup_finished, 1);
}
virtual void TearDown() {
hci_callbacks_t callbacks;
};
-static void signal_work_item(UNUSED_ATTR void *context) {
- semaphore_post(done);
-}
-
-static void flush_thread(thread_t *thread) {
- thread_post(thread, signal_work_item, NULL);
- semaphore_wait(done);
-}
-
-TEST_F(HciLayerTest, test_cycle_power) {
- reset_for(cycle_power);
- hci->set_chip_power_on(true);
- hci->set_chip_power_on(false);
-
- EXPECT_CALL_COUNT(vendor_send_command, 2);
-}
-
-TEST_F(HciLayerTest, test_preload) {
- reset_for(preload);
- hci->do_preload();
-
- flush_thread(internal_thread);
- EXPECT_CALL_COUNT(hal_open, 1);
- EXPECT_CALL_COUNT(vendor_send_async_command, 1);
-}
-
TEST_F(HciLayerTest, test_postload) {
reset_for(postload);
hci->do_postload();
}
// TODO(zachoverflow): test post-reassembly better, stub out fragmenter instead of using it
-
-TEST_F(HciLayerTest, test_turn_on_logging) {
- reset_for(turn_on_logging);
- hci->turn_on_logging(logging_path);
- EXPECT_CALL_COUNT(btsnoop_open, 1);
-}
-
-TEST_F(HciLayerTest, test_turn_off_logging) {
- reset_for(turn_off_logging);
- hci->turn_off_logging();
- EXPECT_CALL_COUNT(btsnoop_close, 1);
-}
#include "bte.h"
#include "btif_common.h"
#include "btu.h"
+#include "btsnoop.h"
#include "bt_utils.h"
#include "fixed_queue.h"
#include "gki.h"
#define HCI_LOGGING_FILENAME "/data/misc/bluedroid/btsnoop_hci.log"
#endif
-/* Stack preload process maximum retry attempts */
-#ifndef PRELOAD_MAX_RETRY_ATTEMPTS
-#define PRELOAD_MAX_RETRY_ATTEMPTS 0
-#endif
-
-/*******************************************************************************
-** Local type definitions
-*******************************************************************************/
-/* Preload retry control block */
-typedef struct
-{
- int retry_counts;
- alarm_t *alarm;
-} bt_preload_retry_cb_t;
-
/******************************************************************************
** Variables
******************************************************************************/
** Static variables
*******************************************************************************/
static const hci_t *hci;
+static const btsnoop_t *btsnoop;
static const hci_callbacks_t hci_callbacks;
-static bt_preload_retry_cb_t preload_retry_cb;
// Lock to serialize shutdown requests from upper layer.
static pthread_mutex_t shutdown_lock;
/*******************************************************************************
** Static functions
*******************************************************************************/
-static void bte_hci_enable(void);
-static void bte_hci_disable(void);
-static void preload_start_wait_timer(void);
-static void preload_stop_wait_timer(void);
static void dump_upbound_data_to_btu(fixed_queue_t *queue, void *context);
/*******************************************************************************
if (!hci)
ALOGE("%s could not get hci layer interface.", __func__);
+ btsnoop = btsnoop_get_interface();
+
upbound_data = fixed_queue_new(SIZE_MAX);
dispatch_thread = thread_new("hci_dispatch");
data_dispatcher_register_default(hci->upward_dispatcher, upbound_data);
- memset(&preload_retry_cb, 0, sizeof(bt_preload_retry_cb_t));
- preload_retry_cb.alarm = alarm_new();
-
bte_load_conf(BTE_STACK_CONF_FILE);
#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
bte_load_ble_conf(BTE_BLE_STACK_CONF_FILE);
#endif
pthread_mutex_init(&shutdown_lock, NULL);
-
+ btsnoop->set_logging_path(hci_logfile);
}
/******************************************************************************
******************************************************************************/
void bte_main_shutdown()
{
- alarm_free(preload_retry_cb.alarm);
- preload_retry_cb.alarm = NULL;
+ thread_free(dispatch_thread);
+ data_dispatcher_register_default(hci_layer_get_interface()->upward_dispatcher, NULL);
+ fixed_queue_free(upbound_data, NULL);
- pthread_mutex_destroy(&shutdown_lock);
+ dispatch_thread = NULL;
+ upbound_data = NULL;
+ pthread_mutex_destroy(&shutdown_lock);
GKI_shutdown();
}
BTU_StartUp();
- bte_hci_enable();
+ btsnoop->set_is_running(hci_logging_enabled || hci_logging_config);
+ assert(hci->start_up_async(btif_local_bd_addr.address, &hci_callbacks));
}
/******************************************************************************
{
APPL_TRACE_DEBUG("%s", __FUNCTION__);
- preload_stop_wait_timer();
- bte_hci_disable();
+ if (hci) {
+ // Shutdown is not thread safe and must be protected.
+ pthread_mutex_lock(&shutdown_lock);
+
+ btsnoop->set_is_running(false);
+ hci->shut_down();
+
+ pthread_mutex_unlock(&shutdown_lock);
+ }
+
BTU_ShutDown();
fixed_queue_free(btu_bta_msg_queue, NULL);
******************************************************************************/
void bte_main_config_hci_logging(BOOLEAN enable, BOOLEAN bt_disabled)
{
- int old = (hci_logging_enabled == TRUE) || (hci_logging_config == TRUE);
- int new;
-
- hci_logging_config = enable;
-
- new = (hci_logging_enabled == TRUE) || (hci_logging_config == TRUE);
-
- if ((old == new) || bt_disabled) {
- return;
- }
-
- if (new)
- hci->turn_on_logging(hci_logfile);
- else
- hci->turn_off_logging();
-}
-
-/******************************************************************************
-**
-** Function bte_hci_enable
-**
-** Description Enable HCI & Vendor modules
-**
-** Returns None
-**
-******************************************************************************/
-static void bte_hci_enable(void)
-{
- APPL_TRACE_DEBUG("%s", __FUNCTION__);
-
- preload_start_wait_timer();
-
- bool success = hci->start_up(btif_local_bd_addr.address, &hci_callbacks);
- APPL_TRACE_EVENT("libbt-hci start_up returns %d", success);
-
- assert(success);
-
- if (hci_logging_enabled == TRUE || hci_logging_config == TRUE)
- hci->turn_on_logging(hci_logfile);
-
-#if (defined (BT_CLEAN_TURN_ON_DISABLED) && BT_CLEAN_TURN_ON_DISABLED == TRUE)
- APPL_TRACE_DEBUG("%s not turning off the chip before turning it on", __FUNCTION__);
-
- /* Do not power off the chip before powering on if BT_CLEAN_TURN_ON_DISABLED flag
- is defined and set to TRUE to avoid below mentioned issue.
-
- Wingray kernel driver maintains a combined counter to keep track of
- BT-Wifi state. Invoking set_power(BT_HC_CHIP_PWR_OFF) when the BT is already
- in OFF state causes this counter to be incorrectly decremented and results in undesired
- behavior of the chip.
-
- This is only a workaround and when the issue is fixed in the kernel this work around
- should be removed. */
-#else
- /* toggle chip power to ensure we will reset chip in case
- a previous stack shutdown wasn't completed gracefully */
- hci->set_chip_power_on(false);
-#endif
- hci->set_chip_power_on(true);
- hci->do_preload();
-}
-
-/******************************************************************************
-**
-** Function bte_hci_disable
-**
-** Description Disable HCI & Vendor modules
-**
-** Returns None
-**
-******************************************************************************/
-static void bte_hci_disable(void)
-{
- APPL_TRACE_DEBUG("%s", __FUNCTION__);
-
- if (!hci)
- return;
-
- // Shutdown is not thread safe and must be protected.
- pthread_mutex_lock(&shutdown_lock);
-
- if (hci_logging_enabled == TRUE || hci_logging_config == TRUE)
- hci->turn_off_logging();
- hci->shut_down();
-
- pthread_mutex_unlock(&shutdown_lock);
-}
-
-/*******************************************************************************
-**
-** Function preload_wait_timeout
-**
-** Description Timeout thread of preload watchdog timer
-**
-** Returns None
-**
-*******************************************************************************/
-static void preload_wait_timeout(UNUSED_ATTR void *context)
-{
- APPL_TRACE_ERROR("...preload_wait_timeout (retried:%d/max-retry:%d)...",
- preload_retry_cb.retry_counts,
- PRELOAD_MAX_RETRY_ATTEMPTS);
-
- if (preload_retry_cb.retry_counts++ < PRELOAD_MAX_RETRY_ATTEMPTS)
- {
- bte_hci_disable();
- GKI_delay(100);
- bte_hci_enable();
- }
- else
- {
- // Inform the bt jni thread initialization has failed.
- btif_transfer_context(btif_init_fail, 0, NULL, 0, NULL);
- }
-}
-
-/*******************************************************************************
-**
-** Function preload_start_wait_timer
-**
-** Description Launch startup watchdog timer
-**
-** Returns None
-**
-*******************************************************************************/
-static void preload_start_wait_timer(void)
-{
- uint32_t timeout_ms;
- char timeout_prop[PROPERTY_VALUE_MAX];
- if (!property_get("bluetooth.enable_timeout_ms", timeout_prop, "3000") || (timeout_ms = atoi(timeout_prop)) < 100)
- timeout_ms = 3000;
-
- alarm_set(preload_retry_cb.alarm, timeout_ms, preload_wait_timeout, NULL);
-}
-
-/*******************************************************************************
-**
-** Function preload_stop_wait_timer
-**
-** Description Stop preload watchdog timer
-**
-** Returns None
-**
-*******************************************************************************/
-static void preload_stop_wait_timer(void)
-{
- alarm_cancel(preload_retry_cb.alarm);
+ hci_logging_config = enable;
+ btsnoop->set_is_running((hci_logging_config || hci_logging_enabled) && !bt_disabled);
}
/******************************************************************************
/******************************************************************************
**
-** Function preload_cb
+** Function hci_startup_cb
**
** Description HOST/CONTROLLER LIB CALLBACK API - This function is called
** when the libbt-hci completed stack preload process
** Returns None
**
******************************************************************************/
-static void preload_cb(bool success)
+static void hci_startup_cb(bool success)
{
APPL_TRACE_EVENT("HC preload_cb %d [1:SUCCESS 0:FAIL]", success);
- if (success)
- {
- preload_stop_wait_timer();
-
+ if (success) {
/* notify BTU task that libbt-hci is ready */
GKI_send_event(BTU_TASK, BT_EVT_PRELOAD_CMPL);
+ } else {
+ /* Notify BTIF_TASK that the init procedure had failed*/
+ GKI_send_event(BTIF_TASK, BT_EVT_HARDWARE_INIT_FAIL);
}
}
** The libbt-hci Callback Functions Table
*****************************************************************************/
static const hci_callbacks_t hci_callbacks = {
- preload_cb,
+ hci_startup_cb,
tx_result
};