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