}
 EXPORT_SYMBOL_GPL(rc_keydown_notimeout);
 
+/**
+ * rc_validate_filter() - checks that the scancode and mask are valid and
+ *                       provides sensible defaults
+ * @protocol:  the protocol for the filter
+ * @filter:    the scancode and mask
+ * @return:    0 or -EINVAL if the filter is not valid
+ */
+static int rc_validate_filter(enum rc_type protocol,
+                             struct rc_scancode_filter *filter)
+{
+       static u32 masks[] = {
+               [RC_TYPE_RC5] = 0x1f7f,
+               [RC_TYPE_RC5X_20] = 0x1f7f3f,
+               [RC_TYPE_RC5_SZ] = 0x2fff,
+               [RC_TYPE_SONY12] = 0x1f007f,
+               [RC_TYPE_SONY15] = 0xff007f,
+               [RC_TYPE_SONY20] = 0x1fff7f,
+               [RC_TYPE_JVC] = 0xffff,
+               [RC_TYPE_NEC] = 0xffff,
+               [RC_TYPE_NECX] = 0xffffff,
+               [RC_TYPE_NEC32] = 0xffffffff,
+               [RC_TYPE_SANYO] = 0x1fffff,
+               [RC_TYPE_RC6_0] = 0xffff,
+               [RC_TYPE_RC6_6A_20] = 0xfffff,
+               [RC_TYPE_RC6_6A_24] = 0xffffff,
+               [RC_TYPE_RC6_6A_32] = 0xffffffff,
+               [RC_TYPE_RC6_MCE] = 0xffff7fff,
+               [RC_TYPE_SHARP] = 0x1fff,
+       };
+       u32 s = filter->data;
+
+       switch (protocol) {
+       case RC_TYPE_NECX:
+               if ((((s >> 16) ^ ~(s >> 8)) & 0xff) == 0)
+                       return -EINVAL;
+               break;
+       case RC_TYPE_NEC32:
+               if ((((s >> 24) ^ ~(s >> 16)) & 0xff) == 0)
+                       return -EINVAL;
+               break;
+       case RC_TYPE_RC6_MCE:
+               if ((s & 0xffff0000) != 0x800f0000)
+                       return -EINVAL;
+               break;
+       case RC_TYPE_RC6_6A_32:
+               if ((s & 0xffff0000) == 0x800f0000)
+                       return -EINVAL;
+               break;
+       default:
+               break;
+       }
+
+       filter->data &= masks[protocol];
+       filter->mask &= masks[protocol];
+
+       return 0;
+}
+
 int rc_open(struct rc_dev *rdev)
 {
        int rval = 0;
                new_filter.data = val;
 
        if (fattr->type == RC_FILTER_WAKEUP) {
-               /* refuse to set a filter unless a protocol is enabled */
-               if (dev->wakeup_protocol == RC_TYPE_UNKNOWN) {
+               /*
+                * Refuse to set a filter unless a protocol is enabled
+                * and the filter is valid for that protocol
+                */
+               if (dev->wakeup_protocol != RC_TYPE_UNKNOWN)
+                       ret = rc_validate_filter(dev->wakeup_protocol,
+                                                &new_filter);
+               else
                        ret = -EINVAL;
+
+               if (ret != 0)
                        goto unlock;
-               }
        }
 
        if (fattr->type == RC_FILTER_NORMAL && !dev->enabled_protocols &&