xref: /linux/drivers/hid/hid-multitouch.c (revision fb55b402)
15519cab4SBenjamin Tissoires /*
25519cab4SBenjamin Tissoires  *  HID driver for multitouch panels
35519cab4SBenjamin Tissoires  *
4c2ef8f21SBenjamin Tissoires  *  Copyright (c) 2010-2012 Stephane Chatty <chatty@enac.fr>
5b0a78681SBenjamin Tissoires  *  Copyright (c) 2010-2013 Benjamin Tissoires <benjamin.tissoires@gmail.com>
6c2ef8f21SBenjamin Tissoires  *  Copyright (c) 2010-2012 Ecole Nationale de l'Aviation Civile, France
7b0a78681SBenjamin Tissoires  *  Copyright (c) 2012-2013 Red Hat, Inc
85519cab4SBenjamin Tissoires  *
94875ac11SRichard Nauber  *  This code is partly based on hid-egalax.c:
104875ac11SRichard Nauber  *
114875ac11SRichard Nauber  *  Copyright (c) 2010 Stephane Chatty <chatty@enac.fr>
124875ac11SRichard Nauber  *  Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se>
134875ac11SRichard Nauber  *  Copyright (c) 2010 Canonical, Ltd.
144875ac11SRichard Nauber  *
15f786bba4SBenjamin Tissoires  *  This code is partly based on hid-3m-pct.c:
16f786bba4SBenjamin Tissoires  *
17f786bba4SBenjamin Tissoires  *  Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
18f786bba4SBenjamin Tissoires  *  Copyright (c) 2010      Henrik Rydberg <rydberg@euromail.se>
19f786bba4SBenjamin Tissoires  *  Copyright (c) 2010      Canonical, Ltd.
20f786bba4SBenjamin Tissoires  *
215519cab4SBenjamin Tissoires  */
225519cab4SBenjamin Tissoires 
235519cab4SBenjamin Tissoires /*
245519cab4SBenjamin Tissoires  * This program is free software; you can redistribute it and/or modify it
255519cab4SBenjamin Tissoires  * under the terms of the GNU General Public License as published by the Free
265519cab4SBenjamin Tissoires  * Software Foundation; either version 2 of the License, or (at your option)
275519cab4SBenjamin Tissoires  * any later version.
285519cab4SBenjamin Tissoires  */
295519cab4SBenjamin Tissoires 
30b0a78681SBenjamin Tissoires /*
31b0a78681SBenjamin Tissoires  * This driver is regularly tested thanks to the tool hid-test[1].
32b0a78681SBenjamin Tissoires  * This tool relies on hid-replay[2] and a database of hid devices[3].
33b0a78681SBenjamin Tissoires  * Please run these regression tests before patching this module so that
34b0a78681SBenjamin Tissoires  * your patch won't break existing known devices.
35b0a78681SBenjamin Tissoires  *
36b0a78681SBenjamin Tissoires  * [1] https://github.com/bentiss/hid-test
37b0a78681SBenjamin Tissoires  * [2] https://github.com/bentiss/hid-replay
38b0a78681SBenjamin Tissoires  * [3] https://github.com/bentiss/hid-devices
39b0a78681SBenjamin Tissoires  */
40b0a78681SBenjamin Tissoires 
415519cab4SBenjamin Tissoires #include <linux/device.h>
425519cab4SBenjamin Tissoires #include <linux/hid.h>
435519cab4SBenjamin Tissoires #include <linux/module.h>
445519cab4SBenjamin Tissoires #include <linux/slab.h>
455519cab4SBenjamin Tissoires #include <linux/input/mt.h>
4629cc309dSNicolas Boichat #include <linux/jiffies.h>
4749a5a827SBenjamin Tissoires #include <linux/string.h>
484f4001bcSBenjamin Tissoires #include <linux/timer.h>
495519cab4SBenjamin Tissoires 
505519cab4SBenjamin Tissoires 
515519cab4SBenjamin Tissoires MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
52ef2fafb3SBenjamin Tissoires MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
535519cab4SBenjamin Tissoires MODULE_DESCRIPTION("HID multitouch panels");
545519cab4SBenjamin Tissoires MODULE_LICENSE("GPL");
555519cab4SBenjamin Tissoires 
565519cab4SBenjamin Tissoires #include "hid-ids.h"
575519cab4SBenjamin Tissoires 
585519cab4SBenjamin Tissoires /* quirks to control the device */
59fd911896SBenjamin Tissoires #define MT_QUIRK_NOT_SEEN_MEANS_UP	BIT(0)
60fd911896SBenjamin Tissoires #define MT_QUIRK_SLOT_IS_CONTACTID	BIT(1)
61fd911896SBenjamin Tissoires #define MT_QUIRK_CYPRESS		BIT(2)
62fd911896SBenjamin Tissoires #define MT_QUIRK_SLOT_IS_CONTACTNUMBER	BIT(3)
63fd911896SBenjamin Tissoires #define MT_QUIRK_ALWAYS_VALID		BIT(4)
64fd911896SBenjamin Tissoires #define MT_QUIRK_VALID_IS_INRANGE	BIT(5)
65fd911896SBenjamin Tissoires #define MT_QUIRK_VALID_IS_CONFIDENCE	BIT(6)
66fd911896SBenjamin Tissoires #define MT_QUIRK_CONFIDENCE		BIT(7)
67fd911896SBenjamin Tissoires #define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE	BIT(8)
68fd911896SBenjamin Tissoires #define MT_QUIRK_NO_AREA		BIT(9)
69fd911896SBenjamin Tissoires #define MT_QUIRK_IGNORE_DUPLICATES	BIT(10)
70fd911896SBenjamin Tissoires #define MT_QUIRK_HOVERING		BIT(11)
71fd911896SBenjamin Tissoires #define MT_QUIRK_CONTACT_CNT_ACCURATE	BIT(12)
72fd911896SBenjamin Tissoires #define MT_QUIRK_FORCE_GET_FEATURE	BIT(13)
73fd911896SBenjamin Tissoires #define MT_QUIRK_FIX_CONST_CONTACT_ID	BIT(14)
74fd911896SBenjamin Tissoires #define MT_QUIRK_TOUCH_SIZE_SCALING	BIT(15)
754f4001bcSBenjamin Tissoires #define MT_QUIRK_STICKY_FINGERS		BIT(16)
76957b8dffSJoão Paulo Rechi Vita #define MT_QUIRK_ASUS_CUSTOM_UP		BIT(17)
775519cab4SBenjamin Tissoires 
789abebedbSAndrew Duggan #define MT_INPUTMODE_TOUCHSCREEN	0x02
799abebedbSAndrew Duggan #define MT_INPUTMODE_TOUCHPAD		0x03
809abebedbSAndrew Duggan 
812c6e0277SSeth Forshee #define MT_BUTTONTYPE_CLICKPAD		0
822c6e0277SSeth Forshee 
834f4001bcSBenjamin Tissoires #define MT_IO_FLAGS_RUNNING		0
8496098274SBenjamin Tissoires #define MT_IO_FLAGS_ACTIVE_SLOTS	1
8596098274SBenjamin Tissoires #define MT_IO_FLAGS_PENDING_SLOTS	2
864f4001bcSBenjamin Tissoires 
875519cab4SBenjamin Tissoires struct mt_slot {
88349fd670SBenjamin Tissoires 	__s32 x, y, cx, cy, p, w, h;
895519cab4SBenjamin Tissoires 	__s32 contactid;	/* the device ContactID assigned to this slot */
905519cab4SBenjamin Tissoires 	bool touch_state;	/* is the touch valid? */
919b3bb9b8SBenjamin Tissoires 	bool inrange_state;	/* is the finger in proximity of the sensor? */
926dd2e27aSAllen Hung 	bool confidence_state;  /* is the touch made by a finger? */
935519cab4SBenjamin Tissoires };
945519cab4SBenjamin Tissoires 
955519cab4SBenjamin Tissoires struct mt_class {
962d93666eSBenjamin Tissoires 	__s32 name;	/* MT_CLS */
975519cab4SBenjamin Tissoires 	__s32 quirks;
985519cab4SBenjamin Tissoires 	__s32 sn_move;	/* Signal/noise ratio for move events */
99f786bba4SBenjamin Tissoires 	__s32 sn_width;	/* Signal/noise ratio for width events */
100f786bba4SBenjamin Tissoires 	__s32 sn_height;	/* Signal/noise ratio for height events */
1015519cab4SBenjamin Tissoires 	__s32 sn_pressure;	/* Signal/noise ratio for pressure events */
1025519cab4SBenjamin Tissoires 	__u8 maxcontacts;
103c2ef8f21SBenjamin Tissoires 	bool is_indirect;	/* true for touchpads */
1046aef704eSBenjamin Tissoires 	bool export_all_inputs;	/* do not ignore mouse, keyboards, etc... */
1055519cab4SBenjamin Tissoires };
1065519cab4SBenjamin Tissoires 
1073ac36d15SBenjamin Tissoires struct mt_fields {
1083ac36d15SBenjamin Tissoires 	unsigned usages[HID_MAX_FIELDS];
1093ac36d15SBenjamin Tissoires 	unsigned int length;
1103ac36d15SBenjamin Tissoires };
1113ac36d15SBenjamin Tissoires 
1125519cab4SBenjamin Tissoires struct mt_device {
1135519cab4SBenjamin Tissoires 	struct mt_slot curdata;	/* placeholder of incoming data */
114eec29e3dSBenjamin Tissoires 	struct mt_class mtclass;	/* our mt device class */
1154f4001bcSBenjamin Tissoires 	struct timer_list release_timer;	/* to release sticky fingers */
1160ee32774SKees Cook 	struct hid_device *hdev;	/* hid_device we're attached to */
1173ac36d15SBenjamin Tissoires 	struct mt_fields *fields;	/* temporary placeholder for storing the
1183ac36d15SBenjamin Tissoires 					   multitouch fields */
1194f4001bcSBenjamin Tissoires 	unsigned long mt_io_flags;	/* mt flags (MT_IO_FLAGS_*) */
1207e3cc447SBenjamin Tissoires 	int cc_index;	/* contact count field index in the report */
1217e3cc447SBenjamin Tissoires 	int cc_value_index;	/* contact count value index in the field */
1225519cab4SBenjamin Tissoires 	unsigned last_slot_field;	/* the last field of a slot */
12355978fa9SBenjamin Tissoires 	unsigned mt_report_id;	/* the report ID of the multitouch device */
124b897f6dbSBenjamin Tissoires 	unsigned long initial_quirks;	/* initial quirks state */
1258821f5dcSBenjamin Tissoires 	__s16 inputmode;	/* InputMode HID feature, -1 if non-existent */
1268821f5dcSBenjamin Tissoires 	__s16 inputmode_index;	/* InputMode HID feature index in the report */
1278821f5dcSBenjamin Tissoires 	__s16 maxcontact_report_id;	/* Maximum Contact Number HID feature,
12831ae9bddSBenjamin Tissoires 				   -1 if non-existent */
1299abebedbSAndrew Duggan 	__u8 inputmode_value;  /* InputMode HID feature value */
1305519cab4SBenjamin Tissoires 	__u8 num_received;	/* how many contacts we received */
1315519cab4SBenjamin Tissoires 	__u8 num_expected;	/* expected last contact index */
1325519cab4SBenjamin Tissoires 	__u8 maxcontacts;
1339e87f22aSBenjamin Tissoires 	__u8 touches_by_report;	/* how many touches are present in one report:
1349e87f22aSBenjamin Tissoires 				* 1 means we should use a serial protocol
1359e87f22aSBenjamin Tissoires 				* > 1 means hybrid (multitouch) protocol */
136015fdaa9SBenjamin Tissoires 	__u8 buttons_count;	/* number of physical buttons per touchpad */
1372c6e0277SSeth Forshee 	bool is_buttonpad;	/* is this device a button pad? */
13876f5902aSHenrik Rydberg 	bool serial_maybe;	/* need to check for serial protocol */
1395519cab4SBenjamin Tissoires 	bool curvalid;		/* is the current contact valid? */
14076f5902aSHenrik Rydberg 	unsigned mt_flags;	/* flags to pass to input-mt */
14129cc309dSNicolas Boichat 	__s32 dev_time;		/* the scan time provided by the device */
14229cc309dSNicolas Boichat 	unsigned long jiffies;	/* the frame's jiffies */
14329cc309dSNicolas Boichat 	int timestamp;		/* the timestamp to be sent */
1445519cab4SBenjamin Tissoires };
1455519cab4SBenjamin Tissoires 
146a69c5f8bSBenjamin Tissoires static void mt_post_parse_default_settings(struct mt_device *td);
147a69c5f8bSBenjamin Tissoires static void mt_post_parse(struct mt_device *td);
148a69c5f8bSBenjamin Tissoires 
1495519cab4SBenjamin Tissoires /* classes of device behavior */
15022408283SBenjamin Tissoires #define MT_CLS_DEFAULT				0x0001
15122408283SBenjamin Tissoires 
152a062cc5aSStephane Chatty #define MT_CLS_SERIAL				0x0002
153a062cc5aSStephane Chatty #define MT_CLS_CONFIDENCE			0x0003
1545e7ea11fSBenjamin Tissoires #define MT_CLS_CONFIDENCE_CONTACT_ID		0x0004
1555e7ea11fSBenjamin Tissoires #define MT_CLS_CONFIDENCE_MINUS_ONE		0x0005
1565e7ea11fSBenjamin Tissoires #define MT_CLS_DUAL_INRANGE_CONTACTID		0x0006
1575e7ea11fSBenjamin Tissoires #define MT_CLS_DUAL_INRANGE_CONTACTNUMBER	0x0007
1580fa9c616SBenjamin Tissoires /* reserved					0x0008 */
159b7ea95ffSAaron Tian #define MT_CLS_INRANGE_CONTACTNUMBER		0x0009
160dc3e1d80SBenjamin Tissoires #define MT_CLS_NSMU				0x000a
1610fa9c616SBenjamin Tissoires /* reserved					0x0010 */
1620fa9c616SBenjamin Tissoires /* reserved					0x0011 */
163f961bd35SBenjamin Tissoires #define MT_CLS_WIN_8				0x0012
1646aef704eSBenjamin Tissoires #define MT_CLS_EXPORT_ALL_INPUTS		0x0013
165504c932cSMasaki Ota #define MT_CLS_WIN_8_DUAL			0x0014
16622408283SBenjamin Tissoires 
16722408283SBenjamin Tissoires /* vendor specific classes */
16822408283SBenjamin Tissoires #define MT_CLS_3M				0x0101
1690fa9c616SBenjamin Tissoires /* reserved					0x0102 */
17022408283SBenjamin Tissoires #define MT_CLS_EGALAX				0x0103
1711b723e8dSBenjamin Tissoires #define MT_CLS_EGALAX_SERIAL			0x0104
172847672cdSBenjamin Tissoires #define MT_CLS_TOPSEED				0x0105
1732258e863SDenis Kovalev #define MT_CLS_PANASONIC			0x0106
17477723e3bSHenrik Rydberg #define MT_CLS_FLATFROG				0x0107
175cdcd3ac4SJiri Kosina #define MT_CLS_GENERALTOUCH_TWOFINGERS		0x0108
176cdcd3ac4SJiri Kosina #define MT_CLS_GENERALTOUCH_PWT_TENFINGERS	0x0109
177f3287a99SBenjamin Tissoires #define MT_CLS_LG				0x010a
178957b8dffSJoão Paulo Rechi Vita #define MT_CLS_ASUS				0x010b
179da10bc25SMathieu Magnaudet #define MT_CLS_VTL				0x0110
1800e82232cSWei-Ning Huang #define MT_CLS_GOOGLE				0x0111
1815519cab4SBenjamin Tissoires 
1829498f954SBenjamin Tissoires #define MT_DEFAULT_MAXCONTACT	10
183afbcb04cSBenjamin Tissoires #define MT_MAX_MAXCONTACT	250
1849498f954SBenjamin Tissoires 
18529cc309dSNicolas Boichat /*
18629cc309dSNicolas Boichat  * Resync device and local timestamps after that many microseconds without
18729cc309dSNicolas Boichat  * receiving data.
18829cc309dSNicolas Boichat  */
18929cc309dSNicolas Boichat #define MAX_TIMESTAMP_INTERVAL	1000000
19029cc309dSNicolas Boichat 
1912c2110e9SHenrik Rydberg #define MT_USB_DEVICE(v, p)	HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH, v, p)
1922c2110e9SHenrik Rydberg #define MT_BT_DEVICE(v, p)	HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_MULTITOUCH, v, p)
1932c2110e9SHenrik Rydberg 
1945519cab4SBenjamin Tissoires /*
1955519cab4SBenjamin Tissoires  * these device-dependent functions determine what slot corresponds
1965519cab4SBenjamin Tissoires  * to a valid contact that was just read.
1975519cab4SBenjamin Tissoires  */
1985519cab4SBenjamin Tissoires 
199a3b5e577SBenjamin Tissoires static int cypress_compute_slot(struct mt_device *td)
200a3b5e577SBenjamin Tissoires {
201a3b5e577SBenjamin Tissoires 	if (td->curdata.contactid != 0 || td->num_received == 0)
202a3b5e577SBenjamin Tissoires 		return td->curdata.contactid;
203a3b5e577SBenjamin Tissoires 	else
204a3b5e577SBenjamin Tissoires 		return -1;
205a3b5e577SBenjamin Tissoires }
206a3b5e577SBenjamin Tissoires 
207b3c21d2cSJiri Kosina static struct mt_class mt_classes[] = {
2082d93666eSBenjamin Tissoires 	{ .name = MT_CLS_DEFAULT,
209dc3e1d80SBenjamin Tissoires 		.quirks = MT_QUIRK_ALWAYS_VALID |
210dc3e1d80SBenjamin Tissoires 			MT_QUIRK_CONTACT_CNT_ACCURATE },
211dc3e1d80SBenjamin Tissoires 	{ .name = MT_CLS_NSMU,
2129498f954SBenjamin Tissoires 		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP },
213a062cc5aSStephane Chatty 	{ .name = MT_CLS_SERIAL,
214a062cc5aSStephane Chatty 		.quirks = MT_QUIRK_ALWAYS_VALID},
21522408283SBenjamin Tissoires 	{ .name = MT_CLS_CONFIDENCE,
21622408283SBenjamin Tissoires 		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE },
2175e7ea11fSBenjamin Tissoires 	{ .name = MT_CLS_CONFIDENCE_CONTACT_ID,
2185e7ea11fSBenjamin Tissoires 		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
2195e7ea11fSBenjamin Tissoires 			MT_QUIRK_SLOT_IS_CONTACTID },
22022408283SBenjamin Tissoires 	{ .name = MT_CLS_CONFIDENCE_MINUS_ONE,
22122408283SBenjamin Tissoires 		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
22222408283SBenjamin Tissoires 			MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE },
2231e9cf35bSBenjamin Tissoires 	{ .name = MT_CLS_DUAL_INRANGE_CONTACTID,
2242d93666eSBenjamin Tissoires 		.quirks = MT_QUIRK_VALID_IS_INRANGE |
2252d93666eSBenjamin Tissoires 			MT_QUIRK_SLOT_IS_CONTACTID,
2262d93666eSBenjamin Tissoires 		.maxcontacts = 2 },
2271e9cf35bSBenjamin Tissoires 	{ .name = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
2282d93666eSBenjamin Tissoires 		.quirks = MT_QUIRK_VALID_IS_INRANGE |
2292d93666eSBenjamin Tissoires 			MT_QUIRK_SLOT_IS_CONTACTNUMBER,
2302d93666eSBenjamin Tissoires 		.maxcontacts = 2 },
231b7ea95ffSAaron Tian 	{ .name = MT_CLS_INRANGE_CONTACTNUMBER,
232b7ea95ffSAaron Tian 		.quirks = MT_QUIRK_VALID_IS_INRANGE |
233b7ea95ffSAaron Tian 			MT_QUIRK_SLOT_IS_CONTACTNUMBER },
234f961bd35SBenjamin Tissoires 	{ .name = MT_CLS_WIN_8,
235f961bd35SBenjamin Tissoires 		.quirks = MT_QUIRK_ALWAYS_VALID |
236f961bd35SBenjamin Tissoires 			MT_QUIRK_IGNORE_DUPLICATES |
237f961bd35SBenjamin Tissoires 			MT_QUIRK_HOVERING |
2384f4001bcSBenjamin Tissoires 			MT_QUIRK_CONTACT_CNT_ACCURATE |
2394f4001bcSBenjamin Tissoires 			MT_QUIRK_STICKY_FINGERS },
2406aef704eSBenjamin Tissoires 	{ .name = MT_CLS_EXPORT_ALL_INPUTS,
2416aef704eSBenjamin Tissoires 		.quirks = MT_QUIRK_ALWAYS_VALID |
2426aef704eSBenjamin Tissoires 			MT_QUIRK_CONTACT_CNT_ACCURATE,
2436aef704eSBenjamin Tissoires 		.export_all_inputs = true },
244504c932cSMasaki Ota 	{ .name = MT_CLS_WIN_8_DUAL,
245504c932cSMasaki Ota 		.quirks = MT_QUIRK_ALWAYS_VALID |
246504c932cSMasaki Ota 			MT_QUIRK_IGNORE_DUPLICATES |
247504c932cSMasaki Ota 			MT_QUIRK_HOVERING |
248504c932cSMasaki Ota 			MT_QUIRK_CONTACT_CNT_ACCURATE,
249504c932cSMasaki Ota 		.export_all_inputs = true },
25022408283SBenjamin Tissoires 
25122408283SBenjamin Tissoires 	/*
25222408283SBenjamin Tissoires 	 * vendor specific classes
25322408283SBenjamin Tissoires 	 */
25422408283SBenjamin Tissoires 	{ .name = MT_CLS_3M,
25522408283SBenjamin Tissoires 		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
256e9d0a26dSHungNien Chen 			MT_QUIRK_SLOT_IS_CONTACTID |
257e9d0a26dSHungNien Chen 			MT_QUIRK_TOUCH_SIZE_SCALING,
25822408283SBenjamin Tissoires 		.sn_move = 2048,
25922408283SBenjamin Tissoires 		.sn_width = 128,
260c5d40be5SHenrik Rydberg 		.sn_height = 128,
261c5d40be5SHenrik Rydberg 		.maxcontacts = 60,
262c5d40be5SHenrik Rydberg 	},
2634875ac11SRichard Nauber 	{ .name = MT_CLS_EGALAX,
2644875ac11SRichard Nauber 		.quirks =  MT_QUIRK_SLOT_IS_CONTACTID |
2652261bb9fSBenjamin Tissoires 			MT_QUIRK_VALID_IS_INRANGE,
2664875ac11SRichard Nauber 		.sn_move = 4096,
2674875ac11SRichard Nauber 		.sn_pressure = 32,
2684875ac11SRichard Nauber 	},
2691b723e8dSBenjamin Tissoires 	{ .name = MT_CLS_EGALAX_SERIAL,
2701b723e8dSBenjamin Tissoires 		.quirks =  MT_QUIRK_SLOT_IS_CONTACTID |
2711b723e8dSBenjamin Tissoires 			MT_QUIRK_ALWAYS_VALID,
2722d93666eSBenjamin Tissoires 		.sn_move = 4096,
2732d93666eSBenjamin Tissoires 		.sn_pressure = 32,
2742d93666eSBenjamin Tissoires 	},
275847672cdSBenjamin Tissoires 	{ .name = MT_CLS_TOPSEED,
276847672cdSBenjamin Tissoires 		.quirks = MT_QUIRK_ALWAYS_VALID,
277847672cdSBenjamin Tissoires 		.is_indirect = true,
278847672cdSBenjamin Tissoires 		.maxcontacts = 2,
279847672cdSBenjamin Tissoires 	},
2802258e863SDenis Kovalev 	{ .name = MT_CLS_PANASONIC,
2812258e863SDenis Kovalev 		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP,
2822258e863SDenis Kovalev 		.maxcontacts = 4 },
283f5ff4e1eSXianhan Yu 	{ .name	= MT_CLS_GENERALTOUCH_TWOFINGERS,
284f5ff4e1eSXianhan Yu 		.quirks	= MT_QUIRK_NOT_SEEN_MEANS_UP |
285f5ff4e1eSXianhan Yu 			MT_QUIRK_VALID_IS_INRANGE |
2867b226292SLuosong 			MT_QUIRK_SLOT_IS_CONTACTID,
287f5ff4e1eSXianhan Yu 		.maxcontacts = 2
288f5ff4e1eSXianhan Yu 	},
289f5ff4e1eSXianhan Yu 	{ .name	= MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
290f5ff4e1eSXianhan Yu 		.quirks	= MT_QUIRK_NOT_SEEN_MEANS_UP |
2917b226292SLuosong 			MT_QUIRK_SLOT_IS_CONTACTID
292f5ff4e1eSXianhan Yu 	},
293043b403aSBenjamin Tissoires 
29477723e3bSHenrik Rydberg 	{ .name = MT_CLS_FLATFROG,
29577723e3bSHenrik Rydberg 		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
29677723e3bSHenrik Rydberg 			MT_QUIRK_NO_AREA,
29777723e3bSHenrik Rydberg 		.sn_move = 2048,
29877723e3bSHenrik Rydberg 		.maxcontacts = 40,
29977723e3bSHenrik Rydberg 	},
300f3287a99SBenjamin Tissoires 	{ .name = MT_CLS_LG,
301f3287a99SBenjamin Tissoires 		.quirks = MT_QUIRK_ALWAYS_VALID |
302f3287a99SBenjamin Tissoires 			MT_QUIRK_FIX_CONST_CONTACT_ID |
303f3287a99SBenjamin Tissoires 			MT_QUIRK_IGNORE_DUPLICATES |
304f3287a99SBenjamin Tissoires 			MT_QUIRK_HOVERING |
305f3287a99SBenjamin Tissoires 			MT_QUIRK_CONTACT_CNT_ACCURATE },
306957b8dffSJoão Paulo Rechi Vita 	{ .name = MT_CLS_ASUS,
307957b8dffSJoão Paulo Rechi Vita 		.quirks = MT_QUIRK_ALWAYS_VALID |
308957b8dffSJoão Paulo Rechi Vita 			MT_QUIRK_CONTACT_CNT_ACCURATE |
309957b8dffSJoão Paulo Rechi Vita 			MT_QUIRK_ASUS_CUSTOM_UP },
310da10bc25SMathieu Magnaudet 	{ .name = MT_CLS_VTL,
311da10bc25SMathieu Magnaudet 		.quirks = MT_QUIRK_ALWAYS_VALID |
312da10bc25SMathieu Magnaudet 			MT_QUIRK_CONTACT_CNT_ACCURATE |
313da10bc25SMathieu Magnaudet 			MT_QUIRK_FORCE_GET_FEATURE,
314da10bc25SMathieu Magnaudet 	},
3150e82232cSWei-Ning Huang 	{ .name = MT_CLS_GOOGLE,
3160e82232cSWei-Ning Huang 		.quirks = MT_QUIRK_ALWAYS_VALID |
3170e82232cSWei-Ning Huang 			MT_QUIRK_CONTACT_CNT_ACCURATE |
3180e82232cSWei-Ning Huang 			MT_QUIRK_SLOT_IS_CONTACTID |
3190e82232cSWei-Ning Huang 			MT_QUIRK_HOVERING
3200e82232cSWei-Ning Huang 	},
3212d93666eSBenjamin Tissoires 	{ }
3225519cab4SBenjamin Tissoires };
3235519cab4SBenjamin Tissoires 
324eec29e3dSBenjamin Tissoires static ssize_t mt_show_quirks(struct device *dev,
325eec29e3dSBenjamin Tissoires 			   struct device_attribute *attr,
326eec29e3dSBenjamin Tissoires 			   char *buf)
327eec29e3dSBenjamin Tissoires {
328ee79a8f8SGeliang Tang 	struct hid_device *hdev = to_hid_device(dev);
329eec29e3dSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
330eec29e3dSBenjamin Tissoires 
331eec29e3dSBenjamin Tissoires 	return sprintf(buf, "%u\n", td->mtclass.quirks);
332eec29e3dSBenjamin Tissoires }
333eec29e3dSBenjamin Tissoires 
334eec29e3dSBenjamin Tissoires static ssize_t mt_set_quirks(struct device *dev,
335eec29e3dSBenjamin Tissoires 			  struct device_attribute *attr,
336eec29e3dSBenjamin Tissoires 			  const char *buf, size_t count)
337eec29e3dSBenjamin Tissoires {
338ee79a8f8SGeliang Tang 	struct hid_device *hdev = to_hid_device(dev);
339eec29e3dSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
340eec29e3dSBenjamin Tissoires 
341eec29e3dSBenjamin Tissoires 	unsigned long val;
342eec29e3dSBenjamin Tissoires 
343eec29e3dSBenjamin Tissoires 	if (kstrtoul(buf, 0, &val))
344eec29e3dSBenjamin Tissoires 		return -EINVAL;
345eec29e3dSBenjamin Tissoires 
346eec29e3dSBenjamin Tissoires 	td->mtclass.quirks = val;
347eec29e3dSBenjamin Tissoires 
3487e3cc447SBenjamin Tissoires 	if (td->cc_index < 0)
349c2517f62SBenjamin Tissoires 		td->mtclass.quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
350c2517f62SBenjamin Tissoires 
351eec29e3dSBenjamin Tissoires 	return count;
352eec29e3dSBenjamin Tissoires }
353eec29e3dSBenjamin Tissoires 
354eec29e3dSBenjamin Tissoires static DEVICE_ATTR(quirks, S_IWUSR | S_IRUGO, mt_show_quirks, mt_set_quirks);
355eec29e3dSBenjamin Tissoires 
356eec29e3dSBenjamin Tissoires static struct attribute *sysfs_attrs[] = {
357eec29e3dSBenjamin Tissoires 	&dev_attr_quirks.attr,
358eec29e3dSBenjamin Tissoires 	NULL
359eec29e3dSBenjamin Tissoires };
360eec29e3dSBenjamin Tissoires 
3619182fb98SArvind Yadav static const struct attribute_group mt_attribute_group = {
362eec29e3dSBenjamin Tissoires 	.attrs = sysfs_attrs
363eec29e3dSBenjamin Tissoires };
364eec29e3dSBenjamin Tissoires 
3656d4f5440SMika Westerberg static void mt_get_feature(struct hid_device *hdev, struct hid_report *report)
3666d4f5440SMika Westerberg {
3676d4f5440SMika Westerberg 	struct mt_device *td = hid_get_drvdata(hdev);
3686d4f5440SMika Westerberg 	int ret, size = hid_report_len(report);
3696d4f5440SMika Westerberg 	u8 *buf;
3706d4f5440SMika Westerberg 
3716d4f5440SMika Westerberg 	/*
372b897f6dbSBenjamin Tissoires 	 * Do not fetch the feature report if the device has been explicitly
373b897f6dbSBenjamin Tissoires 	 * marked as non-capable.
3746d4f5440SMika Westerberg 	 */
375b897f6dbSBenjamin Tissoires 	if (td->initial_quirks & HID_QUIRK_NO_INIT_REPORTS)
3766d4f5440SMika Westerberg 		return;
3776d4f5440SMika Westerberg 
3786d4f5440SMika Westerberg 	buf = hid_alloc_report_buf(report, GFP_KERNEL);
3796d4f5440SMika Westerberg 	if (!buf)
3806d4f5440SMika Westerberg 		return;
3816d4f5440SMika Westerberg 
3826d4f5440SMika Westerberg 	ret = hid_hw_raw_request(hdev, report->id, buf, size,
3836d4f5440SMika Westerberg 				 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
3846d4f5440SMika Westerberg 	if (ret < 0) {
3856d4f5440SMika Westerberg 		dev_warn(&hdev->dev, "failed to fetch feature %d\n",
3866d4f5440SMika Westerberg 			 report->id);
3876d4f5440SMika Westerberg 	} else {
3886d4f5440SMika Westerberg 		ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf,
3896d4f5440SMika Westerberg 					   size, 0);
3906d4f5440SMika Westerberg 		if (ret)
3916d4f5440SMika Westerberg 			dev_warn(&hdev->dev, "failed to report feature\n");
3926d4f5440SMika Westerberg 	}
3936d4f5440SMika Westerberg 
3946d4f5440SMika Westerberg 	kfree(buf);
3956d4f5440SMika Westerberg }
3966d4f5440SMika Westerberg 
397f635bd11SHenrik Rydberg static void mt_feature_mapping(struct hid_device *hdev,
3985519cab4SBenjamin Tissoires 		struct hid_field *field, struct hid_usage *usage)
3995519cab4SBenjamin Tissoires {
4005519cab4SBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
4019498f954SBenjamin Tissoires 
4029498f954SBenjamin Tissoires 	switch (usage->hid) {
4039498f954SBenjamin Tissoires 	case HID_DG_INPUTMODE:
4048821f5dcSBenjamin Tissoires 		/* Ignore if value index is out of bounds. */
4058821f5dcSBenjamin Tissoires 		if (usage->usage_index >= field->report_count) {
4068821f5dcSBenjamin Tissoires 			dev_err(&hdev->dev, "HID_DG_INPUTMODE out of range\n");
4074aceed37SBenjamin Tissoires 			break;
4084aceed37SBenjamin Tissoires 		}
4098821f5dcSBenjamin Tissoires 
41073e7d63eSBenjamin Tissoires 		if (td->inputmode < 0) {
4118821f5dcSBenjamin Tissoires 			td->inputmode = field->report->id;
4128821f5dcSBenjamin Tissoires 			td->inputmode_index = usage->usage_index;
41373e7d63eSBenjamin Tissoires 		} else {
41473e7d63eSBenjamin Tissoires 			/*
41573e7d63eSBenjamin Tissoires 			 * Some elan panels wrongly declare 2 input mode
41673e7d63eSBenjamin Tissoires 			 * features, and silently ignore when we set the
41773e7d63eSBenjamin Tissoires 			 * value in the second field. Skip the second feature
41873e7d63eSBenjamin Tissoires 			 * and hope for the best.
41973e7d63eSBenjamin Tissoires 			 */
42073e7d63eSBenjamin Tissoires 			dev_info(&hdev->dev,
42173e7d63eSBenjamin Tissoires 				 "Ignoring the extra HID_DG_INPUTMODE\n");
42273e7d63eSBenjamin Tissoires 		}
4234aceed37SBenjamin Tissoires 
4249498f954SBenjamin Tissoires 		break;
4259498f954SBenjamin Tissoires 	case HID_DG_CONTACTMAX:
4266d4f5440SMika Westerberg 		mt_get_feature(hdev, field->report);
4276d4f5440SMika Westerberg 
42831ae9bddSBenjamin Tissoires 		td->maxcontact_report_id = field->report->id;
4299498f954SBenjamin Tissoires 		td->maxcontacts = field->value[0];
430afbcb04cSBenjamin Tissoires 		if (!td->maxcontacts &&
431afbcb04cSBenjamin Tissoires 		    field->logical_maximum <= MT_MAX_MAXCONTACT)
432afbcb04cSBenjamin Tissoires 			td->maxcontacts = field->logical_maximum;
433eec29e3dSBenjamin Tissoires 		if (td->mtclass.maxcontacts)
4349498f954SBenjamin Tissoires 			/* check if the maxcontacts is given by the class */
435eec29e3dSBenjamin Tissoires 			td->maxcontacts = td->mtclass.maxcontacts;
4369498f954SBenjamin Tissoires 
4379498f954SBenjamin Tissoires 		break;
4382c6e0277SSeth Forshee 	case HID_DG_BUTTONTYPE:
4392c6e0277SSeth Forshee 		if (usage->usage_index >= field->report_count) {
4402c6e0277SSeth Forshee 			dev_err(&hdev->dev, "HID_DG_BUTTONTYPE out of range\n");
4412c6e0277SSeth Forshee 			break;
4422c6e0277SSeth Forshee 		}
4432c6e0277SSeth Forshee 
4446d4f5440SMika Westerberg 		mt_get_feature(hdev, field->report);
4452c6e0277SSeth Forshee 		if (field->value[usage->usage_index] == MT_BUTTONTYPE_CLICKPAD)
4462c6e0277SSeth Forshee 			td->is_buttonpad = true;
4472c6e0277SSeth Forshee 
4482c6e0277SSeth Forshee 		break;
44945c5c682SBenjamin Tissoires 	case 0xff0000c5:
45045c5c682SBenjamin Tissoires 		/* Retrieve the Win8 blob once to enable some devices */
45145c5c682SBenjamin Tissoires 		if (usage->usage_index == 0)
45245c5c682SBenjamin Tissoires 			mt_get_feature(hdev, field->report);
45345c5c682SBenjamin Tissoires 		break;
4545519cab4SBenjamin Tissoires 	}
4555519cab4SBenjamin Tissoires }
4565519cab4SBenjamin Tissoires 
4575519cab4SBenjamin Tissoires static void set_abs(struct input_dev *input, unsigned int code,
4585519cab4SBenjamin Tissoires 		struct hid_field *field, int snratio)
4595519cab4SBenjamin Tissoires {
4605519cab4SBenjamin Tissoires 	int fmin = field->logical_minimum;
4615519cab4SBenjamin Tissoires 	int fmax = field->logical_maximum;
4625519cab4SBenjamin Tissoires 	int fuzz = snratio ? (fmax - fmin) / snratio : 0;
4635519cab4SBenjamin Tissoires 	input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
46437cf6e6fSBenjamin Tissoires 	input_abs_set_res(input, code, hidinput_calc_abs_res(field, code));
4655519cab4SBenjamin Tissoires }
4665519cab4SBenjamin Tissoires 
4673ac36d15SBenjamin Tissoires static void mt_store_field(struct hid_usage *usage, struct mt_device *td,
468ed9d5c96SBenjamin Tissoires 		struct hid_input *hi)
469ed9d5c96SBenjamin Tissoires {
4703ac36d15SBenjamin Tissoires 	struct mt_fields *f = td->fields;
4713ac36d15SBenjamin Tissoires 
4723ac36d15SBenjamin Tissoires 	if (f->length >= HID_MAX_FIELDS)
4733ac36d15SBenjamin Tissoires 		return;
4743ac36d15SBenjamin Tissoires 
4753ac36d15SBenjamin Tissoires 	f->usages[f->length++] = usage->hid;
476ed9d5c96SBenjamin Tissoires }
477ed9d5c96SBenjamin Tissoires 
478a69c5f8bSBenjamin Tissoires static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
4795519cab4SBenjamin Tissoires 		struct hid_field *field, struct hid_usage *usage,
4805519cab4SBenjamin Tissoires 		unsigned long **bit, int *max)
4815519cab4SBenjamin Tissoires {
4825519cab4SBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
483eec29e3dSBenjamin Tissoires 	struct mt_class *cls = &td->mtclass;
484c2ef8f21SBenjamin Tissoires 	int code;
485349fd670SBenjamin Tissoires 	struct hid_usage *prev_usage = NULL;
4864875ac11SRichard Nauber 
487658d4aedSJeff Brown 	if (field->application == HID_DG_TOUCHSCREEN)
48876f5902aSHenrik Rydberg 		td->mt_flags |= INPUT_MT_DIRECT;
489658d4aedSJeff Brown 
49076f5902aSHenrik Rydberg 	/*
49176f5902aSHenrik Rydberg 	 * Model touchscreens providing buttons as touchpads.
492c2ef8f21SBenjamin Tissoires 	 */
493c2ef8f21SBenjamin Tissoires 	if (field->application == HID_DG_TOUCHPAD ||
4949abebedbSAndrew Duggan 	    (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {
49576f5902aSHenrik Rydberg 		td->mt_flags |= INPUT_MT_POINTER;
4969abebedbSAndrew Duggan 		td->inputmode_value = MT_INPUTMODE_TOUCHPAD;
4979abebedbSAndrew Duggan 	}
498c2ef8f21SBenjamin Tissoires 
499015fdaa9SBenjamin Tissoires 	/* count the buttons on touchpads */
500015fdaa9SBenjamin Tissoires 	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON)
501015fdaa9SBenjamin Tissoires 		td->buttons_count++;
502015fdaa9SBenjamin Tissoires 
503349fd670SBenjamin Tissoires 	if (usage->usage_index)
504349fd670SBenjamin Tissoires 		prev_usage = &field->usage[usage->usage_index - 1];
505349fd670SBenjamin Tissoires 
5065519cab4SBenjamin Tissoires 	switch (usage->hid & HID_USAGE_PAGE) {
5075519cab4SBenjamin Tissoires 
5085519cab4SBenjamin Tissoires 	case HID_UP_GENDESK:
5095519cab4SBenjamin Tissoires 		switch (usage->hid) {
5105519cab4SBenjamin Tissoires 		case HID_GD_X:
511349fd670SBenjamin Tissoires 			if (prev_usage && (prev_usage->hid == usage->hid)) {
512349fd670SBenjamin Tissoires 				hid_map_usage(hi, usage, bit, max,
513349fd670SBenjamin Tissoires 					EV_ABS, ABS_MT_TOOL_X);
514349fd670SBenjamin Tissoires 				set_abs(hi->input, ABS_MT_TOOL_X, field,
515349fd670SBenjamin Tissoires 					cls->sn_move);
516349fd670SBenjamin Tissoires 			} else {
5175519cab4SBenjamin Tissoires 				hid_map_usage(hi, usage, bit, max,
5185519cab4SBenjamin Tissoires 					EV_ABS, ABS_MT_POSITION_X);
5195519cab4SBenjamin Tissoires 				set_abs(hi->input, ABS_MT_POSITION_X, field,
5205519cab4SBenjamin Tissoires 					cls->sn_move);
521349fd670SBenjamin Tissoires 			}
522349fd670SBenjamin Tissoires 
5233ac36d15SBenjamin Tissoires 			mt_store_field(usage, td, hi);
5245519cab4SBenjamin Tissoires 			return 1;
5255519cab4SBenjamin Tissoires 		case HID_GD_Y:
526349fd670SBenjamin Tissoires 			if (prev_usage && (prev_usage->hid == usage->hid)) {
527349fd670SBenjamin Tissoires 				hid_map_usage(hi, usage, bit, max,
528349fd670SBenjamin Tissoires 					EV_ABS, ABS_MT_TOOL_Y);
529349fd670SBenjamin Tissoires 				set_abs(hi->input, ABS_MT_TOOL_Y, field,
530349fd670SBenjamin Tissoires 					cls->sn_move);
531349fd670SBenjamin Tissoires 			} else {
5325519cab4SBenjamin Tissoires 				hid_map_usage(hi, usage, bit, max,
5335519cab4SBenjamin Tissoires 					EV_ABS, ABS_MT_POSITION_Y);
5345519cab4SBenjamin Tissoires 				set_abs(hi->input, ABS_MT_POSITION_Y, field,
5355519cab4SBenjamin Tissoires 					cls->sn_move);
536349fd670SBenjamin Tissoires 			}
537349fd670SBenjamin Tissoires 
5383ac36d15SBenjamin Tissoires 			mt_store_field(usage, td, hi);
5395519cab4SBenjamin Tissoires 			return 1;
5405519cab4SBenjamin Tissoires 		}
5415519cab4SBenjamin Tissoires 		return 0;
5425519cab4SBenjamin Tissoires 
5435519cab4SBenjamin Tissoires 	case HID_UP_DIGITIZER:
5445519cab4SBenjamin Tissoires 		switch (usage->hid) {
5455519cab4SBenjamin Tissoires 		case HID_DG_INRANGE:
5469b3bb9b8SBenjamin Tissoires 			if (cls->quirks & MT_QUIRK_HOVERING) {
5479b3bb9b8SBenjamin Tissoires 				hid_map_usage(hi, usage, bit, max,
5489b3bb9b8SBenjamin Tissoires 					EV_ABS, ABS_MT_DISTANCE);
5499b3bb9b8SBenjamin Tissoires 				input_set_abs_params(hi->input,
5509b3bb9b8SBenjamin Tissoires 					ABS_MT_DISTANCE, 0, 1, 0, 0);
5519b3bb9b8SBenjamin Tissoires 			}
5523ac36d15SBenjamin Tissoires 			mt_store_field(usage, td, hi);
5535519cab4SBenjamin Tissoires 			return 1;
5545519cab4SBenjamin Tissoires 		case HID_DG_CONFIDENCE:
555504c932cSMasaki Ota 			if ((cls->name == MT_CLS_WIN_8 ||
556504c932cSMasaki Ota 				cls->name == MT_CLS_WIN_8_DUAL) &&
5576dd2e27aSAllen Hung 				field->application == HID_DG_TOUCHPAD)
5586dd2e27aSAllen Hung 				cls->quirks |= MT_QUIRK_CONFIDENCE;
5593ac36d15SBenjamin Tissoires 			mt_store_field(usage, td, hi);
5605519cab4SBenjamin Tissoires 			return 1;
5615519cab4SBenjamin Tissoires 		case HID_DG_TIPSWITCH:
5625519cab4SBenjamin Tissoires 			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
5635519cab4SBenjamin Tissoires 			input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
5643ac36d15SBenjamin Tissoires 			mt_store_field(usage, td, hi);
5655519cab4SBenjamin Tissoires 			return 1;
5665519cab4SBenjamin Tissoires 		case HID_DG_CONTACTID:
5673ac36d15SBenjamin Tissoires 			mt_store_field(usage, td, hi);
5689e87f22aSBenjamin Tissoires 			td->touches_by_report++;
56955978fa9SBenjamin Tissoires 			td->mt_report_id = field->report->id;
5705519cab4SBenjamin Tissoires 			return 1;
5715519cab4SBenjamin Tissoires 		case HID_DG_WIDTH:
5725519cab4SBenjamin Tissoires 			hid_map_usage(hi, usage, bit, max,
5735519cab4SBenjamin Tissoires 					EV_ABS, ABS_MT_TOUCH_MAJOR);
57477723e3bSHenrik Rydberg 			if (!(cls->quirks & MT_QUIRK_NO_AREA))
575f786bba4SBenjamin Tissoires 				set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
576f786bba4SBenjamin Tissoires 					cls->sn_width);
5773ac36d15SBenjamin Tissoires 			mt_store_field(usage, td, hi);
5785519cab4SBenjamin Tissoires 			return 1;
5795519cab4SBenjamin Tissoires 		case HID_DG_HEIGHT:
5805519cab4SBenjamin Tissoires 			hid_map_usage(hi, usage, bit, max,
5815519cab4SBenjamin Tissoires 					EV_ABS, ABS_MT_TOUCH_MINOR);
58277723e3bSHenrik Rydberg 			if (!(cls->quirks & MT_QUIRK_NO_AREA)) {
583f786bba4SBenjamin Tissoires 				set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
584f786bba4SBenjamin Tissoires 					cls->sn_height);
5851e648a13SBenjamin Tissoires 				input_set_abs_params(hi->input,
5861e648a13SBenjamin Tissoires 					ABS_MT_ORIENTATION, 0, 1, 0, 0);
58777723e3bSHenrik Rydberg 			}
5883ac36d15SBenjamin Tissoires 			mt_store_field(usage, td, hi);
5895519cab4SBenjamin Tissoires 			return 1;
5905519cab4SBenjamin Tissoires 		case HID_DG_TIPPRESSURE:
5915519cab4SBenjamin Tissoires 			hid_map_usage(hi, usage, bit, max,
5925519cab4SBenjamin Tissoires 					EV_ABS, ABS_MT_PRESSURE);
5935519cab4SBenjamin Tissoires 			set_abs(hi->input, ABS_MT_PRESSURE, field,
5945519cab4SBenjamin Tissoires 				cls->sn_pressure);
5953ac36d15SBenjamin Tissoires 			mt_store_field(usage, td, hi);
5965519cab4SBenjamin Tissoires 			return 1;
59729cc309dSNicolas Boichat 		case HID_DG_SCANTIME:
59829cc309dSNicolas Boichat 			hid_map_usage(hi, usage, bit, max,
59929cc309dSNicolas Boichat 				EV_MSC, MSC_TIMESTAMP);
60029cc309dSNicolas Boichat 			input_set_capability(hi->input, EV_MSC, MSC_TIMESTAMP);
60129cc309dSNicolas Boichat 			mt_store_field(usage, td, hi);
60229cc309dSNicolas Boichat 			return 1;
6035519cab4SBenjamin Tissoires 		case HID_DG_CONTACTCOUNT:
6048821f5dcSBenjamin Tissoires 			/* Ignore if indexes are out of bounds. */
6058821f5dcSBenjamin Tissoires 			if (field->index >= field->report->maxfield ||
6068821f5dcSBenjamin Tissoires 			    usage->usage_index >= field->report_count)
6078821f5dcSBenjamin Tissoires 				return 1;
6087e3cc447SBenjamin Tissoires 			td->cc_index = field->index;
6097e3cc447SBenjamin Tissoires 			td->cc_value_index = usage->usage_index;
6105519cab4SBenjamin Tissoires 			return 1;
6115519cab4SBenjamin Tissoires 		case HID_DG_CONTACTMAX:
6125519cab4SBenjamin Tissoires 			/* we don't set td->last_slot_field as contactcount and
6135519cab4SBenjamin Tissoires 			 * contact max are global to the report */
6145519cab4SBenjamin Tissoires 			return -1;
615c2ef8f21SBenjamin Tissoires 		case HID_DG_TOUCH:
616c2ef8f21SBenjamin Tissoires 			/* Legacy devices use TIPSWITCH and not TOUCH.
617c2ef8f21SBenjamin Tissoires 			 * Let's just ignore this field. */
618c2ef8f21SBenjamin Tissoires 			return -1;
61965b258e9SAlan Cox 		}
6205519cab4SBenjamin Tissoires 		/* let hid-input decide for the others */
6215519cab4SBenjamin Tissoires 		return 0;
6225519cab4SBenjamin Tissoires 
623c2ef8f21SBenjamin Tissoires 	case HID_UP_BUTTON:
624c2ef8f21SBenjamin Tissoires 		code = BTN_MOUSE + ((usage->hid - 1) & HID_USAGE);
625594312b8SBenjamin Tissoires 		/*
626594312b8SBenjamin Tissoires 		 * MS PTP spec says that external buttons left and right have
627594312b8SBenjamin Tissoires 		 * usages 2 and 3.
628594312b8SBenjamin Tissoires 		 */
629504c932cSMasaki Ota 		if ((cls->name == MT_CLS_WIN_8 ||
630504c932cSMasaki Ota 			cls->name == MT_CLS_WIN_8_DUAL) &&
631594312b8SBenjamin Tissoires 		    field->application == HID_DG_TOUCHPAD &&
632594312b8SBenjamin Tissoires 		    (usage->hid & HID_USAGE) > 1)
633594312b8SBenjamin Tissoires 			code--;
634c2ef8f21SBenjamin Tissoires 		hid_map_usage(hi, usage, bit, max, EV_KEY, code);
635c2ef8f21SBenjamin Tissoires 		input_set_capability(hi->input, EV_KEY, code);
636c2ef8f21SBenjamin Tissoires 		return 1;
637c2ef8f21SBenjamin Tissoires 
6385519cab4SBenjamin Tissoires 	case 0xff000000:
6395519cab4SBenjamin Tissoires 		/* we do not want to map these: no input-oriented meaning */
6405519cab4SBenjamin Tissoires 		return -1;
6415519cab4SBenjamin Tissoires 	}
6425519cab4SBenjamin Tissoires 
6435519cab4SBenjamin Tissoires 	return 0;
6445519cab4SBenjamin Tissoires }
6455519cab4SBenjamin Tissoires 
6463e1b5015SHenrik Rydberg static int mt_compute_slot(struct mt_device *td, struct input_dev *input)
6475519cab4SBenjamin Tissoires {
648eec29e3dSBenjamin Tissoires 	__s32 quirks = td->mtclass.quirks;
6495519cab4SBenjamin Tissoires 
6502d93666eSBenjamin Tissoires 	if (quirks & MT_QUIRK_SLOT_IS_CONTACTID)
6512d93666eSBenjamin Tissoires 		return td->curdata.contactid;
6525519cab4SBenjamin Tissoires 
6532d93666eSBenjamin Tissoires 	if (quirks & MT_QUIRK_CYPRESS)
654a3b5e577SBenjamin Tissoires 		return cypress_compute_slot(td);
655a3b5e577SBenjamin Tissoires 
6562d93666eSBenjamin Tissoires 	if (quirks & MT_QUIRK_SLOT_IS_CONTACTNUMBER)
6572d93666eSBenjamin Tissoires 		return td->num_received;
6585572da08SBenjamin Tissoires 
6594a6ee685SBenjamin Tissoires 	if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE)
6604a6ee685SBenjamin Tissoires 		return td->curdata.contactid - 1;
6614a6ee685SBenjamin Tissoires 
6623e1b5015SHenrik Rydberg 	return input_mt_get_slot_by_key(input, td->curdata.contactid);
6635519cab4SBenjamin Tissoires }
6645519cab4SBenjamin Tissoires 
6655519cab4SBenjamin Tissoires /*
6665519cab4SBenjamin Tissoires  * this function is called when a whole contact has been processed,
6675519cab4SBenjamin Tissoires  * so that it can assign it to a slot and store the data there
6685519cab4SBenjamin Tissoires  */
6693e1b5015SHenrik Rydberg static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
6705519cab4SBenjamin Tissoires {
671c2517f62SBenjamin Tissoires 	if ((td->mtclass.quirks & MT_QUIRK_CONTACT_CNT_ACCURATE) &&
672c2517f62SBenjamin Tissoires 	    td->num_received >= td->num_expected)
673c2517f62SBenjamin Tissoires 		return;
674c2517f62SBenjamin Tissoires 
67520b60e6dSBenjamin Tissoires 	if (td->curvalid || (td->mtclass.quirks & MT_QUIRK_ALWAYS_VALID)) {
6766dd2e27aSAllen Hung 		int active;
6773e1b5015SHenrik Rydberg 		int slotnum = mt_compute_slot(td, input);
6783e1b5015SHenrik Rydberg 		struct mt_slot *s = &td->curdata;
67928728399SBenjamin Tissoires 		struct input_mt *mt = input->mt;
6805519cab4SBenjamin Tissoires 
6813e1b5015SHenrik Rydberg 		if (slotnum < 0 || slotnum >= td->maxcontacts)
6823e1b5015SHenrik Rydberg 			return;
6835519cab4SBenjamin Tissoires 
68428728399SBenjamin Tissoires 		if ((td->mtclass.quirks & MT_QUIRK_IGNORE_DUPLICATES) && mt) {
68528728399SBenjamin Tissoires 			struct input_mt_slot *slot = &mt->slots[slotnum];
68628728399SBenjamin Tissoires 			if (input_mt_is_active(slot) &&
68728728399SBenjamin Tissoires 			    input_mt_is_used(mt, slot))
68828728399SBenjamin Tissoires 				return;
68928728399SBenjamin Tissoires 		}
69028728399SBenjamin Tissoires 
6916dd2e27aSAllen Hung 		if (!(td->mtclass.quirks & MT_QUIRK_CONFIDENCE))
6926dd2e27aSAllen Hung 			s->confidence_state = 1;
6936dd2e27aSAllen Hung 		active = (s->touch_state || s->inrange_state) &&
6946dd2e27aSAllen Hung 							s->confidence_state;
6956dd2e27aSAllen Hung 
6963e1b5015SHenrik Rydberg 		input_mt_slot(input, slotnum);
6976dd2e27aSAllen Hung 		input_mt_report_slot_state(input, MT_TOOL_FINGER, active);
6986dd2e27aSAllen Hung 		if (active) {
6999b3bb9b8SBenjamin Tissoires 			/* this finger is in proximity of the sensor */
700f786bba4SBenjamin Tissoires 			int wide = (s->w > s->h);
701e9d0a26dSHungNien Chen 			int major = max(s->w, s->h);
702e9d0a26dSHungNien Chen 			int minor = min(s->w, s->h);
703e9d0a26dSHungNien Chen 
704e9d0a26dSHungNien Chen 			/*
705e9d0a26dSHungNien Chen 			 * divided by two to match visual scale of touch
706e9d0a26dSHungNien Chen 			 * for devices with this quirk
707e9d0a26dSHungNien Chen 			 */
708e9d0a26dSHungNien Chen 			if (td->mtclass.quirks & MT_QUIRK_TOUCH_SIZE_SCALING) {
709e9d0a26dSHungNien Chen 				major = major >> 1;
710e9d0a26dSHungNien Chen 				minor = minor >> 1;
711e9d0a26dSHungNien Chen 			}
712f786bba4SBenjamin Tissoires 
7135519cab4SBenjamin Tissoires 			input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x);
7145519cab4SBenjamin Tissoires 			input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y);
715349fd670SBenjamin Tissoires 			input_event(input, EV_ABS, ABS_MT_TOOL_X, s->cx);
716349fd670SBenjamin Tissoires 			input_event(input, EV_ABS, ABS_MT_TOOL_Y, s->cy);
7179b3bb9b8SBenjamin Tissoires 			input_event(input, EV_ABS, ABS_MT_DISTANCE,
7189b3bb9b8SBenjamin Tissoires 				!s->touch_state);
719f786bba4SBenjamin Tissoires 			input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
7205519cab4SBenjamin Tissoires 			input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
721f786bba4SBenjamin Tissoires 			input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
722f786bba4SBenjamin Tissoires 			input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
72396098274SBenjamin Tissoires 
72496098274SBenjamin Tissoires 			set_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags);
7252d93666eSBenjamin Tissoires 		}
7265519cab4SBenjamin Tissoires 	}
7275519cab4SBenjamin Tissoires 
7283e1b5015SHenrik Rydberg 	td->num_received++;
7293e1b5015SHenrik Rydberg }
7303e1b5015SHenrik Rydberg 
7313e1b5015SHenrik Rydberg /*
7323e1b5015SHenrik Rydberg  * this function is called when a whole packet has been received and processed,
7333e1b5015SHenrik Rydberg  * so that it can decide what to send to the input layer.
7343e1b5015SHenrik Rydberg  */
7353e1b5015SHenrik Rydberg static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
7363e1b5015SHenrik Rydberg {
73776f5902aSHenrik Rydberg 	input_mt_sync_frame(input);
73829cc309dSNicolas Boichat 	input_event(input, EV_MSC, MSC_TIMESTAMP, td->timestamp);
7395519cab4SBenjamin Tissoires 	input_sync(input);
7405519cab4SBenjamin Tissoires 	td->num_received = 0;
74196098274SBenjamin Tissoires 	if (test_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags))
74296098274SBenjamin Tissoires 		set_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags);
74396098274SBenjamin Tissoires 	else
74496098274SBenjamin Tissoires 		clear_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags);
74596098274SBenjamin Tissoires 	clear_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags);
7465519cab4SBenjamin Tissoires }
7475519cab4SBenjamin Tissoires 
74829cc309dSNicolas Boichat static int mt_compute_timestamp(struct mt_device *td, struct hid_field *field,
74929cc309dSNicolas Boichat 		__s32 value)
75029cc309dSNicolas Boichat {
75129cc309dSNicolas Boichat 	long delta = value - td->dev_time;
75229cc309dSNicolas Boichat 	unsigned long jdelta = jiffies_to_usecs(jiffies - td->jiffies);
75329cc309dSNicolas Boichat 
75429cc309dSNicolas Boichat 	td->jiffies = jiffies;
75529cc309dSNicolas Boichat 	td->dev_time = value;
75629cc309dSNicolas Boichat 
75729cc309dSNicolas Boichat 	if (delta < 0)
75829cc309dSNicolas Boichat 		delta += field->logical_maximum;
75929cc309dSNicolas Boichat 
76029cc309dSNicolas Boichat 	/* HID_DG_SCANTIME is expressed in 100us, we want it in us. */
76129cc309dSNicolas Boichat 	delta *= 100;
76229cc309dSNicolas Boichat 
76329cc309dSNicolas Boichat 	if (jdelta > MAX_TIMESTAMP_INTERVAL)
76429cc309dSNicolas Boichat 		/* No data received for a while, resync the timestamp. */
76529cc309dSNicolas Boichat 		return 0;
76629cc309dSNicolas Boichat 	else
76729cc309dSNicolas Boichat 		return td->timestamp + delta;
76829cc309dSNicolas Boichat }
76929cc309dSNicolas Boichat 
770a69c5f8bSBenjamin Tissoires static int mt_touch_event(struct hid_device *hid, struct hid_field *field,
7715519cab4SBenjamin Tissoires 				struct hid_usage *usage, __s32 value)
7725519cab4SBenjamin Tissoires {
77355978fa9SBenjamin Tissoires 	/* we will handle the hidinput part later, now remains hiddev */
77455978fa9SBenjamin Tissoires 	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
77555978fa9SBenjamin Tissoires 		hid->hiddev_hid_event(hid, field, usage, value);
77655978fa9SBenjamin Tissoires 
77755978fa9SBenjamin Tissoires 	return 1;
77855978fa9SBenjamin Tissoires }
77955978fa9SBenjamin Tissoires 
78055978fa9SBenjamin Tissoires static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
78155978fa9SBenjamin Tissoires 				struct hid_usage *usage, __s32 value)
78255978fa9SBenjamin Tissoires {
7835519cab4SBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hid);
784eec29e3dSBenjamin Tissoires 	__s32 quirks = td->mtclass.quirks;
7854c437555SBenjamin Tissoires 	struct input_dev *input = field->hidinput->input;
7865519cab4SBenjamin Tissoires 
7873e1b5015SHenrik Rydberg 	if (hid->claimed & HID_CLAIMED_INPUT) {
7885519cab4SBenjamin Tissoires 		switch (usage->hid) {
7895519cab4SBenjamin Tissoires 		case HID_DG_INRANGE:
79020b60e6dSBenjamin Tissoires 			if (quirks & MT_QUIRK_VALID_IS_INRANGE)
7912d93666eSBenjamin Tissoires 				td->curvalid = value;
7929b3bb9b8SBenjamin Tissoires 			if (quirks & MT_QUIRK_HOVERING)
7939b3bb9b8SBenjamin Tissoires 				td->curdata.inrange_state = value;
7945519cab4SBenjamin Tissoires 			break;
7955519cab4SBenjamin Tissoires 		case HID_DG_TIPSWITCH:
7962d93666eSBenjamin Tissoires 			if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
7975519cab4SBenjamin Tissoires 				td->curvalid = value;
7985519cab4SBenjamin Tissoires 			td->curdata.touch_state = value;
7995519cab4SBenjamin Tissoires 			break;
8005519cab4SBenjamin Tissoires 		case HID_DG_CONFIDENCE:
8016dd2e27aSAllen Hung 			if (quirks & MT_QUIRK_CONFIDENCE)
8026dd2e27aSAllen Hung 				td->curdata.confidence_state = value;
8032d93666eSBenjamin Tissoires 			if (quirks & MT_QUIRK_VALID_IS_CONFIDENCE)
8042d93666eSBenjamin Tissoires 				td->curvalid = value;
8055519cab4SBenjamin Tissoires 			break;
8065519cab4SBenjamin Tissoires 		case HID_DG_CONTACTID:
8075519cab4SBenjamin Tissoires 			td->curdata.contactid = value;
8085519cab4SBenjamin Tissoires 			break;
8095519cab4SBenjamin Tissoires 		case HID_DG_TIPPRESSURE:
8105519cab4SBenjamin Tissoires 			td->curdata.p = value;
8115519cab4SBenjamin Tissoires 			break;
8125519cab4SBenjamin Tissoires 		case HID_GD_X:
813349fd670SBenjamin Tissoires 			if (usage->code == ABS_MT_TOOL_X)
814349fd670SBenjamin Tissoires 				td->curdata.cx = value;
815349fd670SBenjamin Tissoires 			else
8165519cab4SBenjamin Tissoires 				td->curdata.x = value;
8175519cab4SBenjamin Tissoires 			break;
8185519cab4SBenjamin Tissoires 		case HID_GD_Y:
819349fd670SBenjamin Tissoires 			if (usage->code == ABS_MT_TOOL_Y)
820349fd670SBenjamin Tissoires 				td->curdata.cy = value;
821349fd670SBenjamin Tissoires 			else
8225519cab4SBenjamin Tissoires 				td->curdata.y = value;
8235519cab4SBenjamin Tissoires 			break;
8245519cab4SBenjamin Tissoires 		case HID_DG_WIDTH:
8255519cab4SBenjamin Tissoires 			td->curdata.w = value;
8265519cab4SBenjamin Tissoires 			break;
8275519cab4SBenjamin Tissoires 		case HID_DG_HEIGHT:
8285519cab4SBenjamin Tissoires 			td->curdata.h = value;
8295519cab4SBenjamin Tissoires 			break;
83029cc309dSNicolas Boichat 		case HID_DG_SCANTIME:
83129cc309dSNicolas Boichat 			td->timestamp = mt_compute_timestamp(td, field, value);
83229cc309dSNicolas Boichat 			break;
8335519cab4SBenjamin Tissoires 		case HID_DG_CONTACTCOUNT:
8345519cab4SBenjamin Tissoires 			break;
835c2ef8f21SBenjamin Tissoires 		case HID_DG_TOUCH:
836c2ef8f21SBenjamin Tissoires 			/* do nothing */
837c2ef8f21SBenjamin Tissoires 			break;
8385519cab4SBenjamin Tissoires 
8395519cab4SBenjamin Tissoires 		default:
8404c437555SBenjamin Tissoires 			if (usage->type)
8414c437555SBenjamin Tissoires 				input_event(input, usage->type, usage->code,
8424c437555SBenjamin Tissoires 						value);
84355978fa9SBenjamin Tissoires 			return;
8445519cab4SBenjamin Tissoires 		}
8455519cab4SBenjamin Tissoires 
84654f4c0c3SBenjamin Tissoires 		if (usage->usage_index + 1 == field->report_count) {
84754f4c0c3SBenjamin Tissoires 			/* we only take into account the last report. */
8482258e863SDenis Kovalev 			if (usage->hid == td->last_slot_field)
8493e1b5015SHenrik Rydberg 				mt_complete_slot(td, field->hidinput->input);
85054f4c0c3SBenjamin Tissoires 		}
8515519cab4SBenjamin Tissoires 
8522d93666eSBenjamin Tissoires 	}
85355978fa9SBenjamin Tissoires }
8542d93666eSBenjamin Tissoires 
855a69c5f8bSBenjamin Tissoires static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
85655978fa9SBenjamin Tissoires {
85755978fa9SBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hid);
85855978fa9SBenjamin Tissoires 	struct hid_field *field;
85955978fa9SBenjamin Tissoires 	unsigned count;
86055978fa9SBenjamin Tissoires 	int r, n;
8615519cab4SBenjamin Tissoires 
8624f4001bcSBenjamin Tissoires 	/* sticky fingers release in progress, abort */
8634f4001bcSBenjamin Tissoires 	if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
8644f4001bcSBenjamin Tissoires 		return;
8654f4001bcSBenjamin Tissoires 
866c2517f62SBenjamin Tissoires 	/*
867c2517f62SBenjamin Tissoires 	 * Includes multi-packet support where subsequent
868c2517f62SBenjamin Tissoires 	 * packets are sent with zero contactcount.
869c2517f62SBenjamin Tissoires 	 */
8707e3cc447SBenjamin Tissoires 	if (td->cc_index >= 0) {
8717e3cc447SBenjamin Tissoires 		struct hid_field *field = report->field[td->cc_index];
8727e3cc447SBenjamin Tissoires 		int value = field->value[td->cc_value_index];
8737e3cc447SBenjamin Tissoires 		if (value)
8747e3cc447SBenjamin Tissoires 			td->num_expected = value;
8757e3cc447SBenjamin Tissoires 	}
876c2517f62SBenjamin Tissoires 
87755978fa9SBenjamin Tissoires 	for (r = 0; r < report->maxfield; r++) {
87855978fa9SBenjamin Tissoires 		field = report->field[r];
87955978fa9SBenjamin Tissoires 		count = field->report_count;
88055978fa9SBenjamin Tissoires 
88155978fa9SBenjamin Tissoires 		if (!(HID_MAIN_ITEM_VARIABLE & field->flags))
88255978fa9SBenjamin Tissoires 			continue;
88355978fa9SBenjamin Tissoires 
88455978fa9SBenjamin Tissoires 		for (n = 0; n < count; n++)
88555978fa9SBenjamin Tissoires 			mt_process_mt_event(hid, field, &field->usage[n],
88655978fa9SBenjamin Tissoires 					field->value[n]);
88755978fa9SBenjamin Tissoires 	}
8885b62efd8SBenjamin Tissoires 
8895b62efd8SBenjamin Tissoires 	if (td->num_received >= td->num_expected)
8905b62efd8SBenjamin Tissoires 		mt_sync_frame(td, report->field[0]->hidinput->input);
8914f4001bcSBenjamin Tissoires 
8924f4001bcSBenjamin Tissoires 	/*
8934f4001bcSBenjamin Tissoires 	 * Windows 8 specs says 2 things:
8944f4001bcSBenjamin Tissoires 	 * - once a contact has been reported, it has to be reported in each
8954f4001bcSBenjamin Tissoires 	 *   subsequent report
8964f4001bcSBenjamin Tissoires 	 * - the report rate when fingers are present has to be at least
8974f4001bcSBenjamin Tissoires 	 *   the refresh rate of the screen, 60 or 120 Hz
8984f4001bcSBenjamin Tissoires 	 *
8994f4001bcSBenjamin Tissoires 	 * I interprete this that the specification forces a report rate of
9004f4001bcSBenjamin Tissoires 	 * at least 60 Hz for a touchscreen to be certified.
9014f4001bcSBenjamin Tissoires 	 * Which means that if we do not get a report whithin 16 ms, either
9024f4001bcSBenjamin Tissoires 	 * something wrong happens, either the touchscreen forgets to send
9034f4001bcSBenjamin Tissoires 	 * a release. Taking a reasonable margin allows to remove issues
9044f4001bcSBenjamin Tissoires 	 * with USB communication or the load of the machine.
9054f4001bcSBenjamin Tissoires 	 *
9064f4001bcSBenjamin Tissoires 	 * Given that Win 8 devices are forced to send a release, this will
9074f4001bcSBenjamin Tissoires 	 * only affect laggish machines and the ones that have a firmware
9084f4001bcSBenjamin Tissoires 	 * defect.
9094f4001bcSBenjamin Tissoires 	 */
91096098274SBenjamin Tissoires 	if (td->mtclass.quirks & MT_QUIRK_STICKY_FINGERS) {
91196098274SBenjamin Tissoires 		if (test_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags))
91296098274SBenjamin Tissoires 			mod_timer(&td->release_timer,
91396098274SBenjamin Tissoires 				  jiffies + msecs_to_jiffies(100));
91496098274SBenjamin Tissoires 		else
91596098274SBenjamin Tissoires 			del_timer(&td->release_timer);
91696098274SBenjamin Tissoires 	}
9174f4001bcSBenjamin Tissoires 
9184f4001bcSBenjamin Tissoires 	clear_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags);
9195519cab4SBenjamin Tissoires }
9205519cab4SBenjamin Tissoires 
921b2c68a2fSDmitry Torokhov static int mt_touch_input_configured(struct hid_device *hdev,
922a69c5f8bSBenjamin Tissoires 					struct hid_input *hi)
923a69c5f8bSBenjamin Tissoires {
924a69c5f8bSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
925a69c5f8bSBenjamin Tissoires 	struct mt_class *cls = &td->mtclass;
926a69c5f8bSBenjamin Tissoires 	struct input_dev *input = hi->input;
927b2c68a2fSDmitry Torokhov 	int ret;
928a69c5f8bSBenjamin Tissoires 
929a69c5f8bSBenjamin Tissoires 	if (!td->maxcontacts)
930a69c5f8bSBenjamin Tissoires 		td->maxcontacts = MT_DEFAULT_MAXCONTACT;
931a69c5f8bSBenjamin Tissoires 
932a69c5f8bSBenjamin Tissoires 	mt_post_parse(td);
933a69c5f8bSBenjamin Tissoires 	if (td->serial_maybe)
934a69c5f8bSBenjamin Tissoires 		mt_post_parse_default_settings(td);
935a69c5f8bSBenjamin Tissoires 
936a69c5f8bSBenjamin Tissoires 	if (cls->is_indirect)
937a69c5f8bSBenjamin Tissoires 		td->mt_flags |= INPUT_MT_POINTER;
938a69c5f8bSBenjamin Tissoires 
939a69c5f8bSBenjamin Tissoires 	if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
940a69c5f8bSBenjamin Tissoires 		td->mt_flags |= INPUT_MT_DROP_UNUSED;
941a69c5f8bSBenjamin Tissoires 
942015fdaa9SBenjamin Tissoires 	/* check for clickpads */
943015fdaa9SBenjamin Tissoires 	if ((td->mt_flags & INPUT_MT_POINTER) && (td->buttons_count == 1))
9442c6e0277SSeth Forshee 		td->is_buttonpad = true;
9452c6e0277SSeth Forshee 
9462c6e0277SSeth Forshee 	if (td->is_buttonpad)
947015fdaa9SBenjamin Tissoires 		__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
948015fdaa9SBenjamin Tissoires 
949b2c68a2fSDmitry Torokhov 	ret = input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
950b2c68a2fSDmitry Torokhov 	if (ret)
951b2c68a2fSDmitry Torokhov 		return ret;
952a69c5f8bSBenjamin Tissoires 
953a69c5f8bSBenjamin Tissoires 	td->mt_flags = 0;
954b2c68a2fSDmitry Torokhov 	return 0;
955a69c5f8bSBenjamin Tissoires }
956a69c5f8bSBenjamin Tissoires 
957957b8dffSJoão Paulo Rechi Vita #define mt_map_key_clear(c)	hid_map_usage_clear(hi, usage, bit, \
958957b8dffSJoão Paulo Rechi Vita 						    max, EV_KEY, (c))
959a69c5f8bSBenjamin Tissoires static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
960a69c5f8bSBenjamin Tissoires 		struct hid_field *field, struct hid_usage *usage,
961a69c5f8bSBenjamin Tissoires 		unsigned long **bit, int *max)
962a69c5f8bSBenjamin Tissoires {
9636aef704eSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
9646aef704eSBenjamin Tissoires 
9656aef704eSBenjamin Tissoires 	/*
9666aef704eSBenjamin Tissoires 	 * If mtclass.export_all_inputs is not set, only map fields from
9676aef704eSBenjamin Tissoires 	 * TouchScreen or TouchPad collections. We need to ignore fields
9686aef704eSBenjamin Tissoires 	 * that belong to other collections such as Mouse that might have
9696aef704eSBenjamin Tissoires 	 * the same GenericDesktop usages.
9706aef704eSBenjamin Tissoires 	 */
9716aef704eSBenjamin Tissoires 	if (!td->mtclass.export_all_inputs &&
9726aef704eSBenjamin Tissoires 	    field->application != HID_DG_TOUCHSCREEN &&
973fa11aa72SBenjamin Tissoires 	    field->application != HID_DG_PEN &&
9748fe89ef0SBenjamin Tissoires 	    field->application != HID_DG_TOUCHPAD &&
9758fe89ef0SBenjamin Tissoires 	    field->application != HID_GD_KEYBOARD &&
976e57f4e67SHans de Goede 	    field->application != HID_GD_SYSTEM_CONTROL &&
9771fbf74efSJoão Paulo Rechi Vita 	    field->application != HID_CP_CONSUMER_CONTROL &&
978957b8dffSJoão Paulo Rechi Vita 	    field->application != HID_GD_WIRELESS_RADIO_CTLS &&
979957b8dffSJoão Paulo Rechi Vita 	    !(field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS &&
980957b8dffSJoão Paulo Rechi Vita 	      td->mtclass.quirks & MT_QUIRK_ASUS_CUSTOM_UP))
9816f492f28SBenjamin Tissoires 		return -1;
982a69c5f8bSBenjamin Tissoires 
9836aef704eSBenjamin Tissoires 	/*
984957b8dffSJoão Paulo Rechi Vita 	 * Some Asus keyboard+touchpad devices have the hotkeys defined in the
985957b8dffSJoão Paulo Rechi Vita 	 * touchpad report descriptor. We need to treat these as an array to
986957b8dffSJoão Paulo Rechi Vita 	 * map usages to input keys.
987957b8dffSJoão Paulo Rechi Vita 	 */
98839bbf402SJiri Kosina 	if (field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS &&
989957b8dffSJoão Paulo Rechi Vita 	    td->mtclass.quirks & MT_QUIRK_ASUS_CUSTOM_UP &&
990957b8dffSJoão Paulo Rechi Vita 	    (usage->hid & HID_USAGE_PAGE) == HID_UP_CUSTOM) {
991957b8dffSJoão Paulo Rechi Vita 		set_bit(EV_REP, hi->input->evbit);
992957b8dffSJoão Paulo Rechi Vita 		if (field->flags & HID_MAIN_ITEM_VARIABLE)
993957b8dffSJoão Paulo Rechi Vita 			field->flags &= ~HID_MAIN_ITEM_VARIABLE;
994957b8dffSJoão Paulo Rechi Vita 		switch (usage->hid & HID_USAGE) {
995957b8dffSJoão Paulo Rechi Vita 		case 0x10: mt_map_key_clear(KEY_BRIGHTNESSDOWN);	break;
996957b8dffSJoão Paulo Rechi Vita 		case 0x20: mt_map_key_clear(KEY_BRIGHTNESSUP);		break;
997957b8dffSJoão Paulo Rechi Vita 		case 0x35: mt_map_key_clear(KEY_DISPLAY_OFF);		break;
998957b8dffSJoão Paulo Rechi Vita 		case 0x6b: mt_map_key_clear(KEY_F21);			break;
999957b8dffSJoão Paulo Rechi Vita 		case 0x6c: mt_map_key_clear(KEY_SLEEP);			break;
1000957b8dffSJoão Paulo Rechi Vita 		default:
1001957b8dffSJoão Paulo Rechi Vita 			return -1;
1002957b8dffSJoão Paulo Rechi Vita 		}
1003957b8dffSJoão Paulo Rechi Vita 		return 1;
1004957b8dffSJoão Paulo Rechi Vita 	}
1005957b8dffSJoão Paulo Rechi Vita 
1006957b8dffSJoão Paulo Rechi Vita 	/*
10076aef704eSBenjamin Tissoires 	 * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
10086aef704eSBenjamin Tissoires 	 * for the stylus.
10091cc1cc92SBrent Adam 	 * The check for mt_report_id ensures we don't process
10101cc1cc92SBrent Adam 	 * HID_DG_CONTACTCOUNT from the pen report as it is outside the physical
10111cc1cc92SBrent Adam 	 * collection, but within the report ID.
10126aef704eSBenjamin Tissoires 	 */
1013a69c5f8bSBenjamin Tissoires 	if (field->physical == HID_DG_STYLUS)
1014e55f6200SBenjamin Tissoires 		return 0;
10151cc1cc92SBrent Adam 	else if ((field->physical == 0) &&
10161cc1cc92SBrent Adam 		 (field->report->id != td->mt_report_id) &&
10171cc1cc92SBrent Adam 		 (td->mt_report_id != -1))
10181cc1cc92SBrent Adam 		return 0;
1019a69c5f8bSBenjamin Tissoires 
10206aef704eSBenjamin Tissoires 	if (field->application == HID_DG_TOUCHSCREEN ||
10216aef704eSBenjamin Tissoires 	    field->application == HID_DG_TOUCHPAD)
1022a69c5f8bSBenjamin Tissoires 		return mt_touch_input_mapping(hdev, hi, field, usage, bit, max);
10236aef704eSBenjamin Tissoires 
10246aef704eSBenjamin Tissoires 	/* let hid-core decide for the others */
10256aef704eSBenjamin Tissoires 	return 0;
1026a69c5f8bSBenjamin Tissoires }
1027a69c5f8bSBenjamin Tissoires 
1028a69c5f8bSBenjamin Tissoires static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
1029a69c5f8bSBenjamin Tissoires 		struct hid_field *field, struct hid_usage *usage,
1030a69c5f8bSBenjamin Tissoires 		unsigned long **bit, int *max)
1031a69c5f8bSBenjamin Tissoires {
10326aef704eSBenjamin Tissoires 	/*
10336aef704eSBenjamin Tissoires 	 * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
10346aef704eSBenjamin Tissoires 	 * for the stylus.
10356aef704eSBenjamin Tissoires 	 */
1036fa11aa72SBenjamin Tissoires 	if (field->physical == HID_DG_STYLUS)
1037e55f6200SBenjamin Tissoires 		return 0;
1038fa11aa72SBenjamin Tissoires 
10396aef704eSBenjamin Tissoires 	if (field->application == HID_DG_TOUCHSCREEN ||
10404cf56a89SDmitry Torokhov 	    field->application == HID_DG_TOUCHPAD) {
10414cf56a89SDmitry Torokhov 		/* We own these mappings, tell hid-input to ignore them */
10424cf56a89SDmitry Torokhov 		return -1;
10434cf56a89SDmitry Torokhov 	}
10446aef704eSBenjamin Tissoires 
10456aef704eSBenjamin Tissoires 	/* let hid-core decide for the others */
10466aef704eSBenjamin Tissoires 	return 0;
1047a69c5f8bSBenjamin Tissoires }
1048a69c5f8bSBenjamin Tissoires 
1049a69c5f8bSBenjamin Tissoires static int mt_event(struct hid_device *hid, struct hid_field *field,
1050a69c5f8bSBenjamin Tissoires 				struct hid_usage *usage, __s32 value)
1051a69c5f8bSBenjamin Tissoires {
1052a69c5f8bSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hid);
1053a69c5f8bSBenjamin Tissoires 
1054a69c5f8bSBenjamin Tissoires 	if (field->report->id == td->mt_report_id)
1055a69c5f8bSBenjamin Tissoires 		return mt_touch_event(hid, field, usage, value);
1056a69c5f8bSBenjamin Tissoires 
1057e55f6200SBenjamin Tissoires 	return 0;
1058a69c5f8bSBenjamin Tissoires }
1059a69c5f8bSBenjamin Tissoires 
1060a69c5f8bSBenjamin Tissoires static void mt_report(struct hid_device *hid, struct hid_report *report)
1061a69c5f8bSBenjamin Tissoires {
1062a69c5f8bSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hid);
1063e55f6200SBenjamin Tissoires 	struct hid_field *field = report->field[0];
1064a69c5f8bSBenjamin Tissoires 
1065a69c5f8bSBenjamin Tissoires 	if (!(hid->claimed & HID_CLAIMED_INPUT))
1066a69c5f8bSBenjamin Tissoires 		return;
1067a69c5f8bSBenjamin Tissoires 
1068a69c5f8bSBenjamin Tissoires 	if (report->id == td->mt_report_id)
1069e55f6200SBenjamin Tissoires 		return mt_touch_report(hid, report);
1070fa11aa72SBenjamin Tissoires 
1071e55f6200SBenjamin Tissoires 	if (field && field->hidinput && field->hidinput->input)
1072e55f6200SBenjamin Tissoires 		input_sync(field->hidinput->input);
10735519cab4SBenjamin Tissoires }
10745519cab4SBenjamin Tissoires 
10755519cab4SBenjamin Tissoires static void mt_set_input_mode(struct hid_device *hdev)
10765519cab4SBenjamin Tissoires {
10775519cab4SBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
10785519cab4SBenjamin Tissoires 	struct hid_report *r;
10795519cab4SBenjamin Tissoires 	struct hid_report_enum *re;
1080da10bc25SMathieu Magnaudet 	struct mt_class *cls = &td->mtclass;
1081da10bc25SMathieu Magnaudet 	char *buf;
1082da10bc25SMathieu Magnaudet 	int report_len;
10835519cab4SBenjamin Tissoires 
10845519cab4SBenjamin Tissoires 	if (td->inputmode < 0)
10855519cab4SBenjamin Tissoires 		return;
10865519cab4SBenjamin Tissoires 
10875519cab4SBenjamin Tissoires 	re = &(hdev->report_enum[HID_FEATURE_REPORT]);
10885519cab4SBenjamin Tissoires 	r = re->report_id_hash[td->inputmode];
10895519cab4SBenjamin Tissoires 	if (r) {
1090da10bc25SMathieu Magnaudet 		if (cls->quirks & MT_QUIRK_FORCE_GET_FEATURE) {
1091dabb05c6SMathieu Magnaudet 			report_len = hid_report_len(r);
1092da10bc25SMathieu Magnaudet 			buf = hid_alloc_report_buf(r, GFP_KERNEL);
1093da10bc25SMathieu Magnaudet 			if (!buf) {
1094da10bc25SMathieu Magnaudet 				hid_err(hdev, "failed to allocate buffer for report\n");
1095da10bc25SMathieu Magnaudet 				return;
1096da10bc25SMathieu Magnaudet 			}
1097da10bc25SMathieu Magnaudet 			hid_hw_raw_request(hdev, r->id, buf, report_len,
1098da10bc25SMathieu Magnaudet 					   HID_FEATURE_REPORT,
1099da10bc25SMathieu Magnaudet 					   HID_REQ_GET_REPORT);
1100da10bc25SMathieu Magnaudet 			kfree(buf);
1101da10bc25SMathieu Magnaudet 		}
11029abebedbSAndrew Duggan 		r->field[0]->value[td->inputmode_index] = td->inputmode_value;
1103d8814272SBenjamin Tissoires 		hid_hw_request(hdev, r, HID_REQ_SET_REPORT);
11045519cab4SBenjamin Tissoires 	}
11055519cab4SBenjamin Tissoires }
11065519cab4SBenjamin Tissoires 
110731ae9bddSBenjamin Tissoires static void mt_set_maxcontacts(struct hid_device *hdev)
110831ae9bddSBenjamin Tissoires {
110931ae9bddSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
111031ae9bddSBenjamin Tissoires 	struct hid_report *r;
111131ae9bddSBenjamin Tissoires 	struct hid_report_enum *re;
111231ae9bddSBenjamin Tissoires 	int fieldmax, max;
111331ae9bddSBenjamin Tissoires 
111431ae9bddSBenjamin Tissoires 	if (td->maxcontact_report_id < 0)
111531ae9bddSBenjamin Tissoires 		return;
111631ae9bddSBenjamin Tissoires 
111731ae9bddSBenjamin Tissoires 	if (!td->mtclass.maxcontacts)
111831ae9bddSBenjamin Tissoires 		return;
111931ae9bddSBenjamin Tissoires 
112031ae9bddSBenjamin Tissoires 	re = &hdev->report_enum[HID_FEATURE_REPORT];
112131ae9bddSBenjamin Tissoires 	r = re->report_id_hash[td->maxcontact_report_id];
112231ae9bddSBenjamin Tissoires 	if (r) {
112331ae9bddSBenjamin Tissoires 		max = td->mtclass.maxcontacts;
112431ae9bddSBenjamin Tissoires 		fieldmax = r->field[0]->logical_maximum;
112531ae9bddSBenjamin Tissoires 		max = min(fieldmax, max);
112631ae9bddSBenjamin Tissoires 		if (r->field[0]->value[0] != max) {
112731ae9bddSBenjamin Tissoires 			r->field[0]->value[0] = max;
1128d8814272SBenjamin Tissoires 			hid_hw_request(hdev, r, HID_REQ_SET_REPORT);
112931ae9bddSBenjamin Tissoires 		}
113031ae9bddSBenjamin Tissoires 	}
113131ae9bddSBenjamin Tissoires }
113231ae9bddSBenjamin Tissoires 
11334fa3a583SHenrik Rydberg static void mt_post_parse_default_settings(struct mt_device *td)
11344fa3a583SHenrik Rydberg {
11354fa3a583SHenrik Rydberg 	__s32 quirks = td->mtclass.quirks;
11364fa3a583SHenrik Rydberg 
11374fa3a583SHenrik Rydberg 	/* unknown serial device needs special quirks */
11384fa3a583SHenrik Rydberg 	if (td->touches_by_report == 1) {
11394fa3a583SHenrik Rydberg 		quirks |= MT_QUIRK_ALWAYS_VALID;
11404fa3a583SHenrik Rydberg 		quirks &= ~MT_QUIRK_NOT_SEEN_MEANS_UP;
11414fa3a583SHenrik Rydberg 		quirks &= ~MT_QUIRK_VALID_IS_INRANGE;
11424fa3a583SHenrik Rydberg 		quirks &= ~MT_QUIRK_VALID_IS_CONFIDENCE;
1143e0bb8f9aSBenjamin Tissoires 		quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
11444fa3a583SHenrik Rydberg 	}
11454fa3a583SHenrik Rydberg 
11464fa3a583SHenrik Rydberg 	td->mtclass.quirks = quirks;
11474fa3a583SHenrik Rydberg }
11484fa3a583SHenrik Rydberg 
11493ac36d15SBenjamin Tissoires static void mt_post_parse(struct mt_device *td)
11503ac36d15SBenjamin Tissoires {
11513ac36d15SBenjamin Tissoires 	struct mt_fields *f = td->fields;
1152c2517f62SBenjamin Tissoires 	struct mt_class *cls = &td->mtclass;
11533ac36d15SBenjamin Tissoires 
11543ac36d15SBenjamin Tissoires 	if (td->touches_by_report > 0) {
11553ac36d15SBenjamin Tissoires 		int field_count_per_touch = f->length / td->touches_by_report;
11563ac36d15SBenjamin Tissoires 		td->last_slot_field = f->usages[field_count_per_touch - 1];
11573ac36d15SBenjamin Tissoires 	}
1158c2517f62SBenjamin Tissoires 
11597e3cc447SBenjamin Tissoires 	if (td->cc_index < 0)
1160c2517f62SBenjamin Tissoires 		cls->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
11613ac36d15SBenjamin Tissoires }
11623ac36d15SBenjamin Tissoires 
1163b2c68a2fSDmitry Torokhov static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
116476f5902aSHenrik Rydberg {
116576f5902aSHenrik Rydberg 	struct mt_device *td = hid_get_drvdata(hdev);
1166c08d46aaSBenjamin Tissoires 	char *name;
1167c08d46aaSBenjamin Tissoires 	const char *suffix = NULL;
11686aef704eSBenjamin Tissoires 	struct hid_field *field = hi->report->field[0];
1169b2c68a2fSDmitry Torokhov 	int ret;
117076f5902aSHenrik Rydberg 
1171b2c68a2fSDmitry Torokhov 	if (hi->report->id == td->mt_report_id) {
1172b2c68a2fSDmitry Torokhov 		ret = mt_touch_input_configured(hdev, hi);
1173b2c68a2fSDmitry Torokhov 		if (ret)
1174b2c68a2fSDmitry Torokhov 			return ret;
1175b2c68a2fSDmitry Torokhov 	}
117676f5902aSHenrik Rydberg 
11776aef704eSBenjamin Tissoires 	/*
11786aef704eSBenjamin Tissoires 	 * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
11796aef704eSBenjamin Tissoires 	 * for the stylus. Check this first, and then rely on the application
11806aef704eSBenjamin Tissoires 	 * field.
11816aef704eSBenjamin Tissoires 	 */
1182c08d46aaSBenjamin Tissoires 	if (hi->report->field[0]->physical == HID_DG_STYLUS) {
1183c08d46aaSBenjamin Tissoires 		suffix = "Pen";
1184e55f6200SBenjamin Tissoires 		/* force BTN_STYLUS to allow tablet matching in udev */
1185e55f6200SBenjamin Tissoires 		__set_bit(BTN_STYLUS, hi->input->keybit);
11866aef704eSBenjamin Tissoires 	} else {
11876aef704eSBenjamin Tissoires 		switch (field->application) {
11886aef704eSBenjamin Tissoires 		case HID_GD_KEYBOARD:
11896aef704eSBenjamin Tissoires 			suffix = "Keyboard";
11906aef704eSBenjamin Tissoires 			break;
11916aef704eSBenjamin Tissoires 		case HID_GD_KEYPAD:
11926aef704eSBenjamin Tissoires 			suffix = "Keypad";
11936aef704eSBenjamin Tissoires 			break;
11946aef704eSBenjamin Tissoires 		case HID_GD_MOUSE:
11956aef704eSBenjamin Tissoires 			suffix = "Mouse";
11966aef704eSBenjamin Tissoires 			break;
11976aef704eSBenjamin Tissoires 		case HID_DG_STYLUS:
11986aef704eSBenjamin Tissoires 			suffix = "Pen";
11996aef704eSBenjamin Tissoires 			/* force BTN_STYLUS to allow tablet matching in udev */
12006aef704eSBenjamin Tissoires 			__set_bit(BTN_STYLUS, hi->input->keybit);
12016aef704eSBenjamin Tissoires 			break;
12026aef704eSBenjamin Tissoires 		case HID_DG_TOUCHSCREEN:
12036aef704eSBenjamin Tissoires 			/* we do not set suffix = "Touchscreen" */
12046aef704eSBenjamin Tissoires 			break;
1205dc425a1cSMika Westerberg 		case HID_DG_TOUCHPAD:
1206dc425a1cSMika Westerberg 			suffix = "Touchpad";
1207dc425a1cSMika Westerberg 			break;
12086aef704eSBenjamin Tissoires 		case HID_GD_SYSTEM_CONTROL:
12096aef704eSBenjamin Tissoires 			suffix = "System Control";
12106aef704eSBenjamin Tissoires 			break;
12116aef704eSBenjamin Tissoires 		case HID_CP_CONSUMER_CONTROL:
12126aef704eSBenjamin Tissoires 			suffix = "Consumer Control";
12136aef704eSBenjamin Tissoires 			break;
12141fbf74efSJoão Paulo Rechi Vita 		case HID_GD_WIRELESS_RADIO_CTLS:
12151fbf74efSJoão Paulo Rechi Vita 			suffix = "Wireless Radio Control";
12161fbf74efSJoão Paulo Rechi Vita 			break;
1217957b8dffSJoão Paulo Rechi Vita 		case HID_VD_ASUS_CUSTOM_MEDIA_KEYS:
1218957b8dffSJoão Paulo Rechi Vita 			suffix = "Custom Media Keys";
1219957b8dffSJoão Paulo Rechi Vita 			break;
12206aef704eSBenjamin Tissoires 		default:
12216aef704eSBenjamin Tissoires 			suffix = "UNKNOWN";
12226aef704eSBenjamin Tissoires 			break;
12236aef704eSBenjamin Tissoires 		}
122476f5902aSHenrik Rydberg 	}
122576f5902aSHenrik Rydberg 
1226c08d46aaSBenjamin Tissoires 	if (suffix) {
1227c08d46aaSBenjamin Tissoires 		name = devm_kzalloc(&hi->input->dev,
1228c08d46aaSBenjamin Tissoires 				    strlen(hdev->name) + strlen(suffix) + 2,
1229c08d46aaSBenjamin Tissoires 				    GFP_KERNEL);
1230c08d46aaSBenjamin Tissoires 		if (name) {
1231c08d46aaSBenjamin Tissoires 			sprintf(name, "%s %s", hdev->name, suffix);
1232c08d46aaSBenjamin Tissoires 			hi->input->name = name;
1233c08d46aaSBenjamin Tissoires 		}
1234c08d46aaSBenjamin Tissoires 	}
1235b2c68a2fSDmitry Torokhov 
1236b2c68a2fSDmitry Torokhov 	return 0;
1237c08d46aaSBenjamin Tissoires }
1238c08d46aaSBenjamin Tissoires 
1239f3287a99SBenjamin Tissoires static void mt_fix_const_field(struct hid_field *field, unsigned int usage)
1240f3287a99SBenjamin Tissoires {
1241f3287a99SBenjamin Tissoires 	if (field->usage[0].hid != usage ||
1242f3287a99SBenjamin Tissoires 	    !(field->flags & HID_MAIN_ITEM_CONSTANT))
1243f3287a99SBenjamin Tissoires 		return;
1244f3287a99SBenjamin Tissoires 
1245f3287a99SBenjamin Tissoires 	field->flags &= ~HID_MAIN_ITEM_CONSTANT;
1246f3287a99SBenjamin Tissoires 	field->flags |= HID_MAIN_ITEM_VARIABLE;
1247f3287a99SBenjamin Tissoires }
1248f3287a99SBenjamin Tissoires 
1249f3287a99SBenjamin Tissoires static void mt_fix_const_fields(struct hid_device *hdev, unsigned int usage)
1250f3287a99SBenjamin Tissoires {
1251f3287a99SBenjamin Tissoires 	struct hid_report *report;
1252f3287a99SBenjamin Tissoires 	int i;
1253f3287a99SBenjamin Tissoires 
1254f3287a99SBenjamin Tissoires 	list_for_each_entry(report,
1255f3287a99SBenjamin Tissoires 			    &hdev->report_enum[HID_INPUT_REPORT].report_list,
1256f3287a99SBenjamin Tissoires 			    list) {
1257f3287a99SBenjamin Tissoires 
1258f3287a99SBenjamin Tissoires 		if (!report->maxfield)
1259f3287a99SBenjamin Tissoires 			continue;
1260f3287a99SBenjamin Tissoires 
1261f3287a99SBenjamin Tissoires 		for (i = 0; i < report->maxfield; i++)
1262f3287a99SBenjamin Tissoires 			if (report->field[i]->maxusage >= 1)
1263f3287a99SBenjamin Tissoires 				mt_fix_const_field(report->field[i], usage);
1264f3287a99SBenjamin Tissoires 	}
1265f3287a99SBenjamin Tissoires }
1266f3287a99SBenjamin Tissoires 
12674f4001bcSBenjamin Tissoires static void mt_release_contacts(struct hid_device *hid)
12684f4001bcSBenjamin Tissoires {
12694f4001bcSBenjamin Tissoires 	struct hid_input *hidinput;
12704f4001bcSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hid);
12714f4001bcSBenjamin Tissoires 
12724f4001bcSBenjamin Tissoires 	list_for_each_entry(hidinput, &hid->inputs, list) {
12734f4001bcSBenjamin Tissoires 		struct input_dev *input_dev = hidinput->input;
12744f4001bcSBenjamin Tissoires 		struct input_mt *mt = input_dev->mt;
12754f4001bcSBenjamin Tissoires 		int i;
12764f4001bcSBenjamin Tissoires 
12774f4001bcSBenjamin Tissoires 		if (mt) {
12784f4001bcSBenjamin Tissoires 			for (i = 0; i < mt->num_slots; i++) {
12794f4001bcSBenjamin Tissoires 				input_mt_slot(input_dev, i);
12804f4001bcSBenjamin Tissoires 				input_mt_report_slot_state(input_dev,
12814f4001bcSBenjamin Tissoires 							   MT_TOOL_FINGER,
12824f4001bcSBenjamin Tissoires 							   false);
12834f4001bcSBenjamin Tissoires 			}
12844f4001bcSBenjamin Tissoires 			input_mt_sync_frame(input_dev);
12854f4001bcSBenjamin Tissoires 			input_sync(input_dev);
12864f4001bcSBenjamin Tissoires 		}
12874f4001bcSBenjamin Tissoires 	}
12884f4001bcSBenjamin Tissoires 
12894f4001bcSBenjamin Tissoires 	td->num_received = 0;
12904f4001bcSBenjamin Tissoires }
12914f4001bcSBenjamin Tissoires 
12920ee32774SKees Cook static void mt_expired_timeout(struct timer_list *t)
12934f4001bcSBenjamin Tissoires {
12940ee32774SKees Cook 	struct mt_device *td = from_timer(td, t, release_timer);
12950ee32774SKees Cook 	struct hid_device *hdev = td->hdev;
12964f4001bcSBenjamin Tissoires 
12974f4001bcSBenjamin Tissoires 	/*
12984f4001bcSBenjamin Tissoires 	 * An input report came in just before we release the sticky fingers,
12994f4001bcSBenjamin Tissoires 	 * it will take care of the sticky fingers.
13004f4001bcSBenjamin Tissoires 	 */
13014f4001bcSBenjamin Tissoires 	if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
13024f4001bcSBenjamin Tissoires 		return;
130396098274SBenjamin Tissoires 	if (test_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags))
13044f4001bcSBenjamin Tissoires 		mt_release_contacts(hdev);
13054f4001bcSBenjamin Tissoires 	clear_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags);
13064f4001bcSBenjamin Tissoires }
13074f4001bcSBenjamin Tissoires 
13085519cab4SBenjamin Tissoires static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
13095519cab4SBenjamin Tissoires {
13102d93666eSBenjamin Tissoires 	int ret, i;
13115519cab4SBenjamin Tissoires 	struct mt_device *td;
13122d93666eSBenjamin Tissoires 	struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
13132d93666eSBenjamin Tissoires 
13142d93666eSBenjamin Tissoires 	for (i = 0; mt_classes[i].name ; i++) {
13152d93666eSBenjamin Tissoires 		if (id->driver_data == mt_classes[i].name) {
13162d93666eSBenjamin Tissoires 			mtclass = &(mt_classes[i]);
13172d93666eSBenjamin Tissoires 			break;
13182d93666eSBenjamin Tissoires 		}
13192d93666eSBenjamin Tissoires 	}
13205519cab4SBenjamin Tissoires 
1321c08d46aaSBenjamin Tissoires 	td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL);
13225519cab4SBenjamin Tissoires 	if (!td) {
13235519cab4SBenjamin Tissoires 		dev_err(&hdev->dev, "cannot allocate multitouch data\n");
13245519cab4SBenjamin Tissoires 		return -ENOMEM;
13255519cab4SBenjamin Tissoires 	}
13260ee32774SKees Cook 	td->hdev = hdev;
1327eec29e3dSBenjamin Tissoires 	td->mtclass = *mtclass;
13285519cab4SBenjamin Tissoires 	td->inputmode = -1;
132931ae9bddSBenjamin Tissoires 	td->maxcontact_report_id = -1;
13309abebedbSAndrew Duggan 	td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
13317e3cc447SBenjamin Tissoires 	td->cc_index = -1;
1332fa11aa72SBenjamin Tissoires 	td->mt_report_id = -1;
13335519cab4SBenjamin Tissoires 	hid_set_drvdata(hdev, td);
13345519cab4SBenjamin Tissoires 
1335c08d46aaSBenjamin Tissoires 	td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields),
1336c08d46aaSBenjamin Tissoires 				  GFP_KERNEL);
13373ac36d15SBenjamin Tissoires 	if (!td->fields) {
13383ac36d15SBenjamin Tissoires 		dev_err(&hdev->dev, "cannot allocate multitouch fields data\n");
1339c08d46aaSBenjamin Tissoires 		return -ENOMEM;
13403ac36d15SBenjamin Tissoires 	}
13413ac36d15SBenjamin Tissoires 
134276f5902aSHenrik Rydberg 	if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
134376f5902aSHenrik Rydberg 		td->serial_maybe = true;
134476f5902aSHenrik Rydberg 
1345b897f6dbSBenjamin Tissoires 	/*
1346b897f6dbSBenjamin Tissoires 	 * Store the initial quirk state
1347b897f6dbSBenjamin Tissoires 	 */
1348b897f6dbSBenjamin Tissoires 	td->initial_quirks = hdev->quirks;
1349b897f6dbSBenjamin Tissoires 
1350b897f6dbSBenjamin Tissoires 	/* This allows the driver to correctly support devices
1351b897f6dbSBenjamin Tissoires 	 * that emit events over several HID messages.
1352b897f6dbSBenjamin Tissoires 	 */
1353b897f6dbSBenjamin Tissoires 	hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
1354b897f6dbSBenjamin Tissoires 
1355b897f6dbSBenjamin Tissoires 	/*
1356b897f6dbSBenjamin Tissoires 	 * This allows the driver to handle different input sensors
1357b897f6dbSBenjamin Tissoires 	 * that emits events through different reports on the same HID
1358b897f6dbSBenjamin Tissoires 	 * device.
1359b897f6dbSBenjamin Tissoires 	 */
1360b897f6dbSBenjamin Tissoires 	hdev->quirks |= HID_QUIRK_MULTI_INPUT;
1361b897f6dbSBenjamin Tissoires 	hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT;
1362b897f6dbSBenjamin Tissoires 
1363b897f6dbSBenjamin Tissoires 	/*
1364b897f6dbSBenjamin Tissoires 	 * Some multitouch screens do not like to be polled for input
1365b897f6dbSBenjamin Tissoires 	 * reports. Fortunately, the Win8 spec says that all touches
1366b897f6dbSBenjamin Tissoires 	 * should be sent during each report, making the initialization
1367b897f6dbSBenjamin Tissoires 	 * of input reports unnecessary. For Win7 devices, well, let's hope
1368b897f6dbSBenjamin Tissoires 	 * they will still be happy (this is only be a problem if a touch
1369b897f6dbSBenjamin Tissoires 	 * was already there while probing the device).
1370b897f6dbSBenjamin Tissoires 	 *
1371b897f6dbSBenjamin Tissoires 	 * In addition some touchpads do not behave well if we read
1372b897f6dbSBenjamin Tissoires 	 * all feature reports from them. Instead we prevent
1373b897f6dbSBenjamin Tissoires 	 * initial report fetching and then selectively fetch each
1374b897f6dbSBenjamin Tissoires 	 * report we are interested in.
1375b897f6dbSBenjamin Tissoires 	 */
1376b897f6dbSBenjamin Tissoires 	hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
1377b897f6dbSBenjamin Tissoires 
13780ee32774SKees Cook 	timer_setup(&td->release_timer, mt_expired_timeout, 0);
13794f4001bcSBenjamin Tissoires 
13805519cab4SBenjamin Tissoires 	ret = hid_parse(hdev);
13815519cab4SBenjamin Tissoires 	if (ret != 0)
1382c08d46aaSBenjamin Tissoires 		return ret;
13835519cab4SBenjamin Tissoires 
1384f3287a99SBenjamin Tissoires 	if (mtclass->quirks & MT_QUIRK_FIX_CONST_CONTACT_ID)
1385f3287a99SBenjamin Tissoires 		mt_fix_const_fields(hdev, HID_DG_CONTACTID);
1386f3287a99SBenjamin Tissoires 
13875519cab4SBenjamin Tissoires 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
13882d93666eSBenjamin Tissoires 	if (ret)
1389c08d46aaSBenjamin Tissoires 		return ret;
13905519cab4SBenjamin Tissoires 
1391eec29e3dSBenjamin Tissoires 	ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group);
13920c4b3c63SNicholas Krause 	if (ret)
13930c4b3c63SNicholas Krause 		dev_warn(&hdev->dev, "Cannot allocate sysfs group for %s\n",
13940c4b3c63SNicholas Krause 				hdev->name);
1395eec29e3dSBenjamin Tissoires 
139631ae9bddSBenjamin Tissoires 	mt_set_maxcontacts(hdev);
13975519cab4SBenjamin Tissoires 	mt_set_input_mode(hdev);
13985519cab4SBenjamin Tissoires 
1399c08d46aaSBenjamin Tissoires 	/* release .fields memory as it is not used anymore */
1400c08d46aaSBenjamin Tissoires 	devm_kfree(&hdev->dev, td->fields);
14013ac36d15SBenjamin Tissoires 	td->fields = NULL;
14023ac36d15SBenjamin Tissoires 
14035519cab4SBenjamin Tissoires 	return 0;
14045519cab4SBenjamin Tissoires }
14055519cab4SBenjamin Tissoires 
14065519cab4SBenjamin Tissoires #ifdef CONFIG_PM
14075519cab4SBenjamin Tissoires static int mt_reset_resume(struct hid_device *hdev)
14085519cab4SBenjamin Tissoires {
1409d3e69b9aSBenson Leung 	mt_release_contacts(hdev);
141031ae9bddSBenjamin Tissoires 	mt_set_maxcontacts(hdev);
14115519cab4SBenjamin Tissoires 	mt_set_input_mode(hdev);
14125519cab4SBenjamin Tissoires 	return 0;
14135519cab4SBenjamin Tissoires }
1414dfeefd10SScott Liu 
1415dfeefd10SScott Liu static int mt_resume(struct hid_device *hdev)
1416dfeefd10SScott Liu {
1417dfeefd10SScott Liu 	/* Some Elan legacy devices require SET_IDLE to be set on resume.
1418dfeefd10SScott Liu 	 * It should be safe to send it to other devices too.
1419dfeefd10SScott Liu 	 * Tested on 3M, Stantum, Cypress, Zytronic, eGalax, and Elan panels. */
1420dfeefd10SScott Liu 
14214ba25d3fSBenjamin Tissoires 	hid_hw_idle(hdev, 0, 0, HID_REQ_SET_IDLE);
1422dfeefd10SScott Liu 
1423dfeefd10SScott Liu 	return 0;
1424dfeefd10SScott Liu }
14255519cab4SBenjamin Tissoires #endif
14265519cab4SBenjamin Tissoires 
14275519cab4SBenjamin Tissoires static void mt_remove(struct hid_device *hdev)
14285519cab4SBenjamin Tissoires {
1429b897f6dbSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
1430b897f6dbSBenjamin Tissoires 
14314f4001bcSBenjamin Tissoires 	del_timer_sync(&td->release_timer);
14324f4001bcSBenjamin Tissoires 
1433eec29e3dSBenjamin Tissoires 	sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
14345939212dSBenjamin Tissoires 	hid_hw_stop(hdev);
1435b897f6dbSBenjamin Tissoires 	hdev->quirks = td->initial_quirks;
14365519cab4SBenjamin Tissoires }
14375519cab4SBenjamin Tissoires 
14380fa9c616SBenjamin Tissoires /*
14390fa9c616SBenjamin Tissoires  * This list contains only:
14400fa9c616SBenjamin Tissoires  * - VID/PID of products not working with the default multitouch handling
14410fa9c616SBenjamin Tissoires  * - 2 generic rules.
14420fa9c616SBenjamin Tissoires  * So there is no point in adding here any device with MT_CLS_DEFAULT.
14430fa9c616SBenjamin Tissoires  */
14445519cab4SBenjamin Tissoires static const struct hid_device_id mt_devices[] = {
14455519cab4SBenjamin Tissoires 
1446f786bba4SBenjamin Tissoires 	/* 3M panels */
1447f786bba4SBenjamin Tissoires 	{ .driver_data = MT_CLS_3M,
14482c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_3M,
1449f786bba4SBenjamin Tissoires 			USB_DEVICE_ID_3M1968) },
1450f786bba4SBenjamin Tissoires 	{ .driver_data = MT_CLS_3M,
14512c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_3M,
1452f786bba4SBenjamin Tissoires 			USB_DEVICE_ID_3M2256) },
1453c4fad877SBenjamin Tissoires 	{ .driver_data = MT_CLS_3M,
14542c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_3M,
1455c4fad877SBenjamin Tissoires 			USB_DEVICE_ID_3M3266) },
1456f786bba4SBenjamin Tissoires 
1457504c932cSMasaki Ota 	/* Alps devices */
1458504c932cSMasaki Ota 	{ .driver_data = MT_CLS_WIN_8_DUAL,
1459504c932cSMasaki Ota 		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
1460504c932cSMasaki Ota 			USB_VENDOR_ID_ALPS_JP,
1461504c932cSMasaki Ota 			HID_DEVICE_ID_ALPS_U1_DUAL_PTP) },
1462504c932cSMasaki Ota 	{ .driver_data = MT_CLS_WIN_8_DUAL,
1463504c932cSMasaki Ota 		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
1464504c932cSMasaki Ota 			USB_VENDOR_ID_ALPS_JP,
1465504c932cSMasaki Ota 			HID_DEVICE_ID_ALPS_U1_DUAL_3BTN_PTP) },
1466504c932cSMasaki Ota 
146756d859e1SPavel Tatashin 	/* Lenovo X1 TAB Gen 2 */
146856d859e1SPavel Tatashin 	{ .driver_data = MT_CLS_WIN_8_DUAL,
146956d859e1SPavel Tatashin 		HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8,
147056d859e1SPavel Tatashin 			   USB_VENDOR_ID_LENOVO,
147156d859e1SPavel Tatashin 			   USB_DEVICE_ID_LENOVO_X1_TAB) },
147256d859e1SPavel Tatashin 
14736aef704eSBenjamin Tissoires 	/* Anton devices */
14746aef704eSBenjamin Tissoires 	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
14756aef704eSBenjamin Tissoires 		MT_USB_DEVICE(USB_VENDOR_ID_ANTON,
14766aef704eSBenjamin Tissoires 			USB_DEVICE_ID_ANTON_TOUCH_PAD) },
1477e6aac342SBenjamin Tissoires 
1478957b8dffSJoão Paulo Rechi Vita 	/* Asus T304UA */
1479957b8dffSJoão Paulo Rechi Vita 	{ .driver_data = MT_CLS_ASUS,
1480957b8dffSJoão Paulo Rechi Vita 		HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8,
1481957b8dffSJoão Paulo Rechi Vita 			USB_VENDOR_ID_ASUSTEK,
1482957b8dffSJoão Paulo Rechi Vita 			USB_DEVICE_ID_ASUSTEK_T304_KEYBOARD) },
1483957b8dffSJoão Paulo Rechi Vita 
1484b1057124SBenjamin Tissoires 	/* Atmel panels */
1485b1057124SBenjamin Tissoires 	{ .driver_data = MT_CLS_SERIAL,
14862c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_ATMEL,
1487841cb157SBenjamin Tissoires 			USB_DEVICE_ID_ATMEL_MXT_DIGITIZER) },
1488b1057124SBenjamin Tissoires 
14899ed32695SJiri Kosina 	/* Baanto multitouch devices */
1490dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
149116b79bb8SJiri Kosina 		MT_USB_DEVICE(USB_VENDOR_ID_BAANTO,
14929ed32695SJiri Kosina 			USB_DEVICE_ID_BAANTO_MT_190W2) },
14930fa9c616SBenjamin Tissoires 
1494a841b62cSBenjamin Tissoires 	/* Cando panels */
1495a841b62cSBenjamin Tissoires 	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
14962c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
1497a841b62cSBenjamin Tissoires 			USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
1498a841b62cSBenjamin Tissoires 	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
14992c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
1500a841b62cSBenjamin Tissoires 			USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
1501a841b62cSBenjamin Tissoires 
1502942fd422SAustin Zhang 	/* Chunghwa Telecom touch panels */
1503dc3e1d80SBenjamin Tissoires 	{  .driver_data = MT_CLS_NSMU,
15042c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT,
1505942fd422SAustin Zhang 			USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) },
1506942fd422SAustin Zhang 
1507070f63b4SYang Bo 	/* CJTouch panels */
1508070f63b4SYang Bo 	{ .driver_data = MT_CLS_NSMU,
1509070f63b4SYang Bo 		MT_USB_DEVICE(USB_VENDOR_ID_CJTOUCH,
1510070f63b4SYang Bo 			USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0020) },
1511070f63b4SYang Bo 	{ .driver_data = MT_CLS_NSMU,
1512070f63b4SYang Bo 		MT_USB_DEVICE(USB_VENDOR_ID_CJTOUCH,
1513070f63b4SYang Bo 			USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0040) },
1514070f63b4SYang Bo 
151579603dc9SBenjamin Tissoires 	/* CVTouch panels */
1516dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
15172c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_CVTOUCH,
151879603dc9SBenjamin Tissoires 			USB_DEVICE_ID_CVTOUCH_SCREEN) },
151979603dc9SBenjamin Tissoires 
152022408283SBenjamin Tissoires 	/* eGalax devices (resistive) */
152122408283SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX,
15222c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1523e36f690bSBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D) },
152422408283SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX,
15252c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1526e36f690bSBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E) },
152722408283SBenjamin Tissoires 
152822408283SBenjamin Tissoires 	/* eGalax devices (capacitive) */
1529fd1d1525SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
15302c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1531fd1d1525SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7207) },
153222408283SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX,
15332c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1534e36f690bSBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C) },
1535fd1d1525SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
15362c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1537fd1d1525SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224) },
15382ce09df4SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
15392c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
15402ce09df4SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_722A) },
154122408283SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
15422c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
154322408283SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_725E) },
1544fd1d1525SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
15452c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1546fd1d1525SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7262) },
154722408283SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX,
15482c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
154922408283SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B) },
155022408283SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX,
155122408283SBenjamin Tissoires 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1552e36f690bSBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1) },
1553fd1d1525SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
15542c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1555fd1d1525SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72AA) },
15561fd8f047SChris Bagwell 	{ .driver_data = MT_CLS_EGALAX,
1557aa672da1SAndy Shevchenko 		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
1558aa672da1SAndy Shevchenko 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72C4) },
1559aa672da1SAndy Shevchenko 	{ .driver_data = MT_CLS_EGALAX,
1560aa672da1SAndy Shevchenko 		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
1561aa672da1SAndy Shevchenko 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72D0) },
1562aa672da1SAndy Shevchenko 	{ .driver_data = MT_CLS_EGALAX,
15632c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
156466f06127SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA) },
156566f06127SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX,
15662c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1567bb9ff210SMarek Vasut 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302) },
15681b723e8dSBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
15692c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1570fd1d1525SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7349) },
1571fd1d1525SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
15722c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1573ae01c9e5SThierry Reding 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_73F7) },
1574ae01c9e5SThierry Reding 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
1575ae01c9e5SThierry Reding 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1576e36f690bSBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) },
157722408283SBenjamin Tissoires 
15787c7606a2STomas Sokorai 	/* Elitegroup panel */
15797c7606a2STomas Sokorai 	{ .driver_data = MT_CLS_SERIAL,
15807c7606a2STomas Sokorai 		MT_USB_DEVICE(USB_VENDOR_ID_ELITEGROUP,
15817c7606a2STomas Sokorai 			USB_DEVICE_ID_ELITEGROUP_05D8) },
15827c7606a2STomas Sokorai 
158377723e3bSHenrik Rydberg 	/* Flatfrog Panels */
158477723e3bSHenrik Rydberg 	{ .driver_data = MT_CLS_FLATFROG,
158577723e3bSHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_FLATFROG,
158677723e3bSHenrik Rydberg 			USB_DEVICE_ID_MULTITOUCH_3200) },
158777723e3bSHenrik Rydberg 
15883db187e7SBenjamin Tissoires 	/* FocalTech Panels */
15893db187e7SBenjamin Tissoires 	{ .driver_data = MT_CLS_SERIAL,
15903db187e7SBenjamin Tissoires 		MT_USB_DEVICE(USB_VENDOR_ID_CYGNAL,
15913db187e7SBenjamin Tissoires 			USB_DEVICE_ID_FOCALTECH_FTXXXX_MULTITOUCH) },
15923db187e7SBenjamin Tissoires 
15935572da08SBenjamin Tissoires 	/* GeneralTouch panel */
1594f5ff4e1eSXianhan Yu 	{ .driver_data = MT_CLS_GENERALTOUCH_TWOFINGERS,
15952c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
15965572da08SBenjamin Tissoires 			USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
1597f5ff4e1eSXianhan Yu 	{ .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
1598f5ff4e1eSXianhan Yu 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
1599f5ff4e1eSXianhan Yu 			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PWT_TENFINGERS) },
16007b226292SLuosong 	{ .driver_data = MT_CLS_GENERALTOUCH_TWOFINGERS,
16017b226292SLuosong 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
16027b226292SLuosong 			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0101) },
16037b226292SLuosong 	{ .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
16047b226292SLuosong 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
16057b226292SLuosong 			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0102) },
16067b226292SLuosong 	{ .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
16077b226292SLuosong 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
16087b226292SLuosong 			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0106) },
16097b226292SLuosong 	{ .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
16107b226292SLuosong 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
16117b226292SLuosong 			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_010A) },
16127b226292SLuosong 	{ .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
16137b226292SLuosong 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
16147b226292SLuosong 			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100) },
16155572da08SBenjamin Tissoires 
16164d5df5d1SAndreas Nielsen 	/* Gametel game controller */
1617dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
16182c2110e9SHenrik Rydberg 		MT_BT_DEVICE(USB_VENDOR_ID_FRUCTEL,
16194d5df5d1SAndreas Nielsen 			USB_DEVICE_ID_GAMETEL_MT_MODE) },
16204d5df5d1SAndreas Nielsen 
1621ee0fbd14SBenjamin Tissoires 	/* GoodTouch panels */
1622dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
16232c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH,
1624ee0fbd14SBenjamin Tissoires 			USB_DEVICE_ID_GOODTOUCH_000f) },
1625ee0fbd14SBenjamin Tissoires 
162654580365SBenjamin Tissoires 	/* Hanvon panels */
162754580365SBenjamin Tissoires 	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
16282c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT,
162954580365SBenjamin Tissoires 			USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) },
163054580365SBenjamin Tissoires 
16314e61f0d7SAustin Zhang 	/* Ilitek dual touch panel */
1632dc3e1d80SBenjamin Tissoires 	{  .driver_data = MT_CLS_NSMU,
16332c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_ILITEK,
16344e61f0d7SAustin Zhang 			USB_DEVICE_ID_ILITEK_MULTITOUCH) },
16354e61f0d7SAustin Zhang 
1636f3287a99SBenjamin Tissoires 	/* LG Melfas panel */
1637f3287a99SBenjamin Tissoires 	{ .driver_data = MT_CLS_LG,
1638f3287a99SBenjamin Tissoires 		HID_USB_DEVICE(USB_VENDOR_ID_LG,
1639f3287a99SBenjamin Tissoires 			USB_DEVICE_ID_LG_MELFAS_MT) },
1640f3287a99SBenjamin Tissoires 
16414a6ee685SBenjamin Tissoires 	/* MosArt panels */
16424a6ee685SBenjamin Tissoires 	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
16432c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_ASUS,
16444a6ee685SBenjamin Tissoires 			USB_DEVICE_ID_ASUS_T91MT)},
16454a6ee685SBenjamin Tissoires 	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
16462c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_ASUS,
16474a6ee685SBenjamin Tissoires 			USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) },
16484a6ee685SBenjamin Tissoires 	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
16492c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_TURBOX,
16504a6ee685SBenjamin Tissoires 			USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) },
16514a6ee685SBenjamin Tissoires 
16524db703eaSAustin Hendrix 	/* Novatek Panel */
1653dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
16544380d819SJiri Kosina 		MT_USB_DEVICE(USB_VENDOR_ID_NOVATEK,
16554db703eaSAustin Hendrix 			USB_DEVICE_ID_NOVATEK_PCT) },
16564db703eaSAustin Hendrix 
1657a80e803aSBenjamin Tissoires 	/* Ntrig Panel */
1658a80e803aSBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
1659a80e803aSBenjamin Tissoires 		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
1660a80e803aSBenjamin Tissoires 			USB_VENDOR_ID_NTRIG, 0x1b05) },
1661a80e803aSBenjamin Tissoires 
1662*fb55b402SHans de Goede 	/* Panasonic panels */
1663*fb55b402SHans de Goede 	{ .driver_data = MT_CLS_PANASONIC,
1664*fb55b402SHans de Goede 		MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC,
1665*fb55b402SHans de Goede 			USB_DEVICE_ID_PANABOARD_UBT780) },
1666*fb55b402SHans de Goede 	{ .driver_data = MT_CLS_PANASONIC,
1667*fb55b402SHans de Goede 		MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC,
1668*fb55b402SHans de Goede 			USB_DEVICE_ID_PANABOARD_UBT880) },
1669*fb55b402SHans de Goede 
1670b7ea95ffSAaron Tian 	/* PixArt optical touch screen */
1671b7ea95ffSAaron Tian 	{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
16722c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_PIXART,
1673b7ea95ffSAaron Tian 			USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN) },
1674b7ea95ffSAaron Tian 	{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
16752c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_PIXART,
1676b7ea95ffSAaron Tian 			USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1) },
1677b7ea95ffSAaron Tian 	{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
16782c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_PIXART,
1679b7ea95ffSAaron Tian 			USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2) },
1680b7ea95ffSAaron Tian 
16815519cab4SBenjamin Tissoires 	/* PixCir-based panels */
16821e9cf35bSBenjamin Tissoires 	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
16832c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
16845519cab4SBenjamin Tissoires 			USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
16855519cab4SBenjamin Tissoires 
16865e7ea11fSBenjamin Tissoires 	/* Quanta-based panels */
16875e7ea11fSBenjamin Tissoires 	{ .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID,
16882c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_QUANTA,
16895e7ea11fSBenjamin Tissoires 			USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001) },
1690a6802e00SForest Bond 
1691043b403aSBenjamin Tissoires 	/* Stantum panels */
1692bf5af9b5SBenjamin Tissoires 	{ .driver_data = MT_CLS_CONFIDENCE,
16932c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM,
1694043b403aSBenjamin Tissoires 			USB_DEVICE_ID_MTP_STM)},
1695043b403aSBenjamin Tissoires 
1696847672cdSBenjamin Tissoires 	/* TopSeed panels */
1697847672cdSBenjamin Tissoires 	{ .driver_data = MT_CLS_TOPSEED,
16982c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_TOPSEED2,
1699847672cdSBenjamin Tissoires 			USB_DEVICE_ID_TOPSEED2_PERIPAD_701) },
1700847672cdSBenjamin Tissoires 
17015e74e56dSBenjamin Tissoires 	/* Touch International panels */
1702dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
17032c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_TOUCH_INTL,
17045e74e56dSBenjamin Tissoires 			USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH) },
17055e74e56dSBenjamin Tissoires 
1706617b64f9SBenjamin Tissoires 	/* Unitec panels */
1707dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
17082c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_UNITEC,
1709617b64f9SBenjamin Tissoires 			USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) },
1710dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
17112c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_UNITEC,
1712617b64f9SBenjamin Tissoires 			USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
1713bf9d121eSKaiChung Cheng 
1714da10bc25SMathieu Magnaudet 	/* VTL panels */
1715da10bc25SMathieu Magnaudet 	{ .driver_data = MT_CLS_VTL,
1716da10bc25SMathieu Magnaudet 		MT_USB_DEVICE(USB_VENDOR_ID_VTL,
1717da10bc25SMathieu Magnaudet 			USB_DEVICE_ID_VTL_MULTITOUCH_FF3F) },
1718da10bc25SMathieu Magnaudet 
1719bf9d121eSKaiChung Cheng 	/* Wistron panels */
1720bf9d121eSKaiChung Cheng 	{ .driver_data = MT_CLS_NSMU,
1721bf9d121eSKaiChung Cheng 		MT_USB_DEVICE(USB_VENDOR_ID_WISTRON,
1722bf9d121eSKaiChung Cheng 			USB_DEVICE_ID_WISTRON_OPTICAL_TOUCH) },
1723bf9d121eSKaiChung Cheng 
1724bc8a2a9bSice chien 	/* XAT */
1725dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
17262c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XAT,
1727bc8a2a9bSice chien 			USB_DEVICE_ID_XAT_CSR) },
1728617b64f9SBenjamin Tissoires 
172911576c61SMasatoshi Hoshikawa 	/* Xiroku */
1730dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
17312c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
173211576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_SPX) },
1733dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
17342c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
173511576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_MPX) },
1736dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
17372c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
173811576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_CSR) },
1739dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
17402c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
174111576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_SPX1) },
1742dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
17432c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
174411576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_MPX1) },
1745dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
17462c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
174711576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_CSR1) },
1748dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
17492c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
175011576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_SPX2) },
1751dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
17522c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
175311576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_MPX2) },
1754dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
17552c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
175611576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_CSR2) },
175711576c61SMasatoshi Hoshikawa 
17580e82232cSWei-Ning Huang 	/* Google MT devices */
17590e82232cSWei-Ning Huang 	{ .driver_data = MT_CLS_GOOGLE,
17600e82232cSWei-Ning Huang 		HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_GOOGLE,
17610e82232cSWei-Ning Huang 			USB_DEVICE_ID_GOOGLE_TOUCH_ROSE) },
17620e82232cSWei-Ning Huang 
17634fa3a583SHenrik Rydberg 	/* Generic MT device */
17644fa3a583SHenrik Rydberg 	{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH, HID_ANY_ID, HID_ANY_ID) },
1765f961bd35SBenjamin Tissoires 
1766f961bd35SBenjamin Tissoires 	/* Generic Win 8 certified MT device */
1767f961bd35SBenjamin Tissoires 	{  .driver_data = MT_CLS_WIN_8,
1768f961bd35SBenjamin Tissoires 		HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH_WIN_8,
1769f961bd35SBenjamin Tissoires 			HID_ANY_ID, HID_ANY_ID) },
17705519cab4SBenjamin Tissoires 	{ }
17715519cab4SBenjamin Tissoires };
17725519cab4SBenjamin Tissoires MODULE_DEVICE_TABLE(hid, mt_devices);
17735519cab4SBenjamin Tissoires 
17745519cab4SBenjamin Tissoires static const struct hid_usage_id mt_grabbed_usages[] = {
17755519cab4SBenjamin Tissoires 	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
17765519cab4SBenjamin Tissoires 	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
17775519cab4SBenjamin Tissoires };
17785519cab4SBenjamin Tissoires 
17795519cab4SBenjamin Tissoires static struct hid_driver mt_driver = {
17805519cab4SBenjamin Tissoires 	.name = "hid-multitouch",
17815519cab4SBenjamin Tissoires 	.id_table = mt_devices,
17825519cab4SBenjamin Tissoires 	.probe = mt_probe,
17835519cab4SBenjamin Tissoires 	.remove = mt_remove,
17845519cab4SBenjamin Tissoires 	.input_mapping = mt_input_mapping,
17855519cab4SBenjamin Tissoires 	.input_mapped = mt_input_mapped,
178676f5902aSHenrik Rydberg 	.input_configured = mt_input_configured,
17875519cab4SBenjamin Tissoires 	.feature_mapping = mt_feature_mapping,
17885519cab4SBenjamin Tissoires 	.usage_table = mt_grabbed_usages,
17895519cab4SBenjamin Tissoires 	.event = mt_event,
179055978fa9SBenjamin Tissoires 	.report = mt_report,
17915519cab4SBenjamin Tissoires #ifdef CONFIG_PM
17925519cab4SBenjamin Tissoires 	.reset_resume = mt_reset_resume,
1793dfeefd10SScott Liu 	.resume = mt_resume,
17945519cab4SBenjamin Tissoires #endif
17955519cab4SBenjamin Tissoires };
1796f425458eSH Hartley Sweeten module_hid_driver(mt_driver);
1797