[PATCH BlueZ 4/7] shared/bass: Add APIs to register bcast src changed cb

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



A BAP Broadcast Assistant (BASS Client) needs to listen for GATT
notifications for Broadcast Receive State characteristics from peer
Scan Delegators (BASS Servers), in order to learn about updates in
Broadcasters known by the peer - for example, the Assistant can be
informed if the peer requires a Broadcast Code to decrypt an encrypted
stream.

This adds APIs that the BASS plugin can use to register/unregister
callbacks to be called on each received notification.
---
 src/shared/bass.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++
 src/shared/bass.h |  5 +++
 2 files changed, 100 insertions(+)

diff --git a/src/shared/bass.c b/src/shared/bass.c
index d9ab210b7..b54bf3094 100644
--- a/src/shared/bass.c
+++ b/src/shared/bass.c
@@ -71,6 +71,8 @@ struct bt_bass {
 	bt_bass_destroy_func_t debug_destroy;
 	void *debug_data;
 
+	struct queue *src_cbs;
+
 	void *user_data;
 };
 
@@ -118,6 +120,13 @@ static struct bt_iso_qos default_qos = {
 	}
 };
 
+struct bt_bass_src_changed {
+	unsigned int id;
+	bt_bass_src_func_t cb;
+	bt_bass_destroy_func_t destroy;
+	void *data;
+};
+
 static void bass_bcast_src_free(void *data);
 
 static void bass_debug(struct bt_bass *bass, const char *format, ...)
@@ -132,6 +141,64 @@ static void bass_debug(struct bt_bass *bass, const char *format, ...)
 	va_end(ap);
 }
 
+unsigned int bt_bass_src_register(struct bt_bass *bass, bt_bass_src_func_t cb,
+				void *user_data, bt_bass_destroy_func_t destroy)
+{
+	struct bt_bass_src_changed *changed;
+	static unsigned int id;
+
+	if (!bass)
+		return 0;
+
+	changed = new0(struct bt_bass_src_changed, 1);
+	if (!changed)
+		return 0;
+
+	changed->id = ++id ? id : ++id;
+	changed->cb = cb;
+	changed->destroy = destroy;
+	changed->data = user_data;
+
+	queue_push_tail(bass->src_cbs, changed);
+
+	return changed->id;
+}
+
+static void bass_src_changed_free(void *data)
+{
+	struct bt_bass_src_changed *changed = data;
+
+	if (changed->destroy)
+		changed->destroy(changed->data);
+
+	free(changed);
+}
+
+static bool match_src_changed_id(const void *data, const void *match_data)
+{
+	const struct bt_bass_src_changed *changed = data;
+	unsigned int id = PTR_TO_UINT(match_data);
+
+	return (changed->id == id);
+}
+
+bool bt_bass_src_unregister(struct bt_bass *bass, unsigned int id)
+{
+	struct bt_bass_src_changed *changed;
+
+	if (!bass)
+		return false;
+
+	changed = queue_remove_if(bass->src_cbs, match_src_changed_id,
+						UINT_TO_PTR(id));
+	if (!changed)
+		return false;
+
+	bass_src_changed_free(changed);
+
+	return true;
+}
+
 static int bass_build_bcast_src(struct bt_bcast_src *bcast_src,
 				const uint8_t *value, uint16_t length)
 {
@@ -1321,6 +1388,27 @@ static void read_bcast_recv_state(bool success, uint8_t att_ecode,
 	}
 }
 
+static void notify_src_changed(void *data, void *user_data)
+{
+	struct bt_bass_src_changed *changed = data;
+	struct bt_bcast_src *bcast_src = user_data;
+	uint32_t bis_sync = 0;
+
+	for (uint8_t i = 0; i < bcast_src->num_subgroups; i++) {
+		struct bt_bass_subgroup_data *sgrp =
+				&bcast_src->subgroup_data[i];
+
+		/* Create a bitmask of all BIS indices that the peer has
+		 * synchronized with.
+		 */
+		bis_sync |= sgrp->bis_sync;
+	}
+
+	if (changed->cb)
+		changed->cb(bcast_src->id, bcast_src->bid, bcast_src->enc,
+					bis_sync, changed->data);
+}
+
 static void bcast_recv_state_notify(struct bt_bass *bass, uint16_t value_handle,
 				const uint8_t *value, uint16_t length,
 				void *user_data)
@@ -1353,6 +1441,11 @@ static void bcast_recv_state_notify(struct bt_bass *bass, uint16_t value_handle,
 
 	if (new_src)
 		queue_push_tail(bass->rdb->bcast_srcs, bcast_src);
+
+	/* Notify the update in the Broadcast Receive State characteristic
+	 * to all drivers that registered a callback.
+	 */
+	queue_foreach(bass->src_cbs, notify_src_changed, bcast_src);
 }
 
 static void bass_register(uint16_t att_ecode, void *user_data)
@@ -1562,6 +1655,7 @@ static void bass_free(void *data)
 	bt_bass_detach(bass);
 	bass_db_free(bass->rdb);
 	queue_destroy(bass->notify, NULL);
+	queue_destroy(bass->src_cbs, bass_src_changed_free);
 
 	free(bass);
 }
@@ -1656,6 +1750,7 @@ struct bt_bass *bt_bass_new(struct gatt_db *ldb, struct gatt_db *rdb,
 	bass = new0(struct bt_bass, 1);
 	bass->ldb = db;
 	bass->notify = queue_new();
+	bass->src_cbs = queue_new();
 
 	if (!rdb)
 		goto done;
diff --git a/src/shared/bass.h b/src/shared/bass.h
index 864b01637..01c1279bb 100644
--- a/src/shared/bass.h
+++ b/src/shared/bass.h
@@ -119,6 +119,8 @@ struct bt_bass_remove_src_params {
 typedef void (*bt_bass_func_t)(struct bt_bass *bass, void *user_data);
 typedef void (*bt_bass_destroy_func_t)(void *user_data);
 typedef void (*bt_bass_debug_func_t)(const char *str, void *user_data);
+typedef void (*bt_bass_src_func_t)(uint8_t id, uint32_t bid, uint8_t enc,
+					uint32_t bis_sync, void *user_data);
 
 struct bt_att *bt_bass_get_att(struct bt_bass *bass);
 struct bt_gatt_client *bt_bass_get_client(struct bt_bass *bass);
@@ -138,3 +140,6 @@ void bt_bass_add_db(struct gatt_db *db, const bdaddr_t *adapter_bdaddr);
 int bt_bass_send(struct bt_bass *bass,
 		struct bt_bass_bcast_audio_scan_cp_hdr *hdr,
 		struct iovec *params);
+unsigned int bt_bass_src_register(struct bt_bass *bass, bt_bass_src_func_t cb,
+			void *user_data, bt_bass_destroy_func_t destroy);
+bool bt_bass_src_unregister(struct bt_bass *bass, unsigned int id);
-- 
2.39.2





[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux