diff --git a/samples/bluetooth/a2dp_source/CMakeLists.txt b/samples/bluetooth/a2dp_source/CMakeLists.txt new file mode 100644 index 0000000000000..03194aa85726d --- /dev/null +++ b/samples/bluetooth/a2dp_source/CMakeLists.txt @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.13.1) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(a2dp_source) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) + +zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/a2dp_source/README.rst b/samples/bluetooth/a2dp_source/README.rst new file mode 100644 index 0000000000000..7a6b8ed7f8155 --- /dev/null +++ b/samples/bluetooth/a2dp_source/README.rst @@ -0,0 +1,40 @@ +.. _bt_a2dp_source: + +Bluetooth: A2DP +#################### + +Overview +******** + +Application demonstrating usage of the A2dp Profile APIs. + +This sample can be found under :zephyr_file:`samples/bluetooth/a2dp_source` in +the Zephyr tree. + +Check :ref:`bluetooth samples section ` for details. + +Requirements +************ + +* BlueZ running on the host, or +* A board with Bluetooth BR/EDR (Classic) support + +Building and Running +******************** + +When building targeting mimxrt1060_evk board with the murata 1xk Controller. + +Building for an mimxrt1060_evk + murata 1xk +------------------------------------------- + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/a2dp_source/ + :board: mimxrt1060_evk + :goals: build + +Building for the sample +----------------------- + +1. input `bt discover` to discover BT devices. +2. input `bt connect ` to connect the found BT device, the is the result of step 1. +3. `bt disconnect` can be used to disconnect connection. diff --git a/samples/bluetooth/a2dp_source/boards/mimxrt1060_evk.overlay b/samples/bluetooth/a2dp_source/boards/mimxrt1060_evk.overlay new file mode 100644 index 0000000000000..f48eea9172ce5 --- /dev/null +++ b/samples/bluetooth/a2dp_source/boards/mimxrt1060_evk.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + zephyr,bt-uart = &lpuart3; + }; +}; + +&lpuart3 { + status = "okay"; + current-speed = <3000000>; + hw-flow-control; +}; diff --git a/samples/bluetooth/a2dp_source/prj.conf b/samples/bluetooth/a2dp_source/prj.conf new file mode 100644 index 0000000000000..639c3b2a03bff --- /dev/null +++ b/samples/bluetooth/a2dp_source/prj.conf @@ -0,0 +1,15 @@ +CONFIG_BT=y +CONFIG_BT_L2CAP_TX_MTU=1000 +CONFIG_BT_BREDR=y +CONFIG_BT_AVDTP=y +CONFIG_BT_A2DP=y +CONFIG_BT_A2DP_SOURCE=y +CONFIG_LIBSBC_ENCODER=y +CONFIG_BT_DEVICE_NAME="a2dp-source-sample" +CONFIG_HEAP_MEM_POOL_SIZE=4096 +CONFIG_SHELL=y +CONFIG_SHELL_HELP=y +CONFIG_SHELL_MINIMAL=y +CONFIG_SHELL_BACKEND_SERIAL=y +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_EVT_RX_COUNT=12 diff --git a/samples/bluetooth/a2dp_source/sample.yaml b/samples/bluetooth/a2dp_source/sample.yaml new file mode 100644 index 0000000000000..fe623bf3c5873 --- /dev/null +++ b/samples/bluetooth/a2dp_source/sample.yaml @@ -0,0 +1,7 @@ +sample: + name: Bluetooth A2dp Source +tests: + sample.bluetooth.a2dp_source: + harness: bluetooth + platform_allow: mimxrt1060_evk + tags: bluetooth diff --git a/samples/bluetooth/a2dp_source/src/a2dp_media_48KHz_1ksin.h b/samples/bluetooth/a2dp_source/src/a2dp_media_48KHz_1ksin.h new file mode 100644 index 0000000000000..11f4951448f48 --- /dev/null +++ b/samples/bluetooth/a2dp_source/src/a2dp_media_48KHz_1ksin.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2021 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ +static const uint8_t beethoven[] = { +0x0, 0x0, 0x0, 0x0, 0xb5, 0x10, 0xb5, 0x10, 0x21, 0x21, 0x21, 0x21, 0xfb, 0x30, 0xfb, 0x30, +0xff, 0x3f, 0xff, 0x3f, 0xeb, 0x4d, 0xeb, 0x4d, 0x82, 0x5a, 0x82, 0x5a, 0x8c, 0x65, 0x8c, 0x65, +0xd9, 0x6e, 0xd9, 0x6e, 0x41, 0x76, 0x41, 0x76, 0xa2, 0x7b, 0xa2, 0x7b, 0xe7, 0x7e, 0xe7, 0x7e, +0xff, 0x7f, 0xff, 0x7f, 0xe7, 0x7e, 0xe7, 0x7e, 0xa2, 0x7b, 0xa2, 0x7b, 0x41, 0x76, 0x41, 0x76, +0xd9, 0x6e, 0xd9, 0x6e, 0x8c, 0x65, 0x8c, 0x65, 0x82, 0x5a, 0x82, 0x5a, 0xeb, 0x4d, 0xeb, 0x4d, +0xff, 0x3f, 0xff, 0x3f, 0xfb, 0x30, 0xfb, 0x30, 0x21, 0x21, 0x21, 0x21, 0xb5, 0x10, 0xb5, 0x10, +0x0, 0x0, 0x0, 0x0, 0x4b, 0xef, 0x4b, 0xef, 0xdf, 0xde, 0xdf, 0xde, 0x5, 0xcf, 0x5, 0xcf, +0x0, 0xc0, 0x0, 0xc0, 0x15, 0xb2, 0x15, 0xb2, 0x7e, 0xa5, 0x7e, 0xa5, 0x74, 0x9a, 0x74, 0x9a, +0x27, 0x91, 0x27, 0x91, 0xbf, 0x89, 0xbf, 0x89, 0x5e, 0x84, 0x5e, 0x84, 0x19, 0x81, 0x19, 0x81, +0x1, 0x80, 0x1, 0x80, 0x19, 0x81, 0x19, 0x81, 0x5e, 0x84, 0x5e, 0x84, 0xbf, 0x89, 0xbf, 0x89, +0x27, 0x91, 0x27, 0x91, 0x74, 0x9a, 0x74, 0x9a, 0x7e, 0xa5, 0x7e, 0xa5, 0x15, 0xb2, 0x15, 0xb2, +0x0, 0xc0, 0x0, 0xc0, 0x5, 0xcf, 0x5, 0xcf, 0xdf, 0xde, 0xdf, 0xde, 0x4b, 0xef, 0x4b, 0xef, + +0x0, 0x0, 0x0, 0x0, 0xb5, 0x10, 0xb5, 0x10, 0x21, 0x21, 0x21, 0x21, 0xfb, 0x30, 0xfb, 0x30, +0xff, 0x3f, 0xff, 0x3f, 0xeb, 0x4d, 0xeb, 0x4d, 0x82, 0x5a, 0x82, 0x5a, 0x8c, 0x65, 0x8c, 0x65, +0xd9, 0x6e, 0xd9, 0x6e, 0x41, 0x76, 0x41, 0x76, 0xa2, 0x7b, 0xa2, 0x7b, 0xe7, 0x7e, 0xe7, 0x7e, +0xff, 0x7f, 0xff, 0x7f, 0xe7, 0x7e, 0xe7, 0x7e, 0xa2, 0x7b, 0xa2, 0x7b, 0x41, 0x76, 0x41, 0x76, +0xd9, 0x6e, 0xd9, 0x6e, 0x8c, 0x65, 0x8c, 0x65, 0x82, 0x5a, 0x82, 0x5a, 0xeb, 0x4d, 0xeb, 0x4d, +0xff, 0x3f, 0xff, 0x3f, 0xfb, 0x30, 0xfb, 0x30, 0x21, 0x21, 0x21, 0x21, 0xb5, 0x10, 0xb5, 0x10, +0x0, 0x0, 0x0, 0x0, 0x4b, 0xef, 0x4b, 0xef, 0xdf, 0xde, 0xdf, 0xde, 0x5, 0xcf, 0x5, 0xcf, +0x0, 0xc0, 0x0, 0xc0, 0x15, 0xb2, 0x15, 0xb2, 0x7e, 0xa5, 0x7e, 0xa5, 0x74, 0x9a, 0x74, 0x9a, +0x27, 0x91, 0x27, 0x91, 0xbf, 0x89, 0xbf, 0x89, 0x5e, 0x84, 0x5e, 0x84, 0x19, 0x81, 0x19, 0x81, +0x1, 0x80, 0x1, 0x80, 0x19, 0x81, 0x19, 0x81, 0x5e, 0x84, 0x5e, 0x84, 0xbf, 0x89, 0xbf, 0x89, +0x27, 0x91, 0x27, 0x91, 0x74, 0x9a, 0x74, 0x9a, 0x7e, 0xa5, 0x7e, 0xa5, 0x15, 0xb2, 0x15, 0xb2, +0x0, 0xc0, 0x0, 0xc0, 0x5, 0xcf, 0x5, 0xcf, 0xdf, 0xde, 0xdf, 0xde, 0x4b, 0xef, 0x4b, 0xef, + +0x0, 0x0, 0x0, 0x0, 0xb5, 0x10, 0xb5, 0x10, 0x21, 0x21, 0x21, 0x21, 0xfb, 0x30, 0xfb, 0x30, +0xff, 0x3f, 0xff, 0x3f, 0xeb, 0x4d, 0xeb, 0x4d, 0x82, 0x5a, 0x82, 0x5a, 0x8c, 0x65, 0x8c, 0x65, +0xd9, 0x6e, 0xd9, 0x6e, 0x41, 0x76, 0x41, 0x76, 0xa2, 0x7b, 0xa2, 0x7b, 0xe7, 0x7e, 0xe7, 0x7e, +0xff, 0x7f, 0xff, 0x7f, 0xe7, 0x7e, 0xe7, 0x7e, 0xa2, 0x7b, 0xa2, 0x7b, 0x41, 0x76, 0x41, 0x76, +0xd9, 0x6e, 0xd9, 0x6e, 0x8c, 0x65, 0x8c, 0x65, 0x82, 0x5a, 0x82, 0x5a, 0xeb, 0x4d, 0xeb, 0x4d, +0xff, 0x3f, 0xff, 0x3f, 0xfb, 0x30, 0xfb, 0x30, 0x21, 0x21, 0x21, 0x21, 0xb5, 0x10, 0xb5, 0x10, +0x0, 0x0, 0x0, 0x0, 0x4b, 0xef, 0x4b, 0xef, 0xdf, 0xde, 0xdf, 0xde, 0x5, 0xcf, 0x5, 0xcf, +0x0, 0xc0, 0x0, 0xc0, 0x15, 0xb2, 0x15, 0xb2, 0x7e, 0xa5, 0x7e, 0xa5, 0x74, 0x9a, 0x74, 0x9a, +0x27, 0x91, 0x27, 0x91, 0xbf, 0x89, 0xbf, 0x89, 0x5e, 0x84, 0x5e, 0x84, 0x19, 0x81, 0x19, 0x81, +0x1, 0x80, 0x1, 0x80, 0x19, 0x81, 0x19, 0x81, 0x5e, 0x84, 0x5e, 0x84, 0xbf, 0x89, 0xbf, 0x89, +0x27, 0x91, 0x27, 0x91, 0x74, 0x9a, 0x74, 0x9a, 0x7e, 0xa5, 0x7e, 0xa5, 0x15, 0xb2, 0x15, 0xb2, +0x0, 0xc0, 0x0, 0xc0, 0x5, 0xcf, 0x5, 0xcf, 0xdf, 0xde, 0xdf, 0xde, 0x4b, 0xef, 0x4b, 0xef, + +0x0, 0x0, 0x0, 0x0, 0xb5, 0x10, 0xb5, 0x10, 0x21, 0x21, 0x21, 0x21, 0xfb, 0x30, 0xfb, 0x30, +0xff, 0x3f, 0xff, 0x3f, 0xeb, 0x4d, 0xeb, 0x4d, 0x82, 0x5a, 0x82, 0x5a, 0x8c, 0x65, 0x8c, 0x65, +0xd9, 0x6e, 0xd9, 0x6e, 0x41, 0x76, 0x41, 0x76, 0xa2, 0x7b, 0xa2, 0x7b, 0xe7, 0x7e, 0xe7, 0x7e, +0xff, 0x7f, 0xff, 0x7f, 0xe7, 0x7e, 0xe7, 0x7e, 0xa2, 0x7b, 0xa2, 0x7b, 0x41, 0x76, 0x41, 0x76, +0xd9, 0x6e, 0xd9, 0x6e, 0x8c, 0x65, 0x8c, 0x65, 0x82, 0x5a, 0x82, 0x5a, 0xeb, 0x4d, 0xeb, 0x4d, +0xff, 0x3f, 0xff, 0x3f, 0xfb, 0x30, 0xfb, 0x30, 0x21, 0x21, 0x21, 0x21, 0xb5, 0x10, 0xb5, 0x10, +0x0, 0x0, 0x0, 0x0, 0x4b, 0xef, 0x4b, 0xef, 0xdf, 0xde, 0xdf, 0xde, 0x5, 0xcf, 0x5, 0xcf, +0x0, 0xc0, 0x0, 0xc0, 0x15, 0xb2, 0x15, 0xb2, 0x7e, 0xa5, 0x7e, 0xa5, 0x74, 0x9a, 0x74, 0x9a, +0x27, 0x91, 0x27, 0x91, 0xbf, 0x89, 0xbf, 0x89, 0x5e, 0x84, 0x5e, 0x84, 0x19, 0x81, 0x19, 0x81, +0x1, 0x80, 0x1, 0x80, 0x19, 0x81, 0x19, 0x81, 0x5e, 0x84, 0x5e, 0x84, 0xbf, 0x89, 0xbf, 0x89, +0x27, 0x91, 0x27, 0x91, 0x74, 0x9a, 0x74, 0x9a, 0x7e, 0xa5, 0x7e, 0xa5, 0x15, 0xb2, 0x15, 0xb2, +0x0, 0xc0, 0x0, 0xc0, 0x5, 0xcf, 0x5, 0xcf, 0xdf, 0xde, 0xdf, 0xde, 0x4b, 0xef, 0x4b, 0xef, + +0x0, 0x0, 0x0, 0x0, 0xb5, 0x10, 0xb5, 0x10, 0x21, 0x21, 0x21, 0x21, 0xfb, 0x30, 0xfb, 0x30, +0xff, 0x3f, 0xff, 0x3f, 0xeb, 0x4d, 0xeb, 0x4d, 0x82, 0x5a, 0x82, 0x5a, 0x8c, 0x65, 0x8c, 0x65, +0xd9, 0x6e, 0xd9, 0x6e, 0x41, 0x76, 0x41, 0x76, 0xa2, 0x7b, 0xa2, 0x7b, 0xe7, 0x7e, 0xe7, 0x7e, +0xff, 0x7f, 0xff, 0x7f, 0xe7, 0x7e, 0xe7, 0x7e, 0xa2, 0x7b, 0xa2, 0x7b, 0x41, 0x76, 0x41, 0x76, +0xd9, 0x6e, 0xd9, 0x6e, 0x8c, 0x65, 0x8c, 0x65, 0x82, 0x5a, 0x82, 0x5a, 0xeb, 0x4d, 0xeb, 0x4d, +0xff, 0x3f, 0xff, 0x3f, 0xfb, 0x30, 0xfb, 0x30, 0x21, 0x21, 0x21, 0x21, 0xb5, 0x10, 0xb5, 0x10, +0x0, 0x0, 0x0, 0x0, 0x4b, 0xef, 0x4b, 0xef, 0xdf, 0xde, 0xdf, 0xde, 0x5, 0xcf, 0x5, 0xcf, +0x0, 0xc0, 0x0, 0xc0, 0x15, 0xb2, 0x15, 0xb2, 0x7e, 0xa5, 0x7e, 0xa5, 0x74, 0x9a, 0x74, 0x9a, +0x27, 0x91, 0x27, 0x91, 0xbf, 0x89, 0xbf, 0x89, 0x5e, 0x84, 0x5e, 0x84, 0x19, 0x81, 0x19, 0x81, +0x1, 0x80, 0x1, 0x80, 0x19, 0x81, 0x19, 0x81, 0x5e, 0x84, 0x5e, 0x84, 0xbf, 0x89, 0xbf, 0x89, +0x27, 0x91, 0x27, 0x91, 0x74, 0x9a, 0x74, 0x9a, 0x7e, 0xa5, 0x7e, 0xa5, 0x15, 0xb2, 0x15, 0xb2, +0x0, 0xc0, 0x0, 0xc0, 0x5, 0xcf, 0x5, 0xcf, 0xdf, 0xde, 0xdf, 0xde, 0x4b, 0xef, 0x4b, 0xef, + +0x0, 0x0, 0x0, 0x0, 0xb5, 0x10, 0xb5, 0x10, 0x21, 0x21, 0x21, 0x21, 0xfb, 0x30, 0xfb, 0x30, +0xff, 0x3f, 0xff, 0x3f, 0xeb, 0x4d, 0xeb, 0x4d, 0x82, 0x5a, 0x82, 0x5a, 0x8c, 0x65, 0x8c, 0x65, +0xd9, 0x6e, 0xd9, 0x6e, 0x41, 0x76, 0x41, 0x76, 0xa2, 0x7b, 0xa2, 0x7b, 0xe7, 0x7e, 0xe7, 0x7e, +0xff, 0x7f, 0xff, 0x7f, 0xe7, 0x7e, 0xe7, 0x7e, 0xa2, 0x7b, 0xa2, 0x7b, 0x41, 0x76, 0x41, 0x76, +0xd9, 0x6e, 0xd9, 0x6e, 0x8c, 0x65, 0x8c, 0x65, 0x82, 0x5a, 0x82, 0x5a, 0xeb, 0x4d, 0xeb, 0x4d, +0xff, 0x3f, 0xff, 0x3f, 0xfb, 0x30, 0xfb, 0x30, 0x21, 0x21, 0x21, 0x21, 0xb5, 0x10, 0xb5, 0x10, +0x0, 0x0, 0x0, 0x0, 0x4b, 0xef, 0x4b, 0xef, 0xdf, 0xde, 0xdf, 0xde, 0x5, 0xcf, 0x5, 0xcf, +0x0, 0xc0, 0x0, 0xc0, 0x15, 0xb2, 0x15, 0xb2, 0x7e, 0xa5, 0x7e, 0xa5, 0x74, 0x9a, 0x74, 0x9a, +0x27, 0x91, 0x27, 0x91, 0xbf, 0x89, 0xbf, 0x89, 0x5e, 0x84, 0x5e, 0x84, 0x19, 0x81, 0x19, 0x81, +0x1, 0x80, 0x1, 0x80, 0x19, 0x81, 0x19, 0x81, 0x5e, 0x84, 0x5e, 0x84, 0xbf, 0x89, 0xbf, 0x89, +0x27, 0x91, 0x27, 0x91, 0x74, 0x9a, 0x74, 0x9a, 0x7e, 0xa5, 0x7e, 0xa5, 0x15, 0xb2, 0x15, 0xb2, +0x0, 0xc0, 0x0, 0xc0, 0x5, 0xcf, 0x5, 0xcf, 0xdf, 0xde, 0xdf, 0xde, 0x4b, 0xef, 0x4b, 0xef, + +0x0, 0x0, 0x0, 0x0, 0xb5, 0x10, 0xb5, 0x10, 0x21, 0x21, 0x21, 0x21, 0xfb, 0x30, 0xfb, 0x30, +0xff, 0x3f, 0xff, 0x3f, 0xeb, 0x4d, 0xeb, 0x4d, 0x82, 0x5a, 0x82, 0x5a, 0x8c, 0x65, 0x8c, 0x65, +0xd9, 0x6e, 0xd9, 0x6e, 0x41, 0x76, 0x41, 0x76, 0xa2, 0x7b, 0xa2, 0x7b, 0xe7, 0x7e, 0xe7, 0x7e, +0xff, 0x7f, 0xff, 0x7f, 0xe7, 0x7e, 0xe7, 0x7e, 0xa2, 0x7b, 0xa2, 0x7b, 0x41, 0x76, 0x41, 0x76, +0xd9, 0x6e, 0xd9, 0x6e, 0x8c, 0x65, 0x8c, 0x65, 0x82, 0x5a, 0x82, 0x5a, 0xeb, 0x4d, 0xeb, 0x4d, +0xff, 0x3f, 0xff, 0x3f, 0xfb, 0x30, 0xfb, 0x30, 0x21, 0x21, 0x21, 0x21, 0xb5, 0x10, 0xb5, 0x10, +0x0, 0x0, 0x0, 0x0, 0x4b, 0xef, 0x4b, 0xef, 0xdf, 0xde, 0xdf, 0xde, 0x5, 0xcf, 0x5, 0xcf, +0x0, 0xc0, 0x0, 0xc0, 0x15, 0xb2, 0x15, 0xb2, 0x7e, 0xa5, 0x7e, 0xa5, 0x74, 0x9a, 0x74, 0x9a, +0x27, 0x91, 0x27, 0x91, 0xbf, 0x89, 0xbf, 0x89, 0x5e, 0x84, 0x5e, 0x84, 0x19, 0x81, 0x19, 0x81, +0x1, 0x80, 0x1, 0x80, 0x19, 0x81, 0x19, 0x81, 0x5e, 0x84, 0x5e, 0x84, 0xbf, 0x89, 0xbf, 0x89, +0x27, 0x91, 0x27, 0x91, 0x74, 0x9a, 0x74, 0x9a, 0x7e, 0xa5, 0x7e, 0xa5, 0x15, 0xb2, 0x15, 0xb2, +0x0, 0xc0, 0x0, 0xc0, 0x5, 0xcf, 0x5, 0xcf, 0xdf, 0xde, 0xdf, 0xde, 0x4b, 0xef, 0x4b, 0xef, + +0x0, 0x0, 0x0, 0x0, 0xb5, 0x10, 0xb5, 0x10, 0x21, 0x21, 0x21, 0x21, 0xfb, 0x30, 0xfb, 0x30, +0xff, 0x3f, 0xff, 0x3f, 0xeb, 0x4d, 0xeb, 0x4d, 0x82, 0x5a, 0x82, 0x5a, 0x8c, 0x65, 0x8c, 0x65, +0xd9, 0x6e, 0xd9, 0x6e, 0x41, 0x76, 0x41, 0x76, 0xa2, 0x7b, 0xa2, 0x7b, 0xe7, 0x7e, 0xe7, 0x7e, +0xff, 0x7f, 0xff, 0x7f, 0xe7, 0x7e, 0xe7, 0x7e, 0xa2, 0x7b, 0xa2, 0x7b, 0x41, 0x76, 0x41, 0x76, +0xd9, 0x6e, 0xd9, 0x6e, 0x8c, 0x65, 0x8c, 0x65, 0x82, 0x5a, 0x82, 0x5a, 0xeb, 0x4d, 0xeb, 0x4d, +0xff, 0x3f, 0xff, 0x3f, 0xfb, 0x30, 0xfb, 0x30, 0x21, 0x21, 0x21, 0x21, 0xb5, 0x10, 0xb5, 0x10, +0x0, 0x0, 0x0, 0x0, 0x4b, 0xef, 0x4b, 0xef, 0xdf, 0xde, 0xdf, 0xde, 0x5, 0xcf, 0x5, 0xcf, +0x0, 0xc0, 0x0, 0xc0, 0x15, 0xb2, 0x15, 0xb2, 0x7e, 0xa5, 0x7e, 0xa5, 0x74, 0x9a, 0x74, 0x9a, +0x27, 0x91, 0x27, 0x91, 0xbf, 0x89, 0xbf, 0x89, 0x5e, 0x84, 0x5e, 0x84, 0x19, 0x81, 0x19, 0x81, +0x1, 0x80, 0x1, 0x80, 0x19, 0x81, 0x19, 0x81, 0x5e, 0x84, 0x5e, 0x84, 0xbf, 0x89, 0xbf, 0x89, +0x27, 0x91, 0x27, 0x91, 0x74, 0x9a, 0x74, 0x9a, 0x7e, 0xa5, 0x7e, 0xa5, 0x15, 0xb2, 0x15, 0xb2, +0x0, 0xc0, 0x0, 0xc0, 0x5, 0xcf, 0x5, 0xcf, 0xdf, 0xde, 0xdf, 0xde, 0x4b, 0xef, 0x4b, 0xef, + +0x0, 0x0, 0x0, 0x0, 0xb5, 0x10, 0xb5, 0x10, 0x21, 0x21, 0x21, 0x21, 0xfb, 0x30, 0xfb, 0x30, +0xff, 0x3f, 0xff, 0x3f, 0xeb, 0x4d, 0xeb, 0x4d, 0x82, 0x5a, 0x82, 0x5a, 0x8c, 0x65, 0x8c, 0x65, +0xd9, 0x6e, 0xd9, 0x6e, 0x41, 0x76, 0x41, 0x76, 0xa2, 0x7b, 0xa2, 0x7b, 0xe7, 0x7e, 0xe7, 0x7e, +0xff, 0x7f, 0xff, 0x7f, 0xe7, 0x7e, 0xe7, 0x7e, 0xa2, 0x7b, 0xa2, 0x7b, 0x41, 0x76, 0x41, 0x76, +0xd9, 0x6e, 0xd9, 0x6e, 0x8c, 0x65, 0x8c, 0x65, 0x82, 0x5a, 0x82, 0x5a, 0xeb, 0x4d, 0xeb, 0x4d, +0xff, 0x3f, 0xff, 0x3f, 0xfb, 0x30, 0xfb, 0x30, 0x21, 0x21, 0x21, 0x21, 0xb5, 0x10, 0xb5, 0x10, +0x0, 0x0, 0x0, 0x0, 0x4b, 0xef, 0x4b, 0xef, 0xdf, 0xde, 0xdf, 0xde, 0x5, 0xcf, 0x5, 0xcf, +0x0, 0xc0, 0x0, 0xc0, 0x15, 0xb2, 0x15, 0xb2, 0x7e, 0xa5, 0x7e, 0xa5, 0x74, 0x9a, 0x74, 0x9a, +0x27, 0x91, 0x27, 0x91, 0xbf, 0x89, 0xbf, 0x89, 0x5e, 0x84, 0x5e, 0x84, 0x19, 0x81, 0x19, 0x81, +0x1, 0x80, 0x1, 0x80, 0x19, 0x81, 0x19, 0x81, 0x5e, 0x84, 0x5e, 0x84, 0xbf, 0x89, 0xbf, 0x89, +0x27, 0x91, 0x27, 0x91, 0x74, 0x9a, 0x74, 0x9a, 0x7e, 0xa5, 0x7e, 0xa5, 0x15, 0xb2, 0x15, 0xb2, +0x0, 0xc0, 0x0, 0xc0, 0x5, 0xcf, 0x5, 0xcf, 0xdf, 0xde, 0xdf, 0xde, 0x4b, 0xef, 0x4b, 0xef, + +0x0, 0x0, 0x0, 0x0, 0xb5, 0x10, 0xb5, 0x10, 0x21, 0x21, 0x21, 0x21, 0xfb, 0x30, 0xfb, 0x30, +0xff, 0x3f, 0xff, 0x3f, 0xeb, 0x4d, 0xeb, 0x4d, 0x82, 0x5a, 0x82, 0x5a, 0x8c, 0x65, 0x8c, 0x65, +0xd9, 0x6e, 0xd9, 0x6e, 0x41, 0x76, 0x41, 0x76, 0xa2, 0x7b, 0xa2, 0x7b, 0xe7, 0x7e, 0xe7, 0x7e, +0xff, 0x7f, 0xff, 0x7f, 0xe7, 0x7e, 0xe7, 0x7e, 0xa2, 0x7b, 0xa2, 0x7b, 0x41, 0x76, 0x41, 0x76, +0xd9, 0x6e, 0xd9, 0x6e, 0x8c, 0x65, 0x8c, 0x65, 0x82, 0x5a, 0x82, 0x5a, 0xeb, 0x4d, 0xeb, 0x4d, +0xff, 0x3f, 0xff, 0x3f, 0xfb, 0x30, 0xfb, 0x30, 0x21, 0x21, 0x21, 0x21, 0xb5, 0x10, 0xb5, 0x10, +0x0, 0x0, 0x0, 0x0, 0x4b, 0xef, 0x4b, 0xef, 0xdf, 0xde, 0xdf, 0xde, 0x5, 0xcf, 0x5, 0xcf, +0x0, 0xc0, 0x0, 0xc0, 0x15, 0xb2, 0x15, 0xb2, 0x7e, 0xa5, 0x7e, 0xa5, 0x74, 0x9a, 0x74, 0x9a, +0x27, 0x91, 0x27, 0x91, 0xbf, 0x89, 0xbf, 0x89, 0x5e, 0x84, 0x5e, 0x84, 0x19, 0x81, 0x19, 0x81, +0x1, 0x80, 0x1, 0x80, 0x19, 0x81, 0x19, 0x81, 0x5e, 0x84, 0x5e, 0x84, 0xbf, 0x89, 0xbf, 0x89, +0x27, 0x91, 0x27, 0x91, 0x74, 0x9a, 0x74, 0x9a, 0x7e, 0xa5, 0x7e, 0xa5, 0x15, 0xb2, 0x15, 0xb2, +0x0, 0xc0, 0x0, 0xc0, 0x5, 0xcf, 0x5, 0xcf, 0xdf, 0xde, 0xdf, 0xde, 0x4b, 0xef, 0x4b, 0xef, +}; diff --git a/samples/bluetooth/a2dp_source/src/app_connect.c b/samples/bluetooth/a2dp_source/src/app_connect.c new file mode 100644 index 0000000000000..7c30d6c0b5c74 --- /dev/null +++ b/samples/bluetooth/a2dp_source/src/app_connect.c @@ -0,0 +1,132 @@ +/* + * Copyright 2020 - 2021 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "app_connect.h" + +extern void app_sdp_discover_a2dp_sink(void); +static void connected(struct bt_conn *conn, uint8_t err); +static void disconnected(struct bt_conn *conn, uint8_t reason); +static void security_changed(struct bt_conn *conn, bt_security_t level, + enum bt_security_err err); + +struct bt_conn *default_conn; +bt_addr_t default_peer_addr; +static uint8_t default_connect_initialized; + +static struct bt_conn_cb conn_callbacks = { + .connected = connected, + .disconnected = disconnected, + .security_changed = security_changed, +}; +extern struct bt_a2dp *default_a2dp; +static void connected(struct bt_conn *conn, uint8_t err) +{ + if (err) { + if (default_conn != NULL) { + bt_conn_unref(default_conn); + default_conn = NULL; + } + printk("Connection failed (err 0x%02x)\n", err); + } else { + if (1U == default_connect_initialized) { + struct bt_conn_info info; + + default_connect_initialized = 0U; + bt_conn_get_info(conn, &info); + if (info.type == BT_CONN_TYPE_LE) { + return; + } + + default_conn = bt_conn_ref(conn); + /* + * Do an SDP Query on Successful ACL connection complete with the + * required device + */ + if (0 == memcmp(info.br.dst, &default_peer_addr, 6U)) { + app_sdp_discover_a2dp_sink(); + } + printk("Connected\n"); + } + } +} + +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + printk("Disconnected (reason 0x%02x)\n", reason); + + if (default_conn != conn) { + return; + } + + if (default_conn) { + bt_conn_unref(default_conn); + default_conn = NULL; + } else { + return; + } +} + +static void security_changed(struct bt_conn *conn, bt_security_t level, + enum bt_security_err err) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + if (!err) { + printk("Security changed: %s level %u\n", addr, level); + } else { + if (err == BT_SECURITY_ERR_PIN_OR_KEY_MISSING) { + printk("\n"); + + printk("___________________________________________________________\n"); + printk("The peer device seems to have lost the bonding information.\n"); + printk("Kindly delete the bonding information of the peer from the\n"); + printk("and try again.\n\n"); + + printk("\n"); + } + printk("Security failed: %s level %u err %d\n", addr, level, err); + } +} + +void app_connect(uint8_t *addr) +{ + default_connect_initialized = 1U; + memcpy(&default_peer_addr, addr, 6U); + default_conn = bt_conn_create_br(&default_peer_addr, BT_BR_CONN_PARAM_DEFAULT); + if (!default_conn) { + default_connect_initialized = 0U; + printk("Connection failed\r\n"); + } else { + /* unref connection obj in advance as app user */ + bt_conn_unref(default_conn); + printk("Connection pending\r\n"); + } +} + +void app_disconnect(void) +{ + if (bt_conn_disconnect(default_conn, 0x13U)) { + printk("Disconnection failed\r\n"); + } +} + +void app_connect_init(void) +{ + bt_conn_cb_register(&conn_callbacks); +} diff --git a/samples/bluetooth/a2dp_source/src/app_connect.h b/samples/bluetooth/a2dp_source/src/app_connect.h new file mode 100644 index 0000000000000..47f19d30390a3 --- /dev/null +++ b/samples/bluetooth/a2dp_source/src/app_connect.h @@ -0,0 +1,27 @@ +/* + * Copyright 2020 - 2021 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef __APP_CONNECT_H__ +#define __APP_CONNECT_H__ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +extern struct bt_conn *default_conn; +extern bt_addr_t default_peer_addr; + +/******************************************************************************* + * API + ******************************************************************************/ + +void app_connect_init(void); + +void app_connect(uint8_t *addr); + +void app_disconnect(void); + +#endif /* __APP_CONNECT_H__ */ diff --git a/samples/bluetooth/a2dp_source/src/app_discover.c b/samples/bluetooth/a2dp_source/src/app_discover.c new file mode 100644 index 0000000000000..cae072e7972a7 --- /dev/null +++ b/samples/bluetooth/a2dp_source/src/app_discover.c @@ -0,0 +1,107 @@ +/* + * Copyright 2020 - 2021 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define APP_INQUIRY_LENGTH (10) /* 10 * 1.28 Sec */ +#define APP_INQUIRY_NUM_RESPONSES (20) + +static uint32_t br_discover_result_count; +static struct bt_br_discovery_result br_discovery_results[APP_INQUIRY_NUM_RESPONSES]; + +static void br_device_found(size_t index, const bt_addr_t *addr, int8_t rssi, + const uint8_t cod[3], const uint8_t eir[240]) +{ + char br_addr[BT_ADDR_STR_LEN]; + char name[239]; + int len = 240; + + (void)memset(name, 0, sizeof(name)); + + while (len) { + if (len < 2) { + break; + } + + /* Look for early termination */ + if (!eir[0]) { + break; + } + + /* check if field length is correct */ + if (eir[0] > len - 1) { + break; + } + + switch (eir[1]) { + case BT_DATA_NAME_SHORTENED: + case BT_DATA_NAME_COMPLETE: + memcpy(name, &eir[2], (eir[0] - 1) > (sizeof(name) - 1) ? + (sizeof(name) - 1) : (eir[0] - 1)); + break; + default: + break; + } + + /* Parse next AD Structure */ + len -= (eir[0] + 1); + eir += (eir[0] + 1); + } + + bt_addr_to_str(addr, br_addr, sizeof(br_addr)); + printk("[%d]: %s, RSSI %i %s\r\n", index + 1, br_addr, rssi, name); +} + +static void br_discovery_complete(struct bt_br_discovery_result *results, + size_t count) +{ + size_t index; + + br_discover_result_count = count; + printk("BR/EDR discovery complete\r\n"); + for (index = 0; index < count; ++index) { + br_device_found(index, &results[index].addr, results[index].rssi, + results[index].cod, results[index].eir); + } +} + +void app_discover(void) +{ + int err; + struct bt_br_discovery_param param; + + param.length = APP_INQUIRY_LENGTH; + param.limited = 0U; + err = bt_br_discovery_start(¶m, br_discovery_results, + APP_INQUIRY_NUM_RESPONSES, + br_discovery_complete); + if (err != 0) { + printk("Failed to start discovery\r\n"); + } else { + printk("Discovery started. Please wait ...\r\n"); + } +} + +uint8_t *app_get_addr(uint8_t select) +{ + if (select < br_discover_result_count) { + return &br_discovery_results[select].addr.val[0]; + } + + return NULL; +} diff --git a/samples/bluetooth/a2dp_source/src/app_discover.h b/samples/bluetooth/a2dp_source/src/app_discover.h new file mode 100644 index 0000000000000..ad61721a110d1 --- /dev/null +++ b/samples/bluetooth/a2dp_source/src/app_discover.h @@ -0,0 +1,22 @@ +/* + * Copyright 2020 - 2021 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef __APP_DISCOVER_H__ +#define __APP_DISCOVER_H__ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/******************************************************************************* + * API + ******************************************************************************/ + +void app_discover(void); + +uint8_t *app_get_addr(uint8_t select); + +#endif /* __APP_DISCOVER_H__ */ diff --git a/samples/bluetooth/a2dp_source/src/app_shell.c b/samples/bluetooth/a2dp_source/src/app_shell.c new file mode 100644 index 0000000000000..41476dea3c28d --- /dev/null +++ b/samples/bluetooth/a2dp_source/src/app_shell.c @@ -0,0 +1,86 @@ +/* + * Copyright 2020 - 2021 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "app_discover.h" +#include "app_connect.h" + +static int cmd_a2dp_source_bt_discover(const struct shell *sh, size_t argc, char *argv[]) +{ + app_discover(); + return 0; +} + +static int cmd_a2dp_source_bt_connect(const struct shell *sh, size_t argc, char *argv[]) +{ + uint8_t select_index = 0; + char *ch = argv[1]; + uint8_t *addr; + + if (argc < 2) { + printk("the parameter count is wrong\r\n"); + return SHELL_CMD_HELP_PRINTED; + } + + for (select_index = 0; select_index < strlen(ch); ++select_index) { + if ((ch[select_index] < '0') || (ch[select_index] > '9')) { + printk("the parameter is wrong\r\n"); + return SHELL_CMD_HELP_PRINTED; + } + } + + switch (strlen(ch)) { + case 1: + select_index = ch[0] - '0'; + break; + case 2: + select_index = (ch[0] - '0') * 10 + (ch[1] - '0'); + break; + default: + printk("the parameter is wrong\r\n"); + break; + } + + if (select_index == 0U) { + printk("the parameter is wrong\r\n"); + } + addr = app_get_addr(select_index - 1); + app_connect(addr); + return 0; +} + +static int cmd_a2dp_source_bt_disconnect(const struct shell *sh, size_t argc, char *argv[]) +{ + app_disconnect(); + return 0; +} + +SHELL_STATIC_SUBCMD_SET_CREATE(a2dp_source_bt_cmds, + SHELL_CMD(discover, NULL, "start to find BT devices", cmd_a2dp_source_bt_discover), + SHELL_CMD_ARG(connect, NULL, + "connect to the device that is found, for example: bt connectdevice n (from 1)", + cmd_a2dp_source_bt_connect, 2, 0), + SHELL_CMD(disconnect, NULL, "disconnect current connection", + cmd_a2dp_source_bt_disconnect), + SHELL_SUBCMD_SET_END +); + +SHELL_CMD_REGISTER(bt, &a2dp_source_bt_cmds, "a2dp source demo shell commands", NULL); diff --git a/samples/bluetooth/a2dp_source/src/main.c b/samples/bluetooth/a2dp_source/src/main.c new file mode 100644 index 0000000000000..f25d2a8cdada4 --- /dev/null +++ b/samples/bluetooth/a2dp_source/src/main.c @@ -0,0 +1,331 @@ +/* + * Copyright 2020 - 2021 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "app_connect.h" +#include "a2dp_media_48KHz_1ksin.h" + +#define SDP_CLIENT_USER_BUF_LEN 512U +NET_BUF_POOL_FIXED_DEFINE(app_sdp_client_pool, CONFIG_BT_MAX_CONN, + SDP_CLIENT_USER_BUF_LEN, 8, NULL); + +static uint8_t app_sdp_a2sink_user(struct bt_conn *conn, struct bt_sdp_client_result *result); + +static struct bt_sdp_discover_params discov_a2dp_sink = { + .uuid = BT_UUID_DECLARE_16(BT_SDP_AUDIO_SINK_SVCLASS), + .func = app_sdp_a2sink_user, + .pool = &app_sdp_client_pool, +}; + +static void a2dp_playback_timeout_handler(struct k_timer *timer); +K_TIMER_DEFINE(a2dp_player_timer, a2dp_playback_timeout_handler, NULL); + +#define APPL_A2DP_MTU (672U) +#define DEFAULT_BIT_RATE (328u) + +static uint32_t a2dp_src_sf; + +static int64_t ref_time; +static uint32_t a2dp_src_missed_count; +static volatile uint8_t a2dp_src_playback; +static int tone_index; +uint8_t a2dp_src_nc; + +#define A2DP_SBC_BLOCK_MAX (512U) +uint32_t audio_time_interval; /* ms */ +uint32_t audio_frame_sample_count; +uint8_t a2dp_pcm_buffer[1920u]; /* 10ms max packet pcm data size. the max is 480 * 2 * 2 */ +uint8_t a2dp_sbc_encode_buffer_frame[A2DP_SBC_BLOCK_MAX]; +struct sbc_encoder encoder; +uint32_t send_samples_count; +uint16_t send_count; + +#define A2DP_SRC_PERIOD_MS 10 + +struct bt_a2dp *default_a2dp; +struct bt_a2dp_endpoint *default_a2dp_endpoint; +BT_A2DP_SBC_SOURCE_ENDPOINT(sbc_endpoint, A2DP_SBC_SAMP_FREQ_48000); + +static uint8_t *a2dp_pl_produce_media(uint32_t a2dp_src_num_samples) +{ + uint8_t *media = NULL; + uint16_t medialen; + + /* Music Audio is Stereo */ + medialen = (a2dp_src_num_samples * a2dp_src_nc * 2); + + /* For mono or dual configuration, skip alternative samples */ + if (1 == a2dp_src_nc) { + uint16_t index; + + media = (uint8_t *)&a2dp_pcm_buffer[0]; + + for (index = 0; index < a2dp_src_num_samples; index++) { + media[(2 * index)] = *((uint8_t *)beethoven + tone_index); + media[(2 * index) + 1] = *((uint8_t *)beethoven + tone_index + 1); + /* Update the tone index */ + tone_index += 4u; + if (tone_index >= sizeof(beethoven)) { + tone_index = 0U; + } + } + } else { + if ((tone_index + (a2dp_src_num_samples << 2)) > sizeof(beethoven)) { + media = (uint8_t *)&a2dp_pcm_buffer[0]; + memcpy(media, ((uint8_t *)beethoven + tone_index), + sizeof(beethoven) - tone_index); + memcpy(&media[sizeof(beethoven) - tone_index], + ((uint8_t *)beethoven), + ((a2dp_src_num_samples << 2) - (sizeof(beethoven) - tone_index))); + /* Update the tone index */ + tone_index = ((a2dp_src_num_samples << 2) - + (sizeof(beethoven) - tone_index)); + } else { + media = ((uint8_t *)beethoven + tone_index); + /* Update the tone index */ + tone_index += (a2dp_src_num_samples << 2); + if (tone_index >= sizeof(beethoven)) { + tone_index = 0U; + } + } + } + + return media; +} + +static void a2dp_playback_timeout_handler(struct k_timer *timer) +{ + int64_t period_ms; + uint32_t a2dp_src_num_samples; + uint8_t *pcm_data; + uint8_t index; + uint32_t pcm_frame_size; + uint32_t pcm_frame_samples; + uint32_t encoded_frame_size; + uint8_t *net_buffer; + struct net_buf *buf; + uint32_t sample_count = 0; + uint8_t frame_num = 0; + int ret; + struct bt_a2dp_codec_sbc_media_packet_hdr *sbc_hdr; + int err; + + /* If stopped then return */ + if (0U == a2dp_src_playback) { + return; + } + + period_ms = k_uptime_delta(&ref_time); + + buf = bt_a2dp_media_buf_alloc(NULL); + if (buf == NULL) { + return; + } + sbc_hdr = net_buf_add(buf, sizeof(struct bt_a2dp_codec_sbc_media_packet_hdr)); + memset(sbc_hdr, 0, sizeof(struct bt_a2dp_codec_sbc_media_packet_hdr)); + /* Get the number of samples */ + a2dp_src_num_samples = (uint16_t)((period_ms * a2dp_src_sf) / 1000); + a2dp_src_missed_count += (uint32_t)((period_ms * a2dp_src_sf) % 1000); + + /* Raw adjust for the drift */ + while (a2dp_src_missed_count >= (1000 * audio_frame_sample_count)) { + a2dp_src_num_samples += audio_frame_sample_count; + a2dp_src_missed_count -= (1000 * audio_frame_sample_count); + } + + pcm_data = a2dp_pl_produce_media(a2dp_src_num_samples); + if (pcm_data == NULL) { + return; + } + + pcm_frame_size = sbc_frame_bytes(&encoder); + pcm_frame_samples = sbc_frame_samples(&encoder); + encoded_frame_size = sbc_frame_encoded_bytes(&encoder); + for (index = 0; index < (a2dp_src_num_samples / audio_frame_sample_count); index++) { + net_buffer = net_buf_tail(buf); + if (buf->len + encoded_frame_size > bt_a2dp_get_media_mtu(default_a2dp_endpoint)) { + printk("mtu error"); + return; + } + + err = sbc_encode(&encoder, + (uint8_t *)&pcm_data[index * pcm_frame_size], + encoded_frame_size, &net_buffer[0]); + if (err) { + printk("sbc encode fail"); + continue; + } + buf->len += encoded_frame_size; + sample_count += pcm_frame_samples; + frame_num++; + } + + sbc_hdr->number_of_sbc_frames = frame_num; + ret = bt_a2dp_media_send(default_a2dp_endpoint, buf, send_count, send_samples_count); + if (ret < 0) { + printk(" Failed to send SBC audio data on streams(%d)\n", ret); + net_buf_unref(buf); + } else { + send_count++; + send_samples_count += sample_count; + } +} + +static void music_control_a2dp_start_callback(int err) +{ + /* Start Audio Source */ + a2dp_src_playback = 1U; + audio_frame_sample_count = sbc_frame_samples(&encoder); + + /* calculate the interval that contains multiple of frame. default is 10ms */ + audio_time_interval = ((10 * a2dp_src_sf / 1000) / audio_frame_sample_count); + audio_time_interval = audio_time_interval * audio_frame_sample_count * 1000 / a2dp_src_sf; + k_uptime_delta(&ref_time); + k_timer_start(&a2dp_player_timer, K_MSEC(audio_time_interval), K_MSEC(audio_time_interval)); +} + +void app_endpoint_configured(struct bt_a2dp_endpoint_configure_result *result) +{ + if (result->err == 0) { + default_a2dp_endpoint = &sbc_endpoint; + struct bt_a2dp_codec_sbc_params *config = + (struct bt_a2dp_codec_sbc_params *) + &result->config.media_config->codec_ie[0]; + + a2dp_src_sf = bt_a2dp_sbc_get_sampling_frequency(config); + a2dp_src_nc = bt_a2dp_sbc_get_channel_num(config); + + sbc_setup_encoder(&encoder, a2dp_src_sf, bt_a2dp_sbc_get_channel_mode(config), + bt_a2dp_sbc_get_block_length(config), bt_a2dp_sbc_get_subband_num(config), + bt_a2dp_sbc_get_allocation_method(config), DEFAULT_BIT_RATE); + bt_a2dp_start(default_a2dp_endpoint); + printk("a2dp start playing\r\n"); + } +} + +void app_configured(int err) +{ + if (err) { + printk("configuring fail\r\n"); + } +} + +void app_connected(struct bt_a2dp *a2dp, int err) +{ + if (!err) { + bt_a2dp_configure(a2dp, app_configured); + printk("a2dp connected success\r\n"); + } else { + if (default_a2dp != NULL) { + default_a2dp = NULL; + } + printk("a2dp connected fail\r\n"); + } +} + +void app_disconnected(struct bt_a2dp *a2dp) +{ + if (default_a2dp != NULL) { + default_a2dp = NULL; + } + a2dp_src_playback = 0U; + /* stop timer */ + k_timer_stop(&a2dp_player_timer); + printk("a2dp disconnected\r\n"); +} + +static uint8_t app_sdp_a2sink_user(struct bt_conn *conn, + struct bt_sdp_client_result *result) +{ + uint16_t param; + int res; + + if ((result) && (result->resp_buf)) { + printk("sdp success callback\r\n"); + res = bt_sdp_get_proto_param(result->resp_buf, BT_SDP_PROTO_L2CAP, ¶m); + if (res < 0) { + printk("PSM is not found\r\n"); + return BT_SDP_DISCOVER_UUID_CONTINUE; + } + if (param == BT_UUID_AVDTP_VAL) { + printk("A2DP Service found. Connecting ...\n"); + default_a2dp = bt_a2dp_connect(default_conn); + if (default_a2dp == NULL) { + printk("fail to connect a2dp\r\n"); + } + return BT_SDP_DISCOVER_UUID_STOP; + } + return BT_SDP_DISCOVER_UUID_CONTINUE; + } + + printk("sdp fail callback\r\n"); + return BT_SDP_DISCOVER_UUID_CONTINUE; +} + +void app_sdp_discover_a2dp_sink(void) +{ + int res; + + res = bt_sdp_discover(default_conn, &discov_a2dp_sink); + if (res) { + printk("SDP discovery failed: result\r\n"); + } else { + printk("SDP discovery started\r\n"); + } +} + +static void app_a2dp_init(void) +{ + struct bt_a2dp_connect_cb connect_cb; + + connect_cb.connected = app_connected; + connect_cb.disconnected = app_disconnected; + + sbc_endpoint.control_cbs.start_play = music_control_a2dp_start_callback; + sbc_endpoint.control_cbs.configured = app_endpoint_configured; + bt_a2dp_register_endpoint(&sbc_endpoint, BT_A2DP_AUDIO, BT_A2DP_SOURCE); + + bt_a2dp_register_connect_callback(&connect_cb); +} + +static void bt_ready(int err) +{ + if (err) { + printk("Bluetooth init failed (err %d)\n", err); + return; + } + + printk("Bluetooth initialized\n"); + + app_connect_init(); + app_a2dp_init(); +} + +int main(void) +{ + int err; + + err = bt_enable(bt_ready); + if (err) { + printk("Bluetooth init failed (err %d)\n", err); + } + + return err; +}