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:
parent
04229f7bfc
commit
de285cce11
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue