]> sigrok.org Git - libsigrok.git/blobdiff - src/input/logicport.c
output/csv: use intermediate time_t var, silence compiler warning
[libsigrok.git] / src / input / logicport.c
index 99ad2c84cce6ea446ff83c0d7cf5aed29f1d9a79..ea4cb39b252bb406aaf31bcb4a343128ed2dab9b 100644 (file)
 #include <libsigrok/libsigrok.h>
 #include "libsigrok-internal.h"
 
-/* TODO: Move these helpers to some library API routine group. */
-struct sr_channel_group *sr_channel_group_new(const char *name, void *priv);
-void sr_channel_group_free(struct sr_channel_group *cg);
-
 #define LOG_PREFIX     "input/logicport"
 
 #define MAX_CHANNELS   34
@@ -155,26 +151,6 @@ static void free_signal_group(struct signal_group_desc *desc)
        g_free(desc);
 }
 
-struct sr_channel_group *sr_channel_group_new(const char *name, void *priv)
-{
-       struct sr_channel_group *cg;
-
-       cg = g_malloc0(sizeof(*cg));
-       if (name && *name)
-               cg->name = g_strdup(name);
-       cg->priv = priv;
-
-       return cg;
-}
-
-void sr_channel_group_free(struct sr_channel_group *cg)
-{
-       if (!cg)
-               return;
-       g_free(cg->name);
-       g_slist_free(cg->channels);
-}
-
 /* Wrapper for GDestroyNotify compatibility. */
 static void sg_free(void *p)
 {
@@ -282,7 +258,7 @@ static int process_signal_group(struct context *inc, char **args)
 {
        char *name, *wires;
        struct signal_group_desc *desc;
-       uint64_t bit_tmpl, bit_mask;
+       uint64_t bit_mask;
        char *p, *endp;
        size_t idx;
 
@@ -328,16 +304,7 @@ static int process_signal_group(struct context *inc, char **args)
                return SR_ERR_MALLOC;
        inc->signal_groups = g_slist_append(inc->signal_groups, desc);
 
-       /*
-        * Determine the bit mask of the group's signals' indices.
-        *
-        * Implementation note: Use a "template" for a single bit, to
-        * avoid portability issues with upper bits. Without this 64bit
-        * intermediate variable, I would not know how to phrase e.g.
-        * (1ULL << 33) in portable, robust, and easy to maintain ways
-        * on all platforms that are supported by sigrok.
-        */
-       bit_tmpl = 1UL << 0;
+       /* Determine the bit mask of the group's signals' indices. */
        bit_mask = 0;
        p = wires;
        while (p && *p) {
@@ -352,7 +319,7 @@ static int process_signal_group(struct context *inc, char **args)
                        p++;
                if (idx >= MAX_CHANNELS)
                        return SR_ERR_DATA;
-               bit_mask = bit_tmpl << idx;
+               bit_mask = UINT64_C(1) << idx;
                if (inc->wires_grouped & bit_mask) {
                        sr_warn("Not adding signal at index %zu to group %s (multiple assignments)",
                                idx, name);
@@ -415,7 +382,7 @@ static int process_enabled_channels(struct context *inc, char **flags)
        if (count != inc->channel_count)
                return SR_ERR_DATA;
        bits = 0;
-       mask = 1UL << 0;
+       mask = UINT64_C(1);
        for (idx = 0; idx < inc->channel_count; idx++, mask <<= 1) {
                if (strcmp(flags[idx], "True") == 0)
                        bits |= mask;
@@ -438,7 +405,7 @@ static int process_inverted_channels(struct context *inc, char **flags)
        if (count != inc->channel_count)
                return SR_ERR_DATA;
        bits = 0;
-       mask = 1UL << 0;
+       mask = UINT64_C(1);
        for (idx = 0; idx < inc->channel_count; idx++, mask <<= 1) {
                if (strcmp(flags[idx], "True") == 0)
                        bits |= mask;
@@ -466,7 +433,7 @@ static int process_sample_line(struct context *inc, char **values)
                return SR_ERR_DATA;
        entry = &inc->sample_data_queue[inc->sample_lines_read];
        entry->bits = 0;
-       mask = 1UL << 0;
+       mask = UINT64_C(1);
        for (idx = 0; idx < inc->channel_count; idx++, mask <<= 1) {
                if (strcmp(values[idx], "1") == 0)
                        entry->bits |= mask;
@@ -776,8 +743,8 @@ static int parse_header(struct sr_input *in)
        return SR_OK;
 }
 
-/* Create sigrok channels and groups. Allocate the session feed buffer. */
-static int create_channels_groups_buffer(struct sr_input *in)
+/* Create sigrok channels and groups. */
+static int create_channels_groups(struct sr_input *in)
 {
        struct context *inc;
        uint64_t mask;
@@ -792,7 +759,10 @@ static int create_channels_groups_buffer(struct sr_input *in)
 
        inc = in->priv;
 
-       mask = 1UL << 0;
+       if (inc->channels)
+               return SR_OK;
+
+       mask = UINT64_C(1);
        for (idx = 0; idx < inc->channel_count; idx++, mask <<= 1) {
                name = inc->signal_names[idx];
                if (!name || !*name)
@@ -808,11 +778,10 @@ static int create_channels_groups_buffer(struct sr_input *in)
        sdi = in->sdi;
        for (l = inc->signal_groups; l; l = l->next) {
                desc = l->data;
-               cg = sr_channel_group_new(desc->name, NULL);
+               cg = sr_channel_group_new(sdi, desc->name, NULL);
                if (!cg)
                        return SR_ERR_MALLOC;
-               sdi->channel_groups = g_slist_append(sdi->channel_groups, cg);
-               mask = 1UL << 0;
+               mask = UINT64_C(1);
                for (idx = 0; idx < inc->channel_count; idx++, mask <<= 1) {
                        if (!(desc->mask & mask))
                                continue;
@@ -823,6 +792,16 @@ static int create_channels_groups_buffer(struct sr_input *in)
                }
        }
 
+       return SR_OK;
+}
+
+/* Allocate the session feed buffer. */
+static int create_feed_buffer(struct sr_input *in)
+{
+       struct context *inc;
+
+       inc = in->priv;
+
        inc->unitsize = (inc->channel_count + 7) / 8;
        inc->samples_per_chunk = CHUNK_SIZE / inc->unitsize;
        inc->samples_in_buffer = 0;
@@ -838,8 +817,6 @@ static int send_buffer(struct sr_input *in)
 {
        struct context *inc;
        struct sr_datafeed_packet packet;
-       struct sr_datafeed_meta meta;
-       struct sr_config *src;
        struct sr_datafeed_logic logic;
        int rc;
 
@@ -855,14 +832,8 @@ static int send_buffer(struct sr_input *in)
        }
 
        if (inc->sample_rate && !inc->rate_sent) {
-               packet.type = SR_DF_META;
-               packet.payload = &meta;
-               src = sr_config_new(SR_CONF_SAMPLERATE,
+               rc = sr_session_send_meta(in->sdi, SR_CONF_SAMPLERATE,
                        g_variant_new_uint64(inc->sample_rate));
-               meta.config = g_slist_append(NULL, src);
-               rc = sr_session_send(in->sdi, &packet);
-               g_slist_free(meta.config);
-               sr_config_free(src);
                if (rc)
                        return rc;
                inc->rate_sent = TRUE;
@@ -987,7 +958,7 @@ static int prepare_session_feed(struct sr_input *in)
         * - If there are any signal groups, put all signals into
         *   an anonymous group that are not part of another group.
         */
-       inc->wires_all_mask = 1UL << 0;
+       inc->wires_all_mask = UINT64_C(1);
        inc->wires_all_mask <<= inc->channel_count;
        inc->wires_all_mask--;
        sr_dbg("all wires mask: 0x%" PRIx64 ".", inc->wires_all_mask);
@@ -1013,7 +984,10 @@ static int prepare_session_feed(struct sr_input *in)
         * header to the session. Optionally send the sample
         * rate before sample data will be sent.
         */
-       rc = create_channels_groups_buffer(in);
+       rc = create_channels_groups(in);
+       if (rc)
+               return rc;
+       rc = create_feed_buffer(in);
        if (rc)
                return rc;
 
@@ -1022,7 +996,7 @@ static int prepare_session_feed(struct sr_input *in)
        return SR_OK;
 }
 
-static int format_match(GHashTable *metadata)
+static int format_match(GHashTable *metadata, unsigned int *confidence)
 {
        GString *buf, *tmpbuf;
        int rc;
@@ -1041,6 +1015,7 @@ static int format_match(GHashTable *metadata)
        if (rc == SR_OK && version && build) {
                sr_dbg("Looks like a LogicProbe project, version %s, build %s.",
                        version, build);
+               *confidence = 1;
        }
        g_string_free(tmpbuf, TRUE);
 
@@ -1141,7 +1116,8 @@ static void cleanup(struct sr_input *in)
         * and scalars, so that re-runs start out fresh again.
         */
        g_free(inc->sw_version);
-       g_string_free(inc->cont_buff, TRUE);
+       if (inc->cont_buff)
+               g_string_free(inc->cont_buff, TRUE);
        g_free(inc->sample_data_queue);
        for (idx = 0; idx < inc->channel_count; idx++)
                g_free(inc->wire_names[idx]);
@@ -1156,13 +1132,21 @@ static void cleanup(struct sr_input *in)
 static int reset(struct sr_input *in)
 {
        struct context *inc;
+       GSList *channels;
 
        inc = in->priv;
+
+       /*
+        * The input module's .reset() routine clears the 'inc' context,
+        * but 'in' is kept which contains channel groups which reference
+        * channels. Since we cannot re-create the channels (applications
+        * don't expect us to, see bug #1215), make sure to keep the
+        * channels across the reset operation.
+        */
+       channels = inc->channels;
+       inc->channels = NULL;
        cleanup(in);
-       inc->ch_feed_prep = FALSE;
-       inc->header_sent = FALSE;
-       inc->rate_sent = FALSE;
-       g_string_truncate(in->buf, 0);
+       inc->channels = channels;
 
        return SR_OK;
 }