Diff between 73e110b5b039c452a540a38bdeb55aa9fa3f2b3a and e809154eba57d61fb8f058ae71c05a444c093763

Changed Files

File Additions Deletions Status
android/adapter.c +185 -10 modified
android/adapter.h +5 -2 modified
android/main.c +50 -250 modified

Full Patch

diff --git a/android/adapter.c b/android/adapter.c
index f8bfb36..1d628c8 100644
--- a/android/adapter.c
+++ b/android/adapter.c
@@ -58,6 +58,8 @@
 #define BASELEN_PROP_CHANGED sizeof(struct hal_ev_adapter_props_changed) \
 				+ (sizeof(struct hal_property))
 
+static uint16_t option_index = MGMT_INDEX_NONE;
+
 static int notification_sk = -1;
 
 /* This list contains addresses which are asked for records */
@@ -1337,28 +1339,201 @@ failed:
 	adapter_ready(err);
 }
 
-void bt_adapter_init(uint16_t index, struct mgmt *mgmt, bt_adapter_ready cb)
+static void mgmt_index_added_event(uint16_t index, uint16_t length,
+					const void *param, void *user_data)
 {
-	mgmt_if = mgmt_ref(mgmt);
+	DBG("index %u", index);
 
-	adapter.index = index;
+	if (adapter.index != MGMT_INDEX_NONE) {
+		DBG("skip event for index %u", index);
+		return;
+	}
 
-	adapter_ready = cb;
+	if (option_index != MGMT_INDEX_NONE && option_index != index) {
+		DBG("skip event for index %u (option %u)", index, option_index);
+		return;
+	}
 
-	/* TODO: Read discoverable timeout from some storage */
+	if (mgmt_send(mgmt_if, MGMT_OP_READ_INFO, index, 0, NULL,
+				read_info_complete, NULL, NULL) == 0) {
+		adapter_ready(-EIO);
+		return;
+	}
+}
 
-	if (mgmt_send(mgmt, MGMT_OP_READ_INFO, index, 0, NULL,
-					read_info_complete, NULL, NULL) > 0)
+static void mgmt_index_removed_event(uint16_t index, uint16_t length,
+					const void *param, void *user_data)
+{
+	DBG("index %u", index);
+
+	if (index != adapter.index)
 		return;
 
-	mgmt_unref(mgmt_if);
-	mgmt_if = NULL;
+	error("Adapter was removed. Exiting.");
+	raise(SIGTERM);
+}
+
+static void read_index_list_complete(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	const struct mgmt_rp_read_index_list *rp = param;
+	uint16_t num;
+	int i;
+
+	DBG("");
+
+	if (status) {
+		error("%s: Failed to read index list: %s (0x%02x)",
+					__func__, mgmt_errstr(status), status);
+		goto failed;
+	}
+
+	if (length < sizeof(*rp)) {
+		error("%s: Wrong size of read index list response", __func__);
+		goto failed;
+	}
+
+	num = btohs(rp->num_controllers);
+
+	DBG("Number of controllers: %u", num);
+
+	if (num * sizeof(uint16_t) + sizeof(*rp) != length) {
+		error("%s: Incorrect pkt size for index list rsp", __func__);
+		goto failed;
+	}
+
+	if (adapter.index != MGMT_INDEX_NONE)
+		return;
+
+	for (i = 0; i < num; i++) {
+		uint16_t index = btohs(rp->index[i]);
+
+		if (option_index != MGMT_INDEX_NONE && option_index != index)
+			continue;
+
+		if (mgmt_send(mgmt_if, MGMT_OP_READ_INFO, index, 0, NULL,
+					read_info_complete, NULL, NULL) == 0)
+			goto failed;
+
+		adapter.index = index;
+		return;
+	}
+
+	return;
+
+failed:
+	adapter_ready(-EIO);
+}
+
+static void read_version_complete(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	const struct mgmt_rp_read_version *rp = param;
+	uint8_t mgmt_version, mgmt_revision;
+
+	DBG("");
+
+	if (status) {
+		error("Failed to read version information: %s (0x%02x)",
+						mgmt_errstr(status), status);
+		goto failed;
+	}
+
+	if (length < sizeof(*rp)) {
+		error("Wrong size response");
+		goto failed;
+	}
 
-	adapter.index = MGMT_INDEX_NONE;
+	mgmt_version = rp->version;
+	mgmt_revision = btohs(rp->revision);
+
+	info("Bluetooth management interface %u.%u initialized",
+						mgmt_version, mgmt_revision);
+
+	if (MGMT_VERSION(mgmt_version, mgmt_revision) < MGMT_VERSION(1, 3)) {
+		error("Version 1.3 or later of management interface required");
+		goto failed;
+	}
+
+	mgmt_register(mgmt_if, MGMT_EV_INDEX_ADDED, MGMT_INDEX_NONE,
+					mgmt_index_added_event, NULL, NULL);
+	mgmt_register(mgmt_if, MGMT_EV_INDEX_REMOVED, MGMT_INDEX_NONE,
+					mgmt_index_removed_event, NULL, NULL);
+
+	if (mgmt_send(mgmt_if, MGMT_OP_READ_INDEX_LIST, MGMT_INDEX_NONE, 0,
+			NULL, read_index_list_complete, NULL, NULL) > 0)
+		return;
 
+	error("Failed to read controller index list");
+
+failed:
 	adapter_ready(-EIO);
 }
 
