]> sigrok.org Git - libsigrok.git/blobdiff - session_driver.c
Add struct sr_session parameter to all session source backends.
[libsigrok.git] / session_driver.c
index 5041092b4c5e760cc53ce3346c9ba42f6ead3b1b..9120ea14575b4f2e71fbfa3d0fcdfc28100b8467 100644 (file)
 #include "libsigrok.h"
 #include "libsigrok-internal.h"
 
-/* Message logging helpers with subsystem-specific prefix string. */
-#define LOG_PREFIX "virtual-session: "
-#define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args)
-#define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args)
-#define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args)
-#define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args)
-#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args)
-#define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args)
+#define LOG_PREFIX "virtual-session"
 
 /* size of payloads sent across the session bus */
 /** @cond PRIVATE */
 #define CHUNKSIZE (512 * 1024)
 /** @endcond */
 
+SR_PRIV struct sr_dev_driver session_driver_info;
+static struct sr_dev_driver *di = &session_driver_info;
+
 struct session_vdev {
        char *sessionfile;
        char *capturefile;
@@ -48,15 +44,15 @@ struct session_vdev {
        int bytes_read;
        uint64_t samplerate;
        int unitsize;
-       int num_probes;
+       int num_channels;
        int cur_chunk;
+       gboolean finished;
 };
 
-static GSList *dev_insts = NULL;
 static const int hwcaps[] = {
        SR_CONF_CAPTUREFILE,
        SR_CONF_CAPTURE_UNITSIZE,
-       0,
+       SR_CONF_SAMPLERATE,
 };
 
 static int receive_data(int fd, int revents, void *cb_data)
@@ -66,7 +62,6 @@ static int receive_data(int fd, int revents, void *cb_data)
        struct sr_datafeed_packet packet;
        struct sr_datafeed_logic logic;
        struct zip_stat zs;
-       GSList *l;
        int ret, got_data;
        char capturefile[16];
        void *buf;
@@ -74,13 +69,10 @@ static int receive_data(int fd, int revents, void *cb_data)
        (void)fd;
        (void)revents;
 
+       sdi = cb_data;
        got_data = FALSE;
-       for (l = dev_insts; l; l = l->next) {
-               sdi = l->data;
-               if (!(vdev = sdi->priv))
-                       /* Already done with this instance. */
-                       continue;
-
+       vdev = sdi->priv;
+       if (!vdev->finished) {
                if (!vdev->capfile) {
                        /* No capture file opened yet, or finished with the last
                         * chunked one. */
@@ -120,10 +112,8 @@ static int receive_data(int fd, int revents, void *cb_data)
                                        sr_dbg("Opened %s.", capturefile);
                                } else {
                                        /* We got all the chunks, finish up. */
-                                       g_free(vdev->capturefile);
-                                       g_free(vdev);
-                                       sdi->priv = NULL;
-                                       continue;
+                                       vdev->finished = TRUE;
+                                       return TRUE;
                                }
                        }
                }
@@ -133,8 +123,12 @@ static int receive_data(int fd, int revents, void *cb_data)
                        return FALSE;
                }
 
