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)