diff options
Diffstat (limited to 'drivers/usb/misc')
32 files changed, 5480 insertions, 4941 deletions
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index abe3aa67ed0..1bca274dc3b 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -2,11 +2,9 @@ # USB Miscellaneous driver configuration # comment "USB Miscellaneous drivers" - depends on USB config USB_EMI62 tristate "EMI 6|2m USB Audio interface support" - depends on USB ---help--- This driver loads firmware to Emagic EMI 6|2m low latency USB Audio and Midi interface. @@ -21,7 +19,6 @@ config USB_EMI62 config USB_EMI26 tristate "EMI 2|6 USB Audio interface support" - depends on USB ---help--- This driver loads firmware to Emagic EMI 2|6 low latency USB Audio interface. @@ -34,7 +31,6 @@ config USB_EMI26 config USB_ADUTUX tristate "ADU devices from Ontrak Control Systems" - depends on USB help Say Y if you want to use an ADU device from Ontrak Control Systems. @@ -44,7 +40,6 @@ config USB_ADUTUX config USB_SEVSEG tristate "USB 7-Segment LED Display" - depends on USB help Say Y here if you have a USB 7-Segment Display by Delcom @@ -53,7 +48,6 @@ config USB_SEVSEG config USB_RIO500 tristate "USB Diamond Rio500 support" - depends on USB help Say Y here if you want to connect a USB Rio500 mp3 player to your computer's USB port. Please read <file:Documentation/usb/rio.txt> @@ -64,7 +58,6 @@ config USB_RIO500 config USB_LEGOTOWER tristate "USB Lego Infrared Tower support" - depends on USB help Say Y here if you want to connect a USB Lego Infrared Tower to your computer's USB port. @@ -77,7 +70,6 @@ config USB_LEGOTOWER config USB_LCD tristate "USB LCD driver support" - depends on USB help Say Y here if you want to connect an USBLCD to your computer's USB port. The USBLCD is a small USB interface board for @@ -87,20 +79,8 @@ 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 help Say Y here if you want to connect an USBLED device to your computer's USB port. @@ -110,7 +90,6 @@ config USB_LED config USB_CYPRESS_CY7C63 tristate "Cypress CY7C63xxx USB driver support" - depends on USB help Say Y here if you want to connect a Cypress CY7C63xxx micro controller to your computer's USB port. Currently this @@ -124,7 +103,6 @@ config USB_CYPRESS_CY7C63 config USB_CYTHERM tristate "Cypress USB thermometer driver support" - depends on USB help Say Y here if you want to connect a Cypress USB thermometer device to your computer's USB port. This device is also known @@ -137,7 +115,6 @@ config USB_CYTHERM config USB_IDMOUSE tristate "Siemens ID USB Mouse Fingerprint sensor support" - depends on USB help Say Y here if you want to use the fingerprint sensor on the Siemens ID Mouse. There is also a Siemens ID Mouse @@ -151,8 +128,6 @@ config USB_IDMOUSE config USB_FTDI_ELAN tristate "Elan PCMCIA CardBus Adapter USB Client" - depends on USB - default M help ELAN's Uxxx series of adapters are USB to PCMCIA CardBus adapters. Currently only the U132 adapter is available. @@ -175,7 +150,6 @@ config USB_FTDI_ELAN config USB_APPLEDISPLAY tristate "Apple Cinema Display support" - depends on USB select BACKLIGHT_LCD_SUPPORT select BACKLIGHT_CLASS_DEVICE help @@ -186,7 +160,6 @@ source "drivers/usb/misc/sisusbvga/Kconfig" config USB_LD tristate "USB LD driver" - depends on USB help This driver is for generic USB devices that use interrupt transfers, like LD Didactic's USB devices. @@ -196,7 +169,6 @@ config USB_LD config USB_TRANCEVIBRATOR tristate "PlayStation 2 Trance Vibrator driver support" - depends on USB help Say Y here if you want to connect a PlayStation 2 Trance Vibrator device to your computer's USB port. @@ -206,7 +178,6 @@ config USB_TRANCEVIBRATOR config USB_IOWARRIOR tristate "IO Warrior driver support" - depends on USB help Say Y here if you want to support the IO Warrior devices from Code Mercenaries. This includes support for the following devices: @@ -220,7 +191,6 @@ config USB_IOWARRIOR config USB_TEST tristate "USB testing driver" - depends on USB help This driver is for testing host controller software. It is used with specialized device firmware for regression and stress testing, @@ -229,9 +199,21 @@ config USB_TEST See <http://www.linux-usb.org/usbtest/> for more information, including sample test device firmware and "how to use it". +config USB_EHSET_TEST_FIXTURE + tristate "USB EHSET Test Fixture driver" + help + Say Y here if you want to support the special test fixture device + used for the USB-IF Embedded Host High-Speed Electrical Test procedure. + + When the test fixture is connected, it can enumerate as one of several + VID/PID pairs. This driver then initiates a corresponding test mode on + the downstream port to which the test fixture is attached. + + See <http://www.usb.org/developers/onthego/EHSET_v1.01.pdf> for more + information. + config USB_ISIGHTFW tristate "iSight firmware loading support" - depends on USB select FW_LOADER help This driver loads firmware for USB Apple iSight cameras, allowing @@ -242,17 +224,27 @@ 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 +config USB_YUREX + tristate "USB YUREX driver support" 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. + Say Y here if you want to connect a YUREX to your computer's + USB port. The YUREX is a leg-shakes sensor. See + <http://bbu.kayac.com/en/> for further information. + This driver supports read/write of leg-shakes counter and + fasync for the counter update via a device file /dev/yurex*. To compile this driver as a module, choose M here: the - module will be called vstusb. + module will be called yurex. +config USB_EZUSB_FX2 + tristate "Functions for loading firmware on EZUSB chips" + help + Say Y here if you need EZUSB device support. + (Cypress FX/FX2/FX2LP microcontrollers) +config USB_HSIC_USB3503 + tristate "USB3503 HSIC to USB20 Driver" + depends on I2C + select REGMAP_I2C + help + This option enables support for SMSC USB3503 HSIC to USB 2.0 Driver. diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 0826aab8303..e748fd5dbe9 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -2,31 +2,28 @@ # Makefile for the rest of the USB drivers # (the ones that don't fit into any other categories) # - -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 -obj-$(CONFIG_USB_EMI62) += emi62.o -obj-$(CONFIG_USB_FTDI_ELAN) += ftdi-elan.o -obj-$(CONFIG_USB_IDMOUSE) += idmouse.o -obj-$(CONFIG_USB_IOWARRIOR) += iowarrior.o -obj-$(CONFIG_USB_ISIGHTFW) += isight_firmware.o -obj-$(CONFIG_USB_LCD) += usblcd.o -obj-$(CONFIG_USB_LD) += ldusb.o -obj-$(CONFIG_USB_LED) += usbled.o -obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o -obj-$(CONFIG_USB_RIO500) += rio500.o -obj-$(CONFIG_USB_TEST) += usbtest.o +obj-$(CONFIG_USB_ADUTUX) += adutux.o +obj-$(CONFIG_USB_APPLEDISPLAY) += appledisplay.o +obj-$(CONFIG_USB_CYPRESS_CY7C63) += cypress_cy7c63.o +obj-$(CONFIG_USB_CYTHERM) += cytherm.o +obj-$(CONFIG_USB_EMI26) += emi26.o +obj-$(CONFIG_USB_EMI62) += emi62.o +obj-$(CONFIG_USB_EZUSB_FX2) += ezusb.o +obj-$(CONFIG_USB_FTDI_ELAN) += ftdi-elan.o +obj-$(CONFIG_USB_IDMOUSE) += idmouse.o +obj-$(CONFIG_USB_IOWARRIOR) += iowarrior.o +obj-$(CONFIG_USB_ISIGHTFW) += isight_firmware.o +obj-$(CONFIG_USB_LCD) += usblcd.o +obj-$(CONFIG_USB_LD) += ldusb.o +obj-$(CONFIG_USB_LED) += usbled.o +obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o +obj-$(CONFIG_USB_RIO500) += rio500.o +obj-$(CONFIG_USB_TEST) += usbtest.o +obj-$(CONFIG_USB_EHSET_TEST_FIXTURE) += ehset.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/ +obj-$(CONFIG_USB_USS720) += uss720.o +obj-$(CONFIG_USB_SEVSEG) += usbsevseg.o +obj-$(CONFIG_USB_YUREX) += yurex.o +obj-$(CONFIG_USB_HSIC_USB3503) += usb3503.o -ifeq ($(CONFIG_USB_DEBUG),y) -EXTRA_CFLAGS += -DDEBUG -endif +obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index 20352654201..493c7f268b6 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -18,52 +18,34 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/kernel.h> #include <linux/errno.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/usb.h> #include <linux/mutex.h> -#include <asm/uaccess.h> - -#ifdef CONFIG_USB_DEBUG -static int debug = 5; -#else -static int debug = 1; -#endif - -/* 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) - +#include <linux/uaccess.h> /* Version Information */ #define DRIVER_VERSION "v0.0.13" #define DRIVER_AUTHOR "John Homppi" #define DRIVER_DESC "adutux (see www.ontrak.net)" -/* Module parameters */ -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); - /* Define these values to match your device */ #define ADU_VENDOR_ID 0x0a07 #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 */ + { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+20) }, /* ADU120 */ + { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+30) }, /* ADU130 */ { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+100) }, /* ADU200 */ { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+108) }, /* ADU208 */ { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+118) }, /* ADU218 */ - { }/* Terminating entry */ + { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, device_table); @@ -92,16 +74,16 @@ MODULE_DEVICE_TABLE(usb, device_table); /* Structure to hold all of our device specific stuff */ struct adu_device { struct mutex mtx; - struct usb_device* udev; /* save off the usb device pointer */ - struct usb_interface* interface; + struct usb_device *udev; /* save off the usb device pointer */ + struct usb_interface *interface; unsigned int minor; /* the starting minor number for this device */ char serial_number[8]; int open_count; /* number of times this port has been opened */ - char* read_buffer_primary; + char *read_buffer_primary; int read_buffer_length; - char* read_buffer_secondary; + char *read_buffer_secondary; int secondary_head; int secondary_tail; spinlock_t buflock; @@ -109,14 +91,14 @@ struct adu_device { wait_queue_head_t read_wait; wait_queue_head_t write_wait; - char* interrupt_in_buffer; - struct usb_endpoint_descriptor* interrupt_in_endpoint; - struct urb* interrupt_in_urb; + char *interrupt_in_buffer; + struct usb_endpoint_descriptor *interrupt_in_endpoint; + struct urb *interrupt_in_urb; int read_urb_finished; - char* interrupt_out_buffer; - struct usb_endpoint_descriptor* interrupt_out_endpoint; - struct urb* interrupt_out_urb; + char *interrupt_out_buffer; + struct usb_endpoint_descriptor *interrupt_out_endpoint; + struct urb *interrupt_out_urb; int out_urb_finished; }; @@ -124,19 +106,11 @@ static DEFINE_MUTEX(adutux_mutex); static struct usb_driver adu_driver; -static void adu_debug_data(int level, const char *function, int size, - const unsigned char *data) +static inline void adu_debug_data(struct device *dev, const char *function, + int size, const unsigned char *data) { - int i; - - if (debug < level) - return; - - printk(KERN_DEBUG __FILE__": %s - length = %d, data = ", - function, size); - for (i = 0; i < size; ++i) - printk("%.2x ", data[i]); - printk("\n"); + dev_dbg(dev, "%s - length = %d, data = %*ph\n", + function, size, size, data); } /** @@ -147,12 +121,8 @@ static void adu_abort_transfers(struct adu_device *dev) { unsigned long flags; - dbg(2," %s : enter", __func__); - - if (dev->udev == NULL) { - dbg(1," %s : udev is null", __func__); - goto exit; - } + if (dev->udev == NULL) + return; /* shutdown transfer */ @@ -170,15 +140,10 @@ static void adu_abort_transfers(struct adu_device *dev) usb_kill_urb(dev->interrupt_out_urb); } else spin_unlock_irqrestore(&dev->buflock, flags); - -exit: - dbg(2," %s : leave", __func__); } static void adu_delete(struct adu_device *dev) { - dbg(2, "%s enter", __func__); - /* free data structures */ usb_free_urb(dev->interrupt_in_urb); usb_free_urb(dev->interrupt_out_urb); @@ -187,8 +152,6 @@ static void adu_delete(struct adu_device *dev) kfree(dev->interrupt_in_buffer); kfree(dev->interrupt_out_buffer); kfree(dev); - - dbg(2, "%s : leave", __func__); } static void adu_interrupt_in_callback(struct urb *urb) @@ -196,34 +159,35 @@ static void adu_interrupt_in_callback(struct urb *urb) struct adu_device *dev = urb->context; int status = urb->status; - dbg(4," %s : enter, status %d", __func__, status); - adu_debug_data(5, __func__, urb->actual_length, - urb->transfer_buffer); + adu_debug_data(&dev->udev->dev, __func__, + urb->actual_length, urb->transfer_buffer); spin_lock(&dev->buflock); if (status != 0) { if ((status != -ENOENT) && (status != -ECONNRESET) && (status != -ESHUTDOWN)) { - dbg(1," %s : nonzero status received: %d", - __func__, status); + dev_dbg(&dev->udev->dev, + "%s : nonzero status received: %d\n", + __func__, status); } goto exit; } if (urb->actual_length > 0 && dev->interrupt_in_buffer[0] != 0x00) { if (dev->read_buffer_length < - (4 * le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize)) - + (4 * usb_endpoint_maxp(dev->interrupt_in_endpoint)) - (urb->actual_length)) { memcpy (dev->read_buffer_primary + dev->read_buffer_length, dev->interrupt_in_buffer, urb->actual_length); dev->read_buffer_length += urb->actual_length; - dbg(2," %s reading %d ", __func__, - urb->actual_length); + dev_dbg(&dev->udev->dev,"%s reading %d\n", __func__, + urb->actual_length); } else { - dbg(1," %s : read_buffer overflow", __func__); + dev_dbg(&dev->udev->dev,"%s : read_buffer overflow\n", + __func__); } } @@ -232,9 +196,6 @@ exit: spin_unlock(&dev->buflock); /* always wake up so we recover from errors */ wake_up_interruptible(&dev->read_wait); - adu_debug_data(5, __func__, urb->actual_length, - urb->transfer_buffer); - dbg(4," %s : leave, status %d", __func__, status); } static void adu_interrupt_out_callback(struct urb *urb) @@ -242,27 +203,23 @@ static void adu_interrupt_out_callback(struct urb *urb) struct adu_device *dev = urb->context; int status = urb->status; - dbg(4," %s : enter, status %d", __func__, status); - adu_debug_data(5,__func__, urb->actual_length, urb->transfer_buffer); + adu_debug_data(&dev->udev->dev, __func__, + urb->actual_length, urb->transfer_buffer); if (status != 0) { if ((status != -ENOENT) && (status != -ECONNRESET)) { - dbg(1, " %s :nonzero status received: %d", - __func__, status); + dev_dbg(&dev->udev->dev, + "%s :nonzero status received: %d\n", __func__, + status); } - goto exit; + return; } spin_lock(&dev->buflock); dev->out_urb_finished = 1; wake_up(&dev->write_wait); spin_unlock(&dev->buflock); -exit: - - adu_debug_data(5, __func__, urb->actual_length, - urb->transfer_buffer); - dbg(4," %s : leave, status %d", __func__, status); } static int adu_open(struct inode *inode, struct file *file) @@ -272,19 +229,16 @@ static int adu_open(struct inode *inode, struct file *file) int subminor; int retval; - dbg(2,"%s : enter", __func__); - subminor = iminor(inode); - if ((retval = mutex_lock_interruptible(&adutux_mutex))) { - dbg(2, "%s : mutex lock failed", __func__); + retval = mutex_lock_interruptible(&adutux_mutex); + if (retval) goto exit_no_lock; - } interface = usb_find_interface(&adu_driver, subminor); if (!interface) { - printk(KERN_ERR "adutux: %s - error, can't find device for " - "minor %d\n", __func__, subminor); + pr_err("%s - error, can't find device for minor %d\n", + __func__, subminor); retval = -ENODEV; goto exit_no_device; } @@ -302,7 +256,8 @@ static int adu_open(struct inode *inode, struct file *file) } ++dev->open_count; - dbg(2,"%s : open count %d", __func__, dev->open_count); + dev_dbg(&dev->udev->dev, "%s: open count %d\n", __func__, + dev->open_count); /* save device in the file's private structure */ file->private_data = dev; @@ -311,11 +266,11 @@ static int adu_open(struct inode *inode, struct file *file) dev->read_buffer_length = 0; /* fixup first read by having urb waiting for it */ - usb_fill_int_urb(dev->interrupt_in_urb,dev->udev, + usb_fill_int_urb(dev->interrupt_in_urb, dev->udev, usb_rcvintpipe(dev->udev, dev->interrupt_in_endpoint->bEndpointAddress), dev->interrupt_in_buffer, - le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), + usb_endpoint_maxp(dev->interrupt_in_endpoint), adu_interrupt_in_callback, dev, dev->interrupt_in_endpoint->bInterval); dev->read_urb_finished = 0; @@ -332,23 +287,19 @@ static int adu_open(struct inode *inode, struct file *file) exit_no_device: mutex_unlock(&adutux_mutex); exit_no_lock: - dbg(2,"%s : leave, return value %d ", __func__, retval); return retval; } static void adu_release_internal(struct adu_device *dev) { - dbg(2," %s : enter", __func__); - /* decrement our usage count for the device */ --dev->open_count; - dbg(2," %s : open count %d", __func__, dev->open_count); + dev_dbg(&dev->udev->dev, "%s : open count %d\n", __func__, + dev->open_count); if (dev->open_count <= 0) { adu_abort_transfers(dev); dev->open_count = 0; } - - dbg(2," %s : leave", __func__); } static int adu_release(struct inode *inode, struct file *file) @@ -356,17 +307,13 @@ static int adu_release(struct inode *inode, struct file *file) struct adu_device *dev; int retval = 0; - dbg(2," %s : enter", __func__); - if (file == NULL) { - dbg(1," %s : file is NULL", __func__); retval = -ENODEV; goto exit; } dev = file->private_data; if (dev == NULL) { - dbg(1," %s : object is NULL", __func__); retval = -ENODEV; goto exit; } @@ -374,7 +321,7 @@ static int adu_release(struct inode *inode, struct file *file) mutex_lock(&adutux_mutex); /* not interruptible */ if (dev->open_count <= 0) { - dbg(1," %s : device not opened", __func__); + dev_dbg(&dev->udev->dev, "%s : device not opened\n", __func__); retval = -ENODEV; goto unlock; } @@ -388,7 +335,6 @@ static int adu_release(struct inode *inode, struct file *file) unlock: mutex_unlock(&adutux_mutex); exit: - dbg(2," %s : leave, return value %d", __func__, retval); return retval; } @@ -405,41 +351,38 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, unsigned long flags; DECLARE_WAITQUEUE(wait, current); - dbg(2," %s : enter, count = %Zd, file=%p", __func__, count, file); - dev = file->private_data; - dbg(2," %s : dev=%p", __func__, dev); - if (mutex_lock_interruptible(&dev->mtx)) return -ERESTARTSYS; /* verify that the device wasn't unplugged */ if (dev->udev == NULL) { retval = -ENODEV; - printk(KERN_ERR "adutux: No device or device unplugged %d\n", - retval); + pr_err("No device or device unplugged %d\n", retval); goto exit; } /* verify that some data was requested */ if (count == 0) { - dbg(1," %s : read request of 0 bytes", __func__); + dev_dbg(&dev->udev->dev, "%s : read request of 0 bytes\n", + __func__); goto exit; } timeout = COMMAND_TIMEOUT; - dbg(2," %s : about to start looping", __func__); + dev_dbg(&dev->udev->dev, "%s : about to start looping\n", __func__); while (bytes_to_read) { int data_in_secondary = dev->secondary_tail - dev->secondary_head; - dbg(2," %s : while, data_in_secondary=%d, status=%d", - __func__, data_in_secondary, - dev->interrupt_in_urb->status); + dev_dbg(&dev->udev->dev, + "%s : while, data_in_secondary=%d, status=%d\n", + __func__, data_in_secondary, + dev->interrupt_in_urb->status); if (data_in_secondary) { /* drain secondary buffer */ int amount = bytes_to_read < data_in_secondary ? bytes_to_read : data_in_secondary; i = copy_to_user(buffer, dev->read_buffer_secondary+dev->secondary_head, amount); - if (i < 0) { + if (i) { retval = -EFAULT; goto exit; } @@ -456,8 +399,9 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, if (dev->read_buffer_length) { /* we secure access to the primary */ char *tmp; - dbg(2," %s : swap, read_buffer_length = %d", - __func__, dev->read_buffer_length); + dev_dbg(&dev->udev->dev, + "%s : swap, read_buffer_length = %d\n", + __func__, dev->read_buffer_length); tmp = dev->read_buffer_secondary; dev->read_buffer_secondary = dev->read_buffer_primary; dev->read_buffer_primary = tmp; @@ -472,18 +416,22 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, if (!dev->read_urb_finished) { /* somebody is doing IO */ spin_unlock_irqrestore(&dev->buflock, flags); - dbg(2," %s : submitted already", __func__); + dev_dbg(&dev->udev->dev, + "%s : submitted already\n", + __func__); } else { /* we must initiate input */ - dbg(2," %s : initiate input", __func__); + dev_dbg(&dev->udev->dev, + "%s : initiate input\n", + __func__); dev->read_urb_finished = 0; spin_unlock_irqrestore(&dev->buflock, flags); - usb_fill_int_urb(dev->interrupt_in_urb,dev->udev, - usb_rcvintpipe(dev->udev, - dev->interrupt_in_endpoint->bEndpointAddress), + usb_fill_int_urb(dev->interrupt_in_urb, dev->udev, + usb_rcvintpipe(dev->udev, + dev->interrupt_in_endpoint->bEndpointAddress), dev->interrupt_in_buffer, - le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), + usb_endpoint_maxp(dev->interrupt_in_endpoint), adu_interrupt_in_callback, dev, dev->interrupt_in_endpoint->bInterval); @@ -493,7 +441,9 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, if (retval == -ENOMEM) { retval = bytes_read ? bytes_read : -ENOMEM; } - dbg(2," %s : submit failed", __func__); + dev_dbg(&dev->udev->dev, + "%s : submit failed\n", + __func__); goto exit; } } @@ -512,13 +462,16 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, remove_wait_queue(&dev->read_wait, &wait); if (timeout <= 0) { - dbg(2," %s : timeout", __func__); + dev_dbg(&dev->udev->dev, + "%s : timeout\n", __func__); retval = bytes_read ? bytes_read : -ETIMEDOUT; goto exit; } if (signal_pending(current)) { - dbg(2," %s : signal pending", __func__); + dev_dbg(&dev->udev->dev, + "%s : signal pending\n", + __func__); retval = bytes_read ? bytes_read : -EINTR; goto exit; } @@ -532,11 +485,11 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, if (should_submit && dev->read_urb_finished) { dev->read_urb_finished = 0; spin_unlock_irqrestore(&dev->buflock, flags); - usb_fill_int_urb(dev->interrupt_in_urb,dev->udev, + usb_fill_int_urb(dev->interrupt_in_urb, dev->udev, usb_rcvintpipe(dev->udev, - dev->interrupt_in_endpoint->bEndpointAddress), + dev->interrupt_in_endpoint->bEndpointAddress), dev->interrupt_in_buffer, - le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), + usb_endpoint_maxp(dev->interrupt_in_endpoint), adu_interrupt_in_callback, dev, dev->interrupt_in_endpoint->bInterval); @@ -551,7 +504,6 @@ exit: /* unlock the device */ mutex_unlock(&dev->mtx); - dbg(2," %s : leave, return value %d", __func__, retval); return retval; } @@ -566,8 +518,6 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, unsigned long flags; int retval; - dbg(2," %s : enter, count = %Zd", __func__, count); - dev = file->private_data; retval = mutex_lock_interruptible(&dev->mtx); @@ -577,14 +527,14 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, /* verify that the device wasn't unplugged */ if (dev->udev == NULL) { retval = -ENODEV; - printk(KERN_ERR "adutux: No device or device unplugged %d\n", - retval); + pr_err("No device or device unplugged %d\n", retval); goto exit; } /* verify that we actually have some data to write */ if (count == 0) { - dbg(1," %s : write request of 0 bytes", __func__); + dev_dbg(&dev->udev->dev, "%s : write request of 0 bytes\n", + __func__); goto exit; } @@ -597,13 +547,15 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, mutex_unlock(&dev->mtx); if (signal_pending(current)) { - dbg(1," %s : interrupted", __func__); + dev_dbg(&dev->udev->dev, "%s : interrupted\n", + __func__); set_current_state(TASK_RUNNING); retval = -EINTR; goto exit_onqueue; } if (schedule_timeout(COMMAND_TIMEOUT) == 0) { - dbg(1, "%s - command timed out.", __func__); + dev_dbg(&dev->udev->dev, + "%s - command timed out.\n", __func__); retval = -ETIMEDOUT; goto exit_onqueue; } @@ -614,18 +566,22 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, goto exit_nolock; } - dbg(4," %s : in progress, count = %Zd", __func__, count); + dev_dbg(&dev->udev->dev, + "%s : in progress, count = %Zd\n", + __func__, count); } else { spin_unlock_irqrestore(&dev->buflock, flags); set_current_state(TASK_RUNNING); remove_wait_queue(&dev->write_wait, &waita); - dbg(4," %s : sending, count = %Zd", __func__, count); + dev_dbg(&dev->udev->dev, "%s : sending, count = %Zd\n", + __func__, count); /* write the data into interrupt_out_buffer from userspace */ - buffer_size = le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize); + buffer_size = usb_endpoint_maxp(dev->interrupt_out_endpoint); bytes_to_write = count > buffer_size ? buffer_size : count; - dbg(4," %s : buffer_size = %Zd, count = %Zd, bytes_to_write = %Zd", - __func__, buffer_size, count, bytes_to_write); + dev_dbg(&dev->udev->dev, + "%s : buffer_size = %Zd, count = %Zd, bytes_to_write = %Zd\n", + __func__, buffer_size, count, bytes_to_write); if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write) != 0) { retval = -EFAULT; @@ -664,7 +620,6 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, exit: mutex_unlock(&dev->mtx); exit_nolock: - dbg(2," %s : leave, return value %d", __func__, retval); return retval; exit_onqueue: @@ -679,6 +634,7 @@ static const struct file_operations adu_fops = { .write = adu_write, .open = adu_open, .release = adu_release, + .llseek = noop_llseek, }; /* @@ -709,14 +665,12 @@ static int adu_probe(struct usb_interface *interface, int out_end_size; int i; - dbg(2," %s : enter", __func__); - if (udev == NULL) { dev_err(&interface->dev, "udev is NULL.\n"); goto exit; } - /* allocate memory for our device state and intialize it */ + /* allocate memory for our device state and initialize it */ dev = kzalloc(sizeof(struct adu_device), GFP_KERNEL); if (dev == NULL) { dev_err(&interface->dev, "Out of memory\n"); @@ -751,8 +705,8 @@ static int adu_probe(struct usb_interface *interface, goto error; } - in_end_size = le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize); - out_end_size = le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize); + in_end_size = usb_endpoint_maxp(dev->interrupt_in_endpoint); + out_end_size = usb_endpoint_maxp(dev->interrupt_out_endpoint); dev->read_buffer_primary = kmalloc((4 * in_end_size), GFP_KERNEL); if (!dev->read_buffer_primary) { @@ -810,7 +764,7 @@ static int adu_probe(struct usb_interface *interface, dev_err(&interface->dev, "Could not retrieve serial number\n"); goto error; } - dbg(2," %s : serial_number=%s", __func__, dev->serial_number); + dev_dbg(&interface->dev,"serial_number=%s", dev->serial_number); /* we can register the device now, as it is ready */ usb_set_intfdata(interface, dev); @@ -828,11 +782,9 @@ static int adu_probe(struct usb_interface *interface, /* let the user know what node this device is now attached to */ dev_info(&interface->dev, "ADU%d %s now attached to /dev/usb/adutux%d\n", - udev->descriptor.idProduct, dev->serial_number, + le16_to_cpu(udev->descriptor.idProduct), dev->serial_number, (dev->minor - ADU_MINOR_BASE)); exit: - dbg(2," %s : leave, return value %p (dev)", __func__, dev); - return retval; error: @@ -850,8 +802,6 @@ static void adu_disconnect(struct usb_interface *interface) struct adu_device *dev; int minor; - dbg(2," %s : enter", __func__); - dev = usb_get_intfdata(interface); mutex_lock(&dev->mtx); /* not interruptible */ @@ -864,7 +814,8 @@ static void adu_disconnect(struct usb_interface *interface) usb_set_intfdata(interface, NULL); /* if the device is not opened, then we clean up right now */ - dbg(2," %s : open count %d", __func__, dev->open_count); + dev_dbg(&dev->udev->dev, "%s : open count %d\n", + __func__, dev->open_count); if (!dev->open_count) adu_delete(dev); @@ -872,8 +823,6 @@ static void adu_disconnect(struct usb_interface *interface) dev_info(&interface->dev, "ADU device adutux%d now disconnected\n", (minor - ADU_MINOR_BASE)); - - dbg(2," %s : leave", __func__); } /* usb specific object needed to register this driver with the usb subsystem */ @@ -884,40 +833,7 @@ static struct usb_driver adu_driver = { .id_table = device_table, }; -static int __init adu_init(void) -{ - int result; - - dbg(2," %s : enter", __func__); - - /* register this driver with the USB subsystem */ - result = usb_register(&adu_driver); - if (result < 0) { - printk(KERN_ERR "usb_register failed for the "__FILE__ - " driver. Error number %d\n", result); - goto exit; - } - - printk(KERN_INFO "adutux " DRIVER_DESC " " DRIVER_VERSION "\n"); - printk(KERN_INFO "adutux is an experimental driver. " - "Use at your own risk\n"); - -exit: - dbg(2," %s : leave, return value %d", __func__, result); - - return result; -} - -static void __exit adu_exit(void) -{ - dbg(2," %s : enter", __func__); - /* deregister this driver with the USB subsystem */ - usb_deregister(&adu_driver); - dbg(2," %s : leave", __func__); -} - -module_init(adu_init); -module_exit(adu_exit); +module_usb_driver(adu_driver); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index 1eb9e4162cc..b3d245ef46e 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -24,11 +24,12 @@ #include <linux/errno.h> #include <linux/init.h> #include <linux/module.h> +#include <linux/slab.h> #include <linux/usb.h> #include <linux/backlight.h> #include <linux/timer.h> #include <linux/workqueue.h> -#include <asm/atomic.h> +#include <linux/atomic.h> #define APPLE_VENDOR_ID 0x05AC @@ -57,11 +58,12 @@ .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) }, { APPLEDISPLAY_DEVICE(0x921d) }, + { APPLEDISPLAY_DEVICE(0x9236) }, /* Terminating entry */ { } @@ -79,6 +81,7 @@ struct appledisplay { struct delayed_work work; int button_pressed; spinlock_t lock; + struct mutex sysfslock; /* concurrent read and write */ }; static atomic_t count_displays = ATOMIC_INIT(0); @@ -87,6 +90,7 @@ static struct workqueue_struct *wq; static void appledisplay_complete(struct urb *urb) { struct appledisplay *pdata = urb->context; + struct device *dev = &pdata->udev->dev; unsigned long flags; int status = urb->status; int retval; @@ -96,18 +100,18 @@ static void appledisplay_complete(struct urb *urb) /* success */ break; case -EOVERFLOW: - printk(KERN_ERR "appletouch: OVERFLOW with data " - "length %d, actual length is %d\n", + dev_err(dev, + "OVERFLOW with data length %d, actual length is %d\n", ACD_URB_BUFFER_LEN, pdata->urb->actual_length); case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: /* This urb is terminated, clean up */ - dbg("%s - urb shuttingdown with status: %d", + dev_dbg(dev, "%s - urb shuttingdown with status: %d\n", __func__, status); return; default: - dbg("%s - nonzero urb status received: %d", + dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status); goto exit; } @@ -131,8 +135,7 @@ static void appledisplay_complete(struct urb *urb) exit: retval = usb_submit_urb(pdata->urb, GFP_ATOMIC); if (retval) { - dev_err(&pdata->udev->dev, - "%s - usb_submit_urb failed with result %d\n", + dev_err(dev, "%s - usb_submit_urb failed with result %d\n", __func__, retval); } } @@ -142,6 +145,7 @@ static int appledisplay_bl_update_status(struct backlight_device *bd) struct appledisplay *pdata = bl_get_data(bd); int retval; + mutex_lock(&pdata->sysfslock); pdata->msgdata[0] = 0x10; pdata->msgdata[1] = bd->props.brightness; @@ -154,15 +158,17 @@ static int appledisplay_bl_update_status(struct backlight_device *bd) 0, pdata->msgdata, 2, ACD_USB_TIMEOUT); - + mutex_unlock(&pdata->sysfslock); + return retval; } static int appledisplay_bl_get_brightness(struct backlight_device *bd) { struct appledisplay *pdata = bl_get_data(bd); - int retval; + int retval, brightness; + mutex_lock(&pdata->sysfslock); retval = usb_control_msg( pdata->udev, usb_rcvctrlpipe(pdata->udev, 0), @@ -172,14 +178,16 @@ static int appledisplay_bl_get_brightness(struct backlight_device *bd) 0, pdata->msgdata, 2, ACD_USB_TIMEOUT); + brightness = pdata->msgdata[1]; + mutex_unlock(&pdata->sysfslock); if (retval < 0) return retval; else - return pdata->msgdata[1]; + return brightness; } -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, }; @@ -202,6 +210,7 @@ static void appledisplay_work(struct work_struct *work) static int appledisplay_probe(struct usb_interface *iface, const struct usb_device_id *id) { + struct backlight_properties props; struct appledisplay *pdata; struct usb_device *udev = interface_to_usbdev(iface); struct usb_host_interface *iface_desc; @@ -238,6 +247,7 @@ static int appledisplay_probe(struct usb_interface *iface, spin_lock_init(&pdata->lock); INIT_DELAYED_WORK(&pdata->work, appledisplay_work); + mutex_init(&pdata->sysfslock); /* Allocate buffer for control messages */ pdata->msgdata = kmalloc(ACD_MSG_BUFFER_LEN, GFP_KERNEL); @@ -257,7 +267,7 @@ static int appledisplay_probe(struct usb_interface *iface, } /* Allocate buffer for interrupt data */ - pdata->urbdata = usb_buffer_alloc(pdata->udev, ACD_URB_BUFFER_LEN, + pdata->urbdata = usb_alloc_coherent(pdata->udev, ACD_URB_BUFFER_LEN, GFP_KERNEL, &pdata->urb->transfer_dma); if (!pdata->urbdata) { retval = -ENOMEM; @@ -279,15 +289,17 @@ static int appledisplay_probe(struct usb_interface *iface, /* Register backlight device */ snprintf(bl_name, sizeof(bl_name), "appledisplay%d", atomic_inc_return(&count_displays) - 1); + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; + props.max_brightness = 0xff; pdata->bd = backlight_device_register(bl_name, NULL, pdata, - &appledisplay_bl_data); + &appledisplay_bl_data, &props); if (IS_ERR(pdata->bd)) { dev_err(&iface->dev, "Backlight registration failed\n"); + retval = PTR_ERR(pdata->bd); goto error; } - pdata->bd->props.max_brightness = 0xff; - /* Try to get brightness */ brightness = appledisplay_bl_get_brightness(pdata->bd); @@ -313,7 +325,7 @@ error: if (pdata->urb) { usb_kill_urb(pdata->urb); if (pdata->urbdata) - usb_buffer_free(pdata->udev, ACD_URB_BUFFER_LEN, + usb_free_coherent(pdata->udev, ACD_URB_BUFFER_LEN, pdata->urbdata, pdata->urb->transfer_dma); usb_free_urb(pdata->urb); } @@ -334,7 +346,7 @@ static void appledisplay_disconnect(struct usb_interface *iface) usb_kill_urb(pdata->urb); cancel_delayed_work(&pdata->work); backlight_device_unregister(pdata->bd); - usb_buffer_free(pdata->udev, ACD_URB_BUFFER_LEN, + usb_free_coherent(pdata->udev, ACD_URB_BUFFER_LEN, pdata->urbdata, pdata->urb->transfer_dma); usb_free_urb(pdata->urb); kfree(pdata->msgdata); diff --git a/drivers/usb/misc/berry_charge.c b/drivers/usb/misc/berry_charge.c deleted file mode 100644 index c05a85bc592..00000000000 --- 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 5720bfef6a3..402b94dd253 100644 --- a/drivers/usb/misc/cypress_cy7c63.c +++ b/drivers/usb/misc/cypress_cy7c63.c @@ -29,9 +29,9 @@ * published by the Free Software Foundation, version 2. */ -#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> +#include <linux/slab.h> #include <linux/usb.h> #define DRIVER_AUTHOR "Oliver Bock (bock@tfh-berlin.de)" @@ -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) }, { } }; @@ -195,11 +195,9 @@ static ssize_t get_port1_handler(struct device *dev, return read_port(dev, attr, buf, 1, CYPRESS_READ_PORT_ID1); } -static DEVICE_ATTR(port0, S_IWUGO | S_IRUGO, - get_port0_handler, set_port0_handler); +static DEVICE_ATTR(port0, S_IRUGO | S_IWUSR, get_port0_handler, set_port0_handler); -static DEVICE_ATTR(port1, S_IWUGO | S_IRUGO, - get_port1_handler, set_port1_handler); +static DEVICE_ATTR(port1, S_IRUGO | S_IWUSR, get_port1_handler, set_port1_handler); static int cypress_probe(struct usb_interface *interface, @@ -272,27 +270,7 @@ static struct usb_driver cypress_driver = { .id_table = cypress_table, }; -static int __init cypress_init(void) -{ - int result; - - /* register this driver with the USB subsystem */ - result = usb_register(&cypress_driver); - if (result) - printk(KERN_ERR KBUILD_MODNAME ": usb_register failed! " - "Error number: %d\n", result); - - return result; -} - -static void __exit cypress_exit(void) -{ - /* deregister this driver with the USB subsystem */ - usb_deregister(&cypress_driver); -} - -module_init(cypress_init); -module_exit(cypress_exit); +module_usb_driver(cypress_driver); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/misc/cytherm.c b/drivers/usb/misc/cytherm.c index 4fb3c38b924..9bab1a33bc1 100644 --- a/drivers/usb/misc/cytherm.c +++ b/drivers/usb/misc/cytherm.c @@ -16,7 +16,7 @@ #include <linux/kernel.h> #include <linux/errno.h> -#include <linux/init.h> +#include <linux/slab.h> #include <linux/module.h> #include <linux/usb.h> @@ -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) }, { } }; @@ -416,31 +416,7 @@ static void cytherm_disconnect(struct usb_interface *interface) dev_info(&interface->dev, "Cypress thermometer now disconnected\n"); } - -static int __init usb_cytherm_init(void) -{ - int result; - - result = usb_register(&cytherm_driver); - if (result) { - printk(KERN_ERR KBUILD_MODNAME ": usb_register failed! " - "Error number: %d\n", result); - return result; - } - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -} - -static void __exit usb_cytherm_exit(void) -{ - usb_deregister(&cytherm_driver); -} - - -module_init (usb_cytherm_init); -module_exit (usb_cytherm_exit); +module_usb_driver(cytherm_driver); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/misc/ehset.c b/drivers/usb/misc/ehset.c new file mode 100644 index 00000000000..c31b4a33e6b --- /dev/null +++ b/drivers/usb/misc/ehset.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/usb.h> +#include <linux/usb/ch11.h> + +#define TEST_SE0_NAK_PID 0x0101 +#define TEST_J_PID 0x0102 +#define TEST_K_PID 0x0103 +#define TEST_PACKET_PID 0x0104 +#define TEST_HS_HOST_PORT_SUSPEND_RESUME 0x0106 +#define TEST_SINGLE_STEP_GET_DEV_DESC 0x0107 +#define TEST_SINGLE_STEP_SET_FEATURE 0x0108 + +static int ehset_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + int ret = -EINVAL; + struct usb_device *dev = interface_to_usbdev(intf); + struct usb_device *hub_udev = dev->parent; + struct usb_device_descriptor *buf; + u8 portnum = dev->portnum; + u16 test_pid = le16_to_cpu(dev->descriptor.idProduct); + + switch (test_pid) { + case TEST_SE0_NAK_PID: + ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0), + USB_REQ_SET_FEATURE, USB_RT_PORT, + USB_PORT_FEAT_TEST, + (TEST_SE0_NAK << 8) | portnum, + NULL, 0, 1000); + break; + case TEST_J_PID: + ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0), + USB_REQ_SET_FEATURE, USB_RT_PORT, + USB_PORT_FEAT_TEST, + (TEST_J << 8) | portnum, + NULL, 0, 1000); + break; + case TEST_K_PID: + ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0), + USB_REQ_SET_FEATURE, USB_RT_PORT, + USB_PORT_FEAT_TEST, + (TEST_K << 8) | portnum, + NULL, 0, 1000); + break; + case TEST_PACKET_PID: + ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0), + USB_REQ_SET_FEATURE, USB_RT_PORT, + USB_PORT_FEAT_TEST, + (TEST_PACKET << 8) | portnum, + NULL, 0, 1000); + break; + case TEST_HS_HOST_PORT_SUSPEND_RESUME: + /* Test: wait for 15secs -> suspend -> 15secs delay -> resume */ + msleep(15 * 1000); + ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0), + USB_REQ_SET_FEATURE, USB_RT_PORT, + USB_PORT_FEAT_SUSPEND, portnum, + NULL, 0, 1000); + if (ret < 0) + break; + + msleep(15 * 1000); + ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0), + USB_REQ_CLEAR_FEATURE, USB_RT_PORT, + USB_PORT_FEAT_SUSPEND, portnum, + NULL, 0, 1000); + break; + case TEST_SINGLE_STEP_GET_DEV_DESC: + /* Test: wait for 15secs -> GetDescriptor request */ + msleep(15 * 1000); + buf = kmalloc(USB_DT_DEVICE_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, + USB_DT_DEVICE << 8, 0, + buf, USB_DT_DEVICE_SIZE, + USB_CTRL_GET_TIMEOUT); + kfree(buf); + break; + case TEST_SINGLE_STEP_SET_FEATURE: + /* + * GetDescriptor SETUP request -> 15secs delay -> IN & STATUS + * + * Note, this test is only supported on root hubs since the + * SetPortFeature handling can only be done inside the HCD's + * hub_control callback function. + */ + if (hub_udev != dev->bus->root_hub) { + dev_err(&intf->dev, "SINGLE_STEP_SET_FEATURE test only supported on root hub\n"); + break; + } + + ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0), + USB_REQ_SET_FEATURE, USB_RT_PORT, + USB_PORT_FEAT_TEST, + (6 << 8) | portnum, + NULL, 0, 60 * 1000); + + break; + default: + dev_err(&intf->dev, "%s: unsupported PID: 0x%x\n", + __func__, test_pid); + } + + return (ret < 0) ? ret : 0; +} + +static void ehset_disconnect(struct usb_interface *intf) +{ +} + +static const struct usb_device_id ehset_id_table[] = { + { USB_DEVICE(0x1a0a, TEST_SE0_NAK_PID) }, + { USB_DEVICE(0x1a0a, TEST_J_PID) }, + { USB_DEVICE(0x1a0a, TEST_K_PID) }, + { USB_DEVICE(0x1a0a, TEST_PACKET_PID) }, + { USB_DEVICE(0x1a0a, TEST_HS_HOST_PORT_SUSPEND_RESUME) }, + { USB_DEVICE(0x1a0a, TEST_SINGLE_STEP_GET_DEV_DESC) }, + { USB_DEVICE(0x1a0a, TEST_SINGLE_STEP_SET_FEATURE) }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, ehset_id_table); + +static struct usb_driver ehset_driver = { + .name = "usb_ehset_test", + .probe = ehset_probe, + .disconnect = ehset_disconnect, + .id_table = ehset_id_table, +}; + +module_usb_driver(ehset_driver); + +MODULE_DESCRIPTION("USB Driver for EHSET Test Fixture"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c index 879a980ca8c..8950fa5e973 100644 --- a/drivers/usb/misc/emi26.c +++ b/drivers/usb/misc/emi26.c @@ -13,7 +13,6 @@ #include <linux/errno.h> #include <linux/slab.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/usb.h> #include <linux/delay.h> #include <linux/firmware.h> @@ -37,9 +36,6 @@ static int emi26_set_reset(struct usb_device *dev, unsigned char reset_bit); static int emi26_load_firmware (struct usb_device *dev); static int emi26_probe(struct usb_interface *intf, const struct usb_device_id *id); static void emi26_disconnect(struct usb_interface *intf); -static int __init emi26_init (void); -static void __exit emi26_exit (void); - /* thanks to drivers/usb/serial/keyspan_pda.c code */ static int emi26_writememory (struct usb_device *dev, int address, @@ -81,18 +77,14 @@ static int emi26_load_firmware (struct usb_device *dev) const struct firmware *bitstream_fw = NULL; const struct firmware *firmware_fw = NULL; const struct ihex_binrec *rec; - int err; + int err = -ENOMEM; int i; __u32 addr; /* Address to write */ __u8 *buf; buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL); - if (!buf) { - dev_err(&dev->dev, "%s - error loading firmware: error = %d\n", - __func__, -ENOMEM); - err = -ENOMEM; + if (!buf) goto wraperr; - } err = request_ihex_firmware(&loader_fw, "emi26/loader.fw", &dev->dev); if (err) @@ -114,11 +106,8 @@ static int emi26_load_firmware (struct usb_device *dev) /* Assert reset (stop the CPU in the EMI) */ err = emi26_set_reset(dev,1); - if (err < 0) { - dev_err(&dev->dev,"%s - error loading firmware: error = %d\n", - __func__, err); + if (err < 0) goto wraperr; - } rec = (const struct ihex_binrec *)loader_fw->data; /* 1. We need to put the loader for the FPGA into the EZ-USB */ @@ -126,19 +115,15 @@ static int emi26_load_firmware (struct usb_device *dev) err = emi26_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_INTERNAL); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } rec = ihex_next_binrec(rec); } /* De-assert reset (let the CPU run) */ err = emi26_set_reset(dev,0); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } msleep(250); /* let device settle */ /* 2. We upload the FPGA firmware into the EMI @@ -156,18 +141,14 @@ static int emi26_load_firmware (struct usb_device *dev) rec = ihex_next_binrec(rec); } err = emi26_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } } while (rec); /* Assert reset (stop the CPU in the EMI) */ err = emi26_set_reset(dev,1); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } /* 3. We need to put the loader for the firmware into the EZ-USB (again...) */ for (rec = (const struct ihex_binrec *)loader_fw->data; @@ -175,19 +156,15 @@ static int emi26_load_firmware (struct usb_device *dev) err = emi26_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_INTERNAL); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } } msleep(250); /* let device settle */ /* De-assert reset (let the CPU run) */ err = emi26_set_reset(dev,0); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } /* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */ @@ -197,19 +174,15 @@ static int emi26_load_firmware (struct usb_device *dev) err = emi26_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_EXTERNAL); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } } } - + /* Assert reset (stop the CPU in the EMI) */ err = emi26_set_reset(dev,1); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } for (rec = (const struct ihex_binrec *)firmware_fw->data; rec; rec = ihex_next_binrec(rec)) { @@ -217,19 +190,15 @@ static int emi26_load_firmware (struct usb_device *dev) err = emi26_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_INTERNAL); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } } } /* De-assert reset (let the CPU run) */ err = emi26_set_reset(dev,0); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } msleep(250); /* let device settle */ /* return 1 to fail the driver inialization @@ -237,6 +206,10 @@ static int emi26_load_firmware (struct usb_device *dev) err = 1; wraperr: + if (err < 0) + dev_err(&dev->dev,"%s - error loading firmware: error = %d\n", + __func__, err); + release_firmware(loader_fw); release_firmware(bitstream_fw); release_firmware(firmware_fw); @@ -245,7 +218,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 */ @@ -276,18 +249,7 @@ static struct usb_driver emi26_driver = { .id_table = id_table, }; -static int __init emi26_init (void) -{ - return usb_register(&emi26_driver); -} - -static void __exit emi26_exit (void) -{ - usb_deregister (&emi26_driver); -} - -module_init(emi26_init); -module_exit(emi26_exit); +module_usb_driver(emi26_driver); MODULE_AUTHOR("Tapio Laxström"); MODULE_DESCRIPTION("Emagic EMI 2|6 firmware loader."); diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c index 59860b32853..1d9be4431b7 100644 --- a/drivers/usb/misc/emi62.c +++ b/drivers/usb/misc/emi62.c @@ -10,7 +10,6 @@ #include <linux/kernel.h> #include <linux/errno.h> #include <linux/slab.h> -#include <linux/init.h> #include <linux/module.h> #include <linux/usb.h> #include <linux/delay.h> @@ -46,9 +45,6 @@ static int emi62_set_reset(struct usb_device *dev, unsigned char reset_bit); static int emi62_load_firmware (struct usb_device *dev); static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *id); static void emi62_disconnect(struct usb_interface *intf); -static int __init emi62_init (void); -static void __exit emi62_exit (void); - /* thanks to drivers/usb/serial/keyspan_pda.c code */ static int emi62_writememory(struct usb_device *dev, int address, @@ -59,7 +55,7 @@ static int emi62_writememory(struct usb_device *dev, int address, unsigned char *buffer = kmemdup(data, length, GFP_KERNEL); if (!buffer) { - err("emi62: kmalloc(%d) failed.", length); + dev_err(&dev->dev, "kmalloc(%d) failed.\n", length); return -ENOMEM; } /* Note: usb_control_msg returns negative value on error or length of the @@ -76,9 +72,8 @@ static int emi62_set_reset (struct usb_device *dev, unsigned char reset_bit) dev_info(&dev->dev, "%s - %d\n", __func__, reset_bit); response = emi62_writememory (dev, CPUCS_REG, &reset_bit, 1, 0xa0); - if (response < 0) { - err("emi62: set_reset (%d) failed", reset_bit); - } + if (response < 0) + dev_err(&dev->dev, "set_reset (%d) failed\n", reset_bit); return response; } @@ -90,18 +85,15 @@ static int emi62_load_firmware (struct usb_device *dev) const struct firmware *bitstream_fw = NULL; const struct firmware *firmware_fw = NULL; const struct ihex_binrec *rec; - int err; + int err = -ENOMEM; int i; __u32 addr; /* Address to write */ __u8 *buf; dev_dbg(&dev->dev, "load_firmware\n"); buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL); - if (!buf) { - err( "%s - error loading firmware: error = %d", __func__, -ENOMEM); - err = -ENOMEM; + if (!buf) goto wraperr; - } err = request_ihex_firmware(&loader_fw, "emi62/loader.fw", &dev->dev); if (err) @@ -115,16 +107,13 @@ static int emi62_load_firmware (struct usb_device *dev) err = request_ihex_firmware(&firmware_fw, FIRMWARE_FW, &dev->dev); if (err) { nofw: - err( "%s - request_firmware() failed", __func__); goto wraperr; } /* Assert reset (stop the CPU in the EMI) */ err = emi62_set_reset(dev,1); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } rec = (const struct ihex_binrec *)loader_fw->data; @@ -133,19 +122,15 @@ static int emi62_load_firmware (struct usb_device *dev) err = emi62_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_INTERNAL); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } rec = ihex_next_binrec(rec); } /* De-assert reset (let the CPU run) */ err = emi62_set_reset(dev,0); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } msleep(250); /* let device settle */ /* 2. We upload the FPGA firmware into the EMI @@ -163,18 +148,14 @@ static int emi62_load_firmware (struct usb_device *dev) rec = ihex_next_binrec(rec); } err = emi62_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } } while (rec); /* Assert reset (stop the CPU in the EMI) */ err = emi62_set_reset(dev,1); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } /* 3. We need to put the loader for the firmware into the EZ-USB (again...) */ for (rec = (const struct ihex_binrec *)loader_fw->data; @@ -182,18 +163,14 @@ static int emi62_load_firmware (struct usb_device *dev) err = emi62_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_INTERNAL); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } } /* De-assert reset (let the CPU run) */ err = emi62_set_reset(dev,0); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } msleep(250); /* let device settle */ /* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */ @@ -204,19 +181,15 @@ static int emi62_load_firmware (struct usb_device *dev) err = emi62_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_EXTERNAL); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } } } /* Assert reset (stop the CPU in the EMI) */ err = emi62_set_reset(dev,1); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } for (rec = (const struct ihex_binrec *)firmware_fw->data; rec; rec = ihex_next_binrec(rec)) { @@ -224,19 +197,15 @@ static int emi62_load_firmware (struct usb_device *dev) err = emi62_writememory(dev, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len), ANCHOR_LOAD_EXTERNAL); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } } } /* De-assert reset (let the CPU run) */ err = emi62_set_reset(dev,0); - if (err < 0) { - err("%s - error loading firmware: error = %d", __func__, err); + if (err < 0) goto wraperr; - } msleep(250); /* let device settle */ release_firmware(loader_fw); @@ -250,6 +219,9 @@ static int emi62_load_firmware (struct usb_device *dev) return 1; wraperr: + if (err < 0) + dev_err(&dev->dev,"%s - error loading firmware: error = %d\n", + __func__, err); release_firmware(loader_fw); release_firmware(bitstream_fw); release_firmware(firmware_fw); @@ -259,7 +231,7 @@ wraperr: return err; } -static __devinitdata struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(EMI62_VENDOR_ID, EMI62_PRODUCT_ID) }, { } /* Terminating entry */ }; @@ -290,22 +262,7 @@ static struct usb_driver emi62_driver = { .id_table = id_table, }; -static int __init emi62_init (void) -{ - int retval; - retval = usb_register (&emi62_driver); - if (retval) - printk(KERN_ERR "adi-emi: registration failed\n"); - return retval; -} - -static void __exit emi62_exit (void) -{ - usb_deregister (&emi62_driver); -} - -module_init(emi62_init); -module_exit(emi62_exit); +module_usb_driver(emi62_driver); MODULE_AUTHOR("Tapio Laxström"); MODULE_DESCRIPTION("Emagic EMI 6|2m firmware loader."); diff --git a/drivers/usb/misc/ezusb.c b/drivers/usb/misc/ezusb.c new file mode 100644 index 00000000000..947811bc812 --- /dev/null +++ b/drivers/usb/misc/ezusb.c @@ -0,0 +1,166 @@ +/* + * EZ-USB specific functions used by some of the USB to Serial drivers. + * + * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.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/slab.h> +#include <linux/module.h> +#include <linux/usb.h> +#include <linux/firmware.h> +#include <linux/ihex.h> +#include <linux/usb/ezusb.h> + +struct ezusb_fx_type { + /* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */ + unsigned short cpucs_reg; + unsigned short max_internal_adress; +}; + +static struct ezusb_fx_type ezusb_fx1 = { + .cpucs_reg = 0x7F92, + .max_internal_adress = 0x1B3F, +}; + +/* Commands for writing to memory */ +#define WRITE_INT_RAM 0xA0 +#define WRITE_EXT_RAM 0xA3 + +static int ezusb_writememory(struct usb_device *dev, int address, + unsigned char *data, int length, __u8 request) +{ + int result; + unsigned char *transfer_buffer; + + if (!dev) + return -ENODEV; + + transfer_buffer = kmemdup(data, length, GFP_KERNEL); + if (!transfer_buffer) { + dev_err(&dev->dev, "%s - kmalloc(%d) failed.\n", + __func__, length); + return -ENOMEM; + } + result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + address, 0, transfer_buffer, length, 3000); + + kfree(transfer_buffer); + return result; +} + +static int ezusb_set_reset(struct usb_device *dev, unsigned short cpucs_reg, + unsigned char reset_bit) +{ + int response = ezusb_writememory(dev, cpucs_reg, &reset_bit, 1, WRITE_INT_RAM); + if (response < 0) + dev_err(&dev->dev, "%s-%d failed: %d\n", + __func__, reset_bit, response); + return response; +} + +int ezusb_fx1_set_reset(struct usb_device *dev, unsigned char reset_bit) +{ + return ezusb_set_reset(dev, ezusb_fx1.cpucs_reg, reset_bit); +} +EXPORT_SYMBOL_GPL(ezusb_fx1_set_reset); + +static int ezusb_ihex_firmware_download(struct usb_device *dev, + struct ezusb_fx_type fx, + const char *firmware_path) +{ + int ret = -ENOENT; + const struct firmware *firmware = NULL; + const struct ihex_binrec *record; + + if (request_ihex_firmware(&firmware, firmware_path, + &dev->dev)) { + dev_err(&dev->dev, + "%s - request \"%s\" failed\n", + __func__, firmware_path); + goto out; + } + + ret = ezusb_set_reset(dev, fx.cpucs_reg, 0); + if (ret < 0) + goto out; + + record = (const struct ihex_binrec *)firmware->data; + for (; record; record = ihex_next_binrec(record)) { + if (be32_to_cpu(record->addr) > fx.max_internal_adress) { + ret = ezusb_writememory(dev, be32_to_cpu(record->addr), + (unsigned char *)record->data, + be16_to_cpu(record->len), WRITE_EXT_RAM); + if (ret < 0) { + dev_err(&dev->dev, "%s - ezusb_writememory " + "failed writing internal memory " + "(%d %04X %p %d)\n", __func__, ret, + be32_to_cpu(record->addr), record->data, + be16_to_cpu(record->len)); + goto out; + } + } + } + + ret = ezusb_set_reset(dev, fx.cpucs_reg, 1); + if (ret < 0) + goto out; + record = (const struct ihex_binrec *)firmware->data; + for (; record; record = ihex_next_binrec(record)) { + if (be32_to_cpu(record->addr) <= fx.max_internal_adress) { + ret = ezusb_writememory(dev, be32_to_cpu(record->addr), + (unsigned char *)record->data, + be16_to_cpu(record->len), WRITE_INT_RAM); + if (ret < 0) { + dev_err(&dev->dev, "%s - ezusb_writememory " + "failed writing external memory " + "(%d %04X %p %d)\n", __func__, ret, + be32_to_cpu(record->addr), record->data, + be16_to_cpu(record->len)); + goto out; + } + } + } + ret = ezusb_set_reset(dev, fx.cpucs_reg, 0); +out: + release_firmware(firmware); + return ret; +} + +int ezusb_fx1_ihex_firmware_download(struct usb_device *dev, + const char *firmware_path) +{ + return ezusb_ihex_firmware_download(dev, ezusb_fx1, firmware_path); +} +EXPORT_SYMBOL_GPL(ezusb_fx1_ihex_firmware_download); + +#if 0 +/* + * Once someone one needs these fx2 functions, uncomment them + * and add them to ezusb.h and all should be good. + */ +static struct ezusb_fx_type ezusb_fx2 = { + .cpucs_reg = 0xE600, + .max_internal_adress = 0x3FFF, +}; + +int ezusb_fx2_set_reset(struct usb_device *dev, unsigned char reset_bit) +{ + return ezusb_set_reset(dev, ezusb_fx2.cpucs_reg, reset_bit); +} +EXPORT_SYMBOL_GPL(ezusb_fx2_set_reset); + +int ezusb_fx2_ihex_firmware_download(struct usb_device *dev, + const char *firmware_path) +{ + return ezusb_ihex_firmware_download(dev, ezusb_fx2, firmware_path); +} +EXPORT_SYMBOL_GPL(ezusb_fx2_ihex_firmware_download); +#endif + +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 9d0675ed0d4..8ab1f8f3c26 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -1,40 +1,43 @@ /* -* USB FTDI client driver for Elan Digital Systems's Uxxx adapters -* -* Copyright(C) 2006 Elan Digital Systems Limited -* http://www.elandigitalsystems.com -* -* Author and Maintainer - Tony Olech - Elan Digital Systems -* tony.olech@elandigitalsystems.com -* -* 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. -* -* -* This driver was written by Tony Olech(tony.olech@elandigitalsystems.com) -* based on various USB client drivers in the 2.6.15 linux kernel -* with constant reference to the 3rd Edition of Linux Device Drivers -* published by O'Reilly -* -* The U132 adapter is a USB to CardBus adapter specifically designed -* for PC cards that contain an OHCI host controller. Typical PC cards -* are the Orange Mobile 3G Option GlobeTrotter Fusion card. -* -* The U132 adapter will *NOT *work with PC cards that do not contain -* an OHCI controller. A simple way to test whether a PC card has an -* OHCI controller as an interface is to insert the PC card directly -* into a laptop(or desktop) with a CardBus slot and if "lspci" shows -* a new USB controller and "lsusb -v" shows a new OHCI Host Controller -* then there is a good chance that the U132 adapter will support the -* PC card.(you also need the specific client driver for the PC card) -* -* Please inform the Author and Maintainer about any PC cards that -* contain OHCI Host Controller and work when directly connected to -* an embedded CardBus slot but do not work when they are connected -* via an ELAN U132 adapter. -* -*/ + * USB FTDI client driver for Elan Digital Systems's Uxxx adapters + * + * Copyright(C) 2006 Elan Digital Systems Limited + * http://www.elandigitalsystems.com + * + * Author and Maintainer - Tony Olech - Elan Digital Systems + * tony.olech@elandigitalsystems.com + * + * 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. + * + * + * This driver was written by Tony Olech(tony.olech@elandigitalsystems.com) + * based on various USB client drivers in the 2.6.15 linux kernel + * with constant reference to the 3rd Edition of Linux Device Drivers + * published by O'Reilly + * + * The U132 adapter is a USB to CardBus adapter specifically designed + * for PC cards that contain an OHCI host controller. Typical PC cards + * are the Orange Mobile 3G Option GlobeTrotter Fusion card. + * + * The U132 adapter will *NOT *work with PC cards that do not contain + * an OHCI controller. A simple way to test whether a PC card has an + * OHCI controller as an interface is to insert the PC card directly + * into a laptop(or desktop) with a CardBus slot and if "lspci" shows + * a new USB controller and "lsusb -v" shows a new OHCI Host Controller + * then there is a good chance that the U132 adapter will support the + * PC card.(you also need the specific client driver for the PC card) + * + * Please inform the Author and Maintainer about any PC cards that + * contain OHCI Host Controller and work when directly connected to + * an embedded CardBus slot but do not work when they are connected + * via an ELAN U132 adapter. + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/kernel.h> #include <linux/errno.h> #include <linux/init.h> @@ -53,174 +56,174 @@ MODULE_AUTHOR("Tony Olech"); MODULE_DESCRIPTION("FTDI ELAN driver"); MODULE_LICENSE("GPL"); #define INT_MODULE_PARM(n, v) static int n = v;module_param(n, int, 0444) -static int distrust_firmware = 1; +static bool distrust_firmware = 1; module_param(distrust_firmware, bool, 0); -MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren" - "t setup"); +MODULE_PARM_DESC(distrust_firmware, + "true to distrust firmware power/overcurrent setup"); extern struct platform_driver u132_platform_driver; static struct workqueue_struct *status_queue; static struct workqueue_struct *command_queue; static struct workqueue_struct *respond_queue; /* -* ftdi_module_lock exists to protect access to global variables -* -*/ + * ftdi_module_lock exists to protect access to global variables + * + */ static struct mutex ftdi_module_lock; static int ftdi_instances = 0; static struct list_head ftdi_static_list; /* -* end of the global variables protected by ftdi_module_lock -*/ + * end of the global variables protected by ftdi_module_lock + */ #include "usb_u132.h" #include <asm/io.h> -#include "../core/hcd.h" +#include <linux/usb/hcd.h> - /* FIXME ohci.h is ONLY for internal use by the OHCI driver. - * If you're going to try stuff like this, you need to split - * out shareable stuff (register declarations?) into its own - * file, maybe name <linux/usb/ohci.h> - */ +/* FIXME ohci.h is ONLY for internal use by the OHCI driver. + * If you're going to try stuff like this, you need to split + * out shareable stuff (register declarations?) into its own + * file, maybe name <linux/usb/ohci.h> + */ #include "../host/ohci.h" /* Define these values to match your devices*/ #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[] = { - {USB_DEVICE(USB_FTDI_ELAN_VENDOR_ID, USB_FTDI_ELAN_PRODUCT_ID)}, - { /* Terminating entry */ } +static const struct usb_device_id ftdi_elan_table[] = { + {USB_DEVICE(USB_FTDI_ELAN_VENDOR_ID, USB_FTDI_ELAN_PRODUCT_ID)}, + { /* Terminating entry */ } }; MODULE_DEVICE_TABLE(usb, ftdi_elan_table); /* only the jtag(firmware upgrade device) interface requires -* a device file and corresponding minor number, but the -* interface is created unconditionally - I suppose it could -* be configured or not according to a module parameter. -* But since we(now) require one interface per device, -* and since it unlikely that a normal installation would -* require more than a couple of elan-ftdi devices, 8 seems -* like a reasonable limit to have here, and if someone -* really requires more than 8 devices, then they can frig the -* code and recompile -*/ + * a device file and corresponding minor number, but the + * interface is created unconditionally - I suppose it could + * be configured or not according to a module parameter. + * But since we(now) require one interface per device, + * and since it unlikely that a normal installation would + * require more than a couple of elan-ftdi devices, 8 seems + * like a reasonable limit to have here, and if someone + * really requires more than 8 devices, then they can frig the + * code and recompile + */ #define USB_FTDI_ELAN_MINOR_BASE 192 #define COMMAND_BITS 5 #define COMMAND_SIZE (1<<COMMAND_BITS) #define COMMAND_MASK (COMMAND_SIZE-1) struct u132_command { - u8 header; - u16 length; - u8 address; - u8 width; - u32 value; - int follows; - void *buffer; + u8 header; + u16 length; + u8 address; + u8 width; + u32 value; + int follows; + void *buffer; }; #define RESPOND_BITS 5 #define RESPOND_SIZE (1<<RESPOND_BITS) #define RESPOND_MASK (RESPOND_SIZE-1) struct u132_respond { - u8 header; - u8 address; - u32 *value; - int *result; - struct completion wait_completion; + u8 header; + u8 address; + u32 *value; + int *result; + struct completion wait_completion; }; struct u132_target { - void *endp; - struct urb *urb; - int toggle_bits; - int error_count; - int condition_code; - int repeat_number; - int halted; - int skipped; - int actual; - int non_null; - int active; - int abandoning; - void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, - int toggle_bits, int error_count, int condition_code, - int repeat_number, int halted, int skipped, int actual, - int non_null); + void *endp; + struct urb *urb; + int toggle_bits; + int error_count; + int condition_code; + int repeat_number; + int halted; + int skipped; + int actual; + int non_null; + int active; + int abandoning; + void (*callback)(void *endp, struct urb *urb, u8 *buf, int len, + int toggle_bits, int error_count, int condition_code, + int repeat_number, int halted, int skipped, int actual, + int non_null); }; /* Structure to hold all of our device specific stuff*/ struct usb_ftdi { - struct list_head ftdi_list; - struct mutex u132_lock; - int command_next; - int command_head; - struct u132_command command[COMMAND_SIZE]; - int respond_next; - int respond_head; - struct u132_respond respond[RESPOND_SIZE]; - struct u132_target target[4]; - char device_name[16]; - unsigned synchronized:1; - unsigned enumerated:1; - unsigned registered:1; - unsigned initialized:1; - unsigned card_ejected:1; - int function; - int sequence_num; - int disconnected; - int gone_away; - int stuck_status; - int status_queue_delay; - struct semaphore sw_lock; - struct usb_device *udev; - struct usb_interface *interface; - struct usb_class_driver *class; - struct delayed_work status_work; - struct delayed_work command_work; - struct delayed_work respond_work; - struct u132_platform_data platform_data; - struct resource resources[0]; - struct platform_device platform_dev; - unsigned char *bulk_in_buffer; - size_t bulk_in_size; - size_t bulk_in_last; - size_t bulk_in_left; - __u8 bulk_in_endpointAddr; - __u8 bulk_out_endpointAddr; - struct kref kref; - u32 controlreg; - u8 response[4 + 1024]; - int expected; - int recieved; - int ed_found; + struct list_head ftdi_list; + struct mutex u132_lock; + int command_next; + int command_head; + struct u132_command command[COMMAND_SIZE]; + int respond_next; + int respond_head; + struct u132_respond respond[RESPOND_SIZE]; + struct u132_target target[4]; + char device_name[16]; + unsigned synchronized:1; + unsigned enumerated:1; + unsigned registered:1; + unsigned initialized:1; + unsigned card_ejected:1; + int function; + int sequence_num; + int disconnected; + int gone_away; + int stuck_status; + int status_queue_delay; + struct semaphore sw_lock; + struct usb_device *udev; + struct usb_interface *interface; + struct usb_class_driver *class; + struct delayed_work status_work; + struct delayed_work command_work; + struct delayed_work respond_work; + struct u132_platform_data platform_data; + struct resource resources[0]; + struct platform_device platform_dev; + unsigned char *bulk_in_buffer; + size_t bulk_in_size; + size_t bulk_in_last; + size_t bulk_in_left; + __u8 bulk_in_endpointAddr; + __u8 bulk_out_endpointAddr; + struct kref kref; + u32 controlreg; + u8 response[4 + 1024]; + int expected; + int received; + int ed_found; }; #define kref_to_usb_ftdi(d) container_of(d, struct usb_ftdi, kref) #define platform_device_to_usb_ftdi(d) container_of(d, struct usb_ftdi, \ - platform_dev) + platform_dev) static struct usb_driver ftdi_elan_driver; static void ftdi_elan_delete(struct kref *kref) { - struct usb_ftdi *ftdi = kref_to_usb_ftdi(kref); - dev_warn(&ftdi->udev->dev, "FREEING ftdi=%p\n", ftdi); - usb_put_dev(ftdi->udev); - ftdi->disconnected += 1; - mutex_lock(&ftdi_module_lock); - list_del_init(&ftdi->ftdi_list); - ftdi_instances -= 1; - mutex_unlock(&ftdi_module_lock); - kfree(ftdi->bulk_in_buffer); - ftdi->bulk_in_buffer = NULL; + struct usb_ftdi *ftdi = kref_to_usb_ftdi(kref); + dev_warn(&ftdi->udev->dev, "FREEING ftdi=%p\n", ftdi); + usb_put_dev(ftdi->udev); + ftdi->disconnected += 1; + mutex_lock(&ftdi_module_lock); + list_del_init(&ftdi->ftdi_list); + ftdi_instances -= 1; + mutex_unlock(&ftdi_module_lock); + kfree(ftdi->bulk_in_buffer); + ftdi->bulk_in_buffer = NULL; } static void ftdi_elan_put_kref(struct usb_ftdi *ftdi) { - kref_put(&ftdi->kref, ftdi_elan_delete); + kref_put(&ftdi->kref, ftdi_elan_delete); } static void ftdi_elan_get_kref(struct usb_ftdi *ftdi) { - kref_get(&ftdi->kref); + kref_get(&ftdi->kref); } static void ftdi_elan_init_kref(struct usb_ftdi *ftdi) { - kref_init(&ftdi->kref); + kref_init(&ftdi->kref); } static void ftdi_status_requeue_work(struct usb_ftdi *ftdi, unsigned int delta) @@ -237,8 +240,8 @@ static void ftdi_status_queue_work(struct usb_ftdi *ftdi, unsigned int delta) static void ftdi_status_cancel_work(struct usb_ftdi *ftdi) { - if (cancel_delayed_work(&ftdi->status_work)) - kref_put(&ftdi->kref, ftdi_elan_delete); + if (cancel_delayed_work(&ftdi->status_work)) + kref_put(&ftdi->kref, ftdi_elan_delete); } static void ftdi_command_requeue_work(struct usb_ftdi *ftdi, unsigned int delta) @@ -255,12 +258,12 @@ static void ftdi_command_queue_work(struct usb_ftdi *ftdi, unsigned int delta) static void ftdi_command_cancel_work(struct usb_ftdi *ftdi) { - if (cancel_delayed_work(&ftdi->command_work)) - kref_put(&ftdi->kref, ftdi_elan_delete); + if (cancel_delayed_work(&ftdi->command_work)) + kref_put(&ftdi->kref, ftdi_elan_delete); } static void ftdi_response_requeue_work(struct usb_ftdi *ftdi, - unsigned int delta) + unsigned int delta) { if (!queue_delayed_work(respond_queue, &ftdi->respond_work, delta)) kref_put(&ftdi->kref, ftdi_elan_delete); @@ -274,26 +277,26 @@ static void ftdi_respond_queue_work(struct usb_ftdi *ftdi, unsigned int delta) static void ftdi_response_cancel_work(struct usb_ftdi *ftdi) { - if (cancel_delayed_work(&ftdi->respond_work)) - kref_put(&ftdi->kref, ftdi_elan_delete); + if (cancel_delayed_work(&ftdi->respond_work)) + kref_put(&ftdi->kref, ftdi_elan_delete); } void ftdi_elan_gone_away(struct platform_device *pdev) { - struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); - ftdi->gone_away += 1; - ftdi_elan_put_kref(ftdi); + struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); + ftdi->gone_away += 1; + ftdi_elan_put_kref(ftdi); } EXPORT_SYMBOL_GPL(ftdi_elan_gone_away); static void ftdi_release_platform_dev(struct device *dev) { - dev->parent = NULL; + dev->parent = NULL; } static void ftdi_elan_do_callback(struct usb_ftdi *ftdi, - struct u132_target *target, u8 *buffer, int length); + struct u132_target *target, u8 *buffer, int length); static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi); static void ftdi_elan_kick_respond_queue(struct usb_ftdi *ftdi); static int ftdi_elan_setupOHCI(struct usb_ftdi *ftdi); @@ -305,420 +308,416 @@ static int ftdi_elan_command_engine(struct usb_ftdi *ftdi); static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi); static int ftdi_elan_hcd_init(struct usb_ftdi *ftdi) { - int result; - if (ftdi->platform_dev.dev.parent) - return -EBUSY; - ftdi_elan_get_kref(ftdi); - ftdi->platform_data.potpg = 100; - ftdi->platform_data.reset = NULL; - ftdi->platform_dev.id = ftdi->sequence_num; - ftdi->platform_dev.resource = ftdi->resources; - ftdi->platform_dev.num_resources = ARRAY_SIZE(ftdi->resources); - ftdi->platform_dev.dev.platform_data = &ftdi->platform_data; - ftdi->platform_dev.dev.parent = NULL; - ftdi->platform_dev.dev.release = ftdi_release_platform_dev; - ftdi->platform_dev.dev.dma_mask = NULL; - snprintf(ftdi->device_name, sizeof(ftdi->device_name), "u132_hcd"); - ftdi->platform_dev.name = ftdi->device_name; - dev_info(&ftdi->udev->dev, "requesting module '%s'\n", "u132_hcd"); - request_module("u132_hcd"); - dev_info(&ftdi->udev->dev, "registering '%s'\n", - ftdi->platform_dev.name); - result = platform_device_register(&ftdi->platform_dev); - return result; + int result; + if (ftdi->platform_dev.dev.parent) + return -EBUSY; + ftdi_elan_get_kref(ftdi); + ftdi->platform_data.potpg = 100; + ftdi->platform_data.reset = NULL; + ftdi->platform_dev.id = ftdi->sequence_num; + ftdi->platform_dev.resource = ftdi->resources; + ftdi->platform_dev.num_resources = ARRAY_SIZE(ftdi->resources); + ftdi->platform_dev.dev.platform_data = &ftdi->platform_data; + ftdi->platform_dev.dev.parent = NULL; + ftdi->platform_dev.dev.release = ftdi_release_platform_dev; + ftdi->platform_dev.dev.dma_mask = NULL; + snprintf(ftdi->device_name, sizeof(ftdi->device_name), "u132_hcd"); + ftdi->platform_dev.name = ftdi->device_name; + dev_info(&ftdi->udev->dev, "requesting module '%s'\n", "u132_hcd"); + request_module("u132_hcd"); + dev_info(&ftdi->udev->dev, "registering '%s'\n", + ftdi->platform_dev.name); + result = platform_device_register(&ftdi->platform_dev); + return result; } static void ftdi_elan_abandon_completions(struct usb_ftdi *ftdi) { - mutex_lock(&ftdi->u132_lock); - while (ftdi->respond_next > ftdi->respond_head) { - struct u132_respond *respond = &ftdi->respond[RESPOND_MASK & - ftdi->respond_head++]; - *respond->result = -ESHUTDOWN; - *respond->value = 0; - complete(&respond->wait_completion); - } mutex_unlock(&ftdi->u132_lock); + mutex_lock(&ftdi->u132_lock); + while (ftdi->respond_next > ftdi->respond_head) { + struct u132_respond *respond = &ftdi->respond[RESPOND_MASK & + ftdi->respond_head++]; + *respond->result = -ESHUTDOWN; + *respond->value = 0; + complete(&respond->wait_completion); + } mutex_unlock(&ftdi->u132_lock); } static void ftdi_elan_abandon_targets(struct usb_ftdi *ftdi) { - int ed_number = 4; - mutex_lock(&ftdi->u132_lock); - while (ed_number-- > 0) { - struct u132_target *target = &ftdi->target[ed_number]; - if (target->active == 1) { - target->condition_code = TD_DEVNOTRESP; - mutex_unlock(&ftdi->u132_lock); - ftdi_elan_do_callback(ftdi, target, NULL, 0); - mutex_lock(&ftdi->u132_lock); - } - } - ftdi->recieved = 0; - ftdi->expected = 4; - ftdi->ed_found = 0; - mutex_unlock(&ftdi->u132_lock); + int ed_number = 4; + mutex_lock(&ftdi->u132_lock); + while (ed_number-- > 0) { + struct u132_target *target = &ftdi->target[ed_number]; + if (target->active == 1) { + target->condition_code = TD_DEVNOTRESP; + mutex_unlock(&ftdi->u132_lock); + ftdi_elan_do_callback(ftdi, target, NULL, 0); + mutex_lock(&ftdi->u132_lock); + } + } + ftdi->received = 0; + ftdi->expected = 4; + ftdi->ed_found = 0; + mutex_unlock(&ftdi->u132_lock); } static void ftdi_elan_flush_targets(struct usb_ftdi *ftdi) { - int ed_number = 4; - mutex_lock(&ftdi->u132_lock); - while (ed_number-- > 0) { - struct u132_target *target = &ftdi->target[ed_number]; - target->abandoning = 1; - wait_1:if (target->active == 1) { - int command_size = ftdi->command_next - - ftdi->command_head; - if (command_size < COMMAND_SIZE) { - struct u132_command *command = &ftdi->command[ - COMMAND_MASK & ftdi->command_next]; - command->header = 0x80 | (ed_number << 5) | 0x4; - command->length = 0x00; - command->address = 0x00; - command->width = 0x00; - command->follows = 0; - command->value = 0; - command->buffer = &command->value; - ftdi->command_next += 1; - ftdi_elan_kick_command_queue(ftdi); - } else { - mutex_unlock(&ftdi->u132_lock); - msleep(100); - mutex_lock(&ftdi->u132_lock); - goto wait_1; - } - } - wait_2:if (target->active == 1) { - int command_size = ftdi->command_next - - ftdi->command_head; - if (command_size < COMMAND_SIZE) { - struct u132_command *command = &ftdi->command[ - COMMAND_MASK & ftdi->command_next]; - command->header = 0x90 | (ed_number << 5); - command->length = 0x00; - command->address = 0x00; - command->width = 0x00; - command->follows = 0; - command->value = 0; - command->buffer = &command->value; - ftdi->command_next += 1; - ftdi_elan_kick_command_queue(ftdi); - } else { - mutex_unlock(&ftdi->u132_lock); - msleep(100); - mutex_lock(&ftdi->u132_lock); - goto wait_2; - } - } - } - ftdi->recieved = 0; - ftdi->expected = 4; - ftdi->ed_found = 0; - mutex_unlock(&ftdi->u132_lock); + int ed_number = 4; + mutex_lock(&ftdi->u132_lock); + while (ed_number-- > 0) { + struct u132_target *target = &ftdi->target[ed_number]; + target->abandoning = 1; + wait_1:if (target->active == 1) { + int command_size = ftdi->command_next - + ftdi->command_head; + if (command_size < COMMAND_SIZE) { + struct u132_command *command = &ftdi->command[ + COMMAND_MASK & ftdi->command_next]; + command->header = 0x80 | (ed_number << 5) | 0x4; + command->length = 0x00; + command->address = 0x00; + command->width = 0x00; + command->follows = 0; + command->value = 0; + command->buffer = &command->value; + ftdi->command_next += 1; + ftdi_elan_kick_command_queue(ftdi); + } else { + mutex_unlock(&ftdi->u132_lock); + msleep(100); + mutex_lock(&ftdi->u132_lock); + goto wait_1; + } + } + wait_2:if (target->active == 1) { + int command_size = ftdi->command_next - + ftdi->command_head; + if (command_size < COMMAND_SIZE) { + struct u132_command *command = &ftdi->command[ + COMMAND_MASK & ftdi->command_next]; + command->header = 0x90 | (ed_number << 5); + command->length = 0x00; + command->address = 0x00; + command->width = 0x00; + command->follows = 0; + command->value = 0; + command->buffer = &command->value; + ftdi->command_next += 1; + ftdi_elan_kick_command_queue(ftdi); + } else { + mutex_unlock(&ftdi->u132_lock); + msleep(100); + mutex_lock(&ftdi->u132_lock); + goto wait_2; + } + } + } + ftdi->received = 0; + ftdi->expected = 4; + ftdi->ed_found = 0; + mutex_unlock(&ftdi->u132_lock); } static void ftdi_elan_cancel_targets(struct usb_ftdi *ftdi) { - int ed_number = 4; - mutex_lock(&ftdi->u132_lock); - while (ed_number-- > 0) { - struct u132_target *target = &ftdi->target[ed_number]; - target->abandoning = 1; - wait:if (target->active == 1) { - int command_size = ftdi->command_next - - ftdi->command_head; - if (command_size < COMMAND_SIZE) { - struct u132_command *command = &ftdi->command[ - COMMAND_MASK & ftdi->command_next]; - command->header = 0x80 | (ed_number << 5) | 0x4; - command->length = 0x00; - command->address = 0x00; - command->width = 0x00; - command->follows = 0; - command->value = 0; - command->buffer = &command->value; - ftdi->command_next += 1; - ftdi_elan_kick_command_queue(ftdi); - } else { - mutex_unlock(&ftdi->u132_lock); - msleep(100); - mutex_lock(&ftdi->u132_lock); - goto wait; - } - } - } - ftdi->recieved = 0; - ftdi->expected = 4; - ftdi->ed_found = 0; - mutex_unlock(&ftdi->u132_lock); + int ed_number = 4; + mutex_lock(&ftdi->u132_lock); + while (ed_number-- > 0) { + struct u132_target *target = &ftdi->target[ed_number]; + target->abandoning = 1; + wait:if (target->active == 1) { + int command_size = ftdi->command_next - + ftdi->command_head; + if (command_size < COMMAND_SIZE) { + struct u132_command *command = &ftdi->command[ + COMMAND_MASK & ftdi->command_next]; + command->header = 0x80 | (ed_number << 5) | 0x4; + command->length = 0x00; + command->address = 0x00; + command->width = 0x00; + command->follows = 0; + command->value = 0; + command->buffer = &command->value; + ftdi->command_next += 1; + ftdi_elan_kick_command_queue(ftdi); + } else { + mutex_unlock(&ftdi->u132_lock); + msleep(100); + mutex_lock(&ftdi->u132_lock); + goto wait; + } + } + } + ftdi->received = 0; + ftdi->expected = 4; + ftdi->ed_found = 0; + mutex_unlock(&ftdi->u132_lock); } static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi) { - ftdi_command_queue_work(ftdi, 0); - return; + ftdi_command_queue_work(ftdi, 0); } static void ftdi_elan_command_work(struct work_struct *work) { - struct usb_ftdi *ftdi = + struct usb_ftdi *ftdi = container_of(work, struct usb_ftdi, command_work.work); - if (ftdi->disconnected > 0) { - ftdi_elan_put_kref(ftdi); - return; - } else { - int retval = ftdi_elan_command_engine(ftdi); - if (retval == -ESHUTDOWN) { - ftdi->disconnected += 1; - } else if (retval == -ENODEV) { - ftdi->disconnected += 1; - } else if (retval) - dev_err(&ftdi->udev->dev, "command error %d\n", retval); - ftdi_command_requeue_work(ftdi, msecs_to_jiffies(10)); - return; - } + if (ftdi->disconnected > 0) { + ftdi_elan_put_kref(ftdi); + return; + } else { + int retval = ftdi_elan_command_engine(ftdi); + if (retval == -ESHUTDOWN) { + ftdi->disconnected += 1; + } else if (retval == -ENODEV) { + ftdi->disconnected += 1; + } else if (retval) + dev_err(&ftdi->udev->dev, "command error %d\n", retval); + ftdi_command_requeue_work(ftdi, msecs_to_jiffies(10)); + return; + } } static void ftdi_elan_kick_respond_queue(struct usb_ftdi *ftdi) { - ftdi_respond_queue_work(ftdi, 0); - return; + ftdi_respond_queue_work(ftdi, 0); } static void ftdi_elan_respond_work(struct work_struct *work) { - struct usb_ftdi *ftdi = + struct usb_ftdi *ftdi = container_of(work, struct usb_ftdi, respond_work.work); - if (ftdi->disconnected > 0) { - ftdi_elan_put_kref(ftdi); - return; - } else { - int retval = ftdi_elan_respond_engine(ftdi); - if (retval == 0) { - } else if (retval == -ESHUTDOWN) { - ftdi->disconnected += 1; - } else if (retval == -ENODEV) { - ftdi->disconnected += 1; - } else if (retval == -EILSEQ) { - ftdi->disconnected += 1; - } else { - ftdi->disconnected += 1; - dev_err(&ftdi->udev->dev, "respond error %d\n", retval); - } - if (ftdi->disconnected > 0) { - ftdi_elan_abandon_completions(ftdi); - ftdi_elan_abandon_targets(ftdi); - } - ftdi_response_requeue_work(ftdi, msecs_to_jiffies(10)); - return; - } + if (ftdi->disconnected > 0) { + ftdi_elan_put_kref(ftdi); + return; + } else { + int retval = ftdi_elan_respond_engine(ftdi); + if (retval == 0) { + } else if (retval == -ESHUTDOWN) { + ftdi->disconnected += 1; + } else if (retval == -ENODEV) { + ftdi->disconnected += 1; + } else if (retval == -EILSEQ) { + ftdi->disconnected += 1; + } else { + ftdi->disconnected += 1; + dev_err(&ftdi->udev->dev, "respond error %d\n", retval); + } + if (ftdi->disconnected > 0) { + ftdi_elan_abandon_completions(ftdi); + ftdi_elan_abandon_targets(ftdi); + } + ftdi_response_requeue_work(ftdi, msecs_to_jiffies(10)); + return; + } } /* -* the sw_lock is initially held and will be freed -* after the FTDI has been synchronized -* -*/ + * the sw_lock is initially held and will be freed + * after the FTDI has been synchronized + * + */ static void ftdi_elan_status_work(struct work_struct *work) { - struct usb_ftdi *ftdi = + struct usb_ftdi *ftdi = container_of(work, struct usb_ftdi, status_work.work); - int work_delay_in_msec = 0; - if (ftdi->disconnected > 0) { - ftdi_elan_put_kref(ftdi); - return; - } else if (ftdi->synchronized == 0) { - down(&ftdi->sw_lock); - if (ftdi_elan_synchronize(ftdi) == 0) { - ftdi->synchronized = 1; - ftdi_command_queue_work(ftdi, 1); - ftdi_respond_queue_work(ftdi, 1); - up(&ftdi->sw_lock); - work_delay_in_msec = 100; - } else { - dev_err(&ftdi->udev->dev, "synchronize failed\n"); - up(&ftdi->sw_lock); - work_delay_in_msec = 10 *1000; - } - } else if (ftdi->stuck_status > 0) { - if (ftdi_elan_stuck_waiting(ftdi) == 0) { - ftdi->stuck_status = 0; - ftdi->synchronized = 0; - } else if ((ftdi->stuck_status++ % 60) == 1) { - dev_err(&ftdi->udev->dev, "WRONG type of card inserted " - "- please remove\n"); - } else - dev_err(&ftdi->udev->dev, "WRONG type of card inserted " - "- checked %d times\n", ftdi->stuck_status); - work_delay_in_msec = 100; - } else if (ftdi->enumerated == 0) { - if (ftdi_elan_enumeratePCI(ftdi) == 0) { - ftdi->enumerated = 1; - work_delay_in_msec = 250; - } else - work_delay_in_msec = 1000; - } else if (ftdi->initialized == 0) { - if (ftdi_elan_setupOHCI(ftdi) == 0) { - ftdi->initialized = 1; - work_delay_in_msec = 500; - } else { - dev_err(&ftdi->udev->dev, "initialized failed - trying " - "again in 10 seconds\n"); - work_delay_in_msec = 1 *1000; - } - } else if (ftdi->registered == 0) { - work_delay_in_msec = 10; - if (ftdi_elan_hcd_init(ftdi) == 0) { - ftdi->registered = 1; - } else - dev_err(&ftdi->udev->dev, "register failed\n"); - work_delay_in_msec = 250; - } else { - if (ftdi_elan_checkingPCI(ftdi) == 0) { - work_delay_in_msec = 250; - } else if (ftdi->controlreg & 0x00400000) { - if (ftdi->gone_away > 0) { - dev_err(&ftdi->udev->dev, "PCI device eject con" - "firmed platform_dev.dev.parent=%p plat" - "form_dev.dev=%p\n", - ftdi->platform_dev.dev.parent, - &ftdi->platform_dev.dev); - platform_device_unregister(&ftdi->platform_dev); - ftdi->platform_dev.dev.parent = NULL; - ftdi->registered = 0; - ftdi->enumerated = 0; - ftdi->card_ejected = 0; - ftdi->initialized = 0; - ftdi->gone_away = 0; - } else - ftdi_elan_flush_targets(ftdi); - work_delay_in_msec = 250; - } else { - dev_err(&ftdi->udev->dev, "PCI device has disappeared\n" - ); - ftdi_elan_cancel_targets(ftdi); - work_delay_in_msec = 500; - ftdi->enumerated = 0; - ftdi->initialized = 0; - } - } - if (ftdi->disconnected > 0) { - ftdi_elan_put_kref(ftdi); - return; - } else { - ftdi_status_requeue_work(ftdi, - msecs_to_jiffies(work_delay_in_msec)); - return; - } + int work_delay_in_msec = 0; + if (ftdi->disconnected > 0) { + ftdi_elan_put_kref(ftdi); + return; + } else if (ftdi->synchronized == 0) { + down(&ftdi->sw_lock); + if (ftdi_elan_synchronize(ftdi) == 0) { + ftdi->synchronized = 1; + ftdi_command_queue_work(ftdi, 1); + ftdi_respond_queue_work(ftdi, 1); + up(&ftdi->sw_lock); + work_delay_in_msec = 100; + } else { + dev_err(&ftdi->udev->dev, "synchronize failed\n"); + up(&ftdi->sw_lock); + work_delay_in_msec = 10 *1000; + } + } else if (ftdi->stuck_status > 0) { + if (ftdi_elan_stuck_waiting(ftdi) == 0) { + ftdi->stuck_status = 0; + ftdi->synchronized = 0; + } else if ((ftdi->stuck_status++ % 60) == 1) { + dev_err(&ftdi->udev->dev, "WRONG type of card inserted - please remove\n"); + } else + dev_err(&ftdi->udev->dev, "WRONG type of card inserted - checked %d times\n", + ftdi->stuck_status); + work_delay_in_msec = 100; + } else if (ftdi->enumerated == 0) { + if (ftdi_elan_enumeratePCI(ftdi) == 0) { + ftdi->enumerated = 1; + work_delay_in_msec = 250; + } else + work_delay_in_msec = 1000; + } else if (ftdi->initialized == 0) { + if (ftdi_elan_setupOHCI(ftdi) == 0) { + ftdi->initialized = 1; + work_delay_in_msec = 500; + } else { + dev_err(&ftdi->udev->dev, "initialized failed - trying again in 10 seconds\n"); + work_delay_in_msec = 1 *1000; + } + } else if (ftdi->registered == 0) { + work_delay_in_msec = 10; + if (ftdi_elan_hcd_init(ftdi) == 0) { + ftdi->registered = 1; + } else + dev_err(&ftdi->udev->dev, "register failed\n"); + work_delay_in_msec = 250; + } else { + if (ftdi_elan_checkingPCI(ftdi) == 0) { + work_delay_in_msec = 250; + } else if (ftdi->controlreg & 0x00400000) { + if (ftdi->gone_away > 0) { + dev_err(&ftdi->udev->dev, "PCI device eject confirmed platform_dev.dev.parent=%p platform_dev.dev=%p\n", + ftdi->platform_dev.dev.parent, + &ftdi->platform_dev.dev); + platform_device_unregister(&ftdi->platform_dev); + ftdi->platform_dev.dev.parent = NULL; + ftdi->registered = 0; + ftdi->enumerated = 0; + ftdi->card_ejected = 0; + ftdi->initialized = 0; + ftdi->gone_away = 0; + } else + ftdi_elan_flush_targets(ftdi); + work_delay_in_msec = 250; + } else { + dev_err(&ftdi->udev->dev, "PCI device has disappeared\n"); + ftdi_elan_cancel_targets(ftdi); + work_delay_in_msec = 500; + ftdi->enumerated = 0; + ftdi->initialized = 0; + } + } + if (ftdi->disconnected > 0) { + ftdi_elan_put_kref(ftdi); + return; + } else { + ftdi_status_requeue_work(ftdi, + msecs_to_jiffies(work_delay_in_msec)); + return; + } } /* -* file_operations for the jtag interface -* -* the usage count for the device is incremented on open() -* and decremented on release() -*/ + * file_operations for the jtag interface + * + * the usage count for the device is incremented on open() + * and decremented on release() + */ 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); - if (!interface) { - printk(KERN_ERR "can't find device for minor %d\n", subminor); - return -ENODEV; - } else { - struct usb_ftdi *ftdi = usb_get_intfdata(interface); - if (!ftdi) { - return -ENODEV; - } else { - if (down_interruptible(&ftdi->sw_lock)) { - return -EINTR; - } else { - ftdi_elan_get_kref(ftdi); - file->private_data = ftdi; - return 0; - } - } - } + int subminor; + struct usb_interface *interface; + + subminor = iminor(inode); + interface = usb_find_interface(&ftdi_elan_driver, subminor); + + if (!interface) { + pr_err("can't find device for minor %d\n", subminor); + return -ENODEV; + } else { + struct usb_ftdi *ftdi = usb_get_intfdata(interface); + if (!ftdi) { + return -ENODEV; + } else { + if (down_interruptible(&ftdi->sw_lock)) { + return -EINTR; + } else { + ftdi_elan_get_kref(ftdi); + file->private_data = ftdi; + return 0; + } + } + } } static int ftdi_elan_release(struct inode *inode, struct file *file) { - struct usb_ftdi *ftdi = (struct usb_ftdi *)file->private_data; - if (ftdi == NULL) - return -ENODEV; - up(&ftdi->sw_lock); /* decrement the count on our device */ - ftdi_elan_put_kref(ftdi); - return 0; + struct usb_ftdi *ftdi = file->private_data; + if (ftdi == NULL) + return -ENODEV; + up(&ftdi->sw_lock); /* decrement the count on our device */ + ftdi_elan_put_kref(ftdi); + return 0; } /* -* -* blocking bulk reads are used to get data from the device -* -*/ + * + * blocking bulk reads are used to get data from the device + * + */ static ssize_t ftdi_elan_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { - char data[30 *3 + 4]; - char *d = data; - int m = (sizeof(data) - 1) / 3; - int bytes_read = 0; - int retry_on_empty = 10; - int retry_on_timeout = 5; - struct usb_ftdi *ftdi = (struct usb_ftdi *)file->private_data; - if (ftdi->disconnected > 0) { - return -ENODEV; - } - data[0] = 0; - have:if (ftdi->bulk_in_left > 0) { - if (count-- > 0) { - char *p = ++ftdi->bulk_in_last + ftdi->bulk_in_buffer; - ftdi->bulk_in_left -= 1; - if (bytes_read < m) { - d += sprintf(d, " %02X", 0x000000FF & *p); - } else if (bytes_read > m) { - } else - d += sprintf(d, " .."); - if (copy_to_user(buffer++, p, 1)) { - return -EFAULT; - } else { - bytes_read += 1; - goto have; - } - } else - return bytes_read; - } - more:if (count > 0) { - int packet_bytes = 0; - int retval = usb_bulk_msg(ftdi->udev, - usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr), - ftdi->bulk_in_buffer, ftdi->bulk_in_size, - &packet_bytes, 50); - if (packet_bytes > 2) { - ftdi->bulk_in_left = packet_bytes - 2; - ftdi->bulk_in_last = 1; - goto have; - } else if (retval == -ETIMEDOUT) { - if (retry_on_timeout-- > 0) { - goto more; - } else if (bytes_read > 0) { - return bytes_read; - } else - return retval; - } else if (retval == 0) { - if (retry_on_empty-- > 0) { - goto more; - } else - return bytes_read; - } else - return retval; - } else - return bytes_read; + char data[30 *3 + 4]; + char *d = data; + int m = (sizeof(data) - 1) / 3; + int bytes_read = 0; + int retry_on_empty = 10; + int retry_on_timeout = 5; + struct usb_ftdi *ftdi = file->private_data; + if (ftdi->disconnected > 0) { + return -ENODEV; + } + data[0] = 0; +have:if (ftdi->bulk_in_left > 0) { + if (count-- > 0) { + char *p = ++ftdi->bulk_in_last + ftdi->bulk_in_buffer; + ftdi->bulk_in_left -= 1; + if (bytes_read < m) { + d += sprintf(d, " %02X", 0x000000FF & *p); + } else if (bytes_read > m) { + } else + d += sprintf(d, " .."); + if (copy_to_user(buffer++, p, 1)) { + return -EFAULT; + } else { + bytes_read += 1; + goto have; + } + } else + return bytes_read; + } +more:if (count > 0) { + int packet_bytes = 0; + int retval = usb_bulk_msg(ftdi->udev, + usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr), + ftdi->bulk_in_buffer, ftdi->bulk_in_size, + &packet_bytes, 50); + if (packet_bytes > 2) { + ftdi->bulk_in_left = packet_bytes - 2; + ftdi->bulk_in_last = 1; + goto have; + } else if (retval == -ETIMEDOUT) { + if (retry_on_timeout-- > 0) { + goto more; + } else if (bytes_read > 0) { + return bytes_read; + } else + return retval; + } else if (retval == 0) { + if (retry_on_empty-- > 0) { + goto more; + } else + return bytes_read; + } else + return retval; + } else + return bytes_read; } static void ftdi_elan_write_bulk_callback(struct urb *urb) @@ -727,469 +726,462 @@ static void ftdi_elan_write_bulk_callback(struct urb *urb) int status = urb->status; if (status && !(status == -ENOENT || status == -ECONNRESET || - status == -ESHUTDOWN)) { - dev_err(&ftdi->udev->dev, "urb=%p write bulk status received: %" - "d\n", urb, status); - } - usb_buffer_free(urb->dev, urb->transfer_buffer_length, - urb->transfer_buffer, urb->transfer_dma); + status == -ESHUTDOWN)) { + dev_err(&ftdi->udev->dev, + "urb=%p write bulk status received: %d\n", urb, status); + } + usb_free_coherent(urb->dev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); } static int fill_buffer_with_all_queued_commands(struct usb_ftdi *ftdi, - char *buf, int command_size, int total_size) -{ - int ed_commands = 0; - int b = 0; - int I = command_size; - int i = ftdi->command_head; - while (I-- > 0) { - struct u132_command *command = &ftdi->command[COMMAND_MASK & - i++]; - int F = command->follows; - u8 *f = command->buffer; - if (command->header & 0x80) { - ed_commands |= 1 << (0x3 & (command->header >> 5)); - } - buf[b++] = command->header; - buf[b++] = (command->length >> 0) & 0x00FF; - buf[b++] = (command->length >> 8) & 0x00FF; - buf[b++] = command->address; - buf[b++] = command->width; - while (F-- > 0) { - buf[b++] = *f++; - } - } - return ed_commands; + char *buf, int command_size, int total_size) +{ + int ed_commands = 0; + int b = 0; + int I = command_size; + int i = ftdi->command_head; + while (I-- > 0) { + struct u132_command *command = &ftdi->command[COMMAND_MASK & + i++]; + int F = command->follows; + u8 *f = command->buffer; + if (command->header & 0x80) { + ed_commands |= 1 << (0x3 & (command->header >> 5)); + } + buf[b++] = command->header; + buf[b++] = (command->length >> 0) & 0x00FF; + buf[b++] = (command->length >> 8) & 0x00FF; + buf[b++] = command->address; + buf[b++] = command->width; + while (F-- > 0) { + buf[b++] = *f++; + } + } + return ed_commands; } static int ftdi_elan_total_command_size(struct usb_ftdi *ftdi, int command_size) { - int total_size = 0; - int I = command_size; - int i = ftdi->command_head; - while (I-- > 0) { - struct u132_command *command = &ftdi->command[COMMAND_MASK & - i++]; - total_size += 5 + command->follows; - } return total_size; + int total_size = 0; + int I = command_size; + int i = ftdi->command_head; + while (I-- > 0) { + struct u132_command *command = &ftdi->command[COMMAND_MASK & + i++]; + total_size += 5 + command->follows; + } return total_size; } static int ftdi_elan_command_engine(struct usb_ftdi *ftdi) { - int retval; - char *buf; - int ed_commands; - int total_size; - struct urb *urb; - int command_size = ftdi->command_next - ftdi->command_head; - if (command_size == 0) - return 0; - total_size = ftdi_elan_total_command_size(ftdi, command_size); - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - dev_err(&ftdi->udev->dev, "could not get a urb to write %d comm" - "ands totaling %d bytes to the Uxxx\n", command_size, - total_size); - return -ENOMEM; - } - buf = usb_buffer_alloc(ftdi->udev, total_size, GFP_KERNEL, - &urb->transfer_dma); - if (!buf) { - dev_err(&ftdi->udev->dev, "could not get a buffer to write %d c" - "ommands totaling %d bytes to the Uxxx\n", command_size, - total_size); - usb_free_urb(urb); - return -ENOMEM; - } - ed_commands = fill_buffer_with_all_queued_commands(ftdi, buf, - command_size, total_size); - usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev, - ftdi->bulk_out_endpointAddr), buf, total_size, - ftdi_elan_write_bulk_callback, ftdi); - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - if (ed_commands) { - char diag[40 *3 + 4]; - char *d = diag; - int m = total_size; - u8 *c = buf; - int s = (sizeof(diag) - 1) / 3; - diag[0] = 0; - while (s-- > 0 && m-- > 0) { - if (s > 0 || m == 0) { - d += sprintf(d, " %02X", *c++); - } else - d += sprintf(d, " .."); - } - } - retval = usb_submit_urb(urb, GFP_KERNEL); - if (retval) { - dev_err(&ftdi->udev->dev, "failed %d to submit urb %p to write " - "%d commands totaling %d bytes to the Uxxx\n", retval, - urb, command_size, total_size); - usb_buffer_free(ftdi->udev, total_size, buf, urb->transfer_dma); - usb_free_urb(urb); - return retval; - } - usb_free_urb(urb); /* release our reference to this urb, - the USB core will eventually free it entirely */ - ftdi->command_head += command_size; - ftdi_elan_kick_respond_queue(ftdi); - return 0; + int retval; + char *buf; + int ed_commands; + int total_size; + struct urb *urb; + int command_size = ftdi->command_next - ftdi->command_head; + if (command_size == 0) + return 0; + total_size = ftdi_elan_total_command_size(ftdi, command_size); + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + dev_err(&ftdi->udev->dev, "could not get a urb to write %d commands totaling %d bytes to the Uxxx\n", + command_size, total_size); + return -ENOMEM; + } + buf = usb_alloc_coherent(ftdi->udev, total_size, GFP_KERNEL, + &urb->transfer_dma); + if (!buf) { + dev_err(&ftdi->udev->dev, "could not get a buffer to write %d commands totaling %d bytes to the Uxxx\n", + command_size, total_size); + usb_free_urb(urb); + return -ENOMEM; + } + ed_commands = fill_buffer_with_all_queued_commands(ftdi, buf, + command_size, total_size); + usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev, + ftdi->bulk_out_endpointAddr), buf, total_size, + ftdi_elan_write_bulk_callback, ftdi); + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + if (ed_commands) { + char diag[40 *3 + 4]; + char *d = diag; + int m = total_size; + u8 *c = buf; + int s = (sizeof(diag) - 1) / 3; + diag[0] = 0; + while (s-- > 0 && m-- > 0) { + if (s > 0 || m == 0) { + d += sprintf(d, " %02X", *c++); + } else + d += sprintf(d, " .."); + } + } + retval = usb_submit_urb(urb, GFP_KERNEL); + if (retval) { + dev_err(&ftdi->udev->dev, "failed %d to submit urb %p to write %d commands totaling %d bytes to the Uxxx\n", + retval, urb, command_size, total_size); + usb_free_coherent(ftdi->udev, total_size, buf, urb->transfer_dma); + usb_free_urb(urb); + return retval; + } + usb_free_urb(urb); /* release our reference to this urb, + the USB core will eventually free it entirely */ + ftdi->command_head += command_size; + ftdi_elan_kick_respond_queue(ftdi); + return 0; } static void ftdi_elan_do_callback(struct usb_ftdi *ftdi, - struct u132_target *target, u8 *buffer, int length) -{ - struct urb *urb = target->urb; - int halted = target->halted; - int skipped = target->skipped; - int actual = target->actual; - int non_null = target->non_null; - int toggle_bits = target->toggle_bits; - int error_count = target->error_count; - int condition_code = target->condition_code; - int repeat_number = target->repeat_number; - void (*callback) (void *, struct urb *, u8 *, int, int, int, int, int, - int, int, int, int) = target->callback; - target->active -= 1; - target->callback = NULL; - (*callback) (target->endp, urb, buffer, length, toggle_bits, - error_count, condition_code, repeat_number, halted, skipped, - actual, non_null); + struct u132_target *target, u8 *buffer, int length) +{ + struct urb *urb = target->urb; + int halted = target->halted; + int skipped = target->skipped; + int actual = target->actual; + int non_null = target->non_null; + int toggle_bits = target->toggle_bits; + int error_count = target->error_count; + int condition_code = target->condition_code; + int repeat_number = target->repeat_number; + void (*callback) (void *, struct urb *, u8 *, int, int, int, int, int, + int, int, int, int) = target->callback; + target->active -= 1; + target->callback = NULL; + (*callback) (target->endp, urb, buffer, length, toggle_bits, + error_count, condition_code, repeat_number, halted, skipped, + actual, non_null); } static char *have_ed_set_response(struct usb_ftdi *ftdi, - struct u132_target *target, u16 ed_length, int ed_number, int ed_type, - char *b) -{ - int payload = (ed_length >> 0) & 0x07FF; - mutex_lock(&ftdi->u132_lock); - target->actual = 0; - target->non_null = (ed_length >> 15) & 0x0001; - target->repeat_number = (ed_length >> 11) & 0x000F; - if (ed_type == 0x02) { - if (payload == 0 || target->abandoning > 0) { - target->abandoning = 0; - mutex_unlock(&ftdi->u132_lock); - ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response, - payload); - ftdi->recieved = 0; - ftdi->expected = 4; - ftdi->ed_found = 0; - return ftdi->response; - } else { - ftdi->expected = 4 + payload; - ftdi->ed_found = 1; - mutex_unlock(&ftdi->u132_lock); - return b; - } - } else if (ed_type == 0x03) { - if (payload == 0 || target->abandoning > 0) { - target->abandoning = 0; - mutex_unlock(&ftdi->u132_lock); - ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response, - payload); - ftdi->recieved = 0; - ftdi->expected = 4; - ftdi->ed_found = 0; - return ftdi->response; - } else { - ftdi->expected = 4 + payload; - ftdi->ed_found = 1; - mutex_unlock(&ftdi->u132_lock); - return b; - } - } else if (ed_type == 0x01) { - target->abandoning = 0; - mutex_unlock(&ftdi->u132_lock); - ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response, - payload); - ftdi->recieved = 0; - ftdi->expected = 4; - ftdi->ed_found = 0; - return ftdi->response; - } else { - target->abandoning = 0; - mutex_unlock(&ftdi->u132_lock); - ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response, - payload); - ftdi->recieved = 0; - ftdi->expected = 4; - ftdi->ed_found = 0; - return ftdi->response; - } + struct u132_target *target, u16 ed_length, int ed_number, int ed_type, + char *b) +{ + int payload = (ed_length >> 0) & 0x07FF; + mutex_lock(&ftdi->u132_lock); + target->actual = 0; + target->non_null = (ed_length >> 15) & 0x0001; + target->repeat_number = (ed_length >> 11) & 0x000F; + if (ed_type == 0x02) { + if (payload == 0 || target->abandoning > 0) { + target->abandoning = 0; + mutex_unlock(&ftdi->u132_lock); + ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response, + payload); + ftdi->received = 0; + ftdi->expected = 4; + ftdi->ed_found = 0; + return ftdi->response; + } else { + ftdi->expected = 4 + payload; + ftdi->ed_found = 1; + mutex_unlock(&ftdi->u132_lock); + return b; + } + } else if (ed_type == 0x03) { + if (payload == 0 || target->abandoning > 0) { + target->abandoning = 0; + mutex_unlock(&ftdi->u132_lock); + ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response, + payload); + ftdi->received = 0; + ftdi->expected = 4; + ftdi->ed_found = 0; + return ftdi->response; + } else { + ftdi->expected = 4 + payload; + ftdi->ed_found = 1; + mutex_unlock(&ftdi->u132_lock); + return b; + } + } else if (ed_type == 0x01) { + target->abandoning = 0; + mutex_unlock(&ftdi->u132_lock); + ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response, + payload); + ftdi->received = 0; + ftdi->expected = 4; + ftdi->ed_found = 0; + return ftdi->response; + } else { + target->abandoning = 0; + mutex_unlock(&ftdi->u132_lock); + ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response, + payload); + ftdi->received = 0; + ftdi->expected = 4; + ftdi->ed_found = 0; + return ftdi->response; + } } static char *have_ed_get_response(struct usb_ftdi *ftdi, - struct u132_target *target, u16 ed_length, int ed_number, int ed_type, - char *b) + struct u132_target *target, u16 ed_length, int ed_number, int ed_type, + char *b) { - mutex_lock(&ftdi->u132_lock); - target->condition_code = TD_DEVNOTRESP; - target->actual = (ed_length >> 0) & 0x01FF; - target->non_null = (ed_length >> 15) & 0x0001; - target->repeat_number = (ed_length >> 11) & 0x000F; - mutex_unlock(&ftdi->u132_lock); - if (target->active) - ftdi_elan_do_callback(ftdi, target, NULL, 0); - target->abandoning = 0; - ftdi->recieved = 0; - ftdi->expected = 4; - ftdi->ed_found = 0; - return ftdi->response; + mutex_lock(&ftdi->u132_lock); + target->condition_code = TD_DEVNOTRESP; + target->actual = (ed_length >> 0) & 0x01FF; + target->non_null = (ed_length >> 15) & 0x0001; + target->repeat_number = (ed_length >> 11) & 0x000F; + mutex_unlock(&ftdi->u132_lock); + if (target->active) + ftdi_elan_do_callback(ftdi, target, NULL, 0); + target->abandoning = 0; + ftdi->received = 0; + ftdi->expected = 4; + ftdi->ed_found = 0; + return ftdi->response; } /* -* The engine tries to empty the FTDI fifo -* -* all responses found in the fifo data are dispatched thus -* the response buffer can only ever hold a maximum sized -* response from the Uxxx. -* -*/ + * The engine tries to empty the FTDI fifo + * + * all responses found in the fifo data are dispatched thus + * the response buffer can only ever hold a maximum sized + * response from the Uxxx. + * + */ static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi) { - u8 *b = ftdi->response + ftdi->recieved; - int bytes_read = 0; - int retry_on_empty = 1; - int retry_on_timeout = 3; - int empty_packets = 0; - read:{ - int packet_bytes = 0; - int retval = usb_bulk_msg(ftdi->udev, - usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr), - ftdi->bulk_in_buffer, ftdi->bulk_in_size, - &packet_bytes, 500); - char diag[30 *3 + 4]; - char *d = diag; - int m = packet_bytes; - u8 *c = ftdi->bulk_in_buffer; - int s = (sizeof(diag) - 1) / 3; - diag[0] = 0; - while (s-- > 0 && m-- > 0) { - if (s > 0 || m == 0) { - d += sprintf(d, " %02X", *c++); - } else - d += sprintf(d, " .."); - } - if (packet_bytes > 2) { - ftdi->bulk_in_left = packet_bytes - 2; - ftdi->bulk_in_last = 1; - goto have; - } else if (retval == -ETIMEDOUT) { - if (retry_on_timeout-- > 0) { - dev_err(&ftdi->udev->dev, "TIMED OUT with packe" - "t_bytes = %d with total %d bytes%s\n", - packet_bytes, bytes_read, diag); - goto more; - } else if (bytes_read > 0) { - dev_err(&ftdi->udev->dev, "ONLY %d bytes%s\n", - bytes_read, diag); - return -ENOMEM; - } else { - dev_err(&ftdi->udev->dev, "TIMED OUT with packe" - "t_bytes = %d with total %d bytes%s\n", - packet_bytes, bytes_read, diag); - return -ENOMEM; - } - } else if (retval == -EILSEQ) { - dev_err(&ftdi->udev->dev, "error = %d with packet_bytes" - " = %d with total %d bytes%s\n", retval, - packet_bytes, bytes_read, diag); - return retval; - } else if (retval) { - dev_err(&ftdi->udev->dev, "error = %d with packet_bytes" - " = %d with total %d bytes%s\n", retval, - packet_bytes, bytes_read, diag); - return retval; - } else if (packet_bytes == 2) { - unsigned char s0 = ftdi->bulk_in_buffer[0]; - unsigned char s1 = ftdi->bulk_in_buffer[1]; - empty_packets += 1; - if (s0 == 0x31 && s1 == 0x60) { - if (retry_on_empty-- > 0) { - goto more; - } else - return 0; - } else if (s0 == 0x31 && s1 == 0x00) { - if (retry_on_empty-- > 0) { - goto more; - } else - return 0; - } else { - if (retry_on_empty-- > 0) { - goto more; - } else - return 0; - } - } else if (packet_bytes == 1) { - if (retry_on_empty-- > 0) { - goto more; - } else - return 0; - } else { - if (retry_on_empty-- > 0) { - goto more; - } else - return 0; - } - } - more:{ - goto read; - } - have:if (ftdi->bulk_in_left > 0) { - u8 c = ftdi->bulk_in_buffer[++ftdi->bulk_in_last]; - bytes_read += 1; - ftdi->bulk_in_left -= 1; - if (ftdi->recieved == 0 && c == 0xFF) { - goto have; - } else - *b++ = c; - if (++ftdi->recieved < ftdi->expected) { - goto have; - } else if (ftdi->ed_found) { - int ed_number = (ftdi->response[0] >> 5) & 0x03; - u16 ed_length = (ftdi->response[2] << 8) | - ftdi->response[1]; - struct u132_target *target = &ftdi->target[ed_number]; - int payload = (ed_length >> 0) & 0x07FF; - char diag[30 *3 + 4]; - char *d = diag; - int m = payload; - u8 *c = 4 + ftdi->response; - int s = (sizeof(diag) - 1) / 3; - diag[0] = 0; - while (s-- > 0 && m-- > 0) { - if (s > 0 || m == 0) { - d += sprintf(d, " %02X", *c++); - } else - d += sprintf(d, " .."); - } - ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response, - payload); - ftdi->recieved = 0; - ftdi->expected = 4; - ftdi->ed_found = 0; - b = ftdi->response; - goto have; - } else if (ftdi->expected == 8) { - u8 buscmd; - int respond_head = ftdi->respond_head++; - struct u132_respond *respond = &ftdi->respond[ - RESPOND_MASK & respond_head]; - u32 data = ftdi->response[7]; - data <<= 8; - data |= ftdi->response[6]; - data <<= 8; - data |= ftdi->response[5]; - data <<= 8; - data |= ftdi->response[4]; - *respond->value = data; - *respond->result = 0; - complete(&respond->wait_completion); - ftdi->recieved = 0; - ftdi->expected = 4; - ftdi->ed_found = 0; - b = ftdi->response; - buscmd = (ftdi->response[0] >> 0) & 0x0F; - if (buscmd == 0x00) { - } else if (buscmd == 0x02) { - } else if (buscmd == 0x06) { - } else if (buscmd == 0x0A) { - } else - dev_err(&ftdi->udev->dev, "Uxxx unknown(%0X) va" - "lue = %08X\n", buscmd, data); - goto have; - } else { - if ((ftdi->response[0] & 0x80) == 0x00) { - ftdi->expected = 8; - goto have; - } else { - int ed_number = (ftdi->response[0] >> 5) & 0x03; - int ed_type = (ftdi->response[0] >> 0) & 0x03; - u16 ed_length = (ftdi->response[2] << 8) | - ftdi->response[1]; - struct u132_target *target = &ftdi->target[ - ed_number]; - target->halted = (ftdi->response[0] >> 3) & - 0x01; - target->skipped = (ftdi->response[0] >> 2) & - 0x01; - target->toggle_bits = (ftdi->response[3] >> 6) - & 0x03; - target->error_count = (ftdi->response[3] >> 4) - & 0x03; - target->condition_code = (ftdi->response[ - 3] >> 0) & 0x0F; - if ((ftdi->response[0] & 0x10) == 0x00) { - b = have_ed_set_response(ftdi, target, - ed_length, ed_number, ed_type, - b); - goto have; - } else { - b = have_ed_get_response(ftdi, target, - ed_length, ed_number, ed_type, - b); - goto have; - } - } - } - } else - goto more; + u8 *b = ftdi->response + ftdi->received; + int bytes_read = 0; + int retry_on_empty = 1; + int retry_on_timeout = 3; + int empty_packets = 0; +read:{ + int packet_bytes = 0; + int retval = usb_bulk_msg(ftdi->udev, + usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr), + ftdi->bulk_in_buffer, ftdi->bulk_in_size, + &packet_bytes, 500); + char diag[30 *3 + 4]; + char *d = diag; + int m = packet_bytes; + u8 *c = ftdi->bulk_in_buffer; + int s = (sizeof(diag) - 1) / 3; + diag[0] = 0; + while (s-- > 0 && m-- > 0) { + if (s > 0 || m == 0) { + d += sprintf(d, " %02X", *c++); + } else + d += sprintf(d, " .."); + } + if (packet_bytes > 2) { + ftdi->bulk_in_left = packet_bytes - 2; + ftdi->bulk_in_last = 1; + goto have; + } else if (retval == -ETIMEDOUT) { + if (retry_on_timeout-- > 0) { + dev_err(&ftdi->udev->dev, "TIMED OUT with packet_bytes = %d with total %d bytes%s\n", + packet_bytes, bytes_read, diag); + goto more; + } else if (bytes_read > 0) { + dev_err(&ftdi->udev->dev, "ONLY %d bytes%s\n", + bytes_read, diag); + return -ENOMEM; + } else { + dev_err(&ftdi->udev->dev, "TIMED OUT with packet_bytes = %d with total %d bytes%s\n", + packet_bytes, bytes_read, diag); + return -ENOMEM; + } + } else if (retval == -EILSEQ) { + dev_err(&ftdi->udev->dev, "error = %d with packet_bytes = %d with total %d bytes%s\n", + retval, packet_bytes, bytes_read, diag); + return retval; + } else if (retval) { + dev_err(&ftdi->udev->dev, "error = %d with packet_bytes = %d with total %d bytes%s\n", + retval, packet_bytes, bytes_read, diag); + return retval; + } else if (packet_bytes == 2) { + unsigned char s0 = ftdi->bulk_in_buffer[0]; + unsigned char s1 = ftdi->bulk_in_buffer[1]; + empty_packets += 1; + if (s0 == 0x31 && s1 == 0x60) { + if (retry_on_empty-- > 0) { + goto more; + } else + return 0; + } else if (s0 == 0x31 && s1 == 0x00) { + if (retry_on_empty-- > 0) { + goto more; + } else + return 0; + } else { + if (retry_on_empty-- > 0) { + goto more; + } else + return 0; + } + } else if (packet_bytes == 1) { + if (retry_on_empty-- > 0) { + goto more; + } else + return 0; + } else { + if (retry_on_empty-- > 0) { + goto more; + } else + return 0; + } + } +more:{ + goto read; + } +have:if (ftdi->bulk_in_left > 0) { + u8 c = ftdi->bulk_in_buffer[++ftdi->bulk_in_last]; + bytes_read += 1; + ftdi->bulk_in_left -= 1; + if (ftdi->received == 0 && c == 0xFF) { + goto have; + } else + *b++ = c; + if (++ftdi->received < ftdi->expected) { + goto have; + } else if (ftdi->ed_found) { + int ed_number = (ftdi->response[0] >> 5) & 0x03; + u16 ed_length = (ftdi->response[2] << 8) | + ftdi->response[1]; + struct u132_target *target = &ftdi->target[ed_number]; + int payload = (ed_length >> 0) & 0x07FF; + char diag[30 *3 + 4]; + char *d = diag; + int m = payload; + u8 *c = 4 + ftdi->response; + int s = (sizeof(diag) - 1) / 3; + diag[0] = 0; + while (s-- > 0 && m-- > 0) { + if (s > 0 || m == 0) { + d += sprintf(d, " %02X", *c++); + } else + d += sprintf(d, " .."); + } + ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response, + payload); + ftdi->received = 0; + ftdi->expected = 4; + ftdi->ed_found = 0; + b = ftdi->response; + goto have; + } else if (ftdi->expected == 8) { + u8 buscmd; + int respond_head = ftdi->respond_head++; + struct u132_respond *respond = &ftdi->respond[ + RESPOND_MASK & respond_head]; + u32 data = ftdi->response[7]; + data <<= 8; + data |= ftdi->response[6]; + data <<= 8; + data |= ftdi->response[5]; + data <<= 8; + data |= ftdi->response[4]; + *respond->value = data; + *respond->result = 0; + complete(&respond->wait_completion); + ftdi->received = 0; + ftdi->expected = 4; + ftdi->ed_found = 0; + b = ftdi->response; + buscmd = (ftdi->response[0] >> 0) & 0x0F; + if (buscmd == 0x00) { + } else if (buscmd == 0x02) { + } else if (buscmd == 0x06) { + } else if (buscmd == 0x0A) { + } else + dev_err(&ftdi->udev->dev, "Uxxx unknown(%0X) value = %08X\n", + buscmd, data); + goto have; + } else { + if ((ftdi->response[0] & 0x80) == 0x00) { + ftdi->expected = 8; + goto have; + } else { + int ed_number = (ftdi->response[0] >> 5) & 0x03; + int ed_type = (ftdi->response[0] >> 0) & 0x03; + u16 ed_length = (ftdi->response[2] << 8) | + ftdi->response[1]; + struct u132_target *target = &ftdi->target[ + ed_number]; + target->halted = (ftdi->response[0] >> 3) & + 0x01; + target->skipped = (ftdi->response[0] >> 2) & + 0x01; + target->toggle_bits = (ftdi->response[3] >> 6) + & 0x03; + target->error_count = (ftdi->response[3] >> 4) + & 0x03; + target->condition_code = (ftdi->response[ + 3] >> 0) & 0x0F; + if ((ftdi->response[0] & 0x10) == 0x00) { + b = have_ed_set_response(ftdi, target, + ed_length, ed_number, ed_type, + b); + goto have; + } else { + b = have_ed_get_response(ftdi, target, + ed_length, ed_number, ed_type, + b); + goto have; + } + } + } + } else + goto more; } /* -* create a urb, and a buffer for it, and copy the data to the urb -* -*/ + * create a urb, and a buffer for it, and copy the data to the urb + * + */ static ssize_t ftdi_elan_write(struct file *file, const char __user *user_buffer, size_t count, loff_t *ppos) { - int retval = 0; - struct urb *urb; - char *buf; - struct usb_ftdi *ftdi = file->private_data; - - if (ftdi->disconnected > 0) { - return -ENODEV; - } - if (count == 0) { - goto exit; - } - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - retval = -ENOMEM; - goto error_1; - } - buf = usb_buffer_alloc(ftdi->udev, count, GFP_KERNEL, - &urb->transfer_dma); - if (!buf) { - retval = -ENOMEM; - goto error_2; - } - if (copy_from_user(buf, user_buffer, count)) { - retval = -EFAULT; - goto error_3; - } - usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev, - ftdi->bulk_out_endpointAddr), buf, count, - ftdi_elan_write_bulk_callback, ftdi); - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - retval = usb_submit_urb(urb, GFP_KERNEL); - if (retval) { - dev_err(&ftdi->udev->dev, "failed submitting write urb, error %" - "d\n", retval); - goto error_3; - } - usb_free_urb(urb); + int retval = 0; + struct urb *urb; + char *buf; + struct usb_ftdi *ftdi = file->private_data; + + if (ftdi->disconnected > 0) { + return -ENODEV; + } + if (count == 0) { + goto exit; + } + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + retval = -ENOMEM; + goto error_1; + } + buf = usb_alloc_coherent(ftdi->udev, count, GFP_KERNEL, + &urb->transfer_dma); + if (!buf) { + retval = -ENOMEM; + goto error_2; + } + if (copy_from_user(buf, user_buffer, count)) { + retval = -EFAULT; + goto error_3; + } + usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev, + ftdi->bulk_out_endpointAddr), buf, count, + ftdi_elan_write_bulk_callback, ftdi); + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + retval = usb_submit_urb(urb, GFP_KERNEL); + if (retval) { + dev_err(&ftdi->udev->dev, + "failed submitting write urb, error %d\n", retval); + goto error_3; + } + usb_free_urb(urb); exit: - return count; + return count; error_3: - usb_buffer_free(ftdi->udev, count, buf, urb->transfer_dma); + usb_free_coherent(ftdi->udev, count, buf, urb->transfer_dma); error_2: usb_free_urb(urb); error_1: @@ -1197,29 +1189,29 @@ error_1: } static const struct file_operations ftdi_elan_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = ftdi_elan_read, - .write = ftdi_elan_write, - .open = ftdi_elan_open, - .release = ftdi_elan_release, + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = ftdi_elan_read, + .write = ftdi_elan_write, + .open = ftdi_elan_open, + .release = ftdi_elan_release, }; /* -* usb class driver info in order to get a minor number from the usb core, -* and to have the device registered with the driver core -*/ + * usb class driver info in order to get a minor number from the usb core, + * and to have the device registered with the driver core + */ static struct usb_class_driver ftdi_elan_jtag_class = { - .name = "ftdi-%d-jtag", - .fops = &ftdi_elan_fops, - .minor_base = USB_FTDI_ELAN_MINOR_BASE, + .name = "ftdi-%d-jtag", + .fops = &ftdi_elan_fops, + .minor_base = USB_FTDI_ELAN_MINOR_BASE, }; /* -* the following definitions are for the -* ELAN FPGA state machgine processor that -* lies on the other side of the FTDI chip -*/ + * the following definitions are for the + * ELAN FPGA state machgine processor that + * lies on the other side of the FTDI chip + */ #define cPCIu132rd 0x0 #define cPCIu132wr 0x1 #define cPCIiord 0x2 @@ -1250,1695 +1242,1663 @@ static struct usb_class_driver ftdi_elan_jtag_class = { #define cCCnotaccessed 0xF static int ftdi_elan_write_reg(struct usb_ftdi *ftdi, u32 data) { - wait:if (ftdi->disconnected > 0) { - return -ENODEV; - } else { - int command_size; - mutex_lock(&ftdi->u132_lock); - command_size = ftdi->command_next - ftdi->command_head; - if (command_size < COMMAND_SIZE) { - struct u132_command *command = &ftdi->command[ - COMMAND_MASK & ftdi->command_next]; - command->header = 0x00 | cPCIu132wr; - command->length = 0x04; - command->address = 0x00; - command->width = 0x00; - command->follows = 4; - command->value = data; - command->buffer = &command->value; - ftdi->command_next += 1; - ftdi_elan_kick_command_queue(ftdi); - mutex_unlock(&ftdi->u132_lock); - return 0; - } else { - mutex_unlock(&ftdi->u132_lock); - msleep(100); - goto wait; - } - } +wait:if (ftdi->disconnected > 0) { + return -ENODEV; + } else { + int command_size; + mutex_lock(&ftdi->u132_lock); + command_size = ftdi->command_next - ftdi->command_head; + if (command_size < COMMAND_SIZE) { + struct u132_command *command = &ftdi->command[ + COMMAND_MASK & ftdi->command_next]; + command->header = 0x00 | cPCIu132wr; + command->length = 0x04; + command->address = 0x00; + command->width = 0x00; + command->follows = 4; + command->value = data; + command->buffer = &command->value; + ftdi->command_next += 1; + ftdi_elan_kick_command_queue(ftdi); + mutex_unlock(&ftdi->u132_lock); + return 0; + } else { + mutex_unlock(&ftdi->u132_lock); + msleep(100); + goto wait; + } + } } static int ftdi_elan_write_config(struct usb_ftdi *ftdi, int config_offset, - u8 width, u32 data) -{ - u8 addressofs = config_offset / 4; - wait:if (ftdi->disconnected > 0) { - return -ENODEV; - } else { - int command_size; - mutex_lock(&ftdi->u132_lock); - command_size = ftdi->command_next - ftdi->command_head; - if (command_size < COMMAND_SIZE) { - struct u132_command *command = &ftdi->command[ - COMMAND_MASK & ftdi->command_next]; - command->header = 0x00 | (cPCIcfgwr & 0x0F); - command->length = 0x04; - command->address = addressofs; - command->width = 0x00 | (width & 0x0F); - command->follows = 4; - command->value = data; - command->buffer = &command->value; - ftdi->command_next += 1; - ftdi_elan_kick_command_queue(ftdi); - mutex_unlock(&ftdi->u132_lock); - return 0; - } else { - mutex_unlock(&ftdi->u132_lock); - msleep(100); - goto wait; - } - } + u8 width, u32 data) +{ + u8 addressofs = config_offset / 4; +wait:if (ftdi->disconnected > 0) { + return -ENODEV; + } else { + int command_size; + mutex_lock(&ftdi->u132_lock); + command_size = ftdi->command_next - ftdi->command_head; + if (command_size < COMMAND_SIZE) { + struct u132_command *command = &ftdi->command[ + COMMAND_MASK & ftdi->command_next]; + command->header = 0x00 | (cPCIcfgwr & 0x0F); + command->length = 0x04; + command->address = addressofs; + command->width = 0x00 | (width & 0x0F); + command->follows = 4; + command->value = data; + command->buffer = &command->value; + ftdi->command_next += 1; + ftdi_elan_kick_command_queue(ftdi); + mutex_unlock(&ftdi->u132_lock); + return 0; + } else { + mutex_unlock(&ftdi->u132_lock); + msleep(100); + goto wait; + } + } } static int ftdi_elan_write_pcimem(struct usb_ftdi *ftdi, int mem_offset, - u8 width, u32 data) -{ - u8 addressofs = mem_offset / 4; - wait:if (ftdi->disconnected > 0) { - return -ENODEV; - } else { - int command_size; - mutex_lock(&ftdi->u132_lock); - command_size = ftdi->command_next - ftdi->command_head; - if (command_size < COMMAND_SIZE) { - struct u132_command *command = &ftdi->command[ - COMMAND_MASK & ftdi->command_next]; - command->header = 0x00 | (cPCImemwr & 0x0F); - command->length = 0x04; - command->address = addressofs; - command->width = 0x00 | (width & 0x0F); - command->follows = 4; - command->value = data; - command->buffer = &command->value; - ftdi->command_next += 1; - ftdi_elan_kick_command_queue(ftdi); - mutex_unlock(&ftdi->u132_lock); - return 0; - } else { - mutex_unlock(&ftdi->u132_lock); - msleep(100); - goto wait; - } - } + u8 width, u32 data) +{ + u8 addressofs = mem_offset / 4; +wait:if (ftdi->disconnected > 0) { + return -ENODEV; + } else { + int command_size; + mutex_lock(&ftdi->u132_lock); + command_size = ftdi->command_next - ftdi->command_head; + if (command_size < COMMAND_SIZE) { + struct u132_command *command = &ftdi->command[ + COMMAND_MASK & ftdi->command_next]; + command->header = 0x00 | (cPCImemwr & 0x0F); + command->length = 0x04; + command->address = addressofs; + command->width = 0x00 | (width & 0x0F); + command->follows = 4; + command->value = data; + command->buffer = &command->value; + ftdi->command_next += 1; + ftdi_elan_kick_command_queue(ftdi); + mutex_unlock(&ftdi->u132_lock); + return 0; + } else { + mutex_unlock(&ftdi->u132_lock); + msleep(100); + goto wait; + } + } } int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, int mem_offset, - u8 width, u32 data) + u8 width, u32 data) { - struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); - return ftdi_elan_write_pcimem(ftdi, mem_offset, width, data); + struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); + return ftdi_elan_write_pcimem(ftdi, mem_offset, width, data); } EXPORT_SYMBOL_GPL(usb_ftdi_elan_write_pcimem); static int ftdi_elan_read_reg(struct usb_ftdi *ftdi, u32 *data) { - wait:if (ftdi->disconnected > 0) { - return -ENODEV; - } else { - int command_size; - int respond_size; - mutex_lock(&ftdi->u132_lock); - command_size = ftdi->command_next - ftdi->command_head; - respond_size = ftdi->respond_next - ftdi->respond_head; - if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE) - { - struct u132_command *command = &ftdi->command[ - COMMAND_MASK & ftdi->command_next]; - struct u132_respond *respond = &ftdi->respond[ - RESPOND_MASK & ftdi->respond_next]; - int result = -ENODEV; - respond->result = &result; - respond->header = command->header = 0x00 | cPCIu132rd; - command->length = 0x04; - respond->address = command->address = cU132cmd_status; - command->width = 0x00; - command->follows = 0; - command->value = 0; - command->buffer = NULL; - respond->value = data; - init_completion(&respond->wait_completion); - ftdi->command_next += 1; - ftdi->respond_next += 1; - ftdi_elan_kick_command_queue(ftdi); - mutex_unlock(&ftdi->u132_lock); - wait_for_completion(&respond->wait_completion); - return result; - } else { - mutex_unlock(&ftdi->u132_lock); - msleep(100); - goto wait; - } - } +wait:if (ftdi->disconnected > 0) { + return -ENODEV; + } else { + int command_size; + int respond_size; + mutex_lock(&ftdi->u132_lock); + command_size = ftdi->command_next - ftdi->command_head; + respond_size = ftdi->respond_next - ftdi->respond_head; + if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE) + { + struct u132_command *command = &ftdi->command[ + COMMAND_MASK & ftdi->command_next]; + struct u132_respond *respond = &ftdi->respond[ + RESPOND_MASK & ftdi->respond_next]; + int result = -ENODEV; + respond->result = &result; + respond->header = command->header = 0x00 | cPCIu132rd; + command->length = 0x04; + respond->address = command->address = cU132cmd_status; + command->width = 0x00; + command->follows = 0; + command->value = 0; + command->buffer = NULL; + respond->value = data; + init_completion(&respond->wait_completion); + ftdi->command_next += 1; + ftdi->respond_next += 1; + ftdi_elan_kick_command_queue(ftdi); + mutex_unlock(&ftdi->u132_lock); + wait_for_completion(&respond->wait_completion); + return result; + } else { + mutex_unlock(&ftdi->u132_lock); + msleep(100); + goto wait; + } + } } static int ftdi_elan_read_config(struct usb_ftdi *ftdi, int config_offset, - u8 width, u32 *data) -{ - u8 addressofs = config_offset / 4; - wait:if (ftdi->disconnected > 0) { - return -ENODEV; - } else { - int command_size; - int respond_size; - mutex_lock(&ftdi->u132_lock); - command_size = ftdi->command_next - ftdi->command_head; - respond_size = ftdi->respond_next - ftdi->respond_head; - if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE) - { - struct u132_command *command = &ftdi->command[ - COMMAND_MASK & ftdi->command_next]; - struct u132_respond *respond = &ftdi->respond[ - RESPOND_MASK & ftdi->respond_next]; - int result = -ENODEV; - respond->result = &result; - respond->header = command->header = 0x00 | (cPCIcfgrd & - 0x0F); - command->length = 0x04; - respond->address = command->address = addressofs; - command->width = 0x00 | (width & 0x0F); - command->follows = 0; - command->value = 0; - command->buffer = NULL; - respond->value = data; - init_completion(&respond->wait_completion); - ftdi->command_next += 1; - ftdi->respond_next += 1; - ftdi_elan_kick_command_queue(ftdi); - mutex_unlock(&ftdi->u132_lock); - wait_for_completion(&respond->wait_completion); - return result; - } else { - mutex_unlock(&ftdi->u132_lock); - msleep(100); - goto wait; - } - } + u8 width, u32 *data) +{ + u8 addressofs = config_offset / 4; +wait:if (ftdi->disconnected > 0) { + return -ENODEV; + } else { + int command_size; + int respond_size; + mutex_lock(&ftdi->u132_lock); + command_size = ftdi->command_next - ftdi->command_head; + respond_size = ftdi->respond_next - ftdi->respond_head; + if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE) + { + struct u132_command *command = &ftdi->command[ + COMMAND_MASK & ftdi->command_next]; + struct u132_respond *respond = &ftdi->respond[ + RESPOND_MASK & ftdi->respond_next]; + int result = -ENODEV; + respond->result = &result; + respond->header = command->header = 0x00 | (cPCIcfgrd & + 0x0F); + command->length = 0x04; + respond->address = command->address = addressofs; + command->width = 0x00 | (width & 0x0F); + command->follows = 0; + command->value = 0; + command->buffer = NULL; + respond->value = data; + init_completion(&respond->wait_completion); + ftdi->command_next += 1; + ftdi->respond_next += 1; + ftdi_elan_kick_command_queue(ftdi); + mutex_unlock(&ftdi->u132_lock); + wait_for_completion(&respond->wait_completion); + return result; + } else { + mutex_unlock(&ftdi->u132_lock); + msleep(100); + goto wait; + } + } } static int ftdi_elan_read_pcimem(struct usb_ftdi *ftdi, int mem_offset, - u8 width, u32 *data) -{ - u8 addressofs = mem_offset / 4; - wait:if (ftdi->disconnected > 0) { - return -ENODEV; - } else { - int command_size; - int respond_size; - mutex_lock(&ftdi->u132_lock); - command_size = ftdi->command_next - ftdi->command_head; - respond_size = ftdi->respond_next - ftdi->respond_head; - if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE) - { - struct u132_command *command = &ftdi->command[ - COMMAND_MASK & ftdi->command_next]; - struct u132_respond *respond = &ftdi->respond[ - RESPOND_MASK & ftdi->respond_next]; - int result = -ENODEV; - respond->result = &result; - respond->header = command->header = 0x00 | (cPCImemrd & - 0x0F); - command->length = 0x04; - respond->address = command->address = addressofs; - command->width = 0x00 | (width & 0x0F); - command->follows = 0; - command->value = 0; - command->buffer = NULL; - respond->value = data; - init_completion(&respond->wait_completion); - ftdi->command_next += 1; - ftdi->respond_next += 1; - ftdi_elan_kick_command_queue(ftdi); - mutex_unlock(&ftdi->u132_lock); - wait_for_completion(&respond->wait_completion); - return result; - } else { - mutex_unlock(&ftdi->u132_lock); - msleep(100); - goto wait; - } - } + u8 width, u32 *data) +{ + u8 addressofs = mem_offset / 4; +wait:if (ftdi->disconnected > 0) { + return -ENODEV; + } else { + int command_size; + int respond_size; + mutex_lock(&ftdi->u132_lock); + command_size = ftdi->command_next - ftdi->command_head; + respond_size = ftdi->respond_next - ftdi->respond_head; + if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE) + { + struct u132_command *command = &ftdi->command[ + COMMAND_MASK & ftdi->command_next]; + struct u132_respond *respond = &ftdi->respond[ + RESPOND_MASK & ftdi->respond_next]; + int result = -ENODEV; + respond->result = &result; + respond->header = command->header = 0x00 | (cPCImemrd & + 0x0F); + command->length = 0x04; + respond->address = command->address = addressofs; + command->width = 0x00 | (width & 0x0F); + command->follows = 0; + command->value = 0; + command->buffer = NULL; + respond->value = data; + init_completion(&respond->wait_completion); + ftdi->command_next += 1; + ftdi->respond_next += 1; + ftdi_elan_kick_command_queue(ftdi); + mutex_unlock(&ftdi->u132_lock); + wait_for_completion(&respond->wait_completion); + return result; + } else { + mutex_unlock(&ftdi->u132_lock); + msleep(100); + goto wait; + } + } } int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, int mem_offset, - u8 width, u32 *data) + u8 width, u32 *data) { - struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); - if (ftdi->initialized == 0) { - return -ENODEV; - } else - return ftdi_elan_read_pcimem(ftdi, mem_offset, width, data); + struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); + if (ftdi->initialized == 0) { + return -ENODEV; + } else + return ftdi_elan_read_pcimem(ftdi, mem_offset, width, data); } EXPORT_SYMBOL_GPL(usb_ftdi_elan_read_pcimem); static int ftdi_elan_edset_setup(struct usb_ftdi *ftdi, u8 ed_number, - void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, - void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, - int toggle_bits, int error_count, int condition_code, int repeat_number, - int halted, int skipped, int actual, int non_null)) -{ - u8 ed = ed_number - 1; - wait:if (ftdi->disconnected > 0) { - return -ENODEV; - } else if (ftdi->initialized == 0) { - return -ENODEV; - } else { - int command_size; - mutex_lock(&ftdi->u132_lock); - command_size = ftdi->command_next - ftdi->command_head; - if (command_size < COMMAND_SIZE) { - struct u132_target *target = &ftdi->target[ed]; - struct u132_command *command = &ftdi->command[ - COMMAND_MASK & ftdi->command_next]; - command->header = 0x80 | (ed << 5); - command->length = 0x8007; - command->address = (toggle_bits << 6) | (ep_number << 2) - | (address << 0); - command->width = usb_maxpacket(urb->dev, urb->pipe, - usb_pipeout(urb->pipe)); - command->follows = 8; - command->value = 0; - command->buffer = urb->setup_packet; - target->callback = callback; - target->endp = endp; - target->urb = urb; - target->active = 1; - ftdi->command_next += 1; - ftdi_elan_kick_command_queue(ftdi); - mutex_unlock(&ftdi->u132_lock); - return 0; - } else { - mutex_unlock(&ftdi->u132_lock); - msleep(100); - goto wait; - } - } + void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, + void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, + int toggle_bits, int error_count, int condition_code, int repeat_number, + int halted, int skipped, int actual, int non_null)) +{ + u8 ed = ed_number - 1; +wait:if (ftdi->disconnected > 0) { + return -ENODEV; + } else if (ftdi->initialized == 0) { + return -ENODEV; + } else { + int command_size; + mutex_lock(&ftdi->u132_lock); + command_size = ftdi->command_next - ftdi->command_head; + if (command_size < COMMAND_SIZE) { + struct u132_target *target = &ftdi->target[ed]; + struct u132_command *command = &ftdi->command[ + COMMAND_MASK & ftdi->command_next]; + command->header = 0x80 | (ed << 5); + command->length = 0x8007; + command->address = (toggle_bits << 6) | (ep_number << 2) + | (address << 0); + command->width = usb_maxpacket(urb->dev, urb->pipe, + usb_pipeout(urb->pipe)); + command->follows = 8; + command->value = 0; + command->buffer = urb->setup_packet; + target->callback = callback; + target->endp = endp; + target->urb = urb; + target->active = 1; + ftdi->command_next += 1; + ftdi_elan_kick_command_queue(ftdi); + mutex_unlock(&ftdi->u132_lock); + return 0; + } else { + mutex_unlock(&ftdi->u132_lock); + msleep(100); + goto wait; + } + } } int usb_ftdi_elan_edset_setup(struct platform_device *pdev, u8 ed_number, - void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, - void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, - int toggle_bits, int error_count, int condition_code, int repeat_number, - int halted, int skipped, int actual, int non_null)) + void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, + void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, + int toggle_bits, int error_count, int condition_code, int repeat_number, + int halted, int skipped, int actual, int non_null)) { - struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); - return ftdi_elan_edset_setup(ftdi, ed_number, endp, urb, address, - ep_number, toggle_bits, callback); + struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); + return ftdi_elan_edset_setup(ftdi, ed_number, endp, urb, address, + ep_number, toggle_bits, callback); } EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_setup); static int ftdi_elan_edset_input(struct usb_ftdi *ftdi, u8 ed_number, - void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, - void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, - int toggle_bits, int error_count, int condition_code, int repeat_number, - int halted, int skipped, int actual, int non_null)) -{ - u8 ed = ed_number - 1; - wait:if (ftdi->disconnected > 0) { - return -ENODEV; - } else if (ftdi->initialized == 0) { - return -ENODEV; - } else { - int command_size; - mutex_lock(&ftdi->u132_lock); - command_size = ftdi->command_next - ftdi->command_head; - if (command_size < COMMAND_SIZE) { - struct u132_target *target = &ftdi->target[ed]; - struct u132_command *command = &ftdi->command[ - COMMAND_MASK & ftdi->command_next]; - u32 remaining_length = urb->transfer_buffer_length - - urb->actual_length; - command->header = 0x82 | (ed << 5); - if (remaining_length == 0) { - command->length = 0x0000; - } else if (remaining_length > 1024) { - command->length = 0x8000 | 1023; - } else - command->length = 0x8000 | (remaining_length - - 1); - command->address = (toggle_bits << 6) | (ep_number << 2) - | (address << 0); - command->width = usb_maxpacket(urb->dev, urb->pipe, - usb_pipeout(urb->pipe)); - command->follows = 0; - command->value = 0; - command->buffer = NULL; - target->callback = callback; - target->endp = endp; - target->urb = urb; - target->active = 1; - ftdi->command_next += 1; - ftdi_elan_kick_command_queue(ftdi); - mutex_unlock(&ftdi->u132_lock); - return 0; - } else { - mutex_unlock(&ftdi->u132_lock); - msleep(100); - goto wait; - } - } + void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, + void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, + int toggle_bits, int error_count, int condition_code, int repeat_number, + int halted, int skipped, int actual, int non_null)) +{ + u8 ed = ed_number - 1; +wait:if (ftdi->disconnected > 0) { + return -ENODEV; + } else if (ftdi->initialized == 0) { + return -ENODEV; + } else { + int command_size; + mutex_lock(&ftdi->u132_lock); + command_size = ftdi->command_next - ftdi->command_head; + if (command_size < COMMAND_SIZE) { + struct u132_target *target = &ftdi->target[ed]; + struct u132_command *command = &ftdi->command[ + COMMAND_MASK & ftdi->command_next]; + u32 remaining_length = urb->transfer_buffer_length - + urb->actual_length; + command->header = 0x82 | (ed << 5); + if (remaining_length == 0) { + command->length = 0x0000; + } else if (remaining_length > 1024) { + command->length = 0x8000 | 1023; + } else + command->length = 0x8000 | (remaining_length - + 1); + command->address = (toggle_bits << 6) | (ep_number << 2) + | (address << 0); + command->width = usb_maxpacket(urb->dev, urb->pipe, + usb_pipeout(urb->pipe)); + command->follows = 0; + command->value = 0; + command->buffer = NULL; + target->callback = callback; + target->endp = endp; + target->urb = urb; + target->active = 1; + ftdi->command_next += 1; + ftdi_elan_kick_command_queue(ftdi); + mutex_unlock(&ftdi->u132_lock); + return 0; + } else { + mutex_unlock(&ftdi->u132_lock); + msleep(100); + goto wait; + } + } } int usb_ftdi_elan_edset_input(struct platform_device *pdev, u8 ed_number, - void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, - void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, - int toggle_bits, int error_count, int condition_code, int repeat_number, - int halted, int skipped, int actual, int non_null)) + void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, + void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, + int toggle_bits, int error_count, int condition_code, int repeat_number, + int halted, int skipped, int actual, int non_null)) { - struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); - return ftdi_elan_edset_input(ftdi, ed_number, endp, urb, address, - ep_number, toggle_bits, callback); + struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); + return ftdi_elan_edset_input(ftdi, ed_number, endp, urb, address, + ep_number, toggle_bits, callback); } EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_input); static int ftdi_elan_edset_empty(struct usb_ftdi *ftdi, u8 ed_number, - void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, - void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, - int toggle_bits, int error_count, int condition_code, int repeat_number, - int halted, int skipped, int actual, int non_null)) -{ - u8 ed = ed_number - 1; - wait:if (ftdi->disconnected > 0) { - return -ENODEV; - } else if (ftdi->initialized == 0) { - return -ENODEV; - } else { - int command_size; - mutex_lock(&ftdi->u132_lock); - command_size = ftdi->command_next - ftdi->command_head; - if (command_size < COMMAND_SIZE) { - struct u132_target *target = &ftdi->target[ed]; - struct u132_command *command = &ftdi->command[ - COMMAND_MASK & ftdi->command_next]; - command->header = 0x81 | (ed << 5); - command->length = 0x0000; - command->address = (toggle_bits << 6) | (ep_number << 2) - | (address << 0); - command->width = usb_maxpacket(urb->dev, urb->pipe, - usb_pipeout(urb->pipe)); - command->follows = 0; - command->value = 0; - command->buffer = NULL; - target->callback = callback; - target->endp = endp; - target->urb = urb; - target->active = 1; - ftdi->command_next += 1; - ftdi_elan_kick_command_queue(ftdi); - mutex_unlock(&ftdi->u132_lock); - return 0; - } else { - mutex_unlock(&ftdi->u132_lock); - msleep(100); - goto wait; - } - } + void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, + void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, + int toggle_bits, int error_count, int condition_code, int repeat_number, + int halted, int skipped, int actual, int non_null)) +{ + u8 ed = ed_number - 1; +wait:if (ftdi->disconnected > 0) { + return -ENODEV; + } else if (ftdi->initialized == 0) { + return -ENODEV; + } else { + int command_size; + mutex_lock(&ftdi->u132_lock); + command_size = ftdi->command_next - ftdi->command_head; + if (command_size < COMMAND_SIZE) { + struct u132_target *target = &ftdi->target[ed]; + struct u132_command *command = &ftdi->command[ + COMMAND_MASK & ftdi->command_next]; + command->header = 0x81 | (ed << 5); + command->length = 0x0000; + command->address = (toggle_bits << 6) | (ep_number << 2) + | (address << 0); + command->width = usb_maxpacket(urb->dev, urb->pipe, + usb_pipeout(urb->pipe)); + command->follows = 0; + command->value = 0; + command->buffer = NULL; + target->callback = callback; + target->endp = endp; + target->urb = urb; + target->active = 1; + ftdi->command_next += 1; + ftdi_elan_kick_command_queue(ftdi); + mutex_unlock(&ftdi->u132_lock); + return 0; + } else { + mutex_unlock(&ftdi->u132_lock); + msleep(100); + goto wait; + } + } } int usb_ftdi_elan_edset_empty(struct platform_device *pdev, u8 ed_number, - void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, - void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, - int toggle_bits, int error_count, int condition_code, int repeat_number, - int halted, int skipped, int actual, int non_null)) + void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, + void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, + int toggle_bits, int error_count, int condition_code, int repeat_number, + int halted, int skipped, int actual, int non_null)) { - struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); - return ftdi_elan_edset_empty(ftdi, ed_number, endp, urb, address, - ep_number, toggle_bits, callback); + struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); + return ftdi_elan_edset_empty(ftdi, ed_number, endp, urb, address, + ep_number, toggle_bits, callback); } EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_empty); static int ftdi_elan_edset_output(struct usb_ftdi *ftdi, u8 ed_number, - void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, - void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, - int toggle_bits, int error_count, int condition_code, int repeat_number, - int halted, int skipped, int actual, int non_null)) -{ - u8 ed = ed_number - 1; - wait:if (ftdi->disconnected > 0) { - return -ENODEV; - } else if (ftdi->initialized == 0) { - return -ENODEV; - } else { - int command_size; - mutex_lock(&ftdi->u132_lock); - command_size = ftdi->command_next - ftdi->command_head; - if (command_size < COMMAND_SIZE) { - u8 *b; - u16 urb_size; - int i = 0; - char data[30 *3 + 4]; - char *d = data; - int m = (sizeof(data) - 1) / 3; - int l = 0; - struct u132_target *target = &ftdi->target[ed]; - struct u132_command *command = &ftdi->command[ - COMMAND_MASK & ftdi->command_next]; - command->header = 0x81 | (ed << 5); - command->address = (toggle_bits << 6) | (ep_number << 2) - | (address << 0); - command->width = usb_maxpacket(urb->dev, urb->pipe, - usb_pipeout(urb->pipe)); - command->follows = min_t(u32, 1024, - urb->transfer_buffer_length - - urb->actual_length); - command->value = 0; - command->buffer = urb->transfer_buffer + - urb->actual_length; - command->length = 0x8000 | (command->follows - 1); - b = command->buffer; - urb_size = command->follows; - data[0] = 0; - while (urb_size-- > 0) { - if (i > m) { - } else if (i++ < m) { - int w = sprintf(d, " %02X", *b++); - d += w; - l += w; - } else - d += sprintf(d, " .."); - } - target->callback = callback; - target->endp = endp; - target->urb = urb; - target->active = 1; - ftdi->command_next += 1; - ftdi_elan_kick_command_queue(ftdi); - mutex_unlock(&ftdi->u132_lock); - return 0; - } else { - mutex_unlock(&ftdi->u132_lock); - msleep(100); - goto wait; - } - } + void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, + void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, + int toggle_bits, int error_count, int condition_code, int repeat_number, + int halted, int skipped, int actual, int non_null)) +{ + u8 ed = ed_number - 1; +wait:if (ftdi->disconnected > 0) { + return -ENODEV; + } else if (ftdi->initialized == 0) { + return -ENODEV; + } else { + int command_size; + mutex_lock(&ftdi->u132_lock); + command_size = ftdi->command_next - ftdi->command_head; + if (command_size < COMMAND_SIZE) { + u8 *b; + u16 urb_size; + int i = 0; + char data[30 *3 + 4]; + char *d = data; + int m = (sizeof(data) - 1) / 3; + int l = 0; + struct u132_target *target = &ftdi->target[ed]; + struct u132_command *command = &ftdi->command[ + COMMAND_MASK & ftdi->command_next]; + command->header = 0x81 | (ed << 5); + command->address = (toggle_bits << 6) | (ep_number << 2) + | (address << 0); + command->width = usb_maxpacket(urb->dev, urb->pipe, + usb_pipeout(urb->pipe)); + command->follows = min_t(u32, 1024, + urb->transfer_buffer_length - + urb->actual_length); + command->value = 0; + command->buffer = urb->transfer_buffer + + urb->actual_length; + command->length = 0x8000 | (command->follows - 1); + b = command->buffer; + urb_size = command->follows; + data[0] = 0; + while (urb_size-- > 0) { + if (i > m) { + } else if (i++ < m) { + int w = sprintf(d, " %02X", *b++); + d += w; + l += w; + } else + d += sprintf(d, " .."); + } + target->callback = callback; + target->endp = endp; + target->urb = urb; + target->active = 1; + ftdi->command_next += 1; + ftdi_elan_kick_command_queue(ftdi); + mutex_unlock(&ftdi->u132_lock); + return 0; + } else { + mutex_unlock(&ftdi->u132_lock); + msleep(100); + goto wait; + } + } } int usb_ftdi_elan_edset_output(struct platform_device *pdev, u8 ed_number, - void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, - void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, - int toggle_bits, int error_count, int condition_code, int repeat_number, - int halted, int skipped, int actual, int non_null)) + void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, + void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, + int toggle_bits, int error_count, int condition_code, int repeat_number, + int halted, int skipped, int actual, int non_null)) { - struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); - return ftdi_elan_edset_output(ftdi, ed_number, endp, urb, address, - ep_number, toggle_bits, callback); + struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); + return ftdi_elan_edset_output(ftdi, ed_number, endp, urb, address, + ep_number, toggle_bits, callback); } EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_output); static int ftdi_elan_edset_single(struct usb_ftdi *ftdi, u8 ed_number, - void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, - void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, - int toggle_bits, int error_count, int condition_code, int repeat_number, - int halted, int skipped, int actual, int non_null)) -{ - u8 ed = ed_number - 1; - wait:if (ftdi->disconnected > 0) { - return -ENODEV; - } else if (ftdi->initialized == 0) { - return -ENODEV; - } else { - int command_size; - mutex_lock(&ftdi->u132_lock); - command_size = ftdi->command_next - ftdi->command_head; - if (command_size < COMMAND_SIZE) { - u32 remaining_length = urb->transfer_buffer_length - - urb->actual_length; - struct u132_target *target = &ftdi->target[ed]; - struct u132_command *command = &ftdi->command[ - COMMAND_MASK & ftdi->command_next]; - command->header = 0x83 | (ed << 5); - if (remaining_length == 0) { - command->length = 0x0000; - } else if (remaining_length > 1024) { - command->length = 0x8000 | 1023; - } else - command->length = 0x8000 | (remaining_length - - 1); - command->address = (toggle_bits << 6) | (ep_number << 2) - | (address << 0); - command->width = usb_maxpacket(urb->dev, urb->pipe, - usb_pipeout(urb->pipe)); - command->follows = 0; - command->value = 0; - command->buffer = NULL; - target->callback = callback; - target->endp = endp; - target->urb = urb; - target->active = 1; - ftdi->command_next += 1; - ftdi_elan_kick_command_queue(ftdi); - mutex_unlock(&ftdi->u132_lock); - return 0; - } else { - mutex_unlock(&ftdi->u132_lock); - msleep(100); - goto wait; - } - } + void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, + void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, + int toggle_bits, int error_count, int condition_code, int repeat_number, + int halted, int skipped, int actual, int non_null)) +{ + u8 ed = ed_number - 1; +wait:if (ftdi->disconnected > 0) { + return -ENODEV; + } else if (ftdi->initialized == 0) { + return -ENODEV; + } else { + int command_size; + mutex_lock(&ftdi->u132_lock); + command_size = ftdi->command_next - ftdi->command_head; + if (command_size < COMMAND_SIZE) { + u32 remaining_length = urb->transfer_buffer_length - + urb->actual_length; + struct u132_target *target = &ftdi->target[ed]; + struct u132_command *command = &ftdi->command[ + COMMAND_MASK & ftdi->command_next]; + command->header = 0x83 | (ed << 5); + if (remaining_length == 0) { + command->length = 0x0000; + } else if (remaining_length > 1024) { + command->length = 0x8000 | 1023; + } else + command->length = 0x8000 | (remaining_length - + 1); + command->address = (toggle_bits << 6) | (ep_number << 2) + | (address << 0); + command->width = usb_maxpacket(urb->dev, urb->pipe, + usb_pipeout(urb->pipe)); + command->follows = 0; + command->value = 0; + command->buffer = NULL; + target->callback = callback; + target->endp = endp; + target->urb = urb; + target->active = 1; + ftdi->command_next += 1; + ftdi_elan_kick_command_queue(ftdi); + mutex_unlock(&ftdi->u132_lock); + return 0; + } else { + mutex_unlock(&ftdi->u132_lock); + msleep(100); + goto wait; + } + } } int usb_ftdi_elan_edset_single(struct platform_device *pdev, u8 ed_number, - void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, - void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, - int toggle_bits, int error_count, int condition_code, int repeat_number, - int halted, int skipped, int actual, int non_null)) + void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, + void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, + int toggle_bits, int error_count, int condition_code, int repeat_number, + int halted, int skipped, int actual, int non_null)) { - struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); - return ftdi_elan_edset_single(ftdi, ed_number, endp, urb, address, - ep_number, toggle_bits, callback); + struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); + return ftdi_elan_edset_single(ftdi, ed_number, endp, urb, address, + ep_number, toggle_bits, callback); } EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_single); static int ftdi_elan_edset_flush(struct usb_ftdi *ftdi, u8 ed_number, - void *endp) -{ - u8 ed = ed_number - 1; - if (ftdi->disconnected > 0) { - return -ENODEV; - } else if (ftdi->initialized == 0) { - return -ENODEV; - } else { - struct u132_target *target = &ftdi->target[ed]; - mutex_lock(&ftdi->u132_lock); - if (target->abandoning > 0) { - mutex_unlock(&ftdi->u132_lock); - return 0; - } else { - target->abandoning = 1; - wait_1:if (target->active == 1) { - int command_size = ftdi->command_next - - ftdi->command_head; - if (command_size < COMMAND_SIZE) { - struct u132_command *command = - &ftdi->command[COMMAND_MASK & - ftdi->command_next]; - command->header = 0x80 | (ed << 5) | - 0x4; - command->length = 0x00; - command->address = 0x00; - command->width = 0x00; - command->follows = 0; - command->value = 0; - command->buffer = &command->value; - ftdi->command_next += 1; - ftdi_elan_kick_command_queue(ftdi); - } else { - mutex_unlock(&ftdi->u132_lock); - msleep(100); - mutex_lock(&ftdi->u132_lock); - goto wait_1; - } - } - mutex_unlock(&ftdi->u132_lock); - return 0; - } - } + void *endp) +{ + u8 ed = ed_number - 1; + if (ftdi->disconnected > 0) { + return -ENODEV; + } else if (ftdi->initialized == 0) { + return -ENODEV; + } else { + struct u132_target *target = &ftdi->target[ed]; + mutex_lock(&ftdi->u132_lock); + if (target->abandoning > 0) { + mutex_unlock(&ftdi->u132_lock); + return 0; + } else { + target->abandoning = 1; + wait_1:if (target->active == 1) { + int command_size = ftdi->command_next - + ftdi->command_head; + if (command_size < COMMAND_SIZE) { + struct u132_command *command = + &ftdi->command[COMMAND_MASK & + ftdi->command_next]; + command->header = 0x80 | (ed << 5) | + 0x4; + command->length = 0x00; + command->address = 0x00; + command->width = 0x00; + command->follows = 0; + command->value = 0; + command->buffer = &command->value; + ftdi->command_next += 1; + ftdi_elan_kick_command_queue(ftdi); + } else { + mutex_unlock(&ftdi->u132_lock); + msleep(100); + mutex_lock(&ftdi->u132_lock); + goto wait_1; + } + } + mutex_unlock(&ftdi->u132_lock); + return 0; + } + } } int usb_ftdi_elan_edset_flush(struct platform_device *pdev, u8 ed_number, - void *endp) + void *endp) { - struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); - return ftdi_elan_edset_flush(ftdi, ed_number, endp); + struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); + return ftdi_elan_edset_flush(ftdi, ed_number, endp); } EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_flush); static int ftdi_elan_flush_input_fifo(struct usb_ftdi *ftdi) { - int retry_on_empty = 10; - int retry_on_timeout = 5; - int retry_on_status = 20; - more:{ - int packet_bytes = 0; - int retval = usb_bulk_msg(ftdi->udev, - usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr), - ftdi->bulk_in_buffer, ftdi->bulk_in_size, - &packet_bytes, 100); - if (packet_bytes > 2) { - char diag[30 *3 + 4]; - char *d = diag; - int m = (sizeof(diag) - 1) / 3; - char *b = ftdi->bulk_in_buffer; - int bytes_read = 0; - diag[0] = 0; - while (packet_bytes-- > 0) { - char c = *b++; - if (bytes_read < m) { - d += sprintf(d, " %02X", - 0x000000FF & c); - } else if (bytes_read > m) { - } else - d += sprintf(d, " .."); - bytes_read += 1; - continue; - } - goto more; - } else if (packet_bytes > 1) { - char s1 = ftdi->bulk_in_buffer[0]; - char s2 = ftdi->bulk_in_buffer[1]; - if (s1 == 0x31 && s2 == 0x60) { - return 0; - } else if (retry_on_status-- > 0) { - goto more; - } else { - dev_err(&ftdi->udev->dev, "STATUS ERROR retry l" - "imit reached\n"); - return -EFAULT; - } - } else if (packet_bytes > 0) { - char b1 = ftdi->bulk_in_buffer[0]; - dev_err(&ftdi->udev->dev, "only one byte flushed from F" - "TDI = %02X\n", b1); - if (retry_on_status-- > 0) { - goto more; - } else { - dev_err(&ftdi->udev->dev, "STATUS ERROR retry l" - "imit reached\n"); - return -EFAULT; - } - } else if (retval == -ETIMEDOUT) { - if (retry_on_timeout-- > 0) { - goto more; - } else { - dev_err(&ftdi->udev->dev, "TIMED OUT retry limi" - "t reached\n"); - return -ENOMEM; - } - } else if (retval == 0) { - if (retry_on_empty-- > 0) { - goto more; - } else { - dev_err(&ftdi->udev->dev, "empty packet retry l" - "imit reached\n"); - return -ENOMEM; - } - } else { - dev_err(&ftdi->udev->dev, "error = %d\n", retval); - return retval; - } - } - return -1; + int retry_on_empty = 10; + int retry_on_timeout = 5; + int retry_on_status = 20; +more:{ + int packet_bytes = 0; + int retval = usb_bulk_msg(ftdi->udev, + usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr), + ftdi->bulk_in_buffer, ftdi->bulk_in_size, + &packet_bytes, 100); + if (packet_bytes > 2) { + char diag[30 *3 + 4]; + char *d = diag; + int m = (sizeof(diag) - 1) / 3; + char *b = ftdi->bulk_in_buffer; + int bytes_read = 0; + diag[0] = 0; + while (packet_bytes-- > 0) { + char c = *b++; + if (bytes_read < m) { + d += sprintf(d, " %02X", + 0x000000FF & c); + } else if (bytes_read > m) { + } else + d += sprintf(d, " .."); + bytes_read += 1; + continue; + } + goto more; + } else if (packet_bytes > 1) { + char s1 = ftdi->bulk_in_buffer[0]; + char s2 = ftdi->bulk_in_buffer[1]; + if (s1 == 0x31 && s2 == 0x60) { + return 0; + } else if (retry_on_status-- > 0) { + goto more; + } else { + dev_err(&ftdi->udev->dev, "STATUS ERROR retry limit reached\n"); + return -EFAULT; + } + } else if (packet_bytes > 0) { + char b1 = ftdi->bulk_in_buffer[0]; + dev_err(&ftdi->udev->dev, "only one byte flushed from FTDI = %02X\n", + b1); + if (retry_on_status-- > 0) { + goto more; + } else { + dev_err(&ftdi->udev->dev, "STATUS ERROR retry limit reached\n"); + return -EFAULT; + } + } else if (retval == -ETIMEDOUT) { + if (retry_on_timeout-- > 0) { + goto more; + } else { + dev_err(&ftdi->udev->dev, "TIMED OUT retry limit reached\n"); + return -ENOMEM; + } + } else if (retval == 0) { + if (retry_on_empty-- > 0) { + goto more; + } else { + dev_err(&ftdi->udev->dev, "empty packet retry limit reached\n"); + return -ENOMEM; + } + } else { + dev_err(&ftdi->udev->dev, "error = %d\n", retval); + return retval; + } + } + return -1; } /* -* send the long flush sequence -* -*/ + * send the long flush sequence + * + */ static int ftdi_elan_synchronize_flush(struct usb_ftdi *ftdi) { - int retval; - struct urb *urb; - char *buf; - int I = 257; - int i = 0; - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - dev_err(&ftdi->udev->dev, "could not alloc a urb for flush sequ" - "ence\n"); - return -ENOMEM; - } - buf = usb_buffer_alloc(ftdi->udev, I, GFP_KERNEL, &urb->transfer_dma); - if (!buf) { - dev_err(&ftdi->udev->dev, "could not get a buffer for flush seq" - "uence\n"); - usb_free_urb(urb); - return -ENOMEM; - } - while (I-- > 0) - buf[i++] = 0x55; - usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev, - ftdi->bulk_out_endpointAddr), buf, i, - ftdi_elan_write_bulk_callback, ftdi); - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - retval = usb_submit_urb(urb, GFP_KERNEL); - if (retval) { - dev_err(&ftdi->udev->dev, "failed to submit urb containing the " - "flush sequence\n"); - usb_buffer_free(ftdi->udev, i, buf, urb->transfer_dma); - usb_free_urb(urb); - return -ENOMEM; - } - usb_free_urb(urb); - return 0; + int retval; + struct urb *urb; + char *buf; + int I = 257; + int i = 0; + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + dev_err(&ftdi->udev->dev, "could not alloc a urb for flush sequence\n"); + return -ENOMEM; + } + buf = usb_alloc_coherent(ftdi->udev, I, GFP_KERNEL, &urb->transfer_dma); + if (!buf) { + dev_err(&ftdi->udev->dev, "could not get a buffer for flush sequence\n"); + usb_free_urb(urb); + return -ENOMEM; + } + while (I-- > 0) + buf[i++] = 0x55; + usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev, + ftdi->bulk_out_endpointAddr), buf, i, + ftdi_elan_write_bulk_callback, ftdi); + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + retval = usb_submit_urb(urb, GFP_KERNEL); + if (retval) { + dev_err(&ftdi->udev->dev, "failed to submit urb containing the flush sequence\n"); + usb_free_coherent(ftdi->udev, i, buf, urb->transfer_dma); + usb_free_urb(urb); + return -ENOMEM; + } + usb_free_urb(urb); + return 0; } /* -* send the reset sequence -* -*/ + * send the reset sequence + * + */ static int ftdi_elan_synchronize_reset(struct usb_ftdi *ftdi) { - int retval; - struct urb *urb; - char *buf; - int I = 4; - int i = 0; - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - dev_err(&ftdi->udev->dev, "could not get a urb for the reset se" - "quence\n"); - return -ENOMEM; - } - buf = usb_buffer_alloc(ftdi->udev, I, GFP_KERNEL, &urb->transfer_dma); - if (!buf) { - dev_err(&ftdi->udev->dev, "could not get a buffer for the reset" - " sequence\n"); - usb_free_urb(urb); - return -ENOMEM; - } - buf[i++] = 0x55; - buf[i++] = 0xAA; - buf[i++] = 0x5A; - buf[i++] = 0xA5; - usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev, - ftdi->bulk_out_endpointAddr), buf, i, - ftdi_elan_write_bulk_callback, ftdi); - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - retval = usb_submit_urb(urb, GFP_KERNEL); - if (retval) { - dev_err(&ftdi->udev->dev, "failed to submit urb containing the " - "reset sequence\n"); - usb_buffer_free(ftdi->udev, i, buf, urb->transfer_dma); - usb_free_urb(urb); - return -ENOMEM; - } - usb_free_urb(urb); - return 0; + int retval; + struct urb *urb; + char *buf; + int I = 4; + int i = 0; + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + dev_err(&ftdi->udev->dev, "could not get a urb for the reset sequence\n"); + return -ENOMEM; + } + buf = usb_alloc_coherent(ftdi->udev, I, GFP_KERNEL, &urb->transfer_dma); + if (!buf) { + dev_err(&ftdi->udev->dev, "could not get a buffer for the reset sequence\n"); + usb_free_urb(urb); + return -ENOMEM; + } + buf[i++] = 0x55; + buf[i++] = 0xAA; + buf[i++] = 0x5A; + buf[i++] = 0xA5; + usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev, + ftdi->bulk_out_endpointAddr), buf, i, + ftdi_elan_write_bulk_callback, ftdi); + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + retval = usb_submit_urb(urb, GFP_KERNEL); + if (retval) { + dev_err(&ftdi->udev->dev, "failed to submit urb containing the reset sequence\n"); + usb_free_coherent(ftdi->udev, i, buf, urb->transfer_dma); + usb_free_urb(urb); + return -ENOMEM; + } + usb_free_urb(urb); + return 0; } static int ftdi_elan_synchronize(struct usb_ftdi *ftdi) { - int retval; - int long_stop = 10; - int retry_on_timeout = 5; - int retry_on_empty = 10; - int err_count = 0; - retval = ftdi_elan_flush_input_fifo(ftdi); - if (retval) - return retval; - ftdi->bulk_in_left = 0; - ftdi->bulk_in_last = -1; - while (long_stop-- > 0) { - int read_stop; - int read_stuck; - retval = ftdi_elan_synchronize_flush(ftdi); - if (retval) - return retval; - retval = ftdi_elan_flush_input_fifo(ftdi); - if (retval) - return retval; - reset:retval = ftdi_elan_synchronize_reset(ftdi); - if (retval) - return retval; - read_stop = 100; - read_stuck = 10; - read:{ - int packet_bytes = 0; - retval = usb_bulk_msg(ftdi->udev, - usb_rcvbulkpipe(ftdi->udev, - ftdi->bulk_in_endpointAddr), - ftdi->bulk_in_buffer, ftdi->bulk_in_size, - &packet_bytes, 500); - if (packet_bytes > 2) { - char diag[30 *3 + 4]; - char *d = diag; - int m = (sizeof(diag) - 1) / 3; - char *b = ftdi->bulk_in_buffer; - int bytes_read = 0; - unsigned char c = 0; - diag[0] = 0; - while (packet_bytes-- > 0) { - c = *b++; - if (bytes_read < m) { - d += sprintf(d, " %02X", c); - } else if (bytes_read > m) { - } else - d += sprintf(d, " .."); - bytes_read += 1; - continue; - } - if (c == 0x7E) { - return 0; - } else { - if (c == 0x55) { - goto read; - } else if (read_stop-- > 0) { - goto read; - } else { - dev_err(&ftdi->udev->dev, "retr" - "y limit reached\n"); - continue; - } - } - } else if (packet_bytes > 1) { - unsigned char s1 = ftdi->bulk_in_buffer[0]; - unsigned char s2 = ftdi->bulk_in_buffer[1]; - if (s1 == 0x31 && s2 == 0x00) { - if (read_stuck-- > 0) { - goto read; - } else - goto reset; - } else if (s1 == 0x31 && s2 == 0x60) { - if (read_stop-- > 0) { - goto read; - } else { - dev_err(&ftdi->udev->dev, "retr" - "y limit reached\n"); - continue; - } - } else { - if (read_stop-- > 0) { - goto read; - } else { - dev_err(&ftdi->udev->dev, "retr" - "y limit reached\n"); - continue; - } - } - } else if (packet_bytes > 0) { - if (read_stop-- > 0) { - goto read; - } else { - dev_err(&ftdi->udev->dev, "retry limit " - "reached\n"); - continue; - } - } else if (retval == -ETIMEDOUT) { - if (retry_on_timeout-- > 0) { - goto read; - } else { - dev_err(&ftdi->udev->dev, "TIMED OUT re" - "try limit reached\n"); - continue; - } - } else if (retval == 0) { - if (retry_on_empty-- > 0) { - goto read; - } else { - dev_err(&ftdi->udev->dev, "empty packet" - " retry limit reached\n"); - continue; - } - } else { - err_count += 1; - dev_err(&ftdi->udev->dev, "error = %d\n", - retval); - if (read_stop-- > 0) { - goto read; - } else { - dev_err(&ftdi->udev->dev, "retry limit " - "reached\n"); - continue; - } - } - } - } - dev_err(&ftdi->udev->dev, "failed to synchronize\n"); - return -EFAULT; + int retval; + int long_stop = 10; + int retry_on_timeout = 5; + int retry_on_empty = 10; + int err_count = 0; + retval = ftdi_elan_flush_input_fifo(ftdi); + if (retval) + return retval; + ftdi->bulk_in_left = 0; + ftdi->bulk_in_last = -1; + while (long_stop-- > 0) { + int read_stop; + int read_stuck; + retval = ftdi_elan_synchronize_flush(ftdi); + if (retval) + return retval; + retval = ftdi_elan_flush_input_fifo(ftdi); + if (retval) + return retval; + reset:retval = ftdi_elan_synchronize_reset(ftdi); + if (retval) + return retval; + read_stop = 100; + read_stuck = 10; + read:{ + int packet_bytes = 0; + retval = usb_bulk_msg(ftdi->udev, + usb_rcvbulkpipe(ftdi->udev, + ftdi->bulk_in_endpointAddr), + ftdi->bulk_in_buffer, ftdi->bulk_in_size, + &packet_bytes, 500); + if (packet_bytes > 2) { + char diag[30 *3 + 4]; + char *d = diag; + int m = (sizeof(diag) - 1) / 3; + char *b = ftdi->bulk_in_buffer; + int bytes_read = 0; + unsigned char c = 0; + diag[0] = 0; + while (packet_bytes-- > 0) { + c = *b++; + if (bytes_read < m) { + d += sprintf(d, " %02X", c); + } else if (bytes_read > m) { + } else + d += sprintf(d, " .."); + bytes_read += 1; + continue; + } + if (c == 0x7E) { + return 0; + } else { + if (c == 0x55) { + goto read; + } else if (read_stop-- > 0) { + goto read; + } else { + dev_err(&ftdi->udev->dev, "retry limit reached\n"); + continue; + } + } + } else if (packet_bytes > 1) { + unsigned char s1 = ftdi->bulk_in_buffer[0]; + unsigned char s2 = ftdi->bulk_in_buffer[1]; + if (s1 == 0x31 && s2 == 0x00) { + if (read_stuck-- > 0) { + goto read; + } else + goto reset; + } else if (s1 == 0x31 && s2 == 0x60) { + if (read_stop-- > 0) { + goto read; + } else { + dev_err(&ftdi->udev->dev, "retry limit reached\n"); + continue; + } + } else { + if (read_stop-- > 0) { + goto read; + } else { + dev_err(&ftdi->udev->dev, "retry limit reached\n"); + continue; + } + } + } else if (packet_bytes > 0) { + if (read_stop-- > 0) { + goto read; + } else { + dev_err(&ftdi->udev->dev, "retry limit reached\n"); + continue; + } + } else if (retval == -ETIMEDOUT) { + if (retry_on_timeout-- > 0) { + goto read; + } else { + dev_err(&ftdi->udev->dev, "TIMED OUT retry limit reached\n"); + continue; + } + } else if (retval == 0) { + if (retry_on_empty-- > 0) { + goto read; + } else { + dev_err(&ftdi->udev->dev, "empty packet retry limit reached\n"); + continue; + } + } else { + err_count += 1; + dev_err(&ftdi->udev->dev, "error = %d\n", + retval); + if (read_stop-- > 0) { + goto read; + } else { + dev_err(&ftdi->udev->dev, "retry limit reached\n"); + continue; + } + } + } + } + dev_err(&ftdi->udev->dev, "failed to synchronize\n"); + return -EFAULT; } static int ftdi_elan_stuck_waiting(struct usb_ftdi *ftdi) { - int retry_on_empty = 10; - int retry_on_timeout = 5; - int retry_on_status = 50; - more:{ - int packet_bytes = 0; - int retval = usb_bulk_msg(ftdi->udev, - usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr), - ftdi->bulk_in_buffer, ftdi->bulk_in_size, - &packet_bytes, 1000); - if (packet_bytes > 2) { - char diag[30 *3 + 4]; - char *d = diag; - int m = (sizeof(diag) - 1) / 3; - char *b = ftdi->bulk_in_buffer; - int bytes_read = 0; - diag[0] = 0; - while (packet_bytes-- > 0) { - char c = *b++; - if (bytes_read < m) { - d += sprintf(d, " %02X", - 0x000000FF & c); - } else if (bytes_read > m) { - } else - d += sprintf(d, " .."); - bytes_read += 1; - continue; - } - goto more; - } else if (packet_bytes > 1) { - char s1 = ftdi->bulk_in_buffer[0]; - char s2 = ftdi->bulk_in_buffer[1]; - if (s1 == 0x31 && s2 == 0x60) { - return 0; - } else if (retry_on_status-- > 0) { - msleep(5); - goto more; - } else - return -EFAULT; - } else if (packet_bytes > 0) { - char b1 = ftdi->bulk_in_buffer[0]; - dev_err(&ftdi->udev->dev, "only one byte flushed from F" - "TDI = %02X\n", b1); - if (retry_on_status-- > 0) { - msleep(5); - goto more; - } else { - dev_err(&ftdi->udev->dev, "STATUS ERROR retry l" - "imit reached\n"); - return -EFAULT; - } - } else if (retval == -ETIMEDOUT) { - if (retry_on_timeout-- > 0) { - goto more; - } else { - dev_err(&ftdi->udev->dev, "TIMED OUT retry limi" - "t reached\n"); - return -ENOMEM; - } - } else if (retval == 0) { - if (retry_on_empty-- > 0) { - goto more; - } else { - dev_err(&ftdi->udev->dev, "empty packet retry l" - "imit reached\n"); - return -ENOMEM; - } - } else { - dev_err(&ftdi->udev->dev, "error = %d\n", retval); - return -ENOMEM; - } - } - return -1; + int retry_on_empty = 10; + int retry_on_timeout = 5; + int retry_on_status = 50; +more:{ + int packet_bytes = 0; + int retval = usb_bulk_msg(ftdi->udev, + usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr), + ftdi->bulk_in_buffer, ftdi->bulk_in_size, + &packet_bytes, 1000); + if (packet_bytes > 2) { + char diag[30 *3 + 4]; + char *d = diag; + int m = (sizeof(diag) - 1) / 3; + char *b = ftdi->bulk_in_buffer; + int bytes_read = 0; + diag[0] = 0; + while (packet_bytes-- > 0) { + char c = *b++; + if (bytes_read < m) { + d += sprintf(d, " %02X", + 0x000000FF & c); + } else if (bytes_read > m) { + } else + d += sprintf(d, " .."); + bytes_read += 1; + continue; + } + goto more; + } else if (packet_bytes > 1) { + char s1 = ftdi->bulk_in_buffer[0]; + char s2 = ftdi->bulk_in_buffer[1]; + if (s1 == 0x31 && s2 == 0x60) { + return 0; + } else if (retry_on_status-- > 0) { + msleep(5); + goto more; + } else + return -EFAULT; + } else if (packet_bytes > 0) { + char b1 = ftdi->bulk_in_buffer[0]; + dev_err(&ftdi->udev->dev, "only one byte flushed from FTDI = %02X\n", b1); + if (retry_on_status-- > 0) { + msleep(5); + goto more; + } else { + dev_err(&ftdi->udev->dev, "STATUS ERROR retry limit reached\n"); + return -EFAULT; + } + } else if (retval == -ETIMEDOUT) { + if (retry_on_timeout-- > 0) { + goto more; + } else { + dev_err(&ftdi->udev->dev, "TIMED OUT retry limit reached\n"); + return -ENOMEM; + } + } else if (retval == 0) { + if (retry_on_empty-- > 0) { + goto more; + } else { + dev_err(&ftdi->udev->dev, "empty packet retry limit reached\n"); + return -ENOMEM; + } + } else { + dev_err(&ftdi->udev->dev, "error = %d\n", retval); + return -ENOMEM; + } + } + return -1; } static int ftdi_elan_checkingPCI(struct usb_ftdi *ftdi) { - int UxxxStatus = ftdi_elan_read_reg(ftdi, &ftdi->controlreg); - if (UxxxStatus) - return UxxxStatus; - if (ftdi->controlreg & 0x00400000) { - if (ftdi->card_ejected) { - } else { - ftdi->card_ejected = 1; - dev_err(&ftdi->udev->dev, "CARD EJECTED - controlreg = " - "%08X\n", ftdi->controlreg); - } - return -ENODEV; - } else { - u8 fn = ftdi->function - 1; - int activePCIfn = fn << 8; - u32 pcidata; - u32 pciVID; - u32 pciPID; - int reg = 0; - UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, - &pcidata); - if (UxxxStatus) - return UxxxStatus; - pciVID = pcidata & 0xFFFF; - pciPID = (pcidata >> 16) & 0xFFFF; - if (pciVID == ftdi->platform_data.vendor && pciPID == - ftdi->platform_data.device) { - return 0; - } else { - dev_err(&ftdi->udev->dev, "vendor=%04X pciVID=%04X devi" - "ce=%04X pciPID=%04X\n", - ftdi->platform_data.vendor, pciVID, - ftdi->platform_data.device, pciPID); - return -ENODEV; - } - } + int UxxxStatus = ftdi_elan_read_reg(ftdi, &ftdi->controlreg); + if (UxxxStatus) + return UxxxStatus; + if (ftdi->controlreg & 0x00400000) { + if (ftdi->card_ejected) { + } else { + ftdi->card_ejected = 1; + dev_err(&ftdi->udev->dev, "CARD EJECTED - controlreg = %08X\n", + ftdi->controlreg); + } + return -ENODEV; + } else { + u8 fn = ftdi->function - 1; + int activePCIfn = fn << 8; + u32 pcidata; + u32 pciVID; + u32 pciPID; + int reg = 0; + UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, + &pcidata); + if (UxxxStatus) + return UxxxStatus; + pciVID = pcidata & 0xFFFF; + pciPID = (pcidata >> 16) & 0xFFFF; + if (pciVID == ftdi->platform_data.vendor && pciPID == + ftdi->platform_data.device) { + return 0; + } else { + dev_err(&ftdi->udev->dev, "vendor=%04X pciVID=%04X device=%04X pciPID=%04X\n", + ftdi->platform_data.vendor, pciVID, + ftdi->platform_data.device, pciPID); + return -ENODEV; + } + } } #define ftdi_read_pcimem(ftdi, member, data) ftdi_elan_read_pcimem(ftdi, \ - offsetof(struct ohci_regs, member), 0, data); + offsetof(struct ohci_regs, member), 0, data); #define ftdi_write_pcimem(ftdi, member, data) ftdi_elan_write_pcimem(ftdi, \ - offsetof(struct ohci_regs, member), 0, data); + offsetof(struct ohci_regs, member), 0, data); #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR -#define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \ - OHCI_INTR_WDH) +#define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \ + OHCI_INTR_WDH) static int ftdi_elan_check_controller(struct usb_ftdi *ftdi, int quirk) { - int devices = 0; - int retval; - u32 hc_control; - int num_ports; - u32 control; - u32 rh_a = -1; - u32 status; - u32 fminterval; - u32 hc_fminterval; - u32 periodicstart; - u32 cmdstatus; - u32 roothub_a; - int mask = OHCI_INTR_INIT; - int sleep_time = 0; - int reset_timeout = 30; /* ... allow extra time */ - int temp; - retval = ftdi_write_pcimem(ftdi, intrdisable, OHCI_INTR_MIE); - if (retval) - return retval; - retval = ftdi_read_pcimem(ftdi, control, &control); - if (retval) - return retval; - retval = ftdi_read_pcimem(ftdi, roothub.a, &rh_a); - if (retval) - return retval; - num_ports = rh_a & RH_A_NDP; - retval = ftdi_read_pcimem(ftdi, fminterval, &hc_fminterval); - if (retval) - return retval; - hc_fminterval &= 0x3fff; - if (hc_fminterval != FI) { - } - hc_fminterval |= FSMP(hc_fminterval) << 16; - retval = ftdi_read_pcimem(ftdi, control, &hc_control); - if (retval) - return retval; - switch (hc_control & OHCI_CTRL_HCFS) { - case OHCI_USB_OPER: - sleep_time = 0; - break; - case OHCI_USB_SUSPEND: - case OHCI_USB_RESUME: - hc_control &= OHCI_CTRL_RWC; - hc_control |= OHCI_USB_RESUME; - sleep_time = 10; - break; - default: - hc_control &= OHCI_CTRL_RWC; - hc_control |= OHCI_USB_RESET; - sleep_time = 50; - break; - } - retval = ftdi_write_pcimem(ftdi, control, hc_control); - if (retval) - return retval; - retval = ftdi_read_pcimem(ftdi, control, &control); - if (retval) - return retval; - msleep(sleep_time); - retval = ftdi_read_pcimem(ftdi, roothub.a, &roothub_a); - if (retval) - return retval; - if (!(roothub_a & RH_A_NPS)) { /* power down each port */ - for (temp = 0; temp < num_ports; temp++) { - retval = ftdi_write_pcimem(ftdi, - roothub.portstatus[temp], RH_PS_LSDA); - if (retval) - return retval; - } - } - retval = ftdi_read_pcimem(ftdi, control, &control); - if (retval) - return retval; - retry:retval = ftdi_read_pcimem(ftdi, cmdstatus, &status); - if (retval) - return retval; - retval = ftdi_write_pcimem(ftdi, cmdstatus, OHCI_HCR); - if (retval) - return retval; - extra:{ - retval = ftdi_read_pcimem(ftdi, cmdstatus, &status); - if (retval) - return retval; - if (0 != (status & OHCI_HCR)) { - if (--reset_timeout == 0) { - dev_err(&ftdi->udev->dev, "USB HC reset timed o" - "ut!\n"); - return -ENODEV; - } else { - msleep(5); - goto extra; - } - } - } - if (quirk & OHCI_QUIRK_INITRESET) { - retval = ftdi_write_pcimem(ftdi, control, hc_control); - if (retval) - return retval; - retval = ftdi_read_pcimem(ftdi, control, &control); - if (retval) - return retval; - } - retval = ftdi_write_pcimem(ftdi, ed_controlhead, 0x00000000); - if (retval) - return retval; - retval = ftdi_write_pcimem(ftdi, ed_bulkhead, 0x11000000); - if (retval) - return retval; - retval = ftdi_write_pcimem(ftdi, hcca, 0x00000000); - if (retval) - return retval; - retval = ftdi_read_pcimem(ftdi, fminterval, &fminterval); - if (retval) - return retval; - retval = ftdi_write_pcimem(ftdi, fminterval, - ((fminterval & FIT) ^ FIT) | hc_fminterval); - if (retval) - return retval; - retval = ftdi_write_pcimem(ftdi, periodicstart, - ((9 *hc_fminterval) / 10) & 0x3fff); - if (retval) - return retval; - retval = ftdi_read_pcimem(ftdi, fminterval, &fminterval); - if (retval) - return retval; - retval = ftdi_read_pcimem(ftdi, periodicstart, &periodicstart); - if (retval) - return retval; - if (0 == (fminterval & 0x3fff0000) || 0 == periodicstart) { - if (!(quirk & OHCI_QUIRK_INITRESET)) { - quirk |= OHCI_QUIRK_INITRESET; - goto retry; - } else - dev_err(&ftdi->udev->dev, "init err(%08x %04x)\n", - fminterval, periodicstart); - } /* start controller operations */ - hc_control &= OHCI_CTRL_RWC; - hc_control |= OHCI_CONTROL_INIT | OHCI_CTRL_BLE | OHCI_USB_OPER; - retval = ftdi_write_pcimem(ftdi, control, hc_control); - if (retval) - return retval; - retval = ftdi_write_pcimem(ftdi, cmdstatus, OHCI_BLF); - if (retval) - return retval; - retval = ftdi_read_pcimem(ftdi, cmdstatus, &cmdstatus); - if (retval) - return retval; - retval = ftdi_read_pcimem(ftdi, control, &control); - if (retval) - return retval; - retval = ftdi_write_pcimem(ftdi, roothub.status, RH_HS_DRWE); - if (retval) - return retval; - retval = ftdi_write_pcimem(ftdi, intrstatus, mask); - if (retval) - return retval; - retval = ftdi_write_pcimem(ftdi, intrdisable, - OHCI_INTR_MIE | OHCI_INTR_OC | OHCI_INTR_RHSC | OHCI_INTR_FNO | - OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_SF | OHCI_INTR_WDH | - OHCI_INTR_SO); - if (retval) - return retval; /* handle root hub init quirks ... */ - retval = ftdi_read_pcimem(ftdi, roothub.a, &roothub_a); - if (retval) - return retval; - roothub_a &= ~(RH_A_PSM | RH_A_OCPM); - if (quirk & OHCI_QUIRK_SUPERIO) { - roothub_a |= RH_A_NOCP; - roothub_a &= ~(RH_A_POTPGT | RH_A_NPS); - retval = ftdi_write_pcimem(ftdi, roothub.a, roothub_a); - if (retval) - return retval; - } else if ((quirk & OHCI_QUIRK_AMD756) || distrust_firmware) { - roothub_a |= RH_A_NPS; - retval = ftdi_write_pcimem(ftdi, roothub.a, roothub_a); - if (retval) - return retval; - } - retval = ftdi_write_pcimem(ftdi, roothub.status, RH_HS_LPSC); - if (retval) - return retval; - retval = ftdi_write_pcimem(ftdi, roothub.b, - (roothub_a & RH_A_NPS) ? 0 : RH_B_PPCM); - if (retval) - return retval; - retval = ftdi_read_pcimem(ftdi, control, &control); - if (retval) - return retval; - mdelay((roothub_a >> 23) & 0x1fe); - for (temp = 0; temp < num_ports; temp++) { - u32 portstatus; - retval = ftdi_read_pcimem(ftdi, roothub.portstatus[temp], - &portstatus); - if (retval) - return retval; - if (1 & portstatus) - devices += 1; - } - return devices; + int devices = 0; + int retval; + u32 hc_control; + int num_ports; + u32 control; + u32 rh_a = -1; + u32 status; + u32 fminterval; + u32 hc_fminterval; + u32 periodicstart; + u32 cmdstatus; + u32 roothub_a; + int mask = OHCI_INTR_INIT; + int sleep_time = 0; + int reset_timeout = 30; /* ... allow extra time */ + int temp; + retval = ftdi_write_pcimem(ftdi, intrdisable, OHCI_INTR_MIE); + if (retval) + return retval; + retval = ftdi_read_pcimem(ftdi, control, &control); + if (retval) + return retval; + retval = ftdi_read_pcimem(ftdi, roothub.a, &rh_a); + if (retval) + return retval; + num_ports = rh_a & RH_A_NDP; + retval = ftdi_read_pcimem(ftdi, fminterval, &hc_fminterval); + if (retval) + return retval; + hc_fminterval &= 0x3fff; + if (hc_fminterval != FI) { + } + hc_fminterval |= FSMP(hc_fminterval) << 16; + retval = ftdi_read_pcimem(ftdi, control, &hc_control); + if (retval) + return retval; + switch (hc_control & OHCI_CTRL_HCFS) { + case OHCI_USB_OPER: + sleep_time = 0; + break; + case OHCI_USB_SUSPEND: + case OHCI_USB_RESUME: + hc_control &= OHCI_CTRL_RWC; + hc_control |= OHCI_USB_RESUME; + sleep_time = 10; + break; + default: + hc_control &= OHCI_CTRL_RWC; + hc_control |= OHCI_USB_RESET; + sleep_time = 50; + break; + } + retval = ftdi_write_pcimem(ftdi, control, hc_control); + if (retval) + return retval; + retval = ftdi_read_pcimem(ftdi, control, &control); + if (retval) + return retval; + msleep(sleep_time); + retval = ftdi_read_pcimem(ftdi, roothub.a, &roothub_a); + if (retval) + return retval; + if (!(roothub_a & RH_A_NPS)) { /* power down each port */ + for (temp = 0; temp < num_ports; temp++) { + retval = ftdi_write_pcimem(ftdi, + roothub.portstatus[temp], RH_PS_LSDA); + if (retval) + return retval; + } + } + retval = ftdi_read_pcimem(ftdi, control, &control); + if (retval) + return retval; +retry:retval = ftdi_read_pcimem(ftdi, cmdstatus, &status); + if (retval) + return retval; + retval = ftdi_write_pcimem(ftdi, cmdstatus, OHCI_HCR); + if (retval) + return retval; +extra:{ + retval = ftdi_read_pcimem(ftdi, cmdstatus, &status); + if (retval) + return retval; + if (0 != (status & OHCI_HCR)) { + if (--reset_timeout == 0) { + dev_err(&ftdi->udev->dev, "USB HC reset timed out!\n"); + return -ENODEV; + } else { + msleep(5); + goto extra; + } + } + } + if (quirk & OHCI_QUIRK_INITRESET) { + retval = ftdi_write_pcimem(ftdi, control, hc_control); + if (retval) + return retval; + retval = ftdi_read_pcimem(ftdi, control, &control); + if (retval) + return retval; + } + retval = ftdi_write_pcimem(ftdi, ed_controlhead, 0x00000000); + if (retval) + return retval; + retval = ftdi_write_pcimem(ftdi, ed_bulkhead, 0x11000000); + if (retval) + return retval; + retval = ftdi_write_pcimem(ftdi, hcca, 0x00000000); + if (retval) + return retval; + retval = ftdi_read_pcimem(ftdi, fminterval, &fminterval); + if (retval) + return retval; + retval = ftdi_write_pcimem(ftdi, fminterval, + ((fminterval & FIT) ^ FIT) | hc_fminterval); + if (retval) + return retval; + retval = ftdi_write_pcimem(ftdi, periodicstart, + ((9 *hc_fminterval) / 10) & 0x3fff); + if (retval) + return retval; + retval = ftdi_read_pcimem(ftdi, fminterval, &fminterval); + if (retval) + return retval; + retval = ftdi_read_pcimem(ftdi, periodicstart, &periodicstart); + if (retval) + return retval; + if (0 == (fminterval & 0x3fff0000) || 0 == periodicstart) { + if (!(quirk & OHCI_QUIRK_INITRESET)) { + quirk |= OHCI_QUIRK_INITRESET; + goto retry; + } else + dev_err(&ftdi->udev->dev, "init err(%08x %04x)\n", + fminterval, periodicstart); + } /* start controller operations */ + hc_control &= OHCI_CTRL_RWC; + hc_control |= OHCI_CONTROL_INIT | OHCI_CTRL_BLE | OHCI_USB_OPER; + retval = ftdi_write_pcimem(ftdi, control, hc_control); + if (retval) + return retval; + retval = ftdi_write_pcimem(ftdi, cmdstatus, OHCI_BLF); + if (retval) + return retval; + retval = ftdi_read_pcimem(ftdi, cmdstatus, &cmdstatus); + if (retval) + return retval; + retval = ftdi_read_pcimem(ftdi, control, &control); + if (retval) + return retval; + retval = ftdi_write_pcimem(ftdi, roothub.status, RH_HS_DRWE); + if (retval) + return retval; + retval = ftdi_write_pcimem(ftdi, intrstatus, mask); + if (retval) + return retval; + retval = ftdi_write_pcimem(ftdi, intrdisable, + OHCI_INTR_MIE | OHCI_INTR_OC | OHCI_INTR_RHSC | OHCI_INTR_FNO | + OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_SF | OHCI_INTR_WDH | + OHCI_INTR_SO); + if (retval) + return retval; /* handle root hub init quirks ... */ + retval = ftdi_read_pcimem(ftdi, roothub.a, &roothub_a); + if (retval) + return retval; + roothub_a &= ~(RH_A_PSM | RH_A_OCPM); + if (quirk & OHCI_QUIRK_SUPERIO) { + roothub_a |= RH_A_NOCP; + roothub_a &= ~(RH_A_POTPGT | RH_A_NPS); + retval = ftdi_write_pcimem(ftdi, roothub.a, roothub_a); + if (retval) + return retval; + } else if ((quirk & OHCI_QUIRK_AMD756) || distrust_firmware) { + roothub_a |= RH_A_NPS; + retval = ftdi_write_pcimem(ftdi, roothub.a, roothub_a); + if (retval) + return retval; + } + retval = ftdi_write_pcimem(ftdi, roothub.status, RH_HS_LPSC); + if (retval) + return retval; + retval = ftdi_write_pcimem(ftdi, roothub.b, + (roothub_a & RH_A_NPS) ? 0 : RH_B_PPCM); + if (retval) + return retval; + retval = ftdi_read_pcimem(ftdi, control, &control); + if (retval) + return retval; + mdelay((roothub_a >> 23) & 0x1fe); + for (temp = 0; temp < num_ports; temp++) { + u32 portstatus; + retval = ftdi_read_pcimem(ftdi, roothub.portstatus[temp], + &portstatus); + if (retval) + return retval; + if (1 & portstatus) + devices += 1; + } + return devices; } static int ftdi_elan_setup_controller(struct usb_ftdi *ftdi, int fn) { - u32 latence_timer; - int UxxxStatus; - u32 pcidata; - int reg = 0; - int activePCIfn = fn << 8; - UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x2800); - if (UxxxStatus) - return UxxxStatus; - reg = 16; - UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0, - 0xFFFFFFFF); - if (UxxxStatus) - return UxxxStatus; - UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, - &pcidata); - if (UxxxStatus) - return UxxxStatus; - UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0, - 0xF0000000); - if (UxxxStatus) - return UxxxStatus; - UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, - &pcidata); - if (UxxxStatus) - return UxxxStatus; - reg = 12; - UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, - &latence_timer); - if (UxxxStatus) - return UxxxStatus; - latence_timer &= 0xFFFF00FF; - latence_timer |= 0x00001600; - UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00, - latence_timer); - if (UxxxStatus) - return UxxxStatus; - UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, - &pcidata); - if (UxxxStatus) - return UxxxStatus; - reg = 4; - UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00, - 0x06); - if (UxxxStatus) - return UxxxStatus; - UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, - &pcidata); - if (UxxxStatus) - return UxxxStatus; - for (reg = 0; reg <= 0x54; reg += 4) { - UxxxStatus = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); - if (UxxxStatus) - return UxxxStatus; - } - return 0; + u32 latence_timer; + int UxxxStatus; + u32 pcidata; + int reg = 0; + int activePCIfn = fn << 8; + UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x2800); + if (UxxxStatus) + return UxxxStatus; + reg = 16; + UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0, + 0xFFFFFFFF); + if (UxxxStatus) + return UxxxStatus; + UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, + &pcidata); + if (UxxxStatus) + return UxxxStatus; + UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0, + 0xF0000000); + if (UxxxStatus) + return UxxxStatus; + UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, + &pcidata); + if (UxxxStatus) + return UxxxStatus; + reg = 12; + UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, + &latence_timer); + if (UxxxStatus) + return UxxxStatus; + latence_timer &= 0xFFFF00FF; + latence_timer |= 0x00001600; + UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00, + latence_timer); + if (UxxxStatus) + return UxxxStatus; + UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, + &pcidata); + if (UxxxStatus) + return UxxxStatus; + reg = 4; + UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00, + 0x06); + if (UxxxStatus) + return UxxxStatus; + UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, + &pcidata); + if (UxxxStatus) + return UxxxStatus; + for (reg = 0; reg <= 0x54; reg += 4) { + UxxxStatus = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); + if (UxxxStatus) + return UxxxStatus; + } + return 0; } static int ftdi_elan_close_controller(struct usb_ftdi *ftdi, int fn) { - u32 latence_timer; - int UxxxStatus; - u32 pcidata; - int reg = 0; - int activePCIfn = fn << 8; - UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x2800); - if (UxxxStatus) - return UxxxStatus; - reg = 16; - UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0, - 0xFFFFFFFF); - if (UxxxStatus) - return UxxxStatus; - UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, - &pcidata); - if (UxxxStatus) - return UxxxStatus; - UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0, - 0x00000000); - if (UxxxStatus) - return UxxxStatus; - UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, - &pcidata); - if (UxxxStatus) - return UxxxStatus; - reg = 12; - UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, - &latence_timer); - if (UxxxStatus) - return UxxxStatus; - latence_timer &= 0xFFFF00FF; - latence_timer |= 0x00001600; - UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00, - latence_timer); - if (UxxxStatus) - return UxxxStatus; - UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, - &pcidata); - if (UxxxStatus) - return UxxxStatus; - reg = 4; - UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00, - 0x00); - if (UxxxStatus) - return UxxxStatus; - UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, - &pcidata); - if (UxxxStatus) - return UxxxStatus; - return 0; + u32 latence_timer; + int UxxxStatus; + u32 pcidata; + int reg = 0; + int activePCIfn = fn << 8; + UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x2800); + if (UxxxStatus) + return UxxxStatus; + reg = 16; + UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0, + 0xFFFFFFFF); + if (UxxxStatus) + return UxxxStatus; + UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, + &pcidata); + if (UxxxStatus) + return UxxxStatus; + UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0, + 0x00000000); + if (UxxxStatus) + return UxxxStatus; + UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, + &pcidata); + if (UxxxStatus) + return UxxxStatus; + reg = 12; + UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, + &latence_timer); + if (UxxxStatus) + return UxxxStatus; + latence_timer &= 0xFFFF00FF; + latence_timer |= 0x00001600; + UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00, + latence_timer); + if (UxxxStatus) + return UxxxStatus; + UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, + &pcidata); + if (UxxxStatus) + return UxxxStatus; + reg = 4; + UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00, + 0x00); + if (UxxxStatus) + return UxxxStatus; + UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, + &pcidata); + if (UxxxStatus) + return UxxxStatus; + return 0; } static int ftdi_elan_found_controller(struct usb_ftdi *ftdi, int fn, int quirk) { - int result; - int UxxxStatus; - UxxxStatus = ftdi_elan_setup_controller(ftdi, fn); - if (UxxxStatus) - return UxxxStatus; - result = ftdi_elan_check_controller(ftdi, quirk); - UxxxStatus = ftdi_elan_close_controller(ftdi, fn); - if (UxxxStatus) - return UxxxStatus; - return result; + int result; + int UxxxStatus; + UxxxStatus = ftdi_elan_setup_controller(ftdi, fn); + if (UxxxStatus) + return UxxxStatus; + result = ftdi_elan_check_controller(ftdi, quirk); + UxxxStatus = ftdi_elan_close_controller(ftdi, fn); + if (UxxxStatus) + return UxxxStatus; + return result; } static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi) { - u32 controlreg; - u8 sensebits; - int UxxxStatus; - UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); - if (UxxxStatus) - return UxxxStatus; - UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000000L); - if (UxxxStatus) - return UxxxStatus; - msleep(750); - UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x100); - if (UxxxStatus) - return UxxxStatus; - UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x500); - if (UxxxStatus) - return UxxxStatus; - UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); - if (UxxxStatus) - return UxxxStatus; - UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020CL | 0x000); - if (UxxxStatus) - return UxxxStatus; - UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020DL | 0x000); - if (UxxxStatus) - return UxxxStatus; - msleep(250); - UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020FL | 0x000); - if (UxxxStatus) - return UxxxStatus; - UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); - if (UxxxStatus) - return UxxxStatus; - UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x800); - if (UxxxStatus) - return UxxxStatus; - UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); - if (UxxxStatus) - return UxxxStatus; - UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); - if (UxxxStatus) - return UxxxStatus; - msleep(1000); - sensebits = (controlreg >> 16) & 0x000F; - if (0x0D == sensebits) - return 0; - else + u32 controlreg; + u8 sensebits; + int UxxxStatus; + UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); + if (UxxxStatus) + return UxxxStatus; + UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000000L); + if (UxxxStatus) + return UxxxStatus; + msleep(750); + UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x100); + if (UxxxStatus) + return UxxxStatus; + UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x500); + if (UxxxStatus) + return UxxxStatus; + UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); + if (UxxxStatus) + return UxxxStatus; + UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020CL | 0x000); + if (UxxxStatus) + return UxxxStatus; + UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020DL | 0x000); + if (UxxxStatus) + return UxxxStatus; + msleep(250); + UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020FL | 0x000); + if (UxxxStatus) + return UxxxStatus; + UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); + if (UxxxStatus) + return UxxxStatus; + UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x800); + if (UxxxStatus) + return UxxxStatus; + UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); + if (UxxxStatus) + return UxxxStatus; + UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); + if (UxxxStatus) + return UxxxStatus; + msleep(1000); + sensebits = (controlreg >> 16) & 0x000F; + if (0x0D == sensebits) + return 0; + else return - ENXIO; } static int ftdi_elan_setupOHCI(struct usb_ftdi *ftdi) { - int UxxxStatus; - u32 pcidata; - int reg = 0; - u8 fn; - int activePCIfn = 0; - int max_devices = 0; - int controllers = 0; - int unrecognized = 0; - ftdi->function = 0; - for (fn = 0; (fn < 4); fn++) { - u32 pciVID = 0; - u32 pciPID = 0; - int devices = 0; - activePCIfn = fn << 8; - UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, - &pcidata); - if (UxxxStatus) - return UxxxStatus; - pciVID = pcidata & 0xFFFF; - pciPID = (pcidata >> 16) & 0xFFFF; - if ((pciVID == PCI_VENDOR_ID_OPTI) && (pciPID == 0xc861)) { - devices = ftdi_elan_found_controller(ftdi, fn, 0); - controllers += 1; - } else if ((pciVID == PCI_VENDOR_ID_NEC) && (pciPID == 0x0035)) - { - devices = ftdi_elan_found_controller(ftdi, fn, 0); - controllers += 1; - } else if ((pciVID == PCI_VENDOR_ID_AL) && (pciPID == 0x5237)) { - devices = ftdi_elan_found_controller(ftdi, fn, 0); - controllers += 1; - } else if ((pciVID == PCI_VENDOR_ID_ATT) && (pciPID == 0x5802)) - { - devices = ftdi_elan_found_controller(ftdi, fn, 0); - controllers += 1; - } else if (pciVID == PCI_VENDOR_ID_AMD && pciPID == 0x740c) { - devices = ftdi_elan_found_controller(ftdi, fn, - OHCI_QUIRK_AMD756); - controllers += 1; - } else if (pciVID == PCI_VENDOR_ID_COMPAQ && pciPID == 0xa0f8) { - devices = ftdi_elan_found_controller(ftdi, fn, - OHCI_QUIRK_ZFMICRO); - controllers += 1; - } else if (0 == pcidata) { - } else - unrecognized += 1; - if (devices > max_devices) { - max_devices = devices; - ftdi->function = fn + 1; - ftdi->platform_data.vendor = pciVID; - ftdi->platform_data.device = pciPID; - } - } - if (ftdi->function > 0) { - UxxxStatus = ftdi_elan_setup_controller(ftdi, - ftdi->function - 1); - if (UxxxStatus) - return UxxxStatus; - return 0; - } else if (controllers > 0) { - return -ENXIO; - } else if (unrecognized > 0) { - return -ENXIO; - } else { - ftdi->enumerated = 0; - return -ENXIO; - } + int UxxxStatus; + u32 pcidata; + int reg = 0; + u8 fn; + int activePCIfn = 0; + int max_devices = 0; + int controllers = 0; + int unrecognized = 0; + ftdi->function = 0; + for (fn = 0; (fn < 4); fn++) { + u32 pciVID = 0; + u32 pciPID = 0; + int devices = 0; + activePCIfn = fn << 8; + UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, + &pcidata); + if (UxxxStatus) + return UxxxStatus; + pciVID = pcidata & 0xFFFF; + pciPID = (pcidata >> 16) & 0xFFFF; + if ((pciVID == PCI_VENDOR_ID_OPTI) && (pciPID == 0xc861)) { + devices = ftdi_elan_found_controller(ftdi, fn, 0); + controllers += 1; + } else if ((pciVID == PCI_VENDOR_ID_NEC) && (pciPID == 0x0035)) + { + devices = ftdi_elan_found_controller(ftdi, fn, 0); + controllers += 1; + } else if ((pciVID == PCI_VENDOR_ID_AL) && (pciPID == 0x5237)) { + devices = ftdi_elan_found_controller(ftdi, fn, 0); + controllers += 1; + } else if ((pciVID == PCI_VENDOR_ID_ATT) && (pciPID == 0x5802)) + { + devices = ftdi_elan_found_controller(ftdi, fn, 0); + controllers += 1; + } else if (pciVID == PCI_VENDOR_ID_AMD && pciPID == 0x740c) { + devices = ftdi_elan_found_controller(ftdi, fn, + OHCI_QUIRK_AMD756); + controllers += 1; + } else if (pciVID == PCI_VENDOR_ID_COMPAQ && pciPID == 0xa0f8) { + devices = ftdi_elan_found_controller(ftdi, fn, + OHCI_QUIRK_ZFMICRO); + controllers += 1; + } else if (0 == pcidata) { + } else + unrecognized += 1; + if (devices > max_devices) { + max_devices = devices; + ftdi->function = fn + 1; + ftdi->platform_data.vendor = pciVID; + ftdi->platform_data.device = pciPID; + } + } + if (ftdi->function > 0) { + UxxxStatus = ftdi_elan_setup_controller(ftdi, + ftdi->function - 1); + if (UxxxStatus) + return UxxxStatus; + return 0; + } else if (controllers > 0) { + return -ENXIO; + } else if (unrecognized > 0) { + return -ENXIO; + } else { + ftdi->enumerated = 0; + return -ENXIO; + } } /* -* we use only the first bulk-in and bulk-out endpoints -*/ + * we use only the first bulk-in and bulk-out endpoints + */ static int ftdi_elan_probe(struct usb_interface *interface, - const struct usb_device_id *id) + const struct usb_device_id *id) { - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; - size_t buffer_size; - int i; - int retval = -ENOMEM; - struct usb_ftdi *ftdi; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + size_t buffer_size; + int i; + int retval = -ENOMEM; + struct usb_ftdi *ftdi; ftdi = kzalloc(sizeof(struct usb_ftdi), GFP_KERNEL); - if (!ftdi) { - printk(KERN_ERR "Out of memory\n"); - return -ENOMEM; - } - - mutex_lock(&ftdi_module_lock); - list_add_tail(&ftdi->ftdi_list, &ftdi_static_list); - ftdi->sequence_num = ++ftdi_instances; - mutex_unlock(&ftdi_module_lock); - ftdi_elan_init_kref(ftdi); - init_MUTEX(&ftdi->sw_lock); - ftdi->udev = usb_get_dev(interface_to_usbdev(interface)); - ftdi->interface = interface; - mutex_init(&ftdi->u132_lock); - ftdi->expected = 4; - iface_desc = interface->cur_altsetting; - for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { - endpoint = &iface_desc->endpoint[i].desc; - if (!ftdi->bulk_in_endpointAddr && + if (!ftdi) + return -ENOMEM; + + mutex_lock(&ftdi_module_lock); + list_add_tail(&ftdi->ftdi_list, &ftdi_static_list); + ftdi->sequence_num = ++ftdi_instances; + mutex_unlock(&ftdi_module_lock); + ftdi_elan_init_kref(ftdi); + sema_init(&ftdi->sw_lock, 1); + ftdi->udev = usb_get_dev(interface_to_usbdev(interface)); + ftdi->interface = interface; + mutex_init(&ftdi->u132_lock); + ftdi->expected = 4; + iface_desc = interface->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + if (!ftdi->bulk_in_endpointAddr && usb_endpoint_is_bulk_in(endpoint)) { - buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); - ftdi->bulk_in_size = buffer_size; - ftdi->bulk_in_endpointAddr = endpoint->bEndpointAddress; - ftdi->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); - if (!ftdi->bulk_in_buffer) { - dev_err(&ftdi->udev->dev, "Could not allocate b" - "ulk_in_buffer\n"); - retval = -ENOMEM; - goto error; - } - } - if (!ftdi->bulk_out_endpointAddr && + buffer_size = usb_endpoint_maxp(endpoint); + ftdi->bulk_in_size = buffer_size; + ftdi->bulk_in_endpointAddr = endpoint->bEndpointAddress; + ftdi->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); + if (!ftdi->bulk_in_buffer) { + dev_err(&ftdi->udev->dev, "Could not allocate bulk_in_buffer\n"); + retval = -ENOMEM; + goto error; + } + } + if (!ftdi->bulk_out_endpointAddr && usb_endpoint_is_bulk_out(endpoint)) { - ftdi->bulk_out_endpointAddr = - endpoint->bEndpointAddress; - } - } - if (!(ftdi->bulk_in_endpointAddr && ftdi->bulk_out_endpointAddr)) { - dev_err(&ftdi->udev->dev, "Could not find both bulk-in and bulk" - "-out endpoints\n"); - retval = -ENODEV; - goto error; - } - dev_info(&ftdi->udev->dev, "interface %d has I=%02X O=%02X\n", - iface_desc->desc.bInterfaceNumber, ftdi->bulk_in_endpointAddr, - ftdi->bulk_out_endpointAddr); - usb_set_intfdata(interface, ftdi); - if (iface_desc->desc.bInterfaceNumber == 0 && - ftdi->bulk_in_endpointAddr == 0x81 && - ftdi->bulk_out_endpointAddr == 0x02) { - retval = usb_register_dev(interface, &ftdi_elan_jtag_class); - if (retval) { - dev_err(&ftdi->udev->dev, "Not able to get a minor for " - "this device.\n"); - usb_set_intfdata(interface, NULL); - retval = -ENOMEM; - goto error; - } else { - ftdi->class = &ftdi_elan_jtag_class; - dev_info(&ftdi->udev->dev, "USB FDTI=%p JTAG interface " - "%d now attached to ftdi%d\n", ftdi, - iface_desc->desc.bInterfaceNumber, - interface->minor); - return 0; - } - } else if (iface_desc->desc.bInterfaceNumber == 1 && - ftdi->bulk_in_endpointAddr == 0x83 && - ftdi->bulk_out_endpointAddr == 0x04) { - ftdi->class = NULL; - dev_info(&ftdi->udev->dev, "USB FDTI=%p ELAN interface %d now a" - "ctivated\n", ftdi, iface_desc->desc.bInterfaceNumber); - INIT_DELAYED_WORK(&ftdi->status_work, ftdi_elan_status_work); - INIT_DELAYED_WORK(&ftdi->command_work, ftdi_elan_command_work); - INIT_DELAYED_WORK(&ftdi->respond_work, ftdi_elan_respond_work); - ftdi_status_queue_work(ftdi, msecs_to_jiffies(3 *1000)); - return 0; - } else { - dev_err(&ftdi->udev->dev, - "Could not find ELAN's U132 device\n"); - retval = -ENODEV; - goto error; - } - error:if (ftdi) { - ftdi_elan_put_kref(ftdi); - } - return retval; + ftdi->bulk_out_endpointAddr = + endpoint->bEndpointAddress; + } + } + if (!(ftdi->bulk_in_endpointAddr && ftdi->bulk_out_endpointAddr)) { + dev_err(&ftdi->udev->dev, "Could not find both bulk-in and bulk-out endpoints\n"); + retval = -ENODEV; + goto error; + } + dev_info(&ftdi->udev->dev, "interface %d has I=%02X O=%02X\n", + iface_desc->desc.bInterfaceNumber, ftdi->bulk_in_endpointAddr, + ftdi->bulk_out_endpointAddr); + usb_set_intfdata(interface, ftdi); + if (iface_desc->desc.bInterfaceNumber == 0 && + ftdi->bulk_in_endpointAddr == 0x81 && + ftdi->bulk_out_endpointAddr == 0x02) { + retval = usb_register_dev(interface, &ftdi_elan_jtag_class); + if (retval) { + dev_err(&ftdi->udev->dev, "Not able to get a minor for this device\n"); + usb_set_intfdata(interface, NULL); + retval = -ENOMEM; + goto error; + } else { + ftdi->class = &ftdi_elan_jtag_class; + dev_info(&ftdi->udev->dev, "USB FDTI=%p JTAG interface %d now attached to ftdi%d\n", + ftdi, iface_desc->desc.bInterfaceNumber, + interface->minor); + return 0; + } + } else if (iface_desc->desc.bInterfaceNumber == 1 && + ftdi->bulk_in_endpointAddr == 0x83 && + ftdi->bulk_out_endpointAddr == 0x04) { + ftdi->class = NULL; + dev_info(&ftdi->udev->dev, "USB FDTI=%p ELAN interface %d now activated\n", + ftdi, iface_desc->desc.bInterfaceNumber); + INIT_DELAYED_WORK(&ftdi->status_work, ftdi_elan_status_work); + INIT_DELAYED_WORK(&ftdi->command_work, ftdi_elan_command_work); + INIT_DELAYED_WORK(&ftdi->respond_work, ftdi_elan_respond_work); + ftdi_status_queue_work(ftdi, msecs_to_jiffies(3 *1000)); + return 0; + } else { + dev_err(&ftdi->udev->dev, + "Could not find ELAN's U132 device\n"); + retval = -ENODEV; + goto error; + } +error:if (ftdi) { + ftdi_elan_put_kref(ftdi); + } + return retval; } static void ftdi_elan_disconnect(struct usb_interface *interface) { - struct usb_ftdi *ftdi = usb_get_intfdata(interface); - ftdi->disconnected += 1; - if (ftdi->class) { - int minor = interface->minor; - struct usb_class_driver *class = ftdi->class; - usb_set_intfdata(interface, NULL); - usb_deregister_dev(interface, class); - dev_info(&ftdi->udev->dev, "USB FTDI U132 jtag interface on min" - "or %d now disconnected\n", minor); - } else { - ftdi_status_cancel_work(ftdi); - ftdi_command_cancel_work(ftdi); - ftdi_response_cancel_work(ftdi); - ftdi_elan_abandon_completions(ftdi); - ftdi_elan_abandon_targets(ftdi); - if (ftdi->registered) { - platform_device_unregister(&ftdi->platform_dev); - ftdi->synchronized = 0; - ftdi->enumerated = 0; - ftdi->initialized = 0; - ftdi->registered = 0; - } - flush_workqueue(status_queue); - flush_workqueue(command_queue); - flush_workqueue(respond_queue); - ftdi->disconnected += 1; - usb_set_intfdata(interface, NULL); - dev_info(&ftdi->udev->dev, "USB FTDI U132 host controller inter" - "face now disconnected\n"); - } - ftdi_elan_put_kref(ftdi); + struct usb_ftdi *ftdi = usb_get_intfdata(interface); + ftdi->disconnected += 1; + if (ftdi->class) { + int minor = interface->minor; + struct usb_class_driver *class = ftdi->class; + usb_set_intfdata(interface, NULL); + usb_deregister_dev(interface, class); + dev_info(&ftdi->udev->dev, "USB FTDI U132 jtag interface on minor %d now disconnected\n", + minor); + } else { + ftdi_status_cancel_work(ftdi); + ftdi_command_cancel_work(ftdi); + ftdi_response_cancel_work(ftdi); + ftdi_elan_abandon_completions(ftdi); + ftdi_elan_abandon_targets(ftdi); + if (ftdi->registered) { + platform_device_unregister(&ftdi->platform_dev); + ftdi->synchronized = 0; + ftdi->enumerated = 0; + ftdi->initialized = 0; + ftdi->registered = 0; + } + flush_workqueue(status_queue); + flush_workqueue(command_queue); + flush_workqueue(respond_queue); + ftdi->disconnected += 1; + usb_set_intfdata(interface, NULL); + dev_info(&ftdi->udev->dev, "USB FTDI U132 host controller interface now disconnected\n"); + } + ftdi_elan_put_kref(ftdi); } static struct usb_driver ftdi_elan_driver = { - .name = "ftdi-elan", - .probe = ftdi_elan_probe, - .disconnect = ftdi_elan_disconnect, - .id_table = ftdi_elan_table, + .name = "ftdi-elan", + .probe = ftdi_elan_probe, + .disconnect = ftdi_elan_disconnect, + .id_table = ftdi_elan_table, }; static int __init ftdi_elan_init(void) { - int result; - printk(KERN_INFO "driver %s built at %s on %s\n", ftdi_elan_driver.name, - __TIME__, __DATE__); - mutex_init(&ftdi_module_lock); - INIT_LIST_HEAD(&ftdi_static_list); - status_queue = create_singlethread_workqueue("ftdi-status-control"); + int result; + pr_info("driver %s\n", ftdi_elan_driver.name); + mutex_init(&ftdi_module_lock); + INIT_LIST_HEAD(&ftdi_static_list); + status_queue = create_singlethread_workqueue("ftdi-status-control"); if (!status_queue) goto err_status_queue; - command_queue = create_singlethread_workqueue("ftdi-command-engine"); + command_queue = create_singlethread_workqueue("ftdi-command-engine"); if (!command_queue) goto err_command_queue; - respond_queue = create_singlethread_workqueue("ftdi-respond-engine"); + respond_queue = create_singlethread_workqueue("ftdi-respond-engine"); if (!respond_queue) goto err_respond_queue; - result = usb_register(&ftdi_elan_driver); - if (result) { + result = usb_register(&ftdi_elan_driver); + if (result) { destroy_workqueue(status_queue); destroy_workqueue(command_queue); destroy_workqueue(respond_queue); - printk(KERN_ERR "usb_register failed. Error number %d\n", - result); + pr_err("usb_register failed. Error number %d\n", result); } - return result; + return result; - err_respond_queue: +err_respond_queue: destroy_workqueue(command_queue); - err_command_queue: +err_command_queue: destroy_workqueue(status_queue); - err_status_queue: - printk(KERN_ERR "%s couldn't create workqueue\n", ftdi_elan_driver.name); +err_status_queue: + pr_err("%s couldn't create workqueue\n", ftdi_elan_driver.name); return -ENOMEM; } static void __exit ftdi_elan_exit(void) { - struct usb_ftdi *ftdi; - struct usb_ftdi *temp; - usb_deregister(&ftdi_elan_driver); - printk(KERN_INFO "ftdi_u132 driver deregistered\n"); - list_for_each_entry_safe(ftdi, temp, &ftdi_static_list, ftdi_list) { - ftdi_status_cancel_work(ftdi); - ftdi_command_cancel_work(ftdi); - ftdi_response_cancel_work(ftdi); - } flush_workqueue(status_queue); - destroy_workqueue(status_queue); - status_queue = NULL; - flush_workqueue(command_queue); - destroy_workqueue(command_queue); - command_queue = NULL; - flush_workqueue(respond_queue); - destroy_workqueue(respond_queue); - respond_queue = NULL; + struct usb_ftdi *ftdi; + struct usb_ftdi *temp; + usb_deregister(&ftdi_elan_driver); + pr_info("ftdi_u132 driver deregistered\n"); + list_for_each_entry_safe(ftdi, temp, &ftdi_static_list, ftdi_list) { + ftdi_status_cancel_work(ftdi); + ftdi_command_cancel_work(ftdi); + ftdi_response_cancel_work(ftdi); + } flush_workqueue(status_queue); + destroy_workqueue(status_queue); + status_queue = NULL; + flush_workqueue(command_queue); + destroy_workqueue(command_queue); + command_queue = NULL; + flush_workqueue(respond_queue); + destroy_workqueue(respond_queue); + respond_queue = NULL; } diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c index 1337a9ce80b..4e38683c653 100644 --- a/drivers/usb/misc/idmouse.c +++ b/drivers/usb/misc/idmouse.c @@ -19,7 +19,6 @@ #include <linux/kernel.h> #include <linux/errno.h> #include <linux/delay.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/completion.h> @@ -48,7 +47,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 */ @@ -105,6 +104,7 @@ static const struct file_operations idmouse_fops = { .read = idmouse_read, .open = idmouse_open, .release = idmouse_release, + .llseek = default_llseek, }; /* class driver information */ @@ -199,7 +199,8 @@ reset: return -EAGAIN; /* should be IMGSIZE == 65040 */ - dbg("read %d bytes fingerprint data", bytes_read); + dev_dbg(&dev->interface->dev, "read %d bytes fingerprint data\n", + bytes_read); return result; } @@ -358,21 +359,21 @@ static int idmouse_probe(struct usb_interface *interface, endpoint = &iface_desc->endpoint[0].desc; if (!dev->bulk_in_endpointAddr && usb_endpoint_is_bulk_in(endpoint)) { /* we found a bulk in endpoint */ - dev->orig_bi_size = le16_to_cpu(endpoint->wMaxPacketSize); + dev->orig_bi_size = usb_endpoint_maxp(endpoint); dev->bulk_in_size = 0x200; /* works _much_ faster */ dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; dev->bulk_in_buffer = kmalloc(IMGSIZE + dev->bulk_in_size, GFP_KERNEL); if (!dev->bulk_in_buffer) { - err("Unable to allocate input buffer."); + dev_err(&interface->dev, "Unable to allocate input buffer.\n"); idmouse_delete(dev); return -ENOMEM; } } if (!(dev->bulk_in_endpointAddr)) { - err("Unable to find bulk-in endpoint."); + dev_err(&interface->dev, "Unable to find bulk-in endpoint.\n"); idmouse_delete(dev); return -ENODEV; } @@ -384,7 +385,7 @@ static int idmouse_probe(struct usb_interface *interface, result = usb_register_dev(interface, &idmouse_class); if (result) { /* something prevented us from registering this device */ - err("Unble to allocate minor number."); + dev_err(&interface->dev, "Unable to allocate minor number.\n"); usb_set_intfdata(interface, NULL); idmouse_delete(dev); return result; @@ -427,29 +428,7 @@ static void idmouse_disconnect(struct usb_interface *interface) dev_info(&interface->dev, "disconnected\n"); } -static int __init usb_idmouse_init(void) -{ - int result; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - /* register this driver with the USB subsystem */ - result = usb_register(&idmouse_driver); - if (result) - err("Unable to register device (error %d).", result); - - return result; -} - -static void __exit usb_idmouse_exit(void) -{ - /* deregister this driver with the USB subsystem */ - usb_deregister(&idmouse_driver); -} - -module_init(usb_idmouse_init); -module_exit(usb_idmouse_exit); +module_usb_driver(idmouse_driver); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index e75bb87ee92..c6bfd13f6c9 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -15,10 +15,9 @@ #include <linux/module.h> #include <linux/usb.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/sched.h> -#include <linux/smp_lock.h> +#include <linux/mutex.h> #include <linux/poll.h> #include <linux/usb/iowarrior.h> @@ -40,7 +39,7 @@ #ifdef CONFIG_USB_DYNAMIC_MINORS #define IOWARRIOR_MINOR_BASE 0 #else -#define IOWARRIOR_MINOR_BASE 208 // SKELETON_MINOR_BASE 192 + 16, not offical yet +#define IOWARRIOR_MINOR_BASE 208 // SKELETON_MINOR_BASE 192 + 16, not official yet #endif /* interrupt input queue size */ @@ -52,18 +51,12 @@ */ #define MAX_WRITES_IN_FLIGHT 4 -/* Use our own dbg macro */ -#undef dbg -#define dbg( format, arg... ) do { if( debug ) printk( KERN_DEBUG __FILE__ ": " format "\n" , ## arg ); } while ( 0 ) - MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); /* Module parameters */ -static int debug = 0; -module_param(debug, bool, 0644); -MODULE_PARM_DESC(debug, "debug=1 enables debugging messages"); +static DEFINE_MUTEX(iowarrior_mutex); static struct usb_driver iowarrior_driver; static DEFINE_MUTEX(iowarrior_open_disc_lock); @@ -139,7 +132,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)}, @@ -235,12 +228,12 @@ static void iowarrior_write_callback(struct urb *urb) if (status && !(status == -ENOENT || status == -ECONNRESET || status == -ESHUTDOWN)) { - dbg("%s - nonzero write bulk status received: %d", - __func__, status); + dev_dbg(&dev->interface->dev, + "nonzero write bulk status received: %d\n", status); } /* free up our allocated buffer */ - usb_buffer_free(urb->dev, urb->transfer_buffer_length, - urb->transfer_buffer, urb->transfer_dma); + usb_free_coherent(urb->dev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); /* tell a waiting writer the interrupt-out-pipe is available again */ atomic_dec(&dev->write_busy); wake_up_interruptible(&dev->write_wait); @@ -251,7 +244,7 @@ static void iowarrior_write_callback(struct urb *urb) */ static inline void iowarrior_delete(struct iowarrior *dev) { - dbg("%s - minor %d", __func__, dev->minor); + dev_dbg(&dev->interface->dev, "minor %d\n", dev->minor); kfree(dev->int_in_buffer); usb_free_urb(dev->int_in_urb); kfree(dev->read_queue); @@ -282,13 +275,14 @@ static ssize_t iowarrior_read(struct file *file, char __user *buffer, int read_idx; int offset; - dev = (struct iowarrior *)file->private_data; + dev = file->private_data; /* verify that the device wasn't unplugged */ if (dev == NULL || !dev->present) return -ENODEV; - dbg("%s - minor %d, count = %zd", __func__, dev->minor, count); + dev_dbg(&dev->interface->dev, "minor %d, count = %zd\n", + dev->minor, count); /* read count must be packet size (+ time stamp) */ if ((count != dev->report_size) @@ -299,7 +293,7 @@ static ssize_t iowarrior_read(struct file *file, char __user *buffer, do { atomic_set(&dev->overflow_flag, 0); if ((read_idx = read_index(dev)) == -1) { - /* queue emty */ + /* queue empty */ if (file->f_flags & O_NONBLOCK) return -EAGAIN; else { @@ -348,7 +342,7 @@ static ssize_t iowarrior_write(struct file *file, char *buf = NULL; /* for IOW24 and IOW56 we need a buffer */ struct urb *int_out_urb = NULL; - dev = (struct iowarrior *)file->private_data; + dev = file->private_data; mutex_lock(&dev->mutex); /* verify that the device wasn't unplugged */ @@ -356,7 +350,8 @@ static ssize_t iowarrior_write(struct file *file, retval = -ENODEV; goto exit; } - dbg("%s - minor %d, count = %zd", __func__, dev->minor, count); + dev_dbg(&dev->interface->dev, "minor %d, count = %zd\n", + dev->minor, count); /* if count is 0 we're already done */ if (count == 0) { retval = 0; @@ -373,7 +368,7 @@ static ssize_t iowarrior_write(struct file *file, case USB_DEVICE_ID_CODEMERCS_IOWPV2: case USB_DEVICE_ID_CODEMERCS_IOW40: /* IOW24 and IOW40 use a synchronous call */ - buf = kmalloc(8, GFP_KERNEL); /* 8 bytes are enough for both products */ + buf = kmalloc(count, GFP_KERNEL); if (!buf) { retval = -ENOMEM; goto exit; @@ -418,14 +413,16 @@ static ssize_t iowarrior_write(struct file *file, int_out_urb = usb_alloc_urb(0, GFP_KERNEL); if (!int_out_urb) { retval = -ENOMEM; - dbg("%s Unable to allocate urb ", __func__); + dev_dbg(&dev->interface->dev, + "Unable to allocate urb\n"); goto error_no_urb; } - buf = usb_buffer_alloc(dev->udev, dev->report_size, - GFP_KERNEL, &int_out_urb->transfer_dma); + buf = usb_alloc_coherent(dev->udev, dev->report_size, + GFP_KERNEL, &int_out_urb->transfer_dma); if (!buf) { retval = -ENOMEM; - dbg("%s Unable to allocate buffer ", __func__); + dev_dbg(&dev->interface->dev, + "Unable to allocate buffer\n"); goto error_no_buffer; } usb_fill_int_urb(int_out_urb, dev->udev, @@ -441,8 +438,9 @@ static ssize_t iowarrior_write(struct file *file, } retval = usb_submit_urb(int_out_urb, GFP_KERNEL); if (retval) { - dbg("%s submit error %d for urb nr.%d", __func__, - retval, atomic_read(&dev->write_busy)); + dev_dbg(&dev->interface->dev, + "submit error %d for urb nr.%d\n", + retval, atomic_read(&dev->write_busy)); goto error; } /* submit was ok */ @@ -459,8 +457,8 @@ static ssize_t iowarrior_write(struct file *file, break; } error: - usb_buffer_free(dev->udev, dev->report_size, buf, - int_out_urb->transfer_dma); + usb_free_coherent(dev->udev, dev->report_size, buf, + int_out_urb->transfer_dma); error_no_buffer: usb_free_urb(int_out_urb); error_no_urb: @@ -483,7 +481,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd, int retval; int io_res; /* checks for bytes read/written and copy_to/from_user results */ - dev = (struct iowarrior *)file->private_data; + dev = file->private_data; if (dev == NULL) { return -ENODEV; } @@ -493,7 +491,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd, return -ENOMEM; /* lock this object */ - lock_kernel(); + mutex_lock(&iowarrior_mutex); mutex_lock(&dev->mutex); /* verify that the device wasn't unplugged */ @@ -502,8 +500,8 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd, goto error_out; } - dbg("%s - minor %d, cmd 0x%.4x, arg %ld", __func__, dev->minor, cmd, - arg); + dev_dbg(&dev->interface->dev, "minor %d, cmd 0x%.4x, arg %ld\n", + dev->minor, cmd, arg); retval = 0; io_res = 0; @@ -541,7 +539,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd, retval = io_res; else { io_res = copy_to_user(user_buffer, buffer, dev->report_size); - if (io_res < 0) + if (io_res) retval = -EFAULT; } break; @@ -552,6 +550,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd, /* needed for power consumption */ struct usb_config_descriptor *cfg_descriptor = &dev->udev->actconfig->desc; + memset(&info, 0, sizeof(info)); /* directly from the descriptor */ info.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); info.product = dev->product_id; @@ -573,7 +572,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd, } io_res = copy_to_user((struct iowarrior_info __user *)arg, &info, sizeof(struct iowarrior_info)); - if (io_res < 0) + if (io_res) retval = -EFAULT; break; } @@ -585,7 +584,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd, error_out: /* unlock the device */ mutex_unlock(&dev->mutex); - unlock_kernel(); + mutex_unlock(&iowarrior_mutex); kfree(buffer); return retval; } @@ -600,14 +599,14 @@ static int iowarrior_open(struct inode *inode, struct file *file) int subminor; int retval = 0; - dbg("%s", __func__); - + mutex_lock(&iowarrior_mutex); subminor = iminor(inode); interface = usb_find_interface(&iowarrior_driver, subminor); if (!interface) { - err("%s - error, can't find device for minor %d", __func__, - subminor); + mutex_unlock(&iowarrior_mutex); + printk(KERN_ERR "%s - error, can't find device for minor %d\n", + __func__, subminor); return -ENODEV; } @@ -615,6 +614,7 @@ static int iowarrior_open(struct inode *inode, struct file *file) dev = usb_get_intfdata(interface); if (!dev) { mutex_unlock(&iowarrior_open_disc_lock); + mutex_unlock(&iowarrior_mutex); return -ENODEV; } @@ -641,6 +641,7 @@ static int iowarrior_open(struct inode *inode, struct file *file) out: mutex_unlock(&dev->mutex); + mutex_unlock(&iowarrior_mutex); return retval; } @@ -652,12 +653,12 @@ static int iowarrior_release(struct inode *inode, struct file *file) struct iowarrior *dev; int retval = 0; - dev = (struct iowarrior *)file->private_data; + dev = file->private_data; if (dev == NULL) { return -ENODEV; } - dbg("%s - minor %d", __func__, dev->minor); + dev_dbg(&dev->interface->dev, "minor %d\n", dev->minor); /* lock our device */ mutex_lock(&dev->mutex); @@ -666,7 +667,7 @@ static int iowarrior_release(struct inode *inode, struct file *file) retval = -ENODEV; /* close called more than once */ mutex_unlock(&dev->mutex); } else { - dev->opened = 0; /* we're closeing now */ + dev->opened = 0; /* we're closing now */ retval = 0; if (dev->present) { /* @@ -725,9 +726,10 @@ static const struct file_operations iowarrior_fops = { .open = iowarrior_open, .release = iowarrior_release, .poll = iowarrior_poll, + .llseek = noop_llseek, }; -static char *iowarrior_devnode(struct device *dev, mode_t *mode) +static char *iowarrior_devnode(struct device *dev, umode_t *mode) { return kasprintf(GFP_KERNEL, "usb/%s", dev_name(dev)); } @@ -762,7 +764,7 @@ static int iowarrior_probe(struct usb_interface *interface, int i; int retval = -ENOMEM; - /* allocate memory for our device state and intialize it */ + /* allocate memory for our device state and initialize it */ dev = kzalloc(sizeof(struct iowarrior), GFP_KERNEL); if (dev == NULL) { dev_err(&interface->dev, "Out of memory\n"); @@ -795,8 +797,8 @@ static int iowarrior_probe(struct usb_interface *interface, /* this one will match for the IOWarrior56 only */ dev->int_out_endpoint = endpoint; } - /* we have to check the report_size often, so remember it in the endianess suitable for our machine */ - dev->report_size = le16_to_cpu(dev->int_in_endpoint->wMaxPacketSize); + /* we have to check the report_size often, so remember it in the endianness suitable for our machine */ + dev->report_size = usb_endpoint_maxp(dev->int_in_endpoint); if ((dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) && (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56)) /* IOWarrior56 has wMaxPacketSize different from report size */ @@ -920,15 +922,4 @@ static struct usb_driver iowarrior_driver = { .id_table = iowarrior_ids, }; -static int __init iowarrior_init(void) -{ - return usb_register(&iowarrior_driver); -} - -static void __exit iowarrior_exit(void) -{ - usb_deregister(&iowarrior_driver); -} - -module_init(iowarrior_init); -module_exit(iowarrior_exit); +module_usb_driver(iowarrior_driver); diff --git a/drivers/usb/misc/isight_firmware.c b/drivers/usb/misc/isight_firmware.c index b897f6554ec..1c61830e96f 100644 --- a/drivers/usb/misc/isight_firmware.c +++ b/drivers/usb/misc/isight_firmware.c @@ -25,8 +25,9 @@ #include <linux/firmware.h> #include <linux/errno.h> #include <linux/module.h> +#include <linux/slab.h> -static struct usb_device_id id_table[] = { +static const struct usb_device_id id_table[] = { {USB_DEVICE(0x05ac, 0x8300)}, {}, }; @@ -54,8 +55,9 @@ static int isight_firmware_load(struct usb_interface *intf, ptr = firmware->data; + buf[0] = 0x01; if (usb_control_msg - (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\1", 1, + (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, buf, 1, 300) != 1) { printk(KERN_ERR "Failed to initialise isight firmware loader\n"); @@ -99,8 +101,9 @@ static int isight_firmware_load(struct usb_interface *intf, } } + buf[0] = 0x00; if (usb_control_msg - (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\0", 1, + (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, buf, 1, 300) != 1) { printk(KERN_ERR "isight firmware loading completion failed\n"); ret = -ENODEV; @@ -112,6 +115,8 @@ out: return ret; } +MODULE_FIRMWARE("isight.fw"); + static void isight_firmware_disconnect(struct usb_interface *intf) { } @@ -123,18 +128,7 @@ static struct usb_driver isight_firmware_driver = { .id_table = id_table, }; -static int __init isight_firmware_init(void) -{ - return usb_register(&isight_firmware_driver); -} - -static void __exit isight_firmware_exit(void) -{ - usb_deregister(&isight_firmware_driver); -} - -module_init(isight_firmware_init); -module_exit(isight_firmware_exit); +module_usb_driver(isight_firmware_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>"); diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index 90f130126c1..82503a7ff6c 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -20,16 +20,10 @@ * Derived from Lego USB Tower driver * Copyright (C) 2003 David Glance <advidgsf@sourceforge.net> * 2001-2004 Juergen Stuber <starblue@users.sourceforge.net> - * - * V0.1 (mh) Initial version - * V0.11 (mh) Added raw support for HID 1.0 devices (no interrupt out endpoint) - * V0.12 (mh) Added kmalloc check for string buffer - * V0.13 (mh) Added support for LD X-Ray and Machine Test System */ #include <linux/kernel.h> #include <linux/errno.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/mutex.h> @@ -41,20 +35,39 @@ /* Define these values to match your devices */ #define USB_VENDOR_ID_LD 0x0f11 /* USB Vendor ID of LD Didactic GmbH */ -#define USB_DEVICE_ID_LD_CASSY 0x1000 /* USB Product ID of CASSY-S */ +#define USB_DEVICE_ID_LD_CASSY 0x1000 /* USB Product ID of CASSY-S modules with 8 bytes endpoint size */ +#define USB_DEVICE_ID_LD_CASSY2 0x1001 /* USB Product ID of CASSY-S modules with 64 bytes endpoint size */ #define USB_DEVICE_ID_LD_POCKETCASSY 0x1010 /* USB Product ID of Pocket-CASSY */ +#define USB_DEVICE_ID_LD_POCKETCASSY2 0x1011 /* USB Product ID of Pocket-CASSY 2 (reserved) */ #define USB_DEVICE_ID_LD_MOBILECASSY 0x1020 /* USB Product ID of Mobile-CASSY */ +#define USB_DEVICE_ID_LD_MOBILECASSY2 0x1021 /* USB Product ID of Mobile-CASSY 2 (reserved) */ +#define USB_DEVICE_ID_LD_MICROCASSYVOLTAGE 0x1031 /* USB Product ID of Micro-CASSY Voltage */ +#define USB_DEVICE_ID_LD_MICROCASSYCURRENT 0x1032 /* USB Product ID of Micro-CASSY Current */ +#define USB_DEVICE_ID_LD_MICROCASSYTIME 0x1033 /* USB Product ID of Micro-CASSY Time (reserved) */ +#define USB_DEVICE_ID_LD_MICROCASSYTEMPERATURE 0x1035 /* USB Product ID of Micro-CASSY Temperature */ +#define USB_DEVICE_ID_LD_MICROCASSYPH 0x1038 /* USB Product ID of Micro-CASSY pH */ #define USB_DEVICE_ID_LD_JWM 0x1080 /* USB Product ID of Joule and Wattmeter */ #define USB_DEVICE_ID_LD_DMMP 0x1081 /* USB Product ID of Digital Multimeter P (reserved) */ #define USB_DEVICE_ID_LD_UMIP 0x1090 /* USB Product ID of UMI P */ -#define USB_DEVICE_ID_LD_XRAY1 0x1100 /* USB Product ID of X-Ray Apparatus */ -#define USB_DEVICE_ID_LD_XRAY2 0x1101 /* USB Product ID of X-Ray Apparatus */ +#define USB_DEVICE_ID_LD_UMIC 0x10A0 /* USB Product ID of UMI C */ +#define USB_DEVICE_ID_LD_UMIB 0x10B0 /* USB Product ID of UMI B */ +#define USB_DEVICE_ID_LD_XRAY 0x1100 /* USB Product ID of X-Ray Apparatus 55481 */ +#define USB_DEVICE_ID_LD_XRAY2 0x1101 /* USB Product ID of X-Ray Apparatus 554800 */ +#define USB_DEVICE_ID_LD_XRAYCT 0x1110 /* USB Product ID of X-Ray Apparatus CT 554821*/ #define USB_DEVICE_ID_LD_VIDEOCOM 0x1200 /* USB Product ID of VideoCom */ +#define USB_DEVICE_ID_LD_MOTOR 0x1210 /* USB Product ID of Motor (reserved) */ #define USB_DEVICE_ID_LD_COM3LAB 0x2000 /* USB Product ID of COM3LAB */ #define USB_DEVICE_ID_LD_TELEPORT 0x2010 /* USB Product ID of Terminal Adapter */ #define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020 /* USB Product ID of Network Analyser */ #define USB_DEVICE_ID_LD_POWERCONTROL 0x2030 /* USB Product ID of Converter Control Unit */ #define USB_DEVICE_ID_LD_MACHINETEST 0x2040 /* USB Product ID of Machine Test System */ +#define USB_DEVICE_ID_LD_MOSTANALYSER 0x2050 /* USB Product ID of MOST Protocol Analyser */ +#define USB_DEVICE_ID_LD_MOSTANALYSER2 0x2051 /* USB Product ID of MOST Protocol Analyser 2 */ +#define USB_DEVICE_ID_LD_ABSESP 0x2060 /* USB Product ID of ABS ESP */ +#define USB_DEVICE_ID_LD_AUTODATABUS 0x2070 /* USB Product ID of Automotive Data Buses */ +#define USB_DEVICE_ID_LD_MCT 0x2080 /* USB Product ID of Microcontroller technique */ +#define USB_DEVICE_ID_LD_HYBRID 0x2090 /* USB Product ID of Automotive Hybrid */ +#define USB_DEVICE_ID_LD_HEATCONTROL 0x20A0 /* USB Product ID of Heat control */ #define USB_VENDOR_ID_VERNIER 0x08f7 #define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002 @@ -69,21 +82,39 @@ #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_CASSY2) }, { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY2) }, { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY2) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYVOLTAGE) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYCURRENT) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYTIME) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYTEMPERATURE) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYPH) }, { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM) }, { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP) }, { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP) }, - { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY1) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIC) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIB) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY) }, { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2) }, { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOTOR) }, { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB) }, { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT) }, { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER) }, { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL) }, { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOSTANALYSER) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOSTANALYSER2) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_ABSESP) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_AUTODATABUS) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MCT) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HYBRID) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HEATCONTROL) }, { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) }, { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) }, { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) }, @@ -91,25 +122,12 @@ static struct usb_device_id ld_usb_table [] = { { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, ld_usb_table); -MODULE_VERSION("V0.13"); +MODULE_VERSION("V0.14"); MODULE_AUTHOR("Michael Hund <mhund@ld-didactic.de>"); MODULE_DESCRIPTION("LD USB Driver"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("LD USB Devices"); -#ifdef CONFIG_USB_DEBUG - static int debug = 1; -#else - static int debug = 0; -#endif - -/* Use our own dbg macro */ -#define dbg_info(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) - -/* Module parameters */ -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); - /* All interrupt in transfers are collected in a ring buffer to * avoid racing conditions and get better performance of the driver. */ @@ -224,8 +242,9 @@ static void ld_usb_interrupt_in_callback(struct urb *urb) status == -ESHUTDOWN) { goto exit; } else { - dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n", - __func__, status); + dev_dbg(&dev->intf->dev, + "%s: nonzero status received: %d\n", __func__, + status); spin_lock(&dev->rbsl); goto resubmit; /* maybe we can recover */ } @@ -240,8 +259,8 @@ static void ld_usb_interrupt_in_callback(struct urb *urb) *actual_buffer = urb->actual_length; memcpy(actual_buffer+1, dev->interrupt_in_buffer, urb->actual_length); dev->ring_head = next_ring_head; - dbg_info(&dev->intf->dev, "%s: received %d bytes\n", - __func__, urb->actual_length); + dev_dbg(&dev->intf->dev, "%s: received %d bytes\n", + __func__, urb->actual_length); } else { dev_warn(&dev->intf->dev, "Ring buffer overflow, %d bytes dropped\n", @@ -278,9 +297,9 @@ static void ld_usb_interrupt_out_callback(struct urb *urb) if (status && !(status == -ENOENT || status == -ECONNRESET || status == -ESHUTDOWN)) - dbg_info(&dev->intf->dev, - "%s - nonzero write interrupt status received: %d\n", - __func__, status); + dev_dbg(&dev->intf->dev, + "%s - nonzero write interrupt status received: %d\n", + __func__, status); dev->interrupt_out_busy = 0; wake_up_interruptible(&dev->write_wait); @@ -302,8 +321,8 @@ static int ld_usb_open(struct inode *inode, struct file *file) interface = usb_find_interface(&ld_usb_driver, subminor); if (!interface) { - err("%s - error, can't find device for minor %d\n", - __func__, subminor); + printk(KERN_ERR "%s - error, can't find device for minor %d\n", + __func__, subminor); return -ENODEV; } @@ -453,7 +472,7 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count, /* verify that the device wasn't unplugged */ if (dev->intf == NULL) { retval = -ENODEV; - err("No device or device unplugged %d\n", retval); + printk(KERN_ERR "ldusb: No device or device unplugged %d\n", retval); goto unlock_exit; } @@ -533,7 +552,7 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer, /* verify that the device wasn't unplugged */ if (dev->intf == NULL) { retval = -ENODEV; - err("No device or device unplugged %d\n", retval); + printk(KERN_ERR "ldusb: No device or device unplugged %d\n", retval); goto unlock_exit; } @@ -553,7 +572,8 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer, bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size); if (bytes_to_write < count) dev_warn(&dev->intf->dev, "Write buffer overflow, %zd bytes dropped\n",count-bytes_to_write); - dbg_info(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", __func__, count, bytes_to_write); + dev_dbg(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", + __func__, count, bytes_to_write); if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) { retval = -EFAULT; @@ -571,7 +591,9 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer, bytes_to_write, USB_CTRL_SET_TIMEOUT * HZ); if (retval < 0) - err("Couldn't submit HID_REQ_SET_REPORT %d\n", retval); + dev_err(&dev->intf->dev, + "Couldn't submit HID_REQ_SET_REPORT %d\n", + retval); goto unlock_exit; } @@ -592,7 +614,8 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer, retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL); if (retval) { dev->interrupt_out_busy = 0; - err("Couldn't submit interrupt_out_urb %d\n", retval); + dev_err(&dev->intf->dev, + "Couldn't submit interrupt_out_urb %d\n", retval); goto unlock_exit; } retval = bytes_to_write; @@ -613,6 +636,7 @@ static const struct file_operations ld_usb_fops = { .open = ld_usb_open, .release = ld_usb_release, .poll = ld_usb_poll, + .llseek = no_llseek, }; /* @@ -641,7 +665,7 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id * int i; int retval = -ENOMEM; - /* allocate memory for our device state and intialize it */ + /* allocate memory for our device state and initialize it */ dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { @@ -688,7 +712,7 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id * if (dev->interrupt_out_endpoint == NULL) dev_warn(&intf->dev, "Interrupt out endpoint not found (using control endpoint instead)\n"); - dev->interrupt_in_endpoint_size = le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize); + dev->interrupt_in_endpoint_size = usb_endpoint_maxp(dev->interrupt_in_endpoint); dev->ring_buffer = kmalloc(ring_buffer_size*(sizeof(size_t)+dev->interrupt_in_endpoint_size), GFP_KERNEL); if (!dev->ring_buffer) { dev_err(&intf->dev, "Couldn't allocate ring_buffer\n"); @@ -704,7 +728,7 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id * dev_err(&intf->dev, "Couldn't allocate interrupt_in_urb\n"); goto error; } - dev->interrupt_out_endpoint_size = dev->interrupt_out_endpoint ? le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize) : + dev->interrupt_out_endpoint_size = dev->interrupt_out_endpoint ? usb_endpoint_maxp(dev->interrupt_out_endpoint) : udev->descriptor.bMaxPacketSize0; dev->interrupt_out_buffer = kmalloc(write_buffer_size*dev->interrupt_out_endpoint_size, GFP_KERNEL); if (!dev->interrupt_out_buffer) { @@ -788,30 +812,5 @@ static struct usb_driver ld_usb_driver = { .id_table = ld_usb_table, }; -/** - * ld_usb_init - */ -static int __init ld_usb_init(void) -{ - int retval; - - /* 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); - - return retval; -} - -/** - * ld_usb_exit - */ -static void __exit ld_usb_exit(void) -{ - /* deregister this driver with the USB subsystem */ - usb_deregister(&ld_usb_driver); -} - -module_init(ld_usb_init); -module_exit(ld_usb_exit); +module_usb_driver(ld_usb_driver); diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index faa6d623de7..97cd9e24bd2 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -75,9 +75,10 @@ * - move reset into open to clean out spurious data */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/kernel.h> #include <linux/errno.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/completion.h> @@ -87,25 +88,11 @@ #include <linux/poll.h> -#ifdef CONFIG_USB_DEBUG - static int debug = 4; -#else - static int debug = 0; -#endif - -/* 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) - - /* Version Information */ #define DRIVER_VERSION "v0.96" #define DRIVER_AUTHOR "Juergen Stuber <starblue@sourceforge.net>" #define DRIVER_DESC "LEGO USB Tower Driver" -/* Module parameters */ -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); /* The defaults are chosen to work with the latest versions of leJOS and NQC. */ @@ -192,7 +179,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 */ }; @@ -266,7 +253,7 @@ static const struct file_operations tower_fops = { .llseek = tower_llseek, }; -static char *legousbtower_devnode(struct device *dev, mode_t *mode) +static char *legousbtower_devnode(struct device *dev, umode_t *mode) { return kasprintf(GFP_KERNEL, "usb/%s", dev_name(dev)); } @@ -295,18 +282,12 @@ static struct usb_driver tower_driver = { /** * lego_usb_tower_debug_data */ -static inline void lego_usb_tower_debug_data (int level, const char *function, int size, const unsigned char *data) +static inline void lego_usb_tower_debug_data(struct device *dev, + const char *function, int size, + const unsigned char *data) { - int i; - - if (debug < level) - return; - - printk (KERN_DEBUG __FILE__": %s - length = %d, data = ", function, size); - for (i = 0; i < size; ++i) { - printk ("%.2x ", data[i]); - } - printk ("\n"); + dev_dbg(dev, "%s - length = %d, data = %*ph\n", + function, size, size, data); } @@ -315,8 +296,6 @@ static inline void lego_usb_tower_debug_data (int level, const char *function, i */ static inline void tower_delete (struct lego_usb_tower *dev) { - dbg(2, "%s: enter", __func__); - tower_abort_transfers (dev); /* free data structures */ @@ -326,8 +305,6 @@ static inline void tower_delete (struct lego_usb_tower *dev) kfree (dev->interrupt_in_buffer); kfree (dev->interrupt_out_buffer); kfree (dev); - - dbg(2, "%s: leave", __func__); } @@ -343,16 +320,13 @@ static int tower_open (struct inode *inode, struct file *file) struct tower_reset_reply reset_reply; int result; - dbg(2, "%s: enter", __func__); - nonseekable_open(inode, file); subminor = iminor(inode); interface = usb_find_interface (&tower_driver, subminor); if (!interface) { - err ("%s - error, can't find device for minor %d", - __func__, subminor); + pr_err("error, can't find device for minor %d\n", subminor); retval = -ENODEV; goto exit; } @@ -394,7 +368,8 @@ static int tower_open (struct inode *inode, struct file *file) sizeof(reset_reply), 1000); if (result < 0) { - err("LEGO USB Tower reset control request failed"); + dev_err(&dev->udev->dev, + "LEGO USB Tower reset control request failed\n"); retval = result; goto unlock_exit; } @@ -406,7 +381,7 @@ static int tower_open (struct inode *inode, struct file *file) dev->udev, usb_rcvintpipe(dev->udev, dev->interrupt_in_endpoint->bEndpointAddress), dev->interrupt_in_buffer, - le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), + usb_endpoint_maxp(dev->interrupt_in_endpoint), tower_interrupt_in_callback, dev, dev->interrupt_in_interval); @@ -417,7 +392,8 @@ static int tower_open (struct inode *inode, struct file *file) retval = usb_submit_urb (dev->interrupt_in_urb, GFP_KERNEL); if (retval) { - err("Couldn't submit interrupt_in_urb %d", retval); + dev_err(&dev->udev->dev, + "Couldn't submit interrupt_in_urb %d\n", retval); dev->interrupt_in_running = 0; dev->open_count = 0; goto unlock_exit; @@ -430,8 +406,6 @@ unlock_exit: mutex_unlock(&dev->lock); exit: - dbg(2, "%s: leave, return value %d ", __func__, retval); - return retval; } @@ -443,12 +417,9 @@ static int tower_release (struct inode *inode, struct file *file) struct lego_usb_tower *dev; int retval = 0; - dbg(2, "%s: enter", __func__); - - dev = (struct lego_usb_tower *)file->private_data; + dev = file->private_data; if (dev == NULL) { - dbg(1, "%s: object is NULL", __func__); retval = -ENODEV; goto exit_nolock; } @@ -460,7 +431,8 @@ static int tower_release (struct inode *inode, struct file *file) } if (dev->open_count != 1) { - dbg(1, "%s: device not opened exactly once", __func__); + dev_dbg(&dev->udev->dev, "%s: device not opened exactly once\n", + __func__); retval = -ENODEV; goto unlock_exit; } @@ -486,7 +458,6 @@ unlock_exit: exit: mutex_unlock(&open_disc_mutex); exit_nolock: - dbg(2, "%s: leave, return value %d", __func__, retval); return retval; } @@ -497,12 +468,8 @@ exit_nolock: */ static void tower_abort_transfers (struct lego_usb_tower *dev) { - dbg(2, "%s: enter", __func__); - - if (dev == NULL) { - dbg(1, "%s: dev is null", __func__); - goto exit; - } + if (dev == NULL) + return; /* shutdown transfer */ if (dev->interrupt_in_running) { @@ -513,9 +480,6 @@ static void tower_abort_transfers (struct lego_usb_tower *dev) } if (dev->interrupt_out_busy && dev->udev) usb_kill_urb(dev->interrupt_out_urb); - -exit: - dbg(2, "%s: leave", __func__); } @@ -548,8 +512,6 @@ static unsigned int tower_poll (struct file *file, poll_table *wait) struct lego_usb_tower *dev; unsigned int mask = 0; - dbg(2, "%s: enter", __func__); - dev = file->private_data; if (!dev->udev) @@ -566,8 +528,6 @@ static unsigned int tower_poll (struct file *file, poll_table *wait) mask |= POLLOUT | POLLWRNORM; } - dbg(2, "%s: leave, mask = %d", __func__, mask); - return mask; } @@ -592,9 +552,7 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count, int retval = 0; unsigned long timeout = 0; - dbg(2, "%s: enter, count = %Zd", __func__, count); - - dev = (struct lego_usb_tower *)file->private_data; + dev = file->private_data; /* lock this object */ if (mutex_lock_interruptible(&dev->lock)) { @@ -605,13 +563,13 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count, /* verify that the device wasn't unplugged */ if (dev->udev == NULL) { retval = -ENODEV; - err("No device or device unplugged %d", retval); + pr_err("No device or device unplugged %d\n", retval); goto unlock_exit; } /* verify that we actually have some data to read */ if (count == 0) { - dbg(1, "%s: read request of 0 bytes", __func__); + dev_dbg(&dev->udev->dev, "read request of 0 bytes\n"); goto unlock_exit; } @@ -667,7 +625,6 @@ unlock_exit: mutex_unlock(&dev->lock); exit: - dbg(2, "%s: leave, return value %d", __func__, retval); return retval; } @@ -681,9 +638,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t size_t bytes_to_write; int retval = 0; - dbg(2, "%s: enter, count = %Zd", __func__, count); - - dev = (struct lego_usb_tower *)file->private_data; + dev = file->private_data; /* lock this object */ if (mutex_lock_interruptible(&dev->lock)) { @@ -694,13 +649,13 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t /* verify that the device wasn't unplugged */ if (dev->udev == NULL) { retval = -ENODEV; - err("No device or device unplugged %d", retval); + pr_err("No device or device unplugged %d\n", retval); goto unlock_exit; } /* verify that we actually have some data to write */ if (count == 0) { - dbg(1, "%s: write request of 0 bytes", __func__); + dev_dbg(&dev->udev->dev, "write request of 0 bytes\n"); goto unlock_exit; } @@ -718,7 +673,8 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t /* write the data into interrupt_out_buffer from userspace */ bytes_to_write = min_t(int, count, write_buffer_size); - dbg(4, "%s: count = %Zd, bytes_to_write = %Zd", __func__, count, bytes_to_write); + dev_dbg(&dev->udev->dev, "%s: count = %Zd, bytes_to_write = %Zd\n", + __func__, count, bytes_to_write); if (copy_from_user (dev->interrupt_out_buffer, buffer, bytes_to_write)) { retval = -EFAULT; @@ -741,7 +697,8 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t retval = usb_submit_urb (dev->interrupt_out_urb, GFP_KERNEL); if (retval) { dev->interrupt_out_busy = 0; - err("Couldn't submit interrupt_out_urb %d", retval); + dev_err(&dev->udev->dev, + "Couldn't submit interrupt_out_urb %d\n", retval); goto unlock_exit; } retval = bytes_to_write; @@ -751,8 +708,6 @@ unlock_exit: mutex_unlock(&dev->lock); exit: - dbg(2, "%s: leave, return value %d", __func__, retval); - return retval; } @@ -766,9 +721,8 @@ static void tower_interrupt_in_callback (struct urb *urb) int status = urb->status; int retval; - dbg(4, "%s: enter, status %d", __func__, status); - - lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); + lego_usb_tower_debug_data(&dev->udev->dev, __func__, + urb->actual_length, urb->transfer_buffer); if (status) { if (status == -ENOENT || @@ -776,7 +730,9 @@ static void tower_interrupt_in_callback (struct urb *urb) status == -ESHUTDOWN) { goto exit; } else { - dbg(1, "%s: nonzero status received: %d", __func__, status); + dev_dbg(&dev->udev->dev, + "%s: nonzero status received: %d\n", __func__, + status); goto resubmit; /* maybe we can recover */ } } @@ -789,9 +745,11 @@ static void tower_interrupt_in_callback (struct urb *urb) urb->actual_length); dev->read_buffer_length += urb->actual_length; dev->read_last_arrival = jiffies; - dbg(3, "%s: received %d bytes", __func__, urb->actual_length); + dev_dbg(&dev->udev->dev, "%s: received %d bytes\n", + __func__, urb->actual_length); } else { - printk(KERN_WARNING "%s: read_buffer overflow, %d bytes dropped", __func__, urb->actual_length); + pr_warn("read_buffer overflow, %d bytes dropped\n", + urb->actual_length); } spin_unlock (&dev->read_buffer_lock); } @@ -800,17 +758,15 @@ resubmit: /* resubmit if we're still running */ if (dev->interrupt_in_running && dev->udev) { retval = usb_submit_urb (dev->interrupt_in_urb, GFP_ATOMIC); - if (retval) { - err("%s: usb_submit_urb failed (%d)", __func__, retval); - } + if (retval) + dev_err(&dev->udev->dev, + "%s: usb_submit_urb failed (%d)\n", + __func__, retval); } exit: dev->interrupt_in_done = 1; wake_up_interruptible (&dev->read_wait); - - lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); - dbg(4, "%s: leave, status %d", __func__, status); } @@ -822,22 +778,20 @@ static void tower_interrupt_out_callback (struct urb *urb) struct lego_usb_tower *dev = urb->context; int status = urb->status; - dbg(4, "%s: enter, status %d", __func__, status); - lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); + lego_usb_tower_debug_data(&dev->udev->dev, __func__, + urb->actual_length, urb->transfer_buffer); /* sync/async unlink faults aren't errors */ if (status && !(status == -ENOENT || status == -ECONNRESET || status == -ESHUTDOWN)) { - dbg(1, "%s - nonzero write bulk status received: %d", - __func__, status); + dev_dbg(&dev->udev->dev, + "%s: nonzero write bulk status received: %d\n", __func__, + status); } dev->interrupt_out_busy = 0; wake_up_interruptible(&dev->write_wait); - - lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); - dbg(4, "%s: leave, status %d", __func__, status); } @@ -849,6 +803,7 @@ static void tower_interrupt_out_callback (struct urb *urb) */ static int tower_probe (struct usb_interface *interface, const struct usb_device_id *id) { + struct device *idev = &interface->dev; struct usb_device *udev = interface_to_usbdev(interface); struct lego_usb_tower *dev = NULL; struct usb_host_interface *iface_desc; @@ -858,17 +813,12 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device int retval = -ENOMEM; int result; - dbg(2, "%s: enter", __func__); - - if (udev == NULL) - dev_info(&interface->dev, "udev is NULL.\n"); - /* allocate memory for our device state and initialize it */ dev = kmalloc (sizeof(struct lego_usb_tower), GFP_KERNEL); if (dev == NULL) { - err ("Out of memory"); + dev_err(idev, "Out of memory\n"); goto exit; } @@ -912,37 +862,37 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device } } if(dev->interrupt_in_endpoint == NULL) { - err("interrupt in endpoint not found"); + dev_err(idev, "interrupt in endpoint not found\n"); goto error; } if (dev->interrupt_out_endpoint == NULL) { - err("interrupt out endpoint not found"); + dev_err(idev, "interrupt out endpoint not found\n"); goto error; } dev->read_buffer = kmalloc (read_buffer_size, GFP_KERNEL); if (!dev->read_buffer) { - err("Couldn't allocate read_buffer"); + dev_err(idev, "Couldn't allocate read_buffer\n"); goto error; } - dev->interrupt_in_buffer = kmalloc (le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), GFP_KERNEL); + dev->interrupt_in_buffer = kmalloc (usb_endpoint_maxp(dev->interrupt_in_endpoint), GFP_KERNEL); if (!dev->interrupt_in_buffer) { - err("Couldn't allocate interrupt_in_buffer"); + dev_err(idev, "Couldn't allocate interrupt_in_buffer\n"); goto error; } dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); if (!dev->interrupt_in_urb) { - err("Couldn't allocate interrupt_in_urb"); + dev_err(idev, "Couldn't allocate interrupt_in_urb\n"); goto error; } dev->interrupt_out_buffer = kmalloc (write_buffer_size, GFP_KERNEL); if (!dev->interrupt_out_buffer) { - err("Couldn't allocate interrupt_out_buffer"); + dev_err(idev, "Couldn't allocate interrupt_out_buffer\n"); goto error; } dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); if (!dev->interrupt_out_urb) { - err("Couldn't allocate interrupt_out_urb"); + dev_err(idev, "Couldn't allocate interrupt_out_urb\n"); goto error; } dev->interrupt_in_interval = interrupt_in_interval ? interrupt_in_interval : dev->interrupt_in_endpoint->bInterval; @@ -955,7 +905,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device if (retval) { /* something prevented us from registering this driver */ - err ("Not able to get a minor for this device."); + dev_err(idev, "Not able to get a minor for this device.\n"); usb_set_intfdata (interface, NULL); goto error; } @@ -977,7 +927,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device sizeof(get_version_reply), 1000); if (result < 0) { - err("LEGO USB Tower get version control request failed"); + dev_err(idev, "LEGO USB Tower get version control request failed\n"); retval = result; goto error; } @@ -988,8 +938,6 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device exit: - dbg(2, "%s: leave, return value 0x%.8lx (dev)", __func__, (long) dev); - return retval; error: @@ -1008,8 +956,6 @@ static void tower_disconnect (struct usb_interface *interface) struct lego_usb_tower *dev; int minor; - dbg(2, "%s: enter", __func__); - dev = usb_get_intfdata (interface); mutex_lock(&open_disc_mutex); usb_set_intfdata (interface, NULL); @@ -1036,55 +982,9 @@ static void tower_disconnect (struct usb_interface *interface) dev_info(&interface->dev, "LEGO USB Tower #%d now disconnected\n", (minor - LEGO_USB_TOWER_MINOR_BASE)); - - dbg(2, "%s: leave", __func__); -} - - - -/** - * lego_usb_tower_init - */ -static int __init lego_usb_tower_init(void) -{ - int result; - int retval = 0; - - dbg(2, "%s: enter", __func__); - - /* 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); - retval = -1; - goto exit; - } - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - -exit: - dbg(2, "%s: leave, return value %d", __func__, retval); - - return retval; -} - - -/** - * lego_usb_tower_exit - */ -static void __exit lego_usb_tower_exit(void) -{ - dbg(2, "%s: enter", __func__); - - /* deregister this driver with the USB subsystem */ - usb_deregister (&tower_driver); - - dbg(2, "%s: leave", __func__); } -module_init (lego_usb_tower_init); -module_exit (lego_usb_tower_exit); +module_usb_driver(tower_driver); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c index 32d0199d0c3..13731d51262 100644 --- a/drivers/usb/misc/rio500.c +++ b/drivers/usb/misc/rio500.c @@ -32,11 +32,10 @@ #include <linux/kernel.h> #include <linux/signal.h> #include <linux/sched.h> -#include <linux/smp_lock.h> +#include <linux/mutex.h> #include <linux/errno.h> #include <linux/random.h> #include <linux/poll.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/usb.h> @@ -72,16 +71,20 @@ struct rio_usb_data { struct mutex lock; /* general race avoidance */ }; +static DEFINE_MUTEX(rio500_mutex); static struct rio_usb_data rio_instance; static int open_rio(struct inode *inode, struct file *file) { struct rio_usb_data *rio = &rio_instance; + /* against disconnect() */ + mutex_lock(&rio500_mutex); mutex_lock(&(rio->lock)); if (rio->isopen || !rio->present) { mutex_unlock(&(rio->lock)); + mutex_unlock(&rio500_mutex); 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"); + mutex_unlock(&rio500_mutex); 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) { @@ -149,10 +152,10 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg) requesttype = rio_cmd.requesttype | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE; - dbg - ("sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x", - requesttype, rio_cmd.request, rio_cmd.value, - rio_cmd.index, rio_cmd.length); + dev_dbg(&rio->rio_dev->dev, + "sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x\n", + requesttype, rio_cmd.request, rio_cmd.value, + rio_cmd.index, rio_cmd.length); /* Send rio control message */ retries = 3; while (retries) { @@ -167,11 +170,14 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg) if (result == -ETIMEDOUT) retries--; else if (result < 0) { - err("Error executing ioctrl. code = %d", result); + dev_err(&rio->rio_dev->dev, + "Error executing ioctrl. code = %d\n", + result); retries = 0; } else { - dbg("Executed ioctl. Result = %d (data=%02x)", - result, buffer[0]); + dev_dbg(&rio->rio_dev->dev, + "Executed ioctl. Result = %d (data=%02x)\n", + result, buffer[0]); if (copy_to_user(rio_cmd.buffer, buffer, rio_cmd.length)) { free_page((unsigned long) buffer); @@ -217,9 +223,10 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg) requesttype = rio_cmd.requesttype | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; - dbg("sending command: reqtype=%0x req=%0x value=%0x index=%0x len=%0x", - requesttype, rio_cmd.request, rio_cmd.value, - rio_cmd.index, rio_cmd.length); + dev_dbg(&rio->rio_dev->dev, + "sending command: reqtype=%0x req=%0x value=%0x index=%0x len=%0x\n", + requesttype, rio_cmd.request, rio_cmd.value, + rio_cmd.index, rio_cmd.length); /* Send rio control message */ retries = 3; while (retries) { @@ -234,10 +241,13 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg) if (result == -ETIMEDOUT) retries--; else if (result < 0) { - err("Error executing ioctrl. code = %d", result); + dev_err(&rio->rio_dev->dev, + "Error executing ioctrl. code = %d\n", + result); retries = 0; } else { - dbg("Executed ioctl. Result = %d", result); + dev_dbg(&rio->rio_dev->dev, + "Executed ioctl. Result = %d\n", result); retries = 0; } @@ -254,7 +264,6 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg) err_out: mutex_unlock(&(rio->lock)); - unlock_kernel(); return retval; } @@ -310,8 +319,9 @@ write_rio(struct file *file, const char __user *buffer, usb_sndbulkpipe(rio->rio_dev, 2), obuf, thistime, &partial, 5000); - dbg("write stats: result:%d thistime:%lu partial:%u", - result, thistime, partial); + dev_dbg(&rio->rio_dev->dev, + "write stats: result:%d thistime:%lu partial:%u\n", + result, thistime, partial); if (result == -ETIMEDOUT) { /* NAK - so hold for a while */ if (!maxretry--) { @@ -327,9 +337,10 @@ write_rio(struct file *file, const char __user *buffer, thistime -= partial; } else break; - }; + } if (result) { - err("Write Whoops - %x", result); + dev_err(&rio->rio_dev->dev, "Write Whoops - %x\n", + result); errn = -EIO; goto error; } @@ -390,15 +401,17 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) ibuf, this_read, &partial, 8000); - dbg("read stats: result:%d this_read:%u partial:%u", - result, this_read, partial); + dev_dbg(&rio->rio_dev->dev, + "read stats: result:%d this_read:%u partial:%u\n", + result, this_read, partial); if (partial) { count = this_read = partial; } else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */ if (!maxretry--) { mutex_unlock(&(rio->lock)); - err("read_rio: maxretry timeout"); + dev_err(&rio->rio_dev->dev, + "read_rio: maxretry timeout\n"); return -ETIME; } prepare_to_wait(&rio->wait_q, &wait, TASK_INTERRUPTIBLE); @@ -407,8 +420,9 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) continue; } else if (result != -EREMOTEIO) { mutex_unlock(&(rio->lock)); - err("Read Whoops - result:%u partial:%u this_read:%u", - result, partial, this_read); + dev_err(&rio->rio_dev->dev, + "Read Whoops - result:%u partial:%u this_read:%u\n", + result, partial, this_read); return -EIO; } else { mutex_unlock(&(rio->lock)); @@ -436,6 +450,7 @@ static const struct file_operations usb_rio_fops = { .unlocked_ioctl = ioctl_rio, .open = open_rio, .release = close_rio, + .llseek = noop_llseek, }; static struct usb_class_driver usb_rio_class = { @@ -455,26 +470,29 @@ static int probe_rio(struct usb_interface *intf, retval = usb_register_dev(intf, &usb_rio_class); if (retval) { - err("Not able to get a minor for this device."); + dev_err(&dev->dev, + "Not able to get a minor for this device.\n"); return -ENOMEM; } rio->rio_dev = dev; if (!(rio->obuf = kmalloc(OBUF_SIZE, GFP_KERNEL))) { - err("probe_rio: Not enough memory for the output buffer"); + dev_err(&dev->dev, + "probe_rio: Not enough memory for the output buffer\n"); usb_deregister_dev(intf, &usb_rio_class); return -ENOMEM; } - dbg("probe_rio: obuf address:%p", rio->obuf); + dev_dbg(&intf->dev, "obuf address:%p\n", rio->obuf); if (!(rio->ibuf = kmalloc(IBUF_SIZE, GFP_KERNEL))) { - err("probe_rio: Not enough memory for the input buffer"); + dev_err(&dev->dev, + "probe_rio: Not enough memory for the input buffer\n"); usb_deregister_dev(intf, &usb_rio_class); kfree(rio->obuf); return -ENOMEM; } - dbg("probe_rio: ibuf address:%p", rio->ibuf); + dev_dbg(&intf->dev, "ibuf address:%p\n", rio->ibuf); mutex_init(&(rio->lock)); @@ -489,6 +507,7 @@ static void disconnect_rio(struct usb_interface *intf) struct rio_usb_data *rio = usb_get_intfdata (intf); usb_set_intfdata (intf, NULL); + mutex_lock(&rio500_mutex); if (rio) { usb_deregister_dev(intf, &usb_rio_class); @@ -498,6 +517,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)); + mutex_unlock(&rio500_mutex); return; } kfree(rio->ibuf); @@ -508,9 +528,10 @@ static void disconnect_rio(struct usb_interface *intf) rio->present = 0; mutex_unlock(&(rio->lock)); } + mutex_unlock(&rio500_mutex); } -static struct usb_device_id rio_table [] = { +static const struct usb_device_id rio_table[] = { { USB_DEVICE(0x0841, 1) }, /* Rio 500 */ { } /* Terminating entry */ }; @@ -524,33 +545,7 @@ static struct usb_driver rio_driver = { .id_table = rio_table, }; -static int __init usb_rio_init(void) -{ - int retval; - retval = usb_register(&rio_driver); - if (retval) - goto out; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - -out: - return retval; -} - - -static void __exit usb_rio_cleanup(void) -{ - struct rio_usb_data *rio = &rio_instance; - - rio->present = 0; - usb_deregister(&rio_driver); - - -} - -module_init(usb_rio_init); -module_exit(usb_rio_cleanup); +module_usb_driver(rio_driver); MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); diff --git a/drivers/usb/misc/sisusbvga/Kconfig b/drivers/usb/misc/sisusbvga/Kconfig index 30ea7ca6846..36bc28c884a 100644 --- a/drivers/usb/misc/sisusbvga/Kconfig +++ b/drivers/usb/misc/sisusbvga/Kconfig @@ -1,7 +1,8 @@ config USB_SISUSBVGA tristate "USB 2.0 SVGA dongle support (Net2280/SiS315)" - depends on USB && (USB_MUSB_HDRC || USB_EHCI_HCD) + depends on (USB_MUSB_HDRC || USB_EHCI_HCD) + select FONT_SUPPORT if USB_SISUSBVGA_CON ---help--- Say Y here if you intend to attach a USB2VGA dongle based on a Net2280 and a SiS315 chip. diff --git a/drivers/usb/misc/sisusbvga/Makefile b/drivers/usb/misc/sisusbvga/Makefile index 7f934cfc906..3142476ccc8 100644 --- a/drivers/usb/misc/sisusbvga/Makefile +++ b/drivers/usb/misc/sisusbvga/Makefile @@ -4,5 +4,4 @@ obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga.o -sisusbvga-objs := sisusb.o sisusb_init.o sisusb_con.o - +sisusbvga-y := sisusb.o sisusb_init.o sisusb_con.o diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 0025847743f..06b5d77cd9a 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -47,7 +47,6 @@ #include <linux/spinlock.h> #include <linux/kref.h> #include <linux/usb.h> -#include <linux/smp_lock.h> #include <linux/vmalloc.h> #include "sisusb.h" @@ -250,7 +249,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 +305,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) { @@ -2124,8 +2123,8 @@ sisusb_get_ramconfig(struct sisusb_usb_data *sisusb) u8 tmp8, tmp82, ramtype; int bw = 0; char *ramtypetext1 = NULL; - const char *ramtypetext2[] = { "SDR SDRAM", "SDR SGRAM", - "DDR SDRAM", "DDR SGRAM" }; + static const char ram_datarate[4] = {'S', 'S', 'D', 'D'}; + static const char ram_dynamictype[4] = {'D', 'G', 'D', 'G'}; static const int busSDR[4] = {64, 64, 128, 128}; static const int busDDR[4] = {32, 32, 64, 64}; static const int busDDRA[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2}; @@ -2157,8 +2156,10 @@ sisusb_get_ramconfig(struct sisusb_usb_data *sisusb) break; } - dev_info(&sisusb->sisusb_dev->dev, "%dMB %s %s, bus width %d\n", (sisusb->vramsize >> 20), ramtypetext1, - ramtypetext2[ramtype], bw); + + dev_info(&sisusb->sisusb_dev->dev, "%dMB %s %cDR S%cRAM, bus width %d\n", + sisusb->vramsize >> 20, ramtypetext1, + ram_datarate[ramtype], ram_dynamictype[ramtype], bw); } static int @@ -2416,11 +2417,13 @@ sisusb_open(struct inode *inode, struct file *file) struct usb_interface *interface; int subminor = iminor(inode); - if (!(interface = usb_find_interface(&sisusb_driver, subminor))) + if (!(interface = usb_find_interface(&sisusb_driver, subminor))) { return -ENODEV; + } - if (!(sisusb = usb_get_intfdata(interface))) + if (!(sisusb = usb_get_intfdata(interface))) { return -ENODEV; + } mutex_lock(&sisusb->lock); @@ -2435,7 +2438,8 @@ sisusb_open(struct inode *inode, struct file *file) } if (!sisusb->devinit) { - if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) { + if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH || + sisusb->sisusb_dev->speed == USB_SPEED_SUPER) { if (sisusb_init_gfxdevice(sisusb, 0)) { mutex_unlock(&sisusb->lock); dev_err(&sisusb->sisusb_dev->dev, "Failed to initialize device\n"); @@ -2485,7 +2489,7 @@ sisusb_release(struct inode *inode, struct file *file) { struct sisusb_usb_data *sisusb; - if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) + if (!(sisusb = file->private_data)) return -ENODEV; mutex_lock(&sisusb->lock); @@ -2517,7 +2521,7 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) u16 buf16; u32 buf32, address; - if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) + if (!(sisusb = file->private_data)) return -ENODEV; mutex_lock(&sisusb->lock); @@ -2659,7 +2663,7 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, u16 buf16; u32 buf32, address; - if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) + if (!(sisusb = file->private_data)) return -ENODEV; mutex_lock(&sisusb->lock); @@ -2802,7 +2806,7 @@ sisusb_lseek(struct file *file, loff_t offset, int orig) struct sisusb_usb_data *sisusb; loff_t ret; - if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) + if (!(sisusb = file->private_data)) return -ENODEV; mutex_lock(&sisusb->lock); @@ -2964,13 +2968,12 @@ sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct sisusb_usb_data *sisusb; struct sisusb_info x; struct sisusb_command y; - int retval = 0; + long retval = 0; u32 __user *argp = (u32 __user *)arg; - if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) + if (!(sisusb = file->private_data)) return -ENODEV; - lock_kernel(); mutex_lock(&sisusb->lock); /* Sanity check */ @@ -3007,6 +3010,7 @@ sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) #else x.sisusb_conactive = 0; #endif + memset(x.sisusb_reserved, 0, sizeof(x.sisusb_reserved)); if (copy_to_user((void __user *)arg, &x, sizeof(x))) retval = -EFAULT; @@ -3029,7 +3033,6 @@ sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) err_out: mutex_unlock(&sisusb->lock); - unlock_kernel(); return retval; } @@ -3083,7 +3086,7 @@ static int sisusb_probe(struct usb_interface *intf, /* Allocate memory for our private */ if (!(sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL))) { - dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for private data\n"); + dev_err(&dev->dev, "Failed to allocate memory for private data\n"); return -ENOMEM; } kref_init(&sisusb->kref); @@ -3167,7 +3170,7 @@ static int sisusb_probe(struct usb_interface *intf, sisusb->present = 1; - if (dev->speed == USB_SPEED_HIGH) { + if (dev->speed == USB_SPEED_HIGH || dev->speed == USB_SPEED_SUPER) { int initscreen = 1; #ifdef INCL_SISUSB_CON if (sisusb_first_vc > 0 && @@ -3238,13 +3241,15 @@ 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) }, { USB_DEVICE(0x0711, 0x0902) }, { USB_DEVICE(0x0711, 0x0903) }, { USB_DEVICE(0x0711, 0x0918) }, + { USB_DEVICE(0x0711, 0x0920) }, + { USB_DEVICE(0x0711, 0x0950) }, { USB_DEVICE(0x182d, 0x021c) }, { USB_DEVICE(0x182d, 0x0269) }, { } diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index b624320df90..a638c4e9a94 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/drivers/usb/misc/sisusbvga/sisusb_con.c @@ -58,7 +58,6 @@ #include <linux/string.h> #include <linux/kd.h> #include <linux/init.h> -#include <linux/slab.h> #include <linux/vt_kern.h> #include <linux/selection.h> #include <linux/spinlock.h> @@ -209,7 +208,7 @@ sisusbcon_init(struct vc_data *c, int init) struct sisusb_usb_data *sisusb; int cols, rows; - /* This is called by take_over_console(), + /* This is called by do_take_over_console(), * ie by us/under our control. It is * only called after text mode and fonts * are set up/restored. @@ -274,7 +273,7 @@ sisusbcon_deinit(struct vc_data *c) struct sisusb_usb_data *sisusb; int i; - /* This is called by take_over_console() + /* This is called by do_take_over_console() * and others, ie not under our control. */ @@ -1188,9 +1187,9 @@ sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot, * And so is the hi_font_mask. */ for (i = 0; i < MAX_NR_CONSOLES; i++) { - struct vc_data *c = vc_cons[i].d; - if (c && c->vc_sw == &sisusb_con) - c->vc_hi_font_mask = ch512 ? 0x0800 : 0; + struct vc_data *d = vc_cons[i].d; + if (d && d->vc_sw == &sisusb_con) + d->vc_hi_font_mask = ch512 ? 0x0800 : 0; } sisusb->current_font_512 = ch512; @@ -1250,7 +1249,7 @@ sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot, mutex_unlock(&sisusb->lock); if (dorecalc && c) { - int i, rows = c->vc_scan_lines / fh; + int rows = c->vc_scan_lines / fh; /* Now adjust our consoles' size */ @@ -1491,8 +1490,9 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) mutex_unlock(&sisusb->lock); /* Now grab the desired console(s) */ - ret = take_over_console(&sisusb_con, first - 1, last - 1, 0); - + console_lock(); + ret = do_take_over_console(&sisusb_con, first - 1, last - 1, 0); + console_unlock(); if (!ret) sisusb->haveconsole = 1; else { @@ -1536,11 +1536,14 @@ sisusb_console_exit(struct sisusb_usb_data *sisusb) if (sisusb->haveconsole) { for (i = 0; i < MAX_NR_CONSOLES; i++) - if (sisusb->havethisconsole[i]) - take_over_console(&sisusb_dummy_con, i, i, 0); + if (sisusb->havethisconsole[i]) { + console_lock(); + do_take_over_console(&sisusb_dummy_con, i, i, 0); + console_unlock(); /* At this point, con_deinit for all our - * consoles is executed by take_over_console(). + * consoles is executed by do_take_over_console(). */ + } sisusb->haveconsole = 0; } diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.c b/drivers/usb/misc/sisusbvga/sisusb_init.c index 0ab99074483..bf0032ca35e 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_init.c +++ b/drivers/usb/misc/sisusbvga/sisusb_init.c @@ -40,8 +40,6 @@ #include <linux/kernel.h> #include <linux/errno.h> #include <linux/poll.h> -#include <linux/init.h> -#include <linux/slab.h> #include <linux/spinlock.h> #include "sisusb.h" diff --git a/drivers/usb/misc/trancevibrator.c b/drivers/usb/misc/trancevibrator.c index 2e14102955c..4145314a515 100644 --- a/drivers/usb/misc/trancevibrator.c +++ b/drivers/usb/misc/trancevibrator.c @@ -21,7 +21,7 @@ /* Standard include files */ #include <linux/kernel.h> #include <linux/errno.h> -#include <linux/init.h> +#include <linux/slab.h> #include <linux/module.h> #include <linux/usb.h> @@ -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) }, { }, }; @@ -85,7 +85,7 @@ static ssize_t set_speed(struct device *dev, struct device_attribute *attr, return count; } -static DEVICE_ATTR(speed, S_IWUGO | S_IRUGO, show_speed, set_speed); +static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR, show_speed, set_speed); static int tv_probe(struct usb_interface *interface, const struct usb_device_id *id) @@ -136,26 +136,7 @@ static struct usb_driver tv_driver = { .id_table = id_table, }; -static int __init tv_init(void) -{ - int retval = usb_register(&tv_driver); - if (retval) { - err("usb_register failed. Error number %d", retval); - return retval; - } - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -} - -static void __exit tv_exit(void) -{ - usb_deregister(&tv_driver); -} - -module_init (tv_init); -module_exit (tv_exit); +module_usb_driver(tv_driver); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c new file mode 100644 index 00000000000..f43c61989ce --- /dev/null +++ b/drivers/usb/misc/usb3503.c @@ -0,0 +1,408 @@ +/* + * Driver for SMSC USB3503 USB 2.0 hub controller driver + * + * Copyright (c) 2012-2013 Dongjin Kim (tobetter@gmail.com) + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/clk.h> +#include <linux/i2c.h> +#include <linux/gpio.h> +#include <linux/delay.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/of_gpio.h> +#include <linux/platform_device.h> +#include <linux/platform_data/usb3503.h> +#include <linux/regmap.h> + +#define USB3503_VIDL 0x00 +#define USB3503_VIDM 0x01 +#define USB3503_PIDL 0x02 +#define USB3503_PIDM 0x03 +#define USB3503_DIDL 0x04 +#define USB3503_DIDM 0x05 + +#define USB3503_CFG1 0x06 +#define USB3503_SELF_BUS_PWR (1 << 7) + +#define USB3503_CFG2 0x07 +#define USB3503_CFG3 0x08 +#define USB3503_NRD 0x09 + +#define USB3503_PDS 0x0a + +#define USB3503_SP_ILOCK 0xe7 +#define USB3503_SPILOCK_CONNECT (1 << 1) +#define USB3503_SPILOCK_CONFIG (1 << 0) + +#define USB3503_CFGP 0xee +#define USB3503_CLKSUSP (1 << 7) + +#define USB3503_RESET 0xff + +struct usb3503 { + enum usb3503_mode mode; + struct regmap *regmap; + struct device *dev; + struct clk *clk; + u8 port_off_mask; + int gpio_intn; + int gpio_reset; + int gpio_connect; + bool secondary_ref_clk; +}; + +static int usb3503_reset(struct usb3503 *hub, int state) +{ + if (!state && gpio_is_valid(hub->gpio_connect)) + gpio_set_value_cansleep(hub->gpio_connect, 0); + + if (gpio_is_valid(hub->gpio_reset)) + gpio_set_value_cansleep(hub->gpio_reset, state); + + /* Wait T_HUBINIT == 4ms for hub logic to stabilize */ + if (state) + usleep_range(4000, 10000); + + return 0; +} + +static int usb3503_connect(struct usb3503 *hub) +{ + struct device *dev = hub->dev; + int err; + + usb3503_reset(hub, 1); + + if (hub->regmap) { + /* SP_ILOCK: set connect_n, config_n for config */ + err = regmap_write(hub->regmap, USB3503_SP_ILOCK, + (USB3503_SPILOCK_CONNECT + | USB3503_SPILOCK_CONFIG)); + if (err < 0) { + dev_err(dev, "SP_ILOCK failed (%d)\n", err); + return err; + } + + /* PDS : Disable For Self Powered Operation */ + if (hub->port_off_mask) { + err = regmap_update_bits(hub->regmap, USB3503_PDS, + hub->port_off_mask, + hub->port_off_mask); + if (err < 0) { + dev_err(dev, "PDS failed (%d)\n", err); + return err; + } + } + + /* CFG1 : SELF_BUS_PWR -> Self-Powerd operation */ + err = regmap_update_bits(hub->regmap, USB3503_CFG1, + USB3503_SELF_BUS_PWR, + USB3503_SELF_BUS_PWR); + if (err < 0) { + dev_err(dev, "CFG1 failed (%d)\n", err); + return err; + } + + /* SP_LOCK: clear connect_n, config_n for hub connect */ + err = regmap_update_bits(hub->regmap, USB3503_SP_ILOCK, + (USB3503_SPILOCK_CONNECT + | USB3503_SPILOCK_CONFIG), 0); + if (err < 0) { + dev_err(dev, "SP_ILOCK failed (%d)\n", err); + return err; + } + } + + if (gpio_is_valid(hub->gpio_connect)) + gpio_set_value_cansleep(hub->gpio_connect, 1); + + hub->mode = USB3503_MODE_HUB; + dev_info(dev, "switched to HUB mode\n"); + + return 0; +} + +static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode) +{ + struct device *dev = hub->dev; + int err = 0; + + switch (mode) { + case USB3503_MODE_HUB: + err = usb3503_connect(hub); + break; + + case USB3503_MODE_STANDBY: + usb3503_reset(hub, 0); + + hub->mode = mode; + dev_info(dev, "switched to STANDBY mode\n"); + break; + + default: + dev_err(dev, "unknown mode is requested\n"); + err = -EINVAL; + break; + } + + return err; +} + +static const struct regmap_config usb3503_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = USB3503_RESET, +}; + +static int usb3503_probe(struct usb3503 *hub) +{ + struct device *dev = hub->dev; + struct usb3503_platform_data *pdata = dev_get_platdata(dev); + struct device_node *np = dev->of_node; + int err; + u32 mode = USB3503_MODE_HUB; + const u32 *property; + int len; + + if (pdata) { + hub->port_off_mask = pdata->port_off_mask; + hub->gpio_intn = pdata->gpio_intn; + hub->gpio_connect = pdata->gpio_connect; + hub->gpio_reset = pdata->gpio_reset; + hub->mode = pdata->initial_mode; + } else if (np) { + struct clk *clk; + hub->port_off_mask = 0; + + clk = devm_clk_get(dev, "refclk"); + if (IS_ERR(clk) && PTR_ERR(clk) != -ENOENT) { + dev_err(dev, "unable to request refclk (%d)\n", err); + return PTR_ERR(clk); + } + + if (!IS_ERR(clk)) { + u32 rate = 0; + hub->clk = clk; + + if (!of_property_read_u32(np, "refclk-frequency", + &rate)) { + + switch (rate) { + case 38400000: + case 26000000: + case 19200000: + case 12000000: + hub->secondary_ref_clk = 0; + break; + case 24000000: + case 27000000: + case 25000000: + case 50000000: + hub->secondary_ref_clk = 1; + break; + default: + dev_err(dev, + "unsupported reference clock rate (%d)\n", + (int) rate); + return -EINVAL; + } + err = clk_set_rate(hub->clk, rate); + if (err) { + dev_err(dev, + "unable to set reference clock rate to %d\n", + (int) rate); + return err; + } + } + + err = clk_prepare_enable(hub->clk); + if (err) { + dev_err(dev, + "unable to enable reference clock\n"); + return err; + } + } + + property = of_get_property(np, "disabled-ports", &len); + if (property && (len / sizeof(u32)) > 0) { + int i; + for (i = 0; i < len / sizeof(u32); i++) { + u32 port = be32_to_cpu(property[i]); + if ((1 <= port) && (port <= 3)) + hub->port_off_mask |= (1 << port); + } + } + + hub->gpio_intn = of_get_named_gpio(np, "intn-gpios", 0); + if (hub->gpio_intn == -EPROBE_DEFER) + return -EPROBE_DEFER; + hub->gpio_connect = of_get_named_gpio(np, "connect-gpios", 0); + if (hub->gpio_connect == -EPROBE_DEFER) + return -EPROBE_DEFER; + hub->gpio_reset = of_get_named_gpio(np, "reset-gpios", 0); + if (hub->gpio_reset == -EPROBE_DEFER) + return -EPROBE_DEFER; + of_property_read_u32(np, "initial-mode", &mode); + hub->mode = mode; + } + + if (hub->port_off_mask && !hub->regmap) + dev_err(dev, "Ports disabled with no control interface\n"); + + if (gpio_is_valid(hub->gpio_intn)) { + int val = hub->secondary_ref_clk ? GPIOF_OUT_INIT_LOW : + GPIOF_OUT_INIT_HIGH; + err = devm_gpio_request_one(dev, hub->gpio_intn, val, + "usb3503 intn"); + if (err) { + dev_err(dev, + "unable to request GPIO %d as connect pin (%d)\n", + hub->gpio_intn, err); + return err; + } + } + + if (gpio_is_valid(hub->gpio_connect)) { + err = devm_gpio_request_one(dev, hub->gpio_connect, + GPIOF_OUT_INIT_LOW, "usb3503 connect"); + if (err) { + dev_err(dev, + "unable to request GPIO %d as connect pin (%d)\n", + hub->gpio_connect, err); + return err; + } + } + + if (gpio_is_valid(hub->gpio_reset)) { + err = devm_gpio_request_one(dev, hub->gpio_reset, + GPIOF_OUT_INIT_LOW, "usb3503 reset"); + if (err) { + dev_err(dev, + "unable to request GPIO %d as reset pin (%d)\n", + hub->gpio_reset, err); + return err; + } + } + + usb3503_switch_mode(hub, hub->mode); + + dev_info(dev, "%s: probed in %s mode\n", __func__, + (hub->mode == USB3503_MODE_HUB) ? "hub" : "standby"); + + return 0; +} + +static int usb3503_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct usb3503 *hub; + int err; + + hub = devm_kzalloc(&i2c->dev, sizeof(struct usb3503), GFP_KERNEL); + if (!hub) { + dev_err(&i2c->dev, "private data alloc fail\n"); + return -ENOMEM; + } + + i2c_set_clientdata(i2c, hub); + hub->regmap = devm_regmap_init_i2c(i2c, &usb3503_regmap_config); + if (IS_ERR(hub->regmap)) { + err = PTR_ERR(hub->regmap); + dev_err(&i2c->dev, "Failed to initialise regmap: %d\n", err); + return err; + } + hub->dev = &i2c->dev; + + return usb3503_probe(hub); +} + +static int usb3503_platform_probe(struct platform_device *pdev) +{ + struct usb3503 *hub; + + hub = devm_kzalloc(&pdev->dev, sizeof(struct usb3503), GFP_KERNEL); + if (!hub) { + dev_err(&pdev->dev, "private data alloc fail\n"); + return -ENOMEM; + } + hub->dev = &pdev->dev; + + return usb3503_probe(hub); +} + +static const struct i2c_device_id usb3503_id[] = { + { USB3503_I2C_NAME, 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, usb3503_id); + +#ifdef CONFIG_OF +static const struct of_device_id usb3503_of_match[] = { + { .compatible = "smsc,usb3503", }, + { .compatible = "smsc,usb3503a", }, + {}, +}; +MODULE_DEVICE_TABLE(of, usb3503_of_match); +#endif + +static struct i2c_driver usb3503_i2c_driver = { + .driver = { + .name = USB3503_I2C_NAME, + .of_match_table = of_match_ptr(usb3503_of_match), + }, + .probe = usb3503_i2c_probe, + .id_table = usb3503_id, +}; + +static struct platform_driver usb3503_platform_driver = { + .driver = { + .name = USB3503_I2C_NAME, + .of_match_table = of_match_ptr(usb3503_of_match), + .owner = THIS_MODULE, + }, + .probe = usb3503_platform_probe, +}; + +static int __init usb3503_init(void) +{ + int err; + + err = i2c_register_driver(THIS_MODULE, &usb3503_i2c_driver); + if (err != 0) + pr_err("usb3503: Failed to register I2C driver: %d\n", err); + + err = platform_driver_register(&usb3503_platform_driver); + if (err != 0) + pr_err("usb3503: Failed to register platform driver: %d\n", + err); + + return 0; +} +module_init(usb3503_init); + +static void __exit usb3503_exit(void) +{ + platform_driver_unregister(&usb3503_platform_driver); + i2c_del_driver(&usb3503_i2c_driver); +} +module_exit(usb3503_exit); + +MODULE_AUTHOR("Dongjin Kim <tobetter@gmail.com>"); +MODULE_DESCRIPTION("USB3503 USB HUB driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c index 4fb120357c5..1184390508e 100644 --- a/drivers/usb/misc/usblcd.c +++ b/drivers/usb/misc/usblcd.c @@ -14,12 +14,10 @@ *****************************************************************************/ #include <linux/module.h> #include <linux/kernel.h> -#include <linux/init.h> #include <linux/slab.h> -#include <linux/smp_lock.h> #include <linux/errno.h> #include <linux/mutex.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/usb.h> #define DRIVER_VERSION "USBLCD Driver Version 1.05" @@ -30,26 +28,34 @@ #define IOCTL_GET_DRV_VERSION 2 -static struct usb_device_id id_table [] = { +static DEFINE_MUTEX(lcd_mutex); +static const struct usb_device_id id_table[] = { { .idVendor = 0x10D2, .match_flags = USB_DEVICE_ID_MATCH_VENDOR, }, { }, }; -MODULE_DEVICE_TABLE (usb, id_table); +MODULE_DEVICE_TABLE(usb, id_table); static DEFINE_MUTEX(open_disc_mutex); struct usb_lcd { - struct usb_device * udev; /* init: probe_lcd */ - struct usb_interface * interface; /* the interface for this device */ - unsigned char * bulk_in_buffer; /* the buffer to receive data */ - size_t bulk_in_size; /* the size of the receive buffer */ - __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ - __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ + struct usb_device *udev; /* init: probe_lcd */ + struct usb_interface *interface; /* the interface for + this device */ + unsigned char *bulk_in_buffer; /* the buffer to receive + data */ + size_t bulk_in_size; /* the size of the + receive buffer */ + __u8 bulk_in_endpointAddr; /* the address of the + bulk in endpoint */ + __u8 bulk_out_endpointAddr; /* the address of the + bulk out endpoint */ struct kref kref; - struct semaphore limit_sem; /* to stop writes at full throttle from - * using up all RAM */ - struct usb_anchor submitted; /* URBs to wait for before suspend */ + struct semaphore limit_sem; /* to stop writes at + full throttle from + using up all RAM */ + struct usb_anchor submitted; /* URBs to wait for + before suspend */ }; #define to_lcd_dev(d) container_of(d, struct usb_lcd, kref) @@ -63,8 +69,8 @@ static void lcd_delete(struct kref *kref) struct usb_lcd *dev = to_lcd_dev(kref); usb_put_dev(dev->udev); - kfree (dev->bulk_in_buffer); - kfree (dev); + kfree(dev->bulk_in_buffer); + kfree(dev); } @@ -74,12 +80,14 @@ static int lcd_open(struct inode *inode, struct file *file) struct usb_interface *interface; int subminor, r; + mutex_lock(&lcd_mutex); subminor = iminor(inode); interface = usb_find_interface(&lcd_driver, subminor); if (!interface) { - err ("USBLCD: %s - error, can't find device for minor %d", - __func__, subminor); + mutex_unlock(&lcd_mutex); + printk(KERN_ERR "USBLCD: %s - error, can't find device for minor %d\n", + __func__, subminor); return -ENODEV; } @@ -87,6 +95,7 @@ static int lcd_open(struct inode *inode, struct file *file) dev = usb_get_intfdata(interface); if (!dev) { mutex_unlock(&open_disc_mutex); + mutex_unlock(&lcd_mutex); return -ENODEV; } @@ -98,11 +107,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); + mutex_unlock(&lcd_mutex); return r; } /* save our object in the file's private structure */ file->private_data = dev; + mutex_unlock(&lcd_mutex); return 0; } @@ -111,7 +122,7 @@ static int lcd_release(struct inode *inode, struct file *file) { struct usb_lcd *dev; - dev = (struct usb_lcd *)file->private_data; + dev = file->private_data; if (dev == NULL) return -ENODEV; @@ -121,17 +132,19 @@ static int lcd_release(struct inode *inode, struct file *file) return 0; } -static ssize_t lcd_read(struct file *file, char __user * buffer, size_t count, loff_t *ppos) +static ssize_t lcd_read(struct file *file, char __user * buffer, + size_t count, loff_t *ppos) { struct usb_lcd *dev; int retval = 0; int bytes_read; - dev = (struct usb_lcd *)file->private_data; + dev = file->private_data; /* do a blocking bulk read to get data from the device */ - retval = usb_bulk_msg(dev->udev, - usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr), + retval = usb_bulk_msg(dev->udev, + usb_rcvbulkpipe(dev->udev, + dev->bulk_in_endpointAddr), dev->bulk_in_buffer, min(dev->bulk_in_size, count), &bytes_read, 10000); @@ -153,26 +166,26 @@ static long lcd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) u16 bcdDevice; char buf[30]; - dev = (struct usb_lcd *)file->private_data; + dev = file->private_data; if (dev == NULL) return -ENODEV; - + switch (cmd) { case IOCTL_GET_HARD_VERSION: - lock_kernel(); + mutex_lock(&lcd_mutex); bcdDevice = le16_to_cpu((dev->udev)->descriptor.bcdDevice); - sprintf(buf,"%1d%1d.%1d%1d", + sprintf(buf, "%1d%1d.%1d%1d", (bcdDevice & 0xF000)>>12, (bcdDevice & 0xF00)>>8, (bcdDevice & 0xF0)>>4, (bcdDevice & 0xF)); - unlock_kernel(); - if (copy_to_user((void __user *)arg,buf,strlen(buf))!=0) + mutex_unlock(&lcd_mutex); + if (copy_to_user((void __user *)arg, buf, strlen(buf)) != 0) return -EFAULT; break; case IOCTL_GET_DRV_VERSION: - sprintf(buf,DRIVER_VERSION); - if (copy_to_user((void __user *)arg,buf,strlen(buf))!=0) + sprintf(buf, DRIVER_VERSION); + if (copy_to_user((void __user *)arg, buf, strlen(buf)) != 0) return -EFAULT; break; default: @@ -194,26 +207,27 @@ static void lcd_write_bulk_callback(struct urb *urb) if (status && !(status == -ENOENT || status == -ECONNRESET || - status == -ESHUTDOWN)) { - dbg("USBLCD: %s - nonzero write bulk status received: %d", - __func__, status); + status == -ESHUTDOWN)) { + dev_dbg(&dev->interface->dev, + "nonzero write bulk status received: %d\n", status); } /* free up our allocated buffer */ - usb_buffer_free(urb->dev, urb->transfer_buffer_length, - urb->transfer_buffer, urb->transfer_dma); + usb_free_coherent(urb->dev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); up(&dev->limit_sem); } -static ssize_t lcd_write(struct file *file, const char __user * user_buffer, size_t count, loff_t *ppos) +static ssize_t lcd_write(struct file *file, const char __user * user_buffer, + size_t count, loff_t *ppos) { struct usb_lcd *dev; - int retval = 0, r; + int retval = 0, r; struct urb *urb = NULL; char *buf = NULL; - - dev = (struct usb_lcd *)file->private_data; - + + dev = file->private_data; + /* verify that we actually have some data to write */ if (count == 0) goto exit; @@ -228,34 +242,39 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz retval = -ENOMEM; goto err_no_buf; } - - buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma); + + buf = usb_alloc_coherent(dev->udev, count, GFP_KERNEL, + &urb->transfer_dma); if (!buf) { retval = -ENOMEM; goto error; } - + if (copy_from_user(buf, user_buffer, count)) { retval = -EFAULT; goto error; } - + /* initialize the urb properly */ usb_fill_bulk_urb(urb, dev->udev, - usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), + usb_sndbulkpipe(dev->udev, + dev->bulk_out_endpointAddr), buf, count, lcd_write_bulk_callback, dev); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; usb_anchor_urb(urb, &dev->submitted); - + /* send the data out the bulk port */ retval = usb_submit_urb(urb, GFP_KERNEL); if (retval) { - err("USBLCD: %s - failed submitting write urb, error %d", __func__, retval); + dev_err(&dev->udev->dev, + "%s - failed submitting write urb, error %d\n", + __func__, retval); goto error_unanchor; } - - /* release our reference to this urb, the USB core will eventually free it entirely */ + + /* release our reference to this urb, + the USB core will eventually free it entirely */ usb_free_urb(urb); exit: @@ -263,7 +282,7 @@ exit: error_unanchor: usb_unanchor_urb(urb); error: - usb_buffer_free(dev->udev, count, buf, urb->transfer_dma); + usb_free_coherent(dev->udev, count, buf, urb->transfer_dma); usb_free_urb(urb); err_no_buf: up(&dev->limit_sem); @@ -271,12 +290,13 @@ err_no_buf: } static const struct file_operations lcd_fops = { - .owner = THIS_MODULE, - .read = lcd_read, - .write = lcd_write, - .open = lcd_open, + .owner = THIS_MODULE, + .read = lcd_read, + .write = lcd_write, + .open = lcd_open, .unlocked_ioctl = lcd_ioctl, - .release = lcd_release, + .release = lcd_release, + .llseek = noop_llseek, }; /* @@ -284,12 +304,13 @@ static const struct file_operations lcd_fops = { * and to have the device registered with the driver core */ static struct usb_class_driver lcd_class = { - .name = "lcd%d", - .fops = &lcd_fops, - .minor_base = USBLCD_MINOR, + .name = "lcd%d", + .fops = &lcd_fops, + .minor_base = USBLCD_MINOR, }; -static int lcd_probe(struct usb_interface *interface, const struct usb_device_id *id) +static int lcd_probe(struct usb_interface *interface, + const struct usb_device_id *id) { struct usb_lcd *dev = NULL; struct usb_host_interface *iface_desc; @@ -301,7 +322,7 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id /* allocate memory for our device state and initialize it */ dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { - err("Out of memory"); + dev_err(&interface->dev, "Out of memory\n"); goto error; } kref_init(&dev->kref); @@ -316,7 +337,7 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id retval = -ENODEV; goto error; } - + /* set up the endpoint information */ /* use only the first bulk-in and bulk-out endpoints */ iface_desc = interface->cur_altsetting; @@ -326,12 +347,13 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id if (!dev->bulk_in_endpointAddr && usb_endpoint_is_bulk_in(endpoint)) { /* we found a bulk in endpoint */ - buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); + buffer_size = usb_endpoint_maxp(endpoint); dev->bulk_in_size = buffer_size; dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); if (!dev->bulk_in_buffer) { - err("Could not allocate bulk_in_buffer"); + dev_err(&interface->dev, + "Could not allocate bulk_in_buffer\n"); goto error; } } @@ -343,7 +365,8 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id } } if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) { - err("Could not find both bulk-in and bulk-out endpoints"); + dev_err(&interface->dev, + "Could not find both bulk-in and bulk-out endpoints\n"); goto error; } @@ -354,7 +377,8 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id retval = usb_register_dev(interface, &lcd_class); if (retval) { /* something prevented us from registering this driver */ - err("Not able to get a minor for this device."); + dev_err(&interface->dev, + "Not able to get a minor for this device.\n"); usb_set_intfdata(interface, NULL); goto error; } @@ -363,7 +387,7 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id dev_info(&interface->dev, "USBLCD Version %1d%1d.%1d%1d found " "at address %d\n", (i & 0xF000)>>12, (i & 0xF00)>>8, - (i & 0xF0)>>4,(i & 0xF), dev->udev->devnum); + (i & 0xF0)>>4, (i & 0xF), dev->udev->devnum); /* let the user know what node this device is now attached to */ dev_info(&interface->dev, "USB LCD device now attached to USBLCD-%d\n", @@ -395,7 +419,7 @@ static int lcd_suspend(struct usb_interface *intf, pm_message_t message) return 0; } -static int lcd_resume (struct usb_interface *intf) +static int lcd_resume(struct usb_interface *intf) { return 0; } @@ -403,16 +427,16 @@ static int lcd_resume (struct usb_interface *intf) static void lcd_disconnect(struct usb_interface *interface) { struct usb_lcd *dev; - int minor = interface->minor; + int minor = interface->minor; mutex_lock(&open_disc_mutex); - dev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); + dev = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); mutex_unlock(&open_disc_mutex); - /* give back our minor */ - usb_deregister_dev(interface, &lcd_class); - + /* give back our minor */ + usb_deregister_dev(interface, &lcd_class); + /* decrement our usage count */ kref_put(&dev->kref, lcd_delete); @@ -429,25 +453,7 @@ static struct usb_driver lcd_driver = { .supports_autosuspend = 1, }; -static int __init usb_lcd_init(void) -{ - int result; - - result = usb_register(&lcd_driver); - if (result) - err("usb_register failed. Error number %d", result); - - return result; -} - - -static void __exit usb_lcd_exit(void) -{ - usb_deregister(&lcd_driver); -} - -module_init(usb_lcd_init); -module_exit(usb_lcd_exit); +module_usb_driver(lcd_driver); MODULE_AUTHOR("Georges Toth <g.toth@e-biz.lu>"); MODULE_DESCRIPTION(DRIVER_VERSION); diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c index 06cb71942dc..bdef0d6eb91 100644 --- a/drivers/usb/misc/usbled.c +++ b/drivers/usb/misc/usbled.c @@ -1,5 +1,5 @@ /* - * USB LED driver - 1.1 + * USB LED driver * * Copyright (C) 2004 Greg Kroah-Hartman (greg@kroah.com) * @@ -11,7 +11,6 @@ #include <linux/kernel.h> #include <linux/errno.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/usb.h> @@ -20,31 +19,57 @@ #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com" #define DRIVER_DESC "USB LED Driver" -#define VENDOR_ID 0x0fc5 -#define PRODUCT_ID 0x1223 +enum led_type { + DELCOM_VISUAL_SIGNAL_INDICATOR, + DREAM_CHEEKY_WEBMAIL_NOTIFIER, + RISO_KAGAKU_LED +}; + +/* the Webmail LED made by RISO KAGAKU CORP. decodes a color index + internally, we want to keep the red+green+blue sysfs api, so we decode + from 1-bit RGB to the riso kagaku color index according to this table... */ + +static unsigned const char riso_kagaku_tbl[] = { +/* R+2G+4B -> riso kagaku color index */ + [0] = 0, /* black */ + [1] = 2, /* red */ + [2] = 1, /* green */ + [3] = 5, /* yellow */ + [4] = 3, /* blue */ + [5] = 6, /* magenta */ + [6] = 4, /* cyan */ + [7] = 7 /* white */ +}; + +#define RISO_KAGAKU_IX(r,g,b) riso_kagaku_tbl[((r)?1:0)+((g)?2:0)+((b)?4:0)] /* table of devices that work with this driver */ -static struct usb_device_id id_table [] = { - { USB_DEVICE(VENDOR_ID, PRODUCT_ID) }, +static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x0fc5, 0x1223), + .driver_info = DELCOM_VISUAL_SIGNAL_INDICATOR }, + { USB_DEVICE(0x1d34, 0x0004), + .driver_info = DREAM_CHEEKY_WEBMAIL_NOTIFIER }, + { USB_DEVICE(0x1d34, 0x000a), + .driver_info = DREAM_CHEEKY_WEBMAIL_NOTIFIER }, + { USB_DEVICE(0x1294, 0x1320), + .driver_info = RISO_KAGAKU_LED }, { }, }; -MODULE_DEVICE_TABLE (usb, id_table); +MODULE_DEVICE_TABLE(usb, id_table); struct usb_led { - struct usb_device * udev; + struct usb_device *udev; unsigned char blue; unsigned char red; unsigned char green; + enum led_type type; }; -#define BLUE 0x04 -#define RED 0x02 -#define GREEN 0x01 static void change_color(struct usb_led *led) { - int retval; - unsigned char color = 0x07; + int retval = 0; unsigned char *buffer; + int actlength; buffer = kmalloc(8, GFP_KERNEL); if (!buffer) { @@ -52,39 +77,87 @@ static void change_color(struct usb_led *led) return; } - if (led->blue) - color &= ~(BLUE); - if (led->red) - color &= ~(RED); - if (led->green) - color &= ~(GREEN); - dev_dbg(&led->udev->dev, - "blue = %d, red = %d, green = %d, color = %.2x\n", - led->blue, led->red, led->green, color); - - retval = usb_control_msg(led->udev, - usb_sndctrlpipe(led->udev, 0), - 0x12, - 0xc8, - (0x02 * 0x100) + 0x0a, - (0x00 * 0x100) + color, - buffer, - 8, - 2000); + switch (led->type) { + case DELCOM_VISUAL_SIGNAL_INDICATOR: { + unsigned char color = 0x07; + + if (led->blue) + color &= ~0x04; + if (led->red) + color &= ~0x02; + if (led->green) + color &= ~0x01; + dev_dbg(&led->udev->dev, + "blue = %d, red = %d, green = %d, color = %.2x\n", + led->blue, led->red, led->green, color); + + retval = usb_control_msg(led->udev, + usb_sndctrlpipe(led->udev, 0), + 0x12, + 0xc8, + (0x02 * 0x100) + 0x0a, + (0x00 * 0x100) + color, + buffer, + 8, + 2000); + break; + } + + case DREAM_CHEEKY_WEBMAIL_NOTIFIER: + dev_dbg(&led->udev->dev, + "red = %d, green = %d, blue = %d\n", + led->red, led->green, led->blue); + + buffer[0] = led->red; + buffer[1] = led->green; + buffer[2] = led->blue; + buffer[3] = buffer[4] = buffer[5] = 0; + buffer[6] = 0x1a; + buffer[7] = 0x05; + + retval = usb_control_msg(led->udev, + usb_sndctrlpipe(led->udev, 0), + 0x09, + 0x21, + 0x200, + 0, + buffer, + 8, + 2000); + break; + + case RISO_KAGAKU_LED: + buffer[0] = RISO_KAGAKU_IX(led->red, led->green, led->blue); + buffer[1] = 0; + buffer[2] = 0; + buffer[3] = 0; + buffer[4] = 0; + + retval = usb_interrupt_msg(led->udev, + usb_sndctrlpipe(led->udev, 2), + buffer, 5, &actlength, 1000 /*ms timeout*/); + break; + + default: + dev_err(&led->udev->dev, "unknown device type %d\n", led->type); + } + if (retval) dev_dbg(&led->udev->dev, "retval = %d\n", retval); kfree(buffer); } #define show_set(value) \ -static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ +static ssize_t show_##value(struct device *dev, struct device_attribute *attr,\ + char *buf) \ { \ struct usb_interface *intf = to_usb_interface(dev); \ struct usb_led *led = usb_get_intfdata(intf); \ \ return sprintf(buf, "%d\n", led->value); \ } \ -static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ +static ssize_t set_##value(struct device *dev, struct device_attribute *attr,\ + const char *buf, size_t count) \ { \ struct usb_interface *intf = to_usb_interface(dev); \ struct usb_led *led = usb_get_intfdata(intf); \ @@ -94,12 +167,13 @@ static ssize_t set_##value(struct device *dev, struct device_attribute *attr, co change_color(led); \ return count; \ } \ -static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value); +static DEVICE_ATTR(value, S_IRUGO | S_IWUSR, show_##value, set_##value); show_set(blue); show_set(red); show_set(green); -static int led_probe(struct usb_interface *interface, const struct usb_device_id *id) +static int led_probe(struct usb_interface *interface, + const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev(interface); struct usb_led *dev = NULL; @@ -107,13 +181,14 @@ static int led_probe(struct usb_interface *interface, const struct usb_device_id dev = kzalloc(sizeof(struct usb_led), GFP_KERNEL); if (dev == NULL) { - dev_err(&interface->dev, "Out of memory\n"); + dev_err(&interface->dev, "out of memory\n"); goto error_mem; } dev->udev = usb_get_dev(udev); + dev->type = id->driver_info; - usb_set_intfdata (interface, dev); + usb_set_intfdata(interface, dev); retval = device_create_file(&interface->dev, &dev_attr_blue); if (retval) @@ -125,6 +200,31 @@ static int led_probe(struct usb_interface *interface, const struct usb_device_id if (retval) goto error; + if (dev->type == DREAM_CHEEKY_WEBMAIL_NOTIFIER) { + unsigned char *enable; + + enable = kmemdup("\x1f\x02\0\x5f\0\0\x1a\x03", 8, GFP_KERNEL); + if (!enable) { + dev_err(&interface->dev, "out of memory\n"); + retval = -ENOMEM; + goto error; + } + + retval = usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + 0x09, + 0x21, + 0x200, + 0, + enable, + 8, + 2000); + + kfree(enable); + if (retval != 8) + goto error; + } + dev_info(&interface->dev, "USB LED device now attached\n"); return 0; @@ -132,7 +232,7 @@ error: device_remove_file(&interface->dev, &dev_attr_blue); device_remove_file(&interface->dev, &dev_attr_red); device_remove_file(&interface->dev, &dev_attr_green); - usb_set_intfdata (interface, NULL); + usb_set_intfdata(interface, NULL); usb_put_dev(dev->udev); kfree(dev); error_mem: @@ -143,14 +243,14 @@ static void led_disconnect(struct usb_interface *interface) { struct usb_led *dev; - dev = usb_get_intfdata (interface); + dev = usb_get_intfdata(interface); device_remove_file(&interface->dev, &dev_attr_blue); device_remove_file(&interface->dev, &dev_attr_red); device_remove_file(&interface->dev, &dev_attr_green); /* first remove the files, then set the pointer to NULL */ - usb_set_intfdata (interface, NULL); + usb_set_intfdata(interface, NULL); usb_put_dev(dev->udev); @@ -166,23 +266,7 @@ static struct usb_driver led_driver = { .id_table = id_table, }; -static int __init usb_led_init(void) -{ - int retval = 0; - - retval = usb_register(&led_driver); - if (retval) - err("usb_register failed. Error number %d", retval); - return retval; -} - -static void __exit usb_led_exit(void) -{ - usb_deregister(&led_driver); -} - -module_init (usb_led_init); -module_exit (usb_led_exit); +module_usb_driver(led_driver); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/misc/usbsevseg.c b/drivers/usb/misc/usbsevseg.c index 3db255537e7..1fe6b73c22f 100644 --- a/drivers/usb/misc/usbsevseg.c +++ b/drivers/usb/misc/usbsevseg.c @@ -12,7 +12,6 @@ #include <linux/kernel.h> #include <linux/errno.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/string.h> @@ -24,10 +23,10 @@ #define VENDOR_ID 0x0fc5 #define PRODUCT_ID 0x1227 -#define MAXLEN 6 +#define MAXLEN 8 /* 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) }, { }, }; @@ -49,6 +48,7 @@ struct usb_sevsegdev { u16 textlength; u8 shadow_power; /* for PM */ + u8 has_interface_pm; }; /* sysfs_streq can't replace this completely @@ -56,7 +56,7 @@ struct usb_sevsegdev { * if str commands are used, we would assume the end of string * so mem commands are used. */ -inline size_t my_memlen(const char *buf, size_t count) +static inline size_t my_memlen(const char *buf, size_t count) { if (count > 0 && buf[count-1] == '\n') return count - 1; @@ -68,12 +68,16 @@ static void update_display_powered(struct usb_sevsegdev *mydev) { int rc; - if (!mydev->shadow_power && mydev->powered) { + if (mydev->powered && !mydev->has_interface_pm) { rc = usb_autopm_get_interface(mydev->intf); if (rc < 0) return; + mydev->has_interface_pm = 1; } + if (mydev->shadow_power != 1) + return; + rc = usb_control_msg(mydev->udev, usb_sndctrlpipe(mydev->udev, 0), 0x12, @@ -86,8 +90,10 @@ static void update_display_powered(struct usb_sevsegdev *mydev) if (rc < 0) dev_dbg(&mydev->udev->dev, "power retval = %d\n", rc); - if (mydev->shadow_power && !mydev->powered) + if (!mydev->powered && mydev->has_interface_pm) { usb_autopm_put_interface(mydev->intf); + mydev->has_interface_pm = 0; + } } static void update_display_mode(struct usb_sevsegdev *mydev) @@ -185,7 +191,7 @@ static ssize_t set_attr_##name(struct device *dev, \ \ return count; \ } \ -static DEVICE_ATTR(name, S_IWUGO | S_IRUGO, show_attr_##name, set_attr_##name); +static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_attr_##name, set_attr_##name); static ssize_t show_attr_text(struct device *dev, struct device_attribute *attr, char *buf) @@ -216,7 +222,7 @@ static ssize_t set_attr_text(struct device *dev, return count; } -static DEVICE_ATTR(text, S_IWUGO | S_IRUGO, show_attr_text, set_attr_text); +static DEVICE_ATTR(text, S_IRUGO | S_IWUSR, show_attr_text, set_attr_text); static ssize_t show_attr_decimals(struct device *dev, struct device_attribute *attr, char *buf) @@ -265,8 +271,7 @@ static ssize_t set_attr_decimals(struct device *dev, return count; } -static DEVICE_ATTR(decimals, S_IWUGO | S_IRUGO, - show_attr_decimals, set_attr_decimals); +static DEVICE_ATTR(decimals, S_IRUGO | S_IWUSR, show_attr_decimals, set_attr_decimals); static ssize_t show_attr_textmode(struct device *dev, struct device_attribute *attr, char *buf) @@ -312,8 +317,7 @@ static ssize_t set_attr_textmode(struct device *dev, return -EINVAL; } -static DEVICE_ATTR(textmode, S_IWUGO | S_IRUGO, - show_attr_textmode, set_attr_textmode); +static DEVICE_ATTR(textmode, S_IRUGO | S_IWUSR, show_attr_textmode, set_attr_textmode); MYDEV_ATTR_SIMPLE_UNSIGNED(powered, update_display_powered); @@ -351,6 +355,10 @@ static int sevseg_probe(struct usb_interface *interface, mydev->intf = interface; usb_set_intfdata(interface, mydev); + /* PM */ + mydev->shadow_power = 1; /* currently active */ + mydev->has_interface_pm = 0; /* have not issued autopm_get */ + /*set defaults */ mydev->textmode = 0x02; /* ascii mode */ mydev->mode_msb = 0x06; /* 6 characters */ @@ -428,23 +436,7 @@ static struct usb_driver sevseg_driver = { .supports_autosuspend = 1, }; -static int __init usb_sevseg_init(void) -{ - int rc = 0; - - rc = usb_register(&sevseg_driver); - if (rc) - err("usb_register failed. Error number %d", rc); - return rc; -} - -static void __exit usb_sevseg_exit(void) -{ - usb_deregister(&sevseg_driver); -} - -module_init(usb_sevseg_init); -module_exit(usb_sevseg_exit); +module_usb_driver(sevseg_driver); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 3dab0c0b196..829f446064e 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -7,23 +7,29 @@ #include <linux/moduleparam.h> #include <linux/scatterlist.h> #include <linux/mutex.h> - +#include <linux/timer.h> #include <linux/usb.h> +#define SIMPLE_IO_TIMEOUT 10000 /* in milliseconds */ + +/*-------------------------------------------------------------------------*/ + +static int override_alt = -1; +module_param_named(alt, override_alt, int, 0644); +MODULE_PARM_DESC(alt, ">= 0 to override altsetting selection"); /*-------------------------------------------------------------------------*/ -// FIXME make these public somewhere; usbdevfs.h? -// +/* FIXME make these public somewhere; usbdevfs.h? */ struct usbtest_param { - // inputs + /* inputs */ unsigned test_num; /* 0..(TEST_CASES-1) */ unsigned iterations; unsigned length; unsigned vary; unsigned sglen; - // outputs + /* outputs */ struct timeval duration; }; #define USBTEST_REQUEST _IOWR('U', 100, struct usbtest_param) @@ -45,9 +51,9 @@ struct usbtest_info { const char *name; u8 ep_in; /* bulk/intr source */ u8 ep_out; /* bulk/intr sink */ - unsigned autoconf : 1; - unsigned ctrl_out : 1; - unsigned iso : 1; /* try iso in/out */ + unsigned autoconf:1; + unsigned ctrl_out:1; + unsigned iso:1; /* try iso in/out */ int alt; }; @@ -71,9 +77,9 @@ struct usbtest_dev { u8 *buf; }; -static struct usb_device *testdev_to_usbdev (struct usbtest_dev *test) +static struct usb_device *testdev_to_usbdev(struct usbtest_dev *test) { - return interface_to_usbdev (test->intf); + return interface_to_usbdev(test->intf); } /* set up all urbs so they can be used with either bulk or interrupt */ @@ -84,10 +90,12 @@ static struct usb_device *testdev_to_usbdev (struct usbtest_dev *test) #define WARNING(tdev, fmt, args...) \ dev_warn(&(tdev)->intf->dev , fmt , ## args) +#define GUARD_BYTE 0xA5 + /*-------------------------------------------------------------------------*/ static int -get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf) +get_endpoints(struct usbtest_dev *dev, struct usb_interface *intf) { int tmp; struct usb_host_interface *alt; @@ -102,20 +110,24 @@ get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf) iso_in = iso_out = NULL; alt = intf->altsetting + tmp; + if (override_alt >= 0 && + override_alt != alt->desc.bAlternateSetting) + continue; + /* take the first altsetting with in-bulk + out-bulk; - * ignore other endpoints and altsetttings. + * ignore other endpoints and altsettings. */ for (ep = 0; ep < alt->desc.bNumEndpoints; ep++) { struct usb_host_endpoint *e; e = alt->endpoint + ep; - switch (e->desc.bmAttributes) { + switch (usb_endpoint_type(&e->desc)) { case USB_ENDPOINT_XFER_BULK: break; case USB_ENDPOINT_XFER_ISOC: if (dev->info->iso) goto try_iso; - // FALLTHROUGH + /* FALLTHROUGH */ default: continue; } @@ -136,15 +148,16 @@ try_iso: iso_out = e; } } - if ((in && out) || (iso_in && iso_out)) + if ((in && out) || iso_in || iso_out) goto found; } return -EINVAL; found: - udev = testdev_to_usbdev (dev); + udev = testdev_to_usbdev(dev); + dev->info->alt = alt->desc.bAlternateSetting; if (alt->desc.bAlternateSetting != 0) { - tmp = usb_set_interface (udev, + tmp = usb_set_interface(udev, alt->desc.bInterfaceNumber, alt->desc.bAlternateSetting); if (tmp < 0) @@ -152,18 +165,21 @@ found: } if (in) { - dev->in_pipe = usb_rcvbulkpipe (udev, + dev->in_pipe = usb_rcvbulkpipe(udev, in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); - dev->out_pipe = usb_sndbulkpipe (udev, + dev->out_pipe = usb_sndbulkpipe(udev, out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); } if (iso_in) { dev->iso_in = &iso_in->desc; - dev->in_iso_pipe = usb_rcvisocpipe (udev, + dev->in_iso_pipe = usb_rcvisocpipe(udev, iso_in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + } + + if (iso_out) { dev->iso_out = &iso_out->desc; - dev->out_iso_pipe = usb_sndisocpipe (udev, + dev->out_iso_pipe = usb_sndisocpipe(udev, iso_out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); } @@ -179,45 +195,73 @@ found: * them with non-zero test data (or test for it) when appropriate. */ -static void simple_callback (struct urb *urb) +static void simple_callback(struct urb *urb) { complete(urb->context); } -static struct urb *simple_alloc_urb ( +static struct urb *usbtest_alloc_urb( struct usb_device *udev, int pipe, - unsigned long bytes -) + unsigned long bytes, + unsigned transfer_flags, + unsigned offset) { struct urb *urb; - urb = usb_alloc_urb (0, GFP_KERNEL); + urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) return urb; - usb_fill_bulk_urb (urb, udev, pipe, NULL, bytes, simple_callback, NULL); + usb_fill_bulk_urb(urb, udev, pipe, NULL, bytes, simple_callback, NULL); urb->interval = (udev->speed == USB_SPEED_HIGH) ? (INTERRUPT_RATE << 3) : INTERRUPT_RATE; - urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; - if (usb_pipein (pipe)) + urb->transfer_flags = transfer_flags; + if (usb_pipein(pipe)) urb->transfer_flags |= URB_SHORT_NOT_OK; - urb->transfer_buffer = usb_buffer_alloc (udev, bytes, GFP_KERNEL, - &urb->transfer_dma); + + if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) + urb->transfer_buffer = usb_alloc_coherent(udev, bytes + offset, + GFP_KERNEL, &urb->transfer_dma); + else + urb->transfer_buffer = kmalloc(bytes + offset, GFP_KERNEL); + if (!urb->transfer_buffer) { - usb_free_urb (urb); - urb = NULL; - } else - memset (urb->transfer_buffer, 0, bytes); + usb_free_urb(urb); + return NULL; + } + + /* To test unaligned transfers add an offset and fill the + unused memory with a guard value */ + if (offset) { + memset(urb->transfer_buffer, GUARD_BYTE, offset); + urb->transfer_buffer += offset; + if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) + urb->transfer_dma += offset; + } + + /* For inbound transfers use guard byte so that test fails if + data not correctly copied */ + memset(urb->transfer_buffer, + usb_pipein(urb->pipe) ? GUARD_BYTE : 0, + bytes); return urb; } -static unsigned pattern = 0; +static struct urb *simple_alloc_urb( + struct usb_device *udev, + int pipe, + unsigned long bytes) +{ + return usbtest_alloc_urb(udev, pipe, bytes, URB_NO_TRANSFER_DMA_MAP, 0); +} + +static unsigned pattern; static unsigned mod_pattern; module_param_named(pattern, mod_pattern, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(mod_pattern, "i/o pattern (0 == zeroes)"); -static inline void simple_fill_buf (struct urb *urb) +static inline void simple_fill_buf(struct urb *urb) { unsigned i; u8 *buf = urb->transfer_buffer; @@ -225,9 +269,9 @@ static inline void simple_fill_buf (struct urb *urb) switch (pattern) { default: - // FALLTHROUGH + /* FALLTHROUGH */ case 0: - memset (buf, 0, len); + memset(buf, 0, len); break; case 1: /* mod63 */ for (i = 0; i < len; i++) @@ -236,13 +280,38 @@ static inline void simple_fill_buf (struct urb *urb) } } -static inline int simple_check_buf(struct usbtest_dev *tdev, struct urb *urb) +static inline unsigned long buffer_offset(void *buf) +{ + return (unsigned long)buf & (ARCH_KMALLOC_MINALIGN - 1); +} + +static int check_guard_bytes(struct usbtest_dev *tdev, struct urb *urb) +{ + u8 *buf = urb->transfer_buffer; + u8 *guard = buf - buffer_offset(buf); + unsigned i; + + for (i = 0; guard < buf; i++, guard++) { + if (*guard != GUARD_BYTE) { + ERROR(tdev, "guard byte[%d] %d (not %d)\n", + i, *guard, GUARD_BYTE); + return -EINVAL; + } + } + return 0; +} + +static int simple_check_buf(struct usbtest_dev *tdev, struct urb *urb) { unsigned i; u8 expected; u8 *buf = urb->transfer_buffer; unsigned len = urb->actual_length; + int ret = check_guard_bytes(tdev, urb); + if (ret) + return ret; + for (i = 0; i < len; i++, buf++) { switch (pattern) { /* all-zeroes has no synchronization issues */ @@ -270,14 +339,22 @@ static inline int simple_check_buf(struct usbtest_dev *tdev, struct urb *urb) return 0; } -static void simple_free_urb (struct urb *urb) +static void simple_free_urb(struct urb *urb) { - usb_buffer_free (urb->dev, urb->transfer_buffer_length, - urb->transfer_buffer, urb->transfer_dma); - usb_free_urb (urb); + unsigned long offset = buffer_offset(urb->transfer_buffer); + + if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) + usb_free_coherent( + urb->dev, + urb->transfer_buffer_length + offset, + urb->transfer_buffer - offset, + urb->transfer_dma - offset); + else + kfree(urb->transfer_buffer - offset); + usb_free_urb(urb); } -static int simple_io ( +static int simple_io( struct usbtest_dev *tdev, struct urb *urb, int iterations, @@ -290,20 +367,30 @@ static int simple_io ( int max = urb->transfer_buffer_length; struct completion completion; int retval = 0; + unsigned long expire; urb->context = &completion; while (retval == 0 && iterations-- > 0) { - init_completion (&completion); - if (usb_pipeout (urb->pipe)) - simple_fill_buf (urb); - if ((retval = usb_submit_urb (urb, GFP_KERNEL)) != 0) + init_completion(&completion); + if (usb_pipeout(urb->pipe)) { + simple_fill_buf(urb); + urb->transfer_flags |= URB_ZERO_PACKET; + } + retval = usb_submit_urb(urb, GFP_KERNEL); + if (retval != 0) break; - /* NOTE: no timeouts; can't be broken out of by interrupt */ - wait_for_completion (&completion); - retval = urb->status; + expire = msecs_to_jiffies(SIMPLE_IO_TIMEOUT); + if (!wait_for_completion_timeout(&completion, expire)) { + usb_kill_urb(urb); + retval = (urb->status == -ENOENT ? + -ETIMEDOUT : urb->status); + } else { + retval = urb->status; + } + urb->dev = udev; - if (retval == 0 && usb_pipein (urb->pipe)) + if (retval == 0 && usb_pipein(urb->pipe)) retval = simple_check_buf(tdev, urb); if (vary) { @@ -334,7 +421,7 @@ static int simple_io ( * Yes, this also tests the scatterlist primitives. */ -static void free_sglist (struct scatterlist *sg, int nents) +static void free_sglist(struct scatterlist *sg, int nents) { unsigned i; @@ -343,19 +430,22 @@ static void free_sglist (struct scatterlist *sg, int nents) for (i = 0; i < nents; i++) { if (!sg_page(&sg[i])) continue; - kfree (sg_virt(&sg[i])); + kfree(sg_virt(&sg[i])); } - kfree (sg); + kfree(sg); } static struct scatterlist * -alloc_sglist (int nents, int max, int vary) +alloc_sglist(int nents, int max, int vary) { struct scatterlist *sg; unsigned i; unsigned size = max; - sg = kmalloc (nents * sizeof *sg, GFP_KERNEL); + if (max == 0) + return NULL; + + sg = kmalloc_array(nents, sizeof(*sg), GFP_KERNEL); if (!sg) return NULL; sg_init_table(sg, nents); @@ -364,9 +454,9 @@ alloc_sglist (int nents, int max, int vary) char *buf; unsigned j; - buf = kzalloc (size, GFP_KERNEL); + buf = kzalloc(size, GFP_KERNEL); if (!buf) { - free_sglist (sg, i); + free_sglist(sg, i); return NULL; } @@ -394,7 +484,15 @@ alloc_sglist (int nents, int max, int vary) return sg; } -static int perform_sglist ( +static void sg_timeout(unsigned long _req) +{ + struct usb_sg_request *req = (struct usb_sg_request *) _req; + + req->status = -ETIMEDOUT; + usb_sg_cancel(req); +} + +static int perform_sglist( struct usbtest_dev *tdev, unsigned iterations, int pipe, @@ -405,9 +503,12 @@ static int perform_sglist ( { struct usb_device *udev = testdev_to_usbdev(tdev); int retval = 0; + struct timer_list sg_timer; + + setup_timer_on_stack(&sg_timer, sg_timeout, (unsigned long) req); while (retval == 0 && iterations-- > 0) { - retval = usb_sg_init (req, udev, pipe, + retval = usb_sg_init(req, udev, pipe, (udev->speed == USB_SPEED_HIGH) ? (INTERRUPT_RATE << 3) : INTERRUPT_RATE, @@ -415,7 +516,10 @@ static int perform_sglist ( if (retval) break; - usb_sg_wait (req); + mod_timer(&sg_timer, jiffies + + msecs_to_jiffies(SIMPLE_IO_TIMEOUT)); + usb_sg_wait(req); + del_timer_sync(&sg_timer); retval = req->status; /* FIXME check resulting data pattern */ @@ -423,9 +527,9 @@ static int perform_sglist ( /* FIXME if endpoint halted, clear halt (and log) */ } - // FIXME for unlink or fault handling tests, don't report - // failure if retval is as we expected ... - + /* FIXME for unlink or fault handling tests, don't report + * failure if retval is as we expected ... + */ if (retval) ERROR(tdev, "perform_sglist failed, " "iterations left %d, status %d\n", @@ -449,31 +553,31 @@ static int perform_sglist ( */ static unsigned realworld = 1; -module_param (realworld, uint, 0); -MODULE_PARM_DESC (realworld, "clear to demand stricter spec compliance"); +module_param(realworld, uint, 0); +MODULE_PARM_DESC(realworld, "clear to demand stricter spec compliance"); -static int get_altsetting (struct usbtest_dev *dev) +static int get_altsetting(struct usbtest_dev *dev) { struct usb_interface *iface = dev->intf; - struct usb_device *udev = interface_to_usbdev (iface); + struct usb_device *udev = interface_to_usbdev(iface); int retval; - retval = usb_control_msg (udev, usb_rcvctrlpipe (udev, 0), + retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), USB_REQ_GET_INTERFACE, USB_DIR_IN|USB_RECIP_INTERFACE, - 0, iface->altsetting [0].desc.bInterfaceNumber, + 0, iface->altsetting[0].desc.bInterfaceNumber, dev->buf, 1, USB_CTRL_GET_TIMEOUT); switch (retval) { case 1: - return dev->buf [0]; + return dev->buf[0]; case 0: retval = -ERANGE; - // FALLTHROUGH + /* FALLTHROUGH */ default: return retval; } } -static int set_altsetting (struct usbtest_dev *dev, int alternate) +static int set_altsetting(struct usbtest_dev *dev, int alternate) { struct usb_interface *iface = dev->intf; struct usb_device *udev; @@ -481,9 +585,9 @@ static int set_altsetting (struct usbtest_dev *dev, int alternate) if (alternate < 0 || alternate >= 256) return -EINVAL; - udev = interface_to_usbdev (iface); - return usb_set_interface (udev, - iface->altsetting [0].desc.bInterfaceNumber, + udev = interface_to_usbdev(iface); + return usb_set_interface(udev, + iface->altsetting[0].desc.bInterfaceNumber, alternate); } @@ -491,7 +595,7 @@ static int is_good_config(struct usbtest_dev *tdev, int len) { struct usb_config_descriptor *config; - if (len < sizeof *config) + if (len < sizeof(*config)) return 0; config = (struct usb_config_descriptor *) tdev->buf; @@ -516,14 +620,84 @@ static int is_good_config(struct usbtest_dev *tdev, int len) return 0; } - if (le16_to_cpu(config->wTotalLength) == len) /* read it all */ + if (le16_to_cpu(config->wTotalLength) == len) /* read it all */ return 1; - if (le16_to_cpu(config->wTotalLength) >= TBUF_SIZE) /* max partial read */ + if (le16_to_cpu(config->wTotalLength) >= TBUF_SIZE) /* max partial read */ return 1; ERROR(tdev, "bogus config descriptor read size\n"); return 0; } +static int is_good_ext(struct usbtest_dev *tdev, u8 *buf) +{ + struct usb_ext_cap_descriptor *ext; + u32 attr; + + ext = (struct usb_ext_cap_descriptor *) buf; + + if (ext->bLength != USB_DT_USB_EXT_CAP_SIZE) { + ERROR(tdev, "bogus usb 2.0 extension descriptor length\n"); + return 0; + } + + attr = le32_to_cpu(ext->bmAttributes); + /* bits[1:15] is used and others are reserved */ + if (attr & ~0xfffe) { /* reserved == 0 */ + ERROR(tdev, "reserved bits set\n"); + return 0; + } + + return 1; +} + +static int is_good_ss_cap(struct usbtest_dev *tdev, u8 *buf) +{ + struct usb_ss_cap_descriptor *ss; + + ss = (struct usb_ss_cap_descriptor *) buf; + + if (ss->bLength != USB_DT_USB_SS_CAP_SIZE) { + ERROR(tdev, "bogus superspeed device capability descriptor length\n"); + return 0; + } + + /* + * only bit[1] of bmAttributes is used for LTM and others are + * reserved + */ + if (ss->bmAttributes & ~0x02) { /* reserved == 0 */ + ERROR(tdev, "reserved bits set in bmAttributes\n"); + return 0; + } + + /* bits[0:3] of wSpeedSupported is used and others are reserved */ + if (le16_to_cpu(ss->wSpeedSupported) & ~0x0f) { /* reserved == 0 */ + ERROR(tdev, "reserved bits set in wSpeedSupported\n"); + return 0; + } + + return 1; +} + +static int is_good_con_id(struct usbtest_dev *tdev, u8 *buf) +{ + struct usb_ss_container_id_descriptor *con_id; + + con_id = (struct usb_ss_container_id_descriptor *) buf; + + if (con_id->bLength != USB_DT_USB_SS_CONTN_ID_SIZE) { + ERROR(tdev, "bogus container id descriptor length\n"); + return 0; + } + + if (con_id->bReserved) { /* reserved == 0 */ + ERROR(tdev, "reserved bits set\n"); + return 0; + } + + return 1; +} + /* sanity test for standard requests working with usb_control_mesg() and some * of the utility functions which use it. * @@ -539,10 +713,10 @@ static int is_good_config(struct usbtest_dev *tdev, int len) * to see if usbcore, hcd, and device all behave right. such testing would * involve varied read sizes and other operation sequences. */ -static int ch9_postconfig (struct usbtest_dev *dev) +static int ch9_postconfig(struct usbtest_dev *dev) { struct usb_interface *iface = dev->intf; - struct usb_device *udev = interface_to_usbdev (iface); + struct usb_device *udev = interface_to_usbdev(iface); int i, alt, retval; /* [9.2.3] if there's more than one altsetting, we need to be able to @@ -551,7 +725,7 @@ static int ch9_postconfig (struct usbtest_dev *dev) for (i = 0; i < iface->num_altsetting; i++) { /* 9.2.3 constrains the range here */ - alt = iface->altsetting [i].desc.bAlternateSetting; + alt = iface->altsetting[i].desc.bAlternateSetting; if (alt < 0 || alt >= iface->num_altsetting) { dev_err(&iface->dev, "invalid alt [%d].bAltSetting = %d\n", @@ -563,7 +737,7 @@ static int ch9_postconfig (struct usbtest_dev *dev) continue; /* [9.4.10] set_interface */ - retval = set_altsetting (dev, alt); + retval = set_altsetting(dev, alt); if (retval) { dev_err(&iface->dev, "can't set_interface = %d, %d\n", alt, retval); @@ -571,7 +745,7 @@ static int ch9_postconfig (struct usbtest_dev *dev) } /* [9.4.4] get_interface always works */ - retval = get_altsetting (dev); + retval = get_altsetting(dev); if (retval != alt) { dev_err(&iface->dev, "get alt should be %d, was %d\n", alt, retval); @@ -588,11 +762,11 @@ static int ch9_postconfig (struct usbtest_dev *dev) * ... although some cheap devices (like one TI Hub I've got) * won't return config descriptors except before set_config. */ - retval = usb_control_msg (udev, usb_rcvctrlpipe (udev, 0), + retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), USB_REQ_GET_CONFIGURATION, USB_DIR_IN | USB_RECIP_DEVICE, 0, 0, dev->buf, 1, USB_CTRL_GET_TIMEOUT); - if (retval != 1 || dev->buf [0] != expected) { + if (retval != 1 || dev->buf[0] != expected) { dev_err(&iface->dev, "get config --> %d %d (1 %d)\n", retval, dev->buf[0], expected); return (retval < 0) ? retval : -EDOM; @@ -600,16 +774,100 @@ static int ch9_postconfig (struct usbtest_dev *dev) } /* there's always [9.4.3] a device descriptor [9.6.1] */ - retval = usb_get_descriptor (udev, USB_DT_DEVICE, 0, - dev->buf, sizeof udev->descriptor); - if (retval != sizeof udev->descriptor) { + retval = usb_get_descriptor(udev, USB_DT_DEVICE, 0, + dev->buf, sizeof(udev->descriptor)); + if (retval != sizeof(udev->descriptor)) { dev_err(&iface->dev, "dev descriptor --> %d\n", retval); return (retval < 0) ? retval : -EDOM; } + /* + * there's always [9.4.3] a bos device descriptor [9.6.2] in USB + * 3.0 spec + */ + if (le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0210) { + struct usb_bos_descriptor *bos = NULL; + struct usb_dev_cap_header *header = NULL; + unsigned total, num, length; + u8 *buf; + + retval = usb_get_descriptor(udev, USB_DT_BOS, 0, dev->buf, + sizeof(*udev->bos->desc)); + if (retval != sizeof(*udev->bos->desc)) { + dev_err(&iface->dev, "bos descriptor --> %d\n", retval); + return (retval < 0) ? retval : -EDOM; + } + + bos = (struct usb_bos_descriptor *)dev->buf; + total = le16_to_cpu(bos->wTotalLength); + num = bos->bNumDeviceCaps; + + if (total > TBUF_SIZE) + total = TBUF_SIZE; + + /* + * get generic device-level capability descriptors [9.6.2] + * in USB 3.0 spec + */ + retval = usb_get_descriptor(udev, USB_DT_BOS, 0, dev->buf, + total); + if (retval != total) { + dev_err(&iface->dev, "bos descriptor set --> %d\n", + retval); + return (retval < 0) ? retval : -EDOM; + } + + length = sizeof(*udev->bos->desc); + buf = dev->buf; + for (i = 0; i < num; i++) { + buf += length; + if (buf + sizeof(struct usb_dev_cap_header) > + dev->buf + total) + break; + + header = (struct usb_dev_cap_header *)buf; + length = header->bLength; + + if (header->bDescriptorType != + USB_DT_DEVICE_CAPABILITY) { + dev_warn(&udev->dev, "not device capability descriptor, skip\n"); + continue; + } + + switch (header->bDevCapabilityType) { + case USB_CAP_TYPE_EXT: + if (buf + USB_DT_USB_EXT_CAP_SIZE > + dev->buf + total || + !is_good_ext(dev, buf)) { + dev_err(&iface->dev, "bogus usb 2.0 extension descriptor\n"); + return -EDOM; + } + break; + case USB_SS_CAP_TYPE: + if (buf + USB_DT_USB_SS_CAP_SIZE > + dev->buf + total || + !is_good_ss_cap(dev, buf)) { + dev_err(&iface->dev, "bogus superspeed device capability descriptor\n"); + return -EDOM; + } + break; + case CONTAINER_ID_TYPE: + if (buf + USB_DT_USB_SS_CONTN_ID_SIZE > + dev->buf + total || + !is_good_con_id(dev, buf)) { + dev_err(&iface->dev, "bogus container id descriptor\n"); + return -EDOM; + } + break; + default: + break; + } + } + } + /* there's always [9.4.3] at least one config descriptor [9.6.3] */ for (i = 0; i < udev->descriptor.bNumConfigurations; i++) { - retval = usb_get_descriptor (udev, USB_DT_CONFIG, i, + retval = usb_get_descriptor(udev, USB_DT_CONFIG, i, dev->buf, TBUF_SIZE); if (!is_good_config(dev, retval)) { dev_err(&iface->dev, @@ -618,18 +876,19 @@ static int ch9_postconfig (struct usbtest_dev *dev) return (retval < 0) ? retval : -EDOM; } - // FIXME cross-checking udev->config[i] to make sure usbcore - // parsed it right (etc) would be good testing paranoia + /* FIXME cross-checking udev->config[i] to make sure usbcore + * parsed it right (etc) would be good testing paranoia + */ } /* and sometimes [9.2.6.6] speed dependent descriptors */ if (le16_to_cpu(udev->descriptor.bcdUSB) == 0x0200) { - struct usb_qualifier_descriptor *d = NULL; + struct usb_qualifier_descriptor *d = NULL; /* device qualifier [9.6.2] */ - retval = usb_get_descriptor (udev, + retval = usb_get_descriptor(udev, USB_DT_DEVICE_QUALIFIER, 0, dev->buf, - sizeof (struct usb_qualifier_descriptor)); + sizeof(struct usb_qualifier_descriptor)); if (retval == -EPIPE) { if (udev->speed == USB_SPEED_HIGH) { dev_err(&iface->dev, @@ -638,7 +897,7 @@ static int ch9_postconfig (struct usbtest_dev *dev) return (retval < 0) ? retval : -EDOM; } /* usb2.0 but not high-speed capable; fine */ - } else if (retval != sizeof (struct usb_qualifier_descriptor)) { + } else if (retval != sizeof(struct usb_qualifier_descriptor)) { dev_err(&iface->dev, "dev qualifier --> %d\n", retval); return (retval < 0) ? retval : -EDOM; } else @@ -648,7 +907,7 @@ static int ch9_postconfig (struct usbtest_dev *dev) if (d) { unsigned max = d->bNumConfigurations; for (i = 0; i < max; i++) { - retval = usb_get_descriptor (udev, + retval = usb_get_descriptor(udev, USB_DT_OTHER_SPEED_CONFIG, i, dev->buf, TBUF_SIZE); if (!is_good_config(dev, retval)) { @@ -660,25 +919,26 @@ static int ch9_postconfig (struct usbtest_dev *dev) } } } - // FIXME fetch strings from at least the device descriptor + /* FIXME fetch strings from at least the device descriptor */ /* [9.4.5] get_status always works */ - retval = usb_get_status (udev, USB_RECIP_DEVICE, 0, dev->buf); - if (retval != 2) { + retval = usb_get_status(udev, USB_RECIP_DEVICE, 0, dev->buf); + if (retval) { dev_err(&iface->dev, "get dev status --> %d\n", retval); - return (retval < 0) ? retval : -EDOM; + return retval; } - // FIXME configuration.bmAttributes says if we could try to set/clear - // the device's remote wakeup feature ... if we can, test that here + /* FIXME configuration.bmAttributes says if we could try to set/clear + * the device's remote wakeup feature ... if we can, test that here + */ - retval = usb_get_status (udev, USB_RECIP_INTERFACE, - iface->altsetting [0].desc.bInterfaceNumber, dev->buf); - if (retval != 2) { + retval = usb_get_status(udev, USB_RECIP_INTERFACE, + iface->altsetting[0].desc.bInterfaceNumber, dev->buf); + if (retval) { dev_err(&iface->dev, "get interface status --> %d\n", retval); - return (retval < 0) ? retval : -EDOM; + return retval; } - // FIXME get status for each endpoint in the interface + /* FIXME get status for each endpoint in the interface */ return 0; } @@ -706,7 +966,7 @@ struct ctrl_ctx { int last; }; -#define NUM_SUBCASES 15 /* how many test subcases here? */ +#define NUM_SUBCASES 16 /* how many test subcases here? */ struct subcase { struct usb_ctrlrequest setup; @@ -714,7 +974,7 @@ struct subcase { int expected; }; -static void ctrl_complete (struct urb *urb) +static void ctrl_complete(struct urb *urb) { struct ctrl_ctx *ctx = urb->context; struct usb_ctrlrequest *reqp; @@ -722,9 +982,9 @@ static void ctrl_complete (struct urb *urb) int status = urb->status; reqp = (struct usb_ctrlrequest *)urb->setup_packet; - subcase = container_of (reqp, struct subcase, setup); + subcase = container_of(reqp, struct subcase, setup); - spin_lock (&ctx->lock); + spin_lock(&ctx->lock); ctx->count--; ctx->pending--; @@ -784,14 +1044,14 @@ error: /* unlink whatever's still pending */ for (i = 1; i < ctx->param->sglen; i++) { - struct urb *u = ctx->urb [ - (i + subcase->number) - % ctx->param->sglen]; + struct urb *u = ctx->urb[ + (i + subcase->number) + % ctx->param->sglen]; if (u == urb || !u->dev) continue; spin_unlock(&ctx->lock); - status = usb_unlink_urb (u); + status = usb_unlink_urb(u); spin_lock(&ctx->lock); switch (status) { case -EINPROGRESS: @@ -809,7 +1069,8 @@ error: /* resubmit if we need to, else mark this as done */ if ((status == 0) && (ctx->pending < ctx->count)) { - if ((status = usb_submit_urb (urb, GFP_ATOMIC)) != 0) { + status = usb_submit_urb(urb, GFP_ATOMIC); + if (status != 0) { ERROR(ctx->dev, "can't resubmit ctrl %02x.%02x, err %d\n", reqp->bRequestType, reqp->bRequest, status); @@ -821,21 +1082,24 @@ error: /* signal completion when nothing's queued */ if (ctx->pending == 0) - complete (&ctx->complete); - spin_unlock (&ctx->lock); + complete(&ctx->complete); + spin_unlock(&ctx->lock); } static int -test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) +test_ctrl_queue(struct usbtest_dev *dev, struct usbtest_param *param) { - struct usb_device *udev = testdev_to_usbdev (dev); + struct usb_device *udev = testdev_to_usbdev(dev); struct urb **urb; struct ctrl_ctx context; int i; - spin_lock_init (&context.lock); + if (param->sglen == 0 || param->iterations > UINT_MAX / param->sglen) + return -EOPNOTSUPP; + + spin_lock_init(&context.lock); context.dev = dev; - init_completion (&context.complete); + init_completion(&context.complete); context.count = param->sglen * param->iterations; context.pending = 0; context.status = -ENOMEM; @@ -850,7 +1114,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) if (!urb) return -ENOMEM; for (i = 0; i < param->sglen; i++) { - int pipe = usb_rcvctrlpipe (udev, 0); + int pipe = usb_rcvctrlpipe(udev, 0); unsigned len; struct urb *u; struct usb_ctrlrequest req; @@ -866,126 +1130,142 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) * device, but some are chosen to trigger protocol stalls * or short reads. */ - memset (&req, 0, sizeof req); + memset(&req, 0, sizeof(req)); req.bRequest = USB_REQ_GET_DESCRIPTOR; req.bRequestType = USB_DIR_IN|USB_RECIP_DEVICE; switch (i % NUM_SUBCASES) { - case 0: // get device descriptor - req.wValue = cpu_to_le16 (USB_DT_DEVICE << 8); - len = sizeof (struct usb_device_descriptor); + case 0: /* get device descriptor */ + req.wValue = cpu_to_le16(USB_DT_DEVICE << 8); + len = sizeof(struct usb_device_descriptor); break; - case 1: // get first config descriptor (only) - req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0); - len = sizeof (struct usb_config_descriptor); + case 1: /* get first config descriptor (only) */ + req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0); + len = sizeof(struct usb_config_descriptor); break; - case 2: // get altsetting (OFTEN STALLS) + case 2: /* get altsetting (OFTEN STALLS) */ req.bRequest = USB_REQ_GET_INTERFACE; req.bRequestType = USB_DIR_IN|USB_RECIP_INTERFACE; - // index = 0 means first interface + /* index = 0 means first interface */ len = 1; expected = EPIPE; break; - case 3: // get interface status + case 3: /* get interface status */ req.bRequest = USB_REQ_GET_STATUS; req.bRequestType = USB_DIR_IN|USB_RECIP_INTERFACE; - // interface 0 + /* interface 0 */ len = 2; break; - case 4: // get device status + case 4: /* get device status */ req.bRequest = USB_REQ_GET_STATUS; req.bRequestType = USB_DIR_IN|USB_RECIP_DEVICE; len = 2; break; - case 5: // get device qualifier (MAY STALL) + case 5: /* get device qualifier (MAY STALL) */ req.wValue = cpu_to_le16 (USB_DT_DEVICE_QUALIFIER << 8); - len = sizeof (struct usb_qualifier_descriptor); + len = sizeof(struct usb_qualifier_descriptor); if (udev->speed != USB_SPEED_HIGH) expected = EPIPE; break; - case 6: // get first config descriptor, plus interface - req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0); - len = sizeof (struct usb_config_descriptor); - len += sizeof (struct usb_interface_descriptor); + case 6: /* get first config descriptor, plus interface */ + req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0); + len = sizeof(struct usb_config_descriptor); + len += sizeof(struct usb_interface_descriptor); break; - case 7: // get interface descriptor (ALWAYS STALLS) + case 7: /* get interface descriptor (ALWAYS STALLS) */ req.wValue = cpu_to_le16 (USB_DT_INTERFACE << 8); - // interface == 0 - len = sizeof (struct usb_interface_descriptor); + /* interface == 0 */ + len = sizeof(struct usb_interface_descriptor); expected = -EPIPE; break; - // NOTE: two consecutive stalls in the queue here. - // that tests fault recovery a bit more aggressively. - case 8: // clear endpoint halt (MAY STALL) + /* NOTE: two consecutive stalls in the queue here. + * that tests fault recovery a bit more aggressively. */ + case 8: /* clear endpoint halt (MAY STALL) */ req.bRequest = USB_REQ_CLEAR_FEATURE; req.bRequestType = USB_RECIP_ENDPOINT; - // wValue 0 == ep halt - // wIndex 0 == ep0 (shouldn't halt!) + /* wValue 0 == ep halt */ + /* wIndex 0 == ep0 (shouldn't halt!) */ len = 0; - pipe = usb_sndctrlpipe (udev, 0); + pipe = usb_sndctrlpipe(udev, 0); expected = EPIPE; break; - case 9: // get endpoint status + case 9: /* get endpoint status */ req.bRequest = USB_REQ_GET_STATUS; req.bRequestType = USB_DIR_IN|USB_RECIP_ENDPOINT; - // endpoint 0 + /* endpoint 0 */ len = 2; break; - case 10: // trigger short read (EREMOTEIO) - req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0); + case 10: /* trigger short read (EREMOTEIO) */ + req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0); len = 1024; expected = -EREMOTEIO; break; - // NOTE: two consecutive _different_ faults in the queue. - case 11: // get endpoint descriptor (ALWAYS STALLS) - req.wValue = cpu_to_le16 (USB_DT_ENDPOINT << 8); - // endpoint == 0 - len = sizeof (struct usb_interface_descriptor); + /* NOTE: two consecutive _different_ faults in the queue. */ + case 11: /* get endpoint descriptor (ALWAYS STALLS) */ + req.wValue = cpu_to_le16(USB_DT_ENDPOINT << 8); + /* endpoint == 0 */ + len = sizeof(struct usb_interface_descriptor); expected = EPIPE; break; - // NOTE: sometimes even a third fault in the queue! - case 12: // get string 0 descriptor (MAY STALL) - req.wValue = cpu_to_le16 (USB_DT_STRING << 8); - // string == 0, for language IDs - len = sizeof (struct usb_interface_descriptor); - // may succeed when > 4 languages - expected = EREMOTEIO; // or EPIPE, if no strings + /* NOTE: sometimes even a third fault in the queue! */ + case 12: /* get string 0 descriptor (MAY STALL) */ + req.wValue = cpu_to_le16(USB_DT_STRING << 8); + /* string == 0, for language IDs */ + len = sizeof(struct usb_interface_descriptor); + /* may succeed when > 4 languages */ + expected = EREMOTEIO; /* or EPIPE, if no strings */ break; - case 13: // short read, resembling case 10 - req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0); - // last data packet "should" be DATA1, not DATA0 - len = 1024 - udev->descriptor.bMaxPacketSize0; + case 13: /* short read, resembling case 10 */ + req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0); + /* last data packet "should" be DATA1, not DATA0 */ + if (udev->speed == USB_SPEED_SUPER) + len = 1024 - 512; + else + len = 1024 - udev->descriptor.bMaxPacketSize0; expected = -EREMOTEIO; break; - case 14: // short read; try to fill the last packet - req.wValue = cpu_to_le16 ((USB_DT_DEVICE << 8) | 0); + case 14: /* short read; try to fill the last packet */ + req.wValue = cpu_to_le16((USB_DT_DEVICE << 8) | 0); /* device descriptor size == 18 bytes */ len = udev->descriptor.bMaxPacketSize0; + if (udev->speed == USB_SPEED_SUPER) + len = 512; switch (len) { - case 8: len = 24; break; - case 16: len = 32; break; + case 8: + len = 24; + break; + case 16: + len = 32; + break; } expected = -EREMOTEIO; break; + case 15: + req.wValue = cpu_to_le16(USB_DT_BOS << 8); + if (udev->bos) + len = le16_to_cpu(udev->bos->desc->wTotalLength); + else + len = sizeof(struct usb_bos_descriptor); + if (le16_to_cpu(udev->descriptor.bcdUSB) < 0x0201) + expected = -EPIPE; + break; default: ERROR(dev, "bogus number of ctrl queue testcases!\n"); context.status = -EINVAL; goto cleanup; } - req.wLength = cpu_to_le16 (len); - urb [i] = u = simple_alloc_urb (udev, pipe, len); + req.wLength = cpu_to_le16(len); + urb[i] = u = simple_alloc_urb(udev, pipe, len); if (!u) goto cleanup; - reqp = usb_buffer_alloc (udev, sizeof *reqp, GFP_KERNEL, - &u->setup_dma); + reqp = kmalloc(sizeof(*reqp), GFP_KERNEL); if (!reqp) goto cleanup; reqp->setup = req; reqp->number = i % NUM_SUBCASES; reqp->expected = expected; u->setup_packet = (char *) &reqp->setup; - u->transfer_flags |= URB_NO_SETUP_DMA_MAP; u->context = &context; u->complete = ctrl_complete; @@ -993,9 +1273,9 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) /* queue the urbs */ context.urb = urb; - spin_lock_irq (&context.lock); + spin_lock_irq(&context.lock); for (i = 0; i < param->sglen; i++) { - context.status = usb_submit_urb (urb [i], GFP_ATOMIC); + context.status = usb_submit_urb(urb[i], GFP_ATOMIC); if (context.status != 0) { ERROR(dev, "can't submit urb[%d], status %d\n", i, context.status); @@ -1004,26 +1284,23 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) } context.pending++; } - spin_unlock_irq (&context.lock); + spin_unlock_irq(&context.lock); /* FIXME set timer and time out; provide a disconnect hook */ /* wait for the last one to complete */ if (context.pending > 0) - wait_for_completion (&context.complete); + wait_for_completion(&context.complete); cleanup: for (i = 0; i < param->sglen; i++) { - if (!urb [i]) + if (!urb[i]) continue; - urb [i]->dev = udev; - if (urb [i]->setup_packet) - usb_buffer_free (udev, sizeof (struct usb_ctrlrequest), - urb [i]->setup_packet, - urb [i]->setup_dma); - simple_free_urb (urb [i]); - } - kfree (urb); + urb[i]->dev = udev; + kfree(urb[i]->setup_packet); + simple_free_urb(urb[i]); + } + kfree(urb); return context.status; } #undef NUM_SUBCASES @@ -1031,39 +1308,45 @@ cleanup: /*-------------------------------------------------------------------------*/ -static void unlink1_callback (struct urb *urb) +static void unlink1_callback(struct urb *urb) { int status = urb->status; - // we "know" -EPIPE (stall) never happens + /* we "know" -EPIPE (stall) never happens */ if (!status) - status = usb_submit_urb (urb, GFP_ATOMIC); + status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { urb->status = status; complete(urb->context); } } -static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async) +static int unlink1(struct usbtest_dev *dev, int pipe, int size, int async) { struct urb *urb; struct completion completion; int retval = 0; - init_completion (&completion); - urb = simple_alloc_urb (testdev_to_usbdev (dev), pipe, size); + init_completion(&completion); + urb = simple_alloc_urb(testdev_to_usbdev(dev), pipe, size); if (!urb) return -ENOMEM; urb->context = &completion; urb->complete = unlink1_callback; + if (usb_pipeout(urb->pipe)) { + simple_fill_buf(urb); + urb->transfer_flags |= URB_ZERO_PACKET; + } + /* keep the endpoint busy. there are lots of hc/hcd-internal * states, and testing should get to all of them over time. * * FIXME want additional tests for when endpoint is STALLing * due to errors, or is just NAKing requests. */ - if ((retval = usb_submit_urb (urb, GFP_KERNEL)) != 0) { + retval = usb_submit_urb(urb, GFP_KERNEL); + if (retval != 0) { dev_err(&dev->intf->dev, "submit fail %d\n", retval); return retval; } @@ -1071,11 +1354,14 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async) /* unlinking that should always work. variable delay tests more * hcd states and code paths, even with little other system load. */ - msleep (jiffies % (2 * INTERRUPT_RATE)); + msleep(jiffies % (2 * INTERRUPT_RATE)); if (async) { while (!completion_done(&completion)) { retval = usb_unlink_urb(urb); + if (retval == 0 && usb_pipein(urb->pipe)) + retval = simple_check_buf(dev, urb); + switch (retval) { case -EBUSY: case -EIDRM: @@ -1100,11 +1386,11 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async) break; } } else - usb_kill_urb (urb); + usb_kill_urb(urb); - wait_for_completion (&completion); + wait_for_completion(&completion); retval = urb->status; - simple_free_urb (urb); + simple_free_urb(urb); if (async) return (retval == -ECONNRESET) ? 0 : retval - 1000; @@ -1113,14 +1399,117 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async) 0 : retval - 2000; } -static int unlink_simple (struct usbtest_dev *dev, int pipe, int len) +static int unlink_simple(struct usbtest_dev *dev, int pipe, int len) { int retval = 0; /* test sync and async paths */ - retval = unlink1 (dev, pipe, len, 1); + retval = unlink1(dev, pipe, len, 1); if (!retval) - retval = unlink1 (dev, pipe, len, 0); + retval = unlink1(dev, pipe, len, 0); + return retval; +} + +/*-------------------------------------------------------------------------*/ + +struct queued_ctx { + struct completion complete; + atomic_t pending; + unsigned num; + int status; + struct urb **urbs; +}; + +static void unlink_queued_callback(struct urb *urb) +{ + int status = urb->status; + struct queued_ctx *ctx = urb->context; + + if (ctx->status) + goto done; + if (urb == ctx->urbs[ctx->num - 4] || urb == ctx->urbs[ctx->num - 2]) { + if (status == -ECONNRESET) + goto done; + /* What error should we report if the URB completed normally? */ + } + if (status != 0) + ctx->status = status; + + done: + if (atomic_dec_and_test(&ctx->pending)) + complete(&ctx->complete); +} + +static int unlink_queued(struct usbtest_dev *dev, int pipe, unsigned num, + unsigned size) +{ + struct queued_ctx ctx; + struct usb_device *udev = testdev_to_usbdev(dev); + void *buf; + dma_addr_t buf_dma; + int i; + int retval = -ENOMEM; + + init_completion(&ctx.complete); + atomic_set(&ctx.pending, 1); /* One more than the actual value */ + ctx.num = num; + ctx.status = 0; + + buf = usb_alloc_coherent(udev, size, GFP_KERNEL, &buf_dma); + if (!buf) + return retval; + memset(buf, 0, size); + + /* Allocate and init the urbs we'll queue */ + ctx.urbs = kcalloc(num, sizeof(struct urb *), GFP_KERNEL); + if (!ctx.urbs) + goto free_buf; + for (i = 0; i < num; i++) { + ctx.urbs[i] = usb_alloc_urb(0, GFP_KERNEL); + if (!ctx.urbs[i]) + goto free_urbs; + usb_fill_bulk_urb(ctx.urbs[i], udev, pipe, buf, size, + unlink_queued_callback, &ctx); + ctx.urbs[i]->transfer_dma = buf_dma; + ctx.urbs[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP; + + if (usb_pipeout(ctx.urbs[i]->pipe)) { + simple_fill_buf(ctx.urbs[i]); + ctx.urbs[i]->transfer_flags |= URB_ZERO_PACKET; + } + } + + /* Submit all the URBs and then unlink URBs num - 4 and num - 2. */ + for (i = 0; i < num; i++) { + atomic_inc(&ctx.pending); + retval = usb_submit_urb(ctx.urbs[i], GFP_KERNEL); + if (retval != 0) { + dev_err(&dev->intf->dev, "submit urbs[%d] fail %d\n", + i, retval); + atomic_dec(&ctx.pending); + ctx.status = retval; + break; + } + } + if (i == num) { + usb_unlink_urb(ctx.urbs[num - 4]); + usb_unlink_urb(ctx.urbs[num - 2]); + } else { + while (--i >= 0) + usb_unlink_urb(ctx.urbs[i]); + } + + if (atomic_dec_and_test(&ctx.pending)) /* The extra count */ + complete(&ctx.complete); + wait_for_completion(&ctx.complete); + retval = ctx.status; + + free_urbs: + for (i = 0; i < num; i++) + usb_free_urb(ctx.urbs[i]); + kfree(ctx.urbs); + free_buf: + usb_free_coherent(udev, size, buf, buf_dma); return retval; } @@ -1132,7 +1521,7 @@ static int verify_not_halted(struct usbtest_dev *tdev, int ep, struct urb *urb) u16 status; /* shouldn't look or act halted */ - retval = usb_get_status (urb->dev, USB_RECIP_ENDPOINT, ep, &status); + retval = usb_get_status(urb->dev, USB_RECIP_ENDPOINT, ep, &status); if (retval < 0) { ERROR(tdev, "ep %02x couldn't get no-halt status, %d\n", ep, retval); @@ -1154,13 +1543,12 @@ static int verify_halted(struct usbtest_dev *tdev, int ep, struct urb *urb) u16 status; /* should look and act halted */ - retval = usb_get_status (urb->dev, USB_RECIP_ENDPOINT, ep, &status); + retval = usb_get_status(urb->dev, USB_RECIP_ENDPOINT, ep, &status); if (retval < 0) { ERROR(tdev, "ep %02x couldn't get halt status, %d\n", ep, retval); return retval; } - le16_to_cpus(&status); if (status != 1) { ERROR(tdev, "ep %02x bogus status: %04x != 1\n", ep, status); return -EINVAL; @@ -1184,7 +1572,7 @@ static int test_halt(struct usbtest_dev *tdev, int ep, struct urb *urb) return retval; /* set halt (protocol test only), verify it worked */ - retval = usb_control_msg (urb->dev, usb_sndctrlpipe (urb->dev, 0), + retval = usb_control_msg(urb->dev, usb_sndctrlpipe(urb->dev, 0), USB_REQ_SET_FEATURE, USB_RECIP_ENDPOINT, USB_ENDPOINT_HALT, ep, NULL, 0, USB_CTRL_SET_TIMEOUT); @@ -1193,11 +1581,20 @@ static int test_halt(struct usbtest_dev *tdev, int ep, struct urb *urb) return retval; } retval = verify_halted(tdev, ep, urb); - if (retval < 0) + if (retval < 0) { + int ret; + + /* clear halt anyways, else further tests will fail */ + ret = usb_clear_halt(urb->dev, urb->pipe); + if (ret) + ERROR(tdev, "ep %02x couldn't clear halt, %d\n", + ep, ret); + return retval; + } /* clear halt (tests API + protocol), verify it worked */ - retval = usb_clear_halt (urb->dev, urb->pipe); + retval = usb_clear_halt(urb->dev, urb->pipe); if (retval < 0) { ERROR(tdev, "ep %02x couldn't clear halt, %d\n", ep, retval); return retval; @@ -1211,18 +1608,22 @@ static int test_halt(struct usbtest_dev *tdev, int ep, struct urb *urb) return 0; } -static int halt_simple (struct usbtest_dev *dev) +static int halt_simple(struct usbtest_dev *dev) { - int ep; - int retval = 0; - struct urb *urb; + int ep; + int retval = 0; + struct urb *urb; + struct usb_device *udev = testdev_to_usbdev(dev); - urb = simple_alloc_urb (testdev_to_usbdev (dev), 0, 512); + if (udev->speed == USB_SPEED_SUPER) + urb = simple_alloc_urb(udev, 0, 1024); + else + urb = simple_alloc_urb(udev, 0, 512); if (urb == NULL) return -ENOMEM; if (dev->in_pipe) { - ep = usb_pipeendpoint (dev->in_pipe) | USB_DIR_IN; + ep = usb_pipeendpoint(dev->in_pipe) | USB_DIR_IN; urb->pipe = dev->in_pipe; retval = test_halt(dev, ep, urb); if (retval < 0) @@ -1230,12 +1631,12 @@ static int halt_simple (struct usbtest_dev *dev) } if (dev->out_pipe) { - ep = usb_pipeendpoint (dev->out_pipe); + ep = usb_pipeendpoint(dev->out_pipe); urb->pipe = dev->out_pipe; retval = test_halt(dev, ep, urb); } done: - simple_free_urb (urb); + simple_free_urb(urb); return retval; } @@ -1249,8 +1650,8 @@ done: * need to be able to handle more than one OUT data packet. We'll * try whatever we're told to try. */ -static int ctrl_out (struct usbtest_dev *dev, - unsigned count, unsigned length, unsigned vary) +static int ctrl_out(struct usbtest_dev *dev, + unsigned count, unsigned length, unsigned vary, unsigned offset) { unsigned i, j, len; int retval; @@ -1261,11 +1662,12 @@ static int ctrl_out (struct usbtest_dev *dev, if (length < 1 || length > 0xffff || vary >= length) return -EINVAL; - buf = kmalloc(length, GFP_KERNEL); + buf = kmalloc(length + offset, GFP_KERNEL); if (!buf) return -ENOMEM; - udev = testdev_to_usbdev (dev); + buf += offset; + udev = testdev_to_usbdev(dev); len = length; retval = 0; @@ -1275,8 +1677,8 @@ static int ctrl_out (struct usbtest_dev *dev, for (i = 0; i < count; i++) { /* write patterned data */ for (j = 0; j < len; j++) - buf [j] = i + j; - retval = usb_control_msg (udev, usb_sndctrlpipe (udev,0), + buf[j] = i + j; + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x5b, USB_DIR_OUT|USB_TYPE_VENDOR, 0, 0, buf, len, USB_CTRL_SET_TIMEOUT); if (retval != len) { @@ -1290,7 +1692,7 @@ static int ctrl_out (struct usbtest_dev *dev, } /* read it back -- assuming nothing intervened!! */ - retval = usb_control_msg (udev, usb_rcvctrlpipe (udev,0), + retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x5c, USB_DIR_IN|USB_TYPE_VENDOR, 0, 0, buf, len, USB_CTRL_GET_TIMEOUT); if (retval != len) { @@ -1305,9 +1707,9 @@ static int ctrl_out (struct usbtest_dev *dev, /* fail if we can't verify */ for (j = 0; j < len; j++) { - if (buf [j] != (u8) (i + j)) { + if (buf[j] != (u8) (i + j)) { ERROR(dev, "ctrl_out, byte %d is %d not %d\n", - j, buf [j], (u8) i + j); + j, buf[j], (u8) i + j); retval = -EBADMSG; break; } @@ -1328,10 +1730,10 @@ static int ctrl_out (struct usbtest_dev *dev, } if (retval < 0) - ERROR (dev, "ctrl_out %s failed, code %d, count %d\n", + ERROR(dev, "ctrl_out %s failed, code %d, count %d\n", what, retval, i); - kfree (buf); + kfree(buf - offset); return retval; } @@ -1353,7 +1755,7 @@ struct iso_context { struct usbtest_dev *dev; }; -static void iso_callback (struct urb *urb) +static void iso_callback(struct urb *urb) { struct iso_context *ctx = urb->context; @@ -1365,10 +1767,14 @@ static void iso_callback (struct urb *urb) ctx->errors += urb->error_count; else if (urb->status != 0) ctx->errors += urb->number_of_packets; + else if (urb->actual_length != urb->transfer_buffer_length) + ctx->errors++; + else if (check_guard_bytes(ctx->dev, urb) != 0) + ctx->errors++; if (urb->status == 0 && ctx->count > (ctx->pending - 1) && !ctx->submit_error) { - int status = usb_submit_urb (urb, GFP_ATOMIC); + int status = usb_submit_urb(urb, GFP_ATOMIC); switch (status) { case 0: goto done; @@ -1383,7 +1789,6 @@ static void iso_callback (struct urb *urb) break; } } - simple_free_urb (urb); ctx->pending--; if (ctx->pending == 0) { @@ -1391,17 +1796,18 @@ static void iso_callback (struct urb *urb) dev_err(&ctx->dev->intf->dev, "iso test, %lu errors out of %lu\n", ctx->errors, ctx->packet_count); - complete (&ctx->done); + complete(&ctx->done); } done: spin_unlock(&ctx->lock); } -static struct urb *iso_alloc_urb ( +static struct urb *iso_alloc_urb( struct usb_device *udev, int pipe, struct usb_endpoint_descriptor *desc, - long bytes + long bytes, + unsigned offset ) { struct urb *urb; @@ -1409,11 +1815,11 @@ static struct urb *iso_alloc_urb ( if (bytes < 0 || !desc) return NULL; - maxp = 0x7ff & le16_to_cpu(desc->wMaxPacketSize); - maxp *= 1 + (0x3 & (le16_to_cpu(desc->wMaxPacketSize) >> 11)); + maxp = 0x7ff & usb_endpoint_maxp(desc); + maxp *= 1 + (0x3 & (usb_endpoint_maxp(desc) >> 11)); packets = DIV_ROUND_UP(bytes, maxp); - urb = usb_alloc_urb (packets, GFP_KERNEL); + urb = usb_alloc_urb(packets, GFP_KERNEL); if (!urb) return urb; urb->dev = udev; @@ -1421,31 +1827,42 @@ static struct urb *iso_alloc_urb ( urb->number_of_packets = packets; urb->transfer_buffer_length = bytes; - urb->transfer_buffer = usb_buffer_alloc (udev, bytes, GFP_KERNEL, - &urb->transfer_dma); + urb->transfer_buffer = usb_alloc_coherent(udev, bytes + offset, + GFP_KERNEL, + &urb->transfer_dma); if (!urb->transfer_buffer) { - usb_free_urb (urb); + usb_free_urb(urb); return NULL; } - memset (urb->transfer_buffer, 0, bytes); + if (offset) { + memset(urb->transfer_buffer, GUARD_BYTE, offset); + urb->transfer_buffer += offset; + urb->transfer_dma += offset; + } + /* For inbound transfers use guard byte so that test fails if + data not correctly copied */ + memset(urb->transfer_buffer, + usb_pipein(urb->pipe) ? GUARD_BYTE : 0, + bytes); + for (i = 0; i < packets; i++) { /* here, only the last packet will be short */ - urb->iso_frame_desc[i].length = min ((unsigned) bytes, maxp); + urb->iso_frame_desc[i].length = min((unsigned) bytes, maxp); bytes -= urb->iso_frame_desc[i].length; urb->iso_frame_desc[i].offset = maxp * i; } urb->complete = iso_callback; - // urb->context = SET BY CALLER + /* urb->context = SET BY CALLER */ urb->interval = 1 << (desc->bInterval - 1); urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; return urb; } static int -test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, - int pipe, struct usb_endpoint_descriptor *desc) +test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param, + int pipe, struct usb_endpoint_descriptor *desc, unsigned offset) { struct iso_context context; struct usb_device *udev; @@ -1457,29 +1874,29 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, if (param->sglen > 10) return -EDOM; - memset(&context, 0, sizeof context); + memset(&context, 0, sizeof(context)); context.count = param->iterations * param->sglen; context.dev = dev; - init_completion (&context.done); - spin_lock_init (&context.lock); + init_completion(&context.done); + spin_lock_init(&context.lock); - memset (urbs, 0, sizeof urbs); - udev = testdev_to_usbdev (dev); + memset(urbs, 0, sizeof(urbs)); + udev = testdev_to_usbdev(dev); dev_info(&dev->intf->dev, "... iso period %d %sframes, wMaxPacket %04x\n", 1 << (desc->bInterval - 1), (udev->speed == USB_SPEED_HIGH) ? "micro" : "", - le16_to_cpu(desc->wMaxPacketSize)); + usb_endpoint_maxp(desc)); for (i = 0; i < param->sglen; i++) { - urbs [i] = iso_alloc_urb (udev, pipe, desc, - param->length); - if (!urbs [i]) { + urbs[i] = iso_alloc_urb(udev, pipe, desc, + param->length, offset); + if (!urbs[i]) { status = -ENOMEM; goto fail; } packets += urbs[i]->number_of_packets; - urbs [i]->context = &context; + urbs[i]->context = &context; } packets *= param->iterations; dev_info(&dev->intf->dev, @@ -1488,27 +1905,32 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, / ((udev->speed == USB_SPEED_HIGH) ? 8 : 1), packets); - spin_lock_irq (&context.lock); + spin_lock_irq(&context.lock); for (i = 0; i < param->sglen; i++) { ++context.pending; - status = usb_submit_urb (urbs [i], GFP_ATOMIC); + status = usb_submit_urb(urbs[i], GFP_ATOMIC); if (status < 0) { - ERROR (dev, "submit iso[%d], error %d\n", i, status); + ERROR(dev, "submit iso[%d], error %d\n", i, status); if (i == 0) { - spin_unlock_irq (&context.lock); + spin_unlock_irq(&context.lock); goto fail; } - simple_free_urb (urbs [i]); + simple_free_urb(urbs[i]); + urbs[i] = NULL; context.pending--; context.submit_error = 1; break; } } - spin_unlock_irq (&context.lock); + spin_unlock_irq(&context.lock); - wait_for_completion (&context.done); + wait_for_completion(&context.done); + for (i = 0; i < param->sglen; i++) { + if (urbs[i]) + simple_free_urb(urbs[i]); + } /* * Isochronous transfers are expected to fail sometimes. As an * arbitrary limit, we will report an error if any submissions @@ -1524,12 +1946,32 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, fail: for (i = 0; i < param->sglen; i++) { - if (urbs [i]) - simple_free_urb (urbs [i]); + if (urbs[i]) + simple_free_urb(urbs[i]); } return status; } +static int test_unaligned_bulk( + struct usbtest_dev *tdev, + int pipe, + unsigned length, + int iterations, + unsigned transfer_flags, + const char *label) +{ + int retval; + struct urb *urb = usbtest_alloc_urb( + testdev_to_usbdev(tdev), pipe, length, transfer_flags, 1); + + if (!urb) + return -ENOMEM; + + retval = simple_io(tdev, urb, iterations, 0, 0, label); + simple_free_urb(urb); + return retval; +} + /*-------------------------------------------------------------------------*/ /* We only have this one interface to user space, through usbfs. @@ -1554,10 +1996,10 @@ fail: */ static int -usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) +usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) { - struct usbtest_dev *dev = usb_get_intfdata (intf); - struct usb_device *udev = testdev_to_usbdev (dev); + struct usbtest_dev *dev = usb_get_intfdata(intf); + struct usb_device *udev = testdev_to_usbdev(dev); struct usbtest_param *param = buf; int retval = -EOPNOTSUPP; struct urb *urb; @@ -1566,7 +2008,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) struct timeval start; unsigned i; - // FIXME USBDEVFS_CONNECTINFO doesn't say how fast the device is. + /* FIXME USBDEVFS_CONNECTINFO doesn't say how fast the device is. */ pattern = mod_pattern; @@ -1580,10 +2022,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 @@ -1596,9 +2034,9 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) mutex_unlock(&dev->lock); return -ENODEV; } - res = set_altsetting (dev, dev->info->alt); + res = set_altsetting(dev, dev->info->alt); if (res) { - dev_err (&intf->dev, + dev_err(&intf->dev, "set altsetting to %d failed, %d\n", dev->info->alt, res); mutex_unlock(&dev->lock); @@ -1615,7 +2053,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) * FIXME add more tests! cancel requests, verify the data, control * queueing, concurrent read+write threads, and so on. */ - do_gettimeofday (&start); + do_gettimeofday(&start); switch (param->test_num) { case 0: @@ -1630,14 +2068,14 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) dev_info(&intf->dev, "TEST 1: write %d bytes %u times\n", param->length, param->iterations); - urb = simple_alloc_urb (udev, dev->out_pipe, param->length); + urb = simple_alloc_urb(udev, dev->out_pipe, param->length); if (!urb) { retval = -ENOMEM; break; } - // FIRMWARE: bulk sink (maybe accepts short writes) + /* FIRMWARE: bulk sink (maybe accepts short writes) */ retval = simple_io(dev, urb, param->iterations, 0, 0, "test1"); - simple_free_urb (urb); + simple_free_urb(urb); break; case 2: if (dev->in_pipe == 0) @@ -1645,14 +2083,14 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) dev_info(&intf->dev, "TEST 2: read %d bytes %u times\n", param->length, param->iterations); - urb = simple_alloc_urb (udev, dev->in_pipe, param->length); + urb = simple_alloc_urb(udev, dev->in_pipe, param->length); if (!urb) { retval = -ENOMEM; break; } - // FIRMWARE: bulk source (maybe generates short writes) + /* FIRMWARE: bulk source (maybe generates short writes) */ retval = simple_io(dev, urb, param->iterations, 0, 0, "test2"); - simple_free_urb (urb); + simple_free_urb(urb); break; case 3: if (dev->out_pipe == 0 || param->vary == 0) @@ -1660,15 +2098,15 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) dev_info(&intf->dev, "TEST 3: write/%d 0..%d bytes %u times\n", param->vary, param->length, param->iterations); - urb = simple_alloc_urb (udev, dev->out_pipe, param->length); + urb = simple_alloc_urb(udev, dev->out_pipe, param->length); if (!urb) { retval = -ENOMEM; break; } - // FIRMWARE: bulk sink (maybe accepts short writes) + /* FIRMWARE: bulk sink (maybe accepts short writes) */ retval = simple_io(dev, urb, param->iterations, param->vary, 0, "test3"); - simple_free_urb (urb); + simple_free_urb(urb); break; case 4: if (dev->in_pipe == 0 || param->vary == 0) @@ -1676,15 +2114,15 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) dev_info(&intf->dev, "TEST 4: read/%d 0..%d bytes %u times\n", param->vary, param->length, param->iterations); - urb = simple_alloc_urb (udev, dev->in_pipe, param->length); + urb = simple_alloc_urb(udev, dev->in_pipe, param->length); if (!urb) { retval = -ENOMEM; break; } - // FIRMWARE: bulk source (maybe generates short writes) + /* FIRMWARE: bulk source (maybe generates short writes) */ retval = simple_io(dev, urb, param->iterations, param->vary, 0, "test4"); - simple_free_urb (urb); + simple_free_urb(urb); break; /* Queued bulk I/O tests */ @@ -1695,15 +2133,15 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) "TEST 5: write %d sglists %d entries of %d bytes\n", param->iterations, param->sglen, param->length); - sg = alloc_sglist (param->sglen, param->length, 0); + sg = alloc_sglist(param->sglen, param->length, 0); if (!sg) { retval = -ENOMEM; break; } - // FIRMWARE: bulk sink (maybe accepts short writes) + /* FIRMWARE: bulk sink (maybe accepts short writes) */ retval = perform_sglist(dev, param->iterations, dev->out_pipe, &req, sg, param->sglen); - free_sglist (sg, param->sglen); + free_sglist(sg, param->sglen); break; case 6: @@ -1713,15 +2151,15 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) "TEST 6: read %d sglists %d entries of %d bytes\n", param->iterations, param->sglen, param->length); - sg = alloc_sglist (param->sglen, param->length, 0); + sg = alloc_sglist(param->sglen, param->length, 0); if (!sg) { retval = -ENOMEM; break; } - // FIRMWARE: bulk source (maybe generates short writes) + /* FIRMWARE: bulk source (maybe generates short writes) */ retval = perform_sglist(dev, param->iterations, dev->in_pipe, &req, sg, param->sglen); - free_sglist (sg, param->sglen); + free_sglist(sg, param->sglen); break; case 7: if (dev->out_pipe == 0 || param->sglen == 0 || param->vary == 0) @@ -1730,15 +2168,15 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) "TEST 7: write/%d %d sglists %d entries 0..%d bytes\n", param->vary, param->iterations, param->sglen, param->length); - sg = alloc_sglist (param->sglen, param->length, param->vary); + sg = alloc_sglist(param->sglen, param->length, param->vary); if (!sg) { retval = -ENOMEM; break; } - // FIRMWARE: bulk sink (maybe accepts short writes) + /* FIRMWARE: bulk sink (maybe accepts short writes) */ retval = perform_sglist(dev, param->iterations, dev->out_pipe, &req, sg, param->sglen); - free_sglist (sg, param->sglen); + free_sglist(sg, param->sglen); break; case 8: if (dev->in_pipe == 0 || param->sglen == 0 || param->vary == 0) @@ -1747,15 +2185,15 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) "TEST 8: read/%d %d sglists %d entries 0..%d bytes\n", param->vary, param->iterations, param->sglen, param->length); - sg = alloc_sglist (param->sglen, param->length, param->vary); + sg = alloc_sglist(param->sglen, param->length, param->vary); if (!sg) { retval = -ENOMEM; break; } - // FIRMWARE: bulk source (maybe generates short writes) + /* FIRMWARE: bulk source (maybe generates short writes) */ retval = perform_sglist(dev, param->iterations, dev->in_pipe, &req, sg, param->sglen); - free_sglist (sg, param->sglen); + free_sglist(sg, param->sglen); break; /* non-queued sanity tests for control (chapter 9 subset) */ @@ -1765,7 +2203,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) "TEST 9: ch9 (subset) control tests, %d times\n", param->iterations); for (i = param->iterations; retval == 0 && i--; /* NOP */) - retval = ch9_postconfig (dev); + retval = ch9_postconfig(dev); if (retval) dev_err(&intf->dev, "ch9 subset failed, " "iterations left %d\n", i); @@ -1773,14 +2211,12 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) /* queued control messaging */ case 10: - if (param->sglen == 0) - break; retval = 0; dev_info(&intf->dev, "TEST 10: queue %d control calls, %d times\n", param->sglen, param->iterations); - retval = test_ctrl_queue (dev, param); + retval = test_ctrl_queue(dev, param); break; /* simple non-queued unlinks (ring with one urb) */ @@ -1791,7 +2227,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) dev_info(&intf->dev, "TEST 11: unlink %d reads of %d\n", param->iterations, param->length); for (i = param->iterations; retval == 0 && i--; /* NOP */) - retval = unlink_simple (dev, dev->in_pipe, + retval = unlink_simple(dev, dev->in_pipe, param->length); if (retval) dev_err(&intf->dev, "unlink reads failed %d, " @@ -1804,7 +2240,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) dev_info(&intf->dev, "TEST 12: unlink %d writes of %d\n", param->iterations, param->length); for (i = param->iterations; retval == 0 && i--; /* NOP */) - retval = unlink_simple (dev, dev->out_pipe, + retval = unlink_simple(dev, dev->out_pipe, param->length); if (retval) dev_err(&intf->dev, "unlink writes failed %d, " @@ -1819,7 +2255,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) dev_info(&intf->dev, "TEST 13: set/clear %d halts\n", param->iterations); for (i = param->iterations; retval == 0 && i--; /* NOP */) - retval = halt_simple (dev); + retval = halt_simple(dev); if (retval) ERROR(dev, "halts failed, iterations left %d\n", i); @@ -1834,7 +2270,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) realworld ? 1 : 0, param->length, param->vary); retval = ctrl_out(dev, param->iterations, - param->length, param->vary); + param->length, param->vary, 0); break; /* iso write tests */ @@ -1845,9 +2281,9 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) "TEST 15: write %d iso, %d entries of %d bytes\n", param->iterations, param->sglen, param->length); - // FIRMWARE: iso sink - retval = test_iso_queue (dev, param, - dev->out_iso_pipe, dev->iso_out); + /* FIRMWARE: iso sink */ + retval = test_iso_queue(dev, param, + dev->out_iso_pipe, dev->iso_out, 0); break; /* iso read tests */ @@ -1858,17 +2294,125 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) "TEST 16: read %d iso, %d entries of %d bytes\n", param->iterations, param->sglen, param->length); - // FIRMWARE: iso source - retval = test_iso_queue (dev, param, - dev->in_iso_pipe, dev->iso_in); + /* FIRMWARE: iso source */ + retval = test_iso_queue(dev, param, + dev->in_iso_pipe, dev->iso_in, 0); + break; + + /* FIXME scatterlist cancel (needs helper thread) */ + + /* Tests for bulk I/O using DMA mapping by core and odd address */ + case 17: + if (dev->out_pipe == 0) + break; + dev_info(&intf->dev, + "TEST 17: write odd addr %d bytes %u times core map\n", + param->length, param->iterations); + + retval = test_unaligned_bulk( + dev, dev->out_pipe, + param->length, param->iterations, + 0, "test17"); + break; + + case 18: + if (dev->in_pipe == 0) + break; + dev_info(&intf->dev, + "TEST 18: read odd addr %d bytes %u times core map\n", + param->length, param->iterations); + + retval = test_unaligned_bulk( + dev, dev->in_pipe, + param->length, param->iterations, + 0, "test18"); + break; + + /* Tests for bulk I/O using premapped coherent buffer and odd address */ + case 19: + if (dev->out_pipe == 0) + break; + dev_info(&intf->dev, + "TEST 19: write odd addr %d bytes %u times premapped\n", + param->length, param->iterations); + + retval = test_unaligned_bulk( + dev, dev->out_pipe, + param->length, param->iterations, + URB_NO_TRANSFER_DMA_MAP, "test19"); + break; + + case 20: + if (dev->in_pipe == 0) + break; + dev_info(&intf->dev, + "TEST 20: read odd addr %d bytes %u times premapped\n", + param->length, param->iterations); + + retval = test_unaligned_bulk( + dev, dev->in_pipe, + param->length, param->iterations, + URB_NO_TRANSFER_DMA_MAP, "test20"); + break; + + /* control write tests with unaligned buffer */ + case 21: + if (!dev->info->ctrl_out) + break; + dev_info(&intf->dev, + "TEST 21: %d ep0out odd addr, %d..%d vary %d\n", + param->iterations, + realworld ? 1 : 0, param->length, + param->vary); + retval = ctrl_out(dev, param->iterations, + param->length, param->vary, 1); + break; + + /* unaligned iso tests */ + case 22: + if (dev->out_iso_pipe == 0 || param->sglen == 0) + break; + dev_info(&intf->dev, + "TEST 22: write %d iso odd, %d entries of %d bytes\n", + param->iterations, + param->sglen, param->length); + retval = test_iso_queue(dev, param, + dev->out_iso_pipe, dev->iso_out, 1); break; - // FIXME unlink from queue (ring with N urbs) + case 23: + if (dev->in_iso_pipe == 0 || param->sglen == 0) + break; + dev_info(&intf->dev, + "TEST 23: read %d iso odd, %d entries of %d bytes\n", + param->iterations, + param->sglen, param->length); + retval = test_iso_queue(dev, param, + dev->in_iso_pipe, dev->iso_in, 1); + break; - // FIXME scatterlist cancel (needs helper thread) + /* unlink URBs from a bulk-OUT queue */ + case 24: + if (dev->out_pipe == 0 || !param->length || param->sglen < 4) + break; + retval = 0; + dev_info(&intf->dev, "TEST 24: unlink from %d queues of " + "%d %d-byte writes\n", + param->iterations, param->sglen, param->length); + for (i = param->iterations; retval == 0 && i > 0; --i) { + retval = unlink_queued(dev, dev->out_pipe, + param->sglen, param->length); + if (retval) { + dev_err(&intf->dev, + "unlink queued writes failed %d, " + "iterations left %d\n", retval, i); + break; + } + } + break; } - do_gettimeofday (¶m->duration); + do_gettimeofday(¶m->duration); param->duration.tv_sec -= start.tv_sec; param->duration.tv_usec -= start.tv_usec; if (param->duration.tv_usec < 0) { @@ -1881,22 +2425,22 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) /*-------------------------------------------------------------------------*/ -static unsigned force_interrupt = 0; -module_param (force_interrupt, uint, 0); -MODULE_PARM_DESC (force_interrupt, "0 = test default; else interrupt"); +static unsigned force_interrupt; +module_param(force_interrupt, uint, 0); +MODULE_PARM_DESC(force_interrupt, "0 = test default; else interrupt"); #ifdef GENERIC static unsigned short vendor; module_param(vendor, ushort, 0); -MODULE_PARM_DESC (vendor, "vendor code (from usb-if)"); +MODULE_PARM_DESC(vendor, "vendor code (from usb-if)"); static unsigned short product; module_param(product, ushort, 0); -MODULE_PARM_DESC (product, "product code (from vendor)"); +MODULE_PARM_DESC(product, "product code (from vendor)"); #endif static int -usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id) +usbtest_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *udev; struct usbtest_dev *dev; @@ -1904,7 +2448,7 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id) char *rtest, *wtest; char *irtest, *iwtest; - udev = interface_to_usbdev (intf); + udev = interface_to_usbdev(intf); #ifdef GENERIC /* specify devices by module parameters? */ @@ -1931,8 +2475,9 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id) dev->intf = intf; /* cacheline-aligned scratch for i/o */ - if ((dev->buf = kmalloc (TBUF_SIZE, GFP_KERNEL)) == NULL) { - kfree (dev); + dev->buf = kmalloc(TBUF_SIZE, GFP_KERNEL); + if (dev->buf == NULL) { + kfree(dev); return -ENOMEM; } @@ -1944,30 +2489,32 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id) irtest = iwtest = ""; if (force_interrupt || udev->speed == USB_SPEED_LOW) { if (info->ep_in) { - dev->in_pipe = usb_rcvintpipe (udev, info->ep_in); + dev->in_pipe = usb_rcvintpipe(udev, info->ep_in); rtest = " intr-in"; } if (info->ep_out) { - dev->out_pipe = usb_sndintpipe (udev, info->ep_out); + dev->out_pipe = usb_sndintpipe(udev, info->ep_out); wtest = " intr-out"; } } else { - if (info->autoconf) { + if (override_alt >= 0 || info->autoconf) { int status; - status = get_endpoints (dev, intf); + status = get_endpoints(dev, intf); if (status < 0) { WARNING(dev, "couldn't get endpoints, %d\n", status); + kfree(dev->buf); + kfree(dev); return status; } /* may find bulk or ISO pipes */ } else { if (info->ep_in) - dev->in_pipe = usb_rcvbulkpipe (udev, + dev->in_pipe = usb_rcvbulkpipe(udev, info->ep_in); if (info->ep_out) - dev->out_pipe = usb_sndbulkpipe (udev, + dev->out_pipe = usb_sndbulkpipe(udev, info->ep_out); } if (dev->in_pipe) @@ -1980,16 +2527,10 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id) iwtest = " iso-out"; } - usb_set_intfdata (intf, dev); - dev_info (&intf->dev, "%s\n", info->name); - dev_info (&intf->dev, "%s speed {control%s%s%s%s%s} tests%s\n", - ({ char *tmp; - switch (udev->speed) { - case USB_SPEED_LOW: tmp = "low"; break; - case USB_SPEED_FULL: tmp = "full"; break; - case USB_SPEED_HIGH: tmp = "high"; break; - default: tmp = "unknown"; break; - }; tmp; }), + usb_set_intfdata(intf, dev); + dev_info(&intf->dev, "%s\n", info->name); + dev_info(&intf->dev, "%s {control%s%s%s%s%s} tests%s\n", + usb_speed_string(udev->speed), info->ctrl_out ? " in/out" : "", rtest, wtest, irtest, iwtest, @@ -1997,24 +2538,24 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id) return 0; } -static int usbtest_suspend (struct usb_interface *intf, pm_message_t message) +static int usbtest_suspend(struct usb_interface *intf, pm_message_t message) { return 0; } -static int usbtest_resume (struct usb_interface *intf) +static int usbtest_resume(struct usb_interface *intf) { return 0; } -static void usbtest_disconnect (struct usb_interface *intf) +static void usbtest_disconnect(struct usb_interface *intf) { - struct usbtest_dev *dev = usb_get_intfdata (intf); + struct usbtest_dev *dev = usb_get_intfdata(intf); - usb_set_intfdata (intf, NULL); - dev_dbg (&intf->dev, "disconnect\n"); - kfree (dev); + usb_set_intfdata(intf, NULL); + dev_dbg(&intf->dev, "disconnect\n"); + kfree(dev); } /* Basic testing only needs a device that can source or sink bulk traffic. @@ -2051,9 +2592,9 @@ static struct usbtest_info fw_info = { .ep_in = 2, .ep_out = 2, .alt = 1, - .autoconf = 1, // iso and ctrl_out need autoconf + .autoconf = 1, /* iso and ctrl_out need autoconf */ .ctrl_out = 1, - .iso = 1, // iso_ep's are #8 in/out + .iso = 1, /* iso_ep's are #8 in/out */ }; /* peripheral running Linux and 'zero.c' test firmware, or @@ -2065,6 +2606,7 @@ static struct usbtest_info gz_info = { .name = "Linux gadget zero", .autoconf = 1, .ctrl_out = 1, + .iso = 1, .alt = 0, }; @@ -2101,7 +2643,7 @@ static struct usbtest_info generic_info = { #endif -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { /*-------------------------------------------------------------*/ @@ -2110,56 +2652,56 @@ static struct usb_device_id id_table [] = { */ /* generic EZ-USB FX controller */ - { USB_DEVICE (0x0547, 0x2235), + { USB_DEVICE(0x0547, 0x2235), .driver_info = (unsigned long) &ez1_info, - }, + }, /* CY3671 development board with EZ-USB FX */ - { USB_DEVICE (0x0547, 0x0080), + { USB_DEVICE(0x0547, 0x0080), .driver_info = (unsigned long) &ez1_info, - }, + }, /* generic EZ-USB FX2 controller (or development board) */ - { USB_DEVICE (0x04b4, 0x8613), + { USB_DEVICE(0x04b4, 0x8613), .driver_info = (unsigned long) &ez2_info, - }, + }, /* re-enumerated usb test device firmware */ - { USB_DEVICE (0xfff0, 0xfff0), + { USB_DEVICE(0xfff0, 0xfff0), .driver_info = (unsigned long) &fw_info, - }, + }, /* "Gadget Zero" firmware runs under Linux */ - { USB_DEVICE (0x0525, 0xa4a0), + { USB_DEVICE(0x0525, 0xa4a0), .driver_info = (unsigned long) &gz_info, - }, + }, /* so does a user-mode variant */ - { USB_DEVICE (0x0525, 0xa4a4), + { USB_DEVICE(0x0525, 0xa4a4), .driver_info = (unsigned long) &um_info, - }, + }, /* ... and a user-mode variant that talks iso */ - { USB_DEVICE (0x0525, 0xa4a3), + { USB_DEVICE(0x0525, 0xa4a3), .driver_info = (unsigned long) &um2_info, - }, + }, #ifdef KEYSPAN_19Qi /* Keyspan 19qi uses an21xx (original EZ-USB) */ - // this does not coexist with the real Keyspan 19qi driver! - { USB_DEVICE (0x06cd, 0x010b), + /* this does not coexist with the real Keyspan 19qi driver! */ + { USB_DEVICE(0x06cd, 0x010b), .driver_info = (unsigned long) &ez1_info, - }, + }, #endif /*-------------------------------------------------------------*/ #ifdef IBOT2 /* iBOT2 makes a nice source of high speed bulk-in data */ - // this does not coexist with a real iBOT2 driver! - { USB_DEVICE (0x0b62, 0x0059), + /* this does not coexist with a real iBOT2 driver! */ + { USB_DEVICE(0x0b62, 0x0059), .driver_info = (unsigned long) &ibot2_info, - }, + }, #endif /*-------------------------------------------------------------*/ @@ -2173,13 +2715,13 @@ static struct usb_device_id id_table [] = { { } }; -MODULE_DEVICE_TABLE (usb, id_table); +MODULE_DEVICE_TABLE(usb, id_table); static struct usb_driver usbtest_driver = { .name = "usbtest", .id_table = id_table, .probe = usbtest_probe, - .ioctl = usbtest_ioctl, + .unlocked_ioctl = usbtest_ioctl, .disconnect = usbtest_disconnect, .suspend = usbtest_suspend, .resume = usbtest_resume, @@ -2187,22 +2729,22 @@ static struct usb_driver usbtest_driver = { /*-------------------------------------------------------------------------*/ -static int __init usbtest_init (void) +static int __init usbtest_init(void) { #ifdef GENERIC if (vendor) pr_debug("params: vend=0x%04x prod=0x%04x\n", vendor, product); #endif - return usb_register (&usbtest_driver); + return usb_register(&usbtest_driver); } -module_init (usbtest_init); +module_init(usbtest_init); -static void __exit usbtest_exit (void) +static void __exit usbtest_exit(void) { - usb_deregister (&usbtest_driver); + usb_deregister(&usbtest_driver); } -module_exit (usbtest_exit); +module_exit(usbtest_exit); -MODULE_DESCRIPTION ("USB Core/HCD Testing Driver"); -MODULE_LICENSE ("GPL"); +MODULE_DESCRIPTION("USB Core/HCD Testing Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c index 9a6c27a0179..40ef40affe8 100644 --- a/drivers/usb/misc/uss720.c +++ b/drivers/usb/misc/uss720.c @@ -3,7 +3,7 @@ /* * uss720.c -- USS720 USB Parport Cable. * - * Copyright (C) 1999, 2005 + * Copyright (C) 1999, 2005, 2010 * Thomas Sailer (t.sailer@alumni.ethz.ch) * * This program is free software; you can redistribute it and/or modify @@ -49,6 +49,7 @@ #include <linux/delay.h> #include <linux/completion.h> #include <linux/kref.h> +#include <linux/slab.h> /* * Version Information @@ -74,7 +75,7 @@ struct uss720_async_request { struct list_head asynclist; struct completion compl; struct urb *urb; - struct usb_ctrlrequest dr; + struct usb_ctrlrequest *dr; __u8 reg[7]; }; @@ -84,9 +85,9 @@ static void destroy_priv(struct kref *kref) { struct parport_uss720_private *priv = container_of(kref, struct parport_uss720_private, ref_count); + dev_dbg(&priv->usbdev->dev, "destroying priv datastructure\n"); usb_put_dev(priv->usbdev); kfree(priv); - dbg("destroying priv datastructure"); } static void destroy_async(struct kref *kref) @@ -97,6 +98,7 @@ static void destroy_async(struct kref *kref) if (likely(rq->urb)) usb_free_urb(rq->urb); + kfree(rq->dr); spin_lock_irqsave(&priv->asynclock, flags); list_del_init(&rq->asynclist); spin_unlock_irqrestore(&priv->asynclock, flags); @@ -117,14 +119,17 @@ static void async_complete(struct urb *urb) priv = rq->priv; pp = priv->pp; if (status) { - err("async_complete: urb error %d", status); - } else if (rq->dr.bRequest == 3) { + dev_err(&urb->dev->dev, "async_complete: urb error %d\n", + status); + } else if (rq->dr->bRequest == 3) { memcpy(priv->reg, rq->reg, sizeof(priv->reg)); #if 0 - dbg("async_complete regs %02x %02x %02x %02x %02x %02x %02x", - (unsigned int)priv->reg[0], (unsigned int)priv->reg[1], (unsigned int)priv->reg[2], - (unsigned int)priv->reg[3], (unsigned int)priv->reg[4], (unsigned int)priv->reg[5], - (unsigned int)priv->reg[6]); + dev_dbg(&priv->usbdev->dev, + "async_complete regs %02x %02x %02x %02x %02x %02x %02x\n", + (unsigned int)priv->reg[0], (unsigned int)priv->reg[1], + (unsigned int)priv->reg[2], (unsigned int)priv->reg[3], + (unsigned int)priv->reg[4], (unsigned int)priv->reg[5], + (unsigned int)priv->reg[6]); #endif /* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */ if (rq->reg[2] & rq->reg[1] & 0x10 && pp) @@ -148,9 +153,9 @@ static struct uss720_async_request *submit_async_request(struct parport_uss720_p usbdev = priv->usbdev; if (!usbdev) return NULL; - rq = kmalloc(sizeof(struct uss720_async_request), mem_flags); + rq = kzalloc(sizeof(struct uss720_async_request), mem_flags); if (!rq) { - err("submit_async_request out of memory"); + dev_err(&usbdev->dev, "submit_async_request out of memory\n"); return NULL; } kref_init(&rq->ref_count); @@ -161,28 +166,32 @@ static struct uss720_async_request *submit_async_request(struct parport_uss720_p rq->urb = usb_alloc_urb(0, mem_flags); if (!rq->urb) { kref_put(&rq->ref_count, destroy_async); - err("submit_async_request out of memory"); + dev_err(&usbdev->dev, "submit_async_request out of memory\n"); return NULL; } - rq->dr.bRequestType = requesttype; - rq->dr.bRequest = request; - rq->dr.wValue = cpu_to_le16(value); - rq->dr.wIndex = cpu_to_le16(index); - rq->dr.wLength = cpu_to_le16((request == 3) ? sizeof(rq->reg) : 0); + rq->dr = kmalloc(sizeof(*rq->dr), mem_flags); + if (!rq->dr) { + kref_put(&rq->ref_count, destroy_async); + return NULL; + } + rq->dr->bRequestType = requesttype; + rq->dr->bRequest = request; + rq->dr->wValue = cpu_to_le16(value); + rq->dr->wIndex = cpu_to_le16(index); + rq->dr->wLength = cpu_to_le16((request == 3) ? sizeof(rq->reg) : 0); usb_fill_control_urb(rq->urb, usbdev, (requesttype & 0x80) ? usb_rcvctrlpipe(usbdev, 0) : usb_sndctrlpipe(usbdev, 0), - (unsigned char *)&rq->dr, + (unsigned char *)rq->dr, (request == 3) ? rq->reg : NULL, (request == 3) ? sizeof(rq->reg) : 0, async_complete, rq); /* rq->urb->transfer_flags |= URB_ASYNC_UNLINK; */ spin_lock_irqsave(&priv->asynclock, flags); list_add_tail(&rq->asynclist, &priv->asynclist); spin_unlock_irqrestore(&priv->asynclock, flags); + kref_get(&rq->ref_count); ret = usb_submit_urb(rq->urb, mem_flags); - if (!ret) { - kref_get(&rq->ref_count); + if (!ret) return rq; - } - kref_put(&rq->ref_count, destroy_async); - err("submit_async_request submit_urb failed with %d", ret); + destroy_async(&rq->ref_count); + dev_err(&usbdev->dev, "submit_async_request submit_urb failed with %d\n", ret); return NULL; } @@ -217,7 +226,8 @@ static int get_1284_register(struct parport *pp, unsigned char reg, unsigned cha priv = pp->private_data; rq = submit_async_request(priv, 3, 0xc0, ((unsigned int)reg) << 8, 0, mem_flags); if (!rq) { - err("get_1284_register(%u) failed", (unsigned int)reg); + dev_err(&priv->usbdev->dev, "get_1284_register(%u) failed", + (unsigned int)reg); return -EIO; } if (!val) { @@ -248,7 +258,8 @@ static int set_1284_register(struct parport *pp, unsigned char reg, unsigned cha priv = pp->private_data; rq = submit_async_request(priv, 4, 0x40, (((unsigned int)reg) << 8) | val, 0, mem_flags); if (!rq) { - err("set_1284_register(%u,%u) failed", (unsigned int)reg, (unsigned int)val); + dev_err(&priv->usbdev->dev, "set_1284_register(%u,%u) failed", + (unsigned int)reg, (unsigned int)val); return -EIO; } kref_put(&rq->ref_count, destroy_async); @@ -690,9 +701,9 @@ static int uss720_probe(struct usb_interface *intf, unsigned char reg; int i; - dbg("probe: vendor id 0x%x, device id 0x%x\n", - le16_to_cpu(usbdev->descriptor.idVendor), - le16_to_cpu(usbdev->descriptor.idProduct)); + dev_dbg(&intf->dev, "probe: vendor id 0x%x, device id 0x%x\n", + le16_to_cpu(usbdev->descriptor.idVendor), + le16_to_cpu(usbdev->descriptor.idProduct)); /* our known interfaces have 3 alternate settings */ if (intf->num_altsetting != 3) { @@ -700,7 +711,7 @@ static int uss720_probe(struct usb_interface *intf, return -ENODEV; } i = usb_set_interface(usbdev, intf->altsetting->desc.bInterfaceNumber, 2); - dbg("set inteface result %d", i); + dev_dbg(&intf->dev, "set interface result %d\n", i); interface = intf->cur_altsetting; @@ -731,11 +742,13 @@ static int uss720_probe(struct usb_interface *intf, set_1284_register(pp, 2, 0x0c, GFP_KERNEL); /* debugging */ get_1284_register(pp, 0, ®, GFP_KERNEL); - dbg("reg: %02x %02x %02x %02x %02x %02x %02x", - priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]); + dev_dbg(&intf->dev, "reg: %02x %02x %02x %02x %02x %02x %02x\n", + priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], + priv->reg[4], priv->reg[5], priv->reg[6]); endpoint = &interface->endpoint[2]; - dbg("epaddr %d interval %d", endpoint->desc.bEndpointAddress, endpoint->desc.bInterval); + dev_dbg(&intf->dev, "epaddr %d interval %d\n", + endpoint->desc.bEndpointAddress, endpoint->desc.bInterval); parport_announce_port(pp); usb_set_intfdata(intf, pp); @@ -753,28 +766,29 @@ static void uss720_disconnect(struct usb_interface *intf) struct parport_uss720_private *priv; struct usb_device *usbdev; - dbg("disconnect"); + dev_dbg(&intf->dev, "disconnect\n"); usb_set_intfdata(intf, NULL); if (pp) { priv = pp->private_data; usbdev = priv->usbdev; priv->usbdev = NULL; priv->pp = NULL; - dbg("parport_remove_port"); + dev_dbg(&intf->dev, "parport_remove_port\n"); parport_remove_port(pp); parport_put_port(pp); kill_all_async_requests_priv(priv); kref_put(&priv->ref_count, destroy_priv); } - dbg("disconnect done"); + dev_dbg(&intf->dev, "disconnect done\n"); } /* 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) }, { USB_DEVICE(0x1293, 0x0002) }, + { USB_DEVICE(0x050d, 0x0002) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/misc/vstusb.c b/drivers/usb/misc/vstusb.c deleted file mode 100644 index f26ea8dc157..00000000000 --- 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"); diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c new file mode 100644 index 00000000000..1472805083d --- /dev/null +++ b/drivers/usb/misc/yurex.c @@ -0,0 +1,546 @@ +/* + * Driver for Meywa-Denki & KAYAC YUREX + * + * Copyright (C) 2010 Tomoki Sekiyama (tomoki.sekiyama@gmail.com) + * + * 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. + * + */ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/kref.h> +#include <linux/mutex.h> +#include <linux/uaccess.h> +#include <linux/usb.h> +#include <linux/hid.h> + +#define DRIVER_AUTHOR "Tomoki Sekiyama" +#define DRIVER_DESC "Driver for Meywa-Denki & KAYAC YUREX" + +#define YUREX_VENDOR_ID 0x0c45 +#define YUREX_PRODUCT_ID 0x1010 + +#define CMD_ACK '!' +#define CMD_ANIMATE 'A' +#define CMD_COUNT 'C' +#define CMD_LED 'L' +#define CMD_READ 'R' +#define CMD_SET 'S' +#define CMD_VERSION 'V' +#define CMD_EOF 0x0d +#define CMD_PADDING 0xff + +#define YUREX_BUF_SIZE 8 +#define YUREX_WRITE_TIMEOUT (HZ*2) + +/* table of devices that work with this driver */ +static struct usb_device_id yurex_table[] = { + { USB_DEVICE(YUREX_VENDOR_ID, YUREX_PRODUCT_ID) }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, yurex_table); + +#ifdef CONFIG_USB_DYNAMIC_MINORS +#define YUREX_MINOR_BASE 0 +#else +#define YUREX_MINOR_BASE 192 +#endif + +/* Structure to hold all of our device specific stuff */ +struct usb_yurex { + struct usb_device *udev; + struct usb_interface *interface; + __u8 int_in_endpointAddr; + struct urb *urb; /* URB for interrupt in */ + unsigned char *int_buffer; /* buffer for intterupt in */ + struct urb *cntl_urb; /* URB for control msg */ + struct usb_ctrlrequest *cntl_req; /* req for control msg */ + unsigned char *cntl_buffer; /* buffer for control msg */ + + struct kref kref; + struct mutex io_mutex; + struct fasync_struct *async_queue; + wait_queue_head_t waitq; + + spinlock_t lock; + __s64 bbu; /* BBU from device */ +}; +#define to_yurex_dev(d) container_of(d, struct usb_yurex, kref) + +static struct usb_driver yurex_driver; +static const struct file_operations yurex_fops; + + +static void yurex_control_callback(struct urb *urb) +{ + struct usb_yurex *dev = urb->context; + int status = urb->status; + + if (status) { + dev_err(&urb->dev->dev, "%s - control failed: %d\n", + __func__, status); + wake_up_interruptible(&dev->waitq); + return; + } + /* on success, sender woken up by CMD_ACK int in, or timeout */ +} + +static void yurex_delete(struct kref *kref) +{ + struct usb_yurex *dev = to_yurex_dev(kref); + + dev_dbg(&dev->interface->dev, "%s\n", __func__); + + usb_put_dev(dev->udev); + if (dev->cntl_urb) { + usb_kill_urb(dev->cntl_urb); + kfree(dev->cntl_req); + if (dev->cntl_buffer) + usb_free_coherent(dev->udev, YUREX_BUF_SIZE, + dev->cntl_buffer, dev->cntl_urb->transfer_dma); + usb_free_urb(dev->cntl_urb); + } + if (dev->urb) { + usb_kill_urb(dev->urb); + if (dev->int_buffer) + usb_free_coherent(dev->udev, YUREX_BUF_SIZE, + dev->int_buffer, dev->urb->transfer_dma); + usb_free_urb(dev->urb); + } + kfree(dev); +} + +/* + * usb class driver info in order to get a minor number from the usb core, + * and to have the device registered with the driver core + */ +static struct usb_class_driver yurex_class = { + .name = "yurex%d", + .fops = &yurex_fops, + .minor_base = YUREX_MINOR_BASE, +}; + +static void yurex_interrupt(struct urb *urb) +{ + struct usb_yurex *dev = urb->context; + unsigned char *buf = dev->int_buffer; + int status = urb->status; + unsigned long flags; + int retval, i; + + switch (status) { + case 0: /*success*/ + break; + case -EOVERFLOW: + dev_err(&dev->interface->dev, + "%s - overflow with length %d, actual length is %d\n", + __func__, YUREX_BUF_SIZE, dev->urb->actual_length); + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + case -EILSEQ: + /* The device is terminated, clean up */ + return; + default: + dev_err(&dev->interface->dev, + "%s - unknown status received: %d\n", __func__, status); + goto exit; + } + + /* handle received message */ + switch (buf[0]) { + case CMD_COUNT: + case CMD_READ: + if (buf[6] == CMD_EOF) { + spin_lock_irqsave(&dev->lock, flags); + dev->bbu = 0; + for (i = 1; i < 6; i++) { + dev->bbu += buf[i]; + if (i != 5) + dev->bbu <<= 8; + } + dev_dbg(&dev->interface->dev, "%s count: %lld\n", + __func__, dev->bbu); + spin_unlock_irqrestore(&dev->lock, flags); + + kill_fasync(&dev->async_queue, SIGIO, POLL_IN); + } + else + dev_dbg(&dev->interface->dev, + "data format error - no EOF\n"); + break; + case CMD_ACK: + dev_dbg(&dev->interface->dev, "%s ack: %c\n", + __func__, buf[1]); + wake_up_interruptible(&dev->waitq); + break; + } + +exit: + retval = usb_submit_urb(dev->urb, GFP_ATOMIC); + if (retval) { + dev_err(&dev->interface->dev, "%s - usb_submit_urb failed: %d\n", + __func__, retval); + } +} + +static int yurex_probe(struct usb_interface *interface, const struct usb_device_id *id) +{ + struct usb_yurex *dev; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + int retval = -ENOMEM; + int i; + DEFINE_WAIT(wait); + + /* allocate memory for our device state and initialize it */ + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) { + dev_err(&interface->dev, "Out of memory\n"); + goto error; + } + kref_init(&dev->kref); + mutex_init(&dev->io_mutex); + spin_lock_init(&dev->lock); + init_waitqueue_head(&dev->waitq); + + dev->udev = usb_get_dev(interface_to_usbdev(interface)); + dev->interface = interface; + + /* set up the endpoint information */ + iface_desc = interface->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { + endpoint = &iface_desc->endpoint[i].desc; + + if (usb_endpoint_is_int_in(endpoint)) { + dev->int_in_endpointAddr = endpoint->bEndpointAddress; + break; + } + } + if (!dev->int_in_endpointAddr) { + retval = -ENODEV; + dev_err(&interface->dev, "Could not find endpoints\n"); + goto error; + } + + + /* allocate control URB */ + dev->cntl_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!dev->cntl_urb) { + dev_err(&interface->dev, "Could not allocate control URB\n"); + goto error; + } + + /* allocate buffer for control req */ + dev->cntl_req = kmalloc(YUREX_BUF_SIZE, GFP_KERNEL); + if (!dev->cntl_req) { + dev_err(&interface->dev, "Could not allocate cntl_req\n"); + goto error; + } + + /* allocate buffer for control msg */ + dev->cntl_buffer = usb_alloc_coherent(dev->udev, YUREX_BUF_SIZE, + GFP_KERNEL, + &dev->cntl_urb->transfer_dma); + if (!dev->cntl_buffer) { + dev_err(&interface->dev, "Could not allocate cntl_buffer\n"); + goto error; + } + + /* configure control URB */ + dev->cntl_req->bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | + USB_RECIP_INTERFACE; + dev->cntl_req->bRequest = HID_REQ_SET_REPORT; + dev->cntl_req->wValue = cpu_to_le16((HID_OUTPUT_REPORT + 1) << 8); + dev->cntl_req->wIndex = cpu_to_le16(iface_desc->desc.bInterfaceNumber); + dev->cntl_req->wLength = cpu_to_le16(YUREX_BUF_SIZE); + + usb_fill_control_urb(dev->cntl_urb, dev->udev, + usb_sndctrlpipe(dev->udev, 0), + (void *)dev->cntl_req, dev->cntl_buffer, + YUREX_BUF_SIZE, yurex_control_callback, dev); + dev->cntl_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + + /* allocate interrupt URB */ + dev->urb = usb_alloc_urb(0, GFP_KERNEL); + if (!dev->urb) { + dev_err(&interface->dev, "Could not allocate URB\n"); + goto error; + } + + /* allocate buffer for interrupt in */ + dev->int_buffer = usb_alloc_coherent(dev->udev, YUREX_BUF_SIZE, + GFP_KERNEL, &dev->urb->transfer_dma); + if (!dev->int_buffer) { + dev_err(&interface->dev, "Could not allocate int_buffer\n"); + goto error; + } + + /* configure interrupt URB */ + usb_fill_int_urb(dev->urb, dev->udev, + usb_rcvintpipe(dev->udev, dev->int_in_endpointAddr), + dev->int_buffer, YUREX_BUF_SIZE, yurex_interrupt, + dev, 1); + dev->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + if (usb_submit_urb(dev->urb, GFP_KERNEL)) { + retval = -EIO; + dev_err(&interface->dev, "Could not submitting URB\n"); + goto error; + } + + /* save our data pointer in this interface device */ + usb_set_intfdata(interface, dev); + dev->bbu = -1; + + /* we can register the device now, as it is ready */ + retval = usb_register_dev(interface, &yurex_class); + if (retval) { + dev_err(&interface->dev, + "Not able to get a minor for this device.\n"); + usb_set_intfdata(interface, NULL); + goto error; + } + + dev_info(&interface->dev, + "USB YUREX device now attached to Yurex #%d\n", + interface->minor); + + return 0; + +error: + if (dev) + /* this frees allocated memory */ + kref_put(&dev->kref, yurex_delete); + return retval; +} + +static void yurex_disconnect(struct usb_interface *interface) +{ + struct usb_yurex *dev; + int minor = interface->minor; + + dev = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); + + /* give back our minor */ + usb_deregister_dev(interface, &yurex_class); + + /* prevent more I/O from starting */ + mutex_lock(&dev->io_mutex); + dev->interface = NULL; + mutex_unlock(&dev->io_mutex); + + /* wakeup waiters */ + kill_fasync(&dev->async_queue, SIGIO, POLL_IN); + wake_up_interruptible(&dev->waitq); + + /* decrement our usage count */ + kref_put(&dev->kref, yurex_delete); + + dev_info(&interface->dev, "USB YUREX #%d now disconnected\n", minor); +} + +static struct usb_driver yurex_driver = { + .name = "yurex", + .probe = yurex_probe, + .disconnect = yurex_disconnect, + .id_table = yurex_table, +}; + + +static int yurex_fasync(int fd, struct file *file, int on) +{ + struct usb_yurex *dev; + + dev = (struct usb_yurex *)file->private_data; + return fasync_helper(fd, file, on, &dev->async_queue); +} + +static int yurex_open(struct inode *inode, struct file *file) +{ + struct usb_yurex *dev; + struct usb_interface *interface; + int subminor; + int retval = 0; + + subminor = iminor(inode); + + interface = usb_find_interface(&yurex_driver, subminor); + if (!interface) { + printk(KERN_ERR "%s - error, can't find device for minor %d", + __func__, subminor); + retval = -ENODEV; + goto exit; + } + + dev = usb_get_intfdata(interface); + if (!dev) { + retval = -ENODEV; + goto exit; + } + + /* increment our usage count for the device */ + kref_get(&dev->kref); + + /* save our object in the file's private structure */ + mutex_lock(&dev->io_mutex); + file->private_data = dev; + mutex_unlock(&dev->io_mutex); + +exit: + return retval; +} + +static int yurex_release(struct inode *inode, struct file *file) +{ + struct usb_yurex *dev; + + dev = (struct usb_yurex *)file->private_data; + if (dev == NULL) + return -ENODEV; + + /* decrement the count on our device */ + kref_put(&dev->kref, yurex_delete); + return 0; +} + +static ssize_t yurex_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +{ + struct usb_yurex *dev; + int retval = 0; + int bytes_read = 0; + char in_buffer[20]; + unsigned long flags; + + dev = (struct usb_yurex *)file->private_data; + + mutex_lock(&dev->io_mutex); + if (!dev->interface) { /* already disconnected */ + retval = -ENODEV; + goto exit; + } + + spin_lock_irqsave(&dev->lock, flags); + bytes_read = snprintf(in_buffer, 20, "%lld\n", dev->bbu); + spin_unlock_irqrestore(&dev->lock, flags); + + if (*ppos < bytes_read) { + if (copy_to_user(buffer, in_buffer + *ppos, bytes_read - *ppos)) + retval = -EFAULT; + else { + retval = bytes_read - *ppos; + *ppos += bytes_read; + } + } + +exit: + mutex_unlock(&dev->io_mutex); + return retval; +} + +static ssize_t yurex_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos) +{ + struct usb_yurex *dev; + int i, set = 0, retval = 0; + char buffer[16]; + char *data = buffer; + unsigned long long c, c2 = 0; + signed long timeout = 0; + DEFINE_WAIT(wait); + + count = min(sizeof(buffer), count); + dev = (struct usb_yurex *)file->private_data; + + /* verify that we actually have some data to write */ + if (count == 0) + goto error; + + mutex_lock(&dev->io_mutex); + if (!dev->interface) { /* already disconnected */ + mutex_unlock(&dev->io_mutex); + retval = -ENODEV; + goto error; + } + + if (copy_from_user(buffer, user_buffer, count)) { + mutex_unlock(&dev->io_mutex); + retval = -EFAULT; + goto error; + } + memset(dev->cntl_buffer, CMD_PADDING, YUREX_BUF_SIZE); + + switch (buffer[0]) { + case CMD_ANIMATE: + case CMD_LED: + dev->cntl_buffer[0] = buffer[0]; + dev->cntl_buffer[1] = buffer[1]; + dev->cntl_buffer[2] = CMD_EOF; + break; + case CMD_READ: + case CMD_VERSION: + dev->cntl_buffer[0] = buffer[0]; + dev->cntl_buffer[1] = 0x00; + dev->cntl_buffer[2] = CMD_EOF; + break; + case CMD_SET: + data++; + /* FALL THROUGH */ + case '0' ... '9': + set = 1; + c = c2 = simple_strtoull(data, NULL, 0); + dev->cntl_buffer[0] = CMD_SET; + for (i = 1; i < 6; i++) { + dev->cntl_buffer[i] = (c>>32) & 0xff; + c <<= 8; + } + buffer[6] = CMD_EOF; + break; + default: + mutex_unlock(&dev->io_mutex); + return -EINVAL; + } + + /* send the data as the control msg */ + prepare_to_wait(&dev->waitq, &wait, TASK_INTERRUPTIBLE); + dev_dbg(&dev->interface->dev, "%s - submit %c\n", __func__, + dev->cntl_buffer[0]); + retval = usb_submit_urb(dev->cntl_urb, GFP_KERNEL); + if (retval >= 0) + timeout = schedule_timeout(YUREX_WRITE_TIMEOUT); + finish_wait(&dev->waitq, &wait); + + mutex_unlock(&dev->io_mutex); + + if (retval < 0) { + dev_err(&dev->interface->dev, + "%s - failed to send bulk msg, error %d\n", + __func__, retval); + goto error; + } + if (set && timeout) + dev->bbu = c2; + return timeout ? count : -EIO; + +error: + return retval; +} + +static const struct file_operations yurex_fops = { + .owner = THIS_MODULE, + .read = yurex_read, + .write = yurex_write, + .open = yurex_open, + .release = yurex_release, + .fasync = yurex_fasync, + .llseek = default_llseek, +}; + +module_usb_driver(yurex_driver); + +MODULE_LICENSE("GPL"); |
