From 8898a6a8f06e68bfb83f8cc94237ed54a5df2d57 Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Sun, 22 May 2022 15:10:19 +0300 Subject: [PATCH] bluez5: don't consider profiles the adapter doesn't have Don't try to reconnect or wait for profiles, which cannot be connected because the adapter doesn't have the counterpart sink/source profile. E.g. we should not reconnect/wait for HFP HF on remote device, if we don't have the corresponding HFP AG. --- spa/plugins/bluez5/bluez5-dbus.c | 43 +++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/spa/plugins/bluez5/bluez5-dbus.c b/spa/plugins/bluez5/bluez5-dbus.c index b754bf69c..e2bb9cd3e 100644 --- a/spa/plugins/bluez5/bluez5-dbus.c +++ b/spa/plugins/bluez5/bluez5-dbus.c @@ -820,6 +820,29 @@ static void adapter_free(struct spa_bt_adapter *adapter) free(adapter); } +static uint32_t adapter_connectable_profiles(struct spa_bt_adapter *adapter) +{ + const uint32_t profiles = adapter->profiles; + uint32_t mask = 0; + + if (profiles & SPA_BT_PROFILE_A2DP_SINK) + mask |= SPA_BT_PROFILE_A2DP_SOURCE; + if (profiles & SPA_BT_PROFILE_A2DP_SOURCE) + mask |= SPA_BT_PROFILE_A2DP_SINK; + + if (profiles & SPA_BT_PROFILE_HSP_AG) + mask |= SPA_BT_PROFILE_HSP_HS; + if (profiles & SPA_BT_PROFILE_HSP_HS) + mask |= SPA_BT_PROFILE_HSP_AG; + + if (profiles & SPA_BT_PROFILE_HFP_AG) + mask |= SPA_BT_PROFILE_HFP_HF; + if (profiles & SPA_BT_PROFILE_HFP_HF) + mask |= SPA_BT_PROFILE_HFP_AG; + + return mask; +} + struct spa_bt_device *spa_bt_device_find(struct spa_bt_monitor *monitor, const char *path) { struct spa_bt_device *d; @@ -1145,6 +1168,10 @@ static int reconnect_device_profiles(struct spa_bt_device *device) } } + /* Connect only profiles the adapter has a counterpart for */ + if (device->adapter) + reconnect &= adapter_connectable_profiles(device->adapter); + if (!(device->connected_profiles & SPA_BT_PROFILE_HEADSET_HEAD_UNIT)) { if (reconnect & SPA_BT_PROFILE_HFP_HF) { SPA_FLAG_CLEAR(reconnect, SPA_BT_PROFILE_HSP_HS); @@ -1258,9 +1285,12 @@ int spa_bt_device_check_profiles(struct spa_bt_device *device, bool force) { struct spa_bt_monitor *monitor = device->monitor; uint32_t connected_profiles = device->connected_profiles; - uint32_t direction_masks[2] = { - SPA_BT_PROFILE_A2DP_SINK | SPA_BT_PROFILE_HEADSET_AUDIO, - SPA_BT_PROFILE_A2DP_SOURCE | SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY, + uint32_t connectable_profiles = + device->adapter ? adapter_connectable_profiles(device->adapter) : 0; + uint32_t direction_masks[3] = { + SPA_BT_PROFILE_A2DP_SINK | SPA_BT_PROFILE_HEADSET_HEAD_UNIT, + SPA_BT_PROFILE_A2DP_SOURCE, + SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY, }; bool direction_connected = false; bool all_connected; @@ -1272,15 +1302,16 @@ int spa_bt_device_check_profiles(struct spa_bt_device *device, bool force) connected_profiles |= SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY; for (i = 0; i < SPA_N_ELEMENTS(direction_masks); ++i) { - uint32_t mask = direction_masks[i] & device->profiles; + uint32_t mask = direction_masks[i] & device->profiles & connectable_profiles; if (mask && (connected_profiles & mask) == mask) direction_connected = true; } all_connected = (device->profiles & connected_profiles) == device->profiles; - spa_log_debug(monitor->log, "device %p: profiles %08x %08x %d", - device, device->profiles, connected_profiles, device->added); + spa_log_debug(monitor->log, "device %p: profiles %08x %08x connectable:%08x added:%d all:%d dir:%d", + device, device->profiles, connected_profiles, connectable_profiles, + device->added, all_connected, direction_connected); if (connected_profiles == 0 && spa_list_is_empty(&device->codec_switch_list)) { device_stop_timer(device);