From: Kumar Abhishek <[email protected]> api.c * Use the new beaglelogic.h file * Cleanup redundant code * Implemented soft triggers
protocol.c * Remove TODO Software triggers * Use lseek instead of dummy read() to update read pointer * Use built-in MIN() * Implemented soft triggers protocol.h * Remove unused DEFAULT_SAMPLERATE macro * Update header * Add "lasterror" to devcontext beaglelogic.h * Reorganize * All functions operate on struct dev_context * * Cleanup redundant code and functions Tested on a BeagleBone Black Signed-off-by: Kumar Abhishek <[email protected]> --- hardware/beaglelogic/api.c | 271 ++++++++++++++++++++++++++++++++----- hardware/beaglelogic/beaglelogic.h | 213 +++++++++++++++++++++++++++++ hardware/beaglelogic/protocol.c | 78 ++++++++++- hardware/beaglelogic/protocol.h | 30 +++- 4 files changed, 554 insertions(+), 38 deletions(-) create mode 100644 hardware/beaglelogic/beaglelogic.h diff --git a/hardware/beaglelogic/api.c b/hardware/beaglelogic/api.c index f2b528c..2ea0974 100644 --- a/hardware/beaglelogic/api.c +++ b/hardware/beaglelogic/api.c @@ -18,19 +18,81 @@ */ #include "protocol.h" +#include "beaglelogic.h" SR_PRIV struct sr_dev_driver beaglelogic_driver_info; static struct sr_dev_driver *di = &beaglelogic_driver_info; +/* Hardware options */ +static const int32_t hwopts[] = { + SR_CONF_CONN, +}; + +/* Hardware capabiities */ +static const int32_t hwcaps[] = { + SR_CONF_LOGIC_ANALYZER, + SR_CONF_SAMPLERATE, + SR_CONF_TRIGGER_MATCH, + + SR_CONF_LIMIT_SAMPLES, + SR_CONF_CONTINUOUS, + /* SR_CONF_EXTERNAL_CLOCK, TODO in a future BeagleLogic firmware */ + + SR_CONF_NUM_LOGIC_CHANNELS, +}; + +/* Trigger matching capabilities */ +static const int32_t soft_trigger_matches[] = { + SR_TRIGGER_ZERO, + SR_TRIGGER_ONE, + SR_TRIGGER_RISING, + SR_TRIGGER_FALLING, + SR_TRIGGER_EDGE, +}; + +/* Channels are numbered 0-13 */ +SR_PRIV const char *beaglelogic_channel_names[NUM_CHANNELS + 1] = { + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", + "13", NULL, +}; + +/* Possible sample rates : 10 Hz to 100 MHz = (100 / x) MHz */ +static const uint64_t samplerates[] = { + SR_HZ(10), + SR_MHZ(100), + SR_HZ(1), +}; + static int init(struct sr_context *sr_ctx) { return std_init(sr_ctx, di, LOG_PREFIX); } +static struct dev_context * beaglelogic_devc_alloc(void) +{ + struct dev_context *devc; + + /* Allocate the zeroed structure */ + if (!(devc = g_try_malloc0(sizeof(*devc)))) { + sr_err("Device context alloc failed."); + return NULL; + } + + /* Default non-zero values (if any) */ + devc->fd = -1; + devc->limit_samples = (uint64_t)-1; + + return devc; +} + static GSList *scan(GSList *options) { struct drv_context *drvc; GSList *devices; + struct sr_dev_inst *sdi; + struct dev_context *devc; + struct sr_channel *ch; + int i, maxch; (void)options; @@ -38,8 +100,41 @@ static GSList *scan(GSList *options) drvc = di->priv; drvc->instances = NULL; - /* TODO: scan for devices, either based on a SR_CONF_CONN option - * or on a USB scan. */ + /* Probe for /dev/beaglelogic */ + if (!g_file_test(BEAGLELOGIC_DEV_NODE, G_FILE_TEST_EXISTS)) + return NULL; + + sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, NULL, "BeagleLogic", "1.0"); + sdi->driver = di; + + /* We need to test for number of channels by opening the node */ + devc = beaglelogic_devc_alloc(); + + if (beaglelogic_open_nonblock(devc) != SR_OK) { + g_free(devc); + sr_dev_inst_free(sdi); + + return NULL; + } + beaglelogic_get_sampleunit(devc); + beaglelogic_close(devc); + + maxch = (devc->sampleunit == BL_SAMPLEUNIT_8_BITS) ? 8 : NUM_CHANNELS; + + /* Signal */ + sr_info("BeagleLogic device found at "BEAGLELOGIC_DEV_NODE); + + /* Fill the channels */ + for (i = 0; i < maxch; i++) { + if (!(ch = sr_channel_new(i, SR_CHANNEL_LOGIC, TRUE, + beaglelogic_channel_names[i]))) + return NULL; + sdi->channels = g_slist_append(sdi->channels, ch); + } + + sdi->priv = devc; + drvc->instances = g_slist_append(drvc->instances, sdi); + devices = g_slist_append(devices, sdi); return devices; } @@ -56,31 +151,69 @@ static int dev_clear(void) static int dev_open(struct sr_dev_inst *sdi) { - (void)sdi; - - /* TODO: get handle from sdi->conn and open it. */ + struct dev_context *devc = sdi->priv; + + /* Open BeagleLogic */ + if (beaglelogic_open_nonblock(devc)) + return SR_ERR; + + /* Set fd and local attributes */ + devc->pollfd.fd = devc->fd; + devc->pollfd.events = G_IO_IN; + + /* Get the default attributes */ + beaglelogic_get_samplerate(devc); + beaglelogic_get_sampleunit(devc); + beaglelogic_get_triggerflags(devc); + beaglelogic_get_buffersize(devc); + beaglelogic_get_bufunitsize(devc); + + /* Map the kernel capture FIFO for reads, saves 1 level of memcpy */ + if (beaglelogic_mmap(devc) != SR_OK) { + sr_err("Unable to map capture buffer"); + beaglelogic_close(devc); + return SR_ERR; + } + /* We're good to go now */ sdi->status = SR_ST_ACTIVE; - return SR_OK; } static int dev_close(struct sr_dev_inst *sdi) { - (void)sdi; - - /* TODO: get handle from sdi->conn and close it. */ + struct dev_context *devc = sdi->priv; + if (sdi->status == SR_ST_ACTIVE) { + /* Close the memory mapping and the file */ + beaglelogic_munmap(devc); + beaglelogic_close(devc); + } sdi->status = SR_ST_INACTIVE; - return SR_OK; } static int cleanup(void) { - dev_clear(); + struct drv_context *drvc; + struct sr_dev_inst *sdi; + GSList *l; + + /* unused driver */ + if (!(drvc = di->priv)) + return SR_OK; + + /* Clean up the instances */ + for (l = drvc->instances; l; l = l->next) { + sdi = l->data; + di->dev_close(sdi); + g_free(sdi->priv); + sr_dev_inst_free(sdi); + } + g_slist_free(drvc->instances); + drvc->instances = NULL; - /* TODO: free other driver resources, if any. */ + di->priv = NULL; return SR_OK; } @@ -88,47 +221,71 @@ static int cleanup(void) static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { - int ret; - - (void)sdi; - (void)data; + struct dev_context *devc = sdi->priv; (void)cg; - ret = SR_OK; switch (key) { - /* TODO */ + case SR_CONF_LIMIT_SAMPLES: + *data = g_variant_new_uint64(devc->limit_samples); + break; + + case SR_CONF_SAMPLERATE: + *data = g_variant_new_uint64(devc->cur_samplerate); + break; + default: return SR_ERR_NA; } - return ret; + return SR_OK; } static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { - int ret; - - (void)data; + struct dev_context *devc = sdi->priv; + uint64_t tmp_u64; (void)cg; if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; - ret = SR_OK; switch (key) { - /* TODO */ + case SR_CONF_SAMPLERATE: + devc->cur_samplerate = g_variant_get_uint64(data); + return beaglelogic_set_samplerate(devc); + + case SR_CONF_LIMIT_SAMPLES: + tmp_u64 = g_variant_get_uint64(data); + devc->limit_samples = tmp_u64; + devc->triggerflags = BL_TRIGGERFLAGS_ONESHOT; + + /* Check if we have sufficient buffer size */ + tmp_u64 *= SAMPLEUNIT_TO_BYTES(devc->sampleunit); + if (tmp_u64 > devc->buffersize) { + sr_warn("Insufficient buffer space has been allocated."); + sr_warn("Please use \'echo <size in bytes> > "\ + BEAGLELOGIC_SYSFS_ATTR(memalloc) \ + "\' as root to increase the buffer size, this"\ + " capture is now truncated to %d Msamples", + devc->buffersize / + (SAMPLEUNIT_TO_BYTES(devc->sampleunit) * 1000000)); + } + return beaglelogic_set_triggerflags(devc); + default: - ret = SR_ERR_NA; + return SR_ERR_NA; } - return ret; + return SR_OK; } static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { int ret; + GVariant *gvar; + GVariantBuilder gvb; (void)sdi; (void)data; @@ -136,7 +293,26 @@ static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi, ret = SR_OK; switch (key) { - /* TODO */ + case SR_CONF_SCAN_OPTIONS: + *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, + hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t)); + break; + case SR_CONF_DEVICE_OPTIONS: + *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, + hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t)); + break; + case SR_CONF_SAMPLERATE: + g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}")); + gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), + samplerates, ARRAY_SIZE(samplerates), sizeof(uint64_t)); + g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar); + *data = g_variant_builder_end(&gvb); + break; + case SR_CONF_TRIGGER_MATCH: + *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, + soft_trigger_matches, ARRAY_SIZE(soft_trigger_matches), + sizeof(int32_t)); + break; default: return SR_ERR_NA; } @@ -144,29 +320,62 @@ static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi, return ret; } +/* get a sane timeout for poll() */ +#define BUFUNIT_TIMEOUT_MS(devc) (100 + ((devc->bufunitsize * 1000) / \ + (uint32_t)(devc->cur_samplerate))) + static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) { - (void)sdi; (void)cb_data; + struct dev_context *devc = sdi->priv; + struct sr_trigger *trigger; if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; - /* TODO: configure hardware, reset acquisition state, set up - * callbacks and send header packet. */ + /* Save user pointer */ + devc->cb_data = cb_data; + + /* Configure channels */ + devc->sampleunit = g_slist_length(sdi->channels) > 8 ? + BL_SAMPLEUNIT_16_BITS : BL_SAMPLEUNIT_8_BITS; + beaglelogic_set_sampleunit(devc); + + /* Configure triggers & send header packet */ + if ((trigger = sr_session_trigger_get())) { + devc->stl = soft_trigger_logic_new(sdi, trigger); + devc->trigger_fired = FALSE; + } else + devc->trigger_fired = TRUE; + std_session_send_df_header(cb_data, LOG_PREFIX); + + /* Trigger and add poll on file */ + beaglelogic_start(devc); + sr_session_source_add_pollfd(&devc->pollfd, BUFUNIT_TIMEOUT_MS(devc), + beaglelogic_receive_data, (void *)sdi); return SR_OK; } static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) { + struct dev_context *devc = sdi->priv; + struct sr_datafeed_packet pkt; + (void)cb_data; if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; - /* TODO: stop acquisition. */ + /* Execute a stop on BeagleLogic */ + beaglelogic_stop(devc); + + /* Remove session source and send EOT packet */ + sr_session_source_remove_pollfd(&devc->pollfd); + pkt.type = SR_DF_END; + pkt.payload = NULL; + sr_session_send(sdi, &pkt); return SR_OK; } diff --git a/hardware/beaglelogic/beaglelogic.h b/hardware/beaglelogic/beaglelogic.h new file mode 100644 index 0000000..12e2f48 --- /dev/null +++ b/hardware/beaglelogic/beaglelogic.h @@ -0,0 +1,213 @@ +/* + * This file is part of the libsigrok project. + * + * Copyright (C) 2014 Kumar Abhishek <[email protected]> + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef BEAGLELOGIC_H_ +#define BEAGLELOGIC_H_ + +#include <fcntl.h> + +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/errno.h> +#include <sys/ioctl.h> + +#include <stdlib.h> + +#include <unistd.h> + +/* BeagleLogic device node name */ +#define BEAGLELOGIC_DEV_NODE "/dev/beaglelogic" +#define BEAGLELOGIC_SYSFS_ATTR(a) "/sys/devices/virtual/misc/beaglelogic/"\ + __STRING(a) + +/* Reproduced verbatim from beaglelogic.h in the kernel tree until the kernel + * module hits the mainline. Contains the ABI, so DO NOT TOUCH this section */ + +/* ioctl calls that can be issued on /dev/beaglelogic */ +#define IOCTL_BL_GET_VERSION _IOR('k', 0x20, uint32_t) + +#define IOCTL_BL_GET_SAMPLE_RATE _IOR('k', 0x21, uint32_t) +#define IOCTL_BL_SET_SAMPLE_RATE _IOW('k', 0x21, uint32_t) + +#define IOCTL_BL_GET_SAMPLE_UNIT _IOR('k', 0x22, uint32_t) +#define IOCTL_BL_SET_SAMPLE_UNIT _IOW('k', 0x22, uint32_t) + +#define IOCTL_BL_GET_TRIGGER_FLAGS _IOR('k', 0x23, uint32_t) +#define IOCTL_BL_SET_TRIGGER_FLAGS _IOW('k', 0x23, uint32_t) + +#define IOCTL_BL_CACHE_INVALIDATE _IO('k', 0x25) + +#define IOCTL_BL_GET_BUFFER_SIZE _IOR('k', 0x26, uint32_t) +#define IOCTL_BL_SET_BUFFER_SIZE _IOW('k', 0x26, uint32_t) + +#define IOCTL_BL_GET_BUFUNIT_SIZE _IOR('k', 0x27, uint32_t) + +#define IOCTL_BL_FILL_TEST_PATTERN _IO('k', 0x28) + +#define IOCTL_BL_START _IO('k', 0x29) +#define IOCTL_BL_STOP _IO('k', 0x2A) + +/* Possible States of BeagleLogic */ +enum beaglelogic_states { + STATE_BL_DISABLED, /* Powered off (at module start) */ + STATE_BL_INITIALIZED, /* Powered on */ + STATE_BL_MEMALLOCD, /* Buffers allocated */ + STATE_BL_ARMED, /* All Buffers DMA-mapped and configuration done */ + STATE_BL_RUNNING, /* Data being captured */ + STATE_BL_REQUEST_STOP, /* Stop requested */ + STATE_BL_ERROR /* Buffer overrun */ +}; + +/* Setting attributes */ +enum beaglelogic_triggerflags { + BL_TRIGGERFLAGS_ONESHOT = 0, + BL_TRIGGERFLAGS_CONTINUOUS +}; + +/* Possible sample unit / formats */ +enum beaglelogic_sampleunit { + BL_SAMPLEUNIT_16_BITS = 0, + BL_SAMPLEUNIT_8_BITS +}; +/* END beaglelogic.h */ + +/* For all the functions below: + * Parameters: + * devc : Device context structure to operate on + * Returns: + * SR_OK or SR_ERR + */ + +SR_PRIV int beaglelogic_open_nonblock(struct dev_context *devc); +SR_PRIV int beaglelogic_close(struct dev_context *devc); + +SR_PRIV int beaglelogic_get_buffersize(struct dev_context *devc); +SR_PRIV int beaglelogic_set_buffersize(struct dev_context *devc); + +SR_PRIV int beaglelogic_get_samplerate(struct dev_context *devc); +SR_PRIV int beaglelogic_set_samplerate(struct dev_context *devc); + +SR_PRIV int beaglelogic_get_sampleunit(struct dev_context *devc); +SR_PRIV int beaglelogic_set_sampleunit(struct dev_context *devc); + +SR_PRIV int beaglelogic_get_triggerflags(struct dev_context *devc); +SR_PRIV int beaglelogic_set_triggerflags(struct dev_context *devc); + +/* Start and stop the capture operation */ +SR_PRIV int beaglelogic_start(struct dev_context *devc); +SR_PRIV int beaglelogic_stop(struct dev_context *devc); + +/* Get the last error size */ +SR_PRIV int beaglelogic_getlasterror(struct dev_context *devc); + +/* Gets the unit size of the capture buffer (usually 4 or 8 MB) */ +SR_PRIV int beaglelogic_get_bufunitsize(struct dev_context *devc); + +SR_PRIV int beaglelogic_mmap(struct dev_context *devc); +SR_PRIV int beaglelogic_munmap(struct dev_context *devc); + +/* Sources */ +SR_PRIV inline int beaglelogic_open_nonblock(struct dev_context *devc) { + devc->fd = open(BEAGLELOGIC_DEV_NODE, O_RDONLY | O_NONBLOCK); + return (devc->fd == -1 ? SR_ERR : SR_OK); +} + +SR_PRIV inline int beaglelogic_close(struct dev_context *devc) { + return close(devc->fd); +} + +SR_PRIV inline int beaglelogic_get_buffersize(struct dev_context *devc) { + return ioctl(devc->fd, IOCTL_BL_GET_BUFFER_SIZE, &devc->buffersize); +} + +SR_PRIV inline int beaglelogic_set_buffersize(struct dev_context *devc) { + return ioctl(devc->fd, IOCTL_BL_SET_BUFFER_SIZE, devc->buffersize); +} + +/* This is treated differently as it gets a uint64_t while a uint32_t is read */ +SR_PRIV inline int beaglelogic_get_samplerate(struct dev_context *devc) { + uint32_t arg, err; + err = ioctl(devc->fd, IOCTL_BL_GET_SAMPLE_RATE, &arg); + devc->cur_samplerate = arg; + return err; +} + +SR_PRIV inline int beaglelogic_set_samplerate(struct dev_context *devc) { + return ioctl(devc->fd, IOCTL_BL_SET_SAMPLE_RATE, + (uint32_t)devc->cur_samplerate); +} + +SR_PRIV inline int beaglelogic_get_sampleunit(struct dev_context *devc) { + return ioctl(devc->fd, IOCTL_BL_GET_SAMPLE_UNIT, &devc->sampleunit); +} + +SR_PRIV inline int beaglelogic_set_sampleunit(struct dev_context *devc) { + return ioctl(devc->fd, IOCTL_BL_SET_SAMPLE_UNIT, devc->sampleunit); +} + +SR_PRIV inline int beaglelogic_get_triggerflags(struct dev_context *devc) { + return ioctl(devc->fd, IOCTL_BL_GET_TRIGGER_FLAGS, &devc->triggerflags); +} + +SR_PRIV inline int beaglelogic_set_triggerflags(struct dev_context *devc) { + return ioctl(devc->fd, IOCTL_BL_SET_TRIGGER_FLAGS, devc->triggerflags); +} + +SR_PRIV int beaglelogic_getlasterror(struct dev_context *devc) { + int fd; + char buf[16]; + int ret; + + if ((fd = open(BEAGLELOGIC_SYSFS_ATTR(lasterror), O_RDONLY)) == -1) + return SR_ERR; + + if ((ret = read(fd, buf, 16)) < 0) + return SR_ERR; + + close(fd); + devc->last_error = strtoul(buf, NULL, 10); + + return SR_OK; +} + +SR_PRIV inline int beaglelogic_start(struct dev_context *devc) { + return ioctl(devc->fd, IOCTL_BL_START); +} + +SR_PRIV inline int beaglelogic_stop(struct dev_context *devc) { + return ioctl(devc->fd, IOCTL_BL_STOP); +} + +SR_PRIV int beaglelogic_get_bufunitsize(struct dev_context *devc) { + return ioctl(devc->fd, IOCTL_BL_GET_BUFUNIT_SIZE, &devc->bufunitsize); +} + +SR_PRIV int beaglelogic_mmap(struct dev_context *devc) { + if (!devc->buffersize) + beaglelogic_get_buffersize(devc); + devc->sample_buf = mmap(NULL, devc->buffersize, + PROT_READ, MAP_SHARED, devc->fd, 0); + return (devc->sample_buf == MAP_FAILED ? -1 : SR_OK); +} + +SR_PRIV int beaglelogic_munmap(struct dev_context *devc) { + return munmap(devc->sample_buf, devc->buffersize); +} + +#endif /* BEAGLELOGIC_H_ */ diff --git a/hardware/beaglelogic/protocol.c b/hardware/beaglelogic/protocol.c index f765a95..d68db50 100644 --- a/hardware/beaglelogic/protocol.c +++ b/hardware/beaglelogic/protocol.c @@ -18,22 +18,90 @@ */ #include "protocol.h" +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +/* sigrok-cli supports this at max */ +#define COPY_SIZE (512 * 1024) + +/* This implementation is zero copy from the libsigrok side. + * It does not copy any data, just passes a pointer from the mmap'ed + * kernel buffers appropriately. It is up to the application which is + * using libsigrok to decide how to deal with the data. + */ SR_PRIV int beaglelogic_receive_data(int fd, int revents, void *cb_data) { const struct sr_dev_inst *sdi; struct dev_context *devc; + struct sr_datafeed_packet packet; + struct sr_datafeed_logic logic; - (void)fd; + int trigger_offset; + uint32_t copysize; - if (!(sdi = cb_data)) + if (!(sdi = cb_data) || !(devc = sdi->priv)) return TRUE; - if (!(devc = sdi->priv)) - return TRUE; + copysize = COPY_SIZE; + + logic.unitsize = SAMPLEUNIT_TO_BYTES(devc->sampleunit); if (revents == G_IO_IN) { - /* TODO */ + sr_info("In callback G_IO_IN, offset=%d", devc->offset); + + /* Configure data packet */ + packet.type = SR_DF_LOGIC; + packet.payload = &logic; + logic.data = devc->sample_buf + devc->offset; + logic.length = MIN(copysize, devc->limit_samples * logic.unitsize - devc->bytes_read); + + if (devc->trigger_fired) { + /* Send the incoming transfer to the session bus. */ + sr_session_send(devc->cb_data, &packet); + } else { + /* Check for trigger */ + trigger_offset = soft_trigger_logic_check(devc->stl, + logic.data, + copysize); + + if (trigger_offset > -1) { + trigger_offset *= logic.unitsize; + logic.length -= trigger_offset; + logic.data += trigger_offset; + + sr_session_send(devc->cb_data, &packet); + + devc->trigger_fired = TRUE; + } + } + + /* Move the read pointer forward */ + lseek(fd, copysize, SEEK_CUR); + + /* Update byte count and offset (roll over if needed) */ + devc->bytes_read += logic.length; + if ((devc->offset += copysize) >= devc->buffersize) { + /* One shot capture, we abort and settle with less than + * the required number of samples */ + if (devc->triggerflags) + devc->offset = 0; + else + copysize = 0; + } + + } + + /* EOF Received or we have reached the limit */ + if (devc->bytes_read >= devc->limit_samples * logic.unitsize || + copysize == 0) { + /* Send EOA Packet, stop polling */ + packet.type = SR_DF_END; + packet.payload = NULL; + sr_session_send(sdi, &packet); + + sr_session_source_remove_pollfd(&devc->pollfd); } return TRUE; diff --git a/hardware/beaglelogic/protocol.h b/hardware/beaglelogic/protocol.h index 07d3bf2..f2acfeb 100644 --- a/hardware/beaglelogic/protocol.h +++ b/hardware/beaglelogic/protocol.h @@ -27,16 +27,42 @@ #define LOG_PREFIX "beaglelogic" +/* Maximum possible input channels */ +#define NUM_CHANNELS 14 + +#define SAMPLEUNIT_TO_BYTES(x) ((x) == 1 ? 1 : 2) + /** Private, per-device-instance driver context. */ struct dev_context { /* Model-specific information */ + int max_channels; + uint32_t fw_ver; - /* Acquisition settings */ + /* Acquisition settings: see beaglelogic.h */ + uint64_t cur_samplerate; + uint64_t limit_samples; + uint32_t sampleunit; + uint32_t triggerflags; + + /* Buffers: size of each buffer block and the total buffer area */ + uint32_t bufunitsize; + uint32_t buffersize; /* Operational state */ + int fd; + GPollFD pollfd; + int last_error; + + uint64_t bytes_read; + uint64_t sent_samples; + uint32_t offset; + uint8_t *sample_buf; /* mmap'd kernel buffer here */ - /* Temporary state across callbacks */ + void *cb_data; + /* Trigger logic */ + struct soft_trigger_logic *stl; + gboolean trigger_fired; }; SR_PRIV int beaglelogic_receive_data(int fd, int revents, void *cb_data); -- 1.9.1 ------------------------------------------------------------------------------ Open source business process management suite built on Java and Eclipse Turn processes into business applications with Bonita BPM Community Edition Quickly connect people, data, and systems into organized workflows Winner of BOSSIE, CODIE, OW2 and Gartner awards http://p.sf.net/sfu/Bonitasoft _______________________________________________ sigrok-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/sigrok-devel

