diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2006-12-17 15:50:23 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-02-07 18:44:33 -0500 |
commit | 93bacefc4cc0b53e1cb6a336d43847154fdf6886 (patch) | |
tree | 4a82a9d2693d1165c58602a0bf4a8e5c76c541ef /drivers/usb/serial/usb-serial.c | |
parent | 495a678fc62e850d15f860d39faee07ba0a8910c (diff) |
USB serial: add dynamic id support to usb-serial core
Thanks to Johannes Hölzl <johannes.hoelzl@gmx.de> for fixing a few
things and getting it all working properly.
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>
Signed-off-by: Johannes Hölzl <johannes.hoelzl@gmx.de>
Diffstat (limited to 'drivers/usb/serial/usb-serial.c')
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 716f6806cc89..90beb5c50e59 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -596,6 +596,39 @@ static struct usb_serial * create_serial (struct usb_device *dev, | |||
596 | return serial; | 596 | return serial; |
597 | } | 597 | } |
598 | 598 | ||
599 | static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf, | ||
600 | struct usb_serial_driver *drv) | ||
601 | { | ||
602 | struct usb_dynid *dynid; | ||
603 | |||
604 | spin_lock(&drv->dynids.lock); | ||
605 | list_for_each_entry(dynid, &drv->dynids.list, node) { | ||
606 | if (usb_match_one_id(intf, &dynid->id)) { | ||
607 | spin_unlock(&drv->dynids.lock); | ||
608 | return &dynid->id; | ||
609 | } | ||
610 | } | ||
611 | spin_unlock(&drv->dynids.lock); | ||
612 | return NULL; | ||
613 | } | ||
614 | |||
615 | static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv, | ||
616 | struct usb_interface *intf) | ||
617 | { | ||
618 | const struct usb_device_id *id; | ||
619 | |||
620 | id = usb_match_id(intf, drv->id_table); | ||
621 | if (id) { | ||
622 | dbg("static descriptor matches"); | ||
623 | goto exit; | ||
624 | } | ||
625 | id = match_dynamic_id(intf, drv); | ||
626 | if (id) | ||
627 | dbg("dynamic descriptor matches"); | ||
628 | exit: | ||
629 | return id; | ||
630 | } | ||
631 | |||
599 | static struct usb_serial_driver *search_serial_device(struct usb_interface *iface) | 632 | static struct usb_serial_driver *search_serial_device(struct usb_interface *iface) |
600 | { | 633 | { |
601 | struct list_head *p; | 634 | struct list_head *p; |
@@ -605,11 +638,9 @@ static struct usb_serial_driver *search_serial_device(struct usb_interface *ifac | |||
605 | /* Check if the usb id matches a known device */ | 638 | /* Check if the usb id matches a known device */ |
606 | list_for_each(p, &usb_serial_driver_list) { | 639 | list_for_each(p, &usb_serial_driver_list) { |
607 | t = list_entry(p, struct usb_serial_driver, driver_list); | 640 | t = list_entry(p, struct usb_serial_driver, driver_list); |
608 | id = usb_match_id(iface, t->id_table); | 641 | id = get_iface_id(t, iface); |
609 | if (id != NULL) { | 642 | if (id) |
610 | dbg("descriptor matches"); | ||
611 | return t; | 643 | return t; |
612 | } | ||
613 | } | 644 | } |
614 | 645 | ||
615 | return NULL; | 646 | return NULL; |
@@ -661,7 +692,7 @@ int usb_serial_probe(struct usb_interface *interface, | |||
661 | return -EIO; | 692 | return -EIO; |
662 | } | 693 | } |
663 | 694 | ||
664 | id = usb_match_id(interface, type->id_table); | 695 | id = get_iface_id(type, interface); |
665 | retval = type->probe(serial, id); | 696 | retval = type->probe(serial, id); |
666 | module_put(type->driver.owner); | 697 | module_put(type->driver.owner); |
667 | 698 | ||