diff options
| -rw-r--r-- | profiles/audio/bap.c | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c index b07d65e68b..0dcc57eb5e 100644 --- a/profiles/audio/bap.c +++ b/profiles/audio/bap.c @@ -46,6 +46,8 @@ #include "src/shared/gatt-client.h" #include "src/shared/gatt-server.h" #include "src/shared/bap.h" +#include "src/shared/tmap.h" +#include "src/shared/gmap.h" #include "btio/btio.h" #include "src/plugin.h" @@ -65,6 +67,10 @@ #define MEDIA_ENDPOINT_INTERFACE "org.bluez.MediaEndpoint1" #define MEDIA_INTERFACE "org.bluez.Media1" +#define VCS_UUID_STR "00001844-0000-1000-8000-00805f9b34fb" +#define TMAS_UUID_STR "00001855-0000-1000-8000-00805f9b34fb" +#define GMAS_UUID_STR "00001858-0000-1000-8000-00805f9b34fb" + struct bap_setup; typedef void (*bap_setup_ready_func_t)(struct bap_setup *setup, int code, @@ -438,6 +444,120 @@ static gboolean get_qos(const GDBusPropertyTable *property, return TRUE; } +static bool probe_tmap_role(struct bap_ep *ep, uint32_t data) +{ + struct gatt_db *db = bt_bap_get_db(ep->data->bap, true); + + return bt_tmap_get_role(bt_tmap_find(db)) & data; +} + +static bool probe_gmap_role(struct bap_ep *ep, uint32_t data) +{ + struct gatt_db *db = bt_bap_get_db(ep->data->bap, true); + + return bt_gmap_get_role(bt_gmap_find(db)) & data; +} + +static bool probe_gmap_feature(struct bap_ep *ep, uint32_t data) +{ + struct gatt_db *db = bt_bap_get_db(ep->data->bap, true); + + return bt_gmap_get_features(bt_gmap_find(db)) & data; +} + +struct feature { + const char *name; + bool (*probe)(struct bap_ep *ep, uint32_t data); + uint32_t data; +}; + +static const struct feature tmap_features[] = { + { "cg", probe_tmap_role, BT_TMAP_ROLE_CG }, + { "ct", probe_tmap_role, BT_TMAP_ROLE_CT }, + { "ums", probe_tmap_role, BT_TMAP_ROLE_UMS }, + { "umr", probe_tmap_role, BT_TMAP_ROLE_UMR }, + { "bms", probe_tmap_role, BT_TMAP_ROLE_BMS }, + { "bmr", probe_tmap_role, BT_TMAP_ROLE_BMR }, +}; + +static const struct feature gmap_features[] = { + { "ugg", probe_gmap_role, BT_GMAP_ROLE_UGG }, + { "ugt", probe_gmap_role, BT_GMAP_ROLE_UGT }, + { "bgs", probe_gmap_role, BT_GMAP_ROLE_BGS }, + { "bgr", probe_gmap_role, BT_GMAP_ROLE_BGR }, + { "ugg-multiplex", probe_gmap_feature, BT_GMAP_UGG_MULTIPLEX }, + { "ugg-96kbps-source", probe_gmap_feature, BT_GMAP_UGG_96KBPS }, + { "ugg-multisink", probe_gmap_feature, BT_GMAP_UGG_MULTISINK }, + { "ugt-source", probe_gmap_feature, BT_GMAP_UGT_SOURCE }, + { "ugt-80kbps-source", probe_gmap_feature, + BT_GMAP_UGT_80KBPS_SOURCE }, + { "ugt-sink", probe_gmap_feature, BT_GMAP_UGT_SINK }, + { "ugt-64kbps-sink", probe_gmap_feature, BT_GMAP_UGT_64KBPS_SINK }, + { "ugt-multiplex", probe_gmap_feature, BT_GMAP_UGT_MULTIPLEX }, + { "ugt-multisink", probe_gmap_feature, BT_GMAP_UGT_MULTISINK }, + { "ugt-multisource", probe_gmap_feature, BT_GMAP_UGT_MULTISOURCE }, + { "bgs-96kbps", probe_gmap_feature, BT_GMAP_BGS_96KBPS }, + { "bgr-multisink", probe_gmap_feature, BT_GMAP_BGR_MULTISINK }, + { "bgr-multiplex", probe_gmap_feature, BT_GMAP_BGR_MULTIPLEX }, +}; + +static const struct { + const char *uuid; + const struct feature *items; + size_t count; +} features[] = { + { TMAS_UUID_STR, tmap_features, ARRAY_SIZE(tmap_features) }, + { GMAS_UUID_STR, gmap_features, ARRAY_SIZE(gmap_features) }, +}; + +static gboolean supported_features(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *data) +{ + struct bap_ep *ep = data; + DBusMessageIter dict, entry, variant, list; + size_t i, j; + + dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{sv}", &dict); + + for (i = 0; i < ARRAY_SIZE(features); ++i) { + for (j = 0; j < features[i].count; ++j) { + const struct feature *feature = &features[i].items[j]; + + if (feature->probe(ep, feature->data)) + break; + } + if (j == features[i].count) + continue; + + dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, + NULL, &entry); + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, + &features[i].uuid); + dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, + "as", &variant); + dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY, + "s", &list); + + for (j = 0; j < features[i].count; ++j) { + const struct feature *feature = &features[i].items[j]; + + if (!feature->probe(ep, feature->data)) + continue; + + dbus_message_iter_append_basic(&list, DBUS_TYPE_STRING, + &feature->name); + } + + dbus_message_iter_close_container(&variant, &list); + dbus_message_iter_close_container(&entry, &variant); + dbus_message_iter_close_container(&dict, &entry); + } + + dbus_message_iter_close_container(iter, &dict); + + return TRUE; +} + static const GDBusPropertyTable ep_properties[] = { { "UUID", "s", get_uuid, NULL, NULL, G_DBUS_PROPERTY_FLAG_EXPERIMENTAL }, @@ -457,6 +577,8 @@ static const GDBusPropertyTable ep_properties[] = { G_DBUS_PROPERTY_FLAG_EXPERIMENTAL }, { "QoS", "a{sv}", get_qos, NULL, qos_exists, G_DBUS_PROPERTY_FLAG_EXPERIMENTAL }, + { "SupportedFeatures", "a{sv}", supported_features, NULL, NULL, + G_DBUS_PROPERTY_FLAG_EXPERIMENTAL }, { } }; |
