diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2006-07-01 22:08:49 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-09-27 14:58:50 -0400 |
commit | 8bb54ab573ecd1b4fe2ed66416a8d99a86e65316 (patch) | |
tree | 36df75387a62923e3bd152f3c2ce16147be1828c | |
parent | 36e56a34586783c7986ce09d39db80b27c95ce24 (diff) |
usbcore: add usb_device_driver definition
This patch (as732) adds a usb_device_driver structure, for representing
drivers that manage an entire USB device as opposed to just an
interface. Support routines like usb_register_device_driver,
usb_deregister_device_driver, usb_probe_device, and usb_unbind_device
are also added.
Unlike an earlier version of this patch, the new code is type-safe. To
accomplish this, the existing struct driver embedded in struct
usb_driver had to be wrapped in an intermediate wrapper. This enables
the core to tell at runtime whether a particular struct driver belongs
to a device driver or to an interface driver.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/usb/core/driver.c | 219 | ||||
-rw-r--r-- | drivers/usb/core/generic.c | 17 | ||||
-rw-r--r-- | drivers/usb/core/usb.c | 15 | ||||
-rw-r--r-- | drivers/usb/core/usb.h | 20 | ||||
-rw-r--r-- | include/linux/usb.h | 58 |
5 files changed, 245 insertions, 84 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 8dcf2cd0c569..0d4b5dcee3ab 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -84,7 +84,7 @@ static int usb_create_newid_file(struct usb_driver *usb_drv) | |||
84 | goto exit; | 84 | goto exit; |
85 | 85 | ||
86 | if (usb_drv->probe != NULL) | 86 | if (usb_drv->probe != NULL) |
87 | error = sysfs_create_file(&usb_drv->driver.kobj, | 87 | error = sysfs_create_file(&usb_drv->drvwrap.driver.kobj, |
88 | &driver_attr_new_id.attr); | 88 | &driver_attr_new_id.attr); |
89 | exit: | 89 | exit: |
90 | return error; | 90 | return error; |
@@ -96,7 +96,7 @@ static void usb_remove_newid_file(struct usb_driver *usb_drv) | |||
96 | return; | 96 | return; |
97 | 97 | ||
98 | if (usb_drv->probe != NULL) | 98 | if (usb_drv->probe != NULL) |
99 | sysfs_remove_file(&usb_drv->driver.kobj, | 99 | sysfs_remove_file(&usb_drv->drvwrap.driver.kobj, |
100 | &driver_attr_new_id.attr); | 100 | &driver_attr_new_id.attr); |
101 | } | 101 | } |
102 | 102 | ||
@@ -143,18 +143,55 @@ static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *in | |||
143 | } | 143 | } |
144 | 144 | ||
145 | 145 | ||
146 | /* called from driver core with usb_bus_type.subsys writelock */ | 146 | /* called from driver core with dev locked */ |
147 | static int usb_probe_device(struct device *dev) | ||
148 | { | ||
149 | struct usb_device_driver *udriver = to_usb_device_driver(dev->driver); | ||
150 | struct usb_device *udev; | ||
151 | int error = -ENODEV; | ||
152 | |||
153 | dev_dbg(dev, "%s\n", __FUNCTION__); | ||
154 | |||
155 | if (!is_usb_device(dev)) /* Sanity check */ | ||
156 | return error; | ||
157 | |||
158 | udev = to_usb_device(dev); | ||
159 | |||
160 | /* FIXME: resume a suspended device */ | ||
161 | if (udev->state == USB_STATE_SUSPENDED) | ||
162 | return -EHOSTUNREACH; | ||
163 | |||
164 | /* TODO: Add real matching code */ | ||
165 | |||
166 | error = udriver->probe(udev); | ||
167 | return error; | ||
168 | } | ||
169 | |||
170 | /* called from driver core with dev locked */ | ||
171 | static int usb_unbind_device(struct device *dev) | ||
172 | { | ||
173 | struct usb_device_driver *udriver = to_usb_device_driver(dev->driver); | ||
174 | |||
175 | udriver->disconnect(to_usb_device(dev)); | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | |||
180 | /* called from driver core with dev locked */ | ||
147 | static int usb_probe_interface(struct device *dev) | 181 | static int usb_probe_interface(struct device *dev) |
148 | { | 182 | { |
149 | struct usb_interface * intf = to_usb_interface(dev); | 183 | struct usb_driver *driver = to_usb_driver(dev->driver); |
150 | struct usb_driver * driver = to_usb_driver(dev->driver); | 184 | struct usb_interface *intf; |
151 | const struct usb_device_id *id; | 185 | const struct usb_device_id *id; |
152 | int error = -ENODEV; | 186 | int error = -ENODEV; |
153 | 187 | ||
154 | dev_dbg(dev, "%s\n", __FUNCTION__); | 188 | dev_dbg(dev, "%s\n", __FUNCTION__); |
155 | 189 | ||
156 | if (!driver->probe) | 190 | if (is_usb_device(dev)) /* Sanity check */ |
157 | return error; | 191 | return error; |
192 | |||
193 | intf = to_usb_interface(dev); | ||
194 | |||
158 | /* FIXME we'd much prefer to just resume it ... */ | 195 | /* FIXME we'd much prefer to just resume it ... */ |
159 | if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED) | 196 | if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED) |
160 | return -EHOSTUNREACH; | 197 | return -EHOSTUNREACH; |
@@ -182,19 +219,18 @@ static int usb_probe_interface(struct device *dev) | |||
182 | return error; | 219 | return error; |
183 | } | 220 | } |
184 | 221 | ||
185 | /* called from driver core with usb_bus_type.subsys writelock */ | 222 | /* called from driver core with dev locked */ |
186 | static int usb_unbind_interface(struct device *dev) | 223 | static int usb_unbind_interface(struct device *dev) |
187 | { | 224 | { |
225 | struct usb_driver *driver = to_usb_driver(dev->driver); | ||
188 | struct usb_interface *intf = to_usb_interface(dev); | 226 | struct usb_interface *intf = to_usb_interface(dev); |
189 | struct usb_driver *driver = to_usb_driver(intf->dev.driver); | ||
190 | 227 | ||
191 | intf->condition = USB_INTERFACE_UNBINDING; | 228 | intf->condition = USB_INTERFACE_UNBINDING; |
192 | 229 | ||
193 | /* release all urbs for this interface */ | 230 | /* release all urbs for this interface */ |
194 | usb_disable_interface(interface_to_usbdev(intf), intf); | 231 | usb_disable_interface(interface_to_usbdev(intf), intf); |
195 | 232 | ||
196 | if (driver && driver->disconnect) | 233 | driver->disconnect(intf); |
197 | driver->disconnect(intf); | ||
198 | 234 | ||
199 | /* reset other interface state */ | 235 | /* reset other interface state */ |
200 | usb_set_interface(interface_to_usbdev(intf), | 236 | usb_set_interface(interface_to_usbdev(intf), |
@@ -235,7 +271,7 @@ int usb_driver_claim_interface(struct usb_driver *driver, | |||
235 | if (dev->driver) | 271 | if (dev->driver) |
236 | return -EBUSY; | 272 | return -EBUSY; |
237 | 273 | ||
238 | dev->driver = &driver->driver; | 274 | dev->driver = &driver->drvwrap.driver; |
239 | usb_set_intfdata(iface, priv); | 275 | usb_set_intfdata(iface, priv); |
240 | iface->condition = USB_INTERFACE_BOUND; | 276 | iface->condition = USB_INTERFACE_BOUND; |
241 | mark_active(iface); | 277 | mark_active(iface); |
@@ -270,7 +306,7 @@ void usb_driver_release_interface(struct usb_driver *driver, | |||
270 | struct device *dev = &iface->dev; | 306 | struct device *dev = &iface->dev; |
271 | 307 | ||
272 | /* this should never happen, don't release something that's not ours */ | 308 | /* this should never happen, don't release something that's not ours */ |
273 | if (!dev->driver || dev->driver != &driver->driver) | 309 | if (!dev->driver || dev->driver != &driver->drvwrap.driver) |
274 | return; | 310 | return; |
275 | 311 | ||
276 | /* don't release from within disconnect() */ | 312 | /* don't release from within disconnect() */ |
@@ -433,24 +469,37 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_match_id); | |||
433 | 469 | ||
434 | int usb_device_match(struct device *dev, struct device_driver *drv) | 470 | int usb_device_match(struct device *dev, struct device_driver *drv) |
435 | { | 471 | { |
436 | struct usb_interface *intf; | 472 | /* devices and interfaces are handled separately */ |
437 | struct usb_driver *usb_drv; | 473 | if (is_usb_device(dev)) { |
438 | const struct usb_device_id *id; | ||
439 | |||
440 | /* check for generic driver, which we don't match any device with */ | ||
441 | if (drv == &usb_generic_driver) | ||
442 | return 0; | ||
443 | 474 | ||
444 | intf = to_usb_interface(dev); | 475 | /* interface drivers never match devices */ |
445 | usb_drv = to_usb_driver(drv); | 476 | if (!is_usb_device_driver(drv)) |
477 | return 0; | ||
446 | 478 | ||
447 | id = usb_match_id(intf, usb_drv->id_table); | 479 | /* TODO: Add real matching code */ |
448 | if (id) | ||
449 | return 1; | 480 | return 1; |
450 | 481 | ||
451 | id = usb_match_dynamic_id(intf, usb_drv); | 482 | } else { |
452 | if (id) | 483 | struct usb_interface *intf; |
453 | return 1; | 484 | struct usb_driver *usb_drv; |
485 | const struct usb_device_id *id; | ||
486 | |||
487 | /* device drivers never match interfaces */ | ||
488 | if (is_usb_device_driver(drv)) | ||
489 | return 0; | ||
490 | |||
491 | intf = to_usb_interface(dev); | ||
492 | usb_drv = to_usb_driver(drv); | ||
493 | |||
494 | id = usb_match_id(intf, usb_drv->id_table); | ||
495 | if (id) | ||
496 | return 1; | ||
497 | |||
498 | id = usb_match_dynamic_id(intf, usb_drv); | ||
499 | if (id) | ||
500 | return 1; | ||
501 | } | ||
502 | |||
454 | return 0; | 503 | return 0; |
455 | } | 504 | } |
456 | 505 | ||
@@ -481,14 +530,13 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp, | |||
481 | /* driver is often null here; dev_dbg() would oops */ | 530 | /* driver is often null here; dev_dbg() would oops */ |
482 | pr_debug ("usb %s: uevent\n", dev->bus_id); | 531 | pr_debug ("usb %s: uevent\n", dev->bus_id); |
483 | 532 | ||
484 | /* Must check driver_data here, as on remove driver is always NULL */ | 533 | if (is_usb_device(dev)) |
485 | if ((dev->driver == &usb_generic_driver) || | ||
486 | (dev->driver_data == &usb_generic_driver_data)) | ||
487 | return 0; | 534 | return 0; |
488 | 535 | else { | |
489 | intf = to_usb_interface(dev); | 536 | intf = to_usb_interface(dev); |
490 | usb_dev = interface_to_usbdev (intf); | 537 | usb_dev = interface_to_usbdev(intf); |
491 | alt = intf->cur_altsetting; | 538 | alt = intf->cur_altsetting; |
539 | } | ||
492 | 540 | ||
493 | if (usb_dev->devnum < 0) { | 541 | if (usb_dev->devnum < 0) { |
494 | pr_debug ("usb %s: already deleted?\n", dev->bus_id); | 542 | pr_debug ("usb %s: already deleted?\n", dev->bus_id); |
@@ -569,13 +617,71 @@ static int usb_uevent(struct device *dev, char **envp, | |||
569 | #endif /* CONFIG_HOTPLUG */ | 617 | #endif /* CONFIG_HOTPLUG */ |
570 | 618 | ||
571 | /** | 619 | /** |
572 | * usb_register_driver - register a USB driver | 620 | * usb_register_device_driver - register a USB device (not interface) driver |
573 | * @new_driver: USB operations for the driver | 621 | * @new_udriver: USB operations for the device driver |
574 | * @owner: module owner of this driver. | 622 | * @owner: module owner of this driver. |
575 | * | 623 | * |
576 | * Registers a USB driver with the USB core. The list of unattached | 624 | * Registers a USB device driver with the USB core. The list of |
577 | * interfaces will be rescanned whenever a new driver is added, allowing | 625 | * unattached devices will be rescanned whenever a new driver is |
578 | * the new driver to attach to any recognized devices. | 626 | * added, allowing the new driver to attach to any recognized devices. |
627 | * Returns a negative error code on failure and 0 on success. | ||
628 | */ | ||
629 | int usb_register_device_driver(struct usb_device_driver *new_udriver, | ||
630 | struct module *owner) | ||
631 | { | ||
632 | int retval = 0; | ||
633 | |||
634 | if (usb_disabled()) | ||
635 | return -ENODEV; | ||
636 | |||
637 | new_udriver->drvwrap.for_devices = 1; | ||
638 | new_udriver->drvwrap.driver.name = (char *) new_udriver->name; | ||
639 | new_udriver->drvwrap.driver.bus = &usb_bus_type; | ||
640 | new_udriver->drvwrap.driver.probe = usb_probe_device; | ||
641 | new_udriver->drvwrap.driver.remove = usb_unbind_device; | ||
642 | new_udriver->drvwrap.driver.owner = owner; | ||
643 | |||
644 | retval = driver_register(&new_udriver->drvwrap.driver); | ||
645 | |||
646 | if (!retval) { | ||
647 | pr_info("%s: registered new device driver %s\n", | ||
648 | usbcore_name, new_udriver->name); | ||
649 | usbfs_update_special(); | ||
650 | } else { | ||
651 | printk(KERN_ERR "%s: error %d registering device " | ||
652 | " driver %s\n", | ||
653 | usbcore_name, retval, new_udriver->name); | ||
654 | } | ||
655 | |||
656 | return retval; | ||
657 | } | ||
658 | EXPORT_SYMBOL_GPL(usb_register_device_driver); | ||
659 | |||
660 | /** | ||
661 | * usb_deregister_device_driver - unregister a USB device (not interface) driver | ||
662 | * @udriver: USB operations of the device driver to unregister | ||
663 | * Context: must be able to sleep | ||
664 | * | ||
665 | * Unlinks the specified driver from the internal USB driver list. | ||
666 | */ | ||
667 | void usb_deregister_device_driver(struct usb_device_driver *udriver) | ||
668 | { | ||
669 | pr_info("%s: deregistering device driver %s\n", | ||
670 | usbcore_name, udriver->name); | ||
671 | |||
672 | driver_unregister(&udriver->drvwrap.driver); | ||
673 | usbfs_update_special(); | ||
674 | } | ||
675 | EXPORT_SYMBOL_GPL(usb_deregister_device_driver); | ||
676 | |||
677 | /** | ||
678 | * usb_register_driver - register a USB interface driver | ||
679 | * @new_driver: USB operations for the interface driver | ||
680 | * @owner: module owner of this driver. | ||
681 | * | ||
682 | * Registers a USB interface driver with the USB core. The list of | ||
683 | * unattached interfaces will be rescanned whenever a new driver is | ||
684 | * added, allowing the new driver to attach to any recognized interfaces. | ||
579 | * Returns a negative error code on failure and 0 on success. | 685 | * Returns a negative error code on failure and 0 on success. |
580 | * | 686 | * |
581 | * NOTE: if you want your driver to use the USB major number, you must call | 687 | * NOTE: if you want your driver to use the USB major number, you must call |
@@ -589,23 +695,25 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner) | |||
589 | if (usb_disabled()) | 695 | if (usb_disabled()) |
590 | return -ENODEV; | 696 | return -ENODEV; |
591 | 697 | ||
592 | new_driver->driver.name = (char *)new_driver->name; | 698 | new_driver->drvwrap.for_devices = 0; |
593 | new_driver->driver.bus = &usb_bus_type; | 699 | new_driver->drvwrap.driver.name = (char *) new_driver->name; |
594 | new_driver->driver.probe = usb_probe_interface; | 700 | new_driver->drvwrap.driver.bus = &usb_bus_type; |
595 | new_driver->driver.remove = usb_unbind_interface; | 701 | new_driver->drvwrap.driver.probe = usb_probe_interface; |
596 | new_driver->driver.owner = owner; | 702 | new_driver->drvwrap.driver.remove = usb_unbind_interface; |
703 | new_driver->drvwrap.driver.owner = owner; | ||
597 | spin_lock_init(&new_driver->dynids.lock); | 704 | spin_lock_init(&new_driver->dynids.lock); |
598 | INIT_LIST_HEAD(&new_driver->dynids.list); | 705 | INIT_LIST_HEAD(&new_driver->dynids.list); |
599 | 706 | ||
600 | retval = driver_register(&new_driver->driver); | 707 | retval = driver_register(&new_driver->drvwrap.driver); |
601 | 708 | ||
602 | if (!retval) { | 709 | if (!retval) { |
603 | pr_info("%s: registered new driver %s\n", | 710 | pr_info("%s: registered new interface driver %s\n", |
604 | usbcore_name, new_driver->name); | 711 | usbcore_name, new_driver->name); |
605 | usbfs_update_special(); | 712 | usbfs_update_special(); |
606 | usb_create_newid_file(new_driver); | 713 | usb_create_newid_file(new_driver); |
607 | } else { | 714 | } else { |
608 | printk(KERN_ERR "%s: error %d registering driver %s\n", | 715 | printk(KERN_ERR "%s: error %d registering interface " |
716 | " driver %s\n", | ||
609 | usbcore_name, retval, new_driver->name); | 717 | usbcore_name, retval, new_driver->name); |
610 | } | 718 | } |
611 | 719 | ||
@@ -614,8 +722,8 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner) | |||
614 | EXPORT_SYMBOL_GPL_FUTURE(usb_register_driver); | 722 | EXPORT_SYMBOL_GPL_FUTURE(usb_register_driver); |
615 | 723 | ||
616 | /** | 724 | /** |
617 | * usb_deregister - unregister a USB driver | 725 | * usb_deregister - unregister a USB interface driver |
618 | * @driver: USB operations of the driver to unregister | 726 | * @driver: USB operations of the interface driver to unregister |
619 | * Context: must be able to sleep | 727 | * Context: must be able to sleep |
620 | * | 728 | * |
621 | * Unlinks the specified driver from the internal USB driver list. | 729 | * Unlinks the specified driver from the internal USB driver list. |
@@ -626,11 +734,12 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_register_driver); | |||
626 | */ | 734 | */ |
627 | void usb_deregister(struct usb_driver *driver) | 735 | void usb_deregister(struct usb_driver *driver) |
628 | { | 736 | { |
629 | pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name); | 737 | pr_info("%s: deregistering interface driver %s\n", |
738 | usbcore_name, driver->name); | ||
630 | 739 | ||
631 | usb_remove_newid_file(driver); | 740 | usb_remove_newid_file(driver); |
632 | usb_free_dynids(driver); | 741 | usb_free_dynids(driver); |
633 | driver_unregister(&driver->driver); | 742 | driver_unregister(&driver->drvwrap.driver); |
634 | 743 | ||
635 | usbfs_update_special(); | 744 | usbfs_update_special(); |
636 | } | 745 | } |
@@ -655,7 +764,7 @@ static int usb_generic_suspend(struct device *dev, pm_message_t message) | |||
655 | * marked for FREEZE as soon as their children are already idled. | 764 | * marked for FREEZE as soon as their children are already idled. |
656 | * But those semantics are useless, so we equate the two (sigh). | 765 | * But those semantics are useless, so we equate the two (sigh). |
657 | */ | 766 | */ |
658 | if (dev->driver == &usb_generic_driver) { | 767 | if (is_usb_device(dev)) { |
659 | if (dev->power.power_state.event == message.event) | 768 | if (dev->power.power_state.event == message.event) |
660 | return 0; | 769 | return 0; |
661 | /* we need to rule out bogus requests through sysfs */ | 770 | /* we need to rule out bogus requests through sysfs */ |
@@ -665,8 +774,7 @@ static int usb_generic_suspend(struct device *dev, pm_message_t message) | |||
665 | return usb_port_suspend(to_usb_device(dev)); | 774 | return usb_port_suspend(to_usb_device(dev)); |
666 | } | 775 | } |
667 | 776 | ||
668 | if ((dev->driver == NULL) || | 777 | if (dev->driver == NULL) |
669 | (dev->driver_data == &usb_generic_driver_data)) | ||
670 | return 0; | 778 | return 0; |
671 | 779 | ||
672 | intf = to_usb_interface(dev); | 780 | intf = to_usb_interface(dev); |
@@ -705,15 +813,14 @@ static int usb_generic_resume(struct device *dev) | |||
705 | dev->power.power_state.event = PM_EVENT_ON; | 813 | dev->power.power_state.event = PM_EVENT_ON; |
706 | 814 | ||
707 | /* devices resume through their hubs */ | 815 | /* devices resume through their hubs */ |
708 | if (dev->driver == &usb_generic_driver) { | 816 | if (is_usb_device(dev)) { |
709 | udev = to_usb_device(dev); | 817 | udev = to_usb_device(dev); |
710 | if (udev->state == USB_STATE_NOTATTACHED) | 818 | if (udev->state == USB_STATE_NOTATTACHED) |
711 | return 0; | 819 | return 0; |
712 | return usb_port_resume(udev); | 820 | return usb_port_resume(udev); |
713 | } | 821 | } |
714 | 822 | ||
715 | if ((dev->driver == NULL) || | 823 | if (dev->driver == NULL) { |
716 | (dev->driver_data == &usb_generic_driver_data)) { | ||
717 | dev->power.power_state.event = PM_EVENT_FREEZE; | 824 | dev->power.power_state.event = PM_EVENT_FREEZE; |
718 | return 0; | 825 | return 0; |
719 | } | 826 | } |
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index 7bab9769b34f..fa6f34a12b4b 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c | |||
@@ -21,14 +21,12 @@ | |||
21 | #include <linux/usb.h> | 21 | #include <linux/usb.h> |
22 | #include "usb.h" | 22 | #include "usb.h" |
23 | 23 | ||
24 | static int generic_probe(struct device *dev) | 24 | static int generic_probe(struct usb_device *udev) |
25 | { | 25 | { |
26 | return 0; | 26 | return 0; |
27 | } | 27 | } |
28 | static int generic_remove(struct device *dev) | 28 | static void generic_disconnect(struct usb_device *udev) |
29 | { | 29 | { |
30 | struct usb_device *udev = to_usb_device(dev); | ||
31 | |||
32 | /* if this is only an unbind, not a physical disconnect, then | 30 | /* if this is only an unbind, not a physical disconnect, then |
33 | * unconfigure the device */ | 31 | * unconfigure the device */ |
34 | if (udev->state == USB_STATE_CONFIGURED) | 32 | if (udev->state == USB_STATE_CONFIGURED) |
@@ -37,17 +35,10 @@ static int generic_remove(struct device *dev) | |||
37 | /* in case the call failed or the device was suspended */ | 35 | /* in case the call failed or the device was suspended */ |
38 | if (udev->state >= USB_STATE_CONFIGURED) | 36 | if (udev->state >= USB_STATE_CONFIGURED) |
39 | usb_disable_device(udev, 0); | 37 | usb_disable_device(udev, 0); |
40 | return 0; | ||
41 | } | 38 | } |
42 | 39 | ||
43 | struct device_driver usb_generic_driver = { | 40 | struct usb_device_driver usb_generic_driver = { |
44 | .owner = THIS_MODULE, | ||
45 | .name = "usb", | 41 | .name = "usb", |
46 | .bus = &usb_bus_type, | ||
47 | .probe = generic_probe, | 42 | .probe = generic_probe, |
48 | .remove = generic_remove, | 43 | .disconnect = generic_disconnect, |
49 | }; | 44 | }; |
50 | |||
51 | /* Fun hack to determine if the struct device is a | ||
52 | * usb device or a usb interface. */ | ||
53 | int usb_generic_driver_data; | ||
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 0b8c67bcde60..6dfbc284369b 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -123,7 +123,7 @@ static int __find_interface(struct device * dev, void * data) | |||
123 | struct usb_interface *intf; | 123 | struct usb_interface *intf; |
124 | 124 | ||
125 | /* can't look at usb devices, only interfaces */ | 125 | /* can't look at usb devices, only interfaces */ |
126 | if (dev->driver == &usb_generic_driver) | 126 | if (is_usb_device(dev)) |
127 | return 0; | 127 | return 0; |
128 | 128 | ||
129 | intf = to_usb_interface(dev); | 129 | intf = to_usb_interface(dev); |
@@ -149,7 +149,8 @@ struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor) | |||
149 | 149 | ||
150 | argb.minor = minor; | 150 | argb.minor = minor; |
151 | argb.interface = NULL; | 151 | argb.interface = NULL; |
152 | driver_for_each_device(&drv->driver, NULL, &argb, __find_interface); | 152 | driver_for_each_device(&drv->drvwrap.driver, NULL, &argb, |
153 | __find_interface); | ||
153 | return argb.interface; | 154 | return argb.interface; |
154 | } | 155 | } |
155 | 156 | ||
@@ -204,11 +205,13 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) | |||
204 | device_initialize(&dev->dev); | 205 | device_initialize(&dev->dev); |
205 | dev->dev.bus = &usb_bus_type; | 206 | dev->dev.bus = &usb_bus_type; |
206 | dev->dev.dma_mask = bus->controller->dma_mask; | 207 | dev->dev.dma_mask = bus->controller->dma_mask; |
207 | dev->dev.driver_data = &usb_generic_driver_data; | 208 | dev->dev.driver = &usb_generic_driver.drvwrap.driver; |
208 | dev->dev.driver = &usb_generic_driver; | ||
209 | dev->dev.release = usb_release_dev; | 209 | dev->dev.release = usb_release_dev; |
210 | dev->state = USB_STATE_ATTACHED; | 210 | dev->state = USB_STATE_ATTACHED; |
211 | 211 | ||
212 | /* This magic assignment distinguishes devices from interfaces */ | ||
213 | dev->dev.platform_data = &usb_generic_driver; | ||
214 | |||
212 | INIT_LIST_HEAD(&dev->ep0.urb_list); | 215 | INIT_LIST_HEAD(&dev->ep0.urb_list); |
213 | dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE; | 216 | dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE; |
214 | dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT; | 217 | dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT; |
@@ -838,7 +841,7 @@ static int __init usb_init(void) | |||
838 | retval = usb_hub_init(); | 841 | retval = usb_hub_init(); |
839 | if (retval) | 842 | if (retval) |
840 | goto hub_init_failed; | 843 | goto hub_init_failed; |
841 | retval = driver_register(&usb_generic_driver); | 844 | retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE); |
842 | if (!retval) | 845 | if (!retval) |
843 | goto out; | 846 | goto out; |
844 | 847 | ||
@@ -868,7 +871,7 @@ static void __exit usb_exit(void) | |||
868 | if (nousb) | 871 | if (nousb) |
869 | return; | 872 | return; |
870 | 873 | ||
871 | driver_unregister(&usb_generic_driver); | 874 | usb_deregister_device_driver(&usb_generic_driver); |
872 | usb_major_cleanup(); | 875 | usb_major_cleanup(); |
873 | usbfs_cleanup(); | 876 | usbfs_cleanup(); |
874 | usb_deregister(&usbfs_driver); | 877 | usb_deregister(&usbfs_driver); |
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 82d397a6f773..1d25ccac7832 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h | |||
@@ -34,8 +34,24 @@ extern int usb_port_suspend(struct usb_device *dev); | |||
34 | extern int usb_port_resume(struct usb_device *dev); | 34 | extern int usb_port_resume(struct usb_device *dev); |
35 | 35 | ||
36 | extern struct bus_type usb_bus_type; | 36 | extern struct bus_type usb_bus_type; |
37 | extern struct device_driver usb_generic_driver; | 37 | extern struct usb_device_driver usb_generic_driver; |
38 | extern int usb_generic_driver_data; | 38 | |
39 | /* Here's how we tell apart devices and interfaces. Luckily there's | ||
40 | * no such thing as a platform USB device, so we can steal the use | ||
41 | * of the platform_data field. */ | ||
42 | |||
43 | static inline int is_usb_device(struct device *dev) | ||
44 | { | ||
45 | return dev->platform_data == &usb_generic_driver; | ||
46 | } | ||
47 | |||
48 | /* Do the same for device drivers and interface drivers. */ | ||
49 | |||
50 | static inline int is_usb_device_driver(struct device_driver *drv) | ||
51 | { | ||
52 | return container_of(drv, struct usbdrv_wrap, driver)-> | ||
53 | for_devices; | ||
54 | } | ||
39 | 55 | ||
40 | /* Interfaces and their "power state" are owned by usbcore */ | 56 | /* Interfaces and their "power state" are owned by usbcore */ |
41 | 57 | ||
diff --git a/include/linux/usb.h b/include/linux/usb.h index d2bd0c8e0154..b4ccce6d0982 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
@@ -540,7 +540,17 @@ struct usb_dynids { | |||
540 | }; | 540 | }; |
541 | 541 | ||
542 | /** | 542 | /** |
543 | * struct usb_driver - identifies USB driver to usbcore | 543 | * struct usbdrv_wrap - wrapper for driver-model structure |
544 | * @driver: The driver-model core driver structure. | ||
545 | * @for_devices: Non-zero for device drivers, 0 for interface drivers. | ||
546 | */ | ||
547 | struct usbdrv_wrap { | ||
548 | struct device_driver driver; | ||
549 | int for_devices; | ||
550 | }; | ||
551 | |||
552 | /** | ||
553 | * struct usb_driver - identifies USB interface driver to usbcore | ||
544 | * @name: The driver name should be unique among USB drivers, | 554 | * @name: The driver name should be unique among USB drivers, |
545 | * and should normally be the same as the module name. | 555 | * and should normally be the same as the module name. |
546 | * @probe: Called to see if the driver is willing to manage a particular | 556 | * @probe: Called to see if the driver is willing to manage a particular |
@@ -567,12 +577,12 @@ struct usb_dynids { | |||
567 | * or your driver's probe function will never get called. | 577 | * or your driver's probe function will never get called. |
568 | * @dynids: used internally to hold the list of dynamically added device | 578 | * @dynids: used internally to hold the list of dynamically added device |
569 | * ids for this driver. | 579 | * ids for this driver. |
570 | * @driver: the driver model core driver structure. | 580 | * @drvwrap: Driver-model core structure wrapper. |
571 | * @no_dynamic_id: if set to 1, the USB core will not allow dynamic ids to be | 581 | * @no_dynamic_id: if set to 1, the USB core will not allow dynamic ids to be |
572 | * added to this driver by preventing the sysfs file from being created. | 582 | * added to this driver by preventing the sysfs file from being created. |
573 | * | 583 | * |
574 | * USB drivers must provide a name, probe() and disconnect() methods, | 584 | * USB interface drivers must provide a name, probe() and disconnect() |
575 | * and an id_table. Other driver fields are optional. | 585 | * methods, and an id_table. Other driver fields are optional. |
576 | * | 586 | * |
577 | * The id_table is used in hotplugging. It holds a set of descriptors, | 587 | * The id_table is used in hotplugging. It holds a set of descriptors, |
578 | * and specialized data may be associated with each entry. That table | 588 | * and specialized data may be associated with each entry. That table |
@@ -606,10 +616,40 @@ struct usb_driver { | |||
606 | const struct usb_device_id *id_table; | 616 | const struct usb_device_id *id_table; |
607 | 617 | ||
608 | struct usb_dynids dynids; | 618 | struct usb_dynids dynids; |
609 | struct device_driver driver; | 619 | struct usbdrv_wrap drvwrap; |
610 | unsigned int no_dynamic_id:1; | 620 | unsigned int no_dynamic_id:1; |
611 | }; | 621 | }; |
612 | #define to_usb_driver(d) container_of(d, struct usb_driver, driver) | 622 | #define to_usb_driver(d) container_of(d, struct usb_driver, drvwrap.driver) |
623 | |||
624 | /** | ||
625 | * struct usb_device_driver - identifies USB device driver to usbcore | ||
626 | * @name: The driver name should be unique among USB drivers, | ||
627 | * and should normally be the same as the module name. | ||
628 | * @probe: Called to see if the driver is willing to manage a particular | ||
629 | * device. If it is, probe returns zero and uses dev_set_drvdata() | ||
630 | * to associate driver-specific data with the device. If unwilling | ||
631 | * to manage the device, return a negative errno value. | ||
632 | * @disconnect: Called when the device is no longer accessible, usually | ||
633 | * because it has been (or is being) disconnected or the driver's | ||
634 | * module is being unloaded. | ||
635 | * @suspend: Called when the device is going to be suspended by the system. | ||
636 | * @resume: Called when the device is being resumed by the system. | ||
637 | * @drvwrap: Driver-model core structure wrapper. | ||
638 | * | ||
639 | * USB drivers must provide all the fields listed above except drvwrap. | ||
640 | */ | ||
641 | struct usb_device_driver { | ||
642 | const char *name; | ||
643 | |||
644 | int (*probe) (struct usb_device *udev); | ||
645 | void (*disconnect) (struct usb_device *udev); | ||
646 | |||
647 | int (*suspend) (struct usb_device *udev, pm_message_t message); | ||
648 | int (*resume) (struct usb_device *udev); | ||
649 | struct usbdrv_wrap drvwrap; | ||
650 | }; | ||
651 | #define to_usb_device_driver(d) container_of(d, struct usb_device_driver, \ | ||
652 | drvwrap.driver) | ||
613 | 653 | ||
614 | extern struct bus_type usb_bus_type; | 654 | extern struct bus_type usb_bus_type; |
615 | 655 | ||
@@ -633,13 +673,17 @@ struct usb_class_driver { | |||
633 | * use these in module_init()/module_exit() | 673 | * use these in module_init()/module_exit() |
634 | * and don't forget MODULE_DEVICE_TABLE(usb, ...) | 674 | * and don't forget MODULE_DEVICE_TABLE(usb, ...) |
635 | */ | 675 | */ |
636 | int usb_register_driver(struct usb_driver *, struct module *); | 676 | extern int usb_register_driver(struct usb_driver *, struct module *); |
637 | static inline int usb_register(struct usb_driver *driver) | 677 | static inline int usb_register(struct usb_driver *driver) |
638 | { | 678 | { |
639 | return usb_register_driver(driver, THIS_MODULE); | 679 | return usb_register_driver(driver, THIS_MODULE); |
640 | } | 680 | } |
641 | extern void usb_deregister(struct usb_driver *); | 681 | extern void usb_deregister(struct usb_driver *); |
642 | 682 | ||
683 | extern int usb_register_device_driver(struct usb_device_driver *, | ||
684 | struct module *); | ||
685 | extern void usb_deregister_device_driver(struct usb_device_driver *); | ||
686 | |||
643 | extern int usb_register_dev(struct usb_interface *intf, | 687 | extern int usb_register_dev(struct usb_interface *intf, |
644 | struct usb_class_driver *class_driver); | 688 | struct usb_class_driver *class_driver); |
645 | extern void usb_deregister_dev(struct usb_interface *intf, | 689 | extern void usb_deregister_dev(struct usb_interface *intf, |