]> sigrok.org Git - libsigrok.git/commitdiff
beaglelogic: Implement TCP protocol
authorKumar Abhishek <redacted>
Thu, 21 Sep 2017 16:24:17 +0000 (21:54 +0530)
committerUwe Hermann <redacted>
Tue, 26 Sep 2017 16:14:46 +0000 (18:14 +0200)
BeagleLogic now supports two modes of interface - one being the
native mode running on an ARM system like the BeagleBone Black
and the other mode acting like a TCP client for the BeagleLogic
server running off a BeagleBone compatible system. This makes it
convenient for desktop users to retrieve samples from BeagleLogic,
no more copying files and SSHing into the BeagleBone hardware in
order to use BeagleLogic.

Signed-off-by: Kumar Abhishek <redacted>
Makefile.am
src/hardware/beaglelogic/api.c
src/hardware/beaglelogic/beaglelogic.h
src/hardware/beaglelogic/beaglelogic_tcp.c [new file with mode: 0644]
src/hardware/beaglelogic/protocol.c
src/hardware/beaglelogic/protocol.h

index b2ea8fe01aed86e4974f205266e186787c627c14..cedd8250512f1bd27b3e3c726e64116275cc6226 100644 (file)
@@ -230,7 +230,8 @@ src_libdrivers_la_SOURCES += \
        src/hardware/beaglelogic/protocol.h \
        src/hardware/beaglelogic/protocol.c \
        src/hardware/beaglelogic/api.c \
-       src/hardware/beaglelogic/beaglelogic_native.c
+       src/hardware/beaglelogic/beaglelogic_native.c \
+       src/hardware/beaglelogic/beaglelogic_tcp.c
 endif
 if HW_BRYMEN_BM86X
 src_libdrivers_la_SOURCES += \
index ef3e8ffabd48536f89076f9de369f13e61ec0788..2d21f46d06e4afba451d4c40c3861850aab557e3 100644 (file)
@@ -22,6 +22,7 @@
 #include "beaglelogic.h"
 
 static const uint32_t scanopts[] = {
+       SR_CONF_CONN,
        SR_CONF_NUM_LOGIC_CHANNELS,
 };
 
@@ -67,6 +68,7 @@ static struct dev_context *beaglelogic_devc_alloc(void)
        /* Default non-zero values (if any) */
        devc->fd = -1;
        devc->limit_samples = (uint64_t)-1;
+       devc->tcp_buffer = 0;
 
        return devc;
 }
@@ -77,17 +79,35 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
        struct sr_config *src;
        struct sr_dev_inst *sdi;
        struct dev_context *devc;
+       const char *conn = NULL;
+       gchar **params;
        int i, maxch;
 
-       /* Probe for /dev/beaglelogic */
-       if (!g_file_test(BEAGLELOGIC_DEV_NODE, G_FILE_TEST_EXISTS))
-               return NULL;
-
        maxch = NUM_CHANNELS;
        for (l = options; l; l = l->next) {
                src = l->data;
                if (src->key == SR_CONF_NUM_LOGIC_CHANNELS)
                        maxch = g_variant_get_int32(src->data);
+               if (src->key == SR_CONF_CONN)
+                       conn = g_variant_get_string(src->data, NULL);
+       }
+
+       /* Probe for /dev/beaglelogic if not connecting via TCP */
+       if (conn == NULL) {
+               if (!g_file_test(BEAGLELOGIC_DEV_NODE, G_FILE_TEST_EXISTS))
+                       return NULL;
+       } else {
+               params = g_strsplit(conn, "/", 0);
+               if (!params || !params[1] || !params[2]) {
+                       sr_err("Invalid Parameters.");
+                       g_strfreev(params);
+                       return NULL;
+               }
+               if (g_ascii_strncasecmp(params[0], "tcp", 3)) {
+                       sr_err("Only TCP (tcp-raw) protocol is currently supported.");
+                       g_strfreev(params);
+                       return NULL;
+               }
        }
 
        if (maxch > 8)
@@ -102,8 +122,23 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 
        devc = beaglelogic_devc_alloc();
 
