linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [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).