Re: [PATCH BlueZ 1/1] mesh: Move HCI handling to mesh-io-generic

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

 



Hi Michał, I like where you are going with this.

On Tue, 2019-06-18 at 13:26 +0200, Michał Lowas-Rzechonek wrote:
> This patch separates 'mesh' module from 'mesh_io', particularly
> regarding configuration and initialization.
> 
> Main code is no longer aware of MGMT and HCI usage - querying available
> HCI interfaces now happens in mesh-io-generic.
> ---
>  mesh/main.c            |   4 +-
>  mesh/mesh-io-api.h     |   3 +-
>  mesh/mesh-io-generic.c | 203 ++++++++++++++++++++++++++++++++++++-----
>  mesh/mesh-io.c         |  17 ++--
>  mesh/mesh-io.h         |   2 +-
>  mesh/mesh.c            | 189 +++-----------------------------------
>  mesh/mesh.h            |   4 +-
>  7 files changed, 209 insertions(+), 213 deletions(-)
> 
> diff --git a/mesh/main.c b/mesh/main.c
> index 3cecd8fbf..262e3da48 100644
> --- a/mesh/main.c
> +++ b/mesh/main.c
> @@ -35,6 +35,7 @@
>  
>  #include "mesh/mesh.h"
>  #include "mesh/dbus.h"
> +#include "mesh/mesh-io.h"
>  
>  static const struct option main_options[] = {
>  	{ "index",	required_argument,	NULL, 'i' },
> @@ -166,7 +167,8 @@ int main(int argc, char *argv[])
>  		}
>  	}
>  
> -	if (!mesh_init(index, config_dir)) {
> +
> +	if (!mesh_init(config_dir, MESH_IO_TYPE_GENERIC, &index)) {
>  		l_error("Failed to initialize mesh");
>  		status = EXIT_FAILURE;
>  		goto done;
> diff --git a/mesh/mesh-io-api.h b/mesh/mesh-io-api.h
> index acf12445d..4cdf1f80a 100644
> --- a/mesh/mesh-io-api.h
> +++ b/mesh/mesh-io-api.h
> @@ -19,7 +19,7 @@
>  
>  struct mesh_io_private;
>  
> -typedef bool (*mesh_io_init_t)(uint16_t index, struct mesh_io *io);
> +typedef bool (*mesh_io_init_t)(struct mesh_io *io, void *opts);
>  typedef bool (*mesh_io_destroy_t)(struct mesh_io *io);
>  typedef bool (*mesh_io_caps_t)(struct mesh_io *io, struct mesh_io_caps *caps);
>  typedef bool (*mesh_io_send_t)(struct mesh_io *io,
> @@ -47,7 +47,6 @@ struct mesh_io_api {
>  
>  struct mesh_io {
>  	enum mesh_io_type		type;
> -	uint16_t			index;
>  	const struct mesh_io_api	*api;
>  	struct mesh_io_private		*pvt;
>  };
> diff --git a/mesh/mesh-io-generic.c b/mesh/mesh-io-generic.c
> index 756dceabc..5bfe40700 100644
> --- a/mesh/mesh-io-generic.c
> +++ b/mesh/mesh-io-generic.c
> @@ -26,6 +26,9 @@
>  
>  #include "monitor/bt.h"
>  #include "src/shared/hci.h"
> +#include "lib/bluetooth.h"
> +#include "lib/mgmt.h"
> +#include "src/shared/mgmt.h"
>  
>  #include "mesh/mesh-io.h"
>  #include "mesh/mesh-io-api.h"
> @@ -68,6 +71,19 @@ struct tx_pattern {
>  	uint8_t				len;
>  };
>  
> +struct read_info_req {
> +	int index;
> +	struct mesh_io *io;
> +};
> +
> +static struct l_queue *controllers;
> +static struct mgmt *mgmt_mesh;
> +
> +static bool simple_match(const void *a, const void *b)
> +{
> +	return a == b;
> +}
> +
>  static uint32_t get_instant(void)
>  {
>  	struct timeval tm;
> @@ -278,40 +294,179 @@ static void configure_hci(struct mesh_io_private *io)
>  				sizeof(cmd), hci_generic_callback, NULL, NULL);
>  }
>  
> -static bool dev_init(uint16_t index, struct mesh_io *io)
> +static bool hci_init(struct mesh_io *io)
>  {
> -	struct mesh_io_private *tmp;
> -
> -	if (!io || io->pvt)
> +	io->pvt->hci = bt_hci_new_user_channel(io->pvt->index);
> +	if (!io->pvt->hci) {
> +		l_error("Failed to start mesh io (hci %u)", io->pvt->index);
>  		return false;
> +	}
>  
> -	tmp = l_new(struct mesh_io_private, 1);
> +	configure_hci(io->pvt);
>  
> -	if (tmp == NULL)
> -		return false;
> +	bt_hci_register(io->pvt->hci, BT_HCI_EVT_LE_META_EVENT,
> +						event_callback, io, NULL);
>  
> -	tmp->rx_regs = l_queue_new();
> -	tmp->tx_pkts = l_queue_new();
> -	if (!tmp->rx_regs || !tmp->tx_pkts)
> -		goto fail;
> +	l_debug("Started mesh on hci %u", io->pvt->index);
> +	return true;
> +}
>  
> -	tmp->hci = bt_hci_new_user_channel(index);
> -	if (!tmp->hci)
> -		goto fail;
> +static void read_info_cb(uint8_t status, uint16_t length,
> +					const void *param, void *user_data)
> +{
> +	struct read_info_req *req = user_data;
> +	const struct mgmt_rp_read_info *rp = param;
> +	uint32_t current_settings, supported_settings;
>  
> -	configure_hci(tmp);
> +	l_debug("hci %u status 0x%02x", req->index, status);
>  
> -	bt_hci_register(tmp->hci, BT_HCI_EVT_LE_META_EVENT,
> -						event_callback, io, NULL);
> +	if (status != MGMT_STATUS_SUCCESS) {
> +		l_error("Failed to read info for hci index %u: %s (0x%02x)",
> +				req->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", req->index);
> +		return;
> +	}
> +
> +	if (!(supported_settings & MGMT_SETTING_LE)) {
> +		l_info("Controller hci %u does not support LE", req->index);
> +		return;
> +	}
> +
> +	if (req->io->pvt->index != MGMT_INDEX_NONE &&
> +					req->index != req->io->pvt->index) {
> +		l_debug("Ignore index %d", req->index);
> +		return;
> +	}
> +
> +	req->io->pvt->index = req->index;
> +	hci_init(req->io);
> +}
> +
> +static void index_added(uint16_t index, uint16_t length, const void *param,
> +							void *user_data)
> +{
> +	struct read_info_req *req;
> +	struct mesh_io *io = user_data;
> +
> +	if (io->pvt->index != MGMT_INDEX_NONE &&
> +					index != io->pvt->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));
> +
> +	req = l_new(struct read_info_req, 1);
> +	req->index = index;
> +	req->io = io;
> +
> +	if (mgmt_send(mgmt_mesh, MGMT_OP_READ_INFO, index, 0, NULL,
> +			read_info_cb, req, 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 mgmt_init(struct mesh_io *io)
> +{
> +	mgmt_mesh = mgmt_new_default();
> +	if (!mgmt_mesh) {
> +		l_error("Failed to initialize mesh management");
> +		return false;
> +	}
> +
> +	controllers = l_queue_new();
> +
> +	mgmt_register(mgmt_mesh, MGMT_EV_INDEX_ADDED, MGMT_INDEX_NONE,
> +						index_added, io, NULL);
> +	mgmt_register(mgmt_mesh, MGMT_EV_INDEX_REMOVED, MGMT_INDEX_NONE,
> +						index_removed, io, NULL);
> +
> +	/* Use MGMT to find a candidate controller */
> +	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, io, NULL) <= 0)
> +		return false;
>  
> -	io->pvt = tmp;
>  	return true;
> +}
> +
> +static bool dev_init(struct mesh_io *io, void *opts)
> +{
> +	if (!io || io->pvt)
> +		return false;
> +
> +	io->pvt = l_new(struct mesh_io_private, 1);
> +	io->pvt->index = *(int *)opts;
>  
> -fail:
> -	l_queue_destroy(tmp->rx_regs, l_free);
> -	l_queue_destroy(tmp->tx_pkts, l_free);
> -	l_free(tmp);
> -	return false;
> +	io->pvt->rx_regs = l_queue_new();
> +	io->pvt->tx_pkts = l_queue_new();
> +
> +	if (io->pvt->index == MGMT_INDEX_NONE)
> +		return mgmt_init(io);
> +	else
> +		return hci_init(io);
>  }
>  
>  static bool dev_destroy(struct mesh_io *io)
> @@ -327,6 +482,8 @@ static bool dev_destroy(struct mesh_io *io)
>  	l_queue_destroy(pvt->tx_pkts, l_free);
>  	l_free(pvt);
>  	io->pvt = NULL;
> +	l_queue_destroy(controllers, NULL);
> +	mgmt_unref(mgmt_mesh);

These are statics, so if they need to be totally destroyed, they should be set back to NULL afterwords.

>  
>  	return true;
>  }
> diff --git a/mesh/mesh-io.c b/mesh/mesh-io.c
> index 37153ea9d..b6ad2f995 100644
> --- a/mesh/mesh-io.c
> +++ b/mesh/mesh-io.c
> @@ -39,26 +39,26 @@ static const struct mesh_io_table table[] = {
>  
>  static struct l_queue *io_list;
>  
> +

Style Guide: remove extra blank line

>  static bool match_by_io(const void *a, const void *b)
>  {
>  	return a == b;
>  }
>  
> -static bool match_by_index(const void *a, const void *b)
> +static bool match_by_type(const void *a, const void *b)
>  {
>  	const struct mesh_io *io = a;
> +	const enum mesh_io_type *type = b;
>  
> -	return io->index == L_PTR_TO_UINT(b);
> +	return io->type == *type;
>  }

This is an irregular use of the "match_by" convention...

Try using something like:
enum mesh_io_type type = (enum mesh_io_type) L_PTR_TO_UINT(b);

return io->type == type.

Then below when it is used, pass the type as L_UINT_TO_PTR(type).  I am not certain it will work, but it should
be tried.


>  
> -struct mesh_io *mesh_io_new(uint16_t index, enum mesh_io_type type)
> +struct mesh_io *mesh_io_new(enum mesh_io_type type, void *opts)
>  {
>  	const struct mesh_io_api *api = NULL;
>  	struct mesh_io *io;
>  	uint16_t i;
>  
> -	l_info("%s %d\n", __func__, type);
> -
>  	for (i = 0; i < L_ARRAY_SIZE(table); i++) {
>  		if (table[i].type == type) {
>  			api = table[i].api;
> @@ -66,7 +66,8 @@ struct mesh_io *mesh_io_new(uint16_t index, enum mesh_io_type type)
>  		}
>  	}
>  
> -	io = l_queue_find(io_list, match_by_index, L_UINT_TO_PTR(index));
> +
> +	io = l_queue_find(io_list, match_by_type, &type);
>  
>  	if (!api || !api->init || io)
>  		return NULL;
> @@ -77,9 +78,9 @@ struct mesh_io *mesh_io_new(uint16_t index, enum mesh_io_type type)
>  		return NULL;
>  
>  	io->type = type;
> -	io->index = index;
> +
>  	io->api = api;
> -	if (!api->init(index, io))
> +	if (!api->init(io, opts))
>  		goto fail;
>  
>  	if (!io_list)
> diff --git a/mesh/mesh-io.h b/mesh/mesh-io.h
> index 71d3cb980..6585205c7 100644
> --- a/mesh/mesh-io.h
> +++ b/mesh/mesh-io.h
> @@ -80,7 +80,7 @@ typedef void (*mesh_io_recv_func_t)(void *user_data,
>  typedef void (*mesh_io_status_func_t)(void *user_data, int status,
>  							uint8_t filter_id);
>  
> -struct mesh_io *mesh_io_new(uint16_t index, enum mesh_io_type type);
> +struct mesh_io *mesh_io_new(enum mesh_io_type type, void *opts);
>  void mesh_io_destroy(struct mesh_io *io);
>  
>  bool mesh_io_get_caps(struct mesh_io *io, struct mesh_io_caps *caps);
> diff --git a/mesh/mesh.c b/mesh/mesh.c
> index 231a6bca4..26acfd4dc 100644
> --- a/mesh/mesh.c
> +++ b/mesh/mesh.c
> @@ -24,11 +24,6 @@
>  #define _GNU_SOURCE
>  #include <ell/ell.h>
>  
> -#include "lib/bluetooth.h"
> -#include "lib/mgmt.h"
> -
> -#include "src/shared/mgmt.h"
> -
>  #include "mesh/mesh-io.h"
>  #include "mesh/node.h"
>  #include "mesh/net.h"
> @@ -76,9 +71,6 @@ struct join_data{
>  };
>  
>  static struct bt_mesh mesh;
> -static struct l_queue *controllers;
> -static struct mgmt *mgmt_mesh;
> -static bool initialized;
>  
>  /* We allow only one outstanding Join request */
>  static struct join_data *join_pending;
> @@ -91,29 +83,6 @@ static bool simple_match(const void *a, const void *b)
>  	return a == b;
>  }
>  
> -static void start_io(uint16_t index)
> -{
> -	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);
> -		return;
> -	}
> -
> -	mesh_io_get_caps(io, &caps);
> -	mesh.max_filters = caps.max_num_filters;
> -
> -	mesh.io = io;
> -
> -	l_debug("Started mesh (io %p) on hci %u", mesh.io, index);
> -
> -	node_attach_io_all(io);
> -}
> -
>  /* Used for any outbound traffic that doesn't have Friendship Constraints */
>  /* This includes Beacons, Provisioning and unrestricted Network Traffic */
>  bool mesh_send_pkt(uint8_t count, uint16_t interval,
> @@ -167,143 +136,13 @@ void mesh_unreg_prov_rx(prov_rx_cb_t cb)
>  	mesh_io_deregister_recv_cb(mesh.io, MESH_IO_FILTER_PROV);
>  }
>  
> -static void read_info_cb(uint8_t status, uint16_t length,
> -					const void *param, void *user_data)
> +bool mesh_init(const char *config_dir, enum mesh_io_type type, void *opts)
>  {
> -	uint16_t index = L_PTR_TO_UINT(user_data);
> -	const struct mgmt_rp_read_info *rp = param;
> -	uint32_t current_settings, supported_settings;
> +	struct mesh_io_caps caps;
>  
>  	if (mesh.io)
> -		/* 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(index);
> -}
> -
> -static void index_added(uint16_t index, uint16_t length, const void *param,
> -							void *user_data)
> -{
> -	l_debug("hci device %u", index);
> -
> -	if (mesh.req_index != MGMT_INDEX_NONE &&
> -					index != mesh.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 init_mgmt(void)
> -{
> -	mgmt_mesh = mgmt_new_default();
> -	if (!mgmt_mesh)
> -		return false;
> -
> -	controllers = l_queue_new();
> -	if (!controllers)
> -		return false;
> -
> -	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);
> -	return true;
> -}
> -
> -bool mesh_init(uint16_t index, const char *config_dir)
> -{
> -	if (initialized)
>  		return true;
>  
> -	if (index == MGMT_INDEX_NONE && !init_mgmt()) {
> -		l_error("Failed to initialize mesh management");
> -		return false;
> -	}
> -
> -	mesh.req_index = index;
> -
>  	mesh_model_init();
>  	mesh_agent_init();
>  
> @@ -319,18 +158,16 @@ bool mesh_init(uint16_t index, const char *config_dir)
>  	if (!storage_load_nodes(config_dir))
>  		return false;
>  
> -	if (index == MGMT_INDEX_NONE) {
> -		/* Use MGMT to find a candidate controller */
> -		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, NULL, NULL) <= 0)
> -			return false;
> -	} else {
> -		/* Open specified controller without searching */
> -		start_io(mesh.req_index);
> -		return mesh.io != NULL;
> -	}
> +	mesh.io = mesh_io_new(type, opts);
> +	if (!mesh.io)
> +		return false;
> +
> +	l_debug("io %p", mesh.io);
> +	mesh_io_get_caps(mesh.io, &caps);
> +	mesh.max_filters = caps.max_num_filters;
> +
> +	node_attach_io_all(mesh.io);
> +
>  	return true;
>  }
>  
> @@ -366,7 +203,6 @@ void mesh_cleanup(void)
>  	struct l_dbus_message *reply;
>  
>  	mesh_io_destroy(mesh.io);
> -	mgmt_unref(mgmt_mesh);
>  
>  	if (join_pending) {
>  
> @@ -384,7 +220,6 @@ void mesh_cleanup(void)
>  	node_cleanup_all();
>  	mesh_model_cleanup();
>  
> -	l_queue_destroy(controllers, NULL);
>  	l_dbus_object_remove_interface(dbus_get_bus(), BLUEZ_MESH_PATH,
>  							MESH_NETWORK_INTERFACE);
>  	l_dbus_unregister_interface(dbus_get_bus(), MESH_NETWORK_INTERFACE);
> diff --git a/mesh/mesh.h b/mesh/mesh.h
> index 320a108ed..14b1fb517 100644
> --- a/mesh/mesh.h
> +++ b/mesh/mesh.h
> @@ -28,9 +28,11 @@
>  #define MESH_PROVISIONER_INTERFACE "org.bluez.mesh.Provisioner1"
>  #define ERROR_INTERFACE "org.bluez.mesh.Error"
>  
> +enum mesh_io_type;
> +
>  typedef void (*prov_rx_cb_t)(void *user_data, const uint8_t *data,
>  								uint16_t len);
> -bool mesh_init(uint16_t index, const char *in_config_name);
> +bool mesh_init(const char *in_config_name, enum mesh_io_type type, void *opts);
>  void mesh_cleanup(void);
>  bool mesh_dbus_init(struct l_dbus *dbus);
>  


Otherwise, I like it a lot....  Make sure it continues to work:
1. On platforms with multiple controllers, with the -i hciX option bypassing the MGMT calls
2. On platforms with multiple controllers without the -i, where MGMT interface picks one
3. On single and Zero controller systems with both cases 1 and 2 above.

Best Regards, 
Brian




[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