1 /* main.c - Application main entry point */
2 
3 /*
4  * Copyright 2024-2025 NXP
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <zephyr/types.h>
10 #include <stddef.h>
11 #include <string.h>
12 #include <errno.h>
13 #include <zephyr/sys/printk.h>
14 #include <zephyr/sys/byteorder.h>
15 #include <zephyr/kernel.h>
16 
17 #include <zephyr/bluetooth/bluetooth.h>
18 #include <zephyr/bluetooth/conn.h>
19 #include <zephyr/bluetooth/l2cap.h>
20 #include <zephyr/bluetooth/hci.h>
21 #include <zephyr/bluetooth/sbc.h>
22 #include <zephyr/bluetooth/classic/a2dp_codec_sbc.h>
23 #include <zephyr/bluetooth/classic/a2dp.h>
24 #include <zephyr/bluetooth/classic/sdp.h>
25 #include <zephyr/settings/settings.h>
26 #include "sine.h"
27 
28 static struct bt_br_discovery_param br_discover;
29 static struct bt_br_discovery_result scan_result[CONFIG_BT_A2DP_SOURCE_DISCOVER_RESULT_COUNT];
30 struct k_work discover_work;
31 
32 static struct bt_conn *default_conn;
33 struct bt_a2dp *default_a2dp;
34 static struct bt_a2dp_stream sbc_stream;
35 struct sbc_encoder encoder;
36 
37 BT_A2DP_SBC_SOURCE_EP_DEFAULT(sbc_source_ep);
38 static bool peer_sbc_found;
39 struct bt_a2dp_codec_ie sbc_sink_ep_capabilities;
40 static struct bt_a2dp_ep sbc_sink_ep = {
41 	.codec_cap = &sbc_sink_ep_capabilities,
42 };
43 BT_A2DP_SBC_EP_CFG_DEFAULT(sbc_cfg_default, A2DP_SBC_SAMP_FREQ_44100);
44 
45 /* sbc audio stream control variables */
46 static int64_t ref_time;
47 static uint32_t a2dp_src_missed_count;
48 static volatile bool a2dp_src_playback;
49 static volatile int media_index;
50 static uint32_t a2dp_src_sf;
51 static uint8_t a2dp_src_nc;
52 static uint32_t send_samples_count;
53 static uint16_t send_count;
54 /* max pcm data size per interval. The max sample freq is 48K.
55  * interval * 48 * 2 (max channels) * 2 (sample width) * 2 (the worst case: send two intervals'
56  * data if timer is blocked)
57  */
58 static uint8_t a2dp_pcm_buffer[CONFIG_BT_A2DP_SOURCE_DATA_SEND_INTERVAL * 48 * 2 * 2 * 2];
59 NET_BUF_POOL_DEFINE(a2dp_tx_pool, CONFIG_BT_A2DP_SOURCE_DATA_BUF_COUNT,
60 		    BT_L2CAP_BUF_SIZE(CONFIG_BT_A2DP_SOURCE_DATA_BUF_SIZE),
61 		    CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
62 static void a2dp_playback_timeout_handler(struct k_timer *timer);
63 K_TIMER_DEFINE(a2dp_player_timer, a2dp_playback_timeout_handler, NULL);
64 
65 NET_BUF_POOL_DEFINE(sdp_discover_pool, 10, BT_L2CAP_BUF_SIZE(CONFIG_BT_L2CAP_TX_MTU),
66 		    CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
67 
68 struct k_work_q audio_play_work_q;
69 static K_KERNEL_STACK_DEFINE(audio_play_work_q_thread_stack,
70 			     CONFIG_BT_A2DP_SOURCE_DATA_SEND_WORKQ_STACK_SIZE);
71 
72 #define A2DP_VERSION 0x0104
73 
74 static struct bt_sdp_attribute a2dp_source_attrs[] = {
75 	BT_SDP_NEW_SERVICE,
76 	BT_SDP_LIST(
77 		BT_SDP_ATTR_SVCLASS_ID_LIST,
78 		BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 3),
79 		BT_SDP_DATA_ELEM_LIST(
80 		{
81 			BT_SDP_TYPE_SIZE(BT_SDP_UUID16),
82 			BT_SDP_ARRAY_16(BT_SDP_AUDIO_SOURCE_SVCLASS)
83 		},
84 		)
85 	),
86 	BT_SDP_LIST(
87 		BT_SDP_ATTR_PROTO_DESC_LIST,
88 		BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 16),
89 		BT_SDP_DATA_ELEM_LIST(
90 		{
91 			BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 6),
92 			BT_SDP_DATA_ELEM_LIST(
93 			{
94 				BT_SDP_TYPE_SIZE(BT_SDP_UUID16),
95 				BT_SDP_ARRAY_16(BT_SDP_PROTO_L2CAP)
96 			},
97 			{
98 				BT_SDP_TYPE_SIZE(BT_SDP_UINT16),
99 				BT_SDP_ARRAY_16(BT_UUID_AVDTP_VAL)
100 			},
101 			)
102 		},
103 		{
104 			BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 6),
105 			BT_SDP_DATA_ELEM_LIST(
106 			{
107 				BT_SDP_TYPE_SIZE(BT_SDP_UUID16),
108 				BT_SDP_ARRAY_16(BT_UUID_AVDTP_VAL)
109 			},
110 			{
111 				BT_SDP_TYPE_SIZE(BT_SDP_UINT16),
112 				BT_SDP_ARRAY_16(AVDTP_VERSION)
113 			},
114 			)
115 		},
116 		)
117 	),
118 	BT_SDP_LIST(
119 		BT_SDP_ATTR_PROFILE_DESC_LIST,
120 		BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 8),
121 		BT_SDP_DATA_ELEM_LIST(
122 		{
123 			BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 6),
124 			BT_SDP_DATA_ELEM_LIST(
125 			{
126 				BT_SDP_TYPE_SIZE(BT_SDP_UUID16),
127 				BT_SDP_ARRAY_16(BT_SDP_ADVANCED_AUDIO_SVCLASS)
128 			},
129 			{
130 				BT_SDP_TYPE_SIZE(BT_SDP_UINT16),
131 				BT_SDP_ARRAY_16(A2DP_VERSION)
132 			},
133 			)
134 		},
135 		)
136 	),
137 	BT_SDP_SERVICE_NAME("A2DPSource"),
138 	BT_SDP_SUPPORTED_FEATURES(0x0001U),
139 };
140 
141 static struct bt_sdp_record a2dp_source_rec = BT_SDP_RECORD(a2dp_source_attrs);
142 
a2dp_produce_media_check(uint32_t samples_num)143 static bool a2dp_produce_media_check(uint32_t samples_num)
144 {
145 	uint16_t  medialen;
146 
147 	/* Music Audio is Stereo */
148 	medialen = (samples_num * a2dp_src_nc * 2);
149 
150 	/* need to use a2dp_pcm_buffer to do memcpy */
151 	if ((a2dp_src_nc == 1) || ((media_index + (samples_num << 2)) > sizeof(media_data))) {
152 		if (medialen > sizeof(a2dp_pcm_buffer)) {
153 			return false;
154 		}
155 	}
156 
157 	return true;
158 }
159 
a2dp_produce_media(uint32_t samples_num)160 static uint8_t *a2dp_produce_media(uint32_t samples_num)
161 {
162 	uint8_t *media = NULL;
163 	uint16_t  medialen;
164 
165 	/* Music Audio is Stereo */
166 	medialen = (samples_num * a2dp_src_nc * 2);
167 
168 	/* For mono or dual configuration, skip alternative samples */
169 	if (a2dp_src_nc == 1) {
170 		uint16_t index;
171 
172 		media = (uint8_t *)&a2dp_pcm_buffer[0];
173 
174 		for (index = 0; index < samples_num; index++) {
175 			media[(2 * index)] = *((uint8_t *)media_data + media_index);
176 			media[(2 * index) + 1] = *((uint8_t *)media_data + media_index + 1);
177 			/* Update the tone index */
178 			media_index += 4u;
179 			if (media_index >= sizeof(media_data)) {
180 				media_index = 0U;
181 			}
182 		}
183 	} else {
184 		if ((media_index + (samples_num << 2)) > sizeof(media_data)) {
185 			media = (uint8_t *)&a2dp_pcm_buffer[0];
186 			memcpy(media, ((uint8_t *)media_data + media_index),
187 				sizeof(media_data) - media_index);
188 			memcpy(&media[sizeof(media_data) - media_index],
189 				((uint8_t *)media_data),
190 				((samples_num << 2) - (sizeof(media_data) - media_index)));
191 			/* Update the tone index */
192 			media_index = ((samples_num << 2) -
193 				(sizeof(media_data) - media_index));
194 		} else {
195 			media = ((uint8_t *)media_data + media_index);
196 			/* Update the tone index */
197 			media_index += (samples_num << 2);
198 			if (media_index >= sizeof(media_data)) {
199 				media_index = 0U;
200 			}
201 		}
202 	}
203 
204 	return media;
205 }
206 
audio_play_check(void)207 static void audio_play_check(void)
208 {
209 	uint32_t a2dp_src_num_samples;
210 	uint32_t pcm_frame_samples;
211 	uint8_t frame_num;
212 	struct net_buf *buf;
213 	uint32_t pdu_len;
214 
215 	a2dp_src_num_samples = (uint16_t)((CONFIG_BT_A2DP_SOURCE_DATA_SEND_INTERVAL * a2dp_src_sf)
216 					  / 1000);
217 	pcm_frame_samples = sbc_frame_samples(&encoder);
218 	frame_num = a2dp_src_num_samples / pcm_frame_samples;
219 	if (frame_num * pcm_frame_samples < a2dp_src_num_samples) {
220 		frame_num++;
221 	}
222 	a2dp_src_num_samples = frame_num * pcm_frame_samples;
223 
224 	buf = bt_a2dp_stream_create_pdu(&a2dp_tx_pool, K_FOREVER);
225 	pdu_len = frame_num * sbc_frame_encoded_bytes(&encoder);
226 
227 	if (pdu_len > net_buf_tailroom(buf)) {
228 		printk("need increase buf size %d > %d\n", pdu_len, net_buf_tailroom(buf));
229 	}
230 
231 	pdu_len += buf->len;
232 	if (pdu_len > bt_a2dp_get_mtu(&sbc_stream)) {
233 		printk("need decrease CONFIG_BT_A2DP_SOURCE_DATA_SEND_INTERVAL %d > %d\n", pdu_len,
234 			bt_a2dp_get_mtu(&sbc_stream));
235 	}
236 
237 	if (!a2dp_produce_media_check(a2dp_src_num_samples)) {
238 		printk("need increase a2dp_pcm_buffer\n");
239 	}
240 
241 	net_buf_unref(buf);
242 }
243 
audio_work_handler(struct k_work * work)244 static void audio_work_handler(struct k_work *work)
245 {
246 	int64_t period_ms;
247 	uint32_t a2dp_src_num_samples;
248 	uint8_t *pcm_data;
249 	uint8_t index;
250 	uint32_t pcm_frame_size;
251 	uint32_t pcm_frame_samples;
252 	uint32_t encoded_frame_size;
253 	struct net_buf *buf;
254 	uint8_t *sbc_hdr;
255 	uint32_t pdu_len;
256 	uint32_t out_size;
257 	int err;
258 	uint8_t frame_num = 0;
259 	uint8_t remaining_frame_num;
260 
261 	/* If stopped then return */
262 	if (!a2dp_src_playback || default_a2dp == NULL) {
263 		return;
264 	}
265 
266 	buf = bt_a2dp_stream_create_pdu(&a2dp_tx_pool, K_FOREVER);
267 	if (buf == NULL) {
268 		/* fail */
269 		printk("no buf\n");
270 		return;
271 	}
272 
273 	period_ms = k_uptime_delta(&ref_time);
274 
275 	pcm_frame_size = sbc_frame_bytes(&encoder);
276 	pcm_frame_samples = sbc_frame_samples(&encoder);
277 	encoded_frame_size = sbc_frame_encoded_bytes(&encoder);
278 
279 	sbc_hdr = net_buf_add(buf, 1u);
280 	/* Get the number of samples */
281 	a2dp_src_num_samples = (uint16_t)((period_ms * a2dp_src_sf) / 1000);
282 	a2dp_src_missed_count += (uint32_t)((period_ms * a2dp_src_sf) % 1000);
283 	a2dp_src_missed_count += ((a2dp_src_num_samples % pcm_frame_samples) * 1000);
284 	a2dp_src_num_samples = (a2dp_src_num_samples / pcm_frame_samples) * pcm_frame_samples;
285 	remaining_frame_num = a2dp_src_num_samples / pcm_frame_samples;
286 
287 	pdu_len = buf->len + remaining_frame_num * encoded_frame_size;
288 
289 	/* Raw adjust for the drift */
290 	while (a2dp_src_missed_count >= (1000 * pcm_frame_samples)) {
291 		pdu_len += encoded_frame_size;
292 		a2dp_src_num_samples += pcm_frame_samples;
293 		remaining_frame_num++;
294 		a2dp_src_missed_count -= (1000 * pcm_frame_samples);
295 	}
296 
297 	do {
298 		frame_num = remaining_frame_num;
299 		/* adjust the buf size */
300 		while ((pdu_len - buf->len > net_buf_tailroom(buf)) ||
301 		       (pdu_len > bt_a2dp_get_mtu(&sbc_stream)) ||
302 		       (!a2dp_produce_media_check(a2dp_src_num_samples))) {
303 			pdu_len -= encoded_frame_size;
304 			a2dp_src_missed_count += 1000 * pcm_frame_samples;
305 			a2dp_src_num_samples -= pcm_frame_samples;
306 			frame_num--;
307 		}
308 
309 		pcm_data = a2dp_produce_media(a2dp_src_num_samples);
310 		if (pcm_data == NULL) {
311 			net_buf_unref(buf);
312 			printk("no media data\n");
313 			return;
314 		}
315 
316 		for (index = 0; index < frame_num; index++) {
317 			out_size = sbc_encode(&encoder,
318 					      (uint8_t *)&pcm_data[index * pcm_frame_size],
319 					      net_buf_tail(buf));
320 			if (encoded_frame_size != out_size) {
321 				printk("sbc encode fail\n");
322 				continue;
323 			}
324 
325 			net_buf_add(buf, encoded_frame_size);
326 		}
327 
328 		*sbc_hdr = (uint8_t)BT_A2DP_SBC_MEDIA_HDR_ENCODE(frame_num, 0, 0, 0);
329 
330 		err = bt_a2dp_stream_send(&sbc_stream, buf, send_count, send_samples_count);
331 		if (err != 0) {
332 			net_buf_unref(buf);
333 			printk("  Failed to send SBC audio data on streams(%d)\n", err);
334 		}
335 
336 		send_count++;
337 		send_samples_count += a2dp_src_num_samples;
338 		remaining_frame_num -= frame_num;
339 	} while (remaining_frame_num > 0);
340 }
341 
342 static K_WORK_DEFINE(audio_work, audio_work_handler);
343 
a2dp_playback_timeout_handler(struct k_timer * timer)344 static void a2dp_playback_timeout_handler(struct k_timer *timer)
345 {
346 	k_work_submit_to_queue(&audio_play_work_q, &audio_work);
347 }
348 
sbc_stream_configured(struct bt_a2dp_stream * stream)349 static void sbc_stream_configured(struct bt_a2dp_stream *stream)
350 {
351 	struct sbc_encoder_init_param param;
352 	struct bt_a2dp_codec_sbc_params *sbc_config = (struct bt_a2dp_codec_sbc_params *)
353 						      &sbc_cfg_default.codec_config->codec_ie[0];
354 
355 	printk("stream configured\n");
356 
357 	a2dp_src_sf = bt_a2dp_sbc_get_sampling_frequency(sbc_config);
358 	a2dp_src_nc = bt_a2dp_sbc_get_channel_num(sbc_config);
359 
360 	param.bit_rate = CONFIG_BT_A2DP_SOURCE_SBC_BIT_RATE_DEFAULT;
361 	param.samp_freq = a2dp_src_sf;
362 	param.blk_len = bt_a2dp_sbc_get_block_length(sbc_config);
363 	param.subband = bt_a2dp_sbc_get_subband_num(sbc_config);
364 	param.alloc_mthd = bt_a2dp_sbc_get_allocation_method(sbc_config);
365 	param.ch_mode = bt_a2dp_sbc_get_channel_mode(sbc_config);
366 	param.ch_num = bt_a2dp_sbc_get_channel_num(sbc_config);
367 	param.min_bitpool = sbc_config->min_bitpool;
368 	param.max_bitpool = sbc_config->max_bitpool;
369 
370 	if (sbc_setup_encoder(&encoder, &param) != 0) {
371 		printk("sbc encoder initialization fail\n");
372 		return;
373 	}
374 
375 	bt_a2dp_stream_establish(stream);
376 }
377 
sbc_stream_established(struct bt_a2dp_stream * stream)378 static void sbc_stream_established(struct bt_a2dp_stream *stream)
379 {
380 	printk("stream established\n");
381 	audio_play_check();
382 	bt_a2dp_stream_start(&sbc_stream);
383 }
384 
sbc_stream_released(struct bt_a2dp_stream * stream)385 static void sbc_stream_released(struct bt_a2dp_stream *stream)
386 {
387 	printk("stream released\n");
388 	k_timer_stop(&a2dp_player_timer);
389 }
390 
sbc_stream_started(struct bt_a2dp_stream * stream)391 static void sbc_stream_started(struct bt_a2dp_stream *stream)
392 {
393 	uint32_t audio_time_interval = CONFIG_BT_A2DP_SOURCE_DATA_SEND_INTERVAL;
394 
395 	printk("stream started\n");
396 	/* Start Audio Source */
397 	a2dp_src_playback = true;
398 
399 	k_uptime_delta(&ref_time);
400 	k_timer_start(&a2dp_player_timer, K_MSEC(audio_time_interval), K_MSEC(audio_time_interval));
401 }
402 
403 static struct bt_a2dp_stream_ops sbc_stream_ops = {
404 	.configured = sbc_stream_configured,
405 	.established = sbc_stream_established,
406 	.released = sbc_stream_released,
407 	.started = sbc_stream_started,
408 };
409 
a2dp_discover_ep_cb(struct bt_a2dp * a2dp,struct bt_a2dp_ep_info * info,struct bt_a2dp_ep ** ep)410 static uint8_t a2dp_discover_ep_cb(struct bt_a2dp *a2dp, struct bt_a2dp_ep_info *info,
411 				   struct bt_a2dp_ep **ep)
412 {
413 	if (peer_sbc_found) {
414 		int err;
415 
416 		bt_a2dp_stream_cb_register(&sbc_stream, &sbc_stream_ops);
417 		err = bt_a2dp_stream_config(a2dp, &sbc_stream,
418 						&sbc_source_ep, &sbc_sink_ep,
419 						&sbc_cfg_default);
420 		if (err != 0) {
421 			printk("fail to configure\n");
422 		}
423 
424 		return BT_A2DP_DISCOVER_EP_STOP;
425 	}
426 
427 	if (info != NULL) {
428 		printk("find one endpoint:");
429 
430 		if (info->codec_type == BT_A2DP_SBC) {
431 			printk("it is SBC codec and use it\n");
432 
433 			if (ep != NULL && !peer_sbc_found) {
434 				peer_sbc_found = true;
435 				*ep = &sbc_sink_ep;
436 			}
437 		} else {
438 			printk("it is not SBC codecs\n");
439 		}
440 	}
441 
442 	return BT_A2DP_DISCOVER_EP_CONTINUE;
443 }
444 
445 static struct bt_avdtp_sep_info found_seps[CONFIG_BT_A2DP_SOURCE_EPS_DISCOVER_COUNT];
446 
447 static struct bt_a2dp_discover_param ep_discover_param = {
448 	.cb = a2dp_discover_ep_cb,
449 	.seps_info = &found_seps[0],
450 	.sep_count = CONFIG_BT_A2DP_SOURCE_EPS_DISCOVER_COUNT,
451 };
452 
app_a2dp_connected(struct bt_a2dp * a2dp,int err)453 static void app_a2dp_connected(struct bt_a2dp *a2dp, int err)
454 {
455 	if (err == 0) {
456 		peer_sbc_found = false;
457 
458 		err = bt_a2dp_discover(a2dp, &ep_discover_param);
459 		if (err != 0) {
460 			printk("fail to discover\n");
461 		}
462 
463 		printk("a2dp connected success\n");
464 	} else {
465 		if (default_a2dp != NULL) {
466 			default_a2dp = NULL;
467 		}
468 
469 		printk("a2dp connected fail\n");
470 	}
471 }
472 
app_a2dp_disconnected(struct bt_a2dp * a2dp)473 static void app_a2dp_disconnected(struct bt_a2dp *a2dp)
474 {
475 	if (default_a2dp != NULL) {
476 		default_a2dp = NULL;
477 	}
478 
479 	a2dp_src_playback = false;
480 	/* stop timer */
481 	k_timer_stop(&a2dp_player_timer);
482 	printk("a2dp disconnected\n");
483 }
484 
sdp_discover_cb(struct bt_conn * conn,struct bt_sdp_client_result * result,const struct bt_sdp_discover_params * params)485 static uint8_t sdp_discover_cb(struct bt_conn *conn, struct bt_sdp_client_result *result,
486 			       const struct bt_sdp_discover_params *params)
487 {
488 	int err;
489 	uint16_t value;
490 
491 	printk("Discover done\n");
492 
493 	if (result != NULL && result->resp_buf != NULL) {
494 		err = bt_sdp_get_proto_param(result->resp_buf, BT_SDP_PROTO_L2CAP, &value);
495 
496 		if (err != 0) {
497 			printk("PSM is not found\n");
498 		} else if (value == BT_UUID_AVDTP_VAL) {
499 			printk("The A2DP server found, connecting a2dp\n");
500 			default_a2dp = bt_a2dp_connect(conn);
501 			if (default_a2dp == NULL) {
502 				printk("Fail to create A2DP connection (err %d)\n", err);
503 			}
504 		}
505 	}
506 
507 	return BT_SDP_DISCOVER_UUID_STOP;
508 }
509 
510 static struct bt_sdp_discover_params sdp_discover = {
511 	.type = BT_SDP_DISCOVER_SERVICE_SEARCH_ATTR,
512 	.func = sdp_discover_cb,
513 	.pool = &sdp_discover_pool,
514 	.uuid = BT_UUID_DECLARE_16(BT_SDP_AUDIO_SINK_SVCLASS),
515 };
516 
connected(struct bt_conn * conn,uint8_t err)517 static void connected(struct bt_conn *conn, uint8_t err)
518 {
519 	int res;
520 
521 	if (err != 0) {
522 		if (default_conn != NULL) {
523 			default_conn = NULL;
524 		}
525 
526 		printk("Connection failed, err 0x%02x %s\n", err, bt_hci_err_to_str(err));
527 	} else {
528 		if (default_conn == conn) {
529 			struct bt_conn_info info;
530 
531 			bt_conn_get_info(conn, &info);
532 			if (info.type != BT_CONN_TYPE_BR) {
533 				return;
534 			}
535 
536 			/*
537 			 * Do an SDP Query on Successful ACL connection complete with the
538 			 * required device
539 			 */
540 			res = bt_sdp_discover(default_conn, &sdp_discover);
541 			if (res != 0) {
542 				printk("SDP discovery failed (err %d)\n", res);
543 			} else {
544 				printk("SDP discovery started\n");
545 			}
546 			printk("Connected\n");
547 		}
548 	}
549 }
550 
disconnected(struct bt_conn * conn,uint8_t reason)551 static void disconnected(struct bt_conn *conn, uint8_t reason)
552 {
553 	printk("Disconnected, reason 0x%02x %s\n", reason, bt_hci_err_to_str(reason));
554 
555 	if (default_conn == conn) {
556 		default_conn = NULL;
557 	}
558 }
559 
security_changed(struct bt_conn * conn,bt_security_t level,enum bt_security_err err)560 static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err)
561 {
562 	char addr[BT_ADDR_LE_STR_LEN];
563 	struct bt_conn_info info;
564 
565 	bt_conn_get_info(conn, &info);
566 
567 	bt_addr_to_str(info.br.dst, addr, sizeof(addr));
568 
569 	printk("Security changed: %s level %u, err %s(%d)\n", addr, level,
570 	       bt_security_err_to_str(err), err);
571 }
572 
573 static struct bt_conn_cb conn_callbacks = {
574 	.connected = connected,
575 	.disconnected = disconnected,
576 	.security_changed = security_changed,
577 };
578 
discovery_timeout_cb(const struct bt_br_discovery_result * results,size_t count)579 static void discovery_timeout_cb(const struct bt_br_discovery_result *results, size_t count)
580 {
581 	char addr[BT_ADDR_LE_STR_LEN];
582 	const uint8_t *eir;
583 	bool cod_a2dp = false;
584 	static uint8_t temp[240];
585 	size_t len = sizeof(results->eir);
586 	uint8_t major_device;
587 	uint8_t minor_device;
588 	size_t i;
589 
590 	for (i = 0; i < count; i++) {
591 		bt_addr_to_str(&results[i].addr, addr, sizeof(addr));
592 		printk("Device[%d]: %s, rssi %d, cod 0x%02x%02x%02x", i, addr, results[i].rssi,
593 		       results[i].cod[0], results[i].cod[1], results[i].cod[2]);
594 
595 		major_device = (uint8_t)BT_COD_MAJOR_DEVICE_CLASS(results[i].cod);
596 		minor_device = (uint8_t)BT_COD_MINOR_DEVICE_CLASS(results[i].cod);
597 
598 		if ((major_device & BT_COD_MAJOR_AUDIO_VIDEO) != 0 &&
599 		    (minor_device & BT_COD_MAJOR_AUDIO_VIDEO_MINOR_WEARABLE_HEADSET) != 0) {
600 			cod_a2dp = true;
601 		}
602 
603 		eir = results[i].eir;
604 
605 		while ((eir[0] > 2) && (len > eir[0])) {
606 			switch (eir[1]) {
607 			case BT_DATA_NAME_SHORTENED:
608 			case BT_DATA_NAME_COMPLETE:
609 				memcpy(temp, &eir[2], eir[0] - 1);
610 				temp[eir[0] - 1] = '\0'; /* Set end flag */
611 				printk(", name %s", temp);
612 				break;
613 			default:
614 				/* Skip the EIR */
615 				break;
616 			}
617 			len = len - eir[0] - 1;
618 			eir = eir + eir[0] + 1;
619 		}
620 		printk("\n");
621 
622 		if (cod_a2dp) {
623 			break;
624 		}
625 	}
626 
627 	if (!cod_a2dp) {
628 		(void)k_work_submit(&discover_work);
629 	} else {
630 		(void)k_work_cancel(&discover_work);
631 		default_conn = bt_conn_create_br(&results[i].addr, BT_BR_CONN_PARAM_DEFAULT);
632 
633 		if (default_conn == NULL) {
634 			printk("Fail to create the connection\n");
635 		} else {
636 			bt_conn_unref(default_conn);
637 		}
638 	}
639 }
640 
discover_work_handler(struct k_work * work)641 static void discover_work_handler(struct k_work *work)
642 {
643 	int err;
644 
645 	br_discover.length = 10;
646 	br_discover.limited = false;
647 
648 	err = bt_br_discovery_start(&br_discover, scan_result,
649 				    CONFIG_BT_A2DP_SOURCE_DISCOVER_RESULT_COUNT);
650 	if (err != 0) {
651 		printk("Fail to start discovery (err %d)\n", err);
652 		return;
653 	}
654 }
655 
656 static struct bt_br_discovery_cb discovery_cb = {
657 	.timeout = discovery_timeout_cb,
658 };
659 
660 static struct bt_a2dp_cb a2dp_cb = {
661 	.connected = app_a2dp_connected,
662 	.disconnected = app_a2dp_disconnected,
663 };
664 
bt_ready(int err)665 static void bt_ready(int err)
666 {
667 	if (err != 0) {
668 		printk("Bluetooth init failed (err %d)\n", err);
669 		return;
670 	}
671 
672 	if (IS_ENABLED(CONFIG_SETTINGS)) {
673 		settings_load();
674 	}
675 
676 	printk("Bluetooth initialized\n");
677 
678 	bt_conn_cb_register(&conn_callbacks);
679 
680 	bt_br_discovery_cb_register(&discovery_cb);
681 
682 	bt_sdp_register_service(&a2dp_source_rec);
683 
684 	bt_a2dp_register_ep(&sbc_source_ep, BT_AVDTP_AUDIO, BT_AVDTP_SOURCE);
685 
686 	bt_a2dp_register_cb(&a2dp_cb);
687 
688 	k_work_queue_init(&audio_play_work_q);
689 	k_work_queue_start(&audio_play_work_q, audio_play_work_q_thread_stack,
690 			   CONFIG_BT_A2DP_SOURCE_DATA_SEND_WORKQ_STACK_SIZE,
691 			   K_PRIO_COOP(CONFIG_BT_A2DP_SOURCE_DATA_SEND_WORKQ_PRIORITY), NULL);
692 	k_thread_name_set(&audio_play_work_q.thread, "audio play");
693 
694 	k_work_init(&discover_work, discover_work_handler);
695 
696 	(void)k_work_submit(&discover_work);
697 }
698 
main(void)699 int main(void)
700 {
701 	int err;
702 
703 	printk("Bluetooth A2DP Source demo start...\n");
704 
705 	err = bt_enable(bt_ready);
706 	if (err != 0) {
707 		printk("Bluetooth init failed (err %d)\n", err);
708 	}
709 	return 0;
710 }
711