diff options
Diffstat (limited to 'drivers/hid/hid-multitouch.c')
| -rw-r--r-- | drivers/hid/hid-multitouch.c | 93 | 
1 files changed, 79 insertions, 14 deletions
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 58d0e7aaf08..fa5d7a1ffa9 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -47,10 +47,11 @@ MODULE_LICENSE("GPL");  #define MT_QUIRK_SLOT_IS_CONTACTID	(1 << 1)  #define MT_QUIRK_CYPRESS		(1 << 2)  #define MT_QUIRK_SLOT_IS_CONTACTNUMBER	(1 << 3) -#define MT_QUIRK_VALID_IS_INRANGE	(1 << 4) -#define MT_QUIRK_VALID_IS_CONFIDENCE	(1 << 5) -#define MT_QUIRK_EGALAX_XYZ_FIXUP	(1 << 6) -#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE	(1 << 7) +#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_EGALAX_XYZ_FIXUP	(1 << 7) +#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE	(1 << 8)  struct mt_slot {  	__s32 x, y, p, w, h; @@ -86,11 +87,12 @@ struct mt_class {  /* classes of device behavior */  #define MT_CLS_DEFAULT				0x0001 -#define MT_CLS_CONFIDENCE			0x0002 -#define MT_CLS_CONFIDENCE_MINUS_ONE		0x0003 -#define MT_CLS_DUAL_INRANGE_CONTACTID		0x0004 -#define MT_CLS_DUAL_INRANGE_CONTACTNUMBER	0x0005 -#define MT_CLS_DUAL_NSMU_CONTACTID		0x0006 +#define MT_CLS_SERIAL				0x0002 +#define MT_CLS_CONFIDENCE			0x0003 +#define MT_CLS_CONFIDENCE_MINUS_ONE		0x0004 +#define MT_CLS_DUAL_INRANGE_CONTACTID		0x0005 +#define MT_CLS_DUAL_INRANGE_CONTACTNUMBER	0x0006 +#define MT_CLS_DUAL_NSMU_CONTACTID		0x0007  /* vendor specific classes */  #define MT_CLS_3M				0x0101 @@ -134,6 +136,8 @@ static int find_slot_from_contactid(struct mt_device *td)  struct mt_class mt_classes[] = {  	{ .name = MT_CLS_DEFAULT,  		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP }, +	{ .name = MT_CLS_SERIAL, +		.quirks = MT_QUIRK_ALWAYS_VALID},  	{ .name = MT_CLS_CONFIDENCE,  		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE },  	{ .name = MT_CLS_CONFIDENCE_MINUS_ONE, @@ -213,6 +217,16 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,  	struct mt_class *cls = td->mtclass;  	__s32 quirks = cls->quirks; +	/* 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) +		set_bit(INPUT_PROP_DIRECT, hi->input->propbit); +	else if (field->application == HID_DG_TOUCHPAD) +		set_bit(INPUT_PROP_POINTER, hi->input->propbit); +	else +		return 0; +  	switch (usage->hid & HID_USAGE_PAGE) {  	case HID_UP_GENDESK: @@ -277,6 +291,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,  			td->last_slot_field = usage->hid;  			td->last_field_index = field->index;  			td->last_mt_collection = usage->collection_index; +			hdev->quirks &= ~HID_QUIRK_MULTITOUCH;  			return 1;  		case HID_DG_WIDTH:  			hid_map_usage(hi, usage, bit, max, @@ -435,7 +450,9 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,  	if (hid->claimed & HID_CLAIMED_INPUT && td->slots) {  		switch (usage->hid) {  		case HID_DG_INRANGE: -			if (quirks & MT_QUIRK_VALID_IS_INRANGE) +			if (quirks & MT_QUIRK_ALWAYS_VALID) +				td->curvalid = true; +			else if (quirks & MT_QUIRK_VALID_IS_INRANGE)  				td->curvalid = value;  			break;  		case HID_DG_TIPSWITCH: @@ -513,12 +530,44 @@ static void mt_set_input_mode(struct hid_device *hdev)  	}  } +/* a list of devices for which there is a specialized multitouch driver */ +static const struct hid_device_id mt_have_special_driver[] = { +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, 0x0001) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, 0x0006) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, +			USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, +			USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, +	{ } +}; + +static bool mt_match_one_id(struct hid_device *hdev, +		const struct hid_device_id *id) +{ +	return id->bus == hdev->bus && +		(id->vendor == HID_ANY_ID || id->vendor == hdev->vendor) && +		(id->product == HID_ANY_ID || id->product == hdev->product); +} + +static const struct hid_device_id *mt_match_id(struct hid_device *hdev, +		const struct hid_device_id *id) +{ +	for (; id->bus; id++) +		if (mt_match_one_id(hdev, id)) +			return id; + +	return NULL; +} +  static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)  {  	int ret, i;  	struct mt_device *td;  	struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */ +	if (mt_match_id(hdev, mt_have_special_driver)) +		return -ENODEV; +  	for (i = 0; mt_classes[i].name ; i++) {  		if (id->driver_data == mt_classes[i].name) {  			mtclass = &(mt_classes[i]); @@ -526,10 +575,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)  		}  	} -	/* This allows the driver to correctly support devices -	 * that emit events over several HID messages. -	 */ -	hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;  	td = kzalloc(sizeof(struct mt_device), GFP_KERNEL);  	if (!td) { @@ -545,10 +590,16 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)  	if (ret != 0)  		goto fail; +	hdev->quirks |= HID_QUIRK_MULTITOUCH;  	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);  	if (ret)  		goto fail; +	/* This allows the driver to correctly support devices +	 * that emit events over several HID messages. +	 */ +	hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; +  	td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot),  				GFP_KERNEL);  	if (!td->slots) { @@ -662,6 +713,11 @@ static const struct hid_device_id mt_devices[] = {  		HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH,  			USB_DEVICE_ID_GOODTOUCH_000f) }, +	/* Ideacom panel */ +	{ .driver_data = MT_CLS_SERIAL, +		HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, +			USB_DEVICE_ID_IDEACOM_IDC6650) }, +  	/* Ilitek dual touch panel */  	{  .driver_data = MT_CLS_DEFAULT,  		HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, @@ -672,6 +728,11 @@ static const struct hid_device_id mt_devices[] = {  		HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS,  			USB_DEVICE_ID_IRTOUCH_INFRARED_USB) }, +	/* LG Display panels */ +	{ .driver_data = MT_CLS_DEFAULT, +		HID_USB_DEVICE(USB_VENDOR_ID_LG, +			USB_DEVICE_ID_LG_MULTITOUCH) }, +  	/* Lumio panels */  	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,  		HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, @@ -732,6 +793,10 @@ static const struct hid_device_id mt_devices[] = {  		HID_USB_DEVICE(USB_VENDOR_ID_XAT,  			USB_DEVICE_ID_XAT_CSR) }, +	/* Rest of the world */ +	{ .driver_data = MT_CLS_DEFAULT, +		HID_USB_DEVICE(HID_ANY_ID, HID_ANY_ID) }, +  	{ }  };  MODULE_DEVICE_TABLE(hid, mt_devices);  |