diff options
author | Steve French <sfrench@us.ibm.com> | 2005-10-31 08:36:11 -0800 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2005-10-31 08:36:11 -0800 |
commit | 53b2ec5518aa2623e8c0cb36f1c304a797988a46 (patch) | |
tree | 465d8631ade6c2fcbd7576ff9813d00116c6a1e8 /drivers/usb | |
parent | 0753ca7bc2b876dd136e9db11a20f85cbe4e08b1 (diff) | |
parent | 581c1b14394aee60aff46ea67d05483261ed6527 (diff) | |
download | op-kernel-dev-53b2ec5518aa2623e8c0cb36f1c304a797988a46.zip op-kernel-dev-53b2ec5518aa2623e8c0cb36f1c304a797988a46.tar.gz |
Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Diffstat (limited to 'drivers/usb')
161 files changed, 5251 insertions, 5475 deletions
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index df014c2..a50c2bc 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_USB) += core/ obj-$(CONFIG_USB_MON) += mon/ +obj-$(CONFIG_PCI) += host/ obj-$(CONFIG_USB_EHCI_HCD) += host/ obj-$(CONFIG_USB_ISP116X_HCD) += host/ obj-$(CONFIG_USB_OHCI_HCD) += host/ @@ -17,7 +18,6 @@ obj-$(CONFIG_ETRAX_USB_HOST) += host/ obj-$(CONFIG_USB_ACM) += class/ obj-$(CONFIG_USB_AUDIO) += class/ -obj-$(CONFIG_USB_BLUETOOTH_TTY) += class/ obj-$(CONFIG_USB_MIDI) += class/ obj-$(CONFIG_USB_PRINTER) += class/ diff --git a/drivers/usb/class/Kconfig b/drivers/usb/class/Kconfig index 333e39b..ef105a9 100644 --- a/drivers/usb/class/Kconfig +++ b/drivers/usb/class/Kconfig @@ -28,29 +28,6 @@ config USB_AUDIO To compile this driver as a module, choose M here: the module will be called audio. -comment "USB Bluetooth TTY can only be used with disabled Bluetooth subsystem" - depends on USB && BT - -config USB_BLUETOOTH_TTY - tristate "USB Bluetooth TTY support" - depends on USB && BT=n - ---help--- - This driver implements a nonstandard tty interface to a Bluetooth - device that can be used only by specialized Bluetooth HCI software. - - Say Y here if you want to use OpenBT Bluetooth stack (available - at <http://developer.axis.com/software>), or other TTY based - Bluetooth stacks, and want to connect a USB Bluetooth device - to your computer's USB port. - - Do *not* enable this driver if you want to use generic Linux - Bluetooth support. - - If in doubt, say N here. - - To compile this driver as a module, choose M here: the - module will be called bluetty. - config USB_MIDI tristate "USB MIDI support" depends on USB && SOUND && OBSOLETE_OSS_USB_DRIVER diff --git a/drivers/usb/class/Makefile b/drivers/usb/class/Makefile index 971e549..2294712 100644 --- a/drivers/usb/class/Makefile +++ b/drivers/usb/class/Makefile @@ -5,6 +5,5 @@ obj-$(CONFIG_USB_ACM) += cdc-acm.o obj-$(CONFIG_USB_AUDIO) += audio.o -obj-$(CONFIG_USB_BLUETOOTH_TTY) += bluetty.o obj-$(CONFIG_USB_MIDI) += usb-midi.o obj-$(CONFIG_USB_PRINTER) += usblp.o diff --git a/drivers/usb/class/bluetty.c b/drivers/usb/class/bluetty.c deleted file mode 100644 index 5240233..0000000 --- a/drivers/usb/class/bluetty.c +++ /dev/null @@ -1,1279 +0,0 @@ -/* - * bluetty.c Version 0.13 - * - * Copyright (C) 2000, 2001 Greg Kroah-Hartman <greg@kroah.com> - * Copyright (C) 2000 Mark Douglas Corner <mcorner@umich.edu> - * - * USB Bluetooth TTY driver, based on the Bluetooth Spec version 1.0B - * - * (2001/11/30) Version 0.13 gkh - * - added locking patch from Masoodur Rahman <rmasoodu@in.ibm.com> - * - removed active variable, as open_count will do. - * - * (2001/07/09) Version 0.12 gkh - * - removed in_interrupt() call, as it doesn't make sense to do - * that anymore. - * - * (2001/06/05) Version 0.11 gkh - * - Fixed problem with read urb status saying that we have shutdown, - * and that we shouldn't resubmit the urb. Patch from unknown. - * - * (2001/05/28) Version 0.10 gkh - * - Fixed problem with using data from userspace in the bluetooth_write - * function as found by the CHECKER project. - * - Added a buffer to the write_urb_pool which reduces the number of - * buffers being created and destroyed for ever write. Also cleans - * up the logic a bit. - * - Added a buffer to the control_urb_pool which fixes a memory leak - * when the device is removed from the system. - * - * (2001/05/28) Version 0.9 gkh - * Fixed problem with bluetooth==NULL for bluetooth_read_bulk_callback - * which was found by both the CHECKER project and Mikko Rahkonen. - * - * (08/04/2001) gb - * Identify version on module load. - * - * (2001/03/10) Version 0.8 gkh - * Fixed problem with not unlinking interrupt urb on device close - * and resubmitting the read urb on error with bluetooth struct. - * Thanks to Narayan Mohanram <narayan@RovingNetworks.com> for the - * fixes. - * - * (11/29/2000) Version 0.7 gkh - * Fixed problem with overrunning the tty flip buffer. - * Removed unneeded NULL pointer initialization. - * - * (10/05/2000) Version 0.6 gkh - * Fixed bug with urb->dev not being set properly, now that the usb - * core needs it. - * Got a real major id number and name. - * - * (08/06/2000) Version 0.5 gkh - * Fixed problem of not resubmitting the bulk read urb if there is - * an error in the callback. Ericsson devices seem to need this. - * - * (07/11/2000) Version 0.4 gkh - * Fixed bug in disconnect for when we call tty_hangup - * Fixed bug in bluetooth_ctrl_msg where the bluetooth struct was not - * getting attached to the control urb properly. - * Fixed bug in bluetooth_write where we pay attention to the result - * of bluetooth_ctrl_msg. - * - * (08/03/2000) Version 0.3 gkh mdc - * Merged in Mark's changes to make the driver play nice with the Axis - * stack. - * Made the write bulk use an urb pool to enable larger transfers with - * fewer calls to the driver. - * Fixed off by one bug in acl pkt receive - * Made packet counters specific to each bluetooth device - * Added checks for zero length callbacks - * Added buffers for int and bulk packets. Had to do this otherwise - * packet types could intermingle. - * Made a control urb pool for the control messages. - * - * (07/11/2000) Version 0.2 gkh - * Fixed a small bug found by Nils Faerber in the usb_bluetooth_probe - * function. - * - * (07/09/2000) Version 0.1 gkh - * Initial release. Has support for sending ACL data (which is really just - * a HCI frame.) Raw HCI commands and HCI events are not supported. - * A ioctl will probably be needed for the HCI commands and events in the - * future. All isoch endpoints are ignored at this time also. - * This driver should work for all currently shipping USB Bluetooth - * devices at this time :) - * - */ - -/* - * 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/kernel.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/tty.h> -#include <linux/tty_driver.h> -#include <linux/tty_flip.h> -#include <linux/module.h> -#include <asm/uaccess.h> - -#define DEBUG -#include <linux/usb.h> - -/* - * Version Information - */ -#define DRIVER_VERSION "v0.13" -#define DRIVER_AUTHOR "Greg Kroah-Hartman, Mark Douglas Corner" -#define DRIVER_DESC "USB Bluetooth tty driver" - -/* define this if you have hardware that is not good */ -/*#define BTBUGGYHARDWARE */ - -/* Class, SubClass, and Protocol codes that describe a Bluetooth device */ -#define WIRELESS_CLASS_CODE 0xe0 -#define RF_SUBCLASS_CODE 0x01 -#define BLUETOOTH_PROGRAMMING_PROTOCOL_CODE 0x01 - - -#define BLUETOOTH_TTY_MAJOR 216 /* real device node major id */ -#define BLUETOOTH_TTY_MINORS 256 /* whole lotta bluetooth devices */ - -#define USB_BLUETOOTH_MAGIC 0x6d02 /* magic number for bluetooth struct */ - -#define BLUETOOTH_CONTROL_REQUEST_TYPE 0x20 - -/* Bluetooth packet types */ -#define CMD_PKT 0x01 -#define ACL_PKT 0x02 -#define SCO_PKT 0x03 -#define EVENT_PKT 0x04 -#define ERROR_PKT 0x05 -#define NEG_PKT 0x06 - -/* Message sizes */ -#define MAX_EVENT_SIZE 0xFF -#define EVENT_HDR_SIZE 3 /* 2 for the header + 1 for the type indicator */ -#define EVENT_BUFFER_SIZE (MAX_EVENT_SIZE + EVENT_HDR_SIZE) - -#define MAX_ACL_SIZE 0xFFFF -#define ACL_HDR_SIZE 5 /* 4 for the header + 1 for the type indicator */ -#define ACL_BUFFER_SIZE (MAX_ACL_SIZE + ACL_HDR_SIZE) - -/* parity check flag */ -#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) - -#define CHAR2INT16(c1,c0) (((u32)((c1) & 0xff) << 8) + (u32)((c0) & 0xff)) - -#define NUM_BULK_URBS 24 -#define NUM_CONTROL_URBS 16 - -struct usb_bluetooth { - int magic; - struct usb_device * dev; - struct tty_driver * tty_driver; /* the tty_driver for this device */ - struct tty_struct * tty; /* the corresponding tty for this port */ - - unsigned char minor; /* the starting minor number for this device */ - int throttle; /* throttled by tty layer */ - int open_count; - - __u8 control_out_bInterfaceNum; - struct urb * control_urb_pool[NUM_CONTROL_URBS]; - struct usb_ctrlrequest dr[NUM_CONTROL_URBS]; - - unsigned char * interrupt_in_buffer; - struct urb * interrupt_in_urb; - __u8 interrupt_in_endpointAddress; - __u8 interrupt_in_interval; - int interrupt_in_buffer_size; - - unsigned char * bulk_in_buffer; - struct urb * read_urb; - __u8 bulk_in_endpointAddress; - int bulk_in_buffer_size; - - int bulk_out_buffer_size; - __u8 bulk_out_endpointAddress; - - wait_queue_head_t write_wait; - - struct work_struct work; /* work queue entry for line discipline waking up */ - - unsigned int int_packet_pos; - unsigned char int_buffer[EVENT_BUFFER_SIZE]; - unsigned int bulk_packet_pos; - unsigned char bulk_buffer[ACL_BUFFER_SIZE]; /* 64k preallocated, fix? */ - struct semaphore lock; -}; - - -/* local function prototypes */ -static int bluetooth_open (struct tty_struct *tty, struct file *filp); -static void bluetooth_close (struct tty_struct *tty, struct file *filp); -static int bluetooth_write (struct tty_struct *tty, const unsigned char *buf, int count); -static int bluetooth_write_room (struct tty_struct *tty); -static int bluetooth_chars_in_buffer (struct tty_struct *tty); -static void bluetooth_throttle (struct tty_struct *tty); -static void bluetooth_unthrottle (struct tty_struct *tty); -static int bluetooth_ioctl (struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); -static void bluetooth_set_termios (struct tty_struct *tty, struct termios *old); - -static void bluetooth_int_callback (struct urb *urb, struct pt_regs *regs); -static void bluetooth_ctrl_callback (struct urb *urb, struct pt_regs *regs); -static void bluetooth_read_bulk_callback (struct urb *urb, struct pt_regs *regs); -static void bluetooth_write_bulk_callback (struct urb *urb, struct pt_regs *regs); - -static int usb_bluetooth_probe (struct usb_interface *intf, - const struct usb_device_id *id); -static void usb_bluetooth_disconnect (struct usb_interface *intf); - - -static struct usb_device_id usb_bluetooth_ids [] = { - { USB_DEVICE_INFO(WIRELESS_CLASS_CODE, RF_SUBCLASS_CODE, BLUETOOTH_PROGRAMMING_PROTOCOL_CODE) }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, usb_bluetooth_ids); - -static struct usb_driver usb_bluetooth_driver = { - .owner = THIS_MODULE, - .name = "bluetty", - .probe = usb_bluetooth_probe, - .disconnect = usb_bluetooth_disconnect, - .id_table = usb_bluetooth_ids, -}; - -static struct tty_driver *bluetooth_tty_driver; -static struct usb_bluetooth *bluetooth_table[BLUETOOTH_TTY_MINORS]; - - -static inline int bluetooth_paranoia_check (struct usb_bluetooth *bluetooth, const char *function) -{ - if (!bluetooth) { - dbg("%s - bluetooth == NULL", function); - return -1; - } - if (bluetooth->magic != USB_BLUETOOTH_MAGIC) { - dbg("%s - bad magic number for bluetooth", function); - return -1; - } - - return 0; -} - - -static inline struct usb_bluetooth* get_usb_bluetooth (struct usb_bluetooth *bluetooth, const char *function) -{ - if (!bluetooth || - bluetooth_paranoia_check (bluetooth, function)) { - /* then say that we don't have a valid usb_bluetooth thing, which will - * end up generating -ENODEV return values */ - return NULL; - } - - return bluetooth; -} - - -static inline struct usb_bluetooth *get_bluetooth_by_index (int index) -{ - return bluetooth_table[index]; -} - - -static int bluetooth_ctrl_msg (struct usb_bluetooth *bluetooth, int request, int value, const unsigned char *buf, int len) -{ - struct urb *urb = NULL; - struct usb_ctrlrequest *dr = NULL; - int i; - int status; - - dbg ("%s", __FUNCTION__); - - /* try to find a free urb in our list */ - for (i = 0; i < NUM_CONTROL_URBS; ++i) { - if (bluetooth->control_urb_pool[i]->status != -EINPROGRESS) { - urb = bluetooth->control_urb_pool[i]; - dr = &bluetooth->dr[i]; - break; - } - } - if (urb == NULL) { - dbg ("%s - no free urbs", __FUNCTION__); - return -ENOMEM; - } - - /* keep increasing the urb transfer buffer to fit the size of the message */ - if (urb->transfer_buffer == NULL) { - urb->transfer_buffer = kmalloc (len, GFP_KERNEL); - if (urb->transfer_buffer == NULL) { - err ("%s - out of memory", __FUNCTION__); - return -ENOMEM; - } - } - if (urb->transfer_buffer_length < len) { - kfree(urb->transfer_buffer); - urb->transfer_buffer = kmalloc (len, GFP_KERNEL); - if (urb->transfer_buffer == NULL) { - err ("%s - out of memory", __FUNCTION__); - return -ENOMEM; - } - } - memcpy (urb->transfer_buffer, buf, len); - - dr->bRequestType= BLUETOOTH_CONTROL_REQUEST_TYPE; - dr->bRequest = request; - dr->wValue = cpu_to_le16((u16) value); - dr->wIndex = cpu_to_le16((u16) bluetooth->control_out_bInterfaceNum); - dr->wLength = cpu_to_le16((u16) len); - - usb_fill_control_urb (urb, bluetooth->dev, usb_sndctrlpipe(bluetooth->dev, 0), - (unsigned char*)dr, urb->transfer_buffer, len, bluetooth_ctrl_callback, bluetooth); - - /* send it down the pipe */ - status = usb_submit_urb(urb, GFP_KERNEL); - if (status) - dbg("%s - usb_submit_urb(control) failed with status = %d", __FUNCTION__, status); - - return status; -} - - - - - -/***************************************************************************** - * Driver tty interface functions - *****************************************************************************/ -static int bluetooth_open (struct tty_struct *tty, struct file * filp) -{ - struct usb_bluetooth *bluetooth; - int result; - - dbg("%s", __FUNCTION__); - - /* initialize the pointer incase something fails */ - tty->driver_data = NULL; - - /* get the bluetooth object associated with this tty pointer */ - bluetooth = get_bluetooth_by_index (tty->index); - - if (bluetooth_paranoia_check (bluetooth, __FUNCTION__)) { - return -ENODEV; - } - - down (&bluetooth->lock); - - ++bluetooth->open_count; - if (bluetooth->open_count == 1) { - /* set up our structure making the tty driver remember our object, and us it */ - tty->driver_data = bluetooth; - bluetooth->tty = tty; - - /* force low_latency on so that our tty_push actually forces the data through, - * otherwise it is scheduled, and with high data rates (like with OHCI) data - * can get lost. */ - bluetooth->tty->low_latency = 1; - - /* Reset the packet position counters */ - bluetooth->int_packet_pos = 0; - bluetooth->bulk_packet_pos = 0; - -#ifndef BTBUGGYHARDWARE - /* Start reading from the device */ - usb_fill_bulk_urb (bluetooth->read_urb, bluetooth->dev, - usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress), - bluetooth->bulk_in_buffer, - bluetooth->bulk_in_buffer_size, - bluetooth_read_bulk_callback, bluetooth); - result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL); - if (result) - dbg("%s - usb_submit_urb(read bulk) failed with status %d", __FUNCTION__, result); -#endif - usb_fill_int_urb (bluetooth->interrupt_in_urb, bluetooth->dev, - usb_rcvintpipe(bluetooth->dev, bluetooth->interrupt_in_endpointAddress), - bluetooth->interrupt_in_buffer, - bluetooth->interrupt_in_buffer_size, - bluetooth_int_callback, bluetooth, - bluetooth->interrupt_in_interval); - result = usb_submit_urb(bluetooth->interrupt_in_urb, GFP_KERNEL); - if (result) - dbg("%s - usb_submit_urb(interrupt in) failed with status %d", __FUNCTION__, result); - } - - up(&bluetooth->lock); - - return 0; -} - - -static void bluetooth_close (struct tty_struct *tty, struct file * filp) -{ - struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); - - if (!bluetooth) { - return; - } - - dbg("%s", __FUNCTION__); - - if (!bluetooth->open_count) { - dbg ("%s - device not opened", __FUNCTION__); - return; - } - - down (&bluetooth->lock); - - --bluetooth->open_count; - if (bluetooth->open_count <= 0) { - bluetooth->open_count = 0; - - /* shutdown any in-flight urbs that we know about */ - usb_kill_urb (bluetooth->read_urb); - usb_kill_urb (bluetooth->interrupt_in_urb); - } - up(&bluetooth->lock); -} - - -static int bluetooth_write (struct tty_struct * tty, const unsigned char *buf, int count) -{ - struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); - struct urb *urb = NULL; - unsigned char *temp_buffer = NULL; - const unsigned char *current_buffer; - unsigned char *urb_buffer; - int i; - int retval = 0; - - if (!bluetooth) { - return -ENODEV; - } - - dbg("%s - %d byte(s)", __FUNCTION__, count); - - if (!bluetooth->open_count) { - dbg ("%s - device not opened", __FUNCTION__); - return -EINVAL; - } - - if (count == 0) { - dbg("%s - write request of 0 bytes", __FUNCTION__); - return 0; - } - if (count == 1) { - dbg("%s - write request only included type %d", __FUNCTION__, buf[0]); - return 1; - } - -#ifdef DEBUG - printk (KERN_DEBUG __FILE__ ": %s - length = %d, data = ", __FUNCTION__, count); - for (i = 0; i < count; ++i) { - printk ("%.2x ", buf[i]); - } - printk ("\n"); -#endif - - current_buffer = buf; - - switch (*current_buffer) { - /* First byte indicates the type of packet */ - case CMD_PKT: - /* dbg("%s- Send cmd_pkt len:%d", __FUNCTION__, count);*/ - - retval = bluetooth_ctrl_msg (bluetooth, 0x00, 0x00, ¤t_buffer[1], count-1); - if (retval) { - goto exit; - } - retval = count; - break; - - case ACL_PKT: - ++current_buffer; - --count; - - urb_buffer = kmalloc (count, GFP_ATOMIC); - if (!urb_buffer) { - dev_err(&bluetooth->dev->dev, "out of memory\n"); - retval = -ENOMEM; - goto exit; - } - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!urb) { - dev_err(&bluetooth->dev->dev, "no more free urbs\n"); - kfree(urb_buffer); - retval = -ENOMEM; - goto exit; - } - memcpy (urb_buffer, current_buffer, count); - - /* build up our urb */ - usb_fill_bulk_urb(urb, bluetooth->dev, - usb_sndbulkpipe(bluetooth->dev, - bluetooth->bulk_out_endpointAddress), - urb_buffer, - count, - bluetooth_write_bulk_callback, - bluetooth); - - - /* send it down the pipe */ - retval = usb_submit_urb(urb, GFP_KERNEL); - if (retval) { - dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __FUNCTION__, retval); - goto exit; - } - - /* we are done with this urb, so let the host driver - * really free it when it is finished with it */ - usb_free_urb (urb); - retval = count + 1; - break; - - default : - dbg("%s - unsupported (at this time) write type", __FUNCTION__); - retval = -EINVAL; - break; - } - -exit: - kfree(temp_buffer); - - return retval; -} - - -static int bluetooth_write_room (struct tty_struct *tty) -{ - dbg("%s", __FUNCTION__); - - /* - * We really can take anything the user throws at us - * but let's pick a nice big number to tell the tty - * layer that we have lots of free space - */ - return 2048; -} - - -static int bluetooth_chars_in_buffer (struct tty_struct *tty) -{ - dbg("%s", __FUNCTION__); - - /* - * We can't really account for how much data we - * have sent out, but hasn't made it through to the - * device, so just tell the tty layer that everything - * is flushed. - */ - return 0; -} - - -static void bluetooth_throttle (struct tty_struct * tty) -{ - struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); - - if (!bluetooth) { - return; - } - - dbg("%s", __FUNCTION__); - - if (!bluetooth->open_count) { - dbg ("%s - device not open", __FUNCTION__); - return; - } - - dbg("%s unsupported (at this time)", __FUNCTION__); - - return; -} - - -static void bluetooth_unthrottle (struct tty_struct * tty) -{ - struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); - - if (!bluetooth) { - return; - } - - dbg("%s", __FUNCTION__); - - if (!bluetooth->open_count) { - dbg ("%s - device not open", __FUNCTION__); - return; - } - - dbg("%s unsupported (at this time)", __FUNCTION__); -} - - -static int bluetooth_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) -{ - struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); - - if (!bluetooth) { - return -ENODEV; - } - - dbg("%s - cmd 0x%.4x", __FUNCTION__, cmd); - - if (!bluetooth->open_count) { - dbg ("%s - device not open", __FUNCTION__); - return -ENODEV; - } - - /* FIXME!!! */ - return -ENOIOCTLCMD; -} - - -static void bluetooth_set_termios (struct tty_struct *tty, struct termios * old) -{ - struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); - - if (!bluetooth) { - return; - } - - dbg("%s", __FUNCTION__); - - if (!bluetooth->open_count) { - dbg ("%s - device not open", __FUNCTION__); - return; - } - - /* FIXME!!! */ - - return; -} - - -#ifdef BTBUGGYHARDWARE -void btusb_enable_bulk_read(struct tty_struct *tty){ - struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); - int result; - - if (!bluetooth) { - return; - } - - dbg("%s", __FUNCTION__); - - if (!bluetooth->open_count) { - dbg ("%s - device not open", __FUNCTION__); - return; - } - - if (bluetooth->read_urb) { - usb_fill_bulk_urb(bluetooth->read_urb, bluetooth->dev, - usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress), - bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, - bluetooth_read_bulk_callback, bluetooth); - result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL); - if (result) - err ("%s - failed submitting read urb, error %d", __FUNCTION__, result); - } -} - -void btusb_disable_bulk_read(struct tty_struct *tty){ - struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); - - if (!bluetooth) { - return; - } - - dbg("%s", __FUNCTION__); - - if (!bluetooth->open_count) { - dbg ("%s - device not open", __FUNCTION__); - return; - } - - if ((bluetooth->read_urb) && (bluetooth->read_urb->actual_length)) - usb_kill_urb(bluetooth->read_urb); -} -#endif - - -/***************************************************************************** - * urb callback functions - *****************************************************************************/ - - -static void bluetooth_int_callback (struct urb *urb, struct pt_regs *regs) -{ - struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__); - unsigned char *data = urb->transfer_buffer; - unsigned int i; - unsigned int count = urb->actual_length; - unsigned int packet_size; - int status; - - dbg("%s", __FUNCTION__); - - if (!bluetooth) { - dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__); - return; - } - - switch (urb->status) { - case 0: - /* success */ - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); - return; - default: - dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); - goto exit; - } - - if (!count) { - dbg("%s - zero length int", __FUNCTION__); - goto exit; - } - - -#ifdef DEBUG - if (count) { - printk (KERN_DEBUG __FILE__ ": %s- length = %d, data = ", __FUNCTION__, count); - for (i = 0; i < count; ++i) { - printk ("%.2x ", data[i]); - } - printk ("\n"); - } -#endif - -#ifdef BTBUGGYHARDWARE - if ((count >= 2) && (data[0] == 0xFF) && (data[1] == 0x00)) { - data += 2; - count -= 2; - } - if (count == 0) { - urb->actual_length = 0; - goto exit; - } -#endif - /* We add a packet type identifier to the beginning of each - HCI frame. This makes the data in the tty look like a - serial USB devices. Each HCI frame can be broken across - multiple URBs so we buffer them until we have a full hci - packet */ - - if (!bluetooth->int_packet_pos) { - bluetooth->int_buffer[0] = EVENT_PKT; - bluetooth->int_packet_pos++; - } - - if (bluetooth->int_packet_pos + count > EVENT_BUFFER_SIZE) { - err("%s - exceeded EVENT_BUFFER_SIZE", __FUNCTION__); - bluetooth->int_packet_pos = 0; - goto exit; - } - - memcpy (&bluetooth->int_buffer[bluetooth->int_packet_pos], - urb->transfer_buffer, count); - bluetooth->int_packet_pos += count; - urb->actual_length = 0; - - if (bluetooth->int_packet_pos >= EVENT_HDR_SIZE) - packet_size = bluetooth->int_buffer[2]; - else - goto exit; - - if (packet_size + EVENT_HDR_SIZE < bluetooth->int_packet_pos) { - err("%s - packet was too long", __FUNCTION__); - bluetooth->int_packet_pos = 0; - goto exit; - } - - if (packet_size + EVENT_HDR_SIZE == bluetooth->int_packet_pos) { - for (i = 0; i < bluetooth->int_packet_pos; ++i) { - /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them */ - if (bluetooth->tty->flip.count >= TTY_FLIPBUF_SIZE) { - tty_flip_buffer_push(bluetooth->tty); - } - tty_insert_flip_char(bluetooth->tty, bluetooth->int_buffer[i], 0); - } - tty_flip_buffer_push(bluetooth->tty); - - bluetooth->int_packet_pos = 0; - } - -exit: - status = usb_submit_urb (urb, GFP_ATOMIC); - if (status) - err ("%s - usb_submit_urb failed with result %d", - __FUNCTION__, status); -} - - -static void bluetooth_ctrl_callback (struct urb *urb, struct pt_regs *regs) -{ - struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__); - - dbg("%s", __FUNCTION__); - - if (!bluetooth) { - dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__); - return; - } - - if (urb->status) { - dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); - return; - } -} - - -static void bluetooth_read_bulk_callback (struct urb *urb, struct pt_regs *regs) -{ - struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__); - unsigned char *data = urb->transfer_buffer; - unsigned int count = urb->actual_length; - unsigned int i; - unsigned int packet_size; - int result; - - - dbg("%s", __FUNCTION__); - - if (!bluetooth) { - dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__); - return; - } - - if (urb->status) { - dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); - if (urb->status == -ENOENT) { - dbg("%s - URB canceled, won't reschedule", __FUNCTION__); - return; - } - goto exit; - } - - if (!count) { - dbg("%s - zero length read bulk", __FUNCTION__); - goto exit; - } - -#ifdef DEBUG - if (count) { - printk (KERN_DEBUG __FILE__ ": %s- length = %d, data = ", __FUNCTION__, count); - for (i = 0; i < count; ++i) { - printk ("%.2x ", data[i]); - } - printk ("\n"); - } -#endif -#ifdef BTBUGGYHARDWARE - if ((count == 4) && (data[0] == 0x00) && (data[1] == 0x00) - && (data[2] == 0x00) && (data[3] == 0x00)) { - urb->actual_length = 0; - usb_fill_bulk_urb(bluetooth->read_urb, bluetooth->dev, - usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress), - bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, - bluetooth_read_bulk_callback, bluetooth); - result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL); - if (result) - err ("%s - failed resubmitting read urb, error %d", __FUNCTION__, result); - - return; - } -#endif - /* We add a packet type identifier to the beginning of each - HCI frame. This makes the data in the tty look like a - serial USB devices. Each HCI frame can be broken across - multiple URBs so we buffer them until we have a full hci - packet */ - - if (!bluetooth->bulk_packet_pos) { - bluetooth->bulk_buffer[0] = ACL_PKT; - bluetooth->bulk_packet_pos++; - } - - if (bluetooth->bulk_packet_pos + count > ACL_BUFFER_SIZE) { - err("%s - exceeded ACL_BUFFER_SIZE", __FUNCTION__); - bluetooth->bulk_packet_pos = 0; - goto exit; - } - - memcpy (&bluetooth->bulk_buffer[bluetooth->bulk_packet_pos], - urb->transfer_buffer, count); - bluetooth->bulk_packet_pos += count; - urb->actual_length = 0; - - if (bluetooth->bulk_packet_pos >= ACL_HDR_SIZE) { - packet_size = CHAR2INT16(bluetooth->bulk_buffer[4],bluetooth->bulk_buffer[3]); - } else { - goto exit; - } - - if (packet_size + ACL_HDR_SIZE < bluetooth->bulk_packet_pos) { - err("%s - packet was too long", __FUNCTION__); - bluetooth->bulk_packet_pos = 0; - goto exit; - } - - if (packet_size + ACL_HDR_SIZE == bluetooth->bulk_packet_pos) { - for (i = 0; i < bluetooth->bulk_packet_pos; ++i) { - /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */ - if (bluetooth->tty->flip.count >= TTY_FLIPBUF_SIZE) { - tty_flip_buffer_push(bluetooth->tty); - } - tty_insert_flip_char(bluetooth->tty, bluetooth->bulk_buffer[i], 0); - } - tty_flip_buffer_push(bluetooth->tty); - bluetooth->bulk_packet_pos = 0; - } - -exit: - if (!bluetooth || !bluetooth->open_count) - return; - - usb_fill_bulk_urb(bluetooth->read_urb, bluetooth->dev, - usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress), - bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, - bluetooth_read_bulk_callback, bluetooth); - result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL); - if (result) - err ("%s - failed resubmitting read urb, error %d", __FUNCTION__, result); - - return; -} - - -static void bluetooth_write_bulk_callback (struct urb *urb, struct pt_regs *regs) -{ - struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__); - - dbg("%s", __FUNCTION__); - - /* free up the transfer buffer, as usb_free_urb() does not do this */ - kfree(urb->transfer_buffer); - - if (!bluetooth) { - dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__); - return; - } - - if (urb->status) { - dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); - return; - } - - /* wake up our little function to let the tty layer know that something happened */ - schedule_work(&bluetooth->work); -} - - -static void bluetooth_softint(void *private) -{ - struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)private, __FUNCTION__); - - dbg("%s", __FUNCTION__); - - if (!bluetooth) - return; - - tty_wakeup(bluetooth->tty); -} - - -static int usb_bluetooth_probe (struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev (intf); - struct usb_bluetooth *bluetooth = NULL; - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct usb_endpoint_descriptor *interrupt_in_endpoint[8]; - struct usb_endpoint_descriptor *bulk_in_endpoint[8]; - struct usb_endpoint_descriptor *bulk_out_endpoint[8]; - int control_out_endpoint; - - int minor; - int buffer_size; - int i; - int num_interrupt_in = 0; - int num_bulk_in = 0; - int num_bulk_out = 0; - - interface = intf->cur_altsetting; - control_out_endpoint = interface->desc.bInterfaceNumber; - - /* find the endpoints that we need */ - for (i = 0; i < interface->desc.bNumEndpoints; ++i) { - endpoint = &interface->endpoint[i].desc; - - if ((endpoint->bEndpointAddress & 0x80) && - ((endpoint->bmAttributes & 3) == 0x02)) { - /* we found a bulk in endpoint */ - dbg("found bulk in"); - bulk_in_endpoint[num_bulk_in] = endpoint; - ++num_bulk_in; - } - - if (((endpoint->bEndpointAddress & 0x80) == 0x00) && - ((endpoint->bmAttributes & 3) == 0x02)) { - /* we found a bulk out endpoint */ - dbg("found bulk out"); - bulk_out_endpoint[num_bulk_out] = endpoint; - ++num_bulk_out; - } - - if ((endpoint->bEndpointAddress & 0x80) && - ((endpoint->bmAttributes & 3) == 0x03)) { - /* we found a interrupt in endpoint */ - dbg("found interrupt in"); - interrupt_in_endpoint[num_interrupt_in] = endpoint; - ++num_interrupt_in; - } - } - - /* according to the spec, we can only have 1 bulk_in, 1 bulk_out, and 1 interrupt_in endpoints */ - if ((num_bulk_in != 1) || - (num_bulk_out != 1) || - (num_interrupt_in != 1)) { - dbg ("%s - improper number of endpoints. Bluetooth driver not bound.", __FUNCTION__); - return -EIO; - } - - info("USB Bluetooth converter detected"); - - for (minor = 0; minor < BLUETOOTH_TTY_MINORS && bluetooth_table[minor]; ++minor) - ; - if (bluetooth_table[minor]) { - err("No more free Bluetooth devices"); - return -ENODEV; - } - - if (!(bluetooth = kmalloc(sizeof(struct usb_bluetooth), GFP_KERNEL))) { - err("Out of memory"); - return -ENOMEM; - } - - memset(bluetooth, 0, sizeof(struct usb_bluetooth)); - - bluetooth->magic = USB_BLUETOOTH_MAGIC; - bluetooth->dev = dev; - bluetooth->minor = minor; - INIT_WORK(&bluetooth->work, bluetooth_softint, bluetooth); - init_MUTEX(&bluetooth->lock); - - /* record the interface number for the control out */ - bluetooth->control_out_bInterfaceNum = control_out_endpoint; - - /* create our control out urb pool */ - for (i = 0; i < NUM_CONTROL_URBS; ++i) { - struct urb *urb = usb_alloc_urb(0, GFP_KERNEL); - if (urb == NULL) { - err("No free urbs available"); - goto probe_error; - } - urb->transfer_buffer = NULL; - bluetooth->control_urb_pool[i] = urb; - } - - /* set up the endpoint information */ - endpoint = bulk_in_endpoint[0]; - bluetooth->read_urb = usb_alloc_urb (0, GFP_KERNEL); - if (!bluetooth->read_urb) { - err("No free urbs available"); - goto probe_error; - } - bluetooth->bulk_in_buffer_size = buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); - bluetooth->bulk_in_endpointAddress = endpoint->bEndpointAddress; - bluetooth->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL); - if (!bluetooth->bulk_in_buffer) { - err("Couldn't allocate bulk_in_buffer"); - goto probe_error; - } - usb_fill_bulk_urb(bluetooth->read_urb, dev, usb_rcvbulkpipe(dev, endpoint->bEndpointAddress), - bluetooth->bulk_in_buffer, buffer_size, bluetooth_read_bulk_callback, bluetooth); - - endpoint = bulk_out_endpoint[0]; - bluetooth->bulk_out_endpointAddress = endpoint->bEndpointAddress; - bluetooth->bulk_out_buffer_size = le16_to_cpu(endpoint->wMaxPacketSize) * 2; - - endpoint = interrupt_in_endpoint[0]; - bluetooth->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!bluetooth->interrupt_in_urb) { - err("No free urbs available"); - goto probe_error; - } - bluetooth->interrupt_in_buffer_size = buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); - bluetooth->interrupt_in_endpointAddress = endpoint->bEndpointAddress; - bluetooth->interrupt_in_interval = endpoint->bInterval; - bluetooth->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL); - if (!bluetooth->interrupt_in_buffer) { - err("Couldn't allocate interrupt_in_buffer"); - goto probe_error; - } - usb_fill_int_urb(bluetooth->interrupt_in_urb, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress), - bluetooth->interrupt_in_buffer, buffer_size, bluetooth_int_callback, - bluetooth, endpoint->bInterval); - - /* initialize the devfs nodes for this device and let the user know what bluetooths we are bound to */ - tty_register_device (bluetooth_tty_driver, minor, &intf->dev); - info("Bluetooth converter now attached to ttyUB%d (or usb/ttub/%d for devfs)", minor, minor); - - bluetooth_table[minor] = bluetooth; - - /* success */ - usb_set_intfdata (intf, bluetooth); - return 0; - -probe_error: - if (bluetooth->read_urb) - usb_free_urb (bluetooth->read_urb); - if (bluetooth->bulk_in_buffer) - kfree (bluetooth->bulk_in_buffer); - if (bluetooth->interrupt_in_urb) - usb_free_urb (bluetooth->interrupt_in_urb); - if (bluetooth->interrupt_in_buffer) - kfree (bluetooth->interrupt_in_buffer); - for (i = 0; i < NUM_CONTROL_URBS; ++i) - if (bluetooth->control_urb_pool[i]) { - if (bluetooth->control_urb_pool[i]->transfer_buffer) - kfree (bluetooth->control_urb_pool[i]->transfer_buffer); - usb_free_urb (bluetooth->control_urb_pool[i]); - } - - bluetooth_table[minor] = NULL; - - /* free up any memory that we allocated */ - kfree (bluetooth); - return -EIO; -} - - -static void usb_bluetooth_disconnect(struct usb_interface *intf) -{ - struct usb_bluetooth *bluetooth = usb_get_intfdata (intf); - int i; - - usb_set_intfdata (intf, NULL); - if (bluetooth) { - if ((bluetooth->open_count) && (bluetooth->tty)) - tty_hangup(bluetooth->tty); - - bluetooth->open_count = 0; - - if (bluetooth->read_urb) { - usb_kill_urb (bluetooth->read_urb); - usb_free_urb (bluetooth->read_urb); - } - if (bluetooth->bulk_in_buffer) - kfree (bluetooth->bulk_in_buffer); - - if (bluetooth->interrupt_in_urb) { - usb_kill_urb (bluetooth->interrupt_in_urb); - usb_free_urb (bluetooth->interrupt_in_urb); - } - if (bluetooth->interrupt_in_buffer) - kfree (bluetooth->interrupt_in_buffer); - - tty_unregister_device (bluetooth_tty_driver, bluetooth->minor); - - for (i = 0; i < NUM_CONTROL_URBS; ++i) { - if (bluetooth->control_urb_pool[i]) { - usb_kill_urb (bluetooth->control_urb_pool[i]); - if (bluetooth->control_urb_pool[i]->transfer_buffer) - kfree (bluetooth->control_urb_pool[i]->transfer_buffer); - usb_free_urb (bluetooth->control_urb_pool[i]); - } - } - - info("Bluetooth converter now disconnected from ttyUB%d", bluetooth->minor); - - bluetooth_table[bluetooth->minor] = NULL; - - /* free up any memory that we allocated */ - kfree (bluetooth); - } else { - info("device disconnected"); - } -} - -static struct tty_operations bluetooth_ops = { - .open = bluetooth_open, - .close = bluetooth_close, - .write = bluetooth_write, - .write_room = bluetooth_write_room, - .ioctl = bluetooth_ioctl, - .set_termios = bluetooth_set_termios, - .throttle = bluetooth_throttle, - .unthrottle = bluetooth_unthrottle, - .chars_in_buffer = bluetooth_chars_in_buffer, -}; - -static int usb_bluetooth_init(void) -{ - int i; - int result; - - /* Initialize our global data */ - for (i = 0; i < BLUETOOTH_TTY_MINORS; ++i) { - bluetooth_table[i] = NULL; - } - - info ("USB Bluetooth support registered"); - - bluetooth_tty_driver = alloc_tty_driver(BLUETOOTH_TTY_MINORS); - if (!bluetooth_tty_driver) - return -ENOMEM; - - bluetooth_tty_driver->owner = THIS_MODULE; - bluetooth_tty_driver->driver_name = "usb-bluetooth"; - bluetooth_tty_driver->name = "ttyUB"; - bluetooth_tty_driver->devfs_name = "usb/ttub/"; - bluetooth_tty_driver->major = BLUETOOTH_TTY_MAJOR; - bluetooth_tty_driver->minor_start = 0; - bluetooth_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; - bluetooth_tty_driver->subtype = SERIAL_TYPE_NORMAL; - bluetooth_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; - bluetooth_tty_driver->init_termios = tty_std_termios; - bluetooth_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - tty_set_operations(bluetooth_tty_driver, &bluetooth_ops); - if (tty_register_driver (bluetooth_tty_driver)) { - err("%s - failed to register tty driver", __FUNCTION__); - put_tty_driver(bluetooth_tty_driver); - return -1; - } - - /* register the USB driver */ - result = usb_register(&usb_bluetooth_driver); - if (result < 0) { - tty_unregister_driver(bluetooth_tty_driver); - put_tty_driver(bluetooth_tty_driver); - err("usb_register failed for the USB bluetooth driver. Error number %d", result); - return -1; - } - - info(DRIVER_DESC " " DRIVER_VERSION); - - return 0; -} - - -static void usb_bluetooth_exit(void) -{ - usb_deregister(&usb_bluetooth_driver); - tty_unregister_driver(bluetooth_tty_driver); - put_tty_driver(bluetooth_tty_driver); -} - - -module_init(usb_bluetooth_init); -module_exit(usb_bluetooth_exit); - -/* Module information */ -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_LICENSE("GPL"); - diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 16ecad3..1b47514 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -827,11 +827,10 @@ skip_normal_probe: return -ENODEV; } - if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) { - dev_dbg(&intf->dev, "out of memory (acm kmalloc)\n"); + if (!(acm = kzalloc(sizeof(struct acm), GFP_KERNEL))) { + dev_dbg(&intf->dev, "out of memory (acm kzalloc)\n"); goto alloc_fail; } - memset(acm, 0, sizeof(struct acm)); ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize); readsize = le16_to_cpu(epread->wMaxPacketSize); diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index e195709..357e753 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -844,9 +844,8 @@ static struct file_operations usblp_fops = { }; static struct usb_class_driver usblp_class = { - .name = "usb/lp%d", + .name = "lp%d", .fops = &usblp_fops, - .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, .minor_base = USBLP_MINOR_BASE, }; diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index 1a9ff61..ff03184 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -61,14 +61,17 @@ config USB_DYNAMIC_MINORS If you are unsure about this, say N here. config USB_SUSPEND - bool "USB suspend/resume (EXPERIMENTAL)" + bool "USB selective suspend/resume and wakeup (EXPERIMENTAL)" depends on USB && PM && EXPERIMENTAL help If you say Y here, you can use driver calls or the sysfs "power/state" file to suspend or resume individual USB - peripherals. There are many related features, such as - remote wakeup and driver-specific suspend processing, that - may not yet work as expected. + peripherals. + + Also, USB "remote wakeup" signaling is supported, whereby some + USB devices (like keyboards and network adapters) can wake up + their parent hub. That wakeup cascades up the USB tree, and + could wake the system from states like suspend-to-RAM. If you are unsure about this, say N here. diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile index d5503cf..dd1c4d2 100644 --- a/drivers/usb/core/Makefile +++ b/drivers/usb/core/Makefile @@ -3,7 +3,7 @@ # usbcore-objs := usb.o hub.o hcd.o urb.o message.o \ - config.o file.o buffer.o sysfs.o devio.o + config.o file.o buffer.o sysfs.o devio.o notify.o ifeq ($(CONFIG_PCI),y) usbcore-objs += hcd-pci.o diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c index fc15b4a..57e800a 100644 --- a/drivers/usb/core/buffer.c +++ b/drivers/usb/core/buffer.c @@ -106,7 +106,7 @@ void hcd_buffer_destroy (struct usb_hcd *hcd) void *hcd_buffer_alloc ( struct usb_bus *bus, size_t size, - unsigned mem_flags, + gfp_t mem_flags, dma_addr_t *dma ) { diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 99595e0..9930195 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -112,8 +112,12 @@ void usb_release_interface_cache(struct kref *ref) struct usb_interface_cache *intfc = ref_to_usb_interface_cache(ref); int j; - for (j = 0; j < intfc->num_altsetting; j++) - kfree(intfc->altsetting[j].endpoint); + for (j = 0; j < intfc->num_altsetting; j++) { + struct usb_host_interface *alt = &intfc->altsetting[j]; + + kfree(alt->endpoint); + kfree(alt->string); + } kfree(intfc); } @@ -188,10 +192,9 @@ static int usb_parse_interface(struct device *ddev, int cfgno, } len = sizeof(struct usb_host_endpoint) * num_ep; - alt->endpoint = kmalloc(len, GFP_KERNEL); + alt->endpoint = kzalloc(len, GFP_KERNEL); if (!alt->endpoint) return -ENOMEM; - memset(alt->endpoint, 0, len); /* Parse all the endpoint descriptors */ n = 0; @@ -353,10 +356,9 @@ static int usb_parse_configuration(struct device *ddev, int cfgidx, } len = sizeof(*intfc) + sizeof(struct usb_host_interface) * j; - config->intf_cache[i] = intfc = kmalloc(len, GFP_KERNEL); + config->intf_cache[i] = intfc = kzalloc(len, GFP_KERNEL); if (!intfc) return -ENOMEM; - memset(intfc, 0, len); kref_init(&intfc->ref); } @@ -422,8 +424,6 @@ void usb_destroy_configuration(struct usb_device *dev) struct usb_host_config *cf = &dev->config[c]; kfree(cf->string); - cf->string = NULL; - for (i = 0; i < cf->desc.bNumInterfaces; i++) { if (cf->intf_cache[i]) kref_put(&cf->intf_cache[i]->ref, @@ -459,16 +459,14 @@ int usb_get_configuration(struct usb_device *dev) } length = ncfg * sizeof(struct usb_host_config); - dev->config = kmalloc(length, GFP_KERNEL); + dev->config = kzalloc(length, GFP_KERNEL); if (!dev->config) goto err2; - memset(dev->config, 0, length); length = ncfg * sizeof(char *); - dev->rawdescriptors = kmalloc(length, GFP_KERNEL); + dev->rawdescriptors = kzalloc(length, GFP_KERNEL); if (!dev->rawdescriptors) goto err2; - memset(dev->rawdescriptors, 0, length); buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL); if (!buffer) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 487ff67..942cd43 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -46,6 +46,7 @@ #include <linux/usb.h> #include <linux/usbdevice_fs.h> #include <linux/cdev.h> +#include <linux/notifier.h> #include <asm/uaccess.h> #include <asm/byteorder.h> #include <linux/moduleparam.h> @@ -209,10 +210,10 @@ err: static struct async *alloc_async(unsigned int numisoframes) { unsigned int assize = sizeof(struct async) + numisoframes * sizeof(struct usb_iso_packet_descriptor); - struct async *as = kmalloc(assize, GFP_KERNEL); + struct async *as = kzalloc(assize, GFP_KERNEL); + if (!as) return NULL; - memset(as, 0, assize); as->urb = usb_alloc_urb(numisoframes, GFP_KERNEL); if (!as->urb) { kfree(as); @@ -279,6 +280,28 @@ static inline struct async *async_getpending(struct dev_state *ps, void __user * return NULL; } +static void snoop_urb(struct urb *urb, void __user *userurb) +{ + int j; + unsigned char *data = urb->transfer_buffer; + + if (!usbfs_snoop) + return; + + if (urb->pipe & USB_DIR_IN) + dev_info(&urb->dev->dev, "direction=IN\n"); + else + dev_info(&urb->dev->dev, "direction=OUT\n"); + dev_info(&urb->dev->dev, "userurb=%p\n", userurb); + dev_info(&urb->dev->dev, "transfer_buffer_length=%d\n", + urb->transfer_buffer_length); + dev_info(&urb->dev->dev, "actual_length=%d\n", urb->actual_length); + dev_info(&urb->dev->dev, "data: "); + for (j = 0; j < urb->transfer_buffer_length; ++j) + printk ("%02x ", data[j]); + printk("\n"); +} + static void async_completed(struct urb *urb, struct pt_regs *regs) { struct async *as = (struct async *)urb->context; @@ -296,7 +319,9 @@ static void async_completed(struct urb *urb, struct pt_regs *regs) kill_proc_info_as_uid(as->signr, &sinfo, as->pid, as->uid, as->euid); } - wake_up(&ps->wait); + snoop(&urb->dev->dev, "urb complete\n"); + snoop_urb(urb, as->userurb); + wake_up(&ps->wait); } static void destroy_async (struct dev_state *ps, struct list_head *list) @@ -493,6 +518,23 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig return ret; } +static struct usb_device *usbdev_lookup_minor(int minor) +{ + struct class_device *class_dev; + struct usb_device *dev = NULL; + + down(&usb_device_class->sem); + list_for_each_entry(class_dev, &usb_device_class->children, node) { + if (class_dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) { + dev = class_dev->class_data; + break; + } + } + up(&usb_device_class->sem); + + return dev; +}; + /* * file operations */ @@ -601,7 +643,7 @@ static int proc_control(struct dev_state *ps, void __user *arg) if (usbfs_snoop) { dev_info(&dev->dev, "control read: data "); for (j = 0; j < i; ++j) - printk ("%02x ", (unsigned char)(tbuf)[j]); + printk("%02x ", (unsigned char)(tbuf)[j]); printk("\n"); } if (copy_to_user(ctrl.data, tbuf, i)) { @@ -624,7 +666,7 @@ static int proc_control(struct dev_state *ps, void __user *arg) if (usbfs_snoop) { dev_info(&dev->dev, "control write: data: "); for (j = 0; j < ctrl.wLength; ++j) - printk ("%02x ", (unsigned char)(tbuf)[j]); + printk("%02x ", (unsigned char)(tbuf)[j]); printk("\n"); } usb_unlock_device(dev); @@ -649,7 +691,7 @@ static int proc_bulk(struct dev_state *ps, void __user *arg) unsigned int tmo, len1, pipe; int len2; unsigned char *tbuf; - int i, ret; + int i, j, ret; if (copy_from_user(&bulk, arg, sizeof(bulk))) return -EFAULT; @@ -674,10 +716,18 @@ static int proc_bulk(struct dev_state *ps, void __user *arg) kfree(tbuf); return -EINVAL; } + snoop(&dev->dev, "bulk read: len=0x%02x timeout=%04d\n", + bulk.len, bulk.timeout); usb_unlock_device(dev); i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); usb_lock_device(dev); if (!i && len2) { + if (usbfs_snoop) { + dev_info(&dev->dev, "bulk read: data "); + for (j = 0; j < len2; ++j) + printk("%02x ", (unsigned char)(tbuf)[j]); + printk("\n"); + } if (copy_to_user(bulk.data, tbuf, len2)) { kfree(tbuf); return -EFAULT; @@ -690,6 +740,14 @@ static int proc_bulk(struct dev_state *ps, void __user *arg) return -EFAULT; } } + snoop(&dev->dev, "bulk write: len=0x%02x timeout=%04d\n", + bulk.len, bulk.timeout); + if (usbfs_snoop) { + dev_info(&dev->dev, "bulk write: data: "); + for (j = 0; j < len1; ++j) + printk("%02x ", (unsigned char)(tbuf)[j]); + printk("\n"); + } usb_unlock_device(dev); i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); usb_lock_device(dev); @@ -835,7 +893,6 @@ static int proc_setconfig(struct dev_state *ps, void __user *arg) return status; } - static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, struct usbdevfs_iso_packet_desc __user *iso_frame_desc, void __user *arg) @@ -896,6 +953,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, kfree(dr); return -EFAULT; } + snoop(&ps->dev->dev, "control urb\n"); break; case USBDEVFS_URB_TYPE_BULK: @@ -910,6 +968,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, return -EINVAL; if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length)) return -EFAULT; + snoop(&ps->dev->dev, "bulk urb\n"); break; case USBDEVFS_URB_TYPE_ISO: @@ -939,6 +998,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, return -EINVAL; } uurb->buffer_length = totlen; + snoop(&ps->dev->dev, "iso urb\n"); break; case USBDEVFS_URB_TYPE_INTERRUPT: @@ -954,6 +1014,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, return -EINVAL; if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length)) return -EFAULT; + snoop(&ps->dev->dev, "interrupt urb\n"); break; default: @@ -1003,6 +1064,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, return -EFAULT; } } + snoop(&as->urb->dev->dev, "submit urb\n"); + snoop_urb(as->urb, as->userurb); async_newpending(as); if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) { dev_printk(KERN_DEBUG, &ps->dev->dev, "usbfs: usb_submit_urb returned %d\n", ret); @@ -1238,23 +1301,20 @@ static int proc_releaseinterface(struct dev_state *ps, void __user *arg) return 0; } -static int proc_ioctl (struct dev_state *ps, void __user *arg) +static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl) { - struct usbdevfs_ioctl ctrl; int size; void *buf = NULL; int retval = 0; struct usb_interface *intf = NULL; struct usb_driver *driver = NULL; - /* get input parameters and alloc buffer */ - if (copy_from_user(&ctrl, arg, sizeof (ctrl))) - return -EFAULT; - if ((size = _IOC_SIZE (ctrl.ioctl_code)) > 0) { + /* alloc buffer */ + if ((size = _IOC_SIZE (ctl->ioctl_code)) > 0) { if ((buf = kmalloc (size, GFP_KERNEL)) == NULL) return -ENOMEM; - if ((_IOC_DIR(ctrl.ioctl_code) & _IOC_WRITE)) { - if (copy_from_user (buf, ctrl.data, size)) { + if ((_IOC_DIR(ctl->ioctl_code) & _IOC_WRITE)) { + if (copy_from_user (buf, ctl->data, size)) { kfree(buf); return -EFAULT; } @@ -1270,9 +1330,9 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg) if (ps->dev->state != USB_STATE_CONFIGURED) retval = -EHOSTUNREACH; - else if (!(intf = usb_ifnum_to_if (ps->dev, ctrl.ifno))) + else if (!(intf = usb_ifnum_to_if (ps->dev, ctl->ifno))) retval = -EINVAL; - else switch (ctrl.ioctl_code) { + else switch (ctl->ioctl_code) { /* disconnect kernel driver from interface */ case USBDEVFS_DISCONNECT: @@ -1304,7 +1364,7 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg) if (driver == NULL || driver->ioctl == NULL) { retval = -ENOTTY; } else { - retval = driver->ioctl (intf, ctrl.ioctl_code, buf); + retval = driver->ioctl (intf, ctl->ioctl_code, buf); if (retval == -ENOIOCTLCMD) retval = -ENOTTY; } @@ -1313,15 +1373,42 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg) /* cleanup and return */ if (retval >= 0 - && (_IOC_DIR (ctrl.ioctl_code) & _IOC_READ) != 0 + && (_IOC_DIR (ctl->ioctl_code) & _IOC_READ) != 0 && size > 0 - && copy_to_user (ctrl.data, buf, size) != 0) + && copy_to_user (ctl->data, buf, size) != 0) retval = -EFAULT; kfree(buf); return retval; } +static int proc_ioctl_default(struct dev_state *ps, void __user *arg) +{ + struct usbdevfs_ioctl ctrl; + + if (copy_from_user(&ctrl, arg, sizeof (ctrl))) + return -EFAULT; + return proc_ioctl(ps, &ctrl); +} + +#ifdef CONFIG_COMPAT +static int proc_ioctl_compat(struct dev_state *ps, void __user *arg) +{ + struct usbdevfs_ioctl32 __user *uioc; + struct usbdevfs_ioctl ctrl; + u32 udata; + + uioc = compat_ptr(arg); + if (get_user(ctrl.ifno, &uioc->ifno) || + get_user(ctrl.ioctl_code, &uioc->ioctl_code) || + __get_user(udata, &uioc->data)) + return -EFAULT; + ctrl.data = compat_ptr(udata); + + return proc_ioctl(ps, &ctrl); +} +#endif + /* * NOTE: All requests here that have interface numbers as parameters * are assuming that somehow the configuration has been prevented from @@ -1422,6 +1509,10 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd ret = proc_reapurbnonblock_compat(ps, p); break; + case USBDEVFS_IOCTL32: + snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__); + ret = proc_ioctl_compat(ps, p); + break; #endif case USBDEVFS_DISCARDURB: @@ -1456,7 +1547,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd case USBDEVFS_IOCTL: snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__); - ret = proc_ioctl(ps, p); + ret = proc_ioctl_default(ps, p); break; } usb_unlock_device(dev); @@ -1488,39 +1579,40 @@ struct file_operations usbfs_device_file_operations = { .release = usbdev_release, }; -struct usb_device *usbdev_lookup_minor(int minor) -{ - struct class_device *class_dev; - struct usb_device *dev = NULL; - - down(&usb_device_class->sem); - list_for_each_entry(class_dev, &usb_device_class->children, node) { - if (class_dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) { - dev = class_dev->class_data; - break; - } - } - up(&usb_device_class->sem); - - return dev; -}; - -void usbdev_add(struct usb_device *dev) +static void usbdev_add(struct usb_device *dev) { int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1); - dev->class_dev = class_device_create(usb_device_class, + dev->class_dev = class_device_create(usb_device_class, NULL, MKDEV(USB_DEVICE_MAJOR, minor), &dev->dev, "usbdev%d.%d", dev->bus->busnum, dev->devnum); dev->class_dev->class_data = dev; } -void usbdev_remove(struct usb_device *dev) +static void usbdev_remove(struct usb_device *dev) { class_device_unregister(dev->class_dev); } +static int usbdev_notify(struct notifier_block *self, unsigned long action, + void *dev) +{ + switch (action) { + case USB_DEVICE_ADD: + usbdev_add(dev); + break; + case USB_DEVICE_REMOVE: + usbdev_remove(dev); + break; + } + return NOTIFY_OK; +} + +static struct notifier_block usbdev_nb = { + .notifier_call = usbdev_notify, +}; + static struct cdev usb_device_cdev = { .kobj = {.name = "usb_device", }, .owner = THIS_MODULE, @@ -1540,24 +1632,32 @@ int __init usbdev_init(void) retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX); if (retval) { err("unable to get usb_device major %d", USB_DEVICE_MAJOR); - unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); - goto out; + goto error_cdev; } usb_device_class = class_create(THIS_MODULE, "usb_device"); if (IS_ERR(usb_device_class)) { err("unable to register usb_device class"); retval = PTR_ERR(usb_device_class); - usb_device_class = NULL; - cdev_del(&usb_device_cdev); - unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); + goto error_class; } + usb_register_notify(&usbdev_nb); + out: return retval; + +error_class: + usb_device_class = NULL; + cdev_del(&usb_device_cdev); + +error_cdev: + unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); + goto out; } void usbdev_cleanup(void) { + usb_unregister_notify(&usbdev_nb); class_destroy(usb_device_class); cdev_del(&usb_device_cdev); unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index 65ca131..e695308 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -17,7 +17,6 @@ #include <linux/config.h> #include <linux/module.h> -#include <linux/devfs_fs_kernel.h> #include <linux/spinlock.h> #include <linux/errno.h> @@ -88,8 +87,6 @@ int usb_major_init(void) goto out; } - devfs_mk_dir("usb"); - out: return error; } @@ -97,7 +94,6 @@ out: void usb_major_cleanup(void) { class_destroy(usb_class); - devfs_remove("usb"); unregister_chrdev(USB_MAJOR, "usb"); } @@ -112,8 +108,7 @@ void usb_major_cleanup(void) * enabled, the minor number will be based on the next available free minor, * starting at the class_driver->minor_base. * - * This function also creates the devfs file for the usb device, if devfs - * is enabled, and creates a usb class device in the sysfs tree. + * This function also creates a usb class device in the sysfs tree. * * usb_deregister_dev() must be called when the driver is done with * the minor numbers given out by this function. @@ -162,22 +157,20 @@ int usb_register_dev(struct usb_interface *intf, intf->minor = minor; - /* handle the devfs registration */ - snprintf(name, BUS_ID_SIZE, class_driver->name, minor - minor_base); - devfs_mk_cdev(MKDEV(USB_MAJOR, minor), class_driver->mode, name); - /* create a usb class device for this usb interface */ + snprintf(name, BUS_ID_SIZE, class_driver->name, minor - minor_base); temp = strrchr(name, '/'); if (temp && (temp[1] != 0x00)) ++temp; else temp = name; - intf->class_dev = class_device_create(usb_class, MKDEV(USB_MAJOR, minor), &intf->dev, "%s", temp); + intf->class_dev = class_device_create(usb_class, NULL, + MKDEV(USB_MAJOR, minor), + &intf->dev, "%s", temp); if (IS_ERR(intf->class_dev)) { spin_lock (&minor_lock); usb_minors[intf->minor] = NULL; spin_unlock (&minor_lock); - devfs_remove (name); retval = PTR_ERR(intf->class_dev); } exit: @@ -195,9 +188,8 @@ EXPORT_SYMBOL(usb_register_dev); * call to usb_register_dev() (usually when the device is disconnected * from the system.) * - * This function also cleans up the devfs file for the usb device, if devfs - * is enabled, and removes the usb class device from the sysfs tree. - * + * This function also removes the usb class device from the sysfs tree. + * * This should be called by all drivers that use the USB major number. */ void usb_deregister_dev(struct usb_interface *intf, @@ -220,7 +212,6 @@ void usb_deregister_dev(struct usb_interface *intf, spin_unlock (&minor_lock); snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base); - devfs_remove (name); class_device_destroy(usb_class, MKDEV(USB_MAJOR, intf->minor)); intf->class_dev = NULL; intf->minor = -1; diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 6385d1a..84d9e69 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -30,6 +30,8 @@ #include <asm/io.h> #include <asm/irq.h> #include <linux/usb.h> + +#include "usb.h" #include "hcd.h" @@ -197,6 +199,26 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message) hcd = pci_get_drvdata(dev); + /* Root hub suspend should have stopped all downstream traffic, + * and all bus master traffic. And done so for both the interface + * and the stub usb_device (which we check here). But maybe it + * didn't; writing sysfs power/state files ignores such rules... + * + * We must ignore the FREEZE vs SUSPEND distinction here, because + * otherwise the swsusp will save (and restore) garbage state. + */ + if (hcd->self.root_hub->dev.power.power_state.event == PM_EVENT_ON) + return -EBUSY; + + if (hcd->driver->suspend) { + retval = hcd->driver->suspend(hcd, message); + if (retval) { + dev_dbg (&dev->dev, "PCI pre-suspend fail, %d\n", + retval); + goto done; + } + } + /* FIXME until the generic PM interfaces change a lot more, this * can't use PCI D1 and D2 states. For example, the confusion * between messages and states will need to vanish, and messages @@ -215,31 +237,13 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message) */ has_pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM); - switch (hcd->state) { - - /* entry if root hub wasn't yet suspended ... from sysfs, - * without autosuspend, or if USB_SUSPEND isn't configured. + /* Downstream ports from this root hub should already be quiesced, so + * there will be no DMA activity. Now we can shut down the upstream + * link (except maybe for PME# resume signaling) and enter some PCI + * low power state, if the hardware allows. */ - case HC_STATE_RUNNING: - hcd->state = HC_STATE_QUIESCING; - retval = hcd->driver->suspend (hcd, message); - if (retval) { - dev_dbg (hcd->self.controller, - "suspend fail, retval %d\n", - retval); - break; - } - hcd->state = HC_STATE_SUSPENDED; - /* FALLTHROUGH */ + if (hcd->state == HC_STATE_SUSPENDED) { - /* entry with CONFIG_USB_SUSPEND, or hcds that autosuspend: the - * controller and/or root hub will already have been suspended, - * but it won't be ready for a PCI resume call. - * - * FIXME only CONFIG_USB_SUSPEND guarantees hub_suspend() will - * have been called, otherwise root hub timers still run ... - */ - case HC_STATE_SUSPENDED: /* no DMA or IRQs except when HC is active */ if (dev->current_state == PCI_D0) { pci_save_state (dev); @@ -248,7 +252,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message) if (!has_pci_pm) { dev_dbg (hcd->self.controller, "--> PCI D0/legacy\n"); - break; + goto done; } /* NOTE: dev->current_state becomes nonzero only here, and @@ -259,28 +263,29 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message) retval = pci_set_power_state (dev, PCI_D3hot); if (retval == 0) { dev_dbg (hcd->self.controller, "--> PCI D3\n"); - retval = pci_enable_wake (dev, PCI_D3hot, hcd->remote_wakeup); - if (retval) - break; - retval = pci_enable_wake (dev, PCI_D3cold, hcd->remote_wakeup); - } else if (retval < 0) { + + /* Ignore these return values. We rely on pci code to + * reject requests the hardware can't implement, rather + * than coding the same thing. + */ + (void) pci_enable_wake (dev, PCI_D3hot, hcd->remote_wakeup); + (void) pci_enable_wake (dev, PCI_D3cold, hcd->remote_wakeup); + } else { dev_dbg (&dev->dev, "PCI D3 suspend fail, %d\n", retval); (void) usb_hcd_pci_resume (dev); - break; } - break; - default: + + } else { dev_dbg (hcd->self.controller, "hcd state %d; not suspended\n", hcd->state); WARN_ON(1); retval = -EINVAL; - break; } - /* update power_state **ONLY** to make sysfs happier */ +done: if (retval == 0) - dev->dev.power.power_state = message; + dev->dev.power.power_state = PMSG_SUSPEND; return retval; } EXPORT_SYMBOL (usb_hcd_pci_suspend); @@ -336,20 +341,9 @@ int usb_hcd_pci_resume (struct pci_dev *dev) dev->current_state); } #endif - retval = pci_enable_wake (dev, dev->current_state, 0); - if (retval) { - dev_err(hcd->self.controller, - "can't enable_wake to %d, %d!\n", - dev->current_state, retval); - return retval; - } - retval = pci_enable_wake (dev, PCI_D3cold, 0); - if (retval) { - dev_err(hcd->self.controller, - "can't enable_wake to %d, %d!\n", - PCI_D3cold, retval); - return retval; - } + /* yes, ignore these results too... */ + (void) pci_enable_wake (dev, dev->current_state, 0); + (void) pci_enable_wake (dev, PCI_D3cold, 0); } else { /* Same basic cases: clean (powered/not), dirty */ dev_dbg(hcd->self.controller, "PCI legacy resume\n"); @@ -371,17 +365,17 @@ int usb_hcd_pci_resume (struct pci_dev *dev) dev->dev.power.power_state = PMSG_ON; - hcd->state = HC_STATE_RESUMING; hcd->saw_irq = 0; - retval = hcd->driver->resume (hcd); - if (!HC_IS_RUNNING (hcd->state)) { - dev_dbg (hcd->self.controller, - "resume fail, retval %d\n", retval); - usb_hc_died (hcd); + if (hcd->driver->resume) { + retval = hcd->driver->resume(hcd); + if (retval) { + dev_err (hcd->self.controller, + "PCI post-resume error %d!\n", retval); + usb_hc_died (hcd); + } } - retval = pci_enable_device(dev); return retval; } EXPORT_SYMBOL (usb_hcd_pci_resume); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 1017a97..6c7ca5b 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -130,7 +130,7 @@ static const u8 usb2_rh_dev_descriptor [18] = { 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ 0x00, /* __u8 bDeviceSubClass; */ 0x01, /* __u8 bDeviceProtocol; [ usb 2.0 single TT ]*/ - 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ + 0x40, /* __u8 bMaxPacketSize0; 64 Bytes */ 0x00, 0x00, /* __le16 idVendor; */ 0x00, 0x00, /* __le16 idProduct; */ @@ -153,7 +153,7 @@ static const u8 usb11_rh_dev_descriptor [18] = { 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ 0x00, /* __u8 bDeviceSubClass; */ 0x00, /* __u8 bDeviceProtocol; [ low/full speeds only ] */ - 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ + 0x40, /* __u8 bMaxPacketSize0; 64 Bytes */ 0x00, 0x00, /* __le16 idVendor; */ 0x00, 0x00, /* __le16 idProduct; */ @@ -458,22 +458,18 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) default: /* non-generic request */ - if (HC_IS_SUSPENDED (hcd->state)) - status = -EAGAIN; - else { - switch (typeReq) { - case GetHubStatus: - case GetPortStatus: - len = 4; - break; - case GetHubDescriptor: - len = sizeof (struct usb_hub_descriptor); - break; - } - status = hcd->driver->hub_control (hcd, - typeReq, wValue, wIndex, - tbuf, wLength); + switch (typeReq) { + case GetHubStatus: + case GetPortStatus: + len = 4; + break; + case GetHubDescriptor: + len = sizeof (struct usb_hub_descriptor); + break; } + status = hcd->driver->hub_control (hcd, + typeReq, wValue, wIndex, + tbuf, wLength); break; error: /* "protocol stall" on error */ @@ -487,7 +483,7 @@ error: "CTRL: TypeReq=0x%x val=0x%x " "idx=0x%x len=%d ==> %d\n", typeReq, wValue, wIndex, - wLength, urb->status); + wLength, status); } } if (len) { @@ -748,10 +744,9 @@ struct usb_bus *usb_alloc_bus (struct usb_operations *op) { struct usb_bus *bus; - bus = kmalloc (sizeof *bus, GFP_KERNEL); + bus = kzalloc (sizeof *bus, GFP_KERNEL); if (!bus) return NULL; - memset(bus, 0, sizeof(struct usb_bus)); usb_bus_init (bus); bus->op = op; return bus; @@ -782,7 +777,8 @@ static int usb_register_bus(struct usb_bus *bus) return -E2BIG; } - bus->class_dev = class_device_create(usb_host_class, MKDEV(0,0), bus->controller, "usb_host%d", busnum); + bus->class_dev = class_device_create(usb_host_class, NULL, MKDEV(0,0), + bus->controller, "usb_host%d", busnum); if (IS_ERR(bus->class_dev)) { clear_bit(busnum, busmap.busmap); up(&usb_bus_list_lock); @@ -795,8 +791,7 @@ static int usb_register_bus(struct usb_bus *bus) list_add (&bus->bus_list, &usb_bus_list); up (&usb_bus_list_lock); - usbfs_add_bus (bus); - usbmon_notify_bus_add (bus); + usb_notify_add_bus(bus); dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum); return 0; @@ -823,8 +818,7 @@ static void usb_deregister_bus (struct usb_bus *bus) list_del (&bus->bus_list); up (&usb_bus_list_lock); - usbmon_notify_bus_remove (bus); - usbfs_remove_bus (bus); + usb_notify_remove_bus(bus); clear_bit (bus->busnum, busmap.busmap); @@ -1112,7 +1106,7 @@ static void urb_unlink (struct urb *urb) * expects usb_submit_urb() to have sanity checked and conditioned all * inputs in the urb */ -static int hcd_submit_urb (struct urb *urb, unsigned mem_flags) +static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags) { int status; struct usb_hcd *hcd = urb->dev->bus->hcpriv; @@ -1142,10 +1136,20 @@ static int hcd_submit_urb (struct urb *urb, unsigned mem_flags) else switch (hcd->state) { case HC_STATE_RUNNING: case HC_STATE_RESUMING: +doit: usb_get_dev (urb->dev); list_add_tail (&urb->urb_list, &ep->urb_list); status = 0; break; + case HC_STATE_SUSPENDED: + /* HC upstream links (register access, wakeup signaling) can work + * even when the downstream links (and DMA etc) are quiesced; let + * usbcore talk to the root hub. + */ + if (hcd->self.controller->power.power_state.event == PM_EVENT_ON + && urb->dev->parent == NULL) + goto doit; + /* FALL THROUGH */ default: status = -ESHUTDOWN; break; @@ -1293,12 +1297,6 @@ static int hcd_unlink_urb (struct urb *urb, int status) goto done; } - /* running ~= hc unlink handshake works (irq, timer, etc) - * halted ~= no unlink handshake is needed - * suspended, resuming == should never happen - */ - WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT); - /* insist the urb is still queued */ list_for_each(tmp, &ep->urb_list) { if (tmp == &urb->urb_list) @@ -1430,28 +1428,92 @@ rescan: /*-------------------------------------------------------------------------*/ -#ifdef CONFIG_USB_SUSPEND +#ifdef CONFIG_PM -static int hcd_hub_suspend (struct usb_bus *bus) +int hcd_bus_suspend (struct usb_bus *bus) { struct usb_hcd *hcd; + int status; hcd = container_of (bus, struct usb_hcd, self); - if (hcd->driver->hub_suspend) - return hcd->driver->hub_suspend (hcd); - return 0; + if (!hcd->driver->bus_suspend) + return -ENOENT; + hcd->state = HC_STATE_QUIESCING; + status = hcd->driver->bus_suspend (hcd); + if (status == 0) + hcd->state = HC_STATE_SUSPENDED; + else + dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n", + "suspend", status); + return status; } -static int hcd_hub_resume (struct usb_bus *bus) +int hcd_bus_resume (struct usb_bus *bus) { struct usb_hcd *hcd; + int status; hcd = container_of (bus, struct usb_hcd, self); - if (hcd->driver->hub_resume) - return hcd->driver->hub_resume (hcd); - return 0; + if (!hcd->driver->bus_resume) + return -ENOENT; + if (hcd->state == HC_STATE_RUNNING) + return 0; + hcd->state = HC_STATE_RESUMING; + status = hcd->driver->bus_resume (hcd); + if (status == 0) + hcd->state = HC_STATE_RUNNING; + else { + dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n", + "resume", status); + usb_hc_died(hcd); + } + return status; } +/* + * usb_hcd_suspend_root_hub - HCD autosuspends downstream ports + * @hcd: host controller for this root hub + * + * This call arranges that usb_hcd_resume_root_hub() is safe to call later; + * that the HCD's root hub polling is deactivated; and that the root's hub + * driver is suspended. HCDs may call this to autosuspend when their root + * hub's downstream ports are all inactive: unpowered, disconnected, + * disabled, or suspended. + * + * The HCD will autoresume on device connect change detection (using SRP + * or a D+/D- pullup). The HCD also autoresumes on remote wakeup signaling + * from any ports that are suspended (if that is enabled). In most cases, + * overcurrent signaling (on powered ports) will also start autoresume. + * + * Always called with IRQs blocked. + */ +void usb_hcd_suspend_root_hub (struct usb_hcd *hcd) +{ + struct urb *urb; + + spin_lock (&hcd_root_hub_lock); + usb_suspend_root_hub (hcd->self.root_hub); + + /* force status urb to complete/unlink while suspended */ + if (hcd->status_urb) { + urb = hcd->status_urb; + urb->status = -ECONNRESET; + urb->hcpriv = NULL; + urb->actual_length = 0; + + del_timer (&hcd->rh_timer); + hcd->poll_pending = 0; + hcd->status_urb = NULL; + } else + urb = NULL; + spin_unlock (&hcd_root_hub_lock); + hcd->state = HC_STATE_SUSPENDED; + + if (urb) + usb_hcd_giveback_urb (hcd, urb, NULL); +} +EXPORT_SYMBOL_GPL(usb_hcd_suspend_root_hub); + /** * usb_hcd_resume_root_hub - called by HCD to resume its root hub * @hcd: host controller for this root hub @@ -1459,7 +1521,7 @@ static int hcd_hub_resume (struct usb_bus *bus) * The USB host controller calls this function when its root hub is * suspended (with the remote wakeup feature enabled) and a remote * wakeup request is received. It queues a request for khubd to - * resume the root hub. + * resume the root hub (that is, manage its downstream ports again). */ void usb_hcd_resume_root_hub (struct usb_hcd *hcd) { @@ -1470,13 +1532,9 @@ void usb_hcd_resume_root_hub (struct usb_hcd *hcd) usb_resume_root_hub (hcd->self.root_hub); spin_unlock_irqrestore (&hcd_root_hub_lock, flags); } +EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub); -#else -void usb_hcd_resume_root_hub (struct usb_hcd *hcd) -{ -} #endif -EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub); /*-------------------------------------------------------------------------*/ @@ -1529,10 +1587,6 @@ static struct usb_operations usb_hcd_operations = { .buffer_alloc = hcd_buffer_alloc, .buffer_free = hcd_buffer_free, .disable = hcd_endpoint_disable, -#ifdef CONFIG_USB_SUSPEND - .hub_suspend = hcd_hub_suspend, - .hub_resume = hcd_hub_resume, -#endif }; /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index ac451fa..24a62a2 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -142,22 +142,18 @@ struct hcd_timeout { /* timeouts we allocate */ struct usb_operations { int (*get_frame_number) (struct usb_device *usb_dev); - int (*submit_urb) (struct urb *urb, unsigned mem_flags); + int (*submit_urb) (struct urb *urb, gfp_t mem_flags); int (*unlink_urb) (struct urb *urb, int status); /* allocate dma-consistent buffer for URB_DMA_NOMAPPING */ void *(*buffer_alloc)(struct usb_bus *bus, size_t size, - unsigned mem_flags, + gfp_t mem_flags, dma_addr_t *dma); void (*buffer_free)(struct usb_bus *bus, size_t size, void *addr, dma_addr_t dma); void (*disable)(struct usb_device *udev, struct usb_host_endpoint *ep); - - /* global suspend/resume of bus */ - int (*hub_suspend)(struct usb_bus *); - int (*hub_resume)(struct usb_bus *); }; /* each driver provides one of these, and hardware init support */ @@ -182,12 +178,12 @@ struct hc_driver { int (*start) (struct usb_hcd *hcd); /* NOTE: these suspend/resume calls relate to the HC as - * a whole, not just the root hub; they're for bus glue. + * a whole, not just the root hub; they're for PCI bus glue. */ - /* called after all devices were suspended */ + /* called after suspending the hub, before entering D3 etc */ int (*suspend) (struct usb_hcd *hcd, pm_message_t message); - /* called before any devices get resumed */ + /* called after entering D0 (etc), before resuming the hub */ int (*resume) (struct usb_hcd *hcd); /* cleanly make HCD stop writing memory and doing I/O */ @@ -200,7 +196,7 @@ struct hc_driver { int (*urb_enqueue) (struct usb_hcd *hcd, struct usb_host_endpoint *ep, struct urb *urb, - unsigned mem_flags); + gfp_t mem_flags); int (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb); /* hw synch, freeing endpoint resources that urb_dequeue can't */ @@ -212,8 +208,8 @@ struct hc_driver { int (*hub_control) (struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength); - int (*hub_suspend)(struct usb_hcd *); - int (*hub_resume)(struct usb_hcd *); + int (*bus_suspend)(struct usb_hcd *); + int (*bus_resume)(struct usb_hcd *); int (*start_port_reset)(struct usb_hcd *, unsigned port_num); void (*hub_irq_enable)(struct usb_hcd *); /* Needed only if port-change IRQs are level-triggered */ @@ -247,7 +243,7 @@ int hcd_buffer_create (struct usb_hcd *hcd); void hcd_buffer_destroy (struct usb_hcd *hcd); void *hcd_buffer_alloc (struct usb_bus *bus, size_t size, - unsigned mem_flags, dma_addr_t *dma); + gfp_t mem_flags, dma_addr_t *dma); void hcd_buffer_free (struct usb_bus *bus, size_t size, void *addr, dma_addr_t dma); @@ -355,8 +351,6 @@ extern long usb_calc_bus_time (int speed, int is_input, extern struct usb_bus *usb_alloc_bus (struct usb_operations *); -extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd); - extern void usb_set_device_state(struct usb_device *udev, enum usb_device_state new_state); @@ -378,6 +372,33 @@ extern int usb_find_interface_driver (struct usb_device *dev, #define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN)) +#ifdef CONFIG_PM +extern void usb_hcd_suspend_root_hub (struct usb_hcd *hcd); +extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd); +extern int hcd_bus_suspend (struct usb_bus *bus); +extern int hcd_bus_resume (struct usb_bus *bus); +#else +static inline void usb_hcd_suspend_root_hub(struct usb_hcd *hcd) +{ + return; +} + +static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd) +{ + return; +} + +static inline int hcd_bus_suspend(struct usb_bus *bus) +{ + return 0; +} + +static inline int hcd_bus_resume (struct usb_bus *bus) +{ + return 0; +} +#endif /* CONFIG_PM */ + /* * USB device fs stuff */ @@ -388,23 +409,13 @@ extern int usb_find_interface_driver (struct usb_device *dev, * these are expected to be called from the USB core/hub thread * with the kernel lock held */ -extern void usbfs_add_bus(struct usb_bus *bus); -extern void usbfs_remove_bus(struct usb_bus *bus); -extern void usbfs_add_device(struct usb_device *dev); -extern void usbfs_remove_device(struct usb_device *dev); extern void usbfs_update_special (void); - extern int usbfs_init(void); extern void usbfs_cleanup(void); #else /* CONFIG_USB_DEVICEFS */ -static inline void usbfs_add_bus(struct usb_bus *bus) {} -static inline void usbfs_remove_bus(struct usb_bus *bus) {} -static inline void usbfs_add_device(struct usb_device *dev) {} -static inline void usbfs_remove_device(struct usb_device *dev) {} static inline void usbfs_update_special (void) {} - static inline int usbfs_init(void) { return 0; } static inline void usbfs_cleanup(void) { } @@ -419,8 +430,6 @@ struct usb_mon_operations { void (*urb_submit_error)(struct usb_bus *bus, struct urb *urb, int err); void (*urb_complete)(struct usb_bus *bus, struct urb *urb); /* void (*urb_unlink)(struct usb_bus *bus, struct urb *urb); */ - void (*bus_add)(struct usb_bus *bus); - void (*bus_remove)(struct usb_bus *bus); }; extern struct usb_mon_operations *mon_ops; @@ -443,18 +452,6 @@ static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb) if (bus->monitored) (*mon_ops->urb_complete)(bus, urb); } - -static inline void usbmon_notify_bus_add(struct usb_bus *bus) -{ - if (mon_ops) - (*mon_ops->bus_add)(bus); -} - -static inline void usbmon_notify_bus_remove(struct usb_bus *bus) -{ - if (mon_ops) - (*mon_ops->bus_remove)(bus); -} int usb_mon_register(struct usb_mon_operations *ops); void usb_mon_deregister(void); @@ -465,8 +462,6 @@ static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb) {} static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb, int error) {} static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb) {} -static inline void usbmon_notify_bus_add(struct usb_bus *bus) {} -static inline void usbmon_notify_bus_remove(struct usb_bus *bus) {} #endif /* CONFIG_USB_MON */ diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a12cab5..256d9f6 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -436,9 +436,10 @@ static void hub_power_on(struct usb_hub *hub) { int port1; unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2; + u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); /* if hub supports power switching, enable power on each port */ - if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) < 2) { + if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2) { dev_dbg(hub->intfdev, "enabling power on all ports\n"); for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++) set_port_feature(hub->hdev, port1, @@ -449,10 +450,18 @@ static void hub_power_on(struct usb_hub *hub) msleep(max(pgood_delay, (unsigned) 100)); } -static void hub_quiesce(struct usb_hub *hub) +static inline void __hub_quiesce(struct usb_hub *hub) { - /* stop khubd and related activity */ + /* (nonblocking) khubd and related activity won't re-trigger */ hub->quiescing = 1; + hub->activating = 0; + hub->resume_root_hub = 0; +} + +static void hub_quiesce(struct usb_hub *hub) +{ + /* (blocking) stop khubd and related activity */ + __hub_quiesce(hub); usb_kill_urb(hub->urb); if (hub->has_indicators) cancel_delayed_work(&hub->leds); @@ -466,6 +475,7 @@ static void hub_activate(struct usb_hub *hub) hub->quiescing = 0; hub->activating = 1; + hub->resume_root_hub = 0; status = usb_submit_urb(hub->urb, GFP_NOIO); if (status < 0) dev_err(hub->intfdev, "activate --> %d\n", status); @@ -516,6 +526,7 @@ static int hub_configure(struct usb_hub *hub, struct usb_device *hdev = hub->hdev; struct device *hub_dev = hub->intfdev; u16 hubstatus, hubchange; + u16 wHubCharacteristics; unsigned int pipe; int maxp, ret; char *message; @@ -561,9 +572,9 @@ static int hub_configure(struct usb_hub *hub, dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild, (hdev->maxchild == 1) ? "" : "s"); - le16_to_cpus(&hub->descriptor->wHubCharacteristics); + wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); - if (hub->descriptor->wHubCharacteristics & HUB_CHAR_COMPOUND) { + if (wHubCharacteristics & HUB_CHAR_COMPOUND) { int i; char portstr [USB_MAXCHILDREN + 1]; @@ -576,7 +587,7 @@ static int hub_configure(struct usb_hub *hub, } else dev_dbg(hub_dev, "standalone hub\n"); - switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) { + switch (wHubCharacteristics & HUB_CHAR_LPSM) { case 0x00: dev_dbg(hub_dev, "ganged power switching\n"); break; @@ -589,7 +600,7 @@ static int hub_configure(struct usb_hub *hub, break; } - switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_OCPM) { + switch (wHubCharacteristics & HUB_CHAR_OCPM) { case 0x00: dev_dbg(hub_dev, "global over-current protection\n"); break; @@ -629,7 +640,7 @@ static int hub_configure(struct usb_hub *hub, } /* Note 8 FS bit times == (8 bits / 12000000 bps) ~= 666ns */ - switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_TTTT) { + switch (wHubCharacteristics & HUB_CHAR_TTTT) { case HUB_TTTT_8_BITS: if (hdev->descriptor.bDeviceProtocol != 0) { hub->tt.think_time = 666; @@ -659,7 +670,7 @@ static int hub_configure(struct usb_hub *hub, } /* probe() zeroes hub->indicator[] */ - if (hub->descriptor->wHubCharacteristics & HUB_CHAR_PORTIND) { + if (wHubCharacteristics & HUB_CHAR_PORTIND) { hub->has_indicators = 1; dev_dbg(hub_dev, "Port indicators are supported\n"); } @@ -704,7 +715,7 @@ static int hub_configure(struct usb_hub *hub, (hubstatus & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : "good"); - if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_OCPM) == 0) + if ((wHubCharacteristics & HUB_CHAR_OCPM) == 0) dev_dbg(hub_dev, "%sover-current condition exists\n", (hubstatus & HUB_STATUS_OVERCURRENT) ? "" : "no "); @@ -854,14 +865,12 @@ descriptor_error: /* We found a hub */ dev_info (&intf->dev, "USB hub found\n"); - hub = kmalloc(sizeof(*hub), GFP_KERNEL); + hub = kzalloc(sizeof(*hub), GFP_KERNEL); if (!hub) { dev_dbg (&intf->dev, "couldn't kmalloc hub struct\n"); return -ENOMEM; } - memset(hub, 0, sizeof(*hub)); - INIT_LIST_HEAD(&hub->event_list); hub->intfdev = &intf->dev; hub->hdev = hdev; @@ -1020,9 +1029,15 @@ void usb_set_device_state(struct usb_device *udev, spin_lock_irqsave(&device_state_lock, flags); if (udev->state == USB_STATE_NOTATTACHED) ; /* do nothing */ - else if (new_state != USB_STATE_NOTATTACHED) + else if (new_state != USB_STATE_NOTATTACHED) { udev->state = new_state; - else + if (new_state == USB_STATE_CONFIGURED) + device_init_wakeup(&udev->dev, + (udev->actconfig->desc.bmAttributes + & USB_CONFIG_ATT_WAKEUP)); + else if (new_state != USB_STATE_SUSPENDED) + device_init_wakeup(&udev->dev, 0); + } else recursively_mark_NOTATTACHED(udev); spin_unlock_irqrestore(&device_state_lock, flags); } @@ -1111,14 +1126,14 @@ void usb_disconnect(struct usb_device **pdev) */ usb_disable_device(udev, 0); + usb_notify_remove_device(udev); + /* Free the device number, remove the /proc/bus/usb entry and * the sysfs attributes, and delete the parent's children[] * (or root_hub) pointer. */ dev_dbg (&udev->dev, "unregistering device\n"); release_address(udev); - usbfs_remove_device(udev); - usbdev_remove(udev); usb_remove_sysfs_dev_files(udev); /* Avoid races with recursively_mark_NOTATTACHED() */ @@ -1189,21 +1204,6 @@ static inline void show_string(struct usb_device *udev, char *id, char *string) {} #endif -static void get_string(struct usb_device *udev, char **string, int index) -{ - char *buf; - - if (!index) - return; - buf = kmalloc(256, GFP_KERNEL); - if (!buf) - return; - if (usb_string(udev, index, buf, 256) > 0) - *string = buf; - else - kfree(buf); -} - #ifdef CONFIG_USB_OTG #include "otg_whitelist.h" @@ -1242,9 +1242,10 @@ int usb_new_device(struct usb_device *udev) } /* read the standard strings and cache them if present */ - get_string(udev, &udev->product, udev->descriptor.iProduct); - get_string(udev, &udev->manufacturer, udev->descriptor.iManufacturer); - get_string(udev, &udev->serial, udev->descriptor.iSerialNumber); + udev->product = usb_cache_string(udev, udev->descriptor.iProduct); + udev->manufacturer = usb_cache_string(udev, + udev->descriptor.iManufacturer); + udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber); /* Tell the world! */ dev_dbg(&udev->dev, "new device strings: Mfr=%d, Product=%d, " @@ -1316,11 +1317,9 @@ int usb_new_device(struct usb_device *udev) * (Includes HNP test device.) */ if (udev->bus->b_hnp_enable || udev->bus->is_b_host) { - static int __usb_suspend_device (struct usb_device *, - int port1, pm_message_t state); - err = __usb_suspend_device(udev, - udev->bus->otg_port, - PMSG_SUSPEND); + static int __usb_suspend_device(struct usb_device *, + int port1); + err = __usb_suspend_device(udev, udev->bus->otg_port); if (err < 0) dev_dbg(&udev->dev, "HNP fail, %d\n", err); } @@ -1356,10 +1355,8 @@ int usb_new_device(struct usb_device *udev) } /* USB device state == configured ... usable */ + usb_notify_add_device(udev); - /* add a /proc/bus/usb entry */ - usbdev_add(udev); - usbfs_add_device(udev); return 0; fail: @@ -1510,7 +1507,7 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1) /* FIXME let caller ask to power down the port: * - some devices won't enumerate without a VBUS power cycle * - SRP saves power that way - * - usb_suspend_device(dev, PMSG_SUSPEND) + * - ... new call, TBD ... * That's easy if this hub can switch power per-port, and * khubd reactivates the port later (timer, SRP, etc). * Powerdown must be optional, because of reset/DFU. @@ -1546,11 +1543,7 @@ static int hub_port_suspend(struct usb_hub *hub, int port1, * NOTE: OTG devices may issue remote wakeup (or SRP) even when * we don't explicitly enable it here. */ - if (udev->actconfig - // && FIXME (remote wakeup enabled on this bus) - // ... currently assuming it's always appropriate - && (udev->actconfig->desc.bmAttributes - & USB_CONFIG_ATT_WAKEUP) != 0) { + if (device_may_wakeup(&udev->dev)) { status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, USB_DEVICE_REMOTE_WAKEUP, 0, @@ -1596,11 +1589,14 @@ static int hub_port_suspend(struct usb_hub *hub, int port1, * Other than re-initializing the hub (plug/unplug, except for root hubs), * Linux (2.6) currently has NO mechanisms to initiate that: no khubd * timer, no SRP, no requests through sysfs. + * + * If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when + * the root hub for their bus goes into global suspend ... so we don't + * (falsely) update the device power state to say it suspended. */ -static int __usb_suspend_device (struct usb_device *udev, int port1, - pm_message_t state) +static int __usb_suspend_device (struct usb_device *udev, int port1) { - int status; + int status = 0; /* caller owns the udev device lock */ if (port1 < 0) @@ -1611,95 +1607,39 @@ static int __usb_suspend_device (struct usb_device *udev, int port1, return 0; } - /* suspend interface drivers; if this is a hub, it - * suspends the child devices - */ + /* all interfaces must already be suspended */ if (udev->actconfig) { int i; for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { struct usb_interface *intf; - struct usb_driver *driver; intf = udev->actconfig->interface[i]; - if (state.event <= intf->dev.power.power_state.event) - continue; - if (!intf->dev.driver) - continue; - driver = to_usb_driver(intf->dev.driver); - - if (driver->suspend) { - status = driver->suspend(intf, state); - if (intf->dev.power.power_state.event != state.event - || status) - dev_err(&intf->dev, - "suspend %d fail, code %d\n", - state.event, status); - } - - /* only drivers with suspend() can ever resume(); - * and after power loss, even they won't. - * bus_rescan_devices() can rebind drivers later. - * - * FIXME the PM core self-deadlocks when unbinding - * drivers during suspend/resume ... everything grabs - * dpm_sem (not a spinlock, ugh). we want to unbind, - * since we know every driver's probe/disconnect works - * even for drivers that can't suspend. - */ - if (!driver->suspend || state.event > PM_EVENT_FREEZE) { -#if 1 - dev_warn(&intf->dev, "resume is unsafe!\n"); -#else - down_write(&usb_bus_type.rwsem); - device_release_driver(&intf->dev); - up_write(&usb_bus_type.rwsem); -#endif + if (is_active(intf)) { + dev_dbg(&intf->dev, "nyet suspended\n"); + return -EBUSY; } } } - /* - * FIXME this needs port power off call paths too, to help force - * USB into the "generic" PM model. At least for devices on - * ports that aren't using ganged switching (usually root hubs). - * - * NOTE: SRP-capable links should adopt more aggressive poweroff - * policies (when HNP doesn't apply) once we have mechanisms to - * turn power back on! (Likely not before 2.7...) + /* we only change a device's upstream USB link. + * root hubs have no upstream USB link. */ - if (state.event > PM_EVENT_FREEZE) { - dev_warn(&udev->dev, "no poweroff yet, suspending instead\n"); - } - - /* "global suspend" of the HC-to-USB interface (root hub), or - * "selective suspend" of just one hub-device link. - */ - if (!udev->parent) { - struct usb_bus *bus = udev->bus; - if (bus && bus->op->hub_suspend) { - status = bus->op->hub_suspend (bus); - if (status == 0) { - dev_dbg(&udev->dev, "usb suspend\n"); - usb_set_device_state(udev, - USB_STATE_SUSPENDED); - } - } else - status = -EOPNOTSUPP; - } else + if (udev->parent) status = hub_port_suspend(hdev_to_hub(udev->parent), port1, udev); if (status == 0) - udev->dev.power.power_state = state; + udev->dev.power.power_state = PMSG_SUSPEND; return status; } -/** +#endif + +/* * usb_suspend_device - suspend a usb device * @udev: device that's no longer in active use - * @state: PMSG_SUSPEND to suspend - * Context: must be able to sleep; device not locked + * Context: must be able to sleep; device not locked; pm locks held * * Suspends a USB device that isn't in active use, conserving power. * Devices may wake out of a suspend, if anything important happens, @@ -1707,37 +1647,50 @@ static int __usb_suspend_device (struct usb_device *udev, int port1, * suspend by the host, using usb_resume_device(). It's also routine * to disconnect devices while they are suspended. * + * This only affects the USB hardware for a device; its interfaces + * (and, for hubs, child devices) must already have been suspended. + * * Suspending OTG devices may trigger HNP, if that's been enabled * between a pair of dual-role devices. That will change roles, such * as from A-Host to A-Peripheral or from B-Host back to B-Peripheral. * * Returns 0 on success, else negative errno. */ -int usb_suspend_device(struct usb_device *udev, pm_message_t state) +int usb_suspend_device(struct usb_device *udev) { +#ifdef CONFIG_USB_SUSPEND int port1, status; port1 = locktree(udev); if (port1 < 0) return port1; - status = __usb_suspend_device(udev, port1, state); + status = __usb_suspend_device(udev, port1); usb_unlock_device(udev); return status; +#else + /* NOTE: udev->state unchanged, it's not lying ... */ + udev->dev.power.power_state = PMSG_SUSPEND; + return 0; +#endif } +EXPORT_SYMBOL_GPL(usb_suspend_device); /* + * If the USB "suspend" state is in use (rather than "global suspend"), + * many devices will be individually taken out of suspend state using + * special" resume" signaling. These routines kick in shortly after * hardware resume signaling is finished, either because of selective * resume (by host) or remote wakeup (by device) ... now see what changed * in the tree that's rooted at this device. */ -static int finish_port_resume(struct usb_device *udev) +static int finish_device_resume(struct usb_device *udev) { int status; u16 devstatus; /* caller owns the udev device lock */ - dev_dbg(&udev->dev, "usb resume\n"); + dev_dbg(&udev->dev, "finish resume\n"); /* usb ch9 identifies four variants of SUSPENDED, based on what * state the device resumes to. Linux currently won't see the @@ -1747,7 +1700,6 @@ static int finish_port_resume(struct usb_device *udev) usb_set_device_state(udev, udev->actconfig ? USB_STATE_CONFIGURED : USB_STATE_ADDRESS); - udev->dev.power.power_state = PMSG_ON; /* 10.5.4.5 says be sure devices in the tree are still there. * For now let's assume the device didn't go crazy on resume, @@ -1760,9 +1712,11 @@ static int finish_port_resume(struct usb_device *udev) status); else if (udev->actconfig) { unsigned i; + int (*resume)(struct device *); le16_to_cpus(&devstatus); - if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { + if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP) + && udev->parent) { status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), USB_REQ_CLEAR_FEATURE, @@ -1778,33 +1732,11 @@ static int finish_port_resume(struct usb_device *udev) } /* resume interface drivers; if this is a hub, it - * resumes the child devices + * may have a child resume event to deal with soon */ - for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { - struct usb_interface *intf; - struct usb_driver *driver; - - intf = udev->actconfig->interface[i]; - if (intf->dev.power.power_state.event == PM_EVENT_ON) - continue; - if (!intf->dev.driver) { - /* FIXME maybe force to alt 0 */ - continue; - } - driver = to_usb_driver(intf->dev.driver); - - /* bus_rescan_devices() may rebind drivers */ - if (!driver->resume) - continue; - - /* can we do better than just logging errors? */ - status = driver->resume(intf); - if (intf->dev.power.power_state.event != PM_EVENT_ON - || status) - dev_dbg(&intf->dev, - "resume fail, state %d code %d\n", - intf->dev.power.power_state.event, status); - } + resume = udev->dev.bus->resume; + for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) + (void) resume(&udev->actconfig->interface[i]->dev); status = 0; } else if (udev->devnum <= 0) { @@ -1814,6 +1746,8 @@ static int finish_port_resume(struct usb_device *udev) return status; } +#ifdef CONFIG_USB_SUSPEND + static int hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev) { @@ -1859,7 +1793,7 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev) /* TRSMRCY = 10 msec */ msleep(10); if (udev) - status = finish_port_resume(udev); + status = finish_device_resume(udev); } } if (status < 0) @@ -1868,12 +1802,12 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev) return status; } -static int hub_resume (struct usb_interface *intf); +#endif -/** +/* * usb_resume_device - re-activate a suspended usb device * @udev: device to re-activate - * Context: must be able to sleep; device not locked + * Context: must be able to sleep; device not locked; pm locks held * * This will re-activate the suspended device, increasing power usage * while letting drivers communicate again with its endpoints. @@ -1891,35 +1825,22 @@ int usb_resume_device(struct usb_device *udev) if (port1 < 0) return port1; - /* "global resume" of the HC-to-USB interface (root hub), or - * selective resume of one hub-to-device port - */ - if (!udev->parent) { - struct usb_bus *bus = udev->bus; - if (bus && bus->op->hub_resume) { - status = bus->op->hub_resume (bus); +#ifdef CONFIG_USB_SUSPEND + /* selective resume of one downstream hub-to-device port */ + if (udev->parent) { + if (udev->state == USB_STATE_SUSPENDED) { + // NOTE swsusp may bork us, device state being wrong... + // NOTE this fails if parent is also suspended... + status = hub_port_resume(hdev_to_hub(udev->parent), + port1, udev); } else - status = -EOPNOTSUPP; - if (status == 0) { - dev_dbg(&udev->dev, "usb resume\n"); - /* TRSMRCY = 10 msec */ - msleep(10); - usb_set_device_state (udev, USB_STATE_CONFIGURED); - udev->dev.power.power_state = PMSG_ON; - status = hub_resume (udev - ->actconfig->interface[0]); - } - } else if (udev->state == USB_STATE_SUSPENDED) { - // NOTE this fails if parent is also suspended... - status = hub_port_resume(hdev_to_hub(udev->parent), - port1, udev); - } else { - status = 0; - } - if (status < 0) { + status = 0; + } else +#endif + status = finish_device_resume(udev); + if (status < 0) dev_dbg(&udev->dev, "can't resume, status %d\n", status); - } usb_unlock_device(udev); @@ -1936,6 +1857,8 @@ static int remote_wakeup(struct usb_device *udev) { int status = 0; +#ifdef CONFIG_USB_SUSPEND + /* don't repeat RESUME sequence if this device * was already woken up by some other task */ @@ -1944,38 +1867,52 @@ static int remote_wakeup(struct usb_device *udev) dev_dbg(&udev->dev, "RESUME (wakeup)\n"); /* TRSMRCY = 10 msec */ msleep(10); - status = finish_port_resume(udev); + status = finish_device_resume(udev); } up(&udev->serialize); +#endif return status; } -static int hub_suspend(struct usb_interface *intf, pm_message_t state) +static int hub_suspend(struct usb_interface *intf, pm_message_t msg) { struct usb_hub *hub = usb_get_intfdata (intf); struct usb_device *hdev = hub->hdev; unsigned port1; - int status; - /* stop khubd and related activity */ - hub_quiesce(hub); - - /* then suspend every port */ + /* fail if children aren't already suspended */ for (port1 = 1; port1 <= hdev->maxchild; port1++) { struct usb_device *udev; udev = hdev->children [port1-1]; - if (!udev) - continue; - down(&udev->serialize); - status = __usb_suspend_device(udev, port1, state); - up(&udev->serialize); - if (status < 0) - dev_dbg(&intf->dev, "suspend port %d --> %d\n", - port1, status); + if (udev && (udev->dev.power.power_state.event + == PM_EVENT_ON +#ifdef CONFIG_USB_SUSPEND + || udev->state != USB_STATE_SUSPENDED +#endif + )) { + dev_dbg(&intf->dev, "port %d nyet suspended\n", port1); + return -EBUSY; + } } - intf->dev.power.power_state = state; + /* "global suspend" of the downstream HC-to-USB interface */ + if (!hdev->parent) { + struct usb_bus *bus = hdev->bus; + if (bus) { + int status = hcd_bus_suspend (bus); + + if (status != 0) { + dev_dbg(&hdev->dev, "'global' suspend %d\n", + status); + return status; + } + } else + return -EOPNOTSUPP; + } + + /* stop khubd and related activity */ + hub_quiesce(hub); return 0; } @@ -1983,11 +1920,35 @@ static int hub_resume(struct usb_interface *intf) { struct usb_device *hdev = interface_to_usbdev(intf); struct usb_hub *hub = usb_get_intfdata (intf); - unsigned port1; int status; - if (intf->dev.power.power_state.event == PM_EVENT_ON) - return 0; + /* "global resume" of the downstream HC-to-USB interface */ + if (!hdev->parent) { + struct usb_bus *bus = hdev->bus; + if (bus) { + status = hcd_bus_resume (bus); + if (status) { + dev_dbg(&intf->dev, "'global' resume %d\n", + status); + return status; + } + } else + return -EOPNOTSUPP; + if (status == 0) { + /* TRSMRCY = 10 msec */ + msleep(10); + } + } + + hub_activate(hub); + + /* REVISIT: this recursion probably shouldn't exist. Remove + * this code sometime, after retesting with different root and + * external hubs. + */ +#ifdef CONFIG_USB_SUSPEND + { + unsigned port1; for (port1 = 1; port1 <= hdev->maxchild; port1++) { struct usb_device *udev; @@ -2013,7 +1974,7 @@ static int hub_resume(struct usb_interface *intf) if (portstat & USB_PORT_STAT_SUSPEND) status = hub_port_resume(hub, port1, udev); else { - status = finish_port_resume(udev); + status = finish_device_resume(udev); if (status < 0) { dev_dbg(&intf->dev, "resume port %d --> %d\n", port1, status); @@ -2022,43 +1983,31 @@ static int hub_resume(struct usb_interface *intf) } up(&udev->serialize); } - intf->dev.power.power_state = PMSG_ON; - - hub->resume_root_hub = 0; - hub_activate(hub); + } +#endif return 0; } -void usb_resume_root_hub(struct usb_device *hdev) +void usb_suspend_root_hub(struct usb_device *hdev) { struct usb_hub *hub = hdev_to_hub(hdev); - hub->resume_root_hub = 1; - kick_khubd(hub); + /* This also makes any led blinker stop retriggering. We're called + * from irq, so the blinker might still be scheduled. Caller promises + * that the root hub status URB will be canceled. + */ + __hub_quiesce(hub); + mark_quiesced(to_usb_interface(hub->intfdev)); } -#else /* !CONFIG_USB_SUSPEND */ - -int usb_suspend_device(struct usb_device *udev, pm_message_t state) +void usb_resume_root_hub(struct usb_device *hdev) { - return 0; -} + struct usb_hub *hub = hdev_to_hub(hdev); -int usb_resume_device(struct usb_device *udev) -{ - return 0; + hub->resume_root_hub = 1; + kick_khubd(hub); } -#define hub_suspend NULL -#define hub_resume NULL -#define remote_wakeup(x) 0 - -#endif /* CONFIG_USB_SUSPEND */ - -EXPORT_SYMBOL(usb_suspend_device); -EXPORT_SYMBOL(usb_resume_device); - - /* USB 2.0 spec, 7.1.7.3 / fig 7-29: * @@ -2467,6 +2416,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, { struct usb_device *hdev = hub->hdev; struct device *hub_dev = hub->intfdev; + u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); int status, i; dev_dbg (hub_dev, @@ -2504,8 +2454,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, if (!(portstatus & USB_PORT_STAT_CONNECTION)) { /* maybe switch power back on (e.g. root hub was reset) */ - if ((hub->descriptor->wHubCharacteristics - & HUB_CHAR_LPSM) < 2 + if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2 && !(portstatus & (1 << USB_PORT_FEAT_POWER))) set_port_feature(hdev, port1, USB_PORT_FEAT_POWER); @@ -2684,21 +2633,28 @@ static void hub_events(void) intf = to_usb_interface(hub->intfdev); hub_dev = &intf->dev; - dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n", + i = hub->resume_root_hub; + + dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x%s\n", hdev->state, hub->descriptor ? hub->descriptor->bNbrPorts : 0, /* NOTE: expects max 15 ports... */ (u16) hub->change_bits[0], - (u16) hub->event_bits[0]); + (u16) hub->event_bits[0], + i ? ", resume root" : ""); usb_get_intf(intf); - i = hub->resume_root_hub; spin_unlock_irq(&hub_event_lock); - /* Is this is a root hub wanting to be resumed? */ - if (i) - usb_resume_device(hdev); + /* Is this is a root hub wanting to reactivate the downstream + * ports? If so, be sure the interface resumes even if its + * stub "device" node was never suspended. + */ + if (i) { + dpm_runtime_resume(&hdev->dev); + dpm_runtime_resume(&intf->dev); + } /* Lock the device, then check to see if we were * disconnected while waiting for the lock to succeed. */ diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index e7fa9b5..bf23f89 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h @@ -131,7 +131,7 @@ struct usb_hub_descriptor { __u8 bDescLength; __u8 bDescriptorType; __u8 bNbrPorts; - __u16 wHubCharacteristics; + __le16 wHubCharacteristics; __u8 bPwrOn2PwrGood; __u8 bHubContrCurrent; /* add 1 bit for hub status change; round to bytes */ diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index d07bba0..12f490f 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -39,6 +39,7 @@ #include <linux/usbdevice_fs.h> #include <linux/smp_lock.h> #include <linux/parser.h> +#include <linux/notifier.h> #include <asm/byteorder.h> #include "usb.h" #include "hcd.h" @@ -619,7 +620,7 @@ void usbfs_update_special (void) } } -void usbfs_add_bus(struct usb_bus *bus) +static void usbfs_add_bus(struct usb_bus *bus) { struct dentry *parent; char name[8]; @@ -642,12 +643,9 @@ void usbfs_add_bus(struct usb_bus *bus) err ("error creating usbfs bus entry"); return; } - - usbfs_update_special(); - usbfs_conn_disc_event(); } -void usbfs_remove_bus(struct usb_bus *bus) +static void usbfs_remove_bus(struct usb_bus *bus) { if (bus->usbfs_dentry) { fs_remove_file (bus->usbfs_dentry); @@ -659,12 +657,9 @@ void usbfs_remove_bus(struct usb_bus *bus) remove_special_files(); num_buses = 0; } - - usbfs_update_special(); - usbfs_conn_disc_event(); } -void usbfs_add_device(struct usb_device *dev) +static void usbfs_add_device(struct usb_device *dev) { char name[8]; int i; @@ -690,12 +685,9 @@ void usbfs_add_device(struct usb_device *dev) } if (dev->usbfs_dentry->d_inode) dev->usbfs_dentry->d_inode->i_size = i_size; - - usbfs_update_special(); - usbfs_conn_disc_event(); } -void usbfs_remove_device(struct usb_device *dev) +static void usbfs_remove_device(struct usb_device *dev) { struct dev_state *ds; struct siginfo sinfo; @@ -716,10 +708,33 @@ void usbfs_remove_device(struct usb_device *dev) kill_proc_info_as_uid(ds->discsignr, &sinfo, ds->disc_pid, ds->disc_uid, ds->disc_euid); } } +} + +static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev) +{ + switch (action) { + case USB_DEVICE_ADD: + usbfs_add_device(dev); + break; + case USB_DEVICE_REMOVE: + usbfs_remove_device(dev); + break; + case USB_BUS_ADD: + usbfs_add_bus(dev); + break; + case USB_BUS_REMOVE: + usbfs_remove_bus(dev); + } + usbfs_update_special(); usbfs_conn_disc_event(); + return NOTIFY_OK; } +static struct notifier_block usbfs_nb = { + .notifier_call = usbfs_notify, +}; + /* --------------------------------------------------------------------- */ static struct proc_dir_entry *usbdir = NULL; @@ -732,6 +747,8 @@ int __init usbfs_init(void) if (retval) return retval; + usb_register_notify(&usbfs_nb); + /* create mount point for usbfs */ usbdir = proc_mkdir("usb", proc_bus); @@ -740,6 +757,7 @@ int __init usbfs_init(void) void usbfs_cleanup(void) { + usb_unregister_notify(&usbfs_nb); unregister_filesystem(&usb_fs_type); if (usbdir) remove_proc_entry("usb", proc_bus); diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index f1fb67f..644a3d4 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -187,21 +187,37 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u * If a thread in your driver uses this call, make sure your disconnect() * method can wait for it to complete. Since you don't have a handle on * the URB used, you can't cancel the request. + * + * Because there is no usb_interrupt_msg() and no USBDEVFS_INTERRUPT + * ioctl, users are forced to abuse this routine by using it to submit + * URBs for interrupt endpoints. We will take the liberty of creating + * an interrupt URB (with the default interval) if the target is an + * interrupt endpoint. */ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout) { struct urb *urb; + struct usb_host_endpoint *ep; - if (len < 0) + ep = (usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out) + [usb_pipeendpoint(pipe)]; + if (!ep || len < 0) return -EINVAL; - urb=usb_alloc_urb(0, GFP_KERNEL); + urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) return -ENOMEM; - usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, - usb_api_blocking_completion, NULL); + 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_api_blocking_completion, NULL, + ep->desc.bInterval); + } else + usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, + usb_api_blocking_completion, NULL); return usb_start_wait_urb(urb, timeout, actual_length); } @@ -321,7 +337,7 @@ int usb_sg_init ( struct scatterlist *sg, int nents, size_t length, - unsigned mem_flags + gfp_t mem_flags ) { int i; @@ -771,6 +787,31 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) return err; } +/** + * usb_cache_string - read a string descriptor and cache it for later use + * @udev: the device whose string descriptor is being read + * @index: the descriptor index + * + * Returns a pointer to a kmalloc'ed buffer containing the descriptor string, + * or NULL if the index is 0 or the string could not be read. + */ +char *usb_cache_string(struct usb_device *udev, int index) +{ + char *buf; + char *smallbuf = NULL; + int len; + + if (index > 0 && (buf = kmalloc(256, GFP_KERNEL)) != NULL) { + if ((len = usb_string(udev, index, buf, 256)) > 0) { + if ((smallbuf = kmalloc(++len, GFP_KERNEL)) == NULL) + return buf; + memcpy(smallbuf, buf, len); + } + kfree(buf); + } + return smallbuf; +} + /* * usb_get_device_descriptor - (re)reads the device descriptor (usbcore) * @dev: the device whose device descriptor is being updated @@ -992,8 +1033,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) dev_dbg (&dev->dev, "unregistering interface %s\n", interface->dev.bus_id); usb_remove_sysfs_intf_files(interface); - kfree(interface->cur_altsetting->string); - interface->cur_altsetting->string = NULL; device_del (&interface->dev); } @@ -1133,6 +1172,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) */ /* prevent submissions using previous endpoint settings */ + if (device_is_registered(&iface->dev)) + usb_remove_sysfs_intf_files(iface); usb_disable_interface(dev, iface); iface->cur_altsetting = alt; @@ -1168,6 +1209,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) * (Likewise, EP0 never "halts" on well designed devices.) */ usb_enable_interface(dev, iface); + if (device_is_registered(&iface->dev)) + usb_create_sysfs_intf_files(iface); return 0; } @@ -1217,10 +1260,8 @@ int usb_reset_configuration(struct usb_device *dev) USB_REQ_SET_CONFIGURATION, 0, config->desc.bConfigurationValue, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); - if (retval < 0) { - usb_set_device_state(dev, USB_STATE_ADDRESS); + if (retval < 0) return retval; - } dev->toggle[0] = dev->toggle[1] = 0; @@ -1229,6 +1270,8 @@ int usb_reset_configuration(struct usb_device *dev) struct usb_interface *intf = config->interface[i]; struct usb_host_interface *alt; + if (device_is_registered(&intf->dev)) + usb_remove_sysfs_intf_files(intf); alt = usb_altnum_to_altsetting(intf, 0); /* No altsetting 0? We'll assume the first altsetting. @@ -1241,6 +1284,8 @@ int usb_reset_configuration(struct usb_device *dev) intf->cur_altsetting = alt; usb_enable_interface(dev, intf); + if (device_is_registered(&intf->dev)) + usb_create_sysfs_intf_files(intf); } return 0; } @@ -1328,7 +1373,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) } for (; n < nintf; ++n) { - new_interfaces[n] = kmalloc( + new_interfaces[n] = kzalloc( sizeof(struct usb_interface), GFP_KERNEL); if (!new_interfaces[n]) { @@ -1369,7 +1414,6 @@ free_interfaces: struct usb_host_interface *alt; cp->interface[i] = intf = new_interfaces[i]; - memset(intf, 0, sizeof(*intf)); intfc = cp->intf_cache[i]; intf->altsetting = intfc->altsetting; intf->num_altsetting = intfc->num_altsetting; @@ -1393,6 +1437,7 @@ free_interfaces: intf->dev.dma_mask = dev->dev.dma_mask; intf->dev.release = release_interface; device_initialize (&intf->dev); + mark_quiesced(intf); sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d", dev->bus->busnum, dev->devpath, configuration, @@ -1400,12 +1445,9 @@ free_interfaces: } kfree(new_interfaces); - if ((cp->desc.iConfiguration) && - (cp->string == NULL)) { - cp->string = kmalloc(256, GFP_KERNEL); - if (cp->string) - usb_string(dev, cp->desc.iConfiguration, cp->string, 256); - } + if (cp->string == NULL) + cp->string = usb_cache_string(dev, + cp->desc.iConfiguration); /* Now that all the interfaces are set up, register them * to trigger binding of drivers to interfaces. probe() @@ -1415,13 +1457,12 @@ free_interfaces: */ for (i = 0; i < nintf; ++i) { struct usb_interface *intf = cp->interface[i]; - struct usb_interface_descriptor *desc; + struct usb_host_interface *alt = intf->cur_altsetting; - desc = &intf->altsetting [0].desc; dev_dbg (&dev->dev, "adding %s (config #%d, interface %d)\n", intf->dev.bus_id, configuration, - desc->bInterfaceNumber); + alt->desc.bInterfaceNumber); ret = device_add (&intf->dev); if (ret != 0) { dev_err(&dev->dev, @@ -1430,13 +1471,6 @@ free_interfaces: ret); continue; } - if ((intf->cur_altsetting->desc.iInterface) && - (intf->cur_altsetting->string == NULL)) { - intf->cur_altsetting->string = kmalloc(256, GFP_KERNEL); - if (intf->cur_altsetting->string) - usb_string(dev, intf->cur_altsetting->desc.iInterface, - intf->cur_altsetting->string, 256); - } usb_create_sysfs_intf_files (intf); } } diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c new file mode 100644 index 0000000..37da059 --- /dev/null +++ b/drivers/usb/core/notify.c @@ -0,0 +1,120 @@ +/* + * All the USB notify logic + * + * (C) Copyright 2005 Greg Kroah-Hartman <gregkh@suse.de> + * + * notifier functions originally based on those in kernel/sys.c + * but fixed up to not be so broken. + * + */ + + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/notifier.h> +#ifdef CONFIG_USB_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif +#include <linux/usb.h> + +#include "usb.h" + + +static struct notifier_block *usb_notifier_list; +static DECLARE_MUTEX(usb_notifier_lock); + +static void usb_notifier_chain_register(struct notifier_block **list, + struct notifier_block *n) +{ + down(&usb_notifier_lock); + while (*list) { + if (n->priority > (*list)->priority) + break; + list = &((*list)->next); + } + n->next = *list; + *list = n; + up(&usb_notifier_lock); +} + +static void usb_notifier_chain_unregister(struct notifier_block **nl, + struct notifier_block *n) +{ + down(&usb_notifier_lock); + while ((*nl)!=NULL) { + if ((*nl)==n) { + *nl = n->next; + goto exit; + } + nl=&((*nl)->next); + } +exit: + up(&usb_notifier_lock); +} + +static int usb_notifier_call_chain(struct notifier_block **n, + unsigned long val, void *v) +{ + int ret=NOTIFY_DONE; + struct notifier_block *nb = *n; + + down(&usb_notifier_lock); + while (nb) { + ret = nb->notifier_call(nb,val,v); + if (ret&NOTIFY_STOP_MASK) { + goto exit; + } + nb = nb->next; + } +exit: + up(&usb_notifier_lock); + return ret; +} + +/** + * usb_register_notify - register a notifier callback whenever a usb change happens + * @nb: pointer to the notifier block for the callback events. + * + * These changes are either USB devices or busses being added or removed. + */ +void usb_register_notify(struct notifier_block *nb) +{ + usb_notifier_chain_register(&usb_notifier_list, nb); +} +EXPORT_SYMBOL_GPL(usb_register_notify); + +/** + * usb_unregister_notify - unregister a notifier callback + * @nb: pointer to the notifier block for the callback events. + * + * usb_register_notifier() must have been previously called for this function + * to work properly. + */ +void usb_unregister_notify(struct notifier_block *nb) +{ + usb_notifier_chain_unregister(&usb_notifier_list, nb); +} +EXPORT_SYMBOL_GPL(usb_unregister_notify); + + +void usb_notify_add_device(struct usb_device *udev) +{ + usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev); +} + +void usb_notify_remove_device(struct usb_device *udev) +{ + usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_REMOVE, udev); +} + +void usb_notify_add_bus(struct usb_bus *ubus) +{ + usb_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus); +} + +void usb_notify_remove_bus(struct usb_bus *ubus) +{ + usb_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus); +} diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 00297f1..edd83e0 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -22,9 +22,207 @@ #include "usb.h" +/* endpoint stuff */ +struct ep_object { + struct usb_endpoint_descriptor *desc; + struct usb_device *udev; + struct kobject kobj; +}; +#define to_ep_object(_kobj) \ + container_of(_kobj, struct ep_object, kobj) + +struct ep_attribute { + struct attribute attr; + ssize_t (*show)(struct usb_device *, + struct usb_endpoint_descriptor *, char *); +}; +#define to_ep_attribute(_attr) \ + container_of(_attr, struct ep_attribute, attr) + +#define EP_ATTR(_name) \ +struct ep_attribute ep_##_name = { \ + .attr = {.name = #_name, .owner = THIS_MODULE, \ + .mode = S_IRUGO}, \ + .show = show_ep_##_name} + +#define usb_ep_attr(field, format_string) \ +static ssize_t show_ep_##field(struct usb_device *udev, \ + struct usb_endpoint_descriptor *desc, \ + char *buf) \ +{ \ + return sprintf(buf, format_string, desc->field); \ +} \ +static EP_ATTR(field); + +usb_ep_attr(bLength, "%02x\n") +usb_ep_attr(bEndpointAddress, "%02x\n") +usb_ep_attr(bmAttributes, "%02x\n") +usb_ep_attr(bInterval, "%02x\n") + +static ssize_t show_ep_wMaxPacketSize(struct usb_device *udev, + struct usb_endpoint_descriptor *desc, char *buf) +{ + return sprintf(buf, "%04x\n", + le16_to_cpu(desc->wMaxPacketSize) & 0x07ff); +} +static EP_ATTR(wMaxPacketSize); + +static ssize_t show_ep_type(struct usb_device *udev, + struct usb_endpoint_descriptor *desc, char *buf) +{ + char *type = "unknown"; + + switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + case USB_ENDPOINT_XFER_CONTROL: + type = "Control"; + break; + case USB_ENDPOINT_XFER_ISOC: + type = "Isoc"; + break; + case USB_ENDPOINT_XFER_BULK: + type = "Bulk"; + break; + case USB_ENDPOINT_XFER_INT: + type = "Interrupt"; + break; + } + return sprintf(buf, "%s\n", type); +} +static EP_ATTR(type); + +static ssize_t show_ep_interval(struct usb_device *udev, + struct usb_endpoint_descriptor *desc, char *buf) +{ + char unit; + unsigned interval = 0; + unsigned in; + + in = (desc->bEndpointAddress & USB_DIR_IN); + + switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + case USB_ENDPOINT_XFER_CONTROL: + if (udev->speed == USB_SPEED_HIGH) /* uframes per NAK */ + interval = desc->bInterval; + break; + case USB_ENDPOINT_XFER_ISOC: + interval = 1 << (desc->bInterval - 1); + break; + case USB_ENDPOINT_XFER_BULK: + if (udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */ + interval = desc->bInterval; + break; + case USB_ENDPOINT_XFER_INT: + if (udev->speed == USB_SPEED_HIGH) + interval = 1 << (desc->bInterval - 1); + else + interval = desc->bInterval; + break; + } + interval *= (udev->speed == USB_SPEED_HIGH) ? 125 : 1000; + if (interval % 1000) + unit = 'u'; + else { + unit = 'm'; + interval /= 1000; + } + + return sprintf(buf, "%d%cs\n", interval, unit); +} +static EP_ATTR(interval); + +static ssize_t show_ep_direction(struct usb_device *udev, + struct usb_endpoint_descriptor *desc, char *buf) +{ + char *direction; + + if ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_CONTROL) + direction = "both"; + else if (desc->bEndpointAddress & USB_DIR_IN) + direction = "in"; + else + direction = "out"; + return sprintf(buf, "%s\n", direction); +} +static EP_ATTR(direction); + +static struct attribute *ep_attrs[] = { + &ep_bLength.attr, + &ep_bEndpointAddress.attr, + &ep_bmAttributes.attr, + &ep_bInterval.attr, + &ep_wMaxPacketSize.attr, + &ep_type.attr, + &ep_interval.attr, + &ep_direction.attr, + NULL, +}; + +static void ep_object_release(struct kobject *kobj) +{ + kfree(to_ep_object(kobj)); +} + +static ssize_t ep_object_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct ep_object *ep_obj = to_ep_object(kobj); + struct ep_attribute *ep_attr = to_ep_attribute(attr); + + return (ep_attr->show)(ep_obj->udev, ep_obj->desc, buf); +} + +static struct sysfs_ops ep_object_sysfs_ops = { + .show = ep_object_show, +}; + +static struct kobj_type ep_object_ktype = { + .release = ep_object_release, + .sysfs_ops = &ep_object_sysfs_ops, + .default_attrs = ep_attrs, +}; + +static void usb_create_ep_files(struct kobject *parent, + struct usb_host_endpoint *endpoint, + struct usb_device *udev) +{ + struct ep_object *ep_obj; + struct kobject *kobj; + + ep_obj = kzalloc(sizeof(struct ep_object), GFP_KERNEL); + if (!ep_obj) + return; + + ep_obj->desc = &endpoint->desc; + ep_obj->udev = udev; + + kobj = &ep_obj->kobj; + kobject_set_name(kobj, "ep_%02x", endpoint->desc.bEndpointAddress); + kobj->parent = parent; + kobj->ktype = &ep_object_ktype; + + /* Don't use kobject_register, because it generates a hotplug event */ + kobject_init(kobj); + if (kobject_add(kobj) == 0) + endpoint->kobj = kobj; + else + kobject_put(kobj); +} + +static void usb_remove_ep_files(struct usb_host_endpoint *endpoint) +{ + + if (endpoint->kobj) { + kobject_del(endpoint->kobj); + kobject_put(endpoint->kobj); + endpoint->kobj = NULL; + } +} + /* Active configuration fields */ #define usb_actconfig_show(field, multiplier, format_string) \ -static ssize_t show_##field (struct device *dev, struct device_attribute *attr, char *buf) \ +static ssize_t show_##field (struct device *dev, \ + struct device_attribute *attr, char *buf) \ { \ struct usb_device *udev; \ struct usb_host_config *actconfig; \ @@ -46,22 +244,17 @@ usb_actconfig_attr (bNumInterfaces, 1, "%2d\n") usb_actconfig_attr (bmAttributes, 1, "%2x\n") usb_actconfig_attr (bMaxPower, 2, "%3dmA\n") -static ssize_t show_configuration_string(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t show_configuration_string(struct device *dev, + struct device_attribute *attr, char *buf) { struct usb_device *udev; struct usb_host_config *actconfig; - int len; udev = to_usb_device (dev); actconfig = udev->actconfig; if ((!actconfig) || (!actconfig->string)) return 0; - len = sprintf(buf, actconfig->string, PAGE_SIZE); - if (len < 0) - return 0; - buf[len] = '\n'; - buf[len+1] = 0; - return len+1; + return sprintf(buf, "%s\n", actconfig->string); } static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL); @@ -69,7 +262,8 @@ static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL); usb_actconfig_show(bConfigurationValue, 1, "%u\n"); static ssize_t -set_bConfigurationValue (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +set_bConfigurationValue (struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct usb_device *udev = udev = to_usb_device (dev); int config, value; @@ -87,18 +281,13 @@ static DEVICE_ATTR(bConfigurationValue, S_IRUGO | S_IWUSR, /* String fields */ #define usb_string_attr(name) \ -static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf) \ +static ssize_t show_##name(struct device *dev, \ + struct device_attribute *attr, char *buf) \ { \ struct usb_device *udev; \ - int len; \ \ udev = to_usb_device (dev); \ - len = snprintf(buf, 256, "%s", udev->name); \ - if (len < 0) \ - return 0; \ - buf[len] = '\n'; \ - buf[len+1] = 0; \ - return len+1; \ + return sprintf(buf, "%s\n", udev->name); \ } \ static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); @@ -167,7 +356,8 @@ static DEVICE_ATTR(maxchild, S_IRUGO, show_maxchild, NULL); /* Descriptor fields */ #define usb_descriptor_attr_le16(field, format_string) \ static ssize_t \ -show_##field (struct device *dev, struct device_attribute *attr, char *buf) \ +show_##field (struct device *dev, struct device_attribute *attr, \ + char *buf) \ { \ struct usb_device *udev; \ \ @@ -183,7 +373,8 @@ usb_descriptor_attr_le16(bcdDevice, "%04x\n") #define usb_descriptor_attr(field, format_string) \ static ssize_t \ -show_##field (struct device *dev, struct device_attribute *attr, char *buf) \ +show_##field (struct device *dev, struct device_attribute *attr, \ + char *buf) \ { \ struct usb_device *udev; \ \ @@ -236,19 +427,21 @@ void usb_create_sysfs_dev_files (struct usb_device *udev) if (udev->serial) device_create_file (dev, &dev_attr_serial); device_create_file (dev, &dev_attr_configuration); + usb_create_ep_files(&dev->kobj, &udev->ep0, udev); } void usb_remove_sysfs_dev_files (struct usb_device *udev) { struct device *dev = &udev->dev; + usb_remove_ep_files(&udev->ep0); sysfs_remove_group(&dev->kobj, &dev_attr_grp); - if (udev->descriptor.iManufacturer) + if (udev->manufacturer) device_remove_file(dev, &dev_attr_manufacturer); - if (udev->descriptor.iProduct) + if (udev->product) device_remove_file(dev, &dev_attr_product); - if (udev->descriptor.iSerialNumber) + if (udev->serial) device_remove_file(dev, &dev_attr_serial); device_remove_file (dev, &dev_attr_configuration); } @@ -256,11 +449,13 @@ void usb_remove_sysfs_dev_files (struct usb_device *udev) /* Interface fields */ #define usb_intf_attr(field, format_string) \ static ssize_t \ -show_##field (struct device *dev, struct device_attribute *attr, char *buf) \ +show_##field (struct device *dev, struct device_attribute *attr, \ + char *buf) \ { \ struct usb_interface *intf = to_usb_interface (dev); \ \ - return sprintf (buf, format_string, intf->cur_altsetting->desc.field); \ + return sprintf (buf, format_string, \ + intf->cur_altsetting->desc.field); \ } \ static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL); @@ -271,7 +466,8 @@ usb_intf_attr (bInterfaceClass, "%02x\n") usb_intf_attr (bInterfaceSubClass, "%02x\n") usb_intf_attr (bInterfaceProtocol, "%02x\n") -static ssize_t show_interface_string(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t show_interface_string(struct device *dev, + struct device_attribute *attr, char *buf) { struct usb_interface *intf; struct usb_device *udev; @@ -288,34 +484,28 @@ static ssize_t show_interface_string(struct device *dev, struct device_attribute } static DEVICE_ATTR(interface, S_IRUGO, show_interface_string, NULL); -static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t show_modalias(struct device *dev, + struct device_attribute *attr, char *buf) { struct usb_interface *intf; struct usb_device *udev; - int len; + struct usb_host_interface *alt; intf = to_usb_interface(dev); udev = interface_to_usbdev(intf); - - len = sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct), - le16_to_cpu(udev->descriptor.bcdDevice), - udev->descriptor.bDeviceClass, - udev->descriptor.bDeviceSubClass, - udev->descriptor.bDeviceProtocol); - buf += len; - - if (udev->descriptor.bDeviceClass == 0) { - struct usb_host_interface *alt = intf->cur_altsetting; - - return len + sprintf(buf, "%02Xisc%02Xip%02X\n", - alt->desc.bInterfaceClass, - alt->desc.bInterfaceSubClass, - alt->desc.bInterfaceProtocol); - } else { - return len + sprintf(buf, "*isc*ip*\n"); - } + alt = intf->cur_altsetting; + + return sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02X" + "ic%02Xisc%02Xip%02X\n", + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct), + le16_to_cpu(udev->descriptor.bcdDevice), + udev->descriptor.bDeviceClass, + udev->descriptor.bDeviceSubClass, + udev->descriptor.bDeviceProtocol, + alt->desc.bInterfaceClass, + alt->desc.bInterfaceSubClass, + alt->desc.bInterfaceProtocol); } static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); @@ -333,20 +523,47 @@ static struct attribute_group intf_attr_grp = { .attrs = intf_attrs, }; +static inline void usb_create_intf_ep_files(struct usb_interface *intf, + struct usb_device *udev) +{ + struct usb_host_interface *iface_desc; + int i; + + iface_desc = intf->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) + usb_create_ep_files(&intf->dev.kobj, &iface_desc->endpoint[i], + udev); +} + +static inline void usb_remove_intf_ep_files(struct usb_interface *intf) +{ + struct usb_host_interface *iface_desc; + int i; + + iface_desc = intf->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) + usb_remove_ep_files(&iface_desc->endpoint[i]); +} + void usb_create_sysfs_intf_files (struct usb_interface *intf) { + struct usb_device *udev = interface_to_usbdev(intf); + struct usb_host_interface *alt = intf->cur_altsetting; + sysfs_create_group(&intf->dev.kobj, &intf_attr_grp); - if (intf->cur_altsetting->string) + if (alt->string == NULL) + alt->string = usb_cache_string(udev, alt->desc.iInterface); + if (alt->string) device_create_file(&intf->dev, &dev_attr_interface); - + usb_create_intf_ep_files(intf, udev); } void usb_remove_sysfs_intf_files (struct usb_interface *intf) { + usb_remove_intf_ep_files(intf); sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp); if (intf->cur_altsetting->string) device_remove_file(&intf->dev, &dev_attr_interface); - } diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index c846fef..f2a1fed 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -60,7 +60,7 @@ void usb_init_urb(struct urb *urb) * * The driver must call usb_free_urb() when it is finished with the urb. */ -struct urb *usb_alloc_urb(int iso_packets, unsigned mem_flags) +struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags) { struct urb *urb; @@ -224,7 +224,7 @@ struct urb * usb_get_urb(struct urb *urb) * GFP_NOIO, unless b) or c) apply * */ -int usb_submit_urb(struct urb *urb, unsigned mem_flags) +int usb_submit_urb(struct urb *urb, gfp_t mem_flags) { int pipe, temp, max; struct usb_device *dev; @@ -237,7 +237,8 @@ int usb_submit_urb(struct urb *urb, unsigned mem_flags) (dev->state < USB_STATE_DEFAULT) || (!dev->bus) || (dev->devnum <= 0)) return -ENODEV; - if (dev->state == USB_STATE_SUSPENDED) + if (dev->bus->controller->power.power_state.event != PM_EVENT_ON + || dev->state == USB_STATE_SUSPENDED) return -EHOSTUNREACH; if (!(op = dev->bus->op) || !op->submit_urb) return -ENODEV; diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 7d13150..0eefff7 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -107,10 +107,19 @@ static int usb_probe_interface(struct device *dev) id = usb_match_id (intf, driver->id_table); if (id) { dev_dbg (dev, "%s - got id\n", __FUNCTION__); + + /* Interface "power state" doesn't correspond to any hardware + * state whatsoever. We use it to record when it's bound to + * a driver that may start I/0: it's not frozen/quiesced. + */ + mark_active(intf); intf->condition = USB_INTERFACE_BINDING; error = driver->probe (intf, id); - intf->condition = error ? USB_INTERFACE_UNBOUND : - USB_INTERFACE_BOUND; + if (error) { + mark_quiesced(intf); + intf->condition = USB_INTERFACE_UNBOUND; + } else + intf->condition = USB_INTERFACE_BOUND; } return error; @@ -136,6 +145,7 @@ static int usb_unbind_interface(struct device *dev) 0); usb_set_intfdata(intf, NULL); intf->condition = USB_INTERFACE_UNBOUND; + mark_quiesced(intf); return 0; } @@ -299,6 +309,7 @@ int usb_driver_claim_interface(struct usb_driver *driver, dev->driver = &driver->driver; usb_set_intfdata(iface, priv); iface->condition = USB_INTERFACE_BOUND; + mark_active(iface); /* if interface was already added, bind now; else let * the future device_add() bind it, bypassing probe() @@ -345,6 +356,7 @@ void usb_driver_release_interface(struct usb_driver *driver, dev->driver = NULL; usb_set_intfdata(iface, NULL); iface->condition = USB_INTERFACE_UNBOUND; + mark_quiesced(iface); } /** @@ -557,6 +569,7 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp, { struct usb_interface *intf; struct usb_device *usb_dev; + struct usb_host_interface *alt; int i = 0; int length = 0; @@ -573,7 +586,8 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp, intf = to_usb_interface(dev); usb_dev = interface_to_usbdev (intf); - + alt = intf->cur_altsetting; + if (usb_dev->devnum < 0) { pr_debug ("usb %s: already deleted?\n", dev->bus_id); return -ENODEV; @@ -615,46 +629,27 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp, usb_dev->descriptor.bDeviceProtocol)) return -ENOMEM; - if (usb_dev->descriptor.bDeviceClass == 0) { - struct usb_host_interface *alt = intf->cur_altsetting; + if (add_hotplug_env_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "INTERFACE=%d/%d/%d", + alt->desc.bInterfaceClass, + alt->desc.bInterfaceSubClass, + alt->desc.bInterfaceProtocol)) + return -ENOMEM; - /* 2.4 only exposed interface zero. in 2.5, hotplug - * agents are called for all interfaces, and can use - * $DEVPATH/bInterfaceNumber if necessary. - */ - if (add_hotplug_env_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "INTERFACE=%d/%d/%d", - alt->desc.bInterfaceClass, - alt->desc.bInterfaceSubClass, - alt->desc.bInterfaceProtocol)) - return -ENOMEM; - - if (add_hotplug_env_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", - le16_to_cpu(usb_dev->descriptor.idVendor), - le16_to_cpu(usb_dev->descriptor.idProduct), - le16_to_cpu(usb_dev->descriptor.bcdDevice), - usb_dev->descriptor.bDeviceClass, - usb_dev->descriptor.bDeviceSubClass, - usb_dev->descriptor.bDeviceProtocol, - alt->desc.bInterfaceClass, - alt->desc.bInterfaceSubClass, - alt->desc.bInterfaceProtocol)) - return -ENOMEM; - } else { - if (add_hotplug_env_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic*isc*ip*", - le16_to_cpu(usb_dev->descriptor.idVendor), - le16_to_cpu(usb_dev->descriptor.idProduct), - le16_to_cpu(usb_dev->descriptor.bcdDevice), - usb_dev->descriptor.bDeviceClass, - usb_dev->descriptor.bDeviceSubClass, - usb_dev->descriptor.bDeviceProtocol)) - return -ENOMEM; - } + if (add_hotplug_env_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", + le16_to_cpu(usb_dev->descriptor.idVendor), + le16_to_cpu(usb_dev->descriptor.idProduct), + le16_to_cpu(usb_dev->descriptor.bcdDevice), + usb_dev->descriptor.bDeviceClass, + usb_dev->descriptor.bDeviceSubClass, + usb_dev->descriptor.bDeviceProtocol, + alt->desc.bInterfaceClass, + alt->desc.bInterfaceSubClass, + alt->desc.bInterfaceProtocol)) + return -ENOMEM; envp[i] = NULL; @@ -709,12 +704,10 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) { struct usb_device *dev; - dev = kmalloc(sizeof(*dev), GFP_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return NULL; - memset(dev, 0, sizeof(*dev)); - bus = usb_bus_get(bus); if (!bus) { kfree(dev); @@ -1147,7 +1140,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size, void *usb_buffer_alloc ( struct usb_device *dev, size_t size, - unsigned mem_flags, + gfp_t mem_flags, dma_addr_t *dma ) { @@ -1402,13 +1395,30 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe, usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); } +static int verify_suspended(struct device *dev, void *unused) +{ + return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0; +} + static int usb_generic_suspend(struct device *dev, pm_message_t message) { - struct usb_interface *intf; - struct usb_driver *driver; + struct usb_interface *intf; + struct usb_driver *driver; + int status; - if (dev->driver == &usb_generic_driver) - return usb_suspend_device (to_usb_device(dev), message); + /* USB devices enter SUSPEND state through their hubs, but can be + * marked for FREEZE as soon as their children are already idled. + * But those semantics are useless, so we equate the two (sigh). + */ + if (dev->driver == &usb_generic_driver) { + if (dev->power.power_state.event == message.event) + return 0; + /* we need to rule out bogus requests through sysfs */ + status = device_for_each_child(dev, NULL, verify_suspended); + if (status) + return status; + return usb_suspend_device (to_usb_device(dev)); + } if ((dev->driver == NULL) || (dev->driver_data == &usb_generic_driver_data)) @@ -1417,23 +1427,44 @@ static int usb_generic_suspend(struct device *dev, pm_message_t message) intf = to_usb_interface(dev); driver = to_usb_driver(dev->driver); - /* there's only one USB suspend state */ - if (intf->dev.power.power_state.event) + /* with no hardware, USB interfaces only use FREEZE and ON states */ + if (!is_active(intf)) return 0; - if (driver->suspend) - return driver->suspend(intf, message); - return 0; + if (driver->suspend && driver->resume) { + status = driver->suspend(intf, message); + if (status) + dev_err(dev, "%s error %d\n", "suspend", status); + else + mark_quiesced(intf); + } else { + // FIXME else if there's no suspend method, disconnect... + dev_warn(dev, "no %s?\n", "suspend"); + status = 0; + } + return status; } static int usb_generic_resume(struct device *dev) { - struct usb_interface *intf; - struct usb_driver *driver; + struct usb_interface *intf; + struct usb_driver *driver; + struct usb_device *udev; + int status; - /* devices resume through their hub */ - if (dev->driver == &usb_generic_driver) + if (dev->power.power_state.event == PM_EVENT_ON) + return 0; + + /* mark things as "on" immediately, no matter what errors crop up */ + dev->power.power_state.event = PM_EVENT_ON; + + /* devices resume through their hubs */ + if (dev->driver == &usb_generic_driver) { + udev = to_usb_device(dev); + if (udev->state == USB_STATE_NOTATTACHED) + return 0; return usb_resume_device (to_usb_device(dev)); + } if ((dev->driver == NULL) || (dev->driver_data == &usb_generic_driver_data)) @@ -1442,8 +1473,22 @@ static int usb_generic_resume(struct device *dev) intf = to_usb_interface(dev); driver = to_usb_driver(dev->driver); - if (driver->resume) - return driver->resume(intf); + udev = interface_to_usbdev(intf); + if (udev->state == USB_STATE_NOTATTACHED) + return 0; + + /* if driver was suspended, it has a resume method; + * however, sysfs can wrongly mark things as suspended + * (on the "no suspend method" FIXME path above) + */ + if (driver->resume) { + status = driver->resume(intf); + if (status) { + dev_err(dev, "%s error %d\n", "resume", status); + mark_quiesced(intf); + } + } else + dev_warn(dev, "no %s?\n", "resume"); return 0; } diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index e6504f3..1c4a684 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -13,12 +13,14 @@ extern void usb_disable_device (struct usb_device *dev, int skip_ep0); extern int usb_get_device_descriptor(struct usb_device *dev, unsigned int size); +extern char *usb_cache_string(struct usb_device *udev, int index); extern int usb_set_configuration(struct usb_device *dev, int configuration); extern void usb_lock_all_devices(void); extern void usb_unlock_all_devices(void); extern void usb_kick_khubd(struct usb_device *dev); +extern void usb_suspend_root_hub(struct usb_device *hdev); extern void usb_resume_root_hub(struct usb_device *dev); extern int usb_hub_init(void); @@ -28,6 +30,28 @@ extern void usb_major_cleanup(void); extern int usb_host_init(void); extern void usb_host_cleanup(void); +extern int usb_suspend_device(struct usb_device *dev); +extern int usb_resume_device(struct usb_device *dev); + + +/* Interfaces and their "power state" are owned by usbcore */ + +static inline void mark_active(struct usb_interface *f) +{ + f->dev.power.power_state.event = PM_EVENT_ON; +} + +static inline void mark_quiesced(struct usb_interface *f) +{ + f->dev.power.power_state.event = PM_EVENT_FREEZE; +} + +static inline int is_active(struct usb_interface *f) +{ + return f->dev.power.power_state.event == PM_EVENT_ON; +} + + /* for labeling diagnostics */ extern const char *usbcore_name; @@ -39,9 +63,6 @@ extern void usbfs_conn_disc_event(void); extern int usbdev_init(void); extern void usbdev_cleanup(void); -extern void usbdev_add(struct usb_device *dev); -extern void usbdev_remove(struct usb_device *dev); -extern struct usb_device *usbdev_lookup_minor(int minor); struct dev_state { struct list_head list; /* state list */ @@ -58,3 +79,9 @@ struct dev_state { unsigned long ifclaimed; }; +/* internal notify stuff */ +extern void usb_notify_add_device(struct usb_device *udev); +extern void usb_notify_remove_device(struct usb_device *udev); +extern void usb_notify_add_bus(struct usb_bus *ubus); +extern void usb_notify_remove_bus(struct usb_bus *ubus); + diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 583db7c..975ace3 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -50,7 +50,7 @@ #include <linux/list.h> #include <linux/interrupt.h> #include <linux/version.h> - +#include <linux/platform_device.h> #include <linux/usb.h> #include <linux/usb_gadget.h> @@ -470,7 +470,7 @@ static int dummy_disable (struct usb_ep *_ep) } static struct usb_request * -dummy_alloc_request (struct usb_ep *_ep, unsigned mem_flags) +dummy_alloc_request (struct usb_ep *_ep, gfp_t mem_flags) { struct dummy_ep *ep; struct dummy_request *req; @@ -507,7 +507,7 @@ dummy_alloc_buffer ( struct usb_ep *_ep, unsigned bytes, dma_addr_t *dma, - unsigned mem_flags + gfp_t mem_flags ) { char *retval; struct dummy_ep *ep; @@ -541,7 +541,7 @@ fifo_complete (struct usb_ep *ep, struct usb_request *req) static int dummy_queue (struct usb_ep *_ep, struct usb_request *_req, - unsigned mem_flags) + gfp_t mem_flags) { struct dummy_ep *ep; struct dummy_request *req; @@ -935,14 +935,10 @@ static int dummy_udc_remove (struct device *dev) return 0; } -static int dummy_udc_suspend (struct device *dev, pm_message_t state, - u32 level) +static int dummy_udc_suspend (struct device *dev, pm_message_t state) { struct dummy *dum = dev_get_drvdata(dev); - if (level != SUSPEND_DISABLE) - return 0; - dev_dbg (dev, "%s\n", __FUNCTION__); spin_lock_irq (&dum->lock); dum->udc_suspended = 1; @@ -954,13 +950,10 @@ static int dummy_udc_suspend (struct device *dev, pm_message_t state, return 0; } -static int dummy_udc_resume (struct device *dev, u32 level) +static int dummy_udc_resume (struct device *dev) { struct dummy *dum = dev_get_drvdata(dev); - if (level != RESUME_ENABLE) - return 0; - dev_dbg (dev, "%s\n", __FUNCTION__); spin_lock_irq (&dum->lock); dum->udc_suspended = 0; @@ -974,6 +967,7 @@ static int dummy_udc_resume (struct device *dev, u32 level) static struct device_driver dummy_udc_driver = { .name = (char *) gadget_name, + .owner = THIS_MODULE, .bus = &platform_bus_type, .probe = dummy_udc_probe, .remove = dummy_udc_remove, @@ -999,7 +993,7 @@ static int dummy_urb_enqueue ( struct usb_hcd *hcd, struct usb_host_endpoint *ep, struct urb *urb, - unsigned mem_flags + gfp_t mem_flags ) { struct dummy *dum; struct urbp *urbp; @@ -1758,7 +1752,7 @@ static int dummy_hub_control ( return retval; } -static int dummy_hub_suspend (struct usb_hcd *hcd) +static int dummy_bus_suspend (struct usb_hcd *hcd) { struct dummy *dum = hcd_to_dummy (hcd); @@ -1769,7 +1763,7 @@ static int dummy_hub_suspend (struct usb_hcd *hcd) return 0; } -static int dummy_hub_resume (struct usb_hcd *hcd) +static int dummy_bus_resume (struct usb_hcd *hcd) { struct dummy *dum = hcd_to_dummy (hcd); @@ -1901,8 +1895,8 @@ static const struct hc_driver dummy_hcd = { .hub_status_data = dummy_hub_status, .hub_control = dummy_hub_control, - .hub_suspend = dummy_hub_suspend, - .hub_resume = dummy_hub_resume, + .bus_suspend = dummy_bus_suspend, + .bus_resume = dummy_bus_resume, }; static int dummy_hcd_probe (struct device *dev) @@ -1936,52 +1930,32 @@ static int dummy_hcd_remove (struct device *dev) return 0; } -static int dummy_hcd_suspend (struct device *dev, pm_message_t state, - u32 level) +static int dummy_hcd_suspend (struct device *dev, pm_message_t state) { struct usb_hcd *hcd; - if (level != SUSPEND_DISABLE) - return 0; - dev_dbg (dev, "%s\n", __FUNCTION__); hcd = dev_get_drvdata (dev); -#ifndef CONFIG_USB_SUSPEND - /* Otherwise this would never happen */ - usb_lock_device (hcd->self.root_hub); - dummy_hub_suspend (hcd); - usb_unlock_device (hcd->self.root_hub); -#endif - hcd->state = HC_STATE_SUSPENDED; return 0; } -static int dummy_hcd_resume (struct device *dev, u32 level) +static int dummy_hcd_resume (struct device *dev) { struct usb_hcd *hcd; - if (level != RESUME_ENABLE) - return 0; - dev_dbg (dev, "%s\n", __FUNCTION__); hcd = dev_get_drvdata (dev); hcd->state = HC_STATE_RUNNING; -#ifndef CONFIG_USB_SUSPEND - /* Otherwise this would never happen */ - usb_lock_device (hcd->self.root_hub); - dummy_hub_resume (hcd); - usb_unlock_device (hcd->self.root_hub); -#endif - usb_hcd_poll_rh_status (hcd); return 0; } static struct device_driver dummy_hcd_driver = { .name = (char *) driver_name, + .owner = THIS_MODULE, .bus = &platform_bus_type, .probe = dummy_hcd_probe, .remove = dummy_hcd_remove, diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 49459e3..8f402f8 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -945,11 +945,11 @@ config_buf (enum usb_device_speed speed, /*-------------------------------------------------------------------------*/ -static void eth_start (struct eth_dev *dev, unsigned gfp_flags); -static int alloc_requests (struct eth_dev *dev, unsigned n, unsigned gfp_flags); +static void eth_start (struct eth_dev *dev, gfp_t gfp_flags); +static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags); static int -set_ether_config (struct eth_dev *dev, unsigned gfp_flags) +set_ether_config (struct eth_dev *dev, gfp_t gfp_flags) { int result = 0; struct usb_gadget *gadget = dev->gadget; @@ -1081,7 +1081,7 @@ static void eth_reset_config (struct eth_dev *dev) * that returns config descriptors, and altsetting code. */ static int -eth_set_config (struct eth_dev *dev, unsigned number, unsigned gfp_flags) +eth_set_config (struct eth_dev *dev, unsigned number, gfp_t gfp_flags) { int result = 0; struct usb_gadget *gadget = dev->gadget; @@ -1598,7 +1598,7 @@ static void defer_kevent (struct eth_dev *dev, int flag) static void rx_complete (struct usb_ep *ep, struct usb_request *req); static int -rx_submit (struct eth_dev *dev, struct usb_request *req, unsigned gfp_flags) +rx_submit (struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) { struct sk_buff *skb; int retval = -ENOMEM; @@ -1724,7 +1724,7 @@ clean: } static int prealloc (struct list_head *list, struct usb_ep *ep, - unsigned n, unsigned gfp_flags) + unsigned n, gfp_t gfp_flags) { unsigned i; struct usb_request *req; @@ -1763,7 +1763,7 @@ extra: return 0; } -static int alloc_requests (struct eth_dev *dev, unsigned n, unsigned gfp_flags) +static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags) { int status; @@ -1779,7 +1779,7 @@ fail: return status; } -static void rx_fill (struct eth_dev *dev, unsigned gfp_flags) +static void rx_fill (struct eth_dev *dev, gfp_t gfp_flags) { struct usb_request *req; unsigned long flags; @@ -1962,7 +1962,7 @@ drop: * normally just one notification will be queued. */ -static struct usb_request *eth_req_alloc (struct usb_ep *, unsigned, unsigned); +static struct usb_request *eth_req_alloc (struct usb_ep *, unsigned, gfp_t); static void eth_req_free (struct usb_ep *ep, struct usb_request *req); static void @@ -2024,7 +2024,7 @@ static int rndis_control_ack (struct net_device *net) #endif /* RNDIS */ -static void eth_start (struct eth_dev *dev, unsigned gfp_flags) +static void eth_start (struct eth_dev *dev, gfp_t gfp_flags) { DEBUG (dev, "%s\n", __FUNCTION__); @@ -2092,7 +2092,7 @@ static int eth_stop (struct net_device *net) /*-------------------------------------------------------------------------*/ static struct usb_request * -eth_req_alloc (struct usb_ep *ep, unsigned size, unsigned gfp_flags) +eth_req_alloc (struct usb_ep *ep, unsigned size, gfp_t gfp_flags) { struct usb_request *req; @@ -2533,6 +2533,7 @@ static struct usb_gadget_driver eth_driver = { .driver = { .name = (char *) shortname, + .owner = THIS_MODULE, // .shutdown = ... // .suspend = ... // .resume = ... diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index a41d9d4..ea09aaa 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -224,6 +224,7 @@ #include <linux/fs.h> #include <linux/init.h> #include <linux/kernel.h> +#include <linux/kthread.h> #include <linux/limits.h> #include <linux/list.h> #include <linux/module.h> @@ -669,7 +670,6 @@ struct fsg_dev { wait_queue_head_t thread_wqh; int thread_wakeup_needed; struct completion thread_notifier; - int thread_pid; struct task_struct *thread_task; sigset_t thread_signal_mask; @@ -1084,7 +1084,6 @@ static void wakeup_thread(struct fsg_dev *fsg) static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state) { unsigned long flags; - struct task_struct *thread_task; /* Do nothing if a higher-priority exception is already in progress. * If a lower-or-equal priority exception is in progress, preempt it @@ -1093,9 +1092,9 @@ static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state) if (fsg->state <= new_state) { fsg->exception_req_tag = fsg->ep0_req_tag; fsg->state = new_state; - thread_task = fsg->thread_task; - if (thread_task) - send_sig_info(SIGUSR1, SEND_SIG_FORCED, thread_task); + if (fsg->thread_task) + send_sig_info(SIGUSR1, SEND_SIG_FORCED, + fsg->thread_task); } spin_unlock_irqrestore(&fsg->lock, flags); } @@ -3383,11 +3382,6 @@ static int fsg_main_thread(void *fsg_) { struct fsg_dev *fsg = (struct fsg_dev *) fsg_; - fsg->thread_task = current; - - /* Release all our userspace resources */ - daemonize("file-storage-gadget"); - /* Allow the thread to be killed by a signal, but set the signal mask * to block everything but INT, TERM, KILL, and USR1. */ siginitsetinv(&fsg->thread_signal_mask, sigmask(SIGINT) | @@ -3400,9 +3394,6 @@ static int fsg_main_thread(void *fsg_) * that expects a __user pointer and it will work okay. */ set_fs(get_ds()); - /* Wait for the gadget registration to finish up */ - wait_for_completion(&fsg->thread_notifier); - /* The main loop */ while (fsg->state != FSG_STATE_TERMINATED) { if (exception_in_progress(fsg) || signal_pending(current)) { @@ -3440,8 +3431,9 @@ static int fsg_main_thread(void *fsg_) spin_unlock_irq(&fsg->lock); } + spin_lock_irq(&fsg->lock); fsg->thread_task = NULL; - flush_signals(current); + spin_unlock_irq(&fsg->lock); /* In case we are exiting because of a signal, unregister the * gadget driver and close the backing file. */ @@ -3831,12 +3823,11 @@ static int __init fsg_bind(struct usb_gadget *gadget) /* Create the LUNs, open their backing files, and register the * LUN devices in sysfs. */ - fsg->luns = kmalloc(i * sizeof(struct lun), GFP_KERNEL); + fsg->luns = kzalloc(i * sizeof(struct lun), GFP_KERNEL); if (!fsg->luns) { rc = -ENOMEM; goto out; } - memset(fsg->luns, 0, i * sizeof(struct lun)); fsg->nluns = i; for (i = 0; i < fsg->nluns; ++i) { @@ -3959,10 +3950,12 @@ static int __init fsg_bind(struct usb_gadget *gadget) sprintf(&serial[i], "%02X", c); } - if ((rc = kernel_thread(fsg_main_thread, fsg, (CLONE_VM | CLONE_FS | - CLONE_FILES))) < 0) + fsg->thread_task = kthread_create(fsg_main_thread, fsg, + "file-storage-gadget"); + if (IS_ERR(fsg->thread_task)) { + rc = PTR_ERR(fsg->thread_task); goto out; - fsg->thread_pid = rc; + } INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); INFO(fsg, "Number of LUNs=%d\n", fsg->nluns); @@ -3994,7 +3987,12 @@ static int __init fsg_bind(struct usb_gadget *gadget) DBG(fsg, "removable=%d, stall=%d, buflen=%u\n", mod_data.removable, mod_data.can_stall, mod_data.buflen); - DBG(fsg, "I/O thread pid: %d\n", fsg->thread_pid); + DBG(fsg, "I/O thread pid: %d\n", fsg->thread_task->pid); + + set_bit(REGISTERED, &fsg->atomic_bitflags); + + /* Tell the thread to start working */ + wake_up_process(fsg->thread_task); return 0; autoconf_fail: @@ -4046,6 +4044,7 @@ static struct usb_gadget_driver fsg_driver = { .driver = { .name = (char *) shortname, + .owner = THIS_MODULE, // .release = ... // .suspend = ... // .resume = ... @@ -4057,10 +4056,9 @@ static int __init fsg_alloc(void) { struct fsg_dev *fsg; - fsg = kmalloc(sizeof *fsg, GFP_KERNEL); + fsg = kzalloc(sizeof *fsg, GFP_KERNEL); if (!fsg) return -ENOMEM; - memset(fsg, 0, sizeof *fsg); spin_lock_init(&fsg->lock); init_rwsem(&fsg->filesem); init_waitqueue_head(&fsg->thread_wqh); @@ -4086,15 +4084,9 @@ static int __init fsg_init(void) if ((rc = fsg_alloc()) != 0) return rc; fsg = the_fsg; - if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0) { + if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0) fsg_free(fsg); - return rc; - } - set_bit(REGISTERED, &fsg->atomic_bitflags); - - /* Tell the thread to start working */ - complete(&fsg->thread_notifier); - return 0; + return rc; } module_init(fsg_init); diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index eaab26f..6544697 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -269,7 +269,7 @@ static int goku_ep_disable(struct usb_ep *_ep) /*-------------------------------------------------------------------------*/ static struct usb_request * -goku_alloc_request(struct usb_ep *_ep, unsigned gfp_flags) +goku_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags) { struct goku_request *req; @@ -327,7 +327,7 @@ goku_free_request(struct usb_ep *_ep, struct usb_request *_req) */ static void * goku_alloc_buffer(struct usb_ep *_ep, unsigned bytes, - dma_addr_t *dma, unsigned gfp_flags) + dma_addr_t *dma, gfp_t gfp_flags) { void *retval; struct goku_ep *ep; @@ -789,7 +789,7 @@ finished: /*-------------------------------------------------------------------------*/ static int -goku_queue(struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags) +goku_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) { struct goku_request *req; struct goku_ep *ep; @@ -1970,6 +1970,7 @@ MODULE_DEVICE_TABLE (pci, pci_ids); static struct pci_driver goku_pci_driver = { .name = (char *) driver_name, .id_table = pci_ids, + .owner = THIS_MODULE, .probe = goku_probe, .remove = goku_remove, diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c index 4842577..bc6269f 100644 --- a/drivers/usb/gadget/lh7a40x_udc.c +++ b/drivers/usb/gadget/lh7a40x_udc.c @@ -21,6 +21,8 @@ * */ +#include <linux/platform_device.h> + #include "lh7a40x_udc.h" //#define DEBUG printk @@ -71,13 +73,13 @@ static char *state_names[] = { static int lh7a40x_ep_enable(struct usb_ep *ep, const struct usb_endpoint_descriptor *); static int lh7a40x_ep_disable(struct usb_ep *ep); -static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep, int); +static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep, gfp_t); static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *); static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned, dma_addr_t *, - int); + gfp_t); static void lh7a40x_free_buffer(struct usb_ep *ep, void *, dma_addr_t, unsigned); -static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, int); +static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, gfp_t); static int lh7a40x_dequeue(struct usb_ep *ep, struct usb_request *); static int lh7a40x_set_halt(struct usb_ep *ep, int); static int lh7a40x_fifo_status(struct usb_ep *ep); @@ -1106,7 +1108,7 @@ static int lh7a40x_ep_disable(struct usb_ep *_ep) } static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep, - unsigned gfp_flags) + gfp_t gfp_flags) { struct lh7a40x_request *req; @@ -1134,7 +1136,7 @@ static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *_req) } static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned bytes, - dma_addr_t * dma, unsigned gfp_flags) + dma_addr_t * dma, gfp_t gfp_flags) { char *retval; @@ -1158,7 +1160,7 @@ static void lh7a40x_free_buffer(struct usb_ep *ep, void *buf, dma_addr_t dma, * NOTE: Sets INDEX register */ static int lh7a40x_queue(struct usb_ep *_ep, struct usb_request *_req, - unsigned gfp_flags) + gfp_t gfp_flags) { struct lh7a40x_request *req; struct lh7a40x_ep *ep; @@ -2140,6 +2142,7 @@ static int lh7a40x_udc_remove(struct device *_dev) static struct device_driver udc_driver = { .name = (char *)driver_name, + .owner = THIS_MODULE, .bus = &platform_bus_type, .probe = lh7a40x_udc_probe, .remove = lh7a40x_udc_remove diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 477fab2..0dc6bb0 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -376,7 +376,7 @@ static int net2280_disable (struct usb_ep *_ep) /*-------------------------------------------------------------------------*/ static struct usb_request * -net2280_alloc_request (struct usb_ep *_ep, unsigned gfp_flags) +net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags) { struct net2280_ep *ep; struct net2280_request *req; @@ -463,7 +463,7 @@ net2280_alloc_buffer ( struct usb_ep *_ep, unsigned bytes, dma_addr_t *dma, - unsigned gfp_flags + gfp_t gfp_flags ) { void *retval; @@ -897,7 +897,7 @@ done (struct net2280_ep *ep, struct net2280_request *req, int status) /*-------------------------------------------------------------------------*/ static int -net2280_queue (struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags) +net2280_queue (struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) { struct net2280_request *req; struct net2280_ep *ep; @@ -2948,6 +2948,7 @@ MODULE_DEVICE_TABLE (pci, pci_ids); static struct pci_driver net2280_pci_driver = { .name = (char *) driver_name, .id_table = pci_ids, + .owner = THIS_MODULE, .probe = net2280_probe, .remove = net2280_remove, diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index ff5533e..387692a 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -38,7 +38,7 @@ #include <linux/proc_fs.h> #include <linux/mm.h> #include <linux/moduleparam.h> -#include <linux/device.h> +#include <linux/platform_device.h> #include <linux/usb_ch9.h> #include <linux/usb_gadget.h> #include <linux/usb_otg.h> @@ -269,7 +269,7 @@ static int omap_ep_disable(struct usb_ep *_ep) /*-------------------------------------------------------------------------*/ static struct usb_request * -omap_alloc_request(struct usb_ep *ep, unsigned gfp_flags) +omap_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) { struct omap_req *req; @@ -298,7 +298,7 @@ omap_alloc_buffer( struct usb_ep *_ep, unsigned bytes, dma_addr_t *dma, - unsigned gfp_flags + gfp_t gfp_flags ) { void *retval; @@ -691,7 +691,7 @@ static void next_out_dma(struct omap_ep *ep, struct omap_req *req) } static void -finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status) +finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status, int one) { u16 count; @@ -699,6 +699,8 @@ finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status) ep->dma_counter = (u16) (req->req.dma + req->req.actual); count = dma_dest_len(ep, req->req.dma + req->req.actual); count += req->req.actual; + if (one) + count--; if (count <= req->req.length) req->req.actual = count; @@ -747,7 +749,7 @@ static void dma_irq(struct omap_udc *udc, u16 irq_src) if (!list_empty(&ep->queue)) { req = container_of(ep->queue.next, struct omap_req, queue); - finish_out_dma(ep, req, 0); + finish_out_dma(ep, req, 0, dman_stat & UDC_DMA_RX_SB); } UDC_IRQ_SRC_REG = UDC_RXN_EOT; @@ -925,7 +927,7 @@ static void dma_channel_release(struct omap_ep *ep) while (UDC_RXDMA_CFG_REG & mask) udelay(10); if (req) - finish_out_dma(ep, req, -ECONNRESET); + finish_out_dma(ep, req, -ECONNRESET, 0); } omap_free_dma(ep->lch); ep->dma_channel = 0; @@ -937,7 +939,7 @@ static void dma_channel_release(struct omap_ep *ep) /*-------------------------------------------------------------------------*/ static int -omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags) +omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) { struct omap_ep *ep = container_of(_ep, struct omap_ep, ep); struct omap_req *req = container_of(_req, struct omap_req, req); @@ -1786,8 +1788,12 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src) udc->driver->suspend(&udc->gadget); spin_lock(&udc->lock); } + if (udc->transceiver) + otg_set_suspend(udc->transceiver, 1); } else { VDBG("resume\n"); + if (udc->transceiver) + otg_set_suspend(udc->transceiver, 0); if (udc->gadget.speed == USB_SPEED_FULL && udc->driver->resume) { spin_unlock(&udc->lock); @@ -2909,12 +2915,10 @@ static int __exit omap_udc_remove(struct device *dev) * may involve talking to an external transceiver (e.g. isp1301). */ -static int omap_udc_suspend(struct device *dev, pm_message_t message, u32 level) +static int omap_udc_suspend(struct device *dev, pm_message_t message) { u32 devstat; - if (level != SUSPEND_POWER_DOWN) - return 0; devstat = UDC_DEVSTAT_REG; /* we're requesting 48 MHz clock if the pullup is enabled @@ -2931,11 +2935,8 @@ static int omap_udc_suspend(struct device *dev, pm_message_t message, u32 level) return 0; } -static int omap_udc_resume(struct device *dev, u32 level) +static int omap_udc_resume(struct device *dev) { - if (level != RESUME_POWER_ON) - return 0; - DBG("resume + wakeup/SRP\n"); omap_pullup(&udc->gadget, 1); @@ -2948,6 +2949,7 @@ static int omap_udc_resume(struct device *dev, u32 level) static struct device_driver udc_driver = { .name = (char *) driver_name, + .owner = THIS_MODULE, .bus = &platform_bus_type, .probe = omap_udc_probe, .remove = __exit_p(omap_udc_remove), diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index 73f8c94..ee9cd78 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c @@ -43,7 +43,7 @@ #include <linux/interrupt.h> #include <linux/proc_fs.h> #include <linux/mm.h> -#include <linux/device.h> +#include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <asm/byteorder.h> @@ -332,7 +332,7 @@ static int pxa2xx_ep_disable (struct usb_ep *_ep) * pxa2xx_ep_alloc_request - allocate a request data structure */ static struct usb_request * -pxa2xx_ep_alloc_request (struct usb_ep *_ep, unsigned gfp_flags) +pxa2xx_ep_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags) { struct pxa2xx_request *req; @@ -367,7 +367,7 @@ pxa2xx_ep_free_request (struct usb_ep *_ep, struct usb_request *_req) */ static void * pxa2xx_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes, - dma_addr_t *dma, unsigned gfp_flags) + dma_addr_t *dma, gfp_t gfp_flags) { char *retval; @@ -422,7 +422,7 @@ static inline void ep0_idle (struct pxa2xx_udc *dev) } static int -write_packet(volatile unsigned long *uddr, struct pxa2xx_request *req, unsigned max) +write_packet(volatile u32 *uddr, struct pxa2xx_request *req, unsigned max) { u8 *buf; unsigned length, count; @@ -874,7 +874,7 @@ done: /*-------------------------------------------------------------------------*/ static int -pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags) +pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) { struct pxa2xx_request *req; struct pxa2xx_ep *ep; @@ -2602,24 +2602,23 @@ static int __exit pxa2xx_udc_remove(struct device *_dev) * VBUS IRQs should probably be ignored so that the PXA device just acts * "dead" to USB hosts until system resume. */ -static int pxa2xx_udc_suspend(struct device *dev, pm_message_t state, u32 level) +static int pxa2xx_udc_suspend(struct device *dev, pm_message_t state) { struct pxa2xx_udc *udc = dev_get_drvdata(dev); - if (level == SUSPEND_POWER_DOWN) { - if (!udc->mach->udc_command) - WARN("USB host won't detect disconnect!\n"); - pullup(udc, 0); - } + if (!udc->mach->udc_command) + WARN("USB host won't detect disconnect!\n"); + pullup(udc, 0); + return 0; } -static int pxa2xx_udc_resume(struct device *dev, u32 level) +static int pxa2xx_udc_resume(struct device *dev) { struct pxa2xx_udc *udc = dev_get_drvdata(dev); - if (level == RESUME_POWER_ON) - pullup(udc, 1); + pullup(udc, 1); + return 0; } @@ -2632,6 +2631,7 @@ static int pxa2xx_udc_resume(struct device *dev, u32 level) static struct device_driver udc_driver = { .name = "pxa2xx-udc", + .owner = THIS_MODULE, .bus = &platform_bus_type, .probe = pxa2xx_udc_probe, .shutdown = pxa2xx_udc_shutdown, diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h index a58f3e6..19a883f 100644 --- a/drivers/usb/gadget/pxa2xx_udc.h +++ b/drivers/usb/gadget/pxa2xx_udc.h @@ -69,11 +69,11 @@ struct pxa2xx_ep { * UDDR = UDC Endpoint Data Register (the fifo) * DRCM = DMA Request Channel Map */ - volatile unsigned long *reg_udccs; - volatile unsigned long *reg_ubcr; - volatile unsigned long *reg_uddr; + volatile u32 *reg_udccs; + volatile u32 *reg_ubcr; + volatile u32 *reg_uddr; #ifdef USE_DMA - volatile unsigned long *reg_drcmr; + volatile u32 *reg_drcmr; #define drcmr(n) .reg_drcmr = & DRCMR ## n , #else #define drcmr(n) diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index c925d92..b35ac6d 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -300,18 +300,18 @@ static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed, u8 type, unsigned int index, int is_otg); static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len, - unsigned kmalloc_flags); + gfp_t kmalloc_flags); static void gs_free_req(struct usb_ep *ep, struct usb_request *req); static struct gs_req_entry *gs_alloc_req_entry(struct usb_ep *ep, unsigned len, - unsigned kmalloc_flags); + gfp_t kmalloc_flags); static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req); -static int gs_alloc_ports(struct gs_dev *dev, unsigned kmalloc_flags); +static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags); static void gs_free_ports(struct gs_dev *dev); /* circular buffer */ -static struct gs_buf *gs_buf_alloc(unsigned int size, unsigned kmalloc_flags); +static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags); static void gs_buf_free(struct gs_buf *gb); static void gs_buf_clear(struct gs_buf *gb); static unsigned int gs_buf_data_avail(struct gs_buf *gb); @@ -2091,7 +2091,7 @@ static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed, * usb_request or NULL if there is an error. */ static struct usb_request * -gs_alloc_req(struct usb_ep *ep, unsigned int len, unsigned kmalloc_flags) +gs_alloc_req(struct usb_ep *ep, unsigned int len, gfp_t kmalloc_flags) { struct usb_request *req; @@ -2132,7 +2132,7 @@ static void gs_free_req(struct usb_ep *ep, struct usb_request *req) * endpoint, buffer len, and kmalloc flags. */ static struct gs_req_entry * -gs_alloc_req_entry(struct usb_ep *ep, unsigned len, unsigned kmalloc_flags) +gs_alloc_req_entry(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags) { struct gs_req_entry *req; @@ -2173,7 +2173,7 @@ static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req) * * The device lock is normally held when calling this function. */ -static int gs_alloc_ports(struct gs_dev *dev, unsigned kmalloc_flags) +static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags) { int i; struct gs_port *port; @@ -2255,7 +2255,7 @@ static void gs_free_ports(struct gs_dev *dev) * * Allocate a circular buffer and all associated memory. */ -static struct gs_buf *gs_buf_alloc(unsigned int size, unsigned kmalloc_flags) +static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags) { struct gs_buf *gb; diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 6890e77..6c58636 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -612,7 +612,7 @@ static void source_sink_complete (struct usb_ep *ep, struct usb_request *req) } static struct usb_request * -source_sink_start_ep (struct usb_ep *ep, unsigned gfp_flags) +source_sink_start_ep (struct usb_ep *ep, gfp_t gfp_flags) { struct usb_request *req; int status; @@ -640,7 +640,7 @@ source_sink_start_ep (struct usb_ep *ep, unsigned gfp_flags) } static int -set_source_sink_config (struct zero_dev *dev, unsigned gfp_flags) +set_source_sink_config (struct zero_dev *dev, gfp_t gfp_flags) { int result = 0; struct usb_ep *ep; @@ -744,7 +744,7 @@ static void loopback_complete (struct usb_ep *ep, struct usb_request *req) } static int -set_loopback_config (struct zero_dev *dev, unsigned gfp_flags) +set_loopback_config (struct zero_dev *dev, gfp_t gfp_flags) { int result = 0; struct usb_ep *ep; @@ -845,7 +845,7 @@ static void zero_reset_config (struct zero_dev *dev) * by limiting configuration choices (like the pxa2xx). */ static int -zero_set_config (struct zero_dev *dev, unsigned number, unsigned gfp_flags) +zero_set_config (struct zero_dev *dev, unsigned number, gfp_t gfp_flags) { int result = 0; struct usb_gadget *gadget = dev->gadget; @@ -1302,6 +1302,7 @@ static struct usb_gadget_driver zero_driver = { .driver = { .name = (char *) shortname, + .owner = THIS_MODULE, // .shutdown = ... // .suspend = ... // .resume = ... diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 350d14f..58321d3 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -1,8 +1,9 @@ # -# Makefile for USB Host Controller Driver -# framework and drivers +# Makefile for USB Host Controller Drivers # +obj-$(CONFIG_PCI) += pci-quirks.o + obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index b948ffd..af3c05e 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -182,6 +182,9 @@ static int ehci_halt (struct ehci_hcd *ehci) { u32 temp = readl (&ehci->regs->status); + /* disable any irqs left enabled by previous code */ + writel (0, &ehci->regs->intr_enable); + if ((temp & STS_HALT) != 0) return 0; @@ -297,50 +300,17 @@ static void ehci_watchdog (unsigned long param) spin_unlock_irqrestore (&ehci->lock, flags); } -#ifdef CONFIG_PCI - -/* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/... - * off the controller (maybe it can boot from highspeed USB disks). +/* Reboot notifiers kick in for silicon on any bus (not just pci, etc). + * This forcibly disables dma and IRQs, helping kexec and other cases + * where the next system software may expect clean state. */ -static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap) -{ - struct pci_dev *pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); - - /* always say Linux will own the hardware */ - pci_write_config_byte(pdev, where + 3, 1); - - /* maybe wait a while for BIOS to respond */ - if (cap & (1 << 16)) { - int msec = 5000; - - do { - msleep(10); - msec -= 10; - pci_read_config_dword(pdev, where, &cap); - } while ((cap & (1 << 16)) && msec); - if (cap & (1 << 16)) { - ehci_err(ehci, "BIOS handoff failed (%d, %08x)\n", - where, cap); - // some BIOS versions seem buggy... - // return 1; - ehci_warn (ehci, "continuing after BIOS bug...\n"); - /* disable all SMIs, and clear "BIOS owns" flag */ - pci_write_config_dword(pdev, where + 4, 0); - pci_write_config_byte(pdev, where + 2, 0); - } else - ehci_dbg(ehci, "BIOS handoff succeeded\n"); - } - return 0; -} - -#endif - static int ehci_reboot (struct notifier_block *self, unsigned long code, void *null) { struct ehci_hcd *ehci; ehci = container_of (self, struct ehci_hcd, reboot_notifier); + (void) ehci_halt (ehci); /* make BIOS/etc use companion controller during reboot */ writel (0, &ehci->regs->configured_flag); @@ -363,156 +333,90 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on) msleep(20); } +/*-------------------------------------------------------------------------*/ + +/* + * ehci_work is called from some interrupts, timers, and so on. + * it calls driver completion functions, after dropping ehci->lock. + */ +static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs) +{ + timer_action_done (ehci, TIMER_IO_WATCHDOG); + if (ehci->reclaim_ready) + end_unlink_async (ehci, regs); + + /* another CPU may drop ehci->lock during a schedule scan while + * it reports urb completions. this flag guards against bogus + * attempts at re-entrant schedule scanning. + */ + if (ehci->scanning) + return; + ehci->scanning = 1; + scan_async (ehci, regs); + if (ehci->next_uframe != -1) + scan_periodic (ehci, regs); + ehci->scanning = 0; -/* called by khubd or root hub init threads */ + /* the IO watchdog guards against hardware or driver bugs that + * misplace IRQs, and should let us run completely without IRQs. + * such lossage has been observed on both VT6202 and VT8235. + */ + if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && + (ehci->async->qh_next.ptr != NULL || + ehci->periodic_sched != 0)) + timer_action (ehci, TIMER_IO_WATCHDOG); +} -static int ehci_hc_reset (struct usb_hcd *hcd) +static void ehci_stop (struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); - u32 temp; - unsigned count = 256/4; - spin_lock_init (&ehci->lock); + ehci_dbg (ehci, "stop\n"); - ehci->caps = hcd->regs; - ehci->regs = hcd->regs + HC_LENGTH (readl (&ehci->caps->hc_capbase)); - dbg_hcs_params (ehci, "reset"); - dbg_hcc_params (ehci, "reset"); + /* Turn off port power on all root hub ports. */ + ehci_port_power (ehci, 0); - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = readl (&ehci->caps->hcs_params); + /* no more interrupts ... */ + del_timer_sync (&ehci->watchdog); -#ifdef CONFIG_PCI - if (hcd->self.controller->bus == &pci_bus_type) { - struct pci_dev *pdev = to_pci_dev(hcd->self.controller); + spin_lock_irq(&ehci->lock); + if (HC_IS_RUNNING (hcd->state)) + ehci_quiesce (ehci); - switch (pdev->vendor) { - case PCI_VENDOR_ID_TDI: - if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { - ehci->is_tdi_rh_tt = 1; - tdi_reset (ehci); - } - break; - case PCI_VENDOR_ID_AMD: - /* AMD8111 EHCI doesn't work, according to AMD errata */ - if (pdev->device == 0x7463) { - ehci_info (ehci, "ignoring AMD8111 (errata)\n"); - return -EIO; - } - break; - case PCI_VENDOR_ID_NVIDIA: - /* NVidia reports that certain chips don't handle - * QH, ITD, or SITD addresses above 2GB. (But TD, - * data buffer, and periodic schedule are normal.) - */ - switch (pdev->device) { - case 0x003c: /* MCP04 */ - case 0x005b: /* CK804 */ - case 0x00d8: /* CK8 */ - case 0x00e8: /* CK8S */ - if (pci_set_consistent_dma_mask(pdev, - DMA_31BIT_MASK) < 0) - ehci_warn (ehci, "can't enable NVidia " - "workaround for >2GB RAM\n"); - break; - } - break; - } + ehci_reset (ehci); + writel (0, &ehci->regs->intr_enable); + spin_unlock_irq(&ehci->lock); - /* optional debug port, normally in the first BAR */ - temp = pci_find_capability (pdev, 0x0a); - if (temp) { - pci_read_config_dword(pdev, temp, &temp); - temp >>= 16; - if ((temp & (3 << 13)) == (1 << 13)) { - temp &= 0x1fff; - ehci->debug = hcd->regs + temp; - temp = readl (&ehci->debug->control); - ehci_info (ehci, "debug port %d%s\n", - HCS_DEBUG_PORT(ehci->hcs_params), - (temp & DBGP_ENABLED) - ? " IN USE" - : ""); - if (!(temp & DBGP_ENABLED)) - ehci->debug = NULL; - } - } + /* let companion controllers work when we aren't */ + writel (0, &ehci->regs->configured_flag); + unregister_reboot_notifier (&ehci->reboot_notifier); - temp = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params)); - } else - temp = 0; - - /* EHCI 0.96 and later may have "extended capabilities" */ - while (temp && count--) { - u32 cap; - - pci_read_config_dword (to_pci_dev(hcd->self.controller), - temp, &cap); - ehci_dbg (ehci, "capability %04x at %02x\n", cap, temp); - switch (cap & 0xff) { - case 1: /* BIOS/SMM/... handoff */ - if (bios_handoff (ehci, temp, cap) != 0) - return -EOPNOTSUPP; - break; - case 0: /* illegal reserved capability */ - ehci_warn (ehci, "illegal capability!\n"); - cap = 0; - /* FALLTHROUGH */ - default: /* unknown */ - break; - } - temp = (cap >> 8) & 0xff; - } - if (!count) { - ehci_err (ehci, "bogus capabilities ... PCI problems!\n"); - return -EIO; - } - if (ehci_is_TDI(ehci)) - ehci_reset (ehci); -#endif + remove_debug_files (ehci); - ehci_port_power (ehci, 0); + /* root hub is shut down separately (first, when possible) */ + spin_lock_irq (&ehci->lock); + if (ehci->async) + ehci_work (ehci, NULL); + spin_unlock_irq (&ehci->lock); + ehci_mem_cleanup (ehci); - /* at least the Genesys GL880S needs fixup here */ - temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); - temp &= 0x0f; - if (temp && HCS_N_PORTS(ehci->hcs_params) > temp) { - ehci_dbg (ehci, "bogus port configuration: " - "cc=%d x pcc=%d < ports=%d\n", - HCS_N_CC(ehci->hcs_params), - HCS_N_PCC(ehci->hcs_params), - HCS_N_PORTS(ehci->hcs_params)); - -#ifdef CONFIG_PCI - if (hcd->self.controller->bus == &pci_bus_type) { - struct pci_dev *pdev; - - pdev = to_pci_dev(hcd->self.controller); - switch (pdev->vendor) { - case 0x17a0: /* GENESYS */ - /* GL880S: should be PORTS=2 */ - temp |= (ehci->hcs_params & ~0xf); - ehci->hcs_params = temp; - break; - case PCI_VENDOR_ID_NVIDIA: - /* NF4: should be PCC=10 */ - break; - } - } +#ifdef EHCI_STATS + ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n", + ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim, + ehci->stats.lost_iaa); + ehci_dbg (ehci, "complete %ld unlink %ld\n", + ehci->stats.complete, ehci->stats.unlink); #endif - } - /* force HC to halt state */ - return ehci_halt (ehci); + dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status)); } -static int ehci_start (struct usb_hcd *hcd) +static int ehci_run (struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); u32 temp; int retval; u32 hcc_params; - u8 sbrn = 0; int first; /* skip some things on restart paths */ @@ -551,27 +455,6 @@ static int ehci_start (struct usb_hcd *hcd) } writel (ehci->periodic_dma, &ehci->regs->frame_list); -#ifdef CONFIG_PCI - if (hcd->self.controller->bus == &pci_bus_type) { - struct pci_dev *pdev; - u16 port_wake; - - pdev = to_pci_dev(hcd->self.controller); - - /* Serial Bus Release Number is at PCI 0x60 offset */ - pci_read_config_byte(pdev, 0x60, &sbrn); - - /* port wake capability, reported by boot firmware */ - pci_read_config_word(pdev, 0x62, &port_wake); - hcd->can_wakeup = (port_wake & 1) != 0; - - /* help hc dma work well with cachelines */ - retval = pci_set_mwi(pdev); - if (retval) - ehci_dbg(ehci, "unable to enable MWI - not fatal.\n"); - } -#endif - /* * dedicate a qh for the async ring head, since we couldn't unlink * a 'real' qh without stopping the async schedule [4.8]. use it @@ -667,7 +550,7 @@ static int ehci_start (struct usb_hcd *hcd) temp = HC_VERSION(readl (&ehci->caps->hc_capbase)); ehci_info (ehci, "USB %x.%x %s, EHCI %x.%02x, driver %s\n", - ((sbrn & 0xf0)>>4), (sbrn & 0x0f), + ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), first ? "initialized" : "restarted", temp >> 8, temp & 0xff, DRIVER_VERSION); @@ -679,188 +562,6 @@ static int ehci_start (struct usb_hcd *hcd) return 0; } -/* always called by thread; normally rmmod */ - -static void ehci_stop (struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - - ehci_dbg (ehci, "stop\n"); - - /* Turn off port power on all root hub ports. */ - ehci_port_power (ehci, 0); - - /* no more interrupts ... */ - del_timer_sync (&ehci->watchdog); - - spin_lock_irq(&ehci->lock); - if (HC_IS_RUNNING (hcd->state)) - ehci_quiesce (ehci); - - ehci_reset (ehci); - writel (0, &ehci->regs->intr_enable); - spin_unlock_irq(&ehci->lock); - - /* let companion controllers work when we aren't */ - writel (0, &ehci->regs->configured_flag); - unregister_reboot_notifier (&ehci->reboot_notifier); - - remove_debug_files (ehci); - - /* root hub is shut down separately (first, when possible) */ - spin_lock_irq (&ehci->lock); - if (ehci->async) - ehci_work (ehci, NULL); - spin_unlock_irq (&ehci->lock); - ehci_mem_cleanup (ehci); - -#ifdef EHCI_STATS - ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n", - ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim, - ehci->stats.lost_iaa); - ehci_dbg (ehci, "complete %ld unlink %ld\n", - ehci->stats.complete, ehci->stats.unlink); -#endif - - dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status)); -} - -static int ehci_get_frame (struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - return (readl (&ehci->regs->frame_index) >> 3) % ehci->periodic_size; -} - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_PM - -/* suspend/resume, section 4.3 */ - -/* These routines rely on the bus (pci, platform, etc) - * to handle powerdown and wakeup, and currently also on - * transceivers that don't need any software attention to set up - * the right sort of wakeup. - */ - -static int ehci_suspend (struct usb_hcd *hcd, pm_message_t message) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - - if (time_before (jiffies, ehci->next_statechange)) - msleep (100); - -#ifdef CONFIG_USB_SUSPEND - (void) usb_suspend_device (hcd->self.root_hub, message); -#else - usb_lock_device (hcd->self.root_hub); - (void) ehci_hub_suspend (hcd); - usb_unlock_device (hcd->self.root_hub); -#endif - - // save (PCI) FLADJ in case of Vaux power loss - // ... we'd only use it to handle clock skew - - return 0; -} - -static int ehci_resume (struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - unsigned port; - struct usb_device *root = hcd->self.root_hub; - int retval = -EINVAL; - - // maybe restore (PCI) FLADJ - - if (time_before (jiffies, ehci->next_statechange)) - msleep (100); - - /* If any port is suspended (or owned by the companion), - * we know we can/must resume the HC (and mustn't reset it). - */ - for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) { - u32 status; - port--; - status = readl (&ehci->regs->port_status [port]); - if (!(status & PORT_POWER)) - continue; - if (status & (PORT_SUSPEND | PORT_OWNER)) { - down (&hcd->self.root_hub->serialize); - retval = ehci_hub_resume (hcd); - up (&hcd->self.root_hub->serialize); - break; - } - if (!root->children [port]) - continue; - dbg_port (ehci, __FUNCTION__, port + 1, status); - usb_set_device_state (root->children[port], - USB_STATE_NOTATTACHED); - } - - /* Else reset, to cope with power loss or flush-to-storage - * style "resume" having activated BIOS during reboot. - */ - if (port == 0) { - (void) ehci_halt (ehci); - (void) ehci_reset (ehci); - (void) ehci_hc_reset (hcd); - - /* emptying the schedule aborts any urbs */ - spin_lock_irq (&ehci->lock); - if (ehci->reclaim) - ehci->reclaim_ready = 1; - ehci_work (ehci, NULL); - spin_unlock_irq (&ehci->lock); - - /* restart; khubd will disconnect devices */ - retval = ehci_start (hcd); - - /* here we "know" root ports should always stay powered; - * but some controllers may lose all power. - */ - ehci_port_power (ehci, 1); - } - - return retval; -} - -#endif - -/*-------------------------------------------------------------------------*/ - -/* - * ehci_work is called from some interrupts, timers, and so on. - * it calls driver completion functions, after dropping ehci->lock. - */ -static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs) -{ - timer_action_done (ehci, TIMER_IO_WATCHDOG); - if (ehci->reclaim_ready) - end_unlink_async (ehci, regs); - - /* another CPU may drop ehci->lock during a schedule scan while - * it reports urb completions. this flag guards against bogus - * attempts at re-entrant schedule scanning. - */ - if (ehci->scanning) - return; - ehci->scanning = 1; - scan_async (ehci, regs); - if (ehci->next_uframe != -1) - scan_periodic (ehci, regs); - ehci->scanning = 0; - - /* the IO watchdog guards against hardware or driver bugs that - * misplace IRQs, and should let us run completely without IRQs. - * such lossage has been observed on both VT6202 and VT8235. - */ - if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && - (ehci->async->qh_next.ptr != NULL || - ehci->periodic_sched != 0)) - timer_action (ehci, TIMER_IO_WATCHDOG); -} - /*-------------------------------------------------------------------------*/ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs) @@ -983,7 +684,7 @@ static int ehci_urb_enqueue ( struct usb_hcd *hcd, struct usb_host_endpoint *ep, struct urb *urb, - unsigned mem_flags + gfp_t mem_flags ) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); struct list_head qtd_list; @@ -1171,106 +872,24 @@ done: return; } -/*-------------------------------------------------------------------------*/ - -static const struct hc_driver ehci_driver = { - .description = hcd_name, - .product_desc = "EHCI Host Controller", - .hcd_priv_size = sizeof(struct ehci_hcd), - - /* - * generic hardware linkage - */ - .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2, - - /* - * basic lifecycle operations - */ - .reset = ehci_hc_reset, - .start = ehci_start, -#ifdef CONFIG_PM - .suspend = ehci_suspend, - .resume = ehci_resume, -#endif - .stop = ehci_stop, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - - /* - * scheduling support - */ - .get_frame_number = ehci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - .hub_suspend = ehci_hub_suspend, - .hub_resume = ehci_hub_resume, -}; +static int ehci_get_frame (struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci (hcd); + return (readl (&ehci->regs->frame_index) >> 3) % ehci->periodic_size; +} /*-------------------------------------------------------------------------*/ -/* EHCI 1.0 doesn't require PCI */ - -#ifdef CONFIG_PCI - -/* PCI driver selection metadata; PCI hotplugging uses this */ -static const struct pci_device_id pci_ids [] = { { - /* handle any USB 2.0 EHCI controller */ - PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x20), ~0), - .driver_data = (unsigned long) &ehci_driver, - }, - { /* end: all zeroes */ } -}; -MODULE_DEVICE_TABLE (pci, pci_ids); - -/* pci driver glue; this is a "new style" PCI driver module */ -static struct pci_driver ehci_pci_driver = { - .name = (char *) hcd_name, - .id_table = pci_ids, - - .probe = usb_hcd_pci_probe, - .remove = usb_hcd_pci_remove, - -#ifdef CONFIG_PM - .suspend = usb_hcd_pci_suspend, - .resume = usb_hcd_pci_resume, -#endif -}; - -#endif /* PCI */ - - #define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC MODULE_DESCRIPTION (DRIVER_INFO); MODULE_AUTHOR (DRIVER_AUTHOR); MODULE_LICENSE ("GPL"); -static int __init init (void) -{ - if (usb_disabled()) - return -ENODEV; - - pr_debug ("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", - hcd_name, - sizeof (struct ehci_qh), sizeof (struct ehci_qtd), - sizeof (struct ehci_itd), sizeof (struct ehci_sitd)); - - return pci_register_driver (&ehci_pci_driver); -} -module_init (init); +#ifdef CONFIG_PCI +#include "ehci-pci.c" +#endif -static void __exit cleanup (void) -{ - pci_unregister_driver (&ehci_pci_driver); -} -module_exit (cleanup); +#if !defined(CONFIG_PCI) +#error "missing bus glue for ehci-hcd" +#endif diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 18d3f22..88cb4ad 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -30,7 +30,7 @@ #ifdef CONFIG_PM -static int ehci_hub_suspend (struct usb_hcd *hcd) +static int ehci_bus_suspend (struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); int port; @@ -83,7 +83,7 @@ static int ehci_hub_suspend (struct usb_hcd *hcd) /* caller has locked the root hub, and should reset/reinit on error */ -static int ehci_hub_resume (struct usb_hcd *hcd) +static int ehci_bus_resume (struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); u32 temp; @@ -159,8 +159,8 @@ static int ehci_hub_resume (struct usb_hcd *hcd) #else -#define ehci_hub_suspend NULL -#define ehci_hub_resume NULL +#define ehci_bus_suspend NULL +#define ehci_bus_resume NULL #endif /* CONFIG_PM */ diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c index 5c38ad8..91c2ab4 100644 --- a/drivers/usb/host/ehci-mem.c +++ b/drivers/usb/host/ehci-mem.c @@ -45,7 +45,7 @@ static inline void ehci_qtd_init (struct ehci_qtd *qtd, dma_addr_t dma) INIT_LIST_HEAD (&qtd->qtd_list); } -static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, int flags) +static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, gfp_t flags) { struct ehci_qtd *qtd; dma_addr_t dma; @@ -79,7 +79,7 @@ static void qh_destroy (struct kref *kref) dma_pool_free (ehci->qh_pool, qh, qh->qh_dma); } -static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags) +static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags) { struct ehci_qh *qh; dma_addr_t dma; @@ -161,7 +161,7 @@ static void ehci_mem_cleanup (struct ehci_hcd *ehci) } /* remember to add cleanup code (above) if you add anything here */ -static int ehci_mem_init (struct ehci_hcd *ehci, int flags) +static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags) { int i; diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c new file mode 100644 index 0000000..1450088 --- /dev/null +++ b/drivers/usb/host/ehci-pci.c @@ -0,0 +1,415 @@ +/* + * EHCI HCD (Host Controller Driver) PCI Bus Glue. + * + * Copyright (c) 2000-2004 by David Brownell + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef CONFIG_PCI +#error "This file is PCI bus glue. CONFIG_PCI must be defined." +#endif + +/*-------------------------------------------------------------------------*/ + +/* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/... + * off the controller (maybe it can boot from highspeed USB disks). + */ +static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap) +{ + struct pci_dev *pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); + + /* always say Linux will own the hardware */ + pci_write_config_byte(pdev, where + 3, 1); + + /* maybe wait a while for BIOS to respond */ + if (cap & (1 << 16)) { + int msec = 5000; + + do { + msleep(10); + msec -= 10; + pci_read_config_dword(pdev, where, &cap); + } while ((cap & (1 << 16)) && msec); + if (cap & (1 << 16)) { + ehci_err(ehci, "BIOS handoff failed (%d, %08x)\n", + where, cap); + // some BIOS versions seem buggy... + // return 1; + ehci_warn (ehci, "continuing after BIOS bug...\n"); + /* disable all SMIs, and clear "BIOS owns" flag */ + pci_write_config_dword(pdev, where + 4, 0); + pci_write_config_byte(pdev, where + 2, 0); + } else + ehci_dbg(ehci, "BIOS handoff succeeded\n"); + } + return 0; +} + +/* called by khubd or root hub init threads */ +static int ehci_pci_reset (struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci (hcd); + u32 temp; + unsigned count = 256/4; + + spin_lock_init (&ehci->lock); + + ehci->caps = hcd->regs; + ehci->regs = hcd->regs + HC_LENGTH (readl (&ehci->caps->hc_capbase)); + dbg_hcs_params (ehci, "reset"); + dbg_hcc_params (ehci, "reset"); + + /* cache this readonly data; minimize chip reads */ + ehci->hcs_params = readl (&ehci->caps->hcs_params); + + if (hcd->self.controller->bus == &pci_bus_type) { + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); + + switch (pdev->vendor) { + case PCI_VENDOR_ID_TDI: + if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { + ehci->is_tdi_rh_tt = 1; + tdi_reset (ehci); + } + break; + case PCI_VENDOR_ID_AMD: + /* AMD8111 EHCI doesn't work, according to AMD errata */ + if (pdev->device == 0x7463) { + ehci_info (ehci, "ignoring AMD8111 (errata)\n"); + return -EIO; + } + break; + case PCI_VENDOR_ID_NVIDIA: + /* NVidia reports that certain chips don't handle + * QH, ITD, or SITD addresses above 2GB. (But TD, + * data buffer, and periodic schedule are normal.) + */ + switch (pdev->device) { + case 0x003c: /* MCP04 */ + case 0x005b: /* CK804 */ + case 0x00d8: /* CK8 */ + case 0x00e8: /* CK8S */ + if (pci_set_consistent_dma_mask(pdev, + DMA_31BIT_MASK) < 0) + ehci_warn (ehci, "can't enable NVidia " + "workaround for >2GB RAM\n"); + break; + } + break; + } + + /* optional debug port, normally in the first BAR */ + temp = pci_find_capability (pdev, 0x0a); + if (temp) { + pci_read_config_dword(pdev, temp, &temp); + temp >>= 16; + if ((temp & (3 << 13)) == (1 << 13)) { + temp &= 0x1fff; + ehci->debug = hcd->regs + temp; + temp = readl (&ehci->debug->control); + ehci_info (ehci, "debug port %d%s\n", + HCS_DEBUG_PORT(ehci->hcs_params), + (temp & DBGP_ENABLED) + ? " IN USE" + : ""); + if (!(temp & DBGP_ENABLED)) + ehci->debug = NULL; + } + } + + temp = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params)); + } else + temp = 0; + + /* EHCI 0.96 and later may have "extended capabilities" */ + while (temp && count--) { + u32 cap; + + pci_read_config_dword (to_pci_dev(hcd->self.controller), + temp, &cap); + ehci_dbg (ehci, "capability %04x at %02x\n", cap, temp); + switch (cap & 0xff) { + case 1: /* BIOS/SMM/... handoff */ + if (bios_handoff (ehci, temp, cap) != 0) + return -EOPNOTSUPP; + break; + case 0: /* illegal reserved capability */ + ehci_warn (ehci, "illegal capability!\n"); + cap = 0; + /* FALLTHROUGH */ + default: /* unknown */ + break; + } + temp = (cap >> 8) & 0xff; + } + if (!count) { + ehci_err (ehci, "bogus capabilities ... PCI problems!\n"); + return -EIO; + } + if (ehci_is_TDI(ehci)) + ehci_reset (ehci); + + ehci_port_power (ehci, 0); + + /* at least the Genesys GL880S needs fixup here */ + temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); + temp &= 0x0f; + if (temp && HCS_N_PORTS(ehci->hcs_params) > temp) { + ehci_dbg (ehci, "bogus port configuration: " + "cc=%d x pcc=%d < ports=%d\n", + HCS_N_CC(ehci->hcs_params), + HCS_N_PCC(ehci->hcs_params), + HCS_N_PORTS(ehci->hcs_params)); + + if (hcd->self.controller->bus == &pci_bus_type) { + struct pci_dev *pdev; + + pdev = to_pci_dev(hcd->self.controller); + switch (pdev->vendor) { + case 0x17a0: /* GENESYS */ + /* GL880S: should be PORTS=2 */ + temp |= (ehci->hcs_params & ~0xf); + ehci->hcs_params = temp; + break; + case PCI_VENDOR_ID_NVIDIA: + /* NF4: should be PCC=10 */ + break; + } + } + } + + /* force HC to halt state */ + return ehci_halt (ehci); +} + +static int ehci_pci_start (struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci (hcd); + int result = 0; + + if (hcd->self.controller->bus == &pci_bus_type) { + struct pci_dev *pdev; + u16 port_wake; + + pdev = to_pci_dev(hcd->self.controller); + + /* Serial Bus Release Number is at PCI 0x60 offset */ + pci_read_config_byte(pdev, 0x60, &ehci->sbrn); + + /* port wake capability, reported by boot firmware */ + pci_read_config_word(pdev, 0x62, &port_wake); + hcd->can_wakeup = (port_wake & 1) != 0; + + /* help hc dma work well with cachelines */ + result = pci_set_mwi(pdev); + if (result) + ehci_dbg(ehci, "unable to enable MWI - not fatal.\n"); + } + + return ehci_run (hcd); +} + +/* always called by thread; normally rmmod */ + +static void ehci_pci_stop (struct usb_hcd *hcd) +{ + ehci_stop (hcd); +} + +/*-------------------------------------------------------------------------*/ + +#ifdef CONFIG_PM + +/* suspend/resume, section 4.3 */ + +/* These routines rely on the bus (pci, platform, etc) + * to handle powerdown and wakeup, and currently also on + * transceivers that don't need any software attention to set up + * the right sort of wakeup. + */ + +static int ehci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) +{ + struct ehci_hcd *ehci = hcd_to_ehci (hcd); + + if (time_before (jiffies, ehci->next_statechange)) + msleep (100); + +#ifdef CONFIG_USB_SUSPEND + (void) usb_suspend_device (hcd->self.root_hub); +#else + usb_lock_device (hcd->self.root_hub); + (void) ehci_bus_suspend (hcd); + usb_unlock_device (hcd->self.root_hub); +#endif + + // save (PCI) FLADJ in case of Vaux power loss + // ... we'd only use it to handle clock skew + + return 0; +} + +static int ehci_pci_resume (struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci (hcd); + unsigned port; + struct usb_device *root = hcd->self.root_hub; + int retval = -EINVAL; + + // maybe restore (PCI) FLADJ + + if (time_before (jiffies, ehci->next_statechange)) + msleep (100); + + /* If any port is suspended (or owned by the companion), + * we know we can/must resume the HC (and mustn't reset it). + */ + for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) { + u32 status; + port--; + status = readl (&ehci->regs->port_status [port]); + if (!(status & PORT_POWER)) + continue; + if (status & (PORT_SUSPEND | PORT_OWNER)) { + down (&hcd->self.root_hub->serialize); + retval = ehci_bus_resume (hcd); + up (&hcd->self.root_hub->serialize); + break; + } + if (!root->children [port]) + continue; + dbg_port (ehci, __FUNCTION__, port + 1, status); + usb_set_device_state (root->children[port], + USB_STATE_NOTATTACHED); + } + + /* Else reset, to cope with power loss or flush-to-storage + * style "resume" having activated BIOS during reboot. + */ + if (port == 0) { + (void) ehci_halt (ehci); + (void) ehci_reset (ehci); + (void) ehci_pci_reset (hcd); + + /* emptying the schedule aborts any urbs */ + spin_lock_irq (&ehci->lock); + if (ehci->reclaim) + ehci->reclaim_ready = 1; + ehci_work (ehci, NULL); + spin_unlock_irq (&ehci->lock); + + /* restart; khubd will disconnect devices */ + retval = ehci_run (hcd); + + /* here we "know" root ports should always stay powered; + * but some controllers may lose all power. + */ + ehci_port_power (ehci, 1); + } + + return retval; +} +#endif + +static const struct hc_driver ehci_pci_hc_driver = { + .description = hcd_name, + .product_desc = "EHCI Host Controller", + .hcd_priv_size = sizeof(struct ehci_hcd), + + /* + * generic hardware linkage + */ + .irq = ehci_irq, + .flags = HCD_MEMORY | HCD_USB2, + + /* + * basic lifecycle operations + */ + .reset = ehci_pci_reset, + .start = ehci_pci_start, +#ifdef CONFIG_PM + .suspend = ehci_pci_suspend, + .resume = ehci_pci_resume, +#endif + .stop = ehci_pci_stop, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ehci_urb_enqueue, + .urb_dequeue = ehci_urb_dequeue, + .endpoint_disable = ehci_endpoint_disable, + + /* + * scheduling support + */ + .get_frame_number = ehci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ehci_hub_status_data, + .hub_control = ehci_hub_control, + .bus_suspend = ehci_bus_suspend, + .bus_resume = ehci_bus_resume, +}; + +/*-------------------------------------------------------------------------*/ + +/* PCI driver selection metadata; PCI hotplugging uses this */ +static const struct pci_device_id pci_ids [] = { { + /* handle any USB 2.0 EHCI controller */ + PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x20), ~0), + .driver_data = (unsigned long) &ehci_pci_hc_driver, + }, + { /* end: all zeroes */ } +}; +MODULE_DEVICE_TABLE (pci, pci_ids); + +/* pci driver glue; this is a "new style" PCI driver module */ +static struct pci_driver ehci_pci_driver = { + .name = (char *) hcd_name, + .id_table = pci_ids, + .owner = THIS_MODULE, + + .probe = usb_hcd_pci_probe, + .remove = usb_hcd_pci_remove, + +#ifdef CONFIG_PM + .suspend = usb_hcd_pci_suspend, + .resume = usb_hcd_pci_resume, +#endif +}; + +static int __init ehci_hcd_pci_init (void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_debug ("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", + hcd_name, + sizeof (struct ehci_qh), sizeof (struct ehci_qtd), + sizeof (struct ehci_itd), sizeof (struct ehci_sitd)); + + return pci_register_driver (&ehci_pci_driver); +} +module_init (ehci_hcd_pci_init); + +static void __exit ehci_hcd_pci_cleanup (void) +{ + pci_unregister_driver (&ehci_pci_driver); +} +module_exit (ehci_hcd_pci_cleanup); diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 940d38c..5bb872c 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -477,7 +477,7 @@ qh_urb_transaction ( struct ehci_hcd *ehci, struct urb *urb, struct list_head *head, - int flags + gfp_t flags ) { struct ehci_qtd *qtd, *qtd_prev; dma_addr_t buf; @@ -629,7 +629,7 @@ static struct ehci_qh * qh_make ( struct ehci_hcd *ehci, struct urb *urb, - int flags + gfp_t flags ) { struct ehci_qh *qh = ehci_qh_alloc (ehci, flags); u32 info1 = 0, info2 = 0; @@ -906,7 +906,7 @@ submit_async ( struct usb_host_endpoint *ep, struct urb *urb, struct list_head *qtd_list, - unsigned mem_flags + gfp_t mem_flags ) { struct ehci_qtd *qtd; int epnum; diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index ccc7300..f0c8aa1 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -589,7 +589,7 @@ static int intr_submit ( struct usb_host_endpoint *ep, struct urb *urb, struct list_head *qtd_list, - unsigned mem_flags + gfp_t mem_flags ) { unsigned epnum; unsigned long flags; @@ -634,7 +634,7 @@ done: /* ehci_iso_stream ops work with both ITD and SITD */ static struct ehci_iso_stream * -iso_stream_alloc (unsigned mem_flags) +iso_stream_alloc (gfp_t mem_flags) { struct ehci_iso_stream *stream; @@ -851,7 +851,7 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb) /* ehci_iso_sched ops can be ITD-only or SITD-only */ static struct ehci_iso_sched * -iso_sched_alloc (unsigned packets, unsigned mem_flags) +iso_sched_alloc (unsigned packets, gfp_t mem_flags) { struct ehci_iso_sched *iso_sched; int size = sizeof *iso_sched; @@ -924,7 +924,7 @@ itd_urb_transaction ( struct ehci_iso_stream *stream, struct ehci_hcd *ehci, struct urb *urb, - unsigned mem_flags + gfp_t mem_flags ) { struct ehci_itd *itd; @@ -1418,7 +1418,7 @@ itd_complete ( /*-------------------------------------------------------------------------*/ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, - unsigned mem_flags) + gfp_t mem_flags) { int status = -EINVAL; unsigned long flags; @@ -1529,7 +1529,7 @@ sitd_urb_transaction ( struct ehci_iso_stream *stream, struct ehci_hcd *ehci, struct urb *urb, - unsigned mem_flags + gfp_t mem_flags ) { struct ehci_sitd *sitd; @@ -1779,7 +1779,7 @@ sitd_complete ( static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, - unsigned mem_flags) + gfp_t mem_flags) { int status = -EINVAL; unsigned long flags; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index f34a051..18e257c 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -97,6 +97,7 @@ struct ehci_hcd { /* one per controller */ #else # define COUNT(x) do {} while (0) #endif + u8 sbrn; /* packed release number */ }; /* convert between an HCD pointer and the corresponding EHCI_HCD */ diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index e142056..f9c3f5b 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -70,6 +70,7 @@ #include <linux/interrupt.h> #include <linux/usb.h> #include <linux/usb_isp116x.h> +#include <linux/platform_device.h> #include <asm/io.h> #include <asm/irq.h> @@ -638,7 +639,7 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs) + msecs_to_jiffies(20) + 1); if (intstat & HCINT_RD) { DBG("---- remote wakeup\n"); - schedule_work(&isp116x->rh_resume); + usb_hcd_resume_root_hub(hcd); ret = IRQ_HANDLED; } irqstat &= ~HCuPINT_OPR; @@ -694,7 +695,7 @@ static int balance(struct isp116x *isp116x, u16 period, u16 load) static int isp116x_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep, struct urb *urb, - unsigned mem_flags) + gfp_t mem_flags) { struct isp116x *isp116x = hcd_to_isp116x(hcd); struct usb_device *udev = urb->dev; @@ -1160,7 +1161,7 @@ static int isp116x_hub_control(struct usb_hcd *hcd, #ifdef CONFIG_PM -static int isp116x_hub_suspend(struct usb_hcd *hcd) +static int isp116x_bus_suspend(struct usb_hcd *hcd) { struct isp116x *isp116x = hcd_to_isp116x(hcd); unsigned long flags; @@ -1200,7 +1201,7 @@ static int isp116x_hub_suspend(struct usb_hcd *hcd) return ret; } -static int isp116x_hub_resume(struct usb_hcd *hcd) +static int isp116x_bus_resume(struct usb_hcd *hcd) { struct isp116x *isp116x = hcd_to_isp116x(hcd); u32 val; @@ -1263,21 +1264,11 @@ static int isp116x_hub_resume(struct usb_hcd *hcd) return 0; } -static void isp116x_rh_resume(void *_hcd) -{ - struct usb_hcd *hcd = _hcd; - - usb_resume_device(hcd->self.root_hub); -} #else -#define isp116x_hub_suspend NULL -#define isp116x_hub_resume NULL - -static void isp116x_rh_resume(void *_hcd) -{ -} +#define isp116x_bus_suspend NULL +#define isp116x_bus_resume NULL #endif @@ -1636,8 +1627,8 @@ static struct hc_driver isp116x_hc_driver = { .hub_status_data = isp116x_hub_status_data, .hub_control = isp116x_hub_control, - .hub_suspend = isp116x_hub_suspend, - .hub_resume = isp116x_hub_resume, + .bus_suspend = isp116x_bus_suspend, + .bus_resume = isp116x_bus_resume, }; /*----------------------------------------------------------------*/ @@ -1732,7 +1723,6 @@ static int __init isp116x_probe(struct device *dev) isp116x->addr_reg = addr_reg; spin_lock_init(&isp116x->lock); INIT_LIST_HEAD(&isp116x->async); - INIT_WORK(&isp116x->rh_resume, isp116x_rh_resume, hcd); isp116x->board = dev->platform_data; if (!isp116x->board) { @@ -1774,22 +1764,13 @@ static int __init isp116x_probe(struct device *dev) /* Suspend of platform device */ -static int isp116x_suspend(struct device *dev, pm_message_t state, u32 phase) +static int isp116x_suspend(struct device *dev, pm_message_t state) { int ret = 0; - struct usb_hcd *hcd = dev_get_drvdata(dev); - VDBG("%s: state %x, phase %x\n", __func__, state, phase); + VDBG("%s: state %x\n", __func__, state); - if (phase != SUSPEND_DISABLE && phase != SUSPEND_POWER_DOWN) - return 0; - - ret = usb_suspend_device(hcd->self.root_hub, state); - if (!ret) { - dev->power.power_state = state; - INFO("%s suspended\n", hcd_name); - } else - ERR("%s suspend failed\n", hcd_name); + dev->power.power_state = state; return ret; } @@ -1797,21 +1778,14 @@ static int isp116x_suspend(struct device *dev, pm_message_t state, u32 phase) /* Resume platform device */ -static int isp116x_resume(struct device *dev, u32 phase) +static int isp116x_resume(struct device *dev) { int ret = 0; - struct usb_hcd *hcd = dev_get_drvdata(dev); - VDBG("%s: state %x, phase %x\n", __func__, dev->power.power_state, - phase); - if (phase != RESUME_POWER_ON) - return 0; + VDBG("%s: state %x\n", __func__, dev->power.power_state); + + dev->power.power_state = PMSG_ON; - ret = usb_resume_device(hcd->self.root_hub); - if (!ret) { - dev->power.power_state = PMSG_ON; - VDBG("%s resumed\n", (char *)hcd_name); - } return ret; } diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h index 5887347..c6fec96 100644 --- a/drivers/usb/host/isp116x.h +++ b/drivers/usb/host/isp116x.h @@ -253,7 +253,6 @@ static const int cc_to_error[16] = { struct isp116x { spinlock_t lock; - struct work_struct rh_resume; void __iomem *addr_reg; void __iomem *data_reg; diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c index 3981bf1..f0c78cf 100644 --- a/drivers/usb/host/ohci-au1xxx.c +++ b/drivers/usb/host/ohci-au1xxx.c @@ -18,6 +18,8 @@ * This file is licenced under the GPL. */ +#include <linux/platform_device.h> + #include <asm/mach-au1x00/au1000.h> #define USBH_ENABLE_BE (1<<0) @@ -214,6 +216,11 @@ static const struct hc_driver ohci_au1xxx_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, +#ifdef CONFIG_PM + .bus_suspend = ohci_bus_suspend, + .bus_resume = ohci_bus_resume, +#endif + .start_port_reset = ohci_start_port_reset, }; /*-------------------------------------------------------------------------*/ @@ -259,6 +266,7 @@ static int ohci_hcd_au1xxx_drv_resume(struct device *dev) static struct device_driver ohci_hcd_au1xxx_driver = { .name = "au1xxx-ohci", + .owner = THIS_MODULE, .bus = &platform_bus_type, .probe = ohci_hcd_au1xxx_drv_probe, .remove = ohci_hcd_au1xxx_drv_remove, diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index 7924c74..7bfffcbb 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c @@ -193,10 +193,6 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size) maybe_print_eds (controller, "donehead", ohci_readl (controller, ®s->donehead), next, size); - - /* broken fminterval means traffic won't flow! */ - ohci_dbg (controller, "fminterval %08x\n", - ohci_readl (controller, ®s->fminterval)); } #define dbg_port_sw(hc,num,value,next,size) \ diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 67c1aa5..5c0c6c8 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -180,7 +180,7 @@ static int ohci_urb_enqueue ( struct usb_hcd *hcd, struct usb_host_endpoint *ep, struct urb *urb, - unsigned mem_flags + gfp_t mem_flags ) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); struct ed *ed; @@ -723,7 +723,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) ohci_vdbg (ohci, "resume detect\n"); ohci_writel (ohci, OHCI_INTR_RD, ®s->intrstatus); if (hcd->state != HC_STATE_QUIESCING) - schedule_work(&ohci->rh_resume); + usb_hcd_resume_root_hub(hcd); } if (ints & OHCI_INTR_WDH) { @@ -791,7 +791,7 @@ static void ohci_stop (struct usb_hcd *hcd) /* must not be called from interrupt context */ -#if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM) +#ifdef CONFIG_PM static int ohci_restart (struct ohci_hcd *ohci) { diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index ce7b28d..e01e77b 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -36,7 +36,7 @@ /*-------------------------------------------------------------------------*/ -#if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM) +#ifdef CONFIG_PM #define OHCI_SCHED_ENABLES \ (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE) @@ -45,7 +45,7 @@ static void dl_done_list (struct ohci_hcd *, struct pt_regs *); static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *); static int ohci_restart (struct ohci_hcd *ohci); -static int ohci_hub_suspend (struct usb_hcd *hcd) +static int ohci_bus_suspend (struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); int status = 0; @@ -73,7 +73,6 @@ static int ohci_hub_suspend (struct usb_hcd *hcd) ohci_dbg (ohci, "suspend root hub\n"); /* First stop any processing */ - hcd->state = HC_STATE_QUIESCING; if (ohci->hc_control & OHCI_SCHED_ENABLES) { int limit; @@ -108,7 +107,9 @@ static int ohci_hub_suspend (struct usb_hcd *hcd) else ohci->hc_control &= ~OHCI_CTRL_RWE; - /* Suspend hub */ + /* Suspend hub ... this is the "global (to this bus) suspend" mode, + * which doesn't imply ports will first be individually suspended. + */ ohci->hc_control &= ~OHCI_CTRL_HCFS; ohci->hc_control |= OHCI_USB_SUSPEND; ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); @@ -118,8 +119,9 @@ static int ohci_hub_suspend (struct usb_hcd *hcd) ohci->next_statechange = jiffies + msecs_to_jiffies (5); done: + /* external suspend vs self autosuspend ... same effect */ if (status == 0) - hcd->state = HC_STATE_SUSPENDED; + usb_hcd_suspend_root_hub(hcd); spin_unlock_irqrestore (&ohci->lock, flags); return status; } @@ -133,7 +135,7 @@ static inline struct ed *find_head (struct ed *ed) } /* caller has locked the root hub */ -static int ohci_hub_resume (struct usb_hcd *hcd) +static int ohci_bus_resume (struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); u32 temp, enables; @@ -146,7 +148,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd) ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { - /* this can happen after suspend-to-disk */ + /* this can happen after resuming a swsusp snapshot */ if (hcd->state == HC_STATE_RESUMING) { ohci_dbg (ohci, "BIOS/SMM active, control %03x\n", ohci->hc_control); @@ -169,11 +171,12 @@ static int ohci_hub_resume (struct usb_hcd *hcd) ohci_info (ohci, "wakeup\n"); break; case OHCI_USB_OPER: - ohci_dbg (ohci, "already resumed\n"); - status = 0; + /* this can happen after resuming a swsusp snapshot */ + ohci_dbg (ohci, "snapshot resume? reinit\n"); + status = -EBUSY; break; default: /* RESET, we lost power */ - ohci_dbg (ohci, "root hub hardware reset\n"); + ohci_dbg (ohci, "lost power\n"); status = -EBUSY; } spin_unlock_irq (&ohci->lock); @@ -198,8 +201,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd) } /* Some controllers (lucent erratum) need extra-long delays */ - hcd->state = HC_STATE_RESUMING; - mdelay (20 /* usb 11.5.1.10 */ + 15); + msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1); temp = ohci_readl (ohci, &ohci->regs->control); temp &= OHCI_CTRL_HCFS; @@ -273,28 +275,10 @@ static int ohci_hub_resume (struct usb_hcd *hcd) (void) ohci_readl (ohci, &ohci->regs->control); } - hcd->state = HC_STATE_RUNNING; return 0; } -static void ohci_rh_resume (void *_hcd) -{ - struct usb_hcd *hcd = _hcd; - - usb_lock_device (hcd->self.root_hub); - (void) ohci_hub_resume (hcd); - usb_unlock_device (hcd->self.root_hub); -} - -#else - -static void ohci_rh_resume (void *_hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci (_hcd); - ohci_dbg(ohci, "rh_resume ??\n"); -} - -#endif /* CONFIG_USB_SUSPEND || CONFIG_PM */ +#endif /* CONFIG_PM */ /*-------------------------------------------------------------------------*/ @@ -367,7 +351,6 @@ done: #ifdef CONFIG_PM /* save power by suspending idle root hubs; * INTR_RD wakes us when there's work - * NOTE: if we can do this, we don't need a root hub timer! */ if (can_suspend && !changed @@ -379,8 +362,7 @@ done: && usb_trylock_device (hcd->self.root_hub) ) { ohci_vdbg (ohci, "autosuspend\n"); - (void) ohci_hub_suspend (hcd); - hcd->state = HC_STATE_RUNNING; + (void) ohci_bus_suspend (hcd); usb_unlock_device (hcd->self.root_hub); } #endif @@ -554,7 +536,7 @@ static int ohci_hub_control ( temp = RH_PS_POCI; if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) - schedule_work (&ohci->rh_resume); + usb_hcd_resume_root_hub(hcd); break; case USB_PORT_FEAT_C_SUSPEND: temp = RH_PS_PSSC; diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c index 859aca7b..336c766 100644 --- a/drivers/usb/host/ohci-lh7a404.c +++ b/drivers/usb/host/ohci-lh7a404.c @@ -16,6 +16,8 @@ * This file is licenced under the GPL. */ +#include <linux/platform_device.h> + #include <asm/hardware.h> @@ -193,6 +195,11 @@ static const struct hc_driver ohci_lh7a404_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, +#ifdef CONFIG_PM + .bus_suspend = ohci_bus_suspend, + .bus_resume = ohci_bus_resume, +#endif + .start_port_reset = ohci_start_port_reset, }; /*-------------------------------------------------------------------------*/ @@ -239,6 +246,7 @@ static int ohci_hcd_lh7a404_drv_resume(struct device *dev) static struct device_driver ohci_hcd_lh7a404_driver = { .name = "lh7a404-ohci", + .owner = THIS_MODULE, .bus = &platform_bus_type, .probe = ohci_hcd_lh7a404_drv_probe, .remove = ohci_hcd_lh7a404_drv_remove, diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c index fd3c4d3..bfbe328 100644 --- a/drivers/usb/host/ohci-mem.c +++ b/drivers/usb/host/ohci-mem.c @@ -28,7 +28,6 @@ static void ohci_hcd_init (struct ohci_hcd *ohci) ohci->next_statechange = jiffies; spin_lock_init (&ohci->lock); INIT_LIST_HEAD (&ohci->pending); - INIT_WORK (&ohci->rh_resume, ohci_rh_resume, ohci_to_hcd(ohci)); ohci->reboot_notifier.notifier_call = ohci_reboot; } @@ -84,7 +83,7 @@ dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma) /* TDs ... */ static struct td * -td_alloc (struct ohci_hcd *hc, unsigned mem_flags) +td_alloc (struct ohci_hcd *hc, gfp_t mem_flags) { dma_addr_t dma; struct td *td; @@ -118,7 +117,7 @@ td_free (struct ohci_hcd *hc, struct td *td) /* EDs ... */ static struct ed * -ed_alloc (struct ohci_hcd *hc, unsigned mem_flags) +ed_alloc (struct ohci_hcd *hc, gfp_t mem_flags) { dma_addr_t dma; struct ed *ed; diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index d8f3ba7..e46cc54 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -14,6 +14,10 @@ * This file is licenced under the GPL. */ +#include <linux/signal.h> /* SA_INTERRUPT */ +#include <linux/jiffies.h> +#include <linux/platform_device.h> + #include <asm/hardware.h> #include <asm/io.h> #include <asm/mach-types.h> @@ -420,9 +424,9 @@ static const struct hc_driver ohci_omap_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, -#ifdef CONFIG_USB_SUSPEND - .hub_suspend = ohci_hub_suspend, - .hub_resume = ohci_hub_resume, +#ifdef CONFIG_PM + .bus_suspend = ohci_bus_suspend, + .bus_resume = ohci_bus_resume, #endif .start_port_reset = ohci_start_port_reset, }; @@ -455,50 +459,32 @@ static int ohci_hcd_omap_drv_remove(struct device *dev) #ifdef CONFIG_PM -static int ohci_omap_suspend(struct device *dev, pm_message_t message, u32 level) +static int ohci_omap_suspend(struct device *dev, pm_message_t message) { struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev)); - int status = -EINVAL; - - if (level != SUSPEND_POWER_DOWN) - return 0; - - down(&ohci_to_hcd(ohci)->self.root_hub->serialize); - status = ohci_hub_suspend(ohci_to_hcd(ohci)); - if (status == 0) { - omap_ohci_clock_power(0); - ohci_to_hcd(ohci)->self.root_hub->state = - USB_STATE_SUSPENDED; - ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED; - dev->power.power_state = PMSG_SUSPEND; - } - up(&ohci_to_hcd(ohci)->self.root_hub->serialize); - return status; + + if (time_before(jiffies, ohci->next_statechange)) + msleep(5); + ohci->next_statechange = jiffies; + + omap_ohci_clock_power(0); + ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED; + dev->power.power_state = PMSG_SUSPEND; + return 0; } -static int ohci_omap_resume(struct device *dev, u32 level) +static int ohci_omap_resume(struct device *dev) { struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev)); - int status = 0; - - if (level != RESUME_POWER_ON) - return 0; if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies; + omap_ohci_clock_power(1); -#ifdef CONFIG_USB_SUSPEND - /* get extra cleanup even if remote wakeup isn't in use */ - status = usb_resume_device(ohci_to_hcd(ohci)->self.root_hub); -#else - down(&ohci_to_hcd(ohci)->self.root_hub->serialize); - status = ohci_hub_resume(ohci_to_hcd(ohci)); - up(&ohci_to_hcd(ohci)->self.root_hub->serialize); -#endif - if (status == 0) - dev->power.power_state = PMSG_ON; - return status; + dev->power.power_state = PMSG_ON; + usb_hcd_resume_root_hub(dev_get_drvdata(dev)); + return 0; } #endif @@ -510,6 +496,7 @@ static int ohci_omap_resume(struct device *dev, u32 level) */ static struct device_driver ohci_hcd_omap_driver = { .name = "ohci", + .owner = THIS_MODULE, .bus = &platform_bus_type, .probe = ohci_hcd_omap_drv_probe, .remove = ohci_hcd_omap_drv_remove, diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index eede6be..7ce1d9e 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -14,6 +14,8 @@ * This file is licenced under the GPL. */ +#include <linux/jiffies.h> + #ifdef CONFIG_PPC_PMAC #include <asm/machdep.h> #include <asm/pmac_feature.h> @@ -112,23 +114,13 @@ ohci_pci_start (struct usb_hcd *hcd) static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) { - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - - /* suspend root hub, hoping it keeps power during suspend */ - if (time_before (jiffies, ohci->next_statechange)) - msleep (100); - -#ifdef CONFIG_USB_SUSPEND - (void) usb_suspend_device (hcd->self.root_hub, message); -#else - usb_lock_device (hcd->self.root_hub); - (void) ohci_hub_suspend (hcd); - usb_unlock_device (hcd->self.root_hub); -#endif + /* root hub was already suspended */ - /* let things settle down a bit */ - msleep (100); - + /* FIXME these PMAC things get called in the wrong places. ASIC + * clocks should be turned off AFTER entering D3, and on BEFORE + * trying to enter D0. Evidently the PCI layer doesn't currently + * provide the right sort of platform hooks for this ... + */ #ifdef CONFIG_PPC_PMAC if (_machine == _MACH_Pmac) { struct device_node *of_node; @@ -145,9 +137,6 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) static int ohci_pci_resume (struct usb_hcd *hcd) { - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - int retval = 0; - #ifdef CONFIG_PPC_PMAC if (_machine == _MACH_Pmac) { struct device_node *of_node; @@ -159,19 +148,8 @@ static int ohci_pci_resume (struct usb_hcd *hcd) } #endif /* CONFIG_PPC_PMAC */ - /* resume root hub */ - if (time_before (jiffies, ohci->next_statechange)) - msleep (100); -#ifdef CONFIG_USB_SUSPEND - /* get extra cleanup even if remote wakeup isn't in use */ - retval = usb_resume_device (hcd->self.root_hub); -#else - usb_lock_device (hcd->self.root_hub); - retval = ohci_hub_resume (hcd); - usb_unlock_device (hcd->self.root_hub); -#endif - - return retval; + usb_hcd_resume_root_hub(hcd); + return 0; } #endif /* CONFIG_PM */ @@ -218,9 +196,9 @@ static const struct hc_driver ohci_pci_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, -#ifdef CONFIG_USB_SUSPEND - .hub_suspend = ohci_hub_suspend, - .hub_resume = ohci_hub_resume, +#ifdef CONFIG_PM + .bus_suspend = ohci_bus_suspend, + .bus_resume = ohci_bus_resume, #endif .start_port_reset = ohci_start_port_reset, }; @@ -240,6 +218,7 @@ MODULE_DEVICE_TABLE (pci, pci_ids); static struct pci_driver ohci_pci_driver = { .name = (char *) hcd_name, .id_table = pci_ids, + .owner = THIS_MODULE, .probe = usb_hcd_pci_probe, .remove = usb_hcd_pci_remove, diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c index 2515333..92cf6f4a 100644 --- a/drivers/usb/host/ohci-ppc-soc.c +++ b/drivers/usb/host/ohci-ppc-soc.c @@ -14,6 +14,8 @@ * This file is licenced under the GPL. */ +#include <linux/platform_device.h> + /* configure so an HC device and id are always provided */ /* always called with process context; sleeping is OK */ @@ -163,9 +165,9 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, -#ifdef CONFIG_USB_SUSPEND - .hub_suspend = ohci_hub_suspend, - .hub_resume = ohci_hub_resume, +#ifdef CONFIG_PM + .bus_suspend = ohci_bus_suspend, + .bus_resume = ohci_bus_resume, #endif .start_port_reset = ohci_start_port_reset, }; @@ -193,10 +195,11 @@ static int ohci_hcd_ppc_soc_drv_remove(struct device *dev) static struct device_driver ohci_hcd_ppc_soc_driver = { .name = "ppc-soc-ohci", + .owner = THIS_MODULE, .bus = &platform_bus_type, .probe = ohci_hcd_ppc_soc_drv_probe, .remove = ohci_hcd_ppc_soc_drv_remove, -#if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM) +#ifdef CONFIG_PM /*.suspend = ohci_hcd_ppc_soc_drv_suspend,*/ /*.resume = ohci_hcd_ppc_soc_drv_resume,*/ #endif diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index 2fdb262..59e2056 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -20,6 +20,9 @@ */ #include <linux/device.h> +#include <linux/signal.h> +#include <linux/platform_device.h> + #include <asm/mach-types.h> #include <asm/hardware.h> #include <asm/arch/pxa-regs.h> @@ -278,10 +281,11 @@ static const struct hc_driver ohci_pxa27x_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, -#ifdef CONFIG_USB_SUSPEND - .hub_suspend = ohci_hub_suspend, - .hub_resume = ohci_hub_resume, +#ifdef CONFIG_PM + .bus_suspend = ohci_bus_suspend, + .bus_resume = ohci_bus_resume, #endif + .start_port_reset = ohci_start_port_reset, }; /*-------------------------------------------------------------------------*/ @@ -309,7 +313,7 @@ static int ohci_hcd_pxa27x_drv_remove(struct device *dev) return 0; } -static int ohci_hcd_pxa27x_drv_suspend(struct device *dev, pm_message_t state, u32 level) +static int ohci_hcd_pxa27x_drv_suspend(struct device *dev, pm_message_t state) { // struct platform_device *pdev = to_platform_device(dev); // struct usb_hcd *hcd = dev_get_drvdata(dev); @@ -318,7 +322,7 @@ static int ohci_hcd_pxa27x_drv_suspend(struct device *dev, pm_message_t state, u return 0; } -static int ohci_hcd_pxa27x_drv_resume(struct device *dev, u32 level) +static int ohci_hcd_pxa27x_drv_resume(struct device *dev) { // struct platform_device *pdev = to_platform_device(dev); // struct usb_hcd *hcd = dev_get_drvdata(dev); diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index da7d547..ee1fc60 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -19,6 +19,8 @@ * This file is licenced under the GPL. */ +#include <linux/platform_device.h> + #include <asm/hardware.h> #include <asm/hardware/clock.h> #include <asm/arch/usb-control.h> @@ -448,11 +450,11 @@ static const struct hc_driver ohci_s3c2410_hc_driver = { */ .hub_status_data = ohci_s3c2410_hub_status_data, .hub_control = ohci_s3c2410_hub_control, - -#if defined(CONFIG_USB_SUSPEND) && 0 - .hub_suspend = ohci_hub_suspend, - .hub_resume = ohci_hub_resume, +#ifdef CONFIG_PM + .bus_suspend = ohci_bus_suspend, + .bus_resume = ohci_bus_resume, #endif + .start_port_reset = ohci_start_port_reset, }; /* device driver */ @@ -474,6 +476,7 @@ static int ohci_hcd_s3c2410_drv_remove(struct device *dev) static struct device_driver ohci_hcd_s3c2410_driver = { .name = "s3c2410-ohci", + .owner = THIS_MODULE, .bus = &platform_bus_type, .probe = ohci_hcd_s3c2410_drv_probe, .remove = ohci_hcd_s3c2410_drv_remove, diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c index 814d2be..fb3221e 100644 --- a/drivers/usb/host/ohci-sa1111.c +++ b/drivers/usb/host/ohci-sa1111.c @@ -235,10 +235,11 @@ static const struct hc_driver ohci_sa1111_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, -#ifdef CONFIG_USB_SUSPEND - .hub_suspend = ohci_hub_suspend, - .hub_resume = ohci_hub_resume, +#ifdef CONFIG_PM + .bus_suspend = ohci_bus_suspend, + .bus_resume = ohci_bus_resume, #endif + .start_port_reset = ohci_start_port_reset, }; /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 8a9b9d9..caacf14 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -389,7 +389,6 @@ struct ohci_hcd { unsigned long next_statechange; /* suspend/resume */ u32 fminterval; /* saved register */ - struct work_struct rh_resume; struct notifier_block reboot_notifier; unsigned long flags; /* for HC bugs */ diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c new file mode 100644 index 0000000..b7fd3f6 --- /dev/null +++ b/drivers/usb/host/pci-quirks.c @@ -0,0 +1,296 @@ +/* + * This file contains code to reset and initialize USB host controllers. + * Some of it includes work-arounds for PCI hardware and BIOS quirks. + * It may need to run early during booting -- before USB would normally + * initialize -- to ensure that Linux doesn't use any legacy modes. + * + * Copyright (c) 1999 Martin Mares <mj@ucw.cz> + * (and others) + */ + +#include <linux/config.h> +#ifdef CONFIG_USB_DEBUG +#define DEBUG +#else +#undef DEBUG +#endif + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/acpi.h> + + +#define UHCI_USBLEGSUP 0xc0 /* legacy support */ +#define UHCI_USBCMD 0 /* command register */ +#define UHCI_USBINTR 4 /* interrupt register */ +#define UHCI_USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ +#define UHCI_USBLEGSUP_RO 0x5040 /* R/O and reserved bits */ +#define UHCI_USBCMD_RUN 0x0001 /* RUN/STOP bit */ +#define UHCI_USBCMD_HCRESET 0x0002 /* Host Controller reset */ +#define UHCI_USBCMD_EGSM 0x0008 /* Global Suspend Mode */ +#define UHCI_USBCMD_CONFIGURE 0x0040 /* Config Flag */ +#define UHCI_USBINTR_RESUME 0x0002 /* Resume interrupt enable */ + +#define OHCI_CONTROL 0x04 +#define OHCI_CMDSTATUS 0x08 +#define OHCI_INTRSTATUS 0x0c +#define OHCI_INTRENABLE 0x10 +#define OHCI_INTRDISABLE 0x14 +#define OHCI_OCR (1 << 3) /* ownership change request */ +#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ +#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ +#define OHCI_INTR_OC (1 << 30) /* ownership change */ + +#define EHCI_HCC_PARAMS 0x08 /* extended capabilities */ +#define EHCI_USBCMD 0 /* command register */ +#define EHCI_USBCMD_RUN (1 << 0) /* RUN/STOP bit */ +#define EHCI_USBSTS 4 /* status register */ +#define EHCI_USBSTS_HALTED (1 << 12) /* HCHalted bit */ +#define EHCI_USBINTR 8 /* interrupt register */ +#define EHCI_USBLEGSUP 0 /* legacy support register */ +#define EHCI_USBLEGSUP_BIOS (1 << 16) /* BIOS semaphore */ +#define EHCI_USBLEGSUP_OS (1 << 24) /* OS semaphore */ +#define EHCI_USBLEGCTLSTS 4 /* legacy control/status */ +#define EHCI_USBLEGCTLSTS_SOOE (1 << 13) /* SMI on ownership change */ + + +/* + * Make sure the controller is completely inactive, unable to + * generate interrupts or do DMA. + */ +void uhci_reset_hc(struct pci_dev *pdev, unsigned long base) +{ + /* Turn off PIRQ enable and SMI enable. (This also turns off the + * BIOS's USB Legacy Support.) Turn off all the R/WC bits too. + */ + pci_write_config_word(pdev, UHCI_USBLEGSUP, UHCI_USBLEGSUP_RWC); + + /* Reset the HC - this will force us to get a + * new notification of any already connected + * ports due to the virtual disconnect that it + * implies. + */ + outw(UHCI_USBCMD_HCRESET, base + UHCI_USBCMD); + mb(); + udelay(5); + if (inw(base + UHCI_USBCMD) & UHCI_USBCMD_HCRESET) + dev_warn(&pdev->dev, "HCRESET not completed yet!\n"); + + /* Just to be safe, disable interrupt requests and + * make sure the controller is stopped. + */ + outw(0, base + UHCI_USBINTR); + outw(0, base + UHCI_USBCMD); +} +EXPORT_SYMBOL_GPL(uhci_reset_hc); + +/* + * Initialize a controller that was newly discovered or has just been + * resumed. In either case we can't be sure of its previous state. + * + * Returns: 1 if the controller was reset, 0 otherwise. + */ +int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base) +{ + u16 legsup; + unsigned int cmd, intr; + + /* + * When restarting a suspended controller, we expect all the + * settings to be the same as we left them: + * + * PIRQ and SMI disabled, no R/W bits set in USBLEGSUP; + * Controller is stopped and configured with EGSM set; + * No interrupts enabled except possibly Resume Detect. + * + * If any of these conditions are violated we do a complete reset. + */ + pci_read_config_word(pdev, UHCI_USBLEGSUP, &legsup); + if (legsup & ~(UHCI_USBLEGSUP_RO | UHCI_USBLEGSUP_RWC)) { + dev_dbg(&pdev->dev, "%s: legsup = 0x%04x\n", + __FUNCTION__, legsup); + goto reset_needed; + } + + cmd = inw(base + UHCI_USBCMD); + if ((cmd & UHCI_USBCMD_RUN) || !(cmd & UHCI_USBCMD_CONFIGURE) || + !(cmd & UHCI_USBCMD_EGSM)) { + dev_dbg(&pdev->dev, "%s: cmd = 0x%04x\n", + __FUNCTION__, cmd); + goto reset_needed; + } + + intr = inw(base + UHCI_USBINTR); + if (intr & (~UHCI_USBINTR_RESUME)) { + dev_dbg(&pdev->dev, "%s: intr = 0x%04x\n", + __FUNCTION__, intr); + goto reset_needed; + } + return 0; + +reset_needed: + dev_dbg(&pdev->dev, "Performing full reset\n"); + uhci_reset_hc(pdev, base); + return 1; +} +EXPORT_SYMBOL_GPL(uhci_check_and_reset_hc); + +static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev) +{ + unsigned long base = 0; + int i; + + for (i = 0; i < PCI_ROM_RESOURCE; i++) + if ((pci_resource_flags(pdev, i) & IORESOURCE_IO)) { + base = pci_resource_start(pdev, i); + break; + } + + if (base) + uhci_check_and_reset_hc(pdev, base); +} + +static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) +{ + void __iomem *base; + int wait_time; + u32 control; + + base = ioremap_nocache(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + if (base == NULL) return; + +/* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ +#ifndef __hppa__ + control = readl(base + OHCI_CONTROL); + if (control & OHCI_CTRL_IR) { + wait_time = 500; /* arbitrary; 5 seconds */ + writel(OHCI_INTR_OC, base + OHCI_INTRENABLE); + writel(OHCI_OCR, base + OHCI_CMDSTATUS); + while (wait_time > 0 && + readl(base + OHCI_CONTROL) & OHCI_CTRL_IR) { + wait_time -= 10; + msleep(10); + } + if (wait_time <= 0) + printk(KERN_WARNING "%s %s: early BIOS handoff " + "failed (BIOS bug ?)\n", + pdev->dev.bus_id, "OHCI"); + + /* reset controller, preserving RWC */ + writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL); + } +#endif + + /* + * disable interrupts + */ + writel(~(u32)0, base + OHCI_INTRDISABLE); + writel(~(u32)0, base + OHCI_INTRSTATUS); + + iounmap(base); +} + +static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) +{ + int wait_time, delta; + void __iomem *base, *op_reg_base; + u32 hcc_params, val, temp; + u8 cap_length; + + base = ioremap_nocache(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + if (base == NULL) return; + + cap_length = readb(base); + op_reg_base = base + cap_length; + hcc_params = readl(base + EHCI_HCC_PARAMS); + hcc_params = (hcc_params >> 8) & 0xff; + if (hcc_params) { + pci_read_config_dword(pdev, + hcc_params + EHCI_USBLEGSUP, + &val); + if (((val & 0xff) == 1) && (val & EHCI_USBLEGSUP_BIOS)) { + /* + * Ok, BIOS is in smm mode, try to hand off... + */ + pci_read_config_dword(pdev, + hcc_params + EHCI_USBLEGCTLSTS, + &temp); + pci_write_config_dword(pdev, + hcc_params + EHCI_USBLEGCTLSTS, + temp | EHCI_USBLEGCTLSTS_SOOE); + val |= EHCI_USBLEGSUP_OS; + pci_write_config_dword(pdev, + hcc_params + EHCI_USBLEGSUP, + val); + + wait_time = 500; + do { + msleep(10); + wait_time -= 10; + pci_read_config_dword(pdev, + hcc_params + EHCI_USBLEGSUP, + &val); + } while (wait_time && (val & EHCI_USBLEGSUP_BIOS)); + if (!wait_time) { + /* + * well, possibly buggy BIOS... + */ + printk(KERN_WARNING "%s %s: early BIOS handoff " + "failed (BIOS bug ?)\n", + pdev->dev.bus_id, "EHCI"); + pci_write_config_dword(pdev, + hcc_params + EHCI_USBLEGSUP, + EHCI_USBLEGSUP_OS); + pci_write_config_dword(pdev, + hcc_params + EHCI_USBLEGCTLSTS, + 0); + } + } + } + + /* + * halt EHCI & disable its interrupts in any case + */ + val = readl(op_reg_base + EHCI_USBSTS); + if ((val & EHCI_USBSTS_HALTED) == 0) { + val = readl(op_reg_base + EHCI_USBCMD); + val &= ~EHCI_USBCMD_RUN; + writel(val, op_reg_base + EHCI_USBCMD); + + wait_time = 2000; + delta = 100; + do { + writel(0x3f, op_reg_base + EHCI_USBSTS); + udelay(delta); + wait_time -= delta; + val = readl(op_reg_base + EHCI_USBSTS); + if ((val == ~(u32)0) || (val & EHCI_USBSTS_HALTED)) { + break; + } + } while (wait_time > 0); + } + writel(0, op_reg_base + EHCI_USBINTR); + writel(0x3f, op_reg_base + EHCI_USBSTS); + + iounmap(base); + + return; +} + + + +static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev) +{ + if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI) + quirk_usb_handoff_uhci(pdev); + else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI) + quirk_usb_handoff_ohci(pdev); + else if (pdev->class == PCI_CLASS_SERIAL_USB_EHCI) + quirk_usb_disable_ehci(pdev); +} +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff); diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index d42a15d..5607c0a 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -54,6 +54,7 @@ #include <linux/interrupt.h> #include <linux/usb.h> #include <linux/usb_sl811.h> +#include <linux/platform_device.h> #include <asm/io.h> #include <asm/irq.h> @@ -818,7 +819,7 @@ static int sl811h_urb_enqueue( struct usb_hcd *hcd, struct usb_host_endpoint *hep, struct urb *urb, - unsigned mem_flags + gfp_t mem_flags ) { struct sl811 *sl811 = hcd_to_sl811(hcd); struct usb_device *udev = urb->dev; @@ -1363,7 +1364,7 @@ error: #ifdef CONFIG_PM static int -sl811h_hub_suspend(struct usb_hcd *hcd) +sl811h_bus_suspend(struct usb_hcd *hcd) { // SOFs off DBG("%s\n", __FUNCTION__); @@ -1371,7 +1372,7 @@ sl811h_hub_suspend(struct usb_hcd *hcd) } static int -sl811h_hub_resume(struct usb_hcd *hcd) +sl811h_bus_resume(struct usb_hcd *hcd) { // SOFs on DBG("%s\n", __FUNCTION__); @@ -1380,8 +1381,8 @@ sl811h_hub_resume(struct usb_hcd *hcd) #else -#define sl811h_hub_suspend NULL -#define sl811h_hub_resume NULL +#define sl811h_bus_suspend NULL +#define sl811h_bus_resume NULL #endif @@ -1623,8 +1624,8 @@ static struct hc_driver sl811h_hc_driver = { */ .hub_status_data = sl811h_hub_status_data, .hub_control = sl811h_hub_control, - .hub_suspend = sl811h_hub_suspend, - .hub_resume = sl811h_hub_resume, + .bus_suspend = sl811h_bus_suspend, + .bus_resume = sl811h_bus_resume, }; /*-------------------------------------------------------------------------*/ @@ -1784,17 +1785,14 @@ sl811h_probe(struct device *dev) */ static int -sl811h_suspend(struct device *dev, pm_message_t state, u32 phase) +sl811h_suspend(struct device *dev, pm_message_t state) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct sl811 *sl811 = hcd_to_sl811(hcd); int retval = 0; - if (phase != SUSPEND_POWER_DOWN) - return retval; - if (state.event == PM_EVENT_FREEZE) - retval = sl811h_hub_suspend(hcd); + retval = sl811h_bus_suspend(hcd); else if (state.event == PM_EVENT_SUSPEND) port_power(sl811, 0); if (retval == 0) @@ -1803,14 +1801,11 @@ sl811h_suspend(struct device *dev, pm_message_t state, u32 phase) } static int -sl811h_resume(struct device *dev, u32 phase) +sl811h_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct sl811 *sl811 = hcd_to_sl811(hcd); - if (phase != RESUME_POWER_ON) - return 0; - /* with no "check to see if VBUS is still powered" board hook, * let's assume it'd only be powered to enable remote wakeup. */ @@ -1822,7 +1817,7 @@ sl811h_resume(struct device *dev, u32 phase) } dev->power.power_state = PMSG_ON; - return sl811h_hub_resume(hcd); + return sl811h_bus_resume(hcd); } #else @@ -1837,6 +1832,7 @@ sl811h_resume(struct device *dev, u32 phase) struct device_driver sl811h_driver = { .name = (char *) hcd_name, .bus = &platform_bus_type, + .owner = THIS_MODULE, .probe = sl811h_probe, .remove = __devexit_p(sl811h_remove), diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index 38aebe3..e73faf8 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c @@ -19,6 +19,7 @@ #include <linux/string.h> #include <linux/timer.h> #include <linux/ioport.h> +#include <linux/platform_device.h> #include <pcmcia/cs_types.h> #include <pcmcia/cs.h> diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 4538a98..151154d 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -348,7 +348,6 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, char *bu if (urbp->urb->status != -EINPROGRESS) out += sprintf(out, "Status=%d ", urbp->urb->status); - //out += sprintf(out, "Inserttime=%lx ",urbp->inserttime); //out += sprintf(out, "FSBRtime=%lx ",urbp->fsbrtime); count = 0; @@ -446,11 +445,11 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) out += sprintf(out, "Frame List\n"); for (i = 0; i < UHCI_NUMFRAMES; ++i) { int shown = 0; - td = uhci->fl->frame_cpu[i]; + td = uhci->frame_cpu[i]; if (!td) continue; - if (td->dma_handle != (dma_addr_t)uhci->fl->frame[i]) { + if (td->dma_handle != (dma_addr_t)uhci->frame[i]) { show_frame_num(); out += sprintf(out, " frame list does not match td->dma_handle!\n"); } diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 0c02489..15e0a51 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -101,37 +101,16 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci); #include "uhci-q.c" #include "uhci-hub.c" +extern void uhci_reset_hc(struct pci_dev *pdev, unsigned long base); +extern int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base); + /* - * Make sure the controller is completely inactive, unable to - * generate interrupts or do DMA. + * Finish up a host controller reset and update the recorded state. */ -static void reset_hc(struct uhci_hcd *uhci) +static void finish_reset(struct uhci_hcd *uhci) { int port; - /* Turn off PIRQ enable and SMI enable. (This also turns off the - * BIOS's USB Legacy Support.) Turn off all the R/WC bits too. - */ - pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, - USBLEGSUP_RWC); - - /* Reset the HC - this will force us to get a - * new notification of any already connected - * ports due to the virtual disconnect that it - * implies. - */ - outw(USBCMD_HCRESET, uhci->io_addr + USBCMD); - mb(); - udelay(5); - if (inw(uhci->io_addr + USBCMD) & USBCMD_HCRESET) - dev_warn(uhci_dev(uhci), "HCRESET not completed yet!\n"); - - /* Just to be safe, disable interrupt requests and - * make sure the controller is stopped. - */ - outw(0, uhci->io_addr + USBINTR); - outw(0, uhci->io_addr + USBCMD); - /* HCRESET doesn't affect the Suspend, Reset, and Resume Detect * bits in the port status and control registers. * We have to clear them by hand. @@ -153,7 +132,8 @@ static void reset_hc(struct uhci_hcd *uhci) */ static void hc_died(struct uhci_hcd *uhci) { - reset_hc(uhci); + uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr); + finish_reset(uhci); uhci->hc_inaccessible = 1; } @@ -163,44 +143,8 @@ static void hc_died(struct uhci_hcd *uhci) */ static void check_and_reset_hc(struct uhci_hcd *uhci) { - u16 legsup; - unsigned int cmd, intr; - - /* - * When restarting a suspended controller, we expect all the - * settings to be the same as we left them: - * - * PIRQ and SMI disabled, no R/W bits set in USBLEGSUP; - * Controller is stopped and configured with EGSM set; - * No interrupts enabled except possibly Resume Detect. - * - * If any of these conditions are violated we do a complete reset. - */ - pci_read_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, &legsup); - if (legsup & ~(USBLEGSUP_RO | USBLEGSUP_RWC)) { - dev_dbg(uhci_dev(uhci), "%s: legsup = 0x%04x\n", - __FUNCTION__, legsup); - goto reset_needed; - } - - cmd = inw(uhci->io_addr + USBCMD); - if ((cmd & USBCMD_RS) || !(cmd & USBCMD_CF) || !(cmd & USBCMD_EGSM)) { - dev_dbg(uhci_dev(uhci), "%s: cmd = 0x%04x\n", - __FUNCTION__, cmd); - goto reset_needed; - } - - intr = inw(uhci->io_addr + USBINTR); - if (intr & (~USBINTR_RESUME)) { - dev_dbg(uhci_dev(uhci), "%s: intr = 0x%04x\n", - __FUNCTION__, intr); - goto reset_needed; - } - return; - -reset_needed: - dev_dbg(uhci_dev(uhci), "Performing full reset\n"); - reset_hc(uhci); + if (uhci_check_and_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr)) + finish_reset(uhci); } /* @@ -212,13 +156,13 @@ static void configure_hc(struct uhci_hcd *uhci) outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF); /* Store the frame list base address */ - outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD); + outl(uhci->frame_dma_handle, uhci->io_addr + USBFLBASEADD); /* Set the current frame number */ outw(uhci->frame_number, uhci->io_addr + USBFRNUM); - /* Mark controller as running before we enable interrupts */ - uhci_to_hcd(uhci)->state = HC_STATE_RUNNING; + /* Mark controller as not halted before we enable interrupts */ + uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED; mb(); /* Enable PIRQ */ @@ -319,6 +263,7 @@ __acquires(uhci->lock) static void start_rh(struct uhci_hcd *uhci) { + uhci_to_hcd(uhci)->state = HC_STATE_RUNNING; uhci->is_stopped = 0; smp_wmb(); @@ -437,36 +382,21 @@ static void release_uhci(struct uhci_hcd *uhci) int i; for (i = 0; i < UHCI_NUM_SKELQH; i++) - if (uhci->skelqh[i]) { - uhci_free_qh(uhci, uhci->skelqh[i]); - uhci->skelqh[i] = NULL; - } + uhci_free_qh(uhci, uhci->skelqh[i]); - if (uhci->term_td) { - uhci_free_td(uhci, uhci->term_td); - uhci->term_td = NULL; - } + uhci_free_td(uhci, uhci->term_td); - if (uhci->qh_pool) { - dma_pool_destroy(uhci->qh_pool); - uhci->qh_pool = NULL; - } + dma_pool_destroy(uhci->qh_pool); - if (uhci->td_pool) { - dma_pool_destroy(uhci->td_pool); - uhci->td_pool = NULL; - } + dma_pool_destroy(uhci->td_pool); - if (uhci->fl) { - dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl), - uhci->fl, uhci->fl->dma_handle); - uhci->fl = NULL; - } + kfree(uhci->frame_cpu); - if (uhci->dentry) { - debugfs_remove(uhci->dentry); - uhci->dentry = NULL; - } + dma_free_coherent(uhci_dev(uhci), + UHCI_NUMFRAMES * sizeof(*uhci->frame), + uhci->frame, uhci->frame_dma_handle); + + debugfs_remove(uhci->dentry); } static int uhci_reset(struct usb_hcd *hcd) @@ -545,7 +475,6 @@ static int uhci_start(struct usb_hcd *hcd) struct uhci_hcd *uhci = hcd_to_uhci(hcd); int retval = -EBUSY; int i; - dma_addr_t dma_handle; struct dentry *dentry; hcd->uses_new_polling = 1; @@ -579,17 +508,23 @@ static int uhci_start(struct usb_hcd *hcd) init_waitqueue_head(&uhci->waitqh); - uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl), - &dma_handle, 0); - if (!uhci->fl) { + uhci->frame = dma_alloc_coherent(uhci_dev(uhci), + UHCI_NUMFRAMES * sizeof(*uhci->frame), + &uhci->frame_dma_handle, 0); + if (!uhci->frame) { dev_err(uhci_dev(uhci), "unable to allocate " "consistent memory for frame list\n"); - goto err_alloc_fl; + goto err_alloc_frame; } + memset(uhci->frame, 0, UHCI_NUMFRAMES * sizeof(*uhci->frame)); - memset((void *)uhci->fl, 0, sizeof(*uhci->fl)); - - uhci->fl->dma_handle = dma_handle; + uhci->frame_cpu = kcalloc(UHCI_NUMFRAMES, sizeof(*uhci->frame_cpu), + GFP_KERNEL); + if (!uhci->frame_cpu) { + dev_err(uhci_dev(uhci), "unable to allocate " + "memory for frame pointers\n"); + goto err_alloc_frame_cpu; + } uhci->td_pool = dma_pool_create("uhci_td", uhci_dev(uhci), sizeof(struct uhci_td), 16, 0); @@ -672,7 +607,7 @@ static int uhci_start(struct usb_hcd *hcd) irq = 7; /* Only place we don't use the frame list routines */ - uhci->fl->frame[i] = UHCI_PTR_QH | + uhci->frame[i] = UHCI_PTR_QH | cpu_to_le32(uhci->skelqh[irq]->dma_handle); } @@ -690,31 +625,29 @@ static int uhci_start(struct usb_hcd *hcd) * error exits: */ err_alloc_skelqh: - for (i = 0; i < UHCI_NUM_SKELQH; i++) - if (uhci->skelqh[i]) { + for (i = 0; i < UHCI_NUM_SKELQH; i++) { + if (uhci->skelqh[i]) uhci_free_qh(uhci, uhci->skelqh[i]); - uhci->skelqh[i] = NULL; - } + } uhci_free_td(uhci, uhci->term_td); - uhci->term_td = NULL; err_alloc_term_td: dma_pool_destroy(uhci->qh_pool); - uhci->qh_pool = NULL; err_create_qh_pool: dma_pool_destroy(uhci->td_pool); - uhci->td_pool = NULL; err_create_td_pool: - dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl), - uhci->fl, uhci->fl->dma_handle); - uhci->fl = NULL; + kfree(uhci->frame_cpu); + +err_alloc_frame_cpu: + dma_free_coherent(uhci_dev(uhci), + UHCI_NUMFRAMES * sizeof(*uhci->frame), + uhci->frame, uhci->frame_dma_handle); -err_alloc_fl: +err_alloc_frame: debugfs_remove(uhci->dentry); - uhci->dentry = NULL; err_create_debug_entry: return retval; @@ -726,7 +659,7 @@ static void uhci_stop(struct usb_hcd *hcd) spin_lock_irq(&uhci->lock); if (!uhci->hc_inaccessible) - reset_hc(uhci); + hc_died(uhci); uhci_scan_schedule(uhci, NULL); spin_unlock_irq(&uhci->lock); @@ -774,14 +707,8 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) if (uhci->hc_inaccessible) /* Dead or already suspended */ goto done; -#ifndef CONFIG_USB_SUSPEND - /* Otherwise this would never happen */ - suspend_rh(uhci, UHCI_RH_SUSPENDED); -#endif - if (uhci->rh_state > UHCI_RH_SUSPENDED) { dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n"); - hcd->state = HC_STATE_RUNNING; rc = -EBUSY; goto done; }; @@ -820,10 +747,6 @@ static int uhci_resume(struct usb_hcd *hcd) check_and_reset_hc(uhci); configure_hc(uhci); -#ifndef CONFIG_USB_SUSPEND - /* Otherwise this would never happen */ - wakeup_rh(uhci); -#endif if (uhci->rh_state == UHCI_RH_RESET) suspend_rh(uhci, UHCI_RH_SUSPENDED); @@ -881,8 +804,8 @@ static const struct hc_driver uhci_driver = { #ifdef CONFIG_PM .suspend = uhci_suspend, .resume = uhci_resume, - .hub_suspend = uhci_rh_suspend, - .hub_resume = uhci_rh_resume, + .bus_suspend = uhci_rh_suspend, + .bus_resume = uhci_rh_resume, #endif .stop = uhci_stop, @@ -908,6 +831,7 @@ MODULE_DEVICE_TABLE(pci, uhci_pci_ids); static struct pci_driver uhci_pci_driver = { .name = (char *)hcd_name, .id_table = uhci_pci_ids, + .owner = THIS_MODULE, .probe = usb_hcd_pci_probe, .remove = usb_hcd_pci_remove, diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 282f40b..e576db5 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -7,6 +7,7 @@ #define usb_packetid(pipe) (usb_pipein(pipe) ? USB_PID_IN : USB_PID_OUT) #define PIPE_DEVEP_MASK 0x0007ff00 + /* * Universal Host Controller Interface data structures and defines */ @@ -82,15 +83,10 @@ #define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ #define CAN_SCHEDULE_FRAMES 1000 /* how far future frames can be scheduled */ -struct uhci_frame_list { - __le32 frame[UHCI_NUMFRAMES]; - - void *frame_cpu[UHCI_NUMFRAMES]; - - dma_addr_t dma_handle; -}; -struct urb_priv; +/* + * Queue Headers + */ /* * One role of a QH is to hold a queue of TDs for some endpoint. Each QH is @@ -116,13 +112,13 @@ struct uhci_qh { struct urb_priv *urbp; - struct list_head list; /* P: uhci->frame_list_lock */ - struct list_head remove_list; /* P: uhci->remove_list_lock */ + struct list_head list; + struct list_head remove_list; } __attribute__((aligned(16))); /* * We need a special accessor for the element pointer because it is - * subject to asynchronous updates by the controller + * subject to asynchronous updates by the controller. */ static __le32 inline qh_element(struct uhci_qh *qh) { __le32 element = qh->element; @@ -131,6 +127,11 @@ static __le32 inline qh_element(struct uhci_qh *qh) { return element; } + +/* + * Transfer Descriptors + */ + /* * for TD <status>: */ @@ -183,17 +184,10 @@ static __le32 inline qh_element(struct uhci_qh *qh) { * * That's silly, the hardware doesn't care. The hardware only cares that * the hardware words are 16-byte aligned, and we can have any amount of - * sw space after the TD entry as far as I can tell. - * - * But let's just go with the documentation, at least for 32-bit machines. - * On 64-bit machines we probably want to take advantage of the fact that - * hw doesn't really care about the size of the sw-only area. - * - * Alas, not anymore, we have more than 4 words for software, woops. - * Everything still works tho, surprise! -jerdfelt + * sw space after the TD entry. * * td->link points to either another TD (not necessarily for the same urb or - * even the same endpoint), or nothing (PTR_TERM), or a QH (for queued urbs) + * even the same endpoint), or nothing (PTR_TERM), or a QH (for queued urbs). */ struct uhci_td { /* Hardware fields */ @@ -205,18 +199,16 @@ struct uhci_td { /* Software fields */ dma_addr_t dma_handle; - struct urb *urb; - - struct list_head list; /* P: urb->lock */ - struct list_head remove_list; /* P: uhci->td_remove_list_lock */ + struct list_head list; + struct list_head remove_list; int frame; /* for iso: what frame? */ - struct list_head fl_list; /* P: uhci->frame_list_lock */ + struct list_head fl_list; } __attribute__((aligned(16))); /* * We need a special accessor for the control/status word because it is - * subject to asynchronous updates by the controller + * subject to asynchronous updates by the controller. */ static u32 inline td_status(struct uhci_td *td) { __le32 status = td->status; @@ -227,6 +219,10 @@ static u32 inline td_status(struct uhci_td *td) { /* + * Skeleton Queue Headers + */ + +/* * The UHCI driver places Interrupt, Control and Bulk into QH's both * to group together TD's for one transfer, and also to faciliate queuing * of URB's. To make it easy to insert entries into the schedule, we have @@ -256,15 +252,15 @@ static u32 inline td_status(struct uhci_td *td) { * * The terminating QH is used for 2 reasons: * - To place a terminating TD which is used to workaround a PIIX bug - * (see Intel errata for explanation) + * (see Intel errata for explanation), and * - To loop back to the full-speed control queue for full-speed bandwidth - * reclamation + * reclamation. * * Isochronous transfers are stored before the start of the skeleton * schedule and don't use QH's. While the UHCI spec doesn't forbid the - * use of QH's for Isochronous, it doesn't use them either. Since we don't - * need to use them either, we follow the spec diagrams in hope that it'll - * be more compatible with future UHCI implementations. + * use of QH's for Isochronous, it doesn't use them either. And the spec + * says that queues never advance on an error completion status, which + * makes them totally unsuitable for Isochronous transfers. */ #define UHCI_NUM_SKELQH 12 @@ -314,8 +310,13 @@ static inline int __interval_to_skel(int interval) return 0; /* int128 for 128-255 ms (Max.) */ } + +/* + * The UHCI controller and root hub + */ + /* - * States for the root hub. + * States for the root hub: * * To prevent "bouncing" in the presence of electrical noise, * when there are no devices attached we delay for 1 second in the @@ -326,7 +327,7 @@ static inline int __interval_to_skel(int interval) */ enum uhci_rh_state { /* In the following states the HC must be halted. - * These two must come first */ + * These two must come first. */ UHCI_RH_RESET, UHCI_RH_SUSPENDED, @@ -338,13 +339,13 @@ enum uhci_rh_state { UHCI_RH_SUSPENDING, /* In the following states it's an error if the HC is halted. - * These two must come last */ + * These two must come last. */ UHCI_RH_RUNNING, /* The normal state */ UHCI_RH_RUNNING_NODEVS, /* Running with no devices attached */ }; /* - * This describes the full uhci information. + * The full UHCI controller information: */ struct uhci_hcd { @@ -361,7 +362,11 @@ struct uhci_hcd { struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */ spinlock_t lock; - struct uhci_frame_list *fl; /* P: uhci->lock */ + + dma_addr_t frame_dma_handle; /* Hardware frame list */ + __le32 *frame; + void **frame_cpu; /* CPU's frame list */ + int fsbr; /* Full-speed bandwidth reclamation */ unsigned long fsbrtimeout; /* FSBR delay */ @@ -385,22 +390,22 @@ struct uhci_hcd { unsigned long ports_timeout; /* Time to stop signalling */ /* Main list of URB's currently controlled by this HC */ - struct list_head urb_list; /* P: uhci->lock */ + struct list_head urb_list; /* List of QH's that are done, but waiting to be unlinked (race) */ - struct list_head qh_remove_list; /* P: uhci->lock */ + struct list_head qh_remove_list; unsigned int qh_remove_age; /* Age in frames */ /* List of TD's that are done, but waiting to be freed (race) */ - struct list_head td_remove_list; /* P: uhci->lock */ + struct list_head td_remove_list; unsigned int td_remove_age; /* Age in frames */ /* List of asynchronously unlinked URB's */ - struct list_head urb_remove_list; /* P: uhci->lock */ + struct list_head urb_remove_list; unsigned int urb_remove_age; /* Age in frames */ /* List of URB's awaiting completion callback */ - struct list_head complete_list; /* P: uhci->lock */ + struct list_head complete_list; int rh_numports; /* Number of root-hub ports */ @@ -419,13 +424,17 @@ static inline struct usb_hcd *uhci_to_hcd(struct uhci_hcd *uhci) #define uhci_dev(u) (uhci_to_hcd(u)->self.controller) + +/* + * Private per-URB data + */ struct urb_priv { struct list_head urb_list; struct urb *urb; struct uhci_qh *qh; /* QH for this URB */ - struct list_head td_list; /* P: urb->lock */ + struct list_head td_list; unsigned fsbr : 1; /* URB turned on FSBR */ unsigned fsbr_timeout : 1; /* URB timed out on FSBR */ @@ -434,12 +443,12 @@ struct urb_priv { /* a control transfer, retrigger */ /* the status phase */ - unsigned long inserttime; /* In jiffies */ unsigned long fsbrtime; /* In jiffies */ - struct list_head queue_list; /* P: uhci->frame_list_lock */ + struct list_head queue_list; }; + /* * Locking in uhci.c * @@ -459,6 +468,5 @@ struct urb_priv { #define PCI_VENDOR_ID_GENESYS 0x17a0 #define PCI_DEVICE_ID_GL880S_UHCI 0x8083 -#define PCI_DEVICE_ID_GL880S_EHCI 0x8084 #endif diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index ea0d168..7e46887 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -89,10 +89,10 @@ static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td, td->frame = framenum; /* Is there a TD already mapped there? */ - if (uhci->fl->frame_cpu[framenum]) { + if (uhci->frame_cpu[framenum]) { struct uhci_td *ftd, *ltd; - ftd = uhci->fl->frame_cpu[framenum]; + ftd = uhci->frame_cpu[framenum]; ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list); list_add_tail(&td->fl_list, &ftd->fl_list); @@ -101,29 +101,32 @@ static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td, wmb(); ltd->link = cpu_to_le32(td->dma_handle); } else { - td->link = uhci->fl->frame[framenum]; + td->link = uhci->frame[framenum]; wmb(); - uhci->fl->frame[framenum] = cpu_to_le32(td->dma_handle); - uhci->fl->frame_cpu[framenum] = td; + uhci->frame[framenum] = cpu_to_le32(td->dma_handle); + uhci->frame_cpu[framenum] = td; } } -static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td) +static inline void uhci_remove_td_frame_list(struct uhci_hcd *uhci, + struct uhci_td *td) { /* If it's not inserted, don't remove it */ - if (td->frame == -1 && list_empty(&td->fl_list)) + if (td->frame == -1) { + WARN_ON(!list_empty(&td->fl_list)); return; + } - if (td->frame != -1 && uhci->fl->frame_cpu[td->frame] == td) { + if (uhci->frame_cpu[td->frame] == td) { if (list_empty(&td->fl_list)) { - uhci->fl->frame[td->frame] = td->link; - uhci->fl->frame_cpu[td->frame] = NULL; + uhci->frame[td->frame] = td->link; + uhci->frame_cpu[td->frame] = NULL; } else { struct uhci_td *ntd; ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list); - uhci->fl->frame[td->frame] = cpu_to_le32(ntd->dma_handle); - uhci->fl->frame_cpu[td->frame] = ntd; + uhci->frame[td->frame] = cpu_to_le32(ntd->dma_handle); + uhci->frame_cpu[td->frame] = ntd; } } else { struct uhci_td *ptd; @@ -132,13 +135,20 @@ static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td) ptd->link = td->link; } - wmb(); - td->link = UHCI_PTR_TERM; - list_del_init(&td->fl_list); td->frame = -1; } +static void unlink_isochronous_tds(struct uhci_hcd *uhci, struct urb *urb) +{ + struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; + struct uhci_td *td; + + list_for_each_entry(td, &urbp->td_list, list) + uhci_remove_td_frame_list(uhci, td); + wmb(); +} + /* * Inserts a td list into qh. */ @@ -443,7 +453,6 @@ static struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *u memset((void *)urbp, 0, sizeof(*urbp)); - urbp->inserttime = jiffies; urbp->fsbrtime = jiffies; urbp->urb = urb; @@ -462,8 +471,6 @@ static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td) { struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - td->urb = urb; - list_add_tail(&td->list, &urbp->td_list); } @@ -473,8 +480,6 @@ static void uhci_remove_td_from_urb(struct uhci_td *td) return; list_del_init(&td->list); - - td->urb = NULL; } static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb) @@ -503,7 +508,6 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb) list_for_each_entry_safe(td, tmp, &urbp->td_list, list) { uhci_remove_td_from_urb(td); - uhci_remove_td(uhci, td); list_add(&td->remove_list, &uhci->td_remove_list); } @@ -1073,6 +1077,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb) struct uhci_td *td; int i, ret, frame; int status, destination; + struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; status = TD_CTRL_ACTIVE | TD_CTRL_IOS; destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); @@ -1081,11 +1086,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb) if (ret) return ret; - frame = urb->start_frame; - for (i = 0; i < urb->number_of_packets; i++, frame += urb->interval) { - if (!urb->iso_frame_desc[i].length) - continue; - + for (i = 0; i < urb->number_of_packets; i++) { td = uhci_alloc_td(uhci); if (!td) return -ENOMEM; @@ -1096,8 +1097,12 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb) if (i + 1 >= urb->number_of_packets) td->status |= cpu_to_le32(TD_CTRL_IOC); + } + frame = urb->start_frame; + list_for_each_entry(td, &urbp->td_list, list) { uhci_insert_td_frame_list(uhci, td, frame); + frame += urb->interval; } return -EINPROGRESS; @@ -1110,7 +1115,7 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb) int status; int i, ret = 0; - urb->actual_length = 0; + urb->actual_length = urb->error_count = 0; i = 0; list_for_each_entry(td, &urbp->td_list, list) { @@ -1134,6 +1139,7 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb) i++; } + unlink_isochronous_tds(uhci, urb); return ret; } @@ -1164,7 +1170,7 @@ static struct urb *uhci_find_urb_ep(struct uhci_hcd *uhci, struct urb *urb) static int uhci_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *ep, - struct urb *urb, unsigned mem_flags) + struct urb *urb, gfp_t mem_flags) { int ret; struct uhci_hcd *uhci = hcd_to_uhci(hcd); @@ -1366,6 +1372,8 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) goto done; list_del_init(&urbp->urb_list); + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) + unlink_isochronous_tds(uhci, urb); uhci_unlink_generic(uhci, urb); uhci_get_current_frame_number(uhci); diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c index a330a4b..1d973bc 100644 --- a/drivers/usb/image/mdc800.c +++ b/drivers/usb/image/mdc800.c @@ -425,9 +425,8 @@ static void mdc800_usb_download_notify (struct urb *urb, struct pt_regs *res) static struct usb_driver mdc800_usb_driver; static struct file_operations mdc800_device_ops; static struct usb_class_driver mdc800_class = { - .name = "usb/mdc800%d", + .name = "mdc800%d", .fops = &mdc800_device_ops, - .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, .minor_base = MDC800_DEVICE_MINOR_BASE, }; @@ -976,13 +975,13 @@ static struct usb_driver mdc800_usb_driver = Init and Cleanup this driver (Main Functions) *************************************************************************/ -#define try(A) if (!(A)) goto cleanup_on_fail; - static int __init usb_mdc800_init (void) { int retval = -ENODEV; /* Allocate Memory */ - try (mdc800=kmalloc (sizeof (struct mdc800_data), GFP_KERNEL)); + mdc800=kmalloc (sizeof (struct mdc800_data), GFP_KERNEL); + if (!mdc800) + goto cleanup_on_fail; memset(mdc800, 0, sizeof(struct mdc800_data)); mdc800->dev = NULL; @@ -998,13 +997,25 @@ static int __init usb_mdc800_init (void) mdc800->downloaded = 0; mdc800->written = 0; - try (mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL)); - try (mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL)); - try (mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL)); + mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL); + if (!mdc800->irq_urb_buffer) + goto cleanup_on_fail; + mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL); + if (!mdc800->write_urb_buffer) + goto cleanup_on_fail; + mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL); + if (!mdc800->download_urb_buffer) + goto cleanup_on_fail; - try (mdc800->irq_urb=usb_alloc_urb (0, GFP_KERNEL)); - try (mdc800->download_urb=usb_alloc_urb (0, GFP_KERNEL)); - try (mdc800->write_urb=usb_alloc_urb (0, GFP_KERNEL)); + mdc800->irq_urb=usb_alloc_urb (0, GFP_KERNEL); + if (!mdc800->irq_urb) + goto cleanup_on_fail; + mdc800->download_urb=usb_alloc_urb (0, GFP_KERNEL); + if (!mdc800->download_urb) + goto cleanup_on_fail; + mdc800->write_urb=usb_alloc_urb (0, GFP_KERNEL); + if (!mdc800->write_urb) + goto cleanup_on_fail; /* Register the driver */ retval = usb_register(&mdc800_usb_driver); diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c index c84e148..c89d076 100644 --- a/drivers/usb/image/microtek.c +++ b/drivers/usb/image/microtek.c @@ -773,11 +773,10 @@ static int mts_usb_probe(struct usb_interface *intf, } - new_desc = kmalloc(sizeof(struct mts_desc), GFP_KERNEL); + new_desc = kzalloc(sizeof(struct mts_desc), GFP_KERNEL); if (!new_desc) goto out; - memset(new_desc, 0, sizeof(*new_desc)); new_desc->urb = usb_alloc_urb(0, GFP_KERNEL); if (!new_desc->urb) goto out_kfree; diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c index 74f8760..a32558b 100644 --- a/drivers/usb/input/acecad.c +++ b/drivers/usb/input/acecad.c @@ -53,7 +53,7 @@ struct usb_acecad { char name[128]; char phys[64]; struct usb_device *usbdev; - struct input_dev dev; + struct input_dev *input; struct urb *irq; signed char *data; @@ -64,7 +64,7 @@ static void usb_acecad_irq(struct urb *urb, struct pt_regs *regs) { struct usb_acecad *acecad = urb->context; unsigned char *data = acecad->data; - struct input_dev *dev = &acecad->dev; + struct input_dev *dev = acecad->input; int prox, status; switch (urb->status) { @@ -135,8 +135,8 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ struct usb_host_interface *interface = intf->cur_altsetting; struct usb_endpoint_descriptor *endpoint; struct usb_acecad *acecad; + struct input_dev *input_dev; int pipe, maxp; - char path[64]; if (interface->desc.bNumEndpoints != 1) return -ENODEV; @@ -153,8 +153,9 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); acecad = kzalloc(sizeof(struct usb_acecad), GFP_KERNEL); - if (!acecad) - return -ENOMEM; + input_dev = input_allocate_device(); + if (!acecad || !input_dev) + goto fail1; acecad->data = usb_buffer_alloc(dev, 8, SLAB_KERNEL, &acecad->data_dma); if (!acecad->data) @@ -164,6 +165,9 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ if (!acecad->irq) goto fail2; + acecad->usbdev = dev; + acecad->input = input_dev; + if (dev->manufacturer) strlcpy(acecad->name, dev->manufacturer, sizeof(acecad->name)); @@ -173,48 +177,48 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ strlcat(acecad->name, dev->product, sizeof(acecad->name)); } - usb_make_path(dev, path, sizeof(path)); - snprintf(acecad->phys, sizeof(acecad->phys), "%s/input0", path); + usb_make_path(dev, acecad->phys, sizeof(acecad->phys)); + strlcat(acecad->phys, "/input0", sizeof(acecad->phys)); - acecad->usbdev = dev; + input_dev->name = acecad->name; + input_dev->phys = acecad->phys; + usb_to_input_id(dev, &input_dev->id); + input_dev->cdev.dev = &intf->dev; + input_dev->private = acecad; - acecad->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - acecad->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); - acecad->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); - acecad->dev.keybit[LONG(BTN_DIGI)] = BIT(BTN_TOOL_PEN) |BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2); + input_dev->open = usb_acecad_open; + input_dev->close = usb_acecad_close; + + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); + input_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); + input_dev->keybit[LONG(BTN_DIGI)] = BIT(BTN_TOOL_PEN) |BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2); switch (id->driver_info) { case 0: - acecad->dev.absmax[ABS_X] = 5000; - acecad->dev.absmax[ABS_Y] = 3750; - acecad->dev.absmax[ABS_PRESSURE] = 512; + input_dev->absmax[ABS_X] = 5000; + input_dev->absmax[ABS_Y] = 3750; + input_dev->absmax[ABS_PRESSURE] = 512; if (!strlen(acecad->name)) snprintf(acecad->name, sizeof(acecad->name), "USB Acecad Flair Tablet %04x:%04x", - dev->descriptor.idVendor, dev->descriptor.idProduct); + le16_to_cpu(dev->descriptor.idVendor), + le16_to_cpu(dev->descriptor.idProduct)); break; case 1: - acecad->dev.absmax[ABS_X] = 3000; - acecad->dev.absmax[ABS_Y] = 2250; - acecad->dev.absmax[ABS_PRESSURE] = 1024; + input_dev->absmax[ABS_X] = 3000; + input_dev->absmax[ABS_Y] = 2250; + input_dev->absmax[ABS_PRESSURE] = 1024; if (!strlen(acecad->name)) snprintf(acecad->name, sizeof(acecad->name), "USB Acecad 302 Tablet %04x:%04x", - dev->descriptor.idVendor, dev->descriptor.idProduct); + le16_to_cpu(dev->descriptor.idVendor), + le16_to_cpu(dev->descriptor.idProduct)); break; } - acecad->dev.absfuzz[ABS_X] = 4; - acecad->dev.absfuzz[ABS_Y] = 4; - - acecad->dev.private = acecad; - acecad->dev.open = usb_acecad_open; - acecad->dev.close = usb_acecad_close; - - acecad->dev.name = acecad->name; - acecad->dev.phys = acecad->phys; - usb_to_input_id(dev, &acecad->dev.id); - acecad->dev.dev = &intf->dev; + input_dev->absfuzz[ABS_X] = 4; + input_dev->absfuzz[ABS_Y] = 4; usb_fill_int_urb(acecad->irq, dev, pipe, acecad->data, maxp > 8 ? 8 : maxp, @@ -222,17 +226,15 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ acecad->irq->transfer_dma = acecad->data_dma; acecad->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - input_register_device(&acecad->dev); - - printk(KERN_INFO "input: %s with packet size %d on %s\n", - acecad->name, maxp, path); + input_register_device(acecad->input); usb_set_intfdata(intf, acecad); return 0; fail2: usb_buffer_free(dev, 8, acecad->data, acecad->data_dma); - fail1: kfree(acecad); + fail1: input_free_device(input_dev); + kfree(acecad); return -ENOMEM; } @@ -243,7 +245,7 @@ static void usb_acecad_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); if (acecad) { usb_kill_urb(acecad->irq); - input_unregister_device(&acecad->dev); + input_unregister_device(acecad->input); usb_free_urb(acecad->irq); usb_buffer_free(interface_to_usbdev(intf), 10, acecad->data, acecad->data_dma); kfree(acecad); diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c index cd0cbfe..1c3b472 100644 --- a/drivers/usb/input/aiptek.c +++ b/drivers/usb/input/aiptek.c @@ -317,7 +317,7 @@ struct aiptek_settings { }; struct aiptek { - struct input_dev inputdev; /* input device struct */ + struct input_dev *inputdev; /* input device struct */ struct usb_device *usbdev; /* usb device struct */ struct urb *urb; /* urb for incoming reports */ dma_addr_t data_dma; /* our dma stuffage */ @@ -402,7 +402,7 @@ static void aiptek_irq(struct urb *urb, struct pt_regs *regs) { struct aiptek *aiptek = urb->context; unsigned char *data = aiptek->data; - struct input_dev *inputdev = &aiptek->inputdev; + struct input_dev *inputdev = aiptek->inputdev; int jitterable = 0; int retval, macro, x, y, z, left, right, middle, p, dv, tip, bs, pck; @@ -955,20 +955,20 @@ static int aiptek_program_tablet(struct aiptek *aiptek) /* Query getXextension */ if ((ret = aiptek_query(aiptek, 0x01, 0x00)) < 0) return ret; - aiptek->inputdev.absmin[ABS_X] = 0; - aiptek->inputdev.absmax[ABS_X] = ret - 1; + aiptek->inputdev->absmin[ABS_X] = 0; + aiptek->inputdev->absmax[ABS_X] = ret - 1; /* Query getYextension */ if ((ret = aiptek_query(aiptek, 0x01, 0x01)) < 0) return ret; - aiptek->inputdev.absmin[ABS_Y] = 0; - aiptek->inputdev.absmax[ABS_Y] = ret - 1; + aiptek->inputdev->absmin[ABS_Y] = 0; + aiptek->inputdev->absmax[ABS_Y] = ret - 1; /* Query getPressureLevels */ if ((ret = aiptek_query(aiptek, 0x08, 0x00)) < 0) return ret; - aiptek->inputdev.absmin[ABS_PRESSURE] = 0; - aiptek->inputdev.absmax[ABS_PRESSURE] = ret - 1; + aiptek->inputdev->absmin[ABS_PRESSURE] = 0; + aiptek->inputdev->absmax[ABS_PRESSURE] = ret - 1; /* Depending on whether we are in absolute or relative mode, we will * do a switchToTablet(absolute) or switchToMouse(relative) command. @@ -1025,8 +1025,8 @@ static ssize_t show_tabletSize(struct device *dev, struct device_attribute *attr return 0; return snprintf(buf, PAGE_SIZE, "%dx%d\n", - aiptek->inputdev.absmax[ABS_X] + 1, - aiptek->inputdev.absmax[ABS_Y] + 1); + aiptek->inputdev->absmax[ABS_X] + 1, + aiptek->inputdev->absmax[ABS_Y] + 1); } /* These structs define the sysfs files, param #1 is the name of the @@ -1048,7 +1048,7 @@ static ssize_t show_tabletProductId(struct device *dev, struct device_attribute return 0; return snprintf(buf, PAGE_SIZE, "0x%04x\n", - aiptek->inputdev.id.product); + aiptek->inputdev->id.product); } static DEVICE_ATTR(product_id, S_IRUGO, show_tabletProductId, NULL); @@ -1063,7 +1063,7 @@ static ssize_t show_tabletVendorId(struct device *dev, struct device_attribute * if (aiptek == NULL) return 0; - return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->inputdev.id.vendor); + return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->inputdev->id.vendor); } static DEVICE_ATTR(vendor_id, S_IRUGO, show_tabletVendorId, NULL); @@ -1977,7 +1977,6 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) struct input_dev *inputdev; struct input_handle *inputhandle; struct list_head *node, *next; - char path[64 + 1]; int i; int speeds[] = { 0, AIPTEK_PROGRAMMABLE_DELAY_50, @@ -1996,24 +1995,26 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) */ speeds[0] = programmableDelay; - if ((aiptek = kmalloc(sizeof(struct aiptek), GFP_KERNEL)) == NULL) - return -ENOMEM; - memset(aiptek, 0, sizeof(struct aiptek)); + aiptek = kzalloc(sizeof(struct aiptek), GFP_KERNEL); + inputdev = input_allocate_device(); + if (!aiptek || !inputdev) + goto fail1; aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH, SLAB_ATOMIC, &aiptek->data_dma); - if (aiptek->data == NULL) { - kfree(aiptek); - return -ENOMEM; - } + if (!aiptek->data) + goto fail1; aiptek->urb = usb_alloc_urb(0, GFP_KERNEL); - if (aiptek->urb == NULL) { - usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data, - aiptek->data_dma); - kfree(aiptek); - return -ENOMEM; - } + if (!aiptek->urb) + goto fail2; + + aiptek->inputdev = inputdev; + aiptek->usbdev = usbdev; + aiptek->ifnum = intf->altsetting[0].desc.bInterfaceNumber; + aiptek->inDelay = 0; + aiptek->endDelay = 0; + aiptek->previousJitterable = 0; /* Set up the curSettings struct. Said struct contains the current * programmable parameters. The newSetting struct contains changes @@ -2036,31 +2037,48 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) /* Both structs should have equivalent settings */ - memcpy(&aiptek->newSetting, &aiptek->curSetting, - sizeof(struct aiptek_settings)); + aiptek->newSetting = aiptek->curSetting; + + /* Determine the usb devices' physical path. + * Asketh not why we always pretend we're using "../input0", + * but I suspect this will have to be refactored one + * day if a single USB device can be a keyboard & a mouse + * & a tablet, and the inputX number actually will tell + * us something... + */ + usb_make_path(usbdev, aiptek->features.usbPath, + sizeof(aiptek->features.usbPath)); + strlcat(aiptek->features.usbPath, "/input0", + sizeof(aiptek->features.usbPath)); + + /* Set up client data, pointers to open and close routines + * for the input device. + */ + inputdev->name = "Aiptek"; + inputdev->phys = aiptek->features.usbPath; + usb_to_input_id(usbdev, &inputdev->id); + inputdev->cdev.dev = &intf->dev; + inputdev->private = aiptek; + inputdev->open = aiptek_open; + inputdev->close = aiptek_close; /* Now program the capacities of the tablet, in terms of being * an input device. */ - aiptek->inputdev.evbit[0] |= BIT(EV_KEY) + inputdev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL) | BIT(EV_MSC); - aiptek->inputdev.absbit[0] |= - (BIT(ABS_X) | - BIT(ABS_Y) | - BIT(ABS_PRESSURE) | - BIT(ABS_TILT_X) | - BIT(ABS_TILT_Y) | BIT(ABS_WHEEL) | BIT(ABS_MISC)); + inputdev->absbit[0] |= BIT(ABS_MISC); - aiptek->inputdev.relbit[0] |= + inputdev->relbit[0] |= (BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL) | BIT(REL_MISC)); - aiptek->inputdev.keybit[LONG(BTN_LEFT)] |= + inputdev->keybit[LONG(BTN_LEFT)] |= (BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE)); - aiptek->inputdev.keybit[LONG(BTN_DIGI)] |= + inputdev->keybit[LONG(BTN_DIGI)] |= (BIT(BTN_TOOL_PEN) | BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_PENCIL) | @@ -2070,70 +2088,26 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) BIT(BTN_TOOL_LENS) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2)); - aiptek->inputdev.mscbit[0] = BIT(MSC_SERIAL); + inputdev->mscbit[0] = BIT(MSC_SERIAL); /* Programming the tablet macro keys needs to be done with a for loop * as the keycodes are discontiguous. */ for (i = 0; i < sizeof(macroKeyEvents) / sizeof(macroKeyEvents[0]); ++i) - set_bit(macroKeyEvents[i], aiptek->inputdev.keybit); - - /* Set up client data, pointers to open and close routines - * for the input device. - */ - aiptek->inputdev.private = aiptek; - aiptek->inputdev.open = aiptek_open; - aiptek->inputdev.close = aiptek_close; + set_bit(macroKeyEvents[i], inputdev->keybit); - /* Determine the usb devices' physical path. - * Asketh not why we always pretend we're using "../input0", - * but I suspect this will have to be refactored one - * day if a single USB device can be a keyboard & a mouse - * & a tablet, and the inputX number actually will tell - * us something... - */ - if (usb_make_path(usbdev, path, 64) > 0) - sprintf(aiptek->features.usbPath, "%s/input0", path); - - /* Program the input device coordinate capacities. We do not yet + /* + * Program the input device coordinate capacities. We do not yet * know what maximum X, Y, and Z values are, so we're putting fake * values in. Later, we'll ask the tablet to put in the correct * values. */ - aiptek->inputdev.absmin[ABS_X] = 0; - aiptek->inputdev.absmax[ABS_X] = 2999; - aiptek->inputdev.absmin[ABS_Y] = 0; - aiptek->inputdev.absmax[ABS_Y] = 2249; - aiptek->inputdev.absmin[ABS_PRESSURE] = 0; - aiptek->inputdev.absmax[ABS_PRESSURE] = 511; - aiptek->inputdev.absmin[ABS_TILT_X] = AIPTEK_TILT_MIN; - aiptek->inputdev.absmax[ABS_TILT_X] = AIPTEK_TILT_MAX; - aiptek->inputdev.absmin[ABS_TILT_Y] = AIPTEK_TILT_MIN; - aiptek->inputdev.absmax[ABS_TILT_Y] = AIPTEK_TILT_MAX; - aiptek->inputdev.absmin[ABS_WHEEL] = AIPTEK_WHEEL_MIN; - aiptek->inputdev.absmax[ABS_WHEEL] = AIPTEK_WHEEL_MAX - 1; - aiptek->inputdev.absfuzz[ABS_X] = 0; - aiptek->inputdev.absfuzz[ABS_Y] = 0; - aiptek->inputdev.absfuzz[ABS_PRESSURE] = 0; - aiptek->inputdev.absfuzz[ABS_TILT_X] = 0; - aiptek->inputdev.absfuzz[ABS_TILT_Y] = 0; - aiptek->inputdev.absfuzz[ABS_WHEEL] = 0; - aiptek->inputdev.absflat[ABS_X] = 0; - aiptek->inputdev.absflat[ABS_Y] = 0; - aiptek->inputdev.absflat[ABS_PRESSURE] = 0; - aiptek->inputdev.absflat[ABS_TILT_X] = 0; - aiptek->inputdev.absflat[ABS_TILT_Y] = 0; - aiptek->inputdev.absflat[ABS_WHEEL] = 0; - aiptek->inputdev.name = "Aiptek"; - aiptek->inputdev.phys = aiptek->features.usbPath; - usb_to_input_id(usbdev, &aiptek->inputdev.id); - aiptek->inputdev.dev = &intf->dev; - - aiptek->usbdev = usbdev; - aiptek->ifnum = intf->altsetting[0].desc.bInterfaceNumber; - aiptek->inDelay = 0; - aiptek->endDelay = 0; - aiptek->previousJitterable = 0; + input_set_abs_params(inputdev, ABS_X, 0, 2999, 0, 0); + input_set_abs_params(inputdev, ABS_X, 0, 2249, 0, 0); + input_set_abs_params(inputdev, ABS_PRESSURE, 0, 511, 0, 0); + input_set_abs_params(inputdev, ABS_TILT_X, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0); + input_set_abs_params(inputdev, ABS_TILT_Y, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0); + input_set_abs_params(inputdev, ABS_WHEEL, AIPTEK_WHEEL_MIN, AIPTEK_WHEEL_MAX - 1, 0, 0); endpoint = &intf->altsetting[0].endpoint[0].desc; @@ -2150,28 +2124,6 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) aiptek->urb->transfer_dma = aiptek->data_dma; aiptek->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - /* Register the tablet as an Input Device - */ - input_register_device(&aiptek->inputdev); - - /* We now will look for the evdev device which is mapped to - * the tablet. The partial name is kept in the link list of - * input_handles associated with this input device. - * What identifies an evdev input_handler is that it begins - * with 'event', continues with a digit, and that in turn - * is mapped to /{devfs}/input/eventN. - */ - inputdev = &aiptek->inputdev; - list_for_each_safe(node, next, &inputdev->h_list) { - inputhandle = to_handle(node); - if (strncmp(inputhandle->name, "event", 5) == 0) { - strcpy(aiptek->features.inputPath, inputhandle->name); - break; - } - } - - info("input: Aiptek on %s (%s)\n", path, aiptek->features.inputPath); - /* Program the tablet. This sets the tablet up in the mode * specified in newSetting, and also queries the tablet's * physical capacities. @@ -2186,13 +2138,32 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) for (i = 0; i < sizeof(speeds) / sizeof(speeds[0]); ++i) { aiptek->curSetting.programmableDelay = speeds[i]; (void)aiptek_program_tablet(aiptek); - if (aiptek->inputdev.absmax[ABS_X] > 0) { + if (aiptek->inputdev->absmax[ABS_X] > 0) { info("input: Aiptek using %d ms programming speed\n", aiptek->curSetting.programmableDelay); break; } } + /* Register the tablet as an Input Device + */ + input_register_device(aiptek->inputdev); + + /* We now will look for the evdev device which is mapped to + * the tablet. The partial name is kept in the link list of + * input_handles associated with this input device. + * What identifies an evdev input_handler is that it begins + * with 'event', continues with a digit, and that in turn + * is mapped to input/eventN. + */ + list_for_each_safe(node, next, &inputdev->h_list) { + inputhandle = to_handle(node); + if (strncmp(inputhandle->name, "event", 5) == 0) { + strcpy(aiptek->features.inputPath, inputhandle->name); + break; + } + } + /* Associate this driver's struct with the usb interface. */ usb_set_intfdata(intf, aiptek); @@ -2207,6 +2178,12 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) info("aiptek: error loading 'evdev' module"); return 0; + +fail2: usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data, + aiptek->data_dma); +fail1: input_free_device(inputdev); + kfree(aiptek); + return -ENOMEM; } /* Forward declaration */ @@ -2234,7 +2211,7 @@ static void aiptek_disconnect(struct usb_interface *intf) /* Free & unhook everything from the system. */ usb_kill_urb(aiptek->urb); - input_unregister_device(&aiptek->inputdev); + input_unregister_device(aiptek->inputdev); aiptek_delete_files(&intf->dev); usb_free_urb(aiptek->urb); usb_buffer_free(interface_to_usbdev(intf), diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c index e03c1c5..15840db 100644 --- a/drivers/usb/input/appletouch.c +++ b/drivers/usb/input/appletouch.c @@ -39,7 +39,7 @@ #define APPLE_VENDOR_ID 0x05AC #define ATP_DEVICE(prod) \ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ USB_DEVICE_ID_MATCH_INT_CLASS | \ USB_DEVICE_ID_MATCH_INT_PROTOCOL, \ .idVendor = APPLE_VENDOR_ID, \ @@ -78,9 +78,9 @@ MODULE_DEVICE_TABLE (usb, atp_table); * We try to keep the touchpad aspect ratio while still doing only simple * arithmetics. * The factors below give coordinates like: - * 0 <= x < 960 on 12" and 15" Powerbooks - * 0 <= x < 1600 on 17" Powerbooks - * 0 <= y < 646 + * 0 <= x < 960 on 12" and 15" Powerbooks + * 0 <= x < 1600 on 17" Powerbooks + * 0 <= y < 646 */ #define ATP_XFACT 64 #define ATP_YFACT 43 @@ -93,11 +93,12 @@ MODULE_DEVICE_TABLE (usb, atp_table); /* Structure to hold all of our device specific stuff */ struct atp { + char phys[64]; struct usb_device * udev; /* usb device */ struct urb * urb; /* usb request block */ signed char * data; /* transferred data */ int open; /* non-zero if opened */ - struct input_dev input; /* input dev */ + struct input_dev *input; /* input dev */ int valid; /* are the sensors valid ? */ int x_old; /* last reported x/y, */ int y_old; /* used for smoothing */ @@ -114,11 +115,11 @@ struct atp { int i; \ printk("appletouch: %s %lld", msg, (long long)jiffies); \ for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) \ - printk(" %02x", tab[i]); \ - printk("\n"); \ + printk(" %02x", tab[i]); \ + printk("\n"); \ } -#define dprintk(format, a...) \ +#define dprintk(format, a...) \ do { \ if (debug) printk(format, ##a); \ } while (0) @@ -219,8 +220,8 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs) for (i = 16; i < ATP_XSENSORS; i++) if (dev->xy_cur[i]) { printk("appletouch: 17\" model detected.\n"); - input_set_abs_params(&dev->input, ABS_X, 0, - (ATP_XSENSORS - 1) * + input_set_abs_params(dev->input, ABS_X, 0, + (ATP_XSENSORS - 1) * ATP_XFACT - 1, ATP_FUZZ, 0); break; @@ -260,12 +261,12 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs) "Xz: %3d Yz: %3d\n", x, y, x_z, y_z); - input_report_key(&dev->input, BTN_TOUCH, 1); - input_report_abs(&dev->input, ABS_X, x); - input_report_abs(&dev->input, ABS_Y, y); - input_report_abs(&dev->input, ABS_PRESSURE, + input_report_key(dev->input, BTN_TOUCH, 1); + input_report_abs(dev->input, ABS_X, x); + input_report_abs(dev->input, ABS_Y, y); + input_report_abs(dev->input, ABS_PRESSURE, min(ATP_PRESSURE, x_z + y_z)); - atp_report_fingers(&dev->input, max(x_f, y_f)); + atp_report_fingers(dev->input, max(x_f, y_f)); } dev->x_old = x; dev->y_old = y; @@ -273,17 +274,17 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs) else if (!x && !y) { dev->x_old = dev->y_old = -1; - input_report_key(&dev->input, BTN_TOUCH, 0); - input_report_abs(&dev->input, ABS_PRESSURE, 0); - atp_report_fingers(&dev->input, 0); + input_report_key(dev->input, BTN_TOUCH, 0); + input_report_abs(dev->input, ABS_PRESSURE, 0); + atp_report_fingers(dev->input, 0); /* reset the accumulator on release */ memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); } - input_report_key(&dev->input, BTN_LEFT, !!dev->data[80]); + input_report_key(dev->input, BTN_LEFT, !!dev->data[80]); - input_sync(&dev->input); + input_sync(dev->input); exit: retval = usb_submit_urb(dev->urb, GFP_ATOMIC); @@ -314,21 +315,14 @@ static void atp_close(struct input_dev *input) static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id) { - struct atp *dev = NULL; + struct atp *dev; + struct input_dev *input_dev; + struct usb_device *udev = interface_to_usbdev(iface); struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; int int_in_endpointAddr = 0; int i, retval = -ENOMEM; - /* allocate memory for our device state and initialize it */ - dev = kmalloc(sizeof(struct atp), GFP_KERNEL); - if (dev == NULL) { - err("Out of memory"); - goto err_kmalloc; - } - memset(dev, 0, sizeof(struct atp)); - - dev->udev = interface_to_usbdev(iface); /* set up the endpoint information */ /* use only the first interrupt-in endpoint */ @@ -345,70 +339,82 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id } } if (!int_in_endpointAddr) { - retval = -EIO; err("Could not find int-in endpoint"); - goto err_endpoint; + return -EIO; } - /* save our data pointer in this interface device */ - usb_set_intfdata(iface, dev); + /* allocate memory for our device state and initialize it */ + dev = kzalloc(sizeof(struct atp), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!dev || !input_dev) { + err("Out of memory"); + goto err_free_devs; + } + + dev->udev = udev; + dev->input = input_dev; dev->urb = usb_alloc_urb(0, GFP_KERNEL); if (!dev->urb) { retval = -ENOMEM; - goto err_usballoc; + goto err_free_devs; } + dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL, &dev->urb->transfer_dma); if (!dev->data) { retval = -ENOMEM; - goto err_usbbufalloc; + goto err_free_urb; } - usb_fill_int_urb(dev->urb, dev->udev, - usb_rcvintpipe(dev->udev, int_in_endpointAddr), + + usb_fill_int_urb(dev->urb, udev, + usb_rcvintpipe(udev, int_in_endpointAddr), dev->data, ATP_DATASIZE, atp_complete, dev, 1); - init_input_dev(&dev->input); - dev->input.name = "appletouch"; - dev->input.dev = &iface->dev; - dev->input.private = dev; - dev->input.open = atp_open; - dev->input.close = atp_close; + usb_make_path(udev, dev->phys, sizeof(dev->phys)); + strlcat(dev->phys, "/input0", sizeof(dev->phys)); + + input_dev->name = "appletouch"; + input_dev->phys = dev->phys; + usb_to_input_id(dev->udev, &input_dev->id); + input_dev->cdev.dev = &iface->dev; - usb_to_input_id(dev->udev, &dev->input.id); + input_dev->private = dev; + input_dev->open = atp_open; + input_dev->close = atp_close; - set_bit(EV_ABS, dev->input.evbit); + set_bit(EV_ABS, input_dev->evbit); /* * 12" and 15" Powerbooks only have 16 x sensors, * 17" models are detected later. */ - input_set_abs_params(&dev->input, ABS_X, 0, + input_set_abs_params(input_dev, ABS_X, 0, (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0); - input_set_abs_params(&dev->input, ABS_Y, 0, + input_set_abs_params(input_dev, ABS_Y, 0, (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0); - input_set_abs_params(&dev->input, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0); - set_bit(EV_KEY, dev->input.evbit); - set_bit(BTN_TOUCH, dev->input.keybit); - set_bit(BTN_TOOL_FINGER, dev->input.keybit); - set_bit(BTN_TOOL_DOUBLETAP, dev->input.keybit); - set_bit(BTN_TOOL_TRIPLETAP, dev->input.keybit); - set_bit(BTN_LEFT, dev->input.keybit); + set_bit(EV_KEY, input_dev->evbit); + set_bit(BTN_TOUCH, input_dev->keybit); + set_bit(BTN_TOOL_FINGER, input_dev->keybit); + set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); + set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); + set_bit(BTN_LEFT, input_dev->keybit); - input_register_device(&dev->input); + input_register_device(dev->input); - printk(KERN_INFO "input: appletouch connected\n"); + /* save our data pointer in this interface device */ + usb_set_intfdata(iface, dev); return 0; -err_usbbufalloc: + err_free_urb: usb_free_urb(dev->urb); -err_usballoc: + err_free_devs: usb_set_intfdata(iface, NULL); -err_endpoint: kfree(dev); -err_kmalloc: + input_free_device(input_dev); return retval; } @@ -419,7 +425,7 @@ static void atp_disconnect(struct usb_interface *iface) usb_set_intfdata(iface, NULL); if (dev) { usb_kill_urb(dev->urb); - input_unregister_device(&dev->input); + input_unregister_device(dev->input); usb_free_urb(dev->urb); usb_buffer_free(dev->udev, ATP_DATASIZE, dev->data, dev->urb->transfer_dma); diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index fd99681..9a2a47d 100644 --- a/drivers/usb/input/ati_remote.c +++ b/drivers/usb/input/ati_remote.c @@ -112,7 +112,6 @@ #define NAME_BUFSIZE 80 /* size of product name, path buffers */ #define DATA_BUFSIZE 63 /* size of URB data buffers */ -#define ATI_INPUTNUM 1 /* Which input device to register as */ static unsigned long channel_mask; module_param(channel_mask, ulong, 0444); @@ -162,7 +161,7 @@ static char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; static DECLARE_MUTEX(disconnect_sem); struct ati_remote { - struct input_dev idev; + struct input_dev *idev; struct usb_device *udev; struct usb_interface *interface; @@ -198,15 +197,13 @@ struct ati_remote { #define KIND_ACCEL 7 /* Directional keypad - left, right, up, down.*/ /* Translation table from hardware messages to input events. */ -static struct -{ +static struct { short kind; unsigned char data1, data2; int type; unsigned int code; int value; -} ati_remote_tbl[] = -{ +} ati_remote_tbl[] = { /* Directional control pad axes */ {KIND_ACCEL, 0x35, 0x70, EV_REL, REL_X, -1}, /* left */ {KIND_ACCEL, 0x36, 0x71, EV_REL, REL_X, 1}, /* right */ @@ -286,7 +283,6 @@ static struct /* Local function prototypes */ static void ati_remote_dump (unsigned char *data, unsigned int actual_length); -static void ati_remote_delete (struct ati_remote *dev); static int ati_remote_open (struct input_dev *inputdev); static void ati_remote_close (struct input_dev *inputdev); static int ati_remote_sendpacket (struct ati_remote *ati_remote, u16 cmd, unsigned char *data); @@ -428,7 +424,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) { struct ati_remote *ati_remote = urb->context; unsigned char *data= ati_remote->inbuf; - struct input_dev *dev = &ati_remote->idev; + struct input_dev *dev = ati_remote->idev; int index, acc; int remote_num; @@ -587,38 +583,55 @@ static void ati_remote_irq_in(struct urb *urb, struct pt_regs *regs) } /* - * ati_remote_delete + * ati_remote_alloc_buffers */ -static void ati_remote_delete(struct ati_remote *ati_remote) +static int ati_remote_alloc_buffers(struct usb_device *udev, + struct ati_remote *ati_remote) { - if (ati_remote->irq_urb) - usb_kill_urb(ati_remote->irq_urb); + ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC, + &ati_remote->inbuf_dma); + if (!ati_remote->inbuf) + return -1; - if (ati_remote->out_urb) - usb_kill_urb(ati_remote->out_urb); + ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC, + &ati_remote->outbuf_dma); + if (!ati_remote->outbuf) + return -1; - input_unregister_device(&ati_remote->idev); + ati_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!ati_remote->irq_urb) + return -1; - if (ati_remote->inbuf) - usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, - ati_remote->inbuf, ati_remote->inbuf_dma); + ati_remote->out_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!ati_remote->out_urb) + return -1; - if (ati_remote->outbuf) - usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, - ati_remote->outbuf, ati_remote->outbuf_dma); + return 0; +} +/* + * ati_remote_free_buffers + */ +static void ati_remote_free_buffers(struct ati_remote *ati_remote) +{ if (ati_remote->irq_urb) usb_free_urb(ati_remote->irq_urb); if (ati_remote->out_urb) usb_free_urb(ati_remote->out_urb); - kfree(ati_remote); + if (ati_remote->inbuf) + usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, + ati_remote->inbuf, ati_remote->inbuf_dma); + + if (ati_remote->outbuf) + usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, + ati_remote->inbuf, ati_remote->outbuf_dma); } static void ati_remote_input_init(struct ati_remote *ati_remote) { - struct input_dev *idev = &(ati_remote->idev); + struct input_dev *idev = ati_remote->idev; int i; idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); @@ -637,7 +650,7 @@ static void ati_remote_input_init(struct ati_remote *ati_remote) idev->phys = ati_remote->phys; usb_to_input_id(ati_remote->udev, &idev->id); - idev->dev = &ati_remote->udev->dev; + idev->cdev.dev = &ati_remote->udev->dev; } static int ati_remote_initialize(struct ati_remote *ati_remote) @@ -674,7 +687,7 @@ static int ati_remote_initialize(struct ati_remote *ati_remote) (ati_remote_sendpacket(ati_remote, 0x8007, init2))) { dev_err(&ati_remote->interface->dev, "Initializing ati_remote hardware failed.\n"); - return 1; + return -EIO; } return 0; @@ -686,95 +699,83 @@ static int ati_remote_initialize(struct ati_remote *ati_remote) static int ati_remote_probe(struct usb_interface *interface, const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev(interface); - struct ati_remote *ati_remote = NULL; - struct usb_host_interface *iface_host; - int retval = -ENOMEM; - char path[64]; - - /* Allocate and clear an ati_remote struct */ - if (!(ati_remote = kmalloc(sizeof (struct ati_remote), GFP_KERNEL))) - return -ENOMEM; - memset(ati_remote, 0x00, sizeof (struct ati_remote)); + struct usb_host_interface *iface_host = interface->cur_altsetting; + struct usb_endpoint_descriptor *endpoint_in, *endpoint_out; + struct ati_remote *ati_remote; + struct input_dev *input_dev; + int err = -ENOMEM; - iface_host = interface->cur_altsetting; if (iface_host->desc.bNumEndpoints != 2) { err("%s: Unexpected desc.bNumEndpoints\n", __FUNCTION__); - retval = -ENODEV; - goto error; + return -ENODEV; } - ati_remote->endpoint_in = &(iface_host->endpoint[0].desc); - ati_remote->endpoint_out = &(iface_host->endpoint[1].desc); - ati_remote->udev = udev; - ati_remote->interface = interface; + endpoint_in = &iface_host->endpoint[0].desc; + endpoint_out = &iface_host->endpoint[1].desc; - if (!(ati_remote->endpoint_in->bEndpointAddress & 0x80)) { + if (!(endpoint_in->bEndpointAddress & USB_DIR_IN)) { err("%s: Unexpected endpoint_in->bEndpointAddress\n", __FUNCTION__); - retval = -ENODEV; - goto error; + return -ENODEV; } - if ((ati_remote->endpoint_in->bmAttributes & 3) != 3) { + if ((endpoint_in->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) { err("%s: Unexpected endpoint_in->bmAttributes\n", __FUNCTION__); - retval = -ENODEV; - goto error; + return -ENODEV; } - if (le16_to_cpu(ati_remote->endpoint_in->wMaxPacketSize) == 0) { + if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) { err("%s: endpoint_in message size==0? \n", __FUNCTION__); - retval = -ENODEV; - goto error; + return -ENODEV; } - /* Allocate URB buffers, URBs */ - ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC, - &ati_remote->inbuf_dma); - if (!ati_remote->inbuf) - goto error; + ati_remote = kzalloc(sizeof (struct ati_remote), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!ati_remote || !input_dev) + goto fail1; - ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC, - &ati_remote->outbuf_dma); - if (!ati_remote->outbuf) - goto error; + /* Allocate URB buffers, URBs */ + if (ati_remote_alloc_buffers(udev, ati_remote)) + goto fail2; - ati_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!ati_remote->irq_urb) - goto error; + ati_remote->endpoint_in = endpoint_in; + ati_remote->endpoint_out = endpoint_out; + ati_remote->udev = udev; + ati_remote->idev = input_dev; + ati_remote->interface = interface; - ati_remote->out_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!ati_remote->out_urb) - goto error; + usb_make_path(udev, ati_remote->phys, sizeof(ati_remote->phys)); + strlcpy(ati_remote->phys, "/input0", sizeof(ati_remote->phys)); - usb_make_path(udev, path, NAME_BUFSIZE); - sprintf(ati_remote->phys, "%s/input%d", path, ATI_INPUTNUM); if (udev->manufacturer) - strcat(ati_remote->name, udev->manufacturer); + strlcpy(ati_remote->name, udev->manufacturer, sizeof(ati_remote->name)); if (udev->product) - sprintf(ati_remote->name, "%s %s", ati_remote->name, udev->product); + snprintf(ati_remote->name, sizeof(ati_remote->name), + "%s %s", ati_remote->name, udev->product); if (!strlen(ati_remote->name)) - sprintf(ati_remote->name, DRIVER_DESC "(%04x,%04x)", + snprintf(ati_remote->name, sizeof(ati_remote->name), + DRIVER_DESC "(%04x,%04x)", le16_to_cpu(ati_remote->udev->descriptor.idVendor), le16_to_cpu(ati_remote->udev->descriptor.idProduct)); + ati_remote_input_init(ati_remote); + /* Device Hardware Initialization - fills in ati_remote->idev from udev. */ - retval = ati_remote_initialize(ati_remote); - if (retval) - goto error; + err = ati_remote_initialize(ati_remote); + if (err) + goto fail3; /* Set up and register input device */ - ati_remote_input_init(ati_remote); - input_register_device(&ati_remote->idev); - - dev_info(&ati_remote->interface->dev, "Input registered: %s on %s\n", - ati_remote->name, path); + input_register_device(ati_remote->idev); usb_set_intfdata(interface, ati_remote); + return 0; -error: - if (retval) - ati_remote_delete(ati_remote); - - return retval; +fail3: usb_kill_urb(ati_remote->irq_urb); + usb_kill_urb(ati_remote->out_urb); +fail2: ati_remote_free_buffers(ati_remote); +fail1: input_free_device(input_dev); + kfree(ati_remote); + return err; } /* @@ -791,7 +792,11 @@ static void ati_remote_disconnect(struct usb_interface *interface) return; } - ati_remote_delete(ati_remote); + usb_kill_urb(ati_remote->irq_urb); + usb_kill_urb(ati_remote->out_urb); + input_unregister_device(ati_remote->idev); + ati_remote_free_buffers(ati_remote); + kfree(ati_remote); } /* diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 41f92b9..79ddce4 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1619,8 +1619,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) struct hid_descriptor *hdesc; struct hid_device *hid; unsigned quirks = 0, rsize = 0; - char *buf, *rdesc; - int n, insize = 0; + char *rdesc; + int n, len, insize = 0; for (n = 0; hid_blacklist[n].idVendor; n++) if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) && @@ -1630,10 +1630,11 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) if (quirks & HID_QUIRK_IGNORE) return NULL; - if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && ((!interface->desc.bNumEndpoints) || - usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) { - dbg("class descriptor not present\n"); - return NULL; + if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && + (!interface->desc.bNumEndpoints || + usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) { + dbg("class descriptor not present\n"); + return NULL; } for (n = 0; n < hdesc->bNumDescriptors; n++) @@ -1749,38 +1750,43 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) hid->name[0] = 0; - if (!(buf = kmalloc(64, GFP_KERNEL))) - goto fail; + if (dev->manufacturer) + strlcpy(hid->name, dev->manufacturer, sizeof(hid->name)); + + if (dev->product) { + if (dev->manufacturer) + strlcat(hid->name, " ", sizeof(hid->name)); + strlcat(hid->name, dev->product, sizeof(hid->name)); + } - if (dev->manufacturer) { - strcat(hid->name, dev->manufacturer); - if (dev->product) - snprintf(hid->name, 64, "%s %s", hid->name, dev->product); - } else if (dev->product) { - snprintf(hid->name, 128, "%s", dev->product); - } else - snprintf(hid->name, 128, "%04x:%04x", - le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); - - usb_make_path(dev, buf, 64); - snprintf(hid->phys, 64, "%s/input%d", buf, - intf->altsetting[0].desc.bInterfaceNumber); + if (!strlen(hid->name)) + snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x", + le16_to_cpu(dev->descriptor.idVendor), + le16_to_cpu(dev->descriptor.idProduct)); + + usb_make_path(dev, hid->phys, sizeof(hid->phys)); + strlcat(hid->phys, "/input", sizeof(hid->phys)); + len = strlen(hid->phys); + if (len < sizeof(hid->phys) - 1) + snprintf(hid->phys + len, sizeof(hid->phys) - len, + "%d", intf->altsetting[0].desc.bInterfaceNumber); if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0) hid->uniq[0] = 0; - kfree(buf); - hid->urbctrl = usb_alloc_urb(0, GFP_KERNEL); if (!hid->urbctrl) goto fail; + usb_fill_control_urb(hid->urbctrl, dev, 0, (void *) hid->cr, hid->ctrlbuf, 1, hid_ctrl, hid); hid->urbctrl->setup_dma = hid->cr_dma; hid->urbctrl->transfer_dma = hid->ctrlbuf_dma; hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); + /* May be needed for some devices */ + usb_clear_halt(hid->dev, hid->urbin->pipe); + return hid; fail: @@ -1884,7 +1890,6 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) struct hid_device *hid = usb_get_intfdata (intf); usb_kill_urb(hid->urbin); - intf->dev.power.power_state = PMSG_SUSPEND; dev_dbg(&intf->dev, "suspend\n"); return 0; } @@ -1894,7 +1899,6 @@ static int hid_resume(struct usb_interface *intf) struct hid_device *hid = usb_get_intfdata (intf); int status; - intf->dev.power.power_state = PMSG_ON; if (hid->open) status = usb_submit_urb(hid->urbin, GFP_NOIO); else diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index 0b64522..9ff25eb 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c @@ -76,8 +76,8 @@ static struct { static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, struct hid_usage *usage) { - struct input_dev *input = &hidinput->input; - struct hid_device *device = hidinput->input.private; + struct input_dev *input = hidinput->input; + struct hid_device *device = input->private; int max = 0, code; unsigned long *bit = NULL; @@ -461,7 +461,8 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct if (!field->hidinput) return; - input = &field->hidinput->input; + + input = field->hidinput->input; input_regs(input, regs); @@ -533,13 +534,10 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct void hidinput_report_event(struct hid_device *hid, struct hid_report *report) { - struct list_head *lh; struct hid_input *hidinput; - list_for_each (lh, &hid->inputs) { - hidinput = list_entry(lh, struct hid_input, list); - input_sync(&hidinput->input); - } + list_for_each_entry(hidinput, &hid->inputs, list) + input_sync(hidinput->input); } static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field) @@ -604,6 +602,7 @@ int hidinput_connect(struct hid_device *hid) struct usb_device *dev = hid->dev; struct hid_report *report; struct hid_input *hidinput = NULL; + struct input_dev *input_dev; int i, j, k; INIT_LIST_HEAD(&hid->inputs); @@ -624,25 +623,28 @@ int hidinput_connect(struct hid_device *hid) continue; if (!hidinput) { - hidinput = kmalloc(sizeof(*hidinput), GFP_KERNEL); - if (!hidinput) { + hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!hidinput || !input_dev) { + kfree(hidinput); + input_free_device(input_dev); err("Out of memory during hid input probe"); return -1; } - memset(hidinput, 0, sizeof(*hidinput)); - list_add_tail(&hidinput->list, &hid->inputs); + input_dev->private = hid; + input_dev->event = hidinput_input_event; + input_dev->open = hidinput_open; + input_dev->close = hidinput_close; - hidinput->input.private = hid; - hidinput->input.event = hidinput_input_event; - hidinput->input.open = hidinput_open; - hidinput->input.close = hidinput_close; + input_dev->name = hid->name; + input_dev->phys = hid->phys; + input_dev->uniq = hid->uniq; + usb_to_input_id(dev, &input_dev->id); + input_dev->cdev.dev = &hid->intf->dev; - hidinput->input.name = hid->name; - hidinput->input.phys = hid->phys; - hidinput->input.uniq = hid->uniq; - usb_to_input_id(dev, &hidinput->input.id); - hidinput->input.dev = &hid->intf->dev; + hidinput->input = input_dev; + list_add_tail(&hidinput->list, &hid->inputs); } for (i = 0; i < report->maxfield; i++) @@ -657,7 +659,7 @@ int hidinput_connect(struct hid_device *hid) * UGCI) cram a lot of unrelated inputs into the * same interface. */ hidinput->report = report; - input_register_device(&hidinput->input); + input_register_device(hidinput->input); hidinput = NULL; } } @@ -667,7 +669,7 @@ int hidinput_connect(struct hid_device *hid) * only useful in this case, and not for multi-input quirks. */ if (hidinput) { hid_ff_init(hid); - input_register_device(&hidinput->input); + input_register_device(hidinput->input); } return 0; @@ -675,13 +677,11 @@ int hidinput_connect(struct hid_device *hid) void hidinput_disconnect(struct hid_device *hid) { - struct list_head *lh, *next; - struct hid_input *hidinput; + struct hid_input *hidinput, *next; - list_for_each_safe(lh, next, &hid->inputs) { - hidinput = list_entry(lh, struct hid_input, list); - input_unregister_device(&hidinput->input); + list_for_each_entry_safe(hidinput, next, &hid->inputs, list) { list_del(&hidinput->list); + input_unregister_device(hidinput->input); kfree(hidinput); } } diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c index 0c4c77a..f82c9c9 100644 --- a/drivers/usb/input/hid-lgff.c +++ b/drivers/usb/input/hid-lgff.c @@ -255,22 +255,19 @@ static void hid_lgff_input_init(struct hid_device* hid) u16 idVendor = le16_to_cpu(hid->dev->descriptor.idVendor); u16 idProduct = le16_to_cpu(hid->dev->descriptor.idProduct); struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); + struct input_dev *input_dev = hidinput->input; while (dev->idVendor && (idVendor != dev->idVendor || idProduct != dev->idProduct)) dev++; - ff = dev->ff; + for (ff = dev->ff; *ff >= 0; ff++) + set_bit(*ff, input_dev->ffbit); - while (*ff >= 0) { - set_bit(*ff, hidinput->input.ffbit); - ++ff; - } - - hidinput->input.upload_effect = hid_lgff_upload_effect; - hidinput->input.flush = hid_lgff_flush; + input_dev->upload_effect = hid_lgff_upload_effect; + input_dev->flush = hid_lgff_flush; - set_bit(EV_FF, hidinput->input.evbit); - hidinput->input.ff_effects_max = LGFF_EFFECTS; + set_bit(EV_FF, input_dev->evbit); + input_dev->ff_effects_max = LGFF_EFFECTS; } static void hid_lgff_exit(struct hid_device* hid) diff --git a/drivers/usb/input/hid-tmff.c b/drivers/usb/input/hid-tmff.c index 8f6a0a6..023fd5a 100644 --- a/drivers/usb/input/hid-tmff.c +++ b/drivers/usb/input/hid-tmff.c @@ -111,6 +111,7 @@ int hid_tmff_init(struct hid_device *hid) struct tmff_device *private; struct list_head *pos; struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); + struct input_dev *input_dev = hidinput->input; private = kmalloc(sizeof(struct tmff_device), GFP_KERNEL); if (!private) @@ -155,7 +156,7 @@ int hid_tmff_init(struct hid_device *hid) private->report = report; private->rumble = field; - set_bit(FF_RUMBLE, hidinput->input.ffbit); + set_bit(FF_RUMBLE, input_dev->ffbit); break; default: @@ -164,11 +165,11 @@ int hid_tmff_init(struct hid_device *hid) } /* Fallthrough to here only when a valid usage is found */ - hidinput->input.upload_effect = hid_tmff_upload_effect; - hidinput->input.flush = hid_tmff_flush; + input_dev->upload_effect = hid_tmff_upload_effect; + input_dev->flush = hid_tmff_flush; - set_bit(EV_FF, hidinput->input.evbit); - hidinput->input.ff_effects_max = TMFF_EFFECTS; + set_bit(EV_FF, input_dev->evbit); + input_dev->ff_effects_max = TMFF_EFFECTS; } } diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h index ec2412c..ee48a22 100644 --- a/drivers/usb/input/hid.h +++ b/drivers/usb/input/hid.h @@ -371,7 +371,7 @@ struct hid_control_fifo { struct hid_input { struct list_head list; struct hid_report *report; - struct input_dev input; + struct input_dev *input; }; struct hid_device { /* device report descriptor */ diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c index d324278..440377c 100644 --- a/drivers/usb/input/hiddev.c +++ b/drivers/usb/input/hiddev.c @@ -732,9 +732,8 @@ static struct file_operations hiddev_fops = { }; static struct usb_class_driver hiddev_class = { - .name = "usb/hid/hiddev%d", + .name = "hiddev%d", .fops = &hiddev_fops, - .mode = S_IFCHR | S_IRUGO | S_IWUSR, .minor_base = HIDDEV_MINOR_BASE, }; diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c index becb87e..3b58185 100644 --- a/drivers/usb/input/itmtouch.c +++ b/drivers/usb/input/itmtouch.c @@ -73,7 +73,7 @@ MODULE_LICENSE( DRIVER_LICENSE ); struct itmtouch_dev { struct usb_device *usbdev; /* usb device */ - struct input_dev inputdev; /* input device */ + struct input_dev *inputdev; /* input device */ struct urb *readurb; /* urb */ char rbuf[ITM_BUFSIZE]; /* data */ int users; @@ -88,9 +88,9 @@ static struct usb_device_id itmtouch_ids [] = { static void itmtouch_irq(struct urb *urb, struct pt_regs *regs) { - struct itmtouch_dev * itmtouch = urb->context; + struct itmtouch_dev *itmtouch = urb->context; unsigned char *data = urb->transfer_buffer; - struct input_dev *dev = &itmtouch->inputdev; + struct input_dev *dev = itmtouch->inputdev; int retval; switch (urb->status) { @@ -156,49 +156,62 @@ static void itmtouch_close(struct input_dev *input) static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct itmtouch_dev *itmtouch; + struct input_dev *input_dev; struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; struct usb_device *udev = interface_to_usbdev(intf); unsigned int pipe; unsigned int maxp; - char path[PATH_SIZE]; interface = intf->cur_altsetting; endpoint = &interface->endpoint[0].desc; - if (!(itmtouch = kzalloc(sizeof(struct itmtouch_dev), GFP_KERNEL))) { + itmtouch = kzalloc(sizeof(struct itmtouch_dev), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!itmtouch || !input_dev) { err("%s - Out of memory.", __FUNCTION__); - return -ENOMEM; + goto fail; } itmtouch->usbdev = udev; + itmtouch->inputdev = input_dev; - itmtouch->inputdev.private = itmtouch; - itmtouch->inputdev.open = itmtouch_open; - itmtouch->inputdev.close = itmtouch_close; + if (udev->manufacturer) + strlcpy(itmtouch->name, udev->manufacturer, sizeof(itmtouch->name)); - usb_make_path(udev, path, PATH_SIZE); - - itmtouch->inputdev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - itmtouch->inputdev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); - itmtouch->inputdev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); - - itmtouch->inputdev.name = itmtouch->name; - itmtouch->inputdev.phys = itmtouch->phys; - usb_to_input_id(udev, &itmtouch->inputdev.id); - itmtouch->inputdev.dev = &intf->dev; + if (udev->product) { + if (udev->manufacturer) + strlcat(itmtouch->name, " ", sizeof(itmtouch->name)); + strlcat(itmtouch->name, udev->product, sizeof(itmtouch->name)); + } if (!strlen(itmtouch->name)) sprintf(itmtouch->name, "USB ITM touchscreen"); + usb_make_path(udev, itmtouch->phys, sizeof(itmtouch->phys)); + strlcpy(itmtouch->phys, "/input0", sizeof(itmtouch->phys)); + + input_dev->name = itmtouch->name; + input_dev->phys = itmtouch->phys; + usb_to_input_id(udev, &input_dev->id); + input_dev->cdev.dev = &intf->dev; + input_dev->private = itmtouch; + + input_dev->open = itmtouch_open; + input_dev->close = itmtouch_close; + + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); + input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); + /* device limits */ /* as specified by the ITM datasheet, X and Y are 12bit, * Z (pressure) is 8 bit. However, the fields are defined up * to 14 bits for future possible expansion. */ - input_set_abs_params(&itmtouch->inputdev, ABS_X, 0, 0x0FFF, 2, 0); - input_set_abs_params(&itmtouch->inputdev, ABS_Y, 0, 0x0FFF, 2, 0); - input_set_abs_params(&itmtouch->inputdev, ABS_PRESSURE, 0, 0xFF, 2, 0); + input_set_abs_params(input_dev, ABS_X, 0, 0x0FFF, 2, 0); + input_set_abs_params(input_dev, ABS_Y, 0, 0x0FFF, 2, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xFF, 2, 0); /* initialise the URB so we can read from the transport stream */ pipe = usb_rcvintpipe(itmtouch->usbdev, endpoint->bEndpointAddress); @@ -208,22 +221,23 @@ static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id maxp = ITM_BUFSIZE; itmtouch->readurb = usb_alloc_urb(0, GFP_KERNEL); - if (!itmtouch->readurb) { dbg("%s - usb_alloc_urb failed: itmtouch->readurb", __FUNCTION__); - kfree(itmtouch); - return -ENOMEM; + goto fail; } usb_fill_int_urb(itmtouch->readurb, itmtouch->usbdev, pipe, itmtouch->rbuf, maxp, itmtouch_irq, itmtouch, endpoint->bInterval); - input_register_device(&itmtouch->inputdev); + input_register_device(itmtouch->inputdev); - printk(KERN_INFO "itmtouch: %s registered on %s\n", itmtouch->name, path); usb_set_intfdata(intf, itmtouch); return 0; + + fail: input_free_device(input_dev); + kfree(itmtouch); + return -ENOMEM; } static void itmtouch_disconnect(struct usb_interface *intf) @@ -233,7 +247,7 @@ static void itmtouch_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); if (itmtouch) { - input_unregister_device(&itmtouch->inputdev); + input_unregister_device(itmtouch->inputdev); usb_kill_urb(itmtouch->readurb); usb_free_urb(itmtouch->readurb); kfree(itmtouch); diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c index b6f6ac8..a248664 100644 --- a/drivers/usb/input/kbtab.c +++ b/drivers/usb/input/kbtab.c @@ -34,7 +34,7 @@ MODULE_PARM_DESC(kb_pressure_click, "pressure threshold for clicks"); struct kbtab { signed char *data; dma_addr_t data_dma; - struct input_dev dev; + struct input_dev *dev; struct usb_device *usbdev; struct urb *irq; int x, y; @@ -48,7 +48,7 @@ static void kbtab_irq(struct urb *urb, struct pt_regs *regs) { struct kbtab *kbtab = urb->context; unsigned char *data = kbtab->data; - struct input_dev *dev = &kbtab->dev; + struct input_dev *dev = kbtab->dev; int retval; switch (urb->status) { @@ -124,53 +124,43 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i struct usb_device *dev = interface_to_usbdev(intf); struct usb_endpoint_descriptor *endpoint; struct kbtab *kbtab; - char path[64]; + struct input_dev *input_dev; - if (!(kbtab = kmalloc(sizeof(struct kbtab), GFP_KERNEL))) - return -ENOMEM; - memset(kbtab, 0, sizeof(struct kbtab)); + kbtab = kzalloc(sizeof(struct kbtab), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!kbtab || !input_dev) + goto fail1; kbtab->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &kbtab->data_dma); - if (!kbtab->data) { - kfree(kbtab); - return -ENOMEM; - } + if (!kbtab->data) + goto fail1; kbtab->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!kbtab->irq) { - usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma); - kfree(kbtab); - return -ENOMEM; - } - - kbtab->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC); - kbtab->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); - - kbtab->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); - - kbtab->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH); + if (!kbtab->irq) + goto fail2; - kbtab->dev.mscbit[0] |= BIT(MSC_SERIAL); - - kbtab->dev.absmax[ABS_X] = 0x2000; - kbtab->dev.absmax[ABS_Y] = 0x1750; - kbtab->dev.absmax[ABS_PRESSURE] = 0xff; + kbtab->usbdev = dev; + kbtab->dev = input_dev; - kbtab->dev.absfuzz[ABS_X] = 4; - kbtab->dev.absfuzz[ABS_Y] = 4; + usb_make_path(dev, kbtab->phys, sizeof(kbtab->phys)); + strlcat(kbtab->phys, "/input0", sizeof(kbtab->phys)); - kbtab->dev.private = kbtab; - kbtab->dev.open = kbtab_open; - kbtab->dev.close = kbtab_close; + input_dev->name = "KB Gear Tablet"; + input_dev->phys = kbtab->phys; + usb_to_input_id(dev, &input_dev->id); + input_dev->cdev.dev = &intf->dev; + input_dev->private = kbtab; - usb_make_path(dev, path, 64); - sprintf(kbtab->phys, "%s/input0", path); + input_dev->open = kbtab_open; + input_dev->close = kbtab_close; - kbtab->dev.name = "KB Gear Tablet"; - kbtab->dev.phys = kbtab->phys; - usb_to_input_id(dev, &kbtab->dev.id); - kbtab->dev.dev = &intf->dev; - kbtab->usbdev = dev; + input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC); + input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); + input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH); + input_dev->mscbit[0] |= BIT(MSC_SERIAL); + input_set_abs_params(input_dev, ABS_X, 0, 0x2000, 4, 0); + input_set_abs_params(input_dev, ABS_X, 0, 0x1750, 4, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xff, 0, 0); endpoint = &intf->cur_altsetting->endpoint[0].desc; @@ -181,23 +171,25 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i kbtab->irq->transfer_dma = kbtab->data_dma; kbtab->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - input_register_device(&kbtab->dev); - - printk(KERN_INFO "input: KB Gear Tablet on %s\n", path); + input_register_device(kbtab->dev); usb_set_intfdata(intf, kbtab); - return 0; + +fail2: usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma); +fail1: input_free_device(input_dev); + kfree(kbtab); + return -ENOMEM; } static void kbtab_disconnect(struct usb_interface *intf) { - struct kbtab *kbtab = usb_get_intfdata (intf); + struct kbtab *kbtab = usb_get_intfdata(intf); usb_set_intfdata(intf, NULL); if (kbtab) { usb_kill_urb(kbtab->irq); - input_unregister_device(&kbtab->dev); + input_unregister_device(kbtab->dev); usb_free_urb(kbtab->irq); usb_buffer_free(interface_to_usbdev(intf), 10, kbtab->data, kbtab->data_dma); kfree(kbtab); diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c index 99de1b3..5b8d65f 100644 --- a/drivers/usb/input/keyspan_remote.c +++ b/drivers/usb/input/keyspan_remote.c @@ -20,6 +20,7 @@ #include <linux/moduleparam.h> #include <linux/input.h> #include <linux/usb.h> +#include <linux/usb_input.h> #define DRIVER_VERSION "v0.1" #define DRIVER_AUTHOR "Michael Downey <downey@zymeta.com>" @@ -75,7 +76,7 @@ struct usb_keyspan { char name[128]; char phys[64]; struct usb_device* udev; - struct input_dev input; + struct input_dev *input; struct usb_interface* interface; struct usb_endpoint_descriptor* in_endpoint; struct urb* irq_urb; @@ -136,12 +137,11 @@ static struct usb_driver keyspan_driver; */ static void keyspan_print(struct usb_keyspan* dev) /*unsigned char* data)*/ { - char codes[4*RECV_SIZE]; + char codes[4 * RECV_SIZE]; int i; - for (i = 0; i < RECV_SIZE; i++) { - snprintf(codes+i*3, 4, "%02x ", dev->in_buffer[i]); - } + for (i = 0; i < RECV_SIZE; i++) + snprintf(codes + i * 3, 4, "%02x ", dev->in_buffer[i]); dev_info(&dev->udev->dev, "%s\n", codes); } @@ -153,7 +153,7 @@ static void keyspan_print(struct usb_keyspan* dev) /*unsigned char* data)*/ static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed) { if (dev->data.bits_left >= bits_needed) - return(0); + return 0; /* * Somehow we've missed the last message. The message will be repeated @@ -162,7 +162,7 @@ static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed) if (dev->data.pos >= dev->data.len) { dev_dbg(&dev->udev, "%s - Error ran out of data. pos: %d, len: %d\n", __FUNCTION__, dev->data.pos, dev->data.len); - return(-1); + return -1; } /* Load as much as we can into the tester. */ @@ -172,7 +172,7 @@ static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed) dev->data.bits_left += 8; } - return(0); + return 0; } /* @@ -311,10 +311,10 @@ static void keyspan_check_data(struct usb_keyspan *remote, struct pt_regs *regs) __FUNCTION__, message.system, message.button, message.toggle); if (message.toggle != remote->toggle) { - input_regs(&remote->input, regs); - input_report_key(&remote->input, keyspan_key_table[message.button], 1); - input_report_key(&remote->input, keyspan_key_table[message.button], 0); - input_sync(&remote->input); + input_regs(remote->input, regs); + input_report_key(remote->input, keyspan_key_table[message.button], 1); + input_report_key(remote->input, keyspan_key_table[message.button], 0); + input_sync(remote->input); remote->toggle = message.toggle; } @@ -397,14 +397,9 @@ static int keyspan_open(struct input_dev *dev) { struct usb_keyspan *remote = dev->private; - if (remote->open++) - return 0; - remote->irq_urb->dev = remote->udev; - if (usb_submit_urb(remote->irq_urb, GFP_KERNEL)) { - remote->open--; + if (usb_submit_urb(remote->irq_urb, GFP_KERNEL)) return -EIO; - } return 0; } @@ -413,8 +408,26 @@ static void keyspan_close(struct input_dev *dev) { struct usb_keyspan *remote = dev->private; - if (!--remote->open) - usb_kill_urb(remote->irq_urb); + usb_kill_urb(remote->irq_urb); +} + +static struct usb_endpoint_descriptor *keyspan_get_in_endpoint(struct usb_host_interface *iface) +{ + + struct usb_endpoint_descriptor *endpoint; + int i; + + for (i = 0; i < iface->desc.bNumEndpoints; ++i) { + endpoint = &iface->endpoint[i].desc; + + if ((endpoint->bEndpointAddress & USB_DIR_IN) && + ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) { + /* we found our interrupt in endpoint */ + return endpoint; + } + } + + return NULL; } /* @@ -422,110 +435,78 @@ static void keyspan_close(struct input_dev *dev) */ static int keyspan_probe(struct usb_interface *interface, const struct usb_device_id *id) { - int i; - int retval = -ENOMEM; - char path[64]; - char *buf; - struct usb_keyspan *remote = NULL; - struct usb_host_interface *iface_desc; + struct usb_device *udev = interface_to_usbdev(interface); struct usb_endpoint_descriptor *endpoint; - struct usb_device *udev = usb_get_dev(interface_to_usbdev(interface)); + struct usb_keyspan *remote; + struct input_dev *input_dev; + int i, retval; - /* allocate memory for our device state and initialize it */ - remote = kmalloc(sizeof(*remote), GFP_KERNEL); - if (remote == NULL) { - err("Out of memory\n"); - goto error; + endpoint = keyspan_get_in_endpoint(interface->cur_altsetting); + if (!endpoint) + return -ENODEV; + + remote = kzalloc(sizeof(*remote), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!remote || !input_dev) { + retval = -ENOMEM; + goto fail1; } - memset(remote, 0x00, sizeof(*remote)); remote->udev = udev; + remote->input = input_dev; remote->interface = interface; + remote->in_endpoint = endpoint; remote->toggle = -1; /* Set to -1 so we will always not match the toggle from the first remote message. */ - /* set up the endpoint information */ - /* use only the first in interrupt endpoint */ - iface_desc = interface->cur_altsetting; - for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { - endpoint = &iface_desc->endpoint[i].desc; - - if (!remote->in_endpoint && - (endpoint->bEndpointAddress & USB_DIR_IN) && - ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) { - /* we found our interrupt in endpoint */ - remote->in_endpoint = endpoint; - - remote->in_buffer = usb_buffer_alloc(remote->udev, RECV_SIZE, SLAB_ATOMIC, &remote->in_dma); - if (!remote->in_buffer) { - retval = -ENOMEM; - goto error; - } - } - } - - if (!remote->in_endpoint) { - err("Could not find interrupt input endpoint.\n"); - retval = -ENODEV; - goto error; + remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, SLAB_ATOMIC, &remote->in_dma); + if (!remote->in_buffer) { + retval = -ENOMEM; + goto fail1; } remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL); if (!remote->irq_urb) { - err("Failed to allocate urb.\n"); retval = -ENOMEM; - goto error; + goto fail2; } - retval = keyspan_setup(remote->udev); + retval = keyspan_setup(udev); if (retval) { - err("Failed to setup device.\n"); retval = -ENODEV; - goto error; - } - - /* - * Setup the input system with the bits we are going to be reporting - */ - remote->input.evbit[0] = BIT(EV_KEY); /* We will only report KEY events. */ - for (i = 0; i < 32; ++i) { - if (keyspan_key_table[i] != KEY_RESERVED) { - set_bit(keyspan_key_table[i], remote->input.keybit); - } + goto fail3; } - remote->input.private = remote; - remote->input.open = keyspan_open; - remote->input.close = keyspan_close; - - usb_make_path(remote->udev, path, 64); - sprintf(remote->phys, "%s/input0", path); + if (udev->manufacturer) + strlcpy(remote->name, udev->manufacturer, sizeof(remote->name)); - remote->input.name = remote->name; - remote->input.phys = remote->phys; - remote->input.id.bustype = BUS_USB; - remote->input.id.vendor = le16_to_cpu(remote->udev->descriptor.idVendor); - remote->input.id.product = le16_to_cpu(remote->udev->descriptor.idProduct); - remote->input.id.version = le16_to_cpu(remote->udev->descriptor.bcdDevice); - - if (!(buf = kmalloc(63, GFP_KERNEL))) { - usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma); - kfree(remote); - return -ENOMEM; + if (udev->product) { + if (udev->manufacturer) + strlcat(remote->name, " ", sizeof(remote->name)); + strlcat(remote->name, udev->product, sizeof(remote->name)); } - if (remote->udev->descriptor.iManufacturer && - usb_string(remote->udev, remote->udev->descriptor.iManufacturer, buf, 63) > 0) - strcat(remote->name, buf); + if (!strlen(remote->name)) + snprintf(remote->name, sizeof(remote->name), + "USB Keyspan Remote %04x:%04x", + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct)); - if (remote->udev->descriptor.iProduct && - usb_string(remote->udev, remote->udev->descriptor.iProduct, buf, 63) > 0) - sprintf(remote->name, "%s %s", remote->name, buf); + usb_make_path(udev, remote->phys, sizeof(remote->phys)); + strlcat(remote->phys, "/input0", sizeof(remote->phys)); - if (!strlen(remote->name)) - sprintf(remote->name, "USB Keyspan Remote %04x:%04x", - remote->input.id.vendor, remote->input.id.product); + input_dev->name = remote->name; + input_dev->phys = remote->phys; + usb_to_input_id(udev, &input_dev->id); + input_dev->cdev.dev = &interface->dev; - kfree(buf); + input_dev->evbit[0] = BIT(EV_KEY); /* We will only report KEY events. */ + for (i = 0; i < ARRAY_SIZE(keyspan_key_table); i++) + if (keyspan_key_table[i] != KEY_RESERVED) + set_bit(keyspan_key_table[i], input_dev->keybit); + + input_dev->private = remote; + input_dev->open = keyspan_open; + input_dev->close = keyspan_close; /* * Initialize the URB to access the device. The urb gets sent to the device in keyspan_open() @@ -538,27 +519,17 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* we can register the device now, as it is ready */ - input_register_device(&remote->input); + input_register_device(remote->input); /* save our data pointer in this interface device */ usb_set_intfdata(interface, remote); - /* let the user know what node this device is now attached to */ - info("connected: %s on %s", remote->name, path); return 0; -error: - /* - * In case of error we need to clean up any allocated buffers - */ - if (remote->irq_urb) - usb_free_urb(remote->irq_urb); - - if (remote->in_buffer) - usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma); - - if (remote) - kfree(remote); + fail3: usb_free_urb(remote->irq_urb); + fail2: usb_buffer_free(udev, RECV_SIZE, remote->in_buffer, remote->in_dma); + fail1: kfree(remote); + input_free_device(input_dev); return retval; } @@ -570,23 +541,16 @@ static void keyspan_disconnect(struct usb_interface *interface) { struct usb_keyspan *remote; - /* prevent keyspan_open() from racing keyspan_disconnect() */ - lock_kernel(); - remote = usb_get_intfdata(interface); usb_set_intfdata(interface, NULL); if (remote) { /* We have a valid driver structure so clean up everything we allocated. */ - input_unregister_device(&remote->input); + input_unregister_device(remote->input); usb_kill_urb(remote->irq_urb); usb_free_urb(remote->irq_urb); - usb_buffer_free(interface_to_usbdev(interface), RECV_SIZE, remote->in_buffer, remote->in_dma); + usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma); kfree(remote); } - - unlock_kernel(); - - info("USB Keyspan now disconnected"); } /* diff --git a/drivers/usb/input/map_to_7segment.h b/drivers/usb/input/map_to_7segment.h index 52ff27f..a424094 100644 --- a/drivers/usb/input/map_to_7segment.h +++ b/drivers/usb/input/map_to_7segment.h @@ -79,7 +79,7 @@ struct seg7_conversion_map { static inline int map_to_seg7(struct seg7_conversion_map *map, int c) { - return c & 0x7f ? map->table[c] : -EINVAL; + return c >= 0 && c < sizeof(map->table) ? map->table[c] : -EINVAL; } #define SEG7_CONVERSION_MAP(_name, _map) \ diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c index ff92750..7fce526 100644 --- a/drivers/usb/input/mtouchusb.c +++ b/drivers/usb/input/mtouchusb.c @@ -98,7 +98,7 @@ struct mtouch_usb { dma_addr_t data_dma; struct urb *irq; struct usb_device *udev; - struct input_dev input; + struct input_dev *input; char name[128]; char phys[64]; }; @@ -135,14 +135,14 @@ static void mtouchusb_irq(struct urb *urb, struct pt_regs *regs) goto exit; } - input_regs(&mtouch->input, regs); - input_report_key(&mtouch->input, BTN_TOUCH, + input_regs(mtouch->input, regs); + input_report_key(mtouch->input, BTN_TOUCH, MTOUCHUSB_GET_TOUCHED(mtouch->data)); - input_report_abs(&mtouch->input, ABS_X, MTOUCHUSB_GET_XC(mtouch->data)); - input_report_abs(&mtouch->input, ABS_Y, + input_report_abs(mtouch->input, ABS_X, MTOUCHUSB_GET_XC(mtouch->data)); + input_report_abs(mtouch->input, ABS_Y, (raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC) - MTOUCHUSB_GET_YC(mtouch->data)); - input_sync(&mtouch->input); + input_sync(mtouch->input); exit: retval = usb_submit_urb(urb, GFP_ATOMIC); @@ -195,10 +195,10 @@ static void mtouchusb_free_buffers(struct usb_device *udev, struct mtouch_usb *m static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct mtouch_usb *mtouch; + struct input_dev *input_dev; struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; struct usb_device *udev = interface_to_usbdev(intf); - char path[64]; int nRet; dbg("%s - called", __FUNCTION__); @@ -209,57 +209,55 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i dbg("%s - setting endpoint", __FUNCTION__); endpoint = &interface->endpoint[0].desc; - if (!(mtouch = kmalloc(sizeof(struct mtouch_usb), GFP_KERNEL))) { + mtouch = kzalloc(sizeof(struct mtouch_usb), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!mtouch || !input_dev) { err("%s - Out of memory.", __FUNCTION__); - return -ENOMEM; + goto fail1; } - memset(mtouch, 0, sizeof(struct mtouch_usb)); - mtouch->udev = udev; - dbg("%s - allocating buffers", __FUNCTION__); - if (mtouchusb_alloc_buffers(udev, mtouch)) { - mtouchusb_free_buffers(udev, mtouch); - kfree(mtouch); - return -ENOMEM; - } + if (mtouchusb_alloc_buffers(udev, mtouch)) + goto fail2; - mtouch->input.private = mtouch; - mtouch->input.open = mtouchusb_open; - mtouch->input.close = mtouchusb_close; - - usb_make_path(udev, path, 64); - sprintf(mtouch->phys, "%s/input0", path); - - mtouch->input.name = mtouch->name; - mtouch->input.phys = mtouch->phys; - usb_to_input_id(udev, &mtouch->input.id); - mtouch->input.dev = &intf->dev; - - mtouch->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - mtouch->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y); - mtouch->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); - - /* Used to Scale Compensated Data and Flip Y */ - mtouch->input.absmin[ABS_X] = MTOUCHUSB_MIN_XC; - mtouch->input.absmax[ABS_X] = raw_coordinates ? - MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC; - mtouch->input.absfuzz[ABS_X] = MTOUCHUSB_XC_FUZZ; - mtouch->input.absflat[ABS_X] = MTOUCHUSB_XC_FLAT; - mtouch->input.absmin[ABS_Y] = MTOUCHUSB_MIN_YC; - mtouch->input.absmax[ABS_Y] = raw_coordinates ? - MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC; - mtouch->input.absfuzz[ABS_Y] = MTOUCHUSB_YC_FUZZ; - mtouch->input.absflat[ABS_Y] = MTOUCHUSB_YC_FLAT; + mtouch->udev = udev; + mtouch->input = input_dev; if (udev->manufacturer) - strcat(mtouch->name, udev->manufacturer); - if (udev->product) - sprintf(mtouch->name, "%s %s", mtouch->name, udev->product); + strlcpy(mtouch->name, udev->manufacturer, sizeof(mtouch->name)); + + if (udev->product) { + if (udev->manufacturer) + strlcat(mtouch->name, " ", sizeof(mtouch->name)); + strlcat(mtouch->name, udev->product, sizeof(mtouch->name)); + } if (!strlen(mtouch->name)) - sprintf(mtouch->name, "USB Touchscreen %04x:%04x", - mtouch->input.id.vendor, mtouch->input.id.product); + snprintf(mtouch->name, sizeof(mtouch->name), + "USB Touchscreen %04x:%04x", + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct)); + + usb_make_path(udev, mtouch->phys, sizeof(mtouch->phys)); + strlcpy(mtouch->phys, "/input0", sizeof(mtouch->phys)); + + input_dev->name = mtouch->name; + input_dev->phys = mtouch->phys; + usb_to_input_id(udev, &input_dev->id); + input_dev->cdev.dev = &intf->dev; + input_dev->private = mtouch; + + input_dev->open = mtouchusb_open; + input_dev->close = mtouchusb_close; + + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); + input_set_abs_params(input_dev, ABS_X, MTOUCHUSB_MIN_XC, + raw_coordinates ? MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC, + MTOUCHUSB_XC_FUZZ, MTOUCHUSB_XC_FLAT); + input_set_abs_params(input_dev, ABS_Y, MTOUCHUSB_MIN_YC, + raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC, + MTOUCHUSB_YC_FUZZ, MTOUCHUSB_YC_FLAT); nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0), MTOUCHUSB_RESET, @@ -272,9 +270,7 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i mtouch->irq = usb_alloc_urb(0, GFP_KERNEL); if (!mtouch->irq) { dbg("%s - usb_alloc_urb failed: mtouch->irq", __FUNCTION__); - mtouchusb_free_buffers(udev, mtouch); - kfree(mtouch); - return -ENOMEM; + goto fail2; } dbg("%s - usb_fill_int_urb", __FUNCTION__); @@ -284,7 +280,7 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i mtouchusb_irq, mtouch, endpoint->bInterval); dbg("%s - input_register_device", __FUNCTION__); - input_register_device(&mtouch->input); + input_register_device(mtouch->input); nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0), MTOUCHUSB_ASYNC_REPORT, @@ -293,10 +289,13 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", __FUNCTION__, nRet); - printk(KERN_INFO "input: %s on %s\n", mtouch->name, path); usb_set_intfdata(intf, mtouch); - return 0; + +fail2: mtouchusb_free_buffers(udev, mtouch); +fail1: input_free_device(input_dev); + kfree(mtouch); + return -ENOMEM; } static void mtouchusb_disconnect(struct usb_interface *intf) @@ -308,7 +307,7 @@ static void mtouchusb_disconnect(struct usb_interface *intf) if (mtouch) { dbg("%s - mtouch is initialized, cleaning up", __FUNCTION__); usb_kill_urb(mtouch->irq); - input_unregister_device(&mtouch->input); + input_unregister_device(mtouch->input); usb_free_urb(mtouch->irq); mtouchusb_free_buffers(interface_to_usbdev(intf), mtouch); kfree(mtouch); diff --git a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c index acc71ec..dca5ee9 100644 --- a/drivers/usb/input/pid.c +++ b/drivers/usb/input/pid.c @@ -198,7 +198,7 @@ static int hid_pid_upload_effect(struct input_dev *dev, } effect->id = id; - dev_dbg(&pid_private->hid->dev->dev, "effect ID is %d\n.", id); + dev_dbg(&pid_private->hid->dev->dev, "effect ID is %d.\n", id); pid_private->effects[id].owner = current->pid; pid_private->effects[id].flags = (1 << FF_PID_FLAGS_USED); spin_unlock_irqrestore(&pid_private->lock, flags); @@ -262,6 +262,7 @@ int hid_pid_init(struct hid_device *hid) { struct hid_ff_pid *private; struct hid_input *hidinput = list_entry(&hid->inputs, struct hid_input, list); + struct input_dev *input_dev = hidinput->input; private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL); if (!private) @@ -281,11 +282,12 @@ int hid_pid_init(struct hid_device *hid) usb_fill_control_urb(private->urbffout, hid->dev, 0, (void *)&private->ffcr, private->ctrl_buffer, 8, hid_pid_ctrl_out, hid); - hidinput->input.upload_effect = hid_pid_upload_effect; - hidinput->input.flush = hid_pid_flush; - hidinput->input.ff_effects_max = 8; // A random default - set_bit(EV_FF, hidinput->input.evbit); - set_bit(EV_FF_STATUS, hidinput->input.evbit); + + input_dev->upload_effect = hid_pid_upload_effect; + input_dev->flush = hid_pid_flush; + input_dev->ff_effects_max = 8; // A random default + set_bit(EV_FF, input_dev->evbit); + set_bit(EV_FF_STATUS, input_dev->evbit); spin_lock_init(&private->lock); diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c index ad4afe7..b747623 100644 --- a/drivers/usb/input/powermate.c +++ b/drivers/usb/input/powermate.c @@ -68,7 +68,7 @@ struct powermate_device { struct usb_ctrlrequest *configcr; dma_addr_t configcr_dma; struct usb_device *udev; - struct input_dev input; + struct input_dev *input; spinlock_t lock; int static_brightness; int pulse_speed; @@ -106,10 +106,10 @@ static void powermate_irq(struct urb *urb, struct pt_regs *regs) } /* handle updates to device state */ - input_regs(&pm->input, regs); - input_report_key(&pm->input, BTN_0, pm->data[0] & 0x01); - input_report_rel(&pm->input, REL_DIAL, pm->data[1]); - input_sync(&pm->input); + input_regs(pm->input, regs); + input_report_key(pm->input, BTN_0, pm->data[0] & 0x01); + input_report_rel(pm->input, REL_DIAL, pm->data[1]); + input_sync(pm->input); exit: retval = usb_submit_urb (urb, GFP_ATOMIC); @@ -153,10 +153,10 @@ static void powermate_sync_state(struct powermate_device *pm) Only values of 'arg' quite close to 255 are particularly useful/spectacular. */ - if (pm->pulse_speed < 255){ + if (pm->pulse_speed < 255) { op = 0; // divide arg = 255 - pm->pulse_speed; - } else if (pm->pulse_speed > 255){ + } else if (pm->pulse_speed > 255) { op = 2; // multiply arg = pm->pulse_speed - 255; } else { @@ -166,11 +166,11 @@ static void powermate_sync_state(struct powermate_device *pm) pm->configcr->wValue = cpu_to_le16( (pm->pulse_table << 8) | SET_PULSE_MODE ); pm->configcr->wIndex = cpu_to_le16( (arg << 8) | op ); pm->requires_update &= ~UPDATE_PULSE_MODE; - }else if (pm->requires_update & UPDATE_STATIC_BRIGHTNESS){ + } else if (pm->requires_update & UPDATE_STATIC_BRIGHTNESS) { pm->configcr->wValue = cpu_to_le16( SET_STATIC_BRIGHTNESS ); pm->configcr->wIndex = cpu_to_le16( pm->static_brightness ); pm->requires_update &= ~UPDATE_STATIC_BRIGHTNESS; - }else{ + } else { printk(KERN_ERR "powermate: unknown update required"); pm->requires_update = 0; /* fudge the bug */ return; @@ -228,19 +228,19 @@ static void powermate_pulse_led(struct powermate_device *pm, int static_brightne spin_lock_irqsave(&pm->lock, flags); /* mark state updates which are required */ - if (static_brightness != pm->static_brightness){ + if (static_brightness != pm->static_brightness) { pm->static_brightness = static_brightness; pm->requires_update |= UPDATE_STATIC_BRIGHTNESS; } - if (pulse_asleep != pm->pulse_asleep){ + if (pulse_asleep != pm->pulse_asleep) { pm->pulse_asleep = pulse_asleep; pm->requires_update |= (UPDATE_PULSE_ASLEEP | UPDATE_STATIC_BRIGHTNESS); } - if (pulse_awake != pm->pulse_awake){ + if (pulse_awake != pm->pulse_awake) { pm->pulse_awake = pulse_awake; pm->requires_update |= (UPDATE_PULSE_AWAKE | UPDATE_STATIC_BRIGHTNESS); } - if (pulse_speed != pm->pulse_speed || pulse_table != pm->pulse_table){ + if (pulse_speed != pm->pulse_speed || pulse_table != pm->pulse_table) { pm->pulse_speed = pulse_speed; pm->pulse_table = pulse_table; pm->requires_update |= UPDATE_PULSE_MODE; @@ -283,6 +283,7 @@ static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_dev SLAB_ATOMIC, &pm->data_dma); if (!pm->data) return -1; + pm->configcr = usb_buffer_alloc(udev, sizeof(*(pm->configcr)), SLAB_ATOMIC, &pm->configcr_dma); if (!pm->configcr) @@ -308,8 +309,9 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; struct powermate_device *pm; + struct input_dev *input_dev; int pipe, maxp; - char path[64]; + int err = -ENOMEM; interface = intf->cur_altsetting; endpoint = &interface->endpoint[0].desc; @@ -323,42 +325,61 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i 0, interface->desc.bInterfaceNumber, NULL, 0, USB_CTRL_SET_TIMEOUT); - if (!(pm = kmalloc(sizeof(struct powermate_device), GFP_KERNEL))) - return -ENOMEM; - - memset(pm, 0, sizeof(struct powermate_device)); - pm->udev = udev; + pm = kzalloc(sizeof(struct powermate_device), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!pm || !input_dev) + goto fail1; - if (powermate_alloc_buffers(udev, pm)) { - powermate_free_buffers(udev, pm); - kfree(pm); - return -ENOMEM; - } + if (powermate_alloc_buffers(udev, pm)) + goto fail2; pm->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!pm->irq) { - powermate_free_buffers(udev, pm); - kfree(pm); - return -ENOMEM; - } + if (!pm->irq) + goto fail2; pm->config = usb_alloc_urb(0, GFP_KERNEL); - if (!pm->config) { - usb_free_urb(pm->irq); - powermate_free_buffers(udev, pm); - kfree(pm); - return -ENOMEM; - } + if (!pm->config) + goto fail3; + + pm->udev = udev; + pm->input = input_dev; + + usb_make_path(udev, pm->phys, sizeof(pm->phys)); + strlcpy(pm->phys, "/input0", sizeof(pm->phys)); spin_lock_init(&pm->lock); - init_input_dev(&pm->input); + + switch (le16_to_cpu(udev->descriptor.idProduct)) { + case POWERMATE_PRODUCT_NEW: + input_dev->name = pm_name_powermate; + break; + case POWERMATE_PRODUCT_OLD: + input_dev->name = pm_name_soundknob; + break; + default: + input_dev->name = pm_name_soundknob; + printk(KERN_WARNING "powermate: unknown product id %04x\n", + le16_to_cpu(udev->descriptor.idProduct)); + } + + input_dev->phys = pm->phys; + usb_to_input_id(udev, &input_dev->id); + input_dev->cdev.dev = &intf->dev; + input_dev->private = pm; + + input_dev->event = powermate_input_event; + + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_MSC); + input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0); + input_dev->relbit[LONG(REL_DIAL)] = BIT(REL_DIAL); + input_dev->mscbit[LONG(MSC_PULSELED)] = BIT(MSC_PULSELED); /* get a handle to the interrupt data pipe */ pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); - if(maxp < POWERMATE_PAYLOAD_SIZE_MIN || maxp > POWERMATE_PAYLOAD_SIZE_MAX){ - printk("powermate: Expected payload of %d--%d bytes, found %d bytes!\n", + if (maxp < POWERMATE_PAYLOAD_SIZE_MIN || maxp > POWERMATE_PAYLOAD_SIZE_MAX) { + printk(KERN_WARNING "powermate: Expected payload of %d--%d bytes, found %d bytes!\n", POWERMATE_PAYLOAD_SIZE_MIN, POWERMATE_PAYLOAD_SIZE_MAX, maxp); maxp = POWERMATE_PAYLOAD_SIZE_MAX; } @@ -371,35 +392,11 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i /* register our interrupt URB with the USB system */ if (usb_submit_urb(pm->irq, GFP_KERNEL)) { - powermate_free_buffers(udev, pm); - kfree(pm); - return -EIO; /* failure */ + err = -EIO; + goto fail4; } - switch (le16_to_cpu(udev->descriptor.idProduct)) { - case POWERMATE_PRODUCT_NEW: pm->input.name = pm_name_powermate; break; - case POWERMATE_PRODUCT_OLD: pm->input.name = pm_name_soundknob; break; - default: - pm->input.name = pm_name_soundknob; - printk(KERN_WARNING "powermate: unknown product id %04x\n", - le16_to_cpu(udev->descriptor.idProduct)); - } - - pm->input.private = pm; - pm->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_MSC); - pm->input.keybit[LONG(BTN_0)] = BIT(BTN_0); - pm->input.relbit[LONG(REL_DIAL)] = BIT(REL_DIAL); - pm->input.mscbit[LONG(MSC_PULSELED)] = BIT(MSC_PULSELED); - usb_to_input_id(udev, &pm->input.id); - pm->input.event = powermate_input_event; - pm->input.dev = &intf->dev; - pm->input.phys = pm->phys; - - input_register_device(&pm->input); - - usb_make_path(udev, path, 64); - snprintf(pm->phys, 64, "%s/input0", path); - printk(KERN_INFO "input: %s on %s\n", pm->input.name, pm->input.phys); + input_register_device(pm->input); /* force an update of everything */ pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS; @@ -407,6 +404,13 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i usb_set_intfdata(intf, pm); return 0; + +fail4: usb_free_urb(pm->config); +fail3: usb_free_urb(pm->irq); +fail2: powermate_free_buffers(udev, pm); +fail1: input_free_device(input_dev); + kfree(pm); + return err; } /* Called when a USB device we've accepted ownership of is removed */ @@ -418,7 +422,7 @@ static void powermate_disconnect(struct usb_interface *intf) if (pm) { pm->requires_update = 0; usb_kill_urb(pm->irq); - input_unregister_device(&pm->input); + input_unregister_device(pm->input); usb_free_urb(pm->irq); usb_free_urb(pm->config); powermate_free_buffers(interface_to_usbdev(intf), pm); diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c index 4276c24..0043e6e 100644 --- a/drivers/usb/input/touchkitusb.c +++ b/drivers/usb/input/touchkitusb.c @@ -68,14 +68,16 @@ struct touchkit_usb { dma_addr_t data_dma; struct urb *irq; struct usb_device *udev; - struct input_dev input; + struct input_dev *input; char name[128]; char phys[64]; }; static struct usb_device_id touchkit_devices[] = { {USB_DEVICE(0x3823, 0x0001)}, + {USB_DEVICE(0x0123, 0x0001)}, {USB_DEVICE(0x0eef, 0x0001)}, + {USB_DEVICE(0x0eef, 0x0002)}, {} }; @@ -115,12 +117,12 @@ static void touchkit_irq(struct urb *urb, struct pt_regs *regs) y = TOUCHKIT_GET_Y(touchkit->data); } - input_regs(&touchkit->input, regs); - input_report_key(&touchkit->input, BTN_TOUCH, + input_regs(touchkit->input, regs); + input_report_key(touchkit->input, BTN_TOUCH, TOUCHKIT_GET_TOUCHED(touchkit->data)); - input_report_abs(&touchkit->input, ABS_X, x); - input_report_abs(&touchkit->input, ABS_Y, y); - input_sync(&touchkit->input); + input_report_abs(touchkit->input, ABS_X, x); + input_report_abs(touchkit->input, ABS_Y, y); + input_sync(touchkit->input); exit: retval = usb_submit_urb(urb, GFP_ATOMIC); @@ -171,87 +173,81 @@ static void touchkit_free_buffers(struct usb_device *udev, static int touchkit_probe(struct usb_interface *intf, const struct usb_device_id *id) { - int ret; struct touchkit_usb *touchkit; + struct input_dev *input_dev; struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; struct usb_device *udev = interface_to_usbdev(intf); - char path[64]; interface = intf->cur_altsetting; endpoint = &interface->endpoint[0].desc; - touchkit = kmalloc(sizeof(struct touchkit_usb), GFP_KERNEL); - if (!touchkit) - return -ENOMEM; - - memset(touchkit, 0, sizeof(struct touchkit_usb)); - touchkit->udev = udev; - - if (touchkit_alloc_buffers(udev, touchkit)) { - ret = -ENOMEM; + touchkit = kzalloc(sizeof(struct touchkit_usb), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!touchkit || !input_dev) goto out_free; - } - - touchkit->input.private = touchkit; - touchkit->input.open = touchkit_open; - touchkit->input.close = touchkit_close; - - usb_make_path(udev, path, 64); - sprintf(touchkit->phys, "%s/input0", path); - - touchkit->input.name = touchkit->name; - touchkit->input.phys = touchkit->phys; - usb_to_input_id(udev, &touchkit->input.id); - touchkit->input.dev = &intf->dev; - - touchkit->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - touchkit->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y); - touchkit->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); - - /* Used to Scale Compensated Data */ - touchkit->input.absmin[ABS_X] = TOUCHKIT_MIN_XC; - touchkit->input.absmax[ABS_X] = TOUCHKIT_MAX_XC; - touchkit->input.absfuzz[ABS_X] = TOUCHKIT_XC_FUZZ; - touchkit->input.absflat[ABS_X] = TOUCHKIT_XC_FLAT; - touchkit->input.absmin[ABS_Y] = TOUCHKIT_MIN_YC; - touchkit->input.absmax[ABS_Y] = TOUCHKIT_MAX_YC; - touchkit->input.absfuzz[ABS_Y] = TOUCHKIT_YC_FUZZ; - touchkit->input.absflat[ABS_Y] = TOUCHKIT_YC_FLAT; - - if (udev->manufacturer) - strcat(touchkit->name, udev->manufacturer); - if (udev->product) - sprintf(touchkit->name, "%s %s", touchkit->name, udev->product); - if (!strlen(touchkit->name)) - sprintf(touchkit->name, "USB Touchscreen %04x:%04x", - touchkit->input.id.vendor, touchkit->input.id.product); + if (touchkit_alloc_buffers(udev, touchkit)) + goto out_free; touchkit->irq = usb_alloc_urb(0, GFP_KERNEL); if (!touchkit->irq) { dbg("%s - usb_alloc_urb failed: touchkit->irq", __FUNCTION__); - ret = -ENOMEM; goto out_free_buffers; } + touchkit->udev = udev; + touchkit->input = input_dev; + + if (udev->manufacturer) + strlcpy(touchkit->name, udev->manufacturer, sizeof(touchkit->name)); + + if (udev->product) { + if (udev->manufacturer) + strlcat(touchkit->name, " ", sizeof(touchkit->name)); + strlcat(touchkit->name, udev->product, sizeof(touchkit->name)); + } + + if (!strlen(touchkit->name)) + snprintf(touchkit->name, sizeof(touchkit->name), + "USB Touchscreen %04x:%04x", + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct)); + + usb_make_path(udev, touchkit->phys, sizeof(touchkit->phys)); + strlcpy(touchkit->phys, "/input0", sizeof(touchkit->phys)); + + input_dev->name = touchkit->name; + input_dev->phys = touchkit->phys; + usb_to_input_id(udev, &input_dev->id); + input_dev->cdev.dev = &intf->dev; + input_dev->private = touchkit; + input_dev->open = touchkit_open; + input_dev->close = touchkit_close; + + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); + input_set_abs_params(input_dev, ABS_X, TOUCHKIT_MIN_XC, TOUCHKIT_MAX_XC, + TOUCHKIT_XC_FUZZ, TOUCHKIT_XC_FLAT); + input_set_abs_params(input_dev, ABS_Y, TOUCHKIT_MIN_YC, TOUCHKIT_MAX_YC, + TOUCHKIT_YC_FUZZ, TOUCHKIT_YC_FLAT); + usb_fill_int_urb(touchkit->irq, touchkit->udev, - usb_rcvintpipe(touchkit->udev, 0x81), - touchkit->data, TOUCHKIT_REPORT_DATA_SIZE, - touchkit_irq, touchkit, endpoint->bInterval); + usb_rcvintpipe(touchkit->udev, 0x81), + touchkit->data, TOUCHKIT_REPORT_DATA_SIZE, + touchkit_irq, touchkit, endpoint->bInterval); - input_register_device(&touchkit->input); + input_register_device(touchkit->input); - printk(KERN_INFO "input: %s on %s\n", touchkit->name, path); usb_set_intfdata(intf, touchkit); - return 0; out_free_buffers: touchkit_free_buffers(udev, touchkit); out_free: + input_free_device(input_dev); kfree(touchkit); - return ret; + return -ENOMEM; } static void touchkit_disconnect(struct usb_interface *intf) @@ -265,8 +261,8 @@ static void touchkit_disconnect(struct usb_interface *intf) dbg("%s - touchkit is initialized, cleaning up", __FUNCTION__); usb_set_intfdata(intf, NULL); - input_unregister_device(&touchkit->input); usb_kill_urb(touchkit->irq); + input_unregister_device(touchkit->input); usb_free_urb(touchkit->irq); touchkit_free_buffers(interface_to_usbdev(intf), touchkit); kfree(touchkit); diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c index 28987f1..226b6f9 100644 --- a/drivers/usb/input/usbkbd.c +++ b/drivers/usb/input/usbkbd.c @@ -66,7 +66,7 @@ static unsigned char usb_kbd_keycode[256] = { }; struct usb_kbd { - struct input_dev dev; + struct input_dev *dev; struct usb_device *usbdev; unsigned char old[8]; struct urb *irq, *led; @@ -99,29 +99,29 @@ static void usb_kbd_irq(struct urb *urb, struct pt_regs *regs) goto resubmit; } - input_regs(&kbd->dev, regs); + input_regs(kbd->dev, regs); for (i = 0; i < 8; i++) - input_report_key(&kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1); + input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1); for (i = 2; i < 8; i++) { if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) { if (usb_kbd_keycode[kbd->old[i]]) - input_report_key(&kbd->dev, usb_kbd_keycode[kbd->old[i]], 0); + input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0); else info("Unknown key (scancode %#x) released.", kbd->old[i]); } if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) { if (usb_kbd_keycode[kbd->new[i]]) - input_report_key(&kbd->dev, usb_kbd_keycode[kbd->new[i]], 1); + input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1); else info("Unknown key (scancode %#x) pressed.", kbd->new[i]); } } - input_sync(&kbd->dev); + input_sync(kbd->dev); memcpy(kbd->old, kbd->new, 8); @@ -227,12 +227,12 @@ static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd) static int usb_kbd_probe(struct usb_interface *iface, const struct usb_device_id *id) { - struct usb_device * dev = interface_to_usbdev(iface); + struct usb_device *dev = interface_to_usbdev(iface); struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; struct usb_kbd *kbd; + struct input_dev *input_dev; int i, pipe, maxp; - char path[64]; interface = iface->cur_altsetting; @@ -240,37 +240,59 @@ static int usb_kbd_probe(struct usb_interface *iface, return -ENODEV; endpoint = &interface->endpoint[0].desc; - if (!(endpoint->bEndpointAddress & 0x80)) + if (!(endpoint->bEndpointAddress & USB_DIR_IN)) return -ENODEV; - if ((endpoint->bmAttributes & 3) != 3) + if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) return -ENODEV; pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) - return -ENOMEM; - memset(kbd, 0, sizeof(struct usb_kbd)); + kbd = kzalloc(sizeof(struct usb_kbd), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!kbd || !input_dev) + goto fail1; - if (usb_kbd_alloc_mem(dev, kbd)) { - usb_kbd_free_mem(dev, kbd); - kfree(kbd); - return -ENOMEM; - } + if (usb_kbd_alloc_mem(dev, kbd)) + goto fail2; kbd->usbdev = dev; + kbd->dev = input_dev; + + if (dev->manufacturer) + strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name)); + + if (dev->product) { + if (dev->manufacturer) + strlcat(kbd->name, " ", sizeof(kbd->name)); + strlcat(kbd->name, dev->product, sizeof(kbd->name)); + } + + if (!strlen(kbd->name)) + snprintf(kbd->name, sizeof(kbd->name), + "USB HIDBP Keyboard %04x:%04x", + le16_to_cpu(dev->descriptor.idVendor), + le16_to_cpu(dev->descriptor.idProduct)); + + usb_make_path(dev, kbd->phys, sizeof(kbd->phys)); + strlcpy(kbd->phys, "/input0", sizeof(kbd->phys)); - kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP); - kbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA); + input_dev->name = kbd->name; + input_dev->phys = kbd->phys; + usb_to_input_id(dev, &input_dev->id); + input_dev->cdev.dev = &iface->dev; + input_dev->private = kbd; + + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP); + input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA); for (i = 0; i < 255; i++) - set_bit(usb_kbd_keycode[i], kbd->dev.keybit); - clear_bit(0, kbd->dev.keybit); + set_bit(usb_kbd_keycode[i], input_dev->keybit); + clear_bit(0, input_dev->keybit); - kbd->dev.private = kbd; - kbd->dev.event = usb_kbd_event; - kbd->dev.open = usb_kbd_open; - kbd->dev.close = usb_kbd_close; + input_dev->event = usb_kbd_event; + input_dev->open = usb_kbd_open; + input_dev->close = usb_kbd_close; usb_fill_int_urb(kbd->irq, dev, pipe, kbd->new, (maxp > 8 ? 8 : maxp), @@ -284,37 +306,22 @@ static int usb_kbd_probe(struct usb_interface *iface, kbd->cr->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber); kbd->cr->wLength = cpu_to_le16(1); - usb_make_path(dev, path, 64); - sprintf(kbd->phys, "%s/input0", path); - - kbd->dev.name = kbd->name; - kbd->dev.phys = kbd->phys; - usb_to_input_id(dev, &kbd->dev.id); - kbd->dev.dev = &iface->dev; - - if (dev->manufacturer) - strcat(kbd->name, dev->manufacturer); - if (dev->product) - sprintf(kbd->name, "%s %s", kbd->name, dev->product); - - if (!strlen(kbd->name)) - sprintf(kbd->name, "USB HIDBP Keyboard %04x:%04x", - kbd->dev.id.vendor, kbd->dev.id.product); - usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0), (void *) kbd->cr, kbd->leds, 1, usb_kbd_led, kbd); kbd->led->setup_dma = kbd->cr_dma; kbd->led->transfer_dma = kbd->leds_dma; - kbd->led->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP - | URB_NO_SETUP_DMA_MAP); + kbd->led->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); - input_register_device(&kbd->dev); - - printk(KERN_INFO "input: %s on %s\n", kbd->name, path); + input_register_device(kbd->dev); usb_set_intfdata(iface, kbd); return 0; + +fail2: usb_kbd_free_mem(dev, kbd); +fail1: input_free_device(input_dev); + kfree(kbd); + return -ENOMEM; } static void usb_kbd_disconnect(struct usb_interface *intf) @@ -324,7 +331,7 @@ static void usb_kbd_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); if (kbd) { usb_kill_urb(kbd->irq); - input_unregister_device(&kbd->dev); + input_unregister_device(kbd->dev); usb_kbd_free_mem(interface_to_usbdev(intf), kbd); kfree(kbd); } diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c index 4104dec..230f6b1 100644 --- a/drivers/usb/input/usbmouse.c +++ b/drivers/usb/input/usbmouse.c @@ -50,7 +50,7 @@ struct usb_mouse { char name[128]; char phys[64]; struct usb_device *usbdev; - struct input_dev dev; + struct input_dev *dev; struct urb *irq; signed char *data; @@ -61,7 +61,7 @@ static void usb_mouse_irq(struct urb *urb, struct pt_regs *regs) { struct usb_mouse *mouse = urb->context; signed char *data = mouse->data; - struct input_dev *dev = &mouse->dev; + struct input_dev *dev = mouse->dev; int status; switch (urb->status) { @@ -115,14 +115,14 @@ static void usb_mouse_close(struct input_dev *dev) usb_kill_urb(mouse->irq); } -static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_id * id) +static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id) { - struct usb_device * dev = interface_to_usbdev(intf); + struct usb_device *dev = interface_to_usbdev(intf); struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; struct usb_mouse *mouse; + struct input_dev *input_dev; int pipe, maxp; - char path[64]; interface = intf->cur_altsetting; @@ -130,59 +130,62 @@ static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_ return -ENODEV; endpoint = &interface->endpoint[0].desc; - if (!(endpoint->bEndpointAddress & 0x80)) + if (!(endpoint->bEndpointAddress & USB_DIR_IN)) return -ENODEV; - if ((endpoint->bmAttributes & 3) != 3) + if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) return -ENODEV; pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) - return -ENOMEM; - memset(mouse, 0, sizeof(struct usb_mouse)); + mouse = kzalloc(sizeof(struct usb_mouse), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!mouse || !input_dev) + goto fail1; mouse->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &mouse->data_dma); - if (!mouse->data) { - kfree(mouse); - return -ENOMEM; - } + if (!mouse->data) + goto fail1; mouse->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!mouse->irq) { - usb_buffer_free(dev, 8, mouse->data, mouse->data_dma); - kfree(mouse); - return -ENODEV; - } + if (!mouse->irq) + goto fail2; mouse->usbdev = dev; + mouse->dev = input_dev; + + if (dev->manufacturer) + strlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name)); - mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); - mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); - mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); - mouse->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA); - mouse->dev.relbit[0] |= BIT(REL_WHEEL); + if (dev->product) { + if (dev->manufacturer) + strlcat(mouse->name, " ", sizeof(mouse->name)); + strlcat(mouse->name, dev->product, sizeof(mouse->name)); + } - mouse->dev.private = mouse; - mouse->dev.open = usb_mouse_open; - mouse->dev.close = usb_mouse_close; + if (!strlen(mouse->name)) + snprintf(mouse->name, sizeof(mouse->name), + "USB HIDBP Mouse %04x:%04x", + le16_to_cpu(dev->descriptor.idVendor), + le16_to_cpu(dev->descriptor.idProduct)); - usb_make_path(dev, path, 64); - sprintf(mouse->phys, "%s/input0", path); + usb_make_path(dev, mouse->phys, sizeof(mouse->phys)); + strlcat(mouse->phys, "/input0", sizeof(mouse->phys)); - mouse->dev.name = mouse->name; - mouse->dev.phys = mouse->phys; - usb_to_input_id(dev, &mouse->dev.id); - mouse->dev.dev = &intf->dev; + input_dev->name = mouse->name; + input_dev->phys = mouse->phys; + usb_to_input_id(dev, &input_dev->id); + input_dev->cdev.dev = &intf->dev; - if (dev->manufacturer) - strcat(mouse->name, dev->manufacturer); - if (dev->product) - sprintf(mouse->name, "%s %s", mouse->name, dev->product); + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); + input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); + input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y); + input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA); + input_dev->relbit[0] |= BIT(REL_WHEEL); - if (!strlen(mouse->name)) - sprintf(mouse->name, "USB HIDBP Mouse %04x:%04x", - mouse->dev.id.vendor, mouse->dev.id.product); + input_dev->private = mouse; + input_dev->open = usb_mouse_open; + input_dev->close = usb_mouse_close; usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data, (maxp > 8 ? 8 : maxp), @@ -190,11 +193,15 @@ static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_ mouse->irq->transfer_dma = mouse->data_dma; mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - input_register_device(&mouse->dev); - printk(KERN_INFO "input: %s on %s\n", mouse->name, path); + input_register_device(mouse->dev); usb_set_intfdata(intf, mouse); return 0; + +fail2: usb_buffer_free(dev, 8, mouse->data, mouse->data_dma); +fail1: input_free_device(input_dev); + kfree(mouse); + return -ENOMEM; } static void usb_mouse_disconnect(struct usb_interface *intf) @@ -204,7 +211,7 @@ static void usb_mouse_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); if (mouse) { usb_kill_urb(mouse->irq); - input_unregister_device(&mouse->dev); + input_unregister_device(mouse->dev); usb_free_urb(mouse->irq); usb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma); kfree(mouse); diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c index 3b266af..ea0f757 100644 --- a/drivers/usb/input/wacom.c +++ b/drivers/usb/input/wacom.c @@ -111,7 +111,7 @@ struct wacom_features { struct wacom { signed char *data; dma_addr_t data_dma; - struct input_dev dev; + struct input_dev *dev; struct usb_device *usbdev; struct urb *irq; struct wacom_features *features; @@ -135,7 +135,7 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) { struct wacom *wacom = urb->context; unsigned char *data = wacom->data; - struct input_dev *dev = &wacom->dev; + struct input_dev *dev = wacom->dev; int prox, pressure; int retval; @@ -225,7 +225,7 @@ static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs) { struct wacom *wacom = urb->context; unsigned char *data = wacom->data; - struct input_dev *dev = &wacom->dev; + struct input_dev *dev = wacom->dev; int retval; switch (urb->status) { @@ -275,7 +275,7 @@ static void wacom_penpartner_irq(struct urb *urb, struct pt_regs *regs) { struct wacom *wacom = urb->context; unsigned char *data = wacom->data; - struct input_dev *dev = &wacom->dev; + struct input_dev *dev = wacom->dev; int retval; switch (urb->status) { @@ -318,7 +318,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) { struct wacom *wacom = urb->context; unsigned char *data = wacom->data; - struct input_dev *dev = &wacom->dev; + struct input_dev *dev = wacom->dev; int x, y; int retval; @@ -397,7 +397,7 @@ static int wacom_intuos_inout(struct urb *urb) { struct wacom *wacom = urb->context; unsigned char *data = wacom->data; - struct input_dev *dev = &wacom->dev; + struct input_dev *dev = wacom->dev; int idx; /* tool number */ @@ -479,7 +479,7 @@ static void wacom_intuos_general(struct urb *urb) { struct wacom *wacom = urb->context; unsigned char *data = wacom->data; - struct input_dev *dev = &wacom->dev; + struct input_dev *dev = wacom->dev; unsigned int t; /* general pen packet */ @@ -509,7 +509,7 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) { struct wacom *wacom = urb->context; unsigned char *data = wacom->data; - struct input_dev *dev = &wacom->dev; + struct input_dev *dev = wacom->dev; unsigned int t; int idx; int retval; @@ -738,95 +738,83 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i { struct usb_device *dev = interface_to_usbdev(intf); struct usb_endpoint_descriptor *endpoint; - char rep_data[2] = {0x02, 0x02}; struct wacom *wacom; - char path[64]; + struct input_dev *input_dev; + char rep_data[2] = {0x02, 0x02}; - if (!(wacom = kmalloc(sizeof(struct wacom), GFP_KERNEL))) - return -ENOMEM; - memset(wacom, 0, sizeof(struct wacom)); + wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!wacom || !input_dev) + goto fail1; wacom->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma); - if (!wacom->data) { - kfree(wacom); - return -ENOMEM; - } + if (!wacom->data) + goto fail1; wacom->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!wacom->irq) { - usb_buffer_free(dev, 10, wacom->data, wacom->data_dma); - kfree(wacom); - return -ENOMEM; - } + if (!wacom->irq) + goto fail2; + + wacom->usbdev = dev; + wacom->dev = input_dev; + usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); + strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); wacom->features = wacom_features + (id - wacom_ids); + if (wacom->features->pktlen > 10) + BUG(); + + input_dev->name = wacom->features->name; + usb_to_input_id(dev, &input_dev->id); - wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS); - wacom->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); - wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS); + input_dev->cdev.dev = &intf->dev; + input_dev->private = wacom; + input_dev->open = wacom_open; + input_dev->close = wacom_close; + + input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS); + input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS); + input_set_abs_params(input_dev, ABS_X, 0, wacom->features->y_max, 4, 0); + input_set_abs_params(input_dev, ABS_Y, 0, wacom->features->y_max, 4, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0); switch (wacom->features->type) { case GRAPHIRE: - wacom->dev.evbit[0] |= BIT(EV_REL); - wacom->dev.relbit[0] |= BIT(REL_WHEEL); - wacom->dev.absbit[0] |= BIT(ABS_DISTANCE); - wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); - wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2); + input_dev->evbit[0] |= BIT(EV_REL); + input_dev->relbit[0] |= BIT(REL_WHEEL); + input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); + input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2); + input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom->features->distance_max, 0, 0); break; case INTUOS3: case CINTIQ: - wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); - wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7); - wacom->dev.absbit[0] |= BIT(ABS_RX) | BIT(ABS_RY); + input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); + input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7); + input_set_abs_params(input_dev, ABS_RX, 0, 4097, 0, 0); + input_set_abs_params(input_dev, ABS_RY, 0, 4097, 0, 0); /* fall through */ case INTUOS: - wacom->dev.evbit[0] |= BIT(EV_MSC) | BIT(EV_REL); - wacom->dev.mscbit[0] |= BIT(MSC_SERIAL); - wacom->dev.relbit[0] |= BIT(REL_WHEEL); - wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA); - wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH) + input_dev->evbit[0] |= BIT(EV_MSC) | BIT(EV_REL); + input_dev->mscbit[0] |= BIT(MSC_SERIAL); + input_dev->relbit[0] |= BIT(REL_WHEEL); + input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA); + input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH) | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2); - wacom->dev.absbit[0] |= BIT(ABS_DISTANCE) | BIT(ABS_WHEEL) | BIT(ABS_TILT_X) | BIT(ABS_TILT_Y) | BIT(ABS_RZ) | BIT(ABS_THROTTLE); + input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom->features->distance_max, 0, 0); + input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0); + input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0); + input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0); + input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0); + input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0); break; case PL: - wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER); + input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER); break; } - wacom->dev.absmax[ABS_X] = wacom->features->x_max; - wacom->dev.absmax[ABS_Y] = wacom->features->y_max; - wacom->dev.absmax[ABS_PRESSURE] = wacom->features->pressure_max; - wacom->dev.absmax[ABS_DISTANCE] = wacom->features->distance_max; - wacom->dev.absmax[ABS_TILT_X] = 127; - wacom->dev.absmax[ABS_TILT_Y] = 127; - wacom->dev.absmax[ABS_WHEEL] = 1023; - - wacom->dev.absmax[ABS_RX] = 4097; - wacom->dev.absmax[ABS_RY] = 4097; - wacom->dev.absmin[ABS_RZ] = -900; - wacom->dev.absmax[ABS_RZ] = 899; - wacom->dev.absmin[ABS_THROTTLE] = -1023; - wacom->dev.absmax[ABS_THROTTLE] = 1023; - - wacom->dev.absfuzz[ABS_X] = 4; - wacom->dev.absfuzz[ABS_Y] = 4; - - wacom->dev.private = wacom; - wacom->dev.open = wacom_open; - wacom->dev.close = wacom_close; - - usb_make_path(dev, path, 64); - sprintf(wacom->phys, "%s/input0", path); - - wacom->dev.name = wacom->features->name; - wacom->dev.phys = wacom->phys; - usb_to_input_id(dev, &wacom->dev.id); - wacom->dev.dev = &intf->dev; - wacom->usbdev = dev; - endpoint = &intf->cur_altsetting->endpoint[0].desc; if (wacom->features->pktlen > 10) @@ -839,18 +827,20 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i wacom->irq->transfer_dma = wacom->data_dma; wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - input_register_device(&wacom->dev); + input_register_device(wacom->dev); /* ask the tablet to report tablet data */ usb_set_report(intf, 3, 2, rep_data, 2); /* repeat once (not sure why the first call often fails) */ usb_set_report(intf, 3, 2, rep_data, 2); - printk(KERN_INFO "input: %s on %s\n", wacom->features->name, path); - usb_set_intfdata(intf, wacom); - return 0; + +fail2: usb_buffer_free(dev, 10, wacom->data, wacom->data_dma); +fail1: input_free_device(input_dev); + kfree(wacom); + return -ENOMEM; } static void wacom_disconnect(struct usb_interface *intf) @@ -860,7 +850,7 @@ static void wacom_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); if (wacom) { usb_kill_urb(wacom->irq); - input_unregister_device(&wacom->dev); + input_unregister_device(wacom->dev); usb_free_urb(wacom->irq); usb_buffer_free(interface_to_usbdev(intf), 10, wacom->data, wacom->data_dma); kfree(wacom); diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c index 18125e0..43112f0 100644 --- a/drivers/usb/input/xpad.c +++ b/drivers/usb/input/xpad.c @@ -103,7 +103,7 @@ static struct usb_device_id xpad_table [] = { MODULE_DEVICE_TABLE (usb, xpad_table); struct usb_xpad { - struct input_dev dev; /* input device interface */ + struct input_dev *dev; /* input device interface */ struct usb_device *udev; /* usb device */ struct urb *irq_in; /* urb for interrupt in report */ @@ -125,7 +125,7 @@ struct usb_xpad { static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data, struct pt_regs *regs) { - struct input_dev *dev = &xpad->dev; + struct input_dev *dev = xpad->dev; input_regs(dev, regs); @@ -214,9 +214,9 @@ static void xpad_close (struct input_dev *dev) static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev (intf); - struct usb_xpad *xpad = NULL; + struct usb_xpad *xpad; + struct input_dev *input_dev; struct usb_endpoint_descriptor *ep_irq_in; - char path[64]; int i; for (i = 0; xpad_device[i].idVendor; i++) { @@ -225,89 +225,80 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id break; } - if ((xpad = kmalloc (sizeof(struct usb_xpad), GFP_KERNEL)) == NULL) { - err("cannot allocate memory for new pad"); - return -ENOMEM; - } - memset(xpad, 0, sizeof(struct usb_xpad)); + xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!xpad || !input_dev) + goto fail1; xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN, SLAB_ATOMIC, &xpad->idata_dma); - if (!xpad->idata) { - kfree(xpad); - return -ENOMEM; - } + if (!xpad->idata) + goto fail1; xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL); - if (!xpad->irq_in) { - err("cannot allocate memory for new pad irq urb"); - usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); - kfree(xpad); - return -ENOMEM; - } - - ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; - - usb_fill_int_urb(xpad->irq_in, udev, - usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), - xpad->idata, XPAD_PKT_LEN, xpad_irq_in, - xpad, ep_irq_in->bInterval); - xpad->irq_in->transfer_dma = xpad->idata_dma; - xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + if (!xpad->irq_in) + goto fail2; xpad->udev = udev; + xpad->dev = input_dev; + usb_make_path(udev, xpad->phys, sizeof(xpad->phys)); + strlcat(xpad->phys, "/input0", sizeof(xpad->phys)); - usb_to_input_id(udev, &xpad->dev.id); - xpad->dev.dev = &intf->dev; - xpad->dev.private = xpad; - xpad->dev.name = xpad_device[i].name; - xpad->dev.phys = xpad->phys; - xpad->dev.open = xpad_open; - xpad->dev.close = xpad_close; - - usb_make_path(udev, path, 64); - snprintf(xpad->phys, 64, "%s/input0", path); + input_dev->name = xpad_device[i].name; + input_dev->phys = xpad->phys; + usb_to_input_id(udev, &input_dev->id); + input_dev->cdev.dev = &intf->dev; + input_dev->private = xpad; + input_dev->open = xpad_open; + input_dev->close = xpad_close; - xpad->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); for (i = 0; xpad_btn[i] >= 0; i++) - set_bit(xpad_btn[i], xpad->dev.keybit); + set_bit(xpad_btn[i], input_dev->keybit); for (i = 0; xpad_abs[i] >= 0; i++) { signed short t = xpad_abs[i]; - set_bit(t, xpad->dev.absbit); + set_bit(t, input_dev->absbit); switch (t) { case ABS_X: case ABS_Y: case ABS_RX: case ABS_RY: /* the two sticks */ - xpad->dev.absmax[t] = 32767; - xpad->dev.absmin[t] = -32768; - xpad->dev.absflat[t] = 128; - xpad->dev.absfuzz[t] = 16; + input_set_abs_params(input_dev, t, -32768, 32767, 16, 128); break; case ABS_Z: case ABS_RZ: /* the triggers */ - xpad->dev.absmax[t] = 255; - xpad->dev.absmin[t] = 0; + input_set_abs_params(input_dev, t, 0, 255, 0, 0); break; case ABS_HAT0X: case ABS_HAT0Y: /* the d-pad */ - xpad->dev.absmax[t] = 1; - xpad->dev.absmin[t] = -1; + input_set_abs_params(input_dev, t, -1, 1, 0, 0); break; } } - input_register_device(&xpad->dev); + ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; + usb_fill_int_urb(xpad->irq_in, udev, + usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), + xpad->idata, XPAD_PKT_LEN, xpad_irq_in, + xpad, ep_irq_in->bInterval); + xpad->irq_in->transfer_dma = xpad->idata_dma; + xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - printk(KERN_INFO "input: %s on %s", xpad->dev.name, path); + input_register_device(xpad->dev); usb_set_intfdata(intf, xpad); return 0; + +fail2: usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); +fail1: input_free_device(input_dev); + kfree(xpad); + return -ENOMEM; + } static void xpad_disconnect(struct usb_interface *intf) @@ -317,7 +308,7 @@ static void xpad_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); if (xpad) { usb_kill_urb(xpad->irq_in); - input_unregister_device(&xpad->dev); + input_unregister_device(xpad->dev); usb_free_urb(xpad->irq_in); usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); kfree(xpad); diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c index 58a176e..f526aeb 100644 --- a/drivers/usb/input/yealink.c +++ b/drivers/usb/input/yealink.c @@ -54,6 +54,7 @@ #include <linux/module.h> #include <linux/rwsem.h> #include <linux/usb.h> +#include <linux/usb_input.h> #include "map_to_7segment.h" #include "yealink.h" @@ -101,12 +102,12 @@ static const struct lcd_segment_map { }; struct yealink_dev { - struct input_dev idev; /* input device */ + struct input_dev *idev; /* input device */ struct usb_device *udev; /* usb device */ /* irq input channel */ struct yld_ctl_packet *irq_data; - dma_addr_t irq_dma; + dma_addr_t irq_dma; struct urb *urb_irq; /* control output channel */ @@ -237,7 +238,7 @@ static int map_p1k_to_key(int scancode) */ static void report_key(struct yealink_dev *yld, int key, struct pt_regs *regs) { - struct input_dev *idev = &yld->idev; + struct input_dev *idev = yld->idev; input_regs(idev, regs); if (yld->key_code >= 0) { @@ -809,8 +810,12 @@ static int usb_cleanup(struct yealink_dev *yld, int err) } if (yld->urb_ctl) usb_free_urb(yld->urb_ctl); - if (yld->idev.dev) - input_unregister_device(&yld->idev); + if (yld->idev) { + if (err) + input_free_device(yld->idev); + else + input_unregister_device(yld->idev); + } if (yld->ctl_req) usb_buffer_free(yld->udev, sizeof(*(yld->ctl_req)), yld->ctl_req, yld->ctl_req_dma); @@ -857,7 +862,7 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; struct yealink_dev *yld; - char path[64]; + struct input_dev *input_dev; int ret, pipe, i; i = usb_match(udev); @@ -866,17 +871,21 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) interface = intf->cur_altsetting; endpoint = &interface->endpoint[0].desc; - if (!(endpoint->bEndpointAddress & 0x80)) + if (!(endpoint->bEndpointAddress & USB_DIR_IN)) return -EIO; - if ((endpoint->bmAttributes & 3) != 3) + if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) return -EIO; - if ((yld = kmalloc(sizeof(struct yealink_dev), GFP_KERNEL)) == NULL) + yld = kzalloc(sizeof(struct yealink_dev), GFP_KERNEL); + if (!yld) return -ENOMEM; - memset(yld, 0, sizeof(*yld)); yld->udev = udev; + yld->idev = input_dev = input_allocate_device(); + if (!input_dev) + return usb_cleanup(yld, -ENOMEM); + /* allocate usb buffers */ yld->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN, SLAB_ATOMIC, &yld->irq_dma); @@ -935,42 +944,37 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) yld->urb_ctl->dev = udev; /* find out the physical bus location */ - if (usb_make_path(udev, path, sizeof(path)) > 0) - snprintf(yld->phys, sizeof(yld->phys)-1, "%s/input0", path); + usb_make_path(udev, yld->phys, sizeof(yld->phys)); + strlcat(yld->phys, "/input0", sizeof(yld->phys)); /* register settings for the input device */ - init_input_dev(&yld->idev); - yld->idev.private = yld; - yld->idev.id.bustype = BUS_USB; - yld->idev.id.vendor = le16_to_cpu(udev->descriptor.idVendor); - yld->idev.id.product = le16_to_cpu(udev->descriptor.idProduct); - yld->idev.id.version = le16_to_cpu(udev->descriptor.bcdDevice); - yld->idev.dev = &intf->dev; - yld->idev.name = yld_device[i].name; - yld->idev.phys = yld->phys; - /* yld->idev.event = input_ev; TODO */ - yld->idev.open = input_open; - yld->idev.close = input_close; + input_dev->name = yld_device[i].name; + input_dev->phys = yld->phys; + usb_to_input_id(udev, &input_dev->id); + input_dev->cdev.dev = &intf->dev; + + input_dev->private = yld; + input_dev->open = input_open; + input_dev->close = input_close; + /* input_dev->event = input_ev; TODO */ /* register available key events */ - yld->idev.evbit[0] = BIT(EV_KEY); + input_dev->evbit[0] = BIT(EV_KEY); for (i = 0; i < 256; i++) { int k = map_p1k_to_key(i); if (k >= 0) { - set_bit(k & 0xff, yld->idev.keybit); + set_bit(k & 0xff, input_dev->keybit); if (k >> 8) - set_bit(k >> 8, yld->idev.keybit); + set_bit(k >> 8, input_dev->keybit); } } - printk(KERN_INFO "input: %s on %s\n", yld->idev.name, path); - - input_register_device(&yld->idev); + input_register_device(yld->idev); usb_set_intfdata(intf, yld); /* clear visible elements */ - for (i=0; i<ARRAY_SIZE(lcdMap); i++) + for (i = 0; i < ARRAY_SIZE(lcdMap); i++) setChar(yld, i, ' '); /* display driver version on LCD line 3 */ diff --git a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c index 6ca2fae..27b23c5 100644 --- a/drivers/usb/media/dabusb.c +++ b/drivers/usb/media/dabusb.c @@ -707,9 +707,8 @@ static struct file_operations dabusb_fops = }; static struct usb_class_driver dabusb_class = { - .name = "usb/dabusb%d", + .name = "dabusb%d", .fops = &dabusb_fops, - .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, .minor_base = DABUSB_MINOR, }; diff --git a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c index 20ac9e1..9fe2c27 100644 --- a/drivers/usb/media/konicawc.c +++ b/drivers/usb/media/konicawc.c @@ -119,7 +119,7 @@ struct konicawc { int yplanesz; /* Number of bytes in the Y plane */ unsigned int buttonsts:1; #ifdef CONFIG_INPUT - struct input_dev input; + struct input_dev *input; char input_physname[64]; #endif }; @@ -218,6 +218,57 @@ static void konicawc_adjust_picture(struct uvd *uvd) konicawc_camera_on(uvd); } +#ifdef CONFIG_INPUT + +static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev) +{ + struct input_dev *input_dev; + + usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); + strncat(cam->input_physname, "/input0", sizeof(cam->input_physname)); + + cam->input = input_dev = input_allocate_device(); + if (!input_dev) { + warn("Not enough memory for camera's input device\n"); + return; + } + + input_dev->name = "Konicawc snapshot button"; + input_dev->phys = cam->input_physname; + usb_to_input_id(dev, &input_dev->id); + input_dev->cdev.dev = &dev->dev; + + input_dev->evbit[0] = BIT(EV_KEY); + input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0); + + input_dev->private = cam; + + input_register_device(cam->input); +} + +static void konicawc_unregister_input(struct konicawc *cam) +{ + if (cam->input) { + input_unregister_device(cam->input); + cam->input = NULL; + } +} + +static void konicawc_report_buttonstat(struct konicawc *cam) +{ + if (cam->input) { + input_report_key(cam->input, BTN_0, cam->buttonsts); + input_sync(cam->input); + } +} + +#else + +static inline void konicawc_register_input(struct konicawc *cam, struct usb_device *dev) { } +static inline void konicawc_unregister_input(struct konicawc *cam) { } +static inline void konicawc_report_buttonstat(struct konicawc *cam) { } + +#endif /* CONFIG_INPUT */ static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct urb *stsurb) { @@ -273,10 +324,7 @@ static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct ur if(button != cam->buttonsts) { DEBUG(2, "button: %sclicked", button ? "" : "un"); cam->buttonsts = button; -#ifdef CONFIG_INPUT - input_report_key(&cam->input, BTN_0, cam->buttonsts); - input_sync(&cam->input); -#endif + konicawc_report_buttonstat(cam); } if(sts == 0x01) { /* drop frame */ @@ -645,9 +693,9 @@ static int konicawc_set_video_mode(struct uvd *uvd, struct video_window *vw) RingQueue_Flush(&uvd->dp); cam->lastframe = -2; if(uvd->curframe != -1) { - uvd->frame[uvd->curframe].curline = 0; - uvd->frame[uvd->curframe].seqRead_Length = 0; - uvd->frame[uvd->curframe].seqRead_Index = 0; + uvd->frame[uvd->curframe].curline = 0; + uvd->frame[uvd->curframe].seqRead_Length = 0; + uvd->frame[uvd->curframe].seqRead_Index = 0; } konicawc_start_data(uvd); @@ -718,7 +766,6 @@ static void konicawc_configure_video(struct uvd *uvd) DEBUG(1, "setting initial values"); } - static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id *devid) { struct usb_device *dev = interface_to_usbdev(intf); @@ -839,21 +886,8 @@ static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id err("usbvideo_RegisterVideoDevice() failed."); uvd = NULL; } -#ifdef CONFIG_INPUT - /* Register input device for button */ - memset(&cam->input, 0, sizeof(struct input_dev)); - cam->input.name = "Konicawc snapshot button"; - cam->input.private = cam; - cam->input.evbit[0] = BIT(EV_KEY); - cam->input.keybit[LONG(BTN_0)] = BIT(BTN_0); - usb_to_input_id(dev, &cam->input.id); - input_register_device(&cam->input); - - usb_make_path(dev, cam->input_physname, 56); - strcat(cam->input_physname, "/input0"); - cam->input.phys = cam->input_physname; - info("konicawc: %s on %s\n", cam->input.name, cam->input.phys); -#endif + + konicawc_register_input(cam, dev); } if (uvd) { @@ -869,10 +903,9 @@ static void konicawc_free_uvd(struct uvd *uvd) int i; struct konicawc *cam = (struct konicawc *)uvd->user_data; -#ifdef CONFIG_INPUT - input_unregister_device(&cam->input); -#endif - for (i=0; i < USBVIDEO_NUMSBUF; i++) { + konicawc_unregister_input(cam); + + for (i = 0; i < USBVIDEO_NUMSBUF; i++) { usb_free_urb(cam->sts_urb[i]); cam->sts_urb[i] = NULL; } diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c index ae4681f..5f33f7c 100644 --- a/drivers/usb/misc/auerswald.c +++ b/drivers/usb/misc/auerswald.c @@ -1873,9 +1873,8 @@ static struct file_operations auerswald_fops = }; static struct usb_class_driver auerswald_class = { - .name = "usb/auer%d", + .name = "auer%d", .fops = &auerswald_fops, - .mode = S_IFCHR | S_IRUGO | S_IWUGO, .minor_base = AUER_MINOR_BASE, }; diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c index 733acc2..1dc3e0f 100644 --- a/drivers/usb/misc/idmouse.c +++ b/drivers/usb/misc/idmouse.c @@ -105,11 +105,10 @@ static struct file_operations idmouse_fops = { .release = idmouse_release, }; -/* class driver information for devfs */ +/* class driver information */ static struct usb_class_driver idmouse_class = { - .name = "usb/idmouse%d", + .name = "idmouse%d", .fops = &idmouse_fops, - .mode = S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH, /* filemode (char, 444) */ .minor_base = USB_IDMOUSE_MINOR_BASE, }; @@ -320,20 +319,8 @@ static ssize_t idmouse_read(struct file *file, char __user *buffer, size_t count return -ENODEV; } - if (*ppos >= IMGSIZE) { - up (&dev->sem); - return 0; - } - - count = min ((loff_t)count, IMGSIZE - (*ppos)); - - if (copy_to_user (buffer, dev->bulk_in_buffer + *ppos, count)) { - result = -EFAULT; - } else { - result = count; - *ppos += count; - } - + result = simple_read_from_buffer(buffer, count, ppos, + dev->bulk_in_buffer, IMGSIZE); /* unlock the device */ up(&dev->sem); return result; diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 7d06105..2703e20 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -271,12 +271,11 @@ static struct file_operations tower_fops = { /* * usb class driver info in order to get a minor number from the usb core, - * and to have the device registered with devfs and the driver core + * and to have the device registered with the driver core */ static struct usb_class_driver tower_class = { - .name = "usb/legousbtower%d", + .name = "legousbtower%d", .fops = &tower_fops, - .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, .minor_base = LEGO_USB_TOWER_MINOR_BASE, }; diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c index 26f77e2..7d02d8e 100644 --- a/drivers/usb/misc/rio500.c +++ b/drivers/usb/misc/rio500.c @@ -443,9 +443,8 @@ file_operations usb_rio_fops = { }; static struct usb_class_driver usb_rio_class = { - .name = "usb/rio500%d", + .name = "rio500%d", .fops = &usb_rio_fops, - .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, .minor_base = RIO_MINOR, }; diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 39db315..c946c9a 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -2440,7 +2440,7 @@ int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) { int ret = 0, slot = sisusb->font_slot, i; - struct font_desc *myfont; + const struct font_desc *myfont; u8 *tempbuf; u16 *tempbufb; size_t written; @@ -3239,12 +3239,7 @@ static struct file_operations usb_sisusb_fops = { }; static struct usb_class_driver usb_sisusb_class = { -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13) - .name = "usb/sisusbvga%d", - .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, -#else .name = "sisusbvga%d", -#endif .fops = &usb_sisusb_fops, .minor_base = SISUSB_MINOR }; diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c index 096ab30..85f3725 100644 --- a/drivers/usb/misc/usblcd.c +++ b/drivers/usb/misc/usblcd.c @@ -251,13 +251,12 @@ static struct file_operations lcd_fops = { }; /* - * * usb class driver info in order to get a minor number from the usb core, - * * and to have the device registered with devfs and 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 lcd_class = { - .name = "usb/lcd%d", + .name = "lcd%d", .fops = &lcd_fops, - .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, .minor_base = USBLCD_MINOR, }; diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 54799eb..2997f558 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -9,7 +9,7 @@ #include <linux/mm.h> #include <linux/module.h> #include <linux/moduleparam.h> -#include <asm/scatterlist.h> +#include <linux/scatterlist.h> #include <linux/usb.h> @@ -381,7 +381,6 @@ alloc_sglist (int nents, int max, int vary) sg = kmalloc (nents * sizeof *sg, SLAB_KERNEL); if (!sg) return NULL; - memset (sg, 0, nents * sizeof *sg); for (i = 0; i < nents; i++) { char *buf; @@ -394,9 +393,7 @@ alloc_sglist (int nents, int max, int vary) memset (buf, 0, size); /* kmalloc pages are always physically contiguous! */ - sg [i].page = virt_to_page (buf); - sg [i].offset = offset_in_page (buf); - sg [i].length = size; + sg_init_one(&sg[i], buf, size); if (vary) { size += vary; @@ -983,6 +980,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) 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; @@ -1948,21 +1946,11 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id) static int usbtest_suspend (struct usb_interface *intf, pm_message_t message) { - struct usbtest_dev *dev = usb_get_intfdata (intf); - - down (&dev->sem); - intf->dev.power.power_state = PMSG_SUSPEND; - up (&dev->sem); return 0; } static int usbtest_resume (struct usb_interface *intf) { - struct usbtest_dev *dev = usb_get_intfdata (intf); - - down (&dev->sem); - intf->dev.power.power_state = PMSG_ON; - up (&dev->sem); return 0; } diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c index 03fb70e..0592cb5 100644 --- a/drivers/usb/misc/uss720.c +++ b/drivers/usb/misc/uss720.c @@ -137,7 +137,7 @@ static void async_complete(struct urb *urb, struct pt_regs *ptregs) static struct uss720_async_request *submit_async_request(struct parport_uss720_private *priv, __u8 request, __u8 requesttype, __u16 value, __u16 index, - unsigned int mem_flags) + gfp_t mem_flags) { struct usb_device *usbdev; struct uss720_async_request *rq; @@ -204,7 +204,7 @@ static unsigned int kill_all_async_requests_priv(struct parport_uss720_private * /* --------------------------------------------------------------------- */ -static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val, unsigned int mem_flags) +static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val, gfp_t mem_flags) { struct parport_uss720_private *priv; struct uss720_async_request *rq; @@ -238,7 +238,7 @@ static int get_1284_register(struct parport *pp, unsigned char reg, unsigned cha return -EIO; } -static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val, unsigned int mem_flags) +static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val, gfp_t mem_flags) { struct parport_uss720_private *priv; struct uss720_async_request *rq; diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c index 508a210..c34944c 100644 --- a/drivers/usb/mon/mon_main.c +++ b/drivers/usb/mon/mon_main.c @@ -11,6 +11,7 @@ #include <linux/usb.h> #include <linux/debugfs.h> #include <linux/smp_lock.h> +#include <linux/notifier.h> #include "usb_mon.h" #include "../core/hcd.h" @@ -205,6 +206,23 @@ static void mon_bus_remove(struct usb_bus *ubus) up(&mon_lock); } +static int mon_notify(struct notifier_block *self, unsigned long action, + void *dev) +{ + switch (action) { + case USB_BUS_ADD: + mon_bus_add(dev); + break; + case USB_BUS_REMOVE: + mon_bus_remove(dev); + } + return NOTIFY_OK; +} + +static struct notifier_block mon_nb = { + .notifier_call = mon_notify, +}; + /* * Ops */ @@ -212,8 +230,6 @@ static struct usb_mon_operations mon_ops_0 = { .urb_submit = mon_submit, .urb_submit_error = mon_submit_error, .urb_complete = mon_complete, - .bus_add = mon_bus_add, - .bus_remove = mon_bus_remove, }; /* @@ -329,6 +345,8 @@ static int __init mon_init(void) } // MOD_INC_USE_COUNT(which_module?); + usb_register_notify(&mon_nb); + down(&usb_bus_list_lock); list_for_each_entry (ubus, &usb_bus_list, bus_list) { mon_bus_init(mondir, ubus); @@ -342,6 +360,7 @@ static void __exit mon_exit(void) struct mon_bus *mbus; struct list_head *p; + usb_unregister_notify(&mon_nb); usb_mon_deregister(); down(&mon_lock); diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig index 8c010bb..efd6ca7 100644 --- a/drivers/usb/net/Kconfig +++ b/drivers/usb/net/Kconfig @@ -294,7 +294,7 @@ config USB_NET_ZAURUS This also supports some related device firmware, as used in some PDAs from Olympus and some cell phones from Motorola. - If you install an alternate ROM image, such as the Linux 2.6 based + If you install an alternate image, such as the Linux 2.6 based versions of OpenZaurus, you should no longer need to support this protocol. Only the "eth-fd" or "net_fd" drivers in these devices really need this non-conformant variant of CDC Ethernet (or in diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c index 861f00a..252a34f 100644 --- a/drivers/usb/net/asix.c +++ b/drivers/usb/net/asix.c @@ -753,7 +753,7 @@ static int ax88772_rx_fixup(struct usbnet *dev, struct sk_buff *skb) } static struct sk_buff *ax88772_tx_fixup(struct usbnet *dev, struct sk_buff *skb, - unsigned flags) + gfp_t flags) { int padlen; int headroom = skb_headroom(skb); diff --git a/drivers/usb/net/gl620a.c b/drivers/usb/net/gl620a.c index c8763ae..c0f263b 100644 --- a/drivers/usb/net/gl620a.c +++ b/drivers/usb/net/gl620a.c @@ -301,7 +301,7 @@ static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb) } static struct sk_buff * -genelink_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags) +genelink_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) { int padlen; int length = skb->len; diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c index e04b0ce..6bef1be 100644 --- a/drivers/usb/net/kaweth.c +++ b/drivers/usb/net/kaweth.c @@ -469,7 +469,7 @@ static int kaweth_reset(struct kaweth_device *kaweth) 0, KAWETH_CONTROL_TIMEOUT); - udelay(10000); + mdelay(10); kaweth_dbg("kaweth_reset() returns %d.",result); @@ -477,13 +477,13 @@ static int kaweth_reset(struct kaweth_device *kaweth) } static void kaweth_usb_receive(struct urb *, struct pt_regs *regs); -static int kaweth_resubmit_rx_urb(struct kaweth_device *, unsigned); +static int kaweth_resubmit_rx_urb(struct kaweth_device *, gfp_t); /**************************************************************** int_callback *****************************************************************/ -static void kaweth_resubmit_int_urb(struct kaweth_device *kaweth, int mf) +static void kaweth_resubmit_int_urb(struct kaweth_device *kaweth, gfp_t mf) { int status; @@ -550,7 +550,7 @@ static void kaweth_resubmit_tl(void *d) * kaweth_resubmit_rx_urb ****************************************************************/ static int kaweth_resubmit_rx_urb(struct kaweth_device *kaweth, - unsigned mem_flags) + gfp_t mem_flags) { int result; diff --git a/drivers/usb/net/net1080.c b/drivers/usb/net/net1080.c index a4309c4..cee55f8 100644 --- a/drivers/usb/net/net1080.c +++ b/drivers/usb/net/net1080.c @@ -500,7 +500,7 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb) } static struct sk_buff * -net1080_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags) +net1080_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) { int padlen; struct sk_buff *skb2; diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index 6a4ffe6..537eb18 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c @@ -1384,7 +1384,6 @@ static int pegasus_suspend (struct usb_interface *intf, pm_message_t message) usb_kill_urb(pegasus->rx_urb); usb_kill_urb(pegasus->intr_urb); } - intf->dev.power.power_state = PMSG_SUSPEND; return 0; } @@ -1392,7 +1391,6 @@ static int pegasus_resume (struct usb_interface *intf) { struct pegasus *pegasus = usb_get_intfdata(intf); - intf->dev.power.power_state = PMSG_ON; netif_device_attach (pegasus->net); if (netif_running(pegasus->net)) { pegasus->rx_urb->status = 0; diff --git a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h index b98f2a8..9fbd59b 100644 --- a/drivers/usb/net/pegasus.h +++ b/drivers/usb/net/pegasus.h @@ -181,6 +181,8 @@ PEGASUS_DEV( "Accton USB 10/100 Ethernet Adapter", VENDOR_ACCTON, 0x1046, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_ACCTON, 0x5046, DEFAULT_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "Philips USB 10/100 Ethernet", VENDOR_ACCTON, 0xb004, + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet", VENDOR_ADMTEK, 0x8511, DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA ) diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c index 2ed2e5f..b5a925d 100644 --- a/drivers/usb/net/rndis_host.c +++ b/drivers/usb/net/rndis_host.c @@ -517,7 +517,7 @@ static int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb) } static struct sk_buff * -rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags) +rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) { struct rndis_data_hdr *hdr; struct sk_buff *skb2; diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c index c3d4e35..787dd35 100644 --- a/drivers/usb/net/rtl8150.c +++ b/drivers/usb/net/rtl8150.c @@ -909,6 +909,7 @@ static void rtl8150_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); if (dev) { set_bit(RTL8150_UNPLUG, &dev->flags); + tasklet_disable(&dev->tl); unregister_netdev(dev->netdev); unlink_all_urbs(dev); free_all_urbs(dev); diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index 6c46091..74f05c9 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c @@ -288,7 +288,7 @@ EXPORT_SYMBOL_GPL(usbnet_defer_kevent); static void rx_complete (struct urb *urb, struct pt_regs *regs); -static void rx_submit (struct usbnet *dev, struct urb *urb, unsigned flags) +static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) { struct sk_buff *skb; struct skb_data *entry; @@ -1185,7 +1185,6 @@ int usbnet_suspend (struct usb_interface *intf, pm_message_t message) netif_device_detach (dev->net); (void) unlink_urbs (dev, &dev->rxq); (void) unlink_urbs (dev, &dev->txq); - intf->dev.power.power_state = PMSG_SUSPEND; return 0; } EXPORT_SYMBOL_GPL(usbnet_suspend); @@ -1194,7 +1193,6 @@ int usbnet_resume (struct usb_interface *intf) { struct usbnet *dev = usb_get_intfdata(intf); - intf->dev.power.power_state = PMSG_ON; netif_device_attach (dev->net); tasklet_schedule (&dev->bh); return 0; diff --git a/drivers/usb/net/usbnet.h b/drivers/usb/net/usbnet.h index 7aa0abd..89fc495 100644 --- a/drivers/usb/net/usbnet.h +++ b/drivers/usb/net/usbnet.h @@ -107,7 +107,7 @@ struct driver_info { /* fixup tx packet (add framing) */ struct sk_buff *(*tx_fixup)(struct usbnet *dev, - struct sk_buff *skb, unsigned flags); + struct sk_buff *skb, gfp_t flags); /* for new devices, use the descriptor-reading code instead */ int in; /* rx endpoint */ diff --git a/drivers/usb/net/zaurus.c b/drivers/usb/net/zaurus.c index ee3b892..5d4b7d5 100644 --- a/drivers/usb/net/zaurus.c +++ b/drivers/usb/net/zaurus.c @@ -62,7 +62,7 @@ */ static struct sk_buff * -zaurus_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags) +zaurus_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) { int padlen; struct sk_buff *skb2; diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c index c4e479e..2f52261 100644 --- a/drivers/usb/net/zd1201.c +++ b/drivers/usb/net/zd1201.c @@ -521,7 +521,7 @@ static int zd1201_setconfig(struct zd1201 *zd, int rid, void *buf, int len, int int reqlen; char seq=0; struct urb *urb; - unsigned int gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC; + gfp_t gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC; len += 4; /* first 4 are for header */ diff --git a/drivers/usb/serial/ChangeLog.old b/drivers/usb/serial/ChangeLog.old new file mode 100644 index 0000000..c1b2799 --- /dev/null +++ b/drivers/usb/serial/ChangeLog.old @@ -0,0 +1,730 @@ +This is the contents of some of the drivers/usb/serial/ files that had old +changelog comments. They were quite old, and out of date, and we don't keep +them anymore, so I've put them here, away from the source files, in case +people still care to see them. + +- Greg Kroah-Hartman <greg@kroah.com> October 20, 2005 + +----------------------------------------------------------------------- +usb-serial.h Change Log comments: + + (03/26/2002) gkh + removed the port->tty check from port_paranoia_check() due to serial + consoles not having a tty device assigned to them. + + (12/03/2001) gkh + removed active from the port structure. + added documentation to the usb_serial_device_type structure + + (10/10/2001) gkh + added vendor and product to serial structure. Needed to determine device + owner when the device is disconnected. + + (05/30/2001) gkh + added sem to port structure and removed port_lock + + (10/05/2000) gkh + Added interrupt_in_endpointAddress and bulk_in_endpointAddress to help + fix bug with urb->dev not being set properly, now that the usb core + needs it. + + (09/11/2000) gkh + Added usb_serial_debug_data function to help get rid of #DEBUG in the + drivers. + + (08/28/2000) gkh + Added port_lock to port structure. + + (08/08/2000) gkh + Added open_count to port structure. + + (07/23/2000) gkh + Added bulk_out_endpointAddress to port structure. + + (07/19/2000) gkh, pberger, and borchers + Modifications to allow usb-serial drivers to be modules. + +----------------------------------------------------------------------- +usb-serial.c Change Log comments: + + (12/10/2002) gkh + Split the ports off into their own struct device, and added a + usb-serial bus driver. + + (11/19/2002) gkh + removed a few #ifdefs for the generic code and cleaned up the failure + logic in initialization. + + (10/02/2002) gkh + moved the console code to console.c and out of this file. + + (06/05/2002) gkh + moved location of startup() call in serial_probe() until after all + of the port information and endpoints are initialized. This makes + things easier for some drivers. + + (04/10/2002) gkh + added serial_read_proc function which creates a + /proc/tty/driver/usb-serial file. + + (03/27/2002) gkh + Got USB serial console code working properly and merged into the main + version of the tree. Thanks to Randy Dunlap for the initial version + of this code, and for pushing me to finish it up. + The USB serial console works with any usb serial driver device. + + (03/21/2002) gkh + Moved all manipulation of port->open_count into the core. Now the + individual driver's open and close functions are called only when the + first open() and last close() is called. Making the drivers a bit + smaller and simpler. + Fixed a bug if a driver didn't have the owner field set. + + (02/26/2002) gkh + Moved all locking into the main serial_* functions, instead of having + the individual drivers have to grab the port semaphore. This should + reduce races. + Reworked the MOD_INC logic a bit to always increment and decrement, even + if the generic driver is being used. + + (10/10/2001) gkh + usb_serial_disconnect() now sets the serial->dev pointer is to NULL to + help prevent child drivers from accessing the device since it is now + gone. + + (09/13/2001) gkh + Moved generic driver initialize after we have registered with the USB + core. Thanks to Randy Dunlap for pointing this problem out. + + (07/03/2001) gkh + Fixed module paramater size. Thanks to John Brockmeyer for the pointer. + Fixed vendor and product getting defined through the MODULE_PARM macro + if the Generic driver wasn't compiled in. + Fixed problem with generic_shutdown() not being called for drivers that + don't have a shutdown() function. + + (06/06/2001) gkh + added evil hack that is needed for the prolific pl2303 device due to the + crazy way its endpoints are set up. + + (05/30/2001) gkh + switched from using spinlock to a semaphore, which fixes lots of problems. + + (04/08/2001) gb + Identify version on module load. + + 2001_02_05 gkh + Fixed buffer overflows bug with the generic serial driver. Thanks to + Todd Squires <squirest@ct0.com> for fixing this. + + (01/10/2001) gkh + Fixed bug where the generic serial adaptor grabbed _any_ device that was + offered to it. + + (12/12/2000) gkh + Removed MOD_INC and MOD_DEC from poll and disconnect functions, and + moved them to the serial_open and serial_close functions. + Also fixed bug with there not being a MOD_DEC for the generic driver + (thanks to Gary Brubaker for finding this.) + + (11/29/2000) gkh + Small NULL pointer initialization cleanup which saves a bit of disk image + + (11/01/2000) Adam J. Richter + instead of using idVendor/idProduct pairs, usb serial drivers + now identify their hardware interest with usb_device_id tables, + which they usually have anyhow for use with MODULE_DEVICE_TABLE. + + (10/05/2000) gkh + Fixed bug with urb->dev not being set properly, now that the usb + core needs it. + + (09/11/2000) gkh + Removed DEBUG #ifdefs with call to usb_serial_debug_data + + (08/28/2000) gkh + Added port_lock to port structure. + Added locks for SMP safeness to generic driver + Fixed the ability to open a generic device's port more than once. + + (07/23/2000) gkh + Added bulk_out_endpointAddress to port structure. + + (07/19/2000) gkh, pberger, and borchers + Modifications to allow usb-serial drivers to be modules. + + (07/03/2000) gkh + Added more debugging to serial_ioctl call + + (06/25/2000) gkh + Changed generic_write_bulk_callback to not call wake_up_interruptible + directly, but to have port_softint do it at a safer time. + + (06/23/2000) gkh + Cleaned up debugging statements in a quest to find UHCI timeout bug. + + (05/22/2000) gkh + Changed the makefile, enabling the big CONFIG_USB_SERIAL_SOMTHING to be + removed from the individual device source files. + + (05/03/2000) gkh + Added the Digi Acceleport driver from Al Borchers and Peter Berger. + + (05/02/2000) gkh + Changed devfs and tty register code to work properly now. This was based on + the ACM driver changes by Vojtech Pavlik. + + (04/27/2000) Ryan VanderBijl + Put calls to *_paranoia_checks into one function. + + (04/23/2000) gkh + Fixed bug that Randy Dunlap found for Generic devices with no bulk out ports. + Moved when the startup code printed out the devices that are supported. + + (04/19/2000) gkh + Added driver for ZyXEL omni.net lcd plus ISDN TA + Made startup info message specify which drivers were compiled in. + + (04/03/2000) gkh + Changed the probe process to remove the module unload races. + Changed where the tty layer gets initialized to have devfs work nicer. + Added initial devfs support. + + (03/26/2000) gkh + Split driver up into device specific pieces. + + (03/19/2000) gkh + Fixed oops that could happen when device was removed while a program + was talking to the device. + Removed the static urbs and now all urbs are created and destroyed + dynamically. + Reworked the internal interface. Now everything is based on the + usb_serial_port structure instead of the larger usb_serial structure. + This fixes the bug that a multiport device could not have more than + one port open at one time. + + (03/17/2000) gkh + Added config option for debugging messages. + Added patch for keyspan pda from Brian Warner. + + (03/06/2000) gkh + Added the keyspan pda code from Brian Warner <warner@lothar.com> + Moved a bunch of the port specific stuff into its own structure. This + is in anticipation of the true multiport devices (there's a bug if you + try to access more than one port of any multiport device right now) + + (02/21/2000) gkh + Made it so that any serial devices only have to specify which functions + they want to overload from the generic function calls (great, + inheritance in C, in a driver, just what I wanted...) + Added support for set_termios and ioctl function calls. No drivers take + advantage of this yet. + Removed the #ifdef MODULE, now there is no module specific code. + Cleaned up a few comments in usb-serial.h that were wrong (thanks again + to Miles Lott). + Small fix to get_free_serial. + + (02/14/2000) gkh + Removed the Belkin and Peracom functionality from the driver due to + the lack of support from the vendor, and me not wanting people to + accidenatly buy the device, expecting it to work with Linux. + Added read_bulk_callback and write_bulk_callback to the type structure + for the needs of the FTDI and WhiteHEAT driver. + Changed all reverences to FTDI to FTDI_SIO at the request of Bill + Ryder. + Changed the output urb size back to the max endpoint size to make + the ftdi_sio driver have it easier, and due to the fact that it didn't + really increase the speed any. + + (02/11/2000) gkh + Added VISOR_FUNCTION_CONSOLE to the visor startup function. This was a + patch from Miles Lott (milos@insync.net). + Fixed bug with not restoring the minor range that a device grabs, if + the startup function fails (thanks Miles for finding this). + + (02/05/2000) gkh + Added initial framework for the Keyspan PDA serial converter so that + Brian Warner has a place to put his code. + Made the ezusb specific functions generic enough that different + devices can use them (whiteheat and keyspan_pda both need them). + Split out a whole bunch of structure and other stuff to a separate + usb-serial.h file. + Made the Visor connection messages a little more understandable, now + that Miles Lott (milos@insync.net) has gotten the Generic channel to + work. Also made them always show up in the log file. + + (01/25/2000) gkh + Added initial framework for FTDI serial converter so that Bill Ryder + has a place to put his code. + Added the vendor specific info from Handspring. Now we can print out + informational debug messages as well as understand what is happening. + + (01/23/2000) gkh + Fixed problem of crash when trying to open a port that didn't have a + device assigned to it. Made the minor node finding a little smarter, + now it looks to find a continuous space for the new device. + + (01/21/2000) gkh + Fixed bug in visor_startup with patch from Miles Lott (milos@insync.net) + Fixed get_serial_by_minor which was all messed up for multi port + devices. Fixed multi port problem for generic devices. Now the number + of ports is determined by the number of bulk out endpoints for the + generic device. + + (01/19/2000) gkh + Removed lots of cruft that was around from the old (pre urb) driver + interface. + Made the serial_table dynamic. This should save lots of memory when + the number of minor nodes goes up to 256. + Added initial support for devices that have more than one port. + Added more debugging comments for the Visor, and added a needed + set_configuration call. + + (01/17/2000) gkh + Fixed the WhiteHEAT firmware (my processing tool had a bug) + and added new debug loader firmware for it. + Removed the put_char function as it isn't really needed. + Added visor startup commands as found by the Win98 dump. + + (01/13/2000) gkh + Fixed the vendor id for the generic driver to the one I meant it to be. + + (01/12/2000) gkh + Forget the version numbering...that's pretty useless... + Made the driver able to be compiled so that the user can select which + converter they want to use. This allows people who only want the Visor + support to not pay the memory size price of the WhiteHEAT. + Fixed bug where the generic driver (idVendor=0000 and idProduct=0000) + grabbed the root hub. Not good. + + version 0.4.0 (01/10/2000) gkh + Added whiteheat.h containing the firmware for the ConnectTech WhiteHEAT + device. Added startup function to allow firmware to be downloaded to + a device if it needs to be. + Added firmware download logic to the WhiteHEAT device. + Started to add #defines to split up the different drivers for potential + configuration option. + + version 0.3.1 (12/30/99) gkh + Fixed problems with urb for bulk out. + Added initial support for multiple sets of endpoints. This enables + the Handspring Visor to be attached successfully. Only the first + bulk in / bulk out endpoint pair is being used right now. + + version 0.3.0 (12/27/99) gkh + Added initial support for the Handspring Visor based on a patch from + Miles Lott (milos@sneety.insync.net) + Cleaned up the code a bunch and converted over to using urbs only. + + version 0.2.3 (12/21/99) gkh + Added initial support for the Connect Tech WhiteHEAT converter. + Incremented the number of ports in expectation of getting the + WhiteHEAT to work properly (4 ports per connection). + Added notification on insertion and removal of what port the + device is/was connected to (and what kind of device it was). + + version 0.2.2 (12/16/99) gkh + Changed major number to the new allocated number. We're legal now! + + version 0.2.1 (12/14/99) gkh + Fixed bug that happens when device node is opened when there isn't a + device attached to it. Thanks to marek@webdesign.no for noticing this. + + version 0.2.0 (11/10/99) gkh + Split up internals to make it easier to add different types of serial + converters to the code. + Added a "generic" driver that gets it's vendor and product id + from when the module is loaded. Thanks to David E. Nelson (dnelson@jump.net) + for the idea and sample code (from the usb scanner driver.) + Cleared up any licensing questions by releasing it under the GNU GPL. + + version 0.1.2 (10/25/99) gkh + Fixed bug in detecting device. + + version 0.1.1 (10/05/99) gkh + Changed the major number to not conflict with anything else. + + version 0.1 (09/28/99) gkh + Can recognize the two different devices and start up a read from + device when asked to. Writes also work. No control signals yet, this + all is vendor specific data (i.e. no spec), also no control for + different baud rates or other bit settings. + Currently we are using the same devid as the acm driver. This needs + to change. + +----------------------------------------------------------------------- +visor.c Change Log comments: + + (06/03/2003) Judd Montgomery <judd at jpilot.org> + Added support for module parameter options for untested/unknown + devices. + + (03/09/2003) gkh + Added support for the Sony Clie NZ90V device. Thanks to Martin Brachtl + <brachtl@redgrep.cz> for the information. + + (03/05/2003) gkh + Think Treo support is now working. + + (04/03/2002) gkh + Added support for the Sony OS 4.1 devices. Thanks to Hiroyuki ARAKI + <hiro@zob.ne.jp> for the information. + + (03/27/2002) gkh + Removed assumptions that port->tty was always valid (is not true + for usb serial console devices.) + + (03/23/2002) gkh + Added support for the Palm i705 device, thanks to Thomas Riemer + <tom@netmech.com> for the information. + + (03/21/2002) gkh + Added support for the Palm m130 device, thanks to Udo Eisenbarth + <udo.eisenbarth@web.de> for the information. + + (02/27/2002) gkh + Reworked the urb handling logic. We have no more pool, but dynamically + allocate the urb and the transfer buffer on the fly. In testing this + does not incure any measurable overhead. This also relies on the fact + that we have proper reference counting logic for urbs. + + (02/21/2002) SilaS + Added initial support for the Palm m515 devices. + + (02/14/2002) gkh + Added support for the Clie S-360 device. + + (12/18/2001) gkh + Added better Clie support for 3.5 devices. Thanks to Geoffrey Levand + for the patch. + + (11/11/2001) gkh + Added support for the m125 devices, and added check to prevent oopses + for Clié devices that lie about the number of ports they have. + + (08/30/2001) gkh + Added support for the Clie devices, both the 3.5 and 4.0 os versions. + Many thanks to Daniel Burke, and Bryan Payne for helping with this. + + (08/23/2001) gkh + fixed a few potential bugs pointed out by Oliver Neukum. + + (05/30/2001) gkh + switched from using spinlock to a semaphore, which fixes lots of problems. + + (05/28/2000) gkh + Added initial support for the Palm m500 and Palm m505 devices. + + (04/08/2001) gb + Identify version on module load. + + (01/21/2000) gkh + Added write_room and chars_in_buffer, as they were previously using the + generic driver versions which is all wrong now that we are using an urb + pool. Thanks to Wolfgang Grandegger for pointing this out to me. + Removed count assignment in the write function, which was not needed anymore + either. Thanks to Al Borchers for pointing this out. + + (12/12/2000) gkh + Moved MOD_DEC to end of visor_close to be nicer, as the final write + message can sleep. + + (11/12/2000) gkh + Fixed bug with data being dropped on the floor by forcing tty->low_latency + to be on. Hopefully this fixes the OHCI issue! + + (11/01/2000) Adam J. Richter + usb_device_id table support + + (10/05/2000) gkh + Fixed bug with urb->dev not being set properly, now that the usb + core needs it. + + (09/11/2000) gkh + Got rid of always calling kmalloc for every urb we wrote out to the + device. + Added visor_read_callback so we can keep track of bytes in and out for + those people who like to know the speed of their device. + Removed DEBUG #ifdefs with call to usb_serial_debug_data + + (09/06/2000) gkh + Fixed oops in visor_exit. Need to uncomment usb_unlink_urb call _after_ + the host controller drivers set urb->dev = NULL when the urb is finished. + + (08/28/2000) gkh + Added locks for SMP safeness. + + (08/08/2000) gkh + Fixed endian problem in visor_startup. + Fixed MOD_INC and MOD_DEC logic and the ability to open a port more + than once. + + (07/23/2000) gkh + Added pool of write urbs to speed up transfers to the visor. + + (07/19/2000) gkh + Added module_init and module_exit functions to handle the fact that this + driver is a loadable module now. + + (07/03/2000) gkh + Added visor_set_ioctl and visor_set_termios functions (they don't do much + of anything, but are good for debugging.) + + (06/25/2000) gkh + Fixed bug in visor_unthrottle that should help with the disconnect in PPP + bug that people have been reporting. + + (06/23/2000) gkh + Cleaned up debugging statements in a quest to find UHCI timeout bug. + + (04/27/2000) Ryan VanderBijl + Fixed memory leak in visor_close + + (03/26/2000) gkh + Split driver up into device specific pieces. + +----------------------------------------------------------------------- +pl2303.c Change Log comments: + + 2002_Mar_26 gkh + allowed driver to work properly if there is no tty assigned to a port + (this happens for serial console devices.) + + 2001_Oct_06 gkh + Added RTS and DTR line control. Thanks to joe@bndlg.de for parts of it. + + 2001_Sep_19 gkh + Added break support. + + 2001_Aug_30 gkh + fixed oops in write_bulk_callback. + + 2001_Aug_28 gkh + reworked buffer logic to be like other usb-serial drivers. Hopefully + removing some reported problems. + + 2001_Jun_06 gkh + finished porting to 2.4 format. + + +----------------------------------------------------------------------- +io_edgeport.c Change Log comments: + + 2003_04_03 al borchers + - fixed a bug (that shows up with dosemu) where the tty struct is + used in a callback after it has been freed + + 2.3 2002_03_08 greg kroah-hartman + - fixed bug when multiple devices were attached at the same time. + + 2.2 2001_11_14 greg kroah-hartman + - fixed bug in edge_close that kept the port from being used more + than once. + - fixed memory leak on device removal. + - fixed potential double free of memory when command urb submitting + failed. + - other small cleanups when the device is removed + + 2.1 2001_07_09 greg kroah-hartman + - added support for TIOCMBIS and TIOCMBIC. + + (04/08/2001) gb + - Identify version on module load. + + 2.0 2001_03_05 greg kroah-hartman + - reworked entire driver to fit properly in with the other usb-serial + drivers. Occasional oopses still happen, but it's a good start. + + 1.2.3 (02/23/2001) greg kroah-hartman + - changed device table to work properly for 2.4.x final format. + - fixed problem with dropping data at high data rates. + + 1.2.2 (11/27/2000) greg kroah-hartman + - cleaned up more NTisms. + - Added device table for 2.4.0-test11 + + 1.2.1 (11/08/2000) greg kroah-hartman + - Started to clean up NTisms. + - Fixed problem with dev field of urb for kernels >= 2.4.0-test9 + + 1.2 (10/17/2000) David Iacovelli + Remove all EPIC code and GPL source + Fix RELEVANT_IFLAG macro to include flow control + changes port configuration changes. + Fix redefinition of SERIAL_MAGIC + Change all timeout values to 5 seconds + Tried to fix the UHCI multiple urb submission, but failed miserably. + it seems to work fine with OHCI. + ( Greg take a look at the #if 0 at end of WriteCmdUsb() we must + find a way to work arount this UHCI bug ) + + 1.1 (10/11/2000) David Iacovelli + Fix XON/XOFF flow control to support both IXON and IXOFF + + 0.9.27 (06/30/2000) David Iacovelli + Added transmit queue and now allocate urb for command writes. + + 0.9.26 (06/29/2000) David Iacovelli + Add support for 80251 based edgeport + + 0.9.25 (06/27/2000) David Iacovelli + Do not close the port if it has multiple opens. + + 0.9.24 (05/26/2000) David Iacovelli + Add IOCTLs to support RXTX and JAVA POS + and first cut at running BlackBox Demo + + 0.9.23 (05/24/2000) David Iacovelli + Add IOCTLs to support RXTX and JAVA POS + + 0.9.22 (05/23/2000) David Iacovelli + fixed bug in enumeration. If epconfig turns on mapping by + path after a device is already plugged in, we now update + the mapping correctly + + 0.9.21 (05/16/2000) David Iacovelli + Added BlockUntilChaseResp() to also wait for txcredits + Updated the way we allocate and handle write URBs + Add debug code to dump buffers + + 0.9.20 (05/01/2000) David Iacovelli + change driver to use usb/tts/ + + 0.9.19 (05/01/2000) David Iacovelli + Update code to compile if DEBUG is off + + 0.9.18 (04/28/2000) David Iacovelli + cleanup and test tty_register with devfs + + 0.9.17 (04/27/2000) greg kroah-hartman + changed tty_register around to be like the way it + was before, but now it works properly with devfs. + + 0.9.16 (04/26/2000) david iacovelli + Fixed bug in GetProductInfo() + + 0.9.15 (04/25/2000) david iacovelli + Updated enumeration + + 0.9.14 (04/24/2000) david iacovelli + Removed all config/status IOCTLS and + converted to using /proc/edgeport + still playing with devfs + + 0.9.13 (04/24/2000) david iacovelli + Removed configuration based on ttyUSB0 + Added support for configuration using /prod/edgeport + first attempt at using devfs (not working yet!) + Added IOCTL to GetProductInfo() + Added support for custom baud rates + Add support for random port numbers + + 0.9.12 (04/18/2000) david iacovelli + added additional configuration IOCTLs + use ttyUSB0 for configuration + + 0.9.11 (04/17/2000) greg kroah-hartman + fixed module initialization race conditions. + made all urbs dynamically allocated. + made driver devfs compatible. now it only registers the tty device + when the device is actually plugged in. + + 0.9.10 (04/13/2000) greg kroah-hartman + added proc interface framework. + + 0.9.9 (04/13/2000) david iacovelli + added enumeration code and ioctls to configure the device + + 0.9.8 (04/12/2000) david iacovelli + Change interrupt read start when device is plugged in + and stop when device is removed + process interrupt reads when all ports are closed + (keep value of rxBytesAvail consistent with the edgeport) + set the USB_BULK_QUEUE flag so that we can shove a bunch + of urbs at once down the pipe + + 0.9.7 (04/10/2000) david iacovelli + start to add enumeration code. + generate serial number for epic devices + add support for kdb + + 0.9.6 (03/30/2000) david iacovelli + add IOCTL to get string, manufacture, and boot descriptors + + 0.9.5 (03/14/2000) greg kroah-hartman + more error checking added to SerialOpen to try to fix UHCI open problem + + 0.9.4 (03/09/2000) greg kroah-hartman + added more error checking to handle oops when data is hanging + around and tty is abruptly closed. + + 0.9.3 (03/09/2000) david iacovelli + Add epic support for xon/xoff chars + play with performance + + 0.9.2 (03/08/2000) greg kroah-hartman + changed most "info" calls to "dbg" + implemented flow control properly in the termios call + + 0.9.1 (03/08/2000) david iacovelli + added EPIC support + enabled bootloader update + + 0.9 (03/08/2000) greg kroah-hartman + Release to IO networks. + Integrated changes that David made + made getting urbs for writing SMP safe + + 0.8 (03/07/2000) greg kroah-hartman + Release to IO networks. + Fixed problems that were seen in code by David. + Now both Edgeport/4 and Edgeport/2 works properly. + Changed most of the functions to use port instead of serial. + + 0.7 (02/27/2000) greg kroah-hartman + Milestone 3 release. + Release to IO Networks + ioctl for waiting on line change implemented. + ioctl for getting statistics implemented. + multiport support working. + lsr and msr registers are now handled properly. + change break now hooked up and working. + support for all known Edgeport devices. + + 0.6 (02/22/2000) greg kroah-hartman + Release to IO networks. + CHASE is implemented correctly when port is closed. + SerialOpen now blocks correctly until port is fully opened. + + 0.5 (02/20/2000) greg kroah-hartman + Release to IO networks. + Known problems: + modem status register changes are not sent on to the user + CHASE is not implemented when the port is closed. + + 0.4 (02/16/2000) greg kroah-hartman + Second cut at the CeBit demo. + Doesn't leak memory on every write to the port + Still small leaks on startup. + Added support for Edgeport/2 and Edgeport/8 + + 0.3 (02/15/2000) greg kroah-hartman + CeBit demo release. + Force the line settings to 4800, 8, 1, e for the demo. + Warning! This version leaks memory like crazy! + + 0.2 (01/30/2000) greg kroah-hartman + Milestone 1 release. + Device is found by USB subsystem, enumerated, fimware is downloaded + and the descriptors are printed to the debug log, config is set, and + green light starts to blink. Open port works, and data can be sent + and received at the default settings of the UART. Loopback connector + and debug log confirms this. + + 0.1 (01/23/2000) greg kroah-hartman + Initial release to help IO Networks try to set up their test system. + Edgeport4 is recognized, firmware is downloaded, config is set so + device blinks green light every 3 sec. Port is bound, but opening, + closing, and sending data do not work properly. + + diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 9438909..7b5e8e4 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -394,6 +394,15 @@ config USB_SERIAL_MCT_U232 To compile this driver as a module, choose M here: the module will be called mct_u232. +config USB_SERIAL_NOKIA_DKU2 + tristate "USB Nokia DKU2 Driver" + depends on USB_SERIAL + help + Say Y here if you want to use a Nokia DKU2 device. + + To compile this driver as a module, choose M here: the + module will be called nokia_dku2. + config USB_SERIAL_PL2303 tristate "USB Prolific 2303 Single Port Serial Driver" depends on USB_SERIAL diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 6c7cdcc..55fd461 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA) += keyspan_pda.o obj-$(CONFIG_USB_SERIAL_KLSI) += kl5kusb105.o obj-$(CONFIG_USB_SERIAL_KOBIL_SCT) += kobil_sct.o obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o +obj-$(CONFIG_USB_SERIAL_NOKIA_DKU2) += nokia_dku2.o obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o obj-$(CONFIG_USB_SERIAL_OPTION) += option.o obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index 926d4c2..1f29d88 100644 --- a/drivers/usb/serial/airprime.c +++ b/drivers/usb/serial/airprime.c @@ -30,9 +30,11 @@ static struct usb_driver airprime_driver = { .id_table = id_table, }; -static struct usb_serial_device_type airprime_device = { - .owner = THIS_MODULE, - .name = "airprime", +static struct usb_serial_driver airprime_device = { + .driver = { + .owner = THIS_MODULE, + .name = "airprime", + }, .id_table = id_table, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index abb1b2c..84bc0ee 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -121,10 +121,12 @@ static struct usb_driver belkin_driver = { }; /* All of the device info needed for the serial converters */ -static struct usb_serial_device_type belkin_device = { - .owner = THIS_MODULE, - .name = "Belkin / Peracom / GoHubs USB Serial Adapter", - .short_name = "belkin", +static struct usb_serial_driver belkin_device = { + .driver = { + .owner = THIS_MODULE, + .name = "belkin", + }, + .description = "Belkin / Peracom / GoHubs USB Serial Adapter", .id_table = id_table_combined, .num_interrupt_in = 1, .num_bulk_in = 1, diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index 2f612c2..664139a 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c @@ -18,7 +18,7 @@ static int usb_serial_device_match (struct device *dev, struct device_driver *drv) { - struct usb_serial_device_type *driver; + struct usb_serial_driver *driver; const struct usb_serial_port *port; /* @@ -44,7 +44,7 @@ struct bus_type usb_serial_bus_type = { static int usb_serial_device_probe (struct device *dev) { - struct usb_serial_device_type *driver; + struct usb_serial_driver *driver; struct usb_serial_port *port; int retval = 0; int minor; @@ -57,13 +57,13 @@ static int usb_serial_device_probe (struct device *dev) driver = port->serial->type; if (driver->port_probe) { - if (!try_module_get(driver->owner)) { + if (!try_module_get(driver->driver.owner)) { dev_err(dev, "module get failed, exiting\n"); retval = -EIO; goto exit; } retval = driver->port_probe (port); - module_put(driver->owner); + module_put(driver->driver.owner); if (retval) goto exit; } @@ -72,7 +72,7 @@ static int usb_serial_device_probe (struct device *dev) tty_register_device (usb_serial_tty_driver, minor, dev); dev_info(&port->serial->dev->dev, "%s converter now attached to ttyUSB%d\n", - driver->name, minor); + driver->description, minor); exit: return retval; @@ -80,7 +80,7 @@ exit: static int usb_serial_device_remove (struct device *dev) { - struct usb_serial_device_type *driver; + struct usb_serial_driver *driver; struct usb_serial_port *port; int retval = 0; int minor; @@ -92,43 +92,38 @@ static int usb_serial_device_remove (struct device *dev) driver = port->serial->type; if (driver->port_remove) { - if (!try_module_get(driver->owner)) { + if (!try_module_get(driver->driver.owner)) { dev_err(dev, "module get failed, exiting\n"); retval = -EIO; goto exit; } retval = driver->port_remove (port); - module_put(driver->owner); + module_put(driver->driver.owner); } exit: minor = port->number; tty_unregister_device (usb_serial_tty_driver, minor); dev_info(dev, "%s converter now disconnected from ttyUSB%d\n", - driver->name, minor); + driver->description, minor); return retval; } -int usb_serial_bus_register(struct usb_serial_device_type *device) +int usb_serial_bus_register(struct usb_serial_driver *driver) { int retval; - if (device->short_name) - device->driver.name = (char *)device->short_name; - else - device->driver.name = (char *)device->name; - device->driver.bus = &usb_serial_bus_type; - device->driver.probe = usb_serial_device_probe; - device->driver.remove = usb_serial_device_remove; - device->driver.owner = device->owner; + driver->driver.bus = &usb_serial_bus_type; + driver->driver.probe = usb_serial_device_probe; + driver->driver.remove = usb_serial_device_remove; - retval = driver_register(&device->driver); + retval = driver_register(&driver->driver); return retval; } -void usb_serial_bus_deregister(struct usb_serial_device_type *device) +void usb_serial_bus_deregister(struct usb_serial_driver *driver) { - driver_unregister (&device->driver); + driver_unregister(&driver->driver); } diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 97c78c2..c5334dd 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -67,15 +67,17 @@ MODULE_DEVICE_TABLE (usb, id_table); static struct usb_driver cp2101_driver = { .owner = THIS_MODULE, - .name = "CP2101", + .name = "cp2101", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, }; -static struct usb_serial_device_type cp2101_device = { - .owner = THIS_MODULE, - .name = "CP2101", +static struct usb_serial_driver cp2101_device = { + .driver = { + .owner = THIS_MODULE, + .name = "cp2101", + }, .id_table = id_table, .num_interrupt_in = 0, .num_bulk_in = 0, diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index b5b4310..e581e4a 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -83,10 +83,12 @@ static struct usb_driver cyberjack_driver = { .id_table = id_table, }; -static struct usb_serial_device_type cyberjack_device = { - .owner = THIS_MODULE, - .name = "Reiner SCT Cyberjack USB card reader", - .short_name = "cyberjack", +static struct usb_serial_driver cyberjack_device = { + .driver = { + .owner = THIS_MODULE, + .name = "cyberjack", + }, + .description = "Reiner SCT Cyberjack USB card reader", .id_table = id_table, .num_interrupt_in = 1, .num_bulk_in = 1, diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 9ee1aaf..af9290e 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -176,10 +176,12 @@ static unsigned int cypress_buf_put(struct cypress_buf *cb, const char *buf, u static unsigned int cypress_buf_get(struct cypress_buf *cb, char *buf, unsigned int count); -static struct usb_serial_device_type cypress_earthmate_device = { - .owner = THIS_MODULE, - .name = "DeLorme Earthmate USB", - .short_name = "earthmate", +static struct usb_serial_driver cypress_earthmate_device = { + .driver = { + .owner = THIS_MODULE, + .name = "earthmate", + }, + .description = "DeLorme Earthmate USB", .id_table = id_table_earthmate, .num_interrupt_in = 1, .num_interrupt_out = 1, @@ -203,10 +205,12 @@ static struct usb_serial_device_type cypress_earthmate_device = { .write_int_callback = cypress_write_int_callback, }; -static struct usb_serial_device_type cypress_hidcom_device = { - .owner = THIS_MODULE, - .name = "HID->COM RS232 Adapter", - .short_name = "cyphidcom", +static struct usb_serial_driver cypress_hidcom_device = { + .driver = { + .owner = THIS_MODULE, + .name = "cyphidcom", + }, + .description = "HID->COM RS232 Adapter", .id_table = id_table_cyphidcomrs232, .num_interrupt_in = 1, .num_interrupt_out = 1, diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index a19a47f..dc74644 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -503,10 +503,12 @@ static struct usb_driver digi_driver = { /* device info needed for the Digi serial converter */ -static struct usb_serial_device_type digi_acceleport_2_device = { - .owner = THIS_MODULE, - .name = "Digi 2 port USB adapter", - .short_name = "digi_2", +static struct usb_serial_driver digi_acceleport_2_device = { + .driver = { + .owner = THIS_MODULE, + .name = "digi_2", + }, + .description = "Digi 2 port USB adapter", .id_table = id_table_2, .num_interrupt_in = 0, .num_bulk_in = 4, @@ -530,10 +532,12 @@ static struct usb_serial_device_type digi_acceleport_2_device = { .shutdown = digi_shutdown, }; -static struct usb_serial_device_type digi_acceleport_4_device = { - .owner = THIS_MODULE, - .name = "Digi 4 port USB adapter", - .short_name = "digi_4", +static struct usb_serial_driver digi_acceleport_4_device = { + .driver = { + .owner = THIS_MODULE, + .name = "digi_4", + }, + .description = "Digi 4 port USB adapter", .id_table = id_table_4, .num_interrupt_in = 0, .num_bulk_in = 5, diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index 8d562ab..0b0546d 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c @@ -112,9 +112,11 @@ static struct usb_driver empeg_driver = { .id_table = id_table, }; -static struct usb_serial_device_type empeg_device = { - .owner = THIS_MODULE, - .name = "Empeg", +static struct usb_serial_driver empeg_device = { + .driver = { + .owner = THIS_MODULE, + .name = "empeg", + }, .id_table = id_table, .num_interrupt_in = 0, .num_bulk_in = 1, diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 5a8631c..61204bf 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -411,6 +411,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_ELV_UM100_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ELV_UR100_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ELV_ALC8500_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_PYRAMID_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1000PC_PID) }, /* * These will probably use user-space drivers. Uncomment them if * you need them or use the user-specified vendor/product module @@ -428,7 +430,6 @@ static struct usb_device_id id_table_combined [] = { /* { USB_DEVICE(FTDI_VID, FTDI_ELV_T1100_PID) }, */ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_PCD200_PID) }, */ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_ULA200_PID) }, */ - /* { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1000PC_PID) }, */ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_CSI8_PID) }, */ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_EM1000DL_PID) }, */ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_PCK100_PID) }, */ @@ -471,6 +472,9 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y6_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y8_PID) }, { USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HR_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; @@ -558,10 +562,12 @@ static unsigned short int ftdi_232am_baud_to_divisor (int baud); static __u32 ftdi_232bm_baud_base_to_divisor (int baud, int base); static __u32 ftdi_232bm_baud_to_divisor (int baud); -static struct usb_serial_device_type ftdi_sio_device = { - .owner = THIS_MODULE, - .name = "FTDI USB Serial Device", - .short_name = "ftdi_sio", +static struct usb_serial_driver ftdi_sio_device = { + .driver = { + .owner = THIS_MODULE, + .name = "ftdi_sio", + }, + .description = "FTDI USB Serial Device", .id_table = id_table_combined, .num_interrupt_in = 0, .num_bulk_in = 1, diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 2c35d74..ddb63df 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -199,6 +199,19 @@ #define FTDI_PIEGROUP_PID 0xF208 /* Product Id */ /* + * Definitions for Artemis astronomical USB based cameras + * Check it at http://www.artemisccd.co.uk/ + */ +#define FTDI_ARTEMIS_PID 0xDF28 /* All Artemis Cameras */ + +/* + * Definitions for ATIK Instruments astronomical USB based cameras + * Check it at http://www.atik-instruments.com/ + */ +#define FTDI_ATIK_ATK16_PID 0xDF30 /* ATIK ATK-16 Camera */ +#define FTDI_ATIK_ATK16HR_PID 0xDF31 /* ATIK ATK-16HR Camera */ + +/* * Protego product ids */ #define PROTEGO_SPECIAL_1 0xFC70 /* special/unknown device */ @@ -329,6 +342,9 @@ #define EVOLUTION_VID 0xDEEE /* Vendor ID */ #define EVOLUTION_ER1_PID 0x0300 /* ER1 Control Module */ +/* Pyramid Computer GmbH */ +#define FTDI_PYRAMID_PID 0xE6C8 /* Pyramid Appliance Display */ + /* Commands */ #define FTDI_SIO_RESET 0 /* Reset the port */ #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 2ef614d..35820bd 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -1468,16 +1468,13 @@ static void garmin_shutdown (struct usb_serial *serial) } - - - - - /* All of the device info needed */ -static struct usb_serial_device_type garmin_device = { - .owner = THIS_MODULE, - .name = "Garmin GPS usb/tty", - .short_name = "garmin_gps", +static struct usb_serial_driver garmin_device = { + .driver = { + .owner = THIS_MODULE, + .name = "garmin_gps", + }, + .description = "Garmin GPS usb/tty", .id_table = id_table, .num_interrupt_in = 1, .num_bulk_in = 1, diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 5f7d319..8909208 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -36,10 +36,11 @@ MODULE_PARM_DESC(product, "User specified USB idProduct"); static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */ /* All of the device info needed for the Generic Serial Converter */ -struct usb_serial_device_type usb_serial_generic_device = { - .owner = THIS_MODULE, - .name = "Generic", - .short_name = "generic", +struct usb_serial_driver usb_serial_generic_device = { + .driver = { + .owner = THIS_MODULE, + .name = "generic", + }, .id_table = generic_device_ids, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c index 64d55fb..8eadfb7 100644 --- a/drivers/usb/serial/hp4x.c +++ b/drivers/usb/serial/hp4x.c @@ -38,15 +38,17 @@ MODULE_DEVICE_TABLE(usb, id_table); static struct usb_driver hp49gp_driver = { .owner = THIS_MODULE, - .name = "HP4X", + .name = "hp4X", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, }; -static struct usb_serial_device_type hp49gp_device = { - .owner = THIS_MODULE, - .name = "HP4X", +static struct usb_serial_driver hp49gp_device = { + .driver = { + .owner = THIS_MODULE, + .name = "hp4X", + }, .id_table = id_table, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 04bfe27..dc4c498 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -27,225 +27,6 @@ * Networks technical support, or Peter Berger <pberger@brimson.com>, * or Al Borchers <alborchers@steinerpoint.com>. * - * Version history: - * - * 2003_04_03 al borchers - * - fixed a bug (that shows up with dosemu) where the tty struct is - * used in a callback after it has been freed - * - * 2.3 2002_03_08 greg kroah-hartman - * - fixed bug when multiple devices were attached at the same time. - * - * 2.2 2001_11_14 greg kroah-hartman - * - fixed bug in edge_close that kept the port from being used more - * than once. - * - fixed memory leak on device removal. - * - fixed potential double free of memory when command urb submitting - * failed. - * - other small cleanups when the device is removed - * - * 2.1 2001_07_09 greg kroah-hartman - * - added support for TIOCMBIS and TIOCMBIC. - * - * (04/08/2001) gb - * - Identify version on module load. - * - * 2.0 2001_03_05 greg kroah-hartman - * - reworked entire driver to fit properly in with the other usb-serial - * drivers. Occasional oopses still happen, but it's a good start. - * - * 1.2.3 (02/23/2001) greg kroah-hartman - * - changed device table to work properly for 2.4.x final format. - * - fixed problem with dropping data at high data rates. - * - * 1.2.2 (11/27/2000) greg kroah-hartman - * - cleaned up more NTisms. - * - Added device table for 2.4.0-test11 - * - * 1.2.1 (11/08/2000) greg kroah-hartman - * - Started to clean up NTisms. - * - Fixed problem with dev field of urb for kernels >= 2.4.0-test9 - * - * 1.2 (10/17/2000) David Iacovelli - * Remove all EPIC code and GPL source - * Fix RELEVANT_IFLAG macro to include flow control - * changes port configuration changes. - * Fix redefinition of SERIAL_MAGIC - * Change all timeout values to 5 seconds - * Tried to fix the UHCI multiple urb submission, but failed miserably. - * it seems to work fine with OHCI. - * ( Greg take a look at the #if 0 at end of WriteCmdUsb() we must - * find a way to work arount this UHCI bug ) - * - * 1.1 (10/11/2000) David Iacovelli - * Fix XON/XOFF flow control to support both IXON and IXOFF - * - * 0.9.27 (06/30/2000) David Iacovelli - * Added transmit queue and now allocate urb for command writes. - * - * 0.9.26 (06/29/2000) David Iacovelli - * Add support for 80251 based edgeport - * - * 0.9.25 (06/27/2000) David Iacovelli - * Do not close the port if it has multiple opens. - * - * 0.9.24 (05/26/2000) David Iacovelli - * Add IOCTLs to support RXTX and JAVA POS - * and first cut at running BlackBox Demo - * - * 0.9.23 (05/24/2000) David Iacovelli - * Add IOCTLs to support RXTX and JAVA POS - * - * 0.9.22 (05/23/2000) David Iacovelli - * fixed bug in enumeration. If epconfig turns on mapping by - * path after a device is already plugged in, we now update - * the mapping correctly - * - * 0.9.21 (05/16/2000) David Iacovelli - * Added BlockUntilChaseResp() to also wait for txcredits - * Updated the way we allocate and handle write URBs - * Add debug code to dump buffers - * - * 0.9.20 (05/01/2000) David Iacovelli - * change driver to use usb/tts/ - * - * 0.9.19 (05/01/2000) David Iacovelli - * Update code to compile if DEBUG is off - * - * 0.9.18 (04/28/2000) David Iacovelli - * cleanup and test tty_register with devfs - * - * 0.9.17 (04/27/2000) greg kroah-hartman - * changed tty_register around to be like the way it - * was before, but now it works properly with devfs. - * - * 0.9.16 (04/26/2000) david iacovelli - * Fixed bug in GetProductInfo() - * - * 0.9.15 (04/25/2000) david iacovelli - * Updated enumeration - * - * 0.9.14 (04/24/2000) david iacovelli - * Removed all config/status IOCTLS and - * converted to using /proc/edgeport - * still playing with devfs - * - * 0.9.13 (04/24/2000) david iacovelli - * Removed configuration based on ttyUSB0 - * Added support for configuration using /prod/edgeport - * first attempt at using devfs (not working yet!) - * Added IOCTL to GetProductInfo() - * Added support for custom baud rates - * Add support for random port numbers - * - * 0.9.12 (04/18/2000) david iacovelli - * added additional configuration IOCTLs - * use ttyUSB0 for configuration - * - * 0.9.11 (04/17/2000) greg kroah-hartman - * fixed module initialization race conditions. - * made all urbs dynamically allocated. - * made driver devfs compatible. now it only registers the tty device - * when the device is actually plugged in. - * - * 0.9.10 (04/13/2000) greg kroah-hartman - * added proc interface framework. - * - * 0.9.9 (04/13/2000) david iacovelli - * added enumeration code and ioctls to configure the device - * - * 0.9.8 (04/12/2000) david iacovelli - * Change interrupt read start when device is plugged in - * and stop when device is removed - * process interrupt reads when all ports are closed - * (keep value of rxBytesAvail consistent with the edgeport) - * set the USB_BULK_QUEUE flag so that we can shove a bunch - * of urbs at once down the pipe - * - * 0.9.7 (04/10/2000) david iacovelli - * start to add enumeration code. - * generate serial number for epic devices - * add support for kdb - * - * 0.9.6 (03/30/2000) david iacovelli - * add IOCTL to get string, manufacture, and boot descriptors - * - * 0.9.5 (03/14/2000) greg kroah-hartman - * more error checking added to SerialOpen to try to fix UHCI open problem - * - * 0.9.4 (03/09/2000) greg kroah-hartman - * added more error checking to handle oops when data is hanging - * around and tty is abruptly closed. - * - * 0.9.3 (03/09/2000) david iacovelli - * Add epic support for xon/xoff chars - * play with performance - * - * 0.9.2 (03/08/2000) greg kroah-hartman - * changed most "info" calls to "dbg" - * implemented flow control properly in the termios call - * - * 0.9.1 (03/08/2000) david iacovelli - * added EPIC support - * enabled bootloader update - * - * 0.9 (03/08/2000) greg kroah-hartman - * Release to IO networks. - * Integrated changes that David made - * made getting urbs for writing SMP safe - * - * 0.8 (03/07/2000) greg kroah-hartman - * Release to IO networks. - * Fixed problems that were seen in code by David. - * Now both Edgeport/4 and Edgeport/2 works properly. - * Changed most of the functions to use port instead of serial. - * - * 0.7 (02/27/2000) greg kroah-hartman - * Milestone 3 release. - * Release to IO Networks - * ioctl for waiting on line change implemented. - * ioctl for getting statistics implemented. - * multiport support working. - * lsr and msr registers are now handled properly. - * change break now hooked up and working. - * support for all known Edgeport devices. - * - * 0.6 (02/22/2000) greg kroah-hartman - * Release to IO networks. - * CHASE is implemented correctly when port is closed. - * SerialOpen now blocks correctly until port is fully opened. - * - * 0.5 (02/20/2000) greg kroah-hartman - * Release to IO networks. - * Known problems: - * modem status register changes are not sent on to the user - * CHASE is not implemented when the port is closed. - * - * 0.4 (02/16/2000) greg kroah-hartman - * Second cut at the CeBit demo. - * Doesn't leak memory on every write to the port - * Still small leaks on startup. - * Added support for Edgeport/2 and Edgeport/8 - * - * 0.3 (02/15/2000) greg kroah-hartman - * CeBit demo release. - * Force the line settings to 4800, 8, 1, e for the demo. - * Warning! This version leaks memory like crazy! - * - * 0.2 (01/30/2000) greg kroah-hartman - * Milestone 1 release. - * Device is found by USB subsystem, enumerated, fimware is downloaded - * and the descriptors are printed to the debug log, config is set, and - * green light starts to blink. Open port works, and data can be sent - * and received at the default settings of the UART. Loopback connector - * and debug log confirms this. - * - * 0.1 (01/23/2000) greg kroah-hartman - * Initial release to help IO Networks try to set up their test system. - * Edgeport4 is recognized, firmware is downloaded, config is set so - * device blinks green light every 3 sec. Port is bound, but opening, - * closing, and sending data do not work properly. - * */ #include <linux/config.h> diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h index e7ffe02..fad561c 100644 --- a/drivers/usb/serial/io_tables.h +++ b/drivers/usb/serial/io_tables.h @@ -75,10 +75,12 @@ static struct usb_device_id id_table_combined [] = { MODULE_DEVICE_TABLE (usb, id_table_combined); -static struct usb_serial_device_type edgeport_2port_device = { - .owner = THIS_MODULE, - .name = "Edgeport 2 port adapter", - .short_name = "edgeport_2", +static struct usb_serial_driver edgeport_2port_device = { + .driver = { + .owner = THIS_MODULE, + .name = "edgeport_2", + }, + .description = "Edgeport 2 port adapter", .id_table = edgeport_2port_id_table, .num_interrupt_in = 1, .num_bulk_in = 1, @@ -103,10 +105,12 @@ static struct usb_serial_device_type edgeport_2port_device = { .write_bulk_callback = edge_bulk_out_data_callback, }; -static struct usb_serial_device_type edgeport_4port_device = { - .owner = THIS_MODULE, - .name = "Edgeport 4 port adapter", - .short_name = "edgeport_4", +static struct usb_serial_driver edgeport_4port_device = { + .driver = { + .owner = THIS_MODULE, + .name = "edgeport_4", + }, + .description = "Edgeport 4 port adapter", .id_table = edgeport_4port_id_table, .num_interrupt_in = 1, .num_bulk_in = 1, @@ -131,10 +135,12 @@ static struct usb_serial_device_type edgeport_4port_device = { .write_bulk_callback = edge_bulk_out_data_callback, }; -static struct usb_serial_device_type edgeport_8port_device = { - .owner = THIS_MODULE, - .name = "Edgeport 8 port adapter", - .short_name = "edgeport_8", +static struct usb_serial_driver edgeport_8port_device = { + .driver = { + .owner = THIS_MODULE, + .name = "edgeport_8", + }, + .description = "Edgeport 8 port adapter", .id_table = edgeport_8port_id_table, .num_interrupt_in = 1, .num_bulk_in = 1, diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index ebf9967..832b6d6 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2982,10 +2982,12 @@ static unsigned int edge_buf_get(struct edge_buf *eb, char *buf, } -static struct usb_serial_device_type edgeport_1port_device = { - .owner = THIS_MODULE, - .name = "Edgeport TI 1 port adapter", - .short_name = "edgeport_ti_1", +static struct usb_serial_driver edgeport_1port_device = { + .driver = { + .owner = THIS_MODULE, + .name = "edgeport_ti_1", + }, + .description = "Edgeport TI 1 port adapter", .id_table = edgeport_1port_id_table, .num_interrupt_in = 1, .num_bulk_in = 1, @@ -3010,10 +3012,12 @@ static struct usb_serial_device_type edgeport_1port_device = { .write_bulk_callback = edge_bulk_out_callback, }; -static struct usb_serial_device_type edgeport_2port_device = { - .owner = THIS_MODULE, - .name = "Edgeport TI 2 port adapter", - .short_name = "edgeport_ti_2", +static struct usb_serial_driver edgeport_2port_device = { + .driver = { + .owner = THIS_MODULE, + .name = "edgeport_ti_2", + }, + .description = "Edgeport TI 2 port adapter", .id_table = edgeport_2port_id_table, .num_interrupt_in = 1, .num_bulk_in = 2, diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index c05c2a2..d5d0664 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -92,24 +92,7 @@ static void ipaq_destroy_lists(struct usb_serial_port *port); static struct usb_device_id ipaq_id_table [] = { /* The first entry is a placeholder for the insmod-specified device */ { USB_DEVICE(0x049F, 0x0003) }, - { USB_DEVICE(0x1690, 0x0601) }, /* Askey USB Sync */ - { USB_DEVICE(0x0960, 0x0065) }, /* BCOM USB Sync 0065 */ - { USB_DEVICE(0x0960, 0x0066) }, /* BCOM USB Sync 0066 */ - { USB_DEVICE(0x0960, 0x0067) }, /* BCOM USB Sync 0067 */ - { USB_DEVICE(0x07CF, 0x2001) }, /* CASIO USB Sync 2001 */ - { USB_DEVICE(0x07CF, 0x2002) }, /* CASIO USB Sync 2002 */ - { USB_DEVICE(0x07CF, 0x2003) }, /* CASIO USB Sync 2003 */ - { USB_DEVICE(0x049F, 0x0003) }, /* Compaq iPAQ USB Sync */ - { USB_DEVICE(0x049F, 0x0032) }, /* Compaq iPAQ USB Sync */ - { USB_DEVICE(0x413C, 0x4001) }, /* Dell Axim USB Sync */ - { USB_DEVICE(0x413C, 0x4002) }, /* Dell Axim USB Sync */ - { USB_DEVICE(0x413C, 0x4003) }, /* Dell Axim USB Sync */ - { USB_DEVICE(0x413C, 0x4004) }, /* Dell Axim USB Sync */ - { USB_DEVICE(0x413C, 0x4005) }, /* Dell Axim USB Sync */ - { USB_DEVICE(0x413C, 0x4006) }, /* Dell Axim USB Sync */ - { USB_DEVICE(0x413C, 0x4007) }, /* Dell Axim USB Sync */ - { USB_DEVICE(0x413C, 0x4008) }, /* Dell Axim USB Sync */ - { USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */ + { USB_DEVICE(0x0104, 0x00BE) }, /* Socket USB Sync */ { USB_DEVICE(0x03F0, 0x1016) }, /* HP USB Sync */ { USB_DEVICE(0x03F0, 0x1116) }, /* HP USB Sync 1611 */ { USB_DEVICE(0x03F0, 0x1216) }, /* HP USB Sync 1612 */ @@ -125,7 +108,13 @@ static struct usb_device_id ipaq_id_table [] = { { USB_DEVICE(0x03F0, 0x5016) }, /* HP USB Sync 1650 */ { USB_DEVICE(0x03F0, 0x5116) }, /* HP USB Sync 1651 */ { USB_DEVICE(0x03F0, 0x5216) }, /* HP USB Sync 1652 */ - { USB_DEVICE(0x094B, 0x0001) }, /* Linkup Systems USB Sync */ + { USB_DEVICE(0x0409, 0x00D5) }, /* NEC USB Sync */ + { USB_DEVICE(0x0409, 0x00D6) }, /* NEC USB Sync */ + { USB_DEVICE(0x0409, 0x00D7) }, /* NEC USB Sync */ + { USB_DEVICE(0x0409, 0x8024) }, /* NEC USB Sync */ + { USB_DEVICE(0x0409, 0x8025) }, /* NEC USB Sync */ + { USB_DEVICE(0x043E, 0x9C01) }, /* LGE USB Sync */ + { USB_DEVICE(0x045E, 0x00CE) }, /* Microsoft USB Sync */ { USB_DEVICE(0x045E, 0x0400) }, /* Windows Powered Pocket PC 2002 */ { USB_DEVICE(0x045E, 0x0401) }, /* Windows Powered Pocket PC 2002 */ { USB_DEVICE(0x045E, 0x0402) }, /* Windows Powered Pocket PC 2002 */ @@ -251,17 +240,81 @@ static struct usb_device_id ipaq_id_table [] = { { USB_DEVICE(0x045E, 0x04E8) }, /* Windows Powered Smartphone 2003 */ { USB_DEVICE(0x045E, 0x04E9) }, /* Windows Powered Smartphone 2003 */ { USB_DEVICE(0x045E, 0x04EA) }, /* Windows Powered Smartphone 2003 */ - { USB_DEVICE(0x0961, 0x0010) }, /* Portatec USB Sync */ - { USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */ - { USB_DEVICE(0x0104, 0x00BE) }, /* Socket USB Sync */ + { USB_DEVICE(0x049F, 0x0003) }, /* Compaq iPAQ USB Sync */ + { USB_DEVICE(0x049F, 0x0032) }, /* Compaq iPAQ USB Sync */ + { USB_DEVICE(0x04A4, 0x0014) }, /* Hitachi USB Sync */ + { USB_DEVICE(0x04AD, 0x0301) }, /* USB Sync 0301 */ + { USB_DEVICE(0x04AD, 0x0302) }, /* USB Sync 0302 */ + { USB_DEVICE(0x04AD, 0x0303) }, /* USB Sync 0303 */ + { USB_DEVICE(0x04C5, 0x1058) }, /* FUJITSU USB Sync */ + { USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */ + { USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */ + { USB_DEVICE(0x04E8, 0x5F00) }, /* Samsung NEXiO USB Sync */ + { USB_DEVICE(0x04E8, 0x5F01) }, /* Samsung NEXiO USB Sync */ + { USB_DEVICE(0x04E8, 0x5F02) }, /* Samsung NEXiO USB Sync */ + { USB_DEVICE(0x04E8, 0x5F03) }, /* Samsung NEXiO USB Sync */ + { USB_DEVICE(0x04E8, 0x5F04) }, /* Samsung NEXiO USB Sync */ + { USB_DEVICE(0x04E8, 0x6611) }, /* Samsung MITs USB Sync */ + { USB_DEVICE(0x04E8, 0x6613) }, /* Samsung MITs USB Sync */ + { USB_DEVICE(0x04E8, 0x6615) }, /* Samsung MITs USB Sync */ + { USB_DEVICE(0x04E8, 0x6617) }, /* Samsung MITs USB Sync */ + { USB_DEVICE(0x04E8, 0x6619) }, /* Samsung MITs USB Sync */ + { USB_DEVICE(0x04E8, 0x661B) }, /* Samsung MITs USB Sync */ + { USB_DEVICE(0x04E8, 0x662E) }, /* Samsung MITs USB Sync */ + { USB_DEVICE(0x04E8, 0x6630) }, /* Samsung MITs USB Sync */ + { USB_DEVICE(0x04E8, 0x6632) }, /* Samsung MITs USB Sync */ + { USB_DEVICE(0x04f1, 0x3011) }, /* JVC USB Sync */ + { USB_DEVICE(0x04F1, 0x3012) }, /* JVC USB Sync */ + { USB_DEVICE(0x0502, 0x1631) }, /* c10 Series */ + { USB_DEVICE(0x0502, 0x1632) }, /* c20 Series */ + { USB_DEVICE(0x0502, 0x16E1) }, /* Acer n10 Handheld USB Sync */ + { USB_DEVICE(0x0502, 0x16E2) }, /* Acer n20 Handheld USB Sync */ + { USB_DEVICE(0x0502, 0x16E3) }, /* Acer n30 Handheld USB Sync */ + { USB_DEVICE(0x0536, 0x01A0) }, /* HHP PDT */ + { USB_DEVICE(0x0543, 0x0ED9) }, /* ViewSonic Color Pocket PC V35 */ + { USB_DEVICE(0x0543, 0x1527) }, /* ViewSonic Color Pocket PC V36 */ + { USB_DEVICE(0x0543, 0x1529) }, /* ViewSonic Color Pocket PC V37 */ + { USB_DEVICE(0x0543, 0x152B) }, /* ViewSonic Color Pocket PC V38 */ + { USB_DEVICE(0x0543, 0x152E) }, /* ViewSonic Pocket PC */ + { USB_DEVICE(0x0543, 0x1921) }, /* ViewSonic Communicator Pocket PC */ + { USB_DEVICE(0x0543, 0x1922) }, /* ViewSonic Smartphone */ + { USB_DEVICE(0x0543, 0x1923) }, /* ViewSonic Pocket PC V30 */ + { USB_DEVICE(0x05E0, 0x2000) }, /* Symbol USB Sync */ + { USB_DEVICE(0x05E0, 0x2001) }, /* Symbol USB Sync 0x2001 */ + { USB_DEVICE(0x05E0, 0x2002) }, /* Symbol USB Sync 0x2002 */ + { USB_DEVICE(0x05E0, 0x2003) }, /* Symbol USB Sync 0x2003 */ + { USB_DEVICE(0x05E0, 0x2004) }, /* Symbol USB Sync 0x2004 */ + { USB_DEVICE(0x05E0, 0x2005) }, /* Symbol USB Sync 0x2005 */ + { USB_DEVICE(0x05E0, 0x2006) }, /* Symbol USB Sync 0x2006 */ + { USB_DEVICE(0x05E0, 0x2007) }, /* Symbol USB Sync 0x2007 */ + { USB_DEVICE(0x05E0, 0x2008) }, /* Symbol USB Sync 0x2008 */ + { USB_DEVICE(0x05E0, 0x2009) }, /* Symbol USB Sync 0x2009 */ + { USB_DEVICE(0x05E0, 0x200A) }, /* Symbol USB Sync 0x200A */ + { USB_DEVICE(0x067E, 0x1001) }, /* Intermec Mobile Computer */ + { USB_DEVICE(0x07CF, 0x2001) }, /* CASIO USB Sync 2001 */ + { USB_DEVICE(0x07CF, 0x2002) }, /* CASIO USB Sync 2002 */ + { USB_DEVICE(0x07CF, 0x2003) }, /* CASIO USB Sync 2003 */ { USB_DEVICE(0x0930, 0x0700) }, /* TOSHIBA USB Sync 0700 */ { USB_DEVICE(0x0930, 0x0705) }, /* TOSHIBA Pocket PC e310 */ + { USB_DEVICE(0x0930, 0x0706) }, /* TOSHIBA Pocket PC e740 */ { USB_DEVICE(0x0930, 0x0707) }, /* TOSHIBA Pocket PC e330 Series */ { USB_DEVICE(0x0930, 0x0708) }, /* TOSHIBA Pocket PC e350 Series */ - { USB_DEVICE(0x0930, 0x0706) }, /* TOSHIBA Pocket PC e740 */ { USB_DEVICE(0x0930, 0x0709) }, /* TOSHIBA Pocket PC e750 Series */ { USB_DEVICE(0x0930, 0x070A) }, /* TOSHIBA Pocket PC e400 Series */ { USB_DEVICE(0x0930, 0x070B) }, /* TOSHIBA Pocket PC e800 Series */ + { USB_DEVICE(0x094B, 0x0001) }, /* Linkup Systems USB Sync */ + { USB_DEVICE(0x0960, 0x0065) }, /* BCOM USB Sync 0065 */ + { USB_DEVICE(0x0960, 0x0066) }, /* BCOM USB Sync 0066 */ + { USB_DEVICE(0x0960, 0x0067) }, /* BCOM USB Sync 0067 */ + { USB_DEVICE(0x0961, 0x0010) }, /* Portatec USB Sync */ + { USB_DEVICE(0x099E, 0x0052) }, /* Trimble GeoExplorer */ + { USB_DEVICE(0x099E, 0x4000) }, /* TDS Data Collector */ + { USB_DEVICE(0x0B05, 0x4200) }, /* ASUS USB Sync */ + { USB_DEVICE(0x0B05, 0x4201) }, /* ASUS USB Sync */ + { USB_DEVICE(0x0B05, 0x4202) }, /* ASUS USB Sync */ + { USB_DEVICE(0x0B05, 0x420F) }, /* ASUS USB Sync */ + { USB_DEVICE(0x0B05, 0x9200) }, /* ASUS USB Sync */ + { USB_DEVICE(0x0B05, 0x9202) }, /* ASUS USB Sync */ { USB_DEVICE(0x0BB4, 0x00CE) }, /* HTC USB Sync */ { USB_DEVICE(0x0BB4, 0x0A01) }, /* PocketPC USB Sync */ { USB_DEVICE(0x0BB4, 0x0A02) }, /* PocketPC USB Sync */ @@ -422,116 +475,67 @@ static struct usb_device_id ipaq_id_table [] = { { USB_DEVICE(0x0BB4, 0x0A9D) }, /* SmartPhone USB Sync */ { USB_DEVICE(0x0BB4, 0x0A9E) }, /* SmartPhone USB Sync */ { USB_DEVICE(0x0BB4, 0x0A9F) }, /* SmartPhone USB Sync */ - { USB_DEVICE(0x0409, 0x00D5) }, /* NEC USB Sync */ - { USB_DEVICE(0x0409, 0x00D6) }, /* NEC USB Sync */ - { USB_DEVICE(0x0409, 0x00D7) }, /* NEC USB Sync */ - { USB_DEVICE(0x0409, 0x8024) }, /* NEC USB Sync */ - { USB_DEVICE(0x0409, 0x8025) }, /* NEC USB Sync */ - { USB_DEVICE(0x04A4, 0x0014) }, /* Hitachi USB Sync */ { USB_DEVICE(0x0BF8, 0x1001) }, /* Fujitsu Siemens Computers USB Sync */ - { USB_DEVICE(0x0F98, 0x0201) }, /* Cyberbank USB Sync */ - { USB_DEVICE(0x0502, 0x16E1) }, /* Acer n10 Handheld USB Sync */ - { USB_DEVICE(0x0502, 0x16E3) }, /* Acer n30 Handheld USB Sync */ - { USB_DEVICE(0x0502, 0x16E2) }, /* Acer n20 Handheld USB Sync */ - { USB_DEVICE(0x0502, 0x1631) }, /* c10 Series */ - { USB_DEVICE(0x0502, 0x1632) }, /* c20 Series */ - { USB_DEVICE(0x0B05, 0x9202) }, /* ASUS USB Sync */ - { USB_DEVICE(0x0B05, 0x420F) }, /* ASUS USB Sync */ - { USB_DEVICE(0x0B05, 0x4200) }, /* ASUS USB Sync */ - { USB_DEVICE(0x0B05, 0x4201) }, /* ASUS USB Sync */ - { USB_DEVICE(0x0B05, 0x4202) }, /* ASUS USB Sync */ - { USB_DEVICE(0x0B05, 0x9200) }, /* ASUS USB Sync */ + { USB_DEVICE(0x0C44, 0x03A2) }, /* Motorola iDEN Smartphone */ { USB_DEVICE(0x0C8E, 0x6000) }, /* Cesscom Luxian Series */ - { USB_DEVICE(0x04AD, 0x0301) }, /* USB Sync 0301 */ - { USB_DEVICE(0x04AD, 0x0302) }, /* USB Sync 0302 */ - { USB_DEVICE(0x04AD, 0x0303) }, /* USB Sync 0303 */ + { USB_DEVICE(0x0CAD, 0x9001) }, /* Motorola PowerPad Pocket PC Device */ + { USB_DEVICE(0x0F4E, 0x0200) }, /* Freedom Scientific USB Sync */ + { USB_DEVICE(0x0F98, 0x0201) }, /* Cyberbank USB Sync */ + { USB_DEVICE(0x0FB8, 0x3001) }, /* Wistron USB Sync */ + { USB_DEVICE(0x0FB8, 0x3002) }, /* Wistron USB Sync */ + { USB_DEVICE(0x0FB8, 0x3003) }, /* Wistron USB Sync */ + { USB_DEVICE(0x0FB8, 0x4001) }, /* Wistron USB Sync */ + { USB_DEVICE(0x1066, 0x00CE) }, /* E-TEN USB Sync */ { USB_DEVICE(0x1066, 0x0300) }, /* E-TEN P3XX Pocket PC */ { USB_DEVICE(0x1066, 0x0500) }, /* E-TEN P5XX Pocket PC */ { USB_DEVICE(0x1066, 0x0600) }, /* E-TEN P6XX Pocket PC */ { USB_DEVICE(0x1066, 0x0700) }, /* E-TEN P7XX Pocket PC */ - { USB_DEVICE(0x1066, 0x00CE) }, /* E-TEN USB Sync */ - { USB_DEVICE(0x0F4E, 0x0200) }, /* Freedom Scientific USB Sync */ - { USB_DEVICE(0x04C5, 0x1058) }, /* FUJITSU USB Sync */ - { USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */ - { USB_DEVICE(0x067E, 0x1001) }, /* Intermec Mobile Computer */ - { USB_DEVICE(0x04f1, 0x3011) }, /* JVC USB Sync */ - { USB_DEVICE(0x04F1, 0x3012) }, /* JVC USB Sync */ - { USB_DEVICE(0x3708, 0x20CE) }, /* Legend USB Sync */ - { USB_DEVICE(0x3708, 0x21CE) }, /* Lenovo USB Sync */ - { USB_DEVICE(0x043E, 0x9C01) }, /* LGE USB Sync */ - { USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */ - { USB_DEVICE(0x3340, 0x0B1C) }, /* Generic PPC StrongARM */ - { USB_DEVICE(0x3340, 0x0E3A) }, /* Generic PPC USB Sync */ - { USB_DEVICE(0x3340, 0x0F3A) }, /* Generic SmartPhone USB Sync */ - { USB_DEVICE(0x3340, 0x0F1C) }, /* Itautec USB Sync */ - { USB_DEVICE(0x3340, 0x1326) }, /* Itautec USB Sync */ - { USB_DEVICE(0x3340, 0x3326) }, /* MEDION Winodws Moble USB Sync */ + { USB_DEVICE(0x1114, 0x0001) }, /* Psion Teklogix Sync 753x */ + { USB_DEVICE(0x1114, 0x0004) }, /* Psion Teklogix Sync netBookPro */ + { USB_DEVICE(0x1114, 0x0006) }, /* Psion Teklogix Sync 7525 */ + { USB_DEVICE(0x1182, 0x1388) }, /* VES USB Sync */ + { USB_DEVICE(0x11D9, 0x1002) }, /* Rugged Pocket PC 2003 */ + { USB_DEVICE(0x11D9, 0x1003) }, /* Rugged Pocket PC 2003 */ + { USB_DEVICE(0x1231, 0xCE01) }, /* USB Sync 03 */ + { USB_DEVICE(0x1231, 0xCE02) }, /* USB Sync 03 */ + { USB_DEVICE(0x1690, 0x0601) }, /* Askey USB Sync */ + { USB_DEVICE(0x22B8, 0x4204) }, /* Motorola MPx200 Smartphone */ + { USB_DEVICE(0x22B8, 0x4214) }, /* Motorola MPc GSM */ + { USB_DEVICE(0x22B8, 0x4224) }, /* Motorola MPx220 Smartphone */ + { USB_DEVICE(0x22B8, 0x4234) }, /* Motorola MPc CDMA */ + { USB_DEVICE(0x22B8, 0x4244) }, /* Motorola MPx100 Smartphone */ + { USB_DEVICE(0x3340, 0x011C) }, /* Mio DigiWalker PPC StrongARM */ { USB_DEVICE(0x3340, 0x0326) }, /* Mio DigiWalker 338 */ { USB_DEVICE(0x3340, 0x0426) }, /* Mio DigiWalker 338 */ - { USB_DEVICE(0x3340, 0x011C) }, /* Mio DigiWalker PPC StrongARM */ - { USB_DEVICE(0x3340, 0x053A) }, /* Mio DigiWalker SmartPhone USB Sync */ { USB_DEVICE(0x3340, 0x043A) }, /* Mio DigiWalker USB Sync */ - { USB_DEVICE(0x3340, 0x071C) }, /* MiTAC USB Sync */ { USB_DEVICE(0x3340, 0x051C) }, /* MiTAC USB Sync 528 */ - { USB_DEVICE(0x3340, 0x2326) }, /* Vobis USB Sync */ + { USB_DEVICE(0x3340, 0x053A) }, /* Mio DigiWalker SmartPhone USB Sync */ + { USB_DEVICE(0x3340, 0x071C) }, /* MiTAC USB Sync */ + { USB_DEVICE(0x3340, 0x0B1C) }, /* Generic PPC StrongARM */ + { USB_DEVICE(0x3340, 0x0E3A) }, /* Generic PPC USB Sync */ + { USB_DEVICE(0x3340, 0x0F1C) }, /* Itautec USB Sync */ + { USB_DEVICE(0x3340, 0x0F3A) }, /* Generic SmartPhone USB Sync */ + { USB_DEVICE(0x3340, 0x1326) }, /* Itautec USB Sync */ { USB_DEVICE(0x3340, 0x191C) }, /* YAKUMO USB Sync */ + { USB_DEVICE(0x3340, 0x2326) }, /* Vobis USB Sync */ + { USB_DEVICE(0x3340, 0x3326) }, /* MEDION Winodws Moble USB Sync */ + { USB_DEVICE(0x3708, 0x20CE) }, /* Legend USB Sync */ + { USB_DEVICE(0x3708, 0x21CE) }, /* Lenovo USB Sync */ { USB_DEVICE(0x4113, 0x0210) }, /* Mobile Media Technology USB Sync */ { USB_DEVICE(0x4113, 0x0211) }, /* Mobile Media Technology USB Sync */ { USB_DEVICE(0x4113, 0x0400) }, /* Mobile Media Technology USB Sync */ { USB_DEVICE(0x4113, 0x0410) }, /* Mobile Media Technology USB Sync */ - { USB_DEVICE(0x0CAD, 0x9001) }, /* Motorola PowerPad Pocket PC Device */ - { USB_DEVICE(0x0C44, 0x03A2) }, /* Motorola iDEN Smartphone */ - { USB_DEVICE(0x04E8, 0x6611) }, /* Samsung MITs USB Sync */ - { USB_DEVICE(0x04E8, 0x6613) }, /* Samsung MITs USB Sync */ - { USB_DEVICE(0x04E8, 0x6615) }, /* Samsung MITs USB Sync */ - { USB_DEVICE(0x04E8, 0x6617) }, /* Samsung MITs USB Sync */ - { USB_DEVICE(0x04E8, 0x6619) }, /* Samsung MITs USB Sync */ - { USB_DEVICE(0x04E8, 0x661B) }, /* Samsung MITs USB Sync */ - { USB_DEVICE(0x04E8, 0x5F00) }, /* Samsung NEXiO USB Sync */ - { USB_DEVICE(0x04E8, 0x5F01) }, /* Samsung NEXiO USB Sync */ - { USB_DEVICE(0x04E8, 0x5F02) }, /* Samsung NEXiO USB Sync */ - { USB_DEVICE(0x04E8, 0x5F03) }, /* Samsung NEXiO USB Sync */ - { USB_DEVICE(0x04E8, 0x5F04) }, /* Samsung NEXiO USB Sync */ - { USB_DEVICE(0x04E8, 0x662E) }, /* Samsung MITs USB Sync */ - { USB_DEVICE(0x04E8, 0x6630) }, /* Samsung MITs USB Sync */ - { USB_DEVICE(0x04E8, 0x6632) }, /* Samsung MITs USB Sync */ + { USB_DEVICE(0x413C, 0x4001) }, /* Dell Axim USB Sync */ + { USB_DEVICE(0x413C, 0x4002) }, /* Dell Axim USB Sync */ + { USB_DEVICE(0x413C, 0x4003) }, /* Dell Axim USB Sync */ + { USB_DEVICE(0x413C, 0x4004) }, /* Dell Axim USB Sync */ + { USB_DEVICE(0x413C, 0x4005) }, /* Dell Axim USB Sync */ + { USB_DEVICE(0x413C, 0x4006) }, /* Dell Axim USB Sync */ + { USB_DEVICE(0x413C, 0x4007) }, /* Dell Axim USB Sync */ + { USB_DEVICE(0x413C, 0x4008) }, /* Dell Axim USB Sync */ + { USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */ { USB_DEVICE(0x4505, 0x0010) }, /* Smartphone */ - { USB_DEVICE(0x05E0, 0x2000) }, /* Symbol USB Sync */ - { USB_DEVICE(0x05E0, 0x2001) }, /* Symbol USB Sync 0x2001 */ - { USB_DEVICE(0x05E0, 0x2002) }, /* Symbol USB Sync 0x2002 */ - { USB_DEVICE(0x05E0, 0x2003) }, /* Symbol USB Sync 0x2003 */ - { USB_DEVICE(0x05E0, 0x2004) }, /* Symbol USB Sync 0x2004 */ - { USB_DEVICE(0x05E0, 0x2005) }, /* Symbol USB Sync 0x2005 */ - { USB_DEVICE(0x05E0, 0x2006) }, /* Symbol USB Sync 0x2006 */ - { USB_DEVICE(0x05E0, 0x2007) }, /* Symbol USB Sync 0x2007 */ - { USB_DEVICE(0x05E0, 0x2008) }, /* Symbol USB Sync 0x2008 */ - { USB_DEVICE(0x05E0, 0x2009) }, /* Symbol USB Sync 0x2009 */ - { USB_DEVICE(0x05E0, 0x200A) }, /* Symbol USB Sync 0x200A */ - { USB_DEVICE(0x1182, 0x1388) }, /* VES USB Sync */ - { USB_DEVICE(0x0543, 0x0ED9) }, /* ViewSonic Color Pocket PC V35 */ - { USB_DEVICE(0x0543, 0x1527) }, /* ViewSonic Color Pocket PC V36 */ - { USB_DEVICE(0x0543, 0x1529) }, /* ViewSonic Color Pocket PC V37 */ - { USB_DEVICE(0x0543, 0x152B) }, /* ViewSonic Color Pocket PC V38 */ - { USB_DEVICE(0x0543, 0x152E) }, /* ViewSonic Pocket PC */ - { USB_DEVICE(0x0543, 0x1921) }, /* ViewSonic Communicator Pocket PC */ - { USB_DEVICE(0x0543, 0x1922) }, /* ViewSonic Smartphone */ - { USB_DEVICE(0x0543, 0x1923) }, /* ViewSonic Pocket PC V30 */ - { USB_DEVICE(0x0536, 0x01A0) }, /* HHP PDT */ - { USB_DEVICE(0x099E, 0x0052) }, /* Trimble GeoExplorer */ - { USB_DEVICE(0x099E, 0x4000) }, /* TDS Data Collector */ - { USB_DEVICE(0x0FB8, 0x3001) }, /* Wistron USB Sync */ - { USB_DEVICE(0x0FB8, 0x3002) }, /* Wistron USB Sync */ - { USB_DEVICE(0x0FB8, 0x3003) }, /* Wistron USB Sync */ - { USB_DEVICE(0x0FB8, 0x4001) }, /* Wistron USB Sync */ - { USB_DEVICE(0x11D9, 0x1003) }, /* Rugged Pocket PC 2003 */ - { USB_DEVICE(0x11D9, 0x1002) }, /* Rugged Pocket PC 2003 */ - { USB_DEVICE(0x22B8, 0x4204) }, /* Motorola MPx200 Smartphone */ - { USB_DEVICE(0x22B8, 0x4214) }, /* Motorola MPc GSM */ - { USB_DEVICE(0x22B8, 0x4224) }, /* Motorola MPx220 Smartphone */ - { USB_DEVICE(0x22B8, 0x4234) }, /* Motorola MPc CDMA */ - { USB_DEVICE(0x22B8, 0x4244) }, /* Motorola MPx100 Smartphone */ - { USB_DEVICE(0x1231, 0xCE01) }, /* USB Sync 03 */ - { USB_DEVICE(0x1231, 0xCE02) }, /* USB Sync 03 */ + { USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */ { } /* Terminating entry */ }; @@ -547,9 +551,12 @@ static struct usb_driver ipaq_driver = { /* All of the device info needed for the Compaq iPAQ */ -static struct usb_serial_device_type ipaq_device = { - .owner = THIS_MODULE, - .name = "PocketPC PDA", +static struct usb_serial_driver ipaq_device = { + .driver = { + .owner = THIS_MODULE, + .name = "ipaq", + }, + .description = "PocketPC PDA", .id_table = ipaq_id_table, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = 1, diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 85e2424..a02fada 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -443,10 +443,12 @@ static int ipw_disconnect(struct usb_serial_port *port) return 0; } -static struct usb_serial_device_type ipw_device = { - .owner = THIS_MODULE, - .name = "IPWireless converter", - .short_name = "ipw", +static struct usb_serial_driver ipw_device = { + .driver = { + .owner = THIS_MODULE, + .name = "ipw", + }, + .description = "IPWireless converter", .id_table = usb_ipw_ids, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = 1, diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 937b2fd..19f329e 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -133,9 +133,12 @@ static struct usb_driver ir_driver = { }; -static struct usb_serial_device_type ir_device = { - .owner = THIS_MODULE, - .name = "IR Dongle", +static struct usb_serial_driver ir_device = { + .driver = { + .owner = THIS_MODULE, + .name = "ir-usb", + }, + .description = "IR Dongle", .id_table = id_table, .num_interrupt_in = 1, .num_bulk_in = 1, diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index e9b45b7..5cfc13b 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h @@ -570,10 +570,12 @@ static struct usb_device_id keyspan_4port_ids[] = { }; /* Structs for the devices, pre and post renumeration. */ -static struct usb_serial_device_type keyspan_pre_device = { - .owner = THIS_MODULE, - .name = "Keyspan - (without firmware)", - .short_name = "keyspan_no_firm", +static struct usb_serial_driver keyspan_pre_device = { + .driver = { + .owner = THIS_MODULE, + .name = "keyspan_no_firm", + }, + .description = "Keyspan - (without firmware)", .id_table = keyspan_pre_ids, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, @@ -582,10 +584,12 @@ static struct usb_serial_device_type keyspan_pre_device = { .attach = keyspan_fake_startup, }; -static struct usb_serial_device_type keyspan_1port_device = { - .owner = THIS_MODULE, - .name = "Keyspan 1 port adapter", - .short_name = "keyspan_1", +static struct usb_serial_driver keyspan_1port_device = { + .driver = { + .owner = THIS_MODULE, + .name = "keyspan_1", + }, + .description = "Keyspan 1 port adapter", .id_table = keyspan_1port_ids, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, @@ -607,10 +611,12 @@ static struct usb_serial_device_type keyspan_1port_device = { .shutdown = keyspan_shutdown, }; -static struct usb_serial_device_type keyspan_2port_device = { - .owner = THIS_MODULE, - .name = "Keyspan 2 port adapter", - .short_name = "keyspan_2", +static struct usb_serial_driver keyspan_2port_device = { + .driver = { + .owner = THIS_MODULE, + .name = "keyspan_2", + }, + .description = "Keyspan 2 port adapter", .id_table = keyspan_2port_ids, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, @@ -632,10 +638,12 @@ static struct usb_serial_device_type keyspan_2port_device = { .shutdown = keyspan_shutdown, }; -static struct usb_serial_device_type keyspan_4port_device = { - .owner = THIS_MODULE, - .name = "Keyspan 4 port adapter", - .short_name = "keyspan_4", +static struct usb_serial_driver keyspan_4port_device = { + .driver = { + .owner = THIS_MODULE, + .name = "keyspan_4", + }, + .description = "Keyspan 4 port adapter", .id_table = keyspan_4port_ids, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = 5, diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 635c384..cd4f48b 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -783,10 +783,12 @@ static void keyspan_pda_shutdown (struct usb_serial *serial) } #ifdef KEYSPAN -static struct usb_serial_device_type keyspan_pda_fake_device = { - .owner = THIS_MODULE, - .name = "Keyspan PDA - (prerenumeration)", - .short_name = "keyspan_pda_pre", +static struct usb_serial_driver keyspan_pda_fake_device = { + .driver = { + .owner = THIS_MODULE, + .name = "keyspan_pda_pre", + }, + .description = "Keyspan PDA - (prerenumeration)", .id_table = id_table_fake, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, @@ -797,10 +799,12 @@ static struct usb_serial_device_type keyspan_pda_fake_device = { #endif #ifdef XIRCOM -static struct usb_serial_device_type xircom_pgs_fake_device = { - .owner = THIS_MODULE, - .name = "Xircom / Entregra PGS - (prerenumeration)", - .short_name = "xircom_no_firm", +static struct usb_serial_driver xircom_pgs_fake_device = { + .driver = { + .owner = THIS_MODULE, + .name = "xircom_no_firm", + }, + .description = "Xircom / Entregra PGS - (prerenumeration)", .id_table = id_table_fake_xircom, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, @@ -810,10 +814,12 @@ static struct usb_serial_device_type xircom_pgs_fake_device = { }; #endif -static struct usb_serial_device_type keyspan_pda_device = { - .owner = THIS_MODULE, - .name = "Keyspan PDA", - .short_name = "keyspan_pda", +static struct usb_serial_driver keyspan_pda_device = { + .driver = { + .owner = THIS_MODULE, + .name = "keyspan_pda", + }, + .description = "Keyspan PDA", .id_table = id_table_std, .num_interrupt_in = 1, .num_bulk_in = 0, diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index a11e829..a8951c0 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -123,10 +123,12 @@ static struct usb_driver kl5kusb105d_driver = { .id_table = id_table, }; -static struct usb_serial_device_type kl5kusb105d_device = { - .owner = THIS_MODULE, - .name = "KL5KUSB105D / PalmConnect", - .short_name = "kl5kusb105d", +static struct usb_serial_driver kl5kusb105d_device = { + .driver = { + .owner = THIS_MODULE, + .name = "kl5kusb105d", + }, + .description = "KL5KUSB105D / PalmConnect", .id_table = id_table, .num_interrupt_in = 1, .num_bulk_in = 1, diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index fe4c98a..9456dd9 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -105,9 +105,12 @@ static struct usb_driver kobil_driver = { }; -static struct usb_serial_device_type kobil_device = { - .owner = THIS_MODULE, - .name = "KOBIL USB smart card terminal", +static struct usb_serial_driver kobil_device = { + .driver = { + .owner = THIS_MODULE, + .name = "kobil", + }, + .description = "KOBIL USB smart card terminal", .id_table = id_table, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = 0, diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 50b63696..ca5dbad 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -132,10 +132,12 @@ static struct usb_driver mct_u232_driver = { .id_table = id_table_combined, }; -static struct usb_serial_device_type mct_u232_device = { - .owner = THIS_MODULE, - .name = "MCT U232", - .short_name = "mct_u232", +static struct usb_serial_driver mct_u232_device = { + .driver = { + .owner = THIS_MODULE, + .name = "mct_u232", + }, + .description = "MCT U232", .id_table = id_table_combined, .num_interrupt_in = 2, .num_bulk_in = 0, diff --git a/drivers/usb/serial/nokia_dku2.c b/drivers/usb/serial/nokia_dku2.c new file mode 100644 index 0000000..fad01be --- /dev/null +++ b/drivers/usb/serial/nokia_dku2.c @@ -0,0 +1,142 @@ +/* + * Nokia DKU2 USB driver + * + * Copyright (C) 2004 + * Author: C Kemp + * + * This program is largely derived from work by the linux-usb group + * and associated source files. Please see the usb/serial files for + * individual credits and copyrights. + * + * 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. + * + * 20.09.2005 - Matthias Blaesing <matthias.blaesing@rwth-aachen.de> + * Added short name to device structure to make driver load into kernel 2.6.13 + * + * 20.09.2005 - Matthias Blaesing <matthias.blaesing@rwth-aachen.de> + * Added usb_deregister to exit code - to allow remove and reinsert of module + */ + + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/tty.h> +#include <linux/tty_driver.h> +#include <linux/tty_flip.h> +#include <linux/module.h> +#include <linux/usb.h> +#include "usb-serial.h" + + +#define NOKIA_VENDOR_ID 0x0421 +#define NOKIA7600_PRODUCT_ID 0x0400 +#define NOKIA6230_PRODUCT_ID 0x040f +#define NOKIA6170_PRODUCT_ID 0x0416 +#define NOKIA6670_PRODUCT_ID 0x041d +#define NOKIA6680_PRODUCT_ID 0x041e +#define NOKIA6230i_PRODUCT_ID 0x0428 + +#define NOKIA_AT_PORT 0x82 +#define NOKIA_FBUS_PORT 0x86 + +/* + * Version Information + */ +#define DRIVER_VERSION "v0.2" +#define DRIVER_AUTHOR "C Kemp" +#define DRIVER_DESC "Nokia DKU2 Driver" + +static struct usb_device_id id_table [] = { + { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA7600_PRODUCT_ID) }, + { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6230_PRODUCT_ID) }, + { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6170_PRODUCT_ID) }, + { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6670_PRODUCT_ID) }, + { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6680_PRODUCT_ID) }, + { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6230i_PRODUCT_ID) }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, id_table); + +/* The only thing which makes this device different from a generic + * device is that we have to set an alternative configuration to make + * the relevant endpoints available. In 2.6 this is really easy... */ +static int nokia_probe(struct usb_serial *serial, + const struct usb_device_id *id) +{ + int retval = -ENODEV; + + if (serial->interface->altsetting[0].endpoint[0].desc.bEndpointAddress == NOKIA_AT_PORT) { + /* the AT port */ + dev_info(&serial->dev->dev, "Nokia AT Port:\n"); + retval = 0; + } else if (serial->interface->num_altsetting == 2 && + serial->interface->altsetting[1].endpoint[0].desc.bEndpointAddress == NOKIA_FBUS_PORT) { + /* the FBUS port */ + dev_info(&serial->dev->dev, "Nokia FBUS Port:\n"); + usb_set_interface(serial->dev, 10, 1); + retval = 0; + } + + return retval; +} + +static struct usb_driver nokia_driver = { + .owner = THIS_MODULE, + .name = "nokia_dku2", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, +}; + +static struct usb_serial_driver nokia_serial_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "nokia_dku2", + }, + .description = "Nokia 7600/6230(i)/6170/66x0 DKU2 driver", + .id_table = id_table, + .num_interrupt_in = 1, + .num_bulk_in = 1, + .num_bulk_out = 1, + .num_ports = 1, + .probe = nokia_probe, +}; + +static int __init nokia_init(void) +{ + int retval; + + retval = usb_serial_register(&nokia_serial_driver); + if (retval) + return retval; + + retval = usb_register(&nokia_driver); + if (retval) { + usb_serial_deregister(&nokia_serial_driver); + return retval; + } + + info(DRIVER_VERSION " " DRIVER_AUTHOR); + info(DRIVER_DESC); + + return retval; +} + +static void __exit nokia_exit(void) +{ + usb_deregister(&nokia_driver); + usb_serial_deregister(&nokia_serial_driver); +} + +module_init(nokia_init); +module_exit(nokia_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 6a99ae1..3caf970 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -88,10 +88,12 @@ static struct usb_driver omninet_driver = { }; -static struct usb_serial_device_type zyxel_omninet_device = { - .owner = THIS_MODULE, - .name = "ZyXEL - omni.net lcd plus usb", - .short_name = "omninet", +static struct usb_serial_driver zyxel_omninet_device = { + .driver = { + .owner = THIS_MODULE, + .name = "omninet", + }, + .description = "ZyXEL - omni.net lcd plus usb", .id_table = id_table, .num_interrupt_in = 1, .num_bulk_in = 1, diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 4989e57..7716000 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -105,10 +105,12 @@ static struct usb_driver option_driver = { /* The card has three separate interfaces, wich the serial driver * recognizes separately, thus num_port=1. */ -static struct usb_serial_device_type option_3port_device = { - .owner = THIS_MODULE, - .name = "Option 3G data card", - .short_name = "option", +static struct usb_serial_driver option_3port_device = { + .driver = { + .owner = THIS_MODULE, + .name = "option", + }, + .description = "Option 3G data card", .id_table = option_ids, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 3cf245b..165c119 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -8,31 +8,10 @@ * * 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. + * the Free Software Foundation; either version 2 of the License. * * See Documentation/usb/usb-serial.txt for more information on using this driver * - * 2002_Mar_26 gkh - * allowed driver to work properly if there is no tty assigned to a port - * (this happens for serial console devices.) - * - * 2001_Oct_06 gkh - * Added RTS and DTR line control. Thanks to joe@bndlg.de for parts of it. - * - * 2001_Sep_19 gkh - * Added break support. - * - * 2001_Aug_30 gkh - * fixed oops in write_bulk_callback. - * - * 2001_Aug_28 gkh - * reworked buffer logic to be like other usb-serial drivers. Hopefully - * removing some reported problems. - * - * 2001_Jun_06 gkh - * finished porting to 2.4 format. - * */ #include <linux/config.h> @@ -55,7 +34,6 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.12" #define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver" static int debug; @@ -175,9 +153,11 @@ static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf, /* All of the device info needed for the PL2303 SIO serial converter */ -static struct usb_serial_device_type pl2303_device = { - .owner = THIS_MODULE, - .name = "PL-2303", +static struct usb_serial_driver pl2303_device = { + .driver = { + .owner = THIS_MODULE, + .name = "pl2303", + }, .id_table = id_table, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = 1, @@ -1195,7 +1175,7 @@ static int __init pl2303_init (void) retval = usb_register(&pl2303_driver); if (retval) goto failed_usb_register; - info(DRIVER_DESC " " DRIVER_VERSION); + info(DRIVER_DESC); return 0; failed_usb_register: usb_serial_deregister(&pl2303_device); @@ -1215,7 +1195,6 @@ module_init(pl2303_init); module_exit(pl2303_exit); MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c index 96a1756..c22bdc0 100644 --- a/drivers/usb/serial/safe_serial.c +++ b/drivers/usb/serial/safe_serial.c @@ -92,7 +92,7 @@ MODULE_DESCRIPTION (DRIVER_DESC); MODULE_LICENSE("GPL"); #if defined(CONFIG_USBD_SAFE_SERIAL_VENDOR) && !defined(CONFIG_USBD_SAFE_SERIAL_PRODUCT) -#abort "SAFE_SERIAL_VENDOR defined without SAFE_SERIAL_PRODUCT" +#error "SAFE_SERIAL_VENDOR defined without SAFE_SERIAL_PRODUCT" #endif #if ! defined(CONFIG_USBD_SAFE_SERIAL_VENDOR) @@ -397,9 +397,11 @@ static int safe_startup (struct usb_serial *serial) return 0; } -static struct usb_serial_device_type safe_device = { - .owner = THIS_MODULE, - .name = "Safe", +static struct usb_serial_driver safe_device = { + .driver = { + .owner = THIS_MODULE, + .name = "safe_serial", + }, .id_table = id_table, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 59c88de..205dbf7 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -255,9 +255,12 @@ static struct usb_driver ti_usb_driver = { .id_table = ti_id_table_combined, }; -static struct usb_serial_device_type ti_1port_device = { - .owner = THIS_MODULE, - .name = "TI USB 3410 1 port adapter", +static struct usb_serial_driver ti_1port_device = { + .driver = { + .owner = THIS_MODULE, + .name = "ti_usb_3410_5052_1", + }, + .description = "TI USB 3410 1 port adapter", .id_table = ti_id_table_3410, .num_interrupt_in = 1, .num_bulk_in = 1, @@ -282,9 +285,12 @@ static struct usb_serial_device_type ti_1port_device = { .write_bulk_callback = ti_bulk_out_callback, }; -static struct usb_serial_device_type ti_2port_device = { - .owner = THIS_MODULE, - .name = "TI USB 5052 2 port adapter", +static struct usb_serial_driver ti_2port_device = { + .driver = { + .owner = THIS_MODULE, + .name = "ti_usb_3410_5052_2", + }, + .description = "TI USB 5052 2 port adapter", .id_table = ti_id_table_5052, .num_interrupt_in = 1, .num_bulk_in = 2, diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index e77fbdf..0c4881d 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1,7 +1,7 @@ /* * USB Serial Converter driver * - * Copyright (C) 1999 - 2004 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 1999 - 2005 Greg Kroah-Hartman (greg@kroah.com) * Copyright (C) 2000 Peter Berger (pberger@brimson.com) * Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com) * @@ -9,316 +9,11 @@ * modify it under the terms of the GNU General Public License version * 2 as published by the Free Software Foundation. * - * This driver was originally based on the ACM driver by Armin Fuerst (which was + * This driver was originally based on the ACM driver by Armin Fuerst (which was * based on a driver by Brad Keryan) * * See Documentation/usb/usb-serial.txt for more information on using this driver * - * (12/10/2002) gkh - * Split the ports off into their own struct device, and added a - * usb-serial bus driver. - * - * (11/19/2002) gkh - * removed a few #ifdefs for the generic code and cleaned up the failure - * logic in initialization. - * - * (10/02/2002) gkh - * moved the console code to console.c and out of this file. - * - * (06/05/2002) gkh - * moved location of startup() call in serial_probe() until after all - * of the port information and endpoints are initialized. This makes - * things easier for some drivers. - * - * (04/10/2002) gkh - * added serial_read_proc function which creates a - * /proc/tty/driver/usb-serial file. - * - * (03/27/2002) gkh - * Got USB serial console code working properly and merged into the main - * version of the tree. Thanks to Randy Dunlap for the initial version - * of this code, and for pushing me to finish it up. - * The USB serial console works with any usb serial driver device. - * - * (03/21/2002) gkh - * Moved all manipulation of port->open_count into the core. Now the - * individual driver's open and close functions are called only when the - * first open() and last close() is called. Making the drivers a bit - * smaller and simpler. - * Fixed a bug if a driver didn't have the owner field set. - * - * (02/26/2002) gkh - * Moved all locking into the main serial_* functions, instead of having - * the individual drivers have to grab the port semaphore. This should - * reduce races. - * Reworked the MOD_INC logic a bit to always increment and decrement, even - * if the generic driver is being used. - * - * (10/10/2001) gkh - * usb_serial_disconnect() now sets the serial->dev pointer is to NULL to - * help prevent child drivers from accessing the device since it is now - * gone. - * - * (09/13/2001) gkh - * Moved generic driver initialize after we have registered with the USB - * core. Thanks to Randy Dunlap for pointing this problem out. - * - * (07/03/2001) gkh - * Fixed module paramater size. Thanks to John Brockmeyer for the pointer. - * Fixed vendor and product getting defined through the MODULE_PARM macro - * if the Generic driver wasn't compiled in. - * Fixed problem with generic_shutdown() not being called for drivers that - * don't have a shutdown() function. - * - * (06/06/2001) gkh - * added evil hack that is needed for the prolific pl2303 device due to the - * crazy way its endpoints are set up. - * - * (05/30/2001) gkh - * switched from using spinlock to a semaphore, which fixes lots of problems. - * - * (04/08/2001) gb - * Identify version on module load. - * - * 2001_02_05 gkh - * Fixed buffer overflows bug with the generic serial driver. Thanks to - * Todd Squires <squirest@ct0.com> for fixing this. - * - * (01/10/2001) gkh - * Fixed bug where the generic serial adaptor grabbed _any_ device that was - * offered to it. - * - * (12/12/2000) gkh - * Removed MOD_INC and MOD_DEC from poll and disconnect functions, and - * moved them to the serial_open and serial_close functions. - * Also fixed bug with there not being a MOD_DEC for the generic driver - * (thanks to Gary Brubaker for finding this.) - * - * (11/29/2000) gkh - * Small NULL pointer initialization cleanup which saves a bit of disk image - * - * (11/01/2000) Adam J. Richter - * instead of using idVendor/idProduct pairs, usb serial drivers - * now identify their hardware interest with usb_device_id tables, - * which they usually have anyhow for use with MODULE_DEVICE_TABLE. - * - * (10/05/2000) gkh - * Fixed bug with urb->dev not being set properly, now that the usb - * core needs it. - * - * (09/11/2000) gkh - * Removed DEBUG #ifdefs with call to usb_serial_debug_data - * - * (08/28/2000) gkh - * Added port_lock to port structure. - * Added locks for SMP safeness to generic driver - * Fixed the ability to open a generic device's port more than once. - * - * (07/23/2000) gkh - * Added bulk_out_endpointAddress to port structure. - * - * (07/19/2000) gkh, pberger, and borchers - * Modifications to allow usb-serial drivers to be modules. - * - * (07/03/2000) gkh - * Added more debugging to serial_ioctl call - * - * (06/25/2000) gkh - * Changed generic_write_bulk_callback to not call wake_up_interruptible - * directly, but to have port_softint do it at a safer time. - * - * (06/23/2000) gkh - * Cleaned up debugging statements in a quest to find UHCI timeout bug. - * - * (05/22/2000) gkh - * Changed the makefile, enabling the big CONFIG_USB_SERIAL_SOMTHING to be - * removed from the individual device source files. - * - * (05/03/2000) gkh - * Added the Digi Acceleport driver from Al Borchers and Peter Berger. - * - * (05/02/2000) gkh - * Changed devfs and tty register code to work properly now. This was based on - * the ACM driver changes by Vojtech Pavlik. - * - * (04/27/2000) Ryan VanderBijl - * Put calls to *_paranoia_checks into one function. - * - * (04/23/2000) gkh - * Fixed bug that Randy Dunlap found for Generic devices with no bulk out ports. - * Moved when the startup code printed out the devices that are supported. - * - * (04/19/2000) gkh - * Added driver for ZyXEL omni.net lcd plus ISDN TA - * Made startup info message specify which drivers were compiled in. - * - * (04/03/2000) gkh - * Changed the probe process to remove the module unload races. - * Changed where the tty layer gets initialized to have devfs work nicer. - * Added initial devfs support. - * - * (03/26/2000) gkh - * Split driver up into device specific pieces. - * - * (03/19/2000) gkh - * Fixed oops that could happen when device was removed while a program - * was talking to the device. - * Removed the static urbs and now all urbs are created and destroyed - * dynamically. - * Reworked the internal interface. Now everything is based on the - * usb_serial_port structure instead of the larger usb_serial structure. - * This fixes the bug that a multiport device could not have more than - * one port open at one time. - * - * (03/17/2000) gkh - * Added config option for debugging messages. - * Added patch for keyspan pda from Brian Warner. - * - * (03/06/2000) gkh - * Added the keyspan pda code from Brian Warner <warner@lothar.com> - * Moved a bunch of the port specific stuff into its own structure. This - * is in anticipation of the true multiport devices (there's a bug if you - * try to access more than one port of any multiport device right now) - * - * (02/21/2000) gkh - * Made it so that any serial devices only have to specify which functions - * they want to overload from the generic function calls (great, - * inheritance in C, in a driver, just what I wanted...) - * Added support for set_termios and ioctl function calls. No drivers take - * advantage of this yet. - * Removed the #ifdef MODULE, now there is no module specific code. - * Cleaned up a few comments in usb-serial.h that were wrong (thanks again - * to Miles Lott). - * Small fix to get_free_serial. - * - * (02/14/2000) gkh - * Removed the Belkin and Peracom functionality from the driver due to - * the lack of support from the vendor, and me not wanting people to - * accidenatly buy the device, expecting it to work with Linux. - * Added read_bulk_callback and write_bulk_callback to the type structure - * for the needs of the FTDI and WhiteHEAT driver. - * Changed all reverences to FTDI to FTDI_SIO at the request of Bill - * Ryder. - * Changed the output urb size back to the max endpoint size to make - * the ftdi_sio driver have it easier, and due to the fact that it didn't - * really increase the speed any. - * - * (02/11/2000) gkh - * Added VISOR_FUNCTION_CONSOLE to the visor startup function. This was a - * patch from Miles Lott (milos@insync.net). - * Fixed bug with not restoring the minor range that a device grabs, if - * the startup function fails (thanks Miles for finding this). - * - * (02/05/2000) gkh - * Added initial framework for the Keyspan PDA serial converter so that - * Brian Warner has a place to put his code. - * Made the ezusb specific functions generic enough that different - * devices can use them (whiteheat and keyspan_pda both need them). - * Split out a whole bunch of structure and other stuff to a separate - * usb-serial.h file. - * Made the Visor connection messages a little more understandable, now - * that Miles Lott (milos@insync.net) has gotten the Generic channel to - * work. Also made them always show up in the log file. - * - * (01/25/2000) gkh - * Added initial framework for FTDI serial converter so that Bill Ryder - * has a place to put his code. - * Added the vendor specific info from Handspring. Now we can print out - * informational debug messages as well as understand what is happening. - * - * (01/23/2000) gkh - * Fixed problem of crash when trying to open a port that didn't have a - * device assigned to it. Made the minor node finding a little smarter, - * now it looks to find a continuous space for the new device. - * - * (01/21/2000) gkh - * Fixed bug in visor_startup with patch from Miles Lott (milos@insync.net) - * Fixed get_serial_by_minor which was all messed up for multi port - * devices. Fixed multi port problem for generic devices. Now the number - * of ports is determined by the number of bulk out endpoints for the - * generic device. - * - * (01/19/2000) gkh - * Removed lots of cruft that was around from the old (pre urb) driver - * interface. - * Made the serial_table dynamic. This should save lots of memory when - * the number of minor nodes goes up to 256. - * Added initial support for devices that have more than one port. - * Added more debugging comments for the Visor, and added a needed - * set_configuration call. - * - * (01/17/2000) gkh - * Fixed the WhiteHEAT firmware (my processing tool had a bug) - * and added new debug loader firmware for it. - * Removed the put_char function as it isn't really needed. - * Added visor startup commands as found by the Win98 dump. - * - * (01/13/2000) gkh - * Fixed the vendor id for the generic driver to the one I meant it to be. - * - * (01/12/2000) gkh - * Forget the version numbering...that's pretty useless... - * Made the driver able to be compiled so that the user can select which - * converter they want to use. This allows people who only want the Visor - * support to not pay the memory size price of the WhiteHEAT. - * Fixed bug where the generic driver (idVendor=0000 and idProduct=0000) - * grabbed the root hub. Not good. - * - * version 0.4.0 (01/10/2000) gkh - * Added whiteheat.h containing the firmware for the ConnectTech WhiteHEAT - * device. Added startup function to allow firmware to be downloaded to - * a device if it needs to be. - * Added firmware download logic to the WhiteHEAT device. - * Started to add #defines to split up the different drivers for potential - * configuration option. - * - * version 0.3.1 (12/30/99) gkh - * Fixed problems with urb for bulk out. - * Added initial support for multiple sets of endpoints. This enables - * the Handspring Visor to be attached successfully. Only the first - * bulk in / bulk out endpoint pair is being used right now. - * - * version 0.3.0 (12/27/99) gkh - * Added initial support for the Handspring Visor based on a patch from - * Miles Lott (milos@sneety.insync.net) - * Cleaned up the code a bunch and converted over to using urbs only. - * - * version 0.2.3 (12/21/99) gkh - * Added initial support for the Connect Tech WhiteHEAT converter. - * Incremented the number of ports in expectation of getting the - * WhiteHEAT to work properly (4 ports per connection). - * Added notification on insertion and removal of what port the - * device is/was connected to (and what kind of device it was). - * - * version 0.2.2 (12/16/99) gkh - * Changed major number to the new allocated number. We're legal now! - * - * version 0.2.1 (12/14/99) gkh - * Fixed bug that happens when device node is opened when there isn't a - * device attached to it. Thanks to marek@webdesign.no for noticing this. - * - * version 0.2.0 (11/10/99) gkh - * Split up internals to make it easier to add different types of serial - * converters to the code. - * Added a "generic" driver that gets it's vendor and product id - * from when the module is loaded. Thanks to David E. Nelson (dnelson@jump.net) - * for the idea and sample code (from the usb scanner driver.) - * Cleared up any licensing questions by releasing it under the GNU GPL. - * - * version 0.1.2 (10/25/99) gkh - * Fixed bug in detecting device. - * - * version 0.1.1 (10/05/99) gkh - * Changed the major number to not conflict with anything else. - * - * version 0.1 (09/28/99) gkh - * Can recognize the two different devices and start up a read from - * device when asked to. Writes also work. No control signals yet, this - * all is vendor specific data (i.e. no spec), also no control for - * different baud rates or other bit settings. - * Currently we are using the same devid as the acm driver. This needs - * to change. - * */ #include <linux/config.h> @@ -342,7 +37,6 @@ /* * Version Information */ -#define DRIVER_VERSION "v2.0" #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/" #define DRIVER_DESC "USB Serial Driver core" @@ -427,7 +121,7 @@ static void destroy_serial(struct kref *kref) serial = to_usb_serial(kref); - dbg ("%s - %s", __FUNCTION__, serial->type->name); + dbg("%s - %s", __FUNCTION__, serial->type->description); serial->type->shutdown(serial); @@ -507,7 +201,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp) /* lock this module before we call it * this may fail, which means we must bail out, * safe because we are called with BKL held */ - if (!try_module_get(serial->type->owner)) { + if (!try_module_get(serial->type->driver.owner)) { retval = -ENODEV; goto bailout_kref_put; } @@ -522,7 +216,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp) return 0; bailout_module_put: - module_put(serial->type->owner); + module_put(serial->type->driver.owner); bailout_kref_put: kref_put(&serial->kref, destroy_serial); port->open_count = 0; @@ -553,7 +247,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp) port->tty = NULL; } - module_put(port->serial->type->owner); + module_put(port->serial->type->driver.owner); } kref_put(&port->serial->kref, destroy_serial); @@ -711,16 +405,16 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int char tmp[40]; dbg("%s", __FUNCTION__); - length += sprintf (page, "usbserinfo:1.0 driver:%s\n", DRIVER_VERSION); + length += sprintf (page, "usbserinfo:1.0 driver:2.0\n"); for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) { serial = usb_serial_get_by_index(i); if (serial == NULL) continue; length += sprintf (page+length, "%d:", i); - if (serial->type->owner) - length += sprintf (page+length, " module:%s", module_name(serial->type->owner)); - length += sprintf (page+length, " name:\"%s\"", serial->type->name); + if (serial->type->driver.owner) + length += sprintf (page+length, " module:%s", module_name(serial->type->driver.owner)); + length += sprintf (page+length, " name:\"%s\"", serial->type->description); length += sprintf (page+length, " vendor:%04x product:%04x", le16_to_cpu(serial->dev->descriptor.idVendor), le16_to_cpu(serial->dev->descriptor.idProduct)); @@ -823,7 +517,7 @@ static void port_release(struct device *dev) static struct usb_serial * create_serial (struct usb_device *dev, struct usb_interface *interface, - struct usb_serial_device_type *type) + struct usb_serial_driver *driver) { struct usb_serial *serial; @@ -834,22 +528,22 @@ static struct usb_serial * create_serial (struct usb_device *dev, } memset (serial, 0, sizeof(*serial)); serial->dev = usb_get_dev(dev); - serial->type = type; + serial->type = driver; serial->interface = interface; kref_init(&serial->kref); return serial; } -static struct usb_serial_device_type *search_serial_device(struct usb_interface *iface) +static struct usb_serial_driver *search_serial_device(struct usb_interface *iface) { struct list_head *p; const struct usb_device_id *id; - struct usb_serial_device_type *t; + struct usb_serial_driver *t; /* List trough know devices and see if the usb id matches */ list_for_each(p, &usb_serial_driver_list) { - t = list_entry(p, struct usb_serial_device_type, driver_list); + t = list_entry(p, struct usb_serial_driver, driver_list); id = usb_match_id(iface, t->id_table); if (id != NULL) { dbg("descriptor matches"); @@ -872,7 +566,7 @@ int usb_serial_probe(struct usb_interface *interface, struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS]; struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS]; struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS]; - struct usb_serial_device_type *type = NULL; + struct usb_serial_driver *type = NULL; int retval; int minor; int buffer_size; @@ -900,7 +594,7 @@ int usb_serial_probe(struct usb_interface *interface, if (type->probe) { const struct usb_device_id *id; - if (!try_module_get(type->owner)) { + if (!try_module_get(type->driver.owner)) { dev_err(&interface->dev, "module get failed, exiting\n"); kfree (serial); return -EIO; @@ -908,7 +602,7 @@ int usb_serial_probe(struct usb_interface *interface, id = usb_match_id(interface, type->id_table); retval = type->probe(serial, id); - module_put(type->owner); + module_put(type->driver.owner); if (retval) { dbg ("sub driver rejected device"); @@ -992,7 +686,7 @@ int usb_serial_probe(struct usb_interface *interface, #endif /* found all that we need */ - dev_info(&interface->dev, "%s converter detected\n", type->name); + dev_info(&interface->dev, "%s converter detected\n", type->description); #ifdef CONFIG_USB_SERIAL_GENERIC if (type == &usb_serial_generic_device) { @@ -1007,13 +701,13 @@ int usb_serial_probe(struct usb_interface *interface, if (!num_ports) { /* if this device type has a calc_num_ports function, call it */ if (type->calc_num_ports) { - if (!try_module_get(type->owner)) { + if (!try_module_get(type->driver.owner)) { dev_err(&interface->dev, "module get failed, exiting\n"); kfree (serial); return -EIO; } num_ports = type->calc_num_ports (serial); - module_put(type->owner); + module_put(type->driver.owner); } if (!num_ports) num_ports = type->num_ports; @@ -1158,12 +852,12 @@ int usb_serial_probe(struct usb_interface *interface, /* if this device type has an attach function, call it */ if (type->attach) { - if (!try_module_get(type->owner)) { + if (!try_module_get(type->driver.owner)) { dev_err(&interface->dev, "module get failed, exiting\n"); goto probe_error; } retval = type->attach (serial); - module_put(type->owner); + module_put(type->driver.owner); if (retval < 0) goto probe_error; if (retval > 0) { @@ -1330,7 +1024,7 @@ static int __init usb_serial_init(void) goto exit_generic; } - info(DRIVER_DESC " " DRIVER_VERSION); + info(DRIVER_DESC); return result; @@ -1375,7 +1069,7 @@ module_exit(usb_serial_exit); } \ } while (0) -static void fixup_generic(struct usb_serial_device_type *device) +static void fixup_generic(struct usb_serial_driver *device) { set_to_generic_if_null(device, open); set_to_generic_if_null(device, write); @@ -1387,30 +1081,33 @@ static void fixup_generic(struct usb_serial_device_type *device) set_to_generic_if_null(device, shutdown); } -int usb_serial_register(struct usb_serial_device_type *new_device) +int usb_serial_register(struct usb_serial_driver *driver) { int retval; - fixup_generic(new_device); + fixup_generic(driver); + + if (!driver->description) + driver->description = driver->driver.name; /* Add this device to our list of devices */ - list_add(&new_device->driver_list, &usb_serial_driver_list); + list_add(&driver->driver_list, &usb_serial_driver_list); - retval = usb_serial_bus_register(new_device); + retval = usb_serial_bus_register(driver); if (retval) { - err("problem %d when registering driver %s", retval, new_device->name); - list_del(&new_device->driver_list); + err("problem %d when registering driver %s", retval, driver->description); + list_del(&driver->driver_list); } else - info("USB Serial support registered for %s", new_device->name); + info("USB Serial support registered for %s", driver->description); return retval; } -void usb_serial_deregister(struct usb_serial_device_type *device) +void usb_serial_deregister(struct usb_serial_driver *device) { - info("USB Serial deregistering driver %s", device->name); + info("USB Serial deregistering driver %s", device->description); list_del(&device->driver_list); usb_serial_bus_deregister(device); } @@ -1429,7 +1126,6 @@ EXPORT_SYMBOL_GPL(usb_serial_port_softint); /* Module information */ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_VERSION( DRIVER_VERSION ); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h index 57f92f0..238a5a8 100644 --- a/drivers/usb/serial/usb-serial.h +++ b/drivers/usb/serial/usb-serial.h @@ -1,53 +1,13 @@ /* * USB Serial Converter driver * - * Copyright (C) 1999 - 2004 + * Copyright (C) 1999 - 2005 * 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 as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * the Free Software Foundation; either version 2 of the License. * - * See Documentation/usb/usb-serial.txt for more information on using this driver - * - * (03/26/2002) gkh - * removed the port->tty check from port_paranoia_check() due to serial - * consoles not having a tty device assigned to them. - * - * (12/03/2001) gkh - * removed active from the port structure. - * added documentation to the usb_serial_device_type structure - * - * (10/10/2001) gkh - * added vendor and product to serial structure. Needed to determine device - * owner when the device is disconnected. - * - * (05/30/2001) gkh - * added sem to port structure and removed port_lock - * - * (10/05/2000) gkh - * Added interrupt_in_endpointAddress and bulk_in_endpointAddress to help - * fix bug with urb->dev not being set properly, now that the usb core - * needs it. - * - * (09/11/2000) gkh - * Added usb_serial_debug_data function to help get rid of #DEBUG in the - * drivers. - * - * (08/28/2000) gkh - * Added port_lock to port structure. - * - * (08/08/2000) gkh - * Added open_count to port structure. - * - * (07/23/2000) gkh - * Added bulk_out_endpointAddress to port structure. - * - * (07/19/2000) gkh, pberger, and borchers - * Modifications to allow usb-serial drivers to be modules. - * - * */ @@ -143,7 +103,7 @@ static inline void usb_set_serial_port_data (struct usb_serial_port *port, void /** * usb_serial - structure used by the usb-serial core for a device * @dev: pointer to the struct usb_device for this device - * @type: pointer to the struct usb_serial_device_type for this device + * @type: pointer to the struct usb_serial_driver for this device * @interface: pointer to the struct usb_interface for this device * @minor: the starting minor number for this device * @num_ports: the number of ports this device has @@ -159,7 +119,7 @@ static inline void usb_set_serial_port_data (struct usb_serial_port *port, void */ struct usb_serial { struct usb_device * dev; - struct usb_serial_device_type * type; + struct usb_serial_driver * type; struct usb_interface * interface; unsigned char minor; unsigned char num_ports; @@ -188,13 +148,9 @@ static inline void usb_set_serial_data (struct usb_serial *serial, void *data) } /** - * usb_serial_device_type - a structure that defines a usb serial device - * @owner: pointer to the module that owns this device. - * @name: pointer to a string that describes this device. This string used + * usb_serial_driver - describes a usb serial driver + * @description: pointer to a string that describes this driver. This string used * in the syslog messages when a device is inserted or removed. - * @short_name: a pointer to a string that describes this device in - * KOBJ_NAME_LEN characters or less. This is used for the sysfs interface - * to describe the driver. * @id_table: pointer to a list of usb_device_id structures that define all * of the devices this structure can support. * @num_interrupt_in: the number of interrupt in endpoints this device will @@ -221,16 +177,19 @@ static inline void usb_set_serial_data (struct usb_serial *serial, void *data) * @shutdown: pointer to the driver's shutdown function. This will be * called when the device is removed from the system. * - * This structure is defines a USB Serial device. It provides all of + * This structure is defines a USB Serial driver. It provides all of * the information that the USB serial core code needs. If the function * pointers are defined, then the USB serial core code will call them when * the corresponding tty port functions are called. If they are not * called, the generic serial function will be used instead. + * + * The driver.owner field should be set to the module owner of this driver. + * The driver.name field should be set to the name of this driver (remember + * it will show up in sysfs, so it needs to be short and to the point. + * Useing the module name is a good idea.) */ -struct usb_serial_device_type { - struct module *owner; - char *name; - char *short_name; +struct usb_serial_driver { + const char *description; const struct usb_device_id *id_table; char num_interrupt_in; char num_interrupt_out; @@ -269,10 +228,10 @@ struct usb_serial_device_type { void (*read_bulk_callback)(struct urb *urb, struct pt_regs *regs); void (*write_bulk_callback)(struct urb *urb, struct pt_regs *regs); }; -#define to_usb_serial_driver(d) container_of(d, struct usb_serial_device_type, driver) +#define to_usb_serial_driver(d) container_of(d, struct usb_serial_driver, driver) -extern int usb_serial_register(struct usb_serial_device_type *new_device); -extern void usb_serial_deregister(struct usb_serial_device_type *device); +extern int usb_serial_register(struct usb_serial_driver *driver); +extern void usb_serial_deregister(struct usb_serial_driver *driver); extern void usb_serial_port_softint(void *private); extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id); @@ -303,10 +262,10 @@ extern void usb_serial_generic_shutdown (struct usb_serial *serial); extern int usb_serial_generic_register (int debug); extern void usb_serial_generic_deregister (void); -extern int usb_serial_bus_register (struct usb_serial_device_type *device); -extern void usb_serial_bus_deregister (struct usb_serial_device_type *device); +extern int usb_serial_bus_register (struct usb_serial_driver *device); +extern void usb_serial_bus_deregister (struct usb_serial_driver *device); -extern struct usb_serial_device_type usb_serial_generic_device; +extern struct usb_serial_driver usb_serial_generic_device; extern struct bus_type usb_serial_bus_type; extern struct tty_driver *usb_serial_tty_driver; diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 31c57ad..a473c1c 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -7,139 +7,10 @@ * * 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. + * the Free Software Foundation; either version 2 of the License. * * See Documentation/usb/usb-serial.txt for more information on using this driver * - * (06/03/2003) Judd Montgomery <judd at jpilot.org> - * Added support for module parameter options for untested/unknown - * devices. - * - * (03/09/2003) gkh - * Added support for the Sony Clie NZ90V device. Thanks to Martin Brachtl - * <brachtl@redgrep.cz> for the information. - * - * (03/05/2003) gkh - * Think Treo support is now working. - * - * (04/03/2002) gkh - * Added support for the Sony OS 4.1 devices. Thanks to Hiroyuki ARAKI - * <hiro@zob.ne.jp> for the information. - * - * (03/27/2002) gkh - * Removed assumptions that port->tty was always valid (is not true - * for usb serial console devices.) - * - * (03/23/2002) gkh - * Added support for the Palm i705 device, thanks to Thomas Riemer - * <tom@netmech.com> for the information. - * - * (03/21/2002) gkh - * Added support for the Palm m130 device, thanks to Udo Eisenbarth - * <udo.eisenbarth@web.de> for the information. - * - * (02/27/2002) gkh - * Reworked the urb handling logic. We have no more pool, but dynamically - * allocate the urb and the transfer buffer on the fly. In testing this - * does not incure any measurable overhead. This also relies on the fact - * that we have proper reference counting logic for urbs. - * - * (02/21/2002) SilaS - * Added initial support for the Palm m515 devices. - * - * (02/14/2002) gkh - * Added support for the Clie S-360 device. - * - * (12/18/2001) gkh - * Added better Clie support for 3.5 devices. Thanks to Geoffrey Levand - * for the patch. - * - * (11/11/2001) gkh - * Added support for the m125 devices, and added check to prevent oopses - * for Clié devices that lie about the number of ports they have. - * - * (08/30/2001) gkh - * Added support for the Clie devices, both the 3.5 and 4.0 os versions. - * Many thanks to Daniel Burke, and Bryan Payne for helping with this. - * - * (08/23/2001) gkh - * fixed a few potential bugs pointed out by Oliver Neukum. - * - * (05/30/2001) gkh - * switched from using spinlock to a semaphore, which fixes lots of problems. - * - * (05/28/2000) gkh - * Added initial support for the Palm m500 and Palm m505 devices. - * - * (04/08/2001) gb - * Identify version on module load. - * - * (01/21/2000) gkh - * Added write_room and chars_in_buffer, as they were previously using the - * generic driver versions which is all wrong now that we are using an urb - * pool. Thanks to Wolfgang Grandegger for pointing this out to me. - * Removed count assignment in the write function, which was not needed anymore - * either. Thanks to Al Borchers for pointing this out. - * - * (12/12/2000) gkh - * Moved MOD_DEC to end of visor_close to be nicer, as the final write - * message can sleep. - * - * (11/12/2000) gkh - * Fixed bug with data being dropped on the floor by forcing tty->low_latency - * to be on. Hopefully this fixes the OHCI issue! - * - * (11/01/2000) Adam J. Richter - * usb_device_id table support - * - * (10/05/2000) gkh - * Fixed bug with urb->dev not being set properly, now that the usb - * core needs it. - * - * (09/11/2000) gkh - * Got rid of always calling kmalloc for every urb we wrote out to the - * device. - * Added visor_read_callback so we can keep track of bytes in and out for - * those people who like to know the speed of their device. - * Removed DEBUG #ifdefs with call to usb_serial_debug_data - * - * (09/06/2000) gkh - * Fixed oops in visor_exit. Need to uncomment usb_unlink_urb call _after_ - * the host controller drivers set urb->dev = NULL when the urb is finished. - * - * (08/28/2000) gkh - * Added locks for SMP safeness. - * - * (08/08/2000) gkh - * Fixed endian problem in visor_startup. - * Fixed MOD_INC and MOD_DEC logic and the ability to open a port more - * than once. - * - * (07/23/2000) gkh - * Added pool of write urbs to speed up transfers to the visor. - * - * (07/19/2000) gkh - * Added module_init and module_exit functions to handle the fact that this - * driver is a loadable module now. - * - * (07/03/2000) gkh - * Added visor_set_ioctl and visor_set_termios functions (they don't do much - * of anything, but are good for debugging.) - * - * (06/25/2000) gkh - * Fixed bug in visor_unthrottle that should help with the disconnect in PPP - * bug that people have been reporting. - * - * (06/23/2000) gkh - * Cleaned up debugging statements in a quest to find UHCI timeout bug. - * - * (04/27/2000) Ryan VanderBijl - * Fixed memory leak in visor_close - * - * (03/26/2000) gkh - * Split driver up into device specific pieces. - * */ #include <linux/config.h> @@ -161,7 +32,6 @@ /* * Version Information */ -#define DRIVER_VERSION "v2.1" #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>" #define DRIVER_DESC "USB HandSpring Visor / Palm OS driver" @@ -311,10 +181,12 @@ static struct usb_driver visor_driver = { }; /* All of the device info needed for the Handspring Visor, and Palm 4.0 devices */ -static struct usb_serial_device_type handspring_device = { - .owner = THIS_MODULE, - .name = "Handspring Visor / Palm OS", - .short_name = "visor", +static struct usb_serial_driver handspring_device = { + .driver = { + .owner = THIS_MODULE, + .name = "visor", + }, + .description = "Handspring Visor / Palm OS", .id_table = id_table, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = 2, @@ -339,10 +211,12 @@ static struct usb_serial_device_type handspring_device = { }; /* All of the device info needed for the Clie UX50, TH55 Palm 5.0 devices */ -static struct usb_serial_device_type clie_5_device = { - .owner = THIS_MODULE, - .name = "Sony Clie 5.0", - .short_name = "clie_5", +static struct usb_serial_driver clie_5_device = { + .driver = { + .owner = THIS_MODULE, + .name = "clie_5", + }, + .description = "Sony Clie 5.0", .id_table = clie_id_5_table, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = 2, @@ -367,10 +241,12 @@ static struct usb_serial_device_type clie_5_device = { }; /* device info for the Sony Clie OS version 3.5 */ -static struct usb_serial_device_type clie_3_5_device = { - .owner = THIS_MODULE, - .name = "Sony Clie 3.5", - .short_name = "clie_3.5", +static struct usb_serial_driver clie_3_5_device = { + .driver = { + .owner = THIS_MODULE, + .name = "clie_3.5", + }, + .description = "Sony Clie 3.5", .id_table = clie_id_3_5_table, .num_interrupt_in = 0, .num_bulk_in = 1, @@ -782,7 +658,7 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i break; } dev_info(dev, "%s: port %d, is for %s use\n", - serial->type->name, + serial->type->description, connection_info->connections[i].port, string); } } @@ -791,11 +667,11 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i */ if (num_ports == 0 || num_ports > 2) { dev_warn (dev, "%s: No valid connect info available\n", - serial->type->name); + serial->type->description); num_ports = 2; } - dev_info(dev, "%s: Number of ports: %d\n", serial->type->name, + dev_info(dev, "%s: Number of ports: %d\n", serial->type->description, num_ports); /* @@ -1125,7 +1001,7 @@ static int __init visor_init (void) retval = usb_register(&visor_driver); if (retval) goto failed_usb_register; - info(DRIVER_DESC " " DRIVER_VERSION); + info(DRIVER_DESC); return 0; failed_usb_register: diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index cf3bc30..18c3183 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -156,10 +156,12 @@ static void whiteheat_unthrottle (struct usb_serial_port *port); static void whiteheat_read_callback (struct urb *urb, struct pt_regs *regs); static void whiteheat_write_callback (struct urb *urb, struct pt_regs *regs); -static struct usb_serial_device_type whiteheat_fake_device = { - .owner = THIS_MODULE, - .name = "Connect Tech - WhiteHEAT - (prerenumeration)", - .short_name = "whiteheatnofirm", +static struct usb_serial_driver whiteheat_fake_device = { + .driver = { + .owner = THIS_MODULE, + .name = "whiteheatnofirm", + }, + .description = "Connect Tech - WhiteHEAT - (prerenumeration)", .id_table = id_table_prerenumeration, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, @@ -169,10 +171,12 @@ static struct usb_serial_device_type whiteheat_fake_device = { .attach = whiteheat_firmware_attach, }; -static struct usb_serial_device_type whiteheat_device = { - .owner = THIS_MODULE, - .name = "Connect Tech - WhiteHEAT", - .short_name = "whiteheat", +static struct usb_serial_driver whiteheat_device = { + .driver = { + .owner = THIS_MODULE, + .name = "whiteheat", + }, + .description = "Connect Tech - WhiteHEAT", .id_table = id_table_std, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, @@ -382,10 +386,10 @@ static int whiteheat_attach (struct usb_serial *serial) usb_clear_halt(serial->dev, pipe); ret = usb_bulk_msg (serial->dev, pipe, command, 2, &alen, COMMAND_TIMEOUT_MS); if (ret) { - err("%s: Couldn't send command [%d]", serial->type->name, ret); + err("%s: Couldn't send command [%d]", serial->type->description, ret); goto no_firmware; } else if (alen != sizeof(command)) { - err("%s: Send command incomplete [%d]", serial->type->name, alen); + err("%s: Send command incomplete [%d]", serial->type->description, alen); goto no_firmware; } @@ -394,19 +398,19 @@ static int whiteheat_attach (struct usb_serial *serial) usb_clear_halt(serial->dev, pipe); ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT_MS); if (ret) { - err("%s: Couldn't get results [%d]", serial->type->name, ret); + err("%s: Couldn't get results [%d]", serial->type->description, ret); goto no_firmware; } else if (alen != sizeof(result)) { - err("%s: Get results incomplete [%d]", serial->type->name, alen); + err("%s: Get results incomplete [%d]", serial->type->description, alen); goto no_firmware; } else if (result[0] != command[0]) { - err("%s: Command failed [%d]", serial->type->name, result[0]); + err("%s: Command failed [%d]", serial->type->description, result[0]); goto no_firmware; } hw_info = (struct whiteheat_hw_info *)&result[1]; - info("%s: Driver %s: Firmware v%d.%02d", serial->type->name, + info("%s: Driver %s: Firmware v%d.%02d", serial->type->description, DRIVER_VERSION, hw_info->sw_major_rev, hw_info->sw_minor_rev); for (i = 0; i < serial->num_ports; i++) { @@ -414,7 +418,7 @@ static int whiteheat_attach (struct usb_serial *serial) info = (struct whiteheat_private *)kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL); if (info == NULL) { - err("%s: Out of memory for port structures\n", serial->type->name); + err("%s: Out of memory for port structures\n", serial->type->description); goto no_private; } @@ -484,7 +488,7 @@ static int whiteheat_attach (struct usb_serial *serial) command_info = (struct whiteheat_command_private *)kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL); if (command_info == NULL) { - err("%s: Out of memory for port structures\n", serial->type->name); + err("%s: Out of memory for port structures\n", serial->type->description); goto no_command_private; } @@ -501,9 +505,9 @@ static int whiteheat_attach (struct usb_serial *serial) no_firmware: /* Firmware likely not running */ - err("%s: Unable to retrieve firmware version, try replugging\n", serial->type->name); - err("%s: If the firmware is not running (status led not blinking)\n", serial->type->name); - err("%s: please contact support@connecttech.com\n", serial->type->name); + err("%s: Unable to retrieve firmware version, try replugging\n", serial->type->description); + err("%s: If the firmware is not running (status led not blinking)\n", serial->type->description); + err("%s: please contact support@connecttech.com\n", serial->type->description); return -ENODEV; no_command_private: diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index bb9819c..1a9679f 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -2,7 +2,8 @@ # USB Storage driver configuration # -comment "NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information" +comment "NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'" +comment "may also be needed; see USB_STORAGE Help for more information" depends on USB config USB_STORAGE diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index 2c9402d..89401a5 100644 --- a/drivers/usb/storage/onetouch.c +++ b/drivers/usb/storage/onetouch.c @@ -5,7 +5,7 @@ * Copyright (c) 2005 Nick Sillik <n.sillik@temple.edu> * * Initial work by: - * Copyright (c) 2003 Erik Thyren <erth7411@student.uu.se> + * Copyright (c) 2003 Erik Thyren <erth7411@student.uu.se> * * Based on usbmouse.c (Vojtech Pavlik) and xpad.c (Marko Friedemann) * @@ -46,7 +46,7 @@ void onetouch_release_input(void *onetouch_); struct usb_onetouch { char name[128]; char phys[64]; - struct input_dev dev; /* input device interface */ + struct input_dev *dev; /* input device interface */ struct usb_device *udev; /* usb device */ struct urb *irq; /* urb for interrupt in report */ @@ -58,7 +58,7 @@ static void usb_onetouch_irq(struct urb *urb, struct pt_regs *regs) { struct usb_onetouch *onetouch = urb->context; signed char *data = onetouch->data; - struct input_dev *dev = &onetouch->dev; + struct input_dev *dev = onetouch->dev; int status; switch (urb->status) { @@ -74,11 +74,9 @@ static void usb_onetouch_irq(struct urb *urb, struct pt_regs *regs) } input_regs(dev, regs); - - input_report_key(&onetouch->dev, ONETOUCH_BUTTON, - data[0] & 0x02); - + input_report_key(dev, ONETOUCH_BUTTON, data[0] & 0x02); input_sync(dev); + resubmit: status = usb_submit_urb (urb, SLAB_ATOMIC); if (status) @@ -113,8 +111,8 @@ int onetouch_connect_input(struct us_data *ss) struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; struct usb_onetouch *onetouch; + struct input_dev *input_dev; int pipe, maxp; - char path[64]; interface = ss->pusb_intf->cur_altsetting; @@ -122,62 +120,62 @@ int onetouch_connect_input(struct us_data *ss) return -ENODEV; endpoint = &interface->endpoint[2].desc; - if(!(endpoint->bEndpointAddress & USB_DIR_IN)) + if (!(endpoint->bEndpointAddress & USB_DIR_IN)) return -ENODEV; - if((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) return -ENODEV; pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); - if (!(onetouch = kcalloc(1, sizeof(struct usb_onetouch), GFP_KERNEL))) - return -ENOMEM; + onetouch = kzalloc(sizeof(struct usb_onetouch), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!onetouch || !input_dev) + goto fail1; onetouch->data = usb_buffer_alloc(udev, ONETOUCH_PKT_LEN, SLAB_ATOMIC, &onetouch->data_dma); - if (!onetouch->data){ - kfree(onetouch); - return -ENOMEM; - } + if (!onetouch->data) + goto fail1; onetouch->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!onetouch->irq){ - kfree(onetouch); - usb_buffer_free(udev, ONETOUCH_PKT_LEN, - onetouch->data, onetouch->data_dma); - return -ENODEV; - } - + if (!onetouch->irq) + goto fail2; onetouch->udev = udev; + onetouch->dev = input_dev; - set_bit(EV_KEY, onetouch->dev.evbit); - set_bit(ONETOUCH_BUTTON, onetouch->dev.keybit); - clear_bit(0, onetouch->dev.keybit); + if (udev->manufacturer) + strlcpy(onetouch->name, udev->manufacturer, + sizeof(onetouch->name)); + if (udev->product) { + if (udev->manufacturer) + strlcat(onetouch->name, " ", sizeof(onetouch->name)); + strlcat(onetouch->name, udev->product, sizeof(onetouch->name)); + } - onetouch->dev.private = onetouch; - onetouch->dev.open = usb_onetouch_open; - onetouch->dev.close = usb_onetouch_close; + if (!strlen(onetouch->name)) + snprintf(onetouch->name, sizeof(onetouch->name), + "Maxtor Onetouch %04x:%04x", + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct)); - usb_make_path(udev, path, sizeof(path)); - sprintf(onetouch->phys, "%s/input0", path); + usb_make_path(udev, onetouch->phys, sizeof(onetouch->phys)); + strlcat(onetouch->phys, "/input0", sizeof(onetouch->phys)); - onetouch->dev.name = onetouch->name; - onetouch->dev.phys = onetouch->phys; + input_dev->name = onetouch->name; + input_dev->phys = onetouch->phys; + usb_to_input_id(udev, &input_dev->id); + input_dev->cdev.dev = &udev->dev; - usb_to_input_id(udev, &onetouch->dev.id); + set_bit(EV_KEY, input_dev->evbit); + set_bit(ONETOUCH_BUTTON, input_dev->keybit); + clear_bit(0, input_dev->keybit); - onetouch->dev.dev = &udev->dev; - - if (udev->manufacturer) - strcat(onetouch->name, udev->manufacturer); - if (udev->product) - sprintf(onetouch->name, "%s %s", onetouch->name, - udev->product); - if (!strlen(onetouch->name)) - sprintf(onetouch->name, "Maxtor Onetouch %04x:%04x", - onetouch->dev.id.vendor, onetouch->dev.id.product); + input_dev->private = onetouch; + input_dev->open = usb_onetouch_open; + input_dev->close = usb_onetouch_close; usb_fill_int_urb(onetouch->irq, udev, pipe, onetouch->data, (maxp > 8 ? 8 : maxp), @@ -188,10 +186,15 @@ int onetouch_connect_input(struct us_data *ss) ss->extra_destructor = onetouch_release_input; ss->extra = onetouch; - input_register_device(&onetouch->dev); - printk(KERN_INFO "usb-input: %s on %s\n", onetouch->dev.name, path); + input_register_device(onetouch->dev); return 0; + + fail2: usb_buffer_free(udev, ONETOUCH_PKT_LEN, + onetouch->data, onetouch->data_dma); + fail1: kfree(onetouch); + input_free_device(input_dev); + return -ENOMEM; } void onetouch_release_input(void *onetouch_) @@ -200,11 +203,9 @@ void onetouch_release_input(void *onetouch_) if (onetouch) { usb_kill_urb(onetouch->irq); - input_unregister_device(&onetouch->dev); + input_unregister_device(onetouch->dev); usb_free_urb(onetouch->irq); usb_buffer_free(onetouch->udev, ONETOUCH_PKT_LEN, onetouch->data, onetouch->data_dma); - printk(KERN_INFO "usb-input: deregistering %s\n", - onetouch->dev.name); } } diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index 356342c..33c55a6 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -1,4 +1,4 @@ -/* Driver for SCM Microsystems USB-ATAPI cable +/* Driver for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable * * $Id: shuttle_usbat.c,v 1.17 2002/04/22 03:39:43 mdharm Exp $ * @@ -67,10 +67,10 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us); static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us); /* - * Convenience function to produce an ATAPI read/write sectors command + * Convenience function to produce an ATA read/write sectors command * Use cmd=0x20 for read, cmd=0x30 for write */ -static void usbat_pack_atapi_sector_cmd(unsigned char *buf, +static void usbat_pack_ata_sector_cmd(unsigned char *buf, unsigned char thistime, u32 sector, unsigned char cmd) { @@ -196,10 +196,12 @@ static int usbat_check_status(struct us_data *us) if (rc != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_FAILED; - if (*reply & 0x01 && *reply != 0x51) // error/check condition (0x51 is ok) + /* error/check condition (0x51 is ok) */ + if (*reply & 0x01 && *reply != 0x51) return USB_STOR_TRANSPORT_FAILED; - if (*reply & 0x20) // device fault + /* device fault */ + if (*reply & 0x20) return USB_STOR_TRANSPORT_FAILED; return USB_STOR_TRANSPORT_GOOD; @@ -222,29 +224,39 @@ static int usbat_set_shuttle_features(struct us_data *us, command[0] = 0x40; command[1] = USBAT_CMD_SET_FEAT; - // The only bit relevant to ATA access is bit 6 - // which defines 8 bit data access (set) or 16 bit (unset) + /* + * The only bit relevant to ATA access is bit 6 + * which defines 8 bit data access (set) or 16 bit (unset) + */ command[2] = epp_control; - // If FCQ is set in the qualifier (defined in R/W cmd), then bits U0, U1, - // ET1 and ET2 define an external event to be checked for on event of a - // _read_blocks or _write_blocks operation. The read/write will not take - // place unless the defined trigger signal is active. + /* + * If FCQ is set in the qualifier (defined in R/W cmd), then bits U0, U1, + * ET1 and ET2 define an external event to be checked for on event of a + * _read_blocks or _write_blocks operation. The read/write will not take + * place unless the defined trigger signal is active. + */ command[3] = external_trigger; - // The resultant byte of the mask operation (see mask_byte) is compared for - // equivalence with this test pattern. If equal, the read/write will take - // place. + /* + * The resultant byte of the mask operation (see mask_byte) is compared for + * equivalence with this test pattern. If equal, the read/write will take + * place. + */ command[4] = test_pattern; - // This value is logically ANDed with the status register field specified - // in the read/write command. + /* + * This value is logically ANDed with the status register field specified + * in the read/write command. + */ command[5] = mask_byte; - // If ALQ is set in the qualifier, this field contains the address of the - // registers where the byte count should be read for transferring the data. - // If ALQ is not set, then this field contains the number of bytes to be - // transferred. + /* + * If ALQ is set in the qualifier, this field contains the address of the + * registers where the byte count should be read for transferring the data. + * If ALQ is not set, then this field contains the number of bytes to be + * transferred. + */ command[6] = subcountL; command[7] = subcountH; @@ -273,26 +285,26 @@ static int usbat_wait_not_busy(struct us_data *us, int minutes) if (result!=USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - if (*status & 0x01) { // check condition + if (*status & 0x01) { /* check condition */ result = usbat_read(us, USBAT_ATA, 0x10, status); return USB_STOR_TRANSPORT_FAILED; } - if (*status & 0x20) // device fault + if (*status & 0x20) /* device fault */ return USB_STOR_TRANSPORT_FAILED; - if ((*status & 0x80)==0x00) { // not busy + if ((*status & 0x80)==0x00) { /* not busy */ US_DEBUGP("Waited not busy for %d steps\n", i); return USB_STOR_TRANSPORT_GOOD; } if (i<500) - msleep(10); // 5 seconds + msleep(10); /* 5 seconds */ else if (i<700) - msleep(50); // 10 seconds + msleep(50); /* 10 seconds */ else if (i<1200) - msleep(100); // 50 seconds + msleep(100); /* 50 seconds */ else - msleep(1000); // X minutes + msleep(1000); /* X minutes */ } US_DEBUGP("Waited not busy for %d minutes, timing out.\n", @@ -412,9 +424,12 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us, if (i==0) { cmdlen = 16; - // Write to multiple registers - // Not really sure the 0x07, 0x17, 0xfc, 0xe7 is necessary here, - // but that's what came out of the trace every single time. + /* + * Write to multiple registers + * Not really sure the 0x07, 0x17, 0xfc, 0xe7 is + * necessary here, but that's what came out of the + * trace every single time. + */ command[0] = 0x40; command[1] = access | USBAT_CMD_WRITE_REGS; command[2] = 0x07; @@ -426,7 +441,7 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us, } else cmdlen = 8; - // Conditionally read or write blocks + /* Conditionally read or write blocks */ command[cmdlen-8] = (direction==DMA_TO_DEVICE ? 0x40 : 0xC0); command[cmdlen-7] = access | (direction==DMA_TO_DEVICE ? @@ -456,11 +471,6 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us, } - - //US_DEBUGP("Transfer %s %d bytes, sg buffers %d\n", - // direction == DMA_TO_DEVICE ? "out" : "in", - // len, use_sg); - result = usb_stor_bulk_transfer_sg(us, pipe, content, len, use_sg, NULL); @@ -508,9 +518,9 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us, if (result!=USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - if (*status & 0x01) // check condition + if (*status & 0x01) /* check condition */ return USB_STOR_TRANSPORT_FAILED; - if (*status & 0x20) // device fault + if (*status & 0x20) /* device fault */ return USB_STOR_TRANSPORT_FAILED; US_DEBUGP("Redoing %s\n", @@ -547,32 +557,32 @@ static int usbat_multiple_write(struct us_data *us, BUG_ON(num_registers > US_IOBUF_SIZE/2); - // Write to multiple registers, ATA access + /* Write to multiple registers, ATA access */ command[0] = 0x40; command[1] = USBAT_ATA | USBAT_CMD_WRITE_REGS; - // No relevance + /* No relevance */ command[2] = 0; command[3] = 0; command[4] = 0; command[5] = 0; - // Number of bytes to be transferred (incl. addresses and data) + /* Number of bytes to be transferred (incl. addresses and data) */ command[6] = LSB_of(num_registers*2); command[7] = MSB_of(num_registers*2); - // The setup command + /* The setup command */ result = usbat_execute_command(us, command, 8); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - // Create the reg/data, reg/data sequence + /* Create the reg/data, reg/data sequence */ for (i=0; i<num_registers; i++) { data[i<<1] = registers[i]; data[1+(i<<1)] = data_out[i]; } - // Send the data + /* Send the data */ result = usbat_bulk_write(us, data, num_registers*2); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -606,17 +616,17 @@ static int usbat_read_blocks(struct us_data *us, command[1] = USBAT_ATA | USBAT_CMD_COND_READ_BLOCK; command[2] = USBAT_ATA_DATA; command[3] = USBAT_ATA_STATUS; - command[4] = 0xFD; // Timeout (ms); + command[4] = 0xFD; /* Timeout (ms); */ command[5] = USBAT_QUAL_FCQ; command[6] = LSB_of(len); command[7] = MSB_of(len); - // Multiple block read setup command + /* Multiple block read setup command */ result = usbat_execute_command(us, command, 8); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_FAILED; - // Read the blocks we just asked for + /* Read the blocks we just asked for */ result = usbat_bulk_read(us, buffer, len); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_FAILED; @@ -647,17 +657,17 @@ static int usbat_write_blocks(struct us_data *us, command[1] = USBAT_ATA | USBAT_CMD_COND_WRITE_BLOCK; command[2] = USBAT_ATA_DATA; command[3] = USBAT_ATA_STATUS; - command[4] = 0xFD; // Timeout (ms) + command[4] = 0xFD; /* Timeout (ms) */ command[5] = USBAT_QUAL_FCQ; command[6] = LSB_of(len); command[7] = MSB_of(len); - // Multiple block write setup command + /* Multiple block write setup command */ result = usbat_execute_command(us, command, 8); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_FAILED; - // Write the data + /* Write the data */ result = usbat_bulk_write(us, buffer, len); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_FAILED; @@ -711,16 +721,20 @@ static int usbat_device_reset(struct us_data *us) { int rc; - // Reset peripheral, enable peripheral control signals - // (bring reset signal up) + /* + * Reset peripheral, enable peripheral control signals + * (bring reset signal up) + */ rc = usbat_write_user_io(us, USBAT_UIO_DRVRST | USBAT_UIO_OE1 | USBAT_UIO_OE0, USBAT_UIO_EPAD | USBAT_UIO_1); if (rc != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - // Enable peripheral control signals - // (bring reset signal down) + /* + * Enable peripheral control signals + * (bring reset signal down) + */ rc = usbat_write_user_io(us, USBAT_UIO_OE1 | USBAT_UIO_OE0, USBAT_UIO_EPAD | USBAT_UIO_1); @@ -737,7 +751,7 @@ static int usbat_device_enable_cdt(struct us_data *us) { int rc; - // Enable peripheral control signals and card detect + /* Enable peripheral control signals and card detect */ rc = usbat_write_user_io(us, USBAT_UIO_ACKD | USBAT_UIO_OE1 | USBAT_UIO_OE0, USBAT_UIO_EPAD | USBAT_UIO_1); @@ -786,7 +800,7 @@ static int usbat_flash_check_media(struct us_data *us, if (rc != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - // Check for media existence + /* Check for media existence */ rc = usbat_flash_check_media_present(uio); if (rc == USBAT_FLASH_MEDIA_NONE) { info->sense_key = 0x02; @@ -795,11 +809,11 @@ static int usbat_flash_check_media(struct us_data *us, return USB_STOR_TRANSPORT_FAILED; } - // Check for media change + /* Check for media change */ rc = usbat_flash_check_media_changed(uio); if (rc == USBAT_FLASH_MEDIA_CHANGED) { - // Reset and re-enable card detect + /* Reset and re-enable card detect */ rc = usbat_device_reset(us); if (rc != USB_STOR_TRANSPORT_GOOD) return rc; @@ -855,15 +869,15 @@ static int usbat_identify_device(struct us_data *us, if (rc != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - // Check for error bit - if (status & 0x01) { - // Device is a CompactFlash reader/writer - US_DEBUGP("usbat_identify_device: Detected Flash reader/writer\n"); - info->devicetype = USBAT_DEV_FLASH; - } else { - // Device is HP 8200 + /* Check for error bit, or if the command 'fell through' */ + if (status == 0xA1 || !(status & 0x01)) { + /* Device is HP 8200 */ US_DEBUGP("usbat_identify_device: Detected HP8200 CDRW\n"); info->devicetype = USBAT_DEV_HP8200; + } else { + /* Device is a CompactFlash reader/writer */ + US_DEBUGP("usbat_identify_device: Detected Flash reader/writer\n"); + info->devicetype = USBAT_DEV_FLASH; } return USB_STOR_TRANSPORT_GOOD; @@ -916,7 +930,7 @@ static int usbat_flash_get_sector_count(struct us_data *us, if (!reply) return USB_STOR_TRANSPORT_ERROR; - // ATAPI command : IDENTIFY DEVICE + /* ATA command : IDENTIFY DEVICE */ rc = usbat_multiple_write(us, registers, command, 3); if (rc != USB_STOR_XFER_GOOD) { US_DEBUGP("usbat_flash_get_sector_count: Gah! identify_device failed\n"); @@ -924,7 +938,7 @@ static int usbat_flash_get_sector_count(struct us_data *us, goto leave; } - // Read device status + /* Read device status */ if (usbat_get_status(us, &status) != USB_STOR_XFER_GOOD) { rc = USB_STOR_TRANSPORT_ERROR; goto leave; @@ -932,7 +946,7 @@ static int usbat_flash_get_sector_count(struct us_data *us, msleep(100); - // Read the device identification data + /* Read the device identification data */ rc = usbat_read_block(us, reply, 512); if (rc != USB_STOR_TRANSPORT_GOOD) goto leave; @@ -977,19 +991,23 @@ static int usbat_flash_read_data(struct us_data *us, if (result != USB_STOR_TRANSPORT_GOOD) return result; - // we're working in LBA mode. according to the ATA spec, - // we can support up to 28-bit addressing. I don't know if Jumpshot - // supports beyond 24-bit addressing. It's kind of hard to test - // since it requires > 8GB CF card. + /* + * we're working in LBA mode. according to the ATA spec, + * we can support up to 28-bit addressing. I don't know if Jumpshot + * supports beyond 24-bit addressing. It's kind of hard to test + * since it requires > 8GB CF card. + */ if (sector > 0x0FFFFFFF) return USB_STOR_TRANSPORT_ERROR; totallen = sectors * info->ssize; - // Since we don't read more than 64 KB at a time, we have to create - // a bounce buffer and move the data a piece at a time between the - // bounce buffer and the actual transfer buffer. + /* + * Since we don't read more than 64 KB at a time, we have to create + * a bounce buffer and move the data a piece at a time between the + * bounce buffer and the actual transfer buffer. + */ alloclen = min(totallen, 65536u); buffer = kmalloc(alloclen, GFP_NOIO); @@ -997,27 +1015,29 @@ static int usbat_flash_read_data(struct us_data *us, return USB_STOR_TRANSPORT_ERROR; do { - // loop, never allocate or transfer more than 64k at once - // (min(128k, 255*info->ssize) is the real limit) + /* + * loop, never allocate or transfer more than 64k at once + * (min(128k, 255*info->ssize) is the real limit) + */ len = min(totallen, alloclen); thistime = (len / info->ssize) & 0xff; - // ATAPI command 0x20 (READ SECTORS) - usbat_pack_atapi_sector_cmd(command, thistime, sector, 0x20); + /* ATA command 0x20 (READ SECTORS) */ + usbat_pack_ata_sector_cmd(command, thistime, sector, 0x20); - // Write/execute ATAPI read command + /* Write/execute ATA read command */ result = usbat_multiple_write(us, registers, command, 7); if (result != USB_STOR_TRANSPORT_GOOD) goto leave; - // Read the data we just requested + /* Read the data we just requested */ result = usbat_read_blocks(us, buffer, len); if (result != USB_STOR_TRANSPORT_GOOD) goto leave; US_DEBUGP("usbat_flash_read_data: %d bytes\n", len); - // Store the data in the transfer buffer + /* Store the data in the transfer buffer */ usb_stor_access_xfer_buf(buffer, len, us->srb, &sg_idx, &sg_offset, TO_XFER_BUF); @@ -1061,19 +1081,23 @@ static int usbat_flash_write_data(struct us_data *us, if (result != USB_STOR_TRANSPORT_GOOD) return result; - // we're working in LBA mode. according to the ATA spec, - // we can support up to 28-bit addressing. I don't know if Jumpshot - // supports beyond 24-bit addressing. It's kind of hard to test - // since it requires > 8GB CF card. + /* + * we're working in LBA mode. according to the ATA spec, + * we can support up to 28-bit addressing. I don't know if the device + * supports beyond 24-bit addressing. It's kind of hard to test + * since it requires > 8GB media. + */ if (sector > 0x0FFFFFFF) return USB_STOR_TRANSPORT_ERROR; totallen = sectors * info->ssize; - // Since we don't write more than 64 KB at a time, we have to create - // a bounce buffer and move the data a piece at a time between the - // bounce buffer and the actual transfer buffer. + /* + * Since we don't write more than 64 KB at a time, we have to create + * a bounce buffer and move the data a piece at a time between the + * bounce buffer and the actual transfer buffer. + */ alloclen = min(totallen, 65536u); buffer = kmalloc(alloclen, GFP_NOIO); @@ -1081,24 +1105,26 @@ static int usbat_flash_write_data(struct us_data *us, return USB_STOR_TRANSPORT_ERROR; do { - // loop, never allocate or transfer more than 64k at once - // (min(128k, 255*info->ssize) is the real limit) + /* + * loop, never allocate or transfer more than 64k at once + * (min(128k, 255*info->ssize) is the real limit) + */ len = min(totallen, alloclen); thistime = (len / info->ssize) & 0xff; - // Get the data from the transfer buffer + /* Get the data from the transfer buffer */ usb_stor_access_xfer_buf(buffer, len, us->srb, &sg_idx, &sg_offset, FROM_XFER_BUF); - // ATAPI command 0x30 (WRITE SECTORS) - usbat_pack_atapi_sector_cmd(command, thistime, sector, 0x30); + /* ATA command 0x30 (WRITE SECTORS) */ + usbat_pack_ata_sector_cmd(command, thistime, sector, 0x30); - // Write/execute ATAPI write command + /* Write/execute ATA write command */ result = usbat_multiple_write(us, registers, command, 7); if (result != USB_STOR_TRANSPORT_GOOD) goto leave; - // Write the data + /* Write the data */ result = usbat_write_blocks(us, buffer, len); if (result != USB_STOR_TRANSPORT_GOOD) goto leave; @@ -1169,42 +1195,44 @@ static int usbat_hp8200e_handle_read10(struct us_data *us, srb->transfersize); } - // Since we only read in one block at a time, we have to create - // a bounce buffer and move the data a piece at a time between the - // bounce buffer and the actual transfer buffer. + /* + * Since we only read in one block at a time, we have to create + * a bounce buffer and move the data a piece at a time between the + * bounce buffer and the actual transfer buffer. + */ len = (65535/srb->transfersize) * srb->transfersize; US_DEBUGP("Max read is %d bytes\n", len); len = min(len, srb->request_bufflen); buffer = kmalloc(len, GFP_NOIO); - if (buffer == NULL) // bloody hell! + if (buffer == NULL) /* bloody hell! */ return USB_STOR_TRANSPORT_FAILED; sector = short_pack(data[7+3], data[7+2]); sector <<= 16; sector |= short_pack(data[7+5], data[7+4]); transferred = 0; - sg_segment = 0; // for keeping track of where we are in - sg_offset = 0; // the scatter/gather list + sg_segment = 0; /* for keeping track of where we are in */ + sg_offset = 0; /* the scatter/gather list */ while (transferred != srb->request_bufflen) { if (len > srb->request_bufflen - transferred) len = srb->request_bufflen - transferred; - data[3] = len&0xFF; // (cylL) = expected length (L) - data[4] = (len>>8)&0xFF; // (cylH) = expected length (H) + data[3] = len&0xFF; /* (cylL) = expected length (L) */ + data[4] = (len>>8)&0xFF; /* (cylH) = expected length (H) */ - // Fix up the SCSI command sector and num sectors + /* Fix up the SCSI command sector and num sectors */ - data[7+2] = MSB_of(sector>>16); // SCSI command sector + data[7+2] = MSB_of(sector>>16); /* SCSI command sector */ data[7+3] = LSB_of(sector>>16); data[7+4] = MSB_of(sector&0xFFFF); data[7+5] = LSB_of(sector&0xFFFF); if (data[7+0] == GPCMD_READ_CD) data[7+6] = 0; - data[7+7] = MSB_of(len / srb->transfersize); // SCSI command - data[7+8] = LSB_of(len / srb->transfersize); // num sectors + data[7+7] = MSB_of(len / srb->transfersize); /* SCSI command */ + data[7+8] = LSB_of(len / srb->transfersize); /* num sectors */ result = usbat_hp8200e_rw_block_test(us, USBAT_ATA, registers, data, 19, @@ -1217,16 +1245,16 @@ static int usbat_hp8200e_handle_read10(struct us_data *us, if (result != USB_STOR_TRANSPORT_GOOD) break; - // Store the data in the transfer buffer + /* Store the data in the transfer buffer */ usb_stor_access_xfer_buf(buffer, len, srb, &sg_segment, &sg_offset, TO_XFER_BUF); - // Update the amount transferred and the sector number + /* Update the amount transferred and the sector number */ transferred += len; sector += len / srb->transfersize; - } // while transferred != srb->request_bufflen + } /* while transferred != srb->request_bufflen */ kfree(buffer); return result; @@ -1237,7 +1265,7 @@ static int usbat_select_and_test_registers(struct us_data *us) int selector; unsigned char *status = us->iobuf; - // try device = master, then device = slave. + /* try device = master, then device = slave. */ for (selector = 0xA0; selector <= 0xB0; selector += 0x10) { if (usbat_write(us, USBAT_ATA, USBAT_ATA_DEVICE, selector) != USB_STOR_XFER_GOOD) @@ -1298,7 +1326,7 @@ int init_usbat(struct us_data *us) memset(us->extra, 0, sizeof(struct usbat_info)); info = (struct usbat_info *) (us->extra); - // Enable peripheral control signals + /* Enable peripheral control signals */ rc = usbat_write_user_io(us, USBAT_UIO_OE1 | USBAT_UIO_OE0, USBAT_UIO_EPAD | USBAT_UIO_1); @@ -1337,7 +1365,7 @@ int init_usbat(struct us_data *us) US_DEBUGP("INIT 5\n"); - // Enable peripheral control signals and card detect + /* Enable peripheral control signals and card detect */ rc = usbat_device_enable_cdt(us); if (rc != USB_STOR_TRANSPORT_GOOD) return rc; @@ -1364,7 +1392,7 @@ int init_usbat(struct us_data *us) US_DEBUGP("INIT 9\n"); - // At this point, we need to detect which device we are using + /* At this point, we need to detect which device we are using */ if (usbat_set_transport(us, info)) return USB_STOR_TRANSPORT_ERROR; @@ -1414,10 +1442,10 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us) data[0] = 0x00; data[1] = 0x00; data[2] = 0x00; - data[3] = len&0xFF; // (cylL) = expected length (L) - data[4] = (len>>8)&0xFF; // (cylH) = expected length (H) - data[5] = 0xB0; // (device sel) = slave - data[6] = 0xA0; // (command) = ATA PACKET COMMAND + data[3] = len&0xFF; /* (cylL) = expected length (L) */ + data[4] = (len>>8)&0xFF; /* (cylH) = expected length (H) */ + data[5] = 0xB0; /* (device sel) = slave */ + data[6] = 0xA0; /* (command) = ATA PACKET COMMAND */ for (i=7; i<19; i++) { registers[i] = 0x10; @@ -1466,13 +1494,15 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us) return result; } - // Write the 12-byte command header. - - // If the command is BLANK then set the timer for 75 minutes. - // Otherwise set it for 10 minutes. - - // NOTE: THE 8200 DOCUMENTATION STATES THAT BLANKING A CDRW - // AT SPEED 4 IS UNRELIABLE!!! + /* + * Write the 12-byte command header. + * + * If the command is BLANK then set the timer for 75 minutes. + * Otherwise set it for 10 minutes. + * + * NOTE: THE 8200 DOCUMENTATION STATES THAT BLANKING A CDRW + * AT SPEED 4 IS UNRELIABLE!!! + */ if ( (result = usbat_write_block(us, USBAT_ATA, srb->cmnd, 12, @@ -1481,19 +1511,18 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us) return result; } - // If there is response data to be read in - // then do it here. + /* If there is response data to be read in then do it here. */ if (len != 0 && (srb->sc_data_direction == DMA_FROM_DEVICE)) { - // How many bytes to read in? Check cylL register + /* How many bytes to read in? Check cylL register */ if (usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_ME, status) != USB_STOR_XFER_GOOD) { return USB_STOR_TRANSPORT_ERROR; } - if (len > 0xFF) { // need to read cylH also + if (len > 0xFF) { /* need to read cylH also */ len = *status; if (usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_HI, status) != USB_STOR_XFER_GOOD) { @@ -1556,13 +1585,16 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us) if (rc != USB_STOR_TRANSPORT_GOOD) return rc; - info->ssize = 0x200; // hard coded 512 byte sectors as per ATA spec + /* hard coded 512 byte sectors as per ATA spec */ + info->ssize = 0x200; US_DEBUGP("usbat_flash_transport: READ_CAPACITY: %ld sectors, %ld bytes per sector\n", info->sectors, info->ssize); - // build the reply - // note: must return the sector number of the last sector, - // *not* the total number of sectors + /* + * build the reply + * note: must return the sector number of the last sector, + * *not* the total number of sectors + */ ((__be32 *) ptr)[0] = cpu_to_be32(info->sectors - 1); ((__be32 *) ptr)[1] = cpu_to_be32(info->ssize); usb_stor_set_xfer_buf(ptr, 8, srb); @@ -1586,7 +1618,9 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us) } if (srb->cmnd[0] == READ_12) { - // I don't think we'll ever see a READ_12 but support it anyway... + /* + * I don't think we'll ever see a READ_12 but support it anyway + */ block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) | ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); @@ -1608,7 +1642,9 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us) } if (srb->cmnd[0] == WRITE_12) { - // I don't think we'll ever see a WRITE_12 but support it anyway... + /* + * I don't think we'll ever see a WRITE_12 but support it anyway + */ block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) | ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); @@ -1645,8 +1681,10 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us) } if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) { - // sure. whatever. not like we can stop the user from popping - // the media out of the device (no locking doors, etc) + /* + * sure. whatever. not like we can stop the user from popping + * the media out of the device (no locking doors, etc) + */ return USB_STOR_TRANSPORT_GOOD; } diff --git a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h index 5b8e867..25e7d8b 100644 --- a/drivers/usb/storage/shuttle_usbat.h +++ b/drivers/usb/storage/shuttle_usbat.h @@ -55,8 +55,8 @@ #define USBAT_UIO_WRITE 0 /* Qualifier bits */ -#define USBAT_QUAL_FCQ 0x20 // full compare -#define USBAT_QUAL_ALQ 0x10 // auto load subcount +#define USBAT_QUAL_FCQ 0x20 /* full compare */ +#define USBAT_QUAL_ALQ 0x10 /* auto load subcount */ /* USBAT Flash Media status types */ #define USBAT_FLASH_MEDIA_NONE 0 @@ -67,39 +67,39 @@ #define USBAT_FLASH_MEDIA_CHANGED 1 /* USBAT ATA registers */ -#define USBAT_ATA_DATA 0x10 // read/write data (R/W) -#define USBAT_ATA_FEATURES 0x11 // set features (W) -#define USBAT_ATA_ERROR 0x11 // error (R) -#define USBAT_ATA_SECCNT 0x12 // sector count (R/W) -#define USBAT_ATA_SECNUM 0x13 // sector number (R/W) -#define USBAT_ATA_LBA_ME 0x14 // cylinder low (R/W) -#define USBAT_ATA_LBA_HI 0x15 // cylinder high (R/W) -#define USBAT_ATA_DEVICE 0x16 // head/device selection (R/W) -#define USBAT_ATA_STATUS 0x17 // device status (R) -#define USBAT_ATA_CMD 0x17 // device command (W) -#define USBAT_ATA_ALTSTATUS 0x0E // status (no clear IRQ) (R) +#define USBAT_ATA_DATA 0x10 /* read/write data (R/W) */ +#define USBAT_ATA_FEATURES 0x11 /* set features (W) */ +#define USBAT_ATA_ERROR 0x11 /* error (R) */ +#define USBAT_ATA_SECCNT 0x12 /* sector count (R/W) */ +#define USBAT_ATA_SECNUM 0x13 /* sector number (R/W) */ +#define USBAT_ATA_LBA_ME 0x14 /* cylinder low (R/W) */ +#define USBAT_ATA_LBA_HI 0x15 /* cylinder high (R/W) */ +#define USBAT_ATA_DEVICE 0x16 /* head/device selection (R/W) */ +#define USBAT_ATA_STATUS 0x17 /* device status (R) */ +#define USBAT_ATA_CMD 0x17 /* device command (W) */ +#define USBAT_ATA_ALTSTATUS 0x0E /* status (no clear IRQ) (R) */ /* USBAT User I/O Data registers */ -#define USBAT_UIO_EPAD 0x80 // Enable Peripheral Control Signals -#define USBAT_UIO_CDT 0x40 // Card Detect (Read Only) - // CDT = ACKD & !UI1 & !UI0 -#define USBAT_UIO_1 0x20 // I/O 1 -#define USBAT_UIO_0 0x10 // I/O 0 -#define USBAT_UIO_EPP_ATA 0x08 // 1=EPP mode, 0=ATA mode -#define USBAT_UIO_UI1 0x04 // Input 1 -#define USBAT_UIO_UI0 0x02 // Input 0 -#define USBAT_UIO_INTR_ACK 0x01 // Interrupt (ATA & ISA)/Acknowledge (EPP) +#define USBAT_UIO_EPAD 0x80 /* Enable Peripheral Control Signals */ +#define USBAT_UIO_CDT 0x40 /* Card Detect (Read Only) */ + /* CDT = ACKD & !UI1 & !UI0 */ +#define USBAT_UIO_1 0x20 /* I/O 1 */ +#define USBAT_UIO_0 0x10 /* I/O 0 */ +#define USBAT_UIO_EPP_ATA 0x08 /* 1=EPP mode, 0=ATA mode */ +#define USBAT_UIO_UI1 0x04 /* Input 1 */ +#define USBAT_UIO_UI0 0x02 /* Input 0 */ +#define USBAT_UIO_INTR_ACK 0x01 /* Interrupt (ATA/ISA)/Acknowledge (EPP) */ /* USBAT User I/O Enable registers */ -#define USBAT_UIO_DRVRST 0x80 // Reset Peripheral -#define USBAT_UIO_ACKD 0x40 // Enable Card Detect -#define USBAT_UIO_OE1 0x20 // I/O 1 set=output/clr=input - // If ACKD=1, set OE1 to 1 also. -#define USBAT_UIO_OE0 0x10 // I/O 0 set=output/clr=input -#define USBAT_UIO_ADPRST 0x01 // Reset SCM chip +#define USBAT_UIO_DRVRST 0x80 /* Reset Peripheral */ +#define USBAT_UIO_ACKD 0x40 /* Enable Card Detect */ +#define USBAT_UIO_OE1 0x20 /* I/O 1 set=output/clr=input */ + /* If ACKD=1, set OE1 to 1 also. */ +#define USBAT_UIO_OE0 0x10 /* I/O 0 set=output/clr=input */ +#define USBAT_UIO_ADPRST 0x01 /* Reset SCM chip */ /* USBAT Features */ -#define USBAT_FEAT_ETEN 0x80 // External trigger enable +#define USBAT_FEAT_ETEN 0x80 /* External trigger enable */ #define USBAT_FEAT_U1 0x08 #define USBAT_FEAT_U0 0x04 #define USBAT_FEAT_ET1 0x02 @@ -112,12 +112,12 @@ struct usbat_info { int devicetype; /* Used for Flash readers only */ - unsigned long sectors; // total sector count - unsigned long ssize; // sector size in bytes + unsigned long sectors; /* total sector count */ + unsigned long ssize; /* sector size in bytes */ unsigned char sense_key; - unsigned long sense_asc; // additional sense code - unsigned long sense_ascq; // additional sense code qualifier + unsigned long sense_asc; /* additional sense code */ + unsigned long sense_ascq; /* additional sense code qualifier */ }; #endif diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index c1ba530..7ca896a 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -636,11 +636,11 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) /* use the new buffer we have */ old_request_buffer = srb->request_buffer; - srb->request_buffer = srb->sense_buffer; + srb->request_buffer = us->sensebuf; /* set the buffer length for transfer */ old_request_bufflen = srb->request_bufflen; - srb->request_bufflen = 18; + srb->request_bufflen = US_SENSE_SIZE; /* set up for no scatter-gather use */ old_sg = srb->use_sg; @@ -652,6 +652,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) temp_result = us->transport(us->srb, us); /* let's clean up right away */ + memcpy(srb->sense_buffer, us->sensebuf, US_SENSE_SIZE); srb->resid = old_resid; srb->request_buffer = old_request_buffer; srb->request_bufflen = old_request_bufflen; @@ -923,6 +924,7 @@ int usb_stor_Bulk_max_lun(struct us_data *us) int result; /* issue the command */ + us->iobuf[0] = 0; result = usb_stor_control_msg(us, us->recv_ctrl_pipe, US_BULK_GET_MAX_LUN, USB_DIR_IN | USB_TYPE_CLASS | diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h index 8d9e066..0a362cc 100644 --- a/drivers/usb/storage/transport.h +++ b/drivers/usb/storage/transport.h @@ -50,7 +50,7 @@ #define US_PR_CB 0x01 /* Control/Bulk w/o interrupt */ #define US_PR_BULK 0x50 /* bulk only */ #ifdef CONFIG_USB_STORAGE_USBAT -#define US_PR_SCM_ATAPI 0x80 /* SCM-ATAPI bridge */ +#define US_PR_USBAT 0x80 /* SCM-ATAPI bridge */ #endif #ifdef CONFIG_USB_STORAGE_SDDR09 #define US_PR_EUSB_SDDR09 0x81 /* SCM-SCSI bridge for SDDR-09 */ diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index b79dad1..9e926a8 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -71,12 +71,12 @@ UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x0200, UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001, "HP", "CD-Writer+ 8200e", - US_SC_8070, US_PR_SCM_ATAPI, init_usbat, 0), + US_SC_8070, US_PR_USBAT, init_usbat, 0), UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001, "HP", "CD-Writer+ CD-4e", - US_SC_8070, US_PR_SCM_ATAPI, init_usbat, 0), + US_SC_8070, US_PR_USBAT, init_usbat, 0), #endif /* Patch submitted by Mihnea-Costin Grigore <mihnea@zulu.ro> */ @@ -106,6 +106,13 @@ UNUSUAL_DEV( 0x0411, 0x001c, 0x0113, 0x0113, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), +/* Reported by Stefan Werner <dustbln@gmx.de> */ +UNUSUAL_DEV( 0x0419, 0xaaf6, 0x0100, 0x0100, + "TrekStor", + "i.Beat Joy 2.0", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + /* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */ UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, "SMSC", @@ -244,6 +251,13 @@ UNUSUAL_DEV( 0x04da, 0x2372, 0x0000, 0x9999, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ), +/* Reported by Simeon Simeonov <simeonov_2000@yahoo.com> */ +UNUSUAL_DEV( 0x04da, 0x2373, 0x0000, 0x9999, + "LEICA", + "D-LUX Camera", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ), + /* Most of the following entries were developed with the help of * Shuttle/SCM directly. */ @@ -333,9 +347,9 @@ UNUSUAL_DEV( 0x04fc, 0x80c2, 0x0100, 0x0100, #ifdef CONFIG_USB_STORAGE_USBAT UNUSUAL_DEV( 0x04e6, 0x1010, 0x0000, 0x9999, - "SCM", - "SCM USBAT-02", - US_SC_SCSI, US_PR_SCM_ATAPI, init_usbat, + "Shuttle/SCM", + "USBAT-02", + US_SC_SCSI, US_PR_USBAT, init_usbat, US_FL_SINGLE_LUN), #endif @@ -598,6 +612,16 @@ UNUSUAL_DEV( 0x05ac, 0x1205, 0x0000, 0x9999, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), +/* + * Reported by Tyson Vinson <lornoss@gmail.com> + * This particular productId is the iPod Nano + */ +UNUSUAL_DEV( 0x05ac, 0x120a, 0x0000, 0x9999, + "Apple", + "iPod", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY ), + #ifdef CONFIG_USB_STORAGE_JUMPSHOT UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001, "Lexar", @@ -702,6 +726,14 @@ UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200, US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN ), +#ifdef CONFIG_USB_STORAGE_USBAT +UNUSUAL_DEV( 0x0781, 0x0005, 0x0005, 0x0005, + "Sandisk", + "ImageMate SDDR-05b", + US_SC_SCSI, US_PR_USBAT, init_usbat, + US_FL_SINGLE_LUN ), +#endif + UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100, "Sandisk", "ImageMate SDDR-12", @@ -724,7 +756,7 @@ UNUSUAL_DEV( 0x07ab, 0xfc01, 0x0000, 0x9999, #endif /* Reported by Eero Volotinen <eero@ping-viini.org> */ -UNUSUAL_DEV( 0x07ab, 0xfccd, 0x0406, 0x0406, +UNUSUAL_DEV( 0x07ab, 0xfccd, 0x0000, 0x9999, "Freecom Technologies", "FHD-Classic", US_SC_DEVICE, US_PR_DEVICE, NULL, diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index f9a9bfa..3847ebe 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -54,6 +54,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> +#include <linux/kthread.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> @@ -111,11 +112,6 @@ static atomic_t total_threads = ATOMIC_INIT(0); static DECLARE_COMPLETION(threads_gone); -static int storage_probe(struct usb_interface *iface, - const struct usb_device_id *id); - -static void storage_disconnect(struct usb_interface *iface); - /* The entries in this table, except for final ones here * (USB_MASS_STORAGE_CLASS and the empty entry), correspond, * line for line with the entries of us_unsuaul_dev_list[]. @@ -233,13 +229,40 @@ static struct us_unusual_dev us_unusual_dev_list[] = { { NULL } }; -static struct usb_driver usb_storage_driver = { - .owner = THIS_MODULE, - .name = "usb-storage", - .probe = storage_probe, - .disconnect = storage_disconnect, - .id_table = storage_usb_ids, -}; + +#ifdef CONFIG_PM /* Minimal support for suspend and resume */ + +static int storage_suspend(struct usb_interface *iface, pm_message_t message) +{ + struct us_data *us = usb_get_intfdata(iface); + + /* Wait until no command is running */ + down(&us->dev_semaphore); + + US_DEBUGP("%s\n", __FUNCTION__); + iface->dev.power.power_state.event = message.event; + + /* When runtime PM is working, we'll set a flag to indicate + * whether we should autoresume when a SCSI request arrives. */ + + up(&us->dev_semaphore); + return 0; +} + +static int storage_resume(struct usb_interface *iface) +{ + struct us_data *us = usb_get_intfdata(iface); + + down(&us->dev_semaphore); + + US_DEBUGP("%s\n", __FUNCTION__); + iface->dev.power.power_state.event = PM_EVENT_ON; + + up(&us->dev_semaphore); + return 0; +} + +#endif /* CONFIG_PM */ /* * fill_inquiry_response takes an unsigned char array (which must @@ -288,22 +311,7 @@ static int usb_stor_control_thread(void * __us) struct us_data *us = (struct us_data *)__us; struct Scsi_Host *host = us_to_host(us); - lock_kernel(); - - /* - * This thread doesn't need any user-level access, - * so get rid of all our resources. - */ - daemonize("usb-storage"); current->flags |= PF_NOFREEZE; - unlock_kernel(); - - /* acquire a reference to the host, so it won't be deallocated - * until we're ready to exit */ - scsi_host_get(host); - - /* signal that we've started the thread */ - complete(&(us->notify)); for(;;) { US_DEBUGP("*** thread sleeping.\n"); @@ -467,6 +475,12 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf) US_DEBUGP("I/O buffer allocation failed\n"); return -ENOMEM; } + + us->sensebuf = kmalloc(US_SENSE_SIZE, GFP_KERNEL); + if (!us->sensebuf) { + US_DEBUGP("Sense buffer allocation failed\n"); + return -ENOMEM; + } return 0; } @@ -555,8 +569,8 @@ static int get_transport(struct us_data *us) break; #ifdef CONFIG_USB_STORAGE_USBAT - case US_PR_SCM_ATAPI: - us->transport_name = "SCM/ATAPI"; + case US_PR_USBAT: + us->transport_name = "Shuttle USBAT"; us->transport = usbat_transport; us->transport_reset = usb_stor_CB_reset; us->max_lun = 1; @@ -740,6 +754,7 @@ static int get_pipes(struct us_data *us) static int usb_stor_acquire_resources(struct us_data *us) { int p; + struct task_struct *th; us->current_urb = usb_alloc_urb(0, GFP_KERNEL); if (!us->current_urb) { @@ -747,38 +762,28 @@ static int usb_stor_acquire_resources(struct us_data *us) return -ENOMEM; } - /* Lock the device while we carry out the next two operations */ - down(&us->dev_semaphore); - - /* For bulk-only devices, determine the max LUN value */ - if (us->protocol == US_PR_BULK) { - p = usb_stor_Bulk_max_lun(us); - if (p < 0) { - up(&us->dev_semaphore); - return p; - } - us->max_lun = p; - } - /* Just before we start our control thread, initialize * the device if it needs initialization */ - if (us->unusual_dev->initFunction) - us->unusual_dev->initFunction(us); - - up(&us->dev_semaphore); + if (us->unusual_dev->initFunction) { + p = us->unusual_dev->initFunction(us); + if (p) + return p; + } /* Start up our control thread */ - p = kernel_thread(usb_stor_control_thread, us, CLONE_VM); - if (p < 0) { + th = kthread_create(usb_stor_control_thread, us, "usb-storage"); + if (IS_ERR(th)) { printk(KERN_WARNING USB_STORAGE "Unable to start control thread\n"); - return p; + return PTR_ERR(th); } - us->pid = p; - atomic_inc(&total_threads); - /* Wait for the thread to start */ - wait_for_completion(&(us->notify)); + /* Take a reference to the host for the control thread and + * count it among all the threads we have launched. Then + * start it up. */ + scsi_host_get(us_to_host(us)); + atomic_inc(&total_threads); + wake_up_process(th); return 0; } @@ -812,6 +817,8 @@ static void dissociate_dev(struct us_data *us) { US_DEBUGP("-- %s\n", __FUNCTION__); + kfree(us->sensebuf); + /* Free the device-related DMA-mapped buffers */ if (us->cr) usb_buffer_free(us->pusb_dev, sizeof(*us->cr), us->cr, @@ -872,21 +879,6 @@ static int usb_stor_scan_thread(void * __us) { struct us_data *us = (struct us_data *)__us; - /* - * This thread doesn't need any user-level access, - * so get rid of all our resources. - */ - lock_kernel(); - daemonize("usb-stor-scan"); - unlock_kernel(); - - /* Acquire a reference to the host, so it won't be deallocated - * until we're ready to exit */ - scsi_host_get(us_to_host(us)); - - /* Signal that we've started the thread */ - complete(&(us->notify)); - printk(KERN_DEBUG "usb-storage: device found at %d\n", us->pusb_dev->devnum); @@ -904,6 +896,14 @@ retry: /* If the device is still connected, perform the scanning */ if (!test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { + + /* For bulk-only devices, determine the max LUN value */ + if (us->protocol == US_PR_BULK && + !(us->flags & US_FL_SINGLE_LUN)) { + down(&us->dev_semaphore); + us->max_lun = usb_stor_Bulk_max_lun(us); + up(&us->dev_semaphore); + } scsi_scan_host(us_to_host(us)); printk(KERN_DEBUG "usb-storage: device scan complete\n"); @@ -923,6 +923,7 @@ static int storage_probe(struct usb_interface *intf, struct us_data *us; const int id_index = id - storage_usb_ids; int result; + struct task_struct *th; US_DEBUGP("USB Mass Storage device detected\n"); @@ -1003,17 +1004,21 @@ static int storage_probe(struct usb_interface *intf, } /* Start up the thread for delayed SCSI-device scanning */ - result = kernel_thread(usb_stor_scan_thread, us, CLONE_VM); - if (result < 0) { + th = kthread_create(usb_stor_scan_thread, us, "usb-stor-scan"); + if (IS_ERR(th)) { printk(KERN_WARNING USB_STORAGE "Unable to start the device-scanning thread\n"); quiesce_and_remove_host(us); + result = PTR_ERR(th); goto BadDevice; } - atomic_inc(&total_threads); - /* Wait for the thread to start */ - wait_for_completion(&(us->notify)); + /* Take a reference to the host for the scanning thread and + * count it among all the threads we have launched. Then + * start it up. */ + scsi_host_get(us_to_host(us)); + atomic_inc(&total_threads); + wake_up_process(th); return 0; @@ -1038,6 +1043,18 @@ static void storage_disconnect(struct usb_interface *intf) * Initialization and registration ***********************************************************************/ +static struct usb_driver usb_storage_driver = { + .owner = THIS_MODULE, + .name = "usb-storage", + .probe = storage_probe, + .disconnect = storage_disconnect, +#ifdef CONFIG_PM + .suspend = storage_suspend, + .resume = storage_resume, +#endif + .id_table = storage_usb_ids, +}; + static int __init usb_stor_init(void) { int retval; diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h index a195ada..98b0971 100644 --- a/drivers/usb/storage/usb.h +++ b/drivers/usb/storage/usb.h @@ -117,6 +117,7 @@ enum { US_DO_ALL_FLAGS }; */ #define US_IOBUF_SIZE 64 /* Size of the DMA-mapped I/O buffer */ +#define US_SENSE_SIZE 18 /* Size of the autosense data buffer */ typedef int (*trans_cmnd)(struct scsi_cmnd *, struct us_data*); typedef int (*trans_reset)(struct us_data*); @@ -160,14 +161,12 @@ struct us_data { struct scsi_cmnd *srb; /* current srb */ unsigned int tag; /* current dCBWTag */ - /* thread information */ - int pid; /* control thread */ - /* control and bulk communications data */ struct urb *current_urb; /* USB requests */ struct usb_ctrlrequest *cr; /* control requests */ struct usb_sg_request current_sg; /* scatter-gather req. */ unsigned char *iobuf; /* I/O buffer */ + unsigned char *sensebuf; /* sense data buffer */ dma_addr_t cr_dma; /* buffer DMA addresses */ dma_addr_t iobuf_dma; diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index 353f24d..6c3a53f 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -223,9 +223,8 @@ static struct file_operations skel_fops = { * and to have the device registered with devfs and the driver core */ static struct usb_class_driver skel_class = { - .name = "usb/skel%d", + .name = "skel%d", .fops = &skel_fops, - .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, .minor_base = USB_SKEL_MINOR_BASE, }; |