diff options
author | Felix Fietkau <nbd@openwrt.org> | 2014-12-08 12:04:25 +0000 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2014-12-08 12:04:25 +0000 |
commit | 9a495f6bbbcb294b9926f4ec32e5bbb339395d00 (patch) | |
tree | c76b5e53fffd1d6238ba09da9d8bb7a6bde9e474 /target/linux/sunxi/patches-3.14/284-ir-backports-from-3.15.patch | |
parent | 3951f9492f31b59602a9a7c46fbb041be0929be0 (diff) | |
download | upstream-9a495f6bbbcb294b9926f4ec32e5bbb339395d00.tar.gz upstream-9a495f6bbbcb294b9926f4ec32e5bbb339395d00.tar.bz2 upstream-9a495f6bbbcb294b9926f4ec32e5bbb339395d00.zip |
kernel: refresh patches
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
SVN-Revision: 43564
Diffstat (limited to 'target/linux/sunxi/patches-3.14/284-ir-backports-from-3.15.patch')
-rw-r--r-- | target/linux/sunxi/patches-3.14/284-ir-backports-from-3.15.patch | 1478 |
1 files changed, 575 insertions, 903 deletions
diff --git a/target/linux/sunxi/patches-3.14/284-ir-backports-from-3.15.patch b/target/linux/sunxi/patches-3.14/284-ir-backports-from-3.15.patch index 37ccffce7e..9e703e7dce 100644 --- a/target/linux/sunxi/patches-3.14/284-ir-backports-from-3.15.patch +++ b/target/linux/sunxi/patches-3.14/284-ir-backports-from-3.15.patch @@ -31,233 +31,6 @@ Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com> include/media/rc-core.h | 29 +++++++ 3 files changed, 223 insertions(+) -diff --git a/Documentation/ABI/testing/sysfs-class-rc b/Documentation/ABI/testing/sysfs-class-rc -index 52bc057..c0e1d14 100644 -diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c -index f1b67db..fa8b957 100644 ---- a/drivers/media/rc/rc-main.c -+++ b/drivers/media/rc/rc-main.c -@@ -969,6 +969,130 @@ static ssize_t store_protocols(struct device *device, - return ret; - } - -+/** -+ * struct rc_filter_attribute - Device attribute relating to a filter type. -+ * @attr: Device attribute. -+ * @type: Filter type. -+ * @mask: false for filter value, true for filter mask. -+ */ -+struct rc_filter_attribute { -+ struct device_attribute attr; -+ enum rc_filter_type type; -+ bool mask; -+}; -+#define to_rc_filter_attr(a) container_of(a, struct rc_filter_attribute, attr) -+ -+#define RC_FILTER_ATTR(_name, _mode, _show, _store, _type, _mask) \ -+ struct rc_filter_attribute dev_attr_##_name = { \ -+ .attr = __ATTR(_name, _mode, _show, _store), \ -+ .type = (_type), \ -+ .mask = (_mask), \ -+ } -+ -+/** -+ * show_filter() - shows the current scancode filter value or mask -+ * @device: the device descriptor -+ * @attr: the device attribute struct -+ * @buf: a pointer to the output buffer -+ * -+ * This routine is a callback routine to read a scancode filter value or mask. -+ * It is trigged by reading /sys/class/rc/rc?/[wakeup_]filter[_mask]. -+ * It prints the current scancode filter value or mask of the appropriate filter -+ * type in hexadecimal into @buf and returns the size of the buffer. -+ * -+ * Bits of the filter value corresponding to set bits in the filter mask are -+ * compared against input scancodes and non-matching scancodes are discarded. -+ * -+ * dev->lock is taken to guard against races between device registration, -+ * store_filter and show_filter. -+ */ -+static ssize_t show_filter(struct device *device, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct rc_dev *dev = to_rc_dev(device); -+ struct rc_filter_attribute *fattr = to_rc_filter_attr(attr); -+ u32 val; -+ -+ /* Device is being removed */ -+ if (!dev) -+ return -EINVAL; -+ -+ mutex_lock(&dev->lock); -+ if (!dev->s_filter) -+ val = 0; -+ else if (fattr->mask) -+ val = dev->scancode_filters[fattr->type].mask; -+ else -+ val = dev->scancode_filters[fattr->type].data; -+ mutex_unlock(&dev->lock); -+ -+ return sprintf(buf, "%#x\n", val); -+} -+ -+/** -+ * store_filter() - changes the scancode filter value -+ * @device: the device descriptor -+ * @attr: the device attribute struct -+ * @buf: a pointer to the input buffer -+ * @len: length of the input buffer -+ * -+ * This routine is for changing a scancode filter value or mask. -+ * It is trigged by writing to /sys/class/rc/rc?/[wakeup_]filter[_mask]. -+ * Returns -EINVAL if an invalid filter value for the current protocol was -+ * specified or if scancode filtering is not supported by the driver, otherwise -+ * returns @len. -+ * -+ * Bits of the filter value corresponding to set bits in the filter mask are -+ * compared against input scancodes and non-matching scancodes are discarded. -+ * -+ * dev->lock is taken to guard against races between device registration, -+ * store_filter and show_filter. -+ */ -+static ssize_t store_filter(struct device *device, -+ struct device_attribute *attr, -+ const char *buf, -+ size_t count) -+{ -+ struct rc_dev *dev = to_rc_dev(device); -+ struct rc_filter_attribute *fattr = to_rc_filter_attr(attr); -+ struct rc_scancode_filter local_filter, *filter; -+ int ret; -+ unsigned long val; -+ -+ /* Device is being removed */ -+ if (!dev) -+ return -EINVAL; -+ -+ ret = kstrtoul(buf, 0, &val); -+ if (ret < 0) -+ return ret; -+ -+ /* Scancode filter not supported (but still accept 0) */ -+ if (!dev->s_filter) -+ return val ? -EINVAL : count; -+ -+ mutex_lock(&dev->lock); -+ -+ /* Tell the driver about the new filter */ -+ filter = &dev->scancode_filters[fattr->type]; -+ local_filter = *filter; -+ if (fattr->mask) -+ local_filter.mask = val; -+ else -+ local_filter.data = val; -+ ret = dev->s_filter(dev, fattr->type, &local_filter); -+ if (ret < 0) -+ goto unlock; -+ -+ /* Success, commit the new filter */ -+ *filter = local_filter; -+ -+unlock: -+ mutex_unlock(&dev->lock); -+ return count; -+} -+ - static void rc_dev_release(struct device *device) - { - } -@@ -1000,9 +1124,21 @@ static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env) - */ - static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR, - show_protocols, store_protocols); -+static RC_FILTER_ATTR(filter, S_IRUGO|S_IWUSR, -+ show_filter, store_filter, RC_FILTER_NORMAL, false); -+static RC_FILTER_ATTR(filter_mask, S_IRUGO|S_IWUSR, -+ show_filter, store_filter, RC_FILTER_NORMAL, true); -+static RC_FILTER_ATTR(wakeup_filter, S_IRUGO|S_IWUSR, -+ show_filter, store_filter, RC_FILTER_WAKEUP, false); -+static RC_FILTER_ATTR(wakeup_filter_mask, S_IRUGO|S_IWUSR, -+ show_filter, store_filter, RC_FILTER_WAKEUP, true); - - static struct attribute *rc_dev_attrs[] = { - &dev_attr_protocols.attr, -+ &dev_attr_filter.attr.attr, -+ &dev_attr_filter_mask.attr.attr, -+ &dev_attr_wakeup_filter.attr.attr, -+ &dev_attr_wakeup_filter_mask.attr.attr, - NULL, - }; - -diff --git a/include/media/rc-core.h b/include/media/rc-core.h -index 2f6f1f7..4a72176 100644 ---- a/include/media/rc-core.h -+++ b/include/media/rc-core.h -@@ -35,6 +35,29 @@ enum rc_driver_type { - }; - - /** -+ * struct rc_scancode_filter - Filter scan codes. -+ * @data: Scancode data to match. -+ * @mask: Mask of bits of scancode to compare. -+ */ -+struct rc_scancode_filter { -+ u32 data; -+ u32 mask; -+}; -+ -+/** -+ * enum rc_filter_type - Filter type constants. -+ * @RC_FILTER_NORMAL: Filter for normal operation. -+ * @RC_FILTER_WAKEUP: Filter for waking from suspend. -+ * @RC_FILTER_MAX: Number of filter types. -+ */ -+enum rc_filter_type { -+ RC_FILTER_NORMAL = 0, -+ RC_FILTER_WAKEUP, -+ -+ RC_FILTER_MAX -+}; -+ -+/** - * struct rc_dev - represents a remote control device - * @dev: driver model's view of this device - * @input_name: name of the input child device -@@ -70,6 +93,7 @@ enum rc_driver_type { - * @max_timeout: maximum timeout supported by device - * @rx_resolution : resolution (in ns) of input sampler - * @tx_resolution: resolution (in ns) of output sampler -+ * @scancode_filters: scancode filters (indexed by enum rc_filter_type) - * @change_protocol: allow changing the protocol used on hardware decoders - * @open: callback to allow drivers to enable polling/irq when IR input device - * is opened. -@@ -84,6 +108,7 @@ enum rc_driver_type { - * device doesn't interrupt host until it sees IR pulses - * @s_learning_mode: enable wide band receiver used for learning - * @s_carrier_report: enable carrier reports -+ * @s_filter: set the scancode filter of a given type - */ - struct rc_dev { - struct device dev; -@@ -116,6 +141,7 @@ struct rc_dev { - u32 max_timeout; - u32 rx_resolution; - u32 tx_resolution; -+ struct rc_scancode_filter scancode_filters[RC_FILTER_MAX]; - int (*change_protocol)(struct rc_dev *dev, u64 *rc_type); - int (*open)(struct rc_dev *dev); - void (*close)(struct rc_dev *dev); -@@ -127,6 +153,9 @@ struct rc_dev { - void (*s_idle)(struct rc_dev *dev, bool enable); - int (*s_learning_mode)(struct rc_dev *dev, int enable); - int (*s_carrier_report) (struct rc_dev *dev, int enable); -+ int (*s_filter)(struct rc_dev *dev, -+ enum rc_filter_type type, -+ struct rc_scancode_filter *filter); - }; - - #define to_rc_dev(d) container_of(d, struct rc_dev, dev) From 7b802ce7e8c67510389fdbbe29edd87a75df3a93 Mon Sep 17 00:00:00 2001 From: James Hogan <james.hogan@imgtec.com> Date: Mon, 10 Feb 2014 18:31:56 -0300 @@ -281,19 +54,6 @@ Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com> drivers/media/rc/rc-main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c -index 2ec60f8..6448128 100644 ---- a/drivers/media/rc/rc-main.c -+++ b/drivers/media/rc/rc-main.c -@@ -1090,7 +1090,7 @@ static ssize_t store_filter(struct device *device, - - unlock: - mutex_unlock(&dev->lock); -- return count; -+ return (ret < 0) ? ret : count; - } - - static void rc_dev_release(struct device *device) From b8c7d915087c97a21fa415fa0e860e59739da202 Mon Sep 17 00:00:00 2001 From: James Hogan <james.hogan@imgtec.com> Date: Fri, 28 Feb 2014 20:17:02 -0300 @@ -315,65 +75,6 @@ Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com> drivers/media/rc/rc-main.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) -diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c -index 6448128..0a4f680f 100644 ---- a/drivers/media/rc/rc-main.c -+++ b/drivers/media/rc/rc-main.c -@@ -633,6 +633,7 @@ EXPORT_SYMBOL_GPL(rc_repeat); - static void ir_do_keydown(struct rc_dev *dev, int scancode, - u32 keycode, u8 toggle) - { -+ struct rc_scancode_filter *filter; - bool new_event = !dev->keypressed || - dev->last_scancode != scancode || - dev->last_toggle != toggle; -@@ -640,6 +641,11 @@ static void ir_do_keydown(struct rc_dev *dev, int scancode, - if (new_event && dev->keypressed) - ir_do_keyup(dev, false); - -+ /* Generic scancode filtering */ -+ filter = &dev->scancode_filters[RC_FILTER_NORMAL]; -+ if (filter->mask && ((scancode ^ filter->data) & filter->mask)) -+ return; -+ - input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode); - - if (new_event && keycode != KEY_RESERVED) { -@@ -1019,9 +1025,7 @@ static ssize_t show_filter(struct device *device, - return -EINVAL; - - mutex_lock(&dev->lock); -- if (!dev->s_filter) -- val = 0; -- else if (fattr->mask) -+ if (fattr->mask) - val = dev->scancode_filters[fattr->type].mask; - else - val = dev->scancode_filters[fattr->type].data; -@@ -1069,7 +1073,7 @@ static ssize_t store_filter(struct device *device, - return ret; - - /* Scancode filter not supported (but still accept 0) */ -- if (!dev->s_filter) -+ if (!dev->s_filter && fattr->type != RC_FILTER_NORMAL) - return val ? -EINVAL : count; - - mutex_lock(&dev->lock); -@@ -1081,9 +1085,11 @@ static ssize_t store_filter(struct device *device, - local_filter.mask = val; - else - local_filter.data = val; -- ret = dev->s_filter(dev, fattr->type, &local_filter); -- if (ret < 0) -- goto unlock; -+ if (dev->s_filter) { -+ ret = dev->s_filter(dev, fattr->type, &local_filter); -+ if (ret < 0) -+ goto unlock; -+ } - - /* Success, commit the new filter */ - *filter = local_filter; From 1a1934fab0c920f0d3bceeb60c9fe2dae8a56be9 Mon Sep 17 00:00:00 2001 From: James Hogan <james.hogan@imgtec.com> Date: Fri, 28 Feb 2014 20:17:03 -0300 @@ -429,11 +130,114 @@ Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com> include/media/rc-core.h | 22 ++++++++++++++++++++++ 36 files changed, 73 insertions(+), 50 deletions(-) -diff --git a/drivers/hid/hid-picolcd_cir.c b/drivers/hid/hid-picolcd_cir.c -index 59d5eb1..cf1a9f1 100644 +From acff5f24732acc8a55d0a0f0ee1d19442267df63 Mon Sep 17 00:00:00 2001 +From: James Hogan <james.hogan@imgtec.com> +Date: Fri, 28 Feb 2014 20:17:04 -0300 +Subject: [PATCH] [media] rc: add allowed/enabled wakeup protocol masks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Only a single allowed and enabled protocol mask currently exists in +struct rc_dev, however to support a separate wakeup filter protocol two +of each are needed, ideally as an array. + +Therefore make both rc_dev::allowed_protos and rc_dev::enabled_protocols +arrays, update all users to reference the first element +(RC_FILTER_NORMAL), and add a couple more helper functions for drivers +to use for setting the allowed and enabled wakeup protocols. + +We also rename allowed_protos to allowed_protocols while we're at it, +which is more consistent with enabled_protocols. + +Signed-off-by: James Hogan <james.hogan@imgtec.com> +Reviewed-by: Antti Seppälä <a.seppala@gmail.com> +Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com> +--- + drivers/media/rc/rc-main.c | 10 +++++----- + include/media/rc-core.h | 32 ++++++++++++++++++++++++-------- + 2 files changed, 29 insertions(+), 13 deletions(-) + +From ab88c66deace78989aa71cb139284cf7fb227ba4 Mon Sep 17 00:00:00 2001 +From: James Hogan <james.hogan@imgtec.com> +Date: Fri, 28 Feb 2014 20:17:05 -0300 +Subject: [PATCH] [media] rc: add wakeup_protocols sysfs file +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add a wakeup_protocols sysfs file which controls the new +rc_dev::enabled_protocols[RC_FILTER_WAKEUP], which is the mask of +protocols that are used for the wakeup filter. + +A new RC driver callback change_wakeup_protocol() is called to change +the wakeup protocol mask. + +Signed-off-by: James Hogan <james.hogan@imgtec.com> +Reviewed-by: Antti Seppälä <a.seppala@gmail.com> +Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com> +--- + Documentation/ABI/testing/sysfs-class-rc | 23 +++++- + .../DocBook/media/v4l/remote_controllers.xml | 20 +++++- + drivers/media/rc/rc-main.c | 82 +++++++++++++--------- + include/media/rc-core.h | 3 + + 4 files changed, 90 insertions(+), 38 deletions(-) + +From 6bea25af147fcddcd8fd4557f4184c847c5c6ffd Mon Sep 17 00:00:00 2001 +From: James Hogan <james.hogan@imgtec.com> +Date: Fri, 28 Feb 2014 20:17:06 -0300 +Subject: [PATCH] [media] rc-main: automatically refresh filter on protocol + change +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When either of the normal or wakeup filter protocols are changed, +refresh the corresponding scancode filter, i.e. try and set the same +scancode filter with the new protocol. If that fails clear the filter +instead. + +If no protocol was selected the filter is just cleared, and if no +s_filter callback exists the filter is left unmodified. + +Similarly clear the filter mask when the filter is set if no protocol is +currently selected. + +This simplifies driver code which no longer has to explicitly worry +about modifying the filter on a protocol change. This also allows the +change_wakeup_protocol callback to be omitted entirely if there is only +a single available wakeup protocol at a time, since selecting no +protocol will automatically clear the wakeup filter, disabling wakeup. + +Signed-off-by: James Hogan <james.hogan@imgtec.com> +Reviewed-by: Antti Seppälä <a.seppala@gmail.com> +Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com> +--- + drivers/media/rc/rc-main.c | 41 +++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 39 insertions(+), 2 deletions(-) + +From 262912335c823a2bbcc87003ee55d62cc27f4e48 Mon Sep 17 00:00:00 2001 +From: James Hogan <james.hogan@imgtec.com> +Date: Sat, 1 Mar 2014 19:52:25 -0300 +Subject: [PATCH] [media] rc-main: fix missing unlock if no devno left + +While playing with make coccicheck I noticed this message: +drivers/media/rc/rc-main.c:1245:3-9: preceding lock on line 1238 + +It was introduced by commit 587d1b06e07b ([media] rc-core: reuse device +numbers) which returns -ENOMEM after a mutex_lock without first +unlocking it when there are no more device numbers left. The added code +doesn't depend on the device lock, so move it before the lock is taken. + +Signed-off-by: James Hogan <james.hogan@imgtec.com> +Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com> +--- + drivers/media/rc/rc-main.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + --- a/drivers/hid/hid-picolcd_cir.c +++ b/drivers/hid/hid-picolcd_cir.c -@@ -114,7 +114,7 @@ int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report) +@@ -114,7 +114,7 @@ int picolcd_init_cir(struct picolcd_data rdev->priv = data; rdev->driver_type = RC_DRIVER_IR_RAW; @@ -442,11 +246,9 @@ index 59d5eb1..cf1a9f1 100644 rdev->open = picolcd_cir_open; rdev->close = picolcd_cir_close; rdev->input_name = data->hdev->name; -diff --git a/drivers/media/common/siano/smsir.c b/drivers/media/common/siano/smsir.c -index b8c5cad..6d7c0c8 100644 --- a/drivers/media/common/siano/smsir.c +++ b/drivers/media/common/siano/smsir.c -@@ -88,7 +88,7 @@ int sms_ir_init(struct smscore_device_t *coredev) +@@ -88,7 +88,7 @@ int sms_ir_init(struct smscore_device_t dev->priv = coredev; dev->driver_type = RC_DRIVER_IR_RAW; @@ -455,11 +257,9 @@ index b8c5cad..6d7c0c8 100644 dev->map_name = sms_get_board(board_id)->rc_codes; dev->driver_name = MODULE_NAME; -diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c -index 99ee456..c8fe135 100644 --- a/drivers/media/i2c/ir-kbd-i2c.c +++ b/drivers/media/i2c/ir-kbd-i2c.c -@@ -431,8 +431,8 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) +@@ -431,8 +431,8 @@ static int ir_probe(struct i2c_client *c * Initialize the other fields of rc_dev */ rc->map_name = ir->ir_codes; @@ -470,11 +270,9 @@ index 99ee456..c8fe135 100644 if (!rc->driver_name) rc->driver_name = MODULE_NAME; -diff --git a/drivers/media/pci/cx23885/cx23885-input.c b/drivers/media/pci/cx23885/cx23885-input.c -index 8a49e7c..097d0a0 100644 --- a/drivers/media/pci/cx23885/cx23885-input.c +++ b/drivers/media/pci/cx23885/cx23885-input.c -@@ -346,7 +346,7 @@ int cx23885_input_init(struct cx23885_dev *dev) +@@ -346,7 +346,7 @@ int cx23885_input_init(struct cx23885_de } rc->dev.parent = &dev->pci->dev; rc->driver_type = driver_type; @@ -483,11 +281,9 @@ index 8a49e7c..097d0a0 100644 rc->priv = kernel_ir; rc->open = cx23885_input_ir_open; rc->close = cx23885_input_ir_close; -diff --git a/drivers/media/pci/cx88/cx88-input.c b/drivers/media/pci/cx88/cx88-input.c -index f29e18c..f991696 100644 --- a/drivers/media/pci/cx88/cx88-input.c +++ b/drivers/media/pci/cx88/cx88-input.c -@@ -469,7 +469,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) +@@ -469,7 +469,7 @@ int cx88_ir_init(struct cx88_core *core, dev->timeout = 10 * 1000 * 1000; /* 10 ms */ } else { dev->driver_type = RC_DRIVER_SCANCODE; @@ -496,11 +292,9 @@ index f29e18c..f991696 100644 } ir->core = core; -diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c -index 4d6a63f..2df7c55 100644 --- a/drivers/media/rc/ati_remote.c +++ b/drivers/media/rc/ati_remote.c -@@ -784,7 +784,7 @@ static void ati_remote_rc_init(struct ati_remote *ati_remote) +@@ -784,7 +784,7 @@ static void ati_remote_rc_init(struct at rdev->priv = ati_remote; rdev->driver_type = RC_DRIVER_SCANCODE; @@ -509,11 +303,9 @@ index 4d6a63f..2df7c55 100644 rdev->driver_name = "ati_remote"; rdev->open = ati_remote_rc_open; -diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c -index c1444f8..fc9d23f 100644 --- a/drivers/media/rc/ene_ir.c +++ b/drivers/media/rc/ene_ir.c -@@ -1059,7 +1059,7 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) +@@ -1059,7 +1059,7 @@ static int ene_probe(struct pnp_dev *pnp learning_mode_force = false; rdev->driver_type = RC_DRIVER_IR_RAW; @@ -522,11 +314,9 @@ index c1444f8..fc9d23f 100644 rdev->priv = dev; rdev->open = ene_open; rdev->close = ene_close; -diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c -index d6fa441..46b66e5 100644 --- a/drivers/media/rc/fintek-cir.c +++ b/drivers/media/rc/fintek-cir.c -@@ -541,7 +541,7 @@ static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id +@@ -541,7 +541,7 @@ static int fintek_probe(struct pnp_dev * /* Set up the rc device */ rdev->priv = fintek; rdev->driver_type = RC_DRIVER_IR_RAW; @@ -535,11 +325,9 @@ index d6fa441..46b66e5 100644 rdev->open = fintek_open; rdev->close = fintek_close; rdev->input_name = FINTEK_DESCRIPTION; -diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c -index 80c611c..29b5f89 100644 --- a/drivers/media/rc/gpio-ir-recv.c +++ b/drivers/media/rc/gpio-ir-recv.c -@@ -145,9 +145,9 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) +@@ -145,9 +145,9 @@ static int gpio_ir_recv_probe(struct pla rcdev->dev.parent = &pdev->dev; rcdev->driver_name = GPIO_IR_DRIVER_NAME; if (pdata->allowed_protos) @@ -551,11 +339,9 @@ index 80c611c..29b5f89 100644 rcdev->map_name = pdata->map_name ?: RC_MAP_EMPTY; gpio_dev->rcdev = rcdev; -diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c -index a83519a..627ddfd 100644 --- a/drivers/media/rc/iguanair.c +++ b/drivers/media/rc/iguanair.c -@@ -495,7 +495,7 @@ static int iguanair_probe(struct usb_interface *intf, +@@ -494,7 +494,7 @@ static int iguanair_probe(struct usb_int usb_to_input_id(ir->udev, &rc->input_id); rc->dev.parent = &intf->dev; rc->driver_type = RC_DRIVER_IR_RAW; @@ -564,11 +350,9 @@ index a83519a..627ddfd 100644 rc->priv = ir; rc->open = iguanair_open; rc->close = iguanair_close; -diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c -index 822b9f4..6f24e77 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c -@@ -1017,7 +1017,7 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 *rc_type) +@@ -1017,7 +1017,7 @@ static int imon_ir_change_protocol(struc unsigned char ir_proto_packet[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 }; @@ -577,7 +361,7 @@ index 822b9f4..6f24e77 100644 dev_warn(dev, "Looks like you're trying to use an IR protocol " "this device does not support\n"); -@@ -1867,7 +1867,8 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx) +@@ -1867,7 +1867,8 @@ static struct rc_dev *imon_init_rdev(str rdev->priv = ictx; rdev->driver_type = RC_DRIVER_SCANCODE; @@ -587,7 +371,7 @@ index 822b9f4..6f24e77 100644 rdev->change_protocol = imon_ir_change_protocol; rdev->driver_name = MOD_NAME; -@@ -1880,7 +1881,7 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx) +@@ -1880,7 +1881,7 @@ static struct rc_dev *imon_init_rdev(str if (ictx->product == 0xffdc) { imon_get_ffdc_type(ictx); @@ -596,11 +380,9 @@ index 822b9f4..6f24e77 100644 } imon_set_display_type(ictx); -diff --git a/drivers/media/rc/ir-jvc-decoder.c b/drivers/media/rc/ir-jvc-decoder.c -index 3948138..4ea62a1 100644 --- a/drivers/media/rc/ir-jvc-decoder.c +++ b/drivers/media/rc/ir-jvc-decoder.c -@@ -47,7 +47,7 @@ static int ir_jvc_decode(struct rc_dev *dev, struct ir_raw_event ev) +@@ -47,7 +47,7 @@ static int ir_jvc_decode(struct rc_dev * { struct jvc_dec *data = &dev->raw->jvc; @@ -609,11 +391,9 @@ index 3948138..4ea62a1 100644 return 0; if (!is_timing_event(ev)) { -diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c -index ed2c8a1..d731da6 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c -@@ -35,7 +35,7 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) +@@ -35,7 +35,7 @@ static int ir_lirc_decode(struct rc_dev struct lirc_codec *lirc = &dev->raw->lirc; int sample; @@ -622,11 +402,9 @@ index ed2c8a1..d731da6 100644 return 0; if (!dev->raw->lirc.drv || !dev->raw->lirc.drv->rbuf) -diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c -index 9f3c9b5..0c55f79 100644 --- a/drivers/media/rc/ir-mce_kbd-decoder.c +++ b/drivers/media/rc/ir-mce_kbd-decoder.c -@@ -216,7 +216,7 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev) +@@ -216,7 +216,7 @@ static int ir_mce_kbd_decode(struct rc_d u32 scancode; unsigned long delay; @@ -635,11 +413,9 @@ index 9f3c9b5..0c55f79 100644 return 0; if (!is_timing_event(ev)) { -diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c -index e687a42..9de1791 100644 --- a/drivers/media/rc/ir-nec-decoder.c +++ b/drivers/media/rc/ir-nec-decoder.c -@@ -52,7 +52,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev) +@@ -52,7 +52,7 @@ static int ir_nec_decode(struct rc_dev * u8 address, not_address, command, not_command; bool send_32bits = false; @@ -648,11 +424,9 @@ index e687a42..9de1791 100644 return 0; if (!is_timing_event(ev)) { -diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c -index f0656fa..763c9d1 100644 --- a/drivers/media/rc/ir-raw.c +++ b/drivers/media/rc/ir-raw.c -@@ -256,7 +256,7 @@ int ir_raw_event_register(struct rc_dev *dev) +@@ -256,7 +256,7 @@ int ir_raw_event_register(struct rc_dev return -ENOMEM; dev->raw->dev = dev; @@ -661,11 +435,9 @@ index f0656fa..763c9d1 100644 rc = kfifo_alloc(&dev->raw->kfifo, sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE, GFP_KERNEL); -diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c -index 1085e17..4295d9b2 100644 --- a/drivers/media/rc/ir-rc5-decoder.c +++ b/drivers/media/rc/ir-rc5-decoder.c -@@ -52,7 +52,7 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev) +@@ -52,7 +52,7 @@ static int ir_rc5_decode(struct rc_dev * u8 toggle; u32 scancode; @@ -674,7 +446,7 @@ index 1085e17..4295d9b2 100644 return 0; if (!is_timing_event(ev)) { -@@ -128,7 +128,7 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev) +@@ -128,7 +128,7 @@ again: if (data->wanted_bits == RC5X_NBITS) { /* RC5X */ u8 xdata, command, system; @@ -683,7 +455,7 @@ index 1085e17..4295d9b2 100644 data->state = STATE_INACTIVE; return 0; } -@@ -145,7 +145,7 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev) +@@ -145,7 +145,7 @@ again: } else { /* RC5 */ u8 command, system; @@ -692,11 +464,9 @@ index 1085e17..4295d9b2 100644 data->state = STATE_INACTIVE; return 0; } -diff --git a/drivers/media/rc/ir-rc5-sz-decoder.c b/drivers/media/rc/ir-rc5-sz-decoder.c -index 984e5b9..dc18b74 100644 --- a/drivers/media/rc/ir-rc5-sz-decoder.c +++ b/drivers/media/rc/ir-rc5-sz-decoder.c -@@ -48,7 +48,7 @@ static int ir_rc5_sz_decode(struct rc_dev *dev, struct ir_raw_event ev) +@@ -48,7 +48,7 @@ static int ir_rc5_sz_decode(struct rc_de u8 toggle, command, system; u32 scancode; @@ -705,11 +475,9 @@ index 984e5b9..dc18b74 100644 return 0; if (!is_timing_event(ev)) { -diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c -index 7cba7d3..cfbd64e 100644 --- a/drivers/media/rc/ir-rc6-decoder.c +++ b/drivers/media/rc/ir-rc6-decoder.c -@@ -89,9 +89,9 @@ static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev) +@@ -89,9 +89,9 @@ static int ir_rc6_decode(struct rc_dev * u32 scancode; u8 toggle; @@ -722,11 +490,9 @@ index 7cba7d3..cfbd64e 100644 return 0; if (!is_timing_event(ev)) { -diff --git a/drivers/media/rc/ir-sanyo-decoder.c b/drivers/media/rc/ir-sanyo-decoder.c -index e1351ed..eb715f0 100644 --- a/drivers/media/rc/ir-sanyo-decoder.c +++ b/drivers/media/rc/ir-sanyo-decoder.c -@@ -58,7 +58,7 @@ static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev) +@@ -58,7 +58,7 @@ static int ir_sanyo_decode(struct rc_dev u32 scancode; u8 address, command, not_command; @@ -735,13 +501,9 @@ index e1351ed..eb715f0 100644 return 0; if (!is_timing_event(ev)) { -diff --git a/drivers/media/rc/ir-sharp-decoder.c b/drivers/media/rc/ir-sharp-decoder.c -index 4895bc7..66d2039 100644 -diff --git a/drivers/media/rc/ir-sony-decoder.c b/drivers/media/rc/ir-sony-decoder.c -index 29ab9c2..599c19a 100644 --- a/drivers/media/rc/ir-sony-decoder.c +++ b/drivers/media/rc/ir-sony-decoder.c -@@ -45,8 +45,8 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev) +@@ -45,8 +45,8 @@ static int ir_sony_decode(struct rc_dev u32 scancode; u8 device, subdevice, function; @@ -752,7 +514,7 @@ index 29ab9c2..599c19a 100644 return 0; if (!is_timing_event(ev)) { -@@ -124,7 +124,7 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev) +@@ -124,7 +124,7 @@ static int ir_sony_decode(struct rc_dev switch (data->count) { case 12: @@ -761,7 +523,7 @@ index 29ab9c2..599c19a 100644 data->state = STATE_INACTIVE; return 0; } -@@ -133,7 +133,7 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev) +@@ -133,7 +133,7 @@ static int ir_sony_decode(struct rc_dev function = bitrev8((data->bits >> 4) & 0xFE); break; case 15: @@ -770,7 +532,7 @@ index 29ab9c2..599c19a 100644 data->state = STATE_INACTIVE; return 0; } -@@ -142,7 +142,7 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev) +@@ -142,7 +142,7 @@ static int ir_sony_decode(struct rc_dev function = bitrev8((data->bits >> 7) & 0xFE); break; case 20: @@ -779,11 +541,9 @@ index 29ab9c2..599c19a 100644 data->state = STATE_INACTIVE; return 0; } -diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c -index 63b4225..ab24cc6 100644 --- a/drivers/media/rc/ite-cir.c +++ b/drivers/media/rc/ite-cir.c -@@ -1563,7 +1563,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id +@@ -1563,7 +1563,7 @@ static int ite_probe(struct pnp_dev *pde /* set up ir-core props */ rdev->priv = itdev; rdev->driver_type = RC_DRIVER_IR_RAW; @@ -792,11 +552,9 @@ index 63b4225..ab24cc6 100644 rdev->open = ite_open; rdev->close = ite_close; rdev->s_idle = ite_s_idle; -diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c -index c01b4c1..5d8f3d4 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c -@@ -1211,7 +1211,7 @@ static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir) +@@ -1217,7 +1217,7 @@ static struct rc_dev *mceusb_init_rc_dev rc->dev.parent = dev; rc->priv = ir; rc->driver_type = RC_DRIVER_IR_RAW; @@ -805,11 +563,9 @@ index c01b4c1..5d8f3d4 100644 rc->timeout = MS_TO_NS(100); if (!ir->flags.no_tx) { rc->s_tx_mask = mceusb_set_tx_mask; -diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c -index b81325d..d244e1a 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c -@@ -1044,7 +1044,7 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) +@@ -1042,7 +1042,7 @@ static int nvt_probe(struct pnp_dev *pde /* Set up the rc device */ rdev->priv = nvt; rdev->driver_type = RC_DRIVER_IR_RAW; @@ -818,8 +574,6 @@ index b81325d..d244e1a 100644 rdev->open = nvt_open; rdev->close = nvt_close; rdev->tx_ir = nvt_tx_ir; -diff --git a/drivers/media/rc/rc-loopback.c b/drivers/media/rc/rc-loopback.c -index 53d0282..0a88e0c 100644 --- a/drivers/media/rc/rc-loopback.c +++ b/drivers/media/rc/rc-loopback.c @@ -195,7 +195,7 @@ static int __init loop_init(void) @@ -831,352 +585,29 @@ index 53d0282..0a88e0c 100644 rc->timeout = 100 * 1000 * 1000; /* 100 ms */ rc->min_timeout = 1; rc->max_timeout = UINT_MAX; -diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c -index a5d4f88..47cd373 100644 ---- a/drivers/media/rc/redrat3.c -+++ b/drivers/media/rc/redrat3.c -@@ -922,7 +922,7 @@ static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3) - rc->dev.parent = dev; - rc->priv = rr3; - rc->driver_type = RC_DRIVER_IR_RAW; -- rc->allowed_protos = RC_BIT_ALL; -+ rc_set_allowed_protocols(rc, RC_BIT_ALL); - rc->timeout = US_TO_NS(2750); - rc->tx_ir = redrat3_transmit_ir; - rc->s_tx_carrier = redrat3_set_tx_carrier; -diff --git a/drivers/media/rc/st_rc.c b/drivers/media/rc/st_rc.c -index 8f0cddb..22e4c1f 100644 ---- a/drivers/media/rc/st_rc.c -+++ b/drivers/media/rc/st_rc.c -@@ -287,7 +287,7 @@ static int st_rc_probe(struct platform_device *pdev) - st_rc_hardware_init(rc_dev); - - rdev->driver_type = RC_DRIVER_IR_RAW; -- rdev->allowed_protos = RC_BIT_ALL; -+ rc_set_allowed_protocols(rdev, RC_BIT_ALL); - /* rx sampling rate is 10Mhz */ - rdev->rx_resolution = 100; - rdev->timeout = US_TO_NS(MAX_SYMB_TIME); -diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c -index d7b11e6..f4e0bc3 100644 ---- a/drivers/media/rc/streamzap.c -+++ b/drivers/media/rc/streamzap.c -@@ -322,7 +322,7 @@ static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz) - rdev->dev.parent = dev; - rdev->priv = sz; - rdev->driver_type = RC_DRIVER_IR_RAW; -- rdev->allowed_protos = RC_BIT_ALL; -+ rc_set_allowed_protocols(rdev, RC_BIT_ALL); - rdev->driver_name = DRIVER_NAME; - rdev->map_name = RC_MAP_STREAMZAP; - -diff --git a/drivers/media/rc/ttusbir.c b/drivers/media/rc/ttusbir.c -index d8de205..c5be38e 100644 ---- a/drivers/media/rc/ttusbir.c -+++ b/drivers/media/rc/ttusbir.c -@@ -318,7 +318,7 @@ static int ttusbir_probe(struct usb_interface *intf, - usb_to_input_id(tt->udev, &rc->input_id); - rc->dev.parent = &intf->dev; - rc->driver_type = RC_DRIVER_IR_RAW; -- rc->allowed_protos = RC_BIT_ALL; -+ rc_set_allowed_protocols(rc, RC_BIT_ALL); - rc->priv = tt; - rc->driver_name = DRIVER_NAME; - rc->map_name = RC_MAP_TT_1500; -diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c -index 904baf4..a8b981f 100644 ---- a/drivers/media/rc/winbond-cir.c -+++ b/drivers/media/rc/winbond-cir.c -@@ -1082,7 +1082,7 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id) - data->dev->dev.parent = &device->dev; - data->dev->timeout = MS_TO_NS(100); - data->dev->rx_resolution = US_TO_NS(2); -- data->dev->allowed_protos = RC_BIT_ALL; -+ rc_set_allowed_protocols(data->dev, RC_BIT_ALL); - - err = rc_register_device(data->dev); - if (err) -diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c -index 8a054d6..de02db8 100644 ---- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c -+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c -@@ -164,7 +164,7 @@ static int dvb_usbv2_remote_init(struct dvb_usb_device *d) - dev->driver_name = (char *) d->props->driver_name; - dev->map_name = d->rc.map_name; - dev->driver_type = d->rc.driver_type; -- dev->allowed_protos = d->rc.allowed_protos; -+ rc_set_allowed_protocols(dev, d->rc.allowed_protos); - dev->change_protocol = d->rc.change_protocol; - dev->priv = d; - -diff --git a/drivers/media/usb/dvb-usb/dvb-usb-remote.c b/drivers/media/usb/dvb-usb/dvb-usb-remote.c -index 41bacff..4058aea 100644 ---- a/drivers/media/usb/dvb-usb/dvb-usb-remote.c -+++ b/drivers/media/usb/dvb-usb/dvb-usb-remote.c -@@ -272,7 +272,7 @@ static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d) - dev->driver_name = d->props.rc.core.module_name; - dev->map_name = d->props.rc.core.rc_codes; - dev->change_protocol = d->props.rc.core.change_protocol; -- dev->allowed_protos = d->props.rc.core.allowed_protos; -+ rc_set_allowed_protocols(dev, d->props.rc.core.allowed_protos); - dev->driver_type = d->props.rc.core.driver_type; - usb_to_input_id(d->udev, &dev->input_id); - dev->input_name = "IR-receiver inside an USB DVB receiver"; -diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c -index 2a9bf66..56ef49d 100644 ---- a/drivers/media/usb/em28xx/em28xx-input.c -+++ b/drivers/media/usb/em28xx/em28xx-input.c -@@ -727,7 +727,7 @@ static int em28xx_ir_init(struct em28xx *dev) - case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: - rc->map_name = RC_MAP_HAUPPAUGE; - ir->get_key_i2c = em28xx_get_key_em_haup; -- rc->allowed_protos = RC_BIT_RC5; -+ rc_set_allowed_protocols(rc, RC_BIT_RC5); - break; - case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE: - rc->map_name = RC_MAP_WINFAST_USBII_DELUXE; -@@ -743,7 +743,7 @@ static int em28xx_ir_init(struct em28xx *dev) - switch (dev->chip_id) { - case CHIP_ID_EM2860: - case CHIP_ID_EM2883: -- rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC; -+ rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC); - ir->get_key = default_polling_getkey; - break; - case CHIP_ID_EM2884: -@@ -751,8 +751,8 @@ static int em28xx_ir_init(struct em28xx *dev) - case CHIP_ID_EM28174: - case CHIP_ID_EM28178: - ir->get_key = em2874_polling_getkey; -- rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC | -- RC_BIT_RC6_0; -+ rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC | -+ RC_BIT_RC6_0); - break; - default: - err = -ENODEV; -diff --git a/drivers/media/usb/tm6000/tm6000-input.c b/drivers/media/usb/tm6000/tm6000-input.c -index 8a6bbf1..d1af543 100644 ---- a/drivers/media/usb/tm6000/tm6000-input.c -+++ b/drivers/media/usb/tm6000/tm6000-input.c -@@ -422,7 +422,7 @@ int tm6000_ir_init(struct tm6000_core *dev) - ir->rc = rc; - - /* input setup */ -- rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC; -+ rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC); - /* Neded, in order to support NEC remotes with 24 or 32 bits */ - rc->scanmask = 0xffff; - rc->priv = ir; -diff --git a/include/media/rc-core.h b/include/media/rc-core.h -index 5e7197e..6f3c3d9 100644 ---- a/include/media/rc-core.h -+++ b/include/media/rc-core.h -@@ -160,6 +160,28 @@ struct rc_dev { - - #define to_rc_dev(d) container_of(d, struct rc_dev, dev) - -+static inline bool rc_protocols_allowed(struct rc_dev *rdev, u64 protos) -+{ -+ return rdev->allowed_protos & protos; -+} -+ -+/* should be called prior to registration or with mutex held */ -+static inline void rc_set_allowed_protocols(struct rc_dev *rdev, u64 protos) -+{ -+ rdev->allowed_protos = protos; -+} -+ -+static inline bool rc_protocols_enabled(struct rc_dev *rdev, u64 protos) -+{ -+ return rdev->enabled_protocols & protos; -+} -+ -+/* should be called prior to registration or with mutex held */ -+static inline void rc_set_enabled_protocols(struct rc_dev *rdev, u64 protos) -+{ -+ rdev->enabled_protocols = protos; -+} -+ - /* - * From rc-main.c - * Those functions can be used on any type of Remote Controller. They -From acff5f24732acc8a55d0a0f0ee1d19442267df63 Mon Sep 17 00:00:00 2001 -From: James Hogan <james.hogan@imgtec.com> -Date: Fri, 28 Feb 2014 20:17:04 -0300 -Subject: [PATCH] [media] rc: add allowed/enabled wakeup protocol masks -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Only a single allowed and enabled protocol mask currently exists in -struct rc_dev, however to support a separate wakeup filter protocol two -of each are needed, ideally as an array. - -Therefore make both rc_dev::allowed_protos and rc_dev::enabled_protocols -arrays, update all users to reference the first element -(RC_FILTER_NORMAL), and add a couple more helper functions for drivers -to use for setting the allowed and enabled wakeup protocols. - -We also rename allowed_protos to allowed_protocols while we're at it, -which is more consistent with enabled_protocols. - -Signed-off-by: James Hogan <james.hogan@imgtec.com> -Reviewed-by: Antti Seppälä <a.seppala@gmail.com> -Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com> ---- - drivers/media/rc/rc-main.c | 10 +++++----- - include/media/rc-core.h | 32 ++++++++++++++++++++++++-------- - 2 files changed, 29 insertions(+), 13 deletions(-) - -diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c -index 0a4f680f..309d791 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c -@@ -830,9 +830,9 @@ static ssize_t show_protocols(struct device *device, - - mutex_lock(&dev->lock); - -- enabled = dev->enabled_protocols; -+ enabled = dev->enabled_protocols[RC_FILTER_NORMAL]; - if (dev->driver_type == RC_DRIVER_SCANCODE) -- allowed = dev->allowed_protos; -+ allowed = dev->allowed_protocols[RC_FILTER_NORMAL]; - else if (dev->raw) - allowed = ir_raw_get_allowed_protocols(); - else { -@@ -906,7 +906,7 @@ static ssize_t store_protocols(struct device *device, - ret = -EINVAL; - goto out; - } -- type = dev->enabled_protocols; -+ type = dev->enabled_protocols[RC_FILTER_NORMAL]; - - while ((tmp = strsep((char **) &data, " \n")) != NULL) { - if (!*tmp) -@@ -964,7 +964,7 @@ static ssize_t store_protocols(struct device *device, - } - } - -- dev->enabled_protocols = type; -+ dev->enabled_protocols[RC_FILTER_NORMAL] = type; - IR_dprintk(1, "Current protocol(s): 0x%llx\n", - (long long)type); - -@@ -1316,7 +1316,7 @@ int rc_register_device(struct rc_dev *dev) - rc = dev->change_protocol(dev, &rc_type); - if (rc < 0) - goto out_raw; -- dev->enabled_protocols = rc_type; -+ dev->enabled_protocols[RC_FILTER_NORMAL] = rc_type; - } - - mutex_unlock(&dev->lock); -diff --git a/include/media/rc-core.h b/include/media/rc-core.h -index 6f3c3d9..f165115 100644 ---- a/include/media/rc-core.h -+++ b/include/media/rc-core.h -@@ -73,8 +73,10 @@ enum rc_filter_type { - * @input_dev: the input child device used to communicate events to userspace - * @driver_type: specifies if protocol decoding is done in hardware or software - * @idle: used to keep track of RX state -- * @allowed_protos: bitmask with the supported RC_BIT_* protocols -- * @enabled_protocols: bitmask with the enabled RC_BIT_* protocols -+ * @allowed_protocols: bitmask with the supported RC_BIT_* protocols for each -+ * filter type -+ * @enabled_protocols: bitmask with the enabled RC_BIT_* protocols for each -+ * filter type - * @scanmask: some hardware decoders are not capable of providing the full - * scancode to the application. As this is a hardware limit, we can't do - * anything with it. Yet, as the same keycode table can be used with other -@@ -124,8 +126,8 @@ struct rc_dev { - struct input_dev *input_dev; - enum rc_driver_type driver_type; - bool idle; -- u64 allowed_protos; -- u64 enabled_protocols; -+ u64 allowed_protocols[RC_FILTER_MAX]; -+ u64 enabled_protocols[RC_FILTER_MAX]; - u32 users; - u32 scanmask; - void *priv; -@@ -162,24 +164,38 @@ struct rc_dev { - - static inline bool rc_protocols_allowed(struct rc_dev *rdev, u64 protos) - { -- return rdev->allowed_protos & protos; -+ return rdev->allowed_protocols[RC_FILTER_NORMAL] & protos; - } - - /* should be called prior to registration or with mutex held */ - static inline void rc_set_allowed_protocols(struct rc_dev *rdev, u64 protos) - { -- rdev->allowed_protos = protos; -+ rdev->allowed_protocols[RC_FILTER_NORMAL] = protos; - } - - static inline bool rc_protocols_enabled(struct rc_dev *rdev, u64 protos) +@@ -633,6 +633,7 @@ EXPORT_SYMBOL_GPL(rc_repeat); + static void ir_do_keydown(struct rc_dev *dev, int scancode, + u32 keycode, u8 toggle) { -- return rdev->enabled_protocols & protos; -+ return rdev->enabled_protocols[RC_FILTER_NORMAL] & protos; - } ++ struct rc_scancode_filter *filter; + bool new_event = !dev->keypressed || + dev->last_scancode != scancode || + dev->last_toggle != toggle; +@@ -640,6 +641,11 @@ static void ir_do_keydown(struct rc_dev + if (new_event && dev->keypressed) + ir_do_keyup(dev, false); - /* should be called prior to registration or with mutex held */ - static inline void rc_set_enabled_protocols(struct rc_dev *rdev, u64 protos) - { -- rdev->enabled_protocols = protos; -+ rdev->enabled_protocols[RC_FILTER_NORMAL] = protos; -+} -+ -+/* should be called prior to registration or with mutex held */ -+static inline void rc_set_allowed_wakeup_protocols(struct rc_dev *rdev, -+ u64 protos) -+{ -+ rdev->allowed_protocols[RC_FILTER_WAKEUP] = protos; -+} ++ /* Generic scancode filtering */ ++ filter = &dev->scancode_filters[RC_FILTER_NORMAL]; ++ if (filter->mask && ((scancode ^ filter->data) & filter->mask)) ++ return; + -+/* should be called prior to registration or with mutex held */ -+static inline void rc_set_enabled_wakeup_protocols(struct rc_dev *rdev, -+ u64 protos) -+{ -+ rdev->enabled_protocols[RC_FILTER_WAKEUP] = protos; - } + input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode); - /* -From ab88c66deace78989aa71cb139284cf7fb227ba4 Mon Sep 17 00:00:00 2001 -From: James Hogan <james.hogan@imgtec.com> -Date: Fri, 28 Feb 2014 20:17:05 -0300 -Subject: [PATCH] [media] rc: add wakeup_protocols sysfs file -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add a wakeup_protocols sysfs file which controls the new -rc_dev::enabled_protocols[RC_FILTER_WAKEUP], which is the mask of -protocols that are used for the wakeup filter. - -A new RC driver callback change_wakeup_protocol() is called to change -the wakeup protocol mask. - -Signed-off-by: James Hogan <james.hogan@imgtec.com> -Reviewed-by: Antti Seppälä <a.seppala@gmail.com> -Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com> ---- - Documentation/ABI/testing/sysfs-class-rc | 23 +++++- - .../DocBook/media/v4l/remote_controllers.xml | 20 +++++- - drivers/media/rc/rc-main.c | 82 +++++++++++++--------- - include/media/rc-core.h | 3 + - 4 files changed, 90 insertions(+), 38 deletions(-) - -diff --git a/Documentation/ABI/testing/sysfs-class-rc b/Documentation/ABI/testing/sysfs-class-rc -index c0e1d14..b65674d 100644 -diff --git a/Documentation/DocBook/media/v4l/remote_controllers.xml b/Documentation/DocBook/media/v4l/remote_controllers.xml -index c440a81..5124a6c 100644 -diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c -index 309d791..e6e3ec7 100644 ---- a/drivers/media/rc/rc-main.c -+++ b/drivers/media/rc/rc-main.c -@@ -803,13 +803,38 @@ static struct { + if (new_event && keycode != KEY_RESERVED) { +@@ -795,13 +801,38 @@ static struct { }; /** @@ -1217,7 +648,7 @@ index 309d791..e6e3ec7 100644 * It returns the protocol names of supported protocols. * Enabled protocols are printed in brackets. * -@@ -820,6 +845,7 @@ static ssize_t show_protocols(struct device *device, +@@ -812,6 +843,7 @@ static ssize_t show_protocols(struct dev struct device_attribute *mattr, char *buf) { struct rc_dev *dev = to_rc_dev(device); @@ -1225,13 +656,13 @@ index 309d791..e6e3ec7 100644 u64 allowed, enabled; char *tmp = buf; int i; -@@ -830,9 +856,10 @@ static ssize_t show_protocols(struct device *device, +@@ -822,9 +854,10 @@ static ssize_t show_protocols(struct dev mutex_lock(&dev->lock); -- enabled = dev->enabled_protocols[RC_FILTER_NORMAL]; +- enabled = dev->enabled_protocols; - if (dev->driver_type == RC_DRIVER_SCANCODE) -- allowed = dev->allowed_protocols[RC_FILTER_NORMAL]; +- allowed = dev->allowed_protos; + enabled = dev->enabled_protocols[fattr->type]; + if (dev->driver_type == RC_DRIVER_SCANCODE || + fattr->type == RC_FILTER_WAKEUP) @@ -1239,7 +670,7 @@ index 309d791..e6e3ec7 100644 else if (dev->raw) allowed = ir_raw_get_allowed_protocols(); else { -@@ -864,14 +891,14 @@ static ssize_t show_protocols(struct device *device, +@@ -856,14 +889,14 @@ static ssize_t show_protocols(struct dev } /** @@ -1256,31 +687,34 @@ index 309d791..e6e3ec7 100644 * Writing "+proto" will add a protocol to the list of enabled protocols. * Writing "-proto" will remove a protocol from the list of enabled protocols. * Writing "proto" will enable only "proto". -@@ -888,12 +915,14 @@ static ssize_t store_protocols(struct device *device, +@@ -880,12 +913,15 @@ static ssize_t store_protocols(struct de size_t len) { struct rc_dev *dev = to_rc_dev(device); + struct rc_filter_attribute *fattr = to_rc_filter_attr(mattr); bool enable, disable; const char *tmp; - u64 type; +- u64 type; ++ u64 old_type, type; u64 mask; int rc, i, count = 0; ssize_t ret; + int (*change_protocol)(struct rc_dev *dev, u64 *rc_type); ++ struct rc_scancode_filter local_filter, *filter; /* Device is being removed */ if (!dev) -@@ -906,7 +935,7 @@ static ssize_t store_protocols(struct device *device, +@@ -898,7 +934,8 @@ static ssize_t store_protocols(struct de ret = -EINVAL; goto out; } -- type = dev->enabled_protocols[RC_FILTER_NORMAL]; -+ type = dev->enabled_protocols[fattr->type]; +- type = dev->enabled_protocols; ++ old_type = dev->enabled_protocols[fattr->type]; ++ type = old_type; while ((tmp = strsep((char **) &data, " \n")) != NULL) { if (!*tmp) -@@ -954,8 +983,10 @@ static ssize_t store_protocols(struct device *device, +@@ -946,8 +983,10 @@ static ssize_t store_protocols(struct de goto out; } @@ -1293,151 +727,15 @@ index 309d791..e6e3ec7 100644 if (rc < 0) { IR_dprintk(1, "Error setting protocols to 0x%llx\n", (long long)type); -@@ -964,7 +995,7 @@ static ssize_t store_protocols(struct device *device, +@@ -956,10 +995,40 @@ static ssize_t store_protocols(struct de } } -- dev->enabled_protocols[RC_FILTER_NORMAL] = type; +- dev->enabled_protocols = type; + dev->enabled_protocols[fattr->type] = type; IR_dprintk(1, "Current protocol(s): 0x%llx\n", (long long)type); -@@ -976,26 +1007,6 @@ static ssize_t store_protocols(struct device *device, - } - - /** -- * struct rc_filter_attribute - Device attribute relating to a filter type. -- * @attr: Device attribute. -- * @type: Filter type. -- * @mask: false for filter value, true for filter mask. -- */ --struct rc_filter_attribute { -- struct device_attribute attr; -- enum rc_filter_type type; -- bool mask; --}; --#define to_rc_filter_attr(a) container_of(a, struct rc_filter_attribute, attr) -- --#define RC_FILTER_ATTR(_name, _mode, _show, _store, _type, _mask) \ -- struct rc_filter_attribute dev_attr_##_name = { \ -- .attr = __ATTR(_name, _mode, _show, _store), \ -- .type = (_type), \ -- .mask = (_mask), \ -- } -- --/** - * show_filter() - shows the current scancode filter value or mask - * @device: the device descriptor - * @attr: the device attribute struct -@@ -1128,8 +1139,10 @@ static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env) - /* - * Static device attribute struct with the sysfs attributes for IR's - */ --static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR, -- show_protocols, store_protocols); -+static RC_PROTO_ATTR(protocols, S_IRUGO | S_IWUSR, -+ show_protocols, store_protocols, RC_FILTER_NORMAL); -+static RC_PROTO_ATTR(wakeup_protocols, S_IRUGO | S_IWUSR, -+ show_protocols, store_protocols, RC_FILTER_WAKEUP); - static RC_FILTER_ATTR(filter, S_IRUGO|S_IWUSR, - show_filter, store_filter, RC_FILTER_NORMAL, false); - static RC_FILTER_ATTR(filter_mask, S_IRUGO|S_IWUSR, -@@ -1140,7 +1153,8 @@ static RC_FILTER_ATTR(wakeup_filter_mask, S_IRUGO|S_IWUSR, - show_filter, store_filter, RC_FILTER_WAKEUP, true); - - static struct attribute *rc_dev_attrs[] = { -- &dev_attr_protocols.attr, -+ &dev_attr_protocols.attr.attr, -+ &dev_attr_wakeup_protocols.attr.attr, - &dev_attr_filter.attr.attr, - &dev_attr_filter_mask.attr.attr, - &dev_attr_wakeup_filter.attr.attr, -diff --git a/include/media/rc-core.h b/include/media/rc-core.h -index f165115..0b9f890 100644 ---- a/include/media/rc-core.h -+++ b/include/media/rc-core.h -@@ -97,6 +97,8 @@ enum rc_filter_type { - * @tx_resolution: resolution (in ns) of output sampler - * @scancode_filters: scancode filters (indexed by enum rc_filter_type) - * @change_protocol: allow changing the protocol used on hardware decoders -+ * @change_wakeup_protocol: allow changing the protocol used for wakeup -+ * filtering - * @open: callback to allow drivers to enable polling/irq when IR input device - * is opened. - * @close: callback to allow drivers to disable polling/irq when IR input device -@@ -145,6 +147,7 @@ struct rc_dev { - u32 tx_resolution; - struct rc_scancode_filter scancode_filters[RC_FILTER_MAX]; - int (*change_protocol)(struct rc_dev *dev, u64 *rc_type); -+ int (*change_wakeup_protocol)(struct rc_dev *dev, u64 *rc_type); - int (*open)(struct rc_dev *dev); - void (*close)(struct rc_dev *dev); - int (*s_tx_mask)(struct rc_dev *dev, u32 mask); -From 6bea25af147fcddcd8fd4557f4184c847c5c6ffd Mon Sep 17 00:00:00 2001 -From: James Hogan <james.hogan@imgtec.com> -Date: Fri, 28 Feb 2014 20:17:06 -0300 -Subject: [PATCH] [media] rc-main: automatically refresh filter on protocol - change -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When either of the normal or wakeup filter protocols are changed, -refresh the corresponding scancode filter, i.e. try and set the same -scancode filter with the new protocol. If that fails clear the filter -instead. - -If no protocol was selected the filter is just cleared, and if no -s_filter callback exists the filter is left unmodified. - -Similarly clear the filter mask when the filter is set if no protocol is -currently selected. - -This simplifies driver code which no longer has to explicitly worry -about modifying the filter on a protocol change. This also allows the -change_wakeup_protocol callback to be omitted entirely if there is only -a single available wakeup protocol at a time, since selecting no -protocol will automatically clear the wakeup filter, disabling wakeup. - -Signed-off-by: James Hogan <james.hogan@imgtec.com> -Reviewed-by: Antti Seppälä <a.seppala@gmail.com> -Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com> ---- - drivers/media/rc/rc-main.c | 41 +++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 39 insertions(+), 2 deletions(-) - -diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c -index e6e3ec7..b1a6900 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, - struct rc_filter_attribute *fattr = to_rc_filter_attr(mattr); - bool enable, disable; - const char *tmp; -- u64 type; -+ u64 old_type, type; - u64 mask; - int rc, i, count = 0; - ssize_t ret; - int (*change_protocol)(struct rc_dev *dev, u64 *rc_type); -+ struct rc_scancode_filter local_filter, *filter; - - /* Device is being removed */ - if (!dev) -@@ -935,7 +936,8 @@ static ssize_t store_protocols(struct device *device, - ret = -EINVAL; - goto out; - } -- type = dev->enabled_protocols[fattr->type]; -+ old_type = dev->enabled_protocols[fattr->type]; -+ type = old_type; - - while ((tmp = strsep((char **) &data, " \n")) != NULL) { - if (!*tmp) -@@ -999,6 +1001,36 @@ static ssize_t store_protocols(struct device *device, - IR_dprintk(1, "Current protocol(s): 0x%llx\n", - (long long)type); - + /* + * If the protocol is changed the filter needs updating. + * Try setting the same filter with the new protocol (if any). @@ -1471,42 +769,153 @@ index e6e3ec7..b1a6900 100644 ret = len; out: -@@ -1096,6 +1128,11 @@ static ssize_t store_filter(struct device *device, - local_filter.mask = val; - else - local_filter.data = val; +@@ -967,6 +1036,115 @@ out: + return ret; + } + ++/** ++ * show_filter() - shows the current scancode filter value or mask ++ * @device: the device descriptor ++ * @attr: the device attribute struct ++ * @buf: a pointer to the output buffer ++ * ++ * This routine is a callback routine to read a scancode filter value or mask. ++ * It is trigged by reading /sys/class/rc/rc?/[wakeup_]filter[_mask]. ++ * It prints the current scancode filter value or mask of the appropriate filter ++ * type in hexadecimal into @buf and returns the size of the buffer. ++ * ++ * Bits of the filter value corresponding to set bits in the filter mask are ++ * compared against input scancodes and non-matching scancodes are discarded. ++ * ++ * dev->lock is taken to guard against races between device registration, ++ * store_filter and show_filter. ++ */ ++static ssize_t show_filter(struct device *device, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct rc_dev *dev = to_rc_dev(device); ++ struct rc_filter_attribute *fattr = to_rc_filter_attr(attr); ++ u32 val; ++ ++ /* Device is being removed */ ++ if (!dev) ++ return -EINVAL; ++ ++ mutex_lock(&dev->lock); ++ if (fattr->mask) ++ val = dev->scancode_filters[fattr->type].mask; ++ else ++ val = dev->scancode_filters[fattr->type].data; ++ mutex_unlock(&dev->lock); ++ ++ return sprintf(buf, "%#x\n", val); ++} ++ ++/** ++ * store_filter() - changes the scancode filter value ++ * @device: the device descriptor ++ * @attr: the device attribute struct ++ * @buf: a pointer to the input buffer ++ * @len: length of the input buffer ++ * ++ * This routine is for changing a scancode filter value or mask. ++ * It is trigged by writing to /sys/class/rc/rc?/[wakeup_]filter[_mask]. ++ * Returns -EINVAL if an invalid filter value for the current protocol was ++ * specified or if scancode filtering is not supported by the driver, otherwise ++ * returns @len. ++ * ++ * Bits of the filter value corresponding to set bits in the filter mask are ++ * compared against input scancodes and non-matching scancodes are discarded. ++ * ++ * dev->lock is taken to guard against races between device registration, ++ * store_filter and show_filter. ++ */ ++static ssize_t store_filter(struct device *device, ++ struct device_attribute *attr, ++ const char *buf, ++ size_t count) ++{ ++ struct rc_dev *dev = to_rc_dev(device); ++ struct rc_filter_attribute *fattr = to_rc_filter_attr(attr); ++ struct rc_scancode_filter local_filter, *filter; ++ int ret; ++ unsigned long val; ++ ++ /* Device is being removed */ ++ if (!dev) ++ return -EINVAL; ++ ++ ret = kstrtoul(buf, 0, &val); ++ if (ret < 0) ++ return ret; ++ ++ /* Scancode filter not supported (but still accept 0) */ ++ if (!dev->s_filter && fattr->type != RC_FILTER_NORMAL) ++ return val ? -EINVAL : count; ++ ++ mutex_lock(&dev->lock); ++ ++ /* Tell the driver about the new filter */ ++ filter = &dev->scancode_filters[fattr->type]; ++ local_filter = *filter; ++ if (fattr->mask) ++ local_filter.mask = val; ++ else ++ local_filter.data = val; + if (!dev->enabled_protocols[fattr->type] && local_filter.mask) { + /* refuse to set a filter unless a protocol is enabled */ + ret = -EINVAL; + goto unlock; + } - if (dev->s_filter) { - ret = dev->s_filter(dev, fattr->type, &local_filter); - if (ret < 0) -From 262912335c823a2bbcc87003ee55d62cc27f4e48 Mon Sep 17 00:00:00 2001 -From: James Hogan <james.hogan@imgtec.com> -Date: Sat, 1 Mar 2014 19:52:25 -0300 -Subject: [PATCH] [media] rc-main: fix missing unlock if no devno left - -While playing with make coccicheck I noticed this message: -drivers/media/rc/rc-main.c:1245:3-9: preceding lock on line 1238 - -It was introduced by commit 587d1b06e07b ([media] rc-core: reuse device -numbers) which returns -ENOMEM after a mutex_lock without first -unlocking it when there are no more device numbers left. The added code -doesn't depend on the device lock, so move it before the lock is taken. - -Signed-off-by: James Hogan <james.hogan@imgtec.com> -Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com> ---- - drivers/media/rc/rc-main.c | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - -diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c -index b1a6900..f87e0f0 100644 ---- a/drivers/media/rc/rc-main.c -+++ b/drivers/media/rc/rc-main.c -@@ -1286,14 +1286,6 @@ int rc_register_device(struct rc_dev *dev) ++ if (dev->s_filter) { ++ ret = dev->s_filter(dev, fattr->type, &local_filter); ++ if (ret < 0) ++ goto unlock; ++ } ++ ++ /* Success, commit the new filter */ ++ *filter = local_filter; ++ ++unlock: ++ mutex_unlock(&dev->lock); ++ return (ret < 0) ? ret : count; ++} ++ + static void rc_dev_release(struct device *device) + { + } +@@ -996,11 +1174,26 @@ static int rc_dev_uevent(struct device * + /* + * Static device attribute struct with the sysfs attributes for IR's + */ +-static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR, +- show_protocols, store_protocols); ++static RC_PROTO_ATTR(protocols, S_IRUGO | S_IWUSR, ++ show_protocols, store_protocols, RC_FILTER_NORMAL); ++static RC_PROTO_ATTR(wakeup_protocols, S_IRUGO | S_IWUSR, ++ show_protocols, store_protocols, RC_FILTER_WAKEUP); ++static RC_FILTER_ATTR(filter, S_IRUGO|S_IWUSR, ++ show_filter, store_filter, RC_FILTER_NORMAL, false); ++static RC_FILTER_ATTR(filter_mask, S_IRUGO|S_IWUSR, ++ show_filter, store_filter, RC_FILTER_NORMAL, true); ++static RC_FILTER_ATTR(wakeup_filter, S_IRUGO|S_IWUSR, ++ show_filter, store_filter, RC_FILTER_WAKEUP, false); ++static RC_FILTER_ATTR(wakeup_filter_mask, S_IRUGO|S_IWUSR, ++ show_filter, store_filter, RC_FILTER_WAKEUP, true); + + static struct attribute *rc_dev_attrs[] = { +- &dev_attr_protocols.attr, ++ &dev_attr_protocols.attr.attr, ++ &dev_attr_wakeup_protocols.attr.attr, ++ &dev_attr_filter.attr.attr, ++ &dev_attr_filter_mask.attr.attr, ++ &dev_attr_wakeup_filter.attr.attr, ++ &dev_attr_wakeup_filter_mask.attr.attr, + NULL, + }; + +@@ -1091,14 +1284,6 @@ int rc_register_device(struct rc_dev *de if (dev->close) dev->input_dev->close = ir_close; @@ -1521,7 +930,7 @@ index b1a6900..f87e0f0 100644 do { devno = find_first_zero_bit(ir_core_dev_number, IRRCV_NUM_DEVICES); -@@ -1302,6 +1294,14 @@ int rc_register_device(struct rc_dev *dev) +@@ -1107,6 +1292,14 @@ int rc_register_device(struct rc_dev *de return -ENOMEM; } while (test_and_set_bit(devno, ir_core_dev_number)); @@ -1536,3 +945,266 @@ index b1a6900..f87e0f0 100644 dev->devno = devno; dev_set_name(&dev->dev, "rc%ld", dev->devno); dev_set_drvdata(&dev->dev, dev); +@@ -1172,7 +1365,7 @@ int rc_register_device(struct rc_dev *de + rc = dev->change_protocol(dev, &rc_type); + if (rc < 0) + goto out_raw; +- dev->enabled_protocols = rc_type; ++ dev->enabled_protocols[RC_FILTER_NORMAL] = rc_type; + } + + mutex_unlock(&dev->lock); +--- a/drivers/media/rc/redrat3.c ++++ b/drivers/media/rc/redrat3.c +@@ -922,7 +922,7 @@ static struct rc_dev *redrat3_init_rc_de + rc->dev.parent = dev; + rc->priv = rr3; + rc->driver_type = RC_DRIVER_IR_RAW; +- rc->allowed_protos = RC_BIT_ALL; ++ rc_set_allowed_protocols(rc, RC_BIT_ALL); + rc->timeout = US_TO_NS(2750); + rc->tx_ir = redrat3_transmit_ir; + rc->s_tx_carrier = redrat3_set_tx_carrier; +--- a/drivers/media/rc/st_rc.c ++++ b/drivers/media/rc/st_rc.c +@@ -287,7 +287,7 @@ static int st_rc_probe(struct platform_d + st_rc_hardware_init(rc_dev); + + rdev->driver_type = RC_DRIVER_IR_RAW; +- rdev->allowed_protos = RC_BIT_ALL; ++ rc_set_allowed_protocols(rdev, RC_BIT_ALL); + /* rx sampling rate is 10Mhz */ + rdev->rx_resolution = 100; + rdev->timeout = US_TO_NS(MAX_SYMB_TIME); +--- a/drivers/media/rc/streamzap.c ++++ b/drivers/media/rc/streamzap.c +@@ -322,7 +322,7 @@ static struct rc_dev *streamzap_init_rc_ + rdev->dev.parent = dev; + rdev->priv = sz; + rdev->driver_type = RC_DRIVER_IR_RAW; +- rdev->allowed_protos = RC_BIT_ALL; ++ rc_set_allowed_protocols(rdev, RC_BIT_ALL); + rdev->driver_name = DRIVER_NAME; + rdev->map_name = RC_MAP_STREAMZAP; + +--- a/drivers/media/rc/ttusbir.c ++++ b/drivers/media/rc/ttusbir.c +@@ -318,7 +318,7 @@ static int ttusbir_probe(struct usb_inte + usb_to_input_id(tt->udev, &rc->input_id); + rc->dev.parent = &intf->dev; + rc->driver_type = RC_DRIVER_IR_RAW; +- rc->allowed_protos = RC_BIT_ALL; ++ rc_set_allowed_protocols(rc, RC_BIT_ALL); + rc->priv = tt; + rc->driver_name = DRIVER_NAME; + rc->map_name = RC_MAP_TT_1500; +--- a/drivers/media/rc/winbond-cir.c ++++ b/drivers/media/rc/winbond-cir.c +@@ -1082,7 +1082,7 @@ wbcir_probe(struct pnp_dev *device, cons + data->dev->dev.parent = &device->dev; + data->dev->timeout = MS_TO_NS(100); + data->dev->rx_resolution = US_TO_NS(2); +- data->dev->allowed_protos = RC_BIT_ALL; ++ rc_set_allowed_protocols(data->dev, RC_BIT_ALL); + + err = rc_register_device(data->dev); + if (err) +--- a/drivers/media/usb/dvb-usb/dvb-usb-remote.c ++++ b/drivers/media/usb/dvb-usb/dvb-usb-remote.c +@@ -272,7 +272,7 @@ static int rc_core_dvb_usb_remote_init(s + dev->driver_name = d->props.rc.core.module_name; + dev->map_name = d->props.rc.core.rc_codes; + dev->change_protocol = d->props.rc.core.change_protocol; +- dev->allowed_protos = d->props.rc.core.allowed_protos; ++ rc_set_allowed_protocols(dev, d->props.rc.core.allowed_protos); + dev->driver_type = d->props.rc.core.driver_type; + usb_to_input_id(d->udev, &dev->input_id); + dev->input_name = "IR-receiver inside an USB DVB receiver"; +--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c ++++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +@@ -164,7 +164,7 @@ static int dvb_usbv2_remote_init(struct + dev->driver_name = (char *) d->props->driver_name; + dev->map_name = d->rc.map_name; + dev->driver_type = d->rc.driver_type; +- dev->allowed_protos = d->rc.allowed_protos; ++ rc_set_allowed_protocols(dev, d->rc.allowed_protos); + dev->change_protocol = d->rc.change_protocol; + dev->priv = d; + +--- a/drivers/media/usb/em28xx/em28xx-input.c ++++ b/drivers/media/usb/em28xx/em28xx-input.c +@@ -725,7 +725,7 @@ static int em28xx_ir_init(struct em28xx + case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: + rc->map_name = RC_MAP_HAUPPAUGE; + ir->get_key_i2c = em28xx_get_key_em_haup; +- rc->allowed_protos = RC_BIT_RC5; ++ rc_set_allowed_protocols(rc, RC_BIT_RC5); + break; + case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE: + rc->map_name = RC_MAP_WINFAST_USBII_DELUXE; +@@ -741,7 +741,7 @@ static int em28xx_ir_init(struct em28xx + switch (dev->chip_id) { + case CHIP_ID_EM2860: + case CHIP_ID_EM2883: +- rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC; ++ rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC); + ir->get_key = default_polling_getkey; + break; + case CHIP_ID_EM2884: +@@ -749,8 +749,8 @@ static int em28xx_ir_init(struct em28xx + case CHIP_ID_EM28174: + case CHIP_ID_EM28178: + ir->get_key = em2874_polling_getkey; +- rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC | +- RC_BIT_RC6_0; ++ rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC | ++ RC_BIT_RC6_0); + break; + default: + err = -ENODEV; +--- a/drivers/media/usb/tm6000/tm6000-input.c ++++ b/drivers/media/usb/tm6000/tm6000-input.c +@@ -422,7 +422,7 @@ int tm6000_ir_init(struct tm6000_core *d + ir->rc = rc; + + /* input setup */ +- rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC; ++ rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC); + /* Neded, in order to support NEC remotes with 24 or 32 bits */ + rc->scanmask = 0xffff; + rc->priv = ir; +--- a/include/media/rc-core.h ++++ b/include/media/rc-core.h +@@ -35,6 +35,29 @@ enum rc_driver_type { + }; + + /** ++ * struct rc_scancode_filter - Filter scan codes. ++ * @data: Scancode data to match. ++ * @mask: Mask of bits of scancode to compare. ++ */ ++struct rc_scancode_filter { ++ u32 data; ++ u32 mask; ++}; ++ ++/** ++ * enum rc_filter_type - Filter type constants. ++ * @RC_FILTER_NORMAL: Filter for normal operation. ++ * @RC_FILTER_WAKEUP: Filter for waking from suspend. ++ * @RC_FILTER_MAX: Number of filter types. ++ */ ++enum rc_filter_type { ++ RC_FILTER_NORMAL = 0, ++ RC_FILTER_WAKEUP, ++ ++ RC_FILTER_MAX ++}; ++ ++/** + * struct rc_dev - represents a remote control device + * @dev: driver model's view of this device + * @input_name: name of the input child device +@@ -50,8 +73,10 @@ enum rc_driver_type { + * @input_dev: the input child device used to communicate events to userspace + * @driver_type: specifies if protocol decoding is done in hardware or software + * @idle: used to keep track of RX state +- * @allowed_protos: bitmask with the supported RC_BIT_* protocols +- * @enabled_protocols: bitmask with the enabled RC_BIT_* protocols ++ * @allowed_protocols: bitmask with the supported RC_BIT_* protocols for each ++ * filter type ++ * @enabled_protocols: bitmask with the enabled RC_BIT_* protocols for each ++ * filter type + * @scanmask: some hardware decoders are not capable of providing the full + * scancode to the application. As this is a hardware limit, we can't do + * anything with it. Yet, as the same keycode table can be used with other +@@ -70,7 +95,10 @@ enum rc_driver_type { + * @max_timeout: maximum timeout supported by device + * @rx_resolution : resolution (in ns) of input sampler + * @tx_resolution: resolution (in ns) of output sampler ++ * @scancode_filters: scancode filters (indexed by enum rc_filter_type) + * @change_protocol: allow changing the protocol used on hardware decoders ++ * @change_wakeup_protocol: allow changing the protocol used for wakeup ++ * filtering + * @open: callback to allow drivers to enable polling/irq when IR input device + * is opened. + * @close: callback to allow drivers to disable polling/irq when IR input device +@@ -84,6 +112,7 @@ enum rc_driver_type { + * device doesn't interrupt host until it sees IR pulses + * @s_learning_mode: enable wide band receiver used for learning + * @s_carrier_report: enable carrier reports ++ * @s_filter: set the scancode filter of a given type + */ + struct rc_dev { + struct device dev; +@@ -99,8 +128,8 @@ struct rc_dev { + struct input_dev *input_dev; + enum rc_driver_type driver_type; + bool idle; +- u64 allowed_protos; +- u64 enabled_protocols; ++ u64 allowed_protocols[RC_FILTER_MAX]; ++ u64 enabled_protocols[RC_FILTER_MAX]; + u32 users; + u32 scanmask; + void *priv; +@@ -116,7 +145,9 @@ struct rc_dev { + u32 max_timeout; + u32 rx_resolution; + u32 tx_resolution; ++ struct rc_scancode_filter scancode_filters[RC_FILTER_MAX]; + int (*change_protocol)(struct rc_dev *dev, u64 *rc_type); ++ int (*change_wakeup_protocol)(struct rc_dev *dev, u64 *rc_type); + int (*open)(struct rc_dev *dev); + void (*close)(struct rc_dev *dev); + int (*s_tx_mask)(struct rc_dev *dev, u32 mask); +@@ -127,10 +158,49 @@ struct rc_dev { + void (*s_idle)(struct rc_dev *dev, bool enable); + int (*s_learning_mode)(struct rc_dev *dev, int enable); + int (*s_carrier_report) (struct rc_dev *dev, int enable); ++ int (*s_filter)(struct rc_dev *dev, ++ enum rc_filter_type type, ++ struct rc_scancode_filter *filter); + }; + + #define to_rc_dev(d) container_of(d, struct rc_dev, dev) + ++static inline bool rc_protocols_allowed(struct rc_dev *rdev, u64 protos) ++{ ++ return rdev->allowed_protocols[RC_FILTER_NORMAL] & protos; ++} ++ ++/* should be called prior to registration or with mutex held */ ++static inline void rc_set_allowed_protocols(struct rc_dev *rdev, u64 protos) ++{ ++ rdev->allowed_protocols[RC_FILTER_NORMAL] = protos; ++} ++ ++static inline bool rc_protocols_enabled(struct rc_dev *rdev, u64 protos) ++{ ++ return rdev->enabled_protocols[RC_FILTER_NORMAL] & protos; ++} ++ ++/* should be called prior to registration or with mutex held */ ++static inline void rc_set_enabled_protocols(struct rc_dev *rdev, u64 protos) ++{ ++ rdev->enabled_protocols[RC_FILTER_NORMAL] = protos; ++} ++ ++/* should be called prior to registration or with mutex held */ ++static inline void rc_set_allowed_wakeup_protocols(struct rc_dev *rdev, ++ u64 protos) ++{ ++ rdev->allowed_protocols[RC_FILTER_WAKEUP] = protos; ++} ++ ++/* should be called prior to registration or with mutex held */ ++static inline void rc_set_enabled_wakeup_protocols(struct rc_dev *rdev, ++ u64 protos) ++{ ++ rdev->enabled_protocols[RC_FILTER_WAKEUP] = protos; ++} ++ + /* + * From rc-main.c + * Those functions can be used on any type of Remote Controller. They |