diff options
Diffstat (limited to 'drivers/usb/misc')
-rw-r--r-- | drivers/usb/misc/Kconfig | 25 | ||||
-rw-r--r-- | drivers/usb/misc/Makefile | 2 | ||||
-rw-r--r-- | drivers/usb/misc/adutux.c | 8 | ||||
-rw-r--r-- | drivers/usb/misc/appledisplay.c | 5 | ||||
-rw-r--r-- | drivers/usb/misc/berry_charge.c | 183 | ||||
-rw-r--r-- | drivers/usb/misc/cypress_cy7c63.c | 2 | ||||
-rw-r--r-- | drivers/usb/misc/cytherm.c | 2 | ||||
-rw-r--r-- | drivers/usb/misc/emi26.c | 2 | ||||
-rw-r--r-- | drivers/usb/misc/emi62.c | 2 | ||||
-rw-r--r-- | drivers/usb/misc/ftdi-elan.c | 11 | ||||
-rw-r--r-- | drivers/usb/misc/idmouse.c | 2 | ||||
-rw-r--r-- | drivers/usb/misc/iowarrior.c | 6 | ||||
-rw-r--r-- | drivers/usb/misc/isight_firmware.c | 4 | ||||
-rw-r--r-- | drivers/usb/misc/ldusb.c | 4 | ||||
-rw-r--r-- | drivers/usb/misc/legousbtower.c | 13 | ||||
-rw-r--r-- | drivers/usb/misc/rio500.c | 11 | ||||
-rw-r--r-- | drivers/usb/misc/sisusbvga/sisusb.c | 20 | ||||
-rw-r--r-- | drivers/usb/misc/trancevibrator.c | 2 | ||||
-rw-r--r-- | drivers/usb/misc/usblcd.c | 7 | ||||
-rw-r--r-- | drivers/usb/misc/usbled.c | 2 | ||||
-rw-r--r-- | drivers/usb/misc/usbsevseg.c | 2 | ||||
-rw-r--r-- | drivers/usb/misc/usbtest.c | 6 | ||||
-rw-r--r-- | drivers/usb/misc/uss720.c | 2 | ||||
-rw-r--r-- | drivers/usb/misc/vstusb.c | 783 |
24 files changed, 71 insertions, 1035 deletions
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index abe3aa6..55660ea 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -87,17 +87,6 @@ config USB_LCD To compile this driver as a module, choose M here: the module will be called usblcd. -config USB_BERRY_CHARGE - tristate "USB BlackBerry recharge support" - depends on USB - help - Say Y here if you want to connect a BlackBerry device to your - computer's USB port and have it automatically switch to "recharge" - mode. - - To compile this driver as a module, choose M here: the - module will be called berry_charge. - config USB_LED tristate "USB LED driver support" depends on USB @@ -242,17 +231,3 @@ config USB_ISIGHTFW driver beforehand. Tools for doing so are available at http://bersace03.free.fr -config USB_VST - tristate "USB VST driver" - depends on USB - help - This driver is intended for Vernier Software Technologies - bulk usb devices such as their Ocean-Optics spectrometers or - Labquest. - It is a bulk channel driver with configurable read and write - timeouts. - - To compile this driver as a module, choose M here: the - module will be called vstusb. - - diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 0826aab..717703e 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -5,7 +5,6 @@ obj-$(CONFIG_USB_ADUTUX) += adutux.o obj-$(CONFIG_USB_APPLEDISPLAY) += appledisplay.o -obj-$(CONFIG_USB_BERRY_CHARGE) += berry_charge.o obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o obj-$(CONFIG_USB_CYTHERM) += cytherm.o obj-$(CONFIG_USB_EMI26) += emi26.o @@ -23,7 +22,6 @@ obj-$(CONFIG_USB_TEST) += usbtest.o obj-$(CONFIG_USB_TRANCEVIBRATOR) += trancevibrator.o obj-$(CONFIG_USB_USS720) += uss720.o obj-$(CONFIG_USB_SEVSEG) += usbsevseg.o -obj-$(CONFIG_USB_VST) += vstusb.o obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index 2035265..d240de0 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -38,7 +38,7 @@ static int debug = 1; #define dbg(lvl, format, arg...) \ do { \ if (debug >= lvl) \ - printk(KERN_DEBUG __FILE__ " : " format " \n", ## arg); \ + printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg); \ } while (0) @@ -56,7 +56,7 @@ MODULE_PARM_DESC(debug, "Debug enabled or not"); #define ADU_PRODUCT_ID 0x0064 /* table of devices that work with this driver */ -static struct usb_device_id device_table [] = { +static const struct usb_device_id device_table[] = { { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID) }, /* ADU100 */ { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+20) }, /* ADU120 */ { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+30) }, /* ADU130 */ @@ -132,8 +132,8 @@ static void adu_debug_data(int level, const char *function, int size, if (debug < level) return; - printk(KERN_DEBUG __FILE__": %s - length = %d, data = ", - function, size); + printk(KERN_DEBUG "%s: %s - length = %d, data = ", + __FILE__, function, size); for (i = 0; i < size; ++i) printk("%.2x ", data[i]); printk("\n"); diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index 1eb9e41..4d2952f 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -57,7 +57,7 @@ .bInterfaceProtocol = 0x00 /* table of devices that work with this driver */ -static struct usb_device_id appledisplay_table [] = { +static const struct usb_device_id appledisplay_table[] = { { APPLEDISPLAY_DEVICE(0x9218) }, { APPLEDISPLAY_DEVICE(0x9219) }, { APPLEDISPLAY_DEVICE(0x921c) }, @@ -179,7 +179,7 @@ static int appledisplay_bl_get_brightness(struct backlight_device *bd) return pdata->msgdata[1]; } -static struct backlight_ops appledisplay_bl_data = { +static const struct backlight_ops appledisplay_bl_data = { .get_brightness = appledisplay_bl_get_brightness, .update_status = appledisplay_bl_update_status, }; @@ -283,6 +283,7 @@ static int appledisplay_probe(struct usb_interface *iface, &appledisplay_bl_data); if (IS_ERR(pdata->bd)) { dev_err(&iface->dev, "Backlight registration failed\n"); + retval = PTR_ERR(pdata->bd); goto error; } diff --git a/drivers/usb/misc/berry_charge.c b/drivers/usb/misc/berry_charge.c deleted file mode 100644 index c05a85b..0000000 --- a/drivers/usb/misc/berry_charge.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * USB BlackBerry charging module - * - * Copyright (C) 2007 Greg Kroah-Hartman <gregkh@suse.de> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - * Information on how to switch configs was taken by the bcharge.cc file - * created by the barry.sf.net project. - * - * bcharge.cc has the following copyright: - * Copyright (C) 2006, Net Direct Inc. (http://www.netdirect.ca/) - * and is released under the GPLv2. - * - * - */ - -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/usb.h> - -#define RIM_VENDOR 0x0fca -#define BLACKBERRY 0x0001 -#define BLACKBERRY_PEARL_DUAL 0x0004 -#define BLACKBERRY_PEARL 0x0006 - -static int debug; -static int pearl_dual_mode = 1; - -#ifdef dbg -#undef dbg -#endif -#define dbg(dev, format, arg...) \ - if (debug) \ - dev_printk(KERN_DEBUG , dev , format , ## arg) - -static struct usb_device_id id_table [] = { - { USB_DEVICE(RIM_VENDOR, BLACKBERRY) }, - { USB_DEVICE(RIM_VENDOR, BLACKBERRY_PEARL) }, - { USB_DEVICE(RIM_VENDOR, BLACKBERRY_PEARL_DUAL) }, - { }, /* Terminating entry */ -}; -MODULE_DEVICE_TABLE(usb, id_table); - -static int magic_charge(struct usb_device *udev) -{ - char *dummy_buffer = kzalloc(2, GFP_KERNEL); - int retval; - - if (!dummy_buffer) - return -ENOMEM; - - /* send two magic commands and then set the configuration. The device - * will then reset itself with the new power usage and should start - * charging. */ - - /* Note, with testing, it only seems that the first message is really - * needed (at least for the 8700c), but to be safe, we emulate what - * other operating systems seem to be sending to their device. We - * really need to get some specs for this device to be sure about what - * is going on here. - */ - dbg(&udev->dev, "Sending first magic command\n"); - retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - 0xa5, 0xc0, 0, 1, dummy_buffer, 2, 100); - if (retval != 2) { - dev_err(&udev->dev, "First magic command failed: %d.\n", - retval); - goto exit; - } - - dbg(&udev->dev, "Sending second magic command\n"); - retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - 0xa2, 0x40, 0, 1, dummy_buffer, 0, 100); - if (retval != 0) { - dev_err(&udev->dev, "Second magic command failed: %d.\n", - retval); - goto exit; - } - - dbg(&udev->dev, "Calling set_configuration\n"); - retval = usb_driver_set_configuration(udev, 1); - if (retval) - dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval); - -exit: - kfree(dummy_buffer); - return retval; -} - -static int magic_dual_mode(struct usb_device *udev) -{ - char *dummy_buffer = kzalloc(2, GFP_KERNEL); - int retval; - - if (!dummy_buffer) - return -ENOMEM; - - /* send magic command so that the Blackberry Pearl device exposes - * two interfaces: both the USB mass-storage one and one which can - * be used for database access. */ - dbg(&udev->dev, "Sending magic pearl command\n"); - retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - 0xa9, 0xc0, 1, 1, dummy_buffer, 2, 100); - dbg(&udev->dev, "Magic pearl command returned %d\n", retval); - - dbg(&udev->dev, "Calling set_configuration\n"); - retval = usb_driver_set_configuration(udev, 1); - if (retval) - dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval); - - kfree(dummy_buffer); - return retval; -} - -static int berry_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - - if (udev->bus_mA < 500) { - dbg(&udev->dev, "Not enough power to charge available\n"); - return -ENODEV; - } - - dbg(&udev->dev, "Power is set to %dmA\n", - udev->actconfig->desc.bMaxPower * 2); - - /* check the power usage so we don't try to enable something that is - * already enabled */ - if ((udev->actconfig->desc.bMaxPower * 2) == 500) { - dbg(&udev->dev, "device is already charging, power is " - "set to %dmA\n", udev->actconfig->desc.bMaxPower * 2); - return -ENODEV; - } - - /* turn the power on */ - magic_charge(udev); - - if ((le16_to_cpu(udev->descriptor.idProduct) == BLACKBERRY_PEARL) && - (pearl_dual_mode)) - magic_dual_mode(udev); - - /* we don't really want to bind to the device, userspace programs can - * handle the syncing just fine, so get outta here. */ - return -ENODEV; -} - -static void berry_disconnect(struct usb_interface *intf) -{ -} - -static struct usb_driver berry_driver = { - .name = "berry_charge", - .probe = berry_probe, - .disconnect = berry_disconnect, - .id_table = id_table, -}; - -static int __init berry_init(void) -{ - return usb_register(&berry_driver); -} - -static void __exit berry_exit(void) -{ - usb_deregister(&berry_driver); -} - -module_init(berry_init); -module_exit(berry_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>"); -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -module_param(pearl_dual_mode, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(pearl_dual_mode, "Change Blackberry Pearl to run in dual mode"); diff --git a/drivers/usb/misc/cypress_cy7c63.c b/drivers/usb/misc/cypress_cy7c63.c index 5720bfe..1547d8c 100644 --- a/drivers/usb/misc/cypress_cy7c63.c +++ b/drivers/usb/misc/cypress_cy7c63.c @@ -56,7 +56,7 @@ /* table of devices that work with this driver */ -static struct usb_device_id cypress_table [] = { +static const struct usb_device_id cypress_table[] = { { USB_DEVICE(CYPRESS_VENDOR_ID, CYPRESS_PRODUCT_ID) }, { } }; diff --git a/drivers/usb/misc/cytherm.c b/drivers/usb/misc/cytherm.c index 4fb3c38..b9cbbbd 100644 --- a/drivers/usb/misc/cytherm.c +++ b/drivers/usb/misc/cytherm.c @@ -27,7 +27,7 @@ #define USB_SKEL_VENDOR_ID 0x04b4 #define USB_SKEL_PRODUCT_ID 0x0002 -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) }, { } }; diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c index 879a980..a6521c9 100644 --- a/drivers/usb/misc/emi26.c +++ b/drivers/usb/misc/emi26.c @@ -245,7 +245,7 @@ wraperr: return err; } -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(EMI26_VENDOR_ID, EMI26_PRODUCT_ID) }, { USB_DEVICE(EMI26_VENDOR_ID, EMI26B_PRODUCT_ID) }, { } /* Terminating entry */ diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c index 59860b3..fc15ad4 100644 --- a/drivers/usb/misc/emi62.c +++ b/drivers/usb/misc/emi62.c @@ -259,7 +259,7 @@ wraperr: return err; } -static __devinitdata struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] __devinitconst = { { USB_DEVICE(EMI62_VENDOR_ID, EMI62_PRODUCT_ID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 9d0675e..1edb6d3 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -86,7 +86,7 @@ static struct list_head ftdi_static_list; #define USB_FTDI_ELAN_VENDOR_ID 0x0403 #define USB_FTDI_ELAN_PRODUCT_ID 0xd6ea /* table of devices that work with this driver*/ -static struct usb_device_id ftdi_elan_table[] = { +static const struct usb_device_id ftdi_elan_table[] = { {USB_DEVICE(USB_FTDI_ELAN_VENDOR_ID, USB_FTDI_ELAN_PRODUCT_ID)}, { /* Terminating entry */ } }; @@ -623,9 +623,12 @@ static void ftdi_elan_status_work(struct work_struct *work) */ static int ftdi_elan_open(struct inode *inode, struct file *file) { - int subminor = iminor(inode); - struct usb_interface *interface = usb_find_interface(&ftdi_elan_driver, - subminor); + int subminor; + struct usb_interface *interface; + + subminor = iminor(inode); + interface = usb_find_interface(&ftdi_elan_driver, subminor); + if (!interface) { printk(KERN_ERR "can't find device for minor %d\n", subminor); return -ENODEV; diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c index 1337a9c..a54c3cb 100644 --- a/drivers/usb/misc/idmouse.c +++ b/drivers/usb/misc/idmouse.c @@ -48,7 +48,7 @@ #define ID_CHERRY 0x0010 /* device ID table */ -static struct usb_device_id idmouse_table[] = { +static const struct usb_device_id idmouse_table[] = { {USB_DEVICE(ID_SIEMENS, ID_IDMOUSE)}, /* Siemens ID Mouse (Professional) */ {USB_DEVICE(ID_SIEMENS, ID_CHERRY )}, /* Cherry FingerTIP ID Board */ {} /* terminating null entry */ diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index e75bb87..d3c8523 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -139,7 +139,7 @@ static int usb_set_report(struct usb_interface *intf, unsigned char type, /* driver registration */ /*---------------------*/ /* table of devices that work with this driver */ -static struct usb_device_id iowarrior_ids[] = { +static const struct usb_device_id iowarrior_ids[] = { {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40)}, {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24)}, {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOWPV1)}, @@ -602,10 +602,12 @@ static int iowarrior_open(struct inode *inode, struct file *file) dbg("%s", __func__); + lock_kernel(); subminor = iminor(inode); interface = usb_find_interface(&iowarrior_driver, subminor); if (!interface) { + unlock_kernel(); err("%s - error, can't find device for minor %d", __func__, subminor); return -ENODEV; @@ -615,6 +617,7 @@ static int iowarrior_open(struct inode *inode, struct file *file) dev = usb_get_intfdata(interface); if (!dev) { mutex_unlock(&iowarrior_open_disc_lock); + unlock_kernel(); return -ENODEV; } @@ -641,6 +644,7 @@ static int iowarrior_open(struct inode *inode, struct file *file) out: mutex_unlock(&dev->mutex); + unlock_kernel(); return retval; } diff --git a/drivers/usb/misc/isight_firmware.c b/drivers/usb/misc/isight_firmware.c index b897f65..06e990a 100644 --- a/drivers/usb/misc/isight_firmware.c +++ b/drivers/usb/misc/isight_firmware.c @@ -26,7 +26,7 @@ #include <linux/errno.h> #include <linux/module.h> -static struct usb_device_id id_table[] = { +static const struct usb_device_id id_table[] = { {USB_DEVICE(0x05ac, 0x8300)}, {}, }; @@ -112,6 +112,8 @@ out: return ret; } +MODULE_FIRMWARE("isight.fw"); + static void isight_firmware_disconnect(struct usb_interface *intf) { } diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index 90f1301..dd41d87 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -69,7 +69,7 @@ #endif /* table of devices that work with this driver */ -static struct usb_device_id ld_usb_table [] = { +static const struct usb_device_id ld_usb_table[] = { { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) }, { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) }, { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY) }, @@ -798,7 +798,7 @@ static int __init ld_usb_init(void) /* register this driver with the USB subsystem */ retval = usb_register(&ld_usb_driver); if (retval) - err("usb_register failed for the "__FILE__" driver. Error number %d\n", retval); + err("usb_register failed for the %s driver. Error number %d\n", __FILE__, retval); return retval; } diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index faa6d62..8547bf9 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -95,8 +95,11 @@ /* Use our own dbg macro */ #undef dbg -#define dbg(lvl, format, arg...) do { if (debug >= lvl) printk(KERN_DEBUG __FILE__ ": " format "\n", ## arg); } while (0) - +#define dbg(lvl, format, arg...) \ +do { \ + if (debug >= lvl) \ + printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg); \ +} while (0) /* Version Information */ #define DRIVER_VERSION "v0.96" @@ -192,7 +195,7 @@ struct tower_get_version_reply { /* table of devices that work with this driver */ -static struct usb_device_id tower_table [] = { +static const struct usb_device_id tower_table[] = { { USB_DEVICE(LEGO_USB_TOWER_VENDOR_ID, LEGO_USB_TOWER_PRODUCT_ID) }, { } /* Terminating entry */ }; @@ -302,7 +305,7 @@ static inline void lego_usb_tower_debug_data (int level, const char *function, i if (debug < level) return; - printk (KERN_DEBUG __FILE__": %s - length = %d, data = ", function, size); + printk (KERN_DEBUG "%s: %s - length = %d, data = ", __FILE__, function, size); for (i = 0; i < size; ++i) { printk ("%.2x ", data[i]); } @@ -1055,7 +1058,7 @@ static int __init lego_usb_tower_init(void) /* register this driver with the USB subsystem */ result = usb_register(&tower_driver); if (result < 0) { - err("usb_register failed for the "__FILE__" driver. Error number %d", result); + err("usb_register failed for the %s driver. Error number %d", __FILE__, result); retval = -1; goto exit; } diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c index 32d0199..a85771b 100644 --- a/drivers/usb/misc/rio500.c +++ b/drivers/usb/misc/rio500.c @@ -78,10 +78,13 @@ static int open_rio(struct inode *inode, struct file *file) { struct rio_usb_data *rio = &rio_instance; + /* against disconnect() */ + lock_kernel(); mutex_lock(&(rio->lock)); if (rio->isopen || !rio->present) { mutex_unlock(&(rio->lock)); + unlock_kernel(); return -EBUSY; } rio->isopen = 1; @@ -91,6 +94,7 @@ static int open_rio(struct inode *inode, struct file *file) mutex_unlock(&(rio->lock)); dev_info(&rio->rio_dev->dev, "Rio opened.\n"); + unlock_kernel(); return 0; } @@ -115,7 +119,6 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg) int retries; int retval=0; - lock_kernel(); mutex_lock(&(rio->lock)); /* Sanity check to make sure rio is connected, powered, etc */ if (rio->present == 0 || rio->rio_dev == NULL) { @@ -254,7 +257,6 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg) err_out: mutex_unlock(&(rio->lock)); - unlock_kernel(); return retval; } @@ -489,6 +491,7 @@ static void disconnect_rio(struct usb_interface *intf) struct rio_usb_data *rio = usb_get_intfdata (intf); usb_set_intfdata (intf, NULL); + lock_kernel(); if (rio) { usb_deregister_dev(intf, &usb_rio_class); @@ -498,6 +501,7 @@ static void disconnect_rio(struct usb_interface *intf) /* better let it finish - the release will do whats needed */ rio->rio_dev = NULL; mutex_unlock(&(rio->lock)); + unlock_kernel(); return; } kfree(rio->ibuf); @@ -508,9 +512,10 @@ static void disconnect_rio(struct usb_interface *intf) rio->present = 0; mutex_unlock(&(rio->lock)); } + unlock_kernel(); } -static struct usb_device_id rio_table [] = { +static const struct usb_device_id rio_table[] = { { USB_DEVICE(0x0841, 1) }, /* Rio 500 */ { } /* Terminating entry */ }; diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 8b37a4b..aae95a0 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -250,7 +250,7 @@ sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe, sisusb->urbstatus[index] |= SU_URB_BUSY; /* Submit URB */ - retval = usb_submit_urb(urb, GFP_ATOMIC); + retval = usb_submit_urb(urb, GFP_KERNEL); /* If OK, and if timeout > 0, wait for completion */ if ((retval == 0) && timeout) { @@ -306,7 +306,7 @@ sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data, urb->actual_length = 0; sisusb->completein = 0; - retval = usb_submit_urb(urb, GFP_ATOMIC); + retval = usb_submit_urb(urb, GFP_KERNEL); if (retval == 0) { wait_event_timeout(sisusb->wait_q, sisusb->completein, timeout); if (!sisusb->completein) { @@ -2416,21 +2416,28 @@ sisusb_open(struct inode *inode, struct file *file) struct usb_interface *interface; int subminor = iminor(inode); - if (!(interface = usb_find_interface(&sisusb_driver, subminor))) + lock_kernel(); + if (!(interface = usb_find_interface(&sisusb_driver, subminor))) { + unlock_kernel(); return -ENODEV; + } - if (!(sisusb = usb_get_intfdata(interface))) + if (!(sisusb = usb_get_intfdata(interface))) { + unlock_kernel(); return -ENODEV; + } mutex_lock(&sisusb->lock); if (!sisusb->present || !sisusb->ready) { mutex_unlock(&sisusb->lock); + unlock_kernel(); return -ENODEV; } if (sisusb->isopen) { mutex_unlock(&sisusb->lock); + unlock_kernel(); return -EBUSY; } @@ -2439,11 +2446,13 @@ sisusb_open(struct inode *inode, struct file *file) if (sisusb_init_gfxdevice(sisusb, 0)) { mutex_unlock(&sisusb->lock); dev_err(&sisusb->sisusb_dev->dev, "Failed to initialize device\n"); + unlock_kernel(); return -EIO; } } else { mutex_unlock(&sisusb->lock); dev_err(&sisusb->sisusb_dev->dev, "Device not attached to USB 2.0 hub\n"); + unlock_kernel(); return -EIO; } } @@ -2456,6 +2465,7 @@ sisusb_open(struct inode *inode, struct file *file) file->private_data = sisusb; mutex_unlock(&sisusb->lock); + unlock_kernel(); return 0; } @@ -3238,7 +3248,7 @@ static void sisusb_disconnect(struct usb_interface *intf) kref_put(&sisusb->kref, sisusb_delete); } -static struct usb_device_id sisusb_table [] = { +static const struct usb_device_id sisusb_table[] = { { USB_DEVICE(0x0711, 0x0550) }, { USB_DEVICE(0x0711, 0x0900) }, { USB_DEVICE(0x0711, 0x0901) }, diff --git a/drivers/usb/misc/trancevibrator.c b/drivers/usb/misc/trancevibrator.c index 2e14102..5da28ea 100644 --- a/drivers/usb/misc/trancevibrator.c +++ b/drivers/usb/misc/trancevibrator.c @@ -33,7 +33,7 @@ #define TRANCEVIBRATOR_VENDOR_ID 0x0b49 /* ASCII Corporation */ #define TRANCEVIBRATOR_PRODUCT_ID 0x064f /* Trance Vibrator */ -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(TRANCEVIBRATOR_VENDOR_ID, TRANCEVIBRATOR_PRODUCT_ID) }, { }, }; diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c index 4fb1203..90aede9 100644 --- a/drivers/usb/misc/usblcd.c +++ b/drivers/usb/misc/usblcd.c @@ -30,7 +30,7 @@ #define IOCTL_GET_DRV_VERSION 2 -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { .idVendor = 0x10D2, .match_flags = USB_DEVICE_ID_MATCH_VENDOR, }, { }, }; @@ -74,10 +74,12 @@ static int lcd_open(struct inode *inode, struct file *file) struct usb_interface *interface; int subminor, r; + lock_kernel(); subminor = iminor(inode); interface = usb_find_interface(&lcd_driver, subminor); if (!interface) { + unlock_kernel(); err ("USBLCD: %s - error, can't find device for minor %d", __func__, subminor); return -ENODEV; @@ -87,6 +89,7 @@ static int lcd_open(struct inode *inode, struct file *file) dev = usb_get_intfdata(interface); if (!dev) { mutex_unlock(&open_disc_mutex); + unlock_kernel(); return -ENODEV; } @@ -98,11 +101,13 @@ static int lcd_open(struct inode *inode, struct file *file) r = usb_autopm_get_interface(interface); if (r < 0) { kref_put(&dev->kref, lcd_delete); + unlock_kernel(); return r; } /* save our object in the file's private structure */ file->private_data = dev; + unlock_kernel(); return 0; } diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c index 06cb719..63da2c3 100644 --- a/drivers/usb/misc/usbled.c +++ b/drivers/usb/misc/usbled.c @@ -24,7 +24,7 @@ #define PRODUCT_ID 0x1223 /* table of devices that work with this driver */ -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(VENDOR_ID, PRODUCT_ID) }, { }, }; diff --git a/drivers/usb/misc/usbsevseg.c b/drivers/usb/misc/usbsevseg.c index 3db2555..a9555cb 100644 --- a/drivers/usb/misc/usbsevseg.c +++ b/drivers/usb/misc/usbsevseg.c @@ -27,7 +27,7 @@ #define MAXLEN 6 /* table of devices that work with this driver */ -static struct usb_device_id id_table[] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(VENDOR_ID, PRODUCT_ID) }, { }, }; diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 3dab0c0..a21cce6 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -1580,10 +1580,6 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) return -ERESTARTSYS; /* FIXME: What if a system sleep starts while a test is running? */ - if (!intf->is_active) { - mutex_unlock(&dev->lock); - return -EHOSTUNREACH; - } /* some devices, like ez-usb default devices, need a non-default * altsetting to have any active endpoints. some tests change @@ -2101,7 +2097,7 @@ static struct usbtest_info generic_info = { #endif -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { /*-------------------------------------------------------------*/ diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c index 9a6c27a..f56fed5 100644 --- a/drivers/usb/misc/uss720.c +++ b/drivers/usb/misc/uss720.c @@ -770,7 +770,7 @@ static void uss720_disconnect(struct usb_interface *intf) } /* table of cables that work through this driver */ -static struct usb_device_id uss720_table [] = { +static const struct usb_device_id uss720_table[] = { { USB_DEVICE(0x047e, 0x1001) }, { USB_DEVICE(0x0557, 0x2001) }, { USB_DEVICE(0x0729, 0x1284) }, diff --git a/drivers/usb/misc/vstusb.c b/drivers/usb/misc/vstusb.c deleted file mode 100644 index f26ea8d..0000000 --- a/drivers/usb/misc/vstusb.c +++ /dev/null @@ -1,783 +0,0 @@ -/***************************************************************************** - * File: drivers/usb/misc/vstusb.c - * - * Purpose: Support for the bulk USB Vernier Spectrophotometers - * - * Author: Johnnie Peters - * Axian Consulting - * Beaverton, OR, USA 97005 - * - * Modified by: EQware Engineering, Inc. - * Oregon City, OR, USA 97045 - * - * Copyright: 2007, 2008 - * Vernier Software & Technology - * Beaverton, OR, USA 97005 - * - * Web: www.vernier.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - *****************************************************************************/ -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/mutex.h> -#include <linux/uaccess.h> -#include <linux/usb.h> - -#include <linux/usb/vstusb.h> - -#define DRIVER_VERSION "VST USB Driver Version 1.5" -#define DRIVER_DESC "Vernier Software Technology Bulk USB Driver" - -#ifdef CONFIG_USB_DYNAMIC_MINORS - #define VSTUSB_MINOR_BASE 0 -#else - #define VSTUSB_MINOR_BASE 199 -#endif - -#define USB_VENDOR_OCEANOPTICS 0x2457 -#define USB_VENDOR_VERNIER 0x08F7 /* Vernier Software & Technology */ - -#define USB_PRODUCT_USB2000 0x1002 -#define USB_PRODUCT_ADC1000_FW 0x1003 /* firmware download (renumerates) */ -#define USB_PRODUCT_ADC1000 0x1004 -#define USB_PRODUCT_HR2000_FW 0x1009 /* firmware download (renumerates) */ -#define USB_PRODUCT_HR2000 0x100A -#define USB_PRODUCT_HR4000_FW 0x1011 /* firmware download (renumerates) */ -#define USB_PRODUCT_HR4000 0x1012 -#define USB_PRODUCT_USB650 0x1014 /* "Red Tide" */ -#define USB_PRODUCT_QE65000 0x1018 -#define USB_PRODUCT_USB4000 0x1022 -#define USB_PRODUCT_USB325 0x1024 /* "Vernier Spectrometer" */ - -#define USB_PRODUCT_LABPRO 0x0001 -#define USB_PRODUCT_LABQUEST 0x0005 - -#define VST_MAXBUFFER (64*1024) - -static struct usb_device_id id_table[] = { - { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB2000)}, - { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_HR4000)}, - { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB650)}, - { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB4000)}, - { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB325)}, - { USB_DEVICE(USB_VENDOR_VERNIER, USB_PRODUCT_LABQUEST)}, - { USB_DEVICE(USB_VENDOR_VERNIER, USB_PRODUCT_LABPRO)}, - {}, -}; - -MODULE_DEVICE_TABLE(usb, id_table); - -struct vstusb_device { - struct kref kref; - struct mutex lock; - struct usb_device *usb_dev; - char present; - char isopen; - struct usb_anchor submitted; - int rd_pipe; - int rd_timeout_ms; - int wr_pipe; - int wr_timeout_ms; -}; -#define to_vst_dev(d) container_of(d, struct vstusb_device, kref) - -static struct usb_driver vstusb_driver; - -static void vstusb_delete(struct kref *kref) -{ - struct vstusb_device *vstdev = to_vst_dev(kref); - - usb_put_dev(vstdev->usb_dev); - kfree(vstdev); -} - -static int vstusb_open(struct inode *inode, struct file *file) -{ - struct vstusb_device *vstdev; - struct usb_interface *interface; - - interface = usb_find_interface(&vstusb_driver, iminor(inode)); - - if (!interface) { - printk(KERN_ERR KBUILD_MODNAME - ": %s - error, can't find device for minor %d\n", - __func__, iminor(inode)); - return -ENODEV; - } - - vstdev = usb_get_intfdata(interface); - - if (!vstdev) - return -ENODEV; - - /* lock this device */ - mutex_lock(&vstdev->lock); - - /* can only open one time */ - if ((!vstdev->present) || (vstdev->isopen)) { - mutex_unlock(&vstdev->lock); - return -EBUSY; - } - - /* increment our usage count */ - kref_get(&vstdev->kref); - - vstdev->isopen = 1; - - /* save device in the file's private structure */ - file->private_data = vstdev; - - dev_dbg(&vstdev->usb_dev->dev, "%s: opened\n", __func__); - - mutex_unlock(&vstdev->lock); - - return 0; -} - -static int vstusb_release(struct inode *inode, struct file *file) -{ - struct vstusb_device *vstdev; - - vstdev = file->private_data; - - if (vstdev == NULL) - return -ENODEV; - - mutex_lock(&vstdev->lock); - - vstdev->isopen = 0; - - dev_dbg(&vstdev->usb_dev->dev, "%s: released\n", __func__); - - mutex_unlock(&vstdev->lock); - - kref_put(&vstdev->kref, vstusb_delete); - - return 0; -} - -static void usb_api_blocking_completion(struct urb *urb) -{ - struct completion *completeit = urb->context; - - complete(completeit); -} - -static int vstusb_fill_and_send_urb(struct urb *urb, - struct usb_device *usb_dev, - unsigned int pipe, void *data, - unsigned int len, struct completion *done) -{ - struct usb_host_endpoint *ep; - struct usb_host_endpoint **hostep; - unsigned int pipend; - - int status; - - hostep = usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out; - pipend = usb_pipeendpoint(pipe); - ep = hostep[pipend]; - - if (!ep || (len == 0)) - return -EINVAL; - - if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_INT) { - pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30); - usb_fill_int_urb(urb, usb_dev, pipe, data, len, - (usb_complete_t)usb_api_blocking_completion, - NULL, ep->desc.bInterval); - } else - usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, - (usb_complete_t)usb_api_blocking_completion, - NULL); - - init_completion(done); - urb->context = done; - urb->actual_length = 0; - status = usb_submit_urb(urb, GFP_KERNEL); - - return status; -} - -static int vstusb_complete_urb(struct urb *urb, struct completion *done, - int timeout, int *actual_length) -{ - unsigned long expire; - int status; - - expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT; - if (!wait_for_completion_interruptible_timeout(done, expire)) { - usb_kill_urb(urb); - status = urb->status == -ENOENT ? -ETIMEDOUT : urb->status; - - dev_dbg(&urb->dev->dev, - "%s timed out on ep%d%s len=%d/%d, urb status = %d\n", - current->comm, - usb_pipeendpoint(urb->pipe), - usb_pipein(urb->pipe) ? "in" : "out", - urb->actual_length, - urb->transfer_buffer_length, - urb->status); - - } else { - if (signal_pending(current)) { - /* if really an error */ - if (urb->status && !((urb->status == -ENOENT) || - (urb->status == -ECONNRESET) || - (urb->status == -ESHUTDOWN))) { - status = -EINTR; - usb_kill_urb(urb); - } else { - status = 0; - } - - dev_dbg(&urb->dev->dev, - "%s: signal pending on ep%d%s len=%d/%d," - "urb status = %d\n", - current->comm, - usb_pipeendpoint(urb->pipe), - usb_pipein(urb->pipe) ? "in" : "out", - urb->actual_length, - urb->transfer_buffer_length, - urb->status); - - } else { - status = urb->status; - } - } - - if (actual_length) - *actual_length = urb->actual_length; - - return status; -} - -static ssize_t vstusb_read(struct file *file, char __user *buffer, - size_t count, loff_t *ppos) -{ - struct vstusb_device *vstdev; - int cnt = -1; - void *buf; - int retval = 0; - - struct urb *urb; - struct usb_device *dev; - unsigned int pipe; - int timeout; - - DECLARE_COMPLETION_ONSTACK(done); - - vstdev = file->private_data; - - if (vstdev == NULL) - return -ENODEV; - - /* verify that we actually want to read some data */ - if ((count == 0) || (count > VST_MAXBUFFER)) - return -EINVAL; - - /* lock this object */ - if (mutex_lock_interruptible(&vstdev->lock)) - return -ERESTARTSYS; - - /* anyone home */ - if (!vstdev->present) { - mutex_unlock(&vstdev->lock); - printk(KERN_ERR KBUILD_MODNAME - ": %s: device not present\n", __func__); - return -ENODEV; - } - - /* pull out the necessary data */ - dev = vstdev->usb_dev; - pipe = usb_rcvbulkpipe(dev, vstdev->rd_pipe); - timeout = vstdev->rd_timeout_ms; - - buf = kmalloc(count, GFP_KERNEL); - if (buf == NULL) { - mutex_unlock(&vstdev->lock); - return -ENOMEM; - } - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - kfree(buf); - mutex_unlock(&vstdev->lock); - return -ENOMEM; - } - - usb_anchor_urb(urb, &vstdev->submitted); - retval = vstusb_fill_and_send_urb(urb, dev, pipe, buf, count, &done); - mutex_unlock(&vstdev->lock); - if (retval) { - usb_unanchor_urb(urb); - dev_err(&dev->dev, "%s: error %d filling and sending urb %d\n", - __func__, retval, pipe); - goto exit; - } - - retval = vstusb_complete_urb(urb, &done, timeout, &cnt); - if (retval) { - dev_err(&dev->dev, "%s: error %d completing urb %d\n", - __func__, retval, pipe); - goto exit; - } - - if (copy_to_user(buffer, buf, cnt)) { - dev_err(&dev->dev, "%s: can't copy_to_user\n", __func__); - retval = -EFAULT; - } else { - retval = cnt; - dev_dbg(&dev->dev, "%s: read %d bytes from pipe %d\n", - __func__, cnt, pipe); - } - -exit: - usb_free_urb(urb); - kfree(buf); - return retval; -} - -static ssize_t vstusb_write(struct file *file, const char __user *buffer, - size_t count, loff_t *ppos) -{ - struct vstusb_device *vstdev; - int cnt = -1; - void *buf; - int retval = 0; - - struct urb *urb; - struct usb_device *dev; - unsigned int pipe; - int timeout; - - DECLARE_COMPLETION_ONSTACK(done); - - vstdev = file->private_data; - - if (vstdev == NULL) - return -ENODEV; - - /* verify that we actually have some data to write */ - if ((count == 0) || (count > VST_MAXBUFFER)) - return retval; - - /* lock this object */ - if (mutex_lock_interruptible(&vstdev->lock)) - return -ERESTARTSYS; - - /* anyone home */ - if (!vstdev->present) { - mutex_unlock(&vstdev->lock); - printk(KERN_ERR KBUILD_MODNAME - ": %s: device not present\n", __func__); - return -ENODEV; - } - - /* pull out the necessary data */ - dev = vstdev->usb_dev; - pipe = usb_sndbulkpipe(dev, vstdev->wr_pipe); - timeout = vstdev->wr_timeout_ms; - - buf = kmalloc(count, GFP_KERNEL); - if (buf == NULL) { - mutex_unlock(&vstdev->lock); - return -ENOMEM; - } - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - kfree(buf); - mutex_unlock(&vstdev->lock); - return -ENOMEM; - } - - if (copy_from_user(buf, buffer, count)) { - mutex_unlock(&vstdev->lock); - dev_err(&dev->dev, "%s: can't copy_from_user\n", __func__); - retval = -EFAULT; - goto exit; - } - - usb_anchor_urb(urb, &vstdev->submitted); - retval = vstusb_fill_and_send_urb(urb, dev, pipe, buf, count, &done); - mutex_unlock(&vstdev->lock); - if (retval) { - usb_unanchor_urb(urb); - dev_err(&dev->dev, "%s: error %d filling and sending urb %d\n", - __func__, retval, pipe); - goto exit; - } - - retval = vstusb_complete_urb(urb, &done, timeout, &cnt); - if (retval) { - dev_err(&dev->dev, "%s: error %d completing urb %d\n", - __func__, retval, pipe); - goto exit; - } else { - retval = cnt; - dev_dbg(&dev->dev, "%s: sent %d bytes to pipe %d\n", - __func__, cnt, pipe); - } - -exit: - usb_free_urb(urb); - kfree(buf); - return retval; -} - -static long vstusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - int retval = 0; - int cnt = -1; - void __user *data = (void __user *)arg; - struct vstusb_args usb_data; - - struct vstusb_device *vstdev; - void *buffer = NULL; /* must be initialized. buffer is - * referenced on exit but not all - * ioctls allocate it */ - - struct urb *urb = NULL; /* must be initialized. urb is - * referenced on exit but not all - * ioctls allocate it */ - struct usb_device *dev; - unsigned int pipe; - int timeout; - - DECLARE_COMPLETION_ONSTACK(done); - - vstdev = file->private_data; - - if (_IOC_TYPE(cmd) != VST_IOC_MAGIC) { - dev_warn(&vstdev->usb_dev->dev, - "%s: ioctl command %x, bad ioctl magic %x, " - "expected %x\n", __func__, cmd, - _IOC_TYPE(cmd), VST_IOC_MAGIC); - return -EINVAL; - } - - if (vstdev == NULL) - return -ENODEV; - - if (copy_from_user(&usb_data, data, sizeof(struct vstusb_args))) { - dev_err(&vstdev->usb_dev->dev, "%s: can't copy_from_user\n", - __func__); - return -EFAULT; - } - - /* lock this object */ - if (mutex_lock_interruptible(&vstdev->lock)) { - retval = -ERESTARTSYS; - goto exit; - } - - /* anyone home */ - if (!vstdev->present) { - mutex_unlock(&vstdev->lock); - dev_err(&vstdev->usb_dev->dev, "%s: device not present\n", - __func__); - retval = -ENODEV; - goto exit; - } - - /* pull out the necessary data */ - dev = vstdev->usb_dev; - - switch (cmd) { - - case IOCTL_VSTUSB_CONFIG_RW: - - vstdev->rd_pipe = usb_data.rd_pipe; - vstdev->rd_timeout_ms = usb_data.rd_timeout_ms; - vstdev->wr_pipe = usb_data.wr_pipe; - vstdev->wr_timeout_ms = usb_data.wr_timeout_ms; - - mutex_unlock(&vstdev->lock); - - dev_dbg(&dev->dev, "%s: setting pipes/timeouts, " - "rdpipe = %d, rdtimeout = %d, " - "wrpipe = %d, wrtimeout = %d\n", __func__, - vstdev->rd_pipe, vstdev->rd_timeout_ms, - vstdev->wr_pipe, vstdev->wr_timeout_ms); - break; - - case IOCTL_VSTUSB_SEND_PIPE: - - if ((usb_data.count == 0) || (usb_data.count > VST_MAXBUFFER)) { - mutex_unlock(&vstdev->lock); - retval = -EINVAL; - goto exit; - } - - buffer = kmalloc(usb_data.count, GFP_KERNEL); - if (buffer == NULL) { - mutex_unlock(&vstdev->lock); - retval = -ENOMEM; - goto exit; - } - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - mutex_unlock(&vstdev->lock); - retval = -ENOMEM; - goto exit; - } - - timeout = usb_data.timeout_ms; - - pipe = usb_sndbulkpipe(dev, usb_data.pipe); - - if (copy_from_user(buffer, usb_data.buffer, usb_data.count)) { - dev_err(&dev->dev, "%s: can't copy_from_user\n", - __func__); - mutex_unlock(&vstdev->lock); - retval = -EFAULT; - goto exit; - } - - usb_anchor_urb(urb, &vstdev->submitted); - retval = vstusb_fill_and_send_urb(urb, dev, pipe, buffer, - usb_data.count, &done); - mutex_unlock(&vstdev->lock); - if (retval) { - usb_unanchor_urb(urb); - dev_err(&dev->dev, - "%s: error %d filling and sending urb %d\n", - __func__, retval, pipe); - goto exit; - } - - retval = vstusb_complete_urb(urb, &done, timeout, &cnt); - if (retval) { - dev_err(&dev->dev, "%s: error %d completing urb %d\n", - __func__, retval, pipe); - } - - break; - case IOCTL_VSTUSB_RECV_PIPE: - - if ((usb_data.count == 0) || (usb_data.count > VST_MAXBUFFER)) { - mutex_unlock(&vstdev->lock); - retval = -EINVAL; - goto exit; - } - - buffer = kmalloc(usb_data.count, GFP_KERNEL); - if (buffer == NULL) { - mutex_unlock(&vstdev->lock); - retval = -ENOMEM; - goto exit; - } - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - mutex_unlock(&vstdev->lock); - retval = -ENOMEM; - goto exit; - } - - timeout = usb_data.timeout_ms; - - pipe = usb_rcvbulkpipe(dev, usb_data.pipe); - - usb_anchor_urb(urb, &vstdev->submitted); - retval = vstusb_fill_and_send_urb(urb, dev, pipe, buffer, - usb_data.count, &done); - mutex_unlock(&vstdev->lock); - if (retval) { - usb_unanchor_urb(urb); - dev_err(&dev->dev, - "%s: error %d filling and sending urb %d\n", - __func__, retval, pipe); - goto exit; - } - - retval = vstusb_complete_urb(urb, &done, timeout, &cnt); - if (retval) { - dev_err(&dev->dev, "%s: error %d completing urb %d\n", - __func__, retval, pipe); - goto exit; - } - - if (copy_to_user(usb_data.buffer, buffer, cnt)) { - dev_err(&dev->dev, "%s: can't copy_to_user\n", - __func__); - retval = -EFAULT; - goto exit; - } - - usb_data.count = cnt; - if (copy_to_user(data, &usb_data, sizeof(struct vstusb_args))) { - dev_err(&dev->dev, "%s: can't copy_to_user\n", - __func__); - retval = -EFAULT; - } else { - dev_dbg(&dev->dev, "%s: recv %zd bytes from pipe %d\n", - __func__, usb_data.count, usb_data.pipe); - } - - break; - - default: - mutex_unlock(&vstdev->lock); - dev_warn(&dev->dev, "ioctl_vstusb: invalid ioctl cmd %x\n", - cmd); - return -EINVAL; - break; - } -exit: - usb_free_urb(urb); - kfree(buffer); - return retval; -} - -static const struct file_operations vstusb_fops = { - .owner = THIS_MODULE, - .read = vstusb_read, - .write = vstusb_write, - .unlocked_ioctl = vstusb_ioctl, - .compat_ioctl = vstusb_ioctl, - .open = vstusb_open, - .release = vstusb_release, -}; - -static struct usb_class_driver usb_vstusb_class = { - .name = "usb/vstusb%d", - .fops = &vstusb_fops, - .minor_base = VSTUSB_MINOR_BASE, -}; - -static int vstusb_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct vstusb_device *vstdev; - int i; - int retval = 0; - - /* allocate memory for our device state and intialize it */ - - vstdev = kzalloc(sizeof(*vstdev), GFP_KERNEL); - if (vstdev == NULL) - return -ENOMEM; - - /* must do usb_get_dev() prior to kref_init() since the kref_put() - * release function will do a usb_put_dev() */ - usb_get_dev(dev); - kref_init(&vstdev->kref); - mutex_init(&vstdev->lock); - - i = dev->descriptor.bcdDevice; - - dev_dbg(&intf->dev, "Version %1d%1d.%1d%1d found at address %d\n", - (i & 0xF000) >> 12, (i & 0xF00) >> 8, - (i & 0xF0) >> 4, (i & 0xF), dev->devnum); - - vstdev->present = 1; - vstdev->isopen = 0; - vstdev->usb_dev = dev; - init_usb_anchor(&vstdev->submitted); - - usb_set_intfdata(intf, vstdev); - retval = usb_register_dev(intf, &usb_vstusb_class); - if (retval) { - dev_err(&intf->dev, - "%s: Not able to get a minor for this device.\n", - __func__); - usb_set_intfdata(intf, NULL); - kref_put(&vstdev->kref, vstusb_delete); - return retval; - } - - /* let the user know what node this device is now attached to */ - dev_info(&intf->dev, - "VST USB Device #%d now attached to major %d minor %d\n", - (intf->minor - VSTUSB_MINOR_BASE), USB_MAJOR, intf->minor); - - dev_info(&intf->dev, "%s, %s\n", DRIVER_DESC, DRIVER_VERSION); - - return retval; -} - -static void vstusb_disconnect(struct usb_interface *intf) -{ - struct vstusb_device *vstdev = usb_get_intfdata(intf); - - usb_deregister_dev(intf, &usb_vstusb_class); - usb_set_intfdata(intf, NULL); - - if (vstdev) { - - mutex_lock(&vstdev->lock); - vstdev->present = 0; - - usb_kill_anchored_urbs(&vstdev->submitted); - - mutex_unlock(&vstdev->lock); - - kref_put(&vstdev->kref, vstusb_delete); - } - -} - -static int vstusb_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct vstusb_device *vstdev = usb_get_intfdata(intf); - int time; - if (!vstdev) - return 0; - - mutex_lock(&vstdev->lock); - time = usb_wait_anchor_empty_timeout(&vstdev->submitted, 1000); - if (!time) - usb_kill_anchored_urbs(&vstdev->submitted); - mutex_unlock(&vstdev->lock); - - return 0; -} - -static int vstusb_resume(struct usb_interface *intf) -{ - return 0; -} - -static struct usb_driver vstusb_driver = { - .name = "vstusb", - .probe = vstusb_probe, - .disconnect = vstusb_disconnect, - .suspend = vstusb_suspend, - .resume = vstusb_resume, - .id_table = id_table, -}; - -static int __init vstusb_init(void) -{ - int rc; - - rc = usb_register(&vstusb_driver); - if (rc) - printk(KERN_ERR "%s: failed to register (%d)", __func__, rc); - - return rc; -} - -static void __exit vstusb_exit(void) -{ - usb_deregister(&vstusb_driver); -} - -module_init(vstusb_init); -module_exit(vstusb_exit); - -MODULE_AUTHOR("Dennis O'Brien/Stephen Ware"); -MODULE_DESCRIPTION(DRIVER_VERSION); -MODULE_LICENSE("GPL"); |