diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2005-11-16 17:14:45 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-11-16 17:14:45 -0800 |
commit | e504d12e6db374dce8641f9909ee82c303a2690b (patch) | |
tree | 8dd89411891a6bc3f39b40927fdb6a1ded27adbd /usb | |
parent | 2bd1a3b53728029fdb4ed6898aaa117ce5620810 (diff) | |
download | patches-e504d12e6db374dce8641f9909ee82c303a2690b.tar.gz |
deleted the nokia_dku2 driver.
Diffstat (limited to 'usb')
-rw-r--r-- | usb/usb-delete-nokia_dku2.patch | 188 | ||||
-rw-r--r-- | usb/usb-dynamic-id-01.patch | 742 | ||||
-rw-r--r-- | usb/usb-dynamic-id-02.patch | 352 |
3 files changed, 1282 insertions, 0 deletions
diff --git a/usb/usb-delete-nokia_dku2.patch b/usb/usb-delete-nokia_dku2.patch new file mode 100644 index 0000000000000..cfe838ba63d7f --- /dev/null +++ b/usb/usb-delete-nokia_dku2.patch @@ -0,0 +1,188 @@ +From foo@baz.org Wed Nov 16 13:31:19 2005 +Date: Wed, 16 Nov 2005 13:41:28 -0800 +From: Greg Kroah-Hartman <gregkh@suse.de> +Subject: USB: delete the nokia_dku2 driver + +It was causing too many problems, and this is not the proper type of +driver for this device. + +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/usb/serial/Kconfig | 9 -- + drivers/usb/serial/Makefile | 1 + drivers/usb/serial/nokia_dku2.c | 142 ---------------------------------------- + 3 files changed, 152 deletions(-) + +--- gregkh-2.6.orig/drivers/usb/serial/Kconfig ++++ gregkh-2.6/drivers/usb/serial/Kconfig +@@ -403,15 +403,6 @@ 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 +--- gregkh-2.6.orig/drivers/usb/serial/Makefile ++++ gregkh-2.6/drivers/usb/serial/Makefile +@@ -32,7 +32,6 @@ obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA) += + 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 +--- gregkh-2.6.orig/drivers/usb/serial/nokia_dku2.c ++++ /dev/null +@@ -1,142 +0,0 @@ +-/* +- * 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/usb/usb-dynamic-id-01.patch b/usb/usb-dynamic-id-01.patch new file mode 100644 index 0000000000000..98f3a908f0b47 --- /dev/null +++ b/usb/usb-dynamic-id-01.patch @@ -0,0 +1,742 @@ +From foo@baz.org Wed Nov 16 13:31:19 2005 +Date: Wed, 16 Nov 2005 13:41:28 -0800 +From: Greg Kroah-Hartman <gregkh@suse.de> +Subject: USB: reorg some functions out of the main usb.c file + +This will make the dynamic-id stuff easier to do, as it will be +self-contained. + +No logic was changed at all. + +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + + +--- + Documentation/DocBook/usb.tmpl | 1 + drivers/usb/core/Makefile | 2 + drivers/usb/core/driver.c | 338 +++++++++++++++++++++++++++++++++++++++++ + drivers/usb/core/usb.c | 310 ------------------------------------- + drivers/usb/core/usb.h | 3 + 5 files changed, 343 insertions(+), 311 deletions(-) + +--- gregkh-2.6.orig/drivers/usb/core/usb.c ++++ gregkh-2.6/drivers/usb/core/usb.c +@@ -52,161 +52,6 @@ static int nousb; /* Disable USB when bu + static DECLARE_RWSEM(usb_all_devices_rwsem); + + +-static int generic_probe (struct device *dev) +-{ +- return 0; +-} +-static int generic_remove (struct device *dev) +-{ +- struct usb_device *udev = to_usb_device(dev); +- +- /* if this is only an unbind, not a physical disconnect, then +- * unconfigure the device */ +- if (udev->state == USB_STATE_CONFIGURED) +- usb_set_configuration(udev, 0); +- +- /* in case the call failed or the device was suspended */ +- if (udev->state >= USB_STATE_CONFIGURED) +- usb_disable_device(udev, 0); +- return 0; +-} +- +-static struct device_driver usb_generic_driver = { +- .owner = THIS_MODULE, +- .name = "usb", +- .bus = &usb_bus_type, +- .probe = generic_probe, +- .remove = generic_remove, +-}; +- +-static int usb_generic_driver_data; +- +-/* called from driver core with usb_bus_type.subsys writelock */ +-static int usb_probe_interface(struct device *dev) +-{ +- struct usb_interface * intf = to_usb_interface(dev); +- struct usb_driver * driver = to_usb_driver(dev->driver); +- const struct usb_device_id *id; +- int error = -ENODEV; +- +- dev_dbg(dev, "%s\n", __FUNCTION__); +- +- if (!driver->probe) +- return error; +- /* FIXME we'd much prefer to just resume it ... */ +- if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED) +- return -EHOSTUNREACH; +- +- 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); +- if (error) { +- mark_quiesced(intf); +- intf->condition = USB_INTERFACE_UNBOUND; +- } else +- intf->condition = USB_INTERFACE_BOUND; +- } +- +- return error; +-} +- +-/* called from driver core with usb_bus_type.subsys writelock */ +-static int usb_unbind_interface(struct device *dev) +-{ +- struct usb_interface *intf = to_usb_interface(dev); +- struct usb_driver *driver = to_usb_driver(intf->dev.driver); +- +- intf->condition = USB_INTERFACE_UNBINDING; +- +- /* release all urbs for this interface */ +- usb_disable_interface(interface_to_usbdev(intf), intf); +- +- if (driver && driver->disconnect) +- driver->disconnect(intf); +- +- /* reset other interface state */ +- usb_set_interface(interface_to_usbdev(intf), +- intf->altsetting[0].desc.bInterfaceNumber, +- 0); +- usb_set_intfdata(intf, NULL); +- intf->condition = USB_INTERFACE_UNBOUND; +- mark_quiesced(intf); +- +- return 0; +-} +- +-/** +- * usb_register - register a USB driver +- * @new_driver: USB operations for the driver +- * +- * Registers a USB driver with the USB core. The list of unattached +- * interfaces will be rescanned whenever a new driver is added, allowing +- * the new driver to attach to any recognized devices. +- * Returns a negative error code on failure and 0 on success. +- * +- * NOTE: if you want your driver to use the USB major number, you must call +- * usb_register_dev() to enable that functionality. This function no longer +- * takes care of that. +- */ +-int usb_register(struct usb_driver *new_driver) +-{ +- int retval = 0; +- +- if (nousb) +- return -ENODEV; +- +- new_driver->driver.name = (char *)new_driver->name; +- new_driver->driver.bus = &usb_bus_type; +- new_driver->driver.probe = usb_probe_interface; +- new_driver->driver.remove = usb_unbind_interface; +- new_driver->driver.owner = new_driver->owner; +- +- usb_lock_all_devices(); +- retval = driver_register(&new_driver->driver); +- usb_unlock_all_devices(); +- +- if (!retval) { +- pr_info("%s: registered new driver %s\n", +- usbcore_name, new_driver->name); +- usbfs_update_special(); +- } else { +- printk(KERN_ERR "%s: error %d registering driver %s\n", +- usbcore_name, retval, new_driver->name); +- } +- +- return retval; +-} +- +-/** +- * usb_deregister - unregister a USB driver +- * @driver: USB operations of the driver to unregister +- * Context: must be able to sleep +- * +- * Unlinks the specified driver from the internal USB driver list. +- * +- * NOTE: If you called usb_register_dev(), you still need to call +- * usb_deregister_dev() to clean up your driver's allocated minor numbers, +- * this * call will no longer do it for you. +- */ +-void usb_deregister(struct usb_driver *driver) +-{ +- pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name); +- +- usb_lock_all_devices(); +- driver_unregister (&driver->driver); +- usb_unlock_all_devices(); +- +- usbfs_update_special(); +-} +- + /** + * usb_ifnum_to_if - get the interface object with a given interface number + * @dev: the device whose current configuration is considered +@@ -352,137 +197,6 @@ void usb_driver_release_interface(struct + mark_quiesced(iface); + } + +-/** +- * usb_match_id - find first usb_device_id matching device or interface +- * @interface: the interface of interest +- * @id: array of usb_device_id structures, terminated by zero entry +- * +- * usb_match_id searches an array of usb_device_id's and returns +- * the first one matching the device or interface, or null. +- * This is used when binding (or rebinding) a driver to an interface. +- * Most USB device drivers will use this indirectly, through the usb core, +- * but some layered driver frameworks use it directly. +- * These device tables are exported with MODULE_DEVICE_TABLE, through +- * modutils, to support the driver loading functionality of USB hotplugging. +- * +- * What Matches: +- * +- * The "match_flags" element in a usb_device_id controls which +- * members are used. If the corresponding bit is set, the +- * value in the device_id must match its corresponding member +- * in the device or interface descriptor, or else the device_id +- * does not match. +- * +- * "driver_info" is normally used only by device drivers, +- * but you can create a wildcard "matches anything" usb_device_id +- * as a driver's "modules.usbmap" entry if you provide an id with +- * only a nonzero "driver_info" field. If you do this, the USB device +- * driver's probe() routine should use additional intelligence to +- * decide whether to bind to the specified interface. +- * +- * What Makes Good usb_device_id Tables: +- * +- * The match algorithm is very simple, so that intelligence in +- * driver selection must come from smart driver id records. +- * Unless you have good reasons to use another selection policy, +- * provide match elements only in related groups, and order match +- * specifiers from specific to general. Use the macros provided +- * for that purpose if you can. +- * +- * The most specific match specifiers use device descriptor +- * data. These are commonly used with product-specific matches; +- * the USB_DEVICE macro lets you provide vendor and product IDs, +- * and you can also match against ranges of product revisions. +- * These are widely used for devices with application or vendor +- * specific bDeviceClass values. +- * +- * Matches based on device class/subclass/protocol specifications +- * are slightly more general; use the USB_DEVICE_INFO macro, or +- * its siblings. These are used with single-function devices +- * where bDeviceClass doesn't specify that each interface has +- * its own class. +- * +- * Matches based on interface class/subclass/protocol are the +- * most general; they let drivers bind to any interface on a +- * multiple-function device. Use the USB_INTERFACE_INFO +- * macro, or its siblings, to match class-per-interface style +- * devices (as recorded in bDeviceClass). +- * +- * Within those groups, remember that not all combinations are +- * meaningful. For example, don't give a product version range +- * without vendor and product IDs; or specify a protocol without +- * its associated class and subclass. +- */ +-const struct usb_device_id * +-usb_match_id(struct usb_interface *interface, const struct usb_device_id *id) +-{ +- struct usb_host_interface *intf; +- struct usb_device *dev; +- +- /* proc_connectinfo in devio.c may call us with id == NULL. */ +- if (id == NULL) +- return NULL; +- +- intf = interface->cur_altsetting; +- dev = interface_to_usbdev(interface); +- +- /* It is important to check that id->driver_info is nonzero, +- since an entry that is all zeroes except for a nonzero +- id->driver_info is the way to create an entry that +- indicates that the driver want to examine every +- device and interface. */ +- for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass || +- id->driver_info; id++) { +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && +- id->idVendor != le16_to_cpu(dev->descriptor.idVendor)) +- continue; +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) && +- id->idProduct != le16_to_cpu(dev->descriptor.idProduct)) +- continue; +- +- /* No need to test id->bcdDevice_lo != 0, since 0 is never +- greater than any unsigned number. */ +- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) && +- (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice))) +- continue; +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) && +- (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice))) +- continue; +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) && +- (id->bDeviceClass != dev->descriptor.bDeviceClass)) +- continue; +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) && +- (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass)) +- continue; +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) && +- (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol)) +- continue; +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) && +- (id->bInterfaceClass != intf->desc.bInterfaceClass)) +- continue; +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) && +- (id->bInterfaceSubClass != intf->desc.bInterfaceSubClass)) +- continue; +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) && +- (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol)) +- continue; +- +- return id; +- } +- +- return NULL; +-} +- +- + static int __find_interface(struct device * dev, void * data) + { + struct usb_interface ** ret = (struct usb_interface **)data; +@@ -520,27 +234,6 @@ struct usb_interface *usb_find_interface + return ret ? intf : NULL; + } + +-static int usb_device_match (struct device *dev, struct device_driver *drv) +-{ +- struct usb_interface *intf; +- struct usb_driver *usb_drv; +- const struct usb_device_id *id; +- +- /* check for generic driver, which we don't match any device with */ +- if (drv == &usb_generic_driver) +- return 0; +- +- intf = to_usb_interface(dev); +- usb_drv = to_usb_driver(drv); +- +- id = usb_match_id (intf, usb_drv->id_table); +- if (id) +- return 1; +- +- return 0; +-} +- +- + #ifdef CONFIG_HOTPLUG + + /* +@@ -1591,8 +1284,6 @@ module_exit(usb_exit); + * driver modules to use. + */ + +-EXPORT_SYMBOL(usb_register); +-EXPORT_SYMBOL(usb_deregister); + EXPORT_SYMBOL(usb_disabled); + + EXPORT_SYMBOL_GPL(usb_get_intf); +@@ -1610,7 +1301,6 @@ EXPORT_SYMBOL(usb_unlock_device); + + EXPORT_SYMBOL(usb_driver_claim_interface); + EXPORT_SYMBOL(usb_driver_release_interface); +-EXPORT_SYMBOL(usb_match_id); + EXPORT_SYMBOL(usb_find_interface); + EXPORT_SYMBOL(usb_ifnum_to_if); + EXPORT_SYMBOL(usb_altnum_to_altsetting); +--- gregkh-2.6.orig/drivers/usb/core/Makefile ++++ gregkh-2.6/drivers/usb/core/Makefile +@@ -2,7 +2,7 @@ + # Makefile for USB Core files and filesystem + # + +-usbcore-objs := usb.o hub.o hcd.o urb.o message.o \ ++usbcore-objs := usb.o hub.o hcd.o urb.o message.o driver.o \ + config.o file.o buffer.o sysfs.o devio.o notify.o + + ifeq ($(CONFIG_PCI),y) +--- /dev/null ++++ gregkh-2.6/drivers/usb/core/driver.c +@@ -0,0 +1,338 @@ ++/* ++ * drivers/usb/driver.c - most of the driver model stuff for usb ++ * ++ * (C) Copyright 2005 Greg Kroah-Hartman <gregkh@suse.de> ++ * ++ * based on drivers/usb/usb.c which had the following copyrights: ++ * (C) Copyright Linus Torvalds 1999 ++ * (C) Copyright Johannes Erdfelt 1999-2001 ++ * (C) Copyright Andreas Gal 1999 ++ * (C) Copyright Gregory P. Smith 1999 ++ * (C) Copyright Deti Fliegl 1999 (new USB architecture) ++ * (C) Copyright Randy Dunlap 2000 ++ * (C) Copyright David Brownell 2000-2004 ++ * (C) Copyright Yggdrasil Computing, Inc. 2000 ++ * (usb_device_id matching changes by Adam J. Richter) ++ * (C) Copyright Greg Kroah-Hartman 2002-2003 ++ * ++ * NOTE! This is not actually a driver at all, rather this is ++ * just a collection of helper routines that implement the ++ * generic USB things that the real drivers can use.. ++ * ++ */ ++ ++#include <linux/config.h> ++#include <linux/device.h> ++#include <linux/usb.h> ++#include "hcd.h" ++#include "usb.h" ++ ++static int generic_probe(struct device *dev) ++{ ++ return 0; ++} ++static int generic_remove(struct device *dev) ++{ ++ struct usb_device *udev = to_usb_device(dev); ++ ++ /* if this is only an unbind, not a physical disconnect, then ++ * unconfigure the device */ ++ if (udev->state == USB_STATE_CONFIGURED) ++ usb_set_configuration(udev, 0); ++ ++ /* in case the call failed or the device was suspended */ ++ if (udev->state >= USB_STATE_CONFIGURED) ++ usb_disable_device(udev, 0); ++ return 0; ++} ++ ++struct device_driver usb_generic_driver = { ++ .owner = THIS_MODULE, ++ .name = "usb", ++ .bus = &usb_bus_type, ++ .probe = generic_probe, ++ .remove = generic_remove, ++}; ++ ++/* Fun hack to determine if the struct device is a ++ * usb device or a usb interface. */ ++int usb_generic_driver_data; ++ ++/* called from driver core with usb_bus_type.subsys writelock */ ++static int usb_probe_interface(struct device *dev) ++{ ++ struct usb_interface * intf = to_usb_interface(dev); ++ struct usb_driver * driver = to_usb_driver(dev->driver); ++ const struct usb_device_id *id; ++ int error = -ENODEV; ++ ++ dev_dbg(dev, "%s\n", __FUNCTION__); ++ ++ if (!driver->probe) ++ return error; ++ /* FIXME we'd much prefer to just resume it ... */ ++ if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED) ++ return -EHOSTUNREACH; ++ ++ 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); ++ if (error) { ++ mark_quiesced(intf); ++ intf->condition = USB_INTERFACE_UNBOUND; ++ } else ++ intf->condition = USB_INTERFACE_BOUND; ++ } ++ ++ return error; ++} ++ ++/* called from driver core with usb_bus_type.subsys writelock */ ++static int usb_unbind_interface(struct device *dev) ++{ ++ struct usb_interface *intf = to_usb_interface(dev); ++ struct usb_driver *driver = to_usb_driver(intf->dev.driver); ++ ++ intf->condition = USB_INTERFACE_UNBINDING; ++ ++ /* release all urbs for this interface */ ++ usb_disable_interface(interface_to_usbdev(intf), intf); ++ ++ if (driver && driver->disconnect) ++ driver->disconnect(intf); ++ ++ /* reset other interface state */ ++ usb_set_interface(interface_to_usbdev(intf), ++ intf->altsetting[0].desc.bInterfaceNumber, ++ 0); ++ usb_set_intfdata(intf, NULL); ++ intf->condition = USB_INTERFACE_UNBOUND; ++ mark_quiesced(intf); ++ ++ return 0; ++} ++ ++/** ++ * usb_match_id - find first usb_device_id matching device or interface ++ * @interface: the interface of interest ++ * @id: array of usb_device_id structures, terminated by zero entry ++ * ++ * usb_match_id searches an array of usb_device_id's and returns ++ * the first one matching the device or interface, or null. ++ * This is used when binding (or rebinding) a driver to an interface. ++ * Most USB device drivers will use this indirectly, through the usb core, ++ * but some layered driver frameworks use it directly. ++ * These device tables are exported with MODULE_DEVICE_TABLE, through ++ * modutils, to support the driver loading functionality of USB hotplugging. ++ * ++ * What Matches: ++ * ++ * The "match_flags" element in a usb_device_id controls which ++ * members are used. If the corresponding bit is set, the ++ * value in the device_id must match its corresponding member ++ * in the device or interface descriptor, or else the device_id ++ * does not match. ++ * ++ * "driver_info" is normally used only by device drivers, ++ * but you can create a wildcard "matches anything" usb_device_id ++ * as a driver's "modules.usbmap" entry if you provide an id with ++ * only a nonzero "driver_info" field. If you do this, the USB device ++ * driver's probe() routine should use additional intelligence to ++ * decide whether to bind to the specified interface. ++ * ++ * What Makes Good usb_device_id Tables: ++ * ++ * The match algorithm is very simple, so that intelligence in ++ * driver selection must come from smart driver id records. ++ * Unless you have good reasons to use another selection policy, ++ * provide match elements only in related groups, and order match ++ * specifiers from specific to general. Use the macros provided ++ * for that purpose if you can. ++ * ++ * The most specific match specifiers use device descriptor ++ * data. These are commonly used with product-specific matches; ++ * the USB_DEVICE macro lets you provide vendor and product IDs, ++ * and you can also match against ranges of product revisions. ++ * These are widely used for devices with application or vendor ++ * specific bDeviceClass values. ++ * ++ * Matches based on device class/subclass/protocol specifications ++ * are slightly more general; use the USB_DEVICE_INFO macro, or ++ * its siblings. These are used with single-function devices ++ * where bDeviceClass doesn't specify that each interface has ++ * its own class. ++ * ++ * Matches based on interface class/subclass/protocol are the ++ * most general; they let drivers bind to any interface on a ++ * multiple-function device. Use the USB_INTERFACE_INFO ++ * macro, or its siblings, to match class-per-interface style ++ * devices (as recorded in bDeviceClass). ++ * ++ * Within those groups, remember that not all combinations are ++ * meaningful. For example, don't give a product version range ++ * without vendor and product IDs; or specify a protocol without ++ * its associated class and subclass. ++ */ ++const struct usb_device_id *usb_match_id(struct usb_interface *interface, ++ const struct usb_device_id *id) ++{ ++ struct usb_host_interface *intf; ++ struct usb_device *dev; ++ ++ /* proc_connectinfo in devio.c may call us with id == NULL. */ ++ if (id == NULL) ++ return NULL; ++ ++ intf = interface->cur_altsetting; ++ dev = interface_to_usbdev(interface); ++ ++ /* It is important to check that id->driver_info is nonzero, ++ since an entry that is all zeroes except for a nonzero ++ id->driver_info is the way to create an entry that ++ indicates that the driver want to examine every ++ device and interface. */ ++ for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass || ++ id->driver_info; id++) { ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && ++ id->idVendor != le16_to_cpu(dev->descriptor.idVendor)) ++ continue; ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) && ++ id->idProduct != le16_to_cpu(dev->descriptor.idProduct)) ++ continue; ++ ++ /* No need to test id->bcdDevice_lo != 0, since 0 is never ++ greater than any unsigned number. */ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) && ++ (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice))) ++ continue; ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) && ++ (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice))) ++ continue; ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) && ++ (id->bDeviceClass != dev->descriptor.bDeviceClass)) ++ continue; ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) && ++ (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass)) ++ continue; ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) && ++ (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol)) ++ continue; ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) && ++ (id->bInterfaceClass != intf->desc.bInterfaceClass)) ++ continue; ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) && ++ (id->bInterfaceSubClass != intf->desc.bInterfaceSubClass)) ++ continue; ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) && ++ (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol)) ++ continue; ++ ++ return id; ++ } ++ ++ return NULL; ++} ++EXPORT_SYMBOL(usb_match_id); ++ ++int usb_device_match(struct device *dev, struct device_driver *drv) ++{ ++ struct usb_interface *intf; ++ struct usb_driver *usb_drv; ++ const struct usb_device_id *id; ++ ++ /* check for generic driver, which we don't match any device with */ ++ if (drv == &usb_generic_driver) ++ return 0; ++ ++ intf = to_usb_interface(dev); ++ usb_drv = to_usb_driver(drv); ++ ++ id = usb_match_id(intf, usb_drv->id_table); ++ if (id) ++ return 1; ++ ++ return 0; ++} ++ ++/** ++ * usb_register - register a USB driver ++ * @new_driver: USB operations for the driver ++ * ++ * Registers a USB driver with the USB core. The list of unattached ++ * interfaces will be rescanned whenever a new driver is added, allowing ++ * the new driver to attach to any recognized devices. ++ * Returns a negative error code on failure and 0 on success. ++ * ++ * NOTE: if you want your driver to use the USB major number, you must call ++ * usb_register_dev() to enable that functionality. This function no longer ++ * takes care of that. ++ */ ++int usb_register(struct usb_driver *new_driver) ++{ ++ int retval = 0; ++ ++ if (usb_disabled()) ++ return -ENODEV; ++ ++ new_driver->driver.name = (char *)new_driver->name; ++ new_driver->driver.bus = &usb_bus_type; ++ new_driver->driver.probe = usb_probe_interface; ++ new_driver->driver.remove = usb_unbind_interface; ++ new_driver->driver.owner = new_driver->owner; ++ ++ usb_lock_all_devices(); ++ retval = driver_register(&new_driver->driver); ++ usb_unlock_all_devices(); ++ ++ if (!retval) { ++ pr_info("%s: registered new driver %s\n", ++ usbcore_name, new_driver->name); ++ usbfs_update_special(); ++ } else { ++ printk(KERN_ERR "%s: error %d registering driver %s\n", ++ usbcore_name, retval, new_driver->name); ++ } ++ ++ return retval; ++} ++EXPORT_SYMBOL(usb_register); ++ ++/** ++ * usb_deregister - unregister a USB driver ++ * @driver: USB operations of the driver to unregister ++ * Context: must be able to sleep ++ * ++ * Unlinks the specified driver from the internal USB driver list. ++ * ++ * NOTE: If you called usb_register_dev(), you still need to call ++ * usb_deregister_dev() to clean up your driver's allocated minor numbers, ++ * this * call will no longer do it for you. ++ */ ++void usb_deregister(struct usb_driver *driver) ++{ ++ pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name); ++ ++ usb_lock_all_devices(); ++ driver_unregister(&driver->driver); ++ usb_unlock_all_devices(); ++ ++ usbfs_update_special(); ++} ++EXPORT_SYMBOL(usb_deregister); +--- gregkh-2.6.orig/drivers/usb/core/usb.h ++++ gregkh-2.6/drivers/usb/core/usb.h +@@ -33,6 +33,9 @@ extern void usb_host_cleanup(void); + extern int usb_suspend_device(struct usb_device *dev); + extern int usb_resume_device(struct usb_device *dev); + ++extern struct device_driver usb_generic_driver; ++extern int usb_generic_driver_data; ++extern int usb_device_match(struct device *dev, struct device_driver *drv); + + /* Interfaces and their "power state" are owned by usbcore */ + +--- gregkh-2.6.orig/Documentation/DocBook/usb.tmpl ++++ gregkh-2.6/Documentation/DocBook/usb.tmpl +@@ -253,6 +253,7 @@ + !Edrivers/usb/core/urb.c + !Edrivers/usb/core/message.c + !Edrivers/usb/core/file.c ++!Edrivers/usb/core/driver.c + !Edrivers/usb/core/usb.c + !Edrivers/usb/core/hub.c + </chapter> diff --git a/usb/usb-dynamic-id-02.patch b/usb/usb-dynamic-id-02.patch new file mode 100644 index 0000000000000..92bf1df03e001 --- /dev/null +++ b/usb/usb-dynamic-id-02.patch @@ -0,0 +1,352 @@ +From foo@baz.org Wed Nov 16 13:31:19 2005 +Date: Wed, 16 Nov 2005 13:41:28 -0800 +From: Greg Kroah-Hartman <gregkh@suse.de> +Subject: USB: add dynamic id functionality to USB core + +Echo the usb vendor and product id to the "new_id" file in the driver's +sysfs directory, and then that driver will be able to bind to a device +with those ids if it is present. + + +Example: + echo 0557 2008 > /sys/bus/usb/drivers/foo_driver/new_id +adds the hex values 0557 and 2008 to the device id table for the foo_driver. + + +Note, usb-serial drivers do not currently work with this capability yet. +usb-storage also might have some oddities. + + +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + + +--- + drivers/usb/core/driver.c | 218 +++++++++++++++++++++++++++++++++++----------- + include/linux/usb.h | 8 + + 2 files changed, 176 insertions(+), 50 deletions(-) + +--- gregkh-2.6.orig/drivers/usb/core/driver.c ++++ gregkh-2.6/drivers/usb/core/driver.c +@@ -27,6 +27,15 @@ + #include "hcd.h" + #include "usb.h" + ++static int usb_match_one_id(struct usb_interface *interface, ++ const struct usb_device_id *id); ++ ++struct usb_dynid { ++ struct list_head node; ++ struct usb_device_id id; ++}; ++ ++ + static int generic_probe(struct device *dev) + { + return 0; +@@ -58,6 +67,96 @@ struct device_driver usb_generic_driver + * usb device or a usb interface. */ + int usb_generic_driver_data; + ++#ifdef CONFIG_HOTPLUG ++ ++/* ++ * Adds a new dynamic USBdevice ID to this driver, ++ * and cause the driver to probe for all devices again. ++ */ ++static ssize_t store_new_id(struct device_driver *driver, ++ const char *buf, size_t count) ++{ ++ struct usb_driver *usb_drv = to_usb_driver(driver); ++ struct usb_dynid *dynid; ++ u32 idVendor = 0; ++ u32 idProduct = 0; ++ int fields = 0; ++ ++ fields = sscanf(buf, "%x %x", &idVendor, &idProduct); ++ if (fields < 0) ++ return -EINVAL; ++ ++ dynid = kzalloc(sizeof(*dynid), GFP_KERNEL); ++ if (!dynid) ++ return -ENOMEM; ++ ++ INIT_LIST_HEAD(&dynid->node); ++ dynid->id.idVendor = idVendor; ++ dynid->id.idProduct = idProduct; ++ dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE; ++ ++ spin_lock(&usb_drv->dynids.lock); ++ list_add_tail(&usb_drv->dynids.list, &dynid->node); ++ spin_unlock(&usb_drv->dynids.lock); ++ ++ if (get_driver(&usb_drv->driver)) { ++ driver_attach(&usb_drv->driver); ++ put_driver(&usb_drv->driver); ++ } ++ ++ return count; ++} ++static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); ++ ++static int usb_create_newid_file(struct usb_driver *usb_drv) ++{ ++ int error = 0; ++ ++ if (usb_drv->probe != NULL) ++ error = sysfs_create_file(&usb_drv->driver.kobj, ++ &driver_attr_new_id.attr); ++ return error; ++} ++ ++static void usb_free_dynids(struct usb_driver *usb_drv) ++{ ++ struct usb_dynid *dynid, *n; ++ ++ spin_lock(&usb_drv->dynids.lock); ++ list_for_each_entry_safe(dynid, n, &usb_drv->dynids.list, node) { ++ list_del(&dynid->node); ++ kfree(dynid); ++ } ++ spin_unlock(&usb_drv->dynids.lock); ++} ++#else ++static inline int usb_create_newid_file(struct usb_driver *usb_drv) ++{ ++ return 0; ++} ++ ++static inline void usb_free_dynids(struct usb_driver *usb_drv) ++{ ++} ++#endif ++ ++static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *intf, ++ struct usb_driver *drv) ++{ ++ struct usb_dynid *dynid; ++ ++ spin_lock(&drv->dynids.lock); ++ list_for_each_entry(dynid, &drv->dynids.list, node) { ++ if (usb_match_one_id(intf, &dynid->id)) { ++ spin_unlock(&drv->dynids.lock); ++ return &dynid->id; ++ } ++ } ++ spin_unlock(&drv->dynids.lock); ++ return NULL; ++} ++ ++ + /* called from driver core with usb_bus_type.subsys writelock */ + static int usb_probe_interface(struct device *dev) + { +@@ -75,6 +174,8 @@ static int usb_probe_interface(struct de + return -EHOSTUNREACH; + + id = usb_match_id(intf, driver->id_table); ++ if (!id) ++ id = usb_match_dynamic_id(intf, driver); + if (id) { + dev_dbg(dev, "%s - got id\n", __FUNCTION__); + +@@ -120,6 +221,64 @@ static int usb_unbind_interface(struct d + return 0; + } + ++/* returns 0 if no match, 1 if match */ ++static int usb_match_one_id(struct usb_interface *interface, ++ const struct usb_device_id *id) ++{ ++ struct usb_host_interface *intf; ++ struct usb_device *dev; ++ ++ /* proc_connectinfo in devio.c may call us with id == NULL. */ ++ if (id == NULL) ++ return 0; ++ ++ intf = interface->cur_altsetting; ++ dev = interface_to_usbdev(interface); ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && ++ id->idVendor != le16_to_cpu(dev->descriptor.idVendor)) ++ return 0; ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) && ++ id->idProduct != le16_to_cpu(dev->descriptor.idProduct)) ++ return 0; ++ ++ /* No need to test id->bcdDevice_lo != 0, since 0 is never ++ greater than any unsigned number. */ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) && ++ (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice))) ++ return 0; ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) && ++ (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice))) ++ return 0; ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) && ++ (id->bDeviceClass != dev->descriptor.bDeviceClass)) ++ return 0; ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) && ++ (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass)) ++ return 0; ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) && ++ (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol)) ++ return 0; ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) && ++ (id->bInterfaceClass != intf->desc.bInterfaceClass)) ++ return 0; ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) && ++ (id->bInterfaceSubClass != intf->desc.bInterfaceSubClass)) ++ return 0; ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) && ++ (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol)) ++ return 0; ++ ++ return 1; ++} + /** + * usb_match_id - find first usb_device_id matching device or interface + * @interface: the interface of interest +@@ -184,16 +343,10 @@ static int usb_unbind_interface(struct d + const struct usb_device_id *usb_match_id(struct usb_interface *interface, + const struct usb_device_id *id) + { +- struct usb_host_interface *intf; +- struct usb_device *dev; +- + /* proc_connectinfo in devio.c may call us with id == NULL. */ + if (id == NULL) + return NULL; + +- intf = interface->cur_altsetting; +- dev = interface_to_usbdev(interface); +- + /* It is important to check that id->driver_info is nonzero, + since an entry that is all zeroes except for a nonzero + id->driver_info is the way to create an entry that +@@ -201,50 +354,8 @@ const struct usb_device_id *usb_match_id + device and interface. */ + for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass || + id->driver_info; id++) { +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && +- id->idVendor != le16_to_cpu(dev->descriptor.idVendor)) +- continue; +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) && +- id->idProduct != le16_to_cpu(dev->descriptor.idProduct)) +- continue; +- +- /* No need to test id->bcdDevice_lo != 0, since 0 is never +- greater than any unsigned number. */ +- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) && +- (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice))) +- continue; +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) && +- (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice))) +- continue; +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) && +- (id->bDeviceClass != dev->descriptor.bDeviceClass)) +- continue; +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) && +- (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass)) +- continue; +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) && +- (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol)) +- continue; +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) && +- (id->bInterfaceClass != intf->desc.bInterfaceClass)) +- continue; +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) && +- (id->bInterfaceSubClass != intf->desc.bInterfaceSubClass)) +- continue; +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) && +- (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol)) +- continue; +- +- return id; ++ if (usb_match_one_id(interface, id)) ++ return id; + } + + return NULL; +@@ -268,6 +379,9 @@ int usb_device_match(struct device *dev, + if (id) + return 1; + ++ id = usb_match_dynamic_id(intf, usb_drv); ++ if (id) ++ return 1; + return 0; + } + +@@ -296,6 +410,8 @@ int usb_register(struct usb_driver *new_ + new_driver->driver.probe = usb_probe_interface; + new_driver->driver.remove = usb_unbind_interface; + new_driver->driver.owner = new_driver->owner; ++ spin_lock_init(&new_driver->dynids.lock); ++ INIT_LIST_HEAD(&new_driver->dynids.list); + + usb_lock_all_devices(); + retval = driver_register(&new_driver->driver); +@@ -305,6 +421,7 @@ int usb_register(struct usb_driver *new_ + pr_info("%s: registered new driver %s\n", + usbcore_name, new_driver->name); + usbfs_update_special(); ++ usb_create_newid_file(new_driver); + } else { + printk(KERN_ERR "%s: error %d registering driver %s\n", + usbcore_name, retval, new_driver->name); +@@ -330,6 +447,7 @@ void usb_deregister(struct usb_driver *d + pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name); + + usb_lock_all_devices(); ++ usb_free_dynids(driver); + driver_unregister(&driver->driver); + usb_unlock_all_devices(); + +--- gregkh-2.6.orig/include/linux/usb.h ++++ gregkh-2.6/include/linux/usb.h +@@ -528,6 +528,11 @@ static inline int usb_make_path (struct + + /* ----------------------------------------------------------------------- */ + ++struct usb_dynids { ++ spinlock_t lock; ++ struct list_head list; ++}; ++ + /** + * struct usb_driver - identifies USB driver to usbcore + * @owner: Pointer to the module owner of this driver; initialize +@@ -552,6 +557,8 @@ static inline int usb_make_path (struct + * @id_table: USB drivers use ID table to support hotplugging. + * Export this with MODULE_DEVICE_TABLE(usb,...). This must be set + * or your driver's probe function will never get called. ++ * @dynids: used internally to hold the list of dynamically added device ++ * ids for this driver. + * @driver: the driver model core driver structure. + * + * USB drivers must provide a name, probe() and disconnect() methods, +@@ -587,6 +594,7 @@ struct usb_driver { + + const struct usb_device_id *id_table; + ++ struct usb_dynids dynids; + struct device_driver driver; + }; + #define to_usb_driver(d) container_of(d, struct usb_driver, driver) |