Reparatur des Lagesensors unter Linux für die automatische Bildschirmorientierung

twoexem

Member
Original poster
25 April 2024
9
Hattingen
Hallo Gemeinde!
Ich besitze schon seit knapp 2 Jahren ein SHIFTbook (bzw. SHIFT13mi), und die fehlende Funktion des Lagesensors unter Linux hat mich immer schon gestört. Da ich heute etwas Zeit hatte, habe ich mich mal reingehangen und geschaut, woran's lag.

Das Problem lag an sich an einer falschen Hardware-ID. Der Kernel liest beim Starten den DSDT aus, um die Geräte, die im Rechner verbaut sind, zu identifizieren. Diese werden anschließend dem Betriebssystem zur Verfügung gestellt, und udev ordnet den modalias-Pseudonamen die richtigen Module zu.
Der im SHIFTbook verbaute Lagesensor, ein STM LSM6DSO, ist im DSDT des Gerätes als SMOCF00 vermerkt.
Wenn wir uns mal den Quelltext des Sensor-Kommunikationsmoduls im Linux-Kernel anschauen, merken wir aber:
static const struct acpi_device_id st_lsm6dsx_i2c_acpi_match[] = {
{ "SMO8B30", ST_LSM6DS3TRC_ID, },
{ }
};
Der Linux-Treiber erkennt nur Geräte mit der ID SMO8B30 als Lagesensor. Dadurch wird der eingebaute Lagesensor nicht als solcher erkannt und ignoriert.
Man muss nun den Struct acpi_device_id ändern, damit der Treiber auch wirklich den Sensor identifizieren kann. Das ist relativ simpel. Der geänderte Struct ist:
static const struct acpi_device_id st_lsm6dsx_i2c_acpi_match[] = {
{ "SMO8B30", ST_LSM6DS3TRC_ID, },
{ "SMOCF00", ST_LSM6DSO_ID, },
{ }
};
Wenn man nun die relevante Source-datei st_lsm6dsx_i2c.c in ein Modul kompiliert, dieses anschließend zstd-komprimiert und das alte Modul überschreibt, funktioniert auch der Lagesensor so halb, erkennt aber noch nicht die richtige Bildschirmorientierung. Wenn man das Tablet normal hält, denkt der Sensor, dass das Gerät auf dem Kopf steht und dreht den Bildschirm entsprechend.
Um diesen Fehler zu beheben, muss man noch die Rotationsmatrix ändern. Die sorgt dafür, dass der Sensor richtig erkennt, wo oben und unten sind. Diese sind eigentlich schon im DSDT vorhanden, werden aber nicht ausgelesen, da diese nicht standardisiert sind. Zum beheben dieses Problems muss man im Verzeichnis /etc/udev/hwdb.d/ eine neue hwdb-Datei erstellen. Ich habe meine ganz simpel 10-sensor-shiftbook.hwdb genannt. In diese muss nun:
sensor:modalias:acpi:SMOCF00:*
ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
Damit wird udev mitgeteilt, wie die Orientierungsdaten des Beschleunigungssensors zu interpretieren sind. Anschließend über systemd-hwdb update und udevadm trigger die neuen Parameter einlernen und evtl. noch den iio-Service neustarten.

Ich habe ein Ubuntu-Paket erstellt, welches den Rotationssensor unter Ubuntu wieder zum Laufen bringt. Installationsanleitung ist weiter unten in einer Antwort. Dieses Paket ist nur wichtig, solange das Kernel-Patch noch nicht veröffentlicht wurde.

Hier einmal der Buildprozess für Arch Linux:
0. Erst einmal die relevanten Pakete installieren:
# pacman -S linux-headers iio-sensor-proxy
und anschließend in ein sauberes Arbeitsverzeichnis wechseln.
1. Einmal die relevante Dateien heruntergeladen:
WICHTIG: Ersetzt bitte die Version (aktuell 6.19.8) durch eure eigene. Führt dafür einmal uname -r aus und fügt dann die Version OHNE den letzten Strich und ohne 1 ein.
Heißt also: 6.19.8-arch1-1 wird zu 6.19.8-arch1
$ curl -O "https://raw.githubusercontent.com/archlinux/linux/v6.19.8-arch1/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c"
$ curl -O "https://raw.githubusercontent.com/archlinux/linux/v6.19.8-arch1/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h"
$ curl -O "https://raw.githubusercontent.com/archlinux/linux/v6.19.8-arch1/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c"
$ curl -O "https://raw.githubusercontent.com/archlinux/linux/v6.19.8-arch1/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c"
$ curl -O "https://raw.githubusercontent.com/archlinux/linux/v6.19.8-arch1/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c"

2. Mit dem Texteditor deiner Wahl die Datei st_lsm6dsx_i2c.c bearbeiten. Relevant sind die Zeilen 145-148. Wie oben schon erwähnt, einmal die weitere Zeile einfügen.

3. Eine Datei namens ”Makefile” erstellen und mit einem Texteditor folgenden Inhalt einfügen:
obj-m += st_lsm6dsx.o st_lsm6dsx_i2c.o
st_lsm6dsx-objs := st_lsm6dsx_core.o st_lsm6dsx_buffer.o st_lsm6dsx_shub.o

all:
make -C /usr/lib/modules/$(shell uname -r)/build M=$(PWD) modules

install:
zstd -f st_lsm6dsx_i2c.ko -o st_lsm6dsx_i2c.ko.zst
cp st_lsm6dsx_i2c.ko.zst /usr/lib/modules/$(shell uname -r)/kernel/drivers/iio/imu/st_lsm6dsx/
depmod -A

clean:
make -C /usr/lib/modules/$(shell uname -r)/build M=$(PWD) clean

WICHTIG: Die Indents müssen durch Tab erzeugt werden, nicht durch Leerzeichen. Die Forumsformatierung könnte das etwas kaputtmachen. Ersetzt daher bitte bei Fehlern die Einrückungen durch Tab-Einrückungen.

4. Die geänderte Datei kompilieren:
# make

5. Das fertige Modul installieren:
# make install

6. Neue Datei /etc/udev/hwdb.d/10-sensor-shiftbook.hwdb erzeugen und den folgenden Inhalt mit einem Texteditor einfügen:
sensor:modalias:acpi:SMOCF00:*
ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
WICHTIG: Das erste Leerzeichen in der zweiten Zeile muss ein Leerzeichen sein.

Jetzt könnt ihr entweder das Tablet neu starten oder diese Befehle ausführen:

(7). Das alte laufende Modul neu laden:
# modprobe -r st_lsm6dsx_i2c
# modprobe st_lsm6dsx_i2c

(8). Alle wichtigen Dienste neustarten:
# systemd-hwdb update
# udevadm trigger
# systemctl restart iio-sensor-proxy

Anschließend sollte der Lagesensor wieder ohne Probleme funzen.

WICHTIG: Diese Methode ist NICHT permanent und muss nach jedem Kernel-Update neu durchgeführt werden, oder so lange, bis diese Änderung im Mainline-Kernel angekommen ist.

Ich kann leider nichts über den Build-Prozess auf anderen Distros sagen, da ich persönlich nur Arch Linux nutze. Ich werde aber mal einen Kernel-Patch bemühen, über den auch der Lagesensor im Shiftbook erkannt werden sollte. Ist ja, wie man oben sieht, nur ein simpler Einzeiler ohne großartige Änderungen.

Getestet wurde dieser Fix auf Arch Linux mit KDE Plasma.

Lasst gerne Feedback da.
 
Zuletzt bearbeitet:
Vielleicht Offtopic: dazu fällt mir ein Zitat aus diesem Video ein: der Kernel ist so eingestellt, dass er durchschnittlich ist um möglichst für viele Geräte zu funktionieren. Um die Fähigkeiten des Linuxkernels wirklich nutzen zu können, muss man ihn an sein Gerät anpassen.

Vielleicht gibt es ja Anleitungen um deine Änderungen persistent oder leichter wiederherstellbar zu machen.
 
Vielleicht Offtopic: dazu fällt mir ein Zitat aus diesem Video ein: der Kernel ist so eingestellt, dass er durchschnittlich ist um möglichst für viele Geräte zu funktionieren. Um die Fähigkeiten des Linuxkernels wirklich nutzen zu können, muss man ihn an sein Gerät anpassen.

