aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKay Sievers <kay.sievers@vrfy.org>2007-03-13 10:59:31 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-04-27 16:28:37 -0400
commit9f8b17e643fe6aa505629658445849397bda4e4f (patch)
tree30c45914f7be9f355db30964323673c7d37080e8
parent87840289637e9ea95118ebd76e2e335fdcddd725 (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>
-rw-r--r--drivers/usb/core/Kconfig25
-rw-r--r--drivers/usb/core/devio.c94
-rw-r--r--drivers/usb/core/driver.c58
-rw-r--r--drivers/usb/core/hub.c10
-rw-r--r--drivers/usb/core/inode.c2
-rw-r--r--drivers/usb/core/message.c65
-rw-r--r--drivers/usb/core/usb.c20
-rw-r--r--drivers/usb/core/usb.h14
-rw-r--r--include/linux/usb.h10
9 files changed, 183 insertions, 115 deletions
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index 2fc0f88a3d86..f493fb1eaa27 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -31,7 +31,30 @@ config USB_DEVICEFS
31 For the format of the various /proc/bus/usb/ files, please read 31 For the format of the various /proc/bus/usb/ files, please read
32 <file:Documentation/usb/proc_usb_info.txt>. 32 <file:Documentation/usb/proc_usb_info.txt>.
33 33
34 Most users want to say Y here. 34 Usbfs files can't handle Access Control Lists (ACL), which are the
35 default way to grant access to USB devices for untrusted users of a
36 desktop system. The usbfs functionality is replaced by real
37 device-nodes managed by udev. These nodes live in /dev/bus/usb and
38 are used by libusb.
39
40config USB_DEVICE_CLASS
41 bool "USB device class-devices (DEPRECATED)"
42 depends on USB
43 default n
44 ---help---
45 Userspace access to USB devices is granted by device-nodes exported
46 directly from the usbdev in sysfs. Old versions of the driver
47 core and udev needed additional class devices to export device nodes.
48
49 These additional devices are difficult to handle in userspace, if
50 information about USB interfaces must be available. One device contains
51 the device node, the other device contains the interface data. Both
52 devices are at the same level in sysfs (siblings) and one can't access
53 the other. The device node created directly by the usbdev is the parent
54 device of the interface and therefore easily accessible from the interface
55 event.
56
57 This option provides backward compatibility if needed.
35 58
36config USB_DYNAMIC_MINORS 59config USB_DYNAMIC_MINORS
37 bool "Dynamic USB minor allocation (EXPERIMENTAL)" 60 bool "Dynamic USB minor allocation (EXPERIMENTAL)"
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index fc3545ddb06e..e023f3d56248 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -57,7 +57,6 @@
57 57
58#define USB_MAXBUS 64 58#define USB_MAXBUS 64
59#define USB_DEVICE_MAX USB_MAXBUS * 128 59#define USB_DEVICE_MAX USB_MAXBUS * 128
60static struct class *usb_device_class;
61 60
62/* Mutual exclusion for removal, open, and release */ 61/* Mutual exclusion for removal, open, and release */
63DEFINE_MUTEX(usbfs_mutex); 62DEFINE_MUTEX(usbfs_mutex);
@@ -514,22 +513,25 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig
514 return ret; 513 return ret;
515} 514}
516 515
517static struct usb_device *usbdev_lookup_minor(int minor) 516static int __match_minor(struct device *dev, void *data)
518{ 517{
519 struct device *device; 518 int minor = *((int *)data);
520 struct usb_device *udev = NULL;
521 519
522 down(&usb_device_class->sem); 520 if (dev->devt == MKDEV(USB_DEVICE_MAJOR, minor))
523 list_for_each_entry(device, &usb_device_class->devices, node) { 521 return 1;
524 if (device->devt == MKDEV(USB_DEVICE_MAJOR, minor)) { 522 return 0;
525 udev = device->platform_data; 523}
526 break;
527 }
528 }
529 up(&usb_device_class->sem);
530 524
531 return udev; 525static struct usb_device *usbdev_lookup_by_minor(int minor)
532}; 526{
527 struct device *dev;
528
529 dev = bus_find_device(&usb_bus_type, NULL, &minor, __match_minor);
530 if (!dev)
531 return NULL;
532 put_device(dev);
533 return container_of(dev, struct usb_device, dev);
534}
533 535
534/* 536/*
535 * file operations 537 * file operations
@@ -548,11 +550,14 @@ static int usbdev_open(struct inode *inode, struct file *file)
548 goto out; 550 goto out;
549 551
550 ret = -ENOENT; 552 ret = -ENOENT;
551 /* check if we are called from a real node or usbfs */ 553 /* usbdev device-node */
552 if (imajor(inode) == USB_DEVICE_MAJOR) 554 if (imajor(inode) == USB_DEVICE_MAJOR)
553 dev = usbdev_lookup_minor(iminor(inode)); 555 dev = usbdev_lookup_by_minor(iminor(inode));
556#ifdef CONFIG_USB_DEVICEFS
557 /* procfs file */
554 if (!dev) 558 if (!dev)
555 dev = inode->i_private; 559 dev = inode->i_private;
560#endif
556 if (!dev) 561 if (!dev)
557 goto out; 562 goto out;
558 ret = usb_autoresume_device(dev); 563 ret = usb_autoresume_device(dev);
@@ -1570,7 +1575,7 @@ static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wai
1570 return mask; 1575 return mask;
1571} 1576}
1572 1577
1573const struct file_operations usbfs_device_file_operations = { 1578const struct file_operations usbdev_file_operations = {
1574 .llseek = usbdev_lseek, 1579 .llseek = usbdev_lseek,
1575 .read = usbdev_read, 1580 .read = usbdev_read,
1576 .poll = usbdev_poll, 1581 .poll = usbdev_poll,
@@ -1579,50 +1584,53 @@ const struct file_operations usbfs_device_file_operations = {
1579 .release = usbdev_release, 1584 .release = usbdev_release,
1580}; 1585};
1581 1586
1582static int usbdev_add(struct usb_device *dev) 1587#ifdef CONFIG_USB_DEVICE_CLASS
1588static struct class *usb_classdev_class;
1589
1590static int usb_classdev_add(struct usb_device *dev)
1583{ 1591{
1584 int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1); 1592 int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1);
1585 1593
1586 dev->usbfs_dev = device_create(usb_device_class, &dev->dev, 1594 dev->usb_classdev = device_create(usb_classdev_class, &dev->dev,
1587 MKDEV(USB_DEVICE_MAJOR, minor), 1595 MKDEV(USB_DEVICE_MAJOR, minor),
1588 "usbdev%d.%d", dev->bus->busnum, dev->devnum); 1596 "usbdev%d.%d", dev->bus->busnum, dev->devnum);
1589 if (IS_ERR(dev->usbfs_dev)) 1597 if (IS_ERR(dev->usb_classdev))
1590 return PTR_ERR(dev->usbfs_dev); 1598 return PTR_ERR(dev->usb_classdev);
1591 1599
1592 dev->usbfs_dev->platform_data = dev;
1593 return 0; 1600 return 0;
1594} 1601}
1595 1602
1596static void usbdev_remove(struct usb_device *dev) 1603static void usb_classdev_remove(struct usb_device *dev)
1597{ 1604{
1598 device_unregister(dev->usbfs_dev); 1605 device_unregister(dev->usb_classdev);
1599} 1606}
1600 1607
1601static int usbdev_notify(struct notifier_block *self, unsigned long action, 1608static int usb_classdev_notify(struct notifier_block *self,
1602 void *dev) 1609 unsigned long action, void *dev)
1603{ 1610{
1604 switch (action) { 1611 switch (action) {
1605 case USB_DEVICE_ADD: 1612 case USB_DEVICE_ADD:
1606 if (usbdev_add(dev)) 1613 if (usb_classdev_add(dev))
1607 return NOTIFY_BAD; 1614 return NOTIFY_BAD;
1608 break; 1615 break;
1609 case USB_DEVICE_REMOVE: 1616 case USB_DEVICE_REMOVE:
1610 usbdev_remove(dev); 1617 usb_classdev_remove(dev);
1611 break; 1618 break;
1612 } 1619 }