Commit 448cd1664a573e69f54bfd32f3bb7220212b6cf5
1 parent
d31b2865a4
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 <dtor@mail.ru>
Showing 1 changed file with 73 additions and 68 deletions Side-by-side Diff
drivers/input/evdev.c
... | ... | @@ -492,13 +492,15 @@ |
492 | 492 | } |
493 | 493 | |
494 | 494 | #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) | |
496 | 498 | { |
497 | 499 | static unsigned long keymax_warn_time; |
498 | 500 | unsigned long *bits; |
499 | 501 | int len; |
500 | 502 | |
501 | - switch (_IOC_NR(cmd) & EV_MAX) { | |
503 | + switch (type) { | |
502 | 504 | |
503 | 505 | case 0: bits = dev->evbit; len = EV_MAX; break; |
504 | 506 | case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; |
... | ... | @@ -517,7 +519,7 @@ |
517 | 519 | * EVIOCGBIT(EV_KEY, KEY_MAX) and not realize that 'len' |
518 | 520 | * should be in bytes, not in bits. |
519 | 521 | */ |
520 | - if ((_IOC_NR(cmd) & EV_MAX) == EV_KEY && _IOC_SIZE(cmd) == OLD_KEY_MAX) { | |
522 | + if (type == EV_KEY && size == OLD_KEY_MAX) { | |
521 | 523 | len = OLD_KEY_MAX; |
522 | 524 | if (printk_timed_ratelimit(&keymax_warn_time, 10 * 1000)) |
523 | 525 | printk(KERN_WARNING |
... | ... | @@ -528,7 +530,7 @@ |
528 | 530 | BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long)); |
529 | 531 | } |
530 | 532 | |
531 | - return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode); | |
533 | + return bits_to_user(bits, len, size, p, compat_mode); | |
532 | 534 | } |
533 | 535 | #undef OLD_KEY_MAX |
534 | 536 | |
535 | 537 | |
... | ... | @@ -542,8 +544,10 @@ |
542 | 544 | struct ff_effect effect; |
543 | 545 | int __user *ip = (int __user *)p; |
544 | 546 | unsigned int i, t, u, v; |
547 | + unsigned int size; | |
545 | 548 | int error; |
546 | 549 | |
550 | + /* First we check for fixed-length commands */ | |
547 | 551 | switch (cmd) { |
548 | 552 | |
549 | 553 | case EVIOCGVERSION: |
550 | 554 | |
551 | 555 | |
552 | 556 | |
553 | 557 | |
554 | 558 | |
555 | 559 | |
556 | 560 | |
557 | 561 | |
558 | 562 | |
559 | 563 | |
560 | 564 | |
561 | 565 | |
562 | 566 | |
563 | 567 | |
564 | 568 | |
565 | 569 | |
566 | 570 | |
567 | 571 | |
568 | 572 | |
569 | 573 | |
570 | 574 | |
571 | 575 | |
572 | 576 | |
573 | 577 | |
574 | 578 | |
575 | 579 | |
576 | 580 | |
577 | 581 | |
578 | 582 | |
579 | 583 | |
... | ... | @@ -610,101 +614,102 @@ |
610 | 614 | return evdev_grab(evdev, client); |
611 | 615 | else |
612 | 616 | return evdev_ungrab(evdev, client); |
617 | + } | |
613 | 618 | |
614 | - default: | |
619 | + size = _IOC_SIZE(cmd); | |
615 | 620 | |
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)) | |
618 | 623 | |
619 | - if (_IOC_DIR(cmd) == _IOC_READ) { | |
624 | + switch (EVIOC_MASK_SIZE(cmd)) { | |
620 | 625 | |
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); | |
623 | 628 | |
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); | |
627 | 631 | |
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); | |
631 | 634 | |
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); | |
635 | 637 | |
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); | |
639 | 640 | |
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); | |
642 | 643 | |
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); | |
645 | 646 | |
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; | |
648 | 650 | |
649 | - if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { | |
651 | + error = input_ff_upload(dev, &effect, file); | |
650 | 652 | |
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; | |
653 | 655 | |
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 | + } | |
658 | 658 | |
659 | - return 0; | |
660 | - } | |
659 | + /* Multi-number variable-length handlers */ | |
660 | + if (_IOC_TYPE(cmd) != 'E') | |
661 | + return -EINVAL; | |
661 | 662 | |
662 | - } | |
663 | + if (_IOC_DIR(cmd) == _IOC_READ) { | |
663 | 664 | |
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); | |
665 | 669 | |
666 | - if (_IOC_NR(cmd) == _IOC_NR(EVIOCSFF)) { | |
670 | + if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { | |
667 | 671 | |
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]; | |
670 | 674 | |
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; | |
672 | 678 | |
673 | - if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) | |
674 | - return -EFAULT; | |
679 | + return 0; | |
680 | + } | |
681 | + } | |
675 | 682 | |
676 | - return error; | |
677 | - } | |
683 | + if (_IOC_DIR(cmd) == _IOC_READ) { | |
678 | 684 | |
679 | - if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { | |
685 | + if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { | |
680 | 686 | |
681 | - t = _IOC_NR(cmd) & ABS_MAX; | |
687 | + t = _IOC_NR(cmd) & ABS_MAX; | |
682 | 688 | |
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; | |
687 | 692 | |
688 | - if (_IOC_SIZE(cmd) < sizeof(struct input_absinfo)) | |
689 | - abs.resolution = 0; | |
693 | + if (size < sizeof(struct input_absinfo)) | |
694 | + abs.resolution = 0; | |
690 | 695 | |
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; | |
694 | 699 | |
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); | |
703 | 708 | |
704 | - return 0; | |
705 | - } | |
709 | + return 0; | |
706 | 710 | } |
707 | 711 | } |
712 | + | |
708 | 713 | return -EINVAL; |
709 | 714 | } |
710 | 715 |