Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>


authored by

Kay Sievers and committed by
Greg Kroah-Hartman
9f8b17e6 87840289

+183 -115
+24 -1
drivers/usb/core/Kconfig
··· 31 31 For the format of the various /proc/bus/usb/ files, please read 32 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 + 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. 35 58 36 59 config USB_DYNAMIC_MINORS 37 60 bool "Dynamic USB minor allocation (EXPERIMENTAL)"
+51 -43
drivers/usb/core/devio.c
··· 57 57 58 58 #define USB_MAXBUS 64 59 59 #define USB_DEVICE_MAX USB_MAXBUS * 128 60 - static struct class *usb_device_class; 61 60 62 61 /* Mutual exclusion for removal, open, and release */ 63 62 DEFINE_MUTEX(usbfs_mutex); ··· 513 514 return ret; 514 515 } 515 516 516 - static struct usb_device *usbdev_lookup_minor(int minor) 517 + static int __match_minor(struct device *dev, void *data) 517 518 { 518 - struct device *device; 519 - struct usb_device *udev = NULL; 519 + int minor = *((int *)data); 520 520 521 - down(&usb_device_class->sem); 522 - list_for_each_entry(device, &usb_device_class->devices, node) { 523 - if (device->devt == MKDEV(USB_DEVICE_MAJOR, minor)) { 524 - udev = device->platform_data; 525 - break; 526 - } 527 - } 528 - up(&usb_device_class->sem); 521 + if (dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) 522 + return 1; 523 + return 0; 524 + } 529 525 530 - return udev; 531 - }; 526 + static struct usb_device *usbdev_lookup_by_minor(int minor) 527 + { 528 + struct device *dev; 529 + 530 + dev = bus_find_device(&usb_bus_type, NULL, &minor, __match_minor); 531 + if (!dev) 532 + return NULL; 533 + put_device(dev); 534 + return container_of(dev, struct usb_device, dev); 535 + } 532 536 533 537 /* 534 538 * file operations ··· 550 548 goto out; 551 549 552 550 ret = -ENOENT; 553 - /* check if we are called from a real node or usbfs */ 551 + /* usbdev device-node */ 554 552 if (imajor(inode) == USB_DEVICE_MAJOR) 555 - dev = usbdev_lookup_minor(iminor(inode)); 553 + dev = usbdev_lookup_by_minor(iminor(inode)); 554 + #ifdef CONFIG_USB_DEVICEFS 555 + /* procfs file */ 556 556 if (!dev) 557 557 dev = inode->i_private; 558 + #endif 558 559 if (!dev) 559 560 goto out; 560 561 ret = usb_autoresume_device(dev); ··· 1575 1570 return mask; 1576 1571 } 1577 1572 1578 - const struct file_operations usbfs_device_file_operations = { 1573 + const struct file_operations usbdev_file_operations = { 1579 1574 .llseek = usbdev_lseek, 1580 1575 .read = usbdev_read, 1581 1576 .poll = usbdev_poll, ··· 1584 1579 .release = usbdev_release, 1585 1580 }; 1586 1581 1587 - static int usbdev_add(struct usb_device *dev) 1582 + #ifdef CONFIG_USB_DEVICE_CLASS 1583 + static struct class *usb_classdev_class; 1584 + 1585 + static int usb_classdev_add(struct usb_device *dev) 1588 1586 { 1589 1587 int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1); 1590 1588 1591 - dev->usbfs_dev = device_create(usb_device_class, &dev->dev, 1589 + dev->usb_classdev = device_create(usb_classdev_class, &dev->dev, 1592 1590 MKDEV(USB_DEVICE_MAJOR, minor), 1593 1591 "usbdev%d.%d", dev->bus->busnum, dev->devnum); 1594 - if (IS_ERR(dev->usbfs_dev)) 1595 - return PTR_ERR(dev->usbfs_dev); 1592 + if (IS_ERR(dev->usb_classdev)) 1593 + return PTR_ERR(dev->usb_classdev); 1596 1594 1597 - dev->usbfs_dev->platform_data = dev; 1598 1595 return 0; 1599 1596 } 1600 1597 1601 - static void usbdev_remove(struct usb_device *dev) 1598 + static void usb_classdev_remove(struct usb_device *dev) 1602 1599 { 1603 - device_unregister(dev->usbfs_dev); 1600 + device_unregister(dev->usb_classdev); 1604 1601 } 1605 1602 1606 - static int usbdev_notify(struct notifier_block *self, unsigned long action, 1607 - void *dev) 1603 + static int usb_classdev_notify(struct notifier_block *self, 1604 + unsigned long action, void *dev) 1608 1605 { 1609 1606 switch (action) { 1610 1607 case USB_DEVICE_ADD: 1611 - if (usbdev_add(dev)) 1608 + if (usb_classdev_add(dev)) 1612 1609 return NOTIFY_BAD; 1613 1610 break; 1614 1611 case USB_DEVICE_REMOVE: 1615 - usbdev_remove(dev); 1612 + usb_classdev_remove(dev); 1616 1613 break; 1617 1614 } 1618 1615 return NOTIFY_OK; 1619 1616 } 1620 1617 1621 1618 static struct notifier_block usbdev_nb = { 1622 - .notifier_call = usbdev_notify, 1619 + .notifier_call = usb_classdev_notify, 1623 1620 }; 1621 + #endif 1624 1622 1625 1623 static struct cdev usb_device_cdev = { 1626 1624 .kobj = {.name = "usb_device", }, 1627 1625 .owner = THIS_MODULE, 1628 1626 }; 1629 1627 1630 - int __init usbdev_init(void) 1628 + int __init usb_devio_init(void) 1631 1629 { 1632 1630 int retval; 1633 1631 ··· 1640 1632 err("unable to register minors for usb_device"); 1641 1633 goto out; 1642 1634 } 1643 - cdev_init(&usb_device_cdev, &usbfs_device_file_operations); 1635 + cdev_init(&usb_device_cdev, &usbdev_file_operations); 1644 1636 retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX); 1645 1637 if (retval) { 1646 1638 err("unable to get usb_device major %d", USB_DEVICE_MAJOR); 1647 1639 goto error_cdev; 1648 1640 } 1649 - usb_device_class = class_create(THIS_MODULE, "usb_device"); 1650 - if (IS_ERR(usb_device_class)) { 1641 + #ifdef CONFIG_USB_DEVICE_CLASS 1642 + usb_classdev_class = class_create(THIS_MODULE, "usb_device"); 1643 + if (IS_ERR(usb_classdev_class)) { 1651 1644 err("unable to register usb_device class"); 1652 - retval = PTR_ERR(usb_device_class); 1653 - goto error_class; 1645 + retval = PTR_ERR(usb_classdev_class); 1646 + cdev_del(&usb_device_cdev); 1647 + usb_classdev_class = NULL; 1648 + goto out; 1654 1649 } 1655 1650 1656 1651 usb_register_notify(&usbdev_nb); 1657 - 1652 + #endif 1658 1653 out: 1659 1654 return retval; 1660 - 1661 - error_class: 1662 - usb_device_class = NULL; 1663 - cdev_del(&usb_device_cdev); 1664 1655 1665 1656 error_cdev: 1666 1657 unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); 1667 1658 goto out; 1668 1659 } 1669 1660 1670 - void usbdev_cleanup(void) 1661 + void usb_devio_cleanup(void) 1671 1662 { 1663 + #ifdef CONFIG_USB_DEVICE_CLASS 1672 1664 usb_unregister_notify(&usbdev_nb); 1673 - class_destroy(usb_device_class); 1665 + class_destroy(usb_classdev_class); 1666 + #endif 1674 1667 cdev_del(&usb_device_cdev); 1675 1668 unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); 1676 1669 } 1677 -
+13 -45
drivers/usb/core/driver.c
··· 574 574 } 575 575 576 576 #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 - */ 588 577 static int usb_uevent(struct device *dev, char **envp, int num_envp, 589 578 char *buffer, int buffer_size) 590 579 { 591 - struct usb_interface *intf; 592 580 struct usb_device *usb_dev; 593 - struct usb_host_interface *alt; 594 581 int i = 0; 595 582 int length = 0; 596 583 ··· 587 600 /* driver is often null here; dev_dbg() would oops */ 588 601 pr_debug ("usb %s: uevent\n", dev->bus_id); 589 602 590 - if (is_usb_device(dev)) { 603 + if (is_usb_device(dev)) 591 604 usb_dev = to_usb_device(dev); 592 - alt = NULL; 593 - } else { 594 - intf = to_usb_interface(dev); 605 + else { 606 + struct usb_interface *intf = to_usb_interface(dev); 595 607 usb_dev = interface_to_usbdev(intf); 596 - alt = intf->cur_altsetting; 597 608 } 598 609 599 610 if (usb_dev->devnum < 0) { ··· 606 621 #ifdef CONFIG_USB_DEVICEFS 607 622 /* If this is available, userspace programs can directly read 608 623 * all the device descriptors we don't tell them about. Or 609 - * even act as usermode drivers. 610 - * 611 - * FIXME reduce hardwired intelligence here 624 + * act as usermode drivers. 612 625 */ 613 626 if (add_uevent_var(envp, num_envp, &i, 614 627 buffer, buffer_size, &length, ··· 633 650 usb_dev->descriptor.bDeviceProtocol)) 634 651 return -ENOMEM; 635 652 636 - if (!is_usb_device(dev)) { 637 - 638 - if (add_uevent_var(envp, num_envp, &i, 653 + if (add_uevent_var(envp, num_envp, &i, 639 654 buffer, buffer_size, &length, 640 - "INTERFACE=%d/%d/%d", 641 - alt->desc.bInterfaceClass, 642 - alt->desc.bInterfaceSubClass, 643 - alt->desc.bInterfaceProtocol)) 644 - return -ENOMEM; 655 + "BUSNUM=%03d", 656 + usb_dev->bus->busnum)) 657 + return -ENOMEM; 645 658 646 - if (add_uevent_var(envp, num_envp, &i, 659 + if (add_uevent_var(envp, num_envp, &i, 647 660 buffer, buffer_size, &length, 648 - "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", 649 - le16_to_cpu(usb_dev->descriptor.idVendor), 650 - le16_to_cpu(usb_dev->descriptor.idProduct), 651 - le16_to_cpu(usb_dev->descriptor.bcdDevice), 652 - usb_dev->descriptor.bDeviceClass, 653 - usb_dev->descriptor.bDeviceSubClass, 654 - usb_dev->descriptor.bDeviceProtocol, 655 - alt->desc.bInterfaceClass, 656 - alt->desc.bInterfaceSubClass, 657 - alt->desc.bInterfaceProtocol)) 658 - return -ENOMEM; 659 - } 661 + "DEVNUM=%03d", 662 + usb_dev->devnum)) 663 + return -ENOMEM; 660 664 661 665 envp[i] = NULL; 662 - 663 666 return 0; 664 667 } 665 668 666 669 #else 667 670 668 671 static int usb_uevent(struct device *dev, char **envp, 669 - int num_envp, char *buffer, int buffer_size) 672 + int num_envp, char *buffer, int buffer_size) 670 673 { 671 674 return -ENODEV; 672 675 } 673 - 674 676 #endif /* CONFIG_HOTPLUG */ 675 677 676 678 /**
+7 -3
drivers/usb/core/hub.c
··· 1367 1367 } 1368 1368 #endif 1369 1369 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 + 1370 1374 /* 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. 1373 1377 */ 1374 - err = device_add (&udev->dev); 1378 + err = device_add(&udev->dev); 1375 1379 if (err) { 1376 1380 dev_err(&udev->dev, "can't device_add, error %d\n", err); 1377 1381 goto fail;
+1 -1
drivers/usb/core/inode.c
··· 662 662 sprintf (name, "%03d", dev->devnum); 663 663 dev->usbfs_dentry = fs_create_file (name, devmode | S_IFREG, 664 664 dev->bus->usbfs_dentry, dev, 665 - &usbfs_device_file_operations, 665 + &usbdev_file_operations, 666 666 devuid, devgid); 667 667 if (dev->usbfs_dentry == NULL) { 668 668 err ("error creating usbfs device entry");
+63 -2
drivers/usb/core/message.c
··· 1305 1305 return 0; 1306 1306 } 1307 1307 1308 - static void release_interface(struct device *dev) 1308 + void usb_release_interface(struct device *dev) 1309 1309 { 1310 1310 struct usb_interface *intf = to_usb_interface(dev); 1311 1311 struct usb_interface_cache *intfc = ··· 1314 1314 kref_put(&intfc->ref, usb_release_interface_cache); 1315 1315 kfree(intf); 1316 1316 } 1317 + 1318 + #ifdef CONFIG_HOTPLUG 1319 + static int usb_if_uevent(struct device *dev, char **envp, int num_envp, 1320 + char *buffer, int buffer_size) 1321 + { 1322 + struct usb_device *usb_dev; 1323 + struct usb_interface *intf; 1324 + struct usb_host_interface *alt; 1325 + int i = 0; 1326 + int length = 0; 1327 + 1328 + if (!dev) 1329 + return -ENODEV; 1330 + 1331 + /* driver is often null here; dev_dbg() would oops */ 1332 + pr_debug ("usb %s: uevent\n", dev->bus_id); 1333 + 1334 + intf = to_usb_interface(dev); 1335 + usb_dev = interface_to_usbdev(intf); 1336 + alt = intf->cur_altsetting; 1337 + 1338 + if (add_uevent_var(envp, num_envp, &i, 1339 + buffer, buffer_size, &length, 1340 + "INTERFACE=%d/%d/%d", 1341 + alt->desc.bInterfaceClass, 1342 + alt->desc.bInterfaceSubClass, 1343 + alt->desc.bInterfaceProtocol)) 1344 + return -ENOMEM; 1345 + 1346 + if (add_uevent_var(envp, num_envp, &i, 1347 + buffer, buffer_size, &length, 1348 + "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", 1349 + le16_to_cpu(usb_dev->descriptor.idVendor), 1350 + le16_to_cpu(usb_dev->descriptor.idProduct), 1351 + le16_to_cpu(usb_dev->descriptor.bcdDevice), 1352 + usb_dev->descriptor.bDeviceClass, 1353 + usb_dev->descriptor.bDeviceSubClass, 1354 + usb_dev->descriptor.bDeviceProtocol, 1355 + alt->desc.bInterfaceClass, 1356 + alt->desc.bInterfaceSubClass, 1357 + alt->desc.bInterfaceProtocol)) 1358 + return -ENOMEM; 1359 + 1360 + envp[i] = NULL; 1361 + return 0; 1362 + } 1363 + 1364 + #else 1365 + 1366 + static int usb_if_uevent(struct device *dev, char **envp, 1367 + int num_envp, char *buffer, int buffer_size) 1368 + { 1369 + return -ENODEV; 1370 + } 1371 + #endif /* CONFIG_HOTPLUG */ 1372 + 1373 + struct device_type usb_if_device_type = { 1374 + .name = "usb_interface", 1375 + .release = usb_release_interface, 1376 + .uevent = usb_if_uevent, 1377 + }; 1317 1378 1318 1379 /* 1319 1380 * usb_set_configuration - Makes a particular device setting be current ··· 1539 1478 intf->dev.parent = &dev->dev; 1540 1479 intf->dev.driver = NULL; 1541 1480 intf->dev.bus = &usb_bus_type; 1481 + intf->dev.type = &usb_if_device_type; 1542 1482 intf->dev.dma_mask = dev->dev.dma_mask; 1543 - intf->dev.release = release_interface; 1544 1483 device_initialize (&intf->dev); 1545 1484 mark_quiesced(intf); 1546 1485 sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
+11 -9
drivers/usb/core/usb.c
··· 197 197 kfree(udev); 198 198 } 199 199 200 + struct device_type usb_device_type = { 201 + .name = "usb_device", 202 + .release = usb_release_dev, 203 + }; 204 + 200 205 #ifdef CONFIG_PM 201 206 202 207 static int ksuspend_usb_init(void) ··· 252 247 253 248 device_initialize(&dev->dev); 254 249 dev->dev.bus = &usb_bus_type; 250 + dev->dev.type = &usb_device_type; 255 251 dev->dev.dma_mask = bus->controller->dma_mask; 256 - dev->dev.release = usb_release_dev; 257 252 dev->state = USB_STATE_ATTACHED; 258 - 259 - /* This magic assignment distinguishes devices from interfaces */ 260 - dev->dev.platform_data = &usb_generic_driver; 261 253 262 254 INIT_LIST_HEAD(&dev->ep0.urb_list); 263 255 dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE; ··· 884 882 retval = usb_register(&usbfs_driver); 885 883 if (retval) 886 884 goto driver_register_failed; 887 - retval = usbdev_init(); 885 + retval = usb_devio_init(); 888 886 if (retval) 889 - goto usbdevice_init_failed; 887 + goto usb_devio_init_failed; 890 888 retval = usbfs_init(); 891 889 if (retval) 892 890 goto fs_init_failed; ··· 901 899 hub_init_failed: 902 900 usbfs_cleanup(); 903 901 fs_init_failed: 904 - usbdev_cleanup(); 905 - usbdevice_init_failed: 902 + usb_devio_cleanup(); 903 + usb_devio_init_failed: 906 904 usb_deregister(&usbfs_driver); 907 905 driver_register_failed: 908 906 usb_major_cleanup(); ··· 929 927 usb_major_cleanup(); 930 928 usbfs_cleanup(); 931 929 usb_deregister(&usbfs_driver); 932 - usbdev_cleanup(); 930 + usb_devio_cleanup(); 933 931 usb_hub_cleanup(); 934 932 usb_host_cleanup(); 935 933 bus_unregister(&usb_bus_type);
+6 -8
drivers/usb/core/usb.h
··· 78 78 79 79 extern struct workqueue_struct *ksuspend_usb_wq; 80 80 extern struct bus_type usb_bus_type; 81 + extern struct device_type usb_device_type; 82 + extern struct device_type usb_if_device_type; 81 83 extern struct usb_device_driver usb_generic_driver; 82 - 83 - /* Here's how we tell apart devices and interfaces. Luckily there's 84 - * no such thing as a platform USB device, so we can steal the use 85 - * of the platform_data field. */ 86 84 87 85 static inline int is_usb_device(const struct device *dev) 88 86 { 89 - return dev->platform_data == &usb_generic_driver; 87 + return dev->type == &usb_device_type; 90 88 } 91 89 92 90 /* Do the same for device drivers and interface drivers. */ ··· 120 122 extern struct mutex usbfs_mutex; 121 123 extern struct usb_driver usbfs_driver; 122 124 extern const struct file_operations usbfs_devices_fops; 123 - extern const struct file_operations usbfs_device_file_operations; 125 + extern const struct file_operations usbdev_file_operations; 124 126 extern void usbfs_conn_disc_event(void); 125 127 126 - extern int usbdev_init(void); 127 - extern void usbdev_cleanup(void); 128 + extern int usb_devio_init(void); 129 + extern void usb_devio_cleanup(void); 128 130 129 131 struct dev_state { 130 132 struct list_head list; /* state list */
+7 -3
include/linux/usb.h
··· 299 299 int bandwidth_int_reqs; /* number of Interrupt requests */ 300 300 int bandwidth_isoc_reqs; /* number of Isoc. requests */ 301 301 302 + #ifdef CONFIG_USB_DEVICEFS 302 303 struct dentry *usbfs_dentry; /* usbfs dentry entry for the bus */ 303 - 304 + #endif 304 305 struct class_device *class_dev; /* class device for this bus */ 305 306 306 307 #if defined(CONFIG_USB_MON) ··· 374 373 char *serial; /* iSerialNumber string, if present */ 375 374 376 375 struct list_head filelist; 377 - struct device *usbfs_dev; 376 + #ifdef CONFIG_USB_DEVICE_CLASS 377 + struct device *usb_classdev; 378 + #endif 379 + #ifdef CONFIG_USB_DEVICEFS 378 380 struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */ 379 - 381 + #endif 380 382 /* 381 383 * Child devices - these can be either new devices 382 384 * (if this is a hub device), or different instances