1 /*
2 * Copyright (c) 2021-2024 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <errno.h>
8 #include <stddef.h>
9 #include <stdint.h>
10
11 #include <zephyr/autoconf.h>
12 #include <zephyr/bluetooth/addr.h>
13 #include <zephyr/bluetooth/audio/audio.h>
14 #include <zephyr/bluetooth/audio/bap.h>
15 #include <zephyr/bluetooth/audio/lc3.h>
16 #include <zephyr/bluetooth/audio/pacs.h>
17 #include <zephyr/bluetooth/bluetooth.h>
18 #include <zephyr/bluetooth/byteorder.h>
19 #include <zephyr/bluetooth/conn.h>
20 #include <zephyr/bluetooth/gap.h>
21 #include <zephyr/bluetooth/hci.h>
22 #include <zephyr/bluetooth/hci_types.h>
23 #include <zephyr/bluetooth/iso.h>
24 #include <zephyr/bluetooth/uuid.h>
25 #include <zephyr/kernel.h>
26 #include <zephyr/net_buf.h>
27 #include <zephyr/sys/__assert.h>
28 #include <zephyr/sys/byteorder.h>
29 #include <zephyr/sys/printk.h>
30 #include <zephyr/sys/util.h>
31 #include <zephyr/sys/util_macro.h>
32 #include <zephyr/sys_clock.h>
33 #include <zephyr/types.h>
34
35 #define AVAILABLE_SINK_CONTEXT (BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | \
36 BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | \
37 BT_AUDIO_CONTEXT_TYPE_MEDIA | \
38 BT_AUDIO_CONTEXT_TYPE_GAME | \
39 BT_AUDIO_CONTEXT_TYPE_INSTRUCTIONAL)
40
41 #define AVAILABLE_SOURCE_CONTEXT (BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | \
42 BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | \
43 BT_AUDIO_CONTEXT_TYPE_MEDIA | \
44 BT_AUDIO_CONTEXT_TYPE_GAME)
45
46 NET_BUF_POOL_FIXED_DEFINE(tx_pool, CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT,
47 BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU),
48 CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
49
50 static const struct bt_audio_codec_cap lc3_codec_cap = BT_AUDIO_CODEC_CAP_LC3(
51 BT_AUDIO_CODEC_CAP_FREQ_ANY, BT_AUDIO_CODEC_CAP_DURATION_10,
52 BT_AUDIO_CODEC_CAP_CHAN_COUNT_SUPPORT(1), 40u, 120u, 1u,
53 (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA));
54
55 static struct bt_conn *default_conn;
56 static struct k_work_delayable audio_send_work;
57 static struct bt_bap_stream sink_streams[CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT];
58 static struct audio_source {
59 struct bt_bap_stream stream;
60 uint16_t seq_num;
61 uint16_t max_sdu;
62 size_t len_to_send;
63 } source_streams[CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT];
64 static size_t configured_source_stream_count;
65
66 static const struct bt_bap_qos_cfg_pref qos_pref =
67 BT_BAP_QOS_CFG_PREF(true, BT_GAP_LE_PHY_2M, 0x02, 10, 40000, 40000, 40000, 40000);
68
69 static K_SEM_DEFINE(sem_disconnected, 0, 1);
70
71 static uint8_t unicast_server_addata[] = {
72 BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL), /* ASCS UUID */
73 BT_AUDIO_UNICAST_ANNOUNCEMENT_TARGETED, /* Target Announcement */
74 BT_BYTES_LIST_LE16(AVAILABLE_SINK_CONTEXT),
75 BT_BYTES_LIST_LE16(AVAILABLE_SOURCE_CONTEXT),
76 0x00, /* Metadata length */
77 };
78
79 /* TODO: Expand with BAP data */
80 static const struct bt_data ad[] = {
81 BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
82 BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL)),
83 BT_DATA(BT_DATA_SVC_DATA16, unicast_server_addata, ARRAY_SIZE(unicast_server_addata)),
84 BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1),
85 };
86
87 #define AUDIO_DATA_TIMEOUT_US 1000000UL /* Send data every 1 second */
88 #define SDU_INTERVAL_US 10000UL /* 10 ms SDU interval */
89
get_and_incr_seq_num(const struct bt_bap_stream * stream)90 static uint16_t get_and_incr_seq_num(const struct bt_bap_stream *stream)
91 {
92 for (size_t i = 0U; i < configured_source_stream_count; i++) {
93 if (stream == &source_streams[i].stream) {
94 uint16_t seq_num;
95
96 seq_num = source_streams[i].seq_num;
97
98 if (IS_ENABLED(CONFIG_LIBLC3)) {
99 source_streams[i].seq_num++;
100 } else {
101 source_streams[i].seq_num += (AUDIO_DATA_TIMEOUT_US /
102 SDU_INTERVAL_US);
103 }
104
105 return seq_num;
106 }
107 }
108
109 printk("Could not find endpoint from stream %p\n", stream);
110
111 return 0;
112 }
113
114 #if defined(CONFIG_LIBLC3)
115
116 #include "lc3.h"
117
118 #define MAX_SAMPLE_RATE 48000
119 #define MAX_FRAME_DURATION_US 10000
120 #define MAX_NUM_SAMPLES ((MAX_FRAME_DURATION_US * MAX_SAMPLE_RATE) / USEC_PER_SEC)
121
122 static int16_t audio_buf[MAX_NUM_SAMPLES];
123 static lc3_decoder_t lc3_decoder;
124 static lc3_decoder_mem_48k_t lc3_decoder_mem;
125 static int frames_per_sdu;
126
127 #endif
128
print_hex(const uint8_t * ptr,size_t len)129 void print_hex(const uint8_t *ptr, size_t len)
130 {
131 while (len-- != 0) {
132 printk("%02x", *ptr++);
133 }
134 }
135
print_cb(struct bt_data * data,void * user_data)136 static bool print_cb(struct bt_data *data, void *user_data)
137 {
138 const char *str = (const char *)user_data;
139
140 printk("%s: type 0x%02x value_len %u\n", str, data->type, data->data_len);
141 print_hex(data->data, data->data_len);
142 printk("\n");
143
144 return true;
145 }
146
print_codec_cfg(const struct bt_audio_codec_cfg * codec_cfg)147 static void print_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg)
148 {
149 printk("codec_cfg 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cfg->id, codec_cfg->cid,
150 codec_cfg->vid, codec_cfg->data_len);
151
152 if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) {
153 enum bt_audio_location chan_allocation;
154 int ret;
155
156 /* LC3 uses the generic LTV format - other codecs might do as well */
157
158 bt_audio_data_parse(codec_cfg->data, codec_cfg->data_len, print_cb, "data");
159
160 ret = bt_audio_codec_cfg_get_freq(codec_cfg);
161 if (ret > 0) {
162 printk(" Frequency: %d Hz\n", bt_audio_codec_cfg_freq_to_freq_hz(ret));
163 }
164
165 ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg);
166 if (ret > 0) {
167 printk(" Frame Duration: %d us\n",
168 bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret));
169 }
170
171 ret = bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &chan_allocation, false);
172 if (ret == 0) {
173 printk(" Channel allocation: 0x%x\n", chan_allocation);
174 }
175
176 printk(" Octets per frame: %d (negative means value not pressent)\n",
177 bt_audio_codec_cfg_get_octets_per_frame(codec_cfg));
178 printk(" Frames per SDU: %d\n",
179 bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true));
180 } else {
181 print_hex(codec_cfg->data, codec_cfg->data_len);
182 }
183
184 bt_audio_data_parse(codec_cfg->meta, codec_cfg->meta_len, print_cb, "meta");
185 }
186
print_qos(const struct bt_bap_qos_cfg * qos)187 static void print_qos(const struct bt_bap_qos_cfg *qos)
188 {
189 printk("QoS: interval %u framing 0x%02x phy 0x%02x sdu %u "
190 "rtn %u latency %u pd %u\n",
191 qos->interval, qos->framing, qos->phy, qos->sdu,
192 qos->rtn, qos->latency, qos->pd);
193 }
194
195 /**
196 * @brief Send audio data on timeout
197 *
198 * This will send an increasing amount of audio data, starting from 1 octet.
199 * The data is just mock data, and does not actually represent any audio.
200 *
201 * First iteration : 0x00
202 * Second iteration: 0x00 0x01
203 * Third iteration : 0x00 0x01 0x02
204 *
205 * And so on, until it wraps around the configured MTU (CONFIG_BT_ISO_TX_MTU)
206 *
207 * @param work Pointer to the work structure
208 */
audio_timer_timeout(struct k_work * work)209 static void audio_timer_timeout(struct k_work *work)
210 {
211 int ret;
212 static uint8_t buf_data[CONFIG_BT_ISO_TX_MTU];
213 static bool data_initialized;
214 struct net_buf *buf;
215
216 if (!data_initialized) {
217 /* TODO: Actually encode some audio data */
218 for (size_t i = 0U; i < ARRAY_SIZE(buf_data); i++) {
219 buf_data[i] = (uint8_t)i;
220 }
221
222 data_initialized = true;
223 }
224
225 /* We configured the sink streams to be first in `streams`, so that
226 * we can use `stream[i]` to select sink streams (i.e. streams with
227 * data going to the server)
228 */
229 for (size_t i = 0; i < configured_source_stream_count; i++) {
230 struct bt_bap_stream *stream = &source_streams[i].stream;
231
232 buf = net_buf_alloc(&tx_pool, K_NO_WAIT);
233 if (buf == NULL) {
234 printk("Failed to allocate TX buffer\n");
235 /* Break and retry later */
236 break;
237 }
238 net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE);
239
240 net_buf_add_mem(buf, buf_data, ++source_streams[i].len_to_send);
241
242 ret = bt_bap_stream_send(stream, buf, get_and_incr_seq_num(stream));
243 if (ret < 0) {
244 printk("Failed to send audio data on streams[%zu] (%p): (%d)\n",
245 i, stream, ret);
246 net_buf_unref(buf);
247 } else {
248 printk("Sending mock data with len %zu on streams[%zu] (%p)\n",
249 source_streams[i].len_to_send, i, stream);
250 }
251
252 if (source_streams[i].len_to_send >= source_streams[i].max_sdu) {
253 source_streams[i].len_to_send = 0;
254 }
255 }
256
257 #if defined(CONFIG_LIBLC3)
258 k_work_schedule(&audio_send_work, K_USEC(MAX_FRAME_DURATION_US));
259 #else
260 k_work_schedule(&audio_send_work, K_USEC(AUDIO_DATA_TIMEOUT_US));
261 #endif
262 }
263
stream_dir(const struct bt_bap_stream * stream)264 static enum bt_audio_dir stream_dir(const struct bt_bap_stream *stream)
265 {
266 for (size_t i = 0U; i < ARRAY_SIZE(source_streams); i++) {
267 if (stream == &source_streams[i].stream) {
268 return BT_AUDIO_DIR_SOURCE;
269 }
270 }
271
272 for (size_t i = 0U; i < ARRAY_SIZE(sink_streams); i++) {
273 if (stream == &sink_streams[i]) {
274 return BT_AUDIO_DIR_SINK;
275 }
276 }
277
278 __ASSERT(false, "Invalid stream %p", stream);
279 return 0;
280 }
281
stream_alloc(enum bt_audio_dir dir)282 static struct bt_bap_stream *stream_alloc(enum bt_audio_dir dir)
283 {
284 if (dir == BT_AUDIO_DIR_SOURCE) {
285 for (size_t i = 0; i < ARRAY_SIZE(source_streams); i++) {
286 struct bt_bap_stream *stream = &source_streams[i].stream;
287
288 if (!stream->conn) {
289 return stream;
290 }
291 }
292 } else {
293 for (size_t i = 0; i < ARRAY_SIZE(sink_streams); i++) {
294 struct bt_bap_stream *stream = &sink_streams[i];
295
296 if (!stream->conn) {
297 return stream;
298 }
299 }
300 }
301
302 return NULL;
303 }
304
lc3_config(struct bt_conn * conn,const struct bt_bap_ep * ep,enum bt_audio_dir dir,const struct bt_audio_codec_cfg * codec_cfg,struct bt_bap_stream ** stream,struct bt_bap_qos_cfg_pref * const pref,struct bt_bap_ascs_rsp * rsp)305 static int lc3_config(struct bt_conn *conn, const struct bt_bap_ep *ep, enum bt_audio_dir dir,
306 const struct bt_audio_codec_cfg *codec_cfg, struct bt_bap_stream **stream,
307 struct bt_bap_qos_cfg_pref *const pref, struct bt_bap_ascs_rsp *rsp)
308 {
309 printk("ASE Codec Config: conn %p ep %p dir %u\n", conn, ep, dir);
310
311 print_codec_cfg(codec_cfg);
312
313 *stream = stream_alloc(dir);
314 if (*stream == NULL) {
315 printk("No streams available\n");
316 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_NO_MEM, BT_BAP_ASCS_REASON_NONE);
317
318 return -ENOMEM;
319 }
320
321 printk("ASE Codec Config stream %p\n", *stream);
322
323 if (dir == BT_AUDIO_DIR_SOURCE) {
324 configured_source_stream_count++;
325 }
326
327 *pref = qos_pref;
328
329 #if defined(CONFIG_LIBLC3)
330 /* Nothing to free as static memory is used */
331 lc3_decoder = NULL;
332 #endif
333
334 return 0;
335 }
336
lc3_reconfig(struct bt_bap_stream * stream,enum bt_audio_dir dir,const struct bt_audio_codec_cfg * codec_cfg,struct bt_bap_qos_cfg_pref * const pref,struct bt_bap_ascs_rsp * rsp)337 static int lc3_reconfig(struct bt_bap_stream *stream, enum bt_audio_dir dir,
338 const struct bt_audio_codec_cfg *codec_cfg,
339 struct bt_bap_qos_cfg_pref *const pref, struct bt_bap_ascs_rsp *rsp)
340 {
341 printk("ASE Codec Reconfig: stream %p\n", stream);
342
343 print_codec_cfg(codec_cfg);
344
345 #if defined(CONFIG_LIBLC3)
346 /* Nothing to free as static memory is used */
347 lc3_decoder = NULL;
348 #endif
349
350 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_CONF_UNSUPPORTED, BT_BAP_ASCS_REASON_NONE);
351
352 /* We only support one QoS at the moment, reject changes */
353 return -ENOEXEC;
354 }
355
lc3_qos(struct bt_bap_stream * stream,const struct bt_bap_qos_cfg * qos,struct bt_bap_ascs_rsp * rsp)356 static int lc3_qos(struct bt_bap_stream *stream, const struct bt_bap_qos_cfg *qos,
357 struct bt_bap_ascs_rsp *rsp)
358 {
359 printk("QoS: stream %p qos %p\n", stream, qos);
360
361 print_qos(qos);
362
363 for (size_t i = 0U; i < configured_source_stream_count; i++) {
364 if (stream == &source_streams[i].stream) {
365 source_streams[i].max_sdu = qos->sdu;
366 break;
367 }
368 }
369
370 return 0;
371 }
372
lc3_enable(struct bt_bap_stream * stream,const uint8_t meta[],size_t meta_len,struct bt_bap_ascs_rsp * rsp)373 static int lc3_enable(struct bt_bap_stream *stream, const uint8_t meta[], size_t meta_len,
374 struct bt_bap_ascs_rsp *rsp)
375 {
376 printk("Enable: stream %p meta_len %zu\n", stream, meta_len);
377
378 #if defined(CONFIG_LIBLC3)
379 {
380 int frame_duration_us;
381 int freq;
382 int ret;
383
384 ret = bt_audio_codec_cfg_get_freq(stream->codec_cfg);
385 if (ret > 0) {
386 freq = bt_audio_codec_cfg_freq_to_freq_hz(ret);
387 } else {
388 printk("Error: Codec frequency not set, cannot start codec.");
389 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_CONF_INVALID,
390 BT_BAP_ASCS_REASON_CODEC_DATA);
391 return ret;
392 }
393
394 ret = bt_audio_codec_cfg_get_frame_dur(stream->codec_cfg);
395 if (ret > 0) {
396 frame_duration_us = bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret);
397 } else {
398 printk("Error: Frame duration not set, cannot start codec.");
399 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_CONF_INVALID,
400 BT_BAP_ASCS_REASON_CODEC_DATA);
401 return ret;
402 }
403
404 frames_per_sdu =
405 bt_audio_codec_cfg_get_frame_blocks_per_sdu(stream->codec_cfg, true);
406
407 lc3_decoder = lc3_setup_decoder(frame_duration_us,
408 freq,
409 0, /* No resampling */
410 &lc3_decoder_mem);
411
412 if (lc3_decoder == NULL) {
413 printk("ERROR: Failed to setup LC3 encoder - wrong parameters?\n");
414 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_CONF_INVALID,
415 BT_BAP_ASCS_REASON_CODEC_DATA);
416 return -1;
417 }
418 }
419 #endif
420
421 return 0;
422 }
423
lc3_start(struct bt_bap_stream * stream,struct bt_bap_ascs_rsp * rsp)424 static int lc3_start(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp)
425 {
426 printk("Start: stream %p\n", stream);
427
428 for (size_t i = 0U; i < configured_source_stream_count; i++) {
429 if (stream == &source_streams[i].stream) {
430 source_streams[i].seq_num = 0U;
431 source_streams[i].len_to_send = 0U;
432 break;
433 }
434 }
435
436 if (configured_source_stream_count > 0 &&
437 !k_work_delayable_is_pending(&audio_send_work)) {
438
439 /* Start send timer */
440 k_work_schedule(&audio_send_work, K_MSEC(0));
441 }
442
443 return 0;
444 }
445
data_func_cb(struct bt_data * data,void * user_data)446 static bool data_func_cb(struct bt_data *data, void *user_data)
447 {
448 struct bt_bap_ascs_rsp *rsp = (struct bt_bap_ascs_rsp *)user_data;
449
450 if (!BT_AUDIO_METADATA_TYPE_IS_KNOWN(data->type)) {
451 printk("Invalid metadata type %u or length %u\n", data->type, data->data_len);
452 *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_METADATA_REJECTED, data->type);
453
454 return -EINVAL;
455 }
456
457 return true;
458 }
459
lc3_metadata(struct bt_bap_stream * stream,const uint8_t meta[],size_t meta_len,struct bt_bap_ascs_rsp * rsp)460 static int lc3_metadata(struct bt_bap_stream *stream, const uint8_t meta[], size_t meta_len,
461 struct bt_bap_ascs_rsp *rsp)
462 {
463 printk("Metadata: stream %p meta_len %zu\n", stream, meta_len);
464
465 return bt_audio_data_parse(meta, meta_len, data_func_cb, rsp);
466 }
467
lc3_disable(struct bt_bap_stream * stream,struct bt_bap_ascs_rsp * rsp)468 static int lc3_disable(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp)
469 {
470 printk("Disable: stream %p\n", stream);
471
472 return 0;
473 }
474
lc3_stop(struct bt_bap_stream * stream,struct bt_bap_ascs_rsp * rsp)475 static int lc3_stop(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp)
476 {
477 printk("Stop: stream %p\n", stream);
478
479 return 0;
480 }
481
lc3_release(struct bt_bap_stream * stream,struct bt_bap_ascs_rsp * rsp)482 static int lc3_release(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp)
483 {
484 printk("Release: stream %p\n", stream);
485 return 0;
486 }
487
488 static struct bt_bap_unicast_server_register_param param = {
489 CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT,
490 CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT
491 };
492
493 static const struct bt_bap_unicast_server_cb unicast_server_cb = {
494 .config = lc3_config,
495 .reconfig = lc3_reconfig,
496 .qos = lc3_qos,
497 .enable = lc3_enable,
498 .start = lc3_start,
499 .metadata = lc3_metadata,
500 .disable = lc3_disable,
501 .stop = lc3_stop,
502 .release = lc3_release,
503 };
504
505
506 #if defined(CONFIG_LIBLC3)
507
stream_recv_lc3_codec(struct bt_bap_stream * stream,const struct bt_iso_recv_info * info,struct net_buf * buf)508 static void stream_recv_lc3_codec(struct bt_bap_stream *stream,
509 const struct bt_iso_recv_info *info,
510 struct net_buf *buf)
511 {
512 const bool valid_data = (info->flags & BT_ISO_FLAGS_VALID) == 0;
513 const int octets_per_frame = buf->len / frames_per_sdu;
514
515 if (lc3_decoder == NULL) {
516 printk("LC3 decoder not setup, cannot decode data.\n");
517 return;
518 }
519
520 if (!valid_data) {
521 printk("Bad packet: 0x%02X\n", info->flags);
522 }
523
524 for (int i = 0; i < frames_per_sdu; i++) {
525 /* Passing NULL performs PLC */
526 const int err = lc3_decode(
527 lc3_decoder, valid_data ? net_buf_pull_mem(buf, octets_per_frame) : NULL,
528 octets_per_frame, LC3_PCM_FORMAT_S16, audio_buf, 1);
529
530 if (err == 1) {
531 printk("[%d]: Decoder performed PLC\n", i);
532 } else if (err < 0) {
533 printk("[%d]: Decoder failed - wrong parameters?: %d\n", i, err);
534 }
535 }
536
537 printk("RX stream %p len %u\n", stream, buf->len);
538 }
539
540 #else
541
stream_recv(struct bt_bap_stream * stream,const struct bt_iso_recv_info * info,struct net_buf * buf)542 static void stream_recv(struct bt_bap_stream *stream,
543 const struct bt_iso_recv_info *info,
544 struct net_buf *buf)
545 {
546 if (info->flags & BT_ISO_FLAGS_VALID) {
547 printk("Incoming audio on stream %p len %u\n", stream, buf->len);
548 }
549 }
550
551 #endif
552
stream_stopped(struct bt_bap_stream * stream,uint8_t reason)553 static void stream_stopped(struct bt_bap_stream *stream, uint8_t reason)
554 {
555 printk("Audio Stream %p stopped with reason 0x%02X\n", stream, reason);
556
557 /* Stop send timer */
558 k_work_cancel_delayable(&audio_send_work);
559 }
560
stream_started(struct bt_bap_stream * stream)561 static void stream_started(struct bt_bap_stream *stream)
562 {
563 printk("Audio Stream %p started\n", stream);
564 }
565
stream_enabled_cb(struct bt_bap_stream * stream)566 static void stream_enabled_cb(struct bt_bap_stream *stream)
567 {
568 /* The unicast server is responsible for starting sink ASEs after the
569 * client has enabled them.
570 */
571 if (stream_dir(stream) == BT_AUDIO_DIR_SINK) {
572 const int err = bt_bap_stream_start(stream);
573
574 if (err != 0) {
575 printk("Failed to start stream %p: %d", stream, err);
576 }
577 }
578 }
579
580 static struct bt_bap_stream_ops stream_ops = {
581 #if defined(CONFIG_LIBLC3)
582 .recv = stream_recv_lc3_codec,
583 #else
584 .recv = stream_recv,
585 #endif
586 .stopped = stream_stopped,
587 .started = stream_started,
588 .enabled = stream_enabled_cb,
589 };
590
connected(struct bt_conn * conn,uint8_t err)591 static void connected(struct bt_conn *conn, uint8_t err)
592 {
593 char addr[BT_ADDR_LE_STR_LEN];
594
595 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
596
597 if (err != 0) {
598 printk("Failed to connect to %s %u %s\n", addr, err, bt_hci_err_to_str(err));
599
600 default_conn = NULL;
601 return;
602 }
603
604 printk("Connected: %s\n", addr);
605 default_conn = bt_conn_ref(conn);
606 }
607
disconnected(struct bt_conn * conn,uint8_t reason)608 static void disconnected(struct bt_conn *conn, uint8_t reason)
609 {
610 char addr[BT_ADDR_LE_STR_LEN];
611
612 if (conn != default_conn) {
613 return;
614 }
615
616 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
617
618 printk("Disconnected: %s, reason 0x%02x %s\n", addr, reason, bt_hci_err_to_str(reason));
619
620 bt_conn_unref(default_conn);
621 default_conn = NULL;
622
623 k_sem_give(&sem_disconnected);
624 }
625
626 BT_CONN_CB_DEFINE(conn_callbacks) = {
627 .connected = connected,
628 .disconnected = disconnected,
629 };
630
631 static struct bt_pacs_cap cap_sink = {
632 .codec_cap = &lc3_codec_cap,
633 };
634
635 static struct bt_pacs_cap cap_source = {
636 .codec_cap = &lc3_codec_cap,
637 };
638
set_location(void)639 static int set_location(void)
640 {
641 int err;
642
643 if (IS_ENABLED(CONFIG_BT_PAC_SNK_LOC)) {
644 err = bt_pacs_set_location(BT_AUDIO_DIR_SINK,
645 BT_AUDIO_LOCATION_FRONT_CENTER);
646 if (err != 0) {
647 printk("Failed to set sink location (err %d)\n", err);
648 return err;
649 }
650 }
651
652 if (IS_ENABLED(CONFIG_BT_PAC_SRC_LOC)) {
653 err = bt_pacs_set_location(BT_AUDIO_DIR_SOURCE,
654 (BT_AUDIO_LOCATION_FRONT_LEFT |
655 BT_AUDIO_LOCATION_FRONT_RIGHT));
656 if (err != 0) {
657 printk("Failed to set source location (err %d)\n", err);
658 return err;
659 }
660 }
661
662 printk("Location successfully set\n");
663
664 return 0;
665 }
666
set_supported_contexts(void)667 static int set_supported_contexts(void)
668 {
669 int err;
670
671 if (IS_ENABLED(CONFIG_BT_PAC_SNK)) {
672 err = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SINK,
673 AVAILABLE_SINK_CONTEXT);
674 if (err != 0) {
675 printk("Failed to set sink supported contexts (err %d)\n",
676 err);
677
678 return err;
679 }
680 }
681
682 if (IS_ENABLED(CONFIG_BT_PAC_SRC)) {
683 err = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SOURCE,
684 AVAILABLE_SOURCE_CONTEXT);
685 if (err != 0) {
686 printk("Failed to set source supported contexts (err %d)\n",
687 err);
688
689 return err;
690 }
691 }
692
693 printk("Supported contexts successfully set\n");
694
695 return 0;
696 }
697
set_available_contexts(void)698 static int set_available_contexts(void)
699 {
700 int err;
701
702 if (IS_ENABLED(CONFIG_BT_PAC_SNK)) {
703 err = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SINK,
704 AVAILABLE_SINK_CONTEXT);
705 if (err != 0) {
706 printk("Failed to set sink available contexts (err %d)\n", err);
707 return err;
708 }
709 }
710
711 if (IS_ENABLED(CONFIG_BT_PAC_SRC)) {
712 err = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SOURCE,
713 AVAILABLE_SOURCE_CONTEXT);
714 if (err != 0) {
715 printk("Failed to set source available contexts (err %d)\n", err);
716 return err;
717 }
718 }
719
720 printk("Available contexts successfully set\n");
721 return 0;
722 }
723
main(void)724 int main(void)
725 {
726 struct bt_le_ext_adv *adv;
727 int err;
728
729 err = bt_enable(NULL);
730 if (err != 0) {
731 printk("Bluetooth init failed (err %d)\n", err);
732 return 0;
733 }
734
735 printk("Bluetooth initialized\n");
736
737 bt_bap_unicast_server_register(¶m);
738 bt_bap_unicast_server_register_cb(&unicast_server_cb);
739
740 bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap_sink);
741 bt_pacs_cap_register(BT_AUDIO_DIR_SOURCE, &cap_source);
742
743 for (size_t i = 0; i < ARRAY_SIZE(sink_streams); i++) {
744 bt_bap_stream_cb_register(&sink_streams[i], &stream_ops);
745 }
746
747 for (size_t i = 0; i < ARRAY_SIZE(source_streams); i++) {
748 bt_bap_stream_cb_register(&source_streams[i].stream,
749 &stream_ops);
750 }
751
752 err = set_location();
753 if (err != 0) {
754 return 0;
755 }
756
757 err = set_supported_contexts();
758 if (err != 0) {
759 return 0;
760 }
761
762 err = set_available_contexts();
763 if (err != 0) {
764 return 0;
765 }
766
767 /* Create a connectable advertising set */
768 err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN, NULL, &adv);
769 if (err) {
770 printk("Failed to create advertising set (err %d)\n", err);
771 return 0;
772 }
773
774 err = bt_le_ext_adv_set_data(adv, ad, ARRAY_SIZE(ad), NULL, 0);
775 if (err) {
776 printk("Failed to set advertising data (err %d)\n", err);
777 return 0;
778 }
779
780 while (true) {
781 struct k_work_sync sync;
782
783 err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT);
784 if (err) {
785 printk("Failed to start advertising set (err %d)\n", err);
786 return 0;
787 }
788
789 printk("Advertising successfully started\n");
790
791 if (CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT > 0) {
792 /* Start send timer */
793 k_work_init_delayable(&audio_send_work, audio_timer_timeout);
794 }
795
796 err = k_sem_take(&sem_disconnected, K_FOREVER);
797 if (err != 0) {
798 printk("failed to take sem_disconnected (err %d)\n", err);
799 return 0;
800 }
801
802 /* reset data */
803 configured_source_stream_count = 0U;
804 k_work_cancel_delayable_sync(&audio_send_work, &sync);
805
806 }
807 return 0;
808 }
809