diff options
Diffstat (limited to 'drivers/input')
25 files changed, 1523 insertions, 1113 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/joystick/Kconfig b/drivers/input/joystick/Kconfig index b0023452ec90..12db72d83ea0 100644 --- a/drivers/input/joystick/Kconfig +++ b/drivers/input/joystick/Kconfig | |||
@@ -268,4 +268,11 @@ config JOYSTICK_XPAD | |||
268 | To compile this driver as a module, choose M here: the | 268 | To compile this driver as a module, choose M here: the |
269 | module will be called xpad. | 269 | module will be called xpad. |
270 | 270 | ||
271 | config JOYSTICK_XPAD_FF | ||
272 | bool "X-Box gamepad rumble support" | ||
273 | depends on JOYSTICK_XPAD && INPUT | ||
274 | select INPUT_FF_MEMLESS | ||
275 | ---help--- | ||
276 | Say Y here if you want to take advantage of xbox 360 rumble features. | ||
277 | |||
271 | endif | 278 | endif |
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c index 555319e6378c..4ed3a3eadf19 100644 --- a/drivers/input/joystick/grip_mp.c +++ b/drivers/input/joystick/grip_mp.c | |||
@@ -320,10 +320,10 @@ static int multiport_io(struct gameport* gameport, int sendflags, int sendcode, | |||
320 | 320 | ||
321 | static int dig_mode_start(struct gameport *gameport, u32 *packet) | 321 | static int dig_mode_start(struct gameport *gameport, u32 *packet) |
322 | { | 322 | { |
323 | int i, seq_len = sizeof(init_seq)/sizeof(int); | 323 | int i; |
324 | int flags, tries = 0, bads = 0; | 324 | int flags, tries = 0, bads = 0; |
325 | 325 | ||
326 | for (i = 0; i < seq_len; i++) { /* Send magic sequence */ | 326 | for (i = 0; i < ARRAY_SIZE(init_seq); i++) { /* Send magic sequence */ |
327 | if (init_seq[i]) | 327 | if (init_seq[i]) |
328 | gameport_trigger(gameport); | 328 | gameport_trigger(gameport); |
329 | udelay(GRIP_INIT_DELAY); | 329 | udelay(GRIP_INIT_DELAY); |
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 8c8cd95a6989..244089c52650 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * Ivan Hawkes <blackhawk@ivanhawkes.com> | 8 | * Ivan Hawkes <blackhawk@ivanhawkes.com> |
9 | * 2005 Dominic Cerquetti <binary1230@yahoo.com> | 9 | * 2005 Dominic Cerquetti <binary1230@yahoo.com> |
10 | * 2006 Adam Buchbinder <adam.buchbinder@gmail.com> | 10 | * 2006 Adam Buchbinder <adam.buchbinder@gmail.com> |
11 | * 2007 Jan Kratochvil <honza@jikos.cz> | ||
11 | * | 12 | * |
12 | * This program is free software; you can redistribute it and/or | 13 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU General Public License as | 14 | * modify it under the terms of the GNU General Public License as |
@@ -28,6 +29,7 @@ | |||
28 | * - information from http://euc.jp/periphs/xbox-controller.ja.html | 29 | * - information from http://euc.jp/periphs/xbox-controller.ja.html |
29 | * - the iForce driver drivers/char/joystick/iforce.c | 30 | * - the iForce driver drivers/char/joystick/iforce.c |
30 | * - the skeleton-driver drivers/usb/usb-skeleton.c | 31 | * - the skeleton-driver drivers/usb/usb-skeleton.c |
32 | * - Xbox 360 information http://www.free60.org/wiki/Gamepad | ||
31 | * | 33 | * |
32 | * Thanks to: | 34 | * Thanks to: |
33 | * - ITO Takayuki for providing essential xpad information on his website | 35 | * - ITO Takayuki for providing essential xpad information on his website |
@@ -88,6 +90,9 @@ | |||
88 | #define MAP_DPAD_TO_AXES 1 | 90 | #define MAP_DPAD_TO_AXES 1 |
89 | #define MAP_DPAD_UNKNOWN -1 | 91 | #define MAP_DPAD_UNKNOWN -1 |
90 | 92 | ||
93 | #define XTYPE_XBOX 0 | ||
94 | #define XTYPE_XBOX360 1 | ||
95 | |||
91 | static int dpad_to_buttons; | 96 | static int dpad_to_buttons; |
92 | module_param(dpad_to_buttons, bool, S_IRUGO); | 97 | module_param(dpad_to_buttons, bool, S_IRUGO); |
93 | MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads"); | 98 | MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads"); |
@@ -97,40 +102,42 @@ static const struct xpad_device { | |||
97 | u16 idProduct; | 102 | u16 idProduct; |
98 | char *name; | 103 | char *name; |
99 | u8 dpad_mapping; | 104 | u8 dpad_mapping; |
105 | u8 xtype; | ||
100 | } xpad_device[] = { | 106 | } xpad_device[] = { |
101 | { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", MAP_DPAD_TO_AXES }, | 107 | { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
102 | { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES }, | 108 | { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
103 | { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES }, | 109 | { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
104 | { 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES }, | 110 | { 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
105 | { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS }, | 111 | { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, |
106 | { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES }, | 112 | { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
107 | { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES }, | 113 | { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
108 | { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES }, | 114 | { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
109 | { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES }, | 115 | { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
110 | { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES }, | 116 | { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
111 | { 0x0738, 0x4516, "Mad Catz Control Pad", MAP_DPAD_TO_AXES }, | 117 | { 0x0738, 0x4516, "Mad Catz Control Pad", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
112 | { 0x0738, 0x4522, "Mad Catz LumiCON", MAP_DPAD_TO_AXES }, | 118 | { 0x0738, 0x4522, "Mad Catz LumiCON", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
113 | { 0x0738, 0x4526, "Mad Catz Control Pad Pro", MAP_DPAD_TO_AXES }, | 119 | { 0x0738, 0x4526, "Mad Catz Control Pad Pro", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
114 | { 0x0738, 0x4536, "Mad Catz MicroCON", MAP_DPAD_TO_AXES }, | 120 | { 0x0738, 0x4536, "Mad Catz MicroCON", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
115 | { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS }, | 121 | { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, |
116 | { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", MAP_DPAD_TO_AXES }, | 122 | { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
117 | { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS }, | 123 | { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, |
118 | { 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES }, | 124 | { 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
119 | { 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES }, | 125 | { 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
120 | { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", MAP_DPAD_TO_AXES }, | 126 | { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
121 | { 0x0e4c, 0x1097, "Radica Gamester Controller", MAP_DPAD_TO_AXES }, | 127 | { 0x0e4c, 0x1097, "Radica Gamester Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
122 | { 0x0e4c, 0x2390, "Radica Games Jtech Controller", MAP_DPAD_TO_AXES}, | 128 | { 0x0e4c, 0x2390, "Radica Games Jtech Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
123 | { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", MAP_DPAD_TO_AXES }, | 129 | { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
124 | { 0x0e6f, 0x0005, "Eclipse wireless Controller", MAP_DPAD_TO_AXES }, | 130 | { 0x0e6f, 0x0005, "Eclipse wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
125 | { 0x0e6f, 0x0006, "Edge wireless Controller", MAP_DPAD_TO_AXES }, | 131 | { 0x0e6f, 0x0006, "Edge wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
126 | { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", MAP_DPAD_TO_AXES }, | 132 | { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
127 | { 0x0f30, 0x0202, "Joytech Advanced Controller", MAP_DPAD_TO_AXES }, | 133 | { 0x0f30, 0x0202, "Joytech Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
128 | { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES }, | 134 | { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
129 | { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES }, | 135 | { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
130 | { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS }, | 136 | { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, |
131 | { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS }, | 137 | { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, |
132 | { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES }, | 138 | { 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, |
133 | { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN } | 139 | { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
140 | { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_XBOX } | ||
134 | }; | 141 | }; |
135 | 142 | ||
136 | static const signed short xpad_btn[] = { | 143 | static const signed short xpad_btn[] = { |
@@ -146,6 +153,12 @@ static const signed short xpad_btn_pad[] = { | |||
146 | -1 /* terminating entry */ | 153 | -1 /* terminating entry */ |
147 | }; | 154 | }; |
148 | 155 | ||
156 | static const signed short xpad360_btn[] = { /* buttons for x360 controller */ | ||
157 | BTN_TL, BTN_TR, /* Button LB/RB */ | ||
158 | BTN_MODE, /* The big X button */ | ||
159 | -1 | ||
160 | }; | ||
161 | |||
149 | static const signed short xpad_abs[] = { | 162 | static const signed short xpad_abs[] = { |
150 | ABS_X, ABS_Y, /* left stick */ | 163 | ABS_X, ABS_Y, /* left stick */ |
151 | ABS_RX, ABS_RY, /* right stick */ | 164 | ABS_RX, ABS_RY, /* right stick */ |
@@ -159,8 +172,12 @@ static const signed short xpad_abs_pad[] = { | |||
159 | -1 /* terminating entry */ | 172 | -1 /* terminating entry */ |
160 | }; | 173 | }; |
161 | 174 | ||
175 | /* Xbox 360 has a vendor-specific (sub)class, so we cannot match it with only | ||
176 | * USB_INTERFACE_INFO, more to that this device has 4 InterfaceProtocols, | ||
177 | * but we need only one of them. */ | ||
162 | static struct usb_device_id xpad_table [] = { | 178 | static struct usb_device_id xpad_table [] = { |
163 | { USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */ | 179 | { USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */ |
180 | { USB_DEVICE_INTERFACE_PROTOCOL(0x045e, 0x028e, 1) }, /* X-Box 360 controller */ | ||
164 | { } | 181 | { } |
165 | }; | 182 | }; |
166 | 183 | ||
@@ -174,9 +191,16 @@ struct usb_xpad { | |||
174 | unsigned char *idata; /* input data */ | 191 | unsigned char *idata; /* input data */ |
175 | dma_addr_t idata_dma; | 192 | dma_addr_t idata_dma; |
176 | 193 | ||
194 | #ifdef CONFIG_JOYSTICK_XPAD_FF | ||
195 | struct urb *irq_out; /* urb for interrupt out report */ | ||
196 | unsigned char *odata; /* output data */ | ||
197 | dma_addr_t odata_dma; | ||
198 | #endif | ||
199 | |||
177 | char phys[65]; /* physical device path */ | 200 | char phys[65]; /* physical device path */ |
178 | 201 | ||
179 | int dpad_mapping; /* map d-pad to buttons or to axes */ | 202 | int dpad_mapping; /* map d-pad to buttons or to axes */ |
203 | int xtype; /* type of xbox device */ | ||
180 | }; | 204 | }; |
181 | 205 | ||
182 | /* | 206 | /* |
@@ -212,8 +236,8 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d | |||
212 | } else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ { | 236 | } else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ { |
213 | input_report_key(dev, BTN_LEFT, data[2] & 0x04); | 237 | input_report_key(dev, BTN_LEFT, data[2] & 0x04); |
214 | input_report_key(dev, BTN_RIGHT, data[2] & 0x08); | 238 | input_report_key(dev, BTN_RIGHT, data[2] & 0x08); |
215 | input_report_key(dev, BTN_0, data[2] & 0x01); // up | 239 | input_report_key(dev, BTN_0, data[2] & 0x01); /* up */ |
216 | input_report_key(dev, BTN_1, data[2] & 0x02); // down | 240 | input_report_key(dev, BTN_1, data[2] & 0x02); /* down */ |
217 | } | 241 | } |
218 | 242 | ||
219 | /* start/back buttons and stick press left/right */ | 243 | /* start/back buttons and stick press left/right */ |
@@ -235,6 +259,64 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d | |||
235 | input_sync(dev); | 259 | input_sync(dev); |
236 | } | 260 | } |
237 | 261 | ||
262 | /* | ||
263 | * xpad360_process_packet | ||
264 | * | ||
265 | * Completes a request by converting the data into events for the | ||
266 | * input subsystem. It is version for xbox 360 controller | ||
267 | * | ||
268 | * The used report descriptor was taken from: | ||
269 | * http://www.free60.org/wiki/Gamepad | ||
270 | */ | ||
271 | |||
272 | static void xpad360_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data) | ||
273 | { | ||
274 | struct input_dev *dev = xpad->dev; | ||
275 | |||
276 | /* digital pad */ | ||
277 | if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) { | ||
278 | input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); | ||
279 | input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01)); | ||
280 | } else if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) { | ||
281 | /* dpad as buttons (right, left, down, up) */ | ||
282 | input_report_key(dev, BTN_LEFT, data[2] & 0x04); | ||
283 | input_report_key(dev, BTN_RIGHT, data[2] & 0x08); | ||
284 | input_report_key(dev, BTN_0, data[2] & 0x01); /* up */ | ||
285 | input_report_key(dev, BTN_1, data[2] & 0x02); /* down */ | ||
286 | } | ||
287 | |||
288 | /* start/back buttons */ | ||
289 | input_report_key(dev, BTN_START, data[2] & 0x10); | ||
290 | input_report_key(dev, BTN_BACK, data[2] & 0x20); | ||
291 | |||
292 | /* stick press left/right */ | ||
293 | input_report_key(dev, BTN_THUMBL, data[2] & 0x40); | ||
294 | input_report_key(dev, BTN_THUMBR, data[2] & 0x80); | ||
295 | |||
296 | /* buttons A,B,X,Y,TL,TR and MODE */ | ||
297 | input_report_key(dev, BTN_A, data[3] & 0x10); | ||
298 | input_report_key(dev, BTN_B, data[3] & 0x20); | ||
299 | input_report_key(dev, BTN_X, data[3] & 0x40); | ||
300 | input_report_key(dev, BTN_Y, data[3] & 0x80); | ||
301 | input_report_key(dev, BTN_TL, data[3] & 0x01); | ||
302 | input_report_key(dev, BTN_TR, data[3] & 0x02); | ||
303 | input_report_key(dev, BTN_MODE, data[3] & 0x04); | ||
304 | |||
305 | /* left stick */ | ||
306 | input_report_abs(dev, ABS_X, (__s16) (((__s16)data[7] << 8) | (__s16)data[6])); | ||
307 | input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[9] << 8) | (__s16)data[8])); | ||
308 | |||
309 | /* right stick */ | ||
310 | input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[11] << 8) | (__s16)data[10])); | ||
311 | input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[13] << 8) | (__s16)data[12])); | ||
312 | |||
313 | /* triggers left/right */ | ||
314 | input_report_abs(dev, ABS_Z, data[4]); | ||
315 | input_report_abs(dev, ABS_RZ, data[5]); | ||
316 | |||
317 | input_sync(dev); | ||
318 | } | ||
319 | |||
238 | static void xpad_irq_in(struct urb *urb) | 320 | static void xpad_irq_in(struct urb *urb) |
239 | { | 321 | { |
240 | struct usb_xpad *xpad = urb->context; | 322 | struct usb_xpad *xpad = urb->context; |
@@ -255,7 +337,10 @@ static void xpad_irq_in(struct urb *urb) | |||
255 | goto exit; | 337 | goto exit; |
256 | } | 338 | } |
257 | 339 | ||
258 | xpad_process_packet(xpad, 0, xpad->idata); | 340 | if (xpad->xtype == XTYPE_XBOX360) |
341 | xpad360_process_packet(xpad, 0, xpad->idata); | ||
342 | else | ||
343 | xpad_process_packet(xpad, 0, xpad->idata); | ||
259 | 344 | ||
260 | exit: | 345 | exit: |
261 | retval = usb_submit_urb (urb, GFP_ATOMIC); | 346 | retval = usb_submit_urb (urb, GFP_ATOMIC); |
@@ -264,7 +349,114 @@ exit: | |||
264 | __FUNCTION__, retval); | 349 | __FUNCTION__, retval); |
265 | } | 350 | } |
266 | 351 | ||
267 | static int xpad_open (struct input_dev *dev) | 352 | #ifdef CONFIG_JOYSTICK_XPAD_FF |
353 | static void xpad_irq_out(struct urb *urb) | ||
354 | { | ||
355 | int retval; | ||
356 | |||
357 | switch (urb->status) { | ||
358 | case 0: | ||
359 | /* success */ | ||
360 | break; | ||
361 | case -ECONNRESET: | ||
362 | case -ENOENT: | ||
363 | case -ESHUTDOWN: | ||
364 | /* this urb is terminated, clean up */ | ||
365 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
366 | return; | ||
367 | default: | ||
368 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
369 | goto exit; | ||
370 | } | ||
371 | |||
372 | exit: | ||
373 | retval = usb_submit_urb(urb, GFP_ATOMIC); | ||
374 | if (retval) | ||
375 | err("%s - usb_submit_urb failed with result %d", | ||
376 | __FUNCTION__, retval); | ||
377 | } | ||
378 | |||
379 | static int xpad_play_effect(struct input_dev *dev, void *data, | ||
380 | struct ff_effect *effect) | ||
381 | { | ||
382 | struct usb_xpad *xpad = input_get_drvdata(dev); | ||
383 | |||
384 | if (effect->type == FF_RUMBLE) { | ||
385 | __u16 strong = effect->u.rumble.strong_magnitude; | ||
386 | __u16 weak = effect->u.rumble.weak_magnitude; | ||
387 | xpad->odata[0] = 0x00; | ||
388 | xpad->odata[1] = 0x08; | ||
389 | xpad->odata[2] = 0x00; | ||
390 | xpad->odata[3] = strong / 256; | ||
391 | xpad->odata[4] = weak / 256; | ||
392 | xpad->odata[5] = 0x00; | ||
393 | xpad->odata[6] = 0x00; | ||
394 | xpad->odata[7] = 0x00; | ||
395 | usb_submit_urb(xpad->irq_out, GFP_KERNEL); | ||
396 | } | ||
397 | |||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | static int xpad_init_ff(struct usb_interface *intf, struct usb_xpad *xpad) | ||
402 | { | ||
403 | struct usb_endpoint_descriptor *ep_irq_out; | ||
404 | int error = -ENOMEM; | ||
405 | |||
406 | if (xpad->xtype != XTYPE_XBOX360) | ||
407 | return 0; | ||
408 | |||
409 | xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN, | ||
410 | GFP_ATOMIC, &xpad->odata_dma ); | ||
411 | if (!xpad->odata) | ||
412 | goto fail1; | ||
413 | |||
414 | xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL); | ||
415 | if (!xpad->irq_out) | ||
416 | goto fail2; | ||
417 | |||
418 | ep_irq_out = &intf->cur_altsetting->endpoint[1].desc; | ||
419 | usb_fill_int_urb(xpad->irq_out, xpad->udev, | ||
420 | usb_sndintpipe(xpad->udev, ep_irq_out->bEndpointAddress), | ||
421 | xpad->odata, XPAD_PKT_LEN, | ||
422 | xpad_irq_out, xpad, ep_irq_out->bInterval); | ||
423 | xpad->irq_out->transfer_dma = xpad->odata_dma; | ||
424 | xpad->irq_out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
425 | |||
426 | input_set_capability(xpad->dev, EV_FF, FF_RUMBLE); | ||
427 | |||
428 | error = input_ff_create_memless(xpad->dev, NULL, xpad_play_effect); | ||
429 | if (error) | ||
430 | goto fail2; | ||
431 | |||
432 | return 0; | ||
433 | |||
434 | fail2: usb_buffer_free(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma); | ||
435 | fail1: return error; | ||
436 | } | ||
437 | |||
438 | static void xpad_stop_ff(struct usb_xpad *xpad) | ||
439 | { | ||
440 | if (xpad->xtype == XTYPE_XBOX360) | ||
441 | usb_kill_urb(xpad->irq_out); | ||
442 | } | ||
443 | |||
444 | static void xpad_deinit_ff(struct usb_xpad *xpad) | ||
445 | { | ||
446 | if (xpad->xtype == XTYPE_XBOX360) { | ||
447 | usb_free_urb(xpad->irq_out); | ||
448 | usb_buffer_free(xpad->udev, XPAD_PKT_LEN, | ||
449 | xpad->odata, xpad->odata_dma); | ||
450 | } | ||
451 | } | ||
452 | |||
453 | #else | ||
454 | static int xpad_init_ff(struct usb_interface *intf, struct usb_xpad *xpad) { return 0; } | ||
455 | static void xpad_stop_ff(struct usb_xpad *xpad) { } | ||
456 | static void xpad_deinit_ff(struct usb_xpad *xpad) { } | ||
457 | #endif | ||
458 | |||
459 | static int xpad_open(struct input_dev *dev) | ||
268 | { | 460 | { |
269 | struct usb_xpad *xpad = input_get_drvdata(dev); | 461 | struct usb_xpad *xpad = input_get_drvdata(dev); |
270 | 462 | ||
@@ -275,11 +467,12 @@ static int xpad_open (struct input_dev *dev) | |||
275 | return 0; | 467 | return 0; |
276 | } | 468 | } |
277 | 469 | ||
278 | static void xpad_close (struct input_dev *dev) | 470 | static void xpad_close(struct input_dev *dev) |
279 | { | 471 | { |
280 | struct usb_xpad *xpad = input_get_drvdata(dev); | 472 | struct usb_xpad *xpad = input_get_drvdata(dev); |
281 | 473 | ||
282 | usb_kill_urb(xpad->irq_in); | 474 | usb_kill_urb(xpad->irq_in); |
475 | xpad_stop_ff(xpad); | ||
283 | } | 476 | } |
284 | 477 | ||
285 | static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) | 478 | static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) |
@@ -335,6 +528,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
335 | 528 | ||
336 | xpad->udev = udev; | 529 | xpad->udev = udev; |
337 | xpad->dpad_mapping = xpad_device[i].dpad_mapping; | 530 | xpad->dpad_mapping = xpad_device[i].dpad_mapping; |
531 | xpad->xtype = xpad_device[i].xtype; | ||
338 | if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN) | 532 | if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN) |
339 | xpad->dpad_mapping = dpad_to_buttons; | 533 | xpad->dpad_mapping = dpad_to_buttons; |
340 | xpad->dev = input_dev; | 534 | xpad->dev = input_dev; |
@@ -356,6 +550,9 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
356 | /* set up buttons */ | 550 | /* set up buttons */ |
357 | for (i = 0; xpad_btn[i] >= 0; i++) | 551 | for (i = 0; xpad_btn[i] >= 0; i++) |
358 | set_bit(xpad_btn[i], input_dev->keybit); | 552 | set_bit(xpad_btn[i], input_dev->keybit); |
553 | if (xpad->xtype == XTYPE_XBOX360) | ||
554 | for (i = 0; xpad360_btn[i] >= 0; i++) | ||
555 | set_bit(xpad360_btn[i], input_dev->keybit); | ||
359 | if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) | 556 | if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) |
360 | for (i = 0; xpad_btn_pad[i] >= 0; i++) | 557 | for (i = 0; xpad_btn_pad[i] >= 0; i++) |
361 | set_bit(xpad_btn_pad[i], input_dev->keybit); | 558 | set_bit(xpad_btn_pad[i], input_dev->keybit); |
@@ -367,6 +564,10 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
367 | for (i = 0; xpad_abs_pad[i] >= 0; i++) | 564 | for (i = 0; xpad_abs_pad[i] >= 0; i++) |
368 | xpad_set_up_abs(input_dev, xpad_abs_pad[i]); | 565 | xpad_set_up_abs(input_dev, xpad_abs_pad[i]); |
369 | 566 | ||
567 | error = xpad_init_ff(intf, xpad); | ||
568 | if (error) | ||
569 | goto fail2; | ||
570 | |||
370 | ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; | 571 | ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; |
371 | usb_fill_int_urb(xpad->irq_in, udev, | 572 | usb_fill_int_urb(xpad->irq_in, udev, |
372 | usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), | 573 | usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), |
@@ -396,10 +597,10 @@ static void xpad_disconnect(struct usb_interface *intf) | |||
396 | 597 | ||
397 | usb_set_intfdata(intf, NULL); | 598 | usb_set_intfdata(intf, NULL); |
398 | if (xpad) { | 599 | if (xpad) { |
399 | usb_kill_urb(xpad->irq_in); | ||
400 | input_unregister_device(xpad->dev); | 600 | input_unregister_device(xpad->dev); |
601 | xpad_deinit_ff(xpad); | ||
401 | usb_free_urb(xpad->irq_in); | 602 | usb_free_urb(xpad->irq_in); |
402 | usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN, | 603 | usb_buffer_free(xpad->udev, XPAD_PKT_LEN, |
403 | xpad->idata, xpad->idata_dma); | 604 | xpad->idata, xpad->idata_dma); |
404 | kfree(xpad); | 605 | kfree(xpad); |
405 | } | 606 | } |
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 9950fcb33650..41fc3d03b6eb 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -89,7 +89,7 @@ static unsigned char atkbd_set2_keycode[512] = { | |||
89 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 89 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
90 | 217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125, | 90 | 217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125, |
91 | 173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127, | 91 | 173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127, |
92 | 159, 0,115, 0,164, 0, 0,116,158, 0,150,166, 0, 0, 0,142, | 92 | 159, 0,115, 0,164, 0, 0,116,158, 0,172,166, 0, 0, 0,142, |
93 | 157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0, | 93 | 157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0, |
94 | 226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0, | 94 | 226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0, |
95 | 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112, | 95 | 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112, |
@@ -111,7 +111,7 @@ static unsigned char atkbd_set3_keycode[512] = { | |||
111 | 82, 83, 80, 76, 77, 72, 69, 98, 0, 96, 81, 0, 78, 73, 55,183, | 111 | 82, 83, 80, 76, 77, 72, 69, 98, 0, 96, 81, 0, 78, 73, 55,183, |
112 | 112 | ||
113 | 184,185,186,187, 74, 94, 92, 93, 0, 0, 0,125,126,127,112, 0, | 113 | 184,185,186,187, 74, 94, 92, 93, 0, 0, 0,125,126,127,112, 0, |
114 | 0,139,150,163,165,115,152,150,166,140,160,154,113,114,167,168, | 114 | 0,139,172,163,165,115,152,172,166,140,160,154,113,114,167,168, |
115 | 148,149,147,140 | 115 | 148,149,147,140 |
116 | }; | 116 | }; |
117 | 117 | ||
diff --git a/drivers/input/keyboard/pxa27x_keyboard.c b/drivers/input/keyboard/pxa27x_keyboard.c index f9e82c9ca421..ebe5eacf2990 100644 --- a/drivers/input/keyboard/pxa27x_keyboard.c +++ b/drivers/input/keyboard/pxa27x_keyboard.c | |||
@@ -140,7 +140,7 @@ static int pxakbd_resume(struct platform_device *pdev) | |||
140 | KPREC = pdata->reg_kprec; | 140 | KPREC = pdata->reg_kprec; |
141 | 141 | ||
142 | /* Enable unit clock */ | 142 | /* Enable unit clock */ |
143 | pxa_set_cken(CKEN19_KEYPAD, 1); | 143 | pxa_set_cken(CKEN_KEYPAD, 1); |
144 | } | 144 | } |
145 | 145 | ||
146 | mutex_unlock(&input_dev->mutex); | 146 | mutex_unlock(&input_dev->mutex); |
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 88e29074ac90..9b26574f1466 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -65,9 +65,13 @@ config INPUT_COBALT_BTNS | |||
65 | config INPUT_WISTRON_BTNS | 65 | config INPUT_WISTRON_BTNS |
66 | tristate "x86 Wistron laptop button interface" | 66 | tristate "x86 Wistron laptop button interface" |
67 | depends on X86 && !X86_64 | 67 | depends on X86 && !X86_64 |
68 | select INPUT_POLLDEV | ||
69 | select NEW_LEDS | ||
70 | select LEDS_CLASS | ||
68 | help | 71 | help |
69 | Say Y here for support of Winstron laptop button interface, used on | 72 | Say Y here for support of Winstron laptop button interface, used on |
70 | laptops of various brands, including Acer and Fujitsu-Siemens. | 73 | laptops of various brands, including Acer and Fujitsu-Siemens. If |
74 | available, mail and wifi leds will be controlable via /sys/class/leds. | ||
71 | 75 | ||
72 | To compile this driver as a module, choose M here: the module will | 76 | To compile this driver as a module, choose M here: the module will |
73 | be called wistron_btns. | 77 | be called wistron_btns. |
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 961aad7a0476..60121f10f8d9 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
@@ -20,37 +20,31 @@ | |||
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/dmi.h> | 21 | #include <linux/dmi.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/input.h> | 23 | #include <linux/input-polldev.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/jiffies.h> | ||
25 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
26 | #include <linux/mc146818rtc.h> | 27 | #include <linux/mc146818rtc.h> |
27 | #include <linux/module.h> | 28 | #include <linux/module.h> |
28 | #include <linux/preempt.h> | 29 | #include <linux/preempt.h> |
29 | #include <linux/string.h> | 30 | #include <linux/string.h> |
30 | #include <linux/timer.h> | ||
31 | #include <linux/types.h> | 31 | #include <linux/types.h> |
32 | #include <linux/platform_device.h> | 32 | #include <linux/platform_device.h> |
33 | #include <linux/leds.h> | ||
33 | 34 | ||
34 | /* | 35 | /* How often we poll keys - msecs */ |
35 | * Number of attempts to read data from queue per poll; | 36 | #define POLL_INTERVAL_DEFAULT 500 /* when idle */ |
36 | * the queue can hold up to 31 entries | 37 | #define POLL_INTERVAL_BURST 100 /* when a key was recently pressed */ |
37 | */ | ||
38 | #define MAX_POLL_ITERATIONS 64 | ||
39 | |||
40 | #define POLL_FREQUENCY 10 /* Number of polls per second */ | ||
41 | |||
42 | #if POLL_FREQUENCY > HZ | ||
43 | #error "POLL_FREQUENCY too high" | ||
44 | #endif | ||
45 | 38 | ||
46 | /* BIOS subsystem IDs */ | 39 | /* BIOS subsystem IDs */ |
47 | #define WIFI 0x35 | 40 | #define WIFI 0x35 |
48 | #define BLUETOOTH 0x34 | 41 | #define BLUETOOTH 0x34 |
42 | #define MAIL_LED 0x31 | ||
49 | 43 | ||
50 | MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>"); | 44 | MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>"); |
51 | MODULE_DESCRIPTION("Wistron laptop button driver"); | 45 | MODULE_DESCRIPTION("Wistron laptop button driver"); |
52 | MODULE_LICENSE("GPL v2"); | 46 | MODULE_LICENSE("GPL v2"); |
53 | MODULE_VERSION("0.2"); | 47 | MODULE_VERSION("0.3"); |
54 | 48 | ||
55 | static int force; /* = 0; */ | 49 | static int force; /* = 0; */ |
56 | module_param(force, bool, 0); | 50 | module_param(force, bool, 0); |
@@ -248,9 +242,10 @@ enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH }; | |||
248 | #define FE_WIFI_LED 0x02 | 242 | #define FE_WIFI_LED 0x02 |
249 | #define FE_UNTESTED 0x80 | 243 | #define FE_UNTESTED 0x80 |
250 | 244 | ||
251 | static const struct key_entry *keymap; /* = NULL; Current key map */ | 245 | static struct key_entry *keymap; /* = NULL; Current key map */ |
252 | static int have_wifi; | 246 | static int have_wifi; |
253 | static int have_bluetooth; | 247 | static int have_bluetooth; |
248 | static int have_leds; | ||
254 | 249 | ||
255 | static int __init dmi_matched(struct dmi_system_id *dmi) | 250 | static int __init dmi_matched(struct dmi_system_id *dmi) |
256 | { | 251 | { |
@@ -263,6 +258,8 @@ static int __init dmi_matched(struct dmi_system_id *dmi) | |||
263 | else if (key->type == KE_BLUETOOTH) | 258 | else if (key->type == KE_BLUETOOTH) |
264 | have_bluetooth = 1; | 259 | have_bluetooth = 1; |
265 | } | 260 | } |
261 | have_leds = key->code & (FE_MAIL_LED | FE_WIFI_LED); | ||
262 | |||
266 | return 1; | 263 | return 1; |
267 | } | 264 | } |
268 | 265 | ||
@@ -966,118 +963,163 @@ static int __init select_keymap(void) | |||
966 | 963 | ||
967 | /* Input layer interface */ | 964 | /* Input layer interface */ |
968 | 965 | ||
969 | static struct input_dev *input_dev; | 966 | static struct input_polled_dev *wistron_idev; |
967 | static unsigned long jiffies_last_press; | ||
968 | static int wifi_enabled; | ||
969 | static int bluetooth_enabled; | ||
970 | 970 | ||
971 | static int __devinit setup_input_dev(void) | 971 | static void report_key(struct input_dev *dev, unsigned int keycode) |
972 | { | 972 | { |
973 | const struct key_entry *key; | 973 | input_report_key(dev, keycode, 1); |
974 | int error; | 974 | input_sync(dev); |
975 | input_report_key(dev, keycode, 0); | ||
976 | input_sync(dev); | ||
977 | } | ||
975 | 978 | ||
976 | input_dev = input_allocate_device(); | 979 | static void report_switch(struct input_dev *dev, unsigned int code, int value) |
977 | if (!input_dev) | 980 | { |
978 | return -ENOMEM; | 981 | input_report_switch(dev, code, value); |
982 | input_sync(dev); | ||
983 | } | ||
979 | 984 | ||
980 | input_dev->name = "Wistron laptop buttons"; | ||
981 | input_dev->phys = "wistron/input0"; | ||
982 | input_dev->id.bustype = BUS_HOST; | ||
983 | input_dev->cdev.dev = &wistron_device->dev; | ||
984 | 985 | ||
985 | for (key = keymap; key->type != KE_END; key++) { | 986 | /* led management */ |
986 | switch (key->type) { | 987 | static void wistron_mail_led_set(struct led_classdev *led_cdev, |
987 | case KE_KEY: | 988 | enum led_brightness value) |
988 | set_bit(EV_KEY, input_dev->evbit); | 989 | { |
989 | set_bit(key->keycode, input_dev->keybit); | 990 | bios_set_state(MAIL_LED, (value != LED_OFF) ? 1 : 0); |
990 | break; | 991 | } |
991 | 992 | ||
992 | case KE_SW: | 993 | /* same as setting up wifi card, but for laptops on which the led is managed */ |
993 | set_bit(EV_SW, input_dev->evbit); | 994 | static void wistron_wifi_led_set(struct led_classdev *led_cdev, |
994 | set_bit(key->sw.code, input_dev->swbit); | 995 | enum led_brightness value) |
995 | break; | 996 | { |
997 | bios_set_state(WIFI, (value != LED_OFF) ? 1 : 0); | ||
998 | } | ||
996 | 999 | ||
997 | default: | 1000 | static struct led_classdev wistron_mail_led = { |
998 | ; | 1001 | .name = "mail:green", |
999 | } | 1002 | .brightness_set = wistron_mail_led_set, |
1000 | } | 1003 | }; |
1001 | 1004 | ||
1002 | /* reads information flags on KE_END */ | 1005 | static struct led_classdev wistron_wifi_led = { |
1003 | if (key->code & FE_UNTESTED) | 1006 | .name = "wifi:red", |
1004 | printk(KERN_WARNING "Untested laptop multimedia keys, " | 1007 | .brightness_set = wistron_wifi_led_set, |
1005 | "please report success or failure to eric.piel" | 1008 | }; |
1006 | "@tremplin-utc.net\n"); | ||
1007 | 1009 | ||
1008 | error = input_register_device(input_dev); | 1010 | static void __devinit wistron_led_init(struct device *parent) |
1009 | if (error) { | 1011 | { |
1010 | input_free_device(input_dev); | 1012 | if (have_leds & FE_WIFI_LED) { |
1011 | return error; | 1013 | u16 wifi = bios_get_default_setting(WIFI); |
1014 | if (wifi & 1) { | ||
1015 | wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF; | ||
1016 | if (led_classdev_register(parent, &wistron_wifi_led)) | ||
1017 | have_leds &= ~FE_WIFI_LED; | ||
1018 | else | ||
1019 | bios_set_state(WIFI, wistron_wifi_led.brightness); | ||
1020 | |||
1021 | } else | ||
1022 | have_leds &= ~FE_WIFI_LED; | ||
1012 | } | 1023 | } |
1013 | 1024 | ||
1014 | return 0; | 1025 | if (have_leds & FE_MAIL_LED) { |
1026 | /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */ | ||
1027 | wistron_mail_led.brightness = LED_OFF; | ||
1028 | if (led_classdev_register(parent, &wistron_mail_led)) | ||
1029 | have_leds &= ~FE_MAIL_LED; | ||
1030 | else | ||
1031 | bios_set_state(MAIL_LED, wistron_mail_led.brightness); | ||
1032 | } | ||
1015 | } | 1033 | } |
1016 | 1034 | ||
1017 | static void report_key(unsigned keycode) | 1035 | static void __devexit wistron_led_remove(void) |
1018 | { | 1036 | { |
1019 | input_report_key(input_dev, keycode, 1); | 1037 | if (have_leds & FE_MAIL_LED) |
1020 | input_sync(input_dev); | 1038 | led_classdev_unregister(&wistron_mail_led); |
1021 | input_report_key(input_dev, keycode, 0); | 1039 | |
1022 | input_sync(input_dev); | 1040 | if (have_leds & FE_WIFI_LED) |
1041 | led_classdev_unregister(&wistron_wifi_led); | ||
1023 | } | 1042 | } |
1024 | 1043 | ||
1025 | static void report_switch(unsigned code, int value) | 1044 | static inline void wistron_led_suspend(void) |
1026 | { | 1045 | { |
1027 | input_report_switch(input_dev, code, value); | 1046 | if (have_leds & FE_MAIL_LED) |
1028 | input_sync(input_dev); | 1047 | led_classdev_suspend(&wistron_mail_led); |
1048 | |||
1049 | if (have_leds & FE_WIFI_LED) | ||
1050 | led_classdev_suspend(&wistron_wifi_led); | ||
1029 | } | 1051 | } |
1030 | 1052 | ||
1031 | /* Driver core */ | 1053 | static inline void wistron_led_resume(void) |
1054 | { | ||
1055 | if (have_leds & FE_MAIL_LED) | ||
1056 | led_classdev_resume(&wistron_mail_led); | ||
1032 | 1057 | ||
1033 | static int wifi_enabled; | 1058 | if (have_leds & FE_WIFI_LED) |
1034 | static int bluetooth_enabled; | 1059 | led_classdev_resume(&wistron_wifi_led); |
1060 | } | ||
1061 | |||
1062 | static struct key_entry *wistron_get_entry_by_scancode(int code) | ||
1063 | { | ||
1064 | struct key_entry *key; | ||
1035 | 1065 | ||
1036 | static void poll_bios(unsigned long); | 1066 | for (key = keymap; key->type != KE_END; key++) |
1067 | if (code == key->code) | ||
1068 | return key; | ||
1037 | 1069 | ||
1038 | static struct timer_list poll_timer = TIMER_INITIALIZER(poll_bios, 0, 0); | 1070 | return NULL; |
1071 | } | ||
1039 | 1072 | ||
1040 | static void handle_key(u8 code) | 1073 | static struct key_entry *wistron_get_entry_by_keycode(int keycode) |
1041 | { | 1074 | { |
1042 | const struct key_entry *key; | 1075 | struct key_entry *key; |
1043 | 1076 | ||
1044 | for (key = keymap; key->type != KE_END; key++) { | 1077 | for (key = keymap; key->type != KE_END; key++) |
1045 | if (code == key->code) { | 1078 | if (key->type == KE_KEY && keycode == key->keycode) |
1046 | switch (key->type) { | 1079 | return key; |
1047 | case KE_KEY: | ||
1048 | report_key(key->keycode); | ||
1049 | break; | ||
1050 | 1080 | ||
1051 | case KE_SW: | 1081 | return NULL; |
1052 | report_switch(key->sw.code, key->sw.value); | 1082 | } |
1053 | break; | ||
1054 | 1083 | ||
1055 | case KE_WIFI: | 1084 | static void handle_key(u8 code) |
1056 | if (have_wifi) { | 1085 | { |
1057 | wifi_enabled = !wifi_enabled; | 1086 | const struct key_entry *key = wistron_get_entry_by_scancode(code); |
1058 | bios_set_state(WIFI, wifi_enabled); | ||
1059 | } | ||
1060 | break; | ||
1061 | 1087 | ||
1062 | case KE_BLUETOOTH: | 1088 | if (key) { |
1063 | if (have_bluetooth) { | 1089 | switch (key->type) { |
1064 | bluetooth_enabled = !bluetooth_enabled; | 1090 | case KE_KEY: |
1065 | bios_set_state(BLUETOOTH, bluetooth_enabled); | 1091 | report_key(wistron_idev->input, key->keycode); |
1066 | } | 1092 | break; |
1067 | break; | ||
1068 | 1093 | ||
1069 | case KE_END: | 1094 | case KE_SW: |
1070 | break; | 1095 | report_switch(wistron_idev->input, |
1071 | default: | 1096 | key->sw.code, key->sw.value); |
1072 | BUG(); | 1097 | break; |
1098 | |||
1099 | case KE_WIFI: | ||
1100 | if (have_wifi) { | ||
1101 | wifi_enabled = !wifi_enabled; | ||
1102 | bios_set_state(WIFI, wifi_enabled); | ||
1103 | } | ||
1104 | break; | ||
1105 | |||
1106 | case KE_BLUETOOTH: | ||
1107 | if (have_bluetooth) { | ||
1108 | bluetooth_enabled = !bluetooth_enabled; | ||
1109 | bios_set_state(BLUETOOTH, bluetooth_enabled); | ||
1073 | } | 1110 | } |
1074 | return; | 1111 | break; |
1112 | |||
1113 | default: | ||
1114 | BUG(); | ||
1075 | } | 1115 | } |
1076 | } | 1116 | jiffies_last_press = jiffies; |
1077 | printk(KERN_NOTICE "wistron_btns: Unknown key code %02X\n", code); | 1117 | } else |
1118 | printk(KERN_NOTICE | ||
1119 | "wistron_btns: Unknown key code %02X\n", code); | ||
1078 | } | 1120 | } |
1079 | 1121 | ||
1080 | static void poll_bios(unsigned long discard) | 1122 | static void poll_bios(bool discard) |
1081 | { | 1123 | { |
1082 | u8 qlen; | 1124 | u8 qlen; |
1083 | u16 val; | 1125 | u16 val; |
@@ -1090,15 +1132,118 @@ static void poll_bios(unsigned long discard) | |||
1090 | if (val != 0 && !discard) | 1132 | if (val != 0 && !discard) |
1091 | handle_key((u8)val); | 1133 | handle_key((u8)val); |
1092 | } | 1134 | } |
1135 | } | ||
1136 | |||
1137 | static void wistron_flush(struct input_polled_dev *dev) | ||
1138 | { | ||
1139 | /* Flush stale event queue */ | ||
1140 | poll_bios(true); | ||
1141 | } | ||
1142 | |||
1143 | static void wistron_poll(struct input_polled_dev *dev) | ||
1144 | { | ||
1145 | poll_bios(false); | ||
1146 | |||
1147 | /* Increase poll frequency if user is currently pressing keys (< 2s ago) */ | ||
1148 | if (time_before(jiffies, jiffies_last_press + 2 * HZ)) | ||
1149 | dev->poll_interval = POLL_INTERVAL_BURST; | ||
1150 | else | ||
1151 | dev->poll_interval = POLL_INTERVAL_DEFAULT; | ||
1152 | } | ||
1153 | |||
1154 | static int wistron_getkeycode(struct input_dev *dev, int scancode, int *keycode) | ||
1155 | { | ||
1156 | const struct key_entry *key = wistron_get_entry_by_scancode(scancode); | ||
1157 | |||
1158 | if (key && key->type == KE_KEY) { | ||
1159 | *keycode = key->keycode; | ||
1160 | return 0; | ||
1161 | } | ||
1162 | |||
1163 | return -EINVAL; | ||
1164 | } | ||
1165 | |||
1166 | static int wistron_setkeycode(struct input_dev *dev, int scancode, int keycode) | ||
1167 | { | ||
1168 | struct key_entry *key; | ||
1169 | int old_keycode; | ||
1170 | |||
1171 | if (keycode < 0 || keycode > KEY_MAX) | ||
1172 | return -EINVAL; | ||
1173 | |||
1174 | key = wistron_get_entry_by_scancode(scancode); | ||
1175 | if (key && key->type == KE_KEY) { | ||
1176 | old_keycode = key->keycode; | ||
1177 | key->keycode = keycode; | ||
1178 | set_bit(keycode, dev->keybit); | ||
1179 | if (!wistron_get_entry_by_keycode(old_keycode)) | ||
1180 | clear_bit(old_keycode, dev->keybit); | ||
1181 | return 0; | ||
1182 | } | ||
1093 | 1183 | ||
1094 | mod_timer(&poll_timer, jiffies + HZ / POLL_FREQUENCY); | 1184 | return -EINVAL; |
1095 | } | 1185 | } |
1096 | 1186 | ||
1187 | static int __devinit setup_input_dev(void) | ||
1188 | { | ||
1189 | const struct key_entry *key; | ||
1190 | struct input_dev *input_dev; | ||
1191 | int error; | ||
1192 | |||
1193 | wistron_idev = input_allocate_polled_device(); | ||
1194 | if (!wistron_idev) | ||
1195 | return -ENOMEM; | ||
1196 | |||
1197 | wistron_idev->flush = wistron_flush; | ||
1198 | wistron_idev->poll = wistron_poll; | ||
1199 | wistron_idev->poll_interval = POLL_INTERVAL_DEFAULT; | ||
1200 | |||
1201 | input_dev = wistron_idev->input; | ||
1202 | input_dev->name = "Wistron laptop buttons"; | ||
1203 | input_dev->phys = "wistron/input0"; | ||
1204 | input_dev->id.bustype = BUS_HOST; | ||
1205 | input_dev->dev.parent = &wistron_device->dev; | ||
1206 | |||
1207 | input_dev->getkeycode = wistron_getkeycode; | ||
1208 | input_dev->setkeycode = wistron_setkeycode; | ||
1209 | |||
1210 | for (key = keymap; key->type != KE_END; key++) { | ||
1211 | switch (key->type) { | ||
1212 | case KE_KEY: | ||
1213 | set_bit(EV_KEY, input_dev->evbit); | ||
1214 | set_bit(key->keycode, input_dev->keybit); | ||
1215 | break; | ||
1216 | |||
1217 | case KE_SW: | ||
1218 | set_bit(EV_SW, input_dev->evbit); | ||
1219 | set_bit(key->sw.code, input_dev->swbit); | ||
1220 | break; | ||
1221 | |||
1222 | default: | ||
1223 | break; | ||
1224 | } | ||
1225 | } | ||
1226 | |||
1227 | /* reads information flags on KE_END */ | ||
1228 | if (key->code & FE_UNTESTED) | ||
1229 | printk(KERN_WARNING "Untested laptop multimedia keys, " | ||
1230 | "please report success or failure to eric.piel" | ||
1231 | "@tremplin-utc.net\n"); | ||
1232 | |||
1233 | error = input_register_polled_device(wistron_idev); | ||
1234 | if (error) { | ||
1235 | input_free_polled_device(wistron_idev); | ||
1236 | return error; | ||
1237 | } | ||
1238 | |||
1239 | return 0; | ||
1240 | } | ||
1241 | |||
1242 | /* Driver core */ | ||
1243 | |||
1097 | static int __devinit wistron_probe(struct platform_device *dev) | 1244 | static int __devinit wistron_probe(struct platform_device *dev) |
1098 | { | 1245 | { |
1099 | int err = setup_input_dev(); | 1246 | int err; |
1100 | if (err) | ||
1101 | return err; | ||
1102 | 1247 | ||
1103 | bios_attach(); | 1248 | bios_attach(); |
1104 | cmos_address = bios_get_cmos_address(); | 1249 | cmos_address = bios_get_cmos_address(); |
@@ -1125,15 +1270,21 @@ static int __devinit wistron_probe(struct platform_device *dev) | |||
1125 | bios_set_state(BLUETOOTH, bluetooth_enabled); | 1270 | bios_set_state(BLUETOOTH, bluetooth_enabled); |
1126 | } | 1271 | } |
1127 | 1272 | ||
1128 | poll_bios(1); /* Flush stale event queue and arm timer */ | 1273 | wistron_led_init(&dev->dev); |
1274 | err = setup_input_dev(); | ||
1275 | if (err) { | ||
1276 | bios_detach(); | ||
1277 | return err; | ||
1278 | } | ||
1129 | 1279 | ||
1130 | return 0; | 1280 | return 0; |
1131 | } | 1281 | } |
1132 | 1282 | ||
1133 | static int __devexit wistron_remove(struct platform_device *dev) | 1283 | static int __devexit wistron_remove(struct platform_device *dev) |
1134 | { | 1284 | { |
1135 | del_timer_sync(&poll_timer); | 1285 | wistron_led_remove(); |
1136 | input_unregister_device(input_dev); | 1286 | input_unregister_polled_device(wistron_idev); |
1287 | input_free_polled_device(wistron_idev); | ||
1137 | bios_detach(); | 1288 | bios_detach(); |
1138 | 1289 | ||
1139 | return 0; | 1290 | return 0; |
@@ -1142,14 +1293,13 @@ static int __devexit wistron_remove(struct platform_device *dev) | |||
1142 | #ifdef CONFIG_PM | 1293 | #ifdef CONFIG_PM |
1143 | static int wistron_suspend(struct platform_device *dev, pm_message_t state) | 1294 | static int wistron_suspend(struct platform_device *dev, pm_message_t state) |
1144 | { | 1295 | { |
1145 | del_timer_sync(&poll_timer); | ||
1146 | |||
1147 | if (have_wifi) | 1296 | if (have_wifi) |
1148 | bios_set_state(WIFI, 0); | 1297 | bios_set_state(WIFI, 0); |
1149 | 1298 | ||
1150 | if (have_bluetooth) | 1299 | if (have_bluetooth) |
1151 | bios_set_state(BLUETOOTH, 0); | 1300 | bios_set_state(BLUETOOTH, 0); |
1152 | 1301 | ||
1302 | wistron_led_suspend(); | ||
1153 | return 0; | 1303 | return 0; |
1154 | } | 1304 | } |
1155 | 1305 | ||
@@ -1161,7 +1311,8 @@ static int wistron_resume(struct platform_device *dev) | |||
1161 | if (have_bluetooth) | 1311 | if (have_bluetooth) |
1162 | bios_set_state(BLUETOOTH, bluetooth_enabled); | 1312 | bios_set_state(BLUETOOTH, bluetooth_enabled); |
1163 | 1313 | ||
1164 | poll_bios(1); | 1314 | wistron_led_resume(); |
1315 | poll_bios(true); | ||
1165 | 1316 | ||
1166 | return 0; | 1317 | return 0; |
1167 | } | 1318 | } |
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 50e06e8dd05d..7bbea097cda2 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig | |||
@@ -216,4 +216,20 @@ config MOUSE_HIL | |||
216 | help | 216 | help |
217 | Say Y here to support HIL pointers. | 217 | Say Y here to support HIL pointers. |
218 | 218 | ||
219 | config MOUSE_GPIO | ||
220 | tristate "GPIO mouse" | ||
221 | depends on GENERIC_GPIO | ||
222 | select INPUT_POLLDEV | ||
223 | help | ||
224 | This driver simulates a mouse on GPIO lines of various CPUs (and some | ||
225 | other chips). | ||
226 | |||
227 | Say Y here if your device has buttons or a simple joystick connected | ||
228 | directly to GPIO lines. Your board-specific setup logic must also | ||
229 | provide a platform device and platform data saying which GPIOs are | ||
230 | used. | ||
231 | |||
232 | To compile this driver as a module, choose M here: the | ||
233 | module will be called gpio_mouse. | ||
234 | |||
219 | endif | 235 | endif |
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index aa4ba878533f..9e6e36330820 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile | |||
@@ -15,6 +15,7 @@ obj-$(CONFIG_MOUSE_PS2) += psmouse.o | |||
15 | obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o | 15 | obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o |
16 | obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o | 16 | obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o |
17 | obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o | 17 | obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o |
18 | obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o | ||
18 | 19 | ||
19 | psmouse-objs := psmouse-base.o synaptics.o | 20 | psmouse-objs := psmouse-base.o synaptics.o |
20 | 21 | ||
diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c new file mode 100644 index 000000000000..0936d6ba015c --- /dev/null +++ b/drivers/input/mouse/gpio_mouse.c | |||
@@ -0,0 +1,196 @@ | |||
1 | /* | ||
2 | * Driver for simulating a mouse on GPIO lines. | ||
3 | * | ||
4 | * Copyright (C) 2007 Atmel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/init.h> | ||
12 | #include <linux/version.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/input-polldev.h> | ||
16 | #include <linux/gpio_mouse.h> | ||
17 | |||
18 | #include <asm/gpio.h> | ||
19 | |||
20 | /* | ||
21 | * Timer function which is run every scan_ms ms when the device is opened. | ||
22 | * The dev input varaible is set to the the input_dev pointer. | ||
23 | */ | ||
24 | static void gpio_mouse_scan(struct input_polled_dev *dev) | ||
25 | { | ||
26 | struct gpio_mouse_platform_data *gpio = dev->private; | ||
27 | struct input_dev *input = dev->input; | ||
28 | int x, y; | ||
29 | |||
30 | if (gpio->bleft >= 0) | ||
31 | input_report_key(input, BTN_LEFT, | ||
32 | gpio_get_value(gpio->bleft) ^ gpio->polarity); | ||
33 | if (gpio->bmiddle >= 0) | ||
34 | input_report_key(input, BTN_MIDDLE, | ||
35 | gpio_get_value(gpio->bmiddle) ^ gpio->polarity); | ||
36 | if (gpio->bright >= 0) | ||
37 | input_report_key(input, BTN_RIGHT, | ||
38 | gpio_get_value(gpio->bright) ^ gpio->polarity); | ||
39 | |||
40 | x = (gpio_get_value(gpio->right) ^ gpio->polarity) | ||
41 | - (gpio_get_value(gpio->left) ^ gpio->polarity); | ||
42 | y = (gpio_get_value(gpio->down) ^ gpio->polarity) | ||
43 | - (gpio_get_value(gpio->up) ^ gpio->polarity); | ||
44 | |||
45 | input_report_rel(input, REL_X, x); | ||
46 | input_report_rel(input, REL_Y, y); | ||
47 | input_sync(input); | ||
48 | } | ||
49 | |||
50 | static int __init gpio_mouse_probe(struct platform_device *pdev) | ||
51 | { | ||
52 | struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data; | ||
53 | struct input_polled_dev *input_poll; | ||
54 | struct input_dev *input; | ||
55 | int pin, i; | ||
56 | int error; | ||
57 | |||
58 | if (!pdata) { | ||
59 | dev_err(&pdev->dev, "no platform data\n"); | ||
60 | error = -ENXIO; | ||
61 | goto out; | ||
62 | } | ||
63 | |||
64 | if (pdata->scan_ms < 0) { | ||
65 | dev_err(&pdev->dev, "invalid scan time\n"); | ||
66 | error = -EINVAL; | ||
67 | goto out; | ||
68 | } | ||
69 | |||
70 | for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) { | ||
71 | pin = pdata->pins[i]; | ||
72 | |||
73 | if (pin < 0) { | ||
74 | |||
75 | if (i <= GPIO_MOUSE_PIN_RIGHT) { | ||
76 | /* Mouse direction is required. */ | ||
77 | dev_err(&pdev->dev, | ||
78 | "missing GPIO for directions\n"); | ||
79 | error = -EINVAL; | ||
80 | goto out_free_gpios; | ||
81 | } | ||
82 | |||
83 | if (i == GPIO_MOUSE_PIN_BLEFT) | ||
84 | dev_dbg(&pdev->dev, "no left button defined\n"); | ||
85 | |||
86 | } else { | ||
87 | error = gpio_request(pin, "gpio_mouse"); | ||
88 | if (error) { | ||
89 | dev_err(&pdev->dev, "fail %d pin (%d idx)\n", | ||
90 | pin, i); | ||
91 | goto out_free_gpios; | ||
92 | } | ||
93 | |||
94 | gpio_direction_input(pin); | ||
95 | } | ||
96 | } | ||
97 | |||
98 | input_poll = input_allocate_polled_device(); | ||
99 | if (!input_poll) { | ||
100 | dev_err(&pdev->dev, "not enough memory for input device\n"); | ||
101 | error = -ENOMEM; | ||
102 | goto out_free_gpios; | ||
103 | } | ||
104 | |||
105 | platform_set_drvdata(pdev, input_poll); | ||
106 | |||
107 | /* set input-polldev handlers */ | ||
108 | input_poll->private = pdata; | ||
109 | input_poll->poll = gpio_mouse_scan; | ||
110 | input_poll->poll_interval = pdata->scan_ms; | ||
111 | |||
112 | input = input_poll->input; | ||
113 | input->name = pdev->name; | ||
114 | input->id.bustype = BUS_HOST; | ||
115 | input->dev.parent = &pdev->dev; | ||
116 | |||
117 | input_set_capability(input, EV_REL, REL_X); | ||
118 | input_set_capability(input, EV_REL, REL_Y); | ||
119 | if (pdata->bleft >= 0) | ||
120 | input_set_capability(input, EV_KEY, BTN_LEFT); | ||
121 | if (pdata->bmiddle >= 0) | ||
122 | input_set_capability(input, EV_KEY, BTN_MIDDLE); | ||
123 | if (pdata->bright >= 0) | ||
124 | input_set_capability(input, EV_KEY, BTN_RIGHT); | ||
125 | |||
126 | error = input_register_polled_device(input_poll); | ||
127 | if (error) { | ||
128 | dev_err(&pdev->dev, "could not register input device\n"); | ||
129 | goto out_free_polldev; | ||
130 | } | ||
131 | |||
132 | dev_dbg(&pdev->dev, "%d ms scan time, buttons: %s%s%s\n", | ||
133 | pdata->scan_ms, | ||
134 | pdata->bleft < 0 ? "" : "left ", | ||
135 | pdata->bmiddle < 0 ? "" : "middle ", | ||
136 | pdata->bright < 0 ? "" : "right"); | ||
137 | |||
138 | return 0; | ||
139 | |||
140 | out_free_polldev: | ||
141 | input_free_polled_device(input_poll); | ||
142 | platform_set_drvdata(pdev, NULL); | ||
143 | |||
144 | out_free_gpios: | ||
145 | while (--i >= 0) { | ||
146 | pin = pdata->pins[i]; | ||
147 | if (pin) | ||
148 | gpio_free(pin); | ||
149 | } | ||
150 | out: | ||
151 | return error; | ||
152 | } | ||
153 | |||
154 | static int __devexit gpio_mouse_remove(struct platform_device *pdev) | ||
155 | { | ||
156 | struct input_polled_dev *input = platform_get_drvdata(pdev); | ||
157 | struct gpio_mouse_platform_data *pdata = input->private; | ||
158 | int pin, i; | ||
159 | |||
160 | input_unregister_polled_device(input); | ||
161 | input_free_polled_device(input); | ||
162 | |||
163 | for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) { | ||
164 | pin = pdata->pins[i]; | ||
165 | if (pin >= 0) | ||
166 | gpio_free(pin); | ||
167 | } | ||
168 | |||
169 | platform_set_drvdata(pdev, NULL); | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | struct platform_driver gpio_mouse_device_driver = { | ||
175 | .remove = __devexit_p(gpio_mouse_remove), | ||
176 | .driver = { | ||
177 | .name = "gpio_mouse", | ||
178 | } | ||
179 | }; | ||
180 | |||
181 | static int __init gpio_mouse_init(void) | ||
182 | { | ||
183 | return platform_driver_probe(&gpio_mouse_device_driver, | ||
184 | gpio_mouse_probe); | ||
185 | } | ||
186 | module_init(gpio_mouse_init); | ||
187 | |||
188 | static void __exit gpio_mouse_exit(void) | ||
189 | { | ||
190 | platform_driver_unregister(&gpio_mouse_device_driver); | ||
191 | } | ||
192 | module_exit(gpio_mouse_exit); | ||
193 | |||
194 | MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); | ||
195 | MODULE_DESCRIPTION("GPIO mouse driver"); | ||
196 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index f15f695777f8..b9f0fb2530e2 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -178,6 +178,15 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse) | |||
178 | } | 178 | } |
179 | 179 | ||
180 | /* | 180 | /* |
181 | * Cortron PS2 Trackball reports SIDE button on the 4th bit of the first | ||
182 | * byte. | ||
183 | */ | ||
184 | if (psmouse->type == PSMOUSE_CORTRON) { | ||
185 | input_report_key(dev, BTN_SIDE, (packet[0] >> 3) & 1); | ||
186 | packet[0] |= 0x08; | ||
187 | } | ||
188 | |||
189 | /* | ||
181 | * Generic PS/2 Mouse | 190 | * Generic PS/2 Mouse |
182 | */ | 191 | */ |
183 | 192 | ||
@@ -539,6 +548,20 @@ static int ps2bare_detect(struct psmouse *psmouse, int set_properties) | |||
539 | return 0; | 548 | return 0; |
540 | } | 549 | } |
541 | 550 | ||
551 | /* | ||
552 | * Cortron PS/2 protocol detection. There's no special way to detect it, so it | ||
553 | * must be forced by sysfs protocol writing. | ||
554 | */ | ||
555 | static int cortron_detect(struct psmouse *psmouse, int set_properties) | ||
556 | { | ||
557 | if (set_properties) { | ||
558 | psmouse->vendor = "Cortron"; | ||
559 | psmouse->name = "PS/2 Trackball"; | ||
560 | set_bit(BTN_SIDE, psmouse->dev->keybit); | ||
561 | } | ||
562 | |||
563 | return 0; | ||
564 | } | ||
542 | 565 | ||
543 | /* | 566 | /* |
544 | * psmouse_extensions() probes for any extensions to the basic PS/2 protocol | 567 | * psmouse_extensions() probes for any extensions to the basic PS/2 protocol |
@@ -740,6 +763,12 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
740 | }, | 763 | }, |
741 | #endif | 764 | #endif |
742 | { | 765 | { |
766 | .type = PSMOUSE_CORTRON, | ||
767 | .name = "CortronPS/2", | ||
768 | .alias = "cortps", | ||
769 | .detect = cortron_detect, | ||
770 | }, | ||
771 | { | ||
743 | .type = PSMOUSE_AUTO, | 772 | .type = PSMOUSE_AUTO, |
744 | .name = "auto", | 773 | .name = "auto", |
745 | .alias = "any", | 774 | .alias = "any", |
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 3964e8acbc54..27a68835b5ba 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h | |||
@@ -88,6 +88,7 @@ enum psmouse_type { | |||
88 | PSMOUSE_LIFEBOOK, | 88 | PSMOUSE_LIFEBOOK, |
89 | PSMOUSE_TRACKPOINT, | 89 | PSMOUSE_TRACKPOINT, |
90 | PSMOUSE_TOUCHKIT_PS2, | 90 | PSMOUSE_TOUCHKIT_PS2, |
91 | PSMOUSE_CORTRON, | ||
91 | PSMOUSE_AUTO /* This one should always be last */ | 92 | PSMOUSE_AUTO /* This one should always be last */ |
92 | }; | 93 | }; |
93 | 94 | ||
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/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 887357666c68..0403622ae267 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c | |||
@@ -160,7 +160,7 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer, size_t cou | |||
160 | { | 160 | { |
161 | struct serio_raw_list *list = file->private_data; | 161 | struct serio_raw_list *list = file->private_data; |
162 | struct serio_raw *serio_raw = list->serio_raw; | 162 | struct serio_raw *serio_raw = list->serio_raw; |
163 | char c; | 163 | char uninitialized_var(c); |
164 | ssize_t retval = 0; | 164 | ssize_t retval = 0; |
165 | 165 | ||
166 | if (!serio_raw->serio) | 166 | if (!serio_raw->serio) |
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index cc0a498763d8..94683f58c9e1 100644 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c | |||
@@ -82,8 +82,8 @@ | |||
82 | /* | 82 | /* |
83 | * Version Information | 83 | * Version Information |
84 | */ | 84 | */ |
85 | #define DRIVER_VERSION "v1.5 (May-15-2004)" | 85 | #define DRIVER_VERSION "v2.3 (May 2, 2007)" |
86 | #define DRIVER_AUTHOR "Bryan W. Headley/Chris Atenasio" | 86 | #define DRIVER_AUTHOR "Bryan W. Headley/Chris Atenasio/Cedric Brun/Rene van Paassen" |
87 | #define DRIVER_DESC "Aiptek HyperPen USB Tablet Driver (Linux 2.6.x)" | 87 | #define DRIVER_DESC "Aiptek HyperPen USB Tablet Driver (Linux 2.6.x)" |
88 | 88 | ||
89 | /* | 89 | /* |
@@ -112,7 +112,7 @@ | |||
112 | * (returned as Report 3 - absolute coordinates from the mouse) | 112 | * (returned as Report 3 - absolute coordinates from the mouse) |
113 | * | 113 | * |
114 | * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 | 114 | * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 |
115 | * byte0 0 0 0 0 0 0 1 0 | 115 | * byte0 0 0 0 0 0 0 1 1 |
116 | * byte1 X7 X6 X5 X4 X3 X2 X1 X0 | 116 | * byte1 X7 X6 X5 X4 X3 X2 X1 X0 |
117 | * byte2 X15 X14 X13 X12 X11 X10 X9 X8 | 117 | * byte2 X15 X14 X13 X12 X11 X10 X9 X8 |
118 | * byte3 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 | 118 | * byte3 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 |
@@ -134,7 +134,7 @@ | |||
134 | * (returned as Report 5 - macrokeys from the mouse) | 134 | * (returned as Report 5 - macrokeys from the mouse) |
135 | * | 135 | * |
136 | * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 | 136 | * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 |
137 | * byte0 0 0 0 0 0 1 0 0 | 137 | * byte0 0 0 0 0 0 1 0 1 |
138 | * byte1 0 0 0 BS2 BS Tip IR DV | 138 | * byte1 0 0 0 BS2 BS Tip IR DV |
139 | * byte2 0 0 0 0 0 0 1 0 | 139 | * byte2 0 0 0 0 0 0 1 0 |
140 | * byte3 0 0 0 K4 K3 K2 K1 K0 | 140 | * byte3 0 0 0 K4 K3 K2 K1 K0 |
@@ -218,15 +218,9 @@ | |||
218 | #define AIPTEK_WHEEL_DISABLE (-10101) | 218 | #define AIPTEK_WHEEL_DISABLE (-10101) |
219 | 219 | ||
220 | /* ToolCode values, which BTW are 0x140 .. 0x14f | 220 | /* ToolCode values, which BTW are 0x140 .. 0x14f |
221 | * We have things set up such that if TOOL_BUTTON_FIRED_BIT is | 221 | * We have things set up such that if the tool button has changed, |
222 | * not set, we'll send one instance of AIPTEK_TOOL_BUTTON_xxx. | 222 | * the tools get reset. |
223 | * | ||
224 | * Whenever the user resets the value, TOOL_BUTTON_FIRED_BIT will | ||
225 | * get reset. | ||
226 | */ | 223 | */ |
227 | #define TOOL_BUTTON(x) ((x) & 0x14f) | ||
228 | #define TOOL_BUTTON_FIRED(x) ((x) & 0x200) | ||
229 | #define TOOL_BUTTON_FIRED_BIT 0x200 | ||
230 | /* toolMode codes | 224 | /* toolMode codes |
231 | */ | 225 | */ |
232 | #define AIPTEK_TOOL_BUTTON_PEN_MODE BTN_TOOL_PEN | 226 | #define AIPTEK_TOOL_BUTTON_PEN_MODE BTN_TOOL_PEN |
@@ -264,9 +258,9 @@ | |||
264 | 258 | ||
265 | /* Mouse button programming | 259 | /* Mouse button programming |
266 | */ | 260 | */ |
267 | #define AIPTEK_MOUSE_LEFT_BUTTON 0x01 | 261 | #define AIPTEK_MOUSE_LEFT_BUTTON 0x04 |
268 | #define AIPTEK_MOUSE_RIGHT_BUTTON 0x02 | 262 | #define AIPTEK_MOUSE_RIGHT_BUTTON 0x08 |
269 | #define AIPTEK_MOUSE_MIDDLE_BUTTON 0x04 | 263 | #define AIPTEK_MOUSE_MIDDLE_BUTTON 0x10 |
270 | 264 | ||
271 | /* Stylus button programming | 265 | /* Stylus button programming |
272 | */ | 266 | */ |
@@ -294,7 +288,6 @@ struct aiptek_features { | |||
294 | int modelCode; /* Tablet model code (not unique) */ | 288 | int modelCode; /* Tablet model code (not unique) */ |
295 | int firmwareCode; /* prom/eeprom version */ | 289 | int firmwareCode; /* prom/eeprom version */ |
296 | char usbPath[64 + 1]; /* device's physical usb path */ | 290 | char usbPath[64 + 1]; /* device's physical usb path */ |
297 | char inputPath[64 + 1]; /* input device path */ | ||
298 | }; | 291 | }; |
299 | 292 | ||
300 | struct aiptek_settings { | 293 | struct aiptek_settings { |
@@ -327,9 +320,32 @@ struct aiptek { | |||
327 | int inDelay; /* jitter: in jitter delay? */ | 320 | int inDelay; /* jitter: in jitter delay? */ |
328 | unsigned long endDelay; /* jitter: time when delay ends */ | 321 | unsigned long endDelay; /* jitter: time when delay ends */ |
329 | int previousJitterable; /* jitterable prev value */ | 322 | int previousJitterable; /* jitterable prev value */ |
323 | |||
324 | int lastMacro; /* macro key to reset */ | ||
325 | int previousToolMode; /* pen, pencil, brush, etc. tool */ | ||
330 | unsigned char *data; /* incoming packet data */ | 326 | unsigned char *data; /* incoming packet data */ |
331 | }; | 327 | }; |
332 | 328 | ||
329 | static const int eventTypes[] = { | ||
330 | EV_KEY, EV_ABS, EV_REL, EV_MSC, | ||
331 | }; | ||
332 | |||
333 | static const int absEvents[] = { | ||
334 | ABS_X, ABS_Y, ABS_PRESSURE, ABS_TILT_X, ABS_TILT_Y, | ||
335 | ABS_WHEEL, ABS_MISC, | ||
336 | }; | ||
337 | |||
338 | static const int relEvents[] = { | ||
339 | REL_X, REL_Y, REL_WHEEL, | ||
340 | }; | ||
341 | |||
342 | static const int buttonEvents[] = { | ||
343 | BTN_LEFT, BTN_RIGHT, BTN_MIDDLE, | ||
344 | BTN_TOOL_PEN, BTN_TOOL_RUBBER, BTN_TOOL_PENCIL, BTN_TOOL_AIRBRUSH, | ||
345 | BTN_TOOL_BRUSH, BTN_TOOL_MOUSE, BTN_TOOL_LENS, BTN_TOUCH, | ||
346 | BTN_STYLUS, BTN_STYLUS2, | ||
347 | }; | ||
348 | |||
333 | /* | 349 | /* |
334 | * Permit easy lookup of keyboard events to send, versus | 350 | * Permit easy lookup of keyboard events to send, versus |
335 | * the bitmap which comes from the tablet. This hides the | 351 | * the bitmap which comes from the tablet. This hides the |
@@ -345,23 +361,39 @@ static const int macroKeyEvents[] = { | |||
345 | }; | 361 | }; |
346 | 362 | ||
347 | /*********************************************************************** | 363 | /*********************************************************************** |
348 | * Relative reports deliver values in 2's complement format to | 364 | * Map values to strings and back. Every map shoudl have the following |
349 | * deal with negative offsets. | 365 | * as its last element: { NULL, AIPTEK_INVALID_VALUE }. |
350 | */ | 366 | */ |
351 | static int aiptek_convert_from_2s_complement(unsigned char c) | 367 | #define AIPTEK_INVALID_VALUE -1 |
368 | |||
369 | struct aiptek_map { | ||
370 | const char *string; | ||
371 | int value; | ||
372 | }; | ||
373 | |||
374 | static int map_str_to_val(const struct aiptek_map *map, const char *str, size_t count) | ||
352 | { | 375 | { |
353 | int ret; | 376 | const struct aiptek_map *p; |
354 | unsigned char b = c; | ||
355 | int negate = 0; | ||
356 | 377 | ||
357 | if ((b & 0x80) != 0) { | 378 | if (str[count - 1] == '\n') |
358 | b = ~b; | 379 | count--; |
359 | b--; | 380 | |
360 | negate = 1; | 381 | for (p = map; p->string; p++) |
361 | } | 382 | if (!strncmp(str, p->string, count)) |
362 | ret = b; | 383 | return p->value; |
363 | ret = (negate == 1) ? -ret : ret; | 384 | |
364 | return ret; | 385 | return AIPTEK_INVALID_VALUE; |
386 | } | ||
387 | |||
388 | static const char *map_val_to_str(const struct aiptek_map *map, int val) | ||
389 | { | ||
390 | const struct aiptek_map *p; | ||
391 | |||
392 | for (p = map; p->value != AIPTEK_INVALID_VALUE; p++) | ||
393 | if (val == p->value) | ||
394 | return p->string; | ||
395 | |||
396 | return "unknown"; | ||
365 | } | 397 | } |
366 | 398 | ||
367 | /*********************************************************************** | 399 | /*********************************************************************** |
@@ -385,6 +417,9 @@ static int aiptek_convert_from_2s_complement(unsigned char c) | |||
385 | * Proximity. Why two events? I thought it interesting to know if the | 417 | * Proximity. Why two events? I thought it interesting to know if the |
386 | * Proximity event occurred while the tablet was in absolute or relative | 418 | * Proximity event occurred while the tablet was in absolute or relative |
387 | * mode. | 419 | * mode. |
420 | * Update: REL_MISC proved not to be such a good idea. With REL_MISC you | ||
421 | * get an event transmitted each time. ABS_MISC works better, since it | ||
422 | * can be set and re-set. Thus, only using ABS_MISC from now on. | ||
388 | * | 423 | * |
389 | * Other tablets use the notion of a certain minimum stylus pressure | 424 | * Other tablets use the notion of a certain minimum stylus pressure |
390 | * to infer proximity. While that could have been done, that is yet | 425 | * to infer proximity. While that could have been done, that is yet |
@@ -441,8 +476,8 @@ static void aiptek_irq(struct urb *urb) | |||
441 | aiptek->diagnostic = | 476 | aiptek->diagnostic = |
442 | AIPTEK_DIAGNOSTIC_SENDING_RELATIVE_IN_ABSOLUTE; | 477 | AIPTEK_DIAGNOSTIC_SENDING_RELATIVE_IN_ABSOLUTE; |
443 | } else { | 478 | } else { |
444 | x = aiptek_convert_from_2s_complement(data[2]); | 479 | x = (signed char) data[2]; |
445 | y = aiptek_convert_from_2s_complement(data[3]); | 480 | y = (signed char) data[3]; |
446 | 481 | ||
447 | /* jitterable keeps track of whether any button has been pressed. | 482 | /* jitterable keeps track of whether any button has been pressed. |
448 | * We're also using it to remap the physical mouse button mask | 483 | * We're also using it to remap the physical mouse button mask |
@@ -451,18 +486,20 @@ static void aiptek_irq(struct urb *urb) | |||
451 | * that a non-zero value indicates that one or more | 486 | * that a non-zero value indicates that one or more |
452 | * mouse button was pressed.) | 487 | * mouse button was pressed.) |
453 | */ | 488 | */ |
454 | jitterable = data[5] & 0x07; | 489 | jitterable = data[1] & 0x07; |
455 | 490 | ||
456 | left = (data[5] & aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0; | 491 | left = (data[1] & aiptek->curSetting.mouseButtonLeft >> 2) != 0 ? 1 : 0; |
457 | right = (data[5] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0; | 492 | right = (data[1] & aiptek->curSetting.mouseButtonRight >> 2) != 0 ? 1 : 0; |
458 | middle = (data[5] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0; | 493 | middle = (data[1] & aiptek->curSetting.mouseButtonMiddle >> 2) != 0 ? 1 : 0; |
459 | 494 | ||
460 | input_report_key(inputdev, BTN_LEFT, left); | 495 | input_report_key(inputdev, BTN_LEFT, left); |
461 | input_report_key(inputdev, BTN_MIDDLE, middle); | 496 | input_report_key(inputdev, BTN_MIDDLE, middle); |
462 | input_report_key(inputdev, BTN_RIGHT, right); | 497 | input_report_key(inputdev, BTN_RIGHT, right); |
498 | |||
499 | input_report_abs(inputdev, ABS_MISC, | ||
500 | 1 | AIPTEK_REPORT_TOOL_UNKNOWN); | ||
463 | input_report_rel(inputdev, REL_X, x); | 501 | input_report_rel(inputdev, REL_X, x); |
464 | input_report_rel(inputdev, REL_Y, y); | 502 | input_report_rel(inputdev, REL_Y, y); |
465 | input_report_rel(inputdev, REL_MISC, 1 | AIPTEK_REPORT_TOOL_UNKNOWN); | ||
466 | 503 | ||
467 | /* Wheel support is in the form of a single-event | 504 | /* Wheel support is in the form of a single-event |
468 | * firing. | 505 | * firing. |
@@ -472,6 +509,11 @@ static void aiptek_irq(struct urb *urb) | |||
472 | aiptek->curSetting.wheel); | 509 | aiptek->curSetting.wheel); |
473 | aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE; | 510 | aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE; |
474 | } | 511 | } |
512 | if (aiptek->lastMacro != -1) { | ||
513 | input_report_key(inputdev, | ||
514 | macroKeyEvents[aiptek->lastMacro], 0); | ||
515 | aiptek->lastMacro = -1; | ||
516 | } | ||
475 | input_sync(inputdev); | 517 | input_sync(inputdev); |
476 | } | 518 | } |
477 | } | 519 | } |
@@ -489,8 +531,8 @@ static void aiptek_irq(struct urb *urb) | |||
489 | y = le16_to_cpu(get_unaligned((__le16 *) (data + 3))); | 531 | y = le16_to_cpu(get_unaligned((__le16 *) (data + 3))); |
490 | z = le16_to_cpu(get_unaligned((__le16 *) (data + 6))); | 532 | z = le16_to_cpu(get_unaligned((__le16 *) (data + 6))); |
491 | 533 | ||
492 | p = (data[5] & 0x01) != 0 ? 1 : 0; | 534 | dv = (data[5] & 0x01) != 0 ? 1 : 0; |
493 | dv = (data[5] & 0x02) != 0 ? 1 : 0; | 535 | p = (data[5] & 0x02) != 0 ? 1 : 0; |
494 | tip = (data[5] & 0x04) != 0 ? 1 : 0; | 536 | tip = (data[5] & 0x04) != 0 ? 1 : 0; |
495 | 537 | ||
496 | /* Use jitterable to re-arrange button masks | 538 | /* Use jitterable to re-arrange button masks |
@@ -505,16 +547,18 @@ static void aiptek_irq(struct urb *urb) | |||
505 | * all 'bad' reports... | 547 | * all 'bad' reports... |
506 | */ | 548 | */ |
507 | if (dv != 0) { | 549 | if (dv != 0) { |
508 | /* If we've not already sent a tool_button_?? code, do | 550 | /* If the selected tool changed, reset the old |
509 | * so now. Then set FIRED_BIT so it won't be resent unless | 551 | * tool key, and set the new one. |
510 | * the user forces FIRED_BIT off. | ||
511 | */ | 552 | */ |
512 | if (TOOL_BUTTON_FIRED | 553 | if (aiptek->previousToolMode != |
513 | (aiptek->curSetting.toolMode) == 0) { | 554 | aiptek->curSetting.toolMode) { |
555 | input_report_key(inputdev, | ||
556 | aiptek->previousToolMode, 0); | ||
514 | input_report_key(inputdev, | 557 | input_report_key(inputdev, |
515 | TOOL_BUTTON(aiptek->curSetting.toolMode), | 558 | aiptek->curSetting.toolMode, |
516 | 1); | 559 | 1); |
517 | aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; | 560 | aiptek->previousToolMode = |
561 | aiptek->curSetting.toolMode; | ||
518 | } | 562 | } |
519 | 563 | ||
520 | if (p != 0) { | 564 | if (p != 0) { |
@@ -550,6 +594,11 @@ static void aiptek_irq(struct urb *urb) | |||
550 | } | 594 | } |
551 | } | 595 | } |
552 | input_report_abs(inputdev, ABS_MISC, p | AIPTEK_REPORT_TOOL_STYLUS); | 596 | input_report_abs(inputdev, ABS_MISC, p | AIPTEK_REPORT_TOOL_STYLUS); |
597 | if (aiptek->lastMacro != -1) { | ||
598 | input_report_key(inputdev, | ||
599 | macroKeyEvents[aiptek->lastMacro], 0); | ||
600 | aiptek->lastMacro = -1; | ||
601 | } | ||
553 | input_sync(inputdev); | 602 | input_sync(inputdev); |
554 | } | 603 | } |
555 | } | 604 | } |
@@ -568,23 +617,25 @@ static void aiptek_irq(struct urb *urb) | |||
568 | 617 | ||
569 | jitterable = data[5] & 0x1c; | 618 | jitterable = data[5] & 0x1c; |
570 | 619 | ||
571 | p = (data[5] & 0x01) != 0 ? 1 : 0; | 620 | dv = (data[5] & 0x01) != 0 ? 1 : 0; |
572 | dv = (data[5] & 0x02) != 0 ? 1 : 0; | 621 | p = (data[5] & 0x02) != 0 ? 1 : 0; |
573 | left = (data[5] & aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0; | 622 | left = (data[5] & aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0; |
574 | right = (data[5] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0; | 623 | right = (data[5] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0; |
575 | middle = (data[5] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0; | 624 | middle = (data[5] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0; |
576 | 625 | ||
577 | if (dv != 0) { | 626 | if (dv != 0) { |
578 | /* If we've not already sent a tool_button_?? code, do | 627 | /* If the selected tool changed, reset the old |
579 | * so now. Then set FIRED_BIT so it won't be resent unless | 628 | * tool key, and set the new one. |
580 | * the user forces FIRED_BIT off. | ||
581 | */ | 629 | */ |
582 | if (TOOL_BUTTON_FIRED | 630 | if (aiptek->previousToolMode != |
583 | (aiptek->curSetting.toolMode) == 0) { | 631 | aiptek->curSetting.toolMode) { |
632 | input_report_key(inputdev, | ||
633 | aiptek->previousToolMode, 0); | ||
584 | input_report_key(inputdev, | 634 | input_report_key(inputdev, |
585 | TOOL_BUTTON(aiptek->curSetting.toolMode), | 635 | aiptek->curSetting.toolMode, |
586 | 1); | 636 | 1); |
587 | aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; | 637 | aiptek->previousToolMode = |
638 | aiptek->curSetting.toolMode; | ||
588 | } | 639 | } |
589 | 640 | ||
590 | if (p != 0) { | 641 | if (p != 0) { |
@@ -605,7 +656,12 @@ static void aiptek_irq(struct urb *urb) | |||
605 | aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE; | 656 | aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE; |
606 | } | 657 | } |
607 | } | 658 | } |
608 | input_report_rel(inputdev, REL_MISC, p | AIPTEK_REPORT_TOOL_MOUSE); | 659 | input_report_abs(inputdev, ABS_MISC, p | AIPTEK_REPORT_TOOL_MOUSE); |
660 | if (aiptek->lastMacro != -1) { | ||
661 | input_report_key(inputdev, | ||
662 | macroKeyEvents[aiptek->lastMacro], 0); | ||
663 | aiptek->lastMacro = -1; | ||
664 | } | ||
609 | input_sync(inputdev); | 665 | input_sync(inputdev); |
610 | } | 666 | } |
611 | } | 667 | } |
@@ -615,98 +671,83 @@ static void aiptek_irq(struct urb *urb) | |||
615 | else if (data[0] == 4) { | 671 | else if (data[0] == 4) { |
616 | jitterable = data[1] & 0x18; | 672 | jitterable = data[1] & 0x18; |
617 | 673 | ||
618 | p = (data[1] & 0x01) != 0 ? 1 : 0; | 674 | dv = (data[1] & 0x01) != 0 ? 1 : 0; |
619 | dv = (data[1] & 0x02) != 0 ? 1 : 0; | 675 | p = (data[1] & 0x02) != 0 ? 1 : 0; |
620 | tip = (data[1] & 0x04) != 0 ? 1 : 0; | 676 | tip = (data[1] & 0x04) != 0 ? 1 : 0; |
621 | bs = (data[1] & aiptek->curSetting.stylusButtonLower) != 0 ? 1 : 0; | 677 | bs = (data[1] & aiptek->curSetting.stylusButtonLower) != 0 ? 1 : 0; |
622 | pck = (data[1] & aiptek->curSetting.stylusButtonUpper) != 0 ? 1 : 0; | 678 | pck = (data[1] & aiptek->curSetting.stylusButtonUpper) != 0 ? 1 : 0; |
623 | 679 | ||
624 | macro = data[3]; | 680 | macro = dv && p && tip && !(data[3] & 1) ? (data[3] >> 1) : -1; |
625 | z = le16_to_cpu(get_unaligned((__le16 *) (data + 4))); | 681 | z = le16_to_cpu(get_unaligned((__le16 *) (data + 4))); |
626 | 682 | ||
627 | if (dv != 0) { | 683 | if (dv) { |
628 | /* If we've not already sent a tool_button_?? code, do | 684 | /* If the selected tool changed, reset the old |
629 | * so now. Then set FIRED_BIT so it won't be resent unless | 685 | * tool key, and set the new one. |
630 | * the user forces FIRED_BIT off. | ||
631 | */ | 686 | */ |
632 | if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) { | 687 | if (aiptek->previousToolMode != |
688 | aiptek->curSetting.toolMode) { | ||
689 | input_report_key(inputdev, | ||
690 | aiptek->previousToolMode, 0); | ||
633 | input_report_key(inputdev, | 691 | input_report_key(inputdev, |
634 | TOOL_BUTTON(aiptek->curSetting.toolMode), | 692 | aiptek->curSetting.toolMode, |
635 | 1); | 693 | 1); |
636 | aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; | 694 | aiptek->previousToolMode = |
695 | aiptek->curSetting.toolMode; | ||
637 | } | 696 | } |
697 | } | ||
638 | 698 | ||
639 | if (p != 0) { | 699 | if (aiptek->lastMacro != -1 && aiptek->lastMacro != macro) { |
640 | input_report_key(inputdev, BTN_TOUCH, tip); | 700 | input_report_key(inputdev, macroKeyEvents[aiptek->lastMacro], 0); |
641 | input_report_key(inputdev, BTN_STYLUS, bs); | 701 | aiptek->lastMacro = -1; |
642 | input_report_key(inputdev, BTN_STYLUS2, pck); | 702 | } |
643 | input_report_abs(inputdev, ABS_PRESSURE, z); | ||
644 | } | ||
645 | 703 | ||
646 | /* For safety, we're sending key 'break' codes for the | 704 | if (macro != -1 && macro != aiptek->lastMacro) { |
647 | * neighboring macro keys. | 705 | input_report_key(inputdev, macroKeyEvents[macro], 1); |
648 | */ | 706 | aiptek->lastMacro = macro; |
649 | if (macro > 0) { | ||
650 | input_report_key(inputdev, | ||
651 | macroKeyEvents[macro - 1], 0); | ||
652 | } | ||
653 | if (macro < 25) { | ||
654 | input_report_key(inputdev, | ||
655 | macroKeyEvents[macro + 1], 0); | ||
656 | } | ||
657 | input_report_key(inputdev, macroKeyEvents[macro], p); | ||
658 | input_report_abs(inputdev, ABS_MISC, | ||
659 | p | AIPTEK_REPORT_TOOL_STYLUS); | ||
660 | input_sync(inputdev); | ||
661 | } | 707 | } |
708 | input_report_abs(inputdev, ABS_MISC, | ||
709 | p | AIPTEK_REPORT_TOOL_STYLUS); | ||
710 | input_sync(inputdev); | ||
662 | } | 711 | } |
663 | /* Report 5s come from the macro keys when pressed by mouse | 712 | /* Report 5s come from the macro keys when pressed by mouse |
664 | */ | 713 | */ |
665 | else if (data[0] == 5) { | 714 | else if (data[0] == 5) { |
666 | jitterable = data[1] & 0x1c; | 715 | jitterable = data[1] & 0x1c; |
667 | 716 | ||
668 | p = (data[1] & 0x01) != 0 ? 1 : 0; | 717 | dv = (data[1] & 0x01) != 0 ? 1 : 0; |
669 | dv = (data[1] & 0x02) != 0 ? 1 : 0; | 718 | p = (data[1] & 0x02) != 0 ? 1 : 0; |
670 | left = (data[1]& aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0; | 719 | left = (data[1]& aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0; |
671 | right = (data[1] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0; | 720 | right = (data[1] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0; |
672 | middle = (data[1] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0; | 721 | middle = (data[1] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0; |
673 | macro = data[3]; | 722 | macro = dv && p && left && !(data[3] & 1) ? (data[3] >> 1) : 0; |
674 | 723 | ||
675 | if (dv != 0) { | 724 | if (dv) { |
676 | /* If we've not already sent a tool_button_?? code, do | 725 | /* If the selected tool changed, reset the old |
677 | * so now. Then set FIRED_BIT so it won't be resent unless | 726 | * tool key, and set the new one. |
678 | * the user forces FIRED_BIT off. | ||
679 | */ | 727 | */ |
680 | if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) { | 728 | if (aiptek->previousToolMode != |
681 | input_report_key(inputdev, | 729 | aiptek->curSetting.toolMode) { |
682 | TOOL_BUTTON(aiptek->curSetting.toolMode), | 730 | input_report_key(inputdev, |
683 | 1); | 731 | aiptek->previousToolMode, 0); |
684 | aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; | 732 | input_report_key(inputdev, |
685 | } | 733 | aiptek->curSetting.toolMode, 1); |
686 | 734 | aiptek->previousToolMode = aiptek->curSetting.toolMode; | |
687 | if (p != 0) { | ||
688 | input_report_key(inputdev, BTN_LEFT, left); | ||
689 | input_report_key(inputdev, BTN_MIDDLE, middle); | ||
690 | input_report_key(inputdev, BTN_RIGHT, right); | ||
691 | } | 735 | } |
736 | } | ||
692 | 737 | ||
693 | /* For safety, we're sending key 'break' codes for the | 738 | if (aiptek->lastMacro != -1 && aiptek->lastMacro != macro) { |
694 | * neighboring macro keys. | 739 | input_report_key(inputdev, macroKeyEvents[aiptek->lastMacro], 0); |
695 | */ | 740 | aiptek->lastMacro = -1; |
696 | if (macro > 0) { | 741 | } |
697 | input_report_key(inputdev, | ||
698 | macroKeyEvents[macro - 1], 0); | ||
699 | } | ||
700 | if (macro < 25) { | ||
701 | input_report_key(inputdev, | ||
702 | macroKeyEvents[macro + 1], 0); | ||
703 | } | ||
704 | 742 | ||
743 | if (macro != -1 && macro != aiptek->lastMacro) { | ||
705 | input_report_key(inputdev, macroKeyEvents[macro], 1); | 744 | input_report_key(inputdev, macroKeyEvents[macro], 1); |
706 | input_report_rel(inputdev, ABS_MISC, | 745 | aiptek->lastMacro = macro; |
707 | p | AIPTEK_REPORT_TOOL_MOUSE); | ||
708 | input_sync(inputdev); | ||
709 | } | 746 | } |
747 | |||
748 | input_report_abs(inputdev, ABS_MISC, | ||
749 | p | AIPTEK_REPORT_TOOL_MOUSE); | ||
750 | input_sync(inputdev); | ||
710 | } | 751 | } |
711 | /* We have no idea which tool can generate a report 6. Theoretically, | 752 | /* We have no idea which tool can generate a report 6. Theoretically, |
712 | * neither need to, having been given reports 4 & 5 for such use. | 753 | * neither need to, having been given reports 4 & 5 for such use. |
@@ -725,15 +766,18 @@ static void aiptek_irq(struct urb *urb) | |||
725 | 0); | 766 | 0); |
726 | } | 767 | } |
727 | 768 | ||
728 | /* If we've not already sent a tool_button_?? code, do | 769 | /* If the selected tool changed, reset the old |
729 | * so now. Then set FIRED_BIT so it won't be resent unless | 770 | tool key, and set the new one. |
730 | * the user forces FIRED_BIT off. | 771 | */ |
731 | */ | 772 | if (aiptek->previousToolMode != |
732 | if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) { | 773 | aiptek->curSetting.toolMode) { |
774 | input_report_key(inputdev, | ||
775 | aiptek->previousToolMode, 0); | ||
733 | input_report_key(inputdev, | 776 | input_report_key(inputdev, |
734 | TOOL_BUTTON(aiptek->curSetting. | 777 | aiptek->curSetting.toolMode, |
735 | toolMode), 1); | 778 | 1); |
736 | aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; | 779 | aiptek->previousToolMode = |
780 | aiptek->curSetting.toolMode; | ||
737 | } | 781 | } |
738 | 782 | ||
739 | input_report_key(inputdev, macroKeyEvents[macro], 1); | 783 | input_report_key(inputdev, macroKeyEvents[macro], 1); |
@@ -1007,9 +1051,6 @@ static ssize_t show_tabletSize(struct device *dev, struct device_attribute *attr | |||
1007 | { | 1051 | { |
1008 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1052 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1009 | 1053 | ||
1010 | if (aiptek == NULL) | ||
1011 | return 0; | ||
1012 | |||
1013 | return snprintf(buf, PAGE_SIZE, "%dx%d\n", | 1054 | return snprintf(buf, PAGE_SIZE, "%dx%d\n", |
1014 | aiptek->inputdev->absmax[ABS_X] + 1, | 1055 | aiptek->inputdev->absmax[ABS_X] + 1, |
1015 | aiptek->inputdev->absmax[ABS_Y] + 1); | 1056 | aiptek->inputdev->absmax[ABS_Y] + 1); |
@@ -1024,117 +1065,35 @@ static ssize_t show_tabletSize(struct device *dev, struct device_attribute *attr | |||
1024 | static DEVICE_ATTR(size, S_IRUGO, show_tabletSize, NULL); | 1065 | static DEVICE_ATTR(size, S_IRUGO, show_tabletSize, NULL); |
1025 | 1066 | ||
1026 | /*********************************************************************** | 1067 | /*********************************************************************** |
1027 | * support routines for the 'product_id' file | ||
1028 | */ | ||
1029 | static ssize_t show_tabletProductId(struct device *dev, struct device_attribute *attr, char *buf) | ||
1030 | { | ||
1031 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1032 | |||
1033 | if (aiptek == NULL) | ||
1034 | return 0; | ||
1035 | |||
1036 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", | ||
1037 | aiptek->inputdev->id.product); | ||
1038 | } | ||
1039 | |||
1040 | static DEVICE_ATTR(product_id, S_IRUGO, show_tabletProductId, NULL); | ||
1041 | |||
1042 | /*********************************************************************** | ||
1043 | * support routines for the 'vendor_id' file | ||
1044 | */ | ||
1045 | static ssize_t show_tabletVendorId(struct device *dev, struct device_attribute *attr, char *buf) | ||
1046 | { | ||
1047 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1048 | |||
1049 | if (aiptek == NULL) | ||
1050 | return 0; | ||
1051 | |||
1052 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->inputdev->id.vendor); | ||
1053 | } | ||
1054 | |||
1055 | static DEVICE_ATTR(vendor_id, S_IRUGO, show_tabletVendorId, NULL); | ||
1056 | |||
1057 | /*********************************************************************** | ||
1058 | * support routines for the 'vendor' file | ||
1059 | */ | ||
1060 | static ssize_t show_tabletManufacturer(struct device *dev, struct device_attribute *attr, char *buf) | ||
1061 | { | ||
1062 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1063 | int retval; | ||
1064 | |||
1065 | if (aiptek == NULL) | ||
1066 | return 0; | ||
1067 | |||
1068 | retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->manufacturer); | ||
1069 | return retval; | ||
1070 | } | ||
1071 | |||
1072 | static DEVICE_ATTR(vendor, S_IRUGO, show_tabletManufacturer, NULL); | ||
1073 | |||
1074 | /*********************************************************************** | ||
1075 | * support routines for the 'product' file | ||
1076 | */ | ||
1077 | static ssize_t show_tabletProduct(struct device *dev, struct device_attribute *attr, char *buf) | ||
1078 | { | ||
1079 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1080 | int retval; | ||
1081 | |||
1082 | if (aiptek == NULL) | ||
1083 | return 0; | ||
1084 | |||
1085 | retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->product); | ||
1086 | return retval; | ||
1087 | } | ||
1088 | |||
1089 | static DEVICE_ATTR(product, S_IRUGO, show_tabletProduct, NULL); | ||
1090 | |||
1091 | /*********************************************************************** | ||
1092 | * support routines for the 'pointer_mode' file. Note that this file | 1068 | * support routines for the 'pointer_mode' file. Note that this file |
1093 | * both displays current setting and allows reprogramming. | 1069 | * both displays current setting and allows reprogramming. |
1094 | */ | 1070 | */ |
1071 | static struct aiptek_map pointer_mode_map[] = { | ||
1072 | { "stylus", AIPTEK_POINTER_ONLY_STYLUS_MODE }, | ||
1073 | { "mouse", AIPTEK_POINTER_ONLY_MOUSE_MODE }, | ||
1074 | { "either", AIPTEK_POINTER_EITHER_MODE }, | ||
1075 | { NULL, AIPTEK_INVALID_VALUE } | ||
1076 | }; | ||
1077 | |||
1095 | static ssize_t show_tabletPointerMode(struct device *dev, struct device_attribute *attr, char *buf) | 1078 | static ssize_t show_tabletPointerMode(struct device *dev, struct device_attribute *attr, char *buf) |
1096 | { | 1079 | { |
1097 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1080 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1098 | char *s; | ||
1099 | |||
1100 | if (aiptek == NULL) | ||
1101 | return 0; | ||
1102 | |||
1103 | switch (aiptek->curSetting.pointerMode) { | ||
1104 | case AIPTEK_POINTER_ONLY_STYLUS_MODE: | ||
1105 | s = "stylus"; | ||
1106 | break; | ||
1107 | |||
1108 | case AIPTEK_POINTER_ONLY_MOUSE_MODE: | ||
1109 | s = "mouse"; | ||
1110 | break; | ||
1111 | |||
1112 | case AIPTEK_POINTER_EITHER_MODE: | ||
1113 | s = "either"; | ||
1114 | break; | ||
1115 | 1081 | ||
1116 | default: | 1082 | return snprintf(buf, PAGE_SIZE, "%s\n", |
1117 | s = "unknown"; | 1083 | map_val_to_str(pointer_mode_map, |
1118 | break; | 1084 | aiptek->curSetting.pointerMode)); |
1119 | } | ||
1120 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1121 | } | 1085 | } |
1122 | 1086 | ||
1123 | static ssize_t | 1087 | static ssize_t |
1124 | store_tabletPointerMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1088 | store_tabletPointerMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1125 | { | 1089 | { |
1126 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1090 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1127 | if (aiptek == NULL) | 1091 | int new_mode = map_str_to_val(pointer_mode_map, buf, count); |
1128 | return 0; | ||
1129 | 1092 | ||
1130 | if (strcmp(buf, "stylus") == 0) { | 1093 | if (new_mode == AIPTEK_INVALID_VALUE) |
1131 | aiptek->newSetting.pointerMode = | 1094 | return -EINVAL; |
1132 | AIPTEK_POINTER_ONLY_STYLUS_MODE; | 1095 | |
1133 | } else if (strcmp(buf, "mouse") == 0) { | 1096 | aiptek->newSetting.pointerMode = new_mode; |
1134 | aiptek->newSetting.pointerMode = AIPTEK_POINTER_ONLY_MOUSE_MODE; | ||
1135 | } else if (strcmp(buf, "either") == 0) { | ||
1136 | aiptek->newSetting.pointerMode = AIPTEK_POINTER_EITHER_MODE; | ||
1137 | } | ||
1138 | return count; | 1097 | return count; |
1139 | } | 1098 | } |
1140 | 1099 | ||
@@ -1146,44 +1105,32 @@ static DEVICE_ATTR(pointer_mode, | |||
1146 | * support routines for the 'coordinate_mode' file. Note that this file | 1105 | * support routines for the 'coordinate_mode' file. Note that this file |
1147 | * both displays current setting and allows reprogramming. | 1106 | * both displays current setting and allows reprogramming. |
1148 | */ | 1107 | */ |
1108 | |||
1109 | static struct aiptek_map coordinate_mode_map[] = { | ||
1110 | { "absolute", AIPTEK_COORDINATE_ABSOLUTE_MODE }, | ||
1111 | { "relative", AIPTEK_COORDINATE_RELATIVE_MODE }, | ||
1112 | { NULL, AIPTEK_INVALID_VALUE } | ||
1113 | }; | ||
1114 | |||
1149 | static ssize_t show_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, char *buf) | 1115 | static ssize_t show_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, char *buf) |
1150 | { | 1116 | { |
1151 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1117 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1152 | char *s; | ||
1153 | 1118 | ||
1154 | if (aiptek == NULL) | 1119 | return snprintf(buf, PAGE_SIZE, "%s\n", |
1155 | return 0; | 1120 | map_val_to_str(coordinate_mode_map, |
1156 | 1121 | aiptek->curSetting.coordinateMode)); | |
1157 | switch (aiptek->curSetting.coordinateMode) { | ||
1158 | case AIPTEK_COORDINATE_ABSOLUTE_MODE: | ||
1159 | s = "absolute"; | ||
1160 | break; | ||
1161 | |||
1162 | case AIPTEK_COORDINATE_RELATIVE_MODE: | ||
1163 | s = "relative"; | ||
1164 | break; | ||
1165 | |||
1166 | default: | ||
1167 | s = "unknown"; | ||
1168 | break; | ||
1169 | } | ||
1170 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1171 | } | 1122 | } |
1172 | 1123 | ||
1173 | static ssize_t | 1124 | static ssize_t |
1174 | store_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1125 | store_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1175 | { | 1126 | { |
1176 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1127 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1177 | if (aiptek == NULL) | 1128 | int new_mode = map_str_to_val(coordinate_mode_map, buf, count); |
1178 | return 0; | ||
1179 | 1129 | ||
1180 | if (strcmp(buf, "absolute") == 0) { | 1130 | if (new_mode == AIPTEK_INVALID_VALUE) |
1181 | aiptek->newSetting.pointerMode = | 1131 | return -EINVAL; |
1182 | AIPTEK_COORDINATE_ABSOLUTE_MODE; | 1132 | |
1183 | } else if (strcmp(buf, "relative") == 0) { | 1133 | aiptek->newSetting.coordinateMode = new_mode; |
1184 | aiptek->newSetting.pointerMode = | ||
1185 | AIPTEK_COORDINATE_RELATIVE_MODE; | ||
1186 | } | ||
1187 | return count; | 1134 | return count; |
1188 | } | 1135 | } |
1189 | 1136 | ||
@@ -1195,73 +1142,37 @@ static DEVICE_ATTR(coordinate_mode, | |||
1195 | * support routines for the 'tool_mode' file. Note that this file | 1142 | * support routines for the 'tool_mode' file. Note that this file |
1196 | * both displays current setting and allows reprogramming. | 1143 | * both displays current setting and allows reprogramming. |
1197 | */ | 1144 | */ |
1145 | |||
1146 | static struct aiptek_map tool_mode_map[] = { | ||
1147 | { "mouse", AIPTEK_TOOL_BUTTON_MOUSE_MODE }, | ||
1148 | { "eraser", AIPTEK_TOOL_BUTTON_ERASER_MODE }, | ||
1149 | { "pencil", AIPTEK_TOOL_BUTTON_PENCIL_MODE }, | ||
1150 | { "pen", AIPTEK_TOOL_BUTTON_PEN_MODE }, | ||
1151 | { "brush", AIPTEK_TOOL_BUTTON_BRUSH_MODE }, | ||
1152 | { "airbrush", AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE }, | ||
1153 | { "lens", AIPTEK_TOOL_BUTTON_LENS_MODE }, | ||
1154 | { NULL, AIPTEK_INVALID_VALUE } | ||
1155 | }; | ||
1156 | |||
1198 | static ssize_t show_tabletToolMode(struct device *dev, struct device_attribute *attr, char *buf) | 1157 | static ssize_t show_tabletToolMode(struct device *dev, struct device_attribute *attr, char *buf) |
1199 | { | 1158 | { |
1200 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1159 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1201 | char *s; | ||
1202 | |||
1203 | if (aiptek == NULL) | ||
1204 | return 0; | ||
1205 | |||
1206 | switch (TOOL_BUTTON(aiptek->curSetting.toolMode)) { | ||
1207 | case AIPTEK_TOOL_BUTTON_MOUSE_MODE: | ||
1208 | s = "mouse"; | ||
1209 | break; | ||
1210 | |||
1211 | case AIPTEK_TOOL_BUTTON_ERASER_MODE: | ||
1212 | s = "eraser"; | ||
1213 | break; | ||
1214 | |||
1215 | case AIPTEK_TOOL_BUTTON_PENCIL_MODE: | ||
1216 | s = "pencil"; | ||
1217 | break; | ||
1218 | |||
1219 | case AIPTEK_TOOL_BUTTON_PEN_MODE: | ||
1220 | s = "pen"; | ||
1221 | break; | ||
1222 | |||
1223 | case AIPTEK_TOOL_BUTTON_BRUSH_MODE: | ||
1224 | s = "brush"; | ||
1225 | break; | ||
1226 | |||
1227 | case AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE: | ||
1228 | s = "airbrush"; | ||
1229 | break; | ||
1230 | |||
1231 | case AIPTEK_TOOL_BUTTON_LENS_MODE: | ||
1232 | s = "lens"; | ||
1233 | break; | ||
1234 | 1160 | ||
1235 | default: | 1161 | return snprintf(buf, PAGE_SIZE, "%s\n", |
1236 | s = "unknown"; | 1162 | map_val_to_str(tool_mode_map, |
1237 | break; | 1163 | aiptek->curSetting.toolMode)); |
1238 | } | ||
1239 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1240 | } | 1164 | } |
1241 | 1165 | ||
1242 | static ssize_t | 1166 | static ssize_t |
1243 | store_tabletToolMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1167 | store_tabletToolMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1244 | { | 1168 | { |
1245 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1169 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1246 | if (aiptek == NULL) | 1170 | int new_mode = map_str_to_val(tool_mode_map, buf, count); |
1247 | return 0; | ||
1248 | 1171 | ||
1249 | if (strcmp(buf, "mouse") == 0) { | 1172 | if (new_mode == AIPTEK_INVALID_VALUE) |
1250 | aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_MOUSE_MODE; | 1173 | return -EINVAL; |
1251 | } else if (strcmp(buf, "eraser") == 0) { | ||
1252 | aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_ERASER_MODE; | ||
1253 | } else if (strcmp(buf, "pencil") == 0) { | ||
1254 | aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_PENCIL_MODE; | ||
1255 | } else if (strcmp(buf, "pen") == 0) { | ||
1256 | aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_PEN_MODE; | ||
1257 | } else if (strcmp(buf, "brush") == 0) { | ||
1258 | aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_BRUSH_MODE; | ||
1259 | } else if (strcmp(buf, "airbrush") == 0) { | ||
1260 | aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE; | ||
1261 | } else if (strcmp(buf, "lens") == 0) { | ||
1262 | aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_LENS_MODE; | ||
1263 | } | ||
1264 | 1174 | ||
1175 | aiptek->newSetting.toolMode = new_mode; | ||
1265 | return count; | 1176 | return count; |
1266 | } | 1177 | } |
1267 | 1178 | ||
@@ -1277,9 +1188,6 @@ static ssize_t show_tabletXtilt(struct device *dev, struct device_attribute *att | |||
1277 | { | 1188 | { |
1278 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1189 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1279 | 1190 | ||
1280 | if (aiptek == NULL) | ||
1281 | return 0; | ||
1282 | |||
1283 | if (aiptek->curSetting.xTilt == AIPTEK_TILT_DISABLE) { | 1191 | if (aiptek->curSetting.xTilt == AIPTEK_TILT_DISABLE) { |
1284 | return snprintf(buf, PAGE_SIZE, "disable\n"); | 1192 | return snprintf(buf, PAGE_SIZE, "disable\n"); |
1285 | } else { | 1193 | } else { |
@@ -1294,9 +1202,6 @@ store_tabletXtilt(struct device *dev, struct device_attribute *attr, const char | |||
1294 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1202 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1295 | int x; | 1203 | int x; |
1296 | 1204 | ||
1297 | if (aiptek == NULL) | ||
1298 | return 0; | ||
1299 | |||
1300 | if (strcmp(buf, "disable") == 0) { | 1205 | if (strcmp(buf, "disable") == 0) { |
1301 | aiptek->newSetting.xTilt = AIPTEK_TILT_DISABLE; | 1206 | aiptek->newSetting.xTilt = AIPTEK_TILT_DISABLE; |
1302 | } else { | 1207 | } else { |
@@ -1319,9 +1224,6 @@ static ssize_t show_tabletYtilt(struct device *dev, struct device_attribute *att | |||
1319 | { | 1224 | { |
1320 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1225 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1321 | 1226 | ||
1322 | if (aiptek == NULL) | ||
1323 | return 0; | ||
1324 | |||
1325 | if (aiptek->curSetting.yTilt == AIPTEK_TILT_DISABLE) { | 1227 | if (aiptek->curSetting.yTilt == AIPTEK_TILT_DISABLE) { |
1326 | return snprintf(buf, PAGE_SIZE, "disable\n"); | 1228 | return snprintf(buf, PAGE_SIZE, "disable\n"); |
1327 | } else { | 1229 | } else { |
@@ -1336,9 +1238,6 @@ store_tabletYtilt(struct device *dev, struct device_attribute *attr, const char | |||
1336 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1238 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1337 | int y; | 1239 | int y; |
1338 | 1240 | ||
1339 | if (aiptek == NULL) | ||
1340 | return 0; | ||
1341 | |||
1342 | if (strcmp(buf, "disable") == 0) { | 1241 | if (strcmp(buf, "disable") == 0) { |
1343 | aiptek->newSetting.yTilt = AIPTEK_TILT_DISABLE; | 1242 | aiptek->newSetting.yTilt = AIPTEK_TILT_DISABLE; |
1344 | } else { | 1243 | } else { |
@@ -1361,9 +1260,6 @@ static ssize_t show_tabletJitterDelay(struct device *dev, struct device_attribut | |||
1361 | { | 1260 | { |
1362 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1261 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1363 | 1262 | ||
1364 | if (aiptek == NULL) | ||
1365 | return 0; | ||
1366 | |||
1367 | return snprintf(buf, PAGE_SIZE, "%d\n", aiptek->curSetting.jitterDelay); | 1263 | return snprintf(buf, PAGE_SIZE, "%d\n", aiptek->curSetting.jitterDelay); |
1368 | } | 1264 | } |
1369 | 1265 | ||
@@ -1372,9 +1268,6 @@ store_tabletJitterDelay(struct device *dev, struct device_attribute *attr, const | |||
1372 | { | 1268 | { |
1373 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1269 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1374 | 1270 | ||
1375 | if (aiptek == NULL) | ||
1376 | return 0; | ||
1377 | |||
1378 | aiptek->newSetting.jitterDelay = (int)simple_strtol(buf, NULL, 10); | 1271 | aiptek->newSetting.jitterDelay = (int)simple_strtol(buf, NULL, 10); |
1379 | return count; | 1272 | return count; |
1380 | } | 1273 | } |
@@ -1391,9 +1284,6 @@ static ssize_t show_tabletProgrammableDelay(struct device *dev, struct device_at | |||
1391 | { | 1284 | { |
1392 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1285 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1393 | 1286 | ||
1394 | if (aiptek == NULL) | ||
1395 | return 0; | ||
1396 | |||
1397 | return snprintf(buf, PAGE_SIZE, "%d\n", | 1287 | return snprintf(buf, PAGE_SIZE, "%d\n", |
1398 | aiptek->curSetting.programmableDelay); | 1288 | aiptek->curSetting.programmableDelay); |
1399 | } | 1289 | } |
@@ -1403,9 +1293,6 @@ store_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr, | |||
1403 | { | 1293 | { |
1404 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1294 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1405 | 1295 | ||
1406 | if (aiptek == NULL) | ||
1407 | return 0; | ||
1408 | |||
1409 | aiptek->newSetting.programmableDelay = (int)simple_strtol(buf, NULL, 10); | 1296 | aiptek->newSetting.programmableDelay = (int)simple_strtol(buf, NULL, 10); |
1410 | return count; | 1297 | return count; |
1411 | } | 1298 | } |
@@ -1415,23 +1302,6 @@ static DEVICE_ATTR(delay, | |||
1415 | show_tabletProgrammableDelay, store_tabletProgrammableDelay); | 1302 | show_tabletProgrammableDelay, store_tabletProgrammableDelay); |
1416 | 1303 | ||
1417 | /*********************************************************************** | 1304 | /*********************************************************************** |
1418 | * support routines for the 'input_path' file. Note that this file | ||
1419 | * only displays current setting. | ||
1420 | */ | ||
1421 | static ssize_t show_tabletInputDevice(struct device *dev, struct device_attribute *attr, char *buf) | ||
1422 | { | ||
1423 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1424 | |||
1425 | if (aiptek == NULL) | ||
1426 | return 0; | ||
1427 | |||
1428 | return snprintf(buf, PAGE_SIZE, "/dev/input/%s\n", | ||
1429 | aiptek->features.inputPath); | ||
1430 | } | ||
1431 | |||
1432 | static DEVICE_ATTR(input_path, S_IRUGO, show_tabletInputDevice, NULL); | ||
1433 | |||
1434 | /*********************************************************************** | ||
1435 | * support routines for the 'event_count' file. Note that this file | 1305 | * support routines for the 'event_count' file. Note that this file |
1436 | * only displays current setting. | 1306 | * only displays current setting. |
1437 | */ | 1307 | */ |
@@ -1439,9 +1309,6 @@ static ssize_t show_tabletEventsReceived(struct device *dev, struct device_attri | |||
1439 | { | 1309 | { |
1440 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1310 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1441 | 1311 | ||
1442 | if (aiptek == NULL) | ||
1443 | return 0; | ||
1444 | |||
1445 | return snprintf(buf, PAGE_SIZE, "%ld\n", aiptek->eventCount); | 1312 | return snprintf(buf, PAGE_SIZE, "%ld\n", aiptek->eventCount); |
1446 | } | 1313 | } |
1447 | 1314 | ||
@@ -1456,9 +1323,6 @@ static ssize_t show_tabletDiagnosticMessage(struct device *dev, struct device_at | |||
1456 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1323 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1457 | char *retMsg; | 1324 | char *retMsg; |
1458 | 1325 | ||
1459 | if (aiptek == NULL) | ||
1460 | return 0; | ||
1461 | |||
1462 | switch (aiptek->diagnostic) { | 1326 | switch (aiptek->diagnostic) { |
1463 | case AIPTEK_DIAGNOSTIC_NA: | 1327 | case AIPTEK_DIAGNOSTIC_NA: |
1464 | retMsg = "no errors\n"; | 1328 | retMsg = "no errors\n"; |
@@ -1493,45 +1357,32 @@ static DEVICE_ATTR(diagnostic, S_IRUGO, show_tabletDiagnosticMessage, NULL); | |||
1493 | * support routines for the 'stylus_upper' file. Note that this file | 1357 | * support routines for the 'stylus_upper' file. Note that this file |
1494 | * both displays current setting and allows for setting changing. | 1358 | * both displays current setting and allows for setting changing. |
1495 | */ | 1359 | */ |
1360 | |||
1361 | static struct aiptek_map stylus_button_map[] = { | ||
1362 | { "upper", AIPTEK_STYLUS_UPPER_BUTTON }, | ||
1363 | { "lower", AIPTEK_STYLUS_LOWER_BUTTON }, | ||
1364 | { NULL, AIPTEK_INVALID_VALUE } | ||
1365 | }; | ||
1366 | |||
1496 | static ssize_t show_tabletStylusUpper(struct device *dev, struct device_attribute *attr, char *buf) | 1367 | static ssize_t show_tabletStylusUpper(struct device *dev, struct device_attribute *attr, char *buf) |
1497 | { | 1368 | { |
1498 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1369 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1499 | char *s; | ||
1500 | |||
1501 | if (aiptek == NULL) | ||
1502 | return 0; | ||
1503 | |||
1504 | switch (aiptek->curSetting.stylusButtonUpper) { | ||
1505 | case AIPTEK_STYLUS_UPPER_BUTTON: | ||
1506 | s = "upper"; | ||
1507 | break; | ||
1508 | |||
1509 | case AIPTEK_STYLUS_LOWER_BUTTON: | ||
1510 | s = "lower"; | ||
1511 | break; | ||
1512 | 1370 | ||
1513 | default: | 1371 | return snprintf(buf, PAGE_SIZE, "%s\n", |
1514 | s = "unknown"; | 1372 | map_val_to_str(stylus_button_map, |
1515 | break; | 1373 | aiptek->curSetting.stylusButtonUpper)); |
1516 | } | ||
1517 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1518 | } | 1374 | } |
1519 | 1375 | ||
1520 | static ssize_t | 1376 | static ssize_t |
1521 | store_tabletStylusUpper(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1377 | store_tabletStylusUpper(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1522 | { | 1378 | { |
1523 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1379 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1380 | int new_button = map_str_to_val(stylus_button_map, buf, count); | ||
1524 | 1381 | ||
1525 | if (aiptek == NULL) | 1382 | if (new_button == AIPTEK_INVALID_VALUE) |
1526 | return 0; | 1383 | return -EINVAL; |
1527 | 1384 | ||
1528 | if (strcmp(buf, "upper") == 0) { | 1385 | aiptek->newSetting.stylusButtonUpper = new_button; |
1529 | aiptek->newSetting.stylusButtonUpper = | ||
1530 | AIPTEK_STYLUS_UPPER_BUTTON; | ||
1531 | } else if (strcmp(buf, "lower") == 0) { | ||
1532 | aiptek->newSetting.stylusButtonUpper = | ||
1533 | AIPTEK_STYLUS_LOWER_BUTTON; | ||
1534 | } | ||
1535 | return count; | 1386 | return count; |
1536 | } | 1387 | } |
1537 | 1388 | ||
@@ -1543,45 +1394,26 @@ static DEVICE_ATTR(stylus_upper, | |||
1543 | * support routines for the 'stylus_lower' file. Note that this file | 1394 | * support routines for the 'stylus_lower' file. Note that this file |
1544 | * both displays current setting and allows for setting changing. | 1395 | * both displays current setting and allows for setting changing. |
1545 | */ | 1396 | */ |
1397 | |||
1546 | static ssize_t show_tabletStylusLower(struct device *dev, struct device_attribute *attr, char *buf) | 1398 | static ssize_t show_tabletStylusLower(struct device *dev, struct device_attribute *attr, char *buf) |
1547 | { | 1399 | { |
1548 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1400 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1549 | char *s; | ||
1550 | |||
1551 | if (aiptek == NULL) | ||
1552 | return 0; | ||
1553 | |||
1554 | switch (aiptek->curSetting.stylusButtonLower) { | ||
1555 | case AIPTEK_STYLUS_UPPER_BUTTON: | ||
1556 | s = "upper"; | ||
1557 | break; | ||
1558 | |||
1559 | case AIPTEK_STYLUS_LOWER_BUTTON: | ||
1560 | s = "lower"; | ||
1561 | break; | ||
1562 | 1401 | ||
1563 | default: | 1402 | return snprintf(buf, PAGE_SIZE, "%s\n", |
1564 | s = "unknown"; | 1403 | map_val_to_str(stylus_button_map, |
1565 | break; | 1404 | aiptek->curSetting.stylusButtonLower)); |
1566 | } | ||
1567 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1568 | } | 1405 | } |
1569 | 1406 | ||
1570 | static ssize_t | 1407 | static ssize_t |
1571 | store_tabletStylusLower(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1408 | store_tabletStylusLower(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1572 | { | 1409 | { |
1573 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1410 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1411 | int new_button = map_str_to_val(stylus_button_map, buf, count); | ||
1574 | 1412 | ||
1575 | if (aiptek == NULL) | 1413 | if (new_button == AIPTEK_INVALID_VALUE) |
1576 | return 0; | 1414 | return -EINVAL; |
1577 | 1415 | ||
1578 | if (strcmp(buf, "upper") == 0) { | 1416 | aiptek->newSetting.stylusButtonLower = new_button; |
1579 | aiptek->newSetting.stylusButtonLower = | ||
1580 | AIPTEK_STYLUS_UPPER_BUTTON; | ||
1581 | } else if (strcmp(buf, "lower") == 0) { | ||
1582 | aiptek->newSetting.stylusButtonLower = | ||
1583 | AIPTEK_STYLUS_LOWER_BUTTON; | ||
1584 | } | ||
1585 | return count; | 1417 | return count; |
1586 | } | 1418 | } |
1587 | 1419 | ||
@@ -1593,49 +1425,33 @@ static DEVICE_ATTR(stylus_lower, | |||
1593 | * support routines for the 'mouse_left' file. Note that this file | 1425 | * support routines for the 'mouse_left' file. Note that this file |
1594 | * both displays current setting and allows for setting changing. | 1426 | * both displays current setting and allows for setting changing. |
1595 | */ | 1427 | */ |
1428 | |||
1429 | static struct aiptek_map mouse_button_map[] = { | ||
1430 | { "left", AIPTEK_MOUSE_LEFT_BUTTON }, | ||
1431 | { "middle", AIPTEK_MOUSE_MIDDLE_BUTTON }, | ||
1432 | { "right", AIPTEK_MOUSE_RIGHT_BUTTON }, | ||
1433 | { NULL, AIPTEK_INVALID_VALUE } | ||
1434 | }; | ||
1435 | |||
1596 | static ssize_t show_tabletMouseLeft(struct device *dev, struct device_attribute *attr, char *buf) | 1436 | static ssize_t show_tabletMouseLeft(struct device *dev, struct device_attribute *attr, char *buf) |
1597 | { | 1437 | { |
1598 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1438 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1599 | char *s; | ||
1600 | |||
1601 | if (aiptek == NULL) | ||
1602 | return 0; | ||
1603 | |||
1604 | switch (aiptek->curSetting.mouseButtonLeft) { | ||
1605 | case AIPTEK_MOUSE_LEFT_BUTTON: | ||
1606 | s = "left"; | ||
1607 | break; | ||
1608 | |||
1609 | case AIPTEK_MOUSE_MIDDLE_BUTTON: | ||
1610 | s = "middle"; | ||
1611 | break; | ||
1612 | |||
1613 | case AIPTEK_MOUSE_RIGHT_BUTTON: | ||
1614 | s = "right"; | ||
1615 | break; | ||
1616 | 1439 | ||
1617 | default: | 1440 | return snprintf(buf, PAGE_SIZE, "%s\n", |
1618 | s = "unknown"; | 1441 | map_val_to_str(mouse_button_map, |
1619 | break; | 1442 | aiptek->curSetting.mouseButtonLeft)); |
1620 | } | ||
1621 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1622 | } | 1443 | } |
1623 | 1444 | ||
1624 | static ssize_t | 1445 | static ssize_t |
1625 | store_tabletMouseLeft(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1446 | store_tabletMouseLeft(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1626 | { | 1447 | { |
1627 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1448 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1449 | int new_button = map_str_to_val(mouse_button_map, buf, count); | ||
1628 | 1450 | ||
1629 | if (aiptek == NULL) | 1451 | if (new_button == AIPTEK_INVALID_VALUE) |
1630 | return 0; | 1452 | return -EINVAL; |
1631 | 1453 | ||
1632 | if (strcmp(buf, "left") == 0) { | 1454 | aiptek->newSetting.mouseButtonLeft = new_button; |
1633 | aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_LEFT_BUTTON; | ||
1634 | } else if (strcmp(buf, "middle") == 0) { | ||
1635 | aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_MIDDLE_BUTTON; | ||
1636 | } else if (strcmp(buf, "right") == 0) { | ||
1637 | aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_RIGHT_BUTTON; | ||
1638 | } | ||
1639 | return count; | 1455 | return count; |
1640 | } | 1456 | } |
1641 | 1457 | ||
@@ -1650,48 +1466,22 @@ static DEVICE_ATTR(mouse_left, | |||
1650 | static ssize_t show_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, char *buf) | 1466 | static ssize_t show_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, char *buf) |
1651 | { | 1467 | { |
1652 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1468 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1653 | char *s; | ||
1654 | 1469 | ||
1655 | if (aiptek == NULL) | 1470 | return snprintf(buf, PAGE_SIZE, "%s\n", |
1656 | return 0; | 1471 | map_val_to_str(mouse_button_map, |
1657 | 1472 | aiptek->curSetting.mouseButtonMiddle)); | |
1658 | switch (aiptek->curSetting.mouseButtonMiddle) { | ||
1659 | case AIPTEK_MOUSE_LEFT_BUTTON: | ||
1660 | s = "left"; | ||
1661 | break; | ||
1662 | |||
1663 | case AIPTEK_MOUSE_MIDDLE_BUTTON: | ||
1664 | s = "middle"; | ||
1665 | break; | ||
1666 | |||
1667 | case AIPTEK_MOUSE_RIGHT_BUTTON: | ||
1668 | s = "right"; | ||
1669 | break; | ||
1670 | |||
1671 | default: | ||
1672 | s = "unknown"; | ||
1673 | break; | ||
1674 | } | ||
1675 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1676 | } | 1473 | } |
1677 | 1474 | ||
1678 | static ssize_t | 1475 | static ssize_t |
1679 | store_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1476 | store_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1680 | { | 1477 | { |
1681 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1478 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1479 | int new_button = map_str_to_val(mouse_button_map, buf, count); | ||
1682 | 1480 | ||
1683 | if (aiptek == NULL) | 1481 | if (new_button == AIPTEK_INVALID_VALUE) |
1684 | return 0; | 1482 | return -EINVAL; |
1685 | 1483 | ||
1686 | if (strcmp(buf, "left") == 0) { | 1484 | aiptek->newSetting.mouseButtonMiddle = new_button; |
1687 | aiptek->newSetting.mouseButtonMiddle = AIPTEK_MOUSE_LEFT_BUTTON; | ||
1688 | } else if (strcmp(buf, "middle") == 0) { | ||
1689 | aiptek->newSetting.mouseButtonMiddle = | ||
1690 | AIPTEK_MOUSE_MIDDLE_BUTTON; | ||
1691 | } else if (strcmp(buf, "right") == 0) { | ||
1692 | aiptek->newSetting.mouseButtonMiddle = | ||
1693 | AIPTEK_MOUSE_RIGHT_BUTTON; | ||
1694 | } | ||
1695 | return count; | 1485 | return count; |
1696 | } | 1486 | } |
1697 | 1487 | ||
@@ -1706,47 +1496,22 @@ static DEVICE_ATTR(mouse_middle, | |||
1706 | static ssize_t show_tabletMouseRight(struct device *dev, struct device_attribute *attr, char *buf) | 1496 | static ssize_t show_tabletMouseRight(struct device *dev, struct device_attribute *attr, char *buf) |
1707 | { | 1497 | { |
1708 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1498 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1709 | char *s; | ||
1710 | |||
1711 | if (aiptek == NULL) | ||
1712 | return 0; | ||
1713 | |||
1714 | switch (aiptek->curSetting.mouseButtonRight) { | ||
1715 | case AIPTEK_MOUSE_LEFT_BUTTON: | ||
1716 | s = "left"; | ||
1717 | break; | ||
1718 | |||
1719 | case AIPTEK_MOUSE_MIDDLE_BUTTON: | ||
1720 | s = "middle"; | ||
1721 | break; | ||
1722 | 1499 | ||
1723 | case AIPTEK_MOUSE_RIGHT_BUTTON: | 1500 | return snprintf(buf, PAGE_SIZE, "%s\n", |
1724 | s = "right"; | 1501 | map_val_to_str(mouse_button_map, |
1725 | break; | 1502 | aiptek->curSetting.mouseButtonRight)); |
1726 | |||
1727 | default: | ||
1728 | s = "unknown"; | ||
1729 | break; | ||
1730 | } | ||
1731 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1732 | } | 1503 | } |
1733 | 1504 | ||
1734 | static ssize_t | 1505 | static ssize_t |
1735 | store_tabletMouseRight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1506 | store_tabletMouseRight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1736 | { | 1507 | { |
1737 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1508 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1509 | int new_button = map_str_to_val(mouse_button_map, buf, count); | ||
1738 | 1510 | ||
1739 | if (aiptek == NULL) | 1511 | if (new_button == AIPTEK_INVALID_VALUE) |
1740 | return 0; | 1512 | return -EINVAL; |
1741 | 1513 | ||
1742 | if (strcmp(buf, "left") == 0) { | 1514 | aiptek->newSetting.mouseButtonRight = new_button; |
1743 | aiptek->newSetting.mouseButtonRight = AIPTEK_MOUSE_LEFT_BUTTON; | ||
1744 | } else if (strcmp(buf, "middle") == 0) { | ||
1745 | aiptek->newSetting.mouseButtonRight = | ||
1746 | AIPTEK_MOUSE_MIDDLE_BUTTON; | ||
1747 | } else if (strcmp(buf, "right") == 0) { | ||
1748 | aiptek->newSetting.mouseButtonRight = AIPTEK_MOUSE_RIGHT_BUTTON; | ||
1749 | } | ||
1750 | return count; | 1515 | return count; |
1751 | } | 1516 | } |
1752 | 1517 | ||
@@ -1762,9 +1527,6 @@ static ssize_t show_tabletWheel(struct device *dev, struct device_attribute *att | |||
1762 | { | 1527 | { |
1763 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1528 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1764 | 1529 | ||
1765 | if (aiptek == NULL) | ||
1766 | return 0; | ||
1767 | |||
1768 | if (aiptek->curSetting.wheel == AIPTEK_WHEEL_DISABLE) { | 1530 | if (aiptek->curSetting.wheel == AIPTEK_WHEEL_DISABLE) { |
1769 | return snprintf(buf, PAGE_SIZE, "disable\n"); | 1531 | return snprintf(buf, PAGE_SIZE, "disable\n"); |
1770 | } else { | 1532 | } else { |
@@ -1778,9 +1540,6 @@ store_tabletWheel(struct device *dev, struct device_attribute *attr, const char | |||
1778 | { | 1540 | { |
1779 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1541 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1780 | 1542 | ||
1781 | if (aiptek == NULL) | ||
1782 | return 0; | ||
1783 | |||
1784 | aiptek->newSetting.wheel = (int)simple_strtol(buf, NULL, 10); | 1543 | aiptek->newSetting.wheel = (int)simple_strtol(buf, NULL, 10); |
1785 | return count; | 1544 | return count; |
1786 | } | 1545 | } |
@@ -1794,11 +1553,6 @@ static DEVICE_ATTR(wheel, | |||
1794 | */ | 1553 | */ |
1795 | static ssize_t show_tabletExecute(struct device *dev, struct device_attribute *attr, char *buf) | 1554 | static ssize_t show_tabletExecute(struct device *dev, struct device_attribute *attr, char *buf) |
1796 | { | 1555 | { |
1797 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1798 | |||
1799 | if (aiptek == NULL) | ||
1800 | return 0; | ||
1801 | |||
1802 | /* There is nothing useful to display, so a one-line manual | 1556 | /* There is nothing useful to display, so a one-line manual |
1803 | * is in order... | 1557 | * is in order... |
1804 | */ | 1558 | */ |
@@ -1811,9 +1565,6 @@ store_tabletExecute(struct device *dev, struct device_attribute *attr, const cha | |||
1811 | { | 1565 | { |
1812 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1566 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1813 | 1567 | ||
1814 | if (aiptek == NULL) | ||
1815 | return 0; | ||
1816 | |||
1817 | /* We do not care what you write to this file. Merely the action | 1568 | /* We do not care what you write to this file. Merely the action |
1818 | * of writing to this file triggers a tablet reprogramming. | 1569 | * of writing to this file triggers a tablet reprogramming. |
1819 | */ | 1570 | */ |
@@ -1837,9 +1588,6 @@ static ssize_t show_tabletODMCode(struct device *dev, struct device_attribute *a | |||
1837 | { | 1588 | { |
1838 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1589 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1839 | 1590 | ||
1840 | if (aiptek == NULL) | ||
1841 | return 0; | ||
1842 | |||
1843 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.odmCode); | 1591 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.odmCode); |
1844 | } | 1592 | } |
1845 | 1593 | ||
@@ -1853,9 +1601,6 @@ static ssize_t show_tabletModelCode(struct device *dev, struct device_attribute | |||
1853 | { | 1601 | { |
1854 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1602 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1855 | 1603 | ||
1856 | if (aiptek == NULL) | ||
1857 | return 0; | ||
1858 | |||
1859 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.modelCode); | 1604 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.modelCode); |
1860 | } | 1605 | } |
1861 | 1606 | ||
@@ -1869,86 +1614,39 @@ static ssize_t show_firmwareCode(struct device *dev, struct device_attribute *at | |||
1869 | { | 1614 | { |
1870 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1615 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1871 | 1616 | ||
1872 | if (aiptek == NULL) | ||
1873 | return 0; | ||
1874 | |||
1875 | return snprintf(buf, PAGE_SIZE, "%04x\n", | 1617 | return snprintf(buf, PAGE_SIZE, "%04x\n", |
1876 | aiptek->features.firmwareCode); | 1618 | aiptek->features.firmwareCode); |
1877 | } | 1619 | } |
1878 | 1620 | ||
1879 | static DEVICE_ATTR(firmware_code, S_IRUGO, show_firmwareCode, NULL); | 1621 | static DEVICE_ATTR(firmware_code, S_IRUGO, show_firmwareCode, NULL); |
1880 | 1622 | ||
1881 | /*********************************************************************** | 1623 | static struct attribute *aiptek_attributes[] = { |
1882 | * This routine removes all existing sysfs files managed by this device | 1624 | &dev_attr_size.attr, |
1883 | * driver. | 1625 | &dev_attr_pointer_mode.attr, |
1884 | */ | 1626 | &dev_attr_coordinate_mode.attr, |
1885 | static void aiptek_delete_files(struct device *dev) | 1627 | &dev_attr_tool_mode.attr, |
1886 | { | 1628 | &dev_attr_xtilt.attr, |
1887 | device_remove_file(dev, &dev_attr_size); | 1629 | &dev_attr_ytilt.attr, |
1888 | device_remove_file(dev, &dev_attr_product_id); | 1630 | &dev_attr_jitter.attr, |
1889 | device_remove_file(dev, &dev_attr_vendor_id); | 1631 | &dev_attr_delay.attr, |
1890 | device_remove_file(dev, &dev_attr_vendor); | 1632 | &dev_attr_event_count.attr, |
1891 | device_remove_file(dev, &dev_attr_product); | 1633 | &dev_attr_diagnostic.attr, |
1892 | device_remove_file(dev, &dev_attr_pointer_mode); | 1634 | &dev_attr_odm_code.attr, |
1893 | device_remove_file(dev, &dev_attr_coordinate_mode); | 1635 | &dev_attr_model_code.attr, |
1894 | device_remove_file(dev, &dev_attr_tool_mode); | 1636 | &dev_attr_firmware_code.attr, |
1895 | device_remove_file(dev, &dev_attr_xtilt); | 1637 | &dev_attr_stylus_lower.attr, |
1896 | device_remove_file(dev, &dev_attr_ytilt); | 1638 | &dev_attr_stylus_upper.attr, |
1897 | device_remove_file(dev, &dev_attr_jitter); | 1639 | &dev_attr_mouse_left.attr, |
1898 | device_remove_file(dev, &dev_attr_delay); | 1640 | &dev_attr_mouse_middle.attr, |
1899 | device_remove_file(dev, &dev_attr_input_path); | 1641 | &dev_attr_mouse_right.attr, |
1900 | device_remove_file(dev, &dev_attr_event_count); | 1642 | &dev_attr_wheel.attr, |
1901 | device_remove_file(dev, &dev_attr_diagnostic); | 1643 | &dev_attr_execute.attr, |
1902 | device_remove_file(dev, &dev_attr_odm_code); | 1644 | NULL |
1903 | device_remove_file(dev, &dev_attr_model_code); | 1645 | }; |
1904 | device_remove_file(dev, &dev_attr_firmware_code); | ||
1905 | device_remove_file(dev, &dev_attr_stylus_lower); | ||
1906 | device_remove_file(dev, &dev_attr_stylus_upper); | ||
1907 | device_remove_file(dev, &dev_attr_mouse_left); | ||
1908 | device_remove_file(dev, &dev_attr_mouse_middle); | ||
1909 | device_remove_file(dev, &dev_attr_mouse_right); | ||
1910 | device_remove_file(dev, &dev_attr_wheel); | ||
1911 | device_remove_file(dev, &dev_attr_execute); | ||
1912 | } | ||
1913 | |||
1914 | /*********************************************************************** | ||
1915 | * This routine creates the sysfs files managed by this device | ||
1916 | * driver. | ||
1917 | */ | ||
1918 | static int aiptek_add_files(struct device *dev) | ||
1919 | { | ||
1920 | int ret; | ||
1921 | 1646 | ||
1922 | if ((ret = device_create_file(dev, &dev_attr_size)) || | 1647 | static struct attribute_group aiptek_attribute_group = { |
1923 | (ret = device_create_file(dev, &dev_attr_product_id)) || | 1648 | .attrs = aiptek_attributes, |
1924 | (ret = device_create_file(dev, &dev_attr_vendor_id)) || | 1649 | }; |
1925 | (ret = device_create_file(dev, &dev_attr_vendor)) || | ||
1926 | (ret = device_create_file(dev, &dev_attr_product)) || | ||
1927 | (ret = device_create_file(dev, &dev_attr_pointer_mode)) || | ||
1928 | (ret = device_create_file(dev, &dev_attr_coordinate_mode)) || | ||
1929 | (ret = device_create_file(dev, &dev_attr_tool_mode)) || | ||
1930 | (ret = device_create_file(dev, &dev_attr_xtilt)) || | ||
1931 | (ret = device_create_file(dev, &dev_attr_ytilt)) || | ||
1932 | (ret = device_create_file(dev, &dev_attr_jitter)) || | ||
1933 | (ret = device_create_file(dev, &dev_attr_delay)) || | ||
1934 | (ret = device_create_file(dev, &dev_attr_input_path)) || | ||
1935 | (ret = device_create_file(dev, &dev_attr_event_count)) || | ||
1936 | (ret = device_create_file(dev, &dev_attr_diagnostic)) || | ||
1937 | (ret = device_create_file(dev, &dev_attr_odm_code)) || | ||
1938 | (ret = device_create_file(dev, &dev_attr_model_code)) || | ||
1939 | (ret = device_create_file(dev, &dev_attr_firmware_code)) || | ||
1940 | (ret = device_create_file(dev, &dev_attr_stylus_lower)) || | ||
1941 | (ret = device_create_file(dev, &dev_attr_stylus_upper)) || | ||
1942 | (ret = device_create_file(dev, &dev_attr_mouse_left)) || | ||
1943 | (ret = device_create_file(dev, &dev_attr_mouse_middle)) || | ||
1944 | (ret = device_create_file(dev, &dev_attr_mouse_right)) || | ||
1945 | (ret = device_create_file(dev, &dev_attr_wheel)) || | ||
1946 | (ret = device_create_file(dev, &dev_attr_execute))) { | ||
1947 | err("aiptek: killing own sysfs device files\n"); | ||
1948 | aiptek_delete_files(dev); | ||
1949 | } | ||
1950 | return ret; | ||
1951 | } | ||
1952 | 1650 | ||
1953 | /*********************************************************************** | 1651 | /*********************************************************************** |
1954 | * This routine is called when a tablet has been identified. It basically | 1652 | * This routine is called when a tablet has been identified. It basically |
@@ -1961,8 +1659,6 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
1961 | struct usb_endpoint_descriptor *endpoint; | 1659 | struct usb_endpoint_descriptor *endpoint; |
1962 | struct aiptek *aiptek; | 1660 | struct aiptek *aiptek; |
1963 | struct input_dev *inputdev; | 1661 | struct input_dev *inputdev; |
1964 | struct input_handle *inputhandle; | ||
1965 | struct list_head *node, *next; | ||
1966 | int i; | 1662 | int i; |
1967 | int speeds[] = { 0, | 1663 | int speeds[] = { 0, |
1968 | AIPTEK_PROGRAMMABLE_DELAY_50, | 1664 | AIPTEK_PROGRAMMABLE_DELAY_50, |
@@ -1984,17 +1680,23 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
1984 | 1680 | ||
1985 | aiptek = kzalloc(sizeof(struct aiptek), GFP_KERNEL); | 1681 | aiptek = kzalloc(sizeof(struct aiptek), GFP_KERNEL); |
1986 | inputdev = input_allocate_device(); | 1682 | inputdev = input_allocate_device(); |
1987 | if (!aiptek || !inputdev) | 1683 | if (!aiptek || !inputdev) { |
1684 | warn("aiptek: cannot allocate memory or input device"); | ||
1988 | goto fail1; | 1685 | goto fail1; |
1686 | } | ||
1989 | 1687 | ||
1990 | aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH, | 1688 | aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH, |
1991 | GFP_ATOMIC, &aiptek->data_dma); | 1689 | GFP_ATOMIC, &aiptek->data_dma); |
1992 | if (!aiptek->data) | 1690 | if (!aiptek->data) { |
1691 | warn("aiptek: cannot allocate usb buffer"); | ||
1993 | goto fail1; | 1692 | goto fail1; |
1693 | } | ||
1994 | 1694 | ||
1995 | aiptek->urb = usb_alloc_urb(0, GFP_KERNEL); | 1695 | aiptek->urb = usb_alloc_urb(0, GFP_KERNEL); |
1996 | if (!aiptek->urb) | 1696 | if (!aiptek->urb) { |
1697 | warn("aiptek: cannot allocate urb"); | ||
1997 | goto fail2; | 1698 | goto fail2; |
1699 | } | ||
1998 | 1700 | ||
1999 | aiptek->inputdev = inputdev; | 1701 | aiptek->inputdev = inputdev; |
2000 | aiptek->usbdev = usbdev; | 1702 | aiptek->usbdev = usbdev; |
@@ -2002,6 +1704,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
2002 | aiptek->inDelay = 0; | 1704 | aiptek->inDelay = 0; |
2003 | aiptek->endDelay = 0; | 1705 | aiptek->endDelay = 0; |
2004 | aiptek->previousJitterable = 0; | 1706 | aiptek->previousJitterable = 0; |
1707 | aiptek->lastMacro = -1; | ||
2005 | 1708 | ||
2006 | /* Set up the curSettings struct. Said struct contains the current | 1709 | /* Set up the curSettings struct. Said struct contains the current |
2007 | * programmable parameters. The newSetting struct contains changes | 1710 | * programmable parameters. The newSetting struct contains changes |
@@ -2054,36 +1757,23 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
2054 | /* Now program the capacities of the tablet, in terms of being | 1757 | /* Now program the capacities of the tablet, in terms of being |
2055 | * an input device. | 1758 | * an input device. |
2056 | */ | 1759 | */ |
2057 | inputdev->evbit[0] |= BIT(EV_KEY) | 1760 | for (i = 0; i < ARRAY_SIZE(eventTypes); ++i) |
2058 | | BIT(EV_ABS) | 1761 | __set_bit(eventTypes[i], inputdev->evbit); |
2059 | | BIT(EV_REL) | ||
2060 | | BIT(EV_MSC); | ||
2061 | |||
2062 | inputdev->absbit[0] |= BIT(ABS_MISC); | ||
2063 | 1762 | ||
2064 | inputdev->relbit[0] |= | 1763 | for (i = 0; i < ARRAY_SIZE(absEvents); ++i) |
2065 | (BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL) | BIT(REL_MISC)); | 1764 | __set_bit(absEvents[i], inputdev->absbit); |
2066 | 1765 | ||
2067 | inputdev->keybit[LONG(BTN_LEFT)] |= | 1766 | for (i = 0; i < ARRAY_SIZE(relEvents); ++i) |
2068 | (BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE)); | 1767 | __set_bit(relEvents[i], inputdev->relbit); |
2069 | 1768 | ||
2070 | inputdev->keybit[LONG(BTN_DIGI)] |= | 1769 | __set_bit(MSC_SERIAL, inputdev->mscbit); |
2071 | (BIT(BTN_TOOL_PEN) | | ||
2072 | BIT(BTN_TOOL_RUBBER) | | ||
2073 | BIT(BTN_TOOL_PENCIL) | | ||
2074 | BIT(BTN_TOOL_AIRBRUSH) | | ||
2075 | BIT(BTN_TOOL_BRUSH) | | ||
2076 | BIT(BTN_TOOL_MOUSE) | | ||
2077 | BIT(BTN_TOOL_LENS) | | ||
2078 | BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2)); | ||
2079 | 1770 | ||
2080 | inputdev->mscbit[0] = BIT(MSC_SERIAL); | 1771 | /* Set up key and button codes */ |
1772 | for (i = 0; i < ARRAY_SIZE(buttonEvents); ++i) | ||
1773 | __set_bit(buttonEvents[i], inputdev->keybit); | ||
2081 | 1774 | ||
2082 | /* Programming the tablet macro keys needs to be done with a for loop | ||
2083 | * as the keycodes are discontiguous. | ||
2084 | */ | ||
2085 | for (i = 0; i < ARRAY_SIZE(macroKeyEvents); ++i) | 1775 | for (i = 0; i < ARRAY_SIZE(macroKeyEvents); ++i) |
2086 | set_bit(macroKeyEvents[i], inputdev->keybit); | 1776 | __set_bit(macroKeyEvents[i], inputdev->keybit); |
2087 | 1777 | ||
2088 | /* | 1778 | /* |
2089 | * Program the input device coordinate capacities. We do not yet | 1779 | * Program the input device coordinate capacities. We do not yet |
@@ -2134,25 +1824,11 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
2134 | } | 1824 | } |
2135 | } | 1825 | } |
2136 | 1826 | ||
2137 | /* Register the tablet as an Input Device | 1827 | /* Murphy says that some day someone will have a tablet that fails the |
2138 | */ | 1828 | above test. That's you, Frederic Rodrigo */ |
2139 | err = input_register_device(aiptek->inputdev); | 1829 | if (i == ARRAY_SIZE(speeds)) { |
2140 | if (err) | 1830 | info("input: Aiptek tried all speeds, no sane response"); |
2141 | goto fail2; | 1831 | goto fail2; |
2142 | |||
2143 | /* We now will look for the evdev device which is mapped to | ||
2144 | * the tablet. The partial name is kept in the link list of | ||
2145 | * input_handles associated with this input device. | ||
2146 | * What identifies an evdev input_handler is that it begins | ||
2147 | * with 'event', continues with a digit, and that in turn | ||
2148 | * is mapped to input/eventN. | ||
2149 | */ | ||
2150 | list_for_each_safe(node, next, &inputdev->h_list) { | ||
2151 | inputhandle = to_handle(node); | ||
2152 | if (strncmp(inputhandle->name, "event", 5) == 0) { | ||
2153 | strcpy(aiptek->features.inputPath, inputhandle->name); | ||
2154 | break; | ||
2155 | } | ||
2156 | } | 1832 | } |
2157 | 1833 | ||
2158 | /* Associate this driver's struct with the usb interface. | 1834 | /* Associate this driver's struct with the usb interface. |
@@ -2161,18 +1837,27 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
2161 | 1837 | ||
2162 | /* Set up the sysfs files | 1838 | /* Set up the sysfs files |
2163 | */ | 1839 | */ |
2164 | aiptek_add_files(&intf->dev); | 1840 | err = sysfs_create_group(&intf->dev.kobj, &aiptek_attribute_group); |
1841 | if (err) { | ||
1842 | warn("aiptek: cannot create sysfs group err: %d", err); | ||
1843 | goto fail3; | ||
1844 | } | ||
2165 | 1845 | ||
2166 | /* Make sure the evdev module is loaded. Assuming evdev IS a module :-) | 1846 | /* Register the tablet as an Input Device |
2167 | */ | 1847 | */ |
2168 | if (request_module("evdev") != 0) | 1848 | err = input_register_device(aiptek->inputdev); |
2169 | info("aiptek: error loading 'evdev' module"); | 1849 | if (err) { |
2170 | 1850 | warn("aiptek: input_register_device returned err: %d", err); | |
1851 | goto fail4; | ||
1852 | } | ||
2171 | return 0; | 1853 | return 0; |
2172 | 1854 | ||
1855 | fail4: sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group); | ||
1856 | fail3: usb_free_urb(aiptek->urb); | ||
2173 | fail2: usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data, | 1857 | fail2: usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data, |
2174 | aiptek->data_dma); | 1858 | aiptek->data_dma); |
2175 | fail1: input_free_device(inputdev); | 1859 | fail1: usb_set_intfdata(intf, NULL); |
1860 | input_free_device(inputdev); | ||
2176 | kfree(aiptek); | 1861 | kfree(aiptek); |
2177 | return err; | 1862 | return err; |
2178 | } | 1863 | } |
@@ -2192,7 +1877,7 @@ static void aiptek_disconnect(struct usb_interface *intf) | |||
2192 | */ | 1877 | */ |
2193 | usb_kill_urb(aiptek->urb); | 1878 | usb_kill_urb(aiptek->urb); |
2194 | input_unregister_device(aiptek->inputdev); | 1879 | input_unregister_device(aiptek->inputdev); |
2195 | aiptek_delete_files(&intf->dev); | 1880 | sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group); |
2196 | usb_free_urb(aiptek->urb); | 1881 | usb_free_urb(aiptek->urb); |
2197 | usb_buffer_free(interface_to_usbdev(intf), | 1882 | usb_buffer_free(interface_to_usbdev(intf), |
2198 | AIPTEK_PACKET_LENGTH, | 1883 | AIPTEK_PACKET_LENGTH, |
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index ef01a807ec0f..6542edb6f76e 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h | |||
@@ -11,7 +11,7 @@ | |||
11 | * Copyright (c) 2000 Daniel Egger <egger@suse.de> | 11 | * Copyright (c) 2000 Daniel Egger <egger@suse.de> |
12 | * Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com> | 12 | * Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com> |
13 | * Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be> | 13 | * Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be> |
14 | * Copyright (c) 2002-2006 Ping Cheng <pingc@wacom.com> | 14 | * Copyright (c) 2002-2007 Ping Cheng <pingc@wacom.com> |
15 | * | 15 | * |
16 | * ChangeLog: | 16 | * ChangeLog: |
17 | * v0.1 (vp) - Initial release | 17 | * v0.1 (vp) - Initial release |
@@ -62,8 +62,9 @@ | |||
62 | * - Minor data report fix | 62 | * - Minor data report fix |
63 | * v1.46 (pc) - Split wacom.c into wacom_sys.c and wacom_wac.c, | 63 | * v1.46 (pc) - Split wacom.c into wacom_sys.c and wacom_wac.c, |
64 | * - where wacom_sys.c deals with system specific code, | 64 | * - where wacom_sys.c deals with system specific code, |
65 | * - and wacom_wac.c deals with Wacom specific code | 65 | * - and wacom_wac.c deals with Wacom specific code |
66 | * - Support Intuos3 4x6 | 66 | * - Support Intuos3 4x6 |
67 | * v1.47 (pc) - Added support for Bamboo | ||
67 | */ | 68 | */ |
68 | 69 | ||
69 | /* | 70 | /* |
@@ -84,7 +85,7 @@ | |||
84 | /* | 85 | /* |
85 | * Version Information | 86 | * Version Information |
86 | */ | 87 | */ |
87 | #define DRIVER_VERSION "v1.46" | 88 | #define DRIVER_VERSION "v1.47" |
88 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" | 89 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" |
89 | #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" | 90 | #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" |
90 | #define DRIVER_LICENSE "GPL" | 91 | #define DRIVER_LICENSE "GPL" |
@@ -123,6 +124,7 @@ extern void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wa | |||
123 | extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | 124 | extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac); |
124 | extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | 125 | extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac); |
125 | extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | 126 | extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac); |
127 | extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
126 | extern __u16 wacom_le16_to_cpu(unsigned char *data); | 128 | extern __u16 wacom_le16_to_cpu(unsigned char *data); |
127 | extern __u16 wacom_be16_to_cpu(unsigned char *data); | 129 | extern __u16 wacom_be16_to_cpu(unsigned char *data); |
128 | extern struct wacom_features * get_wacom_feature(const struct usb_device_id *id); | 130 | extern struct wacom_features * get_wacom_feature(const struct usb_device_id *id); |
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 83bddef66067..064e123c9b76 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c | |||
@@ -138,6 +138,12 @@ static void wacom_close(struct input_dev *dev) | |||
138 | usb_kill_urb(wacom->irq); | 138 | usb_kill_urb(wacom->irq); |
139 | } | 139 | } |
140 | 140 | ||
141 | void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
142 | { | ||
143 | input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_1) | BIT(BTN_5); | ||
144 | input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); | ||
145 | } | ||
146 | |||
141 | void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | 147 | void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac) |
142 | { | 148 | { |
143 | input_dev->evbit[0] |= BIT(EV_MSC); | 149 | input_dev->evbit[0] |= BIT(EV_MSC); |
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 7661f03a2db2..fc03ba256f4c 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
@@ -178,7 +178,8 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
178 | 178 | ||
179 | case 2: /* Mouse with wheel */ | 179 | case 2: /* Mouse with wheel */ |
180 | wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04); | 180 | wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04); |
181 | if (wacom->features->type == WACOM_G4) { | 181 | if (wacom->features->type == WACOM_G4 || |
182 | wacom->features->type == WACOM_MO) { | ||
182 | rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03); | 183 | rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03); |
183 | wacom_report_rel(wcombo, REL_WHEEL, -rw); | 184 | wacom_report_rel(wcombo, REL_WHEEL, -rw); |
184 | } else | 185 | } else |
@@ -190,7 +191,8 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
190 | id = CURSOR_DEVICE_ID; | 191 | id = CURSOR_DEVICE_ID; |
191 | wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01); | 192 | wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01); |
192 | wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02); | 193 | wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02); |
193 | if (wacom->features->type == WACOM_G4) | 194 | if (wacom->features->type == WACOM_G4 || |
195 | wacom->features->type == WACOM_MO) | ||
194 | wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f); | 196 | wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f); |
195 | else | 197 | else |
196 | wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); | 198 | wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); |
@@ -226,7 +228,8 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
226 | } | 228 | } |
227 | 229 | ||
228 | /* send pad data */ | 230 | /* send pad data */ |
229 | if (wacom->features->type == WACOM_G4) { | 231 | switch (wacom->features->type) { |
232 | case WACOM_G4: | ||
230 | if (data[7] & 0xf8) { | 233 | if (data[7] & 0xf8) { |
231 | wacom_input_sync(wcombo); /* sync last event */ | 234 | wacom_input_sync(wcombo); /* sync last event */ |
232 | wacom->id[1] = 1; | 235 | wacom->id[1] = 1; |
@@ -247,6 +250,33 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
247 | wacom_report_abs(wcombo, ABS_MISC, 0); | 250 | wacom_report_abs(wcombo, ABS_MISC, 0); |
248 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | 251 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); |
249 | } | 252 | } |
253 | break; | ||
254 | case WACOM_MO: | ||
255 | if ((data[7] & 0xf8) || (data[8] & 0x80)) { | ||
256 | wacom_input_sync(wcombo); /* sync last event */ | ||
257 | wacom->id[1] = 1; | ||
258 | wacom->serial[1] = (data[7] & 0xf8); | ||
259 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); | ||
260 | wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); | ||
261 | wacom_report_key(wcombo, BTN_4, (data[7] & 0x10)); | ||
262 | wacom_report_key(wcombo, BTN_5, (data[7] & 0x40)); | ||
263 | wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f)); | ||
264 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); | ||
265 | wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID); | ||
266 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | ||
267 | } else if (wacom->id[1]) { | ||
268 | wacom_input_sync(wcombo); /* sync last event */ | ||
269 | wacom->id[1] = 0; | ||
270 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); | ||
271 | wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); | ||
272 | wacom_report_key(wcombo, BTN_4, (data[7] & 0x10)); | ||
273 | wacom_report_key(wcombo, BTN_5, (data[7] & 0x40)); | ||
274 | wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f)); | ||
275 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); | ||
276 | wacom_report_abs(wcombo, ABS_MISC, 0); | ||
277 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | ||
278 | } | ||
279 | break; | ||
250 | } | 280 | } |
251 | return 1; | 281 | return 1; |
252 | } | 282 | } |
@@ -331,7 +361,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) | |||
331 | wacom_report_key(wcombo, BTN_EXTRA, 0); | 361 | wacom_report_key(wcombo, BTN_EXTRA, 0); |
332 | wacom_report_abs(wcombo, ABS_THROTTLE, 0); | 362 | wacom_report_abs(wcombo, ABS_THROTTLE, 0); |
333 | wacom_report_abs(wcombo, ABS_RZ, 0); | 363 | wacom_report_abs(wcombo, ABS_RZ, 0); |
334 | } else { | 364 | } else { |
335 | wacom_report_abs(wcombo, ABS_PRESSURE, 0); | 365 | wacom_report_abs(wcombo, ABS_PRESSURE, 0); |
336 | wacom_report_abs(wcombo, ABS_TILT_X, 0); | 366 | wacom_report_abs(wcombo, ABS_TILT_X, 0); |
337 | wacom_report_abs(wcombo, ABS_TILT_Y, 0); | 367 | wacom_report_abs(wcombo, ABS_TILT_Y, 0); |
@@ -423,9 +453,9 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
423 | return result-1; | 453 | return result-1; |
424 | 454 | ||
425 | /* Only large I3 and I1 & I2 support Lense Cursor */ | 455 | /* Only large I3 and I1 & I2 support Lense Cursor */ |
426 | if((wacom->tool[idx] == BTN_TOOL_LENS) | 456 | if ((wacom->tool[idx] == BTN_TOOL_LENS) |
427 | && ((wacom->features->type == INTUOS3) | 457 | && ((wacom->features->type == INTUOS3) |
428 | || (wacom->features->type == INTUOS3S))) | 458 | || (wacom->features->type == INTUOS3S))) |
429 | return 0; | 459 | return 0; |
430 | 460 | ||
431 | /* Cintiq doesn't send data when RDY bit isn't set */ | 461 | /* Cintiq doesn't send data when RDY bit isn't set */ |
@@ -517,6 +547,7 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) | |||
517 | break; | 547 | break; |
518 | case WACOM_G4: | 548 | case WACOM_G4: |
519 | case GRAPHIRE: | 549 | case GRAPHIRE: |
550 | case WACOM_MO: | ||
520 | return (wacom_graphire_irq(wacom_wac, wcombo)); | 551 | return (wacom_graphire_irq(wacom_wac, wcombo)); |
521 | break; | 552 | break; |
522 | case PTU: | 553 | case PTU: |
@@ -538,6 +569,8 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) | |||
538 | void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | 569 | void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac) |
539 | { | 570 | { |
540 | switch (wacom_wac->features->type) { | 571 | switch (wacom_wac->features->type) { |
572 | case WACOM_MO: | ||
573 | input_dev_mo(input_dev, wacom_wac); | ||
541 | case WACOM_G4: | 574 | case WACOM_G4: |
542 | input_dev_g4(input_dev, wacom_wac); | 575 | input_dev_g4(input_dev, wacom_wac); |
543 | /* fall through */ | 576 | /* fall through */ |
@@ -579,6 +612,7 @@ static struct wacom_features wacom_features[] = { | |||
579 | { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 63, GRAPHIRE }, | 612 | { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 63, GRAPHIRE }, |
580 | { "Wacom Volito2 2x3", 8, 3248, 2320, 511, 63, GRAPHIRE }, | 613 | { "Wacom Volito2 2x3", 8, 3248, 2320, 511, 63, GRAPHIRE }, |
581 | { "Wacom PenPartner2", 8, 3250, 2320, 255, 63, GRAPHIRE }, | 614 | { "Wacom PenPartner2", 8, 3250, 2320, 255, 63, GRAPHIRE }, |
615 | { "Wacom Bamboo", 9, 14760, 9225, 511, 63, WACOM_MO }, | ||
582 | { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 31, INTUOS }, | 616 | { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 31, INTUOS }, |
583 | { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, | 617 | { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, |
584 | { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 31, INTUOS }, | 618 | { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 31, INTUOS }, |
@@ -627,6 +661,7 @@ static struct usb_device_id wacom_ids[] = { | |||
627 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) }, | 661 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) }, |
628 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) }, | 662 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) }, |
629 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) }, | 663 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) }, |
664 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x65) }, | ||
630 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) }, | 665 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) }, |
631 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) }, | 666 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) }, |
632 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) }, | 667 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) }, |
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index a5e12e8756de..a302e229bb8a 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h | |||
@@ -25,6 +25,7 @@ enum { | |||
25 | INTUOS3, | 25 | INTUOS3, |
26 | INTUOS3L, | 26 | INTUOS3L, |
27 | CINTIQ, | 27 | CINTIQ, |
28 | WACOM_MO, | ||
28 | MAX_TYPE | 29 | MAX_TYPE |
29 | }; | 30 | }; |
30 | 31 | ||
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index e5cca9bd0406..69371779806a 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -177,6 +177,7 @@ config TOUCHSCREEN_USB_COMPOSITE | |||
177 | - some other eTurboTouch | 177 | - some other eTurboTouch |
178 | - Gunze AHL61 | 178 | - Gunze AHL61 |
179 | - DMC TSC-10/25 | 179 | - DMC TSC-10/25 |
180 | - IRTOUCHSYSTEMS/UNITOP | ||
180 | 181 | ||
181 | Have a look at <http://linux.chapter7.ch/touchkit/> for | 182 | Have a look at <http://linux.chapter7.ch/touchkit/> for |
182 | a usage description and the required user-space stuff. | 183 | a usage description and the required user-space stuff. |
@@ -219,4 +220,9 @@ config TOUCHSCREEN_USB_DMC_TSC10 | |||
219 | bool "DMC TSC-10/25 device support" if EMBEDDED | 220 | bool "DMC TSC-10/25 device support" if EMBEDDED |
220 | depends on TOUCHSCREEN_USB_COMPOSITE | 221 | depends on TOUCHSCREEN_USB_COMPOSITE |
221 | 222 | ||
223 | config TOUCHSCREEN_USB_IRTOUCH | ||
224 | default y | ||
225 | bool "IRTOUCHSYSTEMS/UNITOP device support" if EMBEDDED | ||
226 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
227 | |||
222 | endif | 228 | endif |
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index e3f22852bd09..b407028ffc59 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * - eTurboTouch | 9 | * - eTurboTouch |
10 | * - Gunze AHL61 | 10 | * - Gunze AHL61 |
11 | * - DMC TSC-10/25 | 11 | * - DMC TSC-10/25 |
12 | * - IRTOUCHSYSTEMS/UNITOP | ||
12 | * | 13 | * |
13 | * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch> | 14 | * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch> |
14 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) | 15 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) |
@@ -110,6 +111,7 @@ enum { | |||
110 | DEVTYPE_ETURBO, | 111 | DEVTYPE_ETURBO, |
111 | DEVTYPE_GUNZE, | 112 | DEVTYPE_GUNZE, |
112 | DEVTYPE_DMC_TSC10, | 113 | DEVTYPE_DMC_TSC10, |
114 | DEVTYPE_IRTOUCH, | ||
113 | }; | 115 | }; |
114 | 116 | ||
115 | static struct usb_device_id usbtouch_devices[] = { | 117 | static struct usb_device_id usbtouch_devices[] = { |
@@ -150,6 +152,11 @@ static struct usb_device_id usbtouch_devices[] = { | |||
150 | {USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10}, | 152 | {USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10}, |
151 | #endif | 153 | #endif |
152 | 154 | ||
155 | #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH | ||
156 | {USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, | ||
157 | {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, | ||
158 | #endif | ||
159 | |||
153 | {} | 160 | {} |
154 | }; | 161 | }; |
155 | 162 | ||
@@ -416,6 +423,21 @@ static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |||
416 | 423 | ||
417 | 424 | ||
418 | /***************************************************************************** | 425 | /***************************************************************************** |
426 | * IRTOUCH Part | ||
427 | */ | ||
428 | #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH | ||
429 | static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
430 | { | ||
431 | dev->x = (pkt[3] << 8) | pkt[2]; | ||
432 | dev->y = (pkt[5] << 8) | pkt[4]; | ||
433 | dev->touch = (pkt[1] & 0x03) ? 1 : 0; | ||
434 | |||
435 | return 1; | ||
436 | } | ||
437 | #endif | ||
438 | |||
439 | |||
440 | /***************************************************************************** | ||
419 | * the different device descriptors | 441 | * the different device descriptors |
420 | */ | 442 | */ |
421 | static struct usbtouch_device_info usbtouch_dev_info[] = { | 443 | static struct usbtouch_device_info usbtouch_dev_info[] = { |
@@ -504,6 +526,17 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { | |||
504 | .read_data = dmc_tsc10_read_data, | 526 | .read_data = dmc_tsc10_read_data, |
505 | }, | 527 | }, |
506 | #endif | 528 | #endif |
529 | |||
530 | #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH | ||
531 | [DEVTYPE_IRTOUCH] = { | ||
532 | .min_xc = 0x0, | ||
533 | .max_xc = 0x0fff, | ||
534 | .min_yc = 0x0, | ||
535 | .max_yc = 0x0fff, | ||
536 | .rept_size = 8, | ||
537 | .read_data = irtouch_read_data, | ||
538 | }, | ||
539 | #endif | ||
507 | }; | 540 | }; |
508 | 541 | ||
509 | 542 | ||
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c index 2db364898e15..d2f882e98e5e 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 | } |
@@ -361,7 +371,7 @@ static void tsdev_event(struct input_handle *handle, unsigned int type, | |||
361 | int x, y, tmp; | 371 | int x, y, tmp; |
362 | 372 | ||
363 | do_gettimeofday(&time); | 373 | do_gettimeofday(&time); |
364 | client->event[client->head].millisecs = time.tv_usec / 100; | 374 | client->event[client->head].millisecs = time.tv_usec / 1000; |
365 | client->event[client->head].pressure = tsdev->pressure; | 375 | client->event[client->head].pressure = tsdev->pressure; |
366 | 376 | ||
367 | x = tsdev->x; | 377 | x = tsdev->x; |
@@ -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[] = { |