Skip to content

Commit 448cd16

Browse files
committed
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: Dmitry Torokhov <[email protected]>
1 parent d31b286 commit 448cd16

File tree

1 file changed

+73
-68
lines changed

1 file changed

+73
-68
lines changed

drivers/input/evdev.c

Lines changed: 73 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -492,13 +492,15 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p)
492492
}
493493

494494
#define OLD_KEY_MAX 0x1ff
495-
static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user *p, int compat_mode)
495+
static int handle_eviocgbit(struct input_dev *dev,
496+
unsigned int type, unsigned int size,
497+
void __user *p, int compat_mode)
496498
{
497499
static unsigned long keymax_warn_time;
498500
unsigned long *bits;
499501
int len;
500502

501-
switch (_IOC_NR(cmd) & EV_MAX) {
503+
switch (type) {
502504

503505
case 0: bits = dev->evbit; len = EV_MAX; break;
504506
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
517519
* EVIOCGBIT(EV_KEY, KEY_MAX) and not realize that 'len'
518520
* should be in bytes, not in bits.
519521
*/
520-
if ((_IOC_NR(cmd) & EV_MAX) == EV_KEY && _IOC_SIZE(cmd) == OLD_KEY_MAX) {
522+
if (type == EV_KEY && size == OLD_KEY_MAX) {
521523
len = OLD_KEY_MAX;
522524
if (printk_timed_ratelimit(&keymax_warn_time, 10 * 1000))
523525
printk(KERN_WARNING
@@ -528,7 +530,7 @@ static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user
528530
BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long));
529531
}
530532

531-
return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode);
533+
return bits_to_user(bits, len, size, p, compat_mode);
532534
}
533535
#undef OLD_KEY_MAX
534536

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

550+
/* First we check for fixed-length commands */
547551
switch (cmd) {
548552

549553
case EVIOCGVERSION:
@@ -610,101 +614,102 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
610614
return evdev_grab(evdev, client);
611615
else
612616
return evdev_ungrab(evdev, client);
617+
}
613618

614-
default:
619+
size = _IOC_SIZE(cmd);
615620

616-
if (_IOC_TYPE(cmd) != 'E')
617-
return -EINVAL;
621+
/* Now check variable-length commands */
622+
#define EVIOC_MASK_SIZE(nr) ((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
618623

619-
if (_IOC_DIR(cmd) == _IOC_READ) {
624+
switch (EVIOC_MASK_SIZE(cmd)) {
620625

621-
if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0)))
622-
return handle_eviocgbit(dev, cmd, p, compat_mode);
626+
case EVIOCGKEY(0):
627+
return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode);
623628

624-
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
625-
return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd),
626-
p, compat_mode);
629+
case EVIOCGLED(0):
630+
return bits_to_user(dev->led, LED_MAX, size, p, compat_mode);
627631

628-
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
629-
return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd),
630-
p, compat_mode);
632+
case EVIOCGSND(0):
633+
return bits_to_user(dev->snd, SND_MAX, size, p, compat_mode);
631634

632-
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
633-
return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd),
634-
p, compat_mode);
635+
case EVIOCGSW(0):
636+
return bits_to_user(dev->sw, SW_MAX, size, p, compat_mode);
635637

636-
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0)))
637-
return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd),
638-
p, compat_mode);
638+
case EVIOCGNAME(0):
639+
return str_to_user(dev->name, size, p);
639640

640-
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0)))
641-
return str_to_user(dev->name, _IOC_SIZE(cmd), p);
641+
case EVIOCGPHYS(0):
642+
return str_to_user(dev->phys, size, p);
642643

643-
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0)))
644-
return str_to_user(dev->phys, _IOC_SIZE(cmd), p);
644+
case EVIOCGUNIQ(0):
645+
return str_to_user(dev->uniq, size, p);
645646

646-
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0)))
647-
return str_to_user(dev->uniq, _IOC_SIZE(cmd), p);
647+
case EVIOC_MASK_SIZE(EVIOCSFF):
648+
if (input_ff_effect_from_user(p, size, &effect))
649+
return -EFAULT;
648650

649-
if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
651+
error = input_ff_upload(dev, &effect, file);
650652

651-
t = _IOC_NR(cmd) & ABS_MAX;
652-
abs = dev->absinfo[t];
653+
if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
654+
return -EFAULT;
653655

654-
if (copy_to_user(p, &abs, min_t(size_t,
655-
_IOC_SIZE(cmd),
656-
sizeof(struct input_absinfo))))
657-
return -EFAULT;
656+
return error;
657+
}
658658

659-
return 0;
660-
}
659+
/* Multi-number variable-length handlers */
660+
if (_IOC_TYPE(cmd) != 'E')
661+
return -EINVAL;
661662

662-
}
663+
if (_IOC_DIR(cmd) == _IOC_READ) {
663664

664-
if (_IOC_DIR(cmd) == _IOC_WRITE) {
665+
if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0)))
666+
return handle_eviocgbit(dev,
667+
_IOC_NR(cmd) & EV_MAX, size,
668+
p, compat_mode);
665669

666-
if (_IOC_NR(cmd) == _IOC_NR(EVIOCSFF)) {
670+
if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
667671

668-
if (input_ff_effect_from_user(p, _IOC_SIZE(cmd), &effect))
669-
return -EFAULT;
672+
t = _IOC_NR(cmd) & ABS_MAX;
673+
abs = dev->absinfo[t];
670674

671-
error = input_ff_upload(dev, &effect, file);
675+
if (copy_to_user(p, &abs, min_t(size_t,
676+
size, sizeof(struct input_absinfo))))
677+
return -EFAULT;
672678

673-
if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
674-
return -EFAULT;
679+
return 0;
680+
}
681+
}
675682

676-
return error;
677-
}
683+
if (_IOC_DIR(cmd) == _IOC_READ) {
678684

679-
if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
685+
if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
680686

681-
t = _IOC_NR(cmd) & ABS_MAX;
687+
t = _IOC_NR(cmd) & ABS_MAX;
682688

683-
if (copy_from_user(&abs, p, min_t(size_t,
684-
_IOC_SIZE(cmd),
685-
sizeof(struct input_absinfo))))
686-
return -EFAULT;
689+
if (copy_from_user(&abs, p, min_t(size_t,
690+
size, sizeof(struct input_absinfo))))
691+
return -EFAULT;
687692

688-
if (_IOC_SIZE(cmd) < sizeof(struct input_absinfo))
689-
abs.resolution = 0;
693+
if (size < sizeof(struct input_absinfo))
694+
abs.resolution = 0;
690695

691-
/* We can't change number of reserved MT slots */
692-
if (t == ABS_MT_SLOT)
693-
return -EINVAL;
696+
/* We can't change number of reserved MT slots */
697+
if (t == ABS_MT_SLOT)
698+
return -EINVAL;
694699

695-
/*
696-
* Take event lock to ensure that we are not
697-
* changing device parameters in the middle
698-
* of event.
699-
*/
700-
spin_lock_irq(&dev->event_lock);
701-
dev->absinfo[t] = abs;
702-
spin_unlock_irq(&dev->event_lock);
700+
/*
701+
* Take event lock to ensure that we are not
702+
* changing device parameters in the middle
703+
* of event.
704+
*/
705+
spin_lock_irq(&dev->event_lock);
706+
dev->absinfo[t] = abs;
707+
spin_unlock_irq(&dev->event_lock);
703708

704-
return 0;
705-
}
709+
return 0;
706710
}
707711
}
712+
708713
return -EINVAL;
709714
}
710715

0 commit comments

Comments
 (0)