diff options
Diffstat (limited to 'drivers/usb/core/devio.c')
| -rw-r--r-- | drivers/usb/core/devio.c | 94 |
1 files changed, 51 insertions, 43 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index fc3545ddb06e..e023f3d56248 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
| @@ -57,7 +57,6 @@ | |||
| 57 | 57 | ||
| 58 | #define USB_MAXBUS 64 | 58 | #define USB_MAXBUS 64 |
| 59 | #define USB_DEVICE_MAX USB_MAXBUS * 128 | 59 | #define USB_DEVICE_MAX USB_MAXBUS * 128 |
| 60 | static struct class *usb_device_class; | ||
| 61 | 60 | ||
| 62 | /* Mutual exclusion for removal, open, and release */ | 61 | /* Mutual exclusion for removal, open, and release */ |
| 63 | DEFINE_MUTEX(usbfs_mutex); | 62 | DEFINE_MUTEX(usbfs_mutex); |
| @@ -514,22 +513,25 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig | |||
| 514 | return ret; | 513 | return ret; |
| 515 | } | 514 | } |
| 516 | 515 | ||
| 517 | static struct usb_device *usbdev_lookup_minor(int minor) | 516 | static int __match_minor(struct device *dev, void *data) |
| 518 | { | 517 | { |
| 519 | struct device *device; | 518 | int minor = *((int *)data); |
| 520 | struct usb_device *udev = NULL; | ||
| 521 | 519 | ||
| 522 | down(&usb_device_class->sem); | 520 | if (dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) |
| 523 | list_for_each_entry(device, &usb_device_class->devices, node) { | 521 | return 1; |
| 524 | if (device->devt == MKDEV(USB_DEVICE_MAJOR, minor)) { | 522 | return 0; |
| 525 | udev = device->platform_data; | 523 | } |
| 526 | break; | ||
| 527 | } | ||
| 528 | } | ||
| 529 | up(&usb_device_class->sem); | ||
| 530 | 524 | ||
| 531 | return udev; | 525 | static struct usb_device *usbdev_lookup_by_minor(int minor) |
| 532 | }; | 526 | { |
| 527 | struct device *dev; | ||
| 528 | |||
| 529 | dev = bus_find_device(&usb_bus_type, NULL, &minor, __match_minor); | ||
| 530 | if (!dev) | ||
| 531 | return NULL; | ||
| 532 | put_device(dev); | ||
| 533 | return container_of(dev, struct usb_device, dev); | ||
| 534 | } | ||
| 533 | 535 | ||
| 534 | /* | 536 | /* |
| 535 | * file operations | 537 | * file operations |
| @@ -548,11 +550,14 @@ static int usbdev_open(struct inode *inode, struct file *file) | |||
| 548 | goto out; | 550 | goto out; |
| 549 | 551 | ||
| 550 | ret = -ENOENT; | 552 | ret = -ENOENT; |
| 551 | /* check if we are called from a real node or usbfs */ | 553 | /* usbdev device-node */ |
| 552 | if (imajor(inode) == USB_DEVICE_MAJOR) | 554 | if (imajor(inode) == USB_DEVICE_MAJOR) |
| 553 | dev = usbdev_lookup_minor(iminor(inode)); | 555 | dev = usbdev_lookup_by_minor(iminor(inode)); |
| 556 | #ifdef CONFIG_USB_DEVICEFS | ||
| 557 | /* procfs file */ | ||
| 554 | if (!dev) | 558 | if (!dev) |
| 555 | dev = inode->i_private; | 559 | dev = inode->i_private; |
| 560 | #endif | ||
| 556 | if (!dev) | 561 | if (!dev) |
| 557 | goto out; | 562 | goto out; |
| 558 | ret = usb_autoresume_device(dev); | 563 | ret = usb_autoresume_device(dev); |
| @@ -1570,7 +1575,7 @@ static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wai | |||
| 1570 | return mask; | 1575 | return mask; |
| 1571 | } | 1576 | } |
| 1572 | 1577 | ||
| 1573 | const struct file_operations usbfs_device_file_operations = { | 1578 | const struct file_operations usbdev_file_operations = { |
| 1574 | .llseek = usbdev_lseek, | 1579 | .llseek = usbdev_lseek, |
| 1575 | .read = usbdev_read, | 1580 | .read = usbdev_read, |
| 1576 | .poll = usbdev_poll, | 1581 | .poll = usbdev_poll, |
| @@ -1579,50 +1584,53 @@ const struct file_operations usbfs_device_file_operations = { | |||
| 1579 | .release = usbdev_release, | 1584 | .release = usbdev_release, |
| 1580 | }; | 1585 | }; |
| 1581 | 1586 | ||
| 1582 | static int usbdev_add(struct usb_device *dev) | 1587 | #ifdef CONFIG_USB_DEVICE_CLASS |
| 1588 | static struct class *usb_classdev_class; | ||
| 1589 | |||
| 1590 | static int usb_classdev_add(struct usb_device *dev) | ||
| 1583 | { | 1591 | { |
| 1584 | int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1); | 1592 | int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1); |
| 1585 | 1593 | ||
| 1586 | dev->usbfs_dev = device_create(usb_device_class, &dev->dev, | 1594 | dev->usb_classdev = device_create(usb_classdev_class, &dev->dev, |
| 1587 | MKDEV(USB_DEVICE_MAJOR, minor), | 1595 | MKDEV(USB_DEVICE_MAJOR, minor), |
| 1588 | "usbdev%d.%d", dev->bus->busnum, dev->devnum); | 1596 | "usbdev%d.%d", dev->bus->busnum, dev->devnum); |
| 1589 | if (IS_ERR(dev->usbfs_dev)) | 1597 | if (IS_ERR(dev->usb_classdev)) |
| 1590 | return PTR_ERR(dev->usbfs_dev); | 1598 | return PTR_ERR(dev->usb_classdev); |
| 1591 | 1599 | ||
| 1592 | dev->usbfs_dev->platform_data = dev; | ||
| 1593 | return 0; | 1600 | return 0; |
| 1594 | } | 1601 | } |
| 1595 | 1602 | ||
| 1596 | static void usbdev_remove(struct usb_device *dev) | 1603 | static void usb_classdev_remove(struct usb_device *dev) |
| 1597 | { | 1604 | { |
| 1598 | device_unregister(dev->usbfs_dev); | 1605 | device_unregister(dev->usb_classdev); |
| 1599 | } | 1606 | } |
| 1600 | 1607 | ||
| 1601 | static int usbdev_notify(struct notifier_block *self, unsigned long action, | 1608 | static int usb_classdev_notify(struct notifier_block *self, |
| 1602 | void *dev) | 1609 | unsigned long action, void *dev) |
| 1603 | { | 1610 | { |
| 1604 | switch (action) { | 1611 | switch (action) { |
| 1605 | case USB_DEVICE_ADD: | 1612 | case USB_DEVICE_ADD: |
| 1606 | if (usbdev_add(dev)) | 1613 | if (usb_classdev_add(dev)) |
| 1607 | return NOTIFY_BAD; | 1614 | return NOTIFY_BAD; |
| 1608 | break; | 1615 | break; |
| 1609 | case USB_DEVICE_REMOVE: | 1616 | case USB_DEVICE_REMOVE: |
| 1610 | usbdev_remove(dev); | 1617 | usb_classdev_remove(dev); |
| 1611 | break; | 1618 | break; |
| 1612 | } | 1619 | } |
| 1613 | return NOTIFY_OK; | 1620 | return NOTIFY_OK; |
| 1614 | } | 1621 | } |
| 1615 | 1622 | ||
| 1616 | static struct notifier_block usbdev_nb = { | 1623 | static struct notifier_block usbdev_nb = { |
| 1617 | .notifier_call = usbdev_notify, | 1624 | .notifier_call = usb_classdev_notify, |
| 1618 | }; | 1625 | }; |
| 1626 | #endif | ||
| 1619 | 1627 | ||
| 1620 | static struct cdev usb_device_cdev = { | 1628 | static struct cdev usb_device_cdev = { |
| 1621 | .kobj = {.name = "usb_device", }, | 1629 | .kobj = {.name = "usb_device", }, |
| 1622 | .owner = THIS_MODULE, | 1630 | .owner = THIS_MODULE, |
| 1623 | }; | 1631 | }; |
| 1624 | 1632 | ||
| 1625 | int __init usbdev_init(void) | 1633 | int __init usb_devio_init(void) |
| 1626 | { | 1634 | { |
| 1627 | int retval; | 1635 | int retval; |
| 1628 | 1636 | ||
| @@ -1632,38 +1640,38 @@ int __init usbdev_init(void) | |||
| 1632 | err("unable to register minors for usb_device"); | 1640 | err("unable to register minors for usb_device"); |
| 1633 | goto out; | 1641 | goto out; |
| 1634 | } | 1642 | } |
| 1635 | cdev_init(&usb_device_cdev, &usbfs_device_file_operations); | 1643 | cdev_init(&usb_device_cdev, &usbdev_file_operations); |
| 1636 | retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX); | 1644 | retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX); |
| 1637 | if (retval) { | 1645 | if (retval) { |
| 1638 | err("unable to get usb_device major %d", USB_DEVICE_MAJOR); | 1646 | err("unable to get usb_device major %d", USB_DEVICE_MAJOR); |
| 1639 | goto error_cdev; | 1647 | goto error_cdev; |
| 1640 | } | 1648 | } |
| 1641 | usb_device_class = class_create(THIS_MODULE, "usb_device"); | 1649 | #ifdef CONFIG_USB_DEVICE_CLASS |
| 1642 | if (IS_ERR(usb_device_class)) { | 1650 | usb_classdev_class = class_create(THIS_MODULE, "usb_device"); |
| 1651 | if (IS_ERR(usb_classdev_class)) { | ||
| 1643 | err("unable to register usb_device class"); | 1652 | err("unable to register usb_device class"); |
| 1644 | retval = PTR_ERR(usb_device_class); | 1653 | retval = PTR_ERR(usb_classdev_class); |
| 1645 | goto error_class; | 1654 | cdev_del(&usb_device_cdev); |
| 1655 | usb_classdev_class = NULL; | ||
| 1656 | goto out; | ||
| 1646 | } | 1657 | } |
| 1647 | 1658 | ||
| 1648 | usb_register_notify(&usbdev_nb); | 1659 | usb_register_notify(&usbdev_nb); |
| 1649 | 1660 | #endif | |
| 1650 | out: | 1661 | out: |
| 1651 | return retval; | 1662 | return retval; |
| 1652 | 1663 | ||
| 1653 | error_class: | ||
| 1654 | usb_device_class = NULL; | ||
| 1655 | cdev_del(&usb_device_cdev); | ||
| 1656 | |||
| 1657 | error_cdev: | 1664 | error_cdev: |
| 1658 | unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); | 1665 | unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); |
| 1659 | goto out; | 1666 | goto out; |
| 1660 | } | 1667 | } |
| 1661 | 1668 | ||
| 1662 | void usbdev_cleanup(void) | 1669 | void usb_devio_cleanup(void) |
| 1663 | { | 1670 | { |
| 1671 | #ifdef CONFIG_USB_DEVICE_CLASS | ||
| 1664 | usb_unregister_notify(&usbdev_nb); | 1672 | usb_unregister_notify(&usbdev_nb); |
| 1665 | class_destroy(usb_device_class); | 1673 | class_destroy(usb_classdev_class); |
| 1674 | #endif | ||
| 1666 | cdev_del(&usb_device_cdev); | 1675 | cdev_del(&usb_device_cdev); |
| 1667 | unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); | 1676 | unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); |
| 1668 | } | 1677 | } |
| 1669 | |||
