mesh: Move HCI handling to mesh-io-generic
authorMichał Lowas-Rzechonek <michal.lowas-rzechonek@silvair.com>
Mon, 24 Jun 2019 07:32:28 +0000 (09:32 +0200)
committerAnupam Roy <anupam.r@samsung.com>
Tue, 17 Dec 2019 15:12:04 +0000 (20:42 +0530)
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.

MGMT code is now extracted into mesh-mgmt module, which mesh-io-generic
uses to query interfaces.

Change-Id: I698752859bc7c1218410e83fc1a04a381539984b
Signed-off-by: Anupam Roy <anupam.r@samsung.com>
Makefile.mesh
mesh/main.c
mesh/mesh-io-api.h
mesh/mesh-io-generic.c
mesh/mesh-io.c
mesh/mesh-io.h
mesh/mesh-mgmt.c [new file with mode: 0644]
mesh/mesh-mgmt.h [new file with mode: 0644]
mesh/mesh.c
mesh/mesh.h

index b05fd70..d96c4f4 100644 (file)
@@ -12,6 +12,7 @@ endif
 mesh_sources = mesh/mesh.h mesh/mesh.c \
                                mesh/net-keys.h mesh/net-keys.c \
                                mesh/mesh-io.h mesh/mesh-io.c \
+                               mesh/mesh-mgmt.c mesh/mesh-mgmt.h \
                                mesh/error.h mesh/mesh-io-api.h \
                                mesh/mesh-io-generic.h \
                                mesh/mesh-io-generic.c \
index e233a5b..6854e5d 100644 (file)
@@ -34,6 +34,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' },
@@ -165,7 +166,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;
index acf1244..4cdf1f8 100644 (file)
@@ -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;
 };
index 756dcea..42aaa09 100644 (file)
 
 #include "monitor/bt.h"
 #include "src/shared/hci.h"
+#include "lib/bluetooth.h"
+#include "lib/mgmt.h"
 
+#include "mesh/mesh-mgmt.h"
 #include "mesh/mesh-io.h"
 #include "mesh/mesh-io-api.h"
 #include "mesh/mesh-io-generic.h"
@@ -278,40 +281,52 @@ 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);
+
+       l_debug("Started mesh on hci %u", io->pvt->index);
+       return true;
+}
+
+static void read_info(int index, void *user_data)
+{
+       struct mesh_io *io = user_data;
 
-       tmp->rx_regs = l_queue_new();
-       tmp->tx_pkts = l_queue_new();
-       if (!tmp->rx_regs || !tmp->tx_pkts)
-               goto fail;
+       if (io->pvt->index != MGMT_INDEX_NONE &&
+                                       index != io->pvt->index) {
+               l_debug("Ignore index %d", index);
+               return;
+       }
 
-       tmp->hci = bt_hci_new_user_channel(index);
-       if (!tmp->hci)
-               goto fail;
+       io->pvt->index = index;
+       hci_init(io);
+}
 
-       configure_hci(tmp);
+static bool dev_init(struct mesh_io *io, void *opts)
+{
+       if (!io || io->pvt)
+               return false;
 
-       bt_hci_register(tmp->hci, BT_HCI_EVT_LE_META_EVENT,
-                                               event_callback, io, NULL);
+       io->pvt = l_new(struct mesh_io_private, 1);
+       io->pvt->index = *(int *)opts;
 
-       io->pvt = tmp;
-       return true;
+       io->pvt->rx_regs = l_queue_new();
+       io->pvt->tx_pkts = l_queue_new();
 
-fail:
-       l_queue_destroy(tmp->rx_regs, l_free);
-       l_queue_destroy(tmp->tx_pkts, l_free);
-       l_free(tmp);
-       return false;
+       if (io->pvt->index == MGMT_INDEX_NONE)
+               return mesh_mgmt_list(read_info, io);
+       else
+               return hci_init(io);
 }
 
 static bool dev_destroy(struct mesh_io *io)
