rdtech-dps: Use big endian register access for DPS devices master
authorVolodymyr Ananiev <vovan888@gmail.com>
Sat, 8 Jan 2022 16:43:27 +0000 (18:43 +0200)
committerGerhard Sittig <gerhard.sittig@gmx.net>
Sat, 8 Jan 2022 17:21:27 +0000 (18:21 +0100)
Adresses an issue which was introduced in commit d7a4dad881bf.

Fixes bug #1760

Signed-off-by: Volodymyr Ananiev <vovan888@gmail.com>
25 files changed:
Makefile.am
README
README.devices
configure.ac
src/backend.c
src/binary_helpers.c
src/hardware/asix-sigma/protocol.c
src/hardware/chronovu-la/api.c
src/hardware/chronovu-la/protocol.c
src/hardware/ftdi-la/api.c
src/hardware/ikalogic-scanaplus/api.c
src/hardware/kingst-la2016/api.c
src/hardware/pipistrello-ols/protocol.c
src/hardware/rdtech-dps/protocol.c
src/hardware/rdtech-tc/protocol.c
src/hardware/rdtech-um/protocol.c
src/hardware/rigol-ds/api.c
src/hardware/uni-t-ut181a/api.c
src/input/feed_queue.c
src/input/input.c
src/input/stf.c
src/input/vcd.c
src/libsigrok-internal.h
src/serial.c
src/session.c

index 94cbbe02bebbbd874b3a59e9b5514f98355be2b7..280cf64d29d915199a0b3092f9ffd5a96d5d3f7b 100644 (file)
@@ -85,11 +85,14 @@ libsigrok_la_SOURCES += \
        src/input/logicport.c \
        src/input/raw_analog.c \
        src/input/saleae.c \
-       src/input/stf.c \
        src/input/trace32_ad.c \
        src/input/vcd.c \
        src/input/wav.c \
        src/input/null.c
+if HAVE_INPUT_STF
+libsigrok_la_SOURCES += \
+       src/input/stf.c
+endif
 
 # Output modules
 libsigrok_la_SOURCES += \
@@ -143,6 +146,9 @@ libsigrok_la_SOURCES += \
        src/serial_hid_victor.c \
        src/serial_libsp.c \
        src/scpi/scpi_serial.c
+else
+libsigrok_la_SOURCES += \
+       src/serial.c
 endif
 if NEED_USB
 libsigrok_la_SOURCES += \
diff --git a/README b/README
index d1f965667bc828ffd60d64fbbb0d07129d0fa49f..768c8ca2b6612d1850d69f8f25e95c830850aef7 100644 (file)
--- a/README
+++ b/README
@@ -37,6 +37,7 @@ Requirements for the C library:
  - libtool (only needed when building from git)
  - pkg-config >= 0.22
  - libglib >= 2.32.0
+ - zlib (optional, used for CRC32 calculation in STF input)
  - libzip >= 0.10
  - libtirpc (optional, used by VXI, fallback when glibc >= 2.26)
  - libserialport >= 0.1.1 (optional, used by some drivers)
index 6d139aa9af0b88b31f7e8f028ed6a12f054abe84..226ec06ba59691b2c37a3548987d963d79ae3080 100644 (file)
@@ -500,7 +500,7 @@ a protocol description and use of the protocol depends on the firmware's
 availability at the user's site. Which then would allow to capture to
 DRAM at high rates without the communication bottleneck, before the data
 gets communicated to the PC after the acquisition has completed. Compare
-the native sigrok supoprt for Asix Sigma.
+the native sigrok support for Asix Sigma.
 
 
 ChronoVu LA8/LA16 USB VID/PIDs
index 982f54300b40625041db9504f43dd97e3d27e6bd..424b00022729e4ba70671bfdc17518c3b8646ed0 100644 (file)
@@ -96,6 +96,18 @@ SR_PKGLIBS_RUBY=
 SR_EXTRA_LIBS=
 SR_EXTRA_CXX_LIBS=
 
+SR_ARG_OPT_PKG([zlib], [ZLIB], , [zlib])
+AM_CONDITIONAL([HAVE_ZLIB], [test "x$sr_have_zlib" = xyes])
+AM_COND_IF([HAVE_ZLIB], [
+       SR_APPEND([sr_deps_avail], [crc32 zlib])
+       SR_PREPEND([SR_EXTRA_LIBS], [-lz])
+])
+
+AM_CONDITIONAL([HAVE_INPUT_STF], [test "x$sr_have_zlib" = xyes])
+AM_COND_IF([HAVE_INPUT_STF], [
+       AC_DEFINE([HAVE_INPUT_STF], [1], [Is the STF input module supported?])
+])
+
 SR_ARG_OPT_PKG([libserialport], [LIBSERIALPORT], ,
        [libserialport >= 0.1.1])
 
@@ -301,7 +313,7 @@ SR_DRIVER([fx2lafw], [fx2lafw], [libusb])
 SR_DRIVER([GMC MH 1x/2x], [gmc-mh-1x-2x], [serial_comm])
 SR_DRIVER([GW Instek GDS-800], [gwinstek-gds-800], [serial_comm])
 SR_DRIVER([GW Instek GPD], [gwinstek-gpd], [serial_comm])
