X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fsession_driver.c;h=6befa780ece2b88492abc699a2ab8b266a3168c1;hb=2c24077466a299ead689c90f01f55f6d86c7386b;hp=62b16986e4afa264419fb0263e8381c2afdb176c;hpb=68ac991dbaa05ab91459419400b21b93f02d0e76;p=libsigrok.git diff --git a/src/session_driver.c b/src/session_driver.c index 62b16986..6befa780 100644 --- a/src/session_driver.c +++ b/src/session_driver.c @@ -17,13 +17,14 @@ * along with this program. If not, see . */ +#include #include #include #include #include #include #include -#include "libsigrok.h" +#include #include "libsigrok-internal.h" #define LOG_PREFIX "virtual-session" @@ -34,7 +35,6 @@ /** @endcond */ SR_PRIV struct sr_dev_driver session_driver_info; -static struct sr_dev_driver *di = &session_driver_info; struct session_vdev { char *sessionfile; @@ -52,12 +52,13 @@ struct session_vdev { static const uint32_t devopts[] = { SR_CONF_CAPTUREFILE | SR_CONF_SET, SR_CONF_CAPTURE_UNITSIZE | SR_CONF_GET | SR_CONF_SET, + SR_CONF_NUM_LOGIC_CHANNELS | SR_CONF_SET, SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET, + SR_CONF_SESSIONFILE | SR_CONF_SET, }; -static int receive_data(int fd, int revents, void *cb_data) +static gboolean stream_session_data(struct sr_dev_inst *sdi) { - struct sr_dev_inst *sdi; struct session_vdev *vdev; struct sr_datafeed_packet packet; struct sr_datafeed_logic logic; @@ -66,116 +67,128 @@ static int receive_data(int fd, int revents, void *cb_data) char capturefile[16]; void *buf; - (void)fd; - (void)revents; - - sdi = cb_data; got_data = FALSE; vdev = sdi->priv; - if (!vdev->finished) { - if (!vdev->capfile) { - /* No capture file opened yet, or finished with the last - * chunked one. */ - if (vdev->cur_chunk == 0) { - /* capturefile is always the unchunked base name. */ - if (zip_stat(vdev->archive, vdev->capturefile, 0, &zs) != -1) { - /* No chunks, just a single capture file. */ - vdev->cur_chunk = 0; - if (!(vdev->capfile = zip_fopen(vdev->archive, - vdev->capturefile, 0))) - return FALSE; - sr_dbg("Opened %s.", vdev->capturefile); - } else { - /* Try as first chunk filename. */ - snprintf(capturefile, 15, "%s-1", vdev->capturefile); - if (zip_stat(vdev->archive, capturefile, 0, &zs) != -1) { - vdev->cur_chunk = 1; - if (!(vdev->capfile = zip_fopen(vdev->archive, - capturefile, 0))) - return FALSE; - sr_dbg("Opened %s.", capturefile); - } else { - sr_err("No capture file '%s' in " "session file '%s'.", - vdev->capturefile, vdev->sessionfile); - return FALSE; - } - } + if (!vdev->capfile) { + /* No capture file opened yet, or finished with the last + * chunked one. */ + if (vdev->cur_chunk == 0) { + /* capturefile is always the unchunked base name. */ + if (zip_stat(vdev->archive, vdev->capturefile, 0, &zs) != -1) { + /* No chunks, just a single capture file. */ + vdev->cur_chunk = 0; + if (!(vdev->capfile = zip_fopen(vdev->archive, + vdev->capturefile, 0))) + return FALSE; + sr_dbg("Opened %s.", vdev->capturefile); } else { - /* Capture data is chunked, advance to the next chunk. */ - vdev->cur_chunk++; - snprintf(capturefile, 15, "%s-%d", vdev->capturefile, - vdev->cur_chunk); + /* Try as first chunk filename. */ + snprintf(capturefile, 15, "%s-1", vdev->capturefile); if (zip_stat(vdev->archive, capturefile, 0, &zs) != -1) { + vdev->cur_chunk = 1; if (!(vdev->capfile = zip_fopen(vdev->archive, capturefile, 0))) return FALSE; sr_dbg("Opened %s.", capturefile); } else { - /* We got all the chunks, finish up. */ - vdev->finished = TRUE; - return TRUE; + sr_err("No capture file '%s' in " "session file '%s'.", + vdev->capturefile, vdev->sessionfile); + return FALSE; } } - } - - if (!(buf = g_try_malloc(CHUNKSIZE))) { - sr_err("%s: buf malloc failed", __func__); - return FALSE; - } - - 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; - logic.length = ret; - logic.unitsize = vdev->unitsize; - logic.data = buf; - vdev->bytes_read += ret; - 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. */ - vdev->finished = TRUE; + /* Capture data is chunked, advance to the next chunk. */ + vdev->cur_chunk++; + snprintf(capturefile, 15, "%s-%d", vdev->capturefile, + vdev->cur_chunk); + if (zip_stat(vdev->archive, capturefile, 0, &zs) != -1) { + if (!(vdev->capfile = zip_fopen(vdev->archive, + capturefile, 0))) + return FALSE; + sr_dbg("Opened %s.", capturefile); } else { - /* There might be more chunks, so don't fall through - * to the SR_DF_END here. */ - g_free(buf); - return TRUE; + /* We got all the chunks, finish up. */ + return FALSE; } } - g_free(buf); } - if (!got_data) { - packet.type = SR_DF_END; + buf = g_malloc(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; + logic.length = ret; + logic.unitsize = vdev->unitsize; + logic.data = buf; + vdev->bytes_read += ret; sr_session_send(sdi, &packet); - sr_session_source_remove(sdi->session, -1); + } else { + /* done with this capture file */ + zip_fclose(vdev->capfile); + vdev->capfile = NULL; + if (vdev->cur_chunk != 0) { + /* There might be more chunks, so don't fall through + * to the SR_DF_END here. */ + got_data = TRUE; + } + } + g_free(buf); + + return got_data; +} + +static int receive_data(int fd, int revents, void *cb_data) +{ + struct sr_dev_inst *sdi; + struct session_vdev *vdev; + struct sr_datafeed_packet packet; + + (void)fd; + (void)revents; + + sdi = cb_data; + vdev = sdi->priv; + + if (!vdev->finished && !stream_session_data(sdi)) + vdev->finished = TRUE; + if (!vdev->finished) + return G_SOURCE_CONTINUE; + + if (vdev->capfile) { + zip_fclose(vdev->capfile); + vdev->capfile = NULL; } + if (vdev->archive) { + zip_discard(vdev->archive); + vdev->archive = NULL; + } + packet.type = SR_DF_END; + packet.payload = NULL; + sr_session_send(sdi, &packet); - return TRUE; + return G_SOURCE_REMOVE; } /* driver callbacks */ -static int init(struct sr_context *sr_ctx) +static int init(struct sr_dev_driver *di, struct sr_context *sr_ctx) { return std_init(sr_ctx, di, LOG_PREFIX); } -static int dev_clear(void) +static int dev_clear(const struct sr_dev_driver *di) { struct drv_context *drvc; GSList *l; - drvc = di->priv; + drvc = di->context; for (l = drvc->instances; l; l = l->next) sr_dev_inst_free(l->data); g_slist_free(drvc->instances); @@ -186,10 +199,12 @@ static int dev_clear(void) static int dev_open(struct sr_dev_inst *sdi) { + struct sr_dev_driver *di; struct drv_context *drvc; struct session_vdev *vdev; - drvc = di->priv; + di = sdi->driver; + drvc = di->context; vdev = g_malloc0(sizeof(struct session_vdev)); sdi->priv = vdev; drvc->instances = g_slist_append(drvc->instances, sdi); @@ -263,7 +278,7 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sd vdev->unitsize = g_variant_get_uint64(data); break; case SR_CONF_NUM_LOGIC_CHANNELS: - vdev->num_channels = g_variant_get_uint64(data); + vdev->num_channels = g_variant_get_int32(data); break; default: return SR_ERR_NA; @@ -320,6 +335,18 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) return SR_OK; } +static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) +{ + struct session_vdev *vdev; + + (void)cb_data; + vdev = sdi->priv; + + vdev->finished = TRUE; + + return SR_OK; +} + /** @private */ SR_PRIV struct sr_dev_driver session_driver = { .name = "virtual-session", @@ -336,6 +363,6 @@ SR_PRIV struct sr_dev_driver session_driver = { .dev_open = dev_open, .dev_close = dev_close, .dev_acquisition_start = dev_acquisition_start, - .dev_acquisition_stop = NULL, - .priv = NULL, + .dev_acquisition_stop = dev_acquisition_stop, + .context = NULL, };