|
@@ -130,6 +130,7 @@ struct usbtmc_file_data {
|
|
|
u32 timeout;
|
|
|
u8 srq_byte;
|
|
|
atomic_t srq_asserted;
|
|
|
+ atomic_t closing;
|
|
|
|
|
|
u8 eom_val;
|
|
|
u8 term_char;
|
|
@@ -193,6 +194,8 @@ static int usbtmc_open(struct inode *inode, struct file *filp)
|
|
|
mutex_lock(&data->io_mutex);
|
|
|
file_data->data = data;
|
|
|
|
|
|
+ atomic_set(&file_data->closing, 0);
|
|
|
+
|
|
|
/* copy default values from device settings */
|
|
|
file_data->timeout = USBTMC_TIMEOUT;
|
|
|
file_data->term_char = data->TermChar;
|
|
@@ -223,6 +226,7 @@ static int usbtmc_flush(struct file *file, fl_owner_t id)
|
|
|
if (file_data == NULL)
|
|
|
return -ENODEV;
|
|
|
|
|
|
+ atomic_set(&file_data->closing, 1);
|
|
|
data = file_data->data;
|
|
|
|
|
|
/* wait for io to stop */
|
|
@@ -576,6 +580,54 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_file_data *file_data,
|
|
|
return rv;
|
|
|
}
|
|
|
|
|
|
+static int usbtmc488_ioctl_wait_srq(struct usbtmc_file_data *file_data,
|
|
|
+ __u32 __user *arg)
|
|
|
+{
|
|
|
+ struct usbtmc_device_data *data = file_data->data;
|
|
|
+ struct device *dev = &data->intf->dev;
|
|
|
+ int rv;
|
|
|
+ u32 timeout;
|
|
|
+ unsigned long expire;
|
|
|
+
|
|
|
+ if (!data->iin_ep_present) {
|
|
|
+ dev_dbg(dev, "no interrupt endpoint present\n");
|
|
|
+ return -EFAULT;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (get_user(timeout, arg))
|
|
|
+ return -EFAULT;
|
|
|
+
|
|
|
+ expire = msecs_to_jiffies(timeout);
|
|
|
+
|
|
|
+ mutex_unlock(&data->io_mutex);
|
|
|
+
|
|
|
+ rv = wait_event_interruptible_timeout(
|
|
|
+ data->waitq,
|
|
|
+ atomic_read(&file_data->srq_asserted) != 0 ||
|
|
|
+ atomic_read(&file_data->closing),
|
|
|
+ expire);
|
|
|
+
|
|
|
+ mutex_lock(&data->io_mutex);
|
|
|
+
|
|
|
+ /* Note! disconnect or close could be called in the meantime */
|
|
|
+ if (atomic_read(&file_data->closing) || data->zombie)
|
|
|
+ rv = -ENODEV;
|
|
|
+
|
|
|
+ if (rv < 0) {
|
|
|
+ /* dev can be invalid now! */
|
|
|
+ pr_debug("%s - wait interrupted %d\n", __func__, rv);
|
|
|
+ return rv;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (rv == 0) {
|
|
|
+ dev_dbg(dev, "%s - wait timed out\n", __func__);
|
|
|
+ return -ETIMEDOUT;
|
|
|
+ }
|
|
|
+
|
|
|
+ dev_dbg(dev, "%s - srq asserted\n", __func__);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int usbtmc488_ioctl_simple(struct usbtmc_device_data *data,
|
|
|
void __user *arg, unsigned int cmd)
|
|
|
{
|
|
@@ -2142,6 +2194,11 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|
|
retval = usbtmc488_ioctl_trigger(file_data);
|
|
|
break;
|
|
|
|
|
|
+ case USBTMC488_IOCTL_WAIT_SRQ:
|
|
|
+ retval = usbtmc488_ioctl_wait_srq(file_data,
|
|
|
+ (__u32 __user *)arg);
|
|
|
+ break;
|
|
|
+
|
|
|
case USBTMC_IOCTL_CANCEL_IO:
|
|
|
retval = usbtmc_ioctl_cancel_io(file_data);
|
|
|
break;
|