1 /*
2 * Copyright (c) 2022 Bose Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 /** @file
7 * @brief Bluetooth LE-Audio codec LTV parsing
8 *
9 * Helper functions to parse codec config data as specified in the Bluetooth assigned numbers for
10 * Generic Audio.
11 */
12
13 #include <stdlib.h>
14
15 #include <zephyr/bluetooth/audio/audio.h>
16 #include <zephyr/sys/byteorder.h>
17 #include <zephyr/sys/check.h>
18
19 #include <zephyr/logging/log.h>
20
21 LOG_MODULE_REGISTER(bt_audio_codec, CONFIG_BT_AUDIO_CODEC_LOG_LEVEL);
22
bt_audio_codec_cfg_freq_to_freq_hz(enum bt_audio_codec_config_freq freq)23 int bt_audio_codec_cfg_freq_to_freq_hz(enum bt_audio_codec_config_freq freq)
24 {
25 switch (freq) {
26 case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_8KHZ:
27 return 8000;
28 case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_11KHZ:
29 return 11025;
30 case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_16KHZ:
31 return 16000;
32 case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_22KHZ:
33 return 22050;
34 case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_24KHZ:
35 return 24000;
36 case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_32KHZ:
37 return 32000;
38 case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_44KHZ:
39 return 44100;
40 case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ:
41 return 48000;
42 case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_88KHZ:
43 return 88200;
44 case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_96KHZ:
45 return 96000;
46 case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_176KHZ:
47 return 176400;
48 case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_192KHZ:
49 return 192000;
50 case BT_AUDIO_CODEC_CONFIG_LC3_FREQ_384KHZ:
51 return 384000;
52 default:
53 return -EINVAL;
54 }
55 }
56
bt_audio_codec_cfg_freq_hz_to_freq(uint32_t freq_hz)57 int bt_audio_codec_cfg_freq_hz_to_freq(uint32_t freq_hz)
58 {
59 switch (freq_hz) {
60 case 8000U:
61 return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_8KHZ;
62 case 11025U:
63 return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_11KHZ;
64 case 16000U:
65 return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_16KHZ;
66 case 22050U:
67 return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_22KHZ;
68 case 24000U:
69 return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_24KHZ;
70 case 32000U:
71 return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_32KHZ;
72 case 44100U:
73 return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_44KHZ;
74 case 48000U:
75 return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ;
76 case 88200U:
77 return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_88KHZ;
78 case 96000U:
79 return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_96KHZ;
80 case 176400U:
81 return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_176KHZ;
82 case 192000U:
83 return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_192KHZ;
84 case 384000U:
85 return BT_AUDIO_CODEC_CONFIG_LC3_FREQ_384KHZ;
86 default:
87 return -EINVAL;
88 }
89 }
90
91 struct search_type_param {
92 bool found;
93 uint8_t type;
94 uint8_t data_len;
95 const uint8_t **data;
96 };
97
parse_cb(struct bt_data * data,void * user_data)98 static bool parse_cb(struct bt_data *data, void *user_data)
99 {
100 struct search_type_param *param = (struct search_type_param *)user_data;
101
102 if (param->type == data->type) {
103 param->found = true;
104 param->data_len = data->data_len;
105 *param->data = data->data;
106
107 return false;
108 }
109
110 return true;
111 }
112
113 #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0
114
init_net_buf_simple_from_codec_cfg(struct net_buf_simple * buf,struct bt_audio_codec_cfg * codec_cfg)115 static void init_net_buf_simple_from_codec_cfg(struct net_buf_simple *buf,
116 struct bt_audio_codec_cfg *codec_cfg)
117 {
118 buf->__buf = codec_cfg->data;
119 buf->data = codec_cfg->data;
120 buf->size = sizeof(codec_cfg->data);
121 buf->len = codec_cfg->data_len;
122 }
123
bt_audio_codec_cfg_get_val(const struct bt_audio_codec_cfg * codec_cfg,uint8_t type,const uint8_t ** data)124 uint8_t bt_audio_codec_cfg_get_val(const struct bt_audio_codec_cfg *codec_cfg, uint8_t type,
125 const uint8_t **data)
126 {
127 struct search_type_param param = {
128 .found = false,
129 .type = type,
130 .data_len = 0,
131 .data = data,
132 };
133 int err;
134
135 CHECKIF(codec_cfg == NULL) {
136 LOG_DBG("codec is NULL");
137 return 0;
138 }
139
140 CHECKIF(data == NULL) {
141 LOG_DBG("data is NULL");
142 return 0;
143 }
144
145 *data = NULL;
146
147 err = bt_audio_data_parse(codec_cfg->data, codec_cfg->data_len, parse_cb, ¶m);
148 if (err != 0 && err != -ECANCELED) {
149 LOG_DBG("Could not parse the data: %d", err);
150 return 0;
151 }
152
153 if (param.data == NULL) {
154 LOG_DBG("Could not find the type %u", type);
155 return 0;
156 }
157
158 return param.data_len;
159 }
160
bt_audio_codec_cfg_set_val(struct bt_audio_codec_cfg * codec_cfg,uint8_t type,const uint8_t * data,size_t data_len)161 int bt_audio_codec_cfg_set_val(struct bt_audio_codec_cfg *codec_cfg, uint8_t type,
162 const uint8_t *data, size_t data_len)
163 {
164 CHECKIF(codec_cfg == NULL) {
165 LOG_DBG("codec_cfg is NULL");
166 return -EINVAL;
167 }
168
169 CHECKIF(data == NULL) {
170 LOG_DBG("data is NULL");
171 return -EINVAL;
172 }
173
174 CHECKIF(data_len == 0U || data_len > UINT8_MAX) {
175 LOG_DBG("Invalid data_len %zu", data_len);
176 return -EINVAL;
177 }
178
179 for (uint16_t i = 0U; i < codec_cfg->data_len;) {
180 uint8_t *len = &codec_cfg->data[i++];
181 const uint8_t data_type = codec_cfg->data[i++];
182 const uint8_t value_len = *len - sizeof(data_type);
183
184 if (data_type == type) {
185 uint8_t *value = &codec_cfg->data[i];
186
187 if (data_len == value_len) {
188 memcpy(value, data, data_len);
189 } else {
190 const int16_t diff = data_len - value_len;
191 uint8_t *old_next_data_start;
192 uint8_t *new_next_data_start;
193 uint8_t data_len_to_move;
194
195 /* Check if this is the last value in the buffer */
196 if (value + value_len == codec_cfg->data + codec_cfg->data_len) {
197 data_len_to_move = 0U;
198 } else {
199 old_next_data_start = value + value_len + 1;
200 new_next_data_start = value + data_len + 1;
201 data_len_to_move = codec_cfg->data_len -
202 (old_next_data_start - codec_cfg->data);
203 }
204
205 if (diff < 0) {
206 /* In this case we need to move memory around after the copy
207 * to fit the new shorter data
208 */
209
210 memcpy(value, data, data_len);
211 if (data_len_to_move > 0U) {
212 memmove(new_next_data_start, old_next_data_start,
213 data_len_to_move);
214 }
215 } else {
216 /* In this case we need to move memory around before
217 * the copy to fit the new longer data
218 */
219 if ((codec_cfg->data_len + diff) >
220 ARRAY_SIZE(codec_cfg->data)) {
221 LOG_DBG("Cannot fit data_len %zu in buf with len "
222 "%u and size %u",
223 data_len, codec_cfg->data_len,
224 ARRAY_SIZE(codec_cfg->data));
225 return -ENOMEM;
226 }
227
228 if (data_len_to_move > 0) {
229 memmove(new_next_data_start, old_next_data_start,
230 data_len_to_move);
231 }
232
233 memcpy(value, data, data_len);
234 }
235
236 codec_cfg->data_len += diff;
237 *len += diff;
238 }
239
240 return codec_cfg->data_len;
241 }
242
243 i += value_len;
244 }
245
246 /* If we reach here, we did not find the data in the buffer, so we simply add it */
247 if ((codec_cfg->data_len + data_len) <= ARRAY_SIZE(codec_cfg->data)) {
248 struct net_buf_simple buf;
249
250 init_net_buf_simple_from_codec_cfg(&buf, codec_cfg);
251
252 net_buf_simple_add_u8(&buf, data_len + sizeof(type));
253 net_buf_simple_add_u8(&buf, type);
254 if (data_len > 0) {
255 net_buf_simple_add_mem(&buf, data, data_len);
256 }
257 codec_cfg->data_len = buf.len;
258 } else {
259 LOG_DBG("Cannot fit data_len %zu in codec_cfg with len %u and size %u", data_len,
260 codec_cfg->data_len, ARRAY_SIZE(codec_cfg->data));
261 return -ENOMEM;
262 }
263
264 return codec_cfg->data_len;
265 }
266
bt_audio_codec_cfg_get_freq(const struct bt_audio_codec_cfg * codec_cfg)267 int bt_audio_codec_cfg_get_freq(const struct bt_audio_codec_cfg *codec_cfg)
268 {
269 enum bt_audio_codec_config_freq freq;
270 const uint8_t *data;
271 uint8_t data_len;
272
273 CHECKIF(codec_cfg == NULL) {
274 LOG_DBG("codec is NULL");
275 return -EINVAL;
276 }
277
278 data_len = bt_audio_codec_cfg_get_val(codec_cfg, BT_AUDIO_CODEC_CONFIG_LC3_FREQ, &data);
279 if (data == NULL) {
280 return -ENODATA;
281 }
282
283 if (data_len != sizeof(uint8_t)) {
284 return -EBADMSG;
285 }
286
287 freq = data[0];
288 if (bt_audio_codec_cfg_freq_to_freq_hz(freq) < 0) {
289 LOG_DBG("Invalid freq value: 0x%02X", freq);
290 return -EBADMSG;
291 }
292
293 return freq;
294 }
295
bt_audio_codec_cfg_set_freq(struct bt_audio_codec_cfg * codec_cfg,enum bt_audio_codec_config_freq freq)296 int bt_audio_codec_cfg_set_freq(struct bt_audio_codec_cfg *codec_cfg,
297 enum bt_audio_codec_config_freq freq)
298 {
299 uint8_t freq_u8;
300
301 if (bt_audio_codec_cfg_freq_to_freq_hz(freq) < 0) {
302 LOG_DBG("Invalid freq value: %d", freq);
303 return -EINVAL;
304 }
305
306 freq_u8 = (uint8_t)freq;
307
308 return bt_audio_codec_cfg_set_val(codec_cfg, BT_AUDIO_CODEC_CONFIG_LC3_FREQ, &freq_u8,
309 sizeof(freq_u8));
310 }
311
bt_audio_codec_cfg_get_frame_duration_us(const struct bt_audio_codec_cfg * codec_cfg)312 int bt_audio_codec_cfg_get_frame_duration_us(const struct bt_audio_codec_cfg *codec_cfg)
313 {
314 const uint8_t *data;
315 uint8_t data_len;
316
317 CHECKIF(codec_cfg == NULL) {
318 LOG_DBG("codec is NULL");
319 return -EINVAL;
320 }
321
322 data_len = bt_audio_codec_cfg_get_val(codec_cfg, BT_AUDIO_CODEC_CONFIG_LC3_DURATION, &data);
323 if (data == NULL) {
324 return -ENODATA;
325 }
326
327 if (data_len != sizeof(uint8_t)) {
328 return -EBADMSG;
329 }
330
331 switch (data[0]) {
332 case BT_AUDIO_CODEC_CONFIG_LC3_DURATION_7_5:
333 return 7500;
334 case BT_AUDIO_CODEC_CONFIG_LC3_DURATION_10:
335 return 10000;
336 default:
337 return -EBADMSG;
338 }
339 }
340
bt_audio_codec_cfg_get_chan_allocation(const struct bt_audio_codec_cfg * codec_cfg,enum bt_audio_location * chan_allocation)341 int bt_audio_codec_cfg_get_chan_allocation(const struct bt_audio_codec_cfg *codec_cfg,
342 enum bt_audio_location *chan_allocation)
343 {
344 const uint8_t *data;
345 uint8_t data_len;
346
347 *chan_allocation = 0;
348
349 CHECKIF(codec_cfg == NULL) {
350 LOG_DBG("codec is NULL");
351 return -EINVAL;
352 }
353
354 CHECKIF(chan_allocation == NULL) {
355 return -EINVAL;
356 }
357
358 data_len =
359 bt_audio_codec_cfg_get_val(codec_cfg, BT_AUDIO_CODEC_CONFIG_LC3_CHAN_ALLOC, &data);
360 if (data == NULL) {
361 return -ENODATA;
362 }
363
364 if (data_len != sizeof(uint32_t)) {
365 return -EBADMSG;
366 }
367
368 *chan_allocation = sys_get_le32(data);
369
370 return 0;
371 }
372
bt_audio_codec_cfg_set_chan_allocation(struct bt_audio_codec_cfg * codec_cfg,enum bt_audio_location chan_allocation)373 int bt_audio_codec_cfg_set_chan_allocation(struct bt_audio_codec_cfg *codec_cfg,
374 enum bt_audio_location chan_allocation)
375 {
376 uint32_t chan_allocation_u32;
377
378 if ((chan_allocation & BT_AUDIO_LOCATION_ANY) != chan_allocation) {
379 LOG_DBG("Invalid chan_allocation value: 0x%08X", chan_allocation);
380 return -EINVAL;
381 }
382
383 chan_allocation_u32 = sys_cpu_to_le32((uint32_t)chan_allocation);
384
385 return bt_audio_codec_cfg_set_val(codec_cfg, BT_AUDIO_CODEC_CONFIG_LC3_CHAN_ALLOC,
386 (const uint8_t *)&chan_allocation_u32,
387 sizeof(chan_allocation_u32));
388 }
389
bt_audio_codec_cfg_get_octets_per_frame(const struct bt_audio_codec_cfg * codec_cfg)390 int bt_audio_codec_cfg_get_octets_per_frame(const struct bt_audio_codec_cfg *codec_cfg)
391 {
392 const uint8_t *data;
393 uint8_t data_len;
394
395 CHECKIF(codec_cfg == NULL) {
396 LOG_DBG("codec is NULL");
397 return -EINVAL;
398 }
399
400 data_len =
401 bt_audio_codec_cfg_get_val(codec_cfg, BT_AUDIO_CODEC_CONFIG_LC3_FRAME_LEN, &data);
402 if (data == NULL) {
403 return -ENODATA;
404 }
405
406 if (data_len != sizeof(uint16_t)) {
407 return -EBADMSG;
408 }
409
410 return sys_get_le16(data);
411 }
412
bt_audio_codec_cfg_set_octets_per_frame(struct bt_audio_codec_cfg * codec_cfg,uint16_t octets_per_frame)413 int bt_audio_codec_cfg_set_octets_per_frame(struct bt_audio_codec_cfg *codec_cfg,
414 uint16_t octets_per_frame)
415 {
416 uint16_t octets_per_frame_le16;
417
418 octets_per_frame_le16 = sys_cpu_to_le16(octets_per_frame);
419
420 return bt_audio_codec_cfg_set_val(codec_cfg, BT_AUDIO_CODEC_CONFIG_LC3_FRAME_LEN,
421 (uint8_t *)&octets_per_frame_le16,
422 sizeof(octets_per_frame_le16));
423 }
424
bt_audio_codec_cfg_get_frame_blocks_per_sdu(const struct bt_audio_codec_cfg * codec_cfg,bool fallback_to_default)425 int bt_audio_codec_cfg_get_frame_blocks_per_sdu(const struct bt_audio_codec_cfg *codec_cfg,
426 bool fallback_to_default)
427 {
428 const uint8_t *data;
429 uint8_t data_len;
430
431 CHECKIF(codec_cfg == NULL) {
432 LOG_DBG("codec is NULL");
433 return -EINVAL;
434 }
435
436 data_len = bt_audio_codec_cfg_get_val(codec_cfg,
437 BT_AUDIO_CODEC_CONFIG_LC3_FRAME_BLKS_PER_SDU, &data);
438 if (data == NULL) {
439 if (fallback_to_default) {
440 return 1;
441 }
442
443 return -ENODATA;
444 }
445
446 if (data_len != sizeof(uint8_t)) {
447 return -EBADMSG;
448 }
449
450 return data[0];
451 }
452
bt_audio_codec_cfg_set_frame_blocks_per_sdu(struct bt_audio_codec_cfg * codec_cfg,uint8_t frame_blocks)453 int bt_audio_codec_cfg_set_frame_blocks_per_sdu(struct bt_audio_codec_cfg *codec_cfg,
454 uint8_t frame_blocks)
455 {
456 return bt_audio_codec_cfg_set_val(codec_cfg, BT_AUDIO_CODEC_CONFIG_LC3_FRAME_BLKS_PER_SDU,
457 &frame_blocks, sizeof(frame_blocks));
458 }
459 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 */
460
461 #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0 || \
462 CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE > 0
463
codec_meta_get_val(const uint8_t meta[],size_t meta_len,uint8_t type,const uint8_t ** data)464 static int codec_meta_get_val(const uint8_t meta[], size_t meta_len, uint8_t type,
465 const uint8_t **data)
466 {
467 struct search_type_param param = {
468 .type = type,
469 .data_len = 0,
470 .data = data,
471 };
472 int err;
473
474 CHECKIF(meta == NULL) {
475 LOG_DBG("meta is NULL");
476 return -EINVAL;
477 }
478
479 CHECKIF(data == NULL) {
480 LOG_DBG("data is NULL");
481 return -EINVAL;
482 }
483
484 *data = NULL;
485
486 err = bt_audio_data_parse(meta, meta_len, parse_cb, ¶m);
487 if (err != 0 && err != -ECANCELED) {
488 LOG_DBG("Could not parse the meta data: %d", err);
489 return err;
490 }
491
492 if (!param.found) {
493 LOG_DBG("Could not find the type %u", type);
494 return -ENODATA;
495 }
496
497 return param.data_len;
498 }
499
codec_meta_get_pref_context(const uint8_t meta[],size_t meta_len)500 static int codec_meta_get_pref_context(const uint8_t meta[], size_t meta_len)
501 {
502 const uint8_t *data;
503 int ret;
504
505 CHECKIF(meta == NULL) {
506 LOG_DBG("meta is NULL");
507 return -EINVAL;
508 }
509
510 ret = codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_PREF_CONTEXT, &data);
511 if (data == NULL) {
512 return -ENODATA;
513 }
514
515 if (ret != sizeof(uint16_t)) {
516 return -EBADMSG;
517 }
518
519 return sys_get_le16(data);
520 }
521
codec_meta_get_stream_context(const uint8_t meta[],size_t meta_len)522 static int codec_meta_get_stream_context(const uint8_t meta[], size_t meta_len)
523 {
524 const uint8_t *data;
525 int ret;
526
527 CHECKIF(meta == NULL) {
528 LOG_DBG("meta is NULL");
529 return -EINVAL;
530 }
531
532 ret = codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT, &data);
533 if (data == NULL) {
534 return -ENODATA;
535 }
536
537 if (ret != sizeof(uint16_t)) {
538 return -EBADMSG;
539 }
540
541 return sys_get_le16(data);
542 }
543
codec_meta_get_program_info(const uint8_t meta[],size_t meta_len,const uint8_t ** program_info)544 static int codec_meta_get_program_info(const uint8_t meta[], size_t meta_len,
545 const uint8_t **program_info)
546 {
547 const uint8_t *data;
548 int ret;
549
550 CHECKIF(meta == NULL) {
551 LOG_DBG("meta is NULL");
552 return -EINVAL;
553 }
554
555 CHECKIF(program_info == NULL) {
556 LOG_DBG("program_info is NULL");
557 return -EINVAL;
558 }
559
560 ret = codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_PROGRAM_INFO, &data);
561 if (data == NULL) {
562 return -ENODATA;
563 }
564
565 *program_info = data;
566
567 return ret;
568 }
569
codec_meta_get_stream_lang(const uint8_t meta[],size_t meta_len)570 static int codec_meta_get_stream_lang(const uint8_t meta[], size_t meta_len)
571 {
572 const uint8_t *data;
573 int ret;
574
575 CHECKIF(meta == NULL) {
576 LOG_DBG("meta is NULL");
577 return -EINVAL;
578 }
579
580 ret = codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_STREAM_LANG, &data);
581 if (data == NULL) {
582 return -ENODATA;
583 }
584
585 if (ret != 3) { /* Stream language is 3 octets */
586 return -EBADMSG;
587 }
588
589 return sys_get_le24(data);
590 }
591
codec_meta_get_ccid_list(const uint8_t meta[],size_t meta_len,const uint8_t ** ccid_list)592 static int codec_meta_get_ccid_list(const uint8_t meta[], size_t meta_len,
593 const uint8_t **ccid_list)
594 {
595 const uint8_t *data;
596 int ret;
597
598 CHECKIF(meta == NULL) {
599 LOG_DBG("meta is NULL");
600 return -EINVAL;
601 }
602
603 CHECKIF(ccid_list == NULL) {
604 LOG_DBG("ccid_list is NULL");
605 return -EINVAL;
606 }
607
608 ret = codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_CCID_LIST, &data);
609 if (data == NULL) {
610 return -ENODATA;
611 }
612
613 *ccid_list = data;
614
615 return ret;
616 }
617
codec_meta_get_parental_rating(const uint8_t meta[],size_t meta_len)618 static int codec_meta_get_parental_rating(const uint8_t meta[], size_t meta_len)
619 {
620 const uint8_t *data;
621 int ret;
622
623 CHECKIF(meta == NULL) {
624 LOG_DBG("meta is NULL");
625 return -EINVAL;
626 }
627
628 ret = codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_PARENTAL_RATING, &data);
629 if (data == NULL) {
630 return -ENODATA;
631 }
632
633 if (ret != sizeof(uint8_t)) {
634 return -EBADMSG;
635 }
636
637 return data[0];
638 }
639
codec_meta_get_program_info_uri(const uint8_t meta[],size_t meta_len,const uint8_t ** program_info_uri)640 static int codec_meta_get_program_info_uri(const uint8_t meta[], size_t meta_len,
641 const uint8_t **program_info_uri)
642 {
643 const uint8_t *data;
644 int ret;
645
646 CHECKIF(meta == NULL) {
647 LOG_DBG("meta is NULL");
648 return -EINVAL;
649 }
650
651 CHECKIF(program_info_uri == NULL) {
652 LOG_DBG("program_info_uri is NULL");
653 return -EINVAL;
654 }
655
656 ret = codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_PROGRAM_INFO_URI, &data);
657 if (data == NULL) {
658 return -ENODATA;
659 }
660
661 *program_info_uri = data;
662
663 return ret;
664 }
665
codec_meta_get_audio_active_state(const uint8_t meta[],size_t meta_len)666 static int codec_meta_get_audio_active_state(const uint8_t meta[], size_t meta_len)
667 {
668 const uint8_t *data;
669 int ret;
670
671 CHECKIF(meta == NULL) {
672 LOG_DBG("meta is NULL");
673 return -EINVAL;
674 }
675
676 ret = codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_AUDIO_STATE, &data);
677 if (data == NULL) {
678 return -ENODATA;
679 }
680
681 if (ret != sizeof(uint8_t)) {
682 return -EBADMSG;
683 }
684
685 return data[0];
686 }
687
codec_meta_get_bcast_audio_immediate_rend_flag(const uint8_t meta[],size_t meta_len)688 static int codec_meta_get_bcast_audio_immediate_rend_flag(const uint8_t meta[], size_t meta_len)
689 {
690 const uint8_t *data;
691
692 CHECKIF(meta == NULL) {
693 LOG_DBG("meta is NULL");
694 return -EINVAL;
695 }
696
697 return codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_BROADCAST_IMMEDIATE,
698 &data);
699 }
700
codec_meta_get_extended(const uint8_t meta[],size_t meta_len,const uint8_t ** extended_meta)701 static int codec_meta_get_extended(const uint8_t meta[], size_t meta_len,
702 const uint8_t **extended_meta)
703 {
704 const uint8_t *data;
705 int ret;
706
707 CHECKIF(meta == NULL) {
708 LOG_DBG("meta is NULL");
709 return -EINVAL;
710 }
711
712 CHECKIF(extended_meta == NULL) {
713 LOG_DBG("extended_meta is NULL");
714 return -EINVAL;
715 }
716
717 ret = codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_EXTENDED, &data);
718 if (data == NULL) {
719 return -ENODATA;
720 }
721
722 *extended_meta = data;
723
724 return ret;
725 }
726
codec_meta_get_vendor(const uint8_t meta[],size_t meta_len,const uint8_t ** vendor_meta)727 static int codec_meta_get_vendor(const uint8_t meta[], size_t meta_len, const uint8_t **vendor_meta)
728 {
729 const uint8_t *data;
730 int ret;
731
732 CHECKIF(meta == NULL) {
733 LOG_DBG("meta is NULL");
734 return -EINVAL;
735 }
736
737 CHECKIF(vendor_meta == NULL) {
738 LOG_DBG("vendor_meta is NULL");
739 return -EINVAL;
740 }
741
742 ret = codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_VENDOR, &data);
743 if (data == NULL) {
744 return -ENODATA;
745 }
746
747 *vendor_meta = data;
748
749 return ret;
750 }
751
752 #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0
bt_audio_codec_cfg_meta_get_val(const struct bt_audio_codec_cfg * codec_cfg,uint8_t type,const uint8_t ** data)753 int bt_audio_codec_cfg_meta_get_val(const struct bt_audio_codec_cfg *codec_cfg, uint8_t type,
754 const uint8_t **data)
755 {
756 CHECKIF(codec_cfg == NULL) {
757 LOG_DBG("codec_cfg is NULL");
758 return -EINVAL;
759 }
760
761 return codec_meta_get_val(codec_cfg->meta, codec_cfg->meta_len, type, data);
762 }
763
bt_audio_codec_cfg_meta_get_pref_context(const struct bt_audio_codec_cfg * codec_cfg)764 int bt_audio_codec_cfg_meta_get_pref_context(const struct bt_audio_codec_cfg *codec_cfg)
765 {
766 CHECKIF(codec_cfg == NULL) {
767 LOG_DBG("codec_cfg is NULL");
768 return -EINVAL;
769 }
770
771 return codec_meta_get_pref_context(codec_cfg->meta, codec_cfg->meta_len);
772 }
773
bt_audio_codec_cfg_meta_get_stream_context(const struct bt_audio_codec_cfg * codec_cfg)774 int bt_audio_codec_cfg_meta_get_stream_context(const struct bt_audio_codec_cfg *codec_cfg)
775 {
776 CHECKIF(codec_cfg == NULL) {
777 LOG_DBG("codec_cfg is NULL");
778 return -EINVAL;
779 }
780
781 return codec_meta_get_stream_context(codec_cfg->meta, codec_cfg->meta_len);
782 }
783
bt_audio_codec_cfg_meta_get_program_info(const struct bt_audio_codec_cfg * codec_cfg,const uint8_t ** program_info)784 int bt_audio_codec_cfg_meta_get_program_info(const struct bt_audio_codec_cfg *codec_cfg,
785 const uint8_t **program_info)
786 {
787 CHECKIF(codec_cfg == NULL) {
788 LOG_DBG("codec_cfg is NULL");
789 return -EINVAL;
790 }
791
792 return codec_meta_get_program_info(codec_cfg->meta, codec_cfg->meta_len, program_info);
793 }
794
bt_audio_codec_cfg_meta_get_stream_lang(const struct bt_audio_codec_cfg * codec_cfg)795 int bt_audio_codec_cfg_meta_get_stream_lang(const struct bt_audio_codec_cfg *codec_cfg)
796 {
797 CHECKIF(codec_cfg == NULL) {
798 LOG_DBG("codec_cfg is NULL");
799 return -EINVAL;
800 }
801
802 return codec_meta_get_stream_lang(codec_cfg->meta, codec_cfg->meta_len);
803 }
804
bt_audio_codec_cfg_meta_get_ccid_list(const struct bt_audio_codec_cfg * codec_cfg,const uint8_t ** ccid_list)805 int bt_audio_codec_cfg_meta_get_ccid_list(const struct bt_audio_codec_cfg *codec_cfg,
806 const uint8_t **ccid_list)
807 {
808 CHECKIF(codec_cfg == NULL) {
809 LOG_DBG("codec_cfg is NULL");
810 return -EINVAL;
811 }
812
813 return codec_meta_get_ccid_list(codec_cfg->meta, codec_cfg->meta_len, ccid_list);
814 }
815
bt_audio_codec_cfg_meta_get_parental_rating(const struct bt_audio_codec_cfg * codec_cfg)816 int bt_audio_codec_cfg_meta_get_parental_rating(const struct bt_audio_codec_cfg *codec_cfg)
817 {
818 CHECKIF(codec_cfg == NULL) {
819 LOG_DBG("codec_cfg is NULL");
820 return -EINVAL;
821 }
822
823 return codec_meta_get_parental_rating(codec_cfg->meta, codec_cfg->meta_len);
824 }
825
bt_audio_codec_cfg_meta_get_program_info_uri(const struct bt_audio_codec_cfg * codec_cfg,const uint8_t ** program_info_uri)826 int bt_audio_codec_cfg_meta_get_program_info_uri(const struct bt_audio_codec_cfg *codec_cfg,
827 const uint8_t **program_info_uri)
828 {
829 CHECKIF(codec_cfg == NULL) {
830 LOG_DBG("codec_cfg is NULL");
831 return -EINVAL;
832 }
833
834 return codec_meta_get_program_info_uri(codec_cfg->meta, codec_cfg->meta_len,
835 program_info_uri);
836 }
837
bt_audio_codec_cfg_meta_get_audio_active_state(const struct bt_audio_codec_cfg * codec_cfg)838 int bt_audio_codec_cfg_meta_get_audio_active_state(const struct bt_audio_codec_cfg *codec_cfg)
839 {
840 CHECKIF(codec_cfg == NULL) {
841 LOG_DBG("codec_cfg is NULL");
842 return -EINVAL;
843 }
844
845 return codec_meta_get_audio_active_state(codec_cfg->meta, codec_cfg->meta_len);
846 }
847
bt_audio_codec_cfg_meta_get_bcast_audio_immediate_rend_flag(const struct bt_audio_codec_cfg * codec_cfg)848 int bt_audio_codec_cfg_meta_get_bcast_audio_immediate_rend_flag(
849 const struct bt_audio_codec_cfg *codec_cfg)
850 {
851 CHECKIF(codec_cfg == NULL) {
852 LOG_DBG("codec_cfg is NULL");
853 return -EINVAL;
854 }
855
856 LOG_ERR("codec_cfg->meta_len %zu", codec_cfg->meta_len);
857
858 return codec_meta_get_bcast_audio_immediate_rend_flag(codec_cfg->meta, codec_cfg->meta_len);
859 }
860
bt_audio_codec_cfg_meta_get_extended(const struct bt_audio_codec_cfg * codec_cfg,const uint8_t ** extended_meta)861 int bt_audio_codec_cfg_meta_get_extended(const struct bt_audio_codec_cfg *codec_cfg,
862 const uint8_t **extended_meta)
863 {
864 CHECKIF(codec_cfg == NULL) {
865 LOG_DBG("codec_cfg is NULL");
866 return -EINVAL;
867 }
868
869 return codec_meta_get_extended(codec_cfg->meta, codec_cfg->meta_len, extended_meta);
870 }
871
bt_audio_codec_cfg_meta_get_vendor(const struct bt_audio_codec_cfg * codec_cfg,const uint8_t ** vendor_meta)872 int bt_audio_codec_cfg_meta_get_vendor(const struct bt_audio_codec_cfg *codec_cfg,
873 const uint8_t **vendor_meta)
874 {
875 CHECKIF(codec_cfg == NULL) {
876 LOG_DBG("codec_cfg is NULL");
877 return -EINVAL;
878 }
879
880 return codec_meta_get_vendor(codec_cfg->meta, codec_cfg->meta_len, vendor_meta);
881 }
882 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0 */
883
884 #if CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE > 0
bt_audio_codec_cap_meta_get_val(const struct bt_audio_codec_cap * codec_cap,uint8_t type,const uint8_t ** data)885 int bt_audio_codec_cap_meta_get_val(const struct bt_audio_codec_cap *codec_cap, uint8_t type,
886 const uint8_t **data)
887 {
888 CHECKIF(codec_cap == NULL) {
889 LOG_DBG("codec_cap is NULL");
890 return -EINVAL;
891 }
892
893 return codec_meta_get_val(codec_cap->meta, codec_cap->meta_len, type, data);
894 }
895
bt_audio_codec_cap_meta_get_pref_context(const struct bt_audio_codec_cap * codec_cap)896 int bt_audio_codec_cap_meta_get_pref_context(const struct bt_audio_codec_cap *codec_cap)
897 {
898 CHECKIF(codec_cap == NULL) {
899 LOG_DBG("codec_cap is NULL");
900 return -EINVAL;
901 }
902
903 return codec_meta_get_pref_context(codec_cap->meta, codec_cap->meta_len);
904 }
905
bt_audio_codec_cap_meta_get_stream_context(const struct bt_audio_codec_cap * codec_cap)906 int bt_audio_codec_cap_meta_get_stream_context(const struct bt_audio_codec_cap *codec_cap)
907 {
908 CHECKIF(codec_cap == NULL) {
909 LOG_DBG("codec_cap is NULL");
910 return -EINVAL;
911 }
912
913 return codec_meta_get_stream_context(codec_cap->meta, codec_cap->meta_len);
914 }
915
bt_audio_codec_cap_meta_get_program_info(const struct bt_audio_codec_cap * codec_cap,const uint8_t ** program_info)916 int bt_audio_codec_cap_meta_get_program_info(const struct bt_audio_codec_cap *codec_cap,
917 const uint8_t **program_info)
918 {
919 CHECKIF(codec_cap == NULL) {
920 LOG_DBG("codec_cap is NULL");
921 return -EINVAL;
922 }
923
924 return codec_meta_get_program_info(codec_cap->meta, codec_cap->meta_len, program_info);
925 }
926
bt_audio_codec_cap_meta_get_stream_lang(const struct bt_audio_codec_cap * codec_cap)927 int bt_audio_codec_cap_meta_get_stream_lang(const struct bt_audio_codec_cap *codec_cap)
928 {
929 CHECKIF(codec_cap == NULL) {
930 LOG_DBG("codec_cap is NULL");
931 return -EINVAL;
932 }
933
934 return codec_meta_get_stream_lang(codec_cap->meta, codec_cap->meta_len);
935 }
936
bt_audio_codec_cap_meta_get_ccid_list(const struct bt_audio_codec_cap * codec_cap,const uint8_t ** ccid_list)937 int bt_audio_codec_cap_meta_get_ccid_list(const struct bt_audio_codec_cap *codec_cap,
938 const uint8_t **ccid_list)
939 {
940 CHECKIF(codec_cap == NULL) {
941 LOG_DBG("codec_cap is NULL");
942 return -EINVAL;
943 }
944
945 return codec_meta_get_ccid_list(codec_cap->meta, codec_cap->meta_len, ccid_list);
946 }
947
bt_audio_codec_cap_meta_get_parental_rating(const struct bt_audio_codec_cap * codec_cap)948 int bt_audio_codec_cap_meta_get_parental_rating(const struct bt_audio_codec_cap *codec_cap)
949 {
950 CHECKIF(codec_cap == NULL) {
951 LOG_DBG("codec_cap is NULL");
952 return -EINVAL;
953 }
954
955 return codec_meta_get_parental_rating(codec_cap->meta, codec_cap->meta_len);
956 }
957
bt_audio_codec_cap_meta_get_program_info_uri(const struct bt_audio_codec_cap * codec_cap,const uint8_t ** program_info_uri)958 int bt_audio_codec_cap_meta_get_program_info_uri(const struct bt_audio_codec_cap *codec_cap,
959 const uint8_t **program_info_uri)
960 {
961 CHECKIF(codec_cap == NULL) {
962 LOG_DBG("codec_cap is NULL");
963 return -EINVAL;
964 }
965
966 return codec_meta_get_program_info_uri(codec_cap->meta, codec_cap->meta_len,
967 program_info_uri);
968 }
969
bt_audio_codec_cap_meta_get_audio_active_state(const struct bt_audio_codec_cap * codec_cap)970 int bt_audio_codec_cap_meta_get_audio_active_state(const struct bt_audio_codec_cap *codec_cap)
971 {
972 CHECKIF(codec_cap == NULL) {
973 LOG_DBG("codec_cap is NULL");
974 return -EINVAL;
975 }
976
977 return codec_meta_get_audio_active_state(codec_cap->meta, codec_cap->meta_len);
978 }
979
bt_audio_codec_cap_meta_get_bcast_audio_immediate_rend_flag(const struct bt_audio_codec_cap * codec_cap)980 int bt_audio_codec_cap_meta_get_bcast_audio_immediate_rend_flag(
981 const struct bt_audio_codec_cap *codec_cap)
982 {
983 CHECKIF(codec_cap == NULL) {
984 LOG_DBG("codec_cap is NULL");
985 return -EINVAL;
986 }
987
988 return codec_meta_get_bcast_audio_immediate_rend_flag(codec_cap->meta, codec_cap->meta_len);
989 }
990
bt_audio_codec_cap_meta_get_extended(const struct bt_audio_codec_cap * codec_cap,const uint8_t ** extended_meta)991 int bt_audio_codec_cap_meta_get_extended(const struct bt_audio_codec_cap *codec_cap,
992 const uint8_t **extended_meta)
993 {
994 CHECKIF(codec_cap == NULL) {
995 LOG_DBG("codec_cap is NULL");
996 return -EINVAL;
997 }
998
999 return codec_meta_get_extended(codec_cap->meta, codec_cap->meta_len, extended_meta);
1000 }
1001
bt_audio_codec_cap_meta_get_vendor(const struct bt_audio_codec_cap * codec_cap,const uint8_t ** vendor_meta)1002 int bt_audio_codec_cap_meta_get_vendor(const struct bt_audio_codec_cap *codec_cap,
1003 const uint8_t **vendor_meta)
1004 {
1005 CHECKIF(codec_cap == NULL) {
1006 LOG_DBG("codec_cap is NULL");
1007 return -EINVAL;
1008 }
1009
1010 return codec_meta_get_vendor(codec_cap->meta, codec_cap->meta_len, vendor_meta);
1011 }
1012 #endif /* CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE > 0 */
1013 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0 || \
1014 * CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE > 0 \
1015 */
1016
1017 #if CONFIG_BT_AUDIO_CODEC_CAP_MAX_DATA_SIZE > 0
1018
bt_audio_codec_cap_get_val(const struct bt_audio_codec_cap * codec_cap,uint8_t type,const uint8_t ** data)1019 uint8_t bt_audio_codec_cap_get_val(const struct bt_audio_codec_cap *codec_cap, uint8_t type,
1020 const uint8_t **data)
1021 {
1022 struct search_type_param param = {
1023 .type = type,
1024 .data_len = 0,
1025 .data = data,
1026 };
1027 int err;
1028
1029 CHECKIF(codec_cap == NULL) {
1030 LOG_DBG("codec_cap is NULL");
1031 return 0;
1032 }
1033
1034 CHECKIF(data == NULL) {
1035 LOG_DBG("data is NULL");
1036 return 0;
1037 }
1038
1039 *data = NULL;
1040
1041 err = bt_audio_data_parse(codec_cap->data, codec_cap->data_len, parse_cb, ¶m);
1042 if (err != 0 && err != -ECANCELED) {
1043 LOG_DBG("Could not parse the data: %d", err);
1044 return 0;
1045 }
1046
1047 if (param.data == NULL) {
1048 LOG_DBG("Could not find the type %u", type);
1049 return 0;
1050 }
1051
1052 return param.data_len;
1053 }
1054
bt_audio_codec_cap_get_freq(const struct bt_audio_codec_cap * codec_cap)1055 int bt_audio_codec_cap_get_freq(const struct bt_audio_codec_cap *codec_cap)
1056 {
1057 const uint8_t *data;
1058 uint8_t data_len;
1059
1060 CHECKIF(codec_cap == NULL) {
1061 LOG_DBG("codec_cap is NULL");
1062 return -EINVAL;
1063 }
1064
1065 data_len = bt_audio_codec_cap_get_val(codec_cap, BT_AUDIO_CODEC_LC3_FREQ, &data);
1066 if (data == NULL) {
1067 return -ENODATA;
1068 }
1069
1070 if (data_len != sizeof(uint16_t)) {
1071 return -EBADMSG;
1072 }
1073
1074 return sys_get_le16(data);
1075 }
1076
bt_audio_codec_cap_get_frame_duration(const struct bt_audio_codec_cap * codec_cap)1077 int bt_audio_codec_cap_get_frame_duration(const struct bt_audio_codec_cap *codec_cap)
1078 {
1079 const uint8_t *data;
1080 uint8_t data_len;
1081
1082 CHECKIF(codec_cap == NULL) {
1083 LOG_DBG("codec_cap is NULL");
1084 return -EINVAL;
1085 }
1086
1087 data_len = bt_audio_codec_cap_get_val(codec_cap, BT_AUDIO_CODEC_LC3_DURATION, &data);
1088 if (data == NULL) {
1089 return -ENODATA;
1090 }
1091
1092 if (data_len != sizeof(uint8_t)) {
1093 return -EBADMSG;
1094 }
1095
1096 return data[0];
1097 }
1098
bt_audio_codec_cap_get_supported_audio_chan_counts(const struct bt_audio_codec_cap * codec_cap)1099 int bt_audio_codec_cap_get_supported_audio_chan_counts(const struct bt_audio_codec_cap *codec_cap)
1100 {
1101 const uint8_t *data;
1102 uint8_t data_len;
1103
1104 CHECKIF(codec_cap == NULL) {
1105 LOG_DBG("codec_cap is NULL");
1106 return -EINVAL;
1107 }
1108
1109 data_len = bt_audio_codec_cap_get_val(codec_cap, BT_AUDIO_CODEC_LC3_CHAN_COUNT, &data);
1110 if (data == NULL) {
1111 return -ENODATA;
1112 }
1113
1114 if (data_len != sizeof(uint8_t)) {
1115 return -EBADMSG;
1116 }
1117
1118 return data[0];
1119 }
1120
bt_audio_codec_cap_get_octets_per_frame(const struct bt_audio_codec_cap * codec_cap,struct bt_audio_codec_octets_per_codec_frame * codec_frame)1121 int bt_audio_codec_cap_get_octets_per_frame(
1122 const struct bt_audio_codec_cap *codec_cap,
1123 struct bt_audio_codec_octets_per_codec_frame *codec_frame)
1124 {
1125 const uint8_t *data;
1126 uint8_t data_len;
1127
1128 CHECKIF(codec_cap == NULL) {
1129 LOG_DBG("codec_cap is NULL");
1130 return -EINVAL;
1131 }
1132
1133 CHECKIF(codec_frame == NULL) {
1134 LOG_DBG("codec_frame is NULL");
1135 return -EINVAL;
1136 }
1137
1138 data_len = bt_audio_codec_cap_get_val(codec_cap, BT_AUDIO_CODEC_LC3_FRAME_LEN, &data);
1139 if (data == NULL) {
1140 return -ENODATA;
1141 }
1142
1143 if (data_len != sizeof(uint32_t)) {
1144 return -EBADMSG;
1145 }
1146
1147 codec_frame->min = sys_get_le16(data);
1148 codec_frame->max = sys_get_le16(data + sizeof(codec_frame->min));
1149
1150 return 0;
1151 }
1152
bt_audio_codec_cap_get_max_codec_frames_per_sdu(const struct bt_audio_codec_cap * codec_cap)1153 int bt_audio_codec_cap_get_max_codec_frames_per_sdu(const struct bt_audio_codec_cap *codec_cap)
1154 {
1155 const uint8_t *data;
1156 uint8_t data_len;
1157
1158 CHECKIF(codec_cap == NULL) {
1159 LOG_DBG("codec_cap is NULL");
1160 return -EINVAL;
1161 }
1162
1163 data_len = bt_audio_codec_cap_get_val(codec_cap, BT_AUDIO_CODEC_LC3_FRAME_COUNT, &data);
1164 if (data == NULL) {
1165 return -ENODATA;
1166 }
1167
1168 if (data_len != sizeof(uint8_t)) {
1169 return -EBADMSG;
1170 }
1171
1172 return data[0];
1173 }
1174
1175 #endif /* CONFIG_BT_AUDIO_CODEC_CAP_MAX_DATA_SIZE > 0 */
1176