18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  HID driver for multitouch panels
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  Copyright (c) 2010-2012 Stephane Chatty <chatty@enac.fr>
68c2ecf20Sopenharmony_ci *  Copyright (c) 2010-2013 Benjamin Tissoires <benjamin.tissoires@gmail.com>
78c2ecf20Sopenharmony_ci *  Copyright (c) 2010-2012 Ecole Nationale de l'Aviation Civile, France
88c2ecf20Sopenharmony_ci *  Copyright (c) 2012-2013 Red Hat, Inc
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci *  This code is partly based on hid-egalax.c:
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci *  Copyright (c) 2010 Stephane Chatty <chatty@enac.fr>
138c2ecf20Sopenharmony_ci *  Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se>
148c2ecf20Sopenharmony_ci *  Copyright (c) 2010 Canonical, Ltd.
158c2ecf20Sopenharmony_ci *
168c2ecf20Sopenharmony_ci *  This code is partly based on hid-3m-pct.c:
178c2ecf20Sopenharmony_ci *
188c2ecf20Sopenharmony_ci *  Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
198c2ecf20Sopenharmony_ci *  Copyright (c) 2010      Henrik Rydberg <rydberg@euromail.se>
208c2ecf20Sopenharmony_ci *  Copyright (c) 2010      Canonical, Ltd.
218c2ecf20Sopenharmony_ci */
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci/*
248c2ecf20Sopenharmony_ci */
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci/*
278c2ecf20Sopenharmony_ci * This driver is regularly tested thanks to the test suite in hid-tools[1].
288c2ecf20Sopenharmony_ci * Please run these regression tests before patching this module so that
298c2ecf20Sopenharmony_ci * your patch won't break existing known devices.
308c2ecf20Sopenharmony_ci *
318c2ecf20Sopenharmony_ci * [1] https://gitlab.freedesktop.org/libevdev/hid-tools
328c2ecf20Sopenharmony_ci */
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci#include <linux/device.h>
358c2ecf20Sopenharmony_ci#include <linux/hid.h>
368c2ecf20Sopenharmony_ci#include <linux/module.h>
378c2ecf20Sopenharmony_ci#include <linux/slab.h>
388c2ecf20Sopenharmony_ci#include <linux/input/mt.h>
398c2ecf20Sopenharmony_ci#include <linux/jiffies.h>
408c2ecf20Sopenharmony_ci#include <linux/string.h>
418c2ecf20Sopenharmony_ci#include <linux/timer.h>
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ciMODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
458c2ecf20Sopenharmony_ciMODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
468c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("HID multitouch panels");
478c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci#include "hid-ids.h"
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci/* quirks to control the device */
528c2ecf20Sopenharmony_ci#define MT_QUIRK_NOT_SEEN_MEANS_UP	BIT(0)
538c2ecf20Sopenharmony_ci#define MT_QUIRK_SLOT_IS_CONTACTID	BIT(1)
548c2ecf20Sopenharmony_ci#define MT_QUIRK_CYPRESS		BIT(2)
558c2ecf20Sopenharmony_ci#define MT_QUIRK_SLOT_IS_CONTACTNUMBER	BIT(3)
568c2ecf20Sopenharmony_ci#define MT_QUIRK_ALWAYS_VALID		BIT(4)
578c2ecf20Sopenharmony_ci#define MT_QUIRK_VALID_IS_INRANGE	BIT(5)
588c2ecf20Sopenharmony_ci#define MT_QUIRK_VALID_IS_CONFIDENCE	BIT(6)
598c2ecf20Sopenharmony_ci#define MT_QUIRK_CONFIDENCE		BIT(7)
608c2ecf20Sopenharmony_ci#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE	BIT(8)
618c2ecf20Sopenharmony_ci#define MT_QUIRK_NO_AREA		BIT(9)
628c2ecf20Sopenharmony_ci#define MT_QUIRK_IGNORE_DUPLICATES	BIT(10)
638c2ecf20Sopenharmony_ci#define MT_QUIRK_HOVERING		BIT(11)
648c2ecf20Sopenharmony_ci#define MT_QUIRK_CONTACT_CNT_ACCURATE	BIT(12)
658c2ecf20Sopenharmony_ci#define MT_QUIRK_FORCE_GET_FEATURE	BIT(13)
668c2ecf20Sopenharmony_ci#define MT_QUIRK_FIX_CONST_CONTACT_ID	BIT(14)
678c2ecf20Sopenharmony_ci#define MT_QUIRK_TOUCH_SIZE_SCALING	BIT(15)
688c2ecf20Sopenharmony_ci#define MT_QUIRK_STICKY_FINGERS		BIT(16)
698c2ecf20Sopenharmony_ci#define MT_QUIRK_ASUS_CUSTOM_UP		BIT(17)
708c2ecf20Sopenharmony_ci#define MT_QUIRK_WIN8_PTP_BUTTONS	BIT(18)
718c2ecf20Sopenharmony_ci#define MT_QUIRK_SEPARATE_APP_REPORT	BIT(19)
728c2ecf20Sopenharmony_ci#define MT_QUIRK_FORCE_MULTI_INPUT	BIT(20)
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci#define MT_INPUTMODE_TOUCHSCREEN	0x02
758c2ecf20Sopenharmony_ci#define MT_INPUTMODE_TOUCHPAD		0x03
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci#define MT_BUTTONTYPE_CLICKPAD		0
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_cienum latency_mode {
808c2ecf20Sopenharmony_ci	HID_LATENCY_NORMAL = 0,
818c2ecf20Sopenharmony_ci	HID_LATENCY_HIGH = 1,
828c2ecf20Sopenharmony_ci};
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci#define MT_IO_FLAGS_RUNNING		0
858c2ecf20Sopenharmony_ci#define MT_IO_FLAGS_ACTIVE_SLOTS	1
868c2ecf20Sopenharmony_ci#define MT_IO_FLAGS_PENDING_SLOTS	2
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_cistatic const bool mtrue = true;		/* default for true */
898c2ecf20Sopenharmony_cistatic const bool mfalse;		/* default for false */
908c2ecf20Sopenharmony_cistatic const __s32 mzero;		/* default for 0 */
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci#define DEFAULT_TRUE	((void *)&mtrue)
938c2ecf20Sopenharmony_ci#define DEFAULT_FALSE	((void *)&mfalse)
948c2ecf20Sopenharmony_ci#define DEFAULT_ZERO	((void *)&mzero)
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_cistruct mt_usages {
978c2ecf20Sopenharmony_ci	struct list_head list;
988c2ecf20Sopenharmony_ci	__s32 *x, *y, *cx, *cy, *p, *w, *h, *a;
998c2ecf20Sopenharmony_ci	__s32 *contactid;	/* the device ContactID assigned to this slot */
1008c2ecf20Sopenharmony_ci	bool *tip_state;	/* is the touch valid? */
1018c2ecf20Sopenharmony_ci	bool *inrange_state;	/* is the finger in proximity of the sensor? */
1028c2ecf20Sopenharmony_ci	bool *confidence_state;	/* is the touch made by a finger? */
1038c2ecf20Sopenharmony_ci};
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_cistruct mt_application {
1068c2ecf20Sopenharmony_ci	struct list_head list;
1078c2ecf20Sopenharmony_ci	unsigned int application;
1088c2ecf20Sopenharmony_ci	unsigned int report_id;
1098c2ecf20Sopenharmony_ci	struct list_head mt_usages;	/* mt usages list */
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	__s32 quirks;
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	__s32 *scantime;		/* scantime reported */
1148c2ecf20Sopenharmony_ci	__s32 scantime_logical_max;	/* max value for raw scantime */
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	__s32 *raw_cc;			/* contact count in the report */
1178c2ecf20Sopenharmony_ci	int left_button_state;		/* left button state */
1188c2ecf20Sopenharmony_ci	unsigned int mt_flags;		/* flags to pass to input-mt */
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	unsigned long *pending_palm_slots;	/* slots where we reported palm
1218c2ecf20Sopenharmony_ci						 * and need to release */
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	__u8 num_received;	/* how many contacts we received */
1248c2ecf20Sopenharmony_ci	__u8 num_expected;	/* expected last contact index */
1258c2ecf20Sopenharmony_ci	__u8 buttons_count;	/* number of physical buttons per touchpad */
1268c2ecf20Sopenharmony_ci	__u8 touches_by_report;	/* how many touches are present in one report:
1278c2ecf20Sopenharmony_ci				 * 1 means we should use a serial protocol
1288c2ecf20Sopenharmony_ci				 * > 1 means hybrid (multitouch) protocol
1298c2ecf20Sopenharmony_ci				 */
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	__s32 dev_time;		/* the scan time provided by the device */
1328c2ecf20Sopenharmony_ci	unsigned long jiffies;	/* the frame's jiffies */
1338c2ecf20Sopenharmony_ci	int timestamp;		/* the timestamp to be sent */
1348c2ecf20Sopenharmony_ci	int prev_scantime;		/* scantime reported previously */
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	bool have_contact_count;
1378c2ecf20Sopenharmony_ci};
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_cistruct mt_class {
1408c2ecf20Sopenharmony_ci	__s32 name;	/* MT_CLS */
1418c2ecf20Sopenharmony_ci	__s32 quirks;
1428c2ecf20Sopenharmony_ci	__s32 sn_move;	/* Signal/noise ratio for move events */
1438c2ecf20Sopenharmony_ci	__s32 sn_width;	/* Signal/noise ratio for width events */
1448c2ecf20Sopenharmony_ci	__s32 sn_height;	/* Signal/noise ratio for height events */
1458c2ecf20Sopenharmony_ci	__s32 sn_pressure;	/* Signal/noise ratio for pressure events */
1468c2ecf20Sopenharmony_ci	__u8 maxcontacts;
1478c2ecf20Sopenharmony_ci	bool is_indirect;	/* true for touchpads */
1488c2ecf20Sopenharmony_ci	bool export_all_inputs;	/* do not ignore mouse, keyboards, etc... */
1498c2ecf20Sopenharmony_ci};
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_cistruct mt_report_data {
1528c2ecf20Sopenharmony_ci	struct list_head list;
1538c2ecf20Sopenharmony_ci	struct hid_report *report;
1548c2ecf20Sopenharmony_ci	struct mt_application *application;
1558c2ecf20Sopenharmony_ci	bool is_mt_collection;
1568c2ecf20Sopenharmony_ci};
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_cistruct mt_device {
1598c2ecf20Sopenharmony_ci	struct mt_class mtclass;	/* our mt device class */
1608c2ecf20Sopenharmony_ci	struct timer_list release_timer;	/* to release sticky fingers */
1618c2ecf20Sopenharmony_ci	struct hid_device *hdev;	/* hid_device we're attached to */
1628c2ecf20Sopenharmony_ci	unsigned long mt_io_flags;	/* mt flags (MT_IO_FLAGS_*) */
1638c2ecf20Sopenharmony_ci	__u8 inputmode_value;	/* InputMode HID feature value */
1648c2ecf20Sopenharmony_ci	__u8 maxcontacts;
1658c2ecf20Sopenharmony_ci	bool is_buttonpad;	/* is this device a button pad? */
1668c2ecf20Sopenharmony_ci	bool serial_maybe;	/* need to check for serial protocol */
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	struct list_head applications;
1698c2ecf20Sopenharmony_ci	struct list_head reports;
1708c2ecf20Sopenharmony_ci};
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_cistatic void mt_post_parse_default_settings(struct mt_device *td,
1738c2ecf20Sopenharmony_ci					   struct mt_application *app);
1748c2ecf20Sopenharmony_cistatic void mt_post_parse(struct mt_device *td, struct mt_application *app);
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci/* classes of device behavior */
1778c2ecf20Sopenharmony_ci#define MT_CLS_DEFAULT				0x0001
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci#define MT_CLS_SERIAL				0x0002
1808c2ecf20Sopenharmony_ci#define MT_CLS_CONFIDENCE			0x0003
1818c2ecf20Sopenharmony_ci#define MT_CLS_CONFIDENCE_CONTACT_ID		0x0004
1828c2ecf20Sopenharmony_ci#define MT_CLS_CONFIDENCE_MINUS_ONE		0x0005
1838c2ecf20Sopenharmony_ci#define MT_CLS_DUAL_INRANGE_CONTACTID		0x0006
1848c2ecf20Sopenharmony_ci#define MT_CLS_DUAL_INRANGE_CONTACTNUMBER	0x0007
1858c2ecf20Sopenharmony_ci/* reserved					0x0008 */
1868c2ecf20Sopenharmony_ci#define MT_CLS_INRANGE_CONTACTNUMBER		0x0009
1878c2ecf20Sopenharmony_ci#define MT_CLS_NSMU				0x000a
1888c2ecf20Sopenharmony_ci/* reserved					0x0010 */
1898c2ecf20Sopenharmony_ci/* reserved					0x0011 */
1908c2ecf20Sopenharmony_ci#define MT_CLS_WIN_8				0x0012
1918c2ecf20Sopenharmony_ci#define MT_CLS_EXPORT_ALL_INPUTS		0x0013
1928c2ecf20Sopenharmony_ci/* reserved					0x0014 */
1938c2ecf20Sopenharmony_ci#define MT_CLS_WIN_8_FORCE_MULTI_INPUT		0x0015
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci/* vendor specific classes */
1968c2ecf20Sopenharmony_ci#define MT_CLS_3M				0x0101
1978c2ecf20Sopenharmony_ci/* reserved					0x0102 */
1988c2ecf20Sopenharmony_ci#define MT_CLS_EGALAX				0x0103
1998c2ecf20Sopenharmony_ci#define MT_CLS_EGALAX_SERIAL			0x0104
2008c2ecf20Sopenharmony_ci#define MT_CLS_TOPSEED				0x0105
2018c2ecf20Sopenharmony_ci#define MT_CLS_PANASONIC			0x0106
2028c2ecf20Sopenharmony_ci#define MT_CLS_FLATFROG				0x0107
2038c2ecf20Sopenharmony_ci#define MT_CLS_GENERALTOUCH_TWOFINGERS		0x0108
2048c2ecf20Sopenharmony_ci#define MT_CLS_GENERALTOUCH_PWT_TENFINGERS	0x0109
2058c2ecf20Sopenharmony_ci#define MT_CLS_LG				0x010a
2068c2ecf20Sopenharmony_ci#define MT_CLS_ASUS				0x010b
2078c2ecf20Sopenharmony_ci#define MT_CLS_VTL				0x0110
2088c2ecf20Sopenharmony_ci#define MT_CLS_GOOGLE				0x0111
2098c2ecf20Sopenharmony_ci#define MT_CLS_RAZER_BLADE_STEALTH		0x0112
2108c2ecf20Sopenharmony_ci#define MT_CLS_SMART_TECH			0x0113
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci#define MT_DEFAULT_MAXCONTACT	10
2138c2ecf20Sopenharmony_ci#define MT_MAX_MAXCONTACT	250
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci/*
2168c2ecf20Sopenharmony_ci * Resync device and local timestamps after that many microseconds without
2178c2ecf20Sopenharmony_ci * receiving data.
2188c2ecf20Sopenharmony_ci */
2198c2ecf20Sopenharmony_ci#define MAX_TIMESTAMP_INTERVAL	1000000
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci#define MT_USB_DEVICE(v, p)	HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH, v, p)
2228c2ecf20Sopenharmony_ci#define MT_BT_DEVICE(v, p)	HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_MULTITOUCH, v, p)
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci/*
2258c2ecf20Sopenharmony_ci * these device-dependent functions determine what slot corresponds
2268c2ecf20Sopenharmony_ci * to a valid contact that was just read.
2278c2ecf20Sopenharmony_ci */
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_cistatic int cypress_compute_slot(struct mt_application *application,
2308c2ecf20Sopenharmony_ci				struct mt_usages *slot)
2318c2ecf20Sopenharmony_ci{
2328c2ecf20Sopenharmony_ci	if (*slot->contactid != 0 || application->num_received == 0)
2338c2ecf20Sopenharmony_ci		return *slot->contactid;
2348c2ecf20Sopenharmony_ci	else
2358c2ecf20Sopenharmony_ci		return -1;
2368c2ecf20Sopenharmony_ci}
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_cistatic const struct mt_class mt_classes[] = {
2398c2ecf20Sopenharmony_ci	{ .name = MT_CLS_DEFAULT,
2408c2ecf20Sopenharmony_ci		.quirks = MT_QUIRK_ALWAYS_VALID |
2418c2ecf20Sopenharmony_ci			MT_QUIRK_CONTACT_CNT_ACCURATE },
2428c2ecf20Sopenharmony_ci	{ .name = MT_CLS_NSMU,
2438c2ecf20Sopenharmony_ci		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP },
2448c2ecf20Sopenharmony_ci	{ .name = MT_CLS_SERIAL,
2458c2ecf20Sopenharmony_ci		.quirks = MT_QUIRK_ALWAYS_VALID},
2468c2ecf20Sopenharmony_ci	{ .name = MT_CLS_CONFIDENCE,
2478c2ecf20Sopenharmony_ci		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE },
2488c2ecf20Sopenharmony_ci	{ .name = MT_CLS_CONFIDENCE_CONTACT_ID,
2498c2ecf20Sopenharmony_ci		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
2508c2ecf20Sopenharmony_ci			MT_QUIRK_SLOT_IS_CONTACTID },
2518c2ecf20Sopenharmony_ci	{ .name = MT_CLS_CONFIDENCE_MINUS_ONE,
2528c2ecf20Sopenharmony_ci		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
2538c2ecf20Sopenharmony_ci			MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE },
2548c2ecf20Sopenharmony_ci	{ .name = MT_CLS_DUAL_INRANGE_CONTACTID,
2558c2ecf20Sopenharmony_ci		.quirks = MT_QUIRK_VALID_IS_INRANGE |
2568c2ecf20Sopenharmony_ci			MT_QUIRK_SLOT_IS_CONTACTID,
2578c2ecf20Sopenharmony_ci		.maxcontacts = 2 },
2588c2ecf20Sopenharmony_ci	{ .name = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
2598c2ecf20Sopenharmony_ci		.quirks = MT_QUIRK_VALID_IS_INRANGE |
2608c2ecf20Sopenharmony_ci			MT_QUIRK_SLOT_IS_CONTACTNUMBER,
2618c2ecf20Sopenharmony_ci		.maxcontacts = 2 },
2628c2ecf20Sopenharmony_ci	{ .name = MT_CLS_INRANGE_CONTACTNUMBER,
2638c2ecf20Sopenharmony_ci		.quirks = MT_QUIRK_VALID_IS_INRANGE |
2648c2ecf20Sopenharmony_ci			MT_QUIRK_SLOT_IS_CONTACTNUMBER },
2658c2ecf20Sopenharmony_ci	{ .name = MT_CLS_WIN_8,
2668c2ecf20Sopenharmony_ci		.quirks = MT_QUIRK_ALWAYS_VALID |
2678c2ecf20Sopenharmony_ci			MT_QUIRK_IGNORE_DUPLICATES |
2688c2ecf20Sopenharmony_ci			MT_QUIRK_HOVERING |
2698c2ecf20Sopenharmony_ci			MT_QUIRK_CONTACT_CNT_ACCURATE |
2708c2ecf20Sopenharmony_ci			MT_QUIRK_STICKY_FINGERS |
2718c2ecf20Sopenharmony_ci			MT_QUIRK_WIN8_PTP_BUTTONS,
2728c2ecf20Sopenharmony_ci		.export_all_inputs = true },
2738c2ecf20Sopenharmony_ci	{ .name = MT_CLS_EXPORT_ALL_INPUTS,
2748c2ecf20Sopenharmony_ci		.quirks = MT_QUIRK_ALWAYS_VALID |
2758c2ecf20Sopenharmony_ci			MT_QUIRK_CONTACT_CNT_ACCURATE,
2768c2ecf20Sopenharmony_ci		.export_all_inputs = true },
2778c2ecf20Sopenharmony_ci	{ .name = MT_CLS_WIN_8_FORCE_MULTI_INPUT,
2788c2ecf20Sopenharmony_ci		.quirks = MT_QUIRK_ALWAYS_VALID |
2798c2ecf20Sopenharmony_ci			MT_QUIRK_IGNORE_DUPLICATES |
2808c2ecf20Sopenharmony_ci			MT_QUIRK_HOVERING |
2818c2ecf20Sopenharmony_ci			MT_QUIRK_CONTACT_CNT_ACCURATE |
2828c2ecf20Sopenharmony_ci			MT_QUIRK_STICKY_FINGERS |
2838c2ecf20Sopenharmony_ci			MT_QUIRK_WIN8_PTP_BUTTONS |
2848c2ecf20Sopenharmony_ci			MT_QUIRK_FORCE_MULTI_INPUT,
2858c2ecf20Sopenharmony_ci		.export_all_inputs = true },
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	/*
2888c2ecf20Sopenharmony_ci	 * vendor specific classes
2898c2ecf20Sopenharmony_ci	 */
2908c2ecf20Sopenharmony_ci	{ .name = MT_CLS_3M,
2918c2ecf20Sopenharmony_ci		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
2928c2ecf20Sopenharmony_ci			MT_QUIRK_SLOT_IS_CONTACTID |
2938c2ecf20Sopenharmony_ci			MT_QUIRK_TOUCH_SIZE_SCALING,
2948c2ecf20Sopenharmony_ci		.sn_move = 2048,
2958c2ecf20Sopenharmony_ci		.sn_width = 128,
2968c2ecf20Sopenharmony_ci		.sn_height = 128,
2978c2ecf20Sopenharmony_ci		.maxcontacts = 60,
2988c2ecf20Sopenharmony_ci	},
2998c2ecf20Sopenharmony_ci	{ .name = MT_CLS_EGALAX,
3008c2ecf20Sopenharmony_ci		.quirks =  MT_QUIRK_SLOT_IS_CONTACTID |
3018c2ecf20Sopenharmony_ci			MT_QUIRK_VALID_IS_INRANGE,
3028c2ecf20Sopenharmony_ci		.sn_move = 4096,
3038c2ecf20Sopenharmony_ci		.sn_pressure = 32,
3048c2ecf20Sopenharmony_ci	},
3058c2ecf20Sopenharmony_ci	{ .name = MT_CLS_EGALAX_SERIAL,
3068c2ecf20Sopenharmony_ci		.quirks =  MT_QUIRK_SLOT_IS_CONTACTID |
3078c2ecf20Sopenharmony_ci			MT_QUIRK_ALWAYS_VALID,
3088c2ecf20Sopenharmony_ci		.sn_move = 4096,
3098c2ecf20Sopenharmony_ci		.sn_pressure = 32,
3108c2ecf20Sopenharmony_ci	},
3118c2ecf20Sopenharmony_ci	{ .name = MT_CLS_TOPSEED,
3128c2ecf20Sopenharmony_ci		.quirks = MT_QUIRK_ALWAYS_VALID,
3138c2ecf20Sopenharmony_ci		.is_indirect = true,
3148c2ecf20Sopenharmony_ci		.maxcontacts = 2,
3158c2ecf20Sopenharmony_ci	},
3168c2ecf20Sopenharmony_ci	{ .name = MT_CLS_PANASONIC,
3178c2ecf20Sopenharmony_ci		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP,
3188c2ecf20Sopenharmony_ci		.maxcontacts = 4 },
3198c2ecf20Sopenharmony_ci	{ .name	= MT_CLS_GENERALTOUCH_TWOFINGERS,
3208c2ecf20Sopenharmony_ci		.quirks	= MT_QUIRK_NOT_SEEN_MEANS_UP |
3218c2ecf20Sopenharmony_ci			MT_QUIRK_VALID_IS_INRANGE |
3228c2ecf20Sopenharmony_ci			MT_QUIRK_SLOT_IS_CONTACTID,
3238c2ecf20Sopenharmony_ci		.maxcontacts = 2
3248c2ecf20Sopenharmony_ci	},
3258c2ecf20Sopenharmony_ci	{ .name	= MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
3268c2ecf20Sopenharmony_ci		.quirks	= MT_QUIRK_NOT_SEEN_MEANS_UP |
3278c2ecf20Sopenharmony_ci			MT_QUIRK_SLOT_IS_CONTACTID
3288c2ecf20Sopenharmony_ci	},
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	{ .name = MT_CLS_FLATFROG,
3318c2ecf20Sopenharmony_ci		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
3328c2ecf20Sopenharmony_ci			MT_QUIRK_NO_AREA,
3338c2ecf20Sopenharmony_ci		.sn_move = 2048,
3348c2ecf20Sopenharmony_ci		.maxcontacts = 40,
3358c2ecf20Sopenharmony_ci	},
3368c2ecf20Sopenharmony_ci	{ .name = MT_CLS_LG,
3378c2ecf20Sopenharmony_ci		.quirks = MT_QUIRK_ALWAYS_VALID |
3388c2ecf20Sopenharmony_ci			MT_QUIRK_FIX_CONST_CONTACT_ID |
3398c2ecf20Sopenharmony_ci			MT_QUIRK_IGNORE_DUPLICATES |
3408c2ecf20Sopenharmony_ci			MT_QUIRK_HOVERING |
3418c2ecf20Sopenharmony_ci			MT_QUIRK_CONTACT_CNT_ACCURATE },
3428c2ecf20Sopenharmony_ci	{ .name = MT_CLS_ASUS,
3438c2ecf20Sopenharmony_ci		.quirks = MT_QUIRK_ALWAYS_VALID |
3448c2ecf20Sopenharmony_ci			MT_QUIRK_CONTACT_CNT_ACCURATE |
3458c2ecf20Sopenharmony_ci			MT_QUIRK_ASUS_CUSTOM_UP },
3468c2ecf20Sopenharmony_ci	{ .name = MT_CLS_VTL,
3478c2ecf20Sopenharmony_ci		.quirks = MT_QUIRK_ALWAYS_VALID |
3488c2ecf20Sopenharmony_ci			MT_QUIRK_CONTACT_CNT_ACCURATE |
3498c2ecf20Sopenharmony_ci			MT_QUIRK_FORCE_GET_FEATURE,
3508c2ecf20Sopenharmony_ci	},
3518c2ecf20Sopenharmony_ci	{ .name = MT_CLS_GOOGLE,
3528c2ecf20Sopenharmony_ci		.quirks = MT_QUIRK_ALWAYS_VALID |
3538c2ecf20Sopenharmony_ci			MT_QUIRK_CONTACT_CNT_ACCURATE |
3548c2ecf20Sopenharmony_ci			MT_QUIRK_SLOT_IS_CONTACTID |
3558c2ecf20Sopenharmony_ci			MT_QUIRK_HOVERING
3568c2ecf20Sopenharmony_ci	},
3578c2ecf20Sopenharmony_ci	{ .name = MT_CLS_RAZER_BLADE_STEALTH,
3588c2ecf20Sopenharmony_ci		.quirks = MT_QUIRK_ALWAYS_VALID |
3598c2ecf20Sopenharmony_ci			MT_QUIRK_IGNORE_DUPLICATES |
3608c2ecf20Sopenharmony_ci			MT_QUIRK_HOVERING |
3618c2ecf20Sopenharmony_ci			MT_QUIRK_CONTACT_CNT_ACCURATE |
3628c2ecf20Sopenharmony_ci			MT_QUIRK_WIN8_PTP_BUTTONS,
3638c2ecf20Sopenharmony_ci	},
3648c2ecf20Sopenharmony_ci	{ .name = MT_CLS_SMART_TECH,
3658c2ecf20Sopenharmony_ci		.quirks = MT_QUIRK_ALWAYS_VALID |
3668c2ecf20Sopenharmony_ci			MT_QUIRK_IGNORE_DUPLICATES |
3678c2ecf20Sopenharmony_ci			MT_QUIRK_CONTACT_CNT_ACCURATE |
3688c2ecf20Sopenharmony_ci			MT_QUIRK_SEPARATE_APP_REPORT,
3698c2ecf20Sopenharmony_ci	},
3708c2ecf20Sopenharmony_ci	{ }
3718c2ecf20Sopenharmony_ci};
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_cistatic ssize_t mt_show_quirks(struct device *dev,
3748c2ecf20Sopenharmony_ci			   struct device_attribute *attr,
3758c2ecf20Sopenharmony_ci			   char *buf)
3768c2ecf20Sopenharmony_ci{
3778c2ecf20Sopenharmony_ci	struct hid_device *hdev = to_hid_device(dev);
3788c2ecf20Sopenharmony_ci	struct mt_device *td = hid_get_drvdata(hdev);
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	return sprintf(buf, "%u\n", td->mtclass.quirks);
3818c2ecf20Sopenharmony_ci}
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_cistatic ssize_t mt_set_quirks(struct device *dev,
3848c2ecf20Sopenharmony_ci			  struct device_attribute *attr,
3858c2ecf20Sopenharmony_ci			  const char *buf, size_t count)
3868c2ecf20Sopenharmony_ci{
3878c2ecf20Sopenharmony_ci	struct hid_device *hdev = to_hid_device(dev);
3888c2ecf20Sopenharmony_ci	struct mt_device *td = hid_get_drvdata(hdev);
3898c2ecf20Sopenharmony_ci	struct mt_application *application;
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci	unsigned long val;
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	if (kstrtoul(buf, 0, &val))
3948c2ecf20Sopenharmony_ci		return -EINVAL;
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	td->mtclass.quirks = val;
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	list_for_each_entry(application, &td->applications, list) {
3998c2ecf20Sopenharmony_ci		application->quirks = val;
4008c2ecf20Sopenharmony_ci		if (!application->have_contact_count)
4018c2ecf20Sopenharmony_ci			application->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
4028c2ecf20Sopenharmony_ci	}
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci	return count;
4058c2ecf20Sopenharmony_ci}
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_cistatic DEVICE_ATTR(quirks, S_IWUSR | S_IRUGO, mt_show_quirks, mt_set_quirks);
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_cistatic struct attribute *sysfs_attrs[] = {
4108c2ecf20Sopenharmony_ci	&dev_attr_quirks.attr,
4118c2ecf20Sopenharmony_ci	NULL
4128c2ecf20Sopenharmony_ci};
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_cistatic const struct attribute_group mt_attribute_group = {
4158c2ecf20Sopenharmony_ci	.attrs = sysfs_attrs
4168c2ecf20Sopenharmony_ci};
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_cistatic void mt_get_feature(struct hid_device *hdev, struct hid_report *report)
4198c2ecf20Sopenharmony_ci{
4208c2ecf20Sopenharmony_ci	int ret;
4218c2ecf20Sopenharmony_ci	u32 size = hid_report_len(report);
4228c2ecf20Sopenharmony_ci	u8 *buf;
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	/*
4258c2ecf20Sopenharmony_ci	 * Do not fetch the feature report if the device has been explicitly
4268c2ecf20Sopenharmony_ci	 * marked as non-capable.
4278c2ecf20Sopenharmony_ci	 */
4288c2ecf20Sopenharmony_ci	if (hdev->quirks & HID_QUIRK_NO_INIT_REPORTS)
4298c2ecf20Sopenharmony_ci		return;
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	buf = hid_alloc_report_buf(report, GFP_KERNEL);
4328c2ecf20Sopenharmony_ci	if (!buf)
4338c2ecf20Sopenharmony_ci		return;
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	ret = hid_hw_raw_request(hdev, report->id, buf, size,
4368c2ecf20Sopenharmony_ci				 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
4378c2ecf20Sopenharmony_ci	if (ret < 0) {
4388c2ecf20Sopenharmony_ci		dev_warn(&hdev->dev, "failed to fetch feature %d\n",
4398c2ecf20Sopenharmony_ci			 report->id);
4408c2ecf20Sopenharmony_ci	} else {
4418c2ecf20Sopenharmony_ci		ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf,
4428c2ecf20Sopenharmony_ci					   size, 0);
4438c2ecf20Sopenharmony_ci		if (ret)
4448c2ecf20Sopenharmony_ci			dev_warn(&hdev->dev, "failed to report feature\n");
4458c2ecf20Sopenharmony_ci	}
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci	kfree(buf);
4488c2ecf20Sopenharmony_ci}
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_cistatic void mt_feature_mapping(struct hid_device *hdev,
4518c2ecf20Sopenharmony_ci		struct hid_field *field, struct hid_usage *usage)
4528c2ecf20Sopenharmony_ci{
4538c2ecf20Sopenharmony_ci	struct mt_device *td = hid_get_drvdata(hdev);
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci	switch (usage->hid) {
4568c2ecf20Sopenharmony_ci	case HID_DG_CONTACTMAX:
4578c2ecf20Sopenharmony_ci		mt_get_feature(hdev, field->report);
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci		td->maxcontacts = field->value[0];
4608c2ecf20Sopenharmony_ci		if (!td->maxcontacts &&
4618c2ecf20Sopenharmony_ci		    field->logical_maximum <= MT_MAX_MAXCONTACT)
4628c2ecf20Sopenharmony_ci			td->maxcontacts = field->logical_maximum;
4638c2ecf20Sopenharmony_ci		if (td->mtclass.maxcontacts)
4648c2ecf20Sopenharmony_ci			/* check if the maxcontacts is given by the class */
4658c2ecf20Sopenharmony_ci			td->maxcontacts = td->mtclass.maxcontacts;
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci		break;
4688c2ecf20Sopenharmony_ci	case HID_DG_BUTTONTYPE:
4698c2ecf20Sopenharmony_ci		if (usage->usage_index >= field->report_count) {
4708c2ecf20Sopenharmony_ci			dev_err(&hdev->dev, "HID_DG_BUTTONTYPE out of range\n");
4718c2ecf20Sopenharmony_ci			break;
4728c2ecf20Sopenharmony_ci		}
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci		mt_get_feature(hdev, field->report);
4758c2ecf20Sopenharmony_ci		if (field->value[usage->usage_index] == MT_BUTTONTYPE_CLICKPAD)
4768c2ecf20Sopenharmony_ci			td->is_buttonpad = true;
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci		break;
4798c2ecf20Sopenharmony_ci	case 0xff0000c5:
4808c2ecf20Sopenharmony_ci		/* Retrieve the Win8 blob once to enable some devices */
4818c2ecf20Sopenharmony_ci		if (usage->usage_index == 0)
4828c2ecf20Sopenharmony_ci			mt_get_feature(hdev, field->report);
4838c2ecf20Sopenharmony_ci		break;
4848c2ecf20Sopenharmony_ci	}
4858c2ecf20Sopenharmony_ci}
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_cistatic void set_abs(struct input_dev *input, unsigned int code,
4888c2ecf20Sopenharmony_ci		struct hid_field *field, int snratio)
4898c2ecf20Sopenharmony_ci{
4908c2ecf20Sopenharmony_ci	int fmin = field->logical_minimum;
4918c2ecf20Sopenharmony_ci	int fmax = field->logical_maximum;
4928c2ecf20Sopenharmony_ci	int fuzz = snratio ? (fmax - fmin) / snratio : 0;
4938c2ecf20Sopenharmony_ci	input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
4948c2ecf20Sopenharmony_ci	input_abs_set_res(input, code, hidinput_calc_abs_res(field, code));
4958c2ecf20Sopenharmony_ci}
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_cistatic struct mt_usages *mt_allocate_usage(struct hid_device *hdev,
4988c2ecf20Sopenharmony_ci					   struct mt_application *application)
4998c2ecf20Sopenharmony_ci{
5008c2ecf20Sopenharmony_ci	struct mt_usages *usage;
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	usage = devm_kzalloc(&hdev->dev, sizeof(*usage), GFP_KERNEL);
5038c2ecf20Sopenharmony_ci	if (!usage)
5048c2ecf20Sopenharmony_ci		return NULL;
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	/* set some defaults so we do not need to check for null pointers */
5078c2ecf20Sopenharmony_ci	usage->x = DEFAULT_ZERO;
5088c2ecf20Sopenharmony_ci	usage->y = DEFAULT_ZERO;
5098c2ecf20Sopenharmony_ci	usage->cx = DEFAULT_ZERO;
5108c2ecf20Sopenharmony_ci	usage->cy = DEFAULT_ZERO;
5118c2ecf20Sopenharmony_ci	usage->p = DEFAULT_ZERO;
5128c2ecf20Sopenharmony_ci	usage->w = DEFAULT_ZERO;
5138c2ecf20Sopenharmony_ci	usage->h = DEFAULT_ZERO;
5148c2ecf20Sopenharmony_ci	usage->a = DEFAULT_ZERO;
5158c2ecf20Sopenharmony_ci	usage->contactid = DEFAULT_ZERO;
5168c2ecf20Sopenharmony_ci	usage->tip_state = DEFAULT_FALSE;
5178c2ecf20Sopenharmony_ci	usage->inrange_state = DEFAULT_FALSE;
5188c2ecf20Sopenharmony_ci	usage->confidence_state = DEFAULT_TRUE;
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	list_add_tail(&usage->list, &application->mt_usages);
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	return usage;
5238c2ecf20Sopenharmony_ci}
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_cistatic struct mt_application *mt_allocate_application(struct mt_device *td,
5268c2ecf20Sopenharmony_ci						      struct hid_report *report)
5278c2ecf20Sopenharmony_ci{
5288c2ecf20Sopenharmony_ci	unsigned int application = report->application;
5298c2ecf20Sopenharmony_ci	struct mt_application *mt_application;
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	mt_application = devm_kzalloc(&td->hdev->dev, sizeof(*mt_application),
5328c2ecf20Sopenharmony_ci				      GFP_KERNEL);
5338c2ecf20Sopenharmony_ci	if (!mt_application)
5348c2ecf20Sopenharmony_ci		return NULL;
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	mt_application->application = application;
5378c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&mt_application->mt_usages);
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	if (application == HID_DG_TOUCHSCREEN)
5408c2ecf20Sopenharmony_ci		mt_application->mt_flags |= INPUT_MT_DIRECT;
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci	/*
5438c2ecf20Sopenharmony_ci	 * Model touchscreens providing buttons as touchpads.
5448c2ecf20Sopenharmony_ci	 */
5458c2ecf20Sopenharmony_ci	if (application == HID_DG_TOUCHPAD) {
5468c2ecf20Sopenharmony_ci		mt_application->mt_flags |= INPUT_MT_POINTER;
5478c2ecf20Sopenharmony_ci		td->inputmode_value = MT_INPUTMODE_TOUCHPAD;
5488c2ecf20Sopenharmony_ci	}
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci	mt_application->scantime = DEFAULT_ZERO;
5518c2ecf20Sopenharmony_ci	mt_application->raw_cc = DEFAULT_ZERO;
5528c2ecf20Sopenharmony_ci	mt_application->quirks = td->mtclass.quirks;
5538c2ecf20Sopenharmony_ci	mt_application->report_id = report->id;
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci	list_add_tail(&mt_application->list, &td->applications);
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	return mt_application;
5588c2ecf20Sopenharmony_ci}
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_cistatic struct mt_application *mt_find_application(struct mt_device *td,
5618c2ecf20Sopenharmony_ci						  struct hid_report *report)
5628c2ecf20Sopenharmony_ci{
5638c2ecf20Sopenharmony_ci	unsigned int application = report->application;
5648c2ecf20Sopenharmony_ci	struct mt_application *tmp, *mt_application = NULL;
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	list_for_each_entry(tmp, &td->applications, list) {
5678c2ecf20Sopenharmony_ci		if (application == tmp->application) {
5688c2ecf20Sopenharmony_ci			if (!(td->mtclass.quirks & MT_QUIRK_SEPARATE_APP_REPORT) ||
5698c2ecf20Sopenharmony_ci			    tmp->report_id == report->id) {
5708c2ecf20Sopenharmony_ci				mt_application = tmp;
5718c2ecf20Sopenharmony_ci				break;
5728c2ecf20Sopenharmony_ci			}
5738c2ecf20Sopenharmony_ci		}
5748c2ecf20Sopenharmony_ci	}
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci	if (!mt_application)
5778c2ecf20Sopenharmony_ci		mt_application = mt_allocate_application(td, report);
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	return mt_application;
5808c2ecf20Sopenharmony_ci}
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_cistatic struct mt_report_data *mt_allocate_report_data(struct mt_device *td,
5838c2ecf20Sopenharmony_ci						      struct hid_report *report)
5848c2ecf20Sopenharmony_ci{
5858c2ecf20Sopenharmony_ci	struct mt_report_data *rdata;
5868c2ecf20Sopenharmony_ci	struct hid_field *field;
5878c2ecf20Sopenharmony_ci	int r, n;
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	rdata = devm_kzalloc(&td->hdev->dev, sizeof(*rdata), GFP_KERNEL);
5908c2ecf20Sopenharmony_ci	if (!rdata)
5918c2ecf20Sopenharmony_ci		return NULL;
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	rdata->report = report;
5948c2ecf20Sopenharmony_ci	rdata->application = mt_find_application(td, report);
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	if (!rdata->application) {
5978c2ecf20Sopenharmony_ci		devm_kfree(&td->hdev->dev, rdata);
5988c2ecf20Sopenharmony_ci		return NULL;
5998c2ecf20Sopenharmony_ci	}
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci	for (r = 0; r < report->maxfield; r++) {
6028c2ecf20Sopenharmony_ci		field = report->field[r];
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci		if (!(HID_MAIN_ITEM_VARIABLE & field->flags))
6058c2ecf20Sopenharmony_ci			continue;
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci		if (field->logical == HID_DG_FINGER || td->hdev->group != HID_GROUP_MULTITOUCH_WIN_8) {
6088c2ecf20Sopenharmony_ci			for (n = 0; n < field->report_count; n++) {
6098c2ecf20Sopenharmony_ci				if (field->usage[n].hid == HID_DG_CONTACTID) {
6108c2ecf20Sopenharmony_ci					rdata->is_mt_collection = true;
6118c2ecf20Sopenharmony_ci					break;
6128c2ecf20Sopenharmony_ci				}
6138c2ecf20Sopenharmony_ci			}
6148c2ecf20Sopenharmony_ci		}
6158c2ecf20Sopenharmony_ci	}
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	list_add_tail(&rdata->list, &td->reports);
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	return rdata;
6208c2ecf20Sopenharmony_ci}
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_cistatic struct mt_report_data *mt_find_report_data(struct mt_device *td,
6238c2ecf20Sopenharmony_ci						  struct hid_report *report)
6248c2ecf20Sopenharmony_ci{
6258c2ecf20Sopenharmony_ci	struct mt_report_data *tmp, *rdata = NULL;
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	list_for_each_entry(tmp, &td->reports, list) {
6288c2ecf20Sopenharmony_ci		if (report == tmp->report) {
6298c2ecf20Sopenharmony_ci			rdata = tmp;
6308c2ecf20Sopenharmony_ci			break;
6318c2ecf20Sopenharmony_ci		}
6328c2ecf20Sopenharmony_ci	}
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	if (!rdata)
6358c2ecf20Sopenharmony_ci		rdata = mt_allocate_report_data(td, report);
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	return rdata;
6388c2ecf20Sopenharmony_ci}
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_cistatic void mt_store_field(struct hid_device *hdev,
6418c2ecf20Sopenharmony_ci			   struct mt_application *application,
6428c2ecf20Sopenharmony_ci			   __s32 *value,
6438c2ecf20Sopenharmony_ci			   size_t offset)
6448c2ecf20Sopenharmony_ci{
6458c2ecf20Sopenharmony_ci	struct mt_usages *usage;
6468c2ecf20Sopenharmony_ci	__s32 **target;
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	if (list_empty(&application->mt_usages))
6498c2ecf20Sopenharmony_ci		usage = mt_allocate_usage(hdev, application);
6508c2ecf20Sopenharmony_ci	else
6518c2ecf20Sopenharmony_ci		usage = list_last_entry(&application->mt_usages,
6528c2ecf20Sopenharmony_ci					struct mt_usages,
6538c2ecf20Sopenharmony_ci					list);
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	if (!usage)
6568c2ecf20Sopenharmony_ci		return;
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci	target = (__s32 **)((char *)usage + offset);
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	/* the value has already been filled, create a new slot */
6618c2ecf20Sopenharmony_ci	if (*target != DEFAULT_TRUE &&
6628c2ecf20Sopenharmony_ci	    *target != DEFAULT_FALSE &&
6638c2ecf20Sopenharmony_ci	    *target != DEFAULT_ZERO) {
6648c2ecf20Sopenharmony_ci		if (usage->contactid == DEFAULT_ZERO ||
6658c2ecf20Sopenharmony_ci		    usage->x == DEFAULT_ZERO ||
6668c2ecf20Sopenharmony_ci		    usage->y == DEFAULT_ZERO) {
6678c2ecf20Sopenharmony_ci			hid_dbg(hdev,
6688c2ecf20Sopenharmony_ci				"ignoring duplicate usage on incomplete");
6698c2ecf20Sopenharmony_ci			return;
6708c2ecf20Sopenharmony_ci		}
6718c2ecf20Sopenharmony_ci		usage = mt_allocate_usage(hdev, application);
6728c2ecf20Sopenharmony_ci		if (!usage)
6738c2ecf20Sopenharmony_ci			return;
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci		target = (__s32 **)((char *)usage + offset);
6768c2ecf20Sopenharmony_ci	}
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	*target = value;
6798c2ecf20Sopenharmony_ci}
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci#define MT_STORE_FIELD(__name)						\
6828c2ecf20Sopenharmony_ci	mt_store_field(hdev, app,					\
6838c2ecf20Sopenharmony_ci		       &field->value[usage->usage_index],		\
6848c2ecf20Sopenharmony_ci		       offsetof(struct mt_usages, __name))
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_cistatic int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
6878c2ecf20Sopenharmony_ci		struct hid_field *field, struct hid_usage *usage,
6888c2ecf20Sopenharmony_ci		unsigned long **bit, int *max, struct mt_application *app)
6898c2ecf20Sopenharmony_ci{
6908c2ecf20Sopenharmony_ci	struct mt_device *td = hid_get_drvdata(hdev);
6918c2ecf20Sopenharmony_ci	struct mt_class *cls = &td->mtclass;
6928c2ecf20Sopenharmony_ci	int code;
6938c2ecf20Sopenharmony_ci	struct hid_usage *prev_usage = NULL;
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci	/*
6968c2ecf20Sopenharmony_ci	 * Model touchscreens providing buttons as touchpads.
6978c2ecf20Sopenharmony_ci	 */
6988c2ecf20Sopenharmony_ci	if (field->application == HID_DG_TOUCHSCREEN &&
6998c2ecf20Sopenharmony_ci	    (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {
7008c2ecf20Sopenharmony_ci		app->mt_flags |= INPUT_MT_POINTER;
7018c2ecf20Sopenharmony_ci		td->inputmode_value = MT_INPUTMODE_TOUCHPAD;
7028c2ecf20Sopenharmony_ci	}
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_ci	/* count the buttons on touchpads */
7058c2ecf20Sopenharmony_ci	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON)
7068c2ecf20Sopenharmony_ci		app->buttons_count++;
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_ci	if (usage->usage_index)
7098c2ecf20Sopenharmony_ci		prev_usage = &field->usage[usage->usage_index - 1];
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci	switch (usage->hid & HID_USAGE_PAGE) {
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci	case HID_UP_GENDESK:
7148c2ecf20Sopenharmony_ci		switch (usage->hid) {
7158c2ecf20Sopenharmony_ci		case HID_GD_X:
7168c2ecf20Sopenharmony_ci			if (prev_usage && (prev_usage->hid == usage->hid)) {
7178c2ecf20Sopenharmony_ci				code = ABS_MT_TOOL_X;
7188c2ecf20Sopenharmony_ci				MT_STORE_FIELD(cx);
7198c2ecf20Sopenharmony_ci			} else {
7208c2ecf20Sopenharmony_ci				code = ABS_MT_POSITION_X;
7218c2ecf20Sopenharmony_ci				MT_STORE_FIELD(x);
7228c2ecf20Sopenharmony_ci			}
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_ci			set_abs(hi->input, code, field, cls->sn_move);
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci			/*
7278c2ecf20Sopenharmony_ci			 * A system multi-axis that exports X and Y has a high
7288c2ecf20Sopenharmony_ci			 * chance of being used directly on a surface
7298c2ecf20Sopenharmony_ci			 */
7308c2ecf20Sopenharmony_ci			if (field->application == HID_GD_SYSTEM_MULTIAXIS) {
7318c2ecf20Sopenharmony_ci				__set_bit(INPUT_PROP_DIRECT,
7328c2ecf20Sopenharmony_ci					  hi->input->propbit);
7338c2ecf20Sopenharmony_ci				input_set_abs_params(hi->input,
7348c2ecf20Sopenharmony_ci						     ABS_MT_TOOL_TYPE,
7358c2ecf20Sopenharmony_ci						     MT_TOOL_DIAL,
7368c2ecf20Sopenharmony_ci						     MT_TOOL_DIAL, 0, 0);
7378c2ecf20Sopenharmony_ci			}
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ci			return 1;
7408c2ecf20Sopenharmony_ci		case HID_GD_Y:
7418c2ecf20Sopenharmony_ci			if (prev_usage && (prev_usage->hid == usage->hid)) {
7428c2ecf20Sopenharmony_ci				code = ABS_MT_TOOL_Y;
7438c2ecf20Sopenharmony_ci				MT_STORE_FIELD(cy);
7448c2ecf20Sopenharmony_ci			} else {
7458c2ecf20Sopenharmony_ci				code = ABS_MT_POSITION_Y;
7468c2ecf20Sopenharmony_ci				MT_STORE_FIELD(y);
7478c2ecf20Sopenharmony_ci			}
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_ci			set_abs(hi->input, code, field, cls->sn_move);
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci			return 1;
7528c2ecf20Sopenharmony_ci		}
7538c2ecf20Sopenharmony_ci		return 0;
7548c2ecf20Sopenharmony_ci
7558c2ecf20Sopenharmony_ci	case HID_UP_DIGITIZER:
7568c2ecf20Sopenharmony_ci		switch (usage->hid) {
7578c2ecf20Sopenharmony_ci		case HID_DG_INRANGE:
7588c2ecf20Sopenharmony_ci			if (app->quirks & MT_QUIRK_HOVERING) {
7598c2ecf20Sopenharmony_ci				input_set_abs_params(hi->input,
7608c2ecf20Sopenharmony_ci					ABS_MT_DISTANCE, 0, 1, 0, 0);
7618c2ecf20Sopenharmony_ci			}
7628c2ecf20Sopenharmony_ci			MT_STORE_FIELD(inrange_state);
7638c2ecf20Sopenharmony_ci			return 1;
7648c2ecf20Sopenharmony_ci		case HID_DG_CONFIDENCE:
7658c2ecf20Sopenharmony_ci			if ((cls->name == MT_CLS_WIN_8 ||
7668c2ecf20Sopenharmony_ci			     cls->name == MT_CLS_WIN_8_FORCE_MULTI_INPUT) &&
7678c2ecf20Sopenharmony_ci				(field->application == HID_DG_TOUCHPAD ||
7688c2ecf20Sopenharmony_ci				 field->application == HID_DG_TOUCHSCREEN))
7698c2ecf20Sopenharmony_ci				app->quirks |= MT_QUIRK_CONFIDENCE;
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci			if (app->quirks & MT_QUIRK_CONFIDENCE)
7728c2ecf20Sopenharmony_ci				input_set_abs_params(hi->input,
7738c2ecf20Sopenharmony_ci						     ABS_MT_TOOL_TYPE,
7748c2ecf20Sopenharmony_ci						     MT_TOOL_FINGER,
7758c2ecf20Sopenharmony_ci						     MT_TOOL_PALM, 0, 0);
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_ci			MT_STORE_FIELD(confidence_state);
7788c2ecf20Sopenharmony_ci			return 1;
7798c2ecf20Sopenharmony_ci		case HID_DG_TIPSWITCH:
7808c2ecf20Sopenharmony_ci			if (field->application != HID_GD_SYSTEM_MULTIAXIS)
7818c2ecf20Sopenharmony_ci				input_set_capability(hi->input,
7828c2ecf20Sopenharmony_ci						     EV_KEY, BTN_TOUCH);
7838c2ecf20Sopenharmony_ci			MT_STORE_FIELD(tip_state);
7848c2ecf20Sopenharmony_ci			return 1;
7858c2ecf20Sopenharmony_ci		case HID_DG_CONTACTID:
7868c2ecf20Sopenharmony_ci			MT_STORE_FIELD(contactid);
7878c2ecf20Sopenharmony_ci			app->touches_by_report++;
7888c2ecf20Sopenharmony_ci			return 1;
7898c2ecf20Sopenharmony_ci		case HID_DG_WIDTH:
7908c2ecf20Sopenharmony_ci			if (!(app->quirks & MT_QUIRK_NO_AREA))
7918c2ecf20Sopenharmony_ci				set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
7928c2ecf20Sopenharmony_ci					cls->sn_width);
7938c2ecf20Sopenharmony_ci			MT_STORE_FIELD(w);
7948c2ecf20Sopenharmony_ci			return 1;
7958c2ecf20Sopenharmony_ci		case HID_DG_HEIGHT:
7968c2ecf20Sopenharmony_ci			if (!(app->quirks & MT_QUIRK_NO_AREA)) {
7978c2ecf20Sopenharmony_ci				set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
7988c2ecf20Sopenharmony_ci					cls->sn_height);
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_ci				/*
8018c2ecf20Sopenharmony_ci				 * Only set ABS_MT_ORIENTATION if it is not
8028c2ecf20Sopenharmony_ci				 * already set by the HID_DG_AZIMUTH usage.
8038c2ecf20Sopenharmony_ci				 */
8048c2ecf20Sopenharmony_ci				if (!test_bit(ABS_MT_ORIENTATION,
8058c2ecf20Sopenharmony_ci						hi->input->absbit))
8068c2ecf20Sopenharmony_ci					input_set_abs_params(hi->input,
8078c2ecf20Sopenharmony_ci						ABS_MT_ORIENTATION, 0, 1, 0, 0);
8088c2ecf20Sopenharmony_ci			}
8098c2ecf20Sopenharmony_ci			MT_STORE_FIELD(h);
8108c2ecf20Sopenharmony_ci			return 1;
8118c2ecf20Sopenharmony_ci		case HID_DG_TIPPRESSURE:
8128c2ecf20Sopenharmony_ci			set_abs(hi->input, ABS_MT_PRESSURE, field,
8138c2ecf20Sopenharmony_ci				cls->sn_pressure);
8148c2ecf20Sopenharmony_ci			MT_STORE_FIELD(p);
8158c2ecf20Sopenharmony_ci			return 1;
8168c2ecf20Sopenharmony_ci		case HID_DG_SCANTIME:
8178c2ecf20Sopenharmony_ci			input_set_capability(hi->input, EV_MSC, MSC_TIMESTAMP);
8188c2ecf20Sopenharmony_ci			app->scantime = &field->value[usage->usage_index];
8198c2ecf20Sopenharmony_ci			app->scantime_logical_max = field->logical_maximum;
8208c2ecf20Sopenharmony_ci			return 1;
8218c2ecf20Sopenharmony_ci		case HID_DG_CONTACTCOUNT:
8228c2ecf20Sopenharmony_ci			app->have_contact_count = true;
8238c2ecf20Sopenharmony_ci			app->raw_cc = &field->value[usage->usage_index];
8248c2ecf20Sopenharmony_ci			return 1;
8258c2ecf20Sopenharmony_ci		case HID_DG_AZIMUTH:
8268c2ecf20Sopenharmony_ci			/*
8278c2ecf20Sopenharmony_ci			 * Azimuth has the range of [0, MAX) representing a full
8288c2ecf20Sopenharmony_ci			 * revolution. Set ABS_MT_ORIENTATION to a quarter of
8298c2ecf20Sopenharmony_ci			 * MAX according the definition of ABS_MT_ORIENTATION
8308c2ecf20Sopenharmony_ci			 */
8318c2ecf20Sopenharmony_ci			input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
8328c2ecf20Sopenharmony_ci				-field->logical_maximum / 4,
8338c2ecf20Sopenharmony_ci				field->logical_maximum / 4,
8348c2ecf20Sopenharmony_ci				cls->sn_move ?
8358c2ecf20Sopenharmony_ci				field->logical_maximum / cls->sn_move : 0, 0);
8368c2ecf20Sopenharmony_ci			MT_STORE_FIELD(a);
8378c2ecf20Sopenharmony_ci			return 1;
8388c2ecf20Sopenharmony_ci		case HID_DG_CONTACTMAX:
8398c2ecf20Sopenharmony_ci			/* contact max are global to the report */
8408c2ecf20Sopenharmony_ci			return -1;
8418c2ecf20Sopenharmony_ci		case HID_DG_TOUCH:
8428c2ecf20Sopenharmony_ci			/* Legacy devices use TIPSWITCH and not TOUCH.
8438c2ecf20Sopenharmony_ci			 * Let's just ignore this field. */
8448c2ecf20Sopenharmony_ci			return -1;
8458c2ecf20Sopenharmony_ci		}
8468c2ecf20Sopenharmony_ci		/* let hid-input decide for the others */
8478c2ecf20Sopenharmony_ci		return 0;
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	case HID_UP_BUTTON:
8508c2ecf20Sopenharmony_ci		code = BTN_MOUSE + ((usage->hid - 1) & HID_USAGE);
8518c2ecf20Sopenharmony_ci		/*
8528c2ecf20Sopenharmony_ci		 * MS PTP spec says that external buttons left and right have
8538c2ecf20Sopenharmony_ci		 * usages 2 and 3.
8548c2ecf20Sopenharmony_ci		 */
8558c2ecf20Sopenharmony_ci		if ((app->quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
8568c2ecf20Sopenharmony_ci		    field->application == HID_DG_TOUCHPAD &&
8578c2ecf20Sopenharmony_ci		    (usage->hid & HID_USAGE) > 1)
8588c2ecf20Sopenharmony_ci			code--;
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci		if (field->application == HID_GD_SYSTEM_MULTIAXIS)
8618c2ecf20Sopenharmony_ci			code = BTN_0  + ((usage->hid - 1) & HID_USAGE);
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_ci		hid_map_usage(hi, usage, bit, max, EV_KEY, code);
8648c2ecf20Sopenharmony_ci		if (!*bit)
8658c2ecf20Sopenharmony_ci			return -1;
8668c2ecf20Sopenharmony_ci		input_set_capability(hi->input, EV_KEY, code);
8678c2ecf20Sopenharmony_ci		return 1;
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	case 0xff000000:
8708c2ecf20Sopenharmony_ci		/* we do not want to map these: no input-oriented meaning */
8718c2ecf20Sopenharmony_ci		return -1;
8728c2ecf20Sopenharmony_ci	}
8738c2ecf20Sopenharmony_ci
8748c2ecf20Sopenharmony_ci	return 0;
8758c2ecf20Sopenharmony_ci}
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_cistatic int mt_compute_slot(struct mt_device *td, struct mt_application *app,
8788c2ecf20Sopenharmony_ci			   struct mt_usages *slot,
8798c2ecf20Sopenharmony_ci			   struct input_dev *input)
8808c2ecf20Sopenharmony_ci{
8818c2ecf20Sopenharmony_ci	__s32 quirks = app->quirks;
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ci	if (quirks & MT_QUIRK_SLOT_IS_CONTACTID)
8848c2ecf20Sopenharmony_ci		return *slot->contactid;
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci	if (quirks & MT_QUIRK_CYPRESS)
8878c2ecf20Sopenharmony_ci		return cypress_compute_slot(app, slot);
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_ci	if (quirks & MT_QUIRK_SLOT_IS_CONTACTNUMBER)
8908c2ecf20Sopenharmony_ci		return app->num_received;
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ci	if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE)
8938c2ecf20Sopenharmony_ci		return *slot->contactid - 1;
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_ci	return input_mt_get_slot_by_key(input, *slot->contactid);
8968c2ecf20Sopenharmony_ci}
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_cistatic void mt_release_pending_palms(struct mt_device *td,
8998c2ecf20Sopenharmony_ci				     struct mt_application *app,
9008c2ecf20Sopenharmony_ci				     struct input_dev *input)
9018c2ecf20Sopenharmony_ci{
9028c2ecf20Sopenharmony_ci	int slotnum;
9038c2ecf20Sopenharmony_ci	bool need_sync = false;
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ci	for_each_set_bit(slotnum, app->pending_palm_slots, td->maxcontacts) {
9068c2ecf20Sopenharmony_ci		clear_bit(slotnum, app->pending_palm_slots);
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci		input_mt_slot(input, slotnum);
9098c2ecf20Sopenharmony_ci		input_mt_report_slot_inactive(input);
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci		need_sync = true;
9128c2ecf20Sopenharmony_ci	}
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_ci	if (need_sync) {
9158c2ecf20Sopenharmony_ci		input_mt_sync_frame(input);
9168c2ecf20Sopenharmony_ci		input_sync(input);
9178c2ecf20Sopenharmony_ci	}
9188c2ecf20Sopenharmony_ci}
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci/*
9218c2ecf20Sopenharmony_ci * this function is called when a whole packet has been received and processed,
9228c2ecf20Sopenharmony_ci * so that it can decide what to send to the input layer.
9238c2ecf20Sopenharmony_ci */
9248c2ecf20Sopenharmony_cistatic void mt_sync_frame(struct mt_device *td, struct mt_application *app,
9258c2ecf20Sopenharmony_ci			  struct input_dev *input)
9268c2ecf20Sopenharmony_ci{
9278c2ecf20Sopenharmony_ci	if (app->quirks & MT_QUIRK_WIN8_PTP_BUTTONS)
9288c2ecf20Sopenharmony_ci		input_event(input, EV_KEY, BTN_LEFT, app->left_button_state);
9298c2ecf20Sopenharmony_ci
9308c2ecf20Sopenharmony_ci	input_mt_sync_frame(input);
9318c2ecf20Sopenharmony_ci	input_event(input, EV_MSC, MSC_TIMESTAMP, app->timestamp);
9328c2ecf20Sopenharmony_ci	input_sync(input);
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_ci	mt_release_pending_palms(td, app, input);
9358c2ecf20Sopenharmony_ci
9368c2ecf20Sopenharmony_ci	app->num_received = 0;
9378c2ecf20Sopenharmony_ci	app->left_button_state = 0;
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_ci	if (test_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags))
9408c2ecf20Sopenharmony_ci		set_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags);
9418c2ecf20Sopenharmony_ci	else
9428c2ecf20Sopenharmony_ci		clear_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags);
9438c2ecf20Sopenharmony_ci	clear_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags);
9448c2ecf20Sopenharmony_ci}
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_cistatic int mt_compute_timestamp(struct mt_application *app, __s32 value)
9478c2ecf20Sopenharmony_ci{
9488c2ecf20Sopenharmony_ci	long delta = value - app->prev_scantime;
9498c2ecf20Sopenharmony_ci	unsigned long jdelta = jiffies_to_usecs(jiffies - app->jiffies);
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_ci	app->jiffies = jiffies;
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci	if (delta < 0)
9548c2ecf20Sopenharmony_ci		delta += app->scantime_logical_max;
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci	/* HID_DG_SCANTIME is expressed in 100us, we want it in us. */
9578c2ecf20Sopenharmony_ci	delta *= 100;
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci	if (jdelta > MAX_TIMESTAMP_INTERVAL)
9608c2ecf20Sopenharmony_ci		/* No data received for a while, resync the timestamp. */
9618c2ecf20Sopenharmony_ci		return 0;
9628c2ecf20Sopenharmony_ci	else
9638c2ecf20Sopenharmony_ci		return app->timestamp + delta;
9648c2ecf20Sopenharmony_ci}
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_cistatic int mt_touch_event(struct hid_device *hid, struct hid_field *field,
9678c2ecf20Sopenharmony_ci				struct hid_usage *usage, __s32 value)
9688c2ecf20Sopenharmony_ci{
9698c2ecf20Sopenharmony_ci	/* we will handle the hidinput part later, now remains hiddev */
9708c2ecf20Sopenharmony_ci	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
9718c2ecf20Sopenharmony_ci		hid->hiddev_hid_event(hid, field, usage, value);
9728c2ecf20Sopenharmony_ci
9738c2ecf20Sopenharmony_ci	return 1;
9748c2ecf20Sopenharmony_ci}
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_cistatic int mt_process_slot(struct mt_device *td, struct input_dev *input,
9778c2ecf20Sopenharmony_ci			    struct mt_application *app,
9788c2ecf20Sopenharmony_ci			    struct mt_usages *slot)
9798c2ecf20Sopenharmony_ci{
9808c2ecf20Sopenharmony_ci	struct input_mt *mt = input->mt;
9818c2ecf20Sopenharmony_ci	__s32 quirks = app->quirks;
9828c2ecf20Sopenharmony_ci	bool valid = true;
9838c2ecf20Sopenharmony_ci	bool confidence_state = true;
9848c2ecf20Sopenharmony_ci	bool inrange_state = false;
9858c2ecf20Sopenharmony_ci	int active;
9868c2ecf20Sopenharmony_ci	int slotnum;
9878c2ecf20Sopenharmony_ci	int tool = MT_TOOL_FINGER;
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_ci	if (!slot)
9908c2ecf20Sopenharmony_ci		return -EINVAL;
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci	if ((quirks & MT_QUIRK_CONTACT_CNT_ACCURATE) &&
9938c2ecf20Sopenharmony_ci	    app->num_received >= app->num_expected)
9948c2ecf20Sopenharmony_ci		return -EAGAIN;
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_ci	if (!(quirks & MT_QUIRK_ALWAYS_VALID)) {
9978c2ecf20Sopenharmony_ci		if (quirks & MT_QUIRK_VALID_IS_INRANGE)
9988c2ecf20Sopenharmony_ci			valid = *slot->inrange_state;
9998c2ecf20Sopenharmony_ci		if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
10008c2ecf20Sopenharmony_ci			valid = *slot->tip_state;
10018c2ecf20Sopenharmony_ci		if (quirks & MT_QUIRK_VALID_IS_CONFIDENCE)
10028c2ecf20Sopenharmony_ci			valid = *slot->confidence_state;
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci		if (!valid)
10058c2ecf20Sopenharmony_ci			return 0;
10068c2ecf20Sopenharmony_ci	}
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ci	slotnum = mt_compute_slot(td, app, slot, input);
10098c2ecf20Sopenharmony_ci	if (slotnum < 0 || slotnum >= td->maxcontacts)
10108c2ecf20Sopenharmony_ci		return 0;
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci	if ((quirks & MT_QUIRK_IGNORE_DUPLICATES) && mt) {
10138c2ecf20Sopenharmony_ci		struct input_mt_slot *i_slot = &mt->slots[slotnum];
10148c2ecf20Sopenharmony_ci
10158c2ecf20Sopenharmony_ci		if (input_mt_is_active(i_slot) &&
10168c2ecf20Sopenharmony_ci		    input_mt_is_used(mt, i_slot))
10178c2ecf20Sopenharmony_ci			return -EAGAIN;
10188c2ecf20Sopenharmony_ci	}
10198c2ecf20Sopenharmony_ci
10208c2ecf20Sopenharmony_ci	if (quirks & MT_QUIRK_CONFIDENCE)
10218c2ecf20Sopenharmony_ci		confidence_state = *slot->confidence_state;
10228c2ecf20Sopenharmony_ci
10238c2ecf20Sopenharmony_ci	if (quirks & MT_QUIRK_HOVERING)
10248c2ecf20Sopenharmony_ci		inrange_state = *slot->inrange_state;
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_ci	active = *slot->tip_state || inrange_state;
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ci	if (app->application == HID_GD_SYSTEM_MULTIAXIS)
10298c2ecf20Sopenharmony_ci		tool = MT_TOOL_DIAL;
10308c2ecf20Sopenharmony_ci	else if (unlikely(!confidence_state)) {
10318c2ecf20Sopenharmony_ci		tool = MT_TOOL_PALM;
10328c2ecf20Sopenharmony_ci		if (!active && mt &&
10338c2ecf20Sopenharmony_ci		    input_mt_is_active(&mt->slots[slotnum])) {
10348c2ecf20Sopenharmony_ci			/*
10358c2ecf20Sopenharmony_ci			 * The non-confidence was reported for
10368c2ecf20Sopenharmony_ci			 * previously valid contact that is also no
10378c2ecf20Sopenharmony_ci			 * longer valid. We can't simply report
10388c2ecf20Sopenharmony_ci			 * lift-off as userspace will not be aware
10398c2ecf20Sopenharmony_ci			 * of non-confidence, so we need to split
10408c2ecf20Sopenharmony_ci			 * it into 2 events: active MT_TOOL_PALM
10418c2ecf20Sopenharmony_ci			 * and a separate liftoff.
10428c2ecf20Sopenharmony_ci			 */
10438c2ecf20Sopenharmony_ci			active = true;
10448c2ecf20Sopenharmony_ci			set_bit(slotnum, app->pending_palm_slots);
10458c2ecf20Sopenharmony_ci		}
10468c2ecf20Sopenharmony_ci	}
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_ci	input_mt_slot(input, slotnum);
10498c2ecf20Sopenharmony_ci	input_mt_report_slot_state(input, tool, active);
10508c2ecf20Sopenharmony_ci	if (active) {
10518c2ecf20Sopenharmony_ci		/* this finger is in proximity of the sensor */
10528c2ecf20Sopenharmony_ci		int wide = (*slot->w > *slot->h);
10538c2ecf20Sopenharmony_ci		int major = max(*slot->w, *slot->h);
10548c2ecf20Sopenharmony_ci		int minor = min(*slot->w, *slot->h);
10558c2ecf20Sopenharmony_ci		int orientation = wide;
10568c2ecf20Sopenharmony_ci		int max_azimuth;
10578c2ecf20Sopenharmony_ci		int azimuth;
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_ci		if (slot->a != DEFAULT_ZERO) {
10608c2ecf20Sopenharmony_ci			/*
10618c2ecf20Sopenharmony_ci			 * Azimuth is counter-clockwise and ranges from [0, MAX)
10628c2ecf20Sopenharmony_ci			 * (a full revolution). Convert it to clockwise ranging
10638c2ecf20Sopenharmony_ci			 * [-MAX/2, MAX/2].
10648c2ecf20Sopenharmony_ci			 *
10658c2ecf20Sopenharmony_ci			 * Note that ABS_MT_ORIENTATION require us to report
10668c2ecf20Sopenharmony_ci			 * the limit of [-MAX/4, MAX/4], but the value can go
10678c2ecf20Sopenharmony_ci			 * out of range to [-MAX/2, MAX/2] to report an upside
10688c2ecf20Sopenharmony_ci			 * down ellipsis.
10698c2ecf20Sopenharmony_ci			 */
10708c2ecf20Sopenharmony_ci			azimuth = *slot->a;
10718c2ecf20Sopenharmony_ci			max_azimuth = input_abs_get_max(input,
10728c2ecf20Sopenharmony_ci							ABS_MT_ORIENTATION);
10738c2ecf20Sopenharmony_ci			if (azimuth > max_azimuth * 2)
10748c2ecf20Sopenharmony_ci				azimuth -= max_azimuth * 4;
10758c2ecf20Sopenharmony_ci			orientation = -azimuth;
10768c2ecf20Sopenharmony_ci		}
10778c2ecf20Sopenharmony_ci
10788c2ecf20Sopenharmony_ci		if (quirks & MT_QUIRK_TOUCH_SIZE_SCALING) {
10798c2ecf20Sopenharmony_ci			/*
10808c2ecf20Sopenharmony_ci			 * divided by two to match visual scale of touch
10818c2ecf20Sopenharmony_ci			 * for devices with this quirk
10828c2ecf20Sopenharmony_ci			 */
10838c2ecf20Sopenharmony_ci			major = major >> 1;
10848c2ecf20Sopenharmony_ci			minor = minor >> 1;
10858c2ecf20Sopenharmony_ci		}
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_ci		input_event(input, EV_ABS, ABS_MT_POSITION_X, *slot->x);
10888c2ecf20Sopenharmony_ci		input_event(input, EV_ABS, ABS_MT_POSITION_Y, *slot->y);
10898c2ecf20Sopenharmony_ci		input_event(input, EV_ABS, ABS_MT_TOOL_X, *slot->cx);
10908c2ecf20Sopenharmony_ci		input_event(input, EV_ABS, ABS_MT_TOOL_Y, *slot->cy);
10918c2ecf20Sopenharmony_ci		input_event(input, EV_ABS, ABS_MT_DISTANCE, !*slot->tip_state);
10928c2ecf20Sopenharmony_ci		input_event(input, EV_ABS, ABS_MT_ORIENTATION, orientation);
10938c2ecf20Sopenharmony_ci		input_event(input, EV_ABS, ABS_MT_PRESSURE, *slot->p);
10948c2ecf20Sopenharmony_ci		input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
10958c2ecf20Sopenharmony_ci		input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
10968c2ecf20Sopenharmony_ci
10978c2ecf20Sopenharmony_ci		set_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags);
10988c2ecf20Sopenharmony_ci	}
10998c2ecf20Sopenharmony_ci
11008c2ecf20Sopenharmony_ci	return 0;
11018c2ecf20Sopenharmony_ci}
11028c2ecf20Sopenharmony_ci
11038c2ecf20Sopenharmony_cistatic void mt_process_mt_event(struct hid_device *hid,
11048c2ecf20Sopenharmony_ci				struct mt_application *app,
11058c2ecf20Sopenharmony_ci				struct hid_field *field,
11068c2ecf20Sopenharmony_ci				struct hid_usage *usage,
11078c2ecf20Sopenharmony_ci				__s32 value,
11088c2ecf20Sopenharmony_ci				bool first_packet)
11098c2ecf20Sopenharmony_ci{
11108c2ecf20Sopenharmony_ci	__s32 quirks = app->quirks;
11118c2ecf20Sopenharmony_ci	struct input_dev *input = field->hidinput->input;
11128c2ecf20Sopenharmony_ci
11138c2ecf20Sopenharmony_ci	if (!usage->type || !(hid->claimed & HID_CLAIMED_INPUT))
11148c2ecf20Sopenharmony_ci		return;
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_ci	if (quirks & MT_QUIRK_WIN8_PTP_BUTTONS) {
11178c2ecf20Sopenharmony_ci
11188c2ecf20Sopenharmony_ci		/*
11198c2ecf20Sopenharmony_ci		 * For Win8 PTP touchpads we should only look at
11208c2ecf20Sopenharmony_ci		 * non finger/touch events in the first_packet of a
11218c2ecf20Sopenharmony_ci		 * (possible) multi-packet frame.
11228c2ecf20Sopenharmony_ci		 */
11238c2ecf20Sopenharmony_ci		if (!first_packet)
11248c2ecf20Sopenharmony_ci			return;
11258c2ecf20Sopenharmony_ci
11268c2ecf20Sopenharmony_ci		/*
11278c2ecf20Sopenharmony_ci		 * For Win8 PTP touchpads we map both the clickpad click
11288c2ecf20Sopenharmony_ci		 * and any "external" left buttons to BTN_LEFT if a
11298c2ecf20Sopenharmony_ci		 * device claims to have both we need to report 1 for
11308c2ecf20Sopenharmony_ci		 * BTN_LEFT if either is pressed, so we or all values
11318c2ecf20Sopenharmony_ci		 * together and report the result in mt_sync_frame().
11328c2ecf20Sopenharmony_ci		 */
11338c2ecf20Sopenharmony_ci		if (usage->type == EV_KEY && usage->code == BTN_LEFT) {
11348c2ecf20Sopenharmony_ci			app->left_button_state |= value;
11358c2ecf20Sopenharmony_ci			return;
11368c2ecf20Sopenharmony_ci		}
11378c2ecf20Sopenharmony_ci	}
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_ci	input_event(input, usage->type, usage->code, value);
11408c2ecf20Sopenharmony_ci}
11418c2ecf20Sopenharmony_ci
11428c2ecf20Sopenharmony_cistatic void mt_touch_report(struct hid_device *hid,
11438c2ecf20Sopenharmony_ci			    struct mt_report_data *rdata)
11448c2ecf20Sopenharmony_ci{
11458c2ecf20Sopenharmony_ci	struct mt_device *td = hid_get_drvdata(hid);
11468c2ecf20Sopenharmony_ci	struct hid_report *report = rdata->report;
11478c2ecf20Sopenharmony_ci	struct mt_application *app = rdata->application;
11488c2ecf20Sopenharmony_ci	struct hid_field *field;
11498c2ecf20Sopenharmony_ci	struct input_dev *input;
11508c2ecf20Sopenharmony_ci	struct mt_usages *slot;
11518c2ecf20Sopenharmony_ci	bool first_packet;
11528c2ecf20Sopenharmony_ci	unsigned count;
11538c2ecf20Sopenharmony_ci	int r, n;
11548c2ecf20Sopenharmony_ci	int scantime = 0;
11558c2ecf20Sopenharmony_ci	int contact_count = -1;
11568c2ecf20Sopenharmony_ci
11578c2ecf20Sopenharmony_ci	/* sticky fingers release in progress, abort */
11588c2ecf20Sopenharmony_ci	if (test_and_set_bit_lock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
11598c2ecf20Sopenharmony_ci		return;
11608c2ecf20Sopenharmony_ci
11618c2ecf20Sopenharmony_ci	scantime = *app->scantime;
11628c2ecf20Sopenharmony_ci	app->timestamp = mt_compute_timestamp(app, scantime);
11638c2ecf20Sopenharmony_ci	if (app->raw_cc != DEFAULT_ZERO)
11648c2ecf20Sopenharmony_ci		contact_count = *app->raw_cc;
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_ci	/*
11678c2ecf20Sopenharmony_ci	 * Includes multi-packet support where subsequent
11688c2ecf20Sopenharmony_ci	 * packets are sent with zero contactcount.
11698c2ecf20Sopenharmony_ci	 */
11708c2ecf20Sopenharmony_ci	if (contact_count >= 0) {
11718c2ecf20Sopenharmony_ci		/*
11728c2ecf20Sopenharmony_ci		 * For Win8 PTPs the first packet (td->num_received == 0) may
11738c2ecf20Sopenharmony_ci		 * have a contactcount of 0 if there only is a button event.
11748c2ecf20Sopenharmony_ci		 * We double check that this is not a continuation packet
11758c2ecf20Sopenharmony_ci		 * of a possible multi-packet frame be checking that the
11768c2ecf20Sopenharmony_ci		 * timestamp has changed.
11778c2ecf20Sopenharmony_ci		 */
11788c2ecf20Sopenharmony_ci		if ((app->quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
11798c2ecf20Sopenharmony_ci		    app->num_received == 0 &&
11808c2ecf20Sopenharmony_ci		    app->prev_scantime != scantime)
11818c2ecf20Sopenharmony_ci			app->num_expected = contact_count;
11828c2ecf20Sopenharmony_ci		/* A non 0 contact count always indicates a first packet */
11838c2ecf20Sopenharmony_ci		else if (contact_count)
11848c2ecf20Sopenharmony_ci			app->num_expected = contact_count;
11858c2ecf20Sopenharmony_ci	}
11868c2ecf20Sopenharmony_ci	app->prev_scantime = scantime;
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci	first_packet = app->num_received == 0;
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_ci	input = report->field[0]->hidinput->input;
11918c2ecf20Sopenharmony_ci
11928c2ecf20Sopenharmony_ci	list_for_each_entry(slot, &app->mt_usages, list) {
11938c2ecf20Sopenharmony_ci		if (!mt_process_slot(td, input, app, slot))
11948c2ecf20Sopenharmony_ci			app->num_received++;
11958c2ecf20Sopenharmony_ci	}
11968c2ecf20Sopenharmony_ci
11978c2ecf20Sopenharmony_ci	for (r = 0; r < report->maxfield; r++) {
11988c2ecf20Sopenharmony_ci		field = report->field[r];
11998c2ecf20Sopenharmony_ci		count = field->report_count;
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_ci		if (!(HID_MAIN_ITEM_VARIABLE & field->flags))
12028c2ecf20Sopenharmony_ci			continue;
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_ci		for (n = 0; n < count; n++)
12058c2ecf20Sopenharmony_ci			mt_process_mt_event(hid, app, field,
12068c2ecf20Sopenharmony_ci					    &field->usage[n], field->value[n],
12078c2ecf20Sopenharmony_ci					    first_packet);
12088c2ecf20Sopenharmony_ci	}
12098c2ecf20Sopenharmony_ci
12108c2ecf20Sopenharmony_ci	if (app->num_received >= app->num_expected)
12118c2ecf20Sopenharmony_ci		mt_sync_frame(td, app, input);
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_ci	/*
12148c2ecf20Sopenharmony_ci	 * Windows 8 specs says 2 things:
12158c2ecf20Sopenharmony_ci	 * - once a contact has been reported, it has to be reported in each
12168c2ecf20Sopenharmony_ci	 *   subsequent report
12178c2ecf20Sopenharmony_ci	 * - the report rate when fingers are present has to be at least
12188c2ecf20Sopenharmony_ci	 *   the refresh rate of the screen, 60 or 120 Hz
12198c2ecf20Sopenharmony_ci	 *
12208c2ecf20Sopenharmony_ci	 * I interprete this that the specification forces a report rate of
12218c2ecf20Sopenharmony_ci	 * at least 60 Hz for a touchscreen to be certified.
12228c2ecf20Sopenharmony_ci	 * Which means that if we do not get a report whithin 16 ms, either
12238c2ecf20Sopenharmony_ci	 * something wrong happens, either the touchscreen forgets to send
12248c2ecf20Sopenharmony_ci	 * a release. Taking a reasonable margin allows to remove issues
12258c2ecf20Sopenharmony_ci	 * with USB communication or the load of the machine.
12268c2ecf20Sopenharmony_ci	 *
12278c2ecf20Sopenharmony_ci	 * Given that Win 8 devices are forced to send a release, this will
12288c2ecf20Sopenharmony_ci	 * only affect laggish machines and the ones that have a firmware
12298c2ecf20Sopenharmony_ci	 * defect.
12308c2ecf20Sopenharmony_ci	 */
12318c2ecf20Sopenharmony_ci	if (app->quirks & MT_QUIRK_STICKY_FINGERS) {
12328c2ecf20Sopenharmony_ci		if (test_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags))
12338c2ecf20Sopenharmony_ci			mod_timer(&td->release_timer,
12348c2ecf20Sopenharmony_ci				  jiffies + msecs_to_jiffies(100));
12358c2ecf20Sopenharmony_ci		else
12368c2ecf20Sopenharmony_ci			del_timer(&td->release_timer);
12378c2ecf20Sopenharmony_ci	}
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci	clear_bit_unlock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags);
12408c2ecf20Sopenharmony_ci}
12418c2ecf20Sopenharmony_ci
12428c2ecf20Sopenharmony_cistatic int mt_touch_input_configured(struct hid_device *hdev,
12438c2ecf20Sopenharmony_ci				     struct hid_input *hi,
12448c2ecf20Sopenharmony_ci				     struct mt_application *app)
12458c2ecf20Sopenharmony_ci{
12468c2ecf20Sopenharmony_ci	struct mt_device *td = hid_get_drvdata(hdev);
12478c2ecf20Sopenharmony_ci	struct mt_class *cls = &td->mtclass;
12488c2ecf20Sopenharmony_ci	struct input_dev *input = hi->input;
12498c2ecf20Sopenharmony_ci	int ret;
12508c2ecf20Sopenharmony_ci
12518c2ecf20Sopenharmony_ci	if (!td->maxcontacts)
12528c2ecf20Sopenharmony_ci		td->maxcontacts = MT_DEFAULT_MAXCONTACT;
12538c2ecf20Sopenharmony_ci
12548c2ecf20Sopenharmony_ci	mt_post_parse(td, app);
12558c2ecf20Sopenharmony_ci	if (td->serial_maybe)
12568c2ecf20Sopenharmony_ci		mt_post_parse_default_settings(td, app);
12578c2ecf20Sopenharmony_ci
12588c2ecf20Sopenharmony_ci	if (cls->is_indirect)
12598c2ecf20Sopenharmony_ci		app->mt_flags |= INPUT_MT_POINTER;
12608c2ecf20Sopenharmony_ci
12618c2ecf20Sopenharmony_ci	if (app->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
12628c2ecf20Sopenharmony_ci		app->mt_flags |= INPUT_MT_DROP_UNUSED;
12638c2ecf20Sopenharmony_ci
12648c2ecf20Sopenharmony_ci	/* check for clickpads */
12658c2ecf20Sopenharmony_ci	if ((app->mt_flags & INPUT_MT_POINTER) &&
12668c2ecf20Sopenharmony_ci	    (app->buttons_count == 1))
12678c2ecf20Sopenharmony_ci		td->is_buttonpad = true;
12688c2ecf20Sopenharmony_ci
12698c2ecf20Sopenharmony_ci	if (td->is_buttonpad)
12708c2ecf20Sopenharmony_ci		__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
12718c2ecf20Sopenharmony_ci
12728c2ecf20Sopenharmony_ci	app->pending_palm_slots = devm_kcalloc(&hi->input->dev,
12738c2ecf20Sopenharmony_ci					       BITS_TO_LONGS(td->maxcontacts),
12748c2ecf20Sopenharmony_ci					       sizeof(long),
12758c2ecf20Sopenharmony_ci					       GFP_KERNEL);
12768c2ecf20Sopenharmony_ci	if (!app->pending_palm_slots)
12778c2ecf20Sopenharmony_ci		return -ENOMEM;
12788c2ecf20Sopenharmony_ci
12798c2ecf20Sopenharmony_ci	ret = input_mt_init_slots(input, td->maxcontacts, app->mt_flags);
12808c2ecf20Sopenharmony_ci	if (ret)
12818c2ecf20Sopenharmony_ci		return ret;
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_ci	app->mt_flags = 0;
12848c2ecf20Sopenharmony_ci	return 0;
12858c2ecf20Sopenharmony_ci}
12868c2ecf20Sopenharmony_ci
12878c2ecf20Sopenharmony_ci#define mt_map_key_clear(c)	hid_map_usage_clear(hi, usage, bit, \
12888c2ecf20Sopenharmony_ci						    max, EV_KEY, (c))
12898c2ecf20Sopenharmony_cistatic int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
12908c2ecf20Sopenharmony_ci		struct hid_field *field, struct hid_usage *usage,
12918c2ecf20Sopenharmony_ci		unsigned long **bit, int *max)
12928c2ecf20Sopenharmony_ci{
12938c2ecf20Sopenharmony_ci	struct mt_device *td = hid_get_drvdata(hdev);
12948c2ecf20Sopenharmony_ci	struct mt_application *application;
12958c2ecf20Sopenharmony_ci	struct mt_report_data *rdata;
12968c2ecf20Sopenharmony_ci
12978c2ecf20Sopenharmony_ci	rdata = mt_find_report_data(td, field->report);
12988c2ecf20Sopenharmony_ci	if (!rdata) {
12998c2ecf20Sopenharmony_ci		hid_err(hdev, "failed to allocate data for report\n");
13008c2ecf20Sopenharmony_ci		return 0;
13018c2ecf20Sopenharmony_ci	}
13028c2ecf20Sopenharmony_ci
13038c2ecf20Sopenharmony_ci	application = rdata->application;
13048c2ecf20Sopenharmony_ci
13058c2ecf20Sopenharmony_ci	/*
13068c2ecf20Sopenharmony_ci	 * If mtclass.export_all_inputs is not set, only map fields from
13078c2ecf20Sopenharmony_ci	 * TouchScreen or TouchPad collections. We need to ignore fields
13088c2ecf20Sopenharmony_ci	 * that belong to other collections such as Mouse that might have
13098c2ecf20Sopenharmony_ci	 * the same GenericDesktop usages.
13108c2ecf20Sopenharmony_ci	 */
13118c2ecf20Sopenharmony_ci	if (!td->mtclass.export_all_inputs &&
13128c2ecf20Sopenharmony_ci	    field->application != HID_DG_TOUCHSCREEN &&
13138c2ecf20Sopenharmony_ci	    field->application != HID_DG_PEN &&
13148c2ecf20Sopenharmony_ci	    field->application != HID_DG_TOUCHPAD &&
13158c2ecf20Sopenharmony_ci	    field->application != HID_GD_KEYBOARD &&
13168c2ecf20Sopenharmony_ci	    field->application != HID_GD_SYSTEM_CONTROL &&
13178c2ecf20Sopenharmony_ci	    field->application != HID_CP_CONSUMER_CONTROL &&
13188c2ecf20Sopenharmony_ci	    field->application != HID_GD_WIRELESS_RADIO_CTLS &&
13198c2ecf20Sopenharmony_ci	    field->application != HID_GD_SYSTEM_MULTIAXIS &&
13208c2ecf20Sopenharmony_ci	    !(field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS &&
13218c2ecf20Sopenharmony_ci	      application->quirks & MT_QUIRK_ASUS_CUSTOM_UP))
13228c2ecf20Sopenharmony_ci		return -1;
13238c2ecf20Sopenharmony_ci
13248c2ecf20Sopenharmony_ci	/*
13258c2ecf20Sopenharmony_ci	 * Some Asus keyboard+touchpad devices have the hotkeys defined in the
13268c2ecf20Sopenharmony_ci	 * touchpad report descriptor. We need to treat these as an array to
13278c2ecf20Sopenharmony_ci	 * map usages to input keys.
13288c2ecf20Sopenharmony_ci	 */
13298c2ecf20Sopenharmony_ci	if (field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS &&
13308c2ecf20Sopenharmony_ci	    application->quirks & MT_QUIRK_ASUS_CUSTOM_UP &&
13318c2ecf20Sopenharmony_ci	    (usage->hid & HID_USAGE_PAGE) == HID_UP_CUSTOM) {
13328c2ecf20Sopenharmony_ci		set_bit(EV_REP, hi->input->evbit);
13338c2ecf20Sopenharmony_ci		if (field->flags & HID_MAIN_ITEM_VARIABLE)
13348c2ecf20Sopenharmony_ci			field->flags &= ~HID_MAIN_ITEM_VARIABLE;
13358c2ecf20Sopenharmony_ci		switch (usage->hid & HID_USAGE) {
13368c2ecf20Sopenharmony_ci		case 0x10: mt_map_key_clear(KEY_BRIGHTNESSDOWN);	break;
13378c2ecf20Sopenharmony_ci		case 0x20: mt_map_key_clear(KEY_BRIGHTNESSUP);		break;
13388c2ecf20Sopenharmony_ci		case 0x35: mt_map_key_clear(KEY_DISPLAY_OFF);		break;
13398c2ecf20Sopenharmony_ci		case 0x6b: mt_map_key_clear(KEY_F21);			break;
13408c2ecf20Sopenharmony_ci		case 0x6c: mt_map_key_clear(KEY_SLEEP);			break;
13418c2ecf20Sopenharmony_ci		default:
13428c2ecf20Sopenharmony_ci			return -1;
13438c2ecf20Sopenharmony_ci		}
13448c2ecf20Sopenharmony_ci		return 1;
13458c2ecf20Sopenharmony_ci	}
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ci	if (rdata->is_mt_collection)
13488c2ecf20Sopenharmony_ci		return mt_touch_input_mapping(hdev, hi, field, usage, bit, max,
13498c2ecf20Sopenharmony_ci					      application);
13508c2ecf20Sopenharmony_ci
13518c2ecf20Sopenharmony_ci	/*
13528c2ecf20Sopenharmony_ci	 * some egalax touchscreens have "application == DG_TOUCHSCREEN"
13538c2ecf20Sopenharmony_ci	 * for the stylus. Overwrite the hid_input application
13548c2ecf20Sopenharmony_ci	 */
13558c2ecf20Sopenharmony_ci	if (field->physical == HID_DG_STYLUS)
13568c2ecf20Sopenharmony_ci		hi->application = HID_DG_STYLUS;
13578c2ecf20Sopenharmony_ci
13588c2ecf20Sopenharmony_ci	/* let hid-core decide for the others */
13598c2ecf20Sopenharmony_ci	return 0;
13608c2ecf20Sopenharmony_ci}
13618c2ecf20Sopenharmony_ci
13628c2ecf20Sopenharmony_cistatic int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
13638c2ecf20Sopenharmony_ci		struct hid_field *field, struct hid_usage *usage,
13648c2ecf20Sopenharmony_ci		unsigned long **bit, int *max)
13658c2ecf20Sopenharmony_ci{
13668c2ecf20Sopenharmony_ci	struct mt_device *td = hid_get_drvdata(hdev);
13678c2ecf20Sopenharmony_ci	struct mt_report_data *rdata;
13688c2ecf20Sopenharmony_ci
13698c2ecf20Sopenharmony_ci	rdata = mt_find_report_data(td, field->report);
13708c2ecf20Sopenharmony_ci	if (rdata && rdata->is_mt_collection) {
13718c2ecf20Sopenharmony_ci		/* We own these mappings, tell hid-input to ignore them */
13728c2ecf20Sopenharmony_ci		return -1;
13738c2ecf20Sopenharmony_ci	}
13748c2ecf20Sopenharmony_ci
13758c2ecf20Sopenharmony_ci	/* let hid-core decide for the others */
13768c2ecf20Sopenharmony_ci	return 0;
13778c2ecf20Sopenharmony_ci}
13788c2ecf20Sopenharmony_ci
13798c2ecf20Sopenharmony_cistatic int mt_event(struct hid_device *hid, struct hid_field *field,
13808c2ecf20Sopenharmony_ci				struct hid_usage *usage, __s32 value)
13818c2ecf20Sopenharmony_ci{
13828c2ecf20Sopenharmony_ci	struct mt_device *td = hid_get_drvdata(hid);
13838c2ecf20Sopenharmony_ci	struct mt_report_data *rdata;
13848c2ecf20Sopenharmony_ci
13858c2ecf20Sopenharmony_ci	rdata = mt_find_report_data(td, field->report);
13868c2ecf20Sopenharmony_ci	if (rdata && rdata->is_mt_collection)
13878c2ecf20Sopenharmony_ci		return mt_touch_event(hid, field, usage, value);
13888c2ecf20Sopenharmony_ci
13898c2ecf20Sopenharmony_ci	return 0;
13908c2ecf20Sopenharmony_ci}
13918c2ecf20Sopenharmony_ci
13928c2ecf20Sopenharmony_cistatic void mt_report(struct hid_device *hid, struct hid_report *report)
13938c2ecf20Sopenharmony_ci{
13948c2ecf20Sopenharmony_ci	struct mt_device *td = hid_get_drvdata(hid);
13958c2ecf20Sopenharmony_ci	struct hid_field *field = report->field[0];
13968c2ecf20Sopenharmony_ci	struct mt_report_data *rdata;
13978c2ecf20Sopenharmony_ci
13988c2ecf20Sopenharmony_ci	if (!(hid->claimed & HID_CLAIMED_INPUT))
13998c2ecf20Sopenharmony_ci		return;
14008c2ecf20Sopenharmony_ci
14018c2ecf20Sopenharmony_ci	rdata = mt_find_report_data(td, report);
14028c2ecf20Sopenharmony_ci	if (rdata && rdata->is_mt_collection)
14038c2ecf20Sopenharmony_ci		return mt_touch_report(hid, rdata);
14048c2ecf20Sopenharmony_ci
14058c2ecf20Sopenharmony_ci	if (field && field->hidinput && field->hidinput->input)
14068c2ecf20Sopenharmony_ci		input_sync(field->hidinput->input);
14078c2ecf20Sopenharmony_ci}
14088c2ecf20Sopenharmony_ci
14098c2ecf20Sopenharmony_cistatic bool mt_need_to_apply_feature(struct hid_device *hdev,
14108c2ecf20Sopenharmony_ci				     struct hid_field *field,
14118c2ecf20Sopenharmony_ci				     struct hid_usage *usage,
14128c2ecf20Sopenharmony_ci				     enum latency_mode latency,
14138c2ecf20Sopenharmony_ci				     bool surface_switch,
14148c2ecf20Sopenharmony_ci				     bool button_switch,
14158c2ecf20Sopenharmony_ci				     bool *inputmode_found)
14168c2ecf20Sopenharmony_ci{
14178c2ecf20Sopenharmony_ci	struct mt_device *td = hid_get_drvdata(hdev);
14188c2ecf20Sopenharmony_ci	struct mt_class *cls = &td->mtclass;
14198c2ecf20Sopenharmony_ci	struct hid_report *report = field->report;
14208c2ecf20Sopenharmony_ci	unsigned int index = usage->usage_index;
14218c2ecf20Sopenharmony_ci	char *buf;
14228c2ecf20Sopenharmony_ci	u32 report_len;
14238c2ecf20Sopenharmony_ci	int max;
14248c2ecf20Sopenharmony_ci
14258c2ecf20Sopenharmony_ci	switch (usage->hid) {
14268c2ecf20Sopenharmony_ci	case HID_DG_INPUTMODE:
14278c2ecf20Sopenharmony_ci		/*
14288c2ecf20Sopenharmony_ci		 * Some elan panels wrongly declare 2 input mode features,
14298c2ecf20Sopenharmony_ci		 * and silently ignore when we set the value in the second
14308c2ecf20Sopenharmony_ci		 * field. Skip the second feature and hope for the best.
14318c2ecf20Sopenharmony_ci		 */
14328c2ecf20Sopenharmony_ci		if (*inputmode_found)
14338c2ecf20Sopenharmony_ci			return false;
14348c2ecf20Sopenharmony_ci
14358c2ecf20Sopenharmony_ci		if (cls->quirks & MT_QUIRK_FORCE_GET_FEATURE) {
14368c2ecf20Sopenharmony_ci			report_len = hid_report_len(report);
14378c2ecf20Sopenharmony_ci			buf = hid_alloc_report_buf(report, GFP_KERNEL);
14388c2ecf20Sopenharmony_ci			if (!buf) {
14398c2ecf20Sopenharmony_ci				hid_err(hdev,
14408c2ecf20Sopenharmony_ci					"failed to allocate buffer for report\n");
14418c2ecf20Sopenharmony_ci				return false;
14428c2ecf20Sopenharmony_ci			}
14438c2ecf20Sopenharmony_ci			hid_hw_raw_request(hdev, report->id, buf, report_len,
14448c2ecf20Sopenharmony_ci					   HID_FEATURE_REPORT,
14458c2ecf20Sopenharmony_ci					   HID_REQ_GET_REPORT);
14468c2ecf20Sopenharmony_ci			kfree(buf);
14478c2ecf20Sopenharmony_ci		}
14488c2ecf20Sopenharmony_ci
14498c2ecf20Sopenharmony_ci		field->value[index] = td->inputmode_value;
14508c2ecf20Sopenharmony_ci		*inputmode_found = true;
14518c2ecf20Sopenharmony_ci		return true;
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_ci	case HID_DG_CONTACTMAX:
14548c2ecf20Sopenharmony_ci		if (cls->maxcontacts) {
14558c2ecf20Sopenharmony_ci			max = min_t(int, field->logical_maximum,
14568c2ecf20Sopenharmony_ci				    cls->maxcontacts);
14578c2ecf20Sopenharmony_ci			if (field->value[index] != max) {
14588c2ecf20Sopenharmony_ci				field->value[index] = max;
14598c2ecf20Sopenharmony_ci				return true;
14608c2ecf20Sopenharmony_ci			}
14618c2ecf20Sopenharmony_ci		}
14628c2ecf20Sopenharmony_ci		break;
14638c2ecf20Sopenharmony_ci
14648c2ecf20Sopenharmony_ci	case HID_DG_LATENCYMODE:
14658c2ecf20Sopenharmony_ci		field->value[index] = latency;
14668c2ecf20Sopenharmony_ci		return true;
14678c2ecf20Sopenharmony_ci
14688c2ecf20Sopenharmony_ci	case HID_DG_SURFACESWITCH:
14698c2ecf20Sopenharmony_ci		field->value[index] = surface_switch;
14708c2ecf20Sopenharmony_ci		return true;
14718c2ecf20Sopenharmony_ci
14728c2ecf20Sopenharmony_ci	case HID_DG_BUTTONSWITCH:
14738c2ecf20Sopenharmony_ci		field->value[index] = button_switch;
14748c2ecf20Sopenharmony_ci		return true;
14758c2ecf20Sopenharmony_ci	}
14768c2ecf20Sopenharmony_ci
14778c2ecf20Sopenharmony_ci	return false; /* no need to update the report */
14788c2ecf20Sopenharmony_ci}
14798c2ecf20Sopenharmony_ci
14808c2ecf20Sopenharmony_cistatic void mt_set_modes(struct hid_device *hdev, enum latency_mode latency,
14818c2ecf20Sopenharmony_ci			 bool surface_switch, bool button_switch)
14828c2ecf20Sopenharmony_ci{
14838c2ecf20Sopenharmony_ci	struct hid_report_enum *rep_enum;
14848c2ecf20Sopenharmony_ci	struct hid_report *rep;
14858c2ecf20Sopenharmony_ci	struct hid_usage *usage;
14868c2ecf20Sopenharmony_ci	int i, j;
14878c2ecf20Sopenharmony_ci	bool update_report;
14888c2ecf20Sopenharmony_ci	bool inputmode_found = false;
14898c2ecf20Sopenharmony_ci
14908c2ecf20Sopenharmony_ci	rep_enum = &hdev->report_enum[HID_FEATURE_REPORT];
14918c2ecf20Sopenharmony_ci	list_for_each_entry(rep, &rep_enum->report_list, list) {
14928c2ecf20Sopenharmony_ci		update_report = false;
14938c2ecf20Sopenharmony_ci
14948c2ecf20Sopenharmony_ci		for (i = 0; i < rep->maxfield; i++) {
14958c2ecf20Sopenharmony_ci			/* Ignore if report count is out of bounds. */
14968c2ecf20Sopenharmony_ci			if (rep->field[i]->report_count < 1)
14978c2ecf20Sopenharmony_ci				continue;
14988c2ecf20Sopenharmony_ci
14998c2ecf20Sopenharmony_ci			for (j = 0; j < rep->field[i]->maxusage; j++) {
15008c2ecf20Sopenharmony_ci				usage = &rep->field[i]->usage[j];
15018c2ecf20Sopenharmony_ci
15028c2ecf20Sopenharmony_ci				if (mt_need_to_apply_feature(hdev,
15038c2ecf20Sopenharmony_ci							     rep->field[i],
15048c2ecf20Sopenharmony_ci							     usage,
15058c2ecf20Sopenharmony_ci							     latency,
15068c2ecf20Sopenharmony_ci							     surface_switch,
15078c2ecf20Sopenharmony_ci							     button_switch,
15088c2ecf20Sopenharmony_ci							     &inputmode_found))
15098c2ecf20Sopenharmony_ci					update_report = true;
15108c2ecf20Sopenharmony_ci			}
15118c2ecf20Sopenharmony_ci		}
15128c2ecf20Sopenharmony_ci
15138c2ecf20Sopenharmony_ci		if (update_report)
15148c2ecf20Sopenharmony_ci			hid_hw_request(hdev, rep, HID_REQ_SET_REPORT);
15158c2ecf20Sopenharmony_ci	}
15168c2ecf20Sopenharmony_ci}
15178c2ecf20Sopenharmony_ci
15188c2ecf20Sopenharmony_cistatic void mt_post_parse_default_settings(struct mt_device *td,
15198c2ecf20Sopenharmony_ci					   struct mt_application *app)
15208c2ecf20Sopenharmony_ci{
15218c2ecf20Sopenharmony_ci	__s32 quirks = app->quirks;
15228c2ecf20Sopenharmony_ci
15238c2ecf20Sopenharmony_ci	/* unknown serial device needs special quirks */
15248c2ecf20Sopenharmony_ci	if (list_is_singular(&app->mt_usages)) {
15258c2ecf20Sopenharmony_ci		quirks |= MT_QUIRK_ALWAYS_VALID;
15268c2ecf20Sopenharmony_ci		quirks &= ~MT_QUIRK_NOT_SEEN_MEANS_UP;
15278c2ecf20Sopenharmony_ci		quirks &= ~MT_QUIRK_VALID_IS_INRANGE;
15288c2ecf20Sopenharmony_ci		quirks &= ~MT_QUIRK_VALID_IS_CONFIDENCE;
15298c2ecf20Sopenharmony_ci		quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
15308c2ecf20Sopenharmony_ci	}
15318c2ecf20Sopenharmony_ci
15328c2ecf20Sopenharmony_ci	app->quirks = quirks;
15338c2ecf20Sopenharmony_ci}
15348c2ecf20Sopenharmony_ci
15358c2ecf20Sopenharmony_cistatic void mt_post_parse(struct mt_device *td, struct mt_application *app)
15368c2ecf20Sopenharmony_ci{
15378c2ecf20Sopenharmony_ci	if (!app->have_contact_count)
15388c2ecf20Sopenharmony_ci		app->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
15398c2ecf20Sopenharmony_ci}
15408c2ecf20Sopenharmony_ci
15418c2ecf20Sopenharmony_cistatic int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
15428c2ecf20Sopenharmony_ci{
15438c2ecf20Sopenharmony_ci	struct mt_device *td = hid_get_drvdata(hdev);
15448c2ecf20Sopenharmony_ci	const char *suffix = NULL;
15458c2ecf20Sopenharmony_ci	struct mt_report_data *rdata;
15468c2ecf20Sopenharmony_ci	struct mt_application *mt_application = NULL;
15478c2ecf20Sopenharmony_ci	struct hid_report *report;
15488c2ecf20Sopenharmony_ci	int ret;
15498c2ecf20Sopenharmony_ci
15508c2ecf20Sopenharmony_ci	list_for_each_entry(report, &hi->reports, hidinput_list) {
15518c2ecf20Sopenharmony_ci		rdata = mt_find_report_data(td, report);
15528c2ecf20Sopenharmony_ci		if (!rdata) {
15538c2ecf20Sopenharmony_ci			hid_err(hdev, "failed to allocate data for report\n");
15548c2ecf20Sopenharmony_ci			return -ENOMEM;
15558c2ecf20Sopenharmony_ci		}
15568c2ecf20Sopenharmony_ci
15578c2ecf20Sopenharmony_ci		mt_application = rdata->application;
15588c2ecf20Sopenharmony_ci
15598c2ecf20Sopenharmony_ci		if (rdata->is_mt_collection) {
15608c2ecf20Sopenharmony_ci			ret = mt_touch_input_configured(hdev, hi,
15618c2ecf20Sopenharmony_ci							mt_application);
15628c2ecf20Sopenharmony_ci			if (ret)
15638c2ecf20Sopenharmony_ci				return ret;
15648c2ecf20Sopenharmony_ci		}
15658c2ecf20Sopenharmony_ci	}
15668c2ecf20Sopenharmony_ci
15678c2ecf20Sopenharmony_ci	switch (hi->application) {
15688c2ecf20Sopenharmony_ci	case HID_GD_KEYBOARD:
15698c2ecf20Sopenharmony_ci	case HID_GD_KEYPAD:
15708c2ecf20Sopenharmony_ci	case HID_GD_MOUSE:
15718c2ecf20Sopenharmony_ci	case HID_DG_TOUCHPAD:
15728c2ecf20Sopenharmony_ci	case HID_GD_SYSTEM_CONTROL:
15738c2ecf20Sopenharmony_ci	case HID_CP_CONSUMER_CONTROL:
15748c2ecf20Sopenharmony_ci	case HID_GD_WIRELESS_RADIO_CTLS:
15758c2ecf20Sopenharmony_ci	case HID_GD_SYSTEM_MULTIAXIS:
15768c2ecf20Sopenharmony_ci		/* already handled by hid core */
15778c2ecf20Sopenharmony_ci		break;
15788c2ecf20Sopenharmony_ci	case HID_DG_TOUCHSCREEN:
15798c2ecf20Sopenharmony_ci		/* we do not set suffix = "Touchscreen" */
15808c2ecf20Sopenharmony_ci		hi->input->name = hdev->name;
15818c2ecf20Sopenharmony_ci		break;
15828c2ecf20Sopenharmony_ci	case HID_VD_ASUS_CUSTOM_MEDIA_KEYS:
15838c2ecf20Sopenharmony_ci		suffix = "Custom Media Keys";
15848c2ecf20Sopenharmony_ci		break;
15858c2ecf20Sopenharmony_ci	case HID_DG_STYLUS:
15868c2ecf20Sopenharmony_ci		/* force BTN_STYLUS to allow tablet matching in udev */
15878c2ecf20Sopenharmony_ci		__set_bit(BTN_STYLUS, hi->input->keybit);
15888c2ecf20Sopenharmony_ci		fallthrough;
15898c2ecf20Sopenharmony_ci	case HID_DG_PEN:
15908c2ecf20Sopenharmony_ci		suffix = "Stylus";
15918c2ecf20Sopenharmony_ci		break;
15928c2ecf20Sopenharmony_ci	default:
15938c2ecf20Sopenharmony_ci		suffix = "UNKNOWN";
15948c2ecf20Sopenharmony_ci		break;
15958c2ecf20Sopenharmony_ci	}
15968c2ecf20Sopenharmony_ci
15978c2ecf20Sopenharmony_ci	if (suffix)
15988c2ecf20Sopenharmony_ci		hi->input->name = devm_kasprintf(&hdev->dev, GFP_KERNEL,
15998c2ecf20Sopenharmony_ci						 "%s %s", hdev->name, suffix);
16008c2ecf20Sopenharmony_ci
16018c2ecf20Sopenharmony_ci	return 0;
16028c2ecf20Sopenharmony_ci}
16038c2ecf20Sopenharmony_ci
16048c2ecf20Sopenharmony_cistatic void mt_fix_const_field(struct hid_field *field, unsigned int usage)
16058c2ecf20Sopenharmony_ci{
16068c2ecf20Sopenharmony_ci	if (field->usage[0].hid != usage ||
16078c2ecf20Sopenharmony_ci	    !(field->flags & HID_MAIN_ITEM_CONSTANT))
16088c2ecf20Sopenharmony_ci		return;
16098c2ecf20Sopenharmony_ci
16108c2ecf20Sopenharmony_ci	field->flags &= ~HID_MAIN_ITEM_CONSTANT;
16118c2ecf20Sopenharmony_ci	field->flags |= HID_MAIN_ITEM_VARIABLE;
16128c2ecf20Sopenharmony_ci}
16138c2ecf20Sopenharmony_ci
16148c2ecf20Sopenharmony_cistatic void mt_fix_const_fields(struct hid_device *hdev, unsigned int usage)
16158c2ecf20Sopenharmony_ci{
16168c2ecf20Sopenharmony_ci	struct hid_report *report;
16178c2ecf20Sopenharmony_ci	int i;
16188c2ecf20Sopenharmony_ci
16198c2ecf20Sopenharmony_ci	list_for_each_entry(report,
16208c2ecf20Sopenharmony_ci			    &hdev->report_enum[HID_INPUT_REPORT].report_list,
16218c2ecf20Sopenharmony_ci			    list) {
16228c2ecf20Sopenharmony_ci
16238c2ecf20Sopenharmony_ci		if (!report->maxfield)
16248c2ecf20Sopenharmony_ci			continue;
16258c2ecf20Sopenharmony_ci
16268c2ecf20Sopenharmony_ci		for (i = 0; i < report->maxfield; i++)
16278c2ecf20Sopenharmony_ci			if (report->field[i]->maxusage >= 1)
16288c2ecf20Sopenharmony_ci				mt_fix_const_field(report->field[i], usage);
16298c2ecf20Sopenharmony_ci	}
16308c2ecf20Sopenharmony_ci}
16318c2ecf20Sopenharmony_ci
16328c2ecf20Sopenharmony_cistatic void mt_release_contacts(struct hid_device *hid)
16338c2ecf20Sopenharmony_ci{
16348c2ecf20Sopenharmony_ci	struct hid_input *hidinput;
16358c2ecf20Sopenharmony_ci	struct mt_application *application;
16368c2ecf20Sopenharmony_ci	struct mt_device *td = hid_get_drvdata(hid);
16378c2ecf20Sopenharmony_ci
16388c2ecf20Sopenharmony_ci	list_for_each_entry(hidinput, &hid->inputs, list) {
16398c2ecf20Sopenharmony_ci		struct input_dev *input_dev = hidinput->input;
16408c2ecf20Sopenharmony_ci		struct input_mt *mt = input_dev->mt;
16418c2ecf20Sopenharmony_ci		int i;
16428c2ecf20Sopenharmony_ci
16438c2ecf20Sopenharmony_ci		if (mt) {
16448c2ecf20Sopenharmony_ci			for (i = 0; i < mt->num_slots; i++) {
16458c2ecf20Sopenharmony_ci				input_mt_slot(input_dev, i);
16468c2ecf20Sopenharmony_ci				input_mt_report_slot_inactive(input_dev);
16478c2ecf20Sopenharmony_ci			}
16488c2ecf20Sopenharmony_ci			input_mt_sync_frame(input_dev);
16498c2ecf20Sopenharmony_ci			input_sync(input_dev);
16508c2ecf20Sopenharmony_ci		}
16518c2ecf20Sopenharmony_ci	}
16528c2ecf20Sopenharmony_ci
16538c2ecf20Sopenharmony_ci	list_for_each_entry(application, &td->applications, list) {
16548c2ecf20Sopenharmony_ci		application->num_received = 0;
16558c2ecf20Sopenharmony_ci	}
16568c2ecf20Sopenharmony_ci}
16578c2ecf20Sopenharmony_ci
16588c2ecf20Sopenharmony_cistatic void mt_expired_timeout(struct timer_list *t)
16598c2ecf20Sopenharmony_ci{
16608c2ecf20Sopenharmony_ci	struct mt_device *td = from_timer(td, t, release_timer);
16618c2ecf20Sopenharmony_ci	struct hid_device *hdev = td->hdev;
16628c2ecf20Sopenharmony_ci
16638c2ecf20Sopenharmony_ci	/*
16648c2ecf20Sopenharmony_ci	 * An input report came in just before we release the sticky fingers,
16658c2ecf20Sopenharmony_ci	 * it will take care of the sticky fingers.
16668c2ecf20Sopenharmony_ci	 */
16678c2ecf20Sopenharmony_ci	if (test_and_set_bit_lock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
16688c2ecf20Sopenharmony_ci		return;
16698c2ecf20Sopenharmony_ci	if (test_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags))
16708c2ecf20Sopenharmony_ci		mt_release_contacts(hdev);
16718c2ecf20Sopenharmony_ci	clear_bit_unlock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags);
16728c2ecf20Sopenharmony_ci}
16738c2ecf20Sopenharmony_ci
16748c2ecf20Sopenharmony_cistatic int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
16758c2ecf20Sopenharmony_ci{
16768c2ecf20Sopenharmony_ci	int ret, i;
16778c2ecf20Sopenharmony_ci	struct mt_device *td;
16788c2ecf20Sopenharmony_ci	const struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
16798c2ecf20Sopenharmony_ci
16808c2ecf20Sopenharmony_ci	for (i = 0; mt_classes[i].name ; i++) {
16818c2ecf20Sopenharmony_ci		if (id->driver_data == mt_classes[i].name) {
16828c2ecf20Sopenharmony_ci			mtclass = &(mt_classes[i]);
16838c2ecf20Sopenharmony_ci			break;
16848c2ecf20Sopenharmony_ci		}
16858c2ecf20Sopenharmony_ci	}
16868c2ecf20Sopenharmony_ci
16878c2ecf20Sopenharmony_ci	td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL);
16888c2ecf20Sopenharmony_ci	if (!td) {
16898c2ecf20Sopenharmony_ci		dev_err(&hdev->dev, "cannot allocate multitouch data\n");
16908c2ecf20Sopenharmony_ci		return -ENOMEM;
16918c2ecf20Sopenharmony_ci	}
16928c2ecf20Sopenharmony_ci	td->hdev = hdev;
16938c2ecf20Sopenharmony_ci	td->mtclass = *mtclass;
16948c2ecf20Sopenharmony_ci	td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
16958c2ecf20Sopenharmony_ci	hid_set_drvdata(hdev, td);
16968c2ecf20Sopenharmony_ci
16978c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&td->applications);
16988c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&td->reports);
16998c2ecf20Sopenharmony_ci
17008c2ecf20Sopenharmony_ci	if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
17018c2ecf20Sopenharmony_ci		td->serial_maybe = true;
17028c2ecf20Sopenharmony_ci
17038c2ecf20Sopenharmony_ci	/* This allows the driver to correctly support devices
17048c2ecf20Sopenharmony_ci	 * that emit events over several HID messages.
17058c2ecf20Sopenharmony_ci	 */
17068c2ecf20Sopenharmony_ci	hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
17078c2ecf20Sopenharmony_ci
17088c2ecf20Sopenharmony_ci	/*
17098c2ecf20Sopenharmony_ci	 * This allows the driver to handle different input sensors
17108c2ecf20Sopenharmony_ci	 * that emits events through different applications on the same HID
17118c2ecf20Sopenharmony_ci	 * device.
17128c2ecf20Sopenharmony_ci	 */
17138c2ecf20Sopenharmony_ci	hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
17148c2ecf20Sopenharmony_ci
17158c2ecf20Sopenharmony_ci	if (id->group != HID_GROUP_MULTITOUCH_WIN_8)
17168c2ecf20Sopenharmony_ci		hdev->quirks |= HID_QUIRK_MULTI_INPUT;
17178c2ecf20Sopenharmony_ci
17188c2ecf20Sopenharmony_ci	if (mtclass->quirks & MT_QUIRK_FORCE_MULTI_INPUT) {
17198c2ecf20Sopenharmony_ci		hdev->quirks &= ~HID_QUIRK_INPUT_PER_APP;
17208c2ecf20Sopenharmony_ci		hdev->quirks |= HID_QUIRK_MULTI_INPUT;
17218c2ecf20Sopenharmony_ci	}
17228c2ecf20Sopenharmony_ci
17238c2ecf20Sopenharmony_ci	timer_setup(&td->release_timer, mt_expired_timeout, 0);
17248c2ecf20Sopenharmony_ci
17258c2ecf20Sopenharmony_ci	ret = hid_parse(hdev);
17268c2ecf20Sopenharmony_ci	if (ret != 0)
17278c2ecf20Sopenharmony_ci		return ret;
17288c2ecf20Sopenharmony_ci
17298c2ecf20Sopenharmony_ci	if (mtclass->quirks & MT_QUIRK_FIX_CONST_CONTACT_ID)
17308c2ecf20Sopenharmony_ci		mt_fix_const_fields(hdev, HID_DG_CONTACTID);
17318c2ecf20Sopenharmony_ci
17328c2ecf20Sopenharmony_ci	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
17338c2ecf20Sopenharmony_ci	if (ret)
17348c2ecf20Sopenharmony_ci		return ret;
17358c2ecf20Sopenharmony_ci
17368c2ecf20Sopenharmony_ci	ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group);
17378c2ecf20Sopenharmony_ci	if (ret)
17388c2ecf20Sopenharmony_ci		dev_warn(&hdev->dev, "Cannot allocate sysfs group for %s\n",
17398c2ecf20Sopenharmony_ci				hdev->name);
17408c2ecf20Sopenharmony_ci
17418c2ecf20Sopenharmony_ci	mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
17428c2ecf20Sopenharmony_ci
17438c2ecf20Sopenharmony_ci	return 0;
17448c2ecf20Sopenharmony_ci}
17458c2ecf20Sopenharmony_ci
17468c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
17478c2ecf20Sopenharmony_cistatic int mt_reset_resume(struct hid_device *hdev)
17488c2ecf20Sopenharmony_ci{
17498c2ecf20Sopenharmony_ci	mt_release_contacts(hdev);
17508c2ecf20Sopenharmony_ci	mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
17518c2ecf20Sopenharmony_ci	return 0;
17528c2ecf20Sopenharmony_ci}
17538c2ecf20Sopenharmony_ci
17548c2ecf20Sopenharmony_cistatic int mt_resume(struct hid_device *hdev)
17558c2ecf20Sopenharmony_ci{
17568c2ecf20Sopenharmony_ci	/* Some Elan legacy devices require SET_IDLE to be set on resume.
17578c2ecf20Sopenharmony_ci	 * It should be safe to send it to other devices too.
17588c2ecf20Sopenharmony_ci	 * Tested on 3M, Stantum, Cypress, Zytronic, eGalax, and Elan panels. */
17598c2ecf20Sopenharmony_ci
17608c2ecf20Sopenharmony_ci	hid_hw_idle(hdev, 0, 0, HID_REQ_SET_IDLE);
17618c2ecf20Sopenharmony_ci
17628c2ecf20Sopenharmony_ci	return 0;
17638c2ecf20Sopenharmony_ci}
17648c2ecf20Sopenharmony_ci#endif
17658c2ecf20Sopenharmony_ci
17668c2ecf20Sopenharmony_cistatic void mt_remove(struct hid_device *hdev)
17678c2ecf20Sopenharmony_ci{
17688c2ecf20Sopenharmony_ci	struct mt_device *td = hid_get_drvdata(hdev);
17698c2ecf20Sopenharmony_ci
17708c2ecf20Sopenharmony_ci	del_timer_sync(&td->release_timer);
17718c2ecf20Sopenharmony_ci
17728c2ecf20Sopenharmony_ci	sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
17738c2ecf20Sopenharmony_ci	hid_hw_stop(hdev);
17748c2ecf20Sopenharmony_ci}
17758c2ecf20Sopenharmony_ci
17768c2ecf20Sopenharmony_ci/*
17778c2ecf20Sopenharmony_ci * This list contains only:
17788c2ecf20Sopenharmony_ci * - VID/PID of products not working with the default multitouch handling
17798c2ecf20Sopenharmony_ci * - 2 generic rules.
17808c2ecf20Sopenharmony_ci * So there is no point in adding here any device with MT_CLS_DEFAULT.
17818c2ecf20Sopenharmony_ci */
17828c2ecf20Sopenharmony_cistatic const struct hid_device_id mt_devices[] = {
17838c2ecf20Sopenharmony_ci
17848c2ecf20Sopenharmony_ci	/* 3M panels */
17858c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_3M,
17868c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_3M,
17878c2ecf20Sopenharmony_ci			USB_DEVICE_ID_3M1968) },
17888c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_3M,
17898c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_3M,
17908c2ecf20Sopenharmony_ci			USB_DEVICE_ID_3M2256) },
17918c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_3M,
17928c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_3M,
17938c2ecf20Sopenharmony_ci			USB_DEVICE_ID_3M3266) },
17948c2ecf20Sopenharmony_ci
17958c2ecf20Sopenharmony_ci	/* Anton devices */
17968c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
17978c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_ANTON,
17988c2ecf20Sopenharmony_ci			USB_DEVICE_ID_ANTON_TOUCH_PAD) },
17998c2ecf20Sopenharmony_ci
18008c2ecf20Sopenharmony_ci	/* Asus T304UA */
18018c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_ASUS,
18028c2ecf20Sopenharmony_ci		HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8,
18038c2ecf20Sopenharmony_ci			USB_VENDOR_ID_ASUSTEK,
18048c2ecf20Sopenharmony_ci			USB_DEVICE_ID_ASUSTEK_T304_KEYBOARD) },
18058c2ecf20Sopenharmony_ci
18068c2ecf20Sopenharmony_ci	/* Atmel panels */
18078c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_SERIAL,
18088c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_ATMEL,
18098c2ecf20Sopenharmony_ci			USB_DEVICE_ID_ATMEL_MXT_DIGITIZER) },
18108c2ecf20Sopenharmony_ci
18118c2ecf20Sopenharmony_ci	/* Baanto multitouch devices */
18128c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_NSMU,
18138c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_BAANTO,
18148c2ecf20Sopenharmony_ci			USB_DEVICE_ID_BAANTO_MT_190W2) },
18158c2ecf20Sopenharmony_ci
18168c2ecf20Sopenharmony_ci	/* Cando panels */
18178c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
18188c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
18198c2ecf20Sopenharmony_ci			USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
18208c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
18218c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
18228c2ecf20Sopenharmony_ci			USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
18238c2ecf20Sopenharmony_ci
18248c2ecf20Sopenharmony_ci	/* Chunghwa Telecom touch panels */
18258c2ecf20Sopenharmony_ci	{  .driver_data = MT_CLS_NSMU,
18268c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT,
18278c2ecf20Sopenharmony_ci			USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) },
18288c2ecf20Sopenharmony_ci
18298c2ecf20Sopenharmony_ci	/* CJTouch panels */
18308c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_NSMU,
18318c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_CJTOUCH,
18328c2ecf20Sopenharmony_ci			USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0020) },
18338c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_NSMU,
18348c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_CJTOUCH,
18358c2ecf20Sopenharmony_ci			USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0040) },
18368c2ecf20Sopenharmony_ci
18378c2ecf20Sopenharmony_ci	/* CVTouch panels */
18388c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_NSMU,
18398c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_CVTOUCH,
18408c2ecf20Sopenharmony_ci			USB_DEVICE_ID_CVTOUCH_SCREEN) },
18418c2ecf20Sopenharmony_ci
18428c2ecf20Sopenharmony_ci	/* eGalax devices (resistive) */
18438c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_EGALAX,
18448c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
18458c2ecf20Sopenharmony_ci			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D) },
18468c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_EGALAX,
18478c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
18488c2ecf20Sopenharmony_ci			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E) },
18498c2ecf20Sopenharmony_ci
18508c2ecf20Sopenharmony_ci	/* eGalax devices (capacitive) */
18518c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_EGALAX_SERIAL,
18528c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
18538c2ecf20Sopenharmony_ci			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7207) },
18548c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_EGALAX,
18558c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
18568c2ecf20Sopenharmony_ci			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C) },
18578c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_EGALAX_SERIAL,
18588c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
18598c2ecf20Sopenharmony_ci			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224) },
18608c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_EGALAX_SERIAL,
18618c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
18628c2ecf20Sopenharmony_ci			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_722A) },
18638c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_EGALAX_SERIAL,
18648c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
18658c2ecf20Sopenharmony_ci			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_725E) },
18668c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_EGALAX_SERIAL,
18678c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
18688c2ecf20Sopenharmony_ci			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7262) },
18698c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_EGALAX,
18708c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
18718c2ecf20Sopenharmony_ci			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B) },
18728c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_EGALAX,
18738c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
18748c2ecf20Sopenharmony_ci			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1) },
18758c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_EGALAX_SERIAL,
18768c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
18778c2ecf20Sopenharmony_ci			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72AA) },
18788c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_EGALAX,
18798c2ecf20Sopenharmony_ci		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
18808c2ecf20Sopenharmony_ci			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72C4) },
18818c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_EGALAX,
18828c2ecf20Sopenharmony_ci		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
18838c2ecf20Sopenharmony_ci			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72D0) },
18848c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_EGALAX,
18858c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
18868c2ecf20Sopenharmony_ci			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA) },
18878c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_EGALAX,
18888c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
18898c2ecf20Sopenharmony_ci			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302) },
18908c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_EGALAX_SERIAL,
18918c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
18928c2ecf20Sopenharmony_ci			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7349) },
18938c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_EGALAX_SERIAL,
18948c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
18958c2ecf20Sopenharmony_ci			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_73F7) },
18968c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_EGALAX_SERIAL,
18978c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
18988c2ecf20Sopenharmony_ci			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) },
18998c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_EGALAX,
19008c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
19018c2ecf20Sopenharmony_ci			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_C002) },
19028c2ecf20Sopenharmony_ci
19038c2ecf20Sopenharmony_ci	/* Elan devices */
19048c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT,
19058c2ecf20Sopenharmony_ci		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
19068c2ecf20Sopenharmony_ci			USB_VENDOR_ID_ELAN, 0x313a) },
19078c2ecf20Sopenharmony_ci
19088c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT,
19098c2ecf20Sopenharmony_ci		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
19108c2ecf20Sopenharmony_ci			USB_VENDOR_ID_ELAN, 0x3148) },
19118c2ecf20Sopenharmony_ci
19128c2ecf20Sopenharmony_ci	/* Elitegroup panel */
19138c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_SERIAL,
19148c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_ELITEGROUP,
19158c2ecf20Sopenharmony_ci			USB_DEVICE_ID_ELITEGROUP_05D8) },
19168c2ecf20Sopenharmony_ci
19178c2ecf20Sopenharmony_ci	/* Flatfrog Panels */
19188c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_FLATFROG,
19198c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_FLATFROG,
19208c2ecf20Sopenharmony_ci			USB_DEVICE_ID_MULTITOUCH_3200) },
19218c2ecf20Sopenharmony_ci
19228c2ecf20Sopenharmony_ci	/* FocalTech Panels */
19238c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_SERIAL,
19248c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_CYGNAL,
19258c2ecf20Sopenharmony_ci			USB_DEVICE_ID_FOCALTECH_FTXXXX_MULTITOUCH) },
19268c2ecf20Sopenharmony_ci
19278c2ecf20Sopenharmony_ci	/* GeneralTouch panel */
19288c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_GENERALTOUCH_TWOFINGERS,
19298c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
19308c2ecf20Sopenharmony_ci			USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
19318c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
19328c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
19338c2ecf20Sopenharmony_ci			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PWT_TENFINGERS) },
19348c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_GENERALTOUCH_TWOFINGERS,
19358c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
19368c2ecf20Sopenharmony_ci			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0101) },
19378c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
19388c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
19398c2ecf20Sopenharmony_ci			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0102) },
19408c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
19418c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
19428c2ecf20Sopenharmony_ci			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0106) },
19438c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
19448c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
19458c2ecf20Sopenharmony_ci			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_010A) },
19468c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
19478c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
19488c2ecf20Sopenharmony_ci			USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100) },
19498c2ecf20Sopenharmony_ci
19508c2ecf20Sopenharmony_ci	/* Gametel game controller */
19518c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_NSMU,
19528c2ecf20Sopenharmony_ci		MT_BT_DEVICE(USB_VENDOR_ID_FRUCTEL,
19538c2ecf20Sopenharmony_ci			USB_DEVICE_ID_GAMETEL_MT_MODE) },
19548c2ecf20Sopenharmony_ci
19558c2ecf20Sopenharmony_ci	/* GoodTouch panels */
19568c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_NSMU,
19578c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH,
19588c2ecf20Sopenharmony_ci			USB_DEVICE_ID_GOODTOUCH_000f) },
19598c2ecf20Sopenharmony_ci
19608c2ecf20Sopenharmony_ci	/* Hanvon panels */
19618c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
19628c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT,
19638c2ecf20Sopenharmony_ci			USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) },
19648c2ecf20Sopenharmony_ci
19658c2ecf20Sopenharmony_ci	/* HONOR GLO-GXXX panel */
19668c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_VTL,
19678c2ecf20Sopenharmony_ci		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
19688c2ecf20Sopenharmony_ci			0x347d, 0x7853) },
19698c2ecf20Sopenharmony_ci
19708c2ecf20Sopenharmony_ci	/* Ilitek dual touch panel */
19718c2ecf20Sopenharmony_ci	{  .driver_data = MT_CLS_NSMU,
19728c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_ILITEK,
19738c2ecf20Sopenharmony_ci			USB_DEVICE_ID_ILITEK_MULTITOUCH) },
19748c2ecf20Sopenharmony_ci
19758c2ecf20Sopenharmony_ci	/* LG Melfas panel */
19768c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_LG,
19778c2ecf20Sopenharmony_ci		HID_USB_DEVICE(USB_VENDOR_ID_LG,
19788c2ecf20Sopenharmony_ci			USB_DEVICE_ID_LG_MELFAS_MT) },
19798c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_LG,
19808c2ecf20Sopenharmony_ci		HID_DEVICE(BUS_I2C, HID_GROUP_GENERIC,
19818c2ecf20Sopenharmony_ci			USB_VENDOR_ID_LG, I2C_DEVICE_ID_LG_7010) },
19828c2ecf20Sopenharmony_ci
19838c2ecf20Sopenharmony_ci	/* Lenovo X1 TAB Gen 2 */
19848c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT,
19858c2ecf20Sopenharmony_ci		HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8,
19868c2ecf20Sopenharmony_ci			   USB_VENDOR_ID_LENOVO,
19878c2ecf20Sopenharmony_ci			   USB_DEVICE_ID_LENOVO_X1_TAB) },
19888c2ecf20Sopenharmony_ci
19898c2ecf20Sopenharmony_ci	/* Lenovo X1 TAB Gen 3 */
19908c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT,
19918c2ecf20Sopenharmony_ci		HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8,
19928c2ecf20Sopenharmony_ci			   USB_VENDOR_ID_LENOVO,
19938c2ecf20Sopenharmony_ci			   USB_DEVICE_ID_LENOVO_X1_TAB3) },
19948c2ecf20Sopenharmony_ci
19958c2ecf20Sopenharmony_ci	/* Lenovo X12 TAB Gen 1 */
19968c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT,
19978c2ecf20Sopenharmony_ci		HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8,
19988c2ecf20Sopenharmony_ci			   USB_VENDOR_ID_LENOVO,
19998c2ecf20Sopenharmony_ci			   USB_DEVICE_ID_LENOVO_X12_TAB) },
20008c2ecf20Sopenharmony_ci
20018c2ecf20Sopenharmony_ci	/* MosArt panels */
20028c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
20038c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_ASUS,
20048c2ecf20Sopenharmony_ci			USB_DEVICE_ID_ASUS_T91MT)},
20058c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
20068c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_ASUS,
20078c2ecf20Sopenharmony_ci			USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) },
20088c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
20098c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_TURBOX,
20108c2ecf20Sopenharmony_ci			USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) },
20118c2ecf20Sopenharmony_ci
20128c2ecf20Sopenharmony_ci	/* Novatek Panel */
20138c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_NSMU,
20148c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_NOVATEK,
20158c2ecf20Sopenharmony_ci			USB_DEVICE_ID_NOVATEK_PCT) },
20168c2ecf20Sopenharmony_ci
20178c2ecf20Sopenharmony_ci	/* Ntrig Panel */
20188c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_NSMU,
20198c2ecf20Sopenharmony_ci		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
20208c2ecf20Sopenharmony_ci			USB_VENDOR_ID_NTRIG, 0x1b05) },
20218c2ecf20Sopenharmony_ci
20228c2ecf20Sopenharmony_ci	/* Panasonic panels */
20238c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_PANASONIC,
20248c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC,
20258c2ecf20Sopenharmony_ci			USB_DEVICE_ID_PANABOARD_UBT780) },
20268c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_PANASONIC,
20278c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC,
20288c2ecf20Sopenharmony_ci			USB_DEVICE_ID_PANABOARD_UBT880) },
20298c2ecf20Sopenharmony_ci
20308c2ecf20Sopenharmony_ci	/* PixArt optical touch screen */
20318c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
20328c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_PIXART,
20338c2ecf20Sopenharmony_ci			USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN) },
20348c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
20358c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_PIXART,
20368c2ecf20Sopenharmony_ci			USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1) },
20378c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
20388c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_PIXART,
20398c2ecf20Sopenharmony_ci			USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2) },
20408c2ecf20Sopenharmony_ci
20418c2ecf20Sopenharmony_ci	/* PixCir-based panels */
20428c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
20438c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
20448c2ecf20Sopenharmony_ci			USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
20458c2ecf20Sopenharmony_ci
20468c2ecf20Sopenharmony_ci	/* Quanta-based panels */
20478c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID,
20488c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_QUANTA,
20498c2ecf20Sopenharmony_ci			USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001) },
20508c2ecf20Sopenharmony_ci
20518c2ecf20Sopenharmony_ci	/* Razer touchpads */
20528c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_RAZER_BLADE_STEALTH,
20538c2ecf20Sopenharmony_ci		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
20548c2ecf20Sopenharmony_ci			USB_VENDOR_ID_SYNAPTICS, 0x8323) },
20558c2ecf20Sopenharmony_ci
20568c2ecf20Sopenharmony_ci	/* Smart Tech panels */
20578c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_SMART_TECH,
20588c2ecf20Sopenharmony_ci		MT_USB_DEVICE(0x0b8c, 0x0092)},
20598c2ecf20Sopenharmony_ci
20608c2ecf20Sopenharmony_ci	/* Stantum panels */
20618c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_CONFIDENCE,
20628c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM,
20638c2ecf20Sopenharmony_ci			USB_DEVICE_ID_MTP_STM)},
20648c2ecf20Sopenharmony_ci
20658c2ecf20Sopenharmony_ci	/* Synaptics devices */
20668c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT,
20678c2ecf20Sopenharmony_ci		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
20688c2ecf20Sopenharmony_ci			USB_VENDOR_ID_SYNAPTICS, 0xcd7e) },
20698c2ecf20Sopenharmony_ci
20708c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT,
20718c2ecf20Sopenharmony_ci		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
20728c2ecf20Sopenharmony_ci			USB_VENDOR_ID_SYNAPTICS, 0xce08) },
20738c2ecf20Sopenharmony_ci
20748c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT,
20758c2ecf20Sopenharmony_ci		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
20768c2ecf20Sopenharmony_ci			USB_VENDOR_ID_SYNAPTICS, 0xce09) },
20778c2ecf20Sopenharmony_ci
20788c2ecf20Sopenharmony_ci	/* TopSeed panels */
20798c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_TOPSEED,
20808c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_TOPSEED2,
20818c2ecf20Sopenharmony_ci			USB_DEVICE_ID_TOPSEED2_PERIPAD_701) },
20828c2ecf20Sopenharmony_ci
20838c2ecf20Sopenharmony_ci	/* Touch International panels */
20848c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_NSMU,
20858c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_TOUCH_INTL,
20868c2ecf20Sopenharmony_ci			USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH) },
20878c2ecf20Sopenharmony_ci
20888c2ecf20Sopenharmony_ci	/* Unitec panels */
20898c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_NSMU,
20908c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_UNITEC,
20918c2ecf20Sopenharmony_ci			USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) },
20928c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_NSMU,
20938c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_UNITEC,
20948c2ecf20Sopenharmony_ci			USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
20958c2ecf20Sopenharmony_ci
20968c2ecf20Sopenharmony_ci	/* VTL panels */
20978c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_VTL,
20988c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_VTL,
20998c2ecf20Sopenharmony_ci			USB_DEVICE_ID_VTL_MULTITOUCH_FF3F) },
21008c2ecf20Sopenharmony_ci
21018c2ecf20Sopenharmony_ci	/* Wistron panels */
21028c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_NSMU,
21038c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_WISTRON,
21048c2ecf20Sopenharmony_ci			USB_DEVICE_ID_WISTRON_OPTICAL_TOUCH) },
21058c2ecf20Sopenharmony_ci
21068c2ecf20Sopenharmony_ci	/* XAT */
21078c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_NSMU,
21088c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_XAT,
21098c2ecf20Sopenharmony_ci			USB_DEVICE_ID_XAT_CSR) },
21108c2ecf20Sopenharmony_ci
21118c2ecf20Sopenharmony_ci	/* Xiroku */
21128c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_NSMU,
21138c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
21148c2ecf20Sopenharmony_ci			USB_DEVICE_ID_XIROKU_SPX) },
21158c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_NSMU,
21168c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
21178c2ecf20Sopenharmony_ci			USB_DEVICE_ID_XIROKU_MPX) },
21188c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_NSMU,
21198c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
21208c2ecf20Sopenharmony_ci			USB_DEVICE_ID_XIROKU_CSR) },
21218c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_NSMU,
21228c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
21238c2ecf20Sopenharmony_ci			USB_DEVICE_ID_XIROKU_SPX1) },
21248c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_NSMU,
21258c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
21268c2ecf20Sopenharmony_ci			USB_DEVICE_ID_XIROKU_MPX1) },
21278c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_NSMU,
21288c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
21298c2ecf20Sopenharmony_ci			USB_DEVICE_ID_XIROKU_CSR1) },
21308c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_NSMU,
21318c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
21328c2ecf20Sopenharmony_ci			USB_DEVICE_ID_XIROKU_SPX2) },
21338c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_NSMU,
21348c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
21358c2ecf20Sopenharmony_ci			USB_DEVICE_ID_XIROKU_MPX2) },
21368c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_NSMU,
21378c2ecf20Sopenharmony_ci		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
21388c2ecf20Sopenharmony_ci			USB_DEVICE_ID_XIROKU_CSR2) },
21398c2ecf20Sopenharmony_ci
21408c2ecf20Sopenharmony_ci	/* Google MT devices */
21418c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_GOOGLE,
21428c2ecf20Sopenharmony_ci		HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_GOOGLE,
21438c2ecf20Sopenharmony_ci			USB_DEVICE_ID_GOOGLE_TOUCH_ROSE) },
21448c2ecf20Sopenharmony_ci	{ .driver_data = MT_CLS_GOOGLE,
21458c2ecf20Sopenharmony_ci		HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8, USB_VENDOR_ID_GOOGLE,
21468c2ecf20Sopenharmony_ci			USB_DEVICE_ID_GOOGLE_WHISKERS) },
21478c2ecf20Sopenharmony_ci
21488c2ecf20Sopenharmony_ci	/* Generic MT device */
21498c2ecf20Sopenharmony_ci	{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH, HID_ANY_ID, HID_ANY_ID) },
21508c2ecf20Sopenharmony_ci
21518c2ecf20Sopenharmony_ci	/* Generic Win 8 certified MT device */
21528c2ecf20Sopenharmony_ci	{  .driver_data = MT_CLS_WIN_8,
21538c2ecf20Sopenharmony_ci		HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH_WIN_8,
21548c2ecf20Sopenharmony_ci			HID_ANY_ID, HID_ANY_ID) },
21558c2ecf20Sopenharmony_ci	{ }
21568c2ecf20Sopenharmony_ci};
21578c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(hid, mt_devices);
21588c2ecf20Sopenharmony_ci
21598c2ecf20Sopenharmony_cistatic const struct hid_usage_id mt_grabbed_usages[] = {
21608c2ecf20Sopenharmony_ci	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
21618c2ecf20Sopenharmony_ci	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
21628c2ecf20Sopenharmony_ci};
21638c2ecf20Sopenharmony_ci
21648c2ecf20Sopenharmony_cistatic struct hid_driver mt_driver = {
21658c2ecf20Sopenharmony_ci	.name = "hid-multitouch",
21668c2ecf20Sopenharmony_ci	.id_table = mt_devices,
21678c2ecf20Sopenharmony_ci	.probe = mt_probe,
21688c2ecf20Sopenharmony_ci	.remove = mt_remove,
21698c2ecf20Sopenharmony_ci	.input_mapping = mt_input_mapping,
21708c2ecf20Sopenharmony_ci	.input_mapped = mt_input_mapped,
21718c2ecf20Sopenharmony_ci	.input_configured = mt_input_configured,
21728c2ecf20Sopenharmony_ci	.feature_mapping = mt_feature_mapping,
21738c2ecf20Sopenharmony_ci	.usage_table = mt_grabbed_usages,
21748c2ecf20Sopenharmony_ci	.event = mt_event,
21758c2ecf20Sopenharmony_ci	.report = mt_report,
21768c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
21778c2ecf20Sopenharmony_ci	.reset_resume = mt_reset_resume,
21788c2ecf20Sopenharmony_ci	.resume = mt_resume,
21798c2ecf20Sopenharmony_ci#endif
21808c2ecf20Sopenharmony_ci};
21818c2ecf20Sopenharmony_cimodule_hid_driver(mt_driver);
2182