+bool bt_adapter_start(int index, bt_adapter_ready cb)
+{
+	DBG("index %d", index);
+
+	mgmt_if = mgmt_new_default();
+	if (!mgmt_if) {
+		error("Failed to access management interface");
+		return false;
+	}
+
+	if (mgmt_send(mgmt_if, MGMT_OP_READ_VERSION, MGMT_INDEX_NONE, 0, NULL,
+				read_version_complete, NULL, NULL) == 0) {
+		error("Error sending READ_VERSION mgmt command");
+
+		mgmt_unref(mgmt_if);
+		mgmt_if = NULL;
+
+		return false;
+	}
+
+	if (index >= 0)
+		option_index = index;
+
+	adapter_ready = cb;
+
+	return true;
+}
+
+static void shutdown_complete(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	bt_adapter_stopped cb = user_data;
+
+	if (status != MGMT_STATUS_SUCCESS)
+		error("Clean controller shutdown failed");
+
+	cb();
+}
+
+bool bt_adapter_stop(bt_adapter_stopped cb)
+{
+	struct mgmt_mode cp;
+
+	if (adapter.index == MGMT_INDEX_NONE)
+		return false;
+
+	info("Switching controller off");
+
+	memset(&cp, 0, sizeof(cp));
+
+	return mgmt_send(mgmt_if, MGMT_OP_SET_POWERED, adapter.index,
+				sizeof(cp), &cp, shutdown_complete, (void *)cb,
+				NULL) > 0;
+}
+
+void bt_adapter_cleanup(void)
+{
+	g_free(adapter.name);
+	adapter.name = NULL;
+
+	mgmt_unref(mgmt_if);
+	mgmt_if = NULL;
+}
+
 static bool set_discoverable(uint8_t mode, uint16_t timeout)
 {
 	struct mgmt_cp_set_discoverable cp;
diff --git a/android/adapter.h b/android/adapter.h
index 0e84cb0..e8993f2 100644
--- a/android/adapter.h
+++ b/android/adapter.h
@@ -22,9 +22,12 @@
  */
 
 typedef void (*bt_adapter_ready)(int err);
+bool bt_adapter_start(int index, bt_adapter_ready cb);
 
-void bt_adapter_init(uint16_t index, struct mgmt *mgmt_if,
-							bt_adapter_ready cb);
+typedef void (*bt_adapter_stopped)(void);
+bool bt_adapter_stop(bt_adapter_stopped cb);
+
+void bt_adapter_cleanup(void);
 
 void bt_adapter_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len);
 
diff --git a/android/main.c b/android/main.c
index db8b39a..8164819 100644
--- a/android/main.c
+++ b/android/main.c
@@ -45,8 +45,6 @@
 #include "src/sdpd.h"
 
 #include "lib/bluetooth.h"
-#include "lib/mgmt.h"
-#include "src/shared/mgmt.h"
 
 #include "adapter.h"
 #include "socket.h"
