]> sigrok.org Git - libsigrok.git/commitdiff
Rename rigol-ds1xx2 driver to rigol-ds.
authorMartin Ling <redacted>
Thu, 31 Oct 2013 17:31:39 +0000 (17:31 +0000)
committerMartin Ling <redacted>
Fri, 29 Nov 2013 00:50:59 +0000 (00:50 +0000)
13 files changed:
README.devices
configure.ac
contrib/gnuplot_rigol_ds1xx2.gpi
hardware/Makefile.am
hardware/rigol-ds/Makefile.am [new file with mode: 0644]
hardware/rigol-ds/api.c [new file with mode: 0644]
hardware/rigol-ds/protocol.c [new file with mode: 0644]
hardware/rigol-ds/protocol.h [new file with mode: 0644]
hardware/rigol-ds1xx2/Makefile.am [deleted file]
hardware/rigol-ds1xx2/api.c [deleted file]
hardware/rigol-ds1xx2/protocol.c [deleted file]
hardware/rigol-ds1xx2/protocol.h [deleted file]
hwdriver.c

index f28462a02977a2dc2d5da968fd98d7ed0be67e8d..a99fc7e2e95f8fb0e9783e99c7adf8f0022b533c 100644 (file)
@@ -66,7 +66,7 @@ The following drivers/devices do not need any firmware upload:
  - mic-985xx
  - norma-dmm
  - openbench-logic-sniffer
- - rigol-ds1xx2
+ - rigol-ds
  - serial-dmm
  - teleinfo
  - tondaj-sl-814
@@ -118,7 +118,7 @@ The following drivers/devices do not require a serial port specification:
  - ikalogic-scanaplus
  - kecheng-kc-330b
  - lascar-el-usb
- - rigol-ds1xx2
+ - rigol-ds
  - saleae-logic16
  - uni-t-dmm
  - uni-t-ut32x
@@ -344,12 +344,12 @@ Example:
  $ sigrok-cli --driver ols:conn=/dev/ttyACM0 ...
 
 
-Rigol DS1xx2 oscilloscopes
---------------------------
+Rigol DS oscilloscopes
+----------------------
 
