Linux LED Subsystem: Source Code Walkthrough¶
The previous article introduced how to use the Linux LED subsystem. This follow-up looks at the main kernel-side source files and how the framework is organized.
The most useful files to inspect in the kernel tree are:
1. LED device management¶
drivers/leds/led-class.c implements LED-device registration and removal. The central representation is struct led_classdev, which holds the LED name, current and maximum brightness, callbacks, trigger state, device pointer, and synchronization objects.
The important fields are:
name— used for the LED subdirectory under/sys/class/leds/.brightness— current brightness, exposed throughbrightness.max_brightness— maximum valid brightness.brightness_set/brightness_set_blocking— driver callbacks that change brightness.brightness_get— callback that reports brightness.blink_set— optional hardware-accelerated blinking callback.trigger— the trigger currently controlling the LED.
The framework initialization creates the leds device class and attaches the class power-management and attribute groups:
static int __init leds_init(void)
{
leds_class = class_create("leds");
if (IS_ERR(leds_class))
return PTR_ERR(leds_class);
leds_class->pm = &leds_class_dev_pm_ops;
leds_class->dev_groups = led_groups;
return 0;
}
After this initialization, LED drivers can register a led_classdev instance and appear under /sys/class/leds/. Registration is handled by led_classdev_register_ext(); led_classdev_unregister() removes a registered LED.
2. Core LED functionality¶
drivers/leds/led-core.c provides the common registration and management layer.
It connects a struct led_classdev with sysfs and provides the common routines behind brightness and LED-state changes. It also supports trigger registration and associates LED devices with power-management operations through the class pm hooks.
From user space, this is why a typical LED can be inspected and controlled with files such as:
/sys/class/leds/<name>/brightness
/sys/class/leds/<name>/max_brightness
/sys/class/leds/<name>/trigger
3. LED triggers¶
drivers/leds/led-triggers.c implements trigger registration and management. A trigger changes LED state in response to a condition or event: timers, activity indicators, audio status, heartbeats, and so on.
The key structure is conceptually:
struct led_trigger {
const char *name;
int (*activate)(struct led_classdev *led_cdev);
void (*deactivate)(struct led_classdev *led_cdev);
struct led_hw_trigger_type *trigger_type;
rwlock_t leddev_list_lock;
struct list_head led_cdevs;
struct list_head next_trig;
const struct attribute_group **groups;
};
A trigger is therefore an operating mode for an LED. The timer trigger, for example, makes it blink at a configured interval. A board-specific trigger might indicate a network link, audio activity, or a system state.
4. Responsibilities at a glance¶
| File | Main responsibility |
|---|---|
led-class.c | Registers/unregisters LED class devices; creates the LED class and sysfs-facing objects. |
led-core.c | Supplies common LED-device management, brightness handling, and framework support. |
led-triggers.c | Registers and controls triggers, including built-in trigger behavior. |
include/linux/leds.h | Declares the public LED framework interfaces and data structures. |
Summary¶
The LED subsystem separates an LED driver's hardware callbacks from the common user-space interface. A driver describes its LED with led_classdev, the core exposes it in sysfs, and optional triggers give it event-driven behavior without each driver having to reimplement that logic.