xref: /linux/drivers/hid/hid-multitouch.c (revision 843e475f)
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)
77d9c57a70SBenjamin Tissoires #define MT_QUIRK_WIN8_PTP_BUTTONS	BIT(18)
785519cab4SBenjamin Tissoires 
799abebedbSAndrew Duggan #define MT_INPUTMODE_TOUCHSCREEN	0x02
809abebedbSAndrew Duggan #define MT_INPUTMODE_TOUCHPAD		0x03
819abebedbSAndrew Duggan 
822c6e0277SSeth Forshee #define MT_BUTTONTYPE_CLICKPAD		0
832c6e0277SSeth Forshee 
844f4001bcSBenjamin Tissoires #define MT_IO_FLAGS_RUNNING		0
8596098274SBenjamin Tissoires #define MT_IO_FLAGS_ACTIVE_SLOTS	1
8696098274SBenjamin Tissoires #define MT_IO_FLAGS_PENDING_SLOTS	2
874f4001bcSBenjamin Tissoires 
885519cab4SBenjamin Tissoires struct mt_slot {
8900720277SWei-Ning Huang 	__s32 x, y, cx, cy, p, w, h, a;
905519cab4SBenjamin Tissoires 	__s32 contactid;	/* the device ContactID assigned to this slot */
915519cab4SBenjamin Tissoires 	bool touch_state;	/* is the touch valid? */
929b3bb9b8SBenjamin Tissoires 	bool inrange_state;	/* is the finger in proximity of the sensor? */
936dd2e27aSAllen Hung 	bool confidence_state;  /* is the touch made by a finger? */
9400720277SWei-Ning Huang 	bool has_azimuth;       /* the contact reports azimuth */
955519cab4SBenjamin Tissoires };
965519cab4SBenjamin Tissoires 
975519cab4SBenjamin Tissoires struct mt_class {
982d93666eSBenjamin Tissoires 	__s32 name;	/* MT_CLS */
995519cab4SBenjamin Tissoires 	__s32 quirks;
1005519cab4SBenjamin Tissoires 	__s32 sn_move;	/* Signal/noise ratio for move events */
101f786bba4SBenjamin Tissoires 	__s32 sn_width;	/* Signal/noise ratio for width events */
102f786bba4SBenjamin Tissoires 	__s32 sn_height;	/* Signal/noise ratio for height events */
1035519cab4SBenjamin Tissoires 	__s32 sn_pressure;	/* Signal/noise ratio for pressure events */
1045519cab4SBenjamin Tissoires 	__u8 maxcontacts;
105c2ef8f21SBenjamin Tissoires 	bool is_indirect;	/* true for touchpads */
1066aef704eSBenjamin Tissoires 	bool export_all_inputs;	/* do not ignore mouse, keyboards, etc... */
1075519cab4SBenjamin Tissoires };
1085519cab4SBenjamin Tissoires 
1093ac36d15SBenjamin Tissoires struct mt_fields {
1103ac36d15SBenjamin Tissoires 	unsigned usages[HID_MAX_FIELDS];
1113ac36d15SBenjamin Tissoires 	unsigned int length;
1123ac36d15SBenjamin Tissoires };
1133ac36d15SBenjamin Tissoires 
1145519cab4SBenjamin Tissoires struct mt_device {
1155519cab4SBenjamin Tissoires 	struct mt_slot curdata;	/* placeholder of incoming data */
116eec29e3dSBenjamin Tissoires 	struct mt_class mtclass;	/* our mt device class */
1174f4001bcSBenjamin Tissoires 	struct timer_list release_timer;	/* to release sticky fingers */
1180ee32774SKees Cook 	struct hid_device *hdev;	/* hid_device we're attached to */
1193ac36d15SBenjamin Tissoires 	struct mt_fields *fields;	/* temporary placeholder for storing the
1203ac36d15SBenjamin Tissoires 					   multitouch fields */
1214f4001bcSBenjamin Tissoires 	unsigned long mt_io_flags;	/* mt flags (MT_IO_FLAGS_*) */
1227e3cc447SBenjamin Tissoires 	int cc_index;	/* contact count field index in the report */
1237e3cc447SBenjamin Tissoires 	int cc_value_index;	/* contact count value index in the field */
124af8dc4d0SHans de Goede 	int scantime_index;	/* scantime field index in the report */
125af8dc4d0SHans de Goede 	int scantime_val_index;	/* scantime value index in the field */
126af8dc4d0SHans de Goede 	int prev_scantime;	/* scantime reported in the previous packet */
127127e71bdSHans de Goede 	int left_button_state;	/* left button state */
1285519cab4SBenjamin Tissoires 	unsigned last_slot_field;	/* the last field of a slot */
12955978fa9SBenjamin Tissoires 	unsigned mt_report_id;	/* the report ID of the multitouch device */
130b897f6dbSBenjamin Tissoires 	unsigned long initial_quirks;	/* initial quirks state */
1318821f5dcSBenjamin Tissoires 	__s16 inputmode;	/* InputMode HID feature, -1 if non-existent */
1328821f5dcSBenjamin Tissoires 	__s16 inputmode_index;	/* InputMode HID feature index in the report */
1338821f5dcSBenjamin Tissoires 	__s16 maxcontact_report_id;	/* Maximum Contact Number HID feature,
13431ae9bddSBenjamin Tissoires 				   -1 if non-existent */
1359abebedbSAndrew Duggan 	__u8 inputmode_value;  /* InputMode HID feature value */
1365519cab4SBenjamin Tissoires 	__u8 num_received;	/* how many contacts we received */
1375519cab4SBenjamin Tissoires 	__u8 num_expected;	/* expected last contact index */
1385519cab4SBenjamin Tissoires 	__u8 maxcontacts;
1399e87f22aSBenjamin Tissoires 	__u8 touches_by_report;	/* how many touches are present in one report:
1409e87f22aSBenjamin Tissoires 				* 1 means we should use a serial protocol
1419e87f22aSBenjamin Tissoires 				* > 1 means hybrid (multitouch) protocol */
142015fdaa9SBenjamin Tissoires 	__u8 buttons_count;	/* number of physical buttons per touchpad */
1432c6e0277SSeth Forshee 	bool is_buttonpad;	/* is this device a button pad? */
14476f5902aSHenrik Rydberg 	bool serial_maybe;	/* need to check for serial protocol */
1455519cab4SBenjamin Tissoires 	bool curvalid;		/* is the current contact valid? */
14676f5902aSHenrik Rydberg 	unsigned mt_flags;	/* flags to pass to input-mt */
14729cc309dSNicolas Boichat 	__s32 dev_time;		/* the scan time provided by the device */
14829cc309dSNicolas Boichat 	unsigned long jiffies;	/* the frame's jiffies */
14929cc309dSNicolas Boichat 	int timestamp;		/* the timestamp to be sent */
1505519cab4SBenjamin Tissoires };
1515519cab4SBenjamin Tissoires 
152a69c5f8bSBenjamin Tissoires static void mt_post_parse_default_settings(struct mt_device *td);
153a69c5f8bSBenjamin Tissoires static void mt_post_parse(struct mt_device *td);
154a69c5f8bSBenjamin Tissoires 
1555519cab4SBenjamin Tissoires /* classes of device behavior */
15622408283SBenjamin Tissoires #define MT_CLS_DEFAULT				0x0001
15722408283SBenjamin Tissoires 
158a062cc5aSStephane Chatty #define MT_CLS_SERIAL				0x0002
159a062cc5aSStephane Chatty #define MT_CLS_CONFIDENCE			0x0003
1605e7ea11fSBenjamin Tissoires #define MT_CLS_CONFIDENCE_CONTACT_ID		0x0004
1615e7ea11fSBenjamin Tissoires #define MT_CLS_CONFIDENCE_MINUS_ONE		0x0005
1625e7ea11fSBenjamin Tissoires #define MT_CLS_DUAL_INRANGE_CONTACTID		0x0006
1635e7ea11fSBenjamin Tissoires #define MT_CLS_DUAL_INRANGE_CONTACTNUMBER	0x0007
1640fa9c616SBenjamin Tissoires /* reserved					0x0008 */
165b7ea95ffSAaron Tian #define MT_CLS_INRANGE_CONTACTNUMBER		0x0009
166dc3e1d80SBenjamin Tissoires #define MT_CLS_NSMU				0x000a
1670fa9c616SBenjamin Tissoires /* reserved					0x0010 */
1680fa9c616SBenjamin Tissoires /* reserved					0x0011 */
169f961bd35SBenjamin Tissoires #define MT_CLS_WIN_8				0x0012
1706aef704eSBenjamin Tissoires #define MT_CLS_EXPORT_ALL_INPUTS		0x0013
171504c932cSMasaki Ota #define MT_CLS_WIN_8_DUAL			0x0014
17222408283SBenjamin Tissoires 
17322408283SBenjamin Tissoires /* vendor specific classes */
17422408283SBenjamin Tissoires #define MT_CLS_3M				0x0101
1750fa9c616SBenjamin Tissoires /* reserved					0x0102 */
17622408283SBenjamin Tissoires #define MT_CLS_EGALAX				0x0103
1771b723e8dSBenjamin Tissoires #define MT_CLS_EGALAX_SERIAL			0x0104
178847672cdSBenjamin Tissoires #define MT_CLS_TOPSEED				0x0105
1792258e863SDenis Kovalev #define MT_CLS_PANASONIC			0x0106
18077723e3bSHenrik Rydberg #define MT_CLS_FLATFROG				0x0107
181cdcd3ac4SJiri Kosina #define MT_CLS_GENERALTOUCH_TWOFINGERS		0x0108
182cdcd3ac4SJiri Kosina #define MT_CLS_GENERALTOUCH_PWT_TENFINGERS	0x0109
183f3287a99SBenjamin Tissoires #define MT_CLS_LG				0x010a
184957b8dffSJoão Paulo Rechi Vita #define MT_CLS_ASUS				0x010b
185da10bc25SMathieu Magnaudet #define MT_CLS_VTL				0x0110
1860e82232cSWei-Ning Huang #define MT_CLS_GOOGLE				0x0111
187*843e475fSBenjamin Tissoires #define MT_CLS_RAZER_BLADE_STEALTH		0x0112
1885519cab4SBenjamin Tissoires 
1899498f954SBenjamin Tissoires #define MT_DEFAULT_MAXCONTACT	10
190afbcb04cSBenjamin Tissoires #define MT_MAX_MAXCONTACT	250
1919498f954SBenjamin Tissoires 
19229cc309dSNicolas Boichat /*
19329cc309dSNicolas Boichat  * Resync device and local timestamps after that many microseconds without
19429cc309dSNicolas Boichat  * receiving data.
19529cc309dSNicolas Boichat  */
19629cc309dSNicolas Boichat #define MAX_TIMESTAMP_INTERVAL	1000000
19729cc309dSNicolas Boichat 
1982c2110e9SHenrik Rydberg #define MT_USB_DEVICE(v, p)	HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH, v, p)
1992c2110e9SHenrik Rydberg #define MT_BT_DEVICE(v, p)	HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_MULTITOUCH, v, p)
2002c2110e9SHenrik Rydberg 
2015519cab4SBenjamin Tissoires /*
2025519cab4SBenjamin Tissoires  * these device-dependent functions determine what slot corresponds
2035519cab4SBenjamin Tissoires  * to a valid contact that was just read.
2045519cab4SBenjamin Tissoires  */
2055519cab4SBenjamin Tissoires 
206a3b5e577SBenjamin Tissoires static int cypress_compute_slot(struct mt_device *td)
207a3b5e577SBenjamin Tissoires {
208a3b5e577SBenjamin Tissoires 	if (td->curdata.contactid != 0 || td->num_received == 0)
209a3b5e577SBenjamin Tissoires 		return td->curdata.contactid;
210a3b5e577SBenjamin Tissoires 	else
211a3b5e577SBenjamin Tissoires 		return -1;
212a3b5e577SBenjamin Tissoires }
213a3b5e577SBenjamin Tissoires 
214b3c21d2cSJiri Kosina static struct mt_class mt_classes[] = {
2152d93666eSBenjamin Tissoires 	{ .name = MT_CLS_DEFAULT,
216dc3e1d80SBenjamin Tissoires 		.quirks = MT_QUIRK_ALWAYS_VALID |
217dc3e1d80SBenjamin Tissoires 			MT_QUIRK_CONTACT_CNT_ACCURATE },
218dc3e1d80SBenjamin Tissoires 	{ .name = MT_CLS_NSMU,
2199498f954SBenjamin Tissoires 		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP },
220a062cc5aSStephane Chatty 	{ .name = MT_CLS_SERIAL,
221a062cc5aSStephane Chatty 		.quirks = MT_QUIRK_ALWAYS_VALID},
22222408283SBenjamin Tissoires 	{ .name = MT_CLS_CONFIDENCE,
22322408283SBenjamin Tissoires 		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE },
2245e7ea11fSBenjamin Tissoires 	{ .name = MT_CLS_CONFIDENCE_CONTACT_ID,
2255e7ea11fSBenjamin Tissoires 		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
2265e7ea11fSBenjamin Tissoires 			MT_QUIRK_SLOT_IS_CONTACTID },
22722408283SBenjamin Tissoires 	{ .name = MT_CLS_CONFIDENCE_MINUS_ONE,
22822408283SBenjamin Tissoires 		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
22922408283SBenjamin Tissoires 			MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE },
2301e9cf35bSBenjamin Tissoires 	{ .name = MT_CLS_DUAL_INRANGE_CONTACTID,
2312d93666eSBenjamin Tissoires 		.quirks = MT_QUIRK_VALID_IS_INRANGE |
2322d93666eSBenjamin Tissoires 			MT_QUIRK_SLOT_IS_CONTACTID,
2332d93666eSBenjamin Tissoires 		.maxcontacts = 2 },
2341e9cf35bSBenjamin Tissoires 	{ .name = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
2352d93666eSBenjamin Tissoires 		.quirks = MT_QUIRK_VALID_IS_INRANGE |
2362d93666eSBenjamin Tissoires 			MT_QUIRK_SLOT_IS_CONTACTNUMBER,
2372d93666eSBenjamin Tissoires 		.maxcontacts = 2 },
238b7ea95ffSAaron Tian 	{ .name = MT_CLS_INRANGE_CONTACTNUMBER,
239b7ea95ffSAaron Tian 		.quirks = MT_QUIRK_VALID_IS_INRANGE |
240b7ea95ffSAaron Tian 			MT_QUIRK_SLOT_IS_CONTACTNUMBER },
241f961bd35SBenjamin Tissoires 	{ .name = MT_CLS_WIN_8,
242f961bd35SBenjamin Tissoires 		.quirks = MT_QUIRK_ALWAYS_VALID |
243f961bd35SBenjamin Tissoires 			MT_QUIRK_IGNORE_DUPLICATES |
244f961bd35SBenjamin Tissoires 			MT_QUIRK_HOVERING |
2454f4001bcSBenjamin Tissoires 			MT_QUIRK_CONTACT_CNT_ACCURATE |
246d9c57a70SBenjamin Tissoires 			MT_QUIRK_STICKY_FINGERS |
247d9c57a70SBenjamin Tissoires 			MT_QUIRK_WIN8_PTP_BUTTONS },
2486aef704eSBenjamin Tissoires 	{ .name = MT_CLS_EXPORT_ALL_INPUTS,
2496aef704eSBenjamin Tissoires 		.quirks = MT_QUIRK_ALWAYS_VALID |
2506aef704eSBenjamin Tissoires 			MT_QUIRK_CONTACT_CNT_ACCURATE,
2516aef704eSBenjamin Tissoires 		.export_all_inputs = true },
252504c932cSMasaki Ota 	{ .name = MT_CLS_WIN_8_DUAL,
253504c932cSMasaki Ota 		.quirks = MT_QUIRK_ALWAYS_VALID |
254504c932cSMasaki Ota 			MT_QUIRK_IGNORE_DUPLICATES |
255504c932cSMasaki Ota 			MT_QUIRK_HOVERING |
256d9c57a70SBenjamin Tissoires 			MT_QUIRK_CONTACT_CNT_ACCURATE |
257d9c57a70SBenjamin Tissoires 			MT_QUIRK_WIN8_PTP_BUTTONS,
258504c932cSMasaki Ota 		.export_all_inputs = true },
25922408283SBenjamin Tissoires 
26022408283SBenjamin Tissoires 	/*
26122408283SBenjamin Tissoires 	 * vendor specific classes
26222408283SBenjamin Tissoires 	 */
26322408283SBenjamin Tissoires 	{ .name = MT_CLS_3M,
26422408283SBenjamin Tissoires 		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
265e9d0a26dSHungNien Chen 			MT_QUIRK_SLOT_IS_CONTACTID |
266e9d0a26dSHungNien Chen 			MT_QUIRK_TOUCH_SIZE_SCALING,
26722408283SBenjamin Tissoires 		.sn_move = 2048,
26822408283SBenjamin Tissoires 		.sn_width = 128,
269c5d40be5SHenrik Rydberg 		.sn_height = 128,
270c5d40be5SHenrik Rydberg 		.maxcontacts = 60,
271c5d40be5SHenrik Rydberg 	},
2724875ac11SRichard Nauber 	{ .name = MT_CLS_EGALAX,
2734875ac11SRichard Nauber 		.quirks =  MT_QUIRK_SLOT_IS_CONTACTID |
2742261bb9fSBenjamin Tissoires 			MT_QUIRK_VALID_IS_INRANGE,
2754875ac11SRichard Nauber 		.sn_move = 4096,
2764875ac11SRichard Nauber 		.sn_pressure = 32,
2774875ac11SRichard Nauber 	},
2781b723e8dSBenjamin Tissoires 	{ .name = MT_CLS_EGALAX_SERIAL,
2791b723e8dSBenjamin Tissoires 		.quirks =  MT_QUIRK_SLOT_IS_CONTACTID |
2801b723e8dSBenjamin Tissoires 			MT_QUIRK_ALWAYS_VALID,
2812d93666eSBenjamin Tissoires 		.sn_move = 4096,
2822d93666eSBenjamin Tissoires 		.sn_pressure = 32,
2832d93666eSBenjamin Tissoires 	},
284847672cdSBenjamin Tissoires 	{ .name = MT_CLS_TOPSEED,
285847672cdSBenjamin Tissoires 		.quirks = MT_QUIRK_ALWAYS_VALID,
286847672cdSBenjamin Tissoires 		.is_indirect = true,
287847672cdSBenjamin Tissoires 		.maxcontacts = 2,
288847672cdSBenjamin Tissoires 	},
2892258e863SDenis Kovalev 	{ .name = MT_CLS_PANASONIC,
2902258e863SDenis Kovalev 		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP,
2912258e863SDenis Kovalev 		.maxcontacts = 4 },
292f5ff4e1eSXianhan Yu 	{ .name	= MT_CLS_GENERALTOUCH_TWOFINGERS,
293f5ff4e1eSXianhan Yu 		.quirks	= MT_QUIRK_NOT_SEEN_MEANS_UP |
294f5ff4e1eSXianhan Yu 			MT_QUIRK_VALID_IS_INRANGE |
2957b226292SLuosong 			MT_QUIRK_SLOT_IS_CONTACTID,
296f5ff4e1eSXianhan Yu 		.maxcontacts = 2
297f5ff4e1eSXianhan Yu 	},
298f5ff4e1eSXianhan Yu 	{ .name	= MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
299f5ff4e1eSXianhan Yu 		.quirks	= MT_QUIRK_NOT_SEEN_MEANS_UP |
3007b226292SLuosong 			MT_QUIRK_SLOT_IS_CONTACTID
301f5ff4e1eSXianhan Yu 	},
302043b403aSBenjamin Tissoires 
30377723e3bSHenrik Rydberg 	{ .name = MT_CLS_FLATFROG,
30477723e3bSHenrik Rydberg 		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
30577723e3bSHenrik Rydberg 			MT_QUIRK_NO_AREA,
30677723e3bSHenrik Rydberg 		.sn_move = 2048,
30777723e3bSHenrik Rydberg 		.maxcontacts = 40,
30877723e3bSHenrik Rydberg 	},
309f3287a99SBenjamin Tissoires 	{ .name = MT_CLS_LG,
310f3287a99SBenjamin Tissoires 		.quirks = MT_QUIRK_ALWAYS_VALID |
311f3287a99SBenjamin Tissoires 			MT_QUIRK_FIX_CONST_CONTACT_ID |
312f3287a99SBenjamin Tissoires 			MT_QUIRK_IGNORE_DUPLICATES |
313f3287a99SBenjamin Tissoires 			MT_QUIRK_HOVERING |
314f3287a99SBenjamin Tissoires 			MT_QUIRK_CONTACT_CNT_ACCURATE },
315957b8dffSJoão Paulo Rechi Vita 	{ .name = MT_CLS_ASUS,
316957b8dffSJoão Paulo Rechi Vita 		.quirks = MT_QUIRK_ALWAYS_VALID |
317957b8dffSJoão Paulo Rechi Vita 			MT_QUIRK_CONTACT_CNT_ACCURATE |
318957b8dffSJoão Paulo Rechi Vita 			MT_QUIRK_ASUS_CUSTOM_UP },
319da10bc25SMathieu Magnaudet 	{ .name = MT_CLS_VTL,
320da10bc25SMathieu Magnaudet 		.quirks = MT_QUIRK_ALWAYS_VALID |
321da10bc25SMathieu Magnaudet 			MT_QUIRK_CONTACT_CNT_ACCURATE |
322da10bc25SMathieu Magnaudet 			MT_QUIRK_FORCE_GET_FEATURE,
323da10bc25SMathieu Magnaudet 	},
3240e82232cSWei-Ning Huang 	{ .name = MT_CLS_GOOGLE,
3250e82232cSWei-Ning Huang 		.quirks = MT_QUIRK_ALWAYS_VALID |
3260e82232cSWei-Ning Huang 			MT_QUIRK_CONTACT_CNT_ACCURATE |
3270e82232cSWei-Ning Huang 			MT_QUIRK_SLOT_IS_CONTACTID |
3280e82232cSWei-Ning Huang 			MT_QUIRK_HOVERING
3290e82232cSWei-Ning Huang 	},
330*843e475fSBenjamin Tissoires 	{ .name = MT_CLS_RAZER_BLADE_STEALTH,
331*843e475fSBenjamin Tissoires 		.quirks = MT_QUIRK_ALWAYS_VALID |
332*843e475fSBenjamin Tissoires 			MT_QUIRK_IGNORE_DUPLICATES |
333*843e475fSBenjamin Tissoires 			MT_QUIRK_HOVERING |
334*843e475fSBenjamin Tissoires 			MT_QUIRK_CONTACT_CNT_ACCURATE |
335*843e475fSBenjamin Tissoires 			MT_QUIRK_WIN8_PTP_BUTTONS,
336*843e475fSBenjamin Tissoires 	},
3372d93666eSBenjamin Tissoires 	{ }
3385519cab4SBenjamin Tissoires };
3395519cab4SBenjamin Tissoires 
340eec29e3dSBenjamin Tissoires static ssize_t mt_show_quirks(struct device *dev,
341eec29e3dSBenjamin Tissoires 			   struct device_attribute *attr,
342eec29e3dSBenjamin Tissoires 			   char *buf)
343eec29e3dSBenjamin Tissoires {
344ee79a8f8SGeliang Tang 	struct hid_device *hdev = to_hid_device(dev);
345eec29e3dSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
346eec29e3dSBenjamin Tissoires 
347eec29e3dSBenjamin Tissoires 	return sprintf(buf, "%u\n", td->mtclass.quirks);
348eec29e3dSBenjamin Tissoires }
349eec29e3dSBenjamin Tissoires 
350eec29e3dSBenjamin Tissoires static ssize_t mt_set_quirks(struct device *dev,
351eec29e3dSBenjamin Tissoires 			  struct device_attribute *attr,
352eec29e3dSBenjamin Tissoires 			  const char *buf, size_t count)
353eec29e3dSBenjamin Tissoires {
354ee79a8f8SGeliang Tang 	struct hid_device *hdev = to_hid_device(dev);
355eec29e3dSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
356eec29e3dSBenjamin Tissoires 
357eec29e3dSBenjamin Tissoires 	unsigned long val;
358eec29e3dSBenjamin Tissoires 
359eec29e3dSBenjamin Tissoires 	if (kstrtoul(buf, 0, &val))
360eec29e3dSBenjamin Tissoires 		return -EINVAL;
361eec29e3dSBenjamin Tissoires 
362eec29e3dSBenjamin Tissoires 	td->mtclass.quirks = val;
363eec29e3dSBenjamin Tissoires 
3647e3cc447SBenjamin Tissoires 	if (td->cc_index < 0)
365c2517f62SBenjamin Tissoires 		td->mtclass.quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
366c2517f62SBenjamin Tissoires 
367eec29e3dSBenjamin Tissoires 	return count;
368eec29e3dSBenjamin Tissoires }
369eec29e3dSBenjamin Tissoires 
370eec29e3dSBenjamin Tissoires static DEVICE_ATTR(quirks, S_IWUSR | S_IRUGO, mt_show_quirks, mt_set_quirks);
371eec29e3dSBenjamin Tissoires 
372eec29e3dSBenjamin Tissoires static struct attribute *sysfs_attrs[] = {
373eec29e3dSBenjamin Tissoires 	&dev_attr_quirks.attr,
374eec29e3dSBenjamin Tissoires 	NULL
375eec29e3dSBenjamin Tissoires };
376eec29e3dSBenjamin Tissoires 
3779182fb98SArvind Yadav static const struct attribute_group mt_attribute_group = {
378eec29e3dSBenjamin Tissoires 	.attrs = sysfs_attrs
379eec29e3dSBenjamin Tissoires };
380eec29e3dSBenjamin Tissoires 
3816d4f5440SMika Westerberg static void mt_get_feature(struct hid_device *hdev, struct hid_report *report)
3826d4f5440SMika Westerberg {
3836d4f5440SMika Westerberg 	struct mt_device *td = hid_get_drvdata(hdev);
3846d4f5440SMika Westerberg 	int ret, size = hid_report_len(report);
3856d4f5440SMika Westerberg 	u8 *buf;
3866d4f5440SMika Westerberg 
3876d4f5440SMika Westerberg 	/*
388b897f6dbSBenjamin Tissoires 	 * Do not fetch the feature report if the device has been explicitly
389b897f6dbSBenjamin Tissoires 	 * marked as non-capable.
3906d4f5440SMika Westerberg 	 */
391b897f6dbSBenjamin Tissoires 	if (td->initial_quirks & HID_QUIRK_NO_INIT_REPORTS)
3926d4f5440SMika Westerberg 		return;
3936d4f5440SMika Westerberg 
3946d4f5440SMika Westerberg 	buf = hid_alloc_report_buf(report, GFP_KERNEL);
3956d4f5440SMika Westerberg 	if (!buf)
3966d4f5440SMika Westerberg 		return;
3976d4f5440SMika Westerberg 
3986d4f5440SMika Westerberg 	ret = hid_hw_raw_request(hdev, report->id, buf, size,
3996d4f5440SMika Westerberg 				 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
4006d4f5440SMika Westerberg 	if (ret < 0) {
4016d4f5440SMika Westerberg 		dev_warn(&hdev->dev, "failed to fetch feature %d\n",
4026d4f5440SMika Westerberg 			 report->id);
4036d4f5440SMika Westerberg 	} else {
4046d4f5440SMika Westerberg 		ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf,
4056d4f5440SMika Westerberg 					   size, 0);
4066d4f5440SMika Westerberg 		if (ret)
4076d4f5440SMika Westerberg 			dev_warn(&hdev->dev, "failed to report feature\n");
4086d4f5440SMika Westerberg 	}
4096d4f5440SMika Westerberg 
4106d4f5440SMika Westerberg 	kfree(buf);
4116d4f5440SMika Westerberg }
4126d4f5440SMika Westerberg 
413f635bd11SHenrik Rydberg static void mt_feature_mapping(struct hid_device *hdev,
4145519cab4SBenjamin Tissoires 		struct hid_field *field, struct hid_usage *usage)
4155519cab4SBenjamin Tissoires {
4165519cab4SBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
4179498f954SBenjamin Tissoires 
4189498f954SBenjamin Tissoires 	switch (usage->hid) {
4199498f954SBenjamin Tissoires 	case HID_DG_INPUTMODE:
4208821f5dcSBenjamin Tissoires 		/* Ignore if value index is out of bounds. */
4218821f5dcSBenjamin Tissoires 		if (usage->usage_index >= field->report_count) {
4228821f5dcSBenjamin Tissoires 			dev_err(&hdev->dev, "HID_DG_INPUTMODE out of range\n");
4234aceed37SBenjamin Tissoires 			break;
4244aceed37SBenjamin Tissoires 		}
4258821f5dcSBenjamin Tissoires 
42673e7d63eSBenjamin Tissoires 		if (td->inputmode < 0) {
4278821f5dcSBenjamin Tissoires 			td->inputmode = field->report->id;
4288821f5dcSBenjamin Tissoires 			td->inputmode_index = usage->usage_index;
42973e7d63eSBenjamin Tissoires 		} else {
43073e7d63eSBenjamin Tissoires 			/*
43173e7d63eSBenjamin Tissoires 			 * Some elan panels wrongly declare 2 input mode
43273e7d63eSBenjamin Tissoires 			 * features, and silently ignore when we set the
43373e7d63eSBenjamin Tissoires 			 * value in the second field. Skip the second feature
43473e7d63eSBenjamin Tissoires 			 * and hope for the best.
43573e7d63eSBenjamin Tissoires 			 */
43673e7d63eSBenjamin Tissoires 			dev_info(&hdev->dev,
43773e7d63eSBenjamin Tissoires 				 "Ignoring the extra HID_DG_INPUTMODE\n");
43873e7d63eSBenjamin Tissoires 		}
4394aceed37SBenjamin Tissoires 
4409498f954SBenjamin Tissoires 		break;
4419498f954SBenjamin Tissoires 	case HID_DG_CONTACTMAX:
4426d4f5440SMika Westerberg 		mt_get_feature(hdev, field->report);
4436d4f5440SMika Westerberg 
44431ae9bddSBenjamin Tissoires 		td->maxcontact_report_id = field->report->id;
4459498f954SBenjamin Tissoires 		td->maxcontacts = field->value[0];
446afbcb04cSBenjamin Tissoires 		if (!td->maxcontacts &&
447afbcb04cSBenjamin Tissoires 		    field->logical_maximum <= MT_MAX_MAXCONTACT)
448afbcb04cSBenjamin Tissoires 			td->maxcontacts = field->logical_maximum;
449eec29e3dSBenjamin Tissoires 		if (td->mtclass.maxcontacts)
4509498f954SBenjamin Tissoires 			/* check if the maxcontacts is given by the class */
451eec29e3dSBenjamin Tissoires 			td->maxcontacts = td->mtclass.maxcontacts;
4529498f954SBenjamin Tissoires 
4539498f954SBenjamin Tissoires 		break;
4542c6e0277SSeth Forshee 	case HID_DG_BUTTONTYPE:
4552c6e0277SSeth Forshee 		if (usage->usage_index >= field->report_count) {
4562c6e0277SSeth Forshee 			dev_err(&hdev->dev, "HID_DG_BUTTONTYPE out of range\n");
4572c6e0277SSeth Forshee 			break;
4582c6e0277SSeth Forshee 		}
4592c6e0277SSeth Forshee 
4606d4f5440SMika Westerberg 		mt_get_feature(hdev, field->report);
4612c6e0277SSeth Forshee 		if (field->value[usage->usage_index] == MT_BUTTONTYPE_CLICKPAD)
4622c6e0277SSeth Forshee 			td->is_buttonpad = true;
4632c6e0277SSeth Forshee 
4642c6e0277SSeth Forshee 		break;
46545c5c682SBenjamin Tissoires 	case 0xff0000c5:
46645c5c682SBenjamin Tissoires 		/* Retrieve the Win8 blob once to enable some devices */
46745c5c682SBenjamin Tissoires 		if (usage->usage_index == 0)
46845c5c682SBenjamin Tissoires 			mt_get_feature(hdev, field->report);
46945c5c682SBenjamin Tissoires 		break;
4705519cab4SBenjamin Tissoires 	}
4715519cab4SBenjamin Tissoires }
4725519cab4SBenjamin Tissoires 
4735519cab4SBenjamin Tissoires static void set_abs(struct input_dev *input, unsigned int code,
4745519cab4SBenjamin Tissoires 		struct hid_field *field, int snratio)
4755519cab4SBenjamin Tissoires {
4765519cab4SBenjamin Tissoires 	int fmin = field->logical_minimum;
4775519cab4SBenjamin Tissoires 	int fmax = field->logical_maximum;
4785519cab4SBenjamin Tissoires 	int fuzz = snratio ? (fmax - fmin) / snratio : 0;
4795519cab4SBenjamin Tissoires 	input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
48037cf6e6fSBenjamin Tissoires 	input_abs_set_res(input, code, hidinput_calc_abs_res(field, code));
4815519cab4SBenjamin Tissoires }
4825519cab4SBenjamin Tissoires 
4833ac36d15SBenjamin Tissoires static void mt_store_field(struct hid_usage *usage, struct mt_device *td,
484ed9d5c96SBenjamin Tissoires 		struct hid_input *hi)
485ed9d5c96SBenjamin Tissoires {
4863ac36d15SBenjamin Tissoires 	struct mt_fields *f = td->fields;
4873ac36d15SBenjamin Tissoires 
4883ac36d15SBenjamin Tissoires 	if (f->length >= HID_MAX_FIELDS)
4893ac36d15SBenjamin Tissoires 		return;
4903ac36d15SBenjamin Tissoires 
4913ac36d15SBenjamin Tissoires 	f->usages[f->length++] = usage->hid;
492ed9d5c96SBenjamin Tissoires }
493ed9d5c96SBenjamin Tissoires 
494a69c5f8bSBenjamin Tissoires static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
4955519cab4SBenjamin Tissoires 		struct hid_field *field, struct hid_usage *usage,
4965519cab4SBenjamin Tissoires 		unsigned long **bit, int *max)
4975519cab4SBenjamin Tissoires {
4985519cab4SBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
499eec29e3dSBenjamin Tissoires 	struct mt_class *cls = &td->mtclass;
500c2ef8f21SBenjamin Tissoires 	int code;
501349fd670SBenjamin Tissoires 	struct hid_usage *prev_usage = NULL;
5024875ac11SRichard Nauber 
503658d4aedSJeff Brown 	if (field->application == HID_DG_TOUCHSCREEN)
50476f5902aSHenrik Rydberg 		td->mt_flags |= INPUT_MT_DIRECT;
505658d4aedSJeff Brown 
50676f5902aSHenrik Rydberg 	/*
50776f5902aSHenrik Rydberg 	 * Model touchscreens providing buttons as touchpads.
508c2ef8f21SBenjamin Tissoires 	 */
509c2ef8f21SBenjamin Tissoires 	if (field->application == HID_DG_TOUCHPAD ||
5109abebedbSAndrew Duggan 	    (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {
51176f5902aSHenrik Rydberg 		td->mt_flags |= INPUT_MT_POINTER;
5129abebedbSAndrew Duggan 		td->inputmode_value = MT_INPUTMODE_TOUCHPAD;
5139abebedbSAndrew Duggan 	}
514c2ef8f21SBenjamin Tissoires 
515015fdaa9SBenjamin Tissoires 	/* count the buttons on touchpads */
516015fdaa9SBenjamin Tissoires 	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON)
517015fdaa9SBenjamin Tissoires 		td->buttons_count++;
518015fdaa9SBenjamin Tissoires 
519349fd670SBenjamin Tissoires 	if (usage->usage_index)
520349fd670SBenjamin Tissoires 		prev_usage = &field->usage[usage->usage_index - 1];
521349fd670SBenjamin Tissoires 
5225519cab4SBenjamin Tissoires 	switch (usage->hid & HID_USAGE_PAGE) {
5235519cab4SBenjamin Tissoires 
5245519cab4SBenjamin Tissoires 	case HID_UP_GENDESK:
5255519cab4SBenjamin Tissoires 		switch (usage->hid) {
5265519cab4SBenjamin Tissoires 		case HID_GD_X:
527349fd670SBenjamin Tissoires 			if (prev_usage && (prev_usage->hid == usage->hid)) {
528349fd670SBenjamin Tissoires 				hid_map_usage(hi, usage, bit, max,
529349fd670SBenjamin Tissoires 					EV_ABS, ABS_MT_TOOL_X);
530349fd670SBenjamin Tissoires 				set_abs(hi->input, ABS_MT_TOOL_X, field,
531349fd670SBenjamin Tissoires 					cls->sn_move);
532349fd670SBenjamin Tissoires 			} else {
5335519cab4SBenjamin Tissoires 				hid_map_usage(hi, usage, bit, max,
5345519cab4SBenjamin Tissoires 					EV_ABS, ABS_MT_POSITION_X);
5355519cab4SBenjamin Tissoires 				set_abs(hi->input, ABS_MT_POSITION_X, field,
5365519cab4SBenjamin Tissoires 					cls->sn_move);
537349fd670SBenjamin Tissoires 			}
538349fd670SBenjamin Tissoires 
5393ac36d15SBenjamin Tissoires 			mt_store_field(usage, td, hi);
5405519cab4SBenjamin Tissoires 			return 1;
5415519cab4SBenjamin Tissoires 		case HID_GD_Y:
542349fd670SBenjamin Tissoires 			if (prev_usage && (prev_usage->hid == usage->hid)) {
543349fd670SBenjamin Tissoires 				hid_map_usage(hi, usage, bit, max,
544349fd670SBenjamin Tissoires 					EV_ABS, ABS_MT_TOOL_Y);
545349fd670SBenjamin Tissoires 				set_abs(hi->input, ABS_MT_TOOL_Y, field,
546349fd670SBenjamin Tissoires 					cls->sn_move);
547349fd670SBenjamin Tissoires 			} else {
5485519cab4SBenjamin Tissoires 				hid_map_usage(hi, usage, bit, max,
5495519cab4SBenjamin Tissoires 					EV_ABS, ABS_MT_POSITION_Y);
5505519cab4SBenjamin Tissoires 				set_abs(hi->input, ABS_MT_POSITION_Y, field,
5515519cab4SBenjamin Tissoires 					cls->sn_move);
552349fd670SBenjamin Tissoires 			}
553349fd670SBenjamin Tissoires 
5543ac36d15SBenjamin Tissoires 			mt_store_field(usage, td, hi);
5555519cab4SBenjamin Tissoires 			return 1;
5565519cab4SBenjamin Tissoires 		}
5575519cab4SBenjamin Tissoires 		return 0;
5585519cab4SBenjamin Tissoires 
5595519cab4SBenjamin Tissoires 	case HID_UP_DIGITIZER:
5605519cab4SBenjamin Tissoires 		switch (usage->hid) {
5615519cab4SBenjamin Tissoires 		case HID_DG_INRANGE:
5629b3bb9b8SBenjamin Tissoires 			if (cls->quirks & MT_QUIRK_HOVERING) {
5639b3bb9b8SBenjamin Tissoires 				hid_map_usage(hi, usage, bit, max,
5649b3bb9b8SBenjamin Tissoires 					EV_ABS, ABS_MT_DISTANCE);
5659b3bb9b8SBenjamin Tissoires 				input_set_abs_params(hi->input,
5669b3bb9b8SBenjamin Tissoires 					ABS_MT_DISTANCE, 0, 1, 0, 0);
5679b3bb9b8SBenjamin Tissoires 			}
5683ac36d15SBenjamin Tissoires 			mt_store_field(usage, td, hi);
5695519cab4SBenjamin Tissoires 			return 1;
5705519cab4SBenjamin Tissoires 		case HID_DG_CONFIDENCE:
571504c932cSMasaki Ota 			if ((cls->name == MT_CLS_WIN_8 ||
572504c932cSMasaki Ota 				cls->name == MT_CLS_WIN_8_DUAL) &&
5736dd2e27aSAllen Hung 				field->application == HID_DG_TOUCHPAD)
5746dd2e27aSAllen Hung 				cls->quirks |= MT_QUIRK_CONFIDENCE;
5753ac36d15SBenjamin Tissoires 			mt_store_field(usage, td, hi);
5765519cab4SBenjamin Tissoires 			return 1;
5775519cab4SBenjamin Tissoires 		case HID_DG_TIPSWITCH:
5785519cab4SBenjamin Tissoires 			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
5795519cab4SBenjamin Tissoires 			input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
5803ac36d15SBenjamin Tissoires 			mt_store_field(usage, td, hi);
5815519cab4SBenjamin Tissoires 			return 1;
5825519cab4SBenjamin Tissoires 		case HID_DG_CONTACTID:
5833ac36d15SBenjamin Tissoires 			mt_store_field(usage, td, hi);
5849e87f22aSBenjamin Tissoires 			td->touches_by_report++;
58555978fa9SBenjamin Tissoires 			td->mt_report_id = field->report->id;
5865519cab4SBenjamin Tissoires 			return 1;
5875519cab4SBenjamin Tissoires 		case HID_DG_WIDTH:
5885519cab4SBenjamin Tissoires 			hid_map_usage(hi, usage, bit, max,
5895519cab4SBenjamin Tissoires 					EV_ABS, ABS_MT_TOUCH_MAJOR);
59077723e3bSHenrik Rydberg 			if (!(cls->quirks & MT_QUIRK_NO_AREA))
591f786bba4SBenjamin Tissoires 				set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
592f786bba4SBenjamin Tissoires 					cls->sn_width);
5933ac36d15SBenjamin Tissoires 			mt_store_field(usage, td, hi);
5945519cab4SBenjamin Tissoires 			return 1;
5955519cab4SBenjamin Tissoires 		case HID_DG_HEIGHT:
5965519cab4SBenjamin Tissoires 			hid_map_usage(hi, usage, bit, max,
5975519cab4SBenjamin Tissoires 					EV_ABS, ABS_MT_TOUCH_MINOR);
59877723e3bSHenrik Rydberg 			if (!(cls->quirks & MT_QUIRK_NO_AREA)) {
599f786bba4SBenjamin Tissoires 				set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
600f786bba4SBenjamin Tissoires 					cls->sn_height);
60100720277SWei-Ning Huang 
60200720277SWei-Ning Huang 				/*
60300720277SWei-Ning Huang 				 * Only set ABS_MT_ORIENTATION if it is not
60400720277SWei-Ning Huang 				 * already set by the HID_DG_AZIMUTH usage.
60500720277SWei-Ning Huang 				 */
60600720277SWei-Ning Huang 				if (!test_bit(ABS_MT_ORIENTATION,
60700720277SWei-Ning Huang 						hi->input->absbit))
6081e648a13SBenjamin Tissoires 					input_set_abs_params(hi->input,
6091e648a13SBenjamin Tissoires 						ABS_MT_ORIENTATION, 0, 1, 0, 0);
61077723e3bSHenrik Rydberg 			}
6113ac36d15SBenjamin Tissoires 			mt_store_field(usage, td, hi);
6125519cab4SBenjamin Tissoires 			return 1;
6135519cab4SBenjamin Tissoires 		case HID_DG_TIPPRESSURE:
6145519cab4SBenjamin Tissoires 			hid_map_usage(hi, usage, bit, max,
6155519cab4SBenjamin Tissoires 					EV_ABS, ABS_MT_PRESSURE);
6165519cab4SBenjamin Tissoires 			set_abs(hi->input, ABS_MT_PRESSURE, field,
6175519cab4SBenjamin Tissoires 				cls->sn_pressure);
6183ac36d15SBenjamin Tissoires 			mt_store_field(usage, td, hi);
6195519cab4SBenjamin Tissoires 			return 1;
62029cc309dSNicolas Boichat 		case HID_DG_SCANTIME:
62129cc309dSNicolas Boichat 			hid_map_usage(hi, usage, bit, max,
62229cc309dSNicolas Boichat 				EV_MSC, MSC_TIMESTAMP);
62329cc309dSNicolas Boichat 			input_set_capability(hi->input, EV_MSC, MSC_TIMESTAMP);
62429cc309dSNicolas Boichat 			mt_store_field(usage, td, hi);
625af8dc4d0SHans de Goede 			/* Ignore if indexes are out of bounds. */
626af8dc4d0SHans de Goede 			if (field->index >= field->report->maxfield ||
627af8dc4d0SHans de Goede 			    usage->usage_index >= field->report_count)
628af8dc4d0SHans de Goede 				return 1;
629af8dc4d0SHans de Goede 			td->scantime_index = field->index;
630af8dc4d0SHans de Goede 			td->scantime_val_index = usage->usage_index;
63129cc309dSNicolas Boichat 			return 1;
6325519cab4SBenjamin Tissoires 		case HID_DG_CONTACTCOUNT:
6338821f5dcSBenjamin Tissoires 			/* Ignore if indexes are out of bounds. */
6348821f5dcSBenjamin Tissoires 			if (field->index >= field->report->maxfield ||
6358821f5dcSBenjamin Tissoires 			    usage->usage_index >= field->report_count)
6368821f5dcSBenjamin Tissoires 				return 1;
6377e3cc447SBenjamin Tissoires 			td->cc_index = field->index;
6387e3cc447SBenjamin Tissoires 			td->cc_value_index = usage->usage_index;
6395519cab4SBenjamin Tissoires 			return 1;
64000720277SWei-Ning Huang 		case HID_DG_AZIMUTH:
64100720277SWei-Ning Huang 			hid_map_usage(hi, usage, bit, max,
64200720277SWei-Ning Huang 				EV_ABS, ABS_MT_ORIENTATION);
64300720277SWei-Ning Huang 			/*
64400720277SWei-Ning Huang 			 * Azimuth has the range of [0, MAX) representing a full
64500720277SWei-Ning Huang 			 * revolution. Set ABS_MT_ORIENTATION to a quarter of
64600720277SWei-Ning Huang 			 * MAX according the definition of ABS_MT_ORIENTATION
64700720277SWei-Ning Huang 			 */
64800720277SWei-Ning Huang 			input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
64900720277SWei-Ning Huang 				-field->logical_maximum / 4,
65000720277SWei-Ning Huang 				field->logical_maximum / 4,
65100720277SWei-Ning Huang 				cls->sn_move ?
65200720277SWei-Ning Huang 				field->logical_maximum / cls->sn_move : 0, 0);
65300720277SWei-Ning Huang 			mt_store_field(usage, td, hi);
65400720277SWei-Ning Huang 			return 1;
6555519cab4SBenjamin Tissoires 		case HID_DG_CONTACTMAX:
6565519cab4SBenjamin Tissoires 			/* we don't set td->last_slot_field as contactcount and
6575519cab4SBenjamin Tissoires 			 * contact max are global to the report */
6585519cab4SBenjamin Tissoires 			return -1;
659c2ef8f21SBenjamin Tissoires 		case HID_DG_TOUCH:
660c2ef8f21SBenjamin Tissoires 			/* Legacy devices use TIPSWITCH and not TOUCH.
661c2ef8f21SBenjamin Tissoires 			 * Let's just ignore this field. */
662c2ef8f21SBenjamin Tissoires 			return -1;
66365b258e9SAlan Cox 		}
6645519cab4SBenjamin Tissoires 		/* let hid-input decide for the others */
6655519cab4SBenjamin Tissoires 		return 0;
6665519cab4SBenjamin Tissoires 
667c2ef8f21SBenjamin Tissoires 	case HID_UP_BUTTON:
668c2ef8f21SBenjamin Tissoires 		code = BTN_MOUSE + ((usage->hid - 1) & HID_USAGE);
669594312b8SBenjamin Tissoires 		/*
670594312b8SBenjamin Tissoires 		 * MS PTP spec says that external buttons left and right have
671594312b8SBenjamin Tissoires 		 * usages 2 and 3.
672594312b8SBenjamin Tissoires 		 */
673d9c57a70SBenjamin Tissoires 		if ((cls->quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
674594312b8SBenjamin Tissoires 		    field->application == HID_DG_TOUCHPAD &&
675594312b8SBenjamin Tissoires 		    (usage->hid & HID_USAGE) > 1)
676594312b8SBenjamin Tissoires 			code--;
677c2ef8f21SBenjamin Tissoires 		hid_map_usage(hi, usage, bit, max, EV_KEY, code);
678c2ef8f21SBenjamin Tissoires 		input_set_capability(hi->input, EV_KEY, code);
679c2ef8f21SBenjamin Tissoires 		return 1;
680c2ef8f21SBenjamin Tissoires 
6815519cab4SBenjamin Tissoires 	case 0xff000000:
6825519cab4SBenjamin Tissoires 		/* we do not want to map these: no input-oriented meaning */
6835519cab4SBenjamin Tissoires 		return -1;
6845519cab4SBenjamin Tissoires 	}
6855519cab4SBenjamin Tissoires 
6865519cab4SBenjamin Tissoires 	return 0;
6875519cab4SBenjamin Tissoires }
6885519cab4SBenjamin Tissoires 
6893e1b5015SHenrik Rydberg static int mt_compute_slot(struct mt_device *td, struct input_dev *input)
6905519cab4SBenjamin Tissoires {
691eec29e3dSBenjamin Tissoires 	__s32 quirks = td->mtclass.quirks;
6925519cab4SBenjamin Tissoires 
6932d93666eSBenjamin Tissoires 	if (quirks & MT_QUIRK_SLOT_IS_CONTACTID)
6942d93666eSBenjamin Tissoires 		return td->curdata.contactid;
6955519cab4SBenjamin Tissoires 
6962d93666eSBenjamin Tissoires 	if (quirks & MT_QUIRK_CYPRESS)
697a3b5e577SBenjamin Tissoires 		return cypress_compute_slot(td);
698a3b5e577SBenjamin Tissoires 
6992d93666eSBenjamin Tissoires 	if (quirks & MT_QUIRK_SLOT_IS_CONTACTNUMBER)
7002d93666eSBenjamin Tissoires 		return td->num_received;
7015572da08SBenjamin Tissoires 
7024a6ee685SBenjamin Tissoires 	if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE)
7034a6ee685SBenjamin Tissoires 		return td->curdata.contactid - 1;
7044a6ee685SBenjamin Tissoires 
7053e1b5015SHenrik Rydberg 	return input_mt_get_slot_by_key(input, td->curdata.contactid);
7065519cab4SBenjamin Tissoires }
7075519cab4SBenjamin Tissoires 
7085519cab4SBenjamin Tissoires /*
7095519cab4SBenjamin Tissoires  * this function is called when a whole contact has been processed,
7105519cab4SBenjamin Tissoires  * so that it can assign it to a slot and store the data there
7115519cab4SBenjamin Tissoires  */
7123e1b5015SHenrik Rydberg static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
7135519cab4SBenjamin Tissoires {
714c2517f62SBenjamin Tissoires 	if ((td->mtclass.quirks & MT_QUIRK_CONTACT_CNT_ACCURATE) &&
715c2517f62SBenjamin Tissoires 	    td->num_received >= td->num_expected)
716c2517f62SBenjamin Tissoires 		return;
717c2517f62SBenjamin Tissoires 
71820b60e6dSBenjamin Tissoires 	if (td->curvalid || (td->mtclass.quirks & MT_QUIRK_ALWAYS_VALID)) {
7196dd2e27aSAllen Hung 		int active;
7203e1b5015SHenrik Rydberg 		int slotnum = mt_compute_slot(td, input);
7213e1b5015SHenrik Rydberg 		struct mt_slot *s = &td->curdata;
72228728399SBenjamin Tissoires 		struct input_mt *mt = input->mt;
7235519cab4SBenjamin Tissoires 
7243e1b5015SHenrik Rydberg 		if (slotnum < 0 || slotnum >= td->maxcontacts)
7253e1b5015SHenrik Rydberg 			return;
7265519cab4SBenjamin Tissoires 
72728728399SBenjamin Tissoires 		if ((td->mtclass.quirks & MT_QUIRK_IGNORE_DUPLICATES) && mt) {
72828728399SBenjamin Tissoires 			struct input_mt_slot *slot = &mt->slots[slotnum];
72928728399SBenjamin Tissoires 			if (input_mt_is_active(slot) &&
73028728399SBenjamin Tissoires 			    input_mt_is_used(mt, slot))
73128728399SBenjamin Tissoires 				return;
73228728399SBenjamin Tissoires 		}
73328728399SBenjamin Tissoires 
7346dd2e27aSAllen Hung 		if (!(td->mtclass.quirks & MT_QUIRK_CONFIDENCE))
7356dd2e27aSAllen Hung 			s->confidence_state = 1;
7366dd2e27aSAllen Hung 		active = (s->touch_state || s->inrange_state) &&
7376dd2e27aSAllen Hung 							s->confidence_state;
7386dd2e27aSAllen Hung 
7393e1b5015SHenrik Rydberg 		input_mt_slot(input, slotnum);
7406dd2e27aSAllen Hung 		input_mt_report_slot_state(input, MT_TOOL_FINGER, active);
7416dd2e27aSAllen Hung 		if (active) {
7429b3bb9b8SBenjamin Tissoires 			/* this finger is in proximity of the sensor */
743f786bba4SBenjamin Tissoires 			int wide = (s->w > s->h);
744e9d0a26dSHungNien Chen 			int major = max(s->w, s->h);
745e9d0a26dSHungNien Chen 			int minor = min(s->w, s->h);
74600720277SWei-Ning Huang 			int orientation = wide;
74700720277SWei-Ning Huang 
74800720277SWei-Ning Huang 			if (s->has_azimuth)
74900720277SWei-Ning Huang 				orientation = s->a;
750e9d0a26dSHungNien Chen 
751e9d0a26dSHungNien Chen 			/*
752e9d0a26dSHungNien Chen 			 * divided by two to match visual scale of touch
753e9d0a26dSHungNien Chen 			 * for devices with this quirk
754e9d0a26dSHungNien Chen 			 */
755e9d0a26dSHungNien Chen 			if (td->mtclass.quirks & MT_QUIRK_TOUCH_SIZE_SCALING) {
756e9d0a26dSHungNien Chen 				major = major >> 1;
757e9d0a26dSHungNien Chen 				minor = minor >> 1;
758e9d0a26dSHungNien Chen 			}
759f786bba4SBenjamin Tissoires 
7605519cab4SBenjamin Tissoires 			input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x);
7615519cab4SBenjamin Tissoires 			input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y);
762349fd670SBenjamin Tissoires 			input_event(input, EV_ABS, ABS_MT_TOOL_X, s->cx);
763349fd670SBenjamin Tissoires 			input_event(input, EV_ABS, ABS_MT_TOOL_Y, s->cy);
7649b3bb9b8SBenjamin Tissoires 			input_event(input, EV_ABS, ABS_MT_DISTANCE,
7659b3bb9b8SBenjamin Tissoires 				!s->touch_state);
76600720277SWei-Ning Huang 			input_event(input, EV_ABS, ABS_MT_ORIENTATION,
76700720277SWei-Ning Huang 				orientation);
7685519cab4SBenjamin Tissoires 			input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
769f786bba4SBenjamin Tissoires 			input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
770f786bba4SBenjamin Tissoires 			input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
77196098274SBenjamin Tissoires 
77296098274SBenjamin Tissoires 			set_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags);
7732d93666eSBenjamin Tissoires 		}
7745519cab4SBenjamin Tissoires 	}
7755519cab4SBenjamin Tissoires 
7763e1b5015SHenrik Rydberg 	td->num_received++;
7773e1b5015SHenrik Rydberg }
7783e1b5015SHenrik Rydberg 
7793e1b5015SHenrik Rydberg /*
7803e1b5015SHenrik Rydberg  * this function is called when a whole packet has been received and processed,
7813e1b5015SHenrik Rydberg  * so that it can decide what to send to the input layer.
7823e1b5015SHenrik Rydberg  */
7833e1b5015SHenrik Rydberg static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
7843e1b5015SHenrik Rydberg {
785d9c57a70SBenjamin Tissoires 	if (td->mtclass.quirks & MT_QUIRK_WIN8_PTP_BUTTONS)
786127e71bdSHans de Goede 		input_event(input, EV_KEY, BTN_LEFT, td->left_button_state);
787127e71bdSHans de Goede 
78876f5902aSHenrik Rydberg 	input_mt_sync_frame(input);
78929cc309dSNicolas Boichat 	input_event(input, EV_MSC, MSC_TIMESTAMP, td->timestamp);
7905519cab4SBenjamin Tissoires 	input_sync(input);
7915519cab4SBenjamin Tissoires 	td->num_received = 0;
792127e71bdSHans de Goede 	td->left_button_state = 0;
79396098274SBenjamin Tissoires 	if (test_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags))
79496098274SBenjamin Tissoires 		set_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags);
79596098274SBenjamin Tissoires 	else
79696098274SBenjamin Tissoires 		clear_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags);
79796098274SBenjamin Tissoires 	clear_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags);
7985519cab4SBenjamin Tissoires }
7995519cab4SBenjamin Tissoires 
80029cc309dSNicolas Boichat static int mt_compute_timestamp(struct mt_device *td, struct hid_field *field,
80129cc309dSNicolas Boichat 		__s32 value)
80229cc309dSNicolas Boichat {
80329cc309dSNicolas Boichat 	long delta = value - td->dev_time;
80429cc309dSNicolas Boichat 	unsigned long jdelta = jiffies_to_usecs(jiffies - td->jiffies);
80529cc309dSNicolas Boichat 
80629cc309dSNicolas Boichat 	td->jiffies = jiffies;
80729cc309dSNicolas Boichat 	td->dev_time = value;
80829cc309dSNicolas Boichat 
80929cc309dSNicolas Boichat 	if (delta < 0)
81029cc309dSNicolas Boichat 		delta += field->logical_maximum;
81129cc309dSNicolas Boichat 
81229cc309dSNicolas Boichat 	/* HID_DG_SCANTIME is expressed in 100us, we want it in us. */
81329cc309dSNicolas Boichat 	delta *= 100;
81429cc309dSNicolas Boichat 
81529cc309dSNicolas Boichat 	if (jdelta > MAX_TIMESTAMP_INTERVAL)
81629cc309dSNicolas Boichat 		/* No data received for a while, resync the timestamp. */
81729cc309dSNicolas Boichat 		return 0;
81829cc309dSNicolas Boichat 	else
81929cc309dSNicolas Boichat 		return td->timestamp + delta;
82029cc309dSNicolas Boichat }
82129cc309dSNicolas Boichat 
822a69c5f8bSBenjamin Tissoires static int mt_touch_event(struct hid_device *hid, struct hid_field *field,
8235519cab4SBenjamin Tissoires 				struct hid_usage *usage, __s32 value)
8245519cab4SBenjamin Tissoires {
82555978fa9SBenjamin Tissoires 	/* we will handle the hidinput part later, now remains hiddev */
82655978fa9SBenjamin Tissoires 	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
82755978fa9SBenjamin Tissoires 		hid->hiddev_hid_event(hid, field, usage, value);
82855978fa9SBenjamin Tissoires 
82955978fa9SBenjamin Tissoires 	return 1;
83055978fa9SBenjamin Tissoires }
83155978fa9SBenjamin Tissoires 
83255978fa9SBenjamin Tissoires static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
83355746d28SHans de Goede 				struct hid_usage *usage, __s32 value,
83455746d28SHans de Goede 				bool first_packet)
83555978fa9SBenjamin Tissoires {
8365519cab4SBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hid);
837eec29e3dSBenjamin Tissoires 	__s32 quirks = td->mtclass.quirks;
8384c437555SBenjamin Tissoires 	struct input_dev *input = field->hidinput->input;
8395519cab4SBenjamin Tissoires 
8403e1b5015SHenrik Rydberg 	if (hid->claimed & HID_CLAIMED_INPUT) {
8415519cab4SBenjamin Tissoires 		switch (usage->hid) {
8425519cab4SBenjamin Tissoires 		case HID_DG_INRANGE:
84320b60e6dSBenjamin Tissoires 			if (quirks & MT_QUIRK_VALID_IS_INRANGE)
8442d93666eSBenjamin Tissoires 				td->curvalid = value;
8459b3bb9b8SBenjamin Tissoires 			if (quirks & MT_QUIRK_HOVERING)
8469b3bb9b8SBenjamin Tissoires 				td->curdata.inrange_state = value;
8475519cab4SBenjamin Tissoires 			break;
8485519cab4SBenjamin Tissoires 		case HID_DG_TIPSWITCH:
8492d93666eSBenjamin Tissoires 			if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
8505519cab4SBenjamin Tissoires 				td->curvalid = value;
8515519cab4SBenjamin Tissoires 			td->curdata.touch_state = value;
8525519cab4SBenjamin Tissoires 			break;
8535519cab4SBenjamin Tissoires 		case HID_DG_CONFIDENCE:
8546dd2e27aSAllen Hung 			if (quirks & MT_QUIRK_CONFIDENCE)
8556dd2e27aSAllen Hung 				td->curdata.confidence_state = value;
8562d93666eSBenjamin Tissoires 			if (quirks & MT_QUIRK_VALID_IS_CONFIDENCE)
8572d93666eSBenjamin Tissoires 				td->curvalid = value;
8585519cab4SBenjamin Tissoires 			break;
8595519cab4SBenjamin Tissoires 		case HID_DG_CONTACTID:
8605519cab4SBenjamin Tissoires 			td->curdata.contactid = value;
8615519cab4SBenjamin Tissoires 			break;
8625519cab4SBenjamin Tissoires 		case HID_DG_TIPPRESSURE:
8635519cab4SBenjamin Tissoires 			td->curdata.p = value;
8645519cab4SBenjamin Tissoires 			break;
8655519cab4SBenjamin Tissoires 		case HID_GD_X:
866349fd670SBenjamin Tissoires 			if (usage->code == ABS_MT_TOOL_X)
867349fd670SBenjamin Tissoires 				td->curdata.cx = value;
868349fd670SBenjamin Tissoires 			else
8695519cab4SBenjamin Tissoires 				td->curdata.x = value;
8705519cab4SBenjamin Tissoires 			break;
8715519cab4SBenjamin Tissoires 		case HID_GD_Y:
872349fd670SBenjamin Tissoires 			if (usage->code == ABS_MT_TOOL_Y)
873349fd670SBenjamin Tissoires 				td->curdata.cy = value;
874349fd670SBenjamin Tissoires 			else
8755519cab4SBenjamin Tissoires 				td->curdata.y = value;
8765519cab4SBenjamin Tissoires 			break;
8775519cab4SBenjamin Tissoires 		case HID_DG_WIDTH:
8785519cab4SBenjamin Tissoires 			td->curdata.w = value;
8795519cab4SBenjamin Tissoires 			break;
8805519cab4SBenjamin Tissoires 		case HID_DG_HEIGHT:
8815519cab4SBenjamin Tissoires 			td->curdata.h = value;
8825519cab4SBenjamin Tissoires 			break;
88329cc309dSNicolas Boichat 		case HID_DG_SCANTIME:
88429cc309dSNicolas Boichat 			td->timestamp = mt_compute_timestamp(td, field, value);
88529cc309dSNicolas Boichat 			break;
8865519cab4SBenjamin Tissoires 		case HID_DG_CONTACTCOUNT:
8875519cab4SBenjamin Tissoires 			break;
88800720277SWei-Ning Huang 		case HID_DG_AZIMUTH:
88900720277SWei-Ning Huang 			/*
89000720277SWei-Ning Huang 			 * Azimuth is counter-clockwise and ranges from [0, MAX)
89100720277SWei-Ning Huang 			 * (a full revolution). Convert it to clockwise ranging
89200720277SWei-Ning Huang 			 * [-MAX/2, MAX/2].
89300720277SWei-Ning Huang 			 *
89400720277SWei-Ning Huang 			 * Note that ABS_MT_ORIENTATION require us to report
89500720277SWei-Ning Huang 			 * the limit of [-MAX/4, MAX/4], but the value can go
89600720277SWei-Ning Huang 			 * out of range to [-MAX/2, MAX/2] to report an upside
89700720277SWei-Ning Huang 			 * down ellipsis.
89800720277SWei-Ning Huang 			 */
89900720277SWei-Ning Huang 			if (value > field->logical_maximum / 2)
90000720277SWei-Ning Huang 				value -= field->logical_maximum;
90100720277SWei-Ning Huang 			td->curdata.a = -value;
90200720277SWei-Ning Huang 			td->curdata.has_azimuth = true;
90300720277SWei-Ning Huang 			break;
904c2ef8f21SBenjamin Tissoires 		case HID_DG_TOUCH:
905c2ef8f21SBenjamin Tissoires 			/* do nothing */
906c2ef8f21SBenjamin Tissoires 			break;
9075519cab4SBenjamin Tissoires 
9085519cab4SBenjamin Tissoires 		default:
90955746d28SHans de Goede 			/*
91055746d28SHans de Goede 			 * For Win8 PTP touchpads we should only look at
91155746d28SHans de Goede 			 * non finger/touch events in the first_packet of
91255746d28SHans de Goede 			 * a (possible) multi-packet frame.
91355746d28SHans de Goede 			 */
914d9c57a70SBenjamin Tissoires 			if ((quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
91555746d28SHans de Goede 			    !first_packet)
91655746d28SHans de Goede 				return;
91755746d28SHans de Goede 
918127e71bdSHans de Goede 			/*
919127e71bdSHans de Goede 			 * For Win8 PTP touchpads we map both the clickpad click
920127e71bdSHans de Goede 			 * and any "external" left buttons to BTN_LEFT if a
921127e71bdSHans de Goede 			 * device claims to have both we need to report 1 for
922127e71bdSHans de Goede 			 * BTN_LEFT if either is pressed, so we or all values
923127e71bdSHans de Goede 			 * together and report the result in mt_sync_frame().
924127e71bdSHans de Goede 			 */
925d9c57a70SBenjamin Tissoires 			if ((quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
926127e71bdSHans de Goede 			    usage->type == EV_KEY && usage->code == BTN_LEFT) {
927127e71bdSHans de Goede 				td->left_button_state |= value;
928127e71bdSHans de Goede 				return;
929127e71bdSHans de Goede 			}
930127e71bdSHans de Goede 
9314c437555SBenjamin Tissoires 			if (usage->type)
9324c437555SBenjamin Tissoires 				input_event(input, usage->type, usage->code,
9334c437555SBenjamin Tissoires 						value);
93455978fa9SBenjamin Tissoires 			return;
9355519cab4SBenjamin Tissoires 		}
9365519cab4SBenjamin Tissoires 
93754f4c0c3SBenjamin Tissoires 		if (usage->usage_index + 1 == field->report_count) {
93854f4c0c3SBenjamin Tissoires 			/* we only take into account the last report. */
9392258e863SDenis Kovalev 			if (usage->hid == td->last_slot_field)
9403e1b5015SHenrik Rydberg 				mt_complete_slot(td, field->hidinput->input);
94154f4c0c3SBenjamin Tissoires 		}
9425519cab4SBenjamin Tissoires 
9432d93666eSBenjamin Tissoires 	}
94455978fa9SBenjamin Tissoires }
9452d93666eSBenjamin Tissoires 
946a69c5f8bSBenjamin Tissoires static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
94755978fa9SBenjamin Tissoires {
94855978fa9SBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hid);
94955978fa9SBenjamin Tissoires 	struct hid_field *field;
95055746d28SHans de Goede 	bool first_packet;
95155978fa9SBenjamin Tissoires 	unsigned count;
952af8dc4d0SHans de Goede 	int r, n, scantime = 0;
9535519cab4SBenjamin Tissoires 
9544f4001bcSBenjamin Tissoires 	/* sticky fingers release in progress, abort */
9554f4001bcSBenjamin Tissoires 	if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
9564f4001bcSBenjamin Tissoires 		return;
9574f4001bcSBenjamin Tissoires 
958c2517f62SBenjamin Tissoires 	/*
959c2517f62SBenjamin Tissoires 	 * Includes multi-packet support where subsequent
960c2517f62SBenjamin Tissoires 	 * packets are sent with zero contactcount.
961c2517f62SBenjamin Tissoires 	 */
962af8dc4d0SHans de Goede 	if (td->scantime_index >= 0) {
963af8dc4d0SHans de Goede 		field = report->field[td->scantime_index];
964af8dc4d0SHans de Goede 		scantime = field->value[td->scantime_val_index];
965af8dc4d0SHans de Goede 	}
9667e3cc447SBenjamin Tissoires 	if (td->cc_index >= 0) {
9677e3cc447SBenjamin Tissoires 		struct hid_field *field = report->field[td->cc_index];
9687e3cc447SBenjamin Tissoires 		int value = field->value[td->cc_value_index];
969af8dc4d0SHans de Goede 
970af8dc4d0SHans de Goede 		/*
971af8dc4d0SHans de Goede 		 * For Win8 PTPs the first packet (td->num_received == 0) may
972af8dc4d0SHans de Goede 		 * have a contactcount of 0 if there only is a button event.
973af8dc4d0SHans de Goede 		 * We double check that this is not a continuation packet
974af8dc4d0SHans de Goede 		 * of a possible multi-packet frame be checking that the
975af8dc4d0SHans de Goede 		 * timestamp has changed.
976af8dc4d0SHans de Goede 		 */
977d9c57a70SBenjamin Tissoires 		if ((td->mtclass.quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
978af8dc4d0SHans de Goede 		    td->num_received == 0 && td->prev_scantime != scantime)
979af8dc4d0SHans de Goede 			td->num_expected = value;
980af8dc4d0SHans de Goede 		/* A non 0 contact count always indicates a first packet */
981af8dc4d0SHans de Goede 		else if (value)
9827e3cc447SBenjamin Tissoires 			td->num_expected = value;
9837e3cc447SBenjamin Tissoires 	}
984af8dc4d0SHans de Goede 	td->prev_scantime = scantime;
985c2517f62SBenjamin Tissoires 
98655746d28SHans de Goede 	first_packet = td->num_received == 0;
98755978fa9SBenjamin Tissoires 	for (r = 0; r < report->maxfield; r++) {
98855978fa9SBenjamin Tissoires 		field = report->field[r];
98955978fa9SBenjamin Tissoires 		count = field->report_count;
99055978fa9SBenjamin Tissoires 
99155978fa9SBenjamin Tissoires 		if (!(HID_MAIN_ITEM_VARIABLE & field->flags))
99255978fa9SBenjamin Tissoires 			continue;
99355978fa9SBenjamin Tissoires 
99455978fa9SBenjamin Tissoires 		for (n = 0; n < count; n++)
99555978fa9SBenjamin Tissoires 			mt_process_mt_event(hid, field, &field->usage[n],
99655746d28SHans de Goede 					    field->value[n], first_packet);
99755978fa9SBenjamin Tissoires 	}
9985b62efd8SBenjamin Tissoires 
9995b62efd8SBenjamin Tissoires 	if (td->num_received >= td->num_expected)
10005b62efd8SBenjamin Tissoires 		mt_sync_frame(td, report->field[0]->hidinput->input);
10014f4001bcSBenjamin Tissoires 
10024f4001bcSBenjamin Tissoires 	/*
10034f4001bcSBenjamin Tissoires 	 * Windows 8 specs says 2 things:
10044f4001bcSBenjamin Tissoires 	 * - once a contact has been reported, it has to be reported in each
10054f4001bcSBenjamin Tissoires 	 *   subsequent report
10064f4001bcSBenjamin Tissoires 	 * - the report rate when fingers are present has to be at least
10074f4001bcSBenjamin Tissoires 	 *   the refresh rate of the screen, 60 or 120 Hz
10084f4001bcSBenjamin Tissoires 	 *
10094f4001bcSBenjamin Tissoires 	 * I interprete this that the specification forces a report rate of
10104f4001bcSBenjamin Tissoires 	 * at least 60 Hz for a touchscreen to be certified.
10114f4001bcSBenjamin Tissoires 	 * Which means that if we do not get a report whithin 16 ms, either
10124f4001bcSBenjamin Tissoires 	 * something wrong happens, either the touchscreen forgets to send
10134f4001bcSBenjamin Tissoires 	 * a release. Taking a reasonable margin allows to remove issues
10144f4001bcSBenjamin Tissoires 	 * with USB communication or the load of the machine.
10154f4001bcSBenjamin Tissoires 	 *
10164f4001bcSBenjamin Tissoires 	 * Given that Win 8 devices are forced to send a release, this will
10174f4001bcSBenjamin Tissoires 	 * only affect laggish machines and the ones that have a firmware
10184f4001bcSBenjamin Tissoires 	 * defect.
10194f4001bcSBenjamin Tissoires 	 */
102096098274SBenjamin Tissoires 	if (td->mtclass.quirks & MT_QUIRK_STICKY_FINGERS) {
102196098274SBenjamin Tissoires 		if (test_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags))
102296098274SBenjamin Tissoires 			mod_timer(&td->release_timer,
102396098274SBenjamin Tissoires 				  jiffies + msecs_to_jiffies(100));
102496098274SBenjamin Tissoires 		else
102596098274SBenjamin Tissoires 			del_timer(&td->release_timer);
102696098274SBenjamin Tissoires 	}
10274f4001bcSBenjamin Tissoires 
10284f4001bcSBenjamin Tissoires 	clear_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags);
10295519cab4SBenjamin Tissoires }
10305519cab4SBenjamin Tissoires 
1031b2c68a2fSDmitry Torokhov static int mt_touch_input_configured(struct hid_device *hdev,
1032a69c5f8bSBenjamin Tissoires 					struct hid_input *hi)
1033a69c5f8bSBenjamin Tissoires {
1034a69c5f8bSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
1035a69c5f8bSBenjamin Tissoires 	struct mt_class *cls = &td->mtclass;
1036a69c5f8bSBenjamin Tissoires 	struct input_dev *input = hi->input;
1037b2c68a2fSDmitry Torokhov 	int ret;
1038a69c5f8bSBenjamin Tissoires 
1039a69c5f8bSBenjamin Tissoires 	if (!td->maxcontacts)
1040a69c5f8bSBenjamin Tissoires 		td->maxcontacts = MT_DEFAULT_MAXCONTACT;
1041a69c5f8bSBenjamin Tissoires 
1042a69c5f8bSBenjamin Tissoires 	mt_post_parse(td);
1043a69c5f8bSBenjamin Tissoires 	if (td->serial_maybe)
1044a69c5f8bSBenjamin Tissoires 		mt_post_parse_default_settings(td);
1045a69c5f8bSBenjamin Tissoires 
1046a69c5f8bSBenjamin Tissoires 	if (cls->is_indirect)
1047a69c5f8bSBenjamin Tissoires 		td->mt_flags |= INPUT_MT_POINTER;
1048a69c5f8bSBenjamin Tissoires 
1049a69c5f8bSBenjamin Tissoires 	if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
1050a69c5f8bSBenjamin Tissoires 		td->mt_flags |= INPUT_MT_DROP_UNUSED;
1051a69c5f8bSBenjamin Tissoires 
1052015fdaa9SBenjamin Tissoires 	/* check for clickpads */
1053015fdaa9SBenjamin Tissoires 	if ((td->mt_flags & INPUT_MT_POINTER) && (td->buttons_count == 1))
10542c6e0277SSeth Forshee 		td->is_buttonpad = true;
10552c6e0277SSeth Forshee 
10562c6e0277SSeth Forshee 	if (td->is_buttonpad)
1057015fdaa9SBenjamin Tissoires 		__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
1058015fdaa9SBenjamin Tissoires 
1059b2c68a2fSDmitry Torokhov 	ret = input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
1060b2c68a2fSDmitry Torokhov 	if (ret)
1061b2c68a2fSDmitry Torokhov 		return ret;
1062a69c5f8bSBenjamin Tissoires 
1063a69c5f8bSBenjamin Tissoires 	td->mt_flags = 0;
1064b2c68a2fSDmitry Torokhov 	return 0;
1065a69c5f8bSBenjamin Tissoires }
1066a69c5f8bSBenjamin Tissoires 
1067957b8dffSJoão Paulo Rechi Vita #define mt_map_key_clear(c)	hid_map_usage_clear(hi, usage, bit, \
1068957b8dffSJoão Paulo Rechi Vita 						    max, EV_KEY, (c))
1069a69c5f8bSBenjamin Tissoires static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
1070a69c5f8bSBenjamin Tissoires 		struct hid_field *field, struct hid_usage *usage,
1071a69c5f8bSBenjamin Tissoires 		unsigned long **bit, int *max)
1072a69c5f8bSBenjamin Tissoires {
10736aef704eSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
10746aef704eSBenjamin Tissoires 
10756aef704eSBenjamin Tissoires 	/*
10766aef704eSBenjamin Tissoires 	 * If mtclass.export_all_inputs is not set, only map fields from
10776aef704eSBenjamin Tissoires 	 * TouchScreen or TouchPad collections. We need to ignore fields
10786aef704eSBenjamin Tissoires 	 * that belong to other collections such as Mouse that might have
10796aef704eSBenjamin Tissoires 	 * the same GenericDesktop usages.
10806aef704eSBenjamin Tissoires 	 */
10816aef704eSBenjamin Tissoires 	if (!td->mtclass.export_all_inputs &&
10826aef704eSBenjamin Tissoires 	    field->application != HID_DG_TOUCHSCREEN &&
1083fa11aa72SBenjamin Tissoires 	    field->application != HID_DG_PEN &&
10848fe89ef0SBenjamin Tissoires 	    field->application != HID_DG_TOUCHPAD &&
10858fe89ef0SBenjamin Tissoires 	    field->application != HID_GD_KEYBOARD &&
1086e57f4e67SHans de Goede 	    field->application != HID_GD_SYSTEM_CONTROL &&
10871fbf74efSJoão Paulo Rechi Vita 	    field->application != HID_CP_CONSUMER_CONTROL &&
1088957b8dffSJoão Paulo Rechi Vita 	    field->application != HID_GD_WIRELESS_RADIO_CTLS &&
1089957b8dffSJoão Paulo Rechi Vita 	    !(field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS &&
1090957b8dffSJoão Paulo Rechi Vita 	      td->mtclass.quirks & MT_QUIRK_ASUS_CUSTOM_UP))
10916f492f28SBenjamin Tissoires 		return -1;
1092a69c5f8bSBenjamin Tissoires 
10936aef704eSBenjamin Tissoires 	/*
1094957b8dffSJoão Paulo Rechi Vita 	 * Some Asus keyboard+touchpad devices have the hotkeys defined in the
1095957b8dffSJoão Paulo Rechi Vita 	 * touchpad report descriptor. We need to treat these as an array to
1096957b8dffSJoão Paulo Rechi Vita 	 * map usages to input keys.
1097957b8dffSJoão Paulo Rechi Vita 	 */
109839bbf402SJiri Kosina 	if (field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS &&
1099957b8dffSJoão Paulo Rechi Vita 	    td->mtclass.quirks & MT_QUIRK_ASUS_CUSTOM_UP &&
1100957b8dffSJoão Paulo Rechi Vita 	    (usage->hid & HID_USAGE_PAGE) == HID_UP_CUSTOM) {
1101957b8dffSJoão Paulo Rechi Vita 		set_bit(EV_REP, hi->input->evbit);
1102957b8dffSJoão Paulo Rechi Vita 		if (field->flags & HID_MAIN_ITEM_VARIABLE)
1103957b8dffSJoão Paulo Rechi Vita 			field->flags &= ~HID_MAIN_ITEM_VARIABLE;
1104957b8dffSJoão Paulo Rechi Vita 		switch (usage->hid & HID_USAGE) {
1105957b8dffSJoão Paulo Rechi Vita 		case 0x10: mt_map_key_clear(KEY_BRIGHTNESSDOWN);	break;
1106957b8dffSJoão Paulo Rechi Vita 		case 0x20: mt_map_key_clear(KEY_BRIGHTNESSUP);		break;
1107957b8dffSJoão Paulo Rechi Vita 		case 0x35: mt_map_key_clear(KEY_DISPLAY_OFF);		break;
1108957b8dffSJoão Paulo Rechi Vita 		case 0x6b: mt_map_key_clear(KEY_F21);			break;
1109957b8dffSJoão Paulo Rechi Vita 		case 0x6c: mt_map_key_clear(KEY_SLEEP);			break;
1110957b8dffSJoão Paulo Rechi Vita 		default:
1111957b8dffSJoão Paulo Rechi Vita 			return -1;
1112957b8dffSJoão Paulo Rechi Vita 		}
1113957b8dffSJoão Paulo Rechi Vita 		return 1;
1114957b8dffSJoão Paulo Rechi Vita 	}
1115957b8dffSJoão Paulo Rechi Vita 
1116957b8dffSJoão Paulo Rechi Vita 	/*
11176aef704eSBenjamin Tissoires 	 * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
11186aef704eSBenjamin Tissoires 	 * for the stylus.
11191cc1cc92SBrent Adam 	 * The check for mt_report_id ensures we don't process
11201cc1cc92SBrent Adam 	 * HID_DG_CONTACTCOUNT from the pen report as it is outside the physical
11211cc1cc92SBrent Adam 	 * collection, but within the report ID.
11226aef704eSBenjamin Tissoires 	 */
1123a69c5f8bSBenjamin Tissoires 	if (field->physical == HID_DG_STYLUS)
1124e55f6200SBenjamin Tissoires 		return 0;
11251cc1cc92SBrent Adam 	else if ((field->physical == 0) &&
11261cc1cc92SBrent Adam 		 (field->report->id != td->mt_report_id) &&
11271cc1cc92SBrent Adam 		 (td->mt_report_id != -1))
11281cc1cc92SBrent Adam 		return 0;
1129a69c5f8bSBenjamin Tissoires 
11306aef704eSBenjamin Tissoires 	if (field->application == HID_DG_TOUCHSCREEN ||
11316aef704eSBenjamin Tissoires 	    field->application == HID_DG_TOUCHPAD)
1132a69c5f8bSBenjamin Tissoires 		return mt_touch_input_mapping(hdev, hi, field, usage, bit, max);
11336aef704eSBenjamin Tissoires 
11346aef704eSBenjamin Tissoires 	/* let hid-core decide for the others */
11356aef704eSBenjamin Tissoires 	return 0;
1136a69c5f8bSBenjamin Tissoires }
1137a69c5f8bSBenjamin Tissoires 
1138a69c5f8bSBenjamin Tissoires static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
1139a69c5f8bSBenjamin Tissoires 		struct hid_field *field, struct hid_usage *usage,
1140a69c5f8bSBenjamin Tissoires 		unsigned long **bit, int *max)
1141a69c5f8bSBenjamin Tissoires {
11426aef704eSBenjamin Tissoires 	/*
11436aef704eSBenjamin Tissoires 	 * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
11446aef704eSBenjamin Tissoires 	 * for the stylus.
11456aef704eSBenjamin Tissoires 	 */
1146fa11aa72SBenjamin Tissoires 	if (field->physical == HID_DG_STYLUS)
1147e55f6200SBenjamin Tissoires 		return 0;
1148fa11aa72SBenjamin Tissoires 
11496aef704eSBenjamin Tissoires 	if (field->application == HID_DG_TOUCHSCREEN ||
11504cf56a89SDmitry Torokhov 	    field->application == HID_DG_TOUCHPAD) {
11514cf56a89SDmitry Torokhov 		/* We own these mappings, tell hid-input to ignore them */
11524cf56a89SDmitry Torokhov 		return -1;
11534cf56a89SDmitry Torokhov 	}
11546aef704eSBenjamin Tissoires 
11556aef704eSBenjamin Tissoires 	/* let hid-core decide for the others */
11566aef704eSBenjamin Tissoires 	return 0;
1157a69c5f8bSBenjamin Tissoires }
1158a69c5f8bSBenjamin Tissoires 
1159a69c5f8bSBenjamin Tissoires static int mt_event(struct hid_device *hid, struct hid_field *field,
1160a69c5f8bSBenjamin Tissoires 				struct hid_usage *usage, __s32 value)
1161a69c5f8bSBenjamin Tissoires {
1162a69c5f8bSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hid);
1163a69c5f8bSBenjamin Tissoires 
1164a69c5f8bSBenjamin Tissoires 	if (field->report->id == td->mt_report_id)
1165a69c5f8bSBenjamin Tissoires 		return mt_touch_event(hid, field, usage, value);
1166a69c5f8bSBenjamin Tissoires 
1167e55f6200SBenjamin Tissoires 	return 0;
1168a69c5f8bSBenjamin Tissoires }
1169a69c5f8bSBenjamin Tissoires 
1170a69c5f8bSBenjamin Tissoires static void mt_report(struct hid_device *hid, struct hid_report *report)
1171a69c5f8bSBenjamin Tissoires {
1172a69c5f8bSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hid);
1173e55f6200SBenjamin Tissoires 	struct hid_field *field = report->field[0];
1174a69c5f8bSBenjamin Tissoires 
1175a69c5f8bSBenjamin Tissoires 	if (!(hid->claimed & HID_CLAIMED_INPUT))
1176a69c5f8bSBenjamin Tissoires 		return;
1177a69c5f8bSBenjamin Tissoires 
1178a69c5f8bSBenjamin Tissoires 	if (report->id == td->mt_report_id)
1179e55f6200SBenjamin Tissoires 		return mt_touch_report(hid, report);
1180fa11aa72SBenjamin Tissoires 
1181e55f6200SBenjamin Tissoires 	if (field && field->hidinput && field->hidinput->input)
1182e55f6200SBenjamin Tissoires 		input_sync(field->hidinput->input);
11835519cab4SBenjamin Tissoires }
11845519cab4SBenjamin Tissoires 
11855519cab4SBenjamin Tissoires static void mt_set_input_mode(struct hid_device *hdev)
11865519cab4SBenjamin Tissoires {
11875519cab4SBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
11885519cab4SBenjamin Tissoires 	struct hid_report *r;
11895519cab4SBenjamin Tissoires 	struct hid_report_enum *re;
1190da10bc25SMathieu Magnaudet 	struct mt_class *cls = &td->mtclass;
1191da10bc25SMathieu Magnaudet 	char *buf;
1192da10bc25SMathieu Magnaudet 	int report_len;
11935519cab4SBenjamin Tissoires 
11945519cab4SBenjamin Tissoires 	if (td->inputmode < 0)
11955519cab4SBenjamin Tissoires 		return;
11965519cab4SBenjamin Tissoires 
11975519cab4SBenjamin Tissoires 	re = &(hdev->report_enum[HID_FEATURE_REPORT]);
11985519cab4SBenjamin Tissoires 	r = re->report_id_hash[td->inputmode];
11995519cab4SBenjamin Tissoires 	if (r) {
1200da10bc25SMathieu Magnaudet 		if (cls->quirks & MT_QUIRK_FORCE_GET_FEATURE) {
1201dabb05c6SMathieu Magnaudet 			report_len = hid_report_len(r);
1202da10bc25SMathieu Magnaudet 			buf = hid_alloc_report_buf(r, GFP_KERNEL);
1203da10bc25SMathieu Magnaudet 			if (!buf) {
1204da10bc25SMathieu Magnaudet 				hid_err(hdev, "failed to allocate buffer for report\n");
1205da10bc25SMathieu Magnaudet 				return;
1206da10bc25SMathieu Magnaudet 			}
1207da10bc25SMathieu Magnaudet 			hid_hw_raw_request(hdev, r->id, buf, report_len,
1208da10bc25SMathieu Magnaudet 					   HID_FEATURE_REPORT,
1209da10bc25SMathieu Magnaudet 					   HID_REQ_GET_REPORT);
1210da10bc25SMathieu Magnaudet 			kfree(buf);
1211da10bc25SMathieu Magnaudet 		}
12129abebedbSAndrew Duggan 		r->field[0]->value[td->inputmode_index] = td->inputmode_value;
1213d8814272SBenjamin Tissoires 		hid_hw_request(hdev, r, HID_REQ_SET_REPORT);
12145519cab4SBenjamin Tissoires 	}
12155519cab4SBenjamin Tissoires }
12165519cab4SBenjamin Tissoires 
121731ae9bddSBenjamin Tissoires static void mt_set_maxcontacts(struct hid_device *hdev)
121831ae9bddSBenjamin Tissoires {
121931ae9bddSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
122031ae9bddSBenjamin Tissoires 	struct hid_report *r;
122131ae9bddSBenjamin Tissoires 	struct hid_report_enum *re;
122231ae9bddSBenjamin Tissoires 	int fieldmax, max;
122331ae9bddSBenjamin Tissoires 
122431ae9bddSBenjamin Tissoires 	if (td->maxcontact_report_id < 0)
122531ae9bddSBenjamin Tissoires 		return;
122631ae9bddSBenjamin Tissoires 
122731ae9bddSBenjamin Tissoires 	if (!td->mtclass.maxcontacts)
122831ae9bddSBenjamin Tissoires 		return;
122931ae9bddSBenjamin Tissoires 
123031ae9bddSBenjamin Tissoires 	re = &hdev->report_enum[HID_FEATURE_REPORT];
123131ae9bddSBenjamin Tissoires 	r = re->report_id_hash[td->maxcontact_report_id];
123231ae9bddSBenjamin Tissoires 	if (r) {
123331ae9bddSBenjamin Tissoires 		max = td->mtclass.maxcontacts;
123431ae9bddSBenjamin Tissoires 		fieldmax = r->field[0]->logical_maximum;
123531ae9bddSBenjamin Tissoires 		max = min(fieldmax, max);
123631ae9bddSBenjamin Tissoires 		if (r->field[0]->value[0] != max) {
123731ae9bddSBenjamin Tissoires 			r->field[0]->value[0] = max;
1238d8814272SBenjamin Tissoires 			hid_hw_request(hdev, r, HID_REQ_SET_REPORT);
123931ae9bddSBenjamin Tissoires 		}
124031ae9bddSBenjamin Tissoires 	}
124131ae9bddSBenjamin Tissoires }
124231ae9bddSBenjamin Tissoires 
12434fa3a583SHenrik Rydberg static void mt_post_parse_default_settings(struct mt_device *td)
12444fa3a583SHenrik Rydberg {
12454fa3a583SHenrik Rydberg 	__s32 quirks = td->mtclass.quirks;
12464fa3a583SHenrik Rydberg 
12474fa3a583SHenrik Rydberg 	/* unknown serial device needs special quirks */
12484fa3a583SHenrik Rydberg 	if (td->touches_by_report == 1) {
12494fa3a583SHenrik Rydberg 		quirks |= MT_QUIRK_ALWAYS_VALID;
12504fa3a583SHenrik Rydberg 		quirks &= ~MT_QUIRK_NOT_SEEN_MEANS_UP;
12514fa3a583SHenrik Rydberg 		quirks &= ~MT_QUIRK_VALID_IS_INRANGE;
12524fa3a583SHenrik Rydberg 		quirks &= ~MT_QUIRK_VALID_IS_CONFIDENCE;
1253e0bb8f9aSBenjamin Tissoires 		quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
12544fa3a583SHenrik Rydberg 	}
12554fa3a583SHenrik Rydberg 
12564fa3a583SHenrik Rydberg 	td->mtclass.quirks = quirks;
12574fa3a583SHenrik Rydberg }
12584fa3a583SHenrik Rydberg 
12593ac36d15SBenjamin Tissoires static void mt_post_parse(struct mt_device *td)
12603ac36d15SBenjamin Tissoires {
12613ac36d15SBenjamin Tissoires 	struct mt_fields *f = td->fields;
1262c2517f62SBenjamin Tissoires 	struct mt_class *cls = &td->mtclass;
12633ac36d15SBenjamin Tissoires 
12643ac36d15SBenjamin Tissoires 	if (td->touches_by_report > 0) {
12653ac36d15SBenjamin Tissoires 		int field_count_per_touch = f->length / td->touches_by_report;
12663ac36d15SBenjamin Tissoires 		td->last_slot_field = f->usages[field_count_per_touch - 1];
12673ac36d15SBenjamin Tissoires 	}
1268c2517f62SBenjamin Tissoires 
12697e3cc447SBenjamin Tissoires 	if (td->cc_index < 0)
1270c2517f62SBenjamin Tissoires 		cls->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
12713ac36d15SBenjamin Tissoires }
12723ac36d15SBenjamin Tissoires 
1273b2c68a2fSDmitry Torokhov static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
127476f5902aSHenrik Rydberg {
127576f5902aSHenrik Rydberg 	struct mt_device *td = hid_get_drvdata(hdev);
1276c08d46aaSBenjamin Tissoires 	char *name;
1277c08d46aaSBenjamin Tissoires 	const char *suffix = NULL;
12786aef704eSBenjamin Tissoires 	struct hid_field *field = hi->report->field[0];
1279b2c68a2fSDmitry Torokhov 	int ret;
128076f5902aSHenrik Rydberg 
1281b2c68a2fSDmitry Torokhov 	if (hi->report->id == td->mt_report_id) {
1282b2c68a2fSDmitry Torokhov 		ret = mt_touch_input_configured(hdev, hi);
1283b2c68a2fSDmitry Torokhov 		if (ret)
1284b2c68a2fSDmitry Torokhov 			return ret;
1285b2c68a2fSDmitry Torokhov 	}
128676f5902aSHenrik Rydberg 
12876aef704eSBenjamin Tissoires 	/*
12886aef704eSBenjamin Tissoires 	 * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
12896aef704eSBenjamin Tissoires 	 * for the stylus. Check this first, and then rely on the application
12906aef704eSBenjamin Tissoires 	 * field.
12916aef704eSBenjamin Tissoires 	 */
1292c08d46aaSBenjamin Tissoires 	if (hi->report->field[0]->physical == HID_DG_STYLUS) {
1293c08d46aaSBenjamin Tissoires 		suffix = "Pen";
1294e55f6200SBenjamin Tissoires 		/* force BTN_STYLUS to allow tablet matching in udev */
1295e55f6200SBenjamin Tissoires 		__set_bit(BTN_STYLUS, hi->input->keybit);
12966aef704eSBenjamin Tissoires 	} else {
12976aef704eSBenjamin Tissoires 		switch (field->application) {
12986aef704eSBenjamin Tissoires 		case HID_GD_KEYBOARD:
12996aef704eSBenjamin Tissoires 			suffix = "Keyboard";
13006aef704eSBenjamin Tissoires 			break;
13016aef704eSBenjamin Tissoires 		case HID_GD_KEYPAD:
13026aef704eSBenjamin Tissoires 			suffix = "Keypad";
13036aef704eSBenjamin Tissoires 			break;
13046aef704eSBenjamin Tissoires 		case HID_GD_MOUSE:
13056aef704eSBenjamin Tissoires 			suffix = "Mouse";
13066aef704eSBenjamin Tissoires 			break;
13076aef704eSBenjamin Tissoires 		case HID_DG_STYLUS:
13086aef704eSBenjamin Tissoires 			suffix = "Pen";
13096aef704eSBenjamin Tissoires 			/* force BTN_STYLUS to allow tablet matching in udev */
13106aef704eSBenjamin Tissoires 			__set_bit(BTN_STYLUS, hi->input->keybit);
13116aef704eSBenjamin Tissoires 			break;
13126aef704eSBenjamin Tissoires 		case HID_DG_TOUCHSCREEN:
13136aef704eSBenjamin Tissoires 			/* we do not set suffix = "Touchscreen" */
13146aef704eSBenjamin Tissoires 			break;
1315dc425a1cSMika Westerberg 		case HID_DG_TOUCHPAD:
1316dc425a1cSMika Westerberg 			suffix = "Touchpad";
1317dc425a1cSMika Westerberg 			break;
13186aef704eSBenjamin Tissoires 		case HID_GD_SYSTEM_CONTROL:
13196aef704eSBenjamin Tissoires 			suffix = "System Control";
13206aef704eSBenjamin Tissoires 			break;
13216aef704eSBenjamin Tissoires 		case HID_CP_CONSUMER_CONTROL:
13226aef704eSBenjamin Tissoires 			suffix = "Consumer Control";
13236aef704eSBenjamin Tissoires 			break;
13241fbf74efSJoão Paulo Rechi Vita 		case HID_GD_WIRELESS_RADIO_CTLS:
13251fbf74efSJoão Paulo Rechi Vita 			suffix = "Wireless Radio Control";
13261fbf74efSJoão Paulo Rechi Vita 			break;
1327957b8dffSJoão Paulo Rechi Vita 		case HID_VD_ASUS_CUSTOM_MEDIA_KEYS:
1328957b8dffSJoão Paulo Rechi Vita 			suffix = "Custom Media Keys";
1329957b8dffSJoão Paulo Rechi Vita 			break;
13306aef704eSBenjamin Tissoires 		default:
13316aef704eSBenjamin Tissoires 			suffix = "UNKNOWN";
13326aef704eSBenjamin Tissoires 			break;
13336aef704eSBenjamin Tissoires 		}
133476f5902aSHenrik Rydberg 	}
133576f5902aSHenrik Rydberg 
1336c08d46aaSBenjamin Tissoires 	if (suffix) {
1337c08d46aaSBenjamin Tissoires 		name = devm_kzalloc(&hi->input->dev,
1338c08d46aaSBenjamin Tissoires 				    strlen(hdev->name) + strlen(suffix) + 2,
1339c08d46aaSBenjamin Tissoires 				    GFP_KERNEL);
1340c08d46aaSBenjamin Tissoires 		if (name) {
1341c08d46aaSBenjamin Tissoires 			sprintf(name, "%s %s", hdev->name, suffix);
1342c08d46aaSBenjamin Tissoires 			hi->input->name = name;
1343c08d46aaSBenjamin Tissoires 		}
1344c08d46aaSBenjamin Tissoires 	}
1345b2c68a2fSDmitry Torokhov 
1346b2c68a2fSDmitry Torokhov 	return 0;
1347c08d46aaSBenjamin Tissoires }
1348c08d46aaSBenjamin Tissoires 
1349f3287a99SBenjamin Tissoires static void mt_fix_const_field(struct hid_field *field, unsigned int usage)
1350f3287a99SBenjamin Tissoires {
1351f3287a99SBenjamin Tissoires 	if (field->usage[0].hid != usage ||
1352f3287a99SBenjamin Tissoires 	    !(field->flags & HID_MAIN_ITEM_CONSTANT))
1353f3287a99SBenjamin Tissoires 		return;
1354f3287a99SBenjamin Tissoires 
1355f3287a99SBenjamin Tissoires 	field->flags &= ~HID_MAIN_ITEM_CONSTANT;
1356f3287a99SBenjamin Tissoires 	field->flags |= HID_MAIN_ITEM_VARIABLE;
1357f3287a99SBenjamin Tissoires }
1358f3287a99SBenjamin Tissoires 
1359f3287a99SBenjamin Tissoires static void mt_fix_const_fields(struct hid_device *hdev, unsigned int usage)
1360f3287a99SBenjamin Tissoires {
1361f3287a99SBenjamin Tissoires 	struct hid_report *report;
1362f3287a99SBenjamin Tissoires 	int i;
1363f3287a99SBenjamin Tissoires 
1364f3287a99SBenjamin Tissoires 	list_for_each_entry(report,
1365f3287a99SBenjamin Tissoires 			    &hdev->report_enum[HID_INPUT_REPORT].report_list,
1366f3287a99SBenjamin Tissoires 			    list) {
1367f3287a99SBenjamin Tissoires 
1368f3287a99SBenjamin Tissoires 		if (!report->maxfield)
1369f3287a99SBenjamin Tissoires 			continue;
1370f3287a99SBenjamin Tissoires 
1371f3287a99SBenjamin Tissoires 		for (i = 0; i < report->maxfield; i++)
1372f3287a99SBenjamin Tissoires 			if (report->field[i]->maxusage >= 1)
1373f3287a99SBenjamin Tissoires 				mt_fix_const_field(report->field[i], usage);
1374f3287a99SBenjamin Tissoires 	}
1375f3287a99SBenjamin Tissoires }
1376f3287a99SBenjamin Tissoires 
13774f4001bcSBenjamin Tissoires static void mt_release_contacts(struct hid_device *hid)
13784f4001bcSBenjamin Tissoires {
13794f4001bcSBenjamin Tissoires 	struct hid_input *hidinput;
13804f4001bcSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hid);
13814f4001bcSBenjamin Tissoires 
13824f4001bcSBenjamin Tissoires 	list_for_each_entry(hidinput, &hid->inputs, list) {
13834f4001bcSBenjamin Tissoires 		struct input_dev *input_dev = hidinput->input;
13844f4001bcSBenjamin Tissoires 		struct input_mt *mt = input_dev->mt;
13854f4001bcSBenjamin Tissoires 		int i;
13864f4001bcSBenjamin Tissoires 
13874f4001bcSBenjamin Tissoires 		if (mt) {
13884f4001bcSBenjamin Tissoires 			for (i = 0; i < mt->num_slots; i++) {
13894f4001bcSBenjamin Tissoires 				input_mt_slot(input_dev, i);
13904f4001bcSBenjamin Tissoires 				input_mt_report_slot_state(input_dev,
13914f4001bcSBenjamin Tissoires 							   MT_TOOL_FINGER,
13924f4001bcSBenjamin Tissoires 							   false);
13934f4001bcSBenjamin Tissoires 			}
13944f4001bcSBenjamin Tissoires 			input_mt_sync_frame(input_dev);
13954f4001bcSBenjamin Tissoires 			input_sync(input_dev);
13964f4001bcSBenjamin Tissoires 		}
13974f4001bcSBenjamin Tissoires 	}
13984f4001bcSBenjamin Tissoires 
13994f4001bcSBenjamin Tissoires 	td->num_received = 0;
14004f4001bcSBenjamin Tissoires }
14014f4001bcSBenjamin Tissoires 
14020ee32774SKees Cook static void mt_expired_timeout(struct timer_list *t)
14034f4001bcSBenjamin Tissoires {
14040ee32774SKees Cook 	struct mt_device *td = from_timer(td, t, release_timer);
14050ee32774SKees Cook 	struct hid_device *hdev = td->hdev;
14064f4001bcSBenjamin Tissoires 
14074f4001bcSBenjamin Tissoires 	/*
14084f4001bcSBenjamin Tissoires 	 * An input report came in just before we release the sticky fingers,
14094f4001bcSBenjamin Tissoires 	 * it will take care of the sticky fingers.
14104f4001bcSBenjamin Tissoires 	 */
14114f4001bcSBenjamin Tissoires 	if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
14124f4001bcSBenjamin Tissoires 		return;
141396098274SBenjamin Tissoires 	if (test_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags))
14144f4001bcSBenjamin Tissoires 		mt_release_contacts(hdev);
14154f4001bcSBenjamin Tissoires 	clear_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags);
14164f4001bcSBenjamin Tissoires }
14174f4001bcSBenjamin Tissoires 
14185519cab4SBenjamin Tissoires static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
14195519cab4SBenjamin Tissoires {
14202d93666eSBenjamin Tissoires 	int ret, i;
14215519cab4SBenjamin Tissoires 	struct mt_device *td;
14222d93666eSBenjamin Tissoires 	struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
14232d93666eSBenjamin Tissoires 
14242d93666eSBenjamin Tissoires 	for (i = 0; mt_classes[i].name ; i++) {
14252d93666eSBenjamin Tissoires 		if (id->driver_data == mt_classes[i].name) {
14262d93666eSBenjamin Tissoires 			mtclass = &(mt_classes[i]);
14272d93666eSBenjamin Tissoires 			break;
14282d93666eSBenjamin Tissoires 		}
14292d93666eSBenjamin Tissoires 	}
14305519cab4SBenjamin Tissoires 
1431c08d46aaSBenjamin Tissoires 	td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL);
14325519cab4SBenjamin Tissoires 	if (!td) {
14335519cab4SBenjamin Tissoires 		dev_err(&hdev->dev, "cannot allocate multitouch data\n");
14345519cab4SBenjamin Tissoires 		return -ENOMEM;
14355519cab4SBenjamin Tissoires 	}
14360ee32774SKees Cook 	td->hdev = hdev;
1437eec29e3dSBenjamin Tissoires 	td->mtclass = *mtclass;
14385519cab4SBenjamin Tissoires 	td->inputmode = -1;
143931ae9bddSBenjamin Tissoires 	td->maxcontact_report_id = -1;
14409abebedbSAndrew Duggan 	td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
14417e3cc447SBenjamin Tissoires 	td->cc_index = -1;
1442af8dc4d0SHans de Goede 	td->scantime_index = -1;
1443fa11aa72SBenjamin Tissoires 	td->mt_report_id = -1;
14445519cab4SBenjamin Tissoires 	hid_set_drvdata(hdev, td);
14455519cab4SBenjamin Tissoires 
1446c08d46aaSBenjamin Tissoires 	td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields),
1447c08d46aaSBenjamin Tissoires 				  GFP_KERNEL);
14483ac36d15SBenjamin Tissoires 	if (!td->fields) {
14493ac36d15SBenjamin Tissoires 		dev_err(&hdev->dev, "cannot allocate multitouch fields data\n");
1450c08d46aaSBenjamin Tissoires 		return -ENOMEM;
14513ac36d15SBenjamin Tissoires 	}
14523ac36d15SBenjamin Tissoires 
145376f5902aSHenrik Rydberg 	if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
145476f5902aSHenrik Rydberg 		td->serial_maybe = true;
145576f5902aSHenrik Rydberg 
1456b897f6dbSBenjamin Tissoires 	/*
1457b897f6dbSBenjamin Tissoires 	 * Store the initial quirk state
1458b897f6dbSBenjamin Tissoires 	 */
1459b897f6dbSBenjamin Tissoires 	td->initial_quirks = hdev->quirks;
1460b897f6dbSBenjamin Tissoires 
1461b897f6dbSBenjamin Tissoires 	/* This allows the driver to correctly support devices
1462b897f6dbSBenjamin Tissoires 	 * that emit events over several HID messages.
1463b897f6dbSBenjamin Tissoires 	 */
1464b897f6dbSBenjamin Tissoires 	hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
1465b897f6dbSBenjamin Tissoires 
1466b897f6dbSBenjamin Tissoires 	/*
1467b897f6dbSBenjamin Tissoires 	 * This allows the driver to handle different input sensors
1468b897f6dbSBenjamin Tissoires 	 * that emits events through different reports on the same HID
1469b897f6dbSBenjamin Tissoires 	 * device.
1470b897f6dbSBenjamin Tissoires 	 */
1471b897f6dbSBenjamin Tissoires 	hdev->quirks |= HID_QUIRK_MULTI_INPUT;
1472b897f6dbSBenjamin Tissoires 	hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT;
1473b897f6dbSBenjamin Tissoires 
1474b897f6dbSBenjamin Tissoires 	/*
1475b897f6dbSBenjamin Tissoires 	 * Some multitouch screens do not like to be polled for input
1476b897f6dbSBenjamin Tissoires 	 * reports. Fortunately, the Win8 spec says that all touches
1477b897f6dbSBenjamin Tissoires 	 * should be sent during each report, making the initialization
1478b897f6dbSBenjamin Tissoires 	 * of input reports unnecessary. For Win7 devices, well, let's hope
1479b897f6dbSBenjamin Tissoires 	 * they will still be happy (this is only be a problem if a touch
1480b897f6dbSBenjamin Tissoires 	 * was already there while probing the device).
1481b897f6dbSBenjamin Tissoires 	 *
1482b897f6dbSBenjamin Tissoires 	 * In addition some touchpads do not behave well if we read
1483b897f6dbSBenjamin Tissoires 	 * all feature reports from them. Instead we prevent
1484b897f6dbSBenjamin Tissoires 	 * initial report fetching and then selectively fetch each
1485b897f6dbSBenjamin Tissoires 	 * report we are interested in.
1486b897f6dbSBenjamin Tissoires 	 */
1487b897f6dbSBenjamin Tissoires 	hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
1488b897f6dbSBenjamin Tissoires 
14890ee32774SKees Cook 	timer_setup(&td->release_timer, mt_expired_timeout, 0);
14904f4001bcSBenjamin Tissoires 
14915519cab4SBenjamin Tissoires 	ret = hid_parse(hdev);
14925519cab4SBenjamin Tissoires 	if (ret != 0)
1493c08d46aaSBenjamin Tissoires 		return ret;
14945519cab4SBenjamin Tissoires 
1495f3287a99SBenjamin Tissoires 	if (mtclass->quirks & MT_QUIRK_FIX_CONST_CONTACT_ID)
1496f3287a99SBenjamin Tissoires 		mt_fix_const_fields(hdev, HID_DG_CONTACTID);
1497f3287a99SBenjamin Tissoires 
14985519cab4SBenjamin Tissoires 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
14992d93666eSBenjamin Tissoires 	if (ret)
1500c08d46aaSBenjamin Tissoires 		return ret;
15015519cab4SBenjamin Tissoires 
1502eec29e3dSBenjamin Tissoires 	ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group);
15030c4b3c63SNicholas Krause 	if (ret)
15040c4b3c63SNicholas Krause 		dev_warn(&hdev->dev, "Cannot allocate sysfs group for %s\n",
15050c4b3c63SNicholas Krause 				hdev->name);
1506eec29e3dSBenjamin Tissoires 
150731ae9bddSBenjamin Tissoires 	mt_set_maxcontacts(hdev);
15085519cab4SBenjamin Tissoires 	mt_set_input_mode(hdev);
15095519cab4SBenjamin Tissoires 
1510c08d46aaSBenjamin Tissoires 	/* release .fields memory as it is not used anymore */
1511c08d46aaSBenjamin Tissoires 	devm_kfree(&hdev->dev, td->fields);
15123ac36d15SBenjamin Tissoires 	td->fields = NULL;
15133ac36d15SBenjamin Tissoires 
15145519cab4SBenjamin Tissoires 	return 0;
15155519cab4SBenjamin Tissoires }
15165519cab4SBenjamin Tissoires 
15175519cab4SBenjamin Tissoires #ifdef CONFIG_PM
15185519cab4SBenjamin Tissoires static int mt_reset_resume(struct hid_device *hdev)
15195519cab4SBenjamin Tissoires {
1520d3e69b9aSBenson Leung 	mt_release_contacts(hdev);
152131ae9bddSBenjamin Tissoires 	mt_set_maxcontacts(hdev);
15225519cab4SBenjamin Tissoires 	mt_set_input_mode(hdev);
15235519cab4SBenjamin Tissoires 	return 0;
15245519cab4SBenjamin Tissoires }
1525dfeefd10SScott Liu 
1526dfeefd10SScott Liu static int mt_resume(struct hid_device *hdev)
1527dfeefd10SScott Liu {
1528dfeefd10SScott Liu 	/* Some Elan legacy devices require SET_IDLE to be set on resume.
1529dfeefd10SScott Liu 	 * It should be safe to send it to other devices too.
1530dfeefd10SScott Liu 	 * Tested on 3M, Stantum, Cypress, Zytronic, eGalax, and Elan panels. */
1531dfeefd10SScott Liu 
15324ba25d3fSBenjamin Tissoires 	hid_hw_idle(hdev, 0, 0, HID_REQ_SET_IDLE);
1533dfeefd10SScott Liu 
1534dfeefd10SScott Liu 	return 0;
1535dfeefd10SScott Liu }
15365519cab4SBenjamin Tissoires #endif
15375519cab4SBenjamin Tissoires 
15385519cab4SBenjamin Tissoires static void mt_remove(struct hid_device *hdev)
15395519cab4SBenjamin Tissoires {
1540b897f6dbSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
1541b897f6dbSBenjamin Tissoires 
15424f4001bcSBenjamin Tissoires 	del_timer_sync(&td->release_timer);
15434f4001bcSBenjamin Tissoires 
1544eec29e3dSBenjamin Tissoires 	sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
15455939212dSBenjamin Tissoires 	hid_hw_stop(hdev);
1546b897f6dbSBenjamin Tissoires 	hdev->quirks = td->initial_quirks;
15475519cab4SBenjamin Tissoires }
15485519cab4SBenjamin Tissoires 
15490fa9c616SBenjamin Tissoires /*
15500fa9c616SBenjamin Tissoires  * This list contains only:
15510fa9c616SBenjamin Tissoires  * - VID/PID of products not working with the default multitouch handling
15520fa9c616SBenjamin Tissoires  * - 2 generic rules.
15530fa9c616SBenjamin Tissoires  * So there is no point in adding here any device with MT_CLS_DEFAULT.
15540fa9c616SBenjamin Tissoires  */
15555519cab4SBenjamin Tissoires static const struct hid_device_id mt_devices[] = {
15565519cab4SBenjamin Tissoires 
1557f786bba4SBenjamin Tissoires 	/* 3M panels */
1558f786bba4SBenjamin Tissoires 	{ .driver_data = MT_CLS_3M,
15592c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_3M,
1560f786bba4SBenjamin Tissoires 			USB_DEVICE_ID_3M1968) },
1561f786bba4SBenjamin Tissoires 	{ .driver_data = MT_CLS_3M,
15622c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_3M,
1563f786bba4SBenjamin Tissoires 			USB_DEVICE_ID_3M2256) },
1564c4fad877SBenjamin Tissoires 	{ .driver_data = MT_CLS_3M,
15652c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_3M,
1566c4fad877SBenjamin Tissoires 			USB_DEVICE_ID_3M3266) },
1567f786bba4SBenjamin Tissoires 
1568504c932cSMasaki Ota 	/* Alps devices */
1569504c932cSMasaki Ota 	{ .driver_data = MT_CLS_WIN_8_DUAL,
1570504c932cSMasaki Ota 		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
1571504c932cSMasaki Ota 			USB_VENDOR_ID_ALPS_JP,
1572504c932cSMasaki Ota 			HID_DEVICE_ID_ALPS_U1_DUAL_PTP) },
1573504c932cSMasaki Ota 	{ .driver_data = MT_CLS_WIN_8_DUAL,
1574504c932cSMasaki Ota 		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
1575504c932cSMasaki Ota 			USB_VENDOR_ID_ALPS_JP,
1576504c932cSMasaki Ota 			HID_DEVICE_ID_ALPS_U1_DUAL_3BTN_PTP) },
1577504c932cSMasaki Ota 
157856d859e1SPavel Tatashin 	/* Lenovo X1 TAB Gen 2 */
157956d859e1SPavel Tatashin 	{ .driver_data = MT_CLS_WIN_8_DUAL,
158056d859e1SPavel Tatashin 		HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8,
158156d859e1SPavel Tatashin 			   USB_VENDOR_ID_LENOVO,
158256d859e1SPavel Tatashin 			   USB_DEVICE_ID_LENOVO_X1_TAB) },
158356d859e1SPavel Tatashin 
15846aef704eSBenjamin Tissoires 	/* Anton devices */
15856aef704eSBenjamin Tissoires 	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
15866aef704eSBenjamin Tissoires 		MT_USB_DEVICE(USB_VENDOR_ID_ANTON,
15876aef704eSBenjamin Tissoires 			USB_DEVICE_ID_ANTON_TOUCH_PAD) },
1588e6aac342SBenjamin Tissoires 
1589957b8dffSJoão Paulo Rechi Vita 	/* Asus T304UA */
1590957b8dffSJoão Paulo Rechi Vita 	{ .driver_data = MT_CLS_ASUS,
1591957b8dffSJoão Paulo Rechi Vita 		HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8,
1592957b8dffSJoão Paulo Rechi Vita 			USB_VENDOR_ID_ASUSTEK,
1593957b8dffSJoão Paulo Rechi Vita 			USB_DEVICE_ID_ASUSTEK_T304_KEYBOARD) },
1594957b8dffSJoão Paulo Rechi Vita 
1595b1057124SBenjamin Tissoires 	/* Atmel panels */
1596b1057124SBenjamin Tissoires 	{ .driver_data = MT_CLS_SERIAL,
15972c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_ATMEL,
1598841cb157SBenjamin Tissoires 			USB_DEVICE_ID_ATMEL_MXT_DIGITIZER) },
1599b1057124SBenjamin Tissoires 
16009ed32695SJiri Kosina 	/* Baanto multitouch devices */
1601dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
160216b79bb8SJiri Kosina 		MT_USB_DEVICE(USB_VENDOR_ID_BAANTO,
16039ed32695SJiri Kosina 			USB_DEVICE_ID_BAANTO_MT_190W2) },
16040fa9c616SBenjamin Tissoires 
1605a841b62cSBenjamin Tissoires 	/* Cando panels */
1606a841b62cSBenjamin Tissoires 	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
16072c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
1608a841b62cSBenjamin Tissoires 			USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
1609a841b62cSBenjamin Tissoires 	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
16102c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
1611a841b62cSBenjamin Tissoires 			USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
1612a841b62cSBenjamin Tissoires 
1613942fd422SAustin Zhang 	/* Chunghwa Telecom touch panels */
1614dc3e1d80SBenjamin Tissoires 	{  .driver_data = MT_CLS_NSMU,
16152c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT,
1616942fd422SAustin Zhang 			USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) },
1617942fd422SAustin Zhang 
1618070f63b4SYang Bo 	/* CJTouch panels */
1619070f63b4SYang Bo 	{ .driver_data = MT_CLS_NSMU,
1620070f63b4SYang Bo 		MT_USB_DEVICE(USB_VENDOR_ID_CJTOUCH,
1621070f63b4SYang Bo 			USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0020) },
1622070f63b4SYang Bo 	{ .driver_data = MT_CLS_NSMU,
1623070f63b4SYang Bo 		MT_USB_DEVICE(USB_VENDOR_ID_CJTOUCH,
1624070f63b4SYang Bo 			USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0040) },
1625070f63b4SYang Bo 
162679603dc9SBenjamin Tissoires 	/* CVTouch panels */
1627dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
16282c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_CVTOUCH,
162979603dc9SBenjamin Tissoires 			USB_DEVICE_ID_CVTOUCH_SCREEN) },
163079603dc9SBenjamin Tissoires 
163122408283SBenjamin Tissoires 	/* eGalax devices (resistive) */
163222408283SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX,
16332c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1634e36f690bSBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D) },
163522408283SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX,
16362c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1637e36f690bSBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E) },
163822408283SBenjamin Tissoires 
163922408283SBenjamin Tissoires 	/* eGalax devices (capacitive) */
1640fd1d1525SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
16412c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1642fd1d1525SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7207) },
164322408283SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX,
16442c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1645e36f690bSBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C) },
1646fd1d1525SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
16472c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1648fd1d1525SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224) },
16492ce09df4SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
16502c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
16512ce09df4SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_722A) },
165222408283SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
16532c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
165422408283SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_725E) },
1655fd1d1525SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
16562c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1657fd1d1525SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7262) },
165822408283SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX,
16592c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
166022408283SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B) },
166122408283SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX,
166222408283SBenjamin Tissoires 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1663e36f690bSBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1) },
1664fd1d1525SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
16652c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1666fd1d1525SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72AA) },
16671fd8f047SChris Bagwell 	{ .driver_data = MT_CLS_EGALAX,
1668aa672da1SAndy Shevchenko 		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
1669aa672da1SAndy Shevchenko 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72C4) },
1670aa672da1SAndy Shevchenko 	{ .driver_data = MT_CLS_EGALAX,
1671aa672da1SAndy Shevchenko 		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
1672aa672da1SAndy Shevchenko 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72D0) },
1673aa672da1SAndy Shevchenko 	{ .driver_data = MT_CLS_EGALAX,
16742c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
167566f06127SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA) },
167666f06127SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX,
16772c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1678bb9ff210SMarek Vasut 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302) },
16791b723e8dSBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
16802c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1681fd1d1525SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7349) },
1682fd1d1525SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
16832c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1684ae01c9e5SThierry Reding 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_73F7) },
1685ae01c9e5SThierry Reding 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
1686ae01c9e5SThierry Reding 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1687e36f690bSBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) },
168822408283SBenjamin Tissoires 
16897c7606a2STomas Sokorai 	/* Elitegroup panel */
16907c7606a2STomas Sokorai 	{ .driver_data = MT_CLS_SERIAL,
16917c7606a2STomas Sokorai 		MT_USB_DEVICE(USB_VENDOR_ID_ELITEGROUP,
16927c7606a2STomas Sokorai 			USB_DEVICE_ID_ELITEGROUP_05D8) },
16937c7606a2STomas Sokorai 
169477723e3bSHenrik Rydberg 	/* Flatfrog Panels */
169577723e3bSHenrik Rydberg 	{ .driver_data = MT_CLS_FLATFROG,
169677723e3bSHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_FLATFROG,
169777723e3bSHenrik Rydberg 			USB_DEVICE_ID_MULTITOUCH_3200) },
169877723e3bSHenrik Rydberg 
16993db187e7SBenjamin Tissoires 	/* FocalTech Panels */
17003db187e7SBenjamin Tissoires 	{ .driver_data = MT_CLS_SERIAL,
17013db187e7SBenjamin Tissoires 		MT_USB_DEVICE(USB_VENDOR_ID_CYGNAL,
17023db187e7SBenjamin Tissoires 			USB_DEVICE_ID_FOCALTECH_FTXXXX_MULTITOUCH) },
17033db187e7SBenjamin Tissoires 
17045572da08SBenjamin Tissoires 	/* GeneralTouch panel */
1705f5ff4e1eSXianhan Yu 	{ .driver_data = MT_CLS_GENERALTOUCH_TWOFINGERS,
17062c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
17075572da08SBenjamin Tissoires 			USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
1708f5ff4e1eSXianhan Yu 	{ .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
1709f5ff4e1eSXianhan Yu 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
1710f5ff4e1eSXianhan Yu 			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PWT_TENFINGERS) },
17117b226292SLuosong 	{ .driver_data = MT_CLS_GENERALTOUCH_TWOFINGERS,
17127b226292SLuosong 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
17137b226292SLuosong 			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0101) },
17147b226292SLuosong 	{ .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
17157b226292SLuosong 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
17167b226292SLuosong 			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0102) },
17177b226292SLuosong 	{ .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
17187b226292SLuosong 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
17197b226292SLuosong 			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0106) },
17207b226292SLuosong 	{ .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
17217b226292SLuosong 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
17227b226292SLuosong 			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_010A) },
17237b226292SLuosong 	{ .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
17247b226292SLuosong 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
17257b226292SLuosong 			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100) },
17265572da08SBenjamin Tissoires 
17274d5df5d1SAndreas Nielsen 	/* Gametel game controller */
1728dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
17292c2110e9SHenrik Rydberg 		MT_BT_DEVICE(USB_VENDOR_ID_FRUCTEL,
17304d5df5d1SAndreas Nielsen 			USB_DEVICE_ID_GAMETEL_MT_MODE) },
17314d5df5d1SAndreas Nielsen 
1732ee0fbd14SBenjamin Tissoires 	/* GoodTouch panels */
1733dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
17342c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH,
1735ee0fbd14SBenjamin Tissoires 			USB_DEVICE_ID_GOODTOUCH_000f) },
1736ee0fbd14SBenjamin Tissoires 
173754580365SBenjamin Tissoires 	/* Hanvon panels */
173854580365SBenjamin Tissoires 	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
17392c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT,
174054580365SBenjamin Tissoires 			USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) },
174154580365SBenjamin Tissoires 
17424e61f0d7SAustin Zhang 	/* Ilitek dual touch panel */
1743dc3e1d80SBenjamin Tissoires 	{  .driver_data = MT_CLS_NSMU,
17442c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_ILITEK,
17454e61f0d7SAustin Zhang 			USB_DEVICE_ID_ILITEK_MULTITOUCH) },
17464e61f0d7SAustin Zhang 
1747f3287a99SBenjamin Tissoires 	/* LG Melfas panel */
1748f3287a99SBenjamin Tissoires 	{ .driver_data = MT_CLS_LG,
1749f3287a99SBenjamin Tissoires 		HID_USB_DEVICE(USB_VENDOR_ID_LG,
1750f3287a99SBenjamin Tissoires 			USB_DEVICE_ID_LG_MELFAS_MT) },
1751f3287a99SBenjamin Tissoires 
17524a6ee685SBenjamin Tissoires 	/* MosArt panels */
17534a6ee685SBenjamin Tissoires 	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
17542c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_ASUS,
17554a6ee685SBenjamin Tissoires 			USB_DEVICE_ID_ASUS_T91MT)},
17564a6ee685SBenjamin Tissoires 	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
17572c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_ASUS,
17584a6ee685SBenjamin Tissoires 			USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) },
17594a6ee685SBenjamin Tissoires 	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
17602c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_TURBOX,
17614a6ee685SBenjamin Tissoires 			USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) },
17624a6ee685SBenjamin Tissoires 
17634db703eaSAustin Hendrix 	/* Novatek Panel */
1764dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
17654380d819SJiri Kosina 		MT_USB_DEVICE(USB_VENDOR_ID_NOVATEK,
17664db703eaSAustin Hendrix 			USB_DEVICE_ID_NOVATEK_PCT) },
17674db703eaSAustin Hendrix 
1768a80e803aSBenjamin Tissoires 	/* Ntrig Panel */
1769a80e803aSBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
1770a80e803aSBenjamin Tissoires 		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
1771a80e803aSBenjamin Tissoires 			USB_VENDOR_ID_NTRIG, 0x1b05) },
1772a80e803aSBenjamin Tissoires 
1773fb55b402SHans de Goede 	/* Panasonic panels */
1774fb55b402SHans de Goede 	{ .driver_data = MT_CLS_PANASONIC,
1775fb55b402SHans de Goede 		MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC,
1776fb55b402SHans de Goede 			USB_DEVICE_ID_PANABOARD_UBT780) },
1777fb55b402SHans de Goede 	{ .driver_data = MT_CLS_PANASONIC,
1778fb55b402SHans de Goede 		MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC,
1779fb55b402SHans de Goede 			USB_DEVICE_ID_PANABOARD_UBT880) },
1780fb55b402SHans de Goede 
1781b7ea95ffSAaron Tian 	/* PixArt optical touch screen */
1782b7ea95ffSAaron Tian 	{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
17832c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_PIXART,
1784b7ea95ffSAaron Tian 			USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN) },
1785b7ea95ffSAaron Tian 	{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
17862c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_PIXART,
1787b7ea95ffSAaron Tian 			USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1) },
1788b7ea95ffSAaron Tian 	{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
17892c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_PIXART,
1790b7ea95ffSAaron Tian 			USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2) },
1791b7ea95ffSAaron Tian 
17925519cab4SBenjamin Tissoires 	/* PixCir-based panels */
17931e9cf35bSBenjamin Tissoires 	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
17942c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
17955519cab4SBenjamin Tissoires 			USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
17965519cab4SBenjamin Tissoires 
17975e7ea11fSBenjamin Tissoires 	/* Quanta-based panels */
17985e7ea11fSBenjamin Tissoires 	{ .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID,
17992c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_QUANTA,
18005e7ea11fSBenjamin Tissoires 			USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001) },
1801a6802e00SForest Bond 
1802*843e475fSBenjamin Tissoires 	/* Razer touchpads */
1803*843e475fSBenjamin Tissoires 	{ .driver_data = MT_CLS_RAZER_BLADE_STEALTH,
1804*843e475fSBenjamin Tissoires 		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
1805*843e475fSBenjamin Tissoires 			USB_VENDOR_ID_SYNAPTICS, 0x8323) },
1806*843e475fSBenjamin Tissoires 
1807043b403aSBenjamin Tissoires 	/* Stantum panels */
1808bf5af9b5SBenjamin Tissoires 	{ .driver_data = MT_CLS_CONFIDENCE,
18092c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM,
1810043b403aSBenjamin Tissoires 			USB_DEVICE_ID_MTP_STM)},
1811043b403aSBenjamin Tissoires 
1812847672cdSBenjamin Tissoires 	/* TopSeed panels */
1813847672cdSBenjamin Tissoires 	{ .driver_data = MT_CLS_TOPSEED,
18142c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_TOPSEED2,
1815847672cdSBenjamin Tissoires 			USB_DEVICE_ID_TOPSEED2_PERIPAD_701) },
1816847672cdSBenjamin Tissoires 
18175e74e56dSBenjamin Tissoires 	/* Touch International panels */
1818dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
18192c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_TOUCH_INTL,
18205e74e56dSBenjamin Tissoires 			USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH) },
18215e74e56dSBenjamin Tissoires 
1822617b64f9SBenjamin Tissoires 	/* Unitec panels */
1823dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
18242c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_UNITEC,
1825617b64f9SBenjamin Tissoires 			USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) },
1826dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
18272c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_UNITEC,
1828617b64f9SBenjamin Tissoires 			USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
1829bf9d121eSKaiChung Cheng 
1830da10bc25SMathieu Magnaudet 	/* VTL panels */
1831da10bc25SMathieu Magnaudet 	{ .driver_data = MT_CLS_VTL,
1832da10bc25SMathieu Magnaudet 		MT_USB_DEVICE(USB_VENDOR_ID_VTL,
1833da10bc25SMathieu Magnaudet 			USB_DEVICE_ID_VTL_MULTITOUCH_FF3F) },
1834da10bc25SMathieu Magnaudet 
1835bf9d121eSKaiChung Cheng 	/* Wistron panels */
1836bf9d121eSKaiChung Cheng 	{ .driver_data = MT_CLS_NSMU,
1837bf9d121eSKaiChung Cheng 		MT_USB_DEVICE(USB_VENDOR_ID_WISTRON,
1838bf9d121eSKaiChung Cheng 			USB_DEVICE_ID_WISTRON_OPTICAL_TOUCH) },
1839bf9d121eSKaiChung Cheng 
1840bc8a2a9bSice chien 	/* XAT */
1841dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
18422c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XAT,
1843bc8a2a9bSice chien 			USB_DEVICE_ID_XAT_CSR) },
1844617b64f9SBenjamin Tissoires 
184511576c61SMasatoshi Hoshikawa 	/* Xiroku */
1846dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
18472c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
184811576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_SPX) },
1849dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
18502c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
185111576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_MPX) },
1852dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
18532c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
185411576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_CSR) },
1855dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
18562c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
185711576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_SPX1) },
1858dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
18592c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
186011576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_MPX1) },
1861dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
18622c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
186311576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_CSR1) },
1864dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
18652c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
186611576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_SPX2) },
1867dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
18682c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
186911576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_MPX2) },
1870dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
18712c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
187211576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_CSR2) },
187311576c61SMasatoshi Hoshikawa 
18740e82232cSWei-Ning Huang 	/* Google MT devices */
18750e82232cSWei-Ning Huang 	{ .driver_data = MT_CLS_GOOGLE,
18760e82232cSWei-Ning Huang 		HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_GOOGLE,
18770e82232cSWei-Ning Huang 			USB_DEVICE_ID_GOOGLE_TOUCH_ROSE) },
18780e82232cSWei-Ning Huang 
18794fa3a583SHenrik Rydberg 	/* Generic MT device */
18804fa3a583SHenrik Rydberg 	{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH, HID_ANY_ID, HID_ANY_ID) },
1881f961bd35SBenjamin Tissoires 
1882f961bd35SBenjamin Tissoires 	/* Generic Win 8 certified MT device */
1883f961bd35SBenjamin Tissoires 	{  .driver_data = MT_CLS_WIN_8,
1884f961bd35SBenjamin Tissoires 		HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH_WIN_8,
1885f961bd35SBenjamin Tissoires 			HID_ANY_ID, HID_ANY_ID) },
18865519cab4SBenjamin Tissoires 	{ }
18875519cab4SBenjamin Tissoires };
18885519cab4SBenjamin Tissoires MODULE_DEVICE_TABLE(hid, mt_devices);
18895519cab4SBenjamin Tissoires 
18905519cab4SBenjamin Tissoires static const struct hid_usage_id mt_grabbed_usages[] = {
18915519cab4SBenjamin Tissoires 	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
18925519cab4SBenjamin Tissoires 	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
18935519cab4SBenjamin Tissoires };
18945519cab4SBenjamin Tissoires 
18955519cab4SBenjamin Tissoires static struct hid_driver mt_driver = {
18965519cab4SBenjamin Tissoires 	.name = "hid-multitouch",
18975519cab4SBenjamin Tissoires 	.id_table = mt_devices,
18985519cab4SBenjamin Tissoires 	.probe = mt_probe,
18995519cab4SBenjamin Tissoires 	.remove = mt_remove,
19005519cab4SBenjamin Tissoires 	.input_mapping = mt_input_mapping,
19015519cab4SBenjamin Tissoires 	.input_mapped = mt_input_mapped,
190276f5902aSHenrik Rydberg 	.input_configured = mt_input_configured,
19035519cab4SBenjamin Tissoires 	.feature_mapping = mt_feature_mapping,
19045519cab4SBenjamin Tissoires 	.usage_table = mt_grabbed_usages,
19055519cab4SBenjamin Tissoires 	.event = mt_event,
190655978fa9SBenjamin Tissoires 	.report = mt_report,
19075519cab4SBenjamin Tissoires #ifdef CONFIG_PM
19085519cab4SBenjamin Tissoires 	.reset_resume = mt_reset_resume,
1909dfeefd10SScott Liu 	.resume = mt_resume,
19105519cab4SBenjamin Tissoires #endif
19115519cab4SBenjamin Tissoires };
1912f425458eSH Hartley Sweeten module_hid_driver(mt_driver);
1913