All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH BlueZ 1/1] mesh: Add start up management command chain
@ 2018-09-04 20:00 Inga Stotland
  0 siblings, 0 replies; only message in thread
From: Inga Stotland @ 2018-09-04 20:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Inga Stotland

This allows co-existense of meshd and bluetoothd. meshd will
automatically take control of the first available LE-capable
controller that is not in use , i.e., is poered down.
---
 Makefile.mesh |   4 +-
 mesh/btmesh.c |   5 +-
 mesh/main.c   |  22 ++---
 mesh/mesh.c   | 253 +++++++++++++++++++++++++++++++++++++++++++++-----
 mesh/mesh.h   |   4 +-
 mesh/net.c    |  49 +++++-----
 6 files changed, 269 insertions(+), 68 deletions(-)

diff --git a/Makefile.mesh b/Makefile.mesh
index 643b1a59a..e93e68e38 100644
--- a/Makefile.mesh
+++ b/Makefile.mesh
@@ -23,7 +23,7 @@ libexec_PROGRAMS += mesh/meshd
 mesh_meshd_SOURCES = $(mesh_sources) mesh/main.c
 
 mesh_meshd_LDADD = src/shared/ecc.lo src/shared/queue.lo src/shared/io-ell.lo \
-				src/shared/util.lo src/shared/hci.lo \
+				src/shared/util.lo src/shared/hci.lo src/shared/mgmt.lo \
 				@DBUS_LIBS@ @ELL_LIBS@ -ljson-c
 
 noinst_PROGRAMS += mesh/btmesh
@@ -34,7 +34,7 @@ mesh_btmesh_SOURCES = $(mesh_sources) \
 						mesh/btmesh.c
 
 mesh_btmesh_LDADD = src/shared/ecc.lo src/shared/queue.lo src/shared/io-ell.lo \
-				src/shared/util.lo src/shared/hci.lo \
+				src/shared/util.lo src/shared/hci.lo src/shared/mgmt.lo \
 				src/libshared-mainloop.la \
 				-lreadline @ELL_LIBS@ -ljson-c
 
diff --git a/mesh/btmesh.c b/mesh/btmesh.c
index c312d85db..108ec39f3 100644
--- a/mesh/btmesh.c
+++ b/mesh/btmesh.c
@@ -153,8 +153,8 @@ int main(int argc, char *argv[])
 
 	l_info("Starting mesh on hci%d\n", index);
 
-	mesh = mesh_create(index);
-	if (!mesh || !mesh_load_config(mesh, config_option)) {
+	mesh = mesh_new(index, config_option);
+	if (!mesh) {
 		l_info("Failed to create mesh\n");
 		bt_shell_cleanup();
 		return EXIT_FAILURE;
@@ -170,6 +170,7 @@ int main(int argc, char *argv[])
 	bt_shell_run();
 
 	mesh_unref(mesh);
+	mesh_cleanup();
 	l_main_exit();
 
 	return status;
diff --git a/mesh/main.c b/mesh/main.c
index 8c03f51eb..289b0582b 100644
--- a/mesh/main.c
+++ b/mesh/main.c
@@ -30,6 +30,9 @@
 #include <sys/stat.h>
 #include <ell/ell.h>
 
+#include "lib/bluetooth.h"
+#include "lib/mgmt.h"
+
 #include "mesh/mesh.h"
 #include "mesh/net.h"
 #include "mesh/storage.h"
@@ -81,6 +84,7 @@ int main(int argc, char *argv[])
 	sigset_t mask;
 	struct bt_mesh *mesh = NULL;
 	const char *config_file = NULL;
+	int index = MGMT_INDEX_NONE;
 
 	if (!l_main_init())
 		return -1;
@@ -107,12 +111,7 @@ int main(int argc, char *argv[])
 				goto done;
 			}
 
-			mesh = mesh_create(atoi(str));
-			if (!mesh) {
-				l_error("Failed to initialize mesh");
-				status = EXIT_FAILURE;
-				goto done;
-			}
+			index = atoi(str);
 
 			break;
 		case 'n':
@@ -135,14 +134,8 @@ int main(int argc, char *argv[])
 		}
 	}
 
