diff options
Diffstat (limited to 'drivers/usb/core')
-rw-r--r-- | drivers/usb/core/Makefile | 4 | ||||
-rw-r--r-- | drivers/usb/core/devio.c | 91 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 2 | ||||
-rw-r--r-- | drivers/usb/core/inode.c | 9 | ||||
-rw-r--r-- | drivers/usb/core/usb.c | 15 | ||||
-rw-r--r-- | drivers/usb/core/usb.h | 5 |
6 files changed, 112 insertions, 14 deletions
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile index 9e8c377b816..d5503cf0bf7 100644 --- a/drivers/usb/core/Makefile +++ b/drivers/usb/core/Makefile | |||
@@ -3,14 +3,14 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | usbcore-objs := usb.o hub.o hcd.o urb.o message.o \ | 5 | usbcore-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 | ||
8 | ifeq ($(CONFIG_PCI),y) | 8 | ifeq ($(CONFIG_PCI),y) |
9 | usbcore-objs += hcd-pci.o | 9 | usbcore-objs += hcd-pci.o |
10 | endif | 10 | endif |
11 | 11 | ||
12 | ifeq ($(CONFIG_USB_DEVICEFS),y) | 12 | ifeq ($(CONFIG_USB_DEVICEFS),y) |
13 | usbcore-objs += devio.o inode.o devices.o | 13 | usbcore-objs += inode.o devices.o |
14 | endif | 14 | endif |
15 | 15 | ||
16 | obj-$(CONFIG_USB) += usbcore.o | 16 | obj-$(CONFIG_USB) += usbcore.o |
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index f86bf1454e2..d12bc5e84a1 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 | ||
56 | static struct class *usb_device_class; | ||
57 | |||
53 | struct async { | 58 | struct 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 | */ |
488 | static int usbdev_open(struct inode *inode, struct file *file) | 493 | static 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 | |||
1491 | struct 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 | |||
1508 | void 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 | |||
1519 | void usbdev_remove(struct usb_device *dev) | ||
1520 | { | ||
1521 | class_device_unregister(dev->class_dev); | ||
1522 | } | ||
1523 | |||
1524 | static struct cdev usb_device_cdev = { | ||
1525 | .kobj = {.name = "usb_device", }, | ||
1526 | .owner = THIS_MODULE, | ||
1527 | }; | ||
1528 | |||
1529 | int __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 | |||
1556 | out: | ||
1557 | return retval; | ||
1558 | } | ||
1559 | |||
1560 | void 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 c9412daff68..a220a5e7f4a 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 c3e3a95d380..640f41e4702 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 | ||
747 | void usbfs_cleanup(void) | 741 | void 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 2cddd8a0043..bc966dbc602 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) | |||
1493 | hub_init_failed: | 1498 | hub_init_failed: |
1494 | usbfs_cleanup(); | 1499 | usbfs_cleanup(); |
1495 | fs_init_failed: | 1500 | fs_init_failed: |
1496 | usb_major_cleanup(); | 1501 | usbdev_cleanup(); |
1502 | usbdevice_init_failed: | ||
1503 | usb_deregister(&usbfs_driver); | ||
1504 | driver_register_failed: | ||
1505 | usb_major_cleanup(); | ||
1497 | major_init_failed: | 1506 | major_init_failed: |
1498 | usb_host_cleanup(); | 1507 | usb_host_cleanup(); |
1499 | host_init_failed: | 1508 | host_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 2c690f6d4c1..83d48c8133a 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h | |||
@@ -37,6 +37,11 @@ extern struct file_operations usbfs_devices_fops; | |||
37 | extern struct file_operations usbfs_device_file_operations; | 37 | extern struct file_operations usbfs_device_file_operations; |
38 | extern void usbfs_conn_disc_event(void); | 38 | extern void usbfs_conn_disc_event(void); |
39 | 39 | ||
40 | extern int usbdev_init(void); | ||
41 | extern void usbdev_cleanup(void); | ||
42 | extern void usbdev_add(struct usb_device *dev); | ||
43 | extern void usbdev_remove(struct usb_device *dev); | ||
44 | extern struct usb_device *usbdev_lookup_minor(int minor); | ||
40 | 45 | ||
41 | struct dev_state { | 46 | struct dev_state { |
42 | struct list_head list; /* state list */ | 47 | struct list_head list; /* state list */ |