@@ -65,11 +63,9 @@
 #define STARTUP_GRACE_SECONDS 5
 #define SHUTDOWN_GRACE_SECONDS 10
 
-static GMainLoop *event_loop;
-static struct mgmt *mgmt_if = NULL;
+static guint bluetooth_start_timeout = 0;
 
-static uint16_t adapter_index = MGMT_INDEX_NONE;
-static guint adapter_timeout = 0;
+static GMainLoop *event_loop;
 
 static GIOChannel *hal_cmd_io = NULL;
 static GIOChannel *hal_notif_io = NULL;
@@ -186,35 +182,32 @@ static void handle_service_core(uint8_t opcode, void *buf, uint16_t len)
 	}
 }
 
-static void shutdown_complete(uint8_t status, uint16_t length,
-					const void *param, void *user_data)
+static void bluetooth_stopped(void)
 {
-	if (status != MGMT_STATUS_SUCCESS)
-		error("Clean controller shutdown failed");
+	g_main_loop_quit(event_loop);
+}
 
+static gboolean quit_eventloop(gpointer user_data)
+{
 	g_main_loop_quit(event_loop);
+	return FALSE;
 }
 
-static void shutdown_controller(void)
+static void stop_bluetooth(void)
 {
-	static bool __shutdown = false;
-	struct mgmt_mode cp;
+	static bool __stop = false;
 
-	if (__shutdown)
+	if (__stop)
 		return;
 
-	__shutdown = true;
-
-	info("Switching controller off");
+	__stop = true;
 
-	memset(&cp, 0, sizeof(cp));
-	cp.val = 0x00;
-
-	if (mgmt_send(mgmt_if, MGMT_OP_SET_POWERED, adapter_index,
-			sizeof(cp), &cp, shutdown_complete, NULL, NULL) > 0)
+	if (!bt_adapter_stop(bluetooth_stopped)) {
+		g_main_loop_quit(event_loop);
 		return;
+	}
 
-	g_main_loop_quit(event_loop);
+	g_timeout_add_seconds(SHUTDOWN_GRACE_SECONDS, quit_eventloop, NULL);
 }
 
 static gboolean cmd_watch_cb(GIOChannel *io, GIOCondition cond,
@@ -286,7 +279,7 @@ static gboolean cmd_watch_cb(GIOChannel *io, GIOCondition cond,
 	return TRUE;
 
 fail:
-	shutdown_controller();
+	stop_bluetooth();
 	return FALSE;
 }
 
@@ -294,7 +287,7 @@ static gboolean notif_watch_cb(GIOChannel *io, GIOCondition cond,
 							gpointer user_data)
 {
 	info("HAL notification socket closed, terminating");
-	shutdown_controller();
+	stop_bluetooth();
 
 	return FALSE;
 }
@@ -343,7 +336,7 @@ static gboolean notif_connect_cb(GIOChannel *io, GIOCondition cond,
 	DBG("");
 
 	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
-		g_main_loop_quit(event_loop);
+		stop_bluetooth();
 		return FALSE;
 	}
 
@@ -366,23 +359,38 @@ static gboolean cmd_connect_cb(GIOChannel *io, GIOCondition cond,
 	DBG("");
 
 	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
-		g_main_loop_quit(event_loop);
+		stop_bluetooth();
 		return FALSE;
 	}
 
 	hal_notif_io = connect_hal(notif_connect_cb);
 	if (!hal_notif_io) {
 		error("Cannot connect to HAL, terminating");
-		g_main_loop_quit(event_loop);
+		stop_bluetooth();
 	}
 
 	return FALSE;
 }
 
-static gboolean quit_eventloop(gpointer user_data)
+static void adapter_ready(int err)
 {
-	g_main_loop_quit(event_loop);
-	return FALSE;
+	if (err < 0) {
+		error("Adapter initialization failed: %s", strerror(-err));
+		exit(EXIT_FAILURE);
+	}
+
+	if (bluetooth_start_timeout > 0) {
+		g_source_remove(bluetooth_start_timeout);
+		bluetooth_start_timeout = 0;
+	}
+
+	info("Adapter initialized");
+
+	hal_cmd_io = connect_hal(cmd_connect_cb);
+	if (!hal_cmd_io) {
+		error("Cannot connect to HAL, terminating");
+		stop_bluetooth();
+	}
 }
 
 static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
