forked from rpms/kernel
		
	Fix left-button not working with some hid-multitouch touchpads
This commit is contained in:
		
							parent
							
								
									5d8f3c9211
								
							
						
					
					
						commit
						f10b01dcd4
					
				
							
								
								
									
										106
									
								
								0001-HID-multitouch-Properly-deal-with-Win8-PTP-reports-w.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								0001-HID-multitouch-Properly-deal-with-Win8-PTP-reports-w.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,106 @@ | ||||
| From f5c1da991de077420fda17a236342de5a0068f5d Mon Sep 17 00:00:00 2001 | ||||
| From: Hans de Goede <hdegoede@redhat.com> | ||||
| Date: Wed, 22 Nov 2017 12:57:08 +0100 | ||||
| Subject: [PATCH v2 1/3] HID: multitouch: Properly deal with Win8 PTP reports | ||||
|  with 0 touches | ||||
| 
 | ||||
| The Windows Precision Touchpad spec "Figure 4 Button Only Down and Up" | ||||
| and "Table 9 Report Sequence for Button Only Down and Up" indicate | ||||
| that the first packet of a (possibly hybrid mode multi-packet) frame | ||||
| may contain a contact-count of 0 if only a button is pressed and no | ||||
| fingers are detected. | ||||
| 
 | ||||
| This means that a value of 0 for contact-count is a valid value and | ||||
| should be used as expected contact count when it is the first packet | ||||
| (num_received == 0), as extra check to make sure that this is the first | ||||
| packet of a buttons only frame, we also check that the timestamp is | ||||
| different.
 | ||||
| 
 | ||||
| Signed-off-by: Hans de Goede <hdegoede@redhat.com> | ||||
| Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> | ||||
| Signed-off-by: Jiri Kosina <jkosina@suse.cz> | ||||
| ---
 | ||||
|  drivers/hid/hid-multitouch.c | 32 ++++++++++++++++++++++++++++++-- | ||||
|  1 file changed, 30 insertions(+), 2 deletions(-) | ||||
| 
 | ||||
| diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
 | ||||
| index 9ef24b518f12..d8b1cad74faf 100644
 | ||||
| --- a/drivers/hid/hid-multitouch.c
 | ||||
| +++ b/drivers/hid/hid-multitouch.c
 | ||||
| @@ -119,6 +119,9 @@ struct mt_device {
 | ||||
|  	unsigned long mt_io_flags;	/* mt flags (MT_IO_FLAGS_*) */ | ||||
|  	int cc_index;	/* contact count field index in the report */ | ||||
|  	int cc_value_index;	/* contact count value index in the field */ | ||||
| +	int scantime_index;	/* scantime field index in the report */
 | ||||
| +	int scantime_val_index;	/* scantime value index in the field */
 | ||||
| +	int prev_scantime;	/* scantime reported in the previous packet */
 | ||||
|  	unsigned last_slot_field;	/* the last field of a slot */ | ||||
|  	unsigned mt_report_id;	/* the report ID of the multitouch device */ | ||||
|  	unsigned long initial_quirks;	/* initial quirks state */ | ||||
| @@ -599,6 +602,12 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 | ||||
|  				EV_MSC, MSC_TIMESTAMP); | ||||
|  			input_set_capability(hi->input, EV_MSC, MSC_TIMESTAMP); | ||||
|  			mt_store_field(usage, td, hi); | ||||
| +			/* Ignore if indexes are out of bounds. */
 | ||||
| +			if (field->index >= field->report->maxfield ||
 | ||||
| +			    usage->usage_index >= field->report_count)
 | ||||
| +				return 1;
 | ||||
| +			td->scantime_index = field->index;
 | ||||
| +			td->scantime_val_index = usage->usage_index;
 | ||||
|  			return 1; | ||||
|  		case HID_DG_CONTACTCOUNT: | ||||
|  			/* Ignore if indexes are out of bounds. */ | ||||
| @@ -855,9 +864,10 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
 | ||||
|  static void mt_touch_report(struct hid_device *hid, struct hid_report *report) | ||||
|  { | ||||
|  	struct mt_device *td = hid_get_drvdata(hid); | ||||
| +	__s32 cls = td->mtclass.name;
 | ||||
|  	struct hid_field *field; | ||||
|  	unsigned count; | ||||
| -	int r, n;
 | ||||
| +	int r, n, scantime = 0;
 | ||||
|   | ||||
|  	/* sticky fingers release in progress, abort */ | ||||
|  	if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags)) | ||||
| @@ -867,12 +877,29 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
 | ||||