-	if (!mesh) {
-		usage();
-		status = EXIT_FAILURE;
-		goto done;
-	}
-
-	if (!mesh_load_config(mesh, config_file)) {
-		l_error("Failed to load mesh configuration: %s", config_file);
+	if (!mesh_new(index, config_file)) {
+		l_error("Failed to initialize mesh");
 		status = EXIT_FAILURE;
 		goto done;
 	}
@@ -168,6 +161,7 @@ int main(int argc, char *argv[])
 
 done:
 	mesh_unref(mesh);
+	mesh_cleanup();
 	l_main_exit();
 
 	return status;
diff --git a/mesh/mesh.c b/mesh/mesh.c
index a6f733f5c..3fba0140c 100644
--- a/mesh/mesh.c
+++ b/mesh/mesh.c
@@ -26,9 +26,11 @@
 #include <ell/ell.h>
 
 #include "lib/bluetooth.h"
+#include "lib/mgmt.h"
 
-#include "mesh/mesh-defs.h"
+#include "src/shared/mgmt.h"
 
+#include "mesh/mesh-defs.h"
 #include "mesh/mesh-io.h"
 #include "mesh/node.h"
 #include "mesh/net.h"
@@ -44,11 +46,25 @@ struct scan_filter {
 
 struct bt_mesh {
 	struct mesh_net *net;
-	int ref_count;
+	struct mesh_io *io;
 	struct l_queue *filters;
+	int ref_count;
+	uint16_t index;
+	uint16_t req_index;
 	uint8_t max_filters;
 };
 
+static struct l_queue *controllers;
+static struct l_queue *mesh_list;
+static struct mgmt *mgmt_mesh;
+static bool initialized;
+static struct bt_mesh *current;
+
+static bool simple_match(const void *a, const void *b)
+{
+	return a == b;
+}
+
 static void save_exit_config(struct bt_mesh *mesh)
 {
 	const char *cfg_filename;
@@ -64,36 +80,233 @@ static void save_exit_config(struct bt_mesh *mesh)
 		l_info("Saved final configuration to %s", cfg_filename);
 }
 
-struct bt_mesh *mesh_create(uint16_t index)
+static void start_io(struct bt_mesh *mesh, uint16_t index)
 {
-	struct bt_mesh *mesh;
 	struct mesh_io *io;
 	struct mesh_io_caps caps;
 
+	l_debug("Starting mesh on hci %u", index);
+
+	io = mesh_io_new(index, MESH_IO_TYPE_GENERIC);
+	if (!io) {
+		l_error("Failed to start mesh io (hci %u)", index);
+		current = NULL;
+		return;
+	}
+
+	mesh_io_get_caps(io, &caps);
+	mesh->max_filters = caps.max_num_filters;
+
+	mesh_net_attach(mesh->net, io);
+	mesh_net_set_window_accuracy(mesh->net, caps.window_accuracy);
+	mesh->io = io;
+	mesh->index = index;
+
+	current = NULL;
+
+	l_debug("Started mesh (io %p) on hci %u", mesh->io, index);
+}
+
+static void read_info_cb(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	uint16_t index = L_PTR_TO_UINT(user_data);
+	const struct mgmt_rp_read_info *rp = param;
+	uint32_t current_settings, supported_settings;
+
+	if (!current)
+		/* Already initialized */
+		return;
+
+	l_debug("hci %u status 0x%02x", index, status);
+
+	if (status != MGMT_STATUS_SUCCESS) {
+		l_error("Failed to read info for hci index %u: %s (0x%02x)",
+					index, mgmt_errstr(status), status);
+		return;
+	}
+
+	if (length < sizeof(*rp)) {
+		l_error("Read info response too short");
+		return;
+	}
+
+	current_settings = btohl(rp->current_settings);
+	supported_settings = btohl(rp->supported_settings);
+
+	l_debug("settings: supp %8.8x curr %8.8x",
+					supported_settings, current_settings);
+
+	if (current_settings & MGMT_SETTING_POWERED) {
+		l_info("Controller hci %u is in use", index);
+		return;
+	}
+
+	if (!(supported_settings & MGMT_SETTING_LE)) {
+		l_info("Controller hci %u does not support LE", index);
+		return;
+	}
+
+	start_io(current, index);
+}
+
+static void index_added(uint16_t index, uint16_t length, const void *param,
+							void *user_data)
+{
+	l_debug("hci device %u", index);
+
+	if (!current)
+		return;
+
+	if (current->req_index != MGMT_INDEX_NONE &&
+					index != current->req_index) {
+		l_debug("Ignore index %d", index);
+		return;
+	}
+
+	if (l_queue_find(controllers, simple_match, L_UINT_TO_PTR(index)))
+		return;
+
+	l_queue_push_tail(controllers, L_UINT_TO_PTR(index));
+
+	if (mgmt_send(mgmt_mesh, MGMT_OP_READ_INFO, index, 0, NULL,
+			read_info_cb, L_UINT_TO_PTR(index), NULL) > 0)
+		return;
+
+	l_queue_remove(controllers, L_UINT_TO_PTR(index));
+}
+
+static void index_removed(uint16_t index, uint16_t length, const void *param,
+							void *user_data)
+{
+	l_warn("Hci dev %4.4x removed", index);
+	l_queue_remove(controllers, L_UINT_TO_PTR(index));
+}
+
+static void read_index_list_cb(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;
+
+	if (status != MGMT_STATUS_SUCCESS) {
+		l_error("Failed to read index list: %s (0x%02x)",
+						mgmt_errstr(status), status);
+		return;
+	}
+
+	if (length < sizeof(*rp)) {
+		l_error("Read index list response sixe too short");
+		return;
+	}
+
+	num = btohs(rp->num_controllers);
+
+	l_debug("Number of controllers: %u", num);
+
+	if (num * sizeof(uint16_t) + sizeof(*rp) != length) {
+		l_error("Incorrect packet size for index list response");
+		return;
+	}
+
+	for (i = 0; i < num; i++) {
+		uint16_t index;
+
+		index = btohs(rp->index[i]);
+		index_added(index, 0, NULL, user_data);
+	}
+}
+
+static bool load_config(struct bt_mesh *mesh, const char *in_config_name)
+{
+	if (!mesh->net)
+		return false;
+
+	if (!storage_parse_config(mesh->net, in_config_name))
+		return false;
+
+	/* Register foundational models */
+	mesh_config_srv_init(mesh->net, PRIMARY_ELE_IDX);
+
+	return true;
+}
+
+static bool init_mesh(void)
+{
+	if (initialized)
+		return true;
+
+	controllers = l_queue_new();
+	if (!controllers)
+		return false;
+
+	mesh_list = l_queue_new();
+	if (!mesh_list)
+		return false;
+
+	mgmt_mesh = mgmt_new_default();
+	if (!mgmt_mesh)
+		goto fail;
+
+	mgmt_register(mgmt_mesh, MGMT_EV_INDEX_ADDED, MGMT_INDEX_NONE,
+						index_added, NULL, NULL);
+	mgmt_register(mgmt_mesh, MGMT_EV_INDEX_REMOVED, MGMT_INDEX_NONE,
+						index_removed, NULL, NULL);
+
+	initialized = true;
+	return true;
+
+fail:
+	l_error("Failed to initialize mesh management");
+
+	l_queue_destroy(controllers, NULL);
+
+	return false;
+}
+
+struct bt_mesh *mesh_new(uint16_t index, const char *config_file)
+{
+	struct bt_mesh *mesh;
+
+	if (!init_mesh())
+		return NULL;
+
 	mesh = l_new(struct bt_mesh, 1);
 	if (!mesh)
 		return NULL;
 
+	mesh->req_index = index;
+	mesh->index = MGMT_INDEX_NONE;
+
 	mesh->net = mesh_net_new(index);
 	if (!mesh->net) {
 		l_free(mesh);
 		return NULL;
 	}
 
-	io = mesh_io_new(index, MESH_IO_TYPE_GENERIC);
-	if (!io) {
-		mesh_net_unref(mesh->net);
+	if (!load_config(mesh, config_file)) {
+		l_error("Failed to load mesh configuration: %s", config_file);
 		l_free(mesh);
 		return NULL;
 	}
 
-	mesh_io_get_caps(io, &caps);
-	mesh->max_filters = caps.max_num_filters;
+	/*
+	 * TODO: Check if another mesh is searching for io.
+	 * If so, add to pending list and return.
+	 */
+	l_debug("send read index_list");
+	if (mgmt_send(mgmt_mesh, MGMT_OP_READ_INDEX_LIST,
+				MGMT_INDEX_NONE, 0, NULL,
+				read_index_list_cb, mesh, NULL) > 0) {
+		current = mesh;
+		l_queue_push_tail(mesh_list, mesh);
+		return mesh_ref(mesh);
+	}
 
-	mesh_net_attach(mesh->net, io);
-	mesh_net_set_window_accuracy(mesh->net, caps.window_accuracy);
+	l_free(mesh);
 
-	return mesh_ref(mesh);
+	return NULL;
 }
 
 struct bt_mesh *mesh_ref(struct bt_mesh *mesh)
@@ -127,18 +340,15 @@ void mesh_unref(struct bt_mesh *mesh)
 		mesh_io_destroy(io);
 
 	mesh_net_unref(mesh->net);
+	l_queue_remove(mesh_list, mesh);
 	l_free(mesh);
 }
 
-bool mesh_load_config(struct bt_mesh *mesh, const char *in_config_name)
+void mesh_cleanup(void)
 {
-	if (!storage_parse_config(mesh->net, in_config_name))
-		return false;
-
-	/* Register foundational models */
-	mesh_config_srv_init(mesh->net, PRIMARY_ELE_IDX);
-
-	return true;
+	l_queue_destroy(controllers, NULL);
+	l_queue_destroy(mesh_list, NULL);
+	mgmt_unref(mgmt_mesh);
 }
 
 bool mesh_set_output(struct bt_mesh *mesh, const char *config_name)
@@ -177,8 +387,5 @@ const char *mesh_status_str(uint8_t err)
 
 struct mesh_net *mesh_get_net(struct bt_mesh *mesh)
 {
-	if (!mesh)
-		return NULL;
-
 	return mesh->net;
 }
diff --git a/mesh/mesh.h b/mesh/mesh.h
index 7cd1e6158..8d389883b 100644
--- a/mesh/mesh.h
+++ b/mesh/mesh.h
@@ -21,11 +21,11 @@
 struct bt_mesh;
 struct mesh_net;
 
-struct bt_mesh *mesh_create(uint16_t index);
+struct bt_mesh *mesh_new(uint16_t index, const char *in_config_name);
 struct bt_mesh *mesh_ref(struct bt_mesh *mesh);
 void mesh_unref(struct bt_mesh *mesh);
-bool mesh_load_config(struct bt_mesh *mesh, const char *in_config_name);
 bool mesh_set_output(struct bt_mesh *mesh, const char *out_config_name);
+void mesh_cleanup(void);
 const char *mesh_status_str(uint8_t err);
 
 /* Command line testing */
diff --git a/mesh/net.c b/mesh/net.c
index 544f9efa5..fb17e639d 100644
--- a/mesh/net.c
+++ b/mesh/net.c
@@ -1133,7 +1133,8 @@ int mesh_net_add_key(struct mesh_net *net, bool update, uint16_t idx,
 		return MESH_STATUS_STORAGE_FAIL;
 	}
 
-	start_network_beacon(subnet, net);
+	if (net->io)
+		start_network_beacon(subnet, net);
 
 	return MESH_STATUS_SUCCESS;
 }
@@ -3099,13 +3100,34 @@ bool mesh_net_set_beacon_mode(struct mesh_net *net, bool enable)
 	return true;
 }
 
