# How RGB Lighting Configuration Works on OpenLogi Keyboards (Features 0x8070 and 0x8080)

> Discover how OpenLogi configures RGB lighting on Logitech keyboards, utilizing 0x8070 effects and falling back to 0x8080 protocols for broad hardware compatibility.

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

---

**OpenLogi configures RGB lighting on Logitech HID++ keyboards by prioritizing the modern 0x8070 Color Led Effects feature, dynamically falling back to per-key 0x8081 or legacy 0x8080 protocols when hardware support varies.**

The OpenLogi project implements an open-source driver stack for Logitech peripherals, managing RGB lighting configuration through specific HID++ protocol features. Understanding how the driver negotiates between **0x8070** (Color Led Effects) and **0x8080** (Legacy RGB) enables developers to control keyboard illumination across different hardware generations. This article examines the source code paths that handle static color configuration on supported devices.

## HID++ Lighting Feature Detection and Priority

When OpenLogi initializes a keyboard device, the core layer establishes a prioritized list of lighting control features. According to the orchestration logic in [`crates/openlogi-core/src/device.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/device.rs), the driver attempts to set colors using a strict hierarchy: **0x8070** first, followed by **0x8081** (Per-Key Lighting), and finally **0x8080** (Legacy RGB) as a last resort.

The `set_keyboard_color` routine implements this traversal:

```rust
// crates/openlogi-core/src/device.rs – color-setting loop
for id in [0x8070, 0x8080, 0x8081] {
    // try to write a static colour using the current feature ID
    // …
}

```

This approach ensures modern keyboards utilize the most efficient protocol while maintaining compatibility with older hardware that only exposes legacy endpoints.

## Implementing the Modern Color Led Effects (0x8070)

The **0x8070** feature represents the modern "fixed-effect" engine capable of controlling multiple lighting zones simultaneously. Implementation resides in [`crates/openlogi-device/src/write/lighting.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/write/lighting.rs), where the constant `COLOR_LED_EFFECTS_FEATURE` identifies this protocol:

```rust
const COLOR_LED_EFFECTS_FEATURE: u16 = 0x8070;

```

The write logic constructs a `ColorLedEffect` payload containing the target RGB values and transmits the HID++ "set effect" command. If the device reports **zero available zones**, OpenLogi automatically logs a diagnostic warning and escalates to the fallback path. This zero-zone check prevents silent failures on devices that advertise the feature but lack configurable lighting regions.

## Legacy RGB Fallback (0x8080)

Older keyboard generations expose only the **0x8080** Legacy RGB feature, which uses a simpler `setRgbColor` command structure. When the driver encounters a `FeatureUnsupported` error during the 0x8070 attempt—or when the modern engine reports zero zones—it automatically transitions to this legacy implementation in the same [`lighting.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/lighting.rs) module.

The fallback mechanism ensures broad hardware support without requiring user intervention. Diagnostic logs indicate which path was taken, such as "0x8070 reported zero zones; applying legacy 4-zone fallback," providing transparency during troubleshooting.

## Per-Key Lighting Intermediate Fallback (0x8081)

Between the modern unified engine and the legacy protocol sits **0x8081**, the Per-Key Lighting feature. This feature targets keyboards with individually addressable keys rather than unified zones. The driver attempts this protocol when 0x8070 fails but before resorting to 0x8080, reflecting a middle-ground capability level in the hardware support matrix defined by the lighting feature enumeration.

## CLI Usage and Programmatic API

Users interact with these underlying protocols through the `openlogi-cli` crate, which abstracts the complexity of feature detection. The `openlogi diag lighting` command accepts a six-digit hexadecimal color string validated by [`crates/openlogi-core/src/color.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/color.rs):

```bash

# Set a solid red color on any supported keyboard

openlogi diag lighting ff0000

```

Programmatically, the `Device` struct exposes the same functionality through the `set_keyboard_color` method:

```rust
// Minimal programmatic example (uses the same internal API)
use openlogi_core::device::Device;
use openlogi_core::color::RgbColor;

fn set_red(device: &mut Device) -> Result<(), openlogi_core::error::Error> {
    let red = RgbColor::from_hex("ff0000")?;
    device.set_keyboard_color(red)
}

```

The CLI entry point in [`crates/openlogi-cli/src/cmd/diag/lighting.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-cli/src/cmd/diag/lighting.rs) delegates to this core API, ensuring consistent behavior whether invoked from the command line or embedded in other Rust applications.

## Summary

- **Feature 0x8070** provides the primary modern interface for RGB control using the `ColorLedEffects` protocol, implemented in [`crates/openlogi-device/src/write/lighting.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/write/lighting.rs).
- **Feature 0x8080** serves as the legacy fallback for older keyboards utilizing the `setRgbColor` command.
- The driver prioritizes **0x8070**, then **0x8081**, then **0x8080**, automatically negotiating the best available protocol.
- Zero-zone detection on 0x8070 triggers immediate fallback to prevent configuration failures.
- Both CLI and programmatic APIs abstract this complexity, accepting standard hex color codes through `RgbColor::from_hex`.

## Frequently Asked Questions

### What is the difference between HID++ features 0x8070 and 0x8080?

Feature **0x8070** (Color Led Effects) is the modern protocol supporting multi-zone lighting effects and unified color configuration, while **0x8080** (Legacy RGB) is an older command set found on previous-generation keyboards. OpenLogi prefers 0x8070 for its enhanced capabilities but transparently falls back to 0x8080 when the modern feature is unavailable.

### Why does OpenLogi fall back to 0x8080 when 0x8070 reports zero zones?

When a device advertises the 0x8070 feature but returns zero available lighting zones, it indicates the feature is present but non-functional for RGB control. Rather than failing silently, OpenLogi interprets this as a hardware compatibility signal and escalates to the 0x8080 legacy path or 0x8081 per-key lighting, ensuring the color command reaches the hardware through an alternative protocol.

### How do I set a custom RGB color programmatically using OpenLogi?

Import `RgbColor` from `openlogi_core::color` and call `Device::set_keyboard_color`. The method handles feature negotiation automatically:

```rust
use openlogi_core::{device::Device, color::RgbColor};

let device = Device::new(/* connection params */)?;
let color = RgbColor::from_hex("00ff00")?; // Green
device.set_keyboard_color(color)?;

```

### Which source files manage the RGB lighting configuration?

The primary implementation spans four critical locations: [`crates/openlogi-core/src/device.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/device.rs) orchestrates feature detection and fallback logic; [`crates/openlogi-device/src/write/lighting.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/write/lighting.rs) contains the low-level HID++ command implementations for both 0x8070 and 0x8080; [`crates/openlogi-hidpp/src/feature/color_led_effects.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-hidpp/src/feature/color_led_effects.rs) defines the protocol structures; and [`crates/openlogi-cli/src/cmd/diag/lighting.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-cli/src/cmd/diag/lighting.rs) provides the user-facing command interface.