diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/input/evdev.c | 84 | ||||
-rw-r--r-- | drivers/input/input.c | 136 | ||||
-rw-r--r-- | drivers/input/joydev.c | 84 | ||||
-rw-r--r-- | drivers/input/mousedev.c | 242 | ||||
-rw-r--r-- | drivers/input/tsdev.c | 88 |
5 files changed, 335 insertions, 299 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index be6b93c20f60..ab4b2d9b5327 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -30,6 +30,7 @@ struct evdev { | |||
30 | wait_queue_head_t wait; | 30 | wait_queue_head_t wait; |
31 | struct evdev_client *grab; | 31 | struct evdev_client *grab; |
32 | struct list_head client_list; | 32 | struct list_head client_list; |
33 | struct device dev; | ||
33 | }; | 34 | }; |
34 | 35 | ||
35 | struct evdev_client { | 36 | struct evdev_client { |
@@ -94,8 +95,10 @@ static int evdev_flush(struct file *file, fl_owner_t id) | |||
94 | return input_flush_device(&evdev->handle, file); | 95 | return input_flush_device(&evdev->handle, file); |
95 | } | 96 | } |
96 | 97 | ||
97 | static void evdev_free(struct evdev *evdev) | 98 | static void evdev_free(struct device *dev) |
98 | { | 99 | { |
100 | struct evdev *evdev = container_of(dev, struct evdev, dev); | ||
101 | |||
99 | evdev_table[evdev->minor] = NULL; | 102 | evdev_table[evdev->minor] = NULL; |
100 | kfree(evdev); | 103 | kfree(evdev); |
101 | } | 104 | } |
@@ -114,12 +117,10 @@ static int evdev_release(struct inode *inode, struct file *file) | |||
114 | list_del(&client->node); | 117 | list_del(&client->node); |
115 | kfree(client); | 118 | kfree(client); |
116 | 119 | ||
117 | if (!--evdev->open) { | 120 | if (!--evdev->open && evdev->exist) |
118 | if (evdev->exist) | 121 | input_close_device(&evdev->handle); |
119 | input_close_device(&evdev->handle); | 122 | |
120 | else | 123 | put_device(&evdev->dev); |
121 | evdev_free(evdev); | ||
122 | } | ||
123 | 124 | ||
124 | return 0; | 125 | return 0; |
125 | } | 126 | } |
@@ -139,24 +140,32 @@ static int evdev_open(struct inode *inode, struct file *file) | |||
139 | if (!evdev || !evdev->exist) | 140 | if (!evdev || !evdev->exist) |
140 | return -ENODEV; | 141 | return -ENODEV; |
141 | 142 | ||
143 | get_device(&evdev->dev); | ||
144 | |||
142 | client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL); | 145 | client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL); |
143 | if (!client) | 146 | if (!client) { |
144 | return -ENOMEM; | 147 | error = -ENOMEM; |
148 | goto err_put_evdev; | ||
149 | } | ||
145 | 150 | ||
146 | client->evdev = evdev; | 151 | client->evdev = evdev; |
147 | list_add_tail(&client->node, &evdev->client_list); | 152 | list_add_tail(&client->node, &evdev->client_list); |
148 | 153 | ||
149 | if (!evdev->open++ && evdev->exist) { | 154 | if (!evdev->open++ && evdev->exist) { |
150 | error = input_open_device(&evdev->handle); | 155 | error = input_open_device(&evdev->handle); |
151 | if (error) { | 156 | if (error) |
152 | list_del(&client->node); | 157 | goto err_free_client; |
153 | kfree(client); | ||
154 | return error; | ||
155 | } | ||
156 | } | 158 | } |
157 | 159 | ||
158 | file->private_data = client; | 160 | file->private_data = client; |
159 | return 0; | 161 | return 0; |
162 | |||
163 | err_free_client: | ||
164 | list_del(&client->node); | ||
165 | kfree(client); | ||
166 | err_put_evdev: | ||
167 | put_device(&evdev->dev); | ||
168 | return error; | ||
160 | } | 169 | } |
161 | 170 | ||
162 | #ifdef CONFIG_COMPAT | 171 | #ifdef CONFIG_COMPAT |
@@ -625,8 +634,6 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, | |||
625 | const struct input_device_id *id) | 634 | const struct input_device_id *id) |
626 | { | 635 | { |
627 | struct evdev *evdev; | 636 | struct evdev *evdev; |
628 | struct class_device *cdev; | ||
629 | dev_t devt; | ||
630 | int minor; | 637 | int minor; |
631 | int error; | 638 | int error; |
632 | 639 | ||
@@ -649,38 +656,32 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, | |||
649 | evdev->handle.name = evdev->name; | 656 | evdev->handle.name = evdev->name; |
650 | evdev->handle.handler = handler; | 657 | evdev->handle.handler = handler; |
651 | evdev->handle.private = evdev; | 658 | evdev->handle.private = evdev; |
652 | sprintf(evdev->name, "event%d", minor); | 659 | snprintf(evdev->name, sizeof(evdev->name), "event%d", minor); |
653 | |||
654 | evdev_table[minor] = evdev; | ||
655 | 660 | ||
656 | devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor), | 661 | snprintf(evdev->dev.bus_id, sizeof(evdev->dev.bus_id), |
662 | "event%d", minor); | ||
663 | evdev->dev.class = &input_class; | ||
664 | evdev->dev.parent = &dev->dev; | ||
665 | evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); | ||
666 | evdev->dev.release = evdev_free; | ||
667 | device_initialize(&evdev->dev); | ||
657 | 668 | ||
658 | cdev = class_device_create(&input_class, &dev->cdev, devt, | 669 | evdev_table[minor] = evdev; |
659 | dev->cdev.dev, evdev->name); | ||
660 | if (IS_ERR(cdev)) { | ||
661 | error = PTR_ERR(cdev); | ||
662 | goto err_free_evdev; | ||
663 | } | ||
664 | 670 | ||
665 | /* temporary symlink to keep userspace happy */ | 671 | error = device_add(&evdev->dev); |
666 | error = sysfs_create_link(&input_class.subsys.kobj, | ||
667 | &cdev->kobj, evdev->name); | ||
668 | if (error) | 672 | if (error) |
669 | goto err_cdev_destroy; | 673 | goto err_free_evdev; |
670 | 674 | ||
671 | error = input_register_handle(&evdev->handle); | 675 | error = input_register_handle(&evdev->handle); |
672 | if (error) | 676 | if (error) |
673 | goto err_remove_link; | 677 | goto err_delete_evdev; |
674 | 678 | ||
675 | return 0; | 679 | return 0; |
676 | 680 | ||
677 | err_remove_link: | 681 | err_delete_evdev: |
678 | sysfs_remove_link(&input_class.subsys.kobj, evdev->name); | 682 | device_del(&evdev->dev); |
679 | err_cdev_destroy: | ||
680 | class_device_destroy(&input_class, devt); | ||
681 | err_free_evdev: | 683 | err_free_evdev: |
682 | kfree(evdev); | 684 | put_device(&evdev->dev); |
683 | evdev_table[minor] = NULL; | ||
684 | return error; | 685 | return error; |
685 | } | 686 | } |
686 | 687 | ||
@@ -690,10 +691,8 @@ static void evdev_disconnect(struct input_handle *handle) | |||
690 | struct evdev_client *client; | 691 | struct evdev_client *client; |
691 | 692 | ||
692 | input_unregister_handle(handle); | 693 | input_unregister_handle(handle); |
694 | device_del(&evdev->dev); | ||
693 | 695 | ||
694 | sysfs_remove_link(&input_class.subsys.kobj, evdev->name); | ||
695 | class_device_destroy(&input_class, | ||
696 | MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor)); | ||
697 | evdev->exist = 0; | 696 | evdev->exist = 0; |
698 | 697 | ||
699 | if (evdev->open) { | 698 | if (evdev->open) { |
@@ -702,8 +701,9 @@ static void evdev_disconnect(struct input_handle *handle) | |||
702 | list_for_each_entry(client, &evdev->client_list, node) | 701 | list_for_each_entry(client, &evdev->client_list, node) |
703 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | 702 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); |
704 | wake_up_interruptible(&evdev->wait); | 703 | wake_up_interruptible(&evdev->wait); |
705 | } else | 704 | } |
706 | evdev_free(evdev); | 705 | |
706 | put_device(&evdev->dev); | ||
707 | } | 707 | } |
708 | 708 | ||
709 | static const struct input_device_id evdev_ids[] = { | 709 | static const struct input_device_id evdev_ids[] = { |
diff --git a/drivers/input/input.c b/drivers/input/input.c index ccd8abafcb70..75b4d2a83dd9 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -442,7 +442,7 @@ static int input_attach_handler(struct input_dev *dev, struct input_handler *han | |||
442 | printk(KERN_ERR | 442 | printk(KERN_ERR |
443 | "input: failed to attach handler %s to device %s, " | 443 | "input: failed to attach handler %s to device %s, " |
444 | "error: %d\n", | 444 | "error: %d\n", |
445 | handler->name, kobject_name(&dev->cdev.kobj), error); | 445 | handler->name, kobject_name(&dev->dev.kobj), error); |
446 | 446 | ||
447 | return error; | 447 | return error; |
448 | } | 448 | } |
@@ -527,7 +527,7 @@ static void input_seq_print_bitmap(struct seq_file *seq, const char *name, | |||
527 | static int input_devices_seq_show(struct seq_file *seq, void *v) | 527 | static int input_devices_seq_show(struct seq_file *seq, void *v) |
528 | { | 528 | { |
529 | struct input_dev *dev = container_of(v, struct input_dev, node); | 529 | struct input_dev *dev = container_of(v, struct input_dev, node); |
530 | const char *path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL); | 530 | const char *path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); |
531 | struct input_handle *handle; | 531 | struct input_handle *handle; |
532 | 532 | ||
533 | seq_printf(seq, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n", | 533 | seq_printf(seq, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n", |
@@ -682,15 +682,17 @@ static inline int input_proc_init(void) { return 0; } | |||
682 | static inline void input_proc_exit(void) { } | 682 | static inline void input_proc_exit(void) { } |
683 | #endif | 683 | #endif |
684 | 684 | ||
685 | #define INPUT_DEV_STRING_ATTR_SHOW(name) \ | 685 | #define INPUT_DEV_STRING_ATTR_SHOW(name) \ |
686 | static ssize_t input_dev_show_##name(struct class_device *dev, char *buf) \ | 686 | static ssize_t input_dev_show_##name(struct device *dev, \ |
687 | { \ | 687 | struct device_attribute *attr, \ |
688 | struct input_dev *input_dev = to_input_dev(dev); \ | 688 | char *buf) \ |
689 | \ | 689 | { \ |
690 | return scnprintf(buf, PAGE_SIZE, "%s\n", \ | 690 | struct input_dev *input_dev = to_input_dev(dev); \ |
691 | input_dev->name ? input_dev->name : ""); \ | 691 | \ |
692 | } \ | 692 | return scnprintf(buf, PAGE_SIZE, "%s\n", \ |
693 | static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL); | 693 | input_dev->name ? input_dev->name : ""); \ |
694 | } \ | ||
695 | static DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL) | ||
694 | 696 | ||
695 | INPUT_DEV_STRING_ATTR_SHOW(name); | 697 | INPUT_DEV_STRING_ATTR_SHOW(name); |
696 | INPUT_DEV_STRING_ATTR_SHOW(phys); | 698 | INPUT_DEV_STRING_ATTR_SHOW(phys); |
@@ -744,7 +746,9 @@ static int input_print_modalias(char *buf, int size, struct input_dev *id, | |||
744 | return len; | 746 | return len; |
745 | } | 747 | } |
746 | 748 | ||
747 | static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf) | 749 | static ssize_t input_dev_show_modalias(struct device *dev, |
750 | struct device_attribute *attr, | ||
751 | char *buf) | ||
748 | { | 752 | { |
749 | struct input_dev *id = to_input_dev(dev); | 753 | struct input_dev *id = to_input_dev(dev); |
750 | ssize_t len; | 754 | ssize_t len; |
@@ -753,13 +757,13 @@ static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf) | |||
753 | 757 | ||
754 | return min_t(int, len, PAGE_SIZE); | 758 | return min_t(int, len, PAGE_SIZE); |
755 | } | 759 | } |
756 | static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); | 760 | static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); |
757 | 761 | ||
758 | static struct attribute *input_dev_attrs[] = { | 762 | static struct attribute *input_dev_attrs[] = { |
759 | &class_device_attr_name.attr, | 763 | &dev_attr_name.attr, |
760 | &class_device_attr_phys.attr, | 764 | &dev_attr_phys.attr, |
761 | &class_device_attr_uniq.attr, | 765 | &dev_attr_uniq.attr, |
762 | &class_device_attr_modalias.attr, | 766 | &dev_attr_modalias.attr, |
763 | NULL | 767 | NULL |
764 | }; | 768 | }; |
765 | 769 | ||
@@ -767,13 +771,15 @@ static struct attribute_group input_dev_attr_group = { | |||
767 | .attrs = input_dev_attrs, | 771 | .attrs = input_dev_attrs, |
768 | }; | 772 | }; |
769 | 773 | ||
770 | #define INPUT_DEV_ID_ATTR(name) \ | 774 | #define INPUT_DEV_ID_ATTR(name) \ |
771 | static ssize_t input_dev_show_id_##name(struct class_device *dev, char *buf) \ | 775 | static ssize_t input_dev_show_id_##name(struct device *dev, \ |
772 | { \ | 776 | struct device_attribute *attr, \ |
773 | struct input_dev *input_dev = to_input_dev(dev); \ | 777 | char *buf) \ |
774 | return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name); \ | 778 | { \ |
775 | } \ | 779 | struct input_dev *input_dev = to_input_dev(dev); \ |
776 | static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL); | 780 | return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name); \ |
781 | } \ | ||
782 | static DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL) | ||
777 | 783 | ||
778 | INPUT_DEV_ID_ATTR(bustype); | 784 | INPUT_DEV_ID_ATTR(bustype); |
779 | INPUT_DEV_ID_ATTR(vendor); | 785 | INPUT_DEV_ID_ATTR(vendor); |
@@ -781,10 +787,10 @@ INPUT_DEV_ID_ATTR(product); | |||
781 | INPUT_DEV_ID_ATTR(version); | 787 | INPUT_DEV_ID_ATTR(version); |
782 | 788 | ||
783 | static struct attribute *input_dev_id_attrs[] = { | 789 | static struct attribute *input_dev_id_attrs[] = { |
784 | &class_device_attr_bustype.attr, | 790 | &dev_attr_bustype.attr, |
785 | &class_device_attr_vendor.attr, | 791 | &dev_attr_vendor.attr, |
786 | &class_device_attr_product.attr, | 792 | &dev_attr_product.attr, |
787 | &class_device_attr_version.attr, | 793 | &dev_attr_version.attr, |
788 | NULL | 794 | NULL |
789 | }; | 795 | }; |
790 | 796 | ||
@@ -813,15 +819,17 @@ static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, | |||
813 | return len; | 819 | return len; |
814 | } | 820 | } |
815 | 821 | ||
816 | #define INPUT_DEV_CAP_ATTR(ev, bm) \ | 822 | #define INPUT_DEV_CAP_ATTR(ev, bm) \ |
817 | static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf) \ | 823 | static ssize_t input_dev_show_cap_##bm(struct device *dev, \ |
818 | { \ | 824 | struct device_attribute *attr, \ |
819 | struct input_dev *input_dev = to_input_dev(dev); \ | 825 | char *buf) \ |
820 | int len = input_print_bitmap(buf, PAGE_SIZE, \ | 826 | { \ |
821 | input_dev->bm##bit, ev##_MAX, 1); \ | 827 | struct input_dev *input_dev = to_input_dev(dev); \ |
822 | return min_t(int, len, PAGE_SIZE); \ | 828 | int len = input_print_bitmap(buf, PAGE_SIZE, \ |
823 | } \ | 829 | input_dev->bm##bit, ev##_MAX, 1); \ |
824 | static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL); | 830 | return min_t(int, len, PAGE_SIZE); \ |
831 | } \ | ||
832 | static DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL) | ||
825 | 833 | ||
826 | INPUT_DEV_CAP_ATTR(EV, ev); | 834 | INPUT_DEV_CAP_ATTR(EV, ev); |
827 | INPUT_DEV_CAP_ATTR(KEY, key); | 835 | INPUT_DEV_CAP_ATTR(KEY, key); |
@@ -834,15 +842,15 @@ INPUT_DEV_CAP_ATTR(FF, ff); | |||
834 | INPUT_DEV_CAP_ATTR(SW, sw); | 842 | INPUT_DEV_CAP_ATTR(SW, sw); |
835 | 843 | ||
836 | static struct attribute *input_dev_caps_attrs[] = { | 844 | static struct attribute *input_dev_caps_attrs[] = { |
837 | &class_device_attr_ev.attr, | 845 | &dev_attr_ev.attr, |
838 | &class_device_attr_key.attr, | 846 | &dev_attr_key.attr, |
839 | &class_device_attr_rel.attr, | 847 | &dev_attr_rel.attr, |
840 | &class_device_attr_abs.attr, | 848 | &dev_attr_abs.attr, |
841 | &class_device_attr_msc.attr, | 849 | &dev_attr_msc.attr, |
842 | &class_device_attr_led.attr, | 850 | &dev_attr_led.attr, |
843 | &class_device_attr_snd.attr, | 851 | &dev_attr_snd.attr, |
844 | &class_device_attr_ff.attr, | 852 | &dev_attr_ff.attr, |
845 | &class_device_attr_sw.attr, | 853 | &dev_attr_sw.attr, |
846 | NULL | 854 | NULL |
847 | }; | 855 | }; |
848 | 856 | ||
@@ -858,9 +866,9 @@ static struct attribute_group *input_dev_attr_groups[] = { | |||
858 | NULL | 866 | NULL |
859 | }; | 867 | }; |
860 | 868 | ||
861 | static void input_dev_release(struct class_device *class_dev) | 869 | static void input_dev_release(struct device *device) |
862 | { | 870 | { |
863 | struct input_dev *dev = to_input_dev(class_dev); | 871 | struct input_dev *dev = to_input_dev(device); |
864 | 872 | ||
865 | input_ff_destroy(dev); | 873 | input_ff_destroy(dev); |
866 | kfree(dev); | 874 | kfree(dev); |
@@ -947,10 +955,10 @@ static int input_add_uevent_modalias_var(char **envp, int num_envp, int *cur_ind | |||
947 | return err; \ | 955 | return err; \ |
948 | } while (0) | 956 | } while (0) |
949 | 957 | ||
950 | static int input_dev_uevent(struct class_device *cdev, char **envp, | 958 | static int input_dev_uevent(struct device *device, char **envp, |
951 | int num_envp, char *buffer, int buffer_size) | 959 | int num_envp, char *buffer, int buffer_size) |
952 | { | 960 | { |
953 | struct input_dev *dev = to_input_dev(cdev); | 961 | struct input_dev *dev = to_input_dev(device); |
954 | int i = 0; | 962 | int i = 0; |
955 | int len = 0; | 963 | int len = 0; |
956 | 964 | ||
@@ -988,10 +996,14 @@ static int input_dev_uevent(struct class_device *cdev, char **envp, | |||
988 | return 0; | 996 | return 0; |
989 | } | 997 | } |
990 | 998 | ||
999 | static struct device_type input_dev_type = { | ||
1000 | .groups = input_dev_attr_groups, | ||
1001 | .release = input_dev_release, | ||
1002 | .uevent = input_dev_uevent, | ||
1003 | }; | ||
1004 | |||
991 | struct class input_class = { | 1005 | struct class input_class = { |
992 | .name = "input", | 1006 | .name = "input", |
993 | .release = input_dev_release, | ||
994 | .uevent = input_dev_uevent, | ||
995 | }; | 1007 | }; |
996 | EXPORT_SYMBOL_GPL(input_class); | 1008 | EXPORT_SYMBOL_GPL(input_class); |
997 | 1009 | ||
@@ -1010,9 +1022,9 @@ struct input_dev *input_allocate_device(void) | |||
1010 | 1022 | ||
1011 | dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL); | 1023 | dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL); |
1012 | if (dev) { | 1024 | if (dev) { |
1013 | dev->cdev.class = &input_class; | 1025 | dev->dev.type = &input_dev_type; |
1014 | dev->cdev.groups = input_dev_attr_groups; | 1026 | dev->dev.class = &input_class; |
1015 | class_device_initialize(&dev->cdev); | 1027 | device_initialize(&dev->dev); |
1016 | mutex_init(&dev->mutex); | 1028 | mutex_init(&dev->mutex); |
1017 | INIT_LIST_HEAD(&dev->h_list); | 1029 | INIT_LIST_HEAD(&dev->h_list); |
1018 | INIT_LIST_HEAD(&dev->node); | 1030 | INIT_LIST_HEAD(&dev->node); |
@@ -1131,17 +1143,17 @@ int input_register_device(struct input_dev *dev) | |||
1131 | 1143 | ||
1132 | list_add_tail(&dev->node, &input_dev_list); | 1144 | list_add_tail(&dev->node, &input_dev_list); |
1133 | 1145 | ||
1134 | snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id), | 1146 | snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id), |
1135 | "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1); | 1147 | "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1); |
1136 | 1148 | ||
1137 | if (!dev->cdev.dev) | 1149 | if (dev->cdev.dev) |
1138 | dev->cdev.dev = dev->dev.parent; | 1150 | dev->dev.parent = dev->cdev.dev; |
1139 | 1151 | ||
1140 | error = class_device_add(&dev->cdev); | 1152 | error = device_add(&dev->dev); |
1141 | if (error) | 1153 | if (error) |
1142 | return error; | 1154 | return error; |
1143 | 1155 | ||
1144 | path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL); | 1156 | path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); |
1145 | printk(KERN_INFO "input: %s as %s\n", | 1157 | printk(KERN_INFO "input: %s as %s\n", |
1146 | dev->name ? dev->name : "Unspecified device", path ? path : "N/A"); | 1158 | dev->name ? dev->name : "Unspecified device", path ? path : "N/A"); |
1147 | kfree(path); | 1159 | kfree(path); |
@@ -1173,7 +1185,7 @@ void input_unregister_device(struct input_dev *dev) | |||
1173 | 1185 | ||
1174 | list_del_init(&dev->node); | 1186 | list_del_init(&dev->node); |
1175 | 1187 | ||
1176 | class_device_unregister(&dev->cdev); | 1188 | device_unregister(&dev->dev); |
1177 | 1189 | ||
1178 | input_wakeup_procfs_readers(); | 1190 | input_wakeup_procfs_readers(); |
1179 | } | 1191 | } |
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 10e3b7bc925f..a9a0180bfd46 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
@@ -43,6 +43,8 @@ struct joydev { | |||
43 | struct input_handle handle; | 43 | struct input_handle handle; |
44 | wait_queue_head_t wait; | 44 | wait_queue_head_t wait; |
45 | struct list_head client_list; | 45 | struct list_head client_list; |
46 | struct device dev; | ||
47 | |||
46 | struct js_corr corr[ABS_MAX + 1]; | 48 | struct js_corr corr[ABS_MAX + 1]; |
47 | struct JS_DATA_SAVE_TYPE glue; | 49 | struct JS_DATA_SAVE_TYPE glue; |
48 | int nabs; | 50 | int nabs; |
@@ -138,8 +140,10 @@ static int joydev_fasync(int fd, struct file *file, int on) | |||
138 | return retval < 0 ? retval : 0; | 140 | return retval < 0 ? retval : 0; |
139 | } | 141 | } |
140 | 142 | ||
141 | static void joydev_free(struct joydev *joydev) | 143 | static void joydev_free(struct device *dev) |
142 | { | 144 | { |
145 | struct joydev *joydev = container_of(dev, struct joydev, dev); | ||
146 | |||
143 | joydev_table[joydev->minor] = NULL; | 147 | joydev_table[joydev->minor] = NULL; |
144 | kfree(joydev); | 148 | kfree(joydev); |
145 | } | 149 | } |
@@ -154,12 +158,10 @@ static int joydev_release(struct inode *inode, struct file *file) | |||
154 | list_del(&client->node); | 158 | list_del(&client->node); |
155 | kfree(client); | 159 | kfree(client); |
156 | 160 | ||
157 | if (!--joydev->open) { | 161 | if (!--joydev->open && joydev->exist) |
158 | if (joydev->exist) | 162 | input_close_device(&joydev->handle); |
159 | input_close_device(&joydev->handle); | 163 | |
160 | else | 164 | put_device(&joydev->dev); |
161 | joydev_free(joydev); | ||
162 | } | ||
163 | 165 | ||
164 | return 0; | 166 | return 0; |
165 | } | 167 | } |
@@ -178,24 +180,32 @@ static int joydev_open(struct inode *inode, struct file *file) | |||
178 | if (!joydev || !joydev->exist) | 180 | if (!joydev || !joydev->exist) |
179 | return -ENODEV; | 181 | return -ENODEV; |
180 | 182 | ||
183 | get_device(&joydev->dev); | ||
184 | |||
181 | client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL); | 185 | client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL); |
182 | if (!client) | 186 | if (!client) { |
183 | return -ENOMEM; | 187 | error = -ENOMEM; |
188 | goto err_put_joydev; | ||
189 | } | ||
184 | 190 | ||
185 | client->joydev = joydev; | 191 | client->joydev = joydev; |
186 | list_add_tail(&client->node, &joydev->client_list); | 192 | list_add_tail(&client->node, &joydev->client_list); |
187 | 193 | ||
188 | if (!joydev->open++ && joydev->exist) { | 194 | if (!joydev->open++ && joydev->exist) { |
189 | error = input_open_device(&joydev->handle); | 195 | error = input_open_device(&joydev->handle); |
190 | if (error) { | 196 | if (error) |
191 | list_del(&client->node); | 197 | goto err_free_client; |
192 | kfree(client); | ||
193 | return error; | ||
194 | } | ||
195 | } | 198 | } |
196 | 199 | ||
197 | file->private_data = client; | 200 | file->private_data = client; |
198 | return 0; | 201 | return 0; |
202 | |||
203 | err_free_client: | ||
204 | list_del(&client->node); | ||
205 | kfree(client); | ||
206 | err_put_joydev: | ||
207 | put_device(&joydev->dev); | ||
208 | return error; | ||
199 | } | 209 | } |
200 | 210 | ||
201 | static ssize_t joydev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 211 | static ssize_t joydev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) |
@@ -481,8 +491,6 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, | |||
481 | const struct input_device_id *id) | 491 | const struct input_device_id *id) |
482 | { | 492 | { |
483 | struct joydev *joydev; | 493 | struct joydev *joydev; |
484 | struct class_device *cdev; | ||
485 | dev_t devt; | ||
486 | int i, j, t, minor; | 494 | int i, j, t, minor; |
487 | int error; | 495 | int error; |
488 | 496 | ||
@@ -505,7 +513,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, | |||
505 | joydev->handle.name = joydev->name; | 513 | joydev->handle.name = joydev->name; |
506 | joydev->handle.handler = handler; | 514 | joydev->handle.handler = handler; |
507 | joydev->handle.private = joydev; | 515 | joydev->handle.private = joydev; |
508 | sprintf(joydev->name, "js%d", minor); | 516 | snprintf(joydev->name, sizeof(joydev->name), "js%d", minor); |
509 | 517 | ||
510 | for (i = 0; i < ABS_MAX + 1; i++) | 518 | for (i = 0; i < ABS_MAX + 1; i++) |
511 | if (test_bit(i, dev->absbit)) { | 519 | if (test_bit(i, dev->absbit)) { |
@@ -547,36 +555,30 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, | |||
547 | joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i); | 555 | joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i); |
548 | } | 556 | } |
549 | 557 | ||
550 | joydev_table[minor] = joydev; | 558 | snprintf(joydev->dev.bus_id, sizeof(joydev->dev.bus_id), |
551 | 559 | "js%d", minor); | |
552 | devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor), | 560 | joydev->dev.class = &input_class; |
561 | joydev->dev.parent = &dev->dev; | ||
562 | joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor); | ||
563 | joydev->dev.release = joydev_free; | ||
564 | device_initialize(&joydev->dev); | ||
553 | 565 | ||
554 | cdev = class_device_create(&input_class, &dev->cdev, devt, | 566 | joydev_table[minor] = joydev; |
555 | dev->cdev.dev, joydev->name); | ||
556 | if (IS_ERR(cdev)) { | ||
557 | error = PTR_ERR(cdev); | ||
558 | goto err_free_joydev; | ||
559 | } | ||
560 | 567 | ||
561 | /* temporary symlink to keep userspace happy */ | 568 | error = device_add(&joydev->dev); |
562 | error = sysfs_create_link(&input_class.subsys.kobj, | ||
563 | &cdev->kobj, joydev->name); | ||
564 | if (error) | 569 | if (error) |
565 | goto err_cdev_destroy; | 570 | goto err_free_joydev; |
566 | 571 | ||
567 | error = input_register_handle(&joydev->handle); | 572 | error = input_register_handle(&joydev->handle); |
568 | if (error) | 573 | if (error) |
569 | goto err_remove_link; | 574 | goto err_delete_joydev; |
570 | 575 | ||
571 | return 0; | 576 | return 0; |
572 | 577 | ||
573 | err_remove_link: | 578 | err_delete_joydev: |
574 | sysfs_remove_link(&input_class.subsys.kobj, joydev->name); | 579 | device_del(&joydev->dev); |
575 | err_cdev_destroy: | ||
576 | class_device_destroy(&input_class, devt); | ||
577 | err_free_joydev: | 580 | err_free_joydev: |
578 | joydev_table[minor] = NULL; | 581 | put_device(&joydev->dev); |
579 | kfree(joydev); | ||
580 | return error; | 582 | return error; |
581 | } | 583 | } |
582 | 584 | ||
@@ -587,9 +589,8 @@ static void joydev_disconnect(struct input_handle *handle) | |||
587 | struct joydev_client *client; | 589 | struct joydev_client *client; |
588 | 590 | ||
589 | input_unregister_handle(handle); | 591 | input_unregister_handle(handle); |
592 | device_del(&joydev->dev); | ||
590 | 593 | ||
591 | sysfs_remove_link(&input_class.subsys.kobj, joydev->name); | ||
592 | class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor)); | ||
593 | joydev->exist = 0; | 594 | joydev->exist = 0; |
594 | 595 | ||
595 | if (joydev->open) { | 596 | if (joydev->open) { |
@@ -597,8 +598,9 @@ static void joydev_disconnect(struct input_handle *handle) | |||
597 | list_for_each_entry(client, &joydev->client_list, node) | 598 | list_for_each_entry(client, &joydev->client_list, node) |
598 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | 599 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); |
599 | wake_up_interruptible(&joydev->wait); | 600 | wake_up_interruptible(&joydev->wait); |
600 | } else | 601 | } |
601 | joydev_free(joydev); | 602 | |
603 | put_device(&joydev->dev); | ||
602 | } | 604 | } |
603 | 605 | ||
604 | static const struct input_device_id joydev_blacklist[] = { | 606 | static const struct input_device_id joydev_blacklist[] = { |
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 3f4866d8d18c..9173916b8be5 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c | |||
@@ -64,6 +64,7 @@ struct mousedev { | |||
64 | wait_queue_head_t wait; | 64 | wait_queue_head_t wait; |
65 | struct list_head client_list; | 65 | struct list_head client_list; |
66 | struct input_handle handle; | 66 | struct input_handle handle; |
67 | struct device dev; | ||
67 | 68 | ||
68 | struct list_head mixdev_node; | 69 | struct list_head mixdev_node; |
69 | int mixdev_open; | 70 | int mixdev_open; |
@@ -112,7 +113,7 @@ static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 }; | |||
112 | static struct input_handler mousedev_handler; | 113 | static struct input_handler mousedev_handler; |
113 | 114 | ||
114 | static struct mousedev *mousedev_table[MOUSEDEV_MINORS]; | 115 | static struct mousedev *mousedev_table[MOUSEDEV_MINORS]; |
115 | static struct mousedev mousedev_mix; | 116 | static struct mousedev *mousedev_mix; |
116 | static LIST_HEAD(mousedev_mix_list); | 117 | static LIST_HEAD(mousedev_mix_list); |
117 | 118 | ||
118 | #define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03]) | 119 | #define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03]) |
@@ -218,10 +219,10 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int | |||
218 | 219 | ||
219 | if (value) { | 220 | if (value) { |
220 | set_bit(index, &mousedev->packet.buttons); | 221 | set_bit(index, &mousedev->packet.buttons); |
221 | set_bit(index, &mousedev_mix.packet.buttons); | 222 | set_bit(index, &mousedev_mix->packet.buttons); |
222 | } else { | 223 | } else { |
223 | clear_bit(index, &mousedev->packet.buttons); | 224 | clear_bit(index, &mousedev->packet.buttons); |
224 | clear_bit(index, &mousedev_mix.packet.buttons); | 225 | clear_bit(index, &mousedev_mix->packet.buttons); |
225 | } | 226 | } |
226 | } | 227 | } |
227 | 228 | ||
@@ -287,11 +288,11 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value) | |||
287 | * motion packet so we won't mess current position. | 288 | * motion packet so we won't mess current position. |
288 | */ | 289 | */ |
289 | set_bit(0, &mousedev->packet.buttons); | 290 | set_bit(0, &mousedev->packet.buttons); |
290 | set_bit(0, &mousedev_mix.packet.buttons); | 291 | set_bit(0, &mousedev_mix->packet.buttons); |
291 | mousedev_notify_readers(mousedev, &mousedev_mix.packet); | 292 | mousedev_notify_readers(mousedev, &mousedev_mix->packet); |
292 | mousedev_notify_readers(&mousedev_mix, &mousedev_mix.packet); | 293 | mousedev_notify_readers(mousedev_mix, &mousedev_mix->packet); |
293 | clear_bit(0, &mousedev->packet.buttons); | 294 | clear_bit(0, &mousedev->packet.buttons); |
294 | clear_bit(0, &mousedev_mix.packet.buttons); | 295 | clear_bit(0, &mousedev_mix->packet.buttons); |
295 | } | 296 | } |
296 | mousedev->touch = mousedev->pkt_count = 0; | 297 | mousedev->touch = mousedev->pkt_count = 0; |
297 | mousedev->frac_dx = 0; | 298 | mousedev->frac_dx = 0; |
@@ -343,7 +344,7 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig | |||
343 | } | 344 | } |
344 | 345 | ||
345 | mousedev_notify_readers(mousedev, &mousedev->packet); | 346 | mousedev_notify_readers(mousedev, &mousedev->packet); |
346 | mousedev_notify_readers(&mousedev_mix, &mousedev->packet); | 347 | mousedev_notify_readers(mousedev_mix, &mousedev->packet); |
347 | 348 | ||
348 | mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0; | 349 | mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0; |
349 | mousedev->packet.abs_event = 0; | 350 | mousedev->packet.abs_event = 0; |
@@ -362,8 +363,10 @@ static int mousedev_fasync(int fd, struct file *file, int on) | |||
362 | return retval < 0 ? retval : 0; | 363 | return retval < 0 ? retval : 0; |
363 | } | 364 | } |
364 | 365 | ||
365 | static void mousedev_free(struct mousedev *mousedev) | 366 | static void mousedev_free(struct device *dev) |
366 | { | 367 | { |
368 | struct mousedev *mousedev = container_of(dev, struct mousedev, dev); | ||
369 | |||
367 | mousedev_table[mousedev->minor] = NULL; | 370 | mousedev_table[mousedev->minor] = NULL; |
368 | kfree(mousedev); | 371 | kfree(mousedev); |
369 | } | 372 | } |
@@ -372,15 +375,16 @@ static int mixdev_add_device(struct mousedev *mousedev) | |||
372 | { | 375 | { |
373 | int error; | 376 | int error; |
374 | 377 | ||
375 | if (mousedev_mix.open) { | 378 | if (mousedev_mix->open) { |
376 | error = input_open_device(&mousedev->handle); | 379 | error = input_open_device(&mousedev->handle); |
377 | if (error) | 380 | if (error) |
378 | return error; | 381 | return error; |
379 | 382 | ||
380 | mousedev->open++; | 383 | mousedev->open++; |
381 | mousedev->mixdev_open++; | 384 | mousedev->mixdev_open = 1; |
382 | } | 385 | } |
383 | 386 | ||
387 | get_device(&mousedev->dev); | ||
384 | list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list); | 388 | list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list); |
385 | 389 | ||
386 | return 0; | 390 | return 0; |
@@ -395,36 +399,40 @@ static void mixdev_remove_device(struct mousedev *mousedev) | |||
395 | } | 399 | } |
396 | 400 | ||
397 | list_del_init(&mousedev->mixdev_node); | 401 | list_del_init(&mousedev->mixdev_node); |
402 | put_device(&mousedev->dev); | ||
398 | } | 403 | } |
399 | 404 | ||
400 | static void mixdev_open_devices(void) | 405 | static void mixdev_open_devices(void) |
401 | { | 406 | { |
402 | struct mousedev *mousedev; | 407 | struct mousedev *mousedev; |
403 | 408 | ||
409 | if (mousedev_mix->open++) | ||
410 | return; | ||
411 | |||
404 | list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { | 412 | list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { |
405 | if (mousedev->exist && !mousedev->open) { | 413 | if (!mousedev->mixdev_open) { |
406 | if (input_open_device(&mousedev->handle)) | 414 | if (!mousedev->open && mousedev->exist) |
407 | continue; | 415 | if (input_open_device(&mousedev->handle)) |
416 | continue; | ||
408 | 417 | ||
409 | mousedev->open++; | 418 | mousedev->open++; |
410 | mousedev->mixdev_open++; | 419 | mousedev->mixdev_open = 1; |
411 | } | 420 | } |
412 | } | 421 | } |
413 | } | 422 | } |
414 | 423 | ||
415 | static void mixdev_close_devices(void) | 424 | static void mixdev_close_devices(void) |
416 | { | 425 | { |
417 | struct mousedev *mousedev, *next; | 426 | struct mousedev *mousedev; |
418 | 427 | ||
419 | list_for_each_entry_safe(mousedev, next, &mousedev_mix_list, mixdev_node) { | 428 | if (--mousedev_mix->open) |
429 | return; | ||
430 | |||
431 | list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { | ||
420 | if (mousedev->mixdev_open) { | 432 | if (mousedev->mixdev_open) { |
421 | mousedev->mixdev_open = 0; | 433 | mousedev->mixdev_open = 0; |
422 | if (!--mousedev->open) { | 434 | if (!--mousedev->open && mousedev->exist) |
423 | if (mousedev->exist) | 435 | input_close_device(&mousedev->handle); |
424 | input_close_device(&mousedev->handle); | ||
425 | else | ||
426 | mousedev_free(mousedev); | ||
427 | } | ||
428 | } | 436 | } |
429 | } | 437 | } |
430 | } | 438 | } |
@@ -439,14 +447,12 @@ static int mousedev_release(struct inode *inode, struct file *file) | |||
439 | list_del(&client->node); | 447 | list_del(&client->node); |
440 | kfree(client); | 448 | kfree(client); |
441 | 449 | ||
442 | if (!--mousedev->open) { | 450 | if (mousedev->minor == MOUSEDEV_MIX) |
443 | if (mousedev->minor == MOUSEDEV_MIX) | 451 | mixdev_close_devices(); |
444 | mixdev_close_devices(); | 452 | else if (!--mousedev->open && mousedev->exist) |
445 | else if (mousedev->exist) | 453 | input_close_device(&mousedev->handle); |
446 | input_close_device(&mousedev->handle); | 454 | |
447 | else | 455 | put_device(&mousedev->dev); |
448 | mousedev_free(mousedev); | ||
449 | } | ||
450 | 456 | ||
451 | return 0; | 457 | return 0; |
452 | } | 458 | } |
@@ -473,9 +479,13 @@ static int mousedev_open(struct inode *inode, struct file *file) | |||
473 | if (!mousedev) | 479 | if (!mousedev) |
474 | return -ENODEV; | 480 | return -ENODEV; |
475 | 481 | ||
482 | get_device(&mousedev->dev); | ||
483 | |||
476 | client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL); | 484 | client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL); |
477 | if (!client) | 485 | if (!client) { |
478 | return -ENOMEM; | 486 | error = -ENOMEM; |
487 | goto err_put_mousedev; | ||
488 | } | ||
479 | 489 | ||
480 | spin_lock_init(&client->packet_lock); | 490 | spin_lock_init(&client->packet_lock); |
481 | client->pos_x = xres / 2; | 491 | client->pos_x = xres / 2; |
@@ -483,21 +493,23 @@ static int mousedev_open(struct inode *inode, struct file *file) | |||
483 | client->mousedev = mousedev; | 493 | client->mousedev = mousedev; |
484 | list_add_tail(&client->node, &mousedev->client_list); | 494 | list_add_tail(&client->node, &mousedev->client_list); |
485 | 495 | ||
486 | if (!mousedev->open++) { | 496 | if (mousedev->minor == MOUSEDEV_MIX) |
487 | if (mousedev->minor == MOUSEDEV_MIX) | 497 | mixdev_open_devices(); |
488 | mixdev_open_devices(); | 498 | else if (!mousedev->open++ && mousedev->exist) { |
489 | else if (mousedev->exist) { | 499 | error = input_open_device(&mousedev->handle); |
490 | error = input_open_device(&mousedev->handle); | 500 | if (error) |
491 | if (error) { | 501 | goto err_free_client; |
492 | list_del(&client->node); | ||
493 | kfree(client); | ||
494 | return error; | ||
495 | } | ||
496 | } | ||
497 | } | 502 | } |
498 | 503 | ||
499 | file->private_data = client; | 504 | file->private_data = client; |
500 | return 0; | 505 | return 0; |
506 | |||
507 | err_free_client: | ||
508 | list_del(&client->node); | ||
509 | kfree(client); | ||
510 | err_put_mousedev: | ||
511 | put_device(&mousedev->dev); | ||
512 | return error; | ||
501 | } | 513 | } |
502 | 514 | ||
503 | static inline int mousedev_limit_delta(int delta, int limit) | 515 | static inline int mousedev_limit_delta(int delta, int limit) |
@@ -680,57 +692,96 @@ static const struct file_operations mousedev_fops = { | |||
680 | .fasync = mousedev_fasync, | 692 | .fasync = mousedev_fasync, |
681 | }; | 693 | }; |
682 | 694 | ||
683 | static int mousedev_connect(struct input_handler *handler, struct input_dev *dev, | 695 | static struct mousedev *mousedev_create(struct input_dev *dev, |
684 | const struct input_device_id *id) | 696 | struct input_handler *handler, |
697 | int minor) | ||
685 | { | 698 | { |
686 | struct mousedev *mousedev; | 699 | struct mousedev *mousedev; |
687 | struct class_device *cdev; | ||
688 | dev_t devt; | ||
689 | int minor; | ||
690 | int error; | 700 | int error; |
691 | 701 | ||
692 | for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++); | ||
693 | if (minor == MOUSEDEV_MINORS) { | ||
694 | printk(KERN_ERR "mousedev: no more free mousedev devices\n"); | ||
695 | return -ENFILE; | ||
696 | } | ||
697 | |||
698 | mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL); | 702 | mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL); |
699 | if (!mousedev) | 703 | if (!mousedev) { |
700 | return -ENOMEM; | 704 | error = -ENOMEM; |
705 | goto err_out; | ||
706 | } | ||
701 | 707 | ||
702 | INIT_LIST_HEAD(&mousedev->client_list); | 708 | INIT_LIST_HEAD(&mousedev->client_list); |
703 | INIT_LIST_HEAD(&mousedev->mixdev_node); | 709 | INIT_LIST_HEAD(&mousedev->mixdev_node); |
704 | init_waitqueue_head(&mousedev->wait); | 710 | init_waitqueue_head(&mousedev->wait); |
705 | 711 | ||
712 | if (minor == MOUSEDEV_MIX) | ||
713 | strlcpy(mousedev->name, "mice", sizeof(mousedev->name)); | ||
714 | else | ||
715 | snprintf(mousedev->name, sizeof(mousedev->name), | ||
716 | "mouse%d", minor); | ||
717 | |||
706 | mousedev->minor = minor; | 718 | mousedev->minor = minor; |
707 | mousedev->exist = 1; | 719 | mousedev->exist = 1; |
708 | mousedev->handle.dev = dev; | 720 | mousedev->handle.dev = dev; |
709 | mousedev->handle.name = mousedev->name; | 721 | mousedev->handle.name = mousedev->name; |
710 | mousedev->handle.handler = handler; | 722 | mousedev->handle.handler = handler; |
711 | mousedev->handle.private = mousedev; | 723 | mousedev->handle.private = mousedev; |
712 | sprintf(mousedev->name, "mouse%d", minor); | ||
713 | 724 | ||
714 | mousedev_table[minor] = mousedev; | 725 | strlcpy(mousedev->dev.bus_id, mousedev->name, |
726 | sizeof(mousedev->dev.bus_id)); | ||
727 | mousedev->dev.class = &input_class; | ||
728 | if (dev) | ||
729 | mousedev->dev.parent = &dev->dev; | ||
730 | mousedev->dev.devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor); | ||
731 | mousedev->dev.release = mousedev_free; | ||
732 | device_initialize(&mousedev->dev); | ||
715 | 733 | ||
716 | devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor), | 734 | mousedev_table[minor] = mousedev; |
717 | 735 | ||
718 | cdev = class_device_create(&input_class, &dev->cdev, devt, | 736 | error = device_add(&mousedev->dev); |
719 | dev->cdev.dev, mousedev->name); | 737 | if (error) |
720 | if (IS_ERR(cdev)) { | ||
721 | error = PTR_ERR(cdev); | ||
722 | goto err_free_mousedev; | 738 | goto err_free_mousedev; |
739 | |||
740 | return mousedev; | ||
741 | |||
742 | err_free_mousedev: | ||
743 | put_device(&mousedev->dev); | ||
744 | err_out: | ||
745 | return ERR_PTR(error); | ||
746 | } | ||
747 | |||
748 | static void mousedev_destroy(struct mousedev *mousedev) | ||
749 | { | ||
750 | struct mousedev_client *client; | ||
751 | |||
752 | device_del(&mousedev->dev); | ||
753 | mousedev->exist = 0; | ||
754 | |||
755 | if (mousedev->open) { | ||
756 | input_close_device(&mousedev->handle); | ||
757 | list_for_each_entry(client, &mousedev->client_list, node) | ||
758 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | ||
759 | wake_up_interruptible(&mousedev->wait); | ||
723 | } | 760 | } |
724 | 761 | ||
725 | /* temporary symlink to keep userspace happy */ | 762 | put_device(&mousedev->dev); |
726 | error = sysfs_create_link(&input_class.subsys.kobj, | 763 | } |
727 | &cdev->kobj, mousedev->name); | 764 | |
728 | if (error) | 765 | static int mousedev_connect(struct input_handler *handler, struct input_dev *dev, |
729 | goto err_cdev_destroy; | 766 | const struct input_device_id *id) |
767 | { | ||
768 | struct mousedev *mousedev; | ||
769 | int minor; | ||
770 | int error; | ||
771 | |||
772 | for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++); | ||
773 | if (minor == MOUSEDEV_MINORS) { | ||
774 | printk(KERN_ERR "mousedev: no more free mousedev devices\n"); | ||
775 | return -ENFILE; | ||
776 | } | ||
777 | |||
778 | mousedev = mousedev_create(dev, handler, minor); | ||
779 | if (IS_ERR(mousedev)) | ||
780 | return PTR_ERR(mousedev); | ||
730 | 781 | ||
731 | error = input_register_handle(&mousedev->handle); | 782 | error = input_register_handle(&mousedev->handle); |
732 | if (error) | 783 | if (error) |
733 | goto err_remove_link; | 784 | goto err_delete_mousedev; |
734 | 785 | ||
735 | error = mixdev_add_device(mousedev); | 786 | error = mixdev_add_device(mousedev); |
736 | if (error) | 787 | if (error) |
@@ -740,37 +791,18 @@ static int mousedev_connect(struct input_handler *handler, struct input_dev *dev | |||
740 | 791 | ||
741 | err_unregister_handle: | 792 | err_unregister_handle: |
742 | input_unregister_handle(&mousedev->handle); | 793 | input_unregister_handle(&mousedev->handle); |
743 | err_remove_link: | 794 | err_delete_mousedev: |
744 | sysfs_remove_link(&input_class.subsys.kobj, mousedev->name); | 795 | device_unregister(&mousedev->dev); |
745 | err_cdev_destroy: | ||
746 | class_device_destroy(&input_class, devt); | ||
747 | err_free_mousedev: | ||
748 | mousedev_table[minor] = NULL; | ||
749 | kfree(mousedev); | ||
750 | return error; | 796 | return error; |
751 | } | 797 | } |
752 | 798 | ||
753 | static void mousedev_disconnect(struct input_handle *handle) | 799 | static void mousedev_disconnect(struct input_handle *handle) |
754 | { | 800 | { |
755 | struct mousedev *mousedev = handle->private; | 801 | struct mousedev *mousedev = handle->private; |
756 | struct mousedev_client *client; | ||
757 | |||
758 | input_unregister_handle(handle); | ||
759 | |||
760 | sysfs_remove_link(&input_class.subsys.kobj, mousedev->name); | ||
761 | class_device_destroy(&input_class, | ||
762 | MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor)); | ||
763 | mousedev->exist = 0; | ||
764 | 802 | ||
765 | mixdev_remove_device(mousedev); | 803 | mixdev_remove_device(mousedev); |
766 | 804 | input_unregister_handle(handle); | |
767 | if (mousedev->open) { | 805 | mousedev_destroy(mousedev); |
768 | input_close_device(handle); | ||
769 | list_for_each_entry(client, &mousedev->client_list, node) | ||
770 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | ||
771 | wake_up_interruptible(&mousedev->wait); | ||
772 | } else | ||
773 | mousedev_free(mousedev); | ||
774 | } | 806 | } |
775 | 807 | ||
776 | static const struct input_device_id mousedev_ids[] = { | 808 | static const struct input_device_id mousedev_ids[] = { |
@@ -822,25 +854,16 @@ static int psaux_registered; | |||
822 | 854 | ||
823 | static int __init mousedev_init(void) | 855 | static int __init mousedev_init(void) |
824 | { | 856 | { |
825 | struct class_device *cdev; | ||
826 | int error; | 857 | int error; |
827 | 858 | ||
859 | mousedev_mix = mousedev_create(NULL, &mousedev_handler, MOUSEDEV_MIX); | ||
860 | if (IS_ERR(mousedev_mix)) | ||
861 | return PTR_ERR(mousedev_mix); | ||
862 | |||
828 | error = input_register_handler(&mousedev_handler); | 863 | error = input_register_handler(&mousedev_handler); |
829 | if (error) | 864 | if (error) { |
865 | mousedev_destroy(mousedev_mix); | ||
830 | return error; | 866 | return error; |
831 | |||
832 | memset(&mousedev_mix, 0, sizeof(struct mousedev)); | ||
833 | INIT_LIST_HEAD(&mousedev_mix.client_list); | ||
834 | init_waitqueue_head(&mousedev_mix.wait); | ||
835 | mousedev_table[MOUSEDEV_MIX] = &mousedev_mix; | ||
836 | mousedev_mix.exist = 1; | ||
837 | mousedev_mix.minor = MOUSEDEV_MIX; | ||
838 | |||
839 | cdev = class_device_create(&input_class, NULL, | ||
840 | MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice"); | ||
841 | if (IS_ERR(cdev)) { | ||
842 | input_unregister_handler(&mousedev_handler); | ||
843 | return PTR_ERR(cdev); | ||
844 | } | 867 | } |
845 | 868 | ||
846 | #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX | 869 | #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX |
@@ -863,9 +886,8 @@ static void __exit mousedev_exit(void) | |||
863 | if (psaux_registered) | 886 | if (psaux_registered) |
864 | misc_deregister(&psaux_mouse); | 887 | misc_deregister(&psaux_mouse); |
865 | #endif | 888 | #endif |
866 | class_device_destroy(&input_class, | ||
867 | MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX)); | ||
868 | input_unregister_handler(&mousedev_handler); | 889 | input_unregister_handler(&mousedev_handler); |
890 | mousedev_destroy(mousedev_mix); | ||
869 | } | 891 | } |
870 | 892 | ||
871 | module_init(mousedev_init); | 893 | module_init(mousedev_init); |
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c index 2db364898e15..4cd5bbc44cca 100644 --- a/drivers/input/tsdev.c +++ b/drivers/input/tsdev.c | |||
@@ -109,9 +109,11 @@ struct tsdev { | |||
109 | int open; | 109 | int open; |
110 | int minor; | 110 | int minor; |
111 | char name[8]; | 111 | char name[8]; |
112 | struct input_handle handle; | ||
112 | wait_queue_head_t wait; | 113 | wait_queue_head_t wait; |
113 | struct list_head client_list; | 114 | struct list_head client_list; |
114 | struct input_handle handle; | 115 | struct device dev; |
116 | |||
115 | int x, y, pressure; | 117 | int x, y, pressure; |
116 | struct ts_calibration cal; | 118 | struct ts_calibration cal; |
117 | }; | 119 | }; |
@@ -163,9 +165,13 @@ static int tsdev_open(struct inode *inode, struct file *file) | |||
163 | if (!tsdev || !tsdev->exist) | 165 | if (!tsdev || !tsdev->exist) |
164 | return -ENODEV; | 166 | return -ENODEV; |
165 | 167 | ||
168 | get_device(&tsdev->dev); | ||
169 | |||
166 | client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL); | 170 | client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL); |
167 | if (!client) | 171 | if (!client) { |
168 | return -ENOMEM; | 172 | error = -ENOMEM; |
173 | goto err_put_tsdev; | ||
174 | } | ||
169 | 175 | ||
170 | client->tsdev = tsdev; | 176 | client->tsdev = tsdev; |
171 | client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0; | 177 | client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0; |
@@ -173,19 +179,25 @@ static int tsdev_open(struct inode *inode, struct file *file) | |||
173 | 179 | ||
174 | if (!tsdev->open++ && tsdev->exist) { | 180 | if (!tsdev->open++ && tsdev->exist) { |
175 | error = input_open_device(&tsdev->handle); | 181 | error = input_open_device(&tsdev->handle); |
176 | if (error) { | 182 | if (error) |
177 | list_del(&client->node); | 183 | goto err_free_client; |
178 | kfree(client); | ||
179 | return error; | ||
180 | } | ||
181 | } | 184 | } |
182 | 185 | ||
183 | file->private_data = client; | 186 | file->private_data = client; |
184 | return 0; | 187 | return 0; |
188 | |||
189 | err_free_client: | ||
190 | list_del(&client->node); | ||
191 | kfree(client); | ||
192 | err_put_tsdev: | ||
193 | put_device(&tsdev->dev); | ||
194 | return error; | ||
185 | } | 195 | } |
186 | 196 | ||
187 | static void tsdev_free(struct tsdev *tsdev) | 197 | static void tsdev_free(struct device *dev) |
188 | { | 198 | { |
199 | struct tsdev *tsdev = container_of(dev, struct tsdev, dev); | ||
200 | |||
189 | tsdev_table[tsdev->minor] = NULL; | 201 | tsdev_table[tsdev->minor] = NULL; |
190 | kfree(tsdev); | 202 | kfree(tsdev); |
191 | } | 203 | } |
@@ -200,12 +212,10 @@ static int tsdev_release(struct inode *inode, struct file *file) | |||
200 | list_del(&client->node); | 212 | list_del(&client->node); |
201 | kfree(client); | 213 | kfree(client); |
202 | 214 | ||
203 | if (!--tsdev->open) { | 215 | if (!--tsdev->open && tsdev->exist) |
204 | if (tsdev->exist) | 216 | input_close_device(&tsdev->handle); |
205 | input_close_device(&tsdev->handle); | 217 | |
206 | else | 218 | put_device(&tsdev->dev); |
207 | tsdev_free(tsdev); | ||
208 | } | ||
209 | 219 | ||
210 | return 0; | 220 | return 0; |
211 | } | 221 | } |
@@ -388,8 +398,6 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev, | |||
388 | const struct input_device_id *id) | 398 | const struct input_device_id *id) |
389 | { | 399 | { |
390 | struct tsdev *tsdev; | 400 | struct tsdev *tsdev; |
391 | struct class_device *cdev; | ||
392 | dev_t devt; | ||
393 | int minor, delta; | 401 | int minor, delta; |
394 | int error; | 402 | int error; |
395 | 403 | ||
@@ -407,14 +415,13 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev, | |||
407 | INIT_LIST_HEAD(&tsdev->client_list); | 415 | INIT_LIST_HEAD(&tsdev->client_list); |
408 | init_waitqueue_head(&tsdev->wait); | 416 | init_waitqueue_head(&tsdev->wait); |
409 | 417 | ||
410 | sprintf(tsdev->name, "ts%d", minor); | ||
411 | |||
412 | tsdev->exist = 1; | 418 | tsdev->exist = 1; |
413 | tsdev->minor = minor; | 419 | tsdev->minor = minor; |
414 | tsdev->handle.dev = dev; | 420 | tsdev->handle.dev = dev; |
415 | tsdev->handle.name = tsdev->name; | 421 | tsdev->handle.name = tsdev->name; |
416 | tsdev->handle.handler = handler; | 422 | tsdev->handle.handler = handler; |
417 | tsdev->handle.private = tsdev; | 423 | tsdev->handle.private = tsdev; |
424 | snprintf(tsdev->name, sizeof(tsdev->name), "ts%d", minor); | ||
418 | 425 | ||
419 | /* Precompute the rough calibration matrix */ | 426 | /* Precompute the rough calibration matrix */ |
420 | delta = dev->absmax [ABS_X] - dev->absmin [ABS_X] + 1; | 427 | delta = dev->absmax [ABS_X] - dev->absmin [ABS_X] + 1; |
@@ -429,36 +436,30 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev, | |||
429 | tsdev->cal.yscale = (yres << 8) / delta; | 436 | tsdev->cal.yscale = (yres << 8) / delta; |
430 | tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8); | 437 | tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8); |
431 | 438 | ||
432 | tsdev_table[minor] = tsdev; | 439 | snprintf(tsdev->dev.bus_id, sizeof(tsdev->dev.bus_id), |
433 | 440 | "ts%d", minor); | |
434 | devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor), | 441 | tsdev->dev.class = &input_class; |
442 | tsdev->dev.parent = &dev->dev; | ||
443 | tsdev->dev.devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor); | ||
444 | tsdev->dev.release = tsdev_free; | ||
445 | device_initialize(&tsdev->dev); | ||
435 | 446 | ||
436 | cdev = class_device_create(&input_class, &dev->cdev, devt, | 447 | tsdev_table[minor] = tsdev; |
437 | dev->cdev.dev, tsdev->name); | ||
438 | if (IS_ERR(cdev)) { | ||
439 | error = PTR_ERR(cdev); | ||
440 | goto err_free_tsdev; | ||
441 | } | ||
442 | 448 | ||
443 | /* temporary symlink to keep userspace happy */ | 449 | error = device_add(&tsdev->dev); |
444 | error = sysfs_create_link(&input_class.subsys.kobj, | ||
445 | &cdev->kobj, tsdev->name); | ||
446 | if (error) | 450 | if (error) |
447 | goto err_cdev_destroy; | 451 | goto err_free_tsdev; |
448 | 452 | ||
449 | error = input_register_handle(&tsdev->handle); | 453 | error = input_register_handle(&tsdev->handle); |
450 | if (error) | 454 | if (error) |
451 | goto err_remove_link; | 455 | goto err_delete_tsdev; |
452 | 456 | ||
453 | return 0; | 457 | return 0; |
454 | 458 | ||
455 | err_remove_link: | 459 | err_delete_tsdev: |
456 | sysfs_remove_link(&input_class.subsys.kobj, tsdev->name); | 460 | device_del(&tsdev->dev); |
457 | err_cdev_destroy: | ||
458 | class_device_destroy(&input_class, devt); | ||
459 | err_free_tsdev: | 461 | err_free_tsdev: |
460 | tsdev_table[minor] = NULL; | 462 | put_device(&tsdev->dev); |
461 | kfree(tsdev); | ||
462 | return error; | 463 | return error; |
463 | } | 464 | } |
464 | 465 | ||
@@ -468,10 +469,8 @@ static void tsdev_disconnect(struct input_handle *handle) | |||
468 | struct tsdev_client *client; | 469 | struct tsdev_client *client; |
469 | 470 | ||
470 | input_unregister_handle(handle); | 471 | input_unregister_handle(handle); |
472 | device_del(&tsdev->dev); | ||
471 | 473 | ||
472 | sysfs_remove_link(&input_class.subsys.kobj, tsdev->name); | ||
473 | class_device_destroy(&input_class, | ||
474 | MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor)); | ||
475 | tsdev->exist = 0; | 474 | tsdev->exist = 0; |
476 | 475 | ||
477 | if (tsdev->open) { | 476 | if (tsdev->open) { |
@@ -479,8 +478,9 @@ static void tsdev_disconnect(struct input_handle *handle) | |||
479 | list_for_each_entry(client, &tsdev->client_list, node) | 478 | list_for_each_entry(client, &tsdev->client_list, node) |
480 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | 479 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); |
481 | wake_up_interruptible(&tsdev->wait); | 480 | wake_up_interruptible(&tsdev->wait); |
482 | } else | 481 | } |
483 | tsdev_free(tsdev); | 482 | |
483 | put_device(&tsdev->dev); | ||
484 | } | 484 | } |
485 | 485 | ||
486 | static const struct input_device_id tsdev_ids[] = { | 486 | static const struct input_device_id tsdev_ids[] = { |