1 /* Common functions for LE Audio services */
2
3 /*
4 * Copyright (c) 2022 Codecoup
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #include <zephyr/bluetooth/att.h>
10 #include <zephyr/bluetooth/conn.h>
11 #include <zephyr/bluetooth/hci.h>
12 #include <zephyr/bluetooth/audio/audio.h>
13 #include <zephyr/bluetooth/audio/bap.h>
14 #include <zephyr/logging/log.h>
15 #include <zephyr/sys/check.h>
16
17 #include "audio_internal.h"
18
19 LOG_MODULE_REGISTER(bt_audio, CONFIG_BT_AUDIO_LOG_LEVEL);
20
bt_audio_data_parse(const uint8_t ltv[],size_t size,bool (* func)(struct bt_data * data,void * user_data),void * user_data)21 int bt_audio_data_parse(const uint8_t ltv[], size_t size,
22 bool (*func)(struct bt_data *data, void *user_data), void *user_data)
23 {
24 CHECKIF(ltv == NULL) {
25 LOG_DBG("ltv is NULL");
26
27 return -EINVAL;
28 }
29
30 CHECKIF(func == NULL) {
31 LOG_DBG("func is NULL");
32
33 return -EINVAL;
34 }
35
36 for (size_t i = 0; i < size;) {
37 const uint8_t len = ltv[i];
38 struct bt_data data;
39
40 if (i + len > size || len < sizeof(data.type)) {
41 LOG_DBG("Invalid len %u at i = %zu", len, i);
42
43 return -EINVAL;
44 }
45
46 i++; /* Increment as we have parsed the len field */
47
48 data.type = ltv[i++];
49 data.data_len = len - sizeof(data.type);
50
51 if (data.data_len > 0) {
52 data.data = <v[i];
53 } else {
54 data.data = NULL;
55 }
56
57 if (!func(&data, user_data)) {
58 return -ECANCELED;
59 }
60
61 /* Since we are incrementing i by the value_len, we don't need to increment it
62 * further in the `for` statement
63 */
64 i += data.data_len;
65 }
66
67 return 0;
68 }
69
70 #if defined(CONFIG_BT_CONN)
71
bt_audio_security_check(const struct bt_conn * conn)72 static uint8_t bt_audio_security_check(const struct bt_conn *conn)
73 {
74 struct bt_conn_info info;
75 int err;
76
77 err = bt_conn_get_info(conn, &info);
78 if (err < 0) {
79 return BT_ATT_ERR_UNLIKELY;
80 }
81
82 /* Require an encryption key with at least 128 bits of entropy, derived from SC or OOB
83 * method.
84 */
85 if ((info.security.flags & (BT_SECURITY_FLAG_OOB | BT_SECURITY_FLAG_SC)) == 0) {
86 /* If the client has insufficient security to read/write the requested attribute
87 * then an ATT_ERROR_RSP PDU shall be sent with the Error Code parameter set to
88 * Insufficient Authentication (0x05).
89 */
90 return BT_ATT_ERR_AUTHENTICATION;
91 }
92
93 if (info.security.enc_key_size < BT_ENC_KEY_SIZE_MAX) {
94 return BT_ATT_ERR_ENCRYPTION_KEY_SIZE;
95 }
96
97 return BT_ATT_ERR_SUCCESS;
98 }
99
bt_audio_read_chrc(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)100 ssize_t bt_audio_read_chrc(struct bt_conn *conn, const struct bt_gatt_attr *attr,
101 void *buf, uint16_t len, uint16_t offset)
102 {
103 const struct bt_audio_attr_user_data *user_data = attr->user_data;
104
105 if (user_data->read == NULL) {
106 return BT_GATT_ERR(BT_ATT_ERR_READ_NOT_PERMITTED);
107 }
108
109 if (conn != NULL) {
110 uint8_t err;
111
112 err = bt_audio_security_check(conn);
113 if (err != 0) {
114 return BT_GATT_ERR(err);
115 }
116 }
117
118 return user_data->read(conn, attr, buf, len, offset);
119 }
120
bt_audio_write_chrc(struct bt_conn * conn,const struct bt_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags)121 ssize_t bt_audio_write_chrc(struct bt_conn *conn, const struct bt_gatt_attr *attr,
122 const void *buf, uint16_t len, uint16_t offset, uint8_t flags)
123 {
124 const struct bt_audio_attr_user_data *user_data = attr->user_data;
125
126 if (user_data->write == NULL) {
127 return BT_GATT_ERR(BT_ATT_ERR_WRITE_NOT_PERMITTED);
128 }
129
130 if (conn != NULL) {
131 uint8_t err;
132
133 err = bt_audio_security_check(conn);
134 if (err != 0) {
135 return BT_GATT_ERR(err);
136 }
137 }
138
139 return user_data->write(conn, attr, buf, len, offset, flags);
140 }
141
bt_audio_ccc_cfg_write(struct bt_conn * conn,const struct bt_gatt_attr * attr,uint16_t value)142 ssize_t bt_audio_ccc_cfg_write(struct bt_conn *conn, const struct bt_gatt_attr *attr,
143 uint16_t value)
144 {
145 if (conn != NULL) {
146 uint8_t err;
147
148 err = bt_audio_security_check(conn);
149 if (err != 0) {
150 return BT_GATT_ERR(err);
151 }
152 }
153
154 return sizeof(value);
155 }
156 #endif /* CONFIG_BT_CONN */
157
158 /* Broadcast sink depends on Scan Delegator, so we can just guard it with the Scan Delegator */
159 #if defined(CONFIG_BT_BAP_SCAN_DELEGATOR)
160
decode_bis_data(struct net_buf_simple * buf,struct bt_bap_base_bis_data * bis)161 static int decode_bis_data(struct net_buf_simple *buf, struct bt_bap_base_bis_data *bis)
162 {
163 uint8_t len;
164
165 if (buf->len < BT_BAP_BASE_BIS_DATA_MIN_SIZE) {
166 LOG_DBG("Not enough bytes (%u) to decode BIS data", buf->len);
167
168 return -ENOMEM;
169 }
170
171 bis->index = net_buf_simple_pull_u8(buf);
172 if (!IN_RANGE(bis->index, BT_ISO_BIS_INDEX_MIN, BT_ISO_BIS_INDEX_MAX)) {
173 LOG_DBG("Invalid BIS index %u", bis->index);
174
175 return -EINVAL;
176 }
177
178 /* codec config data length */
179 len = net_buf_simple_pull_u8(buf);
180 if (len > buf->len) {
181 LOG_DBG("Invalid BIS specific codec config data length: %u (buf is %u)", len,
182 buf->len);
183
184 return -EMSGSIZE;
185 }
186
187 if (len > 0) {
188 #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0
189 void *ltv_data;
190
191 if (len > sizeof(bis->data)) {
192 LOG_DBG("Cannot store codec config data of length %u", len);
193
194 return -ENOMEM;
195 }
196
197 ltv_data = net_buf_simple_pull_mem(buf, len);
198
199 bis->data_len = len;
200 memcpy(bis->data, ltv_data, len);
201 #else /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE == 0 */
202 LOG_DBG("Cannot store codec config data");
203
204 return -ENOMEM;
205 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE */
206 }
207
208 return 0;
209 }
210
decode_subgroup(struct net_buf_simple * buf,struct bt_bap_base_subgroup * subgroup)211 static int decode_subgroup(struct net_buf_simple *buf, struct bt_bap_base_subgroup *subgroup)
212 {
213 struct bt_audio_codec_cfg *codec_cfg;
214 uint8_t len;
215
216 codec_cfg = &subgroup->codec_cfg;
217
218 subgroup->bis_count = net_buf_simple_pull_u8(buf);
219 if (subgroup->bis_count > ARRAY_SIZE(subgroup->bis_data)) {
220 LOG_DBG("BASE has more BIS %u than we support %u", subgroup->bis_count,
221 (uint8_t)ARRAY_SIZE(subgroup->bis_data));
222
223 return -ENOMEM;
224 }
225
226 codec_cfg->id = net_buf_simple_pull_u8(buf);
227 codec_cfg->cid = net_buf_simple_pull_le16(buf);
228 codec_cfg->vid = net_buf_simple_pull_le16(buf);
229
230 /* codec configuration data length */
231 len = net_buf_simple_pull_u8(buf);
232 if (len > buf->len) {
233 LOG_DBG("Invalid codec config data length: %u (buf is %u)", len, buf->len);
234
235 return -EINVAL;
236 }
237
238 #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0
239 void *cfg_ltv_data;
240
241 if (len > sizeof(subgroup->codec_cfg.data)) {
242 LOG_DBG("Cannot store codec config data of length %u", len);
243
244 return -ENOMEM;
245 }
246
247 cfg_ltv_data = net_buf_simple_pull_mem(buf, len);
248
249 subgroup->codec_cfg.data_len = len;
250 memcpy(subgroup->codec_cfg.data, cfg_ltv_data, len);
251 #else /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE == 0 */
252 if (len > 0) {
253 LOG_DBG("Cannot store codec config data of length %u", len);
254
255 return -ENOMEM;
256 }
257 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 */
258
259 /* codec metadata length */
260 len = net_buf_simple_pull_u8(buf);
261 if (len > buf->len) {
262 LOG_DBG("Invalid codec config data length: %u (buf is %u)", len, buf->len);
263
264 return -EMSGSIZE;
265 }
266
267 #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0
268 void *meta_ltv_data;
269
270 if (len > sizeof(subgroup->codec_cfg.meta)) {
271 LOG_DBG("Cannot store codec config meta of length %u", len);
272
273 return -ENOMEM;
274 }
275
276 meta_ltv_data = net_buf_simple_pull_mem(buf, len);
277
278 subgroup->codec_cfg.meta_len = len;
279 memcpy(subgroup->codec_cfg.meta, meta_ltv_data, len);
280 #else /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE == 0 */
281 if (len > 0) {
282 LOG_DBG("Cannot store metadata");
283
284 return -ENOMEM;
285 }
286 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE */
287
288 for (size_t i = 0U; i < subgroup->bis_count; i++) {
289 const int err = decode_bis_data(buf, &subgroup->bis_data[i]);
290
291 if (err != 0) {
292 LOG_DBG("Failed to decode BIS data for bis[%zu]: %d", i, err);
293
294 return err;
295 }
296 }
297
298 return 0;
299 }
300
bt_bap_decode_base(struct bt_data * data,struct bt_bap_base * base)301 int bt_bap_decode_base(struct bt_data *data, struct bt_bap_base *base)
302 {
303 struct bt_uuid_16 broadcast_uuid;
304 struct net_buf_simple net_buf;
305 void *uuid;
306
307 CHECKIF(data == NULL) {
308 LOG_DBG("data is NULL");
309
310 return -EINVAL;
311 }
312
313 CHECKIF(base == NULL) {
314 LOG_DBG("base is NULL");
315
316 return -EINVAL;
317 }
318
319 if (data->type != BT_DATA_SVC_DATA16) {
320 LOG_DBG("Invalid type: %u", data->type);
321
322 return -ENOMSG;
323 }
324
325 if (data->data_len < BT_BAP_BASE_MIN_SIZE) {
326 return -EMSGSIZE;
327 }
328
329 net_buf_simple_init_with_data(&net_buf, (void *)data->data,
330 data->data_len);
331
332 uuid = net_buf_simple_pull_mem(&net_buf, BT_UUID_SIZE_16);
333 if (!bt_uuid_create(&broadcast_uuid.uuid, uuid, BT_UUID_SIZE_16)) {
334 LOG_ERR("bt_uuid_create failed");
335
336 return -EINVAL;
337 }
338
339 if (bt_uuid_cmp(&broadcast_uuid.uuid, BT_UUID_BASIC_AUDIO) != 0) {
340 LOG_DBG("Invalid UUID");
341
342 return -ENOMSG;
343 }
344
345 base->pd = net_buf_simple_pull_le24(&net_buf);
346 base->subgroup_count = net_buf_simple_pull_u8(&net_buf);
347
348 if (base->subgroup_count > ARRAY_SIZE(base->subgroups)) {
349 LOG_DBG("Cannot decode BASE with %u subgroups (max supported is %zu)",
350 base->subgroup_count, ARRAY_SIZE(base->subgroups));
351
352 return -ENOMEM;
353 }
354
355 for (size_t i = 0U; i < base->subgroup_count; i++) {
356 const int err = decode_subgroup(&net_buf, &base->subgroups[i]);
357
358 if (err != 0) {
359 LOG_DBG("Failed to decode subgroup[%zu]: %d", i, err);
360
361 return err;
362 }
363 }
364
365 return 0;
366 }
367 #endif /* CONFIG_BT_BAP_SCAN_DELEGATOR */
368