Merge branch 'fix/hda' into for-linus
[pandora-kernel.git] / drivers / hid / hid-ntrig.c
1 /*
2  *  HID driver for N-Trig touchscreens
3  *
4  *  Copyright (c) 2008 Rafi Rubin
5  *  Copyright (c) 2009 Stephane Chatty
6  *
7  */
8
9 /*
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License as published by the Free
12  * Software Foundation; either version 2 of the License, or (at your option)
13  * any later version.
14  */
15
16 #include <linux/device.h>
17 #include <linux/hid.h>
18 #include <linux/module.h>
19 #include <linux/slab.h>
20
21 #include "hid-ids.h"
22
23 #define NTRIG_DUPLICATE_USAGES  0x001
24
25 #define nt_map_key_clear(c)     hid_map_usage_clear(hi, usage, bit, max, \
26                                         EV_KEY, (c))
27
28 struct ntrig_data {
29         /* Incoming raw values for a single contact */
30         __u16 x, y, w, h;
31         __u16 id;
32         __u8 confidence;
33
34         bool reading_mt;
35         __u8 first_contact_confidence;
36
37         __u8 mt_footer[4];
38         __u8 mt_foot_count;
39 };
40
41 /*
42  * this driver is aimed at two firmware versions in circulation:
43  *  - dual pen/finger single touch
44  *  - finger multitouch, pen not working
45  */
46
47 static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
48                 struct hid_field *field, struct hid_usage *usage,
49                 unsigned long **bit, int *max)
50 {
51         /* No special mappings needed for the pen and single touch */
52         if (field->physical)
53                 return 0;
54
55         switch (usage->hid & HID_USAGE_PAGE) {
56         case HID_UP_GENDESK:
57                 switch (usage->hid) {
58                 case HID_GD_X:
59                         hid_map_usage(hi, usage, bit, max,
60                                         EV_ABS, ABS_MT_POSITION_X);
61                         input_set_abs_params(hi->input, ABS_X,
62                                         field->logical_minimum,
63                                         field->logical_maximum, 0, 0);
64                         return 1;
65                 case HID_GD_Y:
66                         hid_map_usage(hi, usage, bit, max,
67                                         EV_ABS, ABS_MT_POSITION_Y);
68                         input_set_abs_params(hi->input, ABS_Y,
69                                         field->logical_minimum,
70                                         field->logical_maximum, 0, 0);
71                         return 1;
72                 }
73                 return 0;
74
75         case HID_UP_DIGITIZER:
76                 switch (usage->hid) {
77                 /* we do not want to map these for now */
78                 case HID_DG_CONTACTID: /* Not trustworthy, squelch for now */
79                 case HID_DG_INPUTMODE:
80                 case HID_DG_DEVICEINDEX:
81                 case HID_DG_CONTACTMAX:
82                         return -1;
83
84                 /* width/height mapped on TouchMajor/TouchMinor/Orientation */
85                 case HID_DG_WIDTH:
86                         hid_map_usage(hi, usage, bit, max,
87                                         EV_ABS, ABS_MT_TOUCH_MAJOR);
88                         return 1;
89                 case HID_DG_HEIGHT:
90                         hid_map_usage(hi, usage, bit, max,
91                                         EV_ABS, ABS_MT_TOUCH_MINOR);
92                         input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
93                                         0, 1, 0, 0);
94                         return 1;
95                 }
96                 return 0;
97
98         case 0xff000000:
99                 /* we do not want to map these: no input-oriented meaning */
100                 return -1;
101         }
102
103         return 0;
104 }
105
106 static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi,
107                 struct hid_field *field, struct hid_usage *usage,
108                 unsigned long **bit, int *max)
109 {
110         /* No special mappings needed for the pen and single touch */
111         if (field->physical)
112                 return 0;
113
114         if (usage->type == EV_KEY || usage->type == EV_REL
115                         || usage->type == EV_ABS)
116                 clear_bit(usage->code, *bit);
117
118         return 0;
119 }
120
121 /*
122  * this function is called upon all reports
123  * so that we can filter contact point information,
124  * decide whether we are in multi or single touch mode
125  * and call input_mt_sync after each point if necessary
126  */
127 static int ntrig_event (struct hid_device *hid, struct hid_field *field,
128                                         struct hid_usage *usage, __s32 value)
129 {
130         struct input_dev *input = field->hidinput->input;
131         struct ntrig_data *nd = hid_get_drvdata(hid);
132
133         /* No special handling needed for the pen */
134         if (field->application == HID_DG_PEN)
135                 return 0;
136
137         if (hid->claimed & HID_CLAIMED_INPUT) {
138                 switch (usage->hid) {
139                 case 0xff000001:
140                         /* Tag indicating the start of a multitouch group */
141                         nd->reading_mt = 1;
142                         nd->first_contact_confidence = 0;
143                         break;
144                 case HID_DG_TIPSWITCH:
145                         /* Prevent emission of touch until validated */
146                         return 1;
147                 case HID_DG_CONFIDENCE:
148                         nd->confidence = value;
149                         break;
150                 case HID_GD_X:
151                         nd->x = value;
152                         /* Clear the contact footer */
153                         nd->mt_foot_count = 0;
154                         break;
155                 case HID_GD_Y:
156                         nd->y = value;
157                         break;
158                 case HID_DG_CONTACTID:
159                         nd->id = value;
160                         break;
161                 case HID_DG_WIDTH:
162                         nd->w = value;
163                         break;
164                 case HID_DG_HEIGHT:
165                         nd->h = value;
166                         /*
167                          * when in single touch mode, this is the last
168                          * report received in a finger event. We want
169                          * to emit a normal (X, Y) position
170                          */
171                         if (!nd->reading_mt) {
172                                 input_report_key(input, BTN_TOOL_DOUBLETAP,
173                                                  (nd->confidence != 0));
174                                 input_event(input, EV_ABS, ABS_X, nd->x);
175                                 input_event(input, EV_ABS, ABS_Y, nd->y);
176                         }
177                         break;
178                 case 0xff000002:
179                         /*
180                          * we receive this when the device is in multitouch
181                          * mode. The first of the three values tagged with
182                          * this usage tells if the contact point is real
183                          * or a placeholder
184                          */
185
186                         /* Shouldn't get more than 4 footer packets, so skip */
187                         if (nd->mt_foot_count >= 4)
188                                 break;
189
190                         nd->mt_footer[nd->mt_foot_count++] = value;
191
192                         /* if the footer isn't complete break */
193                         if (nd->mt_foot_count != 4)
194                                 break;
195
196                         /* Pen activity signal, trigger end of touch. */
197                         if (nd->mt_footer[2]) {
198                                 nd->confidence = 0;
199                                 break;
200                         }
201
202                         /* If the contact was invalid */
203                         if (!(nd->confidence && nd->mt_footer[0])
204                                         || nd->w <= 250
205                                         || nd->h <= 190) {
206                                 nd->confidence = 0;
207                                 break;
208                         }
209
210                         /* emit a normal (X, Y) for the first point only */
211                         if (nd->id == 0) {
212                                 nd->first_contact_confidence = nd->confidence;
213                                 input_event(input, EV_ABS, ABS_X, nd->x);
214                                 input_event(input, EV_ABS, ABS_Y, nd->y);
215                         }
216                         input_event(input, EV_ABS, ABS_MT_POSITION_X, nd->x);
217                         input_event(input, EV_ABS, ABS_MT_POSITION_Y, nd->y);
218                         if (nd->w > nd->h) {
219                                 input_event(input, EV_ABS,
220                                                 ABS_MT_ORIENTATION, 1);
221                                 input_event(input, EV_ABS,
222                                                 ABS_MT_TOUCH_MAJOR, nd->w);
223                                 input_event(input, EV_ABS,
224                                                 ABS_MT_TOUCH_MINOR, nd->h);
225                         } else {
226                                 input_event(input, EV_ABS,
227                                                 ABS_MT_ORIENTATION, 0);
228                                 input_event(input, EV_ABS,
229                                                 ABS_MT_TOUCH_MAJOR, nd->h);
230                                 input_event(input, EV_ABS,
231                                                 ABS_MT_TOUCH_MINOR, nd->w);
232                         }
233                         input_mt_sync(field->hidinput->input);
234                         break;
235
236                 case HID_DG_CONTACTCOUNT: /* End of a multitouch group */
237                         if (!nd->reading_mt)
238                                 break;
239
240                         nd->reading_mt = 0;
241
242                         if (nd->first_contact_confidence) {
243                                 switch (value) {
244                                 case 0: /* for single touch devices */
245                                 case 1:
246                                         input_report_key(input,
247                                                         BTN_TOOL_DOUBLETAP, 1);
248                                         break;
249                                 case 2:
250                                         input_report_key(input,
251                                                         BTN_TOOL_TRIPLETAP, 1);
252                                         break;
253                                 case 3:
254                                 default:
255                                         input_report_key(input,
256                                                         BTN_TOOL_QUADTAP, 1);
257                                 }
258                                 input_report_key(input, BTN_TOUCH, 1);
259                         } else {
260                                 input_report_key(input,
261                                                 BTN_TOOL_DOUBLETAP, 0);
262                                 input_report_key(input,
263                                                 BTN_TOOL_TRIPLETAP, 0);
264                                 input_report_key(input,
265                                                 BTN_TOOL_QUADTAP, 0);
266                                 input_report_key(input, BTN_TOUCH, 0);
267                         }
268                         break;
269
270                 default:
271                         /* fallback to the generic hidinput handling */
272                         return 0;
273                 }
274         }
275
276         /* we have handled the hidinput part, now remains hiddev */
277         if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_hid_event)
278                 hid->hiddev_hid_event(hid, field, usage, value);
279
280         return 1;
281 }
282
283 static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
284 {
285         int ret;
286         struct ntrig_data *nd;
287         struct hid_input *hidinput;
288         struct input_dev *input;
289
290         if (id->driver_data)
291                 hdev->quirks |= HID_QUIRK_MULTI_INPUT;
292
293         nd = kmalloc(sizeof(struct ntrig_data), GFP_KERNEL);
294         if (!nd) {
295                 dev_err(&hdev->dev, "cannot allocate N-Trig data\n");
296                 return -ENOMEM;
297         }
298
299         nd->reading_mt = 0;
300         hid_set_drvdata(hdev, nd);
301
302         ret = hid_parse(hdev);
303         if (ret) {
304                 dev_err(&hdev->dev, "parse failed\n");
305                 goto err_free;
306         }
307
308         ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
309         if (ret) {
310                 dev_err(&hdev->dev, "hw start failed\n");
311                 goto err_free;
312         }
313
314
315         list_for_each_entry(hidinput, &hdev->inputs, list) {
316                 if (hidinput->report->maxfield < 1)
317                         continue;
318
319                 input = hidinput->input;
320                 switch (hidinput->report->field[0]->application) {
321                 case HID_DG_PEN:
322                         input->name = "N-Trig Pen";
323                         break;
324                 case HID_DG_TOUCHSCREEN:
325                         /* These keys are redundant for fingers, clear them
326                          * to prevent incorrect identification */
327                         __clear_bit(BTN_TOOL_PEN, input->keybit);
328                         __clear_bit(BTN_TOOL_FINGER, input->keybit);
329                         __clear_bit(BTN_0, input->keybit);
330                         /*
331                          * A little something special to enable
332                          * two and three finger taps.
333                          */
334                         __set_bit(BTN_TOOL_DOUBLETAP, input->keybit);
335                         __set_bit(BTN_TOOL_TRIPLETAP, input->keybit);
336                         __set_bit(BTN_TOOL_QUADTAP, input->keybit);
337                         /*
338                          * The physical touchscreen (single touch)
339                          * input has a value for physical, whereas
340                          * the multitouch only has logical input
341                          * fields.
342                          */
343                         input->name =
344                                 (hidinput->report->field[0]
345                                  ->physical) ?
346                                 "N-Trig Touchscreen" :
347                                 "N-Trig MultiTouch";
348                         break;
349                 }
350         }
351
352         return 0;
353 err_free:
354         kfree(nd);
355         return ret;
356 }
357
358 static void ntrig_remove(struct hid_device *hdev)
359 {
360         hid_hw_stop(hdev);
361         kfree(hid_get_drvdata(hdev));
362 }
363
364 static const struct hid_device_id ntrig_devices[] = {
365         { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN),
366                 .driver_data = NTRIG_DUPLICATE_USAGES },
367         { }
368 };
369 MODULE_DEVICE_TABLE(hid, ntrig_devices);
370
371 static const struct hid_usage_id ntrig_grabbed_usages[] = {
372         { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
373         { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1 }
374 };
375
376 static struct hid_driver ntrig_driver = {
377         .name = "ntrig",
378         .id_table = ntrig_devices,
379         .probe = ntrig_probe,
380         .remove = ntrig_remove,
381         .input_mapping = ntrig_input_mapping,
382         .input_mapped = ntrig_input_mapped,
383         .usage_table = ntrig_grabbed_usages,
384         .event = ntrig_event,
385 };
386
387 static int __init ntrig_init(void)
388 {
389         return hid_register_driver(&ntrig_driver);
390 }
391
392 static void __exit ntrig_exit(void)
393 {
394         hid_unregister_driver(&ntrig_driver);
395 }
396
397 module_init(ntrig_init);
398 module_exit(ntrig_exit);
399 MODULE_LICENSE("GPL");