# How to Configure RGB Lighting Settings for Compatible Keyboards Using OpenLogi

> Learn to configure keyboard RGB lighting with OpenLogi. This guide explains how to use HID++ RgbEffects and TOML settings to control hardware commands for custom lighting.

- Repository: [Xuan Zhang/OpenLogi](https://github.com/AprilNEA/OpenLogi)
- Tags: how-to-guide
- Published: 2026-09-03

---

**OpenLogi controls RGB lighting through the HID++ **RgbEffects** feature (feature ID `0x8071`), translating TOML configuration values into hardware commands via the `set_rgb_cluster_effect` method.**

OpenLogi is an open-source driver for Logitech devices that exposes deep hardware control through Rust-based HID++ implementations. When you configure RGB lighting settings for compatible keyboards using OpenLogi, the system maps high-level TOML configuration parameters to low-level HID++ protocol commands that directly manipulate the keyboard's LED clusters. This guide walks through the architecture, configuration syntax, and programmatic APIs that enable static colors, brightness scaling, and per-key lighting control.

## Understanding OpenLogi's RGB Lighting Architecture

OpenLogi implements RGB control via the **RgbEffects** feature, a HID++ 2.0 capability identified by feature ID `0x8071`. According to the OpenLogi source code, a compatible device must report `lighting = true` in its capabilities table before the driver initializes lighting controls.

The `RgbEffectsFeature` struct in [`crates/openlogi-hidpp/src/feature/rgb_effects.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-hidpp/src/feature/rgb_effects.rs) manages the following execution workflow:

1. **Acquire software control** – The driver must invoke `set_sw_control` to claim authority over the lighting subsystem from the device firmware.
2. **Select an LED cluster** – Most keyboards expose a single cluster at index `0`, though multi-zone devices use incremental indices.
3. **Apply the effect** – Static colors use effect type `0` sent via `set_rgb_cluster_effect`, while animated patterns use higher indices.
4. **Persist the configuration** – The `persistence` flag determines whether settings survive power cycles by writing to non-volatile memory.

## Verifying Device Compatibility

Before configuring RGB lighting, confirm your keyboard exposes the lighting capability. OpenLogi generates a capability report during device enumeration that appears in the agent logs and UI.

Look for the `lighting` flag within the device's capabilities table. If the device reports `lighting = true`, OpenLogi automatically instantiates the `RgbEffectsFeature` and enables the configuration parser in [`crates/openlogi-device/src/write/lighting.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/write/lighting.rs).

## Configuring RGB via TOML

OpenLogi uses a declarative TOML configuration file (referenced in [`docs/config.example.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/docs/config.example.toml)) to define RGB behavior. Each device entry supports an optional `[lighting]` table that controls enable states, hex color values, and brightness percentages.

Add the following structure to your device configuration:

```toml
[devices."receiver:abcd1234:slot:1".lighting]
enabled    = true          # Boolean toggle for LED power

color      = "ff0000"      # 24-bit hex RGB string

brightness = 80            # Integer percentage 0-100

```

The `color` field parses as a 24-bit RGB value where `"ff0000"` represents full red. The `brightness` value acts as a scaling factor applied to each color channel before transmission. When you save the configuration file, the OpenLogi GUI watches for changes and applies them automatically, or you can restart `openlogi-agent` to force an immediate reload.

## The Internal Workflow: From Config to Hardware

The translation between TOML values and HID++ packets occurs in [`crates/openlogi-device/src/write/lighting.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/write/lighting.rs). This module reads the `enabled`, `color`, and `brightness` fields, validates the ranges, and constructs the parameter array required by the hardware.

Specifically, the writer builds a `params` byte array of length `CLUSTER_EFFECT_PARAM_COUNT` (typically 16 bytes), inserting the scaled RGB values into the first three indices. It then invokes `RgbEffectsFeature::set_rgb_cluster_effect` with the following arguments:

- **cluster**: `0u8` for single-cluster keyboards
- **effect**: `0u8` for static color mode
- **params**: The constructed color array
- **persistence**: `RgbPersistence::PERSISTENT` to write to device memory
- **power_mode**: `PowerModeTarget::On` to apply during active state

This call chain ensures that your TOML configuration results in immediate hardware updates while optionally persisting across reboots.

## Advanced: Per-Key Lighting Control

For keyboards supporting individual key illumination, OpenLogi exposes the **per_key_lighting** feature implemented 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). This API offers granular methods including:

- `set_rgb_zones_single_value` – Apply one color to multiple zones simultaneously
- `set_individual_rgb_zones` – Map distinct colors to specific key indices

Currently, fine-grained per-key configuration requires using the OpenLogi UI, which internally calls these methods. The TOML schema supports basic `per_key` tables, but complex zone mapping is primarily accessible through the graphical editor that writes directly to the HID++ feature buffers.

## Programmatic Control Using the Rust API

Developers building custom tools can interact with RGB lighting directly through the `openlogi-hidpp` crate. The following Rust example demonstrates setting a static red color on cluster 0, mirroring the internal configuration loader logic:

```rust
use openlogi_hidpp::feature::rgb_effects::RgbEffectsFeature;
use openlogi_hidpp::feature::rgb_effects::types::{
    RgbPersistence, PowerModeTarget,
};

async fn set_static_red(feature: &RgbEffectsFeature) -> Result<(), Hidpp20Error> {
    // Cluster 0, Effect 0 = static color mode
    let cluster = 0u8;
    let effect  = 0u8;
    
    // Initialize parameter buffer (size defined by CLUSTER_EFFECT_PARAM_COUNT)
    let mut params = [0u8; 16]; 
    params[0] = 0xFF; // Red channel
    params[1] = 0x00; // Green channel
    params[2] = 0x00; // Blue channel
    
    // Configure persistence and power state
    let persistence = RgbPersistence::PERSISTENT;
    let power_mode  = PowerModeTarget::On;
    
    feature
        .set_rgb_cluster_effect(cluster, effect, params, persistence, power_mode)
        .await
}

```

This implementation references the exact function signatures found in [`crates/openlogi-hidpp/src/feature/rgb_effects.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-hidpp/src/feature/rgb_effects.rs), providing type-safe access to hardware capabilities without manual byte manipulation.

## Summary

- **OpenLogi uses HID++ feature `0x8071`** (RgbEffects) to control keyboard lighting, requiring devices to report `lighting = true` in their capability tables.
- **Configuration occurs via TOML** using the `[lighting]` table with `enabled`, `color`, and `brightness` fields, parsed by [`crates/openlogi-device/src/write/lighting.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/write/lighting.rs).
- **Hardware communication flows through `set_rgb_cluster_effect`** in [`rgb_effects.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/rgb_effects.rs), which requires software control acquisition and supports persistent storage.
- **Per-key lighting** is available through [`per_key_lighting.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/per_key_lighting.rs) for advanced keyboards, though complex configurations currently require the OpenLogi UI.
- **Rust developers** can leverage the `RgbEffectsFeature` API for programmatic control, using `RgbPersistence::PERSISTENT` to save settings directly to device memory.

## Frequently Asked Questions

### What HID++ feature ID controls RGB lighting in OpenLogi?

RGB lighting is controlled by the **RgbEffects** feature, which uses HID++ feature ID `0x8071`. This feature implements methods such as `set_sw_control` and `set_rgb_cluster_effect` in [`crates/openlogi-hidpp/src/feature/rgb_effects.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-hidpp/src/feature/rgb_effects.rs) to manage LED colors, brightness, and power states.

### How do I verify my keyboard supports RGB lighting in OpenLogi?

Check the device capability report generated during enumeration. Compatible keyboards display `lighting = true` within their capabilities table, visible in the OpenLogi UI logs or agent output. Without this flag, the driver will not initialize the `RgbEffectsFeature` instance required for LED control.

### Can I set different colors for individual keys using the TOML configuration?

Basic TOML configuration supports global color and brightness settings for the entire keyboard cluster. While the underlying API 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) supports per-key zones via `set_individual_rgb_zones`, fine-grained per-key color mapping through TOML alone is limited; advanced configurations require using the OpenLogi UI or direct Rust API calls.

### Does OpenLogi persist RGB settings to the keyboard's memory?

Yes, when the `persistence` parameter is set to `RgbPersistence::PERSISTENT` during the `set_rgb_cluster_effect` call, OpenLogi writes the configuration to the keyboard's non-volatile memory. This ensures the lighting configuration survives power cycles and reconnections without requiring software re-initialization.