2011-01-08 01:45:50 +03:00
/*
* HID driver for multitouch panels
*
2012-02-04 20:08:48 +04:00
* Copyright ( c ) 2010 - 2012 Stephane Chatty < chatty @ enac . fr >
2013-02-25 14:31:49 +04:00
* Copyright ( c ) 2010 - 2013 Benjamin Tissoires < benjamin . tissoires @ gmail . com >
2012-02-04 20:08:48 +04:00
* Copyright ( c ) 2010 - 2012 Ecole Nationale de l ' Aviation Civile , France
2013-02-25 14:31:49 +04:00
* Copyright ( c ) 2012 - 2013 Red Hat , Inc
2011-01-08 01:45:50 +03:00
*
2011-03-09 08:20:57 +03:00
* This code is partly based on hid - egalax . c :
*
* Copyright ( c ) 2010 Stephane Chatty < chatty @ enac . fr >
* Copyright ( c ) 2010 Henrik Rydberg < rydberg @ euromail . se >
* Copyright ( c ) 2010 Canonical , Ltd .
*
2011-03-22 19:34:01 +03:00
* This code is partly based on hid - 3 m - pct . c :
*
* Copyright ( c ) 2009 - 2010 Stephane Chatty < chatty @ enac . fr >
* Copyright ( c ) 2010 Henrik Rydberg < rydberg @ euromail . se >
* Copyright ( c ) 2010 Canonical , Ltd .
*
2011-01-08 01:45:50 +03:00
*/
/*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation ; either version 2 of the License , or ( at your option )
* any later version .
*/
2013-02-25 14:31:49 +04:00
/*
* This driver is regularly tested thanks to the tool hid - test [ 1 ] .
* This tool relies on hid - replay [ 2 ] and a database of hid devices [ 3 ] .
* Please run these regression tests before patching this module so that
* your patch won ' t break existing known devices .
*
* [ 1 ] https : //github.com/bentiss/hid-test
* [ 2 ] https : //github.com/bentiss/hid-replay
* [ 3 ] https : //github.com/bentiss/hid-devices
*/
2011-01-08 01:45:50 +03:00
# include <linux/device.h>
# include <linux/hid.h>
# include <linux/module.h>
# include <linux/slab.h>
# include <linux/usb.h>
# include <linux/input/mt.h>
MODULE_AUTHOR ( " Stephane Chatty <chatty@enac.fr> " ) ;
2011-01-31 13:28:21 +03:00
MODULE_AUTHOR ( " Benjamin Tissoires <benjamin.tissoires@gmail.com> " ) ;
2011-01-08 01:45:50 +03:00
MODULE_DESCRIPTION ( " HID multitouch panels " ) ;
MODULE_LICENSE ( " GPL " ) ;
# include "hid-ids.h"
/* quirks to control the device */
# define MT_QUIRK_NOT_SEEN_MEANS_UP (1 << 0)
# define MT_QUIRK_SLOT_IS_CONTACTID (1 << 1)
2011-01-11 18:45:54 +03:00
# define MT_QUIRK_CYPRESS (1 << 2)
2011-01-08 01:47:27 +03:00
# define MT_QUIRK_SLOT_IS_CONTACTNUMBER (1 << 3)
2011-09-18 00:27:30 +04:00
# define MT_QUIRK_ALWAYS_VALID (1 << 4)
# define MT_QUIRK_VALID_IS_INRANGE (1 << 5)
# define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 6)
# define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 8)
2012-09-07 21:37:40 +04:00
# define MT_QUIRK_NO_AREA (1 << 9)
2012-11-14 19:59:23 +04:00
# define MT_QUIRK_IGNORE_DUPLICATES (1 << 10)
2012-11-14 19:59:24 +04:00
# define MT_QUIRK_HOVERING (1 << 11)
2013-01-31 20:22:25 +04:00
# define MT_QUIRK_CONTACT_CNT_ACCURATE (1 << 12)
2011-01-08 01:45:50 +03:00
struct mt_slot {
2012-11-14 19:59:19 +04:00
__s32 x , y , cx , cy , p , w , h ;
2011-01-08 01:45:50 +03:00
__s32 contactid ; /* the device ContactID assigned to this slot */
bool touch_state ; /* is the touch valid? */
2012-11-14 19:59:24 +04:00
bool inrange_state ; /* is the finger in proximity of the sensor? */
2011-01-08 01:45:50 +03:00
} ;
2011-11-23 13:54:28 +04:00
struct mt_class {
__s32 name ; /* MT_CLS */
__s32 quirks ;
__s32 sn_move ; /* Signal/noise ratio for move events */
__s32 sn_width ; /* Signal/noise ratio for width events */
__s32 sn_height ; /* Signal/noise ratio for height events */
__s32 sn_pressure ; /* Signal/noise ratio for pressure events */
__u8 maxcontacts ;
2012-02-04 20:08:48 +04:00
bool is_indirect ; /* true for touchpads */
2011-11-23 13:54:28 +04:00
} ;
2012-05-04 16:53:46 +04:00
struct mt_fields {
unsigned usages [ HID_MAX_FIELDS ] ;
unsigned int length ;
} ;
2011-01-08 01:45:50 +03:00
struct mt_device {
struct mt_slot curdata ; /* placeholder of incoming data */
2011-11-23 13:54:28 +04:00
struct mt_class mtclass ; /* our mt device class */
2012-05-04 16:53:46 +04:00
struct mt_fields * fields ; /* temporary placeholder for storing the
multitouch fields */
2013-02-06 15:10:47 +04:00
int cc_index ; /* contact count field index in the report */
int cc_value_index ; /* contact count value index in the field */
2011-01-08 01:45:50 +03:00
unsigned last_slot_field ; /* the last field of a slot */
2013-01-31 20:22:24 +04:00
unsigned mt_report_id ; /* the report ID of the multitouch device */
2013-03-22 21:38:32 +04:00
unsigned pen_report_id ; /* the report ID of the pen device */
2011-01-08 01:45:50 +03:00
__s8 inputmode ; /* InputMode HID feature, -1 if non-existent */
2012-06-19 16:39:52 +04:00
__s8 inputmode_index ; /* InputMode HID feature index in the report */
2012-02-04 20:08:49 +04:00
__s8 maxcontact_report_id ; /* Maximum Contact Number HID feature,
- 1 if non - existent */
2011-01-08 01:45:50 +03:00
__u8 num_received ; /* how many contacts we received */
__u8 num_expected ; /* expected last contact index */
2011-03-18 16:27:52 +03:00
__u8 maxcontacts ;
2012-03-06 20:57:06 +04:00
__u8 touches_by_report ; /* how many touches are present in one report:
* 1 means we should use a serial protocol
* > 1 means hybrid ( multitouch ) protocol */
2012-09-01 22:11:34 +04:00
bool serial_maybe ; /* need to check for serial protocol */
2011-01-08 01:45:50 +03:00
bool curvalid ; /* is the current contact valid? */
2012-09-01 22:11:34 +04:00
unsigned mt_flags ; /* flags to pass to input-mt */
2011-01-08 01:45:50 +03:00
} ;
2013-03-22 21:38:29 +04:00
static void mt_post_parse_default_settings ( struct mt_device * td ) ;
static void mt_post_parse ( struct mt_device * td ) ;
2011-01-08 01:45:50 +03:00
/* classes of device behavior */
2011-05-20 17:59:34 +04:00
# define MT_CLS_DEFAULT 0x0001
2011-09-18 00:27:30 +04:00
# define MT_CLS_SERIAL 0x0002
# define MT_CLS_CONFIDENCE 0x0003
2011-11-29 16:13:10 +04:00
# define MT_CLS_CONFIDENCE_CONTACT_ID 0x0004
# define MT_CLS_CONFIDENCE_MINUS_ONE 0x0005
# define MT_CLS_DUAL_INRANGE_CONTACTID 0x0006
# define MT_CLS_DUAL_INRANGE_CONTACTNUMBER 0x0007
# define MT_CLS_DUAL_NSMU_CONTACTID 0x0008
2011-12-15 07:09:06 +04:00
# define MT_CLS_INRANGE_CONTACTNUMBER 0x0009
2013-01-31 20:22:31 +04:00
# define MT_CLS_NSMU 0x000a
2013-01-31 20:22:29 +04:00
# define MT_CLS_DUAL_CONTACT_NUMBER 0x0010
2013-01-31 20:22:30 +04:00
# define MT_CLS_DUAL_CONTACT_ID 0x0011
2011-05-20 17:59:34 +04:00
/* vendor specific classes */
# define MT_CLS_3M 0x0101
# define MT_CLS_CYPRESS 0x0102
# define MT_CLS_EGALAX 0x0103
2011-11-23 13:54:34 +04:00
# define MT_CLS_EGALAX_SERIAL 0x0104
2012-02-04 20:08:50 +04:00
# define MT_CLS_TOPSEED 0x0105
2012-02-14 12:50:33 +04:00
# define MT_CLS_PANASONIC 0x0106
2012-09-07 21:37:40 +04:00
# define MT_CLS_FLATFROG 0x0107
2012-10-01 16:38:54 +04:00
# define MT_CLS_GENERALTOUCH_TWOFINGERS 0x0108
# define MT_CLS_GENERALTOUCH_PWT_TENFINGERS 0x0109
2011-01-08 01:45:50 +03:00
2011-03-18 16:27:52 +03:00
# define MT_DEFAULT_MAXCONTACT 10
2012-11-14 19:59:18 +04:00
# define MT_MAX_MAXCONTACT 250
2011-03-18 16:27:52 +03:00
2012-05-04 17:32:04 +04:00
# define MT_USB_DEVICE(v, p) HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH, v, p)
# define MT_BT_DEVICE(v, p) HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_MULTITOUCH, v, p)
2011-01-08 01:45:50 +03:00
/*
* these device - dependent functions determine what slot corresponds
* to a valid contact that was just read .
*/
2011-01-08 01:46:30 +03:00
static int cypress_compute_slot ( struct mt_device * td )
{
if ( td - > curdata . contactid ! = 0 | | td - > num_received = = 0 )
return td - > curdata . contactid ;
else
return - 1 ;
}
2011-11-23 02:23:37 +04:00
static struct mt_class mt_classes [ ] = {
2011-01-11 18:45:54 +03:00
{ . name = MT_CLS_DEFAULT ,
2013-01-31 20:22:31 +04:00
. quirks = MT_QUIRK_ALWAYS_VALID |
MT_QUIRK_CONTACT_CNT_ACCURATE } ,
{ . name = MT_CLS_NSMU ,
2011-03-18 16:27:52 +03:00
. quirks = MT_QUIRK_NOT_SEEN_MEANS_UP } ,
2011-09-18 00:27:30 +04:00
{ . name = MT_CLS_SERIAL ,
. quirks = MT_QUIRK_ALWAYS_VALID } ,
2011-05-20 17:59:34 +04:00
{ . name = MT_CLS_CONFIDENCE ,
. quirks = MT_QUIRK_VALID_IS_CONFIDENCE } ,
2011-11-29 16:13:10 +04:00
{ . name = MT_CLS_CONFIDENCE_CONTACT_ID ,
. quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
MT_QUIRK_SLOT_IS_CONTACTID } ,
2011-05-20 17:59:34 +04:00
{ . name = MT_CLS_CONFIDENCE_MINUS_ONE ,
. quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE } ,
2011-01-31 13:28:20 +03:00
{ . name = MT_CLS_DUAL_INRANGE_CONTACTID ,
2011-01-11 18:45:54 +03:00
. quirks = MT_QUIRK_VALID_IS_INRANGE |
MT_QUIRK_SLOT_IS_CONTACTID ,
. maxcontacts = 2 } ,
2011-01-31 13:28:20 +03:00
{ . name = MT_CLS_DUAL_INRANGE_CONTACTNUMBER ,
2011-01-11 18:45:54 +03:00
. quirks = MT_QUIRK_VALID_IS_INRANGE |
MT_QUIRK_SLOT_IS_CONTACTNUMBER ,
. maxcontacts = 2 } ,
2011-05-20 17:59:34 +04:00
{ . name = MT_CLS_DUAL_NSMU_CONTACTID ,
. quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
MT_QUIRK_SLOT_IS_CONTACTID ,
. maxcontacts = 2 } ,
2011-12-15 07:09:06 +04:00
{ . name = MT_CLS_INRANGE_CONTACTNUMBER ,
. quirks = MT_QUIRK_VALID_IS_INRANGE |
MT_QUIRK_SLOT_IS_CONTACTNUMBER } ,
2013-01-31 20:22:29 +04:00
{ . name = MT_CLS_DUAL_CONTACT_NUMBER ,
. quirks = MT_QUIRK_ALWAYS_VALID |
MT_QUIRK_CONTACT_CNT_ACCURATE |
MT_QUIRK_SLOT_IS_CONTACTNUMBER ,
. maxcontacts = 2 } ,
2013-01-31 20:22:30 +04:00
{ . name = MT_CLS_DUAL_CONTACT_ID ,
. quirks = MT_QUIRK_ALWAYS_VALID |
MT_QUIRK_CONTACT_CNT_ACCURATE |
MT_QUIRK_SLOT_IS_CONTACTID ,
. maxcontacts = 2 } ,
2011-05-20 17:59:34 +04:00
/*
* vendor specific classes
*/
{ . name = MT_CLS_3M ,
. quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
MT_QUIRK_SLOT_IS_CONTACTID ,
. sn_move = 2048 ,
. sn_width = 128 ,
2012-09-05 18:58:12 +04:00
. sn_height = 128 ,
. maxcontacts = 60 ,
} ,
2011-01-11 18:45:54 +03:00
{ . name = MT_CLS_CYPRESS ,
. quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
MT_QUIRK_CYPRESS ,
. maxcontacts = 10 } ,
2011-03-09 08:20:57 +03:00
{ . name = MT_CLS_EGALAX ,
. quirks = MT_QUIRK_SLOT_IS_CONTACTID |
2011-11-23 13:54:29 +04:00
MT_QUIRK_VALID_IS_INRANGE ,
2011-03-09 08:20:57 +03:00
. sn_move = 4096 ,
. sn_pressure = 32 ,
} ,
2011-11-23 13:54:34 +04:00
{ . name = MT_CLS_EGALAX_SERIAL ,
. quirks = MT_QUIRK_SLOT_IS_CONTACTID |
MT_QUIRK_ALWAYS_VALID ,
2011-03-09 08:20:57 +03:00
. sn_move = 4096 ,
. sn_pressure = 32 ,
} ,
2012-02-04 20:08:50 +04:00
{ . name = MT_CLS_TOPSEED ,
. quirks = MT_QUIRK_ALWAYS_VALID ,
. is_indirect = true ,
. maxcontacts = 2 ,
} ,
2012-02-14 12:50:33 +04:00
{ . name = MT_CLS_PANASONIC ,
. quirks = MT_QUIRK_NOT_SEEN_MEANS_UP ,
. maxcontacts = 4 } ,
2012-09-28 06:18:59 +04:00
{ . name = MT_CLS_GENERALTOUCH_TWOFINGERS ,
. quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
MT_QUIRK_VALID_IS_INRANGE |
MT_QUIRK_SLOT_IS_CONTACTNUMBER ,
. maxcontacts = 2
} ,
{ . name = MT_CLS_GENERALTOUCH_PWT_TENFINGERS ,
. quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
2012-10-29 19:04:37 +04:00
MT_QUIRK_SLOT_IS_CONTACTNUMBER
2012-09-28 06:18:59 +04:00
} ,
2011-03-18 16:27:53 +03:00
2012-09-07 21:37:40 +04:00
{ . name = MT_CLS_FLATFROG ,
. quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
MT_QUIRK_NO_AREA ,
. sn_move = 2048 ,
. maxcontacts = 40 ,
} ,
2011-01-11 18:45:54 +03:00
{ }
2011-01-08 01:45:50 +03:00
} ;
2011-11-23 13:54:28 +04:00
static ssize_t mt_show_quirks ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
{
struct hid_device * hdev = container_of ( dev , struct hid_device , dev ) ;
struct mt_device * td = hid_get_drvdata ( hdev ) ;
return sprintf ( buf , " %u \n " , td - > mtclass . quirks ) ;
}
static ssize_t mt_set_quirks ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t count )
{
struct hid_device * hdev = container_of ( dev , struct hid_device , dev ) ;
struct mt_device * td = hid_get_drvdata ( hdev ) ;
unsigned long val ;
if ( kstrtoul ( buf , 0 , & val ) )
return - EINVAL ;
td - > mtclass . quirks = val ;
2013-02-06 15:10:47 +04:00
if ( td - > cc_index < 0 )
2013-01-31 20:22:25 +04:00
td - > mtclass . quirks & = ~ MT_QUIRK_CONTACT_CNT_ACCURATE ;
2011-11-23 13:54:28 +04:00
return count ;
}
static DEVICE_ATTR ( quirks , S_IWUSR | S_IRUGO , mt_show_quirks , mt_set_quirks ) ;
static struct attribute * sysfs_attrs [ ] = {
& dev_attr_quirks . attr ,
NULL
} ;
static struct attribute_group mt_attribute_group = {
. attrs = sysfs_attrs
} ;
2011-02-24 21:30:59 +03:00
static void mt_feature_mapping ( struct hid_device * hdev ,
2011-01-08 01:45:50 +03:00
struct hid_field * field , struct hid_usage * usage )
{
2011-03-18 16:27:52 +03:00
struct mt_device * td = hid_get_drvdata ( hdev ) ;
2012-06-19 16:39:52 +04:00
int i ;
2011-03-18 16:27:52 +03:00
switch ( usage - > hid ) {
case HID_DG_INPUTMODE :
2011-01-08 01:45:50 +03:00
td - > inputmode = field - > report - > id ;
2012-06-19 16:39:52 +04:00
td - > inputmode_index = 0 ; /* has to be updated below */
for ( i = 0 ; i < field - > maxusage ; i + + ) {
if ( field - > usage [ i ] . hid = = usage - > hid ) {
td - > inputmode_index = i ;
break ;
}
}
2011-03-18 16:27:52 +03:00
break ;
case HID_DG_CONTACTMAX :
2012-02-04 20:08:49 +04:00
td - > maxcontact_report_id = field - > report - > id ;
2011-03-18 16:27:52 +03:00
td - > maxcontacts = field - > value [ 0 ] ;
2012-11-14 19:59:18 +04:00
if ( ! td - > maxcontacts & &
field - > logical_maximum < = MT_MAX_MAXCONTACT )
td - > maxcontacts = field - > logical_maximum ;
2011-11-23 13:54:28 +04:00
if ( td - > mtclass . maxcontacts )
2011-03-18 16:27:52 +03:00
/* check if the maxcontacts is given by the class */
2011-11-23 13:54:28 +04:00
td - > maxcontacts = td - > mtclass . maxcontacts ;
2011-03-18 16:27:52 +03:00
break ;
2012-11-14 19:59:25 +04:00
case 0xff0000c5 :
if ( field - > report_count = = 256 & & field - > report_size = = 8 ) {
/* Win 8 devices need special quirks */
__s32 * quirks = & td - > mtclass . quirks ;
* quirks | = MT_QUIRK_ALWAYS_VALID ;
* quirks | = MT_QUIRK_IGNORE_DUPLICATES ;
* quirks | = MT_QUIRK_HOVERING ;
2013-01-31 20:22:26 +04:00
* quirks | = MT_QUIRK_CONTACT_CNT_ACCURATE ;
2012-11-14 19:59:25 +04:00
* quirks & = ~ MT_QUIRK_NOT_SEEN_MEANS_UP ;
* quirks & = ~ MT_QUIRK_VALID_IS_INRANGE ;
* quirks & = ~ MT_QUIRK_VALID_IS_CONFIDENCE ;
}
break ;
2011-01-08 01:45:50 +03:00
}
}
static void set_abs ( struct input_dev * input , unsigned int code ,
struct hid_field * field , int snratio )
{
int fmin = field - > logical_minimum ;
int fmax = field - > logical_maximum ;
int fuzz = snratio ? ( fmax - fmin ) / snratio : 0 ;
input_set_abs_params ( input , code , fmin , fmax , fuzz , 0 ) ;
2012-11-14 19:59:13 +04:00
input_abs_set_res ( input , code , hidinput_calc_abs_res ( field , code ) ) ;
2011-01-08 01:45:50 +03:00
}
2012-05-04 16:53:46 +04:00
static void mt_store_field ( struct hid_usage * usage , struct mt_device * td ,
2012-03-06 20:57:03 +04:00
struct hid_input * hi )
{
2012-05-04 16:53:46 +04:00
struct mt_fields * f = td - > fields ;
if ( f - > length > = HID_MAX_FIELDS )
return ;
f - > usages [ f - > length + + ] = usage - > hid ;
2012-03-06 20:57:03 +04:00
}
2013-03-22 21:38:32 +04:00
static int mt_pen_input_mapping ( struct hid_device * hdev , struct hid_input * hi ,
struct hid_field * field , struct hid_usage * usage ,
unsigned long * * bit , int * max )
{
struct mt_device * td = hid_get_drvdata ( hdev ) ;
td - > pen_report_id = field - > report - > id ;
return 0 ;
}
static int mt_pen_input_mapped ( struct hid_device * hdev , struct hid_input * hi ,
struct hid_field * field , struct hid_usage * usage ,
unsigned long * * bit , int * max )
{
return 0 ;
}
static int mt_pen_event ( struct hid_device * hid , struct hid_field * field ,
struct hid_usage * usage , __s32 value )
{
/* let hid-input handle it */
return 0 ;
}
static void mt_pen_report ( struct hid_device * hid , struct hid_report * report )
{
struct hid_field * field = report - > field [ 0 ] ;
input_sync ( field - > hidinput - > input ) ;
}
static void mt_pen_input_configured ( struct hid_device * hdev ,
struct hid_input * hi )
{
}
2013-03-22 21:38:29 +04:00
static int mt_touch_input_mapping ( struct hid_device * hdev , struct hid_input * hi ,
2011-01-08 01:45:50 +03:00
struct hid_field * field , struct hid_usage * usage ,
unsigned long * * bit , int * max )
{
struct mt_device * td = hid_get_drvdata ( hdev ) ;
2011-11-23 13:54:28 +04:00
struct mt_class * cls = & td - > mtclass ;
2012-02-04 20:08:48 +04:00
int code ;
2012-11-14 19:59:19 +04:00
struct hid_usage * prev_usage = NULL ;
2011-03-09 08:20:57 +03:00
2011-08-16 03:44:28 +04:00
if ( field - > application = = HID_DG_TOUCHSCREEN )
2012-09-01 22:11:34 +04:00
td - > mt_flags | = INPUT_MT_DIRECT ;
2011-08-16 03:44:28 +04:00
2012-09-01 22:11:34 +04:00
/*
* Model touchscreens providing buttons as touchpads .
2012-02-04 20:08:48 +04:00
*/
if ( field - > application = = HID_DG_TOUCHPAD | |
2012-09-01 22:11:34 +04:00
( usage - > hid & HID_USAGE_PAGE ) = = HID_UP_BUTTON )
td - > mt_flags | = INPUT_MT_POINTER ;
2012-02-04 20:08:48 +04:00
2012-11-14 19:59:19 +04:00
if ( usage - > usage_index )
prev_usage = & field - > usage [ usage - > usage_index - 1 ] ;
2011-01-08 01:45:50 +03:00
switch ( usage - > hid & HID_USAGE_PAGE ) {
case HID_UP_GENDESK :
switch ( usage - > hid ) {
case HID_GD_X :
2012-11-14 19:59:19 +04:00
if ( prev_usage & & ( prev_usage - > hid = = usage - > hid ) ) {
hid_map_usage ( hi , usage , bit , max ,
EV_ABS , ABS_MT_TOOL_X ) ;
set_abs ( hi - > input , ABS_MT_TOOL_X , field ,
cls - > sn_move ) ;
} else {
hid_map_usage ( hi , usage , bit , max ,
2011-01-08 01:45:50 +03:00
EV_ABS , ABS_MT_POSITION_X ) ;
2012-11-14 19:59:19 +04:00
set_abs ( hi - > input , ABS_MT_POSITION_X , field ,
cls - > sn_move ) ;
}
2012-05-04 16:53:46 +04:00
mt_store_field ( usage , td , hi ) ;
2011-01-08 01:45:50 +03:00
return 1 ;
case HID_GD_Y :
2012-11-14 19:59:19 +04:00
if ( prev_usage & & ( prev_usage - > hid = = usage - > hid ) ) {
hid_map_usage ( hi , usage , bit , max ,
EV_ABS , ABS_MT_TOOL_Y ) ;
set_abs ( hi - > input , ABS_MT_TOOL_Y , field ,
cls - > sn_move ) ;
} else {
hid_map_usage ( hi , usage , bit , max ,
2011-01-08 01:45:50 +03:00
EV_ABS , ABS_MT_POSITION_Y ) ;
2012-11-14 19:59:19 +04:00
set_abs ( hi - > input , ABS_MT_POSITION_Y , field ,
cls - > sn_move ) ;
}
2012-05-04 16:53:46 +04:00
mt_store_field ( usage , td , hi ) ;
2011-01-08 01:45:50 +03:00
return 1 ;
}
return 0 ;
case HID_UP_DIGITIZER :
switch ( usage - > hid ) {
case HID_DG_INRANGE :
2012-11-14 19:59:24 +04:00
if ( cls - > quirks & MT_QUIRK_HOVERING ) {
hid_map_usage ( hi , usage , bit , max ,
EV_ABS , ABS_MT_DISTANCE ) ;
input_set_abs_params ( hi - > input ,
ABS_MT_DISTANCE , 0 , 1 , 0 , 0 ) ;
}
2012-05-04 16:53:46 +04:00
mt_store_field ( usage , td , hi ) ;
2011-01-08 01:45:50 +03:00
return 1 ;
case HID_DG_CONFIDENCE :
2012-05-04 16:53:46 +04:00
mt_store_field ( usage , td , hi ) ;
2011-01-08 01:45:50 +03:00
return 1 ;
case HID_DG_TIPSWITCH :
hid_map_usage ( hi , usage , bit , max , EV_KEY , BTN_TOUCH ) ;
input_set_capability ( hi - > input , EV_KEY , BTN_TOUCH ) ;
2012-05-04 16:53:46 +04:00
mt_store_field ( usage , td , hi ) ;
2011-01-08 01:45:50 +03:00
return 1 ;
case HID_DG_CONTACTID :
2012-05-04 16:53:46 +04:00
mt_store_field ( usage , td , hi ) ;
2012-03-06 20:57:06 +04:00
td - > touches_by_report + + ;
2013-01-31 20:22:24 +04:00
td - > mt_report_id = field - > report - > id ;
2011-01-08 01:45:50 +03:00
return 1 ;
case HID_DG_WIDTH :
hid_map_usage ( hi , usage , bit , max ,
EV_ABS , ABS_MT_TOUCH_MAJOR ) ;
2012-09-07 21:37:40 +04:00
if ( ! ( cls - > quirks & MT_QUIRK_NO_AREA ) )
set_abs ( hi - > input , ABS_MT_TOUCH_MAJOR , field ,
cls - > sn_width ) ;
2012-05-04 16:53:46 +04:00
mt_store_field ( usage , td , hi ) ;
2011-01-08 01:45:50 +03:00
return 1 ;
case HID_DG_HEIGHT :
hid_map_usage ( hi , usage , bit , max ,
EV_ABS , ABS_MT_TOUCH_MINOR ) ;
2012-09-07 21:37:40 +04:00
if ( ! ( cls - > quirks & MT_QUIRK_NO_AREA ) ) {
set_abs ( hi - > input , ABS_MT_TOUCH_MINOR , field ,
cls - > sn_height ) ;
input_set_abs_params ( hi - > input ,
2011-03-18 16:27:55 +03:00
ABS_MT_ORIENTATION , 0 , 1 , 0 , 0 ) ;
2012-09-07 21:37:40 +04:00
}
2012-05-04 16:53:46 +04:00
mt_store_field ( usage , td , hi ) ;
2011-01-08 01:45:50 +03:00
return 1 ;
case HID_DG_TIPPRESSURE :
hid_map_usage ( hi , usage , bit , max ,
EV_ABS , ABS_MT_PRESSURE ) ;
set_abs ( hi - > input , ABS_MT_PRESSURE , field ,
cls - > sn_pressure ) ;
2012-05-04 16:53:46 +04:00
mt_store_field ( usage , td , hi ) ;
2011-01-08 01:45:50 +03:00
return 1 ;
case HID_DG_CONTACTCOUNT :
2013-02-06 15:10:47 +04:00
td - > cc_index = field - > index ;
td - > cc_value_index = usage - > usage_index ;
2011-01-08 01:45:50 +03:00
return 1 ;
case HID_DG_CONTACTMAX :
/* we don't set td->last_slot_field as contactcount and
* contact max are global to the report */
return - 1 ;
2012-02-04 20:08:48 +04:00
case HID_DG_TOUCH :
/* Legacy devices use TIPSWITCH and not TOUCH.
* Let ' s just ignore this field . */
return - 1 ;
2012-10-25 18:35:25 +04:00
}
2011-01-08 01:45:50 +03:00
/* let hid-input decide for the others */
return 0 ;
2012-02-04 20:08:48 +04:00
case HID_UP_BUTTON :
code = BTN_MOUSE + ( ( usage - > hid - 1 ) & HID_USAGE ) ;
hid_map_usage ( hi , usage , bit , max , EV_KEY , code ) ;
input_set_capability ( hi - > input , EV_KEY , code ) ;
return 1 ;
2011-01-08 01:45:50 +03:00
case 0xff000000 :
/* we do not want to map these: no input-oriented meaning */
return - 1 ;
}
return 0 ;
}
2013-03-22 21:38:29 +04:00
static int mt_touch_input_mapped ( struct hid_device * hdev , struct hid_input * hi ,
2011-01-08 01:45:50 +03:00
struct hid_field * field , struct hid_usage * usage ,
unsigned long * * bit , int * max )
{
if ( usage - > type = = EV_KEY | | usage - > type = = EV_ABS )
set_bit ( usage - > type , hi - > input - > evbit ) ;
return - 1 ;
}
2012-09-01 21:46:58 +04:00
static int mt_compute_slot ( struct mt_device * td , struct input_dev * input )
2011-01-08 01:45:50 +03:00
{
2011-11-23 13:54:28 +04:00
__s32 quirks = td - > mtclass . quirks ;
2011-01-08 01:45:50 +03:00
2011-01-11 18:45:54 +03:00
if ( quirks & MT_QUIRK_SLOT_IS_CONTACTID )
return td - > curdata . contactid ;
2011-01-08 01:45:50 +03:00
2011-01-11 18:45:54 +03:00
if ( quirks & MT_QUIRK_CYPRESS )
2011-01-08 01:46:30 +03:00
return cypress_compute_slot ( td ) ;
2011-01-11 18:45:54 +03:00
if ( quirks & MT_QUIRK_SLOT_IS_CONTACTNUMBER )
return td - > num_received ;
2011-01-08 01:47:27 +03:00
2011-04-22 13:51:48 +04:00
if ( quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE )
return td - > curdata . contactid - 1 ;
2012-09-01 21:46:58 +04:00
return input_mt_get_slot_by_key ( input , td - > curdata . contactid ) ;
2011-01-08 01:45:50 +03:00
}
/*
* this function is called when a whole contact has been processed ,
* so that it can assign it to a slot and store the data there
*/
2012-09-01 21:46:58 +04:00
static void mt_complete_slot ( struct mt_device * td , struct input_dev * input )
2011-01-08 01:45:50 +03:00
{
2013-01-31 20:22:25 +04:00
if ( ( td - > mtclass . quirks & MT_QUIRK_CONTACT_CNT_ACCURATE ) & &
td - > num_received > = td - > num_expected )
return ;
2012-11-14 19:59:20 +04:00
if ( td - > curvalid | | ( td - > mtclass . quirks & MT_QUIRK_ALWAYS_VALID ) ) {
2012-09-01 21:46:58 +04:00
int slotnum = mt_compute_slot ( td , input ) ;
struct mt_slot * s = & td - > curdata ;
2012-11-14 19:59:23 +04:00
struct input_mt * mt = input - > mt ;
2011-01-08 01:45:50 +03:00
2012-09-01 21:46:58 +04:00
if ( slotnum < 0 | | slotnum > = td - > maxcontacts )
return ;
2011-01-08 01:45:50 +03:00
2012-11-14 19:59:23 +04:00
if ( ( td - > mtclass . quirks & MT_QUIRK_IGNORE_DUPLICATES ) & & mt ) {
struct input_mt_slot * slot = & mt - > slots [ slotnum ] ;
if ( input_mt_is_active ( slot ) & &
input_mt_is_used ( mt , slot ) )
return ;
}
2012-09-01 21:46:58 +04:00
input_mt_slot ( input , slotnum ) ;
2011-01-08 01:45:50 +03:00
input_mt_report_slot_state ( input , MT_TOOL_FINGER ,
2012-11-14 19:59:24 +04:00
s - > touch_state | | s - > inrange_state ) ;
if ( s - > touch_state | | s - > inrange_state ) {
/* this finger is in proximity of the sensor */
2011-03-22 19:34:01 +03:00
int wide = ( s - > w > s - > h ) ;
/* divided by two to match visual scale of touch */
int major = max ( s - > w , s - > h ) > > 1 ;
int minor = min ( s - > w , s - > h ) > > 1 ;
2011-01-11 18:45:54 +03:00
input_event ( input , EV_ABS , ABS_MT_POSITION_X , s - > x ) ;
input_event ( input , EV_ABS , ABS_MT_POSITION_Y , s - > y ) ;
2012-11-14 19:59:19 +04:00
input_event ( input , EV_ABS , ABS_MT_TOOL_X , s - > cx ) ;
input_event ( input , EV_ABS , ABS_MT_TOOL_Y , s - > cy ) ;
2012-11-14 19:59:24 +04:00
input_event ( input , EV_ABS , ABS_MT_DISTANCE ,
! s - > touch_state ) ;
2011-03-22 19:34:01 +03:00
input_event ( input , EV_ABS , ABS_MT_ORIENTATION , wide ) ;
2011-01-11 18:45:54 +03:00
input_event ( input , EV_ABS , ABS_MT_PRESSURE , s - > p ) ;
2011-03-22 19:34:01 +03:00
input_event ( input , EV_ABS , ABS_MT_TOUCH_MAJOR , major ) ;
input_event ( input , EV_ABS , ABS_MT_TOUCH_MINOR , minor ) ;
2011-01-11 18:45:54 +03:00
}
2011-01-08 01:45:50 +03:00
}
2012-09-01 21:46:58 +04:00
td - > num_received + + ;
}
/*
* this function is called when a whole packet has been received and processed ,
* so that it can decide what to send to the input layer .
*/
static void mt_sync_frame ( struct mt_device * td , struct input_dev * input )
{
2012-09-01 22:11:34 +04:00
input_mt_sync_frame ( input ) ;
2011-01-08 01:45:50 +03:00
input_sync ( input ) ;
td - > num_received = 0 ;
}
2013-03-22 21:38:29 +04:00
static int mt_touch_event ( struct hid_device * hid , struct hid_field * field ,
2011-01-08 01:45:50 +03:00
struct hid_usage * usage , __s32 value )
2013-01-31 20:22:24 +04:00
{
/* we will handle the hidinput part later, now remains hiddev */
if ( hid - > claimed & HID_CLAIMED_HIDDEV & & hid - > hiddev_hid_event )
hid - > hiddev_hid_event ( hid , field , usage , value ) ;
return 1 ;
}
static void mt_process_mt_event ( struct hid_device * hid , struct hid_field * field ,
struct hid_usage * usage , __s32 value )
2011-01-08 01:45:50 +03:00
{
struct mt_device * td = hid_get_drvdata ( hid ) ;
2011-11-23 13:54:28 +04:00
__s32 quirks = td - > mtclass . quirks ;
2011-01-08 01:45:50 +03:00
2012-09-01 21:46:58 +04:00
if ( hid - > claimed & HID_CLAIMED_INPUT ) {
2011-01-08 01:45:50 +03:00
switch ( usage - > hid ) {
case HID_DG_INRANGE :
2012-11-14 19:59:20 +04:00
if ( quirks & MT_QUIRK_VALID_IS_INRANGE )
2011-01-11 18:45:54 +03:00
td - > curvalid = value ;
2012-11-14 19:59:24 +04:00
if ( quirks & MT_QUIRK_HOVERING )
td - > curdata . inrange_state = value ;
2011-01-08 01:45:50 +03:00
break ;
case HID_DG_TIPSWITCH :
2011-01-11 18:45:54 +03:00
if ( quirks & MT_QUIRK_NOT_SEEN_MEANS_UP )
td - > curvalid = value ;
2011-01-08 01:45:50 +03:00
td - > curdata . touch_state = value ;
break ;
case HID_DG_CONFIDENCE :
2011-01-11 18:45:54 +03:00
if ( quirks & MT_QUIRK_VALID_IS_CONFIDENCE )
td - > curvalid = value ;
2011-01-08 01:45:50 +03:00
break ;
case HID_DG_CONTACTID :
td - > curdata . contactid = value ;
break ;
case HID_DG_TIPPRESSURE :
td - > curdata . p = value ;
break ;
case HID_GD_X :
2012-11-14 19:59:19 +04:00
if ( usage - > code = = ABS_MT_TOOL_X )
td - > curdata . cx = value ;
else
td - > curdata . x = value ;
2011-01-08 01:45:50 +03:00
break ;
case HID_GD_Y :
2012-11-14 19:59:19 +04:00
if ( usage - > code = = ABS_MT_TOOL_Y )
td - > curdata . cy = value ;
else
td - > curdata . y = value ;
2011-01-08 01:45:50 +03:00
break ;
case HID_DG_WIDTH :
td - > curdata . w = value ;
break ;
case HID_DG_HEIGHT :
td - > curdata . h = value ;
break ;
case HID_DG_CONTACTCOUNT :
break ;
2012-02-04 20:08:48 +04:00
case HID_DG_TOUCH :
/* do nothing */
break ;
2011-01-08 01:45:50 +03:00
default :
2013-01-31 20:22:24 +04:00
return ;
2011-01-08 01:45:50 +03:00
}
2012-11-14 19:59:17 +04:00
if ( usage - > usage_index + 1 = = field - > report_count ) {
/* we only take into account the last report. */
if ( usage - > hid = = td - > last_slot_field )
mt_complete_slot ( td , field - > hidinput - > input ) ;
}
2011-01-08 01:45:50 +03:00
2011-01-11 18:45:54 +03:00
}
2013-01-31 20:22:24 +04:00
}
2011-01-08 01:45:50 +03:00
2013-03-22 21:38:29 +04:00
static void mt_touch_report ( struct hid_device * hid , struct hid_report * report )
2013-01-31 20:22:24 +04:00
{
struct mt_device * td = hid_get_drvdata ( hid ) ;
struct hid_field * field ;
unsigned count ;
int r , n ;
2011-01-08 01:45:50 +03:00
2013-01-31 20:22:25 +04:00
/*
* Includes multi - packet support where subsequent
* packets are sent with zero contactcount .
*/
2013-02-06 15:10:47 +04:00
if ( td - > cc_index > = 0 ) {
struct hid_field * field = report - > field [ td - > cc_index ] ;
int value = field - > value [ td - > cc_value_index ] ;
if ( value )
td - > num_expected = value ;
}
2013-01-31 20:22:25 +04:00
2013-01-31 20:22:24 +04:00
for ( r = 0 ; r < report - > maxfield ; r + + ) {
field = report - > field [ r ] ;
count = field - > report_count ;
if ( ! ( HID_MAIN_ITEM_VARIABLE & field - > flags ) )
continue ;
for ( n = 0 ; n < count ; n + + )
mt_process_mt_event ( hid , field , & field - > usage [ n ] ,
field - > value [ n ] ) ;
}
2013-02-27 19:23:15 +04:00
if ( td - > num_received > = td - > num_expected )
mt_sync_frame ( td , report - > field [ 0 ] - > hidinput - > input ) ;
2011-01-08 01:45:50 +03:00
}
2013-03-22 21:38:29 +04:00
static void mt_touch_input_configured ( struct hid_device * hdev ,
struct hid_input * hi )
{
struct mt_device * td = hid_get_drvdata ( hdev ) ;
struct mt_class * cls = & td - > mtclass ;
struct input_dev * input = hi - > input ;
if ( ! td - > maxcontacts )
td - > maxcontacts = MT_DEFAULT_MAXCONTACT ;
mt_post_parse ( td ) ;
if ( td - > serial_maybe )
mt_post_parse_default_settings ( td ) ;
if ( cls - > is_indirect )
td - > mt_flags | = INPUT_MT_POINTER ;
if ( cls - > quirks & MT_QUIRK_NOT_SEEN_MEANS_UP )
td - > mt_flags | = INPUT_MT_DROP_UNUSED ;
input_mt_init_slots ( input , td - > maxcontacts , td - > mt_flags ) ;
td - > mt_flags = 0 ;
}
static int mt_input_mapping ( struct hid_device * hdev , struct hid_input * hi ,
struct hid_field * field , struct hid_usage * usage ,
unsigned long * * bit , int * max )
{
/* Only map fields from TouchScreen or TouchPad collections.
* We need to ignore fields that belong to other collections
* such as Mouse that might have the same GenericDesktop usages . */
if ( field - > application ! = HID_DG_TOUCHSCREEN & &
2013-03-22 21:38:32 +04:00
field - > application ! = HID_DG_PEN & &
2013-03-22 21:38:29 +04:00
field - > application ! = HID_DG_TOUCHPAD )
2013-03-22 21:38:30 +04:00
return - 1 ;
2013-03-22 21:38:29 +04:00
if ( field - > physical = = HID_DG_STYLUS )
2013-03-22 21:38:32 +04:00
return mt_pen_input_mapping ( hdev , hi , field , usage , bit , max ) ;
2013-03-22 21:38:29 +04:00
return mt_touch_input_mapping ( hdev , hi , field , usage , bit , max ) ;
}
static int mt_input_mapped ( struct hid_device * hdev , struct hid_input * hi ,
struct hid_field * field , struct hid_usage * usage ,
unsigned long * * bit , int * max )
{
2013-03-22 21:38:32 +04:00
if ( field - > physical = = HID_DG_STYLUS )
return mt_pen_input_mapped ( hdev , hi , field , usage , bit , max ) ;
2013-03-22 21:38:29 +04:00
return mt_touch_input_mapped ( hdev , hi , field , usage , bit , max ) ;
}
static int mt_event ( struct hid_device * hid , struct hid_field * field ,
struct hid_usage * usage , __s32 value )
{
struct mt_device * td = hid_get_drvdata ( hid ) ;
if ( field - > report - > id = = td - > mt_report_id )
return mt_touch_event ( hid , field , usage , value ) ;
2013-03-22 21:38:32 +04:00
if ( field - > report - > id = = td - > pen_report_id )
return mt_pen_event ( hid , field , usage , value ) ;
2013-03-22 21:38:29 +04:00
/* ignore other reports */
return 1 ;
}
static void mt_report ( struct hid_device * hid , struct hid_report * report )
{
struct mt_device * td = hid_get_drvdata ( hid ) ;
if ( ! ( hid - > claimed & HID_CLAIMED_INPUT ) )
return ;
if ( report - > id = = td - > mt_report_id )
mt_touch_report ( hid , report ) ;
2013-03-22 21:38:32 +04:00
if ( report - > id = = td - > pen_report_id )
mt_pen_report ( hid , report ) ;
2013-03-22 21:38:29 +04:00
}
2011-01-08 01:45:50 +03:00
static void mt_set_input_mode ( struct hid_device * hdev )
{
struct mt_device * td = hid_get_drvdata ( hdev ) ;
struct hid_report * r ;
struct hid_report_enum * re ;
if ( td - > inputmode < 0 )
return ;
re = & ( hdev - > report_enum [ HID_FEATURE_REPORT ] ) ;
r = re - > report_id_hash [ td - > inputmode ] ;
if ( r ) {
2012-06-19 16:39:52 +04:00
r - > field [ 0 ] - > value [ td - > inputmode_index ] = 0x02 ;
2013-02-25 14:31:46 +04:00
hid_hw_request ( hdev , r , HID_REQ_SET_REPORT ) ;
2011-01-08 01:45:50 +03:00
}
}
2012-02-04 20:08:49 +04:00
static void mt_set_maxcontacts ( struct hid_device * hdev )
{
struct mt_device * td = hid_get_drvdata ( hdev ) ;
struct hid_report * r ;
struct hid_report_enum * re ;
int fieldmax , max ;
if ( td - > maxcontact_report_id < 0 )
return ;
if ( ! td - > mtclass . maxcontacts )
return ;
re = & hdev - > report_enum [ HID_FEATURE_REPORT ] ;
r = re - > report_id_hash [ td - > maxcontact_report_id ] ;
if ( r ) {
max = td - > mtclass . maxcontacts ;
fieldmax = r - > field [ 0 ] - > logical_maximum ;
max = min ( fieldmax , max ) ;
if ( r - > field [ 0 ] - > value [ 0 ] ! = max ) {
r - > field [ 0 ] - > value [ 0 ] = max ;
2013-02-25 14:31:46 +04:00
hid_hw_request ( hdev , r , HID_REQ_SET_REPORT ) ;
2012-02-04 20:08:49 +04:00
}
}
}
2012-05-01 10:40:01 +04:00
static void mt_post_parse_default_settings ( struct mt_device * td )
{
__s32 quirks = td - > mtclass . quirks ;
/* unknown serial device needs special quirks */
if ( td - > touches_by_report = = 1 ) {
quirks | = MT_QUIRK_ALWAYS_VALID ;
quirks & = ~ MT_QUIRK_NOT_SEEN_MEANS_UP ;
quirks & = ~ MT_QUIRK_VALID_IS_INRANGE ;
quirks & = ~ MT_QUIRK_VALID_IS_CONFIDENCE ;
2013-01-31 20:22:27 +04:00
quirks & = ~ MT_QUIRK_CONTACT_CNT_ACCURATE ;
2012-05-01 10:40:01 +04:00
}
td - > mtclass . quirks = quirks ;
}
2012-05-04 16:53:46 +04:00
static void mt_post_parse ( struct mt_device * td )
{
struct mt_fields * f = td - > fields ;
2013-01-31 20:22:25 +04:00
struct mt_class * cls = & td - > mtclass ;
2012-05-04 16:53:46 +04:00
if ( td - > touches_by_report > 0 ) {
int field_count_per_touch = f - > length / td - > touches_by_report ;
td - > last_slot_field = f - > usages [ field_count_per_touch - 1 ] ;
}
2013-01-31 20:22:25 +04:00
2013-02-06 15:10:47 +04:00
if ( td - > cc_index < 0 )
2013-01-31 20:22:25 +04:00
cls - > quirks & = ~ MT_QUIRK_CONTACT_CNT_ACCURATE ;
2012-05-04 16:53:46 +04:00
}
2012-09-01 22:11:34 +04:00
static void mt_input_configured ( struct hid_device * hdev , struct hid_input * hi )
{
2013-03-22 21:38:31 +04:00
struct mt_device * td = hid_get_drvdata ( hdev ) ;
2012-09-01 22:11:34 +04:00
2013-03-22 21:38:31 +04:00
if ( hi - > report - > id = = td - > mt_report_id )
mt_touch_input_configured ( hdev , hi ) ;
2013-03-22 21:38:32 +04:00
if ( hi - > report - > id = = td - > pen_report_id )
mt_pen_input_configured ( hdev , hi ) ;
2012-09-01 22:11:34 +04:00
}
2011-01-08 01:45:50 +03:00
static int mt_probe ( struct hid_device * hdev , const struct hid_device_id * id )
{
2011-01-11 18:45:54 +03:00
int ret , i ;
2011-01-08 01:45:50 +03:00
struct mt_device * td ;
2011-01-11 18:45:54 +03:00
struct mt_class * mtclass = mt_classes ; /* MT_CLS_DEFAULT */
2012-08-08 23:45:50 +04:00
for ( i = 0 ; mt_classes [ i ] . name ; i + + ) {
if ( id - > driver_data = = mt_classes [ i ] . name ) {
mtclass = & ( mt_classes [ i ] ) ;
break ;
2011-01-11 18:45:54 +03:00
}
}
2011-01-08 01:45:50 +03:00
2011-11-01 18:26:31 +04:00
/* This allows the driver to correctly support devices
* that emit events over several HID messages .
*/
hdev - > quirks | = HID_QUIRK_NO_INPUT_SYNC ;
2011-01-08 01:45:50 +03:00
2013-03-22 21:38:32 +04:00
/*
* This allows the driver to handle different input sensors
* that emits events through different reports on the same HID
* device .
*/
hdev - > quirks | = HID_QUIRK_MULTI_INPUT ;
hdev - > quirks | = HID_QUIRK_NO_EMPTY_INPUT ;
2011-03-18 16:27:52 +03:00
td = kzalloc ( sizeof ( struct mt_device ) , GFP_KERNEL ) ;
2011-01-08 01:45:50 +03:00
if ( ! td ) {
dev_err ( & hdev - > dev , " cannot allocate multitouch data \n " ) ;
return - ENOMEM ;
}
2011-11-23 13:54:28 +04:00
td - > mtclass = * mtclass ;
2011-01-08 01:45:50 +03:00
td - > inputmode = - 1 ;
2012-02-04 20:08:49 +04:00
td - > maxcontact_report_id = - 1 ;
2013-02-06 15:10:47 +04:00
td - > cc_index = - 1 ;
2013-03-22 21:38:32 +04:00
td - > mt_report_id = - 1 ;
td - > pen_report_id = - 1 ;
2011-01-08 01:45:50 +03:00
hid_set_drvdata ( hdev , td ) ;
2012-05-04 16:53:46 +04:00
td - > fields = kzalloc ( sizeof ( struct mt_fields ) , GFP_KERNEL ) ;
if ( ! td - > fields ) {
dev_err ( & hdev - > dev , " cannot allocate multitouch fields data \n " ) ;
ret = - ENOMEM ;
goto fail ;
}
2012-09-01 22:11:34 +04:00
if ( id - > vendor = = HID_ANY_ID & & id - > product = = HID_ANY_ID )
td - > serial_maybe = true ;
2011-01-08 01:45:50 +03:00
ret = hid_parse ( hdev ) ;
if ( ret ! = 0 )
goto fail ;
ret = hid_hw_start ( hdev , HID_CONNECT_DEFAULT ) ;
2011-01-11 18:45:54 +03:00
if ( ret )
2011-01-08 01:45:50 +03:00
goto fail ;
2011-11-23 13:54:28 +04:00
ret = sysfs_create_group ( & hdev - > dev . kobj , & mt_attribute_group ) ;
2012-02-04 20:08:49 +04:00
mt_set_maxcontacts ( hdev ) ;
2011-01-08 01:45:50 +03:00
mt_set_input_mode ( hdev ) ;
2012-05-04 16:53:46 +04:00
kfree ( td - > fields ) ;
td - > fields = NULL ;
2011-01-08 01:45:50 +03:00
return 0 ;
fail :
2012-05-04 16:53:46 +04:00
kfree ( td - > fields ) ;
2011-01-08 01:45:50 +03:00
kfree ( td ) ;
return ret ;
}
# ifdef CONFIG_PM
static int mt_reset_resume ( struct hid_device * hdev )
{
2012-02-04 20:08:49 +04:00
mt_set_maxcontacts ( hdev ) ;
2011-01-08 01:45:50 +03:00
mt_set_input_mode ( hdev ) ;
return 0 ;
}
2012-08-15 13:21:55 +04:00
static int mt_resume ( struct hid_device * hdev )
{
/* Some Elan legacy devices require SET_IDLE to be set on resume.
* It should be safe to send it to other devices too .
* Tested on 3 M , Stantum , Cypress , Zytronic , eGalax , and Elan panels . */
2013-02-27 19:38:18 +04:00
hid_hw_idle ( hdev , 0 , 0 , HID_REQ_SET_IDLE ) ;
2012-08-15 13:21:55 +04:00
return 0 ;
}
2011-01-08 01:45:50 +03:00
# endif
static void mt_remove ( struct hid_device * hdev )
{
struct mt_device * td = hid_get_drvdata ( hdev ) ;
2011-11-23 13:54:28 +04:00
sysfs_remove_group ( & hdev - > dev . kobj , & mt_attribute_group ) ;
2011-01-08 01:45:50 +03:00
hid_hw_stop ( hdev ) ;
kfree ( td ) ;
hid_set_drvdata ( hdev , NULL ) ;
}
static const struct hid_device_id mt_devices [ ] = {
2011-03-22 19:34:01 +03:00
/* 3M panels */
{ . driver_data = MT_CLS_3M ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_3M ,
2011-03-22 19:34:01 +03:00
USB_DEVICE_ID_3M1968 ) } ,
{ . driver_data = MT_CLS_3M ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_3M ,
2011-03-22 19:34:01 +03:00
USB_DEVICE_ID_3M2256 ) } ,
2011-12-23 18:41:00 +04:00
{ . driver_data = MT_CLS_3M ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_3M ,
2011-12-23 18:41:00 +04:00
USB_DEVICE_ID_3M3266 ) } ,
2011-03-22 19:34:01 +03:00
2011-05-19 16:18:13 +04:00
/* ActionStar panels */
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_NSMU ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_ACTIONSTAR ,
2011-05-19 16:18:13 +04:00
USB_DEVICE_ID_ACTIONSTAR_1011 ) } ,
2011-12-23 18:40:59 +04:00
/* Atmel panels */
{ . driver_data = MT_CLS_SERIAL ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_ATMEL ,
2011-12-23 18:40:59 +04:00
USB_DEVICE_ID_ATMEL_MULTITOUCH ) } ,
2012-03-06 13:53:45 +04:00
{ . driver_data = MT_CLS_SERIAL ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_ATMEL ,
2012-03-06 13:53:45 +04:00
USB_DEVICE_ID_ATMEL_MXT_DIGITIZER ) } ,
2011-12-23 18:40:59 +04:00
2012-04-20 14:15:44 +04:00
/* Baanto multitouch devices */
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_NSMU ,
2012-05-06 01:32:54 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_BAANTO ,
2012-04-20 14:15:44 +04:00
USB_DEVICE_ID_BAANTO_MT_190W2 ) } ,
2011-03-18 16:27:54 +03:00
/* Cando panels */
{ . driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_CANDO ,
2011-03-18 16:27:54 +03:00
USB_DEVICE_ID_CANDO_MULTI_TOUCH ) } ,
2013-01-31 20:22:29 +04:00
{ . driver_data = MT_CLS_DUAL_CONTACT_NUMBER ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_CANDO ,
2011-03-18 16:27:54 +03:00
USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1 ) } ,
{ . driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_CANDO ,
2011-03-18 16:27:54 +03:00
USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 ) } ,
{ . driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_CANDO ,
2011-03-18 16:27:54 +03:00
USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 ) } ,
2011-05-27 22:03:47 +04:00
/* Chunghwa Telecom touch panels */
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_NSMU ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_CHUNGHWAT ,
2011-05-27 22:03:47 +04:00
USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH ) } ,
2011-05-19 16:18:14 +04:00
/* CVTouch panels */
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_NSMU ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_CVTOUCH ,
2011-05-19 16:18:14 +04:00
USB_DEVICE_ID_CVTOUCH_SCREEN ) } ,
2011-01-08 01:46:30 +03:00
/* Cypress panel */
{ . driver_data = MT_CLS_CYPRESS ,
HID_USB_DEVICE ( USB_VENDOR_ID_CYPRESS ,
USB_DEVICE_ID_CYPRESS_TRUETOUCH ) } ,
2011-05-20 17:59:34 +04:00
/* eGalax devices (resistive) */
2011-11-23 13:54:31 +04:00
{ . driver_data = MT_CLS_EGALAX ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_DWAV ,
2011-11-23 13:54:31 +04:00
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D ) } ,
{ . driver_data = MT_CLS_EGALAX ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_DWAV ,
2011-11-23 13:54:31 +04:00
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E ) } ,
2011-05-20 17:59:34 +04:00
/* eGalax devices (capacitive) */
2011-11-23 13:54:31 +04:00
{ . driver_data = MT_CLS_EGALAX ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_DWAV ,
2011-11-23 13:54:31 +04:00
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C ) } ,
2012-03-06 13:53:47 +04:00
{ . driver_data = MT_CLS_EGALAX_SERIAL ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_DWAV ,
2012-03-06 13:53:47 +04:00
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7207 ) } ,
{ . driver_data = MT_CLS_EGALAX_SERIAL ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_DWAV ,
2012-03-06 13:53:47 +04:00
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_725E ) } ,
{ . driver_data = MT_CLS_EGALAX_SERIAL ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_DWAV ,
2012-03-06 13:53:47 +04:00
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224 ) } ,
2012-03-06 20:57:02 +04:00
{ . driver_data = MT_CLS_EGALAX_SERIAL ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_DWAV ,
2012-03-06 20:57:02 +04:00
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_722A ) } ,
2011-11-23 13:54:31 +04:00
{ . driver_data = MT_CLS_EGALAX ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_DWAV ,
2011-11-23 13:54:31 +04:00
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B ) } ,
2012-03-06 13:53:47 +04:00
{ . driver_data = MT_CLS_EGALAX_SERIAL ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_DWAV ,
2012-03-06 13:53:47 +04:00
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7262 ) } ,
2011-11-23 13:54:31 +04:00
{ . driver_data = MT_CLS_EGALAX ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_DWAV ,
2011-11-23 13:54:31 +04:00
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1 ) } ,
2012-03-06 13:53:47 +04:00
{ . driver_data = MT_CLS_EGALAX_SERIAL ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_DWAV ,
2012-03-06 13:53:47 +04:00
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72AA ) } ,
2011-11-23 13:54:33 +04:00
{ . driver_data = MT_CLS_EGALAX ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_DWAV ,
2011-11-23 13:54:33 +04:00
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA ) } ,
2011-11-23 13:54:32 +04:00
{ . driver_data = MT_CLS_EGALAX ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_DWAV ,
2011-11-23 13:54:32 +04:00
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302 ) } ,
2012-03-06 13:53:47 +04:00
{ . driver_data = MT_CLS_EGALAX_SERIAL ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_DWAV ,
2012-03-06 13:53:47 +04:00
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7349 ) } ,
2011-11-23 13:54:34 +04:00
{ . driver_data = MT_CLS_EGALAX_SERIAL ,
2012-08-09 10:34:48 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_DWAV ,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_73F7 ) } ,
2011-11-23 13:54:34 +04:00
{ . driver_data = MT_CLS_EGALAX_SERIAL ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_DWAV ,
2011-11-23 13:54:31 +04:00
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001 ) } ,
2012-08-15 12:01:01 +04:00
{ . driver_data = MT_CLS_EGALAX ,
HID_USB_DEVICE ( USB_VENDOR_ID_DWAV ,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224 ) } ,
{ . driver_data = MT_CLS_EGALAX ,
HID_USB_DEVICE ( USB_VENDOR_ID_DWAV ,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72D0 ) } ,
{ . driver_data = MT_CLS_EGALAX ,
HID_USB_DEVICE ( USB_VENDOR_ID_DWAV ,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72C4 ) } ,
2011-05-20 17:59:34 +04:00
2011-05-19 13:37:29 +04:00
/* Elo TouchSystems IntelliTouch Plus panel */
2013-01-31 20:22:30 +04:00
{ . driver_data = MT_CLS_DUAL_CONTACT_ID ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_ELO ,
2011-05-19 13:37:29 +04:00
USB_DEVICE_ID_ELO_TS2515 ) } ,
2012-09-07 21:37:40 +04:00
/* Flatfrog Panels */
{ . driver_data = MT_CLS_FLATFROG ,
MT_USB_DEVICE ( USB_VENDOR_ID_FLATFROG ,
USB_DEVICE_ID_MULTITOUCH_3200 ) } ,
2011-01-08 01:47:27 +03:00
/* GeneralTouch panel */
2012-09-28 06:18:59 +04:00
{ . driver_data = MT_CLS_GENERALTOUCH_TWOFINGERS ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_GENERAL_TOUCH ,
2011-01-08 01:47:27 +03:00
USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS ) } ,
2012-09-28 06:18:59 +04:00
{ . driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS ,
MT_USB_DEVICE ( USB_VENDOR_ID_GENERAL_TOUCH ,
USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PWT_TENFINGERS ) } ,
2011-01-08 01:47:27 +03:00
2012-03-19 18:41:03 +04:00
/* Gametel game controller */
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_NSMU ,
2012-05-04 17:32:04 +04:00
MT_BT_DEVICE ( USB_VENDOR_ID_FRUCTEL ,
2012-03-19 18:41:03 +04:00
USB_DEVICE_ID_GAMETEL_MT_MODE ) } ,
2011-05-19 16:18:15 +04:00
/* GoodTouch panels */
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_NSMU ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_GOODTOUCH ,
2011-05-19 16:18:15 +04:00
USB_DEVICE_ID_GOODTOUCH_000f ) } ,
2011-11-29 16:13:12 +04:00
/* Hanvon panels */
{ . driver_data = MT_CLS_DUAL_INRANGE_CONTACTID ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_HANVON_ALT ,
2011-11-29 16:13:12 +04:00
USB_DEVICE_ID_HANVON_ALT_MULTITOUCH ) } ,
2011-09-18 00:27:30 +04:00
/* Ideacom panel */
{ . driver_data = MT_CLS_SERIAL ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_IDEACOM ,
2011-09-18 00:27:30 +04:00
USB_DEVICE_ID_IDEACOM_IDC6650 ) } ,
2012-03-06 13:53:46 +04:00
{ . driver_data = MT_CLS_SERIAL ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_IDEACOM ,
2012-03-06 13:53:46 +04:00
USB_DEVICE_ID_IDEACOM_IDC6651 ) } ,
2011-09-18 00:27:30 +04:00
2011-05-09 19:54:14 +04:00
/* Ilitek dual touch panel */
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_NSMU ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_ILITEK ,
2011-05-09 19:54:14 +04:00
USB_DEVICE_ID_ILITEK_MULTITOUCH ) } ,
2011-01-31 13:28:22 +03:00
/* IRTOUCH panels */
{ . driver_data = MT_CLS_DUAL_INRANGE_CONTACTID ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_IRTOUCHSYSTEMS ,
2011-01-31 13:28:22 +03:00
USB_DEVICE_ID_IRTOUCH_INFRARED_USB ) } ,
2011-08-16 08:12:09 +04:00
/* LG Display panels */
{ . driver_data = MT_CLS_DEFAULT ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_LG ,
2011-08-16 08:12:09 +04:00
USB_DEVICE_ID_LG_MULTITOUCH ) } ,
2011-05-18 17:27:24 +04:00
/* Lumio panels */
{ . driver_data = MT_CLS_CONFIDENCE_MINUS_ONE ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_LUMIO ,
2011-05-18 17:27:24 +04:00
USB_DEVICE_ID_CRYSTALTOUCH ) } ,
2011-06-21 17:01:55 +04:00
{ . driver_data = MT_CLS_CONFIDENCE_MINUS_ONE ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_LUMIO ,
2011-06-21 17:01:55 +04:00
USB_DEVICE_ID_CRYSTALTOUCH_DUAL ) } ,
2011-05-18 17:27:24 +04:00
2011-04-22 13:51:48 +04:00
/* MosArt panels */
{ . driver_data = MT_CLS_CONFIDENCE_MINUS_ONE ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_ASUS ,
2011-04-22 13:51:48 +04:00
USB_DEVICE_ID_ASUS_T91MT ) } ,
{ . driver_data = MT_CLS_CONFIDENCE_MINUS_ONE ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_ASUS ,
2011-04-22 13:51:48 +04:00
USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO ) } ,
{ . driver_data = MT_CLS_CONFIDENCE_MINUS_ONE ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_TURBOX ,
2011-04-22 13:51:48 +04:00
USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART ) } ,
2013-01-31 20:22:25 +04:00
/* Nexio panels */
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_DEFAULT ,
2013-01-31 20:22:25 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_NEXIO ,
USB_DEVICE_ID_NEXIO_MULTITOUCH_420 ) } ,
2012-02-14 12:50:33 +04:00
/* Panasonic panels */
{ . driver_data = MT_CLS_PANASONIC ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_PANASONIC ,
2012-02-14 12:50:33 +04:00
USB_DEVICE_ID_PANABOARD_UBT780 ) } ,
{ . driver_data = MT_CLS_PANASONIC ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_PANASONIC ,
2012-02-14 12:50:33 +04:00
USB_DEVICE_ID_PANABOARD_UBT880 ) } ,
2012-06-05 02:27:51 +04:00
/* Novatek Panel */
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_NSMU ,
2012-06-06 18:28:33 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_NOVATEK ,
2012-06-05 02:27:51 +04:00
USB_DEVICE_ID_NOVATEK_PCT ) } ,
2011-04-21 18:21:52 +04:00
/* PenMount panels */
{ . driver_data = MT_CLS_CONFIDENCE ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_PENMOUNT ,
2011-04-21 18:21:52 +04:00
USB_DEVICE_ID_PENMOUNT_PCI ) } ,
2011-12-15 07:09:06 +04:00
/* PixArt optical touch screen */
{ . driver_data = MT_CLS_INRANGE_CONTACTNUMBER ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_PIXART ,
2011-12-15 07:09:06 +04:00
USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN ) } ,
{ . driver_data = MT_CLS_INRANGE_CONTACTNUMBER ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_PIXART ,
2011-12-15 07:09:06 +04:00
USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1 ) } ,
{ . driver_data = MT_CLS_INRANGE_CONTACTNUMBER ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_PIXART ,
2011-12-15 07:09:06 +04:00
USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2 ) } ,
2011-01-08 01:45:50 +03:00
/* PixCir-based panels */
2011-01-31 13:28:20 +03:00
{ . driver_data = MT_CLS_DUAL_INRANGE_CONTACTID ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_HANVON ,
2011-01-08 01:45:50 +03:00
USB_DEVICE_ID_HANVON_MULTITOUCH ) } ,
2011-01-31 13:28:20 +03:00
{ . driver_data = MT_CLS_DUAL_INRANGE_CONTACTID ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_CANDO ,
2011-01-08 01:45:50 +03:00
USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH ) } ,
2011-11-29 16:13:10 +04:00
/* Quanta-based panels */
{ . driver_data = MT_CLS_CONFIDENCE_CONTACT_ID ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_QUANTA ,
2011-11-29 16:13:10 +04:00
USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH ) } ,
{ . driver_data = MT_CLS_CONFIDENCE_CONTACT_ID ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_QUANTA ,
2011-11-29 16:13:10 +04:00
USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001 ) } ,
{ . driver_data = MT_CLS_CONFIDENCE_CONTACT_ID ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_QUANTA ,
2011-11-29 16:13:10 +04:00
USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008 ) } ,
2011-03-18 16:27:53 +03:00
/* Stantum panels */
2011-05-19 16:18:18 +04:00
{ . driver_data = MT_CLS_CONFIDENCE ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_STANTUM ,
2011-03-18 16:27:53 +03:00
USB_DEVICE_ID_MTP ) } ,
2011-05-19 16:18:18 +04:00
{ . driver_data = MT_CLS_CONFIDENCE ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_STANTUM_STM ,
2011-03-18 16:27:53 +03:00
USB_DEVICE_ID_MTP_STM ) } ,
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_DEFAULT ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_STANTUM_SITRONIX ,
2011-03-18 16:27:53 +03:00
USB_DEVICE_ID_MTP_SITRONIX ) } ,
2012-02-04 20:08:50 +04:00
/* TopSeed panels */
{ . driver_data = MT_CLS_TOPSEED ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_TOPSEED2 ,
2012-02-04 20:08:50 +04:00
USB_DEVICE_ID_TOPSEED2_PERIPAD_701 ) } ,
2011-05-19 16:18:16 +04:00
/* Touch International panels */
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_NSMU ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_TOUCH_INTL ,
2011-05-19 16:18:16 +04:00
USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH ) } ,
2011-05-19 16:18:17 +04:00
/* Unitec panels */
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_NSMU ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_UNITEC ,
2011-05-19 16:18:17 +04:00
USB_DEVICE_ID_UNITEC_USB_TOUCH_0709 ) } ,
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_NSMU ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_UNITEC ,
2011-05-19 16:18:17 +04:00
USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19 ) } ,
2011-07-15 12:58:06 +04:00
/* XAT */
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_NSMU ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_XAT ,
2011-07-15 12:58:06 +04:00
USB_DEVICE_ID_XAT_CSR ) } ,
2011-05-19 16:18:17 +04:00
2012-01-05 06:53:46 +04:00
/* Xiroku */
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_NSMU ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_XIROKU ,
2012-01-05 06:53:46 +04:00
USB_DEVICE_ID_XIROKU_SPX ) } ,
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_NSMU ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_XIROKU ,
2012-01-05 06:53:46 +04:00
USB_DEVICE_ID_XIROKU_MPX ) } ,
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_NSMU ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_XIROKU ,
2012-01-05 06:53:46 +04:00
USB_DEVICE_ID_XIROKU_CSR ) } ,
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_NSMU ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_XIROKU ,
2012-01-05 06:53:46 +04:00
USB_DEVICE_ID_XIROKU_SPX1 ) } ,
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_NSMU ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_XIROKU ,
2012-01-05 06:53:46 +04:00
USB_DEVICE_ID_XIROKU_MPX1 ) } ,
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_NSMU ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_XIROKU ,
2012-01-05 06:53:46 +04:00
USB_DEVICE_ID_XIROKU_CSR1 ) } ,
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_NSMU ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_XIROKU ,
2012-01-05 06:53:46 +04:00
USB_DEVICE_ID_XIROKU_SPX2 ) } ,
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_NSMU ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_XIROKU ,
2012-01-05 06:53:46 +04:00
USB_DEVICE_ID_XIROKU_MPX2 ) } ,
2013-01-31 20:22:31 +04:00
{ . driver_data = MT_CLS_NSMU ,
2012-05-04 17:32:04 +04:00
MT_USB_DEVICE ( USB_VENDOR_ID_XIROKU ,
2012-01-05 06:53:46 +04:00
USB_DEVICE_ID_XIROKU_CSR2 ) } ,
2012-06-19 16:39:54 +04:00
/* Zytronic panels */
{ . driver_data = MT_CLS_SERIAL ,
MT_USB_DEVICE ( USB_VENDOR_ID_ZYTRONIC ,
USB_DEVICE_ID_ZYTRONIC_ZXY100 ) } ,
2012-05-01 10:40:01 +04:00
/* Generic MT device */
{ HID_DEVICE ( HID_BUS_ANY , HID_GROUP_MULTITOUCH , HID_ANY_ID , HID_ANY_ID ) } ,
2011-01-08 01:45:50 +03:00
{ }
} ;
MODULE_DEVICE_TABLE ( hid , mt_devices ) ;
static const struct hid_usage_id mt_grabbed_usages [ ] = {
{ HID_ANY_ID , HID_ANY_ID , HID_ANY_ID } ,
{ HID_ANY_ID - 1 , HID_ANY_ID - 1 , HID_ANY_ID - 1 }
} ;
static struct hid_driver mt_driver = {
. name = " hid-multitouch " ,
. id_table = mt_devices ,
. probe = mt_probe ,
. remove = mt_remove ,
. input_mapping = mt_input_mapping ,
. input_mapped = mt_input_mapped ,
2012-09-01 22:11:34 +04:00
. input_configured = mt_input_configured ,
2011-01-08 01:45:50 +03:00
. feature_mapping = mt_feature_mapping ,
. usage_table = mt_grabbed_usages ,
. event = mt_event ,
2013-01-31 20:22:24 +04:00
. report = mt_report ,
2011-01-08 01:45:50 +03:00
# ifdef CONFIG_PM
. reset_resume = mt_reset_resume ,
2012-08-15 13:21:55 +04:00
. resume = mt_resume ,
2011-01-08 01:45:50 +03:00
# endif
} ;
2012-12-18 02:28:26 +04:00
module_hid_driver ( mt_driver ) ;