* [PATCH] HID: i2c-hid: patch Lenovo Yoga Slim 7x Keyboard rdesc
@ 2025-10-09 5:44 Lauri Tirkkonen
2025-10-09 7:38 ` Benjamin Tissoires
0 siblings, 1 reply; 5+ messages in thread
From: Lauri Tirkkonen @ 2025-10-09 5:44 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires, linux-input, linux-kernel
The keyboard of this device has the following in its report description
for Usage (Keyboard) in Collection (Application):
# 0x15, 0x00, // Logical Minimum (0) 52
# 0x25, 0x65, // Logical Maximum (101) 54
# 0x05, 0x07, // Usage Page (Keyboard) 56
# 0x19, 0x00, // Usage Minimum (0) 58
# 0x29, 0xdd, // Usage Maximum (221) 60
# 0x81, 0x00, // Input (Data,Arr,Abs) 62
Since the Usage Min/Max range exceeds the Logical Min/Max range,
keypresses outside the Logical range are not recognized. This includes,
for example, the Japanese language keyboard variant's keys for |, _ and
\.
Patch the report description to make the Logical range match the Usage
range, fixing the interpretation of keypresses above 101 on this device.
Signed-off-by: Lauri Tirkkonen <lauri@hacktheplanet.fi>
---
drivers/hid/hid-ids.h | 1 +
drivers/hid/i2c-hid/i2c-hid-core.c | 25 +++++++++++++++++++++++++
2 files changed, 26 insertions(+)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 5721b8414bbd..bbb932145d2c 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -715,6 +715,7 @@
#define USB_DEVICE_ID_ITE_LENOVO_YOGA2 0x8350
#define I2C_DEVICE_ID_ITE_LENOVO_LEGION_Y720 0x837a
#define USB_DEVICE_ID_ITE_LENOVO_YOGA900 0x8396
+#define I2C_DEVICE_ID_ITE_LENOVO_YOGA_SLIM_7X 0x8987
#define USB_DEVICE_ID_ITE8595 0x8595
#define USB_DEVICE_ID_ITE_MEDION_E1239T 0xce50
diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
index 63f46a2e5788..d78bd97ec24e 100644
--- a/drivers/hid/i2c-hid/i2c-hid-core.c
+++ b/drivers/hid/i2c-hid/i2c-hid-core.c
@@ -740,6 +740,26 @@ static int i2c_hid_raw_request(struct hid_device *hid, unsigned char reportnum,
}
}
+static void patch_lenovo_yoga_slim7x_keyboard_rdesc(struct i2c_hid *ihid,
+ char *rdesc,
+ unsigned int rsize)
+{
+ if (!(rsize == 0xb0 &&
+ rdesc[0x34] == 0x15 && rdesc[0x35] == 0x00 && // Logical Minimum (0)
+ rdesc[0x36] == 0x25 && rdesc[0x37] == 0x65 && // Logical Maximum (101)
+ rdesc[0x38] == 0x05 && rdesc[0x39] == 0x07 && // Usage Page (Keyboard)
+ rdesc[0x3a] == 0x19 && rdesc[0x3b] == 0x00 && // Usage Minimum (0)
+ rdesc[0x3c] == 0x29 && rdesc[0x3d] == 0xdd)) // Usage Maximum (221)
+ return;
+
+ u8 logical_max = rdesc[0x37];
+ u8 usage_max = rdesc[0x3d];
+
+ rdesc[0x37] = usage_max;
+ i2c_hid_dbg(ihid, "%s: patched logical max from %u to %u\n", __func__,
+ logical_max, usage_max);
+}
+
static int i2c_hid_parse(struct hid_device *hid)
{
struct i2c_client *client = hid->driver_data;
@@ -793,6 +813,11 @@ static int i2c_hid_parse(struct hid_device *hid)
}
}
+ if (ihid->hid->vendor == USB_VENDOR_ID_ITE &&
+ ihid->hid->product == I2C_DEVICE_ID_ITE_LENOVO_YOGA_SLIM_7X) {
+ patch_lenovo_yoga_slim7x_keyboard_rdesc(ihid, rdesc, rsize);
+ }
+
i2c_hid_dbg(ihid, "Report Descriptor: %*ph\n", rsize, rdesc);
ret = hid_parse_report(hid, rdesc, rsize);
--
2.51.0
--
Lauri Tirkkonen | lotheac @ IRCnet
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] HID: i2c-hid: patch Lenovo Yoga Slim 7x Keyboard rdesc
2025-10-09 5:44 [PATCH] HID: i2c-hid: patch Lenovo Yoga Slim 7x Keyboard rdesc Lauri Tirkkonen
@ 2025-10-09 7:38 ` Benjamin Tissoires
2025-10-09 8:04 ` Lauri Tirkkonen
0 siblings, 1 reply; 5+ messages in thread
From: Benjamin Tissoires @ 2025-10-09 7:38 UTC (permalink / raw)
To: Lauri Tirkkonen; +Cc: Jiri Kosina, linux-input, linux-kernel
On Oct 09 2025, Lauri Tirkkonen wrote:
> The keyboard of this device has the following in its report description
> for Usage (Keyboard) in Collection (Application):
>
> # 0x15, 0x00, // Logical Minimum (0) 52
> # 0x25, 0x65, // Logical Maximum (101) 54
> # 0x05, 0x07, // Usage Page (Keyboard) 56
> # 0x19, 0x00, // Usage Minimum (0) 58
> # 0x29, 0xdd, // Usage Maximum (221) 60
> # 0x81, 0x00, // Input (Data,Arr,Abs) 62
>
> Since the Usage Min/Max range exceeds the Logical Min/Max range,
> keypresses outside the Logical range are not recognized. This includes,
> for example, the Japanese language keyboard variant's keys for |, _ and
> \.
>
> Patch the report description to make the Logical range match the Usage
> range, fixing the interpretation of keypresses above 101 on this device.
>
> Signed-off-by: Lauri Tirkkonen <lauri@hacktheplanet.fi>
> ---
> drivers/hid/hid-ids.h | 1 +
> drivers/hid/i2c-hid/i2c-hid-core.c | 25 +++++++++++++++++++++++++
> 2 files changed, 26 insertions(+)
>
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index 5721b8414bbd..bbb932145d2c 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -715,6 +715,7 @@
> #define USB_DEVICE_ID_ITE_LENOVO_YOGA2 0x8350
> #define I2C_DEVICE_ID_ITE_LENOVO_LEGION_Y720 0x837a
> #define USB_DEVICE_ID_ITE_LENOVO_YOGA900 0x8396
> +#define I2C_DEVICE_ID_ITE_LENOVO_YOGA_SLIM_7X 0x8987
> #define USB_DEVICE_ID_ITE8595 0x8595
> #define USB_DEVICE_ID_ITE_MEDION_E1239T 0xce50
>
> diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
> index 63f46a2e5788..d78bd97ec24e 100644
> --- a/drivers/hid/i2c-hid/i2c-hid-core.c
> +++ b/drivers/hid/i2c-hid/i2c-hid-core.c
Why patching i2c-hid-core when this is clearly a logical bug, not a
transport (I2C) bug?
I would rather see this fixup in hid-lenovo.c along with the other
lenovo fixes.
Cheers,
Benjamin
> @@ -740,6 +740,26 @@ static int i2c_hid_raw_request(struct hid_device *hid, unsigned char reportnum,
> }
> }
>
> +static void patch_lenovo_yoga_slim7x_keyboard_rdesc(struct i2c_hid *ihid,
> + char *rdesc,
> + unsigned int rsize)
> +{
> + if (!(rsize == 0xb0 &&
> + rdesc[0x34] == 0x15 && rdesc[0x35] == 0x00 && // Logical Minimum (0)
> + rdesc[0x36] == 0x25 && rdesc[0x37] == 0x65 && // Logical Maximum (101)
> + rdesc[0x38] == 0x05 && rdesc[0x39] == 0x07 && // Usage Page (Keyboard)
> + rdesc[0x3a] == 0x19 && rdesc[0x3b] == 0x00 && // Usage Minimum (0)
> + rdesc[0x3c] == 0x29 && rdesc[0x3d] == 0xdd)) // Usage Maximum (221)
> + return;
> +
> + u8 logical_max = rdesc[0x37];
> + u8 usage_max = rdesc[0x3d];
> +
> + rdesc[0x37] = usage_max;
> + i2c_hid_dbg(ihid, "%s: patched logical max from %u to %u\n", __func__,
> + logical_max, usage_max);
> +}
> +
> static int i2c_hid_parse(struct hid_device *hid)
> {
> struct i2c_client *client = hid->driver_data;
> @@ -793,6 +813,11 @@ static int i2c_hid_parse(struct hid_device *hid)
> }
> }
>
> + if (ihid->hid->vendor == USB_VENDOR_ID_ITE &&
> + ihid->hid->product == I2C_DEVICE_ID_ITE_LENOVO_YOGA_SLIM_7X) {
> + patch_lenovo_yoga_slim7x_keyboard_rdesc(ihid, rdesc, rsize);
> + }
> +
> i2c_hid_dbg(ihid, "Report Descriptor: %*ph\n", rsize, rdesc);
>
> ret = hid_parse_report(hid, rdesc, rsize);
> --
> 2.51.0
>
> --
> Lauri Tirkkonen | lotheac @ IRCnet
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] HID: i2c-hid: patch Lenovo Yoga Slim 7x Keyboard rdesc
2025-10-09 7:38 ` Benjamin Tissoires
@ 2025-10-09 8:04 ` Lauri Tirkkonen
2025-10-09 8:29 ` Benjamin Tissoires
0 siblings, 1 reply; 5+ messages in thread
From: Lauri Tirkkonen @ 2025-10-09 8:04 UTC (permalink / raw)
To: Benjamin Tissoires; +Cc: Jiri Kosina, linux-input, linux-kernel
Hi Benjamin,
On Thu, Oct 09 2025 09:38:50 +0200, Benjamin Tissoires wrote:
> > diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
> > index 63f46a2e5788..d78bd97ec24e 100644
> > --- a/drivers/hid/i2c-hid/i2c-hid-core.c
> > +++ b/drivers/hid/i2c-hid/i2c-hid-core.c
>
> Why patching i2c-hid-core when this is clearly a logical bug, not a
> transport (I2C) bug?
>
> I would rather see this fixup in hid-lenovo.c along with the other
> lenovo fixes.
I'm not exactly familiar with HID; please bear with me :) If
i2c-hid-core is not the correct place for this kind of thing, I can move
it, but I'm going to need some guidance on where the correct place is.
This device uses hid-over-i2c, not hid-lenovo; I've got
CONFIG_HID_LENOVO=m but the module is not even loaded. I don't see how
putting the fixup in a module that does not attach to the device could
work. So where should it go?
[ 796.926931] input: hid-over-i2c 048D:8987 Keyboard as /devices/platform/soc@0/bc0000.geniqup/b80000.i2c/i2c-1/1-003a/0018:048D:8987.000F/input/input36
As a side note: apparently there is at least one other device in
existence with a similar error in the report descriptor, which works
fine on Windows:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=652f3d00de523a17b0cebe7b90debccf13aa8c31
--
Lauri Tirkkonen | lotheac @ IRCnet
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] HID: i2c-hid: patch Lenovo Yoga Slim 7x Keyboard rdesc
2025-10-09 8:04 ` Lauri Tirkkonen
@ 2025-10-09 8:29 ` Benjamin Tissoires
2025-10-10 3:40 ` Lauri Tirkkonen
0 siblings, 1 reply; 5+ messages in thread
From: Benjamin Tissoires @ 2025-10-09 8:29 UTC (permalink / raw)
To: Lauri Tirkkonen; +Cc: Jiri Kosina, linux-input, linux-kernel
On Oct 09 2025, Lauri Tirkkonen wrote:
> Hi Benjamin,
>
> On Thu, Oct 09 2025 09:38:50 +0200, Benjamin Tissoires wrote:
> > > diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
> > > index 63f46a2e5788..d78bd97ec24e 100644
> > > --- a/drivers/hid/i2c-hid/i2c-hid-core.c
> > > +++ b/drivers/hid/i2c-hid/i2c-hid-core.c
> >
> > Why patching i2c-hid-core when this is clearly a logical bug, not a
> > transport (I2C) bug?
> >
> > I would rather see this fixup in hid-lenovo.c along with the other
> > lenovo fixes.
>
> I'm not exactly familiar with HID; please bear with me :) If
> i2c-hid-core is not the correct place for this kind of thing, I can move
> it, but I'm going to need some guidance on where the correct place is.
>
> This device uses hid-over-i2c, not hid-lenovo; I've got
> CONFIG_HID_LENOVO=m but the module is not even loaded. I don't see how
> putting the fixup in a module that does not attach to the device could
> work. So where should it go?
Well, the transport layer is i2c-hid, but the logical implementation is
in hid-generic which leverages the hid core default implementation.
In your case, you need to tell hid-lenovo to handle the device so we
stick to nice and tidy approach with each HID driver handling it's own
business.
Adding a line like the following will bind the keyboard part of the
device to hid-lenovo in lenovo_devices[]:
{ HID_DEVICE(BUS_I2C, HID_GROUP_GENERIC,
USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_YOGA_SLIM_7X) },
If you don't use hid-multitouch on the same device you need a
HID_I2C_DEVICE() macro instead.
Once this is in, hid-lenovo.ko will bind to the device, and then we can
start fixing the report descriptor.
>
> [ 796.926931] input: hid-over-i2c 048D:8987 Keyboard as /devices/platform/soc@0/bc0000.geniqup/b80000.i2c/i2c-1/1-003a/0018:048D:8987.000F/input/input36
>
> As a side note: apparently there is at least one other device in
> existence with a similar error in the report descriptor, which works
> fine on Windows:
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=652f3d00de523a17b0cebe7b90debccf13aa8c31
Well, Windows is known for horrible hacks in their own generic layer,
but trying to mimmic them is sometimes harder than it looks :(
Especially because we also handle non Windows devices, and we might
break them while mimmicing Windows while our HID implementation is
currently rather "clean".
Cheers,
Benjamin
>
> --
> Lauri Tirkkonen | lotheac @ IRCnet
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] HID: i2c-hid: patch Lenovo Yoga Slim 7x Keyboard rdesc
2025-10-09 8:29 ` Benjamin Tissoires
@ 2025-10-10 3:40 ` Lauri Tirkkonen
0 siblings, 0 replies; 5+ messages in thread
From: Lauri Tirkkonen @ 2025-10-10 3:40 UTC (permalink / raw)
To: Benjamin Tissoires; +Cc: Jiri Kosina, linux-input, linux-kernel
On Thu, Oct 09 2025 10:29:19 +0200, Benjamin Tissoires wrote:
> On Oct 09 2025, Lauri Tirkkonen wrote:
> > This device uses hid-over-i2c, not hid-lenovo; I've got
> > CONFIG_HID_LENOVO=m but the module is not even loaded. I don't see how
> > putting the fixup in a module that does not attach to the device could
> > work. So where should it go?
>
> Well, the transport layer is i2c-hid, but the logical implementation is
> in hid-generic which leverages the hid core default implementation.
>
> In your case, you need to tell hid-lenovo to handle the device so we
> stick to nice and tidy approach with each HID driver handling it's own
> business.
>
> Adding a line like the following will bind the keyboard part of the
> device to hid-lenovo in lenovo_devices[]:
> { HID_DEVICE(BUS_I2C, HID_GROUP_GENERIC,
> USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_YOGA_SLIM_7X) },
> If you don't use hid-multitouch on the same device you need a
> HID_I2C_DEVICE() macro instead.
Thank you for the explanation; that makes sense.
This machine does have multitouch, but it's in a different product id.
However, it did not work: apparently hid-lenovo can't be loaded on this
machine because it depends on platform_profile, which returns
-EOPNOTSUPP at initialization. This is an arm64 machine with
acpi_disabled. Not sure what to do about that.
--
Lauri Tirkkonen | lotheac @ IRCnet
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-10-10 3:40 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-09 5:44 [PATCH] HID: i2c-hid: patch Lenovo Yoga Slim 7x Keyboard rdesc Lauri Tirkkonen
2025-10-09 7:38 ` Benjamin Tissoires
2025-10-09 8:04 ` Lauri Tirkkonen
2025-10-09 8:29 ` Benjamin Tissoires
2025-10-10 3:40 ` Lauri Tirkkonen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).