-The 'rigol-ds1xx2' driver (for the Rigol DS1052E and some other, similar DSOs)
-currently uses the Linux usbtmc kernel driver. This means it can currently
-only be built and used on Linux (i.e., it's non-portable).
+The 'rigol-ds' driver (for the Rigol DS series DSOs) currently uses the Linux
+usbtmc kernel driver. This means it can currently only be built and used on
+Linux (i.e., it's non-portable).
 
 The use of a kernel module also means it is dependent on the kernel version
 used, as well as on whether this specific module is available in the kernel.
@@ -360,4 +360,3 @@ module as opposed to a libusb-based driver that works in user-space.
 We plan to change the driver to use the 'librevisa' user-space shared
 library (which uses libusb) soon, which will fix all these issues and make
 the driver portable at the same time.
-
index 29880ee5d9041993d4f124c70dc4f134320ab690..c1c4aedce85a2bcf392b99d61199bdde8c7be75e 100644 (file)
@@ -189,10 +189,10 @@ AC_ARG_ENABLE(ols, AC_HELP_STRING([--enable-ols],
        [HW_OLS="$enableval"],
        [HW_OLS=$HW_ENABLED_DEFAULT])
 
-AC_ARG_ENABLE(rigol-ds1xx2, AC_HELP_STRING([--enable-rigol-ds1xx2],
-       [enable Rigol DS1xx2 support [default=yes]]),
-       [HW_RIGOL_DS1XX2="$enableval"],
-       [HW_RIGOL_DS1XX2=$HW_ENABLED_DEFAULT])
+AC_ARG_ENABLE(rigol-ds, AC_HELP_STRING([--enable-rigol-ds],
+       [enable Rigol DS support [default=yes]]),
+       [HW_RIGOL_DS="$enableval"],
+       [HW_RIGOL_DS=$HW_ENABLED_DEFAULT])
 
 AC_ARG_ENABLE(saleae-logic16, AC_HELP_STRING([--enable-saleae-logic16],
        [enable Saleae Logic16 support [default=yes]]),
@@ -334,18 +334,18 @@ PKG_CHECK_MODULES([check], [check >= 0.9.4],
        LIBS="$LIBS $check_LIBS"], [have_check="no"])
 AM_CONDITIONAL(HAVE_CHECK, test x"$have_check" = "xyes")
 
-# The Rigol DS1xx2 driver currently uses the Linux kernel usbtmc module
+# The Rigol DS driver currently uses the Linux kernel usbtmc module
 # (though it is planned to rewrite the driver to be portable later).
 # Thus, it will be disabled for non-Linux builds for now.
 case "$host" in
 *linux*)
        # Do nothing. Whether the driver is enabled is determined by the
        # previous --enable-all-drivers/--disable-all-drivers and/or any
-       # --enable-rigol-ds1xx2/--disable-rigol-ds1xx2 options.
+       # --enable-rigol-ds/--disable-rigol-ds options.
        ;;
 *)
        # Disable the driver for builds that don't target Linux.
-       HW_RIGOL_DS1XX2="no"
+       HW_RIGOL_DS="no"
        ;;
 esac
 
@@ -458,9 +458,9 @@ if test "x$HW_OLS" = "xyes"; then
        AC_DEFINE(HAVE_HW_OLS, 1, [OpenBench Logic Sniffer (OLS) support])
 fi
 
-AM_CONDITIONAL(HW_RIGOL_DS1XX2, test x$HW_RIGOL_DS1XX2 = xyes)
-if test "x$HW_RIGOL_DS1XX2" = "xyes"; then
-       AC_DEFINE(HAVE_HW_RIGOL_DS1XX2, 1, [Rigol DS1xx2 support])
+AM_CONDITIONAL(HW_RIGOL_DS, test x$HW_RIGOL_DS = xyes)
+if test "x$HW_RIGOL_DS" = "xyes"; then
+       AC_DEFINE(HAVE_HW_RIGOL_DS, 1, [Rigol DS support])
 fi
 
 AM_CONDITIONAL(HW_SALEAE_LOGIC16, test x$HW_SALEAE_LOGIC16 = xyes)
@@ -553,7 +553,7 @@ AC_CONFIG_FILES([Makefile version.h hardware/Makefile
                 hardware/kecheng-kc-330b/Makefile
                 hardware/lascar-el-usb/Makefile
                 hardware/mic-985xx/Makefile
-                hardware/rigol-ds1xx2/Makefile
+                hardware/rigol-ds/Makefile
                 hardware/saleae-logic16/Makefile
                 hardware/teleinfo/Makefile
                 hardware/tondaj-sl-814/Makefile
@@ -625,7 +625,7 @@ echo "  - link-mso19 (EXPERIMENTAL)....... $HW_LINK_MSO19"
 echo "  - mic-985xx....................... $HW_MIC_985XX"
 echo "  - norma-dmm....................... $HW_NORMA_DMM"
 echo "  - openbench-logic-sniffer......... $HW_OLS"
-echo "  - rigol-ds1xx2.................... $HW_RIGOL_DS1XX2"
+echo "  - rigol-ds........................ $HW_RIGOL_DS"
 echo "  - saleae-logic16.................. $HW_SALEAE_LOGIC16"
 echo "  - serial-dmm...................... $HW_SERIAL_DMM"
 echo "  - teleinfo........................ $HW_TELEINFO"
index 6800158b1a0490eb8cc9c5972d8428dcb07fbc72..a598b9ebc10bcc825b03cb5ccd7f1ae0bedd2246 100644 (file)
@@ -30,7 +30,7 @@ set output "sigrok_gnuplot.png"
 # Rigol DS1xx2 output is currently always 600 samples in size.
 # This script currently also assumes only one channel is acquired like this:
 #
-#   $ sigrok-cli --driver rigol-ds1xx2 --frames 1 -p CH1 ...
+#   $ sigrok-cli --driver rigol-ds --frames 1 -p CH1 ...
 #
 plot [0:600] \
 "sigrok_gnuplot.dat" using 1 with lines linewidth 2 title "CH1"
index 27735af6ffa21b7d5caf39b67972bd2e9ba4ed66..fec45790c0de35f9b443887901374e851aadb82f 100644 (file)
@@ -41,7 +41,7 @@ SUBDIRS = \
        mic-985xx \
        norma-dmm \
        openbench-logic-sniffer \
-       rigol-ds1xx2 \
+       rigol-ds \
        saleae-logic16 \
        serial-dmm \
        teleinfo \
@@ -142,8 +142,8 @@ if HW_OLS
 libsigrokhardware_la_LIBADD += openbench-logic-sniffer/libsigrok_hw_ols.la
 endif
 
-if HW_RIGOL_DS1XX2
-libsigrokhardware_la_LIBADD += rigol-ds1xx2/libsigrok_hw_rigol_ds1xx2.la
+if HW_RIGOL_DS
+libsigrokhardware_la_LIBADD += rigol-ds/libsigrok_hw_rigol_ds.la
 endif
 
 if HW_SALEAE_LOGIC16
diff --git a/hardware/rigol-ds/Makefile.am b/hardware/rigol-ds/Makefile.am
new file mode 100644 (file)
index 0000000..fba4226
--- /dev/null
@@ -0,0 +1,33 @@
+##
+## This file is part of the libsigrok project.
+##
+## Copyright (C) 2012 Martin Ling <martin-git@earth.li>
+##
+## 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/>.
+##
+
+if HW_RIGOL_DS
+
+# Local lib, this is NOT meant to be installed!
+noinst_LTLIBRARIES = libsigrok_hw_rigol_ds.la
+
+libsigrok_hw_rigol_ds_la_SOURCES = \
+       api.c \
+       protocol.c \
+       protocol.h
+
+libsigrok_hw_rigol_ds_la_CFLAGS = \
+       -I$(top_srcdir)
+
+endif
diff --git a/hardware/rigol-ds/api.c b/hardware/rigol-ds/api.c
new file mode 100644 (file)
index 0000000..e0f4eae
--- /dev/null
@@ -0,0 +1,758 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2012 Martin Ling <martin-git@earth.li>
+ * Copyright (C) 2013 Bert Vermeulen <bert@biot.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 <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include "libsigrok.h"
+#include "libsigrok-internal.h"
+#include "protocol.h"
+
+#define NUM_TIMEBASE  12
+#define NUM_VDIV      8
+
+static const int32_t hwopts[] = {
+       SR_CONF_CONN,
+};
+
+static const int32_t hwcaps[] = {
+       SR_CONF_OSCILLOSCOPE,
+       SR_CONF_TIMEBASE,
+       SR_CONF_TRIGGER_SOURCE,
+       SR_CONF_TRIGGER_SLOPE,
+       SR_CONF_HORIZ_TRIGGERPOS,
+       SR_CONF_NUM_TIMEBASE,
+};
+
+static const int32_t analog_hwcaps[] = {
+       SR_CONF_NUM_VDIV,
+       SR_CONF_VDIV,
+       SR_CONF_COUPLING,
+};
+
+static const uint64_t timebases[][2] = {
+       /* nanoseconds */
+       { 2, 1000000000 },
+       { 5, 1000000000 },
+       { 10, 1000000000 },
+       { 20, 1000000000 },
+       { 50, 1000000000 },
+       { 100, 1000000000 },
+       { 500, 1000000000 },
+       /* microseconds */
+       { 1, 1000000 },
+       { 2, 1000000 },
+       { 5, 1000000 },
+       { 10, 1000000 },
+       { 20, 1000000 },
+       { 50, 1000000 },
+       { 100, 1000000 },
+       { 200, 1000000 },
+       { 500, 1000000 },
+       /* milliseconds */
+       { 1, 1000 },
+       { 2, 1000 },
+       { 5, 1000 },
+       { 10, 1000 },
+       { 20, 1000 },
+       { 50, 1000 },
+       { 100, 1000 },
+       { 200, 1000 },
+       { 500, 1000 },
+       /* seconds */
+       { 1, 1 },
+       { 2, 1 },
+       { 5, 1 },
+       { 10, 1 },
+       { 20, 1 },
+       { 50, 1 },
+};
+
+static const uint64_t vdivs[][2] = {
+       /* millivolts */
+       { 2, 1000 },
+       { 5, 1000 },
+       { 10, 1000 },
+       { 20, 1000 },
+       { 50, 1000 },
+       { 100, 1000 },
+       { 200, 1000 },
+       { 500, 1000 },
+       /* volts */
+       { 1, 1 },
+       { 2, 1 },
+       { 5, 1 },
+       { 10, 1 },
+};
+
+static const char *trigger_sources[] = {
+       "CH1",
+       "CH2",
+       "EXT",
+       "AC Line",
+       "D0",
+       "D1",
+       "D2",
+       "D3",
+       "D4",
+       "D5",
+       "D6",
+       "D7",
+       "D8",
+       "D9",
+       "D10",
+       "D11",
+       "D12",
+       "D13",
+       "D14",
+       "D15",
+};
+
+static const char *coupling[] = {
+       "AC",
+       "DC",
+       "GND",
+};
+
+static const char *supported_models[] = {
+       "DS1052E",
+       "DS1102E",
+       "DS1152E",
+       "DS1052D",
+       "DS1102D",
+       "DS1152D",
+};
+
+SR_PRIV struct sr_dev_driver rigol_ds_driver_info;
+static struct sr_dev_driver *di = &rigol_ds_driver_info;
+
+static void clear_helper(void *priv)
+{
+       struct dev_context *devc;
+
+       devc = priv;
+       g_free(devc->coupling[0]);
+       g_free(devc->coupling[1]);
+       g_free(devc->trigger_source);
+       g_free(devc->trigger_slope);
+       g_slist_free(devc->analog_groups[0].probes);
+       g_slist_free(devc->analog_groups[1].probes);
+       g_slist_free(devc->digital_group.probes);
+}
+
+static int dev_clear(void)
+{
+       return std_dev_clear(di, clear_helper);
+}
+
+static int set_cfg(const struct sr_dev_inst *sdi, const char *format, ...)
+{
+       va_list args;
+       char buf[256];
+
+       va_start(args, format);
+       vsnprintf(buf, 255, format, args);
+       va_end(args);
+       if (rigol_ds_send(sdi, buf) != SR_OK)
+               return SR_ERR;
+
+       /* When setting a bunch of parameters in a row, the DS1052E scrambles
+        * some of them unless there is at least 100ms delay in between. */
+       sr_spew("delay %dms", 100);
+       g_usleep(100000);
+
+       return SR_OK;
+}
+
+static int init(struct sr_context *sr_ctx)
+{
+       return std_init(sr_ctx, di, LOG_PREFIX);
+}
+
+static int probe_port(const char *port, GSList **devices)
+{
+       struct dev_context *devc;
+       struct sr_dev_inst *sdi;
+       struct sr_serial_dev_inst *serial;
+       struct sr_probe *probe;
+       unsigned int i;
+       int len, num_tokens;
+       gboolean matched, has_digital;
+       const char *manufacturer, *model, *version;
+       char buf[256];
+       gchar **tokens, *channel_name;
+
+       *devices = NULL;
+       if (!(serial = sr_serial_dev_inst_new(port, NULL)))
+               return SR_ERR_MALLOC;
+
+       if (serial_open(serial, SERIAL_RDWR) != SR_OK)
+               return SR_ERR;
+       len = serial_write(serial, "*IDN?", 5);
+       len = serial_read(serial, buf, sizeof(buf));
+       if (serial_close(serial) != SR_OK)
+               return SR_ERR;
+
+       sr_serial_dev_inst_free(serial);
+
+       if (len == 0)
+               return SR_ERR_NA;
+
+       buf[len] = 0;
+       tokens = g_strsplit(buf, ",", 0);
+       sr_dbg("response: %s [%s]", port, buf);
+
+       for (num_tokens = 0; tokens[num_tokens] != NULL; num_tokens++);
+
+       if (num_tokens < 4) {
+               g_strfreev(tokens);
+               return SR_ERR_NA;
+       }
+
+       manufacturer = tokens[0];
+       model = tokens[1];
+       version = tokens[3];
+
+       if (strcmp(manufacturer, "Rigol Technologies")) {
+               g_strfreev(tokens);
+               return SR_ERR_NA;
+       }
+
+       matched = has_digital = FALSE;
+       for (i = 0; i < ARRAY_SIZE(supported_models); i++) {
+               if (!strcmp(model, supported_models[i])) {
+                       matched = TRUE;
+                       has_digital = g_str_has_suffix(model, "D");
+                       break;
+               }
+       }
+
+       if (!matched || !(sdi = sr_dev_inst_new(0, SR_ST_ACTIVE,
+               manufacturer, model, version))) {
+               g_strfreev(tokens);
+               return SR_ERR_NA;
+       }
+
+       g_strfreev(tokens);
+
+       if (!(sdi->conn = sr_serial_dev_inst_new(port, NULL)))
+               return SR_ERR_MALLOC;
+       sdi->driver = di;
+       sdi->inst_type = SR_INST_SERIAL;
+
+       if (!(devc = g_try_malloc0(sizeof(struct dev_context))))
+               return SR_ERR_MALLOC;
+       devc->limit_frames = 0;
+       devc->has_digital = has_digital;
+
+       for (i = 0; i < 2; i++) {
+               channel_name = (i == 0 ? "CH1" : "CH2");
+               if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE, channel_name)))
+                       return SR_ERR_MALLOC;
+               sdi->probes = g_slist_append(sdi->probes, probe);
+               devc->analog_groups[i].name = channel_name;
+               devc->analog_groups[i].probes = g_slist_append(NULL, probe);
+               sdi->probe_groups = g_slist_append(sdi->probe_groups,
+                               &devc->analog_groups[i]);
+       }
+
+       if (devc->has_digital) {
+               for (i = 0; i < 16; i++) {
+                       if (!(channel_name = g_strdup_printf("D%d", i)))
+                               return SR_ERR_MALLOC;
+                       probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, channel_name);
+                       g_free(channel_name);
+                       if (!probe)
+                               return SR_ERR_MALLOC;
+                       sdi->probes = g_slist_append(sdi->probes, probe);
+                       devc->digital_group.probes = g_slist_append(
+                                       devc->digital_group.probes, probe);
+                       devc->digital_group.name = "LA";
+                       sdi->probe_groups = g_slist_append(sdi->probe_groups,
+                                       &devc->digital_group);
+               }
+       }
+       sdi->priv = devc;
+
+       *devices = g_slist_append(NULL, sdi);
+
+       return SR_OK;
+}
+
+static GSList *scan(GSList *options)
+{
+       struct drv_context *drvc;
+       struct sr_config *src;
+       GSList *l, *devices;
+       GDir *dir;
+       int ret;
+       const gchar *dev_name;
+       gchar *port = NULL;
+
+       drvc = di->priv;
+
+       for (l = options; l; l = l->next) {
+               src = l->data;
+               if (src->key == SR_CONF_CONN) {
+                       port = (char *)g_variant_get_string(src->data, NULL);
+                       break;
+               }
+       }
+
+       devices = NULL;
+       if (port) {
+               if (probe_port(port, &devices) == SR_ERR_MALLOC)
+                       return NULL;
+       } else {
+               if (!(dir = g_dir_open("/sys/class/usbmisc/", 0, NULL)))
+                       if (!(dir = g_dir_open("/sys/class/usb/", 0, NULL)))
+                               return NULL;
+               while ((dev_name = g_dir_read_name(dir))) {
+                       if (strncmp(dev_name, "usbtmc", 6))
+                               continue;
+                       port = g_strconcat("/dev/", dev_name, NULL);
+                       ret = probe_port(port, &devices);
+                       g_free(port);
+                       if (ret == SR_ERR_MALLOC) {
+                               g_dir_close(dir);
+                               return NULL;
+                       }
+               }
+               g_dir_close(dir);
+       }
+
+       /* Tack a copy of the newly found devices onto the driver list. */
+       l = g_slist_copy(devices);
+       drvc->instances = g_slist_concat(drvc->instances, l);
+
+       return devices;
+}
+
+static GSList *dev_list(void)
+{
+       return ((struct drv_context *)(di->priv))->instances;
+}
+
+static int dev_open(struct sr_dev_inst *sdi)
+{
+
+       if (serial_open(sdi->conn, SERIAL_RDWR) != SR_OK)
+               return SR_ERR;
+
+       if (rigol_ds_get_dev_cfg(sdi) != SR_OK)
+               return SR_ERR;
+
+       sdi->status = SR_ST_ACTIVE;
+
+       return SR_OK;
+}
+
+static int dev_close(struct sr_dev_inst *sdi)
+{
+       struct sr_serial_dev_inst *serial;
+
+       serial = sdi->conn;
+       if (serial && serial->fd != -1) {
+               serial_close(serial);
+               sdi->status = SR_ST_INACTIVE;
+       }
+
+       return SR_OK;
+}
+
+static int cleanup(void)
+{
+       return dev_clear();
+}
+
+static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
+               const struct sr_probe_group *probe_group)
+{
+       struct dev_context *devc;
+       unsigned int i;
+
+       if (!sdi || !(devc = sdi->priv))
+               return SR_ERR_ARG;
+
+       /* If a probe group is specified, it must be a valid one. */
+       if (probe_group) {
+               if (probe_group != &devc->analog_groups[0]
+                               && probe_group != &devc->analog_groups[1]) {
+                       sr_err("Invalid probe group specified.");
+                       return SR_ERR;
+               }
+       }
+
+       switch (id) {
+       case SR_CONF_NUM_TIMEBASE:
+               *data = g_variant_new_int32(NUM_TIMEBASE);
+               break;
+       case SR_CONF_NUM_VDIV:
+               if (!probe_group) {
+                       sr_err("No probe group specified.");
+                       return SR_ERR_PROBE_GROUP;
+               }
+               for (i = 0; i < 2; i++) {
+                       if (probe_group == &devc->analog_groups[i]) {
+                               *data = g_variant_new_int32(NUM_VDIV);
+                               return SR_OK;
+                       }
+               }
+               return SR_ERR_NA;
+       default:
+               return SR_ERR_NA;
+       }
+
+       return SR_OK;
+}
+
+static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
+               const struct sr_probe_group *probe_group)
+{
+       struct dev_context *devc;
+       uint64_t tmp_u64, p, q;
+       double t_dbl;
+       unsigned int i, j;
+       int ret;
+       const char *tmp_str;
+
+       if (!(devc = sdi->priv))
+               return SR_ERR_ARG;
+
+       if (sdi->status != SR_ST_ACTIVE)
+               return SR_ERR_DEV_CLOSED;
+
+       /* If a probe group is specified, it must be a valid one. */
+       if (probe_group) {
+               if (probe_group != &devc->analog_groups[0]
+                               && probe_group != &devc->analog_groups[1]) {
+                       sr_err("Invalid probe group specified.");
+                       return SR_ERR;
+               }
+       }
+
+       ret = SR_OK;
+       switch (id) {
+       case SR_CONF_LIMIT_FRAMES:
+               devc->limit_frames = g_variant_get_uint64(data);
+               break;
+       case SR_CONF_TRIGGER_SLOPE:
+               tmp_u64 = g_variant_get_uint64(data);
+               if (tmp_u64 != 0 && tmp_u64 != 1)
+                       return SR_ERR;
+               g_free(devc->trigger_slope);
+               devc->trigger_slope = g_strdup(tmp_u64 ? "POS" : "NEG");
+               ret = set_cfg(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope);
+               break;
+       case SR_CONF_HORIZ_TRIGGERPOS:
+               t_dbl = g_variant_get_double(data);
+               if (t_dbl < 0.0 || t_dbl > 1.0)
+                       return SR_ERR;
+               devc->horiz_triggerpos = t_dbl;
+               /* We have the trigger offset as a percentage of the frame, but
+                * need to express this in seconds. */
+               t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * NUM_TIMEBASE;
+               ret = set_cfg(sdi, ":TIM:OFFS %.6f", t_dbl);
+               break;
+       case SR_CONF_TIMEBASE:
+               g_variant_get(data, "(tt)", &p, &q);
+               for (i = 0; i < ARRAY_SIZE(timebases); i++) {
+                       if (timebases[i][0] == p && timebases[i][1] == q) {
+                               devc->timebase = (float)p / q;
+                               ret = set_cfg(sdi, ":TIM:SCAL %.9f", devc->timebase);
+                               break;
+                       }
+               }
+               if (i == ARRAY_SIZE(timebases))
+                       ret = SR_ERR_ARG;
+               break;
+       case SR_CONF_TRIGGER_SOURCE:
+               tmp_str = g_variant_get_string(data, NULL);
+               for (i = 0; i < ARRAY_SIZE(trigger_sources); i++) {
+                       if (!strcmp(trigger_sources[i], tmp_str)) {
+                               g_free(devc->trigger_source);
+                               devc->trigger_source = g_strdup(trigger_sources[i]);
+                               if (!strcmp(devc->trigger_source, "AC Line"))
+                                       tmp_str = "ACL";
+                               else if (!strcmp(devc->trigger_source, "CH1"))
+                                       tmp_str = "CHAN1";
+                               else if (!strcmp(devc->trigger_source, "CH2"))
+                                       tmp_str = "CHAN2";
+                               else
+                                       tmp_str = (char *)devc->trigger_source;
+                               ret = set_cfg(sdi, ":TRIG:EDGE:SOUR %s", tmp_str);
+                               break;
+                       }
+               }
+               if (i == ARRAY_SIZE(trigger_sources))
+                       ret = SR_ERR_ARG;
+               break;
+       case SR_CONF_VDIV:
+               if (!probe_group) {
+                       sr_err("No probe group specified.");
+                       return SR_ERR_PROBE_GROUP;
+               }
+               g_variant_get(data, "(tt)", &p, &q);
+               for (i = 0; i < 2; i++) {
+                       if (probe_group == &devc->analog_groups[i]) {
+                               for (j = 0; j < ARRAY_SIZE(vdivs); j++) {
+                                       if (vdivs[j][0] != p || vdivs[j][1] != q)
+                                               continue;
+                                       devc->vdiv[i] = (float)p / q;
+                                       return set_cfg(sdi, ":CHAN%d:SCAL %.3f", i + 1,
+                                                       devc->vdiv[i]);
+                               }
+                               return SR_ERR_ARG;
+                       }
+               }
+               return SR_ERR_NA;
+       case SR_CONF_COUPLING:
+               if (!probe_group) {
+                       sr_err("No probe group specified.");
+                       return SR_ERR_PROBE_GROUP;
+               }
+               tmp_str = g_variant_get_string(data, NULL);
+               for (i = 0; i < 2; i++) {
+                       if (probe_group == &devc->analog_groups[i]) {
+                               for (j = 0; j < ARRAY_SIZE(coupling); j++) {
+                                       if (!strcmp(tmp_str, coupling[j])) {
+                                               g_free(devc->coupling[i]);
+                                               devc->coupling[i] = g_strdup(coupling[j]);
+                                               return set_cfg(sdi, ":CHAN%d:COUP %s", i + 1,
+                                                               devc->coupling[i]);
+                                       }
+                               }
+                               return SR_ERR_ARG;
+                       }
+               }
+               return SR_ERR_NA;
+       default:
+               ret = SR_ERR_NA;
+               break;
+       }
+
+       return ret;
+}
+
+static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
+               const struct sr_probe_group *probe_group)
+{
+       GVariant *tuple, *rational[2];
+       GVariantBuilder gvb;
+       unsigned int i;
+       struct dev_context *devc;
+
+       if (key == SR_CONF_SCAN_OPTIONS) {
+               *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
+                               hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
+               return SR_OK;
+       } else if (key == SR_CONF_DEVICE_OPTIONS && probe_group == NULL) {
+               *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
+                       hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
+               return SR_OK;
+       }
+
+       /* Every other option requires a valid device instance. */
+       if (!sdi || !(devc = sdi->priv))
+               return SR_ERR_ARG;
+
+       /* If a probe group is specified, it must be a valid one. */
+       if (probe_group) {
+               if (probe_group != &devc->analog_groups[0]
+                               && probe_group != &devc->analog_groups[1]) {
+                       sr_err("Invalid probe group specified.");
+                       return SR_ERR;
+               }
+       }
+
+       switch (key) {
+               break;
+       case SR_CONF_DEVICE_OPTIONS:
+               if (!probe_group) {
+                       sr_err("No probe group specified.");
+                       return SR_ERR_PROBE_GROUP;
+               }
+               if (probe_group == &devc->digital_group) {
+                       *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
+                               NULL, 0, sizeof(int32_t));
+                       return SR_OK;
+               } else {
+                       for (i = 0; i < 2; i++) {
+                               if (probe_group == &devc->analog_groups[i]) {
+                                       *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
+                                               analog_hwcaps, ARRAY_SIZE(analog_hwcaps), sizeof(int32_t));
+                                       return SR_OK;
+                               }
+                       }
+                       return SR_ERR_NA;
+               }
+               break;
+       case SR_CONF_COUPLING:
+               if (!probe_group) {
+                       sr_err("No probe group specified.");
+                       return SR_ERR_PROBE_GROUP;
+               }
+               *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling));
+               break;
+       case SR_CONF_VDIV:
+               if (!probe_group) {
+                       sr_err("No probe group specified.");
+                       return SR_ERR_PROBE_GROUP;
+               }
+               g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
+               for (i = 0; i < ARRAY_SIZE(vdivs); i++) {
+                       rational[0] = g_variant_new_uint64(vdivs[i][0]);
+                       rational[1] = g_variant_new_uint64(vdivs[i][1]);
+                       tuple = g_variant_new_tuple(rational, 2);
+                       g_variant_builder_add_value(&gvb, tuple);
+               }
+               *data = g_variant_builder_end(&gvb);
+               break;
+       case SR_CONF_TIMEBASE:
+               g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
+               for (i = 0; i < ARRAY_SIZE(timebases); i++) {
+                       rational[0] = g_variant_new_uint64(timebases[i][0]);
+                       rational[1] = g_variant_new_uint64(timebases[i][1]);
+                       tuple = g_variant_new_tuple(rational, 2);
+                       g_variant_builder_add_value(&gvb, tuple);
+               }
+               *data = g_variant_builder_end(&gvb);
+               break;
+       case SR_CONF_TRIGGER_SOURCE:
+               *data = g_variant_new_strv(trigger_sources,
+                               devc->has_digital ? ARRAY_SIZE(trigger_sources) : 4);
+               break;
+       default:
+               return SR_ERR_NA;
+       }
+
+       return SR_OK;
+}
+
+static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
+{
+       struct sr_serial_dev_inst *serial;
+       struct dev_context *devc;
+       struct sr_probe *probe;
+       GSList *l;
+       char cmd[256];
+
+       if (sdi->status != SR_ST_ACTIVE)
+               return SR_ERR_DEV_CLOSED;
+
+       serial = sdi->conn;
+       devc = sdi->priv;
+
+       for (l = sdi->probes; l; l = l->next) {
+               probe = l->data;
+               sr_dbg("handling probe %s", probe->name);
+               if (probe->type == SR_PROBE_ANALOG) {
+                       if (probe->enabled)
+                               devc->enabled_analog_probes = g_slist_append(
+                                               devc->enabled_analog_probes, probe);
+                       if (probe->enabled != devc->analog_channels[probe->index]) {
+                               /* Enabled channel is currently disabled, or vice versa. */
+                               sprintf(cmd, ":CHAN%d:DISP %s", probe->index + 1,
+                                               probe->enabled ? "ON" : "OFF");
+                               if (rigol_ds_send(sdi, cmd) != SR_OK)
+                                       return SR_ERR;
+                       }
+               } else if (probe->type == SR_PROBE_LOGIC) {
+                       if (probe->enabled)
+                               devc->enabled_digital_probes = g_slist_append(
+                                               devc->enabled_digital_probes, probe);
+                       if (probe->enabled != devc->digital_channels[probe->index]) {
+                               /* Enabled channel is currently disabled, or vice versa. */
+                               sprintf(cmd, ":DIG%d:TURN %s", probe->index,
+                                               probe->enabled ? "ON" : "OFF");
+                               if (rigol_ds_send(sdi, cmd) != SR_OK)
+                                       return SR_ERR;
+                       }
+               }
+       }
+       if (!devc->enabled_analog_probes && !devc->enabled_digital_probes)
+               return SR_ERR;
+
+       sr_source_add(serial->fd, G_IO_IN, 50, rigol_ds_receive, (void *)sdi);
+
+       /* Send header packet to the session bus. */
+       std_session_send_df_header(cb_data, LOG_PREFIX);
+
+       /* Fetch the first frame. */
+       if (devc->enabled_analog_probes) {
+               devc->channel_frame = devc->enabled_analog_probes->data;
+               if (rigol_ds_send(sdi, ":WAV:DATA? CHAN%d",
+                               devc->channel_frame->index + 1) != SR_OK)
+                       return SR_ERR;
+       } else {
+               devc->channel_frame = devc->enabled_digital_probes->data;
+               if (rigol_ds_send(sdi, ":WAV:DATA? DIG") != SR_OK)
+                       return SR_ERR;
+       }
+
+       devc->num_frame_bytes = 0;
+
+       return SR_OK;
+}
+
+static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
+{
+       struct dev_context *devc;
+       struct sr_serial_dev_inst *serial;
+
+       (void)cb_data;
+
+       devc = sdi->priv;
+
+       if (sdi->status != SR_ST_ACTIVE) {
+               sr_err("Device inactive, can't stop acquisition.");
+               return SR_ERR;
+       }
+
+       g_slist_free(devc->enabled_analog_probes);
+       g_slist_free(devc->enabled_digital_probes);
+       devc->enabled_analog_probes = NULL;
+       devc->enabled_digital_probes = NULL;
+       serial = sdi->conn;
+       sr_source_remove(serial->fd);
+
+       return SR_OK;
+}
+
+SR_PRIV struct sr_dev_driver rigol_ds_driver_info = {
+       .name = "rigol-ds",
+       .longname = "Rigol DS",
+       .api_version = 1,
+       .init = init,
+       .cleanup = cleanup,
+       .scan = scan,
+       .dev_list = dev_list,
+       .dev_clear = dev_clear,
+       .config_get = config_get,
+       .config_set = config_set,
+       .config_list = config_list,
+       .dev_open = dev_open,
+       .dev_close = dev_close,
+       .dev_acquisition_start = dev_acquisition_start,
+       .dev_acquisition_stop = dev_acquisition_stop,
+       .priv = NULL,
+};
diff --git a/hardware/rigol-ds/protocol.c b/hardware/rigol-ds/protocol.c
new file mode 100644 (file)
index 0000000..19e660d
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2012 Martin Ling <martin-git@earth.li>
+ * Copyright (C) 2013 Bert Vermeulen <bert@biot.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 <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <math.h>
+#include <glib.h>
+#include "libsigrok.h"
+#include "libsigrok-internal.h"
+#include "protocol.h"
+
+SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
+{
+       struct sr_dev_inst *sdi;
+       struct sr_serial_dev_inst *serial;
+       struct dev_context *devc;
+       struct sr_datafeed_packet packet;
+       struct sr_datafeed_analog analog;
+       struct sr_datafeed_logic logic;
+       unsigned char buf[DIGITAL_WAVEFORM_SIZE];
+       double vdiv, offset;
+       float data[ANALOG_WAVEFORM_SIZE];
+       int len, i, waveform_size;
+       struct sr_probe *probe;
+
+       (void)fd;
+
+       if (!(sdi = cb_data))
+               return TRUE;
+
+       if (!(devc = sdi->priv))
+               return TRUE;
+
+       serial = sdi->conn;
+
+       if (revents == G_IO_IN) {
+               probe = devc->channel_frame;
+               waveform_size = probe->type == SR_PROBE_ANALOG ?
+                               ANALOG_WAVEFORM_SIZE : DIGITAL_WAVEFORM_SIZE;
+               len = serial_read(serial, buf, waveform_size - devc->num_frame_bytes);
+               sr_dbg("Received %d bytes.", len);
+               if (len == -1)
+                       return TRUE;
+
+               if (devc->num_frame_bytes == 0) {
+                       /* Start of a new frame. */
+                       packet.type = SR_DF_FRAME_BEGIN;
+                       sr_session_send(sdi, &packet);
+               }
+
+               if (probe->type == SR_PROBE_ANALOG) {
+                       for (i = 0; i < len; i++) {
+                               vdiv = devc->vdiv[probe->index];
+                               offset = devc->vert_offset[probe->index];
+                               data[i] = vdiv / 25.6 * (128 - buf[i]) - offset;
+                       }
+                       analog.probes = g_slist_append(NULL, probe);
+                       analog.num_samples = len;
+                       analog.data = data;
+                       analog.mq = SR_MQ_VOLTAGE;
+                       analog.unit = SR_UNIT_VOLT;
+                       analog.mqflags = 0;
+                       packet.type = SR_DF_ANALOG;
+                       packet.payload = &analog;
+                       sr_session_send(cb_data, &packet);
+                       g_slist_free(analog.probes);
+
+                       if (len != ANALOG_WAVEFORM_SIZE)
+                               /* Don't have the whole frame yet. */
+                               return TRUE;
+               } else {
+                       logic.length = len - 10;
+                       logic.unitsize = 2;
+                       logic.data = buf + 10;
+                       packet.type = SR_DF_LOGIC;
+                       packet.payload = &logic;
+                       sr_session_send(cb_data, &packet);
+
+                       if (len != DIGITAL_WAVEFORM_SIZE)
+                               /* Don't have the whole frame yet. */
+                               return TRUE;
+               }
+
+               /* End of the frame. */
+               packet.type = SR_DF_FRAME_END;
+               sr_session_send(sdi, &packet);
+               devc->num_frame_bytes = 0;
+
+               if (devc->enabled_analog_probes
+                               && devc->channel_frame == devc->enabled_analog_probes->data
+                               && devc->enabled_analog_probes->next != NULL) {
+                       /* We got the frame for the first analog channel, but
+                        * there's a second analog channel. */
+                       devc->channel_frame = devc->enabled_analog_probes->next->data;
+                       rigol_ds_send(sdi, ":WAV:DATA? CHAN%c",
+                                       devc->channel_frame->name[2]);
+               } else {
+                       /* Done with both analog channels in this frame. */
+                       if (devc->enabled_digital_probes
+                                       && devc->channel_frame != devc->enabled_digital_probes->data) {
+                               /* Now we need to get the digital data. */
+                               devc->channel_frame = devc->enabled_digital_probes->data;
+                               rigol_ds_send(sdi, ":WAV:DATA? DIG");
+                       } else if (++devc->num_frames == devc->limit_frames) {
+                               /* End of last frame. */
+                               packet.type = SR_DF_END;
+                               sr_session_send(sdi, &packet);
+                               sdi->driver->dev_acquisition_stop(sdi, cb_data);
+                       } else {
+                               /* Get the next frame, starting with the first analog channel. */
+                               if (devc->enabled_analog_probes) {
+                                       devc->channel_frame = devc->enabled_analog_probes->data;
+                                       rigol_ds_send(sdi, ":WAV:DATA? CHAN%c",
+                                                       devc->channel_frame->name[2]);
+                               } else {
+                                       devc->channel_frame = devc->enabled_digital_probes->data;
+                                       rigol_ds_send(sdi, ":WAV:DATA? DIG");
+                               }
+                       }
+               }
+       }
+
+       return TRUE;
+}
+
+SR_PRIV int rigol_ds_send(const struct sr_dev_inst *sdi, const char *format, ...)
+{
+       va_list args;
+       char buf[256];
+       int len, out, ret;
+
+       va_start(args, format);
+       len = vsnprintf(buf, 255, format, args);
+       va_end(args);
+       strcat(buf, "\n");
+       len++;
+       out = serial_write(sdi->conn, buf, len);
+       buf[len - 1] = '\0';
+       if (out != len) {
+               sr_dbg("Only sent %d/%d bytes of '%s'.", out, len, buf);
+               ret = SR_ERR;
+       } else {
+               sr_spew("Sent '%s'.", buf);
+               ret = SR_OK;
+       }
+
+       return ret;
+}
+
+static int get_cfg(const struct sr_dev_inst *sdi, char *cmd, char *reply)
+{
+       int len;
+
+       if (rigol_ds_send(sdi, cmd) != SR_OK)
+               return SR_ERR;
+
+       if ((len = serial_read(sdi->conn, reply, 255)) < 0)
+               return SR_ERR;
+       reply[len] = '\0';
+       sr_spew("Received '%s'.", reply);
+
+       return SR_OK;
+}
+
+static int get_cfg_float(const struct sr_dev_inst *sdi, char *cmd, float *f)
+{
+       char buf[256], *e;
+
+       if (get_cfg(sdi, cmd, buf) != SR_OK)
+               return SR_ERR;
+       *f = strtof(buf, &e);
+       if (e == buf || (fpclassify(*f) & (FP_ZERO | FP_NORMAL)) == 0) {
+               sr_dbg("failed to parse response to '%s': '%s'", cmd, buf);
+               return SR_ERR;
+       }
+
+       return SR_OK;
+}
+
+static int get_cfg_string(const struct sr_dev_inst *sdi, char *cmd, char **buf)
+{
+
+       if (!(*buf = g_try_malloc0(256)))
+               return SR_ERR_MALLOC;
+
+       if (get_cfg(sdi, cmd, *buf) != SR_OK)
+               return SR_ERR;
+
+       return SR_OK;
+}
+
+SR_PRIV int rigol_ds_get_dev_cfg(const struct sr_dev_inst *sdi)
+{
+       struct dev_context *devc;
+       char *t_s, *cmd;
+       int i, res;
+
+       devc = sdi->priv;
+
+       /* Analog channel state. */
+       if (get_cfg_string(sdi, ":CHAN1:DISP?", &t_s) != SR_OK)
+               return SR_ERR;
+       devc->analog_channels[0] = !strcmp(t_s, "ON") ? TRUE : FALSE;
+       g_free(t_s);
+       if (get_cfg_string(sdi, ":CHAN2:DISP?", &t_s) != SR_OK)
+               return SR_ERR;
+       devc->analog_channels[1] = !strcmp(t_s, "ON") ? TRUE : FALSE;
+       g_free(t_s);
+       sr_dbg("Current analog channel state CH1 %s CH2 %s",
+                       devc->analog_channels[0] ? "on" : "off",
+                       devc->analog_channels[1] ? "on" : "off");
+
+       /* Digital channel state. */
+       if (devc->has_digital) {
+               sr_dbg("Current digital channel state:");
+               for (i = 0; i < 16; i++) {
+                       cmd = g_strdup_printf(":DIG%d:TURN?", i);
+                       res = get_cfg_string(sdi, cmd, &t_s);
+                       g_free(cmd);
+                       if (res != SR_OK)
+                               return SR_ERR;
+                       devc->digital_channels[i] = !strcmp(t_s, "ON") ? TRUE : FALSE;
+                       g_free(t_s);
+                       sr_dbg("D%d: %s", i, devc->digital_channels[i] ? "on" : "off");
+               }
+       }
+
+       /* Timebase. */
+       if (get_cfg_float(sdi, ":TIM:SCAL?", &devc->timebase) != SR_OK)
+               return SR_ERR;
+       sr_dbg("Current timebase %f", devc->timebase);
+
+       /* Vertical gain. */
+       if (get_cfg_float(sdi, ":CHAN1:SCAL?", &devc->vdiv[0]) != SR_OK)
+               return SR_ERR;
+       if (get_cfg_float(sdi, ":CHAN2:SCAL?", &devc->vdiv[1]) != SR_OK)
+               return SR_ERR;
+       sr_dbg("Current vertical gain CH1 %f CH2 %f", devc->vdiv[0], devc->vdiv[1]);
+
+       /* Vertical offset. */
+       if (get_cfg_float(sdi, ":CHAN1:OFFS?", &devc->vert_offset[0]) != SR_OK)
+               return SR_ERR;
+       if (get_cfg_float(sdi, ":CHAN2:OFFS?", &devc->vert_offset[1]) != SR_OK)
+               return SR_ERR;
+       sr_dbg("Current vertical offset CH1 %f CH2 %f", devc->vert_offset[0],
+                       devc->vert_offset[1]);
+
+       /* Coupling. */
+       if (get_cfg_string(sdi, ":CHAN1:COUP?", &devc->coupling[0]) != SR_OK)
+               return SR_ERR;
+       if (get_cfg_string(sdi, ":CHAN2:COUP?", &devc->coupling[1]) != SR_OK)
+               return SR_ERR;
+       sr_dbg("Current coupling CH1 %s CH2 %s", devc->coupling[0],
+                       devc->coupling[1]);
+
+       /* Trigger source. */
+       if (get_cfg_string(sdi, ":TRIG:EDGE:SOUR?", &devc->trigger_source) != SR_OK)
+               return SR_ERR;
+       sr_dbg("Current trigger source %s", devc->trigger_source);
+
+       /* Horizontal trigger position. */
+       if (get_cfg_float(sdi, ":TIM:OFFS?", &devc->horiz_triggerpos) != SR_OK)
+               return SR_ERR;
+       sr_dbg("Current horizontal trigger position %f", devc->horiz_triggerpos);
+
+       /* Trigger slope. */
+       if (get_cfg_string(sdi, ":TRIG:EDGE:SLOP?", &devc->trigger_slope) != SR_OK)
+               return SR_ERR;
+       sr_dbg("Current trigger slope %s", devc->trigger_slope);
+
+       return SR_OK;
+}
diff --git a/hardware/rigol-ds/protocol.h b/hardware/rigol-ds/protocol.h
new file mode 100644 (file)
index 0000000..cce22b2
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2012 Martin Ling <martin-git@earth.li>
+ * Copyright (C) 2013 Bert Vermeulen <bert@biot.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/>.
+ */
+
+#ifndef LIBSIGROK_HARDWARE_RIGOL_DS_PROTOCOL_H
+#define LIBSIGROK_HARDWARE_RIGOL_DS_PROTOCOL_H
+
+#include <stdint.h>
+#include "libsigrok.h"
+#include "libsigrok-internal.h"
+
+/* Message logging helpers with subsystem-specific prefix string. */
+#define LOG_PREFIX "rigol-ds: "
+#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 ANALOG_WAVEFORM_SIZE 600
+#define DIGITAL_WAVEFORM_SIZE 1210
+
+/** Private, per-device-instance driver context. */
+struct dev_context {
+       /* Device features */
+       gboolean has_digital;
+
+       /* Probe groups */
+       struct sr_probe_group analog_groups[2];
+       struct sr_probe_group digital_group;
+
+       /* Acquisition settings */
+       GSList *enabled_analog_probes;
+       GSList *enabled_digital_probes;
+       uint64_t limit_frames;
+       void *cb_data;
+
+       /* Device settings */
+       gboolean analog_channels[2];
+       gboolean digital_channels[16];
+       float timebase;
+       float vdiv[2];
+       float vert_offset[2];
+       char *trigger_source;
+       float horiz_triggerpos;
+       char *trigger_slope;
+       char *coupling[2];
+
+       /* Operational state */
+       uint64_t num_frames;
+       uint64_t num_frame_bytes;
+       struct sr_probe *channel_frame;
+};
+
+SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data);
+SR_PRIV int rigol_ds_send(const struct sr_dev_inst *sdi, const char *format, ...);
+SR_PRIV int rigol_ds_get_dev_cfg(const struct sr_dev_inst *sdi);
+
+#endif
diff --git a/hardware/rigol-ds1xx2/Makefile.am b/hardware/rigol-ds1xx2/Makefile.am
deleted file mode 100644 (file)
index a538df0..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-##
-## This file is part of the libsigrok project.
-##
-## Copyright (C) 2012 Martin Ling <martin-git@earth.li>
-##
-## 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/>.
-##
-
-if HW_RIGOL_DS1XX2
-
-# Local lib, this is NOT meant to be installed!
-noinst_LTLIBRARIES = libsigrok_hw_rigol_ds1xx2.la
-
-libsigrok_hw_rigol_ds1xx2_la_SOURCES = \
-       api.c \
-       protocol.c \
-       protocol.h
-
-libsigrok_hw_rigol_ds1xx2_la_CFLAGS = \
-       -I$(top_srcdir)
-
-endif
diff --git a/hardware/rigol-ds1xx2/api.c b/hardware/rigol-ds1xx2/api.c
deleted file mode 100644 (file)
index d6f055e..0000000
+++ /dev/null
@@ -1,758 +0,0 @@
-/*
- * This file is part of the libsigrok project.
- *
- * Copyright (C) 2012 Martin Ling <martin-git@earth.li>
- * Copyright (C) 2013 Bert Vermeulen <bert@biot.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 <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-#include "libsigrok.h"
-#include "libsigrok-internal.h"
-#include "protocol.h"
-
-#define NUM_TIMEBASE  12
-#define NUM_VDIV      8
-
-static const int32_t hwopts[] = {
-       SR_CONF_CONN,
-};
-
-static const int32_t hwcaps[] = {
-       SR_CONF_OSCILLOSCOPE,
-       SR_CONF_TIMEBASE,
-       SR_CONF_TRIGGER_SOURCE,
-       SR_CONF_TRIGGER_SLOPE,
-       SR_CONF_HORIZ_TRIGGERPOS,
-       SR_CONF_NUM_TIMEBASE,
-};
-
-static const int32_t analog_hwcaps[] = {
-       SR_CONF_NUM_VDIV,
-       SR_CONF_VDIV,
-       SR_CONF_COUPLING,
-};
-
-static const uint64_t timebases[][2] = {
-       /* nanoseconds */
-       { 2, 1000000000 },
-       { 5, 1000000000 },
-       { 10, 1000000000 },
-       { 20, 1000000000 },
-       { 50, 1000000000 },
-       { 100, 1000000000 },
-       { 500, 1000000000 },
-       /* microseconds */
-       { 1, 1000000 },
-       { 2, 1000000 },
-       { 5, 1000000 },
-       { 10, 1000000 },
-       { 20, 1000000 },
-       { 50, 1000000 },
-       { 100, 1000000 },
-       { 200, 1000000 },
-       { 500, 1000000 },
-       /* milliseconds */
-       { 1, 1000 },
-       { 2, 1000 },
-       { 5, 1000 },
-       { 10, 1000 },
-       { 20, 1000 },
-       { 50, 1000 },
-       { 100, 1000 },
-       { 200, 1000 },
-       { 500, 1000 },
-       /* seconds */
-       { 1, 1 },
-       { 2, 1 },
-       { 5, 1 },
-       { 10, 1 },
-       { 20, 1 },
-       { 50, 1 },
-};
-
-static const uint64_t vdivs[][2] = {
-       /* millivolts */
-       { 2, 1000 },
-       { 5, 1000 },
-       { 10, 1000 },
-       { 20, 1000 },
-       { 50, 1000 },
-       { 100, 1000 },
-       { 200, 1000 },
-       { 500, 1000 },
-       /* volts */
-       { 1, 1 },
-       { 2, 1 },
-       { 5, 1 },
-       { 10, 1 },
-};
-
-static const char *trigger_sources[] = {
-       "CH1",
-       "CH2",
-       "EXT",
-       "AC Line",
-       "D0",
-       "D1",
-       "D2",
-       "D3",
-       "D4",
-       "D5",
-       "D6",
-       "D7",
-       "D8",
-       "D9",
-       "D10",
-       "D11",
-       "D12",
-       "D13",
-       "D14",
-       "D15",
-};
-
-static const char *coupling[] = {
-       "AC",
-       "DC",
-       "GND",
-};
-
-static const char *supported_models[] = {
-       "DS1052E",
-       "DS1102E",
-       "DS1152E",
-       "DS1052D",
-       "DS1102D",
-       "DS1152D",
-};
-
-SR_PRIV struct sr_dev_driver rigol_ds1xx2_driver_info;
-static struct sr_dev_driver *di = &rigol_ds1xx2_driver_info;
-
-static void clear_helper(void *priv)
-{
-       struct dev_context *devc;
-
-       devc = priv;
-       g_free(devc->coupling[0]);
-       g_free(devc->coupling[1]);
-       g_free(devc->trigger_source);
-       g_free(devc->trigger_slope);
-       g_slist_free(devc->analog_groups[0].probes);
-       g_slist_free(devc->analog_groups[1].probes);
-       g_slist_free(devc->digital_group.probes);
-}
-
-static int dev_clear(void)
-{
-       return std_dev_clear(di, clear_helper);
-}
-
-static int set_cfg(const struct sr_dev_inst *sdi, const char *format, ...)
-{
-       va_list args;
-       char buf[256];
-
-       va_start(args, format);
-       vsnprintf(buf, 255, format, args);
-       va_end(args);
-       if (rigol_ds1xx2_send(sdi, buf) != SR_OK)
-               return SR_ERR;
-
-       /* When setting a bunch of parameters in a row, the DS1052E scrambles
-        * some of them unless there is at least 100ms delay in between. */
-       sr_spew("delay %dms", 100);
-       g_usleep(100000);
-
-       return SR_OK;
-}
-
-static int init(struct sr_context *sr_ctx)
-{
-       return std_init(sr_ctx, di, LOG_PREFIX);
-}
-
-static int probe_port(const char *port, GSList **devices)
-{
-       struct dev_context *devc;
-       struct sr_dev_inst *sdi;
-       struct sr_serial_dev_inst *serial;
-       struct sr_probe *probe;
-       unsigned int i;
-       int len, num_tokens;
-       gboolean matched, has_digital;
-       const char *manufacturer, *model, *version;
-       char buf[256];
-       gchar **tokens, *channel_name;
-
-       *devices = NULL;
-       if (!(serial = sr_serial_dev_inst_new(port, NULL)))
-               return SR_ERR_MALLOC;
-
-       if (serial_open(serial, SERIAL_RDWR) != SR_OK)
-               return SR_ERR;
-       len = serial_write(serial, "*IDN?", 5);
-       len = serial_read(serial, buf, sizeof(buf));
-       if (serial_close(serial) != SR_OK)
-               return SR_ERR;
-
-       sr_serial_dev_inst_free(serial);
-
-       if (len == 0)
-               return SR_ERR_NA;
-
-       buf[len] = 0;
-       tokens = g_strsplit(buf, ",", 0);
-       sr_dbg("response: %s [%s]", port, buf);
-
-       for (num_tokens = 0; tokens[num_tokens] != NULL; num_tokens++);
-
-       if (num_tokens < 4) {
-               g_strfreev(tokens);
-               return SR_ERR_NA;
-       }
-
-       manufacturer = tokens[0];
-       model = tokens[1];
-       version = tokens[3];
-
-       if (strcmp(manufacturer, "Rigol Technologies")) {
-               g_strfreev(tokens);
-               return SR_ERR_NA;
-       }
-
-       matched = has_digital = FALSE;
-       for (i = 0; i < ARRAY_SIZE(supported_models); i++) {
-               if (!strcmp(model, supported_models[i])) {
-                       matched = TRUE;
-                       has_digital = g_str_has_suffix(model, "D");
-                       break;
-               }
-       }
-
-       if (!matched || !(sdi = sr_dev_inst_new(0, SR_ST_ACTIVE,
-               manufacturer, model, version))) {
-               g_strfreev(tokens);
-               return SR_ERR_NA;
-       }
-
-       g_strfreev(tokens);
-
-       if (!(sdi->conn = sr_serial_dev_inst_new(port, NULL)))
-               return SR_ERR_MALLOC;
-       sdi->driver = di;
-       sdi->inst_type = SR_INST_SERIAL;
-
-       if (!(devc = g_try_malloc0(sizeof(struct dev_context))))
-               return SR_ERR_MALLOC;
-       devc->limit_frames = 0;
-       devc->has_digital = has_digital;
-
-       for (i = 0; i < 2; i++) {
-               channel_name = (i == 0 ? "CH1" : "CH2");
-               if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE, channel_name)))
-                       return SR_ERR_MALLOC;
-               sdi->probes = g_slist_append(sdi->probes, probe);
-               devc->analog_groups[i].name = channel_name;
-               devc->analog_groups[i].probes = g_slist_append(NULL, probe);
-               sdi->probe_groups = g_slist_append(sdi->probe_groups,
-                               &devc->analog_groups[i]);
-       }
-
-       if (devc->has_digital) {
-               for (i = 0; i < 16; i++) {
-                       if (!(channel_name = g_strdup_printf("D%d", i)))
-                               return SR_ERR_MALLOC;
-                       probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, channel_name);
-                       g_free(channel_name);
-                       if (!probe)
-                               return SR_ERR_MALLOC;
-                       sdi->probes = g_slist_append(sdi->probes, probe);
-                       devc->digital_group.probes = g_slist_append(
-                                       devc->digital_group.probes, probe);
-                       devc->digital_group.name = "LA";
-                       sdi->probe_groups = g_slist_append(sdi->probe_groups,
-                                       &devc->digital_group);
-               }
-       }
-       sdi->priv = devc;
-
-       *devices = g_slist_append(NULL, sdi);
-
-       return SR_OK;
-}
-
-static GSList *scan(GSList *options)
-{
-       struct drv_context *drvc;
-       struct sr_config *src;
-       GSList *l, *devices;
-       GDir *dir;
-       int ret;
-       const gchar *dev_name;
-       gchar *port = NULL;
-
-       drvc = di->priv;
-
-       for (l = options; l; l = l->next) {
-               src = l->data;
-               if (src->key == SR_CONF_CONN) {
-                       port = (char *)g_variant_get_string(src->data, NULL);
-                       break;
-               }
-       }
-
-       devices = NULL;
-       if (port) {
-               if (probe_port(port, &devices) == SR_ERR_MALLOC)
-                       return NULL;
-       } else {
-               if (!(dir = g_dir_open("/sys/class/usbmisc/", 0, NULL)))
-                       if (!(dir = g_dir_open("/sys/class/usb/", 0, NULL)))
-                               return NULL;
-               while ((dev_name = g_dir_read_name(dir))) {
-                       if (strncmp(dev_name, "usbtmc", 6))
-                               continue;
-                       port = g_strconcat("/dev/", dev_name, NULL);
-                       ret = probe_port(port, &devices);
-                       g_free(port);
-                       if (ret == SR_ERR_MALLOC) {
-                               g_dir_close(dir);
-                               return NULL;
-                       }
-               }
-               g_dir_close(dir);
-       }
-
-       /* Tack a copy of the newly found devices onto the driver list. */
-       l = g_slist_copy(devices);
-       drvc->instances = g_slist_concat(drvc->instances, l);
-
-       return devices;
-}
-
-static GSList *dev_list(void)
-{
-       return ((struct drv_context *)(di->priv))->instances;
-}
-
-static int dev_open(struct sr_dev_inst *sdi)
-{
-
-       if (serial_open(sdi->conn, SERIAL_RDWR) != SR_OK)
-               return SR_ERR;
-
-       if (rigol_ds1xx2_get_dev_cfg(sdi) != SR_OK)
-               return SR_ERR;
-
-       sdi->status = SR_ST_ACTIVE;
-
-       return SR_OK;
-}
-
-static int dev_close(struct sr_dev_inst *sdi)
-{
-       struct sr_serial_dev_inst *serial;
-
-       serial = sdi->conn;
-       if (serial && serial->fd != -1) {
-               serial_close(serial);
-               sdi->status = SR_ST_INACTIVE;
-       }
-
-       return SR_OK;
-}
-
-static int cleanup(void)
-{
-       return dev_clear();
-}
-
-static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
-               const struct sr_probe_group *probe_group)
-{
-       struct dev_context *devc;
-       unsigned int i;
-
-       if (!sdi || !(devc = sdi->priv))
-               return SR_ERR_ARG;
-
-       /* If a probe group is specified, it must be a valid one. */
-       if (probe_group) {
-               if (probe_group != &devc->analog_groups[0]
-                               && probe_group != &devc->analog_groups[1]) {
-                       sr_err("Invalid probe group specified.");
-                       return SR_ERR;
-               }
-       }
-
-       switch (id) {
-       case SR_CONF_NUM_TIMEBASE:
-               *data = g_variant_new_int32(NUM_TIMEBASE);
-               break;
-       case SR_CONF_NUM_VDIV:
-               if (!probe_group) {
-                       sr_err("No probe group specified.");
-                       return SR_ERR_PROBE_GROUP;
-               }
-               for (i = 0; i < 2; i++) {
-                       if (probe_group == &devc->analog_groups[i]) {
-                               *data = g_variant_new_int32(NUM_VDIV);
-                               return SR_OK;
-                       }
-               }
-               return SR_ERR_NA;
-       default:
-               return SR_ERR_NA;
-       }
-
-       return SR_OK;
-}
-
-static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
-               const struct sr_probe_group *probe_group)
-{
-       struct dev_context *devc;
-       uint64_t tmp_u64, p, q;
-       double t_dbl;
-       unsigned int i, j;
-       int ret;
-       const char *tmp_str;
-
-       if (!(devc = sdi->priv))
-               return SR_ERR_ARG;
-
-       if (sdi->status != SR_ST_ACTIVE)
-               return SR_ERR_DEV_CLOSED;
-
-       /* If a probe group is specified, it must be a valid one. */
-       if (probe_group) {
-               if (probe_group != &devc->analog_groups[0]
-                               && probe_group != &devc->analog_groups[1]) {
-                       sr_err("Invalid probe group specified.");
-                       return SR_ERR;
-               }
-       }
-
-       ret = SR_OK;
-       switch (id) {
-       case SR_CONF_LIMIT_FRAMES:
-               devc->limit_frames = g_variant_get_uint64(data);
-               break;
-       case SR_CONF_TRIGGER_SLOPE:
-               tmp_u64 = g_variant_get_uint64(data);
-               if (tmp_u64 != 0 && tmp_u64 != 1)
-                       return SR_ERR;
-               g_free(devc->trigger_slope);
-               devc->trigger_slope = g_strdup(tmp_u64 ? "POS" : "NEG");
-               ret = set_cfg(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope);
-               break;
-       case SR_CONF_HORIZ_TRIGGERPOS:
-               t_dbl = g_variant_get_double(data);
-               if (t_dbl < 0.0 || t_dbl > 1.0)
-                       return SR_ERR;
-               devc->horiz_triggerpos = t_dbl;
-               /* We have the trigger offset as a percentage of the frame, but
-                * need to express this in seconds. */
-               t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * NUM_TIMEBASE;
-               ret = set_cfg(sdi, ":TIM:OFFS %.6f", t_dbl);
-               break;
-       case SR_CONF_TIMEBASE:
-               g_variant_get(data, "(tt)", &p, &q);
-               for (i = 0; i < ARRAY_SIZE(timebases); i++) {
-                       if (timebases[i][0] == p && timebases[i][1] == q) {
-                               devc->timebase = (float)p / q;
-                               ret = set_cfg(sdi, ":TIM:SCAL %.9f", devc->timebase);
-                               break;
-                       }
-               }
-               if (i == ARRAY_SIZE(timebases))
-                       ret = SR_ERR_ARG;
-               break;
-       case SR_CONF_TRIGGER_SOURCE:
-               tmp_str = g_variant_get_string(data, NULL);
-               for (i = 0; i < ARRAY_SIZE(trigger_sources); i++) {
-                       if (!strcmp(trigger_sources[i], tmp_str)) {
-                               g_free(devc->trigger_source);
-                               devc->trigger_source = g_strdup(trigger_sources[i]);
-                               if (!strcmp(devc->trigger_source, "AC Line"))
-                                       tmp_str = "ACL";
-                               else if (!strcmp(devc->trigger_source, "CH1"))
-                                       tmp_str = "CHAN1";
-                               else if (!strcmp(devc->trigger_source, "CH2"))
-                                       tmp_str = "CHAN2";
-                               else
-                                       tmp_str = (char *)devc->trigger_source;
-                               ret = set_cfg(sdi, ":TRIG:EDGE:SOUR %s", tmp_str);
-                               break;
-                       }
-               }
-               if (i == ARRAY_SIZE(trigger_sources))
-                       ret = SR_ERR_ARG;
-               break;
-       case SR_CONF_VDIV:
-               if (!probe_group) {
-                       sr_err("No probe group specified.");
-                       return SR_ERR_PROBE_GROUP;
-               }
-               g_variant_get(data, "(tt)", &p, &q);
-               for (i = 0; i < 2; i++) {
-                       if (probe_group == &devc->analog_groups[i]) {
-                               for (j = 0; j < ARRAY_SIZE(vdivs); j++) {
-                                       if (vdivs[j][0] != p || vdivs[j][1] != q)
-                                               continue;
-                                       devc->vdiv[i] = (float)p / q;
-                                       return set_cfg(sdi, ":CHAN%d:SCAL %.3f", i + 1,
-                                                       devc->vdiv[i]);
-                               }
-                               return SR_ERR_ARG;
-                       }
-               }
-               return SR_ERR_NA;
-       case SR_CONF_COUPLING:
-               if (!probe_group) {
-                       sr_err("No probe group specified.");
-                       return SR_ERR_PROBE_GROUP;
-               }
-               tmp_str = g_variant_get_string(data, NULL);
-               for (i = 0; i < 2; i++) {
-                       if (probe_group == &devc->analog_groups[i]) {
-                               for (j = 0; j < ARRAY_SIZE(coupling); j++) {
-                                       if (!strcmp(tmp_str, coupling[j])) {
-                                               g_free(devc->coupling[i]);
-                                               devc->coupling[i] = g_strdup(coupling[j]);
-                                               return set_cfg(sdi, ":CHAN%d:COUP %s", i + 1,
-                                                               devc->coupling[i]);
-                                       }
-                               }
-                               return SR_ERR_ARG;
-                       }
-               }
-               return SR_ERR_NA;
-       default:
-               ret = SR_ERR_NA;
-               break;
-       }
-
-       return ret;
-}
-
-static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
-               const struct sr_probe_group *probe_group)
-{
-       GVariant *tuple, *rational[2];
-       GVariantBuilder gvb;
-       unsigned int i;
-       struct dev_context *devc;
-
-       if (key == SR_CONF_SCAN_OPTIONS) {
-               *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
-                               hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
-               return SR_OK;
-       } else if (key == SR_CONF_DEVICE_OPTIONS && probe_group == NULL) {
-               *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
-                       hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
-               return SR_OK;
-       }
-
-       /* Every other option requires a valid device instance. */
-       if (!sdi || !(devc = sdi->priv))
-               return SR_ERR_ARG;
-
-       /* If a probe group is specified, it must be a valid one. */
-       if (probe_group) {
-               if (probe_group != &devc->analog_groups[0]
-                               && probe_group != &devc->analog_groups[1]) {
-                       sr_err("Invalid probe group specified.");
-                       return SR_ERR;
-               }
-       }
-
-       switch (key) {
-               break;
-       case SR_CONF_DEVICE_OPTIONS:
-               if (!probe_group) {
-                       sr_err("No probe group specified.");
-                       return SR_ERR_PROBE_GROUP;
-               }
-               if (probe_group == &devc->digital_group) {
-                       *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
-                               NULL, 0, sizeof(int32_t));
-                       return SR_OK;
-               } else {
-                       for (i = 0; i < 2; i++) {
-                               if (probe_group == &devc->analog_groups[i]) {
-                                       *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
-                                               analog_hwcaps, ARRAY_SIZE(analog_hwcaps), sizeof(int32_t));
-                                       return SR_OK;
-                               }
-                       }
-                       return SR_ERR_NA;
-               }
-               break;
-       case SR_CONF_COUPLING:
-               if (!probe_group) {
-                       sr_err("No probe group specified.");
-                       return SR_ERR_PROBE_GROUP;
-               }
-               *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling));
-               break;
-       case SR_CONF_VDIV:
-               if (!probe_group) {
-                       sr_err("No probe group specified.");
-                       return SR_ERR_PROBE_GROUP;
-               }
-               g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
-               for (i = 0; i < ARRAY_SIZE(vdivs); i++) {
-                       rational[0] = g_variant_new_uint64(vdivs[i][0]);
-                       rational[1] = g_variant_new_uint64(vdivs[i][1]);
-                       tuple = g_variant_new_tuple(rational, 2);
-                       g_variant_builder_add_value(&gvb, tuple);
-               }
-               *data = g_variant_builder_end(&gvb);
-               break;
-       case SR_CONF_TIMEBASE:
-               g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
-               for (i = 0; i < ARRAY_SIZE(timebases); i++) {
-                       rational[0] = g_variant_new_uint64(timebases[i][0]);
-                       rational[1] = g_variant_new_uint64(timebases[i][1]);
-                       tuple = g_variant_new_tuple(rational, 2);
-                       g_variant_builder_add_value(&gvb, tuple);
-               }
-               *data = g_variant_builder_end(&gvb);
-               break;
-       case SR_CONF_TRIGGER_SOURCE:
-               *data = g_variant_new_strv(trigger_sources,
-                               devc->has_digital ? ARRAY_SIZE(trigger_sources) : 4);
-               break;
-       default:
-               return SR_ERR_NA;
-       }
-
-       return SR_OK;
-}
-
-static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
-{
-       struct sr_serial_dev_inst *serial;
-       struct dev_context *devc;
-       struct sr_probe *probe;
-       GSList *l;
-       char cmd[256];
-
-       if (sdi->status != SR_ST_ACTIVE)
-               return SR_ERR_DEV_CLOSED;
-
-       serial = sdi->conn;
-       devc = sdi->priv;
-
-       for (l = sdi->probes; l; l = l->next) {
-               probe = l->data;
-               sr_dbg("handling probe %s", probe->name);
-               if (probe->type == SR_PROBE_ANALOG) {
-                       if (probe->enabled)
-                               devc->enabled_analog_probes = g_slist_append(
-                                               devc->enabled_analog_probes, probe);
-                       if (probe->enabled != devc->analog_channels[probe->index]) {
-                               /* Enabled channel is currently disabled, or vice versa. */
-                               sprintf(cmd, ":CHAN%d:DISP %s", probe->index + 1,
-                                               probe->enabled ? "ON" : "OFF");
-                               if (rigol_ds1xx2_send(sdi, cmd) != SR_OK)
-                                       return SR_ERR;
-                       }
-               } else if (probe->type == SR_PROBE_LOGIC) {
-                       if (probe->enabled)
-                               devc->enabled_digital_probes = g_slist_append(
-                                               devc->enabled_digital_probes, probe);
-                       if (probe->enabled != devc->digital_channels[probe->index]) {
-                               /* Enabled channel is currently disabled, or vice versa. */
-                               sprintf(cmd, ":DIG%d:TURN %s", probe->index,
-                                               probe->enabled ? "ON" : "OFF");
-                               if (rigol_ds1xx2_send(sdi, cmd) != SR_OK)
-                                       return SR_ERR;
-                       }
-               }
-       }
-       if (!devc->enabled_analog_probes && !devc->enabled_digital_probes)
-               return SR_ERR;
-
-       sr_source_add(serial->fd, G_IO_IN, 50, rigol_ds1xx2_receive, (void *)sdi);
-
-       /* Send header packet to the session bus. */
-       std_session_send_df_header(cb_data, LOG_PREFIX);
-
-       /* Fetch the first frame. */
-       if (devc->enabled_analog_probes) {
-               devc->channel_frame = devc->enabled_analog_probes->data;
-               if (rigol_ds1xx2_send(sdi, ":WAV:DATA? CHAN%d",
-                               devc->channel_frame->index + 1) != SR_OK)
-                       return SR_ERR;
-       } else {
-               devc->channel_frame = devc->enabled_digital_probes->data;
-               if (rigol_ds1xx2_send(sdi, ":WAV:DATA? DIG") != SR_OK)
-                       return SR_ERR;
-       }
-
-       devc->num_frame_bytes = 0;
-
-       return SR_OK;
-}
-
-static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
-{
-       struct dev_context *devc;
-       struct sr_serial_dev_inst *serial;
-
-       (void)cb_data;
-
-       devc = sdi->priv;
-
-       if (sdi->status != SR_ST_ACTIVE) {
-               sr_err("Device inactive, can't stop acquisition.");
-               return SR_ERR;
-       }
-
-       g_slist_free(devc->enabled_analog_probes);
-       g_slist_free(devc->enabled_digital_probes);
-       devc->enabled_analog_probes = NULL;
-       devc->enabled_digital_probes = NULL;
-       serial = sdi->conn;
-       sr_source_remove(serial->fd);
-
-       return SR_OK;
-}
-
-SR_PRIV struct sr_dev_driver rigol_ds1xx2_driver_info = {
-       .name = "rigol-ds1xx2",
-       .longname = "Rigol DS1xx2",
-       .api_version = 1,
-       .init = init,
-       .cleanup = cleanup,
-       .scan = scan,
-       .dev_list = dev_list,
-       .dev_clear = dev_clear,
-       .config_get = config_get,
-       .config_set = config_set,
-       .config_list = config_list,
-       .dev_open = dev_open,
-       .dev_close = dev_close,
-       .dev_acquisition_start = dev_acquisition_start,
-       .dev_acquisition_stop = dev_acquisition_stop,
-       .priv = NULL,
-};
diff --git a/hardware/rigol-ds1xx2/protocol.c b/hardware/rigol-ds1xx2/protocol.c
deleted file mode 100644 (file)
index 0efff69..0000000
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * This file is part of the libsigrok project.
- *
- * Copyright (C) 2012 Martin Ling <martin-git@earth.li>
- * Copyright (C) 2013 Bert Vermeulen <bert@biot.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 <stdlib.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <math.h>
-#include <glib.h>
-#include "libsigrok.h"
-#include "libsigrok-internal.h"
-#include "protocol.h"
-
-SR_PRIV int rigol_ds1xx2_receive(int fd, int revents, void *cb_data)
-{
-       struct sr_dev_inst *sdi;
-       struct sr_serial_dev_inst *serial;
-       struct dev_context *devc;
-       struct sr_datafeed_packet packet;
-       struct sr_datafeed_analog analog;
-       struct sr_datafeed_logic logic;
-       unsigned char buf[DIGITAL_WAVEFORM_SIZE];
-       double vdiv, offset;
-       float data[ANALOG_WAVEFORM_SIZE];
-       int len, i, waveform_size;
-       struct sr_probe *probe;
-
-       (void)fd;
-
-       if (!(sdi = cb_data))
-               return TRUE;
-
-       if (!(devc = sdi->priv))
-               return TRUE;
-
-       serial = sdi->conn;
-
-       if (revents == G_IO_IN) {
-               probe = devc->channel_frame;
-               waveform_size = probe->type == SR_PROBE_ANALOG ?
-                               ANALOG_WAVEFORM_SIZE : DIGITAL_WAVEFORM_SIZE;
-               len = serial_read(serial, buf, waveform_size - devc->num_frame_bytes);
-               sr_dbg("Received %d bytes.", len);
-               if (len == -1)
-                       return TRUE;
-
-               if (devc->num_frame_bytes == 0) {
-                       /* Start of a new frame. */
-                       packet.type = SR_DF_FRAME_BEGIN;
-                       sr_session_send(sdi, &packet);
-               }
-
-               if (probe->type == SR_PROBE_ANALOG) {
-                       for (i = 0; i < len; i++) {
-                               vdiv = devc->vdiv[probe->index];
-                               offset = devc->vert_offset[probe->index];
-                               data[i] = vdiv / 25.6 * (128 - buf[i]) - offset;
-                       }
-                       analog.probes = g_slist_append(NULL, probe);
-                       analog.num_samples = len;
-                       analog.data = data;
-                       analog.mq = SR_MQ_VOLTAGE;
-                       analog.unit = SR_UNIT_VOLT;
-                       analog.mqflags = 0;
-                       packet.type = SR_DF_ANALOG;
-                       packet.payload = &analog;
-                       sr_session_send(cb_data, &packet);
-                       g_slist_free(analog.probes);
-
-                       if (len != ANALOG_WAVEFORM_SIZE)
-                               /* Don't have the whole frame yet. */
-                               return TRUE;
-               } else {
-                       logic.length = len - 10;
-                       logic.unitsize = 2;
-                       logic.data = buf + 10;
-                       packet.type = SR_DF_LOGIC;
-                       packet.payload = &logic;
-                       sr_session_send(cb_data, &packet);
-
-                       if (len != DIGITAL_WAVEFORM_SIZE)
-                               /* Don't have the whole frame yet. */
-                               return TRUE;
-               }
-
-               /* End of the frame. */
-               packet.type = SR_DF_FRAME_END;
-               sr_session_send(sdi, &packet);
-               devc->num_frame_bytes = 0;
-
-               if (devc->enabled_analog_probes
-                               && devc->channel_frame == devc->enabled_analog_probes->data
-                               && devc->enabled_analog_probes->next != NULL) {
-                       /* We got the frame for the first analog channel, but
-                        * there's a second analog channel. */
-                       devc->channel_frame = devc->enabled_analog_probes->next->data;
-                       rigol_ds1xx2_send(sdi, ":WAV:DATA? CHAN%c",
-                                       devc->channel_frame->name[2]);
-               } else {
-                       /* Done with both analog channels in this frame. */
-                       if (devc->enabled_digital_probes
-                                       && devc->channel_frame != devc->enabled_digital_probes->data) {
-                               /* Now we need to get the digital data. */
-                               devc->channel_frame = devc->enabled_digital_probes->data;
-                               rigol_ds1xx2_send(sdi, ":WAV:DATA? DIG");
-                       } else if (++devc->num_frames == devc->limit_frames) {
-                               /* End of last frame. */
-                               packet.type = SR_DF_END;
-                               sr_session_send(sdi, &packet);
-                               sdi->driver->dev_acquisition_stop(sdi, cb_data);
-                       } else {
-                               /* Get the next frame, starting with the first analog channel. */
-                               if (devc->enabled_analog_probes) {
-                                       devc->channel_frame = devc->enabled_analog_probes->data;
-                                       rigol_ds1xx2_send(sdi, ":WAV:DATA? CHAN%c",
-                                                       devc->channel_frame->name[2]);
-                               } else {
-                                       devc->channel_frame = devc->enabled_digital_probes->data;
-                                       rigol_ds1xx2_send(sdi, ":WAV:DATA? DIG");
-                               }
-                       }
-               }
-       }
-
-       return TRUE;
-}
-
-SR_PRIV int rigol_ds1xx2_send(const struct sr_dev_inst *sdi, const char *format, ...)
-{
-       va_list args;
-       char buf[256];
-       int len, out, ret;
-
-       va_start(args, format);
-       len = vsnprintf(buf, 255, format, args);
-       va_end(args);
-       strcat(buf, "\n");
-       len++;
-       out = serial_write(sdi->conn, buf, len);
-       buf[len - 1] = '\0';
-       if (out != len) {
-               sr_dbg("Only sent %d/%d bytes of '%s'.", out, len, buf);
-               ret = SR_ERR;
-       } else {
-               sr_spew("Sent '%s'.", buf);
-               ret = SR_OK;
-       }
-
-       return ret;
-}
-
-static int get_cfg(const struct sr_dev_inst *sdi, char *cmd, char *reply)
-{
-       int len;
-
-       if (rigol_ds1xx2_send(sdi, cmd) != SR_OK)
-               return SR_ERR;
-
-       if ((len = serial_read(sdi->conn, reply, 255)) < 0)
-               return SR_ERR;
-       reply[len] = '\0';
-       sr_spew("Received '%s'.", reply);
-
-       return SR_OK;
-}
-
-static int get_cfg_float(const struct sr_dev_inst *sdi, char *cmd, float *f)
-{
-       char buf[256], *e;
-
-       if (get_cfg(sdi, cmd, buf) != SR_OK)
-               return SR_ERR;
-       *f = strtof(buf, &e);
-       if (e == buf || (fpclassify(*f) & (FP_ZERO | FP_NORMAL)) == 0) {
-               sr_dbg("failed to parse response to '%s': '%s'", cmd, buf);
-               return SR_ERR;
-       }
-
-       return SR_OK;
-}
-
-static int get_cfg_string(const struct sr_dev_inst *sdi, char *cmd, char **buf)
-{
-
-       if (!(*buf = g_try_malloc0(256)))
-               return SR_ERR_MALLOC;
-
-       if (get_cfg(sdi, cmd, *buf) != SR_OK)
-               return SR_ERR;
-
-       return SR_OK;
-}
-
-SR_PRIV int rigol_ds1xx2_get_dev_cfg(const struct sr_dev_inst *sdi)
-{
-       struct dev_context *devc;
-       char *t_s, *cmd;
-       int i, res;
-
-       devc = sdi->priv;
-
-       /* Analog channel state. */
-       if (get_cfg_string(sdi, ":CHAN1:DISP?", &t_s) != SR_OK)
-               return SR_ERR;
-       devc->analog_channels[0] = !strcmp(t_s, "ON") ? TRUE : FALSE;
-       g_free(t_s);
-       if (get_cfg_string(sdi, ":CHAN2:DISP?", &t_s) != SR_OK)
-               return SR_ERR;
-       devc->analog_channels[1] = !strcmp(t_s, "ON") ? TRUE : FALSE;
-       g_free(t_s);
-       sr_dbg("Current analog channel state CH1 %s CH2 %s",
-                       devc->analog_channels[0] ? "on" : "off",
-                       devc->analog_channels[1] ? "on" : "off");
-
-       /* Digital channel state. */
-       if (devc->has_digital) {
-               sr_dbg("Current digital channel state:");
-               for (i = 0; i < 16; i++) {
-                       cmd = g_strdup_printf(":DIG%d:TURN?", i);
-                       res = get_cfg_string(sdi, cmd, &t_s);
-                       g_free(cmd);
-                       if (res != SR_OK)
-                               return SR_ERR;
-                       devc->digital_channels[i] = !strcmp(t_s, "ON") ? TRUE : FALSE;
-                       g_free(t_s);
-                       sr_dbg("D%d: %s", i, devc->digital_channels[i] ? "on" : "off");
-               }
-       }
-
-       /* Timebase. */
-       if (get_cfg_float(sdi, ":TIM:SCAL?", &devc->timebase) != SR_OK)
-               return SR_ERR;
-       sr_dbg("Current timebase %f", devc->timebase);
-
-       /* Vertical gain. */
-       if (get_cfg_float(sdi, ":CHAN1:SCAL?", &devc->vdiv[0]) != SR_OK)
-               return SR_ERR;
-       if (get_cfg_float(sdi, ":CHAN2:SCAL?", &devc->vdiv[1]) != SR_OK)
-               return SR_ERR;
-       sr_dbg("Current vertical gain CH1 %f CH2 %f", devc->vdiv[0], devc->vdiv[1]);
-
-       /* Vertical offset. */
-       if (get_cfg_float(sdi, ":CHAN1:OFFS?", &devc->vert_offset[0]) != SR_OK)
-               return SR_ERR;
-       if (get_cfg_float(sdi, ":CHAN2:OFFS?", &devc->vert_offset[1]) != SR_OK)
-               return SR_ERR;
-       sr_dbg("Current vertical offset CH1 %f CH2 %f", devc->vert_offset[0],
-                       devc->vert_offset[1]);
-
-       /* Coupling. */
-       if (get_cfg_string(sdi, ":CHAN1:COUP?", &devc->coupling[0]) != SR_OK)
-               return SR_ERR;
-       if (get_cfg_string(sdi, ":CHAN2:COUP?", &devc->coupling[1]) != SR_OK)
-               return SR_ERR;
-       sr_dbg("Current coupling CH1 %s CH2 %s", devc->coupling[0],
-                       devc->coupling[1]);
-
-       /* Trigger source. */
-       if (get_cfg_string(sdi, ":TRIG:EDGE:SOUR?", &devc->trigger_source) != SR_OK)
-               return SR_ERR;
-       sr_dbg("Current trigger source %s", devc->trigger_source);
-
-       /* Horizontal trigger position. */
-       if (get_cfg_float(sdi, ":TIM:OFFS?", &devc->horiz_triggerpos) != SR_OK)
-               return SR_ERR;
-       sr_dbg("Current horizontal trigger position %f", devc->horiz_triggerpos);
-
-       /* Trigger slope. */
-       if (get_cfg_string(sdi, ":TRIG:EDGE:SLOP?", &devc->trigger_slope) != SR_OK)
-               return SR_ERR;
-       sr_dbg("Current trigger slope %s", devc->trigger_slope);
-
-       return SR_OK;
-}
diff --git a/hardware/rigol-ds1xx2/protocol.h b/hardware/rigol-ds1xx2/protocol.h
deleted file mode 100644 (file)
index ff345fd..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * This file is part of the libsigrok project.
- *
- * Copyright (C) 2012 Martin Ling <martin-git@earth.li>
- * Copyright (C) 2013 Bert Vermeulen <bert@biot.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/>.
- */
-
-#ifndef LIBSIGROK_HARDWARE_RIGOL_DS1XX2_PROTOCOL_H
-#define LIBSIGROK_HARDWARE_RIGOL_DS1XX2_PROTOCOL_H
-
-#include <stdint.h>
-#include "libsigrok.h"
-#include "libsigrok-internal.h"
-
-/* Message logging helpers with subsystem-specific prefix string. */
-#define LOG_PREFIX "rigol-ds1xx2: "
-#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 ANALOG_WAVEFORM_SIZE 600
-#define DIGITAL_WAVEFORM_SIZE 1210
-
-/** Private, per-device-instance driver context. */
-struct dev_context {
-       /* Device features */
-       gboolean has_digital;
-
-       /* Probe groups */
-       struct sr_probe_group analog_groups[2];
-       struct sr_probe_group digital_group;
-
-       /* Acquisition settings */
-       GSList *enabled_analog_probes;
-       GSList *enabled_digital_probes;
-       uint64_t limit_frames;
-       void *cb_data;
-
-       /* Device settings */
-       gboolean analog_channels[2];
-       gboolean digital_channels[16];
-       float timebase;
-       float vdiv[2];
-       float vert_offset[2];
-       char *trigger_source;
-       float horiz_triggerpos;
-       char *trigger_slope;
-       char *coupling[2];
-
-       /* Operational state */
-       uint64_t num_frames;
-       uint64_t num_frame_bytes;
-       struct sr_probe *channel_frame;
-};
-
-SR_PRIV int rigol_ds1xx2_receive(int fd, int revents, void *cb_data);
-SR_PRIV int rigol_ds1xx2_send(const struct sr_dev_inst *sdi, const char *format, ...);
-SR_PRIV int rigol_ds1xx2_get_dev_cfg(const struct sr_dev_inst *sdi);
-
-#endif
index 5897b63eb823f6509bba1fe98a53731d671698d6..804838c8cc7369a7179ecc377cff9c3bf8399204 100644 (file)
@@ -148,8 +148,8 @@ extern SR_PRIV struct sr_dev_driver norma_dmm_driver_info;
 #ifdef HAVE_HW_OLS
 extern SR_PRIV struct sr_dev_driver ols_driver_info;
 #endif
-#ifdef HAVE_HW_RIGOL_DS1XX2
-extern SR_PRIV struct sr_dev_driver rigol_ds1xx2_driver_info;
+#ifdef HAVE_HW_RIGOL_DS
+extern SR_PRIV struct sr_dev_driver rigol_ds_driver_info;
 #endif
 #ifdef HAVE_HW_SALEAE_LOGIC16
 extern SR_PRIV struct sr_dev_driver saleae_logic16_driver_info;
@@ -274,8 +274,8 @@ static struct sr_dev_driver *drivers_list[] = {
 #ifdef HAVE_HW_OLS
        &ols_driver_info,
 #endif
-#ifdef HAVE_HW_RIGOL_DS1XX2
-       &rigol_ds1xx2_driver_info,
+#ifdef HAVE_HW_RIGOL_DS
+       &rigol_ds_driver_info,
 #endif
 #ifdef HAVE_HW_SALEAE_LOGIC16
        &saleae_logic16_driver_info,