scpi/usbtmc: Implement blacklist for RL1 feature.
This is initially for the Rigol DS1000 series which pretends to support RL1, but doesn't.
This commit is contained in:
parent
b07a1b04e5
commit
115826529c
|
@ -97,6 +97,17 @@ enum {
|
||||||
#define EOM 0x01
|
#define EOM 0x01
|
||||||
#define TERM_CHAR_ENABLED 0x02
|
#define TERM_CHAR_ENABLED 0x02
|
||||||
|
|
||||||
|
struct usbtmc_blacklist {
|
||||||
|
uint16_t vid;
|
||||||
|
uint16_t pid;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct usbtmc_blacklist blacklist_remote[] = {
|
||||||
|
/* Rigol DS1000 series publishes RL1 support, but doesn't support it. */
|
||||||
|
{ 0x1ab1, 0x0588 },
|
||||||
|
ALL_ZERO
|
||||||
|
};
|
||||||
|
|
||||||
static GSList *scpi_usbtmc_libusb_scan(struct drv_context *drvc)
|
static GSList *scpi_usbtmc_libusb_scan(struct drv_context *drvc)
|
||||||
{
|
{
|
||||||
struct libusb_device **devlist;
|
struct libusb_device **devlist;
|
||||||
|
@ -174,6 +185,110 @@ static int scpi_usbtmc_libusb_dev_inst_new(void *priv, struct drv_context *drvc,
|
||||||
return SR_OK;
|
return SR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int check_usbtmc_blacklist(struct usbtmc_blacklist *blacklist,
|
||||||
|
uint16_t vid, uint16_t pid)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; blacklist[i].vid; i++) {
|
||||||
|
if (blacklist[i].vid == vid && blacklist[i].pid == pid)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int scpi_usbtmc_remote(struct scpi_usbtmc_libusb *uscpi)
|
||||||
|
{
|
||||||
|
struct sr_usb_dev_inst *usb = uscpi->usb;
|
||||||
|
struct libusb_device *dev;
|
||||||
|
struct libusb_device_descriptor des;
|
||||||
|
int ret;
|
||||||
|
uint8_t status;
|
||||||
|
|
||||||
|
if (!(uscpi->usb488_dev_cap & USB488_DEV_CAP_RL1))
|
||||||
|
return SR_OK;
|
||||||
|
|
||||||
|
dev = libusb_get_device(usb->devhdl);
|
||||||
|
libusb_get_device_descriptor(dev, &des);
|
||||||
|
if (check_usbtmc_blacklist(blacklist_remote, des.idVendor, des.idProduct))
|
||||||
|
return SR_OK;
|
||||||
|
|
||||||
|
sr_dbg("Locking out local control.");
|
||||||
|
ret = libusb_control_transfer(usb->devhdl,
|
||||||
|
LIBUSB_ENDPOINT_IN |
|
||||||
|
LIBUSB_REQUEST_TYPE_CLASS |
|
||||||
|
LIBUSB_RECIPIENT_INTERFACE,
|
||||||
|
REN_CONTROL, 1,
|
||||||
|
uscpi->interface,
|
||||||
|
&status, 1,
|
||||||
|
TRANSFER_TIMEOUT);
|
||||||
|
if (ret < 0 || status != USBTMC_STATUS_SUCCESS) {
|
||||||
|
if (ret < 0)
|
||||||
|
sr_dbg("Failed to enter REN state: %s.", libusb_error_name(ret));
|
||||||
|
else
|
||||||
|
sr_dbg("Failed to enter REN state: USBTMC status %d.", status);
|
||||||
|
return SR_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = libusb_control_transfer(usb->devhdl,
|
||||||
|
LIBUSB_ENDPOINT_IN |
|
||||||
|
LIBUSB_REQUEST_TYPE_CLASS |
|
||||||
|
LIBUSB_RECIPIENT_INTERFACE,
|
||||||
|
LOCAL_LOCKOUT, 1,
|
||||||
|
uscpi->interface,
|
||||||
|
&status, 1,
|
||||||
|
TRANSFER_TIMEOUT);
|
||||||
|
if (ret < 0 || status != USBTMC_STATUS_SUCCESS) {
|
||||||
|
if (ret < 0)
|
||||||
|
sr_dbg("Failed to enter local lockout state: %s.",
|
||||||
|
libusb_error_name(ret));
|
||||||
|
else
|
||||||
|
sr_dbg("Failed to enter local lockout state: USBTMC "
|
||||||
|
"status %d.", status);
|
||||||
|
return SR_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scpi_usbtmc_local(struct scpi_usbtmc_libusb *uscpi)
|
||||||
|
{
|
||||||
|
struct sr_usb_dev_inst *usb = uscpi->usb;
|
||||||
|
struct libusb_device *dev;
|
||||||
|
struct libusb_device_descriptor des;
|
||||||
|
int ret;
|
||||||
|
uint8_t status;
|
||||||
|
|
||||||
|
if (!(uscpi->usb488_dev_cap & USB488_DEV_CAP_RL1))
|
||||||
|
return;
|
||||||
|
|
||||||
|
dev = libusb_get_device(usb->devhdl);
|
||||||
|
libusb_get_device_descriptor(dev, &des);
|
||||||
|
if (check_usbtmc_blacklist(blacklist_remote, des.idVendor, des.idProduct))
|
||||||
|
return;
|
||||||
|
|
||||||
|
sr_dbg("Returning local control.");
|
||||||
|
ret = libusb_control_transfer(usb->devhdl,
|
||||||
|
LIBUSB_ENDPOINT_IN |
|
||||||
|
LIBUSB_REQUEST_TYPE_CLASS |
|
||||||
|
LIBUSB_RECIPIENT_INTERFACE,
|
||||||
|
GO_TO_LOCAL, 1,
|
||||||
|
uscpi->interface,
|
||||||
|
&status, 1,
|
||||||
|
TRANSFER_TIMEOUT);
|
||||||
|
if (ret < 0 || status != USBTMC_STATUS_SUCCESS) {
|
||||||
|
if (ret < 0)
|
||||||
|
sr_dbg("Failed to clear local lockout state: %s.",
|
||||||
|
libusb_error_name(ret));
|
||||||
|
else
|
||||||
|
sr_dbg("Failed to clear local lockout state: USBTMC "
|
||||||
|
"status %d.", status);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
static int scpi_usbtmc_libusb_open(void *priv)
|
static int scpi_usbtmc_libusb_open(void *priv)
|
||||||
{
|
{
|
||||||
struct scpi_usbtmc_libusb *uscpi = priv;
|
struct scpi_usbtmc_libusb *uscpi = priv;
|
||||||
|
@ -184,7 +299,7 @@ static int scpi_usbtmc_libusb_open(void *priv)
|
||||||
const struct libusb_interface_descriptor *intfdes;
|
const struct libusb_interface_descriptor *intfdes;
|
||||||
const struct libusb_endpoint_descriptor *ep;
|
const struct libusb_endpoint_descriptor *ep;
|
||||||
int confidx, intfidx, epidx, config = 0;
|
int confidx, intfidx, epidx, config = 0;
|
||||||
uint8_t capabilities[24], status;
|
uint8_t capabilities[24];
|
||||||
int ret, found = 0;
|
int ret, found = 0;
|
||||||
|
|
||||||
if (usb->devhdl)
|
if (usb->devhdl)
|
||||||
|
@ -308,31 +423,7 @@ static int scpi_usbtmc_libusb_open(void *priv)
|
||||||
uscpi->usb488_dev_cap & USB488_DEV_CAP_RL1 ? "RL1" : "RL0",
|
uscpi->usb488_dev_cap & USB488_DEV_CAP_RL1 ? "RL1" : "RL0",
|
||||||
uscpi->usb488_dev_cap & USB488_DEV_CAP_DT1 ? "DT1" : "DT0");
|
uscpi->usb488_dev_cap & USB488_DEV_CAP_DT1 ? "DT1" : "DT0");
|
||||||
|
|
||||||
if (uscpi->usb488_dev_cap & USB488_DEV_CAP_RL1) {
|
scpi_usbtmc_remote(uscpi);
|
||||||
sr_dbg("Locking out local control.");
|
|
||||||
ret = libusb_control_transfer(usb->devhdl,
|
|
||||||
LIBUSB_ENDPOINT_IN |
|
|
||||||
LIBUSB_REQUEST_TYPE_CLASS |
|
|
||||||
LIBUSB_RECIPIENT_INTERFACE,
|
|
||||||
REN_CONTROL, 1,
|
|
||||||
uscpi->interface,
|
|
||||||
&status, 1,
|
|
||||||
TRANSFER_TIMEOUT);
|
|
||||||
if (ret < 0 || status != USBTMC_STATUS_SUCCESS) {
|
|
||||||
sr_dbg("Failed to enter REN state.");
|
|
||||||
return SR_OK;
|
|
||||||
}
|
|
||||||
ret = libusb_control_transfer(usb->devhdl,
|
|
||||||
LIBUSB_ENDPOINT_IN |
|
|
||||||
LIBUSB_REQUEST_TYPE_CLASS |
|
|
||||||
LIBUSB_RECIPIENT_INTERFACE,
|
|
||||||
LOCAL_LOCKOUT, 1,
|
|
||||||
uscpi->interface,
|
|
||||||
&status, 1,
|
|
||||||
TRANSFER_TIMEOUT);
|
|
||||||
if (ret < 0 || status != USBTMC_STATUS_SUCCESS)
|
|
||||||
sr_dbg("Failed to enter local lockout state.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return SR_OK;
|
return SR_OK;
|
||||||
}
|
}
|
||||||
|
@ -548,7 +639,6 @@ static int scpi_usbtmc_libusb_close(void *priv)
|
||||||
int ret;
|
int ret;
|
||||||
struct scpi_usbtmc_libusb *uscpi = priv;
|
struct scpi_usbtmc_libusb *uscpi = priv;
|
||||||
struct sr_usb_dev_inst *usb = uscpi->usb;
|
struct sr_usb_dev_inst *usb = uscpi->usb;
|
||||||
uint8_t status;
|
|
||||||
|
|
||||||
if (!usb->devhdl)
|
if (!usb->devhdl)
|
||||||
return SR_ERR;
|
return SR_ERR;
|
||||||
|
@ -565,19 +655,7 @@ static int scpi_usbtmc_libusb_close(void *priv)
|
||||||
uscpi->interrupt_ep, libusb_error_name(ret));
|
uscpi->interrupt_ep, libusb_error_name(ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uscpi->usb488_dev_cap & USB488_DEV_CAP_RL1) {
|
scpi_usbtmc_local(uscpi);
|
||||||
sr_dbg("Returning local control.");
|
|
||||||
ret = libusb_control_transfer(usb->devhdl,
|
|
||||||
LIBUSB_ENDPOINT_IN |
|
|
||||||
LIBUSB_REQUEST_TYPE_CLASS |
|
|
||||||
LIBUSB_RECIPIENT_INTERFACE,
|
|
||||||
GO_TO_LOCAL, 1,
|
|
||||||
uscpi->interface,
|
|
||||||
&status, 1,
|
|
||||||
TRANSFER_TIMEOUT);
|
|
||||||
if (ret < 0 || status != USBTMC_STATUS_SUCCESS)
|
|
||||||
sr_dbg("Failed to clear local lockout state.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ret = libusb_release_interface(usb->devhdl, uscpi->interface)) < 0)
|
if ((ret = libusb_release_interface(usb->devhdl, uscpi->interface)) < 0)
|
||||||
sr_err("Failed to release interface: %s.",
|
sr_err("Failed to release interface: %s.",
|
||||||
|
|
Loading…
Reference in New Issue