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
6 HID Driver and configs for Stantum and Mosart multitouch panels.
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>
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
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
30 Support for Monterey Genius KB29E.
36 + Support for MosArt dual-touch panels.
39 tristate "NTrig" if EMBEDDED
41 @@ -247,6 +253,12 @@ config HID_SONY
43 Support for Sony PS3 controller.
49 + Support for Stantum multitouch panel.
52 tristate "Sunplus" if EMBEDDED
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/
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
109 #define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241
110 #define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242
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
118 +#define USB_VENDOR_ID_ASUSTEK 0x0b05
119 +#define USB_DEVICE_ID_ASUSTEK_LCM 0x1726
120 +#define USB_DEVICE_ID_ASUSTEK_LCM2 0x175b
122 #define USB_VENDOR_ID_ATEN 0x0557
123 #define USB_DEVICE_ID_ATEN_UC100KM 0x2004
125 #define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST 0x0034
126 #define USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST 0x0046
128 +#define USB_VENDOR_ID_STANTUM 0x1f87
129 +#define USB_DEVICE_ID_MTP 0x0002
131 +#define USB_VENDOR_ID_STANTUM2 0x1f87
132 +#define USB_DEVICE_ID_MTP2 0x0001
134 +#define USB_VENDOR_ID_STMICRO 0x0483
135 +#define USB_DEVICE_ID_STMICRO_MTP1 0x3261
137 #define USB_VENDOR_ID_SUN 0x0430
138 #define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab
140 diff --git a/drivers/hid/hid-mosart.c b/drivers/hid/hid-mosart.c
142 index 0000000..e91437c
144 +++ b/drivers/hid/hid-mosart.c
147 + * HID driver for the multitouch panel on the ASUS EeePC T91MT
149 + * Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
150 + * Copyright (c) 2010 Teemu Tuominen <teemu.tuominen@cybercom.com>
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.
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"
168 +MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
169 +MODULE_DESCRIPTION("MosArt dual-touch panel");
170 +MODULE_LICENSE("GPL");
172 +#include "hid-ids.h"
174 +struct mosart_data {
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? */
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)
187 + switch (usage->hid & HID_USAGE_PAGE) {
189 + case HID_UP_GENDESK:
190 + switch (usage->hid) {
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);
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);
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:
220 + case HID_DG_HEIGHT:
222 + case HID_DG_INRANGE:
223 + /* touchscreen emulation */
224 + hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
227 + case HID_DG_CONTACTID:
228 + hid_map_usage(hi, usage, bit, max,
229 + EV_ABS, ABS_MT_TRACKING_ID);
236 + /* ignore HID features */
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)
247 + if (usage->type == EV_KEY || usage->type == EV_ABS)
248 + clear_bit(usage->code, *bit);
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.
257 +static void mosart_filter_event(struct mosart_data *td, struct input_dev *input)
259 + td->first = !td->first; /* touchscreen emulation */
263 + * touchscreen emulation: if no finger in this frame is valid
264 + * and there previously was finger activity, this is a release
266 + if (!td->first && !td->activity_now && td->activity) {
267 + input_event(input, EV_KEY, BTN_TOUCH, 0);
268 + td->activity = false;
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);
277 + input_mt_sync(input);
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;
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);
295 +static int mosart_event(struct hid_device *hid, struct hid_field *field,
296 + struct hid_usage *usage, __s32 value)
298 + struct mosart_data *td = hid_get_drvdata(hid);
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;
311 + mosart_filter_event(td, input);
313 + case HID_DG_CONTACTID:
316 + case HID_DG_CONTACTCOUNT:
317 + /* touch emulation: this is the last field in a frame */
319 + td->activity_now = false;
321 + case HID_DG_CONFIDENCE:
322 + case HID_DG_TIPSWITCH:
323 + /* avoid interference from generic hidinput handling */
327 + /* fallback to the generic hidinput handling */
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);
339 +static int mosart_probe(struct hid_device *hdev, const struct hid_device_id *id)
342 + struct mosart_data *td;
345 + td = kmalloc(sizeof(struct mosart_data), GFP_KERNEL);
347 + dev_err(&hdev->dev, "cannot allocate MosArt data\n");
351 + td->activity = false;
352 + td->activity_now = false;
354 + hid_set_drvdata(hdev, td);
356 + /* currently, it's better to have one evdev device only */
358 + hdev->quirks |= HID_QUIRK_MULTI_INPUT;
361 + ret = hid_parse(hdev);
363 + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
366 + struct hid_report_enum *re = hdev->report_enum
367 + + HID_FEATURE_REPORT;
368 + struct hid_report *r = re->report_id_hash[7];
370 + r->field[0]->value[0] = 0x02;
371 + usbhid_submit_report(hdev, r, USB_DIR_OUT);
378 +static void mosart_remove(struct hid_device *hdev)
381 + kfree(hid_get_drvdata(hdev));
382 + hid_set_drvdata(hdev, NULL);
385 +static const struct hid_device_id mosart_devices[] = {
386 + { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) },
389 +MODULE_DEVICE_TABLE(hid, mosart_devices);
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}
396 +static struct hid_driver mosart_driver = {
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,
407 +static int __init mosart_init(void)
409 + return hid_register_driver(&mosart_driver);
412 +static void __exit mosart_exit(void)
414 + hid_unregister_driver(&mosart_driver);
417 +module_init(mosart_init);
418 +module_exit(mosart_exit);
420 diff --git a/drivers/hid/hid-stantum.c b/drivers/hid/hid-stantum.c
422 index 0000000..bb4430f
424 +++ b/drivers/hid/hid-stantum.c
427 + * HID driver for Stantum multitouch panels
429 + * Copyright (c) 2009 Stephane Chatty <chatty@enac.fr>
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.
440 +#include <linux/device.h>
441 +#include <linux/hid.h>
442 +#include <linux/module.h>
443 +#include <linux/slab.h>
445 +MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
446 +MODULE_DESCRIPTION("Stantum HID multitouch panels");
447 +MODULE_LICENSE("GPL");
449 +#include "hid-ids.h"
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? */
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)
463 + switch (usage->hid & HID_USAGE_PAGE) {
465 + case HID_UP_GENDESK:
466 + switch (usage->hid) {
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);
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);
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:
496 + case HID_DG_TIPSWITCH:
497 + /* touchscreen emulation */
498 + hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
502 + hid_map_usage(hi, usage, bit, max,
503 + EV_ABS, ABS_MT_TOUCH_MAJOR);
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,
511 + case HID_DG_TIPPRESSURE:
512 + hid_map_usage(hi, usage, bit, max,
513 + EV_ABS, ABS_MT_PRESSURE);
516 + case HID_DG_CONTACTID:
517 + hid_map_usage(hi, usage, bit, max,
518 + EV_ABS, ABS_MT_TRACKING_ID);
525 + /* no input-oriented meaning */
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)
536 + if (usage->type == EV_KEY || usage->type == EV_ABS)
537 + clear_bit(usage->code, *bit);
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.
546 +static void stantum_filter_event(struct stantum_data *sd,
547 + struct input_dev *input)
553 + * touchscreen emulation: if the first finger is not valid and
554 + * there previously was finger activity, this is a release
556 + if (sd->first && sd->activity) {
557 + input_event(input, EV_KEY, BTN_TOUCH, 0);
558 + sd->activity = false;
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);
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);
572 + input_event(input, EV_ABS, ABS_MT_PRESSURE, sd->z);
574 + input_mt_sync(input);
577 + /* touchscreen emulation */
579 + if (!sd->activity) {
580 + input_event(input, EV_KEY, BTN_TOUCH, 1);
581 + sd->activity = true;
583 + input_event(input, EV_ABS, ABS_X, sd->x);
584 + input_event(input, EV_ABS, ABS_Y, sd->y);
590 +static int stantum_event(struct hid_device *hid, struct hid_field *field,
591 + struct hid_usage *usage, __s32 value)
593 + struct stantum_data *sd = hid_get_drvdata(hid);
595 + if (hid->claimed & HID_CLAIMED_INPUT) {
596 + struct input_dev *input = field->hidinput->input;
598 + switch (usage->hid) {
599 + case HID_DG_INRANGE:
600 + /* this is the last field in a finger */
601 + stantum_filter_event(sd, input);
606 + case HID_DG_HEIGHT:
615 + case HID_DG_TIPPRESSURE:
618 + case HID_DG_CONTACTID:
621 + case HID_DG_CONFIDENCE:
622 + sd->valid = !!value;
625 + /* this comes only before the first finger */
630 + /* ignore the others */
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);
642 +static int stantum_probe(struct hid_device *hdev,
643 + const struct hid_device_id *id)
646 + struct stantum_data *sd;
648 + sd = kmalloc(sizeof(struct stantum_data), GFP_KERNEL);
650 + dev_err(&hdev->dev, "cannot allocate Stantum data\n");
655 + sd->activity = false;
656 + hid_set_drvdata(hdev, sd);
658 + ret = hid_parse(hdev);
660 + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
668 +static void stantum_remove(struct hid_device *hdev)
671 + kfree(hid_get_drvdata(hdev));
672 + hid_set_drvdata(hdev, NULL);
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) },
681 +MODULE_DEVICE_TABLE(hid, stantum_devices);
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}
688 +static struct hid_driver stantum_driver = {
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,
699 +static int __init stantum_init(void)
701 + return hid_register_driver(&stantum_driver);
704 +static void __exit stantum_exit(void)
706 + hid_unregister_driver(&stantum_driver);
709 +module_init(stantum_init);
710 +module_exit(stantum_exit);