The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH 0/1] HID: logitech: add Bolt receiver support for Logitech HID++ devices
@ 2026-07-12  0:30 Erik Håkansson
  2026-07-12  0:30 ` [PATCH 1/1] " Erik Håkansson
  0 siblings, 1 reply; 14+ messages in thread
From: Erik Håkansson @ 2026-07-12  0:30 UTC (permalink / raw)
  To: jikos, bentiss
  Cc: lains, hadess, linux-input, linux-kernel, Erik Håkansson

This patch adds Logitech Bolt receiver support for Logitech HID++
devices so Bolt-connected HID++ peripherals can expose battery
information through the kernel power_supply path with the correct device
model.

Tested with:
- Logitech MX Keys for Business via Bolt receiver

Erik Håkansson (1):
  HID: logitech: add Bolt receiver support for Logitech HID++ devices

 drivers/hid/hid-logitech-dj.c    | 10 +++++++
 drivers/hid/hid-logitech-hidpp.c | 47 ++++++++++++++++++++++++++++++--
 2 files changed, 54 insertions(+), 3 deletions(-)


base-commit: 44696aa3a489d2baf58efa61b37833f100072bee
-- 
2.55.0


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/1] HID: logitech: add Bolt receiver support for Logitech HID++ devices
  2026-07-12  0:30 [PATCH 0/1] HID: logitech: add Bolt receiver support for Logitech HID++ devices Erik Håkansson
@ 2026-07-12  0:30 ` Erik Håkansson
  2026-07-12 18:03   ` Kateřina Medvědová
  0 siblings, 1 reply; 14+ messages in thread
From: Erik Håkansson @ 2026-07-12  0:30 UTC (permalink / raw)
  To: jikos, bentiss
  Cc: lains, hadess, linux-input, linux-kernel, Erik Håkansson

Add Logitech Bolt receiver support to the Logitech HID receiver and
HID++ drivers.

Handle Bolt receiver notifications in hid-logitech-dj and add a
Bolt-specific initialization path in hid-logitech-hidpp, separate from
the existing Unifying receiver path.

This allows Bolt-connected HID++ devices to expose battery information
through the kernel power_supply path, so userspace tools can report
their battery status with the correct device model.

Tested with:
- Logitech MX Keys for Business via Bolt receiver

Signed-off-by: Erik Håkansson <erikhakan@gmail.com>
---
 drivers/hid/hid-logitech-dj.c    | 10 +++++++
 drivers/hid/hid-logitech-hidpp.c | 48 ++++++++++++++++++++++++++++++--
 2 files changed, 55 insertions(+), 3 deletions(-)

diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 9c574ab8b60b..518a9ee662b0 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -121,6 +121,7 @@ enum recvr_type {
 	recvr_type_27mhz,
 	recvr_type_bluetooth,
 	recvr_type_dinovo,
+	recvr_type_bolt,
 };
 
 struct dj_report {
@@ -1156,6 +1157,10 @@ static void logi_hidpp_recv_queue_notif(struct hid_device *hdev,
 		logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
 		workitem.reports_supported |= STD_KEYBOARD;
 		break;
+	case 0x10:
+		device_type = "Bolt";
+		logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
+		break;
 	}
 
 	/* custom receiver device (eg. powerplay) */
@@ -1894,6 +1899,7 @@ 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);
@@ -2103,6 +2109,10 @@ static const struct hid_device_id logi_dj_receivers[] = {
 	  HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
 		USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_3),
 	 .driver_data = recvr_type_gaming_hidpp_ls_1_3},
+	{ /* Logitech Bolt receiver (0xc548) */
+	  HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
+			 USB_DEVICE_ID_LOGITECH_BOLT_RECEIVER),
+	 .driver_data = recvr_type_bolt},
 	{ /* Logitech lightspeed receiver (0xc54d) */
 	  HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
 		USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_4),
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 90b0184df777..0b5d0a322ae8 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -4161,8 +4161,50 @@ static int hidpp_initialize_battery(struct hidpp_device *hidpp)
 	return ret;
 }
 
+static bool hidpp_is_bolt_child(struct hid_device *hdev)
+{
+	struct device *parent = hdev->dev.parent;
+	struct hid_device *receiver_hdev;
+
+	if (!parent)
+		return false;
+
+	receiver_hdev = to_hid_device(parent);
+	return receiver_hdev->vendor == USB_VENDOR_ID_LOGITECH &&
+	       receiver_hdev->product == USB_DEVICE_ID_LOGITECH_BOLT_RECEIVER;
+}
+
+static int hidpp_bolt_init(struct hidpp_device *hidpp)
+{
+	struct hid_device *hdev = hidpp->hid_dev;
+	char *name;
+	int ret;
+
+	ret = hidpp_serial_init(hidpp);
+	if (ret)
+		return ret;
+
+	name = hidpp_get_device_name(hidpp);
+	if (!name)
+		return -EIO;
+
+	snprintf(hdev->name, sizeof(hdev->name), "%s", name);
+	dbg_hid("HID++ Bolt: Got name: %s\n", name);
+
+	kfree(name);
+	return 0;
+}
+
+static int hidpp_receiver_init(struct hidpp_device *hidpp)
+{
+	if (hidpp_is_bolt_child(hidpp->hid_dev))
+		return hidpp_bolt_init(hidpp);
+
+	return hidpp_unifying_init(hidpp);
+}
+
 /* Get name + serial for USB and Bluetooth HID++ devices */
-static void hidpp_non_unifying_init(struct hidpp_device *hidpp)
+static void hidpp_non_receiver_init(struct hidpp_device *hidpp)
 {
 	struct hid_device *hdev = hidpp->hid_dev;
 	char *name;
@@ -4510,9 +4552,9 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
 	/* Get name + serial, store in hdev->name + hdev->uniq */
 	if (id->group == HID_GROUP_LOGITECH_DJ_DEVICE)
-		hidpp_unifying_init(hidpp);
+		hidpp_receiver_init(hidpp);
 	else
-		hidpp_non_unifying_init(hidpp);
+		hidpp_non_receiver_init(hidpp);
 
 	if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT)
 		connect_mask &= ~HID_CONNECT_HIDINPUT;

base-commit: 44696aa3a489d2baf58efa61b37833f100072bee
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/1] HID: logitech: add Bolt receiver support for Logitech HID++ devices
  2026-07-12  0:30 ` [PATCH 1/1] " Erik Håkansson
@ 2026-07-12 18:03   ` Kateřina Medvědová
  2026-07-13 20:10     ` Erik Håkansson
  2026-07-13 20:12     ` [PATCH v2 0/1] " Erik Håkansson
  0 siblings, 2 replies; 14+ messages in thread
From: Kateřina Medvědová @ 2026-07-12 18:03 UTC (permalink / raw)
  To: erikhakan; +Cc: bentiss, hadess, jikos, lains, linux-input, linux-kernel

Hello Erik,
I tested your patch on my hardware and found two issues:

1. Both keyboard and mouse inputs stop working correctly. The mouse 
becomes very sensitive and creates events that shouldn't happen 
(sometimes scrolls on its own) and the keyboard's keys are scrambled. I 
verified on my hardware that if you pass the first two of Bolt's 
interfaces (0 boot keyboard and 1 boot mouse) to the generic HID driver 
and only handle interface 2 in the DJ driver, you can keep the extra 
functionality (like battery reporting) without affecting inputs. The 
existing bInterfaceNumber >= no_dj_interfaces check never triggers for 
Bolt. no_dj_interfaces = 3, but the receiver's highest interface number 
is 2, so interfaces 0 and 1 fall through to the DJ path. Here's what 
fixed it:


if (id->driver_data == recvr_type_bolt && intf &&
     intf->altsetting->desc.bInterfaceNumber !=
				LOGITECH_DJ_INTERFACE_NUMBER) {
	hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
	return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
}


2. Bolt devices stay behind after unpairing in userspace (using Solaar). 
The existing driver code doesn't handle Bolt's unpair events so devices 
stay visible after unpairing. Here's how I handled it:

if (djrcv_dev->type == recvr_type_bolt &&
     hidpp_report->report_id == REPORT_ID_HIDPP_SHORT &&
     hidpp_report->sub_id == REPORT_TYPE_NOTIF_DEVICE_UNPAIRED) {
	struct dj_workitem workitem = {
		.device_index = device_index,
		.type = WORKITEM_TYPE_UNPAIRED,
	};

	kfifo_in(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem));
	schedule_work(&djrcv_dev->work);
	spin_unlock_irqrestore(&djrcv_dev->lock, flags);
	return false;
}

Hardware tested:
- Logi Bolt receiver (046d:c548)
- Logi POP Icon Keys
- Logi Lift Vertical
- Logi K650

Happy to do more testing.

Regards,
Kateřina Medvědová

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/1] HID: logitech: add Bolt receiver support for Logitech HID++ devices
  2026-07-12 18:03   ` Kateřina Medvědová
@ 2026-07-13 20:10     ` Erik Håkansson
  2026-07-13 20:12     ` [PATCH v2 0/1] " Erik Håkansson
  1 sibling, 0 replies; 14+ messages in thread
From: Erik Håkansson @ 2026-07-13 20:10 UTC (permalink / raw)
  To: k8ie; +Cc: jikos, bentiss, lains, hadess, linux-input, linux-kernel

Hi,

Thank you for testing this.

I could not reproduce issue 1 locally with my MX Keys for Business, but
I applied your fix since it also works on my hardware. Either the
different keyboard models behave differently, or something differs
between our setups. I folded it into the existing interface handling to
keep the code smaller.

I also noticed that my older Lightspeed receiver exposes interfaces 0
and 1 as boot keyboard and mouse interfaces too, while only interfaces
>= 3 are treated as generic HID. So Bolt appears to need different
interface handling from the existing Lightspeed receiver path.

Issue 2 was easy to reproduce, and I applied your fix more or less
verbatim.

I will send a v2 patch shortly. I would be very grateful if you could
test it again.

Regards,
Erik

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2 0/1] HID: logitech: add Bolt receiver support for Logitech HID++ devices
  2026-07-12 18:03   ` Kateřina Medvědová
  2026-07-13 20:10     ` Erik Håkansson
@ 2026-07-13 20:12     ` Erik Håkansson
  2026-07-13 20:12       ` [PATCH v2 1/1] " Erik Håkansson
  1 sibling, 1 reply; 14+ messages in thread
From: Erik Håkansson @ 2026-07-13 20:12 UTC (permalink / raw)
  To: jikos, bentiss
  Cc: lains, hadess, k8ie, linux-input, linux-kernel,
	Erik Håkansson

This patch adds Logitech Bolt receiver support for Logitech HID++
devices so Bolt-connected HID++ peripherals can expose battery
information through the kernel power_supply path with the correct device
model.

Changes in v2:
- Handle only the Bolt receiver/control interface in hid-logitech-dj and
  leave the other Bolt receiver interfaces to generic HID handling.
- Handle Bolt HID++ unpair notifications so child HID devices are removed
  after unpairing.

Thanks to Kateřina Medvědová for testing v1 on additional Bolt hardware
and identifying that Bolt interfaces 0 and 1 must remain handled by the
generic HID path, and that Bolt unpair notifications need explicit
handling.

Reported by Kateřina Medvědová.

Tested with:
- Logitech MX Keys for Business via Bolt receiver

Erik Håkansson (1):
  HID: logitech: add Bolt receiver support for Logitech HID++ devices

 drivers/hid/hid-logitech-dj.c    | 48 +++++++++++++++++++++++++++++---
 drivers/hid/hid-logitech-hidpp.c | 48 ++++++++++++++++++++++++++++++--
 2 files changed, 89 insertions(+), 7 deletions(-)


base-commit: 44696aa3a489d2baf58efa61b37833f100072bee
-- 
2.55.0


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2 1/1] HID: logitech: add Bolt receiver support for Logitech HID++ devices
  2026-07-13 20:12     ` [PATCH v2 0/1] " Erik Håkansson
@ 2026-07-13 20:12       ` Erik Håkansson
  2026-07-13 21:09         ` Kateřina Medvědová
  2026-07-30  8:36         ` Bastien Nocera
  0 siblings, 2 replies; 14+ messages in thread
From: Erik Håkansson @ 2026-07-13 20:12 UTC (permalink / raw)
  To: jikos, bentiss
  Cc: lains, hadess, k8ie, linux-input, linux-kernel,
	Erik Håkansson

