OpenLogi

Receivers

无线 Logitech 设备配对所用的 USB 接收器,通过 HID++ 1.0 寄存器驱动,以 USB 厂商/产品 ID 识别。

A receiver is the USB dongle that wireless Logitech devices pair to. OpenLogi detects the receiver on its USB/HID channel, then enumerates the devices paired to it.

Unlike device features (which use HID++ 2.0), receivers are driven through HID++ 1.0 registers and are always addressed at device index 0xFF (RECEIVER_DEVICE_INDEX). They are identified purely by their USB vendor/product ID — openlogi-hidpp's receiver::detect() matches the channel's VID/PID against the known sets and returns a Receiver.

Implementation status

Receiver support in the vendored hidpp crate is deliberately conservative — public documentation is scarce. Logi Bolt is the most complete (developed and tested against real hardware); Unifying covers discovery and enumeration but its pairing/management surface is thinner and welcomes hardware testing.

Detection

ReceiverVID:PIDTransport
Logi Bolt046D:C548HID++ 1.0 registers (BLE-based)
Unifying046D:C52B, 046D:C532, 046D:C539HID++ 1.0 registers (Unifying / DJ)
Lightspeed046D:C53F, 046D:C547Unifying registers, G-series dongles

receiver::detect(chan) returns Some(Receiver) for a known dongle, or None otherwise.

The Lightspeed dongles bundled with G-series devices answer the same HID++ 1.0 registers as Unifying, so they are detected, enumerated, routed, and paired through the Unifying code path — only the user-facing name differs (Lightspeed Receiver). C53F is the nano receiver of wireless mice such as the G305, verified against a G305 (paired device wpid 0x4074); C547 ships with newer devices such as the G915 keyboard and the G502 X LIGHTSPEED, verified against a G915 (wpid 0x407c). C539 is the Lightspeed gaming receiver, listed with the Unifying PIDs because it is routed as one.

Common API

The Receiver enum wraps the concrete receiver kinds and exposes the shared surface:

ItemDescription
Receiver::Bolt(_) / Receiver::Unifying(_)The detected receiver kind.
name()Human-readable name (e.g. "Logi Bolt Receiver").
get_unique_id()A string that uniquely identifies this receiver (serial or equivalent).
RECEIVER_DEVICE_INDEX (0xFF)The device index used to address the receiver on the channel.

Errors surface as ReceiverErrorUnknownReceiver, or a wrapped HID++ 1.0 Protocol error.

Logi Bolt

The current Logitech receiver. Bolt is BLE-based, pairs up to 6 devices, and authenticates new devices with a passkey before pairing. bolt::Receiver exposes:

FunctionPurpose
count_pairings()Number of currently paired devices (offline ones included).
collect_paired_devices()Enumerate all paired devices (Vec<DeviceConnection>).
get_device_pairing_information(index)Pairing info for one slot (DevicePairingInformation).
get_device_codename(index)The device's codename / name.
get_notification_state() / set_notification_state(..)Read / enable receiver notifications.
trigger_device_arrival()Re-fire DeviceConnection events for all paired devices (enumeration).
discover_devices(timeout) / cancel_device_discovery()Start / stop discovery of pairable devices (≤ 60 s).
pair_device(slot, address, authentication, entropy)Begin pairing a discovered device.
unpair_device(index)Remove a pairing.
listen()Subscribe to receiver Events.

Pairing flow

  1. discover_devices(Some(secs)) — the receiver emits Event::DeviceDiscoveryDeviceDetails (carrying the device address, kind, wpid, authentication) and Event::DeviceDiscoveryDeviceName for each nearby device.
  2. pair_device(slot, address, authentication, entropy)entropy sets passkey complexity (for mice, the number of left/right clicks the user must enter).
  3. The receiver completes pairing and emits Event::DeviceConnection.

Events (bolt::Event)

VariantWhen
DeviceConnection(DeviceConnection)A device connects / disconnects (requires wireless notifications enabled).
DeviceDiscoveryStatus { discovery_enabled }Discovery mode toggles.
DeviceDiscoveryDeviceDetails { counter, kind, wpid, address, authentication }A device is discovered (details + address required to pair).
DeviceDiscoveryDeviceName { .. }The discovered device's name.

DeviceKind covers Keyboard, Mouse, Numpad, Presenter, Remote, Trackball, Touchpad, Tablet, Gamepad, Joystick, Headset (plus Unknown).

Unifying

The previous-generation receiver. Unifying pairs up to 6 devices over the proprietary Unifying / DJ protocol; once addressed by their slot index, paired devices speak HID++ 2.0. unifying::Receiver exposes:

FunctionPurpose
count_pairings()Number of paired devices (offline ones included).
get_receiver_info()Receiver info, including pairing_slots (ReceiverInfo).
get_device_pairing_information(index)Pairing info for one slot (DevicePairingInformation).
trigger_device_arrival()Re-fire connection events for online devices (startup enumeration).
get_unique_id()Receiver serial / unique id.
listen()Subscribe to receiver Events.

Enumerating paired devices (Rust)

use std::sync::Arc;

use hidpp::{
    channel::HidppChannel,
    receiver::{self, Receiver},
};

// chan: Arc<HidppChannel> bound to the receiver's HID interface.
let Some(rx) = receiver::detect(Arc::clone(&chan)) else {
    return; // not a known Logitech receiver
};
println!("{} — {}", rx.name(), rx.get_unique_id().await?);

match rx {
    Receiver::Bolt(bolt) => {
        for dev in bolt.collect_paired_devices().await? {
            // dev: bolt::DeviceConnection — one paired device
            let _ = dev;
        }
    }
    Receiver::Unifying(uni) => {
        let events = uni.listen();
        uni.trigger_device_arrival().await?; // re-fires DeviceConnection events
        while let Ok(event) = events.recv().await {
            // handle unifying::Event::DeviceConnection { .. }
            let _ = event;
            break;
        }
    }
    _ => {}
}

No receiver

Bluetooth-direct and wired devices enumerate as their own inventory — no receiver involved. See Connect a device.

本页目录