-       devc->beaglelogic = &beaglelogic_native_ops;
-
+       if (conn == NULL) {
+               devc->beaglelogic = &beaglelogic_native_ops;
+               sr_info("BeagleLogic device found at "BEAGLELOGIC_DEV_NODE);
+       } else {
+               devc->read_timeout = 1000 * 1000;
+               devc->beaglelogic = &beaglelogic_tcp_ops;
+               devc->address = g_strdup(params[1]);
+               devc->port = g_strdup(params[2]);
+               g_strfreev(params);
+
+               if (devc->beaglelogic->open(devc) != SR_OK)
+                       goto err_free;
+               if (beaglelogic_tcp_detect(devc) != SR_OK)
+                       goto err_free;
+               sr_info("BeagleLogic device found at %s : %s",
+                       devc->address, devc->port);
+       }
        /* Fill the channels */
        for (i = 0; i < maxch; i++)
                sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE,
@@ -111,10 +146,14 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 
        sdi->priv = devc;
 
-       /* Signal */
-       sr_info("BeagleLogic device found at "BEAGLELOGIC_DEV_NODE);
-
        return std_scan_complete(di, g_slist_append(NULL, sdi));
+err_free:
+       g_free(sdi->model);
+       g_free(sdi->version);
+       g_free(devc);
+       g_free(sdi);
+
+       return NULL;
 }
 
 static int dev_open(struct sr_dev_inst *sdi)
@@ -122,11 +161,15 @@ static int dev_open(struct sr_dev_inst *sdi)
        struct dev_context *devc = sdi->priv;
 
        /* Open BeagleLogic */
-       if (devc->beaglelogic->open(devc))
-               return SR_ERR;
+       if (devc->beaglelogic == &beaglelogic_native_ops)
+               if (devc->beaglelogic->open(devc))
+                       return SR_ERR;
 
        /* Set fd and local attributes */
-       devc->pollfd.fd = devc->fd;
+       if (devc->beaglelogic == &beaglelogic_tcp_ops)
+               devc->pollfd.fd = devc->socket;
+       else
+               devc->pollfd.fd = devc->fd;
        devc->pollfd.events = G_IO_IN;
        devc->pollfd.revents = 0;
 
@@ -142,10 +185,14 @@ static int dev_open(struct sr_dev_inst *sdi)
        devc->beaglelogic->set_triggerflags(devc);
 
        /* Map the kernel capture FIFO for reads, saves 1 level of memcpy */
-       if (devc->beaglelogic->mmap(devc) != SR_OK) {
-               sr_err("Unable to map capture buffer");
-               devc->beaglelogic->close(devc);
-               return SR_ERR;
+       if (devc->beaglelogic == &beaglelogic_native_ops) {
+               if (devc->beaglelogic->mmap(devc) != SR_OK) {
+                       sr_err("Unable to map capture buffer");
+                       devc->beaglelogic->close(devc);
+                       return SR_ERR;
+               }
+       } else {
+               devc->tcp_buffer = g_malloc(TCP_BUFFER_SIZE);
        }
 
        return SR_OK;
@@ -156,9 +203,13 @@ static int dev_close(struct sr_dev_inst *sdi)
        struct dev_context *devc = sdi->priv;
 
        /* Close the memory mapping and the file */
-       devc->beaglelogic->munmap(devc);
+       if (devc->beaglelogic == &beaglelogic_native_ops)
+               devc->beaglelogic->munmap(devc);
        devc->beaglelogic->close(devc);
 
+       if (devc->tcp_buffer)
+               g_free(devc->tcp_buffer);
+
        return SR_OK;
 }
 
@@ -288,8 +339,13 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 
        /* Trigger and add poll on file */
        devc->beaglelogic->start(devc);
