From: Bert Vermeulen Date: Mon, 31 Jan 2011 21:34:14 +0000 (+0100) Subject: implement session loading based on a virtual device driver X-Git-Tag: libsigrok-0.1.0~358 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=7d6588743503514c9de5c4fc8a511e9b0bdad7e6;p=libsigrok.git implement session loading based on a virtual device driver --- diff --git a/Makefile.am b/Makefile.am index a7de7a65..8095ff2c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -28,6 +28,8 @@ libsigrok_la_SOURCES = \ datastore.c \ device.c \ session.c \ + session_file.c \ + session_driver.c \ hwplugin.c \ filter.c \ strutil.c diff --git a/device.c b/device.c index 9e922f05..1079bc3e 100644 --- a/device.c +++ b/device.c @@ -84,17 +84,14 @@ struct sr_device *device_new(struct sr_device_plugin *plugin, int plugin_index, { struct sr_device *device; int i; - char probename[16]; device = g_malloc0(sizeof(struct sr_device)); device->plugin = plugin; device->plugin_index = plugin_index; devices = g_slist_append(devices, device); - for (i = 0; i < num_probes; i++) { - snprintf(probename, 16, "%d", i + 1); - device_probe_add(device, probename); - } + for (i = 0; i < num_probes; i++) + device_probe_add(device, NULL); return device; } @@ -152,10 +149,19 @@ void device_probe_clear(struct sr_device *device, int probenum) void device_probe_add(struct sr_device *device, char *name) { struct probe *p; + char probename[16]; + int probenum; + probenum = g_slist_length(device->probes) + 1; p = g_malloc0(sizeof(struct probe)); - p->index = g_slist_length(device->probes) + 1; + p->index = probenum; p->enabled = TRUE; + if (name) { + p->name = g_strdup(name); + } else { + snprintf(probename, 16, "%d", probenum); + p->name = g_strdup(probename); + } p->name = g_strdup(name); p->trigger = NULL; device->probes = g_slist_append(device->probes, p); @@ -178,6 +184,7 @@ struct probe *probe_find(struct sr_device *device, int probenum) return found_probe; } +/* TODO: return SIGROK_ERR if probenum not found */ void device_probe_name(struct sr_device *device, int probenum, char *name) { struct probe *p; @@ -191,6 +198,7 @@ void device_probe_name(struct sr_device *device, int probenum, char *name) p->name = g_strdup(name); } +/* TODO: return SIGROK_ERR if probenum not found */ void device_trigger_clear(struct sr_device *device) { struct probe *p; @@ -208,6 +216,7 @@ void device_trigger_clear(struct sr_device *device) } } +/* TODO: return SIGROK_ERR if probenum not found */ void device_trigger_set(struct sr_device *device, int probenum, char *trigger) { struct probe *p; @@ -220,4 +229,17 @@ void device_trigger_set(struct sr_device *device, int probenum, char *trigger) g_free(p->trigger); p->trigger = g_strdup(trigger); + +} + +gboolean device_has_hwcap(struct sr_device *device, int hwcap) +{ + int *capabilities, i; + + if ((capabilities = device->plugin->get_capabilities())) + for (i = 0; capabilities[i]; i++) + if (capabilities[i] == hwcap) + return TRUE; + + return FALSE; } diff --git a/session.c b/session.c index 58116e75..ab8e5c13 100644 --- a/session.c +++ b/session.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -29,13 +28,6 @@ /* demo.c */ extern GIOChannel channels[2]; -/* There can only be one session at a time. */ -struct session *session; -int num_sources = 0; -/* These live in hwplugin.c, for the frontend to override. */ -extern source_callback_add source_cb_add; -extern source_callback_remove source_cb_remove; - struct source { int fd; int events; @@ -44,25 +36,14 @@ struct source { void *user_data; }; +/* There can only be one session at a time. */ +struct session *session; +int num_sources = 0; + struct source *sources = NULL; int source_timeout = -1; - - -struct session *session_load(const char *filename) -{ - struct session *session; - - /* Avoid compiler warnings. */ - filename = filename; - - /* TODO: Implement. */ - session = NULL; - - return session; -} - struct session *session_new(void) { session = calloc(1, sizeof(struct session)); @@ -127,30 +108,11 @@ void session_datafeed_callback_add(datafeed_callback callback) g_slist_append(session->datafeed_callbacks, callback); } -int session_start(void) -{ - struct sr_device *device; - GSList *l; - int ret; - - g_message("starting session"); - for (l = session->devices; l; l = l->next) { - device = l->data; - if ((ret = device->plugin->start_acquisition( - device->plugin_index, device)) != SR_OK) - break; - } - - return ret; -} - -void session_run(void) +static void session_run_poll() { GPollFD *fds, my_gpollfd; int ret, i; - g_message("running session"); - session->running = TRUE; fds = NULL; while (session->running) { if (fds) @@ -180,7 +142,7 @@ void session_run(void) * asked for that timeout. */ sources[i].cb(fds[i].fd, fds[i].revents, - sources[i].user_data); + sources[i].user_data); } } } @@ -188,10 +150,44 @@ void session_run(void) } +int session_start(void) +{ + struct sr_device *device; + GSList *l; + int ret; + + g_message("session: starting"); + for (l = session->devices; l; l = l->next) { + device = l->data; + if ((ret = device->plugin->start_acquisition( + device->plugin_index, device)) != SR_OK) + break; + } + + return ret; +} + +void session_run(void) +{ + + g_message("session: running"); + session->running = TRUE; + + /* do we have real sources? */ + if (num_sources == 1 && sources[0].fd == -1) + /* dummy source, freewheel over it */ + while (session->running) + sources[0].cb(-1, 0, sources[0].user_data); + else + /* real sources, use g_poll() main loop */ + session_run_poll(); + +} + void session_halt(void) { - g_message("halting session"); + g_message("session: halting"); session->running = FALSE; } @@ -201,7 +197,7 @@ void session_stop(void) struct sr_device *device; GSList *l; - g_message("stopping session"); + g_message("session: stopping"); session->running = FALSE; for (l = session->devices; l; l = l->next) { device = l->data; @@ -226,109 +222,6 @@ void session_bus(struct sr_device *device, struct sr_datafeed_packet *packet) } } -int session_save(char *filename) -{ - GSList *l, *p, *d; - FILE *meta; - struct sr_device *device; - struct probe *probe; - struct datastore *ds; - struct zip *zipfile; - struct zip_source *versrc, *metasrc, *logicsrc; - int bufcnt, devcnt, tmpfile, ret, error; - char version[1], rawname[16], metafile[32], *newfn, *buf; - - newfn = g_malloc(strlen(filename) + 10); - strcpy(newfn, filename); - if (strstr(filename, ".sigrok") != filename+strlen(filename)-7) - strcat(newfn, ".sigrok"); - - /* Quietly delete it first, libzip wants replace ops otherwise. */ - unlink(newfn); - if (!(zipfile = zip_open(newfn, ZIP_CREATE, &error))) - return SR_ERR; - g_free(newfn); - - /* "version" */ - version[0] = '1'; - if (!(versrc = zip_source_buffer(zipfile, version, 1, 0))) - return SR_ERR; - if (zip_add(zipfile, "version", versrc) == -1) { - g_message("error saving version into zipfile: %s", - zip_strerror(zipfile)); - return SR_ERR; - } - - /* init "metadata" */ - strcpy(metafile, "sigrok-meta-XXXXXX"); - if ((tmpfile = g_mkstemp(metafile)) == -1) - return SR_ERR; - close(tmpfile); - meta = fopen(metafile, "wb"); - fprintf(meta, "sigrok version = %s\n", PACKAGE_VERSION); - /* TODO: save protocol decoders used */ - - /* all datastores in all devices */ - devcnt = 1; - for (l = session->devices; l; l = l->next) { - device = l->data; - /* metadata */ - fprintf(meta, "[device]\n"); - if (device->plugin) - fprintf(meta, "driver = %s\n", device->plugin->name); - - ds = device->datastore; - if (ds) { - /* metadata */ - fprintf(meta, "capturefile = logic-%d\n", devcnt); - for (p = device->probes; p; p = p->next) { - probe = p->data; - if (probe->enabled) { - fprintf(meta, "probe %d", probe->index); - if (probe->name) - fprintf(meta, " name \"%s\"", probe->name); - if (probe->trigger) - fprintf(meta, " trigger \"%s\"", - probe->trigger); - fprintf(meta, "\n"); - } - } - - /* dump datastore into logic-n */ - buf = malloc(ds->num_units * ds->ds_unitsize + - DATASTORE_CHUNKSIZE); - bufcnt = 0; - for (d = ds->chunklist; d; d = d->next) { - memcpy(buf + bufcnt, d->data, - DATASTORE_CHUNKSIZE); - bufcnt += DATASTORE_CHUNKSIZE; - } - if (!(logicsrc = zip_source_buffer(zipfile, buf, - ds->num_units * ds->ds_unitsize, TRUE))) - return SR_ERR; - snprintf(rawname, 15, "logic-%d", devcnt); - if (zip_add(zipfile, rawname, logicsrc) == -1) - return SR_ERR; - } - devcnt++; - } - fclose(meta); - - if (!(metasrc = zip_source_file(zipfile, metafile, 0, -1))) - return SR_ERR; - if (zip_add(zipfile, "metadata", metasrc) == -1) - return SR_ERR; - - if ((ret = zip_close(zipfile)) == -1) { - g_message("error saving zipfile: %s", zip_strerror(zipfile)); - return SR_ERR; - } - - unlink(metafile); - - return SR_OK; -} - void session_source_add(int fd, int events, int timeout, receive_data_callback callback, void *user_data) { diff --git a/session_driver.c b/session_driver.c new file mode 100644 index 00000000..bbd5a615 --- /dev/null +++ b/session_driver.c @@ -0,0 +1,306 @@ +/* + * This file is part of the sigrok project. + * + * Copyright (C) 2011 Bert Vermeulen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +/* size of payloads sent across the session bus */ +#define CHUNKSIZE 4096 + +struct session_vdevice { + char *capturefile; + struct zip *archive; + struct zip_file *capfile; + uint64_t samplerate; + int unitsize; + int num_probes; +}; + +static char *sessionfile = NULL; +static GSList *device_instances = NULL; +static int capabilities[] = { + SR_HWCAP_CAPTUREFILE, + SR_HWCAP_CAPTURE_UNITSIZE, + 0, +}; + + +static struct session_vdevice *get_vdevice_by_index(int device_index) +{ + struct sr_device_instance *sdi; + struct session_vdevice *vdevice; + + if (!(sdi = sr_get_device_instance(device_instances, device_index))) + return NULL; + + vdevice = sdi->priv; + + return vdevice; +} + +static int feed_chunk(int fd, int revents, void *user_data) +{ + struct sr_device_instance *sdi; + struct session_vdevice *vdevice; + struct sr_datafeed_packet packet; + GSList *l; + void *buf; + int ret, got_data; + + /* avoid compiler warning */ + fd = fd; + revents = revents; + + g_debug("session_driver: feed chunk"); + + got_data = FALSE; + for (l = device_instances; l; l = l->next) { + sdi = l->data; + vdevice = sdi->priv; + if (!vdevice) + /* already done with this instance */ + continue; + + buf = g_malloc(CHUNKSIZE); + ret = zip_fread(vdevice->capfile, buf, CHUNKSIZE); + if (ret > 0) { + got_data = TRUE; + packet.type = SR_DF_LOGIC; + packet.length = ret; + packet.unitsize = vdevice->unitsize; + packet.payload = buf; + session_bus(user_data, &packet); + } else { + /* done with this capture file */ + zip_fclose(vdevice->capfile); + g_free(vdevice->capturefile); + g_free(vdevice); + sdi->priv = NULL; + } + } + + if (!got_data) { + packet.type = SR_DF_END; + packet.length = 0; + session_bus(user_data, &packet); + } + + return TRUE; +} + +/* driver callbacks */ + +static int hw_init(char *deviceinfo) +{ + + sessionfile = g_strdup(deviceinfo); + + return 0; +} + +static void hw_cleanup(void) +{ + GSList *l; + + for (l = device_instances; l; l = l->next) + sr_device_instance_free(l->data); + + g_free(sessionfile); + +} + +static int hw_opendev(int device_index) +{ + struct sr_device_instance *sdi; + + sdi = sr_device_instance_new(device_index, SR_ST_INITIALIZING, + NULL, NULL, NULL); + if (!sdi) + return SR_ERR; + sdi->priv = g_malloc0(sizeof(struct session_vdevice)); + if (!sdi->priv) + return SR_ERR; + device_instances = g_slist_append(device_instances, sdi); + + return SR_OK; +} + +static void hw_closedev(int device_index) +{ + + /* avoid compiler warning */ + device_index = device_index; + +} + +static void *hw_get_device_info(int device_index, int device_info_id) +{ + struct session_vdevice *vdevice; + void *info; + + if (!(vdevice = get_vdevice_by_index(device_index))) + return NULL; + + info = &vdevice->samplerate; + + return info; +} + +static int hw_get_status(int device_index) +{ + + /* avoid compiler warning */ + device_index = device_index; + + if (devices) + return SR_OK; + else + return SR_ERR; +} + +static int *hw_get_capabilities(void) +{ + + return capabilities; +} + +static int hw_set_configuration(int device_index, int capability, void *value) +{ + struct session_vdevice *vdevice; + uint64_t *tmp_u64; + + if (!(vdevice = get_vdevice_by_index(device_index))) + return SR_ERR; + + switch (capability) { + case SR_HWCAP_SAMPLERATE: + tmp_u64 = value; + vdevice->samplerate = *tmp_u64; + break; + case SR_HWCAP_CAPTUREFILE: + vdevice->capturefile = g_strdup(value); + break; + case SR_HWCAP_CAPTURE_UNITSIZE: + tmp_u64 = value; + vdevice->unitsize = *tmp_u64; + break; + case SR_HWCAP_CAPTURE_NUM_PROBES: + tmp_u64 = value; + vdevice->num_probes = *tmp_u64; + break; + default: + return SR_ERR; + } + + return SR_OK; +} + +static int hw_start_acquisition(int device_index, gpointer session_device_id) +{ + struct zip_stat zs; + struct session_vdevice *vdevice; + struct sr_datafeed_header *header; + struct sr_datafeed_packet *packet; + int err; + + /* avoid compiler warning */ + session_device_id = session_device_id; + + if (!(vdevice = get_vdevice_by_index(device_index))) + return SR_ERR; + + g_message("session_driver: opening archive %s file %s", + sessionfile, vdevice->capturefile); + + if (!(vdevice->archive = zip_open(sessionfile, 0, &err))) { + g_warning("Failed to open session file '%s': zip error %d\n", + sessionfile, err); + return SR_ERR; + } + + if (zip_stat(vdevice->archive, vdevice->capturefile, 0, &zs) == -1) { + g_warning("Failed to check capture file '%s' in session file '%s'.", + vdevice->capturefile, sessionfile); + return SR_ERR; + } + + if (!(vdevice->capfile = zip_fopen(vdevice->archive, vdevice->capturefile, 0))) { + g_warning("Failed to open capture file '%s' in session file '%s'.", + vdevice->capturefile, sessionfile); + return SR_ERR; + } + + /* freewheeling source */ + session_source_add(-1, 0, 0, feed_chunk, session_device_id); + + /* Send header packet to the session bus. */ + packet = g_malloc(sizeof(struct sr_datafeed_packet)); + header = g_malloc(sizeof(struct sr_datafeed_header)); + if (!packet || !header) + return SR_ERR; + packet->type = SR_DF_HEADER; + packet->length = sizeof(struct sr_datafeed_header); + packet->payload = (unsigned char *)header; + header->feed_version = 1; + gettimeofday(&header->starttime, NULL); + header->samplerate = 0; + header->protocol_id = SR_PROTO_RAW; + header->num_logic_probes = vdevice->num_probes; + header->num_analog_probes = 0; + session_bus(session_device_id, packet); + g_free(header); + g_free(packet); + + return SR_OK; +} + +static void hw_stop_acquisition(int device_index, gpointer session_device_id) +{ + struct session_vdevice *vdevice; + + /* avoid compiler warning */ + session_device_id = session_device_id; + +// vdevice = get_vdevice_by_index(device_index); +// zip_fclose(vdevice->capfile); +// zip_close(vdevice->archive); + +} + + +struct sr_device_plugin session_driver = { + "session", + "Session-emulating driver", + 1, + hw_init, + hw_cleanup, + hw_opendev, + hw_closedev, + hw_get_device_info, + hw_get_status, + hw_get_capabilities, + hw_set_configuration, + hw_start_acquisition, + hw_stop_acquisition, +}; diff --git a/session_file.c b/session_file.c new file mode 100644 index 00000000..015927d2 --- /dev/null +++ b/session_file.c @@ -0,0 +1,251 @@ +/* + * This file is part of the sigrok project. + * + * Copyright (C) 2011 Bert Vermeulen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + + +extern struct session *session; +extern struct sr_device_plugin session_driver; + + +int session_load(const char *filename) +{ + GKeyFile *kf; + GPtrArray *capturefiles; + struct zip *archive; + struct zip_file *zf; + struct zip_stat zs; + struct session *session; + struct sr_device *device; + struct probe *probe; + int ret, err, probenum, devcnt, i, j; + uint64_t tmp_u64, total_probes, enabled_probes, p; + char **sections, **keys, *metafile, *val, c; + + if (!(archive = zip_open(filename, 0, &err))) { + g_debug("Failed to open session file: zip error %d", err); + return SR_ERR; + } + + /* check "version" */ + if (!(zf = zip_fopen(archive, "version", 0))) { + g_debug("Not a sigrok session file."); + return SR_ERR; + } + ret = zip_fread(zf, &c, 1); + if (ret != 1 || c != '1') { + g_debug("Not a valid sigrok session file."); + return SR_ERR; + } + zip_fclose(zf); + + /* read "metadata" */ + if (zip_stat(archive, "metadata", 0, &zs) == -1) { + g_debug("Not a valid sigrok session file."); + return SR_ERR; + } + metafile = g_malloc(zs.size); + zf = zip_fopen_index(archive, zs.index, 0); + zip_fread(zf, metafile, zs.size); + zip_fclose(zf); + + kf = g_key_file_new(); + if (!g_key_file_load_from_data(kf, metafile, zs.size, 0, NULL)) { + g_debug("Failed to parse metadata."); + return SR_ERR; + } + + session = session_new(); + + devcnt = 0; + capturefiles = g_ptr_array_new_with_free_func(g_free); + sections = g_key_file_get_groups(kf, NULL); + for (i = 0; sections[i]; i++) { + if (!strcmp(sections[i], "global")) + /* nothing really interesting in here yet */ + continue; + if (!strncmp(sections[i], "device ", 7)) { + /* device section */ + device = NULL; + enabled_probes = 0; + keys = g_key_file_get_keys(kf, sections[i], NULL, NULL); + for (j = 0; keys[j]; j++) { + val = g_key_file_get_string(kf, sections[i], keys[j], NULL); + if (!strcmp(keys[j], "capturefile")) { + device = device_new(&session_driver, devcnt, 0); + if (devcnt == 0) + /* first device, init the plugin */ + device->plugin->init((char *)filename); + session_device_add(device); + device->plugin->set_configuration(devcnt, SR_HWCAP_CAPTUREFILE, val); + g_ptr_array_add(capturefiles, val); + } else if (!strcmp(keys[j], "samplerate")) { + tmp_u64 = sr_parse_sizestring(val); + device->plugin->set_configuration(devcnt, SR_HWCAP_SAMPLERATE, &tmp_u64); + } else if (!strcmp(keys[j], "unitsize")) { + tmp_u64 = strtoull(val, NULL, 10); + device->plugin->set_configuration(devcnt, SR_HWCAP_CAPTURE_UNITSIZE, &tmp_u64); + } else if (!strcmp(keys[j], "total probes")) { + total_probes = strtoull(val, NULL, 10); + device->plugin->set_configuration(devcnt, SR_HWCAP_CAPTURE_NUM_PROBES, &total_probes); + for (p = 1; p <= total_probes; p++) + device_probe_add(device, NULL); + } else if (!strncmp(keys[j], "probe", 5)) { + if (!device) + continue; + enabled_probes++; + tmp_u64 = strtoul(keys[j]+5, NULL, 10); + device_probe_name(device, tmp_u64, val); + } else if (!strncmp(keys[j], "trigger", 7)) { + probenum = strtoul(keys[j]+7, NULL, 10); + device_trigger_set(device, probenum, val); + } + } + g_strfreev(keys); + for (p = enabled_probes; p < total_probes; p++) { + probe = g_slist_nth_data(device->probes, p); + probe->enabled = FALSE; + } + } + } + g_strfreev(sections); + g_key_file_free(kf); + + return SR_OK; +} + +int session_save(char *filename) +{ + GSList *l, *p, *d; + FILE *meta; + struct sr_device *device; + struct probe *probe; + struct datastore *ds; + struct zip *zipfile; + struct zip_source *versrc, *metasrc, *logicsrc; + int bufcnt, devcnt, tmpfile, ret, error, probecnt; + uint64_t samplerate; + char version[1], rawname[16], metafile[32], *newfn, *buf, *s; + + newfn = g_malloc(strlen(filename) + 10); + strcpy(newfn, filename); + if (strstr(filename, ".sigrok") != filename+strlen(filename)-7) + strcat(newfn, ".sigrok"); + + /* Quietly delete it first, libzip wants replace ops otherwise. */ + unlink(newfn); + if (!(zipfile = zip_open(newfn, ZIP_CREATE, &error))) + return SR_ERR; + g_free(newfn); + + /* "version" */ + version[0] = '1'; + if (!(versrc = zip_source_buffer(zipfile, version, 1, 0))) + return SR_ERR; + if (zip_add(zipfile, "version", versrc) == -1) { + g_message("error saving version into zipfile: %s", + zip_strerror(zipfile)); + return SR_ERR; + } + + /* init "metadata" */ + strcpy(metafile, "sigrok-meta-XXXXXX"); + if ((tmpfile = g_mkstemp(metafile)) == -1) + return SR_ERR; + close(tmpfile); + meta = fopen(metafile, "wb"); + fprintf(meta, "[global]\n"); + fprintf(meta, "sigrok version = %s\n", PACKAGE_VERSION); + /* TODO: save protocol decoders used */ + + /* all datastores in all devices */ + devcnt = 1; + for (l = session->devices; l; l = l->next) { + device = l->data; + /* metadata */ + fprintf(meta, "[device %d]\n", devcnt); + if (device->plugin) + fprintf(meta, "driver = %s\n", device->plugin->name); + + ds = device->datastore; + if (ds) { + /* metadata */ + fprintf(meta, "capturefile = logic-%d\n", devcnt); + fprintf(meta, "unitsize = %d\n", ds->ds_unitsize); + fprintf(meta, "total probes = %d\n", g_slist_length(device->probes)); + if (device_has_hwcap(device, SR_HWCAP_SAMPLERATE)) { + samplerate = *((uint64_t *) device->plugin->get_device_info( + device->plugin_index, SR_DI_CUR_SAMPLERATE)); + s = sr_samplerate_string(samplerate); + fprintf(meta, "samplerate = %s\n", s); + free(s); + } + probecnt = 1; + for (p = device->probes; p; p = p->next) { + probe = p->data; + if (probe->enabled) { + if (probe->name) + fprintf(meta, "probe%d = %s\n", probecnt, probe->name); + if (probe->trigger) + fprintf(meta, " trigger%d = %s\n", probecnt, probe->trigger); + probecnt++; + } + } + + /* dump datastore into logic-n */ + buf = malloc(ds->num_units * ds->ds_unitsize + + DATASTORE_CHUNKSIZE); + bufcnt = 0; + for (d = ds->chunklist; d; d = d->next) { + memcpy(buf + bufcnt, d->data, + DATASTORE_CHUNKSIZE); + bufcnt += DATASTORE_CHUNKSIZE; + } + if (!(logicsrc = zip_source_buffer(zipfile, buf, + ds->num_units * ds->ds_unitsize, TRUE))) + return SR_ERR; + snprintf(rawname, 15, "logic-%d", devcnt); + if (zip_add(zipfile, rawname, logicsrc) == -1) + return SR_ERR; + } + devcnt++; + } + fclose(meta); + + if (!(metasrc = zip_source_file(zipfile, metafile, 0, -1))) + return SR_ERR; + if (zip_add(zipfile, "metadata", metasrc) == -1) + return SR_ERR; + + if ((ret = zip_close(zipfile)) == -1) { + g_message("error saving zipfile: %s", zip_strerror(zipfile)); + return SR_ERR; + } + + unlink(metafile); + + return SR_OK; +} + diff --git a/sigrok-proto.h b/sigrok-proto.h index 12665fea..f6187a91 100644 --- a/sigrok-proto.h +++ b/sigrok-proto.h @@ -50,6 +50,7 @@ void device_probe_name(struct sr_device *device, int probenum, char *name); void device_trigger_clear(struct sr_device *device); void device_trigger_set(struct sr_device *device, int probenum, char *trigger); +gboolean device_has_hwcap(struct sr_device *device, int hwcap); /*--- filter.c --------------------------------------------------------------*/ @@ -94,7 +95,7 @@ typedef void (*datafeed_callback) (struct sr_device *device, struct sr_datafeed_packet *packet); /* Session setup */ -struct session *session_load(const char *filename); +int session_load(const char *filename); struct session *session_new(void); void session_destroy(void); void session_device_clear(void); diff --git a/sigrok.h b/sigrok.h index 46a99458..59ab45b5 100644 --- a/sigrok.h +++ b/sigrok.h @@ -224,6 +224,11 @@ enum { SR_HWCAP_CAPTURE_RATIO, /* Set pre/post-trigger capture ratio */ SR_HWCAP_PATTERN_MODE, /* Pattern generator mode */ + /* special stuff */ + SR_HWCAP_CAPTUREFILE, /* capturefile to inject */ + SR_HWCAP_CAPTURE_UNITSIZE, /* unitsize of capturefile data */ + SR_HWCAP_CAPTURE_NUM_PROBES,/* set number of probes */ + /* acquisition modes */ SR_HWCAP_LIMIT_MSEC, /* Set a time limit for sample acquisition */ SR_HWCAP_LIMIT_SAMPLES, /* Set a limit on number of samples */