X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Finput%2Finput.c;h=ee19d66169ece22b67254fdf4c330afbcccb62c7;hb=8c4bff1d25e1c41ef44e3570823789a82f24b12a;hp=f2cc976935147b8396d31f0e086382a987d0efd2;hpb=6d2897e394950bb661a27fd33dbcd14d8c56c61f;p=libsigrok.git diff --git a/src/input/input.c b/src/input/input.c index f2cc9769..ee19d661 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -29,6 +29,8 @@ #define LOG_PREFIX "input" /** @endcond */ +#define CHUNK_SIZE (4 * 1024 * 1024) + /** * @file * @@ -66,6 +68,8 @@ extern SR_PRIV struct sr_input_module input_trace32_ad; extern SR_PRIV struct sr_input_module input_vcd; extern SR_PRIV struct sr_input_module input_wav; extern SR_PRIV struct sr_input_module input_raw_analog; +extern SR_PRIV struct sr_input_module input_logicport; +extern SR_PRIV struct sr_input_module input_null; /* @endcond */ static const struct sr_input_module *input_module_list[] = { @@ -76,6 +80,8 @@ static const struct sr_input_module *input_module_list[] = { &input_vcd, &input_wav, &input_raw_analog, + &input_logicport, + &input_null, NULL, }; @@ -334,11 +340,15 @@ static gboolean check_required_metadata(const uint8_t *metadata, uint8_t *avail) * Try to find an input module that can parse the given buffer. * * The buffer must contain enough of the beginning of the file for - * the input modules to find a match. This is format-dependent, but - * 128 bytes is normally enough. + * the input modules to find a match. This is format-dependent. When + * magic strings get checked, 128 bytes normally could be enough. Note + * that some formats try to parse larger header sections, and benefit + * from seeing a larger scope. * * If an input module is found, an instance is created into *in. - * Otherwise, *in contains NULL. + * Otherwise, *in contains NULL. When multiple input moduless claim + * support for the format, the one with highest confidence takes + * precedence. Applications will see at most one input module spec. * * If an instance is created, it has the given buffer used for scanning * already submitted to it, to be processed before more data is sent. @@ -349,9 +359,10 @@ static gboolean check_required_metadata(const uint8_t *metadata, uint8_t *avail) */ SR_API int sr_input_scan_buffer(GString *buf, const struct sr_input **in) { - const struct sr_input_module *imod; + const struct sr_input_module *imod, *best_imod; GHashTable *meta; unsigned int m, i; + unsigned int conf, best_conf; int ret; uint8_t mitem, avail_metadata[8]; @@ -360,7 +371,8 @@ SR_API int sr_input_scan_buffer(GString *buf, const struct sr_input **in) avail_metadata[1] = 0; *in = NULL; - ret = SR_ERR; + best_imod = NULL; + best_conf = ~0; for (i = 0; input_module_list[i]; i++) { imod = input_module_list[i]; if (!imod->metadata[0]) { @@ -384,45 +396,55 @@ SR_API int sr_input_scan_buffer(GString *buf, const struct sr_input **in) continue; } sr_spew("Trying module %s.", imod->id); - ret = imod->format_match(meta); + ret = imod->format_match(meta, &conf); g_hash_table_destroy(meta); if (ret == SR_ERR_DATA) { /* Module recognized this buffer, but cannot handle it. */ - break; + continue; } else if (ret == SR_ERR) { /* Module didn't recognize this buffer. */ continue; } else if (ret != SR_OK) { /* Can be SR_ERR_NA. */ - return ret; + continue; } /* Found a matching module. */ - sr_spew("Module %s matched.", imod->id); - *in = sr_input_new(imod, NULL); + sr_spew("Module %s matched, confidence %u.", imod->id, conf); + if (conf >= best_conf) + continue; + best_imod = imod; + best_conf = conf; + } + + if (best_imod) { + *in = sr_input_new(best_imod, NULL); g_string_insert_len((*in)->buf, 0, buf->str, buf->len); - break; + return SR_OK; } - return ret; + return SR_ERR; } /** * Try to find an input module that can parse the given file. * * If an input module is found, an instance is created into *in. - * Otherwise, *in contains NULL. + * Otherwise, *in contains NULL. When multiple input moduless claim + * support for the format, the one with highest confidence takes + * precedence. Applications will see at most one input module spec. * */ SR_API int sr_input_scan_file(const char *filename, const struct sr_input **in) { int64_t filesize; FILE *stream; - const struct sr_input_module *imod; + const struct sr_input_module *imod, *best_imod; GHashTable *meta; GString *header; size_t count; unsigned int midx, i; + unsigned int conf, best_conf; int ret; uint8_t avail_metadata[8]; @@ -444,11 +466,9 @@ SR_API int sr_input_scan_file(const char *filename, const struct sr_input **in) fclose(stream); return SR_ERR; } - /* This actually allocates 256 bytes to allow for NUL termination. */ - header = g_string_sized_new(255); + header = g_string_sized_new(CHUNK_SIZE); count = fread(header->str, 1, header->allocated_len - 1, stream); - - if (count != header->allocated_len - 1 && ferror(stream)) { + if (count < 1 || ferror(stream)) { sr_err("Failed to read %s: %s", filename, g_strerror(errno)); fclose(stream); g_string_free(header, TRUE); @@ -471,8 +491,8 @@ SR_API int sr_input_scan_file(const char *filename, const struct sr_input **in) avail_metadata[midx] = 0; /* TODO: MIME type */ - ret = SR_ERR; - + best_imod = NULL; + best_conf = ~0; for (i = 0; input_module_list[i]; i++) { imod = input_module_list[i]; if (!imod->metadata[0]) { @@ -486,24 +506,30 @@ SR_API int sr_input_scan_file(const char *filename, const struct sr_input **in) sr_dbg("Trying module %s.", imod->id); - ret = imod->format_match(meta); + ret = imod->format_match(meta, &conf); if (ret == SR_ERR) { /* Module didn't recognize this buffer. */ continue; } else if (ret != SR_OK) { /* Module recognized this buffer, but cannot handle it. */ - break; + continue; } /* Found a matching module. */ - sr_dbg("Module %s matched.", imod->id); - - *in = sr_input_new(imod, NULL); - break; + sr_dbg("Module %s matched, confidence %u.", imod->id, conf); + if (conf >= best_conf) + continue; + best_imod = imod; + best_conf = conf; } g_hash_table_destroy(meta); g_string_free(header, TRUE); - return ret; + if (best_imod) { + *in = sr_input_new(best_imod, NULL); + return SR_OK; + } + + return SR_ERR; } /** @@ -559,6 +585,27 @@ SR_API int sr_input_end(const struct sr_input *in) return in->module->end((struct sr_input *)in); } +/** + * Reset the input module's input handling structures. + * + * Causes the input module to reset its internal state so that we can re-send + * the input data from the beginning without having to re-create the entire + * input module. + * + * @since 0.5.0 + */ +SR_API int sr_input_reset(const struct sr_input *in) +{ + if (!in->module->reset) { + sr_spew("Tried to reset %s module but no reset handler found.", + in->module->id); + return SR_OK; + } + + sr_spew("Resetting %s module.", in->module->id); + return in->module->reset((struct sr_input *)in); +} + /** * Free the specified input instance and all associated resources. * @@ -571,8 +618,7 @@ SR_API void sr_input_free(const struct sr_input *in) if (in->module->cleanup) in->module->cleanup((struct sr_input *)in); - if (in->sdi) - sr_dev_inst_free(in->sdi); + sr_dev_inst_free(in->sdi); if (in->buf->len > 64) { /* That seems more than just some sub-unitsize leftover... */ sr_warn("Found %" G_GSIZE_FORMAT