-       sr_session_source_add_pollfd(sdi->session, &devc->pollfd,
-                       BUFUNIT_TIMEOUT_MS(devc), beaglelogic_receive_data,
+       if (devc->beaglelogic == &beaglelogic_native_ops)
+               sr_session_source_add_pollfd(sdi->session, &devc->pollfd,
+                       BUFUNIT_TIMEOUT_MS(devc), beaglelogic_native_receive_data,
+                       (void *)sdi);
+       else
+               sr_session_source_add_pollfd(sdi->session, &devc->pollfd,
+                       BUFUNIT_TIMEOUT_MS(devc), beaglelogic_tcp_receive_data,
                        (void *)sdi);
 
        return SR_OK;
@@ -303,7 +359,8 @@ static int dev_acquisition_stop(struct sr_dev_inst *sdi)
        devc->beaglelogic->stop(devc);
 
        /* lseek to offset 0, flushes the cache */
-       lseek(devc->fd, 0, SEEK_SET);
+       if (devc->beaglelogic == &beaglelogic_native_ops)
+               lseek(devc->fd, 0, SEEK_SET);
 
        /* Remove session source and send EOT packet */
        sr_session_source_remove_pollfd(sdi->session, &devc->pollfd);
index 11bd14916fd4224f788089df0fe51d43f9d180f9..3ee0fd693f3e0665f2aa09468839811821660425 100644 (file)
@@ -124,5 +124,8 @@ struct beaglelogic_ops {
 };
 
 SR_PRIV extern const struct beaglelogic_ops beaglelogic_native_ops;
+SR_PRIV extern const struct beaglelogic_ops beaglelogic_tcp_ops;
+
+SR_PRIV int beaglelogic_tcp_detect(struct dev_context *devc);
 
 #endif
diff --git a/src/hardware/beaglelogic/beaglelogic_tcp.c b/src/hardware/beaglelogic/beaglelogic_tcp.c
new file mode 100644 (file)
index 0000000..8baf4ee
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2017 Kumar Abhishek <abhishek@theembeddedkitchen.net>
+ * Portions of the code are adopted from scpi_tcp.c and scpi.c
+ *
+ * Copyright (C) 2013 Martin Ling <martin-sigrok@earth.li>
+ * Copyright (C) 2013 poljar (Damir Jelić) <poljarinho@gmail.com>
+ *
+ * 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/>.
+ */
+
+#include <config.h>
+#ifdef _WIN32
+#define _WIN32_WINNT 0x0501
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#endif
+#include <glib.h>
+#include <string.h>
+#include <unistd.h>
+#ifndef _WIN32
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#endif
+#include <errno.h>
+
+#include "protocol.h"
+#include "beaglelogic.h"
+
+static int beaglelogic_tcp_open(struct dev_context *devc) {
+       struct addrinfo hints;
+       struct addrinfo *results, *res;
+       int err;
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = AF_UNSPEC;
+       hints.ai_socktype = SOCK_STREAM;
+       hints.ai_protocol = IPPROTO_TCP;
+
+       err = getaddrinfo(devc->address, devc->port, &hints, &results);
+
+       if (err) {
+               sr_err("Address lookup failed: %s:%s: %s", devc->address,
+                       devc->port, gai_strerror(err));
+               return SR_ERR;
+       }
+
+       for (res = results; res; res = res->ai_next) {
+               if ((devc->socket = socket(res->ai_family, res->ai_socktype,
+                                               res->ai_protocol)) < 0)
+                       continue;
+               if (connect(devc->socket, res->ai_addr, res->ai_addrlen) != 0) {
+                       close(devc->socket);
+                       devc->socket = -1;
+                       continue;
+               }
+               break;
+       }
+
+       freeaddrinfo(results);
+
+       if (devc->socket < 0) {
+               sr_err("Failed to connect to %s:%s: %s", devc->address,
+                       devc->port, g_strerror(errno));
+               return SR_ERR;
+       }
+
+       return SR_OK;
+}
+
+static int beaglelogic_tcp_send_cmd(struct dev_context *devc,
+                                   const char *format, ...) {
+       int len, out;
+       va_list args, args_copy;
+       char *buf;
+
+       va_start(args, format);
+       va_copy(args_copy, args);
+       len = vsnprintf(NULL, 0, format, args_copy);
+       va_end(args_copy);
+
+       buf = g_malloc0(len + 2);
+       vsprintf(buf, format, args);
+       va_end(args);
+
+       if (buf[len - 1] != '\n')
+               buf[len] = '\n';
+
+       out = send(devc->socket, buf, strlen(buf), 0);
+
+       if (out < 0) {
+               sr_err("Send error: %s", g_strerror(errno));
+               return SR_ERR;
+       }
+
+       if (out < (int)strlen(buf)) {
+               sr_dbg("Only sent %d/%d bytes of command: '%s'.", out,
+                      strlen(buf), buf);
+       }
+
+       sr_spew("Sent command: '%s'.", buf);
+       g_free(buf);
+
+       return SR_OK;
+}
+
+static int beaglelogic_tcp_read_data(struct dev_context *devc, char *buf,
+               int maxlen) {
+       int len;
+
+       len = recv(devc->socket, buf, maxlen, 0);
+
+       if (len < 0) {
+               sr_err("Receive error: %s", g_strerror(errno));
+               return SR_ERR;
+       }
+
+       return len;
+}
+
+static int beaglelogic_tcp_get_string(struct dev_context *devc, const char *cmd,
+               char **tcp_resp) {
+       GString *response = g_string_sized_new(1024);
+       int len;
+       gint64 timeout;
+
+       if (cmd) {
+               if (beaglelogic_tcp_send_cmd(devc, cmd) != SR_OK) {
+                       return SR_ERR;
+               }
+       }
+
+       timeout = g_get_monotonic_time() + devc->read_timeout;
+       len = beaglelogic_tcp_read_data(devc, response->str,
+                                       response->allocated_len);
+
+       if (len < 0) {
+               g_string_free(response, TRUE);
+               return SR_ERR;
+       }
+
+       if (len > 0) {
+               g_string_set_size(response, len);
+       }
+
+       if (g_get_monotonic_time() > timeout) {
+               sr_err("Timed out waiting for response.");
+               g_string_free(response, TRUE);
+               return SR_ERR_TIMEOUT;
+       }
+
+       /* Remove trailing newline if present */
+       if (response->len >= 1 && response->str[response->len - 1] == '\n')
+               g_string_truncate(response, response->len - 1);
+
+       /* Remove trailing carriage return if present */
+       if (response->len >= 1 && response->str[response->len - 1] == '\r')
+               g_string_truncate(response, response->len - 1);
+
+       sr_spew("Got response: '%.70s', length %" G_GSIZE_FORMAT ".",
+               response->str, response->len);
+
+       *tcp_resp = g_string_free(response, FALSE);
+       return SR_OK;
+}
+
+static int beaglelogic_tcp_get_int(struct dev_context *devc,
+                                  const char *cmd, int *response) {
+       int ret;
+       char *resp = NULL;
+
+       ret = beaglelogic_tcp_get_string(devc, cmd, &resp);
+       if (!resp && ret != SR_OK)
+               return ret;
+
+       if (sr_atoi(resp, response) == SR_OK)
+               ret = SR_OK;
+       else
+               ret = SR_ERR_DATA;
+
+       g_free(resp);
+
+       return ret;
+}
+
+SR_PRIV int beaglelogic_tcp_detect(struct dev_context *devc) {
+       char *resp = NULL;
+       int ret;
+
+       ret = beaglelogic_tcp_get_string(devc, "version", &resp);
+       if (ret == SR_OK && !g_ascii_strncasecmp(resp, "BeagleLogic", 11))
+               ret = SR_OK;
+       else
+               ret = SR_ERR;
+
+       g_free(resp);
+       return ret;
+}
+
+static int beaglelogic_open(struct dev_context *devc) {
+       return beaglelogic_tcp_open(devc);
+}
+
+static int beaglelogic_close(struct dev_context *devc) {
+       g_free(devc->address);
+       g_free(devc->port);
+
+       if (close(devc->socket) < 0)
+               return SR_ERR;
+
+       return SR_OK;
+}
+
+static int beaglelogic_get_buffersize(struct dev_context *devc) {
+       return beaglelogic_tcp_get_int(devc, "memalloc",
+               (int *)&devc->buffersize);
+}
+
+static int beaglelogic_set_buffersize(struct dev_context *devc) {
+       int ret;
+       char *resp;
+
+       beaglelogic_tcp_send_cmd(devc, "memalloc %lu", devc->buffersize);
+       ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
+       if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
+               ret = SR_OK;
+       else
+               ret = SR_ERR;
+
+       g_free(resp);
+       return ret;
+}
+
+static int beaglelogic_get_samplerate(struct dev_context *devc) {
+       int arg, err;
+       err = beaglelogic_tcp_get_int(devc, "samplerate", &arg);
+       devc->cur_samplerate = arg;
+       return err;
+}
+
+static int beaglelogic_set_samplerate(struct dev_context *devc) {
+       int ret;
+       char *resp;
+
+       beaglelogic_tcp_send_cmd(devc, "samplerate %lu",
+               (uint32_t)devc->cur_samplerate);
+       ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
+       if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
+               ret = SR_OK;
+       else
+               ret = SR_ERR;
+
+       g_free(resp);
+       return ret;
+}
+
+static int beaglelogic_get_sampleunit(struct dev_context *devc) {
+       return beaglelogic_tcp_get_int(devc, "sampleunit",
+               (int *)&devc->sampleunit);
+}
+
+static int beaglelogic_set_sampleunit(struct dev_context *devc) {
+       int ret;
+       char *resp;
+
+       beaglelogic_tcp_send_cmd(devc, "sampleunit %lu", devc->sampleunit);
+       ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
+       if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
+               ret = SR_OK;
+       else
+               ret = SR_ERR;
+
+       g_free(resp);
+       return ret;
+}
+
+static int beaglelogic_get_triggerflags(struct dev_context *devc) {
+       return beaglelogic_tcp_get_int(devc, "triggerflags",
+               (int *)&devc->triggerflags);
+}
+
+static int beaglelogic_set_triggerflags(struct dev_context *devc) {
+       int ret;
+       char *resp;
+
+       beaglelogic_tcp_send_cmd(devc, "triggerflags %lu", devc->triggerflags);
+       ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
+       if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
+               ret = SR_OK;
+       else
+               ret = SR_ERR;
+
+       g_free(resp);
+       return ret;
+}
+
+static int beaglelogic_get_lasterror(struct dev_context *devc) {
+       devc->last_error = 0;
+       return SR_OK;
+}
+
+static int beaglelogic_start(struct dev_context *devc) {
+       return beaglelogic_tcp_send_cmd(devc, "get");
+}
+
+static int beaglelogic_stop(struct dev_context *devc) {
+       return beaglelogic_tcp_send_cmd(devc, "close");
+}
+
+static int beaglelogic_get_bufunitsize(struct dev_context *devc) {
+       return beaglelogic_tcp_get_int(devc, "bufunitsize",
+               (int *)&devc->bufunitsize);
+}
+
+static int beaglelogic_set_bufunitsize(struct dev_context *devc) {
+       int ret;
+       char *resp;
+
+       beaglelogic_tcp_send_cmd(devc, "bufunitsize %ld", devc->bufunitsize);
+       ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
+       if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
+               ret = SR_OK;
+       else
+               ret = SR_ERR;
+
+       g_free(resp);
+       return ret;
+}
+
+static int dummy(struct dev_context *devc) {
+       (devc);
+       return SR_ERR_NA;
+}
+
+SR_PRIV const struct beaglelogic_ops beaglelogic_tcp_ops = {
+       .open = beaglelogic_open,
+       .close = beaglelogic_close,
+       .get_buffersize = beaglelogic_get_buffersize,
+       .set_buffersize = beaglelogic_set_buffersize,
+       .get_samplerate = beaglelogic_get_samplerate,
+       .set_samplerate = beaglelogic_set_samplerate,
+       .get_sampleunit = beaglelogic_get_sampleunit,
+       .set_sampleunit = beaglelogic_set_sampleunit,
+       .get_triggerflags = beaglelogic_get_triggerflags,
+       .set_triggerflags = beaglelogic_set_triggerflags,
+       .start = beaglelogic_start,
+       .stop = beaglelogic_stop,
+       .get_lasterror = beaglelogic_get_lasterror,
+       .get_bufunitsize = beaglelogic_get_bufunitsize,
+       .set_bufunitsize = beaglelogic_set_bufunitsize,
+       .mmap = dummy,
+       .munmap = dummy,
+};
index 8f3ce26593175b50aff04570dc481a633684071b..2787b9bac9ef56f7c043ab2974a085d45fc63819 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#ifdef _WIN32
+#define _WIN32_WINNT 0x0501
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <sys/socket.h>
+#endif
+#include <errno.h>
 #include "protocol.h"
+#include "beaglelogic.h"
 
 /* Define data packet size independent of packet (bufunitsize bytes) size
  * from the BeagleLogic kernel module */
@@ -32,7 +41,7 @@
  * 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)
