Unter Linux kann man einige Treiber-Einstellungen über sysfs
, ein vom Kernel
bereitgestelltes Pseudo-Dateisystem, erledigen. Auf meinem ThinkPad kann ich
darüber beispielsweise einstellen, wie schnell mein Trackpoint reagieren soll
oder ab welchem Füllstand mein Akku geladen werden soll (damit er nicht gleich
wieder einen Ladezyklus anfängt, wenn ich ihn 5 Minuten nicht am Strom habe).
Diese Einstellungen nimmt man zur Laufzeit z.B. folgendermaßen vor:
# echo 75 > /sys/devices/platform/smapi/BAT0/start_charge_thresh
Nach einem Neustart sind sie natürlich verloren, denn der Kernel hält sie nur
im Speicher. Daher gibt es unter Debian das Paket sysfsutils
, welches
die Möglichkeit bot, diese Einstellungen in /etc/sysfs.conf
zu
konfigurieren. Beim Systemstart wurden diese über ein Init-Script dann nach
/sys
übertragen.
Probleme
Mit diesem Ansatz stimmen mehrere Sachen nicht:
- Die Einstellungen werden an einem „beliebigen“ Zeitpunkt beim Systemstart gesetzt, nämlich dann, wenn das Initscript an der Reihe ist. Für die oben genannte Batterie-Einstellung ist das möglicherweise schon zu spät, das heißt, der Ladezyklus wurde bereits angefangen.
-
Dadurch, dass es ein Script ist, verzögert es den Systemstart mit
systemd
(welcher ansonsten keine Shellscripts mehr benutzt). Die Verzögerung ist zwar minimal, aber es geht ums Prinzip… :-) -
Der Mechanismus ist distributions-spezifisch, was schlecht ist. Generell gibt
es auf allen Linux-Distributionen
/sys
und es ist unnötig, mehrere verschiedene Mechanismen zu haben. - Der wichtigste Punkt ist aber, dass die Einstellungen nicht greifen, wenn man neue Geräte anschließt oder angeschlossene Geräte entfernt und wieder anschließt. Das ist bei USB-Geräten beispielsweise relativ üblich, kann aber auch mit Akkus passieren (ich habe zwei).
Die Lösung: udev-Regeln
Besser wäre es also, die Einstellungen dann zu setzen, wenn das Gerät
tatsächlich im System auftaucht – und was könnte dafür besser geeignet sein als
udev
?
Nehmen wir also das Beispiel von oben, mit der Akku-Einstellung. Zunächst suchen wir uns das passende udev-Gerät. Dazu fangen wir mit dem Pfad an, unter dem die entsprechende sysfs-Datei liegt:
# udevadm info -p /sys/devices/platform/smapi/BAT0 -a device path not found
Das hat nicht geklappt, also probieren wir es eine Ebene höher. Es gilt die
Faustregel: Jeder Ordner, der eine uevent
-Datei enthält, repräsentiert
ein Gerät.
# udevadm info -p /sys/devices/platform/smapi/ -a looking at device '/devices/platform/smapi': KERNEL=="smapi" SUBSYSTEM=="platform" DRIVER=="smapi" ATTR{ac_connected}=="1" looking at parent device '/devices/platform': KERNELS=="platform" SUBSYSTEMS=="" DRIVERS==""
Hierbei werden alle Attribute angezeigt, die man in einer udev-Regel matchen kann. Hierbei werden also nicht alle Attribute angezeigt, es fehlen diejenigen, die man nur beschreiben kann.
Wir legen nun die Datei /etc/udev/rules.d/11-battery.rules
mit folgendem Inhalt an:
# start charging as soon as the battery is below 75% capacity ACTION!="remove",SUBSYSTEM=="platform",DRIVER=="smapi", \ ATTR{BAT0/start_charge_thresh}="75"
Das bedeutet, dass für den smapi-Treiber bei allen Aktionen außer dem Entfernen
die Einstellung BAT0/start_charge_thresh
auf 75
gesetzt wird.
Wir testen diese Regel nun folgendermaßen:
# udevadm test /sys/devices/platform/smapi udev_rules_new: rules use 216324 bytes tokens (18027 * 12 bytes), 28809 bytes buffer udev_rules_new: temporary index used 52580 bytes (2629 * 20 bytes) udev_device_new_from_syspath: device 0x7f4c810df170 has devpath '/devices/platform/smapi' udev_device_new_from_syspath: device 0x7f4c810eebe0 has devpath '/devices/platform/smapi' udev_device_read_db: no db file to read /run/udev/data/+platform:smapi: No such file or directory udev_rules_apply_to_event: ATTR '/sys/devices/platform/smapi/BAT0/start_charge_thresh' writing '75' /etc/udev/rules.d/11-battery.rules:6 udev_device_new_from_syspath: device 0x7f4c810ec4e0 has devpath '/devices/platform' udev_rules_apply_to_event: RUN 'socket:@/org/freedesktop/hal/udev_event' /lib/udev/rules.d/90-hal.rules:2
Dabei achten wir auf die Zeile, die mit udev_rules_apply_to_event:
ATTR
beginnt: Sie zeigt uns an, dass unsere Regel wohlgeformt ist und die
Einstellung gesetzt wurde. Anschließend kann man mit cat
/sys/devices/platform/smapi/BAT0/start_charge_thresh
nochmal nachschauen
und wird feststellen, dass der Wert korrekt gesetzt wurde.
Nun deinstalliert man sysfsutils
und freut sich über einen schnelleren
Systemstart ;-).
Meine udev-Regeln
$ cat /etc/udev/rules.d/10-trackpoint.rules ACTION!="remove",SUBSYSTEM=="serio",DRIVER=="psmouse",ATTR{sensitivity}="150",ATTR{speed}="150" $ cat /etc/udev/rules.d/11-battery.rules # start charging as soon as the battery is below 75% capacity # wait 2 minutes before charging to make battery changes easy ACTION!="remove",SUBSYSTEM=="platform",DRIVER=="smapi", \ ATTR{BAT0/start_charge_thresh}="75", \ ATTR{BAT0/inhibit_charge_minutes}="2"
I run a blog since 2005, spreading knowledge and experience for almost 20 years! :)
If you want to support my work, you can buy me a coffee.
Thank you for your support! ❤️