[PATCH 5/5] rc-main: automatically refresh filter on protocol change

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxx>
Cc: Mauro Carvalho Chehab <m.chehab@xxxxxxxxxxx>
Cc: Antti Seppälä <a.seppala@xxxxxxxxx>
Cc: linux-media@xxxxxxxxxxxxxxx
---
 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).
+	 * Fall back to clearing the filter.
+	 */
+	filter = &dev->scancode_filters[fattr->type];
+	if (old_type != type && filter->mask) {
+		local_filter = *filter;
+		if (!type) {
+			/* no protocol => clear filter */
+			ret = -1;
+		} else if (!dev->s_filter) {
+			/* generic filtering => accept any filter */
+			ret = 0;
+		} else {
+			/* hardware filtering => try setting, otherwise clear */
+			ret = dev->s_filter(dev, fattr->type, &local_filter);
+		}
+		if (ret < 0) {
+			/* clear the filter */
+			local_filter.data = 0;
+			local_filter.mask = 0;
+			if (dev->s_filter)
+				dev->s_filter(dev, fattr->type, &local_filter);
+		}
+
+		/* commit the new filter */
+		*filter = local_filter;
+	}
+
 	ret = len;
 
 out:
@@ -1096,6 +1128,11 @@ static ssize_t store_filter(struct device *device,
 		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)
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux