hid: egalax: Correct for device resolution report error
[pandora-kernel.git] / drivers / hid / hid-egalax.c
1 /*
2  *  HID driver for eGalax dual-touch panels
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/usb.h>
19 #include <linux/slab.h>
20 #include "usbhid/usbhid.h"
21
22 MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
23 MODULE_DESCRIPTION("eGalax dual-touch panel");
24 MODULE_LICENSE("GPL");
25
26 #include "hid-ids.h"
27
28 struct egalax_data {
29         __u16 x, y, z;
30         __u8 id;
31         bool first;             /* is this the first finger in the frame? */
32         bool valid;             /* valid finger data, or just placeholder? */
33         bool activity;          /* at least one active finger previously? */
34         __u16 lastx, lasty, lastz;      /* latest valid (x, y, z) in the frame */
35 };
36
37 static void set_abs(struct input_dev *input, unsigned int code,
38                     struct hid_field *field, int snratio)
39 {
40         int fmin = field->logical_minimum;
41         int fmax = field->logical_maximum;
42         int fuzz = snratio ? (fmax - fmin) / snratio : 0;
43         input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
44 }
45
46 static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi,
47                 struct hid_field *field, struct hid_usage *usage,
48                 unsigned long **bit, int *max)
49 {
50         struct input_dev *input = hi->input;
51
52         switch (usage->hid & HID_USAGE_PAGE) {
53
54         case HID_UP_GENDESK:
55                 switch (usage->hid) {
56                 case HID_GD_X:
57                         field->logical_maximum = 32760;
58                         hid_map_usage(hi, usage, bit, max,
59                                         EV_ABS, ABS_MT_POSITION_X);
60                         set_abs(input, ABS_MT_POSITION_X, field, 0);
61                         /* touchscreen emulation */
62                         set_abs(input, ABS_X, field, 0);
63                         return 1;
64                 case HID_GD_Y:
65                         field->logical_maximum = 32760;
66                         hid_map_usage(hi, usage, bit, max,
67                                         EV_ABS, ABS_MT_POSITION_Y);
68                         set_abs(input, ABS_MT_POSITION_Y, field, 0);
69                         /* touchscreen emulation */
70                         set_abs(input, ABS_Y, field, 0);
71                         return 1;
72                 }
73                 return 0;
74
75         case HID_UP_DIGITIZER:
76                 switch (usage->hid) {
77                 case HID_DG_TIPSWITCH:
78                         /* touchscreen emulation */
79                         hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
80                         input_set_capability(input, EV_KEY, BTN_TOUCH);
81                         return 1;
82                 case HID_DG_INRANGE:
83                 case HID_DG_CONFIDENCE:
84                 case HID_DG_CONTACTCOUNT:
85                 case HID_DG_CONTACTMAX:
86                         return -1;
87                 case HID_DG_CONTACTID:
88                         hid_map_usage(hi, usage, bit, max,
89                                         EV_ABS, ABS_MT_TRACKING_ID);
90                         set_abs(input, ABS_MT_TRACKING_ID, field, 0);
91                         return 1;
92                 case HID_DG_TIPPRESSURE:
93                         hid_map_usage(hi, usage, bit, max,
94                                         EV_ABS, ABS_MT_PRESSURE);
95                         set_abs(input, ABS_MT_PRESSURE, field, 0);
96                         /* touchscreen emulation */
97                         set_abs(input, ABS_PRESSURE, field, 0);
98                         return 1;
99                 }
100                 return 0;
101         }
102
103         /* ignore others (from other reports we won't get anyway) */
104         return -1;
105 }
106
107 static int egalax_input_mapped(struct hid_device *hdev, struct hid_input *hi,
108                 struct hid_field *field, struct hid_usage *usage,
109                 unsigned long **bit, int *max)
110 {
111         /* tell hid-input to skip setup of these event types */
112         if (usage->type == EV_KEY || usage->type == EV_ABS)
113                 set_bit(usage->type, hi->input->evbit);
114         return -1;
115 }
116
117 /*
118  * this function is called when a whole finger has been parsed,
119  * so that it can decide what to send to the input layer.
120  */
121 static void egalax_filter_event(struct egalax_data *td, struct input_dev *input)
122 {
123         td->first = !td->first; /* touchscreen emulation */
124
125         if (td->valid) {
126                 /* emit multitouch events */
127                 input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id);
128                 input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x >> 3);
129                 input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y >> 3);
130                 input_event(input, EV_ABS, ABS_MT_PRESSURE, td->z);
131
132                 input_mt_sync(input);
133
134                 /*
135                  * touchscreen emulation: store (x, y) as
136                  * the last valid values in this frame
137                  */
138                 td->lastx = td->x;
139                 td->lasty = td->y;
140                 td->lastz = td->z;
141         }
142
143         /*
144          * touchscreen emulation: if this is the second finger and at least
145          * one in this frame is valid, the latest valid in the frame is
146          * the oldest on the panel, the one we want for single touch
147          */
148         if (!td->first && td->activity) {
149                 input_event(input, EV_ABS, ABS_X, td->lastx >> 3);
150                 input_event(input, EV_ABS, ABS_Y, td->lasty >> 3);
151                 input_event(input, EV_ABS, ABS_PRESSURE, td->lastz);
152         }
153
154         if (!td->valid) {
155                 /*
156                  * touchscreen emulation: if the first finger is invalid
157                  * and there previously was finger activity, this is a release
158                  */ 
159                 if (td->first && td->activity) {
160                         input_event(input, EV_KEY, BTN_TOUCH, 0);
161                         td->activity = false;
162                 }
163                 return;
164         }
165
166
167         /* touchscreen emulation: if no previous activity, emit touch event */
168         if (!td->activity) {
169                 input_event(input, EV_KEY, BTN_TOUCH, 1);
170                 td->activity = true;
171         }
172 }
173
174
175 static int egalax_event(struct hid_device *hid, struct hid_field *field,
176                                 struct hid_usage *usage, __s32 value)
177 {
178         struct egalax_data *td = hid_get_drvdata(hid);
179
180         /* Note, eGalax has two product lines: the first is resistive and
181          * uses a standard parallel multitouch protocol (product ID ==
182          * 48xx).  The second is capacitive and uses an unusual "serial"
183          * protocol with a different message for each multitouch finger
184          * (product ID == 72xx).  We do not yet generate a correct event
185          * sequence for the capacitive/serial protocol.
186          */
187         if (hid->claimed & HID_CLAIMED_INPUT) {
188                 struct input_dev *input = field->hidinput->input;
189
190                 switch (usage->hid) {
191                 case HID_DG_INRANGE:
192                 case HID_DG_CONFIDENCE:
193                         /* avoid interference from generic hidinput handling */
194                         break;
195                 case HID_DG_TIPSWITCH:
196                         td->valid = value;
197                         break;
198                 case HID_DG_TIPPRESSURE:
199                         td->z = value;
200                         break;
201                 case HID_DG_CONTACTID:
202                         td->id = value;
203                         break;
204                 case HID_GD_X:
205                         td->x = value;
206                         break;
207                 case HID_GD_Y:
208                         td->y = value;
209                         /* this is the last field in a finger */
210                         egalax_filter_event(td, input);
211                         break;
212                 case HID_DG_CONTACTCOUNT:
213                         /* touch emulation: this is the last field in a frame */
214                         td->first = false;
215                         break;
216
217                 default:
218                         /* fallback to the generic hidinput handling */
219                         return 0;
220                 }
221         }
222
223         /* we have handled the hidinput part, now remains hiddev */
224         if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
225                 hid->hiddev_hid_event(hid, field, usage, value);
226
227         return 1;
228 }
229
230 static int egalax_probe(struct hid_device *hdev, const struct hid_device_id *id)
231 {
232         int ret;
233         struct egalax_data *td;
234         struct hid_report *report;
235
236         td = kmalloc(sizeof(struct egalax_data), GFP_KERNEL);
237         if (!td) {
238                 dev_err(&hdev->dev, "cannot allocate eGalax data\n");
239                 return -ENOMEM;
240         }
241         hid_set_drvdata(hdev, td);
242
243         ret = hid_parse(hdev);
244         if (ret)
245                 goto end;
246
247         ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
248         if (ret)
249                 goto end;
250
251         report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[5]; 
252         if (report) {
253                 report->field[0]->value[0] = 2;
254                 usbhid_submit_report(hdev, report, USB_DIR_OUT);
255         }
256
257 end:
258         if (ret)
259                 kfree(td);
260
261         return ret;
262 }
263
264 static void egalax_remove(struct hid_device *hdev)
265 {
266         hid_hw_stop(hdev);
267         kfree(hid_get_drvdata(hdev));
268         hid_set_drvdata(hdev, NULL);
269 }
270
271 static const struct hid_device_id egalax_devices[] = {
272         { HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
273                         USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
274         { HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
275                         USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
276         { }
277 };
278 MODULE_DEVICE_TABLE(hid, egalax_devices);
279
280 static const struct hid_usage_id egalax_grabbed_usages[] = {
281         { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
282         { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
283 };
284
285 static struct hid_driver egalax_driver = {
286         .name = "egalax-touch",
287         .id_table = egalax_devices,
288         .probe = egalax_probe,
289         .remove = egalax_remove,
290         .input_mapping = egalax_input_mapping,
291         .input_mapped = egalax_input_mapped,
292         .usage_table = egalax_grabbed_usages,
293         .event = egalax_event,
294 };
295
296 static int __init egalax_init(void)
297 {
298         return hid_register_driver(&egalax_driver);
299 }
300
301 static void __exit egalax_exit(void)
302 {
303         hid_unregister_driver(&egalax_driver);
304 }
305
306 module_init(egalax_init);
307 module_exit(egalax_exit);
308