aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKay Sievers <kay.sievers@vrfy.org>2005-07-30 19:05:53 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-09-08 19:22:29 -0400
commitfbf82fd2e1f4e679c60516d772d1862c941ca845 (patch)
tree85aee08e665076cf90251e705db13f03b136ce0a
parent22af8878d2d641c6b15fe39fe4de3c05b2c477f0 (diff)
[PATCH] USB: real nodes instead of usbfs
This patch introduces a /sys/class/usb_device/ class where every connected usb-device will show up: tree /sys/class/usb_device/ /sys/class/usb_device/ |-- usb1.1 | |-- dev | `-- device -> ../../../devices/pci0000:00/0000:00:1d.0/usb1 |-- usb2.1 | |-- dev | `-- device -> ../../../devices/pci0000:00/0000:00:1d.1/usb2 ... The presence of the "dev" file lets udev create real device nodes. kay@pim:~/src/linux-2.6> tree /dev/bus/usb/ /dev/bus/usb/ |-- 1 | `-- 1 |-- 2 | `-- 1 ... udev rule: SUBSYSTEM="usb_device", PROGRAM="/sbin/usb_device %k", NAME="%c" (echo $1 | /bin/sed 's/usb\([0-9]*\)\.\([0-9]*\)/bus\/usb\/\1\/\2/') This makes libusb pick up the real nodes instead of the mounted usbfs: export USB_DEVFS_PATH=/dev/bus/usb Background: All this makes it possible to manage usb devices with udev instead of the devfs solution. We are currently working on a pam_console/resmgr replacement driven by udev and a pam-helper. It applies ACL's to device nodes, which is required for modern desktop functionalty like "Fast User Switching" or multiple local login support. New patch with its own major. I've succesfully disabled usbfs and use real nodes only on my box. With: "export USB_DEVFS_PATH=/dev/bus/usb" libusb picks up the udev managed nodes instead of reading usbfs files. This makes udev to provide symlinks for libusb to pick up: SUBSYSTEM="usb_device", PROGRAM="/sbin/usbdevice %k", SYMLINK="%c" /sbin/usbdevice: #!/bin/sh echo $1 | /bin/sed 's/usbdev\([0-9]*\)\.\([0-9]*\)/bus\/usb\/\1\/\2/' Signed-off-by: Kay Sievers <kay.sievers@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/core/Makefile4
-rw-r--r--drivers/usb/core/devio.c91
-rw-r--r--drivers/usb/core/hub.c2
-rw-r--r--drivers/usb/core/inode.c9
-rw-r--r--drivers/usb/core/usb.c15
-rw-r--r--drivers/usb/core/usb.h5
-rw-r--r--include/linux/usb.h2
7 files changed, 114 insertions, 14 deletions
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
index 9e8c377b8161..d5503cf0bf74 100644
--- a/drivers/usb/core/Makefile
+++ b/drivers/usb/core/Makefile
@@ -3,14 +3,14 @@
3# 3#
4 4
5usbcore-objs := usb.o hub.o hcd.o urb.o message.o \ 5usbcore-objs := usb.o hub.o hcd.o urb.o message.o \
6 config.o file.o buffer.o sysfs.o 6 config.o file.o buffer.o sysfs.o devio.o
7 7
8ifeq ($(CONFIG_PCI),y) 8ifeq ($(CONFIG_PCI),y)
9 usbcore-objs += hcd-pci.o 9 usbcore-objs += hcd-pci.o
10endif 10endif
11 11
12ifeq ($(CONFIG_USB_DEVICEFS),y) 12ifeq ($(CONFIG_USB_DEVICEFS),y)
13 usbcore-objs += devio.o inode.o devices.o 13 usbcore-objs += inode.o devices.o
14endif 14endif
15 15
16obj-$(CONFIG_USB) += usbcore.o 16obj-$(CONFIG_USB) += usbcore.o
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index f86bf1454e21..d12bc5e84a1a 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -43,6 +43,7 @@
43#include <linux/module.h> 43#include <linux/module.h>
44#include <linux/usb.h> 44#include <linux/usb.h>
45#include <linux/usbdevice_fs.h> 45#include <linux/usbdevice_fs.h>
46#include <linux/cdev.h>
46#include <asm/uaccess.h> 47#include <asm/uaccess.h>
47#include <asm/byteorder.h> 48#include <asm/byteorder.h>
48#include <linux/moduleparam.h> 49#include <linux/moduleparam.h>
@@ -50,6 +51,10 @@
50#include "hcd.h" /* for usbcore internals */ 51#include "hcd.h" /* for usbcore internals */
51#include "usb.h" 52#include "usb.h"
52 53
54#define USB_MAXBUS 64
55#define USB_DEVICE_MAX USB_MAXBUS * 128
56static struct class *usb_device_class;
57
53struct async { 58struct async {
54 struct list_head asynclist; 59 struct list_head asynclist;
55 struct dev_state *ps; 60 struct dev_state *ps;
@@ -487,7 +492,7 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig
487 */ 492 */
488static int usbdev_open(struct inode *inode, struct file *file) 493static int usbdev_open(struct inode *inode, struct file *file)
489{ 494{
490 struct usb_device *dev; 495 struct usb_device *dev = NULL;
491 struct dev_state *ps; 496 struct dev_state *ps;
492 int ret; 497 int ret;
493 498
@@ -501,11 +506,16 @@ static int usbdev_open(struct inode *inode, struct file *file)
501 506
502 lock_kernel(); 507 lock_kernel();
503 ret = -ENOENT; 508 ret = -ENOENT;
504 dev = usb_get_dev(inode->u.generic_ip); 509 /* check if we are called from a real node or usbfs */
510 if (imajor(inode) == USB_DEVICE_MAJOR)
511 dev = usbdev_lookup_minor(iminor(inode));
512 if (!dev)
513 dev = inode->u.generic_ip;
505 if (!dev) { 514 if (!dev) {
506 kfree(ps); 515 kfree(ps);
507 goto out; 516 goto out;
508 } 517 }
518 usb_get_dev(dev);
509 ret = 0; 519 ret = 0;
510 ps->dev = dev; 520 ps->dev = dev;
511 ps->file = file; 521 ps->file = file;
@@ -1477,3 +1487,80 @@ struct file_operations usbfs_device_file_operations = {
1477 .open = usbdev_open, 1487 .open = usbdev_open,
1478 .release = usbdev_release, 1488 .release = usbdev_release,
1479}; 1489};
1490
1491struct usb_device *usbdev_lookup_minor(int minor)
1492{
1493 struct class_device *class_dev;
1494 struct usb_device *dev = NULL;
1495
1496 down(&usb_device_class->sem);
1497 list_for_each_entry(class_dev, &usb_device_class->children, node) {
1498 if (class_dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) {
1499 dev = class_dev->class_data;
1500 break;
1501 }
1502 }
1503 up(&usb_device_class->sem);
1504
1505 return dev;
1506};
1507
1508void usbdev_add(struct usb_device *dev)
1509{
1510 int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1);
1511
1512 dev->class_dev = class_device_create(usb_device_class,
1513 MKDEV(USB_DEVICE_MAJOR, minor), &dev->dev,
1514 "usbdev%d.%d", dev->bus->busnum, dev->devnum);
1515
1516 dev->class_dev->class_data = dev;
1517}
1518
1519void usbdev_remove(struct usb_device *dev)
1520{
1521 class_device_unregister(dev->class_dev);
1522}
1523
1524static struct cdev usb_device_cdev = {
1525 .kobj = {.name = "usb_device", },
1526 .owner = THIS_MODULE,
1527};
1528
1529int __init usbdev_init(void)
1530{
1531 int retval;
1532
1533 retval = register_chrdev_region(MKDEV(USB_DEVICE_MAJOR, 0),
1534 USB_DEVICE_MAX, "usb_device");
1535 if (retval) {
1536 err("unable to register minors for usb_device");
1537 goto out;
1538 }
1539 cdev_init(&usb_device_cdev, &usbfs_device_file_operations);
1540 retval = cdev_add(&usb_device_cdev,
1541 MKDEV(USB_DEVICE_MAJOR, 0), USB_DEVICE_MAX);
1542 if (retval) {
1543 err("unable to get usb_device major %d", USB_DEVICE_MAJOR);
1544 unregister_chrdev_region(USB_DEVICE_MAJOR, USB_DEVICE_MAX);
1545 goto out;
1546 }
1547 usb_device_class = class_create(THIS_MODULE, "usb_device");
1548 if (IS_ERR(usb_device_class)) {
1549 err("unable to register usb_device class");
1550 retval = PTR_ERR(usb_device_class);
1551 usb_device_class = NULL;
1552 cdev_del(&usb_device_cdev);
1553 unregister_chrdev_region(USB_DEVICE_MAJOR, USB_DEVICE_MAX);
1554 }
1555
1556out:
1557 return retval;
1558}
1559
1560void usbdev_cleanup(void)
1561{
1562 class_destroy(usb_device_class);
1563 cdev_del(&usb_device_cdev);
1564 unregister_chrdev_region(USB_DEVICE_MAJOR, USB_DEVICE_MAX);
1565}
1566
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index c9412daff682..a220a5e7f4a5 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1051,6 +1051,7 @@ void usb_disconnect(struct usb_device **pdev)
1051 dev_dbg (&udev->dev, "unregistering device\n"); 1051 dev_dbg (&udev->dev, "unregistering device\n");
1052 release_address(udev); 1052 release_address(udev);
1053 usbfs_remove_device(udev); 1053 usbfs_remove_device(udev);
1054 usbdev_remove(udev);
1054 usb_remove_sysfs_dev_files(udev); 1055 usb_remove_sysfs_dev_files(udev);
1055 1056
1056 /* Avoid races with recursively_mark_NOTATTACHED() */ 1057 /* Avoid races with recursively_mark_NOTATTACHED() */
@@ -1290,6 +1291,7 @@ int usb_new_device(struct usb_device *udev)
1290 /* USB device state == configured ... usable */ 1291 /* USB device state == configured ... usable */
1291 1292
1292 /* add a /proc/bus/usb entry */ 1293 /* add a /proc/bus/usb entry */
1294 usbdev_add(udev);
1293 usbfs_add_device(udev); 1295 usbfs_add_device(udev);
1294 return 0; 1296 return 0;
1295 1297
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index c3e3a95d3804..640f41e47029 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -728,15 +728,9 @@ int __init usbfs_init(void)
728{ 728{
729 int retval; 729 int retval;
730 730
731 retval = usb_register(&usbfs_driver);
732 if (retval)
733 return retval;
734
735 retval = register_filesystem(&usb_fs_type); 731 retval = register_filesystem(&usb_fs_type);
736 if (retval) { 732 if (retval)
737 usb_deregister(&usbfs_driver);
738 return retval; 733 return retval;
739 }
740 734
741 /* create mount point for usbfs */ 735 /* create mount point for usbfs */
742 usbdir = proc_mkdir("usb", proc_bus); 736 usbdir = proc_mkdir("usb", proc_bus);
@@ -746,7 +740,6 @@ int __init usbfs_init(void)
746 740
747void usbfs_cleanup(void) 741void usbfs_cleanup(void)
748{ 742{
749 usb_deregister(&usbfs_driver);
750 unregister_filesystem(&usb_fs_type); 743 unregister_filesystem(&usb_fs_type);
751 if (usbdir) 744 if (usbdir)
752 remove_proc_entry("usb", proc_bus); 745 remove_proc_entry("usb", proc_bus);
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 2cddd8a00437..bc966dbc6021 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -1478,13 +1478,18 @@ static int __init usb_init(void)
1478 retval = usb_major_init(); 1478 retval = usb_major_init();
1479 if (retval) 1479 if (retval)
1480 goto major_init_failed; 1480 goto major_init_failed;
1481 retval = usb_register(&usbfs_driver);
1482 if (retval)
1483 goto driver_register_failed;
1484 retval = usbdev_init();
1485 if (retval)
1486 goto usbdevice_init_failed;
1481 retval = usbfs_init(); 1487 retval = usbfs_init();
1482 if (retval) 1488 if (retval)
1483 goto fs_init_failed; 1489 goto fs_init_failed;
1484 retval = usb_hub_init(); 1490 retval = usb_hub_init();
1485 if (retval) 1491 if (retval)
1486 goto hub_init_failed; 1492 goto hub_init_failed;
1487
1488 retval = driver_register(&usb_generic_driver); 1493 retval = driver_register(&usb_generic_driver);
1489 if (!retval) 1494 if (!retval)
1490 goto out; 1495 goto out;
@@ -1493,7 +1498,11 @@ static int __init usb_init(void)
1493hub_init_failed: 1498hub_init_failed:
1494 usbfs_cleanup(); 1499 usbfs_cleanup();
1495fs_init_failed: 1500fs_init_failed:
1496 usb_major_cleanup(); 1501 usbdev_cleanup();
1502usbdevice_init_failed:
1503 usb_deregister(&usbfs_driver);
1504driver_register_failed:
1505 usb_major_cleanup();
1497major_init_failed: 1506major_init_failed:
1498 usb_host_cleanup(); 1507 usb_host_cleanup();
1499host_init_failed: 1508host_init_failed:
@@ -1514,6 +1523,8 @@ static void __exit usb_exit(void)
1514 driver_unregister(&usb_generic_driver); 1523 driver_unregister(&usb_generic_driver);
1515 usb_major_cleanup(); 1524 usb_major_cleanup();
1516 usbfs_cleanup(); 1525 usbfs_cleanup();
1526 usb_deregister(&usbfs_driver);
1527 usbdev_cleanup();
1517 usb_hub_cleanup(); 1528 usb_hub_cleanup();
1518 usb_host_cleanup(); 1529 usb_host_cleanup();
1519 bus_unregister(&usb_bus_type); 1530 bus_unregister(&usb_bus_type);
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 2c690f6d4c18..83d48c8133af 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -37,6 +37,11 @@ extern struct file_operations usbfs_devices_fops;
37extern struct file_operations usbfs_device_file_operations; 37extern struct file_operations usbfs_device_file_operations;
38extern void usbfs_conn_disc_event(void); 38extern void usbfs_conn_disc_event(void);
39 39
40extern int usbdev_init(void);
41extern void usbdev_cleanup(void);
42extern void usbdev_add(struct usb_device *dev);
43extern void usbdev_remove(struct usb_device *dev);
44extern struct usb_device *usbdev_lookup_minor(int minor);
40 45
41struct dev_state { 46struct dev_state {
42 struct list_head list; /* state list */ 47 struct list_head list; /* state list */
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 724637792996..434e35120c65 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -5,6 +5,7 @@
5#include <linux/usb_ch9.h> 5#include <linux/usb_ch9.h>
6 6
7#define USB_MAJOR 180 7#define USB_MAJOR 180
8#define USB_DEVICE_MAJOR 189
8 9
9 10
10#ifdef __KERNEL__ 11#ifdef __KERNEL__
@@ -349,6 +350,7 @@ struct usb_device {
349 char *manufacturer; 350 char *manufacturer;
350 char *serial; /* static strings from the device */ 351 char *serial; /* static strings from the device */
351 struct list_head filelist; 352 struct list_head filelist;
353 struct class_device *class_dev;
352 struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */ 354 struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */
353 355
354 /* 356 /*