diff options
Diffstat (limited to 'drivers/media/rc/rc-main.c')
-rw-r--r-- | drivers/media/rc/rc-main.c | 88 |
1 files changed, 53 insertions, 35 deletions
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index ecbc20c4252e..970b93d6f399 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c | |||
@@ -633,19 +633,13 @@ EXPORT_SYMBOL_GPL(rc_repeat); | |||
633 | static void ir_do_keydown(struct rc_dev *dev, int scancode, | 633 | static void ir_do_keydown(struct rc_dev *dev, int scancode, |
634 | u32 keycode, u8 toggle) | 634 | u32 keycode, u8 toggle) |
635 | { | 635 | { |
636 | struct rc_scancode_filter *filter; | 636 | bool new_event = (!dev->keypressed || |
637 | bool new_event = !dev->keypressed || | 637 | dev->last_scancode != scancode || |
638 | dev->last_scancode != scancode || | 638 | dev->last_toggle != toggle); |
639 | dev->last_toggle != toggle; | ||
640 | 639 | ||
641 | if (new_event && dev->keypressed) | 640 | if (new_event && dev->keypressed) |
642 | ir_do_keyup(dev, false); | 641 | ir_do_keyup(dev, false); |
643 | 642 | ||
644 | /* Generic scancode filtering */ | ||
645 | filter = &dev->scancode_filters[RC_FILTER_NORMAL]; | ||
646 | if (filter->mask && ((scancode ^ filter->data) & filter->mask)) | ||
647 | return; | ||
648 | |||
649 | input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode); | 643 | input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode); |
650 | 644 | ||
651 | if (new_event && keycode != KEY_RESERVED) { | 645 | if (new_event && keycode != KEY_RESERVED) { |
@@ -1011,14 +1005,11 @@ static ssize_t store_protocols(struct device *device, | |||
1011 | set_filter = (fattr->type == RC_FILTER_NORMAL) | 1005 | set_filter = (fattr->type == RC_FILTER_NORMAL) |
1012 | ? dev->s_filter : dev->s_wakeup_filter; | 1006 | ? dev->s_filter : dev->s_wakeup_filter; |
1013 | 1007 | ||
1014 | if (old_type != type && filter->mask) { | 1008 | if (set_filter && old_type != type && filter->mask) { |
1015 | local_filter = *filter; | 1009 | local_filter = *filter; |
1016 | if (!type) { | 1010 | if (!type) { |
1017 | /* no protocol => clear filter */ | 1011 | /* no protocol => clear filter */ |
1018 | ret = -1; | 1012 | ret = -1; |
1019 | } else if (!set_filter) { | ||
1020 | /* generic filtering => accept any filter */ | ||
1021 | ret = 0; | ||
1022 | } else { | 1013 | } else { |
1023 | /* hardware filtering => try setting, otherwise clear */ | 1014 | /* hardware filtering => try setting, otherwise clear */ |
1024 | ret = set_filter(dev, &local_filter); | 1015 | ret = set_filter(dev, &local_filter); |
@@ -1027,8 +1018,7 @@ static ssize_t store_protocols(struct device *device, | |||
1027 | /* clear the filter */ | 1018 | /* clear the filter */ |
1028 | local_filter.data = 0; | 1019 | local_filter.data = 0; |
1029 | local_filter.mask = 0; | 1020 | local_filter.mask = 0; |
1030 | if (set_filter) | 1021 | set_filter(dev, &local_filter); |
1031 | set_filter(dev, &local_filter); | ||
1032 | } | 1022 | } |
1033 | 1023 | ||
1034 | /* commit the new filter */ | 1024 | /* commit the new filter */ |
@@ -1072,7 +1062,10 @@ static ssize_t show_filter(struct device *device, | |||
1072 | return -EINVAL; | 1062 | return -EINVAL; |
1073 | 1063 | ||
1074 | mutex_lock(&dev->lock); | 1064 | mutex_lock(&dev->lock); |
1075 | if (fattr->mask) | 1065 | if ((fattr->type == RC_FILTER_NORMAL && !dev->s_filter) || |
1066 | (fattr->type == RC_FILTER_WAKEUP && !dev->s_wakeup_filter)) | ||
1067 | val = 0; | ||
1068 | else if (fattr->mask) | ||
1076 | val = dev->scancode_filters[fattr->type].mask; | 1069 | val = dev->scancode_filters[fattr->type].mask; |
1077 | else | 1070 | else |
1078 | val = dev->scancode_filters[fattr->type].data; | 1071 | val = dev->scancode_filters[fattr->type].data; |
@@ -1120,12 +1113,11 @@ static ssize_t store_filter(struct device *device, | |||
1120 | if (ret < 0) | 1113 | if (ret < 0) |
1121 | return ret; | 1114 | return ret; |
1122 | 1115 | ||
1116 | /* Can the scancode filter be set? */ | ||
1123 | set_filter = (fattr->type == RC_FILTER_NORMAL) ? dev->s_filter : | 1117 | set_filter = (fattr->type == RC_FILTER_NORMAL) ? dev->s_filter : |
1124 | dev->s_wakeup_filter; | 1118 | dev->s_wakeup_filter; |
1125 | 1119 | if (!set_filter) | |
1126 | /* Scancode filter not supported (but still accept 0) */ | 1120 | return -EINVAL; |
1127 | if (!set_filter && fattr->type == RC_FILTER_WAKEUP) | ||
1128 | return val ? -EINVAL : count; | ||
1129 | 1121 | ||
1130 | mutex_lock(&dev->lock); | 1122 | mutex_lock(&dev->lock); |
1131 | 1123 | ||
@@ -1143,11 +1135,9 @@ static ssize_t store_filter(struct device *device, | |||
1143 | goto unlock; | 1135 | goto unlock; |
1144 | } | 1136 | } |
1145 | 1137 | ||
1146 | if (set_filter) { | 1138 | ret = set_filter(dev, &local_filter); |
1147 | ret = set_filter(dev, &local_filter); | 1139 | if (ret < 0) |
1148 | if (ret < 0) | 1140 | goto unlock; |
1149 | goto unlock; | ||
1150 | } | ||
1151 | 1141 | ||
1152 | /* Success, commit the new filter */ | 1142 | /* Success, commit the new filter */ |
1153 | *filter = local_filter; | 1143 | *filter = local_filter; |
@@ -1199,27 +1189,45 @@ static RC_FILTER_ATTR(wakeup_filter, S_IRUGO|S_IWUSR, | |||
1199 | static RC_FILTER_ATTR(wakeup_filter_mask, S_IRUGO|S_IWUSR, | 1189 | static RC_FILTER_ATTR(wakeup_filter_mask, S_IRUGO|S_IWUSR, |
1200 | show_filter, store_filter, RC_FILTER_WAKEUP, true); | 1190 | show_filter, store_filter, RC_FILTER_WAKEUP, true); |
1201 | 1191 | ||
1202 | static struct attribute *rc_dev_attrs[] = { | 1192 | static struct attribute *rc_dev_protocol_attrs[] = { |
1203 | &dev_attr_protocols.attr.attr, | 1193 | &dev_attr_protocols.attr.attr, |
1194 | NULL, | ||
1195 | }; | ||
1196 | |||
1197 | static struct attribute_group rc_dev_protocol_attr_grp = { | ||
1198 | .attrs = rc_dev_protocol_attrs, | ||
1199 | }; | ||
1200 | |||
1201 | static struct attribute *rc_dev_wakeup_protocol_attrs[] = { | ||
1204 | &dev_attr_wakeup_protocols.attr.attr, | 1202 | &dev_attr_wakeup_protocols.attr.attr, |
1203 | NULL, | ||
1204 | }; | ||
1205 | |||
1206 | static struct attribute_group rc_dev_wakeup_protocol_attr_grp = { | ||
1207 | .attrs = rc_dev_wakeup_protocol_attrs, | ||
1208 | }; | ||
1209 | |||
1210 | static struct attribute *rc_dev_filter_attrs[] = { | ||
1205 | &dev_attr_filter.attr.attr, | 1211 | &dev_attr_filter.attr.attr, |
1206 | &dev_attr_filter_mask.attr.attr, | 1212 | &dev_attr_filter_mask.attr.attr, |
1207 | &dev_attr_wakeup_filter.attr.attr, | ||
1208 | &dev_attr_wakeup_filter_mask.attr.attr, | ||
1209 | NULL, | 1213 | NULL, |
1210 | }; | 1214 | }; |
1211 | 1215 | ||
1212 | static struct attribute_group rc_dev_attr_grp = { | 1216 | static struct attribute_group rc_dev_filter_attr_grp = { |
1213 | .attrs = rc_dev_attrs, | 1217 | .attrs = rc_dev_filter_attrs, |
1214 | }; | 1218 | }; |
1215 | 1219 | ||
1216 | static const struct attribute_group *rc_dev_attr_groups[] = { | 1220 | static struct attribute *rc_dev_wakeup_filter_attrs[] = { |
1217 | &rc_dev_attr_grp, | 1221 | &dev_attr_wakeup_filter.attr.attr, |
1218 | NULL | 1222 | &dev_attr_wakeup_filter_mask.attr.attr, |
1223 | NULL, | ||
1224 | }; | ||
1225 | |||
1226 | static struct attribute_group rc_dev_wakeup_filter_attr_grp = { | ||
1227 | .attrs = rc_dev_wakeup_filter_attrs, | ||
1219 | }; | 1228 | }; |
1220 | 1229 | ||
1221 | static struct device_type rc_dev_type = { | 1230 | static struct device_type rc_dev_type = { |
1222 | .groups = rc_dev_attr_groups, | ||
1223 | .release = rc_dev_release, | 1231 | .release = rc_dev_release, |
1224 | .uevent = rc_dev_uevent, | 1232 | .uevent = rc_dev_uevent, |
1225 | }; | 1233 | }; |
@@ -1276,7 +1284,7 @@ int rc_register_device(struct rc_dev *dev) | |||
1276 | static bool raw_init = false; /* raw decoders loaded? */ | 1284 | static bool raw_init = false; /* raw decoders loaded? */ |
1277 | struct rc_map *rc_map; | 1285 | struct rc_map *rc_map; |
1278 | const char *path; | 1286 | const char *path; |
1279 | int rc, devno; | 1287 | int rc, devno, attr = 0; |
1280 | 1288 | ||
1281 | if (!dev || !dev->map_name) | 1289 | if (!dev || !dev->map_name) |
1282 | return -EINVAL; | 1290 | return -EINVAL; |
@@ -1304,6 +1312,16 @@ int rc_register_device(struct rc_dev *dev) | |||
1304 | return -ENOMEM; | 1312 | return -ENOMEM; |
1305 | } while (test_and_set_bit(devno, ir_core_dev_number)); | 1313 | } while (test_and_set_bit(devno, ir_core_dev_number)); |
1306 | 1314 | ||
1315 | dev->dev.groups = dev->sysfs_groups; | ||
1316 | dev->sysfs_groups[attr++] = &rc_dev_protocol_attr_grp; | ||
1317 | if (dev->s_filter) | ||
1318 | dev->sysfs_groups[attr++] = &rc_dev_filter_attr_grp; | ||
1319 | if (dev->s_wakeup_filter) | ||
1320 | dev->sysfs_groups[attr++] = &rc_dev_wakeup_filter_attr_grp; | ||
1321 | if (dev->change_wakeup_protocol) | ||
1322 | dev->sysfs_groups[attr++] = &rc_dev_wakeup_protocol_attr_grp; | ||
1323 | dev->sysfs_groups[attr++] = NULL; | ||
1324 | |||
1307 | /* | 1325 | /* |
1308 | * Take the lock here, as the device sysfs node will appear | 1326 | * Take the lock here, as the device sysfs node will appear |
1309 | * when device_add() is called, which may trigger an ir-keytable udev | 1327 | * when device_add() is called, which may trigger an ir-keytable udev |