aboutsummaryrefslogtreecommitdiffstats
path: root/usb
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2005-12-23 09:51:04 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2005-12-23 09:51:04 -0800
commitc0daf3a9bc6b3aaa611df9f6370fa493937fdf09 (patch)
tree9eb1812e99011e1fc66aea19d11873c53fa7cfac /usb
parentd0e4f6d13b33c4e463a4fb91cfecc4d87fa48c94 (diff)
downloadpatches-c0daf3a9bc6b3aaa611df9f6370fa493937fdf09.tar.gz
make usb-serial-dynamic id a real patch
Diffstat (limited to 'usb')
-rw-r--r--usb/usb-serial-dynamic-id.patch336
1 files changed, 336 insertions, 0 deletions
diff --git a/usb/usb-serial-dynamic-id.patch b/usb/usb-serial-dynamic-id.patch
new file mode 100644
index 0000000000000..fcb1036b6b631
--- /dev/null
+++ b/usb/usb-serial-dynamic-id.patch
@@ -0,0 +1,336 @@
+From foo@baz.org Thu Dec 15 13:04:03 2005
+Date: Thu, 15 Dec 2005 12:58:42 -0800
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Subject: USB serial: add dynamic id support to usb-serial core
+
+This adds support for dynamic usb ids to the usb serial core. The file
+"new_id" will show up under the usb serial driver, not the usb driver
+associated with the usb-serial driver (yeah, it can be a bit confusing
+at first glance...)
+
+This patch also modifies the USB core to allow the usb-serial core to
+reuse much of the dynamic id logic.
+
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+ drivers/usb/core/driver.c | 37 ++++++++++++++++--------------
+ drivers/usb/serial/bus.c | 49 ++++++++++++++++++++++++++++++++++++++++
+ drivers/usb/serial/pl2303.c | 4 +--
+ drivers/usb/serial/usb-serial.c | 43 ++++++++++++++++++++++++++++++-----
+ drivers/usb/serial/usb-serial.h | 2 +
+ include/linux/usb.h | 13 ++++++++++
+ 6 files changed, 123 insertions(+), 25 deletions(-)
+
+---
+--- gregkh-2.6.orig/drivers/usb/core/driver.c
++++ gregkh-2.6/drivers/usb/core/driver.c
+@@ -27,15 +27,6 @@
+ #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;
+@@ -73,10 +64,10 @@ int usb_generic_driver_data;
+ * 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)
++ssize_t usb_store_new_id(struct usb_dynids *dynids,
++ 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;
+@@ -85,6 +76,7 @@ static ssize_t store_new_id(struct devic
+ fields = sscanf(buf, "%x %x", &idVendor, &idProduct);
+ if (fields < 2)
+ return -EINVAL;
++ printk("GREG: idVendor=%x idProduct=%x\n", idVendor, idProduct);
+
+ dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
+ if (!dynid)
+@@ -95,9 +87,9 @@ static ssize_t store_new_id(struct devic
+ 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);
++ spin_lock(&dynids->lock);
++ list_add_tail(&dynids->list, &dynid->node);
++ spin_unlock(&dynids->lock);
+
+ if (get_driver(driver)) {
+ driver_attach(driver);
+@@ -106,6 +98,15 @@ static ssize_t store_new_id(struct devic
+
+ return count;
+ }
++EXPORT_SYMBOL_GPL(usb_store_new_id);
++
++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);
++
++ return usb_store_new_id(&usb_drv->dynids, driver, buf, count);
++}
+ static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
+
+ static int usb_create_newid_file(struct usb_driver *usb_drv)
+@@ -240,8 +241,8 @@ static int usb_unbind_interface(struct d
+ }
+
+ /* returns 0 if no match, 1 if match */
+-static int usb_match_one_id(struct usb_interface *interface,
+- const struct usb_device_id *id)
++int usb_match_one_id(struct usb_interface *interface,
++ const struct usb_device_id *id)
+ {
+ struct usb_host_interface *intf;
+ struct usb_device *dev;
+@@ -297,6 +298,8 @@ static int usb_match_one_id(struct usb_i
+
+ return 1;
+ }
++EXPORT_SYMBOL(usb_match_one_id);
++
+ /**
+ * usb_match_id - find first usb_device_id matching device or interface
+ * @interface: the interface of interest
+--- gregkh-2.6.orig/include/linux/usb.h
++++ gregkh-2.6/include/linux/usb.h
+@@ -417,6 +417,8 @@ extern void usb_driver_release_interface
+ struct usb_interface *iface);
+ const struct usb_device_id *usb_match_id(struct usb_interface *interface,
+ const struct usb_device_id *id);
++extern int usb_match_one_id(struct usb_interface *interface,
++ const struct usb_device_id *id);
+
+ extern struct usb_interface *usb_find_interface(struct usb_driver *drv,
+ int minor);
+@@ -531,11 +533,21 @@ static inline int usb_make_path (struct
+
+ /* ----------------------------------------------------------------------- */
+
++/* Stuff for dynamic usb ids */
+ struct usb_dynids {
+ spinlock_t lock;
+ struct list_head list;
+ };
+
++struct usb_dynid {
++ struct list_head node;
++ struct usb_device_id id;
++};
++
++extern ssize_t usb_store_new_id(struct usb_dynids *dynids,
++ struct device_driver *driver,
++ const char *buf, size_t count);
++
+ /**
+ * struct usb_driver - identifies USB driver to usbcore
+ * @name: The driver name should be unique among USB drivers,
+@@ -1190,6 +1202,7 @@ usb_maxpacket(struct usb_device *udev, i
+ extern void usb_register_notify(struct notifier_block *nb);
+ extern void usb_unregister_notify(struct notifier_block *nb);
+
++
+ #ifdef DEBUG
+ #define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , \
+ __FILE__ , ## arg)
+--- gregkh-2.6.orig/drivers/usb/serial/usb-serial.h
++++ gregkh-2.6/drivers/usb/serial/usb-serial.h
+@@ -203,6 +203,7 @@ struct usb_serial_driver {
+
+ struct list_head driver_list;
+ struct device_driver driver;
++ struct usb_dynids dynids;
+
+ int (*probe) (struct usb_serial *serial, const struct usb_device_id *id);
+ int (*attach) (struct usb_serial *serial);
+@@ -270,6 +271,7 @@ extern int usb_serial_bus_register (stru
+ extern void usb_serial_bus_deregister (struct usb_serial_driver *device);
+
+ extern struct usb_serial_driver usb_serial_generic_device;
++extern struct usb_driver usb_serial_driver;
+ extern struct bus_type usb_serial_bus_type;
+ extern struct tty_driver *usb_serial_tty_driver;
+
+--- gregkh-2.6.orig/drivers/usb/serial/bus.c
++++ gregkh-2.6/drivers/usb/serial/bus.c
+@@ -37,9 +37,55 @@ static int usb_serial_device_match (stru
+ return 0;
+ }
+
++#ifdef CONFIG_HOTPLUG
++static ssize_t store_new_id(struct device_driver *driver,
++ const char *buf, size_t count)
++{
++ struct usb_serial_driver *usb_drv = to_usb_serial_driver(driver);
++ ssize_t retval = usb_store_new_id(&usb_drv->dynids, driver, buf, count);
++
++ if (retval >= 0) {
++ /* kick the usb-serial main driver */
++ struct device_driver *driver = &usb_serial_driver.driver;
++ if (get_driver(driver)) {
++ driver_attach(driver);
++ put_driver(driver);
++ }
++ }
++ return retval;
++}
++
++static struct driver_attribute drv_attrs[] = {
++ __ATTR(new_id, S_IWUSR, NULL, store_new_id),
++ __ATTR_NULL,
++};
++
++static void free_dynids(struct usb_serial_driver *drv)
++{
++ struct usb_dynid *dynid, *n;
++
++ printk("GREG: %s\n", __FUNCTION__);
++ spin_lock(&drv->dynids.lock);
++ list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) {
++ list_del(&dynid->node);
++ kfree(dynid);
++ }
++ spin_unlock(&drv->dynids.lock);
++}
++
++#else
++static struct driver_attribute drv_attrs[] = {
++ __ATTR_NULL,
++};
++static inline void free_dynids(struct usb_driver *drv)
++{
++}
++#endif
++
+ struct bus_type usb_serial_bus_type = {
+ .name = "usb-serial",
+ .match = usb_serial_device_match,
++ .drv_attrs = drv_attrs,
+ };
+
+ static int usb_serial_device_probe (struct device *dev)
+@@ -116,6 +162,8 @@ int usb_serial_bus_register(struct usb_s
+ driver->driver.bus = &usb_serial_bus_type;
+ driver->driver.probe = usb_serial_device_probe;
+ driver->driver.remove = usb_serial_device_remove;
++ spin_lock_init(&driver->dynids.lock);
++ INIT_LIST_HEAD(&driver->dynids.list);
+
+ retval = driver_register(&driver->driver);
+
+@@ -124,6 +172,7 @@ int usb_serial_bus_register(struct usb_s
+
+ void usb_serial_bus_deregister(struct usb_serial_driver *driver)
+ {
++ free_dynids(driver);
+ driver_unregister(&driver->driver);
+ }
+
+--- gregkh-2.6.orig/drivers/usb/serial/usb-serial.c
++++ gregkh-2.6/drivers/usb/serial/usb-serial.c
+@@ -42,7 +42,7 @@
+ #define DRIVER_DESC "USB Serial Driver core"
+
+ /* Driver structure we register with the USB core */
+-static struct usb_driver usb_serial_driver = {
++struct usb_driver usb_serial_driver = {
+ .name = "usbserial",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+@@ -578,6 +578,39 @@ static struct usb_serial * create_serial
+ return serial;
+ }
+
++static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
++ struct usb_serial_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;
++}
++
++static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
++ struct usb_interface *intf)
++{
++ const struct usb_device_id *id;
++
++ id = usb_match_id(intf, drv->id_table);
++ if (id) {
++ dbg("static descriptor matches");
++ goto exit;
++ }
++ id = match_dynamic_id(intf, drv);
++ if (id)
++ dbg("dynamic descriptor matches");
++exit:
++ return id;
++}
++
+ static struct usb_serial_driver *search_serial_device(struct usb_interface *iface)
+ {
+ struct list_head *p;
+@@ -587,11 +620,9 @@ static struct usb_serial_driver *search_
+ /* 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_driver, driver_list);
+- id = usb_match_id(iface, t->id_table);
+- if (id != NULL) {
+- dbg("descriptor matches");
++ id = get_iface_id(t, iface);
++ if (id)
+ return t;
+- }
+ }
+
+ return NULL;
+@@ -643,7 +674,7 @@ int usb_serial_probe(struct usb_interfac
+ return -EIO;
+ }
+
+- id = usb_match_id(interface, type->id_table);
++ id = get_iface_id(type, interface);
+ retval = type->probe(serial, id);
+ module_put(type->driver.owner);
+
+--- gregkh-2.6.orig/drivers/usb/serial/pl2303.c
++++ gregkh-2.6/drivers/usb/serial/pl2303.c
+@@ -58,8 +58,8 @@ static struct usb_device_id id_table []
+ { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) },
+ { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) },
+ { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
+- { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
+- { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) },
++// { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
++// { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) },
+ { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) },
+ { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT) },
+ { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) },