Add Logitech Bolt receiver support to the Logitech HID receiver and
HID++ drivers.

Handle Bolt receiver notifications in hid-logitech-dj and add a
Bolt-specific initialization path in hid-logitech-hidpp, separate from
the existing Unifying receiver path.

This allows Bolt-connected HID++ devices to expose battery information
through the kernel power_supply path, so userspace tools can report
their battery status with the correct device model.

Tested with:
- Logitech MX Keys for Business via Bolt receiver

Reported-by: Kateřina Medvědová <k8ie@mcld.eu>
Link: https://lore.kernel.org/linux-input/345f7347-30a8-4568-a7a6-c70f54a52a8d@mcld.eu/
Signed-off-by: Erik Håkansson <erikhakan@gmail.com>
---
Changes in v2:
- Handle only the Bolt receiver/control interface in hid-logitech-dj and
  leave the other Bolt receiver interfaces to generic HID handling.
- Handle Bolt HID++ unpair notifications so child HID devices are removed
  after unpairing.

 drivers/hid/hid-logitech-dj.c    | 48 +++++++++++++++++++++++++++++---
 drivers/hid/hid-logitech-hidpp.c | 48 ++++++++++++++++++++++++++++++--
 2 files changed, 89 insertions(+), 7 deletions(-)

diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 9c574ab8b60b..571d5caa5bb5 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -121,6 +121,7 @@ enum recvr_type {
 	recvr_type_27mhz,
 	recvr_type_bluetooth,
 	recvr_type_dinovo,
+	recvr_type_bolt,
 };
 
 struct dj_report {
@@ -1156,6 +1157,10 @@ static void logi_hidpp_recv_queue_notif(struct hid_device *hdev,
 		logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
 		workitem.reports_supported |= STD_KEYBOARD;
 		break;
+	case 0x10:
+		device_type = "Bolt";
+		logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
+		break;
 	}
 
 	/* custom receiver device (eg. powerplay) */
@@ -1745,6 +1750,24 @@ static int logi_dj_hidpp_event(struct hid_device *hdev,
 
 	dj_dev = djrcv_dev->paired_dj_devices[device_index];
 
+	/*
+	 * Bolt receivers send explicit unpair notifications as HID++ events;
+	 * queue device removal when we receive one.
+	 */
+	if (djrcv_dev->type == recvr_type_bolt &&
+	    hidpp_report->report_id == REPORT_ID_HIDPP_SHORT &&
+	    hidpp_report->sub_id == REPORT_TYPE_NOTIF_DEVICE_UNPAIRED) {
+		struct dj_workitem workitem = {
+			.device_index = device_index,
+			.type = WORKITEM_TYPE_UNPAIRED,
+		};
+
+		kfifo_in(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem));
+		schedule_work(&djrcv_dev->work);
+		spin_unlock_irqrestore(&djrcv_dev->lock, flags);
+		return false;
+	}
+
 	/*
 	 * With 27 MHz receivers, we do not get an explicit unpair event,
 	 * remove the old device if the user has paired a *different* device.
@@ -1884,6 +1907,9 @@ 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;
@@ -1897,10 +1923,20 @@ static int logi_dj_probe(struct hid_device *hdev,
 	}
 	if (hid_is_usb(hdev)) {
 		intf = to_usb_interface(hdev->dev.parent);
-		if (intf && intf->altsetting->desc.bInterfaceNumber >=
-							no_dj_interfaces) {
-			hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
-			return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+		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);
+			}
 		}
 	}
 
@@ -2103,6 +2139,10 @@ static const struct hid_device_id logi_dj_receivers[] = {
 	  HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
 		USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_3),
 	 .driver_data = recvr_type_gaming_hidpp_ls_1_3},
+	{ /* Logitech Bolt receiver (0xc548) */
+	  HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
+			 USB_DEVICE_ID_LOGITECH_BOLT_RECEIVER),
+	 .driver_data = recvr_type_bolt},
 	{ /* Logitech lightspeed receiver (0xc54d) */
 	  HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
 		USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_4),
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 90b0184df777..0b5d0a322ae8 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -4161,8 +4161,50 @@ static int hidpp_initialize_battery(struct hidpp_device *hidpp)
 	return ret;
 }
 
+static bool hidpp_is_bolt_child(struct hid_device *hdev)
+{
+	struct device *parent = hdev->dev.parent;
+	struct hid_device *receiver_hdev;
+
+	if (!parent)
+		return false;
+
+	receiver_hdev = to_hid_device(parent);
+	return receiver_hdev->vendor == USB_VENDOR_ID_LOGITECH &&
+	       receiver_hdev->product == USB_DEVICE_ID_LOGITECH_BOLT_RECEIVER;
+}
+
+static int hidpp_bolt_init(struct hidpp_device *hidpp)
+{
+	struct hid_device *hdev = hidpp->hid_dev;
+	char *name;
+	int ret;
+
+	ret = hidpp_serial_init(hidpp);
+	if (ret)
+		return ret;
+
+	name = hidpp_get_device_name(hidpp);
+	if (!name)
+		return -EIO;
+
+	snprintf(hdev->name, sizeof(hdev->name), "%s", name);
+	dbg_hid("HID++ Bolt: Got name: %s\n", name);
+
+	kfree(name);
+	return 0;
+}
+
+static int hidpp_receiver_init(struct hidpp_device *hidpp)
+{
+	if (hidpp_is_bolt_child(hidpp->hid_dev))
+		return hidpp_bolt_init(hidpp);
+
+	return hidpp_unifying_init(hidpp);
+}
+
 /* Get name + serial for USB and Bluetooth HID++ devices */
