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 <zephyr/bluetooth/audio/audio.h>
14 #include <zephyr/sys/byteorder.h>
15 #include <zephyr/sys/check.h>
16
17 #include <zephyr/logging/log.h>
18
19 LOG_MODULE_REGISTER(bt_audio_codec, CONFIG_BT_AUDIO_CODEC_LOG_LEVEL);
20
bt_codec_get_val(const struct bt_codec * codec,uint8_t type,const struct bt_codec_data ** data)21 bool bt_codec_get_val(const struct bt_codec *codec,
22 uint8_t type,
23 const struct bt_codec_data **data)
24 {
25 CHECKIF(codec == NULL) {
26 LOG_DBG("codec is NULL");
27 return false;
28 }
29
30 for (size_t i = 0; i < codec->data_count; i++) {
31 if (codec->data[i].data.type == type) {
32 *data = &codec->data[i];
33
34 return true;
35 }
36 }
37
38 return false;
39 }
40
bt_codec_cfg_get_freq(const struct bt_codec * codec)41 int bt_codec_cfg_get_freq(const struct bt_codec *codec)
42 {
43 const struct bt_codec_data *element;
44
45 CHECKIF(codec == NULL) {
46 LOG_DBG("codec is NULL");
47 return BT_AUDIO_CODEC_PARSE_ERR_INVALID_PARAM;
48 }
49
50 if (bt_codec_get_val(codec, BT_CODEC_CONFIG_LC3_FREQ, &element)) {
51
52 switch (element->data.data[0]) {
53 case BT_CODEC_CONFIG_LC3_FREQ_8KHZ:
54 return 8000;
55 case BT_CODEC_CONFIG_LC3_FREQ_11KHZ:
56 return 11025;
57 case BT_CODEC_CONFIG_LC3_FREQ_16KHZ:
58 return 16000;
59 case BT_CODEC_CONFIG_LC3_FREQ_22KHZ:
60 return 22050;
61 case BT_CODEC_CONFIG_LC3_FREQ_24KHZ:
62 return 24000;
63 case BT_CODEC_CONFIG_LC3_FREQ_32KHZ:
64 return 32000;
65 case BT_CODEC_CONFIG_LC3_FREQ_44KHZ:
66 return 44100;
67 case BT_CODEC_CONFIG_LC3_FREQ_48KHZ:
68 return 48000;
69 case BT_CODEC_CONFIG_LC3_FREQ_88KHZ:
70 return 88200;
71 case BT_CODEC_CONFIG_LC3_FREQ_96KHZ:
72 return 96000;
73 case BT_CODEC_CONFIG_LC3_FREQ_176KHZ:
74 return 176400;
75 case BT_CODEC_CONFIG_LC3_FREQ_192KHZ:
76 return 192000;
77 case BT_CODEC_CONFIG_LC3_FREQ_384KHZ:
78 return 384000;
79 default:
80 return BT_AUDIO_CODEC_PARSE_ERR_INVALID_VALUE_FOUND;
81 }
82 }
83
84 return BT_AUDIO_CODEC_PARSE_ERR_TYPE_NOT_FOUND;
85 }
86
bt_codec_cfg_get_frame_duration_us(const struct bt_codec * codec)87 int bt_codec_cfg_get_frame_duration_us(const struct bt_codec *codec)
88 {
89 const struct bt_codec_data *element;
90
91 CHECKIF(codec == NULL) {
92 LOG_DBG("codec is NULL");
93 return BT_AUDIO_CODEC_PARSE_ERR_INVALID_PARAM;
94 }
95
96 if (bt_codec_get_val(codec, BT_CODEC_CONFIG_LC3_DURATION, &element)) {
97 switch (element->data.data[0]) {
98 case BT_CODEC_CONFIG_LC3_DURATION_7_5:
99 return 7500;
100 case BT_CODEC_CONFIG_LC3_DURATION_10:
101 return 10000;
102 default:
103 return BT_AUDIO_CODEC_PARSE_ERR_INVALID_VALUE_FOUND;
104 }
105 }
106
107 return BT_AUDIO_CODEC_PARSE_ERR_TYPE_NOT_FOUND;
108 }
109
bt_codec_cfg_get_chan_allocation_val(const struct bt_codec * codec,enum bt_audio_location * chan_allocation)110 int bt_codec_cfg_get_chan_allocation_val(const struct bt_codec *codec,
111 enum bt_audio_location *chan_allocation)
112 {
113 const struct bt_codec_data *element;
114
115 CHECKIF(codec == NULL) {
116 LOG_DBG("codec is NULL");
117 return BT_AUDIO_CODEC_PARSE_ERR_INVALID_PARAM;
118 }
119
120 CHECKIF(chan_allocation == NULL) {
121 return BT_AUDIO_CODEC_PARSE_ERR_INVALID_PARAM;
122 }
123
124 *chan_allocation = 0;
125 if (bt_codec_get_val(codec, BT_CODEC_CONFIG_LC3_CHAN_ALLOC, &element)) {
126
127 *chan_allocation = sys_le32_to_cpu(*((uint32_t *)&element->data.data[0]));
128
129 return BT_AUDIO_CODEC_PARSE_ERR_SUCCESS;
130 }
131
132 return BT_AUDIO_CODEC_PARSE_ERR_TYPE_NOT_FOUND;
133 }
134
bt_codec_cfg_get_octets_per_frame(const struct bt_codec * codec)135 int bt_codec_cfg_get_octets_per_frame(const struct bt_codec *codec)
136 {
137 const struct bt_codec_data *element;
138
139 CHECKIF(codec == NULL) {
140 LOG_DBG("codec is NULL");
141 return BT_AUDIO_CODEC_PARSE_ERR_INVALID_PARAM;
142 }
143
144 if (bt_codec_get_val(codec, BT_CODEC_CONFIG_LC3_FRAME_LEN, &element)) {
145
146 return sys_le16_to_cpu(*((uint16_t *)&element->data.data[0]));
147 }
148
149 return BT_AUDIO_CODEC_PARSE_ERR_TYPE_NOT_FOUND;
150 }
151
bt_codec_cfg_get_frame_blocks_per_sdu(const struct bt_codec * codec,bool fallback_to_default)152 int bt_codec_cfg_get_frame_blocks_per_sdu(const struct bt_codec *codec, bool fallback_to_default)
153 {
154 const struct bt_codec_data *element;
155
156 CHECKIF(codec == NULL) {
157 LOG_DBG("codec is NULL");
158 return BT_AUDIO_CODEC_PARSE_ERR_INVALID_PARAM;
159 }
160
161 if (bt_codec_get_val(codec, BT_CODEC_CONFIG_LC3_FRAME_BLKS_PER_SDU, &element)) {
162
163 return element->data.data[0];
164 }
165
166 if (fallback_to_default) {
167
168 return 1;
169 }
170
171 return BT_AUDIO_CODEC_PARSE_ERR_TYPE_NOT_FOUND;
172 }
173