]> sigrok.org Git - libsigrok.git/commitdiff
scpi/usbtmc: Implement Rigol DS1000 workaround on any firmware version.
authorBert Vermeulen <redacted>
Mon, 21 Sep 2015 11:45:36 +0000 (13:45 +0200)
committerUwe Hermann <redacted>
Tue, 22 Sep 2015 08:56:58 +0000 (10:56 +0200)
Firmware versions starting with 00.02.04 apparently cause the in and out
bulk endpoints to end up in a HALT state. This is likely related to the
larger transfer size quirk implemented in the Linux kernel for the Rigol
DS1000: this USBTMC implementation does not have that workaround.

Instead, if the firmware version is >= 00.02.04, both endpoints have the HALT
condition cleared on device close.

This fixes bug #354.

src/hardware/rigol-ds/api.c
src/scpi.h
src/scpi/scpi_usbtmc_libusb.c

index ba4b0206ca861113796a5c43d107d77fae99df78..762154a75592d50fbb8ed336af3b1856c9427e91 100644 (file)
@@ -340,12 +340,12 @@ static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi)
                        }
                        if (i != 3)
                                break;
-                       if (n[0] != 0 || n[1] > 2)
-                               break;
-                       if (n[1] == 2 && n[2] > 3)
-                               break;
-                       sr_dbg("Found DS1000 firmware < 0.2.4, using raw data format.");
-                       devc->format = FORMAT_RAW;
+                       scpi->firmware_version = n[0] * 100 + n[1] * 10 + n[2];
+                       if (scpi->firmware_version < 24) {
+                               sr_dbg("Found DS1000 firmware < 0.2.4, using raw data format.");
+                               devc->format = FORMAT_RAW;
+                       }
+                       break;
                } while (0);
                g_strfreev(version);
        }
index aee1bfba836809c711c93849c529b24893267719..c70bd930fd5b2e42d284be08973516790b68ad2c 100644 (file)
@@ -89,6 +89,8 @@ struct sr_scpi_dev_inst {
        void (*free)(void *priv);
        unsigned int read_timeout_ms;
        void *priv;
+       /* Only used for quirk workarounds, notably the Rigol DS1000 series. */
+       uint64_t firmware_version;
 };
 
 SR_PRIV GSList *sr_scpi_scan(struct drv_context *drvc, GSList *options,
index 61d1b70d02f0b7a6935da871fef51e02d3c9e21d..9042ef4fd22925c30813900da774d14f4a33234e 100644 (file)
@@ -45,7 +45,6 @@ struct scpi_usbtmc_libusb {
        int response_length;
        int response_bytes_read;
        int remaining_length;
-       int rigol_ds1000;
 };
 
 /* Some USBTMC-specific enums, as defined in the USBTMC standard. */
@@ -345,8 +344,6 @@ static int scpi_usbtmc_libusb_open(struct sr_scpi_dev_inst *scpi)
                                }
                        }
                        found = 1;
-                       uscpi->rigol_ds1000 = des.idVendor  == 0x1ab1 &&
-                                             des.idProduct == 0x0588;
                }
                libusb_free_config_descriptor(confdes);
                if (found)
@@ -380,24 +377,6 @@ static int scpi_usbtmc_libusb_open(struct sr_scpi_dev_inst *scpi)
                return SR_ERR;
        }
 
-       if (!uscpi->rigol_ds1000) {
-       if ((ret = libusb_clear_halt(usb->devhdl, uscpi->bulk_in_ep)) < 0) {
-               sr_err("Failed to clear halt/stall condition for EP %d: %s.",
-                      uscpi->bulk_in_ep, libusb_error_name(ret));
-               return SR_ERR;
-       }
-       if ((ret = libusb_clear_halt(usb->devhdl, uscpi->bulk_out_ep)) < 0) {
-               sr_err("Failed to clear halt/stall condition for EP %d: %s.",
-                      uscpi->bulk_out_ep, libusb_error_name(ret));
-               return SR_ERR;
-       }
-       if ((ret = libusb_clear_halt(usb->devhdl, uscpi->interrupt_ep)) < 0) {
-               sr_err("Failed to clear halt/stall condition for EP %d: %s.",
-                      uscpi->interrupt_ep, libusb_error_name(ret));
-               return SR_ERR;
-       }
-       }
-
        /* Get capabilities. */
        ret = libusb_control_transfer(usb->devhdl,
                                      LIBUSB_ENDPOINT_IN         |
@@ -638,21 +617,24 @@ static int scpi_usbtmc_libusb_close(struct sr_scpi_dev_inst *scpi)
 {
        struct scpi_usbtmc_libusb *uscpi = scpi->priv;
        struct sr_usb_dev_inst *usb = uscpi->usb;
+       struct libusb_device *dev;
+       struct libusb_device_descriptor des;
        int ret;
 
        if (!usb->devhdl)
                return SR_ERR;
 
-       if (!uscpi->rigol_ds1000) {
-       if ((ret = libusb_clear_halt(usb->devhdl, uscpi->bulk_in_ep)) < 0)
-               sr_err("Failed to clear halt/stall condition for EP %d: %s.",
-                      uscpi->bulk_in_ep, libusb_error_name(ret));
-       if ((ret = libusb_clear_halt(usb->devhdl, uscpi->bulk_out_ep)) < 0)
-               sr_err("Failed to clear halt/stall condition for EP %d: %s.",
-                      uscpi->bulk_out_ep, libusb_error_name(ret));
-       if ((ret = libusb_clear_halt(usb->devhdl, uscpi->interrupt_ep)) < 0)
-               sr_err("Failed to clear halt/stall condition for EP %d: %s.",
-                      uscpi->interrupt_ep, libusb_error_name(ret));
+       dev = libusb_get_device(usb->devhdl);
+       libusb_get_device_descriptor(dev, &des);
+       if (des.idVendor == 0x1ab1 && des.idProduct == 0x0588
+                       && scpi->firmware_version >= 24) {
+               /* Rigol DS1000 with firmware > 0.2.4 needs this. */
+               if ((ret = libusb_clear_halt(usb->devhdl, uscpi->bulk_in_ep)) < 0)
+                       sr_err("Failed to clear halt/stall condition for EP %d: %s.",
+                              uscpi->bulk_out_ep, libusb_error_name(ret));
+               if ((ret = libusb_clear_halt(usb->devhdl, uscpi->bulk_out_ep)) < 0)
+                       sr_err("Failed to clear halt/stall condition for EP %d: %s.",
+                              uscpi->bulk_out_ep, libusb_error_name(ret));
        }
 
        scpi_usbtmc_local(uscpi);