Skip to content

Commit 9f8b17e

Browse files
kaysieversgregkh
authored andcommitted
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 <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 8784028 commit 9f8b17e

File tree

9 files changed

+183
-115
lines changed

9 files changed

+183
-115
lines changed

drivers/usb/core/Kconfig

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,30 @@ config USB_DEVICEFS
3131
For the format of the various /proc/bus/usb/ files, please read
3232
<file:Documentation/usb/proc_usb_info.txt>.
3333

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+
40+
config 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.
3558

3659
config USB_DYNAMIC_MINORS
3760
bool "Dynamic USB minor allocation (EXPERIMENTAL)"

drivers/usb/core/devio.c

Lines changed: 51 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@
5757

5858
#define USB_MAXBUS 64
5959
#define USB_DEVICE_MAX USB_MAXBUS * 128
60-
static struct class *usb_device_class;
6160

6261
/* Mutual exclusion for removal, open, and release */
6362
DEFINE_MUTEX(usbfs_mutex);
@@ -514,22 +513,25 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig
514513
return ret;
515514
}
516515

517-
static struct usb_device *usbdev_lookup_minor(int minor)
516+
static int __match_minor(struct device *dev, void *data)
518517
{
519-
struct device *device;
520-
struct usb_device *udev = NULL;
518+
int minor = *((int *)data);
521519

522-
down(&usb_device_class->sem);
523-
list_for_each_entry(device, &usb_device_class->devices, node) {
524-
if (device->devt == MKDEV(USB_DEVICE_MAJOR, minor)) {
525-
udev = device->platform_data;
526-
break;
527-
}
528-
}
529-
up(&usb_device_class->sem);
520+
if (dev->devt == MKDEV(USB_DEVICE_MAJOR, minor))
521+
return 1;
522+
return 0;
523+
}
530524

531-
return udev;
532-
};
525+
static struct usb_device *usbdev_lookup_by_minor(int minor)
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+
}
533535

534536
/*
535537
* file operations
@@ -548,11 +550,14 @@ static int usbdev_open(struct inode *inode, struct file *file)
548550
goto out;
549551

550552
ret = -ENOENT;
551-
/* check if we are called from a real node or usbfs */
553+
/* usbdev device-node */
552554
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 */
554558
if (!dev)
555559
dev = inode->i_private;
560+
#endif
556561
if (!dev)
557562
goto out;
558563
ret = usb_autoresume_device(dev);
@@ -1570,7 +1575,7 @@ static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wai
15701575
return mask;
15711576
}
15721577

1573-
const struct file_operations usbfs_device_file_operations = {
1578+
const struct file_operations usbdev_file_operations = {
15741579
.llseek = usbdev_lseek,
15751580
.read = usbdev_read,
15761581
.poll = usbdev_poll,
@@ -1579,50 +1584,53 @@ const struct file_operations usbfs_device_file_operations = {
15791584
.release = usbdev_release,
15801585
};
15811586

1582-
static int usbdev_add(struct usb_device *dev)
1587+
#ifdef CONFIG_USB_DEVICE_CLASS
1588+
static struct class *usb_classdev_class;
1589+
1590+
static int usb_classdev_add(struct usb_device *dev)
15831591
{
15841592
int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1);
15851593

1586-
dev->usbfs_dev = device_create(usb_device_class, &dev->dev,
1594+
dev->usb_classdev = device_create(usb_classdev_class, &dev->dev,
15871595
MKDEV(USB_DEVICE_MAJOR, minor),
15881596
"usbdev%d.%d", dev->bus->busnum, dev->devnum);
1589-
if (IS_ERR(dev->usbfs_dev))
1590-
return PTR_ERR(dev->usbfs_dev);
1597+
if (IS_ERR(dev->usb_classdev))
1598+
return PTR_ERR(dev->usb_classdev);
15911599

1592-
dev->usbfs_dev->platform_data = dev;
15931600
return 0;
15941601
}
15951602

1596-
static void usbdev_remove(struct usb_device *dev)
1603+
static void usb_classdev_remove(struct usb_device *dev)
15971604
{
1598-
device_unregister(dev->usbfs_dev);
1605+
device_unregister(dev->usb_classdev);
15991606
}
16001607

1601-
static int usbdev_notify(struct notifier_block *self, unsigned long action,
1602-
void *dev)
1608+
static int usb_classdev_notify(struct notifier_block *self,
1609+
unsigned long action, void *dev)
16031610
{
16041611
switch (action) {
16051612
case USB_DEVICE_ADD:
1606-
if (usbdev_add(dev))
1613+
if (usb_classdev_add(dev))
16071614
return NOTIFY_BAD;
16081615
break;
16091616
case USB_DEVICE_REMOVE:
1610-
usbdev_remove(dev);
1617+
usb_classdev_remove(dev);
16111618
break;
16121619
}
16131620
return NOTIFY_OK;
16141621
}
16151622

16161623
static struct notifier_block usbdev_nb = {
1617-
.notifier_call = usbdev_notify,
1624+
.notifier_call = usb_classdev_notify,
16181625
};
1626+
#endif
16191627

16201628
static struct cdev usb_device_cdev = {
16211629
.kobj = {.name = "usb_device", },
16221630
.owner = THIS_MODULE,
16231631
};
16241632

1625-
int __init usbdev_init(void)
1633+
int __init usb_devio_init(void)
16261634
{
16271635
int retval;
16281636

@@ -1632,38 +1640,38 @@ int __init usbdev_init(void)
16321640
err("unable to register minors for usb_device");
16331641
goto out;
16341642
}
1635-
cdev_init(&usb_device_cdev, &usbfs_device_file_operations);
1643+
cdev_init(&usb_device_cdev, &usbdev_file_operations);
16361644
retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX);
16371645
if (retval) {
16381646
err("unable to get usb_device major %d", USB_DEVICE_MAJOR);
16391647
goto error_cdev;
16401648
}
1641-
usb_device_class = class_create(THIS_MODULE, "usb_device");
1642-
if (IS_ERR(usb_device_class)) {
1649+
#ifdef CONFIG_USB_DEVICE_CLASS
1650+
usb_classdev_class = class_create(THIS_MODULE, "usb_device");
1651+
if (IS_ERR(usb_classdev_class)) {
16431652
err("unable to register usb_device class");
1644-
retval = PTR_ERR(usb_device_class);
1645-
goto error_class;
1653+
retval = PTR_ERR(usb_classdev_class);
1654+
cdev_del(&usb_device_cdev);
1655+
usb_classdev_class = NULL;
1656+
goto out;
16461657
}
16471658

16481659
usb_register_notify(&usbdev_nb);
1649-
1660+
#endif
16501661
out:
16511662
return retval;
16521663

1653-
error_class:
1654-
usb_device_class = NULL;
1655-
cdev_del(&usb_device_cdev);
1656-
16571664
error_cdev:
16581665
unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
16591666
goto out;
16601667
}
16611668

1662-
void usbdev_cleanup(void)
1669+
void usb_devio_cleanup(void)
16631670
{
1671+
#ifdef CONFIG_USB_DEVICE_CLASS
16641672
usb_unregister_notify(&usbdev_nb);
1665-
class_destroy(usb_device_class);
1673+
class_destroy(usb_classdev_class);
1674+
#endif
16661675
cdev_del(&usb_device_cdev);
16671676
unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
16681677
}
1669-

drivers/usb/core/driver.c

Lines changed: 13 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -574,23 +574,10 @@ static int usb_device_match(struct device *dev, struct device_driver *drv)
574574
}
575575

576576
#ifdef CONFIG_HOTPLUG
577-
578-
/*
579-
* This sends an uevent to userspace, typically helping to load driver
580-
* or other modules, configure the device, and more. Drivers can provide
581-
* a MODULE_DEVICE_TABLE to help with module loading subtasks.
582-
*
583-
* We're called either from khubd (the typical case) or from root hub
584-
* (init, kapmd, modprobe, rmmod, etc), but the agents need to handle
585-
* delays in event delivery. Use sysfs (and DEVPATH) to make sure the
586-
* device (and this configuration!) are still present.
587-
*/
588577
static int usb_uevent(struct device *dev, char **envp, int num_envp,
589578
char *buffer, int buffer_size)
590579
{
591-
struct usb_interface *intf;
592580
struct usb_device *usb_dev;
593-
struct usb_host_interface *alt;
594581
int i = 0;
595582
int length = 0;
596583

@@ -600,13 +587,11 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp,
600587
/* driver is often null here; dev_dbg() would oops */
601588
pr_debug ("usb %s: uevent\n", dev->bus_id);
602589

603-
if (is_usb_device(dev)) {
590+
if (is_usb_device(dev))
604591
usb_dev = to_usb_device(dev);
605-
alt = NULL;
606-
} else {
607-
intf = to_usb_interface(dev);
592+
else {
593+
struct usb_interface *intf = to_usb_interface(dev);
608594
usb_dev = interface_to_usbdev(intf);
609-
alt = intf->cur_altsetting;
610595
}
611596

612597
if (usb_dev->devnum < 0) {
@@ -621,9 +606,7 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp,
621606
#ifdef CONFIG_USB_DEVICEFS
622607
/* If this is available, userspace programs can directly read
623608
* all the device descriptors we don't tell them about. Or
624-
* even act as usermode drivers.
625-
*
626-
* FIXME reduce hardwired intelligence here
609+
* act as usermode drivers.
627610
*/
628611
if (add_uevent_var(envp, num_envp, &i,
629612
buffer, buffer_size, &length,
@@ -650,44 +633,29 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp,
650633
usb_dev->descriptor.bDeviceProtocol))
651634
return -ENOMEM;
652635

653-
if (!is_usb_device(dev)) {
654-
655-
if (add_uevent_var(envp, num_envp, &i,
636+
if (add_uevent_var(envp, num_envp, &i,
656637
buffer, buffer_size, &length,
657-
"INTERFACE=%d/%d/%d",
658-
alt->desc.bInterfaceClass,
659-
alt->desc.bInterfaceSubClass,
660-
alt->desc.bInterfaceProtocol))
661-
return -ENOMEM;
638+
"BUSNUM=%03d",
639+
usb_dev->bus->busnum))
640+
return -ENOMEM;
662641

663-
if (add_uevent_var(envp, num_envp, &i,
642+
if (add_uevent_var(envp, num_envp, &i,
664643
buffer, buffer_size, &length,
665-
"MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
666-
le16_to_cpu(usb_dev->descriptor.idVendor),
667-
le16_to_cpu(usb_dev->descriptor.idProduct),
668-
le16_to_cpu(usb_dev->descriptor.bcdDevice),
669-
usb_dev->descriptor.bDeviceClass,
670-
usb_dev->descriptor.bDeviceSubClass,
671-
usb_dev->descriptor.bDeviceProtocol,
672-
alt->desc.bInterfaceClass,
673-
alt->desc.bInterfaceSubClass,
674-
alt->desc.bInterfaceProtocol))
675-
return -ENOMEM;
676-
}
644+
"DEVNUM=%03d",
645+
usb_dev->devnum))
646+
return -ENOMEM;
677647

678648
envp[i] = NULL;
679-
680649
return 0;
681650
}
682651

683652
#else
684653

685654
static int usb_uevent(struct device *dev, char **envp,
686-
int num_envp, char *buffer, int buffer_size)
655+
int num_envp, char *buffer, int buffer_size)
687656
{
688657
return -ENODEV;
689658
}
690-
691659
#endif /* CONFIG_HOTPLUG */
692660

693661
/**

drivers/usb/core/hub.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1367,11 +1367,15 @@ int usb_new_device(struct usb_device *udev)
13671367
}
13681368
#endif
13691369

1370+
/* export the usbdev device-node for libusb */
1371+
udev->dev.devt = MKDEV(USB_DEVICE_MAJOR,
1372+
(((udev->bus->busnum-1) * 128) + (udev->devnum-1)));
1373+
13701374
/* Register the device. The device driver is responsible
1371-
* for adding the device files to usbfs and sysfs and for
1372-
* configuring the device.
1375+
* for adding the device files to sysfs and for configuring
1376+
* the device.
13731377
*/
1374-
err = device_add (&udev->dev);
1378+
err = device_add(&udev->dev);
13751379
if (err) {
13761380
dev_err(&udev->dev, "can't device_add, error %d\n", err);
13771381
goto fail;

drivers/usb/core/inode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,7 @@ static void usbfs_add_device(struct usb_device *dev)
662662
sprintf (name, "%03d", dev->devnum);
663663
dev->usbfs_dentry = fs_create_file (name, devmode | S_IFREG,
664664
dev->bus->usbfs_dentry, dev,
665-
&usbfs_device_file_operations,
665+
&usbdev_file_operations,
666666
devuid, devgid);
667667
if (dev->usbfs_dentry == NULL) {
668668
err ("error creating usbfs device entry");

0 commit comments

Comments
 (0)