X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Finput%2Flogicport.c;h=354330ab453e9f800d5926cc2df081a59906e3c2;hb=HEAD;hp=40921be5220810dcc46464d87e8b531351b58d4a;hpb=e1b115bd4d5ed195b46daf604c35a33c7a760533;p=libsigrok.git diff --git a/src/input/logicport.c b/src/input/logicport.c index 40921be5..ea4cb39b 100644 --- a/src/input/logicport.c +++ b/src/input/logicport.c @@ -60,10 +60,6 @@ #include #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 @@ -141,15 +137,8 @@ static struct signal_group_desc *alloc_signal_group(const char *name) struct signal_group_desc *desc; desc = g_malloc0(sizeof(*desc)); - if (!desc) - return NULL; - if (name) { + if (name) desc->name = g_strdup(name); - if (!desc->name) { - g_free(desc); - return NULL; - } - } return desc; } @@ -162,33 +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 (!cg) - return NULL; - if (name && *name) { - cg->name = g_strdup(name); - if (!cg->name) { - g_free(cg); - return NULL; - } - } - 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) { @@ -296,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; @@ -342,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) { @@ -366,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); @@ -429,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; @@ -452,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; @@ -480,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; @@ -790,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; @@ -806,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) @@ -822,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; @@ -837,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; @@ -852,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; @@ -869,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; @@ -1001,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); @@ -1027,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; @@ -1036,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; @@ -1055,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); @@ -1068,10 +1029,7 @@ static int init(struct sr_input *in, GHashTable *options) (void)options; in->sdi = g_malloc0(sizeof(*in->sdi)); - inc = g_malloc0(sizeof(*inc)); - if (!inc) - return SR_ERR_MALLOC; in->priv = inc; return SR_OK; @@ -1158,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]); @@ -1173,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; }