-               ret = zip_fread(vdev->capfile, buf, CHUNKSIZE);
+               ret = zip_fread(vdev->capfile, buf,
+                               CHUNKSIZE / vdev->unitsize * vdev->unitsize);
                if (ret > 0) {
+                       if (ret % vdev->unitsize != 0)
+                               sr_warn("Read size %d not a multiple of the"
+                                       " unit size %d.", ret, vdev->unitsize);
                        got_data = TRUE;
                        packet.type = SR_DF_LOGIC;
                        packet.payload = &logic;
@@ -142,16 +136,14 @@ static int receive_data(int fd, int revents, void *cb_data)
                        logic.unitsize = vdev->unitsize;
                        logic.data = buf;
                        vdev->bytes_read += ret;
-                       sr_session_send(cb_data, &packet);
+                       sr_session_send(sdi, &packet);
                } else {
                        /* done with this capture file */
                        zip_fclose(vdev->capfile);
                        vdev->capfile = NULL;
                        if (vdev->cur_chunk == 0) {
                                /* It was the only file. */
-                               g_free(vdev->capturefile);
-                               g_free(vdev);
-                               sdi->priv = NULL;
+                               vdev->finished = TRUE;
                        } else {
                                /* There might be more chunks, so don't fall through
                                 * to the SR_DF_END here. */
@@ -164,8 +156,8 @@ static int receive_data(int fd, int revents, void *cb_data)
 
        if (!got_data) {
                packet.type = SR_DF_END;
-               sr_session_send(cb_data, &packet);
-               sr_session_source_remove(-1);
+               sr_session_send(sdi, &packet);
+               sr_session_source_remove(sdi->session, -1);
        }
 
        return TRUE;
@@ -175,41 +167,54 @@ static int receive_data(int fd, int revents, void *cb_data)
 
 static int init(struct sr_context *sr_ctx)
 {
-       (void)sr_ctx;
-
-       return SR_OK;
+       return std_init(sr_ctx, di, LOG_PREFIX);
 }
 
-static int cleanup(void)
+static int dev_clear(void)
 {
+       struct drv_context *drvc;
        GSList *l;
 
-       for (l = dev_insts; l; l = l->next)
+       drvc = di->priv;
+       for (l = drvc->instances; l; l = l->next)
                sr_dev_inst_free(l->data);
-       g_slist_free(dev_insts);
-       dev_insts = NULL;
+       g_slist_free(drvc->instances);
+       drvc->instances = NULL;
 
        return SR_OK;
 }
 
 static int dev_open(struct sr_dev_inst *sdi)
 {
-       if (!(sdi->priv = g_try_malloc0(sizeof(struct session_vdev)))) {
-               sr_err("Device context malloc failed.");
-               return SR_ERR_MALLOC;
-       }
+       struct drv_context *drvc;
+       struct session_vdev *vdev;
 
-       dev_insts = g_slist_append(dev_insts, sdi);
+       drvc = di->priv;
+       vdev = g_malloc0(sizeof(struct session_vdev));
+       sdi->priv = vdev;
+       drvc->instances = g_slist_append(drvc->instances, sdi);
+
+       return SR_OK;
+}
+
+static int dev_close(struct sr_dev_inst *sdi)
+{
+       const struct session_vdev *const vdev = sdi->priv;
+       g_free(vdev->sessionfile);
+       g_free(vdev->capturefile);
+
+       g_free(sdi->priv);
+       sdi->priv = NULL;
 
        return SR_OK;
 }
 
 static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
-               const struct sr_probe_group *probe_group)
+               const struct sr_channel_group *cg)
 {
        struct session_vdev *vdev;
 
-       (void)probe_group;
+       (void)cg;
 
        switch (id) {
        case SR_CONF_SAMPLERATE:
@@ -227,11 +232,11 @@ static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
 }
 
 static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
-               const struct sr_probe_group *probe_group)
+               const struct sr_channel_group *cg)
 {
        struct session_vdev *vdev;
 
-       (void)probe_group;
+       (void)cg;
 
        vdev = sdi->priv;
 
@@ -241,18 +246,20 @@ static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
                sr_info("Setting samplerate to %" PRIu64 ".", vdev->samplerate);
                break;
        case SR_CONF_SESSIONFILE:
+               g_free(vdev->sessionfile);
                vdev->sessionfile = g_strdup(g_variant_get_string(data, NULL));
                sr_info("Setting sessionfile to '%s'.", vdev->sessionfile);
                break;
        case SR_CONF_CAPTUREFILE:
+               g_free(vdev->capturefile);
                vdev->capturefile = g_strdup(g_variant_get_string(data, NULL));
                sr_info("Setting capturefile to '%s'.", vdev->capturefile);
                break;
        case SR_CONF_CAPTURE_UNITSIZE:
                vdev->unitsize = g_variant_get_uint64(data);
                break;
-       case SR_CONF_CAPTURE_NUM_PROBES:
-               vdev->num_probes = g_variant_get_uint64(data);
+       case SR_CONF_NUM_LOGIC_CHANNELS:
+               vdev->num_channels = g_variant_get_uint64(data);
                break;
        default:
                return SR_ERR_NA;
@@ -262,10 +269,10 @@ static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
 }
 
 static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
-               const struct sr_probe_group *probe_group)
+               const struct sr_channel_group *cg)
 {
        (void)sdi;
-       (void)probe_group;
+       (void)cg;
 
        switch (key) {
        case SR_CONF_DEVICE_OPTIONS:
@@ -284,7 +291,12 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
        struct session_vdev *vdev;
        int ret;
 
+       (void)cb_data;
+
        vdev = sdi->priv;
+       vdev->bytes_read = 0;
+       vdev->cur_chunk = 0;
+       vdev->finished = FALSE;
 
        sr_info("Opening archive %s file %s", vdev->sessionfile,
                vdev->capturefile);
@@ -296,10 +308,10 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
        }
 
        /* Send header packet to the session bus. */
-       std_session_send_df_header(cb_data, LOG_PREFIX);
+       std_session_send_df_header(sdi, LOG_PREFIX);
 
        /* freewheeling source */
-       sr_session_source_add(-1, 0, 0, receive_data, cb_data);
+       sr_session_source_add(sdi->session, -1, 0, 0, receive_data, (void *)sdi);
 
        return SR_OK;
 }
@@ -310,15 +322,15 @@ SR_PRIV struct sr_dev_driver session_driver = {
        .longname = "Session-emulating driver",
        .api_version = 1,
        .init = init,
-       .cleanup = cleanup,
+       .cleanup = dev_clear,
        .scan = NULL,
        .dev_list = NULL,
-       .dev_clear = NULL,
+       .dev_clear = dev_clear,
        .config_get = config_get,
        .config_set = config_set,
        .config_list = config_list,
        .dev_open = dev_open,
-       .dev_close = NULL,
+       .dev_close = dev_close,
        .dev_acquisition_start = dev_acquisition_start,
        .dev_acquisition_stop = NULL,
        .priv = NULL,