Vielleicht gibt es ja Anleitungen um deine Änderungen persistent oder leichter wiederherstellbar zu machen.
Soweit ich weiß, nein. Hier ist vor allem die Unvollständigkeit das Problem. Die Kombination aus der speziellen Hardware-ID und dem Gerät ist so halt vorher auf keinem anderen Gerät da gewesen, weshalb das nicht im Mainline-Treiber drinne ist. Das kann man nicht ändern, ohne den Quellcode des Treibers wie oben zu ändern, damit der Treiber weiß, mit welcher Hardware-ID er arbeiten muss.
Das ganze macht man mit 'nem Mainline-Patch persistent. Ich habe schon eine Patch-Einreichung an die Kernel-Mailing-List übermittelt. Wenn das so in ein paar Wochen akzeptiert wird, werden also eh alle SHIFTbooks, die mit Linux laufen, beim nächsten Kernel-Update einen laufenden Bildschirmsensor besitzen, ohne, dass der Nutzer selbst was anderes als das Update machen muss, unabhängig von der Distribution. Manche Distros wie Debian oder Ubuntu bekommen nicht so häufig Kernel-Updates wie bspw. Arch Linux, deswegen könnte es länger dauern, bis es bei Debian angekommen ist als bei Arch.
 
  • Like
Reaktionen: halemmerich und tkopq
Vielleicht Offtopic: dazu fällt mir ein Zitat aus diesem Video ein: der Kernel ist so eingestellt, dass er durchschnittlich ist um möglichst für viele Geräte zu funktionieren. Um die Fähigkeiten des Linuxkernels wirklich nutzen zu können, muss man ihn an sein Gerät anpassen.

Vielleicht gibt es ja Anleitungen um deine Änderungen persistent oder leichter wiederherstellbar zu machen.
Ich habe 'ne andere Idee, das ganze für Nutzer einfacher zu machen. Werde mich mal gleich ransetzen und 'n DKMS-Packet erstellen. Dann kann sich jeder das Paket installieren und hat (bis das Patch im Ubuntu-Release-Cycle angekommen ist) einen funktionierenden Lagesensor.
 
  • Love
  • Like
Reaktionen: Dwain Zwerg und tkopq
@tkopq
Sooo, das wäre erledigt. Öffentliches Repo läuft auf apt.twoexem.com.

Installationsanleitung:
1. GPG-Schlüssel importieren:
curl https://apt.twoexem.com/key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/twoexem.gpg
2. Apt-Quelle hinzufügen:
echo "deb [signed-by=/etc/apt/keyrings/twoexem.gpg] https://apt.twoexem.com stable main" | sudo tee /etc/apt/sources.list.d/twoexem.list
3. Programm installieren:
sudo apt update
sudo apt install st-lsm6dsx-shift13mi

Hab's gerade auf der Live-Version vom generischen Ubuntu-Installer probiert, und es läuft. Keine Garantie für nix. Den Secure-Boot-Teil habe ich noch nicht ausprobiert.

Für alle misstrauischen: Der Quellcode vom Paket ist unter https://git.twoexem.com/twoexem/st-lsm6dsx-shift13mi/ einsehbar.
 
So, noch ein paar kleine Fehlerchen behoben. Jetzt sollte's klappen.

Für Secure Boot-Benutzer:
Es wird nach der Installation ein Passwort vom Benutzer gesetzt. Dieses wird beim Neustart vom BIOS abgefragt, damit das Modul importiert werden kann.

Bitte schreibt, ob und wie es bei euch geklappt hat. Da ich keine Möglichkeit habe, Secure Boot zu testen, kann ich leider nicht selbst verifizieren, ob und wie das Paket mit Secure Boot mit diesem Programm funktioniert.
 
Zuletzt bearbeitet:
Kleines Update: Das Repositorium beinhaltet nun auch detaillierte Build-Anleitungen für Ubuntu und andere Distributionen.

Der Kernel-Patch ist auch weitergekommen und wurde vom Maintainer reviewed. Jetzt muss das ganze nur noch durch den IIO-Maintainer akzeptiert werden.
 
Und noch ein kleines Update: Das Patch ist offiziell im Linux-Kernel angekommen, siehe:
1774798331211.png

Heißt, das Patch wird im Kernel 7.1 vorhanden sein. Kernel 7.1 wird wohl so gegen Juni or Juli veröffentlicht werden und dann auch irgendwann im Ubuntu-Kernel ankommen. Sobald das passiert ist, ist auch mein Paket nicht mehr nötig.