aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/devio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core/devio.c')
-rw-r--r--drivers/usb/core/devio.c91
1 files changed, 89 insertions, 2 deletions
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