X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=output%2Fols.c;h=78a41bb0b4645032eb342ef1796246d165b6da6b;hb=2fe80494471a601484b58dd30043665c0dd84774;hp=25e19f41ac77c20b96f311b2bde760bab6dd83f1;hpb=50985c2019b2b5a6ce394589d89ee925b4f5e3a9;p=libsigrok.git diff --git a/output/ols.c b/output/ols.c index 25e19f41..78a41bb0 100644 --- a/output/ols.c +++ b/output/ols.c @@ -31,29 +31,16 @@ #include "libsigrok.h" #include "libsigrok-internal.h" -/* Message logging helpers with driver-specific prefix string. */ -#define DRIVER_LOG_DOMAIN "output/ols: " -#define sr_log(l, s, args...) sr_log(l, DRIVER_LOG_DOMAIN s, ## args) -#define sr_spew(s, args...) sr_spew(DRIVER_LOG_DOMAIN s, ## args) -#define sr_dbg(s, args...) sr_dbg(DRIVER_LOG_DOMAIN s, ## args) -#define sr_info(s, args...) sr_info(DRIVER_LOG_DOMAIN s, ## args) -#define sr_warn(s, args...) sr_warn(DRIVER_LOG_DOMAIN s, ## args) -#define sr_err(s, args...) sr_err(DRIVER_LOG_DOMAIN s, ## args) +#define LOG_PREFIX "output/ols" struct context { - GString *header; + uint64_t samplerate; uint64_t num_samples; - unsigned int unitsize; }; static int init(struct sr_output *o) { struct context *ctx; - struct sr_probe *probe; - GSList *l; - GVariant *gvar; - uint64_t samplerate; - int num_enabled_probes; if (!(ctx = g_try_malloc(sizeof(struct context)))) { sr_err("%s: ctx malloc failed", __func__); @@ -61,77 +48,102 @@ static int init(struct sr_output *o) } o->internal = ctx; + ctx->samplerate = 0; ctx->num_samples = 0; - num_enabled_probes = 0; - for (l = o->sdi->probes; l; l = l->next) { - probe = l->data; - if (probe->enabled) - num_enabled_probes++; - } - ctx->unitsize = (num_enabled_probes + 7) / 8; - if (o->sdi->driver && sr_dev_has_option(o->sdi, SR_CONF_SAMPLERATE)) { - o->sdi->driver->config_get(SR_CONF_SAMPLERATE, &gvar, o->sdi); - samplerate = g_variant_get_uint64(gvar); + return SR_OK; +} + +static GString *gen_header(const struct sr_dev_inst *sdi, struct context *ctx) +{ + struct sr_channel *ch; + GSList *l; + GString *s; + GVariant *gvar; + int num_enabled_channels; + + if (!ctx->samplerate && sr_config_get(sdi->driver, sdi, NULL, + SR_CONF_SAMPLERATE, &gvar) == SR_OK) { + ctx->samplerate = g_variant_get_uint64(gvar); g_variant_unref(gvar); - } else { - samplerate = 0; } - ctx->header = g_string_sized_new(512); - g_string_append_printf(ctx->header, ";Rate: %"PRIu64"\n", samplerate); - g_string_append_printf(ctx->header, ";Channels: %d\n", num_enabled_probes); - g_string_append_printf(ctx->header, ";EnabledChannels: -1\n"); - g_string_append_printf(ctx->header, ";Compressed: true\n"); - g_string_append_printf(ctx->header, ";CursorEnabled: false\n"); + num_enabled_channels = 0; + for (l = sdi->channels; l; l = l->next) { + ch = l->data; + if (ch->type != SR_CHANNEL_LOGIC) + continue; + if (!ch->enabled) + continue; + num_enabled_channels++; + } - return SR_OK; + s = g_string_sized_new(512); + g_string_append_printf(s, ";Rate: %"PRIu64"\n", ctx->samplerate); + g_string_append_printf(s, ";Channels: %d\n", num_enabled_channels); + g_string_append_printf(s, ";EnabledChannels: -1\n"); + g_string_append_printf(s, ";Compressed: true\n"); + g_string_append_printf(s, ";CursorEnabled: false\n"); + + return s; } -static int event(struct sr_output *o, int event_type, uint8_t **data_out, - uint64_t *length_out) +static int receive(struct sr_output *o, const struct sr_datafeed_packet *packet, + GString **out) { struct context *ctx; + const struct sr_datafeed_meta *meta; + const struct sr_datafeed_logic *logic; + const struct sr_config *src; + GSList *l; + unsigned int i, j; + uint8_t c; + *out = NULL; + if (!o || !o->sdi) + return SR_ERR_ARG; ctx = o->internal; - if (ctx && event_type == SR_DF_END) { - g_string_free(ctx->header, TRUE); - g_free(o->internal); - o->internal = NULL; + switch (packet->type) { + case SR_DF_META: + meta = packet->payload; + for (l = meta->config; l; l = l->next) { + src = l->data; + if (src->key == SR_CONF_SAMPLERATE) + ctx->samplerate = g_variant_get_uint64(src->data); + } + break; + case SR_DF_LOGIC: + logic = packet->payload; + if (ctx->num_samples == 0) { + /* First logic packet in the feed. */ + *out = gen_header(o->sdi, ctx); + } else + *out = g_string_sized_new(512); + for (i = 0; i <= logic->length - logic->unitsize; i += logic->unitsize) { + for (j = 0; j < logic->unitsize; j++) { + /* The OLS format wants the samples presented MSB first. */ + c = *((uint8_t *)logic->data + i + logic->unitsize - 1 - j); + g_string_append_printf(*out, "%02x", c); + } + g_string_append_printf(*out, "@%"PRIu64"\n", ctx->num_samples++); + } + break; } - *data_out = NULL; - *length_out = 0; - return SR_OK; } -static int data(struct sr_output *o, const uint8_t *data_in, - uint64_t length_in, uint8_t **data_out, uint64_t *length_out) +static int cleanup(struct sr_output *o) { - GString *out; struct context *ctx; - uint64_t sample; - unsigned int i; + + if (!o || !o->sdi) + return SR_ERR_ARG; ctx = o->internal; - if (ctx->header) { - /* first data packet */ - out = ctx->header; - ctx->header = NULL; - } else - out = g_string_sized_new(512); - - for (i = 0; i <= length_in - ctx->unitsize; i += ctx->unitsize) { - sample = 0; - memcpy(&sample, data_in + i, ctx->unitsize); - g_string_append_printf(out, "%08x@%"PRIu64"\n", - (uint32_t) sample, ctx->num_samples++); - } - *data_out = (uint8_t *)out->str; - *length_out = out->len; - g_string_free(out, FALSE); + g_free(ctx); + o->internal = NULL; return SR_OK; } @@ -139,8 +151,7 @@ static int data(struct sr_output *o, const uint8_t *data_in, SR_PRIV struct sr_output_format output_ols = { .id = "ols", .description = "OpenBench Logic Sniffer", - .df_type = SR_DF_LOGIC, .init = init, - .data = data, - .event = event, + .receive = receive, + .cleanup = cleanup };