[media] rc: change wakeup_protocols to list all protocol variants
authorSean Young <sean@mess.org>
Mon, 5 Dec 2016 19:08:35 +0000 (17:08 -0200)
committerMauro Carvalho Chehab <mchehab@s-opensource.com>
Mon, 30 Jan 2017 14:15:12 +0000 (12:15 -0200)
For IR wakeup, a driver has to program the hardware to wakeup at a
specific IR sequence, so it makes no sense to allow multiple wakeup
protocols to be selected. In the same manner the sysfs interface only
allows one scancode to be provided.

In addition, we need to know the specific variant of the protocol.

In short, these changes are made to the wakeup_protocols sysfs entry:
 - list all the protocol variants rather than the protocol groups,
   e.g. "nec nec-x nec-32" rather than just "nec".
 - only allow one protocol variant to be selected rather than multiple
 - wakeup_filter can only be set once a protocol has been selected in
   wakeup_protocols.

This is an API change, however the only user of this API is the img-ir,
but the wakeup code was never merged to mainline, so it was never used.

Signed-off-by: Sean Young <sean@mess.org>
Cc: James Hogan <james.hogan@imgtec.com>
Cc: Sifan Naeem <sifan.naeem@imgtec.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Documentation/ABI/testing/sysfs-class-rc
Documentation/media/uapi/rc/rc-sysfs-nodes.rst
drivers/media/rc/img-ir/img-ir-hw.c
drivers/media/rc/img-ir/img-ir-nec.c
drivers/media/rc/img-ir/img-ir-sony.c
drivers/media/rc/rc-ir-raw.c
drivers/media/rc/rc-main.c
include/media/rc-core.h

index b65674da43bb596b81dd4d29792774e0630bfe9d..8be1fd3760e038738d5a78cf04db330bc9b86b14 100644 (file)
@@ -62,18 +62,18 @@ Description:
                This value may be reset to 0 if the current protocol is altered.
 
 What:          /sys/class/rc/rcN/wakeup_protocols
-Date:          Feb 2014
-KernelVersion: 3.15
+Date:          Feb 2017
+KernelVersion: 4.11
 Contact:       Mauro Carvalho Chehab <m.chehab@samsung.com>
 Description:
                Reading this file returns a list of available protocols to use
                for the wakeup filter, something like:
-                   "rc5 rc6 nec jvc [sony]"
+                   "rc-5 nec nec-x rc-6-0 rc-6-6a-24 [rc-6-6a-32] rc-6-mce"
+               Note that protocol variants are listed, so "nec", "sony",
+               "rc-5", "rc-6" have their different bit length encodings
+               listed if available.
                The enabled wakeup protocol is shown in [] brackets.
-               Writing "+proto" will add a protocol to the list of enabled
-               wakeup protocols.
-               Writing "-proto" will remove a protocol from the list of enabled
-               wakeup protocols.
+               Only one protocol can be selected at a time.
                Writing "proto" will use "proto" for wakeup events.
                Writing "none" will disable wakeup.
                Write fails with EINVAL if an invalid protocol combination or
index 6fb944fe21fdb49e4c8b72887e759a557f03b749..3476ae29708f7e4068bbb5166c5d6ee66ef29e16 100644 (file)
@@ -92,15 +92,16 @@ This value may be reset to 0 if the current protocol is altered.
 Reading this file returns a list of available protocols to use for the
 wakeup filter, something like:
 
-``rc5 rc6 nec jvc [sony]``
+``rc-5 nec nec-x rc-6-0 rc-6-6a-24 [rc-6-6a-32] rc-6-mce``
 
-The enabled wakeup protocol is shown in [] brackets.
+Note that protocol variants are listed, so "nec", "sony", "rc-5", "rc-6"
+have their different bit length encodings listed if available.
 
-Writing "+proto" will add a protocol to the list of enabled wakeup
-protocols.
+Note that all protocol variants are listed.
 
-Writing "-proto" will remove a protocol from the list of enabled wakeup
-protocols.
+The enabled wakeup protocol is shown in [] brackets.
+
+Only one protocol can be selected at a time.
 
 Writing "proto" will use "proto" for wakeup events.
 
index 7bb71bc9f534d525d48f9fd97a56e2e749685185..8e2b64135c3984c18d171d04348b2ba62bdd701c 100644 (file)
@@ -488,7 +488,15 @@ static int img_ir_set_filter(struct rc_dev *dev, enum rc_filter_type type,
        /* convert scancode filter to raw filter */
        filter.minlen = 0;
        filter.maxlen = ~0;
-       ret = hw->decoder->filter(sc_filter, &filter, hw->enabled_protocols);
+       if (type == RC_FILTER_NORMAL) {
+               /* guess scancode from protocol */
+               ret = hw->decoder->filter(sc_filter, &filter,
+                                         dev->enabled_protocols);
+       } else {
+               /* for wakeup user provided exact protocol variant */
+               ret = hw->decoder->filter(sc_filter, &filter,
+                                         1ULL << dev->wakeup_protocol);
+       }
        if (ret)
                goto unlock;
        dev_dbg(priv->dev, "IR raw %sfilter=%016llx & %016llx\n",
@@ -581,6 +589,7 @@ static void img_ir_set_decoder(struct img_ir_priv *priv,
        /* clear the wakeup scancode filter */
        rdev->scancode_wakeup_filter.data = 0;
        rdev->scancode_wakeup_filter.mask = 0;
+       rdev->wakeup_protocol = RC_TYPE_UNKNOWN;
 
        /* clear raw filters */
        _img_ir_set_filter(priv, NULL);
@@ -685,7 +694,6 @@ success:
        if (!hw->decoder || !hw->decoder->filter)
                wakeup_protocols = 0;
        rdev->allowed_wakeup_protocols = wakeup_protocols;
-       rdev->enabled_wakeup_protocols = wakeup_protocols;
        return 0;
 }
 
@@ -701,7 +709,6 @@ static void img_ir_set_protocol(struct img_ir_priv *priv, u64 proto)
        mutex_lock(&rdev->lock);
        rdev->enabled_protocols = proto;
        rdev->allowed_wakeup_protocols = proto;
-       rdev->enabled_wakeup_protocols = proto;
        mutex_unlock(&rdev->lock);
 }
 
index 09314933ea0871127e027dd45fced708924fb34a..044fd42b22a090b34a5fb64cbd2df0cba50192bb 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "img-ir-hw.h"
 #include <linux/bitrev.h>
+#include <linux/log2.h>
 
 /* Convert NEC data to a scancode */
 static int img_ir_nec_scancode(int len, u64 raw, u64 enabled_protocols,
@@ -62,7 +63,23 @@ static int img_ir_nec_filter(const struct rc_scancode_filter *in,
        data       = in->data & 0xff;
        data_m     = in->mask & 0xff;
 
-       if ((in->data | in->mask) & 0xff000000) {
+       protocols &= RC_BIT_NEC | RC_BIT_NECX | RC_BIT_NEC32;
+
+       /*
+        * If only one bit is set, we were requested to do an exact
+        * protocol. This should be the case for wakeup filters; for
+        * normal filters, guess the protocol from the scancode.
+        */
+       if (!is_power_of_2(protocols)) {
+               if ((in->data | in->mask) & 0xff000000)
+                       protocols = RC_BIT_NEC32;
+               else if ((in->data | in->mask) & 0x00ff0000)
+                       protocols = RC_BIT_NECX;
+               else
+                       protocols = RC_BIT_NEC;
+       }
+
+       if (protocols == RC_BIT_NEC32) {
                /* 32-bit NEC (used by Apple and TiVo remotes) */
                /* scan encoding: as transmitted, MSBit = first received bit */
                addr       = bitrev8(in->data >> 24);
@@ -73,7 +90,7 @@ static int img_ir_nec_filter(const struct rc_scancode_filter *in,
                data_m     = bitrev8(in->mask >>  8);
                data_inv   = bitrev8(in->data >>  0);
                data_inv_m = bitrev8(in->mask >>  0);
-       } else if ((in->data | in->mask) & 0x00ff0000) {
+       } else if (protocols == RC_BIT_NECX) {
                /* Extended NEC */
                /* scan encoding AAaaDD */
                addr       = (in->data >> 16) & 0xff;
index 7f7375f82ed60017f0dfe6c0517b7ec93ecd85bb..3fcba271a419f8582ded5ecffa29413c2cb9e89d 100644 (file)
@@ -68,19 +68,29 @@ static int img_ir_sony_filter(const struct rc_scancode_filter *in,
        func     = (in->data >> 0)  & 0x7f;
        func_m   = (in->mask >> 0)  & 0x7f;
 
-       if (subdev & subdev_m) {
+       protocols &= RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20;
+
+       /*
+        * If only one bit is set, we were requested to do an exact
+        * protocol. This should be the case for wakeup filters; for
+        * normal filters, guess the protocol from the scancode.
+        */
+       if (!is_power_of_2(protocols)) {
+               if (subdev & subdev_m)
+                       protocols = RC_BIT_SONY20;
+               else if (dev & dev_m & 0xe0)
+                       protocols = RC_BIT_SONY15;
+               else
+                       protocols = RC_BIT_SONY12;
+       }
+
+       if (protocols == RC_BIT_SONY20) {
                /* can't encode subdev and higher device bits */
                if (dev & dev_m & 0xe0)
                        return -EINVAL;
-               /* subdevice (extended) bits only in 20 bit encoding */
-               if (!(protocols & RC_BIT_SONY20))
-                       return -EINVAL;
                len = 20;
                dev_m &= 0x1f;
-       } else if (dev & dev_m & 0xe0) {
-               /* upper device bits only in 15 bit encoding */
-               if (!(protocols & RC_BIT_SONY15))
-                       return -EINVAL;
+       } else if (protocols == RC_BIT_SONY15) {
                len = 15;
                subdev_m = 0;
        } else {
index 0d14410471ba91b23f306cc020a577ab13b28789..68dfe8161ceab19c2d1189eaf25be4c88a0cf363 100644 (file)
@@ -235,7 +235,6 @@ static void ir_raw_disable_protocols(struct rc_dev *dev, u64 protocols)
 {
        mutex_lock(&dev->lock);
        dev->enabled_protocols &= ~protocols;
-       dev->enabled_wakeup_protocols &= ~protocols;
        mutex_unlock(&dev->lock);
 }
 
index 75bdc49eeb3e1b449595ead3672b5e6375aa4b83..a4b12d261eb566279a158f54f28d21e58796b676 100644 (file)
@@ -830,11 +830,6 @@ struct rc_filter_attribute {
 };
 #define to_rc_filter_attr(a) container_of(a, struct rc_filter_attribute, attr)
 
-#define RC_PROTO_ATTR(_name, _mode, _show, _store, _type)              \
-       struct rc_filter_attribute dev_attr_##_name = {                 \
-               .attr = __ATTR(_name, _mode, _show, _store),            \
-               .type = (_type),                                        \
-       }
 #define RC_FILTER_ATTR(_name, _mode, _show, _store, _type, _mask)      \
        struct rc_filter_attribute dev_attr_##_name = {                 \
                .attr = __ATTR(_name, _mode, _show, _store),            \
@@ -860,13 +855,13 @@ static bool lirc_is_present(void)
 }
 
 /**
- * show_protocols() - shows the current/wakeup IR protocol(s)
+ * show_protocols() - shows the current IR protocol(s)
  * @device:    the device descriptor
  * @mattr:     the device attribute struct
  * @buf:       a pointer to the output buffer
  *
  * This routine is a callback routine for input read the IR protocol type(s).
- * it is trigged by reading /sys/class/rc/rc?/[wakeup_]protocols.
+ * it is trigged by reading /sys/class/rc/rc?/protocols.
  * It returns the protocol names of supported protocols.
  * Enabled protocols are printed in brackets.
  *
@@ -877,7 +872,6 @@ static ssize_t show_protocols(struct device *device,
                              struct device_attribute *mattr, char *buf)
 {
        struct rc_dev *dev = to_rc_dev(device);
-       struct rc_filter_attribute *fattr = to_rc_filter_attr(mattr);
        u64 allowed, enabled;
        char *tmp = buf;
        int i;
@@ -891,15 +885,10 @@ static ssize_t show_protocols(struct device *device,
 
        mutex_lock(&dev->lock);
 
-       if (fattr->type == RC_FILTER_NORMAL) {
-               enabled = dev->enabled_protocols;
-               allowed = dev->allowed_protocols;
-               if (dev->raw && !allowed)
-                       allowed = ir_raw_get_allowed_protocols();
-       } else {
-               enabled = dev->enabled_wakeup_protocols;
-               allowed = dev->allowed_wakeup_protocols;
-       }
+       enabled = dev->enabled_protocols;
+       allowed = dev->allowed_protocols;
+       if (dev->raw && !allowed)
+               allowed = ir_raw_get_allowed_protocols();
 
        mutex_unlock(&dev->lock);
 
@@ -1058,11 +1047,8 @@ static ssize_t store_protocols(struct device *device,
                               const char *buf, size_t len)
 {
        struct rc_dev *dev = to_rc_dev(device);
-       struct rc_filter_attribute *fattr = to_rc_filter_attr(mattr);
        u64 *current_protocols;
-       int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
        struct rc_scancode_filter *filter;
-       int (*set_filter)(struct rc_dev *dev, struct rc_scancode_filter *filter);
        u64 old_protocols, new_protocols;
        ssize_t rc;
 
@@ -1073,21 +1059,11 @@ static ssize_t store_protocols(struct device *device,
        if (!atomic_read(&dev->initialized))
                return -ERESTARTSYS;
 
-       if (fattr->type == RC_FILTER_NORMAL) {
-               IR_dprintk(1, "Normal protocol change requested\n");
-               current_protocols = &dev->enabled_protocols;
-               change_protocol = dev->change_protocol;
-               filter = &dev->scancode_filter;
-               set_filter = dev->s_filter;
-       } else {
-               IR_dprintk(1, "Wakeup protocol change requested\n");
-               current_protocols = &dev->enabled_wakeup_protocols;
-               change_protocol = dev->change_wakeup_protocol;
-               filter = &dev->scancode_wakeup_filter;
-               set_filter = dev->s_wakeup_filter;
-       }
+       IR_dprintk(1, "Normal protocol change requested\n");
+       current_protocols = &dev->enabled_protocols;
+       filter = &dev->scancode_filter;
 
-       if (!change_protocol) {
+       if (!dev->change_protocol) {
                IR_dprintk(1, "Protocol switching not supported\n");
                return -EINVAL;
        }
@@ -1100,7 +1076,7 @@ static ssize_t store_protocols(struct device *device,
        if (rc < 0)
                goto out;
 
-       rc = change_protocol(dev, &new_protocols);
+       rc = dev->change_protocol(dev, &new_protocols);
        if (rc < 0) {
                IR_dprintk(1, "Error setting protocols to 0x%llx\n",
                           (long long)new_protocols);
@@ -1123,16 +1099,16 @@ static ssize_t store_protocols(struct device *device,
         * Try setting the same filter with the new protocol (if any).
         * Fall back to clearing the filter.
         */
-       if (set_filter && filter->mask) {
+       if (dev->s_filter && filter->mask) {
                if (new_protocols)
-                       rc = set_filter(dev, filter);
+                       rc = dev->s_filter(dev, filter);
                else
                        rc = -1;
 
                if (rc < 0) {
                        filter->data = 0;
                        filter->mask = 0;
-                       set_filter(dev, filter);
+                       dev->s_filter(dev, filter);
                }
        }
 
@@ -1221,7 +1197,6 @@ static ssize_t store_filter(struct device *device,
        int ret;
        unsigned long val;
        int (*set_filter)(struct rc_dev *dev, struct rc_scancode_filter *filter);
-       u64 *enabled_protocols;
 
        /* Device is being removed */
        if (!dev)
@@ -1236,11 +1211,9 @@ static ssize_t store_filter(struct device *device,
 
        if (fattr->type == RC_FILTER_NORMAL) {
                set_filter = dev->s_filter;
-               enabled_protocols = &dev->enabled_protocols;
                filter = &dev->scancode_filter;
        } else {
                set_filter = dev->s_wakeup_filter;
-               enabled_protocols = &dev->enabled_wakeup_protocols;
                filter = &dev->scancode_wakeup_filter;
        }
 
@@ -1255,7 +1228,16 @@ static ssize_t store_filter(struct device *device,
        else
                new_filter.data = val;
 
-       if (!*enabled_protocols && val) {
+       if (fattr->type == RC_FILTER_WAKEUP) {
+               /* refuse to set a filter unless a protocol is enabled */
+               if (dev->wakeup_protocol == RC_TYPE_UNKNOWN) {
+                       ret = -EINVAL;
+                       goto unlock;
+               }
+       }
+
+       if (fattr->type == RC_FILTER_NORMAL && !dev->enabled_protocols &&
+           val) {
                /* refuse to set a filter unless a protocol is enabled */
                ret = -EINVAL;
                goto unlock;
@@ -1272,6 +1254,172 @@ unlock:
        return (ret < 0) ? ret : len;
 }
 
+/*
+ * This is the list of all variants of all protocols, which is used by
+ * the wakeup_protocols sysfs entry. In the protocols sysfs entry some
+ * some protocols are grouped together (e.g. nec = nec + necx + nec32).
+ *
+ * For wakeup we need to know the exact protocol variant so the hardware
+ * can be programmed exactly what to expect.
+ */
+static const char * const proto_variant_names[] = {
+       [RC_TYPE_UNKNOWN] = "unknown",
+       [RC_TYPE_OTHER] = "other",
+       [RC_TYPE_RC5] = "rc-5",
+       [RC_TYPE_RC5X_20] = "rc-5x-20",
+       [RC_TYPE_RC5_SZ] = "rc-5-sz",
+       [RC_TYPE_JVC] = "jvc",
+       [RC_TYPE_SONY12] = "sony-12",
+       [RC_TYPE_SONY15] = "sony-15",
+       [RC_TYPE_SONY20] = "sony-20",
+       [RC_TYPE_NEC] = "nec",
+       [RC_TYPE_NECX] = "nec-x",
+       [RC_TYPE_NEC32] = "nec-32",
+       [RC_TYPE_SANYO] = "sanyo",
+       [RC_TYPE_MCE_KBD] = "mce_kbd",
+       [RC_TYPE_RC6_0] = "rc-6-0",
+       [RC_TYPE_RC6_6A_20] = "rc-6-6a-20",
+       [RC_TYPE_RC6_6A_24] = "rc-6-6a-24",
+       [RC_TYPE_RC6_6A_32] = "rc-6-6a-32",
+       [RC_TYPE_RC6_MCE] = "rc-6-mce",
+       [RC_TYPE_SHARP] = "sharp",
+       [RC_TYPE_XMP] = "xmp",
+       [RC_TYPE_CEC] = "cec",
+};
+
+/**
+ * show_wakeup_protocols() - shows the wakeup IR protocol
+ * @device:    the device descriptor
+ * @mattr:     the device attribute struct
+ * @buf:       a pointer to the output buffer
+ *
+ * This routine is a callback routine for input read the IR protocol type(s).
+ * it is trigged by reading /sys/class/rc/rc?/wakeup_protocols.
+ * It returns the protocol names of supported protocols.
+ * The enabled protocols are printed in brackets.
+ *
+ * dev->lock is taken to guard against races between device
+ * registration, store_protocols and show_protocols.
+ */
+static ssize_t show_wakeup_protocols(struct device *device,
+                                    struct device_attribute *mattr,
+                                    char *buf)
+{
+       struct rc_dev *dev = to_rc_dev(device);
+       u64 allowed;
+       enum rc_type enabled;
+       char *tmp = buf;
+       int i;
+
+       /* Device is being removed */
+       if (!dev)
+               return -EINVAL;
+
+       if (!atomic_read(&dev->initialized))
+               return -ERESTARTSYS;
+
+       mutex_lock(&dev->lock);
+
+       allowed = dev->allowed_wakeup_protocols;
+       enabled = dev->wakeup_protocol;
+
+       mutex_unlock(&dev->lock);
+
+       IR_dprintk(1, "%s: allowed - 0x%llx, enabled - %d\n",
+                  __func__, (long long)allowed, enabled);
+
+       for (i = 0; i < ARRAY_SIZE(proto_variant_names); i++) {
+               if (allowed & (1ULL << i)) {
+                       if (i == enabled)
+                               tmp += sprintf(tmp, "[%s] ",
+                                               proto_variant_names[i]);
+                       else
+                               tmp += sprintf(tmp, "%s ",
+                                               proto_variant_names[i]);
+               }
+       }
+
+       if (tmp != buf)
+               tmp--;
+       *tmp = '\n';
+
+       return tmp + 1 - buf;
+}
+
+/**
+ * store_wakeup_protocols() - changes the wakeup IR protocol(s)
+ * @device:    the device descriptor
+ * @mattr:     the device attribute struct
+ * @buf:       a pointer to the input buffer
+ * @len:       length of the input buffer
+ *
+ * This routine is for changing the IR protocol type.
+ * It is trigged by writing to /sys/class/rc/rc?/wakeup_protocols.
+ * Returns @len on success or a negative error code.
+ *
+ * dev->lock is taken to guard against races between device
+ * registration, store_protocols and show_protocols.
+ */
+static ssize_t store_wakeup_protocols(struct device *device,
+                                     struct device_attribute *mattr,
+                                     const char *buf, size_t len)
+{
+       struct rc_dev *dev = to_rc_dev(device);
+       enum rc_type protocol;
+       ssize_t rc;
+       u64 allowed;
+       int i;
+
+       /* Device is being removed */
+       if (!dev)
+               return -EINVAL;
+
+       if (!atomic_read(&dev->initialized))
+               return -ERESTARTSYS;
+
+       mutex_lock(&dev->lock);
+
+       allowed = dev->allowed_wakeup_protocols;
+
+       if (sysfs_streq(buf, "none")) {
+               protocol = RC_TYPE_UNKNOWN;
+       } else {
+               for (i = 0; i < ARRAY_SIZE(proto_variant_names); i++) {
+                       if ((allowed & (1ULL << i)) &&
+                           sysfs_streq(buf, proto_variant_names[i])) {
+                               protocol = i;
+                               break;
+                       }
+               }
+
+               if (i == ARRAY_SIZE(proto_variant_names)) {
+                       rc = -EINVAL;
+                       goto out;
+               }
+       }
+
+       if (dev->wakeup_protocol != protocol) {
+               dev->wakeup_protocol = protocol;
+               IR_dprintk(1, "Wakeup protocol changed to %d\n", protocol);
+
+               if (protocol == RC_TYPE_RC6_MCE)
+                       dev->scancode_wakeup_filter.data = 0x800f0000;
+               else
+                       dev->scancode_wakeup_filter.data = 0;
+               dev->scancode_wakeup_filter.mask = 0;
+
+               rc = dev->s_wakeup_filter(dev, &dev->scancode_wakeup_filter);
+               if (rc == 0)
+                       rc = len;
+       } else {
+               rc = len;
+       }
+
+out:
+       mutex_unlock(&dev->lock);
+       return rc;
+}
+
 static void rc_dev_release(struct device *device)
 {
        struct rc_dev *dev = to_rc_dev(device);
@@ -1301,10 +1449,9 @@ 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 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 DEVICE_ATTR(protocols, 0644, show_protocols, store_protocols);
+static DEVICE_ATTR(wakeup_protocols, 0644, show_wakeup_protocols,
+                  store_wakeup_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,
@@ -1315,7 +1462,7 @@ static RC_FILTER_ATTR(wakeup_filter_mask, S_IRUGO|S_IWUSR,
                      show_filter, store_filter, RC_FILTER_WAKEUP, true);
 
 static struct attribute *rc_dev_protocol_attrs[] = {
-       &dev_attr_protocols.attr.attr,
+       &dev_attr_protocols.attr,
        NULL,
 };
 
@@ -1323,15 +1470,6 @@ static struct attribute_group rc_dev_protocol_attr_grp = {
        .attrs  = rc_dev_protocol_attrs,
 };
 
-static struct attribute *rc_dev_wakeup_protocol_attrs[] = {
-       &dev_attr_wakeup_protocols.attr.attr,
-       NULL,
-};
-
-static struct attribute_group rc_dev_wakeup_protocol_attr_grp = {
-       .attrs  = rc_dev_wakeup_protocol_attrs,
-};
-
 static struct attribute *rc_dev_filter_attrs[] = {
        &dev_attr_filter.attr.attr,
        &dev_attr_filter_mask.attr.attr,
@@ -1345,6 +1483,7 @@ static struct attribute_group rc_dev_filter_attr_grp = {
 static struct attribute *rc_dev_wakeup_filter_attrs[] = {
        &dev_attr_wakeup_filter.attr.attr,
        &dev_attr_wakeup_filter_mask.attr.attr,
+       &dev_attr_wakeup_protocols.attr,
        NULL,
 };
 
@@ -1475,8 +1614,6 @@ int rc_register_device(struct rc_dev *dev)
                dev->sysfs_groups[attr++] = &rc_dev_filter_attr_grp;
        if (dev->s_wakeup_filter)
                dev->sysfs_groups[attr++] = &rc_dev_wakeup_filter_attr_grp;
-       if (dev->change_wakeup_protocol)
-               dev->sysfs_groups[attr++] = &rc_dev_wakeup_protocol_attr_grp;
        dev->sysfs_groups[attr++] = NULL;
 
        rc = device_add(&dev->dev);
index 55281b92105a3ebd0d2e899028c3781e298738ea..af4009399d1a6c32482699831122ddcb7b08afdc 100644 (file)
@@ -86,7 +86,8 @@ enum rc_filter_type {
  * @allowed_protocols: bitmask with the supported RC_BIT_* protocols
  * @enabled_protocols: bitmask with the enabled RC_BIT_* protocols
  * @allowed_wakeup_protocols: bitmask with the supported RC_BIT_* wakeup protocols
- * @enabled_wakeup_protocols: bitmask with the enabled RC_BIT_* wakeup protocols
+ * @wakeup_protocol: the enabled RC_TYPE_* wakeup protocol or
+ *     RC_TYPE_UNKNOWN if disabled.
  * @scancode_filter: scancode filter
  * @scancode_wakeup_filter: scancode wakeup filters
  * @scancode_mask: some hardware decoders are not capable of providing the full
@@ -110,8 +111,6 @@ enum rc_filter_type {
  * @rx_resolution : resolution (in ns) of input sampler
  * @tx_resolution: resolution (in ns) of output sampler
  * @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
@@ -126,7 +125,9 @@ enum rc_filter_type {
  * @s_learning_mode: enable wide band receiver used for learning
  * @s_carrier_report: enable carrier reports
  * @s_filter: set the scancode filter
- * @s_wakeup_filter: set the wakeup scancode filter
+ * @s_wakeup_filter: set the wakeup scancode filter. If the mask is zero
+ *     then wakeup should be disabled. wakeup_protocol will be set to
+ *     a valid protocol if mask is nonzero.
  * @s_timeout: set hardware timeout in ns
  */
 struct rc_dev {
@@ -149,7 +150,7 @@ struct rc_dev {
        u64                             allowed_protocols;
        u64                             enabled_protocols;
        u64                             allowed_wakeup_protocols;
-       u64                             enabled_wakeup_protocols;
+       enum rc_type                    wakeup_protocol;
        struct rc_scancode_filter       scancode_filter;
        struct rc_scancode_filter       scancode_wakeup_filter;
        u32                             scancode_mask;
@@ -169,7 +170,6 @@ struct rc_dev {
        u32                             rx_resolution;
        u32                             tx_resolution;
        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);