bluez5: allow disabling sink or source endpoints

Add option bluez5.roles that selects which endpoints (A2DP, BAP, HFP,
HSP) will be enabled.

This extends and deprecates bluez5.headset-roles.
This commit is contained in:
Pauli Virtanen 2023-03-16 20:40:17 +02:00
parent a49d2d41af
commit fa3ee2e20b
2 changed files with 49 additions and 3 deletions

View file

@ -40,6 +40,7 @@ static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.bluez5.native");
#undef SPA_LOG_TOPIC_DEFAULT
#define SPA_LOG_TOPIC_DEFAULT &log_topic
#define PROP_KEY_ROLES "bluez5.roles"
#define PROP_KEY_HEADSET_ROLES "bluez5.headset-roles"
#define HFP_CODEC_SWITCH_INITIAL_TIMEOUT_MSEC 5000
@ -2706,8 +2707,11 @@ static int parse_headset_roles(struct impl *backend, const struct spa_dict *info
const char *str;
int profiles = SPA_BT_PROFILE_NULL;
if (info == NULL ||
(str = spa_dict_lookup(info, PROP_KEY_HEADSET_ROLES)) == NULL)
if (!info)
goto fallback;
if ((str = spa_dict_lookup(info, PROP_KEY_ROLES)) == NULL &&
(str = spa_dict_lookup(info, PROP_KEY_HEADSET_ROLES)) == NULL)
goto fallback;
profiles = spa_bt_profiles_from_json_array(str);

View file

@ -103,6 +103,8 @@ struct spa_bt_monitor {
struct spa_dict enabled_codecs;
enum spa_bt_profile enabled_profiles;
unsigned int connection_info_supported:1;
unsigned int dummy_avrcp_player:1;
@ -508,6 +510,19 @@ static bool codec_has_direction(const struct media_codec *codec, enum spa_bt_med
}
}
static enum spa_bt_profile get_codec_profile(const struct media_codec *codec,
enum spa_bt_media_direction direction)
{
switch (direction) {
case SPA_BT_MEDIA_SOURCE:
return codec->bap ? SPA_BT_PROFILE_BAP_SOURCE : SPA_BT_PROFILE_A2DP_SOURCE;
case SPA_BT_MEDIA_SINK:
return codec->bap ? SPA_BT_PROFILE_BAP_SINK : SPA_BT_PROFILE_A2DP_SINK;
default:
spa_assert_not_reached();
}
}
static bool endpoint_should_be_registered(struct spa_bt_monitor *monitor,
const struct media_codec *codec,
enum spa_bt_media_direction direction)
@ -517,7 +532,8 @@ static bool endpoint_should_be_registered(struct spa_bt_monitor *monitor,
*/
return is_media_codec_enabled(monitor, codec) &&
codec_has_direction(codec, direction) &&
codec->fill_caps;
codec->fill_caps &&
(get_codec_profile(codec, direction) & monitor->enabled_profiles);
}
static DBusHandlerResult endpoint_select_configuration(DBusConnection *conn, DBusMessage *m, void *userdata)
@ -5000,6 +5016,30 @@ int spa_bt_profiles_from_json_array(const char *str)
return profiles;
}
static int parse_roles(struct spa_bt_monitor *monitor, const struct spa_dict *info)
{
const char *str;
int res = 0;
int profiles = SPA_BT_PROFILE_MEDIA_SINK | SPA_BT_PROFILE_MEDIA_SOURCE;
/* HSP/HFP backends parse this property separately */
if (info && (str = spa_dict_lookup(info, "bluez5.roles"))) {
res = spa_bt_profiles_from_json_array(str);
if (res < 0) {
spa_log_warn(monitor->log, "malformed bluez5.roles setting ignored");
goto done;
}
profiles &= res;
}
res = 0;
done:
monitor->enabled_profiles = profiles;
return res;
}
static int parse_codec_array(struct spa_bt_monitor *this, const struct spa_dict *info)
{
const struct media_codec * const * const media_codecs = this->media_codecs;
@ -5185,6 +5225,8 @@ impl_init(const struct spa_handle_factory *factory,
if ((res = parse_codec_array(this, info)) < 0)
goto fail;
parse_roles(this, info);
this->default_audio_info.rate = A2DP_CODEC_DEFAULT_RATE;
this->default_audio_info.channels = A2DP_CODEC_DEFAULT_CHANNELS;