+/*
+ * Analog devices can have samples of different types. Since each
+ * packet has only one meaning, it is restricted to having at most one
+ * type of data. So they can send multiple packets for a single sample.
+ * To further complicate things, they can send multiple samples in a
+ * single packet.
+ *
+ * So we need to pull any channels of interest out of a packet and save
+ * them until we have complete samples to output. Some devices make this
+ * simple by sending DF_FRAME_BEGIN/DF_FRAME_END packets, the latter of which
+ * signals the end of a set of samples, so we can dump things there.
+ *
+ * At least one driver (the demo driver) sends packets that contain parts of
+ * multiple samples without wrapping them in DF_FRAME. Possibly this driver
+ * is buggy, but it's also the standard for testing, so it has to be supported
+ * as is.
+ *
+ * Many assumptions about the "shape" of the data here:
+ *
+ * All of the data for a channel is assumed to be in one frame;
+ * otherwise the data in the second packet will overwrite the data in
+ * the first packet.
+ */
+static void process_analog(struct context *ctx,
+ const struct sr_datafeed_analog *analog)
+{
+ 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)