aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Penkler <dpenkler@gmail.com>2020-12-15 16:56:20 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-12-28 15:50:30 +0100
commitd1d9defdc6d582119d29f5d88f810b72bb1837fa (patch)
treef3dce4bbad4c77f09e8d3876602afd8f81171e86
parentUSB: usbtmc: Add USBTMC_IOCTL_GET_STB (diff)
downloadlinux-dev-d1d9defdc6d582119d29f5d88f810b72bb1837fa.tar.xz
linux-dev-d1d9defdc6d582119d29f5d88f810b72bb1837fa.zip
USB: usbtmc: Add separate USBTMC_IOCTL_GET_SRQ_STB
This new ioctl only returns the status byte (STB) that was originally sent by the device due to a service request (SRQ) condition. This ioctl checks the srq_asserted bit of the associated file descriptor. If set, the srq_asserted bit is reset and the cached STB with original SRQ information is returned. Otherwise the ioctl returns the error code ENOMSG. This ioctl is useful to support non USBTMC-488 compliant devices. Time sensitive applications can read the cached STB without incurring the cost of an urb transaction over the bus. Tested-by: Jian-Wei Wu <jian-wei_wu@keysight.com> Reviewed-by: Guido Kiener <guido.kiener@rohde-schwarz.com> Signed-off-by: Dave Penkler <dpenkler@gmail.com> Link: https://lore.kernel.org/r/20201215155621.9592-4-dpenkler@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/class/usbtmc.c31
-rw-r--r--include/uapi/linux/usb/tmc.h1
2 files changed, 32 insertions, 0 deletions
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 8918e2182eca..d2fcc698c745 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -571,6 +571,32 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_file_data *file_data,
}
+static int usbtmc_ioctl_get_srq_stb(struct usbtmc_file_data *file_data,
+ void __user *arg)
+{
+ struct usbtmc_device_data *data = file_data->data;
+ struct device *dev = &data->intf->dev;
+ int srq_asserted = 0;
+ __u8 stb = 0;
+ int rv;
+
+ spin_lock_irq(&data->dev_lock);
+ srq_asserted = atomic_xchg(&file_data->srq_asserted, srq_asserted);
+
+ if (srq_asserted) {
+ stb = file_data->srq_byte;
+ spin_unlock_irq(&data->dev_lock);
+ rv = put_user(stb, (__u8 __user *)arg);
+ } else {
+ spin_unlock_irq(&data->dev_lock);
+ rv = -ENOMSG;
+ }
+
+ dev_dbg(dev, "stb:0x%02x with srq received %d\n", (unsigned int)stb, rv);
+
+ return rv;
+}
+
static int usbtmc488_ioctl_wait_srq(struct usbtmc_file_data *file_data,
__u32 __user *arg)
{
@@ -2155,6 +2181,11 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
retval = put_user(tmp_byte, (__u8 __user *)arg);
break;
+ case USBTMC_IOCTL_GET_SRQ_STB:
+ retval = usbtmc_ioctl_get_srq_stb(file_data,
+ (void __user *)arg);
+ break;
+
case USBTMC_IOCTL_CANCEL_IO:
retval = usbtmc_ioctl_cancel_io(file_data);
break;
diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h
index 1e7878fe591f..d791cc58a7f0 100644
--- a/include/uapi/linux/usb/tmc.h
+++ b/include/uapi/linux/usb/tmc.h
@@ -103,6 +103,7 @@ struct usbtmc_message {
#define USBTMC_IOCTL_AUTO_ABORT _IOW(USBTMC_IOC_NR, 25, __u8)
#define USBTMC_IOCTL_GET_STB _IOR(USBTMC_IOC_NR, 26, __u8)
+#define USBTMC_IOCTL_GET_SRQ_STB _IOR(USBTMC_IOC_NR, 27, __u8)
/* Cancel and cleanup asynchronous calls */
#define USBTMC_IOCTL_CANCEL_IO _IO(USBTMC_IOC_NR, 35)