Skip to content

Commit

Permalink
accept multiple --config requests for multiple channel groups
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
gsigh committed Aug 3, 2020
1 parent c9c30f5 commit 6c94f0c
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 39 deletions.
27 changes: 18 additions & 9 deletions device.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
}
20 changes: 4 additions & 16 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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));
Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand Down
5 changes: 2 additions & 3 deletions options.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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},
Expand Down
44 changes: 36 additions & 8 deletions session.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion show.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down
6 changes: 4 additions & 2 deletions sigrok-cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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);

Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 6c94f0c

Please sign in to comment.