Differences Between OpenLogi's HID++ Protocol Implementation and the Upstream `hidpp` Crate

OpenLogi's openlogi-hidpp crate is a vendored fork of the upstream hidpp library that adds typed Rust abstractions for 20+ HID++ 2.0 features, stricter error handling, and OpenLogi-specific instrumentation not present in the original crate.

The openlogi-hidpp crate serves as the communication layer between OpenLogi's local-first GUI and Logitech devices. While it retains the core protocol implementation from upstream commit 135c5600807845c269b5d5bfa1f33032281fbd86, the fork diverges significantly in feature coverage, error semantics, and operational observability. This article breaks down each key difference with reference to the actual source files in the AprilNEA/OpenLogi repository.


Expanded Feature Set with Typed Abstractions

The upstream hidpp crate provides only low-level protocol primitives. OpenLogi's fork wraps typed Rust structures around a comprehensive set of HID++ 2.0 features, organized by functional domain.

Feature Coverage Overview

All extended features live in crates/openlogi-hidpp/src/feature/*.rs and self-register via feature::registry ([src/feature/registry.rs](https://github.com/AprilNEA/OpenLogi/blob/master/crates/openlogi-hidpp/src/feature/registry.rs)):

  • Device & Power: Root, FeatureSet, DeviceInformation, UnifiedBattery, WirelessDeviceStatus
  • Hosts & Platform: HostsInfo, ChangeHost, MultiPlatform, DualPlatform
  • Pointer & Wheel: MousePointer, AdjustableDpi, ExtendedAdjustableDpi, VerticalScrolling, HiResWheel, Thumbwheel, SmartShift (plus enhanced variants)
  • Controls & Remapping: ReprogControls, PersistentRemappableAction
  • Keyboard: FnInversion, DisableKeys, DisableKeysByUsage, ModeStatus
  • Lighting: Backlight, Illumination, BrightnessControl, ColorLedEffects, RgbEffects, PerKeyLighting
  • Audio: Sidetone, Equalizer
  • Report Rate: AdjustableReportRate, ExtendedAdjustableReportRate
  • Touch & Crown: Crown, TouchpadRawXy, TouchMouseRaw, SolarKeyboardDashboard

Each wrapper handles official wire format encoding/decoding, provides enums and bitflags for domain values, and includes unit tests against the HID++ specification. The feature list is documented in the fork's README (lines 19-34).

Using Typed Features

use hidpp::device::Device;
use hidpp::feature::unified_battery::UnifiedBattery;

async fn print_battery_status(mut dev: Device) -> Result<(), hidpp::error::Error> {
    // Feature auto-registers via registry.rs; type-safe retrieval
    let battery = dev.get_feature::<UnifiedBattery>().await?;
    let status = battery.read_status().await?;
    println!("Battery: {}% (charging: {})", status.percentage, status.is_charging);
    Ok(())
}
use hidpp::device::Device;
use hidpp::feature::color_led_effects::ColorLedEffects;

async fn set_breathing_effect(mut dev: Device) -> Result<(), hidpp::error::Error> {
    let led = dev.get_feature::<ColorLedEffects>().await?;
    led.set_effect(hidpp::feature::color_led_effects::Effect::Breathing {
        hue: 120,
        period_ms: 1500,
    }).await?;
    Ok(())
}

Stricter Error Handling for Production Reliability

OpenLogi's fork diverges from upstream in its error handling philosophy. The upstream crate sometimes "guesses" unknown wire values to maintain compatibility. OpenLogi deliberately fails fast.

  • Hidpp20Error::UnsupportedResponse: Returned when encountering unexpected field values (lines 39-41)
  • Prevents silent misinterpretation: Critical for the agent architecture where reliable device communication is non-negotiable

This strictness ensures that protocol deviations surface immediately rather than propagating as subtly incorrect state.


OpenLogi-Specific Instrumentation and Diagnostics

The fork introduces tracing and logging hooks absent from upstream, gated behind environment flags.

Wire Tracing in Messages

The channel/message.rs file contains an OpenLogi-specific comment flagging messages for optional trace output (line 74):

// At line 74: message tagged for trace output when OPENLOGI_LOG=hidpp=trace

Channel Diagnostics

The channel.rs module (lines 279-462) adds:

  • supports_short_long_hidpp() utility for capability detection
  • Extra debug messages for the agent's read loop
  • Full diagnostic output under OPENLOGI_LOG=hidpp=trace
std::env::set_var("OPENLOGI_LOG", "hidpp=trace");
// Subsequent HID++ requests emit structured trace logs

Private Derive-Macro Crate for Boilerplate Reduction

OpenLogi ships openlogi-hidpp-derive, a private proc-macro crate that eliminates repetitive trait implementations.

Located at crates/openlogi-hidpp-derive, this crate generates:

  • Feature trait implementations
  • CreatableFeature trait implementations

Used throughout feature modules:

use openlogi_hidpp_derive::Feature;

#[derive(Feature)]
pub struct UnifiedBattery { /* ... */ }

This macro layer is unique to the fork and has no upstream equivalent.


Crate Naming and Versioning Strategy

Aspect Upstream OpenLogi Fork
Package name hidpp openlogi-hidpp
Library target hidpp hidpp (unchanged for API compatibility)
Versioning Independent Synchronized with workspace unified versioning
Upstream tracking N/A Documented provenance: commit 135c5600807845c269b5d5bfa1f33032281fbd86

The naming strategy preserves use hidpp::... imports in downstream code while enabling future upstream syncs without breaking changes.


Documentation and Licensing

The fork includes a dedicated README (crates/openlogi-hidpp/README.md) that upstream lacks:

  • Fork purpose and upstream source attribution
  • Complete feature enumeration
  • Error handling philosophy
  • 0BSD license declaration

This documentation supports both contributors and API consumers navigating the expanded surface area.


Summary

  • Typed feature wrappers: 20+ HID++ 2.0 features with domain-specific abstractions in src/feature/*.rs
  • Strict errors: UnsupportedResponse for unknown values instead of silent guessing
  • Operational visibility: Wire tracing and channel diagnostics via OPENLOGI_LOG=hidpp=trace
  • Derive macros: Private openlogi-hidpp-derive crate eliminates boilerplate
  • Stable API: Library target remains hidpp despite package rename
  • Documented provenance: Upstream commit tracked for future synchronization

Frequently Asked Questions

What is the openlogi-hidpp crate in OpenLogi?

openlogi-hidpp is a vendored fork of the official Logitech hidpp protocol library that powers OpenLogi's device communication. It wraps low-level HID++ protocol primitives in type-safe Rust abstractions and adds features, stricter error handling, and diagnostic instrumentation needed by the OpenLogi agent and GUI.

How do I enable debug logging for HID++ operations?

Set the environment variable OPENLOGI_LOG=hidpp=trace before running your application. This activates wire tracing hooks in channel/message.rs (line 74) and channel diagnostics in channel.rs (lines 279-462). Trace output includes raw message contents and protocol state transitions.

Why does OpenLogi use a fork instead of the upstream hidpp crate directly?

The upstream crate provides only protocol primitives. OpenLogi requires typed abstractions for 20+ HID++ features, strict error handling that fails on unexpected values rather than guessing, and integrated tracing for production debugging. The fork maintains API compatibility (use hidpp::...) while adding these capabilities.

Can I contribute feature implementations back to the OpenLogi fork?

Yes. New features should follow the established pattern: implement in src/feature/<feature_name>.rs, derive Feature and CreatableFeature via openlogi_hidpp_derive, and ensure registration in feature::registry.rs. All features must include enums/bitflags for domain values and unit tests against the HID++ specification.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →