* [PATCH BlueZ 01/11] lib: move VCS, TMAS, GMAS uuid strings to uuid.h
2025-12-06 11:01 [PATCH BlueZ 00/11] Add local TMAS & GMAS servers Pauli Virtanen
@ 2025-12-06 11:01 ` Pauli Virtanen
2025-12-06 12:02 ` Add local TMAS & GMAS servers bluez.test.bot
2025-12-06 11:01 ` [PATCH BlueZ 02/11] shared/tester: check size before trying debug print Pauli Virtanen
` (10 subsequent siblings)
11 siblings, 1 reply; 14+ messages in thread
From: Pauli Virtanen @ 2025-12-06 11:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Pauli Virtanen
These are needed in several places, so move also string version of the
uuid to uuid.h.
The naming in string vs. uint16_t uuid is not systematic in this file.
Retain the _STR suffix to be clearer.
---
lib/bluetooth/uuid.h | 3 +++
profiles/audio/bap.c | 4 ----
profiles/audio/vcp.c | 1 -
3 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/lib/bluetooth/uuid.h b/lib/bluetooth/uuid.h
index 82e948a23..805366c3d 100644
--- a/lib/bluetooth/uuid.h
+++ b/lib/bluetooth/uuid.h
@@ -178,6 +178,7 @@ extern "C" {
#define BCAST_AUDIO_SCAN_CP_UUID 0x2bc7
#define BCAST_RECV_STATE_UUID 0x2bc8
+#define VCS_UUID_STR "00001844-0000-1000-8000-00805f9b34fb"
#define VCS_UUID 0x1844
#define VOL_OFFSET_CS_UUID 0x1845
#define AUDIO_INPUT_CS_UUID 0x1843
@@ -213,10 +214,12 @@ extern "C" {
#define MEDIA_CONTENT_CONTROL_ID_CHRC_UUID 0x2bba
/* Telephony and Media Audio Service */
+#define TMAS_UUID_STR "00001855-0000-1000-8000-00805f9b34fb"
#define TMAS_UUID 0x1855
#define TMAP_ROLE_CHRC_UUID 0x2b51
/* Gaming Audio Service */
+#define GMAS_UUID_STR "00001858-0000-1000-8000-00805f9b34fb"
#define GMAS_UUID 0x1858
#define GMAP_ROLE_CHRC_UUID 0x2c00
#define GMAP_UGG_CHRC_UUID 0x2c01
diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c
index 4c7b8fcc8..9cd649c7b 100644
--- a/profiles/audio/bap.c
+++ b/profiles/audio/bap.c
@@ -67,10 +67,6 @@
#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,
diff --git a/profiles/audio/vcp.c b/profiles/audio/vcp.c
index fb2aff6ce..277c9bbc3 100644
--- a/profiles/audio/vcp.c
+++ b/profiles/audio/vcp.c
@@ -54,7 +54,6 @@
#include "vcp.h"
#include "transport.h"
-#define VCS_UUID_STR "00001844-0000-1000-8000-00805f9b34fb"
#define MEDIA_ENDPOINT_INTERFACE "org.bluez.MediaEndpoint1"
struct vcp_data {
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH BlueZ 02/11] shared/tester: check size before trying debug print
2025-12-06 11:01 [PATCH BlueZ 00/11] Add local TMAS & GMAS servers Pauli Virtanen
2025-12-06 11:01 ` [PATCH BlueZ 01/11] lib: move VCS, TMAS, GMAS uuid strings to uuid.h Pauli Virtanen
@ 2025-12-06 11:01 ` Pauli Virtanen
2025-12-06 11:01 ` [PATCH BlueZ 03/11] shared/tmap, gmap: add macros for feature names and listing Pauli Virtanen
` (9 subsequent siblings)
11 siblings, 0 replies; 14+ messages in thread
From: Pauli Virtanen @ 2025-12-06 11:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Pauli Virtanen
---
src/shared/tester.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/shared/tester.c b/src/shared/tester.c
index 1f59322bc..7a0145b46 100644
--- a/src/shared/tester.c
+++ b/src/shared/tester.c
@@ -983,7 +983,7 @@ static bool test_io_recv(struct io *io, void *user_data)
if (test->iovcnt && !iov->iov_base)
iov = test_get_iov(test);
- if (memcmp(buf, iov->iov_base, len) || (size_t)len != iov->iov_len)
+ if ((size_t)len != iov->iov_len || memcmp(buf, iov->iov_base, len))
tester_monitor('!', 0x0004, 0x0000, iov->iov_base,
iov->iov_len);
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH BlueZ 03/11] shared/tmap, gmap: add macros for feature names and listing
2025-12-06 11:01 [PATCH BlueZ 00/11] Add local TMAS & GMAS servers Pauli Virtanen
2025-12-06 11:01 ` [PATCH BlueZ 01/11] lib: move VCS, TMAS, GMAS uuid strings to uuid.h Pauli Virtanen
2025-12-06 11:01 ` [PATCH BlueZ 02/11] shared/tester: check size before trying debug print Pauli Virtanen
@ 2025-12-06 11:01 ` Pauli Virtanen
2025-12-06 11:01 ` [PATCH BlueZ 04/11] bap: use tmap/gmap macros for listing features Pauli Virtanen
` (8 subsequent siblings)
11 siblings, 0 replies; 14+ messages in thread
From: Pauli Virtanen @ 2025-12-06 11:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Pauli Virtanen
Better use constants for feature names to avoid typos.
Add macros for generating lists containing all features / roles.
---
src/shared/gmap.h | 45 ++++++++++++++++++++++++++++++++++++++++++++-
src/shared/tmap.h | 15 +++++++++++++++
2 files changed, 59 insertions(+), 1 deletion(-)
diff --git a/src/shared/gmap.h b/src/shared/gmap.h
index ef7d96e0a..d633bfe69 100644
--- a/src/shared/gmap.h
+++ b/src/shared/gmap.h
@@ -17,7 +17,7 @@
#define BT_GMAP_ROLE_MASK (BIT(4) - 1)
#define BT_GMAP_UGG_MULTIPLEX (BIT(0) << 0)
-#define BT_GMAP_UGG_96KBPS (BIT(1) << 0)
+#define BT_GMAP_UGG_96KBPS_SOURCE (BIT(1) << 0)
#define BT_GMAP_UGG_MULTISINK (BIT(2) << 0)
#define BT_GMAP_UGG_FEATURE_MASK ((BIT(3) - 1) << 0)
#define BT_GMAP_UGG_FEATURE_SHIFT 0
@@ -46,6 +46,49 @@
BT_GMAP_BGS_FEATURE_MASK | \
BT_GMAP_BGR_FEATURE_MASK)
+#define BT_GMAP_ROLE_UGG_STR "ugg"
+#define BT_GMAP_ROLE_UGT_STR "ugt"
+#define BT_GMAP_ROLE_BGS_STR "bgs"
+#define BT_GMAP_ROLE_BGR_STR "bgr"
+
+#define BT_GMAP_UGG_MULTIPLEX_STR "ugg-multiplex"
+#define BT_GMAP_UGG_96KBPS_SOURCE_STR "ugg-96kbps-source"
+#define BT_GMAP_UGG_MULTISINK_STR "ugg-multisink"
+
+#define BT_GMAP_UGT_SOURCE_STR "ugt-source"
+#define BT_GMAP_UGT_80KBPS_SOURCE_STR "ugt-80kbps-source"
+#define BT_GMAP_UGT_SINK_STR "ugt-sink"
+#define BT_GMAP_UGT_64KBPS_SINK_STR "ugt-64kbps-sink"
+#define BT_GMAP_UGT_MULTIPLEX_STR "ugt-multiplex"
+#define BT_GMAP_UGT_MULTISINK_STR "ugt-multisink"
+#define BT_GMAP_UGT_MULTISOURCE_STR "ugt-multisource"
+
+#define BT_GMAP_BGS_96KBPS_STR "bgs-96kbps"
+
+#define BT_GMAP_BGR_MULTISINK_STR "bgr-multisink"
+#define BT_GMAP_BGR_MULTIPLEX_STR "bgr-multiplex"
+
+#define BT_GMAP_ROLE_LIST(role) \
+ role(BT_GMAP_ROLE_UGG) \
+ role(BT_GMAP_ROLE_UGT) \
+ role(BT_GMAP_ROLE_BGS) \
+ role(BT_GMAP_ROLE_BGR)
+
+#define BT_GMAP_FEATURE_LIST(feature) \
+ feature(BT_GMAP_UGG_MULTIPLEX) \
+ feature(BT_GMAP_UGG_96KBPS_SOURCE) \
+ feature(BT_GMAP_UGG_MULTISINK) \
+ feature(BT_GMAP_UGT_SOURCE) \
+ feature(BT_GMAP_UGT_80KBPS_SOURCE) \
+ feature(BT_GMAP_UGT_SINK) \
+ feature(BT_GMAP_UGT_64KBPS_SINK) \
+ feature(BT_GMAP_UGT_MULTIPLEX) \
+ feature(BT_GMAP_UGT_MULTISINK) \
+ feature(BT_GMAP_UGT_MULTISOURCE) \
+ feature(BT_GMAP_BGS_96KBPS) \
+ feature(BT_GMAP_BGR_MULTISINK) \
+ feature(BT_GMAP_BGR_MULTIPLEX)
+
struct bt_gmap;
typedef void (*bt_gmap_ready_func_t)(struct bt_gmap *gmap, void *user_data);
diff --git a/src/shared/tmap.h b/src/shared/tmap.h
index 9d872f0b6..9b37dc226 100644
--- a/src/shared/tmap.h
+++ b/src/shared/tmap.h
@@ -18,6 +18,21 @@
#define BT_TMAP_ROLE_BMR BIT(5)
#define BT_TMAP_ROLE_MASK (BIT(6) - 1)
+#define BT_TMAP_ROLE_CG_STR "cg"
+#define BT_TMAP_ROLE_CT_STR "ct"
+#define BT_TMAP_ROLE_UMS_STR "ums"
+#define BT_TMAP_ROLE_UMR_STR "umr"
+#define BT_TMAP_ROLE_BMS_STR "bms"
+#define BT_TMAP_ROLE_BMR_STR "bmr"
+
+#define BT_TMAP_ROLE_LIST(role) \
+ role(BT_TMAP_ROLE_CG) \
+ role(BT_TMAP_ROLE_CT) \
+ role(BT_TMAP_ROLE_UMS) \
+ role(BT_TMAP_ROLE_UMR) \
+ role(BT_TMAP_ROLE_BMS) \
+ role(BT_TMAP_ROLE_BMR)
+
struct bt_tmap;
typedef void (*bt_tmap_ready_func_t)(struct bt_tmap *tmap, void *user_data);
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH BlueZ 04/11] bap: use tmap/gmap macros for listing features
2025-12-06 11:01 [PATCH BlueZ 00/11] Add local TMAS & GMAS servers Pauli Virtanen
` (2 preceding siblings ...)
2025-12-06 11:01 ` [PATCH BlueZ 03/11] shared/tmap, gmap: add macros for feature names and listing Pauli Virtanen
@ 2025-12-06 11:01 ` Pauli Virtanen
2025-12-06 11:01 ` [PATCH BlueZ 05/11] shared/tmap: deactivate service if setting Role to 0 Pauli Virtanen
` (7 subsequent siblings)
11 siblings, 0 replies; 14+ messages in thread
From: Pauli Virtanen @ 2025-12-06 11:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Pauli Virtanen
Use listing macros to generate the feature lists.
---
profiles/audio/bap.c | 32 ++++++++------------------------
1 file changed, 8 insertions(+), 24 deletions(-)
diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c
index 9cd649c7b..cda10a643 100644
--- a/profiles/audio/bap.c
+++ b/profiles/audio/bap.c
@@ -469,34 +469,18 @@ struct feature {
uint32_t data;
};
+#define TMAP_ROLE(key) { key ## _STR, probe_tmap_role, key },
+
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 },
+ BT_TMAP_ROLE_LIST(TMAP_ROLE)
};
+#define GMAP_ROLE(key) { key ## _STR, probe_gmap_role, key },
+#define GMAP_FEATURE(key) { key ## _STR, probe_gmap_feature, key },
+
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 },
+ BT_GMAP_ROLE_LIST(GMAP_ROLE)
+ BT_GMAP_FEATURE_LIST(GMAP_FEATURE)
};
static const struct {
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH BlueZ 05/11] shared/tmap: deactivate service if setting Role to 0
2025-12-06 11:01 [PATCH BlueZ 00/11] Add local TMAS & GMAS servers Pauli Virtanen
` (3 preceding siblings ...)
2025-12-06 11:01 ` [PATCH BlueZ 04/11] bap: use tmap/gmap macros for listing features Pauli Virtanen
@ 2025-12-06 11:01 ` Pauli Virtanen
2025-12-06 11:01 ` [PATCH BlueZ 06/11] shared/gmap: deactivate service or remove feature chrc if role removed Pauli Virtanen
` (6 subsequent siblings)
11 siblings, 0 replies; 14+ messages in thread
From: Pauli Virtanen @ 2025-12-06 11:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Pauli Virtanen
Deactivate TMAS if roles are removed.
Also add NULL checks to the set() routine for convenience.
---
src/shared/tmap.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/src/shared/tmap.c b/src/shared/tmap.c
index 6fc96cd89..27e08d74a 100644
--- a/src/shared/tmap.c
+++ b/src/shared/tmap.c
@@ -292,11 +292,17 @@ struct bt_tmap *bt_tmap_add_db(struct gatt_db *db)
void bt_tmap_set_role(struct bt_tmap *tmap, uint16_t role)
{
- if (tmap->client)
+ if (!tmap || tmap->client)
return;
- tmap->db.role_value = role & BT_TMAP_ROLE_MASK;
+ role &= BT_TMAP_ROLE_MASK;
+ if (role == tmap->db.role_value)
+ return;
- /* Expose value only when first set. Role does not have Notify. */
- gatt_db_service_set_active(tmap->db.service, true);
+ DBG(tmap, "set role 0x%02x", role);
+
+ tmap->db.role_value = role;
+
+ /* Expose when first set and present. Role does not have Notify. */
+ gatt_db_service_set_active(tmap->db.service, role != 0);
}
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH BlueZ 06/11] shared/gmap: deactivate service or remove feature chrc if role removed
2025-12-06 11:01 [PATCH BlueZ 00/11] Add local TMAS & GMAS servers Pauli Virtanen
` (4 preceding siblings ...)
2025-12-06 11:01 ` [PATCH BlueZ 05/11] shared/tmap: deactivate service if setting Role to 0 Pauli Virtanen
@ 2025-12-06 11:01 ` Pauli Virtanen
2025-12-06 11:01 ` [PATCH BlueZ 07/11] test-tmap: test removing and adding role Pauli Virtanen
` (5 subsequent siblings)
11 siblings, 0 replies; 14+ messages in thread
From: Pauli Virtanen @ 2025-12-06 11:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Pauli Virtanen
When role is removed, the associated feature chrc must be removed too as
it's then Excluded in spec. If all roles are removed, deactivate the
service instead to avoid consuming ATT handles.
Reserve exactly the right number of handles for the service.
Also add null checks to the feature set routines for convenience.
---
src/shared/gmap.c | 57 +++++++++++++++++++++++++++++++++++------------
1 file changed, 43 insertions(+), 14 deletions(-)
diff --git a/src/shared/gmap.c b/src/shared/gmap.c
index f571f3270..291135db3 100644
--- a/src/shared/gmap.c
+++ b/src/shared/gmap.c
@@ -345,10 +345,27 @@ static void gmap_update_chrc(struct bt_gmap *gmap)
}
}
+static void gmap_init_service(struct bt_gmas_db *db)
+{
+ bt_uuid_t uuid;
+
+ if (db->service) {
+ gatt_db_remove_service(db->db, db->service);
+ db->service = NULL;
+ db->role.attr = NULL;
+ db->ugg.attr = NULL;
+ db->ugt.attr = NULL;
+ db->bgs.attr = NULL;
+ db->bgr.attr = NULL;
+ }
+
+ bt_uuid16_create(&uuid, GMAS_UUID);
+ db->service = gatt_db_add_service(db->db, &uuid, true, 5*2 + 1);
+}
+
struct bt_gmap *bt_gmap_add_db(struct gatt_db *db)
{
struct bt_gmap *gmap;
- bt_uuid_t uuid;
if (!db || queue_find(instances, match_db, db))
return NULL;
@@ -356,8 +373,7 @@ struct bt_gmap *bt_gmap_add_db(struct gatt_db *db)
gmap = new0(struct bt_gmap, 1);
gmap->db.db = gatt_db_ref(db);
- bt_uuid16_create(&uuid, GMAS_UUID);
- gmap->db.service = gatt_db_add_service(db, &uuid, true, 5*3);
+ gmap_init_service(&gmap->db);
if (!instances)
instances = queue_new();
@@ -368,23 +384,41 @@ struct bt_gmap *bt_gmap_add_db(struct gatt_db *db)
void bt_gmap_set_role(struct bt_gmap *gmap, uint8_t role)
{
- if (gmap->client)
+ if (!gmap || gmap->client)
return;
- gmap->db.role.value = role & BT_GMAP_ROLE_MASK;
+ role &= BT_GMAP_ROLE_MASK;
+ if (role == gmap->db.role.value)
+ return;
+
+ DBG(gmap, "set role 0x%02x", role);
+
+ gmap->db.role.value = role;
+
+ /* Removing role must remove feature chrc too; reset svc if needed */
+ if (role && ((!(role & BT_GMAP_ROLE_UGG) && gmap->db.ugg.attr) ||
+ (!(role & BT_GMAP_ROLE_UGT) && gmap->db.ugt.attr) ||
+ (!(role & BT_GMAP_ROLE_BGS) && gmap->db.bgs.attr) ||
+ (!(role & BT_GMAP_ROLE_BGR) && gmap->db.bgr.attr)))
+ gmap_init_service(&gmap->db);
gmap_update_chrc(gmap);
- /* Expose values only when first set */
- gatt_db_service_set_active(gmap->db.service, true);
+ /* Expose values only when first set and active */
+ gatt_db_service_set_active(gmap->db.service, role != 0);
}
-
void bt_gmap_set_features(struct bt_gmap *gmap, uint32_t features)
{
- if (gmap->client)
+ if (!gmap || gmap->client)
return;
+ features &= BT_GMAP_FEATURE_MASK;
+ if (features == bt_gmap_get_features(gmap))
+ return;
+
+ DBG(gmap, "set features 0x%08x", features);
+
gmap->db.ugg.value = (features & BT_GMAP_UGG_FEATURE_MASK)
>> BT_GMAP_UGG_FEATURE_SHIFT;
gmap->db.ugt.value = (features & BT_GMAP_UGT_FEATURE_MASK)
@@ -393,9 +427,4 @@ void bt_gmap_set_features(struct bt_gmap *gmap, uint32_t features)
>> BT_GMAP_BGS_FEATURE_SHIFT;
gmap->db.bgr.value = (features & BT_GMAP_BGR_FEATURE_MASK)
>> BT_GMAP_BGR_FEATURE_SHIFT;
-
- gmap_update_chrc(gmap);
-
- /* Expose values only when first set */
- gatt_db_service_set_active(gmap->db.service, true);
}
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH BlueZ 07/11] test-tmap: test removing and adding role
2025-12-06 11:01 [PATCH BlueZ 00/11] Add local TMAS & GMAS servers Pauli Virtanen
` (5 preceding siblings ...)
2025-12-06 11:01 ` [PATCH BlueZ 06/11] shared/gmap: deactivate service or remove feature chrc if role removed Pauli Virtanen
@ 2025-12-06 11:01 ` Pauli Virtanen
2025-12-06 11:01 ` [PATCH BlueZ 08/11] test-gmap: test removing, adding, and changing role Pauli Virtanen
` (4 subsequent siblings)
11 siblings, 0 replies; 14+ messages in thread
From: Pauli Virtanen @ 2025-12-06 11:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Pauli Virtanen
---
unit/test-tmap.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/unit/test-tmap.c b/unit/test-tmap.c
index 481453112..937dac6ee 100644
--- a/unit/test-tmap.c
+++ b/unit/test-tmap.c
@@ -32,6 +32,7 @@
struct test_config {
uint16_t role;
+ uint16_t old_role;
};
struct test_data {
@@ -221,6 +222,11 @@ static void test_setup_server(const void *user_data)
data->tmap = bt_tmap_add_db(db);
bt_tmap_set_debug(data->tmap, print_debug, "tmap:", NULL);
+ if (data->cfg->old_role) {
+ bt_tmap_set_role(data->tmap, data->cfg->old_role);
+ bt_tmap_set_role(data->tmap, 0);
+ }
+
bt_tmap_set_role(data->tmap, data->cfg->role);
att = bt_att_new(io_get_fd(io), false);
@@ -344,6 +350,11 @@ const struct test_config cfg_read_role = {
.role = BT_TMAP_ROLE_UMS | BT_TMAP_ROLE_BMR,
};
+const struct test_config cfg_read_role_re_add = {
+ .role = BT_TMAP_ROLE_UMS | BT_TMAP_ROLE_BMR,
+ .old_role = BT_TMAP_ROLE_CT,
+};
+
static void test_tmap_cl(void)
{
/* Sec. 4.5.1 TMA Client */
@@ -366,6 +377,10 @@ static void test_tmap_sr(void)
"TMAP Role]",
test_setup_server, test_server, &cfg_read_role,
SGGIT_CHA);
+
+ define_test("TMAP/SR/SGGIT/CHA/BLUEZ-01-C [Re-add Role]",
+ test_setup_server, test_server, &cfg_read_role_re_add,
+ SGGIT_CHA);
}
int main(int argc, char *argv[])
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH BlueZ 08/11] test-gmap: test removing, adding, and changing role
2025-12-06 11:01 [PATCH BlueZ 00/11] Add local TMAS & GMAS servers Pauli Virtanen
` (6 preceding siblings ...)
2025-12-06 11:01 ` [PATCH BlueZ 07/11] test-tmap: test removing and adding role Pauli Virtanen
@ 2025-12-06 11:01 ` Pauli Virtanen
2025-12-06 11:01 ` [PATCH BlueZ 09/11] media: parse SupportedFeatures from registered MediaEndpoints Pauli Virtanen
` (3 subsequent siblings)
11 siblings, 0 replies; 14+ messages in thread
From: Pauli Virtanen @ 2025-12-06 11:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Pauli Virtanen
When role is changed the old characteristic is removed, which shifts the
attribute handles.
---
unit/test-gmap.c | 89 ++++++++++++++++++++++++++++++++++--------------
1 file changed, 64 insertions(+), 25 deletions(-)
diff --git a/unit/test-gmap.c b/unit/test-gmap.c
index 6102ce65d..ce9eeb8f9 100644
--- a/unit/test-gmap.c
+++ b/unit/test-gmap.c
@@ -32,6 +32,7 @@
struct test_config {
uint8_t role;
+ uint8_t old_role;
uint32_t features;
const struct iovec *setup_data;
const size_t setup_data_len;
@@ -107,22 +108,22 @@ static void test_teardown(const void *user_data)
* ATT: Read By Group Type Response (0x11) len 37
* Attribute data length: 6
* Attribute group list: 1 entries
- * Handle range: 0x0001-0x000f
+ * Handle range: 0x0001-0x000b
* UUID: Gaming Audio Service (0x1858)
* ATT: Read By Group Type Request (0x10) len 6
- * Handle range: 0x0006-0xffff
+ * Handle range: 0x000c-0xffff
* Attribute group type: Primary Service (0x2800)
* ATT: Error Response (0x01) len 4
* Read By Group Type Request (0x10)
* Handle: 0x0004
* Error: Attribute Not Found (0x0a)
*/
-#define GMAS_PRIMARY_SERVICE \
+#define GMAS_PRIMARY_SERVICE(base) \
IOV_DATA(0x10, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28), \
IOV_DATA(0x11, 0x06, \
- 0x01, 0x00, 0x0f, 0x00, 0x58, 0x18), \
- IOV_DATA(0x10, 0x10, 0x00, 0xff, 0xff, 0x00, 0x28), \
- IOV_DATA(0x01, 0x10, 0x10, 0x00, 0x0a)
+ 0x01 + base, 0x00, 0x0b + base, 0x00, 0x58, 0x18), \
+ IOV_DATA(0x10, 0x0c + base, 0x00, 0xff, 0xff, 0x00, 0x28), \
+ IOV_DATA(0x01, 0x10, 0x0c + base, 0x00, 0x0a)
/* ATT: Read By Group Type Request (0x10) len 6
@@ -145,9 +146,9 @@ static void test_teardown(const void *user_data)
* Handle: 0x0001
* Error: Attribute Not Found (0x0a)
*/
-#define GMAS_INCLUDE \
- IOV_DATA(0x08, 0x01, 0x00, 0x0f, 0x00, 0x02, 0x28), \
- IOV_DATA(0x01, 0x08, 0x01, 0x00, 0x0a)
+#define GMAS_INCLUDE(base) \
+ IOV_DATA(0x08, 0x01 + base, 0x00, 0x0b + base, 0x00, 0x02, 0x28), \
+ IOV_DATA(0x01, 0x08, 0x01 + base, 0x00, 0x0a)
/* ATT: Read By Type Request (0x08) len 6
* Handle range: 0x0001-0x0003
@@ -182,15 +183,15 @@ static void test_teardown(const void *user_data)
*/
#define IOV_CONTENT(data...) data
-#define GMAS_FIND_CHRC(uuid) \
- IOV_DATA(0x08, 0x01, 0x00, 0x0f, 0x00, 0x03, 0x28), \
+#define GMAS_FIND_CHRC(uuid, base) \
+ IOV_DATA(0x08, 0x01 + base, 0x00, 0x0b + base, 0x00, 0x03, 0x28), \
IOV_DATA(0x09, 0x07, \
- 0x02, 0x00, 0x02, 0x03, 0x00, 0x00, 0x2c, \
- 0x04, 0x00, 0x02, 0x05, 0x00, uuid), \
- IOV_DATA(0x08, 0x05, 0x00, 0x0f, 0x00, 0x03, 0x28), \
- IOV_DATA(0x01, 0x08, 0x05, 0x00, 0x0a), \
- IOV_DATA(0x04, 0x06, 0x00, 0x0f, 0x00), \
- IOV_DATA(0x01, 0x04, 0x06, 0x00, 0x0a)
+ 0x02 + base, 0x00, 0x02, 0x03 + base, 0x00, 0x00, 0x2c, \
+ 0x04 + base, 0x00, 0x02, 0x05 + base, 0x00, uuid), \
+ IOV_DATA(0x08, 0x05 + base, 0x00, 0x0b + base, 0x00, 0x03, 0x28), \
+ IOV_DATA(0x01, 0x08, 0x05 + base, 0x00, 0x0a), \
+ IOV_DATA(0x04, 0x06 + base, 0x00, 0x0b + base, 0x00), \
+ IOV_DATA(0x01, 0x04, 0x06 + base, 0x00, 0x0a)
#define UGG_UUID 0x01, 0x2c
#define UGT_UUID 0x02, 0x2c
@@ -214,19 +215,19 @@ static void test_teardown(const void *user_data)
IOV_DATA(0x01, 0x08, 0x01, 0x00, 0x0a)
-#define GMAS_SETUP(uuid) \
+#define GMAS_SETUP(uuid, base) \
GMAS_MTU_FEAT, \
- GMAS_PRIMARY_SERVICE, \
+ GMAS_PRIMARY_SERVICE(base), \
GMAS_SECONDARY_SERVICE, \
- GMAS_INCLUDE, \
- GMAS_FIND_CHRC(IOV_CONTENT(uuid)), \
+ GMAS_INCLUDE(base), \
+ GMAS_FIND_CHRC(IOV_CONTENT(uuid), base), \
GMAS_DATABASE_HASH
/* GATT Discover All procedure */
-static const struct iovec setup_data_ugg[] = { GMAS_SETUP(UGG_UUID) };
-static const struct iovec setup_data_ugt[] = { GMAS_SETUP(UGT_UUID) };
-static const struct iovec setup_data_bgs[] = { GMAS_SETUP(BGS_UUID) };
-static const struct iovec setup_data_bgr[] = { GMAS_SETUP(BGR_UUID) };
+static const struct iovec setup_data_ugg[] = { GMAS_SETUP(UGG_UUID, 0) };
+static const struct iovec setup_data_ugt[] = { GMAS_SETUP(UGT_UUID, 0) };
+static const struct iovec setup_data_bgs[] = { GMAS_SETUP(BGS_UUID, 0) };
+static const struct iovec setup_data_bgr[] = { GMAS_SETUP(BGR_UUID, 0) };
static void setup_complete_cb(const void *user_data)
{
@@ -252,6 +253,13 @@ static void test_setup_server(const void *user_data)
data->gmap = bt_gmap_add_db(db);
bt_gmap_set_debug(data->gmap, print_debug, "gmap:", NULL);
+ if (data->cfg->old_role) {
+ bt_gmap_set_role(data->gmap, data->cfg->old_role);
+ bt_gmap_set_features(data->gmap, 0xffffffff);
+ bt_gmap_set_role(data->gmap, data->cfg->role);
+ bt_gmap_set_role(data->gmap, 0);
+ }
+
bt_gmap_set_role(data->gmap, data->cfg->role);
bt_gmap_set_features(data->gmap, data->cfg->features);
@@ -466,6 +474,29 @@ static void test_gmap_cl(void)
#define SGGIT_CHA_ROLE READ_ROLE(0x01)
#define SGGIT_CHA_FEAT READ_FEAT(0x01)
+const struct test_config cfg_read_ugg_re_add = {
+ .old_role = BT_GMAP_ROLE_UGG,
+ .role = BT_GMAP_ROLE_UGG,
+ .features = BT_GMAP_UGG_MULTIPLEX,
+ .setup_data = setup_data_ugg,
+ .setup_data_len = ARRAY_SIZE(setup_data_ugg),
+};
+
+#define SGGIT_CHA_FEAT_CHANGE \
+ READ_CHRC(IOV_CONTENT(0x0b + FEAT_HND), 0x01)
+
+static const struct iovec setup_data_ugg_change[] = {
+ GMAS_SETUP(UGG_UUID, 0x0b)
+};
+
+const struct test_config cfg_read_ugg_change = {
+ .old_role = BT_GMAP_ROLE_UGT,
+ .role = BT_GMAP_ROLE_UGG,
+ .features = BT_GMAP_UGG_MULTIPLEX,
+ .setup_data = setup_data_ugg_change,
+ .setup_data_len = ARRAY_SIZE(setup_data_ugg_change),
+};
+
static void test_gmap_sr(void)
{
/* Sec. 4.6.2 GMA Server */
@@ -484,6 +515,14 @@ static void test_gmap_sr(void)
define_test("GMAP/SR/SGGIT/CHA/BV-05-C [Characteristic GGIT - BGR "
"Features]",
test_setup_server, test_server, &cfg_read_bgr, SGGIT_CHA_FEAT);
+
+ define_test("GMAP/SR/SGGIT/CHA/BLUEZ-01-C [Re-add UGG Features]",
+ test_setup_server, test_server, &cfg_read_ugg_re_add,
+ SGGIT_CHA_FEAT);
+
+ define_test("GMAP/SR/SGGIT/CHA/BLUEZ-02-C [Change UGT -> UGG]",
+ test_setup_server, test_server, &cfg_read_ugg_change,
+ SGGIT_CHA_FEAT_CHANGE);
}
int main(int argc, char *argv[])
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH BlueZ 09/11] media: parse SupportedFeatures from registered MediaEndpoints
2025-12-06 11:01 [PATCH BlueZ 00/11] Add local TMAS & GMAS servers Pauli Virtanen
` (7 preceding siblings ...)
2025-12-06 11:01 ` [PATCH BlueZ 08/11] test-gmap: test removing, adding, and changing role Pauli Virtanen
@ 2025-12-06 11:01 ` Pauli Virtanen
2025-12-06 11:01 ` [PATCH BlueZ 10/11] tmap: remove service on device remove Pauli Virtanen
` (2 subsequent siblings)
11 siblings, 0 replies; 14+ messages in thread
From: Pauli Virtanen @ 2025-12-06 11:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Pauli Virtanen
Parse SupportedFeatures for TMAP and GMAP features, and update the
values to the local services if present.
---
profiles/audio/media.c | 160 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 156 insertions(+), 4 deletions(-)
diff --git a/profiles/audio/media.c b/profiles/audio/media.c
index 418a9d06b..9deeed1f4 100644
--- a/profiles/audio/media.c
+++ b/profiles/audio/media.c
@@ -55,6 +55,8 @@
#include "src/shared/att.h"
#include "src/shared/bap.h"
#include "src/shared/bap-debug.h"
+#include "src/shared/tmap.h"
+#include "src/shared/gmap.h"
#ifdef HAVE_A2DP
#include "avdtp.h"
@@ -109,6 +111,12 @@ struct endpoint_request {
void *user_data;
};
+struct endpoint_features {
+ uint8_t tmap_role;
+ uint8_t gmap_role;
+ uint32_t gmap_features;
+};
+
struct media_endpoint {
#ifdef HAVE_A2DP
struct a2dp_sep *sep;
@@ -133,6 +141,7 @@ struct media_endpoint {
GSList *requests;
struct media_adapter *adapter;
GSList *transports;
+ struct endpoint_features features;
};
struct media_player {
@@ -247,6 +256,33 @@ static struct media_endpoint *media_adapter_find_endpoint(
return NULL;
}
+static void update_features(struct media_adapter *adapter)
+{
+ struct endpoint_features all = { 0 };
+ GSList *list;
+ struct btd_gatt_database *database;
+ struct gatt_db *db;
+ struct bt_tmap *tmap;
+ struct bt_gmap *gmap;
+
+ for (list = adapter->endpoints; list; list = list->next) {
+ struct media_endpoint *endpoint = list->data;
+
+ all.tmap_role |= endpoint->features.tmap_role;
+ all.gmap_role |= endpoint->features.gmap_role;
+ all.gmap_features |= endpoint->features.gmap_features;
+ }
+
+ database = btd_adapter_get_database(adapter->btd_adapter);
+ db = btd_gatt_database_get_db(database);
+ tmap = bt_tmap_find(db);
+ gmap = bt_gmap_find(db);
+
+ bt_tmap_set_role(tmap, all.tmap_role);
+ bt_gmap_set_role(gmap, all.gmap_role);
+ bt_gmap_set_features(gmap, all.gmap_features);
+}
+
static void media_endpoint_remove(void *data)
{
struct media_endpoint *endpoint = data;
@@ -270,6 +306,8 @@ static void media_endpoint_remove(void *data)
"MediaEndpoints");
media_endpoint_destroy(endpoint);
+
+ update_features(adapter);
}
static void media_endpoint_exit(DBusConnection *connection, void *user_data)
@@ -1531,6 +1569,7 @@ media_endpoint_create(struct media_adapter *adapter,
int size,
uint8_t *metadata,
int metadata_size,
+ struct endpoint_features *feat,
int *err)
{
struct media_endpoint *endpoint;
@@ -1550,6 +1589,9 @@ media_endpoint_create(struct media_adapter *adapter,
if (qos)
endpoint->qos = *qos;
+ if (feat)
+ endpoint->features = *feat;
+
if (size > 0) {
endpoint->capabilities = g_new(uint8_t, size);
memcpy(endpoint->capabilities, capabilities, size);
@@ -1596,11 +1638,98 @@ media_endpoint_create(struct media_adapter *adapter,
adapter->endpoints = g_slist_append(adapter->endpoints, endpoint);
info("Endpoint registered: sender=%s path=%s", sender, path);
+ update_features(adapter);
+
if (err)
*err = 0;
return endpoint;
}
+static void parse_tmap_role(struct endpoint_features *features, uint32_t data)
+{
+ features->tmap_role |= data;
+}
+
+static void parse_gmap_role(struct endpoint_features *features, uint32_t data)
+{
+ features->gmap_role |= data;
+}
+
+static void parse_gmap_feature(struct endpoint_features *features,
+ uint32_t data)
+{
+ features->gmap_features |= data;
+}
+
+#define TMAP_ROLE(key) \
+ { .uuid = TMAS_UUID_STR, .name = key ## _STR, .data = key, \
+ .func = parse_tmap_role },
+#define GMAP_ROLE(key) \
+ { .uuid = GMAS_UUID_STR, .name = key ## _STR, .data = key, \
+ .func = parse_gmap_role },
+#define GMAP_FEATURE(key) \
+ { .uuid = GMAS_UUID_STR, .name = key ## _STR, .data = key, \
+ .func = parse_gmap_feature },
+
+static const struct endpoint_feature_dbus {
+ const char *uuid;
+ const char *name;
+ uint32_t data;
+ void (*func)(struct endpoint_features *features, uint32_t data);
+} endpoint_features[] = {
+ BT_TMAP_ROLE_LIST(TMAP_ROLE)
+ BT_GMAP_ROLE_LIST(GMAP_ROLE)
+ BT_GMAP_FEATURE_LIST(GMAP_FEATURE)
+};
+
+static void parse_endpoint_feature(const char *uuid, const char *value,
+ struct endpoint_features *features)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(endpoint_features); ++i) {
+ const struct endpoint_feature_dbus *f = &endpoint_features[i];
+
+ if (strcmp(uuid, f->uuid) == 0 && strcmp(value, f->name) == 0) {
+ f->func(features, f->data);
+ break;
+ }
+ }
+}
+
+static int parse_endpoint_features(DBusMessageIter *iter,
+ struct endpoint_features *features)
+{
+ while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_DICT_ENTRY) {
+ const char *uuid, *name;
+ DBusMessageIter value, entry, array;
+ int var;
+
+ dbus_message_iter_recurse(iter, &entry);
+ dbus_message_iter_get_basic(&entry, &uuid);
+
+ dbus_message_iter_next(&entry);
+ dbus_message_iter_recurse(&entry, &value);
+
+ var = dbus_message_iter_get_arg_type(&value);
+ if (var != DBUS_TYPE_ARRAY)
+ return -EINVAL;
+
+ dbus_message_iter_recurse(&value, &array);
+
+ while (dbus_message_iter_get_arg_type(&array)
+ == DBUS_TYPE_STRING) {
+ dbus_message_iter_get_basic(&array, &name);
+ parse_endpoint_feature(uuid, name, features);
+ dbus_message_iter_next(&array);
+ }
+
+ dbus_message_iter_next(iter);
+ }
+
+ return 0;
+}
+
struct vendor {
uint16_t cid;
uint16_t vid;
@@ -1611,7 +1740,8 @@ static int parse_properties(DBusMessageIter *props, const char **uuid,
uint16_t *cid, uint16_t *vid,
struct bt_bap_pac_qos *qos,
uint8_t **capabilities, int *size,
- uint8_t **metadata, int *metadata_size)
+ uint8_t **metadata, int *metadata_size,
+ struct endpoint_features *features)
{
gboolean has_uuid = FALSE;
gboolean has_codec = FALSE;
@@ -1708,6 +1838,15 @@ static int parse_properties(DBusMessageIter *props, const char **uuid,
return -EINVAL;
dbus_message_iter_get_basic(&value,
&qos->supported_context);
+ } else if (strcasecmp(key, "SupportedFeatures") == 0) {
+ DBusMessageIter array;
+
+ if (var != DBUS_TYPE_ARRAY)
+ return -EINVAL;
+
+ dbus_message_iter_recurse(&value, &array);
+ if (parse_endpoint_features(&array, features) < 0)
+ return -EINVAL;
}
dbus_message_iter_next(props);
@@ -1727,6 +1866,7 @@ static DBusMessage *register_endpoint(DBusConnection *conn, DBusMessage *msg,
uint16_t cid = 0;
uint16_t vid = 0;
struct bt_bap_pac_qos qos = {};
+ struct endpoint_features features = { 0 };
uint8_t *capabilities = NULL;
uint8_t *metadata = NULL;
int size = 0;
@@ -1749,13 +1889,13 @@ static DBusMessage *register_endpoint(DBusConnection *conn, DBusMessage *msg,
if (parse_properties(&props, &uuid, &delay_reporting, &codec, &cid,
&vid, &qos, &capabilities, &size, &metadata,
- &metadata_size) < 0)
+ &metadata_size, &features) < 0)
return btd_error_invalid_args(msg);
if (media_endpoint_create(adapter, sender, path, uuid, delay_reporting,
codec, cid, vid, &qos, capabilities,
size, metadata, metadata_size,
- &err) == NULL) {
+ &features, &err) == NULL) {
if (err == -EPROTONOSUPPORT)
return btd_error_not_supported(msg);
else
@@ -2786,6 +2926,7 @@ static void app_register_endpoint(void *data, void *user_data)
int size = 0;
uint8_t *metadata = NULL;
int metadata_size = 0;
+ struct endpoint_features features = { 0 };
DBusMessageIter iter, array;
struct media_endpoint *endpoint;
@@ -2918,12 +3059,23 @@ static void app_register_endpoint(void *data, void *user_data)
dbus_message_iter_get_basic(&iter, &qos.supported_context);
}
+ if (g_dbus_proxy_get_property(proxy, "SupportedFeatures", &iter)) {
+ DBusMessageIter array;
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
+ goto fail;
+
+ dbus_message_iter_recurse(&iter, &array);
+ if (parse_endpoint_features(&array, &features) < 0)
+ goto fail;
+ }
+
endpoint = media_endpoint_create(app->adapter, app->sender, path, uuid,
delay_reporting, codec,
vendor.cid, vendor.vid, &qos,
capabilities, size,
metadata, metadata_size,
- &app->err);
+ &features, &app->err);
if (!endpoint) {
error("Unable to register endpoint %s:%s: %s", app->sender,
path, strerror(-app->err));
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH BlueZ 10/11] tmap: remove service on device remove
2025-12-06 11:01 [PATCH BlueZ 00/11] Add local TMAS & GMAS servers Pauli Virtanen
` (8 preceding siblings ...)
2025-12-06 11:01 ` [PATCH BlueZ 09/11] media: parse SupportedFeatures from registered MediaEndpoints Pauli Virtanen
@ 2025-12-06 11:01 ` Pauli Virtanen
2025-12-06 11:01 ` [PATCH BlueZ 11/11] gmap: " Pauli Virtanen
2025-12-08 19:20 ` [PATCH BlueZ 00/11] Add local TMAS & GMAS servers patchwork-bot+bluetooth
11 siblings, 0 replies; 14+ messages in thread
From: Pauli Virtanen @ 2025-12-06 11:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Pauli Virtanen
Remove service on device_remove() as disconnect() is not necessarily
called on device remove.
---
profiles/audio/tmap.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/profiles/audio/tmap.c b/profiles/audio/tmap.c
index 2525c33bf..23e72165e 100644
--- a/profiles/audio/tmap.c
+++ b/profiles/audio/tmap.c
@@ -141,6 +141,8 @@ static void tmap_remove(struct btd_service *service)
ba2str(device_get_address(device), addr);
DBG("%s", addr);
+
+ remove_service(service);
}
static int tmap_adapter_probe(struct btd_profile *p,
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH BlueZ 11/11] gmap: remove service on device remove
2025-12-06 11:01 [PATCH BlueZ 00/11] Add local TMAS & GMAS servers Pauli Virtanen
` (9 preceding siblings ...)
2025-12-06 11:01 ` [PATCH BlueZ 10/11] tmap: remove service on device remove Pauli Virtanen
@ 2025-12-06 11:01 ` Pauli Virtanen
2025-12-08 19:20 ` [PATCH BlueZ 00/11] Add local TMAS & GMAS servers patchwork-bot+bluetooth
11 siblings, 0 replies; 14+ messages in thread
From: Pauli Virtanen @ 2025-12-06 11:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Pauli Virtanen
Remove service on device_remove() as disconnect() is not necessarily
called on device remove.
---
profiles/audio/gmap.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/profiles/audio/gmap.c b/profiles/audio/gmap.c
index 810bc783c..cf9b43ca1 100644
--- a/profiles/audio/gmap.c
+++ b/profiles/audio/gmap.c
@@ -138,6 +138,8 @@ static void gmap_remove(struct btd_service *service)
ba2str(device_get_address(device), addr);
DBG("%s", addr);
+
+ remove_service(service);
}
static int gmap_adapter_probe(struct btd_profile *p,
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH BlueZ 00/11] Add local TMAS & GMAS servers
2025-12-06 11:01 [PATCH BlueZ 00/11] Add local TMAS & GMAS servers Pauli Virtanen
` (10 preceding siblings ...)
2025-12-06 11:01 ` [PATCH BlueZ 11/11] gmap: " Pauli Virtanen
@ 2025-12-08 19:20 ` patchwork-bot+bluetooth
11 siblings, 0 replies; 14+ messages in thread
From: patchwork-bot+bluetooth @ 2025-12-08 19:20 UTC (permalink / raw)
To: Pauli Virtanen; +Cc: linux-bluetooth
Hello:
This series was applied to bluetooth/bluez.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:
On Sat, 6 Dec 2025 13:01:16 +0200 you wrote:
> Parse TMAS and GMAS features to expose from
> MediaEndpoint::SupportedFeatures
>
> Improve handling of changing TMAP & GMAP features: set the service
> inactive when there is no Role set. For GMAP, we must also remove the
> feature chrc if a role is unset.
>
> [...]
Here is the summary with links:
- [BlueZ,01/11] lib: move VCS, TMAS, GMAS uuid strings to uuid.h
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=0e5f8b6431a3
- [BlueZ,02/11] shared/tester: check size before trying debug print
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=d3b7f5324ebe
- [BlueZ,03/11] shared/tmap, gmap: add macros for feature names and listing
(no matching commit)
- [BlueZ,04/11] bap: use tmap/gmap macros for listing features
(no matching commit)
- [BlueZ,05/11] shared/tmap: deactivate service if setting Role to 0
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=814e54ba288f
- [BlueZ,06/11] shared/gmap: deactivate service or remove feature chrc if role removed
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=b8d21420af2b
- [BlueZ,07/11] test-tmap: test removing and adding role
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=ef6477828392
- [BlueZ,08/11] test-gmap: test removing, adding, and changing role
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=60d707514295
- [BlueZ,09/11] media: parse SupportedFeatures from registered MediaEndpoints
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=e4b968ca4f28
- [BlueZ,10/11] tmap: remove service on device remove
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=8dcfe76b1b39
- [BlueZ,11/11] gmap: remove service on device remove
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=f1bcd84a0fb7
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 14+ messages in thread