OSDN Git Service

Add updated driver from Stephane Lajeunesse
[android-x86/kernel.git] / drivers / hid / hid-hanvon.c
1 /*
2  *  HID driver for the multitouch panel on the Hanvon tablet
3  *
4  *  Copyright (c) 2010 Stephane Chatty <chatty@enac.fr>
5  *
6  */
7
8 /*
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by the Free
11  * Software Foundation; either version 2 of the License, or (at your option)
12  * any later version.
13  */
14
15 #include <linux/device.h>
16 #include <linux/hid.h>
17 #include <linux/module.h>
18 #include <linux/slab.h>
19 #include <linux/usb.h>
20 #include "usbhid/usbhid.h"
21
22 MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
23 MODULE_DESCRIPTION("Hanvon dual-touch panel");
24 MODULE_LICENSE("GPL");
25
26 #include "hid-ids.h"
27
28 struct hanvon_data {
29         __u16 x, y;
30         __u8 id;
31 };
32
33 static int hanvon_input_mapping(struct hid_device *hdev, struct hid_input *hi,
34                 struct hid_field *field, struct hid_usage *usage,
35                 unsigned long **bit, int *max)
36 {
37         switch (usage->hid & HID_USAGE_PAGE) {
38
39         case HID_UP_GENDESK:
40                 switch (usage->hid) {
41                 case HID_GD_X:
42                         hid_map_usage(hi, usage, bit, max,
43                                         EV_ABS, ABS_MT_POSITION_X);
44                         /* touchscreen emulation */
45                         input_set_abs_params(hi->input, ABS_X,
46                                                 field->logical_minimum,
47                                                 field->logical_maximum, 0, 0);
48                         return 1;
49                 case HID_GD_Y:
50                         hid_map_usage(hi, usage, bit, max,
51                                         EV_ABS, ABS_MT_POSITION_Y);
52                         /* touchscreen emulation */
53                         input_set_abs_params(hi->input, ABS_Y,
54                                                 field->logical_minimum,
55                                                 field->logical_maximum, 0, 0);
56                         return 1;
57                 }
58                 return 0;
59
60         case HID_UP_DIGITIZER:
61                 switch (usage->hid) {
62                 case HID_DG_TIPSWITCH:
63                         hid_map_usage(hi, usage, bit, max, EV_ABS,
64                                                 ABS_MT_TOUCH_MAJOR);
65                         return 1;
66
67                 case HID_DG_INRANGE:
68                         hid_map_usage(hi, usage, bit, max, EV_ABS,
69                                                 ABS_MT_TOUCH_MINOR);
70                         return 1;
71
72                 case HID_DG_CONFIDENCE:
73                         hid_map_usage(hi, usage, bit, max, EV_ABS,
74                                                 ABS_MT_WIDTH_MAJOR);
75                         return 1;
76
77                 case HID_DG_CONTACTID:
78                         hid_map_usage(hi, usage, bit, max,
79                                         EV_ABS, ABS_MT_TRACKING_ID);
80                         return 1;
81
82                 case HID_DG_CONTACTCOUNT:
83                         hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MAJOR);
84                         input_set_abs_params(hi->input, ABS_MT_TOUCH_MAJOR, 0, 255, 4, 0);
85                         hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MINOR);
86                         input_set_abs_params(hi->input, ABS_MT_TOUCH_MINOR, 0, 255, 4, 0);
87                         return 1;
88
89                 case HID_DG_CONTACTMAX:
90                         hid_map_usage(hi, usage, bit, max, EV_ABS,
91                                                 ABS_MT_ORIENTATION);
92                         return 1;
93                 }
94                 return 0;
95         }
96
97         return 0;
98 }
99
100 static int hanvon_input_mapped(struct hid_device *hdev, struct hid_input *hi,
101                 struct hid_field *field, struct hid_usage *usage,
102                 unsigned long **bit, int *max)
103 {
104         if (usage->type == EV_KEY || usage->type == EV_ABS)
105                 clear_bit(usage->code, *bit);
106
107         return 0;
108 }
109
110
111 static int hanvon_event(struct hid_device *hid, struct hid_field *field,
112                                 struct hid_usage *usage, __s32 value)
113 {
114 //      struct hanvon_data *td = hid_get_drvdata(hid);
115
116         if (hid->claimed & HID_CLAIMED_INPUT) {
117                 struct input_dev *input = field->hidinput->input;
118                 switch (usage->hid) {
119                 case HID_DG_TIPSWITCH:
120                         input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, value);
121                         break;
122                 case HID_DG_INRANGE:
123                         input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, value);
124                         break;
125                 case HID_DG_CONFIDENCE:
126                         input_event(input, EV_ABS, ABS_MT_WIDTH_MAJOR, value);
127                         break;
128                 case HID_GD_X:
129                         input_event(input, EV_ABS, ABS_MT_POSITION_X, value);
130                         break;
131                 case HID_GD_Y:
132                         input_event(input, EV_ABS, ABS_MT_POSITION_Y, value);
133                         input_mt_sync(input);
134                         break;
135                 case HID_DG_CONTACTID:
136                         input_event(input, EV_ABS, ABS_MT_TRACKING_ID, value);
137                         break;
138                 case HID_DG_CONTACTCOUNT:
139                         input_event(input, EV_ABS, ABS_MT_WIDTH_MINOR, value);
140                         break;
141                 case HID_DG_CONTACTMAX:
142                         break;
143                         input_event(input, EV_ABS, ABS_MT_ORIENTATION, value);
144
145                 default:
146                         /* fallback to the generic hidinput handling */
147                         return 0;
148                 }
149         }
150
151         /* we have handled the hidinput part, now remains hiddev */
152         if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
153                 hid->hiddev_hid_event(hid, field, usage, value);
154
155         return 1;
156 }
157
158 static int hanvon_probe(struct hid_device *hdev, const struct hid_device_id *id)
159 {
160         int ret;
161         struct hanvon_data *td;
162
163
164         td = kmalloc(sizeof(struct hanvon_data), GFP_KERNEL);
165         if (!td) {
166                 dev_err(&hdev->dev, "cannot allocate Hanvon data\n");
167                 return -ENOMEM;
168         }
169         hid_set_drvdata(hdev, td);
170
171         ret = hid_parse(hdev);
172         if (ret == 0)
173                 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
174
175         if (ret)
176                 kfree(td);
177
178         return ret;
179 }
180
181 static void hanvon_remove(struct hid_device *hdev)
182 {
183         hid_hw_stop(hdev);
184         kfree(hid_get_drvdata(hdev));
185         hid_set_drvdata(hdev, NULL);
186 }
187
188 static const struct hid_device_id hanvon_devices[] = {
189         { HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) },
190         { }
191 };
192 MODULE_DEVICE_TABLE(hid, hanvon_devices);
193
194 static const struct hid_usage_id hanvon_grabbed_usages[] = {
195         { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
196         { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
197 };
198
199 static struct hid_driver hanvon_driver = {
200         .name = "hanvon",
201         .id_table = hanvon_devices,
202         .probe = hanvon_probe,
203         .remove = hanvon_remove,
204         .input_mapping = hanvon_input_mapping,
205         .input_mapped = hanvon_input_mapped,
206         .usage_table = hanvon_grabbed_usages,
207         .event = hanvon_event,
208 };
209
210 static int __init hanvon_init(void)
211 {
212         return hid_register_driver(&hanvon_driver);
213 }
214
215 static void __exit hanvon_exit(void)
216 {
217         hid_unregister_driver(&hanvon_driver);
218 }
219
220 module_init(hanvon_init);
221 module_exit(hanvon_exit);
222