scpi/usbtmc: Implement Rigol DS1000 workaround on any firmware version.

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.
This commit is contained in:
Bert Vermeulen 2015-09-21 13:45:36 +02:00 committed by Uwe Hermann
parent 04229f7bfc
commit de285cce11
3 changed files with 21 additions and 37 deletions

View 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);
}

View 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,

View 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);