diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2008-05-17 10:01:05 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2008-05-17 10:01:05 -0400 |
commit | 0e50a4c6ab94ffe7e5515b86b5df9e5abc8c6b13 (patch) | |
tree | 3c688483e71261f564fc43be3157b337ae340dca /drivers/usb/core/sysfs.c | |
parent | 34b2cd5b688b012975fcfc3b3970fc3508fa82c4 (diff) | |
parent | f26a3988917913b3d11b2bd741601a2c64ab9204 (diff) |
Merge branch 'linus' into x86/pebs
Diffstat (limited to 'drivers/usb/core/sysfs.c')
-rw-r--r-- | drivers/usb/core/sysfs.c | 137 |
1 files changed, 85 insertions, 52 deletions
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 5b20a60de8ba..c783cb111847 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c | |||
@@ -538,6 +538,46 @@ static struct attribute_group dev_attr_grp = { | |||
538 | .attrs = dev_attrs, | 538 | .attrs = dev_attrs, |
539 | }; | 539 | }; |
540 | 540 | ||
541 | /* When modifying this list, be sure to modify dev_string_attrs_are_visible() | ||
542 | * accordingly. | ||
543 | */ | ||
544 | static struct attribute *dev_string_attrs[] = { | ||
545 | &dev_attr_manufacturer.attr, | ||
546 | &dev_attr_product.attr, | ||
547 | &dev_attr_serial.attr, | ||
548 | NULL | ||
549 | }; | ||
550 | |||
551 | static mode_t dev_string_attrs_are_visible(struct kobject *kobj, | ||
552 | struct attribute *a, int n) | ||
553 | { | ||
554 | struct usb_device *udev = to_usb_device( | ||
555 | container_of(kobj, struct device, kobj)); | ||
556 | |||
557 | if (a == &dev_attr_manufacturer.attr) { | ||
558 | if (udev->manufacturer == NULL) | ||
559 | return 0; | ||
560 | } else if (a == &dev_attr_product.attr) { | ||
561 | if (udev->product == NULL) | ||
562 | return 0; | ||
563 | } else if (a == &dev_attr_serial.attr) { | ||
564 | if (udev->serial == NULL) | ||
565 | return 0; | ||
566 | } | ||
567 | return a->mode; | ||
568 | } | ||
569 | |||
570 | static struct attribute_group dev_string_attr_grp = { | ||
571 | .attrs = dev_string_attrs, | ||
572 | .is_visible = dev_string_attrs_are_visible, | ||
573 | }; | ||
574 | |||
575 | struct attribute_group *usb_device_groups[] = { | ||
576 | &dev_attr_grp, | ||
577 | &dev_string_attr_grp, | ||
578 | NULL | ||
579 | }; | ||
580 | |||
541 | /* Binary descriptors */ | 581 | /* Binary descriptors */ |
542 | 582 | ||
543 | static ssize_t | 583 | static ssize_t |
@@ -591,10 +631,9 @@ int usb_create_sysfs_dev_files(struct usb_device *udev) | |||
591 | struct device *dev = &udev->dev; | 631 | struct device *dev = &udev->dev; |
592 | int retval; | 632 | int retval; |
593 | 633 | ||
594 | retval = sysfs_create_group(&dev->kobj, &dev_attr_grp); | 634 | /* Unforunately these attributes cannot be created before |
595 | if (retval) | 635 | * the uevent is broadcast. |
596 | return retval; | 636 | */ |
597 | |||
598 | retval = device_create_bin_file(dev, &dev_bin_attr_descriptors); | 637 | retval = device_create_bin_file(dev, &dev_bin_attr_descriptors); |
599 | if (retval) | 638 | if (retval) |
600 | goto error; | 639 | goto error; |
@@ -607,21 +646,6 @@ int usb_create_sysfs_dev_files(struct usb_device *udev) | |||
607 | if (retval) | 646 | if (retval) |
608 | goto error; | 647 | goto error; |
609 | 648 | ||
610 | if (udev->manufacturer) { | ||
611 | retval = device_create_file(dev, &dev_attr_manufacturer); | ||
612 | if (retval) | ||
613 | goto error; | ||
614 | } | ||
615 | if (udev->product) { | ||
616 | retval = device_create_file(dev, &dev_attr_product); | ||
617 | if (retval) | ||
618 | goto error; | ||
619 | } | ||
620 | if (udev->serial) { | ||
621 | retval = device_create_file(dev, &dev_attr_serial); | ||
622 | if (retval) | ||
623 | goto error; | ||
624 | } | ||
625 | retval = usb_create_ep_files(dev, &udev->ep0, udev); | 649 | retval = usb_create_ep_files(dev, &udev->ep0, udev); |
626 | if (retval) | 650 | if (retval) |
627 | goto error; | 651 | goto error; |
@@ -636,13 +660,9 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev) | |||
636 | struct device *dev = &udev->dev; | 660 | struct device *dev = &udev->dev; |
637 | 661 | ||
638 | usb_remove_ep_files(&udev->ep0); | 662 | usb_remove_ep_files(&udev->ep0); |
639 | device_remove_file(dev, &dev_attr_manufacturer); | ||
640 | device_remove_file(dev, &dev_attr_product); | ||
641 | device_remove_file(dev, &dev_attr_serial); | ||
642 | remove_power_attributes(dev); | 663 | remove_power_attributes(dev); |
643 | remove_persist_attributes(dev); | 664 | remove_persist_attributes(dev); |
644 | device_remove_bin_file(dev, &dev_bin_attr_descriptors); | 665 | device_remove_bin_file(dev, &dev_bin_attr_descriptors); |
645 | sysfs_remove_group(&dev->kobj, &dev_attr_grp); | ||
646 | } | 666 | } |
647 | 667 | ||
648 | /* Interface Accociation Descriptor fields */ | 668 | /* Interface Accociation Descriptor fields */ |
@@ -688,17 +708,15 @@ static ssize_t show_interface_string(struct device *dev, | |||
688 | struct device_attribute *attr, char *buf) | 708 | struct device_attribute *attr, char *buf) |
689 | { | 709 | { |
690 | struct usb_interface *intf; | 710 | struct usb_interface *intf; |
691 | struct usb_device *udev; | 711 | char *string; |
692 | int len; | ||
693 | 712 | ||
694 | intf = to_usb_interface(dev); | 713 | intf = to_usb_interface(dev); |
695 | udev = interface_to_usbdev(intf); | 714 | string = intf->cur_altsetting->string; |
696 | len = snprintf(buf, 256, "%s", intf->cur_altsetting->string); | 715 | barrier(); /* The altsetting might change! */ |
697 | if (len < 0) | 716 | |
717 | if (!string) | ||
698 | return 0; | 718 | return 0; |
699 | buf[len] = '\n'; | 719 | return sprintf(buf, "%s\n", string); |
700 | buf[len+1] = 0; | ||
701 | return len+1; | ||
702 | } | 720 | } |
703 | static DEVICE_ATTR(interface, S_IRUGO, show_interface_string, NULL); | 721 | static DEVICE_ATTR(interface, S_IRUGO, show_interface_string, NULL); |
704 | 722 | ||
@@ -727,18 +745,6 @@ static ssize_t show_modalias(struct device *dev, | |||
727 | } | 745 | } |
728 | static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); | 746 | static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); |
729 | 747 | ||
730 | static struct attribute *intf_assoc_attrs[] = { | ||
731 | &dev_attr_iad_bFirstInterface.attr, | ||
732 | &dev_attr_iad_bInterfaceCount.attr, | ||
733 | &dev_attr_iad_bFunctionClass.attr, | ||
734 | &dev_attr_iad_bFunctionSubClass.attr, | ||
735 | &dev_attr_iad_bFunctionProtocol.attr, | ||
736 | NULL, | ||
737 | }; | ||
738 | static struct attribute_group intf_assoc_attr_grp = { | ||
739 | .attrs = intf_assoc_attrs, | ||
740 | }; | ||
741 | |||
742 | static struct attribute *intf_attrs[] = { | 748 | static struct attribute *intf_attrs[] = { |
743 | &dev_attr_bInterfaceNumber.attr, | 749 | &dev_attr_bInterfaceNumber.attr, |
744 | &dev_attr_bAlternateSetting.attr, | 750 | &dev_attr_bAlternateSetting.attr, |
@@ -753,6 +759,37 @@ static struct attribute_group intf_attr_grp = { | |||
753 | .attrs = intf_attrs, | 759 | .attrs = intf_attrs, |
754 | }; | 760 | }; |
755 | 761 | ||
762 | static struct attribute *intf_assoc_attrs[] = { | ||
763 | &dev_attr_iad_bFirstInterface.attr, | ||
764 | &dev_attr_iad_bInterfaceCount.attr, | ||
765 | &dev_attr_iad_bFunctionClass.attr, | ||
766 | &dev_attr_iad_bFunctionSubClass.attr, | ||
767 | &dev_attr_iad_bFunctionProtocol.attr, | ||
768 | NULL, | ||
769 | }; | ||
770 | |||
771 | static mode_t intf_assoc_attrs_are_visible(struct kobject *kobj, | ||
772 | struct attribute *a, int n) | ||
773 | { | ||
774 | struct usb_interface *intf = to_usb_interface( | ||
775 | container_of(kobj, struct device, kobj)); | ||
776 | |||
777 | if (intf->intf_assoc == NULL) | ||
778 | return 0; | ||
779 | return a->mode; | ||
780 | } | ||
781 | |||
782 | static struct attribute_group intf_assoc_attr_grp = { | ||
783 | .attrs = intf_assoc_attrs, | ||
784 | .is_visible = intf_assoc_attrs_are_visible, | ||
785 | }; | ||
786 | |||
787 | struct attribute_group *usb_interface_groups[] = { | ||
788 | &intf_attr_grp, | ||
789 | &intf_assoc_attr_grp, | ||
790 | NULL | ||
791 | }; | ||
792 | |||
756 | static inline void usb_create_intf_ep_files(struct usb_interface *intf, | 793 | static inline void usb_create_intf_ep_files(struct usb_interface *intf, |
757 | struct usb_device *udev) | 794 | struct usb_device *udev) |
758 | { | 795 | { |
@@ -777,23 +814,21 @@ static inline void usb_remove_intf_ep_files(struct usb_interface *intf) | |||
777 | 814 | ||
778 | int usb_create_sysfs_intf_files(struct usb_interface *intf) | 815 | int usb_create_sysfs_intf_files(struct usb_interface *intf) |
779 | { | 816 | { |
780 | struct device *dev = &intf->dev; | ||
781 | struct usb_device *udev = interface_to_usbdev(intf); | 817 | struct usb_device *udev = interface_to_usbdev(intf); |
782 | struct usb_host_interface *alt = intf->cur_altsetting; | 818 | struct usb_host_interface *alt = intf->cur_altsetting; |
783 | int retval; | 819 | int retval; |
784 | 820 | ||
785 | if (intf->sysfs_files_created) | 821 | if (intf->sysfs_files_created) |
786 | return 0; | 822 | return 0; |
787 | retval = sysfs_create_group(&dev->kobj, &intf_attr_grp); | ||
788 | if (retval) | ||
789 | return retval; | ||
790 | 823 | ||
824 | /* The interface string may be present in some altsettings | ||
825 | * and missing in others. Hence its attribute cannot be created | ||
826 | * before the uevent is broadcast. | ||
827 | */ | ||
791 | if (alt->string == NULL) | 828 | if (alt->string == NULL) |
792 | alt->string = usb_cache_string(udev, alt->desc.iInterface); | 829 | alt->string = usb_cache_string(udev, alt->desc.iInterface); |
793 | if (alt->string) | 830 | if (alt->string) |
794 | retval = device_create_file(dev, &dev_attr_interface); | 831 | retval = device_create_file(&intf->dev, &dev_attr_interface); |
795 | if (intf->intf_assoc) | ||
796 | retval = sysfs_create_group(&dev->kobj, &intf_assoc_attr_grp); | ||
797 | usb_create_intf_ep_files(intf, udev); | 832 | usb_create_intf_ep_files(intf, udev); |
798 | intf->sysfs_files_created = 1; | 833 | intf->sysfs_files_created = 1; |
799 | return 0; | 834 | return 0; |
@@ -807,7 +842,5 @@ void usb_remove_sysfs_intf_files(struct usb_interface *intf) | |||
807 | return; | 842 | return; |
808 | usb_remove_intf_ep_files(intf); | 843 | usb_remove_intf_ep_files(intf); |
809 | device_remove_file(dev, &dev_attr_interface); | 844 | device_remove_file(dev, &dev_attr_interface); |
810 | sysfs_remove_group(&dev->kobj, &intf_attr_grp); | ||
811 | sysfs_remove_group(&intf->dev.kobj, &intf_assoc_attr_grp); | ||
812 | intf->sysfs_files_created = 0; | 845 | intf->sysfs_files_created = 0; |
813 | } | 846 | } |