Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions Documentation/ABI/testing/sysfs-class-leds-dynamic
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
What: /sys/class/leds/<led>/zone_type
Date: September 2026
Contact: Marco Scardovi <scardracs@disroot.org>
Description: read
Driver-defined string describing the physical topology of
this lighting zone. Example values include "generic",
"keyboard", "keyboard_per_key", "matrix_2d", "segment_strip",
"logo", "lightbar", and "global".

What: /sys/class/leds/<led>/led_count
Date: September 2026
Contact: Marco Scardovi <scardracs@disroot.org>
Description: read
Total number of individual, addressable LEDs in this zone.

What: /sys/class/leds/<led>/matrix_dimensions
Date: September 2026
Contact: Marco Scardovi <scardracs@disroot.org>
Description: read
Width and height of 2D matrix layouts formatted as two
space-separated integers ("<width> <height>"). This attribute
is only visible when the driver publishes non-zero matrix
dimensions for the zone.

What: /sys/class/leds/<led>/effect_index
Date: September 2026
Contact: Marco Scardovi <scardracs@disroot.org>
Description: read
Space-separated list of animation effects supported by the
hardware or driver. Possible effect names include:
"off", "static", "breathing", "strobe", "spectrum_cycle",
"rainbow", "direct", and "custom".

What: /sys/class/leds/<led>/effect
Date: September 2026
Contact: Marco Scardovi <scardracs@disroot.org>
Description: read/write
Current active hardware effect. Reading outputs the effect name.
Writing an effect name from effect_index selects that
effect. Any active trigger is automatically detached upon
switching effects to prevent lock conflicts.

What: /sys/class/leds/<led>/speed_range
Date: September 2026
Contact: Marco Scardovi <scardracs@disroot.org>
Description: read
Minimum and maximum animation speed level accepted by speed.
Formatted as "0-<max>". Only visible when the driver
supports adjustable speed.

What: /sys/class/leds/<led>/speed
Date: September 2026
Contact: Marco Scardovi <scardracs@disroot.org>
Description: read/write
Current animation speed level (integer within speed_range).
Only visible when the driver supports adjustable speed.

What: /sys/class/leds/<led>/direction_index
Date: September 2026
Contact: Marco Scardovi <scardracs@disroot.org>
Description: read
Space-separated list of supported animation directions.
Only visible when the driver supports directional animations.

What: /sys/class/leds/<led>/direction
Date: September 2026
Contact: Marco Scardovi <scardracs@disroot.org>
Description: read/write
Animation propagation direction. Outputs or accepts one of:
"left", "right", "up", "down", "clockwise", "counter_clockwise".
Only visible when the driver supports directional animations.

What: /sys/class/leds/<led>/max_palette_entries
Date: September 2026
Contact: Marco Scardovi <scardracs@disroot.org>
Description: read
Maximum number of palette entries accepted by effects_palette.
Only visible when the driver supports programmable palettes.

What: /sys/class/leds/<led>/effects_palette
Date: September 2026
Contact: Marco Scardovi <scardracs@disroot.org>
Description: read/write
Multi-color stacked palette used by multi-color animation effects.
Reading outputs space-separated 24-bit hex colors ("#RRGGBB").
Writing accepts a space-separated sequence of hex triplets.
The number of entries must not exceed max_palette_entries.

What: /sys/class/leds/<led>/power_states_index
Date: September 2026
Contact: Marco Scardovi <scardracs@disroot.org>
Description: read
Space-separated list of system power states supported for
lighting persistence ("boot", "awake", "sleep", "shutdown").
Only visible on devices supporting power state configuration.

What: /sys/class/leds/<led>/power_states
Date: September 2026
Contact: Marco Scardovi <scardracs@disroot.org>
Description: read/write
Space-separated list of currently enabled persistence power
states. Writing a space-separated list of state names
idempotently updates active states.
Only visible on devices supporting power state configuration.

What: /sys/class/leds/<led>/direct_buffer
Date: September 2026
Contact: Marco Scardovi <scardracs@disroot.org>
Description: write-only (binary)
Raw packed RGB stream (3 bytes per LED: R, G, B in sequence).
Writing to this node transmits direct per-key or matrix frame data
bypassing hardware effect generators. The write must start at
offset 0 and the buffer size must exactly match (led_count * 3)
bytes.

