#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
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)
{
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;
inc = in->priv;
+ 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];
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 = UINT64_C(1);
for (idx = 0; idx < inc->channel_count; idx++, mask <<= 1) {
if (!(desc->mask & mask))
}
}
+ 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;
{
struct context *inc;
struct sr_datafeed_packet packet;
- struct sr_datafeed_meta meta;
- struct sr_config *src;
struct sr_datafeed_logic logic;
int rc;
}
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;
* 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;
* 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]);
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;
}