diff options
author | Kay Sievers <kay.sievers@vrfy.org> | 2007-03-13 15:59:31 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-04-27 13:28:37 -0700 |
commit | 9f8b17e643fe6aa505629658445849397bda4e4f (patch) | |
tree | 30c45914f7be9f355db30964323673c7d37080e8 /drivers/usb/core/driver.c | |
parent | 87840289637e9ea95118ebd76e2e335fdcddd725 (diff) |
USB: make usbdevices export their device nodes instead of using a separate class
o The "real" usb-devices export now a device node which can
populate /dev/bus/usb.
o The usb_device class is optional now and can be disabled in the
kernel config. Major/minor of the "real" devices and class devices
are the same.
o The environment of the usb-device event contains DEVNUM and BUSNUM to
help udev and get rid of the ugly udev rule we need for the class
devices.
o The usb-devices and usb-interfaces share the same bus, so I used
the new "struct device_type" to let these devices identify
themselves. This also removes the current logic of using a magic
platform-pointer.
The name of the device_type is also added to the environment
which makes it easier to distinguish the different kinds of devices
on the same subsystem.
It looks like this:
add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:1d.1/usb2/2-1
SUBSYSTEM=usb
SEQNUM=1533
MAJOR=189
MINOR=131
DEVTYPE=usb_device
PRODUCT=46d/c03e/2000
TYPE=0/0/0
BUSNUM=002
DEVNUM=004
This udev rule works as a replacement for usb_device class devices:
SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", \
NAME="bus/usb/$env{BUSNUM}/$env{DEVNUM}", MODE="0644"
Updated patch, which needs the device_type patches in Greg's tree.
I also got a bugzilla assigned for this. :)
https://bugzilla.novell.com/show_bug.cgi?id=250659
Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
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 | 58 |
1 files changed, 13 insertions, 45 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 9b6a60fafdd..593386eb974 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -574,23 +574,10 @@ static int usb_device_match(struct device *dev, struct device_driver *drv) } #ifdef CONFIG_HOTPLUG - -/* - * This sends an uevent to userspace, typically helping to load driver - * or other modules, configure the device, and more. Drivers can provide - * a MODULE_DEVICE_TABLE to help with module loading subtasks. - * - * We're called either from khubd (the typical case) or from root hub - * (init, kapmd, modprobe, rmmod, etc), but the agents need to handle - * delays in event delivery. Use sysfs (and DEVPATH) to make sure the - * device (and this configuration!) are still present. - */ static int usb_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) { - struct usb_interface *intf; struct usb_device *usb_dev; - struct usb_host_interface *alt; int i = 0; int length = 0; @@ -600,13 +587,11 @@ 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)) { + if (is_usb_device(dev)) usb_dev = to_usb_device(dev); - alt = NULL; - } else { - intf = to_usb_interface(dev); + else { + struct usb_interface *intf = to_usb_interface(dev); usb_dev = interface_to_usbdev(intf); - alt = intf->cur_altsetting; } if (usb_dev->devnum < 0) { @@ -621,9 +606,7 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp, #ifdef CONFIG_USB_DEVICEFS /* If this is available, userspace programs can directly read * all the device descriptors we don't tell them about. Or - * even act as usermode drivers. - * - * FIXME reduce hardwired intelligence here + * act as usermode drivers. */ if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, @@ -650,44 +633,29 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp, usb_dev->descriptor.bDeviceProtocol)) return -ENOMEM; - if (!is_usb_device(dev)) { - - if (add_uevent_var(envp, num_envp, &i, + 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; + "BUSNUM=%03d", + usb_dev->bus->busnum)) + 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), - le16_to_cpu(usb_dev->descriptor.idProduct), - le16_to_cpu(usb_dev->descriptor.bcdDevice), - usb_dev->descriptor.bDeviceClass, - usb_dev->descriptor.bDeviceSubClass, - usb_dev->descriptor.bDeviceProtocol, - alt->desc.bInterfaceClass, - alt->desc.bInterfaceSubClass, - alt->desc.bInterfaceProtocol)) - return -ENOMEM; - } + "DEVNUM=%03d", + usb_dev->devnum)) + return -ENOMEM; envp[i] = NULL; - return 0; } #else static int usb_uevent(struct device *dev, char **envp, - int num_envp, char *buffer, int buffer_size) + int num_envp, char *buffer, int buffer_size) { return -ENODEV; } - #endif /* CONFIG_HOTPLUG */ /** |