X-Git-Url: https://sigrok.org/gitweb/?p=sigrok-cli.git;a=blobdiff_plain;f=sigrok-cli.c;h=488edc9d4b3d3ff080a77f5577e3c0771c51175d;hp=bcdeb3e9fb7151771f6376383b1329eb0b89116c;hb=3aa87d4c38b26d337bf7bf5eb44b6a4650709804;hpb=37d5ccc11cb29dd65c9a550eb5c5dea55006bc74 diff --git a/sigrok-cli.c b/sigrok-cli.c index bcdeb3e..488edc9 100644 --- a/sigrok-cli.c +++ b/sigrok-cli.c @@ -36,8 +36,7 @@ #define DEFAULT_OUTPUT_FORMAT "bits:width=64" -extern struct sr_hwcap_option sr_drvopts[]; -extern struct sr_hwcap_option sr_hwcap_options[]; +static struct sr_context *sr_ctx = NULL; static uint64_t limit_samples = 0; static uint64_t limit_frames = 0; @@ -45,6 +44,7 @@ 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 +115,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 +125,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); @@ -169,7 +164,7 @@ static GSList *device_scan(void) return NULL; } g_free(drvname); - if (sr_driver_init(driver) != SR_OK) { + if (sr_driver_init(sr_ctx, driver) != SR_OK) { g_critical("Failed to initialize driver."); return NULL; } @@ -185,7 +180,7 @@ static GSList *device_scan(void) drivers = sr_driver_list(); for (i = 0; drivers[i]; i++) { driver = drivers[i]; - if (sr_driver_init(driver) != SR_OK) { + if (sr_driver_init(sr_ctx, driver) != SR_OK) { g_critical("Failed to initialize driver."); return NULL; } @@ -251,6 +246,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 +255,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 +352,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 +493,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", @@ -533,10 +540,10 @@ static void show_pd_detail(void) } static void datafeed_in(const struct sr_dev_inst *sdi, - struct sr_datafeed_packet *packet) + const 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; @@ -544,14 +551,15 @@ static void datafeed_in(const struct sr_dev_inst *sdi, static FILE *outfile = NULL; static int num_analog_probes = 0; struct sr_probe *probe; - struct sr_datafeed_logic *logic; - struct sr_datafeed_meta_logic *meta_logic; - struct sr_datafeed_analog *analog; - struct sr_datafeed_meta_analog *meta_analog; + const struct sr_datafeed_logic *logic; + const struct sr_datafeed_meta_logic *meta_logic; + const struct sr_datafeed_analog *analog; + const struct sr_datafeed_meta_analog *meta_analog; static int num_enabled_analog_probes = 0; 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) @@ -598,9 +606,11 @@ static void datafeed_in(const struct sr_dev_inst *sdi, 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; @@ -622,6 +632,7 @@ static void datafeed_in(const struct sr_dev_inst *sdi, 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; @@ -632,9 +643,9 @@ static void datafeed_in(const struct sr_dev_inst *sdi, * 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 { @@ -663,8 +674,8 @@ static void datafeed_in(const struct sr_dev_inst *sdi, 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; @@ -677,9 +688,9 @@ static void datafeed_in(const struct sr_dev_inst *sdi, 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 @@ -724,9 +735,9 @@ static void datafeed_in(const struct sr_dev_inst *sdi, * 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 { @@ -790,6 +801,14 @@ static void datafeed_in(const struct sr_dev_inst *sdi, 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. @@ -804,7 +823,6 @@ static int register_pds(struct sr_dev *dev, const char *pdstring) int ret; char **pdtokens, **pdtok, *pd_name; - /* Avoid compiler warnings. */ (void)dev; ret = 0; @@ -1045,31 +1063,23 @@ void show_pd_annotations(struct srd_proto_data *pdata, void *cb_data) static int select_probes(struct sr_dev_inst *sdi) { - char **probelist; - int max_probes, i; + struct sr_probe *probe; + 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(sdi->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(sdi, i, probelist[i]); - g_free(probelist[i]); - } else { - sr_dev_probe_enable(sdi, i, FALSE); - } + 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; } @@ -1142,7 +1152,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"); } @@ -1151,7 +1161,7 @@ static void load_input_file_format(void) /* The exact cause was already logged. */ return; } -; + if (fmtargs) g_hash_table_remove(fmtargs, "sigrok_key"); @@ -1188,7 +1198,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(); @@ -1215,76 +1225,68 @@ static void load_input_file(void) 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; - val = NULL; - switch (sr_hwcap_options[i].type) { - case SR_T_UINT64: - ret = sr_parse_sizestring(value, &tmp_u64); - if (ret != SR_OK) - break; - 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; - val = &tmp_rat; - break; - case SR_T_RATIONAL_VOLT: - if ((ret = sr_parse_voltage(value, &tmp_rat)) != SR_OK) - break; - val = &tmp_rat; + 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; - default: - ret = SR_ERR; - } - if (val) - ret = sdi->driver->dev_config_set(sdi, - sr_hwcap_options[i].hwcap, val); - if (ret != SR_OK) { - g_critical("Failed to set device option '%s'.", (char *)key); - return ret; - } + 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; + val = &tmp_rat; + break; + case SR_T_RATIONAL_VOLT: + if ((ret = sr_parse_voltage(value, &tmp_rat)) != SR_OK) break; + val = &tmp_rat; + break; + default: + ret = SR_ERR; } - if (!found) { - g_critical("Unknown device option '%s'.", (char *) key); - return 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; } } @@ -1304,8 +1306,7 @@ static int set_limit_time(const struct sr_dev_inst *sdi) } if (sr_driver_hwcap_exists(sdi->driver, SR_HWCAP_LIMIT_MSEC)) { - if (sdi->driver->dev_config_set(sdi, - SR_HWCAP_LIMIT_MSEC, &time_msec) != SR_OK) { + 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; @@ -1327,8 +1328,8 @@ static int set_limit_time(const struct sr_dev_inst *sdi) return SR_ERR; } - if (sdi->driver->dev_config_set(sdi, - SR_HWCAP_LIMIT_SAMPLES, &limit_samples) != SR_OK) { + 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; @@ -1340,73 +1341,67 @@ static int set_limit_time(const struct sr_dev_inst *sdi) static void run_session(void) { - GSList *devices, *l; + GSList *devices; GHashTable *devargs; struct sr_dev_inst *sdi; int max_probes, i; - char **probelist; - - sr_session_new(); - sr_session_datafeed_callback_add(datafeed_in); + char **triggerlist; devices = device_scan(); - for (l = devices; l; l = l->next) { - sdi = l->data; - printf("found %s %s\n", sdi->vendor, sdi->model); - - devargs = NULL; - if (opt_dev) { - /* TODO: this applies the same options to every device */ - devargs = parse_generic_arg(opt_dev, FALSE); - if (devargs) { - if (set_dev_options(sdi, devargs) != SR_OK) { - return; - } - g_hash_table_destroy(devargs); - } - } + 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; - if (sr_session_dev_add(sdi) != SR_OK) { - g_critical("Failed to use device."); - sr_session_destroy(); - return; - } + sr_session_new(); + sr_session_datafeed_callback_add(datafeed_in); - if (select_probes(sdi) != SR_OK) - return; + if (sr_session_dev_add(sdi) != SR_OK) { + g_critical("Failed to use device."); + sr_session_destroy(); + return; + } - 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(); + 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); } + } - if (opt_triggers) { - probelist = sr_parse_triggerstring(sdi, opt_triggers); - if (!probelist) { - sr_session_destroy(); - return; - } + if (select_probes(sdi) != SR_OK) { + g_critical("Failed to set probes."); + sr_session_destroy(); + return; + } - max_probes = g_slist_length(sdi->probes); - for (i = 0; i < max_probes; i++) { - if (probelist[i]) { - sr_dev_trigger_set(sdi, i, probelist[i]); - g_free(probelist[i]); - } + if (opt_triggers) { + if (!(triggerlist = sr_parse_triggerstring(sdi, opt_triggers))) { + sr_session_destroy(); + return; + } + max_probes = g_slist_length(sdi->probes); + for (i = 0; i < max_probes; i++) { + if (triggerlist[i]) { + sr_dev_trigger_set(sdi, i, triggerlist[i]); + g_free(triggerlist[i]); } - g_free(probelist); } + g_free(triggerlist); + } - if (sdi->driver->dev_config_set(sdi, SR_HWCAP_PROBECONFIG, - (char *)sdi->probes) != SR_OK) { - g_critical("Failed to configure probes."); + 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 (opt_time) { @@ -1418,7 +1413,7 @@ static void run_session(void) if (opt_samples) { if ((sr_parse_sizestring(opt_samples, &limit_samples) != SR_OK) - || (sdi->driver->dev_config_set(sdi, SR_HWCAP_LIMIT_SAMPLES, + || (sr_dev_config_set(sdi, SR_HWCAP_LIMIT_SAMPLES, &limit_samples) != SR_OK)) { g_critical("Failed to configure sample limit."); sr_session_destroy(); @@ -1428,9 +1423,9 @@ static void run_session(void) if (opt_frames) { if ((sr_parse_sizestring(opt_frames, &limit_frames) != SR_OK) - || (sdi->driver->dev_config_set(sdi, - 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; } @@ -1451,7 +1446,7 @@ 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(); @@ -1462,7 +1457,6 @@ static void run_session(void) static void logger(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer cb_data) { - /* Avoid compiler warnings. */ (void)log_domain; (void)cb_data; @@ -1479,6 +1473,7 @@ static void logger(const gchar *log_domain, GLogLevelFlags log_level, int main(int argc, char **argv) { + int ret = 1; GOptionContext *context; GError *error; @@ -1490,45 +1485,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; } /* Set the loglevel (amount of messages to output) for libsigrok. */ if (sr_log_loglevel_set(opt_loglevel) != SR_OK) - return 1; + goto done; /* Set the loglevel (amount of messages to output) for libsigrokdecode. */ if (srd_log_loglevel_set(opt_loglevel) != SRD_OK) - return 1; + goto done; - if (sr_init() != SR_OK) - return 1; + if (sr_init(&sr_ctx) != SR_OK) + goto done; 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) @@ -1539,8 +1534,13 @@ int main(int argc, char **argv) if (opt_pds) srd_exit(); + ret = 0; + +done: + if (sr_ctx) + sr_exit(sr_ctx); + g_option_context_free(context); - sr_exit(); - return 0; + return ret; }