diff options
Diffstat (limited to 'drivers/input/mousedev.c')
-rw-r--r-- | drivers/input/mousedev.c | 61 |
1 files changed, 46 insertions, 15 deletions
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 664bcc8116fc..007e72f80251 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c | |||
@@ -624,23 +624,27 @@ static const struct file_operations mousedev_fops = { | |||
624 | .fasync = mousedev_fasync, | 624 | .fasync = mousedev_fasync, |
625 | }; | 625 | }; |
626 | 626 | ||
627 | static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev, | 627 | static int mousedev_connect(struct input_handler *handler, struct input_dev *dev, |
628 | const struct input_device_id *id) | 628 | const struct input_device_id *id) |
629 | { | 629 | { |
630 | struct mousedev *mousedev; | 630 | struct mousedev *mousedev; |
631 | struct class_device *cdev; | 631 | struct class_device *cdev; |
632 | int minor = 0; | 632 | dev_t devt; |
633 | int minor; | ||
634 | int error; | ||
633 | 635 | ||
634 | for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++); | 636 | for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++); |
635 | if (minor == MOUSEDEV_MINORS) { | 637 | if (minor == MOUSEDEV_MINORS) { |
636 | printk(KERN_ERR "mousedev: no more free mousedev devices\n"); | 638 | printk(KERN_ERR "mousedev: no more free mousedev devices\n"); |
637 | return NULL; | 639 | return -ENFILE; |
638 | } | 640 | } |
639 | 641 | ||
640 | if (!(mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL))) | 642 | mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL); |
641 | return NULL; | 643 | if (!mousedev) |
644 | return -ENOMEM; | ||
642 | 645 | ||
643 | INIT_LIST_HEAD(&mousedev->list); | 646 | INIT_LIST_HEAD(&mousedev->list); |
647 | INIT_LIST_HEAD(&mousedev->mixdev_node); | ||
644 | init_waitqueue_head(&mousedev->wait); | 648 | init_waitqueue_head(&mousedev->wait); |
645 | 649 | ||
646 | mousedev->minor = minor; | 650 | mousedev->minor = minor; |
@@ -651,20 +655,45 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru | |||
651 | mousedev->handle.private = mousedev; | 655 | mousedev->handle.private = mousedev; |
652 | sprintf(mousedev->name, "mouse%d", minor); | 656 | sprintf(mousedev->name, "mouse%d", minor); |
653 | 657 | ||
654 | if (mousedev_mix.open) | ||
655 | input_open_device(&mousedev->handle); | ||
656 | |||
657 | mousedev_table[minor] = mousedev; | 658 | mousedev_table[minor] = mousedev; |
658 | 659 | ||
659 | cdev = class_device_create(&input_class, &dev->cdev, | 660 | devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor), |
660 | MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor), | 661 | |
661 | dev->cdev.dev, mousedev->name); | 662 | cdev = class_device_create(&input_class, &dev->cdev, devt, |
663 | dev->cdev.dev, mousedev->name); | ||
664 | if (IS_ERR(cdev)) { | ||
665 | error = PTR_ERR(cdev); | ||
666 | goto err_free_mousedev; | ||
667 | } | ||
662 | 668 | ||
663 | /* temporary symlink to keep userspace happy */ | 669 | /* temporary symlink to keep userspace happy */ |
664 | sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj, | 670 | error = sysfs_create_link(&input_class.subsys.kset.kobj, |
665 | mousedev->name); | 671 | &cdev->kobj, mousedev->name); |
672 | if (error) | ||
673 | goto err_cdev_destroy; | ||
666 | 674 | ||
667 | return &mousedev->handle; | 675 | error = input_register_handle(&mousedev->handle); |
676 | if (error) | ||
677 | goto err_remove_link; | ||
678 | |||
679 | if (mousedev_mix.open) { | ||
680 | error = input_open_device(&mousedev->handle); | ||
681 | if (error) | ||
682 | goto err_unregister_handle; | ||
683 | } | ||
684 | |||
685 | return 0; | ||
686 | |||
687 | err_unregister_handle: | ||
688 | input_unregister_handle(&mousedev->handle); | ||
689 | err_remove_link: | ||
690 | sysfs_remove_link(&input_class.subsys.kset.kobj, mousedev->name); | ||
691 | err_cdev_destroy: | ||
692 | class_device_destroy(&input_class, devt); | ||
693 | err_free_mousedev: | ||
694 | mousedev_table[minor] = NULL; | ||
695 | kfree(mousedev); | ||
696 | return error; | ||
668 | } | 697 | } |
669 | 698 | ||
670 | static void mousedev_disconnect(struct input_handle *handle) | 699 | static void mousedev_disconnect(struct input_handle *handle) |
@@ -672,6 +701,8 @@ static void mousedev_disconnect(struct input_handle *handle) | |||
672 | struct mousedev *mousedev = handle->private; | 701 | struct mousedev *mousedev = handle->private; |
673 | struct mousedev_list *list; | 702 | struct mousedev_list *list; |
674 | 703 | ||
704 | input_unregister_handle(handle); | ||
705 | |||
675 | sysfs_remove_link(&input_class.subsys.kset.kobj, mousedev->name); | 706 | sysfs_remove_link(&input_class.subsys.kset.kobj, mousedev->name); |
676 | class_device_destroy(&input_class, | 707 | class_device_destroy(&input_class, |
677 | MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor)); | 708 | MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor)); |