Skip to content

fix: connect A2DP after pairing and enable JustWorksRepairing for BT headsets#730

Open
carroarmato0 wants to merge 5 commits into
LoveRetro:mainfrom
carroarmato0:fix/bluetooth-headset-disconnect
Open

fix: connect A2DP after pairing and enable JustWorksRepairing for BT headsets#730
carroarmato0 wants to merge 5 commits into
LoveRetro:mainfrom
carroarmato0:fix/bluetooth-headset-disconnect

Conversation

@carroarmato0
Copy link
Copy Markdown

@carroarmato0 carroarmato0 commented May 19, 2026

Summary

  • PLAT_bluetoothPair() now calls bluetoothctl connect after bluetoothctl pair so the A2DP audio profile is opened immediately after bonding. Without this, earbuds time out (~2 s) waiting for the host to initiate the audio channel and disconnect themselves (BlueZ reason 2 = remote terminated).
  • bt_init.sh now sets JustWorksRepairing = always in main.conf before starting bluetoothd. The XRadio BT controller firmware generates link keys with store_hint=0, so BlueZ never persists the key to disk. After a sleep/wake cycle the key is gone; with JustWorksRepairing=never (the BlueZ default) earbuds can't reconnect without the user re-pairing manually. Setting it to always lets the earbuds re-initiate the bond from their side on wake.

Fixes #467 (no sound after sleep when using BT headphones).

Root cause

The XRadio chip used in TrimUI devices sets store_hint=0 in the MGMT NEW_LINK_KEY event. BlueZ respects this flag and skips writing [LinkKey] to the device info file, so the device is never considered Paired=true. This means:

  1. After pairing, nothing triggers an A2DP connection → earbuds disconnect in ~2 s.
  2. After sleep/wake, the controller's volatile key memory is cleared and BlueZ rejects reconnect attempts from the earbuds.

Files changed

File Change
workspace/all/common/generic_bt.c Add bluetoothctl connect after bluetoothctl pair in PLAT_bluetoothPair()
skeleton/SYSTEM/tg5040/etc/bluetooth/bt_init.sh Patch main.conf to JustWorksRepairing=always before bluetoothd starts
skeleton/SYSTEM/tg5050/etc/bluetooth/bt_init.sh Same patch for tg5050

I've tested this using my Raycon Earbuds and seems to work reliably. Before this fix the earbuds would simply not connect (or get disconnected immediately)

carroarmato0 and others added 2 commits May 19, 2026 14:04
…dsets

The XRadio BT controller firmware generates link keys with store_hint=0,
meaning BlueZ never persists the key to disk. This caused two symptoms:

1. Earbuds disconnect ~2s after pairing: after the BR/EDR bond completes,
   nothing initiates the A2DP audio profile connection. The earbuds time
   out waiting for the host to open the audio channel and disconnect
   (reason 2 = remote terminated). Fixed by calling `bluetoothctl connect`
   immediately after `bluetoothctl pair` in PLAT_bluetoothPair().

2. No sound after sleep/wake (fixes LoveRetro#467): bt_init.sh stop/start clears
   the controller's volatile key memory. On wake, earbuds try to reconnect
   but BlueZ rejects them (no stored key, JustWorksRepairing=never default).
   Fixed by patching main.conf to set JustWorksRepairing=always before
   bluetoothd starts, allowing earbuds to re-initiate the bond from their
   side without user interaction.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
tg5050 (TrimUI Smart Pro S) uses an AIC8800 BT chip, not XRadio.
Remove the chip-specific attribution from the comment so it accurately
describes the symptom rather than incorrectly referencing XRadio.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@carroarmato0 carroarmato0 marked this pull request as draft May 19, 2026 13:19
@carroarmato0 carroarmato0 marked this pull request as ready for review May 19, 2026 13:19
carroarmato0 and others added 2 commits May 19, 2026 17:42
When earbuds power off abruptly, BlueZ may have already cleared the
device's service cache by the time audiomon processes the disconnect
signal. The previous hasUUID() call on disconnect would return false
in that race, silently skipping the audio switch-back to the internal
speaker.

Fix by caching the connected A2DP device MAC at connect time and
comparing against it on disconnect, avoiding the BlueZ query entirely.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…witch

ALSA caches its PCM configuration. After BT disconnects and .asoundrc is
deleted, setting AUDIODEV=default still resolves through the cached config
which may still point to bluealsa — causing SDL to open a dead PCM and
producing no or garbled audio from the speaker.

Fix by naming both endpoints explicitly, matching the same pattern already
used for BT (bluealsa):
- Speaker: plughw:0  (card 0, with format/rate conversion)
- USB DAC: plughw:1  (card 1, with format/rate conversion)
- Bluetooth: bluealsa (unchanged)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Comment thread workspace/all/minarch/ma_audio.c Outdated
// .asoundrc is deleted. Name both endpoints explicitly to bypass the cache.
if (device == AUDIO_SINK_BLUETOOTH)
SDL_setenv("AUDIODEV", "bluealsa", 1);
else if (device == AUDIO_SINK_USBDAC)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cant rely on that order. Example:

  • USB-C device connected on boot, might enumerate as card 0
  • As a result, internal speaker comes up as card 1 (even after disconnecting the usb device).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

No sound after sleep mode when using bt headphones.

2 participants