Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b590c0bf authored by Sean Young's avatar Sean Young Committed by Mauro Carvalho Chehab
Browse files

[media] rc: Add scancode validation



We need to valdiate that scancodes are valid for their protocol; an
incorrect necx scancode could actually be a nec scancode, for example.

Signed-off-by: default avatarSean Young <sean@mess.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent 0751d33c
Loading
Loading
Loading
Loading
+68 −3
Original line number Diff line number Diff line
@@ -724,6 +724,64 @@ void rc_keydown_notimeout(struct rc_dev *dev, enum rc_type protocol,
}
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;
@@ -1229,12 +1287,19 @@ static ssize_t store_filter(struct device *device,
		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 &&
	    val) {