+SR_PRIV int beaglelogic_native_receive_data(int fd, int revents, void *cb_data)
 {
        const struct sr_dev_inst *sdi;
        struct dev_context *devc;
@@ -107,3 +116,86 @@ SR_PRIV int beaglelogic_receive_data(int fd, int revents, void *cb_data)
 
        return TRUE;
 }
+
+SR_PRIV int beaglelogic_tcp_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;
+
+       int len;
+       int pre_trigger_samples;
+       int trigger_offset;
+       uint32_t packetsize;
+       uint64_t bytes_remaining;
+
+       if (!(sdi = cb_data) || !(devc = sdi->priv))
+               return TRUE;
+
+       packetsize = TCP_BUFFER_SIZE;
+       logic.unitsize = SAMPLEUNIT_TO_BYTES(devc->sampleunit);
+
+       if (revents == G_IO_IN) {
+               sr_info("In callback G_IO_IN");
+
+               len = recv(fd, devc->tcp_buffer, TCP_BUFFER_SIZE, 0);
+               if (len < 0) {
+                       sr_err("Receive error: %s", g_strerror(errno));
+                       return SR_ERR;
+               }
+
+               packetsize = len;
+
+               bytes_remaining = (devc->limit_samples * logic.unitsize) -
+                               devc->bytes_read;
+
+               /* Configure data packet */
+               packet.type = SR_DF_LOGIC;
+               packet.payload = &logic;
+               logic.data = devc->tcp_buffer;
+               logic.length = MIN(packetsize, bytes_remaining);
+
+               if (devc->trigger_fired) {
+                       /* Send the incoming transfer to the session bus. */
+                       sr_session_send(sdi, &packet);
+               } else {
+                       /* Check for trigger */
+                       trigger_offset = soft_trigger_logic_check(devc->stl,
+                                       logic.data, packetsize, &pre_trigger_samples);
+                       if (trigger_offset > -1) {
+                               devc->bytes_read += pre_trigger_samples * logic.unitsize;
+                               trigger_offset *= logic.unitsize;
+                               logic.length = MIN(packetsize - trigger_offset,
+                                               bytes_remaining);
+                               logic.data += trigger_offset;
+
+                               sr_session_send(sdi, &packet);
+
+                               devc->trigger_fired = TRUE;
+                       }
+               }
+
+               /* Update byte count and offset (roll over if needed) */
+               devc->bytes_read += logic.length;
+               if ((devc->offset += packetsize) >= devc->buffersize) {
+                       /* One shot capture, we abort and settle with less than
+                        * the required number of samples */
+                       if (devc->triggerflags)
+                               devc->offset = 0;
+                       else
+                               packetsize = 0;
+               }
+       }
+
+       /* EOF Received or we have reached the limit */
+       if (devc->bytes_read >= devc->limit_samples * logic.unitsize ||
+                       packetsize == 0) {
+               /* Send EOA Packet, stop polling */
+               std_session_send_df_end(sdi);
+               devc->beaglelogic->stop(devc);
+               sr_session_source_remove_pollfd(sdi->session, &devc->pollfd);
+       }
+
+       return TRUE;
+}
index 3539a7a4b6d6375c51bd3287d5003073b63cfde5..521673eeb03b742e0d8cfb32405e5709e16d2a75 100644 (file)
@@ -32,6 +32,9 @@
 
 #define SAMPLEUNIT_TO_BYTES(x) ((x) == 1 ? 1 : 2)
 
+#define TCP_BUFFER_SIZE         (128 * 1024)
+
+/** Private, per-device-instance driver context. */
 struct dev_context {
        int max_channels;
        uint32_t fw_ver;
@@ -39,6 +42,13 @@ struct dev_context {
        /* Operations */
        const struct beaglelogic_ops *beaglelogic;
 
+       /* TCP Settings */
+       char *address;
+       char *port;
+       int socket;
+       unsigned int read_timeout;
+       unsigned char *tcp_buffer;
+
        /* Acquisition settings: see beaglelogic.h */
        uint64_t cur_samplerate;
        uint64_t limit_samples;
@@ -64,6 +74,7 @@ struct dev_context {
        gboolean trigger_fired;
 };
 
-SR_PRIV int beaglelogic_receive_data(int fd, int revents, void *cb_data);
+SR_PRIV int beaglelogic_native_receive_data(int fd, int revents, void *cb_data);
+SR_PRIV int beaglelogic_tcp_receive_data(int fd, int revents, void *cb_data);
 
 #endif