@@ -407,12 +415,7 @@ static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
 	case SIGTERM:
 		if (!__terminated) {
 			info("Terminating");
-			if (adapter_index != MGMT_INDEX_NONE) {
-				g_timeout_add_seconds(SHUTDOWN_GRACE_SECONDS,
-							quit_eventloop, NULL);
-				shutdown_controller();
-			} else
-				g_main_loop_quit(event_loop);
+			stop_bluetooth();
 		}
 
 		__terminated = true;
@@ -460,7 +463,7 @@ static guint setup_signalfd(void)
 }
 
 static gboolean option_version = FALSE;
-static gint option_index = MGMT_INDEX_NONE;
+static gint option_index = -1;
 
 static GOptionEntry options[] = {
 	{ "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
@@ -470,216 +473,6 @@ static GOptionEntry options[] = {
 	{ NULL }
 };
 
-static void adapter_ready(int err)
-{
-	if (err < 0) {
-		error("Adapter initialization failed: %s", strerror(-err));
-		exit(EXIT_FAILURE);
-	}
-
-	info("Adapter initialized");
-
-	hal_cmd_io = connect_hal(cmd_connect_cb);
-	if (!hal_cmd_io) {
-		error("Cannot connect to HAL, terminating");
-		g_main_loop_quit(event_loop);
-	}
-}
-
-static void mgmt_index_added_event(uint16_t index, uint16_t length,
-					const void *param, void *user_data)
-{
-	uint16_t opt_index = option_index;
-
-	DBG("index %u", index);
-
-	if (adapter_index != MGMT_INDEX_NONE) {
-		DBG("skip event for index %u", index);
-		return;
-	}
-
-	if (opt_index != MGMT_INDEX_NONE && opt_index != index) {
-		DBG("skip event for index %u (option %u)", index, opt_index);
-		return;
-	}
-
-	if (adapter_timeout > 0) {
-		g_source_remove(adapter_timeout);
-		adapter_timeout = 0;
-	}
-
-	adapter_index = index;
-	bt_adapter_init(index, mgmt_if, adapter_ready);
-}
-
-static void mgmt_index_removed_event(uint16_t index, uint16_t length,
-					const void *param, void *user_data)
-{
-	DBG("index %u", index);
-
-	if (index != adapter_index)
-		return;
-
-	error("Adapter was removed. Exiting.");
-	g_main_loop_quit(event_loop);
-}
-
-static gboolean adapter_timeout_handler(gpointer user_data)
-{
-	adapter_timeout = 0;
-	g_main_loop_quit(event_loop);
-
-	return FALSE;
-}
-
-static void read_index_list_complete(uint8_t status, uint16_t length,
-					const void *param, void *user_data)
-{
-	const struct mgmt_rp_read_index_list *rp = param;
-	uint16_t opt_index = option_index;
-	uint16_t num;
-	int i;
-
-	DBG("");
-
-	if (status) {
-		error("%s: Failed to read index list: %s (0x%02x)",
-					__func__, mgmt_errstr(status), status);
-		goto failed;
-	}
-
-	if (length < sizeof(*rp)) {
-		error("%s: Wrong size of read index list response", __func__);
-		goto failed;
-	}
-
-	num = btohs(rp->num_controllers);
-
-	DBG("Number of controllers: %u", num);
-
-	if (num * sizeof(uint16_t) + sizeof(*rp) != length) {
-		error("%s: Incorrect pkt size for index list rsp", __func__);
-		goto failed;
-	}
-
-	if (adapter_index != MGMT_INDEX_NONE)
-		return;
-
-	for (i = 0; i < num; i++) {
-		uint16_t index = btohs(rp->index[i]);
-
-		if (opt_index != MGMT_INDEX_NONE && opt_index != index)
-			continue;
-
-		adapter_index = index;
-		bt_adapter_init(adapter_index, mgmt_if, adapter_ready);
-		return;
-	}
-
-	if (adapter_index != MGMT_INDEX_NONE)
-		return;
-
-	adapter_timeout = g_timeout_add_seconds(STARTUP_GRACE_SECONDS,
-					adapter_timeout_handler, NULL);
-	if (adapter_timeout > 0)
-		return;
-
-	error("%s: Failed init timeout", __func__);
-
-failed:
-	g_main_loop_quit(event_loop);
-}
-
-static void read_commands_complete(uint8_t status, uint16_t length,
-					const void *param, void *user_data)
-{
-	const struct mgmt_rp_read_commands *rp = param;
-
-	DBG("");
-
-	if (status) {
-		error("Failed to read supported commands: %s (0x%02x)",
-						mgmt_errstr(status), status);
-		return;
-	}
-
-	if (length < sizeof(*rp)) {
-		error("Wrong size response");
-		return;
-	}
-}
-
-static void read_version_complete(uint8_t status, uint16_t length,
-					const void *param, void *user_data)
-{
-	const struct mgmt_rp_read_version *rp = param;
-	uint8_t mgmt_version, mgmt_revision;
-
-	DBG("");
-
-	if (status) {
-		error("Failed to read version information: %s (0x%02x)",
-						mgmt_errstr(status), status);
-		goto failed;
-	}
-
-	if (length < sizeof(*rp)) {
-		error("Wrong size response");
-		goto failed;
-	}
-
-	mgmt_version = rp->version;
-	mgmt_revision = btohs(rp->revision);
-
-	info("Bluetooth management interface %u.%u initialized",
-						mgmt_version, mgmt_revision);
-
-	if (MGMT_VERSION(mgmt_version, mgmt_revision) < MGMT_VERSION(1, 3)) {
-		error("Version 1.3 or later of management interface required");
-		goto failed;
-	}
-
-	mgmt_send(mgmt_if, MGMT_OP_READ_COMMANDS, MGMT_INDEX_NONE, 0, NULL,
-					read_commands_complete, NULL, NULL);
-
-	mgmt_register(mgmt_if, MGMT_EV_INDEX_ADDED, MGMT_INDEX_NONE,
-					mgmt_index_added_event, NULL, NULL);
-	mgmt_register(mgmt_if, MGMT_EV_INDEX_REMOVED, MGMT_INDEX_NONE,
-					mgmt_index_removed_event, NULL, NULL);
-
-	if (mgmt_send(mgmt_if, MGMT_OP_READ_INDEX_LIST, MGMT_INDEX_NONE, 0,
-			NULL, read_index_list_complete, NULL, NULL) > 0)
-		return;
-
-	error("Failed to read controller index list");
-
-failed:
-	g_main_loop_quit(event_loop);
-}
-
-static bool init_mgmt_interface(void)
-{
-	mgmt_if = mgmt_new_default();
-	if (!mgmt_if) {
-		error("Failed to access management interface");
-		return false;
-	}
-
-	if (mgmt_send(mgmt_if, MGMT_OP_READ_VERSION, MGMT_INDEX_NONE, 0, NULL,
-				read_version_complete, NULL, NULL) == 0) {
-		error("Error sending READ_VERSION mgmt command");
-		return false;
-	}
-
-	return true;
-}
-
-static void cleanup_mgmt_interface(void)
-{
-	mgmt_unref(mgmt_if);
-	mgmt_if = NULL;
-}
-
 static void cleanup_hal_connection(void)
 {
 	if (hal_cmd_io) {
@@ -767,7 +560,14 @@ int main(int argc, char *argv[])
 	if (!set_capabilities())
 		return EXIT_FAILURE;
 
-	if (!init_mgmt_interface())
+	bluetooth_start_timeout = g_timeout_add_seconds(STARTUP_GRACE_SECONDS,
+							quit_eventloop, NULL);
+	if (bluetooth_start_timeout == 0) {
+		error("Failed to init startup timeout");
+		return EXIT_FAILURE;
+	}
+
+	if (!bt_adapter_start(option_index, adapter_ready))
 		return EXIT_FAILURE;
 
 	/* Use params: mtu = 0, flags = 0 */
@@ -781,7 +581,7 @@ int main(int argc, char *argv[])
 
 	cleanup_hal_connection();
 	stop_sdp_server();
-	cleanup_mgmt_interface();
+	bt_adapter_cleanup();
 	g_main_loop_unref(event_loop);
 
 	info("Exit");