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) if (i != 3)
break; break;
if (n[0] != 0 || n[1] > 2) scpi->firmware_version = n[0] * 100 + n[1] * 10 + n[2];
break; if (scpi->firmware_version < 24) {
if (n[1] == 2 && n[2] > 3) sr_dbg("Found DS1000 firmware < 0.2.4, using raw data format.");
break; devc->format = FORMAT_RAW;
sr_dbg("Found DS1000 firmware < 0.2.4, using raw data format."); }
devc->format = FORMAT_RAW; break;
} while (0); } while (0);
g_strfreev(version); g_strfreev(version);
} }

View File

@ -89,6 +89,8 @@ struct sr_scpi_dev_inst {
void (*free)(void *priv); void (*free)(void *priv);
unsigned int read_timeout_ms; unsigned int read_timeout_ms;
void *priv; 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, 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_length;
int response_bytes_read; int response_bytes_read;
int remaining_length; int remaining_length;
int rigol_ds1000;
}; };
/* Some USBTMC-specific enums, as defined in the USBTMC standard. */ /* 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; found = 1;
uscpi->rigol_ds1000 = des.idVendor == 0x1ab1 &&
des.idProduct == 0x0588;
} }
libusb_free_config_descriptor(confdes); libusb_free_config_descriptor(confdes);
if (found) if (found)
@ -380,24 +377,6 @@ static int scpi_usbtmc_libusb_open(struct sr_scpi_dev_inst *scpi)
return SR_ERR; 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. */ /* Get capabilities. */
ret = libusb_control_transfer(usb->devhdl, ret = libusb_control_transfer(usb->devhdl,
LIBUSB_ENDPOINT_IN | 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 scpi_usbtmc_libusb *uscpi = scpi->priv;
struct sr_usb_dev_inst *usb = uscpi->usb; struct sr_usb_dev_inst *usb = uscpi->usb;
struct libusb_device *dev;
struct libusb_device_descriptor des;
int ret; int ret;
if (!usb->devhdl) if (!usb->devhdl)
return SR_ERR; return SR_ERR;
if (!uscpi->rigol_ds1000) { dev = libusb_get_device(usb->devhdl);
if ((ret = libusb_clear_halt(usb->devhdl, uscpi->bulk_in_ep)) < 0) libusb_get_device_descriptor(dev, &des);
sr_err("Failed to clear halt/stall condition for EP %d: %s.", if (des.idVendor == 0x1ab1 && des.idProduct == 0x0588
uscpi->bulk_in_ep, libusb_error_name(ret)); && scpi->firmware_version >= 24) {
if ((ret = libusb_clear_halt(usb->devhdl, uscpi->bulk_out_ep)) < 0) /* Rigol DS1000 with firmware > 0.2.4 needs this. */
sr_err("Failed to clear halt/stall condition for EP %d: %s.", if ((ret = libusb_clear_halt(usb->devhdl, uscpi->bulk_in_ep)) < 0)
uscpi->bulk_out_ep, libusb_error_name(ret)); sr_err("Failed to clear halt/stall condition for EP %d: %s.",
if ((ret = libusb_clear_halt(usb->devhdl, uscpi->interrupt_ep)) < 0) uscpi->bulk_out_ep, libusb_error_name(ret));
sr_err("Failed to clear halt/stall condition for EP %d: %s.", if ((ret = libusb_clear_halt(usb->devhdl, uscpi->bulk_out_ep)) < 0)
uscpi->interrupt_ep, libusb_error_name(ret)); sr_err("Failed to clear halt/stall condition for EP %d: %s.",
uscpi->bulk_out_ep, libusb_error_name(ret));
} }
scpi_usbtmc_local(uscpi); scpi_usbtmc_local(uscpi);