@@ -2468,6 +2468,80 @@ static void bap_pac_free(void *data)
free(pac);
}
+static void pacs_sink_location_changed(struct bt_pacs *pacs)
+{
+ uint32_t location = cpu_to_le32(pacs->sink_loc_value);
+
+ gatt_db_attribute_notify(pacs->sink_loc, (void *)&location,
+ sizeof(location), NULL);
+}
+
+static void pacs_add_sink_location(struct bt_pacs *pacs, uint32_t location)
+{
+ location |= pacs->sink_loc_value;
+
+ /* Check if location value needs updating */
+ if (location == pacs->sink_loc_value)
+ return;
+
+ pacs->sink_loc_value = location;
+
+ pacs_sink_location_changed(pacs);
+}
+
+static void pacs_supported_context_changed(struct bt_pacs *pacs)
+{
+ struct bt_pacs_context ctx;
+
+ memset(&ctx, 0, sizeof(ctx));
+
+ ctx.snk = cpu_to_le16(pacs->supported_sink_context_value);
+ ctx.src = cpu_to_le16(pacs->supported_source_context_value);
+
+ gatt_db_attribute_notify(pacs->supported_context, (void *)&ctx,
+ sizeof(ctx), NULL);
+}
+
+static void pacs_add_sink_supported_context(struct bt_pacs *pacs,
+ uint16_t context)
+{
+ context |= pacs->supported_sink_context_value;
+
+ /* Check if context value needs updating */
+ if (context == pacs->supported_sink_context_value)
+ return;
+
+ pacs->supported_sink_context_value = context;
+
+ pacs_supported_context_changed(pacs);
+}
+
+static void pacs_context_changed(struct bt_pacs *pacs)
+{
+ struct bt_pacs_context ctx;
+
+ memset(&ctx, 0, sizeof(ctx));
+
+ ctx.snk = cpu_to_le16(pacs->sink_context_value);
+ ctx.src = cpu_to_le16(pacs->source_context_value);
+
+ gatt_db_attribute_notify(pacs->context, (void *)&ctx, sizeof(ctx),
+ NULL);
+}
+
+static void pacs_add_sink_context(struct bt_pacs *pacs, uint16_t context)
+{
+ context |= pacs->supported_sink_context_value;
+
+ /* Check if context value needs updating */
+ if (context == pacs->sink_context_value)
+ return;
+
+ pacs->sink_context_value = context;
+
+ pacs_context_changed(pacs);
+}
+
static void bap_add_sink(struct bt_bap_pac *pac)
{
struct iovec iov;
@@ -2482,10 +2556,62 @@ static void bap_add_sink(struct bt_bap_pac *pac)
queue_foreach(pac->bdb->sinks, pac_foreach, &iov);
+ pacs_add_sink_location(pac->bdb->pacs, pac->qos.location);
+ pacs_add_sink_supported_context(pac->bdb->pacs,
+ pac->qos.supported_context);
+ pacs_add_sink_context(pac->bdb->pacs, pac->qos.context);
gatt_db_attribute_notify(pac->bdb->pacs->sink, iov.iov_base,
iov.iov_len, NULL);
}
+static void pacs_source_location_changed(struct bt_pacs *pacs)
+{
+ uint32_t location = cpu_to_le32(pacs->source_loc_value);
+
+ gatt_db_attribute_notify(pacs->source_loc, (void *)&location,
+ sizeof(location), NULL);
+}
+
+static void pacs_add_source_location(struct bt_pacs *pacs, uint32_t location)
+{
+ location |= pacs->source_loc_value;
+
+ /* Check if location value needs updating */
+ if (location == pacs->source_loc_value)
+ return;
+
+ pacs->source_loc_value = location;
+
+ pacs_source_location_changed(pacs);
+}
+
+static void pacs_add_source_supported_context(struct bt_pacs *pacs,
+ uint16_t context)
+{
+ context |= pacs->supported_source_context_value;
+
+ /* Check if context value needs updating */
+ if (context == pacs->supported_source_context_value)
+ return;
+
+ pacs->supported_source_context_value = context;
+
+ pacs_supported_context_changed(pacs);
+}
+
+static void pacs_add_source_context(struct bt_pacs *pacs, uint16_t context)
+{
+ context |= pacs->supported_sink_context_value;
+
+ /* Check if context value needs updating */
+ if (context == pacs->sink_context_value)
+ return;
+
+ pacs->sink_context_value = context;
+
+ pacs_context_changed(pacs);
+}
+
static void bap_add_source(struct bt_bap_pac *pac)
{
struct iovec iov;
@@ -2500,6 +2626,11 @@ static void bap_add_source(struct bt_bap_pac *pac)
queue_foreach(pac->bdb->sinks, pac_foreach, &iov);
+ pacs_add_source_location(pac->bdb->pacs, pac->qos.location);
+ pacs_add_source_supported_context(pac->bdb->pacs,
+ pac->qos.supported_context);
+ pacs_add_source_context(pac->bdb->pacs, pac->qos.context);
+
gatt_db_attribute_notify(pac->bdb->pacs->source, iov.iov_base,
iov.iov_len, NULL);
}
@@ -2685,13 +2816,48 @@ static void remove_streams(void *data, void *user_data)
bt_bap_stream_release(stream, NULL, NULL);
}
+static void bap_pac_sink_removed(void *data, void *user_data)
+{
+ struct bt_bap_pac *pac = data;
+ struct bt_bap_pac_qos *qos = user_data;
+
+ qos->location |= pac->qos.location;
+ qos->supported_context |= pac->qos.supported_context;
+ qos->context |= pac->qos.context;
+}
+
bool bt_bap_remove_pac(struct bt_bap_pac *pac)
{
if (!pac)
return false;
- if (queue_remove_if(pac->bdb->sinks, NULL, pac))
+ if (queue_remove_if(pac->bdb->sinks, NULL, pac)) {
+ struct bt_pacs *pacs = pac->bdb->pacs;
+ struct bt_bap_pac_qos qos;
+
+ memset(&qos, 0, sizeof(qos));
+ queue_foreach(pac->bdb->sinks, bap_pac_sink_removed, &qos);
+
+ if (pacs->sink_loc_value != qos.location) {
+ pacs->sink_loc_value = qos.location;
+ pacs_sink_location_changed(pacs);
+ }
+
+ if (pacs->supported_sink_context_value !=
+ qos.supported_context) {
+ pacs->supported_sink_context_value =
+ qos.supported_context;
+ pacs_supported_context_changed(pacs);
+ }
+
+ if (pacs->sink_context_value != qos.context) {
+ pacs->sink_context_value = qos.context;
+ pacs_context_changed(pacs);
+ }
+
+
goto found;
+ }
if (queue_remove_if(pac->bdb->sources, NULL, pac))
goto found;
@@ -131,6 +131,9 @@ struct bt_bap_pac_qos {
uint32_t pd_max;
uint32_t ppd_min;
uint32_t ppd_max;
+ uint32_t location;
+ uint16_t supported_context;
+ uint16_t context;
};
struct bt_bap_pac *bt_bap_add_vendor_pac(struct gatt_db *db,
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> This adds support for setting supported content and contexts on a per PAC record basis which then is carried over to their respective PACS attribute and notified properly when changed (added/removed). --- src/shared/bap.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++- src/shared/bap.h | 3 + 2 files changed, 170 insertions(+), 1 deletion(-)