Replace ad-hoc heuristics with proper bridge event function dispatch:
- Function 0 (ConnectionStateChangedEvent): parse sub-device list length
to determine connect (len>0) vs disconnect (len=0)
- Function 1 (MessageEvent): fallback online detection if headset sends
a message while marked offline (handles cold-start power-on)
Remove CPL sub_id>=0x80 fallback in listener that misidentified HID++
error replies as disconnect events. Skip HID++ 1.0
set_configuration_pending_flags for CenturionReceiver (not supported).
Also adds OnboardEQ (0x0636) support, bridge multi-fragment sends,
bridge-based headset ping probe, and CLI offline display.
- Add signed int8 support to RangeValidator for HeadsetMicGain (0x0611)
- Make HeadsetSidetone version-aware: v1 uses 2-byte skip, v2+ uses
3-byte skip with 0xFF separator per protocol spec
- Fix ruff formatting in device.py, listener.py, udev_impl.py
- Update CenturionReceiver test for renamed receiver
- Add CenturionReceiver class that provides the Receiver UI interface so
the dongle appears as a parent with the headset indented underneath,
matching how Lightspeed/Unifying receivers display
- Independently probe dongle features via feature_request() on the
CenturionReceiver, separate from headset features via bridge
- Fix bridge notification dispatch: remove incorrect sub_cpl=0xFF filter
that was silently dropping all battery and other notifications
- Fix battery status decoding: charging status is at byte 2 (not byte 1)
of the CENTURION_BATTERY_SOC response
- Detect wired vs wireless by checking for CentPPBridge in discovered
features; wired headsets fall back to standalone Device
- Name the dongle "Centurion Receiver" to distinguish from the headset
- Filter unprintable dongle serial (control characters 0x14-0x1F)
- Update CLI show output with proper receiver/child hierarchy and spacing
Replace the hardcoded descriptor entry with dynamic discovery of all device
properties via the Centurion protocol. The headset name, kind, serial,
firmware, and battery are now probed at runtime — matching how the device
actually presents itself rather than relying on static data.
Key changes:
- Discover sub-device features via CentPPBridge and route requests through
the bridge automatically
- Infer device kind from feature IDs (0x06xx = headset) for both wireless
and direct USB connections
- Read device name from USB product string with protocol probe fallback
- Parse bridge error responses (sub_feat_idx=0xFF) instead of timing out
- Handle unknown HID++ error codes gracefully in base.py
- Fix firmware deduplication for Centurion parent devices
- Prefer sub-device serial/firmware over parent (non-printable) values
- Add Centurion-aware display in solaar show with parent/sub-device sections
- Support both wireless (0AF7 dongle) and direct USB (0AF8) connections
Adds support for the Logitech PRO X 2 LIGHTSPEED Gaming Headset (PID 0x0AF7)
which uses the Centurion transport protocol (report ID 0x51 on USB usage page
0xFFA0) instead of standard HID++ report IDs.
Changes:
- HID enumeration: detect Centurion devices via report descriptor parsing
(usage page 0xFFA0, report ID 0x51, 63-byte frames)
- Centurion transport: wrap/unwrap HID++ 2.0 frames in Centurion framing
for write, read, and ping operations
- Feature discovery: enumerate features individually on Centurion devices
(different response format: [remaining_count, feat_hi, feat_lo])
- Device descriptor for PRO X 2 LIGHTSPEED Gaming Headset
- New feature enum entries for Centurion-era headset features (0x06xx)
- CenturionRawRW class for write-only headset settings controlled via
raw Centurion commands reverse-engineered from HeadsetControl
- HeadsetSidetone setting (0-100 range, persisted locally)
Known limitations:
- Only sidetone control is implemented; other features need RE work
- Settings are write-only (no read-back from device)
- Headset features (0x06xx) not discoverable via IRoot; registered manually
* feat: PRO X 2 Superstrike support with click haptics, actuation point and rapid trigger config support
* feat: PRO X 2 Superstrike docs
* docs: document PRO X 2 Superstrike features, device entry, and capabilities
* fix: code review points
# Conflicts:
# lib/logitech_receiver/hidpp20_constants.py
* Fix the write_key_value for dpi_extended
I was playing with the branch from the MR and I wanted to fix the cli stuff, it now properly sets when I use:
solaar config 1 dpi_extended X 400
Should be enough
Signed-off-by: Shane Fagan <mail@shanefagan.com>
* Fix ruff style check
---------
Signed-off-by: Shane Fagan <mail@shanefagan.com>
Co-authored-by: Shane Fagan <mail@shanefagan.com>
* Skip Logitech webcams (PID 0x0800 to 0x09FF) to prevent them from locking up during hidpp checks #3145
* Skip Logitech webcams (PID 0x0800 to 0x09FF) to prevent them from locking up during hidpp checks #3145 - format comment
* Skip Logitech webcams (PID 0x0800 to 0x09FF) to prevent them from locking up during hidpp checks #3145 - format hex
* Skip Logitech webcams from hidpp checks #3145 - local constant for LOGITECH_VENDOR_ID as per code review