Re: [PATCH BlueZ v2] mesh: Add start up management command chain

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Inga,

This patch was applied.

On Tue, 2018-09-04 at 17:20 -0700, Inga Stotland wrote:
> This allows co-existense of meshd and bluetoothd. meshd will
> automatically take control of the first available LE-capable
> controller that is powered 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)




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux