aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 /*