summaryrefslogtreecommitdiff
path: root/drivers/usb/class/usbtmc.c
diff options
context:
space:
mode:
authorDave Penkler <dpenkler@gmail.com>2016-01-27 19:25:24 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-02-03 13:54:06 -0800
commit379d3d33c83b667b0edad0110693567306463882 (patch)
tree9a42ed42b6c3ac7b94a285ccc933c680e08b620a /drivers/usb/class/usbtmc.c
parent29779d89fd049bfc6c07f19aaf9b8d19fe2ecc8c (diff)
Add ioctls to enable and disable local controls on an instrument
These ioctls provide support for the USBTMC-USB488 control requests for REN_CONTROL, GO_TO_LOCAL and LOCAL_LOCKOUT Signed-off-by: Dave Penkler <dpenkler@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/class/usbtmc.c')
-rw-r--r--drivers/usb/class/usbtmc.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 6edb21ca9989..419c72e10464 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -474,6 +474,61 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_device_data *data,
return rv;
}
+static int usbtmc488_ioctl_simple(struct usbtmc_device_data *data,
+ void __user *arg, unsigned int cmd)
+{
+ struct device *dev = &data->intf->dev;
+ __u8 val;
+ u8 *buffer;
+ u16 wValue;
+ int rv;
+
+ if (!(data->usb488_caps & USBTMC488_CAPABILITY_SIMPLE))
+ return -EINVAL;
+
+ buffer = kmalloc(8, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ if (cmd == USBTMC488_REQUEST_REN_CONTROL) {
+ rv = copy_from_user(&val, arg, sizeof(val));
+ if (rv) {
+ rv = -EFAULT;
+ goto exit;
+ }
+ wValue = val ? 1 : 0;
+ } else {
+ wValue = 0;
+ }
+
+ rv = usb_control_msg(data->usb_dev,
+ usb_rcvctrlpipe(data->usb_dev, 0),
+ cmd,
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ wValue,
+ data->ifnum,
+ buffer, 0x01, USBTMC_TIMEOUT);
+ if (rv < 0) {
+ dev_err(dev, "simple usb_control_msg failed %d\n", rv);
+ goto exit;
+ } else if (rv != 1) {
+ dev_warn(dev, "simple usb_control_msg returned %d\n", rv);
+ rv = -EIO;
+ goto exit;
+ }
+
+ if (buffer[0] != USBTMC_STATUS_SUCCESS) {
+ dev_err(dev, "simple control status returned %x\n", buffer[0]);
+ rv = -EIO;
+ goto exit;
+ }
+ rv = 0;
+
+ exit:
+ kfree(buffer);
+ return rv;
+}
+
/*
* Sends a REQUEST_DEV_DEP_MSG_IN message on the Bulk-IN endpoint.
* @transfer_size: number of bytes to request from the device.
@@ -1183,6 +1238,21 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case USBTMC488_IOCTL_READ_STB:
retval = usbtmc488_ioctl_read_stb(data, (void __user *)arg);
break;
+
+ case USBTMC488_IOCTL_REN_CONTROL:
+ retval = usbtmc488_ioctl_simple(data, (void __user *)arg,
+ USBTMC488_REQUEST_REN_CONTROL);
+ break;
+
+ case USBTMC488_IOCTL_GOTO_LOCAL:
+ retval = usbtmc488_ioctl_simple(data, (void __user *)arg,
+ USBTMC488_REQUEST_GOTO_LOCAL);
+ break;
+
+ case USBTMC488_IOCTL_LOCAL_LOCKOUT:
+ retval = usbtmc488_ioctl_simple(data, (void __user *)arg,
+ USBTMC488_REQUEST_LOCAL_LOCKOUT);
+ break;
}
skip_io_on_zombie: