diff options
-rw-r--r-- | drivers/media/rc/rc-main.c | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index e6e3ec7141bf..b1a690054834 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c | |||
@@ -918,11 +918,12 @@ static ssize_t store_protocols(struct device *device, | |||
918 | struct rc_filter_attribute *fattr = to_rc_filter_attr(mattr); | 918 | struct rc_filter_attribute *fattr = to_rc_filter_attr(mattr); |
919 | bool enable, disable; | 919 | bool enable, disable; |
920 | const char *tmp; | 920 | const char *tmp; |
921 | u64 type; | 921 | u64 old_type, type; |
922 | u64 mask; | 922 | u64 mask; |
923 | int rc, i, count = 0; | 923 | int rc, i, count = 0; |
924 | ssize_t ret; | 924 | ssize_t ret; |
925 | int (*change_protocol)(struct rc_dev *dev, u64 *rc_type); | 925 | int (*change_protocol)(struct rc_dev *dev, u64 *rc_type); |
926 | struct rc_scancode_filter local_filter, *filter; | ||
926 | 927 | ||
927 | /* Device is being removed */ | 928 | /* Device is being removed */ |
928 | if (!dev) | 929 | if (!dev) |
@@ -935,7 +936,8 @@ static ssize_t store_protocols(struct device *device, | |||
935 | ret = -EINVAL; | 936 | ret = -EINVAL; |
936 | goto out; | 937 | goto out; |
937 | } | 938 | } |
938 | type = dev->enabled_protocols[fattr->type]; | 939 | old_type = dev->enabled_protocols[fattr->type]; |
940 | type = old_type; | ||
939 | 941 | ||
940 | while ((tmp = strsep((char **) &data, " \n")) != NULL) { | 942 | while ((tmp = strsep((char **) &data, " \n")) != NULL) { |
941 | if (!*tmp) | 943 | if (!*tmp) |
@@ -999,6 +1001,36 @@ static ssize_t store_protocols(struct device *device, | |||
999 | IR_dprintk(1, "Current protocol(s): 0x%llx\n", | 1001 | IR_dprintk(1, "Current protocol(s): 0x%llx\n", |
1000 | (long long)type); | 1002 | (long long)type); |
1001 | 1003 | ||
1004 | /* | ||
1005 | * If the protocol is changed the filter needs updating. | ||
1006 | * Try setting the same filter with the new protocol (if any). | ||
1007 | * Fall back to clearing the filter. | ||
1008 | */ | ||
1009 | filter = &dev->scancode_filters[fattr->type]; | ||
1010 | if (old_type != type && filter->mask) { | ||
1011 | local_filter = *filter; | ||
1012 | if (!type) { | ||
1013 | /* no protocol => clear filter */ | ||
1014 | ret = -1; | ||
1015 | } else if (!dev->s_filter) { | ||
1016 | /* generic filtering => accept any filter */ | ||
1017 | ret = 0; | ||
1018 | } else { | ||
1019 | /* hardware filtering => try setting, otherwise clear */ | ||
1020 | ret = dev->s_filter(dev, fattr->type, &local_filter); | ||
1021 | } | ||
1022 | if (ret < 0) { | ||
1023 | /* clear the filter */ | ||
1024 | local_filter.data = 0; | ||
1025 | local_filter.mask = 0; | ||
1026 | if (dev->s_filter) | ||
1027 | dev->s_filter(dev, fattr->type, &local_filter); | ||
1028 | } | ||
1029 | |||
1030 | /* commit the new filter */ | ||
1031 | *filter = local_filter; | ||
1032 | } | ||
1033 | |||
1002 | ret = len; | 1034 | ret = len; |
1003 | 1035 | ||
1004 | out: | 1036 | out: |
@@ -1096,6 +1128,11 @@ static ssize_t store_filter(struct device *device, | |||
1096 | local_filter.mask = val; | 1128 | local_filter.mask = val; |
1097 | else | 1129 | else |
1098 | local_filter.data = val; | 1130 | local_filter.data = val; |
1131 | if (!dev->enabled_protocols[fattr->type] && local_filter.mask) { | ||
1132 | /* refuse to set a filter unless a protocol is enabled */ | ||
1133 | ret = -EINVAL; | ||
1134 | goto unlock; | ||
1135 | } | ||
1099 | if (dev->s_filter) { | 1136 | if (dev->s_filter) { |
1100 | ret = dev->s_filter(dev, fattr->type, &local_filter); | 1137 | ret = dev->s_filter(dev, fattr->type, &local_filter); |
1101 | if (ret < 0) | 1138 | if (ret < 0) |