OSDN Git Service

Modulizification of the HCI layer
authorZach Johnson <zachoverflow@google.com>
Wed, 24 Sep 2014 01:30:45 +0000 (18:30 -0700)
committerAndre Eisenbach <eisenbach@google.com>
Mon, 16 Mar 2015 23:51:35 +0000 (16:51 -0700)
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.

hci/Android.mk
hci/include/hci_layer.h
hci/include/packet_fragmenter.h
hci/src/hci_layer.c
hci/test/hci_layer_test.cpp
hci/test/packet_fragmenter_test.cpp
main/bte_main.c

index 048652c..b1d04b6 100644 (file)
@@ -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)
index ba674ba..957e500 100644 (file)
@@ -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(
index 93dc97e..c7f643e 100644 (file)
@@ -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);
 
index 07c6484..6b4c2b7 100644 (file)
 #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;
 
index d040138..40d3587 100644 (file)
@@ -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) {
index 2221fc1..929973c 100644 (file)
@@ -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;
 }
 
index 0c5209a..be50e3e 100755 (executable)
@@ -70,9 +70,6 @@
 **  Static variables
 *******************************************************************************/
 static const hci_t *hci;
-static const hci_callbacks_t hci_callbacks;
-// Lock to serialize shutdown requests from upper layer.
-static pthread_mutex_t shutdown_lock;
 
 /*******************************************************************************
 **  Static functions
@@ -81,13 +78,7 @@ static pthread_mutex_t shutdown_lock;
 /*******************************************************************************
 **  Externs
 *******************************************************************************/
-void BTE_LoadStack(void);
-void BTE_UnloadStack(void);
-void scru_flip_bda (BD_ADDR dst, const BD_ADDR src);
-void bte_load_conf(const char *p_path);
 extern void bte_load_ble_conf(const char *p_path);
-bt_bdaddr_t btif_local_bd_addr;
-
 fixed_queue_t *btu_hci_msg_queue;
 
 /******************************************************************************
@@ -125,8 +116,6 @@ void bte_main_boot_entry(void)
     /* Initialize trace feature */
     BTTRC_TraceInit(MAX_TRACE_RAM_SIZE, &BTE_TraceLogBuf[0], BTTRC_METHOD_RAM);
 #endif
-
-    pthread_mutex_init(&shutdown_lock, NULL);
 }
 
 /******************************************************************************
@@ -147,7 +136,6 @@ void bte_main_shutdown()
 
     module_clean_up(get_module(STACK_CONFIG_MODULE));
 
-    pthread_mutex_destroy(&shutdown_lock);
     GKI_shutdown();
 }
 
@@ -165,10 +153,10 @@ void bte_main_enable()
 {
     APPL_TRACE_DEBUG("%s", __FUNCTION__);
 
-//    BTU_StartUp();
-
-    assert(hci->start_up_async(btif_local_bd_addr.address, &hci_callbacks));
     module_start_up(get_module(BTSNOOP_MODULE));
+    module_start_up(get_module(HCI_MODULE));
+
+    BTU_StartUp();
 }
 
 /******************************************************************************
@@ -185,15 +173,8 @@ void bte_main_disable(void)
 {
     APPL_TRACE_DEBUG("%s", __FUNCTION__);
 
+    module_shut_down(get_module(HCI_MODULE));
     module_shut_down(get_module(BTSNOOP_MODULE));
-    if (hci) {
-      // Shutdown is not thread safe and must be protected.
-      pthread_mutex_lock(&shutdown_lock);
-
-      hci->shut_down();
-
-      pthread_mutex_unlock(&shutdown_lock);
-    }
 
     BTU_ShutDown();
 }
@@ -343,66 +324,3 @@ void bte_main_hci_send (BT_HDR *p_msg, UINT16 event)
         GKI_freebuf(p_msg);
     }
 }
-
-/*****************************************************************************
-**
-**   libbt-hci Callback Functions
-**
-*****************************************************************************/
-
-/******************************************************************************
-**
-** 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 hci_startup_cb(bool success)
-{
-    APPL_TRACE_EVENT("HC preload_cb %d [1:SUCCESS 0:FAIL]", success);
-
-    if (success) {
-        BTU_StartUp();
-    } else {
-        ALOGE("%s hci startup failed", __func__);
-        // TODO(cmanton) Initiate shutdown sequence.
-    }
-}
-
-/******************************************************************************
-**
-** Function         tx_result
-**
-** Description      HOST/CONTROLLER LIB CALLBACK API - This function is called
-**                  from the libbt-hci once it has processed/sent the prior data
-**                  buffer which core stack passed to it through transmit_buf
-**                  call earlier.
-**
-**                  The core stack is responsible for releasing the data buffer
-**                  if it has been completedly processed.
-**
-**                  Bluedroid libbt-hci library uses 'transac' parameter to
-**                  pass data-path buffer/packet across bt_hci_lib interface
-**                  boundary. The 'p_buf' is not intended to be used here
-**                  but might point to data portion in data-path buffer.
-**
-** Returns          void
-**
-******************************************************************************/
-static void tx_result(void *p_buf, bool all_fragments_sent) {
-    if (!all_fragments_sent)
-        fixed_queue_enqueue(btu_hci_msg_queue, p_buf);
-    else
-        GKI_freebuf(p_buf);
-}
-
-/*****************************************************************************
-**   The libbt-hci Callback Functions Table
-*****************************************************************************/
-static const hci_callbacks_t hci_callbacks = {
-    hci_startup_cb,
-    tx_result
-};