This allows specifying io type and options when invoking the daemon. By default, meshd runs with MESH_IO_TYPE_GENERIC and tries to attach to the first available HCI interface. Option "--index=<n>" is now just a shortcut for "--io=generic:<n>" --- mesh/main.c | 48 +++++++++++++++++++++++++++--------------- mesh/mesh-io-api.h | 2 ++ mesh/mesh-io-generic.c | 30 ++++++++++++++++++++++++++ mesh/mesh-io.c | 9 ++++++-- mesh/mesh-io.h | 2 +- mesh/mesh.c | 4 ++-- mesh/mesh.h | 2 +- 7 files changed, 74 insertions(+), 23 deletions(-) diff --git a/mesh/main.c b/mesh/main.c index 262e3da48..7adb0c2d2 100644 --- a/mesh/main.c +++ b/mesh/main.c @@ -39,6 +39,7 @@ static const struct option main_options[] = { { "index", required_argument, NULL, 'i' }, + { "io", required_argument, NULL, 'I' }, { "config", optional_argument, NULL, 'c' }, { "nodetach", no_argument, NULL, 'n' }, { "debug", no_argument, NULL, 'd' }, @@ -49,16 +50,23 @@ static const struct option main_options[] = { static void usage(void) { - l_info(""); - l_info("Usage:\n" + fprintf(stderr, + "Usage:\n" "\tbluetooth-meshd [options]\n"); - l_info("Options:\n" - "\t--index <hcinum> Use specified controller\n" + fprintf(stderr, + "Options:\n" + "\t--index <hcinum> Equivalent of `--io=generic:<hcinum>`\n" + "\t--io <io> Use specified io (default: generic)\n" "\t--config Configuration directory\n" "\t--nodetach Run in foreground\n" "\t--debug Enable debug output\n" "\t--dbus-debug Enable D-Bus debugging\n" "\t--help Show %s information\n", __func__); + fprintf(stderr, + "io:\n" + "\tgeneric[:<index>]\n" + "\t\tUse generic HCI io on interface hci<index>, or the first\n" + "\t\tavailable one\n"); } static void do_debug(const char *str, void *user_data) @@ -114,7 +122,7 @@ int main(int argc, char *argv[]) bool dbus_debug = false; struct l_dbus *dbus = NULL; const char *config_dir = NULL; - int index = MGMT_INDEX_NONE; + char *ioarg = NULL; if (!l_main_init()) return -1; @@ -123,7 +131,6 @@ int main(int argc, char *argv[]) for (;;) { int opt; - const char *str; opt = getopt_long(argc, argv, "i:c:ndbh", main_options, NULL); if (opt < 0) @@ -131,18 +138,20 @@ int main(int argc, char *argv[]) switch (opt) { case 'i': - if (strlen(optarg) > 3 && !strncmp(optarg, "hci", 3)) - str = optarg + 3; - else - str = optarg; - if (!isdigit(*str)) { - l_error("Invalid controller index value"); - status = EXIT_FAILURE; + if (ioarg) { + l_error("Use either --index or --io, not both"); + status = EXIT_SUCCESS; goto done; } - - index = atoi(str); - + ioarg = l_strdup_printf("generic:%s", optarg); + break; + case 'I': + if (ioarg) { + l_error("Use either --index or --io, not both"); + status = EXIT_SUCCESS; + goto done; + } + ioarg = l_strdup(optarg); break; case 'n': detached = false; @@ -167,8 +176,10 @@ int main(int argc, char *argv[]) } } + if (!ioarg) + ioarg = l_strdup("generic"); - if (!mesh_init(config_dir, MESH_IO_TYPE_GENERIC, &index)) { + if (!mesh_init(config_dir, ioarg)) { l_error("Failed to initialize mesh"); status = EXIT_FAILURE; goto done; @@ -198,6 +209,9 @@ int main(int argc, char *argv[]) status = l_main_run_with_signal(signal_handler, NULL); done: + if (ioarg) + l_free(ioarg); + mesh_cleanup(); l_dbus_destroy(dbus); l_main_exit(); diff --git a/mesh/mesh-io-api.h b/mesh/mesh-io-api.h index 4cdf1f80a..b7807da53 100644 --- a/mesh/mesh-io-api.h +++ b/mesh/mesh-io-api.h @@ -19,6 +19,7 @@ struct mesh_io_private; +typedef void *(*mesh_io_opts_t)(const char *optarg); 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); @@ -35,6 +36,7 @@ typedef bool (*mesh_io_tx_cancel_t)(struct mesh_io *io, const uint8_t *pattern, uint8_t len); struct mesh_io_api { + mesh_io_opts_t opts; mesh_io_init_t init; mesh_io_destroy_t destroy; mesh_io_caps_t caps; diff --git a/mesh/mesh-io-generic.c b/mesh/mesh-io-generic.c index 42aaa0947..47d0de247 100644 --- a/mesh/mesh-io-generic.c +++ b/mesh/mesh-io-generic.c @@ -312,6 +312,35 @@ static void read_info(int index, void *user_data) hci_init(io); } +static void *dev_opts(const char *optarg) +{ + int *index = l_new(int, 1); + + if (strstr(optarg, "generic") != optarg) + goto fail; + + optarg += strlen("generic"); + if (!*optarg) { + *index = MGMT_INDEX_NONE; + return index; + } + + if (*optarg != ':') + goto fail; + + optarg++; + + if ((sscanf(optarg, "hci%d", index) != 1) && + (sscanf(optarg, "%d", index) != 1)) { + goto fail; + } + + return index; +fail: + l_free(index); + return NULL; +} + static bool dev_init(struct mesh_io *io, void *opts) { if (!io || io->pvt) @@ -783,6 +812,7 @@ static bool filter_set(struct mesh_io *io, } const struct mesh_io_api mesh_io_generic = { + .opts = dev_opts, .init = dev_init, .destroy = dev_destroy, .caps = dev_caps, diff --git a/mesh/mesh-io.c b/mesh/mesh-io.c index 62a8c0e2c..32acd9c2c 100644 --- a/mesh/mesh-io.c +++ b/mesh/mesh-io.c @@ -52,15 +52,20 @@ 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(const char *optarg) { const struct mesh_io_api *api = NULL; + enum mesh_io_type type = MESH_IO_TYPE_NONE; struct mesh_io *io; + void *opts; uint16_t i; for (i = 0; i < L_ARRAY_SIZE(table); i++) { - if (table[i].type == type) { + opts = table[i].api->opts(optarg); + + if (opts) { api = table[i].api; + type = table[i].type; break; } } diff --git a/mesh/mesh-io.h b/mesh/mesh-io.h index 6585205c7..0c367acb7 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(enum mesh_io_type type, void *opts); +struct mesh_io *mesh_io_new(const char *optarg); 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 26acfd4dc..31295d9c6 100644 --- a/mesh/mesh.c +++ b/mesh/mesh.c @@ -136,7 +136,7 @@ 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) +bool mesh_init(const char *config_dir, const char *optarg) { struct mesh_io_caps caps; @@ -158,7 +158,7 @@ bool mesh_init(const char *config_dir, enum mesh_io_type type, void *opts) if (!storage_load_nodes(config_dir)) return false; - mesh.io = mesh_io_new(type, opts); + mesh.io = mesh_io_new(optarg); if (!mesh.io) return false; diff --git a/mesh/mesh.h b/mesh/mesh.h index 14b1fb517..4df0615fc 100644 --- a/mesh/mesh.h +++ b/mesh/mesh.h @@ -32,7 +32,7 @@ enum mesh_io_type; 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 *config_dir, const char *optarg); void mesh_cleanup(void); bool mesh_dbus_init(struct l_dbus *dbus); -- 2.22.0