Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions skeleton/SYSTEM/tg5040/etc/bluetooth/bt_init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ start_bt() {
start_hci_attach
fi

# Allow headsets to auto-reconnect without user re-pairing.
# XRadio BT firmware sets store_hint=0, so link keys are never
# persisted; JustWorksRepairing=always lets earbuds re-initiate
# the bond from their side after a reboot.
if ! grep -q 'JustWorksRepairing = always' /etc/bluetooth/main.conf 2>/dev/null; then
sed -i 's/.*JustWorksRepairing.*/JustWorksRepairing = always/' /etc/bluetooth/main.conf 2>/dev/null
fi

# Start bluetooth daemon if not running
d=`ps | grep bluetoothd | grep -v grep`
[ -z "$d" ] && {
Expand All @@ -69,6 +77,22 @@ start_bt() {

# Set adapter name
bluetoothctl system-alias "$DEVICE_NAME" 2>/dev/null

# Proactively reconnect trusted A2DP audio devices after BT restart.
# Some headphones (e.g. Sony) won't fall back to JustWorks re-pairing
# when authentication fails; they expect the host to initiate using the
# stored link key. Runs in background to avoid blocking startup.
{
sleep 5
for dev_dir in /var/lib/bluetooth/*/; do
for paired_dir in "${dev_dir}"*/; do
[ -f "${paired_dir}info" ] || continue
grep -q "0000110b" "${paired_dir}info" || continue
Comment thread
carroarmato0 marked this conversation as resolved.
mac=$(basename "${paired_dir%/}")
bluetoothctl connect "$mac" >/dev/null 2>&1
done
done
} &
}

}
Expand Down
26 changes: 25 additions & 1 deletion skeleton/SYSTEM/tg5050/etc/bluetooth/bt_init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ start_bt() {
start_hci_attach
fi

# Allow headsets to auto-reconnect without user re-pairing.
# Some BT controller firmware never persists link keys to disk;
# JustWorksRepairing=always lets earbuds re-initiate the bond
# from their side after a reboot without user interaction.
if ! grep -q 'JustWorksRepairing = always' /etc/bluetooth/main.conf 2>/dev/null; then
sed -i 's/.*JustWorksRepairing.*/JustWorksRepairing = always/' /etc/bluetooth/main.conf 2>/dev/null
fi

# Start bluetooth daemon if not running
d=`ps | grep bluetoothd | grep -v grep`
[ -z "$d" ] && {
Expand All @@ -77,8 +85,24 @@ start_bt() {

# Set adapter name
bluetoothctl system-alias "$DEVICE_NAME" 2>/dev/null

# Proactively reconnect trusted A2DP audio devices after BT restart.
# Some headphones (e.g. Sony) won't fall back to JustWorks re-pairing
# when authentication fails; they expect the host to initiate using the
# stored link key. Runs in background to avoid blocking startup.
{
sleep 5
for dev_dir in /var/lib/bluetooth/*/; do
for paired_dir in "${dev_dir}"*/; do
[ -f "${paired_dir}info" ] || continue
grep -q "0000110b" "${paired_dir}info" || continue
mac=$(basename "${paired_dir%/}")
bluetoothctl connect "$mac" >/dev/null 2>&1
done
done
} &
}

}

stop_bt() {
Expand Down
23 changes: 22 additions & 1 deletion workspace/all/audiomon/audiomon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,27 @@ enum DeviceType {

bool use_syslog = false;
bool running = true;
static std::string connected_a2dp_mac;

void log(const std::string& msg) {
if (use_syslog) syslog(LOG_INFO, "%s", msg.c_str());
else std::cout << msg << std::endl;
}

static void initBtStateFromAsoundrc() {
std::ifstream f(AUDIO_FILE);
if (!f) return;
std::string content((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
auto pos = content.find("defaults.bluealsa.device \"");
if (pos == std::string::npos) return;
pos += strlen("defaults.bluealsa.device \"");
auto end = content.find("\"", pos);
if (end == std::string::npos) return;
connected_a2dp_mac = content.substr(pos, end - pos);
Comment thread
frysee marked this conversation as resolved.
log("Restored BT state from .asoundrc: " + connected_a2dp_mac);
SetAudioSink(AUDIO_SINK_BLUETOOTH);
}

void ensureDirExists(const std::string& path) {
mkdir(path.c_str(), 0755);
}
Expand Down Expand Up @@ -203,6 +218,7 @@ void handleDeviceConnected(DBusConnection* conn, const std::string& path) {
std::string mac = pathToMac(path);
if (hasUUID(conn, path, UUID_A2DP)) {
log("Audio device connected: " + mac);
connected_a2dp_mac = mac;
writeAudioFile(mac, DEVICE_BLUETOOTH);
SetAudioSink(AUDIO_SINK_BLUETOOTH);
} else {
Expand All @@ -212,8 +228,12 @@ void handleDeviceConnected(DBusConnection* conn, const std::string& path) {

void handleDeviceDisconnected(DBusConnection* conn, const std::string& path) {
std::string mac = pathToMac(path);
if (hasUUID(conn, path, UUID_A2DP)) {
// Use cached MAC rather than querying BlueZ: after an abrupt power-off the
// device's service cache may already be gone, causing hasUUID to return false
// and silently skip the audio switch-back.
if (!connected_a2dp_mac.empty() && mac == connected_a2dp_mac) {
log("Audio device disconnected: " + mac);
connected_a2dp_mac.clear();
clearAudioFile();
// TODO: we could maintain a stack here, if USBC was connected before and restore that instead
SetAudioSink(AUDIO_SINK_DEFAULT);
Expand Down Expand Up @@ -285,6 +305,7 @@ int main(int argc, char* argv[]) {
InitSettings();
// This will be updated as soon as something connects
SetAudioSink(AUDIO_SINK_DEFAULT);
initBtStateFromAsoundrc();

signal(SIGINT, signalHandler);
signal(SIGTERM, signalHandler);
Expand Down
6 changes: 6 additions & 0 deletions workspace/all/common/generic_bt.c
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,12 @@ void PLAT_bluetoothPair(char *addr) {
}
}

// Connect after pairing to initiate A2DP audio profile.
// Some headsets (store_hint=0 controllers) disconnect ~2s after
// pairing if the host doesn't open the audio channel first.
snprintf(cmd, sizeof(cmd), "bluetoothctl connect %s 2>/dev/null", addr);
system(cmd);

// Remove from discovered list since it's now paired
bt_remove_discovered_device(addr);
}
Expand Down
Loading