Files
onyx/docs/spikes/A-smc.md
Guido Schmit 41ee3cc174 Phase 0: Repo-Gerüst und vier Verifikations-Spikes
Vier Annahmen des Plans vor jedem Implementierungscode geprüft:

A (SMC):  Lüftersteuerung bestätigt — F0md/F1md (klein!) als Auto/Manuell-
          Umschalter, F0Tg als Ziel, Grenzen aus F0Mn/F0Mx. SMC-Integer sind
          little-endian, nicht big-endian wie im verbreiteten Intel-Beispielcode.
          Ladelimit: CHWA/CH0B/CH0C/bfE0/bfF0 existieren auf Mac17,9 nicht.
          Key noch nicht identifiziert, deshalb smc-diff.sh für eine
          Differenzmessung ohne jeden Schreibzugriff.
B (Media): mediaremote-adapter läuft unter 26.6.1, aus dem Quellcode gebaut.
          Liefert vollständige Metadaten inkl. Cover aus Google Chrome — der
          Fall, den AppleScript nicht erreicht.
C (Audio): Process Tap + privates Aggregate-Device liefern echte Samples
          (469 Callbacks/5 s, 0 stille Puffer). Konflikt gefunden: SoundSource
          6.1.1 mit ARK.driver ist bereits installiert.
D (Group): App-Group-Container ist aus einem nicht-sandboxed Prozess erreichbar.
          Damit trägt die Sandbox-Entscheidung, die Bridge-App entfällt.

Spikes sind Wegwerfcode zur Verifikation, kein Produktionscode.
2026-08-10 16:47:54 +02:00

4.0 KiB
Raw Blame History

Spike A — SMC-Keys auf Mac17,9 (M5 Pro)

Gemessen am 10.08.2026, macOS 26.6.1 (25G76), ohne root, ausschließlich lesend. Werkzeug: Spikes/smc-dump.swift. 3486 Keys insgesamt.

Ergebnis in einem Satz

Lüftersteuerung: bestätigt und umsetzbar. Ladelimit: Key noch nicht identifiziert — das Standardverfahren aus AlDente/batt greift auf dieser Maschine nicht, weil die dort benutzten Keys schlicht nicht existieren.

Wichtige Querbefunde

SMC-Integer sind little-endian. Meine erste BE-Dekodierung ergab Unsinn (Akkuspannung 31023 mV). LE ergibt konsistente Werte, zweifach gegengeprüft:

Key Roh LE-Wert Gegenprobe
B0AV AA 2F 12202 mV plausible Zellspannung
CH0V AA 2F 00 00 12202 mV identisch zu B0AV
B0AC 85 FD 635 mA entlädt; passt zu PMVR = 0 W (kein Netzteil)
PPBR 12,13 W ≈ 12,2 V × 0,64 A ✓

flt-Keys sind ebenfalls little-endian IEEE-754. Für die Implementierung heißt das: alle Mehrbyte-SMC-Werte little-endian lesen, entgegen dem verbreiteten Beispielcode, der big-endian annimmt (der stammt aus der Intel-Ära).

Lüfter — vollständig nutzbar

Zwei Lüfter vorhanden (FNum = 2).

Key Typ Wert Bedeutung
F0md / F1md ui8 0 Modus: 0 = auto, 1 = manuell
F0Tg / F1Tg flt 2317 / 2502 Ziel-Drehzahl
F0Ac / F1Ac flt 2321 / 2499 Ist-Drehzahl
F0Mn / F1Mn flt 2317 Minimum
F0Mx / F1Mx flt 7826 Maximum
F0St / F1St ui8 5 Status
FEna hex 07 Freigabe-Bitmaske

Korrektur zur Planannahme: der Modus-Key heißt F0md klein geschrieben, nicht F0Md. Mit der Großschreibung aus der Intel-Dokumentation findet man ihn nicht — genau deshalb lief dieser Spike vor dem Implementierungscode.

FS! (die alte Force-Bitmaske) existiert nicht. Der Weg ist also: F0md = 1F0Tg = Wunschdrehzahl, zurück auf Automatik mit F0md = 0.

Der Sicherheitsrahmen aus dem Plan lässt sich damit sauber umsetzen: F0Mn/F0Mx liefern die harten Grenzen direkt aus der Firmware, und F0md = 0 ist ein einzelner, immer verfügbarer Rückfallbefehl.

Ladelimit — noch offen

Nicht vorhanden: CHWA, CH0B, CH0C, CH0I, CH0J, CH0K, BCLM, bfE0, bfF0.

Damit scheiden sowohl das AlDente-Legacy-Verfahren (CH0B/CH0C) als auch das 80-%-Flag (CHWA) als auch das vollständige Firmware-Backend (bfD0/bfE0/bfF0) aus — von letzterem existiert nur bfD0 (hex, 2 Byte, 00 00).

Vorhanden ist stattdessen ein umfangreicher CH*-Satz. Plausible Kandidaten:

Key Typ Wert (LE) Vermutung
CHTE ui32 0 Ladeziel — 0 könnte „kein Limit" heißen
CHTL ui32 3600 untere Schwelle?
CHTU ui32 4100 obere Schwelle? (mV je Zelle)
CHBV ui32 4125 Ladeschlussspannung mV
CHIL / CHIO flag false Inhibit-Flags
CHSE / CHST / CHRT ui8 0 Status/Steuerung

Das bleibt Vermutung, und Vermutungen werden hier nicht geschrieben. Ein falscher Wert im Lade-Subsystem ist die eine Operation in diesem Projekt, die Hardware dauerhaft beschädigen kann.

Nächster Schritt: Differenzmessung statt Raten

macOS hat selbst eine Ladebegrenzung (Systemeinstellungen → Batterie → Batteriezustand → „Optimiertes Laden" bzw. das 80-%-Limit). Wird sie umgeschaltet, muss sich der zuständige SMC-Key ändern. Spikes/smc-diff.sh nimmt zwei vollständige Dumps auf und zeigt die Differenz — damit ist der Key ohne einen einzigen Schreibzugriff identifizierbar.

Bis dieser Test gelaufen ist, bleibt die Akkukarte reine Anzeige.

Auswirkungen auf den Plan

  1. Phase 6 wird geteilt: Lüftersteuerung kann gebaut werden, das Ladelimit wartet auf die Differenzmessung.
  2. Alle SMC-Werte werden little-endian gelesen — betrifft MetricsProvider und OnyxHelper.
  3. F0Mn/F0Mx werden zur Laufzeit aus der Firmware gelesen statt fest verdrahtet.
  4. Lüfterdrehzahlen sind flt, nicht fpe2.