From patchwork Thu Oct 17 16:34:58 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 836428 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 667921DF745; Thu, 17 Oct 2024 16:35:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729182911; cv=none; b=eFS+GmY1NIt4Yt87BQxdtqR7Y5svfOnVQDQcC4GP012vZwuZFyDdcugrpuYKtgS3/cDcPzsuX6bPl3/7ALLhUI+sBB80getPX/5Z4rxuXFMA8F2uof6EUUhSBh7Gbh+Rp6L8CFodHxeLOwln4MdD3K+Wsw3dqN8nV4HPz+h6EJY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729182911; c=relaxed/simple; bh=pgm6wn80wXgtOLXNt5NNVQ0KRgGvvi85msQODBFXiNs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=GTjWcMU6q/pLLxCI4uvRx0L4H0Jl3a0G4sUOZBe4OoE9l/Bgcrk8LGq7nNGSVTii0Dv7mbTsUaCbSghMELHCKgEh0R6OYeGRjzvy1JfL/jB/0/sTszvJLE5syaofpShXlHO9NKWt2NH/utNTBhG7eACuo51onFa7JJ2pOoO2vz8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gYsMrfal; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="gYsMrfal" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D8231C4CECE; Thu, 17 Oct 2024 16:35:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729182910; bh=pgm6wn80wXgtOLXNt5NNVQ0KRgGvvi85msQODBFXiNs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=gYsMrfalrgaSoD2ejidStOpGz4S/SUbbuS5atO/9KM8vciaDG23LMg9DZyGgQaoHQ O+gukJl8qioQb4B/2AdFn4SQbArKzLq9aHYduNsDcNhbKMzi658fzMydcgLqYETVg/ w4oMWo9zMRGxyvs3so9Gdpl+u7TZ+c/uj2+lwyEgPMgUntacb2IeN2abdEFuky5v+4 Z2gBu1s85rtMK7wUDJEoZW26tWPnqLfTuz0CwsxrAFt81pQ8DSkup4/2yMlzUqvP5M Hzf76SYNoRY+8TRvlStp0T1IFPi0ckYx9UcT9mALm0jQtLmclmZ13wnriPfmyFdxlH 1JomV32FxV+Qg== From: Benjamin Tissoires Date: Thu, 17 Oct 2024 18:34:58 +0200 Subject: [PATCH v2 1/3] HID: bpf: Fix NKRO on Mistel MD770 Precedence: bulk X-Mailing-List: linux-input@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241017-import_bpf_6-13-v2-1-6a7acb89a97f@kernel.org> References: <20241017-import_bpf_6-13-v2-0-6a7acb89a97f@kernel.org> In-Reply-To: <20241017-import_bpf_6-13-v2-0-6a7acb89a97f@kernel.org> To: Jiri Kosina Cc: linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, Benjamin Tissoires , Tatsuyuki Ishi X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1729182907; l=8943; i=bentiss@kernel.org; s=20230215; h=from:subject:message-id; bh=pgm6wn80wXgtOLXNt5NNVQ0KRgGvvi85msQODBFXiNs=; b=envTh4+vvHtrEFcPPeWA48uoPe4P/63vQwdsFW4bou/6m91v1d1b3ySj5INVsWVAxLsb2QP18 3Az6Cv0kiwoCHxG/zS9JDv3RnPC5ucXQsxcmhr2ZkdFXDSvVeu3LIxT X-Developer-Key: i=bentiss@kernel.org; a=ed25519; pk=7D1DyAVh6ajCkuUTudt/chMuXWIJHlv2qCsRkIizvFw= Mistel MD770 keyboard (using Holtek Semiconductor, Inc. controller) has a quirk in report descriptor in one of its interfaces (more detail in the source file). Fix up the descriptor to allow NKRO to work again. Tested by loading the BPF program and confirming that 8 simultaneous keypresses work. Link: https://bugzilla.kernel.org/show_bug.cgi?id=218495 Link: https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/merge_requests/122 Signed-off-by: Tatsuyuki Ishi Signed-off-by: Benjamin Tissoires --- no changes in v2 --- drivers/hid/bpf/progs/Mistel__MD770.bpf.c | 154 ++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/drivers/hid/bpf/progs/Mistel__MD770.bpf.c b/drivers/hid/bpf/progs/Mistel__MD770.bpf.c new file mode 100644 index 0000000000000000000000000000000000000000..fb8b5a6968b125ed88a456aefb427ede0e0bfa9b --- /dev/null +++ b/drivers/hid/bpf/progs/Mistel__MD770.bpf.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Tatsuyuki Ishi + */ + +#include "vmlinux.h" +#include "hid_bpf.h" +#include "hid_bpf_helpers.h" +#include + +#define VID_HOLTEK 0x04D9 +#define PID_MD770 0x0339 +#define RDESC_SIZE 203 + +HID_BPF_CONFIG( + HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, VID_HOLTEK, PID_MD770) +); + +/* + * The Mistel MD770 keyboard reports the first 6 simultaneous key presses + * through the first interface, and anything beyond that through a second + * interface. Unfortunately, the second interface's report descriptor has an + * error, causing events to be malformed and ignored. This HID-BPF driver + * fixes the descriptor to allow NKRO to work again. + * + * For reference, this is the original report descriptor: + * + * 0x05, 0x01, // Usage Page (Generic Desktop) 0 + * 0x09, 0x80, // Usage (System Control) 2 + * 0xa1, 0x01, // Collection (Application) 4 + * 0x85, 0x01, // Report ID (1) 6 + * 0x19, 0x81, // Usage Minimum (129) 8 + * 0x29, 0x83, // Usage Maximum (131) 10 + * 0x15, 0x00, // Logical Minimum (0) 12 + * 0x25, 0x01, // Logical Maximum (1) 14 + * 0x95, 0x03, // Report Count (3) 16 + * 0x75, 0x01, // Report Size (1) 18 + * 0x81, 0x02, // Input (Data,Var,Abs) 20 + * 0x95, 0x01, // Report Count (1) 22 + * 0x75, 0x05, // Report Size (5) 24 + * 0x81, 0x01, // Input (Cnst,Arr,Abs) 26 + * 0xc0, // End Collection 28 + * 0x05, 0x0c, // Usage Page (Consumer Devices) 29 + * 0x09, 0x01, // Usage (Consumer Control) 31 + * 0xa1, 0x01, // Collection (Application) 33 + * 0x85, 0x02, // Report ID (2) 35 + * 0x15, 0x00, // Logical Minimum (0) 37 + * 0x25, 0x01, // Logical Maximum (1) 39 + * 0x95, 0x12, // Report Count (18) 41 + * 0x75, 0x01, // Report Size (1) 43 + * 0x0a, 0x83, 0x01, // Usage (AL Consumer Control Config) 45 + * 0x0a, 0x8a, 0x01, // Usage (AL Email Reader) 48 + * 0x0a, 0x92, 0x01, // Usage (AL Calculator) 51 + * 0x0a, 0x94, 0x01, // Usage (AL Local Machine Browser) 54 + * 0x09, 0xcd, // Usage (Play/Pause) 57 + * 0x09, 0xb7, // Usage (Stop) 59 + * 0x09, 0xb6, // Usage (Scan Previous Track) 61 + * 0x09, 0xb5, // Usage (Scan Next Track) 63 + * 0x09, 0xe2, // Usage (Mute) 65 + * 0x09, 0xea, // Usage (Volume Down) 67 + * 0x09, 0xe9, // Usage (Volume Up) 69 + * 0x0a, 0x21, 0x02, // Usage (AC Search) 71 + * 0x0a, 0x23, 0x02, // Usage (AC Home) 74 + * 0x0a, 0x24, 0x02, // Usage (AC Back) 77 + * 0x0a, 0x25, 0x02, // Usage (AC Forward) 80 + * 0x0a, 0x26, 0x02, // Usage (AC Stop) 83 + * 0x0a, 0x27, 0x02, // Usage (AC Refresh) 86 + * 0x0a, 0x2a, 0x02, // Usage (AC Bookmarks) 89 + * 0x81, 0x02, // Input (Data,Var,Abs) 92 + * 0x95, 0x01, // Report Count (1) 94 + * 0x75, 0x0e, // Report Size (14) 96 + * 0x81, 0x01, // Input (Cnst,Arr,Abs) 98 + * 0xc0, // End Collection 100 + * 0x05, 0x01, // Usage Page (Generic Desktop) 101 + * 0x09, 0x02, // Usage (Mouse) 103 + * 0xa1, 0x01, // Collection (Application) 105 + * 0x09, 0x01, // Usage (Pointer) 107 + * 0xa1, 0x00, // Collection (Physical) 109 + * 0x85, 0x03, // Report ID (3) 111 + * 0x05, 0x09, // Usage Page (Button) 113 + * 0x19, 0x01, // Usage Minimum (1) 115 + * 0x29, 0x08, // Usage Maximum (8) 117 + * 0x15, 0x00, // Logical Minimum (0) 119 + * 0x25, 0x01, // Logical Maximum (1) 121 + * 0x75, 0x01, // Report Size (1) 123 + * 0x95, 0x08, // Report Count (8) 125 + * 0x81, 0x02, // Input (Data,Var,Abs) 127 + * 0x05, 0x01, // Usage Page (Generic Desktop) 129 + * 0x09, 0x30, // Usage (X) 131 + * 0x09, 0x31, // Usage (Y) 133 + * 0x16, 0x01, 0x80, // Logical Minimum (-32767) 135 + * 0x26, 0xff, 0x7f, // Logical Maximum (32767) 138 + * 0x75, 0x10, // Report Size (16) 141 + * 0x95, 0x02, // Report Count (2) 143 + * 0x81, 0x06, // Input (Data,Var,Rel) 145 + * 0x09, 0x38, // Usage (Wheel) 147 + * 0x15, 0x81, // Logical Minimum (-127) 149 + * 0x25, 0x7f, // Logical Maximum (127) 151 + * 0x75, 0x08, // Report Size (8) 153 + * 0x95, 0x01, // Report Count (1) 155 + * 0x81, 0x06, // Input (Data,Var,Rel) 157 + * 0x05, 0x0c, // Usage Page (Consumer Devices) 159 + * 0x0a, 0x38, 0x02, // Usage (AC Pan) 161 + * 0x95, 0x01, // Report Count (1) 164 + * 0x81, 0x06, // Input (Data,Var,Rel) 166 + * 0xc0, // End Collection 168 + * 0xc0, // End Collection 169 + * 0x05, 0x01, // Usage Page (Generic Desktop) 170 + * 0x09, 0x06, // Usage (Keyboard) 172 + * 0xa1, 0x01, // Collection (Application) 174 + * 0x85, 0x04, // Report ID (4) 176 + * 0x05, 0x07, // Usage Page (Keyboard) 178 + * 0x95, 0x01, // Report Count (1) 180 + * 0x75, 0x08, // Report Size (8) 182 + * 0x81, 0x03, // Input (Cnst,Var,Abs) 184 + * 0x95, 0xe8, // Report Count (232) 186 + * 0x75, 0x01, // Report Size (1) 188 + * 0x15, 0x00, // Logical Minimum (0) 190 + * 0x25, 0x01, // Logical Maximum (1) 192 + * 0x05, 0x07, // Usage Page (Keyboard) 194 + * 0x19, 0x00, // Usage Minimum (0) 196 + * 0x29, 0xe7, // Usage Maximum (231) 198 + * 0x81, 0x00, // Input (Data,Arr,Abs) 200 <- change to 0x81, 0x02 (Data,Var,Abs) + * 0xc0, // End Collection 202 + */ + +SEC(HID_BPF_RDESC_FIXUP) +int BPF_PROG(hid_rdesc_fixup_mistel_md770, struct hid_bpf_ctx *hctx) +{ + __u8 *data = hid_bpf_get_data(hctx, 0, HID_MAX_DESCRIPTOR_SIZE); + + if (!data) + return 0; /* EPERM check */ + + if (data[201] == 0x00) + data[201] = 0x02; + + return 0; +} + +HID_BPF_OPS(mistel_md770) = { + .hid_rdesc_fixup = (void *)hid_rdesc_fixup_mistel_md770, +}; + +SEC("syscall") +int probe(struct hid_bpf_probe_args *ctx) +{ + ctx->retval = ctx->rdesc_size != RDESC_SIZE; + if (ctx->retval) + ctx->retval = -EINVAL; + + return 0; +} + +char _license[] SEC("license") = "GPL"; From patchwork Thu Oct 17 16:34:59 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 836885 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CFD871DF990; Thu, 17 Oct 2024 16:35:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729182912; cv=none; b=C/gPayZD0UHeDP8mz3aE2DXwJ+fogPNJsqBzQf12+qYrx6kFWRH9kBnNsFp23KNE7cwWRLihKBr2MB+fB4cU4rhNvOWKF8sdkKJO4rAKeqhRD9J4WxkgGly5nZA7vGL5x3KnGZpAgXVn2GjQwqW/f/ZOwY9aQb9XNasb6BprBPs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729182912; c=relaxed/simple; bh=EMTxQfF0LlVN3f5EpYmdrDjwAeI5+S5pl3WhboVvu/Q=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=uw6w7yct5OkM5qD7ogv5P5jiCVS81jh2yw6G7vQC9Tp+2yKOuOyVDuNZfBE9mL6fOq4/GL4Gd9mBjcpPqNx82xH07kcaUP7BzNPzln2yjqoyW0CT17WdpUoiYIydaRMhXJln0fUapeF1PGh9s8QVW9dYBJWtxI4jIp627EgxMvg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=JoEdyVSP; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="JoEdyVSP" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 513E4C4CEC3; Thu, 17 Oct 2024 16:35:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729182912; bh=EMTxQfF0LlVN3f5EpYmdrDjwAeI5+S5pl3WhboVvu/Q=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=JoEdyVSP9+uUONZ0aFhl9p9wjCvIROm3wqAhP3NwUFFAofFmZnA/9R93/mlBXkRW7 +auY0Nb6GbpEDBfVIiD8MwNtcOpnFJZjYotwZxmoIPVLb6SQyOhGRgkfEfjTCWcbQV BS4eFhyPooGq4SDCHXgwi0yraz5d3j2wwoM9bTpP7LbZIyWYf/EQkVyIA3FxFrg0xu RpIZVeFN/6WYQmf0qV32briMt24bARby0ZQjdAjQSLawQYKYF2ot6/L9x4eu6Wx/Uy 1a/NPi4ivMWlpfsTqEHbOiOpig0HDjyLtuh9EdfR3o4MD/CDIwm6dHUXTjdkd+WZVX 7ZqZjgm7bc2QQ== From: Benjamin Tissoires Date: Thu, 17 Oct 2024 18:34:59 +0200 Subject: [PATCH v2 2/3] HID: bpf: Fix Rapoo M50 Plus Silent side buttons Precedence: bulk X-Mailing-List: linux-input@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241017-import_bpf_6-13-v2-2-6a7acb89a97f@kernel.org> References: <20241017-import_bpf_6-13-v2-0-6a7acb89a97f@kernel.org> In-Reply-To: <20241017-import_bpf_6-13-v2-0-6a7acb89a97f@kernel.org> To: Jiri Kosina Cc: linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, Benjamin Tissoires , =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1729182907; l=8376; i=bentiss@kernel.org; s=20230215; h=from:subject:message-id; bh=EMTxQfF0LlVN3f5EpYmdrDjwAeI5+S5pl3WhboVvu/Q=; b=FxHfhRmIeD11tUwIpyKOJ2VhNEk3fxCLTvFex50hS59Y8pU7NsEST4QS34UqNCRJT8wQsgeac pZccISPOLzQAzqnuMuVpSxflpqyRqrIgUyqelh0FRYdtswfUHFcEurq X-Developer-Key: i=bentiss@kernel.org; a=ed25519; pk=7D1DyAVh6ajCkuUTudt/chMuXWIJHlv2qCsRkIizvFw= The Rapoo M50 Plus Silent mouse has 2 side buttons in addition to the left, right and middles buttons. However, its original HID descriptor has a Usage Maximum of 3, preventing the side buttons to work. This HID-BPF driver changes that usage to 5. Link: https://gitlab.freedesktop.org/libinput/libinput/-/issues/1015 Link: https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/merge_requests/116 Signed-off-by: José Expósito Signed-off-by: Benjamin Tissoires --- no changes in v2 --- drivers/hid/bpf/progs/Rapoo__M50-Plus-Silent.bpf.c | 148 +++++++++++++++++++++ 1 file changed, 148 insertions(+) diff --git a/drivers/hid/bpf/progs/Rapoo__M50-Plus-Silent.bpf.c b/drivers/hid/bpf/progs/Rapoo__M50-Plus-Silent.bpf.c new file mode 100644 index 0000000000000000000000000000000000000000..6b379e45f531dbe843fe59fd98cc12d3fd3c8cc8 --- /dev/null +++ b/drivers/hid/bpf/progs/Rapoo__M50-Plus-Silent.bpf.c @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2024 José Expósito + */ + +#include "vmlinux.h" +#include "hid_bpf.h" +#include "hid_bpf_helpers.h" +#include + +#define VID_RAPOO 0x24AE +#define PID_M50 0x2015 +#define RDESC_SIZE 186 + +HID_BPF_CONFIG( + HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, VID_RAPOO, PID_M50) +); + +/* + * The Rapoo M50 Plus Silent mouse has 2 side buttons in addition to the left, + * right and middle buttons. However, its original HID descriptor has a Usage + * Maximum of 3, preventing the side buttons to work. This HID-BPF driver + * changes that usage to 5. + * + * For reference, this is the original report descriptor: + * + * 0x05, 0x01, // Usage Page (Generic Desktop) 0 + * 0x09, 0x02, // Usage (Mouse) 2 + * 0xa1, 0x01, // Collection (Application) 4 + * 0x85, 0x01, // Report ID (1) 6 + * 0x09, 0x01, // Usage (Pointer) 8 + * 0xa1, 0x00, // Collection (Physical) 10 + * 0x05, 0x09, // Usage Page (Button) 12 + * 0x19, 0x01, // Usage Minimum (1) 14 + * 0x29, 0x03, // Usage Maximum (3) 16 <- change to 0x05 + * 0x15, 0x00, // Logical Minimum (0) 18 + * 0x25, 0x01, // Logical Maximum (1) 20 + * 0x75, 0x01, // Report Size (1) 22 + * 0x95, 0x05, // Report Count (5) 24 + * 0x81, 0x02, // Input (Data,Var,Abs) 26 + * 0x75, 0x03, // Report Size (3) 28 + * 0x95, 0x01, // Report Count (1) 30 + * 0x81, 0x01, // Input (Cnst,Arr,Abs) 32 + * 0x05, 0x01, // Usage Page (Generic Desktop) 34 + * 0x09, 0x30, // Usage (X) 36 + * 0x09, 0x31, // Usage (Y) 38 + * 0x16, 0x01, 0x80, // Logical Minimum (-32767) 40 + * 0x26, 0xff, 0x7f, // Logical Maximum (32767) 43 + * 0x75, 0x10, // Report Size (16) 46 + * 0x95, 0x02, // Report Count (2) 48 + * 0x81, 0x06, // Input (Data,Var,Rel) 50 + * 0x09, 0x38, // Usage (Wheel) 52 + * 0x15, 0x81, // Logical Minimum (-127) 54 + * 0x25, 0x7f, // Logical Maximum (127) 56 + * 0x75, 0x08, // Report Size (8) 58 + * 0x95, 0x01, // Report Count (1) 60 + * 0x81, 0x06, // Input (Data,Var,Rel) 62 + * 0xc0, // End Collection 64 + * 0xc0, // End Collection 65 + * 0x05, 0x0c, // Usage Page (Consumer Devices) 66 + * 0x09, 0x01, // Usage (Consumer Control) 68 + * 0xa1, 0x01, // Collection (Application) 70 + * 0x85, 0x02, // Report ID (2) 72 + * 0x75, 0x10, // Report Size (16) 74 + * 0x95, 0x01, // Report Count (1) 76 + * 0x15, 0x01, // Logical Minimum (1) 78 + * 0x26, 0x8c, 0x02, // Logical Maximum (652) 80 + * 0x19, 0x01, // Usage Minimum (1) 83 + * 0x2a, 0x8c, 0x02, // Usage Maximum (652) 85 + * 0x81, 0x00, // Input (Data,Arr,Abs) 88 + * 0xc0, // End Collection 90 + * 0x05, 0x01, // Usage Page (Generic Desktop) 91 + * 0x09, 0x80, // Usage (System Control) 93 + * 0xa1, 0x01, // Collection (Application) 95 + * 0x85, 0x03, // Report ID (3) 97 + * 0x09, 0x82, // Usage (System Sleep) 99 + * 0x09, 0x81, // Usage (System Power Down) 101 + * 0x09, 0x83, // Usage (System Wake Up) 103 + * 0x15, 0x00, // Logical Minimum (0) 105 + * 0x25, 0x01, // Logical Maximum (1) 107 + * 0x19, 0x01, // Usage Minimum (1) 109 + * 0x29, 0x03, // Usage Maximum (3) 111 + * 0x75, 0x01, // Report Size (1) 113 + * 0x95, 0x03, // Report Count (3) 115 + * 0x81, 0x02, // Input (Data,Var,Abs) 117 + * 0x95, 0x05, // Report Count (5) 119 + * 0x81, 0x01, // Input (Cnst,Arr,Abs) 121 + * 0xc0, // End Collection 123 + * 0x05, 0x01, // Usage Page (Generic Desktop) 124 + * 0x09, 0x00, // Usage (Undefined) 126 + * 0xa1, 0x01, // Collection (Application) 128 + * 0x85, 0x05, // Report ID (5) 130 + * 0x06, 0x00, 0xff, // Usage Page (Vendor Defined Page 1) 132 + * 0x09, 0x01, // Usage (Vendor Usage 1) 135 + * 0x15, 0x81, // Logical Minimum (-127) 137 + * 0x25, 0x7f, // Logical Maximum (127) 139 + * 0x75, 0x08, // Report Size (8) 141 + * 0x95, 0x07, // Report Count (7) 143 + * 0xb1, 0x02, // Feature (Data,Var,Abs) 145 + * 0xc0, // End Collection 147 + * 0x06, 0x00, 0xff, // Usage Page (Vendor Defined Page 1) 148 + * 0x09, 0x0e, // Usage (Vendor Usage 0x0e) 151 + * 0xa1, 0x01, // Collection (Application) 153 + * 0x85, 0xba, // Report ID (186) 155 + * 0x95, 0x1f, // Report Count (31) 157 + * 0x75, 0x08, // Report Size (8) 159 + * 0x26, 0xff, 0x00, // Logical Maximum (255) 161 + * 0x15, 0x00, // Logical Minimum (0) 164 + * 0x09, 0x01, // Usage (Vendor Usage 1) 166 + * 0x91, 0x02, // Output (Data,Var,Abs) 168 + * 0x85, 0xba, // Report ID (186) 170 + * 0x95, 0x1f, // Report Count (31) 172 + * 0x75, 0x08, // Report Size (8) 174 + * 0x26, 0xff, 0x00, // Logical Maximum (255) 176 + * 0x15, 0x00, // Logical Minimum (0) 179 + * 0x09, 0x01, // Usage (Vendor Usage 1) 181 + * 0x81, 0x02, // Input (Data,Var,Abs) 183 + * 0xc0, // End Collection 185 + */ + +SEC(HID_BPF_RDESC_FIXUP) +int BPF_PROG(hid_rdesc_fixup_rapoo_m50, struct hid_bpf_ctx *hctx) +{ + __u8 *data = hid_bpf_get_data(hctx, 0, HID_MAX_DESCRIPTOR_SIZE); + + if (!data) + return 0; /* EPERM check */ + + if (data[17] == 0x03) + data[17] = 0x05; + + return 0; +} + +HID_BPF_OPS(rapoo_m50) = { + .hid_rdesc_fixup = (void *)hid_rdesc_fixup_rapoo_m50, +}; + +SEC("syscall") +int probe(struct hid_bpf_probe_args *ctx) +{ + ctx->retval = ctx->rdesc_size != RDESC_SIZE; + if (ctx->retval) + ctx->retval = -EINVAL; + + return 0; +} + +char _license[] SEC("license") = "GPL"; From patchwork Thu Oct 17 16:35:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 836427 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2EDF21DFD87; Thu, 17 Oct 2024 16:35:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729182914; cv=none; b=jU8vP/1QlKTozvyzytuqOpDoEH5SnYE62kpt0EHIjQnDc1NzZy7eNZGvLucTVDXiByAGSc/H01q9ljFuPbZaCtSr+g4e/e+HAAdxYBGdtEq3uqRG34ShKzarvcZ3QPKPB09TWaUxWhdEB5iTSqh6SUmwTQlLwvm+y073hB1Oa34= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729182914; c=relaxed/simple; bh=wHjaUMUGTPQe/HkvJVYcvU/Y5QGKlkTwf/y/FC47rCA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=SbRF/BPZ3Tp2K2TG36sPDIDJZmt1h86CTEk6nwaOKtIIVAXaoGFRrG+XhvT/+iqNbc14uyOPeg/JBz6horVQFslWSNjziPcfGMm8aEKXR5NX+GdfpBeiOd3y3Z71WfkhQganbD5Bz3EEH8+DsYOoVFqZFPJERyhOEJh9GuyR3+4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=e3hL9cyo; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="e3hL9cyo" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BE13CC4CED2; Thu, 17 Oct 2024 16:35:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729182913; bh=wHjaUMUGTPQe/HkvJVYcvU/Y5QGKlkTwf/y/FC47rCA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=e3hL9cyoQcDhcPoXJs2Ns+CsYRWvRpQtMVtdASWLRaxawwMTh5gq2P2G8QMvMO6xN Gw5hpnO3Nb9j3RVZLNndu/dx5eYeuwy+IYruVa1gtju8mv3tqMcisJuXxpEQBX2MBo vuysnwJK0H13w2cIb895CHqEIbbuYZRH1xMWM3qoY04yQBa55ORYkH1JR3sn6bw7GX cyK1ygoCzG2CXSsSWZH1UCJRhW8HGbpZ8kBR9lgRbVBpmMdb0cNYyosEP+DtuRiKEU 5zcQLMKvoxCm8XYnNG628tZd6ZxrbEozdWSGLl4Hu7bP7mI2kzU+cnbQjPg43cZUNB z9p6CoVhW+3rg== From: Benjamin Tissoires Date: Thu, 17 Oct 2024 18:35:00 +0200 Subject: [PATCH v2 3/3] HID: bpf: drop use of Logical|Physical|UsageRange Precedence: bulk X-Mailing-List: linux-input@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241017-import_bpf_6-13-v2-3-6a7acb89a97f@kernel.org> References: <20241017-import_bpf_6-13-v2-0-6a7acb89a97f@kernel.org> In-Reply-To: <20241017-import_bpf_6-13-v2-0-6a7acb89a97f@kernel.org> To: Jiri Kosina Cc: linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, Benjamin Tissoires , Peter Hutterer X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1729182907; l=12580; i=bentiss@kernel.org; s=20230215; h=from:subject:message-id; bh=wHjaUMUGTPQe/HkvJVYcvU/Y5QGKlkTwf/y/FC47rCA=; b=s0cjm6Gl+p4Da/TvFHVwsS4gR2azj40f2yaw5ASXcz1ejohmG/rxhMsSYKvWzV1+cYVFEdHzj c+QzfAWOr1aBMNCQpw3TQs03xCIaOA80GCyGOHvyOWilb5M91OmC65y X-Developer-Key: i=bentiss@kernel.org; a=ed25519; pk=7D1DyAVh6ajCkuUTudt/chMuXWIJHlv2qCsRkIizvFw= Replace with individual Minimum/Maximum calls to match the HID report descriptor - HID doesn't have a Range field. Abstracting this is good for hand-written descriptors but almost all tools will output min/max instead so let's stick with that. Signed-off-by: Peter Hutterer Signed-off-by: Benjamin Tissoires --- new in v2 --- drivers/hid/bpf/progs/Huion__Dial-2.bpf.c | 66 ++++++++++++++++--------- drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c | 60 ++++++++++++++-------- drivers/hid/bpf/progs/hid_report_helpers.h | 36 ++++++++++---- 3 files changed, 111 insertions(+), 51 deletions(-) diff --git a/drivers/hid/bpf/progs/Huion__Dial-2.bpf.c b/drivers/hid/bpf/progs/Huion__Dial-2.bpf.c index 2411dec6db08b684c6e24c73ab4d509300424768..9670e5ef8d54f0058260294ef99bc65e7e312472 100644 --- a/drivers/hid/bpf/progs/Huion__Dial-2.bpf.c +++ b/drivers/hid/bpf/progs/Huion__Dial-2.bpf.c @@ -214,7 +214,8 @@ static const __u8 fixed_rdesc_pad[] = { CollectionApplication( // -- Byte 0 in report ReportId(PAD_REPORT_ID) - LogicalRange_i8(0, 1) + LogicalMaximum_i8(0) + LogicalMaximum_i8(1) UsagePage_Digitizers Usage_Dig_TabletFunctionKeys CollectionPhysical( @@ -234,14 +235,17 @@ static const __u8 fixed_rdesc_pad[] = { Input(Var|Abs) // Byte 4 in report is the dial Usage_GD_Wheel - LogicalRange_i8(-1, 1) + LogicalMinimum_i8(-1) + LogicalMaximum_i8(1) ReportCount(1) ReportSize(8) Input(Var|Rel) // Byte 5 is the button state UsagePage_Button - UsageRange_i8(0x01, 0x8) - LogicalRange_i8(0x0, 0x1) + UsageMinimum_i8(0x01) + UsageMaximum_i8(0x08) + LogicalMinimum_i8(0x0) + LogicalMaximum_i8(0x1) ReportCount(7) ReportSize(1) Input(Var|Abs) @@ -265,7 +269,8 @@ static const __u8 fixed_rdesc_pen[] = { Usage_Dig_TipSwitch Usage_Dig_BarrelSwitch Usage_Dig_SecondaryBarrelSwitch // maps eraser to BTN_STYLUS2 - LogicalRange_i8(0, 1) + LogicalMinimum_i8(0) + LogicalMaximum_i8(1) ReportSize(1) ReportCount(3) Input(Var|Abs) @@ -280,22 +285,28 @@ static const __u8 fixed_rdesc_pen[] = { UsagePage_GenericDesktop Unit(cm) UnitExponent(-1) - PhysicalRange_i16(0, 266) - LogicalRange_i16(0, 32767) + PhysicalMinimum_i16(0) + PhysicalMaximum_i16(266) + LogicalMinimum_i16(0) + LogicalMaximum_i16(32767) Usage_GD_X Input(Var|Abs) // Bytes 2+3 - PhysicalRange_i16(0, 166) - LogicalRange_i16(0, 32767) + PhysicalMinimum_i16(0) + PhysicalMaximum_i16(166) + LogicalMinimum_i16(0) + LogicalMaximum_i16(32767) Usage_GD_Y Input(Var|Abs) // Bytes 4+5 ) UsagePage_Digitizers Usage_Dig_TipPressure - LogicalRange_i16(0, 8191) + LogicalMinimum_i16(0) + LogicalMaximum_i16(8191) Input(Var|Abs) // Byte 6+7 ReportSize(8) ReportCount(2) - LogicalRange_i8(-60, 60) + LogicalMinimum_i8(-60) + LogicalMaximum_i8(60) Usage_Dig_XTilt Usage_Dig_YTilt Input(Var|Abs) // Byte 8+9 @@ -313,7 +324,8 @@ static const __u8 fixed_rdesc_vendor[] = { Usage_Dig_Pen CollectionPhysical( // Byte 1 are the buttons - LogicalRange_i8(0, 1) + LogicalMinimum_i8(0) + LogicalMaximum_i8(1) ReportSize(1) Usage_Dig_TipSwitch Usage_Dig_BarrelSwitch @@ -333,25 +345,31 @@ static const __u8 fixed_rdesc_vendor[] = { UnitExponent(-1) // Note: reported logical range differs // from the pen report ID for x and y - LogicalRange_i16(0, 53340) - PhysicalRange_i16(0, 266) + LogicalMinimum_i16(0) + LogicalMaximum_i16(53340) + PhysicalMinimum_i16(0) + PhysicalMaximum_i16(266) // Bytes 2/3 in report Usage_GD_X Input(Var|Abs) - LogicalRange_i16(0, 33340) - PhysicalRange_i16(0, 166) + LogicalMinimum_i16(0) + LogicalMaximum_i16(33340) + PhysicalMinimum_i16(0) + PhysicalMaximum_i16(166) // Bytes 4/5 in report Usage_GD_Y Input(Var|Abs) ) // Bytes 6/7 in report - LogicalRange_i16(0, 8191) + LogicalMinimum_i16(0) + LogicalMaximum_i16(8191) Usage_Dig_TipPressure Input(Var|Abs) // Bytes 8/9 in report ReportCount(1) // Padding Input(Const) - LogicalRange_i8(-60, 60) + LogicalMinimum_i8(-60) + LogicalMaximum_i8(60) // Byte 10 in report Usage_Dig_XTilt // Byte 11 in report @@ -366,7 +384,8 @@ static const __u8 fixed_rdesc_vendor[] = { CollectionApplication( // Byte 0 ReportId(PAD_REPORT_ID) - LogicalRange_i8(0, 1) + LogicalMinimum_i8(0) + LogicalMaximum_i8(1) UsagePage_Digitizers Usage_Dig_TabletFunctionKeys CollectionPhysical( @@ -386,15 +405,18 @@ static const __u8 fixed_rdesc_vendor[] = { Input(Var|Abs) // Byte 4 is the button state UsagePage_Button - UsageRange_i8(0x01, 0x8) - LogicalRange_i8(0x0, 0x1) + UsageMinimum_i8(0x1) + UsageMaximum_i8(0x8) + LogicalMinimum_i8(0x0) + LogicalMaximum_i8(0x1) ReportCount(8) ReportSize(1) Input(Var|Abs) // Byte 5 is the top dial UsagePage_GenericDesktop Usage_GD_Wheel - LogicalRange_i8(-1, 1) + LogicalMinimum_i8(-1) + LogicalMaximum_i8(1) ReportCount(1) ReportSize(8) Input(Var|Rel) diff --git a/drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c b/drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c index b09b80132368b6c504a61e1965263bdaaac67fb0..13f64fb49800b16f6d4d48c378f065fcdf51202a 100644 --- a/drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c +++ b/drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c @@ -170,7 +170,8 @@ static const __u8 fixed_rdesc_pad[] = { CollectionApplication( // -- Byte 0 in report ReportId(PAD_REPORT_ID) - LogicalRange_i8(0, 1) + LogicalMinimum_i8(0) + LogicalMaximum_i8(1) UsagePage_Digitizers Usage_Dig_TabletFunctionKeys CollectionPhysical( @@ -190,14 +191,17 @@ static const __u8 fixed_rdesc_pad[] = { Input(Var|Abs) // Byte 4 in report is the wheel Usage_GD_Wheel - LogicalRange_i8(-1, 1) + LogicalMinimum_i8(-1) + LogicalMaximum_i8(1) ReportCount(1) ReportSize(8) Input(Var|Rel) // Byte 5 is the button state UsagePage_Button - UsageRange_i8(0x01, 0x6) - LogicalRange_i8(0x01, 0x6) + UsageMinimum_i8(0x1) + UsageMaximum_i8(0x6) + LogicalMinimum_i8(0x1) + LogicalMaximum_i8(0x6) ReportCount(1) ReportSize(8) Input(Arr|Abs) @@ -219,7 +223,8 @@ static const __u8 fixed_rdesc_pen[] = { Usage_Dig_TipSwitch Usage_Dig_BarrelSwitch Usage_Dig_SecondaryBarrelSwitch // maps eraser to BTN_STYLUS2 - LogicalRange_i8(0, 1) + LogicalMinimum_i8(0) + LogicalMaximum_i8(1) ReportSize(1) ReportCount(3) Input(Var|Abs) @@ -234,18 +239,23 @@ static const __u8 fixed_rdesc_pen[] = { UsagePage_GenericDesktop Unit(cm) UnitExponent(-1) - PhysicalRange_i16(0, 160) - LogicalRange_i16(0, 32767) + PhysicalMinimum_i16(0) + PhysicalMaximum_i16(160) + LogicalMinimum_i16(0) + LogicalMaximum_i16(32767) Usage_GD_X Input(Var|Abs) // Bytes 2+3 - PhysicalRange_i16(0, 100) - LogicalRange_i16(0, 32767) + PhysicalMinimum_i16(0) + PhysicalMaximum_i16(100) + LogicalMinimum_i16(0) + LogicalMaximum_i16(32767) Usage_GD_Y Input(Var|Abs) // Bytes 4+5 ) UsagePage_Digitizers Usage_Dig_TipPressure - LogicalRange_i16(0, 8191) + LogicalMinimum_i16(0) + LogicalMaximum_i16(8191) Input(Var|Abs) // Byte 6+7 // Two bytes padding so we don't need to change the report at all ReportSize(8) @@ -265,7 +275,8 @@ static const __u8 fixed_rdesc_vendor[] = { Usage_Dig_Pen CollectionPhysical( // Byte 1 are the buttons - LogicalRange_i8(0, 1) + LogicalMinimum_i8(0) + LogicalMaximum_i8(1) ReportSize(1) Usage_Dig_TipSwitch Usage_Dig_BarrelSwitch @@ -285,19 +296,24 @@ static const __u8 fixed_rdesc_vendor[] = { UnitExponent(-1) // Note: reported logical range differs // from the pen report ID for x and y - LogicalRange_i16(0, 32000) - PhysicalRange_i16(0, 160) + LogicalMinimum_i16(0) + LogicalMaximum_i16(32000) + PhysicalMinimum_i16(0) + PhysicalMaximum_i16(160) // Bytes 2/3 in report Usage_GD_X Input(Var|Abs) - LogicalRange_i16(0, 20000) - PhysicalRange_i16(0, 100) + LogicalMinimum_i16(0) + LogicalMaximum_i16(20000) + PhysicalMinimum_i16(0) + PhysicalMaximum_i16(100) // Bytes 4/5 in report Usage_GD_Y Input(Var|Abs) ) // Bytes 6/7 in report - LogicalRange_i16(0, 8192) + LogicalMinimum_i16(0) + LogicalMaximum_i16(8192) Usage_Dig_TipPressure Input(Var|Abs) ) @@ -307,7 +323,8 @@ static const __u8 fixed_rdesc_vendor[] = { CollectionApplication( // Byte 0 ReportId(PAD_REPORT_ID) - LogicalRange_i8(0, 1) + LogicalMinimum_i8(0) + LogicalMaximum_i8(1) UsagePage_Digitizers Usage_Dig_TabletFunctionKeys CollectionPhysical( @@ -327,8 +344,10 @@ static const __u8 fixed_rdesc_vendor[] = { Input(Var|Abs) // Byte 4 is the button state UsagePage_Button - UsageRange_i8(0x01, 0x6) - LogicalRange_i8(0x0, 0x1) + UsageMinimum_i8(0x1) + UsageMaximum_i8(0x6) + LogicalMinimum_i8(0x0) + LogicalMaximum_i8(0x1) ReportCount(6) ReportSize(1) Input(Var|Abs) @@ -337,7 +356,8 @@ static const __u8 fixed_rdesc_vendor[] = { // Byte 5 is the wheel UsagePage_GenericDesktop Usage_GD_Wheel - LogicalRange_i8(-1, 1) + LogicalMinimum_i8(-1) + LogicalMaximum_i8(1) ReportCount(1) ReportSize(8) Input(Var|Rel) diff --git a/drivers/hid/bpf/progs/hid_report_helpers.h b/drivers/hid/bpf/progs/hid_report_helpers.h index 0aa1df438eebac72a64cc3fa24aa2fd28b952d1d..9b2a48e4a311b39ca20e7d9819beef8fb70315a6 100644 --- a/drivers/hid/bpf/progs/hid_report_helpers.h +++ b/drivers/hid/bpf/progs/hid_report_helpers.h @@ -52,7 +52,8 @@ * Usage_GD_Keyboard * CollectionApplication( ← Open the collection * ReportId(3) - * LogicalRange_i8(0, 1) + * LogicalMinimum_i8(0) + * LogicalMaximum_i8(1) * // other fields * ) ← End EndCollection * @@ -74,26 +75,43 @@ #define Arr 0x0 #define Abs 0x0 #define Rel 0x4 +#define Null 0x40 +#define Buff 0x0100 /* Use like this: Input(Var|Abs) */ #define Input(i_) 0x081, i8(i_), #define Output(i_) 0x091, i8(i_), #define Feature(i_) 0x0b1, i8(i_), +#define Input_i16(i_) 0x082, LE16(i_), +#define Output_i16(i_) 0x092, LE16(i_), +#define Feature_i16(i_) 0x0b2, LE16(i_), + #define ReportId(id_) 0x85, i8(id_), #define ReportSize(sz_) 0x75, i8(sz_), #define ReportCount(cnt_) 0x95, i8(cnt_), -#define LogicalRange_i8(min_, max_) 0x15, i8(min_), 0x25, i8(max_), -#define LogicalRange_i16(min_, max_) 0x16, LE16(min_), 0x26, LE16(max_), -#define LogicalRange_i32(min_, max_) 0x17, LE32(min_), 0x27, LE32(max_), +#define LogicalMinimum_i8(min_) 0x15, i8(min_), +#define LogicalMinimum_i16(min_) 0x16, LE16(min_), +#define LogicalMinimum_i32(min_) 0x17, LE32(min_), + +#define LogicalMaximum_i8(max_) 0x25, i8(max_), +#define LogicalMaximum_i16(max_) 0x26, LE16(max_), +#define LogicalMaximum_i32(max_) 0x27, LE32(max_), + +#define PhysicalMinimum_i8(min_) 0x35, i8(min_), +#define PhysicalMinimum_i16(min_) 0x36, LE16(min_), +#define PhysicalMinimum_i32(min_) 0x37, LE32(min_), + +#define PhysicalMaximum_i8(max_) 0x45, i8(max_), +#define PhysicalMaximum_i16(max_) 0x46, LE16(max_), +#define PhysicalMaximum_i32(max_) 0x47, LE32(max_), -#define PhysicalRange_i8(min_, max_) 0x35, i8(min_), 0x45, i8(max_), -#define PhysicalRange_i16(min_, max_) 0x36, LE16(min_), 0x46, LE16(max_), -#define PhysicalRange_i32(min_, max_) 0x37, LE32(min_), 0x47, LE32(max_), +#define UsageMinimum_i8(min_) 0x19, i8(min_), +#define UsageMinimum_i16(min_) 0x1a, LE16(min_), -#define UsageRange_i8(min_, max_) 0x19, i8(min_), 0x29, i8(max_), -#define UsageRange_i16(min_, max_) 0x1a, LE16(min_), 0x2a, LE16(max_), +#define UsageMaximum_i8(max_) 0x29, i8(max_), +#define UsageMaximum_i16(max_) 0x2a, LE16(max_), #define UsagePage_i8(p_) 0x05, i8(p_), #define UsagePage_i16(p_) 0x06, LE16(p_),