2 * HID driver for N-Trig touchscreens
4 * Copyright (c) 2008 Rafi Rubin
5 * Copyright (c) 2009 Stephane Chatty
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)
16 #include <linux/device.h>
17 #include <linux/hid.h>
18 #include <linux/module.h>
22 #define NTRIG_DUPLICATE_USAGES 0x001
24 #define nt_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
29 char reading_a_point
, found_contact_id
;
33 * this driver is aimed at two firmware versions in circulation:
34 * - dual pen/finger single touch
35 * - finger multitouch, pen not working
38 static int ntrig_input_mapping(struct hid_device
*hdev
, struct hid_input
*hi
,
39 struct hid_field
*field
, struct hid_usage
*usage
,
40 unsigned long **bit
, int *max
)
42 switch (usage
->hid
& HID_USAGE_PAGE
) {
47 hid_map_usage(hi
, usage
, bit
, max
,
48 EV_ABS
, ABS_MT_POSITION_X
);
49 input_set_abs_params(hi
->input
, ABS_X
,
50 field
->logical_minimum
,
51 field
->logical_maximum
, 0, 0);
54 hid_map_usage(hi
, usage
, bit
, max
,
55 EV_ABS
, ABS_MT_POSITION_Y
);
56 input_set_abs_params(hi
->input
, ABS_Y
,
57 field
->logical_minimum
,
58 field
->logical_maximum
, 0, 0);
63 case HID_UP_DIGITIZER
:
65 /* we do not want to map these for now */
66 case HID_DG_INVERT
: /* value is always 0 */
67 case HID_DG_ERASER
: /* value is always 0 */
68 case HID_DG_CONTACTID
: /* value is useless */
69 case HID_DG_BARRELSWITCH
: /* doubtful */
70 case HID_DG_INPUTMODE
:
71 case HID_DG_DEVICEINDEX
:
72 case HID_DG_CONTACTCOUNT
:
73 case HID_DG_CONTACTMAX
:
76 /* original mapping by Rafi Rubin */
77 case HID_DG_CONFIDENCE
:
78 nt_map_key_clear(BTN_TOOL_DOUBLETAP
);
81 /* width/height mapped on TouchMajor/TouchMinor/Orientation */
83 hid_map_usage(hi
, usage
, bit
, max
,
84 EV_ABS
, ABS_MT_TOUCH_MAJOR
);
87 hid_map_usage(hi
, usage
, bit
, max
,
88 EV_ABS
, ABS_MT_TOUCH_MINOR
);
89 input_set_abs_params(hi
->input
, ABS_MT_ORIENTATION
,
96 /* we do not want to map these: no input-oriented meaning */
103 static int ntrig_input_mapped(struct hid_device
*hdev
, struct hid_input
*hi
,
104 struct hid_field
*field
, struct hid_usage
*usage
,
105 unsigned long **bit
, int *max
)
107 if (usage
->type
== EV_KEY
|| usage
->type
== EV_REL
108 || usage
->type
== EV_ABS
)
109 clear_bit(usage
->code
, *bit
);
115 * this function is called upon all reports
116 * so that we can filter contact point information,
117 * decide whether we are in multi or single touch mode
118 * and call input_mt_sync after each point if necessary
120 static int ntrig_event (struct hid_device
*hid
, struct hid_field
*field
,
121 struct hid_usage
*usage
, __s32 value
)
123 struct input_dev
*input
= field
->hidinput
->input
;
124 struct ntrig_data
*nd
= hid_get_drvdata(hid
);
126 if (hid
->claimed
& HID_CLAIMED_INPUT
) {
127 switch (usage
->hid
) {
130 nd
->reading_a_point
= 1;
135 case HID_DG_CONTACTID
:
137 /* we receive this only when in multitouch mode */
138 nd
->found_contact_id
= 1;
146 * when in single touch mode, this is the last
147 * report received in a finger event. We want
148 * to emit a normal (X, Y) position
150 if (! nd
->found_contact_id
) {
151 input_event(input
, EV_ABS
, ABS_X
, nd
->x
);
152 input_event(input
, EV_ABS
, ABS_Y
, nd
->y
);
155 case HID_DG_TIPPRESSURE
:
157 * when in single touch mode, this is the last
158 * report received in a pen event. We want
159 * to emit a normal (X, Y) position
161 if (! nd
->found_contact_id
) {
162 input_event(input
, EV_ABS
, ABS_X
, nd
->x
);
163 input_event(input
, EV_ABS
, ABS_Y
, nd
->y
);
164 input_event(input
, EV_ABS
, ABS_PRESSURE
, value
);
169 * we receive this when the device is in multitouch
170 * mode. The first of the three values tagged with
171 * this usage tells if the contact point is real
174 if (!nd
->reading_a_point
|| value
!= 1)
176 /* emit a normal (X, Y) for the first point only */
178 input_event(input
, EV_ABS
, ABS_X
, nd
->x
);
179 input_event(input
, EV_ABS
, ABS_Y
, nd
->y
);
181 input_event(input
, EV_ABS
, ABS_MT_POSITION_X
, nd
->x
);
182 input_event(input
, EV_ABS
, ABS_MT_POSITION_Y
, nd
->y
);
184 input_event(input
, EV_ABS
,
185 ABS_MT_ORIENTATION
, 1);
186 input_event(input
, EV_ABS
,
187 ABS_MT_TOUCH_MAJOR
, nd
->w
);
188 input_event(input
, EV_ABS
,
189 ABS_MT_TOUCH_MINOR
, nd
->h
);
191 input_event(input
, EV_ABS
,
192 ABS_MT_ORIENTATION
, 0);
193 input_event(input
, EV_ABS
,
194 ABS_MT_TOUCH_MAJOR
, nd
->h
);
195 input_event(input
, EV_ABS
,
196 ABS_MT_TOUCH_MINOR
, nd
->w
);
198 input_mt_sync(field
->hidinput
->input
);
199 nd
->reading_a_point
= 0;
200 nd
->found_contact_id
= 0;
204 /* fallback to the generic hidinput handling */
209 /* we have handled the hidinput part, now remains hiddev */
210 if (hid
->claimed
& HID_CLAIMED_HIDDEV
&& hid
->hiddev_hid_event
)
211 hid
->hiddev_hid_event(hid
, field
, usage
, value
);
216 static int ntrig_probe(struct hid_device
*hdev
, const struct hid_device_id
*id
)
219 struct ntrig_data
*nd
;
221 nd
= kmalloc(sizeof(struct ntrig_data
), GFP_KERNEL
);
223 dev_err(&hdev
->dev
, "cannot allocate N-Trig data\n");
226 nd
->reading_a_point
= 0;
227 nd
->found_contact_id
= 0;
228 hid_set_drvdata(hdev
, nd
);
230 ret
= hid_parse(hdev
);
232 ret
= hid_hw_start(hdev
, HID_CONNECT_DEFAULT
);
239 static void ntrig_remove(struct hid_device
*hdev
)
242 kfree(hid_get_drvdata(hdev
));
245 static const struct hid_device_id ntrig_devices
[] = {
246 { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG
, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN
),
247 .driver_data
= NTRIG_DUPLICATE_USAGES
},
250 MODULE_DEVICE_TABLE(hid
, ntrig_devices
);
252 static const struct hid_usage_id ntrig_grabbed_usages
[] = {
253 { HID_ANY_ID
, HID_ANY_ID
, HID_ANY_ID
},
254 { HID_ANY_ID
- 1, HID_ANY_ID
- 1, HID_ANY_ID
- 1}
257 static struct hid_driver ntrig_driver
= {
259 .id_table
= ntrig_devices
,
260 .probe
= ntrig_probe
,
261 .remove
= ntrig_remove
,
262 .input_mapping
= ntrig_input_mapping
,
263 .input_mapped
= ntrig_input_mapped
,
264 .usage_table
= ntrig_grabbed_usages
,
265 .event
= ntrig_event
,
268 static int ntrig_init(void)
270 return hid_register_driver(&ntrig_driver
);
273 static void ntrig_exit(void)
275 hid_unregister_driver(&ntrig_driver
);
278 module_init(ntrig_init
);
279 module_exit(ntrig_exit
);
280 MODULE_LICENSE("GPL");