From 0dfc7a22fa31aa8af69d81d15451ba855667822a Mon Sep 17 00:00:00 2001 From: Ken Sanislo Date: Thu, 16 Apr 2026 23:18:18 -0700 Subject: [PATCH] Force FeaturesArray for Centurion devices regardless of reported protocol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Device.__init__ creates self.features as an empty dict ({}) when the reported _protocol is <2.0, reserving FeaturesArray for HID++ 2.0. The protocol floor in the protocol property only helps code paths that access the property (e.g. feature_request's `if self.protocol >= 2.0`). But __init__ reads the raw self._protocol attribute, so a wired G522 (reports 1.1) ends up with self.features = {}. When solaar show later triggers `self.features._check()` inside feature_request, the dict has no _check method → AttributeError → crashes `solaar show` for the wired G522. Fix: use FeaturesArray unconditionally when the device is Centurion. The protocol version reported by these dongles is cosmetic — all Centurion devices speak HID++ 2.0 features. --- lib/logitech_receiver/device.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/logitech_receiver/device.py b/lib/logitech_receiver/device.py index 41c25a4e..d307cdc5 100644 --- a/lib/logitech_receiver/device.py +++ b/lib/logitech_receiver/device.py @@ -222,7 +222,9 @@ class Device: self._protocol = self.descriptor.protocol if self.descriptor.protocol else None self.registers = self.descriptor.registers if self.descriptor.registers else [] - if self._protocol is not None: + # Centurion devices always use HID++ 2.0 features regardless of the + # protocol version the dongle reports (e.g. G522 reports 1.1). + if self._protocol is not None and not self.centurion: self.features = {} if self._protocol < 2.0 else hidpp20.FeaturesArray(self) else: self.features = hidpp20.FeaturesArray(self) # may be a 2.0 device; if not, it will fix itself later