1 /* bap_base.c - BAP BASE handling */
2 
3 /*
4  * Copyright (c) 2023 Nordic Semiconductor ASA
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <errno.h>
10 #include <stdbool.h>
11 #include <stddef.h>
12 #include <stdint.h>
13 #include <string.h>
14 
15 #include <zephyr/autoconf.h>
16 #include <zephyr/bluetooth/audio/audio.h>
17 #include <zephyr/bluetooth/audio/bap.h>
18 #include <zephyr/bluetooth/bluetooth.h>
19 #include <zephyr/bluetooth/gap.h>
20 #include <zephyr/bluetooth/iso.h>
21 #include <zephyr/bluetooth/uuid.h>
22 #include <zephyr/logging/log.h>
23 #include <zephyr/net_buf.h>
24 #include <zephyr/sys/check.h>
25 #include <zephyr/sys/util.h>
26 #include <zephyr/sys/util_macro.h>
27 
28 LOG_MODULE_REGISTER(bt_bap_base, CONFIG_BT_BAP_BASE_LOG_LEVEL);
29 
30 /* The BASE and the following defines are defined by BAP v1.0.1, section 3.7.2.2 Basic Audio
31  * Announcements
32  */
33 #define BASE_CODEC_ID_SIZE       (1 /* id */ + 2 /* cid */ + 2 /* vid */)
34 #define BASE_PD_SIZE             3
35 #define BASE_SUBGROUP_COUNT_SIZE 1
36 #define BASE_NUM_BIS_SIZE        1
37 #define BASE_CC_LEN_SIZE         1
38 #define BASE_META_LEN_SIZE       1
39 #define BASE_BIS_INDEX_SIZE      1
40 #define BASE_BIS_CC_LEN_SIZE     1
41 #define BASE_SUBGROUP_MAX_SIZE   (BT_BASE_MAX_SIZE - BASE_PD_SIZE - BASE_SUBGROUP_COUNT_SIZE)
42 #define BASE_SUBGROUP_MIN_SIZE                                                                     \
43 	(BASE_NUM_BIS_SIZE + BASE_CODEC_ID_SIZE + BASE_CC_LEN_SIZE + BASE_META_LEN_SIZE +          \
44 	 BASE_BIS_INDEX_SIZE + BASE_BIS_CC_LEN_SIZE)
45 #define BASE_MIN_SIZE                                                                              \
46 	(BT_UUID_SIZE_16 + BASE_PD_SIZE + BASE_SUBGROUP_COUNT_SIZE + BASE_SUBGROUP_MIN_SIZE)
47 #define BASE_SUBGROUP_MAX_COUNT                                                                    \
48 	((BT_BASE_MAX_SIZE - BASE_PD_SIZE - BASE_SUBGROUP_COUNT_SIZE) / BASE_SUBGROUP_MIN_SIZE)
49 
base_pull_pd(struct net_buf_simple * net_buf)50 static uint32_t base_pull_pd(struct net_buf_simple *net_buf)
51 {
52 	return net_buf_simple_pull_le24(net_buf);
53 }
54 
base_pull_bis_count(struct net_buf_simple * net_buf)55 static uint8_t base_pull_bis_count(struct net_buf_simple *net_buf)
56 {
57 	return net_buf_simple_pull_u8(net_buf);
58 }
59 
base_pull_codec_id(struct net_buf_simple * net_buf,struct bt_bap_base_codec_id * codec_id)60 static void base_pull_codec_id(struct net_buf_simple *net_buf,
61 			       struct bt_bap_base_codec_id *codec_id)
62 {
63 	struct bt_bap_base_codec_id codec;
64 
65 	codec.id = net_buf_simple_pull_u8(net_buf);    /* coding format */
66 	codec.cid = net_buf_simple_pull_le16(net_buf); /* company id */
67 	codec.vid = net_buf_simple_pull_le16(net_buf); /* VS codec id */
68 
69 	if (codec_id != NULL) {
70 		*codec_id = codec;
71 	}
72 }
73 
base_pull_ltv(struct net_buf_simple * net_buf,uint8_t ** data)74 static uint8_t base_pull_ltv(struct net_buf_simple *net_buf, uint8_t **data)
75 {
76 	const uint8_t len = net_buf_simple_pull_u8(net_buf);
77 
78 	if (data == NULL) {
79 		net_buf_simple_pull_mem(net_buf, len);
80 	} else {
81 		*data = net_buf_simple_pull_mem(net_buf, len);
82 	}
83 
84 	return len;
85 }
86 
check_pull_ltv(struct net_buf_simple * net_buf)87 static bool check_pull_ltv(struct net_buf_simple *net_buf)
88 {
89 	uint8_t ltv_len;
90 
91 	if (net_buf->len < sizeof(ltv_len)) {
92 		return false;
93 	}
94 
95 	ltv_len = net_buf_simple_pull_u8(net_buf);
96 	if (net_buf->len < ltv_len) {
97 		return false;
98 	}
99 	net_buf_simple_pull_mem(net_buf, ltv_len);
100 
101 	return true;
102 }
103 
bt_bap_base_get_base_from_ad(const struct bt_data * ad)104 const struct bt_bap_base *bt_bap_base_get_base_from_ad(const struct bt_data *ad)
105 {
106 	struct bt_uuid_16 broadcast_uuid;
107 	const struct bt_bap_base *base;
108 	struct net_buf_simple net_buf;
109 	uint8_t subgroup_count;
110 	void *uuid;
111 
112 	CHECKIF(ad == NULL) {
113 		LOG_DBG("data is NULL");
114 
115 		return NULL;
116 	}
117 
118 	if (ad->type != BT_DATA_SVC_DATA16) {
119 		LOG_DBG("Invalid type: %u", ad->type);
120 
121 		return NULL;
122 	}
123 
124 	if (ad->data_len < BASE_MIN_SIZE) {
125 		LOG_DBG("Invalid len: %u", ad->data_len);
126 
127 		return NULL;
128 	}
129 
130 	net_buf_simple_init_with_data(&net_buf, (void *)ad->data, ad->data_len);
131 
132 	uuid = net_buf_simple_pull_mem(&net_buf, BT_UUID_SIZE_16);
133 	if (!bt_uuid_create(&broadcast_uuid.uuid, uuid, BT_UUID_SIZE_16)) {
134 		LOG_ERR("bt_uuid_create failed");
135 
136 		return NULL;
137 	}
138 
139 	if (bt_uuid_cmp(&broadcast_uuid.uuid, BT_UUID_BASIC_AUDIO) != 0) {
140 		LOG_DBG("Invalid UUID");
141 
142 		return NULL;
143 	}
144 
145 	/* Store the start of the BASE */
146 	base = (const struct bt_bap_base *)net_buf.data;
147 
148 	/* Pull all data to verify that the result BASE is valid */
149 	base_pull_pd(&net_buf);
150 	subgroup_count = net_buf_simple_pull_u8(&net_buf);
151 	if (subgroup_count == 0 || subgroup_count > BASE_SUBGROUP_MAX_COUNT) {
152 		LOG_DBG("Invalid subgroup count: %u", subgroup_count);
153 
154 		return NULL;
155 	}
156 
157 	for (uint8_t i = 0U; i < subgroup_count; i++) {
158 		uint8_t bis_count;
159 
160 		if (net_buf.len < sizeof(bis_count)) {
161 			LOG_DBG("Invalid BASE length: %u", ad->data_len);
162 
163 			return NULL;
164 		}
165 
166 		bis_count = base_pull_bis_count(&net_buf);
167 		if (bis_count == 0 || bis_count > BT_ISO_MAX_GROUP_ISO_COUNT) {
168 			LOG_DBG("Subgroup[%u]: Invalid BIS count: %u", i, bis_count);
169 
170 			return NULL;
171 		}
172 
173 		if (net_buf.len < BASE_CODEC_ID_SIZE) {
174 			LOG_DBG("Invalid BASE length: %u", ad->data_len);
175 
176 			return NULL;
177 		}
178 
179 		base_pull_codec_id(&net_buf, NULL);
180 
181 		/* Pull CC */
182 		if (!check_pull_ltv(&net_buf)) {
183 			LOG_DBG("Invalid BASE length: %u", ad->data_len);
184 
185 			return NULL;
186 		}
187 
188 		/* Pull meta */
189 		if (!check_pull_ltv(&net_buf)) {
190 			LOG_DBG("Invalid BASE length: %u", ad->data_len);
191 
192 			return NULL;
193 		}
194 
195 		for (uint8_t j = 0U; j < bis_count; j++) {
196 			uint8_t bis_index;
197 
198 			if (net_buf.len < sizeof(bis_index)) {
199 				LOG_DBG("Invalid BASE length: %u", ad->data_len);
200 
201 				return NULL;
202 			}
203 
204 			bis_index = net_buf_simple_pull_u8(&net_buf);
205 			if (bis_index == 0 || bis_index > BT_ISO_BIS_INDEX_MAX) {
206 				LOG_DBG("Subgroup[%u]: Invalid BIS index: %u", i, bis_index);
207 
208 				return NULL;
209 			}
210 
211 			/* Pull BIS CC data */
212 			if (!check_pull_ltv(&net_buf)) {
213 				LOG_DBG("Invalid BASE length: %u", ad->data_len);
214 
215 				return NULL;
216 			}
217 		}
218 	}
219 
220 	return base;
221 }
222 
bt_bap_base_get_size(const struct bt_bap_base * base)223 int bt_bap_base_get_size(const struct bt_bap_base *base)
224 {
225 	struct net_buf_simple net_buf;
226 	uint8_t subgroup_count;
227 	size_t size = 0;
228 
229 	CHECKIF(base == NULL) {
230 		LOG_DBG("base is NULL");
231 
232 		return -EINVAL;
233 	}
234 
235 	net_buf_simple_init_with_data(&net_buf, (void *)base, BT_BASE_MAX_SIZE);
236 	base_pull_pd(&net_buf);
237 	size += BASE_PD_SIZE;
238 	subgroup_count = net_buf_simple_pull_u8(&net_buf);
239 	size += BASE_SUBGROUP_COUNT_SIZE;
240 
241 	/* Parse subgroup data */
242 	for (uint8_t i = 0U; i < subgroup_count; i++) {
243 		uint8_t bis_count;
244 		uint8_t len;
245 
246 		bis_count = base_pull_bis_count(&net_buf);
247 		size += BASE_NUM_BIS_SIZE;
248 
249 		base_pull_codec_id(&net_buf, NULL);
250 		size += BASE_CODEC_ID_SIZE;
251 
252 		/* Codec config */
253 		len = base_pull_ltv(&net_buf, NULL);
254 		size += len + BASE_CC_LEN_SIZE;
255 
256 		/* meta */
257 		len = base_pull_ltv(&net_buf, NULL);
258 		size += len + BASE_META_LEN_SIZE;
259 
260 		/* Parse BIS data */
261 		for (uint8_t j = 0U; j < bis_count; j++) {
262 			/* BIS index */
263 			net_buf_simple_pull_u8(&net_buf);
264 			size += BASE_BIS_INDEX_SIZE;
265 
266 			/* Codec config */
267 			len = base_pull_ltv(&net_buf, NULL);
268 			size += len + BASE_BIS_CC_LEN_SIZE;
269 		}
270 	}
271 
272 	return (int)size;
273 }
274 
bt_bap_base_get_pres_delay(const struct bt_bap_base * base)275 int bt_bap_base_get_pres_delay(const struct bt_bap_base *base)
276 {
277 	struct net_buf_simple net_buf;
278 	uint32_t pd;
279 
280 	CHECKIF(base == NULL) {
281 		LOG_DBG("base is NULL");
282 
283 		return -EINVAL;
284 	}
285 
286 	net_buf_simple_init_with_data(&net_buf, (void *)base, sizeof(pd));
287 	pd = base_pull_pd(&net_buf);
288 
289 	return (int)pd; /* PD is 24-bit so it fits in an int */
290 }
291 
bt_bap_base_get_subgroup_count(const struct bt_bap_base * base)292 int bt_bap_base_get_subgroup_count(const struct bt_bap_base *base)
293 {
294 	struct net_buf_simple net_buf;
295 	uint8_t subgroup_count;
296 
297 	CHECKIF(base == NULL) {
298 		LOG_DBG("base is NULL");
299 
300 		return -EINVAL;
301 	}
302 
303 	net_buf_simple_init_with_data(&net_buf, (void *)base, BT_BASE_MAX_SIZE);
304 	base_pull_pd(&net_buf);
305 	subgroup_count = net_buf_simple_pull_u8(&net_buf);
306 
307 	return (int)subgroup_count; /* subgroup_count is 8-bit so it fits in an int */
308 }
309 
bt_bap_base_foreach_subgroup(const struct bt_bap_base * base,bool (* func)(const struct bt_bap_base_subgroup * data,void * user_data),void * user_data)310 int bt_bap_base_foreach_subgroup(const struct bt_bap_base *base,
311 				 bool (*func)(const struct bt_bap_base_subgroup *data,
312 					      void *user_data),
313 				 void *user_data)
314 {
315 	struct bt_bap_base_subgroup *subgroup;
316 	struct net_buf_simple net_buf;
317 	uint8_t subgroup_count;
318 
319 	CHECKIF(base == NULL) {
320 		LOG_DBG("base is NULL");
321 
322 		return -EINVAL;
323 	}
324 
325 	CHECKIF(func == NULL) {
326 		LOG_DBG("func is NULL");
327 
328 		return -EINVAL;
329 	}
330 
331 	net_buf_simple_init_with_data(&net_buf, (void *)base, BT_BASE_MAX_SIZE);
332 	base_pull_pd(&net_buf);
333 	subgroup_count = net_buf_simple_pull_u8(&net_buf);
334 
335 	for (uint8_t i = 0U; i < subgroup_count; i++) {
336 		subgroup = (struct bt_bap_base_subgroup *)net_buf.data;
337 		if (!func(subgroup, user_data)) {
338 			LOG_DBG("user stopped parsing");
339 
340 			return -ECANCELED;
341 		}
342 
343 		/* Parse subgroup data to get next subgroup pointer */
344 		if (subgroup_count > 1) { /* Only parse data if it isn't the last one */
345 			uint8_t bis_count;
346 
347 			bis_count = base_pull_bis_count(&net_buf);
348 			base_pull_codec_id(&net_buf, NULL);
349 
350 			/* Codec config */
351 			base_pull_ltv(&net_buf, NULL);
352 
353 			/* meta */
354 			base_pull_ltv(&net_buf, NULL);
355 
356 			for (uint8_t j = 0U; j < bis_count; j++) {
357 				net_buf_simple_pull_u8(&net_buf); /* index */
358 
359 				/* Codec config */
360 				base_pull_ltv(&net_buf, NULL);
361 			}
362 		}
363 	}
364 
365 	return 0;
366 }
367 
bt_bap_base_get_subgroup_codec_id(const struct bt_bap_base_subgroup * subgroup,struct bt_bap_base_codec_id * codec_id)368 int bt_bap_base_get_subgroup_codec_id(const struct bt_bap_base_subgroup *subgroup,
369 				      struct bt_bap_base_codec_id *codec_id)
370 {
371 	struct net_buf_simple net_buf;
372 
373 	CHECKIF(subgroup == NULL) {
374 		LOG_DBG("subgroup is NULL");
375 
376 		return -EINVAL;
377 	}
378 
379 	CHECKIF(codec_id == NULL) {
380 		LOG_DBG("codec_id is NULL");
381 
382 		return -EINVAL;
383 	}
384 
385 	net_buf_simple_init_with_data(&net_buf, (void *)subgroup, BASE_SUBGROUP_MAX_SIZE);
386 	base_pull_bis_count(&net_buf);
387 	base_pull_codec_id(&net_buf, codec_id);
388 
389 	return 0;
390 }
391 
bt_bap_base_get_subgroup_codec_data(const struct bt_bap_base_subgroup * subgroup,uint8_t ** data)392 int bt_bap_base_get_subgroup_codec_data(const struct bt_bap_base_subgroup *subgroup, uint8_t **data)
393 {
394 	struct net_buf_simple net_buf;
395 
396 	CHECKIF(subgroup == NULL) {
397 		LOG_DBG("subgroup is NULL");
398 
399 		return -EINVAL;
400 	}
401 
402 	CHECKIF(data == NULL) {
403 		LOG_DBG("data is NULL");
404 
405 		return -EINVAL;
406 	}
407 
408 	net_buf_simple_init_with_data(&net_buf, (void *)subgroup, BASE_SUBGROUP_MAX_SIZE);
409 	base_pull_bis_count(&net_buf);
410 	base_pull_codec_id(&net_buf, NULL);
411 
412 	/* Codec config */
413 	return base_pull_ltv(&net_buf, data);
414 }
415 
bt_bap_base_get_subgroup_codec_meta(const struct bt_bap_base_subgroup * subgroup,uint8_t ** meta)416 int bt_bap_base_get_subgroup_codec_meta(const struct bt_bap_base_subgroup *subgroup, uint8_t **meta)
417 {
418 	struct net_buf_simple net_buf;
419 
420 	CHECKIF(subgroup == NULL) {
421 		LOG_DBG("subgroup is NULL");
422 
423 		return -EINVAL;
424 	}
425 
426 	CHECKIF(meta == NULL) {
427 		LOG_DBG("meta is NULL");
428 
429 		return -EINVAL;
430 	}
431 
432 	net_buf_simple_init_with_data(&net_buf, (void *)subgroup, BASE_SUBGROUP_MAX_SIZE);
433 	base_pull_bis_count(&net_buf);
434 	base_pull_codec_id(&net_buf, NULL);
435 
436 	/* Codec config */
437 	base_pull_ltv(&net_buf, NULL);
438 
439 	/* meta */
440 	return base_pull_ltv(&net_buf, meta);
441 }
442 
bt_bap_base_subgroup_codec_to_codec_cfg(const struct bt_bap_base_subgroup * subgroup,struct bt_audio_codec_cfg * codec_cfg)443 int bt_bap_base_subgroup_codec_to_codec_cfg(const struct bt_bap_base_subgroup *subgroup,
444 					    struct bt_audio_codec_cfg *codec_cfg)
445 {
446 	struct bt_bap_base_codec_id codec_id;
447 	struct net_buf_simple net_buf;
448 	uint8_t *ltv_data;
449 	uint8_t ltv_len;
450 
451 	CHECKIF(subgroup == NULL) {
452 		LOG_DBG("subgroup is NULL");
453 
454 		return -EINVAL;
455 	}
456 
457 	CHECKIF(codec_cfg == NULL) {
458 		LOG_DBG("codec_cfg is NULL");
459 
460 		return -EINVAL;
461 	}
462 
463 	net_buf_simple_init_with_data(&net_buf, (void *)subgroup, BASE_SUBGROUP_MAX_SIZE);
464 	base_pull_bis_count(&net_buf);
465 	base_pull_codec_id(&net_buf, &codec_id);
466 
467 	codec_cfg->id = codec_id.id;
468 	codec_cfg->cid = codec_id.cid;
469 	codec_cfg->vid = codec_id.vid;
470 
471 	/* Codec config */
472 	ltv_len = base_pull_ltv(&net_buf, &ltv_data);
473 
474 	if (ltv_len > ARRAY_SIZE(codec_cfg->data)) {
475 		LOG_DBG("Cannot fit %u octets of codec data (max %zu)", ltv_len,
476 			ARRAY_SIZE(codec_cfg->data));
477 
478 		return -ENOMEM;
479 	}
480 
481 	codec_cfg->data_len = ltv_len;
482 	memcpy(codec_cfg->data, ltv_data, ltv_len);
483 
484 	/* Meta */
485 	ltv_len = base_pull_ltv(&net_buf, &ltv_data);
486 
487 	if (ltv_len > ARRAY_SIZE(codec_cfg->meta)) {
488 		LOG_DBG("Cannot fit %u octets of codec meta (max %zu)", ltv_len,
489 			ARRAY_SIZE(codec_cfg->meta));
490 
491 		return -ENOMEM;
492 	}
493 
494 	codec_cfg->meta_len = ltv_len;
495 	memcpy(codec_cfg->meta, ltv_data, ltv_len);
496 
497 	return 0;
498 }
bt_bap_base_get_subgroup_bis_count(const struct bt_bap_base_subgroup * subgroup)499 int bt_bap_base_get_subgroup_bis_count(const struct bt_bap_base_subgroup *subgroup)
500 {
501 	struct net_buf_simple net_buf;
502 
503 	CHECKIF(subgroup == NULL) {
504 		LOG_DBG("subgroup is NULL");
505 
506 		return -EINVAL;
507 	}
508 
509 	net_buf_simple_init_with_data(&net_buf, (void *)subgroup, BASE_SUBGROUP_MAX_SIZE);
510 
511 	return base_pull_bis_count(&net_buf);
512 }
513 
bt_bap_base_subgroup_foreach_bis(const struct bt_bap_base_subgroup * subgroup,bool (* func)(const struct bt_bap_base_subgroup_bis * subgroup,void * user_data),void * user_data)514 int bt_bap_base_subgroup_foreach_bis(const struct bt_bap_base_subgroup *subgroup,
515 				     bool (*func)(const struct bt_bap_base_subgroup_bis *subgroup,
516 						  void *user_data),
517 				     void *user_data)
518 {
519 	struct net_buf_simple net_buf;
520 	uint8_t bis_count;
521 
522 	CHECKIF(subgroup == NULL) {
523 		LOG_DBG("subgroup is NULL");
524 
525 		return -EINVAL;
526 	}
527 
528 	CHECKIF(func == NULL) {
529 		LOG_DBG("func is NULL");
530 
531 		return -EINVAL;
532 	}
533 
534 	net_buf_simple_init_with_data(&net_buf, (void *)subgroup, BASE_SUBGROUP_MAX_SIZE);
535 
536 	bis_count = base_pull_bis_count(&net_buf);
537 	base_pull_codec_id(&net_buf, NULL);
538 
539 	/* Codec config */
540 	base_pull_ltv(&net_buf, NULL);
541 
542 	/* meta */
543 	base_pull_ltv(&net_buf, NULL);
544 
545 	for (uint8_t i = 0U; i < bis_count; i++) {
546 		struct bt_bap_base_subgroup_bis bis;
547 
548 		bis.index = net_buf_simple_pull_u8(&net_buf); /* index */
549 
550 		/* Codec config */
551 		bis.data_len = base_pull_ltv(&net_buf, &bis.data);
552 
553 		if (!func(&bis, user_data)) {
554 			LOG_DBG("user stopped parsing");
555 
556 			return -ECANCELED;
557 		}
558 	}
559 
560 	return 0;
561 }
562 
bt_bap_base_subgroup_bis_codec_to_codec_cfg(const struct bt_bap_base_subgroup_bis * bis,struct bt_audio_codec_cfg * codec_cfg)563 int bt_bap_base_subgroup_bis_codec_to_codec_cfg(const struct bt_bap_base_subgroup_bis *bis,
564 						struct bt_audio_codec_cfg *codec_cfg)
565 {
566 	CHECKIF(bis == NULL) {
567 		LOG_DBG("bis is NULL");
568 
569 		return -EINVAL;
570 	}
571 
572 	CHECKIF(codec_cfg == NULL) {
573 		LOG_DBG("codec_cfg is NULL");
574 
575 		return -EINVAL;
576 	}
577 
578 	if (bis->data_len > ARRAY_SIZE(codec_cfg->data)) {
579 		LOG_DBG("Cannot fit %u octets of codec data (max %zu)", bis->data_len,
580 			ARRAY_SIZE(codec_cfg->data));
581 
582 		return -ENOMEM;
583 	}
584 
585 	codec_cfg->data_len = bis->data_len;
586 	memcpy(codec_cfg->data, bis->data, bis->data_len);
587 
588 	return 0;
589 }
590 
base_subgroup_bis_cb(const struct bt_bap_base_subgroup_bis * bis,void * user_data)591 static bool base_subgroup_bis_cb(const struct bt_bap_base_subgroup_bis *bis, void *user_data)
592 {
593 	uint32_t *base_bis_index_bitfield = user_data;
594 
595 	*base_bis_index_bitfield |= BT_ISO_BIS_INDEX_BIT(bis->index);
596 
597 	return true;
598 }
599 
base_subgroup_cb(const struct bt_bap_base_subgroup * subgroup,void * user_data)600 static bool base_subgroup_cb(const struct bt_bap_base_subgroup *subgroup, void *user_data)
601 {
602 	const int err = bt_bap_base_subgroup_foreach_bis(subgroup, base_subgroup_bis_cb, user_data);
603 
604 	if (err != 0) {
605 		LOG_DBG("Failed to parse all BIS: %d", err);
606 		return false;
607 	}
608 
609 	return true;
610 }
611 
bt_bap_base_subgroup_get_bis_indexes(const struct bt_bap_base_subgroup * subgroup,uint32_t * bis_indexes)612 int bt_bap_base_subgroup_get_bis_indexes(const struct bt_bap_base_subgroup *subgroup,
613 					 uint32_t *bis_indexes)
614 {
615 	CHECKIF(subgroup == NULL) {
616 		LOG_DBG("subgroup is NULL");
617 
618 		return -EINVAL;
619 	}
620 
621 	CHECKIF(bis_indexes == NULL) {
622 		LOG_DBG("bis_indexes is NULL");
623 
624 		return -EINVAL;
625 	}
626 
627 	*bis_indexes = 0U;
628 
629 	return bt_bap_base_subgroup_foreach_bis(subgroup, base_subgroup_bis_cb, bis_indexes);
630 }
631 
bt_bap_base_get_bis_indexes(const struct bt_bap_base * base,uint32_t * bis_indexes)632 int bt_bap_base_get_bis_indexes(const struct bt_bap_base *base, uint32_t *bis_indexes)
633 {
634 	CHECKIF(base == NULL) {
635 		LOG_DBG("base is NULL");
636 
637 		return -EINVAL;
638 	}
639 
640 	CHECKIF(bis_indexes == NULL) {
641 		LOG_DBG("bis_indexes is NULL");
642 
643 		return -EINVAL;
644 	}
645 
646 	*bis_indexes = 0U;
647 
648 	return bt_bap_base_foreach_subgroup(base, base_subgroup_cb, bis_indexes);
649 }
650