Blame view

drivers/hid/hid-multitouch.c 25.7 KB
5519cab47   Benjamin Tissoires   HID: hid-multitou...
1
2
3
4
5
6
7
  /*
   *  HID driver for multitouch panels
   *
   *  Copyright (c) 2010-2011 Stephane Chatty <chatty@enac.fr>
   *  Copyright (c) 2010-2011 Benjamin Tissoires <benjamin.tissoires@gmail.com>
   *  Copyright (c) 2010-2011 Ecole Nationale de l'Aviation Civile, France
   *
4875ac114   Richard Nauber   HID: merge hid-eg...
8
9
10
11
12
13
   *  This code is partly based on hid-egalax.c:
   *
   *  Copyright (c) 2010 Stephane Chatty <chatty@enac.fr>
   *  Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se>
   *  Copyright (c) 2010 Canonical, Ltd.
   *
f786bba44   Benjamin Tissoires   HID: hid-multitou...
14
15
16
17
18
19
   *  This code is partly based on hid-3m-pct.c:
   *
   *  Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
   *  Copyright (c) 2010      Henrik Rydberg <rydberg@euromail.se>
   *  Copyright (c) 2010      Canonical, Ltd.
   *
5519cab47   Benjamin Tissoires   HID: hid-multitou...
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
   */
  
  /*
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License as published by the Free
   * Software Foundation; either version 2 of the License, or (at your option)
   * any later version.
   */
  
  #include <linux/device.h>
  #include <linux/hid.h>
  #include <linux/module.h>
  #include <linux/slab.h>
  #include <linux/usb.h>
  #include <linux/input/mt.h>
  #include "usbhid/usbhid.h"
  
  
  MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
ef2fafb3e   Benjamin Tissoires   HID: hid-multitou...
39
  MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
5519cab47   Benjamin Tissoires   HID: hid-multitou...
40
41
42
43
44
45
46
47
  MODULE_DESCRIPTION("HID multitouch panels");
  MODULE_LICENSE("GPL");
  
  #include "hid-ids.h"
  
  /* quirks to control the device */
  #define MT_QUIRK_NOT_SEEN_MEANS_UP	(1 << 0)
  #define MT_QUIRK_SLOT_IS_CONTACTID	(1 << 1)
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
48
  #define MT_QUIRK_CYPRESS		(1 << 2)
5572da08a   Benjamin Tissoires   HID: hid-mulitouc...
49
  #define MT_QUIRK_SLOT_IS_CONTACTNUMBER	(1 << 3)
a062cc5a7   Stephane Chatty   HID: hid-multitou...
50
51
52
  #define MT_QUIRK_ALWAYS_VALID		(1 << 4)
  #define MT_QUIRK_VALID_IS_INRANGE	(1 << 5)
  #define MT_QUIRK_VALID_IS_CONFIDENCE	(1 << 6)
a062cc5a7   Stephane Chatty   HID: hid-multitou...
53
  #define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE	(1 << 8)
5519cab47   Benjamin Tissoires   HID: hid-multitou...
54
55
56
57
58
59
60
  
  struct mt_slot {
  	__s32 x, y, p, w, h;
  	__s32 contactid;	/* the device ContactID assigned to this slot */
  	bool touch_state;	/* is the touch valid? */
  	bool seen_in_this_frame;/* has this slot been updated */
  };
eec29e3da   Benjamin Tissoires   HID: multitouch: ...
61
62
63
64
65
66
67
68
69
  struct mt_class {
  	__s32 name;	/* MT_CLS */
  	__s32 quirks;
  	__s32 sn_move;	/* Signal/noise ratio for move events */
  	__s32 sn_width;	/* Signal/noise ratio for width events */
  	__s32 sn_height;	/* Signal/noise ratio for height events */
  	__s32 sn_pressure;	/* Signal/noise ratio for pressure events */
  	__u8 maxcontacts;
  };
5519cab47   Benjamin Tissoires   HID: hid-multitou...
70
71
  struct mt_device {
  	struct mt_slot curdata;	/* placeholder of incoming data */
eec29e3da   Benjamin Tissoires   HID: multitouch: ...
72
  	struct mt_class mtclass;	/* our mt device class */
5519cab47   Benjamin Tissoires   HID: hid-multitou...
73
74
  	unsigned last_field_index;	/* last field index of the report */
  	unsigned last_slot_field;	/* the last field of a slot */
b84bd27fe   Benjamin Tissoires   HID: hid-multitou...
75
  	int last_mt_collection;	/* last known mt-related collection */
5519cab47   Benjamin Tissoires   HID: hid-multitou...
76
77
78
  	__s8 inputmode;		/* InputMode HID feature, -1 if non-existent */
  	__u8 num_received;	/* how many contacts we received */
  	__u8 num_expected;	/* expected last contact index */
9498f954a   Benjamin Tissoires   HID: hid-multitou...
79
  	__u8 maxcontacts;
5519cab47   Benjamin Tissoires   HID: hid-multitou...
80
  	bool curvalid;		/* is the current contact valid? */
9498f954a   Benjamin Tissoires   HID: hid-multitou...
81
  	struct mt_slot *slots;
5519cab47   Benjamin Tissoires   HID: hid-multitou...
82
  };
5519cab47   Benjamin Tissoires   HID: hid-multitou...
83
  /* classes of device behavior */
22408283b   Benjamin Tissoires   HID: hid-multitou...
84
  #define MT_CLS_DEFAULT				0x0001
a062cc5a7   Stephane Chatty   HID: hid-multitou...
85
86
  #define MT_CLS_SERIAL				0x0002
  #define MT_CLS_CONFIDENCE			0x0003
5e7ea11f6   Benjamin Tissoires   HID: multitouch: ...
87
88
89
90
91
  #define MT_CLS_CONFIDENCE_CONTACT_ID		0x0004
  #define MT_CLS_CONFIDENCE_MINUS_ONE		0x0005
  #define MT_CLS_DUAL_INRANGE_CONTACTID		0x0006
  #define MT_CLS_DUAL_INRANGE_CONTACTNUMBER	0x0007
  #define MT_CLS_DUAL_NSMU_CONTACTID		0x0008
b7ea95ff9   Aaron Tian   HID: multitouch: ...
92
  #define MT_CLS_INRANGE_CONTACTNUMBER		0x0009
22408283b   Benjamin Tissoires   HID: hid-multitou...
93
94
95
96
97
  
  /* vendor specific classes */
  #define MT_CLS_3M				0x0101
  #define MT_CLS_CYPRESS				0x0102
  #define MT_CLS_EGALAX				0x0103
