Re: [PATCH BlueZ] mesh: Fix io inititalization sequence

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

 



Applied, Thanks

On Thu, 2019-11-14 at 15:52 -0800, Inga Stotland wrote:
> This introduces a chain of callbacks to indicate whether mesh io
> is initialized and mesh network is ready to use.
> 
> This fixes the reported situation when the receive callbacks
> were setup before the HCI was fully initialized. In other words,
> BT_HCI_CMD_LE_SET_SCAN_PARAMETERS was called before BT_HCI_CMD_RESET
> and, as the result, the callback issueing BT_HCI_CMD_LE_SET_SCAN_ENABLE
> command was not called.
> ---
>  mesh/main.c            | 42 ++++++++++++++++++++++++------------
>  mesh/mesh-io-api.h     |  3 ++-
>  mesh/mesh-io-generic.c | 48 +++++++++++++++++++++++++++++++-----------
>  mesh/mesh-io.c         |  5 +++--
>  mesh/mesh-io.h         |  6 +++++-
>  mesh/mesh.c            | 33 ++++++++++++++++++++++++-----
>  mesh/mesh.h            |  5 ++++-
>  7 files changed, 107 insertions(+), 35 deletions(-)
> 
> diff --git a/mesh/main.c b/mesh/main.c
> index 6ea210c48..3c41acb75 100644
> --- a/mesh/main.c
> +++ b/mesh/main.c
> @@ -38,6 +38,9 @@
>  #include "mesh/dbus.h"
>  #include "mesh/mesh-io.h"
>  
> +static const char *config_dir;
> +static int ctlr_index = MGMT_INDEX_NONE;
> +
>  static const struct option main_options[] = {
>  	{ "index",	required_argument,	NULL, 'i' },
>  	{ "config",	optional_argument,	NULL, 'c' },
> @@ -69,16 +72,38 @@ static void do_debug(const char *str, void *user_data)
>  	l_info("%s%s", prefix, str);
>  }
>  
> +static void mesh_ready_callback(void *user_data, bool success)
> +{
> +	struct l_dbus *dbus = user_data;
> +
> +	if (!success) {
> +		l_error("Failed to start mesh");
> +		l_main_quit();
> +		return;
> +	}
> +
> +	if (!dbus_init(dbus)) {
> +		l_error("Failed to initialize mesh D-Bus resources");
> +		l_main_quit();
> +	}
> +}
> +
>  static void request_name_callback(struct l_dbus *dbus, bool success,
>  					bool queued, void *user_data)
>  {
>  	l_info("Request name %s",
>  		success ? "success": "failed");
>  
> -	if (success)
> -		dbus_init(dbus);
> -	else
> +	if (!success) {
>  		l_main_quit();
> +		return;
> +	}
> +
> +	if (!mesh_init(config_dir, MESH_IO_TYPE_GENERIC, &ctlr_index,
> +					mesh_ready_callback, dbus)) {
> +		l_error("Failed to initialize mesh");
> +		l_main_quit();
> +	}
>  }
>  
>  static void ready_callback(void *user_data)
> @@ -88,7 +113,6 @@ static void ready_callback(void *user_data)
>  	l_info("D-Bus ready");
>  	l_dbus_name_acquire(dbus, BLUEZ_MESH_NAME, false, false, false,
>  						request_name_callback, NULL);
> -
>  }
>  
>  static void disconnect_callback(void *user_data)
> @@ -114,8 +138,6 @@ int main(int argc, char *argv[])
>  	bool detached = true;
>  	bool dbus_debug = false;
>  	struct l_dbus *dbus = NULL;
> -	const char *config_dir = NULL;
> -	int index = MGMT_INDEX_NONE;
>  
>  	if (!l_main_init())
>  		return -1;
> @@ -148,7 +170,7 @@ int main(int argc, char *argv[])
>  				goto done;
>  			}
>  
> -			index = atoi(str);
> +			ctlr_index = atoi(str);
>  
>  			break;
>  		case 'n':
> @@ -175,12 +197,6 @@ int main(int argc, char *argv[])
>  	}
>  
>  
> -	if (!mesh_init(config_dir, MESH_IO_TYPE_GENERIC, &index)) {
> -		l_error("Failed to initialize mesh");
> -		status = EXIT_FAILURE;
> -		goto done;
> -	}
> -
>  	if (!detached)
>  		umask(0077);
>  
> diff --git a/mesh/mesh-io-api.h b/mesh/mesh-io-api.h
> index 4cdf1f80a..75b881800 100644
> --- a/mesh/mesh-io-api.h
> +++ b/mesh/mesh-io-api.h
> @@ -19,7 +19,8 @@
>  
>  struct mesh_io_private;
>  
> -typedef bool (*mesh_io_init_t)(struct mesh_io *io, void *opts);
> +typedef bool (*mesh_io_init_t)(struct mesh_io *io, void *opts,
> +				mesh_io_ready_func_t cb, void *user_data);
>  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,
> diff --git a/mesh/mesh-io-generic.c b/mesh/mesh-io-generic.c
> index 42bf64a0b..b42fb4f1d 100644
> --- a/mesh/mesh-io-generic.c
> +++ b/mesh/mesh-io-generic.c
> @@ -37,14 +37,16 @@
>  #include "mesh/mesh-io-generic.h"
>  
>  struct mesh_io_private {
> -	uint16_t index;
>  	struct bt_hci *hci;
> +	void *user_data;
> +	mesh_io_ready_func_t ready_callback;
>  	struct l_timeout *tx_timeout;
>  	struct l_queue *rx_regs;
>  	struct l_queue *tx_pkts;
> +	struct tx_pkt *tx;
>  	uint8_t filters[4];
>  	bool sending;
> -	struct tx_pkt *tx;
> +	uint16_t index;
>  	uint16_t interval;
>  };
>  
> @@ -283,22 +285,29 @@ static void configure_hci(struct mesh_io_private *io)
>  				sizeof(cmd), hci_generic_callback, NULL, NULL);
>  }
>  
> -static bool hci_init(struct mesh_io *io)
> +static void hci_init(void *user_data)
>  {
> +	struct mesh_io *io = user_data;
> +	bool result = true;
> +
>  	io->pvt->hci = bt_hci_new_user_channel(io->pvt->index);
>  	if (!io->pvt->hci) {
>  		l_error("Failed to start mesh io (hci %u): %s", io->pvt->index,
>  							strerror(errno));
> -		return false;
> +		result = false;
>  	}
>  
> -	configure_hci(io->pvt);
> +	if (result) {
> +		configure_hci(io->pvt);
>  
> -	bt_hci_register(io->pvt->hci, BT_HCI_EVT_LE_META_EVENT,
> +		bt_hci_register(io->pvt->hci, BT_HCI_EVT_LE_META_EVENT,
>  						event_callback, io, NULL);
>  
> -	l_debug("Started mesh on hci %u", io->pvt->index);
> -	return true;
> +		l_debug("Started mesh on hci %u", io->pvt->index);
> +	}
> +
> +	if (io->pvt->ready_callback)
> +		io->pvt->ready_callback(io->pvt->user_data, result);
>  }
>  
>  static void read_info(int index, void *user_data)
> @@ -315,7 +324,8 @@ static void read_info(int index, void *user_data)
>  	hci_init(io);
>  }
>  
> -static bool dev_init(struct mesh_io *io, void *opts)
> +static bool dev_init(struct mesh_io *io, void *opts,
> +				mesh_io_ready_func_t cb, void *user_data)
>  {
>  	if (!io || io->pvt)
>  		return false;
> @@ -326,10 +336,15 @@ static bool dev_init(struct mesh_io *io, void *opts)
>  	io->pvt->rx_regs = l_queue_new();
>  	io->pvt->tx_pkts = l_queue_new();
>  
> +	io->pvt->ready_callback = cb;
> +	io->pvt->user_data = user_data;
> +
>  	if (io->pvt->index == MGMT_INDEX_NONE)
>  		return mesh_mgmt_list(read_info, io);
> -	else
> -		return hci_init(io);
> +
> +	l_idle_oneshot(hci_init, io, NULL);
> +
> +	return true;
>  }
>  
>  static bool dev_destroy(struct mesh_io *io)
> @@ -696,6 +711,15 @@ static bool find_by_filter_id(const void *a, const void *b)
>  	return rx_reg->filter_id == filter_id;
>  }
>  
> +static void scan_enable_rsp(const void *buf, uint8_t size,
> +							void *user_data)
> +{
> +	uint8_t status = *((uint8_t *) buf);
> +
> +	if (status)
> +		l_error("LE Scan enable failed (0x%02x)", status);
> +}
> +
>  static void set_recv_scan_enable(const void *buf, uint8_t size,
>  							void *user_data)
>  {
> @@ -705,7 +729,7 @@ static void set_recv_scan_enable(const void *buf, uint8_t size,
>  	cmd.enable = 0x01;	/* Enable scanning */
>  	cmd.filter_dup = 0x00;	/* Report duplicates */
>  	bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_SCAN_ENABLE,
> -			&cmd, sizeof(cmd), NULL, NULL, NULL);
> +			&cmd, sizeof(cmd), scan_enable_rsp, pvt, NULL);
>  }
>  
>  static bool recv_register(struct mesh_io *io, uint8_t filter_id,
> diff --git a/mesh/mesh-io.c b/mesh/mesh-io.c
> index 94a92e885..95a99b6a5 100644
> --- a/mesh/mesh-io.c
> +++ b/mesh/mesh-io.c
> @@ -52,7 +52,8 @@ static bool match_by_type(const void *a, const void *b)
>  	return io->type == type;
>  }
>  
> -struct mesh_io *mesh_io_new(enum mesh_io_type type, void *opts)
> +struct mesh_io *mesh_io_new(enum mesh_io_type type, void *opts,
> +				mesh_io_ready_func_t cb, void *user_data)
>  {
>  	const struct mesh_io_api *api = NULL;
>  	struct mesh_io *io;
> @@ -78,7 +79,7 @@ struct mesh_io *mesh_io_new(enum mesh_io_type type, void *opts)
>  	io->type = type;
>  
>  	io->api = api;
> -	if (!api->init(io, opts))
> +	if (!api->init(io, opts, cb, user_data))
>  		goto fail;
>  
>  	if (!io_list)
> diff --git a/mesh/mesh-io.h b/mesh/mesh-io.h
> index 1c10779aa..45ff00a3c 100644
> --- a/mesh/mesh-io.h
> +++ b/mesh/mesh-io.h
> @@ -81,7 +81,11 @@ 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(enum mesh_io_type type, void *opts);
> +typedef void (*mesh_io_ready_func_t)(void *user_data, bool result);
> +
> +
> +struct mesh_io *mesh_io_new(enum mesh_io_type type, void *opts,
> +				mesh_io_ready_func_t cb, void *user_data);
>  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 9b2b2073b..55204da56 100644
> --- a/mesh/mesh.c
> +++ b/mesh/mesh.c
> @@ -70,6 +70,11 @@ struct join_data{
>  	uint8_t *uuid;
>  };
>  
> +struct mesh_init_request {
> +	mesh_ready_func_t cb;
> +	void *user_data;
> +};
> +
>  static struct bt_mesh mesh;
>  
>  /* We allow only one outstanding Join request */
> @@ -138,9 +143,23 @@ void mesh_unreg_prov_rx(prov_rx_cb_t cb)
>  	mesh_io_deregister_recv_cb(mesh.io, MESH_IO_FILTER_PROV);
>  }
>  
> -bool mesh_init(const char *config_dir, enum mesh_io_type type, void *opts)
> +static void io_ready_callback(void *user_data, bool result)
> +{
> +	struct mesh_init_request *req = user_data;
> +
> +	if (result)
> +		node_attach_io_all(mesh.io);
> +
> +	req->cb(req->user_data, result);
> +
> +	l_free(req);
> +}
> +
> +bool mesh_init(const char *config_dir, enum mesh_io_type type, void *opts,
> +					mesh_ready_func_t cb, void *user_data)
>  {
>  	struct mesh_io_caps caps;
> +	struct mesh_init_request *req;
>  
>  	if (mesh.io)
>  		return true;
> @@ -159,16 +178,20 @@ bool mesh_init(const char *config_dir, enum mesh_io_type type, void *opts)
>  	if (!node_load_from_storage(storage_dir))
>  		return false;
>  
> -	mesh.io = mesh_io_new(type, opts);
> -	if (!mesh.io)
> +	req = l_new(struct mesh_init_request, 1);
> +	req->cb = cb;
> +	req->user_data = user_data;
> +
> +	mesh.io = mesh_io_new(type, opts, io_ready_callback, req);
> +	if (!mesh.io) {
> +		l_free(req);
>  		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;
>  }
>  
> diff --git a/mesh/mesh.h b/mesh/mesh.h
> index e0a3e1b96..c72632b15 100644
> --- a/mesh/mesh.h
> +++ b/mesh/mesh.h
> @@ -30,9 +30,12 @@
>  
>  enum mesh_io_type;
>  
> +typedef void (*mesh_ready_func_t)(void *user_data, bool success);
>  typedef void (*prov_rx_cb_t)(void *user_data, const uint8_t *data,
>  								uint16_t len);
> -bool mesh_init(const char *in_config_name, enum mesh_io_type type, void *opts);
> +
> +bool mesh_init(const char *in_config_name, enum mesh_io_type type, void *opts,
> +					mesh_ready_func_t cb, void *user_data);
>  void mesh_cleanup(void);
>  bool mesh_dbus_init(struct l_dbus *dbus);
>  




[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