diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2005-12-23 09:51:04 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-12-23 09:51:04 -0800 |
commit | c0daf3a9bc6b3aaa611df9f6370fa493937fdf09 (patch) | |
tree | 9eb1812e99011e1fc66aea19d11873c53fa7cfac /usb | |
parent | d0e4f6d13b33c4e463a4fb91cfecc4d87fa48c94 (diff) | |
download | patches-c0daf3a9bc6b3aaa611df9f6370fa493937fdf09.tar.gz |
make usb-serial-dynamic id a real patch
Diffstat (limited to 'usb')
-rw-r--r-- | usb/usb-serial-dynamic-id.patch | 336 |
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) }, |