[PATCH] HID: logitech-dj: forward Bolt receiver input to the dj child device

From: Grégoire Stein via B4 Relay

Date: Tue Sep 01 2026 - 12:34:29 EST


From: Grégoire Stein <greyxor@xxxxxxxxxxxxxx>

Since Bolt receivers got support in hid-logitech-dj, one detent of the
wheel on an MX Master 4 scrolls 2 to 5 times too far.

For Bolt only LOGITECH_DJ_INTERFACE_NUMBER is kept as a dj interface and
everything else is left as a generic-hid device. Interface 1 therefore
registers an input device of its own, and the paired device's reports
are never forwarded to the dj child device, which ends up receiving
nothing at all.

hid-logitech-hidpp still binds to that child and enables hi-res
scrolling through feature 0x2121. The wheel starts emitting several
ticks per detent, but hidpp_event() applies the multiplier on an input
device that never sees a report. The ticks reach userspace over the
receiver's own mouse interface, where hid-input has no resolution
multiplier and scales each one by 120:

[Logitech USB Receiver Mouse] REL_WHEEL=2 REL_WHEEL_HI_RES=240
[Logitech USB Receiver Mouse] REL_WHEEL=3 REL_WHEEL_HI_RES=360
[Logitech Wireless Mouse PID:b042] (nothing)

Interface 0 is the keyboard endpoint, interface 1 the mouse endpoint and
interface 2 carries DJ/HID++, which is the same layout as the other
HID++ receivers. Set no_dj_interfaces to 3 and drop the special case, so
interfaces 0 and 1 are claimed by the dj driver and their reports get
forwarded to the child, where the multiplier is applied.

Bolt support was tested with a keyboard, and a keyboard has no wheel
multiplier to get wrong, which is probably why this was missed.

Fixes: 022eb347ff3a ("HID: logitech: add Bolt receiver support for Logitech HID++ devices")
Signed-off-by: Grégoire Stein <greyxor@xxxxxxxxxxxxxx>
---
Tested on 7.3-rc1 with an MX Master 4 on a Bolt receiver (046d:c548).
Before the patch one detent gives REL_WHEEL 2-5 / REL_WHEEL_HI_RES
240-600 on the receiver's own mouse endpoint, and the dj child device
gets no reports at all. After it everything comes in on the child device
at 120 per detent.

checkpatch says "trailing statements should be on next line" for the
added case, it is written like the eight cases already in that switch.

I only have a mouse here. Erik, could you check that the MX Keys for
Business still works with this applied?
---
drivers/hid/hid-logitech-dj.c | 22 +++++-----------------
1 file changed, 5 insertions(+), 17 deletions(-)

diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 1d619d2345e1..5a8f63ced627 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -1907,9 +1907,6 @@ static int logi_dj_probe(struct hid_device *hdev,
* 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.
- *
- * Bolt receivers only use LOGITECH_DJ_INTERFACE_NUMBER for receiver
- * reporting. Treat all other Bolt interfaces as generic-hid devices.
*/
switch (id->driver_data) {
case recvr_type_dj: no_dj_interfaces = 3; break;
@@ -1920,23 +1917,14 @@ static int logi_dj_probe(struct hid_device *hdev,
case recvr_type_27mhz: no_dj_interfaces = 2; break;
case recvr_type_bluetooth: no_dj_interfaces = 2; break;
case recvr_type_dinovo: no_dj_interfaces = 2; break;
+ case recvr_type_bolt: no_dj_interfaces = 3; break;
}
if (hid_is_usb(hdev)) {
intf = to_usb_interface(hdev->dev.parent);
- if (intf) {
- bool generic_hid_interface;
-
- if (id->driver_data == recvr_type_bolt)
- generic_hid_interface =
- intf->altsetting->desc.bInterfaceNumber !=
- LOGITECH_DJ_INTERFACE_NUMBER;
- else
- generic_hid_interface =
- intf->altsetting->desc.bInterfaceNumber >= no_dj_interfaces;
- if (generic_hid_interface) {
- hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
- return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- }
+ if (intf && intf->altsetting->desc.bInterfaceNumber >=
+ no_dj_interfaces) {
+ hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
+ return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
}
}


---
base-commit: cee9395acd8043be0644b25c34bfa86623f2b935
change-id: 20260901-bolt-scroll-fix-0f81412fa351

Best regards,
--
Grégoire Stein <greyxor@xxxxxxxxxxxxxx>