-static void hidpp_non_unifying_init(struct hidpp_device *hidpp)
+static void hidpp_non_receiver_init(struct hidpp_device *hidpp)
 {
 	struct hid_device *hdev = hidpp->hid_dev;
 	char *name;
@@ -4510,9 +4552,9 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
 	/* Get name + serial, store in hdev->name + hdev->uniq */
 	if (id->group == HID_GROUP_LOGITECH_DJ_DEVICE)
-		hidpp_unifying_init(hidpp);
+		hidpp_receiver_init(hidpp);
 	else
-		hidpp_non_unifying_init(hidpp);
+		hidpp_non_receiver_init(hidpp);
 
 	if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT)
 		connect_mask &= ~HID_CONNECT_HIDINPUT;
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 1/1] HID: logitech: add Bolt receiver support for Logitech HID++ devices
  2026-07-13 20:12       ` [PATCH v2 1/1] " Erik Håkansson
@ 2026-07-13 21:09         ` Kateřina Medvědová
  2026-07-14  0:54           ` Erik Håkansson
  2026-07-30  8:36         ` Bastien Nocera
  1 sibling, 1 reply; 14+ messages in thread
From: Kateřina Medvědová @ 2026-07-13 21:09 UTC (permalink / raw)
  To: erikhakan; +Cc: bentiss, hadess, jikos, k8ie, lains, linux-input, linux-kernel

Hi,

I tested your V2 and both issues were resolved.

Not sure what caused issue number 1 on my system. I can try to dig 
deeper if it would help.

I have 3 Bolt receivers on hand. Two of them have much newer firmware 
(5.3.20, revision 3). The other one is on 5.0.9. Unfortunately I'm not 
sure which of them I was testing on.
AFAIK the only way to get this information is through Options+.

I'm so glad you're taking this on! I'll keep this on my system for daily 
driving, I love that the battery reporting works!

Thanks,
Kateřina Medvědová

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 1/1] HID: logitech: add Bolt receiver support for Logitech HID++ devices
  2026-07-13 21:09         ` Kateřina Medvědová
@ 2026-07-14  0:54           ` Erik Håkansson
  2026-07-14 10:32             ` Kateřina Medvědová
  0 siblings, 1 reply; 14+ messages in thread
From: Erik Håkansson @ 2026-07-14  0:54 UTC (permalink / raw)
  To: k8ie; +Cc: bentiss, hadess, jikos, lains, linux-input, linux-kernel

Hi,

Thank you very much for your help.

Unfortunately I don't have a Windows system easily accessible, so I
can't check my firmware version in Options+.
fwupdmgr says:
> Current version:    MPR05.03_B0020
so perhaps that means 5.03.20.

Let me know if anything pops up if you dig some more,
Thanks,
Erik

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 1/1] HID: logitech: add Bolt receiver support for Logitech HID++ devices
  2026-07-14  0:54           ` Erik Håkansson
@ 2026-07-14 10:32             ` Kateřina Medvědová
  2026-07-14 15:33               ` Erik Håkansson
  2026-07-30  8:38               ` Bastien Nocera
  0 siblings, 2 replies; 14+ messages in thread
From: Kateřina Medvědová @ 2026-07-14 10:32 UTC (permalink / raw)
  To: Erik Håkansson
  Cc: bentiss, hadess, jikos, lains, linux-input, linux-kernel

Hi,

Just tested V1 again with both of the receiver versions I have on hand 
and the input issues I described happen on both.

btw, thank you for pointing out that you can check the FW version in 
fwupd. This greatly simplified testing.

I do have one find -- when a device gets powered off (yanked battery, 
switch moved to the off position, switching devices), the battery stays 
in upower. Unifying also does this, disconnected devices stay. Either 
this was intentional or a bug. Either way the behavior is consistent 
with the existing code and isn't introduced by your changes. I'm just 
not sure what the correct behavior should be. Sorry if this pollutes the 
discussion, I'm completely new to the LKML.

I'm not sure what else I could try, I'll keep your V2 on my system and 
let you know if any issues pop up.

Regards,
Kate

On 7/14/26 2:54 AM, Erik Håkansson wrote:
> Hi,
> 
> Thank you very much for your help.
> 
> Unfortunately I don't have a Windows system easily accessible, so I
> can't check my firmware version in Options+.
> fwupdmgr says:
>> Current version:    MPR05.03_B0020
> so perhaps that means 5.03.20.
> 
> Let me know if anything pops up if you dig some more,
> Thanks,
> Erik


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 1/1] HID: logitech: add Bolt receiver support for Logitech HID++ devices
  2026-07-14 10:32             ` Kateřina Medvědová
@ 2026-07-14 15:33               ` Erik Håkansson
  2026-07-30  8:38               ` Bastien Nocera
  1 sibling, 0 replies; 14+ messages in thread
From: Erik Håkansson @ 2026-07-14 15:33 UTC (permalink / raw)
  To: Kateřina Medvědová
  Cc: bentiss, hadess, jikos, lains, linux-input, linux-kernel


On 7/14/26 12:32, Kateřina Medvědová wrote:
> Hi,
>
> Just tested V1 again with both of the receiver versions I have on hand 
> and the input issues I described happen on both.

I see. Then I assume it either comes down to our different keyboard 
models behaving differently, or something behaving differently in our 
setups. I use KDE Plasma on Fedora for what it's worth.

>
> btw, thank you for pointing out that you can check the FW version in 
> fwupd. This greatly simplified testing.
>
> I do have one find -- when a device gets powered off (yanked battery, 
> switch moved to the off position, switching devices), the battery 
> stays in upower. Unifying also does this, disconnected devices stay. 
> Either this was intentional or a bug. Either way the behavior is 
> consistent with the existing code and isn't introduced by your 
> changes. I'm just not sure what the correct behavior should be. Sorry 
> if this pollutes the discussion, I'm completely new to the LKML.

Good find! I suggest we leave that separately though. But as I am also 
completely new to the LKML I don't know what best practices here are. 
Let's wait for maintainers to chime in :)

>
> I'm not sure what else I could try, I'll keep your V2 on my system and 
> let you know if any issues pop up.

Great, thank you!

>
> Regards,
> Kate
>
> On 7/14/26 2:54 AM, Erik Håkansson wrote:
>> Hi,
>>
>> Thank you very much for your help.
>>
>> Unfortunately I don't have a Windows system easily accessible, so I
>> can't check my firmware version in Options+.
>> fwupdmgr says:
>>> Current version:    MPR05.03_B0020
>> so perhaps that means 5.03.20.
>>
>> Let me know if anything pops up if you dig some more,
>> Thanks,
>> Erik

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 1/1] HID: logitech: add Bolt receiver support for Logitech HID++ devices
  2026-07-13 20:12       ` [PATCH v2 1/1] " Erik Håkansson
  2026-07-13 21:09         ` Kateřina Medvědová
@ 2026-07-30  8:36         ` Bastien Nocera
  2026-08-01 23:18           ` Erik Håkansson
  1 sibling, 1 reply; 14+ messages in thread
From: Bastien Nocera @ 2026-07-30  8:36 UTC (permalink / raw)
  To: Erik Håkansson, jikos, bentiss
  Cc: lains, k8ie, linux-input, linux-kernel

Hey Eric,

On Mon, 2026-07-13 at 22:12 +0200, Erik Håkansson wrote:
> Add Logitech Bolt receiver support to the Logitech HID receiver and
> HID++ drivers.
> 
> Handle Bolt receiver notifications in hid-logitech-dj and add a
> Bolt-specific initialization path in hid-logitech-hidpp, separate from
> the existing Unifying receiver path.
> 
> This allows Bolt-connected HID++ devices to expose battery information
> through the kernel power_supply path, so userspace tools can report
> their battery status with the correct device model.
> 
> Tested with:
> - Logitech MX Keys for Business via Bolt receiver

I tested this with a Bolt receiver connected to the same M650 mouse I
used in another test earlier, and my Slim Solar+ keyboard.

Every time the mouse is turned off, I get:
kernel: logitech-hidpp-device 0003:046D:B02A.0009: hidpp_root_get_protocol_version: received protocol error 0x04
which probably shouldn't happen.

I also see the battery not going away, but that looks to be a separate
problem.

The only thing I haven't tested, and which might need fixing before we
can merge this is figuring out how quirks can be applied.

The battery reporting works because it probes the available interfaces,
and reports that.

But what about things like:
        { /* Signature M650 over Bluetooth */
          HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH,
                               HIDPP_PRODUCT_SIGNATURE_M650),
          .driver_data = HIDPP_QUIRK_HIDPP_REPROG_CONTROLS_BTNS },
which were added in:
https://patchwork.kernel.org/project/linux-input/list/?series=1121633

The recent "HID: logitech-hidpp: Add support for HID++ Multi-Platform
feature (0x4531)" doesn't work either:
https://patchwork.kernel.org/project/linux-input/list/?series=1119501

Cheers

> 
> Reported-by: Kateřina Medvědová <k8ie@mcld.eu>
> Link: https://lore.kernel.org/linux-input/345f7347-30a8-4568-a7a6-c70f54a52a8d@mcld.eu/
> Signed-off-by: Erik Håkansson <erikhakan@gmail.com>
> ---
> Changes in v2:
> - Handle only the Bolt receiver/control interface in hid-logitech-dj and
>   leave the other Bolt receiver interfaces to generic HID handling.
> - Handle Bolt HID++ unpair notifications so child HID devices are removed
>   after unpairing.
> 
>  drivers/hid/hid-logitech-dj.c    | 48 +++++++++++++++++++++++++++++---
>  drivers/hid/hid-logitech-hidpp.c | 48 ++++++++++++++++++++++++++++++--
>  2 files changed, 89 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
> index 9c574ab8b60b..571d5caa5bb5 100644
> --- a/drivers/hid/hid-logitech-dj.c
> +++ b/drivers/hid/hid-logitech-dj.c
> @@ -121,6 +121,7 @@ enum recvr_type {
>  	recvr_type_27mhz,
>  	recvr_type_bluetooth,
>  	recvr_type_dinovo,
> +	recvr_type_bolt,
>  };
>  
>  struct dj_report {
> @@ -1156,6 +1157,10 @@ static void logi_hidpp_recv_queue_notif(struct hid_device *hdev,
>  		logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
>  		workitem.reports_supported |= STD_KEYBOARD;
>  		break;
> +	case 0x10:
> +		device_type = "Bolt";
> +		logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
> +		break;
>  	}
>  
>  	/* custom receiver device (eg. powerplay) */
> @@ -1745,6 +1750,24 @@ static int logi_dj_hidpp_event(struct hid_device *hdev,
>  
>  	dj_dev = djrcv_dev->paired_dj_devices[device_index];
>  
> +	/*
> +	 * Bolt receivers send explicit unpair notifications as HID++ events;
> +	 * queue device removal when we receive one.
> +	 */
> +	if (djrcv_dev->type == recvr_type_bolt &&
> +	    hidpp_report->report_id == REPORT_ID_HIDPP_SHORT &&
> +	    hidpp_report->sub_id == REPORT_TYPE_NOTIF_DEVICE_UNPAIRED) {
> +		struct dj_workitem workitem = {
> +			.device_index = device_index,
> +			.type = WORKITEM_TYPE_UNPAIRED,
> +		};
> +
> +		kfifo_in(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem));
> +		schedule_work(&djrcv_dev->work);
> +		spin_unlock_irqrestore(&djrcv_dev->lock, flags);
> +		return false;
> +	}
> +
>  	/*
>  	 * With 27 MHz receivers, we do not get an explicit unpair event,
>  	 * remove the old device if the user has paired a *different* device.
> @@ -1884,6 +1907,9 @@ 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;
> @@ -1897,10 +1923,20 @@ static int logi_dj_probe(struct hid_device *hdev,
>  	}
>  	if (hid_is_usb(hdev)) {
>  		intf = to_usb_interface(hdev->dev.parent);
> -		if (intf && intf->altsetting->desc.bInterfaceNumber >=
> -							no_dj_interfaces) {
> -			hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
> -			return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
> +		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);
> +			}
>  		}
>  	}
>  
> @@ -2103,6 +2139,10 @@ static const struct hid_device_id logi_dj_receivers[] = {
>  	  HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
>  		USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_3),
>  	 .driver_data = recvr_type_gaming_hidpp_ls_1_3},
> +	{ /* Logitech Bolt receiver (0xc548) */
> +	  HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
> +			 USB_DEVICE_ID_LOGITECH_BOLT_RECEIVER),
> +	 .driver_data = recvr_type_bolt},
>  	{ /* Logitech lightspeed receiver (0xc54d) */
>  	  HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
>  		USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_4),
> diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
> index 90b0184df777..0b5d0a322ae8 100644
> --- a/drivers/hid/hid-logitech-hidpp.c
> +++ b/drivers/hid/hid-logitech-hidpp.c
> @@ -4161,8 +4161,50 @@ static int hidpp_initialize_battery(struct hidpp_device *hidpp)
>  	return ret;
>  }
>  
> +static bool hidpp_is_bolt_child(struct hid_device *hdev)
> +{
> +	struct device *parent = hdev->dev.parent;
> +	struct hid_device *receiver_hdev;
> +
> +	if (!parent)
> +		return false;
> +
> +	receiver_hdev = to_hid_device(parent);
> +	return receiver_hdev->vendor == USB_VENDOR_ID_LOGITECH &&
> +	       receiver_hdev->product == USB_DEVICE_ID_LOGITECH_BOLT_RECEIVER;
> +}
> +
> +static int hidpp_bolt_init(struct hidpp_device *hidpp)
> +{
> +	struct hid_device *hdev = hidpp->hid_dev;
> +	char *name;
> +	int ret;
> +
> +	ret = hidpp_serial_init(hidpp);
> +	if (ret)
> +		return ret;
> +
> +	name = hidpp_get_device_name(hidpp);
> +	if (!name)
> +		return -EIO;
> +
> +	snprintf(hdev->name, sizeof(hdev->name), "%s", name);
> +	dbg_hid("HID++ Bolt: Got name: %s\n", name);
> +
> +	kfree(name);
> +	return 0;
> +}
> +
> +static int hidpp_receiver_init(struct hidpp_device *hidpp)
> +{
> +	if (hidpp_is_bolt_child(hidpp->hid_dev))
> +		return hidpp_bolt_init(hidpp);
> +
> +	return hidpp_unifying_init(hidpp);
> +}
> +
>  /* Get name + serial for USB and Bluetooth HID++ devices */
> -static void hidpp_non_unifying_init(struct hidpp_device *hidpp)
> +static void hidpp_non_receiver_init(struct hidpp_device *hidpp)
>  {
>  	struct hid_device *hdev = hidpp->hid_dev;
>  	char *name;
> @@ -4510,9 +4552,9 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
>  
>  	/* Get name + serial, store in hdev->name + hdev->uniq */
>  	if (id->group == HID_GROUP_LOGITECH_DJ_DEVICE)
> -		hidpp_unifying_init(hidpp);
> +		hidpp_receiver_init(hidpp);
>  	else
> -		hidpp_non_unifying_init(hidpp);
> +		hidpp_non_receiver_init(hidpp);
>  
>  	if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT)
>  		connect_mask &= ~HID_CONNECT_HIDINPUT;

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 1/1] HID: logitech: add Bolt receiver support for Logitech HID++ devices
  2026-07-14 10:32             ` Kateřina Medvědová
  2026-07-14 15:33               ` Erik Håkansson
@ 2026-07-30  8:38               ` Bastien Nocera
  2026-08-01 23:25                 ` Erik Håkansson
  1 sibling, 1 reply; 14+ messages in thread
From: Bastien Nocera @ 2026-07-30  8:38 UTC (permalink / raw)
  To: Kateřina Medvědová, Erik Håkansson
  Cc: bentiss, jikos, lains, linux-input, linux-kernel

On Tue, 2026-07-14 at 12:32 +0200, Kateřina Medvědová wrote:
> Hi,
> 
> Just tested V1 again with both of the receiver versions I have on
> hand 
> and the input issues I described happen on both.
> 
> btw, thank you for pointing out that you can check the FW version in 
> fwupd. This greatly simplified testing.
> 
> I do have one find -- when a device gets powered off (yanked battery,
> switch moved to the off position, switching devices), the battery
> stays 
> in upower. Unifying also does this, disconnected devices stay.

Unifying definitely didn't use to do this, I don't know whether it's a
problem in upower or the kernel.

"udevadm monitor -k -p" correctly shows the battery switching between
POWER_SUPPLY_ONLINE=0 and POWER_SUPPLY_ONLINE=1 when turning the device
off. Not sure whether that's what it used to do.

If someone has time, please test with older versions of upower (I would
say go back to 1.90.2 and start bisecting).

>  Either
> this was intentional or a bug. Either way the behavior is consistent 
> with the existing code and isn't introduced by your changes. I'm just
> not sure what the correct behavior should be. Sorry if this pollutes
> the 
> discussion, I'm completely new to the LKML.
> 
> I'm not sure what else I could try, I'll keep your V2 on my system
> and 
> let you know if any issues pop up.
> 
> Regards,
> Kate
> 
> On 7/14/26 2:54 AM, Erik Håkansson wrote:
> > Hi,
> > 
> > Thank you very much for your help.
> > 
> > Unfortunately I don't have a Windows system easily accessible, so I
> > can't check my firmware version in Options+.
> > fwupdmgr says:
> > > Current version:    MPR05.03_B0020
> > so perhaps that means 5.03.20.
> > 
> > Let me know if anything pops up if you dig some more,
> > Thanks,
> > Erik

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 1/1] HID: logitech: add Bolt receiver support for Logitech HID++ devices
  2026-07-30  8:36         ` Bastien Nocera
@ 2026-08-01 23:18           ` Erik Håkansson
  0 siblings, 0 replies; 14+ messages in thread
From: Erik Håkansson @ 2026-08-01 23:18 UTC (permalink / raw)
  To: Bastien Nocera, jikos, bentiss; +Cc: lains, k8ie, linux-input, linux-kernel

Hi!

Thanks for the review!
I've looked into the issues a bit.

On 7/30/26 10:36, Bastien Nocera wrote:
> Hey Eric,
>
> On Mon, 2026-07-13 at 22:12 +0200, Erik Håkansson wrote:
>> Add Logitech Bolt receiver support to the Logitech HID receiver and
>> HID++ drivers.
>>
>> Handle Bolt receiver notifications in hid-logitech-dj and add a
>> Bolt-specific initialization path in hid-logitech-hidpp, separate from
>> the existing Unifying receiver path.
>>
>> This allows Bolt-connected HID++ devices to expose battery information
>> through the kernel power_supply path, so userspace tools can report
>> their battery status with the correct device model.
>>
>> Tested with:
>> - Logitech MX Keys for Business via Bolt receiver
> I tested this with a Bolt receiver connected to the same M650 mouse I
> used in another test earlier, and my Slim Solar+ keyboard.
>
> Every time the mouse is turned off, I get:
> kernel: logitech-hidpp-device 0003:046D:B02A.0009: hidpp_root_get_protocol_version: received protocol error 0x04
> which probably shouldn't happen.

I managed to reproduce this and have a fix for it locally. It turns out
Bolt sends 0x04 (HIDPP_ERROR_CONNECT_FAIL) whereas Lightspeed (the only
other device I have to test with) send out 0x09
(HIDPP_ERROR_RESOURCE_ERROR) on device disconnect. So the fix is simply
to support 0x04 as well.

>
> I also see the battery not going away, but that looks to be a separate
> problem.
>
> The only thing I haven't tested, and which might need fixing before we
> can merge this is figuring out how quirks can be applied.
>
> The battery reporting works because it probes the available interfaces,
> and reports that.
>
> But what about things like:
>          { /* Signature M650 over Bluetooth */
>            HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH,
>                                 HIDPP_PRODUCT_SIGNATURE_M650),
>            .driver_data = HIDPP_QUIRK_HIDPP_REPROG_CONTROLS_BTNS },
> which were added in:
> https://patchwork.kernel.org/project/linux-input/list/?series=1121633
>
> The recent "HID: logitech-hidpp: Add support for HID++ Multi-Platform
> feature (0x4531)" doesn't work either:
> https://patchwork.kernel.org/project/linux-input/list/?series=1119501
>
> Cheers

Regarding both the quirks and discrepancy with the bluetooth route, as
well as the Multi-platform feature, I'm still looking into that and
will hopefully have a patch ready in a few days.

Regards,
Erik

>
>> Reported-by: Kateřina Medvědová <k8ie@mcld.eu>
>> Link: https://lore.kernel.org/linux-input/345f7347-30a8-4568-a7a6-c70f54a52a8d@mcld.eu/
>> Signed-off-by: Erik Håkansson <erikhakan@gmail.com>
>> ---
>> Changes in v2:
>> - Handle only the Bolt receiver/control interface in hid-logitech-dj and
>>    leave the other Bolt receiver interfaces to generic HID handling.
>> - Handle Bolt HID++ unpair notifications so child HID devices are removed
>>    after unpairing.
>>
>>   drivers/hid/hid-logitech-dj.c    | 48 +++++++++++++++++++++++++++++---
>>   drivers/hid/hid-logitech-hidpp.c | 48 ++++++++++++++++++++++++++++++--
>>   2 files changed, 89 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
>> index 9c574ab8b60b..571d5caa5bb5 100644
>> --- a/drivers/hid/hid-logitech-dj.c
>> +++ b/drivers/hid/hid-logitech-dj.c
>> @@ -121,6 +121,7 @@ enum recvr_type {
>>   	recvr_type_27mhz,
>>   	recvr_type_bluetooth,
>>   	recvr_type_dinovo,
>> +	recvr_type_bolt,
>>   };
>>   
>>   struct dj_report {
>> @@ -1156,6 +1157,10 @@ static void logi_hidpp_recv_queue_notif(struct hid_device *hdev,
>>   		logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
>>   		workitem.reports_supported |= STD_KEYBOARD;
>>   		break;
>> +	case 0x10:
>> +		device_type = "Bolt";
>> +		logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
>> +		break;
>>   	}
>>   
>>   	/* custom receiver device (eg. powerplay) */
>> @@ -1745,6 +1750,24 @@ static int logi_dj_hidpp_event(struct hid_device *hdev,
>>   
>>   	dj_dev = djrcv_dev->paired_dj_devices[device_index];
>>   
>> +	/*
>> +	 * Bolt receivers send explicit unpair notifications as HID++ events;
>> +	 * queue device removal when we receive one.
>> +	 */
>> +	if (djrcv_dev->type == recvr_type_bolt &&
>> +	    hidpp_report->report_id == REPORT_ID_HIDPP_SHORT &&
>> +	    hidpp_report->sub_id == REPORT_TYPE_NOTIF_DEVICE_UNPAIRED) {
>> +		struct dj_workitem workitem = {
>> +			.device_index = device_index,
>> +			.type = WORKITEM_TYPE_UNPAIRED,
>> +		};
>> +
>> +		kfifo_in(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem));
>> +		schedule_work(&djrcv_dev->work);
>> +		spin_unlock_irqrestore(&djrcv_dev->lock, flags);
>> +		return false;
>> +	}
>> +
>>   	/*
>>   	 * With 27 MHz receivers, we do not get an explicit unpair event,
>>   	 * remove the old device if the user has paired a *different* device.
>> @@ -1884,6 +1907,9 @@ 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;
>> @@ -1897,10 +1923,20 @@ static int logi_dj_probe(struct hid_device *hdev,
>>   	}
>>   	if (hid_is_usb(hdev)) {
>>   		intf = to_usb_interface(hdev->dev.parent);
>> -		if (intf && intf->altsetting->desc.bInterfaceNumber >=
>> -							no_dj_interfaces) {
>> -			hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
>> -			return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
>> +		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);
>> +			}
>>   		}
>>   	}
>>   
>> @@ -2103,6 +2139,10 @@ static const struct hid_device_id logi_dj_receivers[] = {
>>   	  HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
>>   		USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_3),
>>   	 .driver_data = recvr_type_gaming_hidpp_ls_1_3},
>> +	{ /* Logitech Bolt receiver (0xc548) */
>> +	  HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
>> +			 USB_DEVICE_ID_LOGITECH_BOLT_RECEIVER),
>> +	 .driver_data = recvr_type_bolt},
>>   	{ /* Logitech lightspeed receiver (0xc54d) */
>>   	  HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
>>   		USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_4),
>> diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
>> index 90b0184df777..0b5d0a322ae8 100644
>> --- a/drivers/hid/hid-logitech-hidpp.c
>> +++ b/drivers/hid/hid-logitech-hidpp.c
>> @@ -4161,8 +4161,50 @@ static int hidpp_initialize_battery(struct hidpp_device *hidpp)
>>   	return ret;
>>   }
>>   
>> +static bool hidpp_is_bolt_child(struct hid_device *hdev)
>> +{
>> +	struct device *parent = hdev->dev.parent;
>> +	struct hid_device *receiver_hdev;
>> +
>> +	if (!parent)
>> +		return false;
>> +
>> +	receiver_hdev = to_hid_device(parent);
>> +	return receiver_hdev->vendor == USB_VENDOR_ID_LOGITECH &&
>> +	       receiver_hdev->product == USB_DEVICE_ID_LOGITECH_BOLT_RECEIVER;
>> +}
>> +
>> +static int hidpp_bolt_init(struct hidpp_device *hidpp)
>> +{
>> +	struct hid_device *hdev = hidpp->hid_dev;
>> +	char *name;
>> +	int ret;
>> +
>> +	ret = hidpp_serial_init(hidpp);
>> +	if (ret)
>> +		return ret;
>> +
>> +	name = hidpp_get_device_name(hidpp);
>> +	if (!name)
>> +		return -EIO;
>> +
>> +	snprintf(hdev->name, sizeof(hdev->name), "%s", name);
>> +	dbg_hid("HID++ Bolt: Got name: %s\n", name);
>> +
>> +	kfree(name);
>> +	return 0;
>> +}
>> +
>> +static int hidpp_receiver_init(struct hidpp_device *hidpp)
>> +{
>> +	if (hidpp_is_bolt_child(hidpp->hid_dev))
>> +		return hidpp_bolt_init(hidpp);
>> +
>> +	return hidpp_unifying_init(hidpp);
>> +}
>> +
>>   /* Get name + serial for USB and Bluetooth HID++ devices */
>> -static void hidpp_non_unifying_init(struct hidpp_device *hidpp)
>> +static void hidpp_non_receiver_init(struct hidpp_device *hidpp)
>>   {
>>   	struct hid_device *hdev = hidpp->hid_dev;
>>   	char *name;
>> @@ -4510,9 +4552,9 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
>>   
>>   	/* Get name + serial, store in hdev->name + hdev->uniq */
>>   	if (id->group == HID_GROUP_LOGITECH_DJ_DEVICE)
>> -		hidpp_unifying_init(hidpp);
>> +		hidpp_receiver_init(hidpp);
>>   	else
>> -		hidpp_non_unifying_init(hidpp);
>> +		hidpp_non_receiver_init(hidpp);
>>   
>>   	if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT)
>>   		connect_mask &= ~HID_CONNECT_HIDINPUT;

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 1/1] HID: logitech: add Bolt receiver support for Logitech HID++ devices
  2026-07-30  8:38               ` Bastien Nocera
@ 2026-08-01 23:25                 ` Erik Håkansson
  0 siblings, 0 replies; 14+ messages in thread
