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.
This commit is contained in:
Pauli Virtanen 2022-05-22 15:10:19 +03:00 committed by Wim Taymans
parent 8383ee8552
commit 8898a6a8f0

View file

@ -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);