From a5d12f9039b116f8410ff17ff92d325f43cd260a Mon Sep 17 00:00:00 2001 From: Ken Sanislo Date: Fri, 15 May 2026 21:45:04 -0700 Subject: [PATCH] device: use full live name for direct-USB codename MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a receiver-paired mouse/keyboard is plugged in directly over USB, it has no receiver to supply a codename. If it also lacks the DEVICE_FRIENDLY_NAME feature (0x0007), the codename property fell back to name.split(" ")[0] — truncating a good name like "G502 X PLUS" to "G502" at the first space. Use the full live device name instead, only dropping a leading "Logitech" word. The live name is always accurate to the current connection — unlike a persisted copy, which can go stale for devices that report mode-variant names (e.g. a headset's "- Wireless Mode" vs "- Wired Mode"). This matches what the centurion branch already does. --- lib/logitech_receiver/device.py | 11 +++++++---- tests/logitech_receiver/test_device.py | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/lib/logitech_receiver/device.py b/lib/logitech_receiver/device.py index 28b67cab..b2db2feb 100644 --- a/lib/logitech_receiver/device.py +++ b/lib/logitech_receiver/device.py @@ -252,11 +252,14 @@ class Device: if not self.centurion: self._codename = _hidpp20.get_friendly_name(self) if not self._codename and self.name: - if self.centurion: - self._codename = self.name + # Use the full live name; only drop a leading "Logitech". + # Truncating at the first space mangled good names like + # "G502 X PLUS" (direct USB connection, no friendly name). + names = self.name.split(" ") + if not self.centurion and len(names) > 1 and names[0] == "Logitech": + self._codename = " ".join(names[1:]) else: - names = self.name.split(" ") - self._codename = names[1 if len(names) > 1 and names[0] == "Logitech" else 0] + self._codename = self.name if not self._codename and self.receiver: codename = self.receiver.device_codename(self.number) if codename: diff --git a/tests/logitech_receiver/test_device.py b/tests/logitech_receiver/test_device.py index d7ae487f..9836d27e 100644 --- a/tests/logitech_receiver/test_device.py +++ b/tests/logitech_receiver/test_device.py @@ -130,6 +130,23 @@ def test_device_name(device_info, responses, expected_codename, expected_name, e assert test_device.kind == expected_kind +def test_codename_uses_full_name(): + """A direct-connected HID++ 2.0 device with no friendly name uses its full + live name as the codename instead of truncating it at the first space.""" + test_device = device.create_device(LowLevelInterfaceFake(fake_hidpp.r_empty), di_CCCC) + test_device._protocol = 2.0 + test_device.online = True + + test_device._codename = None + test_device._name = "G502 X PLUS" + assert test_device.codename == "G502 X PLUS" + + # a leading "Logitech" is still dropped + test_device._codename = None + test_device._name = "Logitech MX Master 3" + assert test_device.codename == "MX Master 3" + + @pytest.mark.parametrize( "device_info, responses, handle, _name, _codename, number, protocol, registers", zip(