summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-netbook-2.6.33.2/linux-2.6.34-stantum-and-mosart-multitouch-drivers.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-kernel/linux/linux-netbook-2.6.33.2/linux-2.6.34-stantum-and-mosart-multitouch-drivers.patch')
-rw-r--r--meta/recipes-kernel/linux/linux-netbook-2.6.33.2/linux-2.6.34-stantum-and-mosart-multitouch-drivers.patch714
1 files changed, 714 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-netbook-2.6.33.2/linux-2.6.34-stantum-and-mosart-multitouch-drivers.patch b/meta/recipes-kernel/linux/linux-netbook-2.6.33.2/linux-2.6.34-stantum-and-mosart-multitouch-drivers.patch
new file mode 100644
index 0000000000..6f8aaca07e
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-netbook-2.6.33.2/linux-2.6.34-stantum-and-mosart-multitouch-drivers.patch
@@ -0,0 +1,714 @@
1From f7e13f4d9a7a9025244b37a3ad188af7dae841d9 Mon Sep 17 00:00:00 2001
2From: Stephane Chatty <chatty@enac.fr>
3Date: Fri, 9 Apr 2010 15:33:54 -0700
4Subject: [PATCH 105/105] Stantum and Mosart multitouch drivers
5
6HID Driver and configs for Stantum and Mosart multitouch panels.
7
8Patch-mainline: 2.6.34
9
10Signed-off-by: Stephane Chatty <chatty@enac.fr>
11Signed-off-by: Jiri Kosina <jkosina@suse.cz>
12Signed-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
24diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
25index 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
54diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
55index 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-
78diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
79index 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) },
104diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
105index 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
140diff --git a/drivers/hid/hid-mosart.c b/drivers/hid/hid-mosart.c
141new file mode 100644
142index 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+
420diff --git a/drivers/hid/hid-stantum.c b/drivers/hid/hid-stantum.c
421new file mode 100644
422index 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--
7131.6.2.2
714