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

91 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 = 1``F0Tg = 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`.