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)
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);
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(
#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);
#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
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;
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;
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);
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,
// 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);
goto error;
}
- callbacks = upper_callbacks;
memset(incoming_packets, 0, sizeof(incoming_packets));
controller->init(&interface);
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);
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();
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);
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
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) {
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;
#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(
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;
}
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);
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);
// Make sure the data dispatcher allocation isn't tracked
allocation_tracker_reset();
+ module_management_start();
packet_index = 0;
data_size_sum = 0;
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;
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);
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);
EXPECT_CALL_COUNT(vendor_close, 1);
semaphore_free(done);
+ module_management_stop();
AlarmTestHarness::TearDown();
}
hci_inject_t hci_inject;
vendor_t vendor;
low_power_manager_t low_power_manager;
- hci_callbacks_t callbacks;
};
TEST_F(HciLayerTest, test_postload) {
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) {
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;
}
** 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
/*******************************************************************************
** 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;
/******************************************************************************
/* Initialize trace feature */
BTTRC_TraceInit(MAX_TRACE_RAM_SIZE, &BTE_TraceLogBuf[0], BTTRC_METHOD_RAM);
#endif
-
- pthread_mutex_init(&shutdown_lock, NULL);
}
/******************************************************************************
module_clean_up(get_module(STACK_CONFIG_MODULE));
- pthread_mutex_destroy(&shutdown_lock);
GKI_shutdown();
}
{
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();
}
/******************************************************************************
{
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();
}
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
-};