]> sigrok.org Git - sigrok-cli.git/commitdiff
accept multiple --config requests for multiple channel groups
authorGerhard Sittig <redacted>
Sat, 23 May 2020 11:10:14 +0000 (13:10 +0200)
committerGerhard Sittig <redacted>
Mon, 3 Aug 2020 20:26:11 +0000 (22:26 +0200)
The previous UI implementation supported the selection of a channel
group, and defaulted to the device's global options. This let users
either manipulate global or a single channel group's parmeters.

Extend the user interface. Accept multiple -c specs. Apply the remaining
key-value pairs to the channel group which optionally can get specified
in the first item of a -c spec. This lets users modify several channel
groups' parameters in a single program invocation, including arbitrary
combinations including the device's global parameters.

This extension is completely backwards compatible. When a -c spec lacks
a 'channel_group=' item, then the -g spec is used, which defaults to the
global parameters.

Either an empty string or the 'global' literal can be used to select the
global parameters. Several -c specs can select the same channel group.
This can be useful when command lines get generated by other programs.

device.c
main.c
options.c
session.c
show.c
sigrok-cli.h

index 141e3cfd2c9edb35887c02a0a2ff3acb891c4f2c..7da744431154c134b5bee897bc24f817cc774e46 100644 (file)
--- a/device.c
+++ b/device.c
@@ -66,22 +66,31 @@ GSList *device_scan(void)
 /**
  * Lookup a channel group from its name.
  *
- * Uses the previously stored option value to lookup a channel group.
- * Returns a reference to the channel group when the lookup succeeded,
- * or #NULL after lookup failure, or #NULL for the global channel group
- * (the device's global parameters). Emits an error message when the
- * lookup failed while a channel group's name was specified.
+ * Uses the caller specified channel group name, or a previously stored
+ * option value as a fallback. Returns a reference to the channel group
+ * when the lookup succeeded, or #NULL after lookup failure, as well as
+ * #NULL for the global channel group (the device).
+ *
+ * Accepts either #NULL pointer, or an empty string, or the "global"
+ * literal to address the global channel group (the device). Emits an
+ * error message when the lookup failed while a name was specified.
  *
  * @param[in] sdi Device instance.
+ * @param[in] cg_name Caller provided channel group name.
  *
  * @returns The channel group, or #NULL for failed lookup.
  */
-struct sr_channel_group *lookup_channel_group(struct sr_dev_inst *sdi)
+struct sr_channel_group *lookup_channel_group(struct sr_dev_inst *sdi,
+       const char *cg_name)
 {
        struct sr_channel_group *cg;
        GSList *l, *channel_groups;
 
-       if (!opt_channel_group)
+       if (!cg_name)
+               cg_name = opt_channel_group;
+       if (cg_name && g_ascii_strcasecmp(cg_name, "global") == 0)
+               cg_name = NULL;
+       if (!cg_name || !*cg_name)
                return NULL;
 
        channel_groups = sr_dev_inst_channel_groups_get(sdi);
@@ -92,11 +101,11 @@ struct sr_channel_group *lookup_channel_group(struct sr_dev_inst *sdi)
 
        for (l = channel_groups; l; l = l->next) {
                cg = l->data;
-               if (g_ascii_strcasecmp(opt_channel_group, cg->name) != 0)
+               if (g_ascii_strcasecmp(cg_name, cg->name) != 0)
                        continue;
                return cg;
        }
-       g_critical("Invalid channel group '%s'", opt_channel_group);
+       g_critical("Invalid channel group '%s'", cg_name);
 
        return NULL;
 }
diff --git a/main.c b/main.c
index db2bdc016df58f86eef252345f02b667b6c3316d..1de4b16e8ea0adbaeff9a2e2aebde7daeb1570e5 100644 (file)
--- a/main.c
+++ b/main.c
@@ -113,7 +113,6 @@ static void get_option(void)
        const struct sr_key_info *ci;
        GSList *devices;
        GVariant *gvar;
-       GHashTable *devargs;
        int ret;
        char *s;
        struct sr_dev_driver *driver;
@@ -136,14 +135,11 @@ static void get_option(void)
                return;
        }
 
