diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2006-07-01 22:09:35 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-09-27 11:58:50 -0700 |
commit | 782da727b0d59e93c84a627948b1535a3db90392 (patch) | |
tree | 155cfe2df2a57961234c44186890fdcce72a0eb6 /drivers/usb/core/driver.c | |
parent | 8bb54ab573ecd1b4fe2ed66416a8d99a86e65316 (diff) |
usbcore: make usb_generic a usb_device_driver
This patch (as714b) makes usb_generic into a usb_device_driver capable
of being probed and unbound, just like other drivers. A fair amount of
the work that used to get done during discovery or removal of a USB
device have been moved to the probe and disconnect methods of
usb_generic: creating the sysfs attributes and selecting an initial
configuration. However the normal behavior should continue to be the
same as before.
We will now have the possibility of creating other USB device drivers,
They will assist with exporting devices to remote systems
(USB-over-TCPIP) or to paravirtual guest operating systems.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core/driver.c')
-rw-r--r-- | drivers/usb/core/driver.c | 69 |
1 files changed, 34 insertions, 35 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 0d4b5dcee3a..a62de0a8540 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -530,9 +530,10 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp, /* driver is often null here; dev_dbg() would oops */ pr_debug ("usb %s: uevent\n", dev->bus_id); - if (is_usb_device(dev)) - return 0; - else { + if (is_usb_device(dev)) { + usb_dev = to_usb_device(dev); + alt = NULL; + } else { intf = to_usb_interface(dev); usb_dev = interface_to_usbdev(intf); alt = intf->cur_altsetting; @@ -579,15 +580,17 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp, usb_dev->descriptor.bDeviceProtocol)) return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, + if (!is_usb_device(dev)) { + + if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, "INTERFACE=%d/%d/%d", alt->desc.bInterfaceClass, alt->desc.bInterfaceSubClass, alt->desc.bInterfaceProtocol)) - return -ENOMEM; + return -ENOMEM; - if (add_uevent_var(envp, num_envp, &i, + if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", le16_to_cpu(usb_dev->descriptor.idVendor), @@ -599,7 +602,8 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp, alt->desc.bInterfaceClass, alt->desc.bInterfaceSubClass, alt->desc.bInterfaceProtocol)) - return -ENOMEM; + return -ENOMEM; + } envp[i] = NULL; @@ -747,31 +751,22 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_deregister); #ifdef CONFIG_PM -static int verify_suspended(struct device *dev, void *unused) +static int usb_suspend(struct device *dev, pm_message_t message) { - if (dev->driver == NULL) - return 0; - return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0; -} + struct usb_device *udev; + struct usb_device_driver *udriver; + struct usb_interface *intf; + struct usb_driver *driver; + int status; -static int usb_generic_suspend(struct device *dev, pm_message_t message) -{ - struct usb_interface *intf; - struct usb_driver *driver; - int status; - - /* USB devices enter SUSPEND state through their hubs, but can be - * marked for FREEZE as soon as their children are already idled. - * But those semantics are useless, so we equate the two (sigh). - */ if (is_usb_device(dev)) { + if (dev->driver == NULL) + return 0; + udev = to_usb_device(dev); + udriver = to_usb_device_driver(dev->driver); if (dev->power.power_state.event == message.event) return 0; - /* we need to rule out bogus requests through sysfs */ - status = device_for_each_child(dev, NULL, verify_suspended); - if (status) - return status; - return usb_port_suspend(to_usb_device(dev)); + return udriver->suspend(udev, message); } if (dev->driver == NULL) @@ -799,12 +794,13 @@ static int usb_generic_suspend(struct device *dev, pm_message_t message) return status; } -static int usb_generic_resume(struct device *dev) +static int usb_resume(struct device *dev) { - struct usb_interface *intf; - struct usb_driver *driver; - struct usb_device *udev; - int status; + struct usb_device *udev; + struct usb_device_driver *udriver; + struct usb_interface *intf; + struct usb_driver *driver; + int status; if (dev->power.power_state.event == PM_EVENT_ON) return 0; @@ -814,10 +810,13 @@ static int usb_generic_resume(struct device *dev) /* devices resume through their hubs */ if (is_usb_device(dev)) { + if (dev->driver == NULL) + return 0; udev = to_usb_device(dev); + udriver = to_usb_device_driver(dev->driver); if (udev->state == USB_STATE_NOTATTACHED) return 0; - return usb_port_resume(udev); + return udriver->resume(udev); } if (dev->driver == NULL) { @@ -854,7 +853,7 @@ struct bus_type usb_bus_type = { .match = usb_device_match, .uevent = usb_uevent, #ifdef CONFIG_PM - .suspend = usb_generic_suspend, - .resume = usb_generic_resume, + .suspend = usb_suspend, + .resume = usb_resume, #endif }; |