+ int ret;
+ size_t num_rcvd_ch, num_have_ch;
+ size_t idx_have, idx_smpl, idx_rcvd;
+ size_t idx_send;
+ struct sr_analog_meaning *meaning;
+ GSList *l;
+ float *fdata = NULL;
+ struct sr_channel *ch;
+
+ if (!ctx->analog_samples) {
+ ctx->analog_samples = g_malloc(analog->num_samples
+ * sizeof(float) * ctx->num_analog_channels);
+ if (!ctx->num_samples)
+ ctx->num_samples = analog->num_samples;
+ }
+ if (ctx->num_samples != analog->num_samples)
+ sr_warn("Expecting %u analog samples, got %u.",
+ ctx->num_samples, analog->num_samples);
+
+ meaning = analog->meaning;
+ num_rcvd_ch = g_slist_length(meaning->channels);
+ ctx->channels_seen += num_rcvd_ch;
+ sr_dbg("Processing packet of %zu analog channels", num_rcvd_ch);
+ fdata = g_malloc(analog->num_samples * num_rcvd_ch * sizeof(float));
+ if ((ret = sr_analog_to_float(analog, fdata)) != SR_OK)
+ sr_warn("Problems converting data to floating point values.");
+
+ num_have_ch = ctx->num_analog_channels + ctx->num_logic_channels;
+ idx_send = 0;
+ for (idx_have = 0; idx_have < num_have_ch; idx_have++) {
+ if (ctx->channels[idx_have].ch->type != SR_CHANNEL_ANALOG)
+ continue;
+ sr_dbg("Looking for channel %s",
+ ctx->channels[idx_have].ch->name);
+ for (l = meaning->channels, idx_rcvd = 0; l; l = l->next, idx_rcvd++) {
+ ch = l->data;
+ sr_dbg("Checking %s", ch->name);
+ if (ctx->channels[idx_have].ch != ch)
+ continue;
+ if (ctx->label_do && !ctx->label_names) {
+ sr_analog_unit_to_string(analog,
+ &ctx->channels[idx_have].label);
+ }
+ for (idx_smpl = 0; idx_smpl < analog->num_samples; idx_smpl++)
+ ctx->analog_samples[idx_smpl * ctx->num_analog_channels + idx_send] = fdata[idx_smpl * num_rcvd_ch + idx_rcvd];
+ break;
+ }
+ idx_send++;
+ }
+ g_free(fdata);
+}
+
+/*
+ * We treat logic packets the same as analog packets, though it's not
+ * strictly required. This allows us to process mixed signals properly.
+ */
+static void process_logic(struct context *ctx,
+ const struct sr_datafeed_logic *logic)
+{
+ unsigned int i, j, ch, num_samples;
+ int idx;
+ uint8_t *sample;
+
+ num_samples = logic->length / logic->unitsize;
+ ctx->channels_seen += ctx->logic_channel_count;
+ sr_dbg("Logic packet had %d channels", logic->unitsize * 8);
+ if (!ctx->logic_samples) {
+ ctx->logic_samples = g_malloc(num_samples * ctx->num_logic_channels);
+ if (!ctx->num_samples)
+ ctx->num_samples = num_samples;
+ }
+ if (ctx->num_samples != num_samples)
+ sr_warn("Expecting %u samples, got %u",
+ ctx->num_samples, num_samples);
+
+ for (j = ch = 0; ch < ctx->num_logic_channels; j++) {
+ if (ctx->channels[j].ch->type == SR_CHANNEL_LOGIC) {
+ for (i = 0; i < num_samples; i++) {
+ sample = logic->data + i * logic->unitsize;
+ idx = ctx->channels[j].ch->index;
+ if (ctx->label_do && !ctx->label_names)
+ ctx->channels[j].label = "logic";
+ ctx->logic_samples[i * ctx->num_logic_channels + ch] = sample[idx / 8] & (1 << (idx % 8));
+ }
+ ch++;
+ }
+ }
+}
+
+static void dump_saved_values(struct context *ctx, GString **out)
+{
+ unsigned int i, j, analog_size, num_channels;
+ float *analog_sample, value;
+ uint8_t *logic_sample;
+
+ /* If we haven't seen samples we're expecting, skip them. */
+ if ((ctx->num_analog_channels && !ctx->analog_samples) ||
+ (ctx->num_logic_channels && !ctx->logic_samples)) {
+ sr_warn("Discarding partial packet");