1b723e8dc   Benjamin Tissoires   HID: multitouch: ...
98
  #define MT_CLS_EGALAX_SERIAL			0x0104
5519cab47   Benjamin Tissoires   HID: hid-multitou...
99

9498f954a   Benjamin Tissoires   HID: hid-multitou...
100
  #define MT_DEFAULT_MAXCONTACT	10
5519cab47   Benjamin Tissoires   HID: hid-multitou...
101
102
103
104
  /*
   * these device-dependent functions determine what slot corresponds
   * to a valid contact that was just read.
   */
a3b5e577d   Benjamin Tissoires   HID: hid-multitou...
105
106
107
108
109
110
111
  static int cypress_compute_slot(struct mt_device *td)
  {
  	if (td->curdata.contactid != 0 || td->num_received == 0)
  		return td->curdata.contactid;
  	else
  		return -1;
  }
5519cab47   Benjamin Tissoires   HID: hid-multitou...
112
113
114
  static int find_slot_from_contactid(struct mt_device *td)
  {
  	int i;
9498f954a   Benjamin Tissoires   HID: hid-multitou...
115
  	for (i = 0; i < td->maxcontacts; ++i) {
5519cab47   Benjamin Tissoires   HID: hid-multitou...
116
117
118
119
  		if (td->slots[i].contactid == td->curdata.contactid &&
  			td->slots[i].touch_state)
  			return i;
  	}
9498f954a   Benjamin Tissoires   HID: hid-multitou...
120
  	for (i = 0; i < td->maxcontacts; ++i) {
5519cab47   Benjamin Tissoires   HID: hid-multitou...
121
122
123
124
  		if (!td->slots[i].seen_in_this_frame &&
  			!td->slots[i].touch_state)
  			return i;
  	}
5519cab47   Benjamin Tissoires   HID: hid-multitou...
125
126
127
  	/* should not occurs. If this happens that means
  	 * that the device sent more touches that it says
  	 * in the report descriptor. It is ignored then. */
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
128
  	return -1;
5519cab47   Benjamin Tissoires   HID: hid-multitou...
129
  }
b3c21d2ca   Jiri Kosina   HID: multitouch: ...
130
  static struct mt_class mt_classes[] = {
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
131
  	{ .name = MT_CLS_DEFAULT,
9498f954a   Benjamin Tissoires   HID: hid-multitou...
132
  		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP },
a062cc5a7   Stephane Chatty   HID: hid-multitou...
133
134
  	{ .name = MT_CLS_SERIAL,
  		.quirks = MT_QUIRK_ALWAYS_VALID},
22408283b   Benjamin Tissoires   HID: hid-multitou...
135
136
  	{ .name = MT_CLS_CONFIDENCE,
  		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE },
5e7ea11f6   Benjamin Tissoires   HID: multitouch: ...
137
138
139
  	{ .name = MT_CLS_CONFIDENCE_CONTACT_ID,
  		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
  			MT_QUIRK_SLOT_IS_CONTACTID },
22408283b   Benjamin Tissoires   HID: hid-multitou...
140
141
142
  	{ .name = MT_CLS_CONFIDENCE_MINUS_ONE,
  		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
  			MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE },
1e9cf35b9   Benjamin Tissoires   HID: hid-multitou...
143
  	{ .name = MT_CLS_DUAL_INRANGE_CONTACTID,
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
144
145
146
  		.quirks = MT_QUIRK_VALID_IS_INRANGE |
  			MT_QUIRK_SLOT_IS_CONTACTID,
  		.maxcontacts = 2 },
1e9cf35b9   Benjamin Tissoires   HID: hid-multitou...
147
  	{ .name = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
148
149
150
  		.quirks = MT_QUIRK_VALID_IS_INRANGE |
  			MT_QUIRK_SLOT_IS_CONTACTNUMBER,
  		.maxcontacts = 2 },
22408283b   Benjamin Tissoires   HID: hid-multitou...
151
152
153
154
  	{ .name = MT_CLS_DUAL_NSMU_CONTACTID,
  		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
  			MT_QUIRK_SLOT_IS_CONTACTID,
  		.maxcontacts = 2 },
b7ea95ff9   Aaron Tian   HID: multitouch: ...
155
156
157
  	{ .name = MT_CLS_INRANGE_CONTACTNUMBER,
  		.quirks = MT_QUIRK_VALID_IS_INRANGE |
  			MT_QUIRK_SLOT_IS_CONTACTNUMBER },
22408283b   Benjamin Tissoires   HID: hid-multitou...
158
159
160
161
162
163
164
165
166
167
  
  	/*
  	 * vendor specific classes
  	 */
  	{ .name = MT_CLS_3M,
  		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
  			MT_QUIRK_SLOT_IS_CONTACTID,
  		.sn_move = 2048,
  		.sn_width = 128,
  		.sn_height = 128 },
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
168
169
170
171
  	{ .name = MT_CLS_CYPRESS,
  		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
  			MT_QUIRK_CYPRESS,
  		.maxcontacts = 10 },
4875ac114   Richard Nauber   HID: merge hid-eg...
172
173
  	{ .name = MT_CLS_EGALAX,
  		.quirks =  MT_QUIRK_SLOT_IS_CONTACTID |
2261bb9ff   Benjamin Tissoires   HID: multitouch: ...
174
  			MT_QUIRK_VALID_IS_INRANGE,
4875ac114   Richard Nauber   HID: merge hid-eg...
175
176
177
  		.sn_move = 4096,
  		.sn_pressure = 32,
  	},
1b723e8dc   Benjamin Tissoires   HID: multitouch: ...
178
179
180
  	{ .name = MT_CLS_EGALAX_SERIAL,
  		.quirks =  MT_QUIRK_SLOT_IS_CONTACTID |
  			MT_QUIRK_ALWAYS_VALID,
4875ac114   Richard Nauber   HID: merge hid-eg...
181
182
183
  		.sn_move = 4096,
  		.sn_pressure = 32,
  	},
043b403ae   Benjamin Tissoires   HID: hid-multitou...
184

2d93666e7   Benjamin Tissoires   HID: hid-multitou...
185
  	{ }
5519cab47   Benjamin Tissoires   HID: hid-multitou...
186
  };
eec29e3da   Benjamin Tissoires   HID: multitouch: ...
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
  static ssize_t mt_show_quirks(struct device *dev,
  			   struct device_attribute *attr,
  			   char *buf)
  {
  	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  	struct mt_device *td = hid_get_drvdata(hdev);
  
  	return sprintf(buf, "%u
  ", td->mtclass.quirks);
  }
  
  static ssize_t mt_set_quirks(struct device *dev,
  			  struct device_attribute *attr,
  			  const char *buf, size_t count)
  {
  	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
  	struct mt_device *td = hid_get_drvdata(hdev);
  
  	unsigned long val;
  
  	if (kstrtoul(buf, 0, &val))
  		return -EINVAL;
  
  	td->mtclass.quirks = val;
  
  	return count;
  }
  
  static DEVICE_ATTR(quirks, S_IWUSR | S_IRUGO, mt_show_quirks, mt_set_quirks);
  
  static struct attribute *sysfs_attrs[] = {
  	&dev_attr_quirks.attr,
  	NULL
  };
  
  static struct attribute_group mt_attribute_group = {
  	.attrs = sysfs_attrs
  };
f635bd11c   Henrik Rydberg   HID: Do not creat...
225
  static void mt_feature_mapping(struct hid_device *hdev,
5519cab47   Benjamin Tissoires   HID: hid-multitou...
226
227
  		struct hid_field *field, struct hid_usage *usage)
  {
9498f954a   Benjamin Tissoires   HID: hid-multitou...
228
229
230
231
  	struct mt_device *td = hid_get_drvdata(hdev);
  
  	switch (usage->hid) {
  	case HID_DG_INPUTMODE:
5519cab47   Benjamin Tissoires   HID: hid-multitou...
232
  		td->inputmode = field->report->id;
9498f954a   Benjamin Tissoires   HID: hid-multitou...
233
234
235
  		break;
  	case HID_DG_CONTACTMAX:
  		td->maxcontacts = field->value[0];
eec29e3da   Benjamin Tissoires   HID: multitouch: ...
236
  		if (td->mtclass.maxcontacts)
9498f954a   Benjamin Tissoires   HID: hid-multitou...
237
  			/* check if the maxcontacts is given by the class */
eec29e3da   Benjamin Tissoires   HID: multitouch: ...
238
  			td->maxcontacts = td->mtclass.maxcontacts;
9498f954a   Benjamin Tissoires   HID: hid-multitou...
239
240
  
  		break;
5519cab47   Benjamin Tissoires   HID: hid-multitou...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
  	}
  }
  
  static void set_abs(struct input_dev *input, unsigned int code,
  		struct hid_field *field, int snratio)
  {
  	int fmin = field->logical_minimum;
  	int fmax = field->logical_maximum;
  	int fuzz = snratio ? (fmax - fmin) / snratio : 0;
  	input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
  }
  
  static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
  		struct hid_field *field, struct hid_usage *usage,
  		unsigned long **bit, int *max)
  {
  	struct mt_device *td = hid_get_drvdata(hdev);
eec29e3da   Benjamin Tissoires   HID: multitouch: ...
258
  	struct mt_class *cls = &td->mtclass;
4875ac114   Richard Nauber   HID: merge hid-eg...
259

658d4aed5   Jeff Brown   HID: hid-multitou...
260
261
262
263
264
265
266
267
268
  	/* Only map fields from TouchScreen or TouchPad collections.
           * We need to ignore fields that belong to other collections
           * such as Mouse that might have the same GenericDesktop usages. */
  	if (field->application == HID_DG_TOUCHSCREEN)
  		set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
  	else if (field->application == HID_DG_TOUCHPAD)
  		set_bit(INPUT_PROP_POINTER, hi->input->propbit);
  	else
  		return 0;
2261bb9ff   Benjamin Tissoires   HID: multitouch: ...
269
270
271
272
273
  	/* eGalax devices provide a Digitizer.Stylus input which overrides
  	 * the correct Digitizers.Finger X/Y ranges.
  	 * Let's just ignore this input. */
  	if (field->physical == HID_DG_STYLUS)
  		return -1;
5519cab47   Benjamin Tissoires   HID: hid-multitou...
274
275
276
277
278
279
280
281
282
283
284
  	switch (usage->hid & HID_USAGE_PAGE) {
  
  	case HID_UP_GENDESK:
  		switch (usage->hid) {
  		case HID_GD_X:
  			hid_map_usage(hi, usage, bit, max,
  					EV_ABS, ABS_MT_POSITION_X);
  			set_abs(hi->input, ABS_MT_POSITION_X, field,
  				cls->sn_move);
  			/* touchscreen emulation */
  			set_abs(hi->input, ABS_X, field, cls->sn_move);
b84bd27fe   Benjamin Tissoires   HID: hid-multitou...
285
286
287
288
  			if (td->last_mt_collection == usage->collection_index) {
  				td->last_slot_field = usage->hid;
  				td->last_field_index = field->index;
  			}
5519cab47   Benjamin Tissoires   HID: hid-multitou...
289
290
291
292
293
294
295
296
  			return 1;
  		case HID_GD_Y:
  			hid_map_usage(hi, usage, bit, max,
  					EV_ABS, ABS_MT_POSITION_Y);
  			set_abs(hi->input, ABS_MT_POSITION_Y, field,
  				cls->sn_move);
  			/* touchscreen emulation */
  			set_abs(hi->input, ABS_Y, field, cls->sn_move);
b84bd27fe   Benjamin Tissoires   HID: hid-multitou...
297
298
299
300
  			if (td->last_mt_collection == usage->collection_index) {
  				td->last_slot_field = usage->hid;
  				td->last_field_index = field->index;
  			}
5519cab47   Benjamin Tissoires   HID: hid-multitou...
301
302
303
304
305
306
307
  			return 1;
  		}
  		return 0;
  
  	case HID_UP_DIGITIZER:
  		switch (usage->hid) {
  		case HID_DG_INRANGE:
b84bd27fe   Benjamin Tissoires   HID: hid-multitou...
308
309
310
311
  			if (td->last_mt_collection == usage->collection_index) {
  				td->last_slot_field = usage->hid;
  				td->last_field_index = field->index;
  			}
5519cab47   Benjamin Tissoires   HID: hid-multitou...
312
313
  			return 1;
  		case HID_DG_CONFIDENCE:
b84bd27fe   Benjamin Tissoires   HID: hid-multitou...
314
315
316
317
  			if (td->last_mt_collection == usage->collection_index) {
  				td->last_slot_field = usage->hid;
  				td->last_field_index = field->index;
  			}
5519cab47   Benjamin Tissoires   HID: hid-multitou...
318
319
320
321
  			return 1;
  		case HID_DG_TIPSWITCH:
  			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
  			input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
b84bd27fe   Benjamin Tissoires   HID: hid-multitou...
322
323
324
325
  			if (td->last_mt_collection == usage->collection_index) {
  				td->last_slot_field = usage->hid;
  				td->last_field_index = field->index;
  			}
5519cab47   Benjamin Tissoires   HID: hid-multitou...
326
327
  			return 1;
  		case HID_DG_CONTACTID:
50bc03ab5   Benjamin Tissoires   HID: hid-multitou...
328
329
  			if (!td->maxcontacts)
  				td->maxcontacts = MT_DEFAULT_MAXCONTACT;
9498f954a   Benjamin Tissoires   HID: hid-multitou...
330
  			input_mt_init_slots(hi->input, td->maxcontacts);
5519cab47   Benjamin Tissoires   HID: hid-multitou...
331
  			td->last_slot_field = usage->hid;
2955caed8   Benjamin Tissoires   HID: hid-multitou...
332
  			td->last_field_index = field->index;
b84bd27fe   Benjamin Tissoires   HID: hid-multitou...
333
  			td->last_mt_collection = usage->collection_index;
5519cab47   Benjamin Tissoires   HID: hid-multitou...
334
335
336
337
  			return 1;
  		case HID_DG_WIDTH:
  			hid_map_usage(hi, usage, bit, max,
  					EV_ABS, ABS_MT_TOUCH_MAJOR);
f786bba44   Benjamin Tissoires   HID: hid-multitou...
338
339
  			set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
  				cls->sn_width);
b84bd27fe   Benjamin Tissoires   HID: hid-multitou...
340
341
342
343
  			if (td->last_mt_collection == usage->collection_index) {
  				td->last_slot_field = usage->hid;
  				td->last_field_index = field->index;
  			}
5519cab47   Benjamin Tissoires   HID: hid-multitou...
344
345
346
347
  			return 1;
  		case HID_DG_HEIGHT:
  			hid_map_usage(hi, usage, bit, max,
  					EV_ABS, ABS_MT_TOUCH_MINOR);
f786bba44   Benjamin Tissoires   HID: hid-multitou...
348
349
  			set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
  				cls->sn_height);
1e648a137   Benjamin Tissoires   HID: hid-multitou...
350
351
  			input_set_abs_params(hi->input,
  					ABS_MT_ORIENTATION, 0, 1, 0, 0);
b84bd27fe   Benjamin Tissoires   HID: hid-multitou...
352
353
354
355
  			if (td->last_mt_collection == usage->collection_index) {
  				td->last_slot_field = usage->hid;
  				td->last_field_index = field->index;
  			}
5519cab47   Benjamin Tissoires   HID: hid-multitou...
356
357
358
359
360
361
362
363
364
  			return 1;
  		case HID_DG_TIPPRESSURE:
  			hid_map_usage(hi, usage, bit, max,
  					EV_ABS, ABS_MT_PRESSURE);
  			set_abs(hi->input, ABS_MT_PRESSURE, field,
  				cls->sn_pressure);
  			/* touchscreen emulation */
  			set_abs(hi->input, ABS_PRESSURE, field,
  				cls->sn_pressure);
b84bd27fe   Benjamin Tissoires   HID: hid-multitou...
365
366
367
368
  			if (td->last_mt_collection == usage->collection_index) {
  				td->last_slot_field = usage->hid;
  				td->last_field_index = field->index;
  			}
5519cab47   Benjamin Tissoires   HID: hid-multitou...
369
370
  			return 1;
  		case HID_DG_CONTACTCOUNT:
b84bd27fe   Benjamin Tissoires   HID: hid-multitou...
371
372
  			if (td->last_mt_collection == usage->collection_index)
  				td->last_field_index = field->index;
5519cab47   Benjamin Tissoires   HID: hid-multitou...
373
374
375
376
  			return 1;
  		case HID_DG_CONTACTMAX:
  			/* we don't set td->last_slot_field as contactcount and
  			 * contact max are global to the report */
b84bd27fe   Benjamin Tissoires   HID: hid-multitou...
377
378
  			if (td->last_mt_collection == usage->collection_index)
  				td->last_field_index = field->index;
5519cab47   Benjamin Tissoires   HID: hid-multitou...
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
  			return -1;
  		}
  		/* let hid-input decide for the others */
  		return 0;
  
  	case 0xff000000:
  		/* we do not want to map these: no input-oriented meaning */
  		return -1;
  	}
  
  	return 0;
  }
  
  static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
  		struct hid_field *field, struct hid_usage *usage,
  		unsigned long **bit, int *max)
  {
  	if (usage->type == EV_KEY || usage->type == EV_ABS)
  		set_bit(usage->type, hi->input->evbit);
  
  	return -1;
  }
  
  static int mt_compute_slot(struct mt_device *td)
  {
eec29e3da   Benjamin Tissoires   HID: multitouch: ...
404
  	__s32 quirks = td->mtclass.quirks;
5519cab47   Benjamin Tissoires   HID: hid-multitou...
405

2d93666e7   Benjamin Tissoires   HID: hid-multitou...
406
407
  	if (quirks & MT_QUIRK_SLOT_IS_CONTACTID)
  		return td->curdata.contactid;
5519cab47   Benjamin Tissoires   HID: hid-multitou...
408

2d93666e7   Benjamin Tissoires   HID: hid-multitou...
409
  	if (quirks & MT_QUIRK_CYPRESS)
a3b5e577d   Benjamin Tissoires   HID: hid-multitou...
410
  		return cypress_compute_slot(td);
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
411
412
  	if (quirks & MT_QUIRK_SLOT_IS_CONTACTNUMBER)
  		return td->num_received;
5572da08a   Benjamin Tissoires   HID: hid-mulitouc...
413

4a6ee685f   Benjamin Tissoires   HID: hid-multitou...
414
415
  	if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE)
  		return td->curdata.contactid - 1;
5519cab47   Benjamin Tissoires   HID: hid-multitou...
416
417
418
419
420
421
422
423
424
  	return find_slot_from_contactid(td);
  }
  
  /*
   * this function is called when a whole contact has been processed,
   * so that it can assign it to a slot and store the data there
   */
  static void mt_complete_slot(struct mt_device *td)
  {
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
425
  	td->curdata.seen_in_this_frame = true;
5519cab47   Benjamin Tissoires   HID: hid-multitou...
426
  	if (td->curvalid) {
5519cab47   Benjamin Tissoires   HID: hid-multitou...
427
  		int slotnum = mt_compute_slot(td);
9498f954a   Benjamin Tissoires   HID: hid-multitou...
428
  		if (slotnum >= 0 && slotnum < td->maxcontacts)
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
429
  			td->slots[slotnum] = td->curdata;
5519cab47   Benjamin Tissoires   HID: hid-multitou...
430
431
432
433
434
435
436
437
438
439
440
441
  	}
  	td->num_received++;
  }
  
  
  /*
   * this function is called when a whole packet has been received and processed,
   * so that it can decide what to send to the input layer.
   */
  static void mt_emit_event(struct mt_device *td, struct input_dev *input)
  {
  	int i;
9498f954a   Benjamin Tissoires   HID: hid-multitou...
442
  	for (i = 0; i < td->maxcontacts; ++i) {
5519cab47   Benjamin Tissoires   HID: hid-multitou...
443
  		struct mt_slot *s = &(td->slots[i]);
eec29e3da   Benjamin Tissoires   HID: multitouch: ...
444
  		if ((td->mtclass.quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) &&
5519cab47   Benjamin Tissoires   HID: hid-multitou...
445
  			!s->seen_in_this_frame) {
5519cab47   Benjamin Tissoires   HID: hid-multitou...
446
447
448
449
450
451
  			s->touch_state = false;
  		}
  
  		input_mt_slot(input, i);
  		input_mt_report_slot_state(input, MT_TOOL_FINGER,
  			s->touch_state);
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
452
  		if (s->touch_state) {
f786bba44   Benjamin Tissoires   HID: hid-multitou...
453
454
455
456
457
  			/* this finger is on the screen */
  			int wide = (s->w > s->h);
  			/* divided by two to match visual scale of touch */
  			int major = max(s->w, s->h) >> 1;
  			int minor = min(s->w, s->h) >> 1;
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
458
459
  			input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x);
  			input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y);
f786bba44   Benjamin Tissoires   HID: hid-multitou...
460
  			input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
461
  			input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
f786bba44   Benjamin Tissoires   HID: hid-multitou...
462
463
  			input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
  			input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
464
  		}
5519cab47   Benjamin Tissoires   HID: hid-multitou...
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
  		s->seen_in_this_frame = false;
  
  	}
  
  	input_mt_report_pointer_emulation(input, true);
  	input_sync(input);
  	td->num_received = 0;
  }
  
  
  
  static int mt_event(struct hid_device *hid, struct hid_field *field,
  				struct hid_usage *usage, __s32 value)
  {
  	struct mt_device *td = hid_get_drvdata(hid);
eec29e3da   Benjamin Tissoires   HID: multitouch: ...
480
  	__s32 quirks = td->mtclass.quirks;
5519cab47   Benjamin Tissoires   HID: hid-multitou...
481

9498f954a   Benjamin Tissoires   HID: hid-multitou...
482
  	if (hid->claimed & HID_CLAIMED_INPUT && td->slots) {
5519cab47   Benjamin Tissoires   HID: hid-multitou...
483
484
  		switch (usage->hid) {
  		case HID_DG_INRANGE:
a062cc5a7   Stephane Chatty   HID: hid-multitou...
485
486
487
  			if (quirks & MT_QUIRK_ALWAYS_VALID)
  				td->curvalid = true;
  			else if (quirks & MT_QUIRK_VALID_IS_INRANGE)
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
488
  				td->curvalid = value;
5519cab47   Benjamin Tissoires   HID: hid-multitou...
489
490
  			break;
  		case HID_DG_TIPSWITCH:
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
491
492
  			if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
  				td->curvalid = value;
5519cab47   Benjamin Tissoires   HID: hid-multitou...
493
494
495
  			td->curdata.touch_state = value;
  			break;
  		case HID_DG_CONFIDENCE:
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
496
497
  			if (quirks & MT_QUIRK_VALID_IS_CONFIDENCE)
  				td->curvalid = value;
5519cab47   Benjamin Tissoires   HID: hid-multitou...
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
  			break;
  		case HID_DG_CONTACTID:
  			td->curdata.contactid = value;
  			break;
  		case HID_DG_TIPPRESSURE:
  			td->curdata.p = value;
  			break;
  		case HID_GD_X:
  			td->curdata.x = value;
  			break;
  		case HID_GD_Y:
  			td->curdata.y = value;
  			break;
  		case HID_DG_WIDTH:
  			td->curdata.w = value;
  			break;
  		case HID_DG_HEIGHT:
  			td->curdata.h = value;
  			break;
  		case HID_DG_CONTACTCOUNT:
  			/*
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
519
520
  			 * Includes multi-packet support where subsequent
  			 * packets are sent with zero contactcount.
5519cab47   Benjamin Tissoires   HID: hid-multitou...
521
522
  			 */
  			if (value)
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
523
  				td->num_expected = value;
5519cab47   Benjamin Tissoires   HID: hid-multitou...
524
525
526
527
528
529
  			break;
  
  		default:
  			/* fallback to the generic hidinput handling */
  			return 0;
  		}
5519cab47   Benjamin Tissoires   HID: hid-multitou...
530

f153fc399   Henrik Rydberg   HID: hid-multitou...
531
  		if (usage->hid == td->last_slot_field) {
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
532
  			mt_complete_slot(td);
f153fc399   Henrik Rydberg   HID: hid-multitou...
533
  		}
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
534
535
536
537
  
  		if (field->index == td->last_field_index
  			&& td->num_received >= td->num_expected)
  			mt_emit_event(td, field->hidinput->input);
5519cab47   Benjamin Tissoires   HID: hid-multitou...
538

2d93666e7   Benjamin Tissoires   HID: hid-multitou...
539
  	}
5519cab47   Benjamin Tissoires   HID: hid-multitou...
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
  
  	/* we have handled the hidinput part, now remains hiddev */
  	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
  		hid->hiddev_hid_event(hid, field, usage, value);
  
  	return 1;
  }
  
  static void mt_set_input_mode(struct hid_device *hdev)
  {
  	struct mt_device *td = hid_get_drvdata(hdev);
  	struct hid_report *r;
  	struct hid_report_enum *re;
  
  	if (td->inputmode < 0)
  		return;
  
  	re = &(hdev->report_enum[HID_FEATURE_REPORT]);
  	r = re->report_id_hash[td->inputmode];
  	if (r) {
  		r->field[0]->value[0] = 0x02;
  		usbhid_submit_report(hdev, r, USB_DIR_OUT);
  	}
  }
  
  static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
  {
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
567
  	int ret, i;
5519cab47   Benjamin Tissoires   HID: hid-multitou...
568
  	struct mt_device *td;
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
569
570
571
572
573
574
575
576
  	struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
  
  	for (i = 0; mt_classes[i].name ; i++) {
  		if (id->driver_data == mt_classes[i].name) {
  			mtclass = &(mt_classes[i]);
  			break;
  		}
  	}
5519cab47   Benjamin Tissoires   HID: hid-multitou...
577

d682bd7f3   Henrik Rydberg   Revert "HID: mult...
578
579
580
581
  	/* This allows the driver to correctly support devices
  	 * that emit events over several HID messages.
  	 */
  	hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
5519cab47   Benjamin Tissoires   HID: hid-multitou...
582

9498f954a   Benjamin Tissoires   HID: hid-multitou...
583
  	td = kzalloc(sizeof(struct mt_device), GFP_KERNEL);
5519cab47   Benjamin Tissoires   HID: hid-multitou...
584
585
586
587
588
  	if (!td) {
  		dev_err(&hdev->dev, "cannot allocate multitouch data
  ");
  		return -ENOMEM;
  	}
eec29e3da   Benjamin Tissoires   HID: multitouch: ...
589
  	td->mtclass = *mtclass;
5519cab47   Benjamin Tissoires   HID: hid-multitou...
590
  	td->inputmode = -1;
b84bd27fe   Benjamin Tissoires   HID: hid-multitou...
591
  	td->last_mt_collection = -1;
5519cab47   Benjamin Tissoires   HID: hid-multitou...
592
593
594
595
596
597
598
  	hid_set_drvdata(hdev, td);
  
  	ret = hid_parse(hdev);
  	if (ret != 0)
  		goto fail;
  
  	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
2d93666e7   Benjamin Tissoires   HID: hid-multitou...
599
  	if (ret)
5519cab47   Benjamin Tissoires   HID: hid-multitou...
600
  		goto fail;
9498f954a   Benjamin Tissoires   HID: hid-multitou...
601
602
603
604
605
606
607
608
609
  	td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot),
  				GFP_KERNEL);
  	if (!td->slots) {
  		dev_err(&hdev->dev, "cannot allocate multitouch slots
  ");
  		hid_hw_stop(hdev);
  		ret = -ENOMEM;
  		goto fail;
  	}
eec29e3da   Benjamin Tissoires   HID: multitouch: ...
610
  	ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group);
5519cab47   Benjamin Tissoires   HID: hid-multitou...
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
  	mt_set_input_mode(hdev);
  
  	return 0;
  
  fail:
  	kfree(td);
  	return ret;
  }
  
  #ifdef CONFIG_PM
  static int mt_reset_resume(struct hid_device *hdev)
  {
  	mt_set_input_mode(hdev);
  	return 0;
  }
  #endif
  
  static void mt_remove(struct hid_device *hdev)
  {
  	struct mt_device *td = hid_get_drvdata(hdev);
eec29e3da   Benjamin Tissoires   HID: multitouch: ...
631
  	sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
5519cab47   Benjamin Tissoires   HID: hid-multitou...
632
  	hid_hw_stop(hdev);
9498f954a   Benjamin Tissoires   HID: hid-multitou...
633
  	kfree(td->slots);
5519cab47   Benjamin Tissoires   HID: hid-multitou...
634
635
636
637
638
  	kfree(td);
  	hid_set_drvdata(hdev, NULL);
  }
  
  static const struct hid_device_id mt_devices[] = {
f786bba44   Benjamin Tissoires   HID: hid-multitou...
639
640
641
642
643
644
645
  	/* 3M panels */
  	{ .driver_data = MT_CLS_3M,
  		HID_USB_DEVICE(USB_VENDOR_ID_3M,
  			USB_DEVICE_ID_3M1968) },
  	{ .driver_data = MT_CLS_3M,
  		HID_USB_DEVICE(USB_VENDOR_ID_3M,
  			USB_DEVICE_ID_3M2256) },
c4fad877c   Benjamin Tissoires   HID: multitouch: ...
646
647
648
  	{ .driver_data = MT_CLS_3M,
  		HID_USB_DEVICE(USB_VENDOR_ID_3M,
  			USB_DEVICE_ID_3M3266) },
f786bba44   Benjamin Tissoires   HID: hid-multitou...
649

e6aac3427   Benjamin Tissoires   HID: hid-multitou...
650
651
652
653
  	/* ActionStar panels */
  	{ .driver_data = MT_CLS_DEFAULT,
  		HID_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR,
  			USB_DEVICE_ID_ACTIONSTAR_1011) },
b10571246   Benjamin Tissoires   HID: multitouch: ...
654
655
656
657
  	/* Atmel panels */
  	{ .driver_data = MT_CLS_SERIAL,
  		HID_USB_DEVICE(USB_VENDOR_ID_ATMEL,
  			USB_DEVICE_ID_ATMEL_MULTITOUCH) },
a841b62c5   Benjamin Tissoires   HID: hid-multitou...
658
659
660
661
662
663
664
665
666
667
668
669
670
  	/* Cando panels */
  	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
  		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
  			USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
  	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
  		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
  			USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) },
  	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
  		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
  			USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
  	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
  		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
  			USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
942fd4225   Austin Zhang   HID: hid-multitou...
671
672
673
674
  	/* Chunghwa Telecom touch panels */
  	{  .driver_data = MT_CLS_DEFAULT,
  		HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT,
  			USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) },
79603dc9a   Benjamin Tissoires   HID: hid-multitou...
675
676
677
678
  	/* CVTouch panels */
  	{ .driver_data = MT_CLS_DEFAULT,
  		HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH,
  			USB_DEVICE_ID_CVTOUCH_SCREEN) },
a3b5e577d   Benjamin Tissoires   HID: hid-multitou...
679
680
681
682
  	/* Cypress panel */
  	{ .driver_data = MT_CLS_CYPRESS,
  		HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS,
  			USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
22408283b   Benjamin Tissoires   HID: hid-multitou...
683
  	/* eGalax devices (resistive) */
e36f690b3   Benjamin Tissoires   HID: multitouch: ...
684
  	{ .driver_data = MT_CLS_EGALAX,
22408283b   Benjamin Tissoires   HID: hid-multitou...
685
  		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
e36f690b3   Benjamin Tissoires   HID: multitouch: ...
686
687
  			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D) },
  	{ .driver_data = MT_CLS_EGALAX,
22408283b   Benjamin Tissoires   HID: hid-multitou...
688
  		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
e36f690b3   Benjamin Tissoires   HID: multitouch: ...
689
  			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E) },
