# How OpenLogi Implements RGB Lighting Control for Logitech Keyboards

> Learn how OpenLogi enables RGB lighting control for Logitech keyboards using the HID++ 2.0 protocol. Discover an open-source alternative to Logitech Options+.

- Repository: [Xuan Zhang/OpenLogi](https://github.com/AprilNEA/OpenLogi)
- Tags: internals
- Published: 2026-09-13

---

**OpenLogi implements RGB lighting control for Logitech keyboards through the HID++ 2.0 protocol, utilizing the Per-Key Lighting feature (ID 0x8081) and RGB Effects feature (ID 0x8080) to provide an async, open-source alternative to Logitech Options+.**

OpenLogi is a Rust-based open-source implementation that reverse-engineers Logitech's proprietary communication protocols to unlock hardware capabilities on Linux and other platforms. By leveraging HID++ 2.0 feature indices, the project enables precise per-key RGB customization without relying on vendor-specific drivers or closed-source software stacks.

## HID++ 2.0 Protocol Foundation

OpenLogi communicates with Logitech keyboards using the **HID++ 2.0 protocol**, a proprietary extension of standard HID used across modern Logitech peripherals. The RGB lighting implementation relies on two distinct feature IDs:

- **Per-Key Lighting (0x8081)** – Controls individual key illumination and zone-based coloring
- **RGB Effects (0x8080)** – Manages device-wide power states and global lighting effect clusters

These feature IDs are discovered during device enumeration through the HID++ registry, allowing OpenLogi to determine whether connected hardware supports advanced RGB capabilities before attempting configuration.

## Architecture Overview

The implementation spans three layered crates that separate protocol specifics from user-facing APIs.

### openlogi-hidpp: Low-Level Protocol Implementation

The core HID++ definitions reside in [`crates/openlogi-hidpp/src/feature/per_key_lighting.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-hidpp/src/feature/per_key_lighting.rs). The `PerKeyLightingFeature` struct implements the complete per-key API, exposing methods such as:

- `set_individual_rgb_zones()` – Sets unique colors for specific keys
- `set_consecutive_rgb_zones()` – Optimizes batch updates for adjacent keys
- `set_rgb_zones_single_value()` – Applies a uniform color to multiple zones
- `frame_end()` – Commits changes to the device controller

For device-wide management, [`crates/openlogi-hidpp/src/feature/rgb_effects.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-hidpp/src/feature/rgb_effects.rs) provides power-mode handling via `get_rgb_power_mode()` and `set_rgb_power_mode()`, along with cluster-effect configuration for global lighting presets.

### openlogi-device: High-Level Abstraction

The `Device` struct in [`crates/openlogi-device/src/write/lighting.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/write/lighting.rs) translates ergonomic Rust calls into HID++ feature invocations. Methods like `Device::set_rgb_zones_single_value()` wrap the low-level protocol details, handling endpoint management and error propagation while presenting a clean async interface to upper layers.

### openlogi-cli: Command-Line Interface

Quick diagnostics and testing are available through [`crates/openlogi-cli/src/cmd/diag/lighting.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-cli/src/cmd/diag/lighting.rs). The `diag lighting` subcommand parses hexadecimal color strings (e.g., `RRGGBB`) and forwards them through the device layer, enabling rapid hardware validation without writing code.

## Implementation Workflow

OpenLogi executes RGB updates through a five-stage async pipeline:

1. **Feature Discovery** – The agent queries the HID++ registry to locate keyboards advertising support for feature ID `0x8081`.

2. **Endpoint Binding** – `PerKeyLightingFeature::new(endpoint)` instantiates a feature-specific endpoint tied to the discovered device.

3. **Payload Construction** – Helper functions like `individual_zones_args()` and `single_value_args()` serialize RGB data into the 16-byte HID++ payload format required by the protocol specification.

4. **Async Transmission** – The feature calls `endpoint.call_long()` (or `call()` for short commands) to transmit the HID++ packet over the underlying HID transport managed by `openlogi-hid`.

5. **Frame Commit** – `frame_end()` finalizes the update buffer, with optional EEPROM persistence controlled via the `FramePersistence` enum (volatile for temporary effects, non-volatile for permanent configuration changes).

## Code Examples

### Setting Per-Key Colors Programmatically

The following Rust example demonstrates setting a solid cyan color on the first 13 keys using the direct HID++ feature API:

```rust
use openlogi_hidpp::feature::per_key_lighting::{PerKeyLightingFeature, Rgb, FramePersistence};
use openlogi_hidpp::protocol::v20::Hidpp20Error;

// `endpoint` is a `FeatureEndpoint` obtained from the device registry.
let per_key = PerKeyLightingFeature { endpoint };

// Define the target color (bright cyan).
let colour = Rgb { red: 0x00, green: 0xFF, blue: 0xFF };

// Specify zone IDs (key indices). Only the first 13 zones are processed per call.
let zones = &[0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];

// Apply the color to the specified zones.
per_key
    .set_rgb_zones_single_value(colour, zones)
    .await
    .expect("Failed to set per-key RGB");

// Commit the frame (volatile update, not persisted across reboots).
per_key
    .frame_end(FramePersistence::Volatile, 0, 0)
    .await
    .expect("Failed to commit RGB frame");

```

### CLI Diagnostics

For quick hardware testing without compiling Rust code, use the CLI to set the entire keyboard to red:

```bash

# Set keyboard to pure red (FF0000)

openlogi diag lighting ff0000

```

The CLI parses the hexadecimal string, constructs an `Rgb` struct, and invokes the same `set_rgb_zones_single_value()` path used by the desktop application.

## Summary

- OpenLogi uses **HID++ 2.0 feature ID 0x8081** (Per-Key Lighting) for granular RGB control and **0x8080** (RGB Effects) for global power modes
- The codebase follows a three-layer architecture: `openlogi-hidpp` for protocol implementation, `openlogi-device` for high-level device management, and `openlogi-cli` for command-line operations
- Key source files include [`crates/openlogi-hidpp/src/feature/per_key_lighting.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-hidpp/src/feature/per_key_lighting.rs) for low-level features and [`crates/openlogi-device/src/write/lighting.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/write/lighting.rs) for the public API
- Updates are transmitted asynchronously via `endpoint.call_long()` and committed using `frame_end()` with optional EEPROM persistence
- Both programmatic Rust APIs and CLI tools support setting individual keys or uniform colors across zones

## Frequently Asked Questions

### What protocol does OpenLogi use for RGB control?

OpenLogi uses the **HID++ 2.0 protocol**, specifically targeting feature ID `0x8081` for per-key lighting and `0x8080` for RGB effects. This is the same underlying protocol used by Logitech's official software, reverse-engineered to work across platforms without proprietary drivers.

### How many keys can be updated simultaneously in a single call?

The `set_rgb_zones_single_value()` method supports up to **13 zones per invocation**. For updates exceeding this limit, OpenLogi batches commands or uses `set_consecutive_rgb_zones()` for optimized adjacent-key updates, automatically handling the protocol's payload size constraints.

### Is the RGB lighting persistent across reboots?

Persistence depends on the `FramePersistence` parameter passed to `frame_end()`. Use `FramePersistence::Volatile` for temporary effects that reset on power cycle, or specify non-volatile persistence flags to write the configuration to the keyboard's EEPROM for permanent storage.

### Which Logitech devices support per-key RGB through OpenLogi?

Device support depends on whether the keyboard advertises the **Per-Key Lighting feature (0x8081)** in its HID++ registry. Modern Logitech gaming keyboards such as the G Pro series, G915, and G715 typically expose this feature, while office-focused keyboards may only support basic RGB Effects (0x8080) for power modes rather than per-key customization.