The weekend is over, and so is my little endeavour to make my 22-812
work with sigrok.

It works. Well, everything except LOGIC functionality. This one's a
doozie, as the DMM outputs LO if the voltage is < 1V, HI if the voltage
is > 2V, and the actual voltage if the voltage is between 1 and 2 volts.

The rest of the stuff works, and that's what really matters; unless you
guys have specific objections on how the coding was done.

Alex
>From 0c0ffa9a2305bb180b8971c5fe1d285c2b317685 Mon Sep 17 00:00:00 2001
From: Alexandru Gagniuc <[email protected]>
Date: Mon, 15 Oct 2012 01:11:39 -0500
Subject: [PATCH 1/4] .qitignore: Ignore KDE backup files

*.kate-swp files can become annoying, so ignore them.

Signed-off-by: Alexandru Gagniuc <[email protected]>
---
 .gitignore | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.gitignore b/.gitignore
index e2414ec..99bb814 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,3 +32,5 @@ Makefile.in
 .libs/
 *.pc
 
+# KDE backup files
+*.kate-swp
-- 
1.7.11.4

>From 4084e3c28bd7294632d88588b90f42dc4a360c91 Mon Sep 17 00:00:00 2001
From: Alexandru Gagniuc <[email protected]>
Date: Mon, 15 Oct 2012 01:12:53 -0500
Subject: [PATCH 2/4] serial: (Trivial) add support for 4800 baud

Signed-off-by: Alexandru Gagniuc <[email protected]>
---
 libsigrok/hardware/common/serial.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/libsigrok/hardware/common/serial.c b/libsigrok/hardware/common/serial.c
index ad88958..990c5b2 100644
--- a/libsigrok/hardware/common/serial.c
+++ b/libsigrok/hardware/common/serial.c
@@ -218,6 +218,9 @@ SR_PRIV int serial_set_params(int fd, int baudrate, int bits, int parity,
 	case 9600:
 		dcb.BaudRate = CBR_9600;
 		break;
+	case 9600:
+		dcb.BaudRate = CBR_4800;
+		break;
 	default:
 		/* TODO: Error handling. */
 		break;
@@ -238,6 +241,9 @@ SR_PRIV int serial_set_params(int fd, int baudrate, int bits, int parity,
 		return SR_ERR;
 
 	switch (baudrate) {
+	case 4800:
+		baud = B4800;
+		break;
 	case 9600:
 		baud = B9600;
 		break;
-- 
1.7.11.4

>From 88e89e1fd8e7c19dad8bd33eab91c41e03ee4f78 Mon Sep 17 00:00:00 2001
From: Alexandru Gagniuc <[email protected]>
Date: Mon, 15 Oct 2012 01:14:04 -0500
Subject: [PATCH 3/4] libsigrok.h: Add measured quantity and units used by
 Radioshack 22-812

The Radioshack 22-812 can measure parameters such as transistor gain,
dbm, etc. Add those to libsigrok.h.

The SR_UNIT_UNITLESS is for quantities that do not have units. Any
ratio or gain are just factors, whic do not have units. Specifically,
a transistor's gain, or hFE, is a unitless quantity.

Signed-off-by: Alexandru Gagniuc <[email protected]>
---
 libsigrok/libsigrok.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/libsigrok/libsigrok.h b/libsigrok/libsigrok.h
index 595f191..da770f4 100644
--- a/libsigrok/libsigrok.h
+++ b/libsigrok/libsigrok.h
@@ -148,6 +148,10 @@ enum {
 	SR_MQ_CONTINUITY,
 	SR_MQ_PULSE_WIDTH,
 	SR_MQ_CONDUCTANCE,
+	/** For a measurement of electrical power, usually in W, or dBm */
+	SR_MQ_POWER,
+	/** Usually for measuring a transistor's gain, or h_FE*/
+	SR_MQ_GAIN,
 };
 
 /* sr_datafeed_analog.unit values */
@@ -163,7 +167,15 @@ enum {
 	SR_UNIT_PERCENTAGE,
 	SR_UNIT_BOOLEAN,
 	SR_UNIT_SECOND,
+	/** Unit of conductance, the inverse of resistance */
 	SR_UNIT_SIEMENS,
+	/** An absolute measurement of power, in decibels, referenced to
+	 * 1 milliwatt */
+	SR_UNIT_DECIBEL_MW,
+	/** Measurements that intrinsically, do not have units attached, such
+	 * as ratios, gains, etc
+	 * Specifically, a transistor's gain (hFE) is a unitless quantity*/
+	SR_UNIT_UNITLESS,
 };
 
 /** sr_datafeed_analog.flags values */
-- 
1.7.11.4

>From f37451eac1fe6d872dd4243a2c81f763267f04b9 Mon Sep 17 00:00:00 2001
From: Alexandru Gagniuc <[email protected]>
Date: Mon, 15 Oct 2012 01:17:32 -0500
Subject: [PATCH 4/4] radioshack-dmm: Add support for Radioshack 22-812 DMM

Signed-off-by: Alexandru Gagniuc <[email protected]>
---
 libsigrok/Makefile.am                              |   1 +
 libsigrok/configure.ac                             |  12 +
 libsigrok/hardware/Makefile.am                     |   8 +-
 libsigrok/hardware/radioshack-dmm/Makefile.am      |  34 ++
 libsigrok/hardware/radioshack-dmm/api.c            | 451 +++++++++++++++++++++
 libsigrok/hardware/radioshack-dmm/radioshack-dmm.h | 159 ++++++++
 libsigrok/hardware/radioshack-dmm/radioshack.c     | 406 +++++++++++++++++++
 libsigrok/hwdriver.c                               |   6 +
 8 files changed, 1076 insertions(+), 1 deletion(-)
 create mode 100644 libsigrok/hardware/radioshack-dmm/Makefile.am
 create mode 100644 libsigrok/hardware/radioshack-dmm/api.c
 create mode 100644 libsigrok/hardware/radioshack-dmm/radioshack-dmm.c
 create mode 100644 libsigrok/hardware/radioshack-dmm/radioshack-dmm.h
 create mode 100644 libsigrok/hardware/radioshack-dmm/radioshack.c

diff --git a/libsigrok/Makefile.am b/libsigrok/Makefile.am
index e2ccabb..beeb0c3 100644
--- a/libsigrok/Makefile.am
+++ b/libsigrok/Makefile.am
@@ -2,6 +2,7 @@
 ## This file is part of the sigrok project.
 ##
 ## Copyright (C) 2010-2012 Bert Vermeulen <[email protected]>
+## Copyright (C) 2012 Alexandru Gagniuc <[email protected]>
 ##
 ## This program is free software: you can redistribute it and/or modify
 ## it under the terms of the GNU General Public License as published by
diff --git a/libsigrok/configure.ac b/libsigrok/configure.ac
index 7b47ec8..bc51a1e 100644
--- a/libsigrok/configure.ac
+++ b/libsigrok/configure.ac
@@ -2,6 +2,7 @@
 ## This file is part of the sigrok project.
 ##
 ## Copyright (C) 2010-2012 Bert Vermeulen <[email protected]>
+## Copyright (C) 2012 Alexandru Gagniuc <[email protected]>
 ##
 ## This program is free software: you can redistribute it and/or modify
 ## it under the terms of the GNU General Public License as published by
@@ -122,6 +123,15 @@ if test "x$HW_FLUKE_DMM" = "xyes"; then
 	AC_DEFINE(HAVE_HW_FLUKE_DMM, 1, [Fluke DMM support])
 fi
 
+AC_ARG_ENABLE(radioshack-dmm, AC_HELP_STRING([--enable-radioshack-dmm],
+	      [Enable Fluke DMM support. [default=yes]]),
+	      [HW_RADIOSHACK_DMM="$enableval"],
+	      [HW_RADIOSHACK_DMM=yes])
+AM_CONDITIONAL(HW_RADIOSHACK_DMM, test x$HW_RADIOSHACK_DMM = xyes)
+if test "x$HW_RADIOSHACK_DMM" = "xyes"; then
+	AC_DEFINE(HAVE_HW_RADIOSHACK_DMM, 1, [Radioshack DMM support])
+	fi
+
 AC_ARG_ENABLE(fx2lafw, AC_HELP_STRING([--enable-fx2lafw],
 	      [enable fx2lafw support (for FX2 LAs). [default=yes]]),
 	      [LA_FX2LAFW="$enableval"],
@@ -313,6 +323,7 @@ AC_CONFIG_FILES([Makefile
 		 hardware/common/Makefile
 		 hardware/demo/Makefile
 		 hardware/fluke-dmm/Makefile
+		 hardware/radioshack-dmm/Makefile
 		 hardware/fx2lafw/Makefile
 		 hardware/genericdmm/Makefile
 		 hardware/link-mso19/Makefile
@@ -357,6 +368,7 @@ echo "  - ASIX SIGMA/SIGMA2............... $LA_ASIX_SIGMA"
 echo "  - ChronoVu LA8.................... $LA_CHRONOVU_LA8"
 echo "  - Demo driver..................... $LA_DEMO"
 echo "  - Fluke DMM....................... $HW_FLUKE_DMM"
+echo "  - Radioshack DMM.................. $HW_RADIOSHACK_DMM"
 echo "  - fx2lafw (for FX2 LAs)........... $LA_FX2LAFW"
 echo "  - Generic DMM..................... $HW_GENERICDMM"
 echo "  - Link MSO-19..................... $LA_LINK_MSO19"
diff --git a/libsigrok/hardware/Makefile.am b/libsigrok/hardware/Makefile.am
index db5691d..029a222 100644
--- a/libsigrok/hardware/Makefile.am
+++ b/libsigrok/hardware/Makefile.am
@@ -2,6 +2,7 @@
 ## This file is part of the sigrok project.
 ##
 ## Copyright (C) 2011 Uwe Hermann <[email protected]>
+## Copyright (C) 2012 Alexandru Gagniuc <[email protected]>
 ##
 ## This program is free software: you can redistribute it and/or modify
 ## it under the terms of the GNU General Public License as published by
@@ -30,7 +31,8 @@ SUBDIRS = \
 	link-mso19 \
 	openbench-logic-sniffer \
 	zeroplus-logic-cube \
-	hantek-dso
+	hantek-dso \
+	radioshack-dmm
 
 noinst_LTLIBRARIES = libsigrokhardware.la
 
@@ -63,6 +65,10 @@ if HW_FLUKE_DMM
 libsigrokhardware_la_LIBADD += fluke-dmm/libsigrokhwflukedmm.la
 endif
 
+if HW_RADIOSHACK_DMM
+libsigrokhardware_la_LIBADD += radioshack-dmm/libsigrokhwradioshackdmm.la
+endif
+
 if LA_FX2LAFW
 libsigrokhardware_la_LIBADD += fx2lafw/libsigrokhwfx2lafw.la
 endif
diff --git a/libsigrok/hardware/radioshack-dmm/Makefile.am b/libsigrok/hardware/radioshack-dmm/Makefile.am
new file mode 100644
index 0000000..99091aa
--- /dev/null
+++ b/libsigrok/hardware/radioshack-dmm/Makefile.am
@@ -0,0 +1,34 @@
+##
+## This file is part of the sigrok project.
+##
+## Copyright (C) 2012 Bert Vermeulen <[email protected]>
+## Copyright (C) 2012 Alexandru Gagniuc <[email protected]>
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+##
+
+if HW_RADIOSHACK_DMM
+
+# Local lib, this is NOT meant to be installed!
+noinst_LTLIBRARIES = libsigrokhwradioshackdmm.la
+
+libsigrokhwradioshackdmm_la_SOURCES = \
+	api.c \
+	radioshack.c \
+	radioshack-dmm.h
+
+libsigrokhwradioshackdmm_la_CFLAGS = \
+	-I$(top_srcdir)
+
+endif
diff --git a/libsigrok/hardware/radioshack-dmm/api.c b/libsigrok/hardware/radioshack-dmm/api.c
new file mode 100644
index 0000000..ecb4ad5
--- /dev/null
+++ b/libsigrok/hardware/radioshack-dmm/api.c
@@ -0,0 +1,451 @@
+/*
+ * This file is part of the sigrok project.
+ *
+ * Copyright (C) 2012 Bert Vermeulen <[email protected]>
+ * Copyright (C) 2012 Alexandru Gagniuc <[email protected]>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include "libsigrok/libsigrok.h"
+#include "libsigrok-internal.h"
+#include "config.h"
+#include "radioshack-dmm.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+static const int hwopts[] = {
+	SR_HWOPT_CONN,
+	SR_HWOPT_SERIALCOMM,
+	0,
+};
+
+static const int hwcaps[] = {
+	SR_HWCAP_MULTIMETER,
+	SR_HWCAP_LIMIT_SAMPLES,
+	SR_HWCAP_CONTINUOUS,
+	0,
+};
+
+static const char *probe_names[] = {
+	"Probe",
+	NULL,
+};
+
+SR_PRIV struct sr_dev_driver radioshackdmm_driver_info;
+static struct sr_dev_driver *di = &radioshackdmm_driver_info;
+
+static const struct radioshackdmm_profile supported_radioshackdmm[] = {
+	{ RADIOSHACK_22_812, "22-812", 100 },
+};
+
+
+/* Properly close and free all devices. */
+static int clear_instances(void)
+{
+	struct sr_dev_inst *sdi;
+	struct drv_context *drvc;
+	struct dev_context *devc;
+	GSList *l;
+
+	if (!(drvc = di->priv))
+		return SR_OK;
+
+	drvc = di->priv;
+	for (l = drvc->instances; l; l = l->next) {
+		if (!(sdi = l->data))
+			continue;
+		if (!(devc = sdi->priv))
+			continue;
+		sr_serial_dev_inst_free(devc->serial);
+		sr_dev_inst_free(sdi);
+	}
+	g_slist_free(drvc->instances);
+	drvc->instances = NULL;
+
+	return SR_OK;
+}
+
+static int hw_init(void)
+{
+	struct drv_context *drvc;
+
+	if (!(drvc = g_try_malloc0(sizeof(struct drv_context)))) {
+		sr_err("radioshack-dmm: driver context malloc failed.");
+		return SR_ERR;
+	}
+
+	di->priv = drvc;
+
+	return SR_OK;
+}
+
+static int serial_readline(int fd, char **buf, size_t *buflen,
+			   uint64_t timeout_ms)
+{
+	uint64_t start;
+	int maxlen, len;
+
+	timeout_ms *= 1000;
+	start = g_get_monotonic_time();
+
+	maxlen = *buflen;
+	*buflen = len = 0;
+	while(1) {
+		len = maxlen - *buflen - 1;
+		if (len < 1)
+			break;
+		len = serial_read(fd, *buf + *buflen, 1);
+		if (len > 0) {
+			*buflen += len;
+			*(*buf + *buflen) = '\0';
+			if (*buflen > 0 && *(*buf + *buflen - 1) == '\r') {
+				/* Strip LF and terminate. */
+				*(*buf + --*buflen) = '\0';
+				break;
+			}
+		}
+		if (g_get_monotonic_time() - start > timeout_ms)
+			/* Timeout */
+			break;
+		g_usleep(2000);
+	}
+
+	return SR_OK;
+}
+
+static GSList *rs_22_812_scan(const char *conn, const char *serialcomm)
+{
+	struct sr_dev_inst *sdi;
+	struct drv_context *drvc;
+	struct dev_context *devc;
+	struct sr_probe *probe;
+	GSList *devices;
+	int fd, retry;
+	size_t len;
+	char buf[128], *b;
+
+	if ((fd = serial_open(conn, O_RDWR|O_NONBLOCK)) == -1) {
+		sr_err("radioshack-dmm: unable to open %s: %s",
+		       conn, strerror(errno));
+		return NULL;
+	}
+	if (serial_set_paramstr(fd, serialcomm) != SR_OK) {
+		sr_err("radioshack-dmm: unable to set serial parameters");
+		return NULL;
+	}
+
+	drvc = di->priv;
+	b = buf;
+	retry = 0;
+	devices = NULL;
+	/* There's no way to get an ID from the multimeter. It just sends data
+	 * periodically, so the best we can do is check if the packets match the
+	 * expected format. */
+	while (!devices && retry < 3)
+	{
+		size_t i;
+		size_t good_packets = 0;
+		retry++;
+		serial_flush(fd);
+
+		/* Let's get a bit of data and see if we can find a packet */
+		len = sizeof(buf);
+		serial_readline(fd, &b, &len, 250);
+		if( (len == 0) || (len < RS_22_812_PACKET_SIZE) ) {
+			/* Not enough data received, is the DMM connected ? */
+			continue;
+		}
+
+		/* Let's treat our buffer like a stream, and find any
+		 * valid packets */
+		for( i = 0; i < len - RS_22_812_PACKET_SIZE + 1;
+		    /* don't increment i here */ )
+		{
+			const rs_22_812_packet *packet = (void *)(&buf[i]);
+			if( !rs_22_812_is_packet_valid(packet) ){
+				i++;
+				continue;
+			}
+			good_packets++;
+			i += RS_22_812_PACKET_SIZE;
+		}
+
+		/* If we dropped more than two packets worth of data, something
+		 * is wrong */
+		size_t dropped = len - (good_packets * RS_22_812_PACKET_SIZE);
+		if(dropped > 2 * RS_22_812_PACKET_SIZE)
+			continue;
+
+		/* Let's see if we have anything good */
+		if (good_packets == 0)
+			continue;
+
+		if (!(sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, "Radioshack",
+					    "22-812", "")))
+			return NULL;
+		if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) {
+			sr_dbg("radioshack-dmm: failed to malloc devc");
+			return NULL;
+		}
+
+		/* devc->profile = RADIOSHACK_22_812; */
+		devc->serial = sr_serial_dev_inst_new(conn, -1);
+		devc->serialcomm = g_strdup(serialcomm);
+
+		sdi->priv = devc;
+		sdi->driver = di;
+		if (!(probe = sr_probe_new(0, SR_PROBE_ANALOG, TRUE, "P1")))
+			return NULL;
+		sdi->probes = g_slist_append(sdi->probes, probe);
+		drvc->instances = g_slist_append(drvc->instances, sdi);
+		devices = g_slist_append(devices, sdi);
+		break;
+
+	}
+	serial_close(fd);
+
+	return devices;
+}
+
+static GSList *hw_scan(GSList *options)
+{
+	struct sr_hwopt *opt;
+	GSList *l, *devices;
+	const char *conn, *serialcomm;
+
+	conn = serialcomm = NULL;
+	for (l = options; l; l = l->next) {
+		opt = l->data;
+		switch (opt->hwopt) {
+		case SR_HWOPT_CONN:
+			conn = opt->value;
+			break;
+		case SR_HWOPT_SERIALCOMM:
+			serialcomm = opt->value;
+			break;
+		}
+	}
+	if (!conn)
+		return NULL;
+
+	if (serialcomm) {
+		/* Use the provided comm specs. */
+		devices = rs_22_812_scan(conn, serialcomm);
+	} else {
+		/* Then try the default 4800 8n1 */
+		devices = rs_22_812_scan(conn, "4800/8n1");
+	}
+
+	return devices;
+}
+
+static GSList *hw_dev_list(void)
+{
+	struct drv_context *drvc;
+
+	drvc = di->priv;
+
+	return drvc->instances;
+}
+
+static int hw_dev_open(struct sr_dev_inst *sdi)
+{
+	struct dev_context *devc;
+
+	if (!(devc = sdi->priv)) {
+		sr_err("radioshack-dmm: sdi->priv was NULL.");
+		return SR_ERR_BUG;
+	}
+
+	devc->serial->fd = serial_open(devc->serial->port, O_RDWR | O_NONBLOCK);
+	if (devc->serial->fd == -1) {
+		sr_err("radioshack-dmm: Couldn't open serial port '%s'.",
+		       devc->serial->port);
+		return SR_ERR;
+	}
+	if (serial_set_paramstr(devc->serial->fd, devc->serialcomm) != SR_OK) {
+		sr_err("radioshack-dmm: unable to set serial parameters");
+		return SR_ERR;
+	}
+	sdi->status = SR_ST_ACTIVE;
+
+	return SR_OK;
+}
+
+static int hw_dev_close(struct sr_dev_inst *sdi)
+{
+	struct dev_context *devc;
+
+	if (!(devc = sdi->priv)) {
+		sr_err("radioshack-dmm: sdi->priv was NULL.");
+		return SR_ERR_BUG;
+	}
+
+	if (devc->serial && devc->serial->fd != -1) {
+		serial_close(devc->serial->fd);
+		devc->serial->fd = -1;
+		sdi->status = SR_ST_INACTIVE;
+	}
+
+	return SR_OK;
+}
+
+static int hw_cleanup(void)
+{
+	clear_instances();
+
+	return SR_OK;
+}
+
+static int hw_info_get(int info_id, const void **data,
+       const struct sr_dev_inst *sdi)
+{
+	(void)sdi; /* Does nothing. prevents "unused parameter" warning */
+
+	switch (info_id) {
+	case SR_DI_HWOPTS:
+		*data = hwopts;
+		break;
+	case SR_DI_HWCAPS:
+		*data = hwcaps;
+		break;
+	case SR_DI_NUM_PROBES:
+		*data = GINT_TO_POINTER(1);
+		break;
+	case SR_DI_PROBE_NAMES:
+		*data = probe_names;
+		break;
+	default:
+		return SR_ERR_ARG;
+	}
+
+	return SR_OK;
+}
+
+static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap,
+		const void *value)
+{
+	struct dev_context *devc;
+
+	if (sdi->status != SR_ST_ACTIVE)
+		return SR_ERR;
+
+	if (!(devc = sdi->priv)) {
+		sr_err("radioshack-dmm: sdi->priv was NULL.");
+		return SR_ERR_BUG;
+	}
+
+	switch (hwcap) {
+	case SR_HWCAP_LIMIT_SAMPLES:
+		devc->limit_samples = *(const uint64_t *)value;
+		sr_dbg("radioshack-dmm: Setting sample limit to %" PRIu64 ".",
+		       devc->limit_samples);
+		break;
+	default:
+		sr_err("radioshack-dmm: Unknown capability: %d.", hwcap);
+		return SR_ERR;
+		break;
+	}
+
+	return SR_OK;
+}
+
+static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
+		void *cb_data)
+{
+	struct sr_datafeed_packet packet;
+	struct sr_datafeed_header header;
+	struct sr_datafeed_meta_analog meta;
+	struct dev_context *devc;
+
+	if (!(devc = sdi->priv)) {
+		sr_err("radioshack-dmm: sdi->priv was NULL.");
+		return SR_ERR_BUG;
+	}
+
+	sr_dbg("radioshack-dmm: Starting acquisition.");
+
+	devc->cb_data = cb_data;
+
+	/* Send header packet to the session bus. */
+	sr_dbg("radioshack-dmm: Sending SR_DF_HEADER.");
+	packet.type = SR_DF_HEADER;
+	packet.payload = (uint8_t *)&header;
+	header.feed_version = 1;
+	gettimeofday(&header.starttime, NULL);
+	sr_session_send(devc->cb_data, &packet);
+
+	/* Send metadata about the SR_DF_ANALOG packets to come. */
+	sr_dbg("radioshack-dmm: Sending SR_DF_META_ANALOG.");
+	packet.type = SR_DF_META_ANALOG;
+	packet.payload = &meta;
+	meta.num_probes = 1;
+	sr_session_send(devc->cb_data, &packet);
+
+	/* Poll every 100ms, or whenever some data comes in. */
+	sr_source_add(devc->serial->fd, G_IO_IN, 50,
+		      radioshack_receive_data, (void *)sdi );
+
+	return SR_OK;
+}
+
+static int hw_dev_acquisition_stop(const struct sr_dev_inst *sdi,
+		void *cb_data)
+{
+	struct sr_datafeed_packet packet;
+	struct dev_context *devc;
+
+	if (sdi->status != SR_ST_ACTIVE)
+		return SR_ERR;
+
+	if (!(devc = sdi->priv)) {
+		sr_err("radioshack-dmm: sdi->priv was NULL.");
+		return SR_ERR_BUG;
+	}
+
+	sr_dbg("radioshack-dmm: Stopping acquisition.");
+
+	sr_source_remove(devc->serial->fd);
+	hw_dev_close((struct sr_dev_inst *)sdi);
+
+	/* Send end packet to the session bus. */
+	sr_dbg("radioshack-dmm: Sending SR_DF_END.");
+	packet.type = SR_DF_END;
+	sr_session_send(cb_data, &packet);
+
+	return SR_OK;
+}
+
+SR_PRIV struct sr_dev_driver radioshackdmm_driver_info = {
+	.name = "radioshack-dmm",
+	.longname = "Radioshack 22-812/22-039 DMMs",
+	.api_version = 1,
+	.init = hw_init,
+	.cleanup = hw_cleanup,
+	.scan = hw_scan,
+	.dev_list = hw_dev_list,
+	.dev_clear = clear_instances,
+	.dev_open = hw_dev_open,
+	.dev_close = hw_dev_close,
+	.info_get = hw_info_get,
+	.dev_config_set = hw_dev_config_set,
+	.dev_acquisition_start = hw_dev_acquisition_start,
+	.dev_acquisition_stop = hw_dev_acquisition_stop,
+	.priv = NULL,
+};
diff --git a/libsigrok/hardware/radioshack-dmm/radioshack-dmm.c b/libsigrok/hardware/radioshack-dmm/radioshack-dmm.c
new file mode 100644
index 0000000..e69de29
diff --git a/libsigrok/hardware/radioshack-dmm/radioshack-dmm.h b/libsigrok/hardware/radioshack-dmm/radioshack-dmm.h
new file mode 100644
index 0000000..d206d0f
--- /dev/null
+++ b/libsigrok/hardware/radioshack-dmm/radioshack-dmm.h
@@ -0,0 +1,159 @@
+/*
+ * This file is part of the sigrok project.
+ *
+ * Copyright (C) 2012 Bert Vermeulen <[email protected]>
+ * Copyright (C) 2012 Alexandru Gagniuc <[email protected]>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef LIBSIGROK_RADIOSHACK_DMM_H
+#define LIBSIGROK_RADIOSHACK_DMM_H
+
+#define RS_DMM_BUFSIZE  256
+
+/* Byte 1 of the packet, and the modes it represents */
+#define RS_22_812_IND1_HZ	(0x80)
+#define RS_22_812_IND1_OHM	(0x40)
+#define RS_22_812_IND1_KILO	(0x20)
+#define RS_22_812_IND1_MEGA	(0x10)
+#define RS_22_812_IND1_FARAD	(0x08)
+#define RS_22_812_IND1_AMP	(0x04)
+#define RS_22_812_IND1_VOLT	(0x02)
+#define RS_22_812_IND1_MILI	(0x01)
+/* Byte 2 of the packet, and the modes it represents */
+#define RS_22_812_IND2_MICRO	(0x80)
+#define RS_22_812_IND2_NANO	(0x40)
+#define RS_22_812_IND2_DBM	(0x20)
+#define RS_22_812_IND2_SEC	(0x10)
+#define RS_22_812_IND2_DUTY	(0x08)
+#define RS_22_812_IND2_HFE	(0x04)
+#define RS_22_812_IND2_REL	(0x02)
+#define RS_22_812_IND2_MIN	(0x01)
+/* Byte 7 of the packet, and the modes it represents */
+#define RS_22_812_INFO_BEEP	(0x80)
+#define RS_22_812_INFO_DIODE	(0x30)
+#define RS_22_812_INFO_BAT	(0x20)
+#define RS_22_812_INFO_HOLD	(0x10)
+#define RS_22_812_INFO_NEG	(0x08)
+#define RS_22_812_INFO_AC	(0x04)
+#define RS_22_812_INFO_RS232	(0x02)
+#define RS_22_812_INFO_AUTO	(0x01)
+/* Instead of a decimal point, digit 4 carries the MAX flag */
+#define RS_22_812_DIG4_MAX	(0x08)
+/* mask to remove the decimal point fr0m a digit */
+#define RS_22_812_DP_MASK	(0x08)
+
+/* What the LCD values represent */
+#define RS_22_812_LCD_0 0xd7
+#define RS_22_812_LCD_1 0x50
+#define RS_22_812_LCD_2 0xb5
+#define RS_22_812_LCD_3 0xf1
+#define RS_22_812_LCD_4 0x72
+#define RS_22_812_LCD_5 0xe3
+#define RS_22_812_LCD_6 0xe7
+#define RS_22_812_LCD_7 0x51
+#define RS_22_812_LCD_8 0xf7
+#define RS_22_812_LCD_9 0xf3
+
+#define RS_22_812_LCD_C 0x87
+#define RS_22_812_LCD_E
+#define RS_22_812_LCD_F
+#define RS_22_812_LCD_h 0x66
+#define RS_22_812_LCD_H
+#define RS_22_812_LCD_I
+#define RS_22_812_LCD_n
+#define RS_22_812_LCD_P 0x37
+#define RS_22_812_LCD_r
+
+typedef struct {
+	uint8_t mode;
+	uint8_t indicatrix1;
+	uint8_t indicatrix2;
+	uint8_t digit4;
+	uint8_t digit3;
+	uint8_t digit2;
+	uint8_t digit1;
+	uint8_t info;
+	uint8_t checksum;
+} rs_22_812_packet;
+
+#define RS_22_812_PACKET_SIZE (sizeof(rs_22_812_packet))
+
+typedef enum {
+	RS_22_812_MODE_DC_V     = 0,
+	RS_22_812_MODE_AC_V     = 1,
+	RS_22_812_MODE_DC_UA    = 2,
+	RS_22_812_MODE_DC_MA    = 3,
+	RS_22_812_MODE_DC_A     = 4,
+	RS_22_812_MODE_AC_UA    = 5,
+	RS_22_812_MODE_AC_MA    = 6,
+	RS_22_812_MODE_AC_A     = 7,
+	RS_22_812_MODE_OHM      = 8,
+	RS_22_812_MODE_FARAD    = 9,
+	RS_22_812_MODE_HZ       = 10,
+	RS_22_812_MODE_VOLT_HZ  = 11,
+	RS_22_812_MODE_AMP_HZ   = 12,
+	RS_22_812_MODE_DUTY     = 13,
+	RS_22_812_MODE_VOLT_DUTY= 14,
+	RS_22_812_MODE_AMP_DUTY = 15,
+	RS_22_812_MODE_WIDTH    = 16,
+	RS_22_812_MODE_VOLT_WIDTH = 17,
+	RS_22_812_MODE_AMP_WIDTH  = 18,
+	RS_22_812_MODE_DIODE    = 19,
+	RS_22_812_MODE_CONT     = 20,
+	RS_22_812_MODE_HFE      = 21,
+	RS_22_812_MODE_LOGIC    = 22,
+	RS_22_812_MODE_DBM      = 23,
+	//RS_22_812_MODE_   EF = 24,
+	RS_22_812_MODE_TEMP     = 25,
+	RS_22_812_MODE_INVALID  = 26,
+} rs_22_812_mode;
+
+SR_PRIV gboolean rs_22_812_is_packet_valid(const rs_22_812_packet *data );
+
+/* Supported models */
+typedef enum {
+	RADIOSHACK_22_812 = 1,
+} radioshack_model;
+
+/* Supported device profiles */
+struct radioshackdmm_profile {
+	radioshack_model model;
+	const char *modelname;
+	/* How often to poll, in ms. */
+	int poll_period;
+};
+
+/* Private, per-device-instance driver context. */
+typedef struct dev_context {
+	/* const struct radioshackdmm_profile *profile; */
+	uint64_t limit_samples;
+	struct sr_serial_dev_inst *serial;
+	char *serialcomm;
+
+	/* Opaque pointer passed in by the frontend. */
+	void *cb_data;
+
+	/* Runtime. */
+	uint64_t num_samples;
+	uint8_t buf[RS_DMM_BUFSIZE];
+	size_t bufoffset;
+	size_t buflen;
+} rs_dev_ctx;
+
+
+SR_PRIV int radioshack_receive_data(int fd, int revents, void *cb_data);
+
+#endif /* LIBSIGROK_RADIOSHACK_DMM_H */
diff --git a/libsigrok/hardware/radioshack-dmm/radioshack.c b/libsigrok/hardware/radioshack-dmm/radioshack.c
new file mode 100644
index 0000000..078160e
--- /dev/null
+++ b/libsigrok/hardware/radioshack-dmm/radioshack.c
@@ -0,0 +1,406 @@
+/*
+ * This file is part of the sigrok project.
+ *
+ * Copyright (C) 2012 Bert Vermeulen <[email protected]>
+ * Copyright (C) 2012 Alexandru Gagniuc <[email protected]>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include "libsigrok.h"
+#include "libsigrok-internal.h"
+#include "config.h"
+#include "radioshack-dmm.h"
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <errno.h>
+
+
+static gboolean rs_22_812_is_checksum_valid(const rs_22_812_packet *data)
+{
+	uint8_t *raw = (void *) data;
+	uint8_t sum = 0;
+	size_t i;
+	for(i = 0; i < RS_22_812_PACKET_SIZE - 1; i++)
+		sum += raw[i];
+	/* This is just a funky constant added to the checksum */
+	sum += 57;
+	sum -= data->checksum;
+	return(sum == 0);
+}
+
+static gboolean rs_22_812_is_mode_valid(rs_22_812_mode mode)
+{
+	return(mode < RS_22_812_MODE_INVALID);
+}
+
+static gboolean rs_22_812_is_selection_good(const rs_22_812_packet *data)
+{
+	int n_postfix = 0;
+	int n_type = 0;
+	/* Does the packet have more than one multiplier ? */
+	if(data->indicatrix1 & RS_22_812_IND1_KILO)
+		n_postfix++;
+	if(data->indicatrix1 & RS_22_812_IND1_MEGA)
+		n_postfix++;
+	if(data->indicatrix1 & RS_22_812_IND1_MILI)
+		n_postfix++;
+	if(data->indicatrix2 & RS_22_812_IND2_MICRO)
+		n_postfix++;
+	if(data->indicatrix2 & RS_22_812_IND2_NANO)
+		n_postfix++;
+	if(n_postfix > 1)
+		return FALSE;
+
+	/* Does the packet "measure" more than one type of value ?*/
+	if(data->indicatrix1 & RS_22_812_IND1_HZ)
+		n_type++;
+	if(data->indicatrix1 & RS_22_812_IND1_OHM)
+		n_type++;
+	if(data->indicatrix1 & RS_22_812_IND1_FARAD)
+		n_type++;
+	if(data->indicatrix1 & RS_22_812_IND1_AMP)
+		n_type++;
+	if(data->indicatrix1 & RS_22_812_IND1_VOLT)
+		n_type++;
+	if(data->indicatrix2 & RS_22_812_IND2_DBM)
+		n_type++;
+	if(data->indicatrix2 & RS_22_812_IND2_SEC)
+		n_type++;
+	if(data->indicatrix2 & RS_22_812_IND2_DUTY)
+		n_type++;
+	if(data->indicatrix2 & RS_22_812_IND2_HFE)
+		n_type++;
+	if(n_type > 1)
+		return FALSE;
+
+	/* OK, no duplicates */
+	return TRUE;
+}
+
+/* Since the RS 22-812 does not identify itslef in any way shape, or form,
+ * we really don't know for sure who is sending the data. We must use every
+ * possible check to filter out bad packets, especially since detection of the
+ * 22-812 depends on how well we can filter the packets */
+SR_PRIV gboolean rs_22_812_is_packet_valid(const rs_22_812_packet *packet)
+{
+	/* Unfortunately, the packet doesn't have a signature, so we must
+	 * compute its checksum first */
+	if(!rs_22_812_is_checksum_valid(packet))
+		return FALSE;
+
+	if(!rs_22_812_is_mode_valid(packet->mode))
+		return FALSE;
+
+	if(!rs_22_812_is_selection_good(packet)) {
+		return FALSE;
+	}
+	/* Made it here, huh? Then this looks to be a valid packet */
+	return TRUE;
+}
+
+static uint8_t rs_22_812_to_digit(uint8_t raw_digit)
+{
+	/* Take out the decimal point, so we can use a simple switch() */
+	raw_digit &= ~RS_22_812_DP_MASK;
+	switch(raw_digit)
+	{
+	case 0x00:
+	case RS_22_812_LCD_0:
+		return 0;
+	case RS_22_812_LCD_1:
+		return 1;
+	case RS_22_812_LCD_2:
+		return 2;
+	case RS_22_812_LCD_3:
+		return 3;
+	case RS_22_812_LCD_4:
+		return 4;
+	case RS_22_812_LCD_5:
+		return 5;
+	case RS_22_812_LCD_6:
+		return 6;
+	case RS_22_812_LCD_7:
+		return 7;
+	case RS_22_812_LCD_8:
+		return 8;
+	case RS_22_812_LCD_9:
+		return 9;
+	default:
+		return 0xff;
+	}
+}
+
+typedef enum {
+	READ_ALL,
+	READ_TEMP,
+} value_type;
+
+static double lcdraw_to_double(rs_22_812_packet *rs_packet, value_type type)
+{
+	/* *********************************************************************
+	 * Get a raw floating point value from the data
+	 **********************************************************************/
+	double rawval;
+	double multiplier = 1;
+	uint8_t digit;
+	gboolean dp_reached = FALSE;
+	int i, end;
+	switch(type) {
+	case READ_TEMP:
+		/* Do not parse the last digit */
+		end = 1;
+		break;
+	case READ_ALL:
+	default:
+		/* Parse all digits */
+		end = 0;
+	}
+	/* We have 4 digits, and we start from the most significant */
+	for(i = 3; i >= end; i--)
+	{
+		uint8_t raw_digit = *(&(rs_packet->digit4) + i);
+		digit = rs_22_812_to_digit(raw_digit);
+		if(digit == 0xff) {
+			rawval = NAN;
+			break;
+		}
+		/* Digit 1 does not have a decimal point. Instead, the decimal
+		 * point is used to indicate MAX, so we must avoid testing it */
+		if( (i < 3) && (raw_digit & RS_22_812_DP_MASK) )
+			dp_reached = TRUE;
+		if(dp_reached) multiplier /= 10;
+		rawval = rawval * 10 + digit;
+	}
+	rawval *= multiplier;
+	if(rs_packet->info & RS_22_812_INFO_NEG)
+		rawval *= -1;
+
+	/* See if we need to multiply our raw value by anything */
+	if(rs_packet->indicatrix1 & RS_22_812_IND2_NANO) {
+		rawval *= 1E-9;
+	} else if(rs_packet->indicatrix2 & RS_22_812_IND2_MICRO) {
+		rawval *= 1E-6;
+	} else if(rs_packet->indicatrix1 & RS_22_812_IND1_MILI) {
+		rawval *= 1E-3;
+	} else if(rs_packet->indicatrix1 & RS_22_812_IND1_KILO) {
+		rawval *= 1E3;
+	} else if(rs_packet->indicatrix1 & RS_22_812_IND1_MEGA) {
+		rawval *= 1E6;
+	}
+
+	return rawval;
+}
+
+static gboolean rs_22_812_is_celsius(rs_22_812_packet *rs_packet)
+{
+	return((rs_packet->digit4 & ~RS_22_812_DP_MASK) == RS_22_812_LCD_C);
+}
+
+static gboolean rs_22_812_is_shortcirc(rs_22_812_packet *rs_packet)
+{
+	return((rs_packet->digit2 & ~RS_22_812_DP_MASK) == RS_22_812_LCD_h);
+}
+
+static void rs_22_812_handle_packet(rs_22_812_packet *rs_packet,
+				    rs_dev_ctx *devc)
+{
+	double rawval = lcdraw_to_double(rs_packet, READ_ALL);
+	/* *********************************************************************
+	 * Now see what the value means, and pass that on
+	 **********************************************************************/
+	struct sr_datafeed_packet packet;
+	struct sr_datafeed_analog *analog;
+
+	analog = g_try_malloc0(sizeof(struct sr_datafeed_analog));
+	analog->num_samples = 1;
+	analog->data = g_try_malloc(sizeof(float));
+	*analog->data = (float)rawval;
+	analog->mq = -1;
+
+	switch(rs_packet->mode) {
+	case RS_22_812_MODE_DC_V:
+		analog->mq = SR_MQ_VOLTAGE;
+		analog->unit = SR_UNIT_VOLT;
+		analog->mqflags |= SR_MQFLAG_DC;
+		break;
+	case RS_22_812_MODE_AC_V:
+		analog->mq = SR_MQ_VOLTAGE;
+		analog->unit = SR_UNIT_VOLT;
+		analog->mqflags |= SR_MQFLAG_AC;
+		break;
+	case RS_22_812_MODE_DC_UA:
+	case RS_22_812_MODE_DC_MA:
+	case RS_22_812_MODE_DC_A:
+		analog->mq = SR_MQ_CURRENT;
+		analog->unit = SR_UNIT_AMPERE;
+		analog->mqflags |= SR_MQFLAG_DC;
+		break;
+	case RS_22_812_MODE_AC_UA:
+	case RS_22_812_MODE_AC_MA:
+	case RS_22_812_MODE_AC_A:
+		analog->mq = SR_MQ_CURRENT;
+		analog->unit = SR_UNIT_AMPERE;
+		analog->mqflags |= SR_MQFLAG_AC;
+		break;
+	case RS_22_812_MODE_OHM:
+		analog->mq = SR_MQ_RESISTANCE;
+		analog->unit = SR_UNIT_OHM;
+		break;
+	case RS_22_812_MODE_FARAD:
+		analog->mq = SR_MQ_CAPACITANCE;
+		analog->unit = SR_UNIT_FARAD;
+		break;
+	case RS_22_812_MODE_CONT:
+		analog->mq = SR_MQ_CONTINUITY;
+		analog->unit = SR_UNIT_BOOLEAN;
+		*analog->data = rs_22_812_is_shortcirc(rs_packet);
+		break;
+	case RS_22_812_MODE_DIODE:
+		analog->mq = SR_MQ_VOLTAGE;
+		analog->unit = SR_UNIT_VOLT;
+		analog->mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC;
+		break;
+	case RS_22_812_MODE_HZ:
+	case RS_22_812_MODE_VOLT_HZ:
+	case RS_22_812_MODE_AMP_HZ:
+		analog->mq = SR_MQ_FREQUENCY;
+		analog->unit = SR_UNIT_HERTZ;
+		break;
+	case RS_22_812_MODE_LOGIC:
+		analog->mq = 0; /* FIXME */
+		analog->unit = SR_UNIT_BOOLEAN;
+		sr_warn("radioshack-dmm: LOGIC mode not supported yet");
+		g_free(analog->data);
+		g_free(analog);
+		return;
+		break;
+	case RS_22_812_MODE_HFE:
+		analog->mq = SR_MQ_GAIN;
+		analog->unit = SR_UNIT_UNITLESS;
+		break;
+	case RS_22_812_MODE_DUTY:
+	case RS_22_812_MODE_VOLT_DUTY:
+	case RS_22_812_MODE_AMP_DUTY:
+		analog->mq = SR_MQ_DUTY_CYCLE;
+		analog->unit = SR_UNIT_PERCENTAGE;
+		break;
+	case RS_22_812_MODE_WIDTH:
+	case RS_22_812_MODE_VOLT_WIDTH:
+	case RS_22_812_MODE_AMP_WIDTH:
+		analog->mq = SR_MQ_PULSE_WIDTH;
+		analog->unit = SR_UNIT_SECOND;
+	case RS_22_812_MODE_TEMP:
+		analog->mq = SR_MQ_TEMPERATURE;
+		/* We need to reparse */
+		*analog->data = lcdraw_to_double(rs_packet, READ_TEMP);
+		analog->unit = rs_22_812_is_celsius(rs_packet)?
+				SR_UNIT_CELSIUS:SR_UNIT_FAHRENHEIT;
+		break;
+	case RS_22_812_MODE_DBM:
+		analog->mq = SR_MQ_POWER;
+		analog->unit = SR_UNIT_DECIBEL_MW;
+		analog->mqflags |= SR_MQFLAG_AC;
+		break;
+	default:
+		sr_warn("radioshack-dmm: unkown mode: %d", rs_packet->mode);
+		break;
+	}
+
+	if(rs_packet->info & RS_22_812_INFO_HOLD) {
+		analog->mqflags |= SR_MQFLAG_HOLD;
+	}
+	if(rs_packet->digit4 & RS_22_812_DIG4_MAX) {
+		analog->mqflags |= SR_MQFLAG_MAX;
+	}
+	if(rs_packet->indicatrix2 & RS_22_812_IND2_MIN) {
+		analog->mqflags |= SR_MQFLAG_MIN;
+	}
+	if(rs_packet->info & RS_22_812_INFO_AUTO) {
+		analog->mqflags |= SR_MQFLAG_AUTORANGE;
+	}
+
+	if (analog->mq != -1) {
+		/* Got a measurement. */
+		sr_spew("radioshack-dmm: val %f", rawval);
+		packet.type = SR_DF_ANALOG;
+		packet.payload = analog;
+		sr_session_send(devc->cb_data, &packet);
+		devc->num_samples++;
+	}
+	g_free(analog->data);
+	g_free(analog);
+}
+
+static void handle_new_data(rs_dev_ctx *devc, int fd)
+{
+	int len;
+	size_t i;
+	size_t offset = 0;
+	/* Try to get as much data as the buffer can hold */
+	len = RS_DMM_BUFSIZE - devc->buflen;
+	len = serial_read(fd, devc->buf + devc->buflen, len);
+	if (len < 1) {
+		sr_err("radioshack-dmm: serial port read error!");
+		return;
+	}
+	devc->buflen += len;
+
+	/* Now look for packets in that data */
+	while((devc->buflen - offset) >= RS_22_812_PACKET_SIZE)
+	{
+		rs_22_812_packet * packet = (void *)(devc->buf + offset);
+		if( rs_22_812_is_packet_valid(packet) )
+		{
+			rs_22_812_handle_packet(packet, devc);
+			offset += RS_22_812_PACKET_SIZE;
+		} else {
+			offset++;
+		}
+	}
+
+	/* If we have any data left, move it to the beginning of our buffer */
+	for(i = 0; i < devc->buflen - offset; i++)
+		devc->buf[i] = devc->buf[offset + i];
+	devc->buflen -= offset;
+}
+
+SR_PRIV int radioshack_receive_data(int fd, int revents, void *cb_data)
+{
+	const struct sr_dev_inst *sdi;
+	struct dev_context *devc;
+
+	if (!(sdi = cb_data))
+		return TRUE;
+
+	if (!(devc = sdi->priv))
+		return TRUE;
+
+	if (revents == G_IO_IN)
+	{
+		/* Serial data arrived. */
+		handle_new_data(devc, fd);
+	}
+
+	if (devc->num_samples >= devc->limit_samples) {
+		sdi->driver->dev_acquisition_stop(sdi, cb_data);
+		return TRUE;
+	}
+
+	return TRUE;
+}
+
+
diff --git a/libsigrok/hwdriver.c b/libsigrok/hwdriver.c
index 083504c..3b1718d 100644
--- a/libsigrok/hwdriver.c
+++ b/libsigrok/hwdriver.c
@@ -89,6 +89,9 @@ extern SR_PRIV struct sr_dev_driver agdmm_driver_info;
 #ifdef HAVE_HW_FLUKE_DMM
 extern SR_PRIV struct sr_dev_driver flukedmm_driver_info;
 #endif
+#ifdef HAVE_HW_RADIOSHACK_DMM
+extern SR_PRIV struct sr_dev_driver radioshackdmm_driver_info;
+#endif
 
 static struct sr_dev_driver *drivers_list[] = {
 #ifdef HAVE_LA_DEMO
@@ -127,6 +130,9 @@ static struct sr_dev_driver *drivers_list[] = {
 #ifdef HAVE_HW_FLUKE_DMM
 	&flukedmm_driver_info,
 #endif
+#ifdef HAVE_HW_RADIOSHACK_DMM
+	&radioshackdmm_driver_info,
+#endif
 	NULL,
 };
 
-- 
1.7.11.4

------------------------------------------------------------------------------
Don't let slow site performance ruin your business. Deploy New Relic APM
Deploy New Relic app performance management and know exactly
what is happening inside your Ruby, Python, PHP, Java, and .NET app
Try New Relic at no cost today and get our sweet Data Nerd shirt too!
http://p.sf.net/sfu/newrelic-dev2dev
_______________________________________________
sigrok-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/sigrok-devel

Reply via email to