pax_global_header00006660000000000000000000000064132152500200014500gustar00rootroot0000000000000052 comment=971f99d0b0451ed0c4ac6af0a3a8f5098fd8b399 lxi-tools-1.15/000077500000000000000000000000001321525002000133605ustar00rootroot00000000000000lxi-tools-1.15/.gitignore000066400000000000000000000005471321525002000153560ustar00rootroot00000000000000*.tar.xz Makefile.in Makefile aclocal.m4 autom4te.cache/ configure compile depcomp install-sh missing src/Makefile.in src/Makefile config.log config.status .deps/ .libs/ src/include/config.h src/include/config.h.in src/include/config.h.in~ src/include/stamp-h1 *.swp *.asc /ar-lib .dirstamp *.a *.o *.la *.lo /ltmain.sh /config.guess /config.sub /libtool /m4 lxi-tools-1.15/.travis.yml000066400000000000000000000004751321525002000154770ustar00rootroot00000000000000sudo: true language: c before_script: ./autogen.sh script: ./configure --prefix=/usr && make && sudo make install install: - wget https://github.com/lxi/liblxi/archive/master.tar.gz - tar -xvf master.tar.gz - pushd liblxi-master && ./autogen.sh && ./configure --prefix=/usr && make && sudo make install && popd lxi-tools-1.15/AUTHORS000066400000000000000000000005211321525002000144260ustar00rootroot00000000000000Maintainer: Martin Lund Contributors: Robert Scheck Jakub Wilk RoGeorge from EEVBlog forum dpenev from EEVBlog forum PeDre from EEVBlog forum BloodyCactus from EEVBlog forum crispus from EEVBlog forum Thanks to everyone who has contributed to this project. lxi-tools-1.15/COPYING000066400000000000000000000033271321525002000144200ustar00rootroot00000000000000lxi-tools is available for use under the following license, commonly known as the 3-clause (or "modified") BSD license: ----------------------------------------------------------------------- Copyright (c) 2016-2017 Martin Lund All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------- lxi-tools-1.15/ChangeLog000066400000000000000000000234061321525002000151370ustar00rootroot00000000000000=== lxi-tools v1.15 === Changes since lxi-tools v1.14: * Update man page * Add support for using raw/TCP in benchmark mode Add the option to run benchmark using raw/TCP. For example: $ lxi benchmark --address 10.0.0.42 --port 5555 --raw Also, cleanup all port handling code and update documentation accordingly. * Decrease timeout for discover to 2 s Changes since lxi-tools v1.13: * Make screenshot plugin only support Rigol DM3068 Rigol DM3068 is the only DM3000 series digital multimeter that seems to have screenshot support. * Fix entering interactive mode Regardless of using --interactive a SCPI command was still required to be provided to enter interactive mode. * Update AUTHORS * Remove experimental label from Siglent plugins Thanks to Siglent who helped fix and test all the screenshot plugins for their instruments. * Cleanup screenshot plugins * Consolidate Rigol DSA plugins into one * Update README and man page * Support writing screenshot image to stdout To write screenshot image to stdout simply use '-' as the output filename. This allows to pipe the screenshot image directly to other tools for image processing. For example, using imagemagick to automatically convert captured screenshot image to JPG: $ lxi screenshot -a 10.0.0.42 - | convert - screenshot.jpg * Cleanup Siglent screenshot plugins * Update siglent-ssa3000x plugin * Add siglent-sdg plugin * Add siglent-sdm3000 plugin * Move siglent-sds out of experimental * Extend Siglent plugin to include SDS2000X Changes since lxi-tools v1.12: * Update README * Update SSA3000X capture command * Add completion for benchmark command * Update AUTHORS * Fix get_device_id() This function was missing a call to lxi_disconnect() which resulted in some instruments being left hanging when capturing screenshots. Instruments that presumable only allow one active connection. * Add benchmark feature This benchmark feature is useful if you want to compare the VXI-11 request/response performance of your instruments. By default the benchmark sends 100 SCPI ID requests ("*IDN?" commands) to the instrument. For each request it waits for and reads the response. When done the resulting request rate is printed. * Fix screenshot command when using plugin autodetection The wrong timeout value was passed when trying to autodetect which screenshot plugin to use. * Cleanup * Fix Rohde & Schwarz HMO 1000 screenshot plugin Fix plugin so that it does not strip off the PNG header of the PNG image stream. Also, the source files and functions of the plugin is now named more explicitly according to the name of the instrument series (HMO 1000). * Fix Siglent SSA3000 screenshot plugin Changes since lxi-tools v1.11: * Update to new URL * Add snap status * Fix redirection of output to file * Update README * Cleanup configure.ac Jakub Wilk: * Use HTTPS in the configure script Changes since lxi-tools v1.10: * Update README * Update man page * Update AUTHORS * Expand tested instruments list * Rename screenshot plugin rigol-1000 -> rigol-1000z * Add various Rigol screenshot plugins Add the following Rigol screenshot plugins: rigol-dg4000 Rigol DG4000 series function generator rigol-dm3000 Rigol DM3000 series digital multimeter rigol-dp800 Rigol DP800 series power supply rigol-dsa800 Rigol DSA800 series spectrum analyzer rigol-dsa700 Rigol DSA700 series spectrum analyzer The code is added on behalf of PeDre from the EEVBlog forum. * Add authors section in README * Add README.md to prettify GitHub page The original README is still preserved because it is more readable when not reading it via GitHub. Jakub Wilk: * Strip trailing spaces * Fix typo * Fix grammar and typos Changes since lxi-tools v1.9: * Add support for mDNS/DNS-SD discovery Add "--mdns" option which enables the discover command to search for LXI devices/services using mDNS/DNS-SD. * Fix Siglent screenshot plugins Write correct response buffer to file. Improve .regex match expression. Changes since lxi-tools v1.8: * Update README * Fix newlines when redirecting to file or terminal * Rename --dump-hex to --hex * Fix missing error message when no SCPI command defined * Update man page * Remove --dump-file option The correct way to dump response to file is to use pipe output redirection. For example: lxi scpi --address 192.168.1.210 "*IDN?" > response.txt This way it is possible to dump any binary response to file. * Fix missing error message when no IP address defined * Print errors to stderr * Cleanup Siglent SDS1000 plugin name * Add Siglent SSA 3000X screenshot plugin * Cleanup script examples * Correct default SCPI raw/TCP port By default use port 5025 as described here: http://www.lxistandard.org/About/LXI-Protocols.aspx If a different port is needed use the '--raw-port' option. Apparently Rigol is not using the recommended port for raw SCPI commands. * Update descriptions of the plugin options Changes since lxi-tools v1.7: * Update README * Add Siglent SDS 1000 screenshot plugin Changes since lxi-tools v1.6: * Update README * Cleanup * Update .regex for Tektronix plugin * Update .regex for R&S plugin * Update .regex for Keysight plugin * Update man page * Embed instrument IP address in screenshot filename This helps identify screenshot files when capturing screenshots from multiple instruments. It also allows simplifying the APIs used by the screenshot plugins. * Change option '--model' to '--plugin' Lets remove any model vs. plugin confusion and only deal with plugin names. Each plugin includes support for one or more instruments models as described in the plugin description. * Add automatic loading of screenshot plugin feature If no screenshot plugin is specified the tool will automatically try to select the best plugin by matching the instruments ID string against the regular expressions defined in each plugin. Each screenshot plugin defines a .regex string entry containing space separated regular expressions. Each regular expression is matched against the instrument ID string. The plugin with most matches is selected. Note: This mechanism is slightly slower than manually specifying which screenshot plugin because it needs to retrieve the instruments ID string first. * Improve description of Rigol plugins * Fix Rigol 2000 screenshot plugin Remove trailing newline in received image data. * Add screenshot plugin for Rigol 2000 series Also, make existing Rigol plugin only apply for 1000z series. Changes since lxi-tools v1.5: * Add date-time stamp to screenshot filename * Improve command handling In case of a misspelled command the tool would misleadingly respond: "Error: No IP address specified" With this fix, it now responds: "Error: Unknown command" * Update README * Added screenshot plugin for Tektronix 2000 series scopes * Improve scpi response output * Add --raw and --raw-port options to scpi command One can now use choose to use raw/TCP instead of VXI11 when firing SCPI commands. Simply append the --raw option like so: lxi scpi --raw --address 192.168.0.42 "*IDN?" By default raw/TCP port 5555 is used but it can be changed using the --raw-port option. Warning: Using raw/TCP is faster than VXI11 but does not provide any timeout/control mechanisms so if your command somehow stalls it will stall forever. * Use new lxi_connect() function * Cleanup * Make screenshot filename optional In case no screenshot filename is provided the tool will write the screenshot image to an automatically resolved and incremented filename on the form screenshot-###.. For example, screenshot-000.png, screenshot-001.png, etc. * Improve screenshot model listing * Increase default timeout for screenshot command Transferring screenshot image data takes time so lets increase the timeout so we do not easily interrupt a good but slow transfer. * Collapse Rigol screenshot plugin Support all Rigol oscilloscope models via one model name. * Add screenshot support for Keysight IV 2000 X * Cleanup plugins * Add screenshot support for R&S HMO1000 series * Add screenshot support for Rigol 2000/4000 * Create directory for screenshot plugins Changes since lxi-tools v1.4: * Remove -Og flag Not supported by older gcc versions. * Fix various bugs in script and interactive mode Changes since lxi-tools v1.3: * Add screenshot feature to lxi tool The old rigol_1000z_screenshot tool is retired in favor of a screenshot feature in the lxi tool. A new lxi command 'screenshot' is added and also a small screenshot plugin framework which makes it easy to add new screenshot plugins for new instruments. Currently there is only a screenshot plugin for Rigol 1000Z series oscilloscopes. * Update README Changes since lxi-tools v1.2: * Added AUTHORS file * Use new lxi_connect() function * Reconfigure default timeout to 3 seconds Changes since lxi-tools v1.1: * Increase default timeout value for lxi tool Increase the default timeout value for the lxi tool from 1 to 5 seconds * Fix timeout for Rigol screenshot tool Timeout is increased to avoid failure to capture screenshot * Fix typo * Cleanup test script * Fix crash in rigol_1000z_screenshot tool Add error handling to avoid crashing when connecting remote device fails. Changes since lxi-tools v1.0: * Fix missing src/bash-completion/lxi An automake rule was fixed to make sure that the file src/bash-completion/lxi is included in the distributed tarball. * Update README lxi-tools v1.0: * First release (stable) lxi-tools-1.15/Makefile.am000066400000000000000000000000221321525002000154060ustar00rootroot00000000000000SUBDIRS = src man lxi-tools-1.15/README000066400000000000000000000202111321525002000142340ustar00rootroot00000000000000 === lxi-tools === 1. Introduction lxi-tools is a collection of open source software tools that enables control of LXI compatible instruments such as modern oscilloscopes, power supplies, spectrum analyzers etc. All features are consolidated in the 'lxi' application which provides a simple commandline interface to discover LXI instruments, send SCPI commands, and capture screenshots from supported LXI instruments. lxi-tools rely on liblxi for all communication. 2. Usage The commandline interface of the lxi application is described in the output from 'lxi --help': Usage: lxi [--version] [--help] [] -v, --version Display version -h, --help Display help Commands: discover [] Search for LXI devices scpi [] Send SCPI command screenshot [] [] Capture screenshot benchmark [] Benchmark Discover options: -t, --timeout Timeout (default: 3) -m, --mdns Search via mDNS/DNS-SD Scpi options: -a, --address Device IP address -p, --port Use port (default: VXI11: 111, RAW: 5025) -t, --timeout Timeout (default: 3) -x, --hex Print response in hexadecimal -i, --interactive Enter interactive mode -s, --script Run script file -r, --raw Use raw/TCP Screenshot options: -a, --address Device IP address -t, --timeout Timeout (default: 15) -p, --plugin Use screenshot plugin by name -l, --list List available screenshot plugins Benchmark options: -a, --address Device IP address -p, --port Use port (default: VXI11: 111, RAW: 5025) -t, --timeout Timeout (default: 3) -c, --count Number of request messages (default: 100) -r, --raw Use raw/TCP 2.1 Example - Discover LXI devices on available networks $ lxi discover Searching for LXI devices - please wait... Broadcasting on interface lo Broadcasting on interface eth0 Found "RIGOL TECHNOLOGIES,DS1104Z,DS1ZA1234567890,00.04.03.SP2" on address 10.42.1.20 Found "RIGOL TECHNOLOGIES,DP831,DP8F1234567890,00.01.14" on address 10.42.1.67 Broadcasting on interface wlan0 Found 2 devices 2.2 Example - Send SCPI command to an instrument $ lxi scpi --address 10.42.1.20 "*IDN?" RIGOL TECHNOLOGIES,DS1104Z,DS1ZA1234567890,00.04.03 To dump response to file simply do: $ lxi scpi --address 10.42.1.20 "*IDN?" > response.txt 2.3 Example - Capture screenshot from a Rigol 1000z series oscilloscope: $ lxi screenshot --address 10.42.1.20 --plugin rigol-1000z Saved screenshot image to screenshot_10.42.1.20_2017-11-11_13:45:47.png Or using plugin autodetection simply: $ lxi screenshot --address 10.42.1.20 Loaded rigol-1000 screenshot plugin Saved screenshot image to screenshot_10.42.1.20_2017-11-11_13:46:02.png 2.4 Example - Capture screenshot and convert it to any image format By default the format of the captured screenshot image is dictated by which screenshot plugin and instrument are in play. However, it is possible to write the screenshot image to stdout and pipe it directly to other tools for image processing. For example, use ImageMagicks convert tool to automatically convert screenshot image to JPG: $ lxi screenshot --address 10.42.1.20 - | convert - screenshot.jpg 2.5 Example - List available screenshot plugins $ lxi screenshot --list Name Description keysight-iv2000x Keysight InfiniVision 2000X series oscilloscope (experimental) rigol-1000z Rigol DS/MSO 1000z series oscilloscope rigol-2000 Rigol DS/MSO 2000 series oscilloscope rigol-dg4000 Rigol DG 4000 series function generator rigol-dm3000 Rigol DM 3000 series digital multimeter rigol-dp800 Rigol DP 800 series power supply rigol-dsa Rigol DSA 700/800 series spectrum analyzer rs-hmo1000 Rohde & Schwarz HMO 1000 series oscilloscope (experimental) siglent-sdm3000 Siglent SDM 3000/3000X series digital multimeter siglent-sdg Siglent SDG 1000X/2000X/6000X series waveform generator siglent-sds Siglent SDS 1000X/2000X series oscilloscope siglent-ssa3000x Siglent SSA 3000X series spectrum analyzer tektronix-2000 Tektronix DPO/MSO 2000 series oscilloscope (experimental) 2.6 Example - Benchmark instrument request/response performance $ lxi benchmark --address 10.42.1.20 Benchmarking by sending 100 ID requests. Please wait... Result: 24.7 requests/second 3. Installation The latest release version can be downloaded from https://lxi-tools.github.io 3.1 Installation from release tarball Install steps: $ ./configure $ make $ make install Note: lxi-tools depends on liblxi so you need to go install liblxi first. 3.2 Installation using package lxi-tools comes prepackaged for various GNU/Linux distributions. Visit https://lxi-tools.github.io to see list of supported distributions. 4. Tested instruments The commandline lxi tool is tested to work successfully with the following LXI compatible instruments: Instrument Working features Rigol Technologies DG4062 (discover+scpi+screenshot) Rigol Technologies DG4102 (discover+scpi+screenshot) Rigol Technologies DG4162 (discover+scpi+screenshot) Rigol Technologies DP831 (discover+scpi+screenshot) Rigol Technologies DP832 (discover+scpi+screenshot) Rigol Technologies DM3068 (discover+scpi+screenshot) Rigol Technologies DS1104Z (discover+scpi+screenshot) Rigol Technologies DS2302 (discover+scpi+screenshot) Rigol Technologies DSA815 (discover+scpi+screenshot) Rigol Technologies MSO1104Z (discover+scpi+screenshot) Rigol Technologies MSO2302A (discover+scpi+screenshot) Rohde & Schwarz HMO 1202 (discover+scpi+screenshot) Siglent Technologies SDG1032X (discover+scpi+screenshot) Siglent Technologies SDG2122X (discover+scpi+screenshot) Siglent Technologies SDG6052 (discover+scpi+screenshot) Siglent Technologies SDS1202X-E (discover+scpi+screenshot) Siglent Technologies SDS1204X-E (discover+scpi+screenshot) Siglent Technologies SDS2304X (discover+scpi+screenshot) Siglent Technologies SDM3045X (discover+scpi+screenshot) Siglent Technologies SDM3055 (discover+scpi+screenshot) Siglent Technologies SDM3065X (discover+scpi+screenshot) Siglent Technologies SPD3303X-E (scpi) Siglent Technologies SSA3032X (discover+scpi+screenshot) Note: Feel free to add your instrument(s) to the list via GitHub pull request or simply create a GitHub issue reporting your instrument(s) and which features work. 5. Contributing lxi-tools is open source. If you want to help out with the project please join in. All contributions (bug reports, code, doc, ideas, etc.) are welcome. Please use the github issue tracker and pull request features. Also, if you find this free open source software useful please consider making a donation: https://www.paypal.me/lundmar 6. Website Visit https://lxi-tools.github.io 7. License This code is released under BSD-3, commonly known as the 3-clause (or "modified") BSD license. 8. Authors Created by Martin Lund See the AUTHORS file for full list of authors. lxi-tools-1.15/README.md000066400000000000000000000206521321525002000146440ustar00rootroot00000000000000# lxi-tools [![Build Status](https://travis-ci.org/lxi-tools/lxi-tools.svg?branch=master)](https://travis-ci.org/lxi-tools/lxi-tools) [![Snap Status](https://build.snapcraft.io/badge/lxi-tools/lxi-tools.snapcraft.svg)](https://build.snapcraft.io/user/lxi-tools/lxi-tools.snapcraft) ## 1. Introduction lxi-tools is a collection of open source software tools that enables control of LXI compatible instruments such as modern oscilloscopes, power supplies, spectrum analyzers etc. All features are consolidated in the 'lxi' application which provides a simple commandline interface to discover LXI instruments, send SCPI commands, and capture screenshots from supported LXI instruments. lxi-tools rely on liblxi for all communication. ## 2. Usage The commandline interface of the lxi application is described in the output from 'lxi --help': ``` Usage: lxi [--version] [--help] [] -v, --version Display version -h, --help Display help Commands: discover [] Search for LXI devices scpi [] Send SCPI command screenshot [] [] Capture screenshot benchmark [] Benchmark Discover options: -t, --timeout Timeout (default: 3) -m, --mdns Search via mDNS/DNS-SD Scpi options: -a, --address Device IP address -p, --port Use port (default: VXI11: 111, RAW: 5025) -t, --timeout Timeout (default: 3) -x, --hex Print response in hexadecimal -i, --interactive Enter interactive mode -s, --script Run script file -r, --raw Use raw/TCP Screenshot options: -a, --address Device IP address -t, --timeout Timeout (default: 15) -p, --plugin Use screenshot plugin by name -l, --list List available screenshot plugins Benchmark options: -a, --address Device IP address -p, --port Use port (default: VXI11: 111, RAW: 5025) -t, --timeout Timeout (default: 3) -c, --count Number of request messages (default: 100) -r, --raw Use raw/TCP ``` ### 2.1 Example - Discover LXI devices on available networks ``` $ lxi discover Searching for LXI devices - please wait... Broadcasting on interface lo Broadcasting on interface eth0 Found "RIGOL TECHNOLOGIES,DS1104Z,DS1ZA1234567890,00.04.03.SP2" on address 10.42.1.20 Found "RIGOL TECHNOLOGIES,DP831,DP8F1234567890,00.01.14" on address 10.42.1.67 Broadcasting on interface wlan0 Found 2 devices ``` ### 2.2 Example - Send SCPI command to an instrument ``` $ lxi scpi --address 10.42.1.20 "*IDN?" RIGOL TECHNOLOGIES,DS1104Z,DS1ZA1234567890,00.04.03 ``` To dump response to file simply do: ``` $ lxi scpi --address 10.42.1.20 "*IDN?" > response.txt ``` ### 2.3 Example - Capture screenshot from a Rigol 1000z series oscilloscope ``` $ lxi screenshot --address 10.42.1.20 --plugin rigol-1000z Saved screenshot image to screenshot_10.42.1.20_2017-11-11_13:45:47.png ``` Or using plugin autodetection simply: ``` $ lxi screenshot --address 10.42.1.20 Loaded rigol-1000 screenshot plugin Saved screenshot image to screenshot_10.42.1.20_2017-11-11_13:46:02.png ``` ### 2.4 Example - Capture screenshot and convert it to any image format By default the format of the captured screenshot image is dictated by which screenshot plugin and instrument are in play. However, it is possible to write the screenshot image to stdout and pipe it directly to other tools for image processing. For example, use ImageMagicks convert tool to automatically convert screenshot image to JPG: ``` $ lxi screenshot --address 10.42.1.20 - | convert - screenshot.jpg ``` ### 2.5 Example - List available screenshot plugins ``` $ lxi screenshot --list Name Description keysight-iv2000x Keysight InfiniVision 2000X series oscilloscope (experimental) rigol-1000z Rigol DS/MSO 1000z series oscilloscope rigol-2000 Rigol DS/MSO 2000 series oscilloscope rigol-dg4000 Rigol DG 4000 series function generator rigol-dm3000 Rigol DM 3000 series digital multimeter rigol-dp800 Rigol DP 800 series power supply rigol-dsa Rigol DSA 700/800 series spectrum analyzer rs-hmo1000 Rohde & Schwarz HMO 1000 series oscilloscope siglent-sdm3000 Siglent SDM 3000/3000X series digital multimeter siglent-sdg Siglent SDG 1000X/2000X/6000X series waveform generator siglent-sds Siglent SDS 1000X/2000X series oscilloscope siglent-ssa3000x Siglent SSA 3000X series spectrum analyzer tektronix-2000 Tektronix DPO/MSO 2000 series oscilloscope (experimental) ``` ### 2.6 Example - Benchmark instrument request/response performance ``` $ lxi benchmark --address 10.42.1.20 Benchmarking by sending 100 ID requests. Please wait... Result: 24.7 requests/second ``` ## 3. Installation The latest release version can be downloaded from https://lxi-tools.github.io ### 3.1 Installation using release tarball Install steps: ``` $ ./configure $ make $ make install ``` Note: lxi-tools depends on liblxi so you need to go install liblxi first. ### 3.2 Installation using package lxi-tools comes prepackaged for various GNU/Linux distributions. Visit https://lxi-tools.github.io to see list of supported distributions. ## 4. Tested instruments The commandline lxi tool is tested to work successfully with the following LXI compatible instruments: | Instrument | Working features | |---------------------------------|----------------------------| | Rigol Technologies DG4062 | (discover+scpi+screenshot) | | Rigol Technologies DG4102 | (discover+scpi+screenshot) | | Rigol Technologies DG4162 | (discover+scpi+screenshot) | | Rigol Technologies DP831 | (discover+scpi+screenshot) | | Rigol Technologies DP832 | (discover+scpi+screenshot) | | Rigol Technologies DM3068 | (discover+scpi+screenshot) | | Rigol Technologies DS1104Z | (discover+scpi+screenshot) | | Rigol Technologies DS2302 | (discover+scpi+screenshot) | | Rigol Technologies DSA815 | (discover+scpi+screenshot) | | Rigol Technologies MSO1104Z | (discover+scpi+screenshot) | | Rigol Technologies MSO2302A | (discover+scpi+screenshot) | | Rohde & Schwarz HMO 1202 | (discover+scpi+screenshot) | | Siglent Technologies SDG1032X | (discover+scpi+screenshot) | | Siglent Technologies SDG2122X | (discover+scpi+screenshot) | | Siglent Technologies SDG6052 | (discover+scpi+screenshot) | | Siglent Technologies SDS1202X-E | (discover+scpi+screenshot) | | Siglent Technologies SDS1204X-E | (discover+scpi+screenshot) | | Siglent Technologies SDS2304X | (discover+scpi+screenshot) | | Siglent Technologies SDM3045X | (discover+scpi+screenshot) | | Siglent Technologies SDM3055 | (discover+scpi+screenshot) | | Siglent Technologies SDM3065X | (discover+scpi+screenshot) | | Siglent Technologies SPD3303X-E | (scpi) | | Siglent Technologies SSA3032X | (discover+scpi+screenshot) | Note: Feel free to add your instrument(s) to the list via GitHub pull request or simply create a GitHub issue reporting your instrument(s) and which features work. ## 5. Contributing lxi-tools is open source. If you want to help out with the project please join in. All contributions (bug reports, code, doc, ideas, etc.) are welcome. Please use the github issue tracker and pull request features. Also, if you find this free open source software useful please consider making a donation: [![Donate](https://www.paypal.com/en_US/i/btn/x-click-but21.gif)](https://www.paypal.me/lundmar) ## 6. Website Visit https://lxi-tools.github.io ## 7. License This code is released under BSD-3, commonly known as the 3-clause (or "modified") BSD license. ## 8. Authors Created by Martin Lund \ See the AUTHORS file for full list of authors. lxi-tools-1.15/autogen.sh000077500000000000000000000000401321525002000153530ustar00rootroot00000000000000autoreconf --force -v --install lxi-tools-1.15/configure.ac000066400000000000000000000021731321525002000156510ustar00rootroot00000000000000AC_PREREQ([2.68]) AC_INIT([lxi-tools], [1.15], [], [lxi-tools], [https://lxi-tools.github.io]) AC_CONFIG_HEADERS([src/include/config.h]) AM_INIT_AUTOMAKE([1.11 foreign dist-xz no-dist-gzip subdir-objects -Wall -Werror]) AM_SILENT_RULES([yes]) AM_PROG_AR AC_PROG_CC AC_PROG_INSTALL LT_INIT AC_LANG([C]) AC_CHECK_LIB([readline], [readline], [], [AC_MSG_ERROR(libreadline not found)]) AC_CHECK_LIB([lxi], [lxi_connect], [], [AC_MSG_ERROR(liblxi not found)]) # Handle bash completion AC_ARG_WITH([bash-completion-dir], AS_HELP_STRING([--with-bash-completion-dir[=PATH]], [Install the bash auto-completion script in this directory. @<:@default=yes@:>@]), [], [with_bash_completion_dir=yes]) if test "x$with_bash_completion_dir" = "xyes"; then BASH_COMPLETION_DIR="${datadir}/bash-completion/completions" else BASH_COMPLETION_DIR="$with_bash_completion_dir" fi AC_SUBST([BASH_COMPLETION_DIR]) AM_CONDITIONAL([ENABLE_BASH_COMPLETION],[test "x$with_bash_completion_dir" != "xno"]) AC_CONFIG_FILES([Makefile]) AC_CONFIG_FILES([src/Makefile]) AC_CONFIG_FILES([man/Makefile]) AC_OUTPUT lxi-tools-1.15/man/000077500000000000000000000000001321525002000141335ustar00rootroot00000000000000lxi-tools-1.15/man/Makefile.am000066400000000000000000000000261321525002000161650ustar00rootroot00000000000000dist_man_MANS = lxi.1 lxi-tools-1.15/man/lxi.1000066400000000000000000000052331321525002000150140ustar00rootroot00000000000000.TH "lxi" "1" "November 2017" .SH "NAME" lxi \- a tool for controlling LXI compatible instruments. .SH "SYNOPSIS" .PP .B lxi .RB [\| \-\-help \|] .RB [\| \-\-version \|] .I .I [] .SH "DESCRIPTION" .PP lxi is a commandline tool for controlling LXI compatible instruments such as modern oscilloscopes, power supplies, spectrum analyzers, etc. .SH "OPTIONS" .TP .B \-h, \--help Display help .TP .B \-v, \--version Display program version .SH COMMANDS .PP .B discover .I [] .RS Search available networks for LXI devices .RE .PP .B scpi .I [] .RS Send SCPI command .RE .PP .B screenshot .I [] [] .RS Capture screenshot .RE .PP .B benchmark .I [] .RS Benchmark .RE .SH "DISCOVER OPTIONS" .TP .B \-t, \--timeout Timeout in seconds .TP .B \-m, \--mdns Search via mDNS/DNS-SD .SH "SCPI OPTIONS" .TP .B \-a, \--address IP address of LXI device .TP .B \-p, \--port Use port .TP .B \-t, \--timeout Timeout in seconds .TP .B \-x, \--hex Print response in hexadecimal .TP .B \-i, \--interactive Enter interactive mode .TP .B \-s, \--script Run script (plain text file with one SCPI command per line) .TP .B \-r, \--raw Use raw/TCP protocol .SH "SCREENSHOT OPTIONS" .TP .B \-a, \--address IP address of LXI device .TP .B \-t, \--timeout Timeout in seconds .TP .B \-p, \--plugin Use screenshot plugin by name If this option is omitted the tool will automatically try to select the most suitable plugin. .TP .B \-l, \--list List available screenshot plugins .TP To write screenshot image to stdout simply use '-' as the output filename. .SH "BENCHMARK OPTIONS" .TP .B \-a, \--address IP address of LXI device .TP .B \-p, \--port Use port .TP .B \-t, \--timeout Timeout in seconds .TP .B \-c, \--count Number of request messages .TP .B \-r, \--raw Use raw/TCP protocol .SH "EXAMPLES" .TP Search for LXI instruments: lxi discover .TP Search for LXI instruments using mDNS/DNS-SD: lxi discover --mdns .TP Send SCPI command: lxi scpi --address 10.0.0.42 "*IDN?" .TP Send SCPI command and dump response to file: lxi scpi --address 10.0.0.42 "*IDN?" > response.txt .TP Capture screenshot from a Rigol 1000Z series oscilloscope: lxi screenshot --address 10.0.0.42 --plugin rigol-1000z Or by using screenshot plugin autodetection simply: lxi screenshot --address 10.0.0.42 .PP Note: Some LXI devices are slow to process SCPI commands, in which case you might need to take care to increase the timeout value. .SH "WEBSITE" .PP Visit https://lxi-tools.github.io .SH "AUTHOR" .PP Written by Martin Lund lxi-tools-1.15/src/000077500000000000000000000000001321525002000141475ustar00rootroot00000000000000lxi-tools-1.15/src/.gitignore000066400000000000000000000000441321525002000161350ustar00rootroot00000000000000*.o *.a /lxi rigol_1000z_screenshot lxi-tools-1.15/src/Makefile.am000066400000000000000000000017611321525002000162100ustar00rootroot00000000000000bin_PROGRAMS = lxi lxi_SOURCES = lxi.c \ options.c \ include/options.h \ include/error.h \ include/screenshot.h \ screenshot.c \ plugins/screenshot_keysight.c \ plugins/screenshot_rigol-1000z.c \ plugins/screenshot_rigol-2000.c \ plugins/screenshot_rigol-dg4000.c \ plugins/screenshot_rigol-dm3068.c \ plugins/screenshot_rigol-dp800.c \ plugins/screenshot_rigol-dsa.c \ plugins/screenshot_rohde-schwarz-hmo1000.c \ plugins/screenshot_siglent-sdm3000.c \ plugins/screenshot_siglent-sdg.c \ plugins/screenshot_siglent-sds.c \ plugins/screenshot_siglent-ssa3000x.c \ plugins/screenshot_tektronix.c lxi_CFLAGS = lxi_LDADD = -llxi -lreadline if ENABLE_BASH_COMPLETION bashcompletiondir=@BASH_COMPLETION_DIR@ dist_bashcompletion_DATA=bash-completion/lxi endif lxi-tools-1.15/src/bash-completion/000077500000000000000000000000001321525002000172335ustar00rootroot00000000000000lxi-tools-1.15/src/bash-completion/lxi000066400000000000000000000037151321525002000177600ustar00rootroot00000000000000# # Bash completion script for lxi # _lxi() { local cur prev firstword opts discover_opts scpi_opts screenshot_opts COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" firstword=$(get_firstword) # The options we'll complete. opts="-h --help \ -v --version \ discover \ scpi \ screenshot \ benchmark" discover_opts="-t --timeout \ -m --mdns" scpi_opts="-a --address \ -t --timeout \ -x --hex \ -i --interactive \ -s --script" screenshot_opts="-a --address \ -t --timeout \ -p --plugin \ -l --list" benchmark_opts="-a --address \ -t --timeout \ -r --repeat" # Complete the options case "${COMP_CWORD}" in 1) COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) ;; *) case ${firstword} in discover) COMPREPLY=( $(compgen -W "${discover_opts}" -- ${cur}) ) ;; scpi) COMPREPLY=( $(compgen -W "${scpi_opts}" -- ${cur}) ) ;; screenshot) COMPREPLY=( $(compgen -W "${screenshot_opts}" -- ${cur}) ) ;; benchmark) COMPREPLY=( $(compgen -W "${benchmark_opts}" -- ${cur}) ) ;; *) COMPREPLY=() ;; esac ;; esac return 0 } get_firstword() { local firstword i firstword= for ((i = 1; i < ${#COMP_WORDS[@]}; ++i)); do if [[ ${COMP_WORDS[i]} != -* ]]; then firstword=${COMP_WORDS[i]} break fi done echo $firstword } # Bind completion to lxi command complete -o default -F _lxi lxi lxi-tools-1.15/src/include/000077500000000000000000000000001321525002000155725ustar00rootroot00000000000000lxi-tools-1.15/src/include/error.h000066400000000000000000000032371321525002000171010ustar00rootroot00000000000000/* * Copyright (c) 2017 Martin Lund * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef ERROR_H #define ERROR_H #define error_printf(format, args...) \ fprintf(stderr, "Error: " format, ## args) #endif lxi-tools-1.15/src/include/options.h000066400000000000000000000042131321525002000174360ustar00rootroot00000000000000/* * Copyright (c) 2016 Martin Lund * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef OPTIONS_H #define OPTIONS_H #include #include #include /* Options */ struct option_t { int command; int timeout; char ip[500]; char scpi_command[500]; bool hex; bool interactive; bool run_script; char *script_filename; char *plugin_name; bool list; char screenshot_filename[500]; lxi_protocol_t protocol; int port; bool mdns; int count; }; enum command_t { DISCOVER, SCPI, SCREENSHOT, BENCHMARK, NO_COMMAND }; extern struct option_t option; void parse_options(int argc, char *argv[]); #endif lxi-tools-1.15/src/include/screenshot.h000066400000000000000000000037251321525002000201270ustar00rootroot00000000000000/* * Copyright (c) 2017 Martin Lund * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ void screenshot_register_plugins(void); void screenshot_list_plugins(void); int screenshot(char *address, char *plugin_name, char *filename, int timeout); // Screenshot helper function used by plugins to dump image file void screenshot_file_dump(void *data, int length, char *format); struct screenshot_plugin { const char *name; const char *description; const char *regex; int (*screenshot)(char *address, int timeout); }; lxi-tools-1.15/src/lxi.c000066400000000000000000000301541321525002000151120ustar00rootroot00000000000000/* * Copyright (c) 2016-2017 Martin Lund * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include "options.h" #include "error.h" #include "screenshot.h" #include #define RESPONSE_LENGTH_MAX 0x500000 #define ID_LENGTH_MAX 65536 static int device_count = 0; static int service_count = 0; static void hex_print(void *data, int length) { char *bufferp; int i; bufferp = data; (void)bufferp; for (i=0; i= 0) { if ( isspace(line[i]) ) line[i] = '\0'; else break; i--; } } static int scpi(char *ip, int port, int timeout, lxi_protocol_t protocol, char *command) { char response[RESPONSE_LENGTH_MAX] = ""; char command_buffer[1000]; int device, length;; strip_trailing_space(command); if (protocol == RAW) { // Add newline to command string strcpy(command_buffer, command); command_buffer[strlen(command)] = '\n'; command_buffer[strlen(command)+1] = 0; command = command_buffer; } // Connect device = lxi_connect(ip, port, NULL, timeout, protocol); if (device != LXI_OK) { error_printf("Unable to connect to LXI device\n"); goto error_connect; } // Send SCPI command length = lxi_send(device, command, strlen(command), timeout); if (length < 0) { error_printf("Failed to send message\n"); goto error_send; } int question(char *string) { int i; for (i = 0; string[i] != '\0'; i++) { if (string[i] == '?') return true; } return false; } // Only expect response in case we are firing a question command if (question(command)) { length = lxi_receive(device, response, RESPONSE_LENGTH_MAX, timeout); if (length < 0) { error_printf("Failed to receive message\n"); goto error_receive; } // Print response if (option.hex) hex_print(response, length); else { int i; for (i=0; i "); if (input == NULL) break; add_history(input); strip_trailing_space(input); // Skip empty lines if (strlen(input) == 0) continue; // Send entered input as SCPI command length = lxi_send(device, input, strlen(input), timeout); if (length < 0) error_printf("Failed to send message\n"); // Only expect response in case we are firing a question command if (input[strlen(input)-1] == '?') { length = lxi_receive(device, response, RESPONSE_LENGTH_MAX, timeout); if (length < 0) { error_printf("Failed to receive message\n"); } else { // Make sure we terminate response string response[length] = 0; // Print response printf("%s", response); } } } printf("\n"); // Disconnect lxi_disconnect(device); return 0; error_connect: return 1; } static int run_script(char *ip, int port, int timeout, lxi_protocol_t protocol, char *filename) { FILE *fp; char *line = NULL; size_t len = 0; ssize_t read; char response[RESPONSE_LENGTH_MAX] = ""; int device, length, i; // Open script file fp = fopen(filename, "r"); if (fp == NULL) { error_printf("Unable to open file %s\n", filename); goto error_fopen; } // Connect device = lxi_connect(ip, port, NULL, timeout, VXI11); if (device != LXI_OK) { error_printf("Unable to connect to LXI device\n"); goto error_connect; } printf("Connected to %s\n", ip); printf("Running script %s\n\n", filename); while ((read = getline(&line, &len, fp)) != -1) { printf("%s", line); strip_trailing_space(line); // Skip empty lines if (strlen(line) == 1) continue; // Send read line as SCPI command length = lxi_send(device, line, strlen(line), timeout); if (length < 0) error_printf("Failed to send message\n"); // Only expect response in case we are firing a question command if (line[strlen(line)-1] == '?') { length = lxi_receive(device, response, RESPONSE_LENGTH_MAX, timeout); if (length < 0) { error_printf("Failed to receive message\n"); } else { // Make sure we terminate response string response[length] = 0; // Print response for (i=0; i 1 ? 's' : ' '); } else { lxi_discover(&info, option.timeout, DISCOVER_VXI11); printf("\n"); if (device_count == 0) printf("No devices found\n"); else printf("Found %d device%c\n", device_count, device_count > 1 ? 's' : ' '); } printf("\n"); return 0; } static int benchmark(char *ip, int port, int timeout, lxi_protocol_t protocol, int count) { struct timespec start, stop; double elapsed_time; int device, i, bytes_received; char id[ID_LENGTH_MAX]; char *command = "*IDN?"; // Check for required options if (strlen(ip) == 0) { error_printf("Missing address\n"); exit(EXIT_FAILURE); } if (protocol == RAW) command = "*IDN?\n"; // Connect device = lxi_connect(ip, port, NULL, timeout, protocol); if (device != LXI_OK) { error_printf("Unable to connect to LXI device\n"); return 1; } printf("Benchmarking by sending %d ID requests. Please wait...\n", count); // Start time if ( clock_gettime(CLOCK_MONOTONIC, &start) == -1 ) { error_printf("Failed to get start time\n"); return 1; } // Run benchmark for (i=0; i #include #include #include #include #include #include #include #include "config.h" #include "options.h" #include "error.h" #include #define TIMEOUT_SCREENSHOT 15 #define TIMEOUT_DISCOVER 2 #define PORT_VXI11 111 #define PORT_RAW 5025 struct option_t option = { NO_COMMAND, // Default command 3, // Default timeout in seconds "", // Default IP address "", // Default SCPI command false, // Default no hexadecimal print false, // Default no interactive mode false, // Default no run script "", // Default script filename "", // Default screenshot plugin name false, // Default no list "", // Default screenshot filename VXI11, // Default protocol 0, // Default port (set later) false, // Default no mDNS discover 100, // Default number of requests in benchmark }; void print_help(char *argv[]) { printf("Usage: %s [--version] [--help] []\n", argv[0]); printf("\n"); printf(" -v, --version Display version\n"); printf(" -h, --help Display help\n"); printf("\n"); printf("Commands:\n"); printf(" discover [] Search for LXI devices\n"); printf(" scpi [] Send SCPI command\n"); printf(" screenshot [] [] Capture screenshot\n"); printf(" benchmark [] Benchmark\n"); printf("\n"); printf("Discover options:\n"); printf(" -t, --timeout Timeout (default: %d)\n", TIMEOUT_DISCOVER); printf(" -m, --mdns Search via mDNS/DNS-SD\n"); printf("\n"); printf("Scpi options:\n"); printf(" -a, --address Device IP address\n"); printf(" -p, --port Use port (default: VXI11: %d, RAW: %d)\n", PORT_VXI11, PORT_RAW); printf(" -t, --timeout Timeout (default: %d)\n", option.timeout); printf(" -x, --hex Print response in hexadecimal\n"); printf(" -i, --interactive Enter interactive mode\n"); printf(" -s, --script Run script file\n"); printf(" -r, --raw Use raw/TCP\n"); printf("\n"); printf("Screenshot options:\n"); printf(" -a, --address Device IP address\n"); printf(" -t, --timeout Timeout (default: %d)\n", TIMEOUT_SCREENSHOT); printf(" -p, --plugin Use screenshot plugin by name\n"); printf(" -l, --list List available screenshot plugins\n"); printf("\n"); printf("Benchmark options:\n"); printf(" -a, --address Device IP address\n"); printf(" -p, --port Use port (default: VXI11: %d, RAW: %d)\n", PORT_VXI11, PORT_RAW); printf(" -t, --timeout Timeout (default: %d)\n", option.timeout); printf(" -c, --count Number of requests (default: %d)\n", option.count); printf(" -r, --raw Use raw/TCP\n"); printf("\n"); } void print_version(void) { printf("lxi v%s\n", VERSION); } void parse_options(int argc, char *argv[]) { int c; // Print help if no arguments provided if (argc == 1) { print_help(argv); exit(EXIT_SUCCESS); } // Convert default timeout to milliseconds option.timeout = option.timeout * 1000; // getopt_long stores the option index here int option_index = 0; // Skip ahead past command optind = 2; if (strcmp(argv[1], "discover") == 0) { option.command = DISCOVER; // Set default timeout for discovery option.timeout = TIMEOUT_DISCOVER * 1000; static struct option long_options[] = { {"timeout", required_argument, 0, 't'}, {"mdns", no_argument, 0, 'm'}, {0, 0, 0, 0 } }; /* Parse discover options */ c = getopt_long(argc, argv, "t:m", long_options, &option_index); while (c != -1) { switch (c) { case 't': option.timeout = atoi(optarg) * 1000; break; case 'm': option.mdns = true; break; case '?': exit(EXIT_FAILURE); } c = getopt_long(argc, argv, "t:m", long_options, &option_index); } } else if (strcmp(argv[1], "scpi") == 0) { option.command = SCPI; static struct option long_options[] = { {"address", required_argument, 0, 'a'}, {"port", required_argument, 0, 'p'}, {"timeout", required_argument, 0, 't'}, {"hex", no_argument, 0, 'x'}, {"interactive", no_argument, 0, 'i'}, {"script", required_argument, 0, 's'}, {"raw", no_argument, 0, 'r'}, {0, 0, 0, 0 } }; do { /* Parse scpi options */ c = getopt_long(argc, argv, "a:p:t:xis:r", long_options, &option_index); switch (c) { case 'a': strncpy(option.ip, optarg, 500); break; case 'p': option.port = atoi(optarg); break; case 't': option.timeout = atoi(optarg) * 1000; break; case 'x': option.hex = true; break; case 'i': option.interactive = true; break; case 's': option.run_script = true; option.script_filename = optarg; break; case 'r': option.protocol = RAW; break; case '?': exit(EXIT_FAILURE); } } while (c != -1); } else if (strcmp(argv[1], "screenshot") == 0) { option.command = SCREENSHOT; // Set default timeout for screenshots option.timeout = TIMEOUT_SCREENSHOT * 1000; static struct option long_options[] = { {"address", required_argument, 0, 'a'}, {"timeout", required_argument, 0, 't'}, {"plugin", required_argument, 0, 'p'}, {"list", no_argument, 0, 'l'}, {0, 0, 0, 0 } }; do { /* Parse screenshot options */ c = getopt_long(argc, argv, "a:t:p:l", long_options, &option_index); switch (c) { case 'a': strncpy(option.ip, optarg, 500); break; case 't': option.timeout = atoi(optarg) * 1000; break; case 'p': option.plugin_name = optarg; break; case 'l': option.list = true; break; case '?': exit(EXIT_FAILURE); } } while (c != -1); } else if (strcmp(argv[1], "benchmark") == 0) { option.command = BENCHMARK; static struct option long_options[] = { {"address", required_argument, 0, 'a'}, {"port", required_argument, 0, 'p'}, {"timeout", required_argument, 0, 't'}, {"count", required_argument, 0, 'c'}, {"raw", no_argument, 0, 'r'}, {0, 0, 0, 0 } }; do { /* Parse benchmark options */ c = getopt_long(argc, argv, "a:p:t:rc:", long_options, &option_index); switch (c) { case 'a': strncpy(option.ip, optarg, 500); break; case 'p': option.port = atoi(optarg); break; case 't': option.timeout = atoi(optarg) * 1000; break; case 'c': option.count = atoi(optarg); break; case 'r': option.protocol = RAW; break; case '?': exit(EXIT_FAILURE); } } while (c != -1); } else { // No command provided so we restore index optind = 1; static struct option long_options[] = { {"version", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0 } }; do { /* Parse options */ c = getopt_long(argc, argv, "vh", long_options, &option_index); switch (c) { case 'v': print_version(); exit(EXIT_SUCCESS); case 'h': print_help(argv); exit(EXIT_SUCCESS); case '?': exit(EXIT_FAILURE); } } while (c != -1); } if ((option.command == NO_COMMAND) && (optind != argc)) { error_printf("Unknown command\n"); exit(EXIT_FAILURE); } if (option.command == SCPI) { if (optind != argc) strncpy(option.scpi_command, argv[optind++], 500); if (strlen(option.ip) == 0) { error_printf("No IP address specified\n"); exit(EXIT_FAILURE); } if ((strlen(option.scpi_command) == 0) && (option.interactive == false)) { error_printf("No SCPI command specified\n"); exit(EXIT_FAILURE); } } if ((option.command == SCREENSHOT) && (optind != argc)) { strncpy(option.screenshot_filename, argv[optind++], 500); } /* Print any unknown arguments */ if (optind < argc) { error_printf("Unknown arguments: "); while (optind < argc) fprintf(stderr, "%s ", argv[optind++]); fprintf(stderr, "\n"); exit(EXIT_FAILURE); } /* Configure port */ if (option.port == 0) { // See http://www.lxistandard.org/About/LXI-Protocols.aspx if (option.protocol == RAW) option.port = 5025; // Default TCP/RAW port else option.port = 111; // Default TCP/VXI11 port } } lxi-tools-1.15/src/plugins/000077500000000000000000000000001321525002000156305ustar00rootroot00000000000000lxi-tools-1.15/src/plugins/screenshot_keysight.c000066400000000000000000000062101321525002000220570ustar00rootroot00000000000000/* * Copyright (c) 2017 Martin Lund * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "error.h" #include "screenshot.h" #define IMAGE_SIZE_MAX 0x400000 // 4 MB int keysight_screenshot(char *address, int timeout) { char response[IMAGE_SIZE_MAX]; char *command, *image; int device, length, n; char c; // Connect to LXI instrument device = lxi_connect(address, 0, NULL, timeout, VXI11); if (device == LXI_ERROR) { error_printf("Failed to connect\n"); return 1; } // Send SCPI commands to grab PNG image command = ":hardcopy:inksaver off"; lxi_send(device, command, strlen(command), timeout); command = ":display:data? PNG, color"; lxi_send(device, command, strlen(command), timeout); length = lxi_receive(device, response, IMAGE_SIZE_MAX, timeout); if (length < 0) { error_printf("Failed to receive message\n"); return 1; } // Strip IEEE 488.2 Data Block header c = response[1]; n = atoi(&c); image = &response[0]; image += n+5; length -= n+5; // Strip ending newline length--; // Dump remaining PNG image data to file screenshot_file_dump(image, length, "png"); // Disconnect lxi_disconnect(device); return 0; } // Screenshot plugin configuration struct screenshot_plugin keysight_iv2000x = { .name = "keysight-iv2000x", .description = "Keysight InfiniVision 2000X series oscilloscope (experimental)", .regex = "AGILENT KEYSIGHT TECHNOLOGIES DSOX2...A MSOX2...A", .screenshot = keysight_screenshot }; lxi-tools-1.15/src/plugins/screenshot_rigol-1000z.c000066400000000000000000000057241321525002000221250ustar00rootroot00000000000000/* * Copyright (c) 2017 Martin Lund * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "error.h" #include "screenshot.h" #define IMAGE_SIZE_MAX 0x400000 // 4 MB int rigol_1000z_screenshot(char *address, int timeout) { char response[IMAGE_SIZE_MAX]; char *command, *image; int device, length, n; char c; // Connect to LXI instrument device = lxi_connect(address, 0, NULL, timeout, VXI11); if (device == LXI_ERROR) { error_printf("Failed to connect\n"); return 1; } // Send SCPI command to grab PNG image command = "display:data? on,0,png"; lxi_send(device, command, strlen(command), timeout); length = lxi_receive(device, response, IMAGE_SIZE_MAX, timeout); if (length < 0) { error_printf("Failed to receive message\n"); return 1; } // Strip TMC block header c = response[1]; n = atoi(&c); image = &response[0]; image += n+2; length -= n+2; // Dump remaining PNG image data to file screenshot_file_dump(image, length, "png"); // Disconnect lxi_disconnect(device); return 0; } // Screenshot plugin configuration struct screenshot_plugin rigol_1000z = { .name = "rigol-1000z", .description = "Rigol DS/MSO 1000Z series oscilloscope", .regex = "RIGOL TECHNOLOGIES Rigol Technologies DS1...Z MSO1...Z", .screenshot = rigol_1000z_screenshot }; lxi-tools-1.15/src/plugins/screenshot_rigol-2000.c000066400000000000000000000057601321525002000217340ustar00rootroot00000000000000/* * Copyright (c) 2017 Martin Lund * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "error.h" #include "screenshot.h" #define IMAGE_SIZE_MAX 0x400000 // 4 MB int rigol_2000_screenshot(char *address, int timeout) { char response[IMAGE_SIZE_MAX]; char *command, *image; int device, length, n; char c; // Connect to LXI instrument device = lxi_connect(address, 0, NULL, timeout, VXI11); if (device == LXI_ERROR) { error_printf("Failed to connect\n"); return 1; } // Send SCPI command to grab BMP image command = ":display:data?"; lxi_send(device, command, strlen(command), timeout); length = lxi_receive(device, response, IMAGE_SIZE_MAX, timeout); if (length < 0) { error_printf("Failed to receive message\n"); return 1; } // Strip TMC block header c = response[1]; n = atoi(&c); image = &response[0]; image += n+2; length -= n+2; // Strip ending newline length--; // Dump remaining BMP image data to file screenshot_file_dump(image, length, "bmp"); // Disconnect lxi_disconnect(device); return 0; } // Screenshot plugin configuration struct screenshot_plugin rigol_2000 = { .name = "rigol-2000", .description = "Rigol DS/MSO 2000 series oscilloscope", .regex = "RIGOL TECHNOLOGIES Rigol Technologies DS2... MSO2...", .screenshot = rigol_2000_screenshot }; lxi-tools-1.15/src/plugins/screenshot_rigol-dg4000.c000066400000000000000000000057131321525002000222470ustar00rootroot00000000000000/* * Copyright (c) 2017 Martin Lund * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "error.h" #include "screenshot.h" #define IMAGE_SIZE_MAX 0x400000 // 4 MB int rigol_dg4000_screenshot(char *address, int timeout) { char response[IMAGE_SIZE_MAX]; char *command, *image; int device, length, n; char c; // Connect to LXI instrument device = lxi_connect(address, 0, NULL, timeout, VXI11); if (device == LXI_ERROR) { error_printf("Failed to connect\n"); return 1; } // Send SCPI command to grab BMP image command = ":HCOPy:SDUMp:DATA?"; lxi_send(device, command, strlen(command), timeout); length = lxi_receive(device, response, IMAGE_SIZE_MAX, timeout); if (length < 0) { error_printf("Failed to receive message\n"); return 1; } // Strip TMC block header c = response[1]; n = atoi(&c); image = &response[0]; image += n+2; length -= n+2; // Dump remaining BMP image data to file screenshot_file_dump(image, length, "bmp"); // Disconnect lxi_disconnect(device); return 0; } // Screenshot plugin configuration struct screenshot_plugin rigol_dg4000 = { .name = "rigol-dg4000", .description = "Rigol DG 4000 series function generator", .regex = "RIGOL TECHNOLOGIES Rigol Technologies DG4...", .screenshot = rigol_dg4000_screenshot }; lxi-tools-1.15/src/plugins/screenshot_rigol-dm3068.c000066400000000000000000000056751321525002000223010ustar00rootroot00000000000000/* * Copyright (c) 2017 Martin Lund * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "error.h" #include "screenshot.h" #define IMAGE_SIZE_MAX 0x400000 // 4 MB int rigol_dm3068_screenshot(char *address, int timeout) { char response[IMAGE_SIZE_MAX]; char *command, *image; int device, length, n; char c; // Connect to LXI instrument device = lxi_connect(address, 0, NULL, timeout, VXI11); if (device == LXI_ERROR) { error_printf("Failed to connect\n"); return 1; } // Send SCPI command to grab BMP image command = ":DISP:DATA?"; lxi_send(device, command, strlen(command), timeout); length = lxi_receive(device, response, IMAGE_SIZE_MAX, timeout); if (length < 0) { error_printf("Failed to receive message\n"); return 1; } // Strip TMC block header c = response[1]; n = atoi(&c); image = &response[0]; image += n+2; length -= n+2; // Dump remaining BMP image data to file screenshot_file_dump(image, length, "bmp"); // Disconnect lxi_disconnect(device); return 0; } // Screenshot plugin configuration struct screenshot_plugin rigol_dm3068 = { .name = "rigol-dm3068", .description = "Rigol DM 3068 digital multimeter", .regex = "RIGOL TECHNOLOGIES Rigol Technologies DM3068", .screenshot = rigol_dm3068_screenshot }; lxi-tools-1.15/src/plugins/screenshot_rigol-dp800.c000066400000000000000000000056771321525002000222150ustar00rootroot00000000000000/* * Copyright (c) 2017 Martin Lund * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "error.h" #include "screenshot.h" #define IMAGE_SIZE_MAX 0x400000 // 4 MB int rigol_dp800_screenshot(char *address, int timeout) { char response[IMAGE_SIZE_MAX]; char *command, *image; int device, length, n; char c; // Connect to LXI instrument device = lxi_connect(address, 0, NULL, timeout, VXI11); if (device == LXI_ERROR) { error_printf("Failed to connect\n"); return 1; } // Send SCPI command to grab BMP image command = ":SYSTem:PRINT? BMP"; lxi_send(device, command, strlen(command), timeout); length = lxi_receive(device, response, IMAGE_SIZE_MAX, timeout); if (length < 0) { error_printf("Failed to receive message\n"); return 1; } // Strip TMC block header c = response[1]; n = atoi(&c); image = &response[0]; image += n+2; length -= n+2; // Dump remaining BMP image data to file screenshot_file_dump(image, length, "bmp"); // Disconnect lxi_disconnect(device); return 0; } // Screenshot plugin configuration struct screenshot_plugin rigol_dp800 = { .name = "rigol-dp800", .description = "Rigol DP 800 series power supply", .regex = "RIGOL TECHNOLOGIES Rigol Technologies DP8..", .screenshot = rigol_dp800_screenshot }; lxi-tools-1.15/src/plugins/screenshot_rigol-dsa.c000066400000000000000000000057021321525002000221160ustar00rootroot00000000000000/* * Copyright (c) 2017 Martin Lund * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "error.h" #include "screenshot.h" #define IMAGE_SIZE_MAX 0x400000 // 4 MB int rigol_dsa_screenshot(char *address, int timeout) { char response[IMAGE_SIZE_MAX]; char *command, *image; int device, length, n; char c; // Connect to LXI instrument device = lxi_connect(address, 0, NULL, timeout, VXI11); if (device == LXI_ERROR) { error_printf("Failed to connect\n"); return 1; } // Send SCPI command to grab BMP image command = ":PRIV:SNAP? BMP"; lxi_send(device, command, strlen(command), timeout); length = lxi_receive(device, response, IMAGE_SIZE_MAX, timeout); if (length < 0) { error_printf("Failed to receive message\n"); return 1; } // Strip TMC block header c = response[1]; n = atoi(&c); image = &response[0]; image += n+2; length -= n+2; // Dump remaining BMP image data to file screenshot_file_dump(image, length, "bmp"); // Disconnect lxi_disconnect(device); return 0; } // Screenshot plugin configuration struct screenshot_plugin rigol_dsa = { .name = "rigol-dsa", .description = "Rigol DSA 700/800 series spectrum analyzer", .regex = "RIGOL TECHNOLOGIES Rigol Technologies DSA[78]..", .screenshot = rigol_dsa_screenshot }; lxi-tools-1.15/src/plugins/screenshot_rohde-schwarz-hmo1000.c000066400000000000000000000057751321525002000241110ustar00rootroot00000000000000/* * Copyright (c) 2017 Martin Lund * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "error.h" #include "screenshot.h" #define IMAGE_SIZE_MAX 0x400000 // 4 MB int rs_hmo1000_screenshot(char *address, int timeout) { char response[IMAGE_SIZE_MAX]; char *command, *image; int device, length, n; char c; // Connect to LXI instrument device = lxi_connect(address, 0, NULL, timeout, VXI11); if (device == LXI_ERROR) { error_printf("Failed to connect\n"); return 1; } // Send SCPI commands to grab PNG image command = "HCOPy:FORMat PNG"; lxi_send(device, command, strlen(command), timeout); command = "HCOPy:DATA?"; lxi_send(device, command, strlen(command), timeout); length = lxi_receive(device, response, IMAGE_SIZE_MAX, timeout); if (length < 0) { error_printf("Failed to receive message\n"); return 1; } // Strip header c = response[1]; n = atoi(&c); image = &response[0]; image += n+2; length -= n+2; // Dump remaining PNG image data to file screenshot_file_dump(image, length, "png"); // Disconnect lxi_disconnect(device); return 0; } // Screenshot plugin configuration struct screenshot_plugin rs_hmo1000 = { .name = "rs-hmo1000", .description = "Rohde & Schwarz HMO 1000 series oscilloscope", .regex = "Rohde&Schwarz HMO1...", .screenshot = rs_hmo1000_screenshot }; lxi-tools-1.15/src/plugins/screenshot_siglent-sdg.c000066400000000000000000000054751321525002000224640ustar00rootroot00000000000000/* * Copyright (c) 2017 Martin Lund * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "error.h" #include "screenshot.h" #define IMAGE_SIZE_MAX 0x400000 // 4 MB int siglent_sdg_screenshot(char *address, int timeout) { char response[IMAGE_SIZE_MAX] = {}; char *command; int device, length; // Connect to LXI instrument device = lxi_connect(address, 0, NULL, timeout, VXI11); if (device == LXI_ERROR) { error_printf("Failed to connect\n"); return 1; } // Send SCPI command to grab BMP image command = "scdp"; lxi_send(device, command, strlen(command), timeout); length = lxi_receive(device, response, IMAGE_SIZE_MAX, timeout); if (length < 0) { error_printf("Failed to receive message\n"); return 1; } // Dump received BMP image data to file screenshot_file_dump(response, length, "bmp"); // Disconnect lxi_disconnect(device); return 0; } // Screenshot plugin configuration struct screenshot_plugin siglent_sdg = { .name = "siglent-sdg", .description = "Siglent SDG 1000X/2000X/6000X series waveform generator", .regex = "SIGLENT TECHNOLOGIES Siglent Technologies SDG[126]...", .screenshot = siglent_sdg_screenshot }; lxi-tools-1.15/src/plugins/screenshot_siglent-sdm3000.c000066400000000000000000000055021321525002000227640ustar00rootroot00000000000000/* * Copyright (c) 2017 Martin Lund * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "error.h" #include "screenshot.h" #define IMAGE_SIZE_MAX 0x400000 // 4 MB int siglent_sdm3000_screenshot(char *address, int timeout) { char response[IMAGE_SIZE_MAX] = {}; char *command; int device, length; // Connect to LXI instrument device = lxi_connect(address, 0, NULL, timeout, VXI11); if (device == LXI_ERROR) { error_printf("Failed to connect\n"); return 1; } // Send SCPI command to grab BMP image command = "scdp"; lxi_send(device, command, strlen(command), timeout); length = lxi_receive(device, response, IMAGE_SIZE_MAX, timeout); if (length < 0) { error_printf("Failed to receive message\n"); return 1; } // Dump received BMP image data to file screenshot_file_dump(response, length, "bmp"); // Disconnect lxi_disconnect(device); return 0; } // Screenshot plugin configuration struct screenshot_plugin siglent_sdm3000 = { .name = "siglent-sdm3000", .description = "Siglent SDM 3000/3000X series digital multimeter", .regex = "SIGLENT TECHNOLOGIES Siglent Technologies SDM3...", .screenshot = siglent_sdm3000_screenshot }; lxi-tools-1.15/src/plugins/screenshot_siglent-sds.c000066400000000000000000000054601321525002000224720ustar00rootroot00000000000000/* * Copyright (c) 2017 Martin Lund * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "error.h" #include "screenshot.h" #define IMAGE_SIZE_MAX 0x400000 // 4 MB int siglent_sds_screenshot(char *address, int timeout) { char response[IMAGE_SIZE_MAX] = {}; char *command; int device, length; // Connect to LXI instrument device = lxi_connect(address, 0, NULL, timeout, VXI11); if (device == LXI_ERROR) { error_printf("Failed to connect\n"); return 1; } // Send SCPI command to grab BMP image command = "scdp"; lxi_send(device, command, strlen(command), timeout); length = lxi_receive(device, response, IMAGE_SIZE_MAX, timeout); if (length < 0) { error_printf("Failed to receive message\n"); return 1; } // Dump received BMP image data to file screenshot_file_dump(response, length, "bmp"); // Disconnect lxi_disconnect(device); return 0; } // Screenshot plugin configuration struct screenshot_plugin siglent_sds = { .name = "siglent-sds", .description = "Siglent SDS 1000X/2000X series oscilloscope", .regex = "SIGLENT TECHNOLOGIES Siglent Technologies SDS[12]...", .screenshot = siglent_sds_screenshot }; lxi-tools-1.15/src/plugins/screenshot_siglent-ssa3000x.c000066400000000000000000000055011321525002000231560ustar00rootroot00000000000000/* * Copyright (c) 2017 Martin Lund * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "error.h" #include "screenshot.h" #define IMAGE_SIZE_MAX 0x400000 // 4 MB int siglent_ssa3000x_screenshot(char *address, int timeout) { char response[IMAGE_SIZE_MAX] = {}; char *command; int device, length; // Connect to LXI instrument device = lxi_connect(address, 0, NULL, timeout, VXI11); if (device == LXI_ERROR) { error_printf("Failed to connect\n"); return 1; } // Send SCPI command to grab BMP image command = "scdp"; lxi_send(device, command, strlen(command), timeout); length = lxi_receive(device, response, IMAGE_SIZE_MAX, timeout); if (length < 0) { error_printf("Failed to receive message\n"); return 1; } // Dump received BMP image data to file screenshot_file_dump(response, length, "bmp"); // Disconnect lxi_disconnect(device); return 0; } // Screenshot plugin configuration struct screenshot_plugin siglent_ssa3000x = { .name = "siglent-ssa3000x", .description = "Siglent SSA 3000X series spectrum analyzer", .regex = "SIGLENT TECHNOLOGIES Siglent Technologies SSA3...X", .screenshot = siglent_ssa3000x_screenshot }; lxi-tools-1.15/src/plugins/screenshot_tektronix.c000066400000000000000000000057471321525002000222750ustar00rootroot00000000000000/* * Copyright (c) 2017 Martin Lund * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "error.h" #include "screenshot.h" #define IMAGE_SIZE_MAX 0x400000 // 4 MB int tektronix_screenshot(char *address, int timeout) { char response[IMAGE_SIZE_MAX]; char *command; int device, length; // Connect to LXI instrument device = lxi_connect(address, 0, NULL, timeout, VXI11); if (device == LXI_ERROR) { error_printf("Failed to connect\n"); return 1; } // Send SCPI commands to grab PNG image command = "save:image:fileformat PNG"; lxi_send(device, command, strlen(command), timeout); command = "hardcopy:inksaver off"; lxi_send(device, command, strlen(command), timeout); command = "hardcopy start"; lxi_send(device, command, strlen(command), timeout); length = lxi_receive(device, response, IMAGE_SIZE_MAX, timeout); if (length < 0) { error_printf("Failed to receive message\n"); return 1; } // Dump PNG image data to file screenshot_file_dump(response, length, "png"); // Disconnect lxi_disconnect(device); return 0; } // Screenshot plugin configuration struct screenshot_plugin tektronix_2000 = { .name = "tektronix-2000", .description = "Tektronix DPO/MSO 2000 series oscilloscope (experimental)", .regex = "TEKTRONIX DPO2... MSO2...", .screenshot = tektronix_screenshot }; lxi-tools-1.15/src/screenshot.c000066400000000000000000000240351321525002000164740ustar00rootroot00000000000000/* * Copyright (c) 2017 Martin Lund * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include "screenshot.h" #include "options.h" #include "error.h" #include #define PLUGIN_LIST_SIZE_MAX 50 #define ID_LENGTH_MAX 65536 extern struct screenshot_plugin keysight_iv2000x; extern struct screenshot_plugin rigol_1000z; extern struct screenshot_plugin rigol_2000; extern struct screenshot_plugin rigol_dg4000; extern struct screenshot_plugin rigol_dm3068; extern struct screenshot_plugin rigol_dp800; extern struct screenshot_plugin rigol_dsa; extern struct screenshot_plugin rs_hmo1000; extern struct screenshot_plugin siglent_sdm3000; extern struct screenshot_plugin siglent_sdg; extern struct screenshot_plugin siglent_sds; extern struct screenshot_plugin siglent_ssa3000x; extern struct screenshot_plugin tektronix_2000; static struct screenshot_plugin *plugin_list[PLUGIN_LIST_SIZE_MAX] = { }; static int get_device_id(char *address, char *id, int timeout) { int device, bytes_sent, bytes_received; char *command; // Connect to LXI instrument device = lxi_connect(address, 0, NULL, timeout, VXI11); if (device == LXI_ERROR) { error_printf("Failed to connect\n"); goto error_connect; } // Get instrument ID command = "*IDN?"; bytes_sent = lxi_send(device, command, strlen(command), timeout); if (bytes_sent < 0) goto error_send; bytes_received = lxi_receive(device, id, ID_LENGTH_MAX, timeout); if (bytes_received < 0) { error_printf("Failed to receive message\n"); goto error_receive; } // Disconnect lxi_disconnect(device); // Remove trailing newline if (id[bytes_received-1] == '\n') id[bytes_received-1] = 0; return 0; error_receive: error_send: lxi_disconnect(device); error_connect: return 1; } static bool regex_match(const char *string, const char *pattern) { regex_t regex; int status; if (regcomp(®ex, pattern, REG_EXTENDED | REG_NOSUB) != 0) return false; // No match status = regexec(®ex, string, (size_t) 0, NULL, 0); regfree(®ex); if (status != 0) return false; // No match return true; // Match } char *date_time(void) { static char date_time_string[50]; time_t t = time(NULL); struct tm tm = *localtime(&t); sprintf(date_time_string, "%d-%02d-%02d_%02d:%02d:%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); return date_time_string; } void screenshot_file_dump(void *data, int length, char *format) { char automatic_filename[1000]; char *screenshot_filename; char *image_data = data; int i = 0; FILE *fd; // Handle screenshot output if (strlen(option.screenshot_filename) == 0) { // Automatically resolve screenshot filename if no filename is provided sprintf(automatic_filename, "screenshot_%s_%s.%s", option.ip, date_time(), format); screenshot_filename = automatic_filename; } else if (strcmp(option.screenshot_filename, "-") == 0) { // Write image data to stdout in case filename is '-' for (i=0; i= PLUGIN_LIST_SIZE_MAX) { error_printf("Screenshot plugin list full\n"); exit(EXIT_FAILURE); } // Add plugin plugin_list[i] = plugin; } void screenshot_list_plugins(void) { int length, length_max = 0; int i = 0, j = 0; // Find length of longest plugin name while ((i < PLUGIN_LIST_SIZE_MAX) && (plugin_list[i] != NULL)) { length = strlen(plugin_list[i]->name); if (length_max < length) length_max = length; i++; } // Pretty print list of available plugins i=0; for (j=0; j<(length_max-4); j++) putchar(' '); printf("Name Description\n"); while ((i < PLUGIN_LIST_SIZE_MAX) && (plugin_list[i] != NULL)) { for (j=0; j<(length_max-strlen(plugin_list[i]->name)); j++) putchar(' '); printf("%s", plugin_list[i]->name); printf(" %s\n", plugin_list[i]->description); i++; } } void screenshot_register_plugins(void) { // Register screenshot plugins screenshot_plugin_register(&keysight_iv2000x); screenshot_plugin_register(&rigol_1000z); screenshot_plugin_register(&rigol_2000); screenshot_plugin_register(&rigol_dg4000); screenshot_plugin_register(&rigol_dm3068); screenshot_plugin_register(&rigol_dp800); screenshot_plugin_register(&rigol_dsa); screenshot_plugin_register(&rs_hmo1000); screenshot_plugin_register(&siglent_sdm3000); screenshot_plugin_register(&siglent_sdg); screenshot_plugin_register(&siglent_sds); screenshot_plugin_register(&siglent_ssa3000x); screenshot_plugin_register(&tektronix_2000); } int screenshot(char *address, char *plugin_name, char *filename, int timeout) { bool no_match = true; char id[ID_LENGTH_MAX]; bool token_found = true; char *token = NULL; int plugin_winner = -1; int match_count = 0; int match_count_max = 0; char *regex_buffer; int i = 0; // Check for required options if (strlen(address) == 0) { error_printf("Missing address\n"); exit(EXIT_FAILURE); } if (strlen(plugin_name) == 0) { // Get instrument ID if (get_device_id(address, id, timeout) != 0) { error_printf("Unable to retrieve instrument ID\n"); exit(EXIT_FAILURE); } // Find relevant screenshot plugin (match instrument ID to plugin) while ((i < PLUGIN_LIST_SIZE_MAX) && (plugin_list[i] != NULL)) { // Skip plugin if it has no .regex entry if (plugin_list[i]->regex == NULL) { i++; continue; } // Walk through space separated regular expressions in regex string regex_buffer = strdup(plugin_list[i]->regex); while (token_found == true) { if (token == NULL) token = strtok(regex_buffer, " "); else token = strtok(NULL, " "); if (token != NULL) { // Match regular expression against ID if (regex_match(id, token)) match_count++; // Successful match } else token_found = false; } free(regex_buffer); // Plugin with most matches wins if (match_count > match_count_max) { plugin_winner = i; match_count_max = match_count; } // Reset match_count = 0; token_found = true; i++; } if (plugin_winner == -1) { error_printf("Could not autodetect which screenshot plugin to use - please specify plugin name manually\n"); exit(EXIT_FAILURE); } if (isatty(fileno(stdout))) printf("Loaded %s screenshot plugin\n", plugin_list[plugin_winner]->name); no_match = false; i = plugin_winner; } else { // Find relevant screenshot plugin (match specified plugin name to plugin) while ((i < PLUGIN_LIST_SIZE_MAX) && (plugin_list[i] != NULL)) { if (strcmp(plugin_list[i]->name, plugin_name) == 0) { no_match = false; break; } i++; } } if (no_match) { error_printf("Unknown plugin name\n"); exit(EXIT_FAILURE); } // Call capture screenshot function return plugin_list[i]->screenshot(address, timeout); } lxi-tools-1.15/src/test/000077500000000000000000000000001321525002000151265ustar00rootroot00000000000000lxi-tools-1.15/src/test/test.scpi000066400000000000000000000003411321525002000167630ustar00rootroot00000000000000*IDN? :autoscale :stop :run :clear :tforce :single :CHANnel1:DISPlay on :CHANnel2:DISPlay on :CHANnel3:DISPlay on :CHANnel4:DISPlay on :CHANnel1:DISPlay off :CHANnel2:DISPlay off :CHANnel3:DISPlay off :CHANnel4:DISPlay off lxi-tools-1.15/src/test/test.sh000077500000000000000000000005761321525002000164540ustar00rootroot00000000000000IP=$1 SCPI="lxi scpi --address $IP" $SCPI "*IDN?" $SCPI ":autoscale" $SCPI ":stop" $SCPI ":run" $SCPI ":clear" $SCPI ":tforce" $SCPI ":single" $SCPI ":CHANnel1:DISPlay on" $SCPI ":CHANnel2:DISPlay on" $SCPI ":CHANnel3:DISPlay on" $SCPI ":CHANnel4:DISPlay on" $SCPI ":CHANnel1:DISPlay off" $SCPI ":CHANnel2:DISPlay off" $SCPI ":CHANnel3:DISPlay off" $SCPI ":CHANnel4:DISPlay off"