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: Peter Hutterer <peter.hutterer@who-t.net>
Tested-by: Wen He <wen.he_1@nxp.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
This commit is contained in:
Peter Hutterer 2020-06-09 16:03:19 +10:00 committed by Jiri Kosina
parent 8e9ddbde9d
commit 1ad273d6ff

View File

@ -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;
}