Commit 1ad273d6 authored by Peter Hutterer's avatar Peter Hutterer Committed by Jiri Kosina
Browse files

HID: input: do not run GET_REPORT unless there's a Resolution Multiplier



hid-multitouch currently runs GET_REPORT for Contact Max and again to
retrieve the Win8 blob. If both are within the same report, the
Resolution Multiplier code calls GET_FEATURE again and this time,
possibly due to timing, it causes the ILITEK-TP device interpret the
GET_FEATURE as an instruction to change the mode and effectively stop
the device from functioning as expected.

Notably: the device doesn't even have a Resolution Multiplier so it
shouldn't be affected by any of this at all.

Fix this by making sure we only execute GET_REPORT if there is
a Resolution Multiplier in the respective report. Where the
HID_QUIRK_NO_INIT_REPORTS field is set we just bail out immediately. This
shouldn't be triggered by any real device anyway.

Signed-off-by: default avatarPeter Hutterer <peter.hutterer@who-t.net>
Tested-by: default avatarWen He <wen.he_1@nxp.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent 8e9ddbde
Loading
Loading
Loading
Loading
+20 −10
Original line number Diff line number Diff line
@@ -1560,21 +1560,12 @@ static bool __hidinput_change_resolution_multipliers(struct hid_device *hid,
{
	struct hid_usage *usage;
	bool update_needed = false;
	bool get_report_completed = false;
	int i, j;

	if (report->maxfield == 0)
		return false;

	/*
	 * If we have more than one feature within this report we
	 * need to fill in the bits from the others before we can
	 * overwrite the ones for the Resolution Multiplier.
	 */
	if (report->maxfield > 1) {
		hid_hw_request(hid, report, HID_REQ_GET_REPORT);
		hid_hw_wait(hid);
	}

	for (i = 0; i < report->maxfield; i++) {
		__s32 value = use_logical_max ?
			      report->field[i]->logical_maximum :
@@ -1593,6 +1584,25 @@ static bool __hidinput_change_resolution_multipliers(struct hid_device *hid,
			if (usage->hid != HID_GD_RESOLUTION_MULTIPLIER)
				continue;

			/*
			 * If we have more than one feature within this
			 * report we need to fill in the bits from the
			 * others before we can overwrite the ones for the
			 * Resolution Multiplier.
			 *
			 * But if we're not allowed to read from the device,
			 * we just bail. Such a device should not exist
			 * anyway.
			 */
			if (!get_report_completed && report->maxfield > 1) {
				if (hid->quirks & HID_QUIRK_NO_INIT_REPORTS)
					return update_needed;

				hid_hw_request(hid, report, HID_REQ_GET_REPORT);
				hid_hw_wait(hid);
				get_report_completed = true;
			}

			report->field[i]->value[j] = value;
			update_needed = true;
		}