diff options
Diffstat (limited to 'drivers/input/input.c')
-rw-r--r-- | drivers/input/input.c | 77 |
1 files changed, 72 insertions, 5 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c index 072bbf528151..0e2e890c0988 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -27,6 +27,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); | |||
27 | MODULE_DESCRIPTION("Input core"); | 27 | MODULE_DESCRIPTION("Input core"); |
28 | MODULE_LICENSE("GPL"); | 28 | MODULE_LICENSE("GPL"); |
29 | 29 | ||
30 | EXPORT_SYMBOL(input_allocate_device); | ||
30 | EXPORT_SYMBOL(input_register_device); | 31 | EXPORT_SYMBOL(input_register_device); |
31 | EXPORT_SYMBOL(input_unregister_device); | 32 | EXPORT_SYMBOL(input_unregister_device); |
32 | EXPORT_SYMBOL(input_register_handler); | 33 | EXPORT_SYMBOL(input_register_handler); |
@@ -605,6 +606,56 @@ static inline int input_proc_init(void) { return 0; } | |||
605 | static inline void input_proc_exit(void) { } | 606 | static inline void input_proc_exit(void) { } |
606 | #endif | 607 | #endif |
607 | 608 | ||
609 | static void input_dev_release(struct class_device *class_dev) | ||
610 | { | ||
611 | struct input_dev *dev = to_input_dev(class_dev); | ||
612 | |||
613 | kfree(dev); | ||
614 | module_put(THIS_MODULE); | ||
615 | } | ||
616 | |||
617 | static struct class input_dev_class = { | ||
618 | .name = "input_dev", | ||
619 | .release = input_dev_release, | ||
620 | }; | ||
621 | |||
622 | struct input_dev *input_allocate_device(void) | ||
623 | { | ||
624 | struct input_dev *dev; | ||
625 | |||
626 | dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL); | ||
627 | if (dev) { | ||
628 | dev->dynalloc = 1; | ||
629 | dev->cdev.class = &input_dev_class; | ||
630 | class_device_initialize(&dev->cdev); | ||
631 | INIT_LIST_HEAD(&dev->h_list); | ||
632 | INIT_LIST_HEAD(&dev->node); | ||
633 | } | ||
634 | |||
635 | return dev; | ||
636 | } | ||
637 | |||
638 | static void input_register_classdevice(struct input_dev *dev) | ||
639 | { | ||
640 | static atomic_t input_no = ATOMIC_INIT(0); | ||
641 | const char *path; | ||
642 | |||
643 | __module_get(THIS_MODULE); | ||
644 | |||
645 | dev->dev = dev->cdev.dev; | ||
646 | |||
647 | snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id), | ||
648 | "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1); | ||
649 | |||
650 | path = kobject_get_path(&dev->cdev.class->subsys.kset.kobj, GFP_KERNEL); | ||
651 | printk(KERN_INFO "input: %s/%s as %s\n", | ||
652 | dev->name ? dev->name : "Unspecified device", | ||
653 | path ? path : "", dev->cdev.class_id); | ||
654 | kfree(path); | ||
655 | |||
656 | class_device_add(&dev->cdev); | ||
657 | } | ||
658 | |||
608 | void input_register_device(struct input_dev *dev) | 659 | void input_register_device(struct input_dev *dev) |
609 | { | 660 | { |
610 | struct input_handle *handle; | 661 | struct input_handle *handle; |
@@ -637,6 +688,10 @@ void input_register_device(struct input_dev *dev) | |||
637 | if ((handle = handler->connect(handler, dev, id))) | 688 | if ((handle = handler->connect(handler, dev, id))) |
638 | input_link_handle(handle); | 689 | input_link_handle(handle); |
639 | 690 | ||
691 | |||
692 | if (dev->dynalloc) | ||
693 | input_register_classdevice(dev); | ||
694 | |||
640 | #ifdef CONFIG_HOTPLUG | 695 | #ifdef CONFIG_HOTPLUG |
641 | input_call_hotplug("add", dev); | 696 | input_call_hotplug("add", dev); |
642 | #endif | 697 | #endif |
@@ -665,6 +720,9 @@ void input_unregister_device(struct input_dev *dev) | |||
665 | 720 | ||
666 | list_del_init(&dev->node); | 721 | list_del_init(&dev->node); |
667 | 722 | ||
723 | if (dev->dynalloc) | ||
724 | class_device_unregister(&dev->cdev); | ||
725 | |||
668 | input_wakeup_procfs_readers(); | 726 | input_wakeup_procfs_readers(); |
669 | } | 727 | } |
670 | 728 | ||
@@ -753,26 +811,34 @@ static int __init input_init(void) | |||
753 | { | 811 | { |
754 | int err; | 812 | int err; |
755 | 813 | ||
814 | err = class_register(&input_dev_class); | ||
815 | if (err) { | ||
816 | printk(KERN_ERR "input: unable to register input_dev class\n"); | ||
817 | return err; | ||
818 | } | ||
819 | |||
756 | input_class = class_create(THIS_MODULE, "input"); | 820 | input_class = class_create(THIS_MODULE, "input"); |
757 | if (IS_ERR(input_class)) { | 821 | if (IS_ERR(input_class)) { |
758 | printk(KERN_ERR "input: unable to register input class\n"); | 822 | printk(KERN_ERR "input: unable to register input class\n"); |
759 | return PTR_ERR(input_class); | 823 | err = PTR_ERR(input_class); |
824 | goto fail1; | ||
760 | } | 825 | } |
761 | 826 | ||
762 | err = input_proc_init(); | 827 | err = input_proc_init(); |
763 | if (err) | 828 | if (err) |
764 | goto fail1; | 829 | goto fail2; |
765 | 830 | ||
766 | err = register_chrdev(INPUT_MAJOR, "input", &input_fops); | 831 | err = register_chrdev(INPUT_MAJOR, "input", &input_fops); |
767 | if (err) { | 832 | if (err) { |
768 | printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR); | 833 | printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR); |
769 | goto fail2; | 834 | goto fail3; |
770 | } | 835 | } |
771 | 836 | ||
772 | return 0; | 837 | return 0; |
773 | 838 | ||
774 | fail2: input_proc_exit(); | 839 | fail3: input_proc_exit(); |
775 | fail1: class_destroy(input_class); | 840 | fail2: class_destroy(input_class); |
841 | fail1: class_unregister(&input_dev_class); | ||
776 | return err; | 842 | return err; |
777 | } | 843 | } |
778 | 844 | ||
@@ -781,6 +847,7 @@ static void __exit input_exit(void) | |||
781 | input_proc_exit(); | 847 | input_proc_exit(); |
782 | unregister_chrdev(INPUT_MAJOR, "input"); | 848 | unregister_chrdev(INPUT_MAJOR, "input"); |
783 | class_destroy(input_class); | 849 | class_destroy(input_class); |
850 | class_unregister(&input_dev_class); | ||
784 | } | 851 | } |
785 | 852 | ||
786 | subsys_initcall(input_init); | 853 | subsys_initcall(input_init); |