feat(hid): recognise Lightspeed nano receivers (G-series, e.g. G305)#388
feat(hid): recognise Lightspeed nano receivers (G-series, e.g. G305)#388kiwimaker wants to merge 1 commit into
Conversation
Logitech Lightspeed nano receivers (e.g. the one bundled with the G305)
were dropped by receiver::detect(), which only matched Bolt and Unifying
receivers, so a mouse paired to one never surfaced in the inventory.
A Lightspeed receiver exposes the same HID++ 1.0 receiver registers as
Unifying, so route it through the existing Unifying code path and only
differentiate the user-facing receiver name ("Lightspeed Receiver").
- add 046d:c53f to unifying::VPID_PAIRS so detect() builds the receiver
- add LIGHTSPEED_PIDS + speaks_unifying_protocol()/receiver_display_name()
- route Lightspeed as DeviceRoute::Unifying (was defaulting to Bolt) and
classify it as ReceiverFamily::Unifying for pairing
- label the enumerated receiver via receiver_display_name()
- tests for Lightspeed routing and display name
Verified on macOS with a real G305 (paired device wpid 0x4074).
Greptile SummaryThis PR adds support for Logitech Lightspeed nano receivers through the existing Unifying-compatible path. The main changes are:
Confidence Score: 4/5The Linux receiver-child classification path needs a fix before merging.
crates/openlogi-hid/src/route.rs, crates/openlogi-hid/src/pairing.rs, and the Linux receiver-child filtering logic Important Files Changed
Reviews (1): Last reviewed commit: "feat(hid): recognise Lightspeed nano rec..." | Re-trigger Greptile |
| /// the same HID++ 1.0 receiver register protocol as Unifying, so they are | ||
| /// enumerated, routed, and paired through the Unifying code path; only the | ||
| /// user-facing receiver name (see [`receiver_display_name`]) differs. | ||
| pub const LIGHTSPEED_PIDS: &[u16] = &[0xc53f]; |
There was a problem hiding this comment.
Lightspeed Children Stay Unfiltered
Adding 0xc53f makes Lightspeed receivers appear in the receiver inventory, but the Linux receiver-child sysfs filter still checks only Bolt and Unifying PIDs. On Linux, HID child nodes behind this receiver can still be treated as standalone devices, so the same physical mouse can show up with duplicate or wrong direct-device routing.
| if crate::BOLT_PIDS.contains(&product_id) { | ||
| Some(ReceiverFamily::Bolt) | ||
| } else if crate::UNIFYING_PIDS.contains(&product_id) { | ||
| } else if crate::speaks_unifying_protocol(product_id) { |
There was a problem hiding this comment.
Pairing Flow Uses Enumeration Match
family_for now treats every Lightspeed PID as a Unifying pairing receiver, so run_pairing and unpair can write the Unifying pairing commands to 0xc53f. The compatibility noted for enumeration registers does not show that the pairing lock and unpair commands use the same contract, so a Lightspeed receiver that lists devices correctly but rejects those commands can fail pairing or apply the wrong receiver operation.
Summary
Adds recognition for the Logitech Lightspeed nano receiver (
046d:c53f) — the receiver bundled with G-series wireless mice such as the G305. Before this change,receiver::detect()only matched Bolt (c548) and Unifying (c52b,c532) receivers; a Lightspeed receiver fell through toNone, so any mouse paired to it was completely invisible (the mouse never appeared inlist/ the GUI, even though the keyboard on a Unifying receiver did).A Lightspeed nano receiver is not a Unifying receiver, but it exposes the same HID++ 1.0 receiver registers (
0x02connections,0xB5/0x5Npairing info) that this codebase already drives for Unifying. So the cleanest fix is to route it through the existing Unifying code path and differentiate it only where it's user-visible: the receiver's display name.Changes
openlogi-hidpp/receiver::unifying::VPID_PAIRS— add046d:c53fsodetect()builds the (Unifying-protocol) receiver for it. Documented that this is a protocol-compat Lightspeed receiver, not Unifying proper.openlogi-hid/route.rs— newLIGHTSPEED_PIDSlist plus two small helpers:speaks_unifying_protocol(pid)(Unifying ∪ Lightspeed) andreceiver_display_name(pid).device_route_fornow routes Lightspeed receivers asDeviceRoute::Unifying(they were previously defaulting toBolt, which would address pairing slots with the wrong register flow on the write path).openlogi-hid/pairing.rs—family_forclassifies Lightspeed asReceiverFamily::Unifyingvia the shared helper.openlogi-hid/inventory/probe.rs— the enumerated receiver is now labelled viareceiver_display_name, so a Lightspeed receiver surfaces as "Lightspeed Receiver" while Unifying stays "Unifying Receiver".Testing
Verified on macOS with a real Logitech G305 (paired device wpid
0x4074) on its Lightspeed nano receiver:cargo test -p openlogi-hid -p openlogi-hidpp— all pass (incl. the new tests).cargo clippy/cargo fmtclean on the touched crates.Notes / scope
0xc53f(the receiver that shipped with my G305). Other Lightspeed receiver PIDs (0xc539,0xc541,0xc545,0xc547, …) almost certainly work through the same path, but I've deliberately not added PIDs I couldn't verify — they can be appended toLIGHTSPEED_PIDSas people confirm them.openlogi-hid) rather than the vendoredhidppfork, keeping the protocol layer's notion of "this is the Unifying register protocol" intact.DeviceRoute::Unifying) still reads "Unifying"; the primary receiver name shown in the inventory/carousel is correct. Happy to extend the GUI label too if you'd prefer a follow-up.