From patchwork Tue Apr 23 15:46:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 10913251 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 023F214DB for ; Tue, 23 Apr 2019 15:46:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E62A3288B3 for ; Tue, 23 Apr 2019 15:46:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DA94C288D2; Tue, 23 Apr 2019 15:46:30 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 53ABD288B3 for ; Tue, 23 Apr 2019 15:46:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728426AbfDWPq3 (ORCPT ); Tue, 23 Apr 2019 11:46:29 -0400 Received: from mx1.redhat.com ([209.132.183.28]:58686 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727745AbfDWPq3 (ORCPT ); Tue, 23 Apr 2019 11:46:29 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 38CD33D965; Tue, 23 Apr 2019 15:46:29 +0000 (UTC) Received: from plouf.redhat.com (ovpn-116-226.ams2.redhat.com [10.36.116.226]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8A5D95C296; Tue, 23 Apr 2019 15:46:24 +0000 (UTC) From: Benjamin Tissoires To: Jiri Kosina , James Feeney , Peter Hutterer Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, Benjamin Tissoires , stable@vger.kernel.org Subject: [PATCH 1/2] HID: input: make sure the wheel high resolution multiplier is set Date: Tue, 23 Apr 2019 17:46:14 +0200 Message-Id: <20190423154615.18257-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Tue, 23 Apr 2019 15:46:29 +0000 (UTC) Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Some old mice have a tendency to not accept the high resolution multiplier. They reply with a -EPIPE which was previously ignored. Force the call to resolution multiplier to be synchronous and actually check for the answer. If this fails, consider the mouse like a normal one. Fixes: 2dc702c991e377 ("HID: input: use the Resolution Multiplier for high-resolution scrolling") Link: https://bugzilla.redhat.com/show_bug.cgi?id=1700071 Reported-and-tested-by: James Feeney Cc: stable@vger.kernel.org # v5.0+ Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-core.c | 7 +++- drivers/hid/hid-input.c | 81 +++++++++++++++++++++++++---------------- include/linux/hid.h | 2 +- 3 files changed, 56 insertions(+), 34 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 76464aabd20c..92387fc0bf18 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1637,7 +1637,7 @@ static struct hid_report *hid_get_report(struct hid_report_enum *report_enum, * Implement a generic .request() callback, using .raw_request() * DO NOT USE in hid drivers directly, but through hid_hw_request instead. */ -void __hid_request(struct hid_device *hid, struct hid_report *report, +int __hid_request(struct hid_device *hid, struct hid_report *report, int reqtype) { char *buf; @@ -1646,7 +1646,7 @@ void __hid_request(struct hid_device *hid, struct hid_report *report, buf = hid_alloc_report_buf(report, GFP_KERNEL); if (!buf) - return; + return -ENOMEM; len = hid_report_len(report); @@ -1663,8 +1663,11 @@ void __hid_request(struct hid_device *hid, struct hid_report *report, if (reqtype == HID_REQ_GET_REPORT) hid_input_report(hid, report->type, buf, ret, 0); + ret = 0; + out: kfree(buf); + return ret; } EXPORT_SYMBOL_GPL(__hid_request); diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 1fce0076e7dc..fadf76f0a386 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -1542,52 +1542,71 @@ static void hidinput_close(struct input_dev *dev) hid_hw_close(hid); } -static void hidinput_change_resolution_multipliers(struct hid_device *hid) +static bool __hidinput_change_resolution_multipliers(struct hid_device *hid, + struct hid_report *report, bool use_logical_max) { - struct hid_report_enum *rep_enum; - struct hid_report *rep; struct hid_usage *usage; + bool update_needed = false; int i, j; - rep_enum = &hid->report_enum[HID_FEATURE_REPORT]; - list_for_each_entry(rep, &rep_enum->report_list, list) { - bool update_needed = false; + if (report->maxfield == 0) + return false; - if (rep->maxfield == 0) - 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. + */ + if (report->maxfield > 1) { + hid_hw_request(hid, report, HID_REQ_GET_REPORT); + hid_hw_wait(hid); + } - /* - * 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. + for (i = 0; i < report->maxfield; i++) { + __s32 value = use_logical_max ? + report->field[i]->logical_maximum : + report->field[i]->logical_minimum; + + /* There is no good reason for a Resolution + * Multiplier to have a count other than 1. + * Ignore that case. */ - if (rep->maxfield > 1) { - hid_hw_request(hid, rep, HID_REQ_GET_REPORT); - hid_hw_wait(hid); - } + if (report->field[i]->report_count != 1) + continue; - for (i = 0; i < rep->maxfield; i++) { - __s32 logical_max = rep->field[i]->logical_maximum; + for (j = 0; j < report->field[i]->maxusage; j++) { + usage = &report->field[i]->usage[j]; - /* There is no good reason for a Resolution - * Multiplier to have a count other than 1. - * Ignore that case. - */ - if (rep->field[i]->report_count != 1) + if (usage->hid != HID_GD_RESOLUTION_MULTIPLIER) continue; - for (j = 0; j < rep->field[i]->maxusage; j++) { - usage = &rep->field[i]->usage[j]; + *report->field[i]->value = value; + update_needed = true; + } + } + + return update_needed; +} - if (usage->hid != HID_GD_RESOLUTION_MULTIPLIER) - continue; +static void hidinput_change_resolution_multipliers(struct hid_device *hid) +{ + struct hid_report_enum *rep_enum; + struct hid_report *rep; + int ret; - *rep->field[i]->value = logical_max; - update_needed = true; + rep_enum = &hid->report_enum[HID_FEATURE_REPORT]; + list_for_each_entry(rep, &rep_enum->report_list, list) { + bool update_needed = __hidinput_change_resolution_multipliers(hid, + rep, true); + + if (update_needed) { + ret = __hid_request(hid, rep, HID_REQ_SET_REPORT); + if (ret) { + __hidinput_change_resolution_multipliers(hid, + rep, false); + return; } } - if (update_needed) - hid_hw_request(hid, rep, HID_REQ_SET_REPORT); } /* refresh our structs */ diff --git a/include/linux/hid.h b/include/linux/hid.h index ac0c70b4ce10..5a24ebfb5b47 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -894,7 +894,7 @@ struct hid_field *hidinput_get_led_field(struct hid_device *hid); unsigned int hidinput_count_leds(struct hid_device *hid); __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code); void hid_output_report(struct hid_report *report, __u8 *data); -void __hid_request(struct hid_device *hid, struct hid_report *rep, int reqtype); +int __hid_request(struct hid_device *hid, struct hid_report *rep, int reqtype); u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags); struct hid_device *hid_allocate_device(void); struct hid_report *hid_register_report(struct hid_device *device, From patchwork Tue Apr 23 15:46:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 10913253 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 80BB9161F for ; Tue, 23 Apr 2019 15:46:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 718D92864A for ; Tue, 23 Apr 2019 15:46:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6608D28849; Tue, 23 Apr 2019 15:46:43 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 10D142864A for ; Tue, 23 Apr 2019 15:46:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728642AbfDWPqd (ORCPT ); Tue, 23 Apr 2019 11:46:33 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56184 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728637AbfDWPqc (ORCPT ); Tue, 23 Apr 2019 11:46:32 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9CB45307D987; Tue, 23 Apr 2019 15:46:32 +0000 (UTC) Received: from plouf.redhat.com (ovpn-116-226.ams2.redhat.com [10.36.116.226]) by smtp.corp.redhat.com (Postfix) with ESMTP id 01EDF5C269; Tue, 23 Apr 2019 15:46:30 +0000 (UTC) From: Benjamin Tissoires To: Jiri Kosina , James Feeney , Peter Hutterer Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, Benjamin Tissoires , stable@vger.kernel.org Subject: [PATCH 2/2] HID: input: fix assignment of .value Date: Tue, 23 Apr 2019 17:46:15 +0200 Message-Id: <20190423154615.18257-2-benjamin.tissoires@redhat.com> In-Reply-To: <20190423154615.18257-1-benjamin.tissoires@redhat.com> References: <20190423154615.18257-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.48]); Tue, 23 Apr 2019 15:46:32 +0000 (UTC) Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The value field is actually an array of .maxfield. We should assign the correct number to the correct usage. Not that we never encounter a device that requires this ATM, but better have the proper code path. Fixes: 2dc702c991e377 ("HID: input: use the Resolution Multiplier for high-resolution scrolling") Cc: stable@vger.kernel.org # v5.0+ Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index fadf76f0a386..6dd0294e1133 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -1580,7 +1580,7 @@ static bool __hidinput_change_resolution_multipliers(struct hid_device *hid, if (usage->hid != HID_GD_RESOLUTION_MULTIPLIER) continue; - *report->field[i]->value = value; + report->field[i]->value[j] = value; update_needed = true; } }