From patchwork Sat Apr 20 11:21:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910223 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 DDA841515 for ; Sat, 20 Apr 2019 11:22:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CE50F28D25 for ; Sat, 20 Apr 2019 11:22:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C2A9228D94; Sat, 20 Apr 2019 11:22:26 +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 74DB528D25 for ; Sat, 20 Apr 2019 11:22:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727991AbfDTLWZ (ORCPT ); Sat, 20 Apr 2019 07:22:25 -0400 Received: from mx1.redhat.com ([209.132.183.28]:60480 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726082AbfDTLWY (ORCPT ); Sat, 20 Apr 2019 07:22:24 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9AABE83F42; Sat, 20 Apr 2019 11:22:24 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 85BDE19C5A; Sat, 20 Apr 2019 11:22:23 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 01/37] HID: quirks: do not blacklist Logitech devices Date: Sat, 20 Apr 2019 13:21:41 +0200 Message-Id: <20190420112217.27590-2-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Sat, 20 Apr 2019 11:22:24 +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 From: Benjamin Tissoires I am actually suggesting people to not populate this list, and I should probably start to apply my advices to myself. The end result means that if your initrd is lacking hid-logitech-dj or hid-logitech-hidpp, but still contains hid-generic, then your keyboard will work during pre-init. Signed-off-by: Benjamin Tissoires Signed-off-by: Hans de Goede --- drivers/hid/hid-quirks.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c index 77ffba48cc73..426753482494 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -464,13 +464,8 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) }, #endif #if IS_ENABLED(CONFIG_HID_LOGITECH_HIDPP) - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_T651) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL) }, #endif -#if IS_ENABLED(CONFIG_HID_LOGITECH_DJ) - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2) }, -#endif #if IS_ENABLED(CONFIG_HID_MAGICMOUSE) { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD) }, From patchwork Sat Apr 20 11:21:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910225 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 0228B17E0 for ; Sat, 20 Apr 2019 11:22:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E772D28D25 for ; Sat, 20 Apr 2019 11:22:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DBFB728D94; Sat, 20 Apr 2019 11:22:27 +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 7D7B928D25 for ; Sat, 20 Apr 2019 11:22:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727992AbfDTLW0 (ORCPT ); Sat, 20 Apr 2019 07:22:26 -0400 Received: from mx1.redhat.com ([209.132.183.28]:42572 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726082AbfDTLW0 (ORCPT ); Sat, 20 Apr 2019 07:22:26 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id F3D39307CDE7; Sat, 20 Apr 2019 11:22:25 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id DD63D19C5A; Sat, 20 Apr 2019 11:22:24 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 02/37] HID: logitech: Stop setting drvdata to NULL on probe failure and remove Date: Sat, 20 Apr 2019 13:21:42 +0200 Message-Id: <20190420112217.27590-3-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.49]); Sat, 20 Apr 2019 11:22:26 +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 From: Benjamin Tissoires There is no need to set drvdata to NULL on probe failure and remove, the driver-core already does this for us. Signed-off-by: Benjamin Tissoires [hdegoede@redhat.com: Isolate Logitech changes into a separate patch] Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-dj.c | 2 -- drivers/hid/hid-logitech-hidpp.c | 8 +++----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 826fa1e1c8d9..a75101293755 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -1094,7 +1094,6 @@ static int logi_dj_probe(struct hid_device *hdev, hid_parse_fail: kfifo_free(&djrcv_dev->notif_fifo); kfree(djrcv_dev); - hid_set_drvdata(hdev, NULL); return retval; } @@ -1145,7 +1144,6 @@ static void logi_dj_remove(struct hid_device *hdev) kfifo_free(&djrcv_dev->notif_fifo); kfree(djrcv_dev); - hid_set_drvdata(hdev, NULL); } static const struct hid_device_id logi_dj_receivers[] = { diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 29395da8f345..965479fe2736 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -3231,15 +3231,15 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) { ret = wtp_allocate(hdev, id); if (ret) - goto allocate_fail; + return ret; } else if (hidpp->quirks & HIDPP_QUIRK_CLASS_M560) { ret = m560_allocate(hdev); if (ret) - goto allocate_fail; + return ret; } else if (hidpp->quirks & HIDPP_QUIRK_CLASS_K400) { ret = k400_allocate(hdev); if (ret) - goto allocate_fail; + return ret; } INIT_WORK(&hidpp->work, delayed_work_cb); @@ -3334,8 +3334,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) sysfs_remove_group(&hdev->dev.kobj, &ps_attribute_group); cancel_work_sync(&hidpp->work); mutex_destroy(&hidpp->send_mutex); -allocate_fail: - hid_set_drvdata(hdev, NULL); return ret; } From patchwork Sat Apr 20 11:21:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910227 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 7957117E0 for ; Sat, 20 Apr 2019 11:22:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 69BE128D25 for ; Sat, 20 Apr 2019 11:22:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5E3DD28D94; Sat, 20 Apr 2019 11:22:29 +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 0BA7C28D25 for ; Sat, 20 Apr 2019 11:22:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727993AbfDTLW2 (ORCPT ); Sat, 20 Apr 2019 07:22:28 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56612 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726082AbfDTLW1 (ORCPT ); Sat, 20 Apr 2019 07:22:27 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5594A307FBCB; Sat, 20 Apr 2019 11:22:27 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 40F2719C5A; Sat, 20 Apr 2019 11:22:26 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 03/37] HID: logitech-dj: reshuffle logi_dj_recv_forward_* Date: Sat, 20 Apr 2019 13:21:43 +0200 Message-Id: <20190420112217.27590-4-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.41]); Sat, 20 Apr 2019 11:22:27 +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 From: Benjamin Tissoires logi_dj_recv_forward_report() was only intended for DJ reports. logi_dj_recv_forward_hidpp() is more generic at forwarding random HID reports. So rename logi_dj_recv_forward_report() into logi_dj_recv_forward_dj() and logi_dj_recv_forward_hidpp() into logi_dj_recv_forward_report(). Signed-off-by: Benjamin Tissoires Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-dj.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index a75101293755..f2e994d11b70 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -552,8 +552,8 @@ static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev, } } -static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev, - struct dj_report *dj_report) +static void logi_dj_recv_forward_dj(struct dj_receiver_dev *djrcv_dev, + struct dj_report *dj_report) { /* We are called from atomic context (tasklet && djrcv->lock held) */ struct dj_device *dj_device; @@ -573,8 +573,8 @@ static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev, } } -static void logi_dj_recv_forward_hidpp(struct dj_device *dj_dev, u8 *data, - int size) +static void logi_dj_recv_forward_report(struct dj_device *dj_dev, u8 *data, + int size) { /* We are called from atomic context (tasklet && djrcv->lock held) */ if (hid_input_report(dj_dev->hdev, HID_INPUT_REPORT, data, size, 1)) @@ -893,7 +893,7 @@ static int logi_dj_dj_event(struct hid_device *hdev, } break; default: - logi_dj_recv_forward_report(djrcv_dev, dj_report); + logi_dj_recv_forward_dj(djrcv_dev, dj_report); } out: @@ -948,8 +948,8 @@ static int logi_dj_hidpp_event(struct hid_device *hdev, /* received an event for an unknown device, bail out */ goto out; - logi_dj_recv_forward_hidpp(djrcv_dev->paired_dj_devices[device_index], - data, size); + logi_dj_recv_forward_report(djrcv_dev->paired_dj_devices[device_index], + data, size); out: spin_unlock_irqrestore(&djrcv_dev->lock, flags); From patchwork Sat Apr 20 11:21:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910229 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 28E901515 for ; Sat, 20 Apr 2019 11:22:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 19A2528D25 for ; Sat, 20 Apr 2019 11:22:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0E3BD28D94; Sat, 20 Apr 2019 11:22: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 A6A3C28D25 for ; Sat, 20 Apr 2019 11:22:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728001AbfDTLW3 (ORCPT ); Sat, 20 Apr 2019 07:22:29 -0400 Received: from mx1.redhat.com ([209.132.183.28]:60488 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726082AbfDTLW2 (ORCPT ); Sat, 20 Apr 2019 07:22:28 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id ACEA6804F2; Sat, 20 Apr 2019 11:22:28 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9858019C5A; Sat, 20 Apr 2019 11:22:27 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 04/37] HID: logitech-dj: fix variable naming in logi_dj_hidpp_event Date: Sat, 20 Apr 2019 13:21:44 +0200 Message-Id: <20190420112217.27590-5-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Sat, 20 Apr 2019 11:22:28 +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 From: Benjamin Tissoires we are not dealing with a dj_report but a hidpp_event. We don't need all of the struct description in this function, but having the variable named `dj_report` feels weird. Signed-off-by: Benjamin Tissoires Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-dj.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index f2e994d11b70..6408ef13e909 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -108,6 +108,13 @@ struct dj_report { u8 report_params[DJREPORT_SHORT_LENGTH - 3]; }; +struct hidpp_event { + u8 report_id; + u8 device_index; + u8 sub_id; + u8 params[HIDPP_REPORT_LONG_LENGTH - 3U]; +} __packed; + struct dj_receiver_dev { struct hid_device *hdev; struct dj_device *paired_dj_devices[DJ_MAX_PAIRED_DEVICES + @@ -907,9 +914,9 @@ static int logi_dj_hidpp_event(struct hid_device *hdev, int size) { struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev); - struct dj_report *dj_report = (struct dj_report *) data; + struct hidpp_event *hidpp_report = (struct hidpp_event *) data; unsigned long flags; - u8 device_index = dj_report->device_index; + u8 device_index = hidpp_report->device_index; if (device_index == HIDPP_RECEIVER_INDEX) { /* special case were the device wants to know its unifying @@ -938,7 +945,7 @@ static int logi_dj_hidpp_event(struct hid_device *hdev, * so ignore those reports too. */ dev_err(&hdev->dev, "%s: invalid device index:%d\n", - __func__, dj_report->device_index); + __func__, hidpp_report->device_index); return false; } From patchwork Sat Apr 20 11:21:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910231 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 1D7A117E0 for ; Sat, 20 Apr 2019 11:22:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0EE6B28D25 for ; Sat, 20 Apr 2019 11:22:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0303028D94; Sat, 20 Apr 2019 11:22:31 +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 A85EE28D25 for ; Sat, 20 Apr 2019 11:22:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728021AbfDTLWa (ORCPT ); Sat, 20 Apr 2019 07:22:30 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49864 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726082AbfDTLWa (ORCPT ); Sat, 20 Apr 2019 07:22:30 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 11E3B3082E72; Sat, 20 Apr 2019 11:22:30 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id EF15A19C5A; Sat, 20 Apr 2019 11:22:28 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 05/37] HID: logitech-dj: use BIT() macro for RF Report types Date: Sat, 20 Apr 2019 13:21:45 +0200 Message-Id: <20190420112217.27590-6-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.46]); Sat, 20 Apr 2019 11:22:30 +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 From: Benjamin Tissoires Use BIT() macro for RF Report types. Signed-off-by: Benjamin Tissoires Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-dj.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 6408ef13e909..b1ae2d9c5ddc 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -94,12 +94,12 @@ #define REPORT_TYPE_LEDS 0x0E /* RF Report types bitfield */ -#define STD_KEYBOARD 0x00000002 -#define STD_MOUSE 0x00000004 -#define MULTIMEDIA 0x00000008 -#define POWER_KEYS 0x00000010 -#define MEDIA_CENTER 0x00000100 -#define KBD_LEDS 0x00004000 +#define STD_KEYBOARD BIT(1) +#define STD_MOUSE BIT(2) +#define MULTIMEDIA BIT(3) +#define POWER_KEYS BIT(4) +#define MEDIA_CENTER BIT(8) +#define KBD_LEDS BIT(14) struct dj_report { u8 report_id; From patchwork Sat Apr 20 11:21:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910233 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 C26C717E0 for ; Sat, 20 Apr 2019 11:22:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B279C28D25 for ; Sat, 20 Apr 2019 11:22:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A6CFF28D94; Sat, 20 Apr 2019 11:22:32 +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 5462128D25 for ; Sat, 20 Apr 2019 11:22:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728024AbfDTLWb (ORCPT ); Sat, 20 Apr 2019 07:22:31 -0400 Received: from mx1.redhat.com ([209.132.183.28]:37588 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726082AbfDTLWb (ORCPT ); Sat, 20 Apr 2019 07:22:31 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 703D47F7B1; Sat, 20 Apr 2019 11:22:31 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 53BB419C5A; Sat, 20 Apr 2019 11:22:30 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 06/37] HID: logitech-dj: declare and use a few HID++ 1.0 constants Date: Sat, 20 Apr 2019 13:21:46 +0200 Message-Id: <20190420112217.27590-7-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Sat, 20 Apr 2019 11:22:31 +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 From: Benjamin Tissoires For the non DJ receivers, we are going to need to re-use those constants, better have them properly defined. Signed-off-by: Benjamin Tissoires Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-dj.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index b1ae2d9c5ddc..eafe75d55664 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -74,7 +74,6 @@ /* Device Un-Paired Notification */ #define REPORT_TYPE_NOTIF_DEVICE_UNPAIRED 0x40 - /* Connection Status Notification */ #define REPORT_TYPE_NOTIF_CONNECTION_STATUS 0x42 #define CONNECTION_STATUS_PARAM_STATUS 0x00 @@ -101,6 +100,10 @@ #define MEDIA_CENTER BIT(8) #define KBD_LEDS BIT(14) +#define HIDPP_GET_LONG_REGISTER 0x83 +#define HIDPP_REG_PAIRING_INFORMATION 0xB5 +#define HIDPP_PAIRING_INFORMATION 0x20 + struct dj_report { u8 report_id; u8 device_index; @@ -703,8 +706,14 @@ static void logi_dj_ll_close(struct hid_device *hid) * Register 0xB5 is "pairing information". It is solely intended for the * receiver, so do not overwrite the device index. */ -static u8 unifying_pairing_query[] = {0x10, 0xff, 0x83, 0xb5}; -static u8 unifying_pairing_answer[] = {0x11, 0xff, 0x83, 0xb5}; +static u8 unifying_pairing_query[] = { REPORT_ID_HIDPP_SHORT, + HIDPP_RECEIVER_INDEX, + HIDPP_GET_LONG_REGISTER, + HIDPP_REG_PAIRING_INFORMATION }; +static u8 unifying_pairing_answer[] = { REPORT_ID_HIDPP_LONG, + HIDPP_RECEIVER_INDEX, + HIDPP_GET_LONG_REGISTER, + HIDPP_REG_PAIRING_INFORMATION }; static int logi_dj_ll_raw_request(struct hid_device *hid, unsigned char reportnum, __u8 *buf, From patchwork Sat Apr 20 11:21:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910235 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 AE9311515 for ; Sat, 20 Apr 2019 11:22:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9D76F28D25 for ; Sat, 20 Apr 2019 11:22:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 91D4328D94; Sat, 20 Apr 2019 11:22:34 +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 194B728D25 for ; Sat, 20 Apr 2019 11:22:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728039AbfDTLWd (ORCPT ); Sat, 20 Apr 2019 07:22:33 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49404 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726082AbfDTLWd (ORCPT ); Sat, 20 Apr 2019 07:22:33 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C1DF6307D849; Sat, 20 Apr 2019 11:22:32 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id AD86419C5B; Sat, 20 Apr 2019 11:22:31 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 07/37] HID: logitech-dj: remove USB dependency Date: Sat, 20 Apr 2019 13:21:47 +0200 Message-Id: <20190420112217.27590-8-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.48]); Sat, 20 Apr 2019 11:22: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 From: Benjamin Tissoires It is better to rely on the actual content of the report descriptors to enable or not a HID interface. While at it, remove the other USB dependency to have a fully USB agnostic driver. Signed-off-by: Benjamin Tissoires Signed-off-by: Hans de Goede --- Changes in v3 (HdG): -Fix style of some multi-line comments --- drivers/hid/hid-logitech-dj.c | 68 ++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index eafe75d55664..23d3e039ebbb 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -25,8 +25,8 @@ #include #include #include -#include #include +#include #include #include "hid-ids.h" @@ -378,8 +378,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, { /* Called in delayed work context */ struct hid_device *djrcv_hdev = djrcv_dev->hdev; - struct usb_interface *intf = to_usb_interface(djrcv_hdev->dev.parent); - struct usb_device *usbdev = interface_to_usbdev(intf); struct hid_device *dj_hiddev; struct dj_device *dj_dev; @@ -412,7 +410,7 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, dj_hiddev->dev.parent = &djrcv_hdev->dev; dj_hiddev->bus = BUS_USB; - dj_hiddev->vendor = le16_to_cpu(usbdev->descriptor.idVendor); + dj_hiddev->vendor = djrcv_hdev->vendor; dj_hiddev->product = (dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_MSB] << 8) | @@ -423,7 +421,7 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, dj_hiddev->group = HID_GROUP_LOGITECH_DJ_DEVICE; - usb_make_path(usbdev, dj_hiddev->phys, sizeof(dj_hiddev->phys)); + memcpy(dj_hiddev->phys, djrcv_hdev->phys, sizeof(djrcv_hdev->phys)); snprintf(tmpstr, sizeof(tmpstr), ":%d", dj_report->device_index); strlcat(dj_hiddev->phys, tmpstr, sizeof(dj_hiddev->phys)); @@ -1008,23 +1006,44 @@ static int logi_dj_raw_event(struct hid_device *hdev, static int logi_dj_probe(struct hid_device *hdev, const struct hid_device_id *id) { - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); + struct hid_report_enum *rep_enum; + struct hid_report *rep; struct dj_receiver_dev *djrcv_dev; + bool has_hidpp = false; int retval; - dbg_hid("%s called for ifnum %d\n", __func__, - intf->cur_altsetting->desc.bInterfaceNumber); + /* + * Call to usbhid to fetch the HID descriptors of the current + * interface subsequently call to the hid/hid-core to parse the + * fetched descriptors. + */ + retval = hid_parse(hdev); + if (retval) { + dev_err(&hdev->dev, + "%s:parse failed\n", __func__); + return retval; + } - /* Ignore interfaces 0 and 1, they will not carry any data, dont create - * any hid_device for them */ - if (intf->cur_altsetting->desc.bInterfaceNumber != - LOGITECH_DJ_INTERFACE_NUMBER) { - dbg_hid("%s: ignoring ifnum %d\n", __func__, - intf->cur_altsetting->desc.bInterfaceNumber); - return -ENODEV; + rep_enum = &hdev->report_enum[HID_INPUT_REPORT]; + + /* + * Check for the HID++ application. + * Note: we should theoretically check for HID++ and DJ + * collections, but this will do. + */ + list_for_each_entry(rep, &rep_enum->report_list, list) { + if (rep->application == 0xff000001) + has_hidpp = true; } - /* Treat interface 2 */ + /* + * Ignore interfaces without DJ/HID++ collection, they will not carry + * any data, dont create any hid_device for them. + */ + if (!has_hidpp) + return -ENODEV; + + /* Treat DJ/HID++ interface */ djrcv_dev = kzalloc(sizeof(struct dj_receiver_dev), GFP_KERNEL); if (!djrcv_dev) { @@ -1045,22 +1064,6 @@ static int logi_dj_probe(struct hid_device *hdev, } hid_set_drvdata(hdev, djrcv_dev); - /* Call to usbhid to fetch the HID descriptors of interface 2 and - * subsequently call to the hid/hid-core to parse the fetched - * descriptors, this will in turn create the hidraw and hiddev nodes - * for interface 2 of the receiver */ - retval = hid_parse(hdev); - if (retval) { - dev_err(&hdev->dev, - "%s:parse of interface 2 failed\n", __func__); - goto hid_parse_fail; - } - - if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, REPORT_ID_DJ_SHORT, - 0, DJREPORT_SHORT_LENGTH - 1)) { - retval = -ENODEV; - goto hid_parse_fail; - } /* Starts the usb device and connects to upper interfaces hiddev and * hidraw */ @@ -1107,7 +1110,6 @@ static int logi_dj_probe(struct hid_device *hdev, hid_hw_stop(hdev); hid_hw_start_fail: -hid_parse_fail: kfifo_free(&djrcv_dev->notif_fifo); kfree(djrcv_dev); return retval; From patchwork Sat Apr 20 11:21:48 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910237 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 0A7CE1515 for ; Sat, 20 Apr 2019 11:22:36 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ECD0F28D25 for ; Sat, 20 Apr 2019 11:22:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E11A928D94; Sat, 20 Apr 2019 11:22:35 +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 243CB28D25 for ; Sat, 20 Apr 2019 11:22:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728042AbfDTLWe (ORCPT ); Sat, 20 Apr 2019 07:22:34 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49766 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726082AbfDTLWe (ORCPT ); Sat, 20 Apr 2019 07:22:34 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 27FCF72652; Sat, 20 Apr 2019 11:22:34 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 121FB19C5B; Sat, 20 Apr 2019 11:22:32 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 08/37] HID: logitech-dj: do not schedule the dj report itself Date: Sat, 20 Apr 2019 13:21:48 +0200 Message-Id: <20190420112217.27590-9-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Sat, 20 Apr 2019 11:22:34 +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 From: Benjamin Tissoires This is a preparatory patch for handling non DJ (HID++ only) receivers, through this module. We can not use the dj_report in the delayed work callback as the HID++ notifications are different both in size and meaning. There should be no functional change. Signed-off-by: Benjamin Tissoires Signed-off-by: Hans de Goede --- Changes in v3 (HdG): -Fix style of some multi-line comments --- drivers/hid/hid-logitech-dj.c | 136 +++++++++++++++++++++------------- 1 file changed, 85 insertions(+), 51 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 23d3e039ebbb..628c3bd87a0d 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -31,7 +31,7 @@ #include "hid-ids.h" #define DJ_MAX_PAIRED_DEVICES 6 -#define DJ_MAX_NUMBER_NOTIFICATIONS 8 +#define DJ_MAX_NUMBER_NOTIFS 8 #define DJ_RECEIVER_INDEX 0 #define DJ_DEVICE_INDEX_MIN 1 #define DJ_DEVICE_INDEX_MAX 6 @@ -135,6 +135,19 @@ struct dj_device { u8 device_index; }; +#define WORKITEM_TYPE_EMPTY 0 +#define WORKITEM_TYPE_PAIRED 1 +#define WORKITEM_TYPE_UNPAIRED 2 +#define WORKITEM_TYPE_UNKNOWN 255 + +struct dj_workitem { + u8 type; /* WORKITEM_TYPE_* */ + u8 device_index; + u8 quad_id_msb; + u8 quad_id_lsb; + u32 reports_supported; +}; + /* Keyboard descriptor (1) */ static const char kbd_descriptor[] = { 0x05, 0x01, /* USAGE_PAGE (generic Desktop) */ @@ -353,15 +366,15 @@ static struct hid_ll_driver logi_dj_ll_driver; static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev); static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev, - struct dj_report *dj_report) + struct dj_workitem *workitem) { /* Called in delayed work context */ struct dj_device *dj_dev; unsigned long flags; spin_lock_irqsave(&djrcv_dev->lock, flags); - dj_dev = djrcv_dev->paired_dj_devices[dj_report->device_index]; - djrcv_dev->paired_dj_devices[dj_report->device_index] = NULL; + dj_dev = djrcv_dev->paired_dj_devices[workitem->device_index]; + djrcv_dev->paired_dj_devices[workitem->device_index] = NULL; spin_unlock_irqrestore(&djrcv_dev->lock, flags); if (dj_dev != NULL) { @@ -374,26 +387,20 @@ static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev, } static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, - struct dj_report *dj_report) + struct dj_workitem *workitem) { /* Called in delayed work context */ struct hid_device *djrcv_hdev = djrcv_dev->hdev; struct hid_device *dj_hiddev; struct dj_device *dj_dev; + u8 device_index = workitem->device_index; /* Device index goes from 1 to 6, we need 3 bytes to store the * semicolon, the index, and a null terminator */ unsigned char tmpstr[3]; - if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] & - SPFUNCTION_DEVICE_LIST_EMPTY) { - dbg_hid("%s: device list is empty\n", __func__); - djrcv_dev->querying_devices = false; - return; - } - - if (djrcv_dev->paired_dj_devices[dj_report->device_index]) { + if (djrcv_dev->paired_dj_devices[device_index]) { /* The device is already known. No need to reallocate it. */ dbg_hid("%s: device is already known\n", __func__); return; @@ -411,10 +418,8 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, dj_hiddev->dev.parent = &djrcv_hdev->dev; dj_hiddev->bus = BUS_USB; dj_hiddev->vendor = djrcv_hdev->vendor; - dj_hiddev->product = - (dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_MSB] - << 8) | - dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_LSB]; + dj_hiddev->product = (workitem->quad_id_msb << 8) | + workitem->quad_id_lsb; snprintf(dj_hiddev->name, sizeof(dj_hiddev->name), "Logitech Unifying Device. Wireless PID:%04x", dj_hiddev->product); @@ -422,7 +427,7 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, dj_hiddev->group = HID_GROUP_LOGITECH_DJ_DEVICE; memcpy(dj_hiddev->phys, djrcv_hdev->phys, sizeof(djrcv_hdev->phys)); - snprintf(tmpstr, sizeof(tmpstr), ":%d", dj_report->device_index); + snprintf(tmpstr, sizeof(tmpstr), ":%d", device_index); strlcat(dj_hiddev->phys, tmpstr, sizeof(dj_hiddev->phys)); dj_dev = kzalloc(sizeof(struct dj_device), GFP_KERNEL); @@ -433,14 +438,13 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, goto dj_device_allocate_fail; } - dj_dev->reports_supported = get_unaligned_le32( - dj_report->report_params + DEVICE_PAIRED_RF_REPORT_TYPE); + dj_dev->reports_supported = workitem->reports_supported; dj_dev->hdev = dj_hiddev; dj_dev->dj_receiver_dev = djrcv_dev; - dj_dev->device_index = dj_report->device_index; + dj_dev->device_index = device_index; dj_hiddev->driver_data = dj_dev; - djrcv_dev->paired_dj_devices[dj_report->device_index] = dj_dev; + djrcv_dev->paired_dj_devices[device_index] = dj_dev; if (hid_add_device(dj_hiddev)) { dev_err(&djrcv_hdev->dev, "%s: failed adding dj_device\n", @@ -451,7 +455,7 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, return; hid_add_device_fail: - djrcv_dev->paired_dj_devices[dj_report->device_index] = NULL; + djrcv_dev->paired_dj_devices[device_index] = NULL; kfree(dj_dev); dj_device_allocate_fail: hid_destroy_device(dj_hiddev); @@ -462,7 +466,7 @@ static void delayedwork_callback(struct work_struct *work) struct dj_receiver_dev *djrcv_dev = container_of(work, struct dj_receiver_dev, work); - struct dj_report dj_report; + struct dj_workitem workitem; unsigned long flags; int count; int retval; @@ -471,10 +475,9 @@ static void delayedwork_callback(struct work_struct *work) spin_lock_irqsave(&djrcv_dev->lock, flags); - count = kfifo_out(&djrcv_dev->notif_fifo, &dj_report, - sizeof(struct dj_report)); + count = kfifo_out(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem)); - if (count != sizeof(struct dj_report)) { + if (count != sizeof(workitem)) { dev_err(&djrcv_dev->hdev->dev, "%s: workitem triggered without " "notifications available\n", __func__); spin_unlock_irqrestore(&djrcv_dev->lock, flags); @@ -490,12 +493,54 @@ static void delayedwork_callback(struct work_struct *work) spin_unlock_irqrestore(&djrcv_dev->lock, flags); - switch (dj_report.report_type) { - case REPORT_TYPE_NOTIF_DEVICE_PAIRED: - logi_dj_recv_add_djhid_device(djrcv_dev, &dj_report); + switch (workitem.type) { + case WORKITEM_TYPE_PAIRED: + logi_dj_recv_add_djhid_device(djrcv_dev, &workitem); break; + case WORKITEM_TYPE_UNPAIRED: + logi_dj_recv_destroy_djhid_device(djrcv_dev, &workitem); + break; + case WORKITEM_TYPE_UNKNOWN: + retval = logi_dj_recv_query_paired_devices(djrcv_dev); + if (retval) { + dev_err(&djrcv_dev->hdev->dev, + "%s: logi_dj_recv_query_paired_devices error: %d\n", + __func__, retval); + } + break; + case WORKITEM_TYPE_EMPTY: + dbg_hid("%s: device list is empty\n", __func__); + break; + } +} + +static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev, + struct dj_report *dj_report) +{ + /* We are called from atomic context (tasklet && djrcv->lock held) */ + struct dj_workitem workitem = { + .device_index = dj_report->device_index, + }; + + switch (dj_report->report_type) { + case REPORT_TYPE_NOTIF_DEVICE_PAIRED: + workitem.type = WORKITEM_TYPE_PAIRED; + if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] & + SPFUNCTION_DEVICE_LIST_EMPTY) { + workitem.type = WORKITEM_TYPE_EMPTY; + break; + } + /* fall-through */ case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED: - logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report); + workitem.quad_id_msb = + dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_MSB]; + workitem.quad_id_lsb = + dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_LSB]; + workitem.reports_supported = get_unaligned_le32( + dj_report->report_params + + DEVICE_PAIRED_RF_REPORT_TYPE); + if (dj_report->report_type == REPORT_TYPE_NOTIF_DEVICE_UNPAIRED) + workitem.type = WORKITEM_TYPE_UNPAIRED; break; default: /* A normal report (i. e. not belonging to a pair/unpair notification) @@ -505,28 +550,17 @@ static void delayedwork_callback(struct work_struct *work) * to this dj_device never arrived to this driver. The reason is that * hid-core discards all packets coming from a device while probe() is * executing. */ - if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) { - /* ok, we don't know the device, just re-ask the - * receiver for the list of connected devices. */ - retval = logi_dj_recv_query_paired_devices(djrcv_dev); - if (!retval) { - /* everything went fine, so just leave */ - break; - } - dev_err(&djrcv_dev->hdev->dev, - "%s:logi_dj_recv_query_paired_devices " - "error:%d\n", __func__, retval); + if (!djrcv_dev->paired_dj_devices[dj_report->device_index]) { + /* + * ok, we don't know the device, just re-ask the + * receiver for the list of connected devices in + * the delayed work callback. + */ + workitem.type = WORKITEM_TYPE_UNKNOWN; } - dbg_hid("%s: unexpected report type\n", __func__); } -} - -static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev, - struct dj_report *dj_report) -{ - /* We are called from atomic context (tasklet && djrcv->lock held) */ - kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); + kfifo_in(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem)); if (schedule_work(&djrcv_dev->work) == 0) { dbg_hid("%s: did not schedule the work item, was already " @@ -1055,7 +1089,7 @@ static int logi_dj_probe(struct hid_device *hdev, INIT_WORK(&djrcv_dev->work, delayedwork_callback); spin_lock_init(&djrcv_dev->lock); if (kfifo_alloc(&djrcv_dev->notif_fifo, - DJ_MAX_NUMBER_NOTIFICATIONS * sizeof(struct dj_report), + DJ_MAX_NUMBER_NOTIFS * sizeof(struct dj_workitem), GFP_KERNEL)) { dev_err(&hdev->dev, "%s:failed allocating notif_fifo\n", __func__); From patchwork Sat Apr 20 11:21:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910239 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 8025517EE for ; Sat, 20 Apr 2019 11:22:36 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7188428D25 for ; Sat, 20 Apr 2019 11:22:36 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6622928D94; Sat, 20 Apr 2019 11:22:36 +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 20BE728D25 for ; Sat, 20 Apr 2019 11:22:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728046AbfDTLWf (ORCPT ); Sat, 20 Apr 2019 07:22:35 -0400 Received: from mx1.redhat.com ([209.132.183.28]:46694 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726082AbfDTLWf (ORCPT ); Sat, 20 Apr 2019 07:22:35 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7CD0D308212A; Sat, 20 Apr 2019 11:22:35 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 692C919C5B; Sat, 20 Apr 2019 11:22:34 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 09/37] HID: logitech-dj: remove unused querying_devices variable Date: Sat, 20 Apr 2019 13:21:49 +0200 Message-Id: <20190420112217.27590-10-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Sat, 20 Apr 2019 11:22:35 +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 querying_devices is never set, so it can safely be removed. Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-dj.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 628c3bd87a0d..9e5aac74808b 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -125,7 +125,6 @@ struct dj_receiver_dev { struct work_struct work; struct kfifo notif_fifo; spinlock_t lock; - bool querying_devices; }; struct dj_device { @@ -653,10 +652,6 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) struct dj_report *dj_report; int retval; - /* no need to protect djrcv_dev->querying_devices */ - if (djrcv_dev->querying_devices) - return 0; - dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); if (!dj_report) return -ENOMEM; From patchwork Sat Apr 20 11:21:50 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910241 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 E95081515 for ; Sat, 20 Apr 2019 11:22:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DA44428D25 for ; Sat, 20 Apr 2019 11:22:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CEA0828D94; Sat, 20 Apr 2019 11:22:37 +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 7C64028D25 for ; Sat, 20 Apr 2019 11:22:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728053AbfDTLWh (ORCPT ); Sat, 20 Apr 2019 07:22:37 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56632 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726082AbfDTLWg (ORCPT ); Sat, 20 Apr 2019 07:22:36 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D69833199361; Sat, 20 Apr 2019 11:22:36 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id BFC4519C5B; Sat, 20 Apr 2019 11:22:35 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 10/37] HID: logitech-dj: protect the paired_dj_devices access in add_djhid_dev with the lock Date: Sat, 20 Apr 2019 13:21:50 +0200 Message-Id: <20190420112217.27590-11-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.41]); Sat, 20 Apr 2019 11:22:36 +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 This protects against logi_dj_recv_add_djhid_device, adding a device to paired_dj_devices from the delayedwork callback, racing versus logi_dj_raw_event trying to access that device. Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-dj.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 9e5aac74808b..e9a165790482 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -393,12 +393,14 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, struct hid_device *dj_hiddev; struct dj_device *dj_dev; u8 device_index = workitem->device_index; + unsigned long flags; /* Device index goes from 1 to 6, we need 3 bytes to store the * semicolon, the index, and a null terminator */ unsigned char tmpstr[3]; + /* We are the only one ever adding a device, no need to lock */ if (djrcv_dev->paired_dj_devices[device_index]) { /* The device is already known. No need to reallocate it. */ dbg_hid("%s: device is already known\n", __func__); @@ -443,7 +445,9 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, dj_dev->device_index = device_index; dj_hiddev->driver_data = dj_dev; + spin_lock_irqsave(&djrcv_dev->lock, flags); djrcv_dev->paired_dj_devices[device_index] = dj_dev; + spin_unlock_irqrestore(&djrcv_dev->lock, flags); if (hid_add_device(dj_hiddev)) { dev_err(&djrcv_hdev->dev, "%s: failed adding dj_device\n", @@ -454,7 +458,9 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, return; hid_add_device_fail: + spin_lock_irqsave(&djrcv_dev->lock, flags); djrcv_dev->paired_dj_devices[device_index] = NULL; + spin_unlock_irqrestore(&djrcv_dev->lock, flags); kfree(dj_dev); dj_device_allocate_fail: hid_destroy_device(dj_hiddev); From patchwork Sat Apr 20 11:21:51 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910243 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 D72E21515 for ; Sat, 20 Apr 2019 11:22:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C775B28D25 for ; Sat, 20 Apr 2019 11:22:39 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BB95128D94; Sat, 20 Apr 2019 11:22:39 +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 510BE28D25 for ; Sat, 20 Apr 2019 11:22:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728054AbfDTLWi (ORCPT ); Sat, 20 Apr 2019 07:22:38 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56638 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726082AbfDTLWi (ORCPT ); Sat, 20 Apr 2019 07:22:38 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 39769319937A; Sat, 20 Apr 2019 11:22:38 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 24B3219C5B; Sat, 20 Apr 2019 11:22:36 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 11/37] HID: logitech-dj: rename dj_receiver_dev.hdev to dj_receiver_dev.hidpp Date: Sat, 20 Apr 2019 13:21:51 +0200 Message-Id: <20190420112217.27590-12-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.41]); Sat, 20 Apr 2019 11:22:38 +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 For the upcoming non-unifying receiver support, we are going to bind to all USB-interfaces of a receiver, sharing a single struct dj_receiver_dev between the interfaces. This means that dj_receiver_dev will contain multiple pointers to a struct hid_device. Rename the current hdev member to hidpp to prepare for this. While at it switch dev_err calls which we are touching anyways from dev_err to hid_err. Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-dj.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index e9a165790482..6244fd41b153 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -119,7 +119,7 @@ struct hidpp_event { } __packed; struct dj_receiver_dev { - struct hid_device *hdev; + struct hid_device *hidpp; struct dj_device *paired_dj_devices[DJ_MAX_PAIRED_DEVICES + DJ_DEVICE_INDEX_MIN]; struct work_struct work; @@ -380,7 +380,7 @@ static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev, hid_destroy_device(dj_dev->hdev); kfree(dj_dev); } else { - dev_err(&djrcv_dev->hdev->dev, "%s: can't destroy a NULL device\n", + hid_err(djrcv_dev->hidpp, "%s: can't destroy a NULL device\n", __func__); } } @@ -389,7 +389,7 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, struct dj_workitem *workitem) { /* Called in delayed work context */ - struct hid_device *djrcv_hdev = djrcv_dev->hdev; + struct hid_device *djrcv_hdev = djrcv_dev->hidpp; struct hid_device *dj_hiddev; struct dj_device *dj_dev; u8 device_index = workitem->device_index; @@ -483,8 +483,7 @@ static void delayedwork_callback(struct work_struct *work) count = kfifo_out(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem)); if (count != sizeof(workitem)) { - dev_err(&djrcv_dev->hdev->dev, "%s: workitem triggered without " - "notifications available\n", __func__); + hid_err(djrcv_dev->hidpp, "delayedwork queued without workitems available\n"); spin_unlock_irqrestore(&djrcv_dev->lock, flags); return; } @@ -508,8 +507,7 @@ static void delayedwork_callback(struct work_struct *work) case WORKITEM_TYPE_UNKNOWN: retval = logi_dj_recv_query_paired_devices(djrcv_dev); if (retval) { - dev_err(&djrcv_dev->hdev->dev, - "%s: logi_dj_recv_query_paired_devices error: %d\n", + hid_err(djrcv_dev->hidpp, "%s: logi_dj_recv_query_paired_devices error: %d\n", __func__, retval); } break; @@ -631,7 +629,7 @@ static void logi_dj_recv_forward_report(struct dj_device *dj_dev, u8 *data, static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, struct dj_report *dj_report) { - struct hid_device *hdev = djrcv_dev->hdev; + struct hid_device *hdev = djrcv_dev->hidpp; struct hid_report *report; struct hid_report_enum *output_report_enum; u8 *data = (u8 *)(&dj_report->device_index); @@ -673,7 +671,7 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, unsigned timeout) { - struct hid_device *hdev = djrcv_dev->hdev; + struct hid_device *hdev = djrcv_dev->hidpp; struct dj_report *dj_report; u8 *buf; int retval; @@ -770,7 +768,7 @@ static int logi_dj_ll_raw_request(struct hid_device *hid, buf[4] = (buf[4] & 0xf0) | (djdev->device_index - 1); else buf[1] = djdev->device_index; - return hid_hw_raw_request(djrcv_dev->hdev, reportnum, buf, + return hid_hw_raw_request(djrcv_dev->hidpp, reportnum, buf, count, report_type, reqtype); } @@ -788,7 +786,7 @@ static int logi_dj_ll_raw_request(struct hid_device *hid, out_buf[1] = djdev->device_index; memcpy(out_buf + 2, buf, count); - ret = hid_hw_raw_request(djrcv_dev->hdev, out_buf[0], out_buf, + ret = hid_hw_raw_request(djrcv_dev->hidpp, out_buf[0], out_buf, DJREPORT_SHORT_LENGTH, report_type, reqtype); kfree(out_buf); @@ -1086,7 +1084,7 @@ static int logi_dj_probe(struct hid_device *hdev, "%s:failed allocating dj_receiver_dev\n", __func__); return -ENOMEM; } - djrcv_dev->hdev = hdev; + djrcv_dev->hidpp = hdev; INIT_WORK(&djrcv_dev->work, delayedwork_callback); spin_lock_init(&djrcv_dev->lock); if (kfifo_alloc(&djrcv_dev->notif_fifo, From patchwork Sat Apr 20 11:21:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910245 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 8257A17E0 for ; Sat, 20 Apr 2019 11:22:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7189828D25 for ; Sat, 20 Apr 2019 11:22:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 65D9128D94; Sat, 20 Apr 2019 11:22: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 B0E2228D25 for ; Sat, 20 Apr 2019 11:22:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728065AbfDTLWm (ORCPT ); Sat, 20 Apr 2019 07:22:42 -0400 Received: from mx1.redhat.com ([209.132.183.28]:39520 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726082AbfDTLWm (ORCPT ); Sat, 20 Apr 2019 07:22:42 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A8D00C069B2C; Sat, 20 Apr 2019 11:22:41 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7DC4819C5B; Sat, 20 Apr 2019 11:22:38 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 12/37] HID: logitech-dj: support sharing struct dj_receiver_dev between USB-interfaces Date: Sat, 20 Apr 2019 13:21:52 +0200 Message-Id: <20190420112217.27590-13-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Sat, 20 Apr 2019 11:22:41 +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 dj/HID++ receivers are really a single logical entity, but for BIOS/Windows compatibility they have multiple USB interfaces. For the upcoming non-unifying receiver support, we need to listen for events from / bind to all USB-interfaces of the receiver. This commit add support to the logitech-dj code for creating a single dj_receiver_dev struct for all interfaces belonging to a single USB-device / receiver, in preparation for adding non-unifying receiver support. Signed-off-by: Hans de Goede --- Changes in v2: -Do not call hid_err(djrcv_dev->hidpp, ... in delayedwork_callback in a case where djrcv_dev->hidpp may be NULL, instead use pr_warn in this special case. The move from err -> warn is intentional since this may happen under normal circumstances (input received during enumeration) --- drivers/hid/hid-logitech-dj.c | 176 ++++++++++++++++++++++++++++------ 1 file changed, 149 insertions(+), 27 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 6244fd41b153..a3ad100e9dc9 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -119,11 +119,16 @@ struct hidpp_event { } __packed; struct dj_receiver_dev { + struct hid_device *mouse; + struct hid_device *keyboard; struct hid_device *hidpp; struct dj_device *paired_dj_devices[DJ_MAX_PAIRED_DEVICES + DJ_DEVICE_INDEX_MIN]; + struct list_head list; + struct kref kref; struct work_struct work; struct kfifo notif_fifo; + bool ready; spinlock_t lock; }; @@ -363,6 +368,110 @@ static const u8 hid_reportid_size_map[NUMBER_OF_HID_REPORTS] = { static struct hid_ll_driver logi_dj_ll_driver; static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev); +static void delayedwork_callback(struct work_struct *work); + +static LIST_HEAD(dj_hdev_list); +static DEFINE_MUTEX(dj_hdev_list_lock); + +/* + * dj/HID++ receivers are really a single logical entity, but for BIOS/Windows + * compatibility they have multiple USB interfaces. On HID++ receivers we need + * to listen for input reports on both interfaces. The functions below are used + * to create a single struct dj_receiver_dev for all interfaces belonging to + * a single USB-device / receiver. + */ +static struct dj_receiver_dev *dj_find_receiver_dev(struct hid_device *hdev) +{ + struct dj_receiver_dev *djrcv_dev; + + /* Try to find an already-probed interface from the same device */ + list_for_each_entry(djrcv_dev, &dj_hdev_list, list) { + if (djrcv_dev->mouse && + hid_compare_device_paths(hdev, djrcv_dev->mouse, '/')) { + kref_get(&djrcv_dev->kref); + return djrcv_dev; + } + if (djrcv_dev->keyboard && + hid_compare_device_paths(hdev, djrcv_dev->keyboard, '/')) { + kref_get(&djrcv_dev->kref); + return djrcv_dev; + } + if (djrcv_dev->hidpp && + hid_compare_device_paths(hdev, djrcv_dev->hidpp, '/')) { + kref_get(&djrcv_dev->kref); + return djrcv_dev; + } + } + + return NULL; +} + +static void dj_release_receiver_dev(struct kref *kref) +{ + struct dj_receiver_dev *djrcv_dev = container_of(kref, struct dj_receiver_dev, kref); + + list_del(&djrcv_dev->list); + kfifo_free(&djrcv_dev->notif_fifo); + kfree(djrcv_dev); +} + +static void dj_put_receiver_dev(struct hid_device *hdev) +{ + struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev); + + mutex_lock(&dj_hdev_list_lock); + + if (djrcv_dev->mouse == hdev) + djrcv_dev->mouse = NULL; + if (djrcv_dev->keyboard == hdev) + djrcv_dev->keyboard = NULL; + if (djrcv_dev->hidpp == hdev) + djrcv_dev->hidpp = NULL; + + kref_put(&djrcv_dev->kref, dj_release_receiver_dev); + + mutex_unlock(&dj_hdev_list_lock); +} + +static struct dj_receiver_dev *dj_get_receiver_dev(struct hid_device *hdev, + unsigned int application, + bool is_hidpp) +{ + struct dj_receiver_dev *djrcv_dev; + + mutex_lock(&dj_hdev_list_lock); + + djrcv_dev = dj_find_receiver_dev(hdev); + if (!djrcv_dev) { + djrcv_dev = kzalloc(sizeof(*djrcv_dev), GFP_KERNEL); + if (!djrcv_dev) + goto out; + + INIT_WORK(&djrcv_dev->work, delayedwork_callback); + spin_lock_init(&djrcv_dev->lock); + if (kfifo_alloc(&djrcv_dev->notif_fifo, + DJ_MAX_NUMBER_NOTIFS * sizeof(struct dj_workitem), + GFP_KERNEL)) { + kfree(djrcv_dev); + djrcv_dev = NULL; + goto out; + } + kref_init(&djrcv_dev->kref); + list_add_tail(&djrcv_dev->list, &dj_hdev_list); + } + + if (application == HID_GD_KEYBOARD) + djrcv_dev->keyboard = hdev; + if (application == HID_GD_MOUSE) + djrcv_dev->mouse = hdev; + if (is_hidpp) + djrcv_dev->hidpp = hdev; + + hid_set_drvdata(hdev, djrcv_dev); +out: + mutex_unlock(&dj_hdev_list_lock); + return djrcv_dev; +} static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev, struct dj_workitem *workitem) @@ -480,6 +589,17 @@ static void delayedwork_callback(struct work_struct *work) spin_lock_irqsave(&djrcv_dev->lock, flags); + /* + * Since we attach to multiple interfaces, we may get scheduled before + * we are bound to the HID++ interface, catch this. + */ + if (!djrcv_dev->ready) { + pr_warn("%s: delayedwork queued before hidpp interface was enumerated\n", + __func__); + spin_unlock_irqrestore(&djrcv_dev->lock, flags); + return; + } + count = kfifo_out(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem)); if (count != sizeof(workitem)) { @@ -1043,6 +1163,7 @@ static int logi_dj_probe(struct hid_device *hdev, struct hid_report *rep; struct dj_receiver_dev *djrcv_dev; bool has_hidpp = false; + unsigned long flags; int retval; /* @@ -1076,27 +1197,15 @@ static int logi_dj_probe(struct hid_device *hdev, if (!has_hidpp) return -ENODEV; - /* Treat DJ/HID++ interface */ - - djrcv_dev = kzalloc(sizeof(struct dj_receiver_dev), GFP_KERNEL); + /* get the current application attached to the node */ + rep = list_first_entry(&rep_enum->report_list, struct hid_report, list); + djrcv_dev = dj_get_receiver_dev(hdev, + rep->application, has_hidpp); if (!djrcv_dev) { dev_err(&hdev->dev, "%s:failed allocating dj_receiver_dev\n", __func__); return -ENOMEM; } - djrcv_dev->hidpp = hdev; - INIT_WORK(&djrcv_dev->work, delayedwork_callback); - spin_lock_init(&djrcv_dev->lock); - if (kfifo_alloc(&djrcv_dev->notif_fifo, - DJ_MAX_NUMBER_NOTIFS * sizeof(struct dj_workitem), - GFP_KERNEL)) { - dev_err(&hdev->dev, - "%s:failed allocating notif_fifo\n", __func__); - kfree(djrcv_dev); - return -ENOMEM; - } - hid_set_drvdata(hdev, djrcv_dev); - /* Starts the usb device and connects to upper interfaces hiddev and * hidraw */ @@ -1126,6 +1235,9 @@ static int logi_dj_probe(struct hid_device *hdev, /* Allow incoming packets to arrive: */ hid_device_io_start(hdev); + spin_lock_irqsave(&djrcv_dev->lock, flags); + djrcv_dev->ready = true; + spin_unlock_irqrestore(&djrcv_dev->lock, flags); retval = logi_dj_recv_query_paired_devices(djrcv_dev); if (retval < 0) { dev_err(&hdev->dev, "%s:logi_dj_recv_query_paired_devices " @@ -1143,10 +1255,8 @@ static int logi_dj_probe(struct hid_device *hdev, hid_hw_stop(hdev); hid_hw_start_fail: - kfifo_free(&djrcv_dev->notif_fifo); - kfree(djrcv_dev); + dj_put_receiver_dev(hdev); return retval; - } #ifdef CONFIG_PM @@ -1170,31 +1280,43 @@ static void logi_dj_remove(struct hid_device *hdev) { struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev); struct dj_device *dj_dev; + unsigned long flags; int i; dbg_hid("%s\n", __func__); + /* + * This ensures that if the work gets requeued from another + * interface of the same receiver it will be a no-op. + */ + spin_lock_irqsave(&djrcv_dev->lock, flags); + djrcv_dev->ready = false; + spin_unlock_irqrestore(&djrcv_dev->lock, flags); + cancel_work_sync(&djrcv_dev->work); hid_hw_close(hdev); hid_hw_stop(hdev); - /* I suppose that at this point the only context that can access - * the djrecv_data is this thread as the work item is guaranteed to - * have finished and no more raw_event callbacks should arrive after - * the remove callback was triggered so no locks are put around the - * code below */ + /* + * For proper operation we need access to all interfaces, so we destroy + * the paired devices when we're unbound from any interface. + * + * Note we may still be bound to other interfaces, sharing the same + * djrcv_dev, so we need locking here. + */ for (i = 0; i < (DJ_MAX_PAIRED_DEVICES + DJ_DEVICE_INDEX_MIN); i++) { + spin_lock_irqsave(&djrcv_dev->lock, flags); dj_dev = djrcv_dev->paired_dj_devices[i]; + djrcv_dev->paired_dj_devices[i] = NULL; + spin_unlock_irqrestore(&djrcv_dev->lock, flags); if (dj_dev != NULL) { hid_destroy_device(dj_dev->hdev); kfree(dj_dev); - djrcv_dev->paired_dj_devices[i] = NULL; } } - kfifo_free(&djrcv_dev->notif_fifo); - kfree(djrcv_dev); + dj_put_receiver_dev(hdev); } static const struct hid_device_id logi_dj_receivers[] = { From patchwork Sat Apr 20 11:21:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910247 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 0B6FB17E0 for ; Sat, 20 Apr 2019 11:22:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F07DD28D25 for ; Sat, 20 Apr 2019 11:22:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E48E828D94; Sat, 20 Apr 2019 11:22:44 +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 7562F28D25 for ; Sat, 20 Apr 2019 11:22:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728066AbfDTLWo (ORCPT ); Sat, 20 Apr 2019 07:22:44 -0400 Received: from mx1.redhat.com ([209.132.183.28]:9297 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726082AbfDTLWn (ORCPT ); Sat, 20 Apr 2019 07:22:43 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0C8B9DA334; Sat, 20 Apr 2019 11:22:43 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id EC4AA19C5B; Sat, 20 Apr 2019 11:22:41 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 13/37] HID: logitech-dj: add logi_dj_recv_queue_unknown_work helper Date: Sat, 20 Apr 2019 13:21:53 +0200 Message-Id: <20190420112217.27590-14-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Sat, 20 Apr 2019 11:22:43 +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 Add a logi_dj_recv_queue_unknown_work helper and implement query rate-limiting inside this helper. The motivations behind this are: 1) We need to queue workitems for reports with no place to forward them from more places with the upcoming non-unifying receiver support, hence the addition of the helper function. 2) When we've missed a pairing info report (or there is a race between the report and input-events) and the input report is e.g. from a mouse being moved, we will get a lot of these before we've finished (re-) querying and enumerating the devices, hence the rate-limiting. Note this also removes the: if (!djrcv_dev->paired_dj_devices[hidpp_report->device_index]) check previously guarding the sending of an unknown workitem, the caller of logi_dj_recv_queue_notification already does this check before calling logi_dj_recv_queue_notification. Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-dj.c | 45 +++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index a3ad100e9dc9..ac0d00e0695c 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -128,6 +128,7 @@ struct dj_receiver_dev { struct kref kref; struct work_struct work; struct kfifo notif_fifo; + unsigned long last_query; /* in jiffies */ bool ready; spinlock_t lock; }; @@ -458,6 +459,7 @@ static struct dj_receiver_dev *dj_get_receiver_dev(struct hid_device *hdev, } kref_init(&djrcv_dev->kref); list_add_tail(&djrcv_dev->list, &dj_hdev_list); + djrcv_dev->last_query = jiffies; } if (application == HID_GD_KEYBOARD) @@ -637,6 +639,30 @@ static void delayedwork_callback(struct work_struct *work) } } +/* + * Sometimes we receive reports for which we do not have a paired dj_device + * associated with the device_index or report-type to forward the report to. + * This means that the original "device paired" notification corresponding + * to the dj_device never arrived to this driver. Possible reasons for this are: + * 1) hid-core discards all packets coming from a device during probe(). + * 2) if the receiver is plugged into a KVM switch then the pairing reports + * are only forwarded to it if the focus is on this PC. + * This function deals with this by re-asking the receiver for the list of + * connected devices in the delayed work callback. + * This function MUST be called with djrcv->lock held. + */ +static void logi_dj_recv_queue_unknown_work(struct dj_receiver_dev *djrcv_dev) +{ + struct dj_workitem workitem = { .type = WORKITEM_TYPE_UNKNOWN }; + + /* Rate limit queries done because of unhandeled reports to 2/sec */ + if (time_before(jiffies, djrcv_dev->last_query + HZ / 2)) + return; + + kfifo_in(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem)); + schedule_work(&djrcv_dev->work); +} + static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev, struct dj_report *dj_report) { @@ -666,21 +692,8 @@ static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev, workitem.type = WORKITEM_TYPE_UNPAIRED; break; default: - /* A normal report (i. e. not belonging to a pair/unpair notification) - * arriving here, means that the report arrived but we did not have a - * paired dj_device associated to the report's device_index, this - * means that the original "device paired" notification corresponding - * to this dj_device never arrived to this driver. The reason is that - * hid-core discards all packets coming from a device while probe() is - * executing. */ - if (!djrcv_dev->paired_dj_devices[dj_report->device_index]) { - /* - * ok, we don't know the device, just re-ask the - * receiver for the list of connected devices in - * the delayed work callback. - */ - workitem.type = WORKITEM_TYPE_UNKNOWN; - } + logi_dj_recv_queue_unknown_work(djrcv_dev); + return; } kfifo_in(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem)); @@ -776,6 +789,8 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) struct dj_report *dj_report; int retval; + djrcv_dev->last_query = jiffies; + dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); if (!dj_report) return -ENOMEM; From patchwork Sat Apr 20 11:21:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910251 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 029C217EE for ; Sat, 20 Apr 2019 11:22:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E5BF428D25 for ; Sat, 20 Apr 2019 11:22:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D9DF128D94; Sat, 20 Apr 2019 11:22:47 +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 E3ADC28D25 for ; Sat, 20 Apr 2019 11:22:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728068AbfDTLWp (ORCPT ); Sat, 20 Apr 2019 07:22:45 -0400 Received: from mx1.redhat.com ([209.132.183.28]:60524 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726082AbfDTLWp (ORCPT ); Sat, 20 Apr 2019 07:22:45 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8B6C17EBC1; Sat, 20 Apr 2019 11:22:44 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4FD5B19C5B; Sat, 20 Apr 2019 11:22:43 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 14/37] HID: logitech-dj: add support for non unifying receivers Date: Sat, 20 Apr 2019 13:21:54 +0200 Message-Id: <20190420112217.27590-15-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Sat, 20 Apr 2019 11:22:44 +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 We emulate the DJ functionality through the driver. The receiver supports "fake device arrival" which behaves like the probing of DJ devices. A non-unifying receiver has 2 USB interfaces, the first one generates standard keypresses and is compatible with the USB Keyboard Boot Subclass. The second interface sends events for the mouse and special keys such as the consumer-page keys. Events are split this way for BIOS / Windows / generic-hid driver compatibility. This split does not actually match with which device the event originate from, e.g. the consumer-page key events originate from the keyboard but are delivered on the mouse interface. To make sure the events are actually delivered to the dj_device representing the originating device, we pick which dj_dev to forward a "regular" input-report to based on the report-number, rather then based on the originating interface. Co-authored-by: Benjamin Tissoires Signed-off-by: Benjamin Tissoires Signed-off-by: Hans de Goede --- drivers/hid/hid-ids.h | 2 + drivers/hid/hid-logitech-dj.c | 311 +++++++++++++++++++++++++++++----- 2 files changed, 274 insertions(+), 39 deletions(-) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index adce58f24f76..b020321bb168 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -763,7 +763,9 @@ #define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512 #define USB_DEVICE_ID_MX3000_RECEIVER 0xc513 #define USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER 0xc52b +#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER 0xc52f #define USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2 0xc532 +#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2 0xc534 #define USB_DEVICE_ID_SPACETRAVELLER 0xc623 #define USB_DEVICE_ID_SPACENAVIGATOR 0xc626 #define USB_DEVICE_ID_DINOVO_DESKTOP 0xc704 diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index ac0d00e0695c..d880ce641345 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -100,9 +100,26 @@ #define MEDIA_CENTER BIT(8) #define KBD_LEDS BIT(14) +/* HID++ Device Connected Notification */ +#define REPORT_TYPE_NOTIF_DEVICE_CONNECTED 0x41 +#define HIDPP_PARAM_PROTO_TYPE 0x00 +#define HIDPP_PARAM_DEVICE_INFO 0x01 +#define HIDPP_PARAM_EQUAD_LSB 0x02 +#define HIDPP_PARAM_EQUAD_MSB 0x03 +#define HIDPP_DEVICE_TYPE_MASK GENMASK(3, 0) +#define HIDPP_LINK_STATUS_MASK BIT(6) + +#define HIDPP_SET_REGISTER 0x80 #define HIDPP_GET_LONG_REGISTER 0x83 +#define HIDPP_REG_CONNECTION_STATE 0x02 #define HIDPP_REG_PAIRING_INFORMATION 0xB5 #define HIDPP_PAIRING_INFORMATION 0x20 +#define HIDPP_FAKE_DEVICE_ARRIVAL 0x02 + +enum recvr_type { + recvr_type_dj, + recvr_type_hidpp, +}; struct dj_report { u8 report_id; @@ -130,6 +147,8 @@ struct dj_receiver_dev { struct kfifo notif_fifo; unsigned long last_query; /* in jiffies */ bool ready; + enum recvr_type type; + unsigned int unnumbered_application; spinlock_t lock; }; @@ -435,6 +454,7 @@ static void dj_put_receiver_dev(struct hid_device *hdev) } static struct dj_receiver_dev *dj_get_receiver_dev(struct hid_device *hdev, + enum recvr_type type, unsigned int application, bool is_hidpp) { @@ -460,6 +480,7 @@ static struct dj_receiver_dev *dj_get_receiver_dev(struct hid_device *hdev, kref_init(&djrcv_dev->kref); list_add_tail(&djrcv_dev->list, &dj_hdev_list); djrcv_dev->last_query = jiffies; + djrcv_dev->type = type; } if (application == HID_GD_KEYBOARD) @@ -704,6 +725,94 @@ static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev, } } +static void logi_hidpp_dev_conn_notif_equad(struct hidpp_event *hidpp_report, + struct dj_workitem *workitem) +{ + workitem->type = WORKITEM_TYPE_PAIRED; + workitem->quad_id_msb = hidpp_report->params[HIDPP_PARAM_EQUAD_MSB]; + workitem->quad_id_lsb = hidpp_report->params[HIDPP_PARAM_EQUAD_LSB]; + switch (hidpp_report->params[HIDPP_PARAM_DEVICE_INFO] & + HIDPP_DEVICE_TYPE_MASK) { + case REPORT_TYPE_KEYBOARD: + workitem->reports_supported |= STD_KEYBOARD | MULTIMEDIA | + POWER_KEYS | MEDIA_CENTER; + break; + case REPORT_TYPE_MOUSE: + workitem->reports_supported |= STD_MOUSE; + break; + } +} + +static void logi_hidpp_recv_queue_notif(struct hid_device *hdev, + struct hidpp_event *hidpp_report) +{ + /* We are called from atomic context (tasklet && djrcv->lock held) */ + struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev); + const char *device_type = "UNKNOWN"; + struct dj_workitem workitem = { + .type = WORKITEM_TYPE_EMPTY, + .device_index = hidpp_report->device_index, + }; + + switch (hidpp_report->params[HIDPP_PARAM_PROTO_TYPE]) { + case 0x01: + device_type = "Bluetooth"; + break; + case 0x02: + device_type = "27 Mhz"; + break; + case 0x03: + device_type = "QUAD or eQUAD"; + logi_hidpp_dev_conn_notif_equad(hidpp_report, &workitem); + break; + case 0x04: + device_type = "eQUAD step 4 DJ"; + logi_hidpp_dev_conn_notif_equad(hidpp_report, &workitem); + break; + case 0x05: + device_type = "DFU Lite"; + break; + case 0x06: + device_type = "eQUAD step 4 Lite"; + logi_hidpp_dev_conn_notif_equad(hidpp_report, &workitem); + break; + case 0x07: + device_type = "eQUAD step 4 Gaming"; + break; + case 0x08: + device_type = "eQUAD step 4 for gamepads"; + break; + case 0x0a: + device_type = "eQUAD nano Lite"; + logi_hidpp_dev_conn_notif_equad(hidpp_report, &workitem); + break; + case 0x0c: + device_type = "eQUAD Lightspeed"; + break; + } + + if (workitem.type == WORKITEM_TYPE_EMPTY) { + hid_warn(hdev, + "unusable device of type %s (0x%02x) connected on slot %d", + device_type, + hidpp_report->params[HIDPP_PARAM_PROTO_TYPE], + hidpp_report->device_index); + return; + } + + hid_info(hdev, "device of type %s (0x%02x) connected on slot %d", + device_type, hidpp_report->params[HIDPP_PARAM_PROTO_TYPE], + hidpp_report->device_index); + + + kfifo_in(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem)); + + if (schedule_work(&djrcv_dev->work) == 0) { + dbg_hid("%s: did not schedule the work item, was already queued\n", + __func__); + } +} + static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev, struct dj_report *dj_report) { @@ -759,6 +868,36 @@ static void logi_dj_recv_forward_report(struct dj_device *dj_dev, u8 *data, dbg_hid("hid_input_report error\n"); } +static void logi_dj_recv_forward_input_report(struct hid_device *hdev, + u8 *data, int size) +{ + struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev); + struct dj_device *dj_dev; + unsigned long flags; + u8 report = data[0]; + int i; + + if (report > REPORT_TYPE_RFREPORT_LAST) { + hid_err(hdev, "Unexpect input report number %d\n", report); + return; + } + + spin_lock_irqsave(&djrcv_dev->lock, flags); + for (i = 0; i < (DJ_MAX_PAIRED_DEVICES + DJ_DEVICE_INDEX_MIN); i++) { + dj_dev = djrcv_dev->paired_dj_devices[i]; + if (dj_dev && (dj_dev->reports_supported & BIT(report))) { + logi_dj_recv_forward_report(dj_dev, data, size); + spin_unlock_irqrestore(&djrcv_dev->lock, flags); + return; + } + } + + logi_dj_recv_queue_unknown_work(djrcv_dev); + spin_unlock_irqrestore(&djrcv_dev->lock, flags); + + dbg_hid("No dj-devs handling input report number %d\n", report); +} + static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, struct dj_report *dj_report) { @@ -784,6 +923,31 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, return 0; } +static int logi_dj_recv_query_hidpp_devices(struct dj_receiver_dev *djrcv_dev) +{ + const u8 template[] = {REPORT_ID_HIDPP_SHORT, + HIDPP_RECEIVER_INDEX, + HIDPP_SET_REGISTER, + HIDPP_REG_CONNECTION_STATE, + HIDPP_FAKE_DEVICE_ARRIVAL, + 0x00, 0x00}; + u8 *hidpp_report; + int retval; + + hidpp_report = kmemdup(template, sizeof(template), GFP_KERNEL); + if (!hidpp_report) + return -ENOMEM; + + retval = hid_hw_raw_request(djrcv_dev->hidpp, + REPORT_ID_HIDPP_SHORT, + hidpp_report, sizeof(template), + HID_OUTPUT_REPORT, + HID_REQ_SET_REPORT); + + kfree(hidpp_report); + return 0; +} + static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) { struct dj_report *dj_report; @@ -791,6 +955,9 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) djrcv_dev->last_query = jiffies; + if (djrcv_dev->type != recvr_type_dj) + return logi_dj_recv_query_hidpp_devices(djrcv_dev); + dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); if (!dj_report) return -ENOMEM; @@ -809,24 +976,30 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, struct hid_device *hdev = djrcv_dev->hidpp; struct dj_report *dj_report; u8 *buf; - int retval; + int retval = 0; dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); if (!dj_report) return -ENOMEM; - dj_report->report_id = REPORT_ID_DJ_SHORT; - dj_report->device_index = 0xFF; - dj_report->report_type = REPORT_TYPE_CMD_SWITCH; - dj_report->report_params[CMD_SWITCH_PARAM_DEVBITFIELD] = 0x3F; - dj_report->report_params[CMD_SWITCH_PARAM_TIMEOUT_SECONDS] = (u8)timeout; - retval = logi_dj_recv_send_report(djrcv_dev, dj_report); - /* - * Ugly sleep to work around a USB 3.0 bug when the receiver is still - * processing the "switch-to-dj" command while we send an other command. - * 50 msec should gives enough time to the receiver to be ready. - */ - msleep(50); + if (djrcv_dev->type == recvr_type_dj) { + dj_report->report_id = REPORT_ID_DJ_SHORT; + dj_report->device_index = 0xFF; + dj_report->report_type = REPORT_TYPE_CMD_SWITCH; + dj_report->report_params[CMD_SWITCH_PARAM_DEVBITFIELD] = 0x3F; + dj_report->report_params[CMD_SWITCH_PARAM_TIMEOUT_SECONDS] = + (u8)timeout; + + retval = logi_dj_recv_send_report(djrcv_dev, dj_report); + + /* + * Ugly sleep to work around a USB 3.0 bug when the receiver is + * still processing the "switch-to-dj" command while we send an + * other command. + * 50 msec should gives enough time to the receiver to be ready. + */ + msleep(50); + } /* * Magical bits to set up hidpp notifications when the dj devices @@ -910,6 +1083,16 @@ static int logi_dj_ll_raw_request(struct hid_device *hid, if (buf[0] != REPORT_TYPE_LEDS) return -EINVAL; + if (djrcv_dev->type != recvr_type_dj && count >= 2) { + if (!djrcv_dev->keyboard) { + hid_warn(hid, "Received REPORT_TYPE_LEDS request before the keyboard interface was enumerated\n"); + return 0; + } + /* usbhid overrides the report ID and ignores the first byte */ + return hid_hw_raw_request(djrcv_dev->keyboard, 0, buf, count, + report_type, reqtype); + } + out_buf = kzalloc(DJREPORT_SHORT_LENGTH, GFP_ATOMIC); if (!out_buf) return -ENOMEM; @@ -1090,6 +1273,7 @@ static int logi_dj_hidpp_event(struct hid_device *hdev, { struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev); struct hidpp_event *hidpp_report = (struct hidpp_event *) data; + struct dj_device *dj_dev; unsigned long flags; u8 device_index = hidpp_report->device_index; @@ -1126,14 +1310,16 @@ static int logi_dj_hidpp_event(struct hid_device *hdev, spin_lock_irqsave(&djrcv_dev->lock, flags); - if (!djrcv_dev->paired_dj_devices[device_index]) - /* received an event for an unknown device, bail out */ - goto out; - - logi_dj_recv_forward_report(djrcv_dev->paired_dj_devices[device_index], - data, size); + dj_dev = djrcv_dev->paired_dj_devices[device_index]; + if (dj_dev) { + logi_dj_recv_forward_report(dj_dev, data, size); + } else { + if (hidpp_report->sub_id == REPORT_TYPE_NOTIF_DEVICE_CONNECTED) + logi_hidpp_recv_queue_notif(hdev, hidpp_report); + else + logi_dj_recv_queue_unknown_work(djrcv_dev); + } -out: spin_unlock_irqrestore(&djrcv_dev->lock, flags); return false; @@ -1143,8 +1329,30 @@ static int logi_dj_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *data, int size) { + struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev); dbg_hid("%s, size:%d\n", __func__, size); + if (!hdev->report_enum[HID_INPUT_REPORT].numbered) { + + if (djrcv_dev->unnumbered_application == HID_GD_KEYBOARD) { + /* + * For the keyboard, we can reuse the same report by + * using the second byte which is constant in the USB + * HID report descriptor. + */ + data[1] = data[0]; + data[0] = REPORT_TYPE_KEYBOARD; + + logi_dj_recv_forward_input_report(hdev, data, size); + + /* restore previous state */ + data[0] = data[1]; + data[1] = 0; + } + + return false; + } + switch (data[0]) { case REPORT_ID_DJ_SHORT: if (size != DJREPORT_SHORT_LENGTH) { @@ -1168,6 +1376,8 @@ static int logi_dj_raw_event(struct hid_device *hdev, return logi_dj_hidpp_event(hdev, report, data, size); } + logi_dj_recv_forward_input_report(hdev, data, size); + return false; } @@ -1195,6 +1405,10 @@ static int logi_dj_probe(struct hid_device *hdev, rep_enum = &hdev->report_enum[HID_INPUT_REPORT]; + /* no input reports, bail out */ + if (list_empty(&rep_enum->report_list)) + return -ENODEV; + /* * Check for the HID++ application. * Note: we should theoretically check for HID++ and DJ @@ -1209,12 +1423,12 @@ static int logi_dj_probe(struct hid_device *hdev, * Ignore interfaces without DJ/HID++ collection, they will not carry * any data, dont create any hid_device for them. */ - if (!has_hidpp) + if (!has_hidpp && id->driver_data == recvr_type_dj) return -ENODEV; /* get the current application attached to the node */ rep = list_first_entry(&rep_enum->report_list, struct hid_report, list); - djrcv_dev = dj_get_receiver_dev(hdev, + djrcv_dev = dj_get_receiver_dev(hdev, id->driver_data, rep->application, has_hidpp); if (!djrcv_dev) { dev_err(&hdev->dev, @@ -1222,21 +1436,25 @@ static int logi_dj_probe(struct hid_device *hdev, return -ENOMEM; } + if (!rep_enum->numbered) + djrcv_dev->unnumbered_application = rep->application; + /* Starts the usb device and connects to upper interfaces hiddev and * hidraw */ - retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + retval = hid_hw_start(hdev, HID_CONNECT_HIDRAW|HID_CONNECT_HIDDEV); if (retval) { dev_err(&hdev->dev, "%s:hid_hw_start returned error\n", __func__); goto hid_hw_start_fail; } - retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0); - if (retval < 0) { - dev_err(&hdev->dev, - "%s:logi_dj_recv_switch_to_dj_mode returned error:%d\n", - __func__, retval); - goto switch_to_dj_mode_fail; + if (has_hidpp) { + retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0); + if (retval < 0) { + hid_err(hdev, "%s: logi_dj_recv_switch_to_dj_mode returned error:%d\n", + __func__, retval); + goto switch_to_dj_mode_fail; + } } /* This is enabling the polling urb on the IN endpoint */ @@ -1250,14 +1468,16 @@ static int logi_dj_probe(struct hid_device *hdev, /* Allow incoming packets to arrive: */ hid_device_io_start(hdev); - spin_lock_irqsave(&djrcv_dev->lock, flags); - djrcv_dev->ready = true; - spin_unlock_irqrestore(&djrcv_dev->lock, flags); - retval = logi_dj_recv_query_paired_devices(djrcv_dev); - if (retval < 0) { - dev_err(&hdev->dev, "%s:logi_dj_recv_query_paired_devices " - "error:%d\n", __func__, retval); - goto logi_dj_recv_query_paired_devices_failed; + if (has_hidpp) { + spin_lock_irqsave(&djrcv_dev->lock, flags); + djrcv_dev->ready = true; + spin_unlock_irqrestore(&djrcv_dev->lock, flags); + retval = logi_dj_recv_query_paired_devices(djrcv_dev); + if (retval < 0) { + hid_err(hdev, "%s: logi_dj_recv_query_paired_devices error:%d\n", + __func__, retval); + goto logi_dj_recv_query_paired_devices_failed; + } } return retval; @@ -1280,6 +1500,9 @@ static int logi_dj_reset_resume(struct hid_device *hdev) int retval; struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev); + if (djrcv_dev->hidpp != hdev) + return 0; + retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0); if (retval < 0) { dev_err(&hdev->dev, @@ -1336,9 +1559,19 @@ static void logi_dj_remove(struct hid_device *hdev) static const struct hid_device_id logi_dj_receivers[] = { {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, - USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)}, + USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER), + .driver_data = recvr_type_dj}, {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, - USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2)}, + USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2), + .driver_data = recvr_type_dj}, + { /* Logitech Nano (non DJ) receiver */ + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, + USB_DEVICE_ID_LOGITECH_NANO_RECEIVER), + .driver_data = recvr_type_hidpp}, + { /* Logitech Nano (non DJ) receiver */ + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, + USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2), + .driver_data = recvr_type_hidpp}, {} }; From patchwork Sat Apr 20 11:21:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910249 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 6B9F81515 for ; Sat, 20 Apr 2019 11:22:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5BCF328D59 for ; Sat, 20 Apr 2019 11:22:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4FCE128D97; Sat, 20 Apr 2019 11:22:47 +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 BD71E28D59 for ; Sat, 20 Apr 2019 11:22:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728075AbfDTLWq (ORCPT ); Sat, 20 Apr 2019 07:22:46 -0400 Received: from mx1.redhat.com ([209.132.183.28]:35486 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726082AbfDTLWq (ORCPT ); Sat, 20 Apr 2019 07:22:46 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E89A930058A8; Sat, 20 Apr 2019 11:22:45 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id CEFF219C5B; Sat, 20 Apr 2019 11:22:44 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 15/37] HID: logitech-dj: add support for the gaming unifying receiver Date: Sat, 20 Apr 2019 13:21:55 +0200 Message-Id: <20190420112217.27590-16-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.40]); Sat, 20 Apr 2019 11:22:45 +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 From: Benjamin Tissoires This receiver is almost identical to the normal unifying ones except: - it is supposed to be paired to only one device (for performance reasons) - the mice reports have a greater ranges in their values, so they are using a different report ID. Tested on a G403 and a G900. Signed-off-by: Benjamin Tissoires Co-authored-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/hid/hid-ids.h | 1 + drivers/hid/hid-logitech-dj.c | 58 ++++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index b020321bb168..9b5f98b5688c 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -766,6 +766,7 @@ #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER 0xc52f #define USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2 0xc532 #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2 0xc534 +#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_GAMING 0xc539 #define USB_DEVICE_ID_SPACETRAVELLER 0xc623 #define USB_DEVICE_ID_SPACENAVIGATOR 0xc626 #define USB_DEVICE_ID_DINOVO_DESKTOP 0xc704 diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index d880ce641345..9ece9aca40a0 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -119,6 +119,7 @@ enum recvr_type { recvr_type_dj, recvr_type_hidpp, + recvr_type_gaming_hidpp, }; struct dj_report { @@ -247,6 +248,44 @@ static const char mse_descriptor[] = { 0xC0, /* END_COLLECTION */ }; +/* Gaming Mouse descriptor (2) */ +static const char mse_high_res_descriptor[] = { + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x02, /* USAGE (Mouse) */ + 0xA1, 0x01, /* COLLECTION (Application) */ + 0x85, 0x02, /* REPORT_ID = 2 */ + 0x09, 0x01, /* USAGE (pointer) */ + 0xA1, 0x00, /* COLLECTION (physical) */ + 0x05, 0x09, /* USAGE_PAGE (buttons) */ + 0x19, 0x01, /* USAGE_MIN (1) */ + 0x29, 0x10, /* USAGE_MAX (16) */ + 0x15, 0x00, /* LOGICAL_MIN (0) */ + 0x25, 0x01, /* LOGICAL_MAX (1) */ + 0x95, 0x10, /* REPORT_COUNT (16) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (data var abs) */ + 0x05, 0x01, /* USAGE_PAGE (generic desktop) */ + 0x16, 0x01, 0x80, /* LOGICAL_MIN (-32767) */ + 0x26, 0xFF, 0x7F, /* LOGICAL_MAX (32767) */ + 0x75, 0x10, /* REPORT_SIZE (16) */ + 0x95, 0x02, /* REPORT_COUNT (2) */ + 0x09, 0x30, /* USAGE (X) */ + 0x09, 0x31, /* USAGE (Y) */ + 0x81, 0x06, /* INPUT */ + 0x15, 0x81, /* LOGICAL_MIN (-127) */ + 0x25, 0x7F, /* LOGICAL_MAX (127) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x09, 0x38, /* USAGE (wheel) */ + 0x81, 0x06, /* INPUT */ + 0x05, 0x0C, /* USAGE_PAGE(consumer) */ + 0x0A, 0x38, 0x02, /* USAGE(AC Pan) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x81, 0x06, /* INPUT */ + 0xC0, /* END_COLLECTION */ + 0xC0, /* END_COLLECTION */ +}; + /* Consumer Control descriptor (3) */ static const char consumer_descriptor[] = { 0x05, 0x0C, /* USAGE_PAGE (Consumer Devices) */ @@ -788,6 +827,8 @@ static void logi_hidpp_recv_queue_notif(struct hid_device *hdev, break; case 0x0c: device_type = "eQUAD Lightspeed"; + logi_hidpp_dev_conn_notif_equad(hidpp_report, &workitem); + workitem.reports_supported |= STD_KEYBOARD; break; } @@ -1142,7 +1183,12 @@ static int logi_dj_ll_parse(struct hid_device *hid) if (djdev->reports_supported & STD_MOUSE) { dbg_hid("%s: sending a mouse descriptor, reports_supported: " "%x\n", __func__, djdev->reports_supported); - rdcat(rdesc, &rsize, mse_descriptor, sizeof(mse_descriptor)); + if (djdev->dj_receiver_dev->type == recvr_type_gaming_hidpp) + rdcat(rdesc, &rsize, mse_high_res_descriptor, + sizeof(mse_high_res_descriptor)); + else + rdcat(rdesc, &rsize, mse_descriptor, + sizeof(mse_descriptor)); } if (djdev->reports_supported & MULTIMEDIA) { @@ -1360,6 +1406,12 @@ static int logi_dj_raw_event(struct hid_device *hdev, return false; } return logi_dj_dj_event(hdev, report, data, size); + case REPORT_ID_DJ_LONG: + if (size != DJREPORT_LONG_LENGTH) { + dev_err(&hdev->dev, "DJ report of bad size (%d)", size); + return false; + } + return logi_dj_dj_event(hdev, report, data, size); case REPORT_ID_HIDPP_SHORT: if (size != HIDPP_REPORT_SHORT_LENGTH) { dev_err(&hdev->dev, @@ -1572,6 +1624,10 @@ static const struct hid_device_id logi_dj_receivers[] = { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2), .driver_data = recvr_type_hidpp}, + { /* Logitech gaming receiver (0xc539) */ + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, + USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_GAMING), + .driver_data = recvr_type_gaming_hidpp}, {} }; From patchwork Sat Apr 20 11:21:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910253 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 7A24A17E0 for ; Sat, 20 Apr 2019 11:22:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6A74628D25 for ; Sat, 20 Apr 2019 11:22:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5E53928D94; Sat, 20 Apr 2019 11:22:49 +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 A36BA28D25 for ; Sat, 20 Apr 2019 11:22:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728082AbfDTLWs (ORCPT ); Sat, 20 Apr 2019 07:22:48 -0400 Received: from mx1.redhat.com ([209.132.183.28]:42596 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726082AbfDTLWs (ORCPT ); Sat, 20 Apr 2019 07:22:48 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4DBFE308FECF; Sat, 20 Apr 2019 11:22:47 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 365A819C5B; Sat, 20 Apr 2019 11:22:46 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 16/37] HID: logitech-dj: add support for 27 MHz receivers Date: Sat, 20 Apr 2019 13:21:56 +0200 Message-Id: <20190420112217.27590-17-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.49]); Sat, 20 Apr 2019 11:22:47 +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 Most Logitech wireless keyboard and mice using the 27 MHz are hidpp10 devices, add support to logitech-dj for their receivers. Doing so leads to 2 improvements: 1) All these devices share the same USB product-id for their receiver, making it impossible to properly map some special keys / buttons which differ from device to device. Adding support to logitech-dj to see these as hidpp10 devices allows us to get the actual device-id from the keyboard / mouse. 2) It enables battery-monitoring of these devices This patch uses a new HID group for 27Mhz devices, since the logitech-hidpp code needs to be able to differentiate them from other devices instantiated by the logitech-dj code. Signed-off-by: Hans de Goede --- Changes in v2: -Remove chunk to pick a better name for hidpp devices, this is replaced with a more generic fix in a separate patch -Add support for mouse on index 2, numeric-keypad on index 4 -Use a new group for 27MHz, so that logitech-hidpp.c can check for this to enable 27MHz specific behavior, rather then have it guess based on the descriptors. This also allows removing some 27MHz descriptor hacks from logitech-dj.c, so it simplifies things on both ends --- drivers/hid/hid-lg.c | 2 - drivers/hid/hid-logitech-dj.c | 94 ++++++++++++++++++++++++++++++++++- drivers/hid/hid-quirks.c | 1 - include/linux/hid.h | 1 + 4 files changed, 94 insertions(+), 4 deletions(-) diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index 5d419a95b6c2..36d725fdb199 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -876,8 +876,6 @@ static const struct hid_device_id lg_devices[] = { .driver_data = LG_RDESC | LG_WIRELESS }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER), .driver_data = LG_RDESC | LG_WIRELESS }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2), - .driver_data = LG_RDESC | LG_WIRELESS }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER), .driver_data = LG_BAD_RELATIVE_KEYS }, diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 9ece9aca40a0..3004ca91b76b 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -106,6 +106,7 @@ #define HIDPP_PARAM_DEVICE_INFO 0x01 #define HIDPP_PARAM_EQUAD_LSB 0x02 #define HIDPP_PARAM_EQUAD_MSB 0x03 +#define HIDPP_PARAM_27MHZ_DEVID 0x03 #define HIDPP_DEVICE_TYPE_MASK GENMASK(3, 0) #define HIDPP_LINK_STATUS_MASK BIT(6) @@ -120,6 +121,7 @@ enum recvr_type { recvr_type_dj, recvr_type_hidpp, recvr_type_gaming_hidpp, + recvr_type_27mhz, }; struct dj_report { @@ -248,6 +250,44 @@ static const char mse_descriptor[] = { 0xC0, /* END_COLLECTION */ }; +/* Mouse descriptor (2) for 27 MHz receiver, only 8 buttons */ +static const char mse_27mhz_descriptor[] = { + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x02, /* USAGE (Mouse) */ + 0xA1, 0x01, /* COLLECTION (Application) */ + 0x85, 0x02, /* REPORT_ID = 2 */ + 0x09, 0x01, /* USAGE (pointer) */ + 0xA1, 0x00, /* COLLECTION (physical) */ + 0x05, 0x09, /* USAGE_PAGE (buttons) */ + 0x19, 0x01, /* USAGE_MIN (1) */ + 0x29, 0x08, /* USAGE_MAX (8) */ + 0x15, 0x00, /* LOGICAL_MIN (0) */ + 0x25, 0x01, /* LOGICAL_MAX (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (data var abs) */ + 0x05, 0x01, /* USAGE_PAGE (generic desktop) */ + 0x16, 0x01, 0xF8, /* LOGICAL_MIN (-2047) */ + 0x26, 0xFF, 0x07, /* LOGICAL_MAX (2047) */ + 0x75, 0x0C, /* REPORT_SIZE (12) */ + 0x95, 0x02, /* REPORT_COUNT (2) */ + 0x09, 0x30, /* USAGE (X) */ + 0x09, 0x31, /* USAGE (Y) */ + 0x81, 0x06, /* INPUT */ + 0x15, 0x81, /* LOGICAL_MIN (-127) */ + 0x25, 0x7F, /* LOGICAL_MAX (127) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x09, 0x38, /* USAGE (wheel) */ + 0x81, 0x06, /* INPUT */ + 0x05, 0x0C, /* USAGE_PAGE(consumer) */ + 0x0A, 0x38, 0x02, /* USAGE(AC Pan) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x81, 0x06, /* INPUT */ + 0xC0, /* END_COLLECTION */ + 0xC0, /* END_COLLECTION */ +}; + /* Gaming Mouse descriptor (2) */ static const char mse_high_res_descriptor[] = { 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ @@ -596,7 +636,10 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, "Logitech Unifying Device. Wireless PID:%04x", dj_hiddev->product); - dj_hiddev->group = HID_GROUP_LOGITECH_DJ_DEVICE; + if (djrcv_dev->type == recvr_type_27mhz) + dj_hiddev->group = HID_GROUP_LOGITECH_27MHZ_DEVICE; + else + dj_hiddev->group = HID_GROUP_LOGITECH_DJ_DEVICE; memcpy(dj_hiddev->phys, djrcv_hdev->phys, sizeof(djrcv_hdev->phys)); snprintf(tmpstr, sizeof(tmpstr), ":%d", device_index); @@ -782,6 +825,28 @@ static void logi_hidpp_dev_conn_notif_equad(struct hidpp_event *hidpp_report, } } +static void logi_hidpp_dev_conn_notif_27mhz(struct hid_device *hdev, + struct hidpp_event *hidpp_report, + struct dj_workitem *workitem) +{ + workitem->type = WORKITEM_TYPE_PAIRED; + workitem->quad_id_lsb = hidpp_report->params[HIDPP_PARAM_27MHZ_DEVID]; + switch (hidpp_report->device_index) { + case 1: /* Index 1 is always a mouse */ + case 2: /* Index 2 is always a mouse */ + workitem->reports_supported |= STD_MOUSE; + break; + case 3: /* Index 3 is always the keyboard */ + case 4: /* Index 4 is used for an optional separate numpad */ + workitem->reports_supported |= STD_KEYBOARD | MULTIMEDIA | + POWER_KEYS; + break; + default: + hid_warn(hdev, "%s: unexpected device-index %d", __func__, + hidpp_report->device_index); + } +} + static void logi_hidpp_recv_queue_notif(struct hid_device *hdev, struct hidpp_event *hidpp_report) { @@ -799,6 +864,7 @@ static void logi_hidpp_recv_queue_notif(struct hid_device *hdev, break; case 0x02: device_type = "27 Mhz"; + logi_hidpp_dev_conn_notif_27mhz(hdev, hidpp_report, &workitem); break; case 0x03: device_type = "QUAD or eQUAD"; @@ -1186,6 +1252,9 @@ static int logi_dj_ll_parse(struct hid_device *hid) if (djdev->dj_receiver_dev->type == recvr_type_gaming_hidpp) rdcat(rdesc, &rsize, mse_high_res_descriptor, sizeof(mse_high_res_descriptor)); + else if (djdev->dj_receiver_dev->type == recvr_type_27mhz) + rdcat(rdesc, &rsize, mse_27mhz_descriptor, + sizeof(mse_27mhz_descriptor)); else rdcat(rdesc, &rsize, mse_descriptor, sizeof(mse_descriptor)); @@ -1357,6 +1426,25 @@ static int logi_dj_hidpp_event(struct hid_device *hdev, spin_lock_irqsave(&djrcv_dev->lock, flags); dj_dev = djrcv_dev->paired_dj_devices[device_index]; + + /* + * With 27 MHz receivers, we do not get an explicit unpair event, + * remove the old device if the user has paired a *different* device. + */ + if (djrcv_dev->type == recvr_type_27mhz && dj_dev && + hidpp_report->sub_id == REPORT_TYPE_NOTIF_DEVICE_CONNECTED && + hidpp_report->params[HIDPP_PARAM_PROTO_TYPE] == 0x02 && + hidpp_report->params[HIDPP_PARAM_27MHZ_DEVID] != + dj_dev->hdev->product) { + struct dj_workitem workitem = { + .device_index = hidpp_report->device_index, + .type = WORKITEM_TYPE_UNPAIRED, + }; + kfifo_in(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem)); + /* logi_hidpp_recv_queue_notif will queue the work */ + dj_dev = NULL; + } + if (dj_dev) { logi_dj_recv_forward_report(dj_dev, data, size); } else { @@ -1628,6 +1716,10 @@ static const struct hid_device_id logi_dj_receivers[] = { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_GAMING), .driver_data = recvr_type_gaming_hidpp}, + { /* Logitech 27 MHz HID++ 1.0 receiver (0xc517) */ + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, + USB_DEVICE_ID_S510_RECEIVER_2), + .driver_data = recvr_type_27mhz}, {} }; diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c index 426753482494..fea7f7ff5ab1 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -432,7 +432,6 @@ static const struct hid_device_id hid_have_special_driver[] = { #if IS_ENABLED(CONFIG_HID_LOGITECH) { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) }, diff --git a/include/linux/hid.h b/include/linux/hid.h index f9707d1dcb58..9f161fa5cbd4 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -382,6 +382,7 @@ struct hid_item { #define HID_GROUP_WACOM 0x0101 #define HID_GROUP_LOGITECH_DJ_DEVICE 0x0102 #define HID_GROUP_STEAM 0x0103 +#define HID_GROUP_LOGITECH_27MHZ_DEVICE 0x0104 /* * HID protocol status From patchwork Sat Apr 20 11:21:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910255 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 E8F5417EE for ; Sat, 20 Apr 2019 11:22:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DA00628D25 for ; Sat, 20 Apr 2019 11:22:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CE93D28D94; Sat, 20 Apr 2019 11:22:49 +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 7C2D528D59 for ; Sat, 20 Apr 2019 11:22:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728079AbfDTLWt (ORCPT ); Sat, 20 Apr 2019 07:22:49 -0400 Received: from mx1.redhat.com ([209.132.183.28]:55602 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726082AbfDTLWt (ORCPT ); Sat, 20 Apr 2019 07:22:49 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id AAE96C067C19; Sat, 20 Apr 2019 11:22:48 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 924E419C5B; Sat, 20 Apr 2019 11:22:47 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 17/37] HID: logitech-dj: add support for 27 MHz mouse-only receivers Date: Sat, 20 Apr 2019 13:21:57 +0200 Message-Id: <20190420112217.27590-18-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Sat, 20 Apr 2019 11:22:48 +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 27 MHz mouse-only receivers send an unnumbered input report with the mouse data, add special handling for this and add the c51b product-id to the logi_dj_receivers table. Signed-off-by: Hans de Goede --- drivers/hid/hid-ids.h | 1 + drivers/hid/hid-logitech-dj.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 9b5f98b5688c..6b1a32b14042 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -762,6 +762,7 @@ #define USB_DEVICE_ID_S510_RECEIVER_2 0xc517 #define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512 #define USB_DEVICE_ID_MX3000_RECEIVER 0xc513 +#define USB_DEVICE_ID_LOGITECH_27MHZ_MOUSE_RECEIVER 0xc51b #define USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER 0xc52b #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER 0xc52f #define USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2 0xc532 diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 3004ca91b76b..08662b97b2cb 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -1483,6 +1483,16 @@ static int logi_dj_raw_event(struct hid_device *hdev, data[0] = data[1]; data[1] = 0; } + /* The 27 MHz mouse-only receiver sends unnumbered mouse data */ + if (djrcv_dev->unnumbered_application == HID_GD_MOUSE && + size == 6) { + u8 mouse_report[7]; + + /* Prepend report id */ + mouse_report[0] = REPORT_TYPE_MOUSE; + memcpy(mouse_report + 1, data, 6); + logi_dj_recv_forward_input_report(hdev, mouse_report, 7); + } return false; } @@ -1720,6 +1730,10 @@ static const struct hid_device_id logi_dj_receivers[] = { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2), .driver_data = recvr_type_27mhz}, + { /* Logitech 27 MHz HID++ 1.0 mouse-only receiver (0xc51b) */ + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, + USB_DEVICE_ID_LOGITECH_27MHZ_MOUSE_RECEIVER), + .driver_data = recvr_type_27mhz}, {} }; From patchwork Sat Apr 20 11:21:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910257 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 06A621515 for ; Sat, 20 Apr 2019 11:22:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EB1A428D25 for ; Sat, 20 Apr 2019 11:22:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DDB8D28D94; Sat, 20 Apr 2019 11:22:51 +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 5D89928D25 for ; Sat, 20 Apr 2019 11:22:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728085AbfDTLWu (ORCPT ); Sat, 20 Apr 2019 07:22:50 -0400 Received: from mx1.redhat.com ([209.132.183.28]:42606 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726082AbfDTLWu (ORCPT ); Sat, 20 Apr 2019 07:22:50 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0EDDE30BA36D; Sat, 20 Apr 2019 11:22:50 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id EDA6819C5A; Sat, 20 Apr 2019 11:22:48 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 18/37] HID: logitech-dj: replace dev_err calls with hid_err calls Date: Sat, 20 Apr 2019 13:21:58 +0200 Message-Id: <20190420112217.27590-19-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.49]); Sat, 20 Apr 2019 11:22:50 +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 Use hid_err consistently everywhere. While at it also tweak some of the messages for clarity, to consistently have a space after a ':' and in some cases to fit within 80 chars. Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-dj.c | 45 ++++++++++++++--------------------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 08662b97b2cb..c73ceb31b94e 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -620,8 +620,7 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, dj_hiddev = hid_allocate_device(); if (IS_ERR(dj_hiddev)) { - dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n", - __func__); + hid_err(djrcv_hdev, "%s: hid_allocate_dev failed\n", __func__); return; } @@ -648,8 +647,7 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, dj_dev = kzalloc(sizeof(struct dj_device), GFP_KERNEL); if (!dj_dev) { - dev_err(&djrcv_hdev->dev, "%s: failed allocating dj_device\n", - __func__); + hid_err(djrcv_hdev, "%s: failed allocating dj_dev\n", __func__); goto dj_device_allocate_fail; } @@ -664,8 +662,7 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, spin_unlock_irqrestore(&djrcv_dev->lock, flags); if (hid_add_device(dj_hiddev)) { - dev_err(&djrcv_hdev->dev, "%s: failed adding dj_device\n", - __func__); + hid_err(djrcv_hdev, "%s: failed adding dj_device\n", __func__); goto hid_add_device_fail; } @@ -1018,7 +1015,7 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; if (!report) { - dev_err(&hdev->dev, "%s: unable to find dj report\n", __func__); + hid_err(hdev, "%s: unable to find dj report\n", __func__); return -ENODEV; } @@ -1138,14 +1135,14 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, static int logi_dj_ll_open(struct hid_device *hid) { - dbg_hid("%s:%s\n", __func__, hid->phys); + dbg_hid("%s: %s\n", __func__, hid->phys); return 0; } static void logi_dj_ll_close(struct hid_device *hid) { - dbg_hid("%s:%s\n", __func__, hid->phys); + dbg_hid("%s: %s\n", __func__, hid->phys); } /* @@ -1346,7 +1343,7 @@ static int logi_dj_dj_event(struct hid_device *hdev, * so ignore those reports too. */ if (dj_report->device_index != DJ_RECEIVER_INDEX) - dev_err(&hdev->dev, "%s: invalid device index:%d\n", + hid_err(hdev, "%s: invalid device index:%d\n", __func__, dj_report->device_index); return false; } @@ -1418,8 +1415,8 @@ static int logi_dj_hidpp_event(struct hid_device *hdev, * This driver can ignore safely the receiver notifications, * so ignore those reports too. */ - dev_err(&hdev->dev, "%s: invalid device index:%d\n", - __func__, hidpp_report->device_index); + hid_err(hdev, "%s: invalid device index:%d\n", __func__, + hidpp_report->device_index); return false; } @@ -1500,27 +1497,25 @@ static int logi_dj_raw_event(struct hid_device *hdev, switch (data[0]) { case REPORT_ID_DJ_SHORT: if (size != DJREPORT_SHORT_LENGTH) { - dev_err(&hdev->dev, "DJ report of bad size (%d)", size); + hid_err(hdev, "Short DJ report bad size (%d)", size); return false; } return logi_dj_dj_event(hdev, report, data, size); case REPORT_ID_DJ_LONG: if (size != DJREPORT_LONG_LENGTH) { - dev_err(&hdev->dev, "DJ report of bad size (%d)", size); + hid_err(hdev, "Long DJ report bad size (%d)", size); return false; } return logi_dj_dj_event(hdev, report, data, size); case REPORT_ID_HIDPP_SHORT: if (size != HIDPP_REPORT_SHORT_LENGTH) { - dev_err(&hdev->dev, - "Short HID++ report of bad size (%d)", size); + hid_err(hdev, "Short HID++ report bad size (%d)", size); return false; } return logi_dj_hidpp_event(hdev, report, data, size); case REPORT_ID_HIDPP_LONG: if (size != HIDPP_REPORT_LONG_LENGTH) { - dev_err(&hdev->dev, - "Long HID++ report of bad size (%d)", size); + hid_err(hdev, "Long HID++ report bad size (%d)", size); return false; } return logi_dj_hidpp_event(hdev, report, data, size); @@ -1548,8 +1543,7 @@ static int logi_dj_probe(struct hid_device *hdev, */ retval = hid_parse(hdev); if (retval) { - dev_err(&hdev->dev, - "%s:parse failed\n", __func__); + hid_err(hdev, "%s: parse failed\n", __func__); return retval; } @@ -1581,8 +1575,7 @@ static int logi_dj_probe(struct hid_device *hdev, djrcv_dev = dj_get_receiver_dev(hdev, id->driver_data, rep->application, has_hidpp); if (!djrcv_dev) { - dev_err(&hdev->dev, - "%s:failed allocating dj_receiver_dev\n", __func__); + hid_err(hdev, "%s: dj_get_receiver_dev failed\n", __func__); return -ENOMEM; } @@ -1593,8 +1586,7 @@ static int logi_dj_probe(struct hid_device *hdev, * hidraw */ retval = hid_hw_start(hdev, HID_CONNECT_HIDRAW|HID_CONNECT_HIDDEV); if (retval) { - dev_err(&hdev->dev, - "%s:hid_hw_start returned error\n", __func__); + hid_err(hdev, "%s: hid_hw_start returned error\n", __func__); goto hid_hw_start_fail; } @@ -1610,7 +1602,7 @@ static int logi_dj_probe(struct hid_device *hdev, /* This is enabling the polling urb on the IN endpoint */ retval = hid_hw_open(hdev); if (retval < 0) { - dev_err(&hdev->dev, "%s:hid_hw_open returned error:%d\n", + hid_err(hdev, "%s: hid_hw_open returned error:%d\n", __func__, retval); goto llopen_failed; } @@ -1655,8 +1647,7 @@ static int logi_dj_reset_resume(struct hid_device *hdev) retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0); if (retval < 0) { - dev_err(&hdev->dev, - "%s:logi_dj_recv_switch_to_dj_mode returned error:%d\n", + hid_err(hdev, "%s: logi_dj_recv_switch_to_dj_mode returned error:%d\n", __func__, retval); } From patchwork Sat Apr 20 11:21:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910259 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 BBF1B17E0 for ; Sat, 20 Apr 2019 11:22:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AD4BE28D25 for ; Sat, 20 Apr 2019 11:22:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9F0A728D94; Sat, 20 Apr 2019 11:22:52 +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 352CC28D25 for ; Sat, 20 Apr 2019 11:22:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728086AbfDTLWv (ORCPT ); Sat, 20 Apr 2019 07:22:51 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54698 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726082AbfDTLWv (ORCPT ); Sat, 20 Apr 2019 07:22:51 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 660342C9774; Sat, 20 Apr 2019 11:22:51 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 508D219C5A; Sat, 20 Apr 2019 11:22:50 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 19/37] HID: logitech-dj: deal with some KVMs adding an extra interface to the usbdev Date: Sat, 20 Apr 2019 13:21:59 +0200 Message-Id: <20190420112217.27590-20-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Sat, 20 Apr 2019 11:22:51 +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 My Aten cs1764a KVM adds an extra interface to the receiver through which it forwards mouse events, if a separate mouse is plugged in next to the receiver dongle. This interface is present even if no extra mouse is plugged in. logitech-dj trying to handle this extra interface causes mouse events send through the extra interface to not be properly handled. This commit fixes this by treating any extra interfaces as hid-generic interfaces. Signed-off-by: Hans de Goede --- Changes in v3: -Fix "do not use assignment in if condition" checkpatch warning --- drivers/hid/hid-logitech-dj.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index c73ceb31b94e..5f06b80bb404 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -27,6 +27,7 @@ #include #include #include +#include /* For to_usb_interface for kvm extra intf check */ #include #include "hid-ids.h" @@ -1463,6 +1464,9 @@ static int logi_dj_raw_event(struct hid_device *hdev, struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev); dbg_hid("%s, size:%d\n", __func__, size); + if (!djrcv_dev) + return 0; + if (!hdev->report_enum[HID_INPUT_REPORT].numbered) { if (djrcv_dev->unnumbered_application == HID_GD_KEYBOARD) { @@ -1532,6 +1536,8 @@ static int logi_dj_probe(struct hid_device *hdev, struct hid_report_enum *rep_enum; struct hid_report *rep; struct dj_receiver_dev *djrcv_dev; + struct usb_interface *intf; + unsigned int no_dj_interfaces = 0; bool has_hidpp = false; unsigned long flags; int retval; @@ -1547,6 +1553,27 @@ static int logi_dj_probe(struct hid_device *hdev, return retval; } + /* + * Some KVMs add an extra interface for e.g. mouse emulation. If we + * treat these as logitech-dj interfaces then this causes input events + * reported through this extra interface to not be reported correctly. + * To avoid this, we treat these as generic-hid devices. + */ + switch (id->driver_data) { + case recvr_type_dj: no_dj_interfaces = 3; break; + case recvr_type_hidpp: no_dj_interfaces = 2; break; + case recvr_type_gaming_hidpp: no_dj_interfaces = 3; break; + case recvr_type_27mhz: no_dj_interfaces = 2; break; + } + if (hid_is_using_ll_driver(hdev, &usb_hid_driver)) { + intf = to_usb_interface(hdev->dev.parent); + if (intf && intf->altsetting->desc.bInterfaceNumber >= + no_dj_interfaces) { + hdev->quirks |= HID_QUIRK_INPUT_PER_APP; + return hid_hw_start(hdev, HID_CONNECT_DEFAULT); + } + } + rep_enum = &hdev->report_enum[HID_INPUT_REPORT]; /* no input reports, bail out */ @@ -1642,7 +1669,7 @@ static int logi_dj_reset_resume(struct hid_device *hdev) int retval; struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev); - if (djrcv_dev->hidpp != hdev) + if (!djrcv_dev || djrcv_dev->hidpp != hdev) return 0; retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0); @@ -1664,6 +1691,9 @@ static void logi_dj_remove(struct hid_device *hdev) dbg_hid("%s\n", __func__); + if (!djrcv_dev) + return hid_hw_stop(hdev); + /* * This ensures that if the work gets requeued from another * interface of the same receiver it will be a no-op. From patchwork Sat Apr 20 11:22:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910261 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 1C95E17E0 for ; Sat, 20 Apr 2019 11:22:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0CB3B28D25 for ; Sat, 20 Apr 2019 11:22:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 003FB28D94; Sat, 20 Apr 2019 11:22:53 +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 9326528D25 for ; Sat, 20 Apr 2019 11:22:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728107AbfDTLWx (ORCPT ); Sat, 20 Apr 2019 07:22:53 -0400 Received: from mx1.redhat.com ([209.132.183.28]:46774 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728105AbfDTLWx (ORCPT ); Sat, 20 Apr 2019 07:22:53 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C401E307CB52; Sat, 20 Apr 2019 11:22:52 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id A868519C5A; Sat, 20 Apr 2019 11:22:51 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 20/37] HID: logitech-dj: pick a better name for non-unifying receivers Date: Sat, 20 Apr 2019 13:22:00 +0200 Message-Id: <20190420112217.27590-21-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Sat, 20 Apr 2019 11:22:52 +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 hidpp_unifying_get_name() does not work for devices attached to non-unifying receivers. Since we do get a device-type in the device- connection report, we can pick a better name for these devices in hid-logitech-dj.c . Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-dj.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 5f06b80bb404..1488b18266cf 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -111,6 +111,9 @@ #define HIDPP_DEVICE_TYPE_MASK GENMASK(3, 0) #define HIDPP_LINK_STATUS_MASK BIT(6) +#define HIDPP_DEVICE_TYPE_KEYBOARD 1 +#define HIDPP_DEVICE_TYPE_MOUSE 2 + #define HIDPP_SET_REGISTER 0x80 #define HIDPP_GET_LONG_REGISTER 0x83 #define HIDPP_REG_CONNECTION_STATE 0x02 @@ -171,6 +174,7 @@ struct dj_device { struct dj_workitem { u8 type; /* WORKITEM_TYPE_* */ u8 device_index; + u8 device_type; u8 quad_id_msb; u8 quad_id_lsb; u32 reports_supported; @@ -632,9 +636,26 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, dj_hiddev->vendor = djrcv_hdev->vendor; dj_hiddev->product = (workitem->quad_id_msb << 8) | workitem->quad_id_lsb; - snprintf(dj_hiddev->name, sizeof(dj_hiddev->name), - "Logitech Unifying Device. Wireless PID:%04x", - dj_hiddev->product); + if (workitem->device_type) { + const char *type_str = "Device"; + + switch (workitem->device_type) { + case 0x01: type_str = "Keyboard"; break; + case 0x02: type_str = "Mouse"; break; + case 0x03: type_str = "Numpad"; break; + case 0x04: type_str = "Presenter"; break; + case 0x07: type_str = "Remote Control"; break; + case 0x08: type_str = "Trackball"; break; + case 0x09: type_str = "Touchpad"; break; + } + snprintf(dj_hiddev->name, sizeof(dj_hiddev->name), + "Logitech Wireless %s PID:%04x", + type_str, dj_hiddev->product); + } else { + snprintf(dj_hiddev->name, sizeof(dj_hiddev->name), + "Logitech Unifying Device. Wireless PID:%04x", + dj_hiddev->product); + } if (djrcv_dev->type == recvr_type_27mhz) dj_hiddev->group = HID_GROUP_LOGITECH_27MHZ_DEVICE; @@ -809,10 +830,11 @@ static void logi_hidpp_dev_conn_notif_equad(struct hidpp_event *hidpp_report, struct dj_workitem *workitem) { workitem->type = WORKITEM_TYPE_PAIRED; + workitem->device_type = hidpp_report->params[HIDPP_PARAM_DEVICE_INFO] & + HIDPP_DEVICE_TYPE_MASK; workitem->quad_id_msb = hidpp_report->params[HIDPP_PARAM_EQUAD_MSB]; workitem->quad_id_lsb = hidpp_report->params[HIDPP_PARAM_EQUAD_LSB]; - switch (hidpp_report->params[HIDPP_PARAM_DEVICE_INFO] & - HIDPP_DEVICE_TYPE_MASK) { + switch (workitem->device_type) { case REPORT_TYPE_KEYBOARD: workitem->reports_supported |= STD_KEYBOARD | MULTIMEDIA | POWER_KEYS | MEDIA_CENTER; @@ -832,10 +854,12 @@ static void logi_hidpp_dev_conn_notif_27mhz(struct hid_device *hdev, switch (hidpp_report->device_index) { case 1: /* Index 1 is always a mouse */ case 2: /* Index 2 is always a mouse */ + workitem->device_type = HIDPP_DEVICE_TYPE_MOUSE; workitem->reports_supported |= STD_MOUSE; break; case 3: /* Index 3 is always the keyboard */ case 4: /* Index 4 is used for an optional separate numpad */ + workitem->device_type = HIDPP_DEVICE_TYPE_KEYBOARD; workitem->reports_supported |= STD_KEYBOARD | MULTIMEDIA | POWER_KEYS; break; From patchwork Sat Apr 20 11:22:01 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910263 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 54AD21515 for ; Sat, 20 Apr 2019 11:22:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4461328D25 for ; Sat, 20 Apr 2019 11:22:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3880828D94; Sat, 20 Apr 2019 11:22:55 +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 D4C4F28D25 for ; Sat, 20 Apr 2019 11:22:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728110AbfDTLWy (ORCPT ); Sat, 20 Apr 2019 07:22:54 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56696 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728105AbfDTLWy (ORCPT ); Sat, 20 Apr 2019 07:22:54 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2ACB4307FBCB; Sat, 20 Apr 2019 11:22:54 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1290219C5A; Sat, 20 Apr 2019 11:22:52 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 21/37] HID: logitech-dj: remove false-positive error on double queueing of delayed-work Date: Sat, 20 Apr 2019 13:22:01 +0200 Message-Id: <20190420112217.27590-22-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.41]); Sat, 20 Apr 2019 11:22:54 +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 various functions queueing work-items do not check there already is a work-item queued before calling schedule_work(), as such they may race with each-other and with the re-queuing done by the delayedwork_callback itself. This is fine as the delayedwork_callback simply is a nop if scheduled once too much. I've actually seen the false-positive hid_err for this trigger in practice, so lets remove it. While at it also remove the somewhat overzealous debugging around the schedule_work() calls. Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-dj.c | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 1488b18266cf..e30ed320207b 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -727,17 +727,12 @@ static void delayedwork_callback(struct work_struct *work) count = kfifo_out(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem)); if (count != sizeof(workitem)) { - hid_err(djrcv_dev->hidpp, "delayedwork queued without workitems available\n"); spin_unlock_irqrestore(&djrcv_dev->lock, flags); return; } - if (!kfifo_is_empty(&djrcv_dev->notif_fifo)) { - if (schedule_work(&djrcv_dev->work) == 0) { - dbg_hid("%s: did not schedule the work item, was " - "already queued\n", __func__); - } - } + if (!kfifo_is_empty(&djrcv_dev->notif_fifo)) + schedule_work(&djrcv_dev->work); spin_unlock_irqrestore(&djrcv_dev->lock, flags); @@ -819,11 +814,7 @@ static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev, } kfifo_in(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem)); - - if (schedule_work(&djrcv_dev->work) == 0) { - dbg_hid("%s: did not schedule the work item, was already " - "queued\n", __func__); - } + schedule_work(&djrcv_dev->work); } static void logi_hidpp_dev_conn_notif_equad(struct hidpp_event *hidpp_report, @@ -933,13 +924,8 @@ static void logi_hidpp_recv_queue_notif(struct hid_device *hdev, device_type, hidpp_report->params[HIDPP_PARAM_PROTO_TYPE], hidpp_report->device_index); - kfifo_in(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem)); - - if (schedule_work(&djrcv_dev->work) == 0) { - dbg_hid("%s: did not schedule the work item, was already queued\n", - __func__); - } + schedule_work(&djrcv_dev->work); } static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev, From patchwork Sat Apr 20 11:22:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910265 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 5A9BB17E0 for ; Sat, 20 Apr 2019 11:22:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 493F228D25 for ; Sat, 20 Apr 2019 11:22:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3DCEE28D94; Sat, 20 Apr 2019 11:22:57 +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 BA3DF28D25 for ; Sat, 20 Apr 2019 11:22:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728112AbfDTLW4 (ORCPT ); Sat, 20 Apr 2019 07:22:56 -0400 Received: from mx1.redhat.com ([209.132.183.28]:44630 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728105AbfDTLW4 (ORCPT ); Sat, 20 Apr 2019 07:22:56 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 803323082B15; Sat, 20 Apr 2019 11:22:55 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6C68719C5A; Sat, 20 Apr 2019 11:22:54 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 22/37] HID: logitech-dj: make appending of the HID++ descriptors conditional Date: Sat, 20 Apr 2019 13:22:02 +0200 Message-Id: <20190420112217.27590-23-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.45]); Sat, 20 Apr 2019 11:22:55 +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 Make the appending of the HID++ descriptors in logi_dj_ll_parse conditional. This is a preparation patch for adding support for the Logitech mini Bluetooth receiver in HID proxy mode (its default mode), where some of the paired devices may not be Logitech devices and thus may not be HID++ capable. This uses a fake bit 63 in reports_supported, which is changed from an u32 to an u64 for this. Bits <= 31 are not usable for this because that would cause a behavioral change in logi_dj_recv_forward_null_report. Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-dj.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index e30ed320207b..154cc37ed8fd 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -100,6 +100,8 @@ #define POWER_KEYS BIT(4) #define MEDIA_CENTER BIT(8) #define KBD_LEDS BIT(14) +/* Fake (bitnr > NUMBER_OF_HID_REPORTS) bit to track HID++ capability */ +#define HIDPP BIT_ULL(63) /* HID++ Device Connected Notification */ #define REPORT_TYPE_NOTIF_DEVICE_CONNECTED 0x41 @@ -162,7 +164,7 @@ struct dj_receiver_dev { struct dj_device { struct hid_device *hdev; struct dj_receiver_dev *dj_receiver_dev; - u32 reports_supported; + u64 reports_supported; u8 device_index; }; @@ -177,7 +179,7 @@ struct dj_workitem { u8 device_type; u8 quad_id_msb; u8 quad_id_lsb; - u32 reports_supported; + u64 reports_supported; }; /* Keyboard descriptor (1) */ @@ -805,6 +807,7 @@ static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev, workitem.reports_supported = get_unaligned_le32( dj_report->report_params + DEVICE_PAIRED_RF_REPORT_TYPE); + workitem.reports_supported |= HIDPP; if (dj_report->report_type == REPORT_TYPE_NOTIF_DEVICE_UNPAIRED) workitem.type = WORKITEM_TYPE_UNPAIRED; break; @@ -828,10 +831,11 @@ static void logi_hidpp_dev_conn_notif_equad(struct hidpp_event *hidpp_report, switch (workitem->device_type) { case REPORT_TYPE_KEYBOARD: workitem->reports_supported |= STD_KEYBOARD | MULTIMEDIA | - POWER_KEYS | MEDIA_CENTER; + POWER_KEYS | MEDIA_CENTER | + HIDPP; break; case REPORT_TYPE_MOUSE: - workitem->reports_supported |= STD_MOUSE; + workitem->reports_supported |= STD_MOUSE | HIDPP; break; } } @@ -846,13 +850,13 @@ static void logi_hidpp_dev_conn_notif_27mhz(struct hid_device *hdev, case 1: /* Index 1 is always a mouse */ case 2: /* Index 2 is always a mouse */ workitem->device_type = HIDPP_DEVICE_TYPE_MOUSE; - workitem->reports_supported |= STD_MOUSE; + workitem->reports_supported |= STD_MOUSE | HIDPP; break; case 3: /* Index 3 is always the keyboard */ case 4: /* Index 4 is used for an optional separate numpad */ workitem->device_type = HIDPP_DEVICE_TYPE_KEYBOARD; workitem->reports_supported |= STD_KEYBOARD | MULTIMEDIA | - POWER_KEYS; + POWER_KEYS | HIDPP; break; default: hid_warn(hdev, "%s: unexpected device-index %d", __func__, @@ -1249,14 +1253,14 @@ static int logi_dj_ll_parse(struct hid_device *hid) return -ENOMEM; if (djdev->reports_supported & STD_KEYBOARD) { - dbg_hid("%s: sending a kbd descriptor, reports_supported: %x\n", + dbg_hid("%s: sending a kbd descriptor, reports_supported: %llx\n", __func__, djdev->reports_supported); rdcat(rdesc, &rsize, kbd_descriptor, sizeof(kbd_descriptor)); } if (djdev->reports_supported & STD_MOUSE) { - dbg_hid("%s: sending a mouse descriptor, reports_supported: " - "%x\n", __func__, djdev->reports_supported); + dbg_hid("%s: sending a mouse descriptor, reports_supported: %llx\n", + __func__, djdev->reports_supported); if (djdev->dj_receiver_dev->type == recvr_type_gaming_hidpp) rdcat(rdesc, &rsize, mse_high_res_descriptor, sizeof(mse_high_res_descriptor)); @@ -1269,29 +1273,32 @@ static int logi_dj_ll_parse(struct hid_device *hid) } if (djdev->reports_supported & MULTIMEDIA) { - dbg_hid("%s: sending a multimedia report descriptor: %x\n", + dbg_hid("%s: sending a multimedia report descriptor: %llx\n", __func__, djdev->reports_supported); rdcat(rdesc, &rsize, consumer_descriptor, sizeof(consumer_descriptor)); } if (djdev->reports_supported & POWER_KEYS) { - dbg_hid("%s: sending a power keys report descriptor: %x\n", + dbg_hid("%s: sending a power keys report descriptor: %llx\n", __func__, djdev->reports_supported); rdcat(rdesc, &rsize, syscontrol_descriptor, sizeof(syscontrol_descriptor)); } if (djdev->reports_supported & MEDIA_CENTER) { - dbg_hid("%s: sending a media center report descriptor: %x\n", + dbg_hid("%s: sending a media center report descriptor: %llx\n", __func__, djdev->reports_supported); rdcat(rdesc, &rsize, media_descriptor, sizeof(media_descriptor)); } if (djdev->reports_supported & KBD_LEDS) { - dbg_hid("%s: need to send kbd leds report descriptor: %x\n", + dbg_hid("%s: need to send kbd leds report descriptor: %llx\n", __func__, djdev->reports_supported); } - rdcat(rdesc, &rsize, hidpp_descriptor, sizeof(hidpp_descriptor)); + if (djdev->reports_supported & HIDPP) { + rdcat(rdesc, &rsize, hidpp_descriptor, + sizeof(hidpp_descriptor)); + } retval = hid_parse_report(hid, rdesc, rsize); kfree(rdesc); From patchwork Sat Apr 20 11:22:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910267 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 F022D17E0 for ; Sat, 20 Apr 2019 11:22:58 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DF2A528D25 for ; Sat, 20 Apr 2019 11:22:58 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D33BC28D94; Sat, 20 Apr 2019 11:22:58 +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 3B2DB28D25 for ; Sat, 20 Apr 2019 11:22:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728115AbfDTLW5 (ORCPT ); Sat, 20 Apr 2019 07:22:57 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49214 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728105AbfDTLW5 (ORCPT ); Sat, 20 Apr 2019 07:22:57 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D901D309264D; Sat, 20 Apr 2019 11:22:56 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id C443919C5A; Sat, 20 Apr 2019 11:22:55 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 23/37] HID: logitech-dj: add support for Logitech Bluetooth Mini-Receiver Date: Sat, 20 Apr 2019 13:22:03 +0200 Message-Id: <20190420112217.27590-24-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.43]); Sat, 20 Apr 2019 11:22:56 +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 Add support for the Logitech Bluetooth Mini-Receiver in HID proxy mode This requires some special handing in dj_find_receiver_dev because the BT Mini-Receiver contains a built-in hub and has separate USB-devices for the keyboard and mouse interfaces, rather then using 2 interfaces on a single USB device. Otherwise this receiver works identical to the standard non-unifying nano receivers. Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-dj.c | 91 ++++++++++++++++++++++++++++++++--- 1 file changed, 85 insertions(+), 6 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 154cc37ed8fd..64e68ac871cb 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -112,6 +112,7 @@ #define HIDPP_PARAM_27MHZ_DEVID 0x03 #define HIDPP_DEVICE_TYPE_MASK GENMASK(3, 0) #define HIDPP_LINK_STATUS_MASK BIT(6) +#define HIDPP_MANUFACTURER_MASK BIT(7) #define HIDPP_DEVICE_TYPE_KEYBOARD 1 #define HIDPP_DEVICE_TYPE_MOUSE 2 @@ -128,6 +129,7 @@ enum recvr_type { recvr_type_hidpp, recvr_type_gaming_hidpp, recvr_type_27mhz, + recvr_type_bluetooth, }; struct dj_report { @@ -295,6 +297,55 @@ static const char mse_27mhz_descriptor[] = { 0xC0, /* END_COLLECTION */ }; +/* Mouse descriptor (2) for Bluetooth receiver, low-res hwheel, 12 buttons */ +static const char mse_bluetooth_descriptor[] = { + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x02, /* USAGE (Mouse) */ + 0xA1, 0x01, /* COLLECTION (Application) */ + 0x85, 0x02, /* REPORT_ID = 2 */ + 0x09, 0x01, /* USAGE (pointer) */ + 0xA1, 0x00, /* COLLECTION (physical) */ + 0x05, 0x09, /* USAGE_PAGE (buttons) */ + 0x19, 0x01, /* USAGE_MIN (1) */ + 0x29, 0x08, /* USAGE_MAX (8) */ + 0x15, 0x00, /* LOGICAL_MIN (0) */ + 0x25, 0x01, /* LOGICAL_MAX (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (data var abs) */ + 0x05, 0x01, /* USAGE_PAGE (generic desktop) */ + 0x16, 0x01, 0xF8, /* LOGICAL_MIN (-2047) */ + 0x26, 0xFF, 0x07, /* LOGICAL_MAX (2047) */ + 0x75, 0x0C, /* REPORT_SIZE (12) */ + 0x95, 0x02, /* REPORT_COUNT (2) */ + 0x09, 0x30, /* USAGE (X) */ + 0x09, 0x31, /* USAGE (Y) */ + 0x81, 0x06, /* INPUT */ + 0x15, 0x81, /* LOGICAL_MIN (-127) */ + 0x25, 0x7F, /* LOGICAL_MAX (127) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x09, 0x38, /* USAGE (wheel) */ + 0x81, 0x06, /* INPUT */ + 0x05, 0x0C, /* USAGE_PAGE(consumer) */ + 0x0A, 0x38, 0x02, /* USAGE(AC Pan) */ + 0x15, 0xF9, /* LOGICAL_MIN (-7) */ + 0x25, 0x07, /* LOGICAL_MAX (7) */ + 0x75, 0x04, /* REPORT_SIZE (4) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x81, 0x06, /* INPUT */ + 0x05, 0x09, /* USAGE_PAGE (buttons) */ + 0x19, 0x09, /* USAGE_MIN (9) */ + 0x29, 0x0C, /* USAGE_MAX (12) */ + 0x15, 0x00, /* LOGICAL_MIN (0) */ + 0x25, 0x01, /* LOGICAL_MAX (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x95, 0x04, /* REPORT_COUNT (4) */ + 0x81, 0x06, /* INPUT */ + 0xC0, /* END_COLLECTION */ + 0xC0, /* END_COLLECTION */ +}; + /* Gaming Mouse descriptor (2) */ static const char mse_high_res_descriptor[] = { 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ @@ -441,7 +492,7 @@ static const char hidpp_descriptor[] = { /* Make sure all descriptors are present here */ #define MAX_RDESC_SIZE \ (sizeof(kbd_descriptor) + \ - sizeof(mse_descriptor) + \ + sizeof(mse_bluetooth_descriptor) + \ sizeof(consumer_descriptor) + \ sizeof(syscontrol_descriptor) + \ sizeof(media_descriptor) + \ @@ -486,24 +537,32 @@ static DEFINE_MUTEX(dj_hdev_list_lock); * to create a single struct dj_receiver_dev for all interfaces belonging to * a single USB-device / receiver. */ -static struct dj_receiver_dev *dj_find_receiver_dev(struct hid_device *hdev) +static struct dj_receiver_dev *dj_find_receiver_dev(struct hid_device *hdev, + enum recvr_type type) { struct dj_receiver_dev *djrcv_dev; + char sep; + + /* + * The bluetooth receiver contains a built-in hub and has separate + * USB-devices for the keyboard and mouse interfaces. + */ + sep = (type == recvr_type_bluetooth) ? '.' : '/'; /* Try to find an already-probed interface from the same device */ list_for_each_entry(djrcv_dev, &dj_hdev_list, list) { if (djrcv_dev->mouse && - hid_compare_device_paths(hdev, djrcv_dev->mouse, '/')) { + hid_compare_device_paths(hdev, djrcv_dev->mouse, sep)) { kref_get(&djrcv_dev->kref); return djrcv_dev; } if (djrcv_dev->keyboard && - hid_compare_device_paths(hdev, djrcv_dev->keyboard, '/')) { + hid_compare_device_paths(hdev, djrcv_dev->keyboard, sep)) { kref_get(&djrcv_dev->kref); return djrcv_dev; } if (djrcv_dev->hidpp && - hid_compare_device_paths(hdev, djrcv_dev->hidpp, '/')) { + hid_compare_device_paths(hdev, djrcv_dev->hidpp, sep)) { kref_get(&djrcv_dev->kref); return djrcv_dev; } @@ -548,7 +607,7 @@ static struct dj_receiver_dev *dj_get_receiver_dev(struct hid_device *hdev, mutex_lock(&dj_hdev_list_lock); - djrcv_dev = dj_find_receiver_dev(hdev); + djrcv_dev = dj_find_receiver_dev(hdev, type); if (!djrcv_dev) { djrcv_dev = kzalloc(sizeof(*djrcv_dev), GFP_KERNEL); if (!djrcv_dev) @@ -878,6 +937,14 @@ static void logi_hidpp_recv_queue_notif(struct hid_device *hdev, switch (hidpp_report->params[HIDPP_PARAM_PROTO_TYPE]) { case 0x01: device_type = "Bluetooth"; + /* Bluetooth connect packet contents is the same as (e)QUAD */ + logi_hidpp_dev_conn_notif_equad(hidpp_report, &workitem); + if (!(hidpp_report->params[HIDPP_PARAM_DEVICE_INFO] & + HIDPP_MANUFACTURER_MASK)) { + hid_info(hdev, "Non Logitech device connected on slot %d\n", + hidpp_report->device_index); + workitem.reports_supported &= ~HIDPP; + } break; case 0x02: device_type = "27 Mhz"; @@ -1267,6 +1334,9 @@ static int logi_dj_ll_parse(struct hid_device *hid) else if (djdev->dj_receiver_dev->type == recvr_type_27mhz) rdcat(rdesc, &rsize, mse_27mhz_descriptor, sizeof(mse_27mhz_descriptor)); + else if (djdev->dj_receiver_dev->type == recvr_type_bluetooth) + rdcat(rdesc, &rsize, mse_bluetooth_descriptor, + sizeof(mse_bluetooth_descriptor)); else rdcat(rdesc, &rsize, mse_descriptor, sizeof(mse_descriptor)); @@ -1581,6 +1651,7 @@ static int logi_dj_probe(struct hid_device *hdev, case recvr_type_hidpp: no_dj_interfaces = 2; break; case recvr_type_gaming_hidpp: no_dj_interfaces = 3; break; case recvr_type_27mhz: no_dj_interfaces = 2; break; + case recvr_type_bluetooth: no_dj_interfaces = 2; break; } if (hid_is_using_ll_driver(hdev, &usb_hid_driver)) { intf = to_usb_interface(hdev->dev.parent); @@ -1772,6 +1843,14 @@ static const struct hid_device_id logi_dj_receivers[] = { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_27MHZ_MOUSE_RECEIVER), .driver_data = recvr_type_27mhz}, + { /* Logitech MX5000 HID++ / bluetooth receiver keyboard intf. */ + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, + 0xc70e), + .driver_data = recvr_type_bluetooth}, + { /* Logitech MX5000 HID++ / bluetooth receiver mouse intf. */ + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, + 0xc70a), + .driver_data = recvr_type_bluetooth}, {} }; From patchwork Sat Apr 20 11:22:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910269 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 2EAB01515 for ; Sat, 20 Apr 2019 11:23:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1F48A28D25 for ; Sat, 20 Apr 2019 11:23:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 12F1D28D94; Sat, 20 Apr 2019 11:23:02 +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 8BCF728D25 for ; Sat, 20 Apr 2019 11:23:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728117AbfDTLXB (ORCPT ); Sat, 20 Apr 2019 07:23:01 -0400 Received: from mx1.redhat.com ([209.132.183.28]:39598 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728105AbfDTLXB (ORCPT ); Sat, 20 Apr 2019 07:23:01 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4A284C0A1AF7; Sat, 20 Apr 2019 11:23:00 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 28A6619C5A; Sat, 20 Apr 2019 11:22:57 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 24/37] HID: logitech-hidpp: allow non HID++ devices to be handled by this module Date: Sat, 20 Apr 2019 13:22:04 +0200 Message-Id: <20190420112217.27590-25-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Sat, 20 Apr 2019 11:23:00 +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 From: Benjamin Tissoires On the gaming mice, there are 2 interfaces, one for the mouse and one for the macros. Better allow everybody to go through hid-logitech-hidpp than trying to be smarter. Signed-off-by: Benjamin Tissoires Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-hidpp.c | 76 ++++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 8 deletions(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 965479fe2736..3b4d466963af 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -2783,6 +2783,9 @@ static int hidpp_input_mapping(struct hid_device *hdev, struct hid_input *hi, { struct hidpp_device *hidpp = hid_get_drvdata(hdev); + if (!hidpp) + return 0; + if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) return wtp_input_mapping(hdev, hi, field, usage, bit, max); else if (hidpp->quirks & HIDPP_QUIRK_CLASS_M560 && @@ -2798,6 +2801,9 @@ static int hidpp_input_mapped(struct hid_device *hdev, struct hid_input *hi, { struct hidpp_device *hidpp = hid_get_drvdata(hdev); + if (!hidpp) + return 0; + /* Ensure that Logitech G920 is not given a default fuzz/flat value */ if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) { if (usage->type == EV_ABS && (usage->code == ABS_X || @@ -2829,6 +2835,9 @@ static int hidpp_input_configured(struct hid_device *hdev, struct hidpp_device *hidpp = hid_get_drvdata(hdev); struct input_dev *input = hidinput->input; + if (!hidpp) + return 0; + hidpp_populate_input(hidpp, input, true); return 0; @@ -2898,6 +2907,9 @@ static int hidpp_raw_event(struct hid_device *hdev, struct hid_report *report, struct hidpp_device *hidpp = hid_get_drvdata(hdev); int ret = 0; + if (!hidpp) + return 0; + /* Generic HID++ processing. */ switch (data[0]) { case REPORT_ID_HIDPP_VERY_LONG: @@ -2946,7 +2958,12 @@ static int hidpp_event(struct hid_device *hdev, struct hid_field *field, * restriction imposed in hidpp_usages. */ struct hidpp_device *hidpp = hid_get_drvdata(hdev); - struct hidpp_scroll_counter *counter = &hidpp->vertical_wheel_counter; + struct hidpp_scroll_counter *counter; + + if (!hidpp) + return 0; + + counter = &hidpp->vertical_wheel_counter; /* A scroll event may occur before the multiplier has been retrieved or * the input device set, or high-res scroll enabling may fail. In such * cases we must return early (falling back to default behaviour) to @@ -3202,6 +3219,41 @@ static const struct attribute_group ps_attribute_group = { .attrs = sysfs_attrs }; +static bool hidpp_validate_report(struct hid_device *hdev, int id, int size, + bool optional) +{ + struct hid_report_enum *re; + struct hid_report *report; + + if (id >= HID_MAX_IDS || id < 0) { + hid_err(hdev, "invalid HID report id %u\n", id); + return false; + } + + re = &(hdev->report_enum[HID_OUTPUT_REPORT]); + report = re->report_id_hash[id]; + + if (!report) + return optional; + + if (report->field[0]->report_count < size) { + hid_warn(hdev, "not enough values in hidpp report %d\n", id); + return false; + } + + return true; +} + +static bool hidpp_validate_device(struct hid_device *hdev) +{ + return hidpp_validate_report(hdev, REPORT_ID_HIDPP_SHORT, + HIDPP_REPORT_SHORT_LENGTH - 1, false) && + hidpp_validate_report(hdev, REPORT_ID_HIDPP_LONG, + HIDPP_REPORT_LONG_LENGTH - 1, true) && + hidpp_validate_report(hdev, REPORT_ID_HIDPP_VERY_LONG, + HIDPP_REPORT_VERY_LONG_LENGTH - 1, true); +} + static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) { struct hidpp_device *hidpp; @@ -3209,6 +3261,18 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) bool connected; unsigned int connect_mask = HID_CONNECT_DEFAULT; + ret = hid_parse(hdev); + if (ret) { + hid_err(hdev, "%s:parse failed\n", __func__); + return ret; + } + + /* + * Make sure the device is HID++ capable, otherwise treat as generic HID + */ + if (!hidpp_validate_device(hdev)) + return hid_hw_start(hdev, HID_CONNECT_DEFAULT); + hidpp = devm_kzalloc(&hdev->dev, sizeof(struct hidpp_device), GFP_KERNEL); if (!hidpp) @@ -3252,12 +3316,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) hid_warn(hdev, "Cannot allocate sysfs group for %s\n", hdev->name); - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "%s:parse failed\n", __func__); - goto hid_parse_fail; - } - if (hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT) connect_mask &= ~HID_CONNECT_HIDINPUT; @@ -3330,7 +3388,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) hid_hw_stop(hdev); } hid_hw_start_fail: -hid_parse_fail: sysfs_remove_group(&hdev->dev.kobj, &ps_attribute_group); cancel_work_sync(&hidpp->work); mutex_destroy(&hidpp->send_mutex); @@ -3341,6 +3398,9 @@ static void hidpp_remove(struct hid_device *hdev) { struct hidpp_device *hidpp = hid_get_drvdata(hdev); + if (!hidpp) + return hid_hw_stop(hdev); + sysfs_remove_group(&hdev->dev.kobj, &ps_attribute_group); if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) { From patchwork Sat Apr 20 11:22:05 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910271 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 456C61515 for ; Sat, 20 Apr 2019 11:23:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3636328D25 for ; Sat, 20 Apr 2019 11:23:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2A55328D94; Sat, 20 Apr 2019 11:23:03 +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 A5BCD28D25 for ; Sat, 20 Apr 2019 11:23:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728119AbfDTLXC (ORCPT ); Sat, 20 Apr 2019 07:23:02 -0400 Received: from mx1.redhat.com ([209.132.183.28]:37676 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728105AbfDTLXC (ORCPT ); Sat, 20 Apr 2019 07:23:02 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A203E81114; Sat, 20 Apr 2019 11:23:01 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8C60819C5A; Sat, 20 Apr 2019 11:23:00 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 25/37] HID: logitech-hidpp: make .probe usbhid capable Date: Sat, 20 Apr 2019 13:22:05 +0200 Message-Id: <20190420112217.27590-26-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Sat, 20 Apr 2019 11:23:01 +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 From: Benjamin Tissoires The current custom solution for the G920 is not the best because hid_hw_start() is not called at the end of the .probe(). It means that any configuration retrieved after the initial hid_hw_start would not be exposed to user space without races. We can simply force hid_hw_start to just enable the transport layer by not using a connect_mask. This way, we can have a common path between USB, Unifying and Bluetooth devices. With this change, we can now support the non DJ receivers for low end devices, which will allow us to fetch the actual names of the paired device (instead of 'Logitech Wireless Receiver') Tested with a M185 with the non unifying receiver, a T650 and many other unifying devices, and the T651 over Bluetooth. Signed-off-by: Benjamin Tissoires Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-hidpp.c | 86 +++++++++++++++++--------------- 1 file changed, 45 insertions(+), 41 deletions(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 3b4d466963af..b389fcc1a894 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -3316,24 +3316,23 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) hid_warn(hdev, "Cannot allocate sysfs group for %s\n", hdev->name); - if (hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT) - connect_mask &= ~HID_CONNECT_HIDINPUT; - - if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) { - ret = hid_hw_start(hdev, connect_mask); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto hid_hw_start_fail; - } - ret = hid_hw_open(hdev); - if (ret < 0) { - dev_err(&hdev->dev, "%s:hid_hw_open returned error:%d\n", - __func__, ret); - hid_hw_stop(hdev); - goto hid_hw_start_fail; - } + /* + * Plain USB connections need to actually call start and open + * on the transport driver to allow incoming data. + */ + ret = hid_hw_start(hdev, 0); + if (ret) { + hid_err(hdev, "hw start failed\n"); + goto hid_hw_start_fail; } + ret = hid_hw_open(hdev); + if (ret < 0) { + dev_err(&hdev->dev, "%s:hid_hw_open returned error:%d\n", + __func__, ret); + hid_hw_stop(hdev); + goto hid_hw_open_fail; + } /* Allow incoming packets */ hid_device_io_start(hdev); @@ -3347,7 +3346,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) if (!connected) { ret = -ENODEV; hid_err(hdev, "Device not connected"); - goto hid_hw_open_failed; + goto hid_hw_init_fail; } hidpp_overwrite_name(hdev); @@ -3356,37 +3355,36 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)) { ret = wtp_get_config(hidpp); if (ret) - goto hid_hw_open_failed; + goto hid_hw_init_fail; } else if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_G920)) { ret = g920_get_config(hidpp); if (ret) - goto hid_hw_open_failed; + goto hid_hw_init_fail; } - /* Block incoming packets */ - hid_device_io_stop(hdev); + hidpp_connect_event(hidpp); - if (!(hidpp->quirks & HIDPP_QUIRK_CLASS_G920)) { - ret = hid_hw_start(hdev, connect_mask); - if (ret) { - hid_err(hdev, "%s:hid_hw_start returned error\n", __func__); - goto hid_hw_start_fail; - } - } + /* Reset the HID node state */ + hid_device_io_stop(hdev); + hid_hw_close(hdev); + hid_hw_stop(hdev); - /* Allow incoming packets */ - hid_device_io_start(hdev); + if (hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT) + connect_mask &= ~HID_CONNECT_HIDINPUT; - hidpp_connect_event(hidpp); + /* Now export the actual inputs and hidraw nodes to the world */ + ret = hid_hw_start(hdev, connect_mask); + if (ret) { + hid_err(hdev, "%s:hid_hw_start returned error\n", __func__); + goto hid_hw_start_fail; + } return ret; -hid_hw_open_failed: - hid_device_io_stop(hdev); - if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) { - hid_hw_close(hdev); - hid_hw_stop(hdev); - } +hid_hw_init_fail: + hid_hw_close(hdev); +hid_hw_open_fail: + hid_hw_stop(hdev); hid_hw_start_fail: sysfs_remove_group(&hdev->dev.kobj, &ps_attribute_group); cancel_work_sync(&hidpp->work); @@ -3403,10 +3401,9 @@ static void hidpp_remove(struct hid_device *hdev) sysfs_remove_group(&hdev->dev.kobj, &ps_attribute_group); - if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) { + if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) hidpp_ff_deinit(hdev); - hid_hw_close(hdev); - } + hid_hw_stop(hdev); cancel_work_sync(&hidpp->work); mutex_destroy(&hidpp->send_mutex); @@ -3470,7 +3467,14 @@ static const struct hid_device_id hidpp_devices[] = { { LDJ_DEVICE(HID_ANY_ID) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL), + { /* Logitech G403 Gaming Mouse over USB */ + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC082) }, + { /* Logitech G700 Gaming Mouse over USB */ + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC06B) }, + { /* Logitech G900 Gaming Mouse over USB */ + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC081) }, + { /* Logitech G920 Wheel over USB */ + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL), .driver_data = HIDPP_QUIRK_CLASS_G920 | HIDPP_QUIRK_FORCE_OUTPUT_REPORTS}, {} }; From patchwork Sat Apr 20 11:22:06 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910273 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 27DB117E0 for ; Sat, 20 Apr 2019 11:23:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1540E28D25 for ; Sat, 20 Apr 2019 11:23:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0996228D94; Sat, 20 Apr 2019 11:23:04 +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 AC58028D25 for ; Sat, 20 Apr 2019 11:23:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728122AbfDTLXD (ORCPT ); Sat, 20 Apr 2019 07:23:03 -0400 Received: from mx1.redhat.com ([209.132.183.28]:37686 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728105AbfDTLXD (ORCPT ); Sat, 20 Apr 2019 07:23:03 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 053D381114; Sat, 20 Apr 2019 11:23:03 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id E3C8319C5A; Sat, 20 Apr 2019 11:23:01 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 26/37] HID: logitech-hidpp: ignore very-short or empty names Date: Sat, 20 Apr 2019 13:22:06 +0200 Message-Id: <20190420112217.27590-27-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Sat, 20 Apr 2019 11:23:03 +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 devices report an empty or very short name, in this case stick with the name generated by the logitech-dj code instead of overriding it with e.g. "Logitech ". Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-hidpp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index b389fcc1a894..e7f082374943 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -741,6 +741,9 @@ static char *hidpp_unifying_get_name(struct hidpp_device *hidpp_dev) if (2 + len > sizeof(response.rap.params)) return NULL; + if (len < 4) /* logitech devices are usually at least Xddd */ + return NULL; + name = kzalloc(len + 1, GFP_KERNEL); if (!name) return NULL; From patchwork Sat Apr 20 11:22:07 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910275 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 34A8217E0 for ; Sat, 20 Apr 2019 11:23:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2597A28D25 for ; Sat, 20 Apr 2019 11:23:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 19B6D28D94; Sat, 20 Apr 2019 11:23:07 +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 BA1DC28D25 for ; Sat, 20 Apr 2019 11:23:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726280AbfDTLXG (ORCPT ); Sat, 20 Apr 2019 07:23:06 -0400 Received: from mx1.redhat.com ([209.132.183.28]:37694 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726267AbfDTLXG (ORCPT ); Sat, 20 Apr 2019 07:23:06 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E355981114; Sat, 20 Apr 2019 11:23:05 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4802E19C5A; Sat, 20 Apr 2019 11:23:03 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 27/37] HID: logitech-hidpp: do not make failure to get the name fatal Date: Sat, 20 Apr 2019 13:22:07 +0200 Message-Id: <20190420112217.27590-28-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Sat, 20 Apr 2019 11:23:05 +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 With devices attached to a non-unifying 2.4GHz receiver we sometimes fail to get the name. This is not a fatal error, we can just continue with the original name. So instead of bailing out, continue with battery-initialization when this happens. This fixes the battery not getting registered when we fail to get the name. Signed-off-by: Hans de Goede --- Changes in v3: -Fix "do not use assignment in if condition" checkpatch warning --- drivers/hid/hid-logitech-hidpp.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index e7f082374943..2a0866e6face 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -3160,18 +3160,15 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) if (hidpp->name == hdev->name && hidpp->protocol_major >= 2) { name = hidpp_get_device_name(hidpp); - if (!name) { - hid_err(hdev, - "unable to retrieve the name of the device"); - return; - } - - devm_name = devm_kasprintf(&hdev->dev, GFP_KERNEL, "%s", name); - kfree(name); - if (!devm_name) - return; + if (name) { + devm_name = devm_kasprintf(&hdev->dev, GFP_KERNEL, + "%s", name); + kfree(name); + if (!devm_name) + return; - hidpp->name = devm_name; + hidpp->name = devm_name; + } } hidpp_initialize_battery(hidpp); From patchwork Sat Apr 20 11:22:08 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910277 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 501001515 for ; Sat, 20 Apr 2019 11:23:08 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 41AEB28D25 for ; Sat, 20 Apr 2019 11:23:08 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 363B928D94; Sat, 20 Apr 2019 11:23:08 +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 E864228D25 for ; Sat, 20 Apr 2019 11:23:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726542AbfDTLXH (ORCPT ); Sat, 20 Apr 2019 07:23:07 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51210 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726267AbfDTLXH (ORCPT ); Sat, 20 Apr 2019 07:23:07 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 47CA620B02; Sat, 20 Apr 2019 11:23:07 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 31BFC19C5A; Sat, 20 Apr 2019 11:23:06 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 28/37] HID: logitech-hidpp: remove double assignment from __hidpp_send_report Date: Sat, 20 Apr 2019 13:22:08 +0200 Message-Id: <20190420112217.27590-29-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Sat, 20 Apr 2019 11:23:07 +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 hidpp variable is already initialized with hid_get_drvdata(hdev) when it is declared, drop the second no-op assignment. Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-hidpp.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 2a0866e6face..e9bf61d21423 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -206,8 +206,6 @@ static int __hidpp_send_report(struct hid_device *hdev, struct hidpp_device *hidpp = hid_get_drvdata(hdev); int fields_count, ret; - hidpp = hid_get_drvdata(hdev); - switch (hidpp_report->report_id) { case REPORT_ID_HIDPP_SHORT: fields_count = HIDPP_REPORT_SHORT_LENGTH; From patchwork Sat Apr 20 11:22:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910279 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 EE09C17E0 for ; Sat, 20 Apr 2019 11:23:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DF66F28D25 for ; Sat, 20 Apr 2019 11:23:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D386C28D95; Sat, 20 Apr 2019 11:23:09 +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 75A9528D59 for ; Sat, 20 Apr 2019 11:23:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726382AbfDTLXJ (ORCPT ); Sat, 20 Apr 2019 07:23:09 -0400 Received: from mx1.redhat.com ([209.132.183.28]:42628 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726267AbfDTLXI (ORCPT ); Sat, 20 Apr 2019 07:23:08 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9FBC0308FECF; Sat, 20 Apr 2019 11:23:08 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8B34419C5A; Sat, 20 Apr 2019 11:23:07 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 29/37] HID: logitech-hidpp: remove unused origin_is_hid_core function parameter Date: Sat, 20 Apr 2019 13:22:09 +0200 Message-Id: <20190420112217.27590-30-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.49]); Sat, 20 Apr 2019 11:23:08 +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 All the various populate_input functions have an origin_is_hid_core function parameter, but none use it, remove it. Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-hidpp.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index e9bf61d21423..b0da186ef5e7 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -2226,7 +2226,7 @@ static int wtp_input_mapping(struct hid_device *hdev, struct hid_input *hi, } static void wtp_populate_input(struct hidpp_device *hidpp, - struct input_dev *input_dev, bool origin_is_hid_core) + struct input_dev *input_dev) { struct wtp_data *wd = hidpp->private_data; @@ -2622,7 +2622,7 @@ static int m560_raw_event(struct hid_device *hdev, u8 *data, int size) } static void m560_populate_input(struct hidpp_device *hidpp, - struct input_dev *input_dev, bool origin_is_hid_core) + struct input_dev *input_dev) { struct m560_private_data *mydata = hidpp->private_data; @@ -2819,12 +2819,12 @@ static int hidpp_input_mapped(struct hid_device *hdev, struct hid_input *hi, static void hidpp_populate_input(struct hidpp_device *hidpp, - struct input_dev *input, bool origin_is_hid_core) + struct input_dev *input) { if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) - wtp_populate_input(hidpp, input, origin_is_hid_core); + wtp_populate_input(hidpp, input); else if (hidpp->quirks & HIDPP_QUIRK_CLASS_M560) - m560_populate_input(hidpp, input, origin_is_hid_core); + m560_populate_input(hidpp, input); if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL) hidpp->vertical_wheel_counter.dev = input; @@ -2839,7 +2839,7 @@ static int hidpp_input_configured(struct hid_device *hdev, if (!hidpp) return 0; - hidpp_populate_input(hidpp, input, true); + hidpp_populate_input(hidpp, input); return 0; } @@ -3197,7 +3197,7 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) return; } - hidpp_populate_input(hidpp, input, false); + hidpp_populate_input(hidpp, input); ret = input_register_device(input); if (ret) From patchwork Sat Apr 20 11:22:10 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910281 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 7C3E817E0 for ; Sat, 20 Apr 2019 11:23:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6DEA628D25 for ; Sat, 20 Apr 2019 11:23:11 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6267828D95; Sat, 20 Apr 2019 11:23:11 +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 CCA3928D25 for ; Sat, 20 Apr 2019 11:23:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726562AbfDTLXK (ORCPT ); Sat, 20 Apr 2019 07:23:10 -0400 Received: from mx1.redhat.com ([209.132.183.28]:35566 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726267AbfDTLXK (ORCPT ); Sat, 20 Apr 2019 07:23:10 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0449B308402A; Sat, 20 Apr 2019 11:23:10 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id E22CA19C5A; Sat, 20 Apr 2019 11:23:08 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 30/37] HID: logitech-hidpp: use RAP instead of FAP to get the protocol version Date: Sat, 20 Apr 2019 13:22:10 +0200 Message-Id: <20190420112217.27590-31-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.40]); Sat, 20 Apr 2019 11:23:10 +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 According to the logitech_hidpp_2.0_specification_draft_2012-06-04.pdf doc: https://lekensteyn.nl/files/logitech/logitech_hidpp_2.0_specification_draft_2012-06-04.pdf We should use a register-access-protocol request using the short input / output report ids. This is necessary because 27MHz HID++ receivers have a max-packetsize on their HIP++ endpoint of 8, so they cannot support long reports. Using a feature-access-protocol request (which is always long or very-long) with these will cause a timeout error, followed by the hidpp driver treating the device as not being HID++ capable. This commit fixes this by switching to using a rap request to get the protocol version. Besides being tested with a (046d:c517) 27MHz receiver with various 27MHz keyboards and mice, this has also been tested to not cause regressions on a non-unifying dual-HID++ nano receiver (046d:c534) with k270 and m185 HID++-2.0 devices connected and on a unifying/dj receiver (046d:c52b) with a HID++-2.0 Logitech Rechargeable Touchpad T650. Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-hidpp.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index b0da186ef5e7..243426097c51 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -837,13 +837,16 @@ static int hidpp_root_get_feature(struct hidpp_device *hidpp, u16 feature, static int hidpp_root_get_protocol_version(struct hidpp_device *hidpp) { + const u8 ping_byte = 0x5a; + u8 ping_data[3] = { 0, 0, ping_byte }; struct hidpp_report response; int ret; - ret = hidpp_send_fap_command_sync(hidpp, + ret = hidpp_send_rap_command_sync(hidpp, + REPORT_ID_HIDPP_SHORT, HIDPP_PAGE_ROOT_IDX, CMD_ROOT_GET_PROTOCOL_VERSION, - NULL, 0, &response); + ping_data, sizeof(ping_data), &response); if (ret == HIDPP_ERROR_INVALID_SUBID) { hidpp->protocol_major = 1; @@ -863,8 +866,14 @@ static int hidpp_root_get_protocol_version(struct hidpp_device *hidpp) if (ret) return ret; - hidpp->protocol_major = response.fap.params[0]; - hidpp->protocol_minor = response.fap.params[1]; + if (response.rap.params[2] != ping_byte) { + hid_err(hidpp->hid_dev, "%s: ping mismatch 0x%02x != 0x%02x\n", + __func__, response.rap.params[2], ping_byte); + return -EPROTO; + } + + hidpp->protocol_major = response.rap.params[0]; + hidpp->protocol_minor = response.rap.params[1]; print_version: hid_info(hidpp->hid_dev, "HID++ %u.%u device connected.\n", From patchwork Sat Apr 20 11:22:11 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910283 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 89A6A1515 for ; Sat, 20 Apr 2019 11:23:12 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7ACE928D25 for ; Sat, 20 Apr 2019 11:23:12 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6F22E28D95; Sat, 20 Apr 2019 11:23:12 +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 1473B28D25 for ; Sat, 20 Apr 2019 11:23:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728105AbfDTLXL (ORCPT ); Sat, 20 Apr 2019 07:23:11 -0400 Received: from mx1.redhat.com ([209.132.183.28]:39620 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726267AbfDTLXL (ORCPT ); Sat, 20 Apr 2019 07:23:11 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 60D83C0A1AE8; Sat, 20 Apr 2019 11:23:11 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4A16419C5A; Sat, 20 Apr 2019 11:23:10 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 31/37] HID: logitech-hidpp: handle devices attached to 27MHz wireless receivers Date: Sat, 20 Apr 2019 13:22:11 +0200 Message-Id: <20190420112217.27590-32-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Sat, 20 Apr 2019 11:23:11 +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 Logitech 27MHz devices are HID++ devices, so handle them in the hidpp driver, this enables battery monitoring on these devices (and more in follow-up patches). Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-hidpp.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 243426097c51..e8a552c8801d 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -3420,6 +3420,10 @@ static void hidpp_remove(struct hid_device *hdev) HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, \ USB_VENDOR_ID_LOGITECH, (product)) +#define L27MHZ_DEVICE(product) \ + HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_27MHZ_DEVICE, \ + USB_VENDOR_ID_LOGITECH, (product)) + static const struct hid_device_id hidpp_devices[] = { { /* wireless touchpad */ LDJ_DEVICE(0x4011), @@ -3474,6 +3478,8 @@ static const struct hid_device_id hidpp_devices[] = { { LDJ_DEVICE(HID_ANY_ID) }, + { L27MHZ_DEVICE(HID_ANY_ID) }, + { /* Logitech G403 Gaming Mouse over USB */ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC082) }, { /* Logitech G700 Gaming Mouse over USB */ From patchwork Sat Apr 20 11:22:12 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910285 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 9086B17E0 for ; Sat, 20 Apr 2019 11:23:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7FF4328D25 for ; Sat, 20 Apr 2019 11:23:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7431428D95; Sat, 20 Apr 2019 11:23:14 +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 01F5228D25 for ; Sat, 20 Apr 2019 11:23:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726302AbfDTLXN (ORCPT ); Sat, 20 Apr 2019 07:23:13 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49238 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726267AbfDTLXN (ORCPT ); Sat, 20 Apr 2019 07:23:13 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B87B7309264D; Sat, 20 Apr 2019 11:23:12 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id A2DB519C5A; Sat, 20 Apr 2019 11:23:11 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 32/37] HID: logitech-hidpp: do not hardcode very long report length Date: Sat, 20 Apr 2019 13:22:12 +0200 Message-Id: <20190420112217.27590-33-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.43]); Sat, 20 Apr 2019 11:23:12 +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 HID++ spec says the following about the very long report length: "n Bytes, depends on HID++ collection declaration". Hardcoding this breaks talking to some HID++ devices over BlueTooth, since they declare only 45 bytes data for the very long report, rather then the hardcoded 63. This commit fixes this by getting the actual report length from the descriptors. Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-hidpp.c | 50 ++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index e8a552c8801d..ecf1b1e22e1a 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -51,7 +51,7 @@ MODULE_PARM_DESC(disable_tap_to_click, #define HIDPP_REPORT_SHORT_LENGTH 7 #define HIDPP_REPORT_LONG_LENGTH 20 -#define HIDPP_REPORT_VERY_LONG_LENGTH 64 +#define HIDPP_REPORT_VERY_LONG_MAX_LENGTH 64 #define HIDPP_QUIRK_CLASS_WTP BIT(0) #define HIDPP_QUIRK_CLASS_M560 BIT(1) @@ -106,13 +106,13 @@ MODULE_PARM_DESC(disable_tap_to_click, struct fap { u8 feature_index; u8 funcindex_clientid; - u8 params[HIDPP_REPORT_VERY_LONG_LENGTH - 4U]; + u8 params[HIDPP_REPORT_VERY_LONG_MAX_LENGTH - 4U]; }; struct rap { u8 sub_id; u8 reg_address; - u8 params[HIDPP_REPORT_VERY_LONG_LENGTH - 4U]; + u8 params[HIDPP_REPORT_VERY_LONG_MAX_LENGTH - 4U]; }; struct hidpp_report { @@ -162,6 +162,7 @@ struct hidpp_device { void *send_receive_buf; char *name; /* will never be NULL and should not be freed */ wait_queue_head_t wait; + int very_long_report_length; bool answer_available; u8 protocol_major; u8 protocol_minor; @@ -214,7 +215,7 @@ static int __hidpp_send_report(struct hid_device *hdev, fields_count = HIDPP_REPORT_LONG_LENGTH; break; case REPORT_ID_HIDPP_VERY_LONG: - fields_count = HIDPP_REPORT_VERY_LONG_LENGTH; + fields_count = hidpp->very_long_report_length; break; default: return -ENODEV; @@ -340,7 +341,7 @@ static int hidpp_send_rap_command_sync(struct hidpp_device *hidpp_dev, max_count = HIDPP_REPORT_LONG_LENGTH - 4; break; case REPORT_ID_HIDPP_VERY_LONG: - max_count = HIDPP_REPORT_VERY_LONG_LENGTH - 4; + max_count = hidpp_dev->very_long_report_length - 4; break; default: return -EINVAL; @@ -934,7 +935,7 @@ static int hidpp_devicenametype_get_device_name(struct hidpp_device *hidpp, switch (response.report_id) { case REPORT_ID_HIDPP_VERY_LONG: - count = HIDPP_REPORT_VERY_LONG_LENGTH - 4; + count = hidpp->very_long_report_length - 4; break; case REPORT_ID_HIDPP_LONG: count = HIDPP_REPORT_LONG_LENGTH - 4; @@ -2923,7 +2924,7 @@ static int hidpp_raw_event(struct hid_device *hdev, struct hid_report *report, /* Generic HID++ processing. */ switch (data[0]) { case REPORT_ID_HIDPP_VERY_LONG: - if (size != HIDPP_REPORT_VERY_LONG_LENGTH) { + if (size != hidpp->very_long_report_length) { hid_err(hdev, "received hid++ report of bad size (%d)", size); return 1; @@ -3226,24 +3227,34 @@ static const struct attribute_group ps_attribute_group = { .attrs = sysfs_attrs }; -static bool hidpp_validate_report(struct hid_device *hdev, int id, int size, - bool optional) +static int hidpp_get_report_length(struct hid_device *hdev, int id) { struct hid_report_enum *re; struct hid_report *report; + re = &(hdev->report_enum[HID_OUTPUT_REPORT]); + report = re->report_id_hash[id]; + if (!report) + return 0; + + return report->field[0]->report_count + 1; +} + +static bool hidpp_validate_report(struct hid_device *hdev, int id, + int expected_length, bool optional) +{ + int report_length; + if (id >= HID_MAX_IDS || id < 0) { hid_err(hdev, "invalid HID report id %u\n", id); return false; } - re = &(hdev->report_enum[HID_OUTPUT_REPORT]); - report = re->report_id_hash[id]; - - if (!report) + report_length = hidpp_get_report_length(hdev, id); + if (!report_length) return optional; - if (report->field[0]->report_count < size) { + if (report_length < expected_length) { hid_warn(hdev, "not enough values in hidpp report %d\n", id); return false; } @@ -3254,11 +3265,9 @@ static bool hidpp_validate_report(struct hid_device *hdev, int id, int size, static bool hidpp_validate_device(struct hid_device *hdev) { return hidpp_validate_report(hdev, REPORT_ID_HIDPP_SHORT, - HIDPP_REPORT_SHORT_LENGTH - 1, false) && + HIDPP_REPORT_SHORT_LENGTH, false) && hidpp_validate_report(hdev, REPORT_ID_HIDPP_LONG, - HIDPP_REPORT_LONG_LENGTH - 1, true) && - hidpp_validate_report(hdev, REPORT_ID_HIDPP_VERY_LONG, - HIDPP_REPORT_VERY_LONG_LENGTH - 1, true); + HIDPP_REPORT_LONG_LENGTH, true); } static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) @@ -3291,6 +3300,11 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) hidpp->quirks = id->driver_data; + hidpp->very_long_report_length = + hidpp_get_report_length(hdev, REPORT_ID_HIDPP_VERY_LONG); + if (hidpp->very_long_report_length > HIDPP_REPORT_VERY_LONG_MAX_LENGTH) + hidpp->very_long_report_length = HIDPP_REPORT_VERY_LONG_MAX_LENGTH; + if (id->group == HID_GROUP_LOGITECH_DJ_DEVICE) hidpp->quirks |= HIDPP_QUIRK_UNIFYING; From patchwork Sat Apr 20 11:22:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910287 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 61D8317E0 for ; Sat, 20 Apr 2019 11:23:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 528E628D25 for ; Sat, 20 Apr 2019 11:23:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4691028D95; Sat, 20 Apr 2019 11:23:16 +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 7611428D25 for ; Sat, 20 Apr 2019 11:23:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728138AbfDTLXP (ORCPT ); Sat, 20 Apr 2019 07:23:15 -0400 Received: from mx1.redhat.com ([209.132.183.28]:44656 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726267AbfDTLXO (ORCPT ); Sat, 20 Apr 2019 07:23:14 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1C6363082B15; Sat, 20 Apr 2019 11:23:14 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0748019C5A; Sat, 20 Apr 2019 11:23:12 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 33/37] HID: logitech-hidpp: add input_device ptr to struct hidpp_device Date: Sat, 20 Apr 2019 13:22:13 +0200 Message-Id: <20190420112217.27590-34-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.45]); Sat, 20 Apr 2019 11:23:14 +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 Most device-class specific code needs access to the input_device, instead of storing that in the class specific data-struct, simply store this into the hidpp_device struct itself. In case of the m560 this avoids the need for having private data at all and this will also avoid the need to add private data in some upcoming patches. Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-hidpp.c | 143 ++++++++++++------------------- 1 file changed, 56 insertions(+), 87 deletions(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index ecf1b1e22e1a..5ef3f76c3f66 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -149,7 +149,6 @@ struct hidpp_battery { * @last_time: last event time, used to reset remainder after inactivity */ struct hidpp_scroll_counter { - struct input_dev *dev; int wheel_multiplier; int remainder; int direction; @@ -158,6 +157,7 @@ struct hidpp_scroll_counter { struct hidpp_device { struct hid_device *hid_dev; + struct input_dev *input; struct mutex send_mutex; void *send_receive_buf; char *name; /* will never be NULL and should not be freed */ @@ -433,14 +433,15 @@ static void hidpp_prefix_name(char **name, int name_length) * emit low-resolution scroll events when appropriate for * backwards-compatibility with userspace input libraries. */ -static void hidpp_scroll_counter_handle_scroll(struct hidpp_scroll_counter *counter, +static void hidpp_scroll_counter_handle_scroll(struct input_dev *input_dev, + struct hidpp_scroll_counter *counter, int hi_res_value) { int low_res_value, remainder, direction; unsigned long long now, previous; hi_res_value = hi_res_value * 120/counter->wheel_multiplier; - input_report_rel(counter->dev, REL_WHEEL_HI_RES, hi_res_value); + input_report_rel(input_dev, REL_WHEEL_HI_RES, hi_res_value); remainder = counter->remainder; direction = hi_res_value > 0 ? 1 : -1; @@ -474,7 +475,7 @@ static void hidpp_scroll_counter_handle_scroll(struct hidpp_scroll_counter *coun low_res_value = remainder / 120; if (low_res_value == 0) low_res_value = (hi_res_value > 0 ? 1 : -1); - input_report_rel(counter->dev, REL_WHEEL, low_res_value); + input_report_rel(input_dev, REL_WHEEL, low_res_value); remainder -= low_res_value * 120; } counter->remainder = remainder; @@ -2218,7 +2219,6 @@ static int hidpp_ff_deinit(struct hid_device *hid) #define WTP_MANUAL_RESOLUTION 39 struct wtp_data { - struct input_dev *input; u16 x_size, y_size; u8 finger_count; u8 mt_feature_index; @@ -2262,31 +2262,30 @@ static void wtp_populate_input(struct hidpp_device *hidpp, input_mt_init_slots(input_dev, wd->maxcontacts, INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED); - - wd->input = input_dev; } -static void wtp_touch_event(struct wtp_data *wd, +static void wtp_touch_event(struct hidpp_device *hidpp, struct hidpp_touchpad_raw_xy_finger *touch_report) { + struct wtp_data *wd = hidpp->private_data; int slot; if (!touch_report->finger_id || touch_report->contact_type) /* no actual data */ return; - slot = input_mt_get_slot_by_key(wd->input, touch_report->finger_id); + slot = input_mt_get_slot_by_key(hidpp->input, touch_report->finger_id); - input_mt_slot(wd->input, slot); - input_mt_report_slot_state(wd->input, MT_TOOL_FINGER, + input_mt_slot(hidpp->input, slot); + input_mt_report_slot_state(hidpp->input, MT_TOOL_FINGER, touch_report->contact_status); if (touch_report->contact_status) { - input_event(wd->input, EV_ABS, ABS_MT_POSITION_X, + input_event(hidpp->input, EV_ABS, ABS_MT_POSITION_X, touch_report->x); - input_event(wd->input, EV_ABS, ABS_MT_POSITION_Y, + input_event(hidpp->input, EV_ABS, ABS_MT_POSITION_Y, wd->flip_y ? wd->y_size - touch_report->y : touch_report->y); - input_event(wd->input, EV_ABS, ABS_MT_PRESSURE, + input_event(hidpp->input, EV_ABS, ABS_MT_PRESSURE, touch_report->area); } } @@ -2294,19 +2293,18 @@ static void wtp_touch_event(struct wtp_data *wd, static void wtp_send_raw_xy_event(struct hidpp_device *hidpp, struct hidpp_touchpad_raw_xy *raw) { - struct wtp_data *wd = hidpp->private_data; int i; for (i = 0; i < 2; i++) - wtp_touch_event(wd, &(raw->fingers[i])); + wtp_touch_event(hidpp, &(raw->fingers[i])); if (raw->end_of_frame && !(hidpp->quirks & HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS)) - input_event(wd->input, EV_KEY, BTN_LEFT, raw->button); + input_event(hidpp->input, EV_KEY, BTN_LEFT, raw->button); if (raw->end_of_frame || raw->finger_count <= 2) { - input_mt_sync_frame(wd->input); - input_sync(wd->input); + input_mt_sync_frame(hidpp->input); + input_sync(hidpp->input); } } @@ -2356,7 +2354,7 @@ static int wtp_raw_event(struct hid_device *hdev, u8 *data, int size) struct hidpp_report *report = (struct hidpp_report *)data; struct hidpp_touchpad_raw_xy raw; - if (!wd || !wd->input) + if (!wd || !hidpp->input) return 1; switch (data[0]) { @@ -2367,11 +2365,11 @@ static int wtp_raw_event(struct hid_device *hdev, u8 *data, int size) return 1; } if (hidpp->quirks & HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS) { - input_event(wd->input, EV_KEY, BTN_LEFT, + input_event(hidpp->input, EV_KEY, BTN_LEFT, !!(data[1] & 0x01)); - input_event(wd->input, EV_KEY, BTN_RIGHT, + input_event(hidpp->input, EV_KEY, BTN_RIGHT, !!(data[1] & 0x02)); - input_sync(wd->input); + input_sync(hidpp->input); return 0; } else { if (size < 21) @@ -2489,10 +2487,6 @@ static int wtp_connect(struct hid_device *hdev, bool connected) static const u8 m560_config_parameter[] = {0x00, 0xaf, 0x03}; -struct m560_private_data { - struct input_dev *input; -}; - /* how buttons are mapped in the report */ #define M560_MOUSE_BTN_LEFT 0x01 #define M560_MOUSE_BTN_RIGHT 0x02 @@ -2520,28 +2514,12 @@ static int m560_send_config_command(struct hid_device *hdev, bool connected) ); } -static int m560_allocate(struct hid_device *hdev) -{ - struct hidpp_device *hidpp = hid_get_drvdata(hdev); - struct m560_private_data *d; - - d = devm_kzalloc(&hdev->dev, sizeof(struct m560_private_data), - GFP_KERNEL); - if (!d) - return -ENOMEM; - - hidpp->private_data = d; - - return 0; -}; - static int m560_raw_event(struct hid_device *hdev, u8 *data, int size) { struct hidpp_device *hidpp = hid_get_drvdata(hdev); - struct m560_private_data *mydata = hidpp->private_data; /* sanity check */ - if (!mydata || !mydata->input) { + if (!hidpp->input) { hid_err(hdev, "error in parameter\n"); return -EINVAL; } @@ -2568,24 +2546,24 @@ static int m560_raw_event(struct hid_device *hdev, u8 *data, int size) switch (data[5]) { case 0xaf: - input_report_key(mydata->input, BTN_MIDDLE, 1); + input_report_key(hidpp->input, BTN_MIDDLE, 1); break; case 0xb0: - input_report_key(mydata->input, BTN_FORWARD, 1); + input_report_key(hidpp->input, BTN_FORWARD, 1); break; case 0xae: - input_report_key(mydata->input, BTN_BACK, 1); + input_report_key(hidpp->input, BTN_BACK, 1); break; case 0x00: - input_report_key(mydata->input, BTN_BACK, 0); - input_report_key(mydata->input, BTN_FORWARD, 0); - input_report_key(mydata->input, BTN_MIDDLE, 0); + input_report_key(hidpp->input, BTN_BACK, 0); + input_report_key(hidpp->input, BTN_FORWARD, 0); + input_report_key(hidpp->input, BTN_MIDDLE, 0); break; default: hid_err(hdev, "error in report\n"); return 0; } - input_sync(mydata->input); + input_sync(hidpp->input); } else if (data[0] == 0x02) { /* @@ -2599,33 +2577,33 @@ static int m560_raw_event(struct hid_device *hdev, u8 *data, int size) int v; - input_report_key(mydata->input, BTN_LEFT, + input_report_key(hidpp->input, BTN_LEFT, !!(data[1] & M560_MOUSE_BTN_LEFT)); - input_report_key(mydata->input, BTN_RIGHT, + input_report_key(hidpp->input, BTN_RIGHT, !!(data[1] & M560_MOUSE_BTN_RIGHT)); if (data[1] & M560_MOUSE_BTN_WHEEL_LEFT) { - input_report_rel(mydata->input, REL_HWHEEL, -1); - input_report_rel(mydata->input, REL_HWHEEL_HI_RES, + input_report_rel(hidpp->input, REL_HWHEEL, -1); + input_report_rel(hidpp->input, REL_HWHEEL_HI_RES, -120); } else if (data[1] & M560_MOUSE_BTN_WHEEL_RIGHT) { - input_report_rel(mydata->input, REL_HWHEEL, 1); - input_report_rel(mydata->input, REL_HWHEEL_HI_RES, + input_report_rel(hidpp->input, REL_HWHEEL, 1); + input_report_rel(hidpp->input, REL_HWHEEL_HI_RES, 120); } v = hid_snto32(hid_field_extract(hdev, data+3, 0, 12), 12); - input_report_rel(mydata->input, REL_X, v); + input_report_rel(hidpp->input, REL_X, v); v = hid_snto32(hid_field_extract(hdev, data+3, 12, 12), 12); - input_report_rel(mydata->input, REL_Y, v); + input_report_rel(hidpp->input, REL_Y, v); v = hid_snto32(data[6], 8); if (v != 0) - hidpp_scroll_counter_handle_scroll( + hidpp_scroll_counter_handle_scroll(hidpp->input, &hidpp->vertical_wheel_counter, v); - input_sync(mydata->input); + input_sync(hidpp->input); } return 1; @@ -2634,24 +2612,20 @@ static int m560_raw_event(struct hid_device *hdev, u8 *data, int size) static void m560_populate_input(struct hidpp_device *hidpp, struct input_dev *input_dev) { - struct m560_private_data *mydata = hidpp->private_data; - - mydata->input = input_dev; - - __set_bit(EV_KEY, mydata->input->evbit); - __set_bit(BTN_MIDDLE, mydata->input->keybit); - __set_bit(BTN_RIGHT, mydata->input->keybit); - __set_bit(BTN_LEFT, mydata->input->keybit); - __set_bit(BTN_BACK, mydata->input->keybit); - __set_bit(BTN_FORWARD, mydata->input->keybit); + __set_bit(EV_KEY, input_dev->evbit); + __set_bit(BTN_MIDDLE, input_dev->keybit); + __set_bit(BTN_RIGHT, input_dev->keybit); + __set_bit(BTN_LEFT, input_dev->keybit); + __set_bit(BTN_BACK, input_dev->keybit); + __set_bit(BTN_FORWARD, input_dev->keybit); - __set_bit(EV_REL, mydata->input->evbit); - __set_bit(REL_X, mydata->input->relbit); - __set_bit(REL_Y, mydata->input->relbit); - __set_bit(REL_WHEEL, mydata->input->relbit); - __set_bit(REL_HWHEEL, mydata->input->relbit); - __set_bit(REL_WHEEL_HI_RES, mydata->input->relbit); - __set_bit(REL_HWHEEL_HI_RES, mydata->input->relbit); + __set_bit(EV_REL, input_dev->evbit); + __set_bit(REL_X, input_dev->relbit); + __set_bit(REL_Y, input_dev->relbit); + __set_bit(REL_WHEEL, input_dev->relbit); + __set_bit(REL_HWHEEL, input_dev->relbit); + __set_bit(REL_WHEEL_HI_RES, input_dev->relbit); + __set_bit(REL_HWHEEL_HI_RES, input_dev->relbit); } static int m560_input_mapping(struct hid_device *hdev, struct hid_input *hi, @@ -2831,13 +2805,12 @@ static int hidpp_input_mapped(struct hid_device *hdev, struct hid_input *hi, static void hidpp_populate_input(struct hidpp_device *hidpp, struct input_dev *input) { + hidpp->input = input; + if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) wtp_populate_input(hidpp, input); else if (hidpp->quirks & HIDPP_QUIRK_CLASS_M560) m560_populate_input(hidpp, input); - - if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL) - hidpp->vertical_wheel_counter.dev = input; } static int hidpp_input_configured(struct hid_device *hdev, @@ -2981,10 +2954,10 @@ static int hidpp_event(struct hid_device *hdev, struct hid_field *field, * avoid a crash in hidpp_scroll_counter_handle_scroll. */ if (!(hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL) || value == 0 - || counter->dev == NULL || counter->wheel_multiplier == 0) + || hidpp->input == NULL || counter->wheel_multiplier == 0) return 0; - hidpp_scroll_counter_handle_scroll(counter, value); + hidpp_scroll_counter_handle_scroll(hidpp->input, counter, value); return 1; } @@ -3317,10 +3290,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = wtp_allocate(hdev, id); if (ret) return ret; - } else if (hidpp->quirks & HIDPP_QUIRK_CLASS_M560) { - ret = m560_allocate(hdev); - if (ret) - return ret; } else if (hidpp->quirks & HIDPP_QUIRK_CLASS_K400) { ret = k400_allocate(hdev); if (ret) From patchwork Sat Apr 20 11:22:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910289 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 E41A41515 for ; Sat, 20 Apr 2019 11:23:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D527D28D25 for ; Sat, 20 Apr 2019 11:23:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C9AAE28D95; Sat, 20 Apr 2019 11:23:16 +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 703C928D25 for ; Sat, 20 Apr 2019 11:23:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728141AbfDTLXQ (ORCPT ); Sat, 20 Apr 2019 07:23:16 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51232 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726267AbfDTLXP (ORCPT ); Sat, 20 Apr 2019 07:23:15 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 74A2E1F566; Sat, 20 Apr 2019 11:23:15 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5F04819C65; Sat, 20 Apr 2019 11:23:14 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 34/37] HID: logitech-hidpp: make hidpp10_set_register_bit a bit more generic Date: Sat, 20 Apr 2019 13:22:14 +0200 Message-Id: <20190420112217.27590-35-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Sat, 20 Apr 2019 11:23:15 +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 Make hidpp10_set_register_bit() take a mask and value for the register byte being changed, rather then making it only set a single bit. While at it also at defines for the bits which we will be using. Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-hidpp.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 5ef3f76c3f66..2b769766e158 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -491,14 +491,16 @@ static void hidpp_scroll_counter_handle_scroll(struct input_dev *input_dev, #define HIDPP_GET_LONG_REGISTER 0x83 /** - * hidpp10_set_register_bit() - Sets a single bit in a HID++ 1.0 register. + * hidpp10_set_register - Modify a HID++ 1.0 register. * @hidpp_dev: the device to set the register on. * @register_address: the address of the register to modify. * @byte: the byte of the register to modify. Should be less than 3. + * @mask: mask of the bits to modify + * @value: new values for the bits in mask * Return: 0 if successful, otherwise a negative error code. */ -static int hidpp10_set_register_bit(struct hidpp_device *hidpp_dev, - u8 register_address, u8 byte, u8 bit) +static int hidpp10_set_register(struct hidpp_device *hidpp_dev, + u8 register_address, u8 byte, u8 mask, u8 value) { struct hidpp_report response; int ret; @@ -514,7 +516,8 @@ static int hidpp10_set_register_bit(struct hidpp_device *hidpp_dev, memcpy(params, response.rap.params, 3); - params[byte] |= BIT(bit); + params[byte] &= ~mask; + params[byte] |= value & mask; return hidpp_send_rap_command_sync(hidpp_dev, REPORT_ID_HIDPP_SHORT, @@ -523,20 +526,28 @@ static int hidpp10_set_register_bit(struct hidpp_device *hidpp_dev, params, 3, &response); } - -#define HIDPP_REG_GENERAL 0x00 +#define HIDPP_REG_ENABLE_REPORTS 0x00 +#define HIDPP_ENABLE_CONSUMER_REPORT BIT(0) +#define HIDPP_ENABLE_WHEEL_REPORT BIT(2) +#define HIDPP_ENABLE_MOUSE_EXTRA_BTN_REPORT BIT(3) +#define HIDPP_ENABLE_BAT_REPORT BIT(4) +#define HIDPP_ENABLE_HWHEEL_REPORT BIT(5) static int hidpp10_enable_battery_reporting(struct hidpp_device *hidpp_dev) { - return hidpp10_set_register_bit(hidpp_dev, HIDPP_REG_GENERAL, 0, 4); + return hidpp10_set_register(hidpp_dev, HIDPP_REG_ENABLE_REPORTS, 0, + HIDPP_ENABLE_BAT_REPORT, HIDPP_ENABLE_BAT_REPORT); } #define HIDPP_REG_FEATURES 0x01 +#define HIDPP_ENABLE_SPECIAL_BUTTON_FUNC BIT(1) +#define HIDPP_ENABLE_FAST_SCROLL BIT(6) /* On HID++ 1.0 devices, high-res scroll was called "scrolling acceleration". */ static int hidpp10_enable_scrolling_acceleration(struct hidpp_device *hidpp_dev) { - return hidpp10_set_register_bit(hidpp_dev, HIDPP_REG_FEATURES, 0, 6); + return hidpp10_set_register(hidpp_dev, HIDPP_REG_FEATURES, 0, + HIDPP_ENABLE_FAST_SCROLL, HIDPP_ENABLE_FAST_SCROLL); } #define HIDPP_REG_BATTERY_STATUS 0x07 From patchwork Sat Apr 20 11:22:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910291 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 54E751515 for ; Sat, 20 Apr 2019 11:23:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4520728D25 for ; Sat, 20 Apr 2019 11:23:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3922528D95; Sat, 20 Apr 2019 11:23:21 +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 21B7328D25 for ; Sat, 20 Apr 2019 11:23:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728145AbfDTLXT (ORCPT ); Sat, 20 Apr 2019 07:23:19 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56740 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726267AbfDTLXT (ORCPT ); Sat, 20 Apr 2019 07:23:19 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CB068307FBCB; Sat, 20 Apr 2019 11:23:18 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id B737F19C5A; Sat, 20 Apr 2019 11:23:15 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 35/37] HID: logitech-hidpp: add support for HID++ 1.0 wheel reports Date: Sat, 20 Apr 2019 13:22:15 +0200 Message-Id: <20190420112217.27590-36-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.41]); Sat, 20 Apr 2019 11:23:18 +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 Add a quirk for switching wheel event reporting to using the HID++ report for this. This has 2 advantages: 1) Without this tilting the scrollwheel left / right will send a scroll-lock + cursor-left/-right + scroll-lock key-sequence instead of hwheel events 2) The HID++ reports contain the device index instead of using the generic HID implementation, so this will make scroll-wheel events from the wheel on some keyboards be emitted by the right event node. 2. also fixes keyboard scroll-wheel events getting lost in the (mostly theoretical) case of there not being a mouse paired with the receiver. This commit enables this quirk for all 27Mhz mice, it cannot hurt to have it enabled and this avoids the need to keep adding more and more quirks for this. This has been tested in 5 different 27MHz mice, 3 of which have a wheel which can tilt. This commit also adds explicit quirks for 3 keyboards with a zoom-/scroll- wheel. The MX3000 keyboard scroll-wheel can also tilt. I've defined aliases to the new HIDPP_QUIRK_HIDPP_WHEELS for this, so that it is clear why the keyboard has the quirk and in case we want to handle the keyboard wheels and especially the keyboard zoom-wheels differently in the future. Signed-off-by: Hans de Goede --- Changes in v2: -Split HIDPP_QUIRK_HIDPP_HWHEEL_AND_EXTRA_BTNS quirk into separate wheel and extra-mouse-buttons quirks -Also use the wheel-report for the normal/vertical wheel -Automatically apply the quirk to all 27 MHz mice --- drivers/hid/hid-logitech-hidpp.c | 94 ++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 2b769766e158..7f6bebae3a78 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -53,6 +53,9 @@ MODULE_PARM_DESC(disable_tap_to_click, #define HIDPP_REPORT_LONG_LENGTH 20 #define HIDPP_REPORT_VERY_LONG_MAX_LENGTH 64 +#define HIDPP_SUB_ID_ROLLER 0x05 +#define HIDPP_SUB_ID_MOUSE_EXTRA_BTNS 0x06 + #define HIDPP_QUIRK_CLASS_WTP BIT(0) #define HIDPP_QUIRK_CLASS_M560 BIT(1) #define HIDPP_QUIRK_CLASS_K400 BIT(2) @@ -68,6 +71,11 @@ MODULE_PARM_DESC(disable_tap_to_click, #define HIDPP_QUIRK_HI_RES_SCROLL_1P0 BIT(26) #define HIDPP_QUIRK_HI_RES_SCROLL_X2120 BIT(27) #define HIDPP_QUIRK_HI_RES_SCROLL_X2121 BIT(28) +#define HIDPP_QUIRK_HIDPP_WHEELS BIT(29) + +/* These are just aliases for now */ +#define HIDPP_QUIRK_KBD_SCROLL_WHEEL HIDPP_QUIRK_HIDPP_WHEELS +#define HIDPP_QUIRK_KBD_ZOOM_WHEEL HIDPP_QUIRK_HIDPP_WHEELS /* Convenience constant to check for any high-res support. */ #define HIDPP_QUIRK_HI_RES_SCROLL (HIDPP_QUIRK_HI_RES_SCROLL_1P0 | \ @@ -2738,6 +2746,52 @@ static int g920_get_config(struct hidpp_device *hidpp) return 0; } +/* -------------------------------------------------------------------------- */ +/* HID++1.0 devices which use HID++ reports for their wheels */ +/* -------------------------------------------------------------------------- */ +static int hidpp10_wheel_connect(struct hidpp_device *hidpp) +{ + return hidpp10_set_register(hidpp, HIDPP_REG_ENABLE_REPORTS, 0, + HIDPP_ENABLE_WHEEL_REPORT | HIDPP_ENABLE_HWHEEL_REPORT, + HIDPP_ENABLE_WHEEL_REPORT | HIDPP_ENABLE_HWHEEL_REPORT); +} + +static int hidpp10_wheel_raw_event(struct hidpp_device *hidpp, + u8 *data, int size) +{ + s8 value, hvalue; + + if (!hidpp->input) + return -EINVAL; + + if (size < 7) + return 0; + + if (data[0] != REPORT_ID_HIDPP_SHORT || data[2] != HIDPP_SUB_ID_ROLLER) + return 0; + + value = data[3]; + hvalue = data[4]; + + input_report_rel(hidpp->input, REL_WHEEL, value); + input_report_rel(hidpp->input, REL_WHEEL_HI_RES, value * 120); + input_report_rel(hidpp->input, REL_HWHEEL, hvalue); + input_report_rel(hidpp->input, REL_HWHEEL_HI_RES, hvalue * 120); + input_sync(hidpp->input); + + return 1; +} + +static void hidpp10_wheel_populate_input(struct hidpp_device *hidpp, + struct input_dev *input_dev) +{ + __set_bit(EV_REL, input_dev->evbit); + __set_bit(REL_WHEEL, input_dev->relbit); + __set_bit(REL_WHEEL_HI_RES, input_dev->relbit); + __set_bit(REL_HWHEEL, input_dev->relbit); + __set_bit(REL_HWHEEL_HI_RES, input_dev->relbit); +} + /* -------------------------------------------------------------------------- */ /* High-resolution scroll wheels */ /* -------------------------------------------------------------------------- */ @@ -2822,6 +2876,9 @@ static void hidpp_populate_input(struct hidpp_device *hidpp, wtp_populate_input(hidpp, input); else if (hidpp->quirks & HIDPP_QUIRK_CLASS_M560) m560_populate_input(hidpp, input); + + if (hidpp->quirks & HIDPP_QUIRK_HIDPP_WHEELS) + hidpp10_wheel_populate_input(hidpp, input); } static int hidpp_input_configured(struct hid_device *hdev, @@ -2893,6 +2950,12 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data, return ret; } + if (hidpp->quirks & HIDPP_QUIRK_HIDPP_WHEELS) { + ret = hidpp10_wheel_raw_event(hidpp, data, size); + if (ret != 0) + return ret; + } + return 0; } @@ -3140,6 +3203,12 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) return; } + if (hidpp->quirks & HIDPP_QUIRK_HIDPP_WHEELS) { + ret = hidpp10_wheel_connect(hidpp); + if (ret) + return; + } + /* the device is already connected, we can ask for its name and * protocol */ if (!hidpp->protocol_major) { @@ -3254,6 +3323,17 @@ static bool hidpp_validate_device(struct hid_device *hdev) HIDPP_REPORT_LONG_LENGTH, true); } +static bool hidpp_application_equals(struct hid_device *hdev, + unsigned int application) +{ + struct list_head *report_list; + struct hid_report *report; + + report_list = &hdev->report_enum[HID_INPUT_REPORT].report_list; + report = list_first_entry_or_null(report_list, struct hid_report, list); + return report && report->application == application; +} + static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) { struct hidpp_device *hidpp; @@ -3292,6 +3372,10 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) if (id->group == HID_GROUP_LOGITECH_DJ_DEVICE) hidpp->quirks |= HIDPP_QUIRK_UNIFYING; + if (id->group == HID_GROUP_LOGITECH_27MHZ_DEVICE && + hidpp_application_equals(hdev, HID_GD_MOUSE)) + hidpp->quirks |= HIDPP_QUIRK_HIDPP_WHEELS; + if (disable_raw_mode) { hidpp->quirks &= ~HIDPP_QUIRK_CLASS_WTP; hidpp->quirks &= ~HIDPP_QUIRK_NO_HIDINPUT; @@ -3472,6 +3556,16 @@ static const struct hid_device_id hidpp_devices[] = { { LDJ_DEVICE(HID_ANY_ID) }, + { /* Keyboard LX501 (Y-RR53) */ + L27MHZ_DEVICE(0x0049), + .driver_data = HIDPP_QUIRK_KBD_ZOOM_WHEEL }, + { /* Keyboard MX3000 (Y-RAM74) */ + L27MHZ_DEVICE(0x0057), + .driver_data = HIDPP_QUIRK_KBD_SCROLL_WHEEL }, + { /* Keyboard MX3200 (Y-RAV80) */ + L27MHZ_DEVICE(0x005c), + .driver_data = HIDPP_QUIRK_KBD_ZOOM_WHEEL }, + { L27MHZ_DEVICE(HID_ANY_ID) }, { /* Logitech G403 Gaming Mouse over USB */ From patchwork Sat Apr 20 11:22:16 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910293 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 01B7A17E0 for ; Sat, 20 Apr 2019 11:23:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E679E28D25 for ; Sat, 20 Apr 2019 11:23:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DB04028D95; Sat, 20 Apr 2019 11:23:21 +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 6C40028D25 for ; Sat, 20 Apr 2019 11:23:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728157AbfDTLXV (ORCPT ); Sat, 20 Apr 2019 07:23:21 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49260 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726267AbfDTLXU (ORCPT ); Sat, 20 Apr 2019 07:23:20 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2DE07309264D; Sat, 20 Apr 2019 11:23:20 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 19A2119C5A; Sat, 20 Apr 2019 11:23:18 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 36/37] HID: logitech-hidpp: add support for HID++ 1.0 extra mouse buttons reports Date: Sat, 20 Apr 2019 13:22:16 +0200 Message-Id: <20190420112217.27590-37-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.43]); Sat, 20 Apr 2019 11:23:20 +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 mice have extra buttons which are only reported through HID++ 1.0 extra mouse buttons reports, this commit adds support for this and automatically enables this support for all 27 MHz mice. Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-hidpp.c | 77 +++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 7f6bebae3a78..215c3a256c27 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -72,6 +72,7 @@ MODULE_PARM_DESC(disable_tap_to_click, #define HIDPP_QUIRK_HI_RES_SCROLL_X2120 BIT(27) #define HIDPP_QUIRK_HI_RES_SCROLL_X2121 BIT(28) #define HIDPP_QUIRK_HIDPP_WHEELS BIT(29) +#define HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS BIT(30) /* These are just aliases for now */ #define HIDPP_QUIRK_KBD_SCROLL_WHEEL HIDPP_QUIRK_HIDPP_WHEELS @@ -2792,6 +2793,64 @@ static void hidpp10_wheel_populate_input(struct hidpp_device *hidpp, __set_bit(REL_HWHEEL_HI_RES, input_dev->relbit); } +/* -------------------------------------------------------------------------- */ +/* HID++1.0 mice which use HID++ reports for extra mouse buttons */ +/* -------------------------------------------------------------------------- */ +static int hidpp10_extra_mouse_buttons_connect(struct hidpp_device *hidpp) +{ + return hidpp10_set_register(hidpp, HIDPP_REG_ENABLE_REPORTS, 0, + HIDPP_ENABLE_MOUSE_EXTRA_BTN_REPORT, + HIDPP_ENABLE_MOUSE_EXTRA_BTN_REPORT); +} + +static int hidpp10_extra_mouse_buttons_raw_event(struct hidpp_device *hidpp, + u8 *data, int size) +{ + int i; + + if (!hidpp->input) + return -EINVAL; + + if (size < 7) + return 0; + + if (data[0] != REPORT_ID_HIDPP_SHORT || + data[2] != HIDPP_SUB_ID_MOUSE_EXTRA_BTNS) + return 0; + + /* + * Buttons are either delivered through the regular mouse report *or* + * through the extra buttons report. At least for button 6 how it is + * delivered differs per receiver firmware version. Even receivers with + * the same usb-id show different behavior, so we handle both cases. + */ + for (i = 0; i < 8; i++) + input_report_key(hidpp->input, BTN_MOUSE + i, + (data[3] & (1 << i))); + + /* Some mice report events on button 9+, use BTN_MISC */ + for (i = 0; i < 8; i++) + input_report_key(hidpp->input, BTN_MISC + i, + (data[4] & (1 << i))); + + input_sync(hidpp->input); + return 1; +} + +static void hidpp10_extra_mouse_buttons_populate_input( + struct hidpp_device *hidpp, struct input_dev *input_dev) +{ + /* BTN_MOUSE - BTN_MOUSE+7 are set already by the descriptor */ + __set_bit(BTN_0, input_dev->keybit); + __set_bit(BTN_1, input_dev->keybit); + __set_bit(BTN_2, input_dev->keybit); + __set_bit(BTN_3, input_dev->keybit); + __set_bit(BTN_4, input_dev->keybit); + __set_bit(BTN_5, input_dev->keybit); + __set_bit(BTN_6, input_dev->keybit); + __set_bit(BTN_7, input_dev->keybit); +} + /* -------------------------------------------------------------------------- */ /* High-resolution scroll wheels */ /* -------------------------------------------------------------------------- */ @@ -2879,6 +2938,9 @@ static void hidpp_populate_input(struct hidpp_device *hidpp, if (hidpp->quirks & HIDPP_QUIRK_HIDPP_WHEELS) hidpp10_wheel_populate_input(hidpp, input); + + if (hidpp->quirks & HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS) + hidpp10_extra_mouse_buttons_populate_input(hidpp, input); } static int hidpp_input_configured(struct hid_device *hdev, @@ -2956,6 +3018,12 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data, return ret; } + if (hidpp->quirks & HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS) { + ret = hidpp10_extra_mouse_buttons_raw_event(hidpp, data, size); + if (ret != 0) + return ret; + } + return 0; } @@ -3209,6 +3277,12 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) return; } + if (hidpp->quirks & HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS) { + ret = hidpp10_extra_mouse_buttons_connect(hidpp); + if (ret) + return; + } + /* the device is already connected, we can ask for its name and * protocol */ if (!hidpp->protocol_major) { @@ -3374,7 +3448,8 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) if (id->group == HID_GROUP_LOGITECH_27MHZ_DEVICE && hidpp_application_equals(hdev, HID_GD_MOUSE)) - hidpp->quirks |= HIDPP_QUIRK_HIDPP_WHEELS; + hidpp->quirks |= HIDPP_QUIRK_HIDPP_WHEELS | + HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS; if (disable_raw_mode) { hidpp->quirks &= ~HIDPP_QUIRK_CLASS_WTP; From patchwork Sat Apr 20 11:22:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10910295 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 7DE5617E0 for ; Sat, 20 Apr 2019 11:23:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6CAA928D25 for ; Sat, 20 Apr 2019 11:23:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 60ED828D95; Sat, 20 Apr 2019 11:23:23 +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 9F84E28D25 for ; Sat, 20 Apr 2019 11:23:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728158AbfDTLXW (ORCPT ); Sat, 20 Apr 2019 07:23:22 -0400 Received: from mx1.redhat.com ([209.132.183.28]:46876 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726267AbfDTLXW (ORCPT ); Sat, 20 Apr 2019 07:23:22 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 88BB7308213C; Sat, 20 Apr 2019 11:23:21 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 730C119C5A; Sat, 20 Apr 2019 11:23:20 +0000 (UTC) From: Hans de Goede To: Jiri Kosina , Benjamin Tissoires Cc: Hans de Goede , Nestor Lopez Casado , linux-input@vger.kernel.org Subject: [PATCH v3 37/37] HID: logitech-hidpp: add support for HID++ 1.0 consumer keys reports Date: Sat, 20 Apr 2019 13:22:17 +0200 Message-Id: <20190420112217.27590-38-hdegoede@redhat.com> In-Reply-To: <20190420112217.27590-1-hdegoede@redhat.com> References: <20190420112217.27590-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Sat, 20 Apr 2019 11:23:21 +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 All Logitech 27 MHz keyboards and also the MX5000 bluetooth keyboard use Logitech custom usages of 0x10xx in the consumer page. The descriptor for the consumer input-report only declares usages up to 652, so we end up dropping all the input-reports reporting 0x10xx usages without reporting events for these to userspace. This commit adds a descriptor_fixup function for this which changes the usage and logical maximum to 0x107f. Mapping these usages to something other then KEY_UNKNOWN is left to userspace (hwdb). Note: 1. The old descriptor_fixup for this in hid-lg.c used a maximimum of 0x104d this is not high enough, the S520 keyboard battery key sends 0x106f. 2. The descriptor_fixup is flexible so that it works with both the kbd- desc. passed by the logitech-dj code and with bluetooth descriptors. The descriptor_fixup makes most keys work on 27 MHz keyboards, but it is not enough to get all keys to work on 27 MHz keyboards and just the fixup is not enough to get the MX5000 to generate 0x10xx events: 1) The LX501 and MX3000 27 MHz kbds both have a button labelled "media" (called "Media Player" by SetPoint) and a button with a remote-control symbol ("Media Life" in SetPoint) which both send an identical consumer usage-page code (0x0183) making the 2 buttons indistinguishable, switching to HID++ 1.0 consumer keys reports makes the remote-control symbol button generate a 0x10xx Logitech specific code instead. 2) The MX5000 Bluetooth keyboard has 11 keys which report 0x10xx consumer page usages, but unlike 27 MHz devices which happily send 0x10xx codes in their normal consumer-page input-report, the MX5000 honors the maximum of 652 from its descriptor and sends a 0x0000 code (so release) whenever these keys are pressed. When switching to HID++ sub-id 0x03 HID++ 1.0 consumer keys reports these 0x10xx codes do get properly reported. This commit adds support for HID++ 1.0 consumer keys reports and enables this for all 27 MHz keyboards and for the MX5000. Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-hidpp.c | 133 ++++++++++++++++++++++++++++--- 1 file changed, 121 insertions(+), 12 deletions(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 215c3a256c27..72fc9c0566db 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -53,6 +53,7 @@ MODULE_PARM_DESC(disable_tap_to_click, #define HIDPP_REPORT_LONG_LENGTH 20 #define HIDPP_REPORT_VERY_LONG_MAX_LENGTH 64 +#define HIDPP_SUB_ID_CONSUMER_VENDOR_KEYS 0x03 #define HIDPP_SUB_ID_ROLLER 0x05 #define HIDPP_SUB_ID_MOUSE_EXTRA_BTNS 0x06 @@ -73,6 +74,7 @@ MODULE_PARM_DESC(disable_tap_to_click, #define HIDPP_QUIRK_HI_RES_SCROLL_X2121 BIT(28) #define HIDPP_QUIRK_HIDPP_WHEELS BIT(29) #define HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS BIT(30) +#define HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS BIT(31) /* These are just aliases for now */ #define HIDPP_QUIRK_KBD_SCROLL_WHEEL HIDPP_QUIRK_HIDPP_WHEELS @@ -2851,6 +2853,71 @@ static void hidpp10_extra_mouse_buttons_populate_input( __set_bit(BTN_7, input_dev->keybit); } +/* -------------------------------------------------------------------------- */ +/* HID++1.0 kbds which only report 0x10xx consumer usages through sub-id 0x03 */ +/* -------------------------------------------------------------------------- */ + +/* Find the consumer-page input report desc and change Maximums to 0x107f */ +static u8 *hidpp10_consumer_keys_report_fixup(struct hidpp_device *hidpp, + u8 *_rdesc, unsigned int *rsize) +{ + /* Note 0 terminated so we can use strnstr to search for this. */ + const char consumer_rdesc_start[] = { + 0x05, 0x0C, /* USAGE_PAGE (Consumer Devices) */ + 0x09, 0x01, /* USAGE (Consumer Control) */ + 0xA1, 0x01, /* COLLECTION (Application) */ + 0x85, 0x03, /* REPORT_ID = 3 */ + 0x75, 0x10, /* REPORT_SIZE (16) */ + 0x95, 0x02, /* REPORT_COUNT (2) */ + 0x15, 0x01, /* LOGICAL_MIN (1) */ + 0x26, 0x00 /* LOGICAL_MAX (... */ + }; + char *consumer_rdesc, *rdesc = (char *)_rdesc; + unsigned int size; + + consumer_rdesc = strnstr(rdesc, consumer_rdesc_start, *rsize); + size = *rsize - (consumer_rdesc - rdesc); + if (consumer_rdesc && size >= 25) { + consumer_rdesc[15] = 0x7f; + consumer_rdesc[16] = 0x10; + consumer_rdesc[20] = 0x7f; + consumer_rdesc[21] = 0x10; + } + return _rdesc; +} + +static int hidpp10_consumer_keys_connect(struct hidpp_device *hidpp) +{ + return hidpp10_set_register(hidpp, HIDPP_REG_ENABLE_REPORTS, 0, + HIDPP_ENABLE_CONSUMER_REPORT, + HIDPP_ENABLE_CONSUMER_REPORT); +} + +static int hidpp10_consumer_keys_raw_event(struct hidpp_device *hidpp, + u8 *data, int size) +{ + u8 consumer_report[5]; + + if (size < 7) + return 0; + + if (data[0] != REPORT_ID_HIDPP_SHORT || + data[2] != HIDPP_SUB_ID_CONSUMER_VENDOR_KEYS) + return 0; + + /* + * Build a normal consumer report (3) out of the data, this detour + * is necessary to get some keyboards to report their 0x10xx usages. + */ + consumer_report[0] = 0x03; + memcpy(&consumer_report[1], &data[3], 4); + /* We are called from atomic context */ + hid_report_raw_event(hidpp->hid_dev, HID_INPUT_REPORT, + consumer_report, 5, 1); + + return 1; +} + /* -------------------------------------------------------------------------- */ /* High-resolution scroll wheels */ /* -------------------------------------------------------------------------- */ @@ -2886,6 +2953,22 @@ static int hi_res_scroll_enable(struct hidpp_device *hidpp) /* Generic HID++ devices */ /* -------------------------------------------------------------------------- */ +static u8 *hidpp_report_fixup(struct hid_device *hdev, u8 *rdesc, + unsigned int *rsize) +{ + struct hidpp_device *hidpp = hid_get_drvdata(hdev); + + if (!hidpp) + return rdesc; + + /* For 27 MHz keyboards the quirk gets set after hid_parse. */ + if (hdev->group == HID_GROUP_LOGITECH_27MHZ_DEVICE || + (hidpp->quirks & HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS)) + rdesc = hidpp10_consumer_keys_report_fixup(hidpp, rdesc, rsize); + + return rdesc; +} + static int hidpp_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) @@ -3024,6 +3107,12 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data, return ret; } + if (hidpp->quirks & HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS) { + ret = hidpp10_consumer_keys_raw_event(hidpp, data, size); + if (ret != 0) + return ret; + } + return 0; } @@ -3283,6 +3372,12 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) return; } + if (hidpp->quirks & HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS) { + ret = hidpp10_consumer_keys_connect(hidpp); + if (ret) + return; + } + /* the device is already connected, we can ask for its name and * protocol */ if (!hidpp->protocol_major) { @@ -3415,6 +3510,16 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) bool connected; unsigned int connect_mask = HID_CONNECT_DEFAULT; + /* report_fixup needs drvdata to be set before we call hid_parse */ + hidpp = devm_kzalloc(&hdev->dev, sizeof(*hidpp), GFP_KERNEL); + if (!hidpp) + return -ENOMEM; + + hidpp->hid_dev = hdev; + hidpp->name = hdev->name; + hidpp->quirks = id->driver_data; + hid_set_drvdata(hdev, hidpp); + ret = hid_parse(hdev); if (ret) { hid_err(hdev, "%s:parse failed\n", __func__); @@ -3424,19 +3529,11 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) /* * Make sure the device is HID++ capable, otherwise treat as generic HID */ - if (!hidpp_validate_device(hdev)) + if (!hidpp_validate_device(hdev)) { + hid_set_drvdata(hdev, NULL); + devm_kfree(&hdev->dev, hidpp); return hid_hw_start(hdev, HID_CONNECT_DEFAULT); - - hidpp = devm_kzalloc(&hdev->dev, sizeof(struct hidpp_device), - GFP_KERNEL); - if (!hidpp) - return -ENOMEM; - - hidpp->hid_dev = hdev; - hidpp->name = hdev->name; - hid_set_drvdata(hdev, hidpp); - - hidpp->quirks = id->driver_data; + } hidpp->very_long_report_length = hidpp_get_report_length(hdev, REPORT_ID_HIDPP_VERY_LONG); @@ -3451,6 +3548,10 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) hidpp->quirks |= HIDPP_QUIRK_HIDPP_WHEELS | HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS; + if (id->group == HID_GROUP_LOGITECH_27MHZ_DEVICE && + hidpp_application_equals(hdev, HID_GD_KEYBOARD)) + hidpp->quirks |= HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS; + if (disable_raw_mode) { hidpp->quirks &= ~HIDPP_QUIRK_CLASS_WTP; hidpp->quirks &= ~HIDPP_QUIRK_NO_HIDINPUT; @@ -3628,6 +3729,9 @@ static const struct hid_device_id hidpp_devices[] = { { /* Solar Keyboard Logitech K750 */ LDJ_DEVICE(0x4002), .driver_data = HIDPP_QUIRK_CLASS_K750 }, + { /* Keyboard MX5000 (Bluetooth-receiver in HID proxy mode) */ + LDJ_DEVICE(0xb305), + .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, { LDJ_DEVICE(HID_ANY_ID) }, @@ -3652,6 +3756,10 @@ static const struct hid_device_id hidpp_devices[] = { { /* Logitech G920 Wheel over USB */ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL), .driver_data = HIDPP_QUIRK_CLASS_G920 | HIDPP_QUIRK_FORCE_OUTPUT_REPORTS}, + + { /* MX5000 keyboard over Bluetooth */ + HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb305), + .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, {} }; @@ -3665,6 +3773,7 @@ static const struct hid_usage_id hidpp_usages[] = { static struct hid_driver hidpp_driver = { .name = "logitech-hidpp-device", .id_table = hidpp_devices, + .report_fixup = hidpp_report_fixup, .probe = hidpp_probe, .remove = hidpp_remove, .raw_event = hidpp_raw_event,