aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/evdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/evdev.c')
-rw-r--r--drivers/input/evdev.c47
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
608static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev, 608static 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
648static void evdev_disconnect(struct input_handle *handle) 671static 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));