index 37153ea..62a8c0e 100644 (file)
@@ -44,21 +44,20 @@ 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 = L_PTR_TO_UINT(b);
 
-       return io->index == L_PTR_TO_UINT(b);
+       return io->type == type;
 }
 
-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 +65,7 @@ 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, L_UINT_TO_PTR(type));
 
        if (!api || !api->init || io)
                return NULL;
@@ -77,9 +76,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)
index 71d3cb9..6585205 100644 (file)
@@ -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-mgmt.c b/mesh/mesh-mgmt.c
new file mode 100644 (file)
index 0000000..27272d4
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2019  SILVAIR sp. z o.o. All rights reserved.
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "lib/bluetooth.h"
+#include "lib/mgmt.h"
+#include "src/shared/mgmt.h"
+
+#include "ell/queue.h"
+#include "ell/log.h"
+#include "ell/util.h"
+
+#include "mesh/mesh-mgmt.h"
+
+struct read_info_reg {
+       mesh_mgmt_read_info_func_t cb;
+       void *user_data;
+};
+
+struct read_info_req {
+       int index;
+       struct mesh_io *io;
+};
+
+static struct mgmt *mgmt_mesh;
+static struct l_queue *controllers;
+static struct l_queue *read_info_regs;
+
+static bool simple_match(const void *a, const void *b)
+{
+       return a == b;
+}
+
+static void process_read_info_req(void *data, void *user_data)
+{
+       struct read_info_reg *reg = data;
+       int index = L_PTR_TO_UINT(user_data);
+
+       reg->cb(index, reg->user_data);
+}
+
+static void read_info_cb(uint8_t status, uint16_t length,
+                                       const void *param, void *user_data)
+{
+       int index = L_PTR_TO_UINT(user_data);
+       const struct mgmt_rp_read_info *rp = param;
+       uint32_t current_settings, supported_settings;
+
+       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;
+       }
+
+       l_queue_foreach(read_info_regs, process_read_info_req,
+                                                       L_UINT_TO_PTR(index));
+}
+
+static void index_added(uint16_t index, uint16_t length, const void *param,
+                                                       void *user_data)
+{
+       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 mesh_mgmt_init(void)
+{
+       if (!controllers)
+               controllers = l_queue_new();
+
+       if (!read_info_regs)
+               read_info_regs = l_queue_new();
+
+       if (!mgmt_mesh) {
+               mgmt_mesh = mgmt_new_default();
+
+               if (!mgmt_mesh) {
+                       l_error("Failed to initialize mesh management");
+                       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_mgmt_list(mesh_mgmt_read_info_func_t cb, void *user_data)
+{
+       struct read_info_reg *reg;
+
+       if (!mesh_mgmt_init())
+               return false;
+
+       reg = l_new(struct read_info_reg, 1);
+       reg->cb = cb;
+       reg->user_data = user_data;
+
+       l_queue_push_tail(read_info_regs, reg);
+
+       /* 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;
+
+       return true;
+}
diff --git a/mesh/mesh-mgmt.h b/mesh/mesh-mgmt.h
new file mode 100644 (file)
index 0000000..93ad799
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2019  SILVAIR sp. z o.o. All rights reserved.
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ */
+#include <stdbool.h>
+
+typedef void (*mesh_mgmt_read_info_func_t)(int index, void *user_data);
+
+bool mesh_mgmt_list(mesh_mgmt_read_info_func_t cb, void *user_data);
index 09afe30..15ef54c 100644 (file)
 
 #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"
@@ -75,9 +70,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;
@@ -90,29 +82,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,
@@ -166,143 +135,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();
 
@@ -318,18 +157,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;
 }
 
@@ -365,7 +202,6 @@ void mesh_cleanup(void)
        struct l_dbus_message *reply;
 
        mesh_io_destroy(mesh.io);
-       mgmt_unref(mgmt_mesh);
 
        if (join_pending) {
 
@@ -383,7 +219,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);
index 320a108..14b1fb5 100644 (file)
 #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);