-       cg = lookup_channel_group(sdi);
+       cg = lookup_channel_group(sdi, NULL);
        if (!(ci = sr_key_info_name_get(SR_KEY_CONFIG, opt_get)))
                g_critical("Unknown option '%s'", opt_get);
 
-       if ((devargs = parse_generic_arg(opt_config, FALSE, NULL)))
-               set_dev_options(sdi, devargs);
-       else
-               devargs = NULL;
+       set_dev_options_array(sdi, opt_configs);
 
        if ((ret = maybe_config_get(driver, sdi, cg, ci->key, &gvar)) != SR_OK)
                g_critical("Failed to get '%s': %s", opt_get, sr_strerror(ret));
@@ -171,24 +167,18 @@ static void get_option(void)
 
        g_variant_unref(gvar);
        sr_dev_close(sdi);
-       if (devargs)
-               g_hash_table_destroy(devargs);
 }
 
 static void set_options(void)
 {
        struct sr_dev_inst *sdi;
        GSList *devices;
-       GHashTable *devargs;
 
-       if (!opt_config) {
+       if (!opt_configs) {
                g_critical("No setting specified.");
                return;
        }
 
-       if (!(devargs = parse_generic_arg(opt_config, FALSE, NULL)))
-               return;
-
        if (!(devices = device_scan())) {
                g_critical("No devices found.");
                return;
@@ -201,11 +191,9 @@ static void set_options(void)
                return;
        }
 
-       set_dev_options(sdi, devargs);
+       set_dev_options_array(sdi, opt_configs);
 
        sr_dev_close(sdi);
-       g_hash_table_destroy(devargs);
-
 }
 
 int main(int argc, char **argv)
index ebd620d597b37417dcd65338da4b7202b274dc16..8d17e33cc0e8fd7b4998095ab7c8e9de1aed214a 100644 (file)
--- a/options.c
+++ b/options.c
@@ -31,7 +31,7 @@ gboolean opt_wait_trigger = FALSE;
 gchar *opt_input_file = NULL;
 gchar *opt_output_file = NULL;
 gchar *opt_drv = NULL;
-gchar *opt_config = NULL;
+gchar **opt_configs = NULL;
 gchar *opt_channels = NULL;
 gchar *opt_channel_group = NULL;
 gchar *opt_triggers = NULL;
@@ -79,7 +79,6 @@ static gboolean check_ ## option                                          \
 }
 
 CHECK_ONCE(opt_drv)
-CHECK_ONCE(opt_config)
 CHECK_ONCE(opt_input_format)
 CHECK_ONCE(opt_output_format)
 CHECK_ONCE(opt_transform_module)
@@ -112,7 +111,7 @@ static const GOptionEntry optargs[] = {
                        "Set loglevel (5 is most verbose)", NULL},
        {"driver", 'd', 0, G_OPTION_ARG_CALLBACK, &check_opt_drv,
                        "The driver to use", NULL},
-       {"config", 'c', 0, G_OPTION_ARG_CALLBACK, &check_opt_config,
+       {"config", 'c', 0, G_OPTION_ARG_STRING_ARRAY, &opt_configs,
                        "Specify device configuration options", NULL},
        {"input-file", 'i', 0, G_OPTION_ARG_FILENAME_ARRAY, &input_file_array,
                        "Load input from file", NULL},
index 56a4d25e30bb050a2feaccc06e526b41dedd7268..0e426cdd1957268102797f37f0c95a5d981de7fb 100644 (file)
--- a/session.c
+++ b/session.c
@@ -654,19 +654,51 @@ int opt_to_gvar(char *key, char *value, struct sr_config *src)
        return ret;
 }
 