-
 bool mesh_net_attach(struct mesh_net *net, struct mesh_io *io)
 {
 	if (!net)
 		return false;
 
 	net->io = io;
+	if (net->provisioned) {
+
+		mesh_io_register_recv_cb(io, MESH_IO_FILTER_BEACON,
+							beacon_recv, net);
+		mesh_io_register_recv_cb(io, MESH_IO_FILTER_NET,
+							net_msg_recv, net);
+		l_queue_foreach(net->subnets, start_network_beacon, net);
+
+	} else {
+		uint8_t *uuid = node_uuid_get(net->local_node);
+
+		if (!uuid)
+			return false;
+
+		mesh_io_deregister_recv_cb(io, MESH_IO_FILTER_BEACON);
+		mesh_io_deregister_recv_cb(io, MESH_IO_FILTER_NET);
+
+		mesh_prov_listen(net, uuid, (uint8_t *) &net->prov_caps,
+					acceptor_prov_open,
+					acceptor_prov_close,
+					acceptor_prov_receive, net);
+	}
 
 	return true;
 }
@@ -4150,33 +4172,10 @@ bool mesh_net_provisioned_new(struct mesh_net *net, uint8_t device_key[16],
 
 void mesh_net_provisioned_set(struct mesh_net *net, bool provisioned)
 {
-	struct mesh_io *io;
-
 	if (!net)
 		return;
 
 	net->provisioned = provisioned;
-	io = net->io;
-
-	if (provisioned) {
-		mesh_io_register_recv_cb(io, MESH_IO_FILTER_BEACON,
-							beacon_recv, net);
-		mesh_io_register_recv_cb(io, MESH_IO_FILTER_NET,
-							net_msg_recv, net);
-	} else {
-		uint8_t *uuid = node_uuid_get(net->local_node);
-
-		if (!uuid)
-			return;
-
-		mesh_io_deregister_recv_cb(io, MESH_IO_FILTER_BEACON);
-		mesh_io_deregister_recv_cb(io, MESH_IO_FILTER_NET);
-
-		mesh_prov_listen(net, uuid, (uint8_t *) &net->prov_caps,
-					acceptor_prov_open,
-					acceptor_prov_close,
-					acceptor_prov_receive, net);
-	}
 }
 
 bool mesh_net_provisioned_get(struct mesh_net *net)
-- 
2.17.1

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2018-09-04 20:00 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-04 20:00 [PATCH BlueZ 1/1] mesh: Add start up management command chain Inga Stotland

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.