+/*
+ * Primitive operations to handle sample sets:
+ * - Keep a buffer for datafeed submission, capable of holding many
+ * samples (reduces call overhead, improves throughput).
+ * - Have a "current sample set" pointer reference one position in that
+ * large samples buffer.
+ * - Clear the current sample set before text line inspection, then set
+ * the bits which are found active in the current line of text input.
+ * Phrase the API such that call sites can be kept simple. Advance to
+ * the next sample set between lines, flush the larger buffer as needed
+ * (when it is full, or upon EOF).
+ */
+
+static void clear_logic_samples(struct context *inc)
+{
+ inc->sample_buffer = &inc->datafeed_buffer[inc->datafeed_buf_fill];
+ memset(inc->sample_buffer, 0, inc->sample_unit_size);
+}
+
+static void set_logic_level(struct context *inc, size_t ch_idx, int on)
+{
+ size_t byte_idx, bit_idx;
+ uint8_t bit_mask;
+
+ if (ch_idx >= inc->num_channels)
+ return;
+ if (!on)
+ return;
+
+ byte_idx = ch_idx / 8;
+ bit_idx = ch_idx % 8;
+ bit_mask = 1 << bit_idx;
+ inc->sample_buffer[byte_idx] |= bit_mask;
+}
+
+static int flush_logic_samples(const struct sr_input *in)
+{
+ struct context *inc;
+ struct sr_datafeed_packet packet;
+ struct sr_datafeed_logic logic;
+ int rc;
+
+ inc = in->priv;
+ if (!inc->datafeed_buf_fill)
+ return SR_OK;
+
+ memset(&packet, 0, sizeof(packet));
+ memset(&logic, 0, sizeof(logic));
+ packet.type = SR_DF_LOGIC;
+ packet.payload = &logic;
+ logic.unitsize = inc->sample_unit_size;
+ logic.length = inc->datafeed_buf_fill;
+ logic.data = inc->datafeed_buffer;
+
+ rc = sr_session_send(in->sdi, &packet);
+ if (rc != SR_OK)
+ return rc;
+
+ inc->datafeed_buf_fill = 0;
+ return SR_OK;
+}
+
+static int queue_logic_samples(const struct sr_input *in)
+{
+ struct context *inc;
+ int rc;
+
+ inc = in->priv;
+
+ inc->datafeed_buf_fill += inc->sample_unit_size;
+ if (inc->datafeed_buf_fill == inc->datafeed_buf_size) {
+ rc = flush_logic_samples(in);
+ if (rc != SR_OK)
+ return rc;
+ }
+ return SR_OK;
+}
+