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
21 #if defined(CONFIG_BT_CONN)
22
bt_audio_security_check(const struct bt_conn * conn)23 static uint8_t bt_audio_security_check(const struct bt_conn *conn)
24 {
25 struct bt_conn_info info;
26 int err;
27
28 err = bt_conn_get_info(conn, &info);
29 if (err < 0) {
30 return BT_ATT_ERR_UNLIKELY;
31 }
32
33 /* Require an encryption key with at least 128 bits of entropy, derived from SC or OOB
34 * method.
35 */
36 if ((info.security.flags & (BT_SECURITY_FLAG_OOB | BT_SECURITY_FLAG_SC)) == 0) {
37 /* If the client has insufficient security to read/write the requested attribute
38 * then an ATT_ERROR_RSP PDU shall be sent with the Error Code parameter set to
39 * Insufficient Authentication (0x05).
40 */
41 return BT_ATT_ERR_AUTHENTICATION;
42 }
43
44 if (info.security.enc_key_size < BT_ENC_KEY_SIZE_MAX) {
45 return BT_ATT_ERR_ENCRYPTION_KEY_SIZE;
46 }
47
48 return BT_ATT_ERR_SUCCESS;
49 }
50
bt_audio_read_chrc(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)51 ssize_t bt_audio_read_chrc(struct bt_conn *conn, const struct bt_gatt_attr *attr,
52 void *buf, uint16_t len, uint16_t offset)
53 {
54 const struct bt_audio_attr_user_data *user_data = attr->user_data;
55
56 if (user_data->read == NULL) {
57 return BT_GATT_ERR(BT_ATT_ERR_READ_NOT_PERMITTED);
58 }
59
60 if (conn != NULL) {
61 uint8_t err;
62
63 err = bt_audio_security_check(conn);
64 if (err != 0) {
65 return BT_GATT_ERR(err);
66 }
67 }
68
69 return user_data->read(conn, attr, buf, len, offset);
70 }
71
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)72 ssize_t bt_audio_write_chrc(struct bt_conn *conn, const struct bt_gatt_attr *attr,
73 const void *buf, uint16_t len, uint16_t offset, uint8_t flags)
74 {
75 const struct bt_audio_attr_user_data *user_data = attr->user_data;
76
77 if (user_data->write == NULL) {
78 return BT_GATT_ERR(BT_ATT_ERR_WRITE_NOT_PERMITTED);
79 }
80
81 if (conn != NULL) {
82 uint8_t err;
83
84 err = bt_audio_security_check(conn);
85 if (err != 0) {
86 return BT_GATT_ERR(err);
87 }
88 }
89
90 return user_data->write(conn, attr, buf, len, offset, flags);
91 }
92
bt_audio_ccc_cfg_write(struct bt_conn * conn,const struct bt_gatt_attr * attr,uint16_t value)93 ssize_t bt_audio_ccc_cfg_write(struct bt_conn *conn, const struct bt_gatt_attr *attr,
94 uint16_t value)
95 {
96 if (conn != NULL) {
97 uint8_t err;
98
99 err = bt_audio_security_check(conn);
100 if (err != 0) {
101 return BT_GATT_ERR(err);
102 }
103 }
104
105 return sizeof(value);
106 }
107 #endif /* CONFIG_BT_CONN */
108
109 /* Broadcast sink depends on Scan Delegator, so we can just guard it with the Scan Delegator */
110 #if defined(CONFIG_BT_BAP_SCAN_DELEGATOR)
111
decode_codec_ltv(struct net_buf_simple * buf,struct bt_codec_data * codec_data)112 static int decode_codec_ltv(struct net_buf_simple *buf,
113 struct bt_codec_data *codec_data)
114 {
115 void *value;
116
117 if (buf->len < sizeof(codec_data->data.data_len)) {
118 LOG_DBG("Not enough data for LTV length field: %u", buf->len);
119
120 return -ENOMEM;
121 }
122
123 codec_data->data.data_len = net_buf_simple_pull_u8(buf);
124
125 if (buf->len < sizeof(codec_data->data.type)) {
126 LOG_DBG("Not enough data for LTV type field: %u", buf->len);
127
128 return -EMSGSIZE;
129 }
130
131 /* LTV structures include the data.type in the length field,
132 * but we do not do that for the bt_data struct in Zephyr
133 */
134 codec_data->data.data_len -= sizeof(codec_data->data.type);
135
136 codec_data->data.type = net_buf_simple_pull_u8(buf);
137
138 codec_data->data.data = codec_data->value;
139
140 if (buf->len < codec_data->data.data_len) {
141 LOG_DBG("Not enough data for LTV value field: %u/%zu", buf->len,
142 codec_data->data.data_len);
143
144 return -EMSGSIZE;
145 }
146
147 value = net_buf_simple_pull_mem(buf, codec_data->data.data_len);
148 (void)memcpy(codec_data->value, value, codec_data->data.data_len);
149
150 return 0;
151 }
152
decode_bis_data(struct net_buf_simple * buf,struct bt_bap_base_bis_data * bis)153 static int decode_bis_data(struct net_buf_simple *buf, struct bt_bap_base_bis_data *bis)
154 {
155 uint8_t len;
156
157 if (buf->len < BT_BAP_BASE_BIS_DATA_MIN_SIZE) {
158 LOG_DBG("Not enough bytes (%u) to decode BIS data", buf->len);
159
160 return -ENOMEM;
161 }
162
163 bis->index = net_buf_simple_pull_u8(buf);
164 if (!IN_RANGE(bis->index, BT_ISO_BIS_INDEX_MIN, BT_ISO_BIS_INDEX_MAX)) {
165 LOG_DBG("Invalid BIS index %u", bis->index);
166
167 return -EINVAL;
168 }
169
170 /* codec config data length */
171 len = net_buf_simple_pull_u8(buf);
172 if (len > buf->len) {
173 LOG_DBG("Invalid BIS specific codec config data length: %u (buf is %u)", len,
174 buf->len);
175
176 return -EMSGSIZE;
177 }
178
179 if (len > 0) {
180 struct net_buf_simple ltv_buf;
181 void *ltv_data;
182
183 /* Use an extra net_buf_simple to be able to decode until it
184 * is empty (len = 0)
185 */
186 ltv_data = net_buf_simple_pull_mem(buf, len);
187 net_buf_simple_init_with_data(<v_buf, ltv_data, len);
188
189
190 while (ltv_buf.len != 0) {
191 struct bt_codec_data *bis_codec_data;
192 int err;
193
194 if (bis->data_count >= ARRAY_SIZE(bis->data)) {
195 LOG_WRN("BIS data overflow; discarding");
196 break;
197 }
198
199 bis_codec_data = &bis->data[bis->data_count];
200
201 err = decode_codec_ltv(<v_buf, bis_codec_data);
202 if (err != 0) {
203 LOG_DBG("Failed to decode BIS config data for entry[%u]: %d",
204 bis->data_count, err);
205
206 return err;
207 }
208
209 bis->data_count++;
210 }
211 }
212
213 return 0;
214 }
215
decode_subgroup(struct net_buf_simple * buf,struct bt_bap_base_subgroup * subgroup)216 static int decode_subgroup(struct net_buf_simple *buf, struct bt_bap_base_subgroup *subgroup)
217 {
218 struct net_buf_simple ltv_buf;
219 struct bt_codec *codec;
220 void *ltv_data;
221 uint8_t len;
222
223 codec = &subgroup->codec;
224
225 subgroup->bis_count = net_buf_simple_pull_u8(buf);
226 if (subgroup->bis_count > ARRAY_SIZE(subgroup->bis_data)) {
227 LOG_DBG("BASE has more BIS %u than we support %u", subgroup->bis_count,
228 (uint8_t)ARRAY_SIZE(subgroup->bis_data));
229
230 return -ENOMEM;
231 }
232
233 codec->id = net_buf_simple_pull_u8(buf);
234 codec->cid = net_buf_simple_pull_le16(buf);
235 codec->vid = net_buf_simple_pull_le16(buf);
236
237 /* codec configuration data length */
238 len = net_buf_simple_pull_u8(buf);
239 if (len > buf->len) {
240 LOG_DBG("Invalid codec config data length: %u (buf is %u)", len, buf->len);
241
242 return -EINVAL;
243 }
244
245 #if CONFIG_BT_CODEC_MAX_DATA_COUNT > 0
246 /* Use an extra net_buf_simple to be able to decode until it
247 * is empty (len = 0)
248 */
249 ltv_data = net_buf_simple_pull_mem(buf, len);
250 net_buf_simple_init_with_data(<v_buf, ltv_data, len);
251
252 /* The loop below is very similar to codec_config_store with notable
253 * exceptions that it can do early termination, and also does not log
254 * every LTV entry, which would simply be too much for handling
255 * broadcasted BASEs
256 */
257 while (ltv_buf.len != 0) {
258 struct bt_codec_data *codec_data;
259 int err;
260
261 if (codec->data_count >= ARRAY_SIZE(codec->data)) {
262 LOG_WRN("BIS codec data overflow; discarding");
263 break;
264 }
265
266 codec_data = &codec->data[codec->data_count];
267
268 err = decode_codec_ltv(<v_buf, codec_data);
269 if (err != 0) {
270 LOG_DBG("Failed to decode codec config data for entry %u: %d",
271 codec->data_count, err);
272
273 return err;
274 }
275
276 codec->data_count++;
277 }
278
279 if (buf->len < sizeof(len)) {
280 LOG_DBG("Cannot store BASE in buffer");
281
282 return -ENOMEM;
283 }
284 #else /* CONFIG_BT_CODEC_MAX_DATA_COUNT == 0 */
285 if (len > 0) {
286 LOG_DBG("Cannot store codec config data");
287
288 return -ENOMEM;
289 }
290 #endif /* CONFIG_BT_CODEC_MAX_DATA_COUNT */
291
292 /* codec metadata length */
293 len = net_buf_simple_pull_u8(buf);
294 if (len > buf->len) {
295 LOG_DBG("Invalid codec config data length: %u (buf is %u)", len, buf->len);
296
297 return -EMSGSIZE;
298 }
299
300 #if CONFIG_BT_CODEC_MAX_METADATA_COUNT > 0
301 /* Use an extra net_buf_simple to be able to decode until it
302 * is empty (len = 0)
303 */
304 ltv_data = net_buf_simple_pull_mem(buf, len);
305 net_buf_simple_init_with_data(<v_buf, ltv_data, len);
306
307 /* The loop below is very similar to codec_config_store with notable
308 * exceptions that it can do early termination, and also does not log
309 * every LTV entry, which would simply be too much for handling
310 * broadcasted BASEs
311 */
312 while (ltv_buf.len != 0) {
313 struct bt_codec_data *metadata;
314 int err;
315
316 if (codec->meta_count >= ARRAY_SIZE(codec->meta)) {
317 LOG_WRN("BIS codec metadata overflow; discarding");
318 break;
319 }
320
321 metadata = &codec->meta[codec->meta_count];
322
323 err = decode_codec_ltv(<v_buf, metadata);
324 if (err != 0) {
325 LOG_DBG("Failed to decode codec metadata for entry %u: %d",
326 codec->meta_count, err);
327
328 return err;
329 }
330
331 codec->meta_count++;
332 }
333 #else /* CONFIG_BT_CODEC_MAX_METADATA_COUNT == 0 */
334 if (len > 0) {
335 LOG_DBG("Cannot store metadata");
336
337 return -ENOMEM;
338 }
339 #endif /* CONFIG_BT_CODEC_MAX_METADATA_COUNT */
340
341 for (size_t i = 0U; i < subgroup->bis_count; i++) {
342 const int err = decode_bis_data(buf, &subgroup->bis_data[i]);
343
344 if (err != 0) {
345 LOG_DBG("Failed to decode BIS data for bis[%zu]: %d", i, err);
346
347 return err;
348 }
349 }
350
351 return 0;
352 }
353
bt_bap_decode_base(struct bt_data * data,struct bt_bap_base * base)354 int bt_bap_decode_base(struct bt_data *data, struct bt_bap_base *base)
355 {
356 struct bt_uuid_16 broadcast_uuid;
357 struct net_buf_simple net_buf;
358 void *uuid;
359
360 CHECKIF(data == NULL) {
361 LOG_DBG("data is NULL");
362
363 return -EINVAL;
364 }
365
366 CHECKIF(base == NULL) {
367 LOG_DBG("base is NULL");
368
369 return -EINVAL;
370 }
371
372 if (data->type != BT_DATA_SVC_DATA16) {
373 LOG_DBG("Invalid type: %u", data->type);
374
375 return -ENOMSG;
376 }
377
378 if (data->data_len < BT_BAP_BASE_MIN_SIZE) {
379 return -EMSGSIZE;
380 }
381
382 net_buf_simple_init_with_data(&net_buf, (void *)data->data,
383 data->data_len);
384
385 uuid = net_buf_simple_pull_mem(&net_buf, BT_UUID_SIZE_16);
386 if (!bt_uuid_create(&broadcast_uuid.uuid, uuid, BT_UUID_SIZE_16)) {
387 LOG_ERR("bt_uuid_create failed");
388
389 return -EINVAL;
390 }
391
392 if (bt_uuid_cmp(&broadcast_uuid.uuid, BT_UUID_BASIC_AUDIO) != 0) {
393 LOG_DBG("Invalid UUID");
394
395 return -ENOMSG;
396 }
397
398 base->pd = net_buf_simple_pull_le24(&net_buf);
399 base->subgroup_count = net_buf_simple_pull_u8(&net_buf);
400
401 if (base->subgroup_count > ARRAY_SIZE(base->subgroups)) {
402 LOG_DBG("Cannot decode BASE with %u subgroups (max supported is %zu)",
403 base->subgroup_count, ARRAY_SIZE(base->subgroups));
404
405 return -ENOMEM;
406 }
407
408 for (size_t i = 0U; i < base->subgroup_count; i++) {
409 const int err = decode_subgroup(&net_buf, &base->subgroups[i]);
410
411 if (err != 0) {
412 LOG_DBG("Failed to decode subgroup[%zu]: %d", i, err);
413
414 return err;
415 }
416 }
417
418 return 0;
419 }
420 #endif /* CONFIG_BT_BAP_SCAN_DELEGATOR */
421
bt_audio_codec_data_to_buf(const struct bt_codec_data * codec_data,size_t count,uint8_t * buf,size_t buf_size)422 ssize_t bt_audio_codec_data_to_buf(const struct bt_codec_data *codec_data, size_t count,
423 uint8_t *buf, size_t buf_size)
424 {
425 size_t total_len = 0;
426
427 for (size_t i = 0; i < count; i++) {
428 const struct bt_data *ltv = &codec_data[i].data;
429 const uint8_t length = ltv->data_len;
430 const uint8_t type = ltv->type;
431 const uint8_t *value = ltv->data;
432 const size_t ltv_len = sizeof(length) + sizeof(type) + length;
433
434 /* Verify that the buffer can hold the next LTV structure */
435 if (buf_size < total_len + ltv_len) {
436 return -ENOMEM;
437 }
438
439 /* Copy data */
440 buf[total_len++] = length + sizeof(type);
441 buf[total_len++] = type;
442 (void)memcpy(&buf[total_len], value, length);
443
444 total_len += length;
445 }
446
447 return total_len;
448 }
449