What: /sys/class/leds/<led>/frame
Date: September 2026
Contact: Marco Scardovi <scardracs@disroot.org>
Description: write-only (binary)
Raw binary sink for monochrome pixel displays (e.g. AniMe Matrix)
or segment lighting strips. The current ABI only accepts writes
starting at offset 0; each write is forwarded to the hardware
driver as a single frame payload.
1 change: 1 addition & 0 deletions Documentation/leds/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ LEDs
leds-class
leds-class-flash
leds-class-multicolor
leds-class-dynamic
ledtrig-oneshot
ledtrig-transient
ledtrig-usbport
Expand Down
153 changes: 153 additions & 0 deletions Documentation/leds/leds-class-dynamic.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
.. SPDX-License-Identifier: GPL-2.0

======================================
Dynamic Lighting LED class under Linux
======================================

Author: Marco Scardovi <scardracs@disroot.org>

Description
===========
The Dynamic Lighting LED class provides a standardized sysfs interface for
complex, addressable illumination hardware such as per-key RGB keyboard
matrices, 2D LED matrix displays, addressable segment strips, and chassis
lightbars.

The Dynamic Lighting class wraps the standard Linux LED class framework,
providing a unified sysfs ABI for hardware effects, stacked palette
configuration, power state persistence, and high-throughput binary frame
streaming without requiring raw character device access from userspace.

Directory Layout Example
========================
The following examples use ``<led>`` as a placeholder for a Dynamic Lighting
LED class device name.

.. code-block:: console

# ls -l /sys/class/leds/<led>/
-rw-r--r-- 1 root root 4096 Sep 4 17:00 brightness
-r--r--r-- 1 root root 4096 Sep 4 17:00 max_brightness
-r--r--r-- 1 root root 4096 Sep 4 17:00 zone_type
-r--r--r-- 1 root root 4096 Sep 4 17:00 led_count
-r--r--r-- 1 root root 4096 Sep 4 17:00 effect_index
-rw-r--r-- 1 root root 4096 Sep 4 17:00 effect
-r--r--r-- 1 root root 4096 Sep 4 17:00 speed_range
-rw-r--r-- 1 root root 4096 Sep 4 17:00 speed
-r--r--r-- 1 root root 4096 Sep 4 17:00 direction_index
-rw-r--r-- 1 root root 4096 Sep 4 17:00 direction
-r--r--r-- 1 root root 4096 Sep 4 17:00 max_palette_entries
-rw-r--r-- 1 root root 4096 Sep 4 17:00 effects_palette
-r--r--r-- 1 root root 4096 Sep 4 17:00 power_states_index
-rw-r--r-- 1 root root 4096 Sep 4 17:00 power_states
--w------- 1 root root 504 Sep 4 17:00 direct_buffer

Sysfs Attributes
================

``zone_type`` (read-only)
Driver-defined string describing the physical topology of the zone.
Example values include ``generic``, ``keyboard``, ``keyboard_per_key``,
``matrix_2d``, ``segment_strip``, ``logo``, ``lightbar``, or ``global``.

``led_count`` (read-only)
Total number of individually addressable LEDs in this zone.

``matrix_dimensions`` (read-only)
Width and height for 2D matrix layouts formatted as ``<width> <height>``.
Only visible when the driver publishes non-zero matrix dimensions.

``effect_index`` (read-only)
Space-separated list of animation effects supported by the hardware.
Names include: ``off``, ``static``, ``breathing``, ``strobe``,
``spectrum_cycle``, ``rainbow``, ``direct``, and ``custom``.

``effect`` (read/write)
Currently active hardware animation effect. Writing a supported effect name
switches the mode. Any active trigger is automatically detached upon effect
change to eliminate lock conflicts.

``speed_range`` (read-only)
Minimum and maximum effect animation speed accepted by ``speed``. Only visible
when the hardware supports adjustable speed.

``speed`` (read/write)
Current effect animation speed (within ``speed_range``). Only visible when the
hardware supports adjustable speed.

