LEDs

Triggers
There are two types of triggers: simple and complex. Simple triggers are provided by other subsystems. Complex triggers need to be enabled in kernel configs. For a list of complex triggers, see LEDs.

Both trigger types are merged together in the trigger file. To see the available triggers, cat the trigger file, e.g. . The active trigger is shown in brackets.

[none] usb-gadget usb-host rfkill-any rfkill-none kbd-scrolllock kbd-numlock kbd-capslock kbd-kanalock kbd-shiftlock kbd-altgrlock kbd-ctrllock kbd-altlock kbd-shiftllock kbd-shiftrlock kbd-ctrlllock kbd-ctrlrlock timer heartbeat cpu cpu0 cpu1 cpu2 cpu3 default-on panic mmc1 mmc0 rfkill0 rt5033-battery-charging-or-full rt5033-battery-charging rt5033-battery-full rt5033-battery-charging-blink-full-solid bluetooth-power hci0-power rfkill1 phy0rx phy0tx phy0assoc phy0radio rfkill2

To assign a trigger, echo the trigger name to the trigger file, e.g.

When rebooting, the trigger is lost again. To make it permanent, it needs to be set by an udev rule. If you're not sure about the udev matching and assignment keys, you can look them up by e.g. . To set up the udev rule, do something like:


 * (new file)
 * ACTION=="add", SUBSYSTEM=="leds", KERNEL=="tm2-touchkey", ATTR{trigger}="heartbeat"

Most of the complex triggers are tristate in the kernel configs, they can be compiled as a module. The configs can be checked by e.g. . (The asterisk after the S includes LED trigger that are missing the S like LED_TRIGGER_PHY.)

If a trigger is set as a module, let's say for example, the module needs to be loaded by:

before it becomes available in the trigger list. To use it permanently by an udev rule like described above, the module needs to be added to.

List of kernel LED triggers
For more information on a specific trigger, see the referenced links.


 * drivers/leds/trigger/Kconfig
 * CONFIG_LEDS_TRIGGER_TIMER
 * CONFIG_LEDS_TRIGGER_ONESHOT
 * CONFIG_LEDS_TRIGGER_DISK
 * CONFIG_LEDS_TRIGGER_MTD
 * CONFIG_LEDS_TRIGGER_HEARTBEAT
 * CONFIG_LEDS_TRIGGER_BACKLIGHT
 * CONFIG_LEDS_TRIGGER_CPU
 * CONFIG_LEDS_TRIGGER_ACTIVITY
 * CONFIG_LEDS_TRIGGER_GPIO
 * CONFIG_LEDS_TRIGGER_DEFAULT_ON
 * CONFIG_LEDS_TRIGGER_TRANSIENT
 * CONFIG_LEDS_TRIGGER_CAMERA
 * CONFIG_LEDS_TRIGGER_PANIC
 * CONFIG_LEDS_TRIGGER_NETDEV
 * CONFIG_LEDS_TRIGGER_PATTERN
 * CONFIG_LEDS_TRIGGER_AUDIO
 * CONFIG_LEDS_TRIGGER_TTY


 * drivers/usb/core/Kconfig
 * CONFIG_USB_LEDS_TRIGGER_USBPORT


 * drivers/net/phy/Kconfig
 * CONFIG_LED_TRIGGER_PHY (note the "missing" S in LED)


 * net/netfilter/Kconfig
 * CONFIG_NETFILTER_XT_TARGET_LED

ULED driver
The kernel documentation mentions an ULED driver. Including this into a userspace program written in C creates a node in, which can be accessed by the program. There is an example at tools/leds/uledmon.c.

Access via sysfs
LEDs are available in. They can be turned on/off by echoing a value to brightness. However, root access is required. The range of brightness can be checked by e.g. . In the example tm2-touchkey LED, the max_brightnes is 1, so for this LED it's just on or off. Changing the brightness of a LED with sudo can be done like e.g.

or:

visudo
To use the commands in shell scripts without typing the password, the command(s) can be added to the sudoers file, e.g.:

add:

user ALL=NOPASSWD: /usr/bin/tee /sys/class/leds/tm2-touchkey/brightness
 * 1) Allow user to access tm2-touchkey leds withouth password

The command  now works without password prompt.

Changing permissions in sysfs
Alternatively, to change the LED brightness without sudo, permissions in sysfs can be changed. This seems to be rather unconventional. A project modifying game controllers suggests the follwing approach to change permission on all LEDs :

SUBSYSTEM=="leds", ACTION=="add", RUN+="/bin/chgrp -R leds /sys%p", RUN+="/bin/chmod -R g=u /sys%p" SUBSYSTEM=="leds", ACTION=="change", ENV{TRIGGER}!="none", RUN+="/bin/chgrp -R leds /sys%p", RUN+="/bin/chmod -R g=u /sys%p"
 * 1) Assign any new nodes in the 'leds' subsystem (nodes in /sys/class/leds) to the group 'leds' to write without root
 * 2) Create a new group 'leds' before this will do anything!

This changes the owning group from  to   and transcribes the permission from user (root) to group (leds). It needs to be done on action "add" as well as on action "change" because when the kernel performes changes, the group permissions would be overwritten to  again.

Based on this approach, for the tm2-tochkey leds udev rules were implemented to file /lib/udev/rules.d/20-tm2-touchkey-leds.rules after stable release v21.06 that look like this:

ACTION=="add", SUBSYSTEM=="leds", KERNEL=="tm2-touchkey", RUN+="/bin/chgrp -R input /sys%p", RUN+="/bin/chmod -R g=u /sys%p" ACTION=="change", SUBSYSTEM=="leds", KERNEL=="tm2-touchkey", ENV{TRIGGER}!="none", RUN+="/bin/chgrp -R input /sys%p", RUN+="/bin/chmod -R g=u /sys%p"
 * 1) allow users in group "input" to control the tm2-touchkey leds

This permission change is limited to. And the permissions are changed to group  (postmarketOS users are usually already member of group  ). Additionally, the order of the udev rule keys were put in a different order (has no technical effect).

It's not fully clear if  in the last line is required. A comment on unix.stackexchange.com says it would be needed for kernel older than 4.9.

However, with these udev rules in place, an unpriviliged user that's member of the group  can now turn on the tm2-touchkey leds by simply   without sudo. That's especially helpful for usage in shell scripts.

Sync with backlight
See LEDs:Sync with backlight.