displays_physical_linux_sys 0.1.0

Rust library for querying and updating Linux backlight and LED brightness devices via sysfs
Documentation
  • Coverage
  • 100%
    51 out of 51 items documented1 out of 1 items with examples
  • Size
  • Source code size: 59.3 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 1.05 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 11s Average build duration of successful builds.
  • all releases: 11s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Homepage
  • AndreasBackx/displays
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • AndreasBackx

displays_physical_linux_sys

displays_physical_linux_sys is a small Rust library for querying and updating Linux brightness devices exposed through sysfs.

It is also the lowest-level Linux physical brightness backend used by the higher-level displays crate.

Start with the displays crate unless you need direct sysfs access.

It currently works with devices under:

  • /sys/class/backlight
  • /sys/class/leds

The API is intentionally manager-oriented and library-focused. It exposes typed device metadata and brightness update operations instead of mirroring a CLI.

How this maps to Linux

On Linux, brightness for many devices is exposed through the kernel's sysfs interface. Sysfs presents kernel objects as files and directories, usually under /sys.

For this crate, the important directories are:

  • /sys/class/backlight for laptop panels and other backlight-style devices
  • /sys/class/leds for LED-style brightness devices, including some keyboard backlights and indicator LEDs

Each device normally appears as a directory such as:

  • /sys/class/backlight/intel_backlight
  • /sys/class/leds/asus::kbd_backlight

Inside that directory, Linux commonly exposes:

  • brightness: the current raw brightness value that can be written
  • max_brightness: the maximum allowed raw value
  • actual_brightness: the effective brightness actually being applied, when the driver exposes it

This crate reads those files directly. That is why the API exposes raw values as first-class data instead of hiding everything behind percentages.

Understanding raw values

Linux brightness values are device-specific integers, not universal units.

For example:

  • one device may use a range of 0..=255
  • another may use 0..=937
  • another may use 0..=3

So BrightnessUpdate::Raw(100) does not mean the same thing across devices. When you need a cross-device notion of brightness, use percentages.

The crate therefore exposes both:

  • raw values, which match Linux directly
  • brightness_percent, which is derived from brightness / max_brightness

Reading versus actual brightness

Some drivers expose both brightness and actual_brightness.

  • brightness is the configured target value
  • actual_brightness is the effective value reported by the driver

They are often equal, but they do not have to be. For example, hardware or driver behavior may temporarily clamp or lag behind the configured value.

If actual_brightness is not present, the device is still fully usable through this crate.

Permissions and writes

Reading sysfs brightness files is commonly allowed for regular users, but writing is often restricted.

In practice, successful writes usually require one of these:

  • root privileges
  • udev rules that grant write access to the relevant brightness file
  • a system policy that changes device permissions outside the crate

This first version performs direct sysfs writes only. It does not currently use logind or another privileged mediation path.

Why both backlight and leds are included

Linux does not have a single unified "brightness device" abstraction. Similar controls can show up in different sysfs classes depending on the driver and the hardware.

This crate includes both backlight and leds so callers can work with the kernel's available brightness-capable devices through one API.

Features

  • Enumerate backlight and LED brightness devices
  • Read current, maximum, and optional actual brightness values
  • Match devices by class, id, and path
  • Apply brightness updates using raw values, percentages, and deltas
  • Validate updates without writing to sysfs
  • Use a custom sysfs root for tests and fixtures

Usage

use std::collections::BTreeSet;

use displays_physical_linux_sys::{
    BrightnessUpdate, DeviceClass, DeviceIdentifier, DeviceUpdate,
    PhysicalDisplayManagerLinuxSys,
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let manager = PhysicalDisplayManagerLinuxSys::new();

    for device in manager.list()? {
        println!(
            "{} {}: {}/{} ({}%)",
            match device.metadata.class {
                DeviceClass::Backlight => "backlight",
                DeviceClass::Leds => "leds",
            },
            device.metadata.id,
            device.state.brightness_raw,
            device.state.max_brightness_raw,
            device.state.brightness_percent,
        );
    }

    let remaining = manager.update(vec![DeviceUpdate {
        id: DeviceIdentifier {
            class: Some(DeviceClass::Backlight),
            id: Some("intel_backlight".to_string()),
            path: None,
        },
        brightness: Some(BrightnessUpdate::Percent(50)),
    }])?;

    assert!(remaining.is_empty());
    Ok(())
}

Matching

DeviceIdentifier uses subset matching:

  • class restricts matching to one sysfs class
  • id matches the device directory name
  • path matches the full device path exactly

Any field left as None is ignored during matching.

Update semantics

The crate currently supports these update types:

  • BrightnessUpdate::Raw(u32)
  • BrightnessUpdate::Percent(u8)
  • BrightnessUpdate::RawDelta(i32)
  • BrightnessUpdate::PercentDelta(i32)

All writes are clamped to the device's valid raw range 0..=max_brightness.

Linux behavior

The crate reads the same sysfs brightness values that Linux exposes directly. That means raw values are first-class API data rather than being hidden behind a percent-only abstraction.

If an actual_brightness file exists, it is exposed as DeviceState::actual_brightness_raw. It is not required for a device to be usable.

Current scope

This first version uses direct sysfs reads and writes only.

It does not currently include:

  • logind-based write fallback
  • hotplug monitoring
  • non-sysfs backends

Further reading

Kernel documentation:

Man pages to check locally on a Linux system:

  • man 5 sysfs
  • man 7 udev
  • man 8 udevadm

Those references are useful if you want to understand where these files come from, why device permissions differ between systems, or how a particular driver maps hardware brightness into sysfs.

License

MIT