From: Zach Johnson Date: Tue, 9 Sep 2014 01:31:39 +0000 (-0700) Subject: Refactor bte_main into more of a shell. X-Git-Tag: android-x86-7.1-r1~1277^2~235 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=733a06ed9c38fc7f3b00cece9c88ac72b6cc3d98;p=android-x86%2Fsystem-bt.git Refactor bte_main into more of a shell. Moves all HCI initialization into hci_layer. Removes superfluous exposed functionality on the HCI layer (like turning the chip on/off and logging) Also reorganizes some of hci_layer to group related functions together. --- diff --git a/hci/Android.mk b/hci/Android.mk index 3c233e2f0..190abcc7a 100644 --- a/hci/Android.mk +++ b/hci/Android.mk @@ -72,6 +72,6 @@ LOCAL_CFLAGS := -Wall -Werror $(bdroid_CFLAGS) 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) diff --git a/hci/include/btsnoop.h b/hci/include/btsnoop.h index 8c21cd1ab..05ff791a3 100644 --- a/hci/include/btsnoop.h +++ b/hci/include/btsnoop.h @@ -23,11 +23,12 @@ #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 diff --git a/hci/include/hci_layer.h b/hci/include/hci_layer.h index 9ba6238b5..ba674ba6c 100644 --- a/hci/include/hci_layer.h +++ b/hci/include/hci_layer.h @@ -66,14 +66,14 @@ typedef enum { 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; @@ -81,7 +81,9 @@ typedef struct { 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 ); @@ -89,23 +91,12 @@ typedef struct hci_t { // 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; diff --git a/hci/src/btsnoop.c b/hci/src/btsnoop.c index 3bd5ef489..c16e26c11 100644 --- a/hci/src/btsnoop.c +++ b/hci/src/btsnoop.c @@ -49,6 +49,8 @@ static const uint64_t BTSNOOP_EPOCH_DELTA = 0x00dcddb30f2f8000ULL; // 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(); @@ -147,6 +149,24 @@ static void btsnoop_close(void) { 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; @@ -172,8 +192,8 @@ static void btsnoop_capture(const BT_HDR *buffer, bool is_received) { } static const btsnoop_t interface = { - btsnoop_open, - btsnoop_close, + btsnoop_set_logging_path, + btsnoop_set_is_running, btsnoop_capture }; diff --git a/hci/src/hci_layer.c b/hci/src/hci_layer.c index 171d18b8c..60450b5b5 100644 --- a/hci/src/hci_layer.c +++ b/hci/src/hci_layer.c @@ -19,6 +19,7 @@ #define LOG_TAG "hci_layer" #include +#include #include #include "buffer_allocator.h" @@ -87,6 +88,10 @@ typedef struct { 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; @@ -112,6 +117,7 @@ static thread_t *thread; // We own this 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; @@ -124,7 +130,7 @@ static list_t *commands_pending_response; 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); @@ -136,11 +142,12 @@ static void epilog_finished_callback(bool success); 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); @@ -155,7 +162,23 @@ static bool start_up(bdaddr_t local_bdaddr, const hci_callbacks_t *upper_callbac 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; @@ -212,6 +235,25 @@ static bool start_up(bdaddr_t local_bdaddr, const hci_callbacks_t *upper_callbac // 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(); @@ -249,11 +291,17 @@ static void 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); @@ -262,37 +310,11 @@ static void shut_down() { 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, @@ -431,34 +453,25 @@ intercepted:; 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__); @@ -469,10 +482,30 @@ static void event_postload(UNUSED_ATTR void *context) { } } +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); @@ -627,15 +660,11 @@ static void fragmenter_transmit_finished(void *buffer, bool all_fragments_sent) 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. diff --git a/hci/test/hci_layer_test.cpp b/hci/test/hci_layer_test.cpp index cd2c3bae7..d040138d2 100644 --- a/hci/test/hci_layer_test.cpp +++ b/hci/test/hci_layer_test.cpp @@ -41,18 +41,14 @@ extern "C" { } 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"; @@ -74,6 +70,18 @@ static int packet_index; 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); @@ -154,7 +162,7 @@ static void expect_packet(uint16_t event, int max_acl_data_size, const uint8_t * } 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; @@ -165,7 +173,7 @@ STUB_FUNCTION(bool, hal_init, (const hci_hal_callbacks_t *callbacks, thread_t *w } 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; } @@ -246,23 +254,9 @@ STUB_FUNCTION(void, hal_packet_finished, (serial_data_type_t type)) 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; } @@ -316,7 +310,7 @@ STUB_FUNCTION(void, btsnoop_capture, (const BT_HDR *buffer, bool is_received)) } 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; } @@ -350,7 +344,7 @@ STUB_FUNCTION(void, low_power_transmit_done, ()) } 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; @@ -366,7 +360,7 @@ STUB_FUNCTION(void, vendor_close, ()) } 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; @@ -388,32 +382,33 @@ STUB_FUNCTION(void, vendor_set_callback, (vendor_async_opcode_t opcode, UNUSED_A } 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; } @@ -423,10 +418,26 @@ STUB_FUNCTION(int, vendor_send_async_command, (UNUSED_ATTR vendor_async_opcode_t 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); @@ -456,7 +467,7 @@ STUB_FUNCTION(void, command_status_callback, (UNUSED_ATTR uint8_t status, BT_HDR } 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; } @@ -493,8 +504,6 @@ static void reset_for(TEST_MODES_T next) { 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); @@ -502,6 +511,7 @@ static void reset_for(TEST_MODES_T next) { 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); @@ -545,8 +555,6 @@ class HciLayerTest : public AlarmTestHarness { 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; @@ -554,6 +562,7 @@ class HciLayerTest : public AlarmTestHarness { 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; @@ -562,14 +571,18 @@ class HciLayerTest : public AlarmTestHarness { 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() { @@ -594,32 +607,6 @@ class HciLayerTest : public AlarmTestHarness { 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(); @@ -753,15 +740,3 @@ TEST_F(HciLayerTest, test_transmit_command_command_complete) { } // 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); -} diff --git a/main/bte_main.c b/main/bte_main.c index b7ef9d3e2..424eedd2f 100755 --- a/main/bte_main.c +++ b/main/bte_main.c @@ -40,6 +40,7 @@ #include "bte.h" #include "btif_common.h" #include "btu.h" +#include "btsnoop.h" #include "bt_utils.h" #include "fixed_queue.h" #include "gki.h" @@ -67,21 +68,6 @@ #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 ******************************************************************************/ @@ -118,8 +104,8 @@ static const size_t BTU_L2CAP_ALARM_HASH_MAP_SIZE = 17; ** 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; @@ -131,10 +117,6 @@ static thread_t *dispatch_thread; /******************************************************************************* ** 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); /******************************************************************************* @@ -165,6 +147,8 @@ void bte_main_boot_entry(void) 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"); @@ -177,9 +161,6 @@ void bte_main_boot_entry(void) 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); @@ -191,7 +172,7 @@ void bte_main_boot_entry(void) #endif pthread_mutex_init(&shutdown_lock, NULL); - + btsnoop->set_logging_path(hci_logfile); } /****************************************************************************** @@ -205,11 +186,14 @@ void bte_main_boot_entry(void) ******************************************************************************/ 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(); } @@ -247,7 +231,8 @@ void bte_main_enable() 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)); } /****************************************************************************** @@ -264,8 +249,16 @@ void bte_main_disable(void) { 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); @@ -295,153 +288,8 @@ void bte_main_disable(void) ******************************************************************************/ 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); } /****************************************************************************** @@ -598,7 +446,7 @@ void bte_main_hci_send (BT_HDR *p_msg, UINT16 event) /****************************************************************************** ** -** 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 @@ -606,16 +454,16 @@ void bte_main_hci_send (BT_HDR *p_msg, UINT16 event) ** 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); } } @@ -664,6 +512,6 @@ static void tx_result(void *p_buf, bool all_fragments_sent) ** The libbt-hci Callback Functions Table *****************************************************************************/ static const hci_callbacks_t hci_callbacks = { - preload_cb, + hci_startup_cb, tx_result };