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

Commit 448cd166 authored by Dmitry Torokhov's avatar Dmitry Torokhov
Browse files

Input: evdev - rearrange ioctl handling



Split ioctl handling into 3 separate sections: fixed-length ioctls,
variable-length ioctls and multi-number variable length handlers.
This reduces identation and makes the code a bit clearer.

Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent d31b2865
Loading
Loading
Loading
Loading
+73 −68
Original line number Original line Diff line number Diff line
@@ -492,13 +492,15 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p)
}
}


#define OLD_KEY_MAX	0x1ff
#define OLD_KEY_MAX	0x1ff
static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user *p, int compat_mode)
static int handle_eviocgbit(struct input_dev *dev,
			    unsigned int type, unsigned int size,
			    void __user *p, int compat_mode)
{
{
	static unsigned long keymax_warn_time;
	static unsigned long keymax_warn_time;
	unsigned long *bits;
	unsigned long *bits;
	int len;
	int len;


	switch (_IOC_NR(cmd) & EV_MAX) {
	switch (type) {


	case      0: bits = dev->evbit;  len = EV_MAX;  break;
	case      0: bits = dev->evbit;  len = EV_MAX;  break;
	case EV_KEY: bits = dev->keybit; len = KEY_MAX; break;
	case EV_KEY: bits = dev->keybit; len = KEY_MAX; break;
@@ -517,7 +519,7 @@ static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user
	 * EVIOCGBIT(EV_KEY, KEY_MAX) and not realize that 'len'
	 * EVIOCGBIT(EV_KEY, KEY_MAX) and not realize that 'len'
	 * should be in bytes, not in bits.
	 * should be in bytes, not in bits.
	 */
	 */
	if ((_IOC_NR(cmd) & EV_MAX) == EV_KEY && _IOC_SIZE(cmd) == OLD_KEY_MAX) {
	if (type == EV_KEY && size == OLD_KEY_MAX) {
		len = OLD_KEY_MAX;
		len = OLD_KEY_MAX;
		if (printk_timed_ratelimit(&keymax_warn_time, 10 * 1000))
		if (printk_timed_ratelimit(&keymax_warn_time, 10 * 1000))
			printk(KERN_WARNING
			printk(KERN_WARNING
@@ -528,7 +530,7 @@ static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user
				BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long));
				BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long));
	}
	}


	return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode);
	return bits_to_user(bits, len, size, p, compat_mode);
}
}
#undef OLD_KEY_MAX
#undef OLD_KEY_MAX


@@ -542,8 +544,10 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
	struct ff_effect effect;
	struct ff_effect effect;
	int __user *ip = (int __user *)p;
	int __user *ip = (int __user *)p;
	unsigned int i, t, u, v;
	unsigned int i, t, u, v;
	unsigned int size;
	int error;
	int error;


	/* First we check for fixed-length commands */
	switch (cmd) {
	switch (cmd) {


	case EVIOCGVERSION:
	case EVIOCGVERSION:
@@ -610,82 +614,83 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
			return evdev_grab(evdev, client);
			return evdev_grab(evdev, client);
		else
		else
			return evdev_ungrab(evdev, client);
			return evdev_ungrab(evdev, client);
	}


	default:
	size = _IOC_SIZE(cmd);

		if (_IOC_TYPE(cmd) != 'E')
			return -EINVAL;


		if (_IOC_DIR(cmd) == _IOC_READ) {
	/* Now check variable-length commands */
#define EVIOC_MASK_SIZE(nr)	((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))


			if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0)))
	switch (EVIOC_MASK_SIZE(cmd)) {
				return handle_eviocgbit(dev, cmd, p, compat_mode);


			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
	case EVIOCGKEY(0):
				return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd),
		return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode);
						    p, compat_mode);


			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
	case EVIOCGLED(0):
				return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd),
		return bits_to_user(dev->led, LED_MAX, size, p, compat_mode);
						    p, compat_mode);


			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
	case EVIOCGSND(0):
				return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd),
		return bits_to_user(dev->snd, SND_MAX, size, p, compat_mode);
						    p, compat_mode);


			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0)))
	case EVIOCGSW(0):
				return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd),
		return bits_to_user(dev->sw, SW_MAX, size, p, compat_mode);
						    p, compat_mode);


			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0)))
	case EVIOCGNAME(0):
				return str_to_user(dev->name, _IOC_SIZE(cmd), p);
		return str_to_user(dev->name, size, p);


			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0)))
	case EVIOCGPHYS(0):
				return str_to_user(dev->phys, _IOC_SIZE(cmd), p);
		return str_to_user(dev->phys, size, p);


			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0)))
	case EVIOCGUNIQ(0):
				return str_to_user(dev->uniq, _IOC_SIZE(cmd), p);
		return str_to_user(dev->uniq, size, p);


			if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
	case EVIOC_MASK_SIZE(EVIOCSFF):
		if (input_ff_effect_from_user(p, size, &effect))
			return -EFAULT;


				t = _IOC_NR(cmd) & ABS_MAX;
		error = input_ff_upload(dev, &effect, file);
				abs = dev->absinfo[t];


				if (copy_to_user(p, &abs, min_t(size_t,
		if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
								_IOC_SIZE(cmd),
								sizeof(struct input_absinfo))))
			return -EFAULT;
			return -EFAULT;


				return 0;
		return error;
	}
	}


		}
	/* Multi-number variable-length handlers */
	if (_IOC_TYPE(cmd) != 'E')
		return -EINVAL;


		if (_IOC_DIR(cmd) == _IOC_WRITE) {
	if (_IOC_DIR(cmd) == _IOC_READ) {


			if (_IOC_NR(cmd) == _IOC_NR(EVIOCSFF)) {
		if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0)))
			return handle_eviocgbit(dev,
						_IOC_NR(cmd) & EV_MAX, size,
						p, compat_mode);


				if (input_ff_effect_from_user(p, _IOC_SIZE(cmd), &effect))
		if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
					return -EFAULT;


				error = input_ff_upload(dev, &effect, file);
			t = _IOC_NR(cmd) & ABS_MAX;
			abs = dev->absinfo[t];


				if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
			if (copy_to_user(p, &abs, min_t(size_t,
					size, sizeof(struct input_absinfo))))
				return -EFAULT;
				return -EFAULT;


				return error;
			return 0;
		}
		}
	}

	if (_IOC_DIR(cmd) == _IOC_READ) {


		if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
		if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {


			t = _IOC_NR(cmd) & ABS_MAX;
			t = _IOC_NR(cmd) & ABS_MAX;


			if (copy_from_user(&abs, p, min_t(size_t,
			if (copy_from_user(&abs, p, min_t(size_t,
								  _IOC_SIZE(cmd),
					size, sizeof(struct input_absinfo))))
								  sizeof(struct input_absinfo))))
				return -EFAULT;
				return -EFAULT;


				if (_IOC_SIZE(cmd) < sizeof(struct input_absinfo))
			if (size < sizeof(struct input_absinfo))
				abs.resolution = 0;
				abs.resolution = 0;


			/* We can't change number of reserved MT slots */
			/* We can't change number of reserved MT slots */
@@ -704,7 +709,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
			return 0;
			return 0;
		}
		}
	}
	}
	}

	return -EINVAL;
	return -EINVAL;
}
}