From patchwork Sat Mar 30 11:23: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: 10878379 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 46EE913B5 for ; Sat, 30 Mar 2019 11:24:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 32ADA27E01 for ; Sat, 30 Mar 2019 11:24:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 26DC328249; Sat, 30 Mar 2019 11:24: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 B9B9627E01 for ; Sat, 30 Mar 2019 11:24:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730430AbfC3LYZ (ORCPT ); Sat, 30 Mar 2019 07:24:25 -0400 Received: from mx1.redhat.com ([209.132.183.28]:43738 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730414AbfC3LYZ (ORCPT ); Sat, 30 Mar 2019 07:24:25 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E4FB730917AC; Sat, 30 Mar 2019 11:24:24 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id CBD9B18AB6; Sat, 30 Mar 2019 11:24: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 01/28] HID: quirks: do not blacklist Logitech devices Date: Sat, 30 Mar 2019 12:23:51 +0100 Message-Id: <20190330112418.15042-2-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.41]); Sat, 30 Mar 2019 11:24: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 --- 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 94088c0ed68a..a46d7ab7db91 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -467,13 +467,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 Mar 30 11:23: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: 10878381 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 5D66E139A for ; Sat, 30 Mar 2019 11:24:27 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 472E427E01 for ; Sat, 30 Mar 2019 11:24:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3B9AE28249; Sat, 30 Mar 2019 11:24: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 E074227E01 for ; Sat, 30 Mar 2019 11:24:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730453AbfC3LY0 (ORCPT ); Sat, 30 Mar 2019 07:24:26 -0400 Received: from mx1.redhat.com ([209.132.183.28]:35374 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730414AbfC3LY0 (ORCPT ); Sat, 30 Mar 2019 07:24:26 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 50172308424D; Sat, 30 Mar 2019 11:24:26 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id 34614413F; Sat, 30 Mar 2019 11:24:25 +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 02/28] HID: logitech-dj: reshuffle logi_dj_recv_forward_* Date: Sat, 30 Mar 2019 12:23:52 +0100 Message-Id: <20190330112418.15042-3-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.40]); Sat, 30 Mar 2019 11:24: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 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 --- 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 Mar 30 11:23: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: 10878383 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 BB10813B5 for ; Sat, 30 Mar 2019 11:24:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A5CE227E01 for ; Sat, 30 Mar 2019 11:24:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9A29928249; Sat, 30 Mar 2019 11:24:28 +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 3DFD227E01 for ; Sat, 30 Mar 2019 11:24:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730531AbfC3LY1 (ORCPT ); Sat, 30 Mar 2019 07:24:27 -0400 Received: from mx1.redhat.com ([209.132.183.28]:44528 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730414AbfC3LY1 (ORCPT ); Sat, 30 Mar 2019 07:24:27 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id AA99CC007354; Sat, 30 Mar 2019 11:24:27 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id 91351413F; Sat, 30 Mar 2019 11:24: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 03/28] HID: logitech-dj: fix variable naming in logi_dj_hidpp_event Date: Sat, 30 Mar 2019 12:23:53 +0100 Message-Id: <20190330112418.15042-4-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Sat, 30 Mar 2019 11:24: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 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 --- 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 Mar 30 11:23: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: 10878385 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 3A48313B5 for ; Sat, 30 Mar 2019 11:24:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 24A4027E01 for ; Sat, 30 Mar 2019 11:24:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 18F7928249; Sat, 30 Mar 2019 11:24: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 B544727E01 for ; Sat, 30 Mar 2019 11:24:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730532AbfC3LY3 (ORCPT ); Sat, 30 Mar 2019 07:24:29 -0400 Received: from mx1.redhat.com ([209.132.183.28]:35380 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730414AbfC3LY3 (ORCPT ); Sat, 30 Mar 2019 07:24:29 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 119F7308424D; Sat, 30 Mar 2019 11:24:29 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id ECD78413F; Sat, 30 Mar 2019 11:24: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 04/28] HID: logitech-dj: use BIT() macro for RF Report types Date: Sat, 30 Mar 2019 12:23:54 +0100 Message-Id: <20190330112418.15042-5-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.40]); Sat, 30 Mar 2019 11:24:29 +0000 (UTC) Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Benjamin Tissoires Use BIT() macro for RF Report types. Signed-off-by: Benjamin Tissoires --- 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 Mar 30 11:23: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: 10878387 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 774C0139A for ; Sat, 30 Mar 2019 11:24:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6088627E01 for ; Sat, 30 Mar 2019 11:24:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5450E28249; Sat, 30 Mar 2019 11:24: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 024AE27E01 for ; Sat, 30 Mar 2019 11:24:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730591AbfC3LYa (ORCPT ); Sat, 30 Mar 2019 07:24:30 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54444 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730414AbfC3LYa (ORCPT ); Sat, 30 Mar 2019 07:24:30 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6F35D8110C; Sat, 30 Mar 2019 11:24:30 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id 54E73413F; Sat, 30 Mar 2019 11:24:29 +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 05/28] HID: logitech-dj: declare and use a few HID++ 1.0 constants Date: Sat, 30 Mar 2019 12:23:55 +0100 Message-Id: <20190330112418.15042-6-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Sat, 30 Mar 2019 11:24: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 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 --- 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 Mar 30 11:23: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: 10878389 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 8BE20139A for ; Sat, 30 Mar 2019 11:24:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 73BDB28113 for ; Sat, 30 Mar 2019 11:24:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6327027E01; Sat, 30 Mar 2019 11:24: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 DF6D727E01 for ; Sat, 30 Mar 2019 11:24:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730469AbfC3LYe (ORCPT ); Sat, 30 Mar 2019 07:24:34 -0400 Received: from mx1.redhat.com ([209.132.183.28]:35392 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730464AbfC3LYe (ORCPT ); Sat, 30 Mar 2019 07:24:34 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E65C1308424D; Sat, 30 Mar 2019 11:24:33 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id B2B5318AB6; Sat, 30 Mar 2019 11:24: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 06/28] HID: logitech-dj: remove USB dependency Date: Sat, 30 Mar 2019 12:23:56 +0100 Message-Id: <20190330112418.15042-7-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.40]); Sat, 30 Mar 2019 11:24:33 +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 --- drivers/hid/hid-logitech-dj.c | 64 +++++++++++++++++------------------ 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index eafe75d55664..5a72be1b8d83 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,40 @@ 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 +1060,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 +1106,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 Mar 30 11:23: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: 10878391 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 9A47213B5 for ; Sat, 30 Mar 2019 11:24:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8419D27E01 for ; Sat, 30 Mar 2019 11:24:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 77FA82832D; Sat, 30 Mar 2019 11:24: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 AA0EA27E01 for ; Sat, 30 Mar 2019 11:24:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730597AbfC3LYg (ORCPT ); Sat, 30 Mar 2019 07:24:36 -0400 Received: from mx1.redhat.com ([209.132.183.28]:53912 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730464AbfC3LYg (ORCPT ); Sat, 30 Mar 2019 07:24:36 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4E9D581DF3; Sat, 30 Mar 2019 11:24:35 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3577418AB6; Sat, 30 Mar 2019 11:24: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 07/28] HID: logitech-dj: do not schedule the dj report itself Date: Sat, 30 Mar 2019 12:23:57 +0100 Message-Id: <20190330112418.15042-8-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Sat, 30 Mar 2019 11:24: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 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 --- drivers/hid/hid-logitech-dj.c | 134 +++++++++++++++++++++------------- 1 file changed, 83 insertions(+), 51 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 5a72be1b8d83..74911a0caeb6 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,15 @@ 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 " @@ -1051,7 +1083,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 Mar 30 11:23: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: 10878393 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 CB2D6186D for ; Sat, 30 Mar 2019 11:24:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B70F827E01 for ; Sat, 30 Mar 2019 11:24:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AB14228249; Sat, 30 Mar 2019 11:24: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 59BCB28113 for ; Sat, 30 Mar 2019 11:24:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730629AbfC3LYg (ORCPT ); Sat, 30 Mar 2019 07:24:36 -0400 Received: from mx1.redhat.com ([209.132.183.28]:41210 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730464AbfC3LYg (ORCPT ); Sat, 30 Mar 2019 07:24:36 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id AC8083086209; Sat, 30 Mar 2019 11:24:36 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id 91175413F; Sat, 30 Mar 2019 11:24: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 08/28] HID: logitech-dj: remove unused querying_devices variable Date: Sat, 30 Mar 2019 12:23:58 +0100 Message-Id: <20190330112418.15042-9-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Sat, 30 Mar 2019 11:24: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 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 74911a0caeb6..32b985104a8e 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 { @@ -651,10 +650,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 Mar 30 11:23: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: 10878395 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 51B1E139A for ; Sat, 30 Mar 2019 11:24:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3F23B27E01 for ; Sat, 30 Mar 2019 11:24:39 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 33FFB28249; Sat, 30 Mar 2019 11:24: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 D99C327E01 for ; Sat, 30 Mar 2019 11:24:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730632AbfC3LYi (ORCPT ); Sat, 30 Mar 2019 07:24:38 -0400 Received: from mx1.redhat.com ([209.132.183.28]:53764 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730464AbfC3LYi (ORCPT ); Sat, 30 Mar 2019 07:24:38 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1509B3082E0F; Sat, 30 Mar 2019 11:24:38 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id EF7AC19652; Sat, 30 Mar 2019 11:24: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 09/28] HID: logitech-dj: protect the paired_dj_devices access in add_djhid_dev with the lock Date: Sat, 30 Mar 2019 12:23:59 +0100 Message-Id: <20190330112418.15042-10-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.46]); Sat, 30 Mar 2019 11:24: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 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 32b985104a8e..49d34989fc10 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 Mar 30 11:24: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: 10878397 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 2896213B5 for ; Sat, 30 Mar 2019 11:24:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1469A27E01 for ; Sat, 30 Mar 2019 11:24:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0913D28249; Sat, 30 Mar 2019 11:24: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 9070E27E01 for ; Sat, 30 Mar 2019 11:24:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730645AbfC3LYm (ORCPT ); Sat, 30 Mar 2019 07:24:42 -0400 Received: from mx1.redhat.com ([209.132.183.28]:47636 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730464AbfC3LYm (ORCPT ); Sat, 30 Mar 2019 07:24:42 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 87CD0859FE; Sat, 30 Mar 2019 11:24:41 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id 57F68413F; Sat, 30 Mar 2019 11:24: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 10/28] HID: logitech-dj: rename dj_receiver_dev.hdev to dj_receiver_dev.hidpp Date: Sat, 30 Mar 2019 12:24:00 +0100 Message-Id: <20190330112418.15042-11-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Sat, 30 Mar 2019 11:24: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 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 | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 49d34989fc10..9e08b44c76b2 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,9 +507,8 @@ 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", __func__, retval); + hid_err(djrcv_dev->hidpp, "%s: logi_dj_recv_query_paired_devices error:%d\n", + __func__, retval); } break; case WORKITEM_TYPE_EMPTY: @@ -629,7 +627,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); @@ -671,7 +669,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; @@ -768,7 +766,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); } @@ -786,7 +784,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); @@ -1080,7 +1078,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 Mar 30 11:24: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: 10878399 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 EF423139A for ; Sat, 30 Mar 2019 11:24:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DA11128EC6 for ; Sat, 30 Mar 2019 11:24:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CE2A628FEB; Sat, 30 Mar 2019 11:24: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 26E8528EC6 for ; Sat, 30 Mar 2019 11:24:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730662AbfC3LYn (ORCPT ); Sat, 30 Mar 2019 07:24:43 -0400 Received: from mx1.redhat.com ([209.132.183.28]:42934 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730464AbfC3LYn (ORCPT ); Sat, 30 Mar 2019 07:24:43 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E4B5230821C2; Sat, 30 Mar 2019 11:24:42 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id CB7DE413F; Sat, 30 Mar 2019 11:24: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 11/28] HID: logitech-dj: support sharing struct dj_receiver_dev between USB-interfaces Date: Sat, 30 Mar 2019 12:24:01 +0100 Message-Id: <20190330112418.15042-12-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.47]); Sat, 30 Mar 2019 11:24:42 +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 --- drivers/hid/hid-logitech-dj.c | 175 ++++++++++++++++++++++++++++------ 1 file changed, 148 insertions(+), 27 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 9e08b44c76b2..337389c2d6c7 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,16 @@ 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) { + hid_err(djrcv_dev->hidpp, "delayedwork queued before hidpp interface was enumerated\n"); + spin_unlock_irqrestore(&djrcv_dev->lock, flags); + return; + } + count = kfifo_out(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem)); if (count != sizeof(workitem)) { @@ -1041,6 +1160,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; /* Call to usbhid to fetch the HID descriptors of the current @@ -1070,27 +1190,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 */ @@ -1120,6 +1228,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 " @@ -1137,10 +1248,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 @@ -1164,31 +1273,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 Mar 30 11:24: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: 10878401 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 28E5D139A for ; Sat, 30 Mar 2019 11:24:46 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1487328EC6 for ; Sat, 30 Mar 2019 11:24:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0911328FEB; Sat, 30 Mar 2019 11:24:46 +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 8E3E428EC6 for ; Sat, 30 Mar 2019 11:24:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730683AbfC3LYp (ORCPT ); Sat, 30 Mar 2019 07:24:45 -0400 Received: from mx1.redhat.com ([209.132.183.28]:41222 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730464AbfC3LYp (ORCPT ); Sat, 30 Mar 2019 07:24:45 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4FF4F3086223; Sat, 30 Mar 2019 11:24:44 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id 35B30413F; Sat, 30 Mar 2019 11:24: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 12/28] HID: logitech-dj: add logi_dj_recv_queue_unknown_work helper Date: Sat, 30 Mar 2019 12:24:02 +0100 Message-Id: <20190330112418.15042-13-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Sat, 30 Mar 2019 11:24: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 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 | 43 ++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 337389c2d6c7..5e65c3dfc033 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) @@ -636,6 +638,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 is 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) { @@ -665,19 +691,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)); @@ -773,6 +788,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 Mar 30 11:24: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: 10878405 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 43EE613B5 for ; Sat, 30 Mar 2019 11:24:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2CEA728EC6 for ; Sat, 30 Mar 2019 11:24:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 210D428FEB; Sat, 30 Mar 2019 11:24: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 EB6E428EC6 for ; Sat, 30 Mar 2019 11:24:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730689AbfC3LYr (ORCPT ); Sat, 30 Mar 2019 07:24:47 -0400 Received: from mx1.redhat.com ([209.132.183.28]:44594 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730464AbfC3LYr (ORCPT ); Sat, 30 Mar 2019 07:24:47 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D05B1C05B1DC; Sat, 30 Mar 2019 11:24:45 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id 93F7118AB6; Sat, 30 Mar 2019 11:24: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 13/28] HID: logitech-dj: add support for non unifying receivers Date: Sat, 30 Mar 2019 12:24:03 +0100 Message-Id: <20190330112418.15042-14-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Sat, 30 Mar 2019 11:24: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 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 644a9f2bf624..8dac3d221e5c 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -759,7 +759,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 5e65c3dfc033..fc2a82dc7230 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) @@ -703,6 +724,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) { @@ -758,6 +867,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) { @@ -783,6 +922,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; @@ -790,6 +954,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; @@ -808,24 +975,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 @@ -909,6 +1082,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; @@ -1089,6 +1272,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; @@ -1125,14 +1309,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; @@ -1142,8 +1328,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) { @@ -1167,6 +1375,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; } @@ -1192,6 +1402,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 @@ -1204,12 +1418,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, @@ -1217,21 +1431,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 */ @@ -1245,14 +1463,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; @@ -1275,6 +1495,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, @@ -1331,9 +1554,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 Mar 30 11:24: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: 10878403 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 C3530139A for ; Sat, 30 Mar 2019 11:24:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ADB1628F22 for ; Sat, 30 Mar 2019 11:24:48 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A22F028FF0; Sat, 30 Mar 2019 11:24:48 +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 2CF0628FEB for ; Sat, 30 Mar 2019 11:24:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730464AbfC3LYr (ORCPT ); Sat, 30 Mar 2019 07:24:47 -0400 Received: from mx1.redhat.com ([209.132.183.28]:44602 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730684AbfC3LYr (ORCPT ); Sat, 30 Mar 2019 07:24:47 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3932DC05D40A; Sat, 30 Mar 2019 11:24:47 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id 213B0413F; Sat, 30 Mar 2019 11:24:45 +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 14/28] HID: logitech-dj: add support for the gaming unifying receiver Date: Sat, 30 Mar 2019 12:24:04 +0100 Message-Id: <20190330112418.15042-15-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Sat, 30 Mar 2019 11:24: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 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 8dac3d221e5c..f4f76eb6a0ba 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -762,6 +762,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 fc2a82dc7230..9af5479c66ed 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) */ @@ -787,6 +826,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; } @@ -1141,7 +1182,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) { @@ -1359,6 +1405,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, @@ -1567,6 +1619,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 Mar 30 11:24: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: 10878407 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 C15A8139A for ; Sat, 30 Mar 2019 11:24:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AD1A128EC6 for ; Sat, 30 Mar 2019 11:24:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A134028FEB; Sat, 30 Mar 2019 11:24:50 +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 CE2DA28EC6 for ; Sat, 30 Mar 2019 11:24:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730685AbfC3LYt (ORCPT ); Sat, 30 Mar 2019 07:24:49 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54106 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730684AbfC3LYt (ORCPT ); Sat, 30 Mar 2019 07:24:49 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 96F23308FC20; Sat, 30 Mar 2019 11:24:48 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7DB85413F; Sat, 30 Mar 2019 11:24: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 15/28] HID: logitech-dj: add support for 27 MHz receivers Date: Sat, 30 Mar 2019 12:24:05 +0100 Message-Id: <20190330112418.15042-16-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.43]); Sat, 30 Mar 2019 11:24: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 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 Note this commits also sets up a better name for 27 MHz hidpp devices, this is done because unlike other hidpp devices, the logitech-hidpp code will not override the name, so having a good name is important. Signed-off-by: Hans de Goede --- drivers/hid/hid-lg.c | 2 - drivers/hid/hid-logitech-dj.c | 136 ++++++++++++++++++++++++++++++++-- drivers/hid/hid-quirks.c | 1 - 3 files changed, 130 insertions(+), 9 deletions(-) diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index 596227ddb6e0..c8f1e24d38ec 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -818,8 +818,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 9af5479c66ed..f9c88820f684 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) */ @@ -286,7 +326,7 @@ static const char mse_high_res_descriptor[] = { 0xC0, /* END_COLLECTION */ }; -/* Consumer Control descriptor (3) */ +/* Consumer Control descriptor (3) normal, usages 1 - 652 */ static const char consumer_descriptor[] = { 0x05, 0x0C, /* USAGE_PAGE (Consumer Devices) */ 0x09, 0x01, /* USAGE (Consumer Control) */ @@ -302,6 +342,25 @@ static const char consumer_descriptor[] = { 0xC0, /* END_COLLECTION */ }; /* */ +/* + * Consumer Control descriptor (3) 27 MHz devices, usages 1 - 4173 (0x104d) + * Usages > 0x1000 are used for Logitech custom keys + */ +static const char consumer_27mhz_descriptor[] = { + 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, 0x4D, 0x10, /* LOGICAL_MAX (4173) */ + 0x19, 0x01, /* USAGE_MIN (1) */ + 0x2A, 0x4D, 0x10, /* USAGE_MAX (4173) */ + 0x81, 0x00, /* INPUT (Data Ary Abs) */ + 0xC0, /* END_COLLECTION */ +}; /* */ + /* System control descriptor (4) */ static const char syscontrol_descriptor[] = { 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ @@ -387,6 +446,8 @@ static const char hidpp_descriptor[] = { 0x91, 0x00, /* Output (Data,Arr,Abs) */ 0xc0, /* End Collection */ }; +/* Some receivers only support short reports (only support report id 16) */ +#define HIDPP_DESC_SHORT_REPORT_SIZE 27 /* Maximum size of all defined hid reports in bytes (including report id) */ #define MAX_REPORT_SIZE 8 @@ -592,9 +653,16 @@ 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 (djrcv_dev->type == recvr_type_27mhz) { + snprintf(dj_hiddev->name, sizeof(dj_hiddev->name), + "Logitech 27 MHz %s. Wireless PID:%04x", + (device_index == 1) ? "Mouse" : "Keyboard", + dj_hiddev->product); + } else { + snprintf(dj_hiddev->name, sizeof(dj_hiddev->name), + "Logitech Unifying Device. Wireless PID:%04x", + dj_hiddev->product); + } dj_hiddev->group = HID_GROUP_LOGITECH_DJ_DEVICE; @@ -781,6 +849,26 @@ 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: /* Device 1 is always the mouse */ + workitem->reports_supported |= STD_MOUSE; + break; + case 3: /* Device 3 is always the keyboard */ + 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) { @@ -798,6 +886,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"; @@ -1185,6 +1274,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)); @@ -1193,7 +1285,12 @@ 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", __func__, djdev->reports_supported); - rdcat(rdesc, &rsize, consumer_descriptor, sizeof(consumer_descriptor)); + if (djdev->dj_receiver_dev->type == recvr_type_27mhz) + rdcat(rdesc, &rsize, consumer_27mhz_descriptor, + sizeof(consumer_27mhz_descriptor)); + else + rdcat(rdesc, &rsize, consumer_descriptor, + sizeof(consumer_descriptor)); } if (djdev->reports_supported & POWER_KEYS) { @@ -1213,7 +1310,11 @@ static int logi_dj_ll_parse(struct hid_device *hid) __func__, djdev->reports_supported); } - rdcat(rdesc, &rsize, hidpp_descriptor, sizeof(hidpp_descriptor)); + /* 27 MHz receivers only support short reports */ + if (djdev->dj_receiver_dev->type == recvr_type_27mhz) + rdcat(rdesc, &rsize, hidpp_descriptor, HIDPP_DESC_SHORT_REPORT_SIZE); + else + rdcat(rdesc, &rsize, hidpp_descriptor, sizeof(hidpp_descriptor)); retval = hid_parse_report(hid, rdesc, rsize); kfree(rdesc); @@ -1356,6 +1457,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 { @@ -1623,6 +1743,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 a46d7ab7db91..6ef3bd23fbdc 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -436,7 +436,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) }, From patchwork Sat Mar 30 11:24: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: 10878409 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 45F0B186D for ; Sat, 30 Mar 2019 11:24:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 32D1D28EC6 for ; Sat, 30 Mar 2019 11:24:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 271F328FEB; Sat, 30 Mar 2019 11:24: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 CA24B28EC6 for ; Sat, 30 Mar 2019 11:24:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730696AbfC3LYu (ORCPT ); Sat, 30 Mar 2019 07:24:50 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49902 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730684AbfC3LYu (ORCPT ); Sat, 30 Mar 2019 07:24:50 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id F36A13689B; Sat, 30 Mar 2019 11:24:49 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id D9786413F; Sat, 30 Mar 2019 11:24: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 16/28] HID: logitech-dj: add support for 27 MHz mouse-only receivers Date: Sat, 30 Mar 2019 12:24:06 +0100 Message-Id: <20190330112418.15042-17-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Sat, 30 Mar 2019 11:24: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 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 f4f76eb6a0ba..459b43758461 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -758,6 +758,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 f9c88820f684..d4e67962535b 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -1514,6 +1514,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; } @@ -1747,6 +1757,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 Mar 30 11:24: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: 10878411 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 5EFF113B5 for ; Sat, 30 Mar 2019 11:24:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4AB6C28EC6 for ; Sat, 30 Mar 2019 11:24:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3F52D28FEB; Sat, 30 Mar 2019 11:24: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 B662428EC6 for ; Sat, 30 Mar 2019 11:24:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730697AbfC3LYw (ORCPT ); Sat, 30 Mar 2019 07:24:52 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49906 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730684AbfC3LYw (ORCPT ); Sat, 30 Mar 2019 07:24:52 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 60D303688B; Sat, 30 Mar 2019 11:24:51 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4287D413F; Sat, 30 Mar 2019 11:24: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 17/28] HID: logitech-dj: replace dev_err calls with hid_err calls Date: Sat, 30 Mar 2019 12:24:07 +0100 Message-Id: <20190330112418.15042-18-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Sat, 30 Mar 2019 11:24: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 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 d4e67962535b..6012cdf87499 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -641,8 +641,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; } @@ -673,8 +672,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; } @@ -689,8 +687,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; } @@ -1040,7 +1037,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; } @@ -1160,14 +1157,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); } /* @@ -1377,7 +1374,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; } @@ -1449,8 +1446,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; } @@ -1531,27 +1528,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); @@ -1577,8 +1572,7 @@ static int logi_dj_probe(struct hid_device *hdev, * descriptors. */ 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; } @@ -1608,8 +1602,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; } @@ -1620,8 +1613,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; } @@ -1637,7 +1629,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; } @@ -1682,8 +1674,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 Mar 30 11:24: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: 10878413 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 633C613B5 for ; Sat, 30 Mar 2019 11:24:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4EE0528EC6 for ; Sat, 30 Mar 2019 11:24:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4330028FEB; Sat, 30 Mar 2019 11:24:54 +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 D429728EC6 for ; Sat, 30 Mar 2019 11:24:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730698AbfC3LYx (ORCPT ); Sat, 30 Mar 2019 07:24:53 -0400 Received: from mx1.redhat.com ([209.132.183.28]:53782 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730684AbfC3LYx (ORCPT ); Sat, 30 Mar 2019 07:24:53 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BC0883082E0F; Sat, 30 Mar 2019 11:24:52 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id A1182413F; Sat, 30 Mar 2019 11:24: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 18/28] HID: logitech-dj: deal with some KVMs adding an extra interface to the usbdev Date: Sat, 30 Mar 2019 12:24:08 +0100 Message-Id: <20190330112418.15042-19-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.46]); Sat, 30 Mar 2019 11:24: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 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 --- drivers/hid/hid-logitech-dj.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 6012cdf87499..c66b72c760e3 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" @@ -1494,6 +1495,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) { @@ -1563,6 +1567,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; @@ -1576,6 +1582,25 @@ 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)) && + 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 */ @@ -1669,7 +1694,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); @@ -1691,6 +1716,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 Mar 30 11:24: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: 10878415 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 8BBF3139A for ; Sat, 30 Mar 2019 11:24:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 76A6628EC6 for ; Sat, 30 Mar 2019 11:24:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6AFF228FEB; Sat, 30 Mar 2019 11:24: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 0C7DE28EC6 for ; Sat, 30 Mar 2019 11:24:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730700AbfC3LYy (ORCPT ); Sat, 30 Mar 2019 07:24:54 -0400 Received: from mx1.redhat.com ([209.132.183.28]:48182 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730684AbfC3LYy (ORCPT ); Sat, 30 Mar 2019 07:24:54 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 24F6D308339D; Sat, 30 Mar 2019 11:24:54 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0AF6B18AB6; Sat, 30 Mar 2019 11:24: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 19/28] HID: logitech-hidpp: create a name based on the type if non available Date: Sat, 30 Mar 2019 12:24:09 +0100 Message-Id: <20190330112418.15042-20-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.44]); Sat, 30 Mar 2019 11:24: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 From: Benjamin Tissoires Some low cost devices don't even have a name (nor a serial) registered in the receiver. In those case, create a better name that "Logitech USB Receiver" or even "Logitech " if we try to get their name. Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-logitech-hidpp.c | 55 ++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index b950a44157a2..887af6068985 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -717,9 +717,28 @@ static int hidpp10_battery_event(struct hidpp_device *hidpp, u8 *data, int size) } #define HIDPP_REG_PAIRING_INFORMATION 0xB5 +#define HIDPP_PAIRING_INFORMATION 0x20 #define HIDPP_EXTENDED_PAIRING 0x30 #define HIDPP_DEVICE_NAME 0x40 +static int hidpp_unifying_get_type(struct hidpp_device *hidpp_dev) +{ + struct hidpp_report response; + int ret; + u8 params[1] = { HIDPP_PAIRING_INFORMATION }; + + ret = hidpp_send_rap_command_sync(hidpp_dev, + REPORT_ID_HIDPP_SHORT, + HIDPP_GET_LONG_REGISTER, + HIDPP_REG_PAIRING_INFORMATION, + params, 1, &response); + if (ret) + return ret; + + return response.rap.params[7]; + +} + static char *hidpp_unifying_get_name(struct hidpp_device *hidpp_dev) { struct hidpp_report response; @@ -741,6 +760,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 0; + name = kzalloc(len + 1, GFP_KERNEL); if (!name) return NULL; @@ -778,7 +800,7 @@ static int hidpp_unifying_get_serial(struct hidpp_device *hidpp, u32 *serial) static int hidpp_unifying_init(struct hidpp_device *hidpp) { struct hid_device *hdev = hidpp->hid_dev; - const char *name; + const char *name = NULL; u32 serial; int ret; @@ -791,8 +813,35 @@ static int hidpp_unifying_init(struct hidpp_device *hidpp) dbg_hid("HID++ Unifying: Got serial: %s\n", hdev->uniq); name = hidpp_unifying_get_name(hidpp); - if (!name) - return -EIO; + if (!name) { + ret = hidpp_unifying_get_type(hidpp); + if (ret < 0) + return ret; + + switch (ret) { + case 0x01: + name = "Logitech Wireless Keyboard"; + break; + case 0x02: + name = "Logitech Wireless Mouse"; + break; + case 0x03: + name = "Logitech Wireless Numpad"; + break; + case 0x04: + name = "Logitech Wireless Presenter"; + break; + case 0x08: + name = "Logitech Wireless Trackball"; + break; + case 0x09: + name = "Logitech Wireless Touchpad"; + break; + } + if (name) + snprintf(hdev->name, sizeof(hdev->name), "%s", name); + return 0; + } snprintf(hdev->name, sizeof(hdev->name), "%s", name); dbg_hid("HID++ Unifying: Got name: %s\n", name); From patchwork Sat Mar 30 11:24: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: 10878417 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 0EB16139A for ; Sat, 30 Mar 2019 11:24:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EB5E928EC6 for ; Sat, 30 Mar 2019 11:24:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DF76328FEB; Sat, 30 Mar 2019 11:24:56 +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 685F528EC6 for ; Sat, 30 Mar 2019 11:24:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730705AbfC3LY4 (ORCPT ); Sat, 30 Mar 2019 07:24:56 -0400 Received: from mx1.redhat.com ([209.132.183.28]:30069 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730684AbfC3LYz (ORCPT ); Sat, 30 Mar 2019 07:24:55 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8432E308424D; Sat, 30 Mar 2019 11:24:55 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id 69ED9413F; Sat, 30 Mar 2019 11:24: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 20/28] HID: logitech-hidpp: allow non HID++ devices to be handled by this module Date: Sat, 30 Mar 2019 12:24:10 +0100 Message-Id: <20190330112418.15042-21-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.40]); Sat, 30 Mar 2019 11:24: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 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 --- 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 887af6068985..7f6e8e9ea0ea 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -2836,6 +2836,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 && @@ -2851,6 +2854,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 || @@ -2882,6 +2888,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; @@ -2951,6 +2960,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: @@ -2999,7 +3011,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 @@ -3257,6 +3274,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; @@ -3264,6 +3316,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) @@ -3307,12 +3371,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; @@ -3388,7 +3446,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); @@ -3399,6 +3456,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 Mar 30 11:24: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: 10878419 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 D331113B5 for ; Sat, 30 Mar 2019 11:24:58 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B989028EC6 for ; Sat, 30 Mar 2019 11:24:58 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AD64228FEB; Sat, 30 Mar 2019 11:24: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 3634C28EC6 for ; Sat, 30 Mar 2019 11:24:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730439AbfC3LY5 (ORCPT ); Sat, 30 Mar 2019 07:24:57 -0400 Received: from mx1.redhat.com ([209.132.183.28]:37072 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730684AbfC3LY5 (ORCPT ); Sat, 30 Mar 2019 07:24:57 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E0B9D59440; Sat, 30 Mar 2019 11:24:56 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id C642018AB6; Sat, 30 Mar 2019 11:24: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 21/28] HID: logitech-hidpp: make .probe usbhid capable Date: Sat, 30 Mar 2019 12:24:11 +0100 Message-Id: <20190330112418.15042-22-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Sat, 30 Mar 2019 11:24: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 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 --- 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 7f6e8e9ea0ea..e74f788e2ddc 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -3371,24 +3371,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); @@ -3402,7 +3401,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; } hid_info(hdev, "HID++ %u.%u device connected.\n", @@ -3414,37 +3413,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); @@ -3461,10 +3459,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); @@ -3528,7 +3525,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 Mar 30 11:24: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: 10878421 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 7171C13B5 for ; Sat, 30 Mar 2019 11:25:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5D0FD28EC6 for ; Sat, 30 Mar 2019 11:25:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 518F428FEB; Sat, 30 Mar 2019 11:25:01 +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 F303828EC6 for ; Sat, 30 Mar 2019 11:25:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730707AbfC3LZA (ORCPT ); Sat, 30 Mar 2019 07:25:00 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54528 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730684AbfC3LZA (ORCPT ); Sat, 30 Mar 2019 07:25:00 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 66C108110E; Sat, 30 Mar 2019 11:25:00 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id 30A0B5B0A1; Sat, 30 Mar 2019 11:24: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 22/28] HID: logitech-hidpp: simplify printing of HID++ version Date: Sat, 30 Mar 2019 12:24:12 +0100 Message-Id: <20190330112418.15042-23-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Sat, 30 Mar 2019 11:25: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 Simply always print the HID++ version on hidpp_root_get_protocol_version success. This also fixes the version not being printed when a HID++ device connected through a receiver is already connected when the hidpp driver is loaded. Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-hidpp.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index e74f788e2ddc..90be0e0e7cd7 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -896,7 +896,7 @@ static int hidpp_root_get_protocol_version(struct hidpp_device *hidpp) if (ret == HIDPP_ERROR_INVALID_SUBID) { hidpp->protocol_major = 1; hidpp->protocol_minor = 0; - return 0; + goto print_version; } /* the device might not be connected */ @@ -914,18 +914,15 @@ static int hidpp_root_get_protocol_version(struct hidpp_device *hidpp) hidpp->protocol_major = response.fap.params[0]; hidpp->protocol_minor = response.fap.params[1]; - return ret; +print_version: + hid_info(hidpp->hid_dev, "HID++ %u.%u device connected.\n", + hidpp->protocol_major, hidpp->protocol_minor); + return 0; } static bool hidpp_is_connected(struct hidpp_device *hidpp) { - int ret; - - ret = hidpp_root_get_protocol_version(hidpp); - if (!ret) - hid_dbg(hidpp->hid_dev, "HID++ %u.%u device connected.\n", - hidpp->protocol_major, hidpp->protocol_minor); - return ret == 0; + return hidpp_root_get_protocol_version(hidpp) == 0; } /* -------------------------------------------------------------------------- */ @@ -3206,8 +3203,6 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) hid_err(hdev, "Can not get the protocol version.\n"); return; } - hid_info(hdev, "HID++ %u.%u device connected.\n", - hidpp->protocol_major, hidpp->protocol_minor); } if (hidpp->name == hdev->name && hidpp->protocol_major >= 2) { @@ -3404,9 +3399,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) goto hid_hw_init_fail; } - hid_info(hdev, "HID++ %u.%u device connected.\n", - hidpp->protocol_major, hidpp->protocol_minor); - hidpp_overwrite_name(hdev); } From patchwork Sat Mar 30 11:24: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: 10878423 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 EE34D139A for ; Sat, 30 Mar 2019 11:25:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D98FA28EC6 for ; Sat, 30 Mar 2019 11:25:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CCDE228FEB; Sat, 30 Mar 2019 11:25: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 7697828EC6 for ; Sat, 30 Mar 2019 11:25:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730708AbfC3LZC (ORCPT ); Sat, 30 Mar 2019 07:25:02 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54542 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730684AbfC3LZB (ORCPT ); Sat, 30 Mar 2019 07:25:01 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C57BC8110E; Sat, 30 Mar 2019 11:25:01 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id A9316413F; Sat, 30 Mar 2019 11:25: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 23/28] HID: logitech-hidpp: remove hidpp_is_connected() Date: Sat, 30 Mar 2019 12:24:13 +0100 Message-Id: <20190330112418.15042-24-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Sat, 30 Mar 2019 11:25: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 Remove the hidpp_is_connected() function wrapper, and have the callers directly call hidpp_root_get_protocol_version() instead. Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-hidpp.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 90be0e0e7cd7..b782062b147f 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -920,11 +920,6 @@ static int hidpp_root_get_protocol_version(struct hidpp_device *hidpp) return 0; } -static bool hidpp_is_connected(struct hidpp_device *hidpp) -{ - return hidpp_root_get_protocol_version(hidpp) == 0; -} - /* -------------------------------------------------------------------------- */ /* 0x0005: GetDeviceNameType */ /* -------------------------------------------------------------------------- */ @@ -3198,7 +3193,7 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) /* the device is already connected, we can ask for its name and * protocol */ if (!hidpp->protocol_major) { - ret = !hidpp_is_connected(hidpp); + ret = hidpp_root_get_protocol_version(hidpp); if (ret) { hid_err(hdev, "Can not get the protocol version.\n"); return; @@ -3390,7 +3385,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) if (hidpp->quirks & HIDPP_QUIRK_UNIFYING) hidpp_unifying_init(hidpp); - connected = hidpp_is_connected(hidpp); + connected = hidpp_root_get_protocol_version(hidpp) == 0; atomic_set(&hidpp->connected, connected); if (!(hidpp->quirks & HIDPP_QUIRK_UNIFYING)) { if (!connected) { From patchwork Sat Mar 30 11:24: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: 10878425 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 4CF1E13B5 for ; Sat, 30 Mar 2019 11:25:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 37B4C28EC6 for ; Sat, 30 Mar 2019 11:25:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2C30528FEB; Sat, 30 Mar 2019 11:25: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 CB14F28EC6 for ; Sat, 30 Mar 2019 11:25:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730712AbfC3LZD (ORCPT ); Sat, 30 Mar 2019 07:25:03 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54148 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730684AbfC3LZD (ORCPT ); Sat, 30 Mar 2019 07:25:03 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2DC66308FC20; Sat, 30 Mar 2019 11:25:03 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id 125BA413F; Sat, 30 Mar 2019 11:25: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 24/28] HID: logitech-hidpp: change low battery level threshold from 31 to 30 percent Date: Sat, 30 Mar 2019 12:24:14 +0100 Message-Id: <20190330112418.15042-25-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.43]); Sat, 30 Mar 2019 11:25: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 According to hidpp20_batterylevel_get_battery_info my Logitech K270 keyboard reports only 2 battery levels. This matches with what I've seen after testing with batteries at varying level of fullness, it always reports either 5% or 30%. Windows reports "battery good" for the 30% level. I've captured an USB trace of Windows reading the battery and it is getting the same info as the Linux hidpp code gets. Now that Linux handles these devices as hidpp devices, it reports the battery as being low as it treats anything under 31% as low, this leads to the user constantly getting a "Keyboard battery is low" warning from GNOME3, which is very annoying. This commit fixes this by changing the low threshold to anything under 30%, which I assume is what Windows does. Signed-off-by: Hans de Goede --- Changes in v2: -Add a comment to the code explaining wy we deviate from the spec. --- drivers/hid/hid-logitech-hidpp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index b782062b147f..46212e88f7e3 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -1053,7 +1053,11 @@ static int hidpp_map_battery_level(int capacity) { if (capacity < 11) return POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; - else if (capacity < 31) + /* + * The spec says this should be < 31 but some devices report 30 + * with brand new batteries and Windows reports 30 as "Good". + */ + else if (capacity < 30) return POWER_SUPPLY_CAPACITY_LEVEL_LOW; else if (capacity < 81) return POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; From patchwork Sat Mar 30 11:24: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: 10878427 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 2FA2913B5 for ; Sat, 30 Mar 2019 11:25:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1B65328EC6 for ; Sat, 30 Mar 2019 11:25:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0FB3B28FEB; Sat, 30 Mar 2019 11:25: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 2D74328EC6 for ; Sat, 30 Mar 2019 11:25:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730717AbfC3LZE (ORCPT ); Sat, 30 Mar 2019 07:25:04 -0400 Received: from mx1.redhat.com ([209.132.183.28]:48208 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730684AbfC3LZE (ORCPT ); Sat, 30 Mar 2019 07:25:04 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8B9D1308339D; Sat, 30 Mar 2019 11:25:04 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6E6A3413F; Sat, 30 Mar 2019 11:25: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 25/28] HID: logitech-hidpp: use RAP instead of FAP to get the protocol version Date: Sat, 30 Mar 2019 12:24:15 +0100 Message-Id: <20190330112418.15042-26-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.44]); Sat, 30 Mar 2019 11:25:04 +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 46212e88f7e3..656a5ce3fe03 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -885,13 +885,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; @@ -911,8 +914,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 Mar 30 11:24: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: 10878429 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 6129B139A for ; Sat, 30 Mar 2019 11:25:08 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4DABB28EC6 for ; Sat, 30 Mar 2019 11:25:08 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 41FF128FEB; Sat, 30 Mar 2019 11:25: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 ED81328EC6 for ; Sat, 30 Mar 2019 11:25:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730718AbfC3LZH (ORCPT ); Sat, 30 Mar 2019 07:25:07 -0400 Received: from mx1.redhat.com ([209.132.183.28]:50878 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730684AbfC3LZH (ORCPT ); Sat, 30 Mar 2019 07:25:07 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 581FFF74D2; Sat, 30 Mar 2019 11:25:07 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id CCE1718AAA; Sat, 30 Mar 2019 11:25:04 +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 26/28] HID: logitech-hidpp: skip getting pairing info on devs without a long report Date: Sat, 30 Mar 2019 12:24:16 +0100 Message-Id: <20190330112418.15042-27-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Sat, 30 Mar 2019 11:25: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 27 MHz receivers do not support long register reads. This commit makes the hidpp code skip hidpp_unifying_init(), which gets the device serial and name through long register reads, on devices which do not support such reads. This fixes a 5 second delay during probe caused by hidpp_unifying_init() waiting for the first long register read to timeout before bailing. Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-hidpp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 656a5ce3fe03..b4dc8d26a534 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -3395,7 +3395,9 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) /* Allow incoming packets */ hid_device_io_start(hdev); - if (hidpp->quirks & HIDPP_QUIRK_UNIFYING) + if ((hidpp->quirks & HIDPP_QUIRK_UNIFYING) && + hidpp_validate_report(hdev, REPORT_ID_HIDPP_LONG, + HIDPP_REPORT_LONG_LENGTH - 1, false)) hidpp_unifying_init(hidpp); connected = hidpp_root_get_protocol_version(hidpp) == 0; From patchwork Sat Mar 30 11:24: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: 10878431 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 80ABC13B5 for ; Sat, 30 Mar 2019 11:25:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6674C28EC6 for ; Sat, 30 Mar 2019 11:25:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5800528FEB; Sat, 30 Mar 2019 11:25:13 +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 8023828EC6 for ; Sat, 30 Mar 2019 11:25:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730684AbfC3LZM (ORCPT ); Sat, 30 Mar 2019 07:25:12 -0400 Received: from mx1.redhat.com ([209.132.183.28]:41290 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730641AbfC3LZL (ORCPT ); Sat, 30 Mar 2019 07:25:11 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0F4EF3086209; Sat, 30 Mar 2019 11:25:11 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9C2FF413F; Sat, 30 Mar 2019 11:25: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 27/28] HID: logitech-hidpp: add input_device ptr to struct hidpp_device Date: Sat, 30 Mar 2019 12:24:17 +0100 Message-Id: <20190330112418.15042-28-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Sat, 30 Mar 2019 11:25: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 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 b4dc8d26a534..f02a665dfebe 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 */ @@ -434,14 +434,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; @@ -475,7 +476,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; @@ -2265,7 +2266,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; @@ -2309,31 +2309,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); } } @@ -2341,19 +2340,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); } } @@ -2403,7 +2401,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]) { @@ -2414,11 +2412,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) @@ -2536,10 +2534,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 @@ -2567,28 +2561,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; } @@ -2615,24 +2593,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) { /* @@ -2646,33 +2624,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; @@ -2681,24 +2659,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, bool origin_is_hid_core) { - 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, @@ -2878,13 +2852,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) { + hidpp->input = input; + if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) wtp_populate_input(hidpp, input, origin_is_hid_core); else if (hidpp->quirks & HIDPP_QUIRK_CLASS_M560) m560_populate_input(hidpp, input, origin_is_hid_core); - - if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL) - hidpp->vertical_wheel_counter.dev = input; } static int hidpp_input_configured(struct hid_device *hdev, @@ -3028,10 +3001,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; } @@ -3354,10 +3327,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 Mar 30 11:24:18 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: 10878433 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 5798913B5 for ; Sat, 30 Mar 2019 11:25:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 447CE28EC6 for ; Sat, 30 Mar 2019 11:25:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 36BA428FEB; Sat, 30 Mar 2019 11:25: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 B2A9728EC6 for ; Sat, 30 Mar 2019 11:25:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730430AbfC3LZN (ORCPT ); Sat, 30 Mar 2019 07:25:13 -0400 Received: from mx1.redhat.com ([209.132.183.28]:43020 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730641AbfC3LZN (ORCPT ); Sat, 30 Mar 2019 07:25:13 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6D8A630821C2; Sat, 30 Mar 2019 11:25:12 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-76.ams2.redhat.com [10.36.116.76]) by smtp.corp.redhat.com (Postfix) with ESMTP id 52E5E413F; Sat, 30 Mar 2019 11:25: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 28/28] HID: logitech-hidpp: add support for HID++ 1.0 mice hwheel and extra buttons Date: Sat, 30 Mar 2019 12:24:18 +0100 Message-Id: <20190330112418.15042-29-hdegoede@redhat.com> In-Reply-To: <20190330112418.15042-1-hdegoede@redhat.com> References: <20190330112418.15042-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.47]); Sat, 30 Mar 2019 11:25: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 Some HID++ 1.0 (27 MHz) mice have a wheel which clicks left / right for horizontal scrolling and some extra buttons which are not reported through the regular mouse input report. This commits adds support for using the special HID++ input reports for the hwheel and extra buttons, so that these will work under Linux. Signed-off-by: Hans de Goede --- drivers/hid/hid-logitech-hidpp.c | 86 ++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index f02a665dfebe..08040ef095ef 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_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,7 @@ 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_HWHEEL_AND_EXTRA_BTNS BIT(29) /* Convenience constant to check for any high-res support. */ #define HIDPP_QUIRK_HI_RES_SCROLL (HIDPP_QUIRK_HI_RES_SCROLL_1P0 | \ @@ -2774,6 +2778,73 @@ static int g920_get_config(struct hidpp_device *hidpp) return 0; } +/* -------------------------------------------------------------------------- */ +/* HID++1.0 mice which use HID++ report for hwheel and extra buttons */ +/* -------------------------------------------------------------------------- */ + +static int hidpp10_hwheel_connect(struct hid_device *hdev, bool connected) +{ + struct hidpp_device *hidpp = hid_get_drvdata(hdev); + int ret; + + /* Bit 5 enables HID++ 1.0 hwheel reporting */ + ret = hidpp10_set_register_bit(hidpp, HIDPP_REG_GENERAL, 0, 5); + if (ret) + return ret; + + /* Bit 3 enables HID++ 1.0 extra buttons reporting */ + return hidpp10_set_register_bit(hidpp, HIDPP_REG_GENERAL, 0, 3); +} + +static int hidpp10_hwheel_raw_event(struct hidpp_device *hidpp, + u8 *data, int size) +{ + if (!hidpp->input) + return -EINVAL; + + if (size < 7) + return 0; + + if (data[0] == REPORT_ID_HIDPP_SHORT && + data[2] == HIDPP_SUB_ID_ROLLER) { + s8 value = data[4]; + + input_report_rel(hidpp->input, REL_HWHEEL, value); + input_report_rel(hidpp->input, REL_HWHEEL_HI_RES, value * 120); + input_sync(hidpp->input); + } + + if (data[0] == REPORT_ID_HIDPP_SHORT && + data[2] == HIDPP_SUB_ID_MOUSE_EXTRA_BTNS) { + int i; + + for (i = 0; i < 8; i++) + input_report_key(hidpp->input, BTN_0 + i, + (data[4] & (1 << i))); + input_sync(hidpp->input); + } + + return 1; +} + +static void hidpp10_hwheel_populate_input(struct hidpp_device *hidpp, + struct input_dev *input_dev, bool origin_is_hid_core) +{ + __set_bit(EV_REL, input_dev->evbit); + __set_bit(REL_HWHEEL, input_dev->relbit); + __set_bit(REL_HWHEEL_HI_RES, input_dev->relbit); + + __set_bit(EV_KEY, input_dev->evbit); + __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 */ /* -------------------------------------------------------------------------- */ @@ -2858,6 +2929,8 @@ static void hidpp_populate_input(struct hidpp_device *hidpp, wtp_populate_input(hidpp, input, origin_is_hid_core); else if (hidpp->quirks & HIDPP_QUIRK_CLASS_M560) m560_populate_input(hidpp, input, origin_is_hid_core); + else if (hidpp->quirks & HIDPP_QUIRK_HIDPP_HWHEEL_AND_EXTRA_BTNS) + hidpp10_hwheel_populate_input(hidpp, input, origin_is_hid_core); } static int hidpp_input_configured(struct hid_device *hdev, @@ -2929,6 +3002,9 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data, return ret; } + if (hidpp->quirks & HIDPP_QUIRK_HIDPP_HWHEEL_AND_EXTRA_BTNS) + hidpp10_hwheel_raw_event(hidpp, data, size); + return 0; } @@ -3174,6 +3250,10 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) ret = k400_connect(hdev, connected); if (ret) return; + } else if (hidpp->quirks & HIDPP_QUIRK_HIDPP_HWHEEL_AND_EXTRA_BTNS) { + ret = hidpp10_hwheel_connect(hdev, connected); + if (ret) + return; } /* the device is already connected, we can ask for its name and @@ -3493,6 +3573,12 @@ static const struct hid_device_id hidpp_devices[] = { { /* Solar Keyboard Logitech K750 */ LDJ_DEVICE(0x4002), .driver_data = HIDPP_QUIRK_CLASS_K750 }, + { /* Mouse from Logitech "Cordless Rechargeable Desktop" (M-RAK89D) */ + LDJ_DEVICE(0x0029), + .driver_data = HIDPP_QUIRK_HIDPP_HWHEEL_AND_EXTRA_BTNS }, + { /* Mouse Logitech MX3200 (M-RAZ105) */ + LDJ_DEVICE(0x003a), + .driver_data = HIDPP_QUIRK_HIDPP_HWHEEL_AND_EXTRA_BTNS }, { LDJ_DEVICE(HID_ANY_ID) },