|  	 * Includes multi-packet support where subsequent | ||||
|  	 * packets are sent with zero contactcount. | ||||
|  	 */ | ||||
| +	if (td->scantime_index >= 0) {
 | ||||
| +		field = report->field[td->scantime_index];
 | ||||
| +		scantime = field->value[td->scantime_val_index];
 | ||||
| +	}
 | ||||
|  	if (td->cc_index >= 0) { | ||||
|  		struct hid_field *field = report->field[td->cc_index]; | ||||
|  		int value = field->value[td->cc_value_index]; | ||||
| -		if (value)
 | ||||
| +
 | ||||
| +		/*
 | ||||
| +		 * For Win8 PTPs the first packet (td->num_received == 0) may
 | ||||
| +		 * have a contactcount of 0 if there only is a button event.
 | ||||
| +		 * We double check that this is not a continuation packet
 | ||||
| +		 * of a possible multi-packet frame be checking that the
 | ||||
| +		 * timestamp has changed.
 | ||||
| +		 */
 | ||||
| +		if ((cls == MT_CLS_WIN_8 || cls == MT_CLS_WIN_8_DUAL) &&
 | ||||
| +		    td->num_received == 0 && td->prev_scantime != scantime)
 | ||||
| +			td->num_expected = value;
 | ||||
| +		/* A non 0 contact count always indicates a first packet */
 | ||||
| +		else if (value)
 | ||||
|  			td->num_expected = value; | ||||
|  	} | ||||
| +	td->prev_scantime = scantime;
 | ||||
|   | ||||
|  	for (r = 0; r < report->maxfield; r++) { | ||||
|  		field = report->field[r]; | ||||
| @@ -1329,6 +1356,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 | ||||
|  	td->maxcontact_report_id = -1; | ||||
|  	td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN; | ||||
|  	td->cc_index = -1; | ||||
| +	td->scantime_index = -1;
 | ||||
|  	td->mt_report_id = -1; | ||||
|  	hid_set_drvdata(hdev, td); | ||||
|   | ||||
| -- 
 | ||||
| 2.14.3 | ||||
| 
 | ||||
| @ -0,0 +1,84 @@ | ||||
| From c25d877f4ee97deb92170129eee4777a5d5997d9 Mon Sep 17 00:00:00 2001 | ||||
| From: Hans de Goede <hdegoede@redhat.com> | ||||
| Date: Wed, 22 Nov 2017 12:57:09 +0100 | ||||
| Subject: [PATCH v2 2/3] HID: multitouch: Only look at non touch fields in | ||||
|  first packet of a frame | ||||
| 
 | ||||
| Devices in "single finger hybrid mode" will send one report per finger, | ||||
| on some devices only the first report of such a multi-packet frame will | ||||
| contain a value for BTN_LEFT, in subsequent reports (if multiple fingers | ||||
| are down) the value is always 0, causing hid-mt to report BTN_LEFT going | ||||
| 1 - 0 - 1 - 0 when pressing a clickpad and putting down a second finger. | ||||
| This happens for example on USB 0603:0002 mt touchpads. | ||||
| 
 | ||||
| This commit fixes this by only reporting non touch fields for the first | ||||
| packet of a (possibly) multi-packet frame. | ||||
| 
 | ||||
| Signed-off-by: Hans de Goede <hdegoede@redhat.com> | ||||
| Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> | ||||
| Signed-off-by: Jiri Kosina <jkosina@suse.cz> | ||||
| ---
 | ||||
|  drivers/hid/hid-multitouch.c | 17 +++++++++++++++-- | ||||
|  1 file changed, 15 insertions(+), 2 deletions(-) | ||||
| 
 | ||||
| diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
 | ||||
| index d8b1cad74faf..760c4a042e6a 100644
 | ||||
| --- a/drivers/hid/hid-multitouch.c
 | ||||
| +++ b/drivers/hid/hid-multitouch.c
 | ||||
| @@ -787,9 +787,11 @@ static int mt_touch_event(struct hid_device *hid, struct hid_field *field,
 | ||||
|  } | ||||
|   | ||||
|  static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field, | ||||
| -				struct hid_usage *usage, __s32 value)
 | ||||
| +				struct hid_usage *usage, __s32 value,
 | ||||
| +				bool first_packet)
 | ||||
|  { | ||||
|  	struct mt_device *td = hid_get_drvdata(hid); | ||||
| +	__s32 cls = td->mtclass.name;
 | ||||
|  	__s32 quirks = td->mtclass.quirks; | ||||
|  	struct input_dev *input = field->hidinput->input; | ||||
|   | ||||
| @@ -846,6 +848,15 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
 | ||||
|  			break; | ||||
|   | ||||
|  		default: | ||||
| +			/*
 | ||||
| +			 * For Win8 PTP touchpads we should only look at
 | ||||
| +			 * non finger/touch events in the first_packet of
 | ||||
| +			 * a (possible) multi-packet frame.
 | ||||
| +			 */
 | ||||
| +			if ((cls == MT_CLS_WIN_8 || cls == MT_CLS_WIN_8_DUAL) &&
 | ||||
| +			    !first_packet)
 | ||||
| +				return;
 | ||||
| +
 | ||||
|  			if (usage->type) | ||||
|  				input_event(input, usage->type, usage->code, | ||||
|  						value); | ||||
| @@ -866,6 +877,7 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
 | ||||
|  	struct mt_device *td = hid_get_drvdata(hid); | ||||
|  	__s32 cls = td->mtclass.name; | ||||
|  	struct hid_field *field; | ||||
| +	bool first_packet;
 | ||||
|  	unsigned count; | ||||
|  	int r, n, scantime = 0; | ||||
|   | ||||
| @@ -901,6 +913,7 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
 | ||||
|  	} | ||||
|  	td->prev_scantime = scantime; | ||||
|   | ||||
| +	first_packet = td->num_received == 0;
 | ||||
|  	for (r = 0; r < report->maxfield; r++) { | ||||
|  		field = report->field[r]; | ||||
|  		count = field->report_count; | ||||
| @@ -910,7 +923,7 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
 | ||||
|   | ||||
|  		for (n = 0; n < count; n++) | ||||
|  			mt_process_mt_event(hid, field, &field->usage[n], | ||||
| -					field->value[n]);
 | ||||
| +					    field->value[n], first_packet);
 | ||||
|  	} | ||||
|   | ||||
|  	if (td->num_received >= td->num_expected) | ||||
| -- 
 | ||||
| 2.14.3 | ||||
| 
 | ||||
| @ -0,0 +1,78 @@ | ||||
| From 1719566899e5a69b4ba767beb07dab7ceb9ae5a8 Mon Sep 17 00:00:00 2001 | ||||
| From: Hans de Goede <hdegoede@redhat.com> | ||||
| Date: Wed, 22 Nov 2017 12:57:10 +0100 | ||||
| Subject: [PATCH v2 3/3] HID: multitouch: Combine all left-button events in a | ||||
|  frame | ||||
| 
 | ||||
| According to the Win8 Precision Touchpad spec, inside the HID_UP_BUTTON | ||||
| usage-page usage 1 is for a clickpad getting clicked, 2 for an external | ||||
| left button and 3 for an external right button. Since Linux uses | ||||
| BTN_LEFT for a clickpad being clicked we end up mapping both usage 1 | ||||
| and 2 to BTN_LEFT and if a single report contains both then we ended | ||||
| up always reporting the value of both in a single SYN, e.g. : | ||||
| BTN_LEFT 1, BTN_LEFT 0, SYN. This happens for example with Hantick | ||||
| HTT5288 i2c mt touchpads. | ||||
| 
 | ||||
| This commit fixes this by not immediately reporting left button when we | ||||
| parse the report, but instead storing or-ing together the values and | ||||
| reporting the result from mt_sync_frame() when we've a complete frame. | ||||
| 
 | ||||
| Signed-off-by: Hans de Goede <hdegoede@redhat.com> | ||||
| Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> | ||||
| Signed-off-by: Jiri Kosina <jkosina@suse.cz> | ||||
| ---
 | ||||
|  drivers/hid/hid-multitouch.c | 20 ++++++++++++++++++++ | ||||
|  1 file changed, 20 insertions(+) | ||||
| 
 | ||||
| diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
 | ||||
| index 760c4a042e6a..76088f2cf598 100644
 | ||||
| --- a/drivers/hid/hid-multitouch.c
 | ||||
| +++ b/drivers/hid/hid-multitouch.c
 | ||||
| @@ -122,6 +122,7 @@ struct mt_device {
 | ||||
|  	int scantime_index;	/* scantime field index in the report */ | ||||
|  	int scantime_val_index;	/* scantime value index in the field */ | ||||
|  	int prev_scantime;	/* scantime reported in the previous packet */ | ||||
| +	int left_button_state;	/* left button state */
 | ||||
|  	unsigned last_slot_field;	/* the last field of a slot */ | ||||
|  	unsigned mt_report_id;	/* the report ID of the multitouch device */ | ||||
|  	unsigned long initial_quirks;	/* initial quirks state */ | ||||
| @@ -743,10 +744,16 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
 | ||||
|   */ | ||||
|  static void mt_sync_frame(struct mt_device *td, struct input_dev *input) | ||||
|  { | ||||
| +	__s32 cls = td->mtclass.name;
 | ||||
| +
 | ||||
| +	if (cls == MT_CLS_WIN_8 || cls == MT_CLS_WIN_8_DUAL)
 | ||||
| +		input_event(input, EV_KEY, BTN_LEFT, td->left_button_state);
 | ||||
| +
 | ||||
|  	input_mt_sync_frame(input); | ||||
|  	input_event(input, EV_MSC, MSC_TIMESTAMP, td->timestamp); | ||||
|  	input_sync(input); | ||||
|  	td->num_received = 0; | ||||
| +	td->left_button_state = 0;
 | ||||
|  	if (test_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags)) | ||||
|  		set_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags); | ||||
|  	else | ||||
| @@ -857,6 +864,19 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
 | ||||
|  			    !first_packet) | ||||
|  				return; | ||||
|   | ||||
| +			/*
 | ||||
| +			 * For Win8 PTP touchpads we map both the clickpad click
 | ||||
| +			 * and any "external" left buttons to BTN_LEFT if a
 | ||||
| +			 * device claims to have both we need to report 1 for
 | ||||
| +			 * BTN_LEFT if either is pressed, so we or all values
 | ||||
| +			 * together and report the result in mt_sync_frame().
 | ||||
| +			 */
 | ||||
| +			if ((cls == MT_CLS_WIN_8 || cls == MT_CLS_WIN_8_DUAL) &&
 | ||||
| +			    usage->type == EV_KEY && usage->code == BTN_LEFT) {
 | ||||
| +				td->left_button_state |= value;
 | ||||
| +				return;
 | ||||
| +			}
 | ||||
| +
 | ||||
|  			if (usage->type) | ||||
|  				input_event(input, usage->type, usage->code, | ||||
|  						value); | ||||
| -- 
 | ||||
| 2.14.3 | ||||
| 
 | ||||
							
								
								
									
										10
									
								
								kernel.spec
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								kernel.spec
									
									
									
									
									
								
							| @ -641,6 +641,13 @@ Patch628: 0001-Bluetooth-btusb-Add-a-Kconfig-option-to-enable-USB-a.patch | ||||
| # rhbz 1516584 | ||||
| Patch629: drm-ttm-don-t-attempt-to-use-hugepages-if-dma32-requested.mbox | ||||
| 
 | ||||
| # Fix left-button not working with some hid-multitouch touchpads | ||||
| # Adding these suggested by Benjamin Tissoires | ||||
| # Queued in hid.git/for-4.16/hid-quirks-cleanup/multitouch for merging into 4.16 | ||||
| Patch630: 0001-HID-multitouch-Properly-deal-with-Win8-PTP-reports-w.patch | ||||
| Patch631: 0002-HID-multitouch-Only-look-at-non-touch-fields-in-firs.patch | ||||
| Patch632: 0003-HID-multitouch-Combine-all-left-button-events-in-a-f.patch | ||||
| 
 | ||||
| # END OF PATCH DEFINITIONS | ||||
| 
 | ||||
| %endif | ||||
| @ -2190,6 +2197,9 @@ fi | ||||
| # | ||||
| # | ||||
| %changelog | ||||
| * Sun Nov 26 2017 Hans de Goede <jwrdegoede@fedoraproject.org> | ||||
| - Fix left-button not working with some hid-multitouch touchpads | ||||
| 
 | ||||
| * Thu Nov 23 2017 Laura Abbott <labbott@redhat.com> - 4.15.0-0.rc0.git7.2 | ||||
| - Fix for TTM regression (rhbz 1516584) | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user