How the openlogi-hidpp Fork Extends the Vendored HID++ Protocol Crate

The openlogi-hidpp crate extends the upstream hidpp library by adding a registry-driven, type-safe API for 30+ HID++ 2.0 features while maintaining full backward compatibility with existing hidpp imports.

The openlogi-hidpp crate is a strategic vendor fork of the hidpp protocol library within the AprilNEA/OpenLogi repository. While it preserves the original public API to ensure existing code continues working without modification, it introduces a comprehensive extension layer that models the full HID++ 2.0 feature set used by modern Logitech devices.

Fork Provenance and Compatibility Strategy

The fork was created from upstream commit 135c5600807845c269b5d5bfa1f33032281fbd86 (version 0.3.0) and maintains close proximity to the original codebase to facilitate future synchronization. This provenance is documented in the crate's README at crates/openlogi-hidpp/README.md (lines 6-13).

The crate retains the hidpp:: namespace, allowing existing integrations to continue using identical import paths. The extensions live under openlogi_hidpp::feature::, providing a clean separation between the base protocol implementation and OpenLogi-specific enhancements.

Centralized Feature Registry Architecture

At the heart of the extension lies a static registry that maps numeric HID++ feature IDs to their typed implementations. The KNOWN_FEATURES map, constructed by the known_features! macro in src/feature/registry.rs (lines 20-70), serves as the central dispatch mechanism for feature discovery.

When a developer calls device.get_feature::<T>(), the library queries this registry to locate the appropriate implementation. The registry stores not just the feature ID, but also version metadata and constructor functions, enabling automatic selection of the most capable implementation available on the connected device.

Versioned Feature Implementations

HID++ features evolve over time, with newer versions superseding older implementations. The known_features! macro handles this complexity by recording each implementation's STARTING_VERSION (lines 30-48 in src/feature/registry.rs).

For example, AdjustableDpi and ExtendedAdjustableDpi represent different generations of the same capability. The registry automatically selects the appropriate version based on the device's reported feature version, ensuring maximum functionality without manual version checking.

Typed Wrappers for 30+ HID++ 2.0 Features

The fork introduces strongly-typed wrappers for more than thirty HID++ 2.0 features, including UnifiedBattery, SmartShiftEnhanced, PerKeyLighting, and SolarDashboard. Each wrapper resides in its own module under src/feature/ and implements the Feature trait.

For instance, src/feature/adjustable_dpi.rs defines AdjustableDpiFeature, which implements CreatableFeature and exposes methods like set_dpi() and get_dpi(). This pattern repeats across all added features, providing compile-time guarantees, enumerated types for device states, and bit-flags for capability flags.

Robust Error Handling and Spec Compliance

The extension layer enforces strict error handling through Hidpp20Error::UnsupportedResponse, which is returned when a device reports unknown wire values rather than attempting to guess or coerce invalid data. This policy, documented in the README (lines 39-41), ensures callers receive precise feedback about device capabilities.

Every feature module includes co-located unit tests (e.g., src/feature/adjustable_dpi/tests.rs) that encode and decode official wire format examples, verifying behavior against the HID++ specification. This ensures the typed wrappers accurately represent the underlying protocol.

Practical API Usage

The fork maintains API compatibility while adding ergonomic discovery methods:

// Re-exported upstream types work unchanged
let chan = hidpp::HidppChannel::open("/dev/hidraw0")?;
let device = hidpp::Device::new(Arc::new(chan), 0);

// Retrieve typed feature implementations from the registry
let dpi = device.get_feature::<openlogi_hidpp::feature::adjustable_dpi::AdjustableDpiFeature>()?;
let current = dpi.get_dpi()?;
dpi.set_dpi(1200)?;

// Access OpenLogi-specific extensions
let lighting = device.get_feature::<openlogi_hidpp::feature::per_key_lighting::PerKeyLightingFeature>()?;
lighting.set_key_color(key_id, rgb::RGB { r: 0, g: 255, b: 0 })?;

The get_feature method uses the registry to instantiate the correct type, providing a uniform interface for accessing capabilities ranging from basic DPI adjustment to advanced per-key RGB lighting control.

Summary

  • The openlogi-hidpp fork tracks upstream commit 135c5600 (v0.3.0) while adding 30+ HID++ 2.0 feature implementations.
  • A centralized registry (KNOWN_FEATURES in src/feature/registry.rs) maps feature IDs to versioned implementations using the known_features! macro.
  • Type-safe wrappers provide ergonomic APIs for device capabilities like AdjustableDpi and PerKeyLighting.
  • The original hidpp:: namespace remains unchanged, ensuring backward compatibility with existing code.
  • Strict error handling via Hidpp20Error::UnsupportedResponse prevents silent failures when devices lack requested capabilities.

Frequently Asked Questions

What is the relationship between openlogi-hidpp and the upstream hidpp crate?

The openlogi-hidpp crate is a vendor fork created from upstream commit 135c5600807845c269b5d5bfa1f33032281fbd86 (version 0.3.0). It maintains the original public API under the hidpp:: namespace for backward compatibility while adding OpenLogi-specific extensions under openlogi_hidpp::feature::. The fork stays close to upstream to simplify future synchronization.

How does the feature registry handle different versions of the same HID++ feature?

The known_features! macro in src/feature/registry.rs records each implementation's STARTING_VERSION along with a producer function. When device.get_feature::<T>() is called, the registry selects the implementation with the highest version number supported by the connected device, automatically choosing between variants like AdjustableDpi and ExtendedAdjustableDpi without requiring manual version checks.

Where are the HID++ feature implementations located in the codebase?

Individual feature implementations reside in separate modules under crates/openlogi-hidpp/src/feature/. For example, adjustable DPI functionality lives in src/feature/adjustable_dpi.rs, while per-key lighting controls are in src/feature/per_key_lighting.rs. Each module contains the feature struct, trait implementations, unit tests, and wire-format definitions.

How does the fork handle devices that don't support specific HID++ features?

Rather than returning generic errors or guessing values, the fork returns Hidpp20Error::UnsupportedResponse when a device reports unknown or unsupported wire values. This error handling policy, documented in the crate README, ensures applications receive explicit feedback about capability mismatches rather than silent failures or corrupted state.

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 →