diff mbox series

[BlueZ,v3,3/3] shared/bap: Fix bt_bap_select with multiple lpacs

Message ID 20240724160608.2779282-3-luiz.dentz@gmail.com
State Superseded
Headers show
Series [BlueZ,v3,1/3] client/player: Set number of channels based on locations | expand

Commit Message

Luiz Augusto von Dentz July 24, 2024, 4:06 p.m. UTC
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

When there are multiple local PAC records of the same codec with
different locations only the first was consider, also bt_bap_select
would stop doing location matching early if the location don't match
without considering there could be more remote channels.
---
 src/shared/bap.c | 37 +++++++++++++++++++++++++++----------
 1 file changed, 27 insertions(+), 10 deletions(-)
diff mbox series

Patch

diff --git a/src/shared/bap.c b/src/shared/bap.c
index 4bec51011469..499e740c9162 100644
--- a/src/shared/bap.c
+++ b/src/shared/bap.c
@@ -3249,25 +3249,32 @@  static void *ltv_merge(struct iovec *data, struct iovec *cont)
 	return util_iov_append(data, cont->iov_base, cont->iov_len);
 }
 
-static void bap_pac_foreach_channel(size_t i, uint8_t l, uint8_t t, uint8_t *v,
-					void *user_data)
+static void bap_pac_chan_add(struct bt_bap_pac *pac, uint8_t count,
+				uint32_t location)
 {
-	struct bt_bap_pac *pac = user_data;
 	struct bt_bap_chan *chan;
 
-	if (!v)
-		return;
-
 	if (!pac->channels)
 		pac->channels = queue_new();
 
 	chan = new0(struct bt_bap_chan, 1);
-	chan->count = *v;
-	chan->location = bt_bap_pac_get_locations(pac) ? : pac->qos.location;
+	chan->count = count;
+	chan->location = location;
 
 	queue_push_tail(pac->channels, chan);
 }
 
+static void bap_pac_foreach_channel(size_t i, uint8_t l, uint8_t t, uint8_t *v,
+					void *user_data)
+{
+	struct bt_bap_pac *pac = user_data;
+
+	if (!v)
+		return;
+
+	bap_pac_chan_add(pac, *v, bt_bap_pac_get_locations(pac));
+}
+
 static void bap_pac_update_channels(struct bt_bap_pac *pac, struct iovec *data)
 {
 	uint8_t type = 0x03;
@@ -3277,6 +3284,13 @@  static void bap_pac_update_channels(struct bt_bap_pac *pac, struct iovec *data)
 
 	util_ltv_foreach(data->iov_base, data->iov_len, &type,
 				bap_pac_foreach_channel, pac);
+
+	/* If record didn't set a channel count but set a location use that as
+	 * channel count.
+	 */
+	if (queue_isempty(pac->channels) && pac->qos.location)
+		bap_pac_chan_add(pac, pac->qos.location, pac->qos.location);
+
 }
 
 static void bap_pac_merge(struct bt_bap_pac *pac, struct iovec *data,
@@ -3607,6 +3621,9 @@  uint32_t bt_bap_pac_get_locations(struct bt_bap_pac *pac)
 	if (!pac)
 		return 0;
 
+	if (pac->qos.location)
+		return pac->qos.location;
+
 	pacs = pac->bdb->pacs;
 
 	switch (pac->type) {
@@ -5411,7 +5428,7 @@  int bt_bap_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
 
 			/* Try matching the channel location */
 			if (!(map.location & rc->location))
-				break;
+				continue;
 
 			lpac->ops->select(lpac, rpac, map.location &
 						rc->location, &rpac->qos,
@@ -5420,7 +5437,7 @@  int bt_bap_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
 			selected++;
 
 			/* Check if there are any channels left to select */
-				map.count &= ~(map.count & rc->count);
+			map.count &= ~(map.count & rc->count);
 			/* Check if there are any locations left to select */
 			map.location &= ~(map.location & rc->location);