-SR_DRIVER([Hameg HMO], [hameg-hmo], [serial_comm])
+SR_DRIVER([Hameg HMO], [hameg-hmo])
 SR_DRIVER([Hantek 4032L], [hantek-4032l], [libusb])
 SR_DRIVER([Hantek 6xxx], [hantek-6xxx], [libusb])
 SR_DRIVER([Hantek DSO], [hantek-dso], [libusb])
@@ -604,6 +616,7 @@ AM_COND_IF([BINDINGS_CXX], [
 ])
 
 # Check for specific libusb features, now that we know the CFLAGS.
+# Also check for version dependent libftdi features.
 AC_LANG([C])
 sr_save_cflags=$CFLAGS
 sr_save_libs=$LIBS
@@ -613,6 +626,7 @@ AC_CHECK_TYPES([libusb_os_handle],
        [sr_have_libusb_os_handle=yes], [sr_have_libusb_os_handle=no],
        [[#include <libusb.h>]])
 AC_CHECK_FUNCS([zip_discard])
+AC_CHECK_FUNCS([ftdi_tciflush ftdi_tcoflush ftdi_tcioflush])
 LIBS=$sr_save_libs
 CFLAGS=$sr_save_cflags
 
@@ -621,9 +635,12 @@ AM_COND_IF([NEED_USB], [AS_CASE([$sr_have_libusb_os_handle:$host_os], [no:mingw*
 
 sr_glib_version=`$PKG_CONFIG --modversion glib-2.0 2>&AS_MESSAGE_LOG_FD`
 sr_libzip_version=`$PKG_CONFIG --modversion libzip 2>&AS_MESSAGE_LOG_FD`
+sr_zlib_version=`$PKG_CONFIG --modversion zlib 2>&AS_MESSAGE_LOG_FD`
 
 AC_DEFINE_UNQUOTED([CONF_LIBZIP_VERSION], ["$sr_libzip_version"],
        [Build-time version of libzip.])
+AC_DEFINE_UNQUOTED([CONF_ZLIB_VERSION], ["$sr_zlib_version"],
+       [Build-time version of zlib.])
 AC_DEFINE_UNQUOTED([CONF_HOST], ["$host"],
        [The canonical host libsigrok will run on.])
 
index 79340822fb38f8e9cc817297e7b5db6f948fa282..82ad42f7ee6b7b2e442a78a7af93c06433dd4c3f 100644 (file)
@@ -137,6 +137,10 @@ SR_API GSList *sr_buildinfo_libs_get(void)
                glib_binary_age, glib_interface_age));
        l = g_slist_append(l, m);
 
+       m = g_slist_append(NULL, g_strdup("zlib"));
+       m = g_slist_append(m, g_strdup_printf("%s", CONF_ZLIB_VERSION));
+       l = g_slist_append(l, m);
+
        m = g_slist_append(NULL, g_strdup("libzip"));
        m = g_slist_append(m, g_strdup_printf("%s", CONF_LIBZIP_VERSION));
        l = g_slist_append(l, m);
index 9108f5bb7678983e04aad9c753696db4fbbbee0d..86c4c5838fce2bf470524bd3c2a0b8859a741514 100644 (file)
@@ -37,17 +37,17 @@ SR_PRIV int bv_get_value(float *out, const struct binary_value_spec *spec, const
                break
 
        switch (spec->type) {
-               VALUE_TYPE(BVT_UINT8, R8, 1);
+               VALUE_TYPE(BVT_UINT8, R8, sizeof(uint8_t));
 
-               VALUE_TYPE(BVT_BE_UINT16, RB16, 2);
-               VALUE_TYPE(BVT_BE_UINT32, RB32, 4);
-               VALUE_TYPE(BVT_BE_UINT64, RB64, 8);
-               VALUE_TYPE(BVT_BE_FLOAT, RBFL, 4);
+               VALUE_TYPE(BVT_BE_UINT16, RB16, sizeof(uint16_t));
+               VALUE_TYPE(BVT_BE_UINT32, RB32, sizeof(uint32_t));
+               VALUE_TYPE(BVT_BE_UINT64, RB64, sizeof(uint64_t));
+               VALUE_TYPE(BVT_BE_FLOAT, RBFL, sizeof(float));
 
-               VALUE_TYPE(BVT_LE_UINT16, RL16, 2);
-               VALUE_TYPE(BVT_LE_UINT32, RL32, 4);
-               VALUE_TYPE(BVT_LE_UINT64, RL64, 8);
-               VALUE_TYPE(BVT_LE_FLOAT, RLFL, 4);
+               VALUE_TYPE(BVT_LE_UINT16, RL16, sizeof(uint16_t));
+               VALUE_TYPE(BVT_LE_UINT32, RL32, sizeof(uint32_t));
+               VALUE_TYPE(BVT_LE_UINT64, RL64, sizeof(uint64_t));
+               VALUE_TYPE(BVT_LE_FLOAT, RLFL, sizeof(float));
 
        default:
                return SR_ERR_ARG;
index df59693db0e62841368ed10637db209ac853c02a..142316514c7ceab0ebda7fc8a157fa66cc495302 100644 (file)
@@ -625,7 +625,7 @@ static int sigma_fpga_init_bitbang_once(struct dev_context *devc)
        if (ret != SR_OK)
                return ret;
        g_usleep(10 * 1000);
-       ftdi_usb_purge_buffers(&devc->ftdi.ctx);
+       PURGE_FTDI_BOTH(&devc->ftdi.ctx);
 
        /*
         * Wait until the FPGA asserts INIT_B. Check in a maximum number
@@ -889,7 +889,7 @@ static int upload_firmware(struct sr_context *ctx, struct dev_context *devc,
                        ftdi_get_error_string(&devc->ftdi.ctx));
                return SR_ERR;
        }
-       ftdi_usb_purge_buffers(&devc->ftdi.ctx);
+       PURGE_FTDI_BOTH(&devc->ftdi.ctx);
        while (sigma_read_raw(devc, &pins, sizeof(pins)) > 0)
                ;
 
index 694bd54ac84fb91f0f864cefa67d9d31eb2a641c..d35a4f5377d2b8d8bc943cfbf893b2a043340444 100644 (file)
@@ -243,7 +243,7 @@ static int dev_open(struct sr_dev_inst *sdi)
                goto err_ftdi_free;
        }
 
-       if ((ret = ftdi_usb_purge_buffers(devc->ftdic)) < 0) {
+       if ((ret = PURGE_FTDI_BOTH(devc->ftdic)) < 0) {
                sr_err("Failed to purge FTDI buffers (%d): %s.",
                       ret, ftdi_get_error_string(devc->ftdic));
                goto err_ftdi_free;
index da772f5b1d8f5ffcdb1d3ab46227dad39dc2922d..ae8f427a7e9af002e6069382493be45375e47728 100644 (file)
@@ -202,7 +202,7 @@ static int close_usb_reset_sequencer(struct dev_context *devc)
                sr_dbg("Purging buffers, resetting+closing FTDI device.");
 
                /* Log errors, but ignore them (i.e., don't abort). */
-               if ((ret = ftdi_usb_purge_buffers(devc->ftdic)) < 0)
+               if ((ret = PURGE_FTDI_BOTH(devc->ftdic)) < 0)
                        sr_err("Failed to purge FTDI buffers (%d): %s.",
                               ret, ftdi_get_error_string(devc->ftdic));
                if ((ret = ftdi_usb_reset(devc->ftdic)) < 0)
index 8bb67121cc6c71051b279b200ffc6a6d95e2372d..2e7e59f49324c4b63310e4fb6c03ced6f229ed29 100644 (file)
@@ -325,7 +325,7 @@ static int dev_open(struct sr_dev_inst *sdi)
                goto err_ftdi_free;
        }
 
-       ret = ftdi_usb_purge_buffers(devc->ftdic);
+       ret = PURGE_FTDI_BOTH(devc->ftdic);
        if (ret < 0) {
                sr_err("Failed to purge FTDI RX/TX buffers (%d): %s.",
                       ret, ftdi_get_error_string(devc->ftdic));
index f29e5c39ae327c24b37a4ade4047cecc4410bc98..fb3b137f3fc36f7ad620295494607cd0185aa0e5 100644 (file)
@@ -141,7 +141,7 @@ static int dev_open(struct sr_dev_inst *sdi)
                return SR_ERR;
        }
 
-       if ((ret = ftdi_usb_purge_buffers(devc->ftdic)) < 0) {
+       if ((ret = PURGE_FTDI_BOTH(devc->ftdic)) < 0) {
                sr_err("Failed to purge FTDI RX/TX buffers (%d): %s.",
                       ret, ftdi_get_error_string(devc->ftdic));
                goto err_dev_open_close_ftdic;
index 1b1b425a0204169440429807430067f4ac58064a..216869ed8f222b29bb7599712a24e26ee72b01c4 100644 (file)
@@ -504,13 +504,14 @@ static int config_list(uint32_t key, GVariant **data,
 {
        struct dev_context *devc;
 
-       devc = sdi->priv;
-
        switch (key) {
        case SR_CONF_SCAN_OPTIONS:
        case SR_CONF_DEVICE_OPTIONS:
                return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
        case SR_CONF_SAMPLERATE:
+               if (!sdi)
+                       return SR_ERR_ARG;
+               devc = sdi->priv;
                if (devc->max_samplerate == SR_MHZ(200)) {
                        *data = std_gvar_samplerates(ARRAY_AND_SIZE(samplerates_la2016));
                }
index f0ef680527abc48d925f9dae6b9bbcb1adeb5add..1b54dd164e23075f4fb3c77c53fb3a810d5bf081 100644 (file)
@@ -90,7 +90,7 @@ SR_PRIV int p_ols_open(struct dev_context *devc)
                return SR_ERR;
        }
 
-       if ((ret = ftdi_usb_purge_buffers(devc->ftdic)) < 0) {
+       if ((ret = PURGE_FTDI_BOTH(devc->ftdic)) < 0) {
                sr_err("Failed to purge FTDI RX/TX buffers (%d): %s.",
                       ret, ftdi_get_error_string(devc->ftdic));
                goto err_open_close_ftdic;
index 9ce2eb66e3a855337dc63f0bed452ba165f511f1..83090d86ac7c2253c6662a305b7beab10015df67 100644 (file)
@@ -132,7 +132,7 @@ static int rdtech_dps_set_reg(const struct sr_dev_inst *sdi,
        modbus = sdi->conn;
 
        wrptr = (void *)registers;
-       write_u16le(wrptr, value);
+       write_u16be(wrptr, value);
 
        g_mutex_lock(&devc->rw_mutex);
        ret = sr_modbus_write_multiple_registers(modbus, address,
@@ -187,8 +187,8 @@ SR_PRIV int rdtech_dps_get_model_version(struct sr_modbus_dev_inst *modbus,
                if (ret != SR_OK)
                        return ret;
                rdptr = (void *)registers;
-               *model = read_u16le_inc(&rdptr);
-               *version = read_u16le_inc(&rdptr);
+               *model = read_u16be_inc(&rdptr);
+               *version = read_u16be_inc(&rdptr);
                *serno = 0;
                sr_info("RDTech DPS/DPH model: %u version: %u",
                        *model, *version);
@@ -327,25 +327,25 @@ SR_PRIV int rdtech_dps_get_state(const struct sr_dev_inst *sdi,
 
                /* Interpret the registers' values. */
                rdptr = (const void *)registers;
-               uset_raw = read_u16le_inc(&rdptr);
+               uset_raw = read_u16be_inc(&rdptr);
                volt_target = uset_raw / devc->voltage_multiplier;
-               iset_raw = read_u16le_inc(&rdptr);
+               iset_raw = read_u16be_inc(&rdptr);
                curr_limit = iset_raw / devc->current_multiplier;
-               uout_raw = read_u16le_inc(&rdptr);
+               uout_raw = read_u16be_inc(&rdptr);
                curr_voltage = uout_raw / devc->voltage_multiplier;
-               iout_raw = read_u16le_inc(&rdptr);
+               iout_raw = read_u16be_inc(&rdptr);
                curr_current = iout_raw / devc->current_multiplier;
-               power_raw = read_u16le_inc(&rdptr);
+               power_raw = read_u16be_inc(&rdptr);
                curr_power = power_raw / 100.0f;
-               (void)read_u16le_inc(&rdptr); /* UIN */
-               reg_val = read_u16le_inc(&rdptr); /* LOCK */
+               (void)read_u16be_inc(&rdptr); /* UIN */
+               reg_val = read_u16be_inc(&rdptr); /* LOCK */
                is_lock = reg_val != 0;
-               reg_val = read_u16le_inc(&rdptr); /* PROTECT */
+               reg_val = read_u16be_inc(&rdptr); /* PROTECT */
                uses_ovp = reg_val == STATE_OVP;
                uses_ocp = reg_val == STATE_OCP;
-               reg_state = read_u16le_inc(&rdptr); /* CV_CC */
+               reg_state = read_u16be_inc(&rdptr); /* CV_CC */
                is_reg_cc = reg_state == MODE_CC;
-               out_state = read_u16le_inc(&rdptr); /* ENABLE */
+               out_state = read_u16be_inc(&rdptr); /* ENABLE */
                is_out_enabled = out_state != 0;
 
                /* Transfer another chunk of registers in a single call. */
@@ -358,9 +358,9 @@ SR_PRIV int rdtech_dps_get_state(const struct sr_dev_inst *sdi,
 
                /* Interpret the second registers chunk's values. */
                rdptr = (const void *)registers;
-               ovpset_raw = read_u16le_inc(&rdptr); /* PRE OVPSET */
+               ovpset_raw = read_u16be_inc(&rdptr); /* PRE OVPSET */
                ovp_threshold = ovpset_raw * devc->voltage_multiplier;
-               ocpset_raw = read_u16le_inc(&rdptr); /* PRE OCPSET */
+               ocpset_raw = read_u16be_inc(&rdptr); /* PRE OCPSET */
                ocp_threshold = ocpset_raw * devc->current_multiplier;
 
                break;
index 456681ea49d6e7766db9b972dcd380f70a89a61d..3b94890d43b30f8926b3321d4533a3602c0a3e7e 100644 (file)
@@ -71,7 +71,7 @@ static const struct binary_analog_channel rdtech_tc_channels[] = {
        { "D-", {  64 + 36, BVT_LE_UINT32, 1e-2, }, 2, SR_MQ_VOLTAGE, SR_UNIT_VOLT },
        { "E0", {  64 + 12, BVT_LE_UINT32, 1e-3, }, 3, SR_MQ_ENERGY, SR_UNIT_WATT_HOUR },
        { "E1", {  64 + 20, BVT_LE_UINT32, 1e-3, }, 3, SR_MQ_ENERGY, SR_UNIT_WATT_HOUR },
-       { NULL, },
+       ALL_ZERO,
 };
 
 static int check_pac_crc(uint8_t *data)
index 25bad0dfc95ec7356fb5993aa5beb6301cfb38eb..04de768713ac04d2d6c039454e1b7982610466cb 100644 (file)
@@ -42,7 +42,7 @@ static const struct binary_analog_channel rdtech_default_channels[] = {
        { "T", { 10, BVT_BE_UINT16, 1.0, },  0, SR_MQ_TEMPERATURE, SR_UNIT_CELSIUS },
        /* Threshold-based recording (mWh) */
        { "E", { 106, BVT_BE_UINT32, 0.001, }, 3, SR_MQ_ENERGY, SR_UNIT_WATT_HOUR },
-       { NULL, },
+       ALL_ZERO,
 };
 
 static const struct binary_analog_channel rdtech_um25c_channels[] = {
@@ -53,7 +53,7 @@ static const struct binary_analog_channel rdtech_um25c_channels[] = {
        { "T", { 10, BVT_BE_UINT16, 1.0, }, 0, SR_MQ_TEMPERATURE, SR_UNIT_CELSIUS },
        /* Threshold-based recording (mWh) */
        { "E", { 106, BVT_BE_UINT32, 0.001, }, 3, SR_MQ_ENERGY, SR_UNIT_WATT_HOUR },
-       { NULL, },
+       ALL_ZERO,
 };
 
 static int poll_csum_fff1(char buf[], int len)
index 95de8f6a0d7b30339a7fd6756ba3d4bfe556d0f6..632c95963cb75e517e6d7abe3cbff783e6cbee70 100644 (file)
@@ -883,6 +883,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
        GSList *l;
        char *cmd;
        int protocol;
+       int ret;
 
        scpi = sdi->conn;
        devc = sdi->priv;
@@ -1021,20 +1022,27 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 
        devc->channel_entry = devc->enabled_channels;
 
-       if (devc->data_source == DATA_SOURCE_LIVE)
-               devc->sample_rate = analog_frame_size(sdi) / 
+       if (devc->data_source == DATA_SOURCE_LIVE) {
+               devc->sample_rate = analog_frame_size(sdi) /
                        (devc->timebase * devc->model->series->num_horizontal_divs);
-       else {
+       else {
                float xinc;
-               if (devc->model->series->protocol >= PROTOCOL_V3 && 
-                               sr_scpi_get_float(sdi->conn, "WAV:XINC?", &xinc) != SR_OK) {
-                       sr_err("Couldn't get sampling rate");
+               if (devc->model->series->protocol < PROTOCOL_V3) {
+                       sr_err("Cannot get samplerate (below V3).");
+                       return SR_ERR;
+               }
+               ret = sr_scpi_get_float(sdi->conn, "WAV:XINC?", &xinc);
+               if (ret != SR_OK) {
+                       sr_err("Cannot get samplerate (WAV:XINC? failed).");
+                       return SR_ERR;
+               }
+               if (!xinc) {
+                       sr_err("Cannot get samplerate (zero XINC value).");
                        return SR_ERR;
                }
                devc->sample_rate = 1. / xinc;
        }
 
-
        if (rigol_ds_capture_start(sdi) != SR_OK)
                return SR_ERR;
 
index de64f2f273f1319f6fbeb207ed433014b70e1525..53fdf18cf9d59300e688641325b3a6d1a4116488 100644 (file)
@@ -203,7 +203,6 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
        serial = sr_serial_dev_inst_new(conn, serialcomm);
        ret = serial_open(serial, SERIAL_RDWR);
        snprintf(conn_id, sizeof(conn_id), "%s", serial->port);
-       serial_flush(serial);
        /*
         * We cannot identify the device at this point in time.
         * Successful open shall suffice for now. More activity
@@ -532,6 +531,10 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
                devc->info.rec_data.samples_total = devc->wait_state.data_value;
                devc->info.rec_data.samples_curr = 0;
                ret = ut181a_send_cmd_get_rec_samples(serial, rec_idx, 0);
+       } else {
+               sr_err("Unhandled data source %d, programming error?",
+                       (int)devc->data_source);
+               ret = SR_ERR_BUG;
        }
        if (ret < 0)
                return ret;
index bd5c16c7f621947f55cd43dd8f641acb3874edab..b25fa77affdc8b7f90731dafa62ed5ef6b6ab9ab 100644 (file)
@@ -95,6 +95,21 @@ SR_API int feed_queue_logic_flush(struct feed_queue_logic *q)
        return SR_OK;
 }
 
+SR_API int feed_queue_logic_send_trigger(struct feed_queue_logic *q)
+{
+       int ret;
+
+       ret = feed_queue_logic_flush(q);
+       if (ret != SR_OK)
+               return ret;
+
+       ret = std_session_send_df_trigger(q->sdi);
+       if (ret != SR_OK)
+               return ret;
+
+       return SR_OK;
+}
+
 SR_API void feed_queue_logic_free(struct feed_queue_logic *q)
 {
 
index 8708cc637a886beb5829354d9b69fffdd1356611..b5de532bc58a1c25a4d3430d223a8b5b8ee7299b 100644 (file)
@@ -80,7 +80,9 @@ static const struct sr_input_module *input_module_list[] = {
        &input_binary,
        &input_chronovu_la8,
        &input_csv,
+#if defined HAVE_INPUT_STF && HAVE_INPUT_STF
        &input_stf,
+#endif
        &input_trace32_ad,
        &input_vcd,
        &input_wav,
index cbf93be4aa9f1a612ad997ed85cd32e040a7ffdb..431b0cbc03893ba707cc3469d061d2f14bb72bdf 100644 (file)
@@ -627,10 +627,9 @@ static void add_sample(const struct sr_input *in, uint16_t data, size_t count)
                        unit_buffer, send_first);
                inc->submit.submit_count += send_first;
                inc->submit.samples_to_trigger -= send_first;
-               feed_queue_logic_flush(inc->submit.feed);
                sr_dbg("Trigger: sending DF packet, at %" PRIu64 ".",
                        inc->submit.submit_count);
-               std_session_send_df_trigger(in->sdi);
+               feed_queue_logic_send_trigger(inc->submit.feed);
        }
        if (count) {
                (void)feed_queue_logic_submit(inc->submit.feed,
index 4e0310bac67e4e55f7e56f6a124812d13dbfb3aa..413712301318787f7201f9389de5748418dbfbeb 100644 (file)
@@ -304,7 +304,7 @@ static void ts_stats_check_early(struct ts_stats *stats)
                if (stats->total_ts_seen != cp->count)
                        continue;
                /* First occurance of that timestamp count. Check the value. */
-               sr_dbg("TS early chk: total %" PRIu64 ", min delta %zu / %zu.",
+               sr_dbg("TS early chk: total %zu, min delta %" PRIu64 " / %" PRIu64 ".",
                        cp->count, seen_delta, check_delta);
                if (check_delta < cp->delta)
                        return;
@@ -821,6 +821,7 @@ static int parse_header_var(struct context *inc, char *contents)
        size_t length;
        char *type, *size_txt, *id, *ref, *idx;
        gboolean is_reg, is_wire, is_real, is_int;
+       gboolean is_str;
        enum sr_channeltype ch_type;
        size_t size, next_size;
        struct vcd_channel *vcd_ch;
@@ -849,13 +850,21 @@ static int parse_header_var(struct context *inc, char *contents)
        is_wire = g_strcmp0(type, "wire") == 0;
        is_real = g_strcmp0(type, "real") == 0;
        is_int = g_strcmp0(type, "integer") == 0;
+       is_str = g_strcmp0(type, "string") == 0;
 
        if (is_reg || is_wire) {
                ch_type = SR_CHANNEL_LOGIC;
        } else if (is_real || is_int) {
                ch_type = SR_CHANNEL_ANALOG;
+       } else if (is_str) {
+               sr_warn("Skipping id %s, name '%s%s', unsupported type '%s'.",
+                       id, ref, idx ? idx : "", type);
+               inc->ignored_signals = g_slist_append(inc->ignored_signals,
+                       g_strdup(id));
+               g_strfreev(parts);
+               return SR_OK;
        } else {
-               sr_info("Unsupported signal type: '%s'", type);
+               sr_err("Unsupported signal type: '%s'", type);
                g_strfreev(parts);
                return SR_ERR_DATA;
        }
@@ -1510,6 +1519,95 @@ static uint8_t vcd_char_to_value(char bit_char, int *warn)
        return ~0;
 }
 
+/*
+ * Check the validity of a VCD string value. It's essential to reliably
+ * accept valid data which the community uses in the field, yet robustly
+ * reject invalid data for users' awareness. Since IEEE 1800-2017 would
+ * not discuss the representation of this data type, it's assumed to not
+ * be an official feature of the VCD file format. This implementation is
+ * an educated guess after inspection of other arbitrary implementations,
+ * not backed by any specification or public documentation.
+ *
+ * A quick summary of the implemented assumptions: Must be a sequence of
+ * ASCII printables. Must not contain whitespace. Might contain escape
+ * sequences: A backslash followed by a single character, like '\n' or
+ * '\\'. Or a backslash and the letter x followed by two hex digits,
+ * like '\x20'. Or a backslash followed by three octal digits, like
+ * '\007'. As an exception also accepts a single digit '\0' but only at
+ * the text end. The string value may be empty, but must not be NULL.
+ *
+ * This implementation assumes an ASCII based platform for simplicity
+ * and readability. Should be a given on sigrok supported platforms.
+ */
+static gboolean vcd_string_valid(const char *s)
+{
+       char c;
+
+       if (!s)
+               return FALSE;
+
+       while (*s) {
+               c = *s++;
+               /* Reject non-printable ASCII chars including DEL. */
+               if (c < ' ')
+                       return FALSE;
+               if (c > '~')
+                       return FALSE;
+               /* Deeper inspection of escape sequences. */
+               if (c == '\\') {
+                       c = *s++;
+                       switch (c) {
+                       case 'a': /* BEL, bell aka "alarm" */
+                       case 'b': /* BS, back space */
+                       case 't': /* TAB, tabulator */
+                       case 'n': /* NL, newline */
+                       case 'v': /* VT, vertical tabulator */
+                       case 'f': /* FF, form feed */
+                       case 'r': /* CR, carriage return */
+                       case '"': /* double quotes */
+                       case '\'': /* tick, single quote */
+                       case '?': /* question mark */
+                       case '\\': /* backslash */
+                               continue;
+                       case 'x': /* \xNN two hex digits */
+                               c = *s++;
+                               if (!g_ascii_isxdigit(c))
+                                       return FALSE;
+                               c = *s++;
+                               if (!g_ascii_isxdigit(c))
+                                       return FALSE;
+                               continue;
+                       case '0': /* \NNN three octal digits */
+                       case '1':
+                       case '2':
+                       case '3':
+                       case '4':
+                       case '5':
+                       case '6':
+                       case '7':
+                               /* Special case '\0' at end of text. */
+                               if (c == '0' && !*s)
+                                       return TRUE;
+                               /*
+                                * First digit was covered by the outer
+                                * switch(). Two more digits to check.
+                                */
+                               c = *s++;
+                               if (!g_ascii_isdigit(c) || c > '7')
+                                       return FALSE;
+                               c = *s++;
+                               if (!g_ascii_isdigit(c) || c > '7')
+                                       return FALSE;
+                               continue;
+                       default:
+                               return FALSE;
+                       }
+               }
+       }
+
+       return TRUE;
+}
+
 /* Parse one text line of the data section. */
 static int parse_textline(const struct sr_input *in, char *lines)
 {
@@ -1518,7 +1616,8 @@ static int parse_textline(const struct sr_input *in, char *lines)
        char **words;
        size_t word_count, word_idx;
        char *curr_word, *next_word, curr_first;
-       gboolean is_timestamp, is_section, is_real, is_multibit, is_singlebit;
+       gboolean is_timestamp, is_section;
+       gboolean is_real, is_multibit, is_singlebit, is_string;
        uint64_t timestamp;
        char *identifier, *endptr;
        size_t count;
@@ -1697,6 +1796,7 @@ static int parse_textline(const struct sr_input *in, char *lines)
                 * timestamp.
                 *
                 * Supported input data formats are:
+                * - S<value> <sep> <id> (value not used, VCD type 'string').
                 * - R<value> <sep> <id> (analog channel, VCD type 'real').
                 * - B<value> <sep> <id> (analog channel, VCD type 'integer').
                 * - B<value> <sep> <id> (logic channels, VCD bit vectors).
@@ -1725,6 +1825,7 @@ static int parse_textline(const struct sr_input *in, char *lines)
                is_singlebit |= curr_first == 'l' || curr_first == 'h';
                is_singlebit |= curr_first == 'x' || curr_first == 'z';
                is_singlebit |= curr_first == 'u' || curr_first == '-';
+               is_string = curr_first == 's';
                if (is_real) {
                        char *real_text;
                        float real_val;
@@ -1872,6 +1973,32 @@ static int parse_textline(const struct sr_input *in, char *lines)
                        process_bits(inc, identifier, inc->conv_bits.value, 1);
                        continue;
                }
+               if (is_string) {
+                       const char *str_value;
+
+                       str_value = &curr_word[1];
+                       identifier = next_word;
+                       word_idx++;
+                       if (!vcd_string_valid(str_value)) {
+                               sr_err("Invalid string data: %s", str_value);
+                               ret = SR_ERR_DATA;
+                               break;
+                       }
+                       if (!identifier || !*identifier) {
+                               sr_err("String value without identifier.");
+                               ret = SR_ERR_DATA;
+                               break;
+                       }
+                       sr_spew("Got string data, id '%s', value \"%s\".",
+                               identifier, str_value);
+                       if (!is_ignored(inc, identifier)) {
+                               sr_err("String value for identifier '%s'.",
+                                       identifier);
+                               ret = SR_ERR_DATA;
+                               break;
+                       }
+                       continue;
+               }
 
                /* Design choice: Consider unsupported input fatal. */
                sr_err("Unknown token '%s'.", curr_word);
index 7a5b717d6d4c7482534a185fbb30ab67e48e2cb4..a2350e02ddf3aed2c48c89bcab2ac8eb8f59dfae 100644 (file)
@@ -32,6 +32,9 @@
 #ifdef HAVE_LIBUSB_1_0
 #include <libusb.h>
 #endif
+#ifdef HAVE_LIBFTDI
+#include <ftdi.h>
+#endif
 #include <stdarg.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -981,6 +984,21 @@ static inline void write_dblle_inc(uint8_t **p, double x)
        libusb_handle_events_timeout(ctx, tv)
 #endif
 
+/*
+ * Convenience for FTDI library version dependency.
+ * - Version 1.5 introduced ftdi_tciflush(), ftdi_tcoflush(), and
+ *   ftdi_tcioflush() all within the same commit, and deprecated
+ *   ftdi_usb_purge_buffers() which suffered from inverse semantics.
+ *   The API is drop-in compatible (arguments count and data types are
+ *   identical). The libsigrok source code always flushes RX and TX at
+ *   the same time, never individually.
+ */
+#if defined HAVE_FTDI_TCIOFLUSH && HAVE_FTDI_TCIOFLUSH
+#  define PURGE_FTDI_BOTH ftdi_tcioflush
+#else
+#  define PURGE_FTDI_BOTH ftdi_usb_purge_buffers
+#endif
+
 /* Static definitions of structs ending with an all-zero entry are a
  * problem when compiling with -Wmissing-field-initializers: GCC
  * suppresses the warning only with { 0 }, clang wants { } */
@@ -1916,8 +1934,6 @@ SR_PRIV int serial_stream_detect(struct sr_serial_dev_inst *serial,
                size_t packet_size, packet_valid_callback is_valid,
                packet_valid_len_callback is_valid_len, size_t *return_size,
                uint64_t timeout_ms);
-SR_PRIV int sr_serial_extract_options(GSList *options, const char **serial_device,
-                                     const char **serial_options);
 SR_PRIV int serial_source_add(struct sr_session *session,
                struct sr_serial_dev_inst *serial, int events, int timeout,
                sr_receive_data_callback cb, void *cb_data);
@@ -1996,6 +2012,9 @@ SR_PRIV const char *ser_hid_chip_find_name_vid_pid(uint16_t vid, uint16_t pid);
 #endif
 #endif
 
+SR_PRIV int sr_serial_extract_options(GSList *options,
+       const char **serial_device, const char **serial_options);
+
 /*--- bt/ API ---------------------------------------------------------------*/
 
 #ifdef HAVE_BLUETOOTH
@@ -2063,7 +2082,9 @@ SR_PRIV gboolean usb_match_manuf_prod(libusb_device *dev,
 
 /** Binary value type */
 enum binary_value_type {
-       BVT_UINT8 = 0,
+       BVT_INVALID,
+
+       BVT_UINT8,
        BVT_BE_UINT8 = BVT_UINT8,
        BVT_LE_UINT8 = BVT_UINT8,
 
@@ -2691,6 +2712,7 @@ SR_API struct feed_queue_logic *feed_queue_logic_alloc(
 SR_API int feed_queue_logic_submit(struct feed_queue_logic *q,
        const uint8_t *data, size_t count);
 SR_API int feed_queue_logic_flush(struct feed_queue_logic *q);
+SR_API int feed_queue_logic_send_trigger(struct feed_queue_logic *q);
 SR_API void feed_queue_logic_free(struct feed_queue_logic *q);
 
 SR_API struct feed_queue_analog *feed_queue_analog_alloc(
index 97bd3159b094f673e0db8070d87eadb960e1cab8..353b7ae14899f12d49cac0a3761469488faa971d 100644 (file)
@@ -925,6 +925,8 @@ SR_PRIV int serial_stream_detect(struct sr_serial_dev_inst *serial,
        return SR_ERR;
 }
 
+#endif
+
 /**
  * Extract the serial device and options from the options linked list.
  *
@@ -977,6 +979,8 @@ SR_PRIV int sr_serial_extract_options(GSList *options,
        return SR_OK;
 }
 
+#ifdef HAVE_SERIAL_COMM
+
 /** @private */
 SR_PRIV int serial_source_add(struct sr_session *session,
        struct sr_serial_dev_inst *serial, int events, int timeout,
index d1a19c56e9967a7187d3dc8fdfca01da25848ab1..8d3f66966a4f156c632d185d4f788274b15e58be 100644 (file)
@@ -1482,9 +1482,16 @@ SR_PRIV int sr_session_source_destroyed(struct sr_session *session,
 
 static void copy_src(struct sr_config *src, struct sr_datafeed_meta *meta_copy)
 {
+       struct sr_config *item;
+
+#if GLIB_CHECK_VERSION(2, 67, 3)
+       item = g_memdup2(src, sizeof(*src));
+#else
+       item = g_memdup(src, sizeof(*src));
+#endif
+
        g_variant_ref(src->data);
-       meta_copy->config = g_slist_append(meta_copy->config,
-                                          g_memdup(src, sizeof(struct sr_config)));
+       meta_copy->config = g_slist_append(meta_copy->config, item);
 }
 
 SR_API int sr_packet_copy(const struct sr_datafeed_packet *packet,
@@ -1496,6 +1503,9 @@ SR_API int sr_packet_copy(const struct sr_datafeed_packet *packet,
        struct sr_datafeed_logic *logic_copy;
        const struct sr_datafeed_analog *analog;
        struct sr_datafeed_analog *analog_copy;
+       struct sr_analog_encoding *encoding_copy;
+       struct sr_analog_meaning *meaning_copy;
+       struct sr_analog_spec *spec_copy;
        uint8_t *payload;
 
        *copy = g_malloc0(sizeof(struct sr_datafeed_packet));
@@ -1540,14 +1550,20 @@ SR_API int sr_packet_copy(const struct sr_datafeed_packet *packet,
                memcpy(analog_copy->data, analog->data,
                                analog->encoding->unitsize * analog->num_samples);
                analog_copy->num_samples = analog->num_samples;
-               analog_copy->encoding = g_memdup(analog->encoding,
-                               sizeof(struct sr_analog_encoding));
-               analog_copy->meaning = g_memdup(analog->meaning,
-                               sizeof(struct sr_analog_meaning));
+#if GLIB_CHECK_VERSION(2, 67, 3)
+               encoding_copy = g_memdup2(analog->encoding, sizeof(*analog->encoding));
+               meaning_copy = g_memdup2(analog->meaning, sizeof(*analog->meaning));
+               spec_copy = g_memdup2(analog->spec, sizeof(*analog->spec));
+#else
+               encoding_copy = g_memdup(analog->encoding, sizeof(*analog->encoding));
+               meaning_copy = g_memdup(analog->meaning, sizeof(*analog->meaning));
+               spec_copy = g_memdup(analog->spec, sizeof(*analog->spec));
+#endif
+               analog_copy->encoding = encoding_copy;
+               analog_copy->meaning = meaning_copy;
                analog_copy->meaning->channels = g_slist_copy(
                                analog->meaning->channels);
-               analog_copy->spec = g_memdup(analog->spec,
-                               sizeof(struct sr_analog_spec));
+               analog_copy->spec = spec_copy;
                (*copy)->payload = analog_copy;
                break;
        default: