diff options
Diffstat (limited to 'drivers/usb/class/usbtmc.c')
| -rw-r--r-- | drivers/usb/class/usbtmc.c | 484 |
1 files changed, 315 insertions, 169 deletions
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 0f5c05f6f9d..103a6e9ee49 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -1,5 +1,5 @@ /** - * drivers/usb/class/usbtmc.c - USB Test & Measurment class driver + * drivers/usb/class/usbtmc.c - USB Test & Measurement class driver * * Copyright (C) 2007 Stefan Kopp, Gechingen, Germany * Copyright (C) 2008 Novell, Inc. @@ -19,17 +19,21 @@ * http://www.gnu.org/copyleft/gpl.html. */ -#include <linux/init.h> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/uaccess.h> #include <linux/kref.h> +#include <linux/slab.h> #include <linux/mutex.h> #include <linux/usb.h> #include <linux/usb/tmc.h> +#define RIGOL 1 +#define USBTMC_HEADER_SIZE 12 #define USBTMC_MINOR_BASE 176 /* @@ -39,7 +43,7 @@ #define USBTMC_SIZE_IOBUFFER 2048 /* Default USB timeout (in milliseconds) */ -#define USBTMC_TIMEOUT 10 +#define USBTMC_TIMEOUT 5000 /* * Maximum number of read cycles to empty bulk in endpoint during CLEAR and @@ -48,15 +52,18 @@ */ #define USBTMC_MAX_READS_TO_CLEAR_BULK_IN 100 -static struct usb_device_id usbtmc_devices[] = { +static const struct usb_device_id usbtmc_devices[] = { { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 0), }, + { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 1), }, { 0, } /* terminating entry */ }; MODULE_DEVICE_TABLE(usb, usbtmc_devices); /* * This structure is the capabilities for the device - * See section 4.2.1.8 of the USBTMC specification for details. + * See section 4.2.1.8 of the USBTMC specification, + * and section 4.2.2 of the USBTMC usb488 subclass + * specification for details. */ struct usbtmc_dev_capabilities { __u8 interface_capabilities; @@ -80,17 +87,31 @@ struct usbtmc_device_data { u8 bTag_last_write; /* needed for abort */ u8 bTag_last_read; /* needed for abort */ + u8 rigol_quirk; + /* attributes from the USB TMC spec for this device */ u8 TermChar; bool TermCharEnabled; bool auto_abort; + bool zombie; /* fd of disconnected device */ + struct usbtmc_dev_capabilities capabilities; struct kref kref; struct mutex io_mutex; /* only one i/o function running at a time */ }; #define to_usbtmc_data(d) container_of(d, struct usbtmc_device_data, kref) +struct usbtmc_ID_rigol_quirk { + __u16 idVendor; + __u16 idProduct; +}; + +static const struct usbtmc_ID_rigol_quirk usbtmc_id_quirk[] = { + { 0x1ab1, 0x0588 }, + { 0, 0 } +}; + /* Forward declarations */ static struct usb_driver usbtmc_driver; @@ -99,20 +120,18 @@ static void usbtmc_delete(struct kref *kref) struct usbtmc_device_data *data = to_usbtmc_data(kref); usb_put_dev(data->usb_dev); - kfree(data); } static int usbtmc_open(struct inode *inode, struct file *filp) { struct usb_interface *intf; struct usbtmc_device_data *data; - int retval = -ENODEV; + int retval = 0; intf = usb_find_interface(&usbtmc_driver, iminor(inode)); if (!intf) { - printk(KERN_ERR KBUILD_MODNAME - ": can not find device for minor %d", iminor(inode)); - goto exit; + pr_err("can not find device for minor %d", iminor(inode)); + return -ENODEV; } data = usb_get_intfdata(intf); @@ -121,7 +140,6 @@ static int usbtmc_open(struct inode *inode, struct file *filp) /* Store pointer in file structure's private data field */ filp->private_data = data; -exit: return retval; } @@ -179,8 +197,7 @@ static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data) for (n = 0; n < current_setting->desc.bNumEndpoints; n++) if (current_setting->endpoint[n].desc.bEndpointAddress == data->bulk_in) - max_size = le16_to_cpu(current_setting->endpoint[n]. - desc.wMaxPacketSize); + max_size = usb_endpoint_maxp(¤t_setting->endpoint[n].desc); if (max_size == 0) { dev_err(dev, "Couldn't get wMaxPacketSize\n"); @@ -261,7 +278,7 @@ usbtmc_abort_bulk_in_status: dev_err(dev, "usb_bulk_msg returned %d\n", rv); goto exit; } - } while ((actual = max_size) && + } while ((actual == max_size) && (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN)); if (actual == max_size) { @@ -341,13 +358,8 @@ usbtmc_abort_bulk_out_check_status: goto exit; usbtmc_abort_bulk_out_clear_halt: - rv = usb_control_msg(data->usb_dev, - usb_sndctrlpipe(data->usb_dev, 0), - USB_REQ_CLEAR_FEATURE, - USB_DIR_OUT | USB_TYPE_STANDARD | - USB_RECIP_ENDPOINT, - USB_ENDPOINT_HALT, data->bulk_out, buffer, - 0, USBTMC_TIMEOUT); + rv = usb_clear_halt(data->usb_dev, + usb_sndbulkpipe(data->usb_dev, data->bulk_out)); if (rv < 0) { dev_err(dev, "usb_control_msg returned %d\n", rv); @@ -360,18 +372,75 @@ exit: 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. + * + * See the USBTMC specification, Table 4. + * + * Also updates bTag_last_write. + */ +static int send_request_dev_dep_msg_in(struct usbtmc_device_data *data, size_t transfer_size) +{ + int retval; + u8 *buffer; + int actual; + + buffer = kmalloc(USBTMC_HEADER_SIZE, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + /* Setup IO buffer for REQUEST_DEV_DEP_MSG_IN message + * Refer to class specs for details + */ + buffer[0] = 2; + buffer[1] = data->bTag; + buffer[2] = ~data->bTag; + buffer[3] = 0; /* Reserved */ + buffer[4] = transfer_size >> 0; + buffer[5] = transfer_size >> 8; + buffer[6] = transfer_size >> 16; + buffer[7] = transfer_size >> 24; + buffer[8] = data->TermCharEnabled * 2; + /* Use term character? */ + buffer[9] = data->TermChar; + buffer[10] = 0; /* Reserved */ + buffer[11] = 0; /* Reserved */ + + /* Send bulk URB */ + retval = usb_bulk_msg(data->usb_dev, + usb_sndbulkpipe(data->usb_dev, + data->bulk_out), + buffer, USBTMC_HEADER_SIZE, &actual, USBTMC_TIMEOUT); + + /* Store bTag (in case we need to abort) */ + data->bTag_last_write = data->bTag; + + /* Increment bTag -- and increment again if zero */ + data->bTag++; + if (!data->bTag) + data->bTag++; + + kfree(buffer); + if (retval < 0) { + dev_err(&data->intf->dev, "usb_bulk_msg in send_request_dev_dep_msg_in() returned %d\n", retval); + return retval; + } + + return 0; +} + static ssize_t usbtmc_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { struct usbtmc_device_data *data; struct device *dev; - unsigned long int n_characters; + u32 n_characters; u8 *buffer; int actual; - int done; - int remaining; + size_t done; + size_t remaining; int retval; - int this_part; + size_t this_part; /* Get pointer to private data structure */ data = filp->private_data; @@ -382,52 +451,44 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, return -ENOMEM; mutex_lock(&data->io_mutex); + if (data->zombie) { + retval = -ENODEV; + goto exit; + } - remaining = count; - done = 0; + if (data->rigol_quirk) { + dev_dbg(dev, "usb_bulk_msg_in: count(%zu)\n", count); - while (remaining > 0) { - if (remaining > USBTMC_SIZE_IOBUFFER - 12 - 3) - this_part = USBTMC_SIZE_IOBUFFER - 12 - 3; - else - this_part = remaining; + retval = send_request_dev_dep_msg_in(data, count); - /* Setup IO buffer for DEV_DEP_MSG_IN message - * Refer to class specs for details - */ - buffer[0] = 2; - buffer[1] = data->bTag; - buffer[2] = ~(data->bTag); - buffer[3] = 0; /* Reserved */ - buffer[4] = (this_part - 12 - 3) & 255; - buffer[5] = ((this_part - 12 - 3) >> 8) & 255; - buffer[6] = ((this_part - 12 - 3) >> 16) & 255; - buffer[7] = ((this_part - 12 - 3) >> 24) & 255; - buffer[8] = data->TermCharEnabled * 2; - /* Use term character? */ - buffer[9] = data->TermChar; - buffer[10] = 0; /* Reserved */ - buffer[11] = 0; /* Reserved */ + if (retval < 0) { + if (data->auto_abort) + usbtmc_ioctl_abort_bulk_out(data); + goto exit; + } + } - /* Send bulk URB */ - retval = usb_bulk_msg(data->usb_dev, - usb_sndbulkpipe(data->usb_dev, - data->bulk_out), - buffer, 12, &actual, USBTMC_TIMEOUT); + /* Loop until we have fetched everything we requested */ + remaining = count; + this_part = remaining; + done = 0; - /* Store bTag (in case we need to abort) */ - data->bTag_last_write = data->bTag; + while (remaining > 0) { + if (!data->rigol_quirk) { + dev_dbg(dev, "usb_bulk_msg_in: remaining(%zu), count(%zu)\n", remaining, count); - /* Increment bTag -- and increment again if zero */ - data->bTag++; - if (!data->bTag) - (data->bTag)++; + if (remaining > USBTMC_SIZE_IOBUFFER - USBTMC_HEADER_SIZE - 3) + this_part = USBTMC_SIZE_IOBUFFER - USBTMC_HEADER_SIZE - 3; + else + this_part = remaining; - if (retval < 0) { + retval = send_request_dev_dep_msg_in(data, this_part); + if (retval < 0) { dev_err(dev, "usb_bulk_msg returned %d\n", retval); - if (data->auto_abort) - usbtmc_ioctl_abort_bulk_out(data); - goto exit; + if (data->auto_abort) + usbtmc_ioctl_abort_bulk_out(data); + goto exit; + } } /* Send bulk URB */ @@ -437,32 +498,109 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, buffer, USBTMC_SIZE_IOBUFFER, &actual, USBTMC_TIMEOUT); + dev_dbg(dev, "usb_bulk_msg: retval(%u), done(%zu), remaining(%zu), actual(%d)\n", retval, done, remaining, actual); + /* Store bTag (in case we need to abort) */ data->bTag_last_read = data->bTag; if (retval < 0) { - dev_err(dev, "Unable to read data, error %d\n", retval); + dev_dbg(dev, "Unable to read data, error %d\n", retval); if (data->auto_abort) usbtmc_ioctl_abort_bulk_in(data); goto exit; } - /* How many characters did the instrument send? */ - n_characters = buffer[4] + - (buffer[5] << 8) + - (buffer[6] << 16) + - (buffer[7] << 24); + /* Parse header in first packet */ + if ((done == 0) || !data->rigol_quirk) { + /* Sanity checks for the header */ + if (actual < USBTMC_HEADER_SIZE) { + dev_err(dev, "Device sent too small first packet: %u < %u\n", actual, USBTMC_HEADER_SIZE); + if (data->auto_abort) + usbtmc_ioctl_abort_bulk_in(data); + goto exit; + } + + if (buffer[0] != 2) { + dev_err(dev, "Device sent reply with wrong MsgID: %u != 2\n", buffer[0]); + if (data->auto_abort) + usbtmc_ioctl_abort_bulk_in(data); + goto exit; + } - /* Copy buffer to user space */ - if (copy_to_user(buf + done, &buffer[12], n_characters)) { - /* There must have been an addressing problem */ - retval = -EFAULT; - goto exit; + if (buffer[1] != data->bTag_last_write) { + dev_err(dev, "Device sent reply with wrong bTag: %u != %u\n", buffer[1], data->bTag_last_write); + if (data->auto_abort) + usbtmc_ioctl_abort_bulk_in(data); + goto exit; + } + + /* How many characters did the instrument send? */ + n_characters = buffer[4] + + (buffer[5] << 8) + + (buffer[6] << 16) + + (buffer[7] << 24); + + if (n_characters > this_part) { + dev_err(dev, "Device wants to return more data than requested: %u > %zu\n", n_characters, count); + if (data->auto_abort) + usbtmc_ioctl_abort_bulk_in(data); + goto exit; + } + + /* Remove the USBTMC header */ + actual -= USBTMC_HEADER_SIZE; + + /* Check if the message is smaller than requested */ + if (data->rigol_quirk) { + if (remaining > n_characters) + remaining = n_characters; + /* Remove padding if it exists */ + if (actual > remaining) + actual = remaining; + } + else { + if (this_part > n_characters) + this_part = n_characters; + /* Remove padding if it exists */ + if (actual > this_part) + actual = this_part; + } + + dev_dbg(dev, "Bulk-IN header: N_characters(%u), bTransAttr(%u)\n", n_characters, buffer[8]); + + remaining -= actual; + + /* Terminate if end-of-message bit received from device */ + if ((buffer[8] & 0x01) && (actual >= n_characters)) + remaining = 0; + + dev_dbg(dev, "Bulk-IN header: remaining(%zu), buf(%p), buffer(%p) done(%zu)\n", remaining,buf,buffer,done); + + + /* Copy buffer to user space */ + if (copy_to_user(buf + done, &buffer[USBTMC_HEADER_SIZE], actual)) { + /* There must have been an addressing problem */ + retval = -EFAULT; + goto exit; + } + done += actual; } + else { + if (actual > remaining) + actual = remaining; + + remaining -= actual; - done += n_characters; - if (n_characters < USBTMC_SIZE_IOBUFFER) - remaining = 0; + dev_dbg(dev, "Bulk-IN header cont: actual(%u), done(%zu), remaining(%zu), buf(%p), buffer(%p)\n", actual, done, remaining,buf,buffer); + + /* Copy buffer to user space */ + if (copy_to_user(buf + done, buffer, actual)) { + /* There must have been an addressing problem */ + retval = -EFAULT; + goto exit; + } + done += actual; + } } /* Update file position value */ @@ -494,13 +632,17 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf, return -ENOMEM; mutex_lock(&data->io_mutex); + if (data->zombie) { + retval = -ENODEV; + goto exit; + } remaining = count; done = 0; while (remaining > 0) { - if (remaining > USBTMC_SIZE_IOBUFFER - 12) { - this_part = USBTMC_SIZE_IOBUFFER - 12; + if (remaining > USBTMC_SIZE_IOBUFFER - USBTMC_HEADER_SIZE) { + this_part = USBTMC_SIZE_IOBUFFER - USBTMC_HEADER_SIZE; buffer[8] = 0; } else { this_part = remaining; @@ -510,29 +652,35 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf, /* Setup IO buffer for DEV_DEP_MSG_OUT message */ buffer[0] = 1; buffer[1] = data->bTag; - buffer[2] = ~(data->bTag); + buffer[2] = ~data->bTag; buffer[3] = 0; /* Reserved */ - buffer[4] = this_part & 255; - buffer[5] = (this_part >> 8) & 255; - buffer[6] = (this_part >> 16) & 255; - buffer[7] = (this_part >> 24) & 255; + buffer[4] = this_part >> 0; + buffer[5] = this_part >> 8; + buffer[6] = this_part >> 16; + buffer[7] = this_part >> 24; /* buffer[8] is set above... */ buffer[9] = 0; /* Reserved */ buffer[10] = 0; /* Reserved */ buffer[11] = 0; /* Reserved */ - if (copy_from_user(&buffer[12], buf + done, this_part)) { + if (copy_from_user(&buffer[USBTMC_HEADER_SIZE], buf + done, this_part)) { retval = -EFAULT; goto exit; } - n_bytes = roundup(12 + this_part, 4); - memset(buffer + 12 + this_part, 0, n_bytes - (12 + this_part)); + n_bytes = roundup(USBTMC_HEADER_SIZE + this_part, 4); + memset(buffer + USBTMC_HEADER_SIZE + this_part, 0, n_bytes - (USBTMC_HEADER_SIZE + this_part)); - retval = usb_bulk_msg(data->usb_dev, - usb_sndbulkpipe(data->usb_dev, - data->bulk_out), - buffer, n_bytes, &actual, USBTMC_TIMEOUT); + do { + retval = usb_bulk_msg(data->usb_dev, + usb_sndbulkpipe(data->usb_dev, + data->bulk_out), + buffer, n_bytes, + &actual, USBTMC_TIMEOUT); + if (retval != 0) + break; + n_bytes -= actual; + } while (n_bytes); data->bTag_last_write = data->bTag; data->bTag++; @@ -601,7 +749,7 @@ static int usbtmc_ioctl_clear(struct usbtmc_device_data *data) for (n = 0; n < current_setting->desc.bNumEndpoints; n++) { desc = ¤t_setting->endpoint[n].desc; if (desc->bEndpointAddress == data->bulk_in) - max_size = le16_to_cpu(desc->wMaxPacketSize); + max_size = usb_endpoint_maxp(desc); } if (max_size == 0) { @@ -669,14 +817,8 @@ usbtmc_clear_check_status: usbtmc_clear_bulk_out_halt: - rv = usb_control_msg(data->usb_dev, - usb_sndctrlpipe(data->usb_dev, 0), - USB_REQ_CLEAR_FEATURE, - USB_DIR_OUT | USB_TYPE_STANDARD | - USB_RECIP_ENDPOINT, - USB_ENDPOINT_HALT, - data->bulk_out, buffer, 0, - USBTMC_TIMEOUT); + rv = usb_clear_halt(data->usb_dev, + usb_sndbulkpipe(data->usb_dev, data->bulk_out)); if (rv < 0) { dev_err(dev, "usb_control_msg returned %d\n", rv); goto exit; @@ -690,66 +832,39 @@ exit: static int usbtmc_ioctl_clear_out_halt(struct usbtmc_device_data *data) { - u8 *buffer; int rv; - buffer = kmalloc(2, GFP_KERNEL); - if (!buffer) - return -ENOMEM; - - rv = usb_control_msg(data->usb_dev, - usb_sndctrlpipe(data->usb_dev, 0), - USB_REQ_CLEAR_FEATURE, - USB_DIR_OUT | USB_TYPE_STANDARD | - USB_RECIP_ENDPOINT, - USB_ENDPOINT_HALT, data->bulk_out, - buffer, 0, USBTMC_TIMEOUT); + rv = usb_clear_halt(data->usb_dev, + usb_sndbulkpipe(data->usb_dev, data->bulk_out)); if (rv < 0) { dev_err(&data->usb_dev->dev, "usb_control_msg returned %d\n", rv); - goto exit; + return rv; } - rv = 0; - -exit: - kfree(buffer); - return rv; + return 0; } static int usbtmc_ioctl_clear_in_halt(struct usbtmc_device_data *data) { - u8 *buffer; int rv; - buffer = kmalloc(2, GFP_KERNEL); - if (!buffer) - return -ENOMEM; - - rv = usb_control_msg(data->usb_dev, usb_sndctrlpipe(data->usb_dev, 0), - USB_REQ_CLEAR_FEATURE, - USB_DIR_OUT | USB_TYPE_STANDARD | - USB_RECIP_ENDPOINT, - USB_ENDPOINT_HALT, data->bulk_in, buffer, 0, - USBTMC_TIMEOUT); + rv = usb_clear_halt(data->usb_dev, + usb_rcvbulkpipe(data->usb_dev, data->bulk_in)); if (rv < 0) { dev_err(&data->usb_dev->dev, "usb_control_msg returned %d\n", rv); - goto exit; + return rv; } - rv = 0; - -exit: - kfree(buffer); - return rv; + return 0; } static int get_capabilities(struct usbtmc_device_data *data) { struct device *dev = &data->usb_dev->dev; char *buffer; - int rv; + int rv = 0; buffer = kmalloc(0x18, GFP_KERNEL); if (!buffer) @@ -761,30 +876,33 @@ static int get_capabilities(struct usbtmc_device_data *data) 0, 0, buffer, 0x18, USBTMC_TIMEOUT); if (rv < 0) { dev_err(dev, "usb_control_msg returned %d\n", rv); - return rv; + goto err_out; } dev_dbg(dev, "GET_CAPABILITIES returned %x\n", buffer[0]); + if (buffer[0] != USBTMC_STATUS_SUCCESS) { + dev_err(dev, "GET_CAPABILITIES returned %x\n", buffer[0]); + rv = -EPERM; + goto err_out; + } dev_dbg(dev, "Interface capabilities are %x\n", buffer[4]); dev_dbg(dev, "Device capabilities are %x\n", buffer[5]); dev_dbg(dev, "USB488 interface capabilities are %x\n", buffer[14]); dev_dbg(dev, "USB488 device capabilities are %x\n", buffer[15]); - if (buffer[0] != USBTMC_STATUS_SUCCESS) { - dev_err(dev, "GET_CAPABILITIES returned %x\n", buffer[0]); - return -EPERM; - } data->capabilities.interface_capabilities = buffer[4]; data->capabilities.device_capabilities = buffer[5]; data->capabilities.usb488_interface_capabilities = buffer[14]; data->capabilities.usb488_device_capabilities = buffer[15]; + rv = 0; +err_out: kfree(buffer); - return 0; + return rv; } #define capability_attribute(name) \ -static ssize_t show_##name(struct device *dev, \ +static ssize_t name##_show(struct device *dev, \ struct device_attribute *attr, char *buf) \ { \ struct usb_interface *intf = to_usb_interface(dev); \ @@ -792,7 +910,7 @@ static ssize_t show_##name(struct device *dev, \ \ return sprintf(buf, "%d\n", data->capabilities.name); \ } \ -static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) +static DEVICE_ATTR_RO(name) capability_attribute(interface_capabilities); capability_attribute(device_capabilities); @@ -811,7 +929,7 @@ static struct attribute_group capability_attr_grp = { .attrs = capability_attrs, }; -static ssize_t show_TermChar(struct device *dev, +static ssize_t TermChar_show(struct device *dev, struct device_attribute *attr, char *buf) { struct usb_interface *intf = to_usb_interface(dev); @@ -820,7 +938,7 @@ static ssize_t show_TermChar(struct device *dev, return sprintf(buf, "%c\n", data->TermChar); } -static ssize_t store_TermChar(struct device *dev, +static ssize_t TermChar_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -832,10 +950,10 @@ static ssize_t store_TermChar(struct device *dev, data->TermChar = buf[0]; return count; } -static DEVICE_ATTR(TermChar, S_IRUGO, show_TermChar, store_TermChar); +static DEVICE_ATTR_RW(TermChar); #define data_attribute(name) \ -static ssize_t show_##name(struct device *dev, \ +static ssize_t name##_show(struct device *dev, \ struct device_attribute *attr, char *buf) \ { \ struct usb_interface *intf = to_usb_interface(dev); \ @@ -843,7 +961,7 @@ static ssize_t show_##name(struct device *dev, \ \ return sprintf(buf, "%d\n", data->name); \ } \ -static ssize_t store_##name(struct device *dev, \ +static ssize_t name##_store(struct device *dev, \ struct device_attribute *attr, \ const char *buf, size_t count) \ { \ @@ -861,7 +979,7 @@ static ssize_t store_##name(struct device *dev, \ else \ return count; \ } \ -static DEVICE_ATTR(name, S_IRUGO, show_##name, store_##name) +static DEVICE_ATTR_RW(name) data_attribute(TermCharEnabled); data_attribute(auto_abort); @@ -921,38 +1039,50 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) data = file->private_data; mutex_lock(&data->io_mutex); + if (data->zombie) { + retval = -ENODEV; + goto skip_io_on_zombie; + } switch (cmd) { case USBTMC_IOCTL_CLEAR_OUT_HALT: retval = usbtmc_ioctl_clear_out_halt(data); + break; case USBTMC_IOCTL_CLEAR_IN_HALT: retval = usbtmc_ioctl_clear_in_halt(data); + break; case USBTMC_IOCTL_INDICATOR_PULSE: retval = usbtmc_ioctl_indicator_pulse(data); + break; case USBTMC_IOCTL_CLEAR: retval = usbtmc_ioctl_clear(data); + break; case USBTMC_IOCTL_ABORT_BULK_OUT: retval = usbtmc_ioctl_abort_bulk_out(data); + break; case USBTMC_IOCTL_ABORT_BULK_IN: retval = usbtmc_ioctl_abort_bulk_in(data); + break; } +skip_io_on_zombie: mutex_unlock(&data->io_mutex); return retval; } -static struct file_operations fops = { +static const struct file_operations fops = { .owner = THIS_MODULE, .read = usbtmc_read, .write = usbtmc_write, .open = usbtmc_open, .release = usbtmc_release, .unlocked_ioctl = usbtmc_ioctl, + .llseek = default_llseek, }; static struct usb_class_driver usbtmc_class = { @@ -973,7 +1103,7 @@ static int usbtmc_probe(struct usb_interface *intf, dev_dbg(&intf->dev, "%s called\n", __func__); - data = kmalloc(sizeof(struct usbtmc_device_data), GFP_KERNEL); + data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL); if (!data) { dev_err(&intf->dev, "Unable to allocate kernel memory\n"); return -ENOMEM; @@ -985,6 +1115,21 @@ static int usbtmc_probe(struct usb_interface *intf, usb_set_intfdata(intf, data); kref_init(&data->kref); mutex_init(&data->io_mutex); + data->zombie = 0; + + /* Determine if it is a Rigol or not */ + data->rigol_quirk = 0; + dev_dbg(&intf->dev, "Trying to find if device Vendor 0x%04X Product 0x%04X has the RIGOL quirk\n", + le16_to_cpu(data->usb_dev->descriptor.idVendor), + le16_to_cpu(data->usb_dev->descriptor.idProduct)); + for(n = 0; usbtmc_id_quirk[n].idVendor > 0; n++) { + if ((usbtmc_id_quirk[n].idVendor == le16_to_cpu(data->usb_dev->descriptor.idVendor)) && + (usbtmc_id_quirk[n].idProduct == le16_to_cpu(data->usb_dev->descriptor.idProduct))) { + dev_dbg(&intf->dev, "Setting this device as having the RIGOL quirk\n"); + data->rigol_quirk = 1; + break; + } + } /* Initialize USBTMC bTag and other fields */ data->bTag = 1; @@ -1055,31 +1200,32 @@ static void usbtmc_disconnect(struct usb_interface *intf) usb_deregister_dev(intf, &usbtmc_class); sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp); sysfs_remove_group(&intf->dev.kobj, &data_attr_grp); + mutex_lock(&data->io_mutex); + data->zombie = 1; + mutex_unlock(&data->io_mutex); kref_put(&data->kref, usbtmc_delete); } +static int usbtmc_suspend(struct usb_interface *intf, pm_message_t message) +{ + /* this driver does not have pending URBs */ + return 0; +} + +static int usbtmc_resume(struct usb_interface *intf) +{ + return 0; +} + static struct usb_driver usbtmc_driver = { .name = "usbtmc", .id_table = usbtmc_devices, .probe = usbtmc_probe, - .disconnect = usbtmc_disconnect + .disconnect = usbtmc_disconnect, + .suspend = usbtmc_suspend, + .resume = usbtmc_resume, }; -static int __init usbtmc_init(void) -{ - int retcode; - - retcode = usb_register(&usbtmc_driver); - if (retcode) - printk(KERN_ERR KBUILD_MODNAME": Unable to register driver\n"); - return retcode; -} -module_init(usbtmc_init); - -static void __exit usbtmc_exit(void) -{ - usb_deregister(&usbtmc_driver); -} -module_exit(usbtmc_exit); +module_usb_driver(usbtmc_driver); MODULE_LICENSE("GPL"); |
