hid-multitouch.c revision b105712469d957cf1ab223c1ea72b7ba88edb926
15519cab477b61326963c8d523520db0342862b63Benjamin Tissoires/*
25519cab477b61326963c8d523520db0342862b63Benjamin Tissoires *  HID driver for multitouch panels
35519cab477b61326963c8d523520db0342862b63Benjamin Tissoires *
45519cab477b61326963c8d523520db0342862b63Benjamin Tissoires *  Copyright (c) 2010-2011 Stephane Chatty <chatty@enac.fr>
55519cab477b61326963c8d523520db0342862b63Benjamin Tissoires *  Copyright (c) 2010-2011 Benjamin Tissoires <benjamin.tissoires@gmail.com>
65519cab477b61326963c8d523520db0342862b63Benjamin Tissoires *  Copyright (c) 2010-2011 Ecole Nationale de l'Aviation Civile, France
75519cab477b61326963c8d523520db0342862b63Benjamin Tissoires *
84875ac114d8bce99838a9b0ee7c3f5469cc6352eRichard Nauber *  This code is partly based on hid-egalax.c:
94875ac114d8bce99838a9b0ee7c3f5469cc6352eRichard Nauber *
104875ac114d8bce99838a9b0ee7c3f5469cc6352eRichard Nauber *  Copyright (c) 2010 Stephane Chatty <chatty@enac.fr>
114875ac114d8bce99838a9b0ee7c3f5469cc6352eRichard Nauber *  Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se>
124875ac114d8bce99838a9b0ee7c3f5469cc6352eRichard Nauber *  Copyright (c) 2010 Canonical, Ltd.
134875ac114d8bce99838a9b0ee7c3f5469cc6352eRichard Nauber *
14f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires *  This code is partly based on hid-3m-pct.c:
15f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires *
16f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires *  Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
17f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires *  Copyright (c) 2010      Henrik Rydberg <rydberg@euromail.se>
18f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires *  Copyright (c) 2010      Canonical, Ltd.
19f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires *
205519cab477b61326963c8d523520db0342862b63Benjamin Tissoires */
215519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
225519cab477b61326963c8d523520db0342862b63Benjamin Tissoires/*
235519cab477b61326963c8d523520db0342862b63Benjamin Tissoires * This program is free software; you can redistribute it and/or modify it
245519cab477b61326963c8d523520db0342862b63Benjamin Tissoires * under the terms of the GNU General Public License as published by the Free
255519cab477b61326963c8d523520db0342862b63Benjamin Tissoires * Software Foundation; either version 2 of the License, or (at your option)
265519cab477b61326963c8d523520db0342862b63Benjamin Tissoires * any later version.
275519cab477b61326963c8d523520db0342862b63Benjamin Tissoires */
285519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
295519cab477b61326963c8d523520db0342862b63Benjamin Tissoires#include <linux/device.h>
305519cab477b61326963c8d523520db0342862b63Benjamin Tissoires#include <linux/hid.h>
315519cab477b61326963c8d523520db0342862b63Benjamin Tissoires#include <linux/module.h>
325519cab477b61326963c8d523520db0342862b63Benjamin Tissoires#include <linux/slab.h>
335519cab477b61326963c8d523520db0342862b63Benjamin Tissoires#include <linux/usb.h>
345519cab477b61326963c8d523520db0342862b63Benjamin Tissoires#include <linux/input/mt.h>
355519cab477b61326963c8d523520db0342862b63Benjamin Tissoires#include "usbhid/usbhid.h"
365519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
375519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
385519cab477b61326963c8d523520db0342862b63Benjamin TissoiresMODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
39ef2fafb3e233ca9cb390fc3c1461b7f3859998fcBenjamin TissoiresMODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
405519cab477b61326963c8d523520db0342862b63Benjamin TissoiresMODULE_DESCRIPTION("HID multitouch panels");
415519cab477b61326963c8d523520db0342862b63Benjamin TissoiresMODULE_LICENSE("GPL");
425519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
435519cab477b61326963c8d523520db0342862b63Benjamin Tissoires#include "hid-ids.h"
445519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
455519cab477b61326963c8d523520db0342862b63Benjamin Tissoires/* quirks to control the device */
465519cab477b61326963c8d523520db0342862b63Benjamin Tissoires#define MT_QUIRK_NOT_SEEN_MEANS_UP	(1 << 0)
475519cab477b61326963c8d523520db0342862b63Benjamin Tissoires#define MT_QUIRK_SLOT_IS_CONTACTID	(1 << 1)
482d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires#define MT_QUIRK_CYPRESS		(1 << 2)
495572da08a784621f2ab4fdc8dc65471261871795Benjamin Tissoires#define MT_QUIRK_SLOT_IS_CONTACTNUMBER	(1 << 3)
50a062cc5a76fa1d12f0821e56e3746cad2dc2fc65Stephane Chatty#define MT_QUIRK_ALWAYS_VALID		(1 << 4)
51a062cc5a76fa1d12f0821e56e3746cad2dc2fc65Stephane Chatty#define MT_QUIRK_VALID_IS_INRANGE	(1 << 5)
52a062cc5a76fa1d12f0821e56e3746cad2dc2fc65Stephane Chatty#define MT_QUIRK_VALID_IS_CONFIDENCE	(1 << 6)
53a062cc5a76fa1d12f0821e56e3746cad2dc2fc65Stephane Chatty#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE	(1 << 8)
545519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
555519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresstruct mt_slot {
565519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	__s32 x, y, p, w, h;
575519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	__s32 contactid;	/* the device ContactID assigned to this slot */
585519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	bool touch_state;	/* is the touch valid? */
595519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	bool seen_in_this_frame;/* has this slot been updated */
605519cab477b61326963c8d523520db0342862b63Benjamin Tissoires};
615519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
62eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoiresstruct mt_class {
63eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	__s32 name;	/* MT_CLS */
64eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	__s32 quirks;
65eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	__s32 sn_move;	/* Signal/noise ratio for move events */
66eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	__s32 sn_width;	/* Signal/noise ratio for width events */
67eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	__s32 sn_height;	/* Signal/noise ratio for height events */
68eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	__s32 sn_pressure;	/* Signal/noise ratio for pressure events */
69eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	__u8 maxcontacts;
70eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires};
71eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires
725519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresstruct mt_device {
735519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	struct mt_slot curdata;	/* placeholder of incoming data */
74eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	struct mt_class mtclass;	/* our mt device class */
755519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	unsigned last_field_index;	/* last field index of the report */
765519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	unsigned last_slot_field;	/* the last field of a slot */
77b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires	int last_mt_collection;	/* last known mt-related collection */
785519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	__s8 inputmode;		/* InputMode HID feature, -1 if non-existent */
795519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	__u8 num_received;	/* how many contacts we received */
805519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	__u8 num_expected;	/* expected last contact index */
819498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires	__u8 maxcontacts;
825519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	bool curvalid;		/* is the current contact valid? */
839498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires	struct mt_slot *slots;
845519cab477b61326963c8d523520db0342862b63Benjamin Tissoires};
855519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
865519cab477b61326963c8d523520db0342862b63Benjamin Tissoires/* classes of device behavior */
8722408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires#define MT_CLS_DEFAULT				0x0001
8822408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires
89a062cc5a76fa1d12f0821e56e3746cad2dc2fc65Stephane Chatty#define MT_CLS_SERIAL				0x0002
90a062cc5a76fa1d12f0821e56e3746cad2dc2fc65Stephane Chatty#define MT_CLS_CONFIDENCE			0x0003
915e7ea11f603a0aeb77fd1bff0b242931ffe139deBenjamin Tissoires#define MT_CLS_CONFIDENCE_CONTACT_ID		0x0004
925e7ea11f603a0aeb77fd1bff0b242931ffe139deBenjamin Tissoires#define MT_CLS_CONFIDENCE_MINUS_ONE		0x0005
935e7ea11f603a0aeb77fd1bff0b242931ffe139deBenjamin Tissoires#define MT_CLS_DUAL_INRANGE_CONTACTID		0x0006
945e7ea11f603a0aeb77fd1bff0b242931ffe139deBenjamin Tissoires#define MT_CLS_DUAL_INRANGE_CONTACTNUMBER	0x0007
955e7ea11f603a0aeb77fd1bff0b242931ffe139deBenjamin Tissoires#define MT_CLS_DUAL_NSMU_CONTACTID		0x0008
96b7ea95ff9baab144dacdc30d752307938c5ab6bfAaron Tian#define MT_CLS_INRANGE_CONTACTNUMBER		0x0009
9722408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires
9822408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires/* vendor specific classes */
9922408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires#define MT_CLS_3M				0x0101
10022408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires#define MT_CLS_CYPRESS				0x0102
10122408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires#define MT_CLS_EGALAX				0x0103
1021b723e8dc81b23141bfb8991e002073b17fd0199Benjamin Tissoires#define MT_CLS_EGALAX_SERIAL			0x0104
1035519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
1049498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires#define MT_DEFAULT_MAXCONTACT	10
1059498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires
1065519cab477b61326963c8d523520db0342862b63Benjamin Tissoires/*
1075519cab477b61326963c8d523520db0342862b63Benjamin Tissoires * these device-dependent functions determine what slot corresponds
1085519cab477b61326963c8d523520db0342862b63Benjamin Tissoires * to a valid contact that was just read.
1095519cab477b61326963c8d523520db0342862b63Benjamin Tissoires */
1105519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
111a3b5e577d96bfccbc41ebf4df784e3a153072273Benjamin Tissoiresstatic int cypress_compute_slot(struct mt_device *td)
112a3b5e577d96bfccbc41ebf4df784e3a153072273Benjamin Tissoires{
113a3b5e577d96bfccbc41ebf4df784e3a153072273Benjamin Tissoires	if (td->curdata.contactid != 0 || td->num_received == 0)
114a3b5e577d96bfccbc41ebf4df784e3a153072273Benjamin Tissoires		return td->curdata.contactid;
115a3b5e577d96bfccbc41ebf4df784e3a153072273Benjamin Tissoires	else
116a3b5e577d96bfccbc41ebf4df784e3a153072273Benjamin Tissoires		return -1;
117a3b5e577d96bfccbc41ebf4df784e3a153072273Benjamin Tissoires}
118a3b5e577d96bfccbc41ebf4df784e3a153072273Benjamin Tissoires
1195519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresstatic int find_slot_from_contactid(struct mt_device *td)
1205519cab477b61326963c8d523520db0342862b63Benjamin Tissoires{
1215519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	int i;
1229498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires	for (i = 0; i < td->maxcontacts; ++i) {
1235519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		if (td->slots[i].contactid == td->curdata.contactid &&
1245519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			td->slots[i].touch_state)
1255519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			return i;
1265519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	}
1279498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires	for (i = 0; i < td->maxcontacts; ++i) {
1285519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		if (!td->slots[i].seen_in_this_frame &&
1295519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			!td->slots[i].touch_state)
1305519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			return i;
1315519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	}
1325519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	/* should not occurs. If this happens that means
1335519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	 * that the device sent more touches that it says
1345519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	 * in the report descriptor. It is ignored then. */
1352d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires	return -1;
1365519cab477b61326963c8d523520db0342862b63Benjamin Tissoires}
1375519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
1385519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresstruct mt_class mt_classes[] = {
1392d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires	{ .name = MT_CLS_DEFAULT,
1409498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP },
141a062cc5a76fa1d12f0821e56e3746cad2dc2fc65Stephane Chatty	{ .name = MT_CLS_SERIAL,
142a062cc5a76fa1d12f0821e56e3746cad2dc2fc65Stephane Chatty		.quirks = MT_QUIRK_ALWAYS_VALID},
14322408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires	{ .name = MT_CLS_CONFIDENCE,
14422408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE },
1455e7ea11f603a0aeb77fd1bff0b242931ffe139deBenjamin Tissoires	{ .name = MT_CLS_CONFIDENCE_CONTACT_ID,
1465e7ea11f603a0aeb77fd1bff0b242931ffe139deBenjamin Tissoires		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
1475e7ea11f603a0aeb77fd1bff0b242931ffe139deBenjamin Tissoires			MT_QUIRK_SLOT_IS_CONTACTID },
14822408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires	{ .name = MT_CLS_CONFIDENCE_MINUS_ONE,
14922408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
15022408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires			MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE },
1511e9cf35b995610e7ba2934d3dc92e3a03fa361a1Benjamin Tissoires	{ .name = MT_CLS_DUAL_INRANGE_CONTACTID,
1522d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires		.quirks = MT_QUIRK_VALID_IS_INRANGE |
1532d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires			MT_QUIRK_SLOT_IS_CONTACTID,
1542d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires		.maxcontacts = 2 },
1551e9cf35b995610e7ba2934d3dc92e3a03fa361a1Benjamin Tissoires	{ .name = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
1562d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires		.quirks = MT_QUIRK_VALID_IS_INRANGE |
1572d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires			MT_QUIRK_SLOT_IS_CONTACTNUMBER,
1582d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires		.maxcontacts = 2 },
15922408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires	{ .name = MT_CLS_DUAL_NSMU_CONTACTID,
16022408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
16122408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires			MT_QUIRK_SLOT_IS_CONTACTID,
16222408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires		.maxcontacts = 2 },
163b7ea95ff9baab144dacdc30d752307938c5ab6bfAaron Tian	{ .name = MT_CLS_INRANGE_CONTACTNUMBER,
164b7ea95ff9baab144dacdc30d752307938c5ab6bfAaron Tian		.quirks = MT_QUIRK_VALID_IS_INRANGE |
165b7ea95ff9baab144dacdc30d752307938c5ab6bfAaron Tian			MT_QUIRK_SLOT_IS_CONTACTNUMBER },
16622408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires
16722408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires	/*
16822408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires	 * vendor specific classes
16922408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires	 */
17022408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires	{ .name = MT_CLS_3M,
17122408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
17222408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires			MT_QUIRK_SLOT_IS_CONTACTID,
17322408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires		.sn_move = 2048,
17422408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires		.sn_width = 128,
17522408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires		.sn_height = 128 },
1762d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires	{ .name = MT_CLS_CYPRESS,
1772d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
1782d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires			MT_QUIRK_CYPRESS,
1792d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires		.maxcontacts = 10 },
1804875ac114d8bce99838a9b0ee7c3f5469cc6352eRichard Nauber	{ .name = MT_CLS_EGALAX,
1814875ac114d8bce99838a9b0ee7c3f5469cc6352eRichard Nauber		.quirks =  MT_QUIRK_SLOT_IS_CONTACTID |
1822261bb9ff0dc38e1d5f35af08f75ec3b37ba6335Benjamin Tissoires			MT_QUIRK_VALID_IS_INRANGE,
1834875ac114d8bce99838a9b0ee7c3f5469cc6352eRichard Nauber		.sn_move = 4096,
1844875ac114d8bce99838a9b0ee7c3f5469cc6352eRichard Nauber		.sn_pressure = 32,
1854875ac114d8bce99838a9b0ee7c3f5469cc6352eRichard Nauber	},
1861b723e8dc81b23141bfb8991e002073b17fd0199Benjamin Tissoires	{ .name = MT_CLS_EGALAX_SERIAL,
1871b723e8dc81b23141bfb8991e002073b17fd0199Benjamin Tissoires		.quirks =  MT_QUIRK_SLOT_IS_CONTACTID |
1881b723e8dc81b23141bfb8991e002073b17fd0199Benjamin Tissoires			MT_QUIRK_ALWAYS_VALID,
1891b723e8dc81b23141bfb8991e002073b17fd0199Benjamin Tissoires		.sn_move = 4096,
1901b723e8dc81b23141bfb8991e002073b17fd0199Benjamin Tissoires		.sn_pressure = 32,
1911b723e8dc81b23141bfb8991e002073b17fd0199Benjamin Tissoires	},
192043b403aede4a528ed99ceaf050f567f1283a23eBenjamin Tissoires
1932d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires	{ }
1945519cab477b61326963c8d523520db0342862b63Benjamin Tissoires};
1955519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
196eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoiresstatic ssize_t mt_show_quirks(struct device *dev,
197eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires			   struct device_attribute *attr,
198eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires			   char *buf)
199eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires{
200eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
201eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	struct mt_device *td = hid_get_drvdata(hdev);
202eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires
203eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	return sprintf(buf, "%u\n", td->mtclass.quirks);
204eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires}
205eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires
206eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoiresstatic ssize_t mt_set_quirks(struct device *dev,
207eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires			  struct device_attribute *attr,
208eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires			  const char *buf, size_t count)
209eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires{
210eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
211eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	struct mt_device *td = hid_get_drvdata(hdev);
212eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires
213eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	unsigned long val;
214eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires
215eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	if (kstrtoul(buf, 0, &val))
216eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires		return -EINVAL;
217eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires
218eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	td->mtclass.quirks = val;
219eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires
220eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	return count;
221eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires}
222eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires
223eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoiresstatic DEVICE_ATTR(quirks, S_IWUSR | S_IRUGO, mt_show_quirks, mt_set_quirks);
224eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires
225eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoiresstatic struct attribute *sysfs_attrs[] = {
226eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	&dev_attr_quirks.attr,
227eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	NULL
228eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires};
229eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires
230eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoiresstatic struct attribute_group mt_attribute_group = {
231eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	.attrs = sysfs_attrs
232eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires};
233eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires
234f635bd11c8d332d917fb9a4cad3071b2357d5b2aHenrik Rydbergstatic void mt_feature_mapping(struct hid_device *hdev,
2355519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		struct hid_field *field, struct hid_usage *usage)
2365519cab477b61326963c8d523520db0342862b63Benjamin Tissoires{
2379498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires	struct mt_device *td = hid_get_drvdata(hdev);
2389498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires
2399498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires	switch (usage->hid) {
2409498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires	case HID_DG_INPUTMODE:
2415519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		td->inputmode = field->report->id;
2429498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires		break;
2439498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires	case HID_DG_CONTACTMAX:
2449498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires		td->maxcontacts = field->value[0];
245eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires		if (td->mtclass.maxcontacts)
2469498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires			/* check if the maxcontacts is given by the class */
247eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires			td->maxcontacts = td->mtclass.maxcontacts;
2489498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires
2499498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires		break;
2505519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	}
2515519cab477b61326963c8d523520db0342862b63Benjamin Tissoires}
2525519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
2535519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresstatic void set_abs(struct input_dev *input, unsigned int code,
2545519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		struct hid_field *field, int snratio)
2555519cab477b61326963c8d523520db0342862b63Benjamin Tissoires{
2565519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	int fmin = field->logical_minimum;
2575519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	int fmax = field->logical_maximum;
2585519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	int fuzz = snratio ? (fmax - fmin) / snratio : 0;
2595519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
2605519cab477b61326963c8d523520db0342862b63Benjamin Tissoires}
2615519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
2625519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresstatic int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
2635519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		struct hid_field *field, struct hid_usage *usage,
2645519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		unsigned long **bit, int *max)
2655519cab477b61326963c8d523520db0342862b63Benjamin Tissoires{
2665519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	struct mt_device *td = hid_get_drvdata(hdev);
267eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	struct mt_class *cls = &td->mtclass;
2684875ac114d8bce99838a9b0ee7c3f5469cc6352eRichard Nauber
269658d4aed59b36f877edc668cc27b188a33e643e5Jeff Brown	/* Only map fields from TouchScreen or TouchPad collections.
270658d4aed59b36f877edc668cc27b188a33e643e5Jeff Brown         * We need to ignore fields that belong to other collections
271658d4aed59b36f877edc668cc27b188a33e643e5Jeff Brown         * such as Mouse that might have the same GenericDesktop usages. */
272658d4aed59b36f877edc668cc27b188a33e643e5Jeff Brown	if (field->application == HID_DG_TOUCHSCREEN)
273658d4aed59b36f877edc668cc27b188a33e643e5Jeff Brown		set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
274658d4aed59b36f877edc668cc27b188a33e643e5Jeff Brown	else if (field->application == HID_DG_TOUCHPAD)
275658d4aed59b36f877edc668cc27b188a33e643e5Jeff Brown		set_bit(INPUT_PROP_POINTER, hi->input->propbit);
276658d4aed59b36f877edc668cc27b188a33e643e5Jeff Brown	else
277658d4aed59b36f877edc668cc27b188a33e643e5Jeff Brown		return 0;
278658d4aed59b36f877edc668cc27b188a33e643e5Jeff Brown
2792261bb9ff0dc38e1d5f35af08f75ec3b37ba6335Benjamin Tissoires	/* eGalax devices provide a Digitizer.Stylus input which overrides
2802261bb9ff0dc38e1d5f35af08f75ec3b37ba6335Benjamin Tissoires	 * the correct Digitizers.Finger X/Y ranges.
2812261bb9ff0dc38e1d5f35af08f75ec3b37ba6335Benjamin Tissoires	 * Let's just ignore this input. */
2822261bb9ff0dc38e1d5f35af08f75ec3b37ba6335Benjamin Tissoires	if (field->physical == HID_DG_STYLUS)
2832261bb9ff0dc38e1d5f35af08f75ec3b37ba6335Benjamin Tissoires		return -1;
2842261bb9ff0dc38e1d5f35af08f75ec3b37ba6335Benjamin Tissoires
2855519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	switch (usage->hid & HID_USAGE_PAGE) {
2865519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
2875519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	case HID_UP_GENDESK:
2885519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		switch (usage->hid) {
2895519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		case HID_GD_X:
2905519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			hid_map_usage(hi, usage, bit, max,
2915519cab477b61326963c8d523520db0342862b63Benjamin Tissoires					EV_ABS, ABS_MT_POSITION_X);
2925519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			set_abs(hi->input, ABS_MT_POSITION_X, field,
2935519cab477b61326963c8d523520db0342862b63Benjamin Tissoires				cls->sn_move);
2945519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			/* touchscreen emulation */
2955519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			set_abs(hi->input, ABS_X, field, cls->sn_move);
296b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires			if (td->last_mt_collection == usage->collection_index) {
297b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires				td->last_slot_field = usage->hid;
298b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires				td->last_field_index = field->index;
299b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires			}
3005519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			return 1;
3015519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		case HID_GD_Y:
3025519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			hid_map_usage(hi, usage, bit, max,
3035519cab477b61326963c8d523520db0342862b63Benjamin Tissoires					EV_ABS, ABS_MT_POSITION_Y);
3045519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			set_abs(hi->input, ABS_MT_POSITION_Y, field,
3055519cab477b61326963c8d523520db0342862b63Benjamin Tissoires				cls->sn_move);
3065519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			/* touchscreen emulation */
3075519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			set_abs(hi->input, ABS_Y, field, cls->sn_move);
308b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires			if (td->last_mt_collection == usage->collection_index) {
309b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires				td->last_slot_field = usage->hid;
310b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires				td->last_field_index = field->index;
311b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires			}
3125519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			return 1;
3135519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		}
3145519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		return 0;
3155519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
3165519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	case HID_UP_DIGITIZER:
3175519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		switch (usage->hid) {
3185519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		case HID_DG_INRANGE:
319b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires			if (td->last_mt_collection == usage->collection_index) {
320b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires				td->last_slot_field = usage->hid;
321b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires				td->last_field_index = field->index;
322b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires			}
3235519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			return 1;
3245519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		case HID_DG_CONFIDENCE:
325b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires			if (td->last_mt_collection == usage->collection_index) {
326b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires				td->last_slot_field = usage->hid;
327b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires				td->last_field_index = field->index;
328b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires			}
3295519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			return 1;
3305519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		case HID_DG_TIPSWITCH:
3315519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
3325519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
333b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires			if (td->last_mt_collection == usage->collection_index) {
334b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires				td->last_slot_field = usage->hid;
335b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires				td->last_field_index = field->index;
336b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires			}
3375519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			return 1;
3385519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		case HID_DG_CONTACTID:
33950bc03ab5c7529fdfe4e01621efca7d26439ea00Benjamin Tissoires			if (!td->maxcontacts)
34050bc03ab5c7529fdfe4e01621efca7d26439ea00Benjamin Tissoires				td->maxcontacts = MT_DEFAULT_MAXCONTACT;
3419498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires			input_mt_init_slots(hi->input, td->maxcontacts);
3425519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			td->last_slot_field = usage->hid;
3432955caed8b9865c1f04fcde6bd7103d5d5ec9415Benjamin Tissoires			td->last_field_index = field->index;
344b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires			td->last_mt_collection = usage->collection_index;
3455519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			return 1;
3465519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		case HID_DG_WIDTH:
3475519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			hid_map_usage(hi, usage, bit, max,
3485519cab477b61326963c8d523520db0342862b63Benjamin Tissoires					EV_ABS, ABS_MT_TOUCH_MAJOR);
349f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires			set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
350f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires				cls->sn_width);
351b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires			if (td->last_mt_collection == usage->collection_index) {
352b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires				td->last_slot_field = usage->hid;
353b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires				td->last_field_index = field->index;
354b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires			}
3555519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			return 1;
3565519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		case HID_DG_HEIGHT:
3575519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			hid_map_usage(hi, usage, bit, max,
3585519cab477b61326963c8d523520db0342862b63Benjamin Tissoires					EV_ABS, ABS_MT_TOUCH_MINOR);
359f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires			set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
360f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires				cls->sn_height);
3611e648a13720ef5de51f132501acf3e443d1a36d4Benjamin Tissoires			input_set_abs_params(hi->input,
3621e648a13720ef5de51f132501acf3e443d1a36d4Benjamin Tissoires					ABS_MT_ORIENTATION, 0, 1, 0, 0);
363b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires			if (td->last_mt_collection == usage->collection_index) {
364b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires				td->last_slot_field = usage->hid;
365b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires				td->last_field_index = field->index;
366b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires			}
3675519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			return 1;
3685519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		case HID_DG_TIPPRESSURE:
3695519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			hid_map_usage(hi, usage, bit, max,
3705519cab477b61326963c8d523520db0342862b63Benjamin Tissoires					EV_ABS, ABS_MT_PRESSURE);
3715519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			set_abs(hi->input, ABS_MT_PRESSURE, field,
3725519cab477b61326963c8d523520db0342862b63Benjamin Tissoires				cls->sn_pressure);
3735519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			/* touchscreen emulation */
3745519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			set_abs(hi->input, ABS_PRESSURE, field,
3755519cab477b61326963c8d523520db0342862b63Benjamin Tissoires				cls->sn_pressure);
376b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires			if (td->last_mt_collection == usage->collection_index) {
377b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires				td->last_slot_field = usage->hid;
378b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires				td->last_field_index = field->index;
379b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires			}
3805519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			return 1;
3815519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		case HID_DG_CONTACTCOUNT:
382b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires			if (td->last_mt_collection == usage->collection_index)
383b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires				td->last_field_index = field->index;
3845519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			return 1;
3855519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		case HID_DG_CONTACTMAX:
3865519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			/* we don't set td->last_slot_field as contactcount and
3875519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			 * contact max are global to the report */
388b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires			if (td->last_mt_collection == usage->collection_index)
389b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires				td->last_field_index = field->index;
3905519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			return -1;
3915519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		}
3925519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		/* let hid-input decide for the others */
3935519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		return 0;
3945519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
3955519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	case 0xff000000:
3965519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		/* we do not want to map these: no input-oriented meaning */
3975519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		return -1;
3985519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	}
3995519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
4005519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	return 0;
4015519cab477b61326963c8d523520db0342862b63Benjamin Tissoires}
4025519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
4035519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresstatic int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
4045519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		struct hid_field *field, struct hid_usage *usage,
4055519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		unsigned long **bit, int *max)
4065519cab477b61326963c8d523520db0342862b63Benjamin Tissoires{
4075519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	if (usage->type == EV_KEY || usage->type == EV_ABS)
4085519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		set_bit(usage->type, hi->input->evbit);
4095519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
4105519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	return -1;
4115519cab477b61326963c8d523520db0342862b63Benjamin Tissoires}
4125519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
4135519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresstatic int mt_compute_slot(struct mt_device *td)
4145519cab477b61326963c8d523520db0342862b63Benjamin Tissoires{
415eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	__s32 quirks = td->mtclass.quirks;
4165519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
4172d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires	if (quirks & MT_QUIRK_SLOT_IS_CONTACTID)
4182d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires		return td->curdata.contactid;
4195519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
4202d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires	if (quirks & MT_QUIRK_CYPRESS)
421a3b5e577d96bfccbc41ebf4df784e3a153072273Benjamin Tissoires		return cypress_compute_slot(td);
422a3b5e577d96bfccbc41ebf4df784e3a153072273Benjamin Tissoires
4232d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires	if (quirks & MT_QUIRK_SLOT_IS_CONTACTNUMBER)
4242d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires		return td->num_received;
4255572da08a784621f2ab4fdc8dc65471261871795Benjamin Tissoires
4264a6ee685fbcba4a440cf86f41557752ba81e2ccfBenjamin Tissoires	if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE)
4274a6ee685fbcba4a440cf86f41557752ba81e2ccfBenjamin Tissoires		return td->curdata.contactid - 1;
4284a6ee685fbcba4a440cf86f41557752ba81e2ccfBenjamin Tissoires
4295519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	return find_slot_from_contactid(td);
4305519cab477b61326963c8d523520db0342862b63Benjamin Tissoires}
4315519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
4325519cab477b61326963c8d523520db0342862b63Benjamin Tissoires/*
4335519cab477b61326963c8d523520db0342862b63Benjamin Tissoires * this function is called when a whole contact has been processed,
4345519cab477b61326963c8d523520db0342862b63Benjamin Tissoires * so that it can assign it to a slot and store the data there
4355519cab477b61326963c8d523520db0342862b63Benjamin Tissoires */
4365519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresstatic void mt_complete_slot(struct mt_device *td)
4375519cab477b61326963c8d523520db0342862b63Benjamin Tissoires{
4382d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires	td->curdata.seen_in_this_frame = true;
4395519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	if (td->curvalid) {
4405519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		int slotnum = mt_compute_slot(td);
4415519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
4429498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires		if (slotnum >= 0 && slotnum < td->maxcontacts)
4432d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires			td->slots[slotnum] = td->curdata;
4445519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	}
4455519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	td->num_received++;
4465519cab477b61326963c8d523520db0342862b63Benjamin Tissoires}
4475519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
4485519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
4495519cab477b61326963c8d523520db0342862b63Benjamin Tissoires/*
4505519cab477b61326963c8d523520db0342862b63Benjamin Tissoires * this function is called when a whole packet has been received and processed,
4515519cab477b61326963c8d523520db0342862b63Benjamin Tissoires * so that it can decide what to send to the input layer.
4525519cab477b61326963c8d523520db0342862b63Benjamin Tissoires */
4535519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresstatic void mt_emit_event(struct mt_device *td, struct input_dev *input)
4545519cab477b61326963c8d523520db0342862b63Benjamin Tissoires{
4555519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	int i;
4565519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
4579498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires	for (i = 0; i < td->maxcontacts; ++i) {
4585519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		struct mt_slot *s = &(td->slots[i]);
459eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires		if ((td->mtclass.quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) &&
4605519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			!s->seen_in_this_frame) {
4615519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			s->touch_state = false;
4625519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		}
4635519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
4645519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		input_mt_slot(input, i);
4655519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		input_mt_report_slot_state(input, MT_TOOL_FINGER,
4665519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			s->touch_state);
4672d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires		if (s->touch_state) {
468f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires			/* this finger is on the screen */
469f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires			int wide = (s->w > s->h);
470f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires			/* divided by two to match visual scale of touch */
471f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires			int major = max(s->w, s->h) >> 1;
472f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires			int minor = min(s->w, s->h) >> 1;
473f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires
4742d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires			input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x);
4752d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires			input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y);
476f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires			input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
4772d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires			input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
478f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires			input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
479f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires			input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
4802d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires		}
4815519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		s->seen_in_this_frame = false;
4825519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
4835519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	}
4845519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
4855519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	input_mt_report_pointer_emulation(input, true);
4865519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	input_sync(input);
4875519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	td->num_received = 0;
4885519cab477b61326963c8d523520db0342862b63Benjamin Tissoires}
4895519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
4905519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
4915519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
4925519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresstatic int mt_event(struct hid_device *hid, struct hid_field *field,
4935519cab477b61326963c8d523520db0342862b63Benjamin Tissoires				struct hid_usage *usage, __s32 value)
4945519cab477b61326963c8d523520db0342862b63Benjamin Tissoires{
4955519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	struct mt_device *td = hid_get_drvdata(hid);
496eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	__s32 quirks = td->mtclass.quirks;
4975519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
4989498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires	if (hid->claimed & HID_CLAIMED_INPUT && td->slots) {
4995519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		switch (usage->hid) {
5005519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		case HID_DG_INRANGE:
501a062cc5a76fa1d12f0821e56e3746cad2dc2fc65Stephane Chatty			if (quirks & MT_QUIRK_ALWAYS_VALID)
502a062cc5a76fa1d12f0821e56e3746cad2dc2fc65Stephane Chatty				td->curvalid = true;
503a062cc5a76fa1d12f0821e56e3746cad2dc2fc65Stephane Chatty			else if (quirks & MT_QUIRK_VALID_IS_INRANGE)
5042d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires				td->curvalid = value;
5055519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			break;
5065519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		case HID_DG_TIPSWITCH:
5072d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires			if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
5082d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires				td->curvalid = value;
5095519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			td->curdata.touch_state = value;
5105519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			break;
5115519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		case HID_DG_CONFIDENCE:
5122d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires			if (quirks & MT_QUIRK_VALID_IS_CONFIDENCE)
5132d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires				td->curvalid = value;
5145519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			break;
5155519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		case HID_DG_CONTACTID:
5165519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			td->curdata.contactid = value;
5175519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			break;
5185519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		case HID_DG_TIPPRESSURE:
5195519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			td->curdata.p = value;
5205519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			break;
5215519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		case HID_GD_X:
5225519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			td->curdata.x = value;
5235519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			break;
5245519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		case HID_GD_Y:
5255519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			td->curdata.y = value;
5265519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			break;
5275519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		case HID_DG_WIDTH:
5285519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			td->curdata.w = value;
5295519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			break;
5305519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		case HID_DG_HEIGHT:
5315519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			td->curdata.h = value;
5325519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			break;
5335519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		case HID_DG_CONTACTCOUNT:
5345519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			/*
5352d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires			 * Includes multi-packet support where subsequent
5362d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires			 * packets are sent with zero contactcount.
5375519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			 */
5385519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			if (value)
5392d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires				td->num_expected = value;
5405519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			break;
5415519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
5425519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		default:
5435519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			/* fallback to the generic hidinput handling */
5445519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			return 0;
5455519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		}
5465519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
547f153fc3990d4ad2709a52d7150e2c04363afb1fbHenrik Rydberg		if (usage->hid == td->last_slot_field) {
5482d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires			mt_complete_slot(td);
549f153fc3990d4ad2709a52d7150e2c04363afb1fbHenrik Rydberg		}
5502d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires
5512d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires		if (field->index == td->last_field_index
5522d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires			&& td->num_received >= td->num_expected)
5532d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires			mt_emit_event(td, field->hidinput->input);
5545519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
5552d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires	}
5565519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
5575519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	/* we have handled the hidinput part, now remains hiddev */
5585519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
5595519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		hid->hiddev_hid_event(hid, field, usage, value);
5605519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
5615519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	return 1;
5625519cab477b61326963c8d523520db0342862b63Benjamin Tissoires}
5635519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
5645519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresstatic void mt_set_input_mode(struct hid_device *hdev)
5655519cab477b61326963c8d523520db0342862b63Benjamin Tissoires{
5665519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	struct mt_device *td = hid_get_drvdata(hdev);
5675519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	struct hid_report *r;
5685519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	struct hid_report_enum *re;
5695519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
5705519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	if (td->inputmode < 0)
5715519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		return;
5725519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
5735519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	re = &(hdev->report_enum[HID_FEATURE_REPORT]);
5745519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	r = re->report_id_hash[td->inputmode];
5755519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	if (r) {
5765519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		r->field[0]->value[0] = 0x02;
5775519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		usbhid_submit_report(hdev, r, USB_DIR_OUT);
5785519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	}
5795519cab477b61326963c8d523520db0342862b63Benjamin Tissoires}
5805519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
5815519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresstatic int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
5825519cab477b61326963c8d523520db0342862b63Benjamin Tissoires{
5832d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires	int ret, i;
5845519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	struct mt_device *td;
5852d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires	struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
5862d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires
5872d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires	for (i = 0; mt_classes[i].name ; i++) {
5882d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires		if (id->driver_data == mt_classes[i].name) {
5892d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires			mtclass = &(mt_classes[i]);
5902d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires			break;
5912d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires		}
5922d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires	}
5935519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
594d682bd7f38b73e5dff0b5584c8ec301ccf76e4dbHenrik Rydberg	/* This allows the driver to correctly support devices
595d682bd7f38b73e5dff0b5584c8ec301ccf76e4dbHenrik Rydberg	 * that emit events over several HID messages.
596d682bd7f38b73e5dff0b5584c8ec301ccf76e4dbHenrik Rydberg	 */
597d682bd7f38b73e5dff0b5584c8ec301ccf76e4dbHenrik Rydberg	hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
5985519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
5999498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires	td = kzalloc(sizeof(struct mt_device), GFP_KERNEL);
6005519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	if (!td) {
6015519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		dev_err(&hdev->dev, "cannot allocate multitouch data\n");
6025519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		return -ENOMEM;
6035519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	}
604eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	td->mtclass = *mtclass;
6055519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	td->inputmode = -1;
606b84bd27fe70206f9253c395958134e4e4b7e55f0Benjamin Tissoires	td->last_mt_collection = -1;
6075519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	hid_set_drvdata(hdev, td);
6085519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
6095519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	ret = hid_parse(hdev);
6105519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	if (ret != 0)
6115519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		goto fail;
6125519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
6135519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
6142d93666e70662cfcf1927e1a858685f5b38d5d65Benjamin Tissoires	if (ret)
6155519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		goto fail;
6165519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
6179498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires	td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot),
6189498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires				GFP_KERNEL);
6199498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires	if (!td->slots) {
6209498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires		dev_err(&hdev->dev, "cannot allocate multitouch slots\n");
6219498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires		hid_hw_stop(hdev);
6229498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires		ret = -ENOMEM;
6239498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires		goto fail;
6249498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires	}
6259498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires
626eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group);
627eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires
6285519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	mt_set_input_mode(hdev);
6295519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
6305519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	return 0;
6315519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
6325519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresfail:
6335519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	kfree(td);
6345519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	return ret;
6355519cab477b61326963c8d523520db0342862b63Benjamin Tissoires}
6365519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
6375519cab477b61326963c8d523520db0342862b63Benjamin Tissoires#ifdef CONFIG_PM
6385519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresstatic int mt_reset_resume(struct hid_device *hdev)
6395519cab477b61326963c8d523520db0342862b63Benjamin Tissoires{
6405519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	mt_set_input_mode(hdev);
6415519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	return 0;
6425519cab477b61326963c8d523520db0342862b63Benjamin Tissoires}
6435519cab477b61326963c8d523520db0342862b63Benjamin Tissoires#endif
6445519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
6455519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresstatic void mt_remove(struct hid_device *hdev)
6465519cab477b61326963c8d523520db0342862b63Benjamin Tissoires{
6475519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	struct mt_device *td = hid_get_drvdata(hdev);
648eec29e3dab483a5d9a742a6fa68db1ec1f0f7504Benjamin Tissoires	sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
6495519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	hid_hw_stop(hdev);
6509498f954a4ec389806333041a1018909c6fe0518Benjamin Tissoires	kfree(td->slots);
6515519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	kfree(td);
6525519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	hid_set_drvdata(hdev, NULL);
6535519cab477b61326963c8d523520db0342862b63Benjamin Tissoires}
6545519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
6555519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresstatic const struct hid_device_id mt_devices[] = {
6565519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
657f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires	/* 3M panels */
658f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires	{ .driver_data = MT_CLS_3M,
659f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_3M,
660f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires			USB_DEVICE_ID_3M1968) },
661f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires	{ .driver_data = MT_CLS_3M,
662f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_3M,
663f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires			USB_DEVICE_ID_3M2256) },
664f786bba4499cf3de20da345ce090457ebcef03b0Benjamin Tissoires
665e6aac3427ef03f61e7478514d0648b58359d05d1Benjamin Tissoires	/* ActionStar panels */
666e6aac3427ef03f61e7478514d0648b58359d05d1Benjamin Tissoires	{ .driver_data = MT_CLS_DEFAULT,
667e6aac3427ef03f61e7478514d0648b58359d05d1Benjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR,
668e6aac3427ef03f61e7478514d0648b58359d05d1Benjamin Tissoires			USB_DEVICE_ID_ACTIONSTAR_1011) },
669e6aac3427ef03f61e7478514d0648b58359d05d1Benjamin Tissoires
670b105712469d957cf1ab223c1ea72b7ba88edb926Benjamin Tissoires	/* Atmel panels */
671b105712469d957cf1ab223c1ea72b7ba88edb926Benjamin Tissoires	{ .driver_data = MT_CLS_SERIAL,
672b105712469d957cf1ab223c1ea72b7ba88edb926Benjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_ATMEL,
673b105712469d957cf1ab223c1ea72b7ba88edb926Benjamin Tissoires			USB_DEVICE_ID_ATMEL_MULTITOUCH) },
674b105712469d957cf1ab223c1ea72b7ba88edb926Benjamin Tissoires
675a841b62c5d5f75ce3676fde755696d30cc8de99aBenjamin Tissoires	/* Cando panels */
676a841b62c5d5f75ce3676fde755696d30cc8de99aBenjamin Tissoires	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
677a841b62c5d5f75ce3676fde755696d30cc8de99aBenjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
678a841b62c5d5f75ce3676fde755696d30cc8de99aBenjamin Tissoires			USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
679a841b62c5d5f75ce3676fde755696d30cc8de99aBenjamin Tissoires	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
680a841b62c5d5f75ce3676fde755696d30cc8de99aBenjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
681a841b62c5d5f75ce3676fde755696d30cc8de99aBenjamin Tissoires			USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) },
682a841b62c5d5f75ce3676fde755696d30cc8de99aBenjamin Tissoires	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
683a841b62c5d5f75ce3676fde755696d30cc8de99aBenjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
684a841b62c5d5f75ce3676fde755696d30cc8de99aBenjamin Tissoires			USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
685a841b62c5d5f75ce3676fde755696d30cc8de99aBenjamin Tissoires	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
686a841b62c5d5f75ce3676fde755696d30cc8de99aBenjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
687a841b62c5d5f75ce3676fde755696d30cc8de99aBenjamin Tissoires			USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
688a841b62c5d5f75ce3676fde755696d30cc8de99aBenjamin Tissoires
689942fd4225f72826b31d893582b6ae7e172bb3202Austin Zhang	/* Chunghwa Telecom touch panels */
690942fd4225f72826b31d893582b6ae7e172bb3202Austin Zhang	{  .driver_data = MT_CLS_DEFAULT,
691942fd4225f72826b31d893582b6ae7e172bb3202Austin Zhang		HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT,
692942fd4225f72826b31d893582b6ae7e172bb3202Austin Zhang			USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) },
693942fd4225f72826b31d893582b6ae7e172bb3202Austin Zhang
69479603dc9a8223856cf3194dcabad32b9828c7be9Benjamin Tissoires	/* CVTouch panels */
69579603dc9a8223856cf3194dcabad32b9828c7be9Benjamin Tissoires	{ .driver_data = MT_CLS_DEFAULT,
69679603dc9a8223856cf3194dcabad32b9828c7be9Benjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH,
69779603dc9a8223856cf3194dcabad32b9828c7be9Benjamin Tissoires			USB_DEVICE_ID_CVTOUCH_SCREEN) },
69879603dc9a8223856cf3194dcabad32b9828c7be9Benjamin Tissoires
699a3b5e577d96bfccbc41ebf4df784e3a153072273Benjamin Tissoires	/* Cypress panel */
700a3b5e577d96bfccbc41ebf4df784e3a153072273Benjamin Tissoires	{ .driver_data = MT_CLS_CYPRESS,
701a3b5e577d96bfccbc41ebf4df784e3a153072273Benjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS,
702a3b5e577d96bfccbc41ebf4df784e3a153072273Benjamin Tissoires			USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
703a3b5e577d96bfccbc41ebf4df784e3a153072273Benjamin Tissoires
70422408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires	/* eGalax devices (resistive) */
705e36f690b37945e0a9bb1554e1546eeec93f7d1f6Benjamin Tissoires	{ .driver_data = MT_CLS_EGALAX,
70622408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
707e36f690b37945e0a9bb1554e1546eeec93f7d1f6Benjamin Tissoires			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D) },
708e36f690b37945e0a9bb1554e1546eeec93f7d1f6Benjamin Tissoires	{ .driver_data = MT_CLS_EGALAX,
70922408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
710e36f690b37945e0a9bb1554e1546eeec93f7d1f6Benjamin Tissoires			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E) },
71122408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires
71222408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires	/* eGalax devices (capacitive) */
713e36f690b37945e0a9bb1554e1546eeec93f7d1f6Benjamin Tissoires	{ .driver_data = MT_CLS_EGALAX,
71422408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
715e36f690b37945e0a9bb1554e1546eeec93f7d1f6Benjamin Tissoires			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C) },
716e36f690b37945e0a9bb1554e1546eeec93f7d1f6Benjamin Tissoires	{ .driver_data = MT_CLS_EGALAX,
71722408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
718e36f690b37945e0a9bb1554e1546eeec93f7d1f6Benjamin Tissoires			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B) },
719e36f690b37945e0a9bb1554e1546eeec93f7d1f6Benjamin Tissoires	{ .driver_data = MT_CLS_EGALAX,
72022408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
721e36f690b37945e0a9bb1554e1546eeec93f7d1f6Benjamin Tissoires			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1) },
722e36f690b37945e0a9bb1554e1546eeec93f7d1f6Benjamin Tissoires	{ .driver_data = MT_CLS_EGALAX,
7231fd8f047490dd0ec4e4db710fcbc1bd4798d944cChris Bagwell		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
72466f06127f34ad6e8a1b24a2c03144b694d19f99fBenjamin Tissoires			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA) },
72566f06127f34ad6e8a1b24a2c03144b694d19f99fBenjamin Tissoires	{ .driver_data = MT_CLS_EGALAX,
72666f06127f34ad6e8a1b24a2c03144b694d19f99fBenjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
727bb9ff21072043634f147c05ac65dbf8185d4af6dMarek Vasut			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302) },
7281b723e8dc81b23141bfb8991e002073b17fd0199Benjamin Tissoires	{ .driver_data = MT_CLS_EGALAX_SERIAL,
729bb9ff21072043634f147c05ac65dbf8185d4af6dMarek Vasut		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
730e36f690b37945e0a9bb1554e1546eeec93f7d1f6Benjamin Tissoires			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) },
73122408283bca57780bdd53da5a6e4474b71b94430Benjamin Tissoires
732c04abeeff9d76a703cac1e6d312853b0fc8136f5Benjamin Tissoires	/* Elo TouchSystems IntelliTouch Plus panel */
733c04abeeff9d76a703cac1e6d312853b0fc8136f5Benjamin Tissoires	{ .driver_data = MT_CLS_DUAL_NSMU_CONTACTID,
734c04abeeff9d76a703cac1e6d312853b0fc8136f5Benjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_ELO,
735c04abeeff9d76a703cac1e6d312853b0fc8136f5Benjamin Tissoires			USB_DEVICE_ID_ELO_TS2515) },
736c04abeeff9d76a703cac1e6d312853b0fc8136f5Benjamin Tissoires
7375572da08a784621f2ab4fdc8dc65471261871795Benjamin Tissoires	/* GeneralTouch panel */
7381e9cf35b995610e7ba2934d3dc92e3a03fa361a1Benjamin Tissoires	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
7395572da08a784621f2ab4fdc8dc65471261871795Benjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
7405572da08a784621f2ab4fdc8dc65471261871795Benjamin Tissoires			USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
7415572da08a784621f2ab4fdc8dc65471261871795Benjamin Tissoires
742ee0fbd149182d91e3b9df7b306eb03cd1f1dd4a1Benjamin Tissoires	/* GoodTouch panels */
743ee0fbd149182d91e3b9df7b306eb03cd1f1dd4a1Benjamin Tissoires	{ .driver_data = MT_CLS_DEFAULT,
744ee0fbd149182d91e3b9df7b306eb03cd1f1dd4a1Benjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH,
745ee0fbd149182d91e3b9df7b306eb03cd1f1dd4a1Benjamin Tissoires			USB_DEVICE_ID_GOODTOUCH_000f) },
746ee0fbd149182d91e3b9df7b306eb03cd1f1dd4a1Benjamin Tissoires
747545803651da8dde248eeb8ce3ed1e547e9e4ac0aBenjamin Tissoires	/* Hanvon panels */
748545803651da8dde248eeb8ce3ed1e547e9e4ac0aBenjamin Tissoires	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
749545803651da8dde248eeb8ce3ed1e547e9e4ac0aBenjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT,
750545803651da8dde248eeb8ce3ed1e547e9e4ac0aBenjamin Tissoires			USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) },
751545803651da8dde248eeb8ce3ed1e547e9e4ac0aBenjamin Tissoires
752a062cc5a76fa1d12f0821e56e3746cad2dc2fc65Stephane Chatty	/* Ideacom panel */
753a062cc5a76fa1d12f0821e56e3746cad2dc2fc65Stephane Chatty	{ .driver_data = MT_CLS_SERIAL,
754a062cc5a76fa1d12f0821e56e3746cad2dc2fc65Stephane Chatty		HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM,
755a062cc5a76fa1d12f0821e56e3746cad2dc2fc65Stephane Chatty			USB_DEVICE_ID_IDEACOM_IDC6650) },
756a062cc5a76fa1d12f0821e56e3746cad2dc2fc65Stephane Chatty
7574e61f0d75aa86c9e59451f6bcffcdceb355b4fc4Austin Zhang	/* Ilitek dual touch panel */
7584e61f0d75aa86c9e59451f6bcffcdceb355b4fc4Austin Zhang	{  .driver_data = MT_CLS_DEFAULT,
7594e61f0d75aa86c9e59451f6bcffcdceb355b4fc4Austin Zhang		HID_USB_DEVICE(USB_VENDOR_ID_ILITEK,
7604e61f0d75aa86c9e59451f6bcffcdceb355b4fc4Austin Zhang			USB_DEVICE_ID_ILITEK_MULTITOUCH) },
7614e61f0d75aa86c9e59451f6bcffcdceb355b4fc4Austin Zhang
7624dfcced8a1f42248f9e7a461485f6aa5f66d2105Benjamin Tissoires	/* IRTOUCH panels */
7634dfcced8a1f42248f9e7a461485f6aa5f66d2105Benjamin Tissoires	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
7644dfcced8a1f42248f9e7a461485f6aa5f66d2105Benjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS,
7654dfcced8a1f42248f9e7a461485f6aa5f66d2105Benjamin Tissoires			USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
7664dfcced8a1f42248f9e7a461485f6aa5f66d2105Benjamin Tissoires
767c50bb1a4005630f47b5da26336f74a485033a515Jeff Brown	/* LG Display panels */
768c50bb1a4005630f47b5da26336f74a485033a515Jeff Brown	{ .driver_data = MT_CLS_DEFAULT,
769c50bb1a4005630f47b5da26336f74a485033a515Jeff Brown		HID_USB_DEVICE(USB_VENDOR_ID_LG,
770c50bb1a4005630f47b5da26336f74a485033a515Jeff Brown			USB_DEVICE_ID_LG_MULTITOUCH) },
771c50bb1a4005630f47b5da26336f74a485033a515Jeff Brown
772df167c4a0d68a9dbde044a39a77f255ac666f93eBenjamin Tissoires	/* Lumio panels */
773df167c4a0d68a9dbde044a39a77f255ac666f93eBenjamin Tissoires	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
774df167c4a0d68a9dbde044a39a77f255ac666f93eBenjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_LUMIO,
775df167c4a0d68a9dbde044a39a77f255ac666f93eBenjamin Tissoires			USB_DEVICE_ID_CRYSTALTOUCH) },
776c3ead6de4f6bd1c08a81f84e629e3dbf4a9078f0Benjamin Tissoires	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
777c3ead6de4f6bd1c08a81f84e629e3dbf4a9078f0Benjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_LUMIO,
778c3ead6de4f6bd1c08a81f84e629e3dbf4a9078f0Benjamin Tissoires			USB_DEVICE_ID_CRYSTALTOUCH_DUAL) },
779df167c4a0d68a9dbde044a39a77f255ac666f93eBenjamin Tissoires
7804a6ee685fbcba4a440cf86f41557752ba81e2ccfBenjamin Tissoires	/* MosArt panels */
7814a6ee685fbcba4a440cf86f41557752ba81e2ccfBenjamin Tissoires	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
7824a6ee685fbcba4a440cf86f41557752ba81e2ccfBenjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_ASUS,
7834a6ee685fbcba4a440cf86f41557752ba81e2ccfBenjamin Tissoires			USB_DEVICE_ID_ASUS_T91MT)},
7844a6ee685fbcba4a440cf86f41557752ba81e2ccfBenjamin Tissoires	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
7854a6ee685fbcba4a440cf86f41557752ba81e2ccfBenjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_ASUS,
7864a6ee685fbcba4a440cf86f41557752ba81e2ccfBenjamin Tissoires			USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) },
7874a6ee685fbcba4a440cf86f41557752ba81e2ccfBenjamin Tissoires	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
7884a6ee685fbcba4a440cf86f41557752ba81e2ccfBenjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_TURBOX,
7894a6ee685fbcba4a440cf86f41557752ba81e2ccfBenjamin Tissoires			USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) },
7904a6ee685fbcba4a440cf86f41557752ba81e2ccfBenjamin Tissoires
7916ab3a9a63fc16b04f7de48eb0190d516dd7574dfJohn Sung	/* PenMount panels */
7926ab3a9a63fc16b04f7de48eb0190d516dd7574dfJohn Sung	{ .driver_data = MT_CLS_CONFIDENCE,
7936ab3a9a63fc16b04f7de48eb0190d516dd7574dfJohn Sung		HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT,
7946ab3a9a63fc16b04f7de48eb0190d516dd7574dfJohn Sung			USB_DEVICE_ID_PENMOUNT_PCI) },
7956ab3a9a63fc16b04f7de48eb0190d516dd7574dfJohn Sung
796b7ea95ff9baab144dacdc30d752307938c5ab6bfAaron Tian	/* PixArt optical touch screen */
797b7ea95ff9baab144dacdc30d752307938c5ab6bfAaron Tian	{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
798b7ea95ff9baab144dacdc30d752307938c5ab6bfAaron Tian		HID_USB_DEVICE(USB_VENDOR_ID_PIXART,
799b7ea95ff9baab144dacdc30d752307938c5ab6bfAaron Tian			USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN) },
800b7ea95ff9baab144dacdc30d752307938c5ab6bfAaron Tian	{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
801b7ea95ff9baab144dacdc30d752307938c5ab6bfAaron Tian		HID_USB_DEVICE(USB_VENDOR_ID_PIXART,
802b7ea95ff9baab144dacdc30d752307938c5ab6bfAaron Tian			USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1) },
803b7ea95ff9baab144dacdc30d752307938c5ab6bfAaron Tian	{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
804b7ea95ff9baab144dacdc30d752307938c5ab6bfAaron Tian		HID_USB_DEVICE(USB_VENDOR_ID_PIXART,
805b7ea95ff9baab144dacdc30d752307938c5ab6bfAaron Tian			USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2) },
806b7ea95ff9baab144dacdc30d752307938c5ab6bfAaron Tian
8075519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	/* PixCir-based panels */
8081e9cf35b995610e7ba2934d3dc92e3a03fa361a1Benjamin Tissoires	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
8095519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_HANVON,
8105519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			USB_DEVICE_ID_HANVON_MULTITOUCH) },
8111e9cf35b995610e7ba2934d3dc92e3a03fa361a1Benjamin Tissoires	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
8125519cab477b61326963c8d523520db0342862b63Benjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
8135519cab477b61326963c8d523520db0342862b63Benjamin Tissoires			USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
8145519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
8155e7ea11f603a0aeb77fd1bff0b242931ffe139deBenjamin Tissoires	/* Quanta-based panels */
8165e7ea11f603a0aeb77fd1bff0b242931ffe139deBenjamin Tissoires	{ .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID,
8175e7ea11f603a0aeb77fd1bff0b242931ffe139deBenjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_QUANTA,
8185e7ea11f603a0aeb77fd1bff0b242931ffe139deBenjamin Tissoires			USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
8195e7ea11f603a0aeb77fd1bff0b242931ffe139deBenjamin Tissoires	{ .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID,
8205e7ea11f603a0aeb77fd1bff0b242931ffe139deBenjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_QUANTA,
8215e7ea11f603a0aeb77fd1bff0b242931ffe139deBenjamin Tissoires			USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001) },
8225e7ea11f603a0aeb77fd1bff0b242931ffe139deBenjamin Tissoires	{ .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID,
8235e7ea11f603a0aeb77fd1bff0b242931ffe139deBenjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_QUANTA,
8245e7ea11f603a0aeb77fd1bff0b242931ffe139deBenjamin Tissoires			USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008) },
8255e7ea11f603a0aeb77fd1bff0b242931ffe139deBenjamin Tissoires
826043b403aede4a528ed99ceaf050f567f1283a23eBenjamin Tissoires	/* Stantum panels */
827bf5af9b5bba2453ff46f241e8f2e139ca79302e7Benjamin Tissoires	{ .driver_data = MT_CLS_CONFIDENCE,
828043b403aede4a528ed99ceaf050f567f1283a23eBenjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_STANTUM,
829043b403aede4a528ed99ceaf050f567f1283a23eBenjamin Tissoires			USB_DEVICE_ID_MTP)},
830bf5af9b5bba2453ff46f241e8f2e139ca79302e7Benjamin Tissoires	{ .driver_data = MT_CLS_CONFIDENCE,
83185a600825b425d52e466c6093dcdfeba85eb0044Benjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM,
832043b403aede4a528ed99ceaf050f567f1283a23eBenjamin Tissoires			USB_DEVICE_ID_MTP_STM)},
833bf5af9b5bba2453ff46f241e8f2e139ca79302e7Benjamin Tissoires	{ .driver_data = MT_CLS_CONFIDENCE,
83485a600825b425d52e466c6093dcdfeba85eb0044Benjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX,
835043b403aede4a528ed99ceaf050f567f1283a23eBenjamin Tissoires			USB_DEVICE_ID_MTP_SITRONIX)},
836043b403aede4a528ed99ceaf050f567f1283a23eBenjamin Tissoires
8375e74e56da03f581482c104628951eeb1455848eaBenjamin Tissoires	/* Touch International panels */
8385e74e56da03f581482c104628951eeb1455848eaBenjamin Tissoires	{ .driver_data = MT_CLS_DEFAULT,
8395e74e56da03f581482c104628951eeb1455848eaBenjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_TOUCH_INTL,
8405e74e56da03f581482c104628951eeb1455848eaBenjamin Tissoires			USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH) },
8415e74e56da03f581482c104628951eeb1455848eaBenjamin Tissoires
842617b64f97708be26a061e6c8178ad46b4c49d031Benjamin Tissoires	/* Unitec panels */
843617b64f97708be26a061e6c8178ad46b4c49d031Benjamin Tissoires	{ .driver_data = MT_CLS_DEFAULT,
844617b64f97708be26a061e6c8178ad46b4c49d031Benjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_UNITEC,
845617b64f97708be26a061e6c8178ad46b4c49d031Benjamin Tissoires			USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) },
846617b64f97708be26a061e6c8178ad46b4c49d031Benjamin Tissoires	{ .driver_data = MT_CLS_DEFAULT,
847617b64f97708be26a061e6c8178ad46b4c49d031Benjamin Tissoires		HID_USB_DEVICE(USB_VENDOR_ID_UNITEC,
848617b64f97708be26a061e6c8178ad46b4c49d031Benjamin Tissoires			USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
849bc8a2a9b4e5c418bebaa6bb812982b7ecd298821ice chien	/* XAT */
850bc8a2a9b4e5c418bebaa6bb812982b7ecd298821ice chien	{ .driver_data = MT_CLS_DEFAULT,
851bc8a2a9b4e5c418bebaa6bb812982b7ecd298821ice chien		HID_USB_DEVICE(USB_VENDOR_ID_XAT,
852bc8a2a9b4e5c418bebaa6bb812982b7ecd298821ice chien			USB_DEVICE_ID_XAT_CSR) },
853617b64f97708be26a061e6c8178ad46b4c49d031Benjamin Tissoires
8545519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	{ }
8555519cab477b61326963c8d523520db0342862b63Benjamin Tissoires};
8565519cab477b61326963c8d523520db0342862b63Benjamin TissoiresMODULE_DEVICE_TABLE(hid, mt_devices);
8575519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
8585519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresstatic const struct hid_usage_id mt_grabbed_usages[] = {
8595519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
8605519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
8615519cab477b61326963c8d523520db0342862b63Benjamin Tissoires};
8625519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
8635519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresstatic struct hid_driver mt_driver = {
8645519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	.name = "hid-multitouch",
8655519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	.id_table = mt_devices,
8665519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	.probe = mt_probe,
8675519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	.remove = mt_remove,
8685519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	.input_mapping = mt_input_mapping,
8695519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	.input_mapped = mt_input_mapped,
8705519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	.feature_mapping = mt_feature_mapping,
8715519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	.usage_table = mt_grabbed_usages,
8725519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	.event = mt_event,
8735519cab477b61326963c8d523520db0342862b63Benjamin Tissoires#ifdef CONFIG_PM
8745519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	.reset_resume = mt_reset_resume,
8755519cab477b61326963c8d523520db0342862b63Benjamin Tissoires#endif
8765519cab477b61326963c8d523520db0342862b63Benjamin Tissoires};
8775519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
8785519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresstatic int __init mt_init(void)
8795519cab477b61326963c8d523520db0342862b63Benjamin Tissoires{
8805519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	return hid_register_driver(&mt_driver);
8815519cab477b61326963c8d523520db0342862b63Benjamin Tissoires}
8825519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
8835519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresstatic void __exit mt_exit(void)
8845519cab477b61326963c8d523520db0342862b63Benjamin Tissoires{
8855519cab477b61326963c8d523520db0342862b63Benjamin Tissoires	hid_unregister_driver(&mt_driver);
8865519cab477b61326963c8d523520db0342862b63Benjamin Tissoires}
8875519cab477b61326963c8d523520db0342862b63Benjamin Tissoires
8885519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresmodule_init(mt_init);
8895519cab477b61326963c8d523520db0342862b63Benjamin Tissoiresmodule_exit(mt_exit);
890