xref: /linux/drivers/hid/hid-multitouch.c (revision 01eaac7e)
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 /*
31f146d1c4SBenjamin Tissoires  * This driver is regularly tested thanks to the test suite in hid-tools[1].
32b0a78681SBenjamin Tissoires  * Please run these regression tests before patching this module so that
33b0a78681SBenjamin Tissoires  * your patch won't break existing known devices.
34b0a78681SBenjamin Tissoires  *
35f146d1c4SBenjamin Tissoires  * [1] https://gitlab.freedesktop.org/libevdev/hid-tools
36b0a78681SBenjamin Tissoires  */
37b0a78681SBenjamin Tissoires 
385519cab4SBenjamin Tissoires #include <linux/device.h>
395519cab4SBenjamin Tissoires #include <linux/hid.h>
405519cab4SBenjamin Tissoires #include <linux/module.h>
415519cab4SBenjamin Tissoires #include <linux/slab.h>
425519cab4SBenjamin Tissoires #include <linux/input/mt.h>
4329cc309dSNicolas Boichat #include <linux/jiffies.h>
4449a5a827SBenjamin Tissoires #include <linux/string.h>
454f4001bcSBenjamin Tissoires #include <linux/timer.h>
465519cab4SBenjamin Tissoires 
475519cab4SBenjamin Tissoires 
485519cab4SBenjamin Tissoires MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
49ef2fafb3SBenjamin Tissoires MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
505519cab4SBenjamin Tissoires MODULE_DESCRIPTION("HID multitouch panels");
515519cab4SBenjamin Tissoires MODULE_LICENSE("GPL");
525519cab4SBenjamin Tissoires 
535519cab4SBenjamin Tissoires #include "hid-ids.h"
545519cab4SBenjamin Tissoires 
555519cab4SBenjamin Tissoires /* quirks to control the device */
56fd911896SBenjamin Tissoires #define MT_QUIRK_NOT_SEEN_MEANS_UP	BIT(0)
57fd911896SBenjamin Tissoires #define MT_QUIRK_SLOT_IS_CONTACTID	BIT(1)
58fd911896SBenjamin Tissoires #define MT_QUIRK_CYPRESS		BIT(2)
59fd911896SBenjamin Tissoires #define MT_QUIRK_SLOT_IS_CONTACTNUMBER	BIT(3)
60fd911896SBenjamin Tissoires #define MT_QUIRK_ALWAYS_VALID		BIT(4)
61fd911896SBenjamin Tissoires #define MT_QUIRK_VALID_IS_INRANGE	BIT(5)
62fd911896SBenjamin Tissoires #define MT_QUIRK_VALID_IS_CONFIDENCE	BIT(6)
63fd911896SBenjamin Tissoires #define MT_QUIRK_CONFIDENCE		BIT(7)
64fd911896SBenjamin Tissoires #define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE	BIT(8)
65fd911896SBenjamin Tissoires #define MT_QUIRK_NO_AREA		BIT(9)
66fd911896SBenjamin Tissoires #define MT_QUIRK_IGNORE_DUPLICATES	BIT(10)
67fd911896SBenjamin Tissoires #define MT_QUIRK_HOVERING		BIT(11)
68fd911896SBenjamin Tissoires #define MT_QUIRK_CONTACT_CNT_ACCURATE	BIT(12)
69fd911896SBenjamin Tissoires #define MT_QUIRK_FORCE_GET_FEATURE	BIT(13)
70fd911896SBenjamin Tissoires #define MT_QUIRK_FIX_CONST_CONTACT_ID	BIT(14)
71fd911896SBenjamin Tissoires #define MT_QUIRK_TOUCH_SIZE_SCALING	BIT(15)
724f4001bcSBenjamin Tissoires #define MT_QUIRK_STICKY_FINGERS		BIT(16)
73957b8dffSJoão Paulo Rechi Vita #define MT_QUIRK_ASUS_CUSTOM_UP		BIT(17)
74d9c57a70SBenjamin Tissoires #define MT_QUIRK_WIN8_PTP_BUTTONS	BIT(18)
755519cab4SBenjamin Tissoires 
769abebedbSAndrew Duggan #define MT_INPUTMODE_TOUCHSCREEN	0x02
779abebedbSAndrew Duggan #define MT_INPUTMODE_TOUCHPAD		0x03
789abebedbSAndrew Duggan 
792c6e0277SSeth Forshee #define MT_BUTTONTYPE_CLICKPAD		0
802c6e0277SSeth Forshee 
8102946f4bSBenjamin Tissoires enum latency_mode {
8202946f4bSBenjamin Tissoires 	HID_LATENCY_NORMAL = 0,
8302946f4bSBenjamin Tissoires 	HID_LATENCY_HIGH = 1,
8402946f4bSBenjamin Tissoires };
8502946f4bSBenjamin Tissoires 
864f4001bcSBenjamin Tissoires #define MT_IO_FLAGS_RUNNING		0
8796098274SBenjamin Tissoires #define MT_IO_FLAGS_ACTIVE_SLOTS	1
8896098274SBenjamin Tissoires #define MT_IO_FLAGS_PENDING_SLOTS	2
894f4001bcSBenjamin Tissoires 
90*01eaac7eSBenjamin Tissoires static const bool mtrue = true;		/* default for true */
91*01eaac7eSBenjamin Tissoires static const bool mfalse;		/* default for false */
92*01eaac7eSBenjamin Tissoires static const __s32 mzero;		/* default for 0 */
93*01eaac7eSBenjamin Tissoires 
94*01eaac7eSBenjamin Tissoires #define DEFAULT_TRUE	((void *)&mtrue)
95*01eaac7eSBenjamin Tissoires #define DEFAULT_FALSE	((void *)&mfalse)
96*01eaac7eSBenjamin Tissoires #define DEFAULT_ZERO	((void *)&mzero)
97*01eaac7eSBenjamin Tissoires 
98*01eaac7eSBenjamin Tissoires struct mt_usages {
99*01eaac7eSBenjamin Tissoires 	struct list_head list;
100*01eaac7eSBenjamin Tissoires 	__s32 *x, *y, *cx, *cy, *p, *w, *h, *a;
101*01eaac7eSBenjamin Tissoires 	__s32 *contactid;	/* the device ContactID assigned to this slot */
102*01eaac7eSBenjamin Tissoires 	bool *tip_state;	/* is the touch valid? */
103*01eaac7eSBenjamin Tissoires 	bool *inrange_state;	/* is the finger in proximity of the sensor? */
104*01eaac7eSBenjamin Tissoires 	bool *confidence_state;	/* is the touch made by a finger? */
1055519cab4SBenjamin Tissoires };
1065519cab4SBenjamin Tissoires 
107f146d1c4SBenjamin Tissoires struct mt_application {
108f146d1c4SBenjamin Tissoires 	struct list_head list;
109f146d1c4SBenjamin Tissoires 	unsigned int application;
110*01eaac7eSBenjamin Tissoires 	struct list_head mt_usages;	/* mt usages list */
1113ceb3826SBenjamin Tissoires 
1123ceb3826SBenjamin Tissoires 	__s32 quirks;
1133ceb3826SBenjamin Tissoires 
114*01eaac7eSBenjamin Tissoires 	__s32 *scantime;		/* scantime reported */
115*01eaac7eSBenjamin Tissoires 	__s32 scantime_logical_max;	/* max value for raw scantime */
116f146d1c4SBenjamin Tissoires 
117*01eaac7eSBenjamin Tissoires 	__s32 *raw_cc;			/* contact count in the report */
118f146d1c4SBenjamin Tissoires 	int left_button_state;		/* left button state */
119f146d1c4SBenjamin Tissoires 	unsigned int mt_flags;		/* flags to pass to input-mt */
120f146d1c4SBenjamin Tissoires 
121f146d1c4SBenjamin Tissoires 	__u8 num_received;	/* how many contacts we received */
122f146d1c4SBenjamin Tissoires 	__u8 num_expected;	/* expected last contact index */
123f146d1c4SBenjamin Tissoires 	__u8 buttons_count;	/* number of physical buttons per touchpad */
124f146d1c4SBenjamin Tissoires 	__u8 touches_by_report;	/* how many touches are present in one report:
125f146d1c4SBenjamin Tissoires 				 * 1 means we should use a serial protocol
126f146d1c4SBenjamin Tissoires 				 * > 1 means hybrid (multitouch) protocol
127f146d1c4SBenjamin Tissoires 				 */
128f146d1c4SBenjamin Tissoires 
129f146d1c4SBenjamin Tissoires 	__s32 dev_time;		/* the scan time provided by the device */
130f146d1c4SBenjamin Tissoires 	unsigned long jiffies;	/* the frame's jiffies */
131f146d1c4SBenjamin Tissoires 	int timestamp;		/* the timestamp to be sent */
132f146d1c4SBenjamin Tissoires 	int prev_scantime;		/* scantime reported previously */
133f146d1c4SBenjamin Tissoires 
134f146d1c4SBenjamin Tissoires 	bool have_contact_count;
135f146d1c4SBenjamin Tissoires };
136f146d1c4SBenjamin Tissoires 
1375519cab4SBenjamin Tissoires struct mt_class {
1382d93666eSBenjamin Tissoires 	__s32 name;	/* MT_CLS */
1395519cab4SBenjamin Tissoires 	__s32 quirks;
1405519cab4SBenjamin Tissoires 	__s32 sn_move;	/* Signal/noise ratio for move events */
141f786bba4SBenjamin Tissoires 	__s32 sn_width;	/* Signal/noise ratio for width events */
142f786bba4SBenjamin Tissoires 	__s32 sn_height;	/* Signal/noise ratio for height events */
1435519cab4SBenjamin Tissoires 	__s32 sn_pressure;	/* Signal/noise ratio for pressure events */
1445519cab4SBenjamin Tissoires 	__u8 maxcontacts;
145c2ef8f21SBenjamin Tissoires 	bool is_indirect;	/* true for touchpads */
1466aef704eSBenjamin Tissoires 	bool export_all_inputs;	/* do not ignore mouse, keyboards, etc... */
1475519cab4SBenjamin Tissoires };
1485519cab4SBenjamin Tissoires 
1498dfe14b3SBenjamin Tissoires struct mt_report_data {
1508dfe14b3SBenjamin Tissoires 	struct list_head list;
1518dfe14b3SBenjamin Tissoires 	struct hid_report *report;
1528dfe14b3SBenjamin Tissoires 	struct mt_application *application;
1538dfe14b3SBenjamin Tissoires 	bool is_mt_collection;
1548dfe14b3SBenjamin Tissoires };
1558dfe14b3SBenjamin Tissoires 
1565519cab4SBenjamin Tissoires struct mt_device {
157eec29e3dSBenjamin Tissoires 	struct mt_class mtclass;	/* our mt device class */
1584f4001bcSBenjamin Tissoires 	struct timer_list release_timer;	/* to release sticky fingers */
1590ee32774SKees Cook 	struct hid_device *hdev;	/* hid_device we're attached to */
1604f4001bcSBenjamin Tissoires 	unsigned long mt_io_flags;	/* mt flags (MT_IO_FLAGS_*) */
1619abebedbSAndrew Duggan 	__u8 inputmode_value;	/* InputMode HID feature value */
1625519cab4SBenjamin Tissoires 	__u8 maxcontacts;
1632c6e0277SSeth Forshee 	bool is_buttonpad;	/* is this device a button pad? */
16476f5902aSHenrik Rydberg 	bool serial_maybe;	/* need to check for serial protocol */
165f146d1c4SBenjamin Tissoires 
166f146d1c4SBenjamin Tissoires 	struct list_head applications;
1678dfe14b3SBenjamin Tissoires 	struct list_head reports;
1685519cab4SBenjamin Tissoires };
1695519cab4SBenjamin Tissoires 
170f146d1c4SBenjamin Tissoires static void mt_post_parse_default_settings(struct mt_device *td,
171f146d1c4SBenjamin Tissoires 					   struct mt_application *app);
172f146d1c4SBenjamin Tissoires static void mt_post_parse(struct mt_device *td, struct mt_application *app);
173a69c5f8bSBenjamin Tissoires 
1745519cab4SBenjamin Tissoires /* classes of device behavior */
17522408283SBenjamin Tissoires #define MT_CLS_DEFAULT				0x0001
17622408283SBenjamin Tissoires 
177a062cc5aSStephane Chatty #define MT_CLS_SERIAL				0x0002
178a062cc5aSStephane Chatty #define MT_CLS_CONFIDENCE			0x0003
1795e7ea11fSBenjamin Tissoires #define MT_CLS_CONFIDENCE_CONTACT_ID		0x0004
1805e7ea11fSBenjamin Tissoires #define MT_CLS_CONFIDENCE_MINUS_ONE		0x0005
1815e7ea11fSBenjamin Tissoires #define MT_CLS_DUAL_INRANGE_CONTACTID		0x0006
1825e7ea11fSBenjamin Tissoires #define MT_CLS_DUAL_INRANGE_CONTACTNUMBER	0x0007
1830fa9c616SBenjamin Tissoires /* reserved					0x0008 */
184b7ea95ffSAaron Tian #define MT_CLS_INRANGE_CONTACTNUMBER		0x0009
185dc3e1d80SBenjamin Tissoires #define MT_CLS_NSMU				0x000a
1860fa9c616SBenjamin Tissoires /* reserved					0x0010 */
1870fa9c616SBenjamin Tissoires /* reserved					0x0011 */
188f961bd35SBenjamin Tissoires #define MT_CLS_WIN_8				0x0012
1896aef704eSBenjamin Tissoires #define MT_CLS_EXPORT_ALL_INPUTS		0x0013
190504c932cSMasaki Ota #define MT_CLS_WIN_8_DUAL			0x0014
19122408283SBenjamin Tissoires 
19222408283SBenjamin Tissoires /* vendor specific classes */
19322408283SBenjamin Tissoires #define MT_CLS_3M				0x0101
1940fa9c616SBenjamin Tissoires /* reserved					0x0102 */
19522408283SBenjamin Tissoires #define MT_CLS_EGALAX				0x0103
1961b723e8dSBenjamin Tissoires #define MT_CLS_EGALAX_SERIAL			0x0104
197847672cdSBenjamin Tissoires #define MT_CLS_TOPSEED				0x0105
1982258e863SDenis Kovalev #define MT_CLS_PANASONIC			0x0106
19977723e3bSHenrik Rydberg #define MT_CLS_FLATFROG				0x0107
200cdcd3ac4SJiri Kosina #define MT_CLS_GENERALTOUCH_TWOFINGERS		0x0108
201cdcd3ac4SJiri Kosina #define MT_CLS_GENERALTOUCH_PWT_TENFINGERS	0x0109
202f3287a99SBenjamin Tissoires #define MT_CLS_LG				0x010a
203957b8dffSJoão Paulo Rechi Vita #define MT_CLS_ASUS				0x010b
204da10bc25SMathieu Magnaudet #define MT_CLS_VTL				0x0110
2050e82232cSWei-Ning Huang #define MT_CLS_GOOGLE				0x0111
206843e475fSBenjamin Tissoires #define MT_CLS_RAZER_BLADE_STEALTH		0x0112
2075519cab4SBenjamin Tissoires 
2089498f954SBenjamin Tissoires #define MT_DEFAULT_MAXCONTACT	10
209afbcb04cSBenjamin Tissoires #define MT_MAX_MAXCONTACT	250
2109498f954SBenjamin Tissoires 
21129cc309dSNicolas Boichat /*
21229cc309dSNicolas Boichat  * Resync device and local timestamps after that many microseconds without
21329cc309dSNicolas Boichat  * receiving data.
21429cc309dSNicolas Boichat  */
21529cc309dSNicolas Boichat #define MAX_TIMESTAMP_INTERVAL	1000000
21629cc309dSNicolas Boichat 
2172c2110e9SHenrik Rydberg #define MT_USB_DEVICE(v, p)	HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH, v, p)
2182c2110e9SHenrik Rydberg #define MT_BT_DEVICE(v, p)	HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_MULTITOUCH, v, p)
2192c2110e9SHenrik Rydberg 
2205519cab4SBenjamin Tissoires /*
2215519cab4SBenjamin Tissoires  * these device-dependent functions determine what slot corresponds
2225519cab4SBenjamin Tissoires  * to a valid contact that was just read.
2235519cab4SBenjamin Tissoires  */
2245519cab4SBenjamin Tissoires 
225*01eaac7eSBenjamin Tissoires static int cypress_compute_slot(struct mt_application *application,
226*01eaac7eSBenjamin Tissoires 				struct mt_usages *slot)
227a3b5e577SBenjamin Tissoires {
228*01eaac7eSBenjamin Tissoires 	if (*slot->contactid != 0 || application->num_received == 0)
229*01eaac7eSBenjamin Tissoires 		return *slot->contactid;
230a3b5e577SBenjamin Tissoires 	else
231a3b5e577SBenjamin Tissoires 		return -1;
232a3b5e577SBenjamin Tissoires }
233a3b5e577SBenjamin Tissoires 
234cf6d15d7SBenjamin Tissoires static const struct mt_class mt_classes[] = {
2352d93666eSBenjamin Tissoires 	{ .name = MT_CLS_DEFAULT,
236dc3e1d80SBenjamin Tissoires 		.quirks = MT_QUIRK_ALWAYS_VALID |
237dc3e1d80SBenjamin Tissoires 			MT_QUIRK_CONTACT_CNT_ACCURATE },
238dc3e1d80SBenjamin Tissoires 	{ .name = MT_CLS_NSMU,
2399498f954SBenjamin Tissoires 		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP },
240a062cc5aSStephane Chatty 	{ .name = MT_CLS_SERIAL,
241a062cc5aSStephane Chatty 		.quirks = MT_QUIRK_ALWAYS_VALID},
24222408283SBenjamin Tissoires 	{ .name = MT_CLS_CONFIDENCE,
24322408283SBenjamin Tissoires 		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE },
2445e7ea11fSBenjamin Tissoires 	{ .name = MT_CLS_CONFIDENCE_CONTACT_ID,
2455e7ea11fSBenjamin Tissoires 		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
2465e7ea11fSBenjamin Tissoires 			MT_QUIRK_SLOT_IS_CONTACTID },
24722408283SBenjamin Tissoires 	{ .name = MT_CLS_CONFIDENCE_MINUS_ONE,
24822408283SBenjamin Tissoires 		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
24922408283SBenjamin Tissoires 			MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE },
2501e9cf35bSBenjamin Tissoires 	{ .name = MT_CLS_DUAL_INRANGE_CONTACTID,
2512d93666eSBenjamin Tissoires 		.quirks = MT_QUIRK_VALID_IS_INRANGE |
2522d93666eSBenjamin Tissoires 			MT_QUIRK_SLOT_IS_CONTACTID,
2532d93666eSBenjamin Tissoires 		.maxcontacts = 2 },
2541e9cf35bSBenjamin Tissoires 	{ .name = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
2552d93666eSBenjamin Tissoires 		.quirks = MT_QUIRK_VALID_IS_INRANGE |
2562d93666eSBenjamin Tissoires 			MT_QUIRK_SLOT_IS_CONTACTNUMBER,
2572d93666eSBenjamin Tissoires 		.maxcontacts = 2 },
258b7ea95ffSAaron Tian 	{ .name = MT_CLS_INRANGE_CONTACTNUMBER,
259b7ea95ffSAaron Tian 		.quirks = MT_QUIRK_VALID_IS_INRANGE |
260b7ea95ffSAaron Tian 			MT_QUIRK_SLOT_IS_CONTACTNUMBER },
261f961bd35SBenjamin Tissoires 	{ .name = MT_CLS_WIN_8,
262f961bd35SBenjamin Tissoires 		.quirks = MT_QUIRK_ALWAYS_VALID |
263f961bd35SBenjamin Tissoires 			MT_QUIRK_IGNORE_DUPLICATES |
264f961bd35SBenjamin Tissoires 			MT_QUIRK_HOVERING |
2654f4001bcSBenjamin Tissoires 			MT_QUIRK_CONTACT_CNT_ACCURATE |
266d9c57a70SBenjamin Tissoires 			MT_QUIRK_STICKY_FINGERS |
267d9c57a70SBenjamin Tissoires 			MT_QUIRK_WIN8_PTP_BUTTONS },
2686aef704eSBenjamin Tissoires 	{ .name = MT_CLS_EXPORT_ALL_INPUTS,
2696aef704eSBenjamin Tissoires 		.quirks = MT_QUIRK_ALWAYS_VALID |
2706aef704eSBenjamin Tissoires 			MT_QUIRK_CONTACT_CNT_ACCURATE,
2716aef704eSBenjamin Tissoires 		.export_all_inputs = true },
272504c932cSMasaki Ota 	{ .name = MT_CLS_WIN_8_DUAL,
273504c932cSMasaki Ota 		.quirks = MT_QUIRK_ALWAYS_VALID |
274504c932cSMasaki Ota 			MT_QUIRK_IGNORE_DUPLICATES |
275504c932cSMasaki Ota 			MT_QUIRK_HOVERING |
276d9c57a70SBenjamin Tissoires 			MT_QUIRK_CONTACT_CNT_ACCURATE |
277d9c57a70SBenjamin Tissoires 			MT_QUIRK_WIN8_PTP_BUTTONS,
278504c932cSMasaki Ota 		.export_all_inputs = true },
27922408283SBenjamin Tissoires 
28022408283SBenjamin Tissoires 	/*
28122408283SBenjamin Tissoires 	 * vendor specific classes
28222408283SBenjamin Tissoires 	 */
28322408283SBenjamin Tissoires 	{ .name = MT_CLS_3M,
28422408283SBenjamin Tissoires 		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
285e9d0a26dSHungNien Chen 			MT_QUIRK_SLOT_IS_CONTACTID |
286e9d0a26dSHungNien Chen 			MT_QUIRK_TOUCH_SIZE_SCALING,
28722408283SBenjamin Tissoires 		.sn_move = 2048,
28822408283SBenjamin Tissoires 		.sn_width = 128,
289c5d40be5SHenrik Rydberg 		.sn_height = 128,
290c5d40be5SHenrik Rydberg 		.maxcontacts = 60,
291c5d40be5SHenrik Rydberg 	},
2924875ac11SRichard Nauber 	{ .name = MT_CLS_EGALAX,
2934875ac11SRichard Nauber 		.quirks =  MT_QUIRK_SLOT_IS_CONTACTID |
2942261bb9fSBenjamin Tissoires 			MT_QUIRK_VALID_IS_INRANGE,
2954875ac11SRichard Nauber 		.sn_move = 4096,
2964875ac11SRichard Nauber 		.sn_pressure = 32,
2974875ac11SRichard Nauber 	},
2981b723e8dSBenjamin Tissoires 	{ .name = MT_CLS_EGALAX_SERIAL,
2991b723e8dSBenjamin Tissoires 		.quirks =  MT_QUIRK_SLOT_IS_CONTACTID |
3001b723e8dSBenjamin Tissoires 			MT_QUIRK_ALWAYS_VALID,
3012d93666eSBenjamin Tissoires 		.sn_move = 4096,
3022d93666eSBenjamin Tissoires 		.sn_pressure = 32,
3032d93666eSBenjamin Tissoires 	},
304847672cdSBenjamin Tissoires 	{ .name = MT_CLS_TOPSEED,
305847672cdSBenjamin Tissoires 		.quirks = MT_QUIRK_ALWAYS_VALID,
306847672cdSBenjamin Tissoires 		.is_indirect = true,
307847672cdSBenjamin Tissoires 		.maxcontacts = 2,
308847672cdSBenjamin Tissoires 	},
3092258e863SDenis Kovalev 	{ .name = MT_CLS_PANASONIC,
3102258e863SDenis Kovalev 		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP,
3112258e863SDenis Kovalev 		.maxcontacts = 4 },
312f5ff4e1eSXianhan Yu 	{ .name	= MT_CLS_GENERALTOUCH_TWOFINGERS,
313f5ff4e1eSXianhan Yu 		.quirks	= MT_QUIRK_NOT_SEEN_MEANS_UP |
314f5ff4e1eSXianhan Yu 			MT_QUIRK_VALID_IS_INRANGE |
3157b226292SLuosong 			MT_QUIRK_SLOT_IS_CONTACTID,
316f5ff4e1eSXianhan Yu 		.maxcontacts = 2
317f5ff4e1eSXianhan Yu 	},
318f5ff4e1eSXianhan Yu 	{ .name	= MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
319f5ff4e1eSXianhan Yu 		.quirks	= MT_QUIRK_NOT_SEEN_MEANS_UP |
3207b226292SLuosong 			MT_QUIRK_SLOT_IS_CONTACTID
321f5ff4e1eSXianhan Yu 	},
322043b403aSBenjamin Tissoires 
32377723e3bSHenrik Rydberg 	{ .name = MT_CLS_FLATFROG,
32477723e3bSHenrik Rydberg 		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
32577723e3bSHenrik Rydberg 			MT_QUIRK_NO_AREA,
32677723e3bSHenrik Rydberg 		.sn_move = 2048,
32777723e3bSHenrik Rydberg 		.maxcontacts = 40,
32877723e3bSHenrik Rydberg 	},
329f3287a99SBenjamin Tissoires 	{ .name = MT_CLS_LG,
330f3287a99SBenjamin Tissoires 		.quirks = MT_QUIRK_ALWAYS_VALID |
331f3287a99SBenjamin Tissoires 			MT_QUIRK_FIX_CONST_CONTACT_ID |
332f3287a99SBenjamin Tissoires 			MT_QUIRK_IGNORE_DUPLICATES |
333f3287a99SBenjamin Tissoires 			MT_QUIRK_HOVERING |
334f3287a99SBenjamin Tissoires 			MT_QUIRK_CONTACT_CNT_ACCURATE },
335957b8dffSJoão Paulo Rechi Vita 	{ .name = MT_CLS_ASUS,
336957b8dffSJoão Paulo Rechi Vita 		.quirks = MT_QUIRK_ALWAYS_VALID |
337957b8dffSJoão Paulo Rechi Vita 			MT_QUIRK_CONTACT_CNT_ACCURATE |
338957b8dffSJoão Paulo Rechi Vita 			MT_QUIRK_ASUS_CUSTOM_UP },
339da10bc25SMathieu Magnaudet 	{ .name = MT_CLS_VTL,
340da10bc25SMathieu Magnaudet 		.quirks = MT_QUIRK_ALWAYS_VALID |
341da10bc25SMathieu Magnaudet 			MT_QUIRK_CONTACT_CNT_ACCURATE |
342da10bc25SMathieu Magnaudet 			MT_QUIRK_FORCE_GET_FEATURE,
343da10bc25SMathieu Magnaudet 	},
3440e82232cSWei-Ning Huang 	{ .name = MT_CLS_GOOGLE,
3450e82232cSWei-Ning Huang 		.quirks = MT_QUIRK_ALWAYS_VALID |
3460e82232cSWei-Ning Huang 			MT_QUIRK_CONTACT_CNT_ACCURATE |
3470e82232cSWei-Ning Huang 			MT_QUIRK_SLOT_IS_CONTACTID |
3480e82232cSWei-Ning Huang 			MT_QUIRK_HOVERING
3490e82232cSWei-Ning Huang 	},
350843e475fSBenjamin Tissoires 	{ .name = MT_CLS_RAZER_BLADE_STEALTH,
351843e475fSBenjamin Tissoires 		.quirks = MT_QUIRK_ALWAYS_VALID |
352843e475fSBenjamin Tissoires 			MT_QUIRK_IGNORE_DUPLICATES |
353843e475fSBenjamin Tissoires 			MT_QUIRK_HOVERING |
354843e475fSBenjamin Tissoires 			MT_QUIRK_CONTACT_CNT_ACCURATE |
355843e475fSBenjamin Tissoires 			MT_QUIRK_WIN8_PTP_BUTTONS,
356843e475fSBenjamin Tissoires 	},
3572d93666eSBenjamin Tissoires 	{ }
3585519cab4SBenjamin Tissoires };
3595519cab4SBenjamin Tissoires 
360eec29e3dSBenjamin Tissoires static ssize_t mt_show_quirks(struct device *dev,
361eec29e3dSBenjamin Tissoires 			   struct device_attribute *attr,
362eec29e3dSBenjamin Tissoires 			   char *buf)
363eec29e3dSBenjamin Tissoires {
364ee79a8f8SGeliang Tang 	struct hid_device *hdev = to_hid_device(dev);
365eec29e3dSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
366eec29e3dSBenjamin Tissoires 
367eec29e3dSBenjamin Tissoires 	return sprintf(buf, "%u\n", td->mtclass.quirks);
368eec29e3dSBenjamin Tissoires }
369eec29e3dSBenjamin Tissoires 
370eec29e3dSBenjamin Tissoires static ssize_t mt_set_quirks(struct device *dev,
371eec29e3dSBenjamin Tissoires 			  struct device_attribute *attr,
372eec29e3dSBenjamin Tissoires 			  const char *buf, size_t count)
373eec29e3dSBenjamin Tissoires {
374ee79a8f8SGeliang Tang 	struct hid_device *hdev = to_hid_device(dev);
375eec29e3dSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
376f146d1c4SBenjamin Tissoires 	struct mt_application *application;
377eec29e3dSBenjamin Tissoires 
378eec29e3dSBenjamin Tissoires 	unsigned long val;
379eec29e3dSBenjamin Tissoires 
380eec29e3dSBenjamin Tissoires 	if (kstrtoul(buf, 0, &val))
381eec29e3dSBenjamin Tissoires 		return -EINVAL;
382eec29e3dSBenjamin Tissoires 
383eec29e3dSBenjamin Tissoires 	td->mtclass.quirks = val;
384eec29e3dSBenjamin Tissoires 
385f146d1c4SBenjamin Tissoires 	list_for_each_entry(application, &td->applications, list) {
3863ceb3826SBenjamin Tissoires 		application->quirks = val;
3873ceb3826SBenjamin Tissoires 		if (!application->have_contact_count)
3883ceb3826SBenjamin Tissoires 			application->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
389f146d1c4SBenjamin Tissoires 	}
390f146d1c4SBenjamin Tissoires 
391eec29e3dSBenjamin Tissoires 	return count;
392eec29e3dSBenjamin Tissoires }
393eec29e3dSBenjamin Tissoires 
394eec29e3dSBenjamin Tissoires static DEVICE_ATTR(quirks, S_IWUSR | S_IRUGO, mt_show_quirks, mt_set_quirks);
395eec29e3dSBenjamin Tissoires 
396eec29e3dSBenjamin Tissoires static struct attribute *sysfs_attrs[] = {
397eec29e3dSBenjamin Tissoires 	&dev_attr_quirks.attr,
398eec29e3dSBenjamin Tissoires 	NULL
399eec29e3dSBenjamin Tissoires };
400eec29e3dSBenjamin Tissoires 
4019182fb98SArvind Yadav static const struct attribute_group mt_attribute_group = {
402eec29e3dSBenjamin Tissoires 	.attrs = sysfs_attrs
403eec29e3dSBenjamin Tissoires };
404eec29e3dSBenjamin Tissoires 
4056d4f5440SMika Westerberg static void mt_get_feature(struct hid_device *hdev, struct hid_report *report)
4066d4f5440SMika Westerberg {
4073064a03bSAaron Ma 	int ret;
4083064a03bSAaron Ma 	u32 size = hid_report_len(report);
4096d4f5440SMika Westerberg 	u8 *buf;
4106d4f5440SMika Westerberg 
4116d4f5440SMika Westerberg 	/*
412b897f6dbSBenjamin Tissoires 	 * Do not fetch the feature report if the device has been explicitly
413b897f6dbSBenjamin Tissoires 	 * marked as non-capable.
4146d4f5440SMika Westerberg 	 */
415adaabbf4SBenjamin Tissoires 	if (hdev->quirks & HID_QUIRK_NO_INIT_REPORTS)
4166d4f5440SMika Westerberg 		return;
4176d4f5440SMika Westerberg 
4186d4f5440SMika Westerberg 	buf = hid_alloc_report_buf(report, GFP_KERNEL);
4196d4f5440SMika Westerberg 	if (!buf)
4206d4f5440SMika Westerberg 		return;
4216d4f5440SMika Westerberg 
4226d4f5440SMika Westerberg 	ret = hid_hw_raw_request(hdev, report->id, buf, size,
4236d4f5440SMika Westerberg 				 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
4246d4f5440SMika Westerberg 	if (ret < 0) {
4256d4f5440SMika Westerberg 		dev_warn(&hdev->dev, "failed to fetch feature %d\n",
4266d4f5440SMika Westerberg 			 report->id);
4276d4f5440SMika Westerberg 	} else {
4286d4f5440SMika Westerberg 		ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf,
4296d4f5440SMika Westerberg 					   size, 0);
4306d4f5440SMika Westerberg 		if (ret)
4316d4f5440SMika Westerberg 			dev_warn(&hdev->dev, "failed to report feature\n");
4326d4f5440SMika Westerberg 	}
4336d4f5440SMika Westerberg 
4346d4f5440SMika Westerberg 	kfree(buf);
4356d4f5440SMika Westerberg }
4366d4f5440SMika Westerberg 
437f635bd11SHenrik Rydberg static void mt_feature_mapping(struct hid_device *hdev,
4385519cab4SBenjamin Tissoires 		struct hid_field *field, struct hid_usage *usage)
4395519cab4SBenjamin Tissoires {
4405519cab4SBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
4419498f954SBenjamin Tissoires 
4429498f954SBenjamin Tissoires 	switch (usage->hid) {
4439498f954SBenjamin Tissoires 	case HID_DG_CONTACTMAX:
4446d4f5440SMika Westerberg 		mt_get_feature(hdev, field->report);
4456d4f5440SMika Westerberg 
4469498f954SBenjamin Tissoires 		td->maxcontacts = field->value[0];
447afbcb04cSBenjamin Tissoires 		if (!td->maxcontacts &&
448afbcb04cSBenjamin Tissoires 		    field->logical_maximum <= MT_MAX_MAXCONTACT)
449afbcb04cSBenjamin Tissoires 			td->maxcontacts = field->logical_maximum;
450eec29e3dSBenjamin Tissoires 		if (td->mtclass.maxcontacts)
4519498f954SBenjamin Tissoires 			/* check if the maxcontacts is given by the class */
452eec29e3dSBenjamin Tissoires 			td->maxcontacts = td->mtclass.maxcontacts;
4539498f954SBenjamin Tissoires 
4549498f954SBenjamin Tissoires 		break;
4552c6e0277SSeth Forshee 	case HID_DG_BUTTONTYPE:
4562c6e0277SSeth Forshee 		if (usage->usage_index >= field->report_count) {
4572c6e0277SSeth Forshee 			dev_err(&hdev->dev, "HID_DG_BUTTONTYPE out of range\n");
4582c6e0277SSeth Forshee 			break;
4592c6e0277SSeth Forshee 		}
4602c6e0277SSeth Forshee 
4616d4f5440SMika Westerberg 		mt_get_feature(hdev, field->report);
4622c6e0277SSeth Forshee 		if (field->value[usage->usage_index] == MT_BUTTONTYPE_CLICKPAD)
4632c6e0277SSeth Forshee 			td->is_buttonpad = true;
4642c6e0277SSeth Forshee 
4652c6e0277SSeth Forshee 		break;
46645c5c682SBenjamin Tissoires 	case 0xff0000c5:
46745c5c682SBenjamin Tissoires 		/* Retrieve the Win8 blob once to enable some devices */
46845c5c682SBenjamin Tissoires 		if (usage->usage_index == 0)
46945c5c682SBenjamin Tissoires 			mt_get_feature(hdev, field->report);
47045c5c682SBenjamin Tissoires 		break;
4715519cab4SBenjamin Tissoires 	}
4725519cab4SBenjamin Tissoires }
4735519cab4SBenjamin Tissoires 
4745519cab4SBenjamin Tissoires static void set_abs(struct input_dev *input, unsigned int code,
4755519cab4SBenjamin Tissoires 		struct hid_field *field, int snratio)
4765519cab4SBenjamin Tissoires {
4775519cab4SBenjamin Tissoires 	int fmin = field->logical_minimum;
4785519cab4SBenjamin Tissoires 	int fmax = field->logical_maximum;
4795519cab4SBenjamin Tissoires 	int fuzz = snratio ? (fmax - fmin) / snratio : 0;
4805519cab4SBenjamin Tissoires 	input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
48137cf6e6fSBenjamin Tissoires 	input_abs_set_res(input, code, hidinput_calc_abs_res(field, code));
4825519cab4SBenjamin Tissoires }
4835519cab4SBenjamin Tissoires 
484*01eaac7eSBenjamin Tissoires static struct mt_usages *mt_allocate_usage(struct hid_device *hdev,
485*01eaac7eSBenjamin Tissoires 					   struct mt_application *application)
486*01eaac7eSBenjamin Tissoires {
487*01eaac7eSBenjamin Tissoires 	struct mt_usages *usage;
488*01eaac7eSBenjamin Tissoires 
489*01eaac7eSBenjamin Tissoires 	usage = devm_kzalloc(&hdev->dev, sizeof(*usage), GFP_KERNEL);
490*01eaac7eSBenjamin Tissoires 	if (!usage)
491*01eaac7eSBenjamin Tissoires 		return NULL;
492*01eaac7eSBenjamin Tissoires 
493*01eaac7eSBenjamin Tissoires 	/* set some defaults so we do not need to check for null pointers */
494*01eaac7eSBenjamin Tissoires 	usage->x = DEFAULT_ZERO;
495*01eaac7eSBenjamin Tissoires 	usage->y = DEFAULT_ZERO;
496*01eaac7eSBenjamin Tissoires 	usage->cx = DEFAULT_ZERO;
497*01eaac7eSBenjamin Tissoires 	usage->cy = DEFAULT_ZERO;
498*01eaac7eSBenjamin Tissoires 	usage->p = DEFAULT_ZERO;
499*01eaac7eSBenjamin Tissoires 	usage->w = DEFAULT_ZERO;
500*01eaac7eSBenjamin Tissoires 	usage->h = DEFAULT_ZERO;
501*01eaac7eSBenjamin Tissoires 	usage->a = DEFAULT_ZERO;
502*01eaac7eSBenjamin Tissoires 	usage->contactid = DEFAULT_ZERO;
503*01eaac7eSBenjamin Tissoires 	usage->tip_state = DEFAULT_FALSE;
504*01eaac7eSBenjamin Tissoires 	usage->inrange_state = DEFAULT_FALSE;
505*01eaac7eSBenjamin Tissoires 	usage->confidence_state = DEFAULT_TRUE;
506*01eaac7eSBenjamin Tissoires 
507*01eaac7eSBenjamin Tissoires 	list_add_tail(&usage->list, &application->mt_usages);
508*01eaac7eSBenjamin Tissoires 
509*01eaac7eSBenjamin Tissoires 	return usage;
510*01eaac7eSBenjamin Tissoires }
511*01eaac7eSBenjamin Tissoires 
512f146d1c4SBenjamin Tissoires static struct mt_application *mt_allocate_application(struct mt_device *td,
513f146d1c4SBenjamin Tissoires 						      unsigned int application)
514f146d1c4SBenjamin Tissoires {
515f146d1c4SBenjamin Tissoires 	struct mt_application *mt_application;
516f146d1c4SBenjamin Tissoires 
517f146d1c4SBenjamin Tissoires 	mt_application = devm_kzalloc(&td->hdev->dev, sizeof(*mt_application),
518f146d1c4SBenjamin Tissoires 				      GFP_KERNEL);
519f146d1c4SBenjamin Tissoires 	if (!mt_application)
520f146d1c4SBenjamin Tissoires 		return NULL;
521f146d1c4SBenjamin Tissoires 
522f146d1c4SBenjamin Tissoires 	mt_application->application = application;
523*01eaac7eSBenjamin Tissoires 	INIT_LIST_HEAD(&mt_application->mt_usages);
524f146d1c4SBenjamin Tissoires 
525f146d1c4SBenjamin Tissoires 	if (application == HID_DG_TOUCHSCREEN)
526f146d1c4SBenjamin Tissoires 		mt_application->mt_flags |= INPUT_MT_DIRECT;
527f146d1c4SBenjamin Tissoires 
528f146d1c4SBenjamin Tissoires 	/*
529f146d1c4SBenjamin Tissoires 	 * Model touchscreens providing buttons as touchpads.
530f146d1c4SBenjamin Tissoires 	 */
531f146d1c4SBenjamin Tissoires 	if (application == HID_DG_TOUCHPAD) {
532f146d1c4SBenjamin Tissoires 		mt_application->mt_flags |= INPUT_MT_POINTER;
533f146d1c4SBenjamin Tissoires 		td->inputmode_value = MT_INPUTMODE_TOUCHPAD;
534f146d1c4SBenjamin Tissoires 	}
535f146d1c4SBenjamin Tissoires 
536*01eaac7eSBenjamin Tissoires 	mt_application->scantime = DEFAULT_ZERO;
537*01eaac7eSBenjamin Tissoires 	mt_application->raw_cc = DEFAULT_ZERO;
5383ceb3826SBenjamin Tissoires 	mt_application->quirks = td->mtclass.quirks;
539f146d1c4SBenjamin Tissoires 
540f146d1c4SBenjamin Tissoires 	list_add_tail(&mt_application->list, &td->applications);
541f146d1c4SBenjamin Tissoires 
542f146d1c4SBenjamin Tissoires 	return mt_application;
543f146d1c4SBenjamin Tissoires }
544f146d1c4SBenjamin Tissoires 
545f146d1c4SBenjamin Tissoires static struct mt_application *mt_find_application(struct mt_device *td,
546f146d1c4SBenjamin Tissoires 						  unsigned int application)
547f146d1c4SBenjamin Tissoires {
548f146d1c4SBenjamin Tissoires 	struct mt_application *tmp, *mt_application = NULL;
549f146d1c4SBenjamin Tissoires 
550f146d1c4SBenjamin Tissoires 	list_for_each_entry(tmp, &td->applications, list) {
551f146d1c4SBenjamin Tissoires 		if (application == tmp->application) {
552f146d1c4SBenjamin Tissoires 			mt_application = tmp;
553f146d1c4SBenjamin Tissoires 			break;
554f146d1c4SBenjamin Tissoires 		}
555f146d1c4SBenjamin Tissoires 	}
556f146d1c4SBenjamin Tissoires 
557f146d1c4SBenjamin Tissoires 	if (!mt_application)
558f146d1c4SBenjamin Tissoires 		mt_application = mt_allocate_application(td, application);
559f146d1c4SBenjamin Tissoires 
560f146d1c4SBenjamin Tissoires 	return mt_application;
561f146d1c4SBenjamin Tissoires }
562f146d1c4SBenjamin Tissoires 
5638dfe14b3SBenjamin Tissoires static struct mt_report_data *mt_allocate_report_data(struct mt_device *td,
5648dfe14b3SBenjamin Tissoires 						      struct hid_report *report)
5658dfe14b3SBenjamin Tissoires {
5668dfe14b3SBenjamin Tissoires 	struct mt_report_data *rdata;
5678dfe14b3SBenjamin Tissoires 	struct hid_field *field;
5688dfe14b3SBenjamin Tissoires 	int r, n;
5698dfe14b3SBenjamin Tissoires 
5708dfe14b3SBenjamin Tissoires 	rdata = devm_kzalloc(&td->hdev->dev, sizeof(*rdata), GFP_KERNEL);
5718dfe14b3SBenjamin Tissoires 	if (!rdata)
5728dfe14b3SBenjamin Tissoires 		return NULL;
5738dfe14b3SBenjamin Tissoires 
5748dfe14b3SBenjamin Tissoires 	rdata->report = report;
5758dfe14b3SBenjamin Tissoires 	rdata->application = mt_find_application(td, report->application);
5768dfe14b3SBenjamin Tissoires 
5778dfe14b3SBenjamin Tissoires 	if (!rdata->application) {
5788dfe14b3SBenjamin Tissoires 		devm_kfree(&td->hdev->dev, rdata);
5798dfe14b3SBenjamin Tissoires 		return NULL;
5808dfe14b3SBenjamin Tissoires 	}
5818dfe14b3SBenjamin Tissoires 
5828dfe14b3SBenjamin Tissoires 	for (r = 0; r < report->maxfield; r++) {
5838dfe14b3SBenjamin Tissoires 		field = report->field[r];
5848dfe14b3SBenjamin Tissoires 
5858dfe14b3SBenjamin Tissoires 		if (!(HID_MAIN_ITEM_VARIABLE & field->flags))
5868dfe14b3SBenjamin Tissoires 			continue;
5878dfe14b3SBenjamin Tissoires 
5888dfe14b3SBenjamin Tissoires 		for (n = 0; n < field->report_count; n++) {
5898dfe14b3SBenjamin Tissoires 			if (field->usage[n].hid == HID_DG_CONTACTID)
5908dfe14b3SBenjamin Tissoires 				rdata->is_mt_collection = true;
5918dfe14b3SBenjamin Tissoires 		}
5928dfe14b3SBenjamin Tissoires 	}
5938dfe14b3SBenjamin Tissoires 
5948dfe14b3SBenjamin Tissoires 	list_add_tail(&rdata->list, &td->reports);
5958dfe14b3SBenjamin Tissoires 
5968dfe14b3SBenjamin Tissoires 	return rdata;
5978dfe14b3SBenjamin Tissoires }
5988dfe14b3SBenjamin Tissoires 
5998dfe14b3SBenjamin Tissoires static struct mt_report_data *mt_find_report_data(struct mt_device *td,
6008dfe14b3SBenjamin Tissoires 						  struct hid_report *report)
6018dfe14b3SBenjamin Tissoires {
6028dfe14b3SBenjamin Tissoires 	struct mt_report_data *tmp, *rdata = NULL;
6038dfe14b3SBenjamin Tissoires 
6048dfe14b3SBenjamin Tissoires 	list_for_each_entry(tmp, &td->reports, list) {
6058dfe14b3SBenjamin Tissoires 		if (report == tmp->report) {
6068dfe14b3SBenjamin Tissoires 			rdata = tmp;
6078dfe14b3SBenjamin Tissoires 			break;
6088dfe14b3SBenjamin Tissoires 		}
6098dfe14b3SBenjamin Tissoires 	}
6108dfe14b3SBenjamin Tissoires 
6118dfe14b3SBenjamin Tissoires 	if (!rdata)
6128dfe14b3SBenjamin Tissoires 		rdata = mt_allocate_report_data(td, report);
6138dfe14b3SBenjamin Tissoires 
6148dfe14b3SBenjamin Tissoires 	return rdata;
6158dfe14b3SBenjamin Tissoires }
6168dfe14b3SBenjamin Tissoires 
617*01eaac7eSBenjamin Tissoires static void mt_store_field(struct hid_device *hdev,
618*01eaac7eSBenjamin Tissoires 			   struct mt_application *application,
619*01eaac7eSBenjamin Tissoires 			   __s32 *value,
620*01eaac7eSBenjamin Tissoires 			   size_t offset)
621ed9d5c96SBenjamin Tissoires {
622*01eaac7eSBenjamin Tissoires 	struct mt_usages *usage;
623*01eaac7eSBenjamin Tissoires 	__s32 **target;
6243ac36d15SBenjamin Tissoires 
625*01eaac7eSBenjamin Tissoires 	if (list_empty(&application->mt_usages))
626*01eaac7eSBenjamin Tissoires 		usage = mt_allocate_usage(hdev, application);
627*01eaac7eSBenjamin Tissoires 	else
628*01eaac7eSBenjamin Tissoires 		usage = list_last_entry(&application->mt_usages,
629*01eaac7eSBenjamin Tissoires 					struct mt_usages,
630*01eaac7eSBenjamin Tissoires 					list);
631*01eaac7eSBenjamin Tissoires 
632*01eaac7eSBenjamin Tissoires 	if (!usage)
6333ac36d15SBenjamin Tissoires 		return;
6343ac36d15SBenjamin Tissoires 
635*01eaac7eSBenjamin Tissoires 	target = (__s32 **)((char *)usage + offset);
636*01eaac7eSBenjamin Tissoires 
637*01eaac7eSBenjamin Tissoires 	/* the value has already been filled, create a new slot */
638*01eaac7eSBenjamin Tissoires 	if (*target != DEFAULT_TRUE &&
639*01eaac7eSBenjamin Tissoires 	    *target != DEFAULT_FALSE &&
640*01eaac7eSBenjamin Tissoires 	    *target != DEFAULT_ZERO) {
641*01eaac7eSBenjamin Tissoires 		usage = mt_allocate_usage(hdev, application);
642*01eaac7eSBenjamin Tissoires 		if (!usage)
643*01eaac7eSBenjamin Tissoires 			return;
644*01eaac7eSBenjamin Tissoires 
645*01eaac7eSBenjamin Tissoires 		target = (__s32 **)((char *)usage + offset);
646ed9d5c96SBenjamin Tissoires 	}
647ed9d5c96SBenjamin Tissoires 
648*01eaac7eSBenjamin Tissoires 	*target = value;
649*01eaac7eSBenjamin Tissoires }
650*01eaac7eSBenjamin Tissoires 
651*01eaac7eSBenjamin Tissoires #define MT_STORE_FIELD(__name)						\
652*01eaac7eSBenjamin Tissoires 	mt_store_field(hdev, app,					\
653*01eaac7eSBenjamin Tissoires 		       &field->value[usage->usage_index],		\
654*01eaac7eSBenjamin Tissoires 		       offsetof(struct mt_usages, __name))
655*01eaac7eSBenjamin Tissoires 
656a69c5f8bSBenjamin Tissoires static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
6575519cab4SBenjamin Tissoires 		struct hid_field *field, struct hid_usage *usage,
658f146d1c4SBenjamin Tissoires 		unsigned long **bit, int *max, struct mt_application *app)
6595519cab4SBenjamin Tissoires {
6605519cab4SBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
661eec29e3dSBenjamin Tissoires 	struct mt_class *cls = &td->mtclass;
662c2ef8f21SBenjamin Tissoires 	int code;
663349fd670SBenjamin Tissoires 	struct hid_usage *prev_usage = NULL;
6644875ac11SRichard Nauber 
66576f5902aSHenrik Rydberg 	/*
66676f5902aSHenrik Rydberg 	 * Model touchscreens providing buttons as touchpads.
667c2ef8f21SBenjamin Tissoires 	 */
668f146d1c4SBenjamin Tissoires 	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {
669f146d1c4SBenjamin Tissoires 		app->mt_flags |= INPUT_MT_POINTER;
6709abebedbSAndrew Duggan 		td->inputmode_value = MT_INPUTMODE_TOUCHPAD;
6719abebedbSAndrew Duggan 	}
672c2ef8f21SBenjamin Tissoires 
673015fdaa9SBenjamin Tissoires 	/* count the buttons on touchpads */
674015fdaa9SBenjamin Tissoires 	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON)
675f146d1c4SBenjamin Tissoires 		app->buttons_count++;
676015fdaa9SBenjamin Tissoires 
677349fd670SBenjamin Tissoires 	if (usage->usage_index)
678349fd670SBenjamin Tissoires 		prev_usage = &field->usage[usage->usage_index - 1];
679349fd670SBenjamin Tissoires 
6805519cab4SBenjamin Tissoires 	switch (usage->hid & HID_USAGE_PAGE) {
6815519cab4SBenjamin Tissoires 
6825519cab4SBenjamin Tissoires 	case HID_UP_GENDESK:
6835519cab4SBenjamin Tissoires 		switch (usage->hid) {
6845519cab4SBenjamin Tissoires 		case HID_GD_X:
685*01eaac7eSBenjamin Tissoires 			if (prev_usage && (prev_usage->hid == usage->hid)) {
686f146d1c4SBenjamin Tissoires 				code = ABS_MT_TOOL_X;
687*01eaac7eSBenjamin Tissoires 				MT_STORE_FIELD(cx);
688*01eaac7eSBenjamin Tissoires 			} else {
689f146d1c4SBenjamin Tissoires 				code = ABS_MT_POSITION_X;
690*01eaac7eSBenjamin Tissoires 				MT_STORE_FIELD(x);
691*01eaac7eSBenjamin Tissoires 			}
692349fd670SBenjamin Tissoires 
693f146d1c4SBenjamin Tissoires 			set_abs(hi->input, code, field, cls->sn_move);
694*01eaac7eSBenjamin Tissoires 
6955519cab4SBenjamin Tissoires 			return 1;
6965519cab4SBenjamin Tissoires 		case HID_GD_Y:
697*01eaac7eSBenjamin Tissoires 			if (prev_usage && (prev_usage->hid == usage->hid)) {
698f146d1c4SBenjamin Tissoires 				code = ABS_MT_TOOL_Y;
699*01eaac7eSBenjamin Tissoires 				MT_STORE_FIELD(cy);
700*01eaac7eSBenjamin Tissoires 			} else {
701f146d1c4SBenjamin Tissoires 				code = ABS_MT_POSITION_Y;
702*01eaac7eSBenjamin Tissoires 				MT_STORE_FIELD(y);
703*01eaac7eSBenjamin Tissoires 			}
704349fd670SBenjamin Tissoires 
705f146d1c4SBenjamin Tissoires 			set_abs(hi->input, code, field, cls->sn_move);
706*01eaac7eSBenjamin Tissoires 
7075519cab4SBenjamin Tissoires 			return 1;
7085519cab4SBenjamin Tissoires 		}
7095519cab4SBenjamin Tissoires 		return 0;
7105519cab4SBenjamin Tissoires 
7115519cab4SBenjamin Tissoires 	case HID_UP_DIGITIZER:
7125519cab4SBenjamin Tissoires 		switch (usage->hid) {
7135519cab4SBenjamin Tissoires 		case HID_DG_INRANGE:
7143ceb3826SBenjamin Tissoires 			if (app->quirks & MT_QUIRK_HOVERING) {
7159b3bb9b8SBenjamin Tissoires 				input_set_abs_params(hi->input,
7169b3bb9b8SBenjamin Tissoires 					ABS_MT_DISTANCE, 0, 1, 0, 0);
7179b3bb9b8SBenjamin Tissoires 			}
718*01eaac7eSBenjamin Tissoires 			MT_STORE_FIELD(inrange_state);
7195519cab4SBenjamin Tissoires 			return 1;
7205519cab4SBenjamin Tissoires 		case HID_DG_CONFIDENCE:
721504c932cSMasaki Ota 			if ((cls->name == MT_CLS_WIN_8 ||
722504c932cSMasaki Ota 				cls->name == MT_CLS_WIN_8_DUAL) &&
7236dd2e27aSAllen Hung 				field->application == HID_DG_TOUCHPAD)
7243ceb3826SBenjamin Tissoires 				app->quirks |= MT_QUIRK_CONFIDENCE;
725*01eaac7eSBenjamin Tissoires 			MT_STORE_FIELD(confidence_state);
7265519cab4SBenjamin Tissoires 			return 1;
7275519cab4SBenjamin Tissoires 		case HID_DG_TIPSWITCH:
7285519cab4SBenjamin Tissoires 			input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
729*01eaac7eSBenjamin Tissoires 			MT_STORE_FIELD(tip_state);
7305519cab4SBenjamin Tissoires 			return 1;
7315519cab4SBenjamin Tissoires 		case HID_DG_CONTACTID:
732*01eaac7eSBenjamin Tissoires 			MT_STORE_FIELD(contactid);
733f146d1c4SBenjamin Tissoires 			app->touches_by_report++;
7345519cab4SBenjamin Tissoires 			return 1;
7355519cab4SBenjamin Tissoires 		case HID_DG_WIDTH:
7363ceb3826SBenjamin Tissoires 			if (!(app->quirks & MT_QUIRK_NO_AREA))
737f786bba4SBenjamin Tissoires 				set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
738f786bba4SBenjamin Tissoires 					cls->sn_width);
739*01eaac7eSBenjamin Tissoires 			MT_STORE_FIELD(w);
7405519cab4SBenjamin Tissoires 			return 1;
7415519cab4SBenjamin Tissoires 		case HID_DG_HEIGHT:
7423ceb3826SBenjamin Tissoires 			if (!(app->quirks & MT_QUIRK_NO_AREA)) {
743f786bba4SBenjamin Tissoires 				set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
744f786bba4SBenjamin Tissoires 					cls->sn_height);
74500720277SWei-Ning Huang 
74600720277SWei-Ning Huang 				/*
74700720277SWei-Ning Huang 				 * Only set ABS_MT_ORIENTATION if it is not
74800720277SWei-Ning Huang 				 * already set by the HID_DG_AZIMUTH usage.
74900720277SWei-Ning Huang 				 */
75000720277SWei-Ning Huang 				if (!test_bit(ABS_MT_ORIENTATION,
75100720277SWei-Ning Huang 						hi->input->absbit))
7521e648a13SBenjamin Tissoires 					input_set_abs_params(hi->input,
7531e648a13SBenjamin Tissoires 						ABS_MT_ORIENTATION, 0, 1, 0, 0);
75477723e3bSHenrik Rydberg 			}
755*01eaac7eSBenjamin Tissoires 			MT_STORE_FIELD(h);
7565519cab4SBenjamin Tissoires 			return 1;
7575519cab4SBenjamin Tissoires 		case HID_DG_TIPPRESSURE:
7585519cab4SBenjamin Tissoires 			set_abs(hi->input, ABS_MT_PRESSURE, field,
7595519cab4SBenjamin Tissoires 				cls->sn_pressure);
760*01eaac7eSBenjamin Tissoires 			MT_STORE_FIELD(p);
7615519cab4SBenjamin Tissoires 			return 1;
76229cc309dSNicolas Boichat 		case HID_DG_SCANTIME:
76329cc309dSNicolas Boichat 			input_set_capability(hi->input, EV_MSC, MSC_TIMESTAMP);
764*01eaac7eSBenjamin Tissoires 			app->scantime = &field->value[usage->usage_index];
765*01eaac7eSBenjamin Tissoires 			app->scantime_logical_max = field->logical_maximum;
76629cc309dSNicolas Boichat 			return 1;
7675519cab4SBenjamin Tissoires 		case HID_DG_CONTACTCOUNT:
768*01eaac7eSBenjamin Tissoires 			app->have_contact_count = true;
769*01eaac7eSBenjamin Tissoires 			app->raw_cc = &field->value[usage->usage_index];
7705519cab4SBenjamin Tissoires 			return 1;
77100720277SWei-Ning Huang 		case HID_DG_AZIMUTH:
77200720277SWei-Ning Huang 			/*
77300720277SWei-Ning Huang 			 * Azimuth has the range of [0, MAX) representing a full
77400720277SWei-Ning Huang 			 * revolution. Set ABS_MT_ORIENTATION to a quarter of
77500720277SWei-Ning Huang 			 * MAX according the definition of ABS_MT_ORIENTATION
77600720277SWei-Ning Huang 			 */
77700720277SWei-Ning Huang 			input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
77800720277SWei-Ning Huang 				-field->logical_maximum / 4,
77900720277SWei-Ning Huang 				field->logical_maximum / 4,
78000720277SWei-Ning Huang 				cls->sn_move ?
78100720277SWei-Ning Huang 				field->logical_maximum / cls->sn_move : 0, 0);
782*01eaac7eSBenjamin Tissoires 			MT_STORE_FIELD(a);
78300720277SWei-Ning Huang 			return 1;
7845519cab4SBenjamin Tissoires 		case HID_DG_CONTACTMAX:
785*01eaac7eSBenjamin Tissoires 			/* contact max are global to the report */
7865519cab4SBenjamin Tissoires 			return -1;
787c2ef8f21SBenjamin Tissoires 		case HID_DG_TOUCH:
788c2ef8f21SBenjamin Tissoires 			/* Legacy devices use TIPSWITCH and not TOUCH.
789c2ef8f21SBenjamin Tissoires 			 * Let's just ignore this field. */
790c2ef8f21SBenjamin Tissoires 			return -1;
79165b258e9SAlan Cox 		}
7925519cab4SBenjamin Tissoires 		/* let hid-input decide for the others */
7935519cab4SBenjamin Tissoires 		return 0;
7945519cab4SBenjamin Tissoires 
795c2ef8f21SBenjamin Tissoires 	case HID_UP_BUTTON:
796c2ef8f21SBenjamin Tissoires 		code = BTN_MOUSE + ((usage->hid - 1) & HID_USAGE);
797594312b8SBenjamin Tissoires 		/*
798594312b8SBenjamin Tissoires 		 * MS PTP spec says that external buttons left and right have
799594312b8SBenjamin Tissoires 		 * usages 2 and 3.
800594312b8SBenjamin Tissoires 		 */
8013ceb3826SBenjamin Tissoires 		if ((app->quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
802594312b8SBenjamin Tissoires 		    field->application == HID_DG_TOUCHPAD &&
803594312b8SBenjamin Tissoires 		    (usage->hid & HID_USAGE) > 1)
804594312b8SBenjamin Tissoires 			code--;
805c2ef8f21SBenjamin Tissoires 		hid_map_usage(hi, usage, bit, max, EV_KEY, code);
806c2ef8f21SBenjamin Tissoires 		input_set_capability(hi->input, EV_KEY, code);
807c2ef8f21SBenjamin Tissoires 		return 1;
808c2ef8f21SBenjamin Tissoires 
8095519cab4SBenjamin Tissoires 	case 0xff000000:
8105519cab4SBenjamin Tissoires 		/* we do not want to map these: no input-oriented meaning */
8115519cab4SBenjamin Tissoires 		return -1;
8125519cab4SBenjamin Tissoires 	}
8135519cab4SBenjamin Tissoires 
8145519cab4SBenjamin Tissoires 	return 0;
8155519cab4SBenjamin Tissoires }
8165519cab4SBenjamin Tissoires 
817f146d1c4SBenjamin Tissoires static int mt_compute_slot(struct mt_device *td, struct mt_application *app,
818*01eaac7eSBenjamin Tissoires 			   struct mt_usages *slot,
819f146d1c4SBenjamin Tissoires 			   struct input_dev *input)
8205519cab4SBenjamin Tissoires {
8213ceb3826SBenjamin Tissoires 	__s32 quirks = app->quirks;
8225519cab4SBenjamin Tissoires 
8232d93666eSBenjamin Tissoires 	if (quirks & MT_QUIRK_SLOT_IS_CONTACTID)
824*01eaac7eSBenjamin Tissoires 		return *slot->contactid;
8255519cab4SBenjamin Tissoires 
8262d93666eSBenjamin Tissoires 	if (quirks & MT_QUIRK_CYPRESS)
827*01eaac7eSBenjamin Tissoires 		return cypress_compute_slot(app, slot);
828a3b5e577SBenjamin Tissoires 
8292d93666eSBenjamin Tissoires 	if (quirks & MT_QUIRK_SLOT_IS_CONTACTNUMBER)
830f146d1c4SBenjamin Tissoires 		return app->num_received;
8315572da08SBenjamin Tissoires 
8324a6ee685SBenjamin Tissoires 	if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE)
833*01eaac7eSBenjamin Tissoires 		return *slot->contactid - 1;
8344a6ee685SBenjamin Tissoires 
835*01eaac7eSBenjamin Tissoires 	return input_mt_get_slot_by_key(input, *slot->contactid);
8363e1b5015SHenrik Rydberg }
8373e1b5015SHenrik Rydberg 
8383e1b5015SHenrik Rydberg /*
8393e1b5015SHenrik Rydberg  * this function is called when a whole packet has been received and processed,
8403e1b5015SHenrik Rydberg  * so that it can decide what to send to the input layer.
8413e1b5015SHenrik Rydberg  */
842f146d1c4SBenjamin Tissoires static void mt_sync_frame(struct mt_device *td, struct mt_application *app,
843f146d1c4SBenjamin Tissoires 			  struct input_dev *input)
8443e1b5015SHenrik Rydberg {
8453ceb3826SBenjamin Tissoires 	if (app->quirks & MT_QUIRK_WIN8_PTP_BUTTONS)
846f146d1c4SBenjamin Tissoires 		input_event(input, EV_KEY, BTN_LEFT, app->left_button_state);
847127e71bdSHans de Goede 
84876f5902aSHenrik Rydberg 	input_mt_sync_frame(input);
849f146d1c4SBenjamin Tissoires 	input_event(input, EV_MSC, MSC_TIMESTAMP, app->timestamp);
8505519cab4SBenjamin Tissoires 	input_sync(input);
851f146d1c4SBenjamin Tissoires 	app->num_received = 0;
852f146d1c4SBenjamin Tissoires 	app->left_button_state = 0;
853f146d1c4SBenjamin Tissoires 
85496098274SBenjamin Tissoires 	if (test_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags))
85596098274SBenjamin Tissoires 		set_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags);
85696098274SBenjamin Tissoires 	else
85796098274SBenjamin Tissoires 		clear_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags);
85896098274SBenjamin Tissoires 	clear_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags);
8595519cab4SBenjamin Tissoires }
8605519cab4SBenjamin Tissoires 
861*01eaac7eSBenjamin Tissoires static int mt_compute_timestamp(struct mt_application *app, __s32 value)
86229cc309dSNicolas Boichat {
863f146d1c4SBenjamin Tissoires 	long delta = value - app->prev_scantime;
864f146d1c4SBenjamin Tissoires 	unsigned long jdelta = jiffies_to_usecs(jiffies - app->jiffies);
86529cc309dSNicolas Boichat 
866f146d1c4SBenjamin Tissoires 	app->jiffies = jiffies;
86729cc309dSNicolas Boichat 
86829cc309dSNicolas Boichat 	if (delta < 0)
869*01eaac7eSBenjamin Tissoires 		delta += app->scantime_logical_max;
87029cc309dSNicolas Boichat 
87129cc309dSNicolas Boichat 	/* HID_DG_SCANTIME is expressed in 100us, we want it in us. */
87229cc309dSNicolas Boichat 	delta *= 100;
87329cc309dSNicolas Boichat 
87429cc309dSNicolas Boichat 	if (jdelta > MAX_TIMESTAMP_INTERVAL)
87529cc309dSNicolas Boichat 		/* No data received for a while, resync the timestamp. */
87629cc309dSNicolas Boichat 		return 0;
87729cc309dSNicolas Boichat 	else
878f146d1c4SBenjamin Tissoires 		return app->timestamp + delta;
87929cc309dSNicolas Boichat }
88029cc309dSNicolas Boichat 
881a69c5f8bSBenjamin Tissoires static int mt_touch_event(struct hid_device *hid, struct hid_field *field,
8825519cab4SBenjamin Tissoires 				struct hid_usage *usage, __s32 value)
8835519cab4SBenjamin Tissoires {
88455978fa9SBenjamin Tissoires 	/* we will handle the hidinput part later, now remains hiddev */
88555978fa9SBenjamin Tissoires 	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
88655978fa9SBenjamin Tissoires 		hid->hiddev_hid_event(hid, field, usage, value);
88755978fa9SBenjamin Tissoires 
88855978fa9SBenjamin Tissoires 	return 1;
88955978fa9SBenjamin Tissoires }
89055978fa9SBenjamin Tissoires 
891*01eaac7eSBenjamin Tissoires static int mt_process_slot(struct mt_device *td, struct input_dev *input,
892*01eaac7eSBenjamin Tissoires 			    struct mt_application *app,
893*01eaac7eSBenjamin Tissoires 			    struct mt_usages *slot)
89455978fa9SBenjamin Tissoires {
895*01eaac7eSBenjamin Tissoires 	struct input_mt *mt = input->mt;
8963ceb3826SBenjamin Tissoires 	__s32 quirks = app->quirks;
897*01eaac7eSBenjamin Tissoires 	bool valid = true;
898*01eaac7eSBenjamin Tissoires 	bool confidence_state = true;
899*01eaac7eSBenjamin Tissoires 	bool inrange_state = false;
900*01eaac7eSBenjamin Tissoires 	int active;
901*01eaac7eSBenjamin Tissoires 	int slotnum;
9025519cab4SBenjamin Tissoires 
903*01eaac7eSBenjamin Tissoires 	if (!slot)
904*01eaac7eSBenjamin Tissoires 		return -EINVAL;
905*01eaac7eSBenjamin Tissoires 
906*01eaac7eSBenjamin Tissoires 	if ((quirks & MT_QUIRK_CONTACT_CNT_ACCURATE) &&
907*01eaac7eSBenjamin Tissoires 	    app->num_received >= app->num_expected)
908*01eaac7eSBenjamin Tissoires 		return -EAGAIN;
909*01eaac7eSBenjamin Tissoires 
910*01eaac7eSBenjamin Tissoires 	if (!(quirks & MT_QUIRK_ALWAYS_VALID)) {
91120b60e6dSBenjamin Tissoires 		if (quirks & MT_QUIRK_VALID_IS_INRANGE)
912*01eaac7eSBenjamin Tissoires 			valid = *slot->inrange_state;
9132d93666eSBenjamin Tissoires 		if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
914*01eaac7eSBenjamin Tissoires 			valid = *slot->tip_state;
9152d93666eSBenjamin Tissoires 		if (quirks & MT_QUIRK_VALID_IS_CONFIDENCE)
916*01eaac7eSBenjamin Tissoires 			valid = *slot->confidence_state;
917*01eaac7eSBenjamin Tissoires 
918*01eaac7eSBenjamin Tissoires 		if (!valid)
919*01eaac7eSBenjamin Tissoires 			return 0;
920*01eaac7eSBenjamin Tissoires 	}
921*01eaac7eSBenjamin Tissoires 
922*01eaac7eSBenjamin Tissoires 	slotnum = mt_compute_slot(td, app, slot, input);
923*01eaac7eSBenjamin Tissoires 	if (slotnum < 0 || slotnum >= td->maxcontacts)
924*01eaac7eSBenjamin Tissoires 		return 0;
925*01eaac7eSBenjamin Tissoires 
926*01eaac7eSBenjamin Tissoires 	if ((quirks & MT_QUIRK_IGNORE_DUPLICATES) && mt) {
927*01eaac7eSBenjamin Tissoires 		struct input_mt_slot *i_slot = &mt->slots[slotnum];
928*01eaac7eSBenjamin Tissoires 
929*01eaac7eSBenjamin Tissoires 		if (input_mt_is_active(i_slot) &&
930*01eaac7eSBenjamin Tissoires 		    input_mt_is_used(mt, i_slot))
931*01eaac7eSBenjamin Tissoires 			return -EAGAIN;
932*01eaac7eSBenjamin Tissoires 	}
933*01eaac7eSBenjamin Tissoires 
934*01eaac7eSBenjamin Tissoires 	if (quirks & MT_QUIRK_CONFIDENCE)
935*01eaac7eSBenjamin Tissoires 		confidence_state = *slot->confidence_state;
936*01eaac7eSBenjamin Tissoires 
937*01eaac7eSBenjamin Tissoires 	if (quirks & MT_QUIRK_HOVERING)
938*01eaac7eSBenjamin Tissoires 		inrange_state = *slot->inrange_state;
939*01eaac7eSBenjamin Tissoires 
940*01eaac7eSBenjamin Tissoires 	active = (*slot->tip_state || inrange_state) && confidence_state;
941*01eaac7eSBenjamin Tissoires 
942*01eaac7eSBenjamin Tissoires 	input_mt_slot(input, slotnum);
943*01eaac7eSBenjamin Tissoires 	input_mt_report_slot_state(input, MT_TOOL_FINGER, active);
944*01eaac7eSBenjamin Tissoires 	if (active) {
945*01eaac7eSBenjamin Tissoires 		/* this finger is in proximity of the sensor */
946*01eaac7eSBenjamin Tissoires 		int wide = (*slot->w > *slot->h);
947*01eaac7eSBenjamin Tissoires 		int major = max(*slot->w, *slot->h);
948*01eaac7eSBenjamin Tissoires 		int minor = min(*slot->w, *slot->h);
949*01eaac7eSBenjamin Tissoires 		int orientation = wide;
950*01eaac7eSBenjamin Tissoires 		int max_azimuth;
951*01eaac7eSBenjamin Tissoires 		int azimuth;
952*01eaac7eSBenjamin Tissoires 
953*01eaac7eSBenjamin Tissoires 		if (slot->a != DEFAULT_ZERO) {
95400720277SWei-Ning Huang 			/*
95500720277SWei-Ning Huang 			 * Azimuth is counter-clockwise and ranges from [0, MAX)
95600720277SWei-Ning Huang 			 * (a full revolution). Convert it to clockwise ranging
95700720277SWei-Ning Huang 			 * [-MAX/2, MAX/2].
95800720277SWei-Ning Huang 			 *
95900720277SWei-Ning Huang 			 * Note that ABS_MT_ORIENTATION require us to report
96000720277SWei-Ning Huang 			 * the limit of [-MAX/4, MAX/4], but the value can go
96100720277SWei-Ning Huang 			 * out of range to [-MAX/2, MAX/2] to report an upside
96200720277SWei-Ning Huang 			 * down ellipsis.
96300720277SWei-Ning Huang 			 */
964*01eaac7eSBenjamin Tissoires 			azimuth = *slot->a;
965*01eaac7eSBenjamin Tissoires 			max_azimuth = input_abs_get_max(input,
966*01eaac7eSBenjamin Tissoires 							ABS_MT_ORIENTATION);
967*01eaac7eSBenjamin Tissoires 			if (azimuth > max_azimuth * 2)
968*01eaac7eSBenjamin Tissoires 				azimuth -= max_azimuth * 4;
969*01eaac7eSBenjamin Tissoires 			orientation = -azimuth;
970*01eaac7eSBenjamin Tissoires 		}
9715519cab4SBenjamin Tissoires 
972*01eaac7eSBenjamin Tissoires 		/*
973*01eaac7eSBenjamin Tissoires 		 * divided by two to match visual scale of touch
974*01eaac7eSBenjamin Tissoires 		 * for devices with this quirk
975*01eaac7eSBenjamin Tissoires 		 */
976*01eaac7eSBenjamin Tissoires 		if (quirks & MT_QUIRK_TOUCH_SIZE_SCALING) {
977*01eaac7eSBenjamin Tissoires 			major = major >> 1;
978*01eaac7eSBenjamin Tissoires 			minor = minor >> 1;
979*01eaac7eSBenjamin Tissoires 		}
980*01eaac7eSBenjamin Tissoires 
981*01eaac7eSBenjamin Tissoires 		input_event(input, EV_ABS, ABS_MT_POSITION_X, *slot->x);
982*01eaac7eSBenjamin Tissoires 		input_event(input, EV_ABS, ABS_MT_POSITION_Y, *slot->y);
983*01eaac7eSBenjamin Tissoires 		input_event(input, EV_ABS, ABS_MT_TOOL_X, *slot->cx);
984*01eaac7eSBenjamin Tissoires 		input_event(input, EV_ABS, ABS_MT_TOOL_Y, *slot->cy);
985*01eaac7eSBenjamin Tissoires 		input_event(input, EV_ABS, ABS_MT_DISTANCE, !*slot->tip_state);
986*01eaac7eSBenjamin Tissoires 		input_event(input, EV_ABS, ABS_MT_ORIENTATION, orientation);
987*01eaac7eSBenjamin Tissoires 		input_event(input, EV_ABS, ABS_MT_PRESSURE, *slot->p);
988*01eaac7eSBenjamin Tissoires 		input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
989*01eaac7eSBenjamin Tissoires 		input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
990*01eaac7eSBenjamin Tissoires 
991*01eaac7eSBenjamin Tissoires 		set_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags);
992*01eaac7eSBenjamin Tissoires 	}
993*01eaac7eSBenjamin Tissoires 
994*01eaac7eSBenjamin Tissoires 	return 0;
995*01eaac7eSBenjamin Tissoires }
996*01eaac7eSBenjamin Tissoires 
997*01eaac7eSBenjamin Tissoires static void mt_process_mt_event(struct hid_device *hid,
998*01eaac7eSBenjamin Tissoires 				struct mt_application *app,
999*01eaac7eSBenjamin Tissoires 				struct hid_field *field,
1000*01eaac7eSBenjamin Tissoires 				struct hid_usage *usage,
1001*01eaac7eSBenjamin Tissoires 				__s32 value,
1002*01eaac7eSBenjamin Tissoires 				bool first_packet)
1003*01eaac7eSBenjamin Tissoires {
1004*01eaac7eSBenjamin Tissoires 	__s32 quirks = app->quirks;
1005*01eaac7eSBenjamin Tissoires 	struct input_dev *input = field->hidinput->input;
1006*01eaac7eSBenjamin Tissoires 
1007*01eaac7eSBenjamin Tissoires 	if (!usage->type || !(hid->claimed & HID_CLAIMED_INPUT))
1008*01eaac7eSBenjamin Tissoires 		return;
1009*01eaac7eSBenjamin Tissoires 
1010*01eaac7eSBenjamin Tissoires 	if (quirks & MT_QUIRK_WIN8_PTP_BUTTONS) {
1011*01eaac7eSBenjamin Tissoires 
101255746d28SHans de Goede 		/*
101355746d28SHans de Goede 		 * For Win8 PTP touchpads we should only look at
1014*01eaac7eSBenjamin Tissoires 		 * non finger/touch events in the first_packet of a
1015*01eaac7eSBenjamin Tissoires 		 * (possible) multi-packet frame.
101655746d28SHans de Goede 		 */
1017*01eaac7eSBenjamin Tissoires 		if (!first_packet)
101855746d28SHans de Goede 			return;
101955746d28SHans de Goede 
1020127e71bdSHans de Goede 		/*
1021127e71bdSHans de Goede 		 * For Win8 PTP touchpads we map both the clickpad click
1022127e71bdSHans de Goede 		 * and any "external" left buttons to BTN_LEFT if a
1023127e71bdSHans de Goede 		 * device claims to have both we need to report 1 for
1024127e71bdSHans de Goede 		 * BTN_LEFT if either is pressed, so we or all values
1025127e71bdSHans de Goede 		 * together and report the result in mt_sync_frame().
1026127e71bdSHans de Goede 		 */
1027*01eaac7eSBenjamin Tissoires 		if (usage->type == EV_KEY && usage->code == BTN_LEFT) {
1028f146d1c4SBenjamin Tissoires 			app->left_button_state |= value;
1029127e71bdSHans de Goede 			return;
1030127e71bdSHans de Goede 		}
10315519cab4SBenjamin Tissoires 	}
10325519cab4SBenjamin Tissoires 
1033*01eaac7eSBenjamin Tissoires 	input_event(input, usage->type, usage->code, value);
103455978fa9SBenjamin Tissoires }
10352d93666eSBenjamin Tissoires 
10368dfe14b3SBenjamin Tissoires static void mt_touch_report(struct hid_device *hid,
10378dfe14b3SBenjamin Tissoires 			    struct mt_report_data *rdata)
103855978fa9SBenjamin Tissoires {
103955978fa9SBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hid);
10408dfe14b3SBenjamin Tissoires 	struct hid_report *report = rdata->report;
10418dfe14b3SBenjamin Tissoires 	struct mt_application *app = rdata->application;
104255978fa9SBenjamin Tissoires 	struct hid_field *field;
1043*01eaac7eSBenjamin Tissoires 	struct input_dev *input;
1044*01eaac7eSBenjamin Tissoires 	struct mt_usages *slot;
104555746d28SHans de Goede 	bool first_packet;
104655978fa9SBenjamin Tissoires 	unsigned count;
1047f146d1c4SBenjamin Tissoires 	int r, n;
1048f146d1c4SBenjamin Tissoires 	int scantime = 0;
1049f146d1c4SBenjamin Tissoires 	int contact_count = -1;
10505519cab4SBenjamin Tissoires 
10514f4001bcSBenjamin Tissoires 	/* sticky fingers release in progress, abort */
10524f4001bcSBenjamin Tissoires 	if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
10534f4001bcSBenjamin Tissoires 		return;
10544f4001bcSBenjamin Tissoires 
1055*01eaac7eSBenjamin Tissoires 	scantime = *app->scantime;
1056*01eaac7eSBenjamin Tissoires 	app->timestamp = mt_compute_timestamp(app, scantime);
1057*01eaac7eSBenjamin Tissoires 	if (app->raw_cc != DEFAULT_ZERO)
1058*01eaac7eSBenjamin Tissoires 		contact_count = *app->raw_cc;
1059*01eaac7eSBenjamin Tissoires 
1060c2517f62SBenjamin Tissoires 	/*
1061c2517f62SBenjamin Tissoires 	 * Includes multi-packet support where subsequent
1062c2517f62SBenjamin Tissoires 	 * packets are sent with zero contactcount.
1063c2517f62SBenjamin Tissoires 	 */
1064*01eaac7eSBenjamin Tissoires 	if (contact_count >= 0) {
1065af8dc4d0SHans de Goede 		/*
1066af8dc4d0SHans de Goede 		 * For Win8 PTPs the first packet (td->num_received == 0) may
1067af8dc4d0SHans de Goede 		 * have a contactcount of 0 if there only is a button event.
1068af8dc4d0SHans de Goede 		 * We double check that this is not a continuation packet
1069af8dc4d0SHans de Goede 		 * of a possible multi-packet frame be checking that the
1070af8dc4d0SHans de Goede 		 * timestamp has changed.
1071af8dc4d0SHans de Goede 		 */
10723ceb3826SBenjamin Tissoires 		if ((app->quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
1073f146d1c4SBenjamin Tissoires 		    app->num_received == 0 &&
1074f146d1c4SBenjamin Tissoires 		    app->prev_scantime != scantime)
1075f146d1c4SBenjamin Tissoires 			app->num_expected = contact_count;
1076af8dc4d0SHans de Goede 		/* A non 0 contact count always indicates a first packet */
1077f146d1c4SBenjamin Tissoires 		else if (contact_count)
1078f146d1c4SBenjamin Tissoires 			app->num_expected = contact_count;
10797e3cc447SBenjamin Tissoires 	}
1080f146d1c4SBenjamin Tissoires 	app->prev_scantime = scantime;
1081c2517f62SBenjamin Tissoires 
1082f146d1c4SBenjamin Tissoires 	first_packet = app->num_received == 0;
1083*01eaac7eSBenjamin Tissoires 
1084*01eaac7eSBenjamin Tissoires 	input = report->field[0]->hidinput->input;
1085*01eaac7eSBenjamin Tissoires 
1086*01eaac7eSBenjamin Tissoires 	list_for_each_entry(slot, &app->mt_usages, list) {
1087*01eaac7eSBenjamin Tissoires 		if (!mt_process_slot(td, input, app, slot))
1088*01eaac7eSBenjamin Tissoires 			app->num_received++;
1089*01eaac7eSBenjamin Tissoires 	}
1090*01eaac7eSBenjamin Tissoires 
109155978fa9SBenjamin Tissoires 	for (r = 0; r < report->maxfield; r++) {
109255978fa9SBenjamin Tissoires 		field = report->field[r];
109355978fa9SBenjamin Tissoires 		count = field->report_count;
109455978fa9SBenjamin Tissoires 
109555978fa9SBenjamin Tissoires 		if (!(HID_MAIN_ITEM_VARIABLE & field->flags))
109655978fa9SBenjamin Tissoires 			continue;
109755978fa9SBenjamin Tissoires 
109855978fa9SBenjamin Tissoires 		for (n = 0; n < count; n++)
1099*01eaac7eSBenjamin Tissoires 			mt_process_mt_event(hid, app, field,
1100*01eaac7eSBenjamin Tissoires 					    &field->usage[n], field->value[n],
1101*01eaac7eSBenjamin Tissoires 					    first_packet);
110255978fa9SBenjamin Tissoires 	}
11035b62efd8SBenjamin Tissoires 
1104f146d1c4SBenjamin Tissoires 	if (app->num_received >= app->num_expected)
1105*01eaac7eSBenjamin Tissoires 		mt_sync_frame(td, app, input);
11064f4001bcSBenjamin Tissoires 
11074f4001bcSBenjamin Tissoires 	/*
11084f4001bcSBenjamin Tissoires 	 * Windows 8 specs says 2 things:
11094f4001bcSBenjamin Tissoires 	 * - once a contact has been reported, it has to be reported in each
11104f4001bcSBenjamin Tissoires 	 *   subsequent report
11114f4001bcSBenjamin Tissoires 	 * - the report rate when fingers are present has to be at least
11124f4001bcSBenjamin Tissoires 	 *   the refresh rate of the screen, 60 or 120 Hz
11134f4001bcSBenjamin Tissoires 	 *
11144f4001bcSBenjamin Tissoires 	 * I interprete this that the specification forces a report rate of
11154f4001bcSBenjamin Tissoires 	 * at least 60 Hz for a touchscreen to be certified.
11164f4001bcSBenjamin Tissoires 	 * Which means that if we do not get a report whithin 16 ms, either
11174f4001bcSBenjamin Tissoires 	 * something wrong happens, either the touchscreen forgets to send
11184f4001bcSBenjamin Tissoires 	 * a release. Taking a reasonable margin allows to remove issues
11194f4001bcSBenjamin Tissoires 	 * with USB communication or the load of the machine.
11204f4001bcSBenjamin Tissoires 	 *
11214f4001bcSBenjamin Tissoires 	 * Given that Win 8 devices are forced to send a release, this will
11224f4001bcSBenjamin Tissoires 	 * only affect laggish machines and the ones that have a firmware
11234f4001bcSBenjamin Tissoires 	 * defect.
11244f4001bcSBenjamin Tissoires 	 */
11253ceb3826SBenjamin Tissoires 	if (app->quirks & MT_QUIRK_STICKY_FINGERS) {
112696098274SBenjamin Tissoires 		if (test_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags))
112796098274SBenjamin Tissoires 			mod_timer(&td->release_timer,
112896098274SBenjamin Tissoires 				  jiffies + msecs_to_jiffies(100));
112996098274SBenjamin Tissoires 		else
113096098274SBenjamin Tissoires 			del_timer(&td->release_timer);
113196098274SBenjamin Tissoires 	}
11324f4001bcSBenjamin Tissoires 
11334f4001bcSBenjamin Tissoires 	clear_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags);
11345519cab4SBenjamin Tissoires }
11355519cab4SBenjamin Tissoires 
1136b2c68a2fSDmitry Torokhov static int mt_touch_input_configured(struct hid_device *hdev,
1137f146d1c4SBenjamin Tissoires 				     struct hid_input *hi,
1138f146d1c4SBenjamin Tissoires 				     struct mt_application *app)
1139a69c5f8bSBenjamin Tissoires {
1140a69c5f8bSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
1141a69c5f8bSBenjamin Tissoires 	struct mt_class *cls = &td->mtclass;
1142a69c5f8bSBenjamin Tissoires 	struct input_dev *input = hi->input;
1143b2c68a2fSDmitry Torokhov 	int ret;
1144a69c5f8bSBenjamin Tissoires 
1145a69c5f8bSBenjamin Tissoires 	if (!td->maxcontacts)
1146a69c5f8bSBenjamin Tissoires 		td->maxcontacts = MT_DEFAULT_MAXCONTACT;
1147a69c5f8bSBenjamin Tissoires 
1148f146d1c4SBenjamin Tissoires 	mt_post_parse(td, app);
1149a69c5f8bSBenjamin Tissoires 	if (td->serial_maybe)
1150f146d1c4SBenjamin Tissoires 		mt_post_parse_default_settings(td, app);
1151a69c5f8bSBenjamin Tissoires 
1152a69c5f8bSBenjamin Tissoires 	if (cls->is_indirect)
1153f146d1c4SBenjamin Tissoires 		app->mt_flags |= INPUT_MT_POINTER;
1154a69c5f8bSBenjamin Tissoires 
11553ceb3826SBenjamin Tissoires 	if (app->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
1156f146d1c4SBenjamin Tissoires 		app->mt_flags |= INPUT_MT_DROP_UNUSED;
1157a69c5f8bSBenjamin Tissoires 
1158015fdaa9SBenjamin Tissoires 	/* check for clickpads */
1159f146d1c4SBenjamin Tissoires 	if ((app->mt_flags & INPUT_MT_POINTER) &&
1160f146d1c4SBenjamin Tissoires 	    (app->buttons_count == 1))
11612c6e0277SSeth Forshee 		td->is_buttonpad = true;
11622c6e0277SSeth Forshee 
11632c6e0277SSeth Forshee 	if (td->is_buttonpad)
1164015fdaa9SBenjamin Tissoires 		__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
1165015fdaa9SBenjamin Tissoires 
1166f146d1c4SBenjamin Tissoires 	ret = input_mt_init_slots(input, td->maxcontacts, app->mt_flags);
1167b2c68a2fSDmitry Torokhov 	if (ret)
1168b2c68a2fSDmitry Torokhov 		return ret;
1169a69c5f8bSBenjamin Tissoires 
1170f146d1c4SBenjamin Tissoires 	app->mt_flags = 0;
1171b2c68a2fSDmitry Torokhov 	return 0;
1172a69c5f8bSBenjamin Tissoires }
1173a69c5f8bSBenjamin Tissoires 
1174957b8dffSJoão Paulo Rechi Vita #define mt_map_key_clear(c)	hid_map_usage_clear(hi, usage, bit, \
1175957b8dffSJoão Paulo Rechi Vita 						    max, EV_KEY, (c))
1176a69c5f8bSBenjamin Tissoires static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
1177a69c5f8bSBenjamin Tissoires 		struct hid_field *field, struct hid_usage *usage,
1178a69c5f8bSBenjamin Tissoires 		unsigned long **bit, int *max)
1179a69c5f8bSBenjamin Tissoires {
11806aef704eSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
1181f146d1c4SBenjamin Tissoires 	struct mt_application *application;
11828dfe14b3SBenjamin Tissoires 	struct mt_report_data *rdata;
11836aef704eSBenjamin Tissoires 
11848dfe14b3SBenjamin Tissoires 	rdata = mt_find_report_data(td, field->report);
11858dfe14b3SBenjamin Tissoires 	if (!rdata) {
11868dfe14b3SBenjamin Tissoires 		hid_err(hdev, "failed to allocate data for report\n");
11878dfe14b3SBenjamin Tissoires 		return 0;
11888dfe14b3SBenjamin Tissoires 	}
11898dfe14b3SBenjamin Tissoires 
11908dfe14b3SBenjamin Tissoires 	application = rdata->application;
11913ceb3826SBenjamin Tissoires 
11926aef704eSBenjamin Tissoires 	/*
11936aef704eSBenjamin Tissoires 	 * If mtclass.export_all_inputs is not set, only map fields from
11946aef704eSBenjamin Tissoires 	 * TouchScreen or TouchPad collections. We need to ignore fields
11956aef704eSBenjamin Tissoires 	 * that belong to other collections such as Mouse that might have
11966aef704eSBenjamin Tissoires 	 * the same GenericDesktop usages.
11976aef704eSBenjamin Tissoires 	 */
11986aef704eSBenjamin Tissoires 	if (!td->mtclass.export_all_inputs &&
11996aef704eSBenjamin Tissoires 	    field->application != HID_DG_TOUCHSCREEN &&
1200fa11aa72SBenjamin Tissoires 	    field->application != HID_DG_PEN &&
12018fe89ef0SBenjamin Tissoires 	    field->application != HID_DG_TOUCHPAD &&
12028fe89ef0SBenjamin Tissoires 	    field->application != HID_GD_KEYBOARD &&
1203e57f4e67SHans de Goede 	    field->application != HID_GD_SYSTEM_CONTROL &&
12041fbf74efSJoão Paulo Rechi Vita 	    field->application != HID_CP_CONSUMER_CONTROL &&
1205957b8dffSJoão Paulo Rechi Vita 	    field->application != HID_GD_WIRELESS_RADIO_CTLS &&
1206957b8dffSJoão Paulo Rechi Vita 	    !(field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS &&
12073ceb3826SBenjamin Tissoires 	      application->quirks & MT_QUIRK_ASUS_CUSTOM_UP))
12086f492f28SBenjamin Tissoires 		return -1;
1209a69c5f8bSBenjamin Tissoires 
12106aef704eSBenjamin Tissoires 	/*
1211957b8dffSJoão Paulo Rechi Vita 	 * Some Asus keyboard+touchpad devices have the hotkeys defined in the
1212957b8dffSJoão Paulo Rechi Vita 	 * touchpad report descriptor. We need to treat these as an array to
1213957b8dffSJoão Paulo Rechi Vita 	 * map usages to input keys.
1214957b8dffSJoão Paulo Rechi Vita 	 */
121539bbf402SJiri Kosina 	if (field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS &&
12163ceb3826SBenjamin Tissoires 	    application->quirks & MT_QUIRK_ASUS_CUSTOM_UP &&
1217957b8dffSJoão Paulo Rechi Vita 	    (usage->hid & HID_USAGE_PAGE) == HID_UP_CUSTOM) {
1218957b8dffSJoão Paulo Rechi Vita 		set_bit(EV_REP, hi->input->evbit);
1219957b8dffSJoão Paulo Rechi Vita 		if (field->flags & HID_MAIN_ITEM_VARIABLE)
1220957b8dffSJoão Paulo Rechi Vita 			field->flags &= ~HID_MAIN_ITEM_VARIABLE;
1221957b8dffSJoão Paulo Rechi Vita 		switch (usage->hid & HID_USAGE) {
1222957b8dffSJoão Paulo Rechi Vita 		case 0x10: mt_map_key_clear(KEY_BRIGHTNESSDOWN);	break;
1223957b8dffSJoão Paulo Rechi Vita 		case 0x20: mt_map_key_clear(KEY_BRIGHTNESSUP);		break;
1224957b8dffSJoão Paulo Rechi Vita 		case 0x35: mt_map_key_clear(KEY_DISPLAY_OFF);		break;
1225957b8dffSJoão Paulo Rechi Vita 		case 0x6b: mt_map_key_clear(KEY_F21);			break;
1226957b8dffSJoão Paulo Rechi Vita 		case 0x6c: mt_map_key_clear(KEY_SLEEP);			break;
1227957b8dffSJoão Paulo Rechi Vita 		default:
1228957b8dffSJoão Paulo Rechi Vita 			return -1;
1229957b8dffSJoão Paulo Rechi Vita 		}
1230957b8dffSJoão Paulo Rechi Vita 		return 1;
1231957b8dffSJoão Paulo Rechi Vita 	}
1232957b8dffSJoão Paulo Rechi Vita 
12338dfe14b3SBenjamin Tissoires 	if (rdata->is_mt_collection &&
12348dfe14b3SBenjamin Tissoires 	    (field->application == HID_DG_TOUCHSCREEN ||
12358dfe14b3SBenjamin Tissoires 	     field->application == HID_DG_TOUCHPAD))
1236f146d1c4SBenjamin Tissoires 		return mt_touch_input_mapping(hdev, hi, field, usage, bit, max,
1237f146d1c4SBenjamin Tissoires 					      application);
12386aef704eSBenjamin Tissoires 
12396aef704eSBenjamin Tissoires 	/* let hid-core decide for the others */
12406aef704eSBenjamin Tissoires 	return 0;
1241a69c5f8bSBenjamin Tissoires }
1242a69c5f8bSBenjamin Tissoires 
1243a69c5f8bSBenjamin Tissoires static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
1244a69c5f8bSBenjamin Tissoires 		struct hid_field *field, struct hid_usage *usage,
1245a69c5f8bSBenjamin Tissoires 		unsigned long **bit, int *max)
1246a69c5f8bSBenjamin Tissoires {
12476aef704eSBenjamin Tissoires 	/*
12486aef704eSBenjamin Tissoires 	 * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
12496aef704eSBenjamin Tissoires 	 * for the stylus.
12506aef704eSBenjamin Tissoires 	 */
1251fa11aa72SBenjamin Tissoires 	if (field->physical == HID_DG_STYLUS)
1252e55f6200SBenjamin Tissoires 		return 0;
1253fa11aa72SBenjamin Tissoires 
12546aef704eSBenjamin Tissoires 	if (field->application == HID_DG_TOUCHSCREEN ||
12554cf56a89SDmitry Torokhov 	    field->application == HID_DG_TOUCHPAD) {
12564cf56a89SDmitry Torokhov 		/* We own these mappings, tell hid-input to ignore them */
12574cf56a89SDmitry Torokhov 		return -1;
12584cf56a89SDmitry Torokhov 	}
12596aef704eSBenjamin Tissoires 
12606aef704eSBenjamin Tissoires 	/* let hid-core decide for the others */
12616aef704eSBenjamin Tissoires 	return 0;
1262a69c5f8bSBenjamin Tissoires }
1263a69c5f8bSBenjamin Tissoires 
1264a69c5f8bSBenjamin Tissoires static int mt_event(struct hid_device *hid, struct hid_field *field,
1265a69c5f8bSBenjamin Tissoires 				struct hid_usage *usage, __s32 value)
1266a69c5f8bSBenjamin Tissoires {
1267a69c5f8bSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hid);
12688dfe14b3SBenjamin Tissoires 	struct mt_report_data *rdata;
1269a69c5f8bSBenjamin Tissoires 
12708dfe14b3SBenjamin Tissoires 	rdata = mt_find_report_data(td, field->report);
12718dfe14b3SBenjamin Tissoires 	if (rdata && rdata->is_mt_collection)
1272a69c5f8bSBenjamin Tissoires 		return mt_touch_event(hid, field, usage, value);
1273a69c5f8bSBenjamin Tissoires 
1274e55f6200SBenjamin Tissoires 	return 0;
1275a69c5f8bSBenjamin Tissoires }
1276a69c5f8bSBenjamin Tissoires 
1277a69c5f8bSBenjamin Tissoires static void mt_report(struct hid_device *hid, struct hid_report *report)
1278a69c5f8bSBenjamin Tissoires {
1279a69c5f8bSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hid);
1280e55f6200SBenjamin Tissoires 	struct hid_field *field = report->field[0];
12818dfe14b3SBenjamin Tissoires 	struct mt_report_data *rdata;
1282a69c5f8bSBenjamin Tissoires 
1283a69c5f8bSBenjamin Tissoires 	if (!(hid->claimed & HID_CLAIMED_INPUT))
1284a69c5f8bSBenjamin Tissoires 		return;
1285a69c5f8bSBenjamin Tissoires 
12868dfe14b3SBenjamin Tissoires 	rdata = mt_find_report_data(td, report);
12878dfe14b3SBenjamin Tissoires 	if (rdata && rdata->is_mt_collection)
12888dfe14b3SBenjamin Tissoires 		return mt_touch_report(hid, rdata);
1289fa11aa72SBenjamin Tissoires 
1290e55f6200SBenjamin Tissoires 	if (field && field->hidinput && field->hidinput->input)
1291e55f6200SBenjamin Tissoires 		input_sync(field->hidinput->input);
12925519cab4SBenjamin Tissoires }
12935519cab4SBenjamin Tissoires 
12947f81c8dbSBenjamin Tissoires static bool mt_need_to_apply_feature(struct hid_device *hdev,
12957f81c8dbSBenjamin Tissoires 				     struct hid_field *field,
129602946f4bSBenjamin Tissoires 				     struct hid_usage *usage,
129702946f4bSBenjamin Tissoires 				     enum latency_mode latency,
129802946f4bSBenjamin Tissoires 				     bool surface_switch,
129902946f4bSBenjamin Tissoires 				     bool button_switch)
13005519cab4SBenjamin Tissoires {
13015519cab4SBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
1302da10bc25SMathieu Magnaudet 	struct mt_class *cls = &td->mtclass;
13037f81c8dbSBenjamin Tissoires 	struct hid_report *report = field->report;
13047f81c8dbSBenjamin Tissoires 	unsigned int index = usage->usage_index;
1305da10bc25SMathieu Magnaudet 	char *buf;
13063064a03bSAaron Ma 	u32 report_len;
13077f81c8dbSBenjamin Tissoires 	int max;
13085519cab4SBenjamin Tissoires 
13097f81c8dbSBenjamin Tissoires 	switch (usage->hid) {
13107f81c8dbSBenjamin Tissoires 	case HID_DG_INPUTMODE:
1311da10bc25SMathieu Magnaudet 		if (cls->quirks & MT_QUIRK_FORCE_GET_FEATURE) {
13127f81c8dbSBenjamin Tissoires 			report_len = hid_report_len(report);
13137f81c8dbSBenjamin Tissoires 			buf = hid_alloc_report_buf(report, GFP_KERNEL);
1314da10bc25SMathieu Magnaudet 			if (!buf) {
13157f81c8dbSBenjamin Tissoires 				hid_err(hdev,
13167f81c8dbSBenjamin Tissoires 					"failed to allocate buffer for report\n");
13177f81c8dbSBenjamin Tissoires 				return false;
1318da10bc25SMathieu Magnaudet 			}
13197f81c8dbSBenjamin Tissoires 			hid_hw_raw_request(hdev, report->id, buf, report_len,
1320da10bc25SMathieu Magnaudet 					   HID_FEATURE_REPORT,
1321da10bc25SMathieu Magnaudet 					   HID_REQ_GET_REPORT);
1322da10bc25SMathieu Magnaudet 			kfree(buf);
1323da10bc25SMathieu Magnaudet 		}
13247f81c8dbSBenjamin Tissoires 
13257f81c8dbSBenjamin Tissoires 		field->value[index] = td->inputmode_value;
13267f81c8dbSBenjamin Tissoires 		return true;
13277f81c8dbSBenjamin Tissoires 
13287f81c8dbSBenjamin Tissoires 	case HID_DG_CONTACTMAX:
13293ceb3826SBenjamin Tissoires 		if (cls->maxcontacts) {
13307f81c8dbSBenjamin Tissoires 			max = min_t(int, field->logical_maximum,
13313ceb3826SBenjamin Tissoires 				    cls->maxcontacts);
13327f81c8dbSBenjamin Tissoires 			if (field->value[index] != max) {
13337f81c8dbSBenjamin Tissoires 				field->value[index] = max;
13347f81c8dbSBenjamin Tissoires 				return true;
13355519cab4SBenjamin Tissoires 			}
13365519cab4SBenjamin Tissoires 		}
13377f81c8dbSBenjamin Tissoires 		break;
133802946f4bSBenjamin Tissoires 
133902946f4bSBenjamin Tissoires 	case HID_DG_LATENCYMODE:
134002946f4bSBenjamin Tissoires 		field->value[index] = latency;
134199c703acSJiri Kosina 		return true;
134202946f4bSBenjamin Tissoires 
134302946f4bSBenjamin Tissoires 	case HID_DG_SURFACESWITCH:
134402946f4bSBenjamin Tissoires 		field->value[index] = surface_switch;
134599c703acSJiri Kosina 		return true;
134602946f4bSBenjamin Tissoires 
134702946f4bSBenjamin Tissoires 	case HID_DG_BUTTONSWITCH:
134802946f4bSBenjamin Tissoires 		field->value[index] = button_switch;
134999c703acSJiri Kosina 		return true;
13507f81c8dbSBenjamin Tissoires 	}
13515519cab4SBenjamin Tissoires 
13527f81c8dbSBenjamin Tissoires 	return false; /* no need to update the report */
13537f81c8dbSBenjamin Tissoires }
13547f81c8dbSBenjamin Tissoires 
135502946f4bSBenjamin Tissoires static void mt_set_modes(struct hid_device *hdev, enum latency_mode latency,
135602946f4bSBenjamin Tissoires 			 bool surface_switch, bool button_switch)
135731ae9bddSBenjamin Tissoires {
13587f81c8dbSBenjamin Tissoires 	struct hid_report_enum *rep_enum;
13597f81c8dbSBenjamin Tissoires 	struct hid_report *rep;
13607f81c8dbSBenjamin Tissoires 	struct hid_usage *usage;
13617f81c8dbSBenjamin Tissoires 	int i, j;
13627f81c8dbSBenjamin Tissoires 	bool update_report;
136331ae9bddSBenjamin Tissoires 
13647f81c8dbSBenjamin Tissoires 	rep_enum = &hdev->report_enum[HID_FEATURE_REPORT];
13657f81c8dbSBenjamin Tissoires 	list_for_each_entry(rep, &rep_enum->report_list, list) {
13667f81c8dbSBenjamin Tissoires 		update_report = false;
136731ae9bddSBenjamin Tissoires 
13687f81c8dbSBenjamin Tissoires 		for (i = 0; i < rep->maxfield; i++) {
13697f81c8dbSBenjamin Tissoires 			/* Ignore if report count is out of bounds. */
13707f81c8dbSBenjamin Tissoires 			if (rep->field[i]->report_count < 1)
13717f81c8dbSBenjamin Tissoires 				continue;
137231ae9bddSBenjamin Tissoires 
13737f81c8dbSBenjamin Tissoires 			for (j = 0; j < rep->field[i]->maxusage; j++) {
13747f81c8dbSBenjamin Tissoires 				usage = &rep->field[i]->usage[j];
13757f81c8dbSBenjamin Tissoires 
13767f81c8dbSBenjamin Tissoires 				if (mt_need_to_apply_feature(hdev,
13777f81c8dbSBenjamin Tissoires 							     rep->field[i],
137802946f4bSBenjamin Tissoires 							     usage,
137902946f4bSBenjamin Tissoires 							     latency,
138002946f4bSBenjamin Tissoires 							     surface_switch,
138102946f4bSBenjamin Tissoires 							     button_switch))
13827f81c8dbSBenjamin Tissoires 					update_report = true;
138331ae9bddSBenjamin Tissoires 			}
138431ae9bddSBenjamin Tissoires 		}
13857f81c8dbSBenjamin Tissoires 
13867f81c8dbSBenjamin Tissoires 		if (update_report)
13877f81c8dbSBenjamin Tissoires 			hid_hw_request(hdev, rep, HID_REQ_SET_REPORT);
13887f81c8dbSBenjamin Tissoires 	}
138931ae9bddSBenjamin Tissoires }
139031ae9bddSBenjamin Tissoires 
1391f146d1c4SBenjamin Tissoires static void mt_post_parse_default_settings(struct mt_device *td,
1392f146d1c4SBenjamin Tissoires 					   struct mt_application *app)
13934fa3a583SHenrik Rydberg {
13943ceb3826SBenjamin Tissoires 	__s32 quirks = app->quirks;
13954fa3a583SHenrik Rydberg 
13964fa3a583SHenrik Rydberg 	/* unknown serial device needs special quirks */
1397*01eaac7eSBenjamin Tissoires 	if (list_is_singular(&app->mt_usages)) {
13984fa3a583SHenrik Rydberg 		quirks |= MT_QUIRK_ALWAYS_VALID;
13994fa3a583SHenrik Rydberg 		quirks &= ~MT_QUIRK_NOT_SEEN_MEANS_UP;
14004fa3a583SHenrik Rydberg 		quirks &= ~MT_QUIRK_VALID_IS_INRANGE;
14014fa3a583SHenrik Rydberg 		quirks &= ~MT_QUIRK_VALID_IS_CONFIDENCE;
1402e0bb8f9aSBenjamin Tissoires 		quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
14034fa3a583SHenrik Rydberg 	}
14044fa3a583SHenrik Rydberg 
14053ceb3826SBenjamin Tissoires 	app->quirks = quirks;
14064fa3a583SHenrik Rydberg }
14074fa3a583SHenrik Rydberg 
1408f146d1c4SBenjamin Tissoires static void mt_post_parse(struct mt_device *td, struct mt_application *app)
14093ac36d15SBenjamin Tissoires {
1410*01eaac7eSBenjamin Tissoires 	if (!app->have_contact_count)
14113ceb3826SBenjamin Tissoires 		app->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
14123ac36d15SBenjamin Tissoires }
14133ac36d15SBenjamin Tissoires 
1414b2c68a2fSDmitry Torokhov static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
141576f5902aSHenrik Rydberg {
141676f5902aSHenrik Rydberg 	struct mt_device *td = hid_get_drvdata(hdev);
1417c08d46aaSBenjamin Tissoires 	char *name;
1418c08d46aaSBenjamin Tissoires 	const char *suffix = NULL;
141940ec2603SBenjamin Tissoires 	unsigned int application = 0;
14208dfe14b3SBenjamin Tissoires 	struct mt_report_data *rdata;
1421f146d1c4SBenjamin Tissoires 	struct mt_application *mt_application = NULL;
142240ec2603SBenjamin Tissoires 	struct hid_report *report;
1423b2c68a2fSDmitry Torokhov 	int ret;
142476f5902aSHenrik Rydberg 
142540ec2603SBenjamin Tissoires 	list_for_each_entry(report, &hi->reports, hidinput_list) {
142640ec2603SBenjamin Tissoires 		application = report->application;
14278dfe14b3SBenjamin Tissoires 		rdata = mt_find_report_data(td, report);
14288dfe14b3SBenjamin Tissoires 		if (!rdata) {
14298dfe14b3SBenjamin Tissoires 			hid_err(hdev, "failed to allocate data for report\n");
14308dfe14b3SBenjamin Tissoires 			return -ENOMEM;
14318dfe14b3SBenjamin Tissoires 		}
1432f146d1c4SBenjamin Tissoires 
14338dfe14b3SBenjamin Tissoires 		mt_application = rdata->application;
14348dfe14b3SBenjamin Tissoires 
14358dfe14b3SBenjamin Tissoires 		if (rdata->is_mt_collection) {
1436f146d1c4SBenjamin Tissoires 			ret = mt_touch_input_configured(hdev, hi,
1437f146d1c4SBenjamin Tissoires 							mt_application);
1438b2c68a2fSDmitry Torokhov 			if (ret)
1439b2c68a2fSDmitry Torokhov 				return ret;
1440b2c68a2fSDmitry Torokhov 		}
144176f5902aSHenrik Rydberg 
14426aef704eSBenjamin Tissoires 		/*
144340ec2603SBenjamin Tissoires 		 * some egalax touchscreens have "application == DG_TOUCHSCREEN"
144440ec2603SBenjamin Tissoires 		 * for the stylus. Check this first, and then rely on
144540ec2603SBenjamin Tissoires 		 * the application field.
14466aef704eSBenjamin Tissoires 		 */
144740ec2603SBenjamin Tissoires 		if (report->field[0]->physical == HID_DG_STYLUS) {
1448c08d46aaSBenjamin Tissoires 			suffix = "Pen";
1449e55f6200SBenjamin Tissoires 			/* force BTN_STYLUS to allow tablet matching in udev */
1450e55f6200SBenjamin Tissoires 			__set_bit(BTN_STYLUS, hi->input->keybit);
145140ec2603SBenjamin Tissoires 		}
145240ec2603SBenjamin Tissoires 	}
145340ec2603SBenjamin Tissoires 
145440ec2603SBenjamin Tissoires 	if (!suffix) {
145540ec2603SBenjamin Tissoires 		switch (application) {
14566aef704eSBenjamin Tissoires 		case HID_GD_KEYBOARD:
14576aef704eSBenjamin Tissoires 		case HID_GD_KEYPAD:
14586aef704eSBenjamin Tissoires 		case HID_GD_MOUSE:
145940ec2603SBenjamin Tissoires 		case HID_DG_TOUCHPAD:
146040ec2603SBenjamin Tissoires 		case HID_GD_SYSTEM_CONTROL:
146140ec2603SBenjamin Tissoires 		case HID_CP_CONSUMER_CONTROL:
146240ec2603SBenjamin Tissoires 		case HID_GD_WIRELESS_RADIO_CTLS:
146340ec2603SBenjamin Tissoires 			/* already handled by hid core */
14646aef704eSBenjamin Tissoires 			break;
14656aef704eSBenjamin Tissoires 		case HID_DG_TOUCHSCREEN:
14666aef704eSBenjamin Tissoires 			/* we do not set suffix = "Touchscreen" */
146740ec2603SBenjamin Tissoires 			hi->input->name = hdev->name;
14686aef704eSBenjamin Tissoires 			break;
146940ec2603SBenjamin Tissoires 		case HID_DG_STYLUS:
147040ec2603SBenjamin Tissoires 			/* force BTN_STYLUS to allow tablet matching in udev */
147140ec2603SBenjamin Tissoires 			__set_bit(BTN_STYLUS, hi->input->keybit);
14721fbf74efSJoão Paulo Rechi Vita 			break;
1473957b8dffSJoão Paulo Rechi Vita 		case HID_VD_ASUS_CUSTOM_MEDIA_KEYS:
1474957b8dffSJoão Paulo Rechi Vita 			suffix = "Custom Media Keys";
1475957b8dffSJoão Paulo Rechi Vita 			break;
14766aef704eSBenjamin Tissoires 		default:
14776aef704eSBenjamin Tissoires 			suffix = "UNKNOWN";
14786aef704eSBenjamin Tissoires 			break;
14796aef704eSBenjamin Tissoires 		}
148076f5902aSHenrik Rydberg 	}
148176f5902aSHenrik Rydberg 
1482c08d46aaSBenjamin Tissoires 	if (suffix) {
1483c08d46aaSBenjamin Tissoires 		name = devm_kzalloc(&hi->input->dev,
1484c08d46aaSBenjamin Tissoires 				    strlen(hdev->name) + strlen(suffix) + 2,
1485c08d46aaSBenjamin Tissoires 				    GFP_KERNEL);
1486c08d46aaSBenjamin Tissoires 		if (name) {
1487c08d46aaSBenjamin Tissoires 			sprintf(name, "%s %s", hdev->name, suffix);
1488c08d46aaSBenjamin Tissoires 			hi->input->name = name;
1489c08d46aaSBenjamin Tissoires 		}
1490c08d46aaSBenjamin Tissoires 	}
1491b2c68a2fSDmitry Torokhov 
1492b2c68a2fSDmitry Torokhov 	return 0;
1493c08d46aaSBenjamin Tissoires }
1494c08d46aaSBenjamin Tissoires 
1495f3287a99SBenjamin Tissoires static void mt_fix_const_field(struct hid_field *field, unsigned int usage)
1496f3287a99SBenjamin Tissoires {
1497f3287a99SBenjamin Tissoires 	if (field->usage[0].hid != usage ||
1498f3287a99SBenjamin Tissoires 	    !(field->flags & HID_MAIN_ITEM_CONSTANT))
1499f3287a99SBenjamin Tissoires 		return;
1500f3287a99SBenjamin Tissoires 
1501f3287a99SBenjamin Tissoires 	field->flags &= ~HID_MAIN_ITEM_CONSTANT;
1502f3287a99SBenjamin Tissoires 	field->flags |= HID_MAIN_ITEM_VARIABLE;
1503f3287a99SBenjamin Tissoires }
1504f3287a99SBenjamin Tissoires 
1505f3287a99SBenjamin Tissoires static void mt_fix_const_fields(struct hid_device *hdev, unsigned int usage)
1506f3287a99SBenjamin Tissoires {
1507f3287a99SBenjamin Tissoires 	struct hid_report *report;
1508f3287a99SBenjamin Tissoires 	int i;
1509f3287a99SBenjamin Tissoires 
1510f3287a99SBenjamin Tissoires 	list_for_each_entry(report,
1511f3287a99SBenjamin Tissoires 			    &hdev->report_enum[HID_INPUT_REPORT].report_list,
1512f3287a99SBenjamin Tissoires 			    list) {
1513f3287a99SBenjamin Tissoires 
1514f3287a99SBenjamin Tissoires 		if (!report->maxfield)
1515f3287a99SBenjamin Tissoires 			continue;
1516f3287a99SBenjamin Tissoires 
1517f3287a99SBenjamin Tissoires 		for (i = 0; i < report->maxfield; i++)
1518f3287a99SBenjamin Tissoires 			if (report->field[i]->maxusage >= 1)
1519f3287a99SBenjamin Tissoires 				mt_fix_const_field(report->field[i], usage);
1520f3287a99SBenjamin Tissoires 	}
1521f3287a99SBenjamin Tissoires }
1522f3287a99SBenjamin Tissoires 
15234f4001bcSBenjamin Tissoires static void mt_release_contacts(struct hid_device *hid)
15244f4001bcSBenjamin Tissoires {
15254f4001bcSBenjamin Tissoires 	struct hid_input *hidinput;
1526f146d1c4SBenjamin Tissoires 	struct mt_application *application;
15274f4001bcSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hid);
15284f4001bcSBenjamin Tissoires 
15294f4001bcSBenjamin Tissoires 	list_for_each_entry(hidinput, &hid->inputs, list) {
15304f4001bcSBenjamin Tissoires 		struct input_dev *input_dev = hidinput->input;
15314f4001bcSBenjamin Tissoires 		struct input_mt *mt = input_dev->mt;
15324f4001bcSBenjamin Tissoires 		int i;
15334f4001bcSBenjamin Tissoires 
15344f4001bcSBenjamin Tissoires 		if (mt) {
15354f4001bcSBenjamin Tissoires 			for (i = 0; i < mt->num_slots; i++) {
15364f4001bcSBenjamin Tissoires 				input_mt_slot(input_dev, i);
15374f4001bcSBenjamin Tissoires 				input_mt_report_slot_state(input_dev,
15384f4001bcSBenjamin Tissoires 							   MT_TOOL_FINGER,
15394f4001bcSBenjamin Tissoires 							   false);
15404f4001bcSBenjamin Tissoires 			}
15414f4001bcSBenjamin Tissoires 			input_mt_sync_frame(input_dev);
15424f4001bcSBenjamin Tissoires 			input_sync(input_dev);
15434f4001bcSBenjamin Tissoires 		}
15444f4001bcSBenjamin Tissoires 	}
15454f4001bcSBenjamin Tissoires 
1546f146d1c4SBenjamin Tissoires 	list_for_each_entry(application, &td->applications, list) {
1547f146d1c4SBenjamin Tissoires 		application->num_received = 0;
1548f146d1c4SBenjamin Tissoires 	}
15494f4001bcSBenjamin Tissoires }
15504f4001bcSBenjamin Tissoires 
15510ee32774SKees Cook static void mt_expired_timeout(struct timer_list *t)
15524f4001bcSBenjamin Tissoires {
15530ee32774SKees Cook 	struct mt_device *td = from_timer(td, t, release_timer);
15540ee32774SKees Cook 	struct hid_device *hdev = td->hdev;
15554f4001bcSBenjamin Tissoires 
15564f4001bcSBenjamin Tissoires 	/*
15574f4001bcSBenjamin Tissoires 	 * An input report came in just before we release the sticky fingers,
15584f4001bcSBenjamin Tissoires 	 * it will take care of the sticky fingers.
15594f4001bcSBenjamin Tissoires 	 */
15604f4001bcSBenjamin Tissoires 	if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
15614f4001bcSBenjamin Tissoires 		return;
156296098274SBenjamin Tissoires 	if (test_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags))
15634f4001bcSBenjamin Tissoires 		mt_release_contacts(hdev);
15644f4001bcSBenjamin Tissoires 	clear_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags);
15654f4001bcSBenjamin Tissoires }
15664f4001bcSBenjamin Tissoires 
15675519cab4SBenjamin Tissoires static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
15685519cab4SBenjamin Tissoires {
15692d93666eSBenjamin Tissoires 	int ret, i;
15705519cab4SBenjamin Tissoires 	struct mt_device *td;
1571cf6d15d7SBenjamin Tissoires 	const struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
15722d93666eSBenjamin Tissoires 
15732d93666eSBenjamin Tissoires 	for (i = 0; mt_classes[i].name ; i++) {
15742d93666eSBenjamin Tissoires 		if (id->driver_data == mt_classes[i].name) {
15752d93666eSBenjamin Tissoires 			mtclass = &(mt_classes[i]);
15762d93666eSBenjamin Tissoires 			break;
15772d93666eSBenjamin Tissoires 		}
15782d93666eSBenjamin Tissoires 	}
15795519cab4SBenjamin Tissoires 
1580c08d46aaSBenjamin Tissoires 	td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL);
15815519cab4SBenjamin Tissoires 	if (!td) {
15825519cab4SBenjamin Tissoires 		dev_err(&hdev->dev, "cannot allocate multitouch data\n");
15835519cab4SBenjamin Tissoires 		return -ENOMEM;
15845519cab4SBenjamin Tissoires 	}
15850ee32774SKees Cook 	td->hdev = hdev;
1586eec29e3dSBenjamin Tissoires 	td->mtclass = *mtclass;
15879abebedbSAndrew Duggan 	td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
15885519cab4SBenjamin Tissoires 	hid_set_drvdata(hdev, td);
15895519cab4SBenjamin Tissoires 
1590f146d1c4SBenjamin Tissoires 	INIT_LIST_HEAD(&td->applications);
15918dfe14b3SBenjamin Tissoires 	INIT_LIST_HEAD(&td->reports);
1592f146d1c4SBenjamin Tissoires 
159376f5902aSHenrik Rydberg 	if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
159476f5902aSHenrik Rydberg 		td->serial_maybe = true;
159576f5902aSHenrik Rydberg 
1596b897f6dbSBenjamin Tissoires 	/* This allows the driver to correctly support devices
1597b897f6dbSBenjamin Tissoires 	 * that emit events over several HID messages.
1598b897f6dbSBenjamin Tissoires 	 */
1599b897f6dbSBenjamin Tissoires 	hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
1600b897f6dbSBenjamin Tissoires 
1601b897f6dbSBenjamin Tissoires 	/*
1602b897f6dbSBenjamin Tissoires 	 * This allows the driver to handle different input sensors
160340ec2603SBenjamin Tissoires 	 * that emits events through different applications on the same HID
1604b897f6dbSBenjamin Tissoires 	 * device.
1605b897f6dbSBenjamin Tissoires 	 */
160640ec2603SBenjamin Tissoires 	hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
1607b897f6dbSBenjamin Tissoires 
16080ee32774SKees Cook 	timer_setup(&td->release_timer, mt_expired_timeout, 0);
16094f4001bcSBenjamin Tissoires 
16105519cab4SBenjamin Tissoires 	ret = hid_parse(hdev);
16115519cab4SBenjamin Tissoires 	if (ret != 0)
1612c08d46aaSBenjamin Tissoires 		return ret;
16135519cab4SBenjamin Tissoires 
1614f3287a99SBenjamin Tissoires 	if (mtclass->quirks & MT_QUIRK_FIX_CONST_CONTACT_ID)
1615f3287a99SBenjamin Tissoires 		mt_fix_const_fields(hdev, HID_DG_CONTACTID);
1616f3287a99SBenjamin Tissoires 
16175519cab4SBenjamin Tissoires 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
16182d93666eSBenjamin Tissoires 	if (ret)
1619c08d46aaSBenjamin Tissoires 		return ret;
16205519cab4SBenjamin Tissoires 
1621eec29e3dSBenjamin Tissoires 	ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group);
16220c4b3c63SNicholas Krause 	if (ret)
16230c4b3c63SNicholas Krause 		dev_warn(&hdev->dev, "Cannot allocate sysfs group for %s\n",
16240c4b3c63SNicholas Krause 				hdev->name);
1625eec29e3dSBenjamin Tissoires 
162602946f4bSBenjamin Tissoires 	mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
16275519cab4SBenjamin Tissoires 
16285519cab4SBenjamin Tissoires 	return 0;
16295519cab4SBenjamin Tissoires }
16305519cab4SBenjamin Tissoires 
16315519cab4SBenjamin Tissoires #ifdef CONFIG_PM
16325519cab4SBenjamin Tissoires static int mt_reset_resume(struct hid_device *hdev)
16335519cab4SBenjamin Tissoires {
1634d3e69b9aSBenson Leung 	mt_release_contacts(hdev);
163502946f4bSBenjamin Tissoires 	mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
16365519cab4SBenjamin Tissoires 	return 0;
16375519cab4SBenjamin Tissoires }
1638dfeefd10SScott Liu 
1639dfeefd10SScott Liu static int mt_resume(struct hid_device *hdev)
1640dfeefd10SScott Liu {
1641dfeefd10SScott Liu 	/* Some Elan legacy devices require SET_IDLE to be set on resume.
1642dfeefd10SScott Liu 	 * It should be safe to send it to other devices too.
1643dfeefd10SScott Liu 	 * Tested on 3M, Stantum, Cypress, Zytronic, eGalax, and Elan panels. */
1644dfeefd10SScott Liu 
16454ba25d3fSBenjamin Tissoires 	hid_hw_idle(hdev, 0, 0, HID_REQ_SET_IDLE);
1646dfeefd10SScott Liu 
1647dfeefd10SScott Liu 	return 0;
1648dfeefd10SScott Liu }
16495519cab4SBenjamin Tissoires #endif
16505519cab4SBenjamin Tissoires 
16515519cab4SBenjamin Tissoires static void mt_remove(struct hid_device *hdev)
16525519cab4SBenjamin Tissoires {
1653b897f6dbSBenjamin Tissoires 	struct mt_device *td = hid_get_drvdata(hdev);
1654b897f6dbSBenjamin Tissoires 
16554f4001bcSBenjamin Tissoires 	del_timer_sync(&td->release_timer);
16564f4001bcSBenjamin Tissoires 
1657eec29e3dSBenjamin Tissoires 	sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
16585939212dSBenjamin Tissoires 	hid_hw_stop(hdev);
16595519cab4SBenjamin Tissoires }
16605519cab4SBenjamin Tissoires 
16610fa9c616SBenjamin Tissoires /*
16620fa9c616SBenjamin Tissoires  * This list contains only:
16630fa9c616SBenjamin Tissoires  * - VID/PID of products not working with the default multitouch handling
16640fa9c616SBenjamin Tissoires  * - 2 generic rules.
16650fa9c616SBenjamin Tissoires  * So there is no point in adding here any device with MT_CLS_DEFAULT.
16660fa9c616SBenjamin Tissoires  */
16675519cab4SBenjamin Tissoires static const struct hid_device_id mt_devices[] = {
16685519cab4SBenjamin Tissoires 
1669f786bba4SBenjamin Tissoires 	/* 3M panels */
1670f786bba4SBenjamin Tissoires 	{ .driver_data = MT_CLS_3M,
16712c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_3M,
1672f786bba4SBenjamin Tissoires 			USB_DEVICE_ID_3M1968) },
1673f786bba4SBenjamin Tissoires 	{ .driver_data = MT_CLS_3M,
16742c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_3M,
1675f786bba4SBenjamin Tissoires 			USB_DEVICE_ID_3M2256) },
1676c4fad877SBenjamin Tissoires 	{ .driver_data = MT_CLS_3M,
16772c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_3M,
1678c4fad877SBenjamin Tissoires 			USB_DEVICE_ID_3M3266) },
1679f786bba4SBenjamin Tissoires 
1680504c932cSMasaki Ota 	/* Alps devices */
1681504c932cSMasaki Ota 	{ .driver_data = MT_CLS_WIN_8_DUAL,
1682504c932cSMasaki Ota 		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
1683504c932cSMasaki Ota 			USB_VENDOR_ID_ALPS_JP,
1684504c932cSMasaki Ota 			HID_DEVICE_ID_ALPS_U1_DUAL_PTP) },
1685504c932cSMasaki Ota 	{ .driver_data = MT_CLS_WIN_8_DUAL,
1686504c932cSMasaki Ota 		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
1687504c932cSMasaki Ota 			USB_VENDOR_ID_ALPS_JP,
1688504c932cSMasaki Ota 			HID_DEVICE_ID_ALPS_U1_DUAL_3BTN_PTP) },
1689504c932cSMasaki Ota 
169056d859e1SPavel Tatashin 	/* Lenovo X1 TAB Gen 2 */
169156d859e1SPavel Tatashin 	{ .driver_data = MT_CLS_WIN_8_DUAL,
169256d859e1SPavel Tatashin 		HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8,
169356d859e1SPavel Tatashin 			   USB_VENDOR_ID_LENOVO,
169456d859e1SPavel Tatashin 			   USB_DEVICE_ID_LENOVO_X1_TAB) },
169556d859e1SPavel Tatashin 
16966aef704eSBenjamin Tissoires 	/* Anton devices */
16976aef704eSBenjamin Tissoires 	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
16986aef704eSBenjamin Tissoires 		MT_USB_DEVICE(USB_VENDOR_ID_ANTON,
16996aef704eSBenjamin Tissoires 			USB_DEVICE_ID_ANTON_TOUCH_PAD) },
1700e6aac342SBenjamin Tissoires 
1701957b8dffSJoão Paulo Rechi Vita 	/* Asus T304UA */
1702957b8dffSJoão Paulo Rechi Vita 	{ .driver_data = MT_CLS_ASUS,
1703957b8dffSJoão Paulo Rechi Vita 		HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8,
1704957b8dffSJoão Paulo Rechi Vita 			USB_VENDOR_ID_ASUSTEK,
1705957b8dffSJoão Paulo Rechi Vita 			USB_DEVICE_ID_ASUSTEK_T304_KEYBOARD) },
1706957b8dffSJoão Paulo Rechi Vita 
1707b1057124SBenjamin Tissoires 	/* Atmel panels */
1708b1057124SBenjamin Tissoires 	{ .driver_data = MT_CLS_SERIAL,
17092c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_ATMEL,
1710841cb157SBenjamin Tissoires 			USB_DEVICE_ID_ATMEL_MXT_DIGITIZER) },
1711b1057124SBenjamin Tissoires 
17129ed32695SJiri Kosina 	/* Baanto multitouch devices */
1713dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
171416b79bb8SJiri Kosina 		MT_USB_DEVICE(USB_VENDOR_ID_BAANTO,
17159ed32695SJiri Kosina 			USB_DEVICE_ID_BAANTO_MT_190W2) },
17160fa9c616SBenjamin Tissoires 
1717a841b62cSBenjamin Tissoires 	/* Cando panels */
1718a841b62cSBenjamin Tissoires 	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
17192c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
1720a841b62cSBenjamin Tissoires 			USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
1721a841b62cSBenjamin Tissoires 	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
17222c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
1723a841b62cSBenjamin Tissoires 			USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
1724a841b62cSBenjamin Tissoires 
1725942fd422SAustin Zhang 	/* Chunghwa Telecom touch panels */
1726dc3e1d80SBenjamin Tissoires 	{  .driver_data = MT_CLS_NSMU,
17272c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT,
1728942fd422SAustin Zhang 			USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) },
1729942fd422SAustin Zhang 
1730070f63b4SYang Bo 	/* CJTouch panels */
1731070f63b4SYang Bo 	{ .driver_data = MT_CLS_NSMU,
1732070f63b4SYang Bo 		MT_USB_DEVICE(USB_VENDOR_ID_CJTOUCH,
1733070f63b4SYang Bo 			USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0020) },
1734070f63b4SYang Bo 	{ .driver_data = MT_CLS_NSMU,
1735070f63b4SYang Bo 		MT_USB_DEVICE(USB_VENDOR_ID_CJTOUCH,
1736070f63b4SYang Bo 			USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0040) },
1737070f63b4SYang Bo 
173879603dc9SBenjamin Tissoires 	/* CVTouch panels */
1739dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
17402c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_CVTOUCH,
174179603dc9SBenjamin Tissoires 			USB_DEVICE_ID_CVTOUCH_SCREEN) },
174279603dc9SBenjamin Tissoires 
174322408283SBenjamin Tissoires 	/* eGalax devices (resistive) */
174422408283SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX,
17452c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1746e36f690bSBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D) },
174722408283SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX,
17482c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1749e36f690bSBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E) },
175022408283SBenjamin Tissoires 
175122408283SBenjamin Tissoires 	/* eGalax devices (capacitive) */
1752fd1d1525SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
17532c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1754fd1d1525SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7207) },
175522408283SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX,
17562c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1757e36f690bSBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C) },
1758fd1d1525SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
17592c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1760fd1d1525SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224) },
17612ce09df4SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
17622c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
17632ce09df4SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_722A) },
176422408283SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
17652c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
176622408283SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_725E) },
1767fd1d1525SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
17682c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1769fd1d1525SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7262) },
177022408283SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX,
17712c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
177222408283SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B) },
177322408283SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX,
177422408283SBenjamin Tissoires 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1775e36f690bSBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1) },
1776fd1d1525SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
17772c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1778fd1d1525SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72AA) },
17791fd8f047SChris Bagwell 	{ .driver_data = MT_CLS_EGALAX,
1780aa672da1SAndy Shevchenko 		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
1781aa672da1SAndy Shevchenko 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72C4) },
1782aa672da1SAndy Shevchenko 	{ .driver_data = MT_CLS_EGALAX,
1783aa672da1SAndy Shevchenko 		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
1784aa672da1SAndy Shevchenko 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72D0) },
1785aa672da1SAndy Shevchenko 	{ .driver_data = MT_CLS_EGALAX,
17862c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
178766f06127SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA) },
178866f06127SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX,
17892c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1790bb9ff210SMarek Vasut 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302) },
17911b723e8dSBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
17922c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1793fd1d1525SBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7349) },
1794fd1d1525SBenjamin Tissoires 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
17952c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1796ae01c9e5SThierry Reding 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_73F7) },
1797ae01c9e5SThierry Reding 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
1798ae01c9e5SThierry Reding 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
1799e36f690bSBenjamin Tissoires 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) },
180022408283SBenjamin Tissoires 
18017c7606a2STomas Sokorai 	/* Elitegroup panel */
18027c7606a2STomas Sokorai 	{ .driver_data = MT_CLS_SERIAL,
18037c7606a2STomas Sokorai 		MT_USB_DEVICE(USB_VENDOR_ID_ELITEGROUP,
18047c7606a2STomas Sokorai 			USB_DEVICE_ID_ELITEGROUP_05D8) },
18057c7606a2STomas Sokorai 
180677723e3bSHenrik Rydberg 	/* Flatfrog Panels */
180777723e3bSHenrik Rydberg 	{ .driver_data = MT_CLS_FLATFROG,
180877723e3bSHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_FLATFROG,
180977723e3bSHenrik Rydberg 			USB_DEVICE_ID_MULTITOUCH_3200) },
181077723e3bSHenrik Rydberg 
18113db187e7SBenjamin Tissoires 	/* FocalTech Panels */
18123db187e7SBenjamin Tissoires 	{ .driver_data = MT_CLS_SERIAL,
18133db187e7SBenjamin Tissoires 		MT_USB_DEVICE(USB_VENDOR_ID_CYGNAL,
18143db187e7SBenjamin Tissoires 			USB_DEVICE_ID_FOCALTECH_FTXXXX_MULTITOUCH) },
18153db187e7SBenjamin Tissoires 
18165572da08SBenjamin Tissoires 	/* GeneralTouch panel */
1817f5ff4e1eSXianhan Yu 	{ .driver_data = MT_CLS_GENERALTOUCH_TWOFINGERS,
18182c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
18195572da08SBenjamin Tissoires 			USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
1820f5ff4e1eSXianhan Yu 	{ .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
1821f5ff4e1eSXianhan Yu 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
1822f5ff4e1eSXianhan Yu 			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PWT_TENFINGERS) },
18237b226292SLuosong 	{ .driver_data = MT_CLS_GENERALTOUCH_TWOFINGERS,
18247b226292SLuosong 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
18257b226292SLuosong 			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0101) },
18267b226292SLuosong 	{ .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
18277b226292SLuosong 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
18287b226292SLuosong 			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0102) },
18297b226292SLuosong 	{ .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
18307b226292SLuosong 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
18317b226292SLuosong 			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0106) },
18327b226292SLuosong 	{ .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
18337b226292SLuosong 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
18347b226292SLuosong 			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_010A) },
18357b226292SLuosong 	{ .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
18367b226292SLuosong 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
18377b226292SLuosong 			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100) },
18385572da08SBenjamin Tissoires 
18394d5df5d1SAndreas Nielsen 	/* Gametel game controller */
1840dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
18412c2110e9SHenrik Rydberg 		MT_BT_DEVICE(USB_VENDOR_ID_FRUCTEL,
18424d5df5d1SAndreas Nielsen 			USB_DEVICE_ID_GAMETEL_MT_MODE) },
18434d5df5d1SAndreas Nielsen 
1844ee0fbd14SBenjamin Tissoires 	/* GoodTouch panels */
1845dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
18462c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH,
1847ee0fbd14SBenjamin Tissoires 			USB_DEVICE_ID_GOODTOUCH_000f) },
1848ee0fbd14SBenjamin Tissoires 
184954580365SBenjamin Tissoires 	/* Hanvon panels */
185054580365SBenjamin Tissoires 	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
18512c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT,
185254580365SBenjamin Tissoires 			USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) },
185354580365SBenjamin Tissoires 
18544e61f0d7SAustin Zhang 	/* Ilitek dual touch panel */
1855dc3e1d80SBenjamin Tissoires 	{  .driver_data = MT_CLS_NSMU,
18562c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_ILITEK,
18574e61f0d7SAustin Zhang 			USB_DEVICE_ID_ILITEK_MULTITOUCH) },
18584e61f0d7SAustin Zhang 
1859f3287a99SBenjamin Tissoires 	/* LG Melfas panel */
1860f3287a99SBenjamin Tissoires 	{ .driver_data = MT_CLS_LG,
1861f3287a99SBenjamin Tissoires 		HID_USB_DEVICE(USB_VENDOR_ID_LG,
1862f3287a99SBenjamin Tissoires 			USB_DEVICE_ID_LG_MELFAS_MT) },
1863f3287a99SBenjamin Tissoires 
18644a6ee685SBenjamin Tissoires 	/* MosArt panels */
18654a6ee685SBenjamin Tissoires 	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
18662c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_ASUS,
18674a6ee685SBenjamin Tissoires 			USB_DEVICE_ID_ASUS_T91MT)},
18684a6ee685SBenjamin Tissoires 	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
18692c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_ASUS,
18704a6ee685SBenjamin Tissoires 			USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) },
18714a6ee685SBenjamin Tissoires 	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
18722c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_TURBOX,
18734a6ee685SBenjamin Tissoires 			USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) },
18744a6ee685SBenjamin Tissoires 
18754db703eaSAustin Hendrix 	/* Novatek Panel */
1876dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
18774380d819SJiri Kosina 		MT_USB_DEVICE(USB_VENDOR_ID_NOVATEK,
18784db703eaSAustin Hendrix 			USB_DEVICE_ID_NOVATEK_PCT) },
18794db703eaSAustin Hendrix 
1880a80e803aSBenjamin Tissoires 	/* Ntrig Panel */
1881a80e803aSBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
1882a80e803aSBenjamin Tissoires 		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
1883a80e803aSBenjamin Tissoires 			USB_VENDOR_ID_NTRIG, 0x1b05) },
1884a80e803aSBenjamin Tissoires 
1885fb55b402SHans de Goede 	/* Panasonic panels */
1886fb55b402SHans de Goede 	{ .driver_data = MT_CLS_PANASONIC,
1887fb55b402SHans de Goede 		MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC,
1888fb55b402SHans de Goede 			USB_DEVICE_ID_PANABOARD_UBT780) },
1889fb55b402SHans de Goede 	{ .driver_data = MT_CLS_PANASONIC,
1890fb55b402SHans de Goede 		MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC,
1891fb55b402SHans de Goede 			USB_DEVICE_ID_PANABOARD_UBT880) },
1892fb55b402SHans de Goede 
1893b7ea95ffSAaron Tian 	/* PixArt optical touch screen */
1894b7ea95ffSAaron Tian 	{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
18952c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_PIXART,
1896b7ea95ffSAaron Tian 			USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN) },
1897b7ea95ffSAaron Tian 	{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
18982c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_PIXART,
1899b7ea95ffSAaron Tian 			USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1) },
1900b7ea95ffSAaron Tian 	{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
19012c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_PIXART,
1902b7ea95ffSAaron Tian 			USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2) },
1903b7ea95ffSAaron Tian 
19045519cab4SBenjamin Tissoires 	/* PixCir-based panels */
19051e9cf35bSBenjamin Tissoires 	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
19062c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
19075519cab4SBenjamin Tissoires 			USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
19085519cab4SBenjamin Tissoires 
19095e7ea11fSBenjamin Tissoires 	/* Quanta-based panels */
19105e7ea11fSBenjamin Tissoires 	{ .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID,
19112c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_QUANTA,
19125e7ea11fSBenjamin Tissoires 			USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001) },
1913a6802e00SForest Bond 
1914843e475fSBenjamin Tissoires 	/* Razer touchpads */
1915843e475fSBenjamin Tissoires 	{ .driver_data = MT_CLS_RAZER_BLADE_STEALTH,
1916843e475fSBenjamin Tissoires 		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
1917843e475fSBenjamin Tissoires 			USB_VENDOR_ID_SYNAPTICS, 0x8323) },
1918843e475fSBenjamin Tissoires 
1919043b403aSBenjamin Tissoires 	/* Stantum panels */
1920bf5af9b5SBenjamin Tissoires 	{ .driver_data = MT_CLS_CONFIDENCE,
19212c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM,
1922043b403aSBenjamin Tissoires 			USB_DEVICE_ID_MTP_STM)},
1923043b403aSBenjamin Tissoires 
1924847672cdSBenjamin Tissoires 	/* TopSeed panels */
1925847672cdSBenjamin Tissoires 	{ .driver_data = MT_CLS_TOPSEED,
19262c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_TOPSEED2,
1927847672cdSBenjamin Tissoires 			USB_DEVICE_ID_TOPSEED2_PERIPAD_701) },
1928847672cdSBenjamin Tissoires 
19295e74e56dSBenjamin Tissoires 	/* Touch International panels */
1930dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
19312c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_TOUCH_INTL,
19325e74e56dSBenjamin Tissoires 			USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH) },
19335e74e56dSBenjamin Tissoires 
1934617b64f9SBenjamin Tissoires 	/* Unitec panels */
1935dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
19362c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_UNITEC,
1937617b64f9SBenjamin Tissoires 			USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) },
1938dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
19392c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_UNITEC,
1940617b64f9SBenjamin Tissoires 			USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
1941bf9d121eSKaiChung Cheng 
1942da10bc25SMathieu Magnaudet 	/* VTL panels */
1943da10bc25SMathieu Magnaudet 	{ .driver_data = MT_CLS_VTL,
1944da10bc25SMathieu Magnaudet 		MT_USB_DEVICE(USB_VENDOR_ID_VTL,
1945da10bc25SMathieu Magnaudet 			USB_DEVICE_ID_VTL_MULTITOUCH_FF3F) },
1946da10bc25SMathieu Magnaudet 
1947bf9d121eSKaiChung Cheng 	/* Wistron panels */
1948bf9d121eSKaiChung Cheng 	{ .driver_data = MT_CLS_NSMU,
1949bf9d121eSKaiChung Cheng 		MT_USB_DEVICE(USB_VENDOR_ID_WISTRON,
1950bf9d121eSKaiChung Cheng 			USB_DEVICE_ID_WISTRON_OPTICAL_TOUCH) },
1951bf9d121eSKaiChung Cheng 
1952bc8a2a9bSice chien 	/* XAT */
1953dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
19542c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XAT,
1955bc8a2a9bSice chien 			USB_DEVICE_ID_XAT_CSR) },
1956617b64f9SBenjamin Tissoires 
195711576c61SMasatoshi Hoshikawa 	/* Xiroku */
1958dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
19592c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
196011576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_SPX) },
1961dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
19622c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
196311576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_MPX) },
1964dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
19652c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
196611576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_CSR) },
1967dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
19682c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
196911576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_SPX1) },
1970dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
19712c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
197211576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_MPX1) },
1973dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
19742c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
197511576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_CSR1) },
1976dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
19772c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
197811576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_SPX2) },
1979dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
19802c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
198111576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_MPX2) },
1982dc3e1d80SBenjamin Tissoires 	{ .driver_data = MT_CLS_NSMU,
19832c2110e9SHenrik Rydberg 		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
198411576c61SMasatoshi Hoshikawa 			USB_DEVICE_ID_XIROKU_CSR2) },
198511576c61SMasatoshi Hoshikawa 
19860e82232cSWei-Ning Huang 	/* Google MT devices */
19870e82232cSWei-Ning Huang 	{ .driver_data = MT_CLS_GOOGLE,
19880e82232cSWei-Ning Huang 		HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_GOOGLE,
19890e82232cSWei-Ning Huang 			USB_DEVICE_ID_GOOGLE_TOUCH_ROSE) },
19900e82232cSWei-Ning Huang 
19914fa3a583SHenrik Rydberg 	/* Generic MT device */
19924fa3a583SHenrik Rydberg 	{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH, HID_ANY_ID, HID_ANY_ID) },
1993f961bd35SBenjamin Tissoires 
1994f961bd35SBenjamin Tissoires 	/* Generic Win 8 certified MT device */
1995f961bd35SBenjamin Tissoires 	{  .driver_data = MT_CLS_WIN_8,
1996f961bd35SBenjamin Tissoires 		HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH_WIN_8,
1997f961bd35SBenjamin Tissoires 			HID_ANY_ID, HID_ANY_ID) },
19985519cab4SBenjamin Tissoires 	{ }
19995519cab4SBenjamin Tissoires };
20005519cab4SBenjamin Tissoires MODULE_DEVICE_TABLE(hid, mt_devices);
20015519cab4SBenjamin Tissoires 
20025519cab4SBenjamin Tissoires static const struct hid_usage_id mt_grabbed_usages[] = {
20035519cab4SBenjamin Tissoires 	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
20045519cab4SBenjamin Tissoires 	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
20055519cab4SBenjamin Tissoires };
20065519cab4SBenjamin Tissoires 
20075519cab4SBenjamin Tissoires static struct hid_driver mt_driver = {
20085519cab4SBenjamin Tissoires 	.name = "hid-multitouch",
20095519cab4SBenjamin Tissoires 	.id_table = mt_devices,
20105519cab4SBenjamin Tissoires 	.probe = mt_probe,
20115519cab4SBenjamin Tissoires 	.remove = mt_remove,
20125519cab4SBenjamin Tissoires 	.input_mapping = mt_input_mapping,
20135519cab4SBenjamin Tissoires 	.input_mapped = mt_input_mapped,
201476f5902aSHenrik Rydberg 	.input_configured = mt_input_configured,
20155519cab4SBenjamin Tissoires 	.feature_mapping = mt_feature_mapping,
20165519cab4SBenjamin Tissoires 	.usage_table = mt_grabbed_usages,
20175519cab4SBenjamin Tissoires 	.event = mt_event,
201855978fa9SBenjamin Tissoires 	.report = mt_report,
20195519cab4SBenjamin Tissoires #ifdef CONFIG_PM
20205519cab4SBenjamin Tissoires 	.reset_resume = mt_reset_resume,
2021dfeefd10SScott Liu 	.resume = mt_resume,
20225519cab4SBenjamin Tissoires #endif
20235519cab4SBenjamin Tissoires };
2024f425458eSH Hartley Sweeten module_hid_driver(mt_driver);
2025