22408283b   Benjamin Tissoires   HID: hid-multitou...
690
691
  
  	/* eGalax devices (capacitive) */
e36f690b3   Benjamin Tissoires   HID: multitouch: ...
692
  	{ .driver_data = MT_CLS_EGALAX,
22408283b   Benjamin Tissoires   HID: hid-multitou...
693
  		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
e36f690b3   Benjamin Tissoires   HID: multitouch: ...
694
695
  			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C) },
  	{ .driver_data = MT_CLS_EGALAX,
22408283b   Benjamin Tissoires   HID: hid-multitou...
696
  		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
e36f690b3   Benjamin Tissoires   HID: multitouch: ...
697
698
  			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B) },
  	{ .driver_data = MT_CLS_EGALAX,
22408283b   Benjamin Tissoires   HID: hid-multitou...
699
  		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
e36f690b3   Benjamin Tissoires   HID: multitouch: ...
700
701
  			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1) },
  	{ .driver_data = MT_CLS_EGALAX,
1fd8f0474   Chris Bagwell   HID: hid-multitou...
702
  		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
66f06127f   Benjamin Tissoires   HID: multitouch: ...
703
704
705
  			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA) },
  	{ .driver_data = MT_CLS_EGALAX,
  		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
bb9ff2107   Marek Vasut   HID: multitouch: ...
706
  			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302) },
1b723e8dc   Benjamin Tissoires   HID: multitouch: ...
707
  	{ .driver_data = MT_CLS_EGALAX_SERIAL,
bb9ff2107   Marek Vasut   HID: multitouch: ...
708
  		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
e36f690b3   Benjamin Tissoires   HID: multitouch: ...
709
  			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) },
22408283b   Benjamin Tissoires   HID: hid-multitou...
710

c04abeeff   Benjamin Tissoires   HID: hid-multitou...
711
712
713
714
  	/* Elo TouchSystems IntelliTouch Plus panel */
  	{ .driver_data = MT_CLS_DUAL_NSMU_CONTACTID,
  		HID_USB_DEVICE(USB_VENDOR_ID_ELO,
  			USB_DEVICE_ID_ELO_TS2515) },
5572da08a   Benjamin Tissoires   HID: hid-mulitouc...
715
  	/* GeneralTouch panel */
1e9cf35b9   Benjamin Tissoires   HID: hid-multitou...
716
  	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
5572da08a   Benjamin Tissoires   HID: hid-mulitouc...
717
718
  		HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
  			USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
ee0fbd149   Benjamin Tissoires   HID: hid-multitou...
719
720
721
722
  	/* GoodTouch panels */
  	{ .driver_data = MT_CLS_DEFAULT,
  		HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH,
  			USB_DEVICE_ID_GOODTOUCH_000f) },
545803651   Benjamin Tissoires   HID: hid-multitou...
723
724
725
726
  	/* Hanvon panels */
  	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
  		HID_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT,
  			USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) },
a062cc5a7   Stephane Chatty   HID: hid-multitou...
727
728
729
730
  	/* Ideacom panel */
  	{ .driver_data = MT_CLS_SERIAL,
  		HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM,
  			USB_DEVICE_ID_IDEACOM_IDC6650) },
4e61f0d75   Austin Zhang   HID: hid-multitou...
731
732
733
734
  	/* Ilitek dual touch panel */
  	{  .driver_data = MT_CLS_DEFAULT,
  		HID_USB_DEVICE(USB_VENDOR_ID_ILITEK,
  			USB_DEVICE_ID_ILITEK_MULTITOUCH) },
4dfcced8a   Benjamin Tissoires   HID: hid-multitou...
735
736
737
738
  	/* IRTOUCH panels */
  	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
  		HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS,
  			USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
c50bb1a40   Jeff Brown   HID: hid-multitou...
739
740
741
742
  	/* LG Display panels */
  	{ .driver_data = MT_CLS_DEFAULT,
  		HID_USB_DEVICE(USB_VENDOR_ID_LG,
  			USB_DEVICE_ID_LG_MULTITOUCH) },
df167c4a0   Benjamin Tissoires   HID: hid-multitou...
743
744
745
746
  	/* Lumio panels */
  	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
  		HID_USB_DEVICE(USB_VENDOR_ID_LUMIO,
  			USB_DEVICE_ID_CRYSTALTOUCH) },
c3ead6de4   Benjamin Tissoires   HID: hid-multitou...
747
748
749
  	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
  		HID_USB_DEVICE(USB_VENDOR_ID_LUMIO,
  			USB_DEVICE_ID_CRYSTALTOUCH_DUAL) },
df167c4a0   Benjamin Tissoires   HID: hid-multitou...
750

4a6ee685f   Benjamin Tissoires   HID: hid-multitou...
751
752
753
754
755
756
757
758
759
760
  	/* MosArt panels */
  	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
  		HID_USB_DEVICE(USB_VENDOR_ID_ASUS,
  			USB_DEVICE_ID_ASUS_T91MT)},
  	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
  		HID_USB_DEVICE(USB_VENDOR_ID_ASUS,
  			USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) },
  	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
  		HID_USB_DEVICE(USB_VENDOR_ID_TURBOX,
  			USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) },
6ab3a9a63   John Sung   HID: hid-multitou...
761
762
763
764
  	/* PenMount panels */
  	{ .driver_data = MT_CLS_CONFIDENCE,
  		HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT,
  			USB_DEVICE_ID_PENMOUNT_PCI) },
b7ea95ff9   Aaron Tian   HID: multitouch: ...
765
766
767
768
769
770
771
772
773
774
  	/* PixArt optical touch screen */
  	{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
  		HID_USB_DEVICE(USB_VENDOR_ID_PIXART,
  			USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN) },
  	{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
  		HID_USB_DEVICE(USB_VENDOR_ID_PIXART,
  			USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1) },
  	{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
  		HID_USB_DEVICE(USB_VENDOR_ID_PIXART,
  			USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2) },
5519cab47   Benjamin Tissoires   HID: hid-multitou...
775
  	/* PixCir-based panels */
1e9cf35b9   Benjamin Tissoires   HID: hid-multitou...
776
  	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
5519cab47   Benjamin Tissoires   HID: hid-multitou...
777
778
  		HID_USB_DEVICE(USB_VENDOR_ID_HANVON,
  			USB_DEVICE_ID_HANVON_MULTITOUCH) },
1e9cf35b9   Benjamin Tissoires   HID: hid-multitou...
779
  	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
5519cab47   Benjamin Tissoires   HID: hid-multitou...
780
781
  		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
  			USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
5e7ea11f6   Benjamin Tissoires   HID: multitouch: ...
782
783
784
785
786
787
788
789
790
791
  	/* Quanta-based panels */
  	{ .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID,
  		HID_USB_DEVICE(USB_VENDOR_ID_QUANTA,
  			USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
  	{ .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID,
  		HID_USB_DEVICE(USB_VENDOR_ID_QUANTA,
  			USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001) },
  	{ .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID,
  		HID_USB_DEVICE(USB_VENDOR_ID_QUANTA,
  			USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008) },
043b403ae   Benjamin Tissoires   HID: hid-multitou...
792
  	/* Stantum panels */
bf5af9b5b   Benjamin Tissoires   HID: hid-multitou...
793
  	{ .driver_data = MT_CLS_CONFIDENCE,
043b403ae   Benjamin Tissoires   HID: hid-multitou...
794
795
  		HID_USB_DEVICE(USB_VENDOR_ID_STANTUM,
  			USB_DEVICE_ID_MTP)},
bf5af9b5b   Benjamin Tissoires   HID: hid-multitou...
796
  	{ .driver_data = MT_CLS_CONFIDENCE,
85a600825   Benjamin Tissoires   HID: hid-multitou...
797
  		HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM,
043b403ae   Benjamin Tissoires   HID: hid-multitou...
798
  			USB_DEVICE_ID_MTP_STM)},
bf5af9b5b   Benjamin Tissoires   HID: hid-multitou...
799
  	{ .driver_data = MT_CLS_CONFIDENCE,
85a600825   Benjamin Tissoires   HID: hid-multitou...
800
  		HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX,
043b403ae   Benjamin Tissoires   HID: hid-multitou...
801
  			USB_DEVICE_ID_MTP_SITRONIX)},
5e74e56da   Benjamin Tissoires   HID: hid-multitou...
802
803
804
805
  	/* Touch International panels */
  	{ .driver_data = MT_CLS_DEFAULT,
  		HID_USB_DEVICE(USB_VENDOR_ID_TOUCH_INTL,
  			USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH) },
617b64f97   Benjamin Tissoires   HID: hid-multitou...
806
807
808
809
810
811
812
  	/* Unitec panels */
  	{ .driver_data = MT_CLS_DEFAULT,
  		HID_USB_DEVICE(USB_VENDOR_ID_UNITEC,
  			USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) },
  	{ .driver_data = MT_CLS_DEFAULT,
  		HID_USB_DEVICE(USB_VENDOR_ID_UNITEC,
  			USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
bc8a2a9b4   ice chien   HID: hid-multitou...
813
814
815
816
  	/* XAT */
  	{ .driver_data = MT_CLS_DEFAULT,
  		HID_USB_DEVICE(USB_VENDOR_ID_XAT,
  			USB_DEVICE_ID_XAT_CSR) },
617b64f97   Benjamin Tissoires   HID: hid-multitou...
817

11576c611   Masatoshi Hoshikawa   HID: hid-multitou...
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
  	/* Xiroku */
  	{ .driver_data = MT_CLS_DEFAULT,
  		HID_USB_DEVICE(USB_VENDOR_ID_XIROKU,
  			USB_DEVICE_ID_XIROKU_SPX) },
  	{ .driver_data = MT_CLS_DEFAULT,
  		HID_USB_DEVICE(USB_VENDOR_ID_XIROKU,
  			USB_DEVICE_ID_XIROKU_MPX) },
  	{ .driver_data = MT_CLS_DEFAULT,
  		HID_USB_DEVICE(USB_VENDOR_ID_XIROKU,
  			USB_DEVICE_ID_XIROKU_CSR) },
  	{ .driver_data = MT_CLS_DEFAULT,
  		HID_USB_DEVICE(USB_VENDOR_ID_XIROKU,
  			USB_DEVICE_ID_XIROKU_SPX1) },
  	{ .driver_data = MT_CLS_DEFAULT,
  		HID_USB_DEVICE(USB_VENDOR_ID_XIROKU,
  			USB_DEVICE_ID_XIROKU_MPX1) },
  	{ .driver_data = MT_CLS_DEFAULT,
  		HID_USB_DEVICE(USB_VENDOR_ID_XIROKU,
  			USB_DEVICE_ID_XIROKU_CSR1) },
  	{ .driver_data = MT_CLS_DEFAULT,
  		HID_USB_DEVICE(USB_VENDOR_ID_XIROKU,
  			USB_DEVICE_ID_XIROKU_SPX2) },
  	{ .driver_data = MT_CLS_DEFAULT,
  		HID_USB_DEVICE(USB_VENDOR_ID_XIROKU,
  			USB_DEVICE_ID_XIROKU_MPX2) },
  	{ .driver_data = MT_CLS_DEFAULT,
  		HID_USB_DEVICE(USB_VENDOR_ID_XIROKU,
  			USB_DEVICE_ID_XIROKU_CSR2) },
5519cab47   Benjamin Tissoires   HID: hid-multitou...
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
  	{ }
  };
  MODULE_DEVICE_TABLE(hid, mt_devices);
  
  static const struct hid_usage_id mt_grabbed_usages[] = {
  	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
  	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
  };
  
  static struct hid_driver mt_driver = {
  	.name = "hid-multitouch",
  	.id_table = mt_devices,
  	.probe = mt_probe,
  	.remove = mt_remove,
  	.input_mapping = mt_input_mapping,
  	.input_mapped = mt_input_mapped,
  	.feature_mapping = mt_feature_mapping,
  	.usage_table = mt_grabbed_usages,
  	.event = mt_event,
  #ifdef CONFIG_PM
  	.reset_resume = mt_reset_resume,
  #endif
  };
  
  static int __init mt_init(void)
  {
  	return hid_register_driver(&mt_driver);
  }
  
  static void __exit mt_exit(void)
  {
  	hid_unregister_driver(&mt_driver);
  }
  
  module_init(mt_init);
  module_exit(mt_exit);