diff options
Diffstat (limited to 'drivers/input/evdev.c')
-rw-r--r-- | drivers/input/evdev.c | 47 |
1 files changed, 36 insertions, 11 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 64b47de052bb..840fa1986527 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -605,21 +605,24 @@ static const struct file_operations evdev_fops = { | |||
605 | .flush = evdev_flush | 605 | .flush = evdev_flush |
606 | }; | 606 | }; |
607 | 607 | ||
608 | static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev, | 608 | static int evdev_connect(struct input_handler *handler, struct input_dev *dev, |
609 | const struct input_device_id *id) | 609 | const struct input_device_id *id) |
610 | { | 610 | { |
611 | struct evdev *evdev; | 611 | struct evdev *evdev; |
612 | struct class_device *cdev; | 612 | struct class_device *cdev; |
613 | dev_t devt; | ||
613 | int minor; | 614 | int minor; |
615 | int error; | ||
614 | 616 | ||
615 | for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++); | 617 | for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++); |
616 | if (minor == EVDEV_MINORS) { | 618 | if (minor == EVDEV_MINORS) { |
617 | printk(KERN_ERR "evdev: no more free evdev devices\n"); | 619 | printk(KERN_ERR "evdev: no more free evdev devices\n"); |
618 | return NULL; | 620 | return -ENFILE; |
619 | } | 621 | } |
620 | 622 | ||
621 | if (!(evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL))) | 623 | evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL); |
622 | return NULL; | 624 | if (!evdev) |
625 | return -ENOMEM; | ||
623 | 626 | ||
624 | INIT_LIST_HEAD(&evdev->list); | 627 | INIT_LIST_HEAD(&evdev->list); |
625 | init_waitqueue_head(&evdev->wait); | 628 | init_waitqueue_head(&evdev->wait); |
@@ -634,15 +637,35 @@ static struct input_handle *evdev_connect(struct input_handler *handler, struct | |||
634 | 637 | ||
635 | evdev_table[minor] = evdev; | 638 | evdev_table[minor] = evdev; |
636 | 639 | ||
637 | cdev = class_device_create(&input_class, &dev->cdev, | 640 | devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor), |
638 | MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor), | 641 | |
639 | dev->cdev.dev, evdev->name); | 642 | cdev = class_device_create(&input_class, &dev->cdev, devt, |
643 | dev->cdev.dev, evdev->name); | ||
644 | if (IS_ERR(cdev)) { | ||
645 | error = PTR_ERR(cdev); | ||
646 | goto err_free_evdev; | ||
647 | } | ||
640 | 648 | ||
641 | /* temporary symlink to keep userspace happy */ | 649 | /* temporary symlink to keep userspace happy */ |
642 | sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj, | 650 | error = sysfs_create_link(&input_class.subsys.kset.kobj, |
643 | evdev->name); | 651 | &cdev->kobj, evdev->name); |
652 | if (error) | ||
653 | goto err_cdev_destroy; | ||
654 | |||
655 | error = input_register_handle(&evdev->handle); | ||
656 | if (error) | ||
657 | goto err_remove_link; | ||
644 | 658 | ||
645 | return &evdev->handle; | 659 | return 0; |
660 | |||
661 | err_remove_link: | ||
662 | sysfs_remove_link(&input_class.subsys.kset.kobj, evdev->name); | ||
663 | err_cdev_destroy: | ||
664 | class_device_destroy(&input_class, devt); | ||
665 | err_free_evdev: | ||
666 | kfree(evdev); | ||
667 | evdev_table[minor] = NULL; | ||
668 | return error; | ||
646 | } | 669 | } |
647 | 670 | ||
648 | static void evdev_disconnect(struct input_handle *handle) | 671 | static void evdev_disconnect(struct input_handle *handle) |
@@ -650,6 +673,8 @@ static void evdev_disconnect(struct input_handle *handle) | |||
650 | struct evdev *evdev = handle->private; | 673 | struct evdev *evdev = handle->private; |
651 | struct evdev_list *list; | 674 | struct evdev_list *list; |
652 | 675 | ||
676 | input_unregister_handle(handle); | ||
677 | |||
653 | sysfs_remove_link(&input_class.subsys.kset.kobj, evdev->name); | 678 | sysfs_remove_link(&input_class.subsys.kset.kobj, evdev->name); |
654 | class_device_destroy(&input_class, | 679 | class_device_destroy(&input_class, |
655 | MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor)); | 680 | MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor)); |