]> code.ossystems Code Review - openembedded-core.git/blob
6f8aaca07eeab8be95ad298877889b9a587f2674
[openembedded-core.git] /
1 From f7e13f4d9a7a9025244b37a3ad188af7dae841d9 Mon Sep 17 00:00:00 2001
2 From: Stephane Chatty <chatty@enac.fr>
3 Date: Fri, 9 Apr 2010 15:33:54 -0700
4 Subject: [PATCH 105/105] Stantum and Mosart multitouch drivers 
5
6 HID Driver and configs for Stantum and Mosart multitouch panels.
7
8 Patch-mainline: 2.6.34
9
10 Signed-off-by: Stephane Chatty <chatty@enac.fr>
11 Signed-off-by: Jiri Kosina <jkosina@suse.cz>
12 Signed-off-by: Priya Vijayan <priya.vijayan@intel.com>
13 ---
14  drivers/hid/Kconfig       |   12 ++
15  drivers/hid/Makefile      |    3 +-
16  drivers/hid/hid-core.c    |    7 +-
17  drivers/hid/hid-ids.h     |   15 ++-
18  drivers/hid/hid-mosart.c  |  274 +++++++++++++++++++++++++++++++++++++++++++
19  drivers/hid/hid-stantum.c |  285 +++++++++++++++++++++++++++++++++++++++++++++
20  6 files changed, 590 insertions(+), 6 deletions(-)
21  create mode 100644 drivers/hid/hid-mosart.c
22  create mode 100644 drivers/hid/hid-stantum.c
23
24 diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
25 index 37fb241..55906bc 100644
26 --- a/drivers/hid/Kconfig
27 +++ b/drivers/hid/Kconfig
28 @@ -203,6 +203,12 @@ config HID_MONTEREY
29         ---help---
30         Support for Monterey Genius KB29E.
31  
32 +config HID_MOSART
33 +       tristate "MosArt"
34 +       depends on USB_HID
35 +       ---help---
36 +       Support for MosArt dual-touch panels.
37 +
38  config HID_NTRIG
39         tristate "NTrig" if EMBEDDED
40         depends on USB_HID
41 @@ -247,6 +253,12 @@ config HID_SONY
42         ---help---
43         Support for Sony PS3 controller.
44  
45 +config HID_STANTUM
46 +       tristate "Stantum"
47 +       depends on USB_HID
48 +       ---help---      
49 +       Support for Stantum multitouch panel.
50 +
51  config HID_SUNPLUS
52         tristate "Sunplus" if EMBEDDED
53         depends on USB_HID
54 diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
55 index b05f921..bbda0b0 100644
56 --- a/drivers/hid/Makefile
57 +++ b/drivers/hid/Makefile
58 @@ -34,12 +34,14 @@ obj-$(CONFIG_HID_KYE)               += hid-kye.o
59  obj-$(CONFIG_HID_LOGITECH)     += hid-logitech.o
60  obj-$(CONFIG_HID_MICROSOFT)    += hid-microsoft.o
61  obj-$(CONFIG_HID_MONTEREY)     += hid-monterey.o
62 +obj-$(CONFIG_HID_MOSART)        += hid-mosart.o
63  obj-$(CONFIG_HID_NTRIG)                += hid-ntrig.o
64  obj-$(CONFIG_HID_PANTHERLORD)  += hid-pl.o
65  obj-$(CONFIG_HID_PETALYNX)     += hid-petalynx.o
66  obj-$(CONFIG_HID_SAMSUNG)      += hid-samsung.o
67  obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
68  obj-$(CONFIG_HID_SONY)         += hid-sony.o
69 +obj-$(CONFIG_HID_STANTUM)       += hid-stantum.o
70  obj-$(CONFIG_HID_SUNPLUS)      += hid-sunplus.o
71  obj-$(CONFIG_HID_GREENASIA)    += hid-gaff.o
72  obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o
73 @@ -51,4 +53,3 @@ obj-$(CONFIG_HID_WACOM)               += hid-wacom.o
74  obj-$(CONFIG_USB_HID)          += usbhid/
75  obj-$(CONFIG_USB_MOUSE)                += usbhid/
76  obj-$(CONFIG_USB_KBD)          += usbhid/
77 -
78 diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
79 index b126102..fbf6f3e 100644
80 --- a/drivers/hid/hid-core.c
81 +++ b/drivers/hid/hid-core.c
82 @@ -1342,6 +1342,9 @@ static const struct hid_device_id hid_blacklist[] = {
83         { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
84         { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
85         { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
86 +       { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) },
87 +       { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM2, USB_DEVICE_ID_MTP2) },
88 +       { HID_USB_DEVICE(USB_VENDOR_ID_STMICRO, USB_DEVICE_ID_STMICRO_MTP1) },
89         { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
90         { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
91         { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
92 @@ -1544,8 +1546,9 @@ static const struct hid_device_id hid_ignore_list[] = {
93         { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24) },
94         { HID_USB_DEVICE(USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1) },
95         { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) },
96 -       { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM)},
97 -       { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2)},
98 +       { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT)},
99 +       { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM)},
100 +       { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM2)},
101         { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) },
102         { HID_USB_DEVICE(USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD) },
103         { HID_USB_DEVICE(USB_VENDOR_ID_CIDC, 0x0103) },
104 diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
105 index 6865ca2..92c8a78 100644
106 --- a/drivers/hid/hid-ids.h
107 +++ b/drivers/hid/hid-ids.h
108 @@ -96,9 +96,12 @@
109  #define USB_DEVICE_ID_APPLE_ATV_IRCONTROL      0x8241
110  #define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242
111  
112 -#define USB_VENDOR_ID_ASUS             0x0b05
113 -#define USB_DEVICE_ID_ASUS_LCM         0x1726
114 -#define USB_DEVICE_ID_ASUS_LCM2                0x175b
115 +#define USB_VENDOR_ID_ASUS                     0x0486
116 +#define USB_DEVICE_ID_ASUS_T91MT        0x0185
117 +
118 +#define USB_VENDOR_ID_ASUSTEK                  0x0b05
119 +#define USB_DEVICE_ID_ASUSTEK_LCM              0x1726
120 +#define USB_DEVICE_ID_ASUSTEK_LCM2             0x175b
121  
122  #define USB_VENDOR_ID_ATEN             0x0557
123  #define USB_DEVICE_ID_ATEN_UC100KM     0x2004
124 @@ -399,6 +402,15 @@
125  #define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST    0x0034
126  #define USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST     0x0046
127  
128 +#define USB_VENDOR_ID_STANTUM           0x1f87
129 +#define USB_DEVICE_ID_MTP               0x0002
130 +
131 +#define USB_VENDOR_ID_STANTUM2          0x1f87
132 +#define USB_DEVICE_ID_MTP2              0x0001
133 +
134 +#define USB_VENDOR_ID_STMICRO           0x0483
135 +#define USB_DEVICE_ID_STMICRO_MTP1      0x3261
136 +
137  #define USB_VENDOR_ID_SUN              0x0430
138  #define USB_DEVICE_ID_RARITAN_KVM_DONGLE       0xcdab
139  
140 diff --git a/drivers/hid/hid-mosart.c b/drivers/hid/hid-mosart.c
141 new file mode 100644
142 index 0000000..e91437c
143 --- /dev/null
144 +++ b/drivers/hid/hid-mosart.c
145 @@ -0,0 +1,274 @@
146 +/*
147 + *  HID driver for the multitouch panel on the ASUS EeePC T91MT
148 + *
149 + *  Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
150 + *  Copyright (c) 2010 Teemu Tuominen <teemu.tuominen@cybercom.com>
151 + *
152 + */
153 +
154 +/*
155 + * This program is free software; you can redistribute it and/or modify it
156 + * under the terms of the GNU General Public License as published by the Free
157 + * Software Foundation; either version 2 of the License, or (at your option)
158 + * any later version.
159 + */
160 +
161 +#include <linux/device.h>
162 +#include <linux/hid.h>
163 +#include <linux/module.h>
164 +#include <linux/slab.h>
165 +#include <linux/usb.h>
166 +#include "usbhid/usbhid.h"
167 +
168 +MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
169 +MODULE_DESCRIPTION("MosArt dual-touch panel");
170 +MODULE_LICENSE("GPL");
171 +
172 +#include "hid-ids.h"
173 +
174 +struct mosart_data {
175 +       __u16 x, y;
176 +       __u8 id;
177 +       bool valid;             /* valid finger data, or just placeholder? */
178 +       bool first;             /* is this the first finger in this frame? */
179 +       bool activity_now;      /* at least one active finger in this frame? */
180 +       bool activity;          /* at least one active finger previously? */
181 +};
182 +
183 +static int mosart_input_mapping(struct hid_device *hdev, struct hid_input *hi,
184 +               struct hid_field *field, struct hid_usage *usage,
185 +               unsigned long **bit, int *max)
186 +{
187 +       switch (usage->hid & HID_USAGE_PAGE) {
188 +
189 +       case HID_UP_GENDESK:
190 +               switch (usage->hid) {
191 +               case HID_GD_X:
192 +                       hid_map_usage(hi, usage, bit, max,
193 +                                       EV_ABS, ABS_MT_POSITION_X);
194 +                       /* touchscreen emulation */
195 +                       input_set_abs_params(hi->input, ABS_X,
196 +                                               field->logical_minimum,
197 +                                               field->logical_maximum, 0, 0);
198 +                       return 1;
199 +               case HID_GD_Y:
200 +                       hid_map_usage(hi, usage, bit, max,
201 +                                       EV_ABS, ABS_MT_POSITION_Y);
202 +                       /* touchscreen emulation */
203 +                       input_set_abs_params(hi->input, ABS_Y,
204 +                                               field->logical_minimum,
205 +                                               field->logical_maximum, 0, 0);
206 +                       return 1;
207 +               }
208 +               return 0;
209 +
210 +       case HID_UP_DIGITIZER:
211 +               switch (usage->hid) {
212 +               case HID_DG_CONFIDENCE:
213 +               case HID_DG_TIPSWITCH:
214 +               case HID_DG_INPUTMODE:
215 +               case HID_DG_DEVICEINDEX:
216 +               case HID_DG_CONTACTCOUNT:
217 +               case HID_DG_CONTACTMAX:
218 +               case HID_DG_TIPPRESSURE:
219 +               case HID_DG_WIDTH:
220 +               case HID_DG_HEIGHT:
221 +                       return -1;
222 +               case HID_DG_INRANGE:
223 +                       /* touchscreen emulation */
224 +                       hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
225 +                       return 1;
226 +
227 +               case HID_DG_CONTACTID:
228 +                       hid_map_usage(hi, usage, bit, max,
229 +                                       EV_ABS, ABS_MT_TRACKING_ID);
230 +                       return 1;
231 +
232 +               }
233 +               return 0;
234 +
235 +       case 0xff000000:
236 +               /* ignore HID features */
237 +               return -1;
238 +       }
239 +
240 +       return 0;
241 +}
242 +
243 +static int mosart_input_mapped(struct hid_device *hdev, struct hid_input *hi,
244 +               struct hid_field *field, struct hid_usage *usage,
245 +               unsigned long **bit, int *max)
246 +{
247 +       if (usage->type == EV_KEY || usage->type == EV_ABS)
248 +               clear_bit(usage->code, *bit);
249 +
250 +       return 0;
251 +}
252 +
253 +/*
254 + * this function is called when a whole finger has been parsed,
255 + * so that it can decide what to send to the input layer.
256 + */
257 +static void mosart_filter_event(struct mosart_data *td, struct input_dev *input)
258 +{
259 +       td->first = !td->first; /* touchscreen emulation */
260 +
261 +       if (!td->valid) {
262 +               /*
263 +                * touchscreen emulation: if no finger in this frame is valid
264 +                * and there previously was finger activity, this is a release
265 +                */ 
266 +               if (!td->first && !td->activity_now && td->activity) {
267 +                       input_event(input, EV_KEY, BTN_TOUCH, 0);
268 +                       td->activity = false;
269 +               }
270 +               return;
271 +       }
272 +
273 +       input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id);
274 +       input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
275 +       input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);
276 +
277 +       input_mt_sync(input);
278 +       td->valid = false;
279 +
280 +       /* touchscreen emulation: if first active finger in this frame... */
281 +       if (!td->activity_now) {
282 +               /* if there was no previous activity, emit touch event */
283 +               if (!td->activity) {
284 +                       input_event(input, EV_KEY, BTN_TOUCH, 1);
285 +                       td->activity = true;
286 +               }
287 +               td->activity_now = true;
288 +               /* and in any case this is our preferred finger */
289 +               input_event(input, EV_ABS, ABS_X, td->x);
290 +               input_event(input, EV_ABS, ABS_Y, td->y);
291 +       }
292 +}
293 +
294 +
295 +static int mosart_event(struct hid_device *hid, struct hid_field *field,
296 +                               struct hid_usage *usage, __s32 value)
297 +{
298 +       struct mosart_data *td = hid_get_drvdata(hid);
299 +
300 +       if (hid->claimed & HID_CLAIMED_INPUT) {
301 +               struct input_dev *input = field->hidinput->input;
302 +               switch (usage->hid) {
303 +               case HID_DG_INRANGE:
304 +                       td->valid = !!value;
305 +                       break;
306 +               case HID_GD_X:
307 +                       td->x = value;
308 +                       break;
309 +               case HID_GD_Y:
310 +                       td->y = value;
311 +                       mosart_filter_event(td, input);
312 +                       break;
313 +               case HID_DG_CONTACTID:
314 +                       td->id = value;
315 +                       break;
316 +               case HID_DG_CONTACTCOUNT:
317 +                       /* touch emulation: this is the last field in a frame */
318 +                       td->first = false;
319 +                       td->activity_now = false;
320 +                       break;
321 +               case HID_DG_CONFIDENCE:
322 +               case HID_DG_TIPSWITCH:
323 +                       /* avoid interference from generic hidinput handling */
324 +                       break;
325 +
326 +               default:
327 +                       /* fallback to the generic hidinput handling */
328 +                       return 0;
329 +               }
330 +       }
331 +
332 +       /* we have handled the hidinput part, now remains hiddev */
333 +       if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
334 +               hid->hiddev_hid_event(hid, field, usage, value);
335 +
336 +       return 1;
337 +}
338 +
339 +static int mosart_probe(struct hid_device *hdev, const struct hid_device_id *id)
340 +{
341 +       int ret;
342 +       struct mosart_data *td;
343 +
344 +
345 +       td = kmalloc(sizeof(struct mosart_data), GFP_KERNEL);
346 +       if (!td) {
347 +               dev_err(&hdev->dev, "cannot allocate MosArt data\n");
348 +               return -ENOMEM;
349 +       }
350 +       td->valid = false;
351 +       td->activity = false;
352 +       td->activity_now = false;
353 +       td->first = false;
354 +       hid_set_drvdata(hdev, td);
355 +
356 +       /* currently, it's better to have one evdev device only */
357 +#if 0
358 +       hdev->quirks |= HID_QUIRK_MULTI_INPUT;
359 +#endif
360 +
361 +       ret = hid_parse(hdev);
362 +       if (ret == 0)
363 +               ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
364 +
365 +       if (ret == 0) {
366 +               struct hid_report_enum *re = hdev->report_enum
367 +                                               + HID_FEATURE_REPORT;
368 +               struct hid_report *r = re->report_id_hash[7];
369 +
370 +               r->field[0]->value[0] = 0x02;
371 +               usbhid_submit_report(hdev, r, USB_DIR_OUT);
372 +       } else 
373 +               kfree(td);
374 +
375 +       return ret;
376 +}
377 +
378 +static void mosart_remove(struct hid_device *hdev)
379 +{
380 +       hid_hw_stop(hdev);
381 +       kfree(hid_get_drvdata(hdev));
382 +       hid_set_drvdata(hdev, NULL);
383 +}
384 +
385 +static const struct hid_device_id mosart_devices[] = {
386 +       { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) },
387 +       { }
388 +};
389 +MODULE_DEVICE_TABLE(hid, mosart_devices);
390 +
391 +static const struct hid_usage_id mosart_grabbed_usages[] = {
392 +       { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
393 +       { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
394 +};
395 +
396 +static struct hid_driver mosart_driver = {
397 +       .name = "mosart",
398 +       .id_table = mosart_devices,
399 +       .probe = mosart_probe,
400 +       .remove = mosart_remove,
401 +       .input_mapping = mosart_input_mapping,
402 +       .input_mapped = mosart_input_mapped,
403 +       .usage_table = mosart_grabbed_usages,
404 +       .event = mosart_event,
405 +};
406 +
407 +static int __init mosart_init(void)
408 +{
409 +       return hid_register_driver(&mosart_driver);
410 +}
411 +
412 +static void __exit mosart_exit(void)
413 +{
414 +       hid_unregister_driver(&mosart_driver);
415 +}
416 +
417 +module_init(mosart_init);
418 +module_exit(mosart_exit);
419 +
420 diff --git a/drivers/hid/hid-stantum.c b/drivers/hid/hid-stantum.c
421 new file mode 100644
422 index 0000000..bb4430f
423 --- /dev/null
424 +++ b/drivers/hid/hid-stantum.c
425 @@ -0,0 +1,286 @@
426 +/*
427 + *  HID driver for Stantum multitouch panels
428 + *
429 + *  Copyright (c) 2009 Stephane Chatty <chatty@enac.fr>
430 + *
431 + */
432 +
433 +/*
434 + * This program is free software; you can redistribute it and/or modify it
435 + * under the terms of the GNU General Public License as published by the Free
436 + * Software Foundation; either version 2 of the License, or (at your option)
437 + * any later version.
438 + */
439 +
440 +#include <linux/device.h>
441 +#include <linux/hid.h>
442 +#include <linux/module.h>
443 +#include <linux/slab.h>
444 +
445 +MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
446 +MODULE_DESCRIPTION("Stantum HID multitouch panels");
447 +MODULE_LICENSE("GPL");
448 +
449 +#include "hid-ids.h"
450 +
451 +struct stantum_data {
452 +       __s32 x, y, z, w, h;    /* x, y, pressure, width, height */
453 +       __u16 id;               /* touch id */
454 +       bool valid;             /* valid finger data, or just placeholder? */
455 +       bool first;             /* first finger in the HID packet? */
456 +       bool activity;          /* at least one active finger so far? */
457 +};
458 +
459 +static int stantum_input_mapping(struct hid_device *hdev, struct hid_input *hi,
460 +               struct hid_field *field, struct hid_usage *usage,
461 +               unsigned long **bit, int *max)
462 +{
463 +       switch (usage->hid & HID_USAGE_PAGE) {
464 +
465 +       case HID_UP_GENDESK:
466 +               switch (usage->hid) {
467 +               case HID_GD_X:
468 +                       hid_map_usage(hi, usage, bit, max,
469 +                                       EV_ABS, ABS_MT_POSITION_X);
470 +                       /* touchscreen emulation */
471 +                       input_set_abs_params(hi->input, ABS_X,
472 +                                               field->logical_minimum,
473 +                                               field->logical_maximum, 0, 0);
474 +                       return 1;
475 +               case HID_GD_Y:
476 +                       hid_map_usage(hi, usage, bit, max,
477 +                                       EV_ABS, ABS_MT_POSITION_Y);
478 +                       /* touchscreen emulation */
479 +                       input_set_abs_params(hi->input, ABS_Y,
480 +                                               field->logical_minimum,
481 +                                               field->logical_maximum, 0, 0);
482 +                       return 1;
483 +               }
484 +               return 0;
485 +
486 +       case HID_UP_DIGITIZER:
487 +               switch (usage->hid) {
488 +               case HID_DG_INRANGE:
489 +               case HID_DG_CONFIDENCE:
490 +               case HID_DG_INPUTMODE:
491 +               case HID_DG_DEVICEINDEX:
492 +               case HID_DG_CONTACTCOUNT:
493 +               case HID_DG_CONTACTMAX:
494 +                       return -1;
495 +
496 +               case HID_DG_TIPSWITCH:
497 +                       /* touchscreen emulation */
498 +                       hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
499 +                       return 1;
500 +
501 +               case HID_DG_WIDTH:
502 +                       hid_map_usage(hi, usage, bit, max,
503 +                                       EV_ABS, ABS_MT_TOUCH_MAJOR);
504 +                       return 1;
505 +               case HID_DG_HEIGHT:
506 +                       hid_map_usage(hi, usage, bit, max,
507 +                                       EV_ABS, ABS_MT_TOUCH_MINOR);
508 +                       input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
509 +                                       1, 1, 0, 0);
510 +                       return 1;
511 +               case HID_DG_TIPPRESSURE:
512 +                       hid_map_usage(hi, usage, bit, max,
513 +                                       EV_ABS, ABS_MT_PRESSURE);
514 +                       return 1;
515 +
516 +               case HID_DG_CONTACTID:
517 +                       hid_map_usage(hi, usage, bit, max,
518 +                                       EV_ABS, ABS_MT_TRACKING_ID);
519 +                       return 1;
520 +
521 +               }
522 +               return 0;
523 +
524 +       case 0xff000000:
525 +               /* no input-oriented meaning */
526 +               return -1;
527 +       }
528 +
529 +       return 0;
530 +}
531 +
532 +static int stantum_input_mapped(struct hid_device *hdev, struct hid_input *hi,
533 +               struct hid_field *field, struct hid_usage *usage,
534 +               unsigned long **bit, int *max)
535 +{
536 +       if (usage->type == EV_KEY || usage->type == EV_ABS)
537 +               clear_bit(usage->code, *bit);
538 +
539 +       return 0;
540 +}
541 +
542 +/*
543 + * this function is called when a whole finger has been parsed,
544 + * so that it can decide what to send to the input layer.
545 + */
546 +static void stantum_filter_event(struct stantum_data *sd,
547 +                                       struct input_dev *input)
548 +{
549 +       bool wide;
550 +
551 +       if (!sd->valid) {
552 +               /*
553 +                * touchscreen emulation: if the first finger is not valid and
554 +                * there previously was finger activity, this is a release
555 +                */
556 +               if (sd->first && sd->activity) {
557 +                       input_event(input, EV_KEY, BTN_TOUCH, 0);
558 +                       sd->activity = false;
559 +               }
560 +               return;
561 +       }
562 +
563 +       input_event(input, EV_ABS, ABS_MT_TRACKING_ID, sd->id);
564 +       input_event(input, EV_ABS, ABS_MT_POSITION_X, sd->x);
565 +       input_event(input, EV_ABS, ABS_MT_POSITION_Y, sd->y);
566 +
567 +       wide = (sd->w > sd->h);
568 +       input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
569 +       input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, wide ? sd->w : sd->h);
570 +       input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, wide ? sd->h : sd->w);
571 +
572 +       input_event(input, EV_ABS, ABS_MT_PRESSURE, sd->z);
573 +
574 +       input_mt_sync(input);
575 +       sd->valid = false;
576 +
577 +       /* touchscreen emulation */
578 +       if (sd->first) {
579 +               if (!sd->activity) {
580 +                       input_event(input, EV_KEY, BTN_TOUCH, 1);
581 +                       sd->activity = true;
582 +               }
583 +               input_event(input, EV_ABS, ABS_X, sd->x);
584 +               input_event(input, EV_ABS, ABS_Y, sd->y);
585 +       }
586 +       sd->first = false;
587 +}
588 +
589 +
590 +static int stantum_event(struct hid_device *hid, struct hid_field *field,
591 +                               struct hid_usage *usage, __s32 value)
592 +{
593 +       struct stantum_data *sd = hid_get_drvdata(hid);
594 +
595 +       if (hid->claimed & HID_CLAIMED_INPUT) {
596 +               struct input_dev *input = field->hidinput->input;
597 +
598 +               switch (usage->hid) {
599 +               case HID_DG_INRANGE:
600 +                       /* this is the last field in a finger */
601 +                       stantum_filter_event(sd, input);
602 +                       break;
603 +               case HID_DG_WIDTH:
604 +                       sd->w = value;
605 +                       break;
606 +               case HID_DG_HEIGHT:
607 +                       sd->h = value;
608 +                       break;
609 +               case HID_GD_X:
610 +                       sd->x = value;
611 +                       break;
612 +               case HID_GD_Y:
613 +                       sd->y = value;
614 +                       break;
615 +               case HID_DG_TIPPRESSURE:
616 +                       sd->z = value;
617 +                       break;
618 +               case HID_DG_CONTACTID:
619 +                       sd->id = value;
620 +                       break;
621 +               case HID_DG_CONFIDENCE:
622 +                       sd->valid = !!value;
623 +                       break;
624 +               case 0xff000002:
625 +                       /* this comes only before the first finger */
626 +                       sd->first = true;
627 +                       break;
628 +
629 +               default:
630 +                       /* ignore the others */
631 +                       return 1;
632 +               }
633 +       }
634 +
635 +       /* we have handled the hidinput part, now remains hiddev */
636 +       if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
637 +               hid->hiddev_hid_event(hid, field, usage, value);
638 +
639 +       return 1;
640 +}
641 +
642 +static int stantum_probe(struct hid_device *hdev,
643 +                               const struct hid_device_id *id)
644 +{
645 +       int ret;
646 +       struct stantum_data *sd;
647 +
648 +       sd = kmalloc(sizeof(struct stantum_data), GFP_KERNEL);
649 +       if (!sd) {
650 +               dev_err(&hdev->dev, "cannot allocate Stantum data\n");
651 +               return -ENOMEM;
652 +       }
653 +       sd->valid = false;
654 +       sd->first = false;
655 +       sd->activity = false;
656 +       hid_set_drvdata(hdev, sd);
657 +
658 +       ret = hid_parse(hdev);
659 +       if (!ret)
660 +               ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
661 +
662 +       if (ret)
663 +               kfree(sd);
664 +
665 +       return ret;
666 +}
667 +
668 +static void stantum_remove(struct hid_device *hdev)
669 +{
670 +       hid_hw_stop(hdev);
671 +       kfree(hid_get_drvdata(hdev));
672 +       hid_set_drvdata(hdev, NULL);
673 +}
674 +
675 +static const struct hid_device_id stantum_devices[] = {
676 +       { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) },
677 +       { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM2, USB_DEVICE_ID_MTP2) },
678 +       { HID_USB_DEVICE(USB_VENDOR_ID_STMICRO, USB_DEVICE_ID_STMICRO_MTP1) },
679 +       { }
680 +};
681 +MODULE_DEVICE_TABLE(hid, stantum_devices);
682 +
683 +static const struct hid_usage_id stantum_grabbed_usages[] = {
684 +       { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
685 +       { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
686 +};
687 +
688 +static struct hid_driver stantum_driver = {
689 +       .name = "stantum",
690 +       .id_table = stantum_devices,
691 +       .probe = stantum_probe,
692 +       .remove = stantum_remove,
693 +       .input_mapping = stantum_input_mapping,
694 +       .input_mapped = stantum_input_mapped,
695 +       .usage_table = stantum_grabbed_usages,
696 +       .event = stantum_event,
697 +};
698 +
699 +static int __init stantum_init(void)
700 +{
701 +       return hid_register_driver(&stantum_driver);
702 +}
703 +
704 +static void __exit stantum_exit(void)
705 +{
706 +       hid_unregister_driver(&stantum_driver);
707 +}
708 +
709 +module_init(stantum_init);
710 +module_exit(stantum_exit);
711 +
712 -- 
713 1.6.2.2
714