Framework 'hacken'

Eén van de leuke dingen aan Linux is de snelheid waarmee sommige dingen ontwikkeld worden en wat er dus beschikbaar komt. Een mooi voorbeeld hiervan is de firmware van de Framework 13 laptop; dit is gebaseerd op dezelfde firmware als die moderne Chromebooks gebruiken.

De Framework zit echter hardwaretechnisch wat anders in elkaar dan de meeste Chromebooks, want de Framework heeft een aantal (status)LEDjes aan de linker- en rechterkant van de laptop die bijvoorbeeld knipperen als je de laptop op aan het laden bent. Ook de aan- en uitknop heeft een LED erin zitten om aan te geven dat de laptop aanstaat.

Met andere laptops zijn deze LEDjes uit te lezen via /sys/class/leds, en vaak kun je ze ook handmatig aan- of uitzetten. Dat was tot voor kort met de Framework niet mogelijk omdat de code hiervoor ontbrak, aangezien dit iets is wat Chromebooks niet hebben.

Een van de hoofdontwikkelaars hiervan heeft, in samenwerking met Framework, de ondersteuning hiervoor toegevoegd en ik heb ermee zitten spelen en ben daardoor achter wat leuke details gekomen van de LEDjes in de Framework. Hieronder een paar van die leuke details en hoe je hier zelf mee kunt spelen.

Update 11-09-2024:

Dit werkt alleen in Linux kernel versie 6.11 vanaf versie RC5 en hoger!

Beschikbare LEDjes

De volgende LEDjes zijn benaderbaar / te gebruiken:

En dan heb je de vrij standaard LEDjes nog:

En dan is er nog één LED die niet standaard is maar ook niet onder de chromeos paraplu valt:

Keyboardverlichting

Net als veel andere laptops heeft ook de Framework 13 keyboardverlichting. Tot voor kort was het niet mogelijk deze vanuit het OS te regelen, maar kon je het alleen regelen via de sneltoetsen op het toetsenbord. Dat is met de meest recente update aangepast en heb je nu de mogelijkheid dit te beheren via /sys/class/leds/chromeos::kbd_backlight/.

Huidige helderheid

Om de huidige helderheid te achterhalen is het een kwestie van het bestand /sys/class/leds/chromeos::kbd_backlight/brightness uit te lezen.

Maximale helderheid

Veel verlichting heeft een minimale (0) en een maximale helderheid. Om hierachter te komen wat dit is lees je /sys/class/leds/chromeos::kbd_backlight/max_brightness uit. In dit geval is de maximale helderheid 100.

Helderheid instellen

Voor het instellen van de helderheid gebruik je hetzelfde bestand als voor het uitlezen van de huidige helderheid, met als enige verschil dat je nu de nieuwe waarde erin schrijft. Om het toetsenbord bijvoorbeeld op 50% in te stellen:

echo 50 | sudo tee /sys/class/leds/chromeos\:\:kbd_backlight/brightness

Aan/uit knop

Veel leuker dan de keyboardverlichting is het feit dat de Framework 13 ook een LED heeft voor de aan/uit knop van de laptop. Als deze brand is de laptop aan, en anders is de laptop uit. Deze is te beheren via /sys/class/leds/chromeos:multicolor:power/.

Huidige helderheid

Een van de eigenaardigheden van deze LED is dat als de laptop aanstaat en er verder nog niet met deze LED is gespeeld de helderheid (via /sys/class/leds/chromeos:multicolor:power/brightness) volgens het systeem op 0 staat, terwijl de knop toch echt ‘aan’ staat.

Maximale helderheid

Dit doe je met cat /sys/class/leds/chromeos\:multicolor\:power/brightness, maar let op dat dit niet de werkelijkheid hoeft weer te geven. Als cat /sys/class/leds/chromeos\:multicolor\:power/trigger op [chromeos-auto] staat gaat de helderheid (en kleur) buiten het OS om.

Helderheid instellen

Dit is een beetje een aparte, de maximale helderheid volgens /sys/class/leds/chromeos:multicolor:power/max_brightness is 100, maar of je nu 1 of 100 als waarde gebruikt maakt niet uit, de helderheid is hetzelfde. Als je de waarde op 0 instelt gaat de toets uit, dus dit is een overgecompliceerde aan/uit knop voor het LEDje in de aan/uit knop.

Om ’m aan te zetten:

echo 1 | sudo tee /sys/class/leds/chromeos\:multicolor\:power/brightness

En om ’m uit te zetten:

echo 0 | sudo tee /sys/class/leds/chromeos\:multicolor\:power/brightness

Een andere eigenaardigheid is dat als je het LEDje uitzet en weer aanzet deze standaard rood is, omdat de kleur standaard ingesteld staat op rood (zie hieronder).

Andere kleuren

De LED in de aan/uitknop ondersteunt meerdere kleuren. Welke dit zijn staat in /sys/class/leds/chromeos:multicolor:power/multi_index, en zijn de volgende:

En om te bepalen welke kleur de LED is wordt /sys/class/leds/chromeos:multicolor:power/multi_intensity gebruikt, en heeft standaard de volgende waarden:

En daaraan zie je ook waarom de LED als je deze zelf aanzet rood is, de waardes uit /sys/class/leds/chromeos:multicolor:power/multi_intensity zijn voor de kleuren genoemd in /sys/class/leds/chromeos:multicolor:power/multi_index.

Als je die twee naast elkaar legt krijg je het volgende totaaloverzicht

Kleur Waarde
red 100
green 0
blue 0
yellow 0
white 0
amber 0

Wil je dus dat de LED in je aan/uitknop groen is in plaats van rood? Dat kan:

echo 0 100 0 0 0 0 | sudo tee /sys/class/leds/chromeos\:multicolor\:power/multi_intensity

Je kunt dus ook twee (of meer) kleuren combineren. Bijvoorbeeld red en blue:

echo 50 0 50 0 0 0 | sudo tee /sys/class/leds/chromeos\:multicolor\:power/multi_intensity

Bug: geen blauw

De LED in de stroomknop van de Framework heeft volgens het bestand multi_index ook een blauwe stand, maar die werkt niet als de kleur in multi_intensity op blauw word ingesteld. Waarom dat is ontgaat me even.

Linker LED

De Framework 13 heeft links in de body een LED zitten tussen de twee USB poorten. Deze wordt gebruikt om aan te geven als de laptop aan de stroom hangt.

Huidige helderheid

Dit doe je met cat /sys/class/leds/chromeos\:multicolor\:left/brightness. Zoals je ziet werkt dit hetzelfde als de andere LED lampjes tot nu toe.

Maximale helderheid

Ook dit werkt op dezelfde manier als de andere LED lampjes in de Framework: cat /sys/class/leds/chromeos\:multicolor\:left/max_brightness.

Helderheid instellen

En ook dit werkt op dezelfde manier als de andere LED lampjes:

echo 50 | sudo tee /sys/class/leds/chromeos\:multicolor\:left/brightness

Om het linker frame LEDje op 50% helderheid in te stellen. Net als bij de aan/uitknop lijkt dit echter niet veel uit te halen, en werken alleen 0 en >= 1 waar 0 het lampje uitzet en alles groter dan 1 het lampje aanzet. Waarom er een helderheidsschaal lijkt te zijn is de grote vraag.

Andere kleuren

Net als de aan/uitknop ondersteunt deze LED ook meerdere kleuren. Welke dit zijn staat, net als bij de aan/uitknop LED, genoteerd in /sys/class/leds/chromeos\:multicolor\:left/multi_index:

En om te bepalen welke kleur de LED is wordt /sys/class/leds/chromeos\:multicolor\:left/multi_intensity gebruikt, en heeft standaard de volgende waarden:

Dit werkt op dezelfde manier als de LED van de aan/uitknop, en is ook de reden waarom ook deze LED rood word als je deze handmatig activeert. Ook hier is het volgende totaaloverzicht:

Kleur Waarde
red 100
green 0
blue 0
yellow 0
white 0
amber 0

Wil je de LED groen maken in plaats van rood? Dat kan:

echo 0 100 0 0 0 0 | sudo tee /sys/class/leds/chromeos\:multicolor\:left/multi_intensity

Zie het stuk hierboven over de aan/uitknop LED voor meer voorbeelden.

Rechter LED

De Framework 13 heeft rechts in de body een LED zitten tussen de twee USB poorten. Deze wordt gebruikt om aan te geven als de laptop aan de stroom hangt.

Huidige helderheid

Dit doe je met cat /sys/class/leds/chromeos\:multicolor\:right/brightness. Zoals je ziet werkt dit hetzelfde als de andere LED lampjes tot nu toe.

Maximale helderheid

Ook dit werkt op dezelfde manier als de andere LED lampjes in de Framework: cat /sys/class/leds/chromeos\:multicolor\:right/max_brightness.

Helderheid instellen

En ook dit werkt op dezelfde manier als de andere LED lampjes:

echo 50 | sudo tee /sys/class/leds/chromeos\:multicolor\:right/brightness

Om het rechter frame LEDje op 50% helderheid in te stellen. Net als bij de aan/uitknop en het linker frame LEDje lijkt dit echter niet veel uit te halen, en werken alleen 0 en >= 1 waar 0 het lampje uitzet en alles groter dan 1 het lampje aanzet. Waarom er ook hier een helderheidsschaal lijkt te zijn is de grote vraag.

Andere kleuren

Net als de aan/uitknop en het linker frame LEDjs ondersteunt deze LED ook meerdere kleuren. Welke dit zijn staat, net als bij de aan/uitknop en het linker frame LEDje, genoteerd in /sys/class/leds/chromeos\:multicolor\:right/multi_index:

En om te bepalen welke kleur de LED is wordt /sys/class/leds/chromeos\:multicolor\:right/multi_intensity gebruikt, en heeft standaard de volgende waarden:

Dit werkt op dezelfde manier als de LEDjes van de aan/uitknop en de linker frame LED, en is ook de reden waarom deze LED rood word als je deze handmatig activeert. Ook hier is het volgende totaaloverzicht:

Kleur Waarde
red 100
green 0
blue 0
yellow 0
white 0
amber 0

Wil je de LED groen maken in plaats van rood? Dat kan:

echo 0 100 0 0 0 0 | sudo tee /sys/class/leds/chromeos\:multicolor\:right/multi_intensity

Zie het stuk hierboven over de aan/uitknop LED voor meer voorbeelden.

Extra: knipperen van LED(jes)

Het leuke van LEDjes is het kunnen knipperen ervan. Dit kan met de verschillende LEDjes in de Framework ook, en er is zelfs al een kernelmodule voor om dit zo makkelijk mogelijk te maken!

Deze module heet ledtrig_timer en is standaard niet geladen. Om dat te doen voer je het volgende uit:

sudo modprobe ledtrig_timer

Om de module te laden. Als dat gebeurd is dan kun je LEDjes laten knipperen. En aangezien een aantal LEDjes meerdere kleuren ondersteunen kun je lopen kloten met de kleuren zodat het net eerst kerstboom wordt, hiervoor heb ik het volgende bash script geschreven:

#!/usr/bin/env bash
# shellcheck disable=SC1001

BRIGHTNESS=/sys/class/leds/chromeos\:multicolor\:power/brightness
TRIGGER=/sys/class/leds/chromeos\:multicolor\:power/trigger
COLOR=/sys/class/leds/chromeos\:multicolor\:power/multi_intensity
NAP="${1:-20}"
DELAY_ON="${2:-500}"
DELAY_OFF="${3:-500}"

trap ctrl_c INT

ctrl_c() {
	# When the user presses Control+C to stop the multicolor
	# madness return stuff to normal
	echo 'Stopping the multicolor madness. Bye.'
	echo chromeos-auto > ${TRIGGER}
	exit 0
}

bootstrap() {
	echo timer > ${TRIGGER}
	echo ${DELAY_ON} > /sys/class/leds/chromeos\:multicolor\:power/delay_on
	echo ${DELAY_OFF} > /sys/class/leds/chromeos\:multicolor\:power/delay_off
}

if [[ $(lsmod | grep -c ledtrig_timer) -eq 0 ]]; then
	modprobe ledtrig_timer
fi

if [[ -d /sys/class/leds/chromeos\:multicolor\:power/ ]]; then
	echo 100 > ${BRIGHTNESS}
	echo timer > ${TRIGGER}
	
	echo 'Blink blink'
	
	while true; do
		# Loop through all colors the Framework 13's power button LED supports.
		# Oddly it reports 'red', 'green', 'blue', 'yellow', 'white', 'amber'
		# but blue does *not* work.
		
		# Red
		echo "... red"
		echo 100 0 0 0 0 0 > ${COLOR}
		bootstrap
		sleep ${NAP}
	
		# Green
		echo "... green"
		echo 0 100 0 0 0 0 > ${COLOR}
		bootstrap
		sleep ${NAP}
		
		# Yellow
		echo "... yellow"
		echo 0 0 0 100 0 0 > ${COLOR}
		bootstrap
		sleep ${NAP}
		
		# White
		echo "... white"
		echo 0 0 0 0 100 0 > ${COLOR}
		bootstrap
		sleep ${NAP}
		
		# Amber
		echo "... amber"
		echo 0 0 0 0 0 100 > ${COLOR}
		bootstrap
		sleep ${NAP}
	done
else
	echo 'This system does not appear to have the required LED interface(s). Is this a Framework 13 laptop with the correct kernel and firmware versions?'
	exit 1
fi