summaryrefslogtreecommitdiffstats
path: root/hci
diff options
context:
space:
mode:
authorZach Johnson <zachoverflow@google.com>2014-09-23 18:30:45 -0700
committerAndre Eisenbach <eisenbach@google.com>2015-03-16 16:51:35 -0700
commit093948aaec3d88f3e52cae28b286d694f2645f82 (patch)
tree91c382274688fd0450757123069fffab6e146c6d /hci
parentb1f991590b530715bb6fb4c44695af1e87e167f6 (diff)
downloadandroid_system_bt-093948aaec3d88f3e52cae28b286d694f2645f82.tar.gz
android_system_bt-093948aaec3d88f3e52cae28b286d694f2645f82.tar.bz2
android_system_bt-093948aaec3d88f3e52cae28b286d694f2645f82.zip
Modulizification of the HCI layer
Shutdown is managed by the stack manager now, so we don't need to lock around it. The fetching of the device address is a bit hacky right now, until it becomes part of its own module.
Diffstat (limited to 'hci')
-rw-r--r--hci/Android.mk2
-rw-r--r--hci/include/hci_layer.h22
-rw-r--r--hci/include/packet_fragmenter.h1
-rw-r--r--hci/src/hci_layer.c72
-rw-r--r--hci/test/hci_layer_test.cpp41
-rw-r--r--hci/test/packet_fragmenter_test.cpp2
6 files changed, 56 insertions, 84 deletions
diff --git a/hci/Android.mk b/hci/Android.mk
index 048652c46..b1d04b68f 100644
--- a/hci/Android.mk
+++ b/hci/Android.mk
@@ -74,6 +74,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 libcutils
+LOCAL_STATIC_LIBRARIES := libbt-hci libosi libcutils libbtcore
include $(BUILD_NATIVE_TEST)
diff --git a/hci/include/hci_layer.h b/hci/include/hci_layer.h
index ba674ba6c..957e5003f 100644
--- a/hci/include/hci_layer.h
+++ b/hci/include/hci_layer.h
@@ -66,31 +66,10 @@ typedef enum {
LPM_WAKE_DEASSERT
} low_power_command_t;
-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.
- startup_finished_cb startup_finished;
-
- // Called when the HCI layer finishes sending a packet.
- transmit_finished_cb transmit_finished;
-} hci_callbacks_t;
-
typedef struct hci_t {
- // Start up the HCI layer, with the specified |local_bdaddr|.
- // |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);
-
// Send a low power command, if supported and the low power manager is enabled.
void (*send_low_power_command)(low_power_command_t command);
@@ -112,6 +91,7 @@ typedef struct hci_t {
void (*transmit_downward)(data_dispatcher_type_t type, void *data);
} hci_t;
+#define HCI_MODULE "hci_module"
const hci_t *hci_layer_get_interface();
const hci_t *hci_layer_get_test_interface(
diff --git a/hci/include/packet_fragmenter.h b/hci/include/packet_fragmenter.h
index 93dc97ef9..c7f643e21 100644
--- a/hci/include/packet_fragmenter.h
+++ b/hci/include/packet_fragmenter.h
@@ -22,6 +22,7 @@
#include "bt_types.h"
#include "hci_layer.h"
+typedef void (*transmit_finished_cb)(BT_HDR *packet, bool all_fragments_sent);
typedef void (*packet_reassembled_cb)(BT_HDR *packet);
typedef void (*packet_fragmented_cb)(BT_HDR *packet, bool send_transmit_finished);
diff --git a/hci/src/hci_layer.c b/hci/src/hci_layer.c
index 07c6484a3..6b4c2b7d7 100644
--- a/hci/src/hci_layer.c
+++ b/hci/src/hci_layer.c
@@ -33,12 +33,17 @@
#include "hci_layer.h"
#include "list.h"
#include "low_power_manager.h"
+#include "module.h"
#include "non_repeating_timer.h"
#include "osi.h"
#include "packet_fragmenter.h"
#include "reactor.h"
#include "vendor.h"
+// TODO(zachoverflow): remove this hack extern
+#include <hardware/bluetooth.h>
+bt_bdaddr_t btif_local_bd_addr;
+
#define HCI_COMMAND_COMPLETE_EVT 0x0E
#define HCI_COMMAND_STATUS_EVT 0x0F
@@ -103,7 +108,6 @@ static hci_t interface;
static const allocator_t *buffer_allocator;
static const btsnoop_t *btsnoop;
static const controller_t *controller;
-static const hci_callbacks_t *callbacks;
static const hci_hal_t *hal;
static const hci_hal_callbacks_t hal_callbacks;
static const hci_inject_t *hci_inject;
@@ -112,10 +116,10 @@ static const packet_fragmenter_t *packet_fragmenter;
static const packet_fragmenter_callbacks_t packet_fragmenter_callbacks;
static const vendor_t *vendor;
+static future_t *startup_future;
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;
@@ -130,6 +134,8 @@ 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 future_t *shut_down();
+
static void event_finish_startup(void *context);
static void firmware_config_callback(bool success);
static void startup_timer_expired(void *context);
@@ -151,12 +157,9 @@ static bool filter_incoming_event(BT_HDR *packet);
static serial_data_type_t event_to_data_type(uint16_t event);
static waiting_command_t *get_waiting_command(command_opcode_t opcode);
-// Interface functions
-
-static bool start_up_async(bdaddr_t local_bdaddr, const hci_callbacks_t *upper_callbacks) {
- assert(local_bdaddr != NULL);
- assert(upper_callbacks != NULL);
+// Module lifecycle functions
+static future_t *start_up(void) {
ALOGI("%s", __func__);
// The host is only allowed to send at most one command initially,
@@ -164,7 +167,6 @@ static bool start_up_async(bdaddr_t local_bdaddr, const hci_callbacks_t *upper_c
// This value can change when you get a command complete or command status event.
command_credits = 1;
firmware_is_configured = false;
- has_shut_down = false;
pthread_mutex_init(&commands_pending_response_lock, NULL);
@@ -220,7 +222,6 @@ static bool start_up_async(bdaddr_t local_bdaddr, const hci_callbacks_t *upper_c
goto error;
}
- callbacks = upper_callbacks;
memset(incoming_packets, 0, sizeof(incoming_packets));
controller->init(&interface);
@@ -229,7 +230,7 @@ static bool start_up_async(bdaddr_t local_bdaddr, const hci_callbacks_t *upper_c
fixed_queue_register_dequeue(command_queue, thread_get_reactor(thread), event_command_ready, NULL);
fixed_queue_register_dequeue(packet_queue, thread_get_reactor(thread), event_packet_ready, NULL);
- vendor->open(local_bdaddr, &interface);
+ vendor->open(btif_local_bd_addr.address, &interface);
hal->init(&hal_callbacks, thread);
low_power_manager->init(thread);
@@ -257,21 +258,16 @@ static bool start_up_async(bdaddr_t local_bdaddr, const hci_callbacks_t *upper_c
power_state = BT_VND_PWR_ON;
vendor->send_command(VENDOR_CHIP_POWER_CONTROL, &power_state);
+ startup_future = future_new();
ALOGD("%s starting async portion", __func__);
thread_post(thread, event_finish_startup, NULL);
-
- return true;
+ return startup_future;
error:;
- interface.shut_down();
- return false;
+ shut_down(); // returns NULL so no need to wait for it
+ return future_new_immediate(FUTURE_FAIL);
}
-static void shut_down() {
- if (has_shut_down) {
- ALOGW("%s already happened for this session", __func__);
- return;
- }
-
+static future_t *shut_down() {
ALOGI("%s", __func__);
hci_inject->close();
@@ -313,9 +309,24 @@ static void shut_down() {
thread_free(thread);
thread = NULL;
firmware_is_configured = false;
- has_shut_down = true;
+
+ return NULL;
}
+const module_t hci_module = {
+ .name = HCI_MODULE,
+ .init = NULL,
+ .start_up = start_up,
+ .shut_down = shut_down,
+ .clean_up = NULL,
+ .dependencies = {
+ BTSNOOP_MODULE,
+ NULL
+ }
+};
+
+// Interface functions
+
static void do_postload() {
ALOGD("%s posting postload work item", __func__);
thread_post(thread, event_postload, NULL);
@@ -367,11 +378,14 @@ static void event_finish_startup(UNUSED_ATTR void *context) {
static void firmware_config_callback(UNUSED_ATTR bool success) {
firmware_is_configured = true;
non_repeating_timer_cancel(startup_timer);
- callbacks->startup_finished(true);
+
+ future_ready(startup_future, FUTURE_SUCCESS);
+ startup_future = NULL;
}
static void startup_timer_expired(UNUSED_ATTR void *context) {
- callbacks->startup_finished(false);
+ future_ready(startup_future, FUTURE_FAIL);
+ startup_future = NULL;
}
// Postload functions
@@ -448,11 +462,14 @@ static void transmit_fragment(BT_HDR *packet, bool send_transmit_finished) {
hal->transmit_data(type, packet->data + packet->offset, packet->len);
if (event != MSG_STACK_TO_HC_HCI_CMD && send_transmit_finished)
- callbacks->transmit_finished(packet, true);
+ buffer_allocator->free(packet);
}
-static void fragmenter_transmit_finished(void *buffer, bool all_fragments_sent) {
- callbacks->transmit_finished(buffer, all_fragments_sent);
+static void fragmenter_transmit_finished(BT_HDR *packet, bool all_fragments_sent) {
+ if (all_fragments_sent)
+ buffer_allocator->free(packet);
+ else
+ data_dispatcher_dispatch(interface.upward_dispatcher, packet->event & MSG_EVT_MASK, packet);
}
static void command_timed_out(UNUSED_ATTR void *context) {
@@ -670,9 +687,6 @@ static waiting_command_t *get_waiting_command(command_opcode_t opcode) {
static void init_layer_interface() {
if (!interface_created) {
- interface.start_up_async = start_up_async;
- interface.shut_down = shut_down;
-
interface.send_low_power_command = low_power_manager->post_command;
interface.do_postload = do_postload;
diff --git a/hci/test/hci_layer_test.cpp b/hci/test/hci_layer_test.cpp
index d040138d2..40d3587b0 100644
--- a/hci/test/hci_layer_test.cpp
+++ b/hci/test/hci_layer_test.cpp
@@ -33,11 +33,14 @@ extern "C" {
#include "hci_inject.h"
#include "hci_layer.h"
#include "low_power_manager.h"
+#include "module.h"
#include "osi.h"
#include "packet_fragmenter.h"
#include "semaphore.h"
#include "test_stubs.h"
#include "vendor.h"
+
+extern const module_t hci_module;
}
DECLARE_TEST_MODES(
@@ -343,9 +346,9 @@ STUB_FUNCTION(void, low_power_transmit_done, ())
UNEXPECTED_CALL;
}
-STUB_FUNCTION(bool, vendor_open, (const uint8_t *addr, const hci_t *hci_interface))
+STUB_FUNCTION(bool, vendor_open, (UNUSED_ATTR const uint8_t *addr, const hci_t *hci_interface))
DURING(start_up_async) AT_CALL(0) {
- EXPECT_EQ(test_addr, addr);
+ //EXPECT_EQ(test_addr, addr); // TODO(zachoverflow): reinstate when address put into module
EXPECT_EQ(hci, hci_interface);
return true;
}
@@ -428,26 +431,6 @@ STUB_FUNCTION(int, vendor_send_async_command, (UNUSED_ATTR vendor_async_opcode_t
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);
- osi_free(buffer);
- return;
- }
-
- UNEXPECTED_CALL;
-}
-
STUB_FUNCTION(void, command_complete_callback, (BT_HDR *response, UNUSED_ATTR void *context))
DURING(transmit_command_command_complete) AT_CALL(0) {
osi_free(response);
@@ -511,8 +494,6 @@ 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);
RESET_CALL_COUNT(controller_init);
@@ -540,6 +521,7 @@ class HciLayerTest : public AlarmTestHarness {
// Make sure the data dispatcher allocation isn't tracked
allocation_tracker_reset();
+ module_management_start();
packet_index = 0;
data_size_sum = 0;
@@ -562,8 +544,6 @@ 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;
controller.get_acl_size_classic = controller_get_acl_size_classic;
@@ -572,8 +552,7 @@ class HciLayerTest : public AlarmTestHarness {
done = semaphore_new(0);
reset_for(start_up_async);
- hci->start_up_async(test_addr, &callbacks);
- semaphore_wait(done);
+ EXPECT_TRUE(module_start_up(&hci_module));
EXPECT_CALL_COUNT(vendor_open, 1);
EXPECT_CALL_COUNT(hal_init, 1);
@@ -582,12 +561,11 @@ class HciLayerTest : public AlarmTestHarness {
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() {
reset_for(shut_down);
- hci->shut_down();
+ module_shut_down(&hci_module);
EXPECT_CALL_COUNT(low_power_cleanup, 1);
EXPECT_CALL_COUNT(hal_close, 1);
@@ -595,6 +573,7 @@ class HciLayerTest : public AlarmTestHarness {
EXPECT_CALL_COUNT(vendor_close, 1);
semaphore_free(done);
+ module_management_stop();
AlarmTestHarness::TearDown();
}
@@ -604,7 +583,6 @@ class HciLayerTest : public AlarmTestHarness {
hci_inject_t hci_inject;
vendor_t vendor;
low_power_manager_t low_power_manager;
- hci_callbacks_t callbacks;
};
TEST_F(HciLayerTest, test_postload) {
@@ -626,7 +604,6 @@ TEST_F(HciLayerTest, test_transmit_simple) {
EXPECT_CALL_COUNT(btsnoop_capture, 1);
EXPECT_CALL_COUNT(low_power_transmit_done, 1);
EXPECT_CALL_COUNT(low_power_wake_assert, 1);
- EXPECT_CALL_COUNT(callback_transmit_finished, 1);
}
TEST_F(HciLayerTest, test_receive_simple) {
diff --git a/hci/test/packet_fragmenter_test.cpp b/hci/test/packet_fragmenter_test.cpp
index 2221fc18a..929973cc1 100644
--- a/hci/test/packet_fragmenter_test.cpp
+++ b/hci/test/packet_fragmenter_test.cpp
@@ -247,7 +247,7 @@ STUB_FUNCTION(void, reassembled_callback, (BT_HDR *packet))
UNEXPECTED_CALL;
}
-STUB_FUNCTION(void, transmit_finished_callback, (UNUSED_ATTR void *packet, UNUSED_ATTR bool sent_all_fragments))
+STUB_FUNCTION(void, transmit_finished_callback, (UNUSED_ATTR BT_HDR *packet, UNUSED_ATTR bool sent_all_fragments))
UNEXPECTED_CALL;
}