X-Git-Url: https://sigrok.org/gitweb/?p=sigrok-cli.git;a=blobdiff_plain;f=sigrok-cli.c;h=2f6c59d80b26bb1eb016ea05fd27426f70943320;hp=814eb1f196d45c7bce1137b37acaaa22625bc4ba;hb=198f4c6c8d8e572aed41dfc3f7d3fe413e421770;hpb=22981b2c4624eb9c3fc570c4cf2631faeeb2bcec diff --git a/sigrok-cli.c b/sigrok-cli.c index 814eb1f..2f6c59d 100644 --- a/sigrok-cli.c +++ b/sigrok-cli.c @@ -36,15 +36,13 @@ #define DEFAULT_OUTPUT_FORMAT "bits:width=64" -extern struct sr_hwcap_option sr_drvopts[]; -extern struct sr_hwcap_option sr_hwcap_options[]; - static uint64_t limit_samples = 0; static uint64_t limit_frames = 0; static struct sr_output_format *output_format = NULL; static int default_output_format = FALSE; static char *output_format_param = NULL; static GHashTable *pd_ann_visible = NULL; +static struct sr_datastore *singleds = NULL; static gboolean opt_version = FALSE; static gint opt_loglevel = SR_LOG_WARN; /* Show errors+warnings per default. */ @@ -115,7 +113,7 @@ static GOptionEntry optargs[] = { /* Convert driver options hash to GSList of struct sr_hwopt. */ static GSList *hash_to_hwopt(GHashTable *hash) { - struct sr_hwcap_option *ho; + const struct sr_hwcap_option *hwo; struct sr_hwopt *hwopt; GList *gl, *keys; GSList *opts; @@ -125,20 +123,15 @@ static GSList *hash_to_hwopt(GHashTable *hash) opts = NULL; for (gl = keys; gl; gl = gl->next) { key = gl->data; - for (ho = sr_drvopts; ho->shortname; ho++) { - if (!strcmp(key, ho->shortname)) { - hwopt = g_try_malloc(sizeof(struct sr_hwopt)); - hwopt->hwopt = ho->hwcap; - value = g_hash_table_lookup(hash, key); - hwopt->value = g_strdup(value); - opts = g_slist_append(opts, hwopt); - break; - } - } - if (!ho->shortname) { + if (!(hwo = sr_drvopt_name_get(key))) { g_critical("Unknown option %s", key); return NULL; } + hwopt = g_try_malloc(sizeof(struct sr_hwopt)); + hwopt->hwopt = hwo->hwcap; + value = g_hash_table_lookup(hash, key); + hwopt->value = g_strdup(value); + opts = g_slist_append(opts, hwopt); } g_list_free(keys); @@ -251,6 +244,8 @@ static void show_version(void) static void print_dev_line(const struct sr_dev_inst *sdi) { + struct sr_probe *probe; + GSList *l; if (sdi->vendor && sdi->vendor[0]) printf("%s ", sdi->vendor); @@ -258,8 +253,18 @@ static void print_dev_line(const struct sr_dev_inst *sdi) printf("%s ", sdi->model); if (sdi->version && sdi->version[0]) printf("%s ", sdi->version); - if (sdi->probes) - printf("with %d probes", g_slist_length(sdi->probes)); + if (sdi->probes) { + if (g_slist_length(sdi->probes) == 1) { + probe = sdi->probes->data; + printf("with 1 probe: %s", probe->name); + } else { + printf("with %d probes:", g_slist_length(sdi->probes)); + for (l = sdi->probes; l; l = l->next) { + probe = l->data; + printf(" %s", probe->name); + } + } + } printf("\n"); } @@ -345,7 +350,7 @@ static void show_dev_detail(void) return; for (cap = 0; hwcaps[cap]; cap++) { - if (!(hwo = sr_hw_hwcap_get(hwcaps[cap]))) + if (!(hwo = sr_devopt_get(hwcaps[cap]))) continue; if (title) { @@ -486,7 +491,7 @@ static void show_pd_detail(void) pdtokens = g_strsplit(opt_pds, ",", -1); for (pdtok = pdtokens; *pdtok; pdtok++) { if (!(dec = srd_decoder_get_by_id(*pdtok))) { - printf("Protocol decoder %s not found.\n", *pdtok); + g_critical("Protocol decoder %s not found.", *pdtok); return; } printf("ID: %s\nName: %s\nLong name: %s\nDescription: %s\n", @@ -532,10 +537,11 @@ static void show_pd_detail(void) g_strfreev(pdtokens); } -static void datafeed_in(struct sr_dev *dev, struct sr_datafeed_packet *packet) +static void datafeed_in(const struct sr_dev_inst *sdi, + struct sr_datafeed_packet *packet) { static struct sr_output *o = NULL; - static int logic_probelist[SR_MAX_NUM_PROBES] = { 0 }; + static int logic_probelist[SR_MAX_NUM_PROBES] = { -1 }; static struct sr_probe *analog_probelist[SR_MAX_NUM_PROBES]; static uint64_t received_samples = 0; static int unitsize = 0; @@ -551,6 +557,7 @@ static void datafeed_in(struct sr_dev *dev, struct sr_datafeed_packet *packet) int num_enabled_probes, sample_size, ret, i; uint64_t output_len, filter_out_len; uint8_t *output_buf, *filter_out; + GString *out; /* If the first packet to come in isn't a header, don't even try. */ if (packet->type != SR_DF_HEADER && o == NULL) @@ -566,7 +573,7 @@ static void datafeed_in(struct sr_dev *dev, struct sr_datafeed_packet *packet) exit(1); } o->format = output_format; - o->dev = dev; + o->sdi = (struct sr_dev_inst *)sdi; o->param = output_format_param; if (o->format->init) { if (o->format->init(o) != SR_OK) { @@ -597,9 +604,11 @@ static void datafeed_in(struct sr_dev *dev, struct sr_datafeed_packet *packet) if (opt_continuous) g_warning("Device stopped after %" PRIu64 " samples.", received_samples); - sr_session_stop(); if (outfile && outfile != stdout) fclose(outfile); + + if (o->format->cleanup) + o->format->cleanup(o); g_free(o); o = NULL; break; @@ -617,10 +626,11 @@ static void datafeed_in(struct sr_dev *dev, struct sr_datafeed_packet *packet) meta_logic = packet->payload; num_enabled_probes = 0; for (i = 0; i < meta_logic->num_probes; i++) { - probe = g_slist_nth_data(dev->probes, i); + probe = g_slist_nth_data(sdi->probes, i); if (probe->enabled) logic_probelist[num_enabled_probes++] = probe->index; } + logic_probelist[num_enabled_probes] = -1; /* How many bytes we need to store num_enabled_probes bits */ unitsize = (num_enabled_probes + 7) / 8; @@ -631,9 +641,9 @@ static void datafeed_in(struct sr_dev *dev, struct sr_datafeed_packet *packet) * dump everything in the datastore as it comes in, * and save from there after the session. */ outfile = NULL; - ret = sr_datastore_new(unitsize, &(dev->datastore)); + ret = sr_datastore_new(unitsize, &singleds); if (ret != SR_OK) { - printf("Failed to create datastore.\n"); + g_critical("Failed to create datastore."); exit(1); } } else { @@ -662,8 +672,8 @@ static void datafeed_in(struct sr_dev *dev, struct sr_datafeed_packet *packet) break; ret = sr_filter_probes(sample_size, unitsize, logic_probelist, - logic->data, logic->length, - &filter_out, &filter_out_len); + logic->data, logic->length, + &filter_out, &filter_out_len); if (ret != SR_OK) break; @@ -676,9 +686,9 @@ static void datafeed_in(struct sr_dev *dev, struct sr_datafeed_packet *packet) limit_samples * sample_size)) filter_out_len = limit_samples * sample_size - received_samples; - if (dev->datastore) - sr_datastore_put(dev->datastore, filter_out, - filter_out_len, sample_size, logic_probelist); + if (singleds) + sr_datastore_put(singleds, filter_out, + filter_out_len, sample_size, logic_probelist); if (opt_output_file && default_output_format) /* saving to a session file, don't need to do anything else @@ -711,7 +721,7 @@ static void datafeed_in(struct sr_dev *dev, struct sr_datafeed_packet *packet) num_analog_probes = meta_analog->num_probes; num_enabled_analog_probes = 0; for (i = 0; i < num_analog_probes; i++) { - probe = g_slist_nth_data(dev->probes, i); + probe = g_slist_nth_data(sdi->probes, i); if (probe->enabled) analog_probelist[num_enabled_analog_probes++] = probe; } @@ -723,9 +733,9 @@ static void datafeed_in(struct sr_dev *dev, struct sr_datafeed_packet *packet) * dump everything in the datastore as it comes in, * and save from there after the session. */ outfile = NULL; - ret = sr_datastore_new(unitsize, &(dev->datastore)); + ret = sr_datastore_new(unitsize, &singleds); if (ret != SR_OK) { - printf("Failed to create datastore.\n"); + g_critical("Failed to create datastore."); exit(1); } } else { @@ -789,6 +799,14 @@ static void datafeed_in(struct sr_dev *dev, struct sr_datafeed_packet *packet) g_message("received unknown packet type %d", packet->type); } + if (o && o->format->recv) { + out = o->format->recv(o, sdi, packet); + if (out && out->len) { + fwrite(out->str, 1, out->len, outfile); + fflush(outfile); + } + } + } /* Register the given PDs for this session. @@ -1042,35 +1060,25 @@ void show_pd_annotations(struct srd_proto_data *pdata, void *cb_data) fflush(stdout); } -static int select_probes(struct sr_dev *dev) +static int select_probes(struct sr_dev_inst *sdi) { struct sr_probe *probe; - char **probelist; - int max_probes, i; + GSList *selected_probes, *l; if (!opt_probes) return SR_OK; - /* - * This only works because a device by default initializes - * and enables all its probes. - */ - max_probes = g_slist_length(dev->probes); - probelist = parse_probestring(max_probes, opt_probes); - if (!probelist) { + if (!(selected_probes = parse_probestring(sdi, opt_probes))) return SR_ERR; - } - for (i = 0; i < max_probes; i++) { - if (probelist[i]) { - sr_dev_probe_name_set(dev, i + 1, probelist[i]); - g_free(probelist[i]); - } else { - probe = sr_dev_probe_find(dev, i + 1); + for (l = sdi->probes; l; l = l->next) { + probe = l->data; + if (g_slist_find(selected_probes, probe)) + probe->enabled = TRUE; + else probe->enabled = FALSE; - } } - g_free(probelist); + g_slist_free(selected_probes); return SR_OK; } @@ -1143,7 +1151,7 @@ static void load_input_file_format(void) char *fmtspec = NULL; if (opt_input_format) { - fmtargs = parse_generic_arg(opt_input_format); + fmtargs = parse_generic_arg(opt_input_format, TRUE); fmtspec = g_hash_table_lookup(fmtargs, "sigrok_key"); } @@ -1152,7 +1160,7 @@ static void load_input_file_format(void) /* The exact cause was already logged. */ return; } -; + if (fmtargs) g_hash_table_remove(fmtargs, "sigrok_key"); @@ -1176,12 +1184,12 @@ static void load_input_file_format(void) } } - if (select_probes(in->vdev) > 0) + if (select_probes(in->sdi) > 0) return; sr_session_new(); sr_session_datafeed_callback_add(datafeed_in); - if (sr_session_dev_add(in->vdev) != SR_OK) { + if (sr_session_dev_add(in->sdi) != SR_OK) { g_critical("Failed to use device."); sr_session_destroy(); return; @@ -1189,7 +1197,7 @@ static void load_input_file_format(void) input_format->loadfile(in, opt_input_file); if (opt_output_file && default_output_format) { - if (sr_session_save(opt_output_file) != SR_OK) + if (sr_session_save(opt_output_file, in->sdi, singleds) != SR_OK) g_critical("Failed to save session."); } sr_session_destroy(); @@ -1214,97 +1222,117 @@ static void load_input_file(void) } } -int num_real_devs(void) -{ - struct sr_dev *dev; - GSList *devs, *l; - int num_devs; - - num_devs = 0; - devs = sr_dev_list(); - for (l = devs; l; l = l->next) { - dev = l->data; - if (!sr_dev_has_hwcap(dev, SR_HWCAP_DEMO_DEV)) - num_devs++; - } - - return num_devs; -} - -static int set_dev_options(struct sr_dev *dev, GHashTable *args) +static int set_dev_options(struct sr_dev_inst *sdi, GHashTable *args) { + const struct sr_hwcap_option *hwo; GHashTableIter iter; gpointer key, value; - int ret, i; + int ret; float tmp_float; uint64_t tmp_u64; struct sr_rational tmp_rat; gboolean tmp_bool; - gboolean found; + void *val; g_hash_table_iter_init(&iter, args); while (g_hash_table_iter_next(&iter, &key, &value)) { - found = FALSE; - for (i = 0; sr_hwcap_options[i].hwcap; i++) { - if (strcmp(sr_hwcap_options[i].shortname, key)) - continue; - if ((value == NULL) && - (sr_hwcap_options[i].type != SR_T_BOOL)) { - g_critical("Option '%s' needs a value.", (char *)key); - return SR_ERR; - } - found = TRUE; - switch (sr_hwcap_options[i].type) { - case SR_T_UINT64: - ret = sr_parse_sizestring(value, &tmp_u64); - if (ret != SR_OK) - break; - ret = dev->driver->dev_config_set(dev->driver_index, - sr_hwcap_options[i].hwcap, &tmp_u64); - break; - case SR_T_CHAR: - ret = dev->driver->dev_config_set(dev->driver_index, - sr_hwcap_options[i].hwcap, value); - break; - case SR_T_BOOL: - if (!value) - tmp_bool = TRUE; - else - tmp_bool = sr_parse_boolstring(value); - ret = dev->driver->dev_config_set(dev->driver_index, - sr_hwcap_options[i].hwcap, - GINT_TO_POINTER(tmp_bool)); - break; - case SR_T_FLOAT: - tmp_float = strtof(value, NULL); - ret = dev->driver->dev_config_set(dev->driver_index, - sr_hwcap_options[i].hwcap, &tmp_float); + if (!(hwo = sr_devopt_name_get(key))) { + g_critical("Unknown device option '%s'.", (char *) key); + return SR_ERR; + } + + if ((value == NULL) && + (hwo->type != SR_T_BOOL)) { + g_critical("Option '%s' needs a value.", (char *)key); + return SR_ERR; + } + val = NULL; + switch (hwo->type) { + case SR_T_UINT64: + ret = sr_parse_sizestring(value, &tmp_u64); + if (ret != SR_OK) break; - case SR_T_RATIONAL_PERIOD: - if ((ret = sr_parse_period(value, &tmp_rat)) != SR_OK) - break; - ret = dev->driver->dev_config_set(dev->driver_index, - sr_hwcap_options[i].hwcap, &tmp_rat); + val = &tmp_u64; + break; + case SR_T_CHAR: + val = value; + break; + case SR_T_BOOL: + if (!value) + tmp_bool = TRUE; + else + tmp_bool = sr_parse_boolstring(value); + val = &tmp_bool; + break; + case SR_T_FLOAT: + tmp_float = strtof(value, NULL); + val = &tmp_float; + break; + case SR_T_RATIONAL_PERIOD: + if ((ret = sr_parse_period(value, &tmp_rat)) != SR_OK) break; - case SR_T_RATIONAL_VOLT: - if ((ret = sr_parse_voltage(value, &tmp_rat)) != SR_OK) - break; - ret = dev->driver->dev_config_set(dev->driver_index, - sr_hwcap_options[i].hwcap, &tmp_rat); + val = &tmp_rat; + break; + case SR_T_RATIONAL_VOLT: + if ((ret = sr_parse_voltage(value, &tmp_rat)) != SR_OK) break; - default: - ret = SR_ERR; - } + val = &tmp_rat; + break; + default: + ret = SR_ERR; + } + if (val) + ret = sr_dev_config_set(sdi, hwo->hwcap, val); + if (ret != SR_OK) { + g_critical("Failed to set device option '%s'.", (char *)key); + return ret; + } + else + break; + } - if (ret != SR_OK) { - g_critical("Failed to set device option '%s'.", (char *)key); - return ret; - } - else - break; + return SR_OK; +} + +static int set_limit_time(const struct sr_dev_inst *sdi) +{ + uint64_t time_msec; + uint64_t *samplerate; + + time_msec = sr_parse_timestring(opt_time); + if (time_msec == 0) { + g_critical("Invalid time '%s'", opt_time); + sr_session_destroy(); + return SR_ERR; + } + + if (sr_driver_hwcap_exists(sdi->driver, SR_HWCAP_LIMIT_MSEC)) { + if (sr_dev_config_set(sdi, SR_HWCAP_LIMIT_MSEC, &time_msec) != SR_OK) { + g_critical("Failed to configure time limit."); + sr_session_destroy(); + return SR_ERR; } - if (!found) { - g_critical("Unknown device option '%s'.", (char *) key); + } + else { + /* time limit set, but device doesn't support this... + * convert to samples based on the samplerate. + */ + limit_samples = 0; + if (sr_dev_has_hwcap(sdi, SR_HWCAP_SAMPLERATE)) { + sr_info_get(sdi->driver, SR_DI_CUR_SAMPLERATE, + (const void **)&samplerate, sdi); + limit_samples = (*samplerate) * time_msec / (uint64_t)1000; + } + if (limit_samples == 0) { + g_critical("Not enough time at this samplerate."); + sr_session_destroy(); + return SR_ERR; + } + + if (sr_dev_config_set(sdi, SR_HWCAP_LIMIT_SAMPLES, + &limit_samples) != SR_OK) { + g_critical("Failed to configure time-based sample limit."); + sr_session_destroy(); return SR_ERR; } } @@ -1314,129 +1342,80 @@ static int set_dev_options(struct sr_dev *dev, GHashTable *args) static void run_session(void) { - struct sr_dev *dev; + GSList *devices; GHashTable *devargs; - int num_devs, max_probes, i; - uint64_t time_msec; - char **probelist, *devspec; + struct sr_dev_inst *sdi; + int max_probes, i; + char **triggerlist; - devargs = NULL; - if (opt_dev) { - devargs = parse_generic_arg(opt_dev); - devspec = g_hash_table_lookup(devargs, "sigrok_key"); - dev = parse_devstring(devspec); - if (!dev) { - g_critical("Device not found."); - return; - } - g_hash_table_remove(devargs, "sigrok_key"); - } else { - num_devs = num_real_devs(); - if (num_devs == 1) { - /* No device specified, but there is only one. */ - devargs = NULL; - dev = parse_devstring("0"); - } else if (num_devs == 0) { - g_critical("No devices found."); - return; - } else { - g_critical("%d devices found, please select one.", num_devs); - return; - } + devices = device_scan(); + if (!devices) { + g_critical("No devices found."); + return; + } + if (g_slist_length(devices) > 1) { + g_critical("sigrok-cli only supports one device for capturing."); + return; } + sdi = devices->data; sr_session_new(); sr_session_datafeed_callback_add(datafeed_in); - if (sr_session_dev_add(dev) != SR_OK) { + if (sr_session_dev_add(sdi) != SR_OK) { g_critical("Failed to use device."); sr_session_destroy(); return; } - if (devargs) { - if (set_dev_options(dev, devargs) != SR_OK) { - sr_session_destroy(); - return; + if (opt_dev) { + if ((devargs = parse_generic_arg(opt_dev, FALSE))) { + if (set_dev_options(sdi, devargs) != SR_OK) + return; + g_hash_table_destroy(devargs); } - g_hash_table_destroy(devargs); } - if (select_probes(dev) != SR_OK) - return; - - if (opt_continuous) { - if (!sr_driver_hwcap_exists(dev->driver, SR_HWCAP_CONTINUOUS)) { - g_critical("This device does not support continuous sampling."); - sr_session_destroy(); - return; - } + if (select_probes(sdi) != SR_OK) { + g_critical("Failed to set probes."); + sr_session_destroy(); + return; } if (opt_triggers) { - probelist = sr_parse_triggerstring(dev, opt_triggers); - if (!probelist) { + if (!(triggerlist = sr_parse_triggerstring(sdi, opt_triggers))) { sr_session_destroy(); return; } - - max_probes = g_slist_length(dev->probes); + max_probes = g_slist_length(sdi->probes); for (i = 0; i < max_probes; i++) { - if (probelist[i]) { - sr_dev_trigger_set(dev, i + 1, probelist[i]); - g_free(probelist[i]); + if (triggerlist[i]) { + sr_dev_trigger_set(sdi, i, triggerlist[i]); + g_free(triggerlist[i]); } } - g_free(probelist); + g_free(triggerlist); } - if (opt_time) { - time_msec = sr_parse_timestring(opt_time); - if (time_msec == 0) { - g_critical("Invalid time '%s'", opt_time); + if (opt_continuous) { + if (!sr_driver_hwcap_exists(sdi->driver, SR_HWCAP_CONTINUOUS)) { + g_critical("This device does not support continuous sampling."); sr_session_destroy(); return; } + } - if (sr_driver_hwcap_exists(dev->driver, SR_HWCAP_LIMIT_MSEC)) { - if (dev->driver->dev_config_set(dev->driver_index, - SR_HWCAP_LIMIT_MSEC, &time_msec) != SR_OK) { - g_critical("Failed to configure time limit."); - sr_session_destroy(); - return; - } - } - else { - /* time limit set, but device doesn't support this... - * convert to samples based on the samplerate. - */ - limit_samples = 0; - if (sr_dev_has_hwcap(dev, SR_HWCAP_SAMPLERATE)) { - const uint64_t *samplerate; - - sr_dev_info_get(dev, SR_DI_CUR_SAMPLERATE, - (const void **)&samplerate); - limit_samples = (*samplerate) * time_msec / (uint64_t)1000; - } - if (limit_samples == 0) { - g_critical("Not enough time at this samplerate."); - sr_session_destroy(); - return; - } - - if (dev->driver->dev_config_set(dev->driver_index, - SR_HWCAP_LIMIT_SAMPLES, &limit_samples) != SR_OK) { - g_critical("Failed to configure time-based sample limit."); - sr_session_destroy(); - return; - } + if (opt_time) { + if (set_limit_time(sdi) != SR_OK) { + sr_session_destroy(); + return; } } if (opt_samples) { if ((sr_parse_sizestring(opt_samples, &limit_samples) != SR_OK) - || (dev->driver->dev_config_set(dev->driver_index, - SR_HWCAP_LIMIT_SAMPLES, &limit_samples) != SR_OK)) { + || (sr_dev_config_set(sdi, SR_HWCAP_LIMIT_SAMPLES, + &limit_samples) != SR_OK)) { g_critical("Failed to configure sample limit."); sr_session_destroy(); return; @@ -1445,21 +1424,14 @@ static void run_session(void) if (opt_frames) { if ((sr_parse_sizestring(opt_frames, &limit_frames) != SR_OK) - || (dev->driver->dev_config_set(dev->driver_index, - SR_HWCAP_LIMIT_FRAMES, &limit_frames) != SR_OK)) { - printf("Failed to configure frame limit.\n"); + || (sr_dev_config_set(sdi, SR_HWCAP_LIMIT_FRAMES, + &limit_frames) != SR_OK)) { + g_critical("Failed to configure frame limit."); sr_session_destroy(); return; } } - if (dev->driver->dev_config_set(dev->driver_index, - SR_HWCAP_PROBECONFIG, (char *)dev->probes) != SR_OK) { - g_critical("Failed to configure probes."); - sr_session_destroy(); - return; - } - if (sr_session_start() != SR_OK) { g_critical("Failed to start session."); sr_session_destroy(); @@ -1475,10 +1447,12 @@ static void run_session(void) clear_anykey(); if (opt_output_file && default_output_format) { - if (sr_session_save(opt_output_file) != SR_OK) + if (sr_session_save(opt_output_file, sdi, singleds) != SR_OK) g_critical("Failed to save session."); } sr_session_destroy(); + g_slist_free(devices); + } static void logger(const gchar *log_domain, GLogLevelFlags log_level, @@ -1501,6 +1475,7 @@ static void logger(const gchar *log_domain, GLogLevelFlags log_level, int main(int argc, char **argv) { + int ret = 1; GOptionContext *context; GError *error; @@ -1512,45 +1487,45 @@ int main(int argc, char **argv) if (!g_option_context_parse(context, &argc, &argv, &error)) { g_critical("%s", error->message); - return 1; + goto done_noexit; } /* Set the loglevel (amount of messages to output) for libsigrok. */ if (sr_log_loglevel_set(opt_loglevel) != SR_OK) - return 1; + goto done_noexit; /* Set the loglevel (amount of messages to output) for libsigrokdecode. */ if (srd_log_loglevel_set(opt_loglevel) != SRD_OK) - return 1; + goto done_noexit; if (sr_init() != SR_OK) - return 1; + goto done_noexit; if (opt_pds) { if (srd_init(NULL) != SRD_OK) - return 1; + goto done; if (register_pds(NULL, opt_pds) != 0) - return 1; + goto done; if (srd_pd_output_callback_add(SRD_OUTPUT_ANN, show_pd_annotations, NULL) != SRD_OK) - return 1; + goto done; if (setup_pd_stack() != 0) - return 1; + goto done; if (setup_pd_annotations() != 0) - return 1; + goto done; } if (setup_output_format() != 0) - return 1; + goto done; if (opt_version) show_version(); else if (opt_list_devs) show_dev_list(); + else if (opt_pds && opt_show) + show_pd_detail(); else if (opt_show) show_dev_detail(); - else if (opt_pds) - show_pd_detail(); else if (opt_input_file) load_input_file(); else if (opt_samples || opt_time || opt_frames || opt_continuous) @@ -1561,8 +1536,13 @@ int main(int argc, char **argv) if (opt_pds) srd_exit(); - g_option_context_free(context); + ret = 0; + +done: sr_exit(); - return 0; +done_noexit: + g_option_context_free(context); + + return ret; }