``direction_index`` (read-only)
Space-separated list of directions accepted by ``direction``. Only
visible when directional effects are supported.

``direction`` (read/write)
Animation propagation direction: ``left``, ``right``, ``up``, ``down``,
``clockwise``, or ``counter_clockwise``. Only visible when directional
effects are supported.

``max_palette_entries`` (read-only)
Maximum number of palette entries accepted by ``effects_palette``. Only
visible when programmable palettes are supported.

``effects_palette`` (read/write)
Space-separated list of 24-bit RGB hex colors (e.g. ``#ff0000 #00ff00``).
Up to ``max_palette_entries`` colors can be defined.

``power_states_index`` (read-only)
List of platform power states supported for illumination persistence
(``boot``, ``awake``, ``sleep``, ``shutdown``).

``power_states`` (read/write)
Currently active persistence states. Writing a space-separated list of
state names idempotently updates the active state bitmask.

``direct_buffer`` (write-only, binary)
Raw binary sink for streaming per-key RGB frames. Each LED requires 3 bytes
in sequence (R, G, B). The write must start at offset 0 and the buffer size
must equal ``led_count * 3`` bytes. Enables efficient high-rate streaming
for visualizers and canvas sinks.

``frame`` (write-only, binary)
Raw binary sink for monochrome display chunks (e.g. 2D pixel matrices) or
segmented lighting bars. The current ABI only accepts writes starting at
offset 0; each write is forwarded to the driver as one frame payload.

Locking Hierarchy & Invariants
==============================
To prevent kernel deadlocks between LED triggers, sysfs handlers, and bus
transfers, the subsystem enforces the following lock order:

1. Acquire outer semaphore: ``mutex_lock(&cdev->led_access)``.
2. If the operation replaces trigger-driven output, disengage/remove the active
LED trigger via ``led_trigger_remove(cdev)``.
3. Acquire internal mutex: ``mutex_lock(&ldev->lock)``.
4. Validate inputs, update state, and dispatch driver callbacks.
5. Release internal mutex: ``mutex_unlock(&ldev->lock)``.
6. Release outer semaphore: ``mutex_unlock(&cdev->led_access)``.

Examples
========

Setting breathing effect at medium speed:
-----------------------------------------
.. code-block:: console

# echo "breathing" > /sys/class/leds/<led>/effect
# echo 1 > /sys/class/leds/<led>/speed

Configuring a custom 3-color palette:
-------------------------------------
.. code-block:: console

# echo "#ff0000 #00ff00 #0000ff" > /sys/class/leds/<led>/effects_palette

Enabling illumination during boot and awake states:
---------------------------------------------------
.. code-block:: console

# echo "boot awake" > /sys/class/leds/<led>/power_states

Streaming a direct RGB frame (for a 168-LED device, 504 bytes):
----------------------------------------------------------------
.. code-block:: console

# dd if=/dev/urandom of=/sys/class/leds/<led>/direct_buffer bs=504 count=1
10 changes: 10 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -14831,6 +14831,16 @@ S: Supported
F: Documentation/scsi/leapraid.rst
F: drivers/scsi/leapraid/

LED DYNAMIC LIGHTING CLASS
M: Marco Scardovi <scardracs@disroot.org>
M: Denis Benato <denis.benato@linux.dev>
L: linux-leds@vger.kernel.org
S: Maintained
F: Documentation/ABI/testing/sysfs-class-leds-dynamic
F: Documentation/leds/leds-class-dynamic.rst
F: drivers/leds/led-class-dynamic.c
F: include/linux/led-dynamic-lighting.h

LED SUBSYSTEM
M: Lee Jones <lee@kernel.org>
M: Pavel Machek <pavel@kernel.org>
Expand Down
1 change: 1 addition & 0 deletions drivers/hid/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ config HID_ASUS
depends on USB_HID
depends on LEDS_CLASS
depends on ASUS_WMI || ASUS_WMI=n
imply LEDS_CLASS_DYNAMIC
select POWER_SUPPLY
help
Support for Asus notebook built-in keyboard and touchpad via i2c, and
Expand Down
Loading