From: Bert Vermeulen Date: Mon, 21 Jul 2014 19:27:33 +0000 (+0200) Subject: Reorganize project tree. X-Git-Tag: libsigrok-0.4.0~1225 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=155b680da482cea2381becb73c51cfb838bff31e;p=libsigrok.git Reorganize project tree. --- diff --git a/Makefile.am b/Makefile.am index 72f97969..3a485e0a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,318 +20,318 @@ ACLOCAL_AMFLAGS = -I autostuff -AM_CPPFLAGS = -DFIRMWARE_DIR='"$(FIRMWARE_DIR)"' +AM_CPPFLAGS = -Isrc -DFIRMWARE_DIR='"$(FIRMWARE_DIR)"' lib_LTLIBRARIES = libsigrok.la # Backend files libsigrok_la_SOURCES = \ - backend.c \ - device.c \ - session.c \ - session_file.c \ - session_driver.c \ - drivers.c \ - hwdriver.c \ - trigger.c \ - soft-trigger.c \ - strutil.c \ - log.c \ - version.c \ - error.c \ - std.c - -# Input formats -libsigrok_la_SOURCES += \ - input/binary.c \ - input/chronovu_la8.c \ - input/csv.c \ - input/input.c \ - input/vcd.c \ - input/wav.c - -# Output formats -libsigrok_la_SOURCES += \ - output/output.c \ - output/analog.c \ - output/ascii.c \ - output/bits.c \ - output/binary.c \ - output/csv.c \ - output/chronovu_la8.c \ - output/gnuplot.c \ - output/hex.c \ - output/ols.c \ - output/vcd.c - -# Hardware (common files) -libsigrok_la_SOURCES += \ - hardware/common/scpi.c \ - hardware/common/scpi_tcp.c + src/backend.c \ + src/device.c \ + src/session.c \ + src/session_file.c \ + src/session_driver.c \ + src/drivers.c \ + src/hwdriver.c \ + src/trigger.c \ + src/soft-trigger.c \ + src/strutil.c \ + src/log.c \ + src/version.c \ + src/error.c \ + src/std.c + +# Input modules +libsigrok_la_SOURCES += \ + src/input/binary.c \ + src/input/chronovu_la8.c \ + src/input/csv.c \ + src/input/input.c \ + src/input/vcd.c \ + src/input/wav.c + +# Output modules +libsigrok_la_SOURCES += \ + src/output/output.c \ + src/output/analog.c \ + src/output/ascii.c \ + src/output/bits.c \ + src/output/binary.c \ + src/output/csv.c \ + src/output/chronovu_la8.c \ + src/output/gnuplot.c \ + src/output/hex.c \ + src/output/ols.c \ + src/output/vcd.c + +# SCPI support +libsigrok_la_SOURCES += \ + src/scpi/scpi.c \ + src/scpi/scpi_tcp.c if NEED_RPC libsigrok_la_SOURCES += \ - hardware/common/scpi_vxi.c \ - hardware/common/vxi_clnt.c \ - hardware/common/vxi_xdr.c \ - hardware/common/vxi.h + src/scpi/scpi_vxi.c \ + src/scpi/vxi_clnt.c \ + src/scpi/vxi_xdr.c \ + src/scpi/vxi.h endif if NEED_SERIAL libsigrok_la_SOURCES += \ - hardware/common/serial.c \ - hardware/common/scpi_serial.c + src/serial.c \ + src/scpi/scpi_serial.c endif if NEED_USB libsigrok_la_SOURCES += \ - hardware/common/ezusb.c \ - hardware/common/usb.c \ - hardware/common/scpi_usbtmc_libusb.c + src/ezusb.c \ + src/usb.c \ + src/scpi/scpi_usbtmc_libusb.c endif if NEED_VISA libsigrok_la_SOURCES += \ - hardware/common/scpi_visa.c + src/scpi/scpi_visa.c endif -# Hardware (DMM parsers) +# Hardware (DMM chip parsers) libsigrok_la_SOURCES += \ - hardware/common/dmm/es519xx.c \ - hardware/common/dmm/fs9721.c \ - hardware/common/dmm/fs9922.c \ - hardware/common/dmm/m2110.c \ - hardware/common/dmm/metex14.c \ - hardware/common/dmm/rs9lcd.c + src/dmm/es519xx.c \ + src/dmm/fs9721.c \ + src/dmm/fs9922.c \ + src/dmm/m2110.c \ + src/dmm/metex14.c \ + src/dmm/rs9lcd.c # Hardware drivers if HW_AGILENT_DMM libsigrok_la_SOURCES += \ - hardware/agilent-dmm/api.c \ - hardware/agilent-dmm/agilent-dmm.h \ - hardware/agilent-dmm/sched.c + src/hardware/agilent-dmm/api.c \ + src/hardware/agilent-dmm/agilent-dmm.h \ + src/hardware/agilent-dmm/sched.c endif if HW_APPA_55II libsigrok_la_SOURCES += \ - hardware/appa-55ii/protocol.h \ - hardware/appa-55ii/protocol.c \ - hardware/appa-55ii/api.c + src/hardware/appa-55ii/protocol.h \ + src/hardware/appa-55ii/protocol.c \ + src/hardware/appa-55ii/api.c endif if HW_ASIX_SIGMA libsigrok_la_SOURCES += \ - hardware/asix-sigma/asix-sigma.h \ - hardware/asix-sigma/asix-sigma.c + src/hardware/asix-sigma/asix-sigma.h \ + src/hardware/asix-sigma/asix-sigma.c endif if HW_ATTEN_PPS3XXX libsigrok_la_SOURCES += \ - hardware/atten-pps3xxx/protocol.h \ - hardware/atten-pps3xxx/protocol.c \ - hardware/atten-pps3xxx/api.c + src/hardware/atten-pps3xxx/protocol.h \ + src/hardware/atten-pps3xxx/protocol.c \ + src/hardware/atten-pps3xxx/api.c endif if HW_BEAGLELOGIC libsigrok_la_SOURCES += \ - hardware/beaglelogic/protocol.h \ - hardware/beaglelogic/protocol.c \ - hardware/beaglelogic/api.c + src/hardware/beaglelogic/protocol.h \ + src/hardware/beaglelogic/protocol.c \ + src/hardware/beaglelogic/api.c endif if HW_BRYMEN_BM86X libsigrok_la_SOURCES += \ - hardware/brymen-bm86x/protocol.h \ - hardware/brymen-bm86x/protocol.c \ - hardware/brymen-bm86x/api.c + src/hardware/brymen-bm86x/protocol.h \ + src/hardware/brymen-bm86x/protocol.c \ + src/hardware/brymen-bm86x/api.c endif if HW_BRYMEN_DMM libsigrok_la_SOURCES += \ - hardware/brymen-dmm/parser.c \ - hardware/brymen-dmm/protocol.h \ - hardware/brymen-dmm/protocol.c \ - hardware/brymen-dmm/api.c + src/hardware/brymen-dmm/parser.c \ + src/hardware/brymen-dmm/protocol.h \ + src/hardware/brymen-dmm/protocol.c \ + src/hardware/brymen-dmm/api.c endif if HW_CEM_DT_885X libsigrok_la_SOURCES += \ - hardware/cem-dt-885x/protocol.h \ - hardware/cem-dt-885x/protocol.c \ - hardware/cem-dt-885x/api.c + src/hardware/cem-dt-885x/protocol.h \ + src/hardware/cem-dt-885x/protocol.c \ + src/hardware/cem-dt-885x/api.c endif if HW_CENTER_3XX libsigrok_la_SOURCES += \ - hardware/center-3xx/protocol.h \ - hardware/center-3xx/protocol.c \ - hardware/center-3xx/api.c + src/hardware/center-3xx/protocol.h \ + src/hardware/center-3xx/protocol.c \ + src/hardware/center-3xx/api.c endif if HW_CHRONOVU_LA libsigrok_la_SOURCES += \ - hardware/chronovu-la/protocol.h \ - hardware/chronovu-la/protocol.c \ - hardware/chronovu-la/api.c + src/hardware/chronovu-la/protocol.h \ + src/hardware/chronovu-la/protocol.c \ + src/hardware/chronovu-la/api.c endif if HW_COLEAD_SLM libsigrok_la_SOURCES += \ - hardware/colead-slm/protocol.h \ - hardware/colead-slm/protocol.c \ - hardware/colead-slm/api.c + src/hardware/colead-slm/protocol.h \ + src/hardware/colead-slm/protocol.c \ + src/hardware/colead-slm/api.c endif if HW_CONRAD_DIGI_35_CPU libsigrok_la_SOURCES += \ - hardware/conrad-digi-35-cpu/protocol.h \ - hardware/conrad-digi-35-cpu/protocol.c \ - hardware/conrad-digi-35-cpu/api.c + src/hardware/conrad-digi-35-cpu/protocol.h \ + src/hardware/conrad-digi-35-cpu/protocol.c \ + src/hardware/conrad-digi-35-cpu/api.c endif if HW_DEMO libsigrok_la_SOURCES += \ - hardware/demo/demo.c + src/hardware/demo/demo.c endif if HW_FLUKE_DMM libsigrok_la_SOURCES += \ - hardware/fluke-dmm/fluke-dmm.h \ - hardware/fluke-dmm/fluke.c \ - hardware/fluke-dmm/api.c + src/hardware/fluke-dmm/fluke-dmm.h \ + src/hardware/fluke-dmm/fluke.c \ + src/hardware/fluke-dmm/api.c endif if HW_FX2LAFW libsigrok_la_SOURCES += \ - hardware/fx2lafw/protocol.h \ - hardware/fx2lafw/protocol.c \ - hardware/fx2lafw/api.c + src/hardware/fx2lafw/protocol.h \ + src/hardware/fx2lafw/protocol.c \ + src/hardware/fx2lafw/api.c endif if HW_GMC_MH_1X_2X libsigrok_la_SOURCES += \ - hardware/gmc-mh-1x-2x/protocol.h \ - hardware/gmc-mh-1x-2x/protocol.c \ - hardware/gmc-mh-1x-2x/api.c + src/hardware/gmc-mh-1x-2x/protocol.h \ + src/hardware/gmc-mh-1x-2x/protocol.c \ + src/hardware/gmc-mh-1x-2x/api.c endif if HW_HAMEG_HMO libsigrok_la_SOURCES += \ - hardware/hameg-hmo/protocol.h \ - hardware/hameg-hmo/protocol.c \ - hardware/hameg-hmo/api.c + src/hardware/hameg-hmo/protocol.h \ + src/hardware/hameg-hmo/protocol.c \ + src/hardware/hameg-hmo/api.c endif if HW_HANTEK_DSO libsigrok_la_SOURCES += \ - hardware/hantek-dso/dso.h \ - hardware/hantek-dso/dso.c \ - hardware/hantek-dso/api.c + src/hardware/hantek-dso/dso.h \ + src/hardware/hantek-dso/dso.c \ + src/hardware/hantek-dso/api.c endif if HW_IKALOGIC_SCANALOGIC2 libsigrok_la_SOURCES += \ - hardware/ikalogic-scanalogic2/protocol.h \ - hardware/ikalogic-scanalogic2/protocol.c \ - hardware/ikalogic-scanalogic2/api.c + src/hardware/ikalogic-scanalogic2/protocol.h \ + src/hardware/ikalogic-scanalogic2/protocol.c \ + src/hardware/ikalogic-scanalogic2/api.c endif if HW_IKALOGIC_SCANAPLUS libsigrok_la_SOURCES += \ - hardware/ikalogic-scanaplus/protocol.h \ - hardware/ikalogic-scanaplus/protocol.c \ - hardware/ikalogic-scanaplus/api.c + src/hardware/ikalogic-scanaplus/protocol.h \ + src/hardware/ikalogic-scanaplus/protocol.c \ + src/hardware/ikalogic-scanaplus/api.c endif if HW_KECHENG_KC_330B libsigrok_la_SOURCES += \ - hardware/kecheng-kc-330b/protocol.h \ - hardware/kecheng-kc-330b/protocol.c \ - hardware/kecheng-kc-330b/api.c + src/hardware/kecheng-kc-330b/protocol.h \ + src/hardware/kecheng-kc-330b/protocol.c \ + src/hardware/kecheng-kc-330b/api.c endif if HW_LASCAR_EL_USB libsigrok_la_SOURCES += \ - hardware/lascar-el-usb/protocol.h \ - hardware/lascar-el-usb/protocol.c \ - hardware/lascar-el-usb/api.c + src/hardware/lascar-el-usb/protocol.h \ + src/hardware/lascar-el-usb/protocol.c \ + src/hardware/lascar-el-usb/api.c endif if HW_MANSON_HCS_3XXX libsigrok_la_SOURCES += \ - hardware/manson-hcs-3xxx/protocol.h \ - hardware/manson-hcs-3xxx/protocol.c \ - hardware/manson-hcs-3xxx/api.c + src/hardware/manson-hcs-3xxx/protocol.h \ + src/hardware/manson-hcs-3xxx/protocol.c \ + src/hardware/manson-hcs-3xxx/api.c endif if HW_MIC_985XX libsigrok_la_SOURCES += \ - hardware/mic-985xx/protocol.h \ - hardware/mic-985xx/protocol.c \ - hardware/mic-985xx/api.c + src/hardware/mic-985xx/protocol.h \ + src/hardware/mic-985xx/protocol.c \ + src/hardware/mic-985xx/api.c endif if HW_MOTECH_LPS_30X libsigrok_la_SOURCES += \ - hardware/motech-lps-30x/protocol.h \ - hardware/motech-lps-30x/protocol.c \ - hardware/motech-lps-30x/api.c + src/hardware/motech-lps-30x/protocol.h \ + src/hardware/motech-lps-30x/protocol.c \ + src/hardware/motech-lps-30x/api.c endif if HW_NORMA_DMM libsigrok_la_SOURCES += \ - hardware/norma-dmm/protocol.h \ - hardware/norma-dmm/protocol.c \ - hardware/norma-dmm/api.c + src/hardware/norma-dmm/protocol.h \ + src/hardware/norma-dmm/protocol.c \ + src/hardware/norma-dmm/api.c endif if HW_OPENBENCH_LOGIC_SNIFFER libsigrok_la_SOURCES += \ - hardware/openbench-logic-sniffer/protocol.h \ - hardware/openbench-logic-sniffer/protocol.c \ - hardware/openbench-logic-sniffer/api.c + src/hardware/openbench-logic-sniffer/protocol.h \ + src/hardware/openbench-logic-sniffer/protocol.c \ + src/hardware/openbench-logic-sniffer/api.c endif if HW_RIGOL_DS libsigrok_la_SOURCES += \ - hardware/rigol-ds/protocol.h \ - hardware/rigol-ds/protocol.c \ - hardware/rigol-ds/api.c + src/hardware/rigol-ds/protocol.h \ + src/hardware/rigol-ds/protocol.c \ + src/hardware/rigol-ds/api.c endif if HW_SALEAE_LOGIC16 libsigrok_la_SOURCES += \ - hardware/saleae-logic16/protocol.h \ - hardware/saleae-logic16/protocol.c \ - hardware/saleae-logic16/api.c + src/hardware/saleae-logic16/protocol.h \ + src/hardware/saleae-logic16/protocol.c \ + src/hardware/saleae-logic16/api.c endif if HW_SERIAL_DMM libsigrok_la_SOURCES += \ - hardware/serial-dmm/protocol.h \ - hardware/serial-dmm/protocol.c \ - hardware/serial-dmm/api.c + src/hardware/serial-dmm/protocol.h \ + src/hardware/serial-dmm/protocol.c \ + src/hardware/serial-dmm/api.c endif if HW_SYSCLK_LWLA libsigrok_la_SOURCES += \ - hardware/sysclk-lwla/lwla.h \ - hardware/sysclk-lwla/lwla.c \ - hardware/sysclk-lwla/protocol.h \ - hardware/sysclk-lwla/protocol.c \ - hardware/sysclk-lwla/api.c + src/hardware/sysclk-lwla/lwla.h \ + src/hardware/sysclk-lwla/lwla.c \ + src/hardware/sysclk-lwla/protocol.h \ + src/hardware/sysclk-lwla/protocol.c \ + src/hardware/sysclk-lwla/api.c endif if HW_TELEINFO libsigrok_la_SOURCES += \ - hardware/teleinfo/protocol.h \ - hardware/teleinfo/protocol.c \ - hardware/teleinfo/api.c + src/hardware/teleinfo/protocol.h \ + src/hardware/teleinfo/protocol.c \ + src/hardware/teleinfo/api.c endif if HW_TESTO libsigrok_la_SOURCES += \ - hardware/testo/protocol.h \ - hardware/testo/protocol.c \ - hardware/testo/api.c + src/hardware/testo/protocol.h \ + src/hardware/testo/protocol.c \ + src/hardware/testo/api.c endif if HW_TONDAJ_SL_814 libsigrok_la_SOURCES += \ - hardware/tondaj-sl-814/protocol.h \ - hardware/tondaj-sl-814/protocol.c \ - hardware/tondaj-sl-814/api.c + src/hardware/tondaj-sl-814/protocol.h \ + src/hardware/tondaj-sl-814/protocol.c \ + src/hardware/tondaj-sl-814/api.c endif if HW_UNI_T_DMM libsigrok_la_SOURCES += \ - hardware/uni-t-dmm/protocol.h \ - hardware/uni-t-dmm/protocol.c \ - hardware/uni-t-dmm/api.c + src/hardware/uni-t-dmm/protocol.h \ + src/hardware/uni-t-dmm/protocol.c \ + src/hardware/uni-t-dmm/api.c endif if HW_UNI_T_UT32X libsigrok_la_SOURCES += \ - hardware/uni-t-ut32x/protocol.h \ - hardware/uni-t-ut32x/protocol.c \ - hardware/uni-t-ut32x/api.c + src/hardware/uni-t-ut32x/protocol.h \ + src/hardware/uni-t-ut32x/protocol.c \ + src/hardware/uni-t-ut32x/api.c endif if HW_VICTOR_DMM libsigrok_la_SOURCES += \ - hardware/victor-dmm/protocol.h \ - hardware/victor-dmm/protocol.c \ - hardware/victor-dmm/api.c + src/hardware/victor-dmm/protocol.h \ + src/hardware/victor-dmm/protocol.c \ + src/hardware/victor-dmm/api.c endif if HW_ZEROPLUS_LOGIC_CUBE libsigrok_la_SOURCES += \ - hardware/zeroplus-logic-cube/analyzer.c \ - hardware/zeroplus-logic-cube/analyzer.h \ - hardware/zeroplus-logic-cube/gl_usb.h \ - hardware/zeroplus-logic-cube/gl_usb.c \ - hardware/zeroplus-logic-cube/protocol.h \ - hardware/zeroplus-logic-cube/protocol.c \ - hardware/zeroplus-logic-cube/api.c + src/hardware/zeroplus-logic-cube/analyzer.c \ + src/hardware/zeroplus-logic-cube/analyzer.h \ + src/hardware/zeroplus-logic-cube/gl_usb.h \ + src/hardware/zeroplus-logic-cube/gl_usb.c \ + src/hardware/zeroplus-logic-cube/protocol.h \ + src/hardware/zeroplus-logic-cube/protocol.c \ + src/hardware/zeroplus-logic-cube/api.c endif libsigrok_la_LIBADD = $(LIBOBJS) @@ -343,7 +343,7 @@ library_include_HEADERS = \ include/libsigrok/libsigrok.h \ include/libsigrok/proto.h \ include/libsigrok/version.h -noinst_HEADERS = libsigrok-internal.h +noinst_HEADERS = src/libsigrok-internal.h pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libsigrok.pc diff --git a/backend.c b/backend.c deleted file mode 100644 index f650fe12..00000000 --- a/backend.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2010-2012 Bert Vermeulen - * Copyright (C) 2012 Peter Stuge - * - * 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 . - */ - -#include -#include "config.h" /* Needed for HAVE_LIBUSB_1_0 and others. */ -#include "libsigrok.h" -#include "libsigrok-internal.h" - -/** @cond PRIVATE */ -#define LOG_PREFIX "backend" -/** @endcond */ - -/** - * @mainpage libsigrok API - * - * @section sec_intro Introduction - * - * The sigrok project aims at creating a - * portable, cross-platform, Free/Libre/Open-Source signal analysis software - * suite that supports various device types (such as logic analyzers, - * oscilloscopes, multimeters, and more). - * - * libsigrok is a shared - * library written in C which provides the basic API for talking to - * supported hardware - * and reading/writing the acquired data into various - * input/output - * file formats. - * - * @section sec_api API reference - * - * See the "Modules" page for an introduction to various libsigrok - * related topics and the detailed API documentation of the respective - * functions. - * - * You can also browse the API documentation by file, or review all - * data structures. - * - * @section sec_mailinglists Mailing lists - * - * There are two mailing lists for sigrok/libsigrok: sigrok-devel and sigrok-commits. - * - * @section sec_irc IRC - * - * You can find the sigrok developers in the - * \#sigrok - * IRC channel on Freenode. - * - * @section sec_website Website - * - * sigrok.org/wiki/Libsigrok - */ - -/** - * @file - * - * Initializing and shutting down libsigrok. - */ - -/** - * @defgroup grp_init Initialization - * - * Initializing and shutting down libsigrok. - * - * Before using any of the libsigrok functionality (except - * sr_log_loglevel_set() and sr_log_opts_set()), sr_init() must - * be called to initialize the library, which will return a struct sr_context - * when the initialization was successful. - * - * When libsigrok functionality is no longer needed, sr_exit() should be - * called, which will (among other things) free the struct sr_context. - * - * Example for a minimal program using libsigrok: - * - * @code{.c} - * #include - * #include - * - * int main(int argc, char **argv) - * { - * int ret; - * struct sr_context *sr_ctx; - * - * if ((ret = sr_init(&sr_ctx)) != SR_OK) { - * printf("Error initializing libsigrok (%s): %s.\n", - * sr_strerror_name(ret), sr_strerror(ret)); - * return 1; - * } - * - * // Use libsigrok functions here... - * - * if ((ret = sr_exit(sr_ctx)) != SR_OK) { - * printf("Error shutting down libsigrok (%s): %s.\n", - * sr_strerror_name(ret), sr_strerror(ret)); - * return 1; - * } - * - * return 0; - * } - * @endcode - * - * @{ - */ - -/** - * Sanity-check all libsigrok drivers. - * - * @retval SR_OK All drivers are OK - * @retval SR_ERR One or more drivers have issues. - */ -static int sanity_check_all_drivers(void) -{ - int i, errors, ret = SR_OK; - struct sr_dev_driver **drivers; - const char *d; - - sr_spew("Sanity-checking all drivers."); - - drivers = sr_driver_list(); - for (i = 0; drivers[i]; i++) { - errors = 0; - - d = (drivers[i]->name) ? drivers[i]->name : "NULL"; - - if (!drivers[i]->name) { - sr_err("No name in driver %d ('%s').", i, d); - errors++; - } - if (!drivers[i]->longname) { - sr_err("No longname in driver %d ('%s').", i, d); - errors++; - } - if (drivers[i]->api_version < 1) { - sr_err("API version in driver %d ('%s') < 1.", i, d); - errors++; - } - if (!drivers[i]->init) { - sr_err("No init in driver %d ('%s').", i, d); - errors++; - } - if (!drivers[i]->cleanup) { - sr_err("No cleanup in driver %d ('%s').", i, d); - errors++; - } - if (!drivers[i]->scan) { - sr_err("No scan in driver %d ('%s').", i, d); - errors++; - } - if (!drivers[i]->dev_list) { - sr_err("No dev_list in driver %d ('%s').", i, d); - errors++; - } - /* Note: config_get() is optional. */ - if (!drivers[i]->config_set) { - sr_err("No config_set in driver %d ('%s').", i, d); - errors++; - } - if (!drivers[i]->config_list) { - sr_err("No config_list in driver %d ('%s').", i, d); - errors++; - } - if (!drivers[i]->dev_open) { - sr_err("No dev_open in driver %d ('%s').", i, d); - errors++; - } - if (!drivers[i]->dev_close) { - sr_err("No dev_close in driver %d ('%s').", i, d); - errors++; - } - if (!drivers[i]->dev_acquisition_start) { - sr_err("No dev_acquisition_start in driver %d ('%s').", - i, d); - errors++; - } - if (!drivers[i]->dev_acquisition_stop) { - sr_err("No dev_acquisition_stop in driver %d ('%s').", - i, d); - errors++; - } - - /* Note: 'priv' is allowed to be NULL. */ - - if (errors == 0) - continue; - - ret = SR_ERR; - } - - return ret; -} - -/** - * Sanity-check all libsigrok input modules. - * - * @retval SR_OK All modules are OK - * @retval SR_ERR One or more modules have issues. - */ -static int sanity_check_all_input_modules(void) -{ - int i, errors, ret = SR_OK; - struct sr_input_format **inputs; - const char *d; - - sr_spew("Sanity-checking all input modules."); - - inputs = sr_input_list(); - for (i = 0; inputs[i]; i++) { - errors = 0; - - d = (inputs[i]->id) ? inputs[i]->id : "NULL"; - - if (!inputs[i]->id) { - sr_err("No ID in module %d ('%s').", i, d); - errors++; - } - if (!inputs[i]->description) { - sr_err("No description in module %d ('%s').", i, d); - errors++; - } - if (!inputs[i]->format_match) { - sr_err("No format_match in module %d ('%s').", i, d); - errors++; - } - if (!inputs[i]->init) { - sr_err("No init in module %d ('%s').", i, d); - errors++; - } - if (!inputs[i]->loadfile) { - sr_err("No loadfile in module %d ('%s').", i, d); - errors++; - } - - if (errors == 0) - continue; - - ret = SR_ERR; - } - - return ret; -} - -/** - * Sanity-check all libsigrok output modules. - * - * @retval SR_OK All modules are OK - * @retval SR_ERR One or more modules have issues. - */ -static int sanity_check_all_output_modules(void) -{ - int i, errors, ret = SR_OK; - struct sr_output_format **outputs; - const char *d; - - sr_spew("Sanity-checking all output modules."); - - outputs = sr_output_list(); - for (i = 0; outputs[i]; i++) { - errors = 0; - - d = (outputs[i]->id) ? outputs[i]->id : "NULL"; - - if (!outputs[i]->id) { - sr_err("No ID in module %d ('%s').", i, d); - errors++; - } - if (!outputs[i]->description) { - sr_err("No description in module '%s'.", d); - errors++; - } - if (!outputs[i]->receive) { - sr_err("No receive in module '%s'.", d); - errors++; - } - - if (errors == 0) - continue; - - ret = SR_ERR; - } - - return ret; -} - -/** - * Initialize libsigrok. - * - * This function must be called before any other libsigrok function. - * - * @param ctx Pointer to a libsigrok context struct pointer. Must not be NULL. - * This will be a pointer to a newly allocated libsigrok context - * object upon success, and is undefined upon errors. - * - * @return SR_OK upon success, a (negative) error code otherwise. Upon errors - * the 'ctx' pointer is undefined and should not be used. Upon success, - * the context will be free'd by sr_exit() as part of the libsigrok - * shutdown. - * - * @since 0.2.0 - */ -SR_API int sr_init(struct sr_context **ctx) -{ - int ret = SR_ERR; - struct sr_context *context; - - if (!ctx) { - sr_err("%s(): libsigrok context was NULL.", __func__); - return SR_ERR; - } - - if (sanity_check_all_drivers() < 0) { - sr_err("Internal driver error(s), aborting."); - return ret; - } - - if (sanity_check_all_input_modules() < 0) { - sr_err("Internal input module error(s), aborting."); - return ret; - } - - if (sanity_check_all_output_modules() < 0) { - sr_err("Internal output module error(s), aborting."); - return ret; - } - - /* + 1 to handle when struct sr_context has no members. */ - context = g_try_malloc0(sizeof(struct sr_context) + 1); - - if (!context) { - ret = SR_ERR_MALLOC; - goto done; - } - -#ifdef HAVE_LIBUSB_1_0 - ret = libusb_init(&context->libusb_ctx); - if (LIBUSB_SUCCESS != ret) { - sr_err("libusb_init() returned %s.", libusb_error_name(ret)); - ret = SR_ERR; - goto done; - } -#endif - - *ctx = context; - context = NULL; - ret = SR_OK; - -done: - if (context) - g_free(context); - return ret; -} - -/** - * Shutdown libsigrok. - * - * @param ctx Pointer to a libsigrok context struct. Must not be NULL. - * - * @retval SR_OK Success - * @retval other Error code SR_ERR, ... - * - * @since 0.2.0 - */ -SR_API int sr_exit(struct sr_context *ctx) -{ - if (!ctx) { - sr_err("%s(): libsigrok context was NULL.", __func__); - return SR_ERR; - } - - sr_hw_cleanup_all(); - -#ifdef HAVE_LIBUSB_1_0 - libusb_exit(ctx->libusb_ctx); -#endif - - g_free(ctx); - - return SR_OK; -} - -/** @} */ diff --git a/device.c b/device.c deleted file mode 100644 index 434d1066..00000000 --- a/device.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2013 Bert Vermeulen - * - * 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 . - */ - -#include -#include -#include "config.h" /* Needed for HAVE_LIBUSB_1_0 and others. */ -#include "libsigrok.h" -#include "libsigrok-internal.h" - -/** @cond PRIVATE */ -#define LOG_PREFIX "device" -/** @endcond */ - -/** - * @file - * - * Device handling in libsigrok. - */ - -/** - * @defgroup grp_devices Devices - * - * Device handling in libsigrok. - * - * @{ - */ - -/** @private - * Allocate and initialize new struct sr_channel - * @param[in] index @copydoc sr_channel::index - * @param[in] type @copydoc sr_channel::type - * @param[in] enabled @copydoc sr_channel::enabled - * @param[in] name @copydoc sr_channel::name - * - * @return NULL (failure) or new struct sr_channel*. - */ -SR_PRIV struct sr_channel *sr_channel_new(int index, int type, - gboolean enabled, const char *name) -{ - struct sr_channel *ch; - - if (!(ch = g_try_malloc0(sizeof(struct sr_channel)))) { - sr_err("Channel malloc failed."); - return NULL; - } - - ch->index = index; - ch->type = type; - ch->enabled = enabled; - if (name) - ch->name = g_strdup(name); - - return ch; -} - -/** - * Set the name of the specified channel in the specified device. - * - * If the channel already has a different name assigned to it, it will be - * removed, and the new name will be saved instead. - * - * @param sdi The device instance the channel is connected to. - * @param[in] channelnum The number of the channel whose name to set. - * Note that the channel numbers start at 0. - * @param[in] name The new name that the specified channel should get. A copy - * of the string is made. - * - * @return SR_OK on success, or SR_ERR_ARG on invalid arguments. - * - * @since 0.3.0 - */ -SR_API int sr_dev_channel_name_set(const struct sr_dev_inst *sdi, - int channelnum, const char *name) -{ - GSList *l; - struct sr_channel *ch; - int ret; - - if (!sdi) { - sr_err("%s: sdi was NULL", __func__); - return SR_ERR_ARG; - } - - ret = SR_ERR_ARG; - for (l = sdi->channels; l; l = l->next) { - ch = l->data; - if (ch->index == channelnum) { - g_free(ch->name); - ch->name = g_strdup(name); - ret = SR_OK; - break; - } - } - - return ret; -} - -/** - * Enable or disable a channel on the specified device. - * - * @param sdi The device instance the channel is connected to. - * @param channelnum The channel number, starting from 0. - * @param state TRUE to enable the channel, FALSE to disable. - * - * @return SR_OK on success or SR_ERR on failure. In case of invalid - * arguments, SR_ERR_ARG is returned and the channel enabled state - * remains unchanged. - * - * @since 0.3.0 - */ -SR_API int sr_dev_channel_enable(const struct sr_dev_inst *sdi, int channelnum, - gboolean state) -{ - GSList *l; - struct sr_channel *ch; - int ret; - gboolean was_enabled; - - if (!sdi) - return SR_ERR_ARG; - - ret = SR_ERR_ARG; - for (l = sdi->channels; l; l = l->next) { - ch = l->data; - if (ch->index == channelnum) { - was_enabled = ch->enabled; - ch->enabled = state; - ret = SR_OK; - if (!state != !was_enabled && sdi->driver - && sdi->driver->config_channel_set) { - ret = sdi->driver->config_channel_set( - sdi, ch, SR_CHANNEL_SET_ENABLED); - /* Roll back change if it wasn't applicable. */ - if (ret == SR_ERR_ARG) - ch->enabled = was_enabled; - } - break; - } - } - - return ret; -} - -/** - * Determine whether the specified device instance has the specified - * capability. - * - * @param sdi Pointer to the device instance to be checked. Must not be NULL. - * If the device's 'driver' field is NULL (virtual device), this - * function will always return FALSE (virtual devices don't have - * a hardware capabilities list). - * @param[in] key The option that should be checked for is supported by the - * specified device. - * - * @retval TRUE Device has the specified option - * @retval FALSE Device does not have the specified option, invalid input - * parameters or other error conditions. - * - * @since 0.2.0 - */ -SR_API gboolean sr_dev_has_option(const struct sr_dev_inst *sdi, int key) -{ - GVariant *gvar; - const int *devopts; - gsize num_opts, i; - int ret; - - if (!sdi || !sdi->driver || !sdi->driver->config_list) - return FALSE; - - if (sdi->driver->config_list(SR_CONF_DEVICE_OPTIONS, - &gvar, sdi, NULL) != SR_OK) - return FALSE; - - ret = FALSE; - devopts = g_variant_get_fixed_array(gvar, &num_opts, sizeof(int32_t)); - for (i = 0; i < num_opts; i++) { - if (devopts[i] == key) { - ret = TRUE; - break; - } - } - g_variant_unref(gvar); - - return ret; -} - -/** @private - * Allocate and init new device instance struct. - * @param[in] index @copydoc sr_dev_inst::index - * @param[in] status @copydoc sr_dev_inst::status - * @param[in] vendor @copydoc sr_dev_inst::vendor - * @param[in] model @copydoc sr_dev_inst::model - * @param[in] version @copydoc sr_dev_inst::version - * - * @retval NULL Error - * @retval struct sr_dev_inst *. Dynamically allocated, free using - * sr_dev_inst_free(). - */ -SR_PRIV struct sr_dev_inst *sr_dev_inst_new(int index, int status, - const char *vendor, const char *model, const char *version) -{ - struct sr_dev_inst *sdi; - - if (!(sdi = g_try_malloc(sizeof(struct sr_dev_inst)))) { - sr_err("Device instance malloc failed."); - return NULL; - } - - sdi->driver = NULL; - sdi->index = index; - sdi->status = status; - sdi->inst_type = -1; - sdi->vendor = vendor ? g_strdup(vendor) : NULL; - sdi->model = model ? g_strdup(model) : NULL; - sdi->version = version ? g_strdup(version) : NULL; - sdi->channels = NULL; - sdi->channel_groups = NULL; - sdi->session = NULL; - sdi->conn = NULL; - sdi->priv = NULL; - - return sdi; -} - -/** @private - * Free device instance struct created by sr_dev_inst(). - * @param sdi struct* to free. - */ -SR_PRIV void sr_dev_inst_free(struct sr_dev_inst *sdi) -{ - struct sr_channel *ch; - GSList *l; - - for (l = sdi->channels; l; l = l->next) { - ch = l->data; - g_free(ch->name); - g_free(ch); - } - g_slist_free(sdi->channels); - - if (sdi->channel_groups) - g_slist_free(sdi->channel_groups); - - g_free(sdi->vendor); - g_free(sdi->model); - g_free(sdi->version); - g_free(sdi); -} - -#ifdef HAVE_LIBUSB_1_0 - -/** @private - * Allocate and init struct for USB device instance. - * @param[in] bus @copydoc sr_usb_dev_inst::bus - * @param[in] address @copydoc sr_usb_dev_inst::address - * @param[in] hdl @copydoc sr_usb_dev_inst::devhdl - * - * @retval NULL Error - * @retval other struct sr_usb_dev_inst * for USB device instance. - */ -SR_PRIV struct sr_usb_dev_inst *sr_usb_dev_inst_new(uint8_t bus, - uint8_t address, struct libusb_device_handle *hdl) -{ - struct sr_usb_dev_inst *udi; - - if (!(udi = g_try_malloc(sizeof(struct sr_usb_dev_inst)))) { - sr_err("USB device instance malloc failed."); - return NULL; - } - - udi->bus = bus; - udi->address = address; - udi->devhdl = hdl; - - return udi; -} - -/** @private - * Free struct * allocated by sr_usb_dev_inst(). - * @param usb struct* to free. Must not be NULL. - */ -SR_PRIV void sr_usb_dev_inst_free(struct sr_usb_dev_inst *usb) -{ - g_free(usb); -} - -#endif - -#ifdef HAVE_LIBSERIALPORT - -/** - * @private - * - * Both parameters are copied to newly allocated strings, and freed - * automatically by sr_serial_dev_inst_free(). - * - * @param[in] port OS-specific serial port specification. Examples: - * "/dev/ttyUSB0", "/dev/ttyACM1", "/dev/tty.Modem-0", "COM1". - * @param[in] serialcomm A serial communication parameters string, in the form - * of \/\\\, for example - * "9600/8n1" or "600/7o2". This is an optional parameter; - * it may be filled in later. - * - * @return A pointer to a newly initialized struct sr_serial_dev_inst, - * or NULL on error. - */ -SR_PRIV struct sr_serial_dev_inst *sr_serial_dev_inst_new(const char *port, - const char *serialcomm) -{ - struct sr_serial_dev_inst *serial; - - if (!port) { - sr_err("Serial port required."); - return NULL; - } - - if (!(serial = g_try_malloc0(sizeof(struct sr_serial_dev_inst)))) { - sr_err("Serial device instance malloc failed."); - return NULL; - } - - serial->port = g_strdup(port); - if (serialcomm) - serial->serialcomm = g_strdup(serialcomm); - - return serial; -} - -/** @private - * Free struct sr_serial_dev_inst * allocated by sr_serial_dev_inst(). - * @param serial struct sr_serial_dev_inst * to free. Must not be NULL. - */ -SR_PRIV void sr_serial_dev_inst_free(struct sr_serial_dev_inst *serial) -{ - g_free(serial->port); - g_free(serial->serialcomm); - g_free(serial); -} -#endif - -/** @private */ -SR_PRIV struct sr_usbtmc_dev_inst *sr_usbtmc_dev_inst_new(const char *device) -{ - struct sr_usbtmc_dev_inst *usbtmc; - - if (!device) { - sr_err("Device name required."); - return NULL; - } - - if (!(usbtmc = g_try_malloc0(sizeof(struct sr_usbtmc_dev_inst)))) { - sr_err("USBTMC device instance malloc failed."); - return NULL; - } - - usbtmc->device = g_strdup(device); - usbtmc->fd = -1; - - return usbtmc; -} - -/** @private */ -SR_PRIV void sr_usbtmc_dev_inst_free(struct sr_usbtmc_dev_inst *usbtmc) -{ - g_free(usbtmc->device); - g_free(usbtmc); -} - -/** - * Get the list of devices/instances of the specified driver. - * - * @param driver The driver to use. Must not be NULL. - * - * @return The list of devices/instances of this driver, or NULL upon errors - * or if the list is empty. - * - * @since 0.2.0 - */ -SR_API GSList *sr_dev_list(const struct sr_dev_driver *driver) -{ - if (driver && driver->dev_list) - return driver->dev_list(); - else - return NULL; -} - -/** - * Clear the list of device instances a driver knows about. - * - * @param driver The driver to use. This must be a pointer to one of - * the entries returned by sr_driver_list(). Must not be NULL. - * - * @retval SR_OK Success - * @retval SR_ERR_ARG Invalid driver - * - * @since 0.2.0 - */ -SR_API int sr_dev_clear(const struct sr_dev_driver *driver) -{ - int ret; - - if (!driver) { - sr_err("Invalid driver."); - return SR_ERR_ARG; - } - - if (driver->dev_clear) - ret = driver->dev_clear(); - else - ret = std_dev_clear(driver, NULL); - - return ret; -} - -/** - * Open the specified device. - * - * @param sdi Device instance to use. Must not be NULL. - * - * @return SR_OK upon success, a negative error code upon errors. - * - * @since 0.2.0 - */ -SR_API int sr_dev_open(struct sr_dev_inst *sdi) -{ - int ret; - - if (!sdi || !sdi->driver || !sdi->driver->dev_open) - return SR_ERR; - - ret = sdi->driver->dev_open(sdi); - - return ret; -} - -/** - * Close the specified device. - * - * @param sdi Device instance to use. Must not be NULL. - * - * @return SR_OK upon success, a negative error code upon errors. - * - * @since 0.2.0 - */ -SR_API int sr_dev_close(struct sr_dev_inst *sdi) -{ - int ret; - - if (!sdi || !sdi->driver || !sdi->driver->dev_close) - return SR_ERR; - - ret = sdi->driver->dev_close(sdi); - - return ret; -} - -/** @} */ diff --git a/drivers.c b/drivers.c deleted file mode 100644 index f93214d3..00000000 --- a/drivers.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2014 Bert Vermeulen - * - * 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 . - */ - -#include "libsigrok.h" -#include "libsigrok-internal.h" - -/** @cond PRIVATE */ -#ifdef HAVE_HW_AGILENT_DMM -extern SR_PRIV struct sr_dev_driver agdmm_driver_info; -#endif -#ifdef HAVE_HW_APPA_55II -extern SR_PRIV struct sr_dev_driver appa_55ii_driver_info; -#endif -#ifdef HAVE_HW_ASIX_SIGMA -extern SR_PRIV struct sr_dev_driver asix_sigma_driver_info; -#endif -#ifdef HAVE_HW_ATTEN_PPS3XXX -extern SR_PRIV struct sr_dev_driver atten_pps3203_driver_info; -#endif -#ifdef HAVE_HW_BEAGLELOGIC -extern SR_PRIV struct sr_dev_driver beaglelogic_driver_info; -#endif -#ifdef HAVE_HW_BRYMEN_BM86X -extern SR_PRIV struct sr_dev_driver brymen_bm86x_driver_info; -#endif -#ifdef HAVE_HW_BRYMEN_DMM -extern SR_PRIV struct sr_dev_driver brymen_bm857_driver_info; -#endif -#ifdef HAVE_HW_CEM_DT_885X -extern SR_PRIV struct sr_dev_driver cem_dt_885x_driver_info; -#endif -#ifdef HAVE_HW_CENTER_3XX -extern SR_PRIV struct sr_dev_driver center_309_driver_info; -extern SR_PRIV struct sr_dev_driver voltcraft_k204_driver_info; -#endif -#ifdef HAVE_HW_CHRONOVU_LA -extern SR_PRIV struct sr_dev_driver chronovu_la_driver_info; -#endif -#ifdef HAVE_HW_COLEAD_SLM -extern SR_PRIV struct sr_dev_driver colead_slm_driver_info; -#endif -#ifdef HAVE_HW_CONRAD_DIGI_35_CPU -extern SR_PRIV struct sr_dev_driver conrad_digi_35_cpu_driver_info; -#endif -#ifdef HAVE_HW_DEMO -extern SR_PRIV struct sr_dev_driver demo_driver_info; -#endif -#ifdef HAVE_HW_FLUKE_DMM -extern SR_PRIV struct sr_dev_driver flukedmm_driver_info; -#endif -#ifdef HAVE_HW_FX2LAFW -extern SR_PRIV struct sr_dev_driver fx2lafw_driver_info; -#endif -#ifdef HAVE_HW_GMC_MH_1X_2X -extern SR_PRIV struct sr_dev_driver gmc_mh_1x_2x_rs232_driver_info; -extern SR_PRIV struct sr_dev_driver gmc_mh_2x_bd232_driver_info; -#endif -#ifdef HAVE_HW_HAMEG_HMO -extern SR_PRIV struct sr_dev_driver hameg_hmo_driver_info; -#endif -#ifdef HAVE_HW_HANTEK_DSO -extern SR_PRIV struct sr_dev_driver hantek_dso_driver_info; -#endif -#ifdef HAVE_HW_IKALOGIC_SCANALOGIC2 -extern SR_PRIV struct sr_dev_driver ikalogic_scanalogic2_driver_info; -#endif -#ifdef HAVE_HW_IKALOGIC_SCANAPLUS -extern SR_PRIV struct sr_dev_driver ikalogic_scanaplus_driver_info; -#endif -#ifdef HAVE_HW_KECHENG_KC_330B -extern SR_PRIV struct sr_dev_driver kecheng_kc_330b_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_LINK_MSO19 -extern SR_PRIV struct sr_dev_driver link_mso19_driver_info; -#endif -#ifdef HAVE_HW_MANSON_HCS_3XXX -extern SR_PRIV struct sr_dev_driver manson_hcs_3xxx_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_MOTECH_LPS_30X -extern SR_PRIV struct sr_dev_driver motech_lps_301_driver_info; -#endif -#ifdef HAVE_HW_NORMA_DMM -extern SR_PRIV struct sr_dev_driver norma_dmm_driver_info; -extern SR_PRIV struct sr_dev_driver siemens_b102x_driver_info; -#endif -#ifdef HAVE_HW_OPENBENCH_LOGIC_SNIFFER -extern SR_PRIV struct sr_dev_driver ols_driver_info; -#endif -#ifdef HAVE_HW_RIGOL_DS -extern SR_PRIV struct sr_dev_driver rigol_ds_driver_info; -#endif -#ifdef HAVE_HW_SALEAE_LOGIC16 -extern SR_PRIV struct sr_dev_driver saleae_logic16_driver_info; -#endif -#ifdef HAVE_HW_SERIAL_DMM -extern SR_PRIV struct sr_dev_driver bbcgm_m2110_driver_info; -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 va_va40b_driver_info; -extern SR_PRIV struct sr_dev_driver metex_m3640d_driver_info; -extern SR_PRIV struct sr_dev_driver metex_m4650cr_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_8061_ser_driver_info; -extern SR_PRIV struct sr_dev_driver voltcraft_m3650cr_driver_info; -extern SR_PRIV struct sr_dev_driver voltcraft_m3650d_driver_info; -extern SR_PRIV struct sr_dev_driver voltcraft_m4650cr_driver_info; -extern SR_PRIV struct sr_dev_driver voltcraft_me42_driver_info; -extern SR_PRIV struct sr_dev_driver voltcraft_vc820_ser_driver_info; -extern SR_PRIV struct sr_dev_driver voltcraft_vc830_ser_driver_info; -extern SR_PRIV struct sr_dev_driver voltcraft_vc840_ser_driver_info; -extern SR_PRIV struct sr_dev_driver uni_t_ut60a_ser_driver_info; -extern SR_PRIV struct sr_dev_driver uni_t_ut60e_ser_driver_info; -extern SR_PRIV struct sr_dev_driver uni_t_ut60g_ser_driver_info; -extern SR_PRIV struct sr_dev_driver uni_t_ut61b_ser_driver_info; -extern SR_PRIV struct sr_dev_driver uni_t_ut61c_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; -extern SR_PRIV struct sr_dev_driver iso_tech_idm103n_driver_info; -extern SR_PRIV struct sr_dev_driver tenma_72_7745_ser_driver_info; -extern SR_PRIV struct sr_dev_driver tenma_72_7750_ser_driver_info; -#endif -#ifdef HAVE_HW_SYSCLK_LWLA -extern SR_PRIV struct sr_dev_driver sysclk_lwla_driver_info; -#endif -#ifdef HAVE_HW_TELEINFO -extern SR_PRIV struct sr_dev_driver teleinfo_driver_info; -#endif -#ifdef HAVE_HW_TESTO -extern SR_PRIV struct sr_dev_driver testo_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_UNI_T_DMM -extern SR_PRIV struct sr_dev_driver tecpel_dmm_8061_driver_info; -extern SR_PRIV struct sr_dev_driver uni_t_ut60a_driver_info; -extern SR_PRIV struct sr_dev_driver uni_t_ut60e_driver_info; -extern SR_PRIV struct sr_dev_driver uni_t_ut60g_driver_info; -extern SR_PRIV struct sr_dev_driver uni_t_ut61b_driver_info; -extern SR_PRIV struct sr_dev_driver uni_t_ut61c_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_vc830_driver_info; -extern SR_PRIV struct sr_dev_driver voltcraft_vc840_driver_info; -extern SR_PRIV struct sr_dev_driver tenma_72_7745_driver_info; -extern SR_PRIV struct sr_dev_driver tenma_72_7750_driver_info; -#endif -#ifdef HAVE_HW_UNI_T_UT32X -extern SR_PRIV struct sr_dev_driver uni_t_ut32x_driver_info; -#endif -#ifdef HAVE_HW_VICTOR_DMM -extern SR_PRIV struct sr_dev_driver victor_dmm_driver_info; -#endif -#ifdef HAVE_HW_ZEROPLUS_LOGIC_CUBE -extern SR_PRIV struct sr_dev_driver zeroplus_logic_cube_driver_info; -#endif - -SR_PRIV struct sr_dev_driver *drivers_list[] = { -#ifdef HAVE_HW_AGILENT_DMM - &agdmm_driver_info, -#endif -#ifdef HAVE_HW_APPA_55II - &appa_55ii_driver_info, -#endif -#ifdef HAVE_HW_ASIX_SIGMA - &asix_sigma_driver_info, -#endif -#ifdef HAVE_HW_ATTEN_PPS3XXX - &atten_pps3203_driver_info, -#endif -#ifdef HAVE_HW_BEAGLELOGIC - &beaglelogic_driver_info, -#endif -#ifdef HAVE_HW_BRYMEN_BM86X - &brymen_bm86x_driver_info, -#endif -#ifdef HAVE_HW_BRYMEN_DMM - &brymen_bm857_driver_info, -#endif -#ifdef HAVE_HW_CEM_DT_885X - &cem_dt_885x_driver_info, -#endif -#ifdef HAVE_HW_CENTER_3XX - ¢er_309_driver_info, - &voltcraft_k204_driver_info, -#endif -#ifdef HAVE_HW_CHRONOVU_LA - &chronovu_la_driver_info, -#endif -#ifdef HAVE_HW_COLEAD_SLM - &colead_slm_driver_info, -#endif -#ifdef HAVE_HW_CONRAD_DIGI_35_CPU - &conrad_digi_35_cpu_driver_info, -#endif -#ifdef HAVE_HW_DEMO - &demo_driver_info, -#endif -#ifdef HAVE_HW_FLUKE_DMM - &flukedmm_driver_info, -#endif -#ifdef HAVE_HW_FX2LAFW - &fx2lafw_driver_info, -#endif -#ifdef HAVE_HW_GMC_MH_1X_2X - &gmc_mh_1x_2x_rs232_driver_info, - &gmc_mh_2x_bd232_driver_info, -#endif -#ifdef HAVE_HW_HAMEG_HMO - &hameg_hmo_driver_info, -#endif -#ifdef HAVE_HW_HANTEK_DSO - &hantek_dso_driver_info, -#endif -#ifdef HAVE_HW_IKALOGIC_SCANALOGIC2 - &ikalogic_scanalogic2_driver_info, -#endif -#ifdef HAVE_HW_IKALOGIC_SCANAPLUS - &ikalogic_scanaplus_driver_info, -#endif -#ifdef HAVE_HW_KECHENG_KC_330B - &kecheng_kc_330b_driver_info, -#endif -#ifdef HAVE_HW_LASCAR_EL_USB - &lascar_el_usb_driver_info, -#endif -#ifdef HAVE_HW_LINK_MSO19 - &link_mso19_driver_info, -#endif -#ifdef HAVE_HW_MANSON_HCS_3XXX - &manson_hcs_3xxx_driver_info, -#endif -#ifdef HAVE_HW_MIC_985XX - &mic_98581_driver_info, - &mic_98583_driver_info, -#endif -#ifdef HAVE_HW_MOTECH_LPS_30X - &motech_lps_301_driver_info, -#endif -#ifdef HAVE_HW_NORMA_DMM - &norma_dmm_driver_info, - &siemens_b102x_driver_info, -#endif -#ifdef HAVE_HW_OPENBENCH_LOGIC_SNIFFER - &ols_driver_info, -#endif -#ifdef HAVE_HW_RIGOL_DS - &rigol_ds_driver_info, -#endif -#ifdef HAVE_HW_SALEAE_LOGIC16 - &saleae_logic16_driver_info, -#endif -#ifdef HAVE_HW_SERIAL_DMM - &bbcgm_m2110_driver_info, - &digitek_dt4000zc_driver_info, - &tekpower_tp4000zc_driver_info, - &metex_me31_driver_info, - &peaktech_3410_driver_info, - &mastech_mas345_driver_info, - &va_va18b_driver_info, - &va_va40b_driver_info, - &metex_m3640d_driver_info, - &metex_m4650cr_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_8061_ser_driver_info, - &voltcraft_m3650cr_driver_info, - &voltcraft_m3650d_driver_info, - &voltcraft_m4650cr_driver_info, - &voltcraft_me42_driver_info, - &voltcraft_vc820_ser_driver_info, - &voltcraft_vc830_ser_driver_info, - &voltcraft_vc840_ser_driver_info, - &uni_t_ut60a_ser_driver_info, - &uni_t_ut60e_ser_driver_info, - &uni_t_ut60g_ser_driver_info, - &uni_t_ut61b_ser_driver_info, - &uni_t_ut61c_ser_driver_info, - &uni_t_ut61d_ser_driver_info, - &uni_t_ut61e_ser_driver_info, - &iso_tech_idm103n_driver_info, - &tenma_72_7745_ser_driver_info, - &tenma_72_7750_ser_driver_info, -#endif -#ifdef HAVE_HW_SYSCLK_LWLA - &sysclk_lwla_driver_info, -#endif -#ifdef HAVE_HW_TELEINFO - &teleinfo_driver_info, -#endif -#ifdef HAVE_HW_TESTO - &testo_driver_info, -#endif -#ifdef HAVE_HW_TONDAJ_SL_814 - &tondaj_sl_814_driver_info, -#endif -#ifdef HAVE_HW_UNI_T_DMM - &tecpel_dmm_8061_driver_info, - &uni_t_ut60a_driver_info, - &uni_t_ut60e_driver_info, - &uni_t_ut60g_driver_info, - &uni_t_ut61b_driver_info, - &uni_t_ut61c_driver_info, - &uni_t_ut61d_driver_info, - &uni_t_ut61e_driver_info, - &voltcraft_vc820_driver_info, - &voltcraft_vc830_driver_info, - &voltcraft_vc840_driver_info, - &tenma_72_7745_driver_info, - &tenma_72_7750_driver_info, -#endif -#ifdef HAVE_HW_UNI_T_UT32X - &uni_t_ut32x_driver_info, -#endif -#ifdef HAVE_HW_VICTOR_DMM - &victor_dmm_driver_info, -#endif -#ifdef HAVE_HW_ZEROPLUS_LOGIC_CUBE - &zeroplus_logic_cube_driver_info, -#endif - NULL, -}; -/** @endcond */ - diff --git a/error.c b/error.c deleted file mode 100644 index f8779752..00000000 --- a/error.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2012 Uwe Hermann - * - * 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 "libsigrok.h" - -/** - * @file - * - * Error handling in libsigrok. - */ - -/** - * @defgroup grp_error Error handling - * - * Error handling in libsigrok. - * - * libsigrok functions usually return @ref SR_OK upon success, or a negative - * error code on failure. - * - * @{ - */ - -/** - * Return a human-readable error string for the given libsigrok error code. - * - * @param error_code A libsigrok error code number, such as SR_ERR_MALLOC. - * - * @return A const string containing a short, human-readable (English) - * description of the error, such as "memory allocation error". - * The string must NOT be free'd by the caller! - * - * @see sr_strerror_name - * - * @since 0.2.0 - */ -SR_API const char *sr_strerror(int error_code) -{ - /* - * Note: All defined SR_* error macros from libsigrok.h must have - * an entry in this function, as well as in sr_strerror_name(). - */ - - switch (error_code) { - case SR_OK: - return "no error"; - case SR_ERR: - return "generic/unspecified error"; - case SR_ERR_MALLOC: - return "memory allocation error"; - case SR_ERR_ARG: - return "invalid argument"; - case SR_ERR_BUG: - return "internal error"; - case SR_ERR_SAMPLERATE: - return "invalid samplerate"; - case SR_ERR_NA: - return "not applicable"; - case SR_ERR_DEV_CLOSED: - return "device closed but should be open"; - case SR_ERR_TIMEOUT: - return "timeout occurred"; - case SR_ERR_CHANNEL_GROUP: - return "no channel group specified"; - default: - return "unknown error"; - } -} - -/** - * Return the "name" string of the given libsigrok error code. - * - * For example, the "name" of the SR_ERR_MALLOC error code is "SR_ERR_MALLOC", - * the name of the SR_OK code is "SR_OK", and so on. - * - * This function can be used for various purposes where the "name" string of - * a libsigrok error code is useful. - * - * @param error_code A libsigrok error code number, such as SR_ERR_MALLOC. - * - * @return A const string containing the "name" of the error code as string. - * The string must NOT be free'd by the caller! - * - * @see sr_strerror - * - * @since 0.2.0 - */ -SR_API const char *sr_strerror_name(int error_code) -{ - /* - * Note: All defined SR_* error macros from libsigrok.h must have - * an entry in this function, as well as in sr_strerror(). - */ - - switch (error_code) { - case SR_OK: - return "SR_OK"; - case SR_ERR: - return "SR_ERR"; - case SR_ERR_MALLOC: - return "SR_ERR_MALLOC"; - case SR_ERR_ARG: - return "SR_ERR_ARG"; - case SR_ERR_BUG: - return "SR_ERR_BUG"; - case SR_ERR_SAMPLERATE: - return "SR_ERR_SAMPLERATE"; - case SR_ERR_NA: - return "SR_ERR_NA"; - case SR_ERR_DEV_CLOSED: - return "SR_ERR_DEV_CLOSED"; - case SR_ERR_TIMEOUT: - return "SR_ERR_TIMEOUT"; - case SR_ERR_CHANNEL_GROUP: - return "SR_ERR_CHANNEL_GROUP"; - default: - return "unknown error code"; - } -} - -/** @} */ diff --git a/hardware/agilent-dmm/agilent-dmm.h b/hardware/agilent-dmm/agilent-dmm.h deleted file mode 100644 index 2277111f..00000000 --- a/hardware/agilent-dmm/agilent-dmm.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2012 Bert Vermeulen - * - * 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 . - */ - -#ifndef LIBSIGROK_HARDWARE_AGILENT_DMM_AGILENT_DMM_H -#define LIBSIGROK_HARDWARE_AGILENT_DMM_AGILENT_DMM_H - -#define LOG_PREFIX "agilent-dmm" - -#define AGDMM_BUFSIZE 256 - -/* Supported models */ -enum { - AGILENT_U1231A = 1, - AGILENT_U1232A, - AGILENT_U1233A, - AGILENT_U1251A, - AGILENT_U1252A, - AGILENT_U1253A, -}; - -/* Supported device profiles */ -struct agdmm_profile { - int model; - const char *modelname; - const struct agdmm_job *jobs; - const struct agdmm_recv *recvs; -}; - -/* Private, per-device-instance driver context. */ -struct dev_context { - const struct agdmm_profile *profile; - uint64_t limit_samples; - uint64_t limit_msec; - - /* Opaque pointer passed in by the frontend. */ - void *cb_data; - - /* Runtime. */ - uint64_t num_samples; - int64_t jobqueue[8]; - unsigned char buf[AGDMM_BUFSIZE]; - int buflen; - int cur_mq; - int cur_unit; - int cur_mqflags; - int cur_divider; - int cur_acdc; - int mode_tempaux; - int mode_continuity; -}; - -struct agdmm_job { - int interval; - int (*send) (const struct sr_dev_inst *sdi); -}; - -struct agdmm_recv { - const char *recv_regex; - int (*recv) (const struct sr_dev_inst *sdi, GMatchInfo *match); -}; - -SR_PRIV int agdmm_receive_data(int fd, int revents, void *cb_data); - -#endif diff --git a/hardware/agilent-dmm/api.c b/hardware/agilent-dmm/api.c deleted file mode 100644 index cb7baa60..00000000 --- a/hardware/agilent-dmm/api.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2012 Bert Vermeulen - * - * 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 . - */ - -#include -#include -#include -#include -#include -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" -#include "agilent-dmm.h" - -static const int32_t hwopts[] = { - SR_CONF_CONN, - SR_CONF_SERIALCOMM, -}; - -static const int32_t hwcaps[] = { - SR_CONF_MULTIMETER, - SR_CONF_LIMIT_SAMPLES, - SR_CONF_LIMIT_MSEC, - SR_CONF_CONTINUOUS, -}; - -extern const struct agdmm_job agdmm_jobs_u123x[]; -extern const struct agdmm_recv agdmm_recvs_u123x[]; -extern const struct agdmm_job agdmm_jobs_u125x[]; -extern const struct agdmm_recv agdmm_recvs_u125x[]; - -/* This works on all the Agilent U12xxA series, although the - * U127xA can apparently also run at 19200/8n1. */ -#define SERIALCOMM "9600/8n1" - -static const struct agdmm_profile supported_agdmm[] = { - { AGILENT_U1231A, "U1231A", agdmm_jobs_u123x, agdmm_recvs_u123x }, - { AGILENT_U1232A, "U1232A", agdmm_jobs_u123x, agdmm_recvs_u123x }, - { AGILENT_U1233A, "U1233A", agdmm_jobs_u123x, agdmm_recvs_u123x }, - { AGILENT_U1251A, "U1251A", agdmm_jobs_u125x, agdmm_recvs_u125x }, - { AGILENT_U1252A, "U1252A", agdmm_jobs_u125x, agdmm_recvs_u125x }, - { AGILENT_U1253A, "U1253A", agdmm_jobs_u125x, agdmm_recvs_u125x }, - { 0, NULL, NULL, NULL } -}; - -SR_PRIV struct sr_dev_driver agdmm_driver_info; -static struct sr_dev_driver *di = &agdmm_driver_info; - -static int init(struct sr_context *sr_ctx) -{ - return std_init(sr_ctx, di, LOG_PREFIX); -} - -static GSList *scan(GSList *options) -{ - struct sr_dev_inst *sdi; - struct drv_context *drvc; - struct dev_context *devc; - struct sr_config *src; - struct sr_channel *ch; - struct sr_serial_dev_inst *serial; - GSList *l, *devices; - int len, i; - const char *conn, *serialcomm; - char *buf, **tokens; - - drvc = di->priv; - drvc->instances = NULL; - - devices = NULL; - conn = serialcomm = NULL; - for (l = options; l; l = l->next) { - src = l->data; - switch (src->key) { - case SR_CONF_CONN: - conn = g_variant_get_string(src->data, NULL); - break; - case SR_CONF_SERIALCOMM: - serialcomm = g_variant_get_string(src->data, NULL); - break; - } - } - if (!conn) - return NULL; - if (!serialcomm) - serialcomm = SERIALCOMM; - - if (!(serial = sr_serial_dev_inst_new(conn, serialcomm))) - return NULL; - - if (serial_open(serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK) - return NULL; - - serial_flush(serial); - if (serial_write(serial, "*IDN?\r\n", 7) == -1) { - sr_err("Unable to send identification string: %s.", - strerror(errno)); - return NULL; - } - - len = 128; - if (!(buf = g_try_malloc(len))) { - sr_err("Serial buffer malloc failed."); - return NULL; - } - serial_readline(serial, &buf, &len, 150); - if (!len) - return NULL; - - tokens = g_strsplit(buf, ",", 4); - if (!strcmp("Agilent Technologies", tokens[0]) - && tokens[1] && tokens[2] && tokens[3]) { - for (i = 0; supported_agdmm[i].model; i++) { - if (strcmp(supported_agdmm[i].modelname, tokens[1])) - continue; - if (!(sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, "Agilent", - tokens[1], tokens[3]))) - return NULL; - if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) { - sr_err("Device context malloc failed."); - return NULL; - } - devc->profile = &supported_agdmm[i]; - devc->cur_mq = -1; - sdi->inst_type = SR_INST_SERIAL; - sdi->conn = serial; - sdi->priv = devc; - sdi->driver = di; - if (!(ch = sr_channel_new(0, SR_CHANNEL_ANALOG, TRUE, "P1"))) - return NULL; - sdi->channels = g_slist_append(sdi->channels, ch); - drvc->instances = g_slist_append(drvc->instances, sdi); - devices = g_slist_append(devices, sdi); - break; - } - } - g_strfreev(tokens); - g_free(buf); - - serial_close(serial); - if (!devices) - sr_serial_dev_inst_free(serial); - - return devices; -} - -static GSList *dev_list(void) -{ - return ((struct drv_context *)(di->priv))->instances; -} - -static int cleanup(void) -{ - return std_dev_clear(di, NULL); -} - -static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc; - - (void)cg; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - if (!(devc = sdi->priv)) { - sr_err("sdi->priv was NULL."); - return SR_ERR_BUG; - } - - switch (id) { - case SR_CONF_LIMIT_MSEC: - /* TODO: not yet implemented */ - if (g_variant_get_uint64(data) == 0) { - sr_err("LIMIT_MSEC can't be 0."); - return SR_ERR; - } - devc->limit_msec = g_variant_get_uint64(data); - sr_dbg("Setting time limit to %" PRIu64 "ms.", - devc->limit_msec); - break; - case SR_CONF_LIMIT_SAMPLES: - devc->limit_samples = g_variant_get_uint64(data); - sr_dbg("Setting sample limit to %" PRIu64 ".", - devc->limit_samples); - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - (void)sdi; - (void)cg; - - switch (key) { - case SR_CONF_SCAN_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t)); - break; - case SR_CONF_DEVICE_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t)); - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) -{ - struct dev_context *devc; - struct sr_serial_dev_inst *serial; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - if (!(devc = sdi->priv)) { - sr_err("sdi->priv was NULL."); - return SR_ERR_BUG; - } - - devc->cb_data = cb_data; - - /* Send header packet to the session bus. */ - std_session_send_df_header(cb_data, LOG_PREFIX); - - /* Poll every 100ms, or whenever some data comes in. */ - serial = sdi->conn; - serial_source_add(sdi->session, serial, G_IO_IN, 100, - agdmm_receive_data, (void *)sdi); - - return SR_OK; -} - -static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) -{ - return std_serial_dev_acquisition_stop(sdi, cb_data, std_serial_dev_close, - sdi->conn, LOG_PREFIX); -} - -SR_PRIV struct sr_dev_driver agdmm_driver_info = { - .name = "agilent-dmm", - .longname = "Agilent U12xx series DMMs", - .api_version = 1, - .init = init, - .cleanup = cleanup, - .scan = scan, - .dev_list = dev_list, - .dev_clear = NULL, - .config_get = NULL, - .config_set = config_set, - .config_list = config_list, - .dev_open = std_serial_dev_open, - .dev_close = std_serial_dev_close, - .dev_acquisition_start = dev_acquisition_start, - .dev_acquisition_stop = dev_acquisition_stop, - .priv = NULL, -}; diff --git a/hardware/agilent-dmm/sched.c b/hardware/agilent-dmm/sched.c deleted file mode 100644 index bd9cb388..00000000 --- a/hardware/agilent-dmm/sched.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2012 Bert Vermeulen - * - * 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 . - */ - -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" -#include "agilent-dmm.h" -#include -#include -#include -#include - -static void dispatch(const struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - const struct agdmm_job *jobs; - int64_t now; - int i; - - devc = sdi->priv; - jobs = devc->profile->jobs; - now = g_get_monotonic_time() / 1000; - for (i = 0; (&jobs[i])->interval; i++) { - if (now - devc->jobqueue[i] > (&jobs[i])->interval) { - sr_spew("Running job %d.", i); - (&jobs[i])->send(sdi); - devc->jobqueue[i] = now; - } - } -} - -static void receive_line(const struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - const struct agdmm_recv *recvs, *recv; - GRegex *reg; - GMatchInfo *match; - int i; - - devc = sdi->priv; - - /* Strip CRLF */ - while (devc->buflen) { - if (*(devc->buf + devc->buflen - 1) == '\r' - || *(devc->buf + devc->buflen - 1) == '\n') - *(devc->buf + --devc->buflen) = '\0'; - else - break; - } - sr_spew("Received '%s'.", devc->buf); - - recv = NULL; - recvs = devc->profile->recvs; - for (i = 0; (&recvs[i])->recv_regex; i++) { - reg = g_regex_new((&recvs[i])->recv_regex, 0, 0, NULL); - if (g_regex_match(reg, (char *)devc->buf, 0, &match)) { - recv = &recvs[i]; - break; - } - g_match_info_unref(match); - g_regex_unref(reg); - } - if (recv) { - recv->recv(sdi, match); - g_match_info_unref(match); - g_regex_unref(reg); - } else - sr_dbg("Unknown line '%s'.", devc->buf); - - /* Done with this. */ - devc->buflen = 0; -} - -SR_PRIV int agdmm_receive_data(int fd, int revents, void *cb_data) -{ - struct sr_dev_inst *sdi; - struct dev_context *devc; - struct sr_serial_dev_inst *serial; - int len; - - (void)fd; - - if (!(sdi = cb_data)) - return TRUE; - - if (!(devc = sdi->priv)) - return TRUE; - - serial = sdi->conn; - if (revents == G_IO_IN) { - /* Serial data arrived. */ - while(AGDMM_BUFSIZE - devc->buflen - 1 > 0) { - len = serial_read(serial, devc->buf + devc->buflen, 1); - if (len < 1) - break; - devc->buflen += len; - *(devc->buf + devc->buflen) = '\0'; - if (*(devc->buf + devc->buflen - 1) == '\n') { - /* End of line */ - receive_line(sdi); - break; - } - } - } - - dispatch(sdi); - - if (devc->limit_samples && devc->num_samples >= devc->limit_samples) - sdi->driver->dev_acquisition_stop(sdi, cb_data); - - return TRUE; -} - -static int agdmm_send(const struct sr_dev_inst *sdi, const char *cmd) -{ - struct sr_serial_dev_inst *serial; - char buf[32]; - - serial = sdi->conn; - - sr_spew("Sending '%s'.", cmd); - strncpy(buf, cmd, 28); - if (!strncmp(buf, "*IDN?", 5)) - strncat(buf, "\r\n", 32); - else - strncat(buf, "\n\r\n", 32); - if (serial_write(serial, buf, strlen(buf)) == -1) { - sr_err("Failed to send: %s.", strerror(errno)); - return SR_ERR; - } - - return SR_OK; -} - -static int send_stat(const struct sr_dev_inst *sdi) -{ - return agdmm_send(sdi, "STAT?"); -} - -static int recv_stat_u123x(const struct sr_dev_inst *sdi, GMatchInfo *match) -{ - struct dev_context *devc; - char *s; - - devc = sdi->priv; - s = g_match_info_fetch(match, 1); - sr_spew("STAT response '%s'.", s); - - /* Max, Min or Avg mode -- no way to tell which, so we'll - * set both flags to denote it's not a normal measurement. */ - if (s[0] == '1') - devc->cur_mqflags |= SR_MQFLAG_MAX | SR_MQFLAG_MIN; - else - devc->cur_mqflags &= ~(SR_MQFLAG_MAX | SR_MQFLAG_MIN); - - if (s[1] == '1') - devc->cur_mqflags |= SR_MQFLAG_RELATIVE; - else - devc->cur_mqflags &= ~SR_MQFLAG_RELATIVE; - - /* Triggered or auto hold modes. */ - if (s[2] == '1' || s[3] == '1') - devc->cur_mqflags |= SR_MQFLAG_HOLD; - else - devc->cur_mqflags &= ~SR_MQFLAG_HOLD; - - /* Temp/aux mode. */ - if (s[7] == '1') - devc->mode_tempaux = TRUE; - else - devc->mode_tempaux = FALSE; - - /* Continuity mode. */ - if (s[16] == '1') - devc->mode_continuity = TRUE; - else - devc->mode_continuity = FALSE; - - g_free(s); - - return SR_OK; -} - -static int recv_stat_u125x(const struct sr_dev_inst *sdi, GMatchInfo *match) -{ - struct dev_context *devc; - char *s; - - devc = sdi->priv; - s = g_match_info_fetch(match, 1); - sr_spew("STAT response '%s'.", s); - - /* Peak hold mode. */ - if (s[4] == '1') - devc->cur_mqflags |= SR_MQFLAG_MAX; - else - devc->cur_mqflags &= ~SR_MQFLAG_MAX; - - /* Triggered hold mode. */ - if (s[7] == '1') - devc->cur_mqflags |= SR_MQFLAG_HOLD; - else - devc->cur_mqflags &= ~SR_MQFLAG_HOLD; - - g_free(s); - - return SR_OK; -} - -static int send_fetc(const struct sr_dev_inst *sdi) -{ - return agdmm_send(sdi, "FETC?"); -} - -static int recv_fetc(const struct sr_dev_inst *sdi, GMatchInfo *match) -{ - struct dev_context *devc; - struct sr_datafeed_packet packet; - struct sr_datafeed_analog analog; - float fvalue; - char *mstr; - - sr_spew("FETC reply '%s'.", g_match_info_get_string(match)); - devc = sdi->priv; - - if (devc->cur_mq == -1) - /* Haven't seen configuration yet, so can't know what - * the fetched float means. Not really an error, we'll - * get metadata soon enough. */ - return SR_OK; - - if (!strcmp(g_match_info_get_string(match), "+9.90000000E+37")) { - /* An invalid measurement shows up on the display as "O.L", but - * comes through like this. Since comparing 38-digit floats - * is rather problematic, we'll cut through this here. */ - fvalue = NAN; - } else { - mstr = g_match_info_fetch(match, 1); - if (sr_atof_ascii(mstr, &fvalue) != SR_OK || fvalue == 0.0) { - g_free(mstr); - sr_err("Invalid float."); - return SR_ERR; - } - g_free(mstr); - if (devc->cur_divider > 0) - fvalue /= devc->cur_divider; - } - - memset(&analog, 0, sizeof(struct sr_datafeed_analog)); - analog.mq = devc->cur_mq; - analog.unit = devc->cur_unit; - analog.mqflags = devc->cur_mqflags; - analog.channels = sdi->channels; - analog.num_samples = 1; - analog.data = &fvalue; - packet.type = SR_DF_ANALOG; - packet.payload = &analog; - sr_session_send(devc->cb_data, &packet); - - devc->num_samples++; - - return SR_OK; -} - -static int send_conf(const struct sr_dev_inst *sdi) -{ - return agdmm_send(sdi, "CONF?"); -} - -static int recv_conf_u123x(const struct sr_dev_inst *sdi, GMatchInfo *match) -{ - struct dev_context *devc; - char *mstr; - - sr_spew("CONF? response '%s'.", g_match_info_get_string(match)); - devc = sdi->priv; - mstr = g_match_info_fetch(match, 1); - if (!strcmp(mstr, "V")) { - devc->cur_mq = SR_MQ_VOLTAGE; - devc->cur_unit = SR_UNIT_VOLT; - devc->cur_mqflags = 0; - devc->cur_divider = 0; - } else if(!strcmp(mstr, "MV")) { - if (devc->mode_tempaux) { - devc->cur_mq = SR_MQ_TEMPERATURE; - /* No way to detect whether Fahrenheit or Celcius - * is used, so we'll just default to Celcius. */ - devc->cur_unit = SR_UNIT_CELSIUS; - devc->cur_mqflags = 0; - devc->cur_divider = 0; - } else { - devc->cur_mq = SR_MQ_VOLTAGE; - devc->cur_unit = SR_UNIT_VOLT; - devc->cur_mqflags = 0; - devc->cur_divider = 1000; - } - } else if(!strcmp(mstr, "A")) { - devc->cur_mq = SR_MQ_CURRENT; - devc->cur_unit = SR_UNIT_AMPERE; - devc->cur_mqflags = 0; - devc->cur_divider = 0; - } else if(!strcmp(mstr, "UA")) { - devc->cur_mq = SR_MQ_CURRENT; - devc->cur_unit = SR_UNIT_AMPERE; - devc->cur_mqflags = 0; - devc->cur_divider = 1000000; - } else if(!strcmp(mstr, "FREQ")) { - devc->cur_mq = SR_MQ_FREQUENCY; - devc->cur_unit = SR_UNIT_HERTZ; - devc->cur_mqflags = 0; - devc->cur_divider = 0; - } else if(!strcmp(mstr, "RES")) { - if (devc->mode_continuity) { - devc->cur_mq = SR_MQ_CONTINUITY; - devc->cur_unit = SR_UNIT_BOOLEAN; - } else { - devc->cur_mq = SR_MQ_RESISTANCE; - devc->cur_unit = SR_UNIT_OHM; - } - devc->cur_mqflags = 0; - devc->cur_divider = 0; - } else if(!strcmp(mstr, "CAP")) { - devc->cur_mq = SR_MQ_CAPACITANCE; - devc->cur_unit = SR_UNIT_FARAD; - devc->cur_mqflags = 0; - devc->cur_divider = 0; - } else - sr_dbg("Unknown first argument."); - g_free(mstr); - - if (g_match_info_get_match_count(match) == 4) { - mstr = g_match_info_fetch(match, 3); - /* Third value, if present, is always AC or DC. */ - if (!strcmp(mstr, "AC")) - devc->cur_mqflags |= SR_MQFLAG_AC; - else if (!strcmp(mstr, "DC")) - devc->cur_mqflags |= SR_MQFLAG_DC; - else - sr_dbg("Unknown third argument."); - g_free(mstr); - } else - devc->cur_mqflags &= ~(SR_MQFLAG_AC | SR_MQFLAG_DC); - - return SR_OK; -} - -static int recv_conf_u125x(const struct sr_dev_inst *sdi, GMatchInfo *match) -{ - struct dev_context *devc; - char *mstr; - - sr_spew("CONF? response '%s'.", g_match_info_get_string(match)); - devc = sdi->priv; - mstr = g_match_info_fetch(match, 1); - if (!strncmp(mstr, "VOLT", 4)) { - devc->cur_mq = SR_MQ_VOLTAGE; - devc->cur_unit = SR_UNIT_VOLT; - devc->cur_mqflags = 0; - devc->cur_divider = 0; - if (mstr[4] == ':') { - if (!strcmp(mstr + 4, "AC")) - devc->cur_mqflags |= SR_MQFLAG_AC; - else if (!strcmp(mstr + 4, "DC")) - devc->cur_mqflags |= SR_MQFLAG_DC; - else - /* "ACDC" appears as well, no idea what it means. */ - devc->cur_mqflags &= ~(SR_MQFLAG_AC | SR_MQFLAG_DC); - } else - devc->cur_mqflags &= ~(SR_MQFLAG_AC | SR_MQFLAG_DC); - } else if(!strcmp(mstr, "CURR")) { - devc->cur_mq = SR_MQ_CURRENT; - devc->cur_unit = SR_UNIT_AMPERE; - devc->cur_mqflags = 0; - devc->cur_divider = 0; - } else if(!strcmp(mstr, "RES")) { - if (devc->mode_continuity) { - devc->cur_mq = SR_MQ_CONTINUITY; - devc->cur_unit = SR_UNIT_BOOLEAN; - } else { - devc->cur_mq = SR_MQ_RESISTANCE; - devc->cur_unit = SR_UNIT_OHM; - } - devc->cur_mqflags = 0; - devc->cur_divider = 0; - } else - sr_dbg("Unknown first argument."); - g_free(mstr); - - return SR_OK; -} - -/* At least the 123x and 125x appear to have this. */ -static int recv_conf(const struct sr_dev_inst *sdi, GMatchInfo *match) -{ - struct dev_context *devc; - char *mstr; - - sr_spew("CONF? response '%s'.", g_match_info_get_string(match)); - devc = sdi->priv; - mstr = g_match_info_fetch(match, 1); - if(!strcmp(mstr, "DIOD")) { - devc->cur_mq = SR_MQ_VOLTAGE; - devc->cur_unit = SR_UNIT_VOLT; - devc->cur_mqflags = SR_MQFLAG_DIODE; - devc->cur_divider = 0; - } else - sr_dbg("Unknown single argument."); - g_free(mstr); - - return SR_OK; -} - -/* This comes in whenever the rotary switch is changed to a new position. - * We could use it to determine the major measurement mode, but we already - * have the output of CONF? for that, which is more detailed. However - * we do need to catch this here, or it'll show up in some other output. */ -static int recv_switch(const struct sr_dev_inst *sdi, GMatchInfo *match) -{ - (void)sdi; - - sr_spew("Switch '%s'.", g_match_info_get_string(match)); - - return SR_OK; -} - -SR_PRIV const struct agdmm_job agdmm_jobs_u123x[] = { - { 143, send_stat }, - { 1000, send_conf }, - { 143, send_fetc }, - { 0, NULL } -}; - -SR_PRIV const struct agdmm_recv agdmm_recvs_u123x[] = { - { "^\"(\\d\\d.{18}\\d)\"$", recv_stat_u123x }, - { "^\\*([0-9])$", recv_switch }, - { "^([-+][0-9]\\.[0-9]{8}E[-+][0-9]{2})$", recv_fetc }, - { "^\"(V|MV|A|UA|FREQ),(\\d),(AC|DC)\"$", recv_conf_u123x }, - { "^\"(RES|CAP),(\\d)\"$", recv_conf_u123x}, - { "^\"(DIOD)\"$", recv_conf }, - { NULL, NULL } -}; - -SR_PRIV const struct agdmm_job agdmm_jobs_u125x[] = { - { 143, send_stat }, - { 1000, send_conf }, - { 143, send_fetc }, - { 0, NULL } -}; - -SR_PRIV const struct agdmm_recv agdmm_recvs_u125x[] = { - { "^\"(\\d\\d.{18}\\d)\"$", recv_stat_u125x }, - { "^\\*([0-9])$", recv_switch }, - { "^([-+][0-9]\\.[0-9]{8}E[-+][0-9]{2})$", recv_fetc }, - { "^(VOLT|CURR|RES|CAP) ([-+][0-9\\.E\\-+]+),([-+][0-9\\.E\\-+]+)$", recv_conf_u125x }, - { "^(VOLT:[ACD]+) ([-+][0-9\\.E\\-+]+),([-+][0-9\\.E\\-+]+)$", recv_conf_u125x }, - { "^\"(DIOD)\"$", recv_conf }, - { NULL, NULL } -}; diff --git a/hardware/appa-55ii/api.c b/hardware/appa-55ii/api.c deleted file mode 100644 index de71e338..00000000 --- a/hardware/appa-55ii/api.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2013 Aurelien Jacobs - * - * 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 . - */ - -#include -#include "protocol.h" - -static const int32_t hwopts[] = { - SR_CONF_CONN, - SR_CONF_SERIALCOMM, -}; - -static const int32_t hwcaps[] = { - SR_CONF_THERMOMETER, - SR_CONF_LIMIT_SAMPLES, - SR_CONF_LIMIT_MSEC, - SR_CONF_CONTINUOUS, - SR_CONF_DATA_SOURCE, -}; - -static const char *data_sources[] = { - "Live", - "Memory", -}; - -SR_PRIV struct sr_dev_driver appa_55ii_driver_info; -static struct sr_dev_driver *di = &appa_55ii_driver_info; - -static int init(struct sr_context *sr_ctx) -{ - return std_init(sr_ctx, di, LOG_PREFIX); -} - -static GSList *scan(GSList *options) -{ - struct drv_context *drvc; - struct dev_context *devc; - struct sr_serial_dev_inst *serial; - struct sr_dev_inst *sdi; - struct sr_channel *ch; - struct sr_config *src; - GSList *devices, *l; - const char *conn, *serialcomm; - uint8_t buf[50]; - size_t len; - - len = sizeof(buf); - devices = NULL; - conn = serialcomm = NULL; - for (l = options; l; l = l->next) { - src = l->data; - switch (src->key) { - case SR_CONF_CONN: - conn = g_variant_get_string(src->data, NULL); - break; - case SR_CONF_SERIALCOMM: - serialcomm = g_variant_get_string(src->data, NULL); - break; - } - } - if (!conn) - return NULL; - if (!serialcomm) - serialcomm = "9600/8n1"; - - if (!(serial = sr_serial_dev_inst_new(conn, serialcomm))) - return NULL; - if (serial_open(serial, SERIAL_RDONLY | SERIAL_NONBLOCK) != SR_OK) - return NULL; - - sr_info("Probing serial port %s.", conn); - - drvc = di->priv; - drvc->instances = NULL; - serial_flush(serial); - - /* Let's get a bit of data and see if we can find a packet. */ - if (serial_stream_detect(serial, buf, &len, 25, - appa_55ii_packet_valid, 500, 9600) != SR_OK) - goto scan_cleanup; - - sr_info("Found device on port %s.", conn); - - if (!(sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, "APPA", "55II", NULL))) - goto scan_cleanup; - - if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) { - sr_err("Device context malloc failed."); - goto scan_cleanup; - } - - devc->data_source = DEFAULT_DATA_SOURCE; - - sdi->inst_type = SR_INST_SERIAL; - sdi->conn = serial; - sdi->priv = devc; - sdi->driver = di; - - if (!(ch = sr_channel_new(0, SR_CHANNEL_ANALOG, TRUE, "T1"))) - goto scan_cleanup; - sdi->channels = g_slist_append(sdi->channels, ch); - if (!(ch = sr_channel_new(0, SR_CHANNEL_ANALOG, TRUE, "T2"))) - goto scan_cleanup; - sdi->channels = g_slist_append(sdi->channels, ch); - - drvc->instances = g_slist_append(drvc->instances, sdi); - devices = g_slist_append(devices, sdi); - -scan_cleanup: - serial_close(serial); - - return devices; -} - -static GSList *dev_list(void) -{ - return ((struct drv_context *)(di->priv))->instances; -} - -static int cleanup(void) -{ - return std_dev_clear(di, NULL); -} - -static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc = sdi->priv; - - (void)cg; - - switch (key) { - case SR_CONF_LIMIT_SAMPLES: - *data = g_variant_new_uint64(devc->limit_samples); - break; - case SR_CONF_LIMIT_MSEC: - *data = g_variant_new_uint64(devc->limit_msec); - break; - case SR_CONF_DATA_SOURCE: - *data = g_variant_new_string(data_sources[devc->data_source]); - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc; - const char *tmp_str; - unsigned int i; - - (void)cg; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - if (!(devc = sdi->priv)) { - sr_err("sdi->priv was NULL."); - return SR_ERR_BUG; - } - - switch (key) { - case SR_CONF_LIMIT_SAMPLES: - devc->limit_samples = g_variant_get_uint64(data); - sr_dbg("Setting sample limit to %" PRIu64 ".", devc->limit_samples); - break; - case SR_CONF_LIMIT_MSEC: - devc->limit_msec = g_variant_get_uint64(data); - sr_dbg("Setting time limit to %" PRIu64 "ms.", devc->limit_msec); - break; - case SR_CONF_DATA_SOURCE: { - tmp_str = g_variant_get_string(data, NULL); - for (i = 0; i < ARRAY_SIZE(data_sources); i++) - if (!strcmp(tmp_str, data_sources[i])) { - devc->data_source = i; - break; - } - if (i == ARRAY_SIZE(data_sources)) - return SR_ERR; - break; - } - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - (void)sdi; - (void)cg; - - switch (key) { - case SR_CONF_SCAN_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t)); - break; - case SR_CONF_DEVICE_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t)); - break; - case SR_CONF_DATA_SOURCE: - *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources)); - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int dev_acquisition_start(const struct sr_dev_inst *sdi, - void *cb_data) -{ - struct sr_serial_dev_inst *serial; - struct dev_context *devc; - - serial = sdi->conn; - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - if (!(devc = sdi->priv)) { - sr_err("sdi->priv was NULL."); - return SR_ERR_BUG; - } - - devc->session_cb_data = cb_data; - - /* - * Reset the number of samples to take. If we've already collected our - * quota, but we start a new session, and don't reset this, we'll just - * quit without acquiring any new samples. - */ - devc->num_samples = 0; - devc->start_time = g_get_monotonic_time(); - - /* Send header packet to the session bus. */ - std_session_send_df_header(cb_data, LOG_PREFIX); - - /* Poll every 50ms, or whenever some data comes in. */ - serial_source_add(sdi->session, serial, G_IO_IN, 50, - appa_55ii_receive_data, (void *)sdi); - - return SR_OK; -} - -static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) -{ - return std_serial_dev_acquisition_stop(sdi, cb_data, - std_serial_dev_close, sdi->conn, LOG_PREFIX); -} - -SR_PRIV struct sr_dev_driver appa_55ii_driver_info = { - .name = "appa-55ii", - .longname = "APPA 55II", - .api_version = 1, - .init = init, - .cleanup = cleanup, - .scan = scan, - .dev_list = dev_list, - .dev_clear = NULL, - .config_get = config_get, - .config_set = config_set, - .config_list = config_list, - .dev_open = std_serial_dev_open, - .dev_close = std_serial_dev_close, - .dev_acquisition_start = dev_acquisition_start, - .dev_acquisition_stop = dev_acquisition_stop, - .priv = NULL, -}; diff --git a/hardware/appa-55ii/protocol.c b/hardware/appa-55ii/protocol.c deleted file mode 100644 index 708262bd..00000000 --- a/hardware/appa-55ii/protocol.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2013 Aurelien Jacobs - * - * 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 . - */ - -#include -#include -#include "protocol.h" - -typedef enum { - LIVE_DATA = 0x00, - LOG_METADATA = 0x11, - LOG_DATA = 0x14, - LOG_START = 0x18, - LOG_END = 0x19, -} packet_type; - -static gboolean appa_55ii_checksum(const uint8_t *buf) -{ - int i, size, checksum; - - size = buf[3] + 4; - checksum = 0; - for (i = 0; i < size; i++) - checksum += buf[i]; - - return buf[size] == (checksum & 0xFF); -} - -SR_PRIV gboolean appa_55ii_packet_valid(const uint8_t *buf) -{ - if (buf[0] == 0x55 && buf[1] == 0x55 && buf[3] <= 32 - && appa_55ii_checksum(buf)) - return TRUE; - - return FALSE; -} - -static uint64_t appa_55ii_flags(const uint8_t *buf) -{ - uint8_t disp_mode; - uint64_t flags; - - disp_mode = buf[4 + 13]; - flags = 0; - if ((disp_mode & 0xF0) == 0x20) - flags |= SR_MQFLAG_HOLD; - if ((disp_mode & 0x0C) == 0x04) - flags |= SR_MQFLAG_MAX; - if ((disp_mode & 0x0C) == 0x08) - flags |= SR_MQFLAG_MIN; - if ((disp_mode & 0x0C) == 0x0C) - flags |= SR_MQFLAG_AVG; - - return flags; -} - -static float appa_55ii_temp(const uint8_t *buf, int ch) -{ - const uint8_t *ptr; - int16_t temp; - uint8_t flags; - - ptr = buf + 4 + 14 + 3 * ch; - temp = RL16(ptr); - flags = ptr[2]; - - if (flags & 0x60) - return INFINITY; - else if (flags & 1) - return (float)temp / 10; - else - return (float)temp; -} - -static void appa_55ii_live_data(struct sr_dev_inst *sdi, const uint8_t *buf) -{ - struct dev_context *devc; - struct sr_datafeed_packet packet; - struct sr_datafeed_analog analog; - struct sr_channel *ch; - float values[APPA_55II_NUM_CHANNELS], *val_ptr; - int i; - - devc = sdi->priv; - - if (devc->data_source != DATA_SOURCE_LIVE) - return; - - val_ptr = values; - memset(&analog, 0, sizeof(analog)); - analog.num_samples = 1; - analog.mq = SR_MQ_TEMPERATURE; - analog.unit = SR_UNIT_CELSIUS; - analog.mqflags = appa_55ii_flags(buf); - analog.data = values; - - for (i = 0; i < APPA_55II_NUM_CHANNELS; i++) { - ch = g_slist_nth_data(sdi->channels, i); - if (!ch->enabled) - continue; - analog.channels = g_slist_append(analog.channels, ch); - *val_ptr++ = appa_55ii_temp(buf, i); - } - - packet.type = SR_DF_ANALOG; - packet.payload = &analog; - sr_session_send(devc->session_cb_data, &packet); - g_slist_free(analog.channels); - - devc->num_samples++; -} - -static void appa_55ii_log_metadata(struct sr_dev_inst *sdi, const uint8_t *buf) -{ - struct dev_context *devc; - - devc = sdi->priv; - devc->num_log_records = (buf[5] << 8) + buf[4]; -} - -static void appa_55ii_log_data_parse(struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - struct sr_datafeed_packet packet; - struct sr_datafeed_analog analog; - struct sr_channel *ch; - float values[APPA_55II_NUM_CHANNELS], *val_ptr; - const uint8_t *buf; - int16_t temp; - int offset, i; - - devc = sdi->priv; - offset = 0; - - while (devc->log_buf_len >= 20 && devc->num_log_records > 0) { - buf = devc->log_buf + offset; - val_ptr = values; - - /* FIXME: Timestamp should be sent in the packet. */ - sr_dbg("Timestamp: %02d:%02d:%02d", buf[2], buf[3], buf[4]); - - memset(&analog, 0, sizeof(analog)); - analog.num_samples = 1; - analog.mq = SR_MQ_TEMPERATURE; - analog.unit = SR_UNIT_CELSIUS; - analog.data = values; - - for (i = 0; i < APPA_55II_NUM_CHANNELS; i++) { - temp = RL16(buf + 12 + 2 * i); - ch = g_slist_nth_data(sdi->channels, i); - if (!ch->enabled) - continue; - analog.channels = g_slist_append(analog.channels, ch); - *val_ptr++ = temp == 0x7FFF ? INFINITY : (float)temp / 10; - } - - packet.type = SR_DF_ANALOG; - packet.payload = &analog; - sr_session_send(devc->session_cb_data, &packet); - g_slist_free(analog.channels); - - devc->num_samples++; - devc->log_buf_len -= 20; - offset += 20; - devc->num_log_records--; - } - - memmove(devc->log_buf, devc->log_buf + offset, devc->log_buf_len); -} - -static void appa_55ii_log_data(struct sr_dev_inst *sdi, const uint8_t *buf) -{ - struct dev_context *devc; - const uint8_t *ptr; - unsigned int size; - int s; - - devc = sdi->priv; - if (devc->data_source != DATA_SOURCE_MEMORY) - return; - - ptr = buf + 4; - size = buf[3]; - while (size > 0) { - s = MIN(size, sizeof(devc->log_buf) - devc->log_buf_len); - memcpy(devc->log_buf + devc->log_buf_len, ptr, s); - devc->log_buf_len += s; - size -= s; - ptr += s; - - appa_55ii_log_data_parse(sdi); - } -} - -static void appa_55ii_log_end(struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - - devc = sdi->priv; - if (devc->data_source != DATA_SOURCE_MEMORY) - return; - - sdi->driver->dev_acquisition_stop(sdi, devc->session_cb_data); -} - -static const uint8_t *appa_55ii_parse_data(struct sr_dev_inst *sdi, - const uint8_t *buf, int len) -{ - if (len < 5) - /* Need more data. */ - return NULL; - - if (buf[0] != 0x55 || buf[1] != 0x55) - /* Try to re-synchronize on a packet start. */ - return buf + 1; - - if (len < 5 + buf[3]) - /* Need more data. */ - return NULL; - - if (!appa_55ii_checksum(buf)) - /* Skip broken packet. */ - return buf + 4 + buf[3] + 1; - - switch ((packet_type)buf[2]) { - case LIVE_DATA: - appa_55ii_live_data(sdi, buf); - break; - case LOG_METADATA: - appa_55ii_log_metadata(sdi, buf); - break; - case LOG_DATA: - appa_55ii_log_data(sdi, buf); - break; - case LOG_START: - break; - case LOG_END: - appa_55ii_log_end(sdi); - break; - default: - sr_warn("Invalid packet type: 0x%02x.", buf[2]); - break; - } - - return buf + 4 + buf[3] + 1; -} - -SR_PRIV int appa_55ii_receive_data(int fd, int revents, void *cb_data) -{ - struct sr_dev_inst *sdi; - struct dev_context *devc; - struct sr_serial_dev_inst *serial; - int64_t time; - const uint8_t *ptr, *next_ptr, *end_ptr; - int len; - - (void)fd; - - if (!(sdi = cb_data) || !(devc = sdi->priv) || revents != G_IO_IN) - return TRUE; - serial = sdi->conn; - - /* Try to get as much data as the buffer can hold. */ - len = sizeof(devc->buf) - devc->buf_len; - len = serial_read(serial, devc->buf + devc->buf_len, len); - if (len < 1) { - sr_err("Serial port read error: %d.", len); - return FALSE; - } - devc->buf_len += len; - - /* Now look for packets in that data. */ - ptr = devc->buf; - end_ptr = ptr + devc->buf_len; - while ((next_ptr = appa_55ii_parse_data(sdi, ptr, end_ptr - ptr))) - ptr = next_ptr; - - /* If we have any data left, move it to the beginning of our buffer. */ - memmove(devc->buf, ptr, end_ptr - ptr); - devc->buf_len -= ptr - devc->buf; - - /* If buffer is full and no valid packet was found, wipe buffer. */ - if (devc->buf_len >= sizeof(devc->buf)) { - devc->buf_len = 0; - return FALSE; - } - - if (devc->limit_samples && devc->num_samples >= devc->limit_samples) { - sr_info("Requested number of samples reached."); - sdi->driver->dev_acquisition_stop(sdi, devc->session_cb_data); - return TRUE; - } - - if (devc->limit_msec) { - time = (g_get_monotonic_time() - devc->start_time) / 1000; - if (time > (int64_t)devc->limit_msec) { - sr_info("Requested time limit reached."); - sdi->driver->dev_acquisition_stop(sdi, - devc->session_cb_data); - return TRUE; - } - } - - return TRUE; -} diff --git a/hardware/appa-55ii/protocol.h b/hardware/appa-55ii/protocol.h deleted file mode 100644 index fa3c2476..00000000 --- a/hardware/appa-55ii/protocol.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2013 Aurelien Jacobs - * - * 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 . - */ - -#ifndef LIBSIGROK_HARDWARE_APPA_55II_PROTOCOL_H -#define LIBSIGROK_HARDWARE_APPA_55II_PROTOCOL_H - -#include -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#define LOG_PREFIX "appa-55ii" - -#define APPA_55II_NUM_CHANNELS 2 -#define APPA_55II_BUF_SIZE (4 + 32 + 1) -#define DEFAULT_DATA_SOURCE DATA_SOURCE_LIVE - -enum { - DATA_SOURCE_LIVE, - DATA_SOURCE_MEMORY, -}; - -/** Private, per-device-instance driver context. */ -struct dev_context { - /* Acquisition settings */ - uint64_t limit_samples; /**< The sampling limit (in number of samples). */ - uint64_t limit_msec; /**< The time limit (in milliseconds). */ - gboolean data_source; /**< Whether to read live samples or memory */ - void *session_cb_data; /**< Opaque pointer passed in by the frontend. */ - - /* Operational state */ - uint64_t num_samples; /**< The number of already received samples. */ - int64_t start_time; /**< The time at which sampling started. */ - - /* Temporary state across callbacks */ - uint8_t buf[APPA_55II_BUF_SIZE]; - unsigned int buf_len; - uint8_t log_buf[64]; - unsigned int log_buf_len; - unsigned int num_log_records; -}; - -SR_PRIV gboolean appa_55ii_packet_valid(const uint8_t *buf); -SR_PRIV int appa_55ii_receive_data(int fd, int revents, void *cb_data); - -#endif diff --git a/hardware/asix-sigma/asix-sigma.c b/hardware/asix-sigma/asix-sigma.c deleted file mode 100644 index bfd69484..00000000 --- a/hardware/asix-sigma/asix-sigma.c +++ /dev/null @@ -1,1553 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2010-2012 HÃ¥vard Espeland , - * Copyright (C) 2010 Martin StensgÃ¥rd - * Copyright (C) 2010 Carl Henrik Lunde - * - * 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 . - */ - -/* - * ASIX SIGMA/SIGMA2 logic analyzer driver - */ - -#include -#include -#include -#include -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" -#include "asix-sigma.h" - -#define USB_VENDOR 0xa600 -#define USB_PRODUCT 0xa000 -#define USB_DESCRIPTION "ASIX SIGMA" -#define USB_VENDOR_NAME "ASIX" -#define USB_MODEL_NAME "SIGMA" - -SR_PRIV struct sr_dev_driver asix_sigma_driver_info; -static struct sr_dev_driver *di = &asix_sigma_driver_info; -static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data); - -/* - * The ASIX Sigma supports arbitrary integer frequency divider in - * the 50MHz mode. The divider is in range 1...256 , allowing for - * very precise sampling rate selection. This driver supports only - * a subset of the sampling rates. - */ -static const uint64_t samplerates[] = { - SR_KHZ(200), /* div=250 */ - SR_KHZ(250), /* div=200 */ - SR_KHZ(500), /* div=100 */ - SR_MHZ(1), /* div=50 */ - SR_MHZ(5), /* div=10 */ - SR_MHZ(10), /* div=5 */ - SR_MHZ(25), /* div=2 */ - SR_MHZ(50), /* div=1 */ - SR_MHZ(100), /* Special FW needed */ - SR_MHZ(200), /* Special FW needed */ -}; - -/* - * Channel numbers seem to go from 1-16, according to this image: - * http://tools.asix.net/img/sigma_sigmacab_pins_720.jpg - * (the cable has two additional GND pins, and a TI and TO pin) - */ -static const char *channel_names[] = { - "1", "2", "3", "4", "5", "6", "7", "8", - "9", "10", "11", "12", "13", "14", "15", "16", -}; - -static const int32_t hwcaps[] = { - SR_CONF_LOGIC_ANALYZER, - SR_CONF_SAMPLERATE, - SR_CONF_TRIGGER_MATCH, - SR_CONF_CAPTURE_RATIO, - SR_CONF_LIMIT_MSEC, -}; - -static const int32_t trigger_matches[] = { - SR_TRIGGER_ZERO, - SR_TRIGGER_ONE, - SR_TRIGGER_RISING, - SR_TRIGGER_FALLING, -}; - -static const char *sigma_firmware_files[] = { - /* 50 MHz, supports 8 bit fractions */ - FIRMWARE_DIR "/asix-sigma-50.fw", - /* 100 MHz */ - FIRMWARE_DIR "/asix-sigma-100.fw", - /* 200 MHz */ - FIRMWARE_DIR "/asix-sigma-200.fw", - /* Synchronous clock from pin */ - FIRMWARE_DIR "/asix-sigma-50sync.fw", - /* Frequency counter */ - FIRMWARE_DIR "/asix-sigma-phasor.fw", -}; - -static int sigma_read(void *buf, size_t size, struct dev_context *devc) -{ - int ret; - - ret = ftdi_read_data(&devc->ftdic, (unsigned char *)buf, size); - if (ret < 0) { - sr_err("ftdi_read_data failed: %s", - ftdi_get_error_string(&devc->ftdic)); - } - - return ret; -} - -static int sigma_write(void *buf, size_t size, struct dev_context *devc) -{ - int ret; - - ret = ftdi_write_data(&devc->ftdic, (unsigned char *)buf, size); - if (ret < 0) { - sr_err("ftdi_write_data failed: %s", - ftdi_get_error_string(&devc->ftdic)); - } else if ((size_t) ret != size) { - sr_err("ftdi_write_data did not complete write."); - } - - return ret; -} - -static int sigma_write_register(uint8_t reg, uint8_t *data, size_t len, - struct dev_context *devc) -{ - size_t i; - uint8_t buf[len + 2]; - int idx = 0; - - buf[idx++] = REG_ADDR_LOW | (reg & 0xf); - buf[idx++] = REG_ADDR_HIGH | (reg >> 4); - - for (i = 0; i < len; ++i) { - buf[idx++] = REG_DATA_LOW | (data[i] & 0xf); - buf[idx++] = REG_DATA_HIGH_WRITE | (data[i] >> 4); - } - - return sigma_write(buf, idx, devc); -} - -static int sigma_set_register(uint8_t reg, uint8_t value, struct dev_context *devc) -{ - return sigma_write_register(reg, &value, 1, devc); -} - -static int sigma_read_register(uint8_t reg, uint8_t *data, size_t len, - struct dev_context *devc) -{ - uint8_t buf[3]; - - buf[0] = REG_ADDR_LOW | (reg & 0xf); - buf[1] = REG_ADDR_HIGH | (reg >> 4); - buf[2] = REG_READ_ADDR; - - sigma_write(buf, sizeof(buf), devc); - - return sigma_read(data, len, devc); -} - -static uint8_t sigma_get_register(uint8_t reg, struct dev_context *devc) -{ - uint8_t value; - - if (1 != sigma_read_register(reg, &value, 1, devc)) { - sr_err("sigma_get_register: 1 byte expected"); - return 0; - } - - return value; -} - -static int sigma_read_pos(uint32_t *stoppos, uint32_t *triggerpos, - struct dev_context *devc) -{ - uint8_t buf[] = { - REG_ADDR_LOW | READ_TRIGGER_POS_LOW, - - REG_READ_ADDR | NEXT_REG, - REG_READ_ADDR | NEXT_REG, - REG_READ_ADDR | NEXT_REG, - REG_READ_ADDR | NEXT_REG, - REG_READ_ADDR | NEXT_REG, - REG_READ_ADDR | NEXT_REG, - }; - uint8_t result[6]; - - sigma_write(buf, sizeof(buf), devc); - - sigma_read(result, sizeof(result), devc); - - *triggerpos = result[0] | (result[1] << 8) | (result[2] << 16); - *stoppos = result[3] | (result[4] << 8) | (result[5] << 16); - - /* Not really sure why this must be done, but according to spec. */ - if ((--*stoppos & 0x1ff) == 0x1ff) - stoppos -= 64; - - if ((*--triggerpos & 0x1ff) == 0x1ff) - triggerpos -= 64; - - return 1; -} - -static int sigma_read_dram(uint16_t startchunk, size_t numchunks, - uint8_t *data, struct dev_context *devc) -{ - size_t i; - uint8_t buf[4096]; - int idx = 0; - - /* Send the startchunk. Index start with 1. */ - buf[0] = startchunk >> 8; - buf[1] = startchunk & 0xff; - sigma_write_register(WRITE_MEMROW, buf, 2, devc); - - /* Read the DRAM. */ - buf[idx++] = REG_DRAM_BLOCK; - buf[idx++] = REG_DRAM_WAIT_ACK; - - for (i = 0; i < numchunks; ++i) { - /* Alternate bit to copy from DRAM to cache. */ - if (i != (numchunks - 1)) - buf[idx++] = REG_DRAM_BLOCK | (((i + 1) % 2) << 4); - - buf[idx++] = REG_DRAM_BLOCK_DATA | ((i % 2) << 4); - - if (i != (numchunks - 1)) - buf[idx++] = REG_DRAM_WAIT_ACK; - } - - sigma_write(buf, idx, devc); - - return sigma_read(data, numchunks * CHUNK_SIZE, devc); -} - -/* Upload trigger look-up tables to Sigma. */ -static int sigma_write_trigger_lut(struct triggerlut *lut, struct dev_context *devc) -{ - int i; - uint8_t tmp[2]; - uint16_t bit; - - /* Transpose the table and send to Sigma. */ - for (i = 0; i < 16; ++i) { - bit = 1 << i; - - tmp[0] = tmp[1] = 0; - - if (lut->m2d[0] & bit) - tmp[0] |= 0x01; - if (lut->m2d[1] & bit) - tmp[0] |= 0x02; - if (lut->m2d[2] & bit) - tmp[0] |= 0x04; - if (lut->m2d[3] & bit) - tmp[0] |= 0x08; - - if (lut->m3 & bit) - tmp[0] |= 0x10; - if (lut->m3s & bit) - tmp[0] |= 0x20; - if (lut->m4 & bit) - tmp[0] |= 0x40; - - if (lut->m0d[0] & bit) - tmp[1] |= 0x01; - if (lut->m0d[1] & bit) - tmp[1] |= 0x02; - if (lut->m0d[2] & bit) - tmp[1] |= 0x04; - if (lut->m0d[3] & bit) - tmp[1] |= 0x08; - - if (lut->m1d[0] & bit) - tmp[1] |= 0x10; - if (lut->m1d[1] & bit) - tmp[1] |= 0x20; - if (lut->m1d[2] & bit) - tmp[1] |= 0x40; - if (lut->m1d[3] & bit) - tmp[1] |= 0x80; - - sigma_write_register(WRITE_TRIGGER_SELECT0, tmp, sizeof(tmp), - devc); - sigma_set_register(WRITE_TRIGGER_SELECT1, 0x30 | i, devc); - } - - /* Send the parameters */ - sigma_write_register(WRITE_TRIGGER_SELECT0, (uint8_t *) &lut->params, - sizeof(lut->params), devc); - - return SR_OK; -} - -static void clear_helper(void *priv) -{ - struct dev_context *devc; - - devc = priv; - - ftdi_deinit(&devc->ftdic); -} - -static int dev_clear(void) -{ - return std_dev_clear(di, clear_helper); -} - -static int init(struct sr_context *sr_ctx) -{ - return std_init(sr_ctx, di, LOG_PREFIX); -} - -static GSList *scan(GSList *options) -{ - struct sr_dev_inst *sdi; - struct sr_channel *ch; - struct drv_context *drvc; - struct dev_context *devc; - GSList *devices; - struct ftdi_device_list *devlist; - char serial_txt[10]; - uint32_t serial; - int ret; - unsigned int i; - - (void)options; - - drvc = di->priv; - - devices = NULL; - - if (!(devc = g_try_malloc(sizeof(struct dev_context)))) { - sr_err("%s: devc malloc failed", __func__); - return NULL; - } - - ftdi_init(&devc->ftdic); - - /* Look for SIGMAs. */ - - if ((ret = ftdi_usb_find_all(&devc->ftdic, &devlist, - USB_VENDOR, USB_PRODUCT)) <= 0) { - if (ret < 0) - sr_err("ftdi_usb_find_all(): %d", ret); - goto free; - } - - /* Make sure it's a version 1 or 2 SIGMA. */ - ftdi_usb_get_strings(&devc->ftdic, devlist->dev, NULL, 0, NULL, 0, - serial_txt, sizeof(serial_txt)); - sscanf(serial_txt, "%x", &serial); - - if (serial < 0xa6010000 || serial > 0xa602ffff) { - sr_err("Only SIGMA and SIGMA2 are supported " - "in this version of libsigrok."); - goto free; - } - - sr_info("Found ASIX SIGMA - Serial: %s", serial_txt); - - devc->cur_samplerate = samplerates[0]; - devc->period_ps = 0; - devc->limit_msec = 0; - devc->cur_firmware = -1; - devc->num_channels = 0; - devc->samples_per_event = 0; - devc->capture_ratio = 50; - devc->use_triggers = 0; - - /* Register SIGMA device. */ - if (!(sdi = sr_dev_inst_new(0, SR_ST_INITIALIZING, USB_VENDOR_NAME, - USB_MODEL_NAME, NULL))) { - sr_err("%s: sdi was NULL", __func__); - goto free; - } - sdi->driver = di; - - for (i = 0; i < ARRAY_SIZE(channel_names); i++) { - ch = sr_channel_new(i, SR_CHANNEL_LOGIC, TRUE, - channel_names[i]); - if (!ch) - return NULL; - sdi->channels = g_slist_append(sdi->channels, ch); - } - - devices = g_slist_append(devices, sdi); - drvc->instances = g_slist_append(drvc->instances, sdi); - sdi->priv = devc; - - /* We will open the device again when we need it. */ - ftdi_list_free(&devlist); - - return devices; - -free: - ftdi_deinit(&devc->ftdic); - g_free(devc); - return NULL; -} - -static GSList *dev_list(void) -{ - return ((struct drv_context *)(di->priv))->instances; -} - -/* - * Configure the FPGA for bitbang mode. - * This sequence is documented in section 2. of the ASIX Sigma programming - * manual. This sequence is necessary to configure the FPGA in the Sigma - * into Bitbang mode, in which it can be programmed with the firmware. - */ -static int sigma_fpga_init_bitbang(struct dev_context *devc) -{ - uint8_t suicide[] = { - 0x84, 0x84, 0x88, 0x84, 0x88, 0x84, 0x88, 0x84, - }; - uint8_t init_array[] = { - 0x01, 0x03, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, - }; - int i, ret, timeout = 10000; - uint8_t data; - - /* Section 2. part 1), do the FPGA suicide. */ - sigma_write(suicide, sizeof(suicide), devc); - sigma_write(suicide, sizeof(suicide), devc); - sigma_write(suicide, sizeof(suicide), devc); - sigma_write(suicide, sizeof(suicide), devc); - - /* Section 2. part 2), do pulse on D1. */ - sigma_write(init_array, sizeof(init_array), devc); - ftdi_usb_purge_buffers(&devc->ftdic); - - /* Wait until the FPGA asserts D6/INIT_B. */ - for (i = 0; i < timeout; i++) { - ret = sigma_read(&data, 1, devc); - if (ret < 0) - return ret; - /* Test if pin D6 got asserted. */ - if (data & (1 << 5)) - return 0; - /* The D6 was not asserted yet, wait a bit. */ - usleep(10000); - } - - return SR_ERR_TIMEOUT; -} - -/* - * Configure the FPGA for logic-analyzer mode. - */ -static int sigma_fpga_init_la(struct dev_context *devc) -{ - /* Initialize the logic analyzer mode. */ - uint8_t logic_mode_start[] = { - REG_ADDR_LOW | (READ_ID & 0xf), - REG_ADDR_HIGH | (READ_ID >> 8), - REG_READ_ADDR, /* Read ID register. */ - - REG_ADDR_LOW | (WRITE_TEST & 0xf), - REG_DATA_LOW | 0x5, - REG_DATA_HIGH_WRITE | 0x5, - REG_READ_ADDR, /* Read scratch register. */ - - REG_DATA_LOW | 0xa, - REG_DATA_HIGH_WRITE | 0xa, - REG_READ_ADDR, /* Read scratch register. */ - - REG_ADDR_LOW | (WRITE_MODE & 0xf), - REG_DATA_LOW | 0x0, - REG_DATA_HIGH_WRITE | 0x8, - }; - - uint8_t result[3]; - int ret; - - /* Initialize the logic analyzer mode. */ - sigma_write(logic_mode_start, sizeof(logic_mode_start), devc); - - /* Expect a 3 byte reply since we issued three READ requests. */ - ret = sigma_read(result, 3, devc); - if (ret != 3) - goto err; - - if (result[0] != 0xa6 || result[1] != 0x55 || result[2] != 0xaa) - goto err; - - return SR_OK; -err: - sr_err("Configuration failed. Invalid reply received."); - return SR_ERR; -} - -/* - * Read the firmware from a file and transform it into a series of bitbang - * pulses used to program the FPGA. Note that the *bb_cmd must be free()'d - * by the caller of this function. - */ -static int sigma_fw_2_bitbang(const char *filename, - uint8_t **bb_cmd, gsize *bb_cmd_size) -{ - GMappedFile *file; - GError *error; - gsize i, file_size, bb_size; - gchar *firmware; - uint8_t *bb_stream, *bbs; - uint32_t imm; - int bit, v; - int ret = SR_OK; - - /* - * Map the file and make the mapped buffer writable. - * NOTE: Using writable=TRUE does _NOT_ mean that file that is mapped - * will be modified. It will not be modified until someone uses - * g_file_set_contents() on it. - */ - error = NULL; - file = g_mapped_file_new(filename, TRUE, &error); - g_assert_no_error(error); - - file_size = g_mapped_file_get_length(file); - firmware = g_mapped_file_get_contents(file); - g_assert(firmware); - - /* Weird magic transformation below, I have no idea what it does. */ - imm = 0x3f6df2ab; - for (i = 0; i < file_size; i++) { - imm = (imm + 0xa853753) % 177 + (imm * 0x8034052); - firmware[i] ^= imm & 0xff; - } - - /* - * Now that the firmware is "transformed", we will transcribe the - * firmware blob into a sequence of toggles of the Dx wires. This - * sequence will be fed directly into the Sigma, which must be in - * the FPGA bitbang programming mode. - */ - - /* Each bit of firmware is transcribed as two toggles of Dx wires. */ - bb_size = file_size * 8 * 2; - bb_stream = (uint8_t *)g_try_malloc(bb_size); - if (!bb_stream) { - sr_err("%s: Failed to allocate bitbang stream", __func__); - ret = SR_ERR_MALLOC; - goto exit; - } - - bbs = bb_stream; - for (i = 0; i < file_size; i++) { - for (bit = 7; bit >= 0; bit--) { - v = (firmware[i] & (1 << bit)) ? 0x40 : 0x00; - *bbs++ = v | 0x01; - *bbs++ = v; - } - } - - /* The transformation completed successfully, return the result. */ - *bb_cmd = bb_stream; - *bb_cmd_size = bb_size; - -exit: - g_mapped_file_unref(file); - return ret; -} - -static int upload_firmware(int firmware_idx, struct dev_context *devc) -{ - int ret; - unsigned char *buf; - unsigned char pins; - size_t buf_size; - const char *firmware = sigma_firmware_files[firmware_idx]; - struct ftdi_context *ftdic = &devc->ftdic; - - /* Make sure it's an ASIX SIGMA. */ - ret = ftdi_usb_open_desc(ftdic, USB_VENDOR, USB_PRODUCT, - USB_DESCRIPTION, NULL); - if (ret < 0) { - sr_err("ftdi_usb_open failed: %s", - ftdi_get_error_string(ftdic)); - return 0; - } - - ret = ftdi_set_bitmode(ftdic, 0xdf, BITMODE_BITBANG); - if (ret < 0) { - sr_err("ftdi_set_bitmode failed: %s", - ftdi_get_error_string(ftdic)); - return 0; - } - - /* Four times the speed of sigmalogan - Works well. */ - ret = ftdi_set_baudrate(ftdic, 750000); - if (ret < 0) { - sr_err("ftdi_set_baudrate failed: %s", - ftdi_get_error_string(ftdic)); - return 0; - } - - /* Initialize the FPGA for firmware upload. */ - ret = sigma_fpga_init_bitbang(devc); - if (ret) - return ret; - - /* Prepare firmware. */ - ret = sigma_fw_2_bitbang(firmware, &buf, &buf_size); - if (ret != SR_OK) { - sr_err("An error occured while reading the firmware: %s", - firmware); - return ret; - } - - /* Upload firmare. */ - sr_info("Uploading firmware file '%s'.", firmware); - sigma_write(buf, buf_size, devc); - - g_free(buf); - - ret = ftdi_set_bitmode(ftdic, 0x00, BITMODE_RESET); - if (ret < 0) { - sr_err("ftdi_set_bitmode failed: %s", - ftdi_get_error_string(ftdic)); - return SR_ERR; - } - - ftdi_usb_purge_buffers(ftdic); - - /* Discard garbage. */ - while (sigma_read(&pins, 1, devc) == 1) - ; - - /* Initialize the FPGA for logic-analyzer mode. */ - ret = sigma_fpga_init_la(devc); - if (ret != SR_OK) - return ret; - - devc->cur_firmware = firmware_idx; - - sr_info("Firmware uploaded."); - - return SR_OK; -} - -static int dev_open(struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - int ret; - - devc = sdi->priv; - - /* Make sure it's an ASIX SIGMA. */ - if ((ret = ftdi_usb_open_desc(&devc->ftdic, - USB_VENDOR, USB_PRODUCT, USB_DESCRIPTION, NULL)) < 0) { - - sr_err("ftdi_usb_open failed: %s", - ftdi_get_error_string(&devc->ftdic)); - - return 0; - } - - sdi->status = SR_ST_ACTIVE; - - return SR_OK; -} - -static int set_samplerate(const struct sr_dev_inst *sdi, uint64_t samplerate) -{ - struct dev_context *devc; - unsigned int i; - int ret; - - devc = sdi->priv; - ret = SR_OK; - - for (i = 0; i < ARRAY_SIZE(samplerates); i++) { - if (samplerates[i] == samplerate) - break; - } - if (samplerates[i] == 0) - return SR_ERR_SAMPLERATE; - - if (samplerate <= SR_MHZ(50)) { - ret = upload_firmware(0, devc); - devc->num_channels = 16; - } else if (samplerate == SR_MHZ(100)) { - ret = upload_firmware(1, devc); - devc->num_channels = 8; - } else if (samplerate == SR_MHZ(200)) { - ret = upload_firmware(2, devc); - devc->num_channels = 4; - } - - if (ret == SR_OK) { - devc->cur_samplerate = samplerate; - devc->period_ps = 1000000000000ULL / samplerate; - devc->samples_per_event = 16 / devc->num_channels; - devc->state.state = SIGMA_IDLE; - } - - return ret; -} - -/* - * In 100 and 200 MHz mode, only a single pin rising/falling can be - * set as trigger. In other modes, two rising/falling triggers can be set, - * in addition to value/mask trigger for any number of channels. - * - * The Sigma supports complex triggers using boolean expressions, but this - * has not been implemented yet. - */ -static int convert_trigger(const struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - struct sr_trigger *trigger; - struct sr_trigger_stage *stage; - struct sr_trigger_match *match; - const GSList *l, *m; - int channelbit, trigger_set; - - devc = sdi->priv; - memset(&devc->trigger, 0, sizeof(struct sigma_trigger)); - if (!(trigger = sr_session_trigger_get(sdi->session))) - return SR_OK; - - trigger_set = 0; - for (l = trigger->stages; l; l = l->next) { - stage = l->data; - for (m = stage->matches; m; m = m->next) { - match = m->data; - if (!match->channel->enabled) - /* Ignore disabled channels with a trigger. */ - continue; - channelbit = 1 << (match->channel->index); - if (devc->cur_samplerate >= SR_MHZ(100)) { - /* Fast trigger support. */ - if (trigger_set) { - sr_err("Only a single pin trigger is " - "supported in 100 and 200MHz mode."); - return SR_ERR; - } - if (match->match == SR_TRIGGER_FALLING) - devc->trigger.fallingmask |= channelbit; - else if (match->match == SR_TRIGGER_RISING) - devc->trigger.risingmask |= channelbit; - else { - sr_err("Only rising/falling trigger is " - "supported in 100 and 200MHz mode."); - return SR_ERR; - } - - ++trigger_set; - } else { - /* Simple trigger support (event). */ - if (match->match == SR_TRIGGER_ONE) { - devc->trigger.simplevalue |= channelbit; - devc->trigger.simplemask |= channelbit; - } - else if (match->match == SR_TRIGGER_ZERO) { - devc->trigger.simplevalue &= ~channelbit; - devc->trigger.simplemask |= channelbit; - } - else if (match->match == SR_TRIGGER_FALLING) { - devc->trigger.fallingmask |= channelbit; - ++trigger_set; - } - else if (match->match == SR_TRIGGER_RISING) { - devc->trigger.risingmask |= channelbit; - ++trigger_set; - } - - /* - * Actually, Sigma supports 2 rising/falling triggers, - * but they are ORed and the current trigger syntax - * does not permit ORed triggers. - */ - if (trigger_set > 1) { - sr_err("Only 1 rising/falling trigger " - "is supported."); - return SR_ERR; - } - } - } - } - - - return SR_OK; -} - -static int dev_close(struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - - devc = sdi->priv; - - /* TODO */ - if (sdi->status == SR_ST_ACTIVE) - ftdi_usb_close(&devc->ftdic); - - sdi->status = SR_ST_INACTIVE; - - return SR_OK; -} - -static int cleanup(void) -{ - return dev_clear(); -} - -static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc; - - (void)cg; - - if (!sdi) - return SR_ERR; - devc = sdi->priv; - - switch (id) { - case SR_CONF_SAMPLERATE: - *data = g_variant_new_uint64(devc->cur_samplerate); - break; - case SR_CONF_LIMIT_MSEC: - *data = g_variant_new_uint64(devc->limit_msec); - break; - case SR_CONF_CAPTURE_RATIO: - *data = g_variant_new_uint64(devc->capture_ratio); - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc; - uint64_t tmp; - int ret; - - (void)cg; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - devc = sdi->priv; - - ret = SR_OK; - switch (id) { - case SR_CONF_SAMPLERATE: - ret = set_samplerate(sdi, g_variant_get_uint64(data)); - break; - case SR_CONF_LIMIT_MSEC: - tmp = g_variant_get_uint64(data); - if (tmp > 0) - devc->limit_msec = g_variant_get_uint64(data); - else - ret = SR_ERR; - break; - case SR_CONF_LIMIT_SAMPLES: - tmp = g_variant_get_uint64(data); - devc->limit_msec = tmp * 1000 / devc->cur_samplerate; - break; - case SR_CONF_CAPTURE_RATIO: - tmp = g_variant_get_uint64(data); - if (tmp <= 100) - devc->capture_ratio = tmp; - else - ret = SR_ERR; - break; - default: - ret = SR_ERR_NA; - } - - return ret; -} - -static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - GVariant *gvar; - GVariantBuilder gvb; - - (void)sdi; - (void)cg; - - switch (key) { - case SR_CONF_DEVICE_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t)); - break; - case SR_CONF_SAMPLERATE: - g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}")); - gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates, - ARRAY_SIZE(samplerates), sizeof(uint64_t)); - g_variant_builder_add(&gvb, "{sv}", "samplerates", gvar); - *data = g_variant_builder_end(&gvb); - break; - case SR_CONF_TRIGGER_MATCH: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - trigger_matches, ARRAY_SIZE(trigger_matches), - sizeof(int32_t)); - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -/* Software trigger to determine exact trigger position. */ -static int get_trigger_offset(uint8_t *samples, uint16_t last_sample, - struct sigma_trigger *t) -{ - int i; - uint16_t sample = 0; - - for (i = 0; i < 8; ++i) { - if (i > 0) - last_sample = sample; - sample = samples[2 * i] | (samples[2 * i + 1] << 8); - - /* Simple triggers. */ - if ((sample & t->simplemask) != t->simplevalue) - continue; - - /* Rising edge. */ - if (((last_sample & t->risingmask) != 0) || - ((sample & t->risingmask) != t->risingmask)) - continue; - - /* Falling edge. */ - if ((last_sample & t->fallingmask) != t->fallingmask || - (sample & t->fallingmask) != 0) - continue; - - break; - } - - /* If we did not match, return original trigger pos. */ - return i & 0x7; -} - - -/* - * Return the timestamp of "DRAM cluster". - */ -static uint16_t sigma_dram_cluster_ts(struct sigma_dram_cluster *cluster) -{ - return (cluster->timestamp_hi << 8) | cluster->timestamp_lo; -} - -static void sigma_decode_dram_cluster(struct sigma_dram_cluster *dram_cluster, - unsigned int events_in_cluster, - unsigned int triggered, - struct sr_dev_inst *sdi) -{ - struct dev_context *devc = sdi->priv; - struct sigma_state *ss = &devc->state; - struct sr_datafeed_packet packet; - struct sr_datafeed_logic logic; - uint16_t tsdiff, ts; - uint8_t samples[2048]; - unsigned int i; - - ts = sigma_dram_cluster_ts(dram_cluster); - tsdiff = ts - ss->lastts; - ss->lastts = ts; - - packet.type = SR_DF_LOGIC; - packet.payload = &logic; - logic.unitsize = 2; - logic.data = samples; - - /* - * First of all, send Sigrok a copy of the last sample from - * previous cluster as many times as needed to make up for - * the differential characteristics of data we get from the - * Sigma. Sigrok needs one sample of data per period. - * - * One DRAM cluster contains a timestamp and seven samples, - * the units of timestamp are "devc->period_ps" , the first - * sample in the cluster happens at the time of the timestamp - * and the remaining samples happen at timestamp +1...+6 . - */ - for (ts = 0; ts < tsdiff - (EVENTS_PER_CLUSTER - 1); ts++) { - i = ts % 1024; - samples[2 * i + 0] = ss->lastsample & 0xff; - samples[2 * i + 1] = ss->lastsample >> 8; - - /* - * If we have 1024 samples ready or we're at the - * end of submitting the padding samples, submit - * the packet to Sigrok. - */ - if ((i == 1023) || (ts == (tsdiff - EVENTS_PER_CLUSTER))) { - logic.length = (i + 1) * logic.unitsize; - sr_session_send(sdi, &packet); - } - } - - /* - * Parse the samples in current cluster and prepare them - * to be submitted to Sigrok. - */ - for (i = 0; i < events_in_cluster; i++) { - samples[2 * i + 1] = dram_cluster->samples[i].sample_lo; - samples[2 * i + 0] = dram_cluster->samples[i].sample_hi; - } - - /* Send data up to trigger point (if triggered). */ - int trigger_offset = 0; - if (triggered) { - /* - * Trigger is not always accurate to sample because of - * pipeline delay. However, it always triggers before - * the actual event. We therefore look at the next - * samples to pinpoint the exact position of the trigger. - */ - trigger_offset = get_trigger_offset(samples, - ss->lastsample, &devc->trigger); - - if (trigger_offset > 0) { - packet.type = SR_DF_LOGIC; - logic.length = trigger_offset * logic.unitsize; - sr_session_send(sdi, &packet); - events_in_cluster -= trigger_offset; - } - - /* Only send trigger if explicitly enabled. */ - if (devc->use_triggers) { - packet.type = SR_DF_TRIGGER; - sr_session_send(sdi, &packet); - } - } - - if (events_in_cluster > 0) { - packet.type = SR_DF_LOGIC; - logic.length = events_in_cluster * logic.unitsize; - logic.data = samples + (trigger_offset * logic.unitsize); - sr_session_send(sdi, &packet); - } - - ss->lastsample = - samples[2 * (events_in_cluster - 1) + 0] | - (samples[2 * (events_in_cluster - 1) + 1] << 8); - -} - -/* - * Decode chunk of 1024 bytes, 64 clusters, 7 events per cluster. - * Each event is 20ns apart, and can contain multiple samples. - * - * For 200 MHz, events contain 4 samples for each channel, spread 5 ns apart. - * For 100 MHz, events contain 2 samples for each channel, spread 10 ns apart. - * For 50 MHz and below, events contain one sample for each channel, - * spread 20 ns apart. - */ -static int decode_chunk_ts(struct sigma_dram_line *dram_line, - uint16_t events_in_line, - uint32_t trigger_event, - struct sr_dev_inst *sdi) -{ - struct sigma_dram_cluster *dram_cluster; - struct dev_context *devc = sdi->priv; - unsigned int clusters_in_line = - (events_in_line + (EVENTS_PER_CLUSTER - 1)) / EVENTS_PER_CLUSTER; - unsigned int events_in_cluster; - unsigned int i; - uint32_t trigger_cluster = ~0, triggered = 0; - - /* Check if trigger is in this chunk. */ - if (trigger_event < (64 * 7)) { - if (devc->cur_samplerate <= SR_MHZ(50)) { - trigger_event -= MIN(EVENTS_PER_CLUSTER - 1, - trigger_event); - } - - /* Find in which cluster the trigger occured. */ - trigger_cluster = trigger_event / EVENTS_PER_CLUSTER; - } - - /* For each full DRAM cluster. */ - for (i = 0; i < clusters_in_line; i++) { - dram_cluster = &dram_line->cluster[i]; - - /* The last cluster might not be full. */ - if ((i == clusters_in_line - 1) && - (events_in_line % EVENTS_PER_CLUSTER)) { - events_in_cluster = events_in_line % EVENTS_PER_CLUSTER; - } else { - events_in_cluster = EVENTS_PER_CLUSTER; - } - - triggered = (i == trigger_cluster); - sigma_decode_dram_cluster(dram_cluster, events_in_cluster, - triggered, sdi); - } - - return SR_OK; -} - -static int download_capture(struct sr_dev_inst *sdi) -{ - struct dev_context *devc = sdi->priv; - const uint32_t chunks_per_read = 32; - struct sigma_dram_line *dram_line; - int bufsz; - uint32_t stoppos, triggerpos; - struct sr_datafeed_packet packet; - uint8_t modestatus; - - uint32_t i; - uint32_t dl_lines_total, dl_lines_curr, dl_lines_done; - uint32_t dl_events_in_line = 64 * 7; - uint32_t trg_line = ~0, trg_event = ~0; - - dram_line = g_try_malloc0(chunks_per_read * sizeof(*dram_line)); - if (!dram_line) - return FALSE; - - sr_info("Downloading sample data."); - - /* Stop acquisition. */ - sigma_set_register(WRITE_MODE, 0x11, devc); - - /* Set SDRAM Read Enable. */ - sigma_set_register(WRITE_MODE, 0x02, devc); - - /* Get the current position. */ - sigma_read_pos(&stoppos, &triggerpos, devc); - - /* Check if trigger has fired. */ - modestatus = sigma_get_register(READ_MODE, devc); - if (modestatus & 0x20) { - trg_line = triggerpos >> 9; - trg_event = triggerpos & 0x1ff; - } - - /* - * Determine how many 1024b "DRAM lines" do we need to read from the - * Sigma so we have a complete set of samples. Note that the last - * line can be only partial, containing less than 64 clusters. - */ - dl_lines_total = (stoppos >> 9) + 1; - - dl_lines_done = 0; - - while (dl_lines_total > dl_lines_done) { - /* We can download only up-to 32 DRAM lines in one go! */ - dl_lines_curr = MIN(chunks_per_read, dl_lines_total); - - bufsz = sigma_read_dram(dl_lines_done, dl_lines_curr, - (uint8_t *)dram_line, devc); - /* TODO: Check bufsz. For now, just avoid compiler warnings. */ - (void)bufsz; - - /* This is the first DRAM line, so find the initial timestamp. */ - if (dl_lines_done == 0) { - devc->state.lastts = - sigma_dram_cluster_ts(&dram_line[0].cluster[0]); - devc->state.lastsample = 0; - } - - for (i = 0; i < dl_lines_curr; i++) { - uint32_t trigger_event = ~0; - /* The last "DRAM line" can be only partially full. */ - if (dl_lines_done + i == dl_lines_total - 1) - dl_events_in_line = stoppos & 0x1ff; - - /* Test if the trigger happened on this line. */ - if (dl_lines_done + i == trg_line) - trigger_event = trg_event; - - decode_chunk_ts(dram_line + i, dl_events_in_line, - trigger_event, sdi); - } - - dl_lines_done += dl_lines_curr; - } - - /* All done. */ - packet.type = SR_DF_END; - sr_session_send(sdi, &packet); - - dev_acquisition_stop(sdi, sdi); - - g_free(dram_line); - - return TRUE; -} - -/* - * Handle the Sigma when in CAPTURE mode. This function checks: - * - Sampling time ended - * - DRAM capacity overflow - * This function triggers download of the samples from Sigma - * in case either of the above conditions is true. - */ -static int sigma_capture_mode(struct sr_dev_inst *sdi) -{ - struct dev_context *devc = sdi->priv; - - uint64_t running_msec; - struct timeval tv; - - uint32_t stoppos, triggerpos; - - /* Check if the selected sampling duration passed. */ - gettimeofday(&tv, 0); - running_msec = (tv.tv_sec - devc->start_tv.tv_sec) * 1000 + - (tv.tv_usec - devc->start_tv.tv_usec) / 1000; - if (running_msec >= devc->limit_msec) - return download_capture(sdi); - - /* Get the position in DRAM to which the FPGA is writing now. */ - sigma_read_pos(&stoppos, &triggerpos, devc); - /* Test if DRAM is full and if so, download the data. */ - if ((stoppos >> 9) == 32767) - return download_capture(sdi); - - return TRUE; -} - -static int receive_data(int fd, int revents, void *cb_data) -{ - struct sr_dev_inst *sdi; - struct dev_context *devc; - - (void)fd; - (void)revents; - - sdi = cb_data; - devc = sdi->priv; - - if (devc->state.state == SIGMA_IDLE) - return TRUE; - - if (devc->state.state == SIGMA_CAPTURE) - return sigma_capture_mode(sdi); - - return TRUE; -} - -/* Build a LUT entry used by the trigger functions. */ -static void build_lut_entry(uint16_t value, uint16_t mask, uint16_t *entry) -{ - int i, j, k, bit; - - /* For each quad channel. */ - for (i = 0; i < 4; ++i) { - entry[i] = 0xffff; - - /* For each bit in LUT. */ - for (j = 0; j < 16; ++j) - - /* For each channel in quad. */ - for (k = 0; k < 4; ++k) { - bit = 1 << (i * 4 + k); - - /* Set bit in entry */ - if ((mask & bit) && - ((!(value & bit)) != - (!(j & (1 << k))))) - entry[i] &= ~(1 << j); - } - } -} - -/* Add a logical function to LUT mask. */ -static void add_trigger_function(enum triggerop oper, enum triggerfunc func, - int index, int neg, uint16_t *mask) -{ - int i, j; - int x[2][2], tmp, a, b, aset, bset, rset; - - memset(x, 0, 4 * sizeof(int)); - - /* Trigger detect condition. */ - switch (oper) { - case OP_LEVEL: - x[0][1] = 1; - x[1][1] = 1; - break; - case OP_NOT: - x[0][0] = 1; - x[1][0] = 1; - break; - case OP_RISE: - x[0][1] = 1; - break; - case OP_FALL: - x[1][0] = 1; - break; - case OP_RISEFALL: - x[0][1] = 1; - x[1][0] = 1; - break; - case OP_NOTRISE: - x[1][1] = 1; - x[0][0] = 1; - x[1][0] = 1; - break; - case OP_NOTFALL: - x[1][1] = 1; - x[0][0] = 1; - x[0][1] = 1; - break; - case OP_NOTRISEFALL: - x[1][1] = 1; - x[0][0] = 1; - break; - } - - /* Transpose if neg is set. */ - if (neg) { - for (i = 0; i < 2; ++i) { - for (j = 0; j < 2; ++j) { - tmp = x[i][j]; - x[i][j] = x[1-i][1-j]; - x[1-i][1-j] = tmp; - } - } - } - - /* Update mask with function. */ - for (i = 0; i < 16; ++i) { - a = (i >> (2 * index + 0)) & 1; - b = (i >> (2 * index + 1)) & 1; - - aset = (*mask >> i) & 1; - bset = x[b][a]; - - if (func == FUNC_AND || func == FUNC_NAND) - rset = aset & bset; - else if (func == FUNC_OR || func == FUNC_NOR) - rset = aset | bset; - else if (func == FUNC_XOR || func == FUNC_NXOR) - rset = aset ^ bset; - - if (func == FUNC_NAND || func == FUNC_NOR || func == FUNC_NXOR) - rset = !rset; - - *mask &= ~(1 << i); - - if (rset) - *mask |= 1 << i; - } -} - -/* - * Build trigger LUTs used by 50 MHz and lower sample rates for supporting - * simple pin change and state triggers. Only two transitions (rise/fall) can be - * set at any time, but a full mask and value can be set (0/1). - */ -static int build_basic_trigger(struct triggerlut *lut, struct dev_context *devc) -{ - int i,j; - uint16_t masks[2] = { 0, 0 }; - - memset(lut, 0, sizeof(struct triggerlut)); - - /* Contant for simple triggers. */ - lut->m4 = 0xa000; - - /* Value/mask trigger support. */ - build_lut_entry(devc->trigger.simplevalue, devc->trigger.simplemask, - lut->m2d); - - /* Rise/fall trigger support. */ - for (i = 0, j = 0; i < 16; ++i) { - if (devc->trigger.risingmask & (1 << i) || - devc->trigger.fallingmask & (1 << i)) - masks[j++] = 1 << i; - } - - build_lut_entry(masks[0], masks[0], lut->m0d); - build_lut_entry(masks[1], masks[1], lut->m1d); - - /* Add glue logic */ - if (masks[0] || masks[1]) { - /* Transition trigger. */ - if (masks[0] & devc->trigger.risingmask) - add_trigger_function(OP_RISE, FUNC_OR, 0, 0, &lut->m3); - if (masks[0] & devc->trigger.fallingmask) - add_trigger_function(OP_FALL, FUNC_OR, 0, 0, &lut->m3); - if (masks[1] & devc->trigger.risingmask) - add_trigger_function(OP_RISE, FUNC_OR, 1, 0, &lut->m3); - if (masks[1] & devc->trigger.fallingmask) - add_trigger_function(OP_FALL, FUNC_OR, 1, 0, &lut->m3); - } else { - /* Only value/mask trigger. */ - lut->m3 = 0xffff; - } - - /* Triggertype: event. */ - lut->params.selres = 3; - - return SR_OK; -} - -static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) -{ - struct dev_context *devc; - struct clockselect_50 clockselect; - int frac, triggerpin, ret; - uint8_t triggerselect = 0; - struct triggerinout triggerinout_conf; - struct triggerlut lut; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - devc = sdi->priv; - - if (convert_trigger(sdi) != SR_OK) { - sr_err("Failed to configure triggers."); - return SR_ERR; - } - - /* If the samplerate has not been set, default to 200 kHz. */ - if (devc->cur_firmware == -1) { - if ((ret = set_samplerate(sdi, SR_KHZ(200))) != SR_OK) - return ret; - } - - /* Enter trigger programming mode. */ - sigma_set_register(WRITE_TRIGGER_SELECT1, 0x20, devc); - - /* 100 and 200 MHz mode. */ - if (devc->cur_samplerate >= SR_MHZ(100)) { - sigma_set_register(WRITE_TRIGGER_SELECT1, 0x81, devc); - - /* Find which pin to trigger on from mask. */ - for (triggerpin = 0; triggerpin < 8; ++triggerpin) - if ((devc->trigger.risingmask | devc->trigger.fallingmask) & - (1 << triggerpin)) - break; - - /* Set trigger pin and light LED on trigger. */ - triggerselect = (1 << LEDSEL1) | (triggerpin & 0x7); - - /* Default rising edge. */ - if (devc->trigger.fallingmask) - triggerselect |= 1 << 3; - - /* All other modes. */ - } else if (devc->cur_samplerate <= SR_MHZ(50)) { - build_basic_trigger(&lut, devc); - - sigma_write_trigger_lut(&lut, devc); - - triggerselect = (1 << LEDSEL1) | (1 << LEDSEL0); - } - - /* Setup trigger in and out pins to default values. */ - memset(&triggerinout_conf, 0, sizeof(struct triggerinout)); - triggerinout_conf.trgout_bytrigger = 1; - triggerinout_conf.trgout_enable = 1; - - sigma_write_register(WRITE_TRIGGER_OPTION, - (uint8_t *) &triggerinout_conf, - sizeof(struct triggerinout), devc); - - /* Go back to normal mode. */ - sigma_set_register(WRITE_TRIGGER_SELECT1, triggerselect, devc); - - /* Set clock select register. */ - if (devc->cur_samplerate == SR_MHZ(200)) - /* Enable 4 channels. */ - sigma_set_register(WRITE_CLOCK_SELECT, 0xf0, devc); - else if (devc->cur_samplerate == SR_MHZ(100)) - /* Enable 8 channels. */ - sigma_set_register(WRITE_CLOCK_SELECT, 0x00, devc); - else { - /* - * 50 MHz mode (or fraction thereof). Any fraction down to - * 50 MHz / 256 can be used, but is not supported by sigrok API. - */ - frac = SR_MHZ(50) / devc->cur_samplerate - 1; - - clockselect.async = 0; - clockselect.fraction = frac; - clockselect.disabled_channels = 0; - - sigma_write_register(WRITE_CLOCK_SELECT, - (uint8_t *) &clockselect, - sizeof(clockselect), devc); - } - - /* Setup maximum post trigger time. */ - sigma_set_register(WRITE_POST_TRIGGER, - (devc->capture_ratio * 255) / 100, devc); - - /* Start acqusition. */ - gettimeofday(&devc->start_tv, 0); - sigma_set_register(WRITE_MODE, 0x0d, devc); - - devc->cb_data = cb_data; - - /* Send header packet to the session bus. */ - std_session_send_df_header(sdi, LOG_PREFIX); - - /* Add capture source. */ - sr_session_source_add(sdi->session, 0, G_IO_IN, 10, receive_data, (void *)sdi); - - devc->state.state = SIGMA_CAPTURE; - - return SR_OK; -} - -static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) -{ - struct dev_context *devc; - - (void)cb_data; - - devc = sdi->priv; - devc->state.state = SIGMA_IDLE; - - sr_session_source_remove(sdi->session, 0); - - return SR_OK; -} - -SR_PRIV struct sr_dev_driver asix_sigma_driver_info = { - .name = "asix-sigma", - .longname = "ASIX SIGMA/SIGMA2", - .api_version = 1, - .init = init, - .cleanup = cleanup, - .scan = scan, - .dev_list = dev_list, - .dev_clear = dev_clear, - .config_get = config_get, - .config_set = config_set, - .config_list = config_list, - .dev_open = dev_open, - .dev_close = dev_close, - .dev_acquisition_start = dev_acquisition_start, - .dev_acquisition_stop = dev_acquisition_stop, - .priv = NULL, -}; diff --git a/hardware/asix-sigma/asix-sigma.h b/hardware/asix-sigma/asix-sigma.h deleted file mode 100644 index 4c9deff6..00000000 --- a/hardware/asix-sigma/asix-sigma.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2010 HÃ¥vard Espeland , - * Copyright (C) 2010 Martin StensgÃ¥rd - * Copyright (C) 2010 Carl Henrik Lunde - * - * 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 . - */ - -#ifndef LIBSIGROK_HARDWARE_ASIX_SIGMA_ASIX_SIGMA_H -#define LIBSIGROK_HARDWARE_ASIX_SIGMA_ASIX_SIGMA_H - -#define LOG_PREFIX "asix-sigma" - -enum sigma_write_register { - WRITE_CLOCK_SELECT = 0, - WRITE_TRIGGER_SELECT0 = 1, - WRITE_TRIGGER_SELECT1 = 2, - WRITE_MODE = 3, - WRITE_MEMROW = 4, - WRITE_POST_TRIGGER = 5, - WRITE_TRIGGER_OPTION = 6, - WRITE_PIN_VIEW = 7, - - WRITE_TEST = 15, -}; - -enum sigma_read_register { - READ_ID = 0, - READ_TRIGGER_POS_LOW = 1, - READ_TRIGGER_POS_HIGH = 2, - READ_TRIGGER_POS_UP = 3, - READ_STOP_POS_LOW = 4, - READ_STOP_POS_HIGH = 5, - READ_STOP_POS_UP = 6, - READ_MODE = 7, - READ_PIN_CHANGE_LOW = 8, - READ_PIN_CHANGE_HIGH = 9, - READ_BLOCK_LAST_TS_LOW = 10, - READ_BLOCK_LAST_TS_HIGH = 11, - READ_PIN_VIEW = 12, - - READ_TEST = 15, -}; - -#define REG_ADDR_LOW (0x0 << 4) -#define REG_ADDR_HIGH (0x1 << 4) -#define REG_DATA_LOW (0x2 << 4) -#define REG_DATA_HIGH_WRITE (0x3 << 4) -#define REG_READ_ADDR (0x4 << 4) -#define REG_DRAM_WAIT_ACK (0x5 << 4) - -/* Bit (1 << 4) can be low or high (double buffer / cache) */ -#define REG_DRAM_BLOCK (0x6 << 4) -#define REG_DRAM_BLOCK_BEGIN (0x8 << 4) -#define REG_DRAM_BLOCK_DATA (0xa << 4) - -#define LEDSEL0 6 -#define LEDSEL1 7 - -#define NEXT_REG 1 - -#define EVENTS_PER_CLUSTER 7 - -#define CHUNK_SIZE 1024 - -/* - * The entire ASIX Sigma DRAM is an array of struct sigma_dram_line[1024]; - */ - -/* One "DRAM cluster" contains a timestamp and 7 samples, 16b total. */ -struct sigma_dram_cluster { - uint8_t timestamp_lo; - uint8_t timestamp_hi; - struct { - uint8_t sample_hi; - uint8_t sample_lo; - } samples[7]; -}; - -/* One "DRAM line" contains 64 "DRAM clusters", 1024b total. */ -struct sigma_dram_line { - struct sigma_dram_cluster cluster[64]; -}; - -struct clockselect_50 { - uint8_t async; - uint8_t fraction; - uint16_t disabled_channels; -}; - -/* The effect of all these are still a bit unclear. */ -struct triggerinout { - uint8_t trgout_resistor_enable : 1; - uint8_t trgout_resistor_pullup : 1; - uint8_t reserved1 : 1; - uint8_t trgout_bytrigger : 1; - uint8_t trgout_byevent : 1; - uint8_t trgout_bytriggerin : 1; - uint8_t reserved2 : 2; - - /* Should be set same as the first two */ - uint8_t trgout_resistor_enable2 : 1; - uint8_t trgout_resistor_pullup2 : 1; - - uint8_t reserved3 : 1; - uint8_t trgout_long : 1; - uint8_t trgout_pin : 1; /* Use 1k resistor. Pullup? */ - uint8_t trgin_negate : 1; - uint8_t trgout_enable : 1; - uint8_t trgin_enable : 1; -}; - -struct triggerlut { - /* The actual LUTs. */ - uint16_t m0d[4], m1d[4], m2d[4]; - uint16_t m3, m3s, m4; - - /* Paramters should be sent as a single register write. */ - struct { - uint8_t selc : 2; - uint8_t selpresc : 6; - - uint8_t selinc : 2; - uint8_t selres : 2; - uint8_t sela : 2; - uint8_t selb : 2; - - uint16_t cmpb; - uint16_t cmpa; - } params; -}; - -/* Trigger configuration */ -struct sigma_trigger { - /* Only two channels can be used in mask. */ - uint16_t risingmask; - uint16_t fallingmask; - - /* Simple trigger support (<= 50 MHz). */ - uint16_t simplemask; - uint16_t simplevalue; - - /* TODO: Advanced trigger support (boolean expressions). */ -}; - -/* Events for trigger operation. */ -enum triggerop { - OP_LEVEL = 1, - OP_NOT, - OP_RISE, - OP_FALL, - OP_RISEFALL, - OP_NOTRISE, - OP_NOTFALL, - OP_NOTRISEFALL, -}; - -/* Logical functions for trigger operation. */ -enum triggerfunc { - FUNC_AND = 1, - FUNC_NAND, - FUNC_OR, - FUNC_NOR, - FUNC_XOR, - FUNC_NXOR, -}; - -struct sigma_state { - enum { - SIGMA_UNINITIALIZED = 0, - SIGMA_IDLE, - SIGMA_CAPTURE, - SIGMA_DOWNLOAD, - } state; - - uint16_t lastts; - uint16_t lastsample; -}; - -/* Private, per-device-instance driver context. */ -struct dev_context { - struct ftdi_context ftdic; - uint64_t cur_samplerate; - uint64_t period_ps; - uint64_t limit_msec; - struct timeval start_tv; - int cur_firmware; - int num_channels; - int cur_channels; - int samples_per_event; - int capture_ratio; - struct sigma_trigger trigger; - int use_triggers; - struct sigma_state state; - void *cb_data; -}; - -#endif diff --git a/hardware/atten-pps3xxx/api.c b/hardware/atten-pps3xxx/api.c deleted file mode 100644 index 5ca3dbe9..00000000 --- a/hardware/atten-pps3xxx/api.c +++ /dev/null @@ -1,518 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2014 Bert Vermeulen - * - * 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 . - */ - -#include -#include -#include "protocol.h" - -/* - * The default serial communication settings on the device are 9600 - * baud, 9 data bits. The 9th bit isn't actually used, and the vendor - * software uses Mark parity to absorb the extra bit. - * - * Since 9 data bits is not a standard available in POSIX, we use two - * stop bits to skip over the extra bit instead. - */ -#define SERIALCOMM "9600/8n2" - -static const int32_t scanopts[] = { - SR_CONF_CONN, - SR_CONF_SERIALCOMM, -}; - -static const int32_t devopts[] = { - SR_CONF_POWER_SUPPLY, - SR_CONF_CONTINUOUS, - SR_CONF_OUTPUT_CHANNEL, - SR_CONF_OVER_CURRENT_PROTECTION, -}; - -static const int32_t devopts_cg[] = { - SR_CONF_OUTPUT_VOLTAGE, - SR_CONF_OUTPUT_VOLTAGE_MAX, - SR_CONF_OUTPUT_CURRENT, - SR_CONF_OUTPUT_CURRENT_MAX, - SR_CONF_OUTPUT_ENABLED, -}; - -static const char *channel_modes[] = { - "Independent", - "Series", - "Parallel", -}; - -static struct pps_model models[] = { - { PPS_3203T_3S, "PPS3203T-3S", - CHANMODE_INDEPENDENT | CHANMODE_SERIES | CHANMODE_PARALLEL, - 3, - { - /* Channel 1 */ - { { 0, 32, 0.01 }, { 0, 3, 0.001 } }, - /* Channel 2 */ - { { 0, 32, 0.01 }, { 0, 3, 0.001 } }, - /* Channel 3 */ - { { 0, 6, 0.01 }, { 0, 3, 0.001 } }, - }, - }, -}; - - -SR_PRIV struct sr_dev_driver atten_pps3203_driver_info; -static struct sr_dev_driver *di = &atten_pps3203_driver_info; - -static int init(struct sr_context *sr_ctx) -{ - return std_init(sr_ctx, di, LOG_PREFIX); -} - -static GSList *scan(GSList *options, int modelid) -{ - struct sr_dev_inst *sdi; - struct drv_context *drvc; - struct dev_context *devc; - struct sr_config *src; - struct sr_channel *ch; - struct sr_channel_group *cg; - struct sr_serial_dev_inst *serial; - GSList *l, *devices; - struct pps_model *model; - uint8_t packet[PACKET_SIZE]; - unsigned int i; - int ret; - const char *conn, *serialcomm; - char channel[10]; - - devices = NULL; - drvc = di->priv; - drvc->instances = NULL; - - conn = serialcomm = NULL; - for (l = options; l; l = l->next) { - src = l->data; - switch (src->key) { - case SR_CONF_CONN: - conn = g_variant_get_string(src->data, NULL); - break; - case SR_CONF_SERIALCOMM: - serialcomm = g_variant_get_string(src->data, NULL); - break; - } - } - if (!conn) - return NULL; - if (!serialcomm) - serialcomm = SERIALCOMM; - - if (!(serial = sr_serial_dev_inst_new(conn, serialcomm))) - return NULL; - - if (serial_open(serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK) - return NULL; - serial_flush(serial); - - /* This is how the vendor software channels for hardware. */ - memset(packet, 0, PACKET_SIZE); - packet[0] = 0xaa; - packet[1] = 0xaa; - if (serial_write(serial, packet, PACKET_SIZE) == -1) { - sr_err("Unable to write while probing for hardware: %s", - strerror(errno)); - return NULL; - } - /* The device responds with a 24-byte packet when it receives a packet. - * At 9600 baud, 300ms is long enough for it to have arrived. */ - g_usleep(300 * 1000); - memset(packet, 0, PACKET_SIZE); - if ((ret = serial_read_nonblocking(serial, packet, PACKET_SIZE)) < 0) { - sr_err("Unable to read while probing for hardware: %s", - strerror(errno)); - return NULL; - } - if (ret != PACKET_SIZE || packet[0] != 0xaa || packet[1] != 0xaa) { - /* Doesn't look like an Atten PPS. */ - return NULL; - } - - model = NULL; - for (i = 0; i < ARRAY_SIZE(models); i++) { - if (models[i].modelid == modelid) { - model = &models[i]; - break; - } - } - if (!model) { - sr_err("Unknown modelid %d", modelid); - return NULL; - } - - sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, "Atten", model->name, NULL); - sdi->driver = di; - sdi->inst_type = SR_INST_SERIAL; - sdi->conn = serial; - for (i = 0; i < MAX_CHANNELS; i++) { - snprintf(channel, 10, "CH%d", i + 1); - ch = sr_channel_new(i, SR_CHANNEL_ANALOG, TRUE, channel); - sdi->channels = g_slist_append(sdi->channels, ch); - cg = g_malloc(sizeof(struct sr_channel_group)); - cg->name = g_strdup(channel); - cg->channels = g_slist_append(NULL, ch); - cg->priv = NULL; - sdi->channel_groups = g_slist_append(sdi->channel_groups, cg); - } - - devc = g_malloc0(sizeof(struct dev_context)); - devc->model = model; - devc->config = g_malloc0(sizeof(struct per_channel_config) * model->num_channels); - sdi->priv = devc; - drvc->instances = g_slist_append(drvc->instances, sdi); - devices = g_slist_append(devices, sdi); - - serial_close(serial); - if (!devices) - sr_serial_dev_inst_free(serial); - - return devices; -} - -static GSList *scan_3203(GSList *options) -{ - return scan(options, PPS_3203T_3S); -} - -static GSList *dev_list(void) -{ - return ((struct drv_context *)(di->priv))->instances; -} - -static int cleanup(void) -{ - return std_dev_clear(di, NULL); -} - -static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc; - struct sr_channel *ch; - int channel, ret; - - if (!sdi) - return SR_ERR_ARG; - - devc = sdi->priv; - - ret = SR_OK; - if (!cg) { - /* No channel group: global options. */ - switch (key) { - case SR_CONF_OUTPUT_CHANNEL: - *data = g_variant_new_string(channel_modes[devc->channel_mode]); - break; - case SR_CONF_OVER_CURRENT_PROTECTION: - *data = g_variant_new_boolean(devc->over_current_protection); - break; - default: - return SR_ERR_NA; - } - } else { - /* We only ever have one channel per channel group in this driver. */ - ch = cg->channels->data; - channel = ch->index; - - switch (key) { - case SR_CONF_OUTPUT_VOLTAGE: - *data = g_variant_new_double(devc->config[channel].output_voltage_last); - break; - case SR_CONF_OUTPUT_VOLTAGE_MAX: - *data = g_variant_new_double(devc->config[channel].output_voltage_max); - break; - case SR_CONF_OUTPUT_CURRENT: - *data = g_variant_new_double(devc->config[channel].output_current_last); - break; - case SR_CONF_OUTPUT_CURRENT_MAX: - *data = g_variant_new_double(devc->config[channel].output_current_max); - break; - case SR_CONF_OUTPUT_ENABLED: - *data = g_variant_new_boolean(devc->config[channel].output_enabled); - break; - default: - return SR_ERR_NA; - } - } - - return ret; -} - -static int find_str(const char *str, const char **strings, int array_size) -{ - int idx, i; - - idx = -1; - for (i = 0; i < array_size; i++) { - if (!strcmp(str, strings[i])) { - idx = i; - break; - } - } - - return idx; -} - -static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc; - struct sr_channel *ch; - gdouble dval; - int channel, ret, ival; - const char *sval; - gboolean bval; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - ret = SR_OK; - devc = sdi->priv; - if (!cg) { - /* No channel group: global options. */ - switch (key) { - case SR_CONF_OUTPUT_CHANNEL: - sval = g_variant_get_string(data, NULL); - if ((ival = find_str(sval, channel_modes, - ARRAY_SIZE(channel_modes))) == -1) { - ret = SR_ERR_ARG; - break; - } - if (devc->model->channel_modes && (1 << ival) == 0) { - /* Not supported on this model. */ - ret = SR_ERR_ARG; - } - if (ival == devc->channel_mode_set) - /* Nothing to do. */ - break; - devc->channel_mode_set = ival; - devc->config_dirty = TRUE; - break; - case SR_CONF_OVER_CURRENT_PROTECTION: - bval = g_variant_get_boolean(data); - if (bval == devc->over_current_protection_set) - /* Nothing to do. */ - break; - devc->over_current_protection_set = bval; - devc->config_dirty = TRUE; - break; - default: - return SR_ERR_NA; - } - } else { - /* Channel group specified: per-channel options. */ - /* We only ever have one channel per channel group in this driver. */ - ch = cg->channels->data; - channel = ch->index; - - switch (key) { - case SR_CONF_OUTPUT_VOLTAGE_MAX: - dval = g_variant_get_double(data); - if (dval < 0 || dval > devc->model->channels[channel].voltage[1]) - ret = SR_ERR_ARG; - devc->config[channel].output_voltage_max = dval; - devc->config_dirty = TRUE; - break; - case SR_CONF_OUTPUT_CURRENT_MAX: - dval = g_variant_get_double(data); - if (dval < 0 || dval > devc->model->channels[channel].current[1]) - ret = SR_ERR_ARG; - devc->config[channel].output_current_max = dval; - devc->config_dirty = TRUE; - break; - case SR_CONF_OUTPUT_ENABLED: - bval = g_variant_get_boolean(data); - if (bval == devc->config[channel].output_enabled_set) - /* Nothing to do. */ - break; - devc->config[channel].output_enabled_set = bval; - devc->config_dirty = TRUE; - break; - default: - ret = SR_ERR_NA; - } - } - - - return ret; -} - -static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc; - struct sr_channel *ch; - GVariant *gvar; - GVariantBuilder gvb; - int channel, ret, i; - - /* Always available, even without sdi. */ - if (key == SR_CONF_SCAN_OPTIONS) { - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - scanopts, ARRAY_SIZE(scanopts), sizeof(int32_t)); - return SR_OK; - } - - if (!sdi) - return SR_ERR_ARG; - devc = sdi->priv; - - ret = SR_OK; - if (!cg) { - /* No channel group: global options. */ - switch (key) { - case SR_CONF_DEVICE_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - devopts, ARRAY_SIZE(devopts), sizeof(int32_t)); - break; - case SR_CONF_OUTPUT_CHANNEL: - if (devc->model->channel_modes == CHANMODE_INDEPENDENT) { - /* The 1-channel models. */ - *data = g_variant_new_strv(channel_modes, 1); - } else { - /* The other models support all modes. */ - *data = g_variant_new_strv(channel_modes, ARRAY_SIZE(channel_modes)); - } - break; - default: - return SR_ERR_NA; - } - } else { - /* Channel group specified: per-channel options. */ - if (!sdi) - return SR_ERR_ARG; - /* We only ever have one channel per channel group in this driver. */ - ch = cg->channels->data; - channel = ch->index; - - switch (key) { - case SR_CONF_DEVICE_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - devopts_cg, ARRAY_SIZE(devopts_cg), sizeof(int32_t)); - break; - case SR_CONF_OUTPUT_VOLTAGE_MAX: - g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY); - /* Min, max, step. */ - for (i = 0; i < 3; i++) { - gvar = g_variant_new_double(devc->model->channels[channel].voltage[i]); - g_variant_builder_add_value(&gvb, gvar); - } - *data = g_variant_builder_end(&gvb); - break; - case SR_CONF_OUTPUT_CURRENT_MAX: - g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY); - /* Min, max, step. */ - for (i = 0; i < 3; i++) { - gvar = g_variant_new_double(devc->model->channels[channel].current[i]); - g_variant_builder_add_value(&gvb, gvar); - } - *data = g_variant_builder_end(&gvb); - break; - default: - return SR_ERR_NA; - } - } - - return ret; -} - -static int dev_close(struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - - devc = sdi->priv; - if (devc->config_dirty) - /* Some configuration changes were queued up but didn't - * get sent to the device, likely because we were never - * in acquisition mode. Send them out now. */ - send_config(sdi); - - return std_serial_dev_close(sdi); -} - -static int dev_acquisition_start(const struct sr_dev_inst *sdi, - void *cb_data) -{ - struct dev_context *devc; - struct sr_serial_dev_inst *serial; - uint8_t packet[PACKET_SIZE]; - - (void)cb_data; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - devc = sdi->priv; - memset(devc->packet, 0x44, PACKET_SIZE); - devc->packet_size = 0; - - devc->acquisition_running = TRUE; - - serial = sdi->conn; - serial_source_add(sdi->session, serial, G_IO_IN, 50, - atten_pps3xxx_receive_data, (void *)sdi); - std_session_send_df_header(cb_data, LOG_PREFIX); - - /* Send a "channel" configuration packet now. */ - memset(packet, 0, PACKET_SIZE); - packet[0] = 0xaa; - packet[1] = 0xaa; - send_packet(sdi, packet); - - return SR_OK; -} - -static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) -{ - struct dev_context *devc; - - (void)cb_data; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - devc = sdi->priv; - devc->acquisition_running = FALSE; - - return SR_OK; -} - -SR_PRIV struct sr_dev_driver atten_pps3203_driver_info = { - .name = "atten-pps3203", - .longname = "Atten PPS3203T-3S", - .api_version = 1, - .init = init, - .cleanup = cleanup, - .scan = scan_3203, - .dev_list = dev_list, - .dev_clear = NULL, - .config_get = config_get, - .config_set = config_set, - .config_list = config_list, - .dev_open = std_serial_dev_open, - .dev_close = dev_close, - .dev_acquisition_start = dev_acquisition_start, - .dev_acquisition_stop = dev_acquisition_stop, - .priv = NULL, -}; diff --git a/hardware/atten-pps3xxx/protocol.c b/hardware/atten-pps3xxx/protocol.c deleted file mode 100644 index ed4d5505..00000000 --- a/hardware/atten-pps3xxx/protocol.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2014 Bert Vermeulen - * - * 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 . - */ - -#include -#include -#include "protocol.h" - -static void dump_packet(char *msg, uint8_t *packet) -{ - int i; - char str[128]; - - str[0] = 0; - for (i = 0; i < PACKET_SIZE; i++) - sprintf(str + strlen(str), "%.2x ", packet[i]); - sr_dbg("%s: %s", msg, str); - -} - -static void handle_packet(const struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - struct sr_datafeed_packet packet; - struct sr_datafeed_analog analog; - float value, data[MAX_CHANNELS]; - int offset, i; - - devc = sdi->priv; - dump_packet("received", devc->packet); - packet.type = SR_DF_ANALOG; - packet.payload = &analog; - analog.channels = sdi->channels; - analog.num_samples = 1; - - analog.mq = SR_MQ_VOLTAGE; - analog.unit = SR_UNIT_VOLT; - analog.mqflags = SR_MQFLAG_DC; - analog.data = data; - for (i = 0; i < devc->model->num_channels; i++) { - offset = 2 + i * 4; - value = ((devc->packet[offset] << 8) + devc->packet[offset + 1]) / 100.0; - analog.data[i] = value; - devc->config[i].output_voltage_last = value; - } - sr_session_send(sdi, &packet); - - analog.mq = SR_MQ_CURRENT; - analog.unit = SR_UNIT_AMPERE; - analog.mqflags = 0; - analog.data = data; - for (i = 0; i < devc->model->num_channels; i++) { - offset = 4 + i * 4; - value = ((devc->packet[offset] << 8) + devc->packet[offset + 1]) / 1000.0; - analog.data[i] = value; - devc->config[i].output_current_last = value; - } - sr_session_send(sdi, &packet); - - for (i = 0; i < devc->model->num_channels; i++) - devc->config[i].output_enabled = (devc->packet[15] & (1 << i)) ? TRUE : FALSE; - - devc->over_current_protection = devc->packet[18] ? TRUE : FALSE; - if (devc->packet[19] < 3) - devc->channel_mode = devc->packet[19]; - -} - -SR_PRIV void send_packet(const struct sr_dev_inst *sdi, uint8_t *packet) -{ - struct sr_serial_dev_inst *serial; - - serial = sdi->conn; - if (serial_write(serial, packet, PACKET_SIZE) == -1) - sr_dbg("Failed to send packet: %s", strerror(errno)); - dump_packet("sent", packet); -} - -SR_PRIV void send_config(const struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - uint8_t packet[PACKET_SIZE]; - int value, offset, i; - - devc = sdi->priv; - memset(packet, 0, PACKET_SIZE); - packet[0] = 0xaa; - packet[1] = 0x20; - packet[14] = 0x01; - packet[16] = 0x01; - for (i = 0; i < devc->model->num_channels; i++) { - offset = 2 + i * 4; - value = devc->config[i].output_voltage_max * 100; - packet[offset] = (value >> 8) & 0xff; - packet[offset + 1] = value & 0xff; - value = devc->config[i].output_current_max * 1000; - packet[offset + 2] = (value >> 8) & 0xff; - packet[offset + 3] = value & 0xff; - if (devc->config[i].output_enabled_set) - packet[15] |= 1 << i; - } - packet[18] = devc->over_current_protection_set ? 1 : 0; - packet[19] = devc->channel_mode_set; - /* Checksum. */ - value = 0; - for (i = 0; i < PACKET_SIZE - 1; i++) - value += packet[i]; - packet[i] = value & 0xff; - send_packet(sdi, packet); - devc->config_dirty = FALSE; - -} - -SR_PRIV int atten_pps3xxx_receive_data(int fd, int revents, void *cb_data) -{ - struct dev_context *devc; - const struct sr_dev_inst *sdi; - struct sr_serial_dev_inst *serial; - struct sr_datafeed_packet packet; - unsigned char c; - - (void)fd; - - if (!(sdi = cb_data)) - return TRUE; - - if (!(devc = sdi->priv)) - return TRUE; - - serial = sdi->conn; - if (revents == G_IO_IN) { - if (serial_read_nonblocking(serial, &c, 1) < 0) - return TRUE; - devc->packet[devc->packet_size++] = c; - if (devc->packet_size == PACKET_SIZE) { - handle_packet(sdi); - devc->packet_size = 0; - if (devc->acquisition_running) - send_config(sdi); - else { - serial_source_remove(sdi->session, serial); - packet.type = SR_DF_END; - sr_session_send(sdi, &packet); - } - } - } - - return TRUE; -} - diff --git a/hardware/atten-pps3xxx/protocol.h b/hardware/atten-pps3xxx/protocol.h deleted file mode 100644 index 1441305d..00000000 --- a/hardware/atten-pps3xxx/protocol.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2014 Bert Vermeulen - * - * 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 . - */ - -#ifndef LIBSIGROK_HARDWARE_ATTEN_PPS3XXX_PROTOCOL_H -#define LIBSIGROK_HARDWARE_ATTEN_PPS3XXX_PROTOCOL_H - -#include -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#define LOG_PREFIX "atten-pps3xxx" - -/* Packets to/from the device. */ -#define PACKET_SIZE 24 - -enum { - PPS_3203T_3S, - PPS_3203T_2S, - PPS_3205T_3S, - PPS_3205T_2S, - PPS_3003S, - PPS_3005S, -}; - -/* Maximum number of output channels handled by this driver. */ -#define MAX_CHANNELS 3 - -#define CHANMODE_INDEPENDENT 1 << 0 -#define CHANMODE_SERIES 1 << 1 -#define CHANMODE_PARALLEL 1 << 2 - -struct channel_spec { - /* Min, max, step. */ - gdouble voltage[3]; - gdouble current[3]; -}; - -struct pps_model { - int modelid; - char *name; - int channel_modes; - int num_channels; - struct channel_spec channels[MAX_CHANNELS]; -}; - -struct per_channel_config { - /* Received from device. */ - gdouble output_voltage_last; - gdouble output_current_last; - gboolean output_enabled; - /* Set by frontend. */ - gdouble output_voltage_max; - gdouble output_current_max; - gboolean output_enabled_set; -}; - -/** Private, per-device-instance driver context. */ -struct dev_context { - /* Model-specific information */ - struct pps_model *model; - - /* Acquisition state */ - gboolean acquisition_running; - - /* Operational state */ - gboolean config_dirty; - struct per_channel_config *config; - /* Received from device. */ - int channel_mode; - gboolean over_current_protection; - /* Set by frontend. */ - int channel_mode_set; - gboolean over_current_protection_set; - - /* Temporary state across callbacks */ - uint8_t packet[PACKET_SIZE]; - int packet_size; - -}; - -SR_PRIV int atten_pps3xxx_receive_data(int fd, int revents, void *cb_data); -SR_PRIV void send_packet(const struct sr_dev_inst *sdi, uint8_t *packet); -SR_PRIV void send_config(const struct sr_dev_inst *sdi); - -#endif diff --git a/hardware/beaglelogic/api.c b/hardware/beaglelogic/api.c deleted file mode 100644 index c86925be..00000000 --- a/hardware/beaglelogic/api.c +++ /dev/null @@ -1,413 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2014 Kumar Abhishek - * - * 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 . - */ - -#include "protocol.h" -#include "beaglelogic.h" - -SR_PRIV struct sr_dev_driver beaglelogic_driver_info; -static struct sr_dev_driver *di = &beaglelogic_driver_info; - -/* Hardware capabiities */ -static const int32_t hwcaps[] = { - SR_CONF_LOGIC_ANALYZER, - SR_CONF_SAMPLERATE, - SR_CONF_TRIGGER_MATCH, - - SR_CONF_LIMIT_SAMPLES, - SR_CONF_CONTINUOUS, - - SR_CONF_NUM_LOGIC_CHANNELS, -}; - -/* Trigger matching capabilities */ -static const int32_t soft_trigger_matches[] = { - SR_TRIGGER_ZERO, - SR_TRIGGER_ONE, - SR_TRIGGER_RISING, - SR_TRIGGER_FALLING, - SR_TRIGGER_EDGE, -}; - -/* Channels are numbered 0-13 */ -SR_PRIV const char *beaglelogic_channel_names[NUM_CHANNELS + 1] = { - "P8_45", "P8_46", "P8_43", "P8_44", "P8_41", "P8_42", "P8_39", "P8_40", - "P8_27", "P8_29", "P8_28", "P8_30", "P8_21", "P8_20", NULL, -}; - -/* Possible sample rates : 10 Hz to 100 MHz = (100 / x) MHz */ -static const uint64_t samplerates[] = { - SR_HZ(10), - SR_MHZ(100), - SR_HZ(1), -}; - -static int init(struct sr_context *sr_ctx) -{ - return std_init(sr_ctx, di, LOG_PREFIX); -} - -static struct dev_context * beaglelogic_devc_alloc(void) -{ - struct dev_context *devc; - - /* Allocate zeroed structure */ - devc = g_try_malloc0(sizeof(*devc)); - - /* Default non-zero values (if any) */ - devc->fd = -1; - devc->limit_samples = (uint64_t)-1; - - return devc; -} - -static GSList *scan(GSList *options) -{ - struct drv_context *drvc; - GSList *devices, *l; - struct sr_config *src; - struct sr_dev_inst *sdi; - struct dev_context *devc; - struct sr_channel *ch; - int i, maxch; - - devices = NULL; - drvc = di->priv; - drvc->instances = NULL; - - /* Probe for /dev/beaglelogic */ - if (!g_file_test(BEAGLELOGIC_DEV_NODE, G_FILE_TEST_EXISTS)) - return NULL; - - sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, NULL, "BeagleLogic", "1.0"); - sdi->driver = di; - - /* Unless explicitly specified, keep max channels to 8 only */ - maxch = 8; - for (l = options; l; l = l->next) { - src = l->data; - if (src->key == SR_CONF_NUM_LOGIC_CHANNELS) - maxch = g_variant_get_int32(src->data); - } - - /* We need to test for number of channels by opening the node */ - devc = beaglelogic_devc_alloc(); - - if (beaglelogic_open_nonblock(devc) != SR_OK) { - g_free(devc); - sr_dev_inst_free(sdi); - - return NULL; - } - - if (maxch > 8) { - maxch = NUM_CHANNELS; - devc->sampleunit = BL_SAMPLEUNIT_16_BITS; - } else { - maxch = 8; - devc->sampleunit = BL_SAMPLEUNIT_8_BITS; - } - - beaglelogic_set_sampleunit(devc); - beaglelogic_close(devc); - - /* Signal */ - sr_info("BeagleLogic device found at "BEAGLELOGIC_DEV_NODE); - - /* Fill the channels */ - for (i = 0; i < maxch; i++) { - if (!(ch = sr_channel_new(i, SR_CHANNEL_LOGIC, TRUE, - beaglelogic_channel_names[i]))) - return NULL; - sdi->channels = g_slist_append(sdi->channels, ch); - } - - sdi->priv = devc; - drvc->instances = g_slist_append(drvc->instances, sdi); - devices = g_slist_append(devices, sdi); - - return devices; -} - -static GSList *dev_list(void) -{ - return ((struct drv_context *)(di->priv))->instances; -} - -static int dev_clear(void) -{ - return std_dev_clear(di, NULL); -} - -static int dev_open(struct sr_dev_inst *sdi) -{ - struct dev_context *devc = sdi->priv; - - /* Open BeagleLogic */ - if (beaglelogic_open_nonblock(devc)) - return SR_ERR; - - /* Set fd and local attributes */ - devc->pollfd.fd = devc->fd; - devc->pollfd.events = G_IO_IN; - - /* Get the default attributes */ - beaglelogic_get_samplerate(devc); - beaglelogic_get_sampleunit(devc); - beaglelogic_get_triggerflags(devc); - beaglelogic_get_buffersize(devc); - beaglelogic_get_bufunitsize(devc); - - /* Map the kernel capture FIFO for reads, saves 1 level of memcpy */ - if (beaglelogic_mmap(devc) != SR_OK) { - sr_err("Unable to map capture buffer"); - beaglelogic_close(devc); - return SR_ERR; - } - - /* We're good to go now */ - sdi->status = SR_ST_ACTIVE; - return SR_OK; -} - -static int dev_close(struct sr_dev_inst *sdi) -{ - struct dev_context *devc = sdi->priv; - - if (sdi->status == SR_ST_ACTIVE) { - /* Close the memory mapping and the file */ - beaglelogic_munmap(devc); - beaglelogic_close(devc); - } - sdi->status = SR_ST_INACTIVE; - return SR_OK; -} - -static int cleanup(void) -{ - struct drv_context *drvc; - struct sr_dev_inst *sdi; - GSList *l; - - /* unused driver */ - if (!(drvc = di->priv)) - return SR_OK; - - /* Clean up the instances */ - for (l = drvc->instances; l; l = l->next) { - sdi = l->data; - di->dev_close(sdi); - g_free(sdi->priv); - sr_dev_inst_free(sdi); - } - g_slist_free(drvc->instances); - drvc->instances = NULL; - - di->priv = NULL; - - return SR_OK; -} - -static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc = sdi->priv; - (void)cg; - - switch (key) { - case SR_CONF_LIMIT_SAMPLES: - *data = g_variant_new_uint64(devc->limit_samples); - break; - - case SR_CONF_SAMPLERATE: - *data = g_variant_new_uint64(devc->cur_samplerate); - break; - - case SR_CONF_NUM_LOGIC_CHANNELS: - *data = g_variant_new_uint32(g_slist_length(sdi->channels)); - break; - - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc = sdi->priv; - uint64_t tmp_u64; - (void)cg; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - switch (key) { - case SR_CONF_SAMPLERATE: - devc->cur_samplerate = g_variant_get_uint64(data); - return beaglelogic_set_samplerate(devc); - - case SR_CONF_LIMIT_SAMPLES: - tmp_u64 = g_variant_get_uint64(data); - devc->limit_samples = tmp_u64; - devc->triggerflags = BL_TRIGGERFLAGS_ONESHOT; - - /* Check if we have sufficient buffer size */ - tmp_u64 *= SAMPLEUNIT_TO_BYTES(devc->sampleunit); - if (tmp_u64 > devc->buffersize) { - sr_warn("Insufficient buffer space has been allocated."); - sr_warn("Please use \'echo > "\ - BEAGLELOGIC_SYSFS_ATTR(memalloc) \ - "\' as root to increase the buffer size, this"\ - " capture is now truncated to %d Msamples", - devc->buffersize / - (SAMPLEUNIT_TO_BYTES(devc->sampleunit) * 1000000)); - } - return beaglelogic_set_triggerflags(devc); - - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - int ret; - GVariant *gvar; - GVariantBuilder gvb; - - (void)sdi; - (void)data; - (void)cg; - - ret = SR_OK; - switch (key) { - case SR_CONF_DEVICE_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t)); - break; - case SR_CONF_SAMPLERATE: - g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}")); - gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), - samplerates, ARRAY_SIZE(samplerates), sizeof(uint64_t)); - g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar); - *data = g_variant_builder_end(&gvb); - break; - case SR_CONF_TRIGGER_MATCH: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - soft_trigger_matches, ARRAY_SIZE(soft_trigger_matches), - sizeof(int32_t)); - break; - default: - return SR_ERR_NA; - } - - return ret; -} - -/* get a sane timeout for poll() */ -#define BUFUNIT_TIMEOUT_MS(devc) (100 + ((devc->bufunitsize * 1000) / \ - (uint32_t)(devc->cur_samplerate))) - -static int dev_acquisition_start(const struct sr_dev_inst *sdi, - void *cb_data) -{ - (void)cb_data; - struct dev_context *devc = sdi->priv; - struct sr_trigger *trigger; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - /* Save user pointer */ - devc->cb_data = cb_data; - - /* Clear capture state */ - devc->bytes_read = 0; - devc->offset = 0; - - /* Configure channels */ - devc->sampleunit = g_slist_length(sdi->channels) > 8 ? - BL_SAMPLEUNIT_16_BITS : BL_SAMPLEUNIT_8_BITS; - beaglelogic_set_sampleunit(devc); - - /* Configure triggers & send header packet */ - if ((trigger = sr_session_trigger_get(sdi->session))) { - devc->stl = soft_trigger_logic_new(sdi, trigger); - devc->trigger_fired = FALSE; - } else - devc->trigger_fired = TRUE; - std_session_send_df_header(cb_data, LOG_PREFIX); - - /* Trigger and add poll on file */ - beaglelogic_start(devc); - sr_session_source_add_pollfd(sdi->session, &devc->pollfd, - BUFUNIT_TIMEOUT_MS(devc), beaglelogic_receive_data, - (void *)sdi); - - return SR_OK; -} - -static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) -{ - struct dev_context *devc = sdi->priv; - struct sr_datafeed_packet pkt; - - (void)cb_data; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - /* Execute a stop on BeagleLogic */ - beaglelogic_stop(devc); - - /* lseek to offset 0, flushes the cache */ - lseek(devc->fd, 0, SEEK_SET); - - /* Remove session source and send EOT packet */ - sr_session_source_remove_pollfd(sdi->session, &devc->pollfd); - pkt.type = SR_DF_END; - pkt.payload = NULL; - sr_session_send(sdi, &pkt); - - return SR_OK; -} - -SR_PRIV struct sr_dev_driver beaglelogic_driver_info = { - .name = "beaglelogic", - .longname = "BeagleLogic", - .api_version = 1, - .init = init, - .cleanup = cleanup, - .scan = scan, - .dev_list = dev_list, - .dev_clear = dev_clear, - .config_get = config_get, - .config_set = config_set, - .config_list = config_list, - .dev_open = dev_open, - .dev_close = dev_close, - .dev_acquisition_start = dev_acquisition_start, - .dev_acquisition_stop = dev_acquisition_stop, - .priv = NULL, -}; diff --git a/hardware/beaglelogic/beaglelogic.h b/hardware/beaglelogic/beaglelogic.h deleted file mode 100644 index 12e2f486..00000000 --- a/hardware/beaglelogic/beaglelogic.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2014 Kumar Abhishek - * - * 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 . - */ - -#ifndef BEAGLELOGIC_H_ -#define BEAGLELOGIC_H_ - -#include - -#include -#include -#include -#include - -#include - -#include - -/* BeagleLogic device node name */ -#define BEAGLELOGIC_DEV_NODE "/dev/beaglelogic" -#define BEAGLELOGIC_SYSFS_ATTR(a) "/sys/devices/virtual/misc/beaglelogic/"\ - __STRING(a) - -/* Reproduced verbatim from beaglelogic.h in the kernel tree until the kernel - * module hits the mainline. Contains the ABI, so DO NOT TOUCH this section */ - -/* ioctl calls that can be issued on /dev/beaglelogic */ -#define IOCTL_BL_GET_VERSION _IOR('k', 0x20, uint32_t) - -#define IOCTL_BL_GET_SAMPLE_RATE _IOR('k', 0x21, uint32_t) -#define IOCTL_BL_SET_SAMPLE_RATE _IOW('k', 0x21, uint32_t) - -#define IOCTL_BL_GET_SAMPLE_UNIT _IOR('k', 0x22, uint32_t) -#define IOCTL_BL_SET_SAMPLE_UNIT _IOW('k', 0x22, uint32_t) - -#define IOCTL_BL_GET_TRIGGER_FLAGS _IOR('k', 0x23, uint32_t) -#define IOCTL_BL_SET_TRIGGER_FLAGS _IOW('k', 0x23, uint32_t) - -#define IOCTL_BL_CACHE_INVALIDATE _IO('k', 0x25) - -#define IOCTL_BL_GET_BUFFER_SIZE _IOR('k', 0x26, uint32_t) -#define IOCTL_BL_SET_BUFFER_SIZE _IOW('k', 0x26, uint32_t) - -#define IOCTL_BL_GET_BUFUNIT_SIZE _IOR('k', 0x27, uint32_t) - -#define IOCTL_BL_FILL_TEST_PATTERN _IO('k', 0x28) - -#define IOCTL_BL_START _IO('k', 0x29) -#define IOCTL_BL_STOP _IO('k', 0x2A) - -/* Possible States of BeagleLogic */ -enum beaglelogic_states { - STATE_BL_DISABLED, /* Powered off (at module start) */ - STATE_BL_INITIALIZED, /* Powered on */ - STATE_BL_MEMALLOCD, /* Buffers allocated */ - STATE_BL_ARMED, /* All Buffers DMA-mapped and configuration done */ - STATE_BL_RUNNING, /* Data being captured */ - STATE_BL_REQUEST_STOP, /* Stop requested */ - STATE_BL_ERROR /* Buffer overrun */ -}; - -/* Setting attributes */ -enum beaglelogic_triggerflags { - BL_TRIGGERFLAGS_ONESHOT = 0, - BL_TRIGGERFLAGS_CONTINUOUS -}; - -/* Possible sample unit / formats */ -enum beaglelogic_sampleunit { - BL_SAMPLEUNIT_16_BITS = 0, - BL_SAMPLEUNIT_8_BITS -}; -/* END beaglelogic.h */ - -/* For all the functions below: - * Parameters: - * devc : Device context structure to operate on - * Returns: - * SR_OK or SR_ERR - */ - -SR_PRIV int beaglelogic_open_nonblock(struct dev_context *devc); -SR_PRIV int beaglelogic_close(struct dev_context *devc); - -SR_PRIV int beaglelogic_get_buffersize(struct dev_context *devc); -SR_PRIV int beaglelogic_set_buffersize(struct dev_context *devc); - -SR_PRIV int beaglelogic_get_samplerate(struct dev_context *devc); -SR_PRIV int beaglelogic_set_samplerate(struct dev_context *devc); - -SR_PRIV int beaglelogic_get_sampleunit(struct dev_context *devc); -SR_PRIV int beaglelogic_set_sampleunit(struct dev_context *devc); - -SR_PRIV int beaglelogic_get_triggerflags(struct dev_context *devc); -SR_PRIV int beaglelogic_set_triggerflags(struct dev_context *devc); - -/* Start and stop the capture operation */ -SR_PRIV int beaglelogic_start(struct dev_context *devc); -SR_PRIV int beaglelogic_stop(struct dev_context *devc); - -/* Get the last error size */ -SR_PRIV int beaglelogic_getlasterror(struct dev_context *devc); - -/* Gets the unit size of the capture buffer (usually 4 or 8 MB) */ -SR_PRIV int beaglelogic_get_bufunitsize(struct dev_context *devc); - -SR_PRIV int beaglelogic_mmap(struct dev_context *devc); -SR_PRIV int beaglelogic_munmap(struct dev_context *devc); - -/* Sources */ -SR_PRIV inline int beaglelogic_open_nonblock(struct dev_context *devc) { - devc->fd = open(BEAGLELOGIC_DEV_NODE, O_RDONLY | O_NONBLOCK); - return (devc->fd == -1 ? SR_ERR : SR_OK); -} - -SR_PRIV inline int beaglelogic_close(struct dev_context *devc) { - return close(devc->fd); -} - -SR_PRIV inline int beaglelogic_get_buffersize(struct dev_context *devc) { - return ioctl(devc->fd, IOCTL_BL_GET_BUFFER_SIZE, &devc->buffersize); -} - -SR_PRIV inline int beaglelogic_set_buffersize(struct dev_context *devc) { - return ioctl(devc->fd, IOCTL_BL_SET_BUFFER_SIZE, devc->buffersize); -} - -/* This is treated differently as it gets a uint64_t while a uint32_t is read */ -SR_PRIV inline int beaglelogic_get_samplerate(struct dev_context *devc) { - uint32_t arg, err; - err = ioctl(devc->fd, IOCTL_BL_GET_SAMPLE_RATE, &arg); - devc->cur_samplerate = arg; - return err; -} - -SR_PRIV inline int beaglelogic_set_samplerate(struct dev_context *devc) { - return ioctl(devc->fd, IOCTL_BL_SET_SAMPLE_RATE, - (uint32_t)devc->cur_samplerate); -} - -SR_PRIV inline int beaglelogic_get_sampleunit(struct dev_context *devc) { - return ioctl(devc->fd, IOCTL_BL_GET_SAMPLE_UNIT, &devc->sampleunit); -} - -SR_PRIV inline int beaglelogic_set_sampleunit(struct dev_context *devc) { - return ioctl(devc->fd, IOCTL_BL_SET_SAMPLE_UNIT, devc->sampleunit); -} - -SR_PRIV inline int beaglelogic_get_triggerflags(struct dev_context *devc) { - return ioctl(devc->fd, IOCTL_BL_GET_TRIGGER_FLAGS, &devc->triggerflags); -} - -SR_PRIV inline int beaglelogic_set_triggerflags(struct dev_context *devc) { - return ioctl(devc->fd, IOCTL_BL_SET_TRIGGER_FLAGS, devc->triggerflags); -} - -SR_PRIV int beaglelogic_getlasterror(struct dev_context *devc) { - int fd; - char buf[16]; - int ret; - - if ((fd = open(BEAGLELOGIC_SYSFS_ATTR(lasterror), O_RDONLY)) == -1) - return SR_ERR; - - if ((ret = read(fd, buf, 16)) < 0) - return SR_ERR; - - close(fd); - devc->last_error = strtoul(buf, NULL, 10); - - return SR_OK; -} - -SR_PRIV inline int beaglelogic_start(struct dev_context *devc) { - return ioctl(devc->fd, IOCTL_BL_START); -} - -SR_PRIV inline int beaglelogic_stop(struct dev_context *devc) { - return ioctl(devc->fd, IOCTL_BL_STOP); -} - -SR_PRIV int beaglelogic_get_bufunitsize(struct dev_context *devc) { - return ioctl(devc->fd, IOCTL_BL_GET_BUFUNIT_SIZE, &devc->bufunitsize); -} - -SR_PRIV int beaglelogic_mmap(struct dev_context *devc) { - if (!devc->buffersize) - beaglelogic_get_buffersize(devc); - devc->sample_buf = mmap(NULL, devc->buffersize, - PROT_READ, MAP_SHARED, devc->fd, 0); - return (devc->sample_buf == MAP_FAILED ? -1 : SR_OK); -} - -SR_PRIV int beaglelogic_munmap(struct dev_context *devc) { - return munmap(devc->sample_buf, devc->buffersize); -} - -#endif /* BEAGLELOGIC_H_ */ diff --git a/hardware/beaglelogic/protocol.c b/hardware/beaglelogic/protocol.c deleted file mode 100644 index 1c01b64f..00000000 --- a/hardware/beaglelogic/protocol.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2014 Kumar Abhishek - * - * 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 . - */ - -#include "protocol.h" -#include -#include -#include -#include - -/* Define data packet size independent of packet (bufunitsize bytes) size - * from the BeagleLogic kernel module */ -#define PACKET_SIZE (512 * 1024) - -/* This implementation is zero copy from the libsigrok side. - * It does not copy any data, just passes a pointer from the mmap'ed - * kernel buffers appropriately. It is up to the application which is - * using libsigrok to decide how to deal with the data. - */ -SR_PRIV int beaglelogic_receive_data(int fd, int revents, void *cb_data) -{ - const struct sr_dev_inst *sdi; - struct dev_context *devc; - struct sr_datafeed_packet packet; - struct sr_datafeed_logic logic; - - int trigger_offset; - uint32_t packetsize; - uint64_t bytes_remaining; - - if (!(sdi = cb_data) || !(devc = sdi->priv)) - return TRUE; - - packetsize = PACKET_SIZE; - logic.unitsize = SAMPLEUNIT_TO_BYTES(devc->sampleunit); - - if (revents == G_IO_IN) { - sr_info("In callback G_IO_IN, offset=%d", devc->offset); - - bytes_remaining = (devc->limit_samples * logic.unitsize) - - devc->bytes_read; - - /* Configure data packet */ - packet.type = SR_DF_LOGIC; - packet.payload = &logic; - logic.data = devc->sample_buf + devc->offset; - logic.length = MIN(packetsize, bytes_remaining); - - if (devc->trigger_fired) { - /* Send the incoming transfer to the session bus. */ - sr_session_send(devc->cb_data, &packet); - } else { - /* Check for trigger */ - trigger_offset = soft_trigger_logic_check(devc->stl, - logic.data, - packetsize); - - if (trigger_offset > -1) { - trigger_offset *= logic.unitsize; - logic.length = MIN(packetsize - trigger_offset, - bytes_remaining); - logic.data += trigger_offset; - - sr_session_send(devc->cb_data, &packet); - - devc->trigger_fired = TRUE; - } - } - - /* Move the read pointer forward */ - lseek(fd, packetsize, SEEK_CUR); - - /* Update byte count and offset (roll over if needed) */ - devc->bytes_read += logic.length; - if ((devc->offset += packetsize) >= devc->buffersize) { - /* One shot capture, we abort and settle with less than - * the required number of samples */ - if (devc->triggerflags) - devc->offset = 0; - else - packetsize = 0; - } - } - - /* EOF Received or we have reached the limit */ - if (devc->bytes_read >= devc->limit_samples * logic.unitsize || - packetsize == 0) { - /* Send EOA Packet, stop polling */ - packet.type = SR_DF_END; - packet.payload = NULL; - sr_session_send(devc->cb_data, &packet); - - sr_session_source_remove_pollfd(sdi->session, &devc->pollfd); - } - - return TRUE; -} diff --git a/hardware/beaglelogic/protocol.h b/hardware/beaglelogic/protocol.h deleted file mode 100644 index f2acfeb0..00000000 --- a/hardware/beaglelogic/protocol.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2014 Kumar Abhishek - * - * 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 . - */ - -#ifndef LIBSIGROK_HARDWARE_BEAGLELOGIC_PROTOCOL_H -#define LIBSIGROK_HARDWARE_BEAGLELOGIC_PROTOCOL_H - -#include -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#define LOG_PREFIX "beaglelogic" - -/* Maximum possible input channels */ -#define NUM_CHANNELS 14 - -#define SAMPLEUNIT_TO_BYTES(x) ((x) == 1 ? 1 : 2) - -/** Private, per-device-instance driver context. */ -struct dev_context { - /* Model-specific information */ - int max_channels; - uint32_t fw_ver; - - /* Acquisition settings: see beaglelogic.h */ - uint64_t cur_samplerate; - uint64_t limit_samples; - uint32_t sampleunit; - uint32_t triggerflags; - - /* Buffers: size of each buffer block and the total buffer area */ - uint32_t bufunitsize; - uint32_t buffersize; - - /* Operational state */ - int fd; - GPollFD pollfd; - int last_error; - - uint64_t bytes_read; - uint64_t sent_samples; - uint32_t offset; - uint8_t *sample_buf; /* mmap'd kernel buffer here */ - - void *cb_data; - - /* Trigger logic */ - struct soft_trigger_logic *stl; - gboolean trigger_fired; -}; - -SR_PRIV int beaglelogic_receive_data(int fd, int revents, void *cb_data); - -#endif diff --git a/hardware/brymen-bm86x/api.c b/hardware/brymen-bm86x/api.c deleted file mode 100644 index be21583b..00000000 --- a/hardware/brymen-bm86x/api.c +++ /dev/null @@ -1,316 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2014 Aurelien Jacobs - * - * 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 . - */ - -#include "protocol.h" - -#define BRYMEN_BC86X "0820.0001" - -static const int32_t hwopts[] = { - SR_CONF_CONN, -}; - -static const int32_t hwcaps[] = { - SR_CONF_MULTIMETER, - SR_CONF_LIMIT_SAMPLES, - SR_CONF_LIMIT_MSEC, - SR_CONF_CONTINUOUS, -}; - -SR_PRIV struct sr_dev_driver brymen_bm86x_driver_info; -static struct sr_dev_driver *di = &brymen_bm86x_driver_info; - -static int init(struct sr_context *sr_ctx) -{ - return std_init(sr_ctx, di, LOG_PREFIX); -} - -static GSList *scan(GSList *options) -{ - GSList *usb_devices, *devices, *l; - struct drv_context *drvc; - struct dev_context *devc; - struct sr_dev_inst *sdi; - struct sr_usb_dev_inst *usb; - struct sr_config *src; - struct sr_channel *ch; - const char *conn; - - drvc = di->priv; - drvc->instances = NULL; - - conn = BRYMEN_BC86X; - for (l = options; l; l = l->next) { - src = l->data; - switch (src->key) { - case SR_CONF_CONN: - conn = g_variant_get_string(src->data, NULL); - break; - } - } - - devices = NULL; - if (!(usb_devices = sr_usb_find(drvc->sr_ctx->libusb_ctx, conn))) { - g_slist_free_full(usb_devices, g_free); - return NULL; - } - - for (l = usb_devices; l; l = l->next) { - usb = l->data; - - if (!(sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, - "Brymen", "BM869", NULL))) { - sr_err("sr_dev_inst_new returned NULL."); - return NULL; - } - - if (!(devc = g_try_malloc0(sizeof(*devc)))) { - sr_err("Device context malloc failed."); - return NULL; - } - - sdi->priv = devc; - sdi->driver = di; - if (!(ch = sr_channel_new(0, SR_CHANNEL_ANALOG, TRUE, "P1"))) - return NULL; - sdi->channels = g_slist_append(sdi->channels, ch); - if (!(ch = sr_channel_new(0, SR_CHANNEL_ANALOG, TRUE, "P2"))) - return NULL; - sdi->channels = g_slist_append(sdi->channels, ch); - - sdi->inst_type = SR_INST_USB; - sdi->conn = usb; - - drvc->instances = g_slist_append(drvc->instances, sdi); - devices = g_slist_append(devices, sdi); - } - - return devices; -} - -static GSList *dev_list(void) -{ - return ((struct drv_context *)(di->priv))->instances; -} - -static int dev_open(struct sr_dev_inst *sdi) -{ - struct drv_context *drvc = di->priv; - struct sr_usb_dev_inst *usb; - struct dev_context *devc; - int ret; - - usb = sdi->conn; - devc = sdi->priv; - - if ((ret = sr_usb_open(drvc->sr_ctx->libusb_ctx, usb)) == SR_OK) - sdi->status = SR_ST_ACTIVE; - - /* Detach kernel drivers which grabbed this device (if any). */ - if (libusb_kernel_driver_active(usb->devhdl, 0) == 1) { - ret = libusb_detach_kernel_driver(usb->devhdl, 0); - if (ret < 0) { - sr_err("Failed to detach kernel driver: %s.", - libusb_error_name(ret)); - return SR_ERR; - } - devc->detached_kernel_driver = 1; - sr_dbg("Successfully detached kernel driver."); - } else { - sr_dbg("No need to detach a kernel driver."); - } - - /* Claim interface 0. */ - if ((ret = libusb_claim_interface(usb->devhdl, 0)) < 0) { - sr_err("Failed to claim interface 0: %s.", - libusb_error_name(ret)); - return SR_ERR; - } - sr_dbg("Successfully claimed interface 0."); - - return ret; -} - -static int dev_close(struct sr_dev_inst *sdi) -{ - struct sr_usb_dev_inst *usb; - struct dev_context *devc; - int ret; - - usb = sdi->conn; - devc = sdi->priv; - - if ((ret = libusb_release_interface(usb->devhdl, 0))) - sr_err("Failed to release interface 0: %s.\n", libusb_error_name(ret)); - else - sr_dbg("Successfully released interface 0.\n"); - - if (!ret && devc->detached_kernel_driver) { - if ((ret = libusb_attach_kernel_driver(usb->devhdl, 0))) { - sr_err("Failed to attach kernel driver: %s.\n", - libusb_error_name(ret)); - } else { - devc->detached_kernel_driver = 0; - sr_dbg("Successfully attached kernel driver.\n"); - } - } - - libusb_close(usb->devhdl); - - sdi->status = SR_ST_INACTIVE; - - return ret; -} - -static int cleanup(void) -{ - return std_dev_clear(di, NULL); -} - -static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc = sdi->priv; - - (void)cg; - - switch (key) { - case SR_CONF_LIMIT_SAMPLES: - *data = g_variant_new_uint64(devc->limit_samples); - break; - case SR_CONF_LIMIT_MSEC: - *data = g_variant_new_uint64(devc->limit_msec); - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc; - - (void)cg; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - if (!(devc = sdi->priv)) { - sr_err("sdi->priv was NULL."); - return SR_ERR_BUG; - } - - switch (key) { - case SR_CONF_LIMIT_SAMPLES: - devc->limit_samples = g_variant_get_uint64(data); - sr_dbg("Setting sample limit to %" PRIu64 ".", devc->limit_samples); - break; - case SR_CONF_LIMIT_MSEC: - devc->limit_msec = g_variant_get_uint64(data); - sr_dbg("Setting time limit to %" PRIu64 "ms.", devc->limit_msec); - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - (void)sdi; - (void)cg; - - switch (key) { - case SR_CONF_SCAN_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t)); - break; - case SR_CONF_DEVICE_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t)); - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int dev_acquisition_start(const struct sr_dev_inst *sdi, - void *cb_data) -{ - struct dev_context *devc; - - (void)cb_data; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - devc = sdi->priv; - devc->start_time = g_get_monotonic_time(); - - /* Send header packet to the session bus. */ - std_session_send_df_header(sdi, LOG_PREFIX); - - sr_session_source_add(sdi->session, 0, 0, 10, - brymen_bm86x_receive_data, (void *)sdi); - - return SR_OK; -} - -static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) -{ - struct sr_datafeed_packet packet; - - (void)cb_data; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - /* Send end packet to the session bus. */ - packet.type = SR_DF_END; - sr_session_send(sdi, &packet); - - sr_session_source_remove(sdi->session, 0); - - return SR_OK; -} - -SR_PRIV struct sr_dev_driver brymen_bm86x_driver_info = { - .name = "brymen-bm86x", - .longname = "Brymen BM86X", - .api_version = 1, - .init = init, - .cleanup = cleanup, - .scan = scan, - .dev_list = dev_list, - .dev_clear = NULL, - .config_get = config_get, - .config_set = config_set, - .config_list = config_list, - .dev_open = dev_open, - .dev_close = dev_close, - .dev_acquisition_start = dev_acquisition_start, - .dev_acquisition_stop = dev_acquisition_stop, - .priv = NULL, -}; diff --git a/hardware/brymen-bm86x/protocol.c b/hardware/brymen-bm86x/protocol.c deleted file mode 100644 index b8e16a3f..00000000 --- a/hardware/brymen-bm86x/protocol.c +++ /dev/null @@ -1,343 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2014 Aurelien Jacobs - * - * 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 . - */ - -#include -#include -#include "protocol.h" - -#define USB_TIMEOUT 500 - -static char char_map[128] = { - [0x20] = '-', - [0x5F] = '0', - [0x50] = '1', - [0x6D] = '2', - [0x7C] = '3', - [0x72] = '4', - [0x3E] = '5', - [0x3F] = '6', - [0x54] = '7', - [0x7F] = '8', - [0x7E] = '9', - [0x0F] = 'C', - [0x27] = 'F', - [0x0B] = 'L', - [0x79] = 'd', - [0x10] = 'i', - [0x39] = 'o', -}; - -static int brymen_bm86x_parse_digits(const unsigned char *buf, int length, - char *str, float *floatval, - char *temp_unit, int flag) -{ - char c, *p = str; - int i, ret; - - if (buf[0] & flag) - *p++ = '-'; - for (i = 0; i < length; i++) { - if (i && i < 5 && buf[i+1] & 0x01) - *p++ = '.'; - c = char_map[buf[i+1] >> 1]; - if (i == 5 && (c == 'C' || c == 'F')) - *temp_unit = c; - else if (c) - *p++ = c; - } - *p = 0; - - if ((ret = sr_atof_ascii(str, floatval))) { - sr_dbg("invalid float string: '%s'", str); - return ret; - } - - return SR_OK; -} - -static void brymen_bm86x_parse(unsigned char *buf, float *floatval, - struct sr_datafeed_analog *analog) -{ - char str[16], temp_unit; - int ret1, ret2, over_limit; - - ret1 = brymen_bm86x_parse_digits(buf+2, 6, str, &floatval[0], - &temp_unit, 0x80); - over_limit = strstr(str, "0L") || strstr(str, "0.L"); - ret2 = brymen_bm86x_parse_digits(buf+9, 4, str, &floatval[1], - &temp_unit, 0x10); - - /* main display */ - if (ret1 == SR_OK || over_limit) { - /* SI unit */ - if (buf[8] & 0x01) { - analog[0].mq = SR_MQ_VOLTAGE; - analog[0].unit = SR_UNIT_VOLT; - if (!strcmp(str, "diod")) - analog[0].mqflags |= SR_MQFLAG_DIODE; - } else if (buf[14] & 0x80) { - analog[0].mq = SR_MQ_CURRENT; - analog[0].unit = SR_UNIT_AMPERE; - } else if (buf[14] & 0x20) { - analog[0].mq = SR_MQ_CAPACITANCE; - analog[0].unit = SR_UNIT_FARAD; - } else if (buf[14] & 0x10) { - analog[0].mq = SR_MQ_CONDUCTANCE; - analog[0].unit = SR_UNIT_SIEMENS; - } else if (buf[15] & 0x01) { - analog[0].mq = SR_MQ_FREQUENCY; - analog[0].unit = SR_UNIT_HERTZ; - } else if (buf[10] & 0x01) { - analog[0].mq = SR_MQ_CONTINUITY; - analog[0].unit = SR_UNIT_OHM; - } else if (buf[15] & 0x10) { - analog[0].mq = SR_MQ_RESISTANCE; - analog[0].unit = SR_UNIT_OHM; - } else if (buf[15] & 0x02) { - analog[0].mq = SR_MQ_POWER; - analog[0].unit = SR_UNIT_DECIBEL_MW; - } else if (buf[15] & 0x80) { - analog[0].mq = SR_MQ_DUTY_CYCLE; - analog[0].unit = SR_UNIT_PERCENTAGE; - } else if (buf[ 2] & 0x0A) { - analog[0].mq = SR_MQ_TEMPERATURE; - if (temp_unit == 'F') - analog[0].unit = SR_UNIT_FAHRENHEIT; - else - analog[0].unit = SR_UNIT_CELSIUS; - } - - /* when MIN MAX and AVG are displayed at the same time, remove them */ - if ((buf[1] & 0xE0) == 0xE0) - buf[1] &= ~0xE0; - - /* AC/DC/Auto flags */ - if (buf[1] & 0x10) analog[0].mqflags |= SR_MQFLAG_DC; - if (buf[2] & 0x01) analog[0].mqflags |= SR_MQFLAG_AC; - if (buf[1] & 0x01) analog[0].mqflags |= SR_MQFLAG_AUTORANGE; - if (buf[1] & 0x08) analog[0].mqflags |= SR_MQFLAG_HOLD; - if (buf[1] & 0x20) analog[0].mqflags |= SR_MQFLAG_MAX; - if (buf[1] & 0x40) analog[0].mqflags |= SR_MQFLAG_MIN; - if (buf[1] & 0x80) analog[0].mqflags |= SR_MQFLAG_AVG; - if (buf[3] & 0x01) analog[0].mqflags |= SR_MQFLAG_RELATIVE; - - /* when dBm is displayed, remove the m suffix so that it is - not considered as the 10e-3 SI prefix */ - if (buf[15] & 0x02) - buf[15] &= ~0x04; - - /* SI prefix */ - if (buf[14] & 0x40) floatval[0] *= 1e-9; /* n */ - if (buf[15] & 0x08) floatval[0] *= 1e-6; /* µ */ - if (buf[15] & 0x04) floatval[0] *= 1e-3; /* m */ - if (buf[15] & 0x40) floatval[0] *= 1e3; /* k */ - if (buf[15] & 0x20) floatval[0] *= 1e6; /* M */ - - if (over_limit) floatval[0] = INFINITY; - } - - /* secondary display */ - if (ret2 == SR_OK) { - /* SI unit */ - if (buf[14] & 0x08) { - analog[1].mq = SR_MQ_VOLTAGE; - analog[1].unit = SR_UNIT_VOLT; - } else if (buf[9] & 0x04) { - analog[1].mq = SR_MQ_CURRENT; - analog[1].unit = SR_UNIT_AMPERE; - } else if (buf[14] & 0x04) { - analog[1].mq = SR_MQ_FREQUENCY; - analog[1].unit = SR_UNIT_HERTZ; - } else if (buf[9] & 0x40) { - analog[1].mq = SR_MQ_TEMPERATURE; - if (temp_unit == 'F') - analog[1].unit = SR_UNIT_FAHRENHEIT; - else - analog[1].unit = SR_UNIT_CELSIUS; - } - - /* AC flag */ - if (buf[9] & 0x20) analog[1].mqflags |= SR_MQFLAG_AC; - - /* SI prefix */ - if (buf[ 9] & 0x01) floatval[1] *= 1e-6; /* µ */ - if (buf[ 9] & 0x02) floatval[1] *= 1e-3; /* m */ - if (buf[14] & 0x02) floatval[1] *= 1e3; /* k */ - if (buf[14] & 0x01) floatval[1] *= 1e6; /* M */ - } - - if (buf[9] & 0x80) - sr_spew("Battery is low."); -} - -static void brymen_bm86x_handle_packet(const struct sr_dev_inst *sdi, - unsigned char *buf) -{ - struct dev_context *devc; - struct sr_datafeed_packet packet; - struct sr_datafeed_analog analog[2]; - float floatval[2]; - - devc = sdi->priv; - - analog[0].mq = -1; - analog[0].mqflags = 0; - - analog[1].mq = -1; - analog[1].mqflags = 0; - - brymen_bm86x_parse(buf, floatval, analog); - - if (analog[0].mq != -1) { - /* Got a measurement. */ - analog[0].num_samples = 1; - analog[0].data = &floatval[0]; - analog[0].channels = g_slist_append(NULL, sdi->channels->data); - packet.type = SR_DF_ANALOG; - packet.payload = &analog[0]; - sr_session_send(sdi, &packet); - g_slist_free(analog[0].channels); - } - - if (analog[1].mq != -1) { - /* Got a measurement. */ - analog[1].num_samples = 1; - analog[1].data = &floatval[1]; - analog[1].channels = g_slist_append(NULL, sdi->channels->next->data); - packet.type = SR_DF_ANALOG; - packet.payload = &analog[1]; - sr_session_send(sdi, &packet); - g_slist_free(analog[1].channels); - } - - if (analog[0].mq != -1 || analog[1].mq != -1) - devc->num_samples++; -} - -static int brymen_bm86x_send_command(const struct sr_dev_inst *sdi) -{ - struct sr_usb_dev_inst *usb; - unsigned char buf[] = { 0x00, 0x86, 0x66 }; - int ret; - - usb = sdi->conn; - - sr_dbg("Sending HID set report."); - ret = libusb_control_transfer(usb->devhdl, - LIBUSB_REQUEST_TYPE_CLASS | - LIBUSB_RECIPIENT_INTERFACE | - LIBUSB_ENDPOINT_OUT, - 9, /* bRequest: HID set_report */ - 0x300, /* wValue: HID feature, report num 0 */ - 0, /* wIndex: interface 0 */ - buf, sizeof(buf), USB_TIMEOUT); - - if (ret < 0) { - sr_err("HID feature report error: %s.", libusb_error_name(ret)); - return SR_ERR; - } - - if (ret != sizeof(buf)) { - sr_err("Short packet: sent %d/%ld bytes.", ret, sizeof(buf)); - return SR_ERR; - } - - return SR_OK; -} - -static int brymen_bm86x_read_interrupt(const struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - struct sr_usb_dev_inst *usb; - unsigned char buf[24]; - int ret, transferred; - - devc = sdi->priv; - usb = sdi->conn; - - sr_dbg("Reading HID interrupt report."); - /* Get data from EP1 using an interrupt transfer. */ - ret = libusb_interrupt_transfer(usb->devhdl, - LIBUSB_ENDPOINT_IN | 1, /* EP1, IN */ - buf, sizeof(buf), - &transferred, USB_TIMEOUT); - - if (ret == LIBUSB_ERROR_TIMEOUT) { - if (++devc->interrupt_pending > 3) - devc->interrupt_pending = 0; - return SR_OK; - } - - if (ret < 0) { - sr_err("USB receive error: %s.", libusb_error_name(ret)); - return SR_ERR; - } - - if (transferred != sizeof(buf)) { - sr_err("Short packet: received %d/%d bytes.", transferred, sizeof(buf)); - return SR_ERR; - } - - devc->interrupt_pending = 0; - brymen_bm86x_handle_packet(sdi, buf); - - return SR_OK; -} - -SR_PRIV int brymen_bm86x_receive_data(int fd, int revents, void *cb_data) -{ - struct sr_dev_inst *sdi; - struct dev_context *devc; - int64_t time; - - (void)fd; - (void)revents; - - if (!(sdi = cb_data)) - return TRUE; - - if (!(devc = sdi->priv)) - return TRUE; - - if (!devc->interrupt_pending) { - if (brymen_bm86x_send_command(sdi)) - return FALSE; - devc->interrupt_pending = 1; - } - - if (brymen_bm86x_read_interrupt(sdi)) - return FALSE; - - if (devc->limit_samples && devc->num_samples >= devc->limit_samples) { - sr_info("Requested number of samples reached, stopping."); - sdi->driver->dev_acquisition_stop(sdi, cb_data); - return TRUE; - } - - if (devc->limit_msec) { - time = (g_get_monotonic_time() - devc->start_time) / 1000; - if (time > (int64_t)devc->limit_msec) { - sr_info("Requested time limit reached, stopping."); - sdi->driver->dev_acquisition_stop(sdi, cb_data); - return TRUE; - } - } - - return TRUE; -} diff --git a/hardware/brymen-bm86x/protocol.h b/hardware/brymen-bm86x/protocol.h deleted file mode 100644 index 57af1552..00000000 --- a/hardware/brymen-bm86x/protocol.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2014 Aurelien Jacobs - * - * 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 . - */ - -#ifndef LIBSIGROK_HARDWARE_BRYMEN_BM86X_PROTOCOL_H -#define LIBSIGROK_HARDWARE_BRYMEN_BM86X_PROTOCOL_H - -#include -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#define LOG_PREFIX "brymen-bm86x" - -/** Private, per-device-instance driver context. */ -struct dev_context { - /* Acquisition settings */ - uint64_t limit_samples; /**< The sampling limit (in number of samples).*/ - uint64_t limit_msec; /**< The time limit (in milliseconds). */ - - /* Operational state */ - int detached_kernel_driver;/**< Whether kernel driver was detached or not */ - uint64_t num_samples; /**< The number of already received samples. */ - int64_t start_time; /**< The time at which sampling started. */ - - /* Temporary state across callbacks */ - int interrupt_pending; -}; - -SR_PRIV int brymen_bm86x_receive_data(int fd, int revents, void *cb_data); - -#endif diff --git a/hardware/brymen-dmm/api.c b/hardware/brymen-dmm/api.c deleted file mode 100644 index 1ccd18af..00000000 --- a/hardware/brymen-dmm/api.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2012 Alexandru Gagniuc - * - * 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 . - */ - -#include "protocol.h" - -static const int32_t hwopts[] = { - SR_CONF_CONN, - SR_CONF_SERIALCOMM, -}; - -static const int32_t hwcaps[] = { - SR_CONF_MULTIMETER, - SR_CONF_LIMIT_SAMPLES, - SR_CONF_CONTINUOUS, - SR_CONF_LIMIT_MSEC, -}; - -SR_PRIV struct sr_dev_driver brymen_bm857_driver_info; -static struct sr_dev_driver *di = &brymen_bm857_driver_info; - -static int init(struct sr_context *sr_ctx) -{ - return std_init(sr_ctx, di, LOG_PREFIX); -} - -static GSList *brymen_scan(const char *conn, const char *serialcomm) -{ - struct sr_dev_inst *sdi; - struct dev_context *devc; - struct drv_context *drvc; - struct sr_channel *ch; - struct sr_serial_dev_inst *serial; - GSList *devices; - int ret; - uint8_t buf[128]; - size_t len; - - if (!(serial = sr_serial_dev_inst_new(conn, serialcomm))) - return NULL; - - if (serial_open(serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK) - return NULL; - - sr_info("Probing port %s.", conn); - - devices = NULL; - - /* Request reading */ - if ((ret = brymen_packet_request(serial)) < 0) { - sr_err("Unable to send command: %d.", ret); - goto scan_cleanup; - } - - len = 128; - ret = brymen_stream_detect(serial, buf, &len, brymen_packet_length, - brymen_packet_is_valid, 1000, 9600); - if (ret != SR_OK) - goto scan_cleanup; - - sr_info("Found device on port %s.", conn); - - if (!(sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, "Brymen", "BM85x", NULL))) - goto scan_cleanup; - - if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) { - sr_err("Device context malloc failed."); - goto scan_cleanup; - } - - sdi->inst_type = SR_INST_SERIAL; - sdi->conn = serial; - drvc = di->priv; - sdi->priv = devc; - sdi->driver = di; - - if (!(ch = sr_channel_new(0, SR_CHANNEL_ANALOG, TRUE, "P1"))) - goto scan_cleanup; - - sdi->channels = g_slist_append(sdi->channels, ch); - drvc->instances = g_slist_append(drvc->instances, sdi); - devices = g_slist_append(devices, sdi); - -scan_cleanup: - serial_close(serial); - - return devices; -} - -static GSList *scan(GSList *options) -{ - struct drv_context *drvc; - struct sr_config *src; - GSList *devices, *l; - const char *conn, *serialcomm; - - devices = NULL; - drvc = di->priv; - drvc->instances = NULL; - - conn = serialcomm = NULL; - for (l = options; l; l = l->next) { - src = l->data; - switch (src->key) { - case SR_CONF_CONN: - conn = g_variant_get_string(src->data, NULL); - break; - case SR_CONF_SERIALCOMM: - serialcomm = g_variant_get_string(src->data, NULL); - break; - } - } - if (!conn) - return NULL; - - if (serialcomm) { - /* Use the provided comm specs. */ - devices = brymen_scan(conn, serialcomm); - } else { - /* But 9600/8n1 should work all of the time. */ - devices = brymen_scan(conn, "9600/8n1/dtr=1/rts=1"); - } - - return devices; -} - -static GSList *dev_list(void) -{ - return ((struct drv_context *)(di->priv))->instances; -} - -static int cleanup(void) -{ - return std_dev_clear(di, NULL); -} - -static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc; - int ret; - - (void)cg; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - if (!(devc = sdi->priv)) { - sr_err("sdi->priv was NULL."); - return SR_ERR_BUG; - } - - ret = SR_OK; - switch (id) { - case SR_CONF_LIMIT_SAMPLES: - devc->limit_samples = g_variant_get_uint64(data); - break; - case SR_CONF_LIMIT_MSEC: - devc->limit_msec = g_variant_get_uint64(data); - break; - default: - ret = SR_ERR_NA; - } - - return ret; -} - -static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - (void)sdi; - (void)cg; - - switch (key) { - case SR_CONF_SCAN_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t)); - break; - case SR_CONF_DEVICE_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t)); - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) -{ - struct dev_context *devc; - struct sr_serial_dev_inst *serial; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - if (!(devc = sdi->priv)) { - sr_err("sdi->priv was NULL."); - return SR_ERR_BUG; - } - - devc->cb_data = cb_data; - - /* - * Reset the number of samples to take. If we've already collected our - * quota, but we start a new session, and don't reset this, we'll just - * quit without acquiring any new samples. - */ - devc->num_samples = 0; - devc->starttime = g_get_monotonic_time(); - - /* Send header packet to the session bus. */ - std_session_send_df_header(cb_data, LOG_PREFIX); - - /* Poll every 50ms, or whenever some data comes in. */ - serial = sdi->conn; - serial_source_add(sdi->session, serial, G_IO_IN, 50, - brymen_dmm_receive_data, (void *)sdi); - - return SR_OK; -} - -static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) -{ - return std_serial_dev_acquisition_stop(sdi, cb_data, std_serial_dev_close, - sdi->conn, LOG_PREFIX); -} - -SR_PRIV struct sr_dev_driver brymen_bm857_driver_info = { - .name = "brymen-bm857", - .longname = "Brymen BM857", - .api_version = 1, - .init = init, - .cleanup = cleanup, - .scan = scan, - .dev_list = dev_list, - .dev_clear = NULL, - .config_get = NULL, - .config_set = config_set, - .config_list = config_list, - .dev_open = std_serial_dev_open, - .dev_close = std_serial_dev_close, - .dev_acquisition_start = dev_acquisition_start, - .dev_acquisition_stop = dev_acquisition_stop, - .priv = NULL, -}; diff --git a/hardware/brymen-dmm/parser.c b/hardware/brymen-dmm/parser.c deleted file mode 100644 index e4b12274..00000000 --- a/hardware/brymen-dmm/parser.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2012 Alexandru Gagniuc - * - * 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 . - */ - -#include "protocol.h" - -#define MAX_PACKET_LEN 22 - -/* Flags passed from the DMM. */ -struct brymen_flags { - gboolean is_low_batt, is_decibel, is_duty_cycle, is_hertz, is_amp; - gboolean is_beep, is_ohm, is_fahrenheit, is_celsius, is_capacitance; - gboolean is_diode, is_volt, is_dc, is_ac; -}; - -struct bm850_command { - uint8_t dle; - uint8_t stx; - uint8_t cmd; - uint8_t arg[2]; - uint8_t checksum; - uint8_t dle2; - uint8_t etx; -}; - -struct brymen_header { - uint8_t dle; - uint8_t stx; - uint8_t cmd; - uint8_t len; -}; - -struct brymen_tail { - uint8_t checksum; - uint8_t dle; - uint8_t etx; -}; - -/* - * We only have one command because we only support the BM-857. However, the - * driver is easily extensible to support more models, as the protocols are - * very similar. - */ -enum { - BM_CMD_REQUEST_READING = 0x00, -}; - -static int bm_send_command(uint8_t command, uint8_t arg1, uint8_t arg2, - struct sr_serial_dev_inst *serial) -{ - struct bm850_command cmdout; - int written; - - cmdout.dle = 0x10; - cmdout.stx = 0x02; - cmdout.cmd = command; - cmdout.arg[0] = arg1; - cmdout.arg[1] = arg2; - cmdout.checksum = arg1 ^ arg2; - cmdout.dle2 = 0x10; - cmdout.etx = 0x03; - - /* TODO: How to compute the checksum? Hardware seems to ignore it. */ - - /* Request reading. */ - written = serial_write(serial, &cmdout, sizeof(cmdout)); - if (written != sizeof(cmdout)) - return SR_ERR; - - return SR_OK; -} - -SR_PRIV int brymen_packet_request(struct sr_serial_dev_inst *serial) -{ - return bm_send_command(BM_CMD_REQUEST_READING, 0, 0, serial); -} - -SR_PRIV int brymen_packet_length(const uint8_t *buf, int *len) -{ - struct brymen_header *hdr; - int packet_len; - size_t buflen; - - buflen = *len; - hdr = (void *)buf; - - /* Did we receive a complete header yet? */ - if (buflen < sizeof(*hdr)) - return PACKET_NEED_MORE_DATA; - - if (hdr->dle != 0x10 || hdr->stx != 0x02) - return PACKET_INVALID_HEADER; - - /* Our packet includes the header, the payload, and the tail. */ - packet_len = sizeof(*hdr) + hdr->len + sizeof(struct brymen_tail); - - /* In case we pick up an invalid header, limit our search. */ - if (packet_len > MAX_PACKET_LEN) { - sr_spew("Header specifies an invalid payload length: %i.", - hdr->len); - return PACKET_INVALID_HEADER; - } - - *len = packet_len; - sr_spew("Expecting a %d-byte packet.", *len); - return PACKET_HEADER_OK; -} - -SR_PRIV gboolean brymen_packet_is_valid(const uint8_t *buf) -{ - struct brymen_header *hdr; - struct brymen_tail *tail; - int i; - uint8_t chksum = 0; - uint8_t *payload; - - payload = (uint8_t *)(buf + sizeof(struct brymen_header)); - - hdr = (void *)buf; - tail = (void *)(payload + hdr->len); - - for (i = 0; i< hdr->len; i++) - chksum ^= payload[i]; - - if (tail->checksum != chksum) { - sr_dbg("Packet has invalid checksum 0x%.2x. Expected 0x%.2x.", - chksum, tail->checksum); - return FALSE; - } - - return TRUE; -} - -static int parse_value(const char *strbuf, int len, float *floatval) -{ - int s, d; - char str[32]; - - if (strstr(strbuf, "OL")) { - sr_dbg("Overlimit."); - *floatval = INFINITY; - return SR_OK; - } - - memset(str, 0, sizeof(str)); - /* Spaces may interfere with parsing the exponent. Strip them. */ - for (s = 0, d = 0; s < len; s++) { - if (strbuf[s] != ' ') - str[d++] = strbuf[s]; - } - if (sr_atof_ascii(str, floatval) != SR_OK) - return SR_ERR; - - return SR_OK; -} - -static void parse_flags(const uint8_t *buf, struct brymen_flags *info) -{ - info->is_low_batt = (buf[4 + 3] & (1 << 7)) != 0; - - info->is_decibel = (buf[4 + 1] & (1 << 5)) != 0; - info->is_duty_cycle = (buf[4 + 1] & (1 << 3)) != 0; - info->is_hertz = (buf[4 + 1] & (1 << 2)) != 0; - info->is_amp = (buf[4 + 1] & (1 << 1)) != 0; - info->is_beep = (buf[4 + 1] & (1 << 0)) != 0; - - info->is_ohm = (buf[4 + 0] & (1 << 7)) != 0; - info->is_fahrenheit = (buf[4 + 0] & (1 << 6)) != 0; - info->is_celsius = (buf[4 + 0] & (1 << 5)) != 0; - info->is_diode = (buf[4 + 0] & (1 << 4)) != 0; - info->is_capacitance = (buf[4 + 0] & (1 << 3)) != 0; - info->is_volt = (buf[4 + 0] & (1 << 2)) != 0; - info->is_dc = (buf[4 + 0] & (1 << 1)) != 0; - info->is_ac = (buf[4 + 0] & (1 << 0)) != 0; -} - -SR_PRIV int brymen_parse(const uint8_t *buf, float *floatval, - struct sr_datafeed_analog *analog, void *info) -{ - struct brymen_flags flags; - struct brymen_header *hdr; - uint8_t *bfunc; - int asciilen; - - (void)info; - - hdr = (void *)buf; - bfunc = (uint8_t *)(buf + sizeof(struct brymen_header)); - - analog->mqflags = 0; - - /* Give some debug info about the package. */ - asciilen = hdr->len - 4; - sr_dbg("DMM flags: %.2x %.2x %.2x %.2x", - bfunc[3], bfunc[2], bfunc[1], bfunc[0]); - /* Value is an ASCII string. */ - sr_dbg("DMM packet: \"%.*s\"", asciilen, bfunc + 4); - - parse_flags(buf, &flags); - if (parse_value((const char *)(bfunc + 4), asciilen, floatval) != SR_OK) - return SR_ERR; - - if (flags.is_volt) { - analog->mq = SR_MQ_VOLTAGE; - analog->unit = SR_UNIT_VOLT; - } - if (flags.is_amp) { - analog->mq = SR_MQ_CURRENT; - analog->unit = SR_UNIT_AMPERE; - } - if (flags.is_ohm) { - if (flags.is_beep) - analog->mq = SR_MQ_CONTINUITY; - else - analog->mq = SR_MQ_RESISTANCE; - analog->unit = SR_UNIT_OHM; - } - if (flags.is_hertz) { - analog->mq = SR_MQ_FREQUENCY; - analog->unit = SR_UNIT_HERTZ; - } - if (flags.is_duty_cycle) { - analog->mq = SR_MQ_DUTY_CYCLE; - analog->unit = SR_UNIT_PERCENTAGE; - } - if (flags.is_capacitance) { - analog->mq = SR_MQ_CAPACITANCE; - analog->unit = SR_UNIT_FARAD; - } - if (flags.is_fahrenheit) { - analog->mq = SR_MQ_TEMPERATURE; - analog->unit = SR_UNIT_FAHRENHEIT; - } - if (flags.is_celsius) { - analog->mq = SR_MQ_TEMPERATURE; - analog->unit = SR_UNIT_CELSIUS; - } - if (flags.is_capacitance) { - analog->mq = SR_MQ_CAPACITANCE; - analog->unit = SR_UNIT_FARAD; - } - - /* - * The high-end Brymen models have a configurable reference impedance. - * When the reference impedance is changed, the DMM sends one packet - * with the value of the new reference impedance. Both decibel and ohm - * flags are set in this case, so we must be careful to correctly - * identify the value as ohm, not dBmW. - */ - if (flags.is_decibel && !flags.is_ohm) { - analog->mq = SR_MQ_POWER; - analog->unit = SR_UNIT_DECIBEL_MW; - /* - * For some reason, dBm measurements are sent by the multimeter - * with a value three orders of magnitude smaller than the - * displayed value. - */ - *floatval *= 1000; - } - - if (flags.is_diode) - analog->mqflags |= SR_MQFLAG_DIODE; - /* We can have both AC+DC in a single measurement. */ - if (flags.is_ac) - analog->mqflags |= SR_MQFLAG_AC; - if (flags.is_dc) - analog->mqflags |= SR_MQFLAG_DC; - - if (flags.is_low_batt) - sr_info("Low battery!"); - - return SR_OK; -} diff --git a/hardware/brymen-dmm/protocol.c b/hardware/brymen-dmm/protocol.c deleted file mode 100644 index dff7b985..00000000 --- a/hardware/brymen-dmm/protocol.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2012 Alexandru Gagniuc - * - * 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 . - */ - -#include "protocol.h" - -static void handle_packet(const uint8_t *buf, struct sr_dev_inst *sdi) -{ - float floatval; - struct dev_context *devc; - struct sr_datafeed_packet packet; - struct sr_datafeed_analog analog; - - devc = sdi->priv; - - analog.num_samples = 1; - analog.mq = -1; - - if (brymen_parse(buf, &floatval, &analog, NULL) != SR_OK) - return; - analog.data = &floatval; - - analog.channels = sdi->channels; - - if (analog.mq != -1) { - /* Got a measurement. */ - packet.type = SR_DF_ANALOG; - packet.payload = &analog; - sr_session_send(devc->cb_data, &packet); - devc->num_samples++; - } -} - -static void handle_new_data(struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - int len, status, offset = 0; - struct sr_serial_dev_inst *serial; - - devc = sdi->priv; - serial = sdi->conn; - - /* Try to get as much data as the buffer can hold. */ - len = DMM_BUFSIZE - devc->buflen; - len = serial_read(serial, devc->buf + devc->buflen, len); - if (len < 1) { - sr_err("Serial port read error: %d.", len); - return; - } - devc->buflen += len; - status = PACKET_INVALID_HEADER; - - /* Now look for packets in that data. */ - while (status != PACKET_NEED_MORE_DATA) { - /* We don't have a header, look for one. */ - if (devc->next_packet_len == 0) { - len = devc->buflen - offset; - status = brymen_packet_length(devc->buf + offset, &len); - if (status == PACKET_HEADER_OK) { - /* We know how large the packet will be. */ - devc->next_packet_len = len; - } else if (status == PACKET_NEED_MORE_DATA) { - /* We didn't yet receive the full header. */ - devc->next_packet_len = 0; - break; - } else { - /* Invalid header. Move on. */ - devc->next_packet_len = 0; - offset++; - continue; - } - } - - /* We know how the packet size, but did we receive all of it? */ - if (devc->buflen - offset < devc->next_packet_len) - break; - - /* We should have a full packet here, so we can check it. */ - if (brymen_packet_is_valid(devc->buf + offset)) { - handle_packet(devc->buf + offset, sdi); - offset += devc->next_packet_len; - } else { - offset++; - } - - /* We are done with this packet. Look for a new one. */ - devc->next_packet_len = 0; - } - - /* If we have any data left, move it to the beginning of our buffer. */ - memmove(devc->buf, devc->buf + offset, devc->buflen - offset); - devc->buflen -= offset; -} - -SR_PRIV int brymen_dmm_receive_data(int fd, int revents, void *cb_data) -{ - struct sr_dev_inst *sdi; - struct dev_context *devc; - struct sr_serial_dev_inst *serial; - int ret; - int64_t time; - - (void)fd; - - if (!(sdi = cb_data)) - return TRUE; - - if (!(devc = sdi->priv)) - return TRUE; - - serial = sdi->conn; - - if (revents == G_IO_IN) { - /* Serial data arrived. */ - handle_new_data(sdi); - } else { - /* Timeout, send another packet request. */ - if ((ret = brymen_packet_request(serial)) < 0) { - sr_err("Failed to request packet: %d.", ret); - return FALSE; - } - } - - if (devc->limit_samples && devc->num_samples >= devc->limit_samples) { - sr_info("Requested number of samples reached, stopping."); - sdi->driver->dev_acquisition_stop(sdi, cb_data); - return TRUE; - } - - if (devc->limit_msec) { - time = (g_get_monotonic_time() - devc->starttime) / 1000; - if (time > (int64_t)devc->limit_msec) { - sr_info("Requested time limit reached, stopping."); - sdi->driver->dev_acquisition_stop(sdi, cb_data); - return TRUE; - } - } - - return TRUE; -} - -/** - * Try to find a valid packet in a serial data stream. - * - * @param serial Previously initialized serial port structure. - * @param buf Buffer containing the bytes to write. - * @param buflen Size of the buffer. - * @param get_packet_size Callback that assesses the size of incoming packets. - * @param is_valid Callback that assesses whether the packet is valid or not. - * @param timeout_ms The timeout after which, if no packet is detected, to - * abort scanning. - * @param baudrate The baudrate of the serial port. This parameter is not - * critical, but it helps fine tune the serial port polling - * delay. - * - * @return SR_OK if a valid packet is found within the given timeout, - * SR_ERR upon failure. - */ -SR_PRIV int brymen_stream_detect(struct sr_serial_dev_inst *serial, - uint8_t *buf, size_t *buflen, - packet_length_t get_packet_size, - packet_valid_callback is_valid, - uint64_t timeout_ms, int baudrate) -{ - int64_t start, time, byte_delay_us; - size_t ibuf, i, maxlen; - int status, len, packet_len, stream_len; - - maxlen = *buflen; - - sr_dbg("Detecting packets on %s (timeout = %" PRIu64 - "ms, baudrate = %d).", serial->port, timeout_ms, baudrate); - - /* Assume 8n1 transmission. That is 10 bits for every byte. */ - byte_delay_us = 10 * (1000000 / baudrate); - start = g_get_monotonic_time(); - - packet_len = i = ibuf = len = 0; - while (ibuf < maxlen) { - len = serial_read(serial, &buf[ibuf], maxlen - ibuf); - if (len > 0) { - ibuf += len; - sr_spew("Read %d bytes.", len); - } - - time = g_get_monotonic_time() - start; - time /= 1000; - - stream_len = ibuf - i; - if (stream_len > 0 && packet_len == 0) { - /* How large of a packet are we expecting? */ - packet_len = stream_len; - status = get_packet_size(&buf[i], &packet_len); - switch(status) { - case PACKET_HEADER_OK: - /* We know how much data we need to wait for. */ - break; - case PACKET_NEED_MORE_DATA: - /* We did not receive the full header. */ - packet_len = 0; - break; - case PACKET_INVALID_HEADER: - default: - /* - * We had enough data, but here was an error in - * parsing the header. Restart parsing from the - * next byte. - */ - packet_len = 0; - i++; - break; - } - } - - if ((stream_len >= packet_len) && (packet_len != 0)) { - /* We have at least a packet's worth of data. */ - if (is_valid(&buf[i])) { - sr_spew("Found valid %d-byte packet after " - "%" PRIu64 "ms.", packet_len, time); - *buflen = ibuf; - return SR_OK; - } else { - sr_spew("Got %d bytes, but not a valid " - "packet.", packet_len); - - } - - /* Not a valid packet. Continue searching. */ - i++; - packet_len = 0; - } - - if (time >= (int64_t)timeout_ms) { - /* Timeout */ - sr_dbg("Detection timed out after %dms.", time); - break; - } - g_usleep(byte_delay_us); - } - - *buflen = ibuf; - sr_err("Didn't find a valid packet (read %d bytes).", ibuf); - - return SR_ERR; -} diff --git a/hardware/brymen-dmm/protocol.h b/hardware/brymen-dmm/protocol.h deleted file mode 100644 index 7c9aaae6..00000000 --- a/hardware/brymen-dmm/protocol.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2012 Alexandru Gagniuc - * - * 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 . - */ - -#ifndef LIBSIGROK_HARDWARE_BRYMEN_DMM_PROTOCOL_H -#define LIBSIGROK_HARDWARE_BRYMEN_DMM_PROTOCOL_H - -#include -#include -#include -#include -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#define LOG_PREFIX "brymen-dmm" - -#define DMM_BUFSIZE 256 - -enum packet_len_status { - PACKET_HEADER_OK, - PACKET_NEED_MORE_DATA, - PACKET_INVALID_HEADER, -}; - -/** Private, per-device-instance driver context. */ -struct dev_context { - /** The current sampling limit (in number of samples). */ - uint64_t limit_samples; - - /** The current sampling limit (in ms). */ - uint64_t limit_msec; - - /** Opaque pointer passed in by the frontend. */ - void *cb_data; - - /** The current number of already received samples. */ - uint64_t num_samples; - - /** Start time of acquisition session */ - int64_t starttime; - - uint8_t buf[DMM_BUFSIZE]; - int bufoffset; - int buflen; - int next_packet_len; -}; - -/** - * Callback that assesses the size and status of the incoming packet. - * - * @return PACKET_HEADER_OK - This is a proper packet header. - * PACKET_NEED_MORE_DATA The buffer does not contain the entire header. - * PACKET_INVALID_HEADER Not a valid start of packet. - */ -typedef int (*packet_length_t)(const uint8_t *buf, int *len); - -SR_PRIV int brymen_dmm_receive_data(int fd, int revents, void *cb_data); -SR_PRIV int brymen_packet_request(struct sr_serial_dev_inst *serial); - -SR_PRIV int brymen_packet_length(const uint8_t *buf, int *len); -SR_PRIV gboolean brymen_packet_is_valid(const uint8_t *buf); - -SR_PRIV int brymen_parse(const uint8_t *buf, float *floatval, - struct sr_datafeed_analog *analog, void *info); - -SR_PRIV int brymen_stream_detect(struct sr_serial_dev_inst *serial, - uint8_t *buf, size_t *buflen, - packet_length_t get_packet_size, - packet_valid_callback is_valid, - uint64_t timeout_ms, int baudrate); - -#endif diff --git a/hardware/cem-dt-885x/api.c b/hardware/cem-dt-885x/api.c deleted file mode 100644 index 9aed5473..00000000 --- a/hardware/cem-dt-885x/api.c +++ /dev/null @@ -1,432 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2013 Bert Vermeulen - * - * 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 . - */ - -#include -#include "protocol.h" - -#define SERIALCOMM "9600/8n1" -/* 23ms is the longest interval between tokens. */ -#define MAX_SCAN_TIME 25 * 1000 - -static const int32_t hwopts[] = { - SR_CONF_CONN, -}; - -static const int32_t hwcaps[] = { - SR_CONF_SOUNDLEVELMETER, - SR_CONF_LIMIT_SAMPLES, - SR_CONF_CONTINUOUS, - SR_CONF_SPL_WEIGHT_FREQ, - SR_CONF_SPL_WEIGHT_TIME, - SR_CONF_SPL_MEASUREMENT_RANGE, - SR_CONF_DATALOG, - SR_CONF_HOLD_MAX, - SR_CONF_HOLD_MIN, - SR_CONF_POWER_OFF, - SR_CONF_DATA_SOURCE, -}; - -static const char *weight_freq[] = { - "A", - "C", -}; - -static const char *weight_time[] = { - "F", - "S", -}; - -static const uint64_t meas_ranges[][2] = { - { 30, 130 }, - { 30, 80 }, - { 50, 100 }, - { 80, 130 }, -}; - -static const char *data_sources[] = { - "Live", - "Memory", -}; -SR_PRIV struct sr_dev_driver cem_dt_885x_driver_info; -static struct sr_dev_driver *di = &cem_dt_885x_driver_info; - - -static int init(struct sr_context *sr_ctx) -{ - return std_init(sr_ctx, di, LOG_PREFIX); -} - -static GSList *scan(GSList *options) -{ - struct drv_context *drvc; - struct dev_context *devc; - struct sr_config *src; - struct sr_serial_dev_inst *serial; - struct sr_dev_inst *sdi; - struct sr_channel *ch; - GSList *l, *devices; - gint64 start; - const char *conn; - unsigned char c; - - conn = NULL; - for (l = options; l; l = l->next) { - src = l->data; - if (src->key == SR_CONF_CONN) - conn = g_variant_get_string(src->data, NULL); - } - if (!conn) - return NULL; - - if (!(serial = sr_serial_dev_inst_new(conn, SERIALCOMM))) - return NULL; - - if (serial_open(serial, SERIAL_RDONLY | SERIAL_NONBLOCK) != SR_OK) - return NULL; - - devices = NULL; - drvc = di->priv; - start = g_get_monotonic_time(); - while (g_get_monotonic_time() - start < MAX_SCAN_TIME) { - if (serial_read(serial, &c, 1) == 1 && c == 0xa5) { - /* Found one. */ - if (!(sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, "CEM", - "DT-885x", NULL))) - return NULL; - - if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) { - sr_dbg("Device context malloc failed."); - return NULL; - } - devc->cur_mqflags = 0; - devc->recording = -1; - devc->cur_meas_range = 0; - devc->cur_data_source = DATA_SOURCE_LIVE; - devc->enable_data_source_memory = FALSE; - - if (!(sdi->conn = sr_serial_dev_inst_new(conn, SERIALCOMM))) - return NULL; - - sdi->inst_type = SR_INST_SERIAL; - sdi->priv = devc; - sdi->driver = di; - if (!(ch = sr_channel_new(0, SR_CHANNEL_ANALOG, TRUE, "SPL"))) - return NULL; - sdi->channels = g_slist_append(sdi->channels, ch); - drvc->instances = g_slist_append(drvc->instances, sdi); - devices = g_slist_append(devices, sdi); - break; - } - /* It takes about 1ms for a byte to come in. */ - g_usleep(1000); - } - - serial_close(serial); - - return devices; -} - -static GSList *dev_list(void) -{ - return ((struct drv_context *)(di->priv))->instances; -} - -static int dev_open(struct sr_dev_inst *sdi) -{ - struct sr_serial_dev_inst *serial; - - serial = sdi->conn; - if (serial_open(serial, SERIAL_RDWR) != SR_OK) - return SR_ERR; - - sdi->status = SR_ST_ACTIVE; - - return SR_OK; -} - -static int cleanup(void) -{ - return std_dev_clear(di, NULL); -} - -static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc; - GVariant *range[2]; - uint64_t low, high; - int tmp, ret; - - (void)cg; - - if (!sdi) - return SR_ERR_ARG; - - devc = sdi->priv; - ret = SR_OK; - switch (key) { - case SR_CONF_LIMIT_SAMPLES: - *data = g_variant_new_uint64(devc->limit_samples); - break; - case SR_CONF_DATALOG: - if ((ret = cem_dt_885x_recording_get(sdi, &tmp)) == SR_OK) - *data = g_variant_new_boolean(tmp); - break; - case SR_CONF_SPL_WEIGHT_FREQ: - tmp = cem_dt_885x_weight_freq_get(sdi); - if (tmp == SR_MQFLAG_SPL_FREQ_WEIGHT_A) - *data = g_variant_new_string("A"); - else if (tmp == SR_MQFLAG_SPL_FREQ_WEIGHT_C) - *data = g_variant_new_string("C"); - else - return SR_ERR; - break; - case SR_CONF_SPL_WEIGHT_TIME: - tmp = cem_dt_885x_weight_time_get(sdi); - if (tmp == SR_MQFLAG_SPL_TIME_WEIGHT_F) - *data = g_variant_new_string("F"); - else if (tmp == SR_MQFLAG_SPL_TIME_WEIGHT_S) - *data = g_variant_new_string("S"); - else - return SR_ERR; - break; - case SR_CONF_HOLD_MAX: - if ((ret = cem_dt_885x_holdmode_get(sdi, &tmp)) == SR_OK) - *data = g_variant_new_boolean(tmp == SR_MQFLAG_MAX); - break; - case SR_CONF_HOLD_MIN: - if ((ret = cem_dt_885x_holdmode_get(sdi, &tmp)) == SR_OK) - *data = g_variant_new_boolean(tmp == SR_MQFLAG_MIN); - break; - case SR_CONF_SPL_MEASUREMENT_RANGE: - if ((ret = cem_dt_885x_meas_range_get(sdi, &low, &high)) == SR_OK) { - range[0] = g_variant_new_uint64(low); - range[1] = g_variant_new_uint64(high); - *data = g_variant_new_tuple(range, 2); - } - break; - case SR_CONF_POWER_OFF: - *data = g_variant_new_boolean(FALSE); - break; - case SR_CONF_DATA_SOURCE: - if (devc->cur_data_source == DATA_SOURCE_LIVE) - *data = g_variant_new_string("Live"); - else - *data = g_variant_new_string("Memory"); - break; - default: - return SR_ERR_NA; - } - - return ret; -} - -static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc; - uint64_t tmp_u64, low, high; - unsigned int i; - int tmp, ret; - const char *tmp_str; - - (void)cg; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - if (!(devc = sdi->priv)) { - sr_err("sdi->priv was NULL."); - return SR_ERR_BUG; - } - - ret = SR_OK; - switch (key) { - case SR_CONF_LIMIT_SAMPLES: - tmp_u64 = g_variant_get_uint64(data); - devc->limit_samples = tmp_u64; - ret = SR_OK; - break; - case SR_CONF_DATALOG: - ret = cem_dt_885x_recording_set(sdi, g_variant_get_boolean(data)); - break; - case SR_CONF_SPL_WEIGHT_FREQ: - tmp_str = g_variant_get_string(data, NULL); - if (!strcmp(tmp_str, "A")) - ret = cem_dt_885x_weight_freq_set(sdi, - SR_MQFLAG_SPL_FREQ_WEIGHT_A); - else if (!strcmp(tmp_str, "C")) - ret = cem_dt_885x_weight_freq_set(sdi, - SR_MQFLAG_SPL_FREQ_WEIGHT_C); - else - return SR_ERR_ARG; - break; - case SR_CONF_SPL_WEIGHT_TIME: - tmp_str = g_variant_get_string(data, NULL); - if (!strcmp(tmp_str, "F")) - ret = cem_dt_885x_weight_time_set(sdi, - SR_MQFLAG_SPL_TIME_WEIGHT_F); - else if (!strcmp(tmp_str, "S")) - ret = cem_dt_885x_weight_time_set(sdi, - SR_MQFLAG_SPL_TIME_WEIGHT_S); - else - return SR_ERR_ARG; - break; - case SR_CONF_HOLD_MAX: - tmp = g_variant_get_boolean(data) ? SR_MQFLAG_MAX : 0; - ret = cem_dt_885x_holdmode_set(sdi, tmp); - break; - case SR_CONF_HOLD_MIN: - tmp = g_variant_get_boolean(data) ? SR_MQFLAG_MIN : 0; - ret = cem_dt_885x_holdmode_set(sdi, tmp); - break; - case SR_CONF_SPL_MEASUREMENT_RANGE: - g_variant_get(data, "(tt)", &low, &high); - ret = SR_ERR_ARG; - for (i = 0; i < ARRAY_SIZE(meas_ranges); i++) { - if (meas_ranges[i][0] == low && meas_ranges[i][1] == high) { - ret = cem_dt_885x_meas_range_set(sdi, low, high); - break; - } - } - break; - case SR_CONF_POWER_OFF: - if (g_variant_get_boolean(data)) - ret = cem_dt_885x_power_off(sdi); - break; - case SR_CONF_DATA_SOURCE: - tmp_str = g_variant_get_string(data, NULL); - if (!strcmp(tmp_str, "Live")) - devc->cur_data_source = DATA_SOURCE_LIVE; - else if (!strcmp(tmp_str, "Memory")) - devc->cur_data_source = DATA_SOURCE_MEMORY; - else - return SR_ERR; - devc->enable_data_source_memory = devc->cur_data_source == DATA_SOURCE_MEMORY; - break; - default: - ret = SR_ERR_NA; - } - - return ret; -} - -static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - GVariant *tuple, *range[2]; - GVariantBuilder gvb; - unsigned int i; - int ret; - - (void)sdi; - (void)cg; - - ret = SR_OK; - switch (key) { - case SR_CONF_SCAN_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t)); - break; - case SR_CONF_DEVICE_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t)); - break; - case SR_CONF_SPL_WEIGHT_FREQ: - *data = g_variant_new_strv(weight_freq, ARRAY_SIZE(weight_freq)); - break; - case SR_CONF_SPL_WEIGHT_TIME: - *data = g_variant_new_strv(weight_time, ARRAY_SIZE(weight_time)); - break; - case SR_CONF_SPL_MEASUREMENT_RANGE: - g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY); - for (i = 0; i < ARRAY_SIZE(meas_ranges); i++) { - range[0] = g_variant_new_uint64(meas_ranges[i][0]); - range[1] = g_variant_new_uint64(meas_ranges[i][1]); - tuple = g_variant_new_tuple(range, 2); - g_variant_builder_add_value(&gvb, tuple); - } - *data = g_variant_builder_end(&gvb); - break; - case SR_CONF_DATA_SOURCE: - *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources)); - break; - default: - return SR_ERR_NA; - } - - return ret; -} - -static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) -{ - struct dev_context *devc; - struct sr_serial_dev_inst *serial; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - if (!(devc = sdi->priv)) { - sr_err("sdi->priv was NULL."); - return SR_ERR_BUG; - } - - devc->cb_data = cb_data; - devc->state = ST_INIT; - devc->num_samples = 0; - devc->buf_len = 0; - - /* Send header packet to the session bus. */ - std_session_send_df_header(cb_data, LOG_PREFIX); - - /* Poll every 100ms, or whenever some data comes in. */ - serial = sdi->conn; - serial_source_add(sdi->session, serial, G_IO_IN, 150, - cem_dt_885x_receive_data, (void *)sdi); - - return SR_OK; -} - -static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) -{ - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - return std_serial_dev_acquisition_stop(sdi, cb_data, std_serial_dev_close, - sdi->conn, LOG_PREFIX); -} - -SR_PRIV struct sr_dev_driver cem_dt_885x_driver_info = { - .name = "cem-dt-885x", - .longname = "CEM DT-885x", - .api_version = 1, - .init = init, - .cleanup = cleanup, - .scan = scan, - .dev_list = dev_list, - .dev_clear = NULL, - .config_get = config_get, - .config_set = config_set, - .config_list = config_list, - .dev_open = dev_open, - .dev_close = std_serial_dev_close, - .dev_acquisition_start = dev_acquisition_start, - .dev_acquisition_stop = dev_acquisition_stop, - .priv = NULL, -}; diff --git a/hardware/cem-dt-885x/protocol.c b/hardware/cem-dt-885x/protocol.c deleted file mode 100644 index 19e08306..00000000 --- a/hardware/cem-dt-885x/protocol.c +++ /dev/null @@ -1,838 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2013 Bert Vermeulen - * - * 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 . - */ - -#include -#include "protocol.h" - -/* Length of expected payload for each token. */ -static int token_payloads[][2] = { - { TOKEN_WEIGHT_TIME_FAST, 0 }, - { TOKEN_WEIGHT_TIME_SLOW, 0 }, - { TOKEN_HOLD_MAX, 0 }, - { TOKEN_HOLD_MIN, 0 }, - { TOKEN_TIME, 3 }, - { TOKEN_MEAS_RANGE_OVER, 0 }, - { TOKEN_MEAS_RANGE_UNDER, 0 }, - { TOKEN_STORE_FULL, 0 }, - { TOKEN_RECORDING_ON, 0 }, - { TOKEN_MEAS_WAS_READOUT, 1 }, - { TOKEN_MEAS_WAS_BARGRAPH, 0 }, - { TOKEN_MEASUREMENT, 2 }, - { TOKEN_HOLD_NONE, 0 }, - { TOKEN_BATTERY_LOW, 0 }, - { TOKEN_MEAS_RANGE_OK, 0 }, - { TOKEN_STORE_OK, 0 }, - { TOKEN_RECORDING_OFF, 0 }, - { TOKEN_WEIGHT_FREQ_A, 1 }, - { TOKEN_WEIGHT_FREQ_C, 1 }, - { TOKEN_BATTERY_OK, 0 }, - { TOKEN_MEAS_RANGE_30_80, 0 }, - { TOKEN_MEAS_RANGE_30_130, 0 }, - { TOKEN_MEAS_RANGE_50_100, 0 }, - { TOKEN_MEAS_RANGE_80_130, 0 }, -}; - -static int find_token_payload_len(unsigned char c) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(token_payloads); i++) { - if (token_payloads[i][0] == c) - return token_payloads[i][1]; - } - - return -1; -} - -/* Process measurement or setting (0xa5 command). */ -static void process_mset(const struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - struct sr_datafeed_packet packet; - struct sr_datafeed_analog analog; - GString *dbg; - float fvalue; - int i; - - devc = sdi->priv; - if (sr_log_loglevel_get() >= SR_LOG_SPEW) { - dbg = g_string_sized_new(128); - g_string_printf(dbg, "got command 0x%.2x token 0x%.2x", - devc->cmd, devc->token); - if (devc->buf_len) { - g_string_append_printf(dbg, " payload"); - for (i = 0; i < devc->buf_len; i++) - g_string_append_printf(dbg, " %.2x", devc->buf[i]); - } - sr_spew("%s", dbg->str); - g_string_free(dbg, TRUE); - } - - switch(devc->token) { - case TOKEN_WEIGHT_TIME_FAST: - devc->cur_mqflags |= SR_MQFLAG_SPL_TIME_WEIGHT_F; - devc->cur_mqflags &= ~SR_MQFLAG_SPL_TIME_WEIGHT_S; - break; - case TOKEN_WEIGHT_TIME_SLOW: - devc->cur_mqflags |= SR_MQFLAG_SPL_TIME_WEIGHT_S; - devc->cur_mqflags &= ~SR_MQFLAG_SPL_TIME_WEIGHT_F; - break; - case TOKEN_WEIGHT_FREQ_A: - devc->cur_mqflags |= SR_MQFLAG_SPL_FREQ_WEIGHT_A; - devc->cur_mqflags &= ~SR_MQFLAG_SPL_FREQ_WEIGHT_C; - break; - case TOKEN_WEIGHT_FREQ_C: - devc->cur_mqflags |= SR_MQFLAG_SPL_FREQ_WEIGHT_C; - devc->cur_mqflags &= ~SR_MQFLAG_SPL_FREQ_WEIGHT_A; - break; - case TOKEN_HOLD_MAX: - devc->cur_mqflags |= SR_MQFLAG_HOLD | SR_MQFLAG_MAX; - devc->cur_mqflags &= ~SR_MQFLAG_MIN; - break; - case TOKEN_HOLD_MIN: - devc->cur_mqflags |= SR_MQFLAG_HOLD | SR_MQFLAG_MIN; - devc->cur_mqflags &= ~SR_MQFLAG_MAX; - break; - case TOKEN_HOLD_NONE: - devc->cur_mqflags &= ~(SR_MQFLAG_MAX | SR_MQFLAG_MIN | SR_MQFLAG_HOLD); - break; - case TOKEN_MEASUREMENT: - fvalue = ((devc->buf[0] & 0xf0) >> 4) * 100; - fvalue += (devc->buf[0] & 0x0f) * 10; - fvalue += ((devc->buf[1] & 0xf0) >> 4); - fvalue += (devc->buf[1] & 0x0f) / 10.0; - devc->last_spl = fvalue; - break; - case TOKEN_MEAS_WAS_READOUT: - case TOKEN_MEAS_WAS_BARGRAPH: - if (devc->cur_mqflags & (SR_MQFLAG_MAX | SR_MQFLAG_MIN)) { - if (devc->token == TOKEN_MEAS_WAS_BARGRAPH) { - /* The device still sends bargraph measurements even - * when in max/min hold mode. Suppress them here, unless - * they're readout values. This duplicates the behavior - * of the device display exactly. */ - break; - } - } - memset(&analog, 0, sizeof(struct sr_datafeed_analog)); - analog.mq = SR_MQ_SOUND_PRESSURE_LEVEL; - analog.mqflags = devc->cur_mqflags; - analog.unit = SR_UNIT_DECIBEL_SPL; - analog.channels = sdi->channels; - analog.num_samples = 1; - analog.data = &devc->last_spl; - packet.type = SR_DF_ANALOG; - packet.payload = &analog; - sr_session_send(devc->cb_data, &packet); - - devc->num_samples++; - if (devc->limit_samples && devc->num_samples >= devc->limit_samples) - sdi->driver->dev_acquisition_stop((struct sr_dev_inst *)sdi, - devc->cb_data); - break; - case TOKEN_RECORDING_ON: - devc->recording = TRUE; - break; - case TOKEN_RECORDING_OFF: - devc->recording = FALSE; - break; - case TOKEN_MEAS_RANGE_30_80: - case TOKEN_MEAS_RANGE_30_130: - case TOKEN_MEAS_RANGE_50_100: - case TOKEN_MEAS_RANGE_80_130: - devc->cur_meas_range = devc->token; - break; - case TOKEN_TIME: - case TOKEN_STORE_OK: - case TOKEN_STORE_FULL: - case TOKEN_BATTERY_OK: - case TOKEN_BATTERY_LOW: - case TOKEN_MEAS_RANGE_OK: - case TOKEN_MEAS_RANGE_OVER: - case TOKEN_MEAS_RANGE_UNDER: - /* Not useful, or not expressable in sigrok. */ - break; - } - -} - -static void send_data(const struct sr_dev_inst *sdi, unsigned char *data, - uint64_t num_samples) -{ - struct dev_context *devc; - struct sr_datafeed_packet packet; - struct sr_datafeed_analog analog; - float fbuf[SAMPLES_PER_PACKET]; - unsigned int i; - - devc = sdi->priv; - - for (i = 0; i < num_samples; i ++) { - fbuf[i] = ((data[i * 2] & 0xf0) >> 4) * 100; - fbuf[i] += (data[i * 2] & 0x0f) * 10; - fbuf[i] += ((data[i * 2 + 1] & 0xf0) >> 4); - fbuf[i] += (data[i * 2 + 1] & 0x0f) / 10.0; - } - memset(&analog, 0, sizeof(struct sr_datafeed_analog)); - analog.mq = SR_MQ_SOUND_PRESSURE_LEVEL; - analog.mqflags = devc->cur_mqflags; - analog.unit = SR_UNIT_DECIBEL_SPL; - analog.channels = sdi->channels; - analog.num_samples = num_samples; - analog.data = fbuf; - packet.type = SR_DF_ANALOG; - packet.payload = &analog; - sr_session_send(devc->cb_data, &packet); - - devc->num_samples += analog.num_samples; - if (devc->limit_samples && devc->num_samples >= devc->limit_samples) - sdi->driver->dev_acquisition_stop((struct sr_dev_inst *)sdi, - devc->cb_data); - - return; -} - -static void process_byte(const struct sr_dev_inst *sdi, const unsigned char c, - int handle_packets) -{ - struct dev_context *devc; - struct sr_datafeed_packet packet; - struct sr_datafeed_meta meta; - struct sr_config *src; - gint64 cur_time; - int len; - - if (!(devc = sdi->priv)) - return; - - if (c == 0xff) { - /* Device is in hold mode */ - devc->cur_mqflags |= SR_MQFLAG_HOLD; - - if (devc->hold_last_sent == 0) { - /* First hold notification. */ - devc->hold_last_sent = g_get_monotonic_time(); - /* When the device leaves hold mode, it starts from scratch. */ - devc->state = ST_INIT; - } else { - cur_time = g_get_monotonic_time(); - if (cur_time - devc->hold_last_sent > HOLD_REPEAT_INTERVAL) { - /* Force the last measurement out again. */ - devc->cmd = 0xa5; - devc->token = TOKEN_MEAS_WAS_READOUT; - if (handle_packets) - process_mset(sdi); - devc->hold_last_sent = cur_time; - } - } - - return; - } - devc->cur_mqflags &= ~SR_MQFLAG_HOLD; - devc->hold_last_sent = 0; - - if (devc->state == ST_INIT) { - if (c == 0xa5) { - devc->cmd = c; - devc->token = 0x00; - devc->state = ST_GET_TOKEN; - } else if (c == 0xbb) { - devc->cmd = c; - devc->buf_len = 0; - devc->state = ST_GET_LOG_HEADER; - sr_dbg("got command 0xbb"); - } - } else if (devc->state == ST_GET_TOKEN) { - devc->token = c; - devc->buf_len = 0; - len = find_token_payload_len(devc->token); - if (len == -1 || len > 0) { - devc->buf_len = 0; - devc->state = ST_GET_DATA; - } else { - if (handle_packets) - process_mset(sdi); - devc->state = ST_INIT; - } - } else if (devc->state == ST_GET_DATA) { - len = find_token_payload_len(devc->token); - if (len == -1) { - /* We don't know this token. */ - sr_dbg("Unknown 0xa5 token 0x%.2x", devc->token); - if (c == 0xa5 || c == 0xbb) { - /* Looks like a new command however. */ - if (handle_packets) - process_mset(sdi); - devc->state = ST_INIT; - } else { - devc->buf[devc->buf_len++] = c; - if (devc->buf_len > BUF_SIZE) { - /* Shouldn't happen, ignore. */ - devc->state = ST_INIT; - } - } - } else { - devc->buf[devc->buf_len++] = c; - if (devc->buf_len == len) { - if (handle_packets) - process_mset(sdi); - devc->state = ST_INIT; - } else if (devc->buf_len > BUF_SIZE) { - /* Shouldn't happen, ignore. */ - devc->state = ST_INIT; - } - } - } else if (devc->state == ST_GET_LOG_HEADER) { - sr_dbg("log header: 0x%.2x", c); - if (devc->buf_len < 2) - devc->buf[devc->buf_len++] = c; - if (devc->buf_len == 2) { - sr_dbg("Device says it has %d bytes stored.", - ((devc->buf[0] << 8) + devc->buf[1]) - 100); - devc->buf_len = 0; - devc->state = ST_GET_LOG_RECORD_META; - } - } else if (devc->state == ST_GET_LOG_RECORD_META) { - sr_dbg("log meta: 0x%.2x", c); - if (c == RECORD_END) { - devc->state = ST_INIT; - /* Stop acquisition after transferring all stored - * records. Otherwise the frontend would have no - * way to tell where stored data ends and live - * measurements begin. */ - sdi->driver->dev_acquisition_stop((struct sr_dev_inst *)sdi, - devc->cb_data); - } else if (c == RECORD_DATA) { - devc->buf_len = 0; - devc->state = ST_GET_LOG_RECORD_DATA; - } else { - /* RECORD_DBA/RECORD_DBC + 7 bytes of metadata */ - devc->buf[devc->buf_len++] = c; - if (devc->buf_len < 8) - /* Keep filling up the record header. */ - return; - if (devc->buf[0] == RECORD_DBA) - devc->cur_mqflags = SR_MQFLAG_SPL_FREQ_WEIGHT_A; - else if (devc->buf[0] == RECORD_DBC) - devc->cur_mqflags = SR_MQFLAG_SPL_FREQ_WEIGHT_C; - else { - /* Shouldn't happen. */ - sr_dbg("Unknown record token 0x%.2x", c); - return; - } - packet.type = SR_DF_META; - packet.payload = &meta; - src = sr_config_new(SR_CONF_SAMPLE_INTERVAL, - g_variant_new_uint64(devc->buf[7] * 1000)); - meta.config = g_slist_append(NULL, src); - sr_session_send(devc->cb_data, &packet); - g_free(src); - devc->buf_len = 0; - } - } else if (devc->state == ST_GET_LOG_RECORD_DATA) { - sr_dbg("log data: 0x%.2x", c); - if (c == RECORD_DBA || c == RECORD_DBC || c == RECORD_DATA || c == RECORD_END) { - /* Work around off-by-one bug in device firmware. This - * happens only on the last record, i.e. before RECORD_END */ - if (devc->buf_len & 1) - devc->buf_len--; - /* Done with this set of samples */ - send_data(sdi, devc->buf, devc->buf_len / 2); - devc->buf_len = 0; - - /* Process this meta marker in the right state. */ - devc->state = ST_GET_LOG_RECORD_META; - process_byte(sdi, c, handle_packets); - } else { - devc->buf[devc->buf_len++] = c; - if (devc->buf_len == SAMPLES_PER_PACKET * 2) { - send_data(sdi, devc->buf, devc->buf_len / 2); - devc->buf_len = 0; - } - } - } - -} - -SR_PRIV int cem_dt_885x_receive_data(int fd, int revents, void *cb_data) -{ - const struct sr_dev_inst *sdi; - struct dev_context *devc; - struct sr_serial_dev_inst *serial; - unsigned char c, cmd; - - (void)fd; - - if (!(sdi = cb_data)) - return TRUE; - - devc = sdi->priv; - serial = sdi->conn; - if (revents == G_IO_IN) { - if (serial_read(serial, &c, 1) != 1) - return TRUE; - process_byte(sdi, c, TRUE); - - if (devc->enable_data_source_memory) { - if (devc->state == ST_GET_LOG_HEADER) { - /* Memory transfer started. */ - devc->enable_data_source_memory = FALSE; - } else { - /* Tell device to start transferring from memory. */ - cmd = CMD_TRANSFER_MEMORY; - serial_write(serial, &cmd, 1); - } - } - } - - return TRUE; -} - - -static int wait_for_token(const struct sr_dev_inst *sdi, int8_t *tokens, int timeout) -{ - struct dev_context *devc; - struct sr_serial_dev_inst *serial; - gint64 start_time; - int i; - unsigned char c; - - serial = sdi->conn; - devc = sdi->priv; - devc->state = ST_INIT; - start_time = g_get_monotonic_time() / 1000; - while (TRUE) { - if (serial_read(serial, &c, 1) != 1) - /* Device might have gone away. */ - return SR_ERR; - process_byte(sdi, c, FALSE); - if (devc->state != ST_INIT) - /* Wait for a whole packet to get processed. */ - continue; - for (i = 0; tokens[i] != -1; i++) { - if (devc->token == tokens[i]) { - sr_spew("wait_for_token: got token 0x%.2x", devc->token); - return SR_OK; - } - } - if (timeout && g_get_monotonic_time() / 1000 - start_time > timeout) - return SR_ERR_TIMEOUT; - } - - return SR_OK; -} - -/* cmd is the command to send, tokens are the tokens that denote the state - * which the command affects. The first token is the desired state. */ -static int cem_dt_885x_toggle(const struct sr_dev_inst *sdi, uint8_t cmd, - int8_t *tokens, int timeout) -{ - struct dev_context *devc; - struct sr_serial_dev_inst *serial; - - serial = sdi->conn; - devc = sdi->priv; - - /* The device doesn't respond to commands very well. The - * only thing to do is wait for the token that will confirm - * whether the command worked or not, and resend if needed. */ - while (TRUE) { - if (serial_write(serial, (const void *)&cmd, 1) != 1) - return SR_ERR; - if (wait_for_token(sdi, tokens, timeout) == SR_ERR) - return SR_ERR; - if (devc->token == tokens[0]) - /* It worked. */ - break; - } - - return SR_OK; -} - -SR_PRIV gboolean cem_dt_885x_recording_get(const struct sr_dev_inst *sdi, - int *state) -{ - struct dev_context *devc; - int8_t tokens[5]; - - devc = sdi->priv; - if (devc->recording == -1) { - /* Didn't pick up device state yet. */ - tokens[0] = TOKEN_RECORDING_ON; - tokens[1] = TOKEN_RECORDING_OFF; - tokens[2] = -1; - if (wait_for_token(sdi, tokens, 510) != SR_OK) - return SR_ERR; - } - *state = devc->token == TOKEN_RECORDING_ON; - - return SR_OK; -} - -SR_PRIV int cem_dt_885x_recording_set(const struct sr_dev_inst *sdi, - gboolean state) -{ - struct dev_context *devc; - int ret; - int8_t tokens[5]; - - devc = sdi->priv; - - /* The toggle below needs the desired state in first position. */ - if (state) { - tokens[0] = TOKEN_RECORDING_ON; - tokens[1] = TOKEN_RECORDING_OFF; - } else { - tokens[0] = TOKEN_RECORDING_OFF; - tokens[1] = TOKEN_RECORDING_ON; - } - tokens[2] = -1; - - if (devc->recording == -1) { - /* Didn't pick up device state yet. */ - if (wait_for_token(sdi, tokens, 0) != SR_OK) - return SR_ERR; - if (devc->token == tokens[0]) - /* Nothing to do. */ - return SR_OK; - } else if (devc->recording == state) - /* Nothing to do. */ - return SR_OK; - - /* Recording state notifications are sent at 2Hz, so allow just over - * that, 510ms, for the state to come in. */ - ret = cem_dt_885x_toggle(sdi, CMD_TOGGLE_RECORDING, tokens, 510); - - return ret; -} - -SR_PRIV int cem_dt_885x_weight_freq_get(const struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - int cur_setting; - int8_t tokens[5]; - - devc = sdi->priv; - - cur_setting = devc->cur_mqflags & (SR_MQFLAG_SPL_FREQ_WEIGHT_A | SR_MQFLAG_SPL_FREQ_WEIGHT_C); - if (cur_setting == 0) { - /* Didn't pick up device state yet. */ - tokens[0] = TOKEN_WEIGHT_FREQ_A; - tokens[1] = TOKEN_WEIGHT_FREQ_C; - tokens[2] = -1; - if (wait_for_token(sdi, tokens, 0) != SR_OK) - return SR_ERR; - if (devc->token == TOKEN_WEIGHT_FREQ_A) - return SR_MQFLAG_SPL_FREQ_WEIGHT_A; - else - return SR_MQFLAG_SPL_FREQ_WEIGHT_C; - } else - return cur_setting; -} - -SR_PRIV int cem_dt_885x_weight_freq_set(const struct sr_dev_inst *sdi, int freqw) -{ - struct dev_context *devc; - int cur_setting, ret; - int8_t tokens[5]; - - devc = sdi->priv; - - cur_setting = devc->cur_mqflags & (SR_MQFLAG_SPL_FREQ_WEIGHT_A | SR_MQFLAG_SPL_FREQ_WEIGHT_C); - if (cur_setting == freqw) - /* Already set to this frequency weighting. */ - return SR_OK; - - /* The toggle below needs the desired state in first position. */ - if (freqw == SR_MQFLAG_SPL_FREQ_WEIGHT_A) { - tokens[0] = TOKEN_WEIGHT_FREQ_A; - tokens[1] = TOKEN_WEIGHT_FREQ_C; - } else { - tokens[0] = TOKEN_WEIGHT_FREQ_C; - tokens[1] = TOKEN_WEIGHT_FREQ_A; - } - tokens[2] = -1; - - if (cur_setting == 0) { - /* Didn't pick up device state yet. */ - if (wait_for_token(sdi, tokens, 0) != SR_OK) - return SR_ERR; - if (devc->token == tokens[0]) - /* Nothing to do. */ - return SR_OK; - } - - /* 10ms timeout seems to work best for this. */ - ret = cem_dt_885x_toggle(sdi, CMD_TOGGLE_WEIGHT_FREQ, tokens, 10); - - return ret; -} - -SR_PRIV int cem_dt_885x_weight_time_get(const struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - int cur_setting; - int8_t tokens[5]; - - devc = sdi->priv; - - cur_setting = devc->cur_mqflags & (SR_MQFLAG_SPL_TIME_WEIGHT_F | SR_MQFLAG_SPL_TIME_WEIGHT_S); - if (cur_setting == 0) { - /* Didn't pick up device state yet. */ - tokens[0] = TOKEN_WEIGHT_TIME_FAST; - tokens[1] = TOKEN_WEIGHT_TIME_SLOW; - tokens[2] = -1; - if (wait_for_token(sdi, tokens, 0) != SR_OK) - return SR_ERR; - if (devc->token == TOKEN_WEIGHT_TIME_FAST) - return SR_MQFLAG_SPL_TIME_WEIGHT_F; - else - return SR_MQFLAG_SPL_TIME_WEIGHT_S; - } else - return cur_setting; -} - -SR_PRIV int cem_dt_885x_weight_time_set(const struct sr_dev_inst *sdi, int timew) -{ - struct dev_context *devc; - int cur_setting, ret; - int8_t tokens[5]; - - devc = sdi->priv; - - cur_setting = devc->cur_mqflags & (SR_MQFLAG_SPL_TIME_WEIGHT_F | SR_MQFLAG_SPL_TIME_WEIGHT_S); - if (cur_setting == timew) - /* Already set to this time weighting. */ - return SR_OK; - - /* The toggle below needs the desired state in first position. */ - if (timew == SR_MQFLAG_SPL_TIME_WEIGHT_F) { - tokens[0] = TOKEN_WEIGHT_TIME_FAST; - tokens[1] = TOKEN_WEIGHT_TIME_SLOW; - } else { - tokens[0] = TOKEN_WEIGHT_TIME_SLOW; - tokens[1] = TOKEN_WEIGHT_TIME_FAST; - } - tokens[2] = -1; - - if (cur_setting == 0) { - /* Didn't pick up device state yet. */ - if (wait_for_token(sdi, tokens, 0) != SR_OK) - return SR_ERR; - if (devc->token == tokens[0]) - /* Nothing to do. */ - return SR_OK; - } - - /* 51ms timeout seems to work best for this. */ - ret = cem_dt_885x_toggle(sdi, CMD_TOGGLE_WEIGHT_TIME, tokens, 51); - - return ret; -} - -SR_PRIV int cem_dt_885x_holdmode_get(const struct sr_dev_inst *sdi, - gboolean *holdmode) -{ - struct dev_context *devc; - int8_t tokens[5]; - - devc = sdi->priv; - - if (devc->cur_mqflags == 0) { - tokens[0] = TOKEN_HOLD_MAX; - tokens[1] = TOKEN_HOLD_MIN; - tokens[2] = TOKEN_HOLD_NONE; - tokens[3] = -1; - if (wait_for_token(sdi, tokens, 0) != SR_OK) - return SR_ERR; - if (devc->token == TOKEN_HOLD_MAX) - devc->cur_mqflags = SR_MQFLAG_MAX; - else if (devc->token == TOKEN_HOLD_MIN) - devc->cur_mqflags = SR_MQFLAG_MIN; - } - *holdmode = devc->cur_mqflags & (SR_MQFLAG_MAX | SR_MQFLAG_MIN); - - return SR_OK; -} - -SR_PRIV int cem_dt_885x_holdmode_set(const struct sr_dev_inst *sdi, int holdmode) -{ - struct dev_context *devc; - int cur_setting, ret; - int8_t tokens[5]; - - devc = sdi->priv; - - /* The toggle below needs the desired state in first position. */ - if (holdmode == SR_MQFLAG_MAX) { - tokens[0] = TOKEN_HOLD_MAX; - tokens[1] = TOKEN_HOLD_MIN; - tokens[2] = TOKEN_HOLD_NONE; - } else if (holdmode == SR_MQFLAG_MIN) { - tokens[0] = TOKEN_HOLD_MIN; - tokens[1] = TOKEN_HOLD_MAX; - tokens[2] = TOKEN_HOLD_NONE; - } else { - tokens[0] = TOKEN_HOLD_NONE; - tokens[1] = TOKEN_HOLD_MAX; - tokens[2] = TOKEN_HOLD_MIN; - } - tokens[3] = -1; - - if (devc->cur_mqflags == 0) { - /* Didn't pick up device state yet. */ - if (wait_for_token(sdi, tokens, 0) != SR_OK) - return SR_ERR; - if (devc->token == tokens[0]) - /* Nothing to do. */ - return SR_OK; - } else { - cur_setting = devc->cur_mqflags & (SR_MQFLAG_MAX | SR_MQFLAG_MIN); - if (cur_setting == holdmode) - /* Already set correctly. */ - return SR_OK; - } - - /* 51ms timeout seems to work best for this. */ - ret = cem_dt_885x_toggle(sdi, CMD_TOGGLE_HOLD_MAX_MIN, tokens, 51); - - return ret; -} - -SR_PRIV int cem_dt_885x_meas_range_get(const struct sr_dev_inst *sdi, - uint64_t *low, uint64_t *high) -{ - struct dev_context *devc; - int8_t tokens[5]; - - devc = sdi->priv; - if (devc->cur_meas_range == 0) { - tokens[0] = TOKEN_MEAS_RANGE_30_130; - tokens[1] = TOKEN_MEAS_RANGE_30_80; - tokens[2] = TOKEN_MEAS_RANGE_50_100; - tokens[3] = TOKEN_MEAS_RANGE_80_130; - tokens[4] = -1; - if (wait_for_token(sdi, tokens, 0) != SR_OK) - return SR_ERR; - devc->cur_meas_range = devc->token; - } - - switch (devc->cur_meas_range) { - case TOKEN_MEAS_RANGE_30_130: - *low = 30; - *high = 130; - break; - case TOKEN_MEAS_RANGE_30_80: - *low = 30; - *high = 80; - break; - case TOKEN_MEAS_RANGE_50_100: - *low = 50; - *high = 100; - break; - case TOKEN_MEAS_RANGE_80_130: - *low = 80; - *high = 130; - break; - default: - return SR_ERR; - } - - return SR_OK; -} - -SR_PRIV int cem_dt_885x_meas_range_set(const struct sr_dev_inst *sdi, - uint64_t low, uint64_t high) -{ - struct dev_context *devc; - int ret; - int8_t token, tokens[6]; - - devc = sdi->priv; - if (low == 30 && high == 130) - token = TOKEN_MEAS_RANGE_30_130; - else if (low == 30 && high == 80) - token = TOKEN_MEAS_RANGE_30_80; - else if (low == 50 && high == 100) - token = TOKEN_MEAS_RANGE_50_100; - else if (low == 80 && high == 130) - token = TOKEN_MEAS_RANGE_80_130; - else - return SR_ERR; - - sr_dbg("want 0x%.2x", token); - /* The toggle below needs the desired state in first position. */ - tokens[0] = token; - tokens[1] = TOKEN_MEAS_RANGE_30_130; - tokens[2] = TOKEN_MEAS_RANGE_30_80; - tokens[3] = TOKEN_MEAS_RANGE_50_100; - tokens[4] = TOKEN_MEAS_RANGE_80_130; - tokens[5] = -1; - - if (devc->cur_meas_range == 0) { - /* 110ms should be enough for two of these announcements */ - if (wait_for_token(sdi, tokens, 110) != SR_OK) - return SR_ERR; - devc->cur_meas_range = devc->token; - } - - if (devc->cur_meas_range == token) - /* Already set to this range. */ - return SR_OK; - - /* For measurement range, it works best to ignore announcements of the - * current setting and keep resending the toggle quickly. */ - tokens[1] = -1; - ret = cem_dt_885x_toggle(sdi, CMD_TOGGLE_MEAS_RANGE, tokens, 11); - - return ret; -} - -SR_PRIV int cem_dt_885x_power_off(const struct sr_dev_inst *sdi) -{ - struct sr_serial_dev_inst *serial; - char c, cmd; - - serial = sdi->conn; - - /* Reopen the port in non-blocking mode, so we can properly - * detect when the device stops communicating. */ - serial_close(serial); - if (serial_open(serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK) - return SR_ERR; - - cmd = CMD_TOGGLE_POWER_OFF; - while (TRUE) { - serial_flush(serial); - if (serial_write(serial, (const void *)&cmd, 1) != 1) - return SR_ERR; - /* It never takes more than 23ms for the next token to arrive. */ - g_usleep(25 * 1000); - if (serial_read(serial, &c, 1) != 1) - /* Device is no longer responding. Good! */ - break; - } - - /* In case the user manually turns on the device again, reset - * the port back to blocking. */ - serial_close(serial); - serial_open(serial, SERIAL_RDWR); - - return SR_OK; -} diff --git a/hardware/cem-dt-885x/protocol.h b/hardware/cem-dt-885x/protocol.h deleted file mode 100644 index 233ef860..00000000 --- a/hardware/cem-dt-885x/protocol.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2013 Bert Vermeulen - * - * 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 . - */ - -#ifndef LIBSIGROK_HARDWARE_CEM_DT_885X_PROTOCOL_H -#define LIBSIGROK_HARDWARE_CEM_DT_885X_PROTOCOL_H - -#include -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#define LOG_PREFIX "cem-dt-885x" - -/* When retrieving samples from device memory, group this many - * together into a sigrok packet. */ -#define SAMPLES_PER_PACKET 50 - -/* Various temporary storage, at least 8 bytes. */ -#define BUF_SIZE SAMPLES_PER_PACKET * 2 - -/* When in hold mode, force the last measurement out at this interval. - * We're using 50ms, which duplicates the non-hold 20Hz update rate. */ -#define HOLD_REPEAT_INTERVAL 50 * 1000 - -enum { - TOKEN_WEIGHT_TIME_FAST = 0x02, - TOKEN_WEIGHT_TIME_SLOW = 0x03, - TOKEN_HOLD_MAX = 0x04, - TOKEN_HOLD_MIN = 0x05, - TOKEN_TIME = 0x06, - TOKEN_MEAS_RANGE_OVER = 0x07, - TOKEN_MEAS_RANGE_UNDER = 0x08, - TOKEN_STORE_FULL = 0x09, - TOKEN_RECORDING_ON = 0x0a, - TOKEN_MEAS_WAS_READOUT = 0x0b, - TOKEN_MEAS_WAS_BARGRAPH = 0x0c, - TOKEN_MEASUREMENT = 0xd, - TOKEN_HOLD_NONE = 0x0e, - TOKEN_BATTERY_LOW = 0x0f, - TOKEN_MEAS_RANGE_OK = 0x11, - TOKEN_STORE_OK = 0x19, - TOKEN_RECORDING_OFF = 0x1a, - TOKEN_WEIGHT_FREQ_A = 0x1b, - TOKEN_WEIGHT_FREQ_C = 0x1c, - TOKEN_BATTERY_OK = 0x1f, - TOKEN_MEAS_RANGE_30_80 = 0x30, - TOKEN_MEAS_RANGE_30_130 = 0x40, - TOKEN_MEAS_RANGE_50_100 = 0x4b, - TOKEN_MEAS_RANGE_80_130 = 0x4c, -}; - -enum { - CMD_TOGGLE_RECORDING = 0x55, - CMD_TOGGLE_WEIGHT_FREQ = 0x99, - CMD_TOGGLE_WEIGHT_TIME = 0x77, - CMD_TOGGLE_HOLD_MAX_MIN = 0x11, - CMD_TOGGLE_MEAS_RANGE = 0x88, - CMD_TOGGLE_POWER_OFF = 0x33, - CMD_TRANSFER_MEMORY = 0xac, -}; - -enum { - RECORD_DBA = 0xaa, - RECORD_DBC = 0xcc, - RECORD_DATA = 0xac, - RECORD_END = 0xdd, -}; - -enum { - DATA_SOURCE_LIVE, - DATA_SOURCE_MEMORY, -}; - -/** Private, per-device-instance driver context. */ -struct dev_context { - /* Device state */ - uint64_t cur_mqflags; - int recording; - int cur_meas_range; - int cur_data_source; - - /* Acquisition settings */ - uint64_t limit_samples; - - /* Operational state */ - int state; - uint64_t num_samples; - gboolean enable_data_source_memory; - - /* Temporary state across callbacks */ - void *cb_data; - unsigned char cmd; - unsigned char token; - int buf_len; - unsigned char buf[BUF_SIZE]; - float last_spl; - gint64 hold_last_sent; -}; - -/* Parser state machine. */ -enum { - ST_INIT, - ST_GET_TOKEN, - ST_GET_DATA, - ST_GET_LOG_HEADER, - ST_GET_LOG_RECORD_META, - ST_GET_LOG_RECORD_DATA, -}; - -SR_PRIV int cem_dt_885x_receive_data(int fd, int revents, void *cb_data); -SR_PRIV int cem_dt_885x_recording_set(const struct sr_dev_inst *sdi, gboolean start); -SR_PRIV gboolean cem_dt_885x_recording_get(const struct sr_dev_inst *sdi, - int *state); -SR_PRIV int cem_dt_885x_weight_freq_get(const struct sr_dev_inst *sdi); -SR_PRIV int cem_dt_885x_weight_freq_set(const struct sr_dev_inst *sdi, int freqw); -SR_PRIV int cem_dt_885x_weight_time_get(const struct sr_dev_inst *sdi); -SR_PRIV int cem_dt_885x_weight_time_set(const struct sr_dev_inst *sdi, int timew); -SR_PRIV int cem_dt_885x_holdmode_get(const struct sr_dev_inst *sdi, - gboolean *holdmode); -SR_PRIV int cem_dt_885x_holdmode_set(const struct sr_dev_inst *sdi, int holdmode); -SR_PRIV int cem_dt_885x_meas_range_get(const struct sr_dev_inst *sdi, - uint64_t *low, uint64_t *high); -SR_PRIV int cem_dt_885x_meas_range_set(const struct sr_dev_inst *sdi, - uint64_t low, uint64_t high); -SR_PRIV int cem_dt_885x_power_off(const struct sr_dev_inst *sdi); - -#endif diff --git a/hardware/center-3xx/api.c b/hardware/center-3xx/api.c deleted file mode 100644 index 3f39b197..00000000 --- a/hardware/center-3xx/api.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2013 Uwe Hermann - * - * 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 "protocol.h" - -static const int32_t hwopts[] = { - SR_CONF_CONN, - SR_CONF_SERIALCOMM, -}; - -static const int32_t hwcaps[] = { - SR_CONF_THERMOMETER, - SR_CONF_LIMIT_SAMPLES, - SR_CONF_LIMIT_MSEC, - SR_CONF_CONTINUOUS, -}; - -static const char *channel_names[] = { - "T1", "T2", "T3", "T4", - NULL, -}; - -SR_PRIV struct sr_dev_driver center_309_driver_info; -SR_PRIV struct sr_dev_driver voltcraft_k204_driver_info; - -SR_PRIV const struct center_dev_info center_devs[] = { - { - "Center", "309", "9600/8n1", 4, 32000, 45, - center_3xx_packet_valid, - ¢er_309_driver_info, receive_data_CENTER_309, - }, - { - "Voltcraft", "K204", "9600/8n1", 4, 32000, 45, - center_3xx_packet_valid, - &voltcraft_k204_driver_info, receive_data_VOLTCRAFT_K204, - }, -}; - -static int dev_clear(int idx) -{ - return std_dev_clear(center_devs[idx].di, NULL); -} - -static int init(struct sr_context *sr_ctx, int idx) -{ - sr_dbg("Selected '%s' subdriver.", center_devs[idx].di->name); - - return std_init(sr_ctx, center_devs[idx].di, LOG_PREFIX); -} - -static GSList *center_scan(const char *conn, const char *serialcomm, int idx) -{ - int i; - struct sr_dev_inst *sdi; - struct drv_context *drvc; - struct dev_context *devc; - struct sr_channel *ch; - struct sr_serial_dev_inst *serial; - GSList *devices; - - if (!(serial = sr_serial_dev_inst_new(conn, serialcomm))) - return NULL; - - if (serial_open(serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK) - return NULL; - - drvc = center_devs[idx].di->priv; - devices = NULL; - serial_flush(serial); - - sr_info("Found device on port %s.", conn); - - if (!(sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, center_devs[idx].vendor, - center_devs[idx].device, NULL))) - goto scan_cleanup; - - if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) { - sr_err("Device context malloc failed."); - goto scan_cleanup; - } - - sdi->inst_type = SR_INST_SERIAL; - sdi->conn = serial; - - sdi->priv = devc; - sdi->driver = center_devs[idx].di; - - for (i = 0; i < center_devs[idx].num_channels; i++) { - if (!(ch = sr_channel_new(i, SR_CHANNEL_ANALOG, - TRUE, channel_names[i]))) - goto scan_cleanup; - sdi->channels = g_slist_append(sdi->channels, ch); - } - - drvc->instances = g_slist_append(drvc->instances, sdi); - devices = g_slist_append(devices, sdi); - -scan_cleanup: - serial_close(serial); - - return devices; -} - -static GSList *scan(GSList *options, int idx) -{ - struct sr_config *src; - GSList *l, *devices; - const char *conn, *serialcomm; - - conn = serialcomm = NULL; - for (l = options; l; l = l->next) { - src = l->data; - switch (src->key) { - case SR_CONF_CONN: - conn = g_variant_get_string(src->data, NULL); - break; - case SR_CONF_SERIALCOMM: - serialcomm = g_variant_get_string(src->data, NULL); - break; - } - } - if (!conn) - return NULL; - - if (serialcomm) { - /* Use the provided comm specs. */ - devices = center_scan(conn, serialcomm, idx); - } else { - /* Try the default. */ - devices = center_scan(conn, center_devs[idx].conn, idx); - } - - return devices; -} - -static GSList *dev_list(int idx) -{ - return ((struct drv_context *)(center_devs[idx].di->priv))->instances; -} - -static int cleanup(int idx) -{ - return dev_clear(idx); -} - -static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc; - - (void)cg; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - devc = sdi->priv; - - switch (id) { - case SR_CONF_LIMIT_SAMPLES: - if (g_variant_get_uint64(data) == 0) - return SR_ERR_ARG; - devc->limit_samples = g_variant_get_uint64(data); - break; - case SR_CONF_LIMIT_MSEC: - if (g_variant_get_uint64(data) == 0) - return SR_ERR_ARG; - devc->limit_msec = g_variant_get_uint64(data); - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - (void)sdi; - (void)cg; - - switch (key) { - case SR_CONF_SCAN_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t)); - break; - case SR_CONF_DEVICE_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t)); - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int dev_acquisition_start(const struct sr_dev_inst *sdi, - void *cb_data, int idx) -{ - struct dev_context *devc; - struct sr_serial_dev_inst *serial; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - devc = sdi->priv; - devc->cb_data = cb_data; - devc->num_samples = 0; - devc->starttime = g_get_monotonic_time(); - - /* Send header packet to the session bus. */ - std_session_send_df_header(cb_data, LOG_PREFIX); - - /* Poll every 500ms, or whenever some data comes in. */ - serial = sdi->conn; - serial_source_add(sdi->session, serial, G_IO_IN, 500, - center_devs[idx].receive_data, (void *)sdi); - - return SR_OK; -} - -static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) -{ - return std_serial_dev_acquisition_stop(sdi, cb_data, - std_serial_dev_close, sdi->conn, LOG_PREFIX); -} - -/* Driver-specific API function wrappers */ -#define HW_INIT(X) \ -static int init_##X(struct sr_context *sr_ctx) { return init(sr_ctx, X); } -#define HW_CLEANUP(X) \ -static int cleanup_##X(void) { return cleanup(X); } -#define HW_SCAN(X) \ -static GSList *scan_##X(GSList *options) { return scan(options, X); } -#define HW_DEV_LIST(X) \ -static GSList *dev_list_##X(void) { return dev_list(X); } -#define HW_DEV_CLEAR(X) \ -static int dev_clear_##X(void) { return dev_clear(X); } -#define HW_DEV_ACQUISITION_START(X) \ -static int dev_acquisition_start_##X(const struct sr_dev_inst *sdi, \ -void *cb_data) { return dev_acquisition_start(sdi, cb_data, X); } - -/* Driver structs and API function wrappers */ -#define DRV(ID, ID_UPPER, NAME, LONGNAME) \ -HW_INIT(ID_UPPER) \ -HW_CLEANUP(ID_UPPER) \ -HW_SCAN(ID_UPPER) \ -HW_DEV_LIST(ID_UPPER) \ -HW_DEV_CLEAR(ID_UPPER) \ -HW_DEV_ACQUISITION_START(ID_UPPER) \ -SR_PRIV struct sr_dev_driver ID##_driver_info = { \ - .name = NAME, \ - .longname = LONGNAME, \ - .api_version = 1, \ - .init = init_##ID_UPPER, \ - .cleanup = cleanup_##ID_UPPER, \ - .scan = scan_##ID_UPPER, \ - .dev_list = dev_list_##ID_UPPER, \ - .dev_clear = dev_clear_##ID_UPPER, \ - .config_get = NULL, \ - .config_set = config_set, \ - .config_list = config_list, \ - .dev_open = std_serial_dev_open, \ - .dev_close = std_serial_dev_close, \ - .dev_acquisition_start = dev_acquisition_start_##ID_UPPER, \ - .dev_acquisition_stop = dev_acquisition_stop, \ - .priv = NULL, \ -}; - -DRV(center_309, CENTER_309, "center-309", "Center 309") -DRV(voltcraft_k204, VOLTCRAFT_K204, "voltcraft-k204", "Voltcraft K204") diff --git a/hardware/center-3xx/protocol.c b/hardware/center-3xx/protocol.c deleted file mode 100644 index ef8b9dcd..00000000 --- a/hardware/center-3xx/protocol.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2013 Uwe Hermann - * - * 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 "protocol.h" - -struct center_info { - float temp[4]; - gboolean rec, std, max, min, maxmin, t1t2, rel, hold, lowbat, celsius; - gboolean memfull, autooff; - gboolean mode_std, mode_rel, mode_max, mode_min, mode_maxmin; -}; - -static int center_send(struct sr_serial_dev_inst *serial, const char *cmd) -{ - int ret; - - if ((ret = serial_write(serial, cmd, strlen(cmd))) < 0) { - sr_err("Error sending '%s' command: %d.", cmd, ret); - return SR_ERR; - } - - return SR_OK; -} - -SR_PRIV gboolean center_3xx_packet_valid(const uint8_t *buf) -{ - return (buf[0] == 0x02 && buf[44] == 0x03); -} - -static void log_packet(const uint8_t *buf, int idx) -{ - int i; - GString *s; - - s = g_string_sized_new(100); - g_string_printf(s, "Packet: "); - for (i = 0; i < center_devs[idx].packet_size; i++) - g_string_append_printf(s, "%02x ", buf[i]); - sr_spew("%s", s->str); - g_string_free(s, TRUE); -} - -static int packet_parse(const uint8_t *buf, int idx, struct center_info *info) -{ - int i; - uint16_t temp_u16; - - log_packet(buf, idx); - - /* Byte 0: Always 0x02. */ - - /* Byte 1: Various status bits. */ - info->rec = (buf[1] & (1 << 0)) != 0; - info->mode_std = (((buf[1] >> 1) & 0x3) == 0); - info->mode_max = (((buf[1] >> 1) & 0x3) == 1); - info->mode_min = (((buf[1] >> 1) & 0x3) == 2); - info->mode_maxmin = (((buf[1] >> 1) & 0x3) == 3); - /* TODO: Rel. Not available on all models. */ - info->t1t2 = (buf[1] & (1 << 3)) != 0; - info->rel = (buf[1] & (1 << 4)) != 0; - info->hold = (buf[1] & (1 << 5)) != 0; - info->lowbat = (buf[1] & (1 << 6)) != 0; - info->celsius = (buf[1] & (1 << 7)) != 0; - - /* Byte 2: Further status bits. */ - info->memfull = (buf[2] & (1 << 0)) != 0; - info->autooff = (buf[2] & (1 << 7)) != 0; - - /* Byte 7+8/9+10/11+12/13+14: channel T1/T2/T3/T4 temperature. */ - for (i = 0; i < 4; i++) { - temp_u16 = buf[8 + (i * 2)]; - temp_u16 |= ((uint16_t)buf[7 + (i * 2)] << 8); - info->temp[i] = (float)temp_u16; - } - - /* Byte 43: Specifies whether we need to divide the value(s) by 10. */ - for (i = 0; i < 4; i++) { - /* Bit = 0: Divide by 10. Bit = 1: Don't divide by 10. */ - if ((buf[43] & (1 << i)) == 0) - info->temp[i] /= 10; - } - - /* Bytes 39-42: Overflow/overlimit bits, depending on mode. */ - for (i = 0; i < 4; i++) { - if (info->mode_std && ((buf[39] & (1 << i)) != 0)) - info->temp[i] = INFINITY; - /* TODO: Rel. Not available on all models. */ - // if (info->mode_rel && ((buf[40] & (1 << i)) != 0)) - // info->temp[i] = INFINITY; - if (info->mode_max && ((buf[41] & (1 << i)) != 0)) - info->temp[i] = INFINITY; - if (info->mode_min && ((buf[42] & (1 << i)) != 0)) - info->temp[i] = INFINITY; - /* TODO: Minmax? */ - } - - /* Byte 44: Always 0x03. */ - - return SR_OK; -} - -static int handle_packet(const uint8_t *buf, struct sr_dev_inst *sdi, int idx) -{ - struct sr_datafeed_packet packet; - struct sr_datafeed_analog analog; - struct dev_context *devc; - struct center_info info; - GSList *l; - int i, ret; - - devc = sdi->priv; - - memset(&analog, 0, sizeof(struct sr_datafeed_analog)); - memset(&info, 0, sizeof(struct center_info)); - - ret = packet_parse(buf, idx, &info); - if (ret < 0) { - sr_err("Failed to parse packet."); - return SR_ERR; - } - - /* Common values for all 4 channels. */ - packet.type = SR_DF_ANALOG; - packet.payload = &analog; - analog.mq = SR_MQ_TEMPERATURE; - analog.unit = (info.celsius) ? SR_UNIT_CELSIUS : SR_UNIT_FAHRENHEIT; - analog.num_samples = 1; - - /* Send the values for T1 - T4. */ - for (i = 0; i < 4; i++) { - l = NULL; - l = g_slist_append(l, g_slist_nth_data(sdi->channels, i)); - analog.channels = l; - analog.data = &(info.temp[i]); - sr_session_send(devc->cb_data, &packet); - g_slist_free(l); - } - - devc->num_samples++; - - return SR_OK; -} - -/* Return TRUE if a full packet was parsed, FALSE otherwise. */ -static gboolean handle_new_data(struct sr_dev_inst *sdi, int idx) -{ - struct dev_context *devc; - struct sr_serial_dev_inst *serial; - int len, i, offset = 0, ret = FALSE; - - devc = sdi->priv; - serial = sdi->conn; - - /* Try to get as much data as the buffer can hold. */ - len = SERIAL_BUFSIZE - devc->buflen; - len = serial_read(serial, devc->buf + devc->buflen, len); - if (len < 1) { - sr_err("Serial port read error: %d.", len); - return FALSE; - } - - devc->buflen += len; - - /* Now look for packets in that data. */ - while ((devc->buflen - offset) >= center_devs[idx].packet_size) { - if (center_devs[idx].packet_valid(devc->buf + offset)) { - handle_packet(devc->buf + offset, sdi, idx); - offset += center_devs[idx].packet_size; - ret = TRUE; - } else { - offset++; - } - } - - /* If we have any data left, move it to the beginning of our buffer. */ - for (i = 0; i < devc->buflen - offset; i++) - devc->buf[i] = devc->buf[offset + i]; - devc->buflen -= offset; - - return ret; -} - -static int receive_data(int fd, int revents, int idx, void *cb_data) -{ - struct sr_dev_inst *sdi; - struct dev_context *devc; - int64_t t; - static gboolean request_new_packet = TRUE; - struct sr_serial_dev_inst *serial; - - (void)fd; - - if (!(sdi = cb_data)) - return TRUE; - - if (!(devc = sdi->priv)) - return TRUE; - - serial = sdi->conn; - - if (revents == G_IO_IN) { - /* New data arrived. */ - request_new_packet = handle_new_data(sdi, idx); - } else { - /* - * Timeout. Send "A" to request a packet, but then don't send - * further "A" commands until we received a full packet first. - */ - if (request_new_packet) { - center_send(serial, "A"); - request_new_packet = FALSE; - } - } - - if (devc->limit_samples && devc->num_samples >= devc->limit_samples) { - sr_info("Requested number of samples reached."); - sdi->driver->dev_acquisition_stop(sdi, cb_data); - return TRUE; - } - - if (devc->limit_msec) { - t = (g_get_monotonic_time() - devc->starttime) / 1000; - if (t > (int64_t)devc->limit_msec) { - sr_info("Requested time limit reached."); - sdi->driver->dev_acquisition_stop(sdi, cb_data); - return TRUE; - } - } - - return TRUE; -} - -#define RECEIVE_DATA(ID_UPPER) \ -SR_PRIV int receive_data_##ID_UPPER(int fd, int revents, void *cb_data) { \ - return receive_data(fd, revents, ID_UPPER, cb_data); } - -/* Driver-specific receive_data() wrappers */ -RECEIVE_DATA(CENTER_309) -RECEIVE_DATA(VOLTCRAFT_K204) diff --git a/hardware/center-3xx/protocol.h b/hardware/center-3xx/protocol.h deleted file mode 100644 index 71e2630d..00000000 --- a/hardware/center-3xx/protocol.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2013 Uwe Hermann - * - * 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 - */ - -#ifndef LIBSIGROK_HARDWARE_CENTER_3XX_PROTOCOL_H -#define LIBSIGROK_HARDWARE_CENTER_3XX_PROTOCOL_H - -#include -#include -#include -#include -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#define LOG_PREFIX "center-3xx" - -/* Note: When adding entries here, don't forget to update CENTER_DEV_COUNT. */ -enum { - CENTER_309, - VOLTCRAFT_K204, -}; - -#define CENTER_DEV_COUNT 2 - -struct center_dev_info { - char *vendor; - char *device; - char *conn; - int num_channels; - uint32_t max_sample_points; - uint8_t packet_size; - gboolean (*packet_valid)(const uint8_t *); - struct sr_dev_driver *di; - int (*receive_data)(int, int, void *); -}; - -extern SR_PRIV const struct center_dev_info center_devs[CENTER_DEV_COUNT]; - -#define SERIAL_BUFSIZE 256 - -/** Private, per-device-instance driver context. */ -struct dev_context { - /** The current sampling limit (in number of samples). */ - uint64_t limit_samples; - - /** The current sampling limit (in ms). */ - uint64_t limit_msec; - - /** Opaque pointer passed in by the frontend. */ - void *cb_data; - - /** The current number of already received samples. */ - uint64_t num_samples; - - int64_t starttime; - - uint8_t buf[SERIAL_BUFSIZE]; - int bufoffset; - int buflen; -}; - -SR_PRIV gboolean center_3xx_packet_valid(const uint8_t *buf); - -SR_PRIV int receive_data_CENTER_309(int fd, int revents, void *cb_data); -SR_PRIV int receive_data_VOLTCRAFT_K204(int fd, int revents, void *cb_data); - -#endif diff --git a/hardware/chronovu-la/api.c b/hardware/chronovu-la/api.c deleted file mode 100644 index 5a8a3d36..00000000 --- a/hardware/chronovu-la/api.c +++ /dev/null @@ -1,558 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2011-2014 Uwe Hermann - * - * 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 "protocol.h" - -SR_PRIV struct sr_dev_driver chronovu_la_driver_info; -static struct sr_dev_driver *di = &chronovu_la_driver_info; - -static const int32_t hwcaps[] = { - SR_CONF_LOGIC_ANALYZER, - SR_CONF_SAMPLERATE, - SR_CONF_TRIGGER_MATCH, - SR_CONF_LIMIT_MSEC, /* TODO: Not yet implemented. */ - SR_CONF_LIMIT_SAMPLES, /* TODO: Not yet implemented. */ -}; - -static const int32_t trigger_matches[] = { - SR_TRIGGER_ZERO, - SR_TRIGGER_ONE, - SR_TRIGGER_RISING, - SR_TRIGGER_FALLING, -}; - -/* The ChronoVu LA8/LA16 can have multiple VID/PID pairs. */ -static struct { - uint16_t vid; - uint16_t pid; - int model; - const char *iproduct; -} vid_pid[] = { - { 0x0403, 0x6001, CHRONOVU_LA8, "ChronoVu LA8" }, - { 0x0403, 0x8867, CHRONOVU_LA8, "ChronoVu LA8" }, - { 0x0403, 0x6001, CHRONOVU_LA16, "ChronoVu LA16" }, - { 0x0403, 0x8867, CHRONOVU_LA16, "ChronoVu LA16" }, -}; - -static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data); - -static void clear_helper(void *priv) -{ - struct dev_context *devc; - - devc = priv; - - ftdi_free(devc->ftdic); - g_free(devc->final_buf); -} - -static int dev_clear(void) -{ - return std_dev_clear(di, clear_helper); -} - -static int init(struct sr_context *sr_ctx) -{ - return std_init(sr_ctx, di, LOG_PREFIX); -} - -static int add_device(int idx, int model, GSList **devices) -{ - int ret; - unsigned int i; - struct sr_dev_inst *sdi; - struct drv_context *drvc; - struct dev_context *devc; - struct sr_channel *ch; - - ret = SR_OK; - - drvc = di->priv; - - /* Allocate memory for our private device context. */ - devc = g_try_malloc(sizeof(struct dev_context)); - - /* Set some sane defaults. */ - devc->prof = &cv_profiles[model]; - devc->ftdic = NULL; /* Will be set in the open() API call. */ - devc->cur_samplerate = 0; /* Set later (different for LA8/LA16). */ - devc->limit_msec = 0; - devc->limit_samples = 0; - devc->cb_data = NULL; - memset(devc->mangled_buf, 0, BS); - devc->final_buf = NULL; - devc->trigger_pattern = 0x0000; /* Irrelevant, see trigger_mask. */ - devc->trigger_mask = 0x0000; /* All channels: "don't care". */ - devc->trigger_edgemask = 0x0000; /* All channels: "state triggered". */ - devc->trigger_found = 0; - devc->done = 0; - devc->block_counter = 0; - devc->divcount = 0; - devc->usb_vid = vid_pid[idx].vid; - devc->usb_pid = vid_pid[idx].pid; - memset(devc->samplerates, 0, sizeof(uint64_t) * 255); - - /* Allocate memory where we'll store the de-mangled data. */ - if (!(devc->final_buf = g_try_malloc(SDRAM_SIZE))) { - sr_err("Failed to allocate memory for sample buffer."); - ret = SR_ERR_MALLOC; - goto err_free_devc; - } - - /* We now know the device, set its max. samplerate as default. */ - devc->cur_samplerate = devc->prof->max_samplerate; - - /* Register the device with libsigrok. */ - sdi = sr_dev_inst_new(0, SR_ST_INITIALIZING, - "ChronoVu", devc->prof->modelname, NULL); - if (!sdi) { - sr_err("Failed to create device instance."); - ret = SR_ERR; - goto err_free_final_buf; - } - sdi->driver = di; - sdi->priv = devc; - - for (i = 0; i < devc->prof->num_channels; i++) { - if (!(ch = sr_channel_new(i, SR_CHANNEL_LOGIC, TRUE, - cv_channel_names[i]))) { - ret = SR_ERR; - goto err_free_dev_inst; - } - sdi->channels = g_slist_append(sdi->channels, ch); - } - - *devices = g_slist_append(*devices, sdi); - drvc->instances = g_slist_append(drvc->instances, sdi); - - return SR_OK; - -err_free_dev_inst: - sr_dev_inst_free(sdi); -err_free_final_buf: - g_free(devc->final_buf); -err_free_devc: - g_free(devc); - - return ret; -} - -static GSList *scan(GSList *options) -{ - int ret; - unsigned int i; - GSList *devices; - struct ftdi_context *ftdic; - - (void)options; - - devices = NULL; - - /* Allocate memory for the FTDI context and initialize it. */ - if (!(ftdic = ftdi_new())) { - sr_err("Failed to initialize libftdi."); - return NULL; - } - - /* Check for LA8 and/or LA16 devices with various VID/PIDs. */ - for (i = 0; i < ARRAY_SIZE(vid_pid); i++) { - ret = ftdi_usb_open_desc(ftdic, vid_pid[i].vid, - vid_pid[i].pid, vid_pid[i].iproduct, NULL); - /* Show errors other than "device not found". */ - if (ret < 0 && ret != -3) - sr_dbg("Error finding/opening device (%d): %s.", - ret, ftdi_get_error_string(ftdic)); - if (ret < 0) - continue; /* No device found, or not usable. */ - - sr_dbg("Found %s device (%04x:%04x).", - vid_pid[i].iproduct, vid_pid[i].vid, vid_pid[i].pid); - - if ((ret = add_device(i, vid_pid[i].model, &devices)) < 0) - sr_dbg("Failed to add device: %d.", ret); - - if ((ret = ftdi_usb_close(ftdic)) < 0) - sr_dbg("Failed to close FTDI device (%d): %s.", - ret, ftdi_get_error_string(ftdic)); - } - - /* Close USB device, deinitialize and free the FTDI context. */ - ftdi_free(ftdic); - ftdic = NULL; - - return devices; -} - -static GSList *dev_list(void) -{ - return ((struct drv_context *)(di->priv))->instances; -} - -static int dev_open(struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - int ret; - - ret = SR_ERR; - - if (!(devc = sdi->priv)) - return SR_ERR_BUG; - - /* Allocate memory for the FTDI context and initialize it. */ - if (!(devc->ftdic = ftdi_new())) { - sr_err("Failed to initialize libftdi."); - return SR_ERR; - } - - sr_dbg("Opening %s device (%04x:%04x).", devc->prof->modelname, - devc->usb_vid, devc->usb_pid); - - /* Open the device. */ - if ((ret = ftdi_usb_open_desc(devc->ftdic, devc->usb_vid, - devc->usb_pid, devc->prof->iproduct, NULL)) < 0) { - sr_err("Failed to open FTDI device (%d): %s.", - ret, ftdi_get_error_string(devc->ftdic)); - goto err_ftdi_free; - } - sr_dbg("Device opened successfully."); - - /* Purge RX/TX buffers in the FTDI chip. */ - if ((ret = ftdi_usb_purge_buffers(devc->ftdic)) < 0) { - sr_err("Failed to purge FTDI buffers (%d): %s.", - ret, ftdi_get_error_string(devc->ftdic)); - goto err_ftdi_free; - } - sr_dbg("FTDI buffers purged successfully."); - - /* Enable flow control in the FTDI chip. */ - if ((ret = ftdi_setflowctrl(devc->ftdic, SIO_RTS_CTS_HS)) < 0) { - sr_err("Failed to enable FTDI flow control (%d): %s.", - ret, ftdi_get_error_string(devc->ftdic)); - goto err_ftdi_free; - } - sr_dbg("FTDI flow control enabled successfully."); - - /* Wait 100ms. */ - g_usleep(100 * 1000); - - sdi->status = SR_ST_ACTIVE; - - return SR_OK; - -err_ftdi_free: - ftdi_free(devc->ftdic); /* Close device (if open), free FTDI context. */ - devc->ftdic = NULL; - return ret; -} - -static int dev_close(struct sr_dev_inst *sdi) -{ - int ret; - struct dev_context *devc; - - if (sdi->status != SR_ST_ACTIVE) - return SR_OK; - - devc = sdi->priv; - - if (devc->ftdic && (ret = ftdi_usb_close(devc->ftdic)) < 0) - sr_err("Failed to close FTDI device (%d): %s.", - ret, ftdi_get_error_string(devc->ftdic)); - sdi->status = SR_ST_INACTIVE; - - return SR_OK; -} - -static int cleanup(void) -{ - return dev_clear(); -} - -static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc; - - (void)cg; - - switch (id) { - case SR_CONF_SAMPLERATE: - if (!sdi || !(devc = sdi->priv)) - return SR_ERR_BUG; - *data = g_variant_new_uint64(devc->cur_samplerate); - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc; - - (void)cg; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - if (!(devc = sdi->priv)) - return SR_ERR_BUG; - - switch (id) { - case SR_CONF_SAMPLERATE: - if (cv_set_samplerate(sdi, g_variant_get_uint64(data)) < 0) - return SR_ERR; - break; - case SR_CONF_LIMIT_MSEC: - if (g_variant_get_uint64(data) == 0) - return SR_ERR_ARG; - devc->limit_msec = g_variant_get_uint64(data); - break; - case SR_CONF_LIMIT_SAMPLES: - if (g_variant_get_uint64(data) == 0) - return SR_ERR_ARG; - devc->limit_samples = g_variant_get_uint64(data); - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - GVariant *gvar, *grange[2]; - GVariantBuilder gvb; - struct dev_context *devc; - - (void)cg; - - switch (key) { - case SR_CONF_DEVICE_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t)); - break; - case SR_CONF_SAMPLERATE: - if (!sdi || !sdi->priv || !(devc = sdi->priv)) - return SR_ERR_BUG; - cv_fill_samplerates_if_needed(sdi); - g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}")); - gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), - devc->samplerates, - ARRAY_SIZE(devc->samplerates), - sizeof(uint64_t)); - g_variant_builder_add(&gvb, "{sv}", "samplerates", gvar); - *data = g_variant_builder_end(&gvb); - break; - case SR_CONF_LIMIT_SAMPLES: - if (!sdi || !sdi->priv || !(devc = sdi->priv) || !devc->prof) - return SR_ERR_BUG; - grange[0] = g_variant_new_uint64(0); - if (devc->prof->model == CHRONOVU_LA8) - grange[1] = g_variant_new_uint64(MAX_NUM_SAMPLES); - else - grange[1] = g_variant_new_uint64(MAX_NUM_SAMPLES / 2); - *data = g_variant_new_tuple(grange, 2); - break; - case SR_CONF_TRIGGER_MATCH: - if (!sdi || !sdi->priv || !(devc = sdi->priv) || !devc->prof) - return SR_ERR_BUG; - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - trigger_matches, devc->prof->num_trigger_matches, - sizeof(int32_t)); - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int receive_data(int fd, int revents, void *cb_data) -{ - int i, ret; - struct sr_dev_inst *sdi; - struct dev_context *devc; - - (void)fd; - (void)revents; - - if (!(sdi = cb_data)) { - sr_err("cb_data was NULL."); - return FALSE; - } - - if (!(devc = sdi->priv)) { - sr_err("sdi->priv was NULL."); - return FALSE; - } - - if (!devc->ftdic) { - sr_err("devc->ftdic was NULL."); - return FALSE; - } - - /* Get one block of data. */ - if ((ret = cv_read_block(devc)) < 0) { - sr_err("Failed to read data block: %d.", ret); - dev_acquisition_stop(sdi, sdi); - return FALSE; - } - - /* We need to get exactly NUM_BLOCKS blocks (i.e. 8MB) of data. */ - if (devc->block_counter != (NUM_BLOCKS - 1)) { - devc->block_counter++; - return TRUE; - } - - sr_dbg("Sampling finished, sending data to session bus now."); - - /* - * All data was received and demangled, send it to the session bus. - * - * Note: Due to the method how data is spread across the 8MByte of - * SDRAM, we can _not_ send it to the session bus in a streaming - * manner while we receive it. We have to receive and de-mangle the - * full 8MByte first, only then the whole buffer contains valid data. - */ - for (i = 0; i < NUM_BLOCKS; i++) - cv_send_block_to_session_bus(devc, i); - - dev_acquisition_stop(sdi, sdi); - - return TRUE; -} - -static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) -{ - struct dev_context *devc; - uint8_t buf[8]; - int bytes_to_write, bytes_written; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - if (!(devc = sdi->priv)) { - sr_err("sdi->priv was NULL."); - return SR_ERR_BUG; - } - - if (!devc->ftdic) { - sr_err("devc->ftdic was NULL."); - return SR_ERR_BUG; - } - - devc->divcount = cv_samplerate_to_divcount(sdi, devc->cur_samplerate); - if (devc->divcount == 0xff) { - sr_err("Invalid divcount/samplerate."); - return SR_ERR; - } - - if (cv_convert_trigger(sdi) != SR_OK) { - sr_err("Failed to configure trigger."); - return SR_ERR; - } - - /* Fill acquisition parameters into buf[]. */ - if (devc->prof->model == CHRONOVU_LA8) { - buf[0] = devc->divcount; - buf[1] = 0xff; /* This byte must always be 0xff. */ - buf[2] = devc->trigger_pattern & 0xff; - buf[3] = devc->trigger_mask & 0xff; - bytes_to_write = 4; - } else { - buf[0] = devc->divcount; - buf[1] = 0xff; /* This byte must always be 0xff. */ - buf[2] = (devc->trigger_pattern & 0xff00) >> 8; /* LSB */ - buf[3] = (devc->trigger_pattern & 0x00ff) >> 0; /* MSB */ - buf[4] = (devc->trigger_mask & 0xff00) >> 8; /* LSB */ - buf[5] = (devc->trigger_mask & 0x00ff) >> 0; /* MSB */ - buf[6] = (devc->trigger_edgemask & 0xff00) >> 8; /* LSB */ - buf[7] = (devc->trigger_edgemask & 0x00ff) >> 0; /* MSB */ - bytes_to_write = 8; - } - - /* Start acquisition. */ - bytes_written = cv_write(devc, buf, bytes_to_write); - - if (bytes_written < 0 || bytes_written != bytes_to_write) { - sr_err("Acquisition failed to start."); - return SR_ERR; - } - - sr_dbg("Hardware acquisition started successfully."); - - devc->cb_data = cb_data; - - /* Send header packet to the session bus. */ - std_session_send_df_header(sdi, LOG_PREFIX); - - /* Time when we should be done (for detecting trigger timeouts). */ - devc->done = (devc->divcount + 1) * devc->prof->trigger_constant + - g_get_monotonic_time() + (10 * G_TIME_SPAN_SECOND); - devc->block_counter = 0; - devc->trigger_found = 0; - - /* Hook up a dummy handler to receive data from the device. */ - sr_session_source_add(sdi->session, -1, G_IO_IN, 0, receive_data, (void *)sdi); - - return SR_OK; -} - -static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) -{ - struct sr_datafeed_packet packet; - - (void)cb_data; - - sr_dbg("Stopping acquisition."); - sr_session_source_remove(sdi->session, -1); - - /* Send end packet to the session bus. */ - sr_dbg("Sending SR_DF_END."); - packet.type = SR_DF_END; - sr_session_send(sdi, &packet); - - return SR_OK; -} - -SR_PRIV struct sr_dev_driver chronovu_la_driver_info = { - .name = "chronovu-la", - .longname = "ChronoVu LA8/LA16", - .api_version = 1, - .init = init, - .cleanup = cleanup, - .scan = scan, - .dev_list = dev_list, - .dev_clear = dev_clear, - .config_get = config_get, - .config_set = config_set, - .config_list = config_list, - .dev_open = dev_open, - .dev_close = dev_close, - .dev_acquisition_start = dev_acquisition_start, - .dev_acquisition_stop = dev_acquisition_stop, - .priv = NULL, -}; diff --git a/hardware/chronovu-la/protocol.c b/hardware/chronovu-la/protocol.c deleted file mode 100644 index c2f31a20..00000000 --- a/hardware/chronovu-la/protocol.c +++ /dev/null @@ -1,506 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2011-2014 Uwe Hermann - * - * 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 "protocol.h" - -SR_PRIV const struct cv_profile cv_profiles[] = { - { CHRONOVU_LA8, "LA8", "ChronoVu LA8", 8, SR_MHZ(100), 2, 0.8388608 }, - { CHRONOVU_LA16, "LA16", "ChronoVu LA16", 16, SR_MHZ(200), 4, 0.042 }, - { 0, NULL, NULL, 0, 0, 0, 0.0 }, -}; - -/* LA8: channels are numbered 0-7. LA16: channels are numbered 0-15. */ -SR_PRIV const char *cv_channel_names[] = { - "0", "1", "2", "3", "4", "5", "6", "7", - "8", "9", "10", "11", "12", "13", "14", "15", -}; - -static int close_usb_reset_sequencer(struct dev_context *devc); - -SR_PRIV void cv_fill_samplerates_if_needed(const struct sr_dev_inst *sdi) -{ - int i; - struct dev_context *devc; - - devc = sdi->priv; - - if (devc->samplerates[0] != 0) - return; - - for (i = 0; i < 255; i++) - devc->samplerates[254 - i] = devc->prof->max_samplerate / (i + 1); -} - -/** - * Check if the given samplerate is supported by the hardware. - * - * @param sdi Device instance. - * @param samplerate The samplerate (in Hz) to check. - * - * @return 1 if the samplerate is supported/valid, 0 otherwise. - */ -static int is_valid_samplerate(const struct sr_dev_inst *sdi, - uint64_t samplerate) -{ - int i; - struct dev_context *devc; - - devc = sdi->priv; - - cv_fill_samplerates_if_needed(sdi); - - for (i = 0; i < 255; i++) { - if (devc->samplerates[i] == samplerate) - return 1; - } - - sr_err("Invalid samplerate (%" PRIu64 "Hz).", samplerate); - - return 0; -} - -/** - * Convert a samplerate (in Hz) to the 'divcount' value the device wants. - * - * The divcount value can be 0x00 - 0xfe (0xff is not valid). - * - * LA8: - * sample period = (divcount + 1) * 10ns. - * divcount = 0x00: 10ns period, 100MHz samplerate. - * divcount = 0xfe: 2550ns period, 392.15kHz samplerate. - * - * LA16: - * sample period = (divcount + 1) * 5ns. - * divcount = 0x00: 5ns period, 200MHz samplerate. - * divcount = 0xfe: 1275ns period, ~784.31kHz samplerate. - * - * @param sdi Device instance. - * @param samplerate The samplerate in Hz. - * - * @return The divcount value as needed by the hardware, or 0xff upon errors. - */ -SR_PRIV uint8_t cv_samplerate_to_divcount(const struct sr_dev_inst *sdi, - uint64_t samplerate) -{ - struct dev_context *devc; - - devc = sdi->priv; - - if (samplerate == 0) { - sr_err("Can't convert invalid samplerate of 0 Hz."); - return 0xff; - } - - if (!is_valid_samplerate(sdi, samplerate)) { - sr_err("Can't get divcount, samplerate invalid."); - return 0xff; - } - - return (devc->prof->max_samplerate / samplerate) - 1; -} - -/** - * Write data of a certain length to the FTDI device. - * - * @param devc The struct containing private per-device-instance data. Must not - * be NULL. devc->ftdic must not be NULL either. - * @param buf The buffer containing the data to write. Must not be NULL. - * @param size The number of bytes to write. Must be > 0. - * - * @return The number of bytes written, or a negative value upon errors. - */ -SR_PRIV int cv_write(struct dev_context *devc, uint8_t *buf, int size) -{ - int bytes_written; - - /* Note: Caller ensures devc/devc->ftdic/buf != NULL and size > 0. */ - - bytes_written = ftdi_write_data(devc->ftdic, buf, size); - - if (bytes_written < 0) { - sr_err("Failed to write data (%d): %s.", - bytes_written, ftdi_get_error_string(devc->ftdic)); - (void) close_usb_reset_sequencer(devc); /* Ignore errors. */ - } else if (bytes_written != size) { - sr_err("Failed to write data, only %d/%d bytes written.", - size, bytes_written); - (void) close_usb_reset_sequencer(devc); /* Ignore errors. */ - } - - return bytes_written; -} - -/** - * Read a certain amount of bytes from the FTDI device. - * - * @param devc The struct containing private per-device-instance data. Must not - * be NULL. devc->ftdic must not be NULL either. - * @param buf The buffer where the received data will be stored. Must not - * be NULL. - * @param size The number of bytes to read. Must be >= 1. - * - * @return The number of bytes read, or a negative value upon errors. - */ -static int cv_read(struct dev_context *devc, uint8_t *buf, int size) -{ - int bytes_read; - - /* Note: Caller ensures devc/devc->ftdic/buf != NULL and size > 0. */ - - bytes_read = ftdi_read_data(devc->ftdic, buf, size); - - if (bytes_read < 0) { - sr_err("Failed to read data (%d): %s.", - bytes_read, ftdi_get_error_string(devc->ftdic)); - } else if (bytes_read != size) { - // sr_err("Failed to read data, only %d/%d bytes read.", - // bytes_read, size); - } - - return bytes_read; -} - -/** - * Close the USB port and reset the sequencer logic. - * - * @param devc The struct containing private per-device-instance data. - * - * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments. - */ -static int close_usb_reset_sequencer(struct dev_context *devc) -{ - /* Magic sequence of bytes for resetting the sequencer logic. */ - uint8_t buf[8] = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; - int ret; - - /* Note: Caller checked that devc and devc->ftdic != NULL. */ - - if (devc->ftdic->usb_dev) { - /* Reset the sequencer logic, then wait 100ms. */ - sr_dbg("Resetting sequencer logic."); - (void) cv_write(devc, buf, 8); /* Ignore errors. */ - g_usleep(100 * 1000); - - /* Purge FTDI buffers, then reset and close the FTDI device. */ - sr_dbg("Purging buffers, resetting+closing FTDI device."); - - /* Log errors, but ignore them (i.e., don't abort). */ - if ((ret = ftdi_usb_purge_buffers(devc->ftdic)) < 0) - sr_err("Failed to purge FTDI buffers (%d): %s.", - ret, ftdi_get_error_string(devc->ftdic)); - if ((ret = ftdi_usb_reset(devc->ftdic)) < 0) - sr_err("Failed to reset FTDI device (%d): %s.", - ret, ftdi_get_error_string(devc->ftdic)); - if ((ret = ftdi_usb_close(devc->ftdic)) < 0) - sr_err("Failed to close FTDI device (%d): %s.", - ret, ftdi_get_error_string(devc->ftdic)); - } - - /* Close USB device, deinitialize and free the FTDI context. */ - ftdi_free(devc->ftdic); - devc->ftdic = NULL; - - return SR_OK; -} - -/** - * Reset the ChronoVu device. - * - * A reset is required after a failed read/write operation or upon timeouts. - * - * @param devc The struct containing private per-device-instance data. - * - * @return SR_OK upon success, SR_ERR upon failure. - */ -static int reset_device(struct dev_context *devc) -{ - uint8_t buf[BS]; - gint64 done, now; - int bytes_read; - - /* Note: Caller checked that devc and devc->ftdic != NULL. */ - - sr_dbg("Resetting the device."); - - /* - * Purge pending read data from the FTDI hardware FIFO until - * no more data is left, or a timeout occurs (after 20s). - */ - done = (20 * G_TIME_SPAN_SECOND) + g_get_monotonic_time(); - do { - /* Try to read bytes until none are left (or errors occur). */ - bytes_read = cv_read(devc, (uint8_t *)&buf, BS); - now = g_get_monotonic_time(); - } while ((done > now) && (bytes_read > 0)); - - /* Reset the sequencer logic and close the USB port. */ - (void) close_usb_reset_sequencer(devc); /* Ignore errors. */ - - sr_dbg("Device reset finished."); - - return SR_OK; -} - -SR_PRIV int cv_convert_trigger(const struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - struct sr_trigger *trigger; - struct sr_trigger_stage *stage; - struct sr_trigger_match *match; - const GSList *l, *m; - uint16_t channel_bit; - - devc = sdi->priv; - devc->trigger_pattern = 0x0000; /* Default to "low" trigger. */ - devc->trigger_mask = 0x0000; /* Default to "don't care". */ - devc->trigger_edgemask = 0x0000; /* Default to "state triggered". */ - - if (!(trigger = sr_session_trigger_get(sdi->session))) - return SR_OK; - - if (g_slist_length(trigger->stages) > 1) { - sr_err("This device only supports 1 trigger stage."); - return SR_ERR; - } - - for (l = trigger->stages; l; l = l->next) { - stage = l->data; - for (m = stage->matches; m; m = m->next) { - match = m->data; - if (!match->channel->enabled) - /* Ignore disabled channels with a trigger. */ - continue; - if (devc->prof->model == CHRONOVU_LA8 && - (match->match == SR_TRIGGER_RISING - || match->match == SR_TRIGGER_FALLING)) { - sr_err("This model supports only simple triggers."); - return SR_ERR; - } - channel_bit = (1 << (match->channel->index)); - - /* state: 1 == high, edge: 1 == rising edge. */ - if (match->match == SR_TRIGGER_ONE - || match->match == SR_TRIGGER_RISING) - devc->trigger_pattern |= channel_bit; - - /* LA16 (but not LA8) supports edge triggering. */ - if ((devc->prof->model == CHRONOVU_LA16)) { - if (match->match == SR_TRIGGER_RISING - || match->match == SR_TRIGGER_FALLING) - devc->trigger_edgemask |= channel_bit; - } - } - } - - sr_dbg("Trigger pattern/mask/edgemask = 0x%04x / 0x%04x / 0x%04x.", - devc->trigger_pattern, devc->trigger_mask, - devc->trigger_edgemask); - - return SR_OK; -} - -SR_PRIV int cv_set_samplerate(const struct sr_dev_inst *sdi, uint64_t samplerate) -{ - struct dev_context *devc; - - /* Note: Caller checked that sdi and sdi->priv != NULL. */ - - devc = sdi->priv; - - sr_spew("Trying to set samplerate to %" PRIu64 "Hz.", samplerate); - - cv_fill_samplerates_if_needed(sdi); - - /* Check if this is a samplerate supported by the hardware. */ - if (!is_valid_samplerate(sdi, samplerate)) { - sr_dbg("Failed to set invalid samplerate (%" PRIu64 "Hz).", - samplerate); - return SR_ERR; - } - - devc->cur_samplerate = samplerate; - - sr_dbg("Samplerate set to %" PRIu64 "Hz.", devc->cur_samplerate); - - return SR_OK; -} - -/** - * Get a block of data from the device. - * - * @param devc The struct containing private per-device-instance data. Must not - * be NULL. devc->ftdic must not be NULL either. - * - * @return SR_OK upon success, or SR_ERR upon errors. - */ -SR_PRIV int cv_read_block(struct dev_context *devc) -{ - int i, byte_offset, m, mi, p, q, index, bytes_read; - gint64 now; - - /* Note: Caller checked that devc and devc->ftdic != NULL. */ - - sr_spew("Reading block %d.", devc->block_counter); - - bytes_read = cv_read(devc, devc->mangled_buf, BS); - - /* If first block read got 0 bytes, retry until success or timeout. */ - if ((bytes_read == 0) && (devc->block_counter == 0)) { - do { - sr_spew("Reading block 0 (again)."); - /* Note: If bytes_read < 0 cv_read() will log errors. */ - bytes_read = cv_read(devc, devc->mangled_buf, BS); - now = g_get_monotonic_time(); - } while ((devc->done > now) && (bytes_read == 0)); - } - - /* Check if block read was successful or a timeout occured. */ - if (bytes_read != BS) { - sr_err("Trigger timed out. Bytes read: %d.", bytes_read); - (void) reset_device(devc); /* Ignore errors. */ - return SR_ERR; - } - - /* De-mangle the data. */ - sr_spew("Demangling block %d.", devc->block_counter); - byte_offset = devc->block_counter * BS; - m = byte_offset / (1024 * 1024); - mi = m * (1024 * 1024); - for (i = 0; i < BS; i++) { - if (devc->prof->model == CHRONOVU_LA8) { - p = i & (1 << 0); - index = m * 2 + (((byte_offset + i) - mi) / 2) * 16; - index += (devc->divcount == 0) ? p : (1 - p); - } else { - p = i & (1 << 0); - q = i & (1 << 1); - index = m * 4 + (((byte_offset + i) - mi) / 4) * 32; - index += q + (1 - p); - } - devc->final_buf[index] = devc->mangled_buf[i]; - } - - return SR_OK; -} - -SR_PRIV void cv_send_block_to_session_bus(struct dev_context *devc, int block) -{ - int i, idx; - uint8_t sample, expected_sample, tmp8; - struct sr_datafeed_packet packet; - struct sr_datafeed_logic logic; - int trigger_point; /* Relative trigger point (in this block). */ - - /* Note: Caller ensures devc/devc->ftdic != NULL and block > 0. */ - - /* TODO: Implement/test proper trigger support for the LA16. */ - - /* Check if we can find the trigger condition in this block. */ - trigger_point = -1; - expected_sample = devc->trigger_pattern & devc->trigger_mask; - for (i = 0; i < BS; i++) { - /* Don't continue if the trigger was found previously. */ - if (devc->trigger_found) - break; - - /* - * Also, don't continue if triggers are "don't care", i.e. if - * no trigger conditions were specified by the user. In that - * case we don't want to send an SR_DF_TRIGGER packet at all. - */ - if (devc->trigger_mask == 0x0000) - break; - - sample = *(devc->final_buf + (block * BS) + i); - - if ((sample & devc->trigger_mask) == expected_sample) { - trigger_point = i; - devc->trigger_found = 1; - break; - } - } - - /* Swap low and high bytes of the 16-bit LA16 samples. */ - if (devc->prof->model == CHRONOVU_LA16) { - for (i = 0; i < BS; i += 2) { - idx = (block * BS) + i; - tmp8 = devc->final_buf[idx]; - devc->final_buf[idx] = devc->final_buf[idx + 1]; - devc->final_buf[idx + 1] = tmp8; - } - } - - /* If no trigger was found, send one SR_DF_LOGIC packet. */ - if (trigger_point == -1) { - /* Send an SR_DF_LOGIC packet to the session bus. */ - sr_spew("Sending SR_DF_LOGIC packet (%d bytes) for " - "block %d.", BS, block); - packet.type = SR_DF_LOGIC; - packet.payload = &logic; - logic.length = BS; - logic.unitsize = devc->prof->num_channels / 8; - logic.data = devc->final_buf + (block * BS); - sr_session_send(devc->cb_data, &packet); - return; - } - - /* - * We found the trigger, so some special handling is needed. We have - * to send an SR_DF_LOGIC packet with the samples before the trigger - * (if any), then the SD_DF_TRIGGER packet itself, then another - * SR_DF_LOGIC packet with the samples after the trigger (if any). - */ - - /* TODO: Send SR_DF_TRIGGER packet before or after the actual sample? */ - - /* If at least one sample is located before the trigger... */ - if (trigger_point > 0) { - /* Send pre-trigger SR_DF_LOGIC packet to the session bus. */ - sr_spew("Sending pre-trigger SR_DF_LOGIC packet, " - "start = %d, length = %d.", block * BS, trigger_point); - packet.type = SR_DF_LOGIC; - packet.payload = &logic; - logic.length = trigger_point; - logic.unitsize = devc->prof->num_channels / 8; - logic.data = devc->final_buf + (block * BS); - sr_session_send(devc->cb_data, &packet); - } - - /* Send the SR_DF_TRIGGER packet to the session bus. */ - sr_spew("Sending SR_DF_TRIGGER packet, sample = %d.", - (block * BS) + trigger_point); - packet.type = SR_DF_TRIGGER; - packet.payload = NULL; - sr_session_send(devc->cb_data, &packet); - - /* If at least one sample is located after the trigger... */ - if (trigger_point < (BS - 1)) { - /* Send post-trigger SR_DF_LOGIC packet to the session bus. */ - sr_spew("Sending post-trigger SR_DF_LOGIC packet, " - "start = %d, length = %d.", - (block * BS) + trigger_point, BS - trigger_point); - packet.type = SR_DF_LOGIC; - packet.payload = &logic; - logic.length = BS - trigger_point; - logic.unitsize = devc->prof->num_channels / 8; - logic.data = devc->final_buf + (block * BS) + trigger_point; - sr_session_send(devc->cb_data, &packet); - } -} diff --git a/hardware/chronovu-la/protocol.h b/hardware/chronovu-la/protocol.h deleted file mode 100644 index c74feaa2..00000000 --- a/hardware/chronovu-la/protocol.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2011-2014 Uwe Hermann - * - * 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 - */ - -#ifndef LIBSIGROK_HARDWARE_CHRONOVU_LA_PROTOCOL_H -#define LIBSIGROK_HARDWARE_CHRONOVU_LA_PROTOCOL_H - -#include -#include -#include -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#define LOG_PREFIX "la8/la16" - -#define SDRAM_SIZE (8 * 1024 * 1024) -#define MAX_NUM_SAMPLES SDRAM_SIZE - -#define BS 4096 /* Block size */ -#define NUM_BLOCKS 2048 /* Number of blocks */ - -enum { - CHRONOVU_LA8, - CHRONOVU_LA16, -}; - -struct cv_profile { - int model; - const char *modelname; - const char *iproduct; /* USB iProduct string */ - unsigned int num_channels; - uint64_t max_samplerate; - const int num_trigger_matches; - float trigger_constant; -}; - -/* Private, per-device-instance driver context. */ -struct dev_context { - /** Device profile struct for this device. */ - const struct cv_profile *prof; - - /** FTDI device context (used by libftdi). */ - struct ftdi_context *ftdic; - - /** The currently configured samplerate of the device. */ - uint64_t cur_samplerate; - - /** The current sampling limit (in ms). */ - uint64_t limit_msec; - - /** The current sampling limit (in number of samples). */ - uint64_t limit_samples; - - void *cb_data; - - /** - * A buffer containing some (mangled) samples from the device. - * Format: Pretty mangled-up (due to hardware reasons), see code. - */ - uint8_t mangled_buf[BS]; - - /** - * An 8MB buffer where we'll store the de-mangled samples. - * LA8: Each sample is 1 byte, MSB is channel 7, LSB is channel 0. - * LA16: Each sample is 2 bytes, MSB is channel 15, LSB is channel 0. - */ - uint8_t *final_buf; - - /** - * Trigger pattern. - * A 1 bit matches a high signal, 0 matches a low signal on a channel. - * - * If the resp. 'trigger_edgemask' bit is set, 1 means "rising edge", - * and 0 means "falling edge". - */ - uint16_t trigger_pattern; - - /** - * Trigger mask. - * A 1 bit means "must match trigger_pattern", 0 means "don't care". - */ - uint16_t trigger_mask; - - /** - * Trigger edge mask. - * A 1 bit means "edge triggered", 0 means "state triggered". - * - * Edge triggering is only supported on LA16 (but not LA8). - */ - uint16_t trigger_edgemask; - - /** Tells us whether an SR_DF_TRIGGER packet was already sent. */ - int trigger_found; - - /** Used for keeping track how much time has passed. */ - gint64 done; - - /** Counter/index for the data block to be read. */ - int block_counter; - - /** The divcount value (determines the sample period). */ - uint8_t divcount; - - /** This ChronoVu device's USB VID/PID. */ - uint16_t usb_vid; - uint16_t usb_pid; - - /** Samplerates supported by this device. */ - uint64_t samplerates[255]; -}; - -/* protocol.c */ -extern SR_PRIV const char *cv_channel_names[]; -extern const struct cv_profile cv_profiles[]; -SR_PRIV void cv_fill_samplerates_if_needed(const struct sr_dev_inst *sdi); -SR_PRIV uint8_t cv_samplerate_to_divcount(const struct sr_dev_inst *sdi, - uint64_t samplerate); -SR_PRIV int cv_write(struct dev_context *devc, uint8_t *buf, int size); -SR_PRIV int cv_convert_trigger(const struct sr_dev_inst *sdi); -SR_PRIV int cv_set_samplerate(const struct sr_dev_inst *sdi, uint64_t samplerate); -SR_PRIV int cv_read_block(struct dev_context *devc); -SR_PRIV void cv_send_block_to_session_bus(struct dev_context *devc, int block); - -#endif diff --git a/hardware/colead-slm/api.c b/hardware/colead-slm/api.c deleted file mode 100644 index d5fc9ac1..00000000 --- a/hardware/colead-slm/api.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2012 Bert Vermeulen - * - * 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 . - */ - -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" -#include "protocol.h" -#include -#include -#include -#include -#include - -/* The Colead SL-5868P uses this. */ -#define SERIALCOMM "2400/8n1" - -static const int32_t hwopts[] = { - SR_CONF_CONN, - SR_CONF_SERIALCOMM, -}; - -static const int32_t hwcaps[] = { - SR_CONF_SOUNDLEVELMETER, - SR_CONF_LIMIT_SAMPLES, - SR_CONF_LIMIT_MSEC, - SR_CONF_CONTINUOUS, -}; - -SR_PRIV struct sr_dev_driver colead_slm_driver_info; -static struct sr_dev_driver *di = &colead_slm_driver_info; - -static int init(struct sr_context *sr_ctx) -{ - return std_init(sr_ctx, di, LOG_PREFIX); -} - -static GSList *scan(GSList *options) -{ - struct drv_context *drvc; - struct dev_context *devc; - struct sr_dev_inst *sdi; - struct sr_config *src; - struct sr_channel *ch; - GSList *devices, *l; - const char *conn, *serialcomm; - - drvc = di->priv; - drvc->instances = NULL; - - devices = NULL; - - conn = serialcomm = NULL; - for (l = options; l; l = l->next) { - src = l->data; - switch (src->key) { - case SR_CONF_CONN: - conn = g_variant_get_string(src->data, NULL); - break; - case SR_CONF_SERIALCOMM: - serialcomm = g_variant_get_string(src->data, NULL); - break; - } - } - if (!conn) - return NULL; - if (!serialcomm) - serialcomm = SERIALCOMM; - - if (!(sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, "Colead", - "SL-5868P", NULL))) - return NULL; - - if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) { - sr_dbg("Device context malloc failed."); - return NULL; - } - - if (!(sdi->conn = sr_serial_dev_inst_new(conn, serialcomm))) - return NULL; - - sdi->inst_type = SR_INST_SERIAL; - sdi->priv = devc; - sdi->driver = di; - if (!(ch = sr_channel_new(0, SR_CHANNEL_ANALOG, TRUE, "P1"))) - return NULL; - sdi->channels = g_slist_append(sdi->channels, ch); - drvc->instances = g_slist_append(drvc->instances, sdi); - devices = g_slist_append(devices, sdi); - - return devices; -} - -static GSList *dev_list(void) -{ - return ((struct drv_context *)(di->priv))->instances; -} - -static int dev_open(struct sr_dev_inst *sdi) -{ - struct sr_serial_dev_inst *serial; - - serial = sdi->conn; - if (serial_open(serial, SERIAL_RDWR) != SR_OK) - return SR_ERR; - - sdi->status = SR_ST_ACTIVE; - - return SR_OK; -} - -static int cleanup(void) -{ - return std_dev_clear(di, NULL); -} - -static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc; - - (void)cg; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - if (!(devc = sdi->priv)) { - sr_err("sdi->priv was NULL."); - return SR_ERR_BUG; - } - - switch (id) { - case SR_CONF_LIMIT_MSEC: - /* TODO: not yet implemented */ - if (g_variant_get_uint64(data) == 0) { - sr_err("LIMIT_MSEC can't be 0."); - return SR_ERR; - } - devc->limit_msec = g_variant_get_uint64(data);; - sr_dbg("Setting time limit to %" PRIu64 "ms.", - devc->limit_msec); - break; - case SR_CONF_LIMIT_SAMPLES: - devc->limit_samples = g_variant_get_uint64(data); - sr_dbg("Setting sample limit to %" PRIu64 ".", - devc->limit_samples); - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - (void)sdi; - (void)cg; - - switch (key) { - case SR_CONF_SCAN_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t)); - break; - case SR_CONF_DEVICE_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t)); - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) -{ - struct dev_context *devc; - struct sr_serial_dev_inst *serial; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - if (!(devc = sdi->priv)) { - sr_err("sdi->priv was NULL."); - return SR_ERR_BUG; - } - - devc->cb_data = cb_data; - - /* Send header packet to the session bus. */ - std_session_send_df_header(cb_data, LOG_PREFIX); - - /* Poll every 150ms, or whenever some data comes in. */ - serial = sdi->conn; - serial_source_add(sdi->session, serial, G_IO_IN, 150, - colead_slm_receive_data, (void *)sdi); - - return SR_OK; -} - -static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) -{ - return std_serial_dev_acquisition_stop(sdi, cb_data, std_serial_dev_close, - sdi->conn, LOG_PREFIX); -} - -SR_PRIV struct sr_dev_driver colead_slm_driver_info = { - .name = "colead-slm", - .longname = "Colead SLM", - .api_version = 1, - .init = init, - .cleanup = cleanup, - .scan = scan, - .dev_list = dev_list, - .dev_clear = NULL, - .config_get = NULL, - .config_set = config_set, - .config_list = config_list, - .dev_open = dev_open, - .dev_close = std_serial_dev_close, - .dev_acquisition_start = dev_acquisition_start, - .dev_acquisition_stop = dev_acquisition_stop, - .priv = NULL, -}; diff --git a/hardware/colead-slm/protocol.c b/hardware/colead-slm/protocol.c deleted file mode 100644 index 4abcdd5e..00000000 --- a/hardware/colead-slm/protocol.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2012 Bert Vermeulen - * - * 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 . - */ - -#include -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" -#include "protocol.h" -#include -#include - -static void process_packet(const struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - struct sr_datafeed_packet packet; - struct sr_datafeed_analog analog; - GString *dbg; - float fvalue; - int checksum, mode, i; - - devc = sdi->priv; - if (sr_log_loglevel_get() >= SR_LOG_SPEW) { - dbg = g_string_sized_new(128); - g_string_printf(dbg, "received packet:"); - for (i = 0; i < 10; i++) - g_string_append_printf(dbg, " %.2x", (devc->buf)[i]); - sr_spew("%s", dbg->str); - g_string_free(dbg, TRUE); - } - - if (devc->buf[0] != 0x08 || devc->buf[1] != 0x04) { - sr_dbg("invalid packet header."); - return; - } - - if (devc->buf[8] != 0x01) { - sr_dbg("invalid measurement."); - return; - } - - checksum = 0; - for (i = 0; i < 9; i++) - checksum += devc->buf[i]; - if ((checksum & 0xff) != devc->buf[9]) { - sr_dbg("invalid packet checksum."); - return; - } - - fvalue = 0.0; - for (i = 3; i < 8; i++) { - if (devc->buf[i] > 0x09) - continue; - fvalue *= 10; - fvalue += devc->buf[i]; - } - fvalue /= 10; - - memset(&analog, 0, sizeof(struct sr_datafeed_analog)); - analog.mq = SR_MQ_SOUND_PRESSURE_LEVEL; - analog.unit = SR_UNIT_DECIBEL_SPL; - analog.channels = sdi->channels; - analog.num_samples = 1; - analog.data = &fvalue; - - /* High nibble should only have 0x01 or 0x02. */ - mode = (devc->buf[2] >> 4) & 0x0f; - if (mode == 0x02) - analog.mqflags |= SR_MQFLAG_HOLD; - else if (mode != 0x01) { - sr_dbg("unknown measurement mode 0x%.2x", mode); - return; - } - - /* Low nibble has 14 combinations of direct/long-term average, - * time scale of that average, frequency weighting, and time - * weighting. */ - mode = devc->buf[2] & 0x0f; - switch (mode) { - case 0x0: - analog.mqflags |= SR_MQFLAG_SPL_FREQ_WEIGHT_A \ - | SR_MQFLAG_SPL_TIME_WEIGHT_F; - break; - case 0x1: - analog.mqflags |= SR_MQFLAG_SPL_FREQ_WEIGHT_A \ - | SR_MQFLAG_SPL_TIME_WEIGHT_S; - break; - case 0x2: - analog.mqflags |= SR_MQFLAG_SPL_FREQ_WEIGHT_C \ - | SR_MQFLAG_SPL_TIME_WEIGHT_F; - break; - case 0x3: - analog.mqflags |= SR_MQFLAG_SPL_FREQ_WEIGHT_C \ - | SR_MQFLAG_SPL_TIME_WEIGHT_S; - break; - case 0x4: - analog.mqflags |= SR_MQFLAG_SPL_FREQ_WEIGHT_FLAT \ - | SR_MQFLAG_SPL_TIME_WEIGHT_F; - break; - case 0x5: - analog.mqflags |= SR_MQFLAG_SPL_FREQ_WEIGHT_FLAT \ - | SR_MQFLAG_SPL_TIME_WEIGHT_S; - break; - case 0x6: - analog.mqflags |= SR_MQFLAG_SPL_PCT_OVER_ALARM \ - | SR_MQFLAG_SPL_FREQ_WEIGHT_A \ - | SR_MQFLAG_SPL_TIME_WEIGHT_F; - break; - case 0x7: - analog.mqflags |= SR_MQFLAG_SPL_PCT_OVER_ALARM \ - | SR_MQFLAG_SPL_FREQ_WEIGHT_A \ - | SR_MQFLAG_SPL_TIME_WEIGHT_S; - break; - case 0x8: - /* 10-second mean, but we don't have MQ flags to express it. */ - analog.mqflags |= SR_MQFLAG_SPL_LAT \ - | SR_MQFLAG_SPL_FREQ_WEIGHT_A \ - | SR_MQFLAG_SPL_TIME_WEIGHT_F; - break; - case 0x9: - /* Mean over a time period between 11 seconds and 24 hours. - * Which is so silly that there's no point in expressing - * either this or the previous case. */ - analog.mqflags |= SR_MQFLAG_SPL_LAT \ - | SR_MQFLAG_SPL_FREQ_WEIGHT_A \ - | SR_MQFLAG_SPL_TIME_WEIGHT_F; - break; - case 0xa: - /* 10-second mean. */ - analog.mqflags |= SR_MQFLAG_SPL_LAT \ - | SR_MQFLAG_SPL_FREQ_WEIGHT_A \ - | SR_MQFLAG_SPL_TIME_WEIGHT_S; - break; - case 0xb: - /* Mean over a time period between 11 seconds and 24 hours. */ - analog.mqflags |= SR_MQFLAG_SPL_LAT \ - | SR_MQFLAG_SPL_FREQ_WEIGHT_A \ - | SR_MQFLAG_SPL_TIME_WEIGHT_S; - break; - case 0xc: - /* Internal calibration on 1kHz sine at 94dB, not useful - * to anything but the device. */ - analog.mqflags |= SR_MQFLAG_SPL_FREQ_WEIGHT_FLAT; - break; - case 0xd: - /* Internal calibration on 1kHz sine at 94dB, not useful - * to anything but the device. */ - analog.mqflags |= SR_MQFLAG_SPL_FREQ_WEIGHT_FLAT; - break; - default: - sr_dbg("unknown configuration 0x%.2x", mode); - return; - break; - } - - packet.type = SR_DF_ANALOG; - packet.payload = &analog; - sr_session_send(devc->cb_data, &packet); - - devc->num_samples++; - -} - -SR_PRIV int colead_slm_receive_data(int fd, int revents, void *cb_data) -{ - const struct sr_dev_inst *sdi; - struct dev_context *devc; - struct sr_serial_dev_inst *serial; - int len; - char buf[128]; - - (void)fd; - - if (!(sdi = cb_data)) - return TRUE; - - if (!(devc = sdi->priv)) - return TRUE; - - if (revents != G_IO_IN) - /* Timeout event. */ - return TRUE; - - serial = sdi->conn; - if (devc->state == IDLE) { - if (serial_read(serial, buf, 128) != 1 || buf[0] != 0x10) - /* Nothing there, or caught the tail end of a previous packet, - * or some garbage. Unless it's a single "data ready" byte, - * we don't want it. */ - return TRUE; - /* Got 0x10, "measurement ready". */ - if (serial_write(serial, "\x20", 1) == -1) - sr_err("unable to send command: %s", strerror(errno)); - else { - devc->state = COMMAND_SENT; - devc->buflen = 0; - } - } else { - len = serial_read(serial, devc->buf + devc->buflen, - 10 - devc->buflen); - if (len < 1) - return TRUE; - devc->buflen += len; - if (devc->buflen > 10) { - sr_dbg("buffer overrun"); - devc->state = IDLE; - return TRUE; - } - if (devc->buflen == 10) { - /* If we got here, we're sure the device sent a "data ready" - * notification, we asked for data, and got it. */ - process_packet(sdi); - devc->state = IDLE; - } - } - - return TRUE; -} diff --git a/hardware/colead-slm/protocol.h b/hardware/colead-slm/protocol.h deleted file mode 100644 index 8942ac85..00000000 --- a/hardware/colead-slm/protocol.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2012 Bert Vermeulen - * - * 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 . - */ - -#ifndef LIBSIGROK_HARDWARE_COLEAD_SLM_PROTOCOL_H -#define LIBSIGROK_HARDWARE_COLEAD_SLM_PROTOCOL_H - -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#define LOG_PREFIX "colead-slm" - -enum { - IDLE, - COMMAND_SENT, -}; - -/** Private, per-device-instance driver context. */ -struct dev_context { - /** The current sampling limit (in number of samples). */ - uint64_t limit_samples; - - /** The current sampling limit (in ms). */ - uint64_t limit_msec; - - /** Opaque pointer passed in by the frontend. */ - void *cb_data; - - /** The current number of already received samples. */ - uint64_t num_samples; - int state; - char buf[10]; - int buflen; -}; - -SR_PRIV int colead_slm_receive_data(int fd, int revents, void *cb_data); - -#endif diff --git a/hardware/common/dmm/es519xx.c b/hardware/common/dmm/es519xx.c deleted file mode 100644 index 075587ce..00000000 --- a/hardware/common/dmm/es519xx.c +++ /dev/null @@ -1,828 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2012 Uwe Hermann - * Copyright (C) 2013 Aurelien Jacobs - * - * 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 - */ - -/* - * Cyrustek ES519XX protocol parser. - * - * Communication parameters: Unidirectional, 2400/7o1 or 19230/7o1 - */ - -#include -#include -#include -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#define LOG_PREFIX "es519xx" - -/* Factors for the respective measurement mode (0 means "invalid"). */ -static const float factors_2400_11b[9][8] = { - {1e-4, 1e-3, 1e-2, 1e-1, 1, 0, 0, 0 }, /* V */ - {1e-7, 1e-6, 0, 0, 0, 0, 0, 0 }, /* uA */ - {1e-5, 1e-4, 0, 0, 0, 0, 0, 0 }, /* mA */ - {1e-2, 0, 0, 0, 0, 0, 0, 0 }, /* A */ - {1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 0, 0 }, /* RPM */ - {1e-1, 1, 1e1, 1e2, 1e3, 1e4, 0, 0 }, /* Resistance */ - {1, 1e1, 1e2, 1e3, 1e4, 1e5, 0, 0 }, /* Frequency */ - {1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5}, /* Capacitance */ - {1e-3, 0, 0, 0, 0, 0, 0, 0 }, /* Diode */ -}; -static const float factors_19200_11b_5digits[9][8] = { - {1e-4, 1e-3, 1e-2, 1e-1, 1e-5, 0, 0, 0}, /* V */ - {1e-8, 1e-7, 0, 0, 0, 0, 0, 0}, /* uA */ - {1e-6, 1e-5, 0, 0, 0, 0, 0, 0}, /* mA */ - {0, 1e-3, 0, 0, 0, 0, 0, 0}, /* A */ - {1e-4, 1e-3, 1e-2, 1e-1, 1, 0, 0, 0}, /* Manual A */ - {1e-2, 1e-1, 1, 1e1, 1e2, 1e3, 1e4, 0}, /* Resistance */ - {1e-1, 0, 1, 1e1, 1e2, 1e3, 1e4, 0}, /* Frequency */ - {1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5}, /* Capacitance */ - {1e-4, 0, 0, 0, 0, 0, 0, 0 }, /* Diode */ -}; -static const float factors_19200_11b_clampmeter[9][8] = { - {1e-3, 1e-2, 1e-1, 1, 1e-4, 0, 0, 0}, /* V */ - {1e-7, 1e-6, 0, 0, 0, 0, 0, 0}, /* uA */ - {1e-5, 1e-4, 0, 0, 0, 0, 0, 0}, /* mA */ - {1e-2, 0, 0, 0, 0, 0, 0, 0}, /* A */ - {1e-3, 1e-2, 1e-1, 1, 0, 0, 0, 0}, /* Manual A */ - {1e-1, 1, 1e1, 1e2, 1e3, 1e4, 0, 0}, /* Resistance */ - {1e-1, 0, 1, 1e1, 1e2, 1e3, 1e4, 0}, /* Frequency */ - {1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5}, /* Capacitance */ - {1e-3, 0, 0, 0, 0, 0, 0, 0 }, /* Diode */ -}; -static const float factors_19200_11b[9][8] = { - {1e-3, 1e-2, 1e-1, 1, 1e-4, 0, 0, 0}, /* V */ - {1e-7, 1e-6, 0, 0, 0, 0, 0, 0}, /* uA */ - {1e-5, 1e-4, 0, 0, 0, 0, 0, 0}, /* mA */ - {1e-3, 1e-2, 0, 0, 0, 0, 0, 0}, /* A */ - {0, 0, 0, 0, 0, 0, 0, 0}, /* Manual A */ - {1e-1, 1, 1e1, 1e2, 1e3, 1e4, 0, 0}, /* Resistance */ - {1, 1e1, 1e2, 1e3, 1e4, 0, 0, 0}, /* Frequency */ - {1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 0}, /* Capacitance */ - {1e-3, 0, 0, 0, 0, 0, 0, 0}, /* Diode */ -}; -static const float factors_19200_14b[9][8] = { - {1e-4, 1e-3, 1e-2, 1e-1, 1e-5, 0, 0, 0}, /* V */ - {1e-8, 1e-7, 0, 0, 0, 0, 0, 0}, /* uA */ - {1e-6, 1e-5, 0, 0, 0, 0, 0, 0}, /* mA */ - {1e-3, 0, 0, 0, 0, 0, 0, 0}, /* A */ - {1e-4, 1e-3, 1e-2, 1e-1, 1, 0, 0, 0}, /* Manual A */ - {1e-2, 1e-1, 1, 1e1, 1e2, 1e3, 1e4, 0}, /* Resistance */ - {1e-2, 1e-1, 0, 1, 1e1, 1e2, 1e3, 1e4}, /* Frequency */ - {1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5}, /* Capacitance */ - {1e-4, 0, 0, 0, 0, 0, 0, 0 }, /* Diode */ -}; - -static int parse_value(const uint8_t *buf, struct es519xx_info *info, - float *result) -{ - int i, intval, num_digits; - float floatval; - - num_digits = 4 + ((info->packet_size == 14) ? 1 : 0); - - /* Bytes 1-4 (or 5): Value (4 or 5 decimal digits) */ - if (info->is_ol) { - sr_spew("Over limit."); - *result = INFINITY; - return SR_OK; - } else if (info->is_ul) { - sr_spew("Under limit."); - *result = INFINITY; - return SR_OK; - } else if (!isdigit(buf[1]) || !isdigit(buf[2]) || - !isdigit(buf[3]) || !isdigit(buf[4]) || - (num_digits == 5 && !isdigit(buf[5]))) { - sr_dbg("Value contained invalid digits: %02x %02x %02x %02x " - "(%c %c %c %c).", buf[1], buf[2], buf[3], buf[4], - buf[1], buf[2], buf[3], buf[4]); - return SR_ERR; - } - intval = (info->is_digit4) ? 1 : 0; - for (i = 0; i < num_digits; i++) - intval = 10 * intval + (buf[i + 1] - '0'); - - /* Apply sign. */ - intval *= info->is_sign ? -1 : 1; - - floatval = (float)intval; - - /* Note: The decimal point position will be parsed later. */ - - sr_spew("The display value is %f.", floatval); - - *result = floatval; - - return SR_OK; -} - -static int parse_range(uint8_t b, float *floatval, - const struct es519xx_info *info) -{ - int idx, mode; - float factor = 0; - - idx = b - '0'; - - if (idx < 0 || idx > 7) { - sr_dbg("Invalid range byte / index: 0x%02x / 0x%02x.", b, idx); - return SR_ERR; - } - - /* Parse range byte (depends on the measurement mode). */ - if (info->is_voltage) - mode = 0; /* V */ - else if (info->is_current && info->is_micro) - mode = 1; /* uA */ - else if (info->is_current && info->is_milli) - mode = 2; /* mA */ - else if (info->is_current && info->is_auto) - mode = 3; /* A */ - else if (info->is_current && !info->is_auto) - mode = 4; /* Manual A */ - else if (info->is_rpm) - /* Not a typo, it's really index 4 in factors_2400_11b[][]. */ - mode = 4; /* RPM */ - else if (info->is_resistance || info->is_continuity) - mode = 5; /* Resistance */ - else if (info->is_frequency) - mode = 6; /* Frequency */ - else if (info->is_capacitance) - mode = 7; /* Capacitance */ - else if (info->is_diode) - mode = 8; /* Diode */ - else if (info->is_duty_cycle) - mode = 0; /* Dummy, unused */ - else { - sr_dbg("Invalid mode, range byte was: 0x%02x.", b); - return SR_ERR; - } - - if (info->is_vbar) { - if (info->is_micro) - factor = (const float[]){1e-1, 1}[idx]; - else if (info->is_milli) - factor = (const float[]){1e-2, 1e-1}[idx]; - } - else if (info->is_duty_cycle) - factor = 1e-1; - else if (info->baudrate == 2400) - factor = factors_2400_11b[mode][idx]; - else if (info->fivedigits) - factor = factors_19200_11b_5digits[mode][idx]; - else if (info->clampmeter) - factor = factors_19200_11b_clampmeter[mode][idx]; - else if (info->packet_size == 11) - factor = factors_19200_11b[mode][idx]; - else if (info->packet_size == 14) - factor = factors_19200_14b[mode][idx]; - - if (factor == 0) { - sr_dbg("Invalid factor for range byte: 0x%02x.", b); - return SR_ERR; - } - - /* Apply respective factor (mode-dependent) on the value. */ - *floatval *= factor; - sr_dbg("Applying factor %f, new value is %f.", factor, *floatval); - - return SR_OK; -} - -static void parse_flags(const uint8_t *buf, struct es519xx_info *info) -{ - int function, status; - - function = 5 + ((info->packet_size == 14) ? 1 : 0); - status = function + 1; - - /* Status byte */ - if (info->alt_functions) { - info->is_sign = (buf[status] & (1 << 3)) != 0; - info->is_batt = (buf[status] & (1 << 2)) != 0; /* Bat. low */ - info->is_ol = (buf[status] & (1 << 1)) != 0; /* Overflow */ - info->is_ol |= (buf[status] & (1 << 0)) != 0; /* Overflow */ - } else { - info->is_judge = (buf[status] & (1 << 3)) != 0; - info->is_sign = (buf[status] & (1 << 2)) != 0; - info->is_batt = (buf[status] & (1 << 1)) != 0; /* Bat. low */ - info->is_ol = (buf[status] & (1 << 0)) != 0; /* Overflow */ - } - - if (info->packet_size == 14) { - /* Option 1 byte */ - info->is_max = (buf[8] & (1 << 3)) != 0; - info->is_min = (buf[8] & (1 << 2)) != 0; - info->is_rel = (buf[8] & (1 << 1)) != 0; - info->is_rmr = (buf[8] & (1 << 0)) != 0; - - /* Option 2 byte */ - info->is_ul = (buf[9] & (1 << 3)) != 0; /* Underflow */ - info->is_pmax = (buf[9] & (1 << 2)) != 0; /* Max. peak value */ - info->is_pmin = (buf[9] & (1 << 1)) != 0; /* Min. peak value */ - - /* Option 3 byte */ - info->is_dc = (buf[10] & (1 << 3)) != 0; - info->is_ac = (buf[10] & (1 << 2)) != 0; - info->is_auto = (buf[10] & (1 << 1)) != 0; - info->is_vahz = (buf[10] & (1 << 0)) != 0; - - /* LPF: Low-pass filter(s) */ - if (info->selectable_lpf) { - /* Option 4 byte */ - info->is_hold = (buf[11] & (1 << 3)) != 0; - info->is_vbar = (buf[11] & (1 << 2)) != 0; - info->is_lpf1 = (buf[11] & (1 << 1)) != 0; - info->is_lpf0 = (buf[11] & (1 << 0)) != 0; - } else { - /* Option 4 byte */ - info->is_vbar = (buf[11] & (1 << 2)) != 0; - info->is_hold = (buf[11] & (1 << 1)) != 0; - info->is_lpf1 = (buf[11] & (1 << 0)) != 0; - } - } else if (info->alt_functions) { - /* Option 2 byte */ - info->is_dc = (buf[8] & (1 << 3)) != 0; - info->is_auto = (buf[8] & (1 << 2)) != 0; - info->is_apo = (buf[8] & (1 << 0)) != 0; - info->is_ac = !info->is_dc; - } else { - /* Option 1 byte */ - if (info->baudrate == 2400) { - info->is_pmax = (buf[7] & (1 << 3)) != 0; - info->is_pmin = (buf[7] & (1 << 2)) != 0; - info->is_vahz = (buf[7] & (1 << 0)) != 0; - } else if (info->fivedigits) { - info->is_ul = (buf[7] & (1 << 3)) != 0; - info->is_pmax = (buf[7] & (1 << 2)) != 0; - info->is_pmin = (buf[7] & (1 << 1)) != 0; - info->is_digit4 = (buf[7] & (1 << 0)) != 0; - } else if (info->clampmeter) { - info->is_ul = (buf[7] & (1 << 3)) != 0; - info->is_vasel = (buf[7] & (1 << 2)) != 0; - info->is_vbar = (buf[7] & (1 << 1)) != 0; - } else { - info->is_hold = (buf[7] & (1 << 3)) != 0; - info->is_max = (buf[7] & (1 << 2)) != 0; - info->is_min = (buf[7] & (1 << 1)) != 0; - } - - /* Option 2 byte */ - info->is_dc = (buf[8] & (1 << 3)) != 0; - info->is_ac = (buf[8] & (1 << 2)) != 0; - info->is_auto = (buf[8] & (1 << 1)) != 0; - if (info->baudrate == 2400) - info->is_apo = (buf[8] & (1 << 0)) != 0; - else - info->is_vahz = (buf[8] & (1 << 0)) != 0; - } - - /* Function byte */ - if (info->alt_functions) { - switch (buf[function]) { - case 0x3f: /* A */ - info->is_current = info->is_auto = TRUE; - break; - case 0x3e: /* uA */ - info->is_current = info->is_micro = info->is_auto = TRUE; - break; - case 0x3d: /* mA */ - info->is_current = info->is_milli = info->is_auto = TRUE; - break; - case 0x3c: /* V */ - info->is_voltage = TRUE; - break; - case 0x37: /* Resistance */ - info->is_resistance = TRUE; - break; - case 0x36: /* Continuity */ - info->is_continuity = TRUE; - break; - case 0x3b: /* Diode */ - info->is_diode = TRUE; - break; - case 0x3a: /* Frequency */ - info->is_frequency = TRUE; - break; - case 0x34: /* ADP0 */ - case 0x35: /* ADP0 */ - info->is_adp0 = TRUE; - break; - case 0x38: /* ADP1 */ - case 0x39: /* ADP1 */ - info->is_adp1 = TRUE; - break; - case 0x32: /* ADP2 */ - case 0x33: /* ADP2 */ - info->is_adp2 = TRUE; - break; - case 0x30: /* ADP3 */ - case 0x31: /* ADP3 */ - info->is_adp3 = TRUE; - break; - default: - sr_dbg("Invalid function byte: 0x%02x.", buf[function]); - break; - } - } else { - /* Note: Some of these mappings are fixed up later. */ - switch (buf[function]) { - case 0x3b: /* V */ - info->is_voltage = TRUE; - break; - case 0x3d: /* uA */ - info->is_current = info->is_micro = info->is_auto = TRUE; - break; - case 0x3f: /* mA */ - info->is_current = info->is_milli = info->is_auto = TRUE; - break; - case 0x30: /* A */ - info->is_current = info->is_auto = TRUE; - break; - case 0x39: /* Manual A */ - info->is_current = TRUE; - info->is_auto = FALSE; /* Manual mode */ - break; - case 0x33: /* Resistance */ - info->is_resistance = TRUE; - break; - case 0x35: /* Continuity */ - info->is_continuity = TRUE; - break; - case 0x31: /* Diode */ - info->is_diode = TRUE; - break; - case 0x32: /* Frequency / RPM / duty cycle */ - if (info->packet_size == 14) { - if (info->is_judge) - info->is_duty_cycle = TRUE; - else - info->is_frequency = TRUE; - } else { - if (info->is_judge) - info->is_rpm = TRUE; - else - info->is_frequency = TRUE; - } - break; - case 0x36: /* Capacitance */ - info->is_capacitance = TRUE; - break; - case 0x34: /* Temperature */ - info->is_temperature = TRUE; - if (info->is_judge) - info->is_celsius = TRUE; - else - info->is_fahrenheit = TRUE; - /* IMPORTANT: The digits always represent Celsius! */ - break; - case 0x3e: /* ADP0 */ - info->is_adp0 = TRUE; - break; - case 0x3c: /* ADP1 */ - info->is_adp1 = TRUE; - break; - case 0x38: /* ADP2 */ - info->is_adp2 = TRUE; - break; - case 0x3a: /* ADP3 */ - info->is_adp3 = TRUE; - break; - default: - sr_dbg("Invalid function byte: 0x%02x.", buf[function]); - break; - } - } - - if (info->is_vahz && (info->is_voltage || info->is_current)) { - info->is_voltage = FALSE; - info->is_current = FALSE; - info->is_milli = info->is_micro = FALSE; - if (info->packet_size == 14) { - if (info->is_judge) - info->is_duty_cycle = TRUE; - else - info->is_frequency = TRUE; - } else { - if (info->is_judge) - info->is_rpm = TRUE; - else - info->is_frequency = TRUE; - } - } - - if (info->is_current && (info->is_micro || info->is_milli) && info->is_vasel) { - info->is_current = info->is_auto = FALSE; - info->is_voltage = TRUE; - } - - if (info->baudrate == 2400) { - /* Inverted mapping between mA and A, and no manual A. */ - if (info->is_current && (info->is_milli || !info->is_auto)) { - info->is_milli = !info->is_milli; - info->is_auto = TRUE; - } - } -} - -static void handle_flags(struct sr_datafeed_analog *analog, - float *floatval, const struct es519xx_info *info) -{ - /* - * Note: is_micro etc. are not used directly to multiply/divide - * floatval, this is handled via parse_range() and factors[][]. - */ - - /* Measurement modes */ - if (info->is_voltage) { - analog->mq = SR_MQ_VOLTAGE; - analog->unit = SR_UNIT_VOLT; - } - if (info->is_current) { - analog->mq = SR_MQ_CURRENT; - analog->unit = SR_UNIT_AMPERE; - } - if (info->is_resistance) { - analog->mq = SR_MQ_RESISTANCE; - analog->unit = SR_UNIT_OHM; - } - if (info->is_frequency) { - analog->mq = SR_MQ_FREQUENCY; - analog->unit = SR_UNIT_HERTZ; - } - if (info->is_capacitance) { - analog->mq = SR_MQ_CAPACITANCE; - analog->unit = SR_UNIT_FARAD; - } - if (info->is_temperature && info->is_celsius) { - analog->mq = SR_MQ_TEMPERATURE; - analog->unit = SR_UNIT_CELSIUS; - } - if (info->is_temperature && info->is_fahrenheit) { - analog->mq = SR_MQ_TEMPERATURE; - analog->unit = SR_UNIT_FAHRENHEIT; - } - if (info->is_continuity) { - analog->mq = SR_MQ_CONTINUITY; - analog->unit = SR_UNIT_BOOLEAN; - *floatval = (*floatval < 0.0 || *floatval > 25.0) ? 0.0 : 1.0; - } - if (info->is_diode) { - analog->mq = SR_MQ_VOLTAGE; - analog->unit = SR_UNIT_VOLT; - } - if (info->is_rpm) { - analog->mq = SR_MQ_FREQUENCY; - analog->unit = SR_UNIT_REVOLUTIONS_PER_MINUTE; - } - if (info->is_duty_cycle) { - analog->mq = SR_MQ_DUTY_CYCLE; - analog->unit = SR_UNIT_PERCENTAGE; - } - - /* Measurement related flags */ - if (info->is_ac) - analog->mqflags |= SR_MQFLAG_AC; - if (info->is_dc) - analog->mqflags |= SR_MQFLAG_DC; - if (info->is_auto) - analog->mqflags |= SR_MQFLAG_AUTORANGE; - if (info->is_diode) - analog->mqflags |= SR_MQFLAG_DIODE; - if (info->is_hold) - /* - * Note: HOLD only affects the number displayed on the LCD, - * but not the value sent via the protocol! It also does not - * affect the bargraph on the LCD. - */ - analog->mqflags |= SR_MQFLAG_HOLD; - if (info->is_max) - analog->mqflags |= SR_MQFLAG_MAX; - if (info->is_min) - analog->mqflags |= SR_MQFLAG_MIN; - if (info->is_rel) - analog->mqflags |= SR_MQFLAG_RELATIVE; - - /* Other flags */ - if (info->is_judge) - sr_spew("Judge bit is set."); - if (info->is_batt) - sr_spew("Battery is low."); - if (info->is_ol) - sr_spew("Input overflow."); - if (info->is_ul) - sr_spew("Input underflow."); - if (info->is_pmax) - sr_spew("pMAX active, LCD shows max. peak value."); - if (info->is_pmin) - sr_spew("pMIN active, LCD shows min. peak value."); - if (info->is_vahz) - sr_spew("VAHZ active."); - if (info->is_apo) - sr_spew("Auto-Power-Off enabled."); - if (info->is_vbar) - sr_spew("VBAR active."); - if ((!info->selectable_lpf && info->is_lpf1) || - (info->selectable_lpf && (!info->is_lpf0 || !info->is_lpf1))) - sr_spew("Low-pass filter feature is active."); -} - -static gboolean flags_valid(const struct es519xx_info *info) -{ - int count; - - /* Does the packet have more than one multiplier? */ - count = (info->is_micro) ? 1 : 0; - count += (info->is_milli) ? 1 : 0; - if (count > 1) { - sr_dbg("More than one multiplier detected in packet."); - return FALSE; - } - - /* Does the packet "measure" more than one type of value? */ - count = (info->is_voltage) ? 1 : 0; - count += (info->is_current) ? 1 : 0; - count += (info->is_resistance) ? 1 : 0; - count += (info->is_frequency) ? 1 : 0; - count += (info->is_capacitance) ? 1 : 0; - count += (info->is_temperature) ? 1 : 0; - count += (info->is_continuity) ? 1 : 0; - count += (info->is_diode) ? 1 : 0; - count += (info->is_rpm) ? 1 : 0; - if (count > 1) { - sr_dbg("More than one measurement type detected in packet."); - return FALSE; - } - - /* Both AC and DC set? */ - if (info->is_ac && info->is_dc) { - sr_dbg("Both AC and DC flags detected in packet."); - return FALSE; - } - - return TRUE; -} - -static gboolean sr_es519xx_packet_valid(const uint8_t *buf, - struct es519xx_info *info) -{ - int s; - - s = info->packet_size; - - if (s == 11 && memcmp(buf, buf + s, s)) - return FALSE; - - if (buf[s - 2] != '\r' || buf[s - 1] != '\n') - return FALSE; - - parse_flags(buf, info); - - if (!flags_valid(info)) - return FALSE; - - return TRUE; -} - -static int sr_es519xx_parse(const uint8_t *buf, float *floatval, - struct sr_datafeed_analog *analog, - struct es519xx_info *info) -{ - int ret; - - if (!sr_es519xx_packet_valid(buf, info)) - return SR_ERR; - - if ((ret = parse_value(buf, info, floatval)) != SR_OK) { - sr_dbg("Error parsing value: %d.", ret); - return ret; - } - - if ((ret = parse_range(buf[0], floatval, info)) != SR_OK) - return ret; - - handle_flags(analog, floatval, info); - return SR_OK; -} - -/* - * Functions for 2400 baud / 11 bytes protocols. - * This includes ES51962, ES51971, ES51972, ES51978 and ES51989. - */ -SR_PRIV gboolean sr_es519xx_2400_11b_packet_valid(const uint8_t *buf) -{ - struct es519xx_info info; - - memset(&info, 0, sizeof(struct es519xx_info)); - info.baudrate = 2400; - info.packet_size = 11; - - return sr_es519xx_packet_valid(buf, &info); -} - -SR_PRIV int sr_es519xx_2400_11b_parse(const uint8_t *buf, float *floatval, - struct sr_datafeed_analog *analog, void *info) -{ - struct es519xx_info *info_local; - - info_local = info; - memset(info_local, 0, sizeof(struct es519xx_info)); - info_local->baudrate = 2400; - info_local->packet_size = 11; - - return sr_es519xx_parse(buf, floatval, analog, info); -} - -/* - * Functions for 2400 baud / 11 byte protocols. - * This includes ES51960, ES51977 and ES51988. - */ -SR_PRIV gboolean sr_es519xx_2400_11b_altfn_packet_valid(const uint8_t *buf) -{ - struct es519xx_info info; - - memset(&info, 0, sizeof(struct es519xx_info)); - info.baudrate = 2400; - info.packet_size = 11; - info.alt_functions = TRUE; - - return sr_es519xx_packet_valid(buf, &info); -} - -SR_PRIV int sr_es519xx_2400_11b_altfn_parse(const uint8_t *buf, - float *floatval, struct sr_datafeed_analog *analog, void *info) -{ - struct es519xx_info *info_local; - - info_local = info; - memset(info_local, 0, sizeof(struct es519xx_info)); - info_local->baudrate = 2400; - info_local->packet_size = 11; - info_local->alt_functions = TRUE; - - return sr_es519xx_parse(buf, floatval, analog, info); -} - -/* - * Functions for 19200 baud / 11 bytes protocols with 5 digits display. - * This includes ES51911, ES51916 and ES51918. - */ -SR_PRIV gboolean sr_es519xx_19200_11b_5digits_packet_valid(const uint8_t *buf) -{ - struct es519xx_info info; - - memset(&info, 0, sizeof(struct es519xx_info)); - info.baudrate = 19200; - info.packet_size = 11; - info.fivedigits = TRUE; - - return sr_es519xx_packet_valid(buf, &info); -} - -SR_PRIV int sr_es519xx_19200_11b_5digits_parse(const uint8_t *buf, - float *floatval, struct sr_datafeed_analog *analog, void *info) -{ - struct es519xx_info *info_local; - - info_local = info; - memset(info_local, 0, sizeof(struct es519xx_info)); - info_local->baudrate = 19200; - info_local->packet_size = 11; - info_local->fivedigits = TRUE; - - return sr_es519xx_parse(buf, floatval, analog, info); -} - -/* - * Functions for 19200 baud / 11 bytes protocols with clamp meter support. - * This includes ES51967 and ES51969. - */ -SR_PRIV gboolean sr_es519xx_19200_11b_clamp_packet_valid(const uint8_t *buf) -{ - struct es519xx_info info; - - memset(&info, 0, sizeof(struct es519xx_info)); - info.baudrate = 19200; - info.packet_size = 11; - info.clampmeter = TRUE; - - return sr_es519xx_packet_valid(buf, &info); -} - -SR_PRIV int sr_es519xx_19200_11b_clamp_parse(const uint8_t *buf, - float *floatval, struct sr_datafeed_analog *analog, void *info) -{ - struct es519xx_info *info_local; - - info_local = info; - memset(info_local, 0, sizeof(struct es519xx_info)); - info_local->baudrate = 19200; - info_local->packet_size = 11; - info_local->clampmeter = TRUE; - - return sr_es519xx_parse(buf, floatval, analog, info); -} - -/* - * Functions for 19200 baud / 11 bytes protocols. - * This includes ES51981, ES51982, ES51983, ES51984 and ES51986. - */ -SR_PRIV gboolean sr_es519xx_19200_11b_packet_valid(const uint8_t *buf) -{ - struct es519xx_info info; - - memset(&info, 0, sizeof(struct es519xx_info)); - info.baudrate = 19200; - info.packet_size = 11; - - return sr_es519xx_packet_valid(buf, &info); -} - -SR_PRIV int sr_es519xx_19200_11b_parse(const uint8_t *buf, float *floatval, - struct sr_datafeed_analog *analog, void *info) -{ - struct es519xx_info *info_local; - - info_local = info; - memset(info_local, 0, sizeof(struct es519xx_info)); - info_local->baudrate = 19200; - info_local->packet_size = 11; - - return sr_es519xx_parse(buf, floatval, analog, info); -} - -/* - * Functions for 19200 baud / 14 bytes protocols. - * This includes ES51921 and ES51922. - */ -SR_PRIV gboolean sr_es519xx_19200_14b_packet_valid(const uint8_t *buf) -{ - struct es519xx_info info; - - memset(&info, 0, sizeof(struct es519xx_info)); - info.baudrate = 19200; - info.packet_size = 14; - - return sr_es519xx_packet_valid(buf, &info); -} - -SR_PRIV int sr_es519xx_19200_14b_parse(const uint8_t *buf, float *floatval, - struct sr_datafeed_analog *analog, void *info) -{ - struct es519xx_info *info_local; - - info_local = info; - memset(info_local, 0, sizeof(struct es519xx_info)); - info_local->baudrate = 19200; - info_local->packet_size = 14; - - return sr_es519xx_parse(buf, floatval, analog, info); -} - -/* - * Functions for 19200 baud / 14 bytes protocols with selectable LPF. - * This includes ES51931 and ES51932. - */ -SR_PRIV gboolean sr_es519xx_19200_14b_sel_lpf_packet_valid(const uint8_t *buf) -{ - struct es519xx_info info; - - memset(&info, 0, sizeof(struct es519xx_info)); - info.baudrate = 19200; - info.packet_size = 14; - info.selectable_lpf = TRUE; - - return sr_es519xx_packet_valid(buf, &info); -} - -SR_PRIV int sr_es519xx_19200_14b_sel_lpf_parse(const uint8_t *buf, - float *floatval, struct sr_datafeed_analog *analog, void *info) -{ - struct es519xx_info *info_local; - - info_local = info; - memset(info_local, 0, sizeof(struct es519xx_info)); - info_local->baudrate = 19200; - info_local->packet_size = 14; - info_local->selectable_lpf = TRUE; - - return sr_es519xx_parse(buf, floatval, analog, info); -} diff --git a/hardware/common/dmm/fs9721.c b/hardware/common/dmm/fs9721.c deleted file mode 100644 index f3101f8b..00000000 --- a/hardware/common/dmm/fs9721.c +++ /dev/null @@ -1,445 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2012 Uwe Hermann - * Copyright (C) 2012 Alexandru Gagniuc - * - * 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 - */ - -/* - * Fortune Semiconductor FS9721_LP3/FS9721B protocol parser. - * - * FS9721_LP3: 4000 counts (3 3/4 digits) - * FS9721B/Q100: 2400 counts (3 2/3 digits) - * - * Same for both chips: - * - Packages: Bare die (78 pins) or QFP-100 - * - Communication parameters: Unidirectional, 2400/8n1 - * - The protocol seems to be exactly the same. - */ - -#include -#include -#include -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#define LOG_PREFIX "fs9721" - -static int parse_digit(uint8_t b) -{ - switch (b) { - case 0x7d: - return 0; - case 0x05: - return 1; - case 0x5b: - return 2; - case 0x1f: - return 3; - case 0x27: - return 4; - case 0x3e: - return 5; - case 0x7e: - return 6; - case 0x15: - return 7; - case 0x7f: - return 8; - case 0x3f: - return 9; - default: - sr_dbg("Invalid digit byte: 0x%02x.", b); - return -1; - } -} - -static gboolean sync_nibbles_valid(const uint8_t *buf) -{ - int i; - - /* Check the synchronization nibbles, and make sure they all match. */ - for (i = 0; i < FS9721_PACKET_SIZE; i++) { - if (((buf[i] >> 4) & 0x0f) != (i + 1)) { - sr_dbg("Sync nibble in byte %d (0x%02x) is invalid.", - i, buf[i]); - return FALSE; - } - } - - return TRUE; -} - -static gboolean flags_valid(const struct fs9721_info *info) -{ - int count; - - /* Does the packet have more than one multiplier? */ - count = 0; - count += (info->is_nano) ? 1 : 0; - count += (info->is_micro) ? 1 : 0; - count += (info->is_milli) ? 1 : 0; - count += (info->is_kilo) ? 1 : 0; - count += (info->is_mega) ? 1 : 0; - if (count > 1) { - sr_dbg("More than one multiplier detected in packet."); - return FALSE; - } - - /* Does the packet "measure" more than one type of value? */ - count = 0; - count += (info->is_hz) ? 1 : 0; - count += (info->is_ohm) ? 1 : 0; - count += (info->is_farad) ? 1 : 0; - count += (info->is_ampere) ? 1 : 0; - count += (info->is_volt) ? 1 : 0; - count += (info->is_percent) ? 1 : 0; - if (count > 1) { - sr_dbg("More than one measurement type detected in packet."); - return FALSE; - } - - /* Both AC and DC set? */ - if (info->is_ac && info->is_dc) { - sr_dbg("Both AC and DC flags detected in packet."); - return FALSE; - } - - /* RS232 flag not set? */ - if (!info->is_rs232) { - sr_dbg("No RS232 flag detected in packet."); - return FALSE; - } - - return TRUE; -} - -static int parse_value(const uint8_t *buf, float *result) -{ - int i, sign, intval = 0, digits[4]; - uint8_t digit_bytes[4]; - float floatval; - - /* Byte 1: LCD SEG2 */ - sign = ((buf[1] & (1 << 3)) != 0) ? -1 : 1; - - /* - * Bytes 1-8: Value (4 decimal digits, sign, decimal point) - * - * Over limit: "0L" (LCD), 0x00 0x7d 0x68 0x00 (digit bytes). - */ - - /* Merge the two nibbles for a digit into one byte. */ - for (i = 0; i < 4; i++) { - digit_bytes[i] = ((buf[1 + (i * 2)] & 0x0f) << 4); - digit_bytes[i] |= (buf[1 + (i * 2) + 1] & 0x0f); - - /* Bit 7 in the byte is not part of the digit. */ - digit_bytes[i] &= ~(1 << 7); - } - - /* Check for "OL". */ - if (digit_bytes[0] == 0x00 && digit_bytes[1] == 0x7d && - digit_bytes[2] == 0x68 && digit_bytes[3] == 0x00) { - sr_spew("Over limit."); - *result = INFINITY; - return SR_OK; - } - - /* Parse the digits. */ - for (i = 0; i < 4; i++) - digits[i] = parse_digit(digit_bytes[i]); - sr_spew("Digits: %02x %02x %02x %02x (%d%d%d%d).", - digit_bytes[0], digit_bytes[1], digit_bytes[2], digit_bytes[3], - digits[0], digits[1], digits[2], digits[3]); - - /* Merge all digits into an integer value. */ - for (i = 0; i < 4; i++) { - intval *= 10; - intval += digits[i]; - } - - floatval = (float)intval; - - /* Decimal point position. */ - if ((buf[3] & (1 << 3)) != 0) { - floatval /= 1000; - sr_spew("Decimal point after first digit."); - } else if ((buf[5] & (1 << 3)) != 0) { - floatval /= 100; - sr_spew("Decimal point after second digit."); - } else if ((buf[7] & (1 << 3)) != 0) { - floatval /= 10; - sr_spew("Decimal point after third digit."); - } else { - sr_spew("No decimal point in the number."); - } - - /* Apply sign. */ - floatval *= sign; - - sr_spew("The display value is %f.", floatval); - - *result = floatval; - - return SR_OK; -} - -static void parse_flags(const uint8_t *buf, struct fs9721_info *info) -{ - /* Byte 0: LCD SEG1 */ - info->is_ac = (buf[0] & (1 << 3)) != 0; - info->is_dc = (buf[0] & (1 << 2)) != 0; - info->is_auto = (buf[0] & (1 << 1)) != 0; - info->is_rs232 = (buf[0] & (1 << 0)) != 0; - - /* Byte 1: LCD SEG2 */ - info->is_sign = (buf[1] & (1 << 3)) != 0; - - /* Byte 9: LCD SEG10 */ - info->is_micro = (buf[9] & (1 << 3)) != 0; - info->is_nano = (buf[9] & (1 << 2)) != 0; - info->is_kilo = (buf[9] & (1 << 1)) != 0; - info->is_diode = (buf[9] & (1 << 0)) != 0; - - /* Byte 10: LCD SEG11 */ - info->is_milli = (buf[10] & (1 << 3)) != 0; - info->is_percent = (buf[10] & (1 << 2)) != 0; - info->is_mega = (buf[10] & (1 << 1)) != 0; - info->is_beep = (buf[10] & (1 << 0)) != 0; - - /* Byte 11: LCD SEG12 */ - info->is_farad = (buf[11] & (1 << 3)) != 0; - info->is_ohm = (buf[11] & (1 << 2)) != 0; - info->is_rel = (buf[11] & (1 << 1)) != 0; - info->is_hold = (buf[11] & (1 << 0)) != 0; - - /* Byte 12: LCD SEG13 */ - info->is_ampere = (buf[12] & (1 << 3)) != 0; - info->is_volt = (buf[12] & (1 << 2)) != 0; - info->is_hz = (buf[12] & (1 << 1)) != 0; - info->is_bat = (buf[12] & (1 << 0)) != 0; - - /* Byte 13: LCD SEG14 */ - info->is_c2c1_11 = (buf[13] & (1 << 3)) != 0; - info->is_c2c1_10 = (buf[13] & (1 << 2)) != 0; - info->is_c2c1_01 = (buf[13] & (1 << 1)) != 0; - info->is_c2c1_00 = (buf[13] & (1 << 0)) != 0; -} - -static void handle_flags(struct sr_datafeed_analog *analog, float *floatval, - const struct fs9721_info *info) -{ - /* Factors */ - if (info->is_nano) - *floatval /= 1000000000; - if (info->is_micro) - *floatval /= 1000000; - if (info->is_milli) - *floatval /= 1000; - if (info->is_kilo) - *floatval *= 1000; - if (info->is_mega) - *floatval *= 1000000; - - /* Measurement modes */ - if (info->is_volt) { - analog->mq = SR_MQ_VOLTAGE; - analog->unit = SR_UNIT_VOLT; - } - if (info->is_ampere) { - analog->mq = SR_MQ_CURRENT; - analog->unit = SR_UNIT_AMPERE; - } - if (info->is_ohm) { - analog->mq = SR_MQ_RESISTANCE; - analog->unit = SR_UNIT_OHM; - } - if (info->is_hz) { - analog->mq = SR_MQ_FREQUENCY; - analog->unit = SR_UNIT_HERTZ; - } - if (info->is_farad) { - analog->mq = SR_MQ_CAPACITANCE; - analog->unit = SR_UNIT_FARAD; - } - if (info->is_beep) { - analog->mq = SR_MQ_CONTINUITY; - analog->unit = SR_UNIT_BOOLEAN; - *floatval = (*floatval == INFINITY) ? 0.0 : 1.0; - } - if (info->is_diode) { - analog->mq = SR_MQ_VOLTAGE; - analog->unit = SR_UNIT_VOLT; - } - if (info->is_percent) { - analog->mq = SR_MQ_DUTY_CYCLE; - analog->unit = SR_UNIT_PERCENTAGE; - } - - /* Measurement related flags */ - if (info->is_ac) - analog->mqflags |= SR_MQFLAG_AC; - if (info->is_dc) - analog->mqflags |= SR_MQFLAG_DC; - if (info->is_auto) - analog->mqflags |= SR_MQFLAG_AUTORANGE; - if (info->is_diode) - analog->mqflags |= SR_MQFLAG_DIODE; - if (info->is_hold) - analog->mqflags |= SR_MQFLAG_HOLD; - if (info->is_rel) - analog->mqflags |= SR_MQFLAG_RELATIVE; - - /* Other flags */ - if (info->is_rs232) - sr_spew("RS232 enabled."); - if (info->is_bat) - sr_spew("Battery is low."); - if (info->is_c2c1_00) - sr_spew("User-defined LCD symbol 0 is active."); - if (info->is_c2c1_01) - sr_spew("User-defined LCD symbol 1 is active."); - if (info->is_c2c1_10) - sr_spew("User-defined LCD symbol 2 is active."); - if (info->is_c2c1_11) - sr_spew("User-defined LCD symbol 3 is active."); -} - -SR_PRIV gboolean sr_fs9721_packet_valid(const uint8_t *buf) -{ - struct fs9721_info info; - - parse_flags(buf, &info); - - return (sync_nibbles_valid(buf) && flags_valid(&info)); -} - -/** - * Parse a protocol packet. - * - * @param buf Buffer containing the 14-byte protocol packet. Must not be NULL. - * @param floatval Pointer to a float variable. That variable will contain the - * result value upon parsing success. Mut not be NULL. - * @param analog Pointer to a struct sr_datafeed_analog. The struct will be - * filled with data according to the protocol packet. - * Must not be NULL. - * @param info Pointer to a struct fs9721_info. The struct will be filled - * with data according to the protocol packet. Must not be NULL. - * - * @return SR_OK upon success, SR_ERR upon failure. Upon errors, the - * 'analog' variable contents are undefined and should not be used. - */ -SR_PRIV int sr_fs9721_parse(const uint8_t *buf, float *floatval, - struct sr_datafeed_analog *analog, void *info) -{ - int ret; - struct fs9721_info *info_local; - - info_local = (struct fs9721_info *)info; - - if ((ret = parse_value(buf, floatval)) != SR_OK) { - sr_dbg("Error parsing value: %d.", ret); - return ret; - } - - parse_flags(buf, info_local); - handle_flags(analog, floatval, info_local); - - return SR_OK; -} - -SR_PRIV void sr_fs9721_00_temp_c(struct sr_datafeed_analog *analog, void *info) -{ - struct fs9721_info *info_local; - - info_local = (struct fs9721_info *)info; - - /* User-defined FS9721_LP3 flag 'c2c1_00' means temperature (C). */ - if (info_local->is_c2c1_00) { - analog->mq = SR_MQ_TEMPERATURE; - analog->unit = SR_UNIT_CELSIUS; - } -} - -SR_PRIV void sr_fs9721_01_temp_c(struct sr_datafeed_analog *analog, void *info) -{ - struct fs9721_info *info_local; - - info_local = (struct fs9721_info *)info; - - /* User-defined FS9721_LP3 flag 'c2c1_01' means temperature (C). */ - if (info_local->is_c2c1_01) { - analog->mq = SR_MQ_TEMPERATURE; - analog->unit = SR_UNIT_CELSIUS; - } -} - -SR_PRIV void sr_fs9721_10_temp_c(struct sr_datafeed_analog *analog, void *info) -{ - struct fs9721_info *info_local; - - info_local = (struct fs9721_info *)info; - - /* User-defined FS9721_LP3 flag 'c2c1_10' means temperature (C). */ - if (info_local->is_c2c1_10) { - analog->mq = SR_MQ_TEMPERATURE; - analog->unit = SR_UNIT_CELSIUS; - } -} - -SR_PRIV void sr_fs9721_01_10_temp_f_c(struct sr_datafeed_analog *analog, void *info) -{ - struct fs9721_info *info_local; - - info_local = (struct fs9721_info *)info; - - /* User-defined FS9721_LP3 flag 'c2c1_01' means temperature (F). */ - if (info_local->is_c2c1_01) { - analog->mq = SR_MQ_TEMPERATURE; - analog->unit = SR_UNIT_FAHRENHEIT; - } - - /* User-defined FS9721_LP3 flag 'c2c1_10' means temperature (C). */ - if (info_local->is_c2c1_10) { - analog->mq = SR_MQ_TEMPERATURE; - analog->unit = SR_UNIT_CELSIUS; - } -} - -SR_PRIV void sr_fs9721_max_c_min(struct sr_datafeed_analog *analog, void *info) -{ - struct fs9721_info *info_local; - - info_local = (struct fs9721_info *)info; - - /* User-defined FS9721_LP3 flag 'c2c1_00' means MAX. */ - if (info_local->is_c2c1_00) - analog->mqflags |= SR_MQFLAG_MAX; - - /* User-defined FS9721_LP3 flag 'c2c1_01' means temperature (C). */ - if (info_local->is_c2c1_01) { - analog->mq = SR_MQ_TEMPERATURE; - analog->unit = SR_UNIT_CELSIUS; - } - - /* User-defined FS9721_LP3 flag 'c2c1_11' means MIN. */ - if (info_local->is_c2c1_11) - analog->mqflags |= SR_MQFLAG_MIN; - -} diff --git a/hardware/common/dmm/fs9922.c b/hardware/common/dmm/fs9922.c deleted file mode 100644 index caaa51c7..00000000 --- a/hardware/common/dmm/fs9922.c +++ /dev/null @@ -1,384 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2012 Uwe Hermann - * - * 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 - */ - -/* - * Fortune Semiconductor FS9922-DMM3/FS9922-DMM4 protocol parser. - */ - -#include -#include -#include -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#define LOG_PREFIX "fs9922" - -static gboolean flags_valid(const struct fs9922_info *info) -{ - int count; - - /* Does the packet have more than one multiplier? */ - count = 0; - count += (info->is_nano) ? 1 : 0; - count += (info->is_micro) ? 1 : 0; - count += (info->is_milli) ? 1 : 0; - count += (info->is_kilo) ? 1 : 0; - count += (info->is_mega) ? 1 : 0; - if (count > 1) { - sr_dbg("More than one multiplier detected in packet."); - return FALSE; - } - - /* - * Does the packet "measure" more than one type of value? - * - * Note: In "diode mode", both is_diode and is_volt will be set. - * That is a valid use-case, so we don't want to error out below - * if it happens. Thus, we don't check for is_diode here. - */ - count = 0; - // count += (info->is_diode) ? 1 : 0; - count += (info->is_percent) ? 1 : 0; - count += (info->is_volt) ? 1 : 0; - count += (info->is_ampere) ? 1 : 0; - count += (info->is_ohm) ? 1 : 0; - count += (info->is_hfe) ? 1 : 0; - count += (info->is_hertz) ? 1 : 0; - count += (info->is_farad) ? 1 : 0; - count += (info->is_celsius) ? 1 : 0; - count += (info->is_fahrenheit) ? 1 : 0; - if (count > 1) { - sr_dbg("More than one measurement type detected in packet."); - return FALSE; - } - - /* Both AC and DC set? */ - if (info->is_ac && info->is_dc) { - sr_dbg("Both AC and DC flags detected in packet."); - return FALSE; - } - - /* Both Celsius and Fahrenheit set? */ - if (info->is_celsius && info->is_fahrenheit) { - sr_dbg("Both Celsius and Fahrenheit flags detected in packet."); - return FALSE; - } - - return TRUE; -} - -static int parse_value(const uint8_t *buf, float *result) -{ - int sign, intval; - float floatval; - - /* Byte 0: Sign ('+' or '-') */ - if (buf[0] == '+') { - sign = 1; - } else if (buf[0] == '-') { - sign = -1; - } else { - sr_dbg("Invalid sign byte: 0x%02x.", buf[0]); - return SR_ERR; - } - - /* - * Bytes 1-4: Value (4 decimal digits) - * - * Over limit: "0.L" on the display, "?0:?" as protocol "digits". - */ - if (buf[1] == '?' && buf[2] == '0' && buf[3] == ':' && buf[4] == '?') { - sr_spew("Over limit."); - *result = INFINITY; - return SR_OK; - } else if (!isdigit(buf[1]) || !isdigit(buf[2]) || - !isdigit(buf[3]) || !isdigit(buf[4])) { - sr_dbg("Value contained invalid digits: %02x %02x %02x %02x (" - "%c %c %c %c).", buf[1], buf[2], buf[3], buf[4]); - return SR_ERR; - } - intval = 0; - intval += (buf[1] - '0') * 1000; - intval += (buf[2] - '0') * 100; - intval += (buf[3] - '0') * 10; - intval += (buf[4] - '0') * 1; - - floatval = (float)intval; - - /* Byte 5: Always ' ' (space, 0x20) */ - - /* - * Byte 6: Decimal point position ('0', '1', '2', or '4') - * - * Note: The Fortune Semiconductor FS9922-DMM3/4 datasheets both have - * an error/typo here. They claim that the values '0'/'1'/'2'/'3' are - * used, but '0'/'1'/'2'/'4' is actually correct. - */ - if (buf[6] != '0' && buf[6] != '1' && buf[6] != '2' && buf[6] != '4') { - sr_dbg("Invalid decimal point value: 0x%02x.", buf[6]); - return SR_ERR; - } - if (buf[6] == '0') - floatval /= 1; - else if (buf[6] == '1') - floatval /= 1000; - else if (buf[6] == '2') - floatval /= 100; - else if (buf[6] == '4') - floatval /= 10; - - /* Apply sign. */ - floatval *= sign; - - sr_spew("The display value is %f.", floatval); - - *result = floatval; - - return SR_OK; -} - -static void parse_flags(const uint8_t *buf, struct fs9922_info *info) -{ - /* Z1/Z2/Z3/Z4 are bits for user-defined LCD symbols (on/off). */ - - /* Byte 7 */ - /* Bit 7: Always 0 */ - /* Bit 6: Always 0 */ - info->is_auto = (buf[7] & (1 << 5)) != 0; - info->is_dc = (buf[7] & (1 << 4)) != 0; - info->is_ac = (buf[7] & (1 << 3)) != 0; - info->is_rel = (buf[7] & (1 << 2)) != 0; - info->is_hold = (buf[7] & (1 << 1)) != 0; - info->is_bpn = (buf[7] & (1 << 0)) != 0; /* Bargraph shown */ - - /* Byte 8 */ - info->is_z1 = (buf[8] & (1 << 7)) != 0; /* User symbol 1 */ - info->is_z2 = (buf[8] & (1 << 6)) != 0; /* User symbol 2 */ - info->is_max = (buf[8] & (1 << 5)) != 0; - info->is_min = (buf[8] & (1 << 4)) != 0; - info->is_apo = (buf[8] & (1 << 3)) != 0; /* Auto-poweroff on */ - info->is_bat = (buf[8] & (1 << 2)) != 0; /* Battery low */ - info->is_nano = (buf[8] & (1 << 1)) != 0; - info->is_z3 = (buf[8] & (1 << 0)) != 0; /* User symbol 3 */ - - /* Byte 9 */ - info->is_micro = (buf[9] & (1 << 7)) != 0; - info->is_milli = (buf[9] & (1 << 6)) != 0; - info->is_kilo = (buf[9] & (1 << 5)) != 0; - info->is_mega = (buf[9] & (1 << 4)) != 0; - info->is_beep = (buf[9] & (1 << 3)) != 0; - info->is_diode = (buf[9] & (1 << 2)) != 0; - info->is_percent = (buf[9] & (1 << 1)) != 0; - info->is_z4 = (buf[9] & (1 << 0)) != 0; /* User symbol 4 */ - - /* Byte 10 */ - info->is_volt = (buf[10] & (1 << 7)) != 0; - info->is_ampere = (buf[10] & (1 << 6)) != 0; - info->is_ohm = (buf[10] & (1 << 5)) != 0; - info->is_hfe = (buf[10] & (1 << 4)) != 0; - info->is_hertz = (buf[10] & (1 << 3)) != 0; - info->is_farad = (buf[10] & (1 << 2)) != 0; - info->is_celsius = (buf[10] & (1 << 1)) != 0; /* Only FS9922-DMM4 */ - info->is_fahrenheit = (buf[10] & (1 << 0)) != 0; /* Only FS9922-DMM4 */ - - /* - * Byte 11: Bar graph - * - * Bit 7 contains the sign of the bargraph number (if the bit is set, - * the number is negative), bits 6..0 contain the actual number. - * Valid range: 0-40 (FS9922-DMM3), 0-60 (FS9922-DMM4). - * - * Upon "over limit" the bargraph value is 1 count above the highest - * valid number (i.e. 41 or 61, depending on chip). - */ - if (info->is_bpn) { - info->bargraph_sign = ((buf[11] & (1 << 7)) != 0) ? -1 : 1; - info->bargraph_value = (buf[11] & 0x7f); - info->bargraph_value *= info->bargraph_sign; - } - - /* Byte 12: Always '\r' (carriage return, 0x0d, 13) */ - - /* Byte 13: Always '\n' (newline, 0x0a, 10) */ -} - -static void handle_flags(struct sr_datafeed_analog *analog, float *floatval, - const struct fs9922_info *info) -{ - /* Factors */ - if (info->is_nano) - *floatval /= 1000000000; - if (info->is_micro) - *floatval /= 1000000; - if (info->is_milli) - *floatval /= 1000; - if (info->is_kilo) - *floatval *= 1000; - if (info->is_mega) - *floatval *= 1000000; - - /* Measurement modes */ - if (info->is_volt || info->is_diode) { - /* Note: In "diode mode" both is_diode and is_volt are set. */ - analog->mq = SR_MQ_VOLTAGE; - analog->unit = SR_UNIT_VOLT; - } - if (info->is_ampere) { - analog->mq = SR_MQ_CURRENT; - analog->unit = SR_UNIT_AMPERE; - } - if (info->is_ohm) { - analog->mq = SR_MQ_RESISTANCE; - analog->unit = SR_UNIT_OHM; - } - if (info->is_hfe) { - analog->mq = SR_MQ_GAIN; - analog->unit = SR_UNIT_UNITLESS; - } - if (info->is_hertz) { - analog->mq = SR_MQ_FREQUENCY; - analog->unit = SR_UNIT_HERTZ; - } - if (info->is_farad) { - analog->mq = SR_MQ_CAPACITANCE; - analog->unit = SR_UNIT_FARAD; - } - if (info->is_celsius) { - analog->mq = SR_MQ_TEMPERATURE; - analog->unit = SR_UNIT_CELSIUS; - } - if (info->is_fahrenheit) { - analog->mq = SR_MQ_TEMPERATURE; - analog->unit = SR_UNIT_FAHRENHEIT; - } - if (info->is_beep) { - analog->mq = SR_MQ_CONTINUITY; - analog->unit = SR_UNIT_BOOLEAN; - *floatval = (*floatval == INFINITY) ? 0.0 : 1.0; - } - if (info->is_percent) { - analog->mq = SR_MQ_DUTY_CYCLE; - analog->unit = SR_UNIT_PERCENTAGE; - } - - /* Measurement related flags */ - if (info->is_ac) - analog->mqflags |= SR_MQFLAG_AC; - if (info->is_dc) - analog->mqflags |= SR_MQFLAG_DC; - if (info->is_auto) - analog->mqflags |= SR_MQFLAG_AUTORANGE; - if (info->is_diode) - analog->mqflags |= SR_MQFLAG_DIODE; - if (info->is_hold) - analog->mqflags |= SR_MQFLAG_HOLD; - if (info->is_max) - analog->mqflags |= SR_MQFLAG_MAX; - if (info->is_min) - analog->mqflags |= SR_MQFLAG_MIN; - if (info->is_rel) - analog->mqflags |= SR_MQFLAG_RELATIVE; - - /* Other flags */ - if (info->is_apo) - sr_spew("Automatic power-off function is active."); - if (info->is_bat) - sr_spew("Battery is low."); - if (info->is_z1) - sr_spew("User-defined LCD symbol 1 is active."); - if (info->is_z2) - sr_spew("User-defined LCD symbol 2 is active."); - if (info->is_z3) - sr_spew("User-defined LCD symbol 3 is active."); - if (info->is_z4) - sr_spew("User-defined LCD symbol 4 is active."); - if (info->is_bpn) - sr_spew("The bargraph value is %d.", info->bargraph_value); - else - sr_spew("The bargraph is not active."); - -} - -SR_PRIV gboolean sr_fs9922_packet_valid(const uint8_t *buf) -{ - struct fs9922_info info; - - /* Byte 0: Sign (must be '+' or '-') */ - if (buf[0] != '+' && buf[0] != '-') - return FALSE; - - /* Byte 12: Always '\r' (carriage return, 0x0d, 13) */ - /* Byte 13: Always '\n' (newline, 0x0a, 10) */ - if (buf[12] != '\r' || buf[13] != '\n') - return FALSE; - - parse_flags(buf, &info); - - return flags_valid(&info); -} - -/** - * Parse a protocol packet. - * - * @param buf Buffer containing the protocol packet. Must not be NULL. - * @param floatval Pointer to a float variable. That variable will contain the - * result value upon parsing success. Must not be NULL. - * @param analog Pointer to a struct sr_datafeed_analog. The struct will be - * filled with data according to the protocol packet. - * Must not be NULL. - * @param info Pointer to a struct fs9922_info. The struct will be filled - * with data according to the protocol packet. Must not be NULL. - * - * @return SR_OK upon success, SR_ERR upon failure. Upon errors, the - * 'analog' variable contents are undefined and should not be used. - */ -SR_PRIV int sr_fs9922_parse(const uint8_t *buf, float *floatval, - struct sr_datafeed_analog *analog, void *info) -{ - int ret; - struct fs9922_info *info_local; - - info_local = (struct fs9922_info *)info; - - if ((ret = parse_value(buf, floatval)) != SR_OK) { - sr_dbg("Error parsing value: %d.", ret); - return ret; - } - - parse_flags(buf, info_local); - handle_flags(analog, floatval, info_local); - - return SR_OK; -} - -SR_PRIV void sr_fs9922_z1_diode(struct sr_datafeed_analog *analog, void *info) -{ - struct fs9922_info *info_local; - - info_local = (struct fs9922_info *)info; - - /* User-defined z1 flag means "diode mode". */ - if (info_local->is_z1) { - analog->mq = SR_MQ_VOLTAGE; - analog->unit = SR_UNIT_VOLT; - analog->mqflags |= SR_MQFLAG_DIODE; - } -} diff --git a/hardware/common/dmm/m2110.c b/hardware/common/dmm/m2110.c deleted file mode 100644 index 5863cef1..00000000 --- a/hardware/common/dmm/m2110.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2013 Matthias Heidbrink - * - * 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 . - */ - -/** - * @file - * - * BBC Goerz Metrawatt M2110 ASCII protocol parser. - * - * Most probably the simplest multimeter protocol ever ;-) . - */ - -#include -#include -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#define LOG_PREFIX "m2110" - -SR_PRIV gboolean sr_m2110_packet_valid(const uint8_t *buf) -{ - float val; - - if ((buf[7] != '\r') || (buf[8] != '\n')) - return FALSE; - - if (!strncmp((const char *)buf, "OVERRNG", 7)) - return TRUE; - - if (sscanf((const char *)buf, "%f", &val) == 1) - return TRUE; - else - return FALSE; -} - -SR_PRIV int sr_m2110_parse(const uint8_t *buf, float *floatval, - struct sr_datafeed_analog *analog, void *info) -{ - float val; - - (void)info; - - /* We don't know the unit, so that's the best we can do. */ - analog->mq = SR_MQ_GAIN; - analog->unit = SR_UNIT_UNITLESS; - analog->mqflags = 0; - - if (!strncmp((const char *)buf, "OVERRNG", 7)) - *floatval = INFINITY; - else if (sscanf((const char *)buf, "%f", &val) == 1) - *floatval = val; - - return SR_OK; -} diff --git a/hardware/common/dmm/metex14.c b/hardware/common/dmm/metex14.c deleted file mode 100644 index 8151aa9d..00000000 --- a/hardware/common/dmm/metex14.c +++ /dev/null @@ -1,343 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2012-2013 Uwe Hermann - * - * 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 - */ - -/** - * @file - * - * Metex 14-bytes ASCII protocol parser. - * - * @internal - * This should work for various multimeters which use this kind of protocol, - * even though there is some variation in which modes each DMM supports. - * - * It does _not_ work for all Metex DMMs, some use a quite different protocol. - */ - -#include -#include -#include -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#define LOG_PREFIX "metex14" - -/** Parse value from buf, byte 2-8. */ -static int parse_value(const uint8_t *buf, struct metex14_info *info, - float *result) -{ - int i, is_ol, cnt; - char valstr[7 + 1]; - - /* Strip all spaces from bytes 2-8. */ - memset(&valstr, 0, 7 + 1); - for (i = 0, cnt = 0; i < 7; i++) { - if (buf[2 + i] != ' ') - valstr[cnt++] = buf[2 + i]; - } - - /* Bytes 5-7: Over limit (various forms) */ - is_ol = 0; - is_ol += (!strcasecmp((const char *)&valstr, ".OL")) ? 1 : 0; - is_ol += (!strcasecmp((const char *)&valstr, "O.L")) ? 1 : 0; - is_ol += (!strcasecmp((const char *)&valstr, "OL.")) ? 1 : 0; - is_ol += (!strcasecmp((const char *)&valstr, "OL")) ? 1 : 0; - is_ol += (!strcasecmp((const char *)&valstr, "-.OL")) ? 1 : 0; - is_ol += (!strcasecmp((const char *)&valstr, "-O.L")) ? 1 : 0; - is_ol += (!strcasecmp((const char *)&valstr, "-OL.")) ? 1 : 0; - is_ol += (!strcasecmp((const char *)&valstr, "-OL")) ? 1 : 0; - if (is_ol != 0) { - sr_spew("Over limit."); - *result = INFINITY; - return SR_OK; - } - - /* Logic functions */ - if (!strcmp((const char *)&valstr, "READY") || - !strcmp((const char *)&valstr, "FLOAT")) { - *result = INFINITY; - info->is_logic = TRUE; - } else if (!strcmp((const char *)&valstr, "Hi")) { - *result = 1.0; - info->is_logic = TRUE; - } else if (!strcmp((const char *)&valstr, "Lo")) { - *result = 0.0; - info->is_logic = TRUE; - } - if (info->is_logic) - return SR_OK; - - /* Bytes 2-8: Sign, value (up to 5 digits) and decimal point */ - sscanf((const char *)&valstr, "%f", result); - - sr_spew("The display value is %f.", *result); - - return SR_OK; -} - -static void parse_flags(const char *buf, struct metex14_info *info) -{ - int i, cnt; - char unit[4 + 1]; - const char *u; - - /* Bytes 0-1: Measurement mode AC, DC */ - info->is_ac = !strncmp(buf, "AC", 2); - info->is_dc = !strncmp(buf, "DC", 2); - - /* Bytes 2-8: See parse_value(). */ - - /* Strip all spaces from bytes 9-12. */ - memset(&unit, 0, 4 + 1); - for (i = 0, cnt = 0; i < 4; i++) { - if (buf[9 + i] != ' ') - unit[cnt++] = buf[9 + i]; - } - - /* Bytes 9-12: Unit */ - u = (const char *)&unit; - if (!strcasecmp(u, "A")) - info->is_ampere = TRUE; - else if (!strcasecmp(u, "mA")) - info->is_milli = info->is_ampere = TRUE; - else if (!strcasecmp(u, "uA")) - info->is_micro = info->is_ampere = TRUE; - else if (!strcasecmp(u, "V")) - info->is_volt = TRUE; - else if (!strcasecmp(u, "mV")) - info->is_milli = info->is_volt = TRUE; - else if (!strcasecmp(u, "Ohm")) - info->is_ohm = TRUE; - else if (!strcasecmp(u, "KOhm")) - info->is_kilo = info->is_ohm = TRUE; - else if (!strcasecmp(u, "MOhm")) - info->is_mega = info->is_ohm = TRUE; - else if (!strcasecmp(u, "pF")) - info->is_pico = info->is_farad = TRUE; - else if (!strcasecmp(u, "nF")) - info->is_nano = info->is_farad = TRUE; - else if (!strcasecmp(u, "uF")) - info->is_micro = info->is_farad = TRUE; - else if (!strcasecmp(u, "KHz")) - info->is_kilo = info->is_hertz = TRUE; - else if (!strcasecmp(u, "C")) - info->is_celsius = TRUE; - else if (!strcasecmp(u, "DB")) - info->is_decibel = TRUE; - else if (!strcasecmp(u, "")) - info->is_unitless = TRUE; - - /* Bytes 0-1: Measurement mode, except AC/DC */ - info->is_resistance = !strncmp(buf, "OH", 2) || - (!strncmp(buf, " ", 2) && info->is_ohm); - info->is_capacity = !strncmp(buf, "CA", 2) || - (!strncmp(buf, " ", 2) && info->is_farad); - info->is_temperature = !strncmp(buf, "TE", 2); - info->is_diode = !strncmp(buf, "DI", 2) || - (!strncmp(buf, " ", 2) && info->is_volt && info->is_milli); - info->is_frequency = !strncmp(buf, "FR", 2) || - (!strncmp(buf, " ", 2) && info->is_hertz); - info->is_gain = !strncmp(buf, "DB", 2); - info->is_hfe = !strncmp(buf, "HF", 2) || - (!strncmp(buf, " ", 2) && !info->is_volt && !info->is_ohm && - !info->is_logic && !info->is_farad && !info->is_hertz); - /* - * Note: - * - Protocol doesn't distinguish "resistance" from "beep" mode. - * - "DB" shows the logarithmic ratio of input voltage to a - * pre-stored (user-changeable) value in the DMM. - */ - - /* Byte 13: Always '\r' (carriage return, 0x0d, 13) */ -} - -static void handle_flags(struct sr_datafeed_analog *analog, float *floatval, - const struct metex14_info *info) -{ - /* Factors */ - if (info->is_pico) - *floatval /= 1000000000000ULL; - if (info->is_nano) - *floatval /= 1000000000; - if (info->is_micro) - *floatval /= 1000000; - if (info->is_milli) - *floatval /= 1000; - if (info->is_kilo) - *floatval *= 1000; - if (info->is_mega) - *floatval *= 1000000; - - /* Measurement modes */ - if (info->is_volt) { - analog->mq = SR_MQ_VOLTAGE; - analog->unit = SR_UNIT_VOLT; - } - if (info->is_ampere) { - analog->mq = SR_MQ_CURRENT; - analog->unit = SR_UNIT_AMPERE; - } - if (info->is_ohm) { - analog->mq = SR_MQ_RESISTANCE; - analog->unit = SR_UNIT_OHM; - } - if (info->is_hertz) { - analog->mq = SR_MQ_FREQUENCY; - analog->unit = SR_UNIT_HERTZ; - } - if (info->is_farad) { - analog->mq = SR_MQ_CAPACITANCE; - analog->unit = SR_UNIT_FARAD; - } - if (info->is_celsius) { - analog->mq = SR_MQ_TEMPERATURE; - analog->unit = SR_UNIT_CELSIUS; - } - if (info->is_diode) { - analog->mq = SR_MQ_VOLTAGE; - analog->unit = SR_UNIT_VOLT; - } - if (info->is_gain) { - analog->mq = SR_MQ_GAIN; - analog->unit = SR_UNIT_DECIBEL_VOLT; - } - if (info->is_hfe) { - analog->mq = SR_MQ_GAIN; - analog->unit = SR_UNIT_UNITLESS; - } - if (info->is_logic) { - analog->mq = SR_MQ_GAIN; - analog->unit = SR_UNIT_UNITLESS; - } - - /* Measurement related flags */ - if (info->is_ac) - analog->mqflags |= SR_MQFLAG_AC; - if (info->is_dc) - analog->mqflags |= SR_MQFLAG_DC; - if (info->is_diode) - analog->mqflags |= SR_MQFLAG_DIODE; -} - -static gboolean flags_valid(const struct metex14_info *info) -{ - int count; - - /* Does the packet have more than one multiplier? */ - count = 0; - count += (info->is_pico) ? 1 : 0; - count += (info->is_nano) ? 1 : 0; - count += (info->is_micro) ? 1 : 0; - count += (info->is_milli) ? 1 : 0; - count += (info->is_kilo) ? 1 : 0; - count += (info->is_mega) ? 1 : 0; - if (count > 1) { - sr_dbg("More than one multiplier detected in packet."); - return FALSE; - } - - /* Does the packet "measure" more than one type of value? */ - count = 0; - count += (info->is_ac) ? 1 : 0; - count += (info->is_dc) ? 1 : 0; - count += (info->is_resistance) ? 1 : 0; - count += (info->is_capacity) ? 1 : 0; - count += (info->is_temperature) ? 1 : 0; - count += (info->is_diode) ? 1 : 0; - count += (info->is_frequency) ? 1 : 0; - if (count > 1) { - sr_dbg("More than one measurement type detected in packet."); - return FALSE; - } - - /* Both AC and DC set? */ - if (info->is_ac && info->is_dc) { - sr_dbg("Both AC and DC flags detected in packet."); - return FALSE; - } - - return TRUE; -} - -#ifdef HAVE_LIBSERIALPORT -SR_PRIV int sr_metex14_packet_request(struct sr_serial_dev_inst *serial) -{ - const uint8_t wbuf = 'D'; - - sr_spew("Requesting DMM packet."); - - return (serial_write(serial, &wbuf, 1) == 1) ? SR_OK : SR_ERR; -} -#endif - -SR_PRIV gboolean sr_metex14_packet_valid(const uint8_t *buf) -{ - struct metex14_info info; - - memset(&info, 0x00, sizeof(struct metex14_info)); - parse_flags((const char *)buf, &info); - - if (!flags_valid(&info)) - return FALSE; - - if (buf[13] != '\r') - return FALSE; - - return TRUE; -} - -/** - * Parse a protocol packet. - * - * @param buf Buffer containing the protocol packet. Must not be NULL. - * @param floatval Pointer to a float variable. That variable will be modified - * in-place depending on the protocol packet. Must not be NULL. - * @param analog Pointer to a struct sr_datafeed_analog. The struct will be - * filled with data according to the protocol packet. - * Must not be NULL. - * @param info Pointer to a struct metex14_info. The struct will be filled - * with data according to the protocol packet. Must not be NULL. - * - * @return SR_OK upon success, SR_ERR upon failure. Upon errors, the - * 'analog' variable contents are undefined and should not be used. - */ -SR_PRIV int sr_metex14_parse(const uint8_t *buf, float *floatval, - struct sr_datafeed_analog *analog, void *info) -{ - int ret; - struct metex14_info *info_local; - - info_local = (struct metex14_info *)info; - - /* Don't print byte 13. That one contains the carriage return. */ - sr_dbg("DMM packet: \"%.13s\"", buf); - - memset(info_local, 0x00, sizeof(struct metex14_info)); - - if ((ret = parse_value(buf, info_local, floatval)) != SR_OK) { - sr_dbg("Error parsing value: %d.", ret); - return ret; - } - - parse_flags((const char *)buf, info_local); - handle_flags(analog, floatval, info_local); - - return SR_OK; -} diff --git a/hardware/common/dmm/rs9lcd.c b/hardware/common/dmm/rs9lcd.c deleted file mode 100644 index 539c2335..00000000 --- a/hardware/common/dmm/rs9lcd.c +++ /dev/null @@ -1,437 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2012 Alexandru Gagniuc - * - * 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 . - */ - -/* - * RadioShack 22-812 protocol parser. - * - * This protocol is currently encountered on the RadioShack 22-812 DMM. - * It is a 9-byte packet representing a 1:1 mapping of the LCD segments, hence - * the name rs9lcd. - * - * The chip is a bare die covered by a plastic blob. It is unclear if this chip - * and protocol is used on any other device. - */ - -#include -#include -#include -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#define LOG_PREFIX "rs9lcd" - -/* Byte 1 of the packet, and the modes it represents */ -#define IND1_HZ (1 << 7) -#define IND1_OHM (1 << 6) -#define IND1_KILO (1 << 5) -#define IND1_MEGA (1 << 4) -#define IND1_FARAD (1 << 3) -#define IND1_AMP (1 << 2) -#define IND1_VOLT (1 << 1) -#define IND1_MILI (1 << 0) -/* Byte 2 of the packet, and the modes it represents */ -#define IND2_MICRO (1 << 7) -#define IND2_NANO (1 << 6) -#define IND2_DBM (1 << 5) -#define IND2_SEC (1 << 4) -#define IND2_DUTY (1 << 3) -#define IND2_HFE (1 << 2) -#define IND2_REL (1 << 1) -#define IND2_MIN (1 << 0) -/* Byte 7 of the packet, and the modes it represents */ -#define INFO_BEEP (1 << 7) -#define INFO_DIODE (1 << 6) -#define INFO_BAT (1 << 5) -#define INFO_HOLD (1 << 4) -#define INFO_NEG (1 << 3) -#define INFO_AC (1 << 2) -#define INFO_RS232 (1 << 1) -#define INFO_AUTO (1 << 0) -/* Instead of a decimal point, digit 4 carries the MAX flag */ -#define DIG4_MAX (1 << 3) -/* Mask to remove the decimal point from a digit */ -#define DP_MASK (1 << 3) - -/* What the LCD values represent */ -#define LCD_0 0xd7 -#define LCD_1 0x50 -#define LCD_2 0xb5 -#define LCD_3 0xf1 -#define LCD_4 0x72 -#define LCD_5 0xe3 -#define LCD_6 0xe7 -#define LCD_7 0x51 -#define LCD_8 0xf7 -#define LCD_9 0xf3 - -#define LCD_C 0x87 -#define LCD_E -#define LCD_F -#define LCD_h 0x66 -#define LCD_H 0x76 -#define LCD_I -#define LCD_n -#define LCD_P 0x37 -#define LCD_r - -enum { - MODE_DC_V = 0, - MODE_AC_V = 1, - MODE_DC_UA = 2, - MODE_DC_MA = 3, - MODE_DC_A = 4, - MODE_AC_UA = 5, - MODE_AC_MA = 6, - MODE_AC_A = 7, - MODE_OHM = 8, - MODE_FARAD = 9, - MODE_HZ = 10, - MODE_VOLT_HZ = 11, /* Dial set to V, Hz selected by Hz button */ - MODE_AMP_HZ = 12, /* Dial set to A, Hz selected by Hz button */ - MODE_DUTY = 13, - MODE_VOLT_DUTY = 14, /* Dial set to V, duty cycle selected */ - MODE_AMP_DUTY = 15, /* Dial set to A, duty cycle selected */ - MODE_WIDTH = 16, - MODE_VOLT_WIDTH = 17, /* Dial set to V, pulse width selected */ - MODE_AMP_WIDTH = 18, /* Dial set to A, pulse width selected */ - MODE_DIODE = 19, - MODE_CONT = 20, - MODE_HFE = 21, - MODE_LOGIC = 22, - MODE_DBM = 23, - /* MODE_EF = 24, */ /* Not encountered on any DMM */ - MODE_TEMP = 25, - MODE_INVALID = 26, -}; - -enum { - READ_ALL, - READ_TEMP, -}; - -struct rs9lcd_packet { - uint8_t mode; - uint8_t indicatrix1; - uint8_t indicatrix2; - uint8_t digit4; - uint8_t digit3; - uint8_t digit2; - uint8_t digit1; - uint8_t info; - uint8_t checksum; -}; - -static gboolean checksum_valid(const struct rs9lcd_packet *rs_packet) -{ - uint8_t *raw; - uint8_t sum = 0; - int i; - - raw = (void *)rs_packet; - - for (i = 0; i < RS9LCD_PACKET_SIZE - 1; i++) - sum += raw[i]; - - /* This is just a funky constant added to the checksum. */ - sum += 57; - sum -= rs_packet->checksum; - return (sum == 0); -} - -static gboolean selection_good(const struct rs9lcd_packet *rs_packet) -{ - int count; - - /* Does the packet have more than one multiplier? */ - count = 0; - count += (rs_packet->indicatrix1 & IND1_KILO) ? 1 : 0; - count += (rs_packet->indicatrix1 & IND1_MEGA) ? 1 : 0; - count += (rs_packet->indicatrix1 & IND1_MILI) ? 1 : 0; - count += (rs_packet->indicatrix2 & IND2_MICRO) ? 1 : 0; - count += (rs_packet->indicatrix2 & IND2_NANO) ? 1 : 0; - if (count > 1) { - sr_dbg("More than one multiplier detected in packet."); - return FALSE; - } - - /* Does the packet "measure" more than one type of value? */ - count = 0; - count += (rs_packet->indicatrix1 & IND1_HZ) ? 1 : 0; - count += (rs_packet->indicatrix1 & IND1_OHM) ? 1 : 0; - count += (rs_packet->indicatrix1 & IND1_FARAD) ? 1 : 0; - count += (rs_packet->indicatrix1 & IND1_AMP) ? 1 : 0; - count += (rs_packet->indicatrix1 & IND1_VOLT) ? 1 : 0; - count += (rs_packet->indicatrix2 & IND2_DBM) ? 1 : 0; - count += (rs_packet->indicatrix2 & IND2_SEC) ? 1 : 0; - count += (rs_packet->indicatrix2 & IND2_DUTY) ? 1 : 0; - count += (rs_packet->indicatrix2 & IND2_HFE) ? 1 : 0; - if (count > 1) { - sr_dbg("More than one measurement type detected in packet."); - return FALSE; - } - - return TRUE; -} - -/* - * Since the 22-812 does not identify itself in any way, shape, or form, - * we really don't know for sure who is sending the data. We must use every - * possible check to filter out bad packets, especially since detection of the - * 22-812 depends on how well we can filter the packets. - */ -SR_PRIV gboolean sr_rs9lcd_packet_valid(const uint8_t *buf) -{ - const struct rs9lcd_packet *rs_packet = (void *)buf; - - /* - * Check for valid mode first, before calculating the checksum. No - * point calculating the checksum, if we know we'll reject the packet. - */ - if (!(rs_packet->mode < MODE_INVALID)) - return FALSE; - - if (!checksum_valid(rs_packet)) { - sr_spew("Packet with invalid checksum. Discarding."); - return FALSE; - } - - if (!selection_good(rs_packet)) { - sr_spew("Packet with invalid selection bits. Discarding."); - return FALSE; - } - - return TRUE; -} - -static uint8_t decode_digit(uint8_t raw_digit) -{ - /* Take out the decimal point, so we can use a simple switch(). */ - raw_digit &= ~DP_MASK; - - switch (raw_digit) { - case 0x00: - case LCD_0: - return 0; - case LCD_1: - return 1; - case LCD_2: - return 2; - case LCD_3: - return 3; - case LCD_4: - return 4; - case LCD_5: - return 5; - case LCD_6: - return 6; - case LCD_7: - return 7; - case LCD_8: - return 8; - case LCD_9: - return 9; - default: - sr_dbg("Invalid digit byte: 0x%02x.", raw_digit); - return 0xff; - } -} - -static double lcd_to_double(const struct rs9lcd_packet *rs_packet, int type) -{ - double rawval = 0, multiplier = 1; - uint8_t digit, raw_digit; - gboolean dp_reached = FALSE; - int i, end; - - /* end = 1: Don't parse last digit. end = 0: Parse all digits. */ - end = (type == READ_TEMP) ? 1 : 0; - - /* We have 4 digits, and we start from the most significant. */ - for (i = 3; i >= end; i--) { - raw_digit = *(&(rs_packet->digit4) + i); - digit = decode_digit(raw_digit); - if (digit == 0xff) { - rawval = NAN; - break; - } - /* - * Digit 1 does not have a decimal point. Instead, the decimal - * point is used to indicate MAX, so we must avoid testing it. - */ - if ((i < 3) && (raw_digit & DP_MASK)) - dp_reached = TRUE; - if (dp_reached) - multiplier /= 10; - rawval = rawval * 10 + digit; - } - rawval *= multiplier; - if (rs_packet->info & INFO_NEG) - rawval *= -1; - - /* See if we need to multiply our raw value by anything. */ - if (rs_packet->indicatrix1 & IND2_NANO) - rawval *= 1E-9; - else if (rs_packet->indicatrix2 & IND2_MICRO) - rawval *= 1E-6; - else if (rs_packet->indicatrix1 & IND1_MILI) - rawval *= 1E-3; - else if (rs_packet->indicatrix1 & IND1_KILO) - rawval *= 1E3; - else if (rs_packet->indicatrix1 & IND1_MEGA) - rawval *= 1E6; - - return rawval; -} - -static gboolean is_celsius(const struct rs9lcd_packet *rs_packet) -{ - return ((rs_packet->digit4 & ~DP_MASK) == LCD_C); -} - -static gboolean is_shortcirc(const struct rs9lcd_packet *rs_packet) -{ - return ((rs_packet->digit2 & ~DP_MASK) == LCD_h); -} - -static gboolean is_logic_high(const struct rs9lcd_packet *rs_packet) -{ - sr_spew("Digit 2: 0x%02x.", rs_packet->digit2 & ~DP_MASK); - return ((rs_packet->digit2 & ~DP_MASK) == LCD_H); -} - -SR_PRIV int sr_rs9lcd_parse(const uint8_t *buf, float *floatval, - struct sr_datafeed_analog *analog, void *info) -{ - const struct rs9lcd_packet *rs_packet = (void *)buf; - double rawval; - - (void)info; - - rawval = lcd_to_double(rs_packet, READ_ALL); - - switch (rs_packet->mode) { - case MODE_DC_V: - analog->mq = SR_MQ_VOLTAGE; - analog->unit = SR_UNIT_VOLT; - analog->mqflags |= SR_MQFLAG_DC; - break; - case MODE_AC_V: - analog->mq = SR_MQ_VOLTAGE; - analog->unit = SR_UNIT_VOLT; - analog->mqflags |= SR_MQFLAG_AC; - break; - case MODE_DC_UA: /* Fall through */ - case MODE_DC_MA: /* Fall through */ - case MODE_DC_A: - analog->mq = SR_MQ_CURRENT; - analog->unit = SR_UNIT_AMPERE; - analog->mqflags |= SR_MQFLAG_DC; - break; - case MODE_AC_UA: /* Fall through */ - case MODE_AC_MA: /* Fall through */ - case MODE_AC_A: - analog->mq = SR_MQ_CURRENT; - analog->unit = SR_UNIT_AMPERE; - analog->mqflags |= SR_MQFLAG_AC; - break; - case MODE_OHM: - analog->mq = SR_MQ_RESISTANCE; - analog->unit = SR_UNIT_OHM; - break; - case MODE_FARAD: - analog->mq = SR_MQ_CAPACITANCE; - analog->unit = SR_UNIT_FARAD; - break; - case MODE_CONT: - analog->mq = SR_MQ_CONTINUITY; - analog->unit = SR_UNIT_BOOLEAN; - rawval = is_shortcirc(rs_packet); - break; - case MODE_DIODE: - analog->mq = SR_MQ_VOLTAGE; - analog->unit = SR_UNIT_VOLT; - analog->mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC; - break; - case MODE_HZ: /* Fall through */ - case MODE_VOLT_HZ: /* Fall through */ - case MODE_AMP_HZ: - analog->mq = SR_MQ_FREQUENCY; - analog->unit = SR_UNIT_HERTZ; - break; - case MODE_LOGIC: - /* - * No matter whether or not we have an actual voltage reading, - * we are measuring voltage, so we set our MQ as VOLTAGE. - */ - analog->mq = SR_MQ_VOLTAGE; - if (!isnan(rawval)) { - /* We have an actual voltage. */ - analog->unit = SR_UNIT_VOLT; - } else { - /* We have either HI or LOW. */ - analog->unit = SR_UNIT_BOOLEAN; - rawval = is_logic_high(rs_packet); - } - break; - case MODE_HFE: - analog->mq = SR_MQ_GAIN; - analog->unit = SR_UNIT_UNITLESS; - break; - case MODE_DUTY: /* Fall through */ - case MODE_VOLT_DUTY: /* Fall through */ - case MODE_AMP_DUTY: - analog->mq = SR_MQ_DUTY_CYCLE; - analog->unit = SR_UNIT_PERCENTAGE; - break; - case MODE_WIDTH: /* Fall through */ - case MODE_VOLT_WIDTH: /* Fall through */ - case MODE_AMP_WIDTH: - analog->mq = SR_MQ_PULSE_WIDTH; - analog->unit = SR_UNIT_SECOND; - break; - case MODE_TEMP: - analog->mq = SR_MQ_TEMPERATURE; - /* We need to reparse. */ - rawval = lcd_to_double(rs_packet, READ_TEMP); - analog->unit = is_celsius(rs_packet) ? - SR_UNIT_CELSIUS : SR_UNIT_FAHRENHEIT; - break; - case MODE_DBM: - analog->mq = SR_MQ_POWER; - analog->unit = SR_UNIT_DECIBEL_MW; - analog->mqflags |= SR_MQFLAG_AC; - break; - default: - sr_dbg("Unknown mode: %d.", rs_packet->mode); - break; - } - - if (rs_packet->info & INFO_HOLD) - analog->mqflags |= SR_MQFLAG_HOLD; - if (rs_packet->digit4 & DIG4_MAX) - analog->mqflags |= SR_MQFLAG_MAX; - if (rs_packet->indicatrix2 & IND2_MIN) - analog->mqflags |= SR_MQFLAG_MIN; - if (rs_packet->info & INFO_AUTO) - analog->mqflags |= SR_MQFLAG_AUTORANGE; - - *floatval = rawval; - return SR_OK; -} diff --git a/hardware/common/ezusb.c b/hardware/common/ezusb.c deleted file mode 100644 index 044b4642..00000000 --- a/hardware/common/ezusb.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2010-2012 Bert Vermeulen - * - * 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 . - */ - -/* - * Helper functions for the Cypress EZ-USB / FX2 series chips. - */ - -#include -#include -#include -#include -#include -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#define LOG_PREFIX "ezusb" - -SR_PRIV int ezusb_reset(struct libusb_device_handle *hdl, int set_clear) -{ - int ret; - unsigned char buf[1]; - - sr_info("setting CPU reset mode %s...", - set_clear ? "on" : "off"); - buf[0] = set_clear ? 1 : 0; - ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR, 0xa0, - 0xe600, 0x0000, buf, 1, 100); - if (ret < 0) - sr_err("Unable to send control request: %s.", - libusb_error_name(ret)); - - return ret; -} - -SR_PRIV int ezusb_install_firmware(libusb_device_handle *hdl, - const char *filename) -{ - FILE *fw; - int offset, chunksize, ret, result; - unsigned char buf[4096]; - - sr_info("Uploading firmware at %s", filename); - if ((fw = g_fopen(filename, "rb")) == NULL) { - sr_err("Unable to open firmware file %s for reading: %s", - filename, strerror(errno)); - return SR_ERR; - } - - result = SR_OK; - offset = 0; - while (1) { - chunksize = fread(buf, 1, 4096, fw); - if (chunksize == 0) - break; - ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR | - LIBUSB_ENDPOINT_OUT, 0xa0, offset, - 0x0000, buf, chunksize, 100); - if (ret < 0) { - sr_err("Unable to send firmware to device: %s.", - libusb_error_name(ret)); - result = SR_ERR; - break; - } - sr_info("Uploaded %d bytes", chunksize); - offset += chunksize; - } - fclose(fw); - sr_info("Firmware upload done"); - - return result; -} - -SR_PRIV int ezusb_upload_firmware(libusb_device *dev, int configuration, - const char *filename) -{ - struct libusb_device_handle *hdl; - int ret; - - sr_info("uploading firmware to device on %d.%d", - libusb_get_bus_number(dev), libusb_get_device_address(dev)); - - if ((ret = libusb_open(dev, &hdl)) < 0) { - sr_err("failed to open device: %s.", libusb_error_name(ret)); - return SR_ERR; - } - -/* - * The libusbx darwin backend is broken: it can report a kernel driver being - * active, but detaching it always returns an error. - */ -#if !defined(__APPLE__) - if (libusb_kernel_driver_active(hdl, 0) == 1) { - if ((ret = libusb_detach_kernel_driver(hdl, 0)) < 0) { - sr_err("failed to detach kernel driver: %s", - libusb_error_name(ret)); - return SR_ERR; - } - } -#endif - - if ((ret = libusb_set_configuration(hdl, configuration)) < 0) { - sr_err("Unable to set configuration: %s", - libusb_error_name(ret)); - return SR_ERR; - } - - if ((ezusb_reset(hdl, 1)) < 0) - return SR_ERR; - - if (ezusb_install_firmware(hdl, filename) < 0) - return SR_ERR; - - if ((ezusb_reset(hdl, 0)) < 0) - return SR_ERR; - - libusb_close(hdl); - - return SR_OK; -} diff --git a/hardware/common/scpi.c b/hardware/common/scpi.c deleted file mode 100644 index 829a4c8c..00000000 --- a/hardware/common/scpi.c +++ /dev/null @@ -1,754 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2013 poljar (Damir Jelić) - * - * 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 . - */ - -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#include -#include - -#define LOG_PREFIX "scpi" - -#define SCPI_READ_RETRIES 100 -#define SCPI_READ_RETRY_TIMEOUT 10000 - -/** - * Parse a string representation of a boolean-like value into a gboolean. - * Similar to sr_parse_boolstring but rejects strings which do not represent - * a boolean-like value. - * - * @param str String to convert. - * @param ret Pointer to a gboolean where the result of the conversion will be - * stored. - * - * @return SR_OK on success, SR_ERR on failure. - */ -static int parse_strict_bool(const char *str, gboolean *ret) -{ - if (!str) - return SR_ERR_ARG; - - if (!g_strcmp0(str, "1") || - !g_ascii_strncasecmp(str, "y", 1) || - !g_ascii_strncasecmp(str, "t", 1) || - !g_ascii_strncasecmp(str, "yes", 3) || - !g_ascii_strncasecmp(str, "true", 4) || - !g_ascii_strncasecmp(str, "on", 2)) { - *ret = TRUE; - return SR_OK; - } else if (!g_strcmp0(str, "0") || - !g_ascii_strncasecmp(str, "n", 1) || - !g_ascii_strncasecmp(str, "f", 1) || - !g_ascii_strncasecmp(str, "no", 2) || - !g_ascii_strncasecmp(str, "false", 5) || - !g_ascii_strncasecmp(str, "off", 3)) { - *ret = FALSE; - return SR_OK; - } - - return SR_ERR; -} - -SR_PRIV extern const struct sr_scpi_dev_inst scpi_serial_dev; -SR_PRIV extern const struct sr_scpi_dev_inst scpi_tcp_raw_dev; -SR_PRIV extern const struct sr_scpi_dev_inst scpi_tcp_rigol_dev; -SR_PRIV extern const struct sr_scpi_dev_inst scpi_usbtmc_libusb_dev; -SR_PRIV extern const struct sr_scpi_dev_inst scpi_vxi_dev; -SR_PRIV extern const struct sr_scpi_dev_inst scpi_visa_dev; - -static const struct sr_scpi_dev_inst *scpi_devs[] = { - &scpi_tcp_raw_dev, - &scpi_tcp_rigol_dev, -#ifdef HAVE_LIBUSB_1_0 - &scpi_usbtmc_libusb_dev, -#endif -#if HAVE_RPC - &scpi_vxi_dev, -#endif -#ifdef HAVE_LIBREVISA - &scpi_visa_dev, -#endif -#ifdef HAVE_LIBSERIALPORT - &scpi_serial_dev, /* must be last as it matches any resource */ -#endif -}; - -static struct sr_dev_inst *sr_scpi_scan_resource(struct drv_context *drvc, - const char *resource, const char *serialcomm, - struct sr_dev_inst *(*probe_device)(struct sr_scpi_dev_inst *scpi)) -{ - struct sr_scpi_dev_inst *scpi; - struct sr_dev_inst *sdi; - - if (!(scpi = scpi_dev_inst_new(drvc, resource, serialcomm))) - return NULL; - - if (sr_scpi_open(scpi) != SR_OK) { - sr_info("Couldn't open SCPI device."); - sr_scpi_free(scpi); - return NULL; - }; - - if ((sdi = probe_device(scpi))) - return sdi; - - sr_scpi_close(scpi); - sr_scpi_free(scpi); - return NULL; -} - -SR_PRIV GSList *sr_scpi_scan(struct drv_context *drvc, GSList *options, - struct sr_dev_inst *(*probe_device)(struct sr_scpi_dev_inst *scpi)) -{ - GSList *resources, *l, *devices; - struct sr_dev_inst *sdi; - const char *resource = NULL; - const char *serialcomm = NULL; - gchar **res; - unsigned i; - - for (l = options; l; l = l->next) { - struct sr_config *src = l->data; - switch (src->key) { - case SR_CONF_CONN: - resource = g_variant_get_string(src->data, NULL); - break; - case SR_CONF_SERIALCOMM: - serialcomm = g_variant_get_string(src->data, NULL); - break; - } - } - - devices = NULL; - for (i = 0; i < ARRAY_SIZE(scpi_devs); i++) { - if ((resource && strcmp(resource, scpi_devs[i]->prefix)) - || !scpi_devs[i]->scan) - continue; - resources = scpi_devs[i]->scan(drvc); - for (l = resources; l; l = l->next) { - res = g_strsplit(l->data, ":", 2); - if (res[0] && (sdi = sr_scpi_scan_resource(drvc, res[0], - serialcomm ? serialcomm : res[1], probe_device))) - devices = g_slist_append(devices, sdi); - g_strfreev(res); - } - g_slist_free_full(resources, g_free); - } - - if (!devices && resource) { - sdi = sr_scpi_scan_resource(drvc, resource, serialcomm, probe_device); - devices = g_slist_append(NULL, sdi); - } - - /* Tack a copy of the newly found devices onto the driver list. */ - if (devices) - drvc->instances = g_slist_concat(drvc->instances, g_slist_copy(devices)); - - return devices; -} - -SR_PRIV struct sr_scpi_dev_inst *scpi_dev_inst_new(struct drv_context *drvc, - const char *resource, const char *serialcomm) -{ - struct sr_scpi_dev_inst *scpi = NULL; - const struct sr_scpi_dev_inst *scpi_dev; - gchar **params; - unsigned i; - - for (i = 0; i < ARRAY_SIZE(scpi_devs); i++) { - scpi_dev = scpi_devs[i]; - if (!strncmp(resource, scpi_dev->prefix, strlen(scpi_dev->prefix))) { - sr_dbg("Opening %s device %s.", scpi_dev->name, resource); - scpi = g_malloc(sizeof(*scpi)); - *scpi = *scpi_dev; - scpi->priv = g_malloc0(scpi->priv_size); - params = g_strsplit(resource, "/", 0); - if (scpi->dev_inst_new(scpi->priv, drvc, resource, - params, serialcomm) != SR_OK) { - sr_scpi_free(scpi); - scpi = NULL; - } - g_strfreev(params); - break; - } - } - - return scpi; -} - -/** - * Open SCPI device. - * - * @param scpi Previously initialized SCPI device structure. - * - * @return SR_OK on success, SR_ERR on failure. - */ -SR_PRIV int sr_scpi_open(struct sr_scpi_dev_inst *scpi) -{ - return scpi->open(scpi->priv); -} - -/** - * Add an event source for an SCPI device. - * - * @param scpi Previously initialized SCPI device structure. - * @param events Events to check for. - * @param timeout Max time to wait before the callback is called, ignored if 0. - * @param cb Callback function to add. Must not be NULL. - * @param cb_data Data for the callback function. Can be NULL. - * - * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, or - * SR_ERR_MALLOC upon memory allocation errors. - */ -SR_PRIV int sr_scpi_source_add(struct sr_session *session, - struct sr_scpi_dev_inst *scpi, int events, int timeout, - sr_receive_data_callback cb, void *cb_data) -{ - return scpi->source_add(session, scpi->priv, events, timeout, cb, cb_data); -} - -/** - * Remove event source for an SCPI device. - * - * @param scpi Previously initialized SCPI device structure. - * - * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, or - * SR_ERR_MALLOC upon memory allocation errors, SR_ERR_BUG upon - * internal errors. - */ -SR_PRIV int sr_scpi_source_remove(struct sr_session *session, - struct sr_scpi_dev_inst *scpi) -{ - return scpi->source_remove(session, scpi->priv); -} - -/** - * Send a SCPI command. - * - * @param scpi Previously initialized SCPI device structure. - * @param format Format string, to be followed by any necessary arguments. - * - * @return SR_OK on success, SR_ERR on failure. - */ -SR_PRIV int sr_scpi_send(struct sr_scpi_dev_inst *scpi, - const char *format, ...) -{ - va_list args; - int ret; - - va_start(args, format); - ret = sr_scpi_send_variadic(scpi, format, args); - va_end(args); - - return ret; -} - -/** - * Send a SCPI command with a variadic argument list. - * - * @param scpi Previously initialized SCPI device structure. - * @param format Format string. - * @param args Argument list. - * - * @return SR_OK on success, SR_ERR on failure. - */ -SR_PRIV int sr_scpi_send_variadic(struct sr_scpi_dev_inst *scpi, - const char *format, va_list args) -{ - va_list args_copy; - char *buf; - int len, ret; - - /* Get length of buffer required. */ - va_copy(args_copy, args); - len = vsnprintf(NULL, 0, format, args_copy); - va_end(args_copy); - - /* Allocate buffer and write out command. */ - buf = g_malloc(len + 1); - vsprintf(buf, format, args); - - /* Send command. */ - ret = scpi->send(scpi->priv, buf); - - /* Free command buffer. */ - g_free(buf); - - return ret; -} - -/** - * Begin receiving an SCPI reply. - * - * @param scpi Previously initialised SCPI device structure. - * - * @return SR_OK on success, SR_ERR on failure. - */ -SR_PRIV int sr_scpi_read_begin(struct sr_scpi_dev_inst *scpi) -{ - return scpi->read_begin(scpi->priv); -} - -/** - * Read part of a response from SCPI device. - * - * @param scpi Previously initialised SCPI device structure. - * @param buf Buffer to store result. - * @param maxlen Maximum number of bytes to read. - * - * @return Number of bytes read, or SR_ERR upon failure. - */ -SR_PRIV int sr_scpi_read_data(struct sr_scpi_dev_inst *scpi, - char *buf, int maxlen) -{ - return scpi->read_data(scpi->priv, buf, maxlen); -} - -/** - * Check whether a complete SCPI response has been received. - * - * @param scpi Previously initialised SCPI device structure. - * - * @return 1 if complete, 0 otherwise. - */ -SR_PRIV int sr_scpi_read_complete(struct sr_scpi_dev_inst *scpi) -{ - return scpi->read_complete(scpi->priv); -} - -/** - * Close SCPI device. - * - * @param scpi Previously initialized SCPI device structure. - * - * @return SR_OK on success, SR_ERR on failure. - */ -SR_PRIV int sr_scpi_close(struct sr_scpi_dev_inst *scpi) -{ - return scpi->close(scpi->priv); -} - -/** - * Free SCPI device. - * - * @param scpi Previously initialized SCPI device structure. - * - * @return SR_OK on success, SR_ERR on failure. - */ -SR_PRIV void sr_scpi_free(struct sr_scpi_dev_inst *scpi) -{ - scpi->free(scpi->priv); - g_free(scpi->priv); - g_free(scpi); -} - -/** - * Send a SCPI command, receive the reply and store the reply in scpi_response. - * - * @param scpi Previously initialised SCPI device structure. - * @param command The SCPI command to send to the device (can be NULL). - * @param scpi_response Pointer where to store the SCPI response. - * - * @return SR_OK on success, SR_ERR on failure. - */ -SR_PRIV int sr_scpi_get_string(struct sr_scpi_dev_inst *scpi, - const char *command, char **scpi_response) -{ - char buf[256]; - int len; - GString *response; - - if (command) - if (sr_scpi_send(scpi, command) != SR_OK) - return SR_ERR; - - if (sr_scpi_read_begin(scpi) != SR_OK) - return SR_ERR; - - response = g_string_new(""); - - *scpi_response = NULL; - - while (!sr_scpi_read_complete(scpi)) { - len = sr_scpi_read_data(scpi, buf, sizeof(buf)); - if (len < 0) { - g_string_free(response, TRUE); - return SR_ERR; - } - g_string_append_len(response, buf, len); - } - - /* Get rid of trailing linefeed if present */ - if (response->len >= 1 && response->str[response->len - 1] == '\n') - g_string_truncate(response, response->len - 1); - - *scpi_response = response->str; - g_string_free(response, FALSE); - - sr_spew("Got response: '%.70s'.", *scpi_response); - - return SR_OK; -} - -/** - * Send a SCPI command, read the reply, parse it as a bool value and store the - * result in scpi_response. - * - * @param scpi Previously initialised SCPI device structure. - * @param command The SCPI command to send to the device (can be NULL). - * @param scpi_response Pointer where to store the parsed result. - * - * @return SR_OK on success, SR_ERR on failure. - */ -SR_PRIV int sr_scpi_get_bool(struct sr_scpi_dev_inst *scpi, - const char *command, gboolean *scpi_response) -{ - int ret; - char *response; - - response = NULL; - - if (sr_scpi_get_string(scpi, command, &response) != SR_OK) - if (!response) - return SR_ERR; - - if (parse_strict_bool(response, scpi_response) == SR_OK) - ret = SR_OK; - else - ret = SR_ERR; - - g_free(response); - - return ret; -} - -/** - * Send a SCPI command, read the reply, parse it as an integer and store the - * result in scpi_response. - * - * @param scpi Previously initialised SCPI device structure. - * @param command The SCPI command to send to the device (can be NULL). - * @param scpi_response Pointer where to store the parsed result. - * - * @return SR_OK on success, SR_ERR on failure. - */ -SR_PRIV int sr_scpi_get_int(struct sr_scpi_dev_inst *scpi, - const char *command, int *scpi_response) -{ - int ret; - char *response; - - response = NULL; - - if (sr_scpi_get_string(scpi, command, &response) != SR_OK) - if (!response) - return SR_ERR; - - if (sr_atoi(response, scpi_response) == SR_OK) - ret = SR_OK; - else - ret = SR_ERR; - - g_free(response); - - return ret; -} - -/** - * Send a SCPI command, read the reply, parse it as a float and store the - * result in scpi_response. - * - * @param scpi Previously initialised SCPI device structure. - * @param command The SCPI command to send to the device (can be NULL). - * @param scpi_response Pointer where to store the parsed result. - * - * @return SR_OK on success, SR_ERR on failure. - */ -SR_PRIV int sr_scpi_get_float(struct sr_scpi_dev_inst *scpi, - const char *command, float *scpi_response) -{ - int ret; - char *response; - - response = NULL; - - if (sr_scpi_get_string(scpi, command, &response) != SR_OK) - if (!response) - return SR_ERR; - - if (sr_atof_ascii(response, scpi_response) == SR_OK) - ret = SR_OK; - else - ret = SR_ERR; - - g_free(response); - - return ret; -} - -/** - * Send a SCPI command, read the reply, parse it as a double and store the - * result in scpi_response. - * - * @param scpi Previously initialised SCPI device structure. - * @param command The SCPI command to send to the device (can be NULL). - * @param scpi_response Pointer where to store the parsed result. - * - * @return SR_OK on success, SR_ERR on failure. - */ -SR_PRIV int sr_scpi_get_double(struct sr_scpi_dev_inst *scpi, - const char *command, double *scpi_response) -{ - int ret; - char *response; - - response = NULL; - - if (sr_scpi_get_string(scpi, command, &response) != SR_OK) - if (!response) - return SR_ERR; - - if (sr_atod(response, scpi_response) == SR_OK) - ret = SR_OK; - else - ret = SR_ERR; - - g_free(response); - - return ret; -} - -/** - * Send a SCPI *OPC? command, read the reply and return the result of the - * command. - * - * @param scpi Previously initialised SCPI device structure. - * - * @return SR_OK on success, SR_ERR on failure. - */ -SR_PRIV int sr_scpi_get_opc(struct sr_scpi_dev_inst *scpi) -{ - unsigned int i; - gboolean opc; - - for (i = 0; i < SCPI_READ_RETRIES; ++i) { - sr_scpi_get_bool(scpi, SCPI_CMD_OPC, &opc); - if (opc) - return SR_OK; - g_usleep(SCPI_READ_RETRY_TIMEOUT); - } - - return SR_ERR; -} - -/** - * Send a SCPI command, read the reply, parse it as comma separated list of - * floats and store the as an result in scpi_response. - * - * @param scpi Previously initialised SCPI device structure. - * @param command The SCPI command to send to the device (can be NULL). - * @param scpi_response Pointer where to store the parsed result. - * - * @return SR_OK upon successfully parsing all values, SR_ERR upon a parsing - * error or upon no response. The allocated response must be freed by - * the caller in the case of an SR_OK as well as in the case of - * parsing error. - */ -SR_PRIV int sr_scpi_get_floatv(struct sr_scpi_dev_inst *scpi, - const char *command, GArray **scpi_response) -{ - int ret; - float tmp; - char *response; - gchar **ptr, **tokens; - GArray *response_array; - - ret = SR_OK; - response = NULL; - tokens = NULL; - - if (sr_scpi_get_string(scpi, command, &response) != SR_OK) - if (!response) - return SR_ERR; - - tokens = g_strsplit(response, ",", 0); - ptr = tokens; - - response_array = g_array_sized_new(TRUE, FALSE, sizeof(float), 256); - - while (*ptr) { - if (sr_atof_ascii(*ptr, &tmp) == SR_OK) - response_array = g_array_append_val(response_array, - tmp); - else - ret = SR_ERR; - - ptr++; - } - g_strfreev(tokens); - g_free(response); - - if (ret == SR_ERR && response_array->len == 0) { - g_array_free(response_array, TRUE); - *scpi_response = NULL; - return SR_ERR; - } - - *scpi_response = response_array; - - return ret; -} - -/** - * Send a SCPI command, read the reply, parse it as comma separated list of - * unsigned 8 bit integers and store the as an result in scpi_response. - * - * @param scpi Previously initialised SCPI device structure. - * @param command The SCPI command to send to the device (can be NULL). - * @param scpi_response Pointer where to store the parsed result. - * - * @return SR_OK upon successfully parsing all values, SR_ERR upon a parsing - * error or upon no response. The allocated response must be freed by - * the caller in the case of an SR_OK as well as in the case of - * parsing error. - */ -SR_PRIV int sr_scpi_get_uint8v(struct sr_scpi_dev_inst *scpi, - const char *command, GArray **scpi_response) -{ - int tmp, ret; - char *response; - gchar **ptr, **tokens; - GArray *response_array; - - ret = SR_OK; - response = NULL; - tokens = NULL; - - if (sr_scpi_get_string(scpi, command, &response) != SR_OK) - if (!response) - return SR_ERR; - - tokens = g_strsplit(response, ",", 0); - ptr = tokens; - - response_array = g_array_sized_new(TRUE, FALSE, sizeof(uint8_t), 256); - - while (*ptr) { - if (sr_atoi(*ptr, &tmp) == SR_OK) - response_array = g_array_append_val(response_array, - tmp); - else - ret = SR_ERR; - - ptr++; - } - g_strfreev(tokens); - g_free(response); - - if (response_array->len == 0) { - g_array_free(response_array, TRUE); - *scpi_response = NULL; - return SR_ERR; - } - - *scpi_response = response_array; - - return ret; -} - -/** - * Send the *IDN? SCPI command, receive the reply, parse it and store the - * reply as a sr_scpi_hw_info structure in the supplied scpi_response pointer. - * - * The hw_info structure must be freed by the caller via sr_scpi_hw_info_free(). - * - * @param scpi Previously initialised SCPI device structure. - * @param scpi_response Pointer where to store the hw_info structure. - * - * @return SR_OK upon success, SR_ERR on failure. - */ -SR_PRIV int sr_scpi_get_hw_id(struct sr_scpi_dev_inst *scpi, - struct sr_scpi_hw_info **scpi_response) -{ - int num_tokens; - char *response; - gchar **tokens; - struct sr_scpi_hw_info *hw_info; - - response = NULL; - tokens = NULL; - - if (sr_scpi_get_string(scpi, SCPI_CMD_IDN, &response) != SR_OK) - if (!response) - return SR_ERR; - - sr_info("Got IDN string: '%s'", response); - - /* - * The response to a '*IDN?' is specified by the SCPI spec. It contains - * a comma-separated list containing the manufacturer name, instrument - * model, serial number of the instrument and the firmware version. - */ - tokens = g_strsplit(response, ",", 0); - - for (num_tokens = 0; tokens[num_tokens] != NULL; num_tokens++); - - if (num_tokens != 4) { - sr_dbg("IDN response not according to spec: %80.s.", response); - g_strfreev(tokens); - g_free(response); - return SR_ERR; - } - g_free(response); - - hw_info = g_try_malloc(sizeof(struct sr_scpi_hw_info)); - if (!hw_info) { - g_strfreev(tokens); - return SR_ERR_MALLOC; - } - - hw_info->manufacturer = g_strdup(tokens[0]); - hw_info->model = g_strdup(tokens[1]); - hw_info->serial_number = g_strdup(tokens[2]); - hw_info->firmware_version = g_strdup(tokens[3]); - - g_strfreev(tokens); - - *scpi_response = hw_info; - - return SR_OK; -} - -/** - * Free a sr_scpi_hw_info struct. - * - * @param hw_info Pointer to the struct to free. - * - * This function is safe to call with a NULL pointer. - */ -SR_PRIV void sr_scpi_hw_info_free(struct sr_scpi_hw_info *hw_info) -{ - if (hw_info) { - g_free(hw_info->manufacturer); - g_free(hw_info->model); - g_free(hw_info->serial_number); - g_free(hw_info->firmware_version); - g_free(hw_info); - } -} diff --git a/hardware/common/scpi_serial.c b/hardware/common/scpi_serial.c deleted file mode 100644 index feb33176..00000000 --- a/hardware/common/scpi_serial.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2013 poljar (Damir Jelić) - * Copyright (C) 2013 Martin Ling - * - * 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 . - */ - -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#include -#include -#include - -#define LOG_PREFIX "scpi_serial" - -#define BUFFER_SIZE 1024 - -struct scpi_serial { - struct sr_serial_dev_inst *serial; - char buffer[BUFFER_SIZE]; - size_t count; - size_t read; -}; - -static struct { - uint16_t vendor_id; - uint16_t product_id; - const char *serialcomm; -} scpi_serial_usb_ids[] = { - { 0x0403, 0xed72, "115200/8n1/flow=1" }, /* Hameg HO720 */ - { 0x0403, 0xed73, "115200/8n1/flow=1" }, /* Hameg HO730 */ -}; - -static GSList *scpi_serial_scan(struct drv_context *drvc) -{ - GSList *l, *r, *resources = NULL; - gchar *res; - unsigned i; - - (void)drvc; - - for (i = 0; i < ARRAY_SIZE(scpi_serial_usb_ids); i++) { - if ((l = sr_serial_find_usb(scpi_serial_usb_ids[i].vendor_id, - scpi_serial_usb_ids[i].product_id)) == NULL) - continue; - for (r = l; r; r = r->next) { - if (scpi_serial_usb_ids[i].serialcomm) - res = g_strdup_printf("%s:%s", (char *) r->data, - scpi_serial_usb_ids[i].serialcomm); - else - res = g_strdup(r->data); - resources = g_slist_append(resources, res); - } - g_slist_free_full(l, g_free); - } - - return resources; -} - -static int scpi_serial_dev_inst_new(void *priv, struct drv_context *drvc, - const char *resource, char **params, const char *serialcomm) -{ - struct scpi_serial *sscpi = priv; - - (void)drvc; - (void)params; - - if (!(sscpi->serial = sr_serial_dev_inst_new(resource, serialcomm))) - return SR_ERR; - - return SR_OK; -} - -static int scpi_serial_open(void *priv) -{ - struct scpi_serial *sscpi = priv; - struct sr_serial_dev_inst *serial = sscpi->serial; - - if (serial_open(serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK) - return SR_ERR; - - if (serial_flush(serial) != SR_OK) - return SR_ERR; - - sscpi->count = 0; - sscpi->read = 0; - - return SR_OK; -} - -static int scpi_serial_source_add(struct sr_session *session, void *priv, - int events, int timeout, sr_receive_data_callback cb, void *cb_data) -{ - struct scpi_serial *sscpi = priv; - struct sr_serial_dev_inst *serial = sscpi->serial; - - return serial_source_add(session, serial, events, timeout, cb, cb_data); -} - -static int scpi_serial_source_remove(struct sr_session *session, void *priv) -{ - struct scpi_serial *sscpi = priv; - struct sr_serial_dev_inst *serial = sscpi->serial; - - return serial_source_remove(session, serial); -} - -static int scpi_serial_send(void *priv, const char *command) -{ - int len, result, written; - gchar *terminated_command; - struct scpi_serial *sscpi = priv; - struct sr_serial_dev_inst *serial = sscpi->serial; - - terminated_command = g_strconcat(command, "\n", NULL); - len = strlen(terminated_command); - written = 0; - while (written < len) { - result = serial_write(serial, terminated_command + written, len - written); - if (result < 0) { - sr_err("Error while sending SCPI command: '%s'.", command); - g_free(terminated_command); - return SR_ERR; - } - written += result; - } - - g_free(terminated_command); - - sr_spew("Successfully sent SCPI command: '%s'.", command); - - return SR_OK; -} - -static int scpi_serial_read_begin(void *priv) -{ - (void) priv; - - return SR_OK; -} - -static int scpi_serial_read_data(void *priv, char *buf, int maxlen) -{ - struct scpi_serial *sscpi = priv; - int len, ret; - - len = BUFFER_SIZE - sscpi->count; - - /* Try to read new data into the buffer if there is space. */ - if (len > 0) { - ret = serial_read(sscpi->serial, sscpi->buffer + sscpi->read, - BUFFER_SIZE - sscpi->count); - - if (ret < 0) - return ret; - - sscpi->count += ret; - - if (ret > 0) - sr_spew("Read %d bytes into buffer.", ret); - } - - /* Return as many bytes as possible from buffer, excluding any trailing newline. */ - if (sscpi->read < sscpi->count) { - len = sscpi->count - sscpi->read; - if (len > maxlen) - len = maxlen; - if (sscpi->buffer[sscpi->read + len - 1] == '\n') - len--; - sr_spew("Returning %d bytes from buffer.", len); - memcpy(buf, sscpi->buffer + sscpi->read, len); - sscpi->read += len; - if (sscpi->read == BUFFER_SIZE) { - sr_spew("Resetting buffer."); - sscpi->count = 0; - sscpi->read = 0; - } - return len; - } - - return 0; -} - -static int scpi_serial_read_complete(void *priv) -{ - struct scpi_serial *sscpi = priv; - - /* If the next character is a newline, discard it and report complete. */ - if (sscpi->read < sscpi->count && sscpi->buffer[sscpi->read] == '\n') { - sscpi->read++; - return 1; - } else { - return 0; - } -} - -static int scpi_serial_close(void *priv) -{ - struct scpi_serial *sscpi = priv; - - return serial_close(sscpi->serial); -} - -static void scpi_serial_free(void *priv) -{ - struct scpi_serial *sscpi = priv; - - sr_serial_dev_inst_free(sscpi->serial); -} - -SR_PRIV const struct sr_scpi_dev_inst scpi_serial_dev = { - .name = "serial", - .prefix = "", - .priv_size = sizeof(struct scpi_serial), - .scan = scpi_serial_scan, - .dev_inst_new = scpi_serial_dev_inst_new, - .open = scpi_serial_open, - .source_add = scpi_serial_source_add, - .source_remove = scpi_serial_source_remove, - .send = scpi_serial_send, - .read_begin = scpi_serial_read_begin, - .read_data = scpi_serial_read_data, - .read_complete = scpi_serial_read_complete, - .close = scpi_serial_close, - .free = scpi_serial_free, -}; diff --git a/hardware/common/scpi_tcp.c b/hardware/common/scpi_tcp.c deleted file mode 100644 index ef3a6c75..00000000 --- a/hardware/common/scpi_tcp.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2013 Martin Ling - * - * 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 . - */ - -#ifdef _WIN32 -#define _WIN32_WINNT 0x0501 -#include -#include -#endif - -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#include -#include -#include -#ifndef _WIN32 -#include -#include -#include -#include -#endif -#include - -#define LOG_PREFIX "scpi_tcp" - -#define LENGTH_BYTES 4 - -struct scpi_tcp { - char *address; - char *port; - int socket; - char length_buf[LENGTH_BYTES]; - int length_bytes_read; - int response_length; - int response_bytes_read; -}; - -static int scpi_tcp_dev_inst_new(void *priv, struct drv_context *drvc, - const char *resource, char **params, const char *serialcomm) -{ - struct scpi_tcp *tcp = priv; - - (void)drvc; - (void)resource; - (void)serialcomm; - - if (!params || !params[1] || !params[2]) { - sr_err("Invalid parameters."); - return SR_ERR; - } - - tcp->address = g_strdup(params[1]); - tcp->port = g_strdup(params[2]); - tcp->socket = -1; - - return SR_OK; -} - -static int scpi_tcp_open(void *priv) -{ - struct scpi_tcp *tcp = priv; - struct addrinfo hints; - struct addrinfo *results, *res; - int err; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - - err = getaddrinfo(tcp->address, tcp->port, &hints, &results); - - if (err) { - sr_err("Address lookup failed: %s:%d: %s", tcp->address, tcp->port, - gai_strerror(err)); - return SR_ERR; - } - - for (res = results; res; res = res->ai_next) { - if ((tcp->socket = socket(res->ai_family, res->ai_socktype, - res->ai_protocol)) < 0) - continue; - if (connect(tcp->socket, res->ai_addr, res->ai_addrlen) != 0) { - close(tcp->socket); - tcp->socket = -1; - continue; - } - break; - } - - freeaddrinfo(results); - - if (tcp->socket < 0) { - sr_err("Failed to connect to %s:%s: %s", tcp->address, tcp->port, - strerror(errno)); - return SR_ERR; - } - - return SR_OK; -} - -static int scpi_tcp_source_add(struct sr_session *session, void *priv, - int events, int timeout, sr_receive_data_callback cb, void *cb_data) -{ - struct scpi_tcp *tcp = priv; - - return sr_session_source_add(session, tcp->socket, events, timeout, - cb, cb_data); -} - -static int scpi_tcp_source_remove(struct sr_session *session, void *priv) -{ - struct scpi_tcp *tcp = priv; - - return sr_session_source_remove(session, tcp->socket); -} - -static int scpi_tcp_send(void *priv, const char *command) -{ - struct scpi_tcp *tcp = priv; - int len, out; - char *terminated_command; - - terminated_command = g_strdup_printf("%s\r\n", command); - len = strlen(terminated_command); - out = send(tcp->socket, terminated_command, len, 0); - g_free(terminated_command); - - if (out < 0) { - sr_err("Send error: %s", strerror(errno)); - return SR_ERR; - } - - if (out < len) { - sr_dbg("Only sent %d/%d bytes of SCPI command: '%s'.", out, - len, command); - } - - sr_spew("Successfully sent SCPI command: '%s'.", command); - - return SR_OK; -} - -static int scpi_tcp_read_begin(void *priv) -{ - struct scpi_tcp *tcp = priv; - - tcp->response_bytes_read = 0; - tcp->length_bytes_read = 0; - - return SR_OK; -} - -static int scpi_tcp_raw_read_data(void *priv, char *buf, int maxlen) -{ - struct scpi_tcp *tcp = priv; - int len; - - len = recv(tcp->socket, buf, maxlen, 0); - - if (len < 0) { - sr_err("Receive error: %s", strerror(errno)); - return SR_ERR; - } - - tcp->length_bytes_read = LENGTH_BYTES; - tcp->response_length = len < maxlen ? len : maxlen + 1; - tcp->response_bytes_read = len; - - return len; -} - -static int scpi_tcp_rigol_read_data(void *priv, char *buf, int maxlen) -{ - struct scpi_tcp *tcp = priv; - int len; - - if (tcp->length_bytes_read < LENGTH_BYTES) { - len = recv(tcp->socket, tcp->length_buf + tcp->length_bytes_read, - LENGTH_BYTES - tcp->length_bytes_read, 0); - if (len < 0) { - sr_err("Receive error: %s", strerror(errno)); - return SR_ERR; - } - - tcp->length_bytes_read += len; - - if (tcp->length_bytes_read < LENGTH_BYTES) - return 0; - else - tcp->response_length = RL32(tcp->length_buf); - } - - if (tcp->response_bytes_read >= tcp->response_length) - return SR_ERR; - - len = recv(tcp->socket, buf, maxlen, 0); - - if (len < 0) { - sr_err("Receive error: %s", strerror(errno)); - return SR_ERR; - } - - tcp->response_bytes_read += len; - - return len; -} - -static int scpi_tcp_read_complete(void *priv) -{ - struct scpi_tcp *tcp = priv; - - return (tcp->length_bytes_read == LENGTH_BYTES && - tcp->response_bytes_read >= tcp->response_length); -} - -static int scpi_tcp_close(void *priv) -{ - struct scpi_tcp *tcp = priv; - - if (close(tcp->socket) < 0) - return SR_ERR; - - return SR_OK; -} - -static void scpi_tcp_free(void *priv) -{ - struct scpi_tcp *tcp = priv; - - g_free(tcp->address); - g_free(tcp->port); -} - -SR_PRIV const struct sr_scpi_dev_inst scpi_tcp_raw_dev = { - .name = "RAW TCP", - .prefix = "tcp-raw", - .priv_size = sizeof(struct scpi_tcp), - .dev_inst_new = scpi_tcp_dev_inst_new, - .open = scpi_tcp_open, - .source_add = scpi_tcp_source_add, - .source_remove = scpi_tcp_source_remove, - .send = scpi_tcp_send, - .read_begin = scpi_tcp_read_begin, - .read_data = scpi_tcp_raw_read_data, - .read_complete = scpi_tcp_read_complete, - .close = scpi_tcp_close, - .free = scpi_tcp_free, -}; - -SR_PRIV const struct sr_scpi_dev_inst scpi_tcp_rigol_dev = { - .name = "RIGOL TCP", - .prefix = "tcp-rigol", - .priv_size = sizeof(struct scpi_tcp), - .dev_inst_new = scpi_tcp_dev_inst_new, - .open = scpi_tcp_open, - .source_add = scpi_tcp_source_add, - .source_remove = scpi_tcp_source_remove, - .send = scpi_tcp_send, - .read_begin = scpi_tcp_read_begin, - .read_data = scpi_tcp_rigol_read_data, - .read_complete = scpi_tcp_read_complete, - .close = scpi_tcp_close, - .free = scpi_tcp_free, -}; diff --git a/hardware/common/scpi_usbtmc_libusb.c b/hardware/common/scpi_usbtmc_libusb.c deleted file mode 100644 index c4470b5d..00000000 --- a/hardware/common/scpi_usbtmc_libusb.c +++ /dev/null @@ -1,585 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2014 Aurelien Jacobs - * - * 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 . - */ - -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#define LOG_PREFIX "scpi_usbtmc" - -#define MAX_TRANSFER_LENGTH 2048 -#define TRANSFER_TIMEOUT 1000 - -struct scpi_usbtmc_libusb { - struct sr_context *ctx; - struct sr_usb_dev_inst *usb; - int detached_kernel_driver; - uint8_t interface; - uint8_t bulk_in_ep; - uint8_t bulk_out_ep; - uint8_t interrupt_ep; - uint8_t usbtmc_int_cap; - uint8_t usbtmc_dev_cap; - uint8_t usb488_dev_cap; - uint8_t bTag; - uint8_t bulkin_attributes; - uint8_t buffer[MAX_TRANSFER_LENGTH]; - int response_length; - int response_bytes_read; - int remaining_length; - int rigol_ds1000; -}; - -/* Some USBTMC-specific enums, as defined in the USBTMC standard. */ -#define SUBCLASS_USBTMC 0x03 -#define USBTMC_USB488 0x01 - -enum { - /* USBTMC control requests */ - INITIATE_ABORT_BULK_OUT = 1, - CHECK_ABORT_BULK_OUT_STATUS = 2, - INITIATE_ABORT_BULK_IN = 3, - CHECK_ABORT_BULK_IN_STATUS = 4, - INITIATE_CLEAR = 5, - CHECK_CLEAR_STATUS = 6, - GET_CAPABILITIES = 7, - INDICATOR_PULSE = 64, - - /* USB488 control requests */ - READ_STATUS_BYTE = 128, - REN_CONTROL = 160, - GO_TO_LOCAL = 161, - LOCAL_LOCKOUT = 162, -}; - -/* USBTMC capabilities */ -#define USBTMC_INT_CAP_LISTEN_ONLY 0x01 -#define USBTMC_INT_CAP_TALK_ONLY 0x02 -#define USBTMC_INT_CAP_INDICATOR 0x04 - -#define USBTMC_DEV_CAP_TERMCHAR 0x01 - -#define USB488_DEV_CAP_DT1 0x01 -#define USB488_DEV_CAP_RL1 0x02 -#define USB488_DEV_CAP_SR1 0x04 -#define USB488_DEV_CAP_SCPI 0x08 - -/* Bulk messages constants */ -#define USBTMC_BULK_HEADER_SIZE 12 - -/* Bulk MsgID values */ -#define DEV_DEP_MSG_OUT 1 -#define REQUEST_DEV_DEP_MSG_IN 2 -#define DEV_DEP_MSG_IN 2 - -/* bmTransferAttributes */ -#define EOM 0x01 -#define TERM_CHAR_ENABLED 0x02 - - -static GSList *scpi_usbtmc_libusb_scan(struct drv_context *drvc) -{ - struct libusb_device **devlist; - struct libusb_device_descriptor des; - struct libusb_config_descriptor *confdes; - const struct libusb_interface_descriptor *intfdes; - GSList *resources = NULL; - int confidx, intfidx, ret, i; - char *res; - - ret = libusb_get_device_list(drvc->sr_ctx->libusb_ctx, &devlist); - if (ret < 0) { - sr_err("Failed to get device list: %s.", - libusb_error_name(ret)); - return NULL; - } - for (i = 0; devlist[i]; i++) { - if ((ret = libusb_get_device_descriptor(devlist[i], &des)) < 0) { - sr_err("Failed to get device descriptor: %s.", - libusb_error_name(ret)); - continue; - } - - for (confidx = 0; confidx < des.bNumConfigurations; confidx++) { - if ((ret = libusb_get_config_descriptor(devlist[i], confidx, &confdes)) < 0) { - sr_dbg("Failed to get configuration descriptor: %s, " - "ignoring device.", libusb_error_name(ret)); - break; - } - for (intfidx = 0; intfidx < confdes->bNumInterfaces; intfidx++) { - intfdes = confdes->interface[intfidx].altsetting; - if (intfdes->bInterfaceClass != LIBUSB_CLASS_APPLICATION || - intfdes->bInterfaceSubClass != SUBCLASS_USBTMC || - intfdes->bInterfaceProtocol != USBTMC_USB488) - continue; - sr_dbg("Found USBTMC device (VID:PID = %04x:%04x, " - "bus.address = %d.%d).", des.idVendor, des.idProduct, - libusb_get_bus_number(devlist[i]), - libusb_get_device_address(devlist[i])); - res = g_strdup_printf("usbtmc/%d.%d", - libusb_get_bus_number(devlist[i]), - libusb_get_device_address(devlist[i])); - resources = g_slist_append(resources, res); - } - libusb_free_config_descriptor(confdes); - } - } - libusb_free_device_list(devlist, 1); - - sr_dbg("Found %d device(s).", g_slist_length(resources)); - - return resources; -} - -static int scpi_usbtmc_libusb_dev_inst_new(void *priv, struct drv_context *drvc, - const char *resource, char **params, const char *serialcomm) -{ - struct scpi_usbtmc_libusb *uscpi = priv; - GSList *devices; - - (void)resource; - (void)serialcomm; - - if (!params || !params[1]) { - sr_err("Invalid parameters."); - return SR_ERR; - } - - uscpi->ctx = drvc->sr_ctx; - devices = sr_usb_find(uscpi->ctx->libusb_ctx, params[1]); - if (g_slist_length(devices) != 1) { - sr_err("Failed to find USB device '%s'.", params[1]); - g_slist_free_full(devices, (GDestroyNotify)sr_usb_dev_inst_free); - return SR_ERR; - } - uscpi->usb = devices->data; - g_slist_free(devices); - - return SR_OK; -} - -static int scpi_usbtmc_libusb_open(void *priv) -{ - struct scpi_usbtmc_libusb *uscpi = priv; - struct sr_usb_dev_inst *usb = uscpi->usb; - struct libusb_device *dev; - struct libusb_device_descriptor des; - struct libusb_config_descriptor *confdes; - const struct libusb_interface_descriptor *intfdes; - const struct libusb_endpoint_descriptor *ep; - int confidx, intfidx, epidx, config = 0; - uint8_t capabilities[24]; - int ret, found = 0; - - if (usb->devhdl) - return SR_OK; - - if (sr_usb_open(uscpi->ctx->libusb_ctx, usb) != SR_OK) - return SR_ERR; - - dev = libusb_get_device(usb->devhdl); - if ((ret = libusb_get_device_descriptor(dev, &des)) < 0) { - sr_err("Failed to get device descriptor: %s.", - libusb_error_name(ret)); - return SR_ERR; - } - - for (confidx = 0; confidx < des.bNumConfigurations; confidx++) { - if ((ret = libusb_get_config_descriptor(dev, confidx, &confdes)) < 0) { - sr_dbg("Failed to get configuration descriptor: %s, " - "ignoring device.", libusb_error_name(ret)); - continue; - } - for (intfidx = 0; intfidx < confdes->bNumInterfaces; intfidx++) { - intfdes = confdes->interface[intfidx].altsetting; - if (intfdes->bInterfaceClass != LIBUSB_CLASS_APPLICATION || - intfdes->bInterfaceSubClass != SUBCLASS_USBTMC || - intfdes->bInterfaceProtocol != USBTMC_USB488) - continue; - uscpi->interface = intfdes->bInterfaceNumber; - sr_dbg("Interface %d", uscpi->interface); - config = confdes->bConfigurationValue; - sr_dbg("Configuration %d", config); - for (epidx = 0; epidx < intfdes->bNumEndpoints; epidx++) { - ep = &intfdes->endpoint[epidx]; - if (ep->bmAttributes == LIBUSB_TRANSFER_TYPE_BULK && - !(ep->bEndpointAddress & (LIBUSB_ENDPOINT_DIR_MASK))) { - uscpi->bulk_out_ep = ep->bEndpointAddress; - sr_dbg("Bulk OUT EP %d", uscpi->bulk_out_ep); - } - if (ep->bmAttributes == LIBUSB_TRANSFER_TYPE_BULK && - ep->bEndpointAddress & (LIBUSB_ENDPOINT_DIR_MASK)) { - uscpi->bulk_in_ep = ep->bEndpointAddress; - sr_dbg("Bulk IN EP %d", uscpi->bulk_in_ep); - } - if (ep->bmAttributes == LIBUSB_TRANSFER_TYPE_INTERRUPT && - ep->bEndpointAddress & (LIBUSB_ENDPOINT_DIR_MASK)) { - uscpi->interrupt_ep = ep->bEndpointAddress; - sr_dbg("Interrupt EP %d", uscpi->interrupt_ep); - } - } - found = 1; - uscpi->rigol_ds1000 = des.idVendor == 0x1ab1 && - des.idProduct == 0x0588; - } - libusb_free_config_descriptor(confdes); - if (found) - break; - } - - if (!found) { - sr_err("Failed to find USBTMC interface."); - return SR_ERR; - } - - if (libusb_kernel_driver_active(usb->devhdl, uscpi->interface) == 1) { - if ((ret = libusb_detach_kernel_driver(usb->devhdl, - uscpi->interface)) < 0) { - sr_err("Failed to detach kernel driver: %s.", - libusb_error_name(ret)); - return SR_ERR; - } - uscpi->detached_kernel_driver = 1; - } - - if ((ret = libusb_set_configuration(usb->devhdl, config)) < 0) { - sr_err("Failed to set configuration: %s.", - libusb_error_name(ret)); - return SR_ERR; - } - - if ((ret = libusb_claim_interface(usb->devhdl, uscpi->interface)) < 0) { - sr_err("Failed to claim interface: %s.", - libusb_error_name(ret)); - return SR_ERR; - } - - if (!uscpi->rigol_ds1000) { - if ((ret = libusb_clear_halt(usb->devhdl, uscpi->bulk_in_ep)) < 0) { - sr_err("Failed to clear halt/stall condition for EP %d: %s.", - uscpi->bulk_in_ep, libusb_error_name(ret)); - return SR_ERR; - } - if ((ret = libusb_clear_halt(usb->devhdl, uscpi->bulk_out_ep)) < 0) { - sr_err("Failed to clear halt/stall condition for EP %d: %s.", - uscpi->bulk_out_ep, libusb_error_name(ret)); - return SR_ERR; - } - if ((ret = libusb_clear_halt(usb->devhdl, uscpi->interrupt_ep)) < 0) { - sr_err("Failed to clear halt/stall condition for EP %d: %s.", - uscpi->interrupt_ep, libusb_error_name(ret)); - return SR_ERR; - } - } - - /* Get capabilities. */ - ret = libusb_control_transfer(usb->devhdl, - LIBUSB_ENDPOINT_IN | - LIBUSB_REQUEST_TYPE_CLASS | - LIBUSB_RECIPIENT_INTERFACE, - GET_CAPABILITIES, 0, - uscpi->interface, - capabilities, sizeof(capabilities), - TRANSFER_TIMEOUT); - if (ret == sizeof(capabilities)) { - uscpi->usbtmc_int_cap = capabilities[ 4]; - uscpi->usbtmc_dev_cap = capabilities[ 5]; - uscpi->usb488_dev_cap = capabilities[15]; - } - sr_dbg("Device capabilities: %s%s%s%s%s, %s, %s", - uscpi->usb488_dev_cap & USB488_DEV_CAP_SCPI ? "SCPI, " : "", - uscpi->usbtmc_dev_cap & USBTMC_DEV_CAP_TERMCHAR ? "TermChar, ": "", - uscpi->usbtmc_int_cap & USBTMC_INT_CAP_LISTEN_ONLY? "L3, " : - uscpi->usbtmc_int_cap & USBTMC_INT_CAP_TALK_ONLY ? "" : "L4, ", - uscpi->usbtmc_int_cap & USBTMC_INT_CAP_TALK_ONLY ? "T5, " : - uscpi->usbtmc_int_cap & USBTMC_INT_CAP_LISTEN_ONLY? "" : "T6, ", - uscpi->usb488_dev_cap & USB488_DEV_CAP_SR1 ? "SR1" : "SR0", - uscpi->usb488_dev_cap & USB488_DEV_CAP_RL1 ? "RL1" : "RL0", - uscpi->usb488_dev_cap & USB488_DEV_CAP_DT1 ? "DT1" : "DT0"); - - return SR_OK; -} - -static int scpi_usbtmc_libusb_source_add(struct sr_session *session, - void *priv, int events, int timeout, sr_receive_data_callback cb, - void *cb_data) -{ - struct scpi_usbtmc_libusb *uscpi = priv; - (void)events; - return usb_source_add(session, uscpi->ctx, timeout, cb, cb_data); -} - -static int scpi_usbtmc_libusb_source_remove(struct sr_session *session, - void *priv) -{ - struct scpi_usbtmc_libusb *uscpi = priv; - return usb_source_remove(session, uscpi->ctx); -} - -static void usbtmc_bulk_out_header_write(void *header, uint8_t MsgID, - uint8_t bTag, - uint32_t TransferSize, - uint8_t bmTransferAttributes, - char TermChar) -{ - W8(header+ 0, MsgID); - W8(header+ 1, bTag); - W8(header+ 2, ~bTag); - W8(header+ 3, 0); - WL32(header+ 4, TransferSize); - W8(header+ 8, bmTransferAttributes); - W8(header+ 9, TermChar); - WL16(header+10, 0); -} - -static int usbtmc_bulk_in_header_read(void *header, uint8_t MsgID, - unsigned char bTag, - int32_t *TransferSize, - uint8_t *bmTransferAttributes) -{ - if (R8(header+0) != MsgID || - R8(header+1) != bTag || - R8(header+2) != (unsigned char)~bTag) - return SR_ERR; - if (TransferSize) - *TransferSize = RL32(header+4); - if (bmTransferAttributes) - *bmTransferAttributes = R8(header+8); - return SR_OK; -} - -static int scpi_usbtmc_bulkout(struct scpi_usbtmc_libusb *uscpi, - uint8_t msg_id, const void *data, int32_t size, - uint8_t transfer_attributes) -{ - struct sr_usb_dev_inst *usb = uscpi->usb; - int padded_size, ret, transferred; - - if (data && size+USBTMC_BULK_HEADER_SIZE+3 > (int)sizeof(uscpi->buffer)) { - sr_err("USBTMC bulk out transfer is too big."); - return SR_ERR; - } - - uscpi->bTag++; - uscpi->bTag += !uscpi->bTag; /* bTag == 0 is invalid so avoid it. */ - - usbtmc_bulk_out_header_write(uscpi->buffer, msg_id, uscpi->bTag, - size, transfer_attributes, 0); - if (data) - memcpy(uscpi->buffer+USBTMC_BULK_HEADER_SIZE, data, size); - else - size = 0; - size += USBTMC_BULK_HEADER_SIZE; - padded_size = (size + 3) & ~0x3; - memset(uscpi->buffer+size, 0, padded_size - size); - - ret = libusb_bulk_transfer(usb->devhdl, uscpi->bulk_out_ep, - uscpi->buffer, padded_size, &transferred, - TRANSFER_TIMEOUT); - if (ret < 0) { - sr_err("USBTMC bulk out transfer error: %s.", - libusb_error_name(ret)); - return SR_ERR; - } - - if (transferred < padded_size) { - sr_dbg("USBTMC bulk out partial transfer (%d/%d bytes).", - transferred, padded_size); - return SR_ERR; - } - - return transferred - USBTMC_BULK_HEADER_SIZE; -} - -static int scpi_usbtmc_bulkin_start(struct scpi_usbtmc_libusb *uscpi, - uint8_t msg_id, void *data, int32_t size, - uint8_t *transfer_attributes) -{ - struct sr_usb_dev_inst *usb = uscpi->usb; - int ret, transferred, message_size; - - ret = libusb_bulk_transfer(usb->devhdl, uscpi->bulk_in_ep, data, size, - &transferred, TRANSFER_TIMEOUT); - if (ret < 0) { - sr_err("USBTMC bulk in transfer error: %s.", - libusb_error_name(ret)); - return SR_ERR; - } - - if (usbtmc_bulk_in_header_read(data, msg_id, uscpi->bTag, &message_size, - transfer_attributes) != SR_OK) { - sr_err("USBTMC invalid bulk in header."); - return SR_ERR; - } - - message_size += USBTMC_BULK_HEADER_SIZE; - uscpi->response_length = MIN(transferred, message_size); - uscpi->response_bytes_read = USBTMC_BULK_HEADER_SIZE; - uscpi->remaining_length = message_size - uscpi->response_length; - - return transferred - USBTMC_BULK_HEADER_SIZE; -} - -static int scpi_usbtmc_bulkin_continue(struct scpi_usbtmc_libusb *uscpi, - void *data, int size) -{ - struct sr_usb_dev_inst *usb = uscpi->usb; - int ret, transferred; - - ret = libusb_bulk_transfer(usb->devhdl, uscpi->bulk_in_ep, data, size, - &transferred, TRANSFER_TIMEOUT); - if (ret < 0) { - sr_err("USBTMC bulk in transfer error: %s.", - libusb_error_name(ret)); - return SR_ERR; - } - - uscpi->response_length = MIN(transferred, uscpi->remaining_length); - uscpi->response_bytes_read = 0; - uscpi->remaining_length -= uscpi->response_length; - - return transferred; -} - -static int scpi_usbtmc_libusb_send(void *priv, const char *command) -{ - struct scpi_usbtmc_libusb *uscpi = priv; - - if (scpi_usbtmc_bulkout(uscpi, DEV_DEP_MSG_OUT, - command, strlen(command), EOM) <= 0) - return SR_ERR; - - sr_spew("Successfully sent SCPI command: '%s'.", command); - - return SR_OK; -} - -static int scpi_usbtmc_libusb_read_begin(void *priv) -{ - struct scpi_usbtmc_libusb *uscpi = priv; - - uscpi->remaining_length = 0; - - if (scpi_usbtmc_bulkout(uscpi, REQUEST_DEV_DEP_MSG_IN, - NULL, INT32_MAX, 0) < 0) - return SR_ERR; - if (scpi_usbtmc_bulkin_start(uscpi, DEV_DEP_MSG_IN, - uscpi->buffer, sizeof(uscpi->buffer), - &uscpi->bulkin_attributes) < 0) - return SR_ERR; - - return SR_OK; -} - -static int scpi_usbtmc_libusb_read_data(void *priv, char *buf, int maxlen) -{ - struct scpi_usbtmc_libusb *uscpi = priv; - int read_length; - - if (uscpi->response_bytes_read >= uscpi->response_length) { - if (uscpi->remaining_length > 0) { - if (scpi_usbtmc_bulkin_continue(uscpi, uscpi->buffer, - sizeof(uscpi->buffer)) <= 0) - return SR_ERR; - } else { - if (uscpi->bulkin_attributes & EOM) - return SR_ERR; - if (scpi_usbtmc_libusb_read_begin(uscpi) < 0) - return SR_ERR; - } - } - - read_length = MIN(uscpi->response_length - uscpi->response_bytes_read, maxlen); - - memcpy(buf, uscpi->buffer + uscpi->response_bytes_read, read_length); - - uscpi->response_bytes_read += read_length; - - return read_length; -} - -static int scpi_usbtmc_libusb_read_complete(void *priv) -{ - struct scpi_usbtmc_libusb *uscpi = priv; - return uscpi->response_bytes_read >= uscpi->response_length && - uscpi->remaining_length <= 0 && - uscpi->bulkin_attributes & EOM; -} - -static int scpi_usbtmc_libusb_close(void *priv) -{ - int ret; - struct scpi_usbtmc_libusb *uscpi = priv; - struct sr_usb_dev_inst *usb = uscpi->usb; - - if (!usb->devhdl) - return SR_ERR; - - if (!uscpi->rigol_ds1000) { - if ((ret = libusb_clear_halt(usb->devhdl, uscpi->bulk_in_ep)) < 0) - sr_err("Failed to clear halt/stall condition for EP %d: %s.", - uscpi->bulk_in_ep, libusb_error_name(ret)); - if ((ret = libusb_clear_halt(usb->devhdl, uscpi->bulk_out_ep)) < 0) - sr_err("Failed to clear halt/stall condition for EP %d: %s.", - uscpi->bulk_out_ep, libusb_error_name(ret)); - if ((ret = libusb_clear_halt(usb->devhdl, uscpi->interrupt_ep)) < 0) - sr_err("Failed to clear halt/stall condition for EP %d: %s.", - uscpi->interrupt_ep, libusb_error_name(ret)); - } - - if ((ret = libusb_release_interface(usb->devhdl, uscpi->interface)) < 0) - sr_err("Failed to release interface: %s.", - libusb_error_name(ret)); - - if (uscpi->detached_kernel_driver) { - if ((ret = libusb_attach_kernel_driver(usb->devhdl, - uscpi->interface)) < 0) - sr_err("Failed to re-attach kernel driver: %s.", - libusb_error_name(ret)); - - uscpi->detached_kernel_driver = 0; - } - libusb_close(usb->devhdl); - usb->devhdl = NULL; - - return SR_OK; -} - -static void scpi_usbtmc_libusb_free(void *priv) -{ - struct scpi_usbtmc_libusb *uscpi = priv; - sr_usb_dev_inst_free(uscpi->usb); -} - -SR_PRIV const struct sr_scpi_dev_inst scpi_usbtmc_libusb_dev = { - .name = "USBTMC", - .prefix = "usbtmc", - .priv_size = sizeof(struct scpi_usbtmc_libusb), - .scan = scpi_usbtmc_libusb_scan, - .dev_inst_new = scpi_usbtmc_libusb_dev_inst_new, - .open = scpi_usbtmc_libusb_open, - .source_add = scpi_usbtmc_libusb_source_add, - .source_remove = scpi_usbtmc_libusb_source_remove, - .send = scpi_usbtmc_libusb_send, - .read_begin = scpi_usbtmc_libusb_read_begin, - .read_data = scpi_usbtmc_libusb_read_data, - .read_complete = scpi_usbtmc_libusb_read_complete, - .close = scpi_usbtmc_libusb_close, - .free = scpi_usbtmc_libusb_free, -}; diff --git a/hardware/common/scpi_visa.c b/hardware/common/scpi_visa.c deleted file mode 100644 index cf34a555..00000000 --- a/hardware/common/scpi_visa.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2013 Martin Ling - * - * 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 . - */ - -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#include -#include - -#define LOG_PREFIX "scpi_visa" - -struct scpi_visa { - char *resource; - ViSession rmgr; - ViSession vi; -}; - -static int scpi_visa_dev_inst_new(void *priv, struct drv_context *drvc, - const char *resource, char **params, const char *serialcomm) -{ - struct scpi_visa *vscpi = priv; - - (void)drvc; - (void)resource; - (void)serialcomm; - - if (!params || !params[1]) { - sr_err("Invalid parameters."); - return SR_ERR_BUG; - } - - vscpi->resource = g_strdup(params[1]); - - return SR_OK; -} - -static int scpi_visa_open(void *priv) -{ - struct scpi_visa *vscpi = priv; - - if (viOpenDefaultRM(&vscpi->rmgr) != VI_SUCCESS) { - sr_err("Cannot open default resource manager."); - return SR_ERR; - } - - if (viOpen(vscpi->rmgr, vscpi->resource, VI_NO_LOCK, 0, &vscpi->vi) != VI_SUCCESS) { - sr_err("Cannot open resource."); - return SR_ERR; - } - - return SR_OK; -} - -static int scpi_visa_source_add(struct sr_session *session, void *priv, - int events, int timeout, sr_receive_data_callback cb, void *cb_data) -{ - (void) priv; - - /* Hook up a dummy handler to receive data from the device. */ - return sr_session_source_add(session, -1, events, timeout, cb, cb_data); -} - -static int scpi_visa_source_remove(struct sr_session *session, void *priv) -{ - (void) priv; - - return sr_session_source_remove(session, -1); -} - -static int scpi_visa_send(void *priv, const char *command) -{ - struct scpi_visa *vscpi = priv; - gchar *terminated_command; - ViUInt32 written = 0; - int len; - - terminated_command = g_strconcat(command, "\n", NULL); - len = strlen(terminated_command); - if (viWrite(vscpi->vi, (ViBuf) (terminated_command + written), len, - &written) != VI_SUCCESS) { - sr_err("Error while sending SCPI command: '%s'.", command); - g_free(terminated_command); - return SR_ERR; - } - - g_free(terminated_command); - - sr_spew("Successfully sent SCPI command: '%s'.", command); - - return SR_OK; -} - -static int scpi_visa_read_begin(void *priv) -{ - (void) priv; - - return SR_OK; -} - -static int scpi_visa_read_data(void *priv, char *buf, int maxlen) -{ - struct scpi_visa *vscpi = priv; - ViUInt32 count; - - if (viRead(vscpi->vi, (ViBuf) buf, maxlen, &count) != VI_SUCCESS) { - sr_err("Read failed."); - return SR_ERR; - } - - return count; -} - -static int scpi_visa_read_complete(void *priv) -{ - struct scpi_visa *vscpi = priv; - ViUInt16 status; - - if (viReadSTB(vscpi->vi, &status) != VI_SUCCESS) { - sr_err("Failed to read status."); - return SR_ERR; - } - - return !(status & 16); -} - -static int scpi_visa_close(void *priv) -{ - struct scpi_visa *vscpi = priv; - - viClose(vscpi->vi); - viClose(vscpi->rmgr); - - return SR_OK; -} - -static void scpi_visa_free(void *priv) -{ - struct scpi_visa *vscpi = priv; - - g_free(vscpi->resource); - g_free(vscpi); -} - -SR_PRIV const struct sr_scpi_dev_inst scpi_visa_dev = { - .name = "VISA", - .prefix = "visa", - .priv_size = sizeof(struct scpi_visa), - .dev_inst_new = scpi_visa_dev_inst_new, - .open = scpi_visa_open, - .source_add = scpi_visa_source_add, - .source_remove = scpi_visa_source_remove, - .send = scpi_visa_send, - .read_begin = scpi_visa_read_begin, - .read_data = scpi_visa_read_data, - .read_complete = scpi_visa_read_complete, - .close = scpi_visa_close, - .free = scpi_visa_free, -}; diff --git a/hardware/common/scpi_vxi.c b/hardware/common/scpi_vxi.c deleted file mode 100644 index 271917b0..00000000 --- a/hardware/common/scpi_vxi.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2014 Aurelien Jacobs - * - * Inspired by the VXI11 Ethernet Protocol for Linux: - * http://optics.eee.nottingham.ac.uk/vxi11/ - * - * 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 . - */ - -#include -#include - -#include "vxi.h" -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#define LOG_PREFIX "scpi_vxi" -#define VXI_DEFAULT_TIMEOUT 2000 /* in ms */ - -struct scpi_vxi { - char *address; - char *instrument; - CLIENT *client; - Device_Link link; - unsigned int max_send_size; - unsigned int read_complete; -}; - -static int scpi_vxi_dev_inst_new(void *priv, struct drv_context *drvc, - const char *resource, char **params, const char *serialcomm) -{ - struct scpi_vxi *vxi = priv; - - (void)drvc; - (void)resource; - (void)serialcomm; - - if (!params || !params[1]) { - sr_err("Invalid parameters."); - return SR_ERR; - } - - vxi->address = g_strdup(params[1]); - vxi->instrument = g_strdup(params[2] ? params[2] : "inst0"); - - return SR_OK; -} - -static int scpi_vxi_open(void *priv) -{ - struct scpi_vxi *vxi = priv; - Create_LinkParms link_parms; - Create_LinkResp *link_resp; - - vxi->client = clnt_create(vxi->address, DEVICE_CORE, DEVICE_CORE_VERSION, "tcp"); - if (vxi->client == NULL) { - sr_err("Client creation failed for %s", vxi->address); - return SR_ERR; - } - - /* Set link parameters */ - link_parms.clientId = (long) vxi->client; - link_parms.lockDevice = 0; - link_parms.lock_timeout = VXI_DEFAULT_TIMEOUT; - link_parms.device = "inst0"; - - if (!(link_resp = create_link_1(&link_parms, vxi->client))) { - sr_err("Link creation failed for %s", vxi->address); - return SR_ERR; - } - vxi->link = link_resp->lid; - vxi->max_send_size = link_resp->maxRecvSize; - - /* Set a default maxRecvSize for devices which do not specify it */ - if (vxi->max_send_size <= 0) - vxi->max_send_size = 4096; - - return SR_OK; -} - -static int scpi_vxi_source_add(struct sr_session *session, void *priv, - int events, int timeout, sr_receive_data_callback cb, void *cb_data) -{ - (void)priv; - - /* Hook up a dummy handler to receive data from the device. */ - return sr_session_source_add(session, -1, events, timeout, cb, cb_data); -} - -static int scpi_vxi_source_remove(struct sr_session *session, void *priv) -{ - (void)priv; - - return sr_session_source_remove(session, -1); -} - -/* Operation Flags */ -#define DF_WAITLOCK 0x01 /* wait if the operation is locked by another link */ -#define DF_END 0x08 /* an END indicator is sent with last byte of buffer */ -#define DF_TERM 0x80 /* a termination char is set during a read */ - -static int scpi_vxi_send(void *priv, const char *command) -{ - struct scpi_vxi *vxi = priv; - Device_WriteResp *write_resp; - Device_WriteParms write_parms; - char *terminated_command; - unsigned int len; - - terminated_command = g_strdup_printf("%s\r\n", command); - len = strlen(terminated_command); - - write_parms.lid = vxi->link; - write_parms.io_timeout = VXI_DEFAULT_TIMEOUT; - write_parms.lock_timeout = VXI_DEFAULT_TIMEOUT; - write_parms.flags = DF_END; - write_parms.data.data_len = MIN(len, vxi->max_send_size); - write_parms.data.data_val = terminated_command; - - if (!(write_resp = device_write_1(&write_parms, vxi->client)) - || write_resp->error) { - sr_err("Device write failed for %s with error %d", - vxi->address, write_resp->error); - return SR_ERR; - } - - g_free(terminated_command); - - if (write_resp->size < len) - sr_dbg("Only sent %d/%d bytes of SCPI command: '%s'.", - write_resp->size, len, command); - else - sr_spew("Successfully sent SCPI command: '%s'.", command); - - return SR_OK; -} - -static int scpi_vxi_read_begin(void *priv) -{ - struct scpi_vxi *vxi = priv; - - vxi->read_complete = 0; - - return SR_OK; -} - -/* Read Response Reason Flags */ -#define RRR_SIZE 0x01 /* requestSize bytes have been transferred */ -#define RRR_TERM 0x02 /* a termination char has been read */ -#define RRR_END 0x04 /* an END indicator has been read */ - -static int scpi_vxi_read_data(void *priv, char *buf, int maxlen) -{ - struct scpi_vxi *vxi = priv; - Device_ReadParms read_parms; - Device_ReadResp *read_resp; - - read_parms.lid = vxi->link; - read_parms.io_timeout = VXI_DEFAULT_TIMEOUT; - read_parms.lock_timeout = VXI_DEFAULT_TIMEOUT; - read_parms.flags = 0; - read_parms.termChar = 0; - read_parms.requestSize = maxlen; - - if (!(read_resp = device_read_1(&read_parms, vxi->client)) - || read_resp->error) { - sr_err("Device read failed for %s with error %d", - vxi->address, read_resp->error); - return SR_ERR; - } - - memcpy(buf, read_resp->data.data_val, read_resp->data.data_len); - vxi->read_complete = read_resp->reason & (RRR_SIZE | RRR_TERM | RRR_END); - return read_resp->data.data_len; /* actual number of bytes received */ -} - -static int scpi_vxi_read_complete(void *priv) -{ - struct scpi_vxi *vxi = priv; - - return vxi->read_complete; -} - -static int scpi_vxi_close(void *priv) -{ - struct scpi_vxi *vxi = priv; - Device_Error *dev_error; - - if (!vxi->client) - return SR_ERR; - - if (!(dev_error = destroy_link_1(&vxi->link, vxi->client))) { - sr_err("Link destruction failed for %s", vxi->address); - return SR_ERR; - } - - clnt_destroy(vxi->client); - vxi->client = NULL; - - return SR_OK; -} - -static void scpi_vxi_free(void *priv) -{ - struct scpi_vxi *vxi = priv; - - g_free(vxi->address); - g_free(vxi->instrument); -} - -SR_PRIV const struct sr_scpi_dev_inst scpi_vxi_dev = { - .name = "VXI", - .prefix = "vxi", - .priv_size = sizeof(struct scpi_vxi), - .dev_inst_new = scpi_vxi_dev_inst_new, - .open = scpi_vxi_open, - .source_add = scpi_vxi_source_add, - .source_remove = scpi_vxi_source_remove, - .send = scpi_vxi_send, - .read_begin = scpi_vxi_read_begin, - .read_data = scpi_vxi_read_data, - .read_complete = scpi_vxi_read_complete, - .close = scpi_vxi_close, - .free = scpi_vxi_free, -}; diff --git a/hardware/common/serial.c b/hardware/common/serial.c deleted file mode 100644 index 9a9a0d94..00000000 --- a/hardware/common/serial.c +++ /dev/null @@ -1,911 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2010-2012 Bert Vermeulen - * Copyright (C) 2010-2012 Uwe Hermann - * Copyright (C) 2012 Alexandru Gagniuc - * - * 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 . - */ - -#include -#include -#include -#include -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#define LOG_PREFIX "serial" - -/** - * Open the specified serial port. - * - * @param serial Previously initialized serial port structure. - * @param[in] flags Flags to use when opening the serial port. Possible flags - * include SERIAL_RDWR, SERIAL_RDONLY, SERIAL_NONBLOCK. - * - * If the serial structure contains a serialcomm string, it will be - * passed to serial_set_paramstr() after the port is opened. - * - * @retval SR_OK Success. - * @retval SR_ERR Failure. - */ -SR_PRIV int serial_open(struct sr_serial_dev_inst *serial, int flags) -{ - int ret; - char *error; - int sp_flags = 0; - - if (!serial) { - sr_dbg("Invalid serial port."); - return SR_ERR; - } - - sr_spew("Opening serial port '%s' (flags %d).", serial->port, flags); - - sp_get_port_by_name(serial->port, &serial->data); - - if (flags & SERIAL_RDWR) - sp_flags = (SP_MODE_READ | SP_MODE_WRITE); - else if (flags & SERIAL_RDONLY) - sp_flags = SP_MODE_READ; - - serial->nonblocking = (flags & SERIAL_NONBLOCK) ? 1 : 0; - - ret = sp_open(serial->data, sp_flags); - - switch (ret) { - case SP_ERR_ARG: - sr_err("Attempt to open serial port with invalid parameters."); - return SR_ERR_ARG; - case SP_ERR_FAIL: - error = sp_last_error_message(); - sr_err("Error opening port (%d): %s.", - sp_last_error_code(), error); - sp_free_error_message(error); - return SR_ERR; - } - - if (serial->serialcomm) - return serial_set_paramstr(serial, serial->serialcomm); - else - return SR_OK; -} - -/** - * Close the specified serial port. - * - * @param serial Previously initialized serial port structure. - * - * @retval SR_OK Success. - * @retval SR_ERR Failure. - */ -SR_PRIV int serial_close(struct sr_serial_dev_inst *serial) -{ - int ret; - char *error; - - if (!serial) { - sr_dbg("Invalid serial port."); - return SR_ERR; - } - - if (!serial->data) { - sr_dbg("Cannot close unopened serial port %s.", serial->port); - return SR_ERR; - } - - sr_spew("Closing serial port %s.", serial->port); - - ret = sp_close(serial->data); - - switch (ret) { - case SP_ERR_ARG: - sr_err("Attempt to close an invalid serial port."); - return SR_ERR_ARG; - case SP_ERR_FAIL: - error = sp_last_error_message(); - sr_err("Error closing port (%d): %s.", - sp_last_error_code(), error); - sp_free_error_message(error); - return SR_ERR; - } - - sp_free_port(serial->data); - serial->data = NULL; - - return SR_OK; -} - -/** - * Flush serial port buffers. - * - * @param serial Previously initialized serial port structure. - * - * @retval SR_OK Success. - * @retval SR_ERR Failure. - */ -SR_PRIV int serial_flush(struct sr_serial_dev_inst *serial) -{ - int ret; - char *error; - - if (!serial) { - sr_dbg("Invalid serial port."); - return SR_ERR; - } - - if (!serial->data) { - sr_dbg("Cannot flush unopened serial port %s.", serial->port); - return SR_ERR; - } - - sr_spew("Flushing serial port %s.", serial->port); - - ret = sp_flush(serial->data, SP_BUF_BOTH); - - switch (ret) { - case SP_ERR_ARG: - sr_err("Attempt to flush an invalid serial port."); - return SR_ERR_ARG; - case SP_ERR_FAIL: - error = sp_last_error_message(); - sr_err("Error flushing port (%d): %s.", - sp_last_error_code(), error); - sp_free_error_message(error); - return SR_ERR; - } - - return SR_OK; -} - -static int _serial_write(struct sr_serial_dev_inst *serial, - const void *buf, size_t count, int nonblocking) -{ - ssize_t ret; - char *error; - - if (!serial) { - sr_dbg("Invalid serial port."); - return SR_ERR; - } - - if (!serial->data) { - sr_dbg("Cannot use unopened serial port %s.", serial->port); - return SR_ERR; - } - - if (nonblocking) - ret = sp_nonblocking_write(serial->data, buf, count); - else - ret = sp_blocking_write(serial->data, buf, count, 0); - - switch (ret) { - case SP_ERR_ARG: - sr_err("Attempted serial port write with invalid arguments."); - return SR_ERR_ARG; - case SP_ERR_FAIL: - error = sp_last_error_message(); - sr_err("Write error (%d): %s.", sp_last_error_code(), error); - sp_free_error_message(error); - return SR_ERR; - } - - sr_spew("Wrote %d/%d bytes.", ret, count); - - return ret; -} - -/** - * Write a number of bytes to the specified serial port. - * - * @param serial Previously initialized serial port structure. - * @param[in] buf Buffer containing the bytes to write. - * @param[in] count Number of bytes to write. - * - * @retval SR_ERR_ARG Invalid argument. - * @retval SR_ERR Other error. - * @retval other The number of bytes written. - */ -SR_PRIV int serial_write(struct sr_serial_dev_inst *serial, - const void *buf, size_t count) -{ - return _serial_write(serial, buf, count, serial->nonblocking); -} - -/** - * Write a number of bytes to the specified serial port, blocking until finished. - * @copydetails serial_write() - */ -SR_PRIV int serial_write_blocking(struct sr_serial_dev_inst *serial, - const void *buf, size_t count) -{ - return _serial_write(serial, buf, count, 0); -} - -/** - * Write a number of bytes to the specified serial port, return immediately. - * @copydetails serial_write() -*/ -SR_PRIV int serial_write_nonblocking(struct sr_serial_dev_inst *serial, - const void *buf, size_t count) -{ - return _serial_write(serial, buf, count, 1); -} - -static int _serial_read(struct sr_serial_dev_inst *serial, void *buf, - size_t count, int nonblocking) -{ - ssize_t ret; - char *error; - - if (!serial) { - sr_dbg("Invalid serial port."); - return SR_ERR; - } - - if (!serial->data) { - sr_dbg("Cannot use unopened serial port %s.", serial->port); - return SR_ERR; - } - - if (nonblocking) - ret = sp_nonblocking_read(serial->data, buf, count); - else - ret = sp_blocking_read(serial->data, buf, count, 0); - - switch (ret) { - case SP_ERR_ARG: - sr_err("Attempted serial port read with invalid arguments."); - return SR_ERR_ARG; - case SP_ERR_FAIL: - error = sp_last_error_message(); - sr_err("Read error (%d): %s.", sp_last_error_code(), error); - sp_free_error_message(error); - return SR_ERR; - } - - if (ret > 0) - sr_spew("Read %d/%d bytes.", ret, count); - - return ret; -} - -/** - * Read a number of bytes from the specified serial port. - * - * @param serial Previously initialized serial port structure. - * @param buf Buffer where to store the bytes that are read. - * @param[in] count The number of bytes to read. - * - * @retval SR_ERR_ARG Invalid argument. - * @retval SR_ERR Other error. - * @retval other The number of bytes read. - */ -SR_PRIV int serial_read(struct sr_serial_dev_inst *serial, void *buf, - size_t count) -{ - return _serial_read(serial, buf, count, serial->nonblocking); -} - -/** - * Read a number of bytes from the specified serial port, block until finished. - * @copydetails serial_read() - */ -SR_PRIV int serial_read_blocking(struct sr_serial_dev_inst *serial, void *buf, - size_t count) -{ - return _serial_read(serial, buf, count, 0); -} - -/** - * Try to read up to @a count bytes from the specified serial port, return - * immediately with what's available. - * @copydetails serial_read() - */ -SR_PRIV int serial_read_nonblocking(struct sr_serial_dev_inst *serial, void *buf, - size_t count) -{ - return _serial_read(serial, buf, count, 1); -} - -/** - * Set serial parameters for the specified serial port. - * - * @param serial Previously initialized serial port structure. - * @param[in] baudrate The baudrate to set. - * @param[in] bits The number of data bits to use (5, 6, 7 or 8). - * @param[in] parity The parity setting to use (0 = none, 1 = even, 2 = odd). - * @param[in] stopbits The number of stop bits to use (1 or 2). - * @param[in] flowcontrol The flow control settings to use (0 = none, - * 1 = RTS/CTS, 2 = XON/XOFF). - * @param[in] rts Status of RTS line (0 or 1; required by some interfaces). - * @param[in] dtr Status of DTR line (0 or 1; required by some interfaces). - * - * @retval SR_OK Success. - * @retval SR_ERR Failure. - */ -SR_PRIV int serial_set_params(struct sr_serial_dev_inst *serial, int baudrate, - int bits, int parity, int stopbits, - int flowcontrol, int rts, int dtr) -{ - int ret; - char *error; - struct sp_port_config *config; - - if (!serial) { - sr_dbg("Invalid serial port."); - return SR_ERR; - } - - if (!serial->data) { - sr_dbg("Cannot configure unopened serial port %s.", serial->port); - return SR_ERR; - } - - sr_spew("Setting serial parameters on port %s.", serial->port); - - sp_new_config(&config); - sp_set_config_baudrate(config, baudrate); - sp_set_config_bits(config, bits); - switch (parity) { - case 0: - sp_set_config_parity(config, SP_PARITY_NONE); - break; - case 1: - sp_set_config_parity(config, SP_PARITY_EVEN); - break; - case 2: - sp_set_config_parity(config, SP_PARITY_ODD); - break; - default: - return SR_ERR_ARG; - } - sp_set_config_stopbits(config, stopbits); - sp_set_config_rts(config, flowcontrol == 1 ? SP_RTS_FLOW_CONTROL : rts); - sp_set_config_cts(config, flowcontrol == 1 ? SP_CTS_FLOW_CONTROL : SP_CTS_IGNORE); - sp_set_config_dtr(config, dtr); - sp_set_config_dsr(config, SP_DSR_IGNORE); - sp_set_config_xon_xoff(config, flowcontrol == 2 ? SP_XONXOFF_INOUT : SP_XONXOFF_DISABLED); - - ret = sp_set_config(serial->data, config); - sp_free_config(config); - - switch (ret) { - case SP_ERR_ARG: - sr_err("Invalid arguments for setting serial port parameters."); - return SR_ERR_ARG; - case SP_ERR_FAIL: - error = sp_last_error_message(); - sr_err("Error setting serial port parameters (%d): %s.", - sp_last_error_code(), error); - sp_free_error_message(error); - return SR_ERR; - } - - return SR_OK; -} - -/** - * Set serial parameters for the specified serial port from parameter string. - * - * @param serial Previously initialized serial port structure. - * @param[in] paramstr A serial communication parameters string of the form - * "/{/