aime-iphone-route.sh v1 hat seit dem Reboot am 29.07. nie gegriffen (0 Zeilen in journalctl -t aime-iphone-route über den ganzen Boot). Zwei Gründe: 1. Die Portnamen waren hartcodiert auf input_FL/input_FR. HFP/mSBC ist mono, die Ports heißen playback_MONO/capture_MONO — der grep matchte nie. 2. Der Guard "micgate.out schon verlinkt -> überspringen" war einmal pro Anruf. WirePlumber legt die HFP-Nodes nicht atomar an, der Uplink erscheint vor der Gegenseite. War bluez_input in genau diesem Durchlauf noch nicht da, wurde die Gegenseite für den ganzen Anruf nicht mehr nachverlinkt. Ein erst mitten im Anruf gesetztes callrec_mix->Uplink wurde ebenso nie entfernt. Folge: Gegenseite -> callmix fehlte (nicht in der Aufnahme, #80/#81 hatten je nur 1 Sprecher) und der Uplink führte den ungegateten Mix statt micgate.out, also wieder das Echo von vor dem Fix am 13.07. v2 ermittelt die Portnamen über pw-link -i/-o und prüft alle drei Links in jedem Durchlauf einzeln nach. link_all legt genau einen Link pro Ziel-Port an: eine Mono-Quelle speist beide Kanäle, eine Stereo-Quelle auf einem Mono-HFP-Port sendet nur FL, weil beide Links in denselben Port summieren würden (+6 dB Uplink). Gegenprobe am echten Anruf steht noch aus.
4.0 KiB
06 — iPhone-Telefonate über Bluetooth (HFP)
Das Board gibt sich gegenüber dem iPhone als Bluetooth-Headset aus („Aime“, AX210/hci0). iPhone-Anrufe
laufen dadurch über das Board: Gegenseite → Aufnahme-Mix, Nutzer-Mikrofon (gegated) → iPhone-Uplink.
Läuft parallel zum PC/USB-Gadget-Pfad — kein Umschalten; bei eingehendem Anruf pausiert der Nutzer sein
PC-Video manuell.
Konfiguration (die funktionierende Kombination)
- WirePlumber-Drop-in:
bluez5.roles = [a2dp_sink hfp_hf hsp_hs]+hfphsp-backend = native(oFono war ein Irrweg, deaktiviert). - Frischer Pair nötig (auf dem iPhone „Gerät ignorieren“, dann neu koppeln) — alte Bonds machen Ärger.
- iPhone „Skynet16“ (B4:96…), bt-agent NoInputNoOutput, Gerät muss Trusted=yes sein (nach Re-Pair stand es auf NO → WirePlumber baut für untrusted Geräte keine HFP-Nodes → Aufnahme #58 hatte nur die Nahseite).
- Einziger Verzicht: BT-Ohrhörer als Aufnahmegerät (AG-Rolle) ist aus — Board ist HF-only.
profile="off"zwischen Anrufen ist normal: HFP-Nodes existieren nur während eines aktiven Anrufs (eSCO/mSBC, 16 kHz).
Audio-Routing während eines Anrufs
flowchart LR
subgraph IPHONE["iPhone (im Anruf)"]
CALL["Telefonat"]
end
subgraph BOARD["Board (BT 'Aime')"]
FAR["bluez_input.MAC.0<br/>= Gegenseite"]
UP["bluez_output.MAC.1<br/>= Uplink zum iPhone"]
MIX[("callmix")]
GATE["micgate.out (gegatetes Mikro)"]
HS["Headset-Hörer"]
end
CALL --> FAR
FAR --> MIX
FAR --> HS
GATE --> UP --> CALL
Echo-Fix: WirePlumber verlinkte den Uplink zunächst mit callrec_mix (ungegatetes Mikro + Gegenseite
selbst!) → Gegenseite hörte sich selbst. Korrekt: Uplink ← micgate.out. Vom Nutzer bestätigt echofrei.
Gegenseite → Headset-Hörer macht WirePlumber selbst (Default-Sink); der Watcher baut diesen Link
nicht. callmix ist eine reine Aufnahme-Senke ohne Ausgang — Gegenseite → callmix macht die Gegenseite
also aufnehmbar, nicht hörbar.
Automatik
sequenceDiagram
participant IP as iPhone
participant BZ as BlueZ/WirePlumber
participant W as aime-iphone-route.sh (Watcher, 1 s Takt)
participant PW as PipeWire
IP->>BZ: Anruf beginnt (eSCO aufgebaut)
BZ->>PW: HFP-Nodes erscheinen — NICHT atomar, Uplink oft vor Gegenseite
BZ->>PW: Gegenseite → Headset-Hörer (WirePlumber-Default)
loop jede Sekunde, solange Uplink-Node existiert
W->>PW: Portnamen ermitteln (HFP = mono, playback_MONO/capture_MONO)
W->>PW: callrec_mix → Uplink trennen, falls vorhanden (Echo-Quelle)
W->>PW: Uplink ← micgate.out verlinken, falls fehlt
W->>PW: Gegenseite → callmix verlinken, falls fehlt (Node kommt später!)
end
IP->>BZ: Anruf endet
BZ->>PW: HFP-Nodes verschwinden (profile=off — normal)
- Watcher persistent:
/opt/callrec/aime-iphone-route.sh+aime-iphone-route.service; überlebt Reboots (Config/Service/Bond+Trusted verifiziert). - Der Watcher-Neustart lässt callmix/Loopbacks intakt.
- Jeder Link wird in JEDEM Durchlauf geprüft, nicht einmal pro Anruf — siehe Changelog 2026-07-30.
- Portnamen werden ermittelt, nicht hartcodiert. HFP/mSBC ist mono, die Ports heißen
playback_MONO/capture_MONO, nichtinput_FL/input_FR. - Kontrolle nach einem Anruf:
journalctl -t aime-iphone-route. Keine Zeile = der Watcher hat nichts getan und die Aufnahme enthält nur die Nahseite.
Offen
- App-seitiger automatischer Aufnahme-Start bei iPhone-Anrufen.
- Voller E2E-Test „Anruf → Aufnahme → Analyse“ über den BT-Pfad.
Referenz: BT-Bond-Quirks (Ohrhörer, historisch)
Buds mit No-Bonding-Quirk: LinkKey musste manuell in /var/lib/bluetooth persistiert werden
(btmon-Capture-Prozedur). RTL8821CU-Wedge-Recovery (USB-Reset, nur über LAN .50) — betrifft den alten
Dongle, der entfernt wurde; nur noch relevant, falls die Hardware zurückkommt.