+int set_dev_options_array(struct sr_dev_inst *sdi, char **opts)
+{
+       size_t opt_idx;
+       const char *opt_text;
+       GHashTable *args;
+       int ret;
+
+       for (opt_idx = 0; opts && opts[opt_idx]; opt_idx++) {
+               opt_text = opts[opt_idx];
+               args = parse_generic_arg(opt_text, FALSE, "channel_group");
+               if (!args)
+                       continue;
+               ret = set_dev_options(sdi, args);
+               g_hash_table_destroy(args);
+               if (ret != SR_OK)
+                       return ret;
+       }
+
+       return SR_OK;
+}
+
 int set_dev_options(struct sr_dev_inst *sdi, GHashTable *args)
 {
        struct sr_config src;
+       const char *cg_name;
        struct sr_channel_group *cg;
        GHashTableIter iter;
        gpointer key, value;
        int ret;
 
+       /*
+        * Not finding the 'sigrok_key' key (optional user specified
+        * channel group name) in the current options group's hash table
+        * is perfectly fine. In that case the -g selection is used,
+        * which defaults to "the device" (global parameters).
+        */
+       cg_name = g_hash_table_lookup(args, "sigrok_key");
+       cg = lookup_channel_group(sdi, cg_name);
+
        g_hash_table_iter_init(&iter, args);
        while (g_hash_table_iter_next(&iter, &key, &value)) {
+               if (g_ascii_strcasecmp(key, "sigrok_key") == 0)
+                       continue;
                if ((ret = opt_to_gvar(key, value, &src)) != 0)
                        return ret;
-               cg = lookup_channel_group(sdi);
                if ((ret = maybe_config_set(sr_dev_inst_driver_get(sdi), sdi, cg,
                                src.key, src.data)) != SR_OK) {
                        g_critical("Failed to set device option '%s': %s.",
@@ -682,7 +714,6 @@ void run_session(void)
 {
        struct df_arg_desc df_arg;
        GSList *devices, *real_devices, *sd;
-       GHashTable *devargs;
        GVariant *gvar;
        struct sr_session *session;
        struct sr_trigger *trigger;
@@ -765,12 +796,9 @@ void run_session(void)
                return;
        }
 
-       if (opt_config) {
-               if ((devargs = parse_generic_arg(opt_config, FALSE, NULL))) {
-                       if (set_dev_options(sdi, devargs) != SR_OK)
-                               return;
-                       g_hash_table_destroy(devargs);
-               }
+       if (opt_configs) {
+               if (set_dev_options_array(sdi, opt_configs) != SR_OK)
+                       return;
        }
 
        if (select_channels(sdi) != SR_OK) {
diff --git a/show.c b/show.c
index a6573e5a3acea9e241b81ad80964f18f9fbbc20a..5c35bb317c972b0442622ef36245a68fd0ba7d63 100644 (file)
--- a/show.c
+++ b/show.c
@@ -441,7 +441,7 @@ void show_dev_detail(void)
         * returned, or which values for them.
         */
        select_channels(sdi);
-       channel_group = lookup_channel_group(sdi);
+       channel_group = lookup_channel_group(sdi, NULL);
 
        if (!(opts = sr_dev_options(driver, sdi, channel_group)))
                /* Driver supports no device instance options. */
index b5603c306d90d6d4f8e3d55e4ee73372cba952e6..51ce454a33722ddecefa4a44154e153c33914a6f 100644 (file)
@@ -56,7 +56,8 @@ void show_serial_ports(void);
 
 /* device.c */
 GSList *device_scan(void);
-struct sr_channel_group *lookup_channel_group(struct sr_dev_inst *sdi);
+struct sr_channel_group *lookup_channel_group(struct sr_dev_inst *sdi,
+       const char *cg_name);
 
 /* session.c */
 struct df_arg_desc {
@@ -76,6 +77,7 @@ struct df_arg_desc {
 void datafeed_in(const struct sr_dev_inst *sdi,
                const struct sr_datafeed_packet *packet, void *cb_data);
 int opt_to_gvar(char *key, char *value, struct sr_config *src);
+int set_dev_options_array(struct sr_dev_inst *sdi, char **opts);
 int set_dev_options(struct sr_dev_inst *sdi, GHashTable *args);
 void run_session(void);
 
@@ -129,7 +131,7 @@ extern gboolean opt_wait_trigger;
 extern gchar *opt_input_file;
 extern gchar *opt_output_file;
 extern gchar *opt_drv;
-extern gchar *opt_config;
+extern gchar **opt_configs;
 extern gchar *opt_channels;
 extern gchar *opt_channel_group;
 extern gchar *opt_triggers;