What HID++ Protocol Crate Does OpenLogi Use and How Is It Forked?

OpenLogi uses a vendored hard-fork of the upstream hidpp crate, packaged as openlogi-hidpp but preserving the original hidpp library target name so existing imports remain unchanged.

Logitech's HID++ protocol powers device communication for keyboards, mice, and other peripherals. The OpenLogi project, which aims to provide an open-source Logitech device management tool, needed full control over this protocol layer. Rather than depending on an external crate, the maintainers chose to hard-fork the original hidpp implementation from the lus/logy repository. This article explains exactly how that fork is structured and why it matters for developers working with the codebase.

How the Fork Is Declared in Cargo.toml

The fork's status is explicitly documented in crates/openlogi-hidpp/Cargo.toml. The package metadata includes:


# Hard fork of the `hidpp` crate from https://github.com/lus/logy

# License: 0BSD (same as upstream)

This declaration serves multiple purposes: it acknowledges upstream provenance, preserves license compatibility, and signals to contributors that this is intentionally divergent code.

Preserving the Original Library Target Name

The most technically significant aspect of this fork is how the library target is configured. While the package name becomes openlogi-hidpp, the [lib] target explicitly retains hidpp:

[package]
name = "openlogi-hidpp"

# ...

[lib]
name = "hidpp"  # Preserved for backward compatibility

As noted in the Cargo.toml comments, this design choice ensures that all dependent crates continue to use use hidpp::… without modification. The rest of the OpenLogi workspace—modules like crates/openlogi-hid and crates/openlogi-device—imports the protocol through standard hidpp paths, unaware that the implementation is vendored.

Why OpenLogi Hard-Forked the HID++ Crate

Several project-specific requirements drove this decision:

  • Custom derive macro integration: The fork incorporates openlogi-hidpp-derive, a private derive macro for HID++ feature boilerplate that would be difficult to upstream
  • Build reproducibility: Vendoring eliminates external dependency drift across platforms
  • Patch autonomy: OpenLogi can apply protocol fixes or Logitech-specific extensions without waiting for upstream releases
  • License alignment: The 0BSD license permit allows unrestricted modification while remaining compatible with the project's licensing goals

Using the Vendored HID++ Crate in Code

The forked crate exposes the same API surface as upstream. Here's how OpenLogi modules interact with HID++ devices:

// Opening a HID++ channel using the vendored fork
use hidpp::channel::{Channel, HidDevice};
use hidpp::feature::battery_status::BatteryStatus;

async fn open_device(path: &str) -> anyhow::Result<Channel> {
    let dev = HidDevice::open(path).await?;
    let chan = Channel::new(dev).await?;
    Ok(chan)
}

async fn battery_status(chan: &Channel) -> anyhow::Result<BatteryStatus> {
    let status = chan.get_feature::<BatteryStatus>().await?;
    Ok(status)
}

These imports resolve to openlogi-hidpp at build time because the workspace's Cargo.toml overrides the hidpp name to point to the local path.

Documentation and Project References

The vendored nature of this crate is transparently documented:

This documentation strategy ensures that new contributors understand the fork relationship without needing to inspect Cargo.toml files.

Crate Purpose
openlogi-hidpp Core HID++ protocol implementation (the fork)
openlogi-hidpp-derive Procedural macros for feature trait derivation
openlogi-hid Platform-specific HID transport layer
openlogi-device High-level device abstraction using hidpp

Summary

  • OpenLogi's HID++ implementation is a hard-fork of the hidpp crate originally authored by lus in the logy repository
  • The fork lives at crates/openlogi-hidpp with package name openlogi-hidpp but library target hidpp
  • This naming strategy allows all workspace code to use use hidpp::… imports unchanged
  • The fork enables custom derive macros, build reproducibility, and independent patch application
  • Documentation in README.md and DEVELOPMENT.md makes the fork status explicit

Frequently Asked Questions

Does OpenLogi use the crates.io version of hidpp?

No. OpenLogi explicitly does not depend on the upstream hidpp crate from crates.io. Instead, it vendors the source code directly in the workspace as openlogi-hidpp, allowing project-specific modifications while maintaining API compatibility.

Why keep the library name as hidpp instead of openlogi_hidpp?

Preserving the hidpp library target name eliminates the need to rewrite imports across the entire codebase. All dependent modules continue using use hidpp::… as they would with upstream, making the fork transparent to consumers. This is configured explicitly in [lib] name = "hidpp" within the crate's Cargo.toml.

What license covers the forked hidpp code?

The fork retains the upstream 0BSD license, an extremely permissive license functionally equivalent to the public domain. This is documented in the crate's Cargo.toml and matches the original lus/logy repository's licensing.

How does this fork differ from the upstream hidpp implementation?

The primary additions are integration with openlogi-hidpp-derive for procedural macro support and any OpenLogi-specific protocol patches. The core HID++ message parsing, feature definitions, and channel abstractions remain compatible with upstream, though they may diverge over time as the project evolves.

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 →