diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-24 00:12:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-24 00:12:49 -0400 |
commit | df462b3dbeeaae7141f1b63cbfcc1e1bae6a85fc (patch) | |
tree | bca52fce066159f136d75c69e79016422212cb1d /drivers/media/rc/rc-main.c | |
parent | 343800e7d20944aead238c2c6e3f7789f8b6587c (diff) | |
parent | cf25220677b3f10468a74278130fe224f73632a6 (diff) |
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (247 commits)
[media] gspca - sunplus: Fix some warnings and simplify code
[media] gspca: Fix some warnings tied to 'no debug'
[media] gspca: Unset debug by default
[media] gspca - cpia1: Remove a bad conditional compilation instruction
[media] gspca - main: Remove USB traces
[media] gspca - main: Version change to 2.13
[media] gspca - stk014 / t613: Accept the index 0 in querymenu
[media] gspca - kinect: Remove __devinitdata
[media] gspca - cpia1: Fix some warnings
[media] video/Kconfig: Fix mis-classified devices
[media] support for medion dvb stick 1660:1921
[media] tm6000: fix uninitialized field, change prink to dprintk
[media] cx231xx: Add support for Iconbit U100
[media] saa7134 add new TV cards
[media] Use a more consistent value for RC repeat period
[media] cx18: Move spinlock and vb_type initialisation into stream_init
[media] tm6000: remove tm6010 sif audio start and stop
[media] tm6000: remove unused exports
[media] tm6000: add pts logging
[media] tm6000: change from ioctl to unlocked_ioctl
...
Diffstat (limited to 'drivers/media/rc/rc-main.c')
-rw-r--r-- | drivers/media/rc/rc-main.c | 54 |
1 files changed, 48 insertions, 6 deletions
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index a2706648e365..f57cd5677ac2 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c | |||
@@ -749,6 +749,9 @@ static struct { | |||
749 | * it is trigged by reading /sys/class/rc/rc?/protocols. | 749 | * it is trigged by reading /sys/class/rc/rc?/protocols. |
750 | * It returns the protocol names of supported protocols. | 750 | * It returns the protocol names of supported protocols. |
751 | * Enabled protocols are printed in brackets. | 751 | * Enabled protocols are printed in brackets. |
752 | * | ||
753 | * dev->lock is taken to guard against races between device | ||
754 | * registration, store_protocols and show_protocols. | ||
752 | */ | 755 | */ |
753 | static ssize_t show_protocols(struct device *device, | 756 | static ssize_t show_protocols(struct device *device, |
754 | struct device_attribute *mattr, char *buf) | 757 | struct device_attribute *mattr, char *buf) |
@@ -762,6 +765,8 @@ static ssize_t show_protocols(struct device *device, | |||
762 | if (!dev) | 765 | if (!dev) |
763 | return -EINVAL; | 766 | return -EINVAL; |
764 | 767 | ||
768 | mutex_lock(&dev->lock); | ||
769 | |||
765 | if (dev->driver_type == RC_DRIVER_SCANCODE) { | 770 | if (dev->driver_type == RC_DRIVER_SCANCODE) { |
766 | enabled = dev->rc_map.rc_type; | 771 | enabled = dev->rc_map.rc_type; |
767 | allowed = dev->allowed_protos; | 772 | allowed = dev->allowed_protos; |
@@ -784,6 +789,9 @@ static ssize_t show_protocols(struct device *device, | |||
784 | if (tmp != buf) | 789 | if (tmp != buf) |
785 | tmp--; | 790 | tmp--; |
786 | *tmp = '\n'; | 791 | *tmp = '\n'; |
792 | |||
793 | mutex_unlock(&dev->lock); | ||
794 | |||
787 | return tmp + 1 - buf; | 795 | return tmp + 1 - buf; |
788 | } | 796 | } |
789 | 797 | ||
@@ -802,6 +810,9 @@ static ssize_t show_protocols(struct device *device, | |||
802 | * Writing "none" will disable all protocols. | 810 | * Writing "none" will disable all protocols. |
803 | * Returns -EINVAL if an invalid protocol combination or unknown protocol name | 811 | * Returns -EINVAL if an invalid protocol combination or unknown protocol name |
804 | * is used, otherwise @len. | 812 | * is used, otherwise @len. |
813 | * | ||
814 | * dev->lock is taken to guard against races between device | ||
815 | * registration, store_protocols and show_protocols. | ||
805 | */ | 816 | */ |
806 | static ssize_t store_protocols(struct device *device, | 817 | static ssize_t store_protocols(struct device *device, |
807 | struct device_attribute *mattr, | 818 | struct device_attribute *mattr, |
@@ -815,18 +826,22 @@ static ssize_t store_protocols(struct device *device, | |||
815 | u64 mask; | 826 | u64 mask; |
816 | int rc, i, count = 0; | 827 | int rc, i, count = 0; |
817 | unsigned long flags; | 828 | unsigned long flags; |
829 | ssize_t ret; | ||
818 | 830 | ||
819 | /* Device is being removed */ | 831 | /* Device is being removed */ |
820 | if (!dev) | 832 | if (!dev) |
821 | return -EINVAL; | 833 | return -EINVAL; |
822 | 834 | ||
835 | mutex_lock(&dev->lock); | ||
836 | |||
823 | if (dev->driver_type == RC_DRIVER_SCANCODE) | 837 | if (dev->driver_type == RC_DRIVER_SCANCODE) |
824 | type = dev->rc_map.rc_type; | 838 | type = dev->rc_map.rc_type; |
825 | else if (dev->raw) | 839 | else if (dev->raw) |
826 | type = dev->raw->enabled_protocols; | 840 | type = dev->raw->enabled_protocols; |
827 | else { | 841 | else { |
828 | IR_dprintk(1, "Protocol switching not supported\n"); | 842 | IR_dprintk(1, "Protocol switching not supported\n"); |
829 | return -EINVAL; | 843 | ret = -EINVAL; |
844 | goto out; | ||
830 | } | 845 | } |
831 | 846 | ||
832 | while ((tmp = strsep((char **) &data, " \n")) != NULL) { | 847 | while ((tmp = strsep((char **) &data, " \n")) != NULL) { |
@@ -860,7 +875,8 @@ static ssize_t store_protocols(struct device *device, | |||
860 | } | 875 | } |
861 | if (i == ARRAY_SIZE(proto_names)) { | 876 | if (i == ARRAY_SIZE(proto_names)) { |
862 | IR_dprintk(1, "Unknown protocol: '%s'\n", tmp); | 877 | IR_dprintk(1, "Unknown protocol: '%s'\n", tmp); |
863 | return -EINVAL; | 878 | ret = -EINVAL; |
879 | goto out; | ||
864 | } | 880 | } |
865 | count++; | 881 | count++; |
866 | } | 882 | } |
@@ -875,7 +891,8 @@ static ssize_t store_protocols(struct device *device, | |||
875 | 891 | ||
876 | if (!count) { | 892 | if (!count) { |
877 | IR_dprintk(1, "Protocol not specified\n"); | 893 | IR_dprintk(1, "Protocol not specified\n"); |
878 | return -EINVAL; | 894 | ret = -EINVAL; |
895 | goto out; | ||
879 | } | 896 | } |
880 | 897 | ||
881 | if (dev->change_protocol) { | 898 | if (dev->change_protocol) { |
@@ -883,7 +900,8 @@ static ssize_t store_protocols(struct device *device, | |||
883 | if (rc < 0) { | 900 | if (rc < 0) { |
884 | IR_dprintk(1, "Error setting protocols to 0x%llx\n", | 901 | IR_dprintk(1, "Error setting protocols to 0x%llx\n", |
885 | (long long)type); | 902 | (long long)type); |
886 | return -EINVAL; | 903 | ret = -EINVAL; |
904 | goto out; | ||
887 | } | 905 | } |
888 | } | 906 | } |
889 | 907 | ||
@@ -898,7 +916,11 @@ static ssize_t store_protocols(struct device *device, | |||
898 | IR_dprintk(1, "Current protocol(s): 0x%llx\n", | 916 | IR_dprintk(1, "Current protocol(s): 0x%llx\n", |
899 | (long long)type); | 917 | (long long)type); |
900 | 918 | ||
901 | return len; | 919 | ret = len; |
920 | |||
921 | out: | ||
922 | mutex_unlock(&dev->lock); | ||
923 | return ret; | ||
902 | } | 924 | } |
903 | 925 | ||
904 | static void rc_dev_release(struct device *device) | 926 | static void rc_dev_release(struct device *device) |
@@ -974,6 +996,7 @@ struct rc_dev *rc_allocate_device(void) | |||
974 | 996 | ||
975 | spin_lock_init(&dev->rc_map.lock); | 997 | spin_lock_init(&dev->rc_map.lock); |
976 | spin_lock_init(&dev->keylock); | 998 | spin_lock_init(&dev->keylock); |
999 | mutex_init(&dev->lock); | ||
977 | setup_timer(&dev->timer_keyup, ir_timer_keyup, (unsigned long)dev); | 1000 | setup_timer(&dev->timer_keyup, ir_timer_keyup, (unsigned long)dev); |
978 | 1001 | ||
979 | dev->dev.type = &rc_dev_type; | 1002 | dev->dev.type = &rc_dev_type; |
@@ -1019,12 +1042,21 @@ int rc_register_device(struct rc_dev *dev) | |||
1019 | if (dev->close) | 1042 | if (dev->close) |
1020 | dev->input_dev->close = ir_close; | 1043 | dev->input_dev->close = ir_close; |
1021 | 1044 | ||
1045 | /* | ||
1046 | * Take the lock here, as the device sysfs node will appear | ||
1047 | * when device_add() is called, which may trigger an ir-keytable udev | ||
1048 | * rule, which will in turn call show_protocols and access either | ||
1049 | * dev->rc_map.rc_type or dev->raw->enabled_protocols before it has | ||
1050 | * been initialized. | ||
1051 | */ | ||
1052 | mutex_lock(&dev->lock); | ||
1053 | |||
1022 | dev->devno = (unsigned long)(atomic_inc_return(&devno) - 1); | 1054 | dev->devno = (unsigned long)(atomic_inc_return(&devno) - 1); |
1023 | dev_set_name(&dev->dev, "rc%ld", dev->devno); | 1055 | dev_set_name(&dev->dev, "rc%ld", dev->devno); |
1024 | dev_set_drvdata(&dev->dev, dev); | 1056 | dev_set_drvdata(&dev->dev, dev); |
1025 | rc = device_add(&dev->dev); | 1057 | rc = device_add(&dev->dev); |
1026 | if (rc) | 1058 | if (rc) |
1027 | return rc; | 1059 | goto out_unlock; |
1028 | 1060 | ||
1029 | rc = ir_setkeytable(dev, rc_map); | 1061 | rc = ir_setkeytable(dev, rc_map); |
1030 | if (rc) | 1062 | if (rc) |
@@ -1046,6 +1078,13 @@ int rc_register_device(struct rc_dev *dev) | |||
1046 | */ | 1078 | */ |
1047 | dev->input_dev->rep[REP_DELAY] = 500; | 1079 | dev->input_dev->rep[REP_DELAY] = 500; |
1048 | 1080 | ||
1081 | /* | ||
1082 | * As a repeat event on protocols like RC-5 and NEC take as long as | ||
1083 | * 110/114ms, using 33ms as a repeat period is not the right thing | ||
1084 | * to do. | ||
1085 | */ | ||
1086 | dev->input_dev->rep[REP_PERIOD] = 125; | ||
1087 | |||
1049 | path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); | 1088 | path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); |
1050 | printk(KERN_INFO "%s: %s as %s\n", | 1089 | printk(KERN_INFO "%s: %s as %s\n", |
1051 | dev_name(&dev->dev), | 1090 | dev_name(&dev->dev), |
@@ -1058,6 +1097,7 @@ int rc_register_device(struct rc_dev *dev) | |||
1058 | if (rc < 0) | 1097 | if (rc < 0) |
1059 | goto out_input; | 1098 | goto out_input; |
1060 | } | 1099 | } |
1100 | mutex_unlock(&dev->lock); | ||
1061 | 1101 | ||
1062 | if (dev->change_protocol) { | 1102 | if (dev->change_protocol) { |
1063 | rc = dev->change_protocol(dev, rc_map->rc_type); | 1103 | rc = dev->change_protocol(dev, rc_map->rc_type); |
@@ -1083,6 +1123,8 @@ out_table: | |||
1083 | ir_free_table(&dev->rc_map); | 1123 | ir_free_table(&dev->rc_map); |
1084 | out_dev: | 1124 | out_dev: |
1085 | device_del(&dev->dev); | 1125 | device_del(&dev->dev); |
1126 | out_unlock: | ||
1127 | mutex_unlock(&dev->lock); | ||
1086 | return rc; | 1128 | return rc; |
1087 | } | 1129 | } |
1088 | EXPORT_SYMBOL_GPL(rc_register_device); | 1130 | EXPORT_SYMBOL_GPL(rc_register_device); |