From: Erik Håkansson @ 2026-08-01 23:25 UTC (permalink / raw)
  To: Bastien Nocera, Kateřina Medvědová
  Cc: bentiss, jikos, lains, linux-input, linux-kernel


On 7/30/26 10:38, Bastien Nocera wrote:
> On Tue, 2026-07-14 at 12:32 +0200, Kateřina Medvědová wrote:
>> Hi,
>>
>> Just tested V1 again with both of the receiver versions I have on
>> hand
>> and the input issues I described happen on both.
>>
>> btw, thank you for pointing out that you can check the FW version in
>> fwupd. This greatly simplified testing.
>>
>> I do have one find -- when a device gets powered off (yanked battery,
>> switch moved to the off position, switching devices), the battery
>> stays
>> in upower. Unifying also does this, disconnected devices stay.
> Unifying definitely didn't use to do this, I don't know whether it's a
> problem in upower or the kernel.
>
> "udevadm monitor -k -p" correctly shows the battery switching between
> POWER_SUPPLY_ONLINE=0 and POWER_SUPPLY_ONLINE=1 when turning the device
> off. Not sure whether that's what it used to do.
>
> If someone has time, please test with older versions of upower (I would
> say go back to 1.90.2 and start bisecting).

I can confirm the behaviour you're describing from "udevadm monitor -k -p". upower changes "state: discharging" to "state: 
unknown" when disconnected while Solaar simply displays the device as 
disconnect but paired. This behaviour is the same for me for both my 
Bolt keyboard and my Lightspeed mouse. The KDE Power widget removes the 
"Discharging" prefix before the battery percentage but otherwise nothing 
changes when disconnecting for either Bolt or Lightspeed device, which I 
guess is because it's based on upower. I could have a look at this and 
try older upower and/or kernel versions, but since it seems to be 
unrelated to this patch I suggest I do it as a separate activity. 
Regards, Erik

>
>>   Either
>> this was intentional or a bug. Either way the behavior is consistent
>> with the existing code and isn't introduced by your changes. I'm just
>> not sure what the correct behavior should be. Sorry if this pollutes
>> the
>> discussion, I'm completely new to the LKML.
>>
>> I'm not sure what else I could try, I'll keep your V2 on my system
>> and
>> let you know if any issues pop up.
>>
>> Regards,
>> Kate
>>
>> On 7/14/26 2:54 AM, Erik Håkansson wrote:
>>> Hi,
>>>
>>> Thank you very much for your help.
>>>
>>> Unfortunately I don't have a Windows system easily accessible, so I
>>> can't check my firmware version in Options+.
>>> fwupdmgr says:
>>>> Current version:    MPR05.03_B0020
>>> so perhaps that means 5.03.20.
>>>
>>> Let me know if anything pops up if you dig some more,
>>> Thanks,
>>> Erik

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2026-08-01 23:25 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-12  0:30 [PATCH 0/1] HID: logitech: add Bolt receiver support for Logitech HID++ devices Erik Håkansson
2026-07-12  0:30 ` [PATCH 1/1] " Erik Håkansson
2026-07-12 18:03   ` Kateřina Medvědová
2026-07-13 20:10     ` Erik Håkansson
2026-07-13 20:12     ` [PATCH v2 0/1] " Erik Håkansson
2026-07-13 20:12       ` [PATCH v2 1/1] " Erik Håkansson
2026-07-13 21:09         ` Kateřina Medvědová
2026-07-14  0:54           ` Erik Håkansson
2026-07-14 10:32             ` Kateřina Medvědová
2026-07-14 15:33               ` Erik Håkansson
2026-07-30  8:38               ` Bastien Nocera
2026-08-01 23:25                 ` Erik Håkansson
2026-07-30  8:36         ` Bastien Nocera
2026-08-01 23:18           ` Erik Håkansson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox