Code drop from DreamSourceLabs first source release.
diff --git a/Makefile.am b/Makefile.am
index 68dbed5..52c9f0e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,5 @@
 ##
-## This file is part of the libsigrok project.
+## This file is part of the libsigrok4DSLogic project.
 ##
 ## Copyright (C) 2010-2012 Bert Vermeulen <bert@biot.com>
 ## Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
@@ -22,11 +22,11 @@
 
 AM_CPPFLAGS = -I$(top_srcdir)
 
-SUBDIRS = contrib hardware input output tests
+SUBDIRS = hardware input output tests
 
-lib_LTLIBRARIES = libsigrok.la
+lib_LTLIBRARIES = libsigrok4DSLogic.la
 
-libsigrok_la_SOURCES = \
+libsigrok4DSLogic_la_SOURCES = \
 	backend.c \
 	device.c \
 	session.c \
@@ -36,24 +36,25 @@
 	filter.c \
 	strutil.c \
 	log.c \
+        trigger.c \
 	version.c \
 	error.c \
 	std.c
 
-libsigrok_la_LIBADD = \
+libsigrok4DSLogic_la_LIBADD = \
 	$(LIBOBJS) \
-	hardware/libsigrokhardware.la \
-	input/libsigrokinput.la \
-	output/libsigrokoutput.la
+	hardware/libsigrok4DSLogichardware.la \
+	input/libsigrok4DSLogicinput.la \
+	output/libsigrok4DSLogicoutput.la
 
-libsigrok_la_LDFLAGS = $(SR_LIB_LDFLAGS)
+libsigrok4DSLogic_la_LDFLAGS = $(SR_LIB_LDFLAGS)
 
-library_includedir = $(includedir)/libsigrok
+library_includedir = $(includedir)/libsigrok4DSLogic
 library_include_HEADERS = libsigrok.h proto.h version.h
 noinst_HEADERS = libsigrok-internal.h
 
 pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = libsigrok.pc
+pkgconfig_DATA = libsigrok4DSLogic.pc
 
 EXTRA_DIST = Doxyfile README.devices
 
diff --git a/README b/README
index 0e74f7b..437294c 100644
--- a/README
+++ b/README
@@ -1,6 +1,9 @@
 -------------------------------------------------------------------------------
 README
 -------------------------------------------------------------------------------
+libsigrok4DSLogic is a shared library which provides the basic API
+for DSLogic hardware.
+libsigrok4DSLogic is based on libsigrok, a shared library from the sigrok project.
 
 The sigrok project aims at creating a portable, cross-platform,
 Free/Libre/Open-Source signal analysis software suite that supports various
@@ -38,23 +41,21 @@
  - libzip >= 0.8
  - libusb-1.0 >= 1.0.9 (optional, used by most drivers)
  - libftdi >= 0.16 (optional, used by some drivers)
- - libudev >= 151 (optional, used by some drivers)
  - libasound / alsa-lib >= 1.0 (optional, only used by the alsa driver)
  - check >= 0.9.4 (optional, only needed to run unit tests)
 
 
 Building and installing
 -----------------------
+Get the libsigrok4DSLogic source code from: www.dreamsourcelab.com/download.html
+In order to build it, run:
 
-In order to get the libsigrok source code and build it, run:
-
- $ git clone git://sigrok.org/libsigrok
  $ cd libsigrok
  $ ./autogen.sh
  $ ./configure
  $ make
 
-For installing libsigrok:
+For installing libsigrok4DSLogic:
 
  $ make install
 
@@ -63,24 +64,10 @@
  http://sigrok.org/wiki/Building
 
 
-Device-specific issues
-----------------------
-
-Please check README.devices for some notes and hints about device- or
-driver-specific issues to be aware of.
-
-
-Firmware
---------
-
-Some devices supported by libsigrok need a firmware to be uploaded before the
-device can be used. See README.devices for details.
-
-
 Copyright and license
 ---------------------
 
-libsigrok is licensed under the terms of the GNU General Public License
+libsigrok4DSLogic is licensed under the terms of the GNU General Public License
 (GPL), version 3 or later.
 
 While some individual source code files are licensed under the GPLv2+, and
@@ -109,4 +96,5 @@
 -------
 
  http://sigrok.org/wiki/Libsigrok
+ http://dreamsourcelab.com
 
diff --git a/autogen.sh b/autogen.sh
old mode 100755
new mode 100644
diff --git a/configure.ac b/configure.ac
index e475f6f..a54b23a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -27,8 +27,8 @@
 m4_define([sr_package_version_micro], [0])
 m4_define([sr_package_version], [sr_package_version_major.sr_package_version_minor.sr_package_version_micro])
 
-AC_INIT([libsigrok], [sr_package_version], [sigrok-devel@lists.sourceforge.net],
-	[libsigrok], [http://www.sigrok.org])
+AC_INIT([libsigrok4DSLogic], [sr_package_version], [support@dreamsourcelab.com],
+	[libsigrok4DSLogic], [http://www.dreamsourcelab.com])
 AC_CONFIG_HEADER([config.h])
 AC_CONFIG_MACRO_DIR([autostuff])
 AC_CONFIG_AUX_DIR([autostuff])
@@ -67,7 +67,7 @@
 # The algorithm for determining which number to change (and how) is nontrivial!
 # http://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info
 SR_LIB_VERSION_CURRENT=1
-SR_LIB_VERSION_REVISION=0
+SR_LIB_VERSION_REVISION=2
 SR_LIB_VERSION_AGE=0
 SR_LIB_VERSION="$SR_LIB_VERSION_CURRENT:$SR_LIB_VERSION_REVISION:$SR_LIB_VERSION_AGE"
 SR_LIB_LDFLAGS="-version-info $SR_LIB_VERSION"
@@ -77,126 +77,31 @@
 AC_SUBST(SR_LIB_VERSION)
 AC_SUBST(SR_LIB_LDFLAGS)
 
-# Hardware support '--enable' options.
-
 AC_ARG_ENABLE(all-drivers, AC_HELP_STRING([--enable-all-drivers],
-	[enable all drivers by default [default=yes]]),
-	[HW_ENABLED_DEFAULT="$enableval"],
-	[HW_ENABLED_DEFAULT="yes"])
-
-AC_ARG_ENABLE(agilent-dmm, AC_HELP_STRING([--enable-agilent-dmm],
-	[enable Agilent DMM support [default=yes]]),
-	[HW_AGILENT_DMM="$enableval"],
-	[HW_AGILENT_DMM=$HW_ENABLED_DEFAULT])
-
-AC_ARG_ENABLE(alsa, AC_HELP_STRING([--enable-alsa],
-	[enable ALSA driver support [default=yes]]),
-	[HW_ALSA="$enableval"],
-	[HW_ALSA=$HW_ENABLED_DEFAULT])
-
-AC_ARG_ENABLE(asix-sigma, AC_HELP_STRING([--enable-asix-sigma],
-	[enable ASIX SIGMA/SIGMA2 support [default=yes]]),
-	[LA_ASIX_SIGMA="$enableval"],
-	[LA_ASIX_SIGMA=$HW_ENABLED_DEFAULT])
-
-AC_ARG_ENABLE(brymen-dmm, AC_HELP_STRING([--enable-brymen-dmm],
-	[enable Brymen DMM support [default=yes]]),
-	[HW_BRYMEN_DMM="$enableval"],
-	[HW_BRYMEN_DMM=$HW_ENABLED_DEFAULT])
-
-AC_ARG_ENABLE(chronovu-la8, AC_HELP_STRING([--enable-chronovu-la8],
-	[enable ChronoVu LA8 support [default=yes]]),
-	[LA_CHRONOVU_LA8="$enableval"],
-	[LA_CHRONOVU_LA8=$HW_ENABLED_DEFAULT])
-
-AC_ARG_ENABLE(colead-slm, AC_HELP_STRING([--enable-colead-slm],
-	[enable Colead SLM support [default=yes]]),
-	[HW_COLEAD_SLM="$enableval"],
-	[HW_COLEAD_SLM=$HW_ENABLED_DEFAULT])
+        [enable all drivers by default [default=yes]]),
+        [HW_ENABLED_DEFAULT="$enableval"],
+        [HW_ENABLED_DEFAULT="yes"])
 
 AC_ARG_ENABLE(demo, AC_HELP_STRING([--enable-demo],
 	[enable demo driver support [default=yes]]),
-	[LA_DEMO="$enableval"],
-	[LA_DEMO=$HW_ENABLED_DEFAULT])
-
-AC_ARG_ENABLE(fluke-dmm, AC_HELP_STRING([--enable-fluke-dmm],
-	[enable Fluke DMM support [default=yes]]),
-	[HW_FLUKE_DMM="$enableval"],
-	[HW_FLUKE_DMM=$HW_ENABLED_DEFAULT])
-
-AC_ARG_ENABLE(fx2lafw, AC_HELP_STRING([--enable-fx2lafw],
-	[enable fx2lafw support (for FX2 LAs). [default=yes]]),
-	[LA_FX2LAFW="$enableval"],
-	[LA_FX2LAFW=$HW_ENABLED_DEFAULT])
-
-AC_ARG_ENABLE(hantek-dso, AC_HELP_STRING([--enable-hantek-dso],
-	[enable Hantek DSO support [default=yes]]),
-	[HW_HANTEK_DSO="$enableval"],
-	[HW_HANTEK_DSO=$HW_ENABLED_DEFAULT])
-
-AC_ARG_ENABLE(lascar-el-usb, AC_HELP_STRING([--enable-lascar-el-usb],
-	[enable Lascar EL-USB support [default=yes]]),
-	[HW_LASCAR_EL_USB="$enableval"],
-	[HW_LASCAR_EL_USB=$HW_ENABLED_DEFAULT])
-
-AC_ARG_ENABLE(link-mso19, AC_HELP_STRING([--enable-link-mso19],
-	[enable Link Instruments MSO-19 support [default=yes]]),
-	[LA_LINK_MSO19="$enableval"],
-	[LA_LINK_MSO19=$HW_ENABLED_DEFAULT])
-
-AC_ARG_ENABLE(mic-985xx, AC_HELP_STRING([--enable-mic-985xx],
-	[enable MIC 985xx support [default=yes]]),
-	[HW_MIC_985XX="$enableval"],
-	[HW_MIC_985XX=$HW_ENABLED_DEFAULT])
-
-AC_ARG_ENABLE(nexus-osciprime, AC_HELP_STRING([--enable-nexus-osciprime],
-	[enable Nexus Osciprime support [default=yes]]),
-	[HW_NEXUS_OSCIPRIME="$enableval"],
-	[HW_NEXUS_OSCIPRIME=$HW_ENABLED_DEFAULT])
-
-AC_ARG_ENABLE(ols, AC_HELP_STRING([--enable-ols],
-	[enable OpenBench Logic Sniffer (OLS) support [default=yes]]),
-	[LA_OLS="$enableval"],
-	[LA_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(serial-dmm, AC_HELP_STRING([--enable-serial-dmm],
-	[enable serial DMM support [default=yes]]),
-	[HW_SERIAL_DMM="$enableval"],
-	[HW_SERIAL_DMM=$HW_ENABLED_DEFAULT])
-
-AC_ARG_ENABLE(tondaj-sl-814, AC_HELP_STRING([--enable-tondaj-sl-814],
-	[enable Tondaj SL-814 support [default=yes]]),
-	[HW_TONDAJ_SL_814="$enableval"],
-	[HW_TONDAJ_SL_814=$HW_ENABLED_DEFAULT])
-
-AC_ARG_ENABLE(uni-t-dmm, AC_HELP_STRING([--enable-uni-t-dmm],
-	[enable UNI-T DMM support [default=yes]]),
-	[HW_UNI_T_DMM="$enableval"],
-	[HW_UNI_T_DMM=$HW_ENABLED_DEFAULT])
-
-AC_ARG_ENABLE(victor-dmm, AC_HELP_STRING([--enable-victor-dmm],
-	[enable victor-dmm support [default=yes]]),
-	[HW_VICTOR_DMM="$enableval"],
-	[HW_VICTOR_DMM=$HW_ENABLED_DEFAULT])
-
-AC_ARG_ENABLE(zeroplus-logic-cube,
-	AC_HELP_STRING([--enable-zeroplus-logic-cube],
-	[enable ZEROPLUS Logic Cube support [default=yes]]),
-	[LA_ZEROPLUS_LOGIC_CUBE="$enableval"],
-	[LA_ZEROPLUS_LOGIC_CUBE=$HW_ENABLED_DEFAULT])
-
+	[HW_DEMO="$enableval"],
+	[HW_DEMO=$HW_ENABLED_DEFAULT])
 # Checks for libraries.
 
+case "$host" in
+*mingw*)
+	# We need to link against the Winsock2 library for SCPI over TCP.
+	LIBS="$LIBS -lws2_32";;
+esac
+
 # This variable collects the pkg-config names of all detected libs.
 # It is then used to construct the "Requires.private:" field in the
-# libsigrok.pc file.
+# libsigrok4DSLogic.pc file.
 SR_PKGLIBS=""
 
+# libm (the standard math library) is always needed.
+AC_SEARCH_LIBS([pow], [m])
+
 # libglib-2.0 is always needed. Abort if it's not found.
 # Note: glib-2.0 is part of the libsigrok API (hard pkg-config requirement).
 # We require at least 2.32.0 due to e.g. g_variant_new_fixed_array().
@@ -204,10 +109,27 @@
 	[CFLAGS="$CFLAGS $GLIB_CFLAGS"; LIBS="$LIBS $GLIB_LIBS"])
 
 # libzip is always needed. Abort if it's not found.
-PKG_CHECK_MODULES([libzip], [libzip >= 0.8],
+PKG_CHECK_MODULES([libzip], [libzip >= 0.10],
 	[CFLAGS="$CFLAGS $libzip_CFLAGS"; LIBS="$LIBS $libzip_LIBS";
 	SR_PKGLIBS="$SR_PKGLIBS libzip"])
 
+# libserialport is only needed for some hardware drivers. Disable the
+# respective drivers if it is not found.
+PKG_CHECK_MODULES([libserialport], [libserialport >= 0.1.0],
+	[have_libserialport="yes"; CFLAGS="$CFLAGS $libserialport_CFLAGS";
+	LIBS="$LIBS $libserialport_LIBS";
+	SR_PKGLIBS="$SR_PKGLIBS libserialport"],
+	[have_libserialport="no"])
+
+# Define HAVE_LIBSERIALPORT in config.h if we found libserialport.
+if test "x$have_libserialport" != "xno"; then
+	AC_DEFINE_UNQUOTED(HAVE_LIBSERIALPORT, [1],
+		[Specifies whether we have libserialport.])
+fi
+
+# Serial port helper code is only compiled in if libserialport was found.
+AM_CONDITIONAL(NEED_SERIAL, test "x$have_libserialport" != xno)
+
 # libusb-1.0 is only needed for some hardware drivers. Disable the respective
 # drivers if it is not found.
 case "$host" in
@@ -223,10 +145,7 @@
 		[have_libusb1_0="yes"; CFLAGS="$CFLAGS $libusb_CFLAGS";
 		LIBS="$LIBS $libusb_LIBS";
 		SR_PKGLIBS="$SR_PKGLIBS libusb-1.0"],
-		[have_libusb1_0="no"; LA_FX2LAFW="no"; HW_HANTEK_DSO="no";
-		HW_LASCAR_EL_USB="no"; HW_NEXUS_OSCIPRIME="no";
-		HW_UNI_T_DMM="no"; HW_VICTOR_DMM="no";
-		LA_ZEROPLUS_LOGIC_CUBE="no"])
+		[have_libusb1_0="no"])
 
 	# Define HAVE_LIBUSB_1_0 in config.h if we found libusb-1.0.
 	if test "x$have_libusb1_0" != "xno"; then
@@ -236,27 +155,7 @@
 	;;
 esac
 
-# USB + FX2 firmware helper code is only compiled in if libusb-1.0 was found.
-AM_CONDITIONAL(NEED_USB, test "x$have_libusb1_0" != xno)
 
-# libftdi is only needed for some hardware drivers. Disable them if not found.
-PKG_CHECK_MODULES([libftdi], [libftdi >= 0.16],
-	[CFLAGS="$CFLAGS $libftdi_CFLAGS";
-	LIBS="$LIBS $libftdi_LIBS";
-	SR_PKGLIBS="$SR_PKGLIBS libftdi"],
-	[LA_ASIX_SIGMA="no"; LA_CHRONOVU_LA8="no"])
-
-# libudev is only needed for some hardware drivers. Disable them if not found.
-PKG_CHECK_MODULES([libudev], [libudev >= 151],
-	[CFLAGS="$CFLAGS $libudev_CFLAGS"; LIBS="$LIBS $libudev_LIBS";
-	SR_PKGLIBS="$SR_PKGLIBS libudev"],
-	[LA_LINK_MSO19="no"])
-
-# ALSA is only needed for some hardware drivers. Disable them if not found.
-PKG_CHECK_MODULES([alsa], [alsa >= 1.0],
-	[CFLAGS="$CFLAGS $alsa_CFLAGS"; LIBS="$LIBS $alsa_LIBS";
-	SR_PKGLIBS="$SR_PKGLIBS alsa"],
-	[HW_ALSA="no"])
 
 # The Check unit testing framework is optional. Disable if not found.
 PKG_CHECK_MODULES([check], [check >= 0.9.4],
@@ -264,135 +163,29 @@
 	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
-# (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.
-	;;
-*)
-	# Disable the driver for builds that don't target Linux.
-	HW_RIGOL_DS1XX2="no"
-	;;
-esac
+# The OLS driver uses serial port file descriptors directly, and therefore
+# will not currently work on Windows.
+
 
 AC_SUBST(SR_PKGLIBS)
 
 # Now set AM_CONDITIONALs and AC_DEFINEs for the enabled/disabled drivers.
 
-AM_CONDITIONAL(HW_AGILENT_DMM, test x$HW_AGILENT_DMM = xyes)
-if test "x$HW_AGILENT_DMM" = "xyes"; then
-	AC_DEFINE(HAVE_HW_AGILENT_DMM, 1, [Agilent DMM support])
-fi
 
-AM_CONDITIONAL(HW_ALSA, test x$HW_ALSA = xyes)
-if test "x$HW_ALSA" = "xyes"; then
-	AC_DEFINE(HAVE_HW_ALSA, 1, [ALSA driver support])
-fi
 
-AM_CONDITIONAL(LA_ASIX_SIGMA, test x$LA_ASIX_SIGMA = xyes)
-if test "x$LA_ASIX_SIGMA" = "xyes"; then
-	AC_DEFINE(HAVE_LA_ASIX_SIGMA, 1, [ASIX SIGMA/SIGMA2 support])
-fi
-
-AM_CONDITIONAL(HW_BRYMEN_DMM, test x$HW_BRYMEN_DMM = xyes)
-if test "x$HW_BRYMEN_DMM" = "xyes"; then
-	AC_DEFINE(HAVE_HW_BRYMEN_DMM, 1, [Brymen DMM support])
-fi
-
-AM_CONDITIONAL(LA_CHRONOVU_LA8, test x$LA_CHRONOVU_LA8 = xyes)
-if test "x$LA_CHRONOVU_LA8" = "xyes"; then
-	AC_DEFINE(HAVE_LA_CHRONOVU_LA8, 1, [ChronoVu LA8 support])
-fi
-
-AM_CONDITIONAL(HW_COLEAD_SLM, test x$HW_COLEAD_SLM = xyes)
-if test "x$HW_COLEAD_SLM" = "xyes"; then
-	AC_DEFINE(HAVE_HW_COLEAD_SLM, 1, [Colead SLM support])
-fi
-
-AM_CONDITIONAL(LA_DEMO, test x$LA_DEMO = xyes)
-if test "x$LA_DEMO" = "xyes"; then
+AM_CONDITIONAL(HW_DEMO, test x$HW_DEMO = xyes)
+if test "x$HW_DEMO" = "xyes"; then
 	AC_DEFINE(HAVE_LA_DEMO, 1, [Demo driver support])
 fi
 
-AM_CONDITIONAL(HW_FLUKE_DMM, test x$HW_FLUKE_DMM = xyes)
-if test "x$HW_FLUKE_DMM" = "xyes"; then
-	AC_DEFINE(HAVE_HW_FLUKE_DMM, 1, [Fluke DMM support])
-fi
 
-AM_CONDITIONAL(LA_FX2LAFW, test x$LA_FX2LAFW = xyes)
-if test "x$LA_FX2LAFW" = "xyes"; then
-	AC_DEFINE(HAVE_LA_FX2LAFW, 1, [fx2lafw support])
-fi
-
-AM_CONDITIONAL(HW_HANTEK_DSO, test x$HW_HANTEK_DSO = xyes)
-if test "x$HW_HANTEK_DSO" = "xyes"; then
-	AC_DEFINE(HAVE_HW_HANTEK_DSO, 1, [Hantek DSO support])
-fi
-
-AM_CONDITIONAL(HW_LASCAR_EL_USB, test x$HW_LASCAR_EL_USB = xyes)
-if test "x$HW_LASCAR_EL_USB" = "xyes"; then
-	AC_DEFINE(HAVE_HW_LASCAR_EL_USB, 1, [Lascar EL-USB support])
-fi
-
-AM_CONDITIONAL(LA_LINK_MSO19, test x$LA_LINK_MSO19 = xyes)
-if test "x$LA_LINK_MSO19" = "xyes"; then
-	AC_DEFINE(HAVE_LA_LINK_MSO19, 1, [Link Instruments MSO-19 support])
-fi
-
-AM_CONDITIONAL(HW_MIC_985XX, test x$HW_MIC_985XX = xyes)
-if test "x$HW_MIC_985XX" = "xyes"; then
-	AC_DEFINE(HAVE_HW_MIC_985XX, 1, [MIC 985xx support])
-fi
-
-AM_CONDITIONAL(HW_NEXUS_OSCIPRIME, test x$HW_NEXUS_OSCIPRIME = xyes)
-if test "x$HW_NEXUS_OSCIPRIME" = "xyes"; then
-	AC_DEFINE(HAVE_HW_NEXUS_OSCIPRIME, 1, [Nexus Osciprime support])
-fi
-
-AM_CONDITIONAL(LA_OLS, test x$LA_OLS = xyes)
-if test "x$LA_OLS" = "xyes"; then
-	AC_DEFINE(HAVE_LA_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])
-fi
-
-AM_CONDITIONAL(HW_SERIAL_DMM, test x$HW_SERIAL_DMM = xyes)
-if test "x$HW_SERIAL_DMM" = "xyes"; then
-	AC_DEFINE(HAVE_HW_SERIAL_DMM, 1, [Serial DMM support])
-fi
-
-AM_CONDITIONAL(HW_TONDAJ_SL_814, test x$HW_TONDAJ_SL_814 = xyes)
-if test "x$HW_TONDAJ_SL_814" = "xyes"; then
-	AC_DEFINE(HAVE_HW_TONDAJ_SL_814, 1, [Tondaj SL-814 support])
-fi
-
-AM_CONDITIONAL(HW_UNI_T_DMM, test x$HW_UNI_T_DMM = xyes)
-if test "x$HW_UNI_T_DMM" = "xyes"; then
-	AC_DEFINE(HAVE_HW_UNI_T_DMM, 1, [UNI-T DMM support])
-fi
-
-AM_CONDITIONAL(HW_VICTOR_DMM, test x$HW_VICTOR_DMM = xyes)
-if test "x$HW_VICTOR_DMM" = "xyes"; then
-	AC_DEFINE(HAVE_HW_VICTOR_DMM, 1, [Victor DMM support])
-fi
-
-AM_CONDITIONAL(LA_ZEROPLUS_LOGIC_CUBE, test x$LA_ZEROPLUS_LOGIC_CUBE = xyes)
-if test "x$LA_ZEROPLUS_LOGIC_CUBE" = "xyes"; then
-	AC_DEFINE(HAVE_LA_ZEROPLUS_LOGIC_CUBE, 1, [ZEROPLUS Logic Cube support])
-fi
 
 # Checks for header files.
 # These are already checked: inttypes.h stdint.h stdlib.h string.h unistd.h.
 AC_CHECK_HEADERS([fcntl.h sys/time.h termios.h])
 
 # Checks for typedefs, structures, and compiler characteristics.
+AC_C_BIGENDIAN
 AC_C_INLINE
 AC_TYPE_INT8_T
 AC_TYPE_INT16_T
@@ -422,34 +215,11 @@
 AC_SUBST(SR_PACKAGE_VERSION)
 
 AC_CONFIG_FILES([Makefile version.h hardware/Makefile
-		 hardware/agilent-dmm/Makefile
-		 hardware/alsa/Makefile
-		 hardware/asix-sigma/Makefile
-		 hardware/brymen-dmm/Makefile
-		 hardware/chronovu-la8/Makefile
-		 hardware/colead-slm/Makefile
-		 hardware/common/Makefile
-		 hardware/lascar-el-usb/Makefile
-		 hardware/mic-985xx/Makefile
-		 hardware/nexus-osciprime/Makefile
-		 hardware/rigol-ds1xx2/Makefile
-		 hardware/tondaj-sl-814/Makefile
-		 hardware/victor-dmm/Makefile
-		 hardware/common/dmm/Makefile
 		 hardware/demo/Makefile
-		 hardware/fluke-dmm/Makefile
-		 hardware/fx2lafw/Makefile
-		 hardware/hantek-dso/Makefile
-		 hardware/link-mso19/Makefile
-		 hardware/openbench-logic-sniffer/Makefile
-		 hardware/serial-dmm/Makefile
-		 hardware/uni-t-dmm/Makefile
-		 hardware/zeroplus-logic-cube/Makefile
 		 input/Makefile
 		 output/Makefile
 		 output/text/Makefile
-		 libsigrok.pc
-		 contrib/Makefile
+		 libsigrok4DSLogic.pc
 		 tests/Makefile
 		])
 
@@ -468,7 +238,7 @@
 echo
 
 # Note: This only works for libs with pkg-config integration.
-for lib in "glib-2.0 >= 2.32.0" "libzip >= 0.8" "libusb-1.0 >= 1.0.9" "libftdi >= 0.16" "libudev >= 151" "alsa >= 1.0" "check >= 0.9.4"; do
+for lib in "glib-2.0 >= 2.32.0" "libzip >= 0.10" "libserialport >= 0.1.0" "libusb-1.0 >= 1.0.9" "libftdi >= 0.16" "libudev >= 151" "alsa >= 1.0" "check >= 0.9.4"; do
 	if `$PKG_CONFIG --exists $lib`; then
 		ver=`$PKG_CONFIG --modversion $lib`
 		answer="yes ($ver)"
@@ -479,26 +249,6 @@
 done
 
 echo -e "\nEnabled hardware drivers:\n"
-echo "  - agilent-dmm..................... $HW_AGILENT_DMM"
-echo "  - alsa............................ $HW_ALSA"
-echo "  - asix-sigma...................... $LA_ASIX_SIGMA"
-echo "  - brymen-dmm...................... $HW_BRYMEN_DMM"
-echo "  - chronovu-la8.................... $LA_CHRONOVU_LA8"
-echo "  - colead-slm...................... $HW_COLEAD_SLM"
-echo "  - demo............................ $LA_DEMO"
-echo "  - fluke-dmm....................... $HW_FLUKE_DMM"
-echo "  - fx2lafw......................... $LA_FX2LAFW"
-echo "  - hantek-dso...................... $HW_HANTEK_DSO"
-echo "  - lascar-el-usb................... $HW_LASCAR_EL_USB"
-echo "  - link-mso19...................... $LA_LINK_MSO19"
-echo "  - mic-985xx....................... $HW_MIC_985XX"
-echo "  - nexus-osciprime................. $HW_NEXUS_OSCIPRIME"
-echo "  - openbench-logic-sniffer......... $LA_OLS"
-echo "  - rigol-ds1xx2.................... $HW_RIGOL_DS1XX2"
-echo "  - serial-dmm...................... $HW_SERIAL_DMM"
-echo "  - tondaj-sl-814................... $HW_TONDAJ_SL_814"
-echo "  - uni-t-dmm....................... $HW_UNI_T_DMM"
-echo "  - victor-dmm...................... $HW_VICTOR_DMM"
-echo "  - zeroplus-logic-cube............. $LA_ZEROPLUS_LOGIC_CUBE"
+echo "  - demo............................ $HW_DEMO"
 echo
 
diff --git a/device.c b/device.c
index a49faa8..cca0bcd 100644
--- a/device.c
+++ b/device.c
@@ -225,7 +225,7 @@
 }
 
 /** @private */
-SR_PRIV struct sr_dev_inst *sr_dev_inst_new(int index, int status,
+SR_PRIV struct sr_dev_inst *sr_dev_inst_new(int mode, int index, int status,
 		const char *vendor, const char *model, const char *version)
 {
 	struct sr_dev_inst *sdi;
@@ -236,6 +236,7 @@
 	}
 
 	sdi->driver = NULL;
+    sdi->mode = mode;
 	sdi->index = index;
 	sdi->status = status;
 	sdi->inst_type = -1;
@@ -250,6 +251,20 @@
 }
 
 /** @private */
+SR_PRIV void sr_dev_probes_free(struct sr_dev_inst *sdi)
+{
+    struct sr_probe *probe;
+    GSList *l;
+
+    for (l = sdi->probes; l; l = l->next) {
+        probe = l->data;
+        g_free(probe->name);
+        g_free(probe);
+    }
+
+    sdi->probes = NULL;
+}
+
 SR_PRIV void sr_dev_inst_free(struct sr_dev_inst *sdi)
 {
 	struct sr_probe *probe;
diff --git a/hardware/Makefile.am b/hardware/Makefile.am
index 3c093b7..4f5d0a7 100644
--- a/hardware/Makefile.am
+++ b/hardware/Makefile.am
@@ -19,117 +19,14 @@
 ##
 
 SUBDIRS = \
-	agilent-dmm \
-	alsa \
-	asix-sigma \
-	brymen-dmm \
-	chronovu-la8 \
-	colead-slm \
-	common \
-	demo \
-	fluke-dmm \
-	fx2lafw \
-	hantek-dso \
-	lascar-el-usb \
-	link-mso19 \
-	mic-985xx \
-	nexus-osciprime \
-	openbench-logic-sniffer \
-	rigol-ds1xx2 \
-	serial-dmm \
-	tondaj-sl-814 \
-	uni-t-dmm \
-	victor-dmm \
-	zeroplus-logic-cube
+	demo
 
-noinst_LTLIBRARIES = libsigrokhardware.la
+noinst_LTLIBRARIES = libsigrok4DSLogichardware.la
 
-libsigrokhardware_la_SOURCES =
+libsigrok4DSLogichardware_la_SOURCES =
 
-libsigrokhardware_la_LIBADD = \
-	common/libsigrokhwcommon.la
+libsigrok4DSLogichardware_la_LIBADD = 
 
-if HW_AGILENT_DMM
-libsigrokhardware_la_LIBADD += agilent-dmm/libsigrokhwagilentdmm.la
+if HW_DEMO
+libsigrok4DSLogichardware_la_LIBADD += demo/libsigrok4DSLogic_hw_demo.la
 endif
-
-if HW_ALSA
-libsigrokhardware_la_LIBADD += alsa/libsigrokhwalsa.la
-endif
-
-if LA_ASIX_SIGMA
-libsigrokhardware_la_LIBADD += asix-sigma/libsigrokhwasixsigma.la
-endif
-
-if HW_BRYMEN_DMM
-libsigrokhardware_la_LIBADD += brymen-dmm/libsigrok_hw_brymen_dmm.la
-endif
-
-if LA_CHRONOVU_LA8
-libsigrokhardware_la_LIBADD += chronovu-la8/libsigrokhwchronovula8.la
-endif
-
-if HW_COLEAD_SLM
-libsigrokhardware_la_LIBADD += colead-slm/libsigrok_hw_colead_slm.la
-endif
-
-if LA_DEMO
-libsigrokhardware_la_LIBADD += demo/libsigrokhwdemo.la
-endif
-
-if HW_FLUKE_DMM
-libsigrokhardware_la_LIBADD += fluke-dmm/libsigrokhwflukedmm.la
-endif
-
-if LA_FX2LAFW
-libsigrokhardware_la_LIBADD += fx2lafw/libsigrokhwfx2lafw.la
-endif
-
-if HW_HANTEK_DSO
-libsigrokhardware_la_LIBADD += hantek-dso/libsigrokhw_hantek_dso.la
-endif
-
-if HW_LASCAR_EL_USB
-libsigrokhardware_la_LIBADD += lascar-el-usb/libsigrok_hw_lascar_el_usb.la
-endif
-
-if LA_LINK_MSO19
-libsigrokhardware_la_LIBADD += link-mso19/libsigrokhwlinkmso19.la
-endif
-
-if HW_MIC_985XX
-libsigrokhardware_la_LIBADD += mic-985xx/libsigrok_hw_mic_985xx.la
-endif
-
-if HW_NEXUS_OSCIPRIME
-libsigrokhardware_la_LIBADD += nexus-osciprime/libsigrok_hw_nexus_osciprime.la
-endif
-
-if LA_OLS
-libsigrokhardware_la_LIBADD += openbench-logic-sniffer/libsigrokhwols.la
-endif
-
-if HW_RIGOL_DS1XX2
-libsigrokhardware_la_LIBADD += rigol-ds1xx2/libsigrok_hw_rigol_ds1xx2.la
-endif
-
-if HW_SERIAL_DMM
-libsigrokhardware_la_LIBADD += serial-dmm/libsigrokhwserialdmm.la
-endif
-
-if HW_TONDAJ_SL_814
-libsigrokhardware_la_LIBADD += tondaj-sl-814/libsigrok_hw_tondaj_sl_814.la
-endif
-
-if HW_UNI_T_DMM
-libsigrokhardware_la_LIBADD += uni-t-dmm/libsigrok_hw_uni_t_dmm.la
-endif
-
-if HW_VICTOR_DMM
-libsigrokhardware_la_LIBADD += victor-dmm/libsigrok_hw_victor_dmm.la
-endif
-
-if LA_ZEROPLUS_LOGIC_CUBE
-libsigrokhardware_la_LIBADD += zeroplus-logic-cube/libsigrokhwzeroplus.la
-endif
-
diff --git a/hardware/demo/Makefile.am b/hardware/demo/Makefile.am
index d175991..9bb85dd 100644
--- a/hardware/demo/Makefile.am
+++ b/hardware/demo/Makefile.am
@@ -17,15 +17,15 @@
 ## along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ##
 
-if LA_DEMO
+if HW_DEMO
 
 # Local lib, this is NOT meant to be installed!
-noinst_LTLIBRARIES = libsigrokhwdemo.la
+noinst_LTLIBRARIES = libsigrok4DSLogic_hw_demo.la
 
-libsigrokhwdemo_la_SOURCES = \
+libsigrok4DSLogic_hw_demo_la_SOURCES = \
 	demo.c
 
-libsigrokhwdemo_la_CFLAGS = \
+libsigrok4DSLogic_hw_demo_la_CFLAGS = \
 	-I$(top_srcdir)
 
 endif
diff --git a/hardware/demo/demo.c b/hardware/demo/demo.c
index 98c9545..67df85e 100644
--- a/hardware/demo/demo.c
+++ b/hardware/demo/demo.c
@@ -23,6 +23,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
+#include <math.h>
 #ifdef _WIN32
 #include <io.h>
 #include <fcntl.h>
@@ -41,42 +42,34 @@
 #define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args)
 
 /* TODO: Number of probes should be configurable. */
-#define NUM_PROBES             8
+#define NUM_PROBES             16
 
 #define DEMONAME               "Demo device"
 
 /* The size of chunks to send through the session bus. */
 /* TODO: Should be configurable. */
-#define BUFSIZE                4096
+#define BUFSIZE                1024*1024
 
-#define STR_PATTERN_SIGROK   "sigrok"
-#define STR_PATTERN_RANDOM   "random"
-#define STR_PATTERN_INC      "incremental"
-#define STR_PATTERN_ALL_LOW  "all-low"
-#define STR_PATTERN_ALL_HIGH "all-high"
+#define PERIOD                  4000
+
+#define PI 3.14159265
+
+#define CONST_LEN               50
 
 /* Supported patterns which we can generate */
 enum {
-	/**
-	 * Pattern which spells "sigrok" using '0's (with '1's as "background")
-	 * when displayed using the 'bits' output format.
-	 */
-	PATTERN_SIGROK,
-
-	/** Pattern which consists of (pseudo-)random values on all probes. */
-	PATTERN_RANDOM,
-
-	/**
-	 * Pattern which consists of incrementing numbers.
-	 * TODO: Better description.
-	 */
-	PATTERN_INC,
-
-	/** Pattern where all probes have a low logic state. */
-	PATTERN_ALL_LOW,
-
-	/** Pattern where all probes have a high logic state. */
-	PATTERN_ALL_HIGH,
+    PATTERN_SINE = 0,
+    PATTERN_SQUARE = 1,
+    PATTERN_TRIANGLE = 2,
+    PATTERN_SAWTOOTH = 3,
+    PATTERN_RANDOM = 4,
+};
+static const char *pattern_strings[] = {
+    "Sine",
+    "Square",
+    "Triangle",
+    "Sawtooth",
+    "Random",
 };
 
 /* Private, per-device-instance driver context. */
@@ -91,6 +84,12 @@
 	uint64_t samples_counter;
 	void *cb_data;
 	int64_t starttime;
+    int stop;
+
+    int trigger_stage;
+    uint16_t trigger_mask;
+    uint16_t trigger_value;
+    uint16_t trigger_edge;
 };
 
 static const int hwcaps[] = {
@@ -103,37 +102,38 @@
 	SR_CONF_CONTINUOUS,
 };
 
-static const uint64_t samplerates[] = {
-	SR_HZ(1),
-	SR_GHZ(1),
-	SR_HZ(1),
+static const int hwoptions[] = {
+    SR_CONF_PATTERN_MODE,
 };
 
-static const char *pattern_strings[] = {
-	"sigrok",
-	"random",
-	"incremental",
-	"all-low",
-	"all-high",
+static const uint64_t samplerates[] = {
+    SR_KHZ(10),
+    SR_KHZ(20),
+    SR_KHZ(50),
+    SR_KHZ(100),
+    SR_KHZ(200),
+    SR_KHZ(500),
+    SR_MHZ(1),
+    SR_MHZ(2),
+    SR_MHZ(5),
+    SR_MHZ(10),
+    SR_MHZ(20),
+    SR_MHZ(50),
+    SR_MHZ(100),
+    SR_MHZ(200),
 };
 
+
+
 /* We name the probes 0-7 on our demo driver. */
 static const char *probe_names[NUM_PROBES + 1] = {
-	"0", "1", "2", "3", "4", "5", "6", "7",
+    "Channel 0", "Channel 1", "Channel 2", "Channel 3",
+    "Channel 4", "Channel 5", "Channel 6", "Channel 7",
+    "Channel 8", "Channel 9", "Channel 10", "Channel 11",
+    "Channel 12", "Channel 13", "Channel 14", "Channel 15",
 	NULL,
 };
 
-static uint8_t pattern_sigrok[] = {
-	0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00,
-	0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00,
-	0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00,
-	0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00,
-	0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00,
-	0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
 /* Private, per-device-instance driver context. */
 /* TODO: struct context as with the other drivers. */
 
@@ -141,6 +141,8 @@
 SR_PRIV struct sr_dev_driver demo_driver_info;
 static struct sr_dev_driver *di = &demo_driver_info;
 
+extern struct ds_trigger *trigger;
+
 static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data);
 
 static int clear_instances(void)
@@ -170,20 +172,13 @@
 
 	devices = NULL;
 
-	sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
+    sdi = sr_dev_inst_new(LOGIC, 0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
 	if (!sdi) {
-		sr_err("Device instance creation failed.");
+        sr_err("Device instance creation failed.");
 		return NULL;
 	}
 	sdi->driver = di;
 
-	for (i = 0; probe_names[i]; i++) {
-		if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
-				probe_names[i])))
-			return NULL;
-		sdi->probes = g_slist_append(sdi->probes, probe);
-	}
-
 	devices = g_slist_append(devices, sdi);
 	drvc->instances = g_slist_append(drvc->instances, sdi);
 
@@ -193,13 +188,29 @@
 	}
 
 	devc->sdi = sdi;
-	devc->cur_samplerate = SR_KHZ(200);
+    devc->cur_samplerate = SR_MHZ(200);
 	devc->limit_samples = 0;
 	devc->limit_msec = 0;
-	devc->sample_generator = PATTERN_SIGROK;
+    devc->sample_generator = PATTERN_SINE;
 
 	sdi->priv = devc;
 
+    if (sdi->mode == LOGIC) {
+        for (i = 0; probe_names[i]; i++) {
+            if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
+                    probe_names[i])))
+                return NULL;
+            sdi->probes = g_slist_append(sdi->probes, probe);
+        }
+    } else if (sdi->mode == ANALOG) {
+        for (i = 0; i < DS_MAX_ANALOG_PROBES_NUM; i++) {
+            if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE,
+                    probe_names[i])))
+                return NULL;
+            sdi->probes = g_slist_append(sdi->probes, probe);
+        }
+    }
+
 	return devices;
 }
 
@@ -266,24 +277,11 @@
 	case SR_CONF_LIMIT_MSEC:
 		*data = g_variant_new_uint64(devc->limit_msec);
 		break;
-	case SR_CONF_PATTERN_MODE:
-		switch (devc->sample_generator) {
-		case PATTERN_SIGROK:
-			*data = g_variant_new_string(STR_PATTERN_SIGROK);
-			break;
-		case PATTERN_RANDOM:
-			*data = g_variant_new_string(STR_PATTERN_RANDOM);
-			break;
-		case PATTERN_INC:
-			*data = g_variant_new_string(STR_PATTERN_INC);
-			break;
-		case PATTERN_ALL_LOW:
-			*data = g_variant_new_string(STR_PATTERN_ALL_LOW);
-			break;
-		case PATTERN_ALL_HIGH:
-			*data = g_variant_new_string(STR_PATTERN_ALL_HIGH);
-			break;
-		}
+    case SR_CONF_DEVICE_MODE:
+        *data = g_variant_new_string(mode_strings[sdi->mode]);
+        break;
+    case SR_CONF_PATTERN_MODE:
+        *data = g_variant_new_string(pattern_strings[devc->sample_generator]);
 		break;
 	default:
 		return SR_ERR_NA;
@@ -292,10 +290,11 @@
 	return SR_OK;
 }
 
-static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi)
+static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi)
 {
-	int ret;
+    int i, ret;
 	const char *stropt;
+    struct sr_probe *probe;
 
 	struct dev_context *const devc = sdi->priv;
 
@@ -318,27 +317,54 @@
 		devc->limit_samples = 0;
 		sr_dbg("%s: setting limit_msec to %" PRIu64, __func__,
 		       devc->limit_msec);
-		ret = SR_OK;
-	} else if (id == SR_CONF_PATTERN_MODE) {
+        ret = SR_OK;
+    } else if (id == SR_CONF_DEVICE_MODE) {
+        stropt = g_variant_get_string(data, NULL);
+        ret = SR_OK;
+        if (!strcmp(stropt, mode_strings[LOGIC])) {
+            sdi->mode = LOGIC;
+            sr_dev_probes_free(sdi);
+            for (i = 0; probe_names[i]; i++) {
+                if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
+                        probe_names[i])))
+                    ret = SR_ERR;
+                else
+                    sdi->probes = g_slist_append(sdi->probes, probe);
+            }
+        } else if (!strcmp(stropt, mode_strings[ANALOG])) {
+            sdi->mode = ANALOG;
+            sr_dev_probes_free(sdi);
+            for (i = 0; i < DS_MAX_ANALOG_PROBES_NUM; i++) {
+                if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE,
+                        probe_names[i])))
+                    ret = SR_ERR;
+                else
+                    sdi->probes = g_slist_append(sdi->probes, probe);
+            }
+        } else {
+            ret = SR_ERR;
+        }
+        sr_dbg("%s: setting mode to %d", __func__, sdi->mode);
+    }else if (id == SR_CONF_PATTERN_MODE) {
 		stropt = g_variant_get_string(data, NULL);
-		ret = SR_OK;
-		if (!strcmp(stropt, STR_PATTERN_SIGROK)) {
-			devc->sample_generator = PATTERN_SIGROK;
-		} else if (!strcmp(stropt, STR_PATTERN_RANDOM)) {
-			devc->sample_generator = PATTERN_RANDOM;
-		} else if (!strcmp(stropt, STR_PATTERN_INC)) {
-			devc->sample_generator = PATTERN_INC;
-		} else if (!strcmp(stropt, STR_PATTERN_ALL_LOW)) {
-			devc->sample_generator = PATTERN_ALL_LOW;
-		} else if (!strcmp(stropt, STR_PATTERN_ALL_HIGH)) {
-			devc->sample_generator = PATTERN_ALL_HIGH;
+        ret = SR_OK;
+        if (!strcmp(stropt, pattern_strings[PATTERN_SINE])) {
+            devc->sample_generator = PATTERN_SINE;
+        } else if (!strcmp(stropt, pattern_strings[PATTERN_SQUARE])) {
+            devc->sample_generator = PATTERN_SQUARE;
+        } else if (!strcmp(stropt, pattern_strings[PATTERN_TRIANGLE])) {
+            devc->sample_generator = PATTERN_TRIANGLE;
+        } else if (!strcmp(stropt, pattern_strings[PATTERN_SAWTOOTH])) {
+            devc->sample_generator = PATTERN_SAWTOOTH;
+        } else if (!strcmp(stropt, pattern_strings[PATTERN_RANDOM])) {
+            devc->sample_generator = PATTERN_RANDOM;
 		} else {
-			ret = SR_ERR;
+            ret = SR_ERR;
 		}
-		sr_dbg("%s: setting pattern to %d",
+        sr_dbg("%s: setting pattern to %d",
 			__func__, devc->sample_generator);
 	} else {
-		ret = SR_ERR_NA;
+        ret = SR_ERR_NA;
 	}
 
 	return ret;
@@ -352,108 +378,213 @@
 	(void)sdi;
 
 	switch (key) {
-	case SR_CONF_DEVICE_OPTIONS:
-		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
-				hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
+    case SR_CONF_DEVICE_OPTIONS:
+//		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
+//				hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
+		*data = g_variant_new_from_data(G_VARIANT_TYPE("ai"),
+                hwcaps, ARRAY_SIZE(hwcaps)*sizeof(int32_t), TRUE, NULL, NULL);
 		break;
-	case SR_CONF_SAMPLERATE:
+    case SR_CONF_DEVICE_CONFIGS:
+//		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
+//				hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
+        *data = g_variant_new_from_data(G_VARIANT_TYPE("ai"),
+                hwoptions, ARRAY_SIZE(hwoptions)*sizeof(int32_t), TRUE, NULL, NULL);
+        break;
+    case SR_CONF_SAMPLERATE:
 		g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
-		gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
-				ARRAY_SIZE(samplerates), sizeof(uint64_t));
-		g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
+//		gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
+//				ARRAY_SIZE(samplerates), sizeof(uint64_t));
+		gvar = g_variant_new_from_data(G_VARIANT_TYPE("at"),
+				samplerates, ARRAY_SIZE(samplerates)*sizeof(uint64_t), TRUE, NULL, NULL);
+        g_variant_builder_add(&gvb, "{sv}", "samplerates", gvar);
 		*data = g_variant_builder_end(&gvb);
 		break;
-	case SR_CONF_PATTERN_MODE:
+    case SR_CONF_DEVICE_MODE:
+        *data = g_variant_new_strv(mode_strings, ARRAY_SIZE(mode_strings));
+        break;
+    case SR_CONF_PATTERN_MODE:
 		*data = g_variant_new_strv(pattern_strings, ARRAY_SIZE(pattern_strings));
 		break;
 	default:
-		return SR_ERR_NA;
+        return SR_ERR_NA;
 	}
 
-	return SR_OK;
+    return SR_OK;
 }
 
-static void samples_generator(uint8_t *buf, uint64_t size,
+static void samples_generator(uint16_t *buf, uint64_t size,
 			      struct dev_context *devc)
 {
-	static uint64_t p = 0;
+    static uint16_t p = 0;
 	uint64_t i;
-
-	/* TODO: Needed? */
-	memset(buf, 0, size);
+    uint16_t demo_data;
 
 	switch (devc->sample_generator) {
-	case PATTERN_SIGROK: /* sigrok pattern */
-		for (i = 0; i < size; i++) {
-			*(buf + i) = ~(pattern_sigrok[
-				p++ % sizeof(pattern_sigrok)] >> 1);
-		}
+    case PATTERN_SINE: /* Sine */
+        for (i = 0; i < size; i++) {
+            if (i%CONST_LEN == 0) {
+                demo_data = 0x8000 * sin(2 * PI * p / 0xffff) + 0x8000;
+                p += CONST_LEN;
+            }
+            *(buf + i) = demo_data;
+        }
 		break;
+    case PATTERN_SQUARE:
+        for (i = 0; i < size; i++) {
+            if (i%CONST_LEN == 0) {
+                demo_data = p > 0x7fff ? 0xf000 : 0x1000;
+                p += CONST_LEN;
+            }
+            *(buf + i) = demo_data;
+        }
+        break;
+    case PATTERN_TRIANGLE:
+        for (i = 0; i < size; i++) {
+            if (i%CONST_LEN == 0) {
+                demo_data = p > 0x7fff ? 0xffff * (2.0f * (0x10000 - p) / 0x10000) :
+                                         0xffff * (2.0f * p / 0x10000);
+                p += CONST_LEN;
+            }
+            *(buf + i) = demo_data;
+        }
+        break;
+    case PATTERN_SAWTOOTH:
+        for (i = 0; i < size; i++) {
+            if (i%CONST_LEN == 0) {
+                demo_data = p;
+                p += CONST_LEN;
+            }
+            *(buf + i) = demo_data;
+        }
+        break;
 	case PATTERN_RANDOM: /* Random */
-		for (i = 0; i < size; i++)
-			*(buf + i) = (uint8_t)(rand() & 0xff);
-		break;
-	case PATTERN_INC: /* Simple increment */
-		for (i = 0; i < size; i++)
-			*(buf + i) = p++;
-		break;
-	case PATTERN_ALL_LOW: /* All probes are low */
-		memset(buf, 0x00, size);
-		break;
-	case PATTERN_ALL_HIGH: /* All probes are high */
-		memset(buf, 0xff, size);
+        for (i = 0; i < size; i++) {
+            if (i%CONST_LEN == 0)
+                demo_data = (uint16_t)(rand() * (0x10000 * 1.0f / RAND_MAX));
+            *(buf + i) = demo_data;
+        }
 		break;
 	default:
-		sr_err("Unknown pattern: %d.", devc->sample_generator);
+        sr_err("Unknown pattern: %d.", devc->sample_generator);
 		break;
 	}
 }
 
 /* Callback handling data */
-static int receive_data(int fd, int revents, void *cb_data)
+static int receive_data(int fd, int revents, const struct sr_dev_inst *sdi)
 {
-	struct dev_context *devc = cb_data;
-	struct sr_datafeed_packet packet;
-	struct sr_datafeed_logic logic;
-	uint8_t buf[BUFSIZE];
+    struct dev_context *devc = sdi->priv;
+    struct sr_datafeed_packet packet;
+    struct sr_datafeed_logic logic;
+    struct sr_datafeed_analog analog;
+    //uint16_t buf[BUFSIZE];
+    uint16_t *buf;
 	static uint64_t samples_to_send, expected_samplenum, sending_now;
 	int64_t time, elapsed;
+    static uint16_t last_sample = 0;
+    uint16_t cur_sample;
+    int i;
 
 	(void)fd;
 	(void)revents;
 
+    if (!(buf = g_try_malloc(BUFSIZE*sizeof(uint16_t)))) {
+        sr_err("buf for receive_data malloc failed.");
+        return FALSE;
+    }
+
 	/* How many "virtual" samples should we have collected by now? */
 	time = g_get_monotonic_time();
 	elapsed = time - devc->starttime;
+    devc->starttime = time;
 	expected_samplenum = elapsed * devc->cur_samplerate / 1000000;
 	/* Of those, how many do we still have to send? */
-	samples_to_send = expected_samplenum - devc->samples_counter;
+    //samples_to_send = (expected_samplenum - devc->samples_counter) / CONST_LEN * CONST_LEN;
+    samples_to_send = expected_samplenum / CONST_LEN * CONST_LEN;
 
-	if (devc->limit_samples) {
-		samples_to_send = MIN(samples_to_send,
-				 devc->limit_samples - devc->samples_counter);
-	}
+    if (devc->limit_samples) {
+        if (sdi->mode == LOGIC)
+            samples_to_send = MIN(samples_to_send,
+                     devc->limit_samples - devc->samples_counter);
+        else if (sdi->mode == ANALOG)
+            samples_to_send = MIN(samples_to_send,
+                     devc->limit_samples);
+    }
 
-	while (samples_to_send > 0) {
-		sending_now = MIN(samples_to_send, sizeof(buf));
-		samples_to_send -= sending_now;
+    while (samples_to_send > 0) {
+        sending_now = MIN(samples_to_send, BUFSIZE);
 		samples_generator(buf, sending_now, devc);
 
-		packet.type = SR_DF_LOGIC;
-		packet.payload = &logic;
-		logic.length = sending_now;
-		logic.unitsize = 1;
-		logic.data = buf;
-		sr_session_send(devc->cb_data, &packet);
-		devc->samples_counter += sending_now;
+        if (devc->trigger_stage != 0) {
+            for (i = 0; i < sending_now; i++) {
+                if (devc->trigger_edge == 0) {
+                    if ((*(buf + i) | devc->trigger_mask) ==
+                            (devc->trigger_value | devc->trigger_mask)) {
+                        devc->trigger_stage = 0;
+                        break;
+                    }
+                } else {
+                    cur_sample = *(buf + i);
+                    if (((last_sample & devc->trigger_edge) ==
+                         (~devc->trigger_value & devc->trigger_edge)) &&
+                        ((cur_sample | devc->trigger_mask) ==
+                         (devc->trigger_value | devc->trigger_mask)) &&
+                        ((cur_sample & devc->trigger_edge) ==
+                         (devc->trigger_value & devc->trigger_edge))) {
+                        devc->trigger_stage = 0;
+                        break;
+                    }
+                    last_sample = cur_sample;
+                }
+            }
+            if (devc->trigger_stage == 0) {
+                struct ds_trigger_pos demo_trigger_pos;
+                demo_trigger_pos.real_pos = i;
+                packet.type = SR_DF_TRIGGER;
+                packet.payload = &demo_trigger_pos;
+                sr_session_send(sdi, &packet);
+            }
+        }
+
+        if (devc->trigger_stage == 0){
+            samples_to_send -= sending_now;
+            if (sdi->mode == LOGIC) {
+                packet.type = SR_DF_LOGIC;
+                packet.payload = &logic;
+                logic.length = sending_now * (NUM_PROBES >> 3);
+                logic.unitsize = (NUM_PROBES >> 3);
+                logic.data = buf;
+            } else if (sdi->mode == ANALOG) {
+                packet.type = SR_DF_ANALOG;
+                packet.payload = &analog;
+                analog.probes = sdi->probes;
+                analog.num_samples = sending_now;
+                analog.mq = SR_MQ_VOLTAGE;
+                analog.unit = SR_UNIT_VOLT;
+                analog.mqflags = SR_MQFLAG_AC;
+                analog.data = buf;
+            }
+
+            sr_session_send(sdi, &packet);
+            if (sdi->mode == LOGIC)
+                devc->samples_counter += sending_now;
+            else if (sdi->mode == ANALOG)
+                devc->samples_counter = (devc->samples_counter + sending_now) % devc->limit_samples;
+        } else {
+            break;
+        }
 	}
 
-	if (devc->limit_samples &&
-		devc->samples_counter >= devc->limit_samples) {
-		sr_info("Requested number of samples reached.");
-		hw_dev_acquisition_stop(devc->sdi, cb_data);
-		return TRUE;
-	}
+    if (sdi->mode == LOGIC &&
+        devc->limit_samples &&
+        devc->samples_counter >= devc->limit_samples) {
+        sr_info("Requested number of samples reached.");
+        hw_dev_acquisition_stop(sdi, NULL);
+        g_free(buf);
+        return TRUE;
+    }
+
+    g_free(buf);
 
 	return TRUE;
 }
@@ -463,11 +594,29 @@
 {
 	struct dev_context *const devc = sdi->priv;
 
-	if (sdi->status != SR_ST_ACTIVE)
-		return SR_ERR_DEV_CLOSED;
+    (void)cb_data;
 
-	devc->cb_data = cb_data;
+    if (sdi->status != SR_ST_ACTIVE)
+        return SR_ERR_DEV_CLOSED;
+
+    //devc->cb_data = cb_data;
 	devc->samples_counter = 0;
+    devc->stop = FALSE;
+
+    /*
+     * trigger setting
+     */
+    if (!trigger->trigger_en || sdi->mode == ANALOG) {
+        devc->trigger_stage = 0;
+    } else {
+        devc->trigger_mask = ds_trigger_get_mask0(TriggerStages);
+        devc->trigger_value = ds_trigger_get_value0(TriggerStages);
+        devc->trigger_edge = ds_trigger_get_edge0(TriggerStages);
+        if (devc->trigger_edge != 0)
+            devc->trigger_stage = 2;
+        else
+            devc->trigger_stage = 1;
+    }
 
 	/*
 	 * Setting two channels connected by a pipe is a remnant from when the
@@ -492,11 +641,12 @@
 	/* Make channels to unbuffered. */
 	g_io_channel_set_buffered(devc->channel, FALSE);
 
-	sr_session_source_add_channel(devc->channel, G_IO_IN | G_IO_ERR,
-		    40, receive_data, devc);
+    sr_session_source_add_channel(devc->channel, G_IO_IN | G_IO_ERR,
+            100, receive_data, sdi);
 
 	/* Send header packet to the session bus. */
-	std_session_send_df_header(cb_data, LOG_PREFIX);
+    //std_session_send_df_header(cb_data, LOG_PREFIX);
+    std_session_send_df_header(sdi, LOG_PREFIX);
 
 	/* We use this timestamp to decide how many more samples to send. */
 	devc->starttime = g_get_monotonic_time();
@@ -513,18 +663,27 @@
 
 	sr_dbg("Stopping aquisition.");
 
-	sr_session_source_remove_channel(devc->channel);
+    devc->stop = TRUE;
+    sr_session_source_remove_channel(devc->channel);
 	g_io_channel_shutdown(devc->channel, FALSE, NULL);
 	g_io_channel_unref(devc->channel);
 	devc->channel = NULL;
 
 	/* Send last packet. */
-	packet.type = SR_DF_END;
-	sr_session_send(devc->cb_data, &packet);
+    packet.type = SR_DF_END;
+    sr_session_send(sdi, &packet);
 
 	return SR_OK;
 }
 
+static int hw_dev_test(struct sr_dev_inst *sdi)
+{
+    if (sdi)
+        return SR_OK;
+    else
+        return SR_ERR;
+}
+
 SR_PRIV struct sr_dev_driver demo_driver_info = {
 	.name = "demo",
 	.longname = "Demo driver and pattern generator",
@@ -539,6 +698,7 @@
 	.config_list = config_list,
 	.dev_open = hw_dev_open,
 	.dev_close = hw_dev_close,
+    .dev_test = hw_dev_test,
 	.dev_acquisition_start = hw_dev_acquisition_start,
 	.dev_acquisition_stop = hw_dev_acquisition_stop,
 	.priv = NULL,
diff --git a/hwdriver.c b/hwdriver.c
index d4ae560..d362f13 100644
--- a/hwdriver.c
+++ b/hwdriver.c
@@ -57,11 +57,15 @@
 		"Serial communication", NULL},
 	{SR_CONF_SAMPLERATE, SR_T_UINT64, "samplerate",
 		"Sample rate", NULL},
-	{SR_CONF_CAPTURE_RATIO, SR_T_UINT64, "captureratio",
+    {SR_CONF_CLOCK_TYPE, SR_T_BOOL, "clocktype",
+        "Using External Clock", NULL},
+    {SR_CONF_CAPTURE_RATIO, SR_T_UINT64, "captureratio",
 		"Pre-trigger capture ratio", NULL},
-	{SR_CONF_PATTERN_MODE, SR_T_CHAR, "pattern",
-		"Pattern generator mode", NULL},
-	{SR_CONF_TRIGGER_TYPE, SR_T_CHAR, "triggertype",
+    {SR_CONF_DEVICE_MODE, SR_T_CHAR, "device",
+        "Device Mode", NULL},
+    {SR_CONF_PATTERN_MODE, SR_T_CHAR, "pattern",
+        "Pattern mode", NULL},
+    {SR_CONF_TRIGGER_TYPE, SR_T_CHAR, "triggertype",
 		"Trigger types", NULL},
 	{SR_CONF_RLE, SR_T_BOOL, "rle",
 		"Run Length Encoding", NULL},
@@ -87,180 +91,20 @@
 };
 
 /** @cond PRIVATE */
-#ifdef HAVE_HW_BRYMEN_DMM
-extern SR_PRIV struct sr_dev_driver brymen_bm857_driver_info;
-#endif
-#ifdef HAVE_HW_COLEAD_SLM
-extern SR_PRIV struct sr_dev_driver colead_slm_driver_info;
-#endif
 #ifdef HAVE_LA_DEMO
 extern SR_PRIV struct sr_dev_driver demo_driver_info;
 #endif
-#ifdef HAVE_HW_LASCAR_EL_USB
-extern SR_PRIV struct sr_dev_driver lascar_el_usb_driver_info;
-#endif
-#ifdef HAVE_HW_MIC_985XX
-extern SR_PRIV struct sr_dev_driver mic_98581_driver_info;
-extern SR_PRIV struct sr_dev_driver mic_98583_driver_info;
-#endif
-#ifdef HAVE_HW_NEXUS_OSCIPRIME
-extern SR_PRIV struct sr_dev_driver nexus_osciprime_driver_info;
-#endif
-#ifdef HAVE_LA_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;
-#endif
-#ifdef HAVE_HW_TONDAJ_SL_814
-extern SR_PRIV struct sr_dev_driver tondaj_sl_814_driver_info;
-#endif
-#ifdef HAVE_HW_VICTOR_DMM
-extern SR_PRIV struct sr_dev_driver victor_dmm_driver_info;
-#endif
-#ifdef HAVE_LA_ZEROPLUS_LOGIC_CUBE
-extern SR_PRIV struct sr_dev_driver zeroplus_logic_cube_driver_info;
-#endif
-#ifdef HAVE_LA_ASIX_SIGMA
-extern SR_PRIV struct sr_dev_driver asix_sigma_driver_info;
-#endif
-#ifdef HAVE_LA_CHRONOVU_LA8
-extern SR_PRIV struct sr_dev_driver chronovu_la8_driver_info;
-#endif
-#ifdef HAVE_LA_LINK_MSO19
-extern SR_PRIV struct sr_dev_driver link_mso19_driver_info;
-#endif
-#ifdef HAVE_HW_ALSA
-extern SR_PRIV struct sr_dev_driver alsa_driver_info;
-#endif
-#ifdef HAVE_LA_FX2LAFW
-extern SR_PRIV struct sr_dev_driver fx2lafw_driver_info;
-#endif
-#ifdef HAVE_HW_HANTEK_DSO
-extern SR_PRIV struct sr_dev_driver hantek_dso_driver_info;
-#endif
-#ifdef HAVE_HW_AGILENT_DMM
-extern SR_PRIV struct sr_dev_driver agdmm_driver_info;
-#endif
-#ifdef HAVE_HW_FLUKE_DMM
-extern SR_PRIV struct sr_dev_driver flukedmm_driver_info;
-#endif
-#ifdef HAVE_HW_SERIAL_DMM
-extern SR_PRIV struct sr_dev_driver digitek_dt4000zc_driver_info;
-extern SR_PRIV struct sr_dev_driver tekpower_tp4000zc_driver_info;
-extern SR_PRIV struct sr_dev_driver metex_me31_driver_info;
-extern SR_PRIV struct sr_dev_driver peaktech_3410_driver_info;
-extern SR_PRIV struct sr_dev_driver mastech_mas345_driver_info;
-extern SR_PRIV struct sr_dev_driver va_va18b_driver_info;
-extern SR_PRIV struct sr_dev_driver metex_m3640d_driver_info;
-extern SR_PRIV struct sr_dev_driver peaktech_4370_driver_info;
-extern SR_PRIV struct sr_dev_driver pce_pce_dm32_driver_info;
-extern SR_PRIV struct sr_dev_driver radioshack_22_168_driver_info;
-extern SR_PRIV struct sr_dev_driver radioshack_22_805_driver_info;
-extern SR_PRIV struct sr_dev_driver radioshack_22_812_driver_info;
-extern SR_PRIV struct sr_dev_driver tecpel_dmm_8060_ser_driver_info;
-extern SR_PRIV struct sr_dev_driver tecpel_dmm_8061_ser_driver_info;
-extern SR_PRIV struct sr_dev_driver voltcraft_vc820_ser_driver_info;
-extern SR_PRIV struct sr_dev_driver voltcraft_vc840_ser_driver_info;
-extern SR_PRIV struct sr_dev_driver uni_t_ut61d_ser_driver_info;
-extern SR_PRIV struct sr_dev_driver uni_t_ut61e_ser_driver_info;
-#endif
-#ifdef HAVE_HW_UNI_T_DMM
-extern SR_PRIV struct sr_dev_driver tecpel_dmm_8060_driver_info;
-extern SR_PRIV struct sr_dev_driver tecpel_dmm_8061_driver_info;
-extern SR_PRIV struct sr_dev_driver uni_t_ut61d_driver_info;
-extern SR_PRIV struct sr_dev_driver uni_t_ut61e_driver_info;
-extern SR_PRIV struct sr_dev_driver voltcraft_vc820_driver_info;
-extern SR_PRIV struct sr_dev_driver voltcraft_vc840_driver_info;
+#ifdef HAVE_LA_DSLOGIC
+extern SR_PRIV struct sr_dev_driver DSLogic_driver_info;
 #endif
 /** @endcond */
 
 static struct sr_dev_driver *drivers_list[] = {
-#ifdef HAVE_HW_BRYMEN_DMM
-	&brymen_bm857_driver_info,
-#endif
-#ifdef HAVE_HW_COLEAD_SLM
-	&colead_slm_driver_info,
-#endif
 #ifdef HAVE_LA_DEMO
 	&demo_driver_info,
 #endif
-#ifdef HAVE_HW_LASCAR_EL_USB
-	&lascar_el_usb_driver_info,
-#endif
-#ifdef HAVE_HW_MIC_985XX
-	&mic_98581_driver_info,
-	&mic_98583_driver_info,
-#endif
-#ifdef HAVE_HW_NEXUS_OSCIPRIME
-	&nexus_osciprime_driver_info,
-#endif
-#ifdef HAVE_LA_OLS
-	&ols_driver_info,
-#endif
-#ifdef HAVE_HW_RIGOL_DS1XX2
-	&rigol_ds1xx2_driver_info,
-#endif
-#ifdef HAVE_HW_TONDAJ_SL_814
-	&tondaj_sl_814_driver_info,
-#endif
-#ifdef HAVE_HW_VICTOR_DMM
-	&victor_dmm_driver_info,
-#endif
-#ifdef HAVE_LA_ZEROPLUS_LOGIC_CUBE
-	&zeroplus_logic_cube_driver_info,
-#endif
-#ifdef HAVE_LA_ASIX_SIGMA
-	&asix_sigma_driver_info,
-#endif
-#ifdef HAVE_LA_CHRONOVU_LA8
-	&chronovu_la8_driver_info,
-#endif
-#ifdef HAVE_LA_LINK_MSO19
-	&link_mso19_driver_info,
-#endif
-#ifdef HAVE_HW_ALSA
-	&alsa_driver_info,
-#endif
-#ifdef HAVE_LA_FX2LAFW
-	&fx2lafw_driver_info,
-#endif
-#ifdef HAVE_HW_HANTEK_DSO
-	&hantek_dso_driver_info,
-#endif
-#ifdef HAVE_HW_AGILENT_DMM
-	&agdmm_driver_info,
-#endif
-#ifdef HAVE_HW_FLUKE_DMM
-	&flukedmm_driver_info,
-#endif
-#ifdef HAVE_HW_SERIAL_DMM
-	&digitek_dt4000zc_driver_info,
-	&tekpower_tp4000zc_driver_info,
-	&metex_me31_driver_info,
-	&peaktech_3410_driver_info,
-	&mastech_mas345_driver_info,
-	&va_va18b_driver_info,
-	&metex_m3640d_driver_info,
-	&peaktech_4370_driver_info,
-	&pce_pce_dm32_driver_info,
-	&radioshack_22_168_driver_info,
-	&radioshack_22_805_driver_info,
-	&radioshack_22_812_driver_info,
-	&tecpel_dmm_8060_ser_driver_info,
-	&tecpel_dmm_8061_ser_driver_info,
-	&voltcraft_vc820_ser_driver_info,
-	&voltcraft_vc840_ser_driver_info,
-	&uni_t_ut61d_ser_driver_info,
-	&uni_t_ut61e_ser_driver_info,
-#endif
-#ifdef HAVE_HW_UNI_T_DMM
-	&tecpel_dmm_8060_driver_info,
-	&tecpel_dmm_8061_driver_info,
-	&uni_t_ut61d_driver_info,
-	&uni_t_ut61e_driver_info,
-	&voltcraft_vc820_driver_info,
-	&voltcraft_vc840_driver_info,
+#ifdef HAVE_LA_DSLOGIC
+    &DSLogic_driver_info,
 #endif
 	NULL,
 };
@@ -553,7 +397,7 @@
 SR_PRIV int sr_source_add(int fd, int events, int timeout,
 			  sr_receive_data_callback_t cb, void *cb_data)
 {
-	return sr_session_source_add(fd, events, timeout, cb, cb_data);
+    return sr_session_source_add(fd, events, timeout, cb, cb_data);
 }
 
 /** @} */
diff --git a/input/Makefile.am b/input/Makefile.am
index e0fa66e..f878db3 100644
--- a/input/Makefile.am
+++ b/input/Makefile.am
@@ -19,15 +19,14 @@
 ##
 
 # Local lib, this is NOT meant to be installed!
-noinst_LTLIBRARIES = libsigrokinput.la
+noinst_LTLIBRARIES = libsigrok4DSLogicinput.la
 
-libsigrokinput_la_SOURCES = \
-	binary.c \
-	chronovu_la8.c \
-	input.c \
-	vcd.c \
-	wav.c
+libsigrok4DSLogicinput_la_SOURCES = \
+        in_binary.c \
+        in_vcd.c \
+        in_wav.c \
+	input.c 
 
-libsigrokinput_la_CFLAGS = \
+libsigrok4DSLogicinput_la_CFLAGS = \
 	-I$(top_srcdir)
 
diff --git a/input/in_binary.c b/input/in_binary.c
new file mode 100644
index 0000000..2d52c30
--- /dev/null
+++ b/input/in_binary.c
@@ -0,0 +1,158 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include "libsigrok.h"
+#include "libsigrok-internal.h"
+
+/* Message logging helpers with subsystem-specific prefix string. */
+#define LOG_PREFIX "input/binary: "
+#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 CHUNKSIZE             (512 * 1024)
+#define DEFAULT_NUM_PROBES    8
+
+struct context {
+	uint64_t samplerate;
+};
+
+static int format_match(const char *filename)
+{
+	(void)filename;
+
+	/* This module will handle anything you throw at it. */
+	return TRUE;
+}
+
+static int init(struct sr_input *in, const char *filename)
+{
+	struct sr_probe *probe;
+	int num_probes, i;
+	char name[SR_MAX_PROBENAME_LEN + 1];
+	char *param;
+	struct context *ctx;
+
+	(void)filename;
+
+	if (!(ctx = g_try_malloc0(sizeof(*ctx)))) {
+		sr_err("Input format context malloc failed.");
+		return SR_ERR_MALLOC;
+	}
+
+	num_probes = DEFAULT_NUM_PROBES;
+	ctx->samplerate = 0;
+
+	if (in->param) {
+		param = g_hash_table_lookup(in->param, "numprobes");
+		if (param) {
+			num_probes = strtoul(param, NULL, 10);
+			if (num_probes < 1)
+				return SR_ERR;
+		}
+
+		param = g_hash_table_lookup(in->param, "samplerate");
+		if (param) {
+			if (sr_parse_sizestring(param, &ctx->samplerate) != SR_OK)
+				return SR_ERR;
+		}
+	}
+
+	/* Create a virtual device. */
+	in->sdi = sr_dev_inst_new(LOGIC, 0, SR_ST_ACTIVE, NULL, NULL, NULL);
+	in->internal = ctx;
+
+	for (i = 0; i < num_probes; i++) {
+		snprintf(name, SR_MAX_PROBENAME_LEN, "%d", i);
+		/* TODO: Check return value. */
+		if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, name)))
+			return SR_ERR;
+		in->sdi->probes = g_slist_append(in->sdi->probes, probe);
+	}
+
+	return SR_OK;
+}
+
+static int loadfile(struct sr_input *in, const char *filename)
+{
+	struct sr_datafeed_packet packet;
+	struct sr_datafeed_meta meta;
+	struct sr_datafeed_logic logic;
+	struct sr_config *src;
+	unsigned char buffer[CHUNKSIZE];
+	int fd, size, num_probes;
+	struct context *ctx;
+
+	ctx = in->internal;
+
+	if ((fd = open(filename, O_RDONLY)) == -1)
+		return SR_ERR;
+
+	num_probes = g_slist_length(in->sdi->probes);
+
+	/* Send header packet to the session bus. */
+	std_session_send_df_header(in->sdi, LOG_PREFIX);
+
+	if (ctx->samplerate) {
+		packet.type = SR_DF_META;
+		packet.payload = &meta;
+		src = sr_config_new(SR_CONF_SAMPLERATE,
+				g_variant_new_uint64(ctx->samplerate));
+		meta.config = g_slist_append(NULL, src);
+		sr_session_send(in->sdi, &packet);
+		sr_config_free(src);
+	}
+
+	/* Chop up the input file into chunks & send it to the session bus. */
+	packet.type = SR_DF_LOGIC;
+	packet.payload = &logic;
+	logic.unitsize = (num_probes + 7) / 8;
+	logic.data = buffer;
+	while ((size = read(fd, buffer, CHUNKSIZE)) > 0) {
+		logic.length = size;
+		sr_session_send(in->sdi, &packet);
+	}
+	close(fd);
+
+	/* Send end packet to the session bus. */
+	packet.type = SR_DF_END;
+	sr_session_send(in->sdi, &packet);
+
+	g_free(ctx);
+	in->internal = NULL;
+
+	return SR_OK;
+}
+
+SR_PRIV struct sr_input_format input_binary = {
+	.id = "binary",
+	.description = "Raw binary",
+	.format_match = format_match,
+	.init = init,
+	.loadfile = loadfile,
+};
diff --git a/input/in_vcd.c b/input/in_vcd.c
new file mode 100644
index 0000000..a143b1c
--- /dev/null
+++ b/input/in_vcd.c
@@ -0,0 +1,609 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2012 Petteri Aimonen <jpa@sr.mail.kapsi.fi>
+ *
+ * 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/>.
+ */
+
+/* The VCD input module has the following options:
+ *
+ * numprobes:   Maximum number of probes to use. The probes are
+ *              detected in the same order as they are listed
+ *              in the $var sections of the VCD file.
+ *
+ * skip:        Allows skipping until given timestamp in the file.
+ *              This can speed up analyzing of long captures.
+ *            
+ *              Value < 0: Skip until first timestamp listed in
+ *              the file. (default)
+ *
+ *              Value = 0: Do not skip, instead generate samples
+ *              beginning from timestamp 0.
+ *
+ *              Value > 0: Start at the given timestamp.
+ *
+ * downsample:  Divide the samplerate by the given factor.
+ *              This can speed up analyzing of long captures.
+ *
+ * compress:    Compress idle periods longer than this value.
+ *              This can speed up analyzing of long captures.
+ *              Default 0 = don't compress.
+ *
+ * Based on Verilog standard IEEE Std 1364-2001 Version C
+ *
+ * Supported features:
+ * - $var with 'wire' and 'reg' types of scalar variables
+ * - $timescale definition for samplerate
+ * - multiple character variable identifiers
+ *
+ * Most important unsupported features:
+ * - vector variables (bit vectors etc.)
+ * - analog, integer and real number variables
+ * - $dumpvars initial value declaration
+ * - $scope namespaces
+ */
+
+/*  */
+
+#include <stdlib.h>
+#include <glib.h>
+#include <stdio.h>
+#include <string.h>
+#include "libsigrok.h"
+#include "libsigrok-internal.h"
+
+/* Message logging helpers with subsystem-specific prefix string. */
+#define LOG_PREFIX "input/vcd: "
+#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 DEFAULT_NUM_PROBES 8
+
+/* Read until specific type of character occurs in file.
+ * Skip input if dest is NULL.
+ * Modes:
+ * 'W' read until whitespace
+ * 'N' read until non-whitespace, and ungetc() the character
+ * '$' read until $end
+ */
+static gboolean read_until(FILE *file, GString *dest, char mode)
+{
+	char prev[4] = "";
+	long startpos = ftell(file);
+	for(;;)
+	{
+		int c = fgetc(file);
+
+		if (c == EOF)
+		{
+			if (mode == '$')
+				sr_err("Unexpected EOF, read started at %ld.", startpos);
+			return FALSE;
+		}
+		
+		if (mode == 'W' && g_ascii_isspace(c))
+			return TRUE;
+		
+		if (mode == 'N' && !g_ascii_isspace(c))
+		{
+			ungetc(c, file);
+			return TRUE;
+		}
+		
+		if (mode == '$')
+		{
+			prev[0] = prev[1]; prev[1] = prev[2]; prev[2] = prev[3]; prev[3] = c;
+			if (prev[0] == '$' && prev[1] == 'e' && prev[2] == 'n' && prev[3] == 'd')
+			{
+				if (dest != NULL)
+					g_string_truncate(dest, dest->len - 3);
+					
+				return TRUE;
+			}
+		}
+
+		if (dest != NULL)
+			g_string_append_c(dest, c);
+	}
+}
+
+/* Reads a single VCD section from input file and parses it to structure.
+ * e.g. $timescale 1ps $end  => "timescale" "1ps"
+ */
+static gboolean parse_section(FILE *file, gchar **name, gchar **contents)
+{
+	gboolean status;
+	GString *sname, *scontents;
+	
+	/* Skip any initial white-space */
+	if (!read_until(file, NULL, 'N')) return FALSE;
+	
+	/* Section tag should start with $. */
+	if (fgetc(file) != '$')
+	{
+		sr_err("Expected $ at beginning of section.");
+		return FALSE;
+	}
+	
+	/* Read the section tag */	
+	sname = g_string_sized_new(32);
+	status = read_until(file, sname, 'W');
+	
+	/* Skip whitespace before content */
+	status = status && read_until(file, NULL, 'N');
+	
+	/* Read the content */
+	scontents = g_string_sized_new(128);
+	status = status && read_until(file, scontents, '$');
+	g_strchomp(scontents->str);
+
+	/* Release strings if status is FALSE, return them if status is TRUE */	
+	*name = g_string_free(sname, !status);
+	*contents = g_string_free(scontents, !status);
+	return status;
+}
+
+struct probe
+{
+	gchar *name;
+	gchar *identifier;
+};
+
+struct context
+{
+	uint64_t samplerate;
+	int maxprobes;
+	int probecount;
+	int downsample;
+	unsigned compress;
+	int64_t skip;
+	GSList *probes;
+};
+
+static void free_probe(void *data)
+{
+	struct probe *probe = data;
+	g_free(probe->name);
+	g_free(probe->identifier);
+	g_free(probe);
+}
+
+static void release_context(struct context *ctx)
+{
+	g_slist_free_full(ctx->probes, free_probe);
+	g_free(ctx);
+}
+
+/* Remove empty parts from an array returned by g_strsplit. */
+static void remove_empty_parts(gchar **parts)
+{
+	gchar **src = parts;
+	gchar **dest = parts;
+	while (*src != NULL)
+	{
+		if (**src != '\0')
+		{
+			*dest++ = *src;
+		}
+		
+		src++;
+	}
+	
+	*dest = NULL;
+}
+
+/* Parse VCD header to get values for context structure.
+ * The context structure should be zeroed before calling this.
+ */
+static gboolean parse_header(FILE *file, struct context *ctx)
+{
+	uint64_t p, q;
+	gchar *name = NULL, *contents = NULL;
+	gboolean status = FALSE;
+	struct probe *probe;
+
+	while (parse_section(file, &name, &contents))
+	{
+		sr_dbg("Section '%s', contents '%s'.", name, contents);
+	
+		if (g_strcmp0(name, "enddefinitions") == 0)
+		{
+			status = TRUE;
+			break;
+		}
+		else if (g_strcmp0(name, "timescale") == 0)
+		{
+			/* The standard allows for values 1, 10 or 100
+			 * and units s, ms, us, ns, ps and fs. */
+			if (sr_parse_period(contents, &p, &q) == SR_OK)
+			{
+				ctx->samplerate = q / p;
+				if (q % p != 0)
+				{
+					/* Does not happen unless time value is non-standard */
+					sr_warn("Inexact rounding of samplerate, %" PRIu64 " / %" PRIu64 " to %" PRIu64 " Hz.",
+						q, p, ctx->samplerate);
+				}
+				
+				sr_dbg("Samplerate: %" PRIu64, ctx->samplerate);
+			}
+			else
+			{
+				sr_err("Parsing timescale failed.");
+			}
+		}
+		else if (g_strcmp0(name, "var") == 0)
+		{
+			/* Format: $var type size identifier reference $end */
+			gchar **parts = g_strsplit_set(contents, " \r\n\t", 0);
+			remove_empty_parts(parts);
+			
+			if (g_strv_length(parts) != 4)
+			{
+				sr_warn("$var section should have 4 items");
+			}
+			else if (g_strcmp0(parts[0], "reg") != 0 && g_strcmp0(parts[0], "wire") != 0)
+			{
+				sr_info("Unsupported signal type: '%s'", parts[0]);
+			}
+			else if (strtol(parts[1], NULL, 10) != 1)
+			{
+				sr_info("Unsupported signal size: '%s'", parts[1]);
+			}
+			else if (ctx->probecount >= ctx->maxprobes)
+			{
+				sr_warn("Skipping '%s' because only %d probes requested.", parts[3], ctx->maxprobes);
+			}
+			else
+			{
+				sr_info("Probe %d is '%s' identified by '%s'.", ctx->probecount, parts[3], parts[2]);
+				probe = g_malloc(sizeof(struct probe));
+				probe->identifier = g_strdup(parts[2]);
+				probe->name = g_strdup(parts[3]);
+				ctx->probes = g_slist_append(ctx->probes, probe);
+				ctx->probecount++;
+			}
+			
+			g_strfreev(parts);
+		}
+		
+		g_free(name); name = NULL;
+		g_free(contents); contents = NULL;
+	}
+	
+	g_free(name);
+	g_free(contents);
+	
+	return status;
+}
+
+static int format_match(const char *filename)
+{
+	FILE *file;
+	gchar *name = NULL, *contents = NULL;
+	gboolean status;
+	
+	file = fopen(filename, "r");
+	if (file == NULL)
+		return FALSE;
+
+	/* If we can parse the first section correctly,
+	 * then it is assumed to be a VCD file.
+	 */
+	status = parse_section(file, &name, &contents);
+	status = status && (*name != '\0');
+	
+	g_free(name);
+	g_free(contents);
+	fclose(file);
+	
+	return status;
+}
+
+static int init(struct sr_input *in, const char *filename)
+{
+	struct sr_probe *probe;
+	int num_probes, i;
+	char name[SR_MAX_PROBENAME_LEN + 1];
+	char *param;
+	struct context *ctx;
+
+	(void)filename;
+
+	if (!(ctx = g_try_malloc0(sizeof(*ctx)))) {
+		sr_err("Input format context malloc failed.");
+		return SR_ERR_MALLOC;
+	}
+
+	num_probes = DEFAULT_NUM_PROBES;
+	ctx->samplerate = 0;
+	ctx->downsample = 1;
+	ctx->skip = -1;
+
+	if (in->param) {
+		param = g_hash_table_lookup(in->param, "numprobes");
+		if (param) {
+			num_probes = strtoul(param, NULL, 10);
+			if (num_probes < 1)
+			{
+				release_context(ctx);
+				return SR_ERR;
+			}
+		}
+		
+		param = g_hash_table_lookup(in->param, "downsample");
+		if (param) {
+			ctx->downsample = strtoul(param, NULL, 10);
+			if (ctx->downsample < 1)
+			{
+				ctx->downsample = 1;
+			}
+		}
+		
+		param = g_hash_table_lookup(in->param, "compress");
+		if (param) {
+			ctx->compress = strtoul(param, NULL, 10);
+		}
+		
+		param = g_hash_table_lookup(in->param, "skip");
+		if (param) {
+			ctx->skip = strtoul(param, NULL, 10) / ctx->downsample;
+		}
+	}
+	
+	/* Maximum number of probes to parse from the VCD */
+	ctx->maxprobes = num_probes;
+
+	/* Create a virtual device. */
+	in->sdi = sr_dev_inst_new(LOGIC, 0, SR_ST_ACTIVE, NULL, NULL, NULL);
+	in->internal = ctx;
+
+	for (i = 0; i < num_probes; i++) {
+		snprintf(name, SR_MAX_PROBENAME_LEN, "%d", i);
+		
+		if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, name)))
+		{
+			release_context(ctx);
+			return SR_ERR;
+		}
+			
+		in->sdi->probes = g_slist_append(in->sdi->probes, probe);
+	}
+
+	return SR_OK;
+}
+
+#define CHUNKSIZE 1024
+
+/* Send N samples of the given value. */
+static void send_samples(const struct sr_dev_inst *sdi, uint64_t sample, uint64_t count)
+{
+	struct sr_datafeed_packet packet;
+	struct sr_datafeed_logic logic;
+	uint64_t buffer[CHUNKSIZE];
+	uint64_t i;
+	unsigned chunksize = CHUNKSIZE;
+		
+	if (count < chunksize)
+		chunksize = count;
+
+	for (i = 0; i < chunksize; i++)
+	{
+		buffer[i] = sample;
+	}
+	
+	packet.type = SR_DF_LOGIC;
+	packet.payload = &logic;	
+	logic.unitsize = sizeof(uint64_t);
+	logic.data = buffer;
+	
+	while (count)
+	{
+		if (count < chunksize)
+			chunksize = count;
+	
+		logic.length = sizeof(uint64_t) * chunksize;
+	
+		sr_session_send(sdi, &packet);
+		count -= chunksize;
+	}
+}
+
+/* Parse the data section of VCD */
+static void parse_contents(FILE *file, const struct sr_dev_inst *sdi, struct context *ctx)
+{
+	GString *token = g_string_sized_new(32);
+	
+	uint64_t prev_timestamp = 0;
+	uint64_t prev_values = 0;
+	
+	/* Read one space-delimited token at a time. */
+	while (read_until(file, NULL, 'N') && read_until(file, token, 'W'))
+	{
+		if (token->str[0] == '#' && g_ascii_isdigit(token->str[1]))
+		{
+			/* Numeric value beginning with # is a new timestamp value */
+			uint64_t timestamp;
+			timestamp = strtoull(token->str + 1, NULL, 10);
+			
+			if (ctx->downsample > 1)
+				timestamp /= ctx->downsample;
+			
+			/* Skip < 0 => skip until first timestamp.
+			 * Skip = 0 => don't skip
+			 * Skip > 0 => skip until timestamp >= skip.
+			 */
+			if (ctx->skip < 0)
+			{
+				ctx->skip = timestamp;
+				prev_timestamp = timestamp;
+			}
+			else if (ctx->skip > 0 && timestamp < (uint64_t)ctx->skip)
+			{
+				prev_timestamp = ctx->skip;
+			}
+			else if (timestamp == prev_timestamp)
+			{
+				/* Ignore repeated timestamps (e.g. sigrok outputs these) */
+			}
+			else
+			{
+				if (ctx->compress != 0 && timestamp - prev_timestamp > ctx->compress)
+				{
+					/* Compress long idle periods */
+					prev_timestamp = timestamp - ctx->compress;
+				}
+			
+				sr_dbg("New timestamp: %" PRIu64, timestamp);
+			
+				/* Generate samples from prev_timestamp up to timestamp - 1. */
+				send_samples(sdi, prev_values, timestamp - prev_timestamp);
+				prev_timestamp = timestamp;
+			}
+		}
+		else if (token->str[0] == '$' && token->len > 1)
+		{
+			/* This is probably a $dumpvars, $comment or similar.
+			 * $dump* contain useful data, but other tags will be skipped until $end. */
+			if (g_strcmp0(token->str, "$dumpvars") == 0 ||
+			    g_strcmp0(token->str, "$dumpon") == 0 ||
+			    g_strcmp0(token->str, "$dumpoff") == 0 ||
+			    g_strcmp0(token->str, "$end") == 0)
+			{
+				/* Ignore, parse contents as normally. */
+			}
+			else
+			{
+				/* Skip until $end */
+				read_until(file, NULL, '$');
+			}
+		}
+		else if (strchr("bBrR", token->str[0]) != NULL)
+		{
+			/* A vector value. Skip it and also the following identifier. */
+			read_until(file, NULL, 'N');
+			read_until(file, NULL, 'W');
+		}
+		else if (strchr("01xXzZ", token->str[0]) != NULL)
+		{
+			/* A new 1-bit sample value */
+			int i, bit;
+			GSList *l;
+			struct probe *probe;
+
+			bit = (token->str[0] == '1');
+		
+			g_string_erase(token, 0, 1);
+			if (token->len == 0)
+			{
+				/* There was a space between value and identifier.
+				 * Read in the rest.
+				 */
+				read_until(file, NULL, 'N');
+				read_until(file, token, 'W');
+			}
+			
+			for (i = 0, l = ctx->probes; i < ctx->probecount && l; i++, l = l->next)
+			{
+				probe = l->data;
+
+				if (g_strcmp0(token->str, probe->identifier) == 0)
+				{
+					sr_dbg("Probe %d new value %d.", i, bit);
+				
+					/* Found our probe */
+					if (bit)
+						prev_values |= (1 << i);
+					else
+						prev_values &= ~(1 << i);
+					
+					break;
+				}
+			}
+			
+			if (i == ctx->probecount)
+			{
+				sr_dbg("Did not find probe for identifier '%s'.", token->str);
+			}
+		}
+		else
+		{
+			sr_warn("Skipping unknown token '%s'.", token->str);
+		}
+		
+		g_string_truncate(token, 0);
+	}
+	
+	g_string_free(token, TRUE);
+}
+
+static int loadfile(struct sr_input *in, const char *filename)
+{
+	struct sr_datafeed_packet packet;
+	struct sr_datafeed_meta meta;
+	struct sr_config *src;
+	FILE *file;
+	struct context *ctx;
+	uint64_t samplerate;
+
+	ctx = in->internal;
+
+	if ((file = fopen(filename, "r")) == NULL)
+		return SR_ERR;
+
+	if (!parse_header(file, ctx))
+	{
+		sr_err("VCD parsing failed");
+		fclose(file);
+		return SR_ERR;
+	}
+
+	/* Send header packet to the session bus. */
+	std_session_send_df_header(in->sdi, LOG_PREFIX);
+
+	/* Send metadata about the SR_DF_LOGIC packets to come. */
+	packet.type = SR_DF_META;
+	packet.payload = &meta;
+	samplerate = ctx->samplerate / ctx->downsample;
+	src = sr_config_new(SR_CONF_SAMPLERATE, g_variant_new_uint64(samplerate));
+	meta.config = g_slist_append(NULL, src);
+	sr_session_send(in->sdi, &packet);
+	sr_config_free(src);
+
+	/* Parse the contents of the VCD file */
+	parse_contents(file, in->sdi, ctx);
+	
+	/* Send end packet to the session bus. */
+	packet.type = SR_DF_END;
+	sr_session_send(in->sdi, &packet);
+
+	fclose(file);
+	release_context(ctx);
+	in->internal = NULL;
+
+	return SR_OK;
+}
+
+SR_PRIV struct sr_input_format input_vcd = {
+	.id = "vcd",
+	.description = "Value Change Dump",
+	.format_match = format_match,
+	.init = init,
+	.loadfile = loadfile,
+};
diff --git a/input/in_wav.c b/input/in_wav.c
new file mode 100644
index 0000000..773b6b8
--- /dev/null
+++ b/input/in_wav.c
@@ -0,0 +1,211 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include "libsigrok.h"
+#include "libsigrok-internal.h"
+
+/* Message logging helpers with subsystem-specific prefix string. */
+#define LOG_PREFIX "input/wav: "
+#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 CHUNK_SIZE 4096
+
+struct context {
+	uint64_t samplerate;
+	int samplesize;
+	int num_channels;
+};
+
+static int get_wav_header(const char *filename, char *buf)
+{
+	struct stat st;
+	int fd, l;
+
+	l = strlen(filename);
+	if (l <= 4 || strcasecmp(filename + l - 4, ".wav"))
+		return SR_ERR;
+
+	if (stat(filename, &st) == -1)
+		return SR_ERR;
+	if (st.st_size <= 45)
+		/* Minimum size of header + 1 8-bit mono PCM sample. */
+		return SR_ERR;
+
+	if ((fd = open(filename, O_RDONLY)) == -1)
+		return SR_ERR;
+
+	l = read(fd, buf, 40);
+	close(fd);
+	if (l != 40)
+		return SR_ERR;
+
+	return SR_OK;
+}
+
+static int format_match(const char *filename)
+{
+	char buf[40];
+
+	if (get_wav_header(filename, buf) != SR_OK)
+		return FALSE;
+
+	if (strncmp(buf, "RIFF", 4))
+		return FALSE;
+	if (strncmp(buf + 8, "WAVE", 4))
+		return FALSE;
+	if (strncmp(buf + 12, "fmt ", 4))
+		return FALSE;
+	if (GUINT16_FROM_LE(*(uint16_t *)(buf + 20)) != 1)
+		/* Not PCM. */
+		return FALSE;
+	if (strncmp(buf + 36, "data", 4))
+		return FALSE;
+
+	return TRUE;
+}
+
+static int init(struct sr_input *in, const char *filename)
+{
+	struct sr_probe *probe;
+	struct context *ctx;
+	char buf[40], probename[8];
+	int i;
+
+	if (get_wav_header(filename, buf) != SR_OK)
+		return SR_ERR;
+
+	if (!(ctx = g_try_malloc0(sizeof(struct context))))
+		return SR_ERR_MALLOC;
+
+	/* Create a virtual device. */
+	in->sdi = sr_dev_inst_new(LOGIC, 0, SR_ST_ACTIVE, NULL, NULL, NULL);
+	in->sdi->priv = ctx;
+
+   	ctx->samplerate = GUINT32_FROM_LE(*(uint32_t *)(buf + 24));
+	ctx->samplesize = GUINT16_FROM_LE(*(uint16_t *)(buf + 34)) / 8;
+	if (ctx->samplesize != 1 && ctx->samplesize != 2 && ctx->samplesize != 4) {
+		sr_err("only 8, 16 or 32 bits per sample supported.");
+		return SR_ERR;
+	}
+
+	if ((ctx->num_channels = GUINT16_FROM_LE(*(uint16_t *)(buf + 22))) > 20) {
+		sr_err("%d channels seems crazy.", ctx->num_channels);
+		return SR_ERR;
+	}
+
+	for (i = 0; i < ctx->num_channels; i++) {
+		snprintf(probename, 8, "CH%d", i + 1);
+		if (!(probe = sr_probe_new(0, SR_PROBE_ANALOG, TRUE, probename)))
+			return SR_ERR;
+		in->sdi->probes = g_slist_append(in->sdi->probes, probe);
+	}
+
+	return SR_OK;
+}
+
+static int loadfile(struct sr_input *in, const char *filename)
+{
+	struct sr_datafeed_packet packet;
+	struct sr_datafeed_meta meta;
+	struct sr_datafeed_analog analog;
+	struct sr_config *src;
+	struct context *ctx;
+	float fdata[CHUNK_SIZE];
+	uint64_t sample;
+	int num_samples, chunk_samples, s, c, fd, l;
+	char buf[CHUNK_SIZE];
+
+	ctx = in->sdi->priv;
+
+	/* Send header packet to the session bus. */
+	std_session_send_df_header(in->sdi, LOG_PREFIX);
+
+	packet.type = SR_DF_META;
+	packet.payload = &meta;
+	src = sr_config_new(SR_CONF_SAMPLERATE,
+			g_variant_new_uint64(ctx->samplerate));
+	meta.config = g_slist_append(NULL, src);
+	sr_session_send(in->sdi, &packet);
+	sr_config_free(src);
+
+	if ((fd = open(filename, O_RDONLY)) == -1)
+		return SR_ERR;
+
+	lseek(fd, 40, SEEK_SET);
+	l = read(fd, buf, 4);
+	num_samples = GUINT32_FROM_LE((uint32_t)*(buf));
+	num_samples /= ctx->samplesize / ctx->num_channels;
+	while (TRUE) {
+		if ((l = read(fd, buf, CHUNK_SIZE)) < 1)
+			break;
+		chunk_samples = l / ctx->samplesize / ctx->num_channels;
+		for (s = 0; s < chunk_samples; s++) {
+			for (c = 0; c < ctx->num_channels; c++) {
+				sample = 0;
+				memcpy(&sample, buf + s * ctx->samplesize + c, ctx->samplesize);
+				switch (ctx->samplesize) {
+				case 1:
+					/* 8-bit PCM samples are unsigned. */
+					fdata[s + c] = (uint8_t)sample / 255.0;
+					break;
+				case 2:
+					fdata[s + c] = GINT16_FROM_LE(sample) / 32767.0;
+					break;
+				case 4:
+					fdata[s + c] = GINT32_FROM_LE(sample) / 65535.0;
+					break;
+				}
+			}
+		}
+		packet.type = SR_DF_ANALOG;
+		packet.payload = &analog;
+		analog.probes = in->sdi->probes;
+		analog.num_samples = chunk_samples;
+		analog.mq = 0;
+		analog.unit = 0;
+		analog.data = fdata;
+		sr_session_send(in->sdi, &packet);
+	}
+
+	close(fd);
+	packet.type = SR_DF_END;
+	sr_session_send(in->sdi, &packet);
+
+	return SR_OK;
+}
+
+
+SR_PRIV struct sr_input_format input_wav = {
+	.id = "wav",
+	.description = "WAV file",
+	.format_match = format_match,
+	.init = init,
+	.loadfile = loadfile,
+};
+
diff --git a/input/input.c b/input/input.c
index fa0bf43..68ae49e 100644
--- a/input/input.c
+++ b/input/input.c
@@ -50,7 +50,7 @@
  */
 
 /** @cond PRIVATE */
-extern SR_PRIV struct sr_input_format input_chronovu_la8;
+
 extern SR_PRIV struct sr_input_format input_binary;
 extern SR_PRIV struct sr_input_format input_vcd;
 extern SR_PRIV struct sr_input_format input_wav;
@@ -58,7 +58,6 @@
 
 static struct sr_input_format *input_module_list[] = {
 	&input_vcd,
-	&input_chronovu_la8,
 	&input_wav,
 	/* This one has to be last, because it will take any input. */
 	&input_binary,
diff --git a/libsigrok-internal.h b/libsigrok-internal.h
index 57005cd..aa8086e 100644
--- a/libsigrok-internal.h
+++ b/libsigrok-internal.h
@@ -84,11 +84,12 @@
 /*--- device.c --------------------------------------------------------------*/
 
 SR_PRIV struct sr_probe *sr_probe_new(int index, int type,
-		gboolean enabled, const char *name);
+                                      gboolean enabled, const char *name);
+SR_PRIV void sr_dev_probes_free(struct sr_dev_inst *sdi);
 
 /* Generic device instances */
-SR_PRIV struct sr_dev_inst *sr_dev_inst_new(int index, int status,
-		const char *vendor, const char *model, const char *version);
+SR_PRIV struct sr_dev_inst *sr_dev_inst_new(int mode, int index, int status,
+                                            const char *vendor, const char *model, const char *version);
 SR_PRIV void sr_dev_inst_free(struct sr_dev_inst *sdi);
 
 #ifdef HAVE_LIBUSB_1_0
@@ -112,7 +113,7 @@
 SR_PRIV void sr_config_free(struct sr_config *src);
 SR_PRIV int sr_source_remove(int fd);
 SR_PRIV int sr_source_add(int fd, int events, int timeout,
-		sr_receive_data_callback_t cb, void *cb_data);
+        sr_receive_data_callback_t cb, void *cb_data);
 
 /*--- session.c -------------------------------------------------------------*/
 
@@ -135,6 +136,14 @@
 SR_PRIV int std_dev_clear(const struct sr_dev_driver *driver,
 		std_dev_clear_t clear_private);
 
+/*--- trigger.c -------------------------------------------------*/
+SR_PRIV uint64_t sr_trigger_get_mask0(uint16_t stage);
+SR_PRIV uint64_t sr_trigger_get_mask1(uint16_t stage);
+SR_PRIV uint64_t sr_trigger_get_value0(uint16_t stage);
+SR_PRIV uint64_t sr_trigger_get_value1(uint16_t stage);
+SR_PRIV uint64_t sr_trigger_get_edge0(uint16_t stage);
+SR_PRIV uint64_t sr_trigger_get_edge1(uint16_t stage);
+
 /*--- hardware/common/serial.c ----------------------------------------------*/
 
 enum {
@@ -180,84 +189,6 @@
 SR_PRIV int sr_usb_open(libusb_context *usb_ctx, struct sr_usb_dev_inst *usb);
 #endif
 
-/*--- hardware/common/dmm/es51922.c -----------------------------------------*/
 
-#define ES51922_PACKET_SIZE 14
-
-struct es51922_info {
-	gboolean is_judge, is_vbar, is_voltage, is_auto, is_micro, is_current;
-	gboolean is_milli, is_resistance, is_continuity, is_diode, is_lpf;
-	gboolean is_frequency, is_duty_cycle, is_capacitance, is_temperature;
-	gboolean is_celsius, is_fahrenheit, is_adp, is_sign, is_batt, is_ol;
-	gboolean is_max, is_min, is_rel, is_rmr, is_ul, is_pmax, is_pmin;
-	gboolean is_dc, is_ac, is_vahz, is_hold, is_nano, is_kilo, is_mega;
-};
-
-SR_PRIV gboolean sr_es51922_packet_valid(const uint8_t *buf);
-SR_PRIV int sr_es51922_parse(const uint8_t *buf, float *floatval,
-			     struct sr_datafeed_analog *analog, void *info);
-
-/*--- hardware/common/dmm/fs9922.c ------------------------------------------*/
-
-#define FS9922_PACKET_SIZE 14
-
-struct fs9922_info {
-	gboolean is_auto, is_dc, is_ac, is_rel, is_hold, is_bpn, is_z1, is_z2;
-	gboolean is_max, is_min, is_apo, is_bat, is_nano, is_z3, is_micro;
-	gboolean is_milli, is_kilo, is_mega, is_beep, is_diode, is_percent;
-	gboolean is_z4, is_volt, is_ampere, is_ohm, is_hfe, is_hertz, is_farad;
-	gboolean is_celsius, is_fahrenheit;
-	int bargraph_sign, bargraph_value;
-};
-
-SR_PRIV gboolean sr_fs9922_packet_valid(const uint8_t *buf);
-SR_PRIV int sr_fs9922_parse(const uint8_t *buf, float *floatval,
-			    struct sr_datafeed_analog *analog, void *info);
-
-/*--- hardware/common/dmm/fs9721.c ------------------------------------------*/
-
-#define FS9721_PACKET_SIZE 14
-
-struct fs9721_info {
-	gboolean is_ac, is_dc, is_auto, is_rs232, is_micro, is_nano, is_kilo;
-	gboolean is_diode, is_milli, is_percent, is_mega, is_beep, is_farad;
-	gboolean is_ohm, is_rel, is_hold, is_ampere, is_volt, is_hz, is_bat;
-	gboolean is_c2c1_11, is_c2c1_10, is_c2c1_01, is_c2c1_00, is_sign;
-};
-
-SR_PRIV gboolean sr_fs9721_packet_valid(const uint8_t *buf);
-SR_PRIV int sr_fs9721_parse(const uint8_t *buf, float *floatval,
-			    struct sr_datafeed_analog *analog, void *info);
-SR_PRIV void sr_fs9721_00_temp_c(struct sr_datafeed_analog *analog, void *info);
-SR_PRIV void sr_fs9721_01_temp_c(struct sr_datafeed_analog *analog, void *info);
-SR_PRIV void sr_fs9721_10_temp_c(struct sr_datafeed_analog *analog, void *info);
-SR_PRIV void sr_fs9721_01_10_temp_f_c(struct sr_datafeed_analog *analog, void *info);
-
-/*--- hardware/common/dmm/metex14.c -----------------------------------------*/
-
-#define METEX14_PACKET_SIZE 14
-
-struct metex14_info {
-	gboolean is_ac, is_dc, is_resistance, is_capacity, is_temperature;
-	gboolean is_diode, is_frequency, is_ampere, is_volt, is_farad;
-	gboolean is_hertz, is_ohm, is_celsius, is_nano, is_micro, is_milli;
-	gboolean is_kilo, is_mega, is_gain, is_decibel, is_hfe, is_unitless;
-};
-
-SR_PRIV int sr_metex14_packet_request(struct sr_serial_dev_inst *serial);
-SR_PRIV gboolean sr_metex14_packet_valid(const uint8_t *buf);
-SR_PRIV int sr_metex14_parse(const uint8_t *buf, float *floatval,
-			     struct sr_datafeed_analog *analog, void *info);
-
-/*--- hardware/common/dmm/rs9lcd.c ------------------------------------------*/
-
-#define RS9LCD_PACKET_SIZE 9
-
-/* Dummy info struct. The parser does not use it. */
-struct rs9lcd_info { int dummy; };
-
-SR_PRIV gboolean sr_rs9lcd_packet_valid(const uint8_t *buf);
-SR_PRIV int sr_rs9lcd_parse(const uint8_t *buf, float *floatval,
-			    struct sr_datafeed_analog *analog, void *info);
 
 #endif
diff --git a/libsigrok.h b/libsigrok.h
index 6cda554..523aabc 100644
--- a/libsigrok.h
+++ b/libsigrok.h
@@ -26,6 +26,14 @@
 #include <inttypes.h>
 #include <glib.h>
 
+#ifdef WIN32
+#define WINVER 0x0500
+#define _WIN32_WINNT WINVER
+#include <Winsock2.h>
+#else
+#include <sys/time.h>
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -80,6 +88,10 @@
 };
 
 #define SR_MAX_PROBENAME_LEN 32
+#define DS_MAX_ANALOG_PROBES_NUM 8
+#define TriggerStages 16
+#define TriggerProbes 16
+#define TriggerCountBits 16
 
 /* Handy little macros */
 #define SR_HZ(n)  (n)
@@ -129,7 +141,7 @@
 #define SR_PRIV
 #endif
 
-typedef int (*sr_receive_data_callback_t)(int fd, int revents, void *cb_data);
+typedef int (*sr_receive_data_callback_t)(int fd, int revents, const struct sr_dev_inst *sdi);
 
 /** Data types used by sr_config_info(). */
 enum {
@@ -280,9 +292,14 @@
 struct sr_datafeed_logic {
 	uint64_t length;
 	uint16_t unitsize;
+    uint16_t data_error;
 	void *data;
 };
 
+struct sr_datafeed_trigger {
+
+};
+
 struct sr_datafeed_analog {
 	/** The probes for which data is included in this packet. */
 	GSList *probes;
@@ -533,6 +550,16 @@
 	SR_PROBE_ANALOG,
 };
 
+enum {
+    LOGIC = 0,
+    ANALOG = 1,
+};
+
+static const char *mode_strings[] = {
+    "Logic Analyzer",
+    "Oscilloscope",
+};
+
 struct sr_probe {
 	/* The index field will go: use g_slist_length(sdi->probes) instead. */
 	int index;
@@ -622,6 +649,9 @@
 	/** The device supports setting a pre/post-trigger capture ratio. */
 	SR_CONF_CAPTURE_RATIO,
 
+    /** */
+    SR_CONF_DEVICE_MODE,
+
 	/** The device supports setting a pattern (pattern generator mode). */
 	SR_CONF_PATTERN_MODE,
 
@@ -664,6 +694,9 @@
 	/** Number of vertical divisions, as related to SR_CONF_VDIV.  */
 	SR_CONF_NUM_VDIV,
 
+    /** clock type (internal/external) */
+    SR_CONF_CLOCK_TYPE,
+
 	/*--- Special stuff -------------------------------------------------*/
 
 	/** Scan options supported by the driver. */
@@ -671,6 +704,7 @@
 
 	/** Device options for a particular device. */
 	SR_CONF_DEVICE_OPTIONS,
+    SR_CONF_DEVICE_CONFIGS,
 
 	/** Session filename. */
 	SR_CONF_SESSIONFILE,
@@ -721,6 +755,7 @@
 	int index;
 	int status;
 	int inst_type;
+    int mode;
 	char *vendor;
 	char *model;
 	char *version;
@@ -771,6 +806,7 @@
 	/* Device-specific */
 	int (*dev_open) (struct sr_dev_inst *sdi);
 	int (*dev_close) (struct sr_dev_inst *sdi);
+    int (*dev_test) (struct sr_dev_inst *sdi);
 	int (*dev_acquisition_start) (const struct sr_dev_inst *sdi,
 			void *cb_data);
 	int (*dev_acquisition_stop) (struct sr_dev_inst *sdi,
@@ -804,10 +840,70 @@
 	 * an async fashion. We need to make sure the session is stopped from
 	 * within the session thread itself.
 	 */
-	GMutex stop_mutex;
+//	GMutex stop_mutex;
 	gboolean abort_session;
 };
 
+enum {
+    SIMPLE_TRIGGER = 0,
+    ADV_TRIGGER,
+};
+
+struct ds_trigger {
+    uint16_t trigger_en;
+    uint16_t trigger_mode;
+    uint16_t trigger_pos;
+    uint16_t trigger_stages;
+    unsigned char trigger_logic[TriggerStages+1];
+    unsigned char trigger0_inv[TriggerStages+1];
+    unsigned char trigger1_inv[TriggerStages+1];
+    char trigger0[TriggerStages+1][TriggerProbes];
+    char trigger1[TriggerStages+1][TriggerProbes];
+    uint16_t trigger0_count[TriggerStages+1];
+    uint16_t trigger1_count[TriggerStages+1];
+};
+
+struct ds_trigger_pos {
+    uint32_t real_pos;
+    uint32_t ram_saddr;
+    unsigned char first_block[504];
+};
+
+//struct libusbhp_t;
+typedef void (*libusbhp_hotplug_cb_fn)(struct libusbhp_device_t *device,
+                                     void *user_data);
+#ifdef __linux__
+#include <libudev.h>
+
+struct dev_list_t {
+  char *path;
+  unsigned short vid;
+  unsigned short pid;
+  struct dev_list_t *next;
+};
+#endif/*__linux__*/
+
+struct libusbhp_t {
+#ifdef __linux__
+  struct udev* hotplug;
+  struct udev_monitor* hotplug_monitor;
+  struct dev_list_t *devlist;
+#endif/*__linux__*/
+#ifdef _WIN32
+  HWND hwnd;
+  HDEVNOTIFY hDeviceNotify;
+  WNDCLASSEX wcex;
+#endif/*_WIN32*/
+  libusbhp_hotplug_cb_fn attach;
+  libusbhp_hotplug_cb_fn detach;
+  void *user_data;
+};
+
+struct libusbhp_device_t {
+    unsigned short idVendor;
+    unsigned short idProduct;
+};
+
 #include "proto.h"
 #include "version.h"
 
diff --git a/libsigrok4DSLogic.pc.in b/libsigrok4DSLogic.pc.in
new file mode 100644
index 0000000..92a2361
--- /dev/null
+++ b/libsigrok4DSLogic.pc.in
@@ -0,0 +1,15 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libsigrok4DSLogic
+Description: Backend library of DSLogic software based on libsigrok
+URL: http://www.dreamsourcelab.com
+Requires: glib-2.0
+Requires.private: @SR_PKGLIBS@
+Version: @VERSION@
+Libs: -L${libdir} -lsigrok4DSLogic
+Libs.private: -lm
+Cflags: -I${includedir}
+
diff --git a/libusbhp.c b/libusbhp.c
new file mode 100644
index 0000000..c93f079
--- /dev/null
+++ b/libusbhp.c
@@ -0,0 +1,392 @@
+/*
+ * This file is part of the DSLogic project.
+ */
+
+#include "libsigrok.h"
+#include "hardware/DSLogic/dslogic.h"
+
+#ifdef __linux__
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#endif/*__linux__*/
+
+#ifdef _WIN32
+#include <windows.h>
+
+#include <initguid.h>
+#include <ddk/usbiodef.h>
+#include <Setupapi.h>
+
+#include <tchar.h>
+#include <conio.h>
+#include <dbt.h>
+#include <stdio.h>
+#include <winuser.h>
+
+#endif/*_WIN32*/
+
+
+
+#ifdef __linux__
+static void dev_list_add(struct libusbhp_t *h, const char *path,
+                         unsigned short vid, unsigned short pid)
+{
+  struct dev_list_t *dev =
+    (struct dev_list_t*)malloc(sizeof(struct dev_list_t));
+  dev->path = strdup(path);
+  dev->vid = vid;
+  dev->pid = pid;
+  dev->next = NULL;
+
+  struct dev_list_t *p = h->devlist;
+  if(!p) {
+    h->devlist = dev;
+    return;
+  }
+
+  while(p->next) {
+    p = p->next;
+  }
+
+  p->next = dev;
+}
+
+static int dev_list_remove(struct libusbhp_t *h, const char *path)
+{
+  struct dev_list_t *p = h->devlist;
+  if(!p) return 1;
+
+  if(!strcmp(p->path, path)) {
+    h->devlist = p->next;
+    free(p->path);
+    free(p);
+    return 0;
+  }
+
+  while(p->next) {
+    if(!strcmp(p->next->path, path)) {
+      struct dev_list_t *pp = p->next;
+      p->next = pp->next;
+      free(pp->path);
+      free(pp->next);
+      free(pp);
+      return 0;
+    }
+    p = p->next;
+  }
+
+  // Not found
+  return 1;
+}
+
+static int dev_list_find(struct libusbhp_t *h, const char *path,
+                         unsigned short *vid, unsigned short *pid)
+{
+  struct dev_list_t *p = h->devlist;
+  while(p) {
+    if(!strcmp(p->path, path)) {
+      *vid = p->vid;
+      *pid = p->pid;
+      return 0;
+    }
+    p = p->next;
+  }
+
+  // Not found
+  return 1;
+}
+#endif/*__linux__*/
+
+#ifdef _WIN32
+SR_PRIV LRESULT CALLBACK WinProcCallback(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
+{
+  struct libusbhp_t *h = (struct libusbhp_t*)GetWindowLong(hwnd, GWL_USERDATA);
+
+  switch(msg) {
+  case WM_DEVICECHANGE:
+    {
+      PDEV_BROADCAST_HDR phdr = (PDEV_BROADCAST_HDR)lp;
+
+      if(!phdr || phdr->dbch_devicetype != DBT_DEVTYP_DEVICEINTERFACE) break;
+
+      PDEV_BROADCAST_DEVICEINTERFACE devif =
+        (PDEV_BROADCAST_DEVICEINTERFACE)lp;
+
+      HDEVINFO devinfolist = SetupDiCreateDeviceInfoList(NULL, NULL);
+      
+      SP_DEVICE_INTERFACE_DATA devifdata;
+      memset(&devifdata, 0, sizeof(devifdata));
+      devifdata.cbSize = sizeof(devifdata);
+      BOOL b = SetupDiOpenDeviceInterface(devinfolist, devif->dbcc_name, 0,
+                                          &devifdata);
+      
+      DWORD required;
+      SP_DEVICE_INTERFACE_DETAIL_DATA devdetaildata;
+      memset(&devdetaildata, 0, sizeof(devdetaildata));
+      devdetaildata.cbSize = sizeof(devdetaildata);
+
+      SP_DEVINFO_DATA devinfodata;
+      memset(&devinfodata, 0, sizeof(devinfodata));
+      devinfodata.cbSize = sizeof(devinfodata);
+      b = SetupDiGetDeviceInterfaceDetail(devinfolist, &devifdata,
+                                          &devdetaildata,
+                                          sizeof(devdetaildata),
+                                          &required, &devinfodata);
+     
+      TCHAR deviceidw[1024];
+      b = SetupDiGetDeviceInstanceIdW(devinfolist, &devinfodata, deviceidw,
+                                      sizeof(deviceidw), NULL);
+
+      char deviceid[1024];
+      //size_t sz;
+      //wcstombs_s(&sz, deviceid, deviceidw, sizeof(deviceid) - 1);
+      wcstombs(deviceid, deviceidw, sizeof(deviceid) - 1);
+
+      char *vid = strstr(deviceid, "VID_");
+      if(vid != NULL) vid += 4;
+
+      char *pid = strstr(deviceid, "PID_");
+      if(pid != NULL)  pid += 4;
+
+      struct libusbhp_device_t *device = NULL;
+
+      if(pid || vid) {
+        device =
+          (struct libusbhp_device_t*)malloc(sizeof(struct libusbhp_device_t));
+      }
+
+      if(pid) {
+        pid[4] = '\0';
+        device->idProduct = (unsigned short)strtol(pid, NULL, 16); 
+      }
+
+      if(vid) {
+        vid[4] = '\0';
+        device->idVendor = (unsigned short)strtol(vid, NULL, 16);
+      }
+
+      if ((device->idVendor == supported_fx2[0].vid) &&
+          (device->idProduct == supported_fx2[0].pid)) {
+          switch(wp) {
+          case DBT_DEVICEARRIVAL:
+            if(h->attach) h->attach(device, h->user_data);
+            break;
+          case DBT_DEVICEREMOVECOMPLETE:
+            if(h->detach) h->detach(device, h->user_data);
+            break;
+          case DBT_DEVNODES_CHANGED:
+          default:
+            break;
+          }
+      }
+
+      if(device) free(device);
+    }
+    break;
+  default:
+    break;
+  }
+  
+  return DefWindowProc(hwnd, msg, wp, lp);
+}
+#endif/*OS_WINDOWS*/
+
+SR_API int libusbhp_init(struct libusbhp_t **handle)
+{
+  struct libusbhp_t *h = (struct libusbhp_t *)malloc(sizeof(struct libusbhp_t));
+
+  h->attach = NULL;
+  h->detach = NULL;
+  h->user_data = NULL;
+
+#ifdef __linux__
+  h->devlist = NULL;
+
+  // create the udev object
+  h->hotplug = udev_new();
+  if(!h->hotplug)
+  {
+    printf("Cannot create udev object\n");
+    free(h);
+    return 1;
+  }
+
+  // create the udev monitor
+  h->hotplug_monitor = udev_monitor_new_from_netlink(h->hotplug, "udev");
+
+  // start receiving hotplug events
+  udev_monitor_filter_add_match_subsystem_devtype(h->hotplug_monitor,
+                                                  "usb", "usb_device");
+  udev_monitor_enable_receiving(h->hotplug_monitor);
+
+  struct udev_enumerate *de = udev_enumerate_new (h->hotplug);
+  udev_enumerate_add_match_subsystem(de, "usb");
+  udev_enumerate_scan_devices(de);
+
+  struct udev_list_entry *lst = udev_enumerate_get_list_entry(de);
+  while(lst) {
+    struct udev_device *dev =
+      udev_device_new_from_syspath(h->hotplug,
+                                   udev_list_entry_get_name(lst));
+
+    if(udev_device_get_devnode(dev)) {
+      unsigned short idVendor =
+        strtol(udev_device_get_sysattr_value(dev, "idVendor"), NULL, 16); 
+      unsigned short idProduct =
+        strtol(udev_device_get_sysattr_value(dev, "idProduct"), NULL, 16); 
+
+      dev_list_add(h, udev_device_get_devnode(dev), idVendor, idProduct);
+    }
+
+    udev_device_unref(dev);
+
+    lst = udev_list_entry_get_next(lst);
+  }
+
+  udev_enumerate_unref(de);
+
+#endif/*__linux__*/
+
+#ifdef _WIN32
+  memset(&h->wcex, 0, sizeof(h->wcex));
+  h->wcex.cbSize = sizeof(WNDCLASSEX);
+  h->wcex.lpfnWndProc = WinProcCallback;
+  h->wcex.hInstance = GetModuleHandle(NULL);  
+  h->wcex.lpszClassName = TEXT("UsbHotplugClass");
+  h->wcex.cbWndExtra = sizeof(struct libusbhp_t*); // Size of data.
+
+  RegisterClassEx(&h->wcex);
+
+  h->hwnd =
+    CreateWindowEx(0, h->wcex.lpszClassName, TEXT("UsbHotplug"), 0, 0, 0, 0,
+                   0, 0, NULL, GetModuleHandle(NULL), NULL);
+
+  SetWindowLong(h->hwnd, GWL_USERDATA, (LONG)h);
+
+
+  DEV_BROADCAST_DEVICEINTERFACE *filter =
+  (DEV_BROADCAST_DEVICEINTERFACE*)malloc(sizeof(DEV_BROADCAST_DEVICEINTERFACE));
+
+  memset(filter, 0, sizeof(DEV_BROADCAST_DEVICEINTERFACE));
+  filter->dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
+  filter->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
+  filter->dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
+
+  h->hDeviceNotify =
+    RegisterDeviceNotification(h->hwnd, filter, DEVICE_NOTIFY_WINDOW_HANDLE);
+  
+  if(h->hDeviceNotify == 0) {
+    //printf("RegisterDeviceNotification error\n");
+    free(h);
+    return 1;
+  }
+#endif/*_WIN32*/
+
+  *handle = h;
+  return 0;
+}
+
+SR_API void libusbhp_exit(struct libusbhp_t *h)
+{
+#ifdef __linux__
+  // destroy the udev monitor
+  udev_monitor_unref(h->hotplug_monitor);
+
+  // destroy the udev object
+  udev_unref(h->hotplug);
+#endif/*__linux__*/
+
+#ifdef _WIN32
+  UnregisterDeviceNotification(h->hDeviceNotify);
+  DestroyWindow(h->hwnd);
+  UnregisterClass(h->wcex.lpszClassName, h->wcex.hInstance);
+#endif/*_WIN32*/
+
+  free(h);
+}
+
+SR_API int libusbhp_handle_events_timeout(struct libusbhp_t *h, struct timeval *tv)
+{
+  int ms = tv->tv_sec * 1000 + tv->tv_usec / 1000;
+
+#ifdef __linux__
+  // create the poll item
+  struct pollfd items[1];
+  items[0].fd = udev_monitor_get_fd(h->hotplug_monitor);
+  items[0].events = POLLIN;
+  items[0].revents = 0;
+
+  // while there are hotplug events to process
+  while(poll(items, 1, ms) > 0) {    
+    // receive the relevant device
+    struct udev_device* dev = udev_monitor_receive_device(h->hotplug_monitor);
+    if(!dev) {
+      // error receiving device, skip it
+      continue;
+    }
+
+    if(!strcmp(udev_device_get_action(dev), "add")) {
+      struct libusbhp_device_t device;
+
+      device.idVendor =
+        strtol(udev_device_get_sysattr_value(dev, "idVendor"), NULL, 16); 
+      device.idProduct =
+        strtol(udev_device_get_sysattr_value(dev, "idProduct"), NULL, 16); 
+
+      dev_list_add(h, udev_device_get_devnode(dev),
+                   device.idVendor, device.idProduct);
+
+      if(h->attach) h->attach(&device, h->user_data);
+    }
+
+    if(!strcmp(udev_device_get_action(dev), "remove")) {
+      struct libusbhp_device_t device;
+
+      int res = dev_list_find(h, udev_device_get_devnode(dev),
+                              &device.idVendor, &device.idProduct);
+
+      if(res) {
+        if(h->detach) h->detach(NULL, h->user_data);
+      } else {
+	dev_list_remove(h, udev_device_get_devnode(dev));
+        if(h->detach) h->detach(&device, h->user_data);
+      }
+    }
+
+    // destroy the relevant device
+    udev_device_unref(dev);
+
+    // clear the revents
+    items[0].revents = 0;
+  }
+#endif/*__linux__*/
+
+#ifdef _WIN32
+  UINT_PTR timer = SetTimer(h->hwnd, 0, ms, NULL);
+
+  MSG msg; 
+  int ret = GetMessage(&msg, NULL, 0, 0);
+
+  if(ret <= 0) return 0;
+  
+  TranslateMessage(&msg);
+  DispatchMessage(&msg);
+
+  KillTimer(h->hwnd, timer);
+#endif/*_WIN32*/
+
+  return 0;
+}
+
+SR_API void libusbhp_register_hotplug_listeners(struct libusbhp_t *handle,
+                                         libusbhp_hotplug_cb_fn connected_cb,
+                                         libusbhp_hotplug_cb_fn disconnected_cb,
+                                         void *user_data)
+{
+  handle->attach = connected_cb;
+  handle->detach = disconnected_cb;
+  handle->user_data = user_data;
+}
diff --git a/output/Makefile.am b/output/Makefile.am
index 62f9842..2bbe59c 100644
--- a/output/Makefile.am
+++ b/output/Makefile.am
@@ -20,21 +20,18 @@
 SUBDIRS = text
 
 # Local lib, this is NOT meant to be installed!
-noinst_LTLIBRARIES = libsigrokoutput.la
+noinst_LTLIBRARIES = libsigrok4DSLogicoutput.la
 
-libsigrokoutput_la_SOURCES = \
-	binary.c \
-	vcd.c \
-	ols.c \
-	gnuplot.c \
-	chronovu_la8.c \
-	csv.c \
-	analog.c \
+libsigrok4DSLogicoutput_la_SOURCES = \
+        out_binary.c \
+        out_vcd.c \
+        out_csv.c \
+        out_analog.c \
 	output.c
 
-libsigrokoutput_la_CFLAGS = \
+libsigrok4DSLogicoutput_la_CFLAGS = \
 	-I$(top_srcdir)
 
-libsigrokoutput_la_LIBADD = \
-	text/libsigrokoutputtext.la
+libsigrok4DSLogicoutput_la_LIBADD = \
+	text/libsigrok4DSLogicoutputtext.la
 
diff --git a/output/out_analog.c b/output/out_analog.c
new file mode 100644
index 0000000..684f882
--- /dev/null
+++ b/output/out_analog.c
@@ -0,0 +1,251 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2012 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 <string.h>
+#include <math.h>
+#include <glib.h>
+#include "libsigrok.h"
+#include "libsigrok-internal.h"
+
+/* Message logging helpers with subsystem-specific prefix string. */
+#define LOG_PREFIX "output/analog: "
+#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)
+
+struct context {
+	int num_enabled_probes;
+	GPtrArray *probelist;
+};
+
+static int init(struct sr_output *o)
+{
+	struct context *ctx;
+	struct sr_probe *probe;
+	GSList *l;
+
+	sr_spew("Initializing output module.");
+
+	if (!o || !o->sdi)
+		return SR_ERR_ARG;
+
+	if (!(ctx = g_try_malloc0(sizeof(struct context)))) {
+		sr_err("Output module context malloc failed.");
+		return SR_ERR_MALLOC;
+	}
+	o->internal = ctx;
+
+	/* Get the number of probes and their names. */
+	ctx->probelist = g_ptr_array_new();
+	for (l = o->sdi->probes; l; l = l->next) {
+		probe = l->data;
+		if (!probe || !probe->enabled)
+			continue;
+		g_ptr_array_add(ctx->probelist, probe->name);
+		ctx->num_enabled_probes++;
+	}
+
+	return SR_OK;
+}
+
+static void si_printf(float value, GString *out, char *unitstr)
+{
+	float v;
+
+	if (signbit(value))
+		v = -(value);
+	else
+		v = value;
+
+	if (v < 1e-12 || v > 1e+12)
+		g_string_append_printf(out, "%f %s", value, unitstr);
+	else if (v > 1e+9)
+		g_string_append_printf(out, "%f G%s", value / 1e+9, unitstr);
+	else if (v > 1e+6)
+		g_string_append_printf(out, "%f M%s", value / 1e+6, unitstr);
+	else if (v > 1e+3)
+		g_string_append_printf(out, "%f k%s", value / 1e+3, unitstr);
+	else if (v < 1e-9)
+		g_string_append_printf(out, "%f n%s", value * 1e+9, unitstr);
+	else if (v < 1e-6)
+		g_string_append_printf(out, "%f u%s", value * 1e+6, unitstr);
+	else if (v < 1e-3)
+		g_string_append_printf(out, "%f m%s", value * 1e+3, unitstr);
+	else
+		g_string_append_printf(out, "%f %s", value, unitstr);
+
+}
+
+static void fancyprint(int unit, int mqflags, float value, GString *out)
+{
+	switch (unit) {
+	case SR_UNIT_VOLT:
+		si_printf(value, out, "V");
+		break;
+	case SR_UNIT_AMPERE:
+		si_printf(value, out, "A");
+		break;
+	case SR_UNIT_OHM:
+		si_printf(value, out, "");
+		g_string_append_unichar(out, 0x2126);
+		break;
+	case SR_UNIT_FARAD:
+		si_printf(value, out, "F");
+		break;
+	case SR_UNIT_KELVIN:
+		si_printf(value, out, "K");
+		break;
+	case SR_UNIT_CELSIUS:
+		si_printf(value, out, "");
+		g_string_append_unichar(out, 0x00b0);
+		g_string_append_c(out, 'C');
+		break;
+	case SR_UNIT_FAHRENHEIT:
+		si_printf(value, out, "");
+		g_string_append_unichar(out, 0x00b0);
+		g_string_append_c(out, 'F');
+		break;
+	case SR_UNIT_HERTZ:
+		si_printf(value, out, "Hz");
+		break;
+	case SR_UNIT_PERCENTAGE:
+		g_string_append_printf(out, "%f%%", value);
+		break;
+	case SR_UNIT_BOOLEAN:
+		if (value > 0)
+			g_string_append_printf(out, "TRUE");
+		else
+			g_string_append_printf(out, "FALSE");
+		break;
+	case SR_UNIT_SECOND:
+		si_printf(value, out, "s");
+		break;
+	case SR_UNIT_SIEMENS:
+		si_printf(value, out, "S");
+		break;
+	case SR_UNIT_DECIBEL_MW:
+		si_printf(value, out, "dBu");
+		break;
+	case SR_UNIT_DECIBEL_VOLT:
+		si_printf(value, out, "dBV");
+		break;
+	case SR_UNIT_DECIBEL_SPL:
+		if (mqflags & SR_MQFLAG_SPL_FREQ_WEIGHT_A)
+			si_printf(value, out, "dB(A)");
+		else if (mqflags & SR_MQFLAG_SPL_FREQ_WEIGHT_C)
+			si_printf(value, out, "dB(C)");
+		else if (mqflags & SR_MQFLAG_SPL_FREQ_WEIGHT_Z)
+			si_printf(value, out, "dB(Z)");
+		else
+			/* No frequency weighting, or non-standard "flat" */
+			si_printf(value, out, "dB(SPL)");
+		if (mqflags & SR_MQFLAG_SPL_TIME_WEIGHT_S)
+			g_string_append(out, " S");
+		else if (mqflags & SR_MQFLAG_SPL_TIME_WEIGHT_F)
+			g_string_append(out, " F");
+		if (mqflags & SR_MQFLAG_SPL_LAT)
+			g_string_append(out, " LAT");
+		else if (mqflags & SR_MQFLAG_SPL_PCT_OVER_ALARM)
+			/* Not a standard function for SLMs, so this is
+			 * a made-up notation. */
+			g_string_append(out, " %oA");
+		break;
+	case SR_UNIT_CONCENTRATION:
+		g_string_append_printf(out, "%f ppm", value * 1000000);
+		break;
+	default:
+		si_printf(value, out, "");
+		break;
+	}
+	if ((mqflags & (SR_MQFLAG_AC | SR_MQFLAG_DC)) == (SR_MQFLAG_AC | SR_MQFLAG_DC))
+		g_string_append_printf(out, " AC+DC");
+	else if (mqflags & SR_MQFLAG_AC)
+		g_string_append_printf(out, " AC");
+	else if (mqflags & SR_MQFLAG_DC)
+		g_string_append_printf(out, " DC");
+	g_string_append_c(out, '\n');
+}
+
+static int receive(struct sr_output *o, const struct sr_dev_inst *sdi,
+		const struct sr_datafeed_packet *packet, GString **out)
+{
+	const struct sr_datafeed_analog *analog;
+	struct sr_probe *probe;
+	GSList *l;
+	const float *fdata;
+	int i, p;
+
+	(void)sdi;
+
+	*out = NULL;
+	if (!o || !o->sdi)
+		return SR_ERR_ARG;
+
+	switch (packet->type) {
+	case SR_DF_FRAME_BEGIN:
+		*out = g_string_new("FRAME-BEGIN\n");
+		break;
+	case SR_DF_FRAME_END:
+		*out = g_string_new("FRAME-END\n");
+		break;
+	case SR_DF_ANALOG:
+		analog = packet->payload;
+		fdata = (const float *)analog->data;
+		*out = g_string_sized_new(512);
+		for (i = 0; i < analog->num_samples; i++) {
+			for (l = analog->probes, p = 0; l; l = l->next, p++) {
+				probe = l->data;
+				g_string_append_printf(*out, "%s: ", probe->name);
+				fancyprint(analog->unit, analog->mqflags,
+						fdata[i + p], *out);
+			}
+		}
+		break;
+	}
+
+	return SR_OK;
+}
+
+static int cleanup(struct sr_output *o)
+{
+	struct context *ctx;
+
+	if (!o || !o->sdi)
+		return SR_ERR_ARG;
+	ctx = o->internal;
+
+	g_ptr_array_free(ctx->probelist, 1);
+	g_free(ctx);
+	o->internal = NULL;
+
+	return SR_OK;
+}
+
+SR_PRIV struct sr_output_format output_analog = {
+	.id = "analog",
+	.description = "Analog data",
+	.df_type = SR_DF_ANALOG,
+	.init = init,
+	.receive = receive,
+	.cleanup = cleanup
+};
diff --git a/output/out_binary.c b/output/out_binary.c
new file mode 100644
index 0000000..2fd858e
--- /dev/null
+++ b/output/out_binary.c
@@ -0,0 +1,77 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include "libsigrok.h"
+#include "libsigrok-internal.h"
+
+/* Message logging helpers with subsystem-specific prefix string. */
+#define LOG_PREFIX "output/binary: "
+#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)
+
+static int data(struct sr_output *o, const uint8_t *data_in,
+		uint64_t length_in, uint8_t **data_out, uint64_t *length_out)
+{
+	uint8_t *outbuf;
+
+	(void)o;
+
+	if (!data_in) {
+		sr_err("%s: data_in was NULL", __func__);
+		return SR_ERR_ARG;
+	}
+
+	if (!length_out) {
+		sr_err("%s: length_out was NULL", __func__);
+		return SR_ERR_ARG;
+	}
+
+	if (length_in == 0) {
+		sr_err("%s: length_in was 0", __func__);
+		return SR_ERR_ARG;
+	}
+
+	if (!(outbuf = g_try_malloc0(length_in))) {
+		sr_err("%s: outbuf malloc failed", __func__);
+		return SR_ERR_MALLOC;
+	}
+
+	memcpy(outbuf, data_in, length_in);
+	*data_out = outbuf;
+	*length_out = length_in;
+
+	return SR_OK;
+}
+
+SR_PRIV struct sr_output_format output_binary = {
+	.id = "binary",
+	.description = "Raw binary",
+	.df_type = SR_DF_LOGIC,
+	.init = NULL,
+	.data = data,
+	.event = NULL,
+};
diff --git a/output/out_csv.c b/output/out_csv.c
new file mode 100644
index 0000000..0a7c504
--- /dev/null
+++ b/output/out_csv.c
@@ -0,0 +1,225 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2011 Uwe Hermann <uwe@hermann-uwe.de>
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include "config.h" /* Needed for PACKAGE_STRING and others. */
+#include "libsigrok.h"
+#include "libsigrok-internal.h"
+
+/* Message logging helpers with subsystem-specific prefix string. */
+#define LOG_PREFIX "output/csv: "
+#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)
+
+struct context {
+	unsigned int num_enabled_probes;
+	unsigned int unitsize;
+	uint64_t samplerate;
+	GString *header;
+	char separator;
+};
+
+/*
+ * TODO:
+ *  - Option to specify delimiter character and/or string.
+ *  - Option to (not) print metadata as comments.
+ *  - Option to specify the comment character(s), e.g. # or ; or C/C++-style.
+ *  - Option to (not) print samplenumber / time as extra column.
+ *  - Option to "compress" output (only print changed samples, VCD-like).
+ *  - Option to print comma-separated bits, or whole bytes/words (for 8/16
+ *    probe LAs) as ASCII/hex etc. etc.
+ *  - Trigger support.
+ */
+
+static int init(struct sr_output *o)
+{
+	struct context *ctx;
+	struct sr_probe *probe;
+	GSList *l;
+	GVariant *gvar;
+	int num_probes;
+	time_t t;
+
+	if (!o) {
+		sr_err("%s: o was NULL", __func__);
+		return SR_ERR_ARG;
+	}
+
+	if (!o->sdi) {
+		sr_err("%s: o->sdi was NULL", __func__);
+		return SR_ERR_ARG;
+	}
+
+	if (!(ctx = g_try_malloc0(sizeof(struct context)))) {
+		sr_err("%s: ctx malloc failed", __func__);
+		return SR_ERR_MALLOC;
+	}
+
+	o->internal = ctx;
+
+	/* Get the number of probes, and the unitsize. */
+	for (l = o->sdi->probes; l; l = l->next) {
+		probe = l->data;
+		if (probe->enabled)
+			ctx->num_enabled_probes++;
+	}
+
+	ctx->unitsize = (ctx->num_enabled_probes + 7) / 8;
+
+	num_probes = g_slist_length(o->sdi->probes);
+
+	if (sr_config_get(o->sdi->driver, SR_CONF_SAMPLERATE, &gvar,
+			o->sdi) == SR_OK) {
+		ctx->samplerate = g_variant_get_uint64(gvar);
+		g_variant_unref(gvar);
+	} else
+		ctx->samplerate = 0;
+
+	ctx->separator = ',';
+	ctx->header = g_string_sized_new(512);
+
+	t = time(NULL);
+
+	/* Some metadata */
+	g_string_append_printf(ctx->header, "; CSV, generated by %s on %s",
+			       PACKAGE_STRING, ctime(&t));
+	g_string_append_printf(ctx->header, "; Samplerate: %"PRIu64"\n",
+			       ctx->samplerate);
+
+	/* Columns / channels */
+	g_string_append_printf(ctx->header, "; Channels (%d/%d): ",
+			       ctx->num_enabled_probes, num_probes);
+	for (l = o->sdi->probes; l; l = l->next) {
+		probe = l->data;
+		if (probe->enabled)
+			g_string_append_printf(ctx->header, "%s, ", probe->name);
+	}
+	g_string_append_printf(ctx->header, "\n");
+
+	return SR_OK;
+}
+
+static int event(struct sr_output *o, int event_type, uint8_t **data_out,
+		 uint64_t *length_out)
+{
+	struct context *ctx;
+
+	if (!o) {
+		sr_err("%s: o was NULL", __func__);
+		return SR_ERR_ARG;
+	}
+
+	if (!(ctx = o->internal)) {
+		sr_err("%s: o->internal was NULL", __func__);
+		return SR_ERR_ARG;
+	}
+
+	if (!data_out) {
+		sr_err("%s: data_out was NULL", __func__);
+		return SR_ERR_ARG;
+	}
+
+	switch (event_type) {
+	case SR_DF_TRIGGER:
+		sr_dbg("%s: SR_DF_TRIGGER event", __func__);
+		/* TODO */
+		*data_out = NULL;
+		*length_out = 0;
+		break;
+	case SR_DF_END:
+		sr_dbg("%s: SR_DF_END event", __func__);
+		/* TODO */
+		*data_out = NULL;
+		*length_out = 0;
+		g_free(o->internal);
+		o->internal = NULL;
+		break;
+	default:
+		sr_err("%s: unsupported event type: %d", __func__, event_type);
+		*data_out = NULL;
+		*length_out = 0;
+		break;
+	}
+
+	return SR_OK;
+}
+
+static int data(struct sr_output *o, const uint8_t *data_in,
+		uint64_t length_in, uint8_t **data_out, uint64_t *length_out)
+{
+	struct context *ctx;
+	GString *outstr;
+	uint64_t sample, i;
+	int j;
+
+	if (!o) {
+		sr_err("%s: o was NULL", __func__);
+		return SR_ERR_ARG;
+	}
+
+	if (!(ctx = o->internal)) {
+		sr_err("%s: o->internal was NULL", __func__);
+		return SR_ERR_ARG;
+	}
+
+	if (!data_in) {
+		sr_err("%s: data_in was NULL", __func__);
+		return SR_ERR_ARG;
+	}
+
+	if (ctx->header) {
+		/* First data packet. */
+		outstr = ctx->header;
+		ctx->header = NULL;
+	} else {
+		outstr = g_string_sized_new(512);
+	}
+
+	for (i = 0; i <= length_in - ctx->unitsize; i += ctx->unitsize) {
+		memcpy(&sample, data_in + i, ctx->unitsize);
+		for (j = ctx->num_enabled_probes - 1; j >= 0; j--) {
+			g_string_append_printf(outstr, "%d%c",
+				(int)((sample & (1 << j)) >> j),
+				ctx->separator);
+		}
+		g_string_append_printf(outstr, "\n");
+	}
+
+	*data_out = (uint8_t *)outstr->str;
+	*length_out = outstr->len;
+	g_string_free(outstr, FALSE);
+
+	return SR_OK;
+}
+
+SR_PRIV struct sr_output_format output_csv = {
+	.id = "csv",
+	.description = "Comma-separated values (CSV)",
+	.df_type = SR_DF_LOGIC,
+	.init = init,
+	.data = data,
+	.event = event,
+};
diff --git a/output/out_vcd.c b/output/out_vcd.c
new file mode 100644
index 0000000..04d7fcb
--- /dev/null
+++ b/output/out_vcd.c
@@ -0,0 +1,231 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include "config.h" /* Needed for PACKAGE and others. */
+#include "libsigrok.h"
+#include "libsigrok-internal.h"
+
+/* Message logging helpers with subsystem-specific prefix string. */
+#define LOG_PREFIX "output/vcd: "
+#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)
+
+struct context {
+	int num_enabled_probes;
+	GArray *probeindices;
+	GString *header;
+	uint8_t *prevsample;
+	int period;
+	uint64_t samplerate;
+	unsigned int unitsize;
+};
+
+static const char *vcd_header_comment = "\
+$comment\n  Acquisition with %d/%d probes at %s\n$end\n";
+
+static int init(struct sr_output *o)
+{
+	struct context *ctx;
+	struct sr_probe *probe;
+	GSList *l;
+	GVariant *gvar;
+	int num_probes, i;
+	char *samplerate_s, *frequency_s, *timestamp;
+	time_t t;
+
+	if (!(ctx = g_try_malloc0(sizeof(struct context)))) {
+		sr_err("%s: ctx malloc failed", __func__);
+		return SR_ERR_MALLOC;
+	}
+
+	o->internal = ctx;
+	ctx->num_enabled_probes = 0;
+	ctx->probeindices = g_array_new(FALSE, FALSE, sizeof(int));
+
+	for (l = o->sdi->probes; l; l = l->next) {
+		probe = l->data;
+		if (!probe->enabled)
+			continue;
+		ctx->probeindices = g_array_append_val(
+				ctx->probeindices, probe->index);
+		ctx->num_enabled_probes++;
+	}
+	if (ctx->num_enabled_probes > 94) {
+		sr_err("VCD only supports 94 probes.");
+		return SR_ERR;
+	}
+
+	ctx->unitsize = (ctx->num_enabled_probes + 7) / 8;
+	ctx->header = g_string_sized_new(512);
+	num_probes = g_slist_length(o->sdi->probes);
+
+	/* timestamp */
+	t = time(NULL);
+	timestamp = g_strdup(ctime(&t));
+	timestamp[strlen(timestamp)-1] = 0;
+	g_string_printf(ctx->header, "$date %s $end\n", timestamp);
+	g_free(timestamp);
+
+	/* generator */
+	g_string_append_printf(ctx->header, "$version %s %s $end\n",
+			PACKAGE, PACKAGE_VERSION);
+
+	if (sr_config_get(o->sdi->driver, SR_CONF_SAMPLERATE, &gvar,
+			o->sdi) == SR_OK) {
+		ctx->samplerate = g_variant_get_uint64(gvar);
+		g_variant_unref(gvar);
+		if (!((samplerate_s = sr_samplerate_string(ctx->samplerate)))) {
+			g_string_free(ctx->header, TRUE);
+			g_free(ctx);
+			return SR_ERR;
+		}
+		g_string_append_printf(ctx->header, vcd_header_comment,
+				 ctx->num_enabled_probes, num_probes, samplerate_s);
+		g_free(samplerate_s);
+	}
+
+	/* timescale */
+	/* VCD can only handle 1/10/100 (s - fs), so scale up first */
+	if (ctx->samplerate > SR_MHZ(1))
+		ctx->period = SR_GHZ(1);
+	else if (ctx->samplerate > SR_KHZ(1))
+		ctx->period = SR_MHZ(1);
+	else
+		ctx->period = SR_KHZ(1);
+	if (!(frequency_s = sr_period_string(ctx->period))) {
+		g_string_free(ctx->header, TRUE);
+		g_free(ctx);
+		return SR_ERR;
+	}
+	g_string_append_printf(ctx->header, "$timescale %s $end\n", frequency_s);
+	g_free(frequency_s);
+
+	/* scope */
+	g_string_append_printf(ctx->header, "$scope module %s $end\n", PACKAGE);
+
+	/* Wires / channels */
+	for (i = 0, l = o->sdi->probes; l; l = l->next, i++) {
+		probe = l->data;
+		if (!probe->enabled)
+			continue;
+		g_string_append_printf(ctx->header, "$var wire 1 %c %s $end\n",
+				(char)('!' + i), probe->name);
+	}
+
+	g_string_append(ctx->header, "$upscope $end\n"
+			"$enddefinitions $end\n$dumpvars\n");
+
+	if (!(ctx->prevsample = g_try_malloc0(ctx->unitsize))) {
+		g_string_free(ctx->header, TRUE);
+		g_free(ctx);
+		sr_err("%s: ctx->prevsample malloc failed", __func__);
+		return SR_ERR_MALLOC;
+	}
+
+	return SR_OK;
+}
+
+static int receive(struct sr_output *o, const struct sr_dev_inst *sdi,
+		const struct sr_datafeed_packet *packet, GString **out)
+{
+	const struct sr_datafeed_logic *logic;
+	struct context *ctx;
+	unsigned int i;
+	int p, curbit, prevbit, index;
+	uint8_t *sample;
+	static uint64_t samplecount = 0;
+
+	(void)sdi;
+
+	*out = NULL;
+	if (!o || !o->internal)
+		return SR_ERR_ARG;
+	ctx = o->internal;
+
+	if (packet->type == SR_DF_END) {
+		*out = g_string_new("$dumpoff\n$end\n");
+		return SR_OK;
+	} else if (packet->type != SR_DF_LOGIC)
+		return SR_OK;
+
+	if (ctx->header) {
+		/* The header is still here, this must be the first packet. */
+		*out = ctx->header;
+		ctx->header = NULL;
+	} else {
+		*out = g_string_sized_new(512);
+	}
+
+	logic = packet->payload;
+	for (i = 0; i <= logic->length - logic->unitsize; i += logic->unitsize) {
+		samplecount++;
+
+		sample = logic->data + i;
+
+		for (p = 0; p < ctx->num_enabled_probes; p++) {
+			index = g_array_index(ctx->probeindices, int, p);
+			curbit = (sample[p / 8] & (((uint8_t) 1) << index)) >> index;
+			prevbit = (ctx->prevsample[p / 8] & (((uint64_t) 1) << index)) >> index;
+
+			/* VCD only contains deltas/changes of signals. */
+			if (prevbit == curbit)
+				continue;
+
+			/* Output which signal changed to which value. */
+			g_string_append_printf(*out, "#%" PRIu64 "\n%i%c\n",
+					(uint64_t)(((float)samplecount / ctx->samplerate)
+					* ctx->period), curbit, (char)('!' + p));
+		}
+
+		memcpy(ctx->prevsample, sample, ctx->unitsize);
+	}
+
+	return SR_OK;
+}
+
+static int cleanup(struct sr_output *o)
+{
+	struct context *ctx;
+
+	if (!o || !o->internal)
+		return SR_ERR_ARG;
+
+	ctx = o->internal;
+	g_free(ctx);
+
+	return SR_OK;
+}
+
+struct sr_output_format output_vcd = {
+	.id = "vcd",
+	.description = "Value Change Dump (VCD)",
+	.df_type = SR_DF_LOGIC,
+	.init = init,
+	.receive = receive,
+	.cleanup = cleanup,
+};
diff --git a/output/output.c b/output/output.c
index a3e5dc7..62ce0c1 100644
--- a/output/output.c
+++ b/output/output.c
@@ -54,9 +54,7 @@
 extern SR_PRIV struct sr_output_format output_text_ascii;
 extern SR_PRIV struct sr_output_format output_binary;
 extern SR_PRIV struct sr_output_format output_vcd;
-extern SR_PRIV struct sr_output_format output_ols;
-extern SR_PRIV struct sr_output_format output_gnuplot;
-extern SR_PRIV struct sr_output_format output_chronovu_la8;
+
 extern SR_PRIV struct sr_output_format output_csv;
 extern SR_PRIV struct sr_output_format output_analog;
 /* extern SR_PRIV struct sr_output_format output_analog_gnuplot; */
@@ -68,9 +66,6 @@
 	&output_text_ascii,
 	&output_binary,
 	&output_vcd,
-	&output_ols,
-	&output_gnuplot,
-	&output_chronovu_la8,
 	&output_csv,
 	&output_analog,
 	/* &output_analog_gnuplot, */
diff --git a/output/text/Makefile.am b/output/text/Makefile.am
index 348892c..a6edae8 100644
--- a/output/text/Makefile.am
+++ b/output/text/Makefile.am
@@ -19,15 +19,15 @@
 ##
 
 # Local lib, this is NOT meant to be installed!
-noinst_LTLIBRARIES = libsigrokoutputtext.la
+noinst_LTLIBRARIES = libsigrok4DSLogicoutputtext.la
 
-libsigrokoutputtext_la_SOURCES = \
+libsigrok4DSLogicoutputtext_la_SOURCES = \
 	text.c \
 	text.h \
 	bits.c \
 	hex.c \
 	ascii.c
 
-libsigrokoutputtext_la_CFLAGS = \
+libsigrok4DSLogicoutputtext_la_CFLAGS = \
 	-I$(top_srcdir)
 
diff --git a/proto.h b/proto.h
index 821846f..322dc2d 100644
--- a/proto.h
+++ b/proto.h
@@ -103,11 +103,11 @@
 SR_API int sr_session_save(const char *filename, const struct sr_dev_inst *sdi,
 		unsigned char *buf, int unitsize, int units);
 SR_API int sr_session_source_add(int fd, int events, int timeout,
-		sr_receive_data_callback_t cb, void *cb_data);
+		sr_receive_data_callback_t cb, const struct sr_dev_inst *sdi);
 SR_API int sr_session_source_add_pollfd(GPollFD *pollfd, int timeout,
-		sr_receive_data_callback_t cb, void *cb_data);
+		sr_receive_data_callback_t cb, const struct sr_dev_inst *sdi);
 SR_API int sr_session_source_add_channel(GIOChannel *channel, int events,
-		int timeout, sr_receive_data_callback_t cb, void *cb_data);
+		int timeout, sr_receive_data_callback_t cb, const struct sr_dev_inst *sdi);
 SR_API int sr_session_source_remove(int fd);
 SR_API int sr_session_source_remove_pollfd(GPollFD *pollfd);
 SR_API int sr_session_source_remove_channel(GIOChannel *channel);
@@ -151,4 +151,29 @@
 SR_API const char *sr_strerror(int error_code);
 SR_API const char *sr_strerror_name(int error_code);
 
+/*--- libusbhp.c ------------------------------------------------------------*/
+SR_API int libusbhp_init(struct libusbhp_t **handle);
+
+SR_API void libusbhp_exit(struct libusbhp_t *handle);
+
+SR_API int libusbhp_handle_events_timeout(struct libusbhp_t *handle, struct timeval *tv);
+
+SR_API void libusbhp_register_hotplug_listeners(struct libusbhp_t *handle,
+                                        libusbhp_hotplug_cb_fn connected_cb,
+                                        libusbhp_hotplug_cb_fn disconnected_cb,
+                                        void *user_data);
+
+/*--- trigger.c ------------------------------------------------------------*/
+SR_API int ds_trigger_init(void);
+SR_API int ds_trigger_destroy(void);
+SR_API int ds_trigger_stage_set_value(uint16_t stage, uint16_t probes, char *trigger0, char *trigger1);
+SR_API int ds_trigger_stage_set_logic(uint16_t stage, uint16_t probes, unsigned char trigger_logic);
+SR_API int ds_trigger_stage_set_inv(uint16_t stage, uint16_t probes, unsigned char trigger0_inv, unsigned char trigger1_inv);
+SR_API int ds_trigger_stage_set_count(uint16_t stage, uint16_t probes, uint16_t trigger0_count, uint16_t trigger1_count);
+SR_API int ds_trigger_probe_set(uint16_t probe, unsigned char trigger0, unsigned char trigger1);
+SR_API int ds_trigger_set_stage(uint16_t stages);
+SR_API int ds_trigger_set_pos(uint16_t position);
+SR_API int ds_trigger_set_en(uint16_t enable);
+SR_API int ds_trigger_set_mode(uint16_t mode);
+
 #endif
diff --git a/session.c b/session.c
index 4fa5daf..29e1908 100644
--- a/session.c
+++ b/session.c
@@ -85,7 +85,7 @@
 
 	session->source_timeout = -1;
 	session->abort_session = FALSE;
-	g_mutex_init(&session->stop_mutex);
+//	g_mutex_init(&session->stop_mutex);
 
 	return session;
 }
@@ -106,9 +106,21 @@
 
 	sr_session_dev_remove_all();
 
+    sr_session_datafeed_callback_remove_all();
+
+    if (session->sources) {
+        g_free(session->sources);
+        session->sources = NULL;
+    }
+
+    if (session->pollfds) {
+        g_free(session->pollfds);
+        session->pollfds = NULL;
+    }
+
 	/* TODO: Error checks needed? */
 
-	g_mutex_clear(&session->stop_mutex);
+//	g_mutex_clear(&session->stop_mutex);
 
 	g_free(session);
 	session = NULL;
@@ -259,13 +271,13 @@
 			 * we check the flag after processing every source, not
 			 * just once per main event loop.
 			 */
-			g_mutex_lock(&session->stop_mutex);
+//			g_mutex_lock(&session->stop_mutex);
 			if (session->abort_session) {
 				sr_session_stop_sync();
 				/* But once is enough. */
 				session->abort_session = FALSE;
 			}
-			g_mutex_unlock(&session->stop_mutex);
+//			g_mutex_unlock(&session->stop_mutex);
 		}
 	}
 
@@ -376,7 +388,7 @@
 		sdi = l->data;
 		if (sdi->driver) {
 			if (sdi->driver->dev_acquisition_stop)
-				sdi->driver->dev_acquisition_stop(sdi, sdi);
+                sdi->driver->dev_acquisition_stop(sdi, NULL);
 		}
 	}
 
@@ -403,9 +415,9 @@
 		return SR_ERR_BUG;
 	}
 
-	g_mutex_lock(&session->stop_mutex);
+//	g_mutex_lock(&session->stop_mutex);
 	session->abort_session = TRUE;
-	g_mutex_unlock(&session->stop_mutex);
+//	g_mutex_unlock(&session->stop_mutex);
 
 	return SR_OK;
 }
@@ -506,7 +518,7 @@
  *         SR_ERR_MALLOC upon memory allocation errors.
  */
 static int _sr_session_source_add(GPollFD *pollfd, int timeout,
-	sr_receive_data_callback_t cb, void *cb_data, gintptr poll_object)
+    sr_receive_data_callback_t cb, const struct sr_dev_inst *sdi, gintptr poll_object)
 {
 	struct source *new_sources, *s;
 	GPollFD *new_pollfds;
@@ -536,7 +548,7 @@
 	s = &new_sources[session->num_sources++];
 	s->timeout = timeout;
 	s->cb = cb;
-	s->cb_data = cb_data;
+	s->cb_data = sdi;
 	s->poll_object = poll_object;
 	session->pollfds = new_pollfds;
 	session->sources = new_sources;
@@ -561,14 +573,14 @@
  *         SR_ERR_MALLOC upon memory allocation errors.
  */
 SR_API int sr_session_source_add(int fd, int events, int timeout,
-		sr_receive_data_callback_t cb, void *cb_data)
+		sr_receive_data_callback_t cb, const struct sr_dev_inst *sdi)
 {
 	GPollFD p;
 
 	p.fd = fd;
 	p.events = events;
 
-	return _sr_session_source_add(&p, timeout, cb, cb_data, (gintptr)fd);
+    return _sr_session_source_add(&p, timeout, cb, sdi, (gintptr)fd);
 }
 
 /**
@@ -583,10 +595,10 @@
  *         SR_ERR_MALLOC upon memory allocation errors.
  */
 SR_API int sr_session_source_add_pollfd(GPollFD *pollfd, int timeout,
-		sr_receive_data_callback_t cb, void *cb_data)
+		sr_receive_data_callback_t cb, const struct sr_dev_inst *sdi)
 {
-	return _sr_session_source_add(pollfd, timeout, cb,
-				      cb_data, (gintptr)pollfd);
+    return _sr_session_source_add(pollfd, timeout, cb,
+                      sdi, (gintptr)pollfd);
 }
 
 /**
@@ -602,7 +614,7 @@
  *         SR_ERR_MALLOC upon memory allocation errors.
  */
 SR_API int sr_session_source_add_channel(GIOChannel *channel, int events,
-		int timeout, sr_receive_data_callback_t cb, void *cb_data)
+		int timeout, sr_receive_data_callback_t cb, const struct sr_dev_inst *sdi)
 {
 	GPollFD p;
 
@@ -613,7 +625,7 @@
 	p.events = events;
 #endif
 
-	return _sr_session_source_add(&p, timeout, cb, cb_data, (gintptr)channel);
+    return _sr_session_source_add(&p, timeout, cb, sdi, (gintptr)channel);
 }
 
 /**
diff --git a/session_driver.c b/session_driver.c
index 9df848d..b040c07 100644
--- a/session_driver.c
+++ b/session_driver.c
@@ -47,6 +47,7 @@
 	struct zip_file *capfile;
 	int bytes_read;
 	uint64_t samplerate;
+    uint64_t total_samples;
 	int unitsize;
 	int num_probes;
 };
@@ -58,7 +59,7 @@
 	0,
 };
 
-static int receive_data(int fd, int revents, void *cb_data)
+static int receive_data(int fd, int revents, const struct sr_dev_inst *cb_sdi)
 {
 	struct sr_dev_inst *sdi;
 	struct session_vdev *vdev;
@@ -95,7 +96,7 @@
 			logic.unitsize = vdev->unitsize;
 			logic.data = buf;
 			vdev->bytes_read += ret;
-			sr_session_send(cb_data, &packet);
+			sr_session_send(cb_sdi, &packet);
 		} else {
 			/* done with this capture file */
 			zip_fclose(vdev->capfile);
@@ -107,7 +108,7 @@
 
 	if (!got_data) {
 		packet.type = SR_DF_END;
-		sr_session_send(cb_data, &packet);
+		sr_session_send(cb_sdi, &packet);
 		sr_session_source_remove(-1);
 	}
 
@@ -160,6 +161,13 @@
 		} else
 			return SR_ERR;
 		break;
+    case SR_CONF_LIMIT_SAMPLES:
+        if (sdi) {
+            vdev = sdi->priv;
+            *data = g_variant_new_uint64(vdev->total_samples);
+        } else
+            return SR_ERR;
+        break;
 	default:
 		return SR_ERR_ARG;
 	}
@@ -189,6 +197,9 @@
 	case SR_CONF_CAPTURE_UNITSIZE:
 		vdev->unitsize = g_variant_get_uint64(data);
 		break;
+    case SR_CONF_LIMIT_SAMPLES:
+        vdev->total_samples = g_variant_get_uint64(data);
+        break;
 	case SR_CONF_CAPTURE_NUM_PROBES:
 		vdev->num_probes = g_variant_get_uint64(data);
 		break;
@@ -207,8 +218,10 @@
 
 	switch (key) {
 	case SR_CONF_DEVICE_OPTIONS:
-		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
-				hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
+//		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
+//				hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
+		*data = g_variant_new_from_data(G_VARIANT_TYPE("ai"),
+				hwcaps, ARRAY_SIZE(hwcaps)*sizeof(int32_t), TRUE, NULL, NULL);
 		break;
 	default:
 		return SR_ERR_ARG;
@@ -248,10 +261,10 @@
 	}
 
 	/* Send header packet to the session bus. */
-	std_session_send_df_header(cb_data, LOG_PREFIX);
+    std_session_send_df_header(sdi, LOG_PREFIX);
 
 	/* freewheeling source */
-	sr_session_source_add(-1, 0, 0, receive_data, cb_data);
+    sr_session_source_add(-1, 0, 0, receive_data, sdi);
 
 	return SR_OK;
 }
diff --git a/session_file.c b/session_file.c
index 4838a6b..43ba01c 100644
--- a/session_file.c
+++ b/session_file.c
@@ -84,27 +84,9 @@
 		return SR_ERR;
 	}
 
-	/* check "version" */
-	version = 0;
-	if (!(zf = zip_fopen(archive, "version", 0))) {
-		sr_dbg("Not a sigrok session file.");
-		return SR_ERR;
-	}
-	if ((ret = zip_fread(zf, s, 10)) == -1) {
-		sr_dbg("Not a valid sigrok session file.");
-		return SR_ERR;
-	}
-	zip_fclose(zf);
-	s[ret] = 0;
-	version = strtoull(s, NULL, 10);
-	if (version != 1) {
-		sr_dbg("Not a valid sigrok session file version.");
-		return SR_ERR;
-	}
-
 	/* read "metadata" */
-	if (zip_stat(archive, "metadata", 0, &zs) == -1) {
-		sr_dbg("Not a valid sigrok session file.");
+    if (zip_stat(archive, "header", 0, &zs) == -1) {
+        sr_dbg("Not a valid DSLogic session file.");
 		return SR_ERR;
 	}
 
@@ -129,10 +111,10 @@
 	capturefiles = g_ptr_array_new_with_free_func(g_free);
 	sections = g_key_file_get_groups(kf, NULL);
 	for (i = 0; sections[i]; i++) {
-		if (!strcmp(sections[i], "global"))
+        if (!strcmp(sections[i], "version"))
 			/* nothing really interesting in here yet */
 			continue;
-		if (!strncmp(sections[i], "device ", 7)) {
+        if (!strncmp(sections[i], "header", 6)) {
 			/* device section */
 			sdi = NULL;
 			enabled_probes = total_probes = 0;
@@ -140,7 +122,7 @@
 			for (j = 0; keys[j]; j++) {
 				val = g_key_file_get_string(kf, sections[i], keys[j], NULL);
 				if (!strcmp(keys[j], "capturefile")) {
-					sdi = sr_dev_inst_new(devcnt, SR_ST_ACTIVE, NULL, NULL, NULL);
+                    sdi = sr_dev_inst_new(LOGIC, devcnt, SR_ST_ACTIVE, NULL, NULL, NULL);
 					sdi->driver = &session_driver;
 					if (devcnt == 0)
 						/* first device, init the driver */
@@ -160,6 +142,10 @@
 					tmp_u64 = strtoull(val, NULL, 10);
 					sdi->driver->config_set(SR_CONF_CAPTURE_UNITSIZE,
 							g_variant_new_uint64(tmp_u64), sdi);
+                } else if (!strcmp(keys[j], "total samples")) {
+                    tmp_u64 = strtoull(val, NULL, 10);
+                    sdi->driver->config_set(SR_CONF_LIMIT_SAMPLES,
+                            g_variant_new_uint64(tmp_u64), sdi);
 				} else if (!strcmp(keys[j], "total probes")) {
 					total_probes = strtoull(val, NULL, 10);
 					sdi->driver->config_set(SR_CONF_CAPTURE_NUM_PROBES,
@@ -213,15 +199,15 @@
 SR_API int sr_session_save(const char *filename, const struct sr_dev_inst *sdi,
 		unsigned char *buf, int unitsize, int units)
 {
-	GSList *l;
-	GVariant *gvar;
-	FILE *meta;
-	struct sr_probe *probe;
-	struct zip *zipfile;
-	struct zip_source *versrc, *metasrc, *logicsrc;
-	int tmpfile, ret, probecnt;
-	uint64_t samplerate;
-	char version[1], rawname[16], metafile[32], *s;
+    GSList *l;
+    GVariant *gvar;
+    FILE *meta;
+    struct sr_probe *probe;
+    struct zip *zipfile;
+    struct zip_source *versrc, *metasrc, *logicsrc;
+    int tmpfile, ret, probecnt;
+    uint64_t samplerate;
+    char rawname[16], metafile[32], *s;
 
 	if (!filename) {
 		sr_err("%s: filename was NULL", __func__);
@@ -233,77 +219,68 @@
 	if (!(zipfile = zip_open(filename, ZIP_CREATE, &ret)))
 		return SR_ERR;
 
-	/* "version" */
-	version[0] = '1';
-	if (!(versrc = zip_source_buffer(zipfile, version, 1, 0)))
-		return SR_ERR;
-	if (zip_add(zipfile, "version", versrc) == -1) {
-		sr_info("error saving version into zipfile: %s",
-			zip_strerror(zipfile));
-		return SR_ERR;
-	}
+    /* init "metadata" */
+    strcpy(metafile, "DSLogic-meta-XXXXXX");
+    if ((tmpfile = g_mkstemp(metafile)) == -1)
+        return SR_ERR;
+    close(tmpfile);
+    meta = g_fopen(metafile, "wb");
+    fprintf(meta, "[version]\n");
+    fprintf(meta, "DSLogic version = %s\n", PACKAGE_VERSION);
 
-	/* init "metadata" */
-	strcpy(metafile, "sigrok-meta-XXXXXX");
-	if ((tmpfile = g_mkstemp(metafile)) == -1)
-		return SR_ERR;
-	close(tmpfile);
-	meta = g_fopen(metafile, "wb");
-	fprintf(meta, "[global]\n");
-	fprintf(meta, "sigrok version = %s\n", PACKAGE_VERSION);
+    /* metadata */
+    fprintf(meta, "[header]\n");
+    if (sdi->driver)
+        fprintf(meta, "driver = %s\n", sdi->driver->name);
 
-	/* metadata */
-	fprintf(meta, "[device 1]\n");
-	if (sdi->driver)
-		fprintf(meta, "driver = %s\n", sdi->driver->name);
+    /* metadata */
+    fprintf(meta, "capturefile = data\n");
+    fprintf(meta, "unitsize = %d\n", unitsize);
+    fprintf(meta, "total samples = %d\n", units);
+    fprintf(meta, "total probes = %d\n", g_slist_length(sdi->probes));
+    if (sr_dev_has_option(sdi, SR_CONF_SAMPLERATE)) {
+        if (sr_config_get(sdi->driver, SR_CONF_SAMPLERATE,
+                &gvar, sdi) == SR_OK) {
+            samplerate = g_variant_get_uint64(gvar);
+            s = sr_samplerate_string(samplerate);
+            fprintf(meta, "samplerate = %s\n", s);
+            g_free(s);
+            g_variant_unref(gvar);
+        }
+    }
+    probecnt = 1;
+    for (l = sdi->probes; l; l = l->next) {
+        probe = l->data;
+        if (probe->enabled) {
+            if (probe->name)
+                fprintf(meta, "probe%d = %s\n", probecnt, probe->name);
+            if (probe->trigger)
+                fprintf(meta, " trigger%d = %s\n", probecnt, probe->trigger);
+            probecnt++;
+        }
+    }
 
-	/* metadata */
-	fprintf(meta, "capturefile = logic-1\n");
-	fprintf(meta, "unitsize = %d\n", unitsize);
-	fprintf(meta, "total probes = %d\n", g_slist_length(sdi->probes));
-	if (sr_dev_has_option(sdi, SR_CONF_SAMPLERATE)) {
-		if (sr_config_get(sdi->driver, SR_CONF_SAMPLERATE,
-				&gvar, sdi) == SR_OK) {
-			samplerate = g_variant_get_uint64(gvar);
-			s = sr_samplerate_string(samplerate);
-			fprintf(meta, "samplerate = %s\n", s);
-			g_free(s);
-			g_variant_unref(gvar);
-		}
-	}
-	probecnt = 1;
-	for (l = sdi->probes; l; l = l->next) {
-		probe = l->data;
-		if (probe->enabled) {
-			if (probe->name)
-				fprintf(meta, "probe%d = %s\n", probecnt, probe->name);
-			if (probe->trigger)
-				fprintf(meta, " trigger%d = %s\n", probecnt, probe->trigger);
-			probecnt++;
-		}
-	}
+    if (!(logicsrc = zip_source_buffer(zipfile, buf,
+               units * unitsize, FALSE)))
+        return SR_ERR;
+    snprintf(rawname, 15, "data");
+    if (zip_add(zipfile, rawname, logicsrc) == -1)
+        return SR_ERR;
+    fclose(meta);
 
-	if (!(logicsrc = zip_source_buffer(zipfile, buf,
-			   units * unitsize, FALSE)))
-		return SR_ERR;
-	snprintf(rawname, 15, "logic-1");
-	if (zip_add(zipfile, rawname, logicsrc) == -1)
-		return SR_ERR;
-	fclose(meta);
+    if (!(metasrc = zip_source_file(zipfile, metafile, 0, -1)))
+        return SR_ERR;
+    if (zip_add(zipfile, "header", metasrc) == -1)
+        return SR_ERR;
 
-	if (!(metasrc = zip_source_file(zipfile, metafile, 0, -1)))
-		return SR_ERR;
-	if (zip_add(zipfile, "metadata", metasrc) == -1)
-		return SR_ERR;
+    if ((ret = zip_close(zipfile)) == -1) {
+        sr_info("error saving zipfile: %s", zip_strerror(zipfile));
+        return SR_ERR;
+    }
 
-	if ((ret = zip_close(zipfile)) == -1) {
-		sr_info("error saving zipfile: %s", zip_strerror(zipfile));
-		return SR_ERR;
-	}
+    unlink(metafile);
 
-	unlink(metafile);
-
-	return SR_OK;
+    return SR_OK;
 }
 
 /** @} */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 6c8a860..25f9438 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -35,6 +35,6 @@
 
 check_main_CFLAGS = @check_CFLAGS@
 
-check_main_LDADD = $(top_builddir)/libsigrok.la @check_LIBS@
+check_main_LDADD = $(top_builddir)/libsigrok4DSLogic.la @check_LIBS@
 
 endif
diff --git a/trigger.c b/trigger.c
new file mode 100644
index 0000000..d8a2aae
--- /dev/null
+++ b/trigger.c
@@ -0,0 +1,291 @@
+/*
+ * This file is part of the DSLogic project.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <assert.h>
+#include <glib.h>
+#include "libsigrok.h"
+#include "libsigrok-internal.h"
+
+/* Message logging helpers with subsystem-specific prefix string. */
+#define LOG_PREFIX "session: "
+#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)
+
+/**
+ * @file
+ *
+ * init, set DSLogic trigger.
+ */
+
+/**
+ * @defgroup Trigger handling
+ *
+ * init, set DSLogic trigger
+ *
+ * @{
+ */
+
+struct ds_trigger *trigger;
+
+/**
+ * recovery trigger to initial status.
+ *
+ * @return SR_OK upon success.
+ */
+SR_API int ds_trigger_init(void)
+{
+    int i, j;
+
+    if (!(trigger = g_try_malloc0(sizeof(struct ds_trigger)))) {
+        sr_err("Trigger malloc failed.");
+        return SR_ERR_MALLOC;
+    }
+
+    trigger->trigger_en = 0;
+    trigger->trigger_mode = SIMPLE_TRIGGER;
+    trigger->trigger_pos = 0;
+    trigger->trigger_stages = 0;
+
+    for (i = 0; i <= TriggerStages; i++) {
+        for (j = 0; j < TriggerProbes; j++) {
+            trigger->trigger0[i][j] = 'X';
+            trigger->trigger1[i][j] = 'X';
+        }
+        trigger->trigger0_count[i] = 0;
+        trigger->trigger1_count[i] = 0;
+        trigger->trigger0_inv[i] = 0;
+        trigger->trigger1_inv[i] = 0;
+        trigger->trigger_logic[i] = 1;
+    }
+
+
+    return SR_OK;
+}
+
+SR_API int ds_trigger_destroy(void)
+{
+    if (trigger)
+        g_free(trigger);
+
+    return SR_OK;
+}
+
+/**
+ * set trigger based on stage
+ *
+ * @return SR_OK upon success.
+ */
+SR_API int ds_trigger_stage_set_value(uint16_t stage, uint16_t probes, char *trigger0, char *trigger1)
+{
+    assert(stage < TriggerStages);
+    assert(probes <= TriggerProbes);
+
+    int j;
+
+    for (j = 0; j< probes; j++) {
+        trigger->trigger0[stage][probes - j - 1] = *(trigger0 + j * 2);
+        trigger->trigger1[stage][probes - j - 1] = *(trigger1 + j * 2);
+    }
+
+    return SR_OK;
+}
+SR_API int ds_trigger_stage_set_logic(uint16_t stage, uint16_t probes, unsigned char trigger_logic)
+{
+    assert(stage < TriggerStages);
+    assert(probes <= TriggerProbes);
+
+    trigger->trigger_logic[stage] = trigger_logic;
+
+    return SR_OK;
+}
+SR_API int ds_trigger_stage_set_inv(uint16_t stage, uint16_t probes, unsigned char trigger0_inv, unsigned char trigger1_inv)
+{
+    assert(stage < TriggerStages);
+    assert(probes <= TriggerProbes);
+
+    trigger->trigger0_inv[stage] = trigger0_inv;
+    trigger->trigger1_inv[stage] = trigger1_inv;
+
+    return SR_OK;
+}
+SR_API int ds_trigger_stage_set_count(uint16_t stage, uint16_t probes, uint16_t trigger0_count, uint16_t trigger1_count)
+{
+    assert(stage < TriggerStages);
+    assert(probes <= TriggerProbes);
+
+    trigger->trigger0_count[stage] = trigger0_count;
+    trigger->trigger1_count[stage] = trigger1_count;
+
+    return SR_OK;
+}
+
+/**
+ * set trigger based on probe
+ *
+ * @return SR_OK upon success.
+ */
+SR_API int ds_trigger_probe_set(uint16_t probe, unsigned char trigger0, unsigned char trigger1)
+{
+    assert(probe < TriggerProbes);
+
+    trigger->trigger0[TriggerStages][probe] = trigger0;
+    trigger->trigger1[TriggerStages][probe] = trigger1;
+
+    return SR_OK;
+}
+
+/**
+ * set trigger stage
+ *
+ * @return SR_OK upon success.
+ */
+SR_API int ds_trigger_set_stage(uint16_t stages)
+{
+    assert(stages <= TriggerStages);
+
+    trigger->trigger_stages = stages;
+
+    return SR_OK;
+}
+
+/**
+ * set trigger position
+ *
+ * @return SR_OK upon success.
+ */
+SR_API int ds_trigger_set_pos(uint16_t position)
+{
+    assert(position <= 100);
+    assert(position >= 0);
+
+    trigger->trigger_pos = position;
+
+    return SR_OK;
+}
+
+/**
+ * set trigger en
+ *
+ * @return SR_OK upon success.
+ */
+SR_API int ds_trigger_set_en(uint16_t enable)
+{
+
+    trigger->trigger_en = enable;
+
+    return SR_OK;
+}
+
+/**
+ * set trigger mode
+ *
+ * @return SR_OK upon success.
+ */
+SR_API int ds_trigger_set_mode(uint16_t mode)
+{
+
+    trigger->trigger_mode = mode;
+
+    return SR_OK;
+}
+
+/*
+ *
+ */
+SR_PRIV uint64_t ds_trigger_get_mask0(uint16_t stage)
+{
+    assert(stage <= TriggerStages);
+
+    uint64_t mask = 0;
+    int i;
+
+    for (i = TriggerProbes - 1; i >= 0 ; i--) {
+        mask = (mask << 1);
+        mask += (trigger->trigger0[stage][i] == 'X' | trigger->trigger0[stage][i] == 'C');
+    }
+
+    return mask;
+}
+SR_PRIV uint64_t ds_trigger_get_mask1(uint16_t stage)
+{
+    assert(stage <= TriggerStages);
+
+    uint64_t mask = 0;
+    int i;
+
+    for (i = TriggerProbes - 1; i >= 0 ; i--) {
+        mask = (mask << 1);
+        mask += (trigger->trigger1[stage][i] == 'X' | trigger->trigger1[stage][i] == 'C');
+    }
+
+    return mask;
+}
+SR_PRIV uint64_t ds_trigger_get_value0(uint16_t stage)
+{
+    assert(stage <= TriggerStages);
+
+    uint64_t value = 0;
+    int i;
+
+    for (i = TriggerProbes - 1; i >= 0 ; i--) {
+        value = (value << 1);
+        value += (trigger->trigger0[stage][i] == '1' | trigger->trigger0[stage][i] == 'R');
+    }
+
+    return value;
+}
+SR_PRIV uint64_t ds_trigger_get_value1(uint16_t stage)
+{
+    assert(stage <= TriggerStages);
+
+    uint64_t value = 0;
+    int i;
+
+    for (i = TriggerProbes - 1; i >= 0 ; i--) {
+        value = (value << 1);
+        value += (trigger->trigger1[stage][i] == '1' | trigger->trigger1[stage][i] == 'R');
+    }
+
+    return value;
+}
+SR_PRIV uint64_t ds_trigger_get_edge0(uint16_t stage)
+{
+    assert(stage <= TriggerStages);
+
+    uint64_t edge = 0;
+    int i;
+
+    for (i = TriggerProbes - 1; i >= 0 ; i--) {
+        edge = (edge << 1);
+        edge += (trigger->trigger0[stage][i] == 'R' | trigger->trigger0[stage][i] == 'F' |
+                 trigger->trigger0[stage][i] == 'C');
+    }
+
+    return edge;
+}
+SR_PRIV uint64_t ds_trigger_get_edge1(uint16_t stage)
+{
+    assert(stage <= TriggerStages);
+
+    uint64_t edge = 0;
+    int i;
+
+    for (i = TriggerProbes - 1; i >= 0 ; i--) {
+        edge = (edge << 1);
+        edge += (trigger->trigger1[stage][i] == 'R' | trigger->trigger1[stage][i] == 'F' |
+                 trigger->trigger1[stage][i] == 'C');
+    }
+
+    return edge;
+}
+
+/** @} */