mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 11:03:11 +00:00
feat(ble_audio): Support ISO & LE Audio functionalities (Preview)
This commit is contained in:
@@ -168,6 +168,7 @@
|
||||
- "components/bt/controller/lib_esp32c5/esp32c5-bt-lib"
|
||||
- "components/bt/controller/lib_esp32h4/esp32h4-bt-lib"
|
||||
- "components/bt/esp_ble_mesh/lib/lib"
|
||||
- "components/bt/esp_ble_audio/lib/lib"
|
||||
- ".gitmodules"
|
||||
|
||||
##############
|
||||
|
||||
@@ -149,3 +149,8 @@
|
||||
path = components/bt/esp_ble_mesh/lib/lib
|
||||
url = ../../espressif/esp-ble-mesh-lib.git
|
||||
shallow = true
|
||||
|
||||
[submodule "components/bt/esp_ble_audio/lib/lib"]
|
||||
path = components/bt/esp_ble_audio/lib/lib
|
||||
url = ../../espressif/esp-ble-audio-lib.git
|
||||
shallow = true
|
||||
|
||||
@@ -57,6 +57,14 @@ if(CONFIG_IDF_DOC_BUILD)
|
||||
${ble_mesh_v11_include_dirs})
|
||||
endif()
|
||||
|
||||
set(ble_iso_include_dirs
|
||||
"esp_ble_audio/api/iso/include"
|
||||
)
|
||||
|
||||
set(ble_audio_include_dirs
|
||||
"esp_ble_audio/api/audio/include"
|
||||
)
|
||||
|
||||
set(bluedroid_include_dirs host/bluedroid/api/include/api)
|
||||
|
||||
if(CONFIG_BT_CONTROLLER_ENABLED OR CONFIG_IDF_DOC_BUILD)
|
||||
@@ -68,6 +76,8 @@ if(CONFIG_IDF_DOC_BUILD)
|
||||
${target_specific_include_dirs}
|
||||
${common_include_dirs}
|
||||
${ble_mesh_include_dirs}
|
||||
${ble_iso_include_dirs}
|
||||
${ble_audio_include_dirs}
|
||||
${bluedroid_include_dirs}
|
||||
${nimble_hci_include_dirs})
|
||||
endif()
|
||||
@@ -680,6 +690,160 @@ if(CONFIG_BT_ENABLED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_ISO)
|
||||
list(APPEND include_dirs
|
||||
${ble_iso_include_dirs}
|
||||
"esp_ble_audio/host"
|
||||
"esp_ble_audio/host/adapter"
|
||||
"esp_ble_audio/include/subsys/bluetooth"
|
||||
"esp_ble_audio/include/subsys/bluetooth/host"
|
||||
"esp_ble_audio/include")
|
||||
|
||||
list(APPEND srcs
|
||||
"esp_ble_audio/host/adapter/nimble/gatt/gatt.c"
|
||||
"esp_ble_audio/host/adapter/nimble/gatt/gatt.db.c"
|
||||
"esp_ble_audio/host/adapter/nimble/gatt/gatt.nrp.c"
|
||||
"esp_ble_audio/host/adapter/nimble/gap.c"
|
||||
"esp_ble_audio/host/adapter/nimble/iso.c"
|
||||
"esp_ble_audio/host/common/adv.c"
|
||||
"esp_ble_audio/host/common/conn.c"
|
||||
"esp_ble_audio/host/common/gatt.c"
|
||||
"esp_ble_audio/host/common/hci.c"
|
||||
"esp_ble_audio/host/common/host.c"
|
||||
"esp_ble_audio/host/common/iso.c"
|
||||
"esp_ble_audio/host/common/scan.c"
|
||||
"esp_ble_audio/host/common/task.c"
|
||||
"esp_ble_audio/host/common/app/gap.c"
|
||||
"esp_ble_audio/host/common/app/gatt.c"
|
||||
"esp_ble_audio/host/utils/crc/crc32_sw.c"
|
||||
"esp_ble_audio/host/utils/addr.c"
|
||||
"esp_ble_audio/host/utils/bt_str.c"
|
||||
"esp_ble_audio/host/utils/buf.c"
|
||||
"esp_ble_audio/host/utils/crypto.c"
|
||||
"esp_ble_audio/host/utils/timer.c"
|
||||
"esp_ble_audio/host/utils/utf8.c"
|
||||
"esp_ble_audio/host/utils/utils.c"
|
||||
"esp_ble_audio/host/utils/uuid.c"
|
||||
"esp_ble_audio/host/iso/iso.c"
|
||||
"esp_ble_audio/api/iso/esp_ble_iso_common_api.c")
|
||||
|
||||
if(CONFIG_BT_OTS OR CONFIG_BT_OTS_CLIENT)
|
||||
list(APPEND srcs
|
||||
"esp_ble_audio/host/common/l2cap.c"
|
||||
"esp_ble_audio/host/adapter/nimble/l2cap.c")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_AUDIO)
|
||||
list(APPEND include_dirs
|
||||
${ble_audio_include_dirs}
|
||||
"esp_ble_audio/include/subsys/bluetooth/host")
|
||||
|
||||
list(APPEND srcs
|
||||
"esp_ble_audio/host/adapter/nimble/profiles/server.c"
|
||||
"esp_ble_audio/host/adapter/nimble/init.c"
|
||||
"esp_ble_audio/host/common/init.c"
|
||||
"esp_ble_audio/api/audio/esp_ble_audio_aics_api.c"
|
||||
"esp_ble_audio/api/audio/esp_ble_audio_bap_api.c"
|
||||
"esp_ble_audio/api/audio/esp_ble_audio_cap_api.c"
|
||||
"esp_ble_audio/api/audio/esp_ble_audio_ccp_api.c"
|
||||
"esp_ble_audio/api/audio/esp_ble_audio_codec_api.c"
|
||||
"esp_ble_audio/api/audio/esp_ble_audio_common_api.c"
|
||||
"esp_ble_audio/api/audio/esp_ble_audio_csip_api.c"
|
||||
"esp_ble_audio/api/audio/esp_ble_audio_gmap_api.c"
|
||||
"esp_ble_audio/api/audio/esp_ble_audio_has_api.c"
|
||||
"esp_ble_audio/api/audio/esp_ble_audio_mcc_api.c"
|
||||
"esp_ble_audio/api/audio/esp_ble_audio_media_proxy_api.c"
|
||||
"esp_ble_audio/api/audio/esp_ble_audio_micp_api.c"
|
||||
"esp_ble_audio/api/audio/esp_ble_audio_pacs_api.c"
|
||||
"esp_ble_audio/api/audio/esp_ble_audio_pbp_api.c"
|
||||
"esp_ble_audio/api/audio/esp_ble_audio_tbs_api.c"
|
||||
"esp_ble_audio/api/audio/esp_ble_audio_tmap_api.c"
|
||||
"esp_ble_audio/api/audio/esp_ble_audio_vcp_api.c"
|
||||
"esp_ble_audio/api/audio/esp_ble_audio_vocs_api.c")
|
||||
|
||||
if(CONFIG_BT_ASCS)
|
||||
list(APPEND srcs
|
||||
"esp_ble_audio/host/adapter/nimble/profiles/ascs.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_PACS)
|
||||
list(APPEND srcs
|
||||
"esp_ble_audio/host/adapter/nimble/profiles/pacs.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_BAP_SCAN_DELEGATOR)
|
||||
list(APPEND srcs
|
||||
"esp_ble_audio/host/adapter/nimble/profiles/bass.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_CAP_ACCEPTOR)
|
||||
list(APPEND srcs
|
||||
"esp_ble_audio/host/adapter/nimble/profiles/cas.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_CSIP_SET_MEMBER)
|
||||
list(APPEND srcs
|
||||
"esp_ble_audio/host/adapter/nimble/profiles/csis.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_TBS)
|
||||
list(APPEND srcs
|
||||
"esp_ble_audio/host/adapter/nimble/profiles/tbs.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_TMAP)
|
||||
list(APPEND srcs
|
||||
"esp_ble_audio/host/adapter/nimble/profiles/tmas.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_VCP_VOL_REND)
|
||||
list(APPEND srcs
|
||||
"esp_ble_audio/host/adapter/nimble/profiles/vcs.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_MICP_MIC_DEV)
|
||||
list(APPEND srcs
|
||||
"esp_ble_audio/host/adapter/nimble/profiles/mics.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_MCS)
|
||||
list(APPEND srcs
|
||||
"esp_ble_audio/host/adapter/nimble/profiles/mcs.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_HAS)
|
||||
list(APPEND srcs
|
||||
"esp_ble_audio/host/adapter/nimble/profiles/has.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_OTS OR CONFIG_BT_OTS_CLIENT)
|
||||
list(APPEND include_dirs
|
||||
"esp_ble_audio/host/services/ots")
|
||||
|
||||
list(APPEND srcs
|
||||
"esp_ble_audio/host/services/ots/ots_l2cap.c")
|
||||
|
||||
if(CONFIG_BT_OTS)
|
||||
list(APPEND srcs
|
||||
"esp_ble_audio/host/services/ots/ots_oacp.c"
|
||||
"esp_ble_audio/host/services/ots/ots_obj_manager.c"
|
||||
"esp_ble_audio/host/services/ots/ots_olcp.c"
|
||||
"esp_ble_audio/host/services/ots/ots.c")
|
||||
|
||||
if(CONFIG_BT_OTS_DIR_LIST_OBJ)
|
||||
list(APPEND srcs
|
||||
"esp_ble_audio/host/services/ots/ots_dir_list.c")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_OTS_CLIENT)
|
||||
list(APPEND srcs
|
||||
"esp_ble_audio/host/services/ots/ots_client.c")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_DUAL_MODE_ARCH)
|
||||
add_subdirectory(porting_btdm)
|
||||
list(APPEND srcs
|
||||
@@ -1171,6 +1335,13 @@ if(CONFIG_BT_NIMBLE_MESH)
|
||||
PROPERTIES COMPILE_FLAGS -Wno-type-limits)
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_AUDIO)
|
||||
if(CONFIG_IDF_TARGET_ESP32H4)
|
||||
add_prebuilt_library(ble_audio "esp_ble_audio/lib/lib/esp32h4/libble_audio.a")
|
||||
target_link_libraries(${COMPONENT_LIB} PRIVATE ble_audio)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE AND CONFIG_BT_NIMBLE_ENABLED)
|
||||
# some variables in NimBLE are only used by asserts
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-unused-but-set-variable -Wno-unused-variable)
|
||||
|
||||
@@ -109,6 +109,16 @@ menu "Bluetooth"
|
||||
This option is to configure the buffer size of the hci adv report cache in hci debug mode.
|
||||
This is a ring buffer, the new data will overwrite the oldest data if the buffer is full.
|
||||
|
||||
menu "BLE ISO Options"
|
||||
depends on BT_ENABLED && SOC_BLE_ISO_SUPPORTED
|
||||
source "$IDF_PATH/components/bt/esp_ble_audio/host/iso/Kconfig.iso.in"
|
||||
endmenu
|
||||
|
||||
menu "BLE Audio Options"
|
||||
depends on BT_ENABLED && SOC_BLE_AUDIO_SUPPORTED
|
||||
source "$IDF_PATH/components/bt/esp_ble_audio/Kconfig.in"
|
||||
endmenu
|
||||
|
||||
endmenu
|
||||
|
||||
menuconfig BLE_MESH
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
# Bluetooth Audio configuration options
|
||||
|
||||
# SPDX-FileCopyrightText: 2020 Intel Corporation
|
||||
# SPDX-FileCopyrightText: 2022 Nordic Semiconductor ASA
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config BT_AUDIO
|
||||
bool # hidden
|
||||
help
|
||||
This option enables Bluetooth Audio support. The specific
|
||||
features that are available may depend on other features
|
||||
that have been enabled in the stack, such as Periodic
|
||||
Advertisement for Broadcast and L2CAP Dynamic Channel
|
||||
for Unicast.
|
||||
|
||||
config BT_AUDIO_RX
|
||||
bool # hidden
|
||||
default y if BT_ASCS_ASE_SNK || BT_BAP_UNICAST_CLIENT_ASE_SRC || BT_BAP_BROADCAST_SINK
|
||||
select BT_AUDIO
|
||||
|
||||
config BT_AUDIO_TX
|
||||
bool # hidden
|
||||
default y if BT_ASCS_ASE_SRC || BT_BAP_UNICAST_CLIENT_ASE_SNK || BT_BAP_BROADCAST_SOURCE
|
||||
select BT_AUDIO
|
||||
|
||||
menu "AICS Options"
|
||||
rsource "Kconfig/Kconfig.aics.in"
|
||||
endmenu
|
||||
|
||||
menu "ASCS Options"
|
||||
rsource "Kconfig/Kconfig.ascs.in"
|
||||
endmenu
|
||||
|
||||
menu "BAP Options"
|
||||
rsource "Kconfig/Kconfig.bap.in"
|
||||
endmenu
|
||||
|
||||
menu "CAP Options"
|
||||
rsource "Kconfig/Kconfig.cap.in"
|
||||
endmenu
|
||||
|
||||
menu "CCP Options"
|
||||
rsource "Kconfig/Kconfig.ccp.in"
|
||||
endmenu
|
||||
|
||||
menu "CSIP Options"
|
||||
rsource "Kconfig/Kconfig.csip.in"
|
||||
endmenu
|
||||
|
||||
menu "GMAP Options"
|
||||
rsource "Kconfig/Kconfig.gmap.in"
|
||||
endmenu
|
||||
|
||||
menu "MCS Options"
|
||||
rsource "Kconfig/Kconfig.mcs.in"
|
||||
endmenu
|
||||
|
||||
menu "MCTL Options"
|
||||
rsource "Kconfig/Kconfig.mctl.in"
|
||||
endmenu
|
||||
|
||||
menu "MICP Options"
|
||||
rsource "Kconfig/Kconfig.micp.in"
|
||||
endmenu
|
||||
|
||||
menu "MPL Options"
|
||||
rsource "Kconfig/Kconfig.mpl.in"
|
||||
endmenu
|
||||
|
||||
menu "PACS Options"
|
||||
rsource "Kconfig/Kconfig.pacs.in"
|
||||
endmenu
|
||||
|
||||
menu "TBS Options"
|
||||
rsource "Kconfig/Kconfig.tbs.in"
|
||||
endmenu
|
||||
|
||||
menu "VCP Options"
|
||||
rsource "Kconfig/Kconfig.vcp.in"
|
||||
endmenu
|
||||
|
||||
menu "VOCS Options"
|
||||
rsource "Kconfig/Kconfig.vocs.in"
|
||||
endmenu
|
||||
|
||||
menu "TMAP Options"
|
||||
rsource "Kconfig/Kconfig.tmap.in"
|
||||
endmenu
|
||||
|
||||
menu "HAS Options"
|
||||
rsource "Kconfig/Kconfig.has.in"
|
||||
endmenu
|
||||
|
||||
menu "PBP Options"
|
||||
rsource "Kconfig/Kconfig.pbp.in"
|
||||
endmenu
|
||||
|
||||
menu "OTS Options"
|
||||
rsource "host/services/ots/Kconfig.ots.in"
|
||||
endmenu
|
||||
|
||||
config BT_AUDIO_NO_LOG
|
||||
bool "Disable BLE Audio Debug Log"
|
||||
default n
|
||||
help
|
||||
Select this to save the BLE Audio related rodata code size. Enabling
|
||||
this option will disable the output of BLE Audio debug log.
|
||||
|
||||
menu "BLE Audio Debug Log Level"
|
||||
depends on !BT_AUDIO_NO_LOG
|
||||
|
||||
choice BT_AUDIO_LOG_LEVEL
|
||||
prompt "LE_AUDIO_LOG_LEVEL"
|
||||
default BT_AUDIO_LOG_LEVEL_WARNING
|
||||
depends on !BT_AUDIO_NO_LOG
|
||||
help
|
||||
Define BLE Audio trace level.
|
||||
|
||||
config BT_AUDIO_LOG_LEVEL_NONE
|
||||
bool "NONE"
|
||||
config BT_AUDIO_LOG_LEVEL_ERROR
|
||||
bool "ERROR"
|
||||
config BT_AUDIO_LOG_LEVEL_WARNING
|
||||
bool "WARNING"
|
||||
config BT_AUDIO_LOG_LEVEL_INFO
|
||||
bool "INFO"
|
||||
config BT_AUDIO_LOG_LEVEL_DEBUG
|
||||
bool "DEBUG"
|
||||
config BT_AUDIO_LOG_LEVEL_VERBOSE
|
||||
bool "VERBOSE"
|
||||
endchoice
|
||||
|
||||
config BT_AUDIO_LOG_LEVEL
|
||||
int
|
||||
default 0 if BT_AUDIO_LOG_LEVEL_NONE
|
||||
default 1 if BT_AUDIO_LOG_LEVEL_ERROR
|
||||
default 2 if BT_AUDIO_LOG_LEVEL_WARNING
|
||||
default 3 if BT_AUDIO_LOG_LEVEL_INFO
|
||||
default 4 if BT_AUDIO_LOG_LEVEL_DEBUG
|
||||
default 5 if BT_AUDIO_LOG_LEVEL_VERBOSE
|
||||
default 2
|
||||
endmenu
|
||||
@@ -0,0 +1,50 @@
|
||||
# Bluetooth Audio - Audio Input Control Service options
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2020 Bose Corporation
|
||||
# SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##################### Audio Input Control Service #####################
|
||||
|
||||
config BT_AICS_MAX_INSTANCE_COUNT
|
||||
int "Audio Input Control Service max instance count"
|
||||
default 0
|
||||
range 0 15
|
||||
help
|
||||
This option sets the maximum number of instances of Audio Input
|
||||
Control Services.
|
||||
|
||||
config BT_AICS
|
||||
bool # hidden
|
||||
default y if BT_AICS_MAX_INSTANCE_COUNT > 0
|
||||
help
|
||||
This hidden option enables support for Audio Input Control Service.
|
||||
|
||||
if BT_AICS
|
||||
|
||||
config BT_AICS_MAX_INPUT_DESCRIPTION_SIZE
|
||||
int "Audio Input Control Service max input description size"
|
||||
default 32
|
||||
range 0 512
|
||||
help
|
||||
This option sets the maximum input description size in octets.
|
||||
|
||||
endif # BT_AICS
|
||||
|
||||
##################### Audio Input Control Service Client #####################
|
||||
|
||||
config BT_AICS_CLIENT_MAX_INSTANCE_COUNT
|
||||
int "Audio Input Control Service client max instance count"
|
||||
default 0
|
||||
range 0 15
|
||||
help
|
||||
This option sets the maximum number of instances of Audio Input
|
||||
Control Services.
|
||||
|
||||
config BT_AICS_CLIENT
|
||||
bool # hidden
|
||||
default y if BT_AICS_CLIENT_MAX_INSTANCE_COUNT > 0
|
||||
help
|
||||
This hidden option enables support for Audio Input Control Service.
|
||||
@@ -0,0 +1,73 @@
|
||||
# Bluetooth Audio - Audio Stream Control configuration options
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2020 Intel Corporation
|
||||
# SPDX-FileCopyrightText: 2022 Nordic Semiconductor ASA
|
||||
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
config BT_ASCS
|
||||
bool "Audio Stream Control Service Support"
|
||||
help
|
||||
This option enables support for Audio Stream Control Service.
|
||||
|
||||
if BT_ASCS
|
||||
|
||||
config BT_ASCS_MAX_ASE_SNK_COUNT
|
||||
int "Maximum number of Audio Stream Endpoint Sink Characteristics"
|
||||
default 2
|
||||
range 0 255
|
||||
help
|
||||
An ASE Sink characteristic represents the state of an ASE, which is
|
||||
coupled to a single direction of a unicast Audio Stream.
|
||||
|
||||
config BT_ASCS_MAX_ASE_SRC_COUNT
|
||||
int "Maximum number of Audio Stream Endpoint Source Characteristics"
|
||||
default 2
|
||||
range 0 255
|
||||
help
|
||||
An ASE Source characteristic represents the state of an ASE, which is
|
||||
coupled to a single direction of a unicast Audio Stream.
|
||||
|
||||
config BT_ASCS_ASE_SNK
|
||||
bool # hidden
|
||||
default y if BT_ASCS_MAX_ASE_SNK_COUNT > 0
|
||||
select BT_PAC_SNK
|
||||
select BT_AUDIO_RX
|
||||
|
||||
config BT_ASCS_ASE_SRC
|
||||
bool # hidden
|
||||
default y if BT_ASCS_MAX_ASE_SRC_COUNT > 0
|
||||
select BT_PAC_SRC
|
||||
select BT_AUDIO_TX
|
||||
|
||||
config BT_ASCS_MAX_ACTIVE_ASES
|
||||
int "Number of simultaneously supported ASE sessions"
|
||||
default BT_ISO_MAX_CHAN
|
||||
range 1 65535
|
||||
help
|
||||
The number of simultaneously supported active ASEs, in particular
|
||||
meaning the number of ASEs that are allowed to be in a non-idle state at
|
||||
a single time.
|
||||
|
||||
config BT_ASCS_ISO_DISCONNECT_DELAY
|
||||
int "Milliseconds of delay before ASCS disconnects ISO after stream stop"
|
||||
range 0 5000
|
||||
default 500
|
||||
help
|
||||
The number of milliseconds ASCS will wait before disconnecting the ISO
|
||||
of a stopped stream. The delay is added as it is the Unicast Client's
|
||||
responsibility, but this is a failsafe to ensure that ISO channel is
|
||||
being properly disconnected.
|
||||
|
||||
config BT_ASCS_ASE_BUF_TIMEOUT
|
||||
int "Milliseconds of timeout when handle concurrent access to the long read ASE buffer"
|
||||
range 0 1000
|
||||
default 50
|
||||
help
|
||||
The number of milliseconds that the ASCS implementation will maximum wait before rejecting
|
||||
an ASE read or dropping a notification if the ASE state is being accessed by another
|
||||
thread.
|
||||
|
||||
|
||||
endif # BT_ASCS
|
||||
@@ -0,0 +1,268 @@
|
||||
# Bluetooth Audio - Basic Audio Profile configuration options
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2020 Intel Corporation
|
||||
# SPDX-FileCopyrightText: 2022-2025 Nordic Semiconductor ASA
|
||||
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
config BT_BAP_UNICAST
|
||||
bool
|
||||
default y if BT_BAP_UNICAST_SERVER || BT_BAP_UNICAST_CLIENT
|
||||
|
||||
config BT_BAP_UNICAST_SERVER
|
||||
bool "Bluetooth Unicast Audio Server Support"
|
||||
select BT_ISO_PERIPHERAL
|
||||
select BT_ASCS
|
||||
select BT_PAC_SNK if BT_ASCS_ASE_SNK
|
||||
select BT_PAC_SRC if BT_ASCS_ASE_SRC
|
||||
help
|
||||
This option enables support for Bluetooth Unicast Audio Server
|
||||
using Isochronous channels.
|
||||
|
||||
config BT_BAP_UNICAST_CLIENT
|
||||
bool "Bluetooth Unicast Audio Client Support"
|
||||
select BT_ISO_CENTRAL
|
||||
help
|
||||
This option enables support for Bluetooth Unicast Audio Client
|
||||
using Isochronous channels.
|
||||
|
||||
config BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE
|
||||
int "Codec Specific Configuration Data Size"
|
||||
default 19
|
||||
range 0 255
|
||||
help
|
||||
Number of octets to support for Codec Specific Configuration data.
|
||||
The default value 19 matches the required fields for the LC3 codec.
|
||||
|
||||
config BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE
|
||||
int "Codec Specific Configuration Metadata Size"
|
||||
default 20
|
||||
range 0 255
|
||||
help
|
||||
Number of octets to support for Codec Specific Configuration metadata.
|
||||
|
||||
config BT_BAP_BASS_MAX_SUBGROUPS
|
||||
int "Maximum number of subgroups supported for the BASS receive states"
|
||||
default 1
|
||||
range 1 24
|
||||
help
|
||||
This option sets the maximum number of subgroups supported.
|
||||
Due to limitations in advertising data, the maximum size of all subgroups are 249.
|
||||
The minimum size of a subgroup is 10 octets.
|
||||
So effectively there can be a maximum of 24 subgroups in a BASE.
|
||||
|
||||
config BT_AUDIO_CODEC_CAP_MAX_DATA_SIZE
|
||||
int "Codec Capabilities Data Size"
|
||||
default 19
|
||||
range 0 255
|
||||
help
|
||||
Number of octets to support for Codec Specific Capabilities data.
|
||||
The default value 19 matches the required fields for the LC3 codec.
|
||||
|
||||
config BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE
|
||||
int "Codec Capabilities Metadata Size"
|
||||
default 4
|
||||
range 0 255
|
||||
help
|
||||
Number of octets to support for Codec Specific Capabilities metadata.
|
||||
|
||||
if BT_BAP_UNICAST_CLIENT
|
||||
|
||||
config BT_BAP_UNICAST_CLIENT_GROUP_COUNT
|
||||
int "Basic Audio Unicast Group count"
|
||||
default 1
|
||||
range 1 BT_ISO_MAX_CIG
|
||||
help
|
||||
This option sets the number of connected audio groups to support as
|
||||
the unicast client.
|
||||
|
||||
config BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT
|
||||
int "Basic Audio Profile Unicast Group Connected Isochronous Stream (CIS) count"
|
||||
depends on BT_BAP_UNICAST_CLIENT_GROUP_COUNT > 0
|
||||
default 1
|
||||
range 1 BT_ISO_MAX_CHAN if BT_ISO_MAX_CHAN < 31
|
||||
range 1 31
|
||||
help
|
||||
This option sets the maximum number of CIS per unicast group to support.
|
||||
Since BAP streams are unidirectional, two BAP streams may use a single CIS, the number of
|
||||
BAP audio streams per group may be up to twice of this value.
|
||||
|
||||
config BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT
|
||||
int "Basic Audio Profile ASE Sink count"
|
||||
default 2
|
||||
range 0 255
|
||||
help
|
||||
This option enables caching a number of Audio Stream Endpoint Sink
|
||||
instances for Basic Audio Profile on a per connection basis.
|
||||
|
||||
config BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT
|
||||
int "Basic Audio Profile ASE Source count"
|
||||
default 2
|
||||
range 0 255
|
||||
help
|
||||
This option enables caching a number of Audio Stream Endpoint Source
|
||||
instances for Basic Audio Profile on a per connection basis.
|
||||
|
||||
config BT_BAP_UNICAST_CLIENT_ASE_SNK
|
||||
bool # hidden
|
||||
default y if BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
|
||||
|
||||
config BT_BAP_UNICAST_CLIENT_ASE_SRC
|
||||
bool # hidden
|
||||
default y if BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
|
||||
|
||||
endif # BT_BAP_UNICAST_CLIENT
|
||||
|
||||
config BT_BAP_BROADCAST_SOURCE
|
||||
bool "Bluetooth Broadcast Source Audio Support"
|
||||
select BT_ISO_BROADCASTER
|
||||
help
|
||||
This option enables support for Bluetooth Broadcast Source Audio using
|
||||
Isochronous channels.
|
||||
|
||||
if BT_BAP_BROADCAST_SOURCE
|
||||
|
||||
config BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT
|
||||
int "Basic Audio Broadcast Source subgroup count"
|
||||
default 1
|
||||
range 1 BT_ISO_MAX_CHAN if BT_ISO_MAX_CHAN < 31
|
||||
range 1 31
|
||||
help
|
||||
This option sets the maximum number of subgroups per broadcast source
|
||||
to support.
|
||||
|
||||
config BT_BAP_BROADCAST_SRC_COUNT
|
||||
int "Basic Audio Broadcaster source count"
|
||||
default 1
|
||||
range 1 BT_ISO_MAX_BIG
|
||||
help
|
||||
This option sets the number of broadcast sources to support.
|
||||
One broadcast source can send multiple streams
|
||||
(up to BT_BAP_BROADCAST_SRC_STREAM_COUNT per broadcast source).
|
||||
|
||||
|
||||
config BT_BAP_BROADCAST_SRC_STREAM_COUNT
|
||||
int "Basic Audio Broadcast Source Stream count"
|
||||
default 1
|
||||
range 1 BT_ISO_MAX_CHAN if BT_ISO_MAX_CHAN < 31
|
||||
range 1 31
|
||||
help
|
||||
This option sets the maximum number of streams per broadcast source
|
||||
to support.
|
||||
|
||||
endif # BT_BAP_BROADCAST_SOURCE
|
||||
|
||||
config BT_BAP_BROADCAST_SINK
|
||||
bool "Bluetooth Broadcast Sink Audio Support"
|
||||
select BT_ISO_SYNC_RECEIVER
|
||||
select BT_PAC_SNK
|
||||
depends on BT_BAP_SCAN_DELEGATOR
|
||||
help
|
||||
This option enables support for Bluetooth Broadcast Sink Audio using
|
||||
Isochronous channels.
|
||||
|
||||
if BT_BAP_BROADCAST_SINK
|
||||
|
||||
config BT_BAP_BROADCAST_SNK_SUBGROUP_COUNT
|
||||
int "Basic Audio Profile Broadcast Sink subgroup count"
|
||||
default 1
|
||||
range 1 BT_BAP_BASS_MAX_SUBGROUPS
|
||||
help
|
||||
This option sets the maximum number of subgroups per broadcast sink
|
||||
to support.
|
||||
|
||||
config BT_BAP_BROADCAST_SNK_COUNT
|
||||
int "Basic Audio Broadcaster Sink count"
|
||||
default 1
|
||||
range 0 BT_ISO_MAX_BIG
|
||||
help
|
||||
This option sets the number of broadcast sinks to support.
|
||||
One broadcast sink can receive multiple streams
|
||||
(up to BT_BAP_BROADCAST_SNK_STREAM_COUNT per broadcast sink).
|
||||
|
||||
config BT_BAP_BROADCAST_SNK_STREAM_COUNT
|
||||
int "Basic Audio Broadcast Sink Stream count"
|
||||
depends on BT_BAP_BROADCAST_SNK_COUNT > 0
|
||||
default 1
|
||||
range 1 BT_ISO_MAX_CHAN if BT_ISO_MAX_CHAN < 31
|
||||
range 1 31
|
||||
help
|
||||
This option sets the maximum number of streams per broadcast sink
|
||||
to support.
|
||||
|
||||
endif # BT_BAP_BROADCAST_SINK
|
||||
|
||||
config BT_BAP_SCAN_DELEGATOR
|
||||
bool "Basic Audio Profile Scan Delegator role support"
|
||||
select BT_ISO_SYNC_RECEIVER
|
||||
help
|
||||
This option enables support for the Scan Delegator role and the
|
||||
Broadcast Audio Scan Service (BASS).
|
||||
|
||||
if BT_BAP_SCAN_DELEGATOR
|
||||
|
||||
config BT_BAP_SCAN_DELEGATOR_RECV_STATE_COUNT
|
||||
int "Scan Delegator Receive State Count"
|
||||
default 1
|
||||
range 1 3
|
||||
help
|
||||
Sets the number of receive state characteristics present on the
|
||||
server. Each characteristic may hold information to sync to a
|
||||
periodic advertise or a broadcast isochronous stream.
|
||||
|
||||
config BT_BAP_SCAN_DELEGATOR_BUF_TIMEOUT
|
||||
int "Milliseconds of timeout when handle concurrent access to the long read ASE buffer"
|
||||
range 0 1000
|
||||
default 50
|
||||
help
|
||||
The maximum number of milliseconds that the scan delegator implementation will wait
|
||||
before rejecting a read or dropping a notification if the scan delegator state is
|
||||
being accessed by another thread.
|
||||
|
||||
endif # BT_BAP_SCAN_DELEGATOR
|
||||
|
||||
config BT_BAP_BROADCAST_ASSISTANT
|
||||
bool "Basic Audio Profile Broadcast Assistant role support"
|
||||
select BT_ISO_SYNC_RECEIVER
|
||||
select BT_AUDIO
|
||||
help
|
||||
This option enables support for the Broadcast Assistant role.
|
||||
|
||||
if BT_BAP_BROADCAST_ASSISTANT
|
||||
|
||||
config BT_BAP_BROADCAST_ASSISTANT_RECV_STATE_COUNT
|
||||
int "Broadcast Assistant Max Receive State Count"
|
||||
default 1
|
||||
range 1 255
|
||||
help
|
||||
Sets the number of maximum receive stat characteristics that will be
|
||||
discovered and ready to use. Each characteristic may hold information
|
||||
to sync to a periodic advertise or a broadcast isochronous stream.
|
||||
|
||||
endif # BT_BAP_BROADCAST_ASSISTANT
|
||||
|
||||
config BT_BAP_DEBUG_STREAM_DATA
|
||||
bool "Bluetooth Audio Stream data debug"
|
||||
help
|
||||
Use this option to enable Bluetooth Audio Stream data debug logs for
|
||||
the Bluetooth Audio functionality. This will enable debug logs for all
|
||||
audio data received and sent.
|
||||
|
||||
config BT_BAP_STREAM
|
||||
# Virtual/hidden option
|
||||
bool
|
||||
default y if BT_ASCS || BT_BAP_UNICAST_CLIENT || \
|
||||
BT_BAP_BROADCAST_SOURCE || BT_BAP_BROADCAST_SINK
|
||||
|
||||
config BT_BAP_DEBUG_STREAM_SEQ_NUM
|
||||
bool "Bluetooth Audio Stream sequence number debug"
|
||||
default y
|
||||
help
|
||||
Use this option to enable Bluetooth Audio Stream sequence number debugging logs for
|
||||
the Bluetooth Audio functionality. This will provide a warning if the application
|
||||
provides unexpected sequence numbers.
|
||||
|
||||
config BT_BAP_BASE
|
||||
bool
|
||||
default y if BT_BAP_BROADCAST_SINK || BT_BAP_BROADCAST_ASSISTANT || BT_BAP_SCAN_DELEGATOR
|
||||
@@ -0,0 +1,58 @@
|
||||
# Bluetooth Audio - Common Audio Profile (CAP) options
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2022 Nordic Semiconductor ASA
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
config BT_CAP
|
||||
bool # hidden
|
||||
default y if BT_CAP_ACCEPTOR || BT_CAP_INITIATOR
|
||||
|
||||
config BT_CAP_ACCEPTOR
|
||||
bool "Common Audio Profile Acceptor Role Support"
|
||||
depends on BT_BAP_UNICAST_SERVER || (BT_BAP_BROADCAST_SINK && BT_BAP_SCAN_DELEGATOR)
|
||||
depends on BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE >= 4
|
||||
help
|
||||
Enabling this will enable the CAP Acceptor role. This instantiates the
|
||||
common audio service (CAS).
|
||||
|
||||
config BT_CAP_ACCEPTOR_SET_MEMBER
|
||||
bool "Common Audio Profile Acceptor Role Set Member support"
|
||||
depends on BT_CAP_ACCEPTOR
|
||||
depends on BT_CSIP_SET_MEMBER
|
||||
help
|
||||
Enabling this will allow a CAP acceptor to be a set member.
|
||||
Enabling this will require a manual register of the CAS service.
|
||||
Enabling will take one of the allocated CSIS instances
|
||||
(BT_CSIP_SET_MEMBER_MAX_INSTANCE_COUNT).
|
||||
|
||||
config BT_CAP_INITIATOR_UNICAST
|
||||
bool # hidden
|
||||
default y if BT_CAP_INITIATOR && BT_BAP_UNICAST_CLIENT
|
||||
|
||||
config BT_CAP_INITIATOR
|
||||
bool "Common Audio Profile Initiator Role Support"
|
||||
depends on (BT_BAP_UNICAST_CLIENT && BT_CSIP_SET_COORDINATOR) || BT_BAP_BROADCAST_SOURCE
|
||||
depends on BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE >= 4
|
||||
help
|
||||
Enabling this will enable the CAP Initiator role.
|
||||
|
||||
config BT_CAP_COMMANDER
|
||||
bool "Common Audio Profile Initiator Role Support"
|
||||
depends on (BT_BAP_BROADCAST_ASSISTANT && BT_BAP_SCAN_DELEGATOR && BT_CSIP_SET_COORDINATOR) || \
|
||||
(BT_BAP_SCAN_DELEGATOR && BT_CSIP_SET_COORDINATOR) || \
|
||||
(BT_VCP_VOL_CTLR && BT_CSIP_SET_COORDINATOR) || \
|
||||
(BT_MICP_MIC_CTLR && BT_CSIP_SET_COORDINATOR) || \
|
||||
BT_TBS_CLIENT || \
|
||||
BT_MCC
|
||||
help
|
||||
Enabling this will enable the CAP Initiator role.
|
||||
|
||||
config BT_CAP_HANDOVER
|
||||
bool "Common Audio Profile Handover Procedures"
|
||||
depends on BT_CAP_COMMANDER && BT_CAP_INITIATOR && BT_BAP_BROADCAST_ASSISTANT && \
|
||||
BT_BAP_BROADCAST_SOURCE && BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
|
||||
help
|
||||
Enable support for the CAP Handover procedures, allowing a device to switch between
|
||||
broadcast and unicast for a usecase.
|
||||
@@ -0,0 +1,52 @@
|
||||
# Bluetooth Audio - Call Control Profile (CCP) configuration options
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2024 Nordic Semiconductor ASA
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
config BT_CCP_CALL_CONTROL_CLIENT
|
||||
bool "Call Control Profile Client Support"
|
||||
depends on BT_TBS_CLIENT
|
||||
help
|
||||
This option enables support for the Call Control Profile Client which uses the Telephone
|
||||
Bearer Service (TBS) client to control calls on a remote device.
|
||||
|
||||
if BT_CCP_CALL_CONTROL_CLIENT
|
||||
|
||||
config BT_CCP_CALL_CONTROL_CLIENT_BEARER_COUNT
|
||||
int "Telephone bearer count"
|
||||
default 1
|
||||
range 1 255 if BT_TBS_CLIENT_TBS
|
||||
range 1 1
|
||||
help
|
||||
The number of supported telephone bearers on the CCP Call Control Client
|
||||
|
||||
endif # BT_CCP_CALL_CONTROL_CLIENT
|
||||
|
||||
config BT_CCP_CALL_CONTROL_SERVER
|
||||
bool "Call Control Profile Call Control Server Support"
|
||||
depends on BT_TBS
|
||||
help
|
||||
This option enables support for the Call Control Profile Call Control Server which uses
|
||||
the Telephone Bearer Service (TBS) to hold and control calls on a device.
|
||||
|
||||
if BT_CCP_CALL_CONTROL_SERVER
|
||||
|
||||
config BT_CCP_CALL_CONTROL_SERVER_BEARER_COUNT
|
||||
int "Telephone bearer count"
|
||||
default 1
|
||||
range 1 255
|
||||
help
|
||||
The number of supported telephone bearers on the CCP Call Control Server
|
||||
|
||||
config BT_CCP_CALL_CONTROL_SERVER_PROVIDER_NAME_MAX_LEN
|
||||
# The original BT_CCP_CALL_CONTROL_SERVER_PROVIDER_NAME_MAX_LENGTH is reported
|
||||
# as too long while running pre-commit check.
|
||||
int "The maximum length of the bearer provider name excluding null terminator"
|
||||
default BT_TBS_MAX_PROVIDER_NAME_LENGTH
|
||||
range 1 BT_TBS_MAX_PROVIDER_NAME_LENGTH
|
||||
help
|
||||
Sets the maximum length of the bearer provider name.
|
||||
|
||||
endif # BT_CCP_CALL_CONTROL_SERVER
|
||||
@@ -0,0 +1,95 @@
|
||||
# Bluetooth Audio - Broadcast Assistant configuration options
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2020 Bose Corporation
|
||||
# SPDX-FileCopyrightText: 2021 Nordic Semiconductor ASA
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
#################### Coordinated Set Identification Service ####################
|
||||
|
||||
config BT_CSIP_SET_MEMBER
|
||||
bool "Coordinated Set Identification Profile Set Member support"
|
||||
help
|
||||
This option enables support for Coordinated Set Identification
|
||||
Profile Set Member role and the Coordinated Set Identification
|
||||
Service.
|
||||
|
||||
if BT_CSIP_SET_MEMBER
|
||||
|
||||
config BT_CSIP_SET_MEMBER_TEST_SAMPLE_DATA
|
||||
bool "Coordinated Set Identification Service Test Sample Data"
|
||||
help
|
||||
Enable the use of the sample data defined by the CSIS spec SIRK.
|
||||
This will use the sample SIRK, prand and LTK.
|
||||
|
||||
WARNING: This option enables anyone to track and decrypt the SIRK
|
||||
(if encrypted) using public sample data.
|
||||
Should not be used for production builds.
|
||||
|
||||
config BT_CSIP_SET_MEMBER_ENC_SIRK_SUPPORT
|
||||
bool "Support for encrypted SIRK"
|
||||
default y
|
||||
help
|
||||
Enables support encrypting the SIRK.
|
||||
|
||||
config BT_CSIP_SET_MEMBER_MAX_INSTANCE_COUNT
|
||||
int "Coordinated Set Identification Profile max service instance count"
|
||||
default 1
|
||||
range 1 255
|
||||
help
|
||||
This option sets the maximum number of instances of Coordinated Set
|
||||
Identification Services. If the service is declared as primary service
|
||||
then only a single instance is possible.
|
||||
|
||||
Enabling BT_CAP_ACCEPTOR_SET_MEMBER will take one of the allocated
|
||||
instances.
|
||||
|
||||
config BT_CSIP_SET_MEMBER_SIRK_NOTIFIABLE
|
||||
bool "SIRK notifiable Support"
|
||||
help
|
||||
This option enables support for clients to be notified on SIRK changes.
|
||||
|
||||
config BT_CSIP_SET_MEMBER_SIZE_NOTIFIABLE
|
||||
bool "Set Size notifiable support"
|
||||
help
|
||||
This option enables support for clients to be notified on Set Size changes.
|
||||
|
||||
endif # BT_CSIP_SET_MEMBER
|
||||
|
||||
#################### Coordinated Set Identification Client ####################
|
||||
|
||||
config BT_CSIP_SET_COORDINATOR
|
||||
bool "Coordinated Set Identification Profile Set Coordinator Support"
|
||||
help
|
||||
This option enables support for Coordinated Set Identification
|
||||
Profile Set Coordinator.
|
||||
|
||||
if BT_CSIP_SET_COORDINATOR
|
||||
|
||||
config BT_CSIP_SET_COORDINATOR_TEST_SAMPLE_DATA
|
||||
bool "Coordinated Set Identification Service Test Sample Data"
|
||||
help
|
||||
Enable the use of the sample data defined by the CSIS spec.
|
||||
This will use the sample SIRK, prand and LTK.
|
||||
|
||||
WARNING: This option enables the client to use the sample data
|
||||
to locate members and decrypt the SIRK, and thus won't work
|
||||
with set members that are not using the sample data.
|
||||
Should not be used for production builds.
|
||||
|
||||
config BT_CSIP_SET_COORDINATOR_MAX_CSIS_INSTANCES
|
||||
int "Coordinated Set Identification Service Count"
|
||||
default 1
|
||||
range 1 3
|
||||
help
|
||||
Sets the number of service instances, which corresponds to the number
|
||||
of different sets the peer device may be in.
|
||||
|
||||
config BT_CSIP_SET_COORDINATOR_ENC_SIRK_SUPPORT
|
||||
bool "Support for encrypted SIRK"
|
||||
default y
|
||||
help
|
||||
Enables support encrypting the SIRK.
|
||||
|
||||
endif # BT_CSIP_SET_COORDINATOR
|
||||
@@ -0,0 +1,28 @@
|
||||
# Bluetooth Audio - Gaming Audio Profile (GMAP) options
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2023 Nordic Semiconductor ASA
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
config BT_GMAP_UGG_SUPPORTED
|
||||
bool # hidden
|
||||
default y if BT_CAP_INITIATOR && BT_BAP_UNICAST_CLIENT && BT_VCP_VOL_CTLR
|
||||
|
||||
config BT_GMAP_UGT_SUPPORTED
|
||||
bool # hidden
|
||||
default y if BT_CAP_ACCEPTOR && BT_BAP_UNICAST_SERVER
|
||||
|
||||
config BT_GMAP_BGS_SUPPORTED
|
||||
bool # hidden
|
||||
default y if BT_CAP_INITIATOR && BT_BAP_BROADCAST_SOURCE && BT_BAP_BROADCAST_ASSISTANT
|
||||
|
||||
config BT_GMAP_BGR_SUPPORTED
|
||||
bool # hidden
|
||||
default y if BT_CAP_ACCEPTOR && BT_BAP_BROADCAST_SINK && BT_VCP_VOL_REND
|
||||
|
||||
config BT_GMAP
|
||||
bool "Gaming Audio Profile"
|
||||
depends on BT_CAP_ACCEPTOR || BT_CAP_INITIATOR
|
||||
help
|
||||
Enabling this will enable GMAP.
|
||||
@@ -0,0 +1,59 @@
|
||||
# Bluetooth Audio - Hearing Access Service options
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2022 Codecoup
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
menuconfig BT_HAS
|
||||
bool "Hearing Access Service support"
|
||||
depends on BT_BAP_UNICAST_SERVER
|
||||
help
|
||||
This option enables support for Hearing Access Service.
|
||||
|
||||
if BT_HAS
|
||||
|
||||
config BT_HAS_FEATURES_NOTIFIABLE
|
||||
bool "Hearing Aid Features Notifiable Support"
|
||||
help
|
||||
This option enables support for clients to subscribe for notifications
|
||||
on the Hearing Aid Features characteristic.
|
||||
|
||||
config BT_HAS_PRESET_COUNT
|
||||
int "Preset record list size"
|
||||
default 2
|
||||
range 0 255
|
||||
help
|
||||
This option sets the number of Hearing Access Service Presets
|
||||
that can be registered. Setting this value to 0 disables Presets support.
|
||||
|
||||
config BT_HAS_PRESET_SUPPORT
|
||||
bool # hidden
|
||||
default y if BT_HAS_PRESET_COUNT > 0
|
||||
|
||||
if BT_HAS_PRESET_SUPPORT
|
||||
|
||||
config BT_HAS_PRESET_NAME_DYNAMIC
|
||||
bool "Allow to set preset name on runtime"
|
||||
help
|
||||
Enabling this option allows for runtime configuration of preset name.
|
||||
|
||||
config BT_HAS_PRESET_CONTROL_POINT_NOTIFIABLE
|
||||
bool "Preset Control Point Notifiable support (depends on EATT)"
|
||||
help
|
||||
This option enables support for clients to subscribe for notifications
|
||||
on the Hearing Aid Preset Control Point characteristic.
|
||||
|
||||
config BT_HAS_ACTIVE_PRESET_INDEX
|
||||
bool # hidden
|
||||
default y if BT_HAS_PRESET_SUPPORT
|
||||
help
|
||||
This option enables the Hearing Aid Active Preset Index characteristic.
|
||||
|
||||
endif # BT_HAS_PRESET_SUPPORT
|
||||
|
||||
endif # BT_HAS
|
||||
|
||||
config BT_HAS_CLIENT
|
||||
bool "Hearing Access Service Client support"
|
||||
help
|
||||
This option enables support for Hearing Access Service Client.
|
||||
@@ -0,0 +1,218 @@
|
||||
# Bluetooth Audio - Media control configuration options
|
||||
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2020-2022 Nordic Semiconductor
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
#### Media Control Service ################################
|
||||
|
||||
config BT_MCS
|
||||
bool "Media Control Service Support"
|
||||
depends on BT_MCTL_LOCAL_PLAYER_REMOTE_CONTROL
|
||||
help
|
||||
This option enables support for the Media Control Service.
|
||||
|
||||
#### Media Control Client ################################
|
||||
|
||||
config BT_MCC
|
||||
bool "Media Control Client Support"
|
||||
help
|
||||
This option enables support for the Media Control Client.
|
||||
|
||||
if BT_MCC
|
||||
|
||||
config BT_MCC_MEDIA_PLAYER_NAME_MAX
|
||||
int "Max length of media player name"
|
||||
default 20
|
||||
range 1 255
|
||||
help
|
||||
Sets the maximum number of bytes (including the null termination) of
|
||||
the name of the media player. If the name is longer, the media
|
||||
control client will truncate the name when reading it.
|
||||
|
||||
config BT_MCC_ICON_URL_MAX
|
||||
int "Max length of media player icon URL"
|
||||
default 40
|
||||
range 1 255
|
||||
help
|
||||
Sets the maximum number of bytes (including the null termination) of
|
||||
the media player icon URL. If the URL is longer, the media control
|
||||
client will truncate the name when reading it.
|
||||
|
||||
config BT_MCC_TRACK_TITLE_MAX
|
||||
int "Max length of the title of a track"
|
||||
default 40
|
||||
range 1 255
|
||||
help
|
||||
Sets the maximum number of bytes (including the null termination) of
|
||||
the title of any track in the media player. If the title is longer,
|
||||
the media control client will truncate the title when reading it.
|
||||
|
||||
config BT_MCC_SEGMENT_NAME_MAX
|
||||
int "Max length of the name of a track segment"
|
||||
default 25
|
||||
range 1 255
|
||||
help
|
||||
Sets the maximum number of bytes (including the null termination)
|
||||
of the name of any track segment in the media player. If the name is
|
||||
longer, the media control client will truncate the name when reading
|
||||
it.
|
||||
|
||||
config BT_MCC_OTS
|
||||
bool "Media Control Client support for Object Transfer Service (depends on OTS Client)"
|
||||
depends on BT_OTS_CLIENT
|
||||
help
|
||||
Use this option to configure support in the Media Control Client for
|
||||
an included Object Transfer Service in the Media Control Service.
|
||||
|
||||
if BT_MCC_OTS
|
||||
|
||||
config BT_MCC_OTC_OBJ_BUF_SIZE
|
||||
int "The size of the buffer used for OTC object in MCC"
|
||||
default 512
|
||||
range 1 65536
|
||||
help
|
||||
Sets the size (in octets) of the buffer used for receiving the content
|
||||
of objects.
|
||||
Should be set large enough to fit any expected object.
|
||||
|
||||
config BT_MCC_TOTAL_OBJ_CONTENT_MEM
|
||||
int "Total memory size to use for storing the content of objects"
|
||||
default 1
|
||||
range 0 65536
|
||||
help
|
||||
Sets the total memory size (in octets) to use for storing the content
|
||||
of objects.
|
||||
This is used for the total memory pool buffer size from which memory
|
||||
is allocated when reading object content.
|
||||
|
||||
config BT_MCC_TRACK_SEGS_MAX_CNT
|
||||
int "Maximum number of tracks segments in a track segment object"
|
||||
default 25
|
||||
range 0 500
|
||||
help
|
||||
Sets the maximum number of tracks segments in a track segment object.
|
||||
If the received object is bigger, the remaining data in the object
|
||||
will be ignored.
|
||||
|
||||
config BT_MCC_GROUP_RECORDS_MAX
|
||||
int "Maximum number of records in a group object"
|
||||
default 25
|
||||
range 0 500
|
||||
help
|
||||
Sets the maximum number of records in a group object. If the received
|
||||
group object has more records than this, the remaining records in the
|
||||
object will be ignored.
|
||||
|
||||
endif # BT_MCC_OTS
|
||||
|
||||
config BT_MCC_SHELL
|
||||
bool "Media Control Client Shell Support"
|
||||
help
|
||||
This option enables shell support for the Media Control Client.
|
||||
|
||||
config BT_MCC_MINIMAL
|
||||
bool "Minimal Media Control Client without optional procedures"
|
||||
help
|
||||
This option disables all optional procedures in the Media Control Client.
|
||||
|
||||
config BT_MCC_READ_MEDIA_PLAYER_ICON_URL
|
||||
bool "Support reading Media Player Icon URL"
|
||||
default y if !BT_MCC_MINIMAL
|
||||
help
|
||||
This option enables support for Read Media Information procedure
|
||||
optionally read the Media Player Icon URL.
|
||||
|
||||
config BT_MCC_READ_TRACK_TITLE
|
||||
bool "Support reading Track Title"
|
||||
default y if !BT_MCC_MINIMAL
|
||||
help
|
||||
This option enables support for reading Track Title.
|
||||
|
||||
config BT_MCC_READ_TRACK_TITLE_ENABLE_SUBSCRIPTION
|
||||
bool "Support to enable or disable the subscription of Track Title"
|
||||
default y if !BT_MCC_MINIMAL
|
||||
help
|
||||
This option enables support for the subscription of Track Title.
|
||||
|
||||
config BT_MCC_READ_TRACK_DURATION
|
||||
bool "Support reading Track Duration"
|
||||
default y if !BT_MCC_MINIMAL
|
||||
help
|
||||
This option enables support for reading Track Duration.
|
||||
|
||||
config BT_MCC_READ_TRACK_POSITION
|
||||
bool "Support reading Track Position"
|
||||
default y if !BT_MCC_MINIMAL
|
||||
help
|
||||
This option enables support for reading Track Position.
|
||||
|
||||
config BT_MCC_SET_TRACK_POSITION
|
||||
bool "Support setting Track Position"
|
||||
default y if !BT_MCC_MINIMAL
|
||||
help
|
||||
This option enables support for setting Track Position.
|
||||
|
||||
config BT_MCC_READ_PLAYBACK_SPEED
|
||||
bool "Support reading Playback Speed"
|
||||
default y if !BT_MCC_MINIMAL
|
||||
help
|
||||
This option enables support for reading Playback Speed.
|
||||
|
||||
config BT_MCC_SET_PLAYBACK_SPEED
|
||||
bool "Support setting Playback Speed"
|
||||
default y if !BT_MCC_MINIMAL
|
||||
help
|
||||
This option enables support for setting Playback Speed.
|
||||
|
||||
config BT_MCC_READ_SEEKING_SPEED
|
||||
bool "Support reading Seeking Speed"
|
||||
default y if !BT_MCC_MINIMAL
|
||||
help
|
||||
This option enables support for reading Seeking Speed.
|
||||
|
||||
config BT_MCC_READ_PLAYING_ORDER
|
||||
bool "Support reading Playing Order"
|
||||
default y if !BT_MCC_MINIMAL
|
||||
help
|
||||
This option enables support for reading Playing Order.
|
||||
|
||||
config BT_MCC_SET_PLAYING_ORDER
|
||||
bool "Support setting Playing Order"
|
||||
default y if !BT_MCC_MINIMAL
|
||||
help
|
||||
This option enables support for setting Playing Order.
|
||||
|
||||
config BT_MCC_READ_PLAYING_ORDER_SUPPORTED
|
||||
bool "Support reading Playing Order Supported"
|
||||
default y if !BT_MCC_MINIMAL
|
||||
help
|
||||
This option enables support for reading Playing Order Supported.
|
||||
|
||||
config BT_MCC_READ_MEDIA_STATE
|
||||
bool "Support reading Media State"
|
||||
default y if !BT_MCC_MINIMAL
|
||||
help
|
||||
This option enables support for reading Media State.
|
||||
|
||||
config BT_MCC_SET_MEDIA_CONTROL_POINT
|
||||
bool "Support setting Media Control Point"
|
||||
default y if !BT_MCC_MINIMAL
|
||||
help
|
||||
This option enables support for setting Media Control Point.
|
||||
|
||||
config BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED
|
||||
bool "Support reading Media Control Point Opcodes Supported"
|
||||
default y if !BT_MCC_MINIMAL
|
||||
help
|
||||
This option enables support for reading Media Control Point Opcodes Supported.
|
||||
|
||||
config BT_MCC_READ_CONTENT_CONTROL_ID
|
||||
bool "Support reading Content Control ID"
|
||||
default y if !BT_MCC_MINIMAL
|
||||
help
|
||||
This option enables support for reading Content Control ID.
|
||||
|
||||
endif # BT_MCC
|
||||
@@ -0,0 +1,59 @@
|
||||
# Bluetooth Audio - Media control configuration options
|
||||
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2022 Nordic Semiconductor
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
# TODO: Decide, and add, top-level namespace prefix (currently none) to symbols.
|
||||
# Dependent upon where the module will be placed.
|
||||
|
||||
config BT_MCTL
|
||||
bool "Support for media player control"
|
||||
help
|
||||
Enables support for control of local and remote media players
|
||||
To enable support for control of a local media player, support for
|
||||
local media player must be enabled
|
||||
|
||||
if BT_MCTL
|
||||
|
||||
config BT_MCTL_LOCAL_PLAYER_CONTROL
|
||||
bool "Support for control of local media player"
|
||||
help
|
||||
This option enables support for control of a local media player
|
||||
|
||||
config BT_MCTL_LOCAL_PLAYER_LOCAL_CONTROL
|
||||
bool "Support for local control of local media player"
|
||||
default y
|
||||
depends on BT_MCTL_LOCAL_PLAYER_CONTROL
|
||||
help
|
||||
This option enables support for local application control of local
|
||||
media players
|
||||
|
||||
config BT_MCTL_LOCAL_PLAYER_REMOTE_CONTROL
|
||||
bool "Support for remote control of local media players"
|
||||
depends on BT_MCTL_LOCAL_PLAYER_CONTROL
|
||||
help
|
||||
This option enables support for remote control of local media
|
||||
players.
|
||||
|
||||
config BT_MCTL_REMOTE_PLAYER_CONTROL
|
||||
bool "Support for control of remote media player"
|
||||
default y
|
||||
# TODO: Remove dependency on BT_MCC once MCC has been reworked
|
||||
depends on BT_MCC
|
||||
help
|
||||
This options enables support for control of a remote media player.
|
||||
|
||||
config BT_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS
|
||||
bool "Support for accessing objects on remote player"
|
||||
depends on BT_MCTL_REMOTE_PLAYER_CONTROL
|
||||
default y
|
||||
# TODO: Remove dependency on BT_MCC_OTS once MCC has been reworked
|
||||
depends on BT_MCC_OTS
|
||||
help
|
||||
This options enables support for accessing objects (tracks, groups,
|
||||
search results, ...) on a remote media player
|
||||
|
||||
endif # BT_MCTL
|
||||
@@ -0,0 +1,62 @@
|
||||
# Bluetooth Audio - Microphone Control Service options
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2020 Bose Corporation
|
||||
# SPDX-FileCopyrightText: 2020-2022 Nordic Semiconductor ASA
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
########### Microphone Control Profile Microphone Device ###########
|
||||
|
||||
config BT_MICP_MIC_DEV
|
||||
bool "Microphone Control Profile Microphone Device Support"
|
||||
help
|
||||
This option enables support for Microphone Control Profile
|
||||
Microphone Device.
|
||||
|
||||
if BT_MICP_MIC_DEV
|
||||
|
||||
config BT_MICP_MIC_DEV_AICS_INSTANCE_COUNT
|
||||
int "Audio Input Control Service instance count for \
|
||||
Microphone Control Service Microphone Device"
|
||||
default 0
|
||||
range 0 BT_AICS_MAX_INSTANCE_COUNT
|
||||
help
|
||||
This option sets the number of instances of Audio Input Control
|
||||
Services for Microphone Control Profile Microphone Device.
|
||||
|
||||
config BT_MICP_MIC_DEV_AICS
|
||||
bool # Hidden
|
||||
default y if BT_MICP_MIC_DEV_AICS_INSTANCE_COUNT > 0
|
||||
help
|
||||
This hidden option makes it possible to easily check if AICS is
|
||||
enabled for Microphone Control Profile Microphone Device.
|
||||
|
||||
endif # BT_MICP_MIC_DEV
|
||||
|
||||
########### Microphone Control Profile Microphone Controller ###########
|
||||
|
||||
config BT_MICP_MIC_CTLR
|
||||
bool "Microphone Control Profile Microphone Controller Support"
|
||||
help
|
||||
This option enables support for the Microphone Control Profile
|
||||
Microphone Controller role
|
||||
|
||||
if BT_MICP_MIC_CTLR
|
||||
|
||||
config BT_MICP_MIC_CTLR_MAX_AICS_INST
|
||||
int "Maximum number of Audio Input Control Service instances to setup"
|
||||
default 0
|
||||
range 0 BT_AICS_CLIENT_MAX_INSTANCE_COUNT
|
||||
help
|
||||
Sets the maximum number of Audio Input Control Service (AICS)
|
||||
instances to setup and use.
|
||||
|
||||
config BT_MICP_MIC_CTLR_AICS
|
||||
bool # Hidden
|
||||
default y if BT_MICP_MIC_CTLR_MAX_AICS_INST > 0
|
||||
help
|
||||
This hidden option makes it possible to easily check if AICS is
|
||||
enabled for MICP client.
|
||||
|
||||
endif # BT_MICP_MIC_CTLR
|
||||
@@ -0,0 +1,110 @@
|
||||
# Bluetooth Audio - Media player configuration options
|
||||
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2022 Nordic Semiconductor
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
config BT_MPL
|
||||
bool "Support for media player"
|
||||
help
|
||||
Enables support for media player
|
||||
Note that the provided media player is a sample that only provides a
|
||||
mock-up with no actual media being played.
|
||||
For real media playback, the sample must be extended, hooked up to a
|
||||
real media player or replaced with a real media player.
|
||||
|
||||
if BT_MPL
|
||||
|
||||
config BT_MPL_MEDIA_PLAYER_NAME
|
||||
string "Media Player Name"
|
||||
default "Player0"
|
||||
help
|
||||
Use this option to set the name of the media player.
|
||||
|
||||
config BT_MPL_MEDIA_PLAYER_NAME_MAX
|
||||
int "Max length of media player name"
|
||||
default 20
|
||||
range 1 255
|
||||
help
|
||||
Sets the maximum number of bytes (including the null termination) of
|
||||
the name of the media player.
|
||||
|
||||
config BT_MPL_ICON_URL
|
||||
string "Media player Icon URL"
|
||||
default "http://server.some.where/path/icon.png"
|
||||
help
|
||||
Use this option to set the URL of the Media Player Icon.
|
||||
|
||||
config BT_MPL_ICON_URL_MAX
|
||||
int "Max length of media player icon URL"
|
||||
default 40
|
||||
range 1 255
|
||||
help
|
||||
Sets the maximum number of bytes (including the null termination) of
|
||||
the media player icon URL.
|
||||
|
||||
config BT_MPL_TRACK_TITLE_MAX
|
||||
int "Max length of the title of a track"
|
||||
default 40
|
||||
range 1 255
|
||||
help
|
||||
Sets the maximum number of bytes (including the null termination) of
|
||||
the title of any track in the media player.
|
||||
|
||||
config BT_MPL_SEGMENT_NAME_MAX
|
||||
int "Max length of the name of a track segment"
|
||||
default 25
|
||||
range 1 255
|
||||
help
|
||||
Sets the maximum number of bytes (including the null termination)
|
||||
of the name of any track segment in the media player.
|
||||
|
||||
config BT_MPL_GROUP_TITLE_MAX
|
||||
int "Max length of the title of a group of tracks"
|
||||
default BT_MPL_TRACK_TITLE_MAX
|
||||
range 1 255
|
||||
help
|
||||
Sets the maximum number of bytes (including the null termination) of
|
||||
the title of any group in the media player.
|
||||
|
||||
config BT_MPL_OBJECTS
|
||||
bool "Support for media player objects"
|
||||
depends on BT_OTS
|
||||
# TODO: Temporarily depends also on BT_MCS, to avoid issues with the
|
||||
# bt_mcs_get_ots() call
|
||||
depends on BT_MCS
|
||||
# OTS shall be instantiated as a Secondary Service and shall be
|
||||
# included in MCS or GMCS.
|
||||
help
|
||||
Enables support for objects in the media player
|
||||
Objects are used to give/get more information about e.g. media tracks.
|
||||
Requires the Object Transfer Service
|
||||
|
||||
if BT_MPL_OBJECTS
|
||||
|
||||
config BT_MPL_MAX_OBJ_SIZE
|
||||
int "Total memory size to use for storing the content of objects"
|
||||
default 127
|
||||
range 0 65536
|
||||
help
|
||||
Sets the total memory size (in octets) to use for storing the content of objects.
|
||||
This is used for the total memory pool buffer size from which memory
|
||||
is allocated when sending object content.
|
||||
|
||||
config BT_MPL_ICON_BITMAP_SIZE
|
||||
int "Media player Icon bitmap object size"
|
||||
default 127
|
||||
help
|
||||
This option sets the maximum size (in octets) of the icon object.
|
||||
|
||||
config BT_MPL_TRACK_MAX_SIZE
|
||||
int "Maximum size for a track object"
|
||||
default 127
|
||||
help
|
||||
This option sets the maximum size (in octets) of a track object.
|
||||
|
||||
endif # BT_MPL_OBJECTS
|
||||
|
||||
endif # BT_MPL
|
||||
@@ -0,0 +1,87 @@
|
||||
# Bluetooth Audio - Published Audio Capabilities configuration options
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2022 Nordic Semiconductor ASA
|
||||
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
config BT_PAC_SNK
|
||||
bool "Sink PAC Characteristic Support"
|
||||
help
|
||||
This option enables support for Sink Published Audio Capabilities.
|
||||
|
||||
if BT_PAC_SNK
|
||||
|
||||
config BT_PAC_SNK_NOTIFIABLE
|
||||
bool "Sink PAC Notifiable Support"
|
||||
help
|
||||
This option enables support for clients to be notified on the Sink
|
||||
PAC Characteristic changes.
|
||||
|
||||
config BT_PAC_SNK_LOC
|
||||
bool "Sink PAC Location Support"
|
||||
default y
|
||||
help
|
||||
This option enables support for Sink PAC Location Characteristic.
|
||||
|
||||
config BT_PAC_SNK_LOC_WRITEABLE
|
||||
bool "Sink PAC Location Writable Support"
|
||||
depends on BT_PAC_SNK_LOC
|
||||
help
|
||||
This option enables support for clients to write to the Sink PAC
|
||||
Location Characteristic.
|
||||
|
||||
config BT_PAC_SNK_LOC_NOTIFIABLE
|
||||
bool "Sink Audio Location Notifiable Support"
|
||||
depends on BT_PAC_SNK_LOC
|
||||
help
|
||||
This option enables support for clients to be notified on the Sink
|
||||
Audio Location Characteristic changes.
|
||||
|
||||
endif # BT_PACS_SNK
|
||||
|
||||
config BT_PAC_SRC
|
||||
bool "Source PAC Characteristic Support"
|
||||
help
|
||||
This option enables support for Source Published Audio Capabilities.
|
||||
|
||||
if BT_PAC_SRC
|
||||
|
||||
config BT_PAC_SRC_NOTIFIABLE
|
||||
bool "Source PAC Notifiable Support"
|
||||
help
|
||||
This option enables support for clients to be notified on the Source
|
||||
PAC Characteristic changes.
|
||||
|
||||
config BT_PAC_SRC_LOC
|
||||
bool "Source PAC Location Support"
|
||||
default y
|
||||
help
|
||||
This option enables support for Source PAC Location Characteristic.
|
||||
|
||||
config BT_PAC_SRC_LOC_WRITEABLE
|
||||
bool "Source PAC Location Writable Support"
|
||||
depends on BT_PAC_SRC_LOC
|
||||
help
|
||||
This option enables support for clients to write to the Source PAC
|
||||
Location Characteristic.
|
||||
|
||||
config BT_PAC_SRC_LOC_NOTIFIABLE
|
||||
bool "Source Audio Location Notifiable Support"
|
||||
depends on BT_PAC_SRC_LOC
|
||||
help
|
||||
This option enables support for clients to be notified on the Source
|
||||
Audio Location Characteristic changes.
|
||||
|
||||
endif # BT_PAC_SRC
|
||||
|
||||
config BT_PACS
|
||||
bool # hidden
|
||||
default y if BT_PAC_SNK || BT_PAC_SRC
|
||||
|
||||
config BT_PACS_SUPPORTED_CONTEXT_NOTIFIABLE
|
||||
bool "Supported Audio Context Notifiable Support"
|
||||
depends on BT_PACS
|
||||
help
|
||||
This option enables support for clients to be notified on the
|
||||
Supported Audio Contexts Characteristic changes.
|
||||
@@ -0,0 +1,11 @@
|
||||
# Bluetooth Audio - Public Broadcast Profile (PBP) options
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2023 NXP
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
config BT_PBP
|
||||
bool "Public Broadcast Profile"
|
||||
help
|
||||
Enabling this will enable PBP.
|
||||
@@ -0,0 +1,252 @@
|
||||
# Bluetooth Audio - Call control configuration options
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2020 Bose Corporation
|
||||
# SPDX-FileCopyrightText: 2024 Nordic Semiconductor ASA
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##################### Telephone Bearer Service #####################
|
||||
|
||||
config BT_TBS
|
||||
bool "Telephone Bearer Service Support"
|
||||
select BT_AUDIO
|
||||
help
|
||||
This option enables support for Telephone Bearer Service. By default this only
|
||||
initializes the GTBS service. If specific TBS services are wanted, they need to be
|
||||
enabled by setting BT_TBS_BEARER_COUNT to a non-zero value.
|
||||
|
||||
if BT_TBS
|
||||
|
||||
config BT_TBS_SUPPORTED_FEATURES
|
||||
int "Telephone Bearer Service Supported Features"
|
||||
default 1
|
||||
range 0 3
|
||||
help
|
||||
Bitfield to set supported features of the bearer.
|
||||
Bit 0: Local Hold and Retrieve
|
||||
Bit 1: Join calls within Telephone Bearer Service
|
||||
|
||||
config BT_TBS_MAX_CALLS
|
||||
int "Telephone Bearer Service Maximum Number Of Calls Supported"
|
||||
default 3
|
||||
range 1 16
|
||||
help
|
||||
Sets the maximum number of calls the service supports per bearer.
|
||||
|
||||
config BT_TBS_BEARER_COUNT
|
||||
int "How many bearer instances the device instantiates"
|
||||
default 0
|
||||
range 0 255
|
||||
help
|
||||
Sets the number of TBS instances that are instantiated
|
||||
|
||||
config BT_TBS_MAX_SCHEME_LIST_LENGTH
|
||||
int "The maximum length of the URI scheme list"
|
||||
default 30
|
||||
range 0 512
|
||||
help
|
||||
Sets the maximum length of the URI scheme list.
|
||||
|
||||
endif # BT_TBS
|
||||
|
||||
##################### Call Control Client #####################
|
||||
|
||||
config BT_TBS_CLIENT_GTBS
|
||||
bool "Generic Telephone Bearer Service client support"
|
||||
help
|
||||
This option enables support for the GTBS-oriented Call Control client.
|
||||
|
||||
config BT_TBS_CLIENT_TBS
|
||||
bool "Telephone Bearer Service client support"
|
||||
help
|
||||
This option enables support for the TBS-oriented Call Control client.
|
||||
|
||||
config BT_TBS_CLIENT
|
||||
bool # hidden
|
||||
default y if BT_TBS_CLIENT_GTBS || BT_TBS_CLIENT_TBS
|
||||
select BT_AUDIO
|
||||
|
||||
if BT_TBS_CLIENT
|
||||
|
||||
config BT_TBS_CLIENT_MAX_CALLS
|
||||
int "Maximum Number Of Calls Supported"
|
||||
default 1
|
||||
help
|
||||
Sets the maximum number of calls the client supports per TBS instance.
|
||||
|
||||
config BT_TBS_CLIENT_MAX_TBS_INSTANCES
|
||||
int "Maximum number of TBS instances to setup"
|
||||
depends on BT_TBS_CLIENT_TBS
|
||||
default 1
|
||||
range 1 3
|
||||
help
|
||||
Sets the maximum number of Telephone Bearer Service (TBS)
|
||||
instances to setup and use.
|
||||
|
||||
config BT_TBS_CLIENT_MINIMAL
|
||||
bool "Minimal TBS Client without optional procedures"
|
||||
default n
|
||||
help
|
||||
This option disables all optional procedures in the TBS Client.
|
||||
|
||||
config BT_TBS_CLIENT_BEARER_PROVIDER_NAME
|
||||
bool "Support reading Bearer Provider Name"
|
||||
default y if !BT_TBS_CLIENT_MINIMAL
|
||||
help
|
||||
This option enables support for reading Bearer Provider Name.
|
||||
|
||||
config BT_TBS_CLIENT_BEARER_UCI
|
||||
bool "Support reading Bearer UCI"
|
||||
default y if !BT_TBS_CLIENT_MINIMAL
|
||||
help
|
||||
This option enables support for reading Bearer UCI.
|
||||
|
||||
config BT_TBS_CLIENT_BEARER_TECHNOLOGY
|
||||
bool "Support reading Bearer Technology"
|
||||
default y if !BT_TBS_CLIENT_MINIMAL
|
||||
help
|
||||
This option enables support for reading Bearer Technology.
|
||||
|
||||
config BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST
|
||||
bool "Support reading Bearer URI Schemes Supported List"
|
||||
default y if !BT_TBS_CLIENT_MINIMAL
|
||||
help
|
||||
This option enables support for reading Bearer URI Schemes Supported
|
||||
List.
|
||||
|
||||
config BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH
|
||||
bool "Support reading Bearer Signal Strength"
|
||||
default y if !BT_TBS_CLIENT_MINIMAL
|
||||
help
|
||||
This option enables support for reading Bearer Signal Strength.
|
||||
|
||||
config BT_TBS_CLIENT_READ_BEARER_SIGNAL_INTERVAL
|
||||
bool "Support reading Bearer Signal Strength Reporting Interval"
|
||||
default y if !BT_TBS_CLIENT_MINIMAL
|
||||
help
|
||||
This option enables support for reading Bearer Signal Strength
|
||||
Reporting Interval.
|
||||
|
||||
config BT_TBS_CLIENT_SET_BEARER_SIGNAL_INTERVAL
|
||||
bool "Support setting Bearer Signal Strength Reporting Interval"
|
||||
default y if !BT_TBS_CLIENT_MINIMAL
|
||||
help
|
||||
This option enables support for setting Bearer Signal Strength
|
||||
Reporting Interval.
|
||||
|
||||
config BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS
|
||||
bool "Support reading Bearer List Current Calls"
|
||||
default y if !BT_TBS_CLIENT_MINIMAL
|
||||
help
|
||||
This option enables support for reading Bearer List Current Calls.
|
||||
|
||||
config BT_TBS_CLIENT_CCID
|
||||
bool "Support reading Content Control ID"
|
||||
default y if !BT_TBS_CLIENT_MINIMAL
|
||||
help
|
||||
This option enables support for reading Content Control ID.
|
||||
|
||||
config BT_TBS_CLIENT_INCOMING_URI
|
||||
bool "Support reading Incoming Call Target Bearer URI"
|
||||
default y if !BT_TBS_CLIENT_MINIMAL
|
||||
help
|
||||
This option enables support for reading Incoming Call Target Bearer
|
||||
URI.
|
||||
|
||||
config BT_TBS_CLIENT_STATUS_FLAGS
|
||||
bool "Support reading Status Flags"
|
||||
default y if !BT_TBS_CLIENT_MINIMAL
|
||||
help
|
||||
This option enables support for reading Status Flags.
|
||||
|
||||
config BT_TBS_CLIENT_CP_PROCEDURES
|
||||
bool # hidden
|
||||
default y
|
||||
depends on (BT_TBS_CLIENT_ACCEPT_CALL || \
|
||||
BT_TBS_CLIENT_TERMINATE_CALL || \
|
||||
BT_TBS_CLIENT_HOLD_CALL || \
|
||||
BT_TBS_CLIENT_RETRIEVE_CALL || \
|
||||
BT_TBS_CLIENT_ORIGINATE_CALL || \
|
||||
BT_TBS_CLIENT_JOIN_CALLS)
|
||||
help
|
||||
This hidden option indicates that there are at least one control
|
||||
point procedure available.
|
||||
When this option is disabled it indicates that the control point can
|
||||
be optimized away.
|
||||
|
||||
config BT_TBS_CLIENT_ACCEPT_CALL
|
||||
bool "Support Accept Call"
|
||||
default y if !BT_TBS_CLIENT_MINIMAL
|
||||
help
|
||||
This option enables support for answering an incoming call.
|
||||
|
||||
config BT_TBS_CLIENT_TERMINATE_CALL
|
||||
bool "Support Terminate Call"
|
||||
default y if !BT_TBS_CLIENT_MINIMAL
|
||||
help
|
||||
This option enables support for terminating a call.
|
||||
|
||||
config BT_TBS_CLIENT_HOLD_CALL
|
||||
bool "Support Hold Call"
|
||||
default y if !BT_TBS_CLIENT_MINIMAL
|
||||
help
|
||||
This option enables support for putting a call on hold.
|
||||
|
||||
config BT_TBS_CLIENT_RETRIEVE_CALL
|
||||
bool "Support Retrieve Call"
|
||||
default y if !BT_TBS_CLIENT_MINIMAL
|
||||
help
|
||||
This option enables support for retrieving a call on hold.
|
||||
|
||||
config BT_TBS_CLIENT_ORIGINATE_CALL
|
||||
bool "Support Originate Call"
|
||||
default y if !BT_TBS_CLIENT_MINIMAL
|
||||
help
|
||||
This option enables support for originating a call.
|
||||
|
||||
config BT_TBS_CLIENT_JOIN_CALLS
|
||||
bool "Support Join Calls"
|
||||
depends on BT_TBS_CLIENT_MAX_CALLS > 1
|
||||
default y if !BT_TBS_CLIENT_MINIMAL
|
||||
help
|
||||
This option enables support for joining calls.
|
||||
|
||||
config BT_TBS_CLIENT_OPTIONAL_OPCODES
|
||||
bool "Support reading Optional Opcodes"
|
||||
default y if !BT_TBS_CLIENT_MINIMAL
|
||||
help
|
||||
This option enables support for reading Optional Opcodes.
|
||||
|
||||
config BT_TBS_CLIENT_INCOMING_CALL
|
||||
bool "Support reading Incoming Call"
|
||||
default y if !BT_TBS_CLIENT_MINIMAL
|
||||
help
|
||||
This option enables support for reading Incoming Call.
|
||||
|
||||
config BT_TBS_CLIENT_CALL_FRIENDLY_NAME
|
||||
bool "Support reading Call Friendly Name"
|
||||
default y if !BT_TBS_CLIENT_MINIMAL
|
||||
help
|
||||
This option enables support for reading Call Friendly Name.
|
||||
|
||||
endif # BT_TBS_CLIENT
|
||||
|
||||
if BT_TBS || BT_TBS_CLIENT
|
||||
|
||||
config BT_TBS_MAX_URI_LENGTH
|
||||
int "The maximum length of the call URI supported"
|
||||
default 30
|
||||
range 4 253
|
||||
help
|
||||
Sets the maximum length of the call URI supported. Note that if this
|
||||
value is lower than a call URI, the call request will be rejected.
|
||||
|
||||
config BT_TBS_MAX_PROVIDER_NAME_LENGTH
|
||||
int "The maximum length of the bearer provider name"
|
||||
default 30
|
||||
range 1 512
|
||||
help
|
||||
Sets the maximum length of the bearer provider name.
|
||||
|
||||
endif # BT_TBS || BT_TBS_CLIENT
|
||||
@@ -0,0 +1,38 @@
|
||||
# Bluetooth Audio - Telephony and Media Audio Profile (TMAP) options
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2023 NXP
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
config BT_TMAP_CG_SUPPORTED
|
||||
bool # hidden
|
||||
default y if (BT_CAP_INITIATOR && BT_CAP_COMMANDER && BT_BAP_UNICAST_CLIENT && \
|
||||
BT_BAP_UNICAST_CLIENT_ASE_SRC > 0 && BT_BAP_UNICAST_CLIENT_ASE_SNK > 0 && \
|
||||
BT_VCP_VOL_CTLR && BT_TBS)
|
||||
|
||||
config BT_TMAP_CT_SUPPORTED
|
||||
bool # hidden
|
||||
default y if BT_CAP_ACCEPTOR && (BT_ASCS_ASE_SNK > 0 || BT_ASCS_ASE_SRC > 0)
|
||||
|
||||
config BT_TMAP_UMS_SUPPORTED
|
||||
bool # hidden
|
||||
default y if (BT_CAP_INITIATOR && BT_CAP_COMMANDER && BT_BAP_UNICAST_CLIENT && \
|
||||
BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 && BT_VCP_VOL_CTLR && BT_MCS)
|
||||
|
||||
config BT_TMAP_UMR_SUPPORTED
|
||||
bool # hidden
|
||||
default y if BT_CAP_ACCEPTOR && BT_ASCS_ASE_SNK > 0 && BT_VCP_VOL_REND
|
||||
|
||||
config BT_TMAP_BMS_SUPPORTED
|
||||
bool # hidden
|
||||
default y if BT_CAP_INITIATOR && BT_BAP_BROADCAST_SOURCE
|
||||
|
||||
config BT_TMAP_BMR_SUPPORTED
|
||||
bool # hidden
|
||||
default y if BT_CAP_ACCEPTOR && BT_BAP_BROADCAST_SINK && BT_VCP_VOL_REND
|
||||
|
||||
config BT_TMAP
|
||||
bool "Telephony and Media Audio Profile"
|
||||
depends on BT_CAP_ACCEPTOR || BT_CAP_INITIATOR
|
||||
help
|
||||
Enabling this will enable TMAP.
|
||||
@@ -0,0 +1,97 @@
|
||||
# Bluetooth Audio - Volume Control Profile configuration options
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2020 Bose Corporation
|
||||
# SPDX-FileCopyrightText: 2020-2022 Nordic Semiconductor ASA
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
################### Volume Control Profile Volume Renderer ###################
|
||||
|
||||
config BT_VCP_VOL_REND
|
||||
bool "Volume Control Profile Volume Renderer Support"
|
||||
help
|
||||
This option enables support for Volume Control Profile Volume Renderer
|
||||
role and the Volume Control Service.
|
||||
|
||||
if BT_VCP_VOL_REND
|
||||
|
||||
config BT_VCP_VOL_REND_VOCS_INSTANCE_COUNT
|
||||
int "Volume Offset Control Service instance count"
|
||||
default 0
|
||||
range 0 BT_VOCS_MAX_INSTANCE_COUNT
|
||||
help
|
||||
This option sets the number of instances of Volume Offset Control
|
||||
Services.
|
||||
|
||||
config BT_VCP_VOL_REND_VOCS
|
||||
bool # Hidden
|
||||
default y if BT_VCP_VOL_REND_VOCS_INSTANCE_COUNT > 0
|
||||
help
|
||||
This hidden option makes it possible to easily check if VOCS is
|
||||
enabled for VCS.
|
||||
|
||||
config BT_VCP_VOL_REND_AICS_INSTANCE_COUNT
|
||||
int "Audio Input Control Service instance count for VCS"
|
||||
default 0
|
||||
range 0 BT_AICS_MAX_INSTANCE_COUNT
|
||||
help
|
||||
This option sets the number of instances of Audio Input Control
|
||||
Services for VCS.
|
||||
|
||||
config BT_VCP_VOL_REND_AICS
|
||||
bool # Hidden
|
||||
default y if BT_VCP_VOL_REND_AICS_INSTANCE_COUNT > 0
|
||||
help
|
||||
This hidden option makes it possible to easily check if AICS is
|
||||
enabled for VCS.
|
||||
|
||||
config BT_VCP_VOL_REND_VOL_FLAGS_NOTIFIABLE
|
||||
bool "Volume Flags notifiable support"
|
||||
help
|
||||
This option enables support for clients to subscribe for notifications
|
||||
on the Volume Flags characteristic.
|
||||
|
||||
endif # BT_VCP_VOL_REND
|
||||
|
||||
################### Volume Control Profile Volume Controller ###################
|
||||
|
||||
config BT_VCP_VOL_CTLR
|
||||
bool "Volume Control Profile Volume Controller Support"
|
||||
help
|
||||
This option enables support for Volume Control Profile Volume
|
||||
Controller.
|
||||
|
||||
if BT_VCP_VOL_CTLR
|
||||
|
||||
config BT_VCP_VOL_CTLR_MAX_VOCS_INST
|
||||
int "Maximum number of VOCS instances to setup"
|
||||
default 0
|
||||
range 0 BT_VOCS_CLIENT_MAX_INSTANCE_COUNT
|
||||
help
|
||||
Sets the maximum number of Volume Offset Control Service (VOCS)
|
||||
instances to setup and use.
|
||||
|
||||
config BT_VCP_VOL_CTLR_VOCS
|
||||
bool # Hidden
|
||||
default y if BT_VCP_VOL_CTLR_MAX_VOCS_INST > 0
|
||||
help
|
||||
This hidden option makes it possible to easily check if VOCS is
|
||||
enabled for VCS client.
|
||||
|
||||
config BT_VCP_VOL_CTLR_MAX_AICS_INST
|
||||
int "Maximum number of AICS instances to setup"
|
||||
default 0
|
||||
range 0 3
|
||||
help
|
||||
Sets the maximum number of Audio Input Control Service (AICS)
|
||||
instances to setup and use.
|
||||
|
||||
config BT_VCP_VOL_CTLR_AICS
|
||||
bool # Hidden
|
||||
default y if BT_VCP_VOL_CTLR_MAX_AICS_INST > 0
|
||||
help
|
||||
This hidden option makes it possible to easily check if AICS is
|
||||
enabled for VCS client.
|
||||
|
||||
endif # BT_VCP_VOL_CTLR
|
||||
@@ -0,0 +1,49 @@
|
||||
# Bluetooth Audio - Volume Offset Control Service options
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2020 Bose Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##################### Volume Offset Control Service #####################
|
||||
|
||||
config BT_VOCS_MAX_INSTANCE_COUNT
|
||||
int "Volume Offset Control Service max instance count"
|
||||
default 0
|
||||
range 0 15
|
||||
help
|
||||
This option sets the maximum number of instances of Volume Offset
|
||||
Control Services.
|
||||
|
||||
config BT_VOCS
|
||||
bool # hidden
|
||||
default y if BT_VOCS_MAX_INSTANCE_COUNT > 0
|
||||
help
|
||||
This hidden option enables support for Volume Control Service.
|
||||
|
||||
if BT_VOCS
|
||||
|
||||
config BT_VOCS_MAX_OUTPUT_DESCRIPTION_SIZE
|
||||
int "Volume Offset Control Service max output description size"
|
||||
default 32
|
||||
range 0 512
|
||||
help
|
||||
This option sets the maximum output description size in octets.
|
||||
|
||||
endif # BT_VOCS
|
||||
|
||||
##################### Volume Offset Control Service Client #####################
|
||||
|
||||
config BT_VOCS_CLIENT_MAX_INSTANCE_COUNT
|
||||
int "Volume Offset Control Service client max instance count"
|
||||
default 0
|
||||
range 0 15
|
||||
help
|
||||
This option sets the maximum number of instances of Volume Offset
|
||||
Control Service clients.
|
||||
|
||||
config BT_VOCS_CLIENT
|
||||
bool # hidden
|
||||
default y if BT_VOCS_CLIENT_MAX_INSTANCE_COUNT > 0
|
||||
help
|
||||
This hidden option enables support for Volume Offset Control Service.
|
||||
@@ -0,0 +1,359 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_ble_audio_aics_api.h"
|
||||
|
||||
#if CONFIG_BT_AICS
|
||||
esp_ble_audio_aics_t *esp_ble_audio_aics_free_instance_get(void)
|
||||
{
|
||||
return bt_aics_free_instance_get_safe();
|
||||
}
|
||||
|
||||
void *esp_ble_audio_aics_svc_decl_get(esp_ble_audio_aics_t *aics)
|
||||
{
|
||||
if (aics == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return bt_aics_svc_decl_get_safe(aics);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_aics_register(esp_ble_audio_aics_t *aics,
|
||||
esp_ble_audio_aics_register_param_t *param)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (aics == NULL || param == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (param->mute > ESP_BLE_AUDIO_AICS_STATE_MUTE_DISABLED ||
|
||||
param->gain_mode > ESP_BLE_AUDIO_AICS_MODE_AUTO ||
|
||||
param->type > ESP_BLE_AUDIO_AICS_INPUT_TYPE_AMBIENT ||
|
||||
param->units == 0 ||
|
||||
param->min_gain > param->max_gain ||
|
||||
param->gain < param->min_gain ||
|
||||
param->gain > param->max_gain) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_aics_register_safe(aics, param);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_aics_activate(esp_ble_audio_aics_t *inst)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_aics_activate_safe(inst);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_aics_deactivate(esp_ble_audio_aics_t *inst)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_aics_deactivate_safe(inst);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_AICS */
|
||||
|
||||
#if CONFIG_BT_AICS || CONFIG_BT_AICS_CLIENT
|
||||
esp_err_t esp_ble_audio_aics_state_get(esp_ble_audio_aics_t *inst)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_aics_state_get_safe(inst);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_aics_gain_setting_get(esp_ble_audio_aics_t *inst)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_aics_gain_setting_get_safe(inst);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_aics_type_get(esp_ble_audio_aics_t *inst)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_aics_type_get_safe(inst);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_aics_status_get(esp_ble_audio_aics_t *inst)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_aics_status_get_safe(inst);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_aics_disable_mute(esp_ble_audio_aics_t *inst)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_aics_disable_mute_safe(inst);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_aics_unmute(esp_ble_audio_aics_t *inst)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_aics_unmute_safe(inst);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_aics_mute(esp_ble_audio_aics_t *inst)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_aics_mute_safe(inst);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_aics_gain_set_manual_only(esp_ble_audio_aics_t *inst)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_aics_gain_set_manual_only_safe(inst);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_aics_gain_set_auto_only(esp_ble_audio_aics_t *inst)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_aics_gain_set_auto_only_safe(inst);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_aics_manual_gain_set(esp_ble_audio_aics_t *inst)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_aics_manual_gain_set_safe(inst);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_aics_automatic_gain_set(esp_ble_audio_aics_t *inst)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_aics_automatic_gain_set_safe(inst);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_aics_gain_set(esp_ble_audio_aics_t *inst, int8_t gain)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_aics_gain_set_safe(inst, gain);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_aics_description_get(esp_ble_audio_aics_t *inst)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_aics_description_get_safe(inst);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_aics_description_set(esp_ble_audio_aics_t *inst,
|
||||
const char *description)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (inst == NULL || description == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_aics_description_set_safe(inst, description);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_AICS || CONFIG_BT_AICS_CLIENT */
|
||||
|
||||
#if CONFIG_BT_AICS_CLIENT
|
||||
esp_err_t esp_ble_audio_aics_discover(uint16_t conn_handle, esp_ble_audio_aics_t *inst,
|
||||
const esp_ble_audio_aics_discover_param_t *param)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
if (inst == NULL || param == NULL ||
|
||||
param->end_handle <= param->start_handle) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_aics_discover(conn, inst, param);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_ble_audio_aics_t *esp_ble_audio_aics_client_free_instance_get(void)
|
||||
{
|
||||
return bt_aics_client_free_instance_get_safe();
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_aics_client_cb_register(esp_ble_audio_aics_t *inst,
|
||||
esp_ble_audio_aics_cb_t *cb)
|
||||
{
|
||||
if (inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
bt_aics_client_cb_register_safe(inst, cb);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_AICS_CLIENT */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,722 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_ble_audio_cap_api.h"
|
||||
|
||||
#if CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER
|
||||
esp_err_t esp_ble_audio_cap_acceptor_register(const esp_ble_audio_csip_set_member_register_param_t *param,
|
||||
esp_ble_audio_csip_set_member_svc_inst_t **svc_inst)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (param == NULL || svc_inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (param->lockable && param->rank == 0) {
|
||||
/* Rank cannot be 0 if service is lockable */
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (param->rank > param->set_size) {
|
||||
/* Invalid rank (shall be less than or equal to set_size */
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_CSIP_SET_MEMBER_MAX_INSTANCE_COUNT > 1
|
||||
if (param->parent == NULL) {
|
||||
/* Parent service not provided */
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
#endif /* CONFIG_BT_CSIP_SET_MEMBER_MAX_INSTANCE_COUNT > 1 */
|
||||
|
||||
err = bt_cap_acceptor_register_safe(param, svc_inst);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER */
|
||||
|
||||
#if CONFIG_BT_CAP
|
||||
esp_err_t esp_ble_audio_cap_stream_ops_register(esp_ble_audio_cap_stream_t *stream,
|
||||
esp_ble_audio_bap_stream_ops_t *ops)
|
||||
{
|
||||
if (stream == NULL || ops == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
bt_cap_stream_ops_register_safe(stream, ops);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_AUDIO_TX
|
||||
esp_err_t esp_ble_audio_cap_stream_send(esp_ble_audio_cap_stream_t *stream,
|
||||
const uint8_t *sdu, uint16_t sdu_len,
|
||||
uint16_t seq_num)
|
||||
{
|
||||
struct net_buf buf = {
|
||||
/* Note: only data and len are used */
|
||||
.data = (void *)sdu,
|
||||
.len = sdu_len,
|
||||
};
|
||||
int err;
|
||||
|
||||
if (stream == NULL || (!sdu ^ !sdu_len)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_stream_send_safe(stream, &buf, seq_num);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_stream_send_ts(esp_ble_audio_cap_stream_t *stream,
|
||||
const uint8_t *sdu, uint16_t sdu_len,
|
||||
uint16_t seq_num, uint32_t ts)
|
||||
{
|
||||
struct net_buf buf = {
|
||||
/* Note: only data and len are used */
|
||||
.data = (void *)sdu,
|
||||
.len = sdu_len,
|
||||
};
|
||||
int err;
|
||||
|
||||
if (stream == NULL || (!sdu ^ !sdu_len)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_stream_send_ts_safe(stream, &buf, seq_num, ts);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_stream_get_tx_sync(esp_ble_audio_cap_stream_t *stream,
|
||||
esp_ble_iso_tx_info_t *info)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (stream == NULL || info == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_stream_get_tx_sync_safe(stream, info);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_AUDIO_TX */
|
||||
#endif /* CONFIG_BT_CAP */
|
||||
|
||||
#if CONFIG_BT_BAP_UNICAST_CLIENT
|
||||
esp_err_t esp_ble_audio_cap_unicast_group_create(const esp_ble_audio_cap_unicast_group_param_t *param,
|
||||
esp_ble_audio_cap_unicast_group_t **unicast_group)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (param == NULL || unicast_group == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_unicast_group_create_safe(param, unicast_group);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_unicast_group_reconfig(esp_ble_audio_cap_unicast_group_t *unicast_group,
|
||||
const esp_ble_audio_cap_unicast_group_param_t *param)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (unicast_group == NULL || param == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_unicast_group_reconfig_safe(unicast_group, param);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_unicast_group_add_streams(esp_ble_audio_cap_unicast_group_t *unicast_group,
|
||||
const esp_ble_audio_cap_unicast_group_stream_pair_param_t params[],
|
||||
size_t num_param)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (unicast_group == NULL || params == NULL || num_param == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_unicast_group_add_streams_safe(unicast_group, params, num_param);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_unicast_group_delete(esp_ble_audio_cap_unicast_group_t *unicast_group)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (unicast_group == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_unicast_group_delete_safe(unicast_group);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
|
||||
|
||||
#if CONFIG_BT_CAP_INITIATOR
|
||||
esp_err_t esp_ble_audio_cap_initiator_register_cb(const esp_ble_audio_cap_initiator_cb_t *cb)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (cb == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_initiator_register_cb_safe(cb);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_initiator_unregister_cb(const esp_ble_audio_cap_initiator_cb_t *cb)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (cb == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_initiator_unregister_cb_safe(cb);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_BAP_UNICAST_CLIENT
|
||||
esp_err_t esp_ble_audio_cap_initiator_unicast_discover(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_cap_initiator_unicast_discover(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_initiator_unicast_audio_start(const esp_ble_audio_cap_unicast_audio_start_param_t *param)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (param == NULL || param->count == 0 || param->stream_params == NULL ||
|
||||
param->count > CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_initiator_unicast_audio_start_safe(param);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_initiator_unicast_audio_update(const esp_ble_audio_cap_unicast_audio_update_param_t *param)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (param == NULL || param->count == 0 || param->stream_params == NULL ||
|
||||
param->count > CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_initiator_unicast_audio_update_safe(param);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_initiator_unicast_audio_stop(const esp_ble_audio_cap_unicast_audio_stop_param_t *param)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (param == NULL || param->count == 0 || param->streams == NULL ||
|
||||
param->count > CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_initiator_unicast_audio_stop_safe(param);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_initiator_unicast_audio_cancel(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_cap_initiator_unicast_audio_cancel_safe();
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
|
||||
|
||||
#if CONFIG_BT_BAP_BROADCAST_SOURCE
|
||||
esp_err_t esp_ble_audio_cap_initiator_broadcast_audio_create(const esp_ble_audio_cap_initiator_broadcast_create_param_t *param,
|
||||
esp_ble_audio_cap_broadcast_source_t **broadcast_source)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (param == NULL || broadcast_source == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_initiator_broadcast_audio_create_safe(param, broadcast_source);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_initiator_broadcast_audio_start(esp_ble_audio_cap_broadcast_source_t *broadcast_source,
|
||||
uint8_t adv_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *adv;
|
||||
int err;
|
||||
|
||||
if (broadcast_source == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
adv = bt_le_ext_adv_find(adv_handle);
|
||||
if (adv == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_cap_initiator_broadcast_audio_start(broadcast_source, adv);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_initiator_broadcast_audio_update(esp_ble_audio_cap_broadcast_source_t *broadcast_source,
|
||||
const uint8_t meta[], size_t meta_len)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (broadcast_source == NULL || meta == NULL || meta_len == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_initiator_broadcast_audio_update_safe(broadcast_source, meta, meta_len);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_initiator_broadcast_audio_stop(esp_ble_audio_cap_broadcast_source_t *broadcast_source)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (broadcast_source == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_initiator_broadcast_audio_stop_safe(broadcast_source);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_initiator_broadcast_audio_delete(esp_ble_audio_cap_broadcast_source_t *broadcast_source)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (broadcast_source == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_initiator_broadcast_audio_delete_safe(broadcast_source);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_initiator_broadcast_get_base(esp_ble_audio_cap_broadcast_source_t *broadcast_source,
|
||||
struct net_buf_simple *base_buf)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (broadcast_source == NULL || base_buf == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_initiator_broadcast_get_base_safe(broadcast_source, base_buf);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
|
||||
#endif /* CONFIG_BT_CAP_INITIATOR */
|
||||
|
||||
#if CONFIG_BT_CAP_HANDOVER
|
||||
esp_err_t esp_ble_audio_cap_handover_register_cb(const esp_ble_audio_cap_handover_cb_t *cb)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (cb == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_handover_register_cb_safe(cb);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_handover_unregister_cb(const esp_ble_audio_cap_handover_cb_t *cb)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (cb == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_handover_unregister_cb_safe(cb);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_handover_unicast_to_broadcast(
|
||||
const esp_ble_audio_cap_handover_unicast_to_broadcast_param_t *param)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (param == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_handover_unicast_to_broadcast_safe(param);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_handover_broadcast_to_unicast(
|
||||
const esp_ble_audio_cap_handover_broadcast_to_unicast_param_t *param)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (param == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_handover_broadcast_to_unicast_safe(param);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_CAP_HANDOVER */
|
||||
|
||||
#if CONFIG_BT_CAP_COMMANDER
|
||||
esp_err_t esp_ble_audio_cap_commander_register_cb(const esp_ble_audio_cap_commander_cb_t *cb)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (cb == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_commander_register_cb_safe(cb);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_commander_unregister_cb(const esp_ble_audio_cap_commander_cb_t *cb)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (cb == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_commander_unregister_cb_safe(cb);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_commander_discover(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_cap_commander_discover(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_commander_cancel(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_cap_commander_cancel_safe();
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_BAP_BROADCAST_ASSISTANT
|
||||
esp_err_t esp_ble_audio_cap_commander_broadcast_reception_start(
|
||||
const esp_ble_audio_cap_commander_broadcast_reception_start_param_t *param)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (param == NULL || param->count == 0 ||
|
||||
param->count > CONFIG_BT_MAX_CONN || param->param == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_commander_broadcast_reception_start_safe(param);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_commander_broadcast_reception_stop(
|
||||
const esp_ble_audio_cap_commander_broadcast_reception_stop_param_t *param)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (param == NULL || param->count == 0 ||
|
||||
param->count > CONFIG_BT_MAX_CONN || param->param == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_commander_broadcast_reception_stop_safe(param);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_cap_commander_distribute_broadcast_code(
|
||||
const esp_ble_audio_cap_commander_distribute_broadcast_code_param_t *param)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (param == NULL || param->count == 0 ||
|
||||
param->count > CONFIG_BT_MAX_CONN || param->param == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_commander_distribute_broadcast_code_safe(param);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */
|
||||
|
||||
#if CONFIG_BT_VCP_VOL_CTLR
|
||||
esp_err_t esp_ble_audio_cap_commander_change_volume(
|
||||
const esp_ble_audio_cap_commander_change_volume_param_t *param)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (param == NULL || param->count == 0 ||
|
||||
param->count > CONFIG_BT_MAX_CONN || param->members == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_commander_change_volume_safe(param);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_VCP_VOL_CTLR_VOCS
|
||||
esp_err_t esp_ble_audio_cap_commander_change_volume_offset(
|
||||
const esp_ble_audio_cap_commander_change_volume_offset_param_t *param)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (param == NULL || param->count == 0 ||
|
||||
param->count > CONFIG_BT_MAX_CONN || param->param == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_commander_change_volume_offset_safe(param);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_VCP_VOL_CTLR_VOCS */
|
||||
|
||||
esp_err_t esp_ble_audio_cap_commander_change_volume_mute_state(
|
||||
const esp_ble_audio_cap_commander_change_volume_mute_state_param_t *param)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (param == NULL || param->count == 0 ||
|
||||
param->count > CONFIG_BT_MAX_CONN || param->members == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_commander_change_volume_mute_state_safe(param);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_VCP_VOL_CTLR */
|
||||
|
||||
#if CONFIG_BT_MICP_MIC_CTLR
|
||||
esp_err_t esp_ble_audio_cap_commander_change_microphone_mute_state(
|
||||
const esp_ble_audio_cap_commander_change_microphone_mute_state_param_t *param)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (param == NULL || param->count == 0 ||
|
||||
param->count > CONFIG_BT_MAX_CONN || param->members == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_commander_change_microphone_mute_state_safe(param);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_MICP_MIC_CTLR_AICS
|
||||
esp_err_t esp_ble_audio_cap_commander_change_microphone_gain_setting(
|
||||
const esp_ble_audio_cap_commander_change_microphone_gain_setting_param_t *param)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (param == NULL || param->count == 0 ||
|
||||
param->count > CONFIG_BT_MAX_CONN || param->param == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_cap_commander_change_microphone_gain_setting_safe(param);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_MICP_MIC_CTLR_AICS */
|
||||
#endif /* CONFIG_BT_MICP_MIC_CTLR */
|
||||
#endif /* CONFIG_BT_CAP_COMMANDER */
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_ble_audio_ccp_api.h"
|
||||
|
||||
#if CONFIG_BT_CCP_CALL_CONTROL_SERVER
|
||||
esp_err_t esp_ble_audio_ccp_call_control_server_register_bearer(
|
||||
const esp_ble_audio_tbs_register_param_t *param,
|
||||
esp_ble_audio_ccp_call_control_server_bearer_t **bearer)
|
||||
{
|
||||
esp_err_t err;
|
||||
|
||||
if (param == NULL || bearer == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_ccp_call_control_server_register_bearer_safe(param, bearer);
|
||||
if (err) {
|
||||
/* Map Zephyr error codes to ESP-IDF error codes */
|
||||
switch (err) {
|
||||
case -EINVAL:
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
case -ENOMEM:
|
||||
return ESP_ERR_NO_MEM;
|
||||
case -EALREADY:
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
case -EAGAIN:
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
default:
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_ccp_call_control_server_unregister_bearer(
|
||||
esp_ble_audio_ccp_call_control_server_bearer_t *bearer)
|
||||
{
|
||||
esp_err_t err;
|
||||
|
||||
if (bearer == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_ccp_call_control_server_unregister_bearer_safe(bearer);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_ccp_call_control_server_set_bearer_provider_name(
|
||||
esp_ble_audio_ccp_call_control_server_bearer_t *bearer, const char *name)
|
||||
{
|
||||
esp_err_t err;
|
||||
|
||||
if (bearer == NULL || name == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_ccp_call_control_server_set_bearer_provider_name_safe(bearer, name);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_ccp_call_control_server_get_bearer_provider_name(
|
||||
esp_ble_audio_ccp_call_control_server_bearer_t *bearer, const char **name)
|
||||
{
|
||||
esp_err_t err;
|
||||
|
||||
if (bearer == NULL || name == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_ccp_call_control_server_get_bearer_provider_name_safe(bearer, name);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_CCP_CALL_CONTROL_SERVER */
|
||||
|
||||
#if CONFIG_BT_CCP_CALL_CONTROL_CLIENT
|
||||
esp_err_t esp_ble_audio_ccp_call_control_client_discover(
|
||||
esp_ble_conn_t *conn, esp_ble_audio_ccp_call_control_client_t **out_client)
|
||||
{
|
||||
esp_err_t err;
|
||||
|
||||
if (conn == NULL || out_client == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_ccp_call_control_client_discover_safe(conn, out_client);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_ccp_call_control_client_register_cb(
|
||||
esp_ble_audio_ccp_call_control_client_cb_t *cb)
|
||||
{
|
||||
esp_err_t err;
|
||||
|
||||
if (cb == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_ccp_call_control_client_register_cb_safe(cb);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_ccp_call_control_client_unregister_cb(
|
||||
esp_ble_audio_ccp_call_control_client_cb_t *cb)
|
||||
{
|
||||
esp_err_t err;
|
||||
|
||||
if (cb == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_ccp_call_control_client_unregister_cb_safe(cb);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_ccp_call_control_client_get_bearers(
|
||||
esp_ble_audio_ccp_call_control_client_t *client,
|
||||
esp_ble_audio_ccp_call_control_client_bearers_t *bearers)
|
||||
{
|
||||
esp_err_t err;
|
||||
|
||||
if (client == NULL || bearers == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_ccp_call_control_client_get_bearers_safe(client, bearers);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_CCP_CALL_CONTROL_CLIENT */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME
|
||||
esp_err_t esp_ble_audio_ccp_call_control_client_read_bearer_provider_name(
|
||||
esp_ble_audio_ccp_call_control_client_bearer_t *bearer)
|
||||
{
|
||||
esp_err_t err;
|
||||
|
||||
if (bearer == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_ccp_call_control_client_read_bearer_provider_name_safe(bearer);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Intel Corporation
|
||||
* SPDX-FileCopyrightText: 2020-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "esp_ble_audio_common_api.h"
|
||||
|
||||
esp_err_t esp_ble_audio_data_parse(const uint8_t ltv[], size_t size,
|
||||
bool (*func)(uint8_t type,
|
||||
const uint8_t *data,
|
||||
uint8_t data_len,
|
||||
void *user_data),
|
||||
void *user_data)
|
||||
{
|
||||
return esp_ble_iso_data_parse(ltv, size, func, user_data);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_data_get_val(const uint8_t ltv_data[],
|
||||
size_t size, uint8_t type,
|
||||
const uint8_t **data,
|
||||
uint8_t *data_len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (ltv_data == NULL || data == NULL || data_len == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ret = bt_audio_data_get_val(ltv_data, size, type, data);
|
||||
if (ret < 0) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
*data_len = ret;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
uint8_t esp_ble_audio_get_chan_count(esp_ble_audio_location_t chan_allocation)
|
||||
{
|
||||
return bt_audio_get_chan_count(chan_allocation);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_gattc_disc_start(uint16_t conn_handle)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_gattc_disc_start_safe(conn_handle);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void esp_ble_audio_gap_app_post_event(uint8_t type, void *param)
|
||||
{
|
||||
bt_le_gap_app_post_event(type, param);
|
||||
}
|
||||
|
||||
void esp_ble_audio_gatt_app_post_event(uint8_t type, void *param)
|
||||
{
|
||||
bt_le_gatt_app_post_event(type, param);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_common_init(esp_ble_audio_init_info_t *info)
|
||||
{
|
||||
bool gap_cb_registered = false;
|
||||
bool gatt_cb_registered = false;
|
||||
int err;
|
||||
|
||||
if (info) {
|
||||
if (info->gap_cb) {
|
||||
err = bt_le_gap_app_cb_register(info->gap_cb);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
gap_cb_registered = true;
|
||||
}
|
||||
|
||||
if (info->gatt_cb) {
|
||||
err = bt_le_gatt_app_cb_register(info->gatt_cb);
|
||||
if (err) {
|
||||
goto unregister_gap;
|
||||
}
|
||||
|
||||
gatt_cb_registered = true;
|
||||
}
|
||||
}
|
||||
|
||||
err = bt_le_host_init();
|
||||
if (err) {
|
||||
goto unregister_gatt;
|
||||
}
|
||||
|
||||
err = bt_le_audio_init();
|
||||
if (err) {
|
||||
bt_le_host_deinit();
|
||||
goto unregister_gatt;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
unregister_gatt:
|
||||
if (gatt_cb_registered) {
|
||||
bt_le_gatt_app_cb_unregister();
|
||||
}
|
||||
unregister_gap:
|
||||
if (gap_cb_registered) {
|
||||
bt_le_gap_app_cb_unregister();
|
||||
}
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_common_start(esp_ble_audio_start_info_t *info)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (info) {
|
||||
#if CONFIG_BT_CSIP_SET_MEMBER
|
||||
uint8_t cas_included = 0;
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(info->csis_insts); i++) {
|
||||
if (info->csis_insts[i].svc_inst &&
|
||||
info->csis_insts[i].included_by_cas) {
|
||||
cas_included++;
|
||||
}
|
||||
}
|
||||
|
||||
/* From CAS Spec:
|
||||
* The CAS shall include no more than one instance of CSIS.
|
||||
*/
|
||||
if (cas_included > 1) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
#endif /* CONFIG_BT_CSIP_SET_MEMBER */
|
||||
}
|
||||
|
||||
err = bt_le_audio_start(info);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_ble_audio_csip_api.h"
|
||||
|
||||
#if CONFIG_BT_CSIP_SET_MEMBER
|
||||
void *esp_ble_audio_csip_set_member_svc_decl_get(const esp_ble_audio_csip_set_member_svc_inst_t *svc_inst)
|
||||
{
|
||||
if (svc_inst == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return bt_csip_set_member_svc_decl_get_safe(svc_inst);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_csip_set_member_register(const esp_ble_audio_csip_set_member_register_param_t *param,
|
||||
esp_ble_audio_csip_set_member_svc_inst_t **svc_inst)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (param == NULL || svc_inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (param->lockable && param->rank == 0) {
|
||||
/* Rank cannot be 0 if service is lockable */
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (param->rank > param->set_size) {
|
||||
/* Invalid rank (shall be less than or equal to set_size */
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_CSIP_SET_MEMBER_MAX_INSTANCE_COUNT > 1
|
||||
if (param->parent == NULL) {
|
||||
/* Parent service not provided */
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
#endif /* CONFIG_BT_CSIP_SET_MEMBER_MAX_INSTANCE_COUNT > 1 */
|
||||
|
||||
err = bt_csip_set_member_register_safe(param, svc_inst);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_csip_set_member_unregister(esp_ble_audio_csip_set_member_svc_inst_t *svc_inst)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (svc_inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_csip_set_member_unregister_safe(svc_inst);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_csip_set_member_sirk(esp_ble_audio_csip_set_member_svc_inst_t *svc_inst,
|
||||
const uint8_t sirk[ESP_BLE_AUDIO_CSIP_SIRK_SIZE])
|
||||
{
|
||||
int err;
|
||||
|
||||
if (svc_inst == NULL || sirk == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_csip_set_member_sirk_safe(svc_inst, sirk);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_csip_set_member_set_size_and_rank(esp_ble_audio_csip_set_member_svc_inst_t *svc_inst,
|
||||
uint8_t size, uint8_t rank)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (svc_inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_csip_set_member_set_size_and_rank_safe(svc_inst, size, rank);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_csip_set_member_get_info(const esp_ble_audio_csip_set_member_svc_inst_t *svc_inst,
|
||||
esp_ble_audio_csip_set_member_set_info_t *info)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (svc_inst == NULL || info == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_csip_set_member_get_info_safe(svc_inst, info);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_csip_set_member_generate_rsi(const esp_ble_audio_csip_set_member_svc_inst_t *svc_inst,
|
||||
uint8_t rsi[ESP_BLE_AUDIO_CSIP_RSI_SIZE])
|
||||
{
|
||||
int err;
|
||||
|
||||
if (svc_inst == NULL || rsi == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_csip_set_member_generate_rsi_safe(svc_inst, rsi);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_csip_set_member_lock(esp_ble_audio_csip_set_member_svc_inst_t *svc_inst,
|
||||
bool lock, bool force)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (svc_inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_csip_set_member_lock_safe(svc_inst, lock, force);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_CSIP_SET_MEMBER */
|
||||
|
||||
#if CONFIG_BT_CSIP_SET_COORDINATOR
|
||||
esp_err_t esp_ble_audio_csip_set_coordinator_discover(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_csip_set_coordinator_discover(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_ble_audio_csip_set_coordinator_set_member_t *
|
||||
esp_ble_audio_csip_set_coordinator_set_member_by_conn(uint16_t conn_handle)
|
||||
{
|
||||
esp_ble_audio_csip_set_coordinator_set_member_t *ret = NULL;
|
||||
void *conn;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = bt_csip_set_coordinator_set_member_by_conn(conn);
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool esp_ble_audio_csip_set_coordinator_is_set_member(const uint8_t sirk[ESP_BLE_AUDIO_CSIP_SIRK_SIZE],
|
||||
uint8_t data_type, const uint8_t *data, uint8_t data_len)
|
||||
{
|
||||
struct bt_data ad = {
|
||||
.type = data_type,
|
||||
.data = data,
|
||||
.data_len = data_len,
|
||||
};
|
||||
|
||||
if (sirk == NULL || data_type != BT_DATA_CSIS_RSI ||
|
||||
data == NULL || data_len != ESP_BLE_AUDIO_CSIP_RSI_SIZE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return bt_csip_set_coordinator_is_set_member_safe(sirk, &ad);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_csip_set_coordinator_register_cb(esp_ble_audio_csip_set_coordinator_cb_t *cb)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (cb == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_csip_set_coordinator_register_cb_safe(cb);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_csip_set_coordinator_ordered_access(const esp_ble_audio_csip_set_coordinator_set_member_t *members[],
|
||||
uint8_t count,
|
||||
const esp_ble_audio_csip_set_coordinator_set_info_t *set_info,
|
||||
bt_csip_set_coordinator_ordered_access_t cb)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (members == NULL ||
|
||||
count == 0 || count > CONFIG_BT_MAX_CONN ||
|
||||
set_info == NULL || cb == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_csip_set_coordinator_ordered_access_safe(members, count, set_info, cb);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_csip_set_coordinator_lock(const esp_ble_audio_csip_set_coordinator_set_member_t **members,
|
||||
uint8_t count,
|
||||
const esp_ble_audio_csip_set_coordinator_set_info_t *set_info)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (members == NULL || count > CONFIG_BT_MAX_CONN || set_info == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_csip_set_coordinator_lock_safe(members, count, set_info);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_csip_set_coordinator_release(const esp_ble_audio_csip_set_coordinator_set_member_t **members,
|
||||
uint8_t count,
|
||||
const esp_ble_audio_csip_set_coordinator_set_info_t *set_info)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (members == NULL || count > CONFIG_BT_MAX_CONN || set_info == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_csip_set_coordinator_release_safe(members, count, set_info);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_CSIP_SET_COORDINATOR */
|
||||
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_ble_audio_gmap_api.h"
|
||||
|
||||
#if CONFIG_BT_GMAP
|
||||
esp_err_t esp_ble_audio_gmap_cb_register(const esp_ble_audio_gmap_cb_t *cb)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (cb == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_gmap_cb_register_safe(cb);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_gmap_discover(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_gmap_discover(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define GMAP_ROLE_MASK (ESP_BLE_AUDIO_GMAP_ROLE_UGG | \
|
||||
ESP_BLE_AUDIO_GMAP_ROLE_UGT | \
|
||||
ESP_BLE_AUDIO_GMAP_ROLE_BGS | \
|
||||
ESP_BLE_AUDIO_GMAP_ROLE_BGR)
|
||||
|
||||
static bool valid_gmap_role(esp_ble_audio_gmap_role_t role)
|
||||
{
|
||||
if (role == 0 || (role & GMAP_ROLE_MASK) != role) {
|
||||
/* Invalid role */
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((role & ESP_BLE_AUDIO_GMAP_ROLE_UGG) != 0 &&
|
||||
!IS_ENABLED(CONFIG_BT_GMAP_UGG_SUPPORTED)) {
|
||||
/* Device does not support the UGG role */
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((role & ESP_BLE_AUDIO_GMAP_ROLE_UGT) != 0 &&
|
||||
!IS_ENABLED(CONFIG_BT_GMAP_UGT_SUPPORTED)) {
|
||||
/* Device does not support the UGT role */
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((role & ESP_BLE_AUDIO_GMAP_ROLE_BGS) != 0 &&
|
||||
!IS_ENABLED(CONFIG_BT_GMAP_BGS_SUPPORTED)) {
|
||||
/* Device does not support the BGS role */
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((role & ESP_BLE_AUDIO_GMAP_ROLE_BGR) != 0 &&
|
||||
!IS_ENABLED(CONFIG_BT_GMAP_BGR_SUPPORTED)) {
|
||||
/* Device does not support the BGR role */
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool valid_gmap_features(esp_ble_audio_gmap_role_t role,
|
||||
esp_ble_audio_gmap_feat_t features)
|
||||
{
|
||||
#if CONFIG_BT_GMAP_UGG_SUPPORTED
|
||||
if ((role & ESP_BLE_AUDIO_GMAP_ROLE_UGG) != 0) {
|
||||
esp_ble_audio_gmap_ugg_feat_t ugg_feat = features.ugg_feat;
|
||||
|
||||
if ((ugg_feat & ESP_BLE_AUDIO_GMAP_UGG_FEAT_MULTIPLEX) != 0 &&
|
||||
CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT == 0) {
|
||||
/* Cannot support ESP_BLE_AUDIO_GMAP_UGG_FEAT_MULTIPLEX with
|
||||
* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT == 0.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((ugg_feat & ESP_BLE_AUDIO_GMAP_UGG_FEAT_96KBPS_SOURCE) != 0 &&
|
||||
CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT == 0) {
|
||||
/* Cannot support ESP_BLE_AUDIO_GMAP_UGG_FEAT_96KBPS_SOURCE with
|
||||
* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT == 0.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((ugg_feat & ESP_BLE_AUDIO_GMAP_UGG_FEAT_MULTISINK) != 0 &&
|
||||
(CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT < 2 ||
|
||||
CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT < 2)) {
|
||||
/* Cannot support ESP_BLE_AUDIO_GMAP_UGG_FEAT_MULTISINK with
|
||||
* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT or
|
||||
* CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT < 2.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_GMAP_UGG_SUPPORTED */
|
||||
|
||||
#if CONFIG_BT_GMAP_UGT_SUPPORTED
|
||||
if ((role & ESP_BLE_AUDIO_GMAP_ROLE_UGT) != 0) {
|
||||
esp_ble_audio_gmap_ugt_feat_t ugt_feat = features.ugt_feat;
|
||||
esp_ble_audio_gmap_bgr_feat_t bgr_feat = features.bgr_feat;
|
||||
|
||||
if ((ugt_feat & ESP_BLE_AUDIO_GMAP_UGT_FEAT_SOURCE) == 0 &&
|
||||
(ugt_feat & ESP_BLE_AUDIO_GMAP_UGT_FEAT_SINK) == 0) {
|
||||
/* Device shall support either ESP_BLE_AUDIO_GMAP_UGT_FEAT_SOURCE or
|
||||
* ESP_BLE_AUDIO_GMAP_UGT_FEAT_SINK.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((ugt_feat & ESP_BLE_AUDIO_GMAP_UGT_FEAT_SOURCE) == 0 &&
|
||||
((ugt_feat & ESP_BLE_AUDIO_GMAP_UGT_FEAT_80KBPS_SOURCE) != 0 ||
|
||||
(ugt_feat & ESP_BLE_AUDIO_GMAP_UGT_FEAT_MULTISOURCE) != 0)) {
|
||||
/* Device shall support ESP_BLE_AUDIO_GMAP_UGT_FEAT_SOURCE if
|
||||
* ESP_BLE_AUDIO_GMAP_UGT_FEAT_80KBPS_SOURCE or
|
||||
* ESP_BLE_AUDIO_GMAP_UGT_FEAT_MULTISOURCE is supported.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((ugt_feat & ESP_BLE_AUDIO_GMAP_UGT_FEAT_SOURCE) != 0 &&
|
||||
CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT == 0) {
|
||||
/* Cannot support ESP_BLE_AUDIO_GMAP_UGT_FEAT_SOURCE with
|
||||
* CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT == 0.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((ugt_feat & ESP_BLE_AUDIO_GMAP_UGT_FEAT_MULTISOURCE) != 0 &&
|
||||
(CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT < 2 ||
|
||||
CONFIG_BT_ASCS_MAX_ACTIVE_ASES < 2)) {
|
||||
/* Cannot support ESP_BLE_AUDIO_GMAP_UGT_FEAT_MULTISOURCE with
|
||||
* CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT or
|
||||
* CONFIG_BT_ASCS_MAX_ACTIVE_ASES < 2.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((ugt_feat & ESP_BLE_AUDIO_GMAP_UGT_FEAT_SINK) != 0 &&
|
||||
CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT == 0) {
|
||||
/* Cannot support ESP_BLE_AUDIO_GMAP_UGT_FEAT_SINK with
|
||||
* CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT == 0.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((ugt_feat & ESP_BLE_AUDIO_GMAP_UGT_FEAT_SINK) == 0 &&
|
||||
((ugt_feat & ESP_BLE_AUDIO_GMAP_UGT_FEAT_64KBPS_SINK) != 0 ||
|
||||
(ugt_feat & ESP_BLE_AUDIO_GMAP_UGT_FEAT_MULTISINK) != 0 ||
|
||||
(ugt_feat & ESP_BLE_AUDIO_GMAP_UGT_FEAT_MULTIPLEX) != 0)) {
|
||||
/* Device shall support ESP_BLE_AUDIO_GMAP_UGT_FEAT_SINK if
|
||||
* ESP_BLE_AUDIO_GMAP_UGT_FEAT_64KBPS_SINK,
|
||||
* ESP_BLE_AUDIO_GMAP_UGT_FEAT_MULTISINK or
|
||||
* ESP_BLE_AUDIO_GMAP_UGT_FEAT_MULTIPLEX is supported.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((ugt_feat & ESP_BLE_AUDIO_GMAP_UGT_FEAT_MULTISINK) != 0 &&
|
||||
(CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT < 2 ||
|
||||
CONFIG_BT_ASCS_MAX_ACTIVE_ASES < 2)) {
|
||||
/* Cannot support ESP_BLE_AUDIO_GMAP_UGT_FEAT_MULTISINK with
|
||||
* CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT or
|
||||
* CONFIG_BT_ASCS_MAX_ACTIVE_ASES < 2.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If the device supports both the UGT and BGT roles, then it needs
|
||||
* have the same support for multiplexing for both roles.
|
||||
*/
|
||||
if ((role & ESP_BLE_AUDIO_GMAP_ROLE_BGR) != 0 &&
|
||||
IS_ENABLED(CONFIG_BT_GMAP_BGR_SUPPORTED) &&
|
||||
!!(ugt_feat & ESP_BLE_AUDIO_GMAP_UGT_FEAT_MULTIPLEX) !=
|
||||
!!(bgr_feat & ESP_BLE_AUDIO_GMAP_BGR_FEAT_MULTIPLEX)) {
|
||||
/* Device shall support ESP_BLE_AUDIO_GMAP_UGT_FEAT_MULTIPLEX if
|
||||
* ESP_BLE_AUDIO_GMAP_BGR_FEAT_MULTIPLEX is supported, and vice versa.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_GMAP_UGT_SUPPORTED */
|
||||
|
||||
#if CONFIG_BT_GMAP_BGR_SUPPORTED
|
||||
if ((role & ESP_BLE_AUDIO_GMAP_ROLE_BGR) != 0) {
|
||||
esp_ble_audio_gmap_bgr_feat_t bgr_feat = features.bgr_feat;
|
||||
|
||||
if ((bgr_feat & ESP_BLE_AUDIO_GMAP_BGR_FEAT_MULTISINK) != 0 &&
|
||||
CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT < 2) {
|
||||
/* Cannot support ESP_BLE_AUDIO_GMAP_BGR_FEAT_MULTISINK with
|
||||
* CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT < 2.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_GMAP_BGR_SUPPORTED */
|
||||
|
||||
/* If the roles are not supported, then the feature characteristics
|
||||
* are not instantiated and the feature values do not need to be
|
||||
* checked, as they will never be read (thus ignore by the stack).
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_gmap_register(esp_ble_audio_gmap_role_t role,
|
||||
esp_ble_audio_gmap_feat_t features)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (valid_gmap_role(role) == false ||
|
||||
valid_gmap_features(role, features) == false) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_gmap_register_safe(role, features);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_gmap_set_role(esp_ble_audio_gmap_role_t role,
|
||||
esp_ble_audio_gmap_feat_t features)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (valid_gmap_role(role) == false ||
|
||||
valid_gmap_features(role, features) == false) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_gmap_set_role_safe(role, features);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_GMAP */
|
||||
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Codecoup
|
||||
* SPDX-FileCopyrightText: 2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_ble_audio_has_api.h"
|
||||
|
||||
#if CONFIG_BT_HAS_CLIENT
|
||||
esp_err_t esp_ble_audio_has_client_cb_register(const esp_ble_audio_has_client_cb_t *cb)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (cb == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_has_client_cb_register_safe(cb);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_has_client_discover(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_has_client_discover(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_has_client_presets_read(esp_ble_audio_has_t *has,
|
||||
uint8_t index,
|
||||
uint8_t max_count)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (has == NULL ||
|
||||
index == ESP_BLE_AUDIO_HAS_PRESET_INDEX_NONE ||
|
||||
max_count == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_has_client_presets_read_safe(has, index, max_count);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_has_client_preset_set(esp_ble_audio_has_t *has,
|
||||
uint8_t index, bool sync)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (has == NULL || index == ESP_BLE_AUDIO_HAS_PRESET_INDEX_NONE) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_has_client_preset_set_safe(has, index, sync);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_has_client_preset_next(esp_ble_audio_has_t *has, bool sync)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (has == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_has_client_preset_next_safe(has, sync);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_has_client_preset_prev(esp_ble_audio_has_t *has, bool sync)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (has == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_has_client_preset_prev_safe(has, sync);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_HAS_CLIENT */
|
||||
|
||||
#if CONFIG_BT_HAS
|
||||
esp_err_t esp_ble_audio_has_register(const esp_ble_audio_has_features_param_t *features)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (features == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_has_register_safe(features);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
#if BLE_AUDIO_SVC_SEP_ADD
|
||||
err = bt_le_has_init();
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif /* BLE_AUDIO_SVC_SEP_ADD */
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_has_preset_register(const esp_ble_audio_has_preset_register_param_t *param)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (param == NULL ||
|
||||
param->index == ESP_BLE_AUDIO_HAS_PRESET_INDEX_NONE ||
|
||||
param->name == NULL ||
|
||||
param->ops == NULL || param->ops->select == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (strlen(param->name) < ESP_BLE_AUDIO_HAS_PRESET_NAME_MIN ||
|
||||
strlen(param->name) > ESP_BLE_AUDIO_HAS_PRESET_NAME_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (!IS_ENABLED(CONFIG_BT_HAS_PRESET_NAME_DYNAMIC) &&
|
||||
(param->properties & ESP_BLE_AUDIO_HAS_PROP_WRITABLE) > 0) {
|
||||
/* Writable presets is not supported */
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_has_preset_register_safe(param);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_has_preset_unregister(uint8_t index)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (index == ESP_BLE_AUDIO_HAS_PRESET_INDEX_NONE) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_has_preset_unregister_safe(index);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_has_preset_available(uint8_t index)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (index == ESP_BLE_AUDIO_HAS_PRESET_INDEX_NONE) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_has_preset_available_safe(index);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_has_preset_unavailable(uint8_t index)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (index == ESP_BLE_AUDIO_HAS_PRESET_INDEX_NONE) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_has_preset_unavailable_safe(index);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_has_preset_active_set(uint8_t index)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (index == ESP_BLE_AUDIO_HAS_PRESET_INDEX_NONE) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_has_preset_active_set_safe(index);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
uint8_t esp_ble_audio_has_preset_active_get(void)
|
||||
{
|
||||
return bt_has_preset_active_get_safe();
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_has_preset_name_change(uint8_t index, const char *name)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (index == ESP_BLE_AUDIO_HAS_PRESET_INDEX_NONE || name == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (strlen(name) < ESP_BLE_AUDIO_HAS_PRESET_NAME_MIN ||
|
||||
strlen(name) > ESP_BLE_AUDIO_HAS_PRESET_NAME_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_has_preset_name_change_safe(index, name);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_has_features_set(const esp_ble_audio_has_features_param_t *features)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (features == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_has_features_set_safe(features);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_HAS */
|
||||
@@ -0,0 +1,947 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_ble_audio_mcs_defs.h"
|
||||
#include "esp_ble_audio_mcc_api.h"
|
||||
|
||||
#if CONFIG_BT_MCC
|
||||
esp_err_t esp_ble_audio_mcc_init(esp_ble_audio_mcc_cb_t *cb)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_mcc_init_safe(cb);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_mcc_discover_mcs(uint16_t conn_handle, bool subscribe)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_discover_mcs(conn, subscribe);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_mcc_read_player_name(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_read_player_name(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_MCC_READ_MEDIA_PLAYER_ICON_URL
|
||||
esp_err_t esp_ble_audio_mcc_read_icon_url(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_read_icon_url(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCC_READ_MEDIA_PLAYER_ICON_URL */
|
||||
|
||||
#if CONFIG_BT_MCC_READ_TRACK_TITLE
|
||||
esp_err_t esp_ble_audio_mcc_read_track_title(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_read_track_title(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCC_READ_TRACK_TITLE */
|
||||
|
||||
#if CONFIG_BT_MCC_READ_TRACK_DURATION
|
||||
esp_err_t esp_ble_audio_mcc_read_track_duration(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_read_track_duration(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCC_READ_TRACK_DURATION */
|
||||
|
||||
#if CONFIG_BT_MCC_READ_TRACK_POSITION
|
||||
esp_err_t esp_ble_audio_mcc_read_track_position(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_read_track_position(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCC_READ_TRACK_POSITION */
|
||||
|
||||
#if CONFIG_BT_MCC_SET_TRACK_POSITION
|
||||
esp_err_t esp_ble_audio_mcc_set_track_position(uint16_t conn_handle, int32_t pos)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_set_track_position(conn, pos);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCC_SET_TRACK_POSITION */
|
||||
|
||||
#if CONFIG_BT_MCC_READ_PLAYBACK_SPEED
|
||||
esp_err_t esp_ble_audio_mcc_read_playback_speed(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_read_playback_speed(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCC_READ_PLAYBACK_SPEED */
|
||||
|
||||
#if CONFIG_BT_MCC_SET_PLAYBACK_SPEED
|
||||
esp_err_t esp_ble_audio_mcc_set_playback_speed(uint16_t conn_handle, int8_t speed)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_set_playback_speed(conn, speed);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCC_SET_PLAYBACK_SPEED */
|
||||
|
||||
#if CONFIG_BT_MCC_READ_SEEKING_SPEED
|
||||
esp_err_t esp_ble_audio_mcc_read_seeking_speed(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_read_seeking_speed(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCC_READ_SEEKING_SPEED */
|
||||
|
||||
#if CONFIG_BT_MCC_READ_PLAYING_ORDER
|
||||
esp_err_t esp_ble_audio_mcc_read_playing_order(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_read_playing_order(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCC_READ_PLAYING_ORDER */
|
||||
|
||||
#if CONFIG_BT_MCC_SET_PLAYING_ORDER
|
||||
esp_err_t esp_ble_audio_mcc_set_playing_order(uint16_t conn_handle, uint8_t order)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_set_playing_order(conn, order);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCC_SET_PLAYING_ORDER */
|
||||
|
||||
#if CONFIG_BT_MCC_READ_PLAYING_ORDER_SUPPORTED
|
||||
esp_err_t esp_ble_audio_mcc_read_playing_orders_supported(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_read_playing_orders_supported(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCC_READ_PLAYING_ORDER_SUPPORTED */
|
||||
|
||||
#if CONFIG_BT_MCC_READ_MEDIA_STATE
|
||||
esp_err_t esp_ble_audio_mcc_read_media_state(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_read_media_state(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCC_READ_MEDIA_STATE */
|
||||
|
||||
#if CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT
|
||||
#define MCS_VALID_OP(opcode) \
|
||||
(IN_RANGE((opcode), ESP_BLE_AUDIO_MCS_OPC_PLAY, ESP_BLE_AUDIO_MCS_OPC_STOP) || \
|
||||
(opcode == ESP_BLE_AUDIO_MCS_OPC_MOVE_RELATIVE) || \
|
||||
IN_RANGE((opcode), ESP_BLE_AUDIO_MCS_OPC_PREV_SEGMENT, ESP_BLE_AUDIO_MCS_OPC_GOTO_SEGMENT) || \
|
||||
IN_RANGE((opcode), ESP_BLE_AUDIO_MCS_OPC_PREV_TRACK, ESP_BLE_AUDIO_MCS_OPC_GOTO_TRACK) || \
|
||||
IN_RANGE((opcode), ESP_BLE_AUDIO_MCS_OPC_PREV_GROUP, ESP_BLE_AUDIO_MCS_OPC_GOTO_GROUP))
|
||||
|
||||
esp_err_t esp_ble_audio_mcc_send_cmd(uint16_t conn_handle,
|
||||
const esp_ble_audio_mpl_cmd_t *cmd)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
if (cmd == NULL || MCS_VALID_OP(cmd->opcode) == false) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_send_cmd(conn, cmd);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT */
|
||||
|
||||
#if CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED
|
||||
esp_err_t esp_ble_audio_mcc_read_opcodes_supported(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_read_opcodes_supported(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED */
|
||||
|
||||
#if CONFIG_BT_MCC_READ_CONTENT_CONTROL_ID
|
||||
esp_err_t esp_ble_audio_mcc_read_content_control_id(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_read_content_control_id(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCC_READ_CONTENT_CONTROL_ID */
|
||||
|
||||
#if CONFIG_BT_MCC_OTS
|
||||
esp_err_t esp_ble_audio_mcc_read_icon_obj_id(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_read_icon_obj_id(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_mcc_read_segments_obj_id(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_read_segments_obj_id(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_mcc_read_current_track_obj_id(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_read_current_track_obj_id(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_mcc_set_current_track_obj_id(uint16_t conn_handle, uint64_t id)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
if (ESP_BLE_AUDIO_MCS_VALID_OBJ_ID(id) == false) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_set_current_track_obj_id(conn, id);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_mcc_read_next_track_obj_id(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_read_next_track_obj_id(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_mcc_set_next_track_obj_id(uint16_t conn_handle, uint64_t id)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
if (ESP_BLE_AUDIO_MCS_VALID_OBJ_ID(id) == false) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_set_next_track_obj_id(conn, id);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_mcc_read_current_group_obj_id(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_read_current_group_obj_id(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_mcc_set_current_group_obj_id(uint16_t conn_handle, uint64_t id)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
if (ESP_BLE_AUDIO_MCS_VALID_OBJ_ID(id) == false) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_set_current_group_obj_id(conn, id);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_mcc_read_parent_group_obj_id(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_read_parent_group_obj_id(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_mcc_send_search(uint16_t conn_handle,
|
||||
const esp_ble_audio_mpl_search_t *search)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
if (search == NULL || IN_RANGE(search->len,
|
||||
ESP_BLE_AUDIO_SEARCH_LEN_MIN,
|
||||
ESP_BLE_AUDIO_SEARCH_LEN_MAX) == false) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_send_search(conn, search);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_mcc_read_search_results_obj_id(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_read_search_results_obj_id(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_mcc_otc_read_object_metadata(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_otc_read_object_metadata(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_mcc_otc_read_icon_object(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_otc_read_icon_object(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_mcc_otc_read_track_segments_object(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_otc_read_track_segments_object(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_mcc_otc_read_current_track_object(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_otc_read_current_track_object(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_mcc_otc_read_next_track_object(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_otc_read_next_track_object(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_mcc_otc_read_current_group_object(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_otc_read_current_group_object(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_mcc_otc_read_parent_group_object(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_mcc_otc_read_parent_group_object(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_MCC_SHELL
|
||||
struct bt_ots_client *esp_ble_audio_mcc_otc_inst(uint16_t conn_handle)
|
||||
{
|
||||
struct bt_ots_client *ret = NULL;
|
||||
void *conn;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = bt_mcc_otc_inst(conn);
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCC_SHELL */
|
||||
#endif /* CONFIG_BT_MCC_OTS */
|
||||
#endif /* CONFIG_BT_MCC */
|
||||
@@ -0,0 +1,585 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_ble_audio_mcs_defs.h"
|
||||
#include "esp_ble_audio_media_proxy_api.h"
|
||||
|
||||
#if CONFIG_BT_MCTL_LOCAL_PLAYER_LOCAL_CONTROL
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_register(esp_ble_audio_media_proxy_ctrl_cbs_t *ctrl_cbs)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (ctrl_cbs == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_register_safe(ctrl_cbs);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
|
||||
|
||||
#if CONFIG_BT_MCTL_REMOTE_PLAYER_CONTROL
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_discover_player(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_discover_player(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCTL_REMOTE_PLAYER_CONTROL */
|
||||
|
||||
#if CONFIG_BT_MCTL_LOCAL_PLAYER_LOCAL_CONTROL || CONFIG_BT_MCTL_REMOTE_PLAYER_CONTROL
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_player_name(esp_ble_audio_media_player_t *player)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_get_player_name_safe(player);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_icon_id(esp_ble_audio_media_player_t *player)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_get_icon_id_safe(player);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_icon_url(esp_ble_audio_media_player_t *player)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_get_icon_url_safe(player);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_track_title(esp_ble_audio_media_player_t *player)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_get_track_title_safe(player);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_track_duration(esp_ble_audio_media_player_t *player)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_get_track_duration_safe(player);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_track_position(esp_ble_audio_media_player_t *player)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_get_track_position_safe(player);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_set_track_position(esp_ble_audio_media_player_t *player,
|
||||
int32_t position)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_set_track_position_safe(player, position);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_playback_speed(esp_ble_audio_media_player_t *player)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_get_playback_speed_safe(player);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_set_playback_speed(esp_ble_audio_media_player_t *player,
|
||||
int8_t speed)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_set_playback_speed_safe(player, speed);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_seeking_speed(esp_ble_audio_media_player_t *player)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_get_seeking_speed_safe(player);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_track_segments_id(esp_ble_audio_media_player_t *player)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_get_track_segments_id_safe(player);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_current_track_id(esp_ble_audio_media_player_t *player)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_get_current_track_id_safe(player);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_set_current_track_id(esp_ble_audio_media_player_t *player,
|
||||
uint64_t id)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL || (IS_ENABLED(CONFIG_BT_MCTL_LOCAL_PLAYER_LOCAL_CONTROL) &&
|
||||
ESP_BLE_AUDIO_MCS_VALID_OBJ_ID(id) == false)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_set_current_track_id_safe(player, id);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_next_track_id(esp_ble_audio_media_player_t *player)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_get_next_track_id_safe(player);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_set_next_track_id(esp_ble_audio_media_player_t *player,
|
||||
uint64_t id)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL || ESP_BLE_AUDIO_MCS_VALID_OBJ_ID(id) == false) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_set_next_track_id_safe(player, id);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_parent_group_id(esp_ble_audio_media_player_t *player)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_get_parent_group_id_safe(player);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_current_group_id(esp_ble_audio_media_player_t *player)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_get_current_group_id_safe(player);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_set_current_group_id(esp_ble_audio_media_player_t *player,
|
||||
uint64_t id)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL || (IS_ENABLED(CONFIG_BT_MCTL_LOCAL_PLAYER_LOCAL_CONTROL) &&
|
||||
ESP_BLE_AUDIO_MCS_VALID_OBJ_ID(id) == false)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_set_current_group_id_safe(player, id);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_playing_order(esp_ble_audio_media_player_t *player)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_get_playing_order_safe(player);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_set_playing_order(esp_ble_audio_media_player_t *player,
|
||||
uint8_t order)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_set_playing_order_safe(player, order);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_playing_orders_supported(esp_ble_audio_media_player_t *player)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_get_playing_orders_supported_safe(player);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_media_state(esp_ble_audio_media_player_t *player)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_get_media_state_safe(player);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_send_command(esp_ble_audio_media_player_t *player,
|
||||
const esp_ble_audio_mpl_cmd_t *command)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL || command == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_send_command_safe(player, command);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_commands_supported(esp_ble_audio_media_player_t *player)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_get_commands_supported_safe(player);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_send_search(esp_ble_audio_media_player_t *player,
|
||||
const esp_ble_audio_mpl_search_t *search)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL || search == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_send_search_safe(player, search);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_search_results_id(esp_ble_audio_media_player_t *player)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_get_search_results_id_safe(player);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_content_ctrl_id(esp_ble_audio_media_player_t *player)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (player == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_ctrl_get_content_ctrl_id_safe(player);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCTL_LOCAL_PLAYER_LOCAL_CONTROL || CONFIG_BT_MCTL_REMOTE_PLAYER_CONTROL */
|
||||
|
||||
#if CONFIG_BT_MCTL_LOCAL_PLAYER_CONTROL
|
||||
static bool pl_calls_is_valid(const esp_ble_audio_media_proxy_pl_calls_t *pl_calls)
|
||||
{
|
||||
if (pl_calls == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pl_calls->get_player_name == NULL ||
|
||||
pl_calls->get_icon_url == NULL ||
|
||||
pl_calls->get_track_title == NULL ||
|
||||
pl_calls->get_track_duration == NULL ||
|
||||
pl_calls->get_track_position == NULL ||
|
||||
pl_calls->set_track_position == NULL ||
|
||||
pl_calls->get_playback_speed == NULL ||
|
||||
pl_calls->set_playback_speed == NULL ||
|
||||
pl_calls->get_seeking_speed == NULL ||
|
||||
pl_calls->get_playing_order == NULL ||
|
||||
pl_calls->set_playing_order == NULL ||
|
||||
pl_calls->get_playing_orders_supported == NULL ||
|
||||
pl_calls->get_media_state == NULL ||
|
||||
pl_calls->send_command == NULL ||
|
||||
pl_calls->get_commands_supported == NULL ||
|
||||
pl_calls->get_content_ctrl_id == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_MPL_OBJECTS
|
||||
if (pl_calls->get_icon_id == NULL ||
|
||||
pl_calls->get_track_segments_id == NULL ||
|
||||
pl_calls->get_current_track_id == NULL ||
|
||||
pl_calls->set_current_track_id == NULL ||
|
||||
pl_calls->get_next_track_id == NULL ||
|
||||
pl_calls->set_next_track_id == NULL ||
|
||||
pl_calls->get_parent_group_id == NULL ||
|
||||
pl_calls->get_current_group_id == NULL ||
|
||||
pl_calls->set_current_group_id == NULL ||
|
||||
pl_calls->send_search == NULL ||
|
||||
pl_calls->get_search_results_id == NULL) {
|
||||
return false;
|
||||
}
|
||||
#endif /* CONFIG_BT_MPL_OBJECTS */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_pl_register(esp_ble_audio_media_proxy_pl_calls_t *pl_calls)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (pl_calls_is_valid(pl_calls) == false) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_media_proxy_pl_register_safe(pl_calls);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_media_proxy_pl_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_media_proxy_pl_init_safe();
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_MCS && BLE_AUDIO_SVC_SEP_ADD
|
||||
err = bt_le_media_proxy_pl_init();
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCS && BLE_AUDIO_SVC_SEP_ADD */
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCTL_LOCAL_PLAYER_CONTROL */
|
||||
|
||||
#if CONFIG_BT_MCS && CONFIG_BT_OTS
|
||||
struct bt_ots *esp_ble_audio_mcs_get_ots(void)
|
||||
{
|
||||
return bt_mcs_get_ots_safe();
|
||||
}
|
||||
#endif /* CONFIG_BT_MCS && CONFIG_BT_OTS */
|
||||
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_ble_audio_micp_api.h"
|
||||
|
||||
#if CONFIG_BT_MICP_MIC_DEV
|
||||
esp_err_t esp_ble_audio_micp_mic_dev_register(esp_ble_audio_micp_mic_dev_register_param_t *param)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (param == NULL ||
|
||||
(CONFIG_BT_MICP_MIC_DEV_AICS_INSTANCE_COUNT && param->aics_param == NULL)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_micp_mic_dev_register_safe(param);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
#if BLE_AUDIO_SVC_SEP_ADD
|
||||
err = bt_le_micp_mic_dev_init();
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif /* BLE_AUDIO_SVC_SEP_ADD */
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_micp_mic_dev_included_get(esp_ble_audio_micp_included_t *included)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (included == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_micp_mic_dev_included_get_safe(included);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_micp_mic_dev_unmute(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_micp_mic_dev_unmute_safe();
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_micp_mic_dev_mute(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_micp_mic_dev_mute_safe();
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_micp_mic_dev_mute_disable(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_micp_mic_dev_mute_disable_safe();
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_micp_mic_dev_mute_get(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_micp_mic_dev_mute_get_safe();
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_MICP_MIC_DEV */
|
||||
|
||||
#if CONFIG_BT_MICP_MIC_CTLR
|
||||
#if CONFIG_BT_MICP_MIC_CTLR_AICS
|
||||
esp_err_t esp_ble_audio_micp_mic_ctlr_included_get(esp_ble_audio_micp_mic_ctlr_t *mic_ctlr,
|
||||
esp_ble_audio_micp_included_t *included)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (mic_ctlr == NULL || included == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_micp_mic_ctlr_included_get_safe(mic_ctlr, included);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_MICP_MIC_CTLR_AICS */
|
||||
|
||||
esp_ble_audio_micp_mic_ctlr_t *esp_ble_audio_micp_mic_ctlr_get_by_conn(uint16_t conn_handle)
|
||||
{
|
||||
esp_ble_audio_micp_mic_ctlr_t *ret = NULL;
|
||||
void *conn;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = bt_micp_mic_ctlr_get_by_conn(conn);
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_micp_mic_ctlr_discover(uint16_t conn_handle,
|
||||
esp_ble_audio_micp_mic_ctlr_t **mic_ctlr)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
if (mic_ctlr == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_micp_mic_ctlr_discover(conn, mic_ctlr);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_micp_mic_ctlr_unmute(esp_ble_audio_micp_mic_ctlr_t *mic_ctlr)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (mic_ctlr == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_micp_mic_ctlr_unmute_safe(mic_ctlr);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_micp_mic_ctlr_mute(esp_ble_audio_micp_mic_ctlr_t *mic_ctlr)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (mic_ctlr == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_micp_mic_ctlr_mute_safe(mic_ctlr);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_micp_mic_ctlr_mute_get(esp_ble_audio_micp_mic_ctlr_t *mic_ctlr)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (mic_ctlr == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_micp_mic_ctlr_mute_get_safe(mic_ctlr);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_micp_mic_ctlr_cb_register(esp_ble_audio_micp_mic_ctlr_cb_t *cb)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (cb == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_micp_mic_ctlr_cb_register_safe(cb);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_MICP_MIC_CTLR */
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Intel Corporation
|
||||
* SPDX-FileCopyrightText: 2021-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_ble_audio_pacs_api.h"
|
||||
|
||||
#if CONFIG_BT_PACS
|
||||
esp_err_t esp_ble_audio_pacs_register(const esp_ble_audio_pacs_register_param_t *param)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (param == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_pacs_register_safe(param);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_pacs_unregister(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_pacs_unregister_safe();
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static bool dir_is_valid(esp_ble_audio_dir_t dir)
|
||||
{
|
||||
if (dir != ESP_BLE_AUDIO_DIR_SINK &&
|
||||
dir != ESP_BLE_AUDIO_DIR_SOURCE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_pacs_cap_register(esp_ble_audio_dir_t dir,
|
||||
esp_ble_audio_pacs_cap_t *cap)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (dir_is_valid(dir) == false ||
|
||||
cap == NULL || cap->codec_cap == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_pacs_cap_register_safe(dir, cap);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_pacs_cap_unregister(esp_ble_audio_dir_t dir,
|
||||
esp_ble_audio_pacs_cap_t *cap)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (dir_is_valid(dir) == false || cap == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_pacs_cap_unregister_safe(dir, cap);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_pacs_set_location(esp_ble_audio_dir_t dir,
|
||||
esp_ble_audio_location_t location)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (dir_is_valid(dir) == false) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_pacs_set_location_safe(dir, location);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_pacs_set_available_contexts(esp_ble_audio_dir_t dir,
|
||||
esp_ble_audio_context_t contexts)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (dir_is_valid(dir) == false) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_pacs_set_available_contexts_safe(dir, contexts);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_ble_audio_context_t esp_ble_audio_pacs_get_available_contexts(esp_ble_audio_dir_t dir)
|
||||
{
|
||||
if (dir_is_valid(dir) == false) {
|
||||
return ESP_BLE_AUDIO_CONTEXT_TYPE_NONE;
|
||||
}
|
||||
|
||||
return bt_pacs_get_available_contexts_safe(dir);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_pacs_conn_set_available_contexts_for_conn(uint16_t conn_handle,
|
||||
esp_ble_audio_dir_t dir,
|
||||
esp_ble_audio_context_t *contexts)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
/* Note: contexts could be NULL */
|
||||
|
||||
if (dir_is_valid(dir) == false) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_pacs_conn_set_available_contexts_for_conn(conn, dir, contexts);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_ble_audio_context_t esp_ble_audio_pacs_get_available_contexts_for_conn(uint16_t conn_handle,
|
||||
esp_ble_audio_dir_t dir)
|
||||
{
|
||||
esp_ble_audio_context_t ret = ESP_BLE_AUDIO_CONTEXT_TYPE_NONE;
|
||||
void *conn;
|
||||
|
||||
if (dir_is_valid(dir) == false) {
|
||||
return ESP_BLE_AUDIO_CONTEXT_TYPE_NONE;
|
||||
}
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = bt_pacs_get_available_contexts_for_conn(conn, dir);
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_pacs_set_supported_contexts(esp_ble_audio_dir_t dir,
|
||||
esp_ble_audio_context_t contexts)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (dir_is_valid(dir) == false) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_pacs_set_supported_contexts_safe(dir, contexts);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_PACS */
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 NXP
|
||||
* SPDX-FileCopyrightText: 2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_ble_audio_pbp_api.h"
|
||||
|
||||
#if CONFIG_BT_PBP
|
||||
esp_err_t esp_ble_audio_pbp_get_announcement(const uint8_t meta[], size_t meta_len,
|
||||
esp_ble_audio_pbp_announcement_feature_t features,
|
||||
struct net_buf_simple *pba_data_buf)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (pba_data_buf == NULL ||
|
||||
pba_data_buf->size < (meta_len + ESP_BLE_AUDIO_PBP_MIN_PBA_SIZE)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if ((meta == NULL && meta_len != 0) || (meta != NULL && meta_len == 0)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_pbp_get_announcement(meta, meta_len, features, pba_data_buf);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_pbp_parse_announcement(uint8_t data_type, const uint8_t *data, uint8_t data_len,
|
||||
esp_ble_audio_pbp_announcement_feature_t *features,
|
||||
uint8_t **meta, uint8_t *meta_len)
|
||||
{
|
||||
struct bt_data ad = {
|
||||
.type = data_type,
|
||||
.data = data,
|
||||
.data_len = data_len,
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (data == NULL || data_len == 0 || features == NULL ||
|
||||
meta == NULL || meta_len == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (data_type != BT_DATA_SVC_DATA16 ||
|
||||
data_len < ESP_BLE_AUDIO_PBP_MIN_PBA_SIZE) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ret = bt_pbp_parse_announcement(&ad, features, meta);
|
||||
if (ret < 0) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
*meta_len = ret;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_PBP */
|
||||
@@ -0,0 +1,997 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Bose Corporation
|
||||
* SPDX-FileCopyrightText: 2021 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_ble_audio_tbs_api.h"
|
||||
|
||||
#if CONFIG_BT_TBS
|
||||
esp_err_t esp_ble_audio_tbs_accept(uint8_t call_index)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_tbs_accept_safe(call_index);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_tbs_hold(uint8_t call_index)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_tbs_hold_safe(call_index);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_tbs_retrieve(uint8_t call_index)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_tbs_retrieve_safe(call_index);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_tbs_terminate(uint8_t call_index)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_tbs_terminate_safe(call_index);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_tbs_originate(uint8_t bearer_index,
|
||||
char *uri,
|
||||
uint8_t *call_index)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (uri == NULL || call_index == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_tbs_originate_safe(bearer_index, uri, call_index);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_tbs_join(uint8_t call_index_cnt, uint8_t *call_indexes)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (call_index_cnt == 0 || call_indexes == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_tbs_join_safe(call_index_cnt, call_indexes);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_tbs_remote_answer(uint8_t call_index)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_tbs_remote_answer_safe(call_index);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_tbs_remote_hold(uint8_t call_index)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_tbs_remote_hold_safe(call_index);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_tbs_remote_retrieve(uint8_t call_index)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_tbs_remote_retrieve_safe(call_index);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_tbs_remote_terminate(uint8_t call_index)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_tbs_remote_terminate_safe(call_index);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_tbs_remote_incoming(uint8_t bearer_index,
|
||||
const char *to,
|
||||
const char *from,
|
||||
const char *friendly_name,
|
||||
uint8_t *call_index)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (to == NULL || from == NULL ||
|
||||
friendly_name == NULL || call_index == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ret = bt_tbs_remote_incoming_safe(bearer_index, to, from, friendly_name);
|
||||
if (ret < 0) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
*call_index = ret;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_tbs_set_bearer_provider_name(uint8_t bearer_index, const char *name)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (name == NULL || strlen(name) == 0 ||
|
||||
strlen(name) >= CONFIG_BT_TBS_MAX_PROVIDER_NAME_LENGTH) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_tbs_set_bearer_provider_name_safe(bearer_index, name);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_tbs_set_bearer_technology(uint8_t bearer_index, uint8_t new_technology)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (new_technology < ESP_BLE_AUDIO_TBS_TECHNOLOGY_3G ||
|
||||
new_technology > ESP_BLE_AUDIO_TBS_TECHNOLOGY_WCDMA) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_tbs_set_bearer_technology_safe(bearer_index, new_technology);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_tbs_set_signal_strength(uint8_t bearer_index, uint8_t new_signal_strength)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (new_signal_strength > ESP_BLE_AUDIO_TBS_SIGNAL_STRENGTH_MAX &&
|
||||
new_signal_strength != ESP_BLE_AUDIO_TBS_SIGNAL_STRENGTH_UNKNOWN) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_tbs_set_signal_strength_safe(bearer_index, new_signal_strength);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#define TBS_VALID_STATUS_FLAGS(val) ((val) <= (BIT(0) | BIT(1)))
|
||||
|
||||
esp_err_t esp_ble_audio_tbs_set_status_flags(uint8_t bearer_index, uint16_t status_flags)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (TBS_VALID_STATUS_FLAGS(status_flags) == false) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_tbs_set_status_flags_safe(bearer_index, status_flags);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_tbs_set_uri_scheme_list(uint8_t bearer_index,
|
||||
const char **uri_list,
|
||||
uint8_t uri_count)
|
||||
{
|
||||
uint8_t count = CONFIG_BT_TBS_BEARER_COUNT;
|
||||
int err;
|
||||
|
||||
if (count == 0 || bearer_index >= count ||
|
||||
(uri_count && uri_list == NULL)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_tbs_set_uri_scheme_list_safe(bearer_index, uri_list, uri_count);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void esp_ble_audio_tbs_register_cb(esp_ble_audio_tbs_cb_t *cbs)
|
||||
{
|
||||
bt_tbs_register_cb_safe(cbs);
|
||||
}
|
||||
|
||||
static bool valid_register_param(const esp_ble_audio_tbs_register_param_t *param)
|
||||
{
|
||||
if (param == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (param->provider_name == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strlen(param->provider_name) == 0 ||
|
||||
strlen(param->provider_name) >= CONFIG_BT_TBS_MAX_PROVIDER_NAME_LENGTH) {
|
||||
/* Provider name empty or length not less than CONFIG_BT_TBS_MAX_PROVIDER_NAME_LENGTH */
|
||||
return false;
|
||||
}
|
||||
|
||||
if (param->uci == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (param->uri_schemes_supported == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IN_RANGE(param->technology,
|
||||
ESP_BLE_AUDIO_TBS_TECHNOLOGY_3G,
|
||||
ESP_BLE_AUDIO_TBS_TECHNOLOGY_WCDMA) == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (param->supported_features > ESP_BLE_AUDIO_TBS_FEATURE_ALL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CONFIG_BT_TBS_BEARER_COUNT == 0 && param->gtbs == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_tbs_register_bearer(const esp_ble_audio_tbs_register_param_t *param,
|
||||
uint8_t *bearer_index)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (param == NULL || valid_register_param(param) == false || bearer_index == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Note: currently only GTBS is supported */
|
||||
if (param->gtbs == false) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ret = bt_tbs_register_bearer_safe(param);
|
||||
if (ret < 0) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
*bearer_index = ret;
|
||||
|
||||
#if BLE_AUDIO_SVC_SEP_ADD
|
||||
if (bt_le_gtbs_init()) {
|
||||
bt_tbs_unregister_bearer_safe(*bearer_index);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif /* BLE_AUDIO_SVC_SEP_ADD */
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_tbs_unregister_bearer(uint8_t bearer_index)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_tbs_unregister_bearer_safe(bearer_index);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT
|
||||
esp_err_t esp_ble_audio_tbs_client_discover(uint16_t conn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_discover(conn);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT_SET_BEARER_SIGNAL_INTERVAL
|
||||
esp_err_t esp_ble_audio_tbs_client_set_signal_strength_interval(uint16_t conn_handle,
|
||||
uint8_t inst_index,
|
||||
uint8_t interval)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_set_signal_strength_interval(conn, inst_index, interval);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_SET_BEARER_SIGNAL_INTERVAL */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT_ORIGINATE_CALL
|
||||
#define TBS_MIN_URI_LEN 3 /* a:b */
|
||||
#define FIRST_PRINTABLE_ASCII_CHAR ' ' /* space */
|
||||
|
||||
static inline bool tbs_valid_uri(const uint8_t *uri, size_t uri_len)
|
||||
{
|
||||
if (uri_len > CONFIG_BT_TBS_MAX_URI_LENGTH || uri_len < TBS_MIN_URI_LEN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (uri[0] < FIRST_PRINTABLE_ASCII_CHAR) {
|
||||
/* Invalid first char */
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 1; i < uri_len; i++) {
|
||||
if (uri[i] == ':' && uri[i + 1] >= FIRST_PRINTABLE_ASCII_CHAR) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_tbs_client_originate_call(uint16_t conn_handle,
|
||||
uint8_t inst_index,
|
||||
const char *uri)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
if (uri == NULL ||
|
||||
tbs_valid_uri((const uint8_t *)uri, strlen(uri)) == false) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_originate_call(conn, inst_index, uri);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_ORIGINATE_CALL */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT_TERMINATE_CALL
|
||||
esp_err_t esp_ble_audio_tbs_client_terminate_call(uint16_t conn_handle,
|
||||
uint8_t inst_index,
|
||||
uint8_t call_index)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_terminate_call(conn, inst_index, call_index);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_TERMINATE_CALL */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT_HOLD_CALL
|
||||
esp_err_t esp_ble_audio_tbs_client_hold_call(uint16_t conn_handle,
|
||||
uint8_t inst_index,
|
||||
uint8_t call_index)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_hold_call(conn, inst_index, call_index);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_HOLD_CALL */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT_ACCEPT_CALL
|
||||
esp_err_t esp_ble_audio_tbs_client_accept_call(uint16_t conn_handle,
|
||||
uint8_t inst_index,
|
||||
uint8_t call_index)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_accept_call(conn, inst_index, call_index);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_ACCEPT_CALL */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT_RETRIEVE_CALL
|
||||
esp_err_t esp_ble_audio_tbs_client_retrieve_call(uint16_t conn_handle,
|
||||
uint8_t inst_index,
|
||||
uint8_t call_index)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_retrieve_call(conn, inst_index, call_index);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_RETRIEVE_CALL */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT_JOIN_CALLS
|
||||
esp_err_t esp_ble_audio_tbs_client_join_calls(uint16_t conn_handle,
|
||||
uint8_t inst_index,
|
||||
const uint8_t *call_indexes,
|
||||
uint8_t count)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
if (call_indexes == NULL ||
|
||||
count < 2 || count > CONFIG_BT_TBS_CLIENT_MAX_CALLS) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_join_calls(conn, inst_index, call_indexes, count);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_JOIN_CALLS */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME
|
||||
esp_err_t esp_ble_audio_tbs_client_read_bearer_provider_name(uint16_t conn_handle, uint8_t inst_index)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_read_bearer_provider_name(conn, inst_index);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT_BEARER_UCI
|
||||
esp_err_t esp_ble_audio_tbs_client_read_bearer_uci(uint16_t conn_handle, uint8_t inst_index)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_read_bearer_uci(conn, inst_index);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_UCI */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY
|
||||
esp_err_t esp_ble_audio_tbs_client_read_technology(uint16_t conn_handle, uint8_t inst_index)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_read_technology(conn, inst_index);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST
|
||||
esp_err_t esp_ble_audio_tbs_client_read_uri_list(uint16_t conn_handle, uint8_t inst_index)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_read_uri_list(conn, inst_index);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH
|
||||
esp_err_t esp_ble_audio_tbs_client_read_signal_strength(uint16_t conn_handle, uint8_t inst_index)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_read_signal_strength(conn, inst_index);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT_READ_BEARER_SIGNAL_INTERVAL
|
||||
esp_err_t esp_ble_audio_tbs_client_read_signal_interval(uint16_t conn_handle, uint8_t inst_index)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_read_signal_interval(conn, inst_index);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_READ_BEARER_SIGNAL_INTERVAL */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS
|
||||
esp_err_t esp_ble_audio_tbs_client_read_current_calls(uint16_t conn_handle, uint8_t inst_index)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_read_current_calls(conn, inst_index);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT_CCID
|
||||
esp_err_t esp_ble_audio_tbs_client_read_ccid(uint16_t conn_handle, uint8_t inst_index)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_read_ccid(conn, inst_index);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_CCID */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT_INCOMING_URI
|
||||
esp_err_t esp_ble_audio_tbs_client_read_call_uri(uint16_t conn_handle, uint8_t inst_index)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_read_call_uri(conn, inst_index);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_INCOMING_URI */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT_STATUS_FLAGS
|
||||
esp_err_t esp_ble_audio_tbs_client_read_status_flags(uint16_t conn_handle, uint8_t inst_index)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_read_status_flags(conn, inst_index);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_STATUS_FLAGS */
|
||||
|
||||
esp_err_t esp_ble_audio_tbs_client_read_call_state(uint16_t conn_handle, uint8_t inst_index)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_read_call_state(conn, inst_index);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT_INCOMING_CALL
|
||||
esp_err_t esp_ble_audio_tbs_client_read_remote_uri(uint16_t conn_handle, uint8_t inst_index)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_read_remote_uri(conn, inst_index);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_INCOMING_CALL */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME
|
||||
esp_err_t esp_ble_audio_tbs_client_read_friendly_name(uint16_t conn_handle, uint8_t inst_index)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_read_friendly_name(conn, inst_index);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES
|
||||
esp_err_t esp_ble_audio_tbs_client_read_optional_opcodes(uint16_t conn_handle, uint8_t inst_index)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_read_optional_opcodes(conn, inst_index);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES */
|
||||
|
||||
esp_err_t esp_ble_audio_tbs_client_register_cb(esp_ble_audio_tbs_client_cb_t *cbs)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (cbs == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_tbs_client_register_cb_safe(cbs);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT_CCID
|
||||
esp_ble_audio_tbs_instance_t *esp_ble_audio_tbs_client_get_by_ccid(uint16_t conn_handle, uint8_t ccid)
|
||||
{
|
||||
esp_ble_audio_tbs_instance_t *ret = NULL;
|
||||
void *conn;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = lib_tbs_client_get_by_ccid(conn, ccid);
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_CCID */
|
||||
#endif /* CONFIG_BT_TBS_CLIENT */
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 NXP
|
||||
* SPDX-FileCopyrightText: 2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_ble_audio_tmap_api.h"
|
||||
|
||||
#if CONFIG_BT_TMAP
|
||||
esp_err_t esp_ble_audio_tmap_register(esp_ble_audio_tmap_role_t role)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_tmap_register_safe(role);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
#if BLE_AUDIO_SVC_SEP_ADD
|
||||
err = bt_le_tmas_init();
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif /* BLE_AUDIO_SVC_SEP_ADD */
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_tmap_discover(uint16_t conn_handle,
|
||||
const esp_ble_audio_tmap_cb_t *tmap_cb)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_tmap_discover(conn, tmap_cb);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void esp_ble_audio_tmap_set_role(esp_ble_audio_tmap_role_t role)
|
||||
{
|
||||
bt_tmap_set_role_safe(role);
|
||||
}
|
||||
#endif /* CONFIG_BT_TMAP */
|
||||
@@ -0,0 +1,430 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_ble_audio_vcp_api.h"
|
||||
|
||||
#if CONFIG_BT_VCP_VOL_REND
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_included_get(esp_ble_audio_vcp_included_t *included)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (included == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_vcp_vol_rend_included_get_safe(included);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_register(esp_ble_audio_vcp_vol_rend_register_param_t *param)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (param == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (CONFIG_BT_VCP_VOL_REND_VOCS_INSTANCE_COUNT && param->vocs_param == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT && param->aics_param == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (param->mute > ESP_BLE_AUDIO_VCP_STATE_MUTED || param->step == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_vcp_vol_rend_register_safe(param);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
#if BLE_AUDIO_SVC_SEP_ADD
|
||||
err = bt_le_vcp_vol_rend_init();
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif /* BLE_AUDIO_SVC_SEP_ADD */
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_set_step(uint8_t volume_step)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (volume_step == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_vcp_vol_rend_set_step_safe(volume_step);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_get_state(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_vcp_vol_rend_get_state_safe();
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_get_flags(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_vcp_vol_rend_get_flags_safe();
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_vol_down(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_vcp_vol_rend_vol_down_safe();
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_vol_up(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_vcp_vol_rend_vol_up_safe();
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_unmute_vol_down(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_vcp_vol_rend_unmute_vol_down_safe();
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_unmute_vol_up(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_vcp_vol_rend_unmute_vol_up_safe();
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_set_vol(uint8_t volume)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_vcp_vol_rend_set_vol_safe(volume);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_unmute(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_vcp_vol_rend_unmute_safe();
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_mute(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_vcp_vol_rend_mute_safe();
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_VCP_VOL_REND */
|
||||
|
||||
#if CONFIG_BT_VCP_VOL_CTLR
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_cb_register(esp_ble_audio_vcp_vol_ctlr_cb_t *cb)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (cb == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_vcp_vol_ctlr_cb_register_safe(cb);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_cb_unregister(esp_ble_audio_vcp_vol_ctlr_cb_t *cb)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (cb == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_vcp_vol_ctlr_cb_unregister_safe(cb);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_discover(uint16_t conn_handle,
|
||||
esp_ble_audio_vcp_vol_ctlr_t **vol_ctlr)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
if (vol_ctlr == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_vcp_vol_ctlr_discover(conn, vol_ctlr);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_ble_audio_vcp_vol_ctlr_t *esp_ble_audio_vcp_vol_ctlr_get_by_conn(uint16_t conn_handle)
|
||||
{
|
||||
esp_ble_audio_vcp_vol_ctlr_t *ret = NULL;
|
||||
void *conn;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = bt_vcp_vol_ctlr_get_by_conn(conn);
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_VCP_VOL_CTLR_VOCS || CONFIG_BT_VCP_VOL_CTLR_AICS
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_included_get(esp_ble_audio_vcp_vol_ctlr_t *vol_ctlr,
|
||||
esp_ble_audio_vcp_included_t *included)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (vol_ctlr == NULL || included == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_vcp_vol_ctlr_included_get_safe(vol_ctlr, included);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_VCP_VOL_CTLR_VOCS || CONFIG_BT_VCP_VOL_CTLR_AICS */
|
||||
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_read_state(esp_ble_audio_vcp_vol_ctlr_t *vol_ctlr)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (vol_ctlr == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_vcp_vol_ctlr_read_state_safe(vol_ctlr);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_read_flags(esp_ble_audio_vcp_vol_ctlr_t *vol_ctlr)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (vol_ctlr == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_vcp_vol_ctlr_read_flags_safe(vol_ctlr);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_vol_down(esp_ble_audio_vcp_vol_ctlr_t *vol_ctlr)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (vol_ctlr == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_vcp_vol_ctlr_vol_down_safe(vol_ctlr);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_vol_up(esp_ble_audio_vcp_vol_ctlr_t *vol_ctlr)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (vol_ctlr == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_vcp_vol_ctlr_vol_up_safe(vol_ctlr);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_unmute_vol_down(esp_ble_audio_vcp_vol_ctlr_t *vol_ctlr)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (vol_ctlr == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_vcp_vol_ctlr_unmute_vol_down_safe(vol_ctlr);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_unmute_vol_up(esp_ble_audio_vcp_vol_ctlr_t *vol_ctlr)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (vol_ctlr == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_vcp_vol_ctlr_unmute_vol_up_safe(vol_ctlr);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_set_vol(esp_ble_audio_vcp_vol_ctlr_t *vol_ctlr, uint8_t volume)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (vol_ctlr == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_vcp_vol_ctlr_set_vol_safe(vol_ctlr, volume);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_unmute(esp_ble_audio_vcp_vol_ctlr_t *vol_ctlr)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (vol_ctlr == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_vcp_vol_ctlr_unmute_safe(vol_ctlr);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_mute(esp_ble_audio_vcp_vol_ctlr_t *vol_ctlr)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (vol_ctlr == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_vcp_vol_ctlr_mute_safe(vol_ctlr);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_VCP_VOL_CTLR */
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_ble_audio_vocs_api.h"
|
||||
|
||||
#if CONFIG_BT_VOCS
|
||||
esp_ble_audio_vocs_t *esp_ble_audio_vocs_free_instance_get(void)
|
||||
{
|
||||
return bt_vocs_free_instance_get_safe();
|
||||
}
|
||||
|
||||
void *esp_ble_audio_vocs_svc_decl_get(esp_ble_audio_vocs_t *vocs)
|
||||
{
|
||||
if (vocs == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return bt_vocs_svc_decl_get_safe(vocs);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vocs_register(esp_ble_audio_vocs_t *vocs,
|
||||
const esp_ble_audio_vocs_register_param_t *param)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (vocs == NULL || param == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_vocs_register_safe(vocs, param);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_VOCS */
|
||||
|
||||
#if CONFIG_BT_VOCS || CONFIG_BT_VOCS_CLIENT
|
||||
esp_err_t esp_ble_audio_vocs_state_get(esp_ble_audio_vocs_t *inst)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_vocs_state_get_safe(inst);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vocs_state_set(esp_ble_audio_vocs_t *inst, int16_t offset)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_vocs_state_set_safe(inst, offset);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vocs_location_get(esp_ble_audio_vocs_t *inst)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_vocs_location_get_safe(inst);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vocs_location_set(esp_ble_audio_vocs_t *inst, uint32_t location)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_vocs_location_set_safe(inst, location);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vocs_description_get(esp_ble_audio_vocs_t *inst)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_vocs_description_get_safe(inst);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vocs_description_set(esp_ble_audio_vocs_t *inst,
|
||||
const char *description)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (inst == NULL || description == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_vocs_description_set_safe(inst, description);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_VOCS || CONFIG_BT_VOCS_CLIENT */
|
||||
|
||||
#if CONFIG_BT_VOCS_CLIENT
|
||||
esp_err_t esp_ble_audio_vocs_client_cb_register(esp_ble_audio_vocs_t *inst,
|
||||
esp_ble_audio_vocs_cb_t *cb)
|
||||
{
|
||||
if (inst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
bt_vocs_client_cb_register_safe(inst, cb);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_ble_audio_vocs_t *esp_ble_audio_vocs_client_free_instance_get(void)
|
||||
{
|
||||
return bt_vocs_client_free_instance_get_safe();
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_vocs_discover(uint16_t conn_handle,
|
||||
esp_ble_audio_vocs_t *inst,
|
||||
const esp_ble_audio_vocs_discover_param_t *param)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
if (inst == NULL || param == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (param->start_handle == 0 ||
|
||||
param->end_handle == 0 ||
|
||||
param->end_handle < param->start_handle) {
|
||||
/* Start handle and end handle shall be non-zero and
|
||||
* start handle shall be less than end handle.
|
||||
*/
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_vocs_discover(conn, inst, param);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_VOCS_CLIENT */
|
||||
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_BLE_AUDIO_AICS_API_H_
|
||||
#define ESP_BLE_AUDIO_AICS_API_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include <zephyr/bluetooth/audio/audio.h>
|
||||
#include <zephyr/bluetooth/audio/aics.h>
|
||||
|
||||
#include "common/init.h"
|
||||
#include "common/host.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!< The mute state is unmuted */
|
||||
#define ESP_BLE_AUDIO_AICS_STATE_UNMUTED BT_AICS_STATE_UNMUTED
|
||||
/*!< The mute state is muted */
|
||||
#define ESP_BLE_AUDIO_AICS_STATE_MUTED BT_AICS_STATE_MUTED
|
||||
/*!< The mute state is disabled */
|
||||
#define ESP_BLE_AUDIO_AICS_STATE_MUTE_DISABLED BT_AICS_STATE_MUTE_DISABLED
|
||||
|
||||
/*!< The gain mode is manual only and cannot be changed to automatic */
|
||||
#define ESP_BLE_AUDIO_AICS_MODE_MANUAL_ONLY BT_AICS_MODE_MANUAL_ONLY
|
||||
/*!< The gain mode is automatic only and cannot be changed to manual */
|
||||
#define ESP_BLE_AUDIO_AICS_MODE_AUTO_ONLY BT_AICS_MODE_AUTO_ONLY
|
||||
/*!< The gain mode is manual */
|
||||
#define ESP_BLE_AUDIO_AICS_MODE_MANUAL BT_AICS_MODE_MANUAL
|
||||
/*!< The gain mode is automatic */
|
||||
#define ESP_BLE_AUDIO_AICS_MODE_AUTO BT_AICS_MODE_AUTO
|
||||
|
||||
/*!< The input is unspecified */
|
||||
#define ESP_BLE_AUDIO_AICS_INPUT_TYPE_UNSPECIFIED BT_AICS_INPUT_TYPE_UNSPECIFIED
|
||||
/*!< The input is a Bluetooth Audio Stream */
|
||||
#define ESP_BLE_AUDIO_AICS_INPUT_TYPE_BLUETOOTH BT_AICS_INPUT_TYPE_BLUETOOTH
|
||||
/*!< The input is a microphone */
|
||||
#define ESP_BLE_AUDIO_AICS_INPUT_TYPE_MICROPHONE BT_AICS_INPUT_TYPE_MICROPHONE
|
||||
/*!< The input is analog */
|
||||
#define ESP_BLE_AUDIO_AICS_INPUT_TYPE_ANALOG BT_AICS_INPUT_TYPE_ANALOG
|
||||
/*!< The input is digital */
|
||||
#define ESP_BLE_AUDIO_AICS_INPUT_TYPE_DIGITAL BT_AICS_INPUT_TYPE_DIGITAL
|
||||
/*!< The input is a radio (AM/FM/XM/etc.) */
|
||||
#define ESP_BLE_AUDIO_AICS_INPUT_TYPE_RADIO BT_AICS_INPUT_TYPE_RADIO
|
||||
/*!< The input is a Streaming Audio Source */
|
||||
#define ESP_BLE_AUDIO_AICS_INPUT_TYPE_STREAMING BT_AICS_INPUT_TYPE_STREAMING
|
||||
/*!< The input is transparent / pass-through */
|
||||
#define ESP_BLE_AUDIO_AICS_INPUT_TYPE_AMBIENT BT_AICS_INPUT_TYPE_AMBIENT
|
||||
|
||||
/** Audio Input Control Service instance. */
|
||||
typedef struct bt_aics esp_ble_audio_aics_t;
|
||||
|
||||
/** Structure to hold callbacks for Audio Input Control Service. */
|
||||
typedef struct bt_aics_cb esp_ble_audio_aics_cb_t;
|
||||
|
||||
/** Structure for initializing an Audio Input Control Service instance. */
|
||||
typedef struct bt_aics_register_param esp_ble_audio_aics_register_param_t;
|
||||
|
||||
/** Structure for discovering an Audio Input Control Service instance. */
|
||||
typedef struct bt_aics_discover_param esp_ble_audio_aics_discover_param_t;
|
||||
|
||||
/**
|
||||
* @brief Get a free instance of Audio Input Control Service from the pool.
|
||||
*
|
||||
* @return Audio Input Control Service instance in case of success or NULL in case of error.
|
||||
*/
|
||||
esp_ble_audio_aics_t *esp_ble_audio_aics_free_instance_get(void);
|
||||
|
||||
/**
|
||||
* @brief Get the service declaration attribute.
|
||||
*
|
||||
* The first service attribute returned can be included in any other GATT service.
|
||||
*
|
||||
* @param aics Audio Input Control Service instance.
|
||||
*
|
||||
* @return Pointer to the attributes of the service.
|
||||
*/
|
||||
void *esp_ble_audio_aics_svc_decl_get(esp_ble_audio_aics_t *aics);
|
||||
|
||||
/**
|
||||
* @brief Initialize the Audio Input Control Service instance.
|
||||
*
|
||||
* @param aics Audio Input Control Service instance.
|
||||
* @param param Audio Input Control Service register parameters.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_aics_register(esp_ble_audio_aics_t *aics,
|
||||
esp_ble_audio_aics_register_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief Activates an Audio Input Control Service instance.
|
||||
*
|
||||
* Audio Input Control Services are activated by default, but this will allow
|
||||
* the server reactivate an Audio Input Control Service instance after it has
|
||||
* been deactivated.
|
||||
*
|
||||
* @param inst The instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_aics_activate(esp_ble_audio_aics_t *inst);
|
||||
|
||||
/**
|
||||
* @brief Deactivates an Audio Input Control Service instance.
|
||||
*
|
||||
* Audio Input Control Services are activated by default, but this will allow
|
||||
* the server to deactivate an Audio Input Control Service.
|
||||
*
|
||||
* @param inst The instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_aics_deactivate(esp_ble_audio_aics_t *inst);
|
||||
|
||||
/**
|
||||
* @brief Read the Audio Input Control Service input state.
|
||||
*
|
||||
* @param inst The instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_aics_state_get(esp_ble_audio_aics_t *inst);
|
||||
|
||||
/**
|
||||
* @brief Read the Audio Input Control Service gain settings.
|
||||
*
|
||||
* @param inst The instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_aics_gain_setting_get(esp_ble_audio_aics_t *inst);
|
||||
|
||||
/**
|
||||
* @brief Read the Audio Input Control Service input type.
|
||||
*
|
||||
* @param inst The instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_aics_type_get(esp_ble_audio_aics_t *inst);
|
||||
|
||||
/**
|
||||
* @brief Read the Audio Input Control Service input status.
|
||||
*
|
||||
* @param inst The instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_aics_status_get(esp_ble_audio_aics_t *inst);
|
||||
|
||||
/**
|
||||
* @brief Disable mute in the Audio Input Control Service.
|
||||
*
|
||||
* @param inst The instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_aics_disable_mute(esp_ble_audio_aics_t *inst);
|
||||
|
||||
/**
|
||||
* @brief Unmute the Audio Input Control Service input.
|
||||
*
|
||||
* @param inst The instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_aics_unmute(esp_ble_audio_aics_t *inst);
|
||||
|
||||
/**
|
||||
* @brief Mute the Audio Input Control Service input.
|
||||
*
|
||||
* @param inst The instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_aics_mute(esp_ble_audio_aics_t *inst);
|
||||
|
||||
/**
|
||||
* @brief Set manual only gain mode in Audio Input Control Service.
|
||||
*
|
||||
* @param inst The instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_aics_gain_set_manual_only(esp_ble_audio_aics_t *inst);
|
||||
|
||||
/**
|
||||
* @brief Set automatic only gain mode in Audio Input Control Service.
|
||||
*
|
||||
* @param inst The instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_aics_gain_set_auto_only(esp_ble_audio_aics_t *inst);
|
||||
|
||||
/**
|
||||
* @brief Set input gain to manual.
|
||||
*
|
||||
* @param inst The instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_aics_manual_gain_set(esp_ble_audio_aics_t *inst);
|
||||
|
||||
/**
|
||||
* @brief Set the input gain to automatic.
|
||||
*
|
||||
* @param inst The instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_aics_automatic_gain_set(esp_ble_audio_aics_t *inst);
|
||||
|
||||
/**
|
||||
* @brief Set the input gain.
|
||||
*
|
||||
* @param inst The instance pointer.
|
||||
* @param gain The gain to set (-128 to 127) in gain setting units.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_aics_gain_set(esp_ble_audio_aics_t *inst, int8_t gain);
|
||||
|
||||
/**
|
||||
* @brief Read the Audio Input Control Service description.
|
||||
*
|
||||
* @param inst The instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_aics_description_get(esp_ble_audio_aics_t *inst);
|
||||
|
||||
/**
|
||||
* @brief Set the Audio Input Control Service description.
|
||||
*
|
||||
* @param inst The instance pointer.
|
||||
* @param description The description as an UTF-8 encoded string.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_aics_description_set(esp_ble_audio_aics_t *inst,
|
||||
const char *description);
|
||||
|
||||
/**
|
||||
* @brief Discover an Audio Input Control Service.
|
||||
*
|
||||
* Attempts to discover an Audio Input Control Service on a server given the
|
||||
* @p param.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst The instance pointer.
|
||||
* @param param Pointer to the parameters.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_aics_discover(uint16_t conn_handle, esp_ble_audio_aics_t *inst,
|
||||
const esp_ble_audio_aics_discover_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief Get a new Audio Input Control Service client instance.
|
||||
*
|
||||
* @return Pointer to the instance, or NULL if no free instances are left.
|
||||
*/
|
||||
esp_ble_audio_aics_t *esp_ble_audio_aics_client_free_instance_get(void);
|
||||
|
||||
/**
|
||||
* @brief Registers the callbacks for the Audio Input Control Service client.
|
||||
*
|
||||
* @param inst The instance pointer.
|
||||
* @param cb Pointer to the callback structure.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_aics_client_cb_register(esp_ble_audio_aics_t *inst,
|
||||
esp_ble_audio_aics_cb_t *cb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_BLE_AUDIO_AICS_API_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,967 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFS_H_
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFS_H_
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include <zephyr/bluetooth/audio/bap_lc3_preset.h>
|
||||
|
||||
#include "esp_ble_audio_lc3_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Struct to hold a BAP defined LC3 preset */
|
||||
typedef struct bt_bap_lc3_preset esp_ble_audio_bap_lc3_preset_t;
|
||||
|
||||
/*!< Helper to declare an LC3 preset structure */
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_PRESET(_codec, _qos) \
|
||||
BT_BAP_LC3_PRESET(_codec, _qos)
|
||||
|
||||
/**
|
||||
* @brief Define an LC3 preset configuration.
|
||||
*
|
||||
* @param _name Preset configuration name.
|
||||
* @param _freq Sample frequency (in Hz).
|
||||
* @param _duration Frame duration (in microseconds).
|
||||
* @param _loc Audio channel location.
|
||||
* @param _len Frame length in octets.
|
||||
* @param _frames_per_sdu Number of frames per SDU.
|
||||
* @param _stream_context Stream context (e.g., Media, Conversational, etc.).
|
||||
* @param _interval Audio frame interval (in microseconds).
|
||||
* @param _sdu SDU size in octets.
|
||||
* @param _rtn Number of retransmissions.
|
||||
* @param _latency Maximum transport latency (in milliseconds).
|
||||
* @param _pd Presentation delay (in microseconds).
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, _freq, _duration, _loc, _len, \
|
||||
_frames_per_sdu, _stream_context, \
|
||||
_interval, _sdu, _rtn, _latency, _pd) \
|
||||
static uint8_t codec_cfg_data_##_name[] = \
|
||||
ESP_BLE_AUDIO_CODEC_CFG_LC3_DATA(_freq, _duration, _loc, _len, _frames_per_sdu); \
|
||||
static uint8_t codec_cfg_meta_##_name[] = \
|
||||
ESP_BLE_AUDIO_CODEC_CFG_LC3_META(_stream_context); \
|
||||
static esp_ble_audio_bap_lc3_preset_t _name = \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET(ESP_BLE_AUDIO_CODEC_CFG_LC3(codec_cfg_data_##_name, \
|
||||
codec_cfg_meta_##_name), \
|
||||
ESP_BLE_AUDIO_BAP_QOS_CFG_UNFRAMED(_interval, _sdu, _rtn, \
|
||||
_latency, _pd));
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 8_1_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_8_1_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_8KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 26u, 1, \
|
||||
_stream_context, \
|
||||
7500u, 26u, 2u, 8u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 8_2_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_8_2_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_8KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 30U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 30u, 2u, 10u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 16_1_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_16_1_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_16KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 30U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 30u, 2u, 8u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 16_2_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_16_2_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_16KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 40U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 40u, 2u, 10u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 24_1_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_24_1_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_24KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 45U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 45u, 2u, 8u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 24_2_1 codec configuration.
|
||||
*
|
||||
* Mandatory to support as unicast server.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_24_2_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_24KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 60U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 60u, 2u, 10u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 32_1_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_32_1_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_32KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 60U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 60u, 2u, 8u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 32_2_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_32_2_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_32KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 80U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 80u, 2u, 10u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 441_1_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_441_1_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_44KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 97U, 1, \
|
||||
_stream_context, \
|
||||
8163u, 97u, 5u, 24u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 441_2_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_441_2_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_44KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 130U, 1, \
|
||||
_stream_context, \
|
||||
10884u, 130u, 5u, 31u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 48_1_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_48_1_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 75U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 75u, 5u, 15u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 48_2_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_48_2_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 100U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 100u, 5u, 20u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 48_3_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_48_3_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 90U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 90u, 5u, 15u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 48_4_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_48_4_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 120u, 1, \
|
||||
_stream_context, \
|
||||
10000u, 120u, 5u, 20u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 48_5_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_48_5_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 117u, 1, \
|
||||
_stream_context, \
|
||||
7500u, 117u, 5u, 15u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 48_6_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_48_6_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 155u, 1, \
|
||||
_stream_context, \
|
||||
10000u, 155u, 5u, 20u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 8_1_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_8_1_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_8KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 26u, 1, \
|
||||
_stream_context, \
|
||||
7500u, 26u, 13u, 75u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 8_2_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_8_2_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_8KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 30U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 30u, 13u, 95u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 16_1_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_16_1_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_16KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 30U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 30u, 13u, 75u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 16_2_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_16_2_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_16KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 40U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 40u, 13u, 95u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 24_1_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_24_1_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_24KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 45U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 45u, 13u, 75u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 24_2_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_24_2_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_24KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 60U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 60u, 13u, 95u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 32_1_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_32_1_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_32KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 60U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 60u, 13u, 75u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 32_2_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_32_2_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_32KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 80U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 80u, 13u, 95u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 441_1_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_441_1_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_44KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 97U, 1, \
|
||||
_stream_context, \
|
||||
8163u, 97u, 13u, 80u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 441_2_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_441_2_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_44KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 130U, 1, \
|
||||
_stream_context, \
|
||||
10884u, 130u, 13u, 85u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 48_1_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_48_1_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 75U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 75u, 13u, 75u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 48_2_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_48_2_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 100U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 100u, 13u, 95u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 48_3_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_48_3_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 90U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 90u, 13u, 75u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 48_4_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_48_4_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 120u, 1, \
|
||||
_stream_context, \
|
||||
10000u, 120u, 13u, 100u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 48_5_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_48_5_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 117u, 1, \
|
||||
_stream_context, \
|
||||
7500u, 117u, 13u, 75u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Unicast 48_6_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_UNICAST_PRESET_48_6_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 155u, 1, \
|
||||
_stream_context, \
|
||||
10000u, 155u, 13u, 100u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 8_1_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_8_1_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_8KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 26u, 1, \
|
||||
_stream_context, \
|
||||
7500u, 26u, 2u, 8u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 8_2_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_8_2_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_8KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 30U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 30u, 2u, 10u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 16_1_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_16_1_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_16KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 30U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 30u, 2u, 8u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 16_2_1 codec configuration.
|
||||
*
|
||||
* Mandatory to support as both broadcast source and sink.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_16_2_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_16KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 40U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 40u, 2u, 10u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 24_1_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_24_1_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_24KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 45U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 45u, 2u, 8u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 24_2_1 codec configuration.
|
||||
*
|
||||
* Mandatory to support as broadcast sink.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_24_2_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_24KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 60U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 60u, 2u, 10u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 32_1_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_32_1_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_32KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 60U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 60u, 2u, 8u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 32_2_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_32_2_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_32KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 80U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 80u, 2u, 10u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 441_1_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_441_1_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_44KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 97U, 1, \
|
||||
_stream_context, \
|
||||
8163u, 97u, 4u, 24u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 441_2_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_441_2_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_44KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 130U, 1, \
|
||||
_stream_context, \
|
||||
10884u, 130u, 4u, 31u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 48_1_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_48_1_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 75U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 75u, 4u, 15u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 48_2_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_48_2_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 100U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 100u, 4u, 20u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 48_3_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_48_3_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 90U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 90u, 4u, 15u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 48_4_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_48_4_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 120u, 1, \
|
||||
_stream_context, \
|
||||
10000u, 120u, 4u, 20u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 48_5_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_48_5_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 117u, 1, \
|
||||
_stream_context, \
|
||||
7500u, 117u, 4u, 15u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 48_6_1 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_48_6_1_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 155u, 1, \
|
||||
_stream_context, \
|
||||
10000u, 155u, 4u, 20u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 8_1_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_8_1_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_8KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 26u, 1, \
|
||||
_stream_context, \
|
||||
7500u, 26u, 4u, 45u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 8_2_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_8_2_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_8KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 30U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 30u, 4u, 60u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 16_1_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_16_1_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_16KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 30U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 30u, 4u, 45u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 16_2_2 codec configuration.
|
||||
*
|
||||
* Mandatory to support as both broadcast source and sink.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_16_2_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_16KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 40U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 40u, 4u, 60u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 24_1_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_24_1_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_24KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 45U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 45u, 4u, 45u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 24_2_2 codec configuration.
|
||||
*
|
||||
* Mandatory to support as broadcast sink.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_24_2_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_24KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 60U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 60u, 4u, 60u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 32_1_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_32_1_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_32KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 60U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 60u, 4u, 45u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 32_2_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_32_2_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_32KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 80U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 80u, 4u, 60u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 441_1_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_441_1_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_44KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 97U, 1, \
|
||||
_stream_context, \
|
||||
8163u, 97u, 4u, 54u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 441_2_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_441_2_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_44KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 130U, 1, \
|
||||
_stream_context, \
|
||||
10884u, 130u, 4u, 60u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 48_1_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_48_1_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 75U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 75u, 4u, 50u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 48_2_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_48_2_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 100U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 100u, 4u, 65u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 48_3_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_48_3_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 90U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 90u, 4u, 50u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 48_4_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_48_4_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 120u, 1, \
|
||||
_stream_context, \
|
||||
10000u, 120u, 4u, 65u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 48_5_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_48_5_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 117u, 1, \
|
||||
_stream_context, \
|
||||
7500u, 117u, 4u, 50u, 40000u)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 Broadcast 48_6_2 codec configuration.
|
||||
*
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_BAP_LC3_BROADCAST_PRESET_48_6_2_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 155u, 1, \
|
||||
_stream_context, \
|
||||
10000u, 155u, 4u, 65u, 40000u)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_BLE_AUDIO_BAP_LC3_PRESET_DEFS_H_ */
|
||||
@@ -0,0 +1,659 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_BLE_AUDIO_CAP_API_H_
|
||||
#define ESP_BLE_AUDIO_CAP_API_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include <zephyr/bluetooth/audio/audio.h>
|
||||
#include <zephyr/bluetooth/audio/cap.h>
|
||||
|
||||
#include "common/init.h"
|
||||
#include "common/host.h"
|
||||
|
||||
#include "esp_ble_audio_bap_api.h"
|
||||
#include "esp_ble_audio_csip_api.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!< The set is an ad-hoc set */
|
||||
#define ESP_BLE_AUDIO_CAP_SET_TYPE_AD_HOC BT_CAP_SET_TYPE_AD_HOC
|
||||
/*!< The set is a CSIP Coordinated Set */
|
||||
#define ESP_BLE_AUDIO_CAP_SET_TYPE_CSIP BT_CAP_SET_TYPE_CSIP
|
||||
/** Type of CAP set */
|
||||
typedef enum bt_cap_set_type esp_ble_audio_cap_set_type_t;
|
||||
|
||||
/** Common Audio Profile stream structure */
|
||||
typedef struct bt_cap_stream esp_ble_audio_cap_stream_t;
|
||||
|
||||
/** Common Audio Broadcast Source structure */
|
||||
typedef struct bt_cap_broadcast_source esp_ble_audio_cap_broadcast_source_t;
|
||||
|
||||
/** Common Audio Unicast Group structure */
|
||||
typedef struct bt_cap_unicast_group esp_ble_audio_cap_unicast_group_t;
|
||||
|
||||
/** Callback structure for CAP procedures */
|
||||
typedef struct bt_cap_initiator_cb esp_ble_audio_cap_initiator_cb_t;
|
||||
|
||||
/** Union represents a Common Audio Set member that are either in a Coordinated or ad-hoc set */
|
||||
typedef union bt_cap_set_member esp_ble_audio_cap_set_member_t;
|
||||
|
||||
/** Parameter structure for each stream in the unicast group */
|
||||
typedef struct bt_cap_unicast_group_stream_param \
|
||||
esp_ble_audio_cap_unicast_group_stream_param_t;
|
||||
|
||||
/* Parameter structure for the unicast group functions */
|
||||
typedef struct bt_cap_unicast_group_stream_pair_param \
|
||||
esp_ble_audio_cap_unicast_group_stream_pair_param_t;
|
||||
|
||||
/** Parameters for the creating unicast groups */
|
||||
typedef struct bt_cap_unicast_group_param \
|
||||
esp_ble_audio_cap_unicast_group_param_t;
|
||||
|
||||
/** CAP unicast audio stream specific parameters for starting audio */
|
||||
typedef struct bt_cap_unicast_audio_start_stream_param \
|
||||
esp_ble_audio_cap_unicast_audio_start_stream_param_t;
|
||||
|
||||
/** CAP unicast audio specific parameters for starting audio */
|
||||
typedef struct bt_cap_unicast_audio_start_param \
|
||||
esp_ble_audio_cap_unicast_audio_start_param_t;
|
||||
|
||||
/** CAP unicast audio stream specific parameters for updating audio */
|
||||
typedef struct bt_cap_unicast_audio_update_stream_param \
|
||||
esp_ble_audio_cap_unicast_audio_update_stream_param_t;
|
||||
|
||||
/** CAP unicast audio specific parameters for updating audio */
|
||||
typedef struct bt_cap_unicast_audio_update_param \
|
||||
esp_ble_audio_cap_unicast_audio_update_param_t;
|
||||
|
||||
/** CAP unicast audio specific parameters for stopping audio */
|
||||
typedef struct bt_cap_unicast_audio_stop_param \
|
||||
esp_ble_audio_cap_unicast_audio_stop_param_t;
|
||||
|
||||
/** CAP Initiator broadcast audio stream specific parameters */
|
||||
typedef struct bt_cap_initiator_broadcast_stream_param \
|
||||
esp_ble_audio_cap_initiator_broadcast_stream_param_t;
|
||||
|
||||
/** CAP Initiator broadcast audio subgroup specific parameters */
|
||||
typedef struct bt_cap_initiator_broadcast_subgroup_param \
|
||||
esp_ble_audio_cap_initiator_broadcast_subgroup_param_t;
|
||||
|
||||
/** CAP Initiator broadcast audio specific parameters for creating audio */
|
||||
typedef struct bt_cap_initiator_broadcast_create_param \
|
||||
esp_ble_audio_cap_initiator_broadcast_create_param_t;
|
||||
|
||||
/** Callback structure for CAP Handover procedures */
|
||||
typedef struct bt_cap_handover_cb esp_ble_audio_cap_handover_cb_t;
|
||||
|
||||
/** CAP Handover unicast audio to broadcast audio specific parameters */
|
||||
typedef struct bt_cap_handover_unicast_to_broadcast_param \
|
||||
esp_ble_audio_cap_handover_unicast_to_broadcast_param_t;
|
||||
|
||||
/** CAP Handover broadcast audio to unicast audio specific parameters */
|
||||
typedef struct bt_cap_handover_broadcast_to_unicast_param \
|
||||
esp_ble_audio_cap_handover_broadcast_to_unicast_param_t;
|
||||
|
||||
/** Callback structure for CAP Commander procedures */
|
||||
typedef struct bt_cap_commander_cb esp_ble_audio_cap_commander_cb_t;
|
||||
|
||||
/** CAP Commander broadcast audio member specific parameters for starting audio reception */
|
||||
typedef struct bt_cap_commander_broadcast_reception_start_member_param \
|
||||
esp_ble_audio_cap_commander_broadcast_reception_start_member_param_t;
|
||||
|
||||
/** CAP Commander broadcast audio specific parameters for starting audio reception */
|
||||
typedef struct bt_cap_commander_broadcast_reception_start_param \
|
||||
esp_ble_audio_cap_commander_broadcast_reception_start_param_t;
|
||||
|
||||
/** CAP Commander broadcast audio member specific parameters for stopping audio reception */
|
||||
typedef struct bt_cap_commander_broadcast_reception_stop_member_param \
|
||||
esp_ble_audio_cap_commander_broadcast_reception_stop_member_param_t;
|
||||
|
||||
/** CAP Commander broadcast audio specific parameters for stopping audio reception */
|
||||
typedef struct bt_cap_commander_broadcast_reception_stop_param \
|
||||
esp_ble_audio_cap_commander_broadcast_reception_stop_param_t;
|
||||
|
||||
/** CAP Commander member parameters for distributing broadcast code */
|
||||
typedef struct bt_cap_commander_distribute_broadcast_code_member_param \
|
||||
esp_ble_audio_cap_commander_distribute_broadcast_code_member_param_t;
|
||||
|
||||
/** Parameters for distributing broadcast code */
|
||||
typedef struct bt_cap_commander_distribute_broadcast_code_param \
|
||||
esp_ble_audio_cap_commander_distribute_broadcast_code_param_t;
|
||||
|
||||
/** Parameters for changing absolute volume */
|
||||
typedef struct bt_cap_commander_change_volume_param \
|
||||
esp_ble_audio_cap_commander_change_volume_param_t;
|
||||
|
||||
/** Parameters for changing volume offset for a member */
|
||||
typedef struct bt_cap_commander_change_volume_offset_member_param \
|
||||
esp_ble_audio_cap_commander_change_volume_offset_member_param_t;
|
||||
|
||||
/** Parameters for changing volume offset */
|
||||
typedef struct bt_cap_commander_change_volume_offset_param \
|
||||
esp_ble_audio_cap_commander_change_volume_offset_param_t;
|
||||
|
||||
/** Parameters for changing volume mute state */
|
||||
typedef struct bt_cap_commander_change_volume_mute_state_param \
|
||||
esp_ble_audio_cap_commander_change_volume_mute_state_param_t;
|
||||
|
||||
/** Parameters for changing microphone mute state */
|
||||
typedef struct bt_cap_commander_change_microphone_mute_state_param \
|
||||
esp_ble_audio_cap_commander_change_microphone_mute_state_param_t;
|
||||
|
||||
/** Parameters for changing microphone gain setting for a member */
|
||||
typedef struct bt_cap_commander_change_microphone_gain_setting_member_param \
|
||||
esp_ble_audio_cap_commander_change_microphone_gain_setting_member_param_t;
|
||||
|
||||
/** Parameters for changing microphone gain setting */
|
||||
typedef struct bt_cap_commander_change_microphone_gain_setting_param \
|
||||
esp_ble_audio_cap_commander_change_microphone_gain_setting_param_t;
|
||||
|
||||
/**
|
||||
* @brief Register the Common Audio Service.
|
||||
*
|
||||
* This will register and enable the service and make it discoverable by
|
||||
* clients. This will also register a Coordinated Set Identification
|
||||
* Service instance.
|
||||
*
|
||||
* @param param Coordinated Set Identification Service register parameters.
|
||||
* @param svc_inst Pointer to the registered Coordinated Set Identification Service.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_acceptor_register(const esp_ble_audio_csip_set_member_register_param_t *param,
|
||||
esp_ble_audio_csip_set_member_svc_inst_t **svc_inst);
|
||||
|
||||
/**
|
||||
* @brief Discovers audio support on a remote device.
|
||||
*
|
||||
* This will discover the Common Audio Service (CAS) on the remote device, to
|
||||
* verify if the remote device supports the Common Audio Profile.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_initiator_unicast_discover(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Register Audio operations for a Common Audio Profile stream.
|
||||
*
|
||||
* Register Audio operations for a stream.
|
||||
*
|
||||
* @param stream Stream object.
|
||||
* @param ops Stream operations structure.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_stream_ops_register(esp_ble_audio_cap_stream_t *stream,
|
||||
esp_ble_audio_bap_stream_ops_t *ops);
|
||||
|
||||
/**
|
||||
* @brief Send data to Common Audio Profile stream without timestamp.
|
||||
*
|
||||
* Sends data over the specified CAP audio stream with a sequence number.
|
||||
*
|
||||
* @param stream Stream object.
|
||||
* @param sdu Buffer containing data to be sent.
|
||||
* @param sdu_len Length of data to be sent.
|
||||
* @param seq_num Packet Sequence number. This value shall be incremented
|
||||
* for each call to this function and at least once per SDU
|
||||
* interval for a specific channel.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_stream_send(esp_ble_audio_cap_stream_t *stream,
|
||||
const uint8_t *sdu, uint16_t sdu_len,
|
||||
uint16_t seq_num);
|
||||
|
||||
/**
|
||||
* @brief Send data to Common Audio Profile stream with timestamp.
|
||||
*
|
||||
* Sends data over the specified CAP audio stream with a sequence number.
|
||||
*
|
||||
* @param stream Stream object.
|
||||
* @param sdu Buffer containing data to be sent.
|
||||
* @param sdu_len Length of data to be sent.
|
||||
* @param seq_num Packet Sequence number. This value shall be incremented
|
||||
* for each call to this function and at least once per SDU
|
||||
* interval for a specific channel.
|
||||
* @param ts Timestamp of the SDU in microseconds (us). This value can
|
||||
* be used to transmit multiple SDUs in the same SDU interval
|
||||
* in a CIG or BIG.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_stream_send_ts(esp_ble_audio_cap_stream_t *stream,
|
||||
const uint8_t *sdu, uint16_t sdu_len,
|
||||
uint16_t seq_num, uint32_t ts);
|
||||
|
||||
/**
|
||||
* @brief Get ISO transmission timing info for a Common Audio Profile stream.
|
||||
*
|
||||
* @param stream Stream object.
|
||||
* @param info Transmit info object.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_stream_get_tx_sync(esp_ble_audio_cap_stream_t *stream,
|
||||
esp_ble_iso_tx_info_t *info);
|
||||
|
||||
/**
|
||||
* @brief Create unicast group.
|
||||
*
|
||||
* Create a new audio unicast group with one or more audio streams as a unicast client.
|
||||
* All streams shall share the same framing.
|
||||
* All streams in the same direction shall share the same interval and latency (see
|
||||
* esp_ble_audio_bap_qos_cfg_t).
|
||||
*
|
||||
* @param param The unicast group create parameters.
|
||||
* @param unicast_group Pointer to the unicast group created.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_unicast_group_create(const esp_ble_audio_cap_unicast_group_param_t *param,
|
||||
esp_ble_audio_cap_unicast_group_t **unicast_group);
|
||||
|
||||
/**
|
||||
* @brief Reconfigure unicast group.
|
||||
*
|
||||
* Reconfigure a unicast group with one or more audio streams as a unicast client.
|
||||
* All streams shall share the same framing.
|
||||
* All streams in the same direction shall share the same interval and latency (see
|
||||
* esp_ble_audio_bap_qos_cfg_t).
|
||||
* All streams in @p param shall already belong to @p unicast_group.
|
||||
* Use esp_ble_audio_cap_unicast_group_add_streams() to add additional streams.
|
||||
*
|
||||
* @param unicast_group Pointer to the unicast group created.
|
||||
* @param param The unicast group reconfigure parameters.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_unicast_group_reconfig(esp_ble_audio_cap_unicast_group_t *unicast_group,
|
||||
const esp_ble_audio_cap_unicast_group_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief Add streams to a unicast group as a unicast client.
|
||||
*
|
||||
* This function can be used to add additional streams to a esp_ble_audio_cap_unicast_group_t.
|
||||
*
|
||||
* This can be called at any time before any of the streams in the group has been started
|
||||
* (see esp_ble_audio_bap_stream_ops_t.started()).
|
||||
* This can also be called after the streams have been stopped (see
|
||||
* esp_ble_audio_bap_stream_ops_t.stopped()).
|
||||
*
|
||||
* Once a stream has been added to a unicast group, it cannot be removed. To remove a stream
|
||||
* from a group, the group must be deleted with esp_ble_audio_cap_unicast_group_delete(), but
|
||||
* this will require all streams in the group to be released first.
|
||||
*
|
||||
* @param unicast_group Pointer to the unicast group
|
||||
* @param params Array of stream parameters with streams being added to the group.
|
||||
* @param num_param Number of parameters in @p params.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_unicast_group_add_streams(esp_ble_audio_cap_unicast_group_t *unicast_group,
|
||||
const esp_ble_audio_cap_unicast_group_stream_pair_param_t params[],
|
||||
size_t num_param);
|
||||
|
||||
/**
|
||||
* @brief Delete audio unicast group.
|
||||
*
|
||||
* Delete a audio unicast group as a client. All streams in the group shall
|
||||
* be in the idle or configured state.
|
||||
*
|
||||
* @param unicast_group Pointer to the unicast group to delete.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_unicast_group_delete(esp_ble_audio_cap_unicast_group_t *unicast_group);
|
||||
|
||||
/**
|
||||
* @brief Register Common Audio Profile Initiator callbacks.
|
||||
*
|
||||
* @param cb The callback structure. Shall remain static.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_initiator_register_cb(const esp_ble_audio_cap_initiator_cb_t *cb);
|
||||
|
||||
/**
|
||||
* @brief Unregister Common Audio Profile Initiator callbacks.
|
||||
*
|
||||
* @param cb The callback structure that was previously registered.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_initiator_unregister_cb(const esp_ble_audio_cap_initiator_cb_t *cb);
|
||||
|
||||
/**
|
||||
* @brief Setup and start unicast audio streams for a set of devices.
|
||||
*
|
||||
* @param param Parameters to start the audio streams.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_initiator_unicast_audio_start(const esp_ble_audio_cap_unicast_audio_start_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief Update unicast audio streams.
|
||||
*
|
||||
* This will update the metadata of one or more streams.
|
||||
*
|
||||
* @param param Update parameters.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_initiator_unicast_audio_update(const esp_ble_audio_cap_unicast_audio_update_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief Stop unicast audio streams.
|
||||
*
|
||||
* This will stop one or more streams.
|
||||
*
|
||||
* @param param Stop parameters.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_initiator_unicast_audio_stop(const esp_ble_audio_cap_unicast_audio_stop_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief Cancel any current Common Audio Profile procedure.
|
||||
*
|
||||
* This will stop the current procedure from continuing and making it possible to run a new
|
||||
* Common Audio Profile procedure.
|
||||
*
|
||||
* It is recommended to do this if any existing procedure takes longer time than expected, which
|
||||
* could indicate a missing response from the Common Audio Profile Acceptor.
|
||||
*
|
||||
* This does not send any requests to any Common Audio Profile Acceptors involved with the current
|
||||
* procedure, and thus notifications from the Common Audio Profile Acceptors may arrive after this
|
||||
* has been called. It is thus recommended to either only use this if a procedure has stalled, or
|
||||
* wait a short while before starting any new Common Audio Profile procedure after this has been
|
||||
* called to avoid getting notifications from the cancelled procedure. The wait time depends on
|
||||
* the connection interval, the number of devices in the previous procedure and the behavior of the
|
||||
* Common Audio Profile Acceptors.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_initiator_unicast_audio_cancel(void);
|
||||
|
||||
/**
|
||||
* @brief Create a Common Audio Profile broadcast source.
|
||||
*
|
||||
* Create a new audio broadcast source with one or more audio streams.
|
||||
*
|
||||
* @param param Parameters to start the audio streams.
|
||||
* @param broadcast_source Pointer to the broadcast source created.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_initiator_broadcast_audio_create(const esp_ble_audio_cap_initiator_broadcast_create_param_t *param,
|
||||
esp_ble_audio_cap_broadcast_source_t **broadcast_source);
|
||||
|
||||
/**
|
||||
* @brief Start Common Audio Profile broadcast source.
|
||||
*
|
||||
* The broadcast source will be visible for scanners once this has been called,
|
||||
* and the device will advertise audio announcements.
|
||||
*
|
||||
* @param broadcast_source Pointer to the broadcast source.
|
||||
* @param adv_handle Handle of an extended advertising set with
|
||||
* periodic advertising configured.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_initiator_broadcast_audio_start(
|
||||
esp_ble_audio_cap_broadcast_source_t *broadcast_source,
|
||||
uint8_t adv_handle);
|
||||
|
||||
/**
|
||||
* @brief Update broadcast audio streams for a Common Audio Profile broadcast source.
|
||||
*
|
||||
* @param broadcast_source The broadcast source to update.
|
||||
* @param meta The new metadata. The metadata shall contain a list
|
||||
* of CCIDs as well as a non-0 context bitfield.
|
||||
* @param meta_len The length of @p meta.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_initiator_broadcast_audio_update(esp_ble_audio_cap_broadcast_source_t *broadcast_source,
|
||||
const uint8_t meta[], size_t meta_len);
|
||||
|
||||
/**
|
||||
* @brief Stop broadcast audio streams for a Common Audio Profile broadcast source.
|
||||
*
|
||||
* @param broadcast_source The broadcast source to stop. The audio streams
|
||||
* in this will be stopped and reset.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_initiator_broadcast_audio_stop(esp_ble_audio_cap_broadcast_source_t *broadcast_source);
|
||||
|
||||
/**
|
||||
* @brief Delete Common Audio Profile broadcast source.
|
||||
*
|
||||
* @param broadcast_source The broadcast source to delete.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_initiator_broadcast_audio_delete(esp_ble_audio_cap_broadcast_source_t *broadcast_source);
|
||||
|
||||
/**
|
||||
* @brief Get the Broadcast Audio Stream Endpoint of a Common Audio Profile
|
||||
* broadcast source.
|
||||
*
|
||||
* This will encode the BASE of a broadcast source into a buffer, that can be
|
||||
* used for advertisement. The encoded BASE will thus be encoded as
|
||||
* little-endian. The BASE shall be put into the periodic advertising data.
|
||||
*
|
||||
* See table 3.15 in the Basic Audio Profile v1.0.1 for the structure.
|
||||
*
|
||||
* @param broadcast_source Pointer to the broadcast source.
|
||||
* @param base_buf Pointer to a buffer where the BASE will be inserted.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_initiator_broadcast_get_base(esp_ble_audio_cap_broadcast_source_t *broadcast_source,
|
||||
struct net_buf_simple *base_buf);
|
||||
|
||||
/**
|
||||
* @brief Register Common Audio Profile Handover callbacks.
|
||||
*
|
||||
* @param cb The callback structure. Shall remain static.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_handover_register_cb(const esp_ble_audio_cap_handover_cb_t *cb);
|
||||
|
||||
/**
|
||||
* @brief Unregister Common Audio Profile Handover callbacks.
|
||||
*
|
||||
* @param cb The callback structure that was previously registered.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_handover_unregister_cb(const esp_ble_audio_cap_handover_cb_t *cb);
|
||||
|
||||
/**
|
||||
* @brief Hands over the sink streams in a unicast group to a broadcast source.
|
||||
*
|
||||
* All streams in the provided unicast group will be stopped and released. The sink streams
|
||||
* will be transferred to a broadcast source, and the broadcast source information will be
|
||||
* shared with all accepters that are currently receiving audio. Any stream that is not in
|
||||
* the streaming state will only be released.
|
||||
*
|
||||
* esp_ble_audio_bap_broadcast_assistant_discover() must have been successfully perform for
|
||||
* all members in @p param before starting this procedure.
|
||||
*
|
||||
* @param param The parameters for the handover.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_handover_unicast_to_broadcast(
|
||||
const esp_ble_audio_cap_handover_unicast_to_broadcast_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief Hands over the data streams in a broadcast source to a unicast group.
|
||||
*
|
||||
* The streams in the broadcast source will be stopped and the broadcast source
|
||||
* will be deleted.
|
||||
*
|
||||
* @param param The parameters for the handover.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_handover_broadcast_to_unicast(
|
||||
const esp_ble_audio_cap_handover_broadcast_to_unicast_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief Register Common Audio Profile Commander callbacks.
|
||||
*
|
||||
* @param cb The callback structure. Shall remain static.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_commander_register_cb(const esp_ble_audio_cap_commander_cb_t *cb);
|
||||
|
||||
/**
|
||||
* @brief Unregister Common Audio Profile Commander callbacks.
|
||||
*
|
||||
* @param cb The callback structure that was previously registered.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_commander_unregister_cb(const esp_ble_audio_cap_commander_cb_t *cb);
|
||||
|
||||
/**
|
||||
* @brief Discovers audio support on a remote device.
|
||||
*
|
||||
* This will discover the Common Audio Service (CAS) on the remote device,
|
||||
* to verify if the remote device supports the Common Audio Profile.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_commander_discover(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Cancel any current Common Audio Profile commander procedure.
|
||||
*
|
||||
* This will stop the current procedure from continuing and making it possible to run a new
|
||||
* Common Audio Profile procedure.
|
||||
*
|
||||
* It is recommended to do this if any existing procedure takes longer time than expected, which
|
||||
* could indicate a missing response from the Common Audio Profile Acceptor.
|
||||
*
|
||||
* This does not send any requests to any Common Audio Profile Acceptors involved with the
|
||||
* current procedure, and thus notifications from the Common Audio Profile Acceptors may
|
||||
* arrive after this has been called. It is thus recommended to either only use this if a
|
||||
* procedure has stalled, or wait a short while before starting any new Common Audio Profile
|
||||
* procedure after this has been called to avoid getting notifications from the cancelled
|
||||
* procedure. The wait time depends on the connection interval, the number of devices in the
|
||||
* previous procedure and the behavior of the Common Audio Profile Acceptors.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_commander_cancel(void);
|
||||
|
||||
/**
|
||||
* @brief Starts the reception of broadcast audio on one or more remote
|
||||
* Common Audio Profile Acceptors.
|
||||
*
|
||||
* @param param The parameters to start the broadcast audio
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_commander_broadcast_reception_start(
|
||||
const esp_ble_audio_cap_commander_broadcast_reception_start_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief Stops the reception of broadcast audio on one or more remote
|
||||
* Common Audio Profile Acceptors.
|
||||
*
|
||||
* @param param The parameters to stop the broadcast audio
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_commander_broadcast_reception_stop(
|
||||
const esp_ble_audio_cap_commander_broadcast_reception_stop_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief Distributes the broadcast code on one or more remote Common
|
||||
* Audio Profile Acceptors.
|
||||
*
|
||||
* @param param The parameters for distributing the broadcast code.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_commander_distribute_broadcast_code(
|
||||
const esp_ble_audio_cap_commander_distribute_broadcast_code_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief Change the volume on one or more Common Audio Profile Acceptors.
|
||||
*
|
||||
* @param param The parameters for the volume change.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_commander_change_volume(
|
||||
const esp_ble_audio_cap_commander_change_volume_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief Change the volume offset on one or more Common Audio Profile Acceptors.
|
||||
*
|
||||
* @param param The parameters for the volume offset change.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_commander_change_volume_offset(
|
||||
const esp_ble_audio_cap_commander_change_volume_offset_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief Change the volume mute state on one or more Common Audio Profile Acceptors.
|
||||
*
|
||||
* @param param The parameters for the volume mute state change.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_commander_change_volume_mute_state(
|
||||
const esp_ble_audio_cap_commander_change_volume_mute_state_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief Change the microphone mute state on one or more Common Audio Profile Acceptors.
|
||||
*
|
||||
* @param param The parameters for the microphone mute state change.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_commander_change_microphone_mute_state(
|
||||
const esp_ble_audio_cap_commander_change_microphone_mute_state_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief Change the microphone gain setting on one or more Common Audio Profile Acceptors.
|
||||
*
|
||||
* @param param The parameters for the microphone gain setting change.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_cap_commander_change_microphone_gain_setting(
|
||||
const esp_ble_audio_cap_commander_change_microphone_gain_setting_param_t *param);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_BLE_AUDIO_CAP_API_H_ */
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_BLE_AUDIO_CCP_API_H_
|
||||
#define ESP_BLE_AUDIO_CCP_API_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include <zephyr/bluetooth/audio/audio.h>
|
||||
#include <zephyr/bluetooth/audio/ccp.h>
|
||||
|
||||
#include "common/init.h"
|
||||
#include "common/host.h"
|
||||
|
||||
#include "esp_ble_audio_tbs_api.h"
|
||||
#include "esp_ble_audio_common_api.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Abstract Call Control Server Telephone Bearer structure */
|
||||
typedef struct bt_ccp_call_control_server_bearer \
|
||||
esp_ble_audio_ccp_call_control_server_bearer_t;
|
||||
|
||||
/** Abstract Call Control Client structure. */
|
||||
typedef struct bt_ccp_call_control_client \
|
||||
esp_ble_audio_ccp_call_control_client_t;
|
||||
|
||||
/** Abstract Call Control Client bearer structure. */
|
||||
typedef struct bt_ccp_call_control_client_bearer \
|
||||
esp_ble_audio_ccp_call_control_client_bearer_t;
|
||||
|
||||
/** Struct with information about bearers of a client */
|
||||
typedef struct bt_ccp_call_control_client_bearers \
|
||||
esp_ble_audio_ccp_call_control_client_bearers_t;
|
||||
|
||||
/** Struct to hold the Telephone Bearer Service client callbacks */
|
||||
typedef struct bt_ccp_call_control_client_cb \
|
||||
esp_ble_audio_ccp_call_control_client_cb_t;
|
||||
|
||||
/**
|
||||
* @brief Register a Telephone Bearer.
|
||||
*
|
||||
* This will register a Telephone Bearer Service (TBS) (or a Generic Telephone
|
||||
* Bearer service (GTBS)) with the provided parameters.
|
||||
*
|
||||
* As per the TBS specification, the GTBS shall be instantiated for the feature,
|
||||
* and as such a GTBS shall always be registered before any TBS can be registered.
|
||||
* Similarly, all TBS shall be unregistered before the GTBS can be unregistered
|
||||
* with esp_ble_audio_ccp_call_control_server_unregister_bearer().
|
||||
*
|
||||
* @param param The parameters to initialize the bearer.
|
||||
* @param bearer Pointer to the initialized bearer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_ccp_call_control_server_register_bearer(
|
||||
const esp_ble_audio_tbs_register_param_t *param,
|
||||
esp_ble_audio_ccp_call_control_server_bearer_t **bearer);
|
||||
|
||||
/**
|
||||
* @brief Unregister a Telephone Bearer.
|
||||
*
|
||||
* This will unregister a Telephone Bearer Service (TBS) (or a Generic Telephone
|
||||
* Bearer service (GTBS)) with the provided parameters. The bearer shall be
|
||||
* registered first by esp_ble_audio_ccp_call_control_server_register_bearer()
|
||||
* before it can be unregistered.
|
||||
*
|
||||
* All TBS shall be unregistered before the GTBS can be unregistered with.
|
||||
*
|
||||
* @param bearer The bearer to unregister.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_ccp_call_control_server_unregister_bearer(
|
||||
esp_ble_audio_ccp_call_control_server_bearer_t *bearer);
|
||||
|
||||
/**
|
||||
* @brief Set a new bearer provider name.
|
||||
*
|
||||
* @param bearer The bearer to set the name for.
|
||||
* @param name The new bearer provider name.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_ccp_call_control_server_set_bearer_provider_name(
|
||||
esp_ble_audio_ccp_call_control_server_bearer_t *bearer, const char *name);
|
||||
|
||||
/**
|
||||
* @brief Get the bearer provider name.
|
||||
*
|
||||
* @param bearer The bearer to get the name for.
|
||||
* @param name Pointer that will be updated to be the bearer provider name.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_ccp_call_control_server_get_bearer_provider_name(
|
||||
esp_ble_audio_ccp_call_control_server_bearer_t *bearer, const char **name);
|
||||
|
||||
/**
|
||||
* @brief Discovers the Telephone Bearer Service (TBS) support on a remote device.
|
||||
*
|
||||
* This will discover the Telephone Bearer Service (TBS) and Generic Telephone Bearer
|
||||
* Service (GTBS) on the remote device.
|
||||
*
|
||||
* @param conn Connection to a remote server.
|
||||
* @param out_client Pointer to client instance on success.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_ccp_call_control_client_discover(
|
||||
esp_ble_conn_t *conn, esp_ble_audio_ccp_call_control_client_t **out_client);
|
||||
|
||||
/**
|
||||
* @brief Register callbacks for the Call Control Client.
|
||||
*
|
||||
* @param cb The callback struct.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_ccp_call_control_client_register_cb(
|
||||
esp_ble_audio_ccp_call_control_client_cb_t *cb);
|
||||
|
||||
/**
|
||||
* @brief Unregister callbacks for the Call Control Client.
|
||||
*
|
||||
* @param cb The callback struct.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_ccp_call_control_client_unregister_cb(
|
||||
esp_ble_audio_ccp_call_control_client_cb_t *cb);
|
||||
|
||||
/**
|
||||
* @brief Get the bearers of a client instance.
|
||||
*
|
||||
* @param client The client to get the bearers of.
|
||||
* @param bearers The bearers struct that will be populated
|
||||
* with the bearers of @p client.
|
||||
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_ccp_call_control_client_get_bearers(
|
||||
esp_ble_audio_ccp_call_control_client_t *client,
|
||||
esp_ble_audio_ccp_call_control_client_bearers_t *bearers);
|
||||
|
||||
/**
|
||||
* @brief Read the bearer provider name of a remote TBS bearer.
|
||||
*
|
||||
* @param bearer The bearer to read the name from.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_ccp_call_control_client_read_bearer_provider_name(
|
||||
esp_ble_audio_ccp_call_control_client_bearer_t *bearer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_BLE_AUDIO_CCP_API_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Intel Corporation
|
||||
* SPDX-FileCopyrightText: 2020-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_BLE_AUDIO_COMMON_API_H_
|
||||
#define ESP_BLE_AUDIO_COMMON_API_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include "common/init.h"
|
||||
#include "common/host.h"
|
||||
#include "common/app/gatt.h"
|
||||
|
||||
#include "esp_ble_iso_common_api.h"
|
||||
|
||||
#include "esp_ble_audio_defs.h"
|
||||
#include "esp_ble_audio_csip_api.h"
|
||||
#include "esp_ble_audio_vcp_api.h"
|
||||
#include "esp_ble_audio_micp_api.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Helper for parsing length-type-value data.
|
||||
*
|
||||
* @param ltv Length-type-value (LTV) encoded data.
|
||||
* @param size Size of the @p ltv data.
|
||||
* @param func Callback function which will be called for each element
|
||||
* that's found in the data. The callback should return
|
||||
* true to continue parsing, or false to stop parsing.
|
||||
* @param user_data User data to be passed to the callback.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_data_parse(const uint8_t ltv[], size_t size,
|
||||
bool (*func)(uint8_t type,
|
||||
const uint8_t *data,
|
||||
uint8_t data_len,
|
||||
void *user_data),
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Get the value of a specific data type in an length-type-value data array.
|
||||
*
|
||||
* @param ltv_data The array containing the length-type-value tuples.
|
||||
* @param size The size of @p ltv_data.
|
||||
* @param type The type to get the value for.
|
||||
* @param data Pointer to the data-pointer to update when item is found.
|
||||
* Any found data will be little endian.
|
||||
* @param data_len Length The length of found @p data (may be 0).
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_data_get_val(const uint8_t ltv_data[],
|
||||
size_t size, uint8_t type,
|
||||
const uint8_t **data,
|
||||
uint8_t *data_len);
|
||||
|
||||
/**
|
||||
* @brief Function to get the number of channels from the channel allocation.
|
||||
*
|
||||
* @param chan_allocation The channel allocation.
|
||||
*
|
||||
* @return The number of channels.
|
||||
*/
|
||||
uint8_t esp_ble_audio_get_chan_count(esp_ble_audio_location_t chan_allocation);
|
||||
|
||||
/**
|
||||
* @brief Start GATT service discovery.
|
||||
*
|
||||
* @note This function is only needed while using NimBLE Host.
|
||||
*
|
||||
* @param conn_handle Connection Handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_gattc_disc_start(uint16_t conn_handle);
|
||||
|
||||
/*!< Audio GAP Extended Scan Recv event */
|
||||
#define ESP_BLE_AUDIO_GAP_EVENT_EXT_SCAN_RECV BT_LE_GAP_APP_EVENT_EXT_SCAN_RECV
|
||||
/*!< Audio GAP Periodic Sync Established event */
|
||||
#define ESP_BLE_AUDIO_GAP_EVENT_PA_SYNC BT_LE_GAP_APP_EVENT_PA_SYNC
|
||||
/*!< Audio GAP Periodic Sync Lost event */
|
||||
#define ESP_BLE_AUDIO_GAP_EVENT_PA_SYNC_LOST BT_LE_GAP_APP_EVENT_PA_SYNC_LOST
|
||||
/*!< Audio GAP Connection Complete event */
|
||||
#define ESP_BLE_AUDIO_GAP_EVENT_ACL_CONNECT BT_LE_GAP_APP_EVENT_ACL_CONNECT
|
||||
/*!< Audio GAP Disconnection Complete event */
|
||||
#define ESP_BLE_AUDIO_GAP_EVENT_ACL_DISCONNECT BT_LE_GAP_APP_EVENT_ACL_DISCONNECT
|
||||
/*!< Audio GAP Security Change event */
|
||||
#define ESP_BLE_AUDIO_GAP_EVENT_SECURITY_CHANGE BT_LE_GAP_APP_EVENT_SECURITY_CHANGE
|
||||
/** Audio GAP application event structure */
|
||||
typedef struct bt_le_gap_app_event esp_ble_audio_gap_app_event_t;
|
||||
|
||||
/*!< Audio GATT MTU exchange complete event */
|
||||
#define ESP_BLE_AUDIO_GATT_EVENT_GATT_MTU_CHANGE BT_LE_GATT_APP_EVENT_GATT_MTU_CHANGE
|
||||
/*!< Audio GATT client discovery complete event */
|
||||
#define ESP_BLE_AUDIO_GATT_EVENT_GATTC_DISC_CMPL BT_LE_GATT_APP_EVENT_GATTC_DISC_CMPL
|
||||
/** Audio GATT application event structure */
|
||||
typedef struct bt_le_gatt_app_event esp_ble_audio_gatt_app_event_t;
|
||||
|
||||
/** Contains callback functions for GAP and GATT events */
|
||||
typedef struct {
|
||||
bt_le_gap_app_cb gap_cb; /*!< GAP event callbacks */
|
||||
bt_le_gatt_app_cb gatt_cb; /*!< GATT event callbacks */
|
||||
} esp_ble_audio_init_info_t;
|
||||
|
||||
/**
|
||||
* @brief Post an application-layer GAP event for audio internal usage.
|
||||
*
|
||||
* @note This function is only needed while using NimBLE Host.
|
||||
*
|
||||
* @param type Event type.
|
||||
* @param param Event parameters.
|
||||
*/
|
||||
void esp_ble_audio_gap_app_post_event(uint8_t type, void *param);
|
||||
|
||||
/**
|
||||
* @brief Post an application-layer GATT event for audio internal usage.
|
||||
*
|
||||
* @note This function is only needed while using NimBLE Host.
|
||||
*
|
||||
* @param type Event type.
|
||||
* @param param Event parameters.
|
||||
*/
|
||||
void esp_ble_audio_gatt_app_post_event(uint8_t type, void *param);
|
||||
|
||||
/**
|
||||
* @brief Initialize BLE Audio common functionality.
|
||||
*
|
||||
* @param info Initialization parameters.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_common_init(esp_ble_audio_init_info_t *info);
|
||||
|
||||
/** Contains service instances for audio profiles */
|
||||
typedef struct {
|
||||
#if CONFIG_BT_CSIP_SET_MEMBER
|
||||
struct {
|
||||
esp_ble_audio_csip_set_member_svc_inst_t *svc_inst; /*!< Pointer of CSIS Service instance */
|
||||
bool included_by_cas; /*!< Indicate if the CSIS Service is included by CAS */
|
||||
} csis_insts[CONFIG_BT_CSIP_SET_MEMBER_MAX_INSTANCE_COUNT]; /*!< Structures of CSIS Service instances */
|
||||
#endif /* CONFIG_BT_CSIP_SET_MEMBER */
|
||||
uint8_t dummy; /*!< Dummy field to avoid empty struct */
|
||||
} esp_ble_audio_start_info_t;
|
||||
|
||||
/**
|
||||
* @brief Start BLE Audio services.
|
||||
*
|
||||
* @param info Service instances to start.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_common_start(esp_ble_audio_start_info_t *info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_BLE_AUDIO_COMMON_API_H_ */
|
||||
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_BLE_AUDIO_CSIP_API_H_
|
||||
#define ESP_BLE_AUDIO_CSIP_API_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include <zephyr/bluetooth/audio/audio.h>
|
||||
#include <zephyr/bluetooth/audio/csip.h>
|
||||
|
||||
#include "common/init.h"
|
||||
#include "common/host.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!< Size of the Set Identification Resolving Key (SIRK) */
|
||||
#define ESP_BLE_AUDIO_CSIP_SIRK_SIZE BT_CSIP_SIRK_SIZE
|
||||
|
||||
/*!< Size of the Resolvable Set Identifier (RSI) */
|
||||
#define ESP_BLE_AUDIO_CSIP_RSI_SIZE BT_CSIP_RSI_SIZE
|
||||
|
||||
/*!< Accept the request to read the SIRK as plaintext */
|
||||
#define ESP_BLE_AUDIO_CSIP_READ_SIRK_REQ_RSP_ACCEPT BT_CSIP_READ_SIRK_REQ_RSP_ACCEPT
|
||||
/*!< Accept the request to read the SIRK, but return encrypted SIRK */
|
||||
#define ESP_BLE_AUDIO_CSIP_READ_SIRK_REQ_RSP_ACCEPT_ENC BT_CSIP_READ_SIRK_REQ_RSP_ACCEPT_ENC
|
||||
/*!< Reject the request to read the SIRK */
|
||||
#define ESP_BLE_AUDIO_CSIP_READ_SIRK_REQ_RSP_REJECT BT_CSIP_READ_SIRK_REQ_RSP_REJECT
|
||||
/*!< SIRK is available only via an OOB procedure */
|
||||
#define ESP_BLE_AUDIO_CSIP_READ_SIRK_REQ_RSP_OOB_ONLY BT_CSIP_READ_SIRK_REQ_RSP_OOB_ONLY
|
||||
|
||||
/**
|
||||
* @brief Helper to declare bt_data array including RSI.
|
||||
*
|
||||
* This macro is mainly for creating an array of struct bt_data elements.
|
||||
*
|
||||
* @param _rsi Pointer to the RSI value.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_CSIP_DATA_RSI(_rsi) BT_CSIP_DATA_RSI(_rsi)
|
||||
|
||||
/** Callback structure for the Coordinated Set Identification Service */
|
||||
typedef struct bt_csip_set_member_cb esp_ble_audio_csip_set_member_cb_t;
|
||||
|
||||
/** Coordinated Set Identification Service instance */
|
||||
typedef struct bt_csip_set_member_svc_inst esp_ble_audio_csip_set_member_svc_inst_t;
|
||||
|
||||
/** Register structure for Coordinated Set Identification Service */
|
||||
typedef struct bt_csip_set_member_register_param esp_ble_audio_csip_set_member_register_param_t;
|
||||
|
||||
/** Struct to hold information about a service instance */
|
||||
typedef struct bt_csip_set_member_set_info esp_ble_audio_csip_set_member_set_info_t;
|
||||
|
||||
/** Struct to hold the Coordinated Set Identification Profile Set Coordinator callbacks */
|
||||
typedef struct bt_csip_set_coordinator_cb esp_ble_audio_csip_set_coordinator_cb_t;
|
||||
|
||||
/** Information about a specific set */
|
||||
typedef struct bt_csip_set_coordinator_set_info esp_ble_audio_csip_set_coordinator_set_info_t;
|
||||
|
||||
/** Struct representing a coordinated set instance on a remote device */
|
||||
typedef struct bt_csip_set_coordinator_csis_inst esp_ble_audio_csip_set_coordinator_csis_inst_t;
|
||||
|
||||
/** Struct representing a remote device as a set member */
|
||||
typedef struct bt_csip_set_coordinator_set_member esp_ble_audio_csip_set_coordinator_set_member_t;
|
||||
|
||||
/**
|
||||
* @brief Get the service declaration attribute.
|
||||
*
|
||||
* The first service attribute can be included in any other GATT service.
|
||||
*
|
||||
* @param svc_inst Pointer to the Coordinated Set Identification Service.
|
||||
*
|
||||
* @return The first CSIS attribute instance.
|
||||
*/
|
||||
void *esp_ble_audio_csip_set_member_svc_decl_get(const esp_ble_audio_csip_set_member_svc_inst_t *svc_inst);
|
||||
|
||||
/**
|
||||
* @brief Register a Coordinated Set Identification Service instance.
|
||||
*
|
||||
* This will register and enable the service and make it discoverable by clients.
|
||||
*
|
||||
* This shall only be done as a server.
|
||||
*
|
||||
* @param param Coordinated Set Identification Service register parameters.
|
||||
* @param svc_inst Pointer to the registered Coordinated Set Identification Service.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_csip_set_member_register(const esp_ble_audio_csip_set_member_register_param_t *param,
|
||||
esp_ble_audio_csip_set_member_svc_inst_t **svc_inst);
|
||||
|
||||
/**
|
||||
* @brief Unregister a Coordinated Set Identification Service instance.
|
||||
*
|
||||
* This will unregister and disable the service instance.
|
||||
*
|
||||
* @param svc_inst Pointer to the registered Coordinated Set Identification Service.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_csip_set_member_unregister(esp_ble_audio_csip_set_member_svc_inst_t *svc_inst);
|
||||
|
||||
/**
|
||||
* @brief Set the SIRK of a service instance.
|
||||
*
|
||||
* @param svc_inst Pointer to the registered Coordinated Set Identification Service.
|
||||
* @param sirk The new SIRK.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_csip_set_member_sirk(esp_ble_audio_csip_set_member_svc_inst_t *svc_inst,
|
||||
const uint8_t sirk[ESP_BLE_AUDIO_CSIP_SIRK_SIZE]);
|
||||
|
||||
/**
|
||||
* @brief Set a new size and rank for a service instance.
|
||||
*
|
||||
* This function can be used to dynamically change the size and rank of a service instance.
|
||||
* It is important to note that a set cannot have multiple devices with the same rank in a
|
||||
* set, and it is up to the caller of this function to ensure that.
|
||||
* Similarly, it is important that the size is updated on all devices in the set at the same
|
||||
* time.
|
||||
*
|
||||
* If CONFIG_BT_CSIP_SET_MEMBER_SIZE_NOTIFIABLE is enabled, this will also send a notification
|
||||
* to all connected or bonded clients.
|
||||
*
|
||||
* @param svc_inst The service instance.
|
||||
* @param size The new set size.
|
||||
* @param rank The new rank. Ignored if the @p svc_inst is not lockable.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_csip_set_member_set_size_and_rank(esp_ble_audio_csip_set_member_svc_inst_t *svc_inst,
|
||||
uint8_t size, uint8_t rank);
|
||||
|
||||
/**
|
||||
* @brief Get information about a service instances.
|
||||
*
|
||||
* @param svc_inst The service instance.
|
||||
* @param info Pointer to a struct to store the information in.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_csip_set_member_get_info(const esp_ble_audio_csip_set_member_svc_inst_t *svc_inst,
|
||||
esp_ble_audio_csip_set_member_set_info_t *info);
|
||||
|
||||
/**
|
||||
* @brief Generate the Resolvable Set Identifier (RSI) value.
|
||||
*
|
||||
* This will generate RSI for given @p svc_inst instance.
|
||||
*
|
||||
* @param svc_inst Pointer to the Coordinated Set Identification Service.
|
||||
* @param rsi Pointer to the 6-octet newly generated RSI data in little-endian.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_csip_set_member_generate_rsi(const esp_ble_audio_csip_set_member_svc_inst_t *svc_inst,
|
||||
uint8_t rsi[ESP_BLE_AUDIO_CSIP_RSI_SIZE]);
|
||||
|
||||
/**
|
||||
* @brief Locks a specific Coordinated Set Identification Service instance on the server.
|
||||
*
|
||||
* @param svc_inst Pointer to the Coordinated Set Identification Service.
|
||||
* @param lock If true lock the set, if false release the set.
|
||||
* @param force This argument only have meaning when @p lock is false
|
||||
* (release) and will force release the lock, regardless of who
|
||||
* took the lock.
|
||||
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_csip_set_member_lock(esp_ble_audio_csip_set_member_svc_inst_t *svc_inst,
|
||||
bool lock, bool force);
|
||||
|
||||
/**
|
||||
* @brief Initialise the csip_set_coordinator instance for a connection.
|
||||
* This will do a discovery on the device and prepare the instance
|
||||
* for following commands.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_csip_set_coordinator_discover(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Get the set member from a connection pointer.
|
||||
*
|
||||
* Get the Coordinated Set Identification Profile Set Coordinator pointer
|
||||
* from connection handle.
|
||||
* Only Set Coordinators that have been initiated can be retrieved.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return Pointer to a Coordinated Set Identification Profile Set Coordinator instance.
|
||||
* NULL if the connection has not been found or has not done discovery yet.
|
||||
*/
|
||||
esp_ble_audio_csip_set_coordinator_set_member_t *
|
||||
esp_ble_audio_csip_set_coordinator_set_member_by_conn(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Check if advertising data indicates a set member.
|
||||
*
|
||||
* @param sirk The SIRK of the set to check against.
|
||||
* @param data_type Type of the advertising data.
|
||||
* @param data Pointer of the advertising data.
|
||||
* @param data_len Length of the advertising data.
|
||||
*
|
||||
* @return True if the advertising data indicates a set member, false otherwise.
|
||||
*/
|
||||
bool esp_ble_audio_csip_set_coordinator_is_set_member(const uint8_t sirk[ESP_BLE_AUDIO_CSIP_SIRK_SIZE],
|
||||
uint8_t data_type, const uint8_t *data, uint8_t data_len);
|
||||
|
||||
/**
|
||||
* @brief Registers callbacks for csip_set_coordinator.
|
||||
*
|
||||
* @param cb Pointer to the callback structure.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_csip_set_coordinator_register_cb(esp_ble_audio_csip_set_coordinator_cb_t *cb);
|
||||
|
||||
/**
|
||||
* @brief Access Coordinated Set devices in an ordered manner as a client.
|
||||
*
|
||||
* This function will read the lock state of all devices and if all devices are
|
||||
* in the unlocked state, then @p cb will be called with the same members as
|
||||
* provided by @p members, but where the members are ordered by rank (if present).
|
||||
*
|
||||
* This procedure only works if all the members have the lock characteristic,
|
||||
* and all either has rank = 0 or unique ranks.
|
||||
*
|
||||
* If any of the members are in the locked state, the procedure will be cancelled.
|
||||
*
|
||||
* This can only be done on members that are bonded.
|
||||
*
|
||||
* @param members Array of set members to access.
|
||||
* @param count Number of set members in @p members.
|
||||
* @param set_info Pointer to the a specific set_info struct, as a member may
|
||||
* be part of multiple sets.
|
||||
* @param cb The callback function to be called for each member.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_csip_set_coordinator_ordered_access(const esp_ble_audio_csip_set_coordinator_set_member_t *members[],
|
||||
uint8_t count,
|
||||
const esp_ble_audio_csip_set_coordinator_set_info_t *set_info,
|
||||
bt_csip_set_coordinator_ordered_access_t cb);
|
||||
|
||||
/**
|
||||
* @brief Lock an array of set members.
|
||||
*
|
||||
* The members will be locked starting from lowest rank going up.
|
||||
*
|
||||
* @param members Array of set members to lock.
|
||||
* @param count Number of set members in @p members.
|
||||
* @param set_info Pointer to the a specific set_info struct, as a member
|
||||
* may be part of multiple sets.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_csip_set_coordinator_lock(const esp_ble_audio_csip_set_coordinator_set_member_t **members,
|
||||
uint8_t count,
|
||||
const esp_ble_audio_csip_set_coordinator_set_info_t *set_info);
|
||||
|
||||
/**
|
||||
* @brief Release an array of set members.
|
||||
*
|
||||
* The members will be released starting from highest rank going down.
|
||||
*
|
||||
* @param members Array of set members to lock.
|
||||
* @param count Number of set members in @p members.
|
||||
* @param set_info Pointer to the a specific set_info struct, as a member
|
||||
* may be part of multiple sets.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_csip_set_coordinator_release(const esp_ble_audio_csip_set_coordinator_set_member_t **members,
|
||||
uint8_t count,
|
||||
const esp_ble_audio_csip_set_coordinator_set_info_t *set_info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_BLE_AUDIO_CSIP_API_H_ */
|
||||
@@ -0,0 +1,567 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Intel Corporation
|
||||
* SPDX-FileCopyrightText: 2020-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_BLE_AUDIO_DEFS_H_
|
||||
#define ESP_BLE_AUDIO_DEFS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include <zephyr/bluetooth/audio/audio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!< Minimum ATT MTU size required by Basic Audio Profile (BAP) */
|
||||
#define ESP_BLE_AUDIO_ATT_MTU_MIN 64
|
||||
|
||||
/**
|
||||
* Audio direction sink.
|
||||
*
|
||||
* For a BAP Unicast Client or Broadcast Source this is considered outgoing audio (TX).
|
||||
* For a BAP Unicast Server or Broadcast Sink this is considered incoming audio (RX).
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_DIR_SINK BT_AUDIO_DIR_SINK
|
||||
/**
|
||||
* Audio direction source.
|
||||
*
|
||||
* For a BAP Unicast Client or Broadcast Source this is considered incoming audio (RX).
|
||||
* For a BAP Unicast Server or Broadcast Sink this is considered outgoing audio (TX).
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_DIR_SOURCE BT_AUDIO_DIR_SOURCE
|
||||
/** Audio direction from the perspective of the BAP Unicast Server / BAP Broadcast Sink */
|
||||
typedef enum bt_audio_dir esp_ble_audio_dir_t;
|
||||
|
||||
/*!< Size of the stream language value, e.g. "eng" */
|
||||
#define ESP_BLE_AUDIO_LANG_SIZE BT_AUDIO_LANG_SIZE
|
||||
|
||||
/*!< Size of the broadcast ID in octets */
|
||||
#define ESP_BLE_AUDIO_BROADCAST_ID_SIZE BT_AUDIO_BROADCAST_ID_SIZE
|
||||
/*!< Maximum broadcast ID value */
|
||||
#define ESP_BLE_AUDIO_BROADCAST_ID_MAX BT_AUDIO_BROADCAST_ID_MAX
|
||||
/*!< Indicates that the server have no preference for the presentation delay */
|
||||
#define ESP_BLE_AUDIO_PD_PREF_NONE BT_AUDIO_PD_PREF_NONE
|
||||
/*!< Maximum presentation delay in microseconds */
|
||||
#define ESP_BLE_AUDIO_PD_MAX BT_AUDIO_PD_MAX
|
||||
/*!< Indicates that the unicast server does not have a preference for any retransmission number */
|
||||
#define ESP_BLE_AUDIO_RTN_PREF_NONE BT_AUDIO_RTN_PREF_NONE
|
||||
/*!< The minimum size of a Broadcast Name as defined by Bluetooth Assigned Numbers */
|
||||
#define ESP_BLE_AUDIO_BROADCAST_NAME_LEN_MIN BT_AUDIO_BROADCAST_NAME_LEN_MIN
|
||||
/*!< The maximum size of a Broadcast Name as defined by Bluetooth Assigned Numbers */
|
||||
#define ESP_BLE_AUDIO_BROADCAST_NAME_LEN_MAX BT_AUDIO_BROADCAST_NAME_LEN_MAX
|
||||
|
||||
/*!< Unicast Server is connectable and is requesting a connection. */
|
||||
#define ESP_BLE_AUDIO_UNICAST_ANNOUNCEMENT_GENERAL BT_AUDIO_UNICAST_ANNOUNCEMENT_GENERAL
|
||||
/*!< Unicast Server is connectable but is not requesting a connection. */
|
||||
#define ESP_BLE_AUDIO_UNICAST_ANNOUNCEMENT_TARGETED BT_AUDIO_UNICAST_ANNOUNCEMENT_TARGETED
|
||||
|
||||
/*!< No context type */
|
||||
#define ESP_BLE_AUDIO_CONTEXT_TYPE_NONE BT_AUDIO_CONTEXT_TYPE_NONE
|
||||
/**
|
||||
* Identifies audio where the use case context does not match any other defined value,
|
||||
* or where the context is unknown or cannot be determined.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_CONTEXT_TYPE_UNSPECIFIED BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED
|
||||
/**
|
||||
* Conversation between humans, for example, in telephony or video calls, including
|
||||
* traditional cellular as well as VoIP and Push-to-Talk
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_CONTEXT_TYPE_CONVERSATIONAL BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL
|
||||
/*!< Media, for example, music playback, radio, podcast or movie soundtrack, or tv audio */
|
||||
#define ESP_BLE_AUDIO_CONTEXT_TYPE_MEDIA BT_AUDIO_CONTEXT_TYPE_MEDIA
|
||||
/**
|
||||
* Audio associated with video gaming, for example gaming media; gaming effects; music
|
||||
* and in-game voice chat between participants; or a mix of all the above
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_CONTEXT_TYPE_GAME BT_AUDIO_CONTEXT_TYPE_GAME
|
||||
/*!< Instructional audio, for example, in navigation, announcements, or user guidance */
|
||||
#define ESP_BLE_AUDIO_CONTEXT_TYPE_INSTRUCTIONAL BT_AUDIO_CONTEXT_TYPE_INSTRUCTIONAL
|
||||
/*!< Man-machine communication, for example, with voice recognition or virtual assistants */
|
||||
#define ESP_BLE_AUDIO_CONTEXT_TYPE_VOICE_ASSISTANTS BT_AUDIO_CONTEXT_TYPE_VOICE_ASSISTANTS
|
||||
/**
|
||||
* Live audio, for example, from a microphone where audio is perceived both through a
|
||||
* direct acoustic path and through an LE Audio Stream
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_CONTEXT_TYPE_LIVE BT_AUDIO_CONTEXT_TYPE_LIVE
|
||||
/**
|
||||
* Sound effects including keyboard and touch feedback; menu and user interface sounds;
|
||||
* and other system sounds
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_CONTEXT_TYPE_SOUND_EFFECTS BT_AUDIO_CONTEXT_TYPE_SOUND_EFFECTS
|
||||
/**
|
||||
* Notification and reminder sounds; attention-seeking audio, for example,
|
||||
* in beeps signaling the arrival of a message
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_CONTEXT_TYPE_NOTIFICATIONS BT_AUDIO_CONTEXT_TYPE_NOTIFICATIONS
|
||||
/**
|
||||
* Alerts the user to an incoming call, for example, an incoming telephony or video call,
|
||||
* including traditional cellular as well as VoIP and Push-to-Talk
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_CONTEXT_TYPE_RINGTONE BT_AUDIO_CONTEXT_TYPE_RINGTONE
|
||||
/**
|
||||
* Alarms and timers; immediate alerts, for example, in a critical battery alarm,
|
||||
* timer expiry or alarm clock, toaster, cooker, kettle, microwave, etc.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_CONTEXT_TYPE_ALERTS BT_AUDIO_CONTEXT_TYPE_ALERTS
|
||||
/*!< Emergency alarm Emergency sounds, for example, fire alarms or other urgent alerts */
|
||||
#define ESP_BLE_AUDIO_CONTEXT_TYPE_EMERGENCY_ALARM BT_AUDIO_CONTEXT_TYPE_EMERGENCY_ALARM
|
||||
/*!< Any known context */
|
||||
#define ESP_BLE_AUDIO_CONTEXT_TYPE_ANY BT_AUDIO_CONTEXT_TYPE_ANY
|
||||
/** Audio Context Type for Generic Audio */
|
||||
typedef enum bt_audio_context esp_ble_audio_context_t;
|
||||
|
||||
/*!< No rating */
|
||||
#define ESP_BLE_AUDIO_PARENTAL_RATING_NO_RATING BT_AUDIO_PARENTAL_RATING_NO_RATING
|
||||
/*!< For all ages */
|
||||
#define ESP_BLE_AUDIO_PARENTAL_RATING_AGE_ANY BT_AUDIO_PARENTAL_RATING_AGE_ANY
|
||||
/*!< Recommended for listeners of age 5 and above */
|
||||
#define ESP_BLE_AUDIO_PARENTAL_RATING_AGE_5_OR_ABOVE BT_AUDIO_PARENTAL_RATING_AGE_5_OR_ABOVE
|
||||
/*!< Recommended for listeners of age 6 and above */
|
||||
#define ESP_BLE_AUDIO_PARENTAL_RATING_AGE_6_OR_ABOVE BT_AUDIO_PARENTAL_RATING_AGE_6_OR_ABOVE
|
||||
/*!< Recommended for listeners of age 7 and above */
|
||||
#define ESP_BLE_AUDIO_PARENTAL_RATING_AGE_7_OR_ABOVE BT_AUDIO_PARENTAL_RATING_AGE_7_OR_ABOVE
|
||||
/*!< Recommended for listeners of age 8 and above */
|
||||
#define ESP_BLE_AUDIO_PARENTAL_RATING_AGE_8_OR_ABOVE BT_AUDIO_PARENTAL_RATING_AGE_8_OR_ABOVE
|
||||
/*!< Recommended for listeners of age 9 and above */
|
||||
#define ESP_BLE_AUDIO_PARENTAL_RATING_AGE_9_OR_ABOVE BT_AUDIO_PARENTAL_RATING_AGE_9_OR_ABOVE
|
||||
/*!< Recommended for listeners of age 10 and above */
|
||||
#define ESP_BLE_AUDIO_PARENTAL_RATING_AGE_10_OR_ABOVE BT_AUDIO_PARENTAL_RATING_AGE_10_OR_ABOVE
|
||||
/*!< Recommended for listeners of age 11 and above */
|
||||
#define ESP_BLE_AUDIO_PARENTAL_RATING_AGE_11_OR_ABOVE BT_AUDIO_PARENTAL_RATING_AGE_11_OR_ABOVE
|
||||
/*!< Recommended for listeners of age 12 and above */
|
||||
#define ESP_BLE_AUDIO_PARENTAL_RATING_AGE_12_OR_ABOVE BT_AUDIO_PARENTAL_RATING_AGE_12_OR_ABOVE
|
||||
/*!< Recommended for listeners of age 13 and above */
|
||||
#define ESP_BLE_AUDIO_PARENTAL_RATING_AGE_13_OR_ABOVE BT_AUDIO_PARENTAL_RATING_AGE_13_OR_ABOVE
|
||||
/*!< Recommended for listeners of age 14 and above */
|
||||
#define ESP_BLE_AUDIO_PARENTAL_RATING_AGE_14_OR_ABOVE BT_AUDIO_PARENTAL_RATING_AGE_14_OR_ABOVE
|
||||
/*!< Recommended for listeners of age 15 and above */
|
||||
#define ESP_BLE_AUDIO_PARENTAL_RATING_AGE_15_OR_ABOVE BT_AUDIO_PARENTAL_RATING_AGE_15_OR_ABOVE
|
||||
/*!< Recommended for listeners of age 16 and above */
|
||||
#define ESP_BLE_AUDIO_PARENTAL_RATING_AGE_16_OR_ABOVE BT_AUDIO_PARENTAL_RATING_AGE_16_OR_ABOVE
|
||||
/*!< Recommended for listeners of age 17 and above */
|
||||
#define ESP_BLE_AUDIO_PARENTAL_RATING_AGE_17_OR_ABOVE BT_AUDIO_PARENTAL_RATING_AGE_17_OR_ABOVE
|
||||
/*!< Recommended for listeners of age 18 and above */
|
||||
#define ESP_BLE_AUDIO_PARENTAL_RATING_AGE_18_OR_ABOVE BT_AUDIO_PARENTAL_RATING_AGE_18_OR_ABOVE
|
||||
/** Parental rating defined by the Generic Audio assigned numbers */
|
||||
typedef enum bt_audio_parental_rating esp_ble_audio_parental_rating_t;
|
||||
|
||||
/*!< No audio data is being transmitted */
|
||||
#define ESP_BLE_AUDIO_ACTIVE_STATE_DISABLED BT_AUDIO_ACTIVE_STATE_DISABLED
|
||||
/*!< Audio data is being transmitted */
|
||||
#define ESP_BLE_AUDIO_ACTIVE_STATE_ENABLED BT_AUDIO_ACTIVE_STATE_ENABLED
|
||||
/** Audio Active State defined by the Generic Audio assigned numbers */
|
||||
typedef enum bt_audio_active_state esp_ble_audio_active_state_t;
|
||||
|
||||
/*!< Preferred audio context */
|
||||
#define ESP_BLE_AUDIO_METADATA_TYPE_PREF_CONTEXT BT_AUDIO_METADATA_TYPE_PREF_CONTEXT
|
||||
/*!< Streaming audio context */
|
||||
#define ESP_BLE_AUDIO_METADATA_TYPE_STREAM_CONTEXT BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT
|
||||
/*!< UTF-8 encoded title or summary of stream content */
|
||||
#define ESP_BLE_AUDIO_METADATA_TYPE_PROGRAM_INFO BT_AUDIO_METADATA_TYPE_PROGRAM_INFO
|
||||
/*!< Language */
|
||||
#define ESP_BLE_AUDIO_METADATA_TYPE_LANG BT_AUDIO_METADATA_TYPE_LANG
|
||||
/*!< Array of 8-bit CCID values */
|
||||
#define ESP_BLE_AUDIO_METADATA_TYPE_CCID_LIST BT_AUDIO_METADATA_TYPE_CCID_LIST
|
||||
/*!< Parental rating */
|
||||
#define ESP_BLE_AUDIO_METADATA_TYPE_PARENTAL_RATING BT_AUDIO_METADATA_TYPE_PARENTAL_RATING
|
||||
/*!< UTF-8 encoded URI for additional Program information */
|
||||
#define ESP_BLE_AUDIO_METADATA_TYPE_PROGRAM_INFO_URI BT_AUDIO_METADATA_TYPE_PROGRAM_INFO_URI
|
||||
/*!< Audio active state */
|
||||
#define ESP_BLE_AUDIO_METADATA_TYPE_AUDIO_STATE BT_AUDIO_METADATA_TYPE_AUDIO_STATE
|
||||
/*!< Broadcast Audio Immediate Rendering flag */
|
||||
#define ESP_BLE_AUDIO_METADATA_TYPE_BROADCAST_IMMEDIATE BT_AUDIO_METADATA_TYPE_BROADCAST_IMMEDIATE
|
||||
/*!< Assisted listening stream */
|
||||
#define ESP_BLE_AUDIO_METADATA_TYPE_ASSISTED_LISTENING_STREAM BT_AUDIO_METADATA_TYPE_ASSISTED_LISTENING_STREAM
|
||||
/*!< UTF-8 encoded Broadcast name */
|
||||
#define ESP_BLE_AUDIO_METADATA_TYPE_BROADCAST_NAME BT_AUDIO_METADATA_TYPE_BROADCAST_NAME
|
||||
/*!< Extended metadata */
|
||||
#define ESP_BLE_AUDIO_METADATA_TYPE_EXTENDED BT_AUDIO_METADATA_TYPE_EXTENDED
|
||||
/*!< Vendor specific metadata */
|
||||
#define ESP_BLE_AUDIO_METADATA_TYPE_VENDOR BT_AUDIO_METADATA_TYPE_VENDOR
|
||||
/**
|
||||
* @brief Helper to check whether metadata type is known by the stack.
|
||||
*
|
||||
* @param _type Metadata type.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_METADATA_TYPE_IS_KNOWN(_type) \
|
||||
BT_AUDIO_METADATA_TYPE_IS_KNOWN(_type)
|
||||
/** Metadata types defined by the Generic Audio assigned numbers */
|
||||
typedef enum bt_audio_metadata_type esp_ble_audio_metadata_type_t;
|
||||
|
||||
/*!< Mono Audio (no specified Audio Location) */
|
||||
#define ESP_BLE_AUDIO_LOCATION_MONO_AUDIO BT_AUDIO_LOCATION_MONO_AUDIO
|
||||
/*!< Front Left */
|
||||
#define ESP_BLE_AUDIO_LOCATION_FRONT_LEFT BT_AUDIO_LOCATION_FRONT_LEFT
|
||||
/*!< Front Right */
|
||||
#define ESP_BLE_AUDIO_LOCATION_FRONT_RIGHT BT_AUDIO_LOCATION_FRONT_RIGHT
|
||||
/*!< Front Center */
|
||||
#define ESP_BLE_AUDIO_LOCATION_FRONT_CENTER BT_AUDIO_LOCATION_FRONT_CENTER
|
||||
/*!< Low Frequency Effects 1 */
|
||||
#define ESP_BLE_AUDIO_LOCATION_LOW_FREQ_EFFECTS_1 BT_AUDIO_LOCATION_LOW_FREQ_EFFECTS_1
|
||||
/*!< Back Left */
|
||||
#define ESP_BLE_AUDIO_LOCATION_BACK_LEFT BT_AUDIO_LOCATION_BACK_LEFT
|
||||
/*!< Back Right */
|
||||
#define ESP_BLE_AUDIO_LOCATION_BACK_RIGHT BT_AUDIO_LOCATION_BACK_RIGHT
|
||||
/*!< Front Left of Center */
|
||||
#define ESP_BLE_AUDIO_LOCATION_FRONT_LEFT_OF_CENTER BT_AUDIO_LOCATION_FRONT_LEFT_OF_CENTER
|
||||
/*!< Front Right of Center */
|
||||
#define ESP_BLE_AUDIO_LOCATION_FRONT_RIGHT_OF_CENTER BT_AUDIO_LOCATION_FRONT_RIGHT_OF_CENTER
|
||||
/*!< Back Center */
|
||||
#define ESP_BLE_AUDIO_LOCATION_BACK_CENTER BT_AUDIO_LOCATION_BACK_CENTER
|
||||
/*!< Low Frequency Effects 2 */
|
||||
#define ESP_BLE_AUDIO_LOCATION_LOW_FREQ_EFFECTS_2 BT_AUDIO_LOCATION_LOW_FREQ_EFFECTS_2
|
||||
/*!< Side Left */
|
||||
#define ESP_BLE_AUDIO_LOCATION_SIDE_LEFT BT_AUDIO_LOCATION_SIDE_LEFT
|
||||
/*!< Side Right */
|
||||
#define ESP_BLE_AUDIO_LOCATION_SIDE_RIGHT BT_AUDIO_LOCATION_SIDE_RIGHT
|
||||
/*!< Top Front Left */
|
||||
#define ESP_BLE_AUDIO_LOCATION_TOP_FRONT_LEFT BT_AUDIO_LOCATION_TOP_FRONT_LEFT
|
||||
/*!< Top Front Right */
|
||||
#define ESP_BLE_AUDIO_LOCATION_TOP_FRONT_RIGHT BT_AUDIO_LOCATION_TOP_FRONT_RIGHT
|
||||
/*!< Top Front Center */
|
||||
#define ESP_BLE_AUDIO_LOCATION_TOP_FRONT_CENTER BT_AUDIO_LOCATION_TOP_FRONT_CENTER
|
||||
/*!< Top Center */
|
||||
#define ESP_BLE_AUDIO_LOCATION_TOP_CENTER BT_AUDIO_LOCATION_TOP_CENTER
|
||||
/*!< Top Back Left */
|
||||
#define ESP_BLE_AUDIO_LOCATION_TOP_BACK_LEFT BT_AUDIO_LOCATION_TOP_BACK_LEFT
|
||||
/*!< Top Back Right */
|
||||
#define ESP_BLE_AUDIO_LOCATION_TOP_BACK_RIGHT BT_AUDIO_LOCATION_TOP_BACK_RIGHT
|
||||
/*!< Top Side Left */
|
||||
#define ESP_BLE_AUDIO_LOCATION_TOP_SIDE_LEFT BT_AUDIO_LOCATION_TOP_SIDE_LEFT
|
||||
/*!< Top Side Right */
|
||||
#define ESP_BLE_AUDIO_LOCATION_TOP_SIDE_RIGHT BT_AUDIO_LOCATION_TOP_SIDE_RIGHT
|
||||
/*!< Top Back Center */
|
||||
#define ESP_BLE_AUDIO_LOCATION_TOP_BACK_CENTER BT_AUDIO_LOCATION_TOP_BACK_CENTER
|
||||
/*!< Bottom Front Center */
|
||||
#define ESP_BLE_AUDIO_LOCATION_BOTTOM_FRONT_CENTER BT_AUDIO_LOCATION_BOTTOM_FRONT_CENTER
|
||||
/*!< Bottom Front Left */
|
||||
#define ESP_BLE_AUDIO_LOCATION_BOTTOM_FRONT_LEFT BT_AUDIO_LOCATION_BOTTOM_FRONT_LEFT
|
||||
/*!< Bottom Front Right */
|
||||
#define ESP_BLE_AUDIO_LOCATION_BOTTOM_FRONT_RIGHT BT_AUDIO_LOCATION_BOTTOM_FRONT_RIGHT
|
||||
/*!< Front Left Wide */
|
||||
#define ESP_BLE_AUDIO_LOCATION_FRONT_LEFT_WIDE BT_AUDIO_LOCATION_FRONT_LEFT_WIDE
|
||||
/*!< Front Right Wide */
|
||||
#define ESP_BLE_AUDIO_LOCATION_FRONT_RIGHT_WIDE BT_AUDIO_LOCATION_FRONT_RIGHT_WIDE
|
||||
/*!< Left Surround */
|
||||
#define ESP_BLE_AUDIO_LOCATION_LEFT_SURROUND BT_AUDIO_LOCATION_LEFT_SURROUND
|
||||
/*!< Right Surround */
|
||||
#define ESP_BLE_AUDIO_LOCATION_RIGHT_SURROUND BT_AUDIO_LOCATION_RIGHT_SURROUND
|
||||
/*!< Any known location */
|
||||
#define ESP_BLE_AUDIO_LOCATION_ANY BT_AUDIO_LOCATION_ANY
|
||||
/** Location values defined by the Generic Audio assigned numbers */
|
||||
typedef enum bt_audio_location esp_ble_audio_location_t;
|
||||
|
||||
/*!< Unspecified audio enhancement */
|
||||
#define ESP_BLE_AUDIO_ASSISTED_LISTENING_STREAM_UNSPECIFIED BT_AUDIO_ASSISTED_LISTENING_STREAM_UNSPECIFIED
|
||||
/** Assisted Listening Stream defined by the Generic Audio assigned numbers */
|
||||
typedef enum bt_audio_assisted_listening_stream esp_ble_audio_assisted_listening_stream_t;
|
||||
|
||||
/*!< Size in octets of a 16-bit UUID */
|
||||
#define ESP_BLE_AUDIO_UUID_SIZE_16 BT_UUID_SIZE_16
|
||||
|
||||
/*!< Audio Input Control Service UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_AICS_VAL BT_UUID_AICS_VAL
|
||||
/*!< Audio Stream Control Service UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_ASCS_VAL BT_UUID_ASCS_VAL
|
||||
/*!< Broadcast Audio Scan Service UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_BASS_VAL BT_UUID_BASS_VAL
|
||||
/*!< Basic Audio Announcement Service UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_BASIC_AUDIO_VAL BT_UUID_BASIC_AUDIO_VAL
|
||||
/*!< Broadcast Audio Announcement Service UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_BROADCAST_AUDIO_VAL BT_UUID_BROADCAST_AUDIO_VAL
|
||||
/*!< Common Audio Service UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_CAS_VAL BT_UUID_CAS_VAL
|
||||
/*!< Coordinated Set Identification Service UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_CSIS_VAL BT_UUID_CSIS_VAL
|
||||
/*!< Gaming Service UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_GMAS_VAL BT_UUID_GMAS_VAL
|
||||
/*!< Generic Media Control Service UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_GMCS_VAL BT_UUID_GMCS_VAL
|
||||
/*!< Generic Telephone Bearer Service UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_GTBS_VAL BT_UUID_GTBS_VAL
|
||||
/*!< Hearing Access Service UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_HAS_VAL BT_UUID_HAS_VAL
|
||||
/*!< Media Control Service UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_MCS_VAL BT_UUID_MCS_VAL
|
||||
/*!< Microphone Control Service UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_MICS_VAL BT_UUID_MICS_VAL
|
||||
/*!< Published Audio Capabilities Service UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_PACS_VAL BT_UUID_PACS_VAL
|
||||
/*!< Public Broadcast Announcement Service UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_PBA_VAL BT_UUID_PBA_VAL
|
||||
/*!< Telephone Bearer Service UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_TBS_VAL BT_UUID_TBS_VAL
|
||||
/*!< Telephony and Media Audio Service UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_TMAS_VAL BT_UUID_TMAS_VAL
|
||||
/*!< Volume Control Service UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_VCS_VAL BT_UUID_VCS_VAL
|
||||
/*!< Volume Offset Control Service UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_VOCS_VAL BT_UUID_VOCS_VAL
|
||||
/*!< Object Transfer Service UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_OTS_VAL BT_UUID_OTS_VAL
|
||||
|
||||
/*!< Audio Input Control Service State value */
|
||||
#define ESP_BLE_AUDIO_UUID_AICS_STATE_VAL BT_UUID_AICS_STATE_VAL
|
||||
/*!< Audio Input Control Service Gain Settings Properties value */
|
||||
#define ESP_BLE_AUDIO_UUID_AICS_GAIN_SETTINGS_VAL BT_UUID_AICS_GAIN_SETTINGS_VAL
|
||||
/*!< Audio Input Control Service Input Type value */
|
||||
#define ESP_BLE_AUDIO_UUID_AICS_INPUT_TYPE_VAL BT_UUID_AICS_INPUT_TYPE_VAL
|
||||
/*!< Audio Input Control Service Input Status value */
|
||||
#define ESP_BLE_AUDIO_UUID_AICS_INPUT_STATUS_VAL BT_UUID_AICS_INPUT_STATUS_VAL
|
||||
/*!< Audio Input Control Service Control Point value */
|
||||
#define ESP_BLE_AUDIO_UUID_AICS_CONTROL_VAL BT_UUID_AICS_CONTROL_VAL
|
||||
/*!< Audio Input Control Service Input Description value */
|
||||
#define ESP_BLE_AUDIO_UUID_AICS_DESCRIPTION_VAL BT_UUID_AICS_DESCRIPTION_VAL
|
||||
|
||||
/*!< Audio Stream Endpoint Sink Characteristic value */
|
||||
#define ESP_BLE_AUDIO_UUID_ASCS_ASE_SNK_VAL BT_UUID_ASCS_ASE_SNK_VAL
|
||||
/*!< Audio Stream Endpoint Source Characteristic value */
|
||||
#define ESP_BLE_AUDIO_UUID_ASCS_ASE_SRC_VAL BT_UUID_ASCS_ASE_SRC_VAL
|
||||
/*!< Audio Stream Endpoint Control Point Characteristic value */
|
||||
#define ESP_BLE_AUDIO_UUID_ASCS_ASE_CP_VAL BT_UUID_ASCS_ASE_CP_VAL
|
||||
|
||||
/*!< Broadcast Audio Scan Service Scan State value */
|
||||
#define ESP_BLE_AUDIO_UUID_BASS_CONTROL_POINT_VAL BT_UUID_BASS_CONTROL_POINT_VAL
|
||||
/*!< Broadcast Audio Scan Service Receive State value */
|
||||
#define ESP_BLE_AUDIO_UUID_BASS_RECV_STATE_VAL BT_UUID_BASS_RECV_STATE_VAL
|
||||
|
||||
/*!< Set Identity Resolving Key value */
|
||||
#define ESP_BLE_AUDIO_UUID_CSIS_SIRK_VAL BT_UUID_CSIS_SIRK_VAL
|
||||
/*!< Set size value */
|
||||
#define ESP_BLE_AUDIO_UUID_CSIS_SET_SIZE_VAL BT_UUID_CSIS_SET_SIZE_VAL
|
||||
/*!< Set lock value */
|
||||
#define ESP_BLE_AUDIO_UUID_CSIS_SET_LOCK_VAL BT_UUID_CSIS_SET_LOCK_VAL
|
||||
/*!< Rank value */
|
||||
#define ESP_BLE_AUDIO_UUID_CSIS_RANK_VAL BT_UUID_CSIS_RANK_VAL
|
||||
|
||||
/*!< Gaming Audio Profile Role UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_GMAP_ROLE_VAL BT_UUID_GMAP_ROLE_VAL
|
||||
/*!< Gaming Audio Profile Unicast Game Gateway Features UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_GMAP_UGG_FEAT_VAL BT_UUID_GMAP_UGG_FEAT_VAL
|
||||
/*!< Gaming Audio Profile Unicast Game Terminal Features UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_GMAP_UGT_FEAT_VAL BT_UUID_GMAP_UGT_FEAT_VAL
|
||||
/*!< Gaming Audio Profile Broadcast Game Sender Features UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_GMAP_BGS_FEAT_VAL BT_UUID_GMAP_BGS_FEAT_VAL
|
||||
/*!< Gaming Audio Profile Broadcast Game Receiver Features UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_GMAP_BGR_FEAT_VAL BT_UUID_GMAP_BGR_FEAT_VAL
|
||||
|
||||
/*!< Hearing Aid Features Characteristic value */
|
||||
#define ESP_BLE_AUDIO_UUID_HAS_HEARING_AID_FEATURES_VAL BT_UUID_HAS_HEARING_AID_FEATURES_VAL
|
||||
/*!< Hearing Aid Preset Control Point Characteristic value */
|
||||
#define ESP_BLE_AUDIO_UUID_HAS_PRESET_CONTROL_POINT_VAL BT_UUID_HAS_PRESET_CONTROL_POINT_VAL
|
||||
/*!< Hearing Aid Active Preset Index Characteristic value */
|
||||
#define ESP_BLE_AUDIO_UUID_HAS_ACTIVE_PRESET_INDEX_VAL BT_UUID_HAS_ACTIVE_PRESET_INDEX_VAL
|
||||
|
||||
/*!< Media player name value */
|
||||
#define ESP_BLE_AUDIO_UUID_MCS_PLAYER_NAME_VAL BT_UUID_MCS_PLAYER_NAME_VAL
|
||||
/*!< Media Icon Object ID value */
|
||||
#define ESP_BLE_AUDIO_UUID_MCS_ICON_OBJ_ID_VAL BT_UUID_MCS_ICON_OBJ_ID_VAL
|
||||
/*!< Media Icon URL value */
|
||||
#define ESP_BLE_AUDIO_UUID_MCS_ICON_URL_VAL BT_UUID_MCS_ICON_URL_VAL
|
||||
/*!< Track Changed value */
|
||||
#define ESP_BLE_AUDIO_UUID_MCS_TRACK_CHANGED_VAL BT_UUID_MCS_TRACK_CHANGED_VAL
|
||||
/*!< Track Title value */
|
||||
#define ESP_BLE_AUDIO_UUID_MCS_TRACK_TITLE_VAL BT_UUID_MCS_TRACK_TITLE_VAL
|
||||
/*!< Track Duration value */
|
||||
#define ESP_BLE_AUDIO_UUID_MCS_TRACK_DURATION_VAL BT_UUID_MCS_TRACK_DURATION_VAL
|
||||
/*!< Track Position value */
|
||||
#define ESP_BLE_AUDIO_UUID_MCS_TRACK_POSITION_VAL BT_UUID_MCS_TRACK_POSITION_VAL
|
||||
/*!< Playback Speed value */
|
||||
#define ESP_BLE_AUDIO_UUID_MCS_PLAYBACK_SPEED_VAL BT_UUID_MCS_PLAYBACK_SPEED_VAL
|
||||
/*!< Seeking Speed value */
|
||||
#define ESP_BLE_AUDIO_UUID_MCS_SEEKING_SPEED_VAL BT_UUID_MCS_SEEKING_SPEED_VAL
|
||||
/*!< Track Segments Object ID value */
|
||||
#define ESP_BLE_AUDIO_UUID_MCS_TRACK_SEGMENTS_OBJ_ID_VAL BT_UUID_MCS_TRACK_SEGMENTS_OBJ_ID_VAL
|
||||
/*!< Current Track Object ID value */
|
||||
#define ESP_BLE_AUDIO_UUID_MCS_CURRENT_TRACK_OBJ_ID_VAL BT_UUID_MCS_CURRENT_TRACK_OBJ_ID_VAL
|
||||
/*!< Next Track Object ID value */
|
||||
#define ESP_BLE_AUDIO_UUID_MCS_NEXT_TRACK_OBJ_ID_VAL BT_UUID_MCS_NEXT_TRACK_OBJ_ID_VAL
|
||||
/*!< Parent Group Object ID value */
|
||||
#define ESP_BLE_AUDIO_UUID_MCS_PARENT_GROUP_OBJ_ID_VAL BT_UUID_MCS_PARENT_GROUP_OBJ_ID_VAL
|
||||
/*!< Group Object ID value */
|
||||
#define ESP_BLE_AUDIO_UUID_MCS_CURRENT_GROUP_OBJ_ID_VAL BT_UUID_MCS_CURRENT_GROUP_OBJ_ID_VAL
|
||||
/*!< Playing Order value */
|
||||
#define ESP_BLE_AUDIO_UUID_MCS_PLAYING_ORDER_VAL BT_UUID_MCS_PLAYING_ORDER_VAL
|
||||
/*!< Playing Orders supported value */
|
||||
#define ESP_BLE_AUDIO_UUID_MCS_PLAYING_ORDERS_VAL BT_UUID_MCS_PLAYING_ORDERS_VAL
|
||||
/*!< Media State value */
|
||||
#define ESP_BLE_AUDIO_UUID_MCS_MEDIA_STATE_VAL BT_UUID_MCS_MEDIA_STATE_VAL
|
||||
/*!< Media Control Point value */
|
||||
#define ESP_BLE_AUDIO_UUID_MCS_MEDIA_CONTROL_POINT_VAL BT_UUID_MCS_MEDIA_CONTROL_POINT_VAL
|
||||
/*!< Media control opcodes supported value */
|
||||
#define ESP_BLE_AUDIO_UUID_MCS_MEDIA_CONTROL_OPCODES_VAL BT_UUID_MCS_MEDIA_CONTROL_OPCODES_VAL
|
||||
/*!< Search result object ID value */
|
||||
#define ESP_BLE_AUDIO_UUID_MCS_SEARCH_RESULTS_OBJ_ID_VAL BT_UUID_MCS_SEARCH_RESULTS_OBJ_ID_VAL
|
||||
/*!< Search control point value */
|
||||
#define ESP_BLE_AUDIO_UUID_MCS_SEARCH_CONTROL_POINT_VAL BT_UUID_MCS_SEARCH_CONTROL_POINT_VAL
|
||||
|
||||
/*!< Microphone Control Service Mute value */
|
||||
#define ESP_BLE_AUDIO_UUID_MICS_MUTE_VAL BT_UUID_MICS_MUTE_VAL
|
||||
|
||||
/*!< Sink PAC Characteristic value */
|
||||
#define ESP_BLE_AUDIO_UUID_PACS_SNK_VAL BT_UUID_PACS_SNK_VAL
|
||||
/*!< Sink PAC Locations Characteristic value */
|
||||
#define ESP_BLE_AUDIO_UUID_PACS_SNK_LOC_VAL BT_UUID_PACS_SNK_LOC_VAL
|
||||
/*!< Source PAC Characteristic value */
|
||||
#define ESP_BLE_AUDIO_UUID_PACS_SRC_VAL BT_UUID_PACS_SRC_VAL
|
||||
/*!< Source PAC Locations Characteristic value */
|
||||
#define ESP_BLE_AUDIO_UUID_PACS_SRC_LOC_VAL BT_UUID_PACS_SRC_LOC_VAL
|
||||
/*!< Available Audio Contexts Characteristic value */
|
||||
#define ESP_BLE_AUDIO_UUID_PACS_AVAILABLE_CONTEXT_VAL BT_UUID_PACS_AVAILABLE_CONTEXT_VAL
|
||||
/*!< Supported Audio Context Characteristic value */
|
||||
#define ESP_BLE_AUDIO_UUID_PACS_SUPPORTED_CONTEXT_VAL BT_UUID_PACS_SUPPORTED_CONTEXT_VAL
|
||||
|
||||
/*!< Bearer Provider Name value */
|
||||
#define ESP_BLE_AUDIO_UUID_TBS_PROVIDER_NAME_VAL BT_UUID_TBS_PROVIDER_NAME_VAL
|
||||
/*!< Bearer UCI value */
|
||||
#define ESP_BLE_AUDIO_UUID_TBS_UCI_VAL BT_UUID_TBS_UCI_VAL
|
||||
/*!< Bearer Technology value */
|
||||
#define ESP_BLE_AUDIO_UUID_TBS_TECHNOLOGY_VAL BT_UUID_TBS_TECHNOLOGY_VAL
|
||||
/*!< Bearer URI Prefixes Supported List value */
|
||||
#define ESP_BLE_AUDIO_UUID_TBS_URI_LIST_VAL BT_UUID_TBS_URI_LIST_VAL
|
||||
/*!< Bearer Signal Strength value */
|
||||
#define ESP_BLE_AUDIO_UUID_TBS_SIGNAL_STRENGTH_VAL BT_UUID_TBS_SIGNAL_STRENGTH_VAL
|
||||
/*!< Bearer Signal Strength Reporting Interval value */
|
||||
#define ESP_BLE_AUDIO_UUID_TBS_SIGNAL_INTERVAL_VAL BT_UUID_TBS_SIGNAL_INTERVAL_VAL
|
||||
/*!< Bearer List Current Calls value */
|
||||
#define ESP_BLE_AUDIO_UUID_TBS_LIST_CURRENT_CALLS_VAL BT_UUID_TBS_LIST_CURRENT_CALLS_VAL
|
||||
/*!< Status flags value */
|
||||
#define ESP_BLE_AUDIO_UUID_TBS_STATUS_FLAGS_VAL BT_UUID_TBS_STATUS_FLAGS_VAL
|
||||
/*!< Incoming Call Target Caller ID value */
|
||||
#define ESP_BLE_AUDIO_UUID_TBS_INCOMING_URI_VAL BT_UUID_TBS_INCOMING_URI_VAL
|
||||
/*!< Call State value */
|
||||
#define ESP_BLE_AUDIO_UUID_TBS_CALL_STATE_VAL BT_UUID_TBS_CALL_STATE_VAL
|
||||
/*!< Call Control Point value */
|
||||
#define ESP_BLE_AUDIO_UUID_TBS_CALL_CONTROL_POINT_VAL BT_UUID_TBS_CALL_CONTROL_POINT_VAL
|
||||
/*!< Optional Opcodes value */
|
||||
#define ESP_BLE_AUDIO_UUID_TBS_OPTIONAL_OPCODES_VAL BT_UUID_TBS_OPTIONAL_OPCODES_VAL
|
||||
/*!< Terminate reason value */
|
||||
#define ESP_BLE_AUDIO_UUID_TBS_TERMINATE_REASON_VAL BT_UUID_TBS_TERMINATE_REASON_VAL
|
||||
/*!< Incoming Call value */
|
||||
#define ESP_BLE_AUDIO_UUID_TBS_INCOMING_CALL_VAL BT_UUID_TBS_INCOMING_CALL_VAL
|
||||
/*!< Incoming Call Friendly name value */
|
||||
#define ESP_BLE_AUDIO_UUID_TBS_FRIENDLY_NAME_VAL BT_UUID_TBS_FRIENDLY_NAME_VAL
|
||||
|
||||
/*!< Volume Control Setting value */
|
||||
#define ESP_BLE_AUDIO_UUID_VCS_STATE_VAL BT_UUID_VCS_STATE_VAL
|
||||
/*!< Volume Control Control point value */
|
||||
#define ESP_BLE_AUDIO_UUID_VCS_CONTROL_VAL BT_UUID_VCS_CONTROL_VAL
|
||||
/*!< Volume Control Flags value */
|
||||
#define ESP_BLE_AUDIO_UUID_VCS_FLAGS_VAL BT_UUID_VCS_FLAGS_VAL
|
||||
|
||||
/*!< Volume Offset State value */
|
||||
#define ESP_BLE_AUDIO_UUID_VOCS_STATE_VAL BT_UUID_VOCS_STATE_VAL
|
||||
/*!< Audio Location value */
|
||||
#define ESP_BLE_AUDIO_UUID_VOCS_LOCATION_VAL BT_UUID_VOCS_LOCATION_VAL
|
||||
/*!< Volume Offset Control Point value */
|
||||
#define ESP_BLE_AUDIO_UUID_VOCS_CONTROL_VAL BT_UUID_VOCS_CONTROL_VAL
|
||||
/*!< Volume Offset Audio Output Description value */
|
||||
#define ESP_BLE_AUDIO_UUID_VOCS_DESCRIPTION_VAL BT_UUID_VOCS_DESCRIPTION_VAL
|
||||
|
||||
/*!< Content Control ID value */
|
||||
#define ESP_BLE_AUDIO_UUID_CCID_VAL BT_UUID_CCID_VAL
|
||||
|
||||
/*!< OTS Feature Characteristic UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_OTS_FEATURE_VAL BT_UUID_OTS_FEATURE_VAL
|
||||
/*!< OTS Object Name Characteristic UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_OTS_NAME_VAL BT_UUID_OTS_NAME_VAL
|
||||
/*!< OTS Object Type Characteristic UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_OTS_TYPE_VAL BT_UUID_OTS_TYPE_VAL
|
||||
/*!< OTS Object Size Characteristic UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_OTS_SIZE_VAL BT_UUID_OTS_SIZE_VAL
|
||||
/*!< OTS Object First-Created Characteristic UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_OTS_FIRST_CREATED_VAL BT_UUID_OTS_FIRST_CREATED_VAL
|
||||
/*!< OTS Object Last-Modified Characteristic UUI value */
|
||||
#define ESP_BLE_AUDIO_UUID_OTS_LAST_MODIFIED_VAL BT_UUID_OTS_LAST_MODIFIED_VAL
|
||||
/*!< OTS Object ID Characteristic UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_OTS_ID_VAL BT_UUID_OTS_ID_VAL
|
||||
/*!< OTS Object Properties Characteristic UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_OTS_PROPERTIES_VAL BT_UUID_OTS_PROPERTIES_VAL
|
||||
/*!< OTS Object Action Control Point Characteristic UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_OTS_ACTION_CP_VAL BT_UUID_OTS_ACTION_CP_VAL
|
||||
/*!< OTS Object List Control Point Characteristic UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_OTS_LIST_CP_VAL BT_UUID_OTS_LIST_CP_VAL
|
||||
/*!< OTS Object List Filter Characteristic UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_OTS_LIST_FILTER_VAL BT_UUID_OTS_LIST_FILTER_VAL
|
||||
/*!< OTS Object Changed Characteristic UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_OTS_CHANGED_VAL BT_UUID_OTS_CHANGED_VAL
|
||||
/*!< OTS Unspecified Object Type UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_OTS_TYPE_UNSPECIFIED_VAL BT_UUID_OTS_TYPE_UNSPECIFIED_VAL
|
||||
/*!< OTS Directory Listing UUID value */
|
||||
#define ESP_BLE_AUDIO_UUID_OTS_DIRECTORY_LISTING_VAL BT_UUID_OTS_DIRECTORY_LISTING_VAL
|
||||
/*!< OTS Media Player Icon Object Type value */
|
||||
#define ESP_BLE_AUDIO_UUID_OTS_TYPE_MPL_ICON_VAL BT_UUID_OTS_TYPE_MPL_ICON_VAL
|
||||
/*!< OTS Track Segments Object Type value */
|
||||
#define ESP_BLE_AUDIO_UUID_OTS_TYPE_TRACK_SEGMENT_VAL BT_UUID_OTS_TYPE_TRACK_SEGMENT_VAL
|
||||
/*!< OTS Track Object Type value */
|
||||
#define ESP_BLE_AUDIO_UUID_OTS_TYPE_TRACK_VAL BT_UUID_OTS_TYPE_TRACK_VAL
|
||||
/*!< OTS Group Object Type value */
|
||||
#define ESP_BLE_AUDIO_UUID_OTS_TYPE_GROUP_VAL BT_UUID_OTS_TYPE_GROUP_VAL
|
||||
|
||||
/*!< Generic Audio Sink */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_GENERIC_AUDIO_SINK BT_APPEARANCE_GENERIC_AUDIO_SINK
|
||||
/*!< Standalone Speaker */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_AUDIO_SINK_STANDALONE_SPEAKER BT_APPEARANCE_AUDIO_SINK_STANDALONE_SPEAKER
|
||||
/*!< Soundbar */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_AUDIO_SINK_SOUNDBAR BT_APPEARANCE_AUDIO_SINK_SOUNDBAR
|
||||
/*!< Bookshelf Speaker */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_AUDIO_SINK_BOOKSHELF_SPEAKER BT_APPEARANCE_AUDIO_SINK_BOOKSHELF_SPEAKER
|
||||
/*!< Standmounted Speaker */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_AUDIO_SINK_STANDMOUNTED_SPEAKER BT_APPEARANCE_AUDIO_SINK_STANDMOUNTED_SPEAKER
|
||||
/*!< Speakerphone */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_AUDIO_SINK_SPEAKERPHONE BT_APPEARANCE_AUDIO_SINK_SPEAKERPHONE
|
||||
|
||||
/*!< Generic Audio Source */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_GENERIC_AUDIO_SOURCE BT_APPEARANCE_GENERIC_AUDIO_SOURCE
|
||||
/*!< Microphone */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_AUDIO_SOURCE_MICROPHONE BT_APPEARANCE_AUDIO_SOURCE_MICROPHONE
|
||||
/*!< Alarm */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_AUDIO_SOURCE_ALARM BT_APPEARANCE_AUDIO_SOURCE_ALARM
|
||||
/*!< Bell */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_AUDIO_SOURCE_BELL BT_APPEARANCE_AUDIO_SOURCE_BELL
|
||||
/*!< Horn */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_AUDIO_SOURCE_HORN BT_APPEARANCE_AUDIO_SOURCE_HORN
|
||||
/*!< Broadcasting Device */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_AUDIO_SOURCE_BROADCASTING_DEVICE BT_APPEARANCE_AUDIO_SOURCE_BROADCASTING_DEVICE
|
||||
/*!< Service Desk */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_AUDIO_SOURCE_SERVICE_DESK BT_APPEARANCE_AUDIO_SOURCE_SERVICE_DESK
|
||||
/*!< Kiosk */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_AUDIO_SOURCE_KIOSK BT_APPEARANCE_AUDIO_SOURCE_KIOSK
|
||||
/*!< Broadcasting Room */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_AUDIO_SOURCE_BROADCASTING_ROOM BT_APPEARANCE_AUDIO_SOURCE_BROADCASTING_ROOM
|
||||
/*!< Auditorium */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_AUDIO_SOURCE_AUDITORIUM BT_APPEARANCE_AUDIO_SOURCE_AUDITORIUM
|
||||
|
||||
/*!< Generic Wearable Audio Device */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_GENERIC_WEARABLE_AUDIO_DEVICE BT_APPEARANCE_GENERIC_WEARABLE_AUDIO_DEVICE
|
||||
/*!< Earbud */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_WEARABLE_AUDIO_DEVICE_EARBUD BT_APPEARANCE_WEARABLE_AUDIO_DEVICE_EARBUD
|
||||
/*!< Headset */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_WEARABLE_AUDIO_DEVICE_HEADSET BT_APPEARANCE_WEARABLE_AUDIO_DEVICE_HEADSET
|
||||
/*!< Headphones */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_WEARABLE_AUDIO_DEVICE_HEADPHONES BT_APPEARANCE_WEARABLE_AUDIO_DEVICE_HEADPHONES
|
||||
/*!< Neck Band */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_WEARABLE_AUDIO_DEVICE_NECK_BAND BT_APPEARANCE_WEARABLE_AUDIO_DEVICE_NECK_BAND
|
||||
|
||||
/*!< Generic Hearing aid */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_GENERIC_HEARING_AID BT_APPEARANCE_GENERIC_HEARING_AID
|
||||
/*!< In-ear hearing aid */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_HEARING_AID_IN_EAR BT_APPEARANCE_HEARING_AID_IN_EAR
|
||||
/*!< Behind-ear hearing aid */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_HEARING_AID_BEHIND_EAR BT_APPEARANCE_HEARING_AID_BEHIND_EAR
|
||||
/*!< Cochlear Implant */
|
||||
#define ESP_BLE_AUDIO_APPEARANCE_HEARING_AID_COCHLEAR_IMPLANT BT_APPEARANCE_HEARING_AID_COCHLEAR_IMPLANT
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_BLE_AUDIO_DEFS_H_ */
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_BLE_AUDIO_GMAP_API_H_
|
||||
#define ESP_BLE_AUDIO_GMAP_API_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include <zephyr/bluetooth/audio/gmap.h>
|
||||
|
||||
#include "common/init.h"
|
||||
#include "common/host.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!< Gaming Role Unicast Game Gateway */
|
||||
#define ESP_BLE_AUDIO_GMAP_ROLE_UGG BT_GMAP_ROLE_UGG
|
||||
/*!< Gaming Role Unicast Game Terminal */
|
||||
#define ESP_BLE_AUDIO_GMAP_ROLE_UGT BT_GMAP_ROLE_UGT
|
||||
/*!< Gaming Role Broadcast Game Sender */
|
||||
#define ESP_BLE_AUDIO_GMAP_ROLE_BGS BT_GMAP_ROLE_BGS
|
||||
/*!< Gaming Role Broadcast Game Receiver */
|
||||
#define ESP_BLE_AUDIO_GMAP_ROLE_BGR BT_GMAP_ROLE_BGR
|
||||
/** Gaming Role bitfield */
|
||||
typedef enum bt_gmap_role esp_ble_audio_gmap_role_t;
|
||||
|
||||
/*!< Support transmitting multiple LC3 codec frames per block in an SDU */
|
||||
#define ESP_BLE_AUDIO_GMAP_UGG_FEAT_MULTIPLEX BT_GMAP_UGG_FEAT_MULTIPLEX
|
||||
/*!< 96 kbps source support */
|
||||
#define ESP_BLE_AUDIO_GMAP_UGG_FEAT_96KBPS_SOURCE BT_GMAP_UGG_FEAT_96KBPS_SOURCE
|
||||
/*!< Support for receiving at least two channels of audio, each in a separate CIS */
|
||||
#define ESP_BLE_AUDIO_GMAP_UGG_FEAT_MULTISINK BT_GMAP_UGG_FEAT_MULTISINK
|
||||
/** Unicast Game Gateway Feature bitfield */
|
||||
typedef enum bt_gmap_ugg_feat esp_ble_audio_gmap_ugg_feat_t;
|
||||
|
||||
/*!< Source support */
|
||||
#define ESP_BLE_AUDIO_GMAP_UGT_FEAT_SOURCE BT_GMAP_UGT_FEAT_SOURCE
|
||||
/*!< 80 kbps source support */
|
||||
#define ESP_BLE_AUDIO_GMAP_UGT_FEAT_80KBPS_SOURCE BT_GMAP_UGT_FEAT_80KBPS_SOURCE
|
||||
/*!< Sink support */
|
||||
#define ESP_BLE_AUDIO_GMAP_UGT_FEAT_SINK BT_GMAP_UGT_FEAT_SINK
|
||||
/*!< 64 kbps sink support */
|
||||
#define ESP_BLE_AUDIO_GMAP_UGT_FEAT_64KBPS_SINK BT_GMAP_UGT_FEAT_64KBPS_SINK
|
||||
/*!< Support for receiving multiple LC3 codec frames per block in an SDU */
|
||||
#define ESP_BLE_AUDIO_GMAP_UGT_FEAT_MULTIPLEX BT_GMAP_UGT_FEAT_MULTIPLEX
|
||||
/*!< Support for receiving at least two audio channels, each in a separate CIS */
|
||||
#define ESP_BLE_AUDIO_GMAP_UGT_FEAT_MULTISINK BT_GMAP_UGT_FEAT_MULTISINK
|
||||
/*!< Support for sending at least two audio channels, each in a separate CIS */
|
||||
#define ESP_BLE_AUDIO_GMAP_UGT_FEAT_MULTISOURCE BT_GMAP_UGT_FEAT_MULTISOURCE
|
||||
/** Unicast Game Terminal Feature bitfield */
|
||||
typedef enum bt_gmap_ugt_feat esp_ble_audio_gmap_ugt_feat_t;
|
||||
|
||||
/*!< 96 kbps support */
|
||||
#define ESP_BLE_AUDIO_GMAP_BGS_FEAT_96KBPS BT_GMAP_BGS_FEAT_96KBPS
|
||||
/** Broadcast Game Receiver Feature bitfield */
|
||||
typedef enum bt_gmap_bgs_feat esp_ble_audio_gmap_bgs_feat_t;
|
||||
|
||||
/*!< Support for receiving at least two audio channels, each in a separate BIS */
|
||||
#define ESP_BLE_AUDIO_GMAP_BGR_FEAT_MULTISINK BT_GMAP_BGR_FEAT_MULTISINK
|
||||
/*!< Support for receiving multiple LC3 codec frames per block in an SDU */
|
||||
#define ESP_BLE_AUDIO_GMAP_BGR_FEAT_MULTIPLEX BT_GMAP_BGR_FEAT_MULTIPLEX
|
||||
/** Broadcast Game Receiver Feature bitfield */
|
||||
typedef enum bt_gmap_bgr_feat esp_ble_audio_gmap_bgr_feat_t;
|
||||
|
||||
/** Hearing Access Service Client callback structure */
|
||||
typedef struct bt_gmap_cb esp_ble_audio_gmap_cb_t;
|
||||
|
||||
/** Broadcast Game Receiver Feature bitfield */
|
||||
typedef struct bt_gmap_feat esp_ble_audio_gmap_feat_t;
|
||||
|
||||
/**
|
||||
* @brief Registers the callbacks used by the Gaming Audio Profile.
|
||||
*
|
||||
* @param cb The callback structure.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_gmap_cb_register(const esp_ble_audio_gmap_cb_t *cb);
|
||||
|
||||
/**
|
||||
* @brief Discover Gaming Service on a remote device.
|
||||
*
|
||||
* Procedure to find a Gaming Service on a server identified by @p conn_handle.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_gmap_discover(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Adds GMAS instance to database and sets the received Gaming Audio Profile role(s).
|
||||
*
|
||||
* @param role Gaming Audio Profile role(s) of the device (one or multiple).
|
||||
* @param features Features of the roles. If a role is not in the @p role parameter, then
|
||||
* the feature value for that role is simply ignored.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_gmap_register(esp_ble_audio_gmap_role_t role,
|
||||
esp_ble_audio_gmap_feat_t features);
|
||||
|
||||
/**
|
||||
* @brief Set one or multiple Gaming Audio Profile roles and features dynamically.
|
||||
*
|
||||
* Previously registered value will be overwritten. If there is a role change, this will trigger
|
||||
* a Gaming Audio Service (GMAS) service change. If there is only a feature change, no service
|
||||
* change will happen.
|
||||
*
|
||||
* @param role Gaming Audio Profile role(s).
|
||||
* @param features Features of the roles. If a role is not in the @p role parameter, then
|
||||
* the feature value for that role is simply ignored.
|
||||
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_gmap_set_role(esp_ble_audio_gmap_role_t role,
|
||||
esp_ble_audio_gmap_feat_t features);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_BLE_AUDIO_GMAP_API_H_ */
|
||||
@@ -0,0 +1,324 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_BLE_AUDIO_GMAP_LC3_PRESET_DEFS_H_
|
||||
#define ESP_BLE_AUDIO_GMAP_LC3_PRESET_DEFS_H_
|
||||
|
||||
#include <zephyr/bluetooth/audio/gmap_lc3_preset.h>
|
||||
|
||||
#include "esp_ble_audio_bap_lc3_preset_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Base macro for defining GMAP LC3 presets.
|
||||
*
|
||||
* @param _name Preset name.
|
||||
* @param _freq Sampling frequency (16, 32, or 48 kHz).
|
||||
* @param _duration Frame duration (7.5 or 10 ms).
|
||||
* @param _loc Audio channel location.
|
||||
* @param _len Frame length in bytes.
|
||||
* @param _frames_per_sdu Number of frames per SDU.
|
||||
* @param _stream_context Stream context type.
|
||||
* @param _interval Interval between packets in microseconds.
|
||||
* @param _sdu SDU size in bytes.
|
||||
* @param _rtn Maximum number of retransmissions.
|
||||
* @param _latency Maximum latency in milliseconds.
|
||||
* @param _pd Presentation delay in microseconds.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_GMAP_LC3_PRESET_DEFINE(_name, _freq, _duration, _loc, _len, \
|
||||
_frames_per_sdu, _stream_context, \
|
||||
_interval, _sdu, _rtn, _latency, _pd) \
|
||||
static uint8_t codec_cfg_data_##_name[] = \
|
||||
ESP_BLE_AUDIO_CODEC_CFG_LC3_DATA(_freq, _duration, _loc, _len, _frames_per_sdu); \
|
||||
static uint8_t codec_cfg_meta_##_name[] = \
|
||||
ESP_BLE_AUDIO_CODEC_CFG_LC3_META(_stream_context); \
|
||||
static esp_ble_audio_bap_lc3_preset_t _name = \
|
||||
ESP_BLE_AUDIO_BAP_LC3_PRESET(ESP_BLE_AUDIO_CODEC_CFG_LC3(codec_cfg_data_##_name, \
|
||||
codec_cfg_meta_##_name), \
|
||||
ESP_BLE_AUDIO_BAP_QOS_CFG_UNFRAMED(_interval, _sdu, _rtn, \
|
||||
_latency, _pd));
|
||||
|
||||
/**
|
||||
* @brief Gaming Reliable (GR) preset at 32kHz, 7.5ms frame duration.
|
||||
*
|
||||
* Optimized for reliable gaming audio with low latency (15ms) and standard presentation delay (10ms).
|
||||
*
|
||||
* @param _name Preset name.
|
||||
* @param _loc Audio channel location.
|
||||
* @param _stream_context Stream context type.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_GMAP_LC3_PRESET_32_1_GR_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_GMAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_32KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 60U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 60U, 1U, 15U, 10000U)
|
||||
|
||||
/**
|
||||
* @brief Gaming Reliable (GR) preset at 32kHz, 10ms frame duration.
|
||||
*
|
||||
* Higher quality variant with increased frame duration for better audio quality.
|
||||
*
|
||||
* @param _name Preset name.
|
||||
* @param _loc Audio channel location.
|
||||
* @param _stream_context Stream context type.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_GMAP_LC3_PRESET_32_2_GR_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_GMAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_32KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 80U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 80U, 1U, 20U, 10000U)
|
||||
|
||||
/**
|
||||
* @brief Gaming Reliable (GR) preset at 48kHz, 7.5ms frame duration.
|
||||
*
|
||||
* High-quality gaming audio with minimal latency.
|
||||
*
|
||||
* @param _name Preset name.
|
||||
* @param _loc Audio channel location.
|
||||
* @param _stream_context Stream context type.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_GMAP_LC3_PRESET_48_1_GR_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_GMAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 75U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 75U, 1U, 15U, 10000U)
|
||||
|
||||
/**
|
||||
* @brief Gaming Reliable (GR) preset at 48kHz, 10ms frame duration.
|
||||
*
|
||||
* High-quality gaming audio with balanced latency and quality.
|
||||
*
|
||||
* @param _name Preset name.
|
||||
* @param _loc Audio channel location.
|
||||
* @param _stream_context Stream context type.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_GMAP_LC3_PRESET_48_2_GR_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_GMAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 100U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 100U, 1U, 20U, 10000U)
|
||||
|
||||
/**
|
||||
* @brief Gaming Reliable (GR) preset at 48kHz, 7.5ms frame duration, higher bitrate.
|
||||
*
|
||||
* Enhanced quality gaming audio with minimal latency.
|
||||
*
|
||||
* @param _name Preset name.
|
||||
* @param _loc Audio channel location.
|
||||
* @param _stream_context Stream context type.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_GMAP_LC3_PRESET_48_3_GR_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_GMAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 90U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 90U, 1U, 15U, 10000U)
|
||||
|
||||
/**
|
||||
* @brief Gaming Reliable (GR) preset at 48kHz, 10ms frame duration, higher bitrate.
|
||||
*
|
||||
* Premium quality gaming audio with balanced latency.
|
||||
*
|
||||
* @param _name Preset name.
|
||||
* @param _loc Audio channel location.
|
||||
* @param _stream_context Stream context type.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_GMAP_LC3_PRESET_48_4_GR_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_GMAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 120u, 1, \
|
||||
_stream_context, \
|
||||
10000u, 120U, 1U, 20U, 10000U)
|
||||
|
||||
/**
|
||||
* @brief Gaming Standard (GS) preset at 16kHz, 7.5ms frame duration.
|
||||
*
|
||||
* Basic gaming audio with longer presentation delay (60ms).
|
||||
*
|
||||
* @param _name Preset name.
|
||||
* @param _loc Audio channel location.
|
||||
* @param _stream_context Stream context type.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_GMAP_LC3_PRESET_16_1_GS_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_GMAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_16KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 30U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 30U, 1U, 15U, 60000U)
|
||||
|
||||
/**
|
||||
* @brief Gaming Standard (GS) preset at 16kHz, 10ms frame duration.
|
||||
*
|
||||
* Basic gaming audio with better quality and longer presentation delay.
|
||||
*
|
||||
* @param _name Preset name.
|
||||
* @param _loc Audio channel location.
|
||||
* @param _stream_context Stream context type.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_GMAP_LC3_PRESET_16_2_GS_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_GMAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_16KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 40U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 40U, 1U, 20U, 60000U)
|
||||
|
||||
/**
|
||||
* @brief Gaming Standard (GS) preset at 32kHz, 7.5ms frame duration.
|
||||
*
|
||||
* Medium quality gaming audio with standard latency.
|
||||
*
|
||||
* @param _name Preset name.
|
||||
* @param _loc Audio channel location.
|
||||
* @param _stream_context Stream context type.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_GMAP_LC3_PRESET_32_1_GS_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_GMAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_32KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 60U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 60U, 1U, 15U, 60000U)
|
||||
|
||||
/**
|
||||
* @brief Gaming Standard (GS) preset at 32kHz, 10ms frame duration.
|
||||
*
|
||||
* Enhanced medium quality gaming audio.
|
||||
*
|
||||
* @param _name Preset name.
|
||||
* @param _loc Audio channel location.
|
||||
* @param _stream_context Stream context type.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_GMAP_LC3_PRESET_32_2_GS_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_GMAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_32KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 80U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 80U, 1U, 20U, 60000U)
|
||||
|
||||
/**
|
||||
* @brief Gaming Standard (GS) preset at 48kHz, 7.5ms frame duration.
|
||||
*
|
||||
* High quality gaming audio with standard latency.
|
||||
*
|
||||
* @param _name Preset name.
|
||||
* @param _loc Audio channel location.
|
||||
* @param _stream_context Stream context type.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_GMAP_LC3_PRESET_48_1_GS_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_GMAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 75U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 75U, 1U, 15U, 60000U)
|
||||
|
||||
/**
|
||||
* @brief Gaming Standard (GS) preset at 48kHz, 10ms frame duration.
|
||||
*
|
||||
* Premium quality gaming audio with standard latency.
|
||||
*
|
||||
* @param _name Preset name.
|
||||
* @param _loc Audio channel location.
|
||||
* @param _stream_context Stream context type.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_GMAP_LC3_PRESET_48_2_GS_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_GMAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 100U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 100U, 1U, 20U, 60000U)
|
||||
|
||||
/**
|
||||
* @brief Generic Gaming (G) preset at 48kHz, 7.5ms frame duration.
|
||||
*
|
||||
* High quality gaming audio with ultra-low latency (8ms).
|
||||
*
|
||||
* @param _name Preset name.
|
||||
* @param _loc Audio channel location.
|
||||
* @param _stream_context Stream context type.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_GMAP_LC3_PRESET_48_1_G_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_GMAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 75U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 75U, 1U, 8U, 10000U)
|
||||
|
||||
/**
|
||||
* @brief Generic Gaming (G) preset at 48kHz, 10ms frame duration.
|
||||
*
|
||||
* High quality gaming audio with very low latency (10ms).
|
||||
*
|
||||
* @param _name Preset name.
|
||||
* @param _loc Audio channel location.
|
||||
* @param _stream_context Stream context type.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_GMAP_LC3_PRESET_48_2_G_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_GMAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 100U, 1, \
|
||||
_stream_context, \
|
||||
10000u, 100U, 1U, 10U, 10000U)
|
||||
|
||||
/**
|
||||
* @brief Generic Gaming (G) preset at 48kHz, 7.5ms frame duration, higher bitrate.
|
||||
*
|
||||
* Premium quality gaming audio with ultra-low latency.
|
||||
*
|
||||
* @param _name Preset name.
|
||||
* @param _loc Audio channel location.
|
||||
* @param _stream_context Stream context type.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_GMAP_LC3_PRESET_48_3_G_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_GMAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_7_5, \
|
||||
_loc, 90U, 1, \
|
||||
_stream_context, \
|
||||
7500u, 90U, 1U, 8U, 10000U)
|
||||
|
||||
/**
|
||||
* @brief Generic Gaming (G) preset at 48kHz, 10ms frame duration, higher bitrate.
|
||||
*
|
||||
* Highest quality gaming audio with very low latency.
|
||||
*
|
||||
* @param _name Preset name.
|
||||
* @param _loc Audio channel location.
|
||||
* @param _stream_context Stream context type.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_GMAP_LC3_PRESET_48_4_G_DEFINE(_name, _loc, _stream_context) \
|
||||
ESP_BLE_AUDIO_GMAP_LC3_PRESET_DEFINE(_name, \
|
||||
BT_AUDIO_CODEC_CFG_FREQ_48KHZ, \
|
||||
BT_AUDIO_CODEC_CFG_DURATION_10, \
|
||||
_loc, 120u, 1, \
|
||||
_stream_context, \
|
||||
10000u, 120U, 1U, 10U, 10000U)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_BLE_AUDIO_GMAP_LC3_PRESET_DEFS_H_ */
|
||||
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Codecoup
|
||||
* SPDX-FileCopyrightText: 2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_BLE_AUDIO_HAS_API_H_
|
||||
#define ESP_BLE_AUDIO_HAS_API_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include <zephyr/bluetooth/conn.h>
|
||||
#include <zephyr/bluetooth/audio/has.h>
|
||||
|
||||
#include "common/init.h"
|
||||
#include "common/host.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!< No index */
|
||||
#define ESP_BLE_AUDIO_HAS_PRESET_INDEX_NONE BT_HAS_PRESET_INDEX_NONE
|
||||
/*!< First preset index */
|
||||
#define ESP_BLE_AUDIO_HAS_PRESET_INDEX_FIRST BT_HAS_PRESET_INDEX_FIRST
|
||||
/*!< Last preset index */
|
||||
#define ESP_BLE_AUDIO_HAS_PRESET_INDEX_LAST BT_HAS_PRESET_INDEX_LAST
|
||||
|
||||
/*!< Preset name minimum length */
|
||||
#define ESP_BLE_AUDIO_HAS_PRESET_NAME_MIN BT_HAS_PRESET_NAME_MIN
|
||||
/*!< Preset name maximum length */
|
||||
#define ESP_BLE_AUDIO_HAS_PRESET_NAME_MAX BT_HAS_PRESET_NAME_MAX
|
||||
|
||||
/*!< No properties set */
|
||||
#define ESP_BLE_AUDIO_HAS_PROP_NONE BT_HAS_PROP_NONE
|
||||
/*!< Preset name can be written by the client */
|
||||
#define ESP_BLE_AUDIO_HAS_PROP_WRITABLE BT_HAS_PROP_WRITABLE
|
||||
/*!< Preset availability */
|
||||
#define ESP_BLE_AUDIO_HAS_PROP_AVAILABLE BT_HAS_PROP_AVAILABLE
|
||||
/** Preset Properties values */
|
||||
typedef enum bt_has_properties esp_ble_audio_has_properties_t;
|
||||
|
||||
/*!< Indicate support for presets */
|
||||
#define ESP_BLE_AUDIO_HAS_PRESET_SUPPORT BT_HAS_PRESET_SUPPORT
|
||||
/** Hearing Aid device capabilities */
|
||||
typedef enum bt_has_capabilities esp_ble_audio_has_capabilities_t;
|
||||
|
||||
/**
|
||||
* Two hearing aids that form a Coordinated Set, one for the right ear and one for the left
|
||||
* ear of the user. Typically used by a user with bilateral hearing loss.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_HAS_HEARING_AID_TYPE_BINAURAL BT_HAS_HEARING_AID_TYPE_BINAURAL
|
||||
/**
|
||||
* A single hearing aid for the left or the right ear. Typically used by a user with
|
||||
* unilateral hearing loss.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_HAS_HEARING_AID_TYPE_MONAURAL BT_HAS_HEARING_AID_TYPE_MONAURAL
|
||||
/**
|
||||
* Two hearing aids with a connection to one another that expose a single Bluetooth radio
|
||||
* interface.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_HAS_HEARING_AID_TYPE_BANDED BT_HAS_HEARING_AID_TYPE_BANDED
|
||||
/** Hearing Aid device type */
|
||||
typedef enum bt_has_hearing_aid_type esp_ble_audio_has_hearing_aid_type_t;
|
||||
|
||||
/** Hearing Access Service object */
|
||||
typedef struct bt_has esp_ble_audio_has_t;
|
||||
|
||||
/** Hearing Access Service Client callback structure */
|
||||
typedef struct bt_has_client_cb esp_ble_audio_has_client_cb_t;
|
||||
|
||||
/** Structure for registering features of a Hearing Access Service instance */
|
||||
typedef struct bt_has_features_param esp_ble_audio_has_features_param_t;
|
||||
|
||||
/** Preset operations structure */
|
||||
typedef struct bt_has_preset_ops esp_ble_audio_has_preset_ops_t;
|
||||
|
||||
/** Preset record definition */
|
||||
typedef struct bt_has_preset_record esp_ble_audio_has_preset_record_t;
|
||||
|
||||
/** Register structure for preset */
|
||||
typedef struct bt_has_preset_register_param esp_ble_audio_has_preset_register_param_t;
|
||||
|
||||
/**
|
||||
* @brief Registers the callbacks used by the Hearing Access Service client.
|
||||
*
|
||||
* @param cb The callback structure.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_has_client_cb_register(const esp_ble_audio_has_client_cb_t *cb);
|
||||
|
||||
/**
|
||||
* @brief Discover Hearing Access Service on a remote device.
|
||||
*
|
||||
* Client method to find a Hearing Access Service on a server identified by @p conn_handle.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_has_client_discover(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Read Preset Records.
|
||||
*
|
||||
* Client method to read up to @p max_count presets starting from given @p index.
|
||||
*
|
||||
* @param has Pointer to the Hearing Access Service object.
|
||||
* @param index The index to start with.
|
||||
* @param max_count Maximum number of presets to read.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_has_client_presets_read(esp_ble_audio_has_t *has,
|
||||
uint8_t index,
|
||||
uint8_t max_count);
|
||||
|
||||
/**
|
||||
* @brief Set Active Preset.
|
||||
*
|
||||
* Client procedure to set preset identified by @p index as active.
|
||||
*
|
||||
* @param has Pointer to the Hearing Access Service object.
|
||||
* @param index Preset index to activate.
|
||||
* @param sync Request active preset synchronization in set.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_has_client_preset_set(esp_ble_audio_has_t *has,
|
||||
uint8_t index, bool sync);
|
||||
|
||||
/**
|
||||
* @brief Activate Next Preset.
|
||||
*
|
||||
* Client procedure to set next available preset as active.
|
||||
*
|
||||
* @param has Pointer to the Hearing Access Service object.
|
||||
* @param sync Request active preset synchronization in set.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_has_client_preset_next(esp_ble_audio_has_t *has, bool sync);
|
||||
|
||||
/**
|
||||
* @brief Activate Previous Preset.
|
||||
*
|
||||
* Client procedure to set previous available preset as active.
|
||||
*
|
||||
* @param has Pointer to the Hearing Access Service object.
|
||||
* @param sync Request active preset synchronization in set.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_has_client_preset_prev(esp_ble_audio_has_t *has, bool sync);
|
||||
|
||||
/**
|
||||
* @brief Register the Hearing Access Service instance.
|
||||
*
|
||||
* @param features Hearing Access Service register parameters.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_has_register(const esp_ble_audio_has_features_param_t *features);
|
||||
|
||||
/**
|
||||
* @brief Register preset.
|
||||
*
|
||||
* Register preset. The preset will be added to the list of exposed preset records.
|
||||
*
|
||||
* @param param Preset registration parameter.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_has_preset_register(const esp_ble_audio_has_preset_register_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief Unregister Preset.
|
||||
*
|
||||
* Unregister preset. The preset will be removed from the list of preset records.
|
||||
*
|
||||
* @param index The index of preset that's being requested to unregister.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_has_preset_unregister(uint8_t index);
|
||||
|
||||
/**
|
||||
* @brief Set the preset as available.
|
||||
*
|
||||
* This will notify preset availability to peer devices. Only available preset can
|
||||
* be selected as active preset.
|
||||
*
|
||||
* @param index The index of preset that's became available.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_has_preset_available(uint8_t index);
|
||||
|
||||
/**
|
||||
* @brief Set the preset as unavailable.
|
||||
*
|
||||
* This will notify preset availability to peer devices. Unavailable preset cannot
|
||||
* be selected as active preset.
|
||||
*
|
||||
* @param index The index of preset that's became unavailable.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_has_preset_unavailable(uint8_t index);
|
||||
|
||||
/**
|
||||
* @brief Set active preset.
|
||||
*
|
||||
* Function used to set the preset identified by the @p index as the active preset.
|
||||
* The preset index will be notified to peer devices.
|
||||
*
|
||||
* @param index Preset index.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_has_preset_active_set(uint8_t index);
|
||||
|
||||
/**
|
||||
* @brief Get active preset.
|
||||
*
|
||||
* Function used to get the currently active preset index.
|
||||
*
|
||||
* @return Active preset index.
|
||||
*/
|
||||
uint8_t esp_ble_audio_has_preset_active_get(void);
|
||||
|
||||
/**
|
||||
* @brief Change the Preset Name.
|
||||
*
|
||||
* Change the name of the preset identified by @p index.
|
||||
*
|
||||
* @param index The index of the preset to change the name of.
|
||||
* @param name Name to write.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_has_preset_name_change(uint8_t index, const char *name);
|
||||
|
||||
/**
|
||||
* @brief Change the Hearing Aid Features.
|
||||
*
|
||||
* Change the hearing aid features.
|
||||
*
|
||||
* @param features The features to be set.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_has_features_set(const esp_ble_audio_has_features_param_t *features);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_BLE_AUDIO_HAS_API_H_ */
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Intel Corporation
|
||||
* SPDX-FileCopyrightText: 2022-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_BLE_AUDIO_LC3_DEFS_H_
|
||||
#define ESP_BLE_AUDIO_LC3_DEFS_H_
|
||||
|
||||
#include <zephyr/bluetooth/audio/lc3.h>
|
||||
|
||||
#include "esp_ble_audio_codec_api.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 codec capability.
|
||||
*
|
||||
* @param _freq Supported Sampling Frequencies bitfield.
|
||||
* @param _duration Supported Frame Durations bitfield.
|
||||
* @param _chan_count Supported channels.
|
||||
* @param _len_min Minimum number of octets supported per codec frame.
|
||||
* @param _len_max Maximum number of octets supported per codec frame.
|
||||
* @param _max_frames_per_sdu Supported maximum codec frames per SDU.
|
||||
* Optional and will be included only if != 1.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_CODEC_CAP_LC3_DATA(_freq, _duration, _chan_count, \
|
||||
_len_min, _len_max, \
|
||||
_max_frames_per_sdu) \
|
||||
BT_AUDIO_CODEC_CAP_LC3_DATA(_freq, _duration, _chan_count, \
|
||||
_len_min, _len_max, \
|
||||
_max_frames_per_sdu)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 codec metadata.
|
||||
*
|
||||
* @param _prefer_context Preferred contexts.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_CODEC_CAP_LC3_META(_prefer_context) \
|
||||
BT_AUDIO_CODEC_CAP_LC3_META(_prefer_context)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 codec capability.
|
||||
*
|
||||
* @param _data LC3 codec capability data.
|
||||
* @param _meta LC3 codec capability metadata.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_CODEC_CAP_LC3(_data, _meta) \
|
||||
ESP_BLE_AUDIO_CODEC_CAP(ESP_BLE_ISO_CODING_FORMAT_LC3, 0x0000, 0x0000, _data, _meta)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 codec data configuration.
|
||||
*
|
||||
* @param _freq Sampling frequency.
|
||||
* @param _duration Frame duration.
|
||||
* @param _loc Audio channel location bitfield.
|
||||
* @param _len Octets per frame (16-bit integer).
|
||||
* @param _frames_per_sdu Frames per SDU (8-bit integer). This value is
|
||||
* optional and will be included only if != 1.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_CODEC_CFG_LC3_DATA(_freq, _duration, _loc, _len, _frames_per_sdu) \
|
||||
BT_AUDIO_CODEC_CFG_LC3_DATA(_freq, _duration, _loc, _len, _frames_per_sdu)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 codec metadata configuration.
|
||||
*
|
||||
* @param _stream_context Stream context.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_CODEC_CFG_LC3_META(_stream_context) \
|
||||
BT_AUDIO_CODEC_CFG_LC3_META(_stream_context)
|
||||
|
||||
/**
|
||||
* @brief Helper to declare LC3 codec configuration.
|
||||
*
|
||||
* @param _data LC3 codec configuration data.
|
||||
* @param _meta LC3 codec configuration metadata.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_CODEC_CFG_LC3(_data, _meta) \
|
||||
ESP_BLE_AUDIO_CODEC_CFG(ESP_BLE_ISO_CODING_FORMAT_LC3, 0x0000, 0x0000, _data, _meta)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_BLE_AUDIO_LC3_DEFS_H_ */
|
||||
@@ -0,0 +1,393 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_BLE_AUDIO_MCC_API_H_
|
||||
#define ESP_BLE_AUDIO_MCC_API_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include <zephyr/bluetooth/services/ots.h>
|
||||
#include <zephyr/bluetooth/audio/mcc.h>
|
||||
|
||||
#include "common/init.h"
|
||||
#include "common/host.h"
|
||||
|
||||
#include "esp_ble_audio_media_proxy_api.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Media control client callbacks */
|
||||
typedef struct bt_mcc_cb esp_ble_audio_mcc_cb_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize Media Control Client.
|
||||
*
|
||||
* @param cb Callbacks to be used.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_init(esp_ble_audio_mcc_cb_t *cb);
|
||||
|
||||
/**
|
||||
* @brief Discover Media Control Service.
|
||||
*
|
||||
* Discover Media Control Service (MCS) on the server given by the connection
|
||||
* Optionally subscribe to notifications.
|
||||
*
|
||||
* Shall be called once, after media control client initialization and before
|
||||
* using other media control client functionality.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param subscribe Whether to subscribe to notifications.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_discover_mcs(uint16_t conn_handle, bool subscribe);
|
||||
|
||||
/**
|
||||
* @brief Read Media Player Name.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_read_player_name(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Read Icon Object ID.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_read_icon_obj_id(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Read Icon Object URL.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_read_icon_url(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Read Track Title.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_read_track_title(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Read Track Duration.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_read_track_duration(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Read Track Position.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_read_track_position(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Set Track position.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param pos Track position.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_set_track_position(uint16_t conn_handle, int32_t pos);
|
||||
|
||||
/**
|
||||
* @brief Read Playback speed.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_read_playback_speed(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Set Playback Speed.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param speed Playback speed.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_set_playback_speed(uint16_t conn_handle, int8_t speed);
|
||||
|
||||
/**
|
||||
* @brief Read Seeking speed.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_read_seeking_speed(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Read Track Segments Object ID.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_read_segments_obj_id(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Read Current Track Object ID.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_read_current_track_obj_id(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Set Current Track Object ID.
|
||||
*
|
||||
* Set the Current Track to the track given by the @p id parameter.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param id Object Transfer Service ID (UINT48) of the track to set as the current track.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_set_current_track_obj_id(uint16_t conn_handle, uint64_t id);
|
||||
|
||||
/**
|
||||
* @brief Read Next Track Object ID.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_read_next_track_obj_id(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Set Next Track Object ID.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param id Object Transfer Service ID (UINT48) of the track to set as the next track.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_set_next_track_obj_id(uint16_t conn_handle, uint64_t id);
|
||||
|
||||
/**
|
||||
* @brief Read Current Group Object ID.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_read_current_group_obj_id(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Set Current Group Object ID.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param id Object Transfer Service ID (UINT48) of the group to set as the current group.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_set_current_group_obj_id(uint16_t conn_handle, uint64_t id);
|
||||
|
||||
/**
|
||||
* @brief Read Parent Group Object ID.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_read_parent_group_obj_id(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Read Playing Order.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_read_playing_order(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Set Playing Order.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param order Playing order.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_set_playing_order(uint16_t conn_handle, uint8_t order);
|
||||
|
||||
/**
|
||||
* @brief Read Playing Orders Supported.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_read_playing_orders_supported(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Read Media State.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_read_media_state(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Send a command.
|
||||
*
|
||||
* Write a command (e.g. "play", "pause") to the server's media control point.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param cmd The command to send.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_send_cmd(uint16_t conn_handle,
|
||||
const esp_ble_audio_mpl_cmd_t *cmd);
|
||||
|
||||
/**
|
||||
* @brief Read Opcodes Supported.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_read_opcodes_supported(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Send a Search command.
|
||||
*
|
||||
* Write a search to the server's search control point.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param search The search.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_send_search(uint16_t conn_handle,
|
||||
const esp_ble_audio_mpl_search_t *search);
|
||||
|
||||
/**
|
||||
* @brief Search Results Group Object ID.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_read_search_results_obj_id(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Read Content Control ID.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_read_content_control_id(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Read the current object metadata.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_otc_read_object_metadata(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Read the Icon Object.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_otc_read_icon_object(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Read the Track Segments Object.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_otc_read_track_segments_object(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Read the Current Track Object.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_otc_read_current_track_object(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Read the Next Track Object.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_otc_read_next_track_object(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Read the Current Group Object.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_otc_read_current_group_object(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Read the Parent Group Object.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_mcc_otc_read_parent_group_object(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Look up MCC OTC instance.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return Pointer to a MCC OTC instance if found else NULL.
|
||||
*/
|
||||
struct bt_ots_client *esp_ble_audio_mcc_otc_inst(uint16_t conn_handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_BLE_AUDIO_MCC_API_H_ */
|
||||
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_BLE_AUDIO_MCS_DEFS_H_
|
||||
#define ESP_BLE_AUDIO_MCS_DEFS_H_
|
||||
|
||||
#include <zephyr/bluetooth/audio/mcs.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!< Minimum playback speed, resulting in 25% speed */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYBACK_SPEED_MIN BT_MCS_PLAYBACK_SPEED_MIN
|
||||
/*!< Quarter playback speed, resulting in 25% speed */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYBACK_SPEED_QUARTER BT_MCS_PLAYBACK_SPEED_QUARTER
|
||||
/*!< Half playback speed, resulting in 50% speed */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYBACK_SPEED_HALF BT_MCS_PLAYBACK_SPEED_HALF
|
||||
/*!< Unity playback speed, resulting in 100% speed */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYBACK_SPEED_UNITY BT_MCS_PLAYBACK_SPEED_UNITY
|
||||
/*!< Double playback speed, resulting in 200% speed */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYBACK_SPEED_DOUBLE BT_MCS_PLAYBACK_SPEED_DOUBLE
|
||||
/*!< Max playback speed, resulting in 395.7% speed (nearly 400%) */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYBACK_SPEED_MAX BT_MCS_PLAYBACK_SPEED_MAX
|
||||
|
||||
/*!< Maximum seeking speed - Can be negated */
|
||||
#define ESP_BLE_AUDIO_MCS_SEEKING_SPEED_FACTOR_MAX BT_MCS_SEEKING_SPEED_FACTOR_MAX
|
||||
/*!< Minimum seeking speed - Can be negated */
|
||||
#define ESP_BLE_AUDIO_MCS_SEEKING_SPEED_FACTOR_MIN BT_MCS_SEEKING_SPEED_FACTOR_MIN
|
||||
/*!< No seeking */
|
||||
#define ESP_BLE_AUDIO_MCS_SEEKING_SPEED_FACTOR_ZERO BT_MCS_SEEKING_SPEED_FACTOR_ZERO
|
||||
|
||||
/*!< A single track is played once; there is no next track. */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYING_ORDER_SINGLE_ONCE BT_MCS_PLAYING_ORDER_SINGLE_ONCE
|
||||
/*!< A single track is played repeatedly; the next track is the current track. */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYING_ORDER_SINGLE_REPEAT BT_MCS_PLAYING_ORDER_SINGLE_REPEAT
|
||||
/*!< The tracks within a group are played once in track order. */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYING_ORDER_INORDER_ONCE BT_MCS_PLAYING_ORDER_INORDER_ONCE
|
||||
/*!< The tracks within a group are played in track order repeatedly. */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYING_ORDER_INORDER_REPEAT BT_MCS_PLAYING_ORDER_INORDER_REPEAT
|
||||
/*!< The tracks within a group are played once only from the oldest first. */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYING_ORDER_OLDEST_ONCE BT_MCS_PLAYING_ORDER_OLDEST_ONCE
|
||||
/*!< The tracks within a group are played from the oldest first repeatedly. */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYING_ORDER_OLDEST_REPEAT BT_MCS_PLAYING_ORDER_OLDEST_REPEAT
|
||||
/*!< The tracks within a group are played once only from the newest first. */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYING_ORDER_NEWEST_ONCE BT_MCS_PLAYING_ORDER_NEWEST_ONCE
|
||||
/*!< The tracks within a group are played from the newest first repeatedly. */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYING_ORDER_NEWEST_REPEAT BT_MCS_PLAYING_ORDER_NEWEST_REPEAT
|
||||
/*!< The tracks within a group are played in random order once. */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYING_ORDER_SHUFFLE_ONCE BT_MCS_PLAYING_ORDER_SHUFFLE_ONCE
|
||||
/*!< The tracks within a group are played in random order repeatedly. */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYING_ORDER_SHUFFLE_REPEAT BT_MCS_PLAYING_ORDER_SHUFFLE_REPEAT
|
||||
|
||||
/*!< The current track is invalid, and no track has been selected. */
|
||||
#define ESP_BLE_AUDIO_MCS_MEDIA_STATE_INACTIVE BT_MCS_MEDIA_STATE_INACTIVE
|
||||
/*!< The media player is playing the current track. */
|
||||
#define ESP_BLE_AUDIO_MCS_MEDIA_STATE_PLAYING BT_MCS_MEDIA_STATE_PLAYING
|
||||
/*!< The current track is paused. The media player has a current track, but it is not being played */
|
||||
#define ESP_BLE_AUDIO_MCS_MEDIA_STATE_PAUSED BT_MCS_MEDIA_STATE_PAUSED
|
||||
/*!< The current track is fast forwarding or fast rewinding. */
|
||||
#define ESP_BLE_AUDIO_MCS_MEDIA_STATE_SEEKING BT_MCS_MEDIA_STATE_SEEKING
|
||||
|
||||
/*!< Start playing the current track. */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_PLAY BT_MCS_OPC_PLAY
|
||||
/*!< Pause playing the current track. */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_PAUSE BT_MCS_OPC_PAUSE
|
||||
/*!< Fast rewind the current track. */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_FAST_REWIND BT_MCS_OPC_FAST_REWIND
|
||||
/*!< Fast forward the current track. */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_FAST_FORWARD BT_MCS_OPC_FAST_FORWARD
|
||||
/**
|
||||
* Stop current activity and return to the paused state and set
|
||||
* the current track position to the start of the current track.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_STOP BT_MCS_OPC_STOP
|
||||
|
||||
/*!< Set a new current track position relative to the current track position. */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_MOVE_RELATIVE BT_MCS_OPC_MOVE_RELATIVE
|
||||
|
||||
/**
|
||||
* Set the current track position to the starting position of
|
||||
* the previous segment of the current track.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_PREV_SEGMENT BT_MCS_OPC_PREV_SEGMENT
|
||||
/**
|
||||
* Set the current track position to the starting position of
|
||||
* the next segment of the current track.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_NEXT_SEGMENT BT_MCS_OPC_NEXT_SEGMENT
|
||||
/**
|
||||
* Set the current track position to the starting position of
|
||||
* the first segment of the current track.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_FIRST_SEGMENT BT_MCS_OPC_FIRST_SEGMENT
|
||||
/**
|
||||
* Set the current track position to the starting position of
|
||||
* the last segment of the current track.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_LAST_SEGMENT BT_MCS_OPC_LAST_SEGMENT
|
||||
/**
|
||||
* Set the current track position to the starting position of
|
||||
* the nth segment of the current track.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_GOTO_SEGMENT BT_MCS_OPC_GOTO_SEGMENT
|
||||
|
||||
/*!< Set the current track to the previous track based on the playing order. */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_PREV_TRACK BT_MCS_OPC_PREV_TRACK
|
||||
/*!< Set the current track to the next track based on the playing order. */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_NEXT_TRACK BT_MCS_OPC_NEXT_TRACK
|
||||
/*!< Set the current track to the first track based on the playing order. */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_FIRST_TRACK BT_MCS_OPC_FIRST_TRACK
|
||||
/*!< Set the current track to the last track based on the playing order. */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_LAST_TRACK BT_MCS_OPC_LAST_TRACK
|
||||
/*!< Set the current track to the nth track based on the playing order. */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_GOTO_TRACK BT_MCS_OPC_GOTO_TRACK
|
||||
|
||||
/*!< Set the current group to the previous group in the sequence of groups. */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_PREV_GROUP BT_MCS_OPC_PREV_GROUP
|
||||
/*!< Set the current group to the next group in the sequence of groups. */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_NEXT_GROUP BT_MCS_OPC_NEXT_GROUP
|
||||
/*!< Set the current group to the first group in the sequence of groups. */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_FIRST_GROUP BT_MCS_OPC_FIRST_GROUP
|
||||
/*!< Set the current group to the last group in the sequence of groups. */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_LAST_GROUP BT_MCS_OPC_LAST_GROUP
|
||||
/*!< Set the current group to the nth group in the sequence of groups. */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_GOTO_GROUP BT_MCS_OPC_GOTO_GROUP
|
||||
|
||||
/*!< Media control point supported opcodes length */
|
||||
#define ESP_BLE_AUDIO_MCS_OPCODES_SUPPORTED_LEN BT_MCS_OPCODES_SUPPORTED_LEN
|
||||
|
||||
/*!< Support the Play opcode */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_SUP_PLAY BT_MCS_OPC_SUP_PLAY
|
||||
/*!< Support the Pause opcode */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_SUP_PAUSE BT_MCS_OPC_SUP_PAUSE
|
||||
/*!< Support the Fast Rewind opcode */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_SUP_FAST_REWIND BT_MCS_OPC_SUP_FAST_REWIND
|
||||
/*!< Support the Fast Forward opcode */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_SUP_FAST_FORWARD BT_MCS_OPC_SUP_FAST_FORWARD
|
||||
/*!< Support the Stop opcode */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_SUP_STOP BT_MCS_OPC_SUP_STOP
|
||||
/*!< Support the Move Relative opcode */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_SUP_MOVE_RELATIVE BT_MCS_OPC_SUP_MOVE_RELATIVE
|
||||
/*!< Support the Previous Segment opcode */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_SUP_PREV_SEGMENT BT_MCS_OPC_SUP_PREV_SEGMENT
|
||||
/*!< Support the Next Segment opcode */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_SUP_NEXT_SEGMENT BT_MCS_OPC_SUP_NEXT_SEGMENT
|
||||
/*!< Support the First Segment opcode */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_SUP_FIRST_SEGMENT BT_MCS_OPC_SUP_FIRST_SEGMENT
|
||||
/*!< Support the Last Segment opcode */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_SUP_LAST_SEGMENT BT_MCS_OPC_SUP_LAST_SEGMENT
|
||||
/*!< Support the Goto Segment opcode */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_SUP_GOTO_SEGMENT BT_MCS_OPC_SUP_GOTO_SEGMENT
|
||||
|
||||
/*!< Support the Previous Track opcode */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_SUP_PREV_TRACK BT_MCS_OPC_SUP_PREV_TRACK
|
||||
/*!< Support the Next Track opcode */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_SUP_NEXT_TRACK BT_MCS_OPC_SUP_NEXT_TRACK
|
||||
/*!< Support the First Track opcode */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_SUP_FIRST_TRACK BT_MCS_OPC_SUP_FIRST_TRACK
|
||||
/*!< Support the Last Track opcode */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_SUP_LAST_TRACK BT_MCS_OPC_SUP_LAST_TRACK
|
||||
/*!< Support the Goto Track opcode */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_SUP_GOTO_TRACK BT_MCS_OPC_SUP_GOTO_TRACK
|
||||
|
||||
/*!< Support the Previous Group opcode */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_SUP_PREV_GROUP BT_MCS_OPC_SUP_PREV_GROUP
|
||||
/*!< Support the Next Group opcode */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_SUP_NEXT_GROUP BT_MCS_OPC_SUP_NEXT_GROUP
|
||||
/*!< Support the First Group opcode */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_SUP_FIRST_GROUP BT_MCS_OPC_SUP_FIRST_GROUP
|
||||
/*!< Support the Last Group opcode */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_SUP_LAST_GROUP BT_MCS_OPC_SUP_LAST_GROUP
|
||||
/*!< Support the Goto Group opcode */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_SUP_GOTO_GROUP BT_MCS_OPC_SUP_GOTO_GROUP
|
||||
|
||||
/** Action requested by the opcode write was completed successfully. */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_NTF_SUCCESS BT_MCS_OPC_NTF_SUCCESS
|
||||
/** An invalid or unsupported opcode was used for the Media Control Point write. */
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_NTF_NOT_SUPPORTED BT_MCS_OPC_NTF_NOT_SUPPORTED
|
||||
/**
|
||||
* The Media Player State characteristic value is Inactive when the opcode is
|
||||
* received or the result of the requested action of the opcode results in the
|
||||
* Media Player State characteristic being set to Inactive.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_NTF_PLAYER_INACTIVE BT_MCS_OPC_NTF_PLAYER_INACTIVE
|
||||
/**
|
||||
* The requested action of any Media Control Point write cannot be completed
|
||||
* successfully because of a condition within the player.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_MCS_OPC_NTF_CANNOT_BE_COMPLETED BT_MCS_OPC_NTF_CANNOT_BE_COMPLETED
|
||||
|
||||
/*!< Search for Track Name */
|
||||
#define ESP_BLE_AUDIO_MCS_SEARCH_TYPE_TRACK_NAME BT_MCS_SEARCH_TYPE_TRACK_NAME
|
||||
/*!< Search for Artist Name */
|
||||
#define ESP_BLE_AUDIO_MCS_SEARCH_TYPE_ARTIST_NAME BT_MCS_SEARCH_TYPE_ARTIST_NAME
|
||||
/*!< Search for Album Name */
|
||||
#define ESP_BLE_AUDIO_MCS_SEARCH_TYPE_ALBUM_NAME BT_MCS_SEARCH_TYPE_ALBUM_NAME
|
||||
/*!< Search for Group Name */
|
||||
#define ESP_BLE_AUDIO_MCS_SEARCH_TYPE_GROUP_NAME BT_MCS_SEARCH_TYPE_GROUP_NAME
|
||||
/*!< Search for Earliest Year */
|
||||
#define ESP_BLE_AUDIO_MCS_SEARCH_TYPE_EARLIEST_YEAR BT_MCS_SEARCH_TYPE_EARLIEST_YEAR
|
||||
/*!< Search for Latest Year */
|
||||
#define ESP_BLE_AUDIO_MCS_SEARCH_TYPE_LATEST_YEAR BT_MCS_SEARCH_TYPE_LATEST_YEAR
|
||||
/*!< Search for Genre */
|
||||
#define ESP_BLE_AUDIO_MCS_SEARCH_TYPE_GENRE BT_MCS_SEARCH_TYPE_GENRE
|
||||
/*!< Search for Tracks only */
|
||||
#define ESP_BLE_AUDIO_MCS_SEARCH_TYPE_ONLY_TRACKS BT_MCS_SEARCH_TYPE_ONLY_TRACKS
|
||||
/*!< Search for Groups only */
|
||||
#define ESP_BLE_AUDIO_MCS_SEARCH_TYPE_ONLY_GROUPS BT_MCS_SEARCH_TYPE_ONLY_GROUPS
|
||||
|
||||
/*!< Search control point minimum length */
|
||||
#define ESP_BLE_AUDIO_SEARCH_LEN_MIN SEARCH_LEN_MIN
|
||||
/*!< Search control point maximum length */
|
||||
#define ESP_BLE_AUDIO_SEARCH_LEN_MAX SEARCH_LEN_MAX
|
||||
|
||||
/*!< Search control point item (SCI) minimum length */
|
||||
#define ESP_BLE_AUDIO_SEARCH_SCI_LEN_MIN SEARCH_SCI_LEN_MIN
|
||||
|
||||
/*!< Search parameters maximum length */
|
||||
#define ESP_BLE_AUDIO_SEARCH_PARAM_MAX SEARCH_PARAM_MAX
|
||||
|
||||
/*!< Search request was accepted; search has started. */
|
||||
#define ESP_BLE_AUDIO_MCS_SCP_NTF_SUCCESS BT_MCS_SCP_NTF_SUCCESS
|
||||
/*!< Search request was invalid; no search started. */
|
||||
#define ESP_BLE_AUDIO_MCS_SCP_NTF_FAILURE BT_MCS_SCP_NTF_FAILURE
|
||||
|
||||
/*!< Group object type is track */
|
||||
#define ESP_BLE_AUDIO_MCS_GROUP_OBJECT_TRACK_TYPE BT_MCS_GROUP_OBJECT_TRACK_TYPE
|
||||
/*!< Group object type is group */
|
||||
#define ESP_BLE_AUDIO_MCS_GROUP_OBJECT_GROUP_TYPE BT_MCS_GROUP_OBJECT_GROUP_TYPE
|
||||
|
||||
/*!< A single track is played once; there is no next track. */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYING_ORDERS_SUPPORTED_SINGLE_ONCE BT_MCS_PLAYING_ORDERS_SUPPORTED_SINGLE_ONCE
|
||||
/*!< A single track is played repeatedly; the next track is the current track. */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYING_ORDERS_SUPPORTED_SINGLE_REPEAT BT_MCS_PLAYING_ORDERS_SUPPORTED_SINGLE_REPEAT
|
||||
/*!< The tracks within a group are played once in track order. */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYING_ORDERS_SUPPORTED_INORDER_ONCE BT_MCS_PLAYING_ORDERS_SUPPORTED_INORDER_ONCE
|
||||
/*!< The tracks within a group are played in track order repeatedly. */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYING_ORDERS_SUPPORTED_INORDER_REPEAT BT_MCS_PLAYING_ORDERS_SUPPORTED_INORDER_REPEAT
|
||||
/*!< The tracks within a group are played once only from the oldest first. */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYING_ORDERS_SUPPORTED_OLDEST_ONCE BT_MCS_PLAYING_ORDERS_SUPPORTED_OLDEST_ONCE
|
||||
/*!< The tracks within a group are played from the oldest first repeatedly. */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYING_ORDERS_SUPPORTED_OLDEST_REPEAT BT_MCS_PLAYING_ORDERS_SUPPORTED_OLDEST_REPEAT
|
||||
/*!< The tracks within a group are played once only from the newest first. */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYING_ORDERS_SUPPORTED_NEWEST_ONCE BT_MCS_PLAYING_ORDERS_SUPPORTED_NEWEST_ONCE
|
||||
/*!< The tracks within a group are played from the newest first repeatedly. */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYING_ORDERS_SUPPORTED_NEWEST_REPEAT BT_MCS_PLAYING_ORDERS_SUPPORTED_NEWEST_REPEAT
|
||||
/*!< The tracks within a group are played in random order once. */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYING_ORDERS_SUPPORTED_SHUFFLE_ONCE BT_MCS_PLAYING_ORDERS_SUPPORTED_SHUFFLE_ONCE
|
||||
/*!< The tracks within a group are played in random order repeatedly. */
|
||||
#define ESP_BLE_AUDIO_MCS_PLAYING_ORDERS_SUPPORTED_SHUFFLE_REPEAT BT_MCS_PLAYING_ORDERS_SUPPORTED_SHUFFLE_REPEAT
|
||||
|
||||
/**
|
||||
* Check if an Object ID is valid for MCS.
|
||||
* This differs from BT_OTS_VALID_OBJ_ID as MCS does not use the directory list object.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_MCS_VALID_OBJ_ID(id) \
|
||||
(IN_RANGE((id), BT_OTS_OBJ_ID_MIN, BT_OTS_OBJ_ID_MAX))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_BLE_AUDIO_MCS_DEFS_H_ */
|
||||
@@ -0,0 +1,743 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_BLE_AUDIO_MEDIA_PROXY_API_H_
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_API_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include <zephyr/bluetooth/services/ots.h>
|
||||
#include <zephyr/bluetooth/audio/media_proxy.h>
|
||||
|
||||
#include "common/init.h"
|
||||
#include "common/host.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!< Minimum playback speed, resulting in 25% speed */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYBACK_SPEED_MIN MEDIA_PROXY_PLAYBACK_SPEED_MIN
|
||||
/*!< Quarter playback speed, resulting in 25% speed */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYBACK_SPEED_QUARTER MEDIA_PROXY_PLAYBACK_SPEED_QUARTER
|
||||
/*!< Half playback speed, resulting in 50% speed */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYBACK_SPEED_HALF MEDIA_PROXY_PLAYBACK_SPEED_HALF
|
||||
/*!< Unity playback speed, resulting in 100% speed */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYBACK_SPEED_UNITY MEDIA_PROXY_PLAYBACK_SPEED_UNITY
|
||||
/*!< Double playback speed, resulting in 200% speed */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYBACK_SPEED_DOUBLE MEDIA_PROXY_PLAYBACK_SPEED_DOUBLE
|
||||
/*!< Max playback speed, resulting in 395.7% speed (nearly 400%) */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYBACK_SPEED_MAX MEDIA_PROXY_PLAYBACK_SPEED_MAX
|
||||
|
||||
/*!< The current track is invalid, and no track has been selected. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_STATE_INACTIVE MEDIA_PROXY_STATE_INACTIVE
|
||||
/*!< The media player is playing the current track. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_STATE_PLAYING MEDIA_PROXY_STATE_PLAYING
|
||||
/*!< The current track is paused. The media player has a current track, but it is not being played */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_STATE_PAUSED MEDIA_PROXY_STATE_PAUSED
|
||||
/*!< The current track is fast forwarding or fast rewinding. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_STATE_SEEKING MEDIA_PROXY_STATE_SEEKING
|
||||
/*!< Used internally as the last state value */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_STATE_LAST MEDIA_PROXY_STATE_LAST
|
||||
|
||||
/*!< Start playing the current track. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_PLAY MEDIA_PROXY_OP_PLAY
|
||||
/*!< Pause playing the current track. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_PAUSE MEDIA_PROXY_OP_PAUSE
|
||||
/*!< Fast rewind the current track. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_FAST_REWIND MEDIA_PROXY_OP_FAST_REWIND
|
||||
/*!< Fast forward the current track. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_FAST_FORWARD MEDIA_PROXY_OP_FAST_FORWARD
|
||||
/**
|
||||
* Stop current activity and return to the paused state and set
|
||||
* the current track position to the start of the current track.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_STOP MEDIA_PROXY_OP_STOP
|
||||
|
||||
/*!< Set a new current track position relative to the current track position. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_MOVE_RELATIVE MEDIA_PROXY_OP_MOVE_RELATIVE
|
||||
|
||||
/**
|
||||
* Set the current track position to the starting position of
|
||||
* the previous segment of the current track.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_PREV_SEGMENT MEDIA_PROXY_OP_PREV_SEGMENT
|
||||
/**
|
||||
* Set the current track position to the starting position of
|
||||
* the next segment of the current track.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_NEXT_SEGMENT MEDIA_PROXY_OP_NEXT_SEGMENT
|
||||
/**
|
||||
* Set the current track position to the starting position of
|
||||
* the first segment of the current track.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_FIRST_SEGMENT MEDIA_PROXY_OP_FIRST_SEGMENT
|
||||
/**
|
||||
* Set the current track position to the starting position of
|
||||
* the last segment of the current track.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_LAST_SEGMENT MEDIA_PROXY_OP_LAST_SEGMENT
|
||||
/**
|
||||
* Set the current track position to the starting position of
|
||||
* the nth segment of the current track.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_GOTO_SEGMENT MEDIA_PROXY_OP_GOTO_SEGMENT
|
||||
|
||||
/*!< Set the current track to the previous track based on the playing order. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_PREV_TRACK MEDIA_PROXY_OP_PREV_TRACK
|
||||
/*!< Set the current track to the next track based on the playing order. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_NEXT_TRACK MEDIA_PROXY_OP_NEXT_TRACK
|
||||
/*!< Set the current track to the first track based on the playing order. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_FIRST_TRACK MEDIA_PROXY_OP_FIRST_TRACK
|
||||
/*!< Set the current track to the last track based on the playing order. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_LAST_TRACK MEDIA_PROXY_OP_LAST_TRACK
|
||||
/*!< Set the current track to the nth track based on the playing order. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_GOTO_TRACK MEDIA_PROXY_OP_GOTO_TRACK
|
||||
|
||||
/*!< Set the current group to the previous group in the sequence of groups. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_PREV_GROUP MEDIA_PROXY_OP_PREV_GROUP
|
||||
/*!< Set the current group to the next group in the sequence of groups. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_NEXT_GROUP MEDIA_PROXY_OP_NEXT_GROUP
|
||||
/*!< Set the current group to the first group in the sequence of groups. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_FIRST_GROUP MEDIA_PROXY_OP_FIRST_GROUP
|
||||
/*!< Set the current group to the last group in the sequence of groups. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_LAST_GROUP MEDIA_PROXY_OP_LAST_GROUP
|
||||
/*!< Set the current group to the nth group in the sequence of groups. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_GOTO_GROUP MEDIA_PROXY_OP_GOTO_GROUP
|
||||
|
||||
/*!< Media player supported opcodes length */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OPCODES_SUPPORTED_LEN MEDIA_PROXY_OPCODES_SUPPORTED_LEN
|
||||
|
||||
/*!< Support the Play opcode */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_SUP_PLAY MEDIA_PROXY_OP_SUP_PLAY
|
||||
/*!< Support the Pause opcode */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_SUP_PAUSE MEDIA_PROXY_OP_SUP_PAUSE
|
||||
/*!< Support the Fast Rewind opcode */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_SUP_FAST_REWIND MEDIA_PROXY_OP_SUP_FAST_REWIND
|
||||
/*!< Support the Fast Forward opcode */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_SUP_FAST_FORWARD MEDIA_PROXY_OP_SUP_FAST_FORWARD
|
||||
/*!< Support the Stop opcode */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_SUP_STOP MEDIA_PROXY_OP_SUP_STOP
|
||||
|
||||
/*!< Support the Move Relative opcode */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_SUP_MOVE_RELATIVE MEDIA_PROXY_OP_SUP_MOVE_RELATIVE
|
||||
|
||||
/*!< Support the Previous Segment opcode */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_SUP_PREV_SEGMENT MEDIA_PROXY_OP_SUP_PREV_SEGMENT
|
||||
/*!< Support the Next Segment opcode */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_SUP_NEXT_SEGMENT MEDIA_PROXY_OP_SUP_NEXT_SEGMENT
|
||||
/*!< Support the First Segment opcode */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_SUP_FIRST_SEGMENT MEDIA_PROXY_OP_SUP_FIRST_SEGMENT
|
||||
/*!< Support the Last Segment opcode */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_SUP_LAST_SEGMENT MEDIA_PROXY_OP_SUP_LAST_SEGMENT
|
||||
/*!< Support the Goto Segment opcode */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_SUP_GOTO_SEGMENT MEDIA_PROXY_OP_SUP_GOTO_SEGMENT
|
||||
|
||||
/*!< Support the Previous Track opcode */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_SUP_PREV_TRACK MEDIA_PROXY_OP_SUP_PREV_TRACK
|
||||
/*!< Support the Next Track opcode */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_SUP_NEXT_TRACK MEDIA_PROXY_OP_SUP_NEXT_TRACK
|
||||
/*!< Support the First Track opcode */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_SUP_FIRST_TRACK MEDIA_PROXY_OP_SUP_FIRST_TRACK
|
||||
/*!< Support the Last Track opcode */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_SUP_LAST_TRACK MEDIA_PROXY_OP_SUP_LAST_TRACK
|
||||
/*!< Support the Goto Track opcode */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_SUP_GOTO_TRACK MEDIA_PROXY_OP_SUP_GOTO_TRACK
|
||||
|
||||
/*!< Support the Previous Group opcode */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_SUP_PREV_GROUP MEDIA_PROXY_OP_SUP_PREV_GROUP
|
||||
/*!< Support the Next Group opcode */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_SUP_NEXT_GROUP MEDIA_PROXY_OP_SUP_NEXT_GROUP
|
||||
/*!< Support the First Group opcode */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_SUP_FIRST_GROUP MEDIA_PROXY_OP_SUP_FIRST_GROUP
|
||||
/*!< Support the Last Group opcode */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_SUP_LAST_GROUP MEDIA_PROXY_OP_SUP_LAST_GROUP
|
||||
/*!< Support the Goto Group opcode */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_OP_SUP_GOTO_GROUP MEDIA_PROXY_OP_SUP_GOTO_GROUP
|
||||
|
||||
/*!< Action requested by the opcode write was completed successfully. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_CMD_SUCCESS MEDIA_PROXY_CMD_SUCCESS
|
||||
/*!< An invalid or unsupported opcode was used for the Media Control Point write. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_CMD_NOT_SUPPORTED MEDIA_PROXY_CMD_NOT_SUPPORTED
|
||||
/**
|
||||
* The Media Player State characteristic value is Inactive when the opcode
|
||||
* is received or the result of the requested action of the opcode results
|
||||
* in the Media Player State characteristic being set to Inactive.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_CMD_PLAYER_INACTIVE MEDIA_PROXY_CMD_PLAYER_INACTIVE
|
||||
/**
|
||||
* The requested action of any Media Control Point write cannot be completed
|
||||
* successfully because of a condition within the player.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_CMD_CANNOT_BE_COMPLETED MEDIA_PROXY_CMD_CANNOT_BE_COMPLETED
|
||||
|
||||
/*!< Search for Track Name */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_SEARCH_TYPE_TRACK_NAME MEDIA_PROXY_SEARCH_TYPE_TRACK_NAME
|
||||
/*!< Search for Artist Name */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_SEARCH_TYPE_ARTIST_NAME MEDIA_PROXY_SEARCH_TYPE_ARTIST_NAME
|
||||
/*!< Search for Album Name */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_SEARCH_TYPE_ALBUM_NAME MEDIA_PROXY_SEARCH_TYPE_ALBUM_NAME
|
||||
/*!< Search for Group Name */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_SEARCH_TYPE_GROUP_NAME MEDIA_PROXY_SEARCH_TYPE_GROUP_NAME
|
||||
/*!< Search for Earliest Year */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_SEARCH_TYPE_EARLIEST_YEAR MEDIA_PROXY_SEARCH_TYPE_EARLIEST_YEAR
|
||||
/*!< Search for Latest Year */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_SEARCH_TYPE_LATEST_YEAR MEDIA_PROXY_SEARCH_TYPE_LATEST_YEAR
|
||||
/*!< Search for Genre */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_SEARCH_TYPE_GENRE MEDIA_PROXY_SEARCH_TYPE_GENRE
|
||||
/*!< Search for Tracks only */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_SEARCH_TYPE_ONLY_TRACKS MEDIA_PROXY_SEARCH_TYPE_ONLY_TRACKS
|
||||
/*!< Search for Groups only */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_SEARCH_TYPE_ONLY_GROUPS MEDIA_PROXY_SEARCH_TYPE_ONLY_GROUPS
|
||||
|
||||
/*!< Search request was accepted; search has started. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_SEARCH_SUCCESS MEDIA_PROXY_SEARCH_SUCCESS
|
||||
/*!< Search request was invalid; no search started. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_SEARCH_FAILURE MEDIA_PROXY_SEARCH_FAILURE
|
||||
|
||||
/*!< Group object type is track */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_GROUP_OBJECT_TRACK_TYPE MEDIA_PROXY_GROUP_OBJECT_TRACK_TYPE
|
||||
/*!< Group object type is group */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_GROUP_OBJECT_GROUP_TYPE MEDIA_PROXY_GROUP_OBJECT_GROUP_TYPE
|
||||
|
||||
/*!< Maximum seeking speed - Can be negated */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_SEEKING_SPEED_FACTOR_MAX MEDIA_PROXY_SEEKING_SPEED_FACTOR_MAX
|
||||
/*!< Minimum seeking speed - Can be negated */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_SEEKING_SPEED_FACTOR_MIN MEDIA_PROXY_SEEKING_SPEED_FACTOR_MIN
|
||||
/*!< No seeking */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_SEEKING_SPEED_FACTOR_ZERO MEDIA_PROXY_SEEKING_SPEED_FACTOR_ZERO
|
||||
|
||||
/*!< A single track is played once; there is no next track. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYING_ORDER_SINGLE_ONCE MEDIA_PROXY_PLAYING_ORDER_SINGLE_ONCE
|
||||
/*!< A single track is played repeatedly; the next track is the current track. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYING_ORDER_SINGLE_REPEAT MEDIA_PROXY_PLAYING_ORDER_SINGLE_REPEAT
|
||||
/*!< The tracks within a group are played once in track order. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYING_ORDER_INORDER_ONCE MEDIA_PROXY_PLAYING_ORDER_INORDER_ONCE
|
||||
/*!< The tracks within a group are played in track order repeatedly. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYING_ORDER_INORDER_REPEAT MEDIA_PROXY_PLAYING_ORDER_INORDER_REPEAT
|
||||
/*!< The tracks within a group are played once only from the oldest first. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYING_ORDER_OLDEST_ONCE MEDIA_PROXY_PLAYING_ORDER_OLDEST_ONCE
|
||||
/*!< The tracks within a group are played from the oldest first repeatedly. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYING_ORDER_OLDEST_REPEAT MEDIA_PROXY_PLAYING_ORDER_OLDEST_REPEAT
|
||||
/*!< The tracks within a group are played once only from the newest first. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYING_ORDER_NEWEST_ONCE MEDIA_PROXY_PLAYING_ORDER_NEWEST_ONCE
|
||||
/*!< The tracks within a group are played from the newest first repeatedly. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYING_ORDER_NEWEST_REPEAT MEDIA_PROXY_PLAYING_ORDER_NEWEST_REPEAT
|
||||
/*!< The tracks within a group are played in random order once. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYING_ORDER_SHUFFLE_ONCE MEDIA_PROXY_PLAYING_ORDER_SHUFFLE_ONCE
|
||||
/*!< The tracks within a group are played in random order repeatedly. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYING_ORDER_SHUFFLE_REPEAT MEDIA_PROXY_PLAYING_ORDER_SHUFFLE_REPEAT
|
||||
|
||||
/*!< A single track is played once; there is no next track. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYING_ORDERS_SUPPORTED_SINGLE_ONCE MEDIA_PROXY_PLAYING_ORDERS_SUPPORTED_SINGLE_ONCE
|
||||
/*!< A single track is played repeatedly; the next track is the current track. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYING_ORDERS_SUPPORTED_SINGLE_REPEAT MEDIA_PROXY_PLAYING_ORDERS_SUPPORTED_SINGLE_REPEAT
|
||||
/*!< The tracks within a group are played once in track order. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYING_ORDERS_SUPPORTED_INORDER_ONCE MEDIA_PROXY_PLAYING_ORDERS_SUPPORTED_INORDER_ONCE
|
||||
/*!< The tracks within a group are played in track order repeatedly. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYING_ORDERS_SUPPORTED_INORDER_REPEAT MEDIA_PROXY_PLAYING_ORDERS_SUPPORTED_INORDER_REPEAT
|
||||
/*!< The tracks within a group are played once only from the oldest first. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYING_ORDERS_SUPPORTED_OLDEST_ONCE MEDIA_PROXY_PLAYING_ORDERS_SUPPORTED_OLDEST_ONCE
|
||||
/*!< The tracks within a group are played from the oldest first repeatedly. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYING_ORDERS_SUPPORTED_OLDEST_REPEAT MEDIA_PROXY_PLAYING_ORDERS_SUPPORTED_OLDEST_REPEAT
|
||||
/*!< The tracks within a group are played once only from the newest first. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYING_ORDERS_SUPPORTED_NEWEST_ONCE MEDIA_PROXY_PLAYING_ORDERS_SUPPORTED_NEWEST_ONCE
|
||||
/*!< The tracks within a group are played from the newest first repeatedly. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYING_ORDERS_SUPPORTED_NEWEST_REPEAT MEDIA_PROXY_PLAYING_ORDERS_SUPPORTED_NEWEST_REPEAT
|
||||
/*!< The tracks within a group are played in random order once. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYING_ORDERS_SUPPORTED_SHUFFLE_ONCE MEDIA_PROXY_PLAYING_ORDERS_SUPPORTED_SHUFFLE_ONCE
|
||||
/*!< The tracks within a group are played in random order repeatedly. */
|
||||
#define ESP_BLE_AUDIO_MEDIA_PROXY_PLAYING_ORDERS_SUPPORTED_SHUFFLE_REPEAT MEDIA_PROXY_PLAYING_ORDERS_SUPPORTED_SHUFFLE_REPEAT
|
||||
|
||||
/** Media player command */
|
||||
typedef struct mpl_cmd esp_ble_audio_mpl_cmd_t;
|
||||
|
||||
/** Media command notification */
|
||||
typedef struct mpl_cmd_ntf esp_ble_audio_mpl_cmd_ntf_t;
|
||||
|
||||
/** Search control item */
|
||||
typedef struct mpl_sci esp_ble_audio_mpl_sci_t;
|
||||
|
||||
/** Search */
|
||||
typedef struct mpl_search esp_ble_audio_mpl_search_t;
|
||||
|
||||
/** Media player instance */
|
||||
typedef struct media_player esp_ble_audio_media_player_t;
|
||||
|
||||
/** Callbacks to a controller, from the media proxy */
|
||||
typedef struct media_proxy_ctrl_cbs esp_ble_audio_media_proxy_ctrl_cbs_t;
|
||||
|
||||
/** Available calls in a player, that the media proxy can call */
|
||||
typedef struct media_proxy_pl_calls esp_ble_audio_media_proxy_pl_calls_t;
|
||||
|
||||
/**
|
||||
* @brief Register a controller with the media_proxy.
|
||||
*
|
||||
* @param ctrl_cbs Callbacks to the controller.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_register(esp_ble_audio_media_proxy_ctrl_cbs_t *ctrl_cbs);
|
||||
|
||||
/**
|
||||
* @brief Discover a remote media player.
|
||||
*
|
||||
* Discover a remote media player instance.
|
||||
* The remote player instance will be discovered, and accessed, using Bluetooth,
|
||||
* via the media control client and a remote media control service.
|
||||
* This call will start a GATT discovery of the Media Control Service on the peer,
|
||||
* and setup handles and subscriptions.
|
||||
*
|
||||
* This shall be called once before any other actions can be executed for the
|
||||
* remote player. The remote player instance will be returned in the
|
||||
* discover_player() callback.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_discover_player(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Read Media Player Name.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_player_name(esp_ble_audio_media_player_t *player);
|
||||
|
||||
/**
|
||||
* @brief Read Icon Object ID.
|
||||
*
|
||||
* Get an ID (48 bit) that can be used to retrieve the Icon
|
||||
* Object from an Object Transfer Service.
|
||||
*
|
||||
* See the Media Control Service spec v1.0 sections 3.2 and
|
||||
* 4.1 for a description of the Icon Object.
|
||||
*
|
||||
* Requires Object Transfer Service
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_icon_id(esp_ble_audio_media_player_t *player);
|
||||
|
||||
/**
|
||||
* @brief Read Icon URL.
|
||||
*
|
||||
* Get a URL to the media player's icon.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_icon_url(esp_ble_audio_media_player_t *player);
|
||||
|
||||
/**
|
||||
* @brief Read Track Title.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_track_title(esp_ble_audio_media_player_t *player);
|
||||
|
||||
/**
|
||||
* @brief Read Track Duration.
|
||||
*
|
||||
* The duration of a track is measured in hundredths of a second.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_track_duration(esp_ble_audio_media_player_t *player);
|
||||
|
||||
/**
|
||||
* @brief Read Track Position.
|
||||
*
|
||||
* The position of the player (the playing position) is measured
|
||||
* in hundredths of a second from the beginning of the track.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_track_position(esp_ble_audio_media_player_t *player);
|
||||
|
||||
/**
|
||||
* @brief Set Track Position.
|
||||
*
|
||||
* Set the playing position of the media player in the current
|
||||
* track. The position is given in hundredths of a second,
|
||||
* from the beginning of the track of the track for positive
|
||||
* values, and (backwards) from the end of the track for
|
||||
* negative values.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
* @param position The track position to set.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_set_track_position(esp_ble_audio_media_player_t *player,
|
||||
int32_t position);
|
||||
|
||||
/**
|
||||
* @brief Get Playback Speed.
|
||||
*
|
||||
* The playback speed parameter is related to the actual
|
||||
* playback speed as follows:
|
||||
* actual playback speed = 2^(speed_parameter/64)
|
||||
*
|
||||
* A speed parameter of 0 corresponds to unity speed playback
|
||||
* (i.e. playback at "normal" speed). A speed parameter of
|
||||
* -128 corresponds to playback at one fourth of normal speed,
|
||||
* 127 corresponds to playback at almost four times the normal
|
||||
* speed.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_playback_speed(esp_ble_audio_media_player_t *player);
|
||||
|
||||
/**
|
||||
* @brief Set Playback Speed.
|
||||
*
|
||||
* See the get_playback_speed() function for an explanation of
|
||||
* the playback speed parameter.
|
||||
*
|
||||
* Note that the media player may not support all possible
|
||||
* values of the playback speed parameter. If the value given
|
||||
* is not supported, and is higher than the current value, the
|
||||
* player should set the playback speed to the next higher
|
||||
* supported value. (And correspondingly to the next lower
|
||||
* supported value for given values lower than the current
|
||||
* value.)
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
* @param speed The playback speed parameter to set.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_set_playback_speed(esp_ble_audio_media_player_t *player,
|
||||
int8_t speed);
|
||||
|
||||
/**
|
||||
* @brief Get Seeking Speed.
|
||||
*
|
||||
* The seeking speed gives the speed with which the player is
|
||||
* seeking. It is a factor, relative to real-time playback
|
||||
* speed - a factor four means seeking happens at four times
|
||||
* the real-time playback speed. Positive values are for
|
||||
* forward seeking, negative values for backwards seeking.
|
||||
*
|
||||
* The seeking speed is not settable - a non-zero seeking speed
|
||||
* is the result of "fast rewind" of "fast forward" commands.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_seeking_speed(esp_ble_audio_media_player_t *player);
|
||||
|
||||
/**
|
||||
* @brief Read Current Track Segments Object ID.
|
||||
*
|
||||
* Get an ID (48 bit) that can be used to retrieve the Current
|
||||
* Track Segments Object from an Object Transfer Service.
|
||||
*
|
||||
* See the Media Control Service spec v1.0 sections 3.10 and
|
||||
* 4.2 for a description of the Track Segments Object.
|
||||
*
|
||||
* Requires Object Transfer Service.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_track_segments_id(esp_ble_audio_media_player_t *player);
|
||||
|
||||
/**
|
||||
* @brief Read Current Track Object ID.
|
||||
*
|
||||
* Get an ID (48 bit) that can be used to retrieve the Current
|
||||
* Track Object from an Object Transfer Service.
|
||||
*
|
||||
* See the Media Control Service spec v1.0 sections 3.11 and
|
||||
* 4.3 for a description of the Current Track Object.
|
||||
*
|
||||
* Requires Object Transfer Service.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_current_track_id(esp_ble_audio_media_player_t *player);
|
||||
|
||||
/**
|
||||
* @brief Set Current Track Object ID.
|
||||
*
|
||||
* Change the player's current track to the track given by the ID.
|
||||
* (Behaves similarly to the goto track command.)
|
||||
*
|
||||
* Requires Object Transfer Service.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
* @param id The ID of a track object.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_set_current_track_id(esp_ble_audio_media_player_t *player,
|
||||
uint64_t id);
|
||||
|
||||
/**
|
||||
* @brief Read Next Track Object ID.
|
||||
*
|
||||
* Get an ID (48 bit) that can be used to retrieve the Next
|
||||
* Track Object from an Object Transfer Service.
|
||||
*
|
||||
* Requires Object Transfer Service.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_next_track_id(esp_ble_audio_media_player_t *player);
|
||||
|
||||
/**
|
||||
* @brief Set Next Track Object ID.
|
||||
*
|
||||
* Change the player's next track to the track given by the ID.
|
||||
*
|
||||
* Requires Object Transfer Service.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
* @param id The ID of a track object.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_set_next_track_id(esp_ble_audio_media_player_t *player,
|
||||
uint64_t id);
|
||||
|
||||
/**
|
||||
* @brief Read Parent Group Object ID.
|
||||
*
|
||||
* Get an ID (48 bit) that can be used to retrieve the Parent
|
||||
* Track Object from an Object Transfer Service.
|
||||
*
|
||||
* The parent group is the parent of the current group.
|
||||
*
|
||||
* See the Media Control Service spec v1.0 sections 3.14 and
|
||||
* 4.4 for a description of the Current Track Object.
|
||||
*
|
||||
* Requires Object Transfer Service.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_parent_group_id(esp_ble_audio_media_player_t *player);
|
||||
|
||||
/**
|
||||
* @brief Read Current Group Object ID.
|
||||
*
|
||||
* Get an ID (48 bit) that can be used to retrieve the Current
|
||||
* Track Object from an Object Transfer Service
|
||||
*
|
||||
* See the Media Control Service spec v1.0 sections 3.14 and
|
||||
* 4.4 for a description of the Current Group Object.
|
||||
*
|
||||
* Requires Object Transfer Service.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_current_group_id(esp_ble_audio_media_player_t *player);
|
||||
|
||||
/**
|
||||
* @brief Set Current Group Object ID.
|
||||
*
|
||||
* Change the player's current group to the group given by the
|
||||
* ID, and the current track to the first track in that group.
|
||||
*
|
||||
* Requires Object Transfer Service.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
* @param id The ID of a group object.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_set_current_group_id(esp_ble_audio_media_player_t *player,
|
||||
uint64_t id);
|
||||
|
||||
/**
|
||||
* @brief Read Playing Order.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_playing_order(esp_ble_audio_media_player_t *player);
|
||||
|
||||
/**
|
||||
* @brief Set Playing Order.
|
||||
*
|
||||
* Set the media player's playing order.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
* @param order The playing order to set.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_set_playing_order(esp_ble_audio_media_player_t *player,
|
||||
uint8_t order);
|
||||
|
||||
/**
|
||||
* @brief Read Playing Orders Supported.
|
||||
*
|
||||
* Read a bitmap containing the media player's supported playing orders.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_playing_orders_supported(esp_ble_audio_media_player_t *player);
|
||||
|
||||
/**
|
||||
* @brief Read Media State.
|
||||
*
|
||||
* Read the media player's state.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_media_state(esp_ble_audio_media_player_t *player);
|
||||
|
||||
/**
|
||||
* @brief Send Command.
|
||||
*
|
||||
* Send a command to the media player.
|
||||
* Commands may cause the media player to change its state.
|
||||
* May result in two callbacks - one for the actual sending of the command
|
||||
* to the player, one for the result of the command from the player.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
* @param command The command to send.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_send_command(esp_ble_audio_media_player_t *player,
|
||||
const esp_ble_audio_mpl_cmd_t *command);
|
||||
|
||||
/**
|
||||
* @brief Read Commands Supported.
|
||||
*
|
||||
* Read a bitmap containing the media player's supported command opcodes.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_commands_supported(esp_ble_audio_media_player_t *player);
|
||||
|
||||
/**
|
||||
* @brief Set Search.
|
||||
*
|
||||
* Write a search to the media player.
|
||||
* If the search is successful, the search results will be available as
|
||||
* a group object in the Object Transfer Service (OTS).
|
||||
*
|
||||
* May result in up to three callbacks:
|
||||
* - one for the actual sending of the search to the player;
|
||||
* - one for the result code for the search from the player;
|
||||
* - if the search is successful, one for the search results object ID
|
||||
* in the OTs.
|
||||
*
|
||||
* Requires Object Transfer Service.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
* @param search The search to write.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_send_search(esp_ble_audio_media_player_t *player,
|
||||
const esp_ble_audio_mpl_search_t *search);
|
||||
|
||||
/**
|
||||
* @brief Read Search Results Object ID.
|
||||
*
|
||||
* Get an ID (48 bit) that can be used to retrieve the Search
|
||||
* Results Object from an Object Transfer Service.
|
||||
*
|
||||
* The search results object is a group object.
|
||||
* The search results object only exists if a successful
|
||||
* search operation has been done.
|
||||
*
|
||||
* Requires Object Transfer Service.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_search_results_id(esp_ble_audio_media_player_t *player);
|
||||
|
||||
/**
|
||||
* @brief Read Content Control ID.
|
||||
*
|
||||
* The content control ID identifies a content control service
|
||||
* on a device, and links it to the corresponding audio stream.
|
||||
*
|
||||
* @param player Media player instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_ctrl_get_content_ctrl_id(esp_ble_audio_media_player_t *player);
|
||||
|
||||
/**
|
||||
* @brief Register a player with the media proxy.
|
||||
*
|
||||
* Register a player with the media proxy module, for use by media
|
||||
* controllers.
|
||||
*
|
||||
* The media proxy may call any non-NULL function pointers in the
|
||||
* supplied media_proxy_pl_calls structure.
|
||||
*
|
||||
* @param pl_calls Function pointers to the media player's calls.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_pl_register(esp_ble_audio_media_proxy_pl_calls_t *pl_calls);
|
||||
|
||||
/**
|
||||
* @brief Initialize player.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_media_proxy_pl_init(void);
|
||||
|
||||
/**
|
||||
* @brief Get the pointer of the Object Transfer Service used by the Media Control Service.
|
||||
*
|
||||
* @return Pointer to an OTS instance if found else NULL.
|
||||
*/
|
||||
struct bt_ots *esp_ble_audio_mcs_get_ots(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_BLE_AUDIO_MEDIA_PROXY_API_H_ */
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_BLE_AUDIO_MICP_API_H_
|
||||
#define ESP_BLE_AUDIO_MICP_API_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include <zephyr/bluetooth/audio/micp.h>
|
||||
|
||||
#include "common/init.h"
|
||||
#include "common/host.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!< The microphone state is unmuted */
|
||||
#define ESP_BLE_AUDIO_MICP_MUTE_UNMUTED BT_MICP_MUTE_UNMUTED
|
||||
/*!< The microphone state is muted */
|
||||
#define ESP_BLE_AUDIO_MICP_MUTE_MUTED BT_MICP_MUTE_MUTED
|
||||
/*!< The microphone state is disabled and cannot be muted or unmuted */
|
||||
#define ESP_BLE_AUDIO_MICP_MUTE_DISABLED BT_MICP_MUTE_DISABLED
|
||||
|
||||
/** Microphone Controller instance */
|
||||
typedef struct bt_micp_mic_ctlr esp_ble_audio_micp_mic_ctlr_t;
|
||||
|
||||
/** Struct to hold the Microphone Controller callbacks */
|
||||
typedef struct bt_micp_mic_ctlr_cb esp_ble_audio_micp_mic_ctlr_cb_t;
|
||||
|
||||
/** Struct to hold the Microphone Device callbacks */
|
||||
typedef struct bt_micp_mic_dev_cb esp_ble_audio_micp_mic_dev_cb_t;
|
||||
|
||||
/** Register parameters structure for Microphone Control Service */
|
||||
typedef struct bt_micp_mic_dev_register_param esp_ble_audio_micp_mic_dev_register_param_t;
|
||||
|
||||
/** Microphone Control Profile included services */
|
||||
typedef struct bt_micp_included esp_ble_audio_micp_included_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize the Microphone Control Profile Microphone Device.
|
||||
*
|
||||
* This will enable the Microphone Control Service instance and make it
|
||||
* discoverable by Microphone Controllers.
|
||||
*
|
||||
* @param param Pointer to an initialization structure.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_micp_mic_dev_register(esp_ble_audio_micp_mic_dev_register_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief Get Microphone Device included services.
|
||||
*
|
||||
* Returns a pointer to a struct that contains information about the
|
||||
* Microphone Device included Audio Input Control Service instances.
|
||||
*
|
||||
* @param included Pointer to store the result in.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_micp_mic_dev_included_get(esp_ble_audio_micp_included_t *included);
|
||||
|
||||
/**
|
||||
* @brief Unmute the Microphone Device.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_micp_mic_dev_unmute(void);
|
||||
|
||||
/**
|
||||
* @brief Mute the Microphone Device.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_micp_mic_dev_mute(void);
|
||||
|
||||
/**
|
||||
* @brief Disable the mute functionality on the Microphone Device.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_micp_mic_dev_mute_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Read the mute state on the Microphone Device.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_micp_mic_dev_mute_get(void);
|
||||
|
||||
/**
|
||||
* @brief Get Microphone Control Profile included services.
|
||||
*
|
||||
* Returns a pointer to a struct that contains information about the
|
||||
* Microphone Control Profile included services instances, such as
|
||||
* pointers to the Audio Input Control Service instances.
|
||||
*
|
||||
* @param mic_ctlr Microphone Controller instance pointer.
|
||||
* @param included Pointer to store the result in.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_micp_mic_ctlr_included_get(esp_ble_audio_micp_mic_ctlr_t *mic_ctlr,
|
||||
esp_ble_audio_micp_included_t *included);
|
||||
|
||||
/**
|
||||
* @brief Get the Microphone controller from a connection pointer.
|
||||
*
|
||||
* Only Microphone controllers that have been initiated can be retrieved.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return Pointer to a Microphone controller instance or NULL if not found.
|
||||
*/
|
||||
esp_ble_audio_micp_mic_ctlr_t *esp_ble_audio_micp_mic_ctlr_get_by_conn(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Discover Microphone Control Service.
|
||||
*
|
||||
* This will start a GATT discovery and setup handles and subscriptions.
|
||||
* This shall be called once before any other actions can be executed
|
||||
* for the peer device.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param mic_ctlr Valid remote instance object on success.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_micp_mic_ctlr_discover(uint16_t conn_handle,
|
||||
esp_ble_audio_micp_mic_ctlr_t **mic_ctlr);
|
||||
|
||||
/**
|
||||
* @brief Unmute a remote Microphone Device.
|
||||
*
|
||||
* @param mic_ctlr Microphone Controller instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_micp_mic_ctlr_unmute(esp_ble_audio_micp_mic_ctlr_t *mic_ctlr);
|
||||
|
||||
/**
|
||||
* @brief Mute a remote Microphone Device.
|
||||
*
|
||||
* @param mic_ctlr Microphone Controller instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_micp_mic_ctlr_mute(esp_ble_audio_micp_mic_ctlr_t *mic_ctlr);
|
||||
|
||||
/**
|
||||
* @brief Read the mute state of a remote Microphone Device.
|
||||
*
|
||||
* @param mic_ctlr Microphone Controller instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_micp_mic_ctlr_mute_get(esp_ble_audio_micp_mic_ctlr_t *mic_ctlr);
|
||||
|
||||
/**
|
||||
* @brief Registers the callbacks used by Microphone Controller.
|
||||
*
|
||||
* This can only be done as the client.
|
||||
*
|
||||
* @param cb The callback structure.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_micp_mic_ctlr_cb_register(esp_ble_audio_micp_mic_ctlr_cb_t *cb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_BLE_AUDIO_MICP_API_H_ */
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Intel Corporation
|
||||
* SPDX-FileCopyrightText: 2021-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_BLE_AUDIO_PACS_API_H_
|
||||
#define ESP_BLE_AUDIO_PACS_API_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include <zephyr/bluetooth/audio/pacs.h>
|
||||
|
||||
#include "common/init.h"
|
||||
#include "common/host.h"
|
||||
|
||||
#include "esp_ble_audio_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Structure for registering PACS */
|
||||
typedef struct bt_pacs_register_param esp_ble_audio_pacs_register_param_t;
|
||||
|
||||
/** Published Audio Capability structure. */
|
||||
typedef struct bt_pacs_cap esp_ble_audio_pacs_cap_t;
|
||||
|
||||
/**
|
||||
* @brief Register the Published Audio Capability Service instance.
|
||||
*
|
||||
* @param param PACS register parameters.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_pacs_register(const esp_ble_audio_pacs_register_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief Unregister the Published Audio Capability Service instance.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_pacs_unregister(void);
|
||||
|
||||
/**
|
||||
* @brief Register Published Audio Capability.
|
||||
*
|
||||
* Register Audio Local Capability.
|
||||
*
|
||||
* @param dir Direction of the endpoint to register capability for.
|
||||
* @param cap Capability structure.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_pacs_cap_register(esp_ble_audio_dir_t dir,
|
||||
esp_ble_audio_pacs_cap_t *cap);
|
||||
|
||||
/**
|
||||
* @brief Unregister Published Audio Capability.
|
||||
*
|
||||
* Unregister Audio Local Capability.
|
||||
*
|
||||
* @param dir Direction of the endpoint to unregister capability for.
|
||||
* @param cap Capability structure.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_pacs_cap_unregister(esp_ble_audio_dir_t dir,
|
||||
esp_ble_audio_pacs_cap_t *cap);
|
||||
|
||||
/**
|
||||
* @brief Set the location for an endpoint type.
|
||||
*
|
||||
* @param dir Direction of the endpoints to change location for.
|
||||
* @param location The location to be set.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_pacs_set_location(esp_ble_audio_dir_t dir,
|
||||
esp_ble_audio_location_t location);
|
||||
|
||||
/**
|
||||
* @brief Set the available contexts for an endpoint type.
|
||||
*
|
||||
* @param dir Direction of the endpoints to change available contexts for.
|
||||
* @param contexts The contexts to be set.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_pacs_set_available_contexts(esp_ble_audio_dir_t dir,
|
||||
esp_ble_audio_context_t contexts);
|
||||
|
||||
/**
|
||||
* @brief Get the available contexts for an endpoint type.
|
||||
*
|
||||
* @param dir Direction of the endpoints to get contexts for.
|
||||
*
|
||||
* @return Bitmask of available contexts.
|
||||
*/
|
||||
esp_ble_audio_context_t esp_ble_audio_pacs_get_available_contexts(esp_ble_audio_dir_t dir);
|
||||
|
||||
/**
|
||||
* @brief Set the available contexts for a given connection.
|
||||
*
|
||||
* This function sets the available contexts value for a given connection.
|
||||
* The Available Context Value is reset to default on ACL disconnection.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param dir Direction of the endpoints to change available contexts for.
|
||||
* @param contexts The contexts to be set or NULL to reset to default.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_pacs_conn_set_available_contexts_for_conn(uint16_t conn_handle,
|
||||
esp_ble_audio_dir_t dir,
|
||||
esp_ble_audio_context_t *contexts);
|
||||
|
||||
/**
|
||||
* @brief Get the available contexts for a given connection.
|
||||
*
|
||||
* This server function returns the available contexts value for a given connection.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param dir Direction of the endpoints to get contexts for.
|
||||
*
|
||||
* @return Bitmask of available contexts.
|
||||
*/
|
||||
esp_ble_audio_context_t esp_ble_audio_pacs_get_available_contexts_for_conn(uint16_t conn_handle,
|
||||
esp_ble_audio_dir_t dir);
|
||||
|
||||
/**
|
||||
* @brief Set the supported contexts for an endpoint type.
|
||||
*
|
||||
* @param dir Direction of the endpoints to change available contexts for.
|
||||
* @param contexts The contexts to be set.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_pacs_set_supported_contexts(esp_ble_audio_dir_t dir,
|
||||
esp_ble_audio_context_t contexts);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_BLE_AUDIO_PACS_API_H_ */
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 NXP
|
||||
* SPDX-FileCopyrightText: 2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_BLE_AUDIO_PBP_API_H_
|
||||
#define ESP_BLE_AUDIO_PBP_API_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include <zephyr/bluetooth/audio/pbp.h>
|
||||
|
||||
#include "common/init.h"
|
||||
#include "common/host.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Minimum size of the Public Broadcast Announcement */
|
||||
#define ESP_BLE_AUDIO_PBP_MIN_PBA_SIZE BT_PBP_MIN_PBA_SIZE
|
||||
|
||||
/*!< Broadcast Streams encryption status */
|
||||
#define ESP_BLE_AUDIO_PBP_ANNOUNCEMENT_FEATURE_ENCRYPTION BT_PBP_ANNOUNCEMENT_FEATURE_ENCRYPTION
|
||||
/*!< Standard Quality Public Broadcast Audio configuration */
|
||||
#define ESP_BLE_AUDIO_PBP_ANNOUNCEMENT_FEATURE_STANDARD_QUALITY BT_PBP_ANNOUNCEMENT_FEATURE_STANDARD_QUALITY
|
||||
/*!< High Quality Public Broadcast Audio configuration */
|
||||
#define ESP_BLE_AUDIO_PBP_ANNOUNCEMENT_FEATURE_HIGH_QUALITY BT_PBP_ANNOUNCEMENT_FEATURE_HIGH_QUALITY
|
||||
/** Public Broadcast Announcement features */
|
||||
typedef enum bt_pbp_announcement_feature esp_ble_audio_pbp_announcement_feature_t;
|
||||
|
||||
/**
|
||||
* @brief Creates a Public Broadcast Announcement based on the information received
|
||||
* in the features parameter.
|
||||
*
|
||||
* @param meta Metadata to be included in the advertising data.
|
||||
* @param meta_len Size of the metadata fields to be included in the advertising data.
|
||||
* @param features Public Broadcast Announcement features.
|
||||
* @param pba_data_buf Pointer to store the PBA advertising data. Buffer size needs to be
|
||||
* meta_len + ESP_BLE_AUDIO_PBP_MIN_PBA_SIZE.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_pbp_get_announcement(const uint8_t meta[], size_t meta_len,
|
||||
esp_ble_audio_pbp_announcement_feature_t features,
|
||||
struct net_buf_simple *pba_data_buf);
|
||||
|
||||
/**
|
||||
* @brief Parses the received advertising data corresponding to a Public Broadcast
|
||||
* Announcement.
|
||||
* Returns the advertised Public Broadcast Announcement features and metadata.
|
||||
*
|
||||
* @param data_type Type of advertising data to be checked.
|
||||
* @param data Pointer of advertising data to be checked.
|
||||
* @param data_len Length of advertising data to be checked.
|
||||
* @param features Pointer to public broadcast source features to store the parsed features in.
|
||||
* @param meta Pointer to the metadata present in the advertising data.
|
||||
* @param meta_len Size of the metadata fields to be included in the advertising data.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_pbp_parse_announcement(uint8_t data_type, const uint8_t *data, uint8_t data_len,
|
||||
esp_ble_audio_pbp_announcement_feature_t *features,
|
||||
uint8_t **meta, uint8_t *meta_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_BLE_AUDIO_PBP_API_H_ */
|
||||
@@ -0,0 +1,635 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Bose Corporation
|
||||
* SPDX-FileCopyrightText: 2021 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_BLE_AUDIO_TBS_API_H_
|
||||
#define ESP_BLE_AUDIO_TBS_API_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include <zephyr/bluetooth/audio/tbs.h>
|
||||
|
||||
#include "common/init.h"
|
||||
#include "common/host.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The GTBS index denotes whenever a callback is from a Generic Telephone
|
||||
* Bearer Service (GTBS) instance, or whenever the client should perform
|
||||
* on action on the GTBS instance of the server, rather than any of the
|
||||
* specific Telephone Bearer Service instances.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_TBS_GTBS_INDEX BT_TBS_GTBS_INDEX
|
||||
|
||||
/*!< A remote party is calling (incoming call). */
|
||||
#define ESP_BLE_AUDIO_TBS_CALL_STATE_INCOMING BT_TBS_CALL_STATE_INCOMING
|
||||
/**
|
||||
* The process to call the remote party has started on the server, but the
|
||||
* remote party is not being alerted (outgoing call).
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_TBS_CALL_STATE_DIALING BT_TBS_CALL_STATE_DIALING
|
||||
/*!< A remote party is being alerted (outgoing call). */
|
||||
#define ESP_BLE_AUDIO_TBS_CALL_STATE_ALERTING BT_TBS_CALL_STATE_ALERTING
|
||||
/*!< The call is in an active conversation. */
|
||||
#define ESP_BLE_AUDIO_TBS_CALL_STATE_ACTIVE BT_TBS_CALL_STATE_ACTIVE
|
||||
/**
|
||||
* The call is connected but held locally. Locally Held implies that either
|
||||
* the server or the client can affect the state.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_TBS_CALL_STATE_LOCALLY_HELD BT_TBS_CALL_STATE_LOCALLY_HELD
|
||||
/**
|
||||
* The call is connected but held remotely. Remotely Held means that the state
|
||||
* is controlled by the remote party of a call.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_TBS_CALL_STATE_REMOTELY_HELD BT_TBS_CALL_STATE_REMOTELY_HELD
|
||||
/*!< The call is connected but held both locally and remotely. */
|
||||
#define ESP_BLE_AUDIO_TBS_CALL_STATE_LOCALLY_AND_REMOTELY_HELD BT_TBS_CALL_STATE_LOCALLY_AND_REMOTELY_HELD
|
||||
|
||||
/*!< The URI value used to originate a call was formed improperly. */
|
||||
#define ESP_BLE_AUDIO_TBS_REASON_BAD_REMOTE_URI BT_TBS_REASON_BAD_REMOTE_URI
|
||||
/*!< The call failed. */
|
||||
#define ESP_BLE_AUDIO_TBS_REASON_CALL_FAILED BT_TBS_REASON_CALL_FAILED
|
||||
/*!< The remote party ended the call. */
|
||||
#define ESP_BLE_AUDIO_TBS_REASON_REMOTE_ENDED_CALL BT_TBS_REASON_REMOTE_ENDED_CALL
|
||||
/*!< The call ended from the server. */
|
||||
#define ESP_BLE_AUDIO_TBS_REASON_SERVER_ENDED_CALL BT_TBS_REASON_SERVER_ENDED_CALL
|
||||
/*!< The line was busy. */
|
||||
#define ESP_BLE_AUDIO_TBS_REASON_LINE_BUSY BT_TBS_REASON_LINE_BUSY
|
||||
/*!< Network congestion. */
|
||||
#define ESP_BLE_AUDIO_TBS_REASON_NETWORK_CONGESTED BT_TBS_REASON_NETWORK_CONGESTED
|
||||
/*!< The client terminated the call. */
|
||||
#define ESP_BLE_AUDIO_TBS_REASON_CLIENT_TERMINATED BT_TBS_REASON_CLIENT_TERMINATED
|
||||
/*!< No service. */
|
||||
#define ESP_BLE_AUDIO_TBS_REASON_NO_SERVICE BT_TBS_REASON_NO_SERVICE
|
||||
/*!< No answer. */
|
||||
#define ESP_BLE_AUDIO_TBS_REASON_NO_ANSWER BT_TBS_REASON_NO_ANSWER
|
||||
/*!< Unspecified. */
|
||||
#define ESP_BLE_AUDIO_TBS_REASON_UNSPECIFIED BT_TBS_REASON_UNSPECIFIED
|
||||
|
||||
/*!< The opcode write was successful. */
|
||||
#define ESP_BLE_AUDIO_TBS_RESULT_CODE_SUCCESS BT_TBS_RESULT_CODE_SUCCESS
|
||||
/*!< An invalid opcode was used for the Call Control Point write. */
|
||||
#define ESP_BLE_AUDIO_TBS_RESULT_CODE_OPCODE_NOT_SUPPORTED BT_TBS_RESULT_CODE_OPCODE_NOT_SUPPORTED
|
||||
/*!< The requested operation cannot be completed. */
|
||||
#define ESP_BLE_AUDIO_TBS_RESULT_CODE_OPERATION_NOT_POSSIBLE BT_TBS_RESULT_CODE_OPERATION_NOT_POSSIBLE
|
||||
/*!< The Call Index used for the Call Control Point write is invalid. */
|
||||
#define ESP_BLE_AUDIO_TBS_RESULT_CODE_INVALID_CALL_INDEX BT_TBS_RESULT_CODE_INVALID_CALL_INDEX
|
||||
/**
|
||||
* The opcode written to the Call Control Point was received when the current
|
||||
* Call State for the Call Index was not in the expected state.
|
||||
*/
|
||||
#define ESP_BLE_AUDIO_TBS_RESULT_CODE_STATE_MISMATCH BT_TBS_RESULT_CODE_STATE_MISMATCH
|
||||
/*!< Lack of internal resources to complete the requested action. */
|
||||
#define ESP_BLE_AUDIO_TBS_RESULT_CODE_OUT_OF_RESOURCES BT_TBS_RESULT_CODE_OUT_OF_RESOURCES
|
||||
/*!< The Outgoing URI is incorrect or invalid when an Originate opcode is sent. */
|
||||
#define ESP_BLE_AUDIO_TBS_RESULT_CODE_INVALID_URI BT_TBS_RESULT_CODE_INVALID_URI
|
||||
|
||||
/*!< Local Hold and Local Retrieve Call Control Point Opcodes supported */
|
||||
#define ESP_BLE_AUDIO_TBS_FEATURE_HOLD BT_TBS_FEATURE_HOLD
|
||||
/*!< Join Call Control Point Opcode supported */
|
||||
#define ESP_BLE_AUDIO_TBS_FEATURE_JOIN BT_TBS_FEATURE_JOIN
|
||||
/*!< All Control Point Opcodes supported */
|
||||
#define ESP_BLE_AUDIO_TBS_FEATURE_ALL BT_TBS_FEATURE_ALL
|
||||
|
||||
/*!< No service */
|
||||
#define ESP_BLE_AUDIO_TBS_SIGNAL_STRENGTH_NO_SERVICE BT_TBS_SIGNAL_STRENGTH_NO_SERVICE
|
||||
/*!< Maximum signal strength */
|
||||
#define ESP_BLE_AUDIO_TBS_SIGNAL_STRENGTH_MAX BT_TBS_SIGNAL_STRENGTH_MAX
|
||||
/*!< Signal strength is unknown */
|
||||
#define ESP_BLE_AUDIO_TBS_SIGNAL_STRENGTH_UNKNOWN BT_TBS_SIGNAL_STRENGTH_UNKNOWN
|
||||
|
||||
/*!< 3G */
|
||||
#define ESP_BLE_AUDIO_TBS_TECHNOLOGY_3G BT_TBS_TECHNOLOGY_3G
|
||||
/*!< 4G */
|
||||
#define ESP_BLE_AUDIO_TBS_TECHNOLOGY_4G BT_TBS_TECHNOLOGY_4G
|
||||
/*!< Long-term evolution (LTE) */
|
||||
#define ESP_BLE_AUDIO_TBS_TECHNOLOGY_LTE BT_TBS_TECHNOLOGY_LTE
|
||||
/*!< Wifi */
|
||||
#define ESP_BLE_AUDIO_TBS_TECHNOLOGY_WIFI BT_TBS_TECHNOLOGY_WIFI
|
||||
/*!< 5G */
|
||||
#define ESP_BLE_AUDIO_TBS_TECHNOLOGY_5G BT_TBS_TECHNOLOGY_5G
|
||||
/*!< Global System for Mobile Communications (GSM) */
|
||||
#define ESP_BLE_AUDIO_TBS_TECHNOLOGY_GSM BT_TBS_TECHNOLOGY_GSM
|
||||
/*!< Code-Division Multiple Access (CDMA) */
|
||||
#define ESP_BLE_AUDIO_TBS_TECHNOLOGY_CDMA BT_TBS_TECHNOLOGY_CDMA
|
||||
/*!< 2G */
|
||||
#define ESP_BLE_AUDIO_TBS_TECHNOLOGY_2G BT_TBS_TECHNOLOGY_2G
|
||||
/*!< Wideband Code-Division Multiple Access (WCDMA) */
|
||||
#define ESP_BLE_AUDIO_TBS_TECHNOLOGY_WCDMA BT_TBS_TECHNOLOGY_WCDMA
|
||||
|
||||
/*!< Inband ringtone enabled */
|
||||
#define ESP_BLE_AUDIO_TBS_STATUS_FLAG_INBAND_RINGTONE BT_TBS_STATUS_FLAG_INBAND_RINGTONE
|
||||
/*!< Server is in silent mod */
|
||||
#define ESP_BLE_AUDIO_TBS_STATUS_FLAG_SILENT_MOD BT_TBS_STATUS_FLAG_SILENT_MOD
|
||||
|
||||
/*!< If set, call is outgoing else incoming */
|
||||
#define ESP_BLE_AUDIO_TBS_CALL_FLAG_OUTGOING BT_TBS_CALL_FLAG_OUTGOING
|
||||
/*!< If set call is withheld, else not withheld */
|
||||
#define ESP_BLE_AUDIO_TBS_CALL_FLAG_WITHHELD BT_TBS_CALL_FLAG_WITHHELD
|
||||
/*!< If set call is withheld by network, else provided by network */
|
||||
#define ESP_BLE_AUDIO_TBS_CALL_FLAG_WITHHELD_BY_NETWORK BT_TBS_CALL_FLAG_WITHHELD_BY_NETWORK
|
||||
|
||||
/** Struct to hold the Telephone Bearer Service callbacks */
|
||||
typedef struct bt_tbs_cb esp_ble_audio_tbs_cb_t;
|
||||
|
||||
/** Telephone Bearer Service instance */
|
||||
typedef struct bt_tbs_instance esp_ble_audio_tbs_instance_t;
|
||||
|
||||
/** Struct to hold the parameters to initialize the bearer */
|
||||
typedef struct bt_tbs_register_param esp_ble_audio_tbs_register_param_t;
|
||||
|
||||
/** Struct to hold the Telephone Bearer Service client callbacks */
|
||||
typedef struct bt_tbs_client_cb esp_ble_audio_tbs_client_cb_t;
|
||||
|
||||
/** Struct to hold a call as the Telephone Bearer Service client */
|
||||
typedef struct bt_tbs_client_call esp_ble_audio_tbs_client_call_t;
|
||||
|
||||
/** Struct to hold a call state */
|
||||
typedef struct bt_tbs_client_call_state esp_ble_audio_tbs_client_call_state_t;
|
||||
|
||||
/**
|
||||
* @brief Accept an alerting call.
|
||||
*
|
||||
* @param call_index The index of the call that will be accepted.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_accept(uint8_t call_index);
|
||||
|
||||
/**
|
||||
* @brief Hold a call.
|
||||
*
|
||||
* @param call_index The index of the call that will be held.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_hold(uint8_t call_index);
|
||||
|
||||
/**
|
||||
* @brief Retrieve a call.
|
||||
*
|
||||
* @param call_index The index of the call that will be retrieved.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_retrieve(uint8_t call_index);
|
||||
|
||||
/**
|
||||
* @brief Terminate a call.
|
||||
*
|
||||
* @param call_index The index of the call that will be terminated.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_terminate(uint8_t call_index);
|
||||
|
||||
/**
|
||||
* @brief Originate a call.
|
||||
*
|
||||
* @param bearer_index The index of the Telephone Bearer.
|
||||
* @param uri The remote URI.
|
||||
* @param call_index Pointer to a value where the new call_index will be stored.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_originate(uint8_t bearer_index,
|
||||
char *uri,
|
||||
uint8_t *call_index);
|
||||
|
||||
/**
|
||||
* @brief Join calls.
|
||||
*
|
||||
* @param call_index_cnt The number of call indexes to join.
|
||||
* @param call_indexes Array of call indexes to join.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_join(uint8_t call_index_cnt, uint8_t *call_indexes);
|
||||
|
||||
/**
|
||||
* @brief Notify the server that the remote party answered the call.
|
||||
*
|
||||
* @param call_index The index of the call that was answered.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_remote_answer(uint8_t call_index);
|
||||
|
||||
/**
|
||||
* @brief Notify the server that the remote party held the call.
|
||||
*
|
||||
* @param call_index The index of the call that was held.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_remote_hold(uint8_t call_index);
|
||||
|
||||
/**
|
||||
* @brief Notify the server that the remote party retrieved the call.
|
||||
*
|
||||
* @param call_index The index of the call that was retrieved.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_remote_retrieve(uint8_t call_index);
|
||||
|
||||
/**
|
||||
* @brief Notify the server that the remote party terminated the call.
|
||||
*
|
||||
* @param call_index The index of the call that was terminated.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_remote_terminate(uint8_t call_index);
|
||||
|
||||
/**
|
||||
* @brief Notify the server of an incoming call.
|
||||
*
|
||||
* @param bearer_index The index of the Telephone Bearer.
|
||||
* @param to The URI that is receiving the call.
|
||||
* @param from The URI of the remote caller.
|
||||
* @param friendly_name The friendly name of the remote caller.
|
||||
* @param call_index The call index on success.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_remote_incoming(uint8_t bearer_index,
|
||||
const char *to,
|
||||
const char *from,
|
||||
const char *friendly_name,
|
||||
uint8_t *call_index);
|
||||
|
||||
/**
|
||||
* @brief Set a new bearer provider.
|
||||
*
|
||||
* @param bearer_index The index of the Telephone Bearer or
|
||||
* ESP_BLE_AUDIO_TBS_GTBS_INDEX for GTBS.
|
||||
* @param name The new bearer provider name.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_set_bearer_provider_name(uint8_t bearer_index, const char *name);
|
||||
|
||||
/**
|
||||
* @brief Set a new bearer technology.
|
||||
*
|
||||
* @param bearer_index The index of the Telephone Bearer or
|
||||
* ESP_BLE_AUDIO_TBS_GTBS_INDEX for GTBS.
|
||||
* @param new_technology The new bearer technology.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_set_bearer_technology(uint8_t bearer_index, uint8_t new_technology);
|
||||
|
||||
/**
|
||||
* @brief Update the signal strength reported by the server.
|
||||
*
|
||||
* @param bearer_index The index of the Telephone Bearer or
|
||||
* ESP_BLE_AUDIO_TBS_GTBS_INDEX for GTBS.
|
||||
* @param new_signal_strength The new signal strength.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_set_signal_strength(uint8_t bearer_index, uint8_t new_signal_strength);
|
||||
|
||||
/**
|
||||
* @brief Sets the feature and status value.
|
||||
*
|
||||
* @param bearer_index The index of the Telephone Bearer or
|
||||
* ESP_BLE_AUDIO_TBS_GTBS_INDEX for GTBS.
|
||||
* @param status_flags The new feature and status value.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_set_status_flags(uint8_t bearer_index, uint16_t status_flags);
|
||||
|
||||
/**
|
||||
* @brief Sets the URI scheme list of a bearer.
|
||||
*
|
||||
* @param bearer_index The index of the Telephone Bearer.
|
||||
* @param uri_list List of URI prefixes (e.g. {"skype", "tel"}).
|
||||
* @param uri_count Number of URI prefixes in @p uri_list.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_set_uri_scheme_list(uint8_t bearer_index,
|
||||
const char **uri_list,
|
||||
uint8_t uri_count);
|
||||
|
||||
/**
|
||||
* @brief Register the callbacks for TBS.
|
||||
*
|
||||
* @param cbs Pointer to the callback structure.
|
||||
*/
|
||||
void esp_ble_audio_tbs_register_cb(esp_ble_audio_tbs_cb_t *cbs);
|
||||
|
||||
/**
|
||||
* @brief Register a Telephone Bearer.
|
||||
*
|
||||
* This will register a Telephone Bearer Service (TBS) (or a Generic Telephone
|
||||
* Bearer service (GTBS)) with the provided parameters.
|
||||
*
|
||||
* As per the TBS specification, the GTBS shall be instantiated for the feature,
|
||||
* and as such a GTBS shall always be registered before any TBS can be registered.
|
||||
*
|
||||
* @param param The parameters to initialize the bearer.
|
||||
* @param bearer_index The registered bearer index on success.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_register_bearer(const esp_ble_audio_tbs_register_param_t *param,
|
||||
uint8_t *bearer_index);
|
||||
|
||||
/**
|
||||
* @brief Unregister a Telephone Bearer.
|
||||
*
|
||||
* This will unregister a Telephone Bearer Service (TBS) (or a Generic Telephone
|
||||
* Bearer service (GTBS)) with the provided parameters.
|
||||
*
|
||||
* Similarly, all TBS shall be unregistered before the GTBS can be unregistered with.
|
||||
*
|
||||
* @param bearer_index The index of the bearer to unregister.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_unregister_bearer(uint8_t bearer_index);
|
||||
|
||||
/**
|
||||
* @brief Discover TBS for a connection. This will start a GATT
|
||||
* discover and setup handles and subscriptions.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_discover(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Set the signal strength reporting interval for a TBS instance.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst_index The index of the TBS instance.
|
||||
* @param interval The interval to write (0-255 seconds).
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_set_signal_strength_interval(uint16_t conn_handle,
|
||||
uint8_t inst_index,
|
||||
uint8_t interval);
|
||||
|
||||
/**
|
||||
* @brief Request to originate a call.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst_index The index of the TBS instance.
|
||||
* @param uri The URI of the callee.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_originate_call(uint16_t conn_handle,
|
||||
uint8_t inst_index,
|
||||
const char *uri);
|
||||
|
||||
/**
|
||||
* @brief Request to terminate a call.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst_index The index of the TBS instance.
|
||||
* @param call_index The call index to terminate.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_terminate_call(uint16_t conn_handle,
|
||||
uint8_t inst_index,
|
||||
uint8_t call_index);
|
||||
|
||||
/**
|
||||
* @brief Request to hold a call.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst_index The index of the TBS instance.
|
||||
* @param call_index The call index to place on hold.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_hold_call(uint16_t conn_handle,
|
||||
uint8_t inst_index,
|
||||
uint8_t call_index);
|
||||
|
||||
/**
|
||||
* @brief Accept an incoming call.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst_index The index of the TBS instance.
|
||||
* @param call_index The call index to accept.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_accept_call(uint16_t conn_handle,
|
||||
uint8_t inst_index,
|
||||
uint8_t call_index);
|
||||
|
||||
/**
|
||||
* @brief Retrieve call from (local) hold.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst_index The index of the TBS instance.
|
||||
* @param call_index The call index to retrieve.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_retrieve_call(uint16_t conn_handle,
|
||||
uint8_t inst_index,
|
||||
uint8_t call_index);
|
||||
|
||||
/**
|
||||
* @brief Join multiple calls.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst_index The index of the TBS instance.
|
||||
* @param call_indexes Array of call indexes.
|
||||
* @param count Number of call indexes in the call_indexes array.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_join_calls(uint16_t conn_handle,
|
||||
uint8_t inst_index,
|
||||
const uint8_t *call_indexes,
|
||||
uint8_t count);
|
||||
|
||||
/**
|
||||
* @brief Read the bearer provider name of a TBS instance.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst_index The index of the TBS instance.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_read_bearer_provider_name(uint16_t conn_handle, uint8_t inst_index);
|
||||
|
||||
/**
|
||||
* @brief Read the UCI of a TBS instance.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst_index The index of the TBS instance.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_read_bearer_uci(uint16_t conn_handle, uint8_t inst_index);
|
||||
|
||||
/**
|
||||
* @brief Read the technology of a TBS instance.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst_index The index of the TBS instance.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_read_technology(uint16_t conn_handle, uint8_t inst_index);
|
||||
|
||||
/**
|
||||
* @brief Read the URI schemes list of a TBS instance.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst_index The index of the TBS instance.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_read_uri_list(uint16_t conn_handle, uint8_t inst_index);
|
||||
|
||||
/**
|
||||
* @brief Read the current signal strength of a TBS instance.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst_index The index of the TBS instance.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_read_signal_strength(uint16_t conn_handle, uint8_t inst_index);
|
||||
|
||||
/**
|
||||
* @brief Read the signal strength reporting interval of a TBS instance.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst_index The index of the TBS instance.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_read_signal_interval(uint16_t conn_handle, uint8_t inst_index);
|
||||
|
||||
/**
|
||||
* @brief Read the list of current calls of a TBS instance.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst_index The index of the TBS instance.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_read_current_calls(uint16_t conn_handle, uint8_t inst_index);
|
||||
|
||||
/**
|
||||
* @brief Read the content ID of a TBS instance.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst_index The index of the TBS instance.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_read_ccid(uint16_t conn_handle, uint8_t inst_index);
|
||||
|
||||
/**
|
||||
* @brief Read the call target URI of a TBS instance.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst_index The index of the TBS instance.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_read_call_uri(uint16_t conn_handle, uint8_t inst_index);
|
||||
|
||||
/**
|
||||
* @brief Read the feature and status value of a TBS instance.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst_index The index of the TBS instance.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_read_status_flags(uint16_t conn_handle, uint8_t inst_index);
|
||||
|
||||
/**
|
||||
* @brief Read the states of the current calls of a TBS instance.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst_index The index of the TBS instance.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_read_call_state(uint16_t conn_handle, uint8_t inst_index);
|
||||
|
||||
/**
|
||||
* @brief Read the remote URI of a TBS instance.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst_index The index of the TBS instance.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_read_remote_uri(uint16_t conn_handle, uint8_t inst_index);
|
||||
|
||||
/**
|
||||
* @brief Read the friendly name of a call for a TBS instance.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst_index The index of the TBS instance.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_read_friendly_name(uint16_t conn_handle, uint8_t inst_index);
|
||||
|
||||
/**
|
||||
* @brief Read the supported opcode of a TBS instance.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst_index The index of the TBS instance.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_read_optional_opcodes(uint16_t conn_handle, uint8_t inst_index);
|
||||
|
||||
/**
|
||||
* @brief Register the callbacks for CCP.
|
||||
*
|
||||
* @param cbs Pointer to the callback structure.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tbs_client_register_cb(esp_ble_audio_tbs_client_cb_t *cbs);
|
||||
|
||||
/**
|
||||
* @brief Look up Telephone Bearer Service instance by CCID.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param ccid The CCID to lookup a service instance for.
|
||||
*
|
||||
* @return Pointer to TBS instance if found, NULL otherwise.
|
||||
*/
|
||||
esp_ble_audio_tbs_instance_t *esp_ble_audio_tbs_client_get_by_ccid(uint16_t conn_handle, uint8_t ccid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_BLE_AUDIO_TBS_API_H_ */
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 NXP
|
||||
* SPDX-FileCopyrightText: 2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_BLE_AUDIO_TMAP_API_H_
|
||||
#define ESP_BLE_AUDIO_TMAP_API_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include <zephyr/bluetooth/audio/tmap.h>
|
||||
|
||||
#include "common/init.h"
|
||||
#include "common/host.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!< TMAP Call Gateway role */
|
||||
#define ESP_BLE_AUDIO_TMAP_ROLE_CG BT_TMAP_ROLE_CG
|
||||
/*!< TMAP Call Terminal role */
|
||||
#define ESP_BLE_AUDIO_TMAP_ROLE_CT BT_TMAP_ROLE_CT
|
||||
/*!< TMAP Unicast Media Sender role */
|
||||
#define ESP_BLE_AUDIO_TMAP_ROLE_UMS BT_TMAP_ROLE_UMS
|
||||
/*!< TMAP Unicast Media Receiver role */
|
||||
#define ESP_BLE_AUDIO_TMAP_ROLE_UMR BT_TMAP_ROLE_UMR
|
||||
/*!< TMAP Broadcast Media Sender role */
|
||||
#define ESP_BLE_AUDIO_TMAP_ROLE_BMS BT_TMAP_ROLE_BMS
|
||||
/*!< TMAP Broadcast Media Receiver role */
|
||||
#define ESP_BLE_AUDIO_TMAP_ROLE_BMR BT_TMAP_ROLE_BMR
|
||||
|
||||
/** TMAP Role characteristic */
|
||||
typedef enum bt_tmap_role esp_ble_audio_tmap_role_t;
|
||||
|
||||
/** TMAP callback structure */
|
||||
typedef struct bt_tmap_cb esp_ble_audio_tmap_cb_t;
|
||||
|
||||
/**
|
||||
* @brief Adds TMAS instance to database and sets the received TMAP role(s).
|
||||
*
|
||||
* @param role TMAP role(s) of the device (one or multiple).
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tmap_register(esp_ble_audio_tmap_role_t role);
|
||||
|
||||
/**
|
||||
* @brief Perform service discovery as TMAP Client.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param tmap_cb Pointer to struct of TMAP callbacks.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_tmap_discover(uint16_t conn_handle,
|
||||
const esp_ble_audio_tmap_cb_t *tmap_cb);
|
||||
|
||||
/**
|
||||
* @brief Set one or multiple TMAP roles dynamically.
|
||||
* Previously registered value will be overwritten.
|
||||
*
|
||||
* @param role TMAP role(s).
|
||||
*/
|
||||
void esp_ble_audio_tmap_set_role(esp_ble_audio_tmap_role_t role);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_BLE_AUDIO_TMAP_API_H_ */
|
||||
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_BLE_AUDIO_VCP_API_H_
|
||||
#define ESP_BLE_AUDIO_VCP_API_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include <zephyr/bluetooth/audio/vcp.h>
|
||||
|
||||
#include "common/init.h"
|
||||
#include "common/host.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!< The volume state is unmuted */
|
||||
#define ESP_BLE_AUDIO_VCP_STATE_UNMUTED BT_VCP_STATE_UNMUTED
|
||||
/*!< The volume state is muted */
|
||||
#define ESP_BLE_AUDIO_VCP_STATE_MUTED BT_VCP_STATE_MUTED
|
||||
|
||||
/** Volume Control Service included services */
|
||||
typedef struct bt_vcp_included esp_ble_audio_vcp_included_t;
|
||||
|
||||
/** Volume Control Service instance */
|
||||
typedef struct bt_vcp_vol_ctlr esp_ble_audio_vcp_vol_ctlr_t;
|
||||
|
||||
/** Struct to hold the Volume Controller callbacks */
|
||||
typedef struct bt_vcp_vol_ctlr_cb esp_ble_audio_vcp_vol_ctlr_cb_t;
|
||||
|
||||
/** Struct to hold the Volume Renderer callbacks */
|
||||
typedef struct bt_vcp_vol_rend_cb esp_ble_audio_vcp_vol_rend_cb_t;
|
||||
|
||||
/** Register structure for Volume Control Service */
|
||||
typedef struct bt_vcp_vol_rend_register_param esp_ble_audio_vcp_vol_rend_register_param_t;
|
||||
|
||||
/**
|
||||
* @brief Get Volume Control Service included services.
|
||||
*
|
||||
* Returns a pointer to a struct that contains information about the
|
||||
* Volume Control Service included service instances, such as pointers
|
||||
* to the Volume Offset Control Service (Volume Offset Control Service)
|
||||
* or Audio Input Control Service (AICS) instances.
|
||||
*
|
||||
* @param included Pointer to store the result in.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_included_get(esp_ble_audio_vcp_included_t *included);
|
||||
|
||||
/**
|
||||
* @brief Register the Volume Control Service.
|
||||
*
|
||||
* This will register and enable the service and make it discoverable by
|
||||
* clients.
|
||||
*
|
||||
* @param param Volume Control Service register parameters.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_register(esp_ble_audio_vcp_vol_rend_register_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief Set the Volume Control Service volume step size.
|
||||
*
|
||||
* This can only be done as the server.
|
||||
*
|
||||
* @param volume_step The volume step size (1-255).
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_set_step(uint8_t volume_step);
|
||||
|
||||
/**
|
||||
* @brief Get the Volume Control Service volume state.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_get_state(void);
|
||||
|
||||
/**
|
||||
* @brief Get the Volume Control Service flags.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_get_flags(void);
|
||||
|
||||
/**
|
||||
* @brief Turn the volume down by one step on the server.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_vol_down(void);
|
||||
|
||||
/**
|
||||
* @brief Turn the volume up by one step on the server.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_vol_up(void);
|
||||
|
||||
/**
|
||||
* @brief Turn the volume down and unmute the server.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_unmute_vol_down(void);
|
||||
|
||||
/**
|
||||
* @brief Turn the volume up and unmute the server.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_unmute_vol_up(void);
|
||||
|
||||
/**
|
||||
* @brief Set the volume on the server.
|
||||
*
|
||||
* @param volume The absolute volume to set.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_set_vol(uint8_t volume);
|
||||
|
||||
/**
|
||||
* @brief Unmute the server.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_unmute(void);
|
||||
|
||||
/**
|
||||
* @brief Mute the server.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_rend_mute(void);
|
||||
|
||||
/**
|
||||
* @brief Registers the callbacks used by the Volume Controller.
|
||||
*
|
||||
* @param cb The callback structure.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_cb_register(esp_ble_audio_vcp_vol_ctlr_cb_t *cb);
|
||||
|
||||
/**
|
||||
* @brief Unregisters the callbacks used by the Volume Controller.
|
||||
*
|
||||
* @param cb The callback structure.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_cb_unregister(esp_ble_audio_vcp_vol_ctlr_cb_t *cb);
|
||||
|
||||
/**
|
||||
* @brief Discover Volume Control Service and included services.
|
||||
*
|
||||
* This will start a GATT discovery and setup handles and subscriptions.
|
||||
* This shall be called once before any other actions can be executed
|
||||
* for the peer device.
|
||||
*
|
||||
* This shall only be done as the client,
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param vol_ctlr Valid remote instance object on success.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_discover(uint16_t conn_handle,
|
||||
esp_ble_audio_vcp_vol_ctlr_t **vol_ctlr);
|
||||
|
||||
/**
|
||||
* @brief Get the volume controller from a connection pointer
|
||||
*
|
||||
* Get the Volume Control Profile Volume Controller pointer from a connection.
|
||||
* Only volume controllers that have been initiated can be retrieved.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
*
|
||||
* @return Pointer to a Volume Control Profile Volume Controller instance.
|
||||
* NULL if the connection has not been found has not done discovery yet.
|
||||
*/
|
||||
esp_ble_audio_vcp_vol_ctlr_t *esp_ble_audio_vcp_vol_ctlr_get_by_conn(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* @brief Get Volume Control Service included services.
|
||||
*
|
||||
* Returns a pointer to a struct that contains information about the
|
||||
* Volume Control Service included service instances, such as pointers
|
||||
* to the Volume Offset Control Service (Volume Offset Control Service)
|
||||
* or Audio Input Control Service (AICS) instances.
|
||||
*
|
||||
* @param vol_ctlr Volume Controller instance pointer.
|
||||
* @param included Pointer to store the result in.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_included_get(esp_ble_audio_vcp_vol_ctlr_t *vol_ctlr,
|
||||
esp_ble_audio_vcp_included_t *included);
|
||||
|
||||
/**
|
||||
* @brief Read the volume state of a remote Volume Renderer.
|
||||
*
|
||||
* @param vol_ctlr Volume Controller instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_read_state(esp_ble_audio_vcp_vol_ctlr_t *vol_ctlr);
|
||||
|
||||
/**
|
||||
* @brief Read the volume flags of a remote Volume Renderer.
|
||||
*
|
||||
* @param vol_ctlr Volume Controller instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_read_flags(esp_ble_audio_vcp_vol_ctlr_t *vol_ctlr);
|
||||
|
||||
/**
|
||||
* @brief Turn the volume down one step on a remote Volume Renderer.
|
||||
*
|
||||
* @param vol_ctlr Volume Controller instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_vol_down(esp_ble_audio_vcp_vol_ctlr_t *vol_ctlr);
|
||||
|
||||
/**
|
||||
* @brief Turn the volume up one step on a remote Volume Renderer.
|
||||
*
|
||||
* @param vol_ctlr Volume Controller instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_vol_up(esp_ble_audio_vcp_vol_ctlr_t *vol_ctlr);
|
||||
|
||||
/**
|
||||
* @brief Turn the volume down one step and unmute on a remote Volume Renderer.
|
||||
*
|
||||
* @param vol_ctlr Volume Controller instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_unmute_vol_down(esp_ble_audio_vcp_vol_ctlr_t *vol_ctlr);
|
||||
|
||||
/**
|
||||
* @brief Turn the volume up one step and unmute on a remote Volume Renderer.
|
||||
*
|
||||
* @param vol_ctlr Volume Controller instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_unmute_vol_up(esp_ble_audio_vcp_vol_ctlr_t *vol_ctlr);
|
||||
|
||||
/**
|
||||
* @brief Set the absolute volume on a remote Volume Renderer.
|
||||
*
|
||||
* @param vol_ctlr Volume Controller instance pointer.
|
||||
* @param volume The absolute volume to set.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_set_vol(esp_ble_audio_vcp_vol_ctlr_t *vol_ctlr, uint8_t volume);
|
||||
|
||||
/**
|
||||
* @brief Unmute a remote Volume Renderer.
|
||||
*
|
||||
* @param vol_ctlr Volume Controller instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_unmute(esp_ble_audio_vcp_vol_ctlr_t *vol_ctlr);
|
||||
|
||||
/**
|
||||
* @brief Mute a remote Volume Renderer.
|
||||
*
|
||||
* @param vol_ctlr Volume Controller instance pointer.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vcp_vol_ctlr_mute(esp_ble_audio_vcp_vol_ctlr_t *vol_ctlr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_BLE_AUDIO_VCP_API_H_ */
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_BLE_AUDIO_VOCS_API_H_
|
||||
#define ESP_BLE_AUDIO_VOCS_API_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include <zephyr/bluetooth/audio/vocs.h>
|
||||
|
||||
#include "common/init.h"
|
||||
#include "common/host.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!< Minimum offset value */
|
||||
#define ESP_BLE_AUDIO_VOCS_MIN_OFFSET BT_VOCS_MIN_OFFSET
|
||||
/*!< Maximum offset value */
|
||||
#define ESP_BLE_AUDIO_VOCS_MAX_OFFSET BT_VOCS_MAX_OFFSET
|
||||
|
||||
/** Volume Offset Control Service instance */
|
||||
typedef struct bt_vocs esp_ble_audio_vocs_t;
|
||||
|
||||
/** Struct to hold the Volume Offset Control Service callbacks */
|
||||
typedef struct bt_vocs_cb esp_ble_audio_vocs_cb_t;
|
||||
|
||||
/** Structure for registering a Volume Offset Control Service instance */
|
||||
typedef struct bt_vocs_register_param esp_ble_audio_vocs_register_param_t;
|
||||
|
||||
/** Structure for discovering a Volume Offset Control Service instance */
|
||||
typedef struct bt_vocs_discover_param esp_ble_audio_vocs_discover_param_t;
|
||||
|
||||
/**
|
||||
* @brief Get a free service instance of Volume Offset Control Service from the pool.
|
||||
*
|
||||
* @return Volume Offset Control Service instance in case of success or NULL in case of error.
|
||||
*/
|
||||
esp_ble_audio_vocs_t *esp_ble_audio_vocs_free_instance_get(void);
|
||||
|
||||
/**
|
||||
* @brief Get the service declaration attribute.
|
||||
*
|
||||
* The first service attribute returned can be included in any other GATT service.
|
||||
*
|
||||
* @param vocs Volume Offset Control Service instance.
|
||||
*
|
||||
* @return Pointer to the attributes of the service.
|
||||
*/
|
||||
void *esp_ble_audio_vocs_svc_decl_get(esp_ble_audio_vocs_t *vocs);
|
||||
|
||||
/**
|
||||
* @brief Register the Volume Offset Control Service instance.
|
||||
*
|
||||
* @param vocs Volume Offset Control Service instance.
|
||||
* @param param Volume Offset Control Service register parameters.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vocs_register(esp_ble_audio_vocs_t *vocs,
|
||||
const esp_ble_audio_vocs_register_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief Read the Volume Offset Control Service offset state.
|
||||
*
|
||||
* @param inst Pointer to the Volume Offset Control Service instance.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vocs_state_get(esp_ble_audio_vocs_t *inst);
|
||||
|
||||
/**
|
||||
* @brief Set the Volume Offset Control Service offset state.
|
||||
*
|
||||
* @param inst Pointer to the Volume Offset Control Service instance.
|
||||
* @param offset The offset to set (-255 to 255).
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vocs_state_set(esp_ble_audio_vocs_t *inst, int16_t offset);
|
||||
|
||||
/**
|
||||
* @brief Read the Volume Offset Control Service location.
|
||||
*
|
||||
* @param inst Pointer to the Volume Offset Control Service instance.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vocs_location_get(esp_ble_audio_vocs_t *inst);
|
||||
|
||||
/**
|
||||
* @brief Set the Volume Offset Control Service location.
|
||||
*
|
||||
* @param inst Pointer to the Volume Offset Control Service instance.
|
||||
* @param location The location to set.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vocs_location_set(esp_ble_audio_vocs_t *inst, uint32_t location);
|
||||
|
||||
/**
|
||||
* @brief Read the Volume Offset Control Service output description.
|
||||
*
|
||||
* @param inst Pointer to the Volume Offset Control Service instance.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vocs_description_get(esp_ble_audio_vocs_t *inst);
|
||||
|
||||
/**
|
||||
* @brief Set the Volume Offset Control Service description.
|
||||
*
|
||||
* @param inst Pointer to the Volume Offset Control Service instance.
|
||||
* @param description The UTF-8 encoded string description to set.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vocs_description_set(esp_ble_audio_vocs_t *inst,
|
||||
const char *description);
|
||||
|
||||
/**
|
||||
* @brief Registers the callbacks for the Volume Offset Control Service client.
|
||||
*
|
||||
* @param inst Pointer to the Volume Offset Control Service client instance.
|
||||
* @param cb Pointer to the callback structure.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vocs_client_cb_register(esp_ble_audio_vocs_t *inst,
|
||||
esp_ble_audio_vocs_cb_t *cb);
|
||||
|
||||
/**
|
||||
* @brief Returns a pointer to a Volume Offset Control Service client instance.
|
||||
*
|
||||
* @return Pointer to the instance, or NULL if no free instances are left.
|
||||
*/
|
||||
esp_ble_audio_vocs_t *esp_ble_audio_vocs_client_free_instance_get(void);
|
||||
|
||||
/**
|
||||
* @brief Discover a Volume Offset Control Service.
|
||||
*
|
||||
* Attempts to discover a Volume Offset Control Service on a server given the @p param.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param inst Pointer to the Volume Offset Control Service client instance.
|
||||
* @param param Pointer to the parameters.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_vocs_discover(uint16_t conn_handle,
|
||||
esp_ble_audio_vocs_t *inst,
|
||||
const esp_ble_audio_vocs_discover_param_t *param);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_BLE_AUDIO_VOCS_API_H_ */
|
||||
@@ -0,0 +1,432 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Intel Corporation
|
||||
* SPDX-FileCopyrightText: 2021-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_ble_iso_common_api.h"
|
||||
|
||||
esp_err_t esp_ble_iso_data_parse(const uint8_t ltv[], size_t size,
|
||||
bool (*func)(uint8_t type,
|
||||
const uint8_t *data,
|
||||
uint8_t data_len,
|
||||
void *user_data),
|
||||
void *user_data)
|
||||
{
|
||||
if (ltv == NULL || func == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size;) {
|
||||
const size_t remaining = size - i;
|
||||
const uint8_t len = ltv[i];
|
||||
uint8_t data_len;
|
||||
uint8_t type;
|
||||
|
||||
/* LTV item format: [len][type][value...], total item size is len + 1.
|
||||
* len includes type and value, but excludes itself.
|
||||
*/
|
||||
if (len < sizeof(uint8_t) || len > (remaining - 1)) {
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}
|
||||
|
||||
type = ltv[i + 1];
|
||||
data_len = len - sizeof(uint8_t);
|
||||
|
||||
/* Skip empty value entries in strict parsing mode. */
|
||||
if (data_len == 0) {
|
||||
i += (size_t)len + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (func(type, <v[i + 2], data_len, user_data) == false) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
i += (size_t)len + 1;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_ISO_UNICAST
|
||||
#if CONFIG_BT_ISO_PERIPHERAL
|
||||
esp_err_t esp_ble_iso_server_register(esp_ble_iso_server_t *server)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_iso_server_register_safe(server);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_iso_server_unregister(esp_ble_iso_server_t *server)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_iso_server_unregister_safe(server);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_ISO_PERIPHERAL */
|
||||
|
||||
#if CONFIG_BT_ISO_CENTRAL
|
||||
esp_err_t esp_ble_iso_cig_create(esp_ble_iso_cig_param_t *param,
|
||||
esp_ble_iso_cig_t **out_cig)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_iso_cig_create_safe(param, out_cig);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_iso_cig_reconfigure(esp_ble_iso_cig_t *cig,
|
||||
esp_ble_iso_cig_param_t *param)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_iso_cig_reconfigure_safe(cig, param);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_iso_cig_terminate(esp_ble_iso_cig_t *cig)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_iso_cig_terminate_safe(cig);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_iso_chan_connect(esp_ble_iso_connect_param_t *param,
|
||||
uint16_t conn_handle, size_t count)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *conn;
|
||||
int err;
|
||||
|
||||
if (param == NULL || count == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
param[i].acl = conn;
|
||||
}
|
||||
|
||||
err = bt_iso_chan_connect(param, count);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_ISO_CENTRAL */
|
||||
|
||||
esp_err_t esp_ble_iso_chan_disconnect(esp_ble_iso_chan_t *chan)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_iso_chan_disconnect_safe(chan);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_ISO_UNICAST */
|
||||
|
||||
static inline bool valid_dir(uint8_t dir)
|
||||
{
|
||||
if (dir != ESP_BLE_ISO_DATA_PATH_DIR_INPUT &&
|
||||
dir != ESP_BLE_ISO_DATA_PATH_DIR_OUTPUT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_iso_setup_data_path(const esp_ble_iso_chan_t *chan, uint8_t dir,
|
||||
const esp_ble_iso_chan_path_t *path)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (chan == NULL || path == NULL || valid_dir(dir) == false) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_iso_setup_data_path_safe(chan, dir, path);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_iso_remove_data_path(const esp_ble_iso_chan_t *chan, uint8_t dir)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (chan == NULL || valid_dir(dir) == false) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_iso_remove_data_path_safe(chan, dir);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_ISO_BROADCAST
|
||||
esp_err_t esp_ble_iso_big_register_cb(esp_ble_iso_big_cb_t *cb)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (cb == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_iso_big_register_cb_safe(cb);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_ISO_BROADCASTER
|
||||
esp_err_t esp_ble_iso_big_ext_adv_add(esp_ble_iso_ext_adv_info_t *info)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (info == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_le_ext_adv_new_safe(info->adv_handle);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_iso_big_ext_adv_delete(esp_ble_iso_ext_adv_info_t *info)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (info == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_le_ext_adv_delete_safe(info->adv_handle);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_iso_big_create(uint8_t adv_handle,
|
||||
esp_ble_iso_big_create_param_t *param,
|
||||
esp_ble_iso_big_t **out_big)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
void *adv;
|
||||
int err;
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
adv = bt_le_ext_adv_find(adv_handle);
|
||||
if (adv == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = bt_iso_big_create(adv, param, out_big);
|
||||
if (err) {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_ISO_BROADCASTER */
|
||||
|
||||
#if CONFIG_BT_ISO_SYNC_RECEIVER
|
||||
esp_err_t esp_ble_iso_big_sync(uint16_t sync_handle,
|
||||
esp_ble_iso_big_sync_param_t *param,
|
||||
esp_ble_iso_big_t **out_big)
|
||||
{
|
||||
void *per_adv_sync;
|
||||
int err;
|
||||
|
||||
per_adv_sync = bt_le_per_adv_sync_find_safe(sync_handle);
|
||||
if (per_adv_sync == NULL) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
err = bt_iso_big_sync_safe(per_adv_sync, param, out_big);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_ISO_SYNC_RECEIVER */
|
||||
|
||||
esp_err_t esp_ble_iso_big_terminate(esp_ble_iso_big_t *big)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_iso_big_terminate_safe(big);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_ISO_BROADCAST */
|
||||
|
||||
esp_err_t esp_ble_iso_chan_get_info(esp_ble_iso_chan_t *chan,
|
||||
esp_ble_iso_info_t *info)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_iso_chan_get_info_safe(chan, info);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_ISO_TX
|
||||
esp_err_t esp_ble_iso_chan_get_tx_sync(esp_ble_iso_chan_t *chan,
|
||||
esp_ble_iso_tx_info_t *info)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_iso_chan_get_tx_sync_safe(chan, info);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_iso_chan_send(esp_ble_iso_chan_t *chan,
|
||||
const uint8_t *sdu,
|
||||
uint16_t sdu_len,
|
||||
uint16_t seq_num)
|
||||
{
|
||||
struct net_buf buf = {
|
||||
/* Note: only data and len are used */
|
||||
.data = (void *)sdu,
|
||||
.len = sdu_len,
|
||||
};
|
||||
int err;
|
||||
|
||||
if (chan == NULL || (!sdu ^ !sdu_len)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_iso_chan_send_safe(chan, &buf, seq_num);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_iso_chan_send_ts(esp_ble_iso_chan_t *chan,
|
||||
const uint8_t *sdu,
|
||||
uint16_t sdu_len,
|
||||
uint16_t seq_num,
|
||||
uint32_t ts)
|
||||
{
|
||||
struct net_buf buf = {
|
||||
/* Note: only data and len are used */
|
||||
.data = (void *)sdu,
|
||||
.len = sdu_len,
|
||||
};
|
||||
int err;
|
||||
|
||||
if (chan == NULL || (!sdu ^ !sdu_len)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_iso_chan_send_ts_safe(chan, &buf, seq_num, ts);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_ISO_TX */
|
||||
|
||||
void esp_ble_iso_gap_app_post_event(uint8_t type, void *param)
|
||||
{
|
||||
bt_le_gap_app_post_event(type, param);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_iso_common_init(esp_ble_iso_init_info_t *info)
|
||||
{
|
||||
bool gap_cb_registered = false;
|
||||
int err;
|
||||
|
||||
if (info) {
|
||||
if (info->gap_cb) {
|
||||
err = bt_le_gap_app_cb_register(info->gap_cb);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
gap_cb_registered = true;
|
||||
}
|
||||
}
|
||||
|
||||
err = bt_le_host_init();
|
||||
if (err) {
|
||||
goto unregister_gap;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
unregister_gap:
|
||||
if (gap_cb_registered) {
|
||||
bt_le_gap_app_cb_unregister();
|
||||
}
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@@ -0,0 +1,594 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Intel Corporation
|
||||
* SPDX-FileCopyrightText: 2021-2024 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_BLE_ISO_COMMON_API_H_
|
||||
#define ESP_BLE_ISO_COMMON_API_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include <zephyr/bluetooth/bluetooth.h>
|
||||
#include <zephyr/bluetooth/iso.h>
|
||||
|
||||
#include <../host/conn_internal.h>
|
||||
|
||||
#include "common/host.h"
|
||||
#include "common/app/gap.h"
|
||||
#include "common/app/gatt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Convert BIS index to bit
|
||||
*
|
||||
* The BIS indexes start from 0x01, so the lowest allowed bit is
|
||||
* BIT(0) that represents index 0x01. To synchronize to e.g. BIS
|
||||
* indexes 0x01 and 0x02, the bitfield value should be BIT(0) | BIT(1).
|
||||
* As a general notation, to sync to BIS index N use BIT(N - 1).
|
||||
*/
|
||||
#define ESP_BLE_ISO_BIS_INDEX_BIT(x) BT_ISO_BIS_INDEX_BIT(x)
|
||||
|
||||
/*!< The minimum value for vendor specific data path ID */
|
||||
#define ESP_BLE_ISO_DATA_PATH_VS_ID_MIN BT_ISO_DATA_PATH_VS_ID_MIN
|
||||
/*!< The maximum value for vendor specific data path ID */
|
||||
#define ESP_BLE_ISO_DATA_PATH_VS_ID_MAX BT_ISO_DATA_PATH_VS_ID_MAX
|
||||
|
||||
/*!< Minimum controller delay in microseconds */
|
||||
#define ESP_BLE_ISO_CONTROLLER_DELAY_MIN BT_ISO_CONTROLLER_DELAY_MIN
|
||||
/*!< Maximum controller delay in microseconds */
|
||||
#define ESP_BLE_ISO_CONTROLLER_DELAY_MAX BT_ISO_CONTROLLER_DELAY_MAX
|
||||
|
||||
/*!< Unknown SDU interval */
|
||||
#define ESP_BLE_ISO_SDU_INTERVAL_UNKNOWN BT_ISO_SDU_INTERVAL_UNKNOWN
|
||||
/*!< Minimum interval value in microseconds */
|
||||
#define ESP_BLE_ISO_SDU_INTERVAL_MIN BT_ISO_SDU_INTERVAL_MIN
|
||||
/*!< Maximum interval value in microseconds */
|
||||
#define ESP_BLE_ISO_SDU_INTERVAL_MAX BT_ISO_SDU_INTERVAL_MAX
|
||||
|
||||
/*!< Minimum ISO interval (N * 1.25 ms) */
|
||||
#define ESP_BLE_ISO_ISO_INTERVAL_MIN BT_ISO_ISO_INTERVAL_MIN
|
||||
/*!< Maximum ISO interval (N * 1.25 ms) */
|
||||
#define ESP_BLE_ISO_ISO_INTERVAL_MAX BT_ISO_ISO_INTERVAL_MAX
|
||||
|
||||
/*!< Minimum latency value in milliseconds */
|
||||
#define ESP_BLE_ISO_LATENCY_MIN BT_ISO_LATENCY_MIN
|
||||
/*!< Maximum latency value in milliseconds */
|
||||
#define ESP_BLE_ISO_LATENCY_MAX BT_ISO_LATENCY_MAX
|
||||
|
||||
/*!< Packets will be sent sequentially between the channels in the group */
|
||||
#define ESP_BLE_ISO_PACKING_SEQUENTIAL BT_ISO_PACKING_SEQUENTIAL
|
||||
/*!< Packets will be sent interleaved between the channels in the group */
|
||||
#define ESP_BLE_ISO_PACKING_INTERLEAVED BT_ISO_PACKING_INTERLEAVED
|
||||
|
||||
/*!< Packets may be framed or unframed */
|
||||
#define ESP_BLE_ISO_FRAMING_UNFRAMED BT_ISO_FRAMING_UNFRAMED
|
||||
/*!< Packets are always framed */
|
||||
#define ESP_BLE_ISO_FRAMING_FRAMED BT_ISO_FRAMING_FRAMED
|
||||
|
||||
/*!< Maximum number of isochronous channels in a single group */
|
||||
#define ESP_BLE_ISO_MAX_GROUP_ISO_COUNT BT_ISO_MAX_GROUP_ISO_COUNT
|
||||
|
||||
/*!< Minimum SDU size */
|
||||
#define ESP_BLE_ISO_MIN_SDU BT_ISO_MIN_SDU
|
||||
/*!< Maximum SDU size */
|
||||
#define ESP_BLE_ISO_MAX_SDU BT_ISO_MAX_SDU
|
||||
|
||||
/*!< Minimum PDU size */
|
||||
#define ESP_BLE_ISO_CONNECTED_PDU_MIN BT_ISO_CONNECTED_PDU_MIN
|
||||
/*!< Minimum PDU size */
|
||||
#define ESP_BLE_ISO_BROADCAST_PDU_MIN BT_ISO_BROADCAST_PDU_MIN
|
||||
/*!< Maximum PDU size */
|
||||
#define ESP_BLE_ISO_PDU_MAX BT_ISO_PDU_MAX
|
||||
|
||||
/*!< Minimum burst number */
|
||||
#define ESP_BLE_ISO_BN_MIN BT_ISO_BN_MIN
|
||||
/*!< Maximum burst number */
|
||||
#define ESP_BLE_ISO_BN_MAX BT_ISO_BN_MAX
|
||||
|
||||
/*!< Minimum flush timeout */
|
||||
#define ESP_BLE_ISO_FT_MIN BT_ISO_FT_MIN
|
||||
/*!< Maximum flush timeout */
|
||||
#define ESP_BLE_ISO_FT_MAX BT_ISO_FT_MAX
|
||||
|
||||
/*!< Minimum number of subevents */
|
||||
#define ESP_BLE_ISO_NSE_MIN BT_ISO_NSE_MIN
|
||||
/*!< Maximum number of subevents */
|
||||
#define ESP_BLE_ISO_NSE_MAX BT_ISO_NSE_MAX
|
||||
|
||||
/*!< Minimum BIG sync timeout value (N * 10 ms) */
|
||||
#define ESP_BLE_ISO_SYNC_TIMEOUT_MIN BT_ISO_SYNC_TIMEOUT_MIN
|
||||
/*!< Maximum BIG sync timeout value (N * 10 ms) */
|
||||
#define ESP_BLE_ISO_SYNC_TIMEOUT_MAX BT_ISO_SYNC_TIMEOUT_MAX
|
||||
|
||||
/*!< Controller controlled maximum subevent count value */
|
||||
#define ESP_BLE_ISO_SYNC_MSE_ANY BT_ISO_SYNC_MSE_ANY
|
||||
/*!< Minimum BIG sync maximum subevent count value */
|
||||
#define ESP_BLE_ISO_SYNC_MSE_MIN BT_ISO_SYNC_MSE_MIN
|
||||
/*!< Maximum BIG sync maximum subevent count value */
|
||||
#define ESP_BLE_ISO_SYNC_MSE_MAX BT_ISO_SYNC_MSE_MAX
|
||||
|
||||
/*!< Minimum connected ISO retransmission value */
|
||||
#define ESP_BLE_ISO_CONNECTED_RTN_MIN BT_ISO_CONNECTED_RTN_MIN
|
||||
/*!< Maximum connected ISO retransmission value */
|
||||
#define ESP_BLE_ISO_CONNECTED_RTN_MAX BT_ISO_CONNECTED_RTN_MAX
|
||||
/*!< Minimum broadcast ISO retransmission value */
|
||||
#define ESP_BLE_ISO_BROADCAST_RTN_MIN BT_ISO_BROADCAST_RTN_MIN
|
||||
/*!< Maximum broadcast ISO retransmission value */
|
||||
#define ESP_BLE_ISO_BROADCAST_RTN_MAX BT_ISO_BROADCAST_RTN_MAX
|
||||
|
||||
/*!< Broadcast code size */
|
||||
#define ESP_BLE_ISO_BROADCAST_CODE_SIZE BT_ISO_BROADCAST_CODE_SIZE
|
||||
|
||||
/*!< Lowest BIS index */
|
||||
#define ESP_BLE_ISO_BIS_INDEX_MIN BT_ISO_BIS_INDEX_MIN
|
||||
/*!< Highest BIS index */
|
||||
#define ESP_BLE_ISO_BIS_INDEX_MAX BT_ISO_BIS_INDEX_MAX
|
||||
|
||||
/*!< Minimum Immediate Repetition Count */
|
||||
#define ESP_BLE_ISO_IRC_MIN BT_ISO_IRC_MIN
|
||||
/*!< Maximum Immediate Repetition Count */
|
||||
#define ESP_BLE_ISO_IRC_MAX BT_ISO_IRC_MAX
|
||||
|
||||
/*!< Minimum pre-transmission offset */
|
||||
#define ESP_BLE_ISO_PTO_MIN BT_ISO_PTO_MIN
|
||||
/*!< Maximum pre-transmission offset */
|
||||
#define ESP_BLE_ISO_PTO_MAX BT_ISO_PTO_MAX
|
||||
|
||||
/*!< No subinterval */
|
||||
#define ESP_BLE_ISO_SUBINTERVAL_NONE BT_ISO_SUBINTERVAL_NONE
|
||||
/*!< Unknown subinterval */
|
||||
#define ESP_BLE_ISO_SUBINTERVAL_UNKNOWN BT_ISO_SUBINTERVAL_UNKNOWN
|
||||
/*!< Minimum subinterval in microseconds */
|
||||
#define ESP_BLE_ISO_SUBINTERVAL_MIN BT_ISO_SUBINTERVAL_MIN
|
||||
/*!< Maximum subinterval in microseconds */
|
||||
#define ESP_BLE_ISO_SUBINTERVAL_MAX BT_ISO_SUBINTERVAL_MAX
|
||||
|
||||
/*!< Audio Input (Host to Controller) Data Path Direction */
|
||||
#define ESP_BLE_ISO_DATA_PATH_DIR_INPUT BT_HCI_DATAPATH_DIR_HOST_TO_CTLR
|
||||
/*!< Audio Output (Controller to Host) Data Path Direction */
|
||||
#define ESP_BLE_ISO_DATA_PATH_DIR_OUTPUT BT_HCI_DATAPATH_DIR_CTLR_TO_HOST
|
||||
|
||||
/*!< Value to set the ISO data path over HCI */
|
||||
#define ESP_BLE_ISO_DATA_PATH_HCI BT_ISO_DATA_PATH_HCI
|
||||
|
||||
/*!< Transparent Coding Format */
|
||||
#define ESP_BLE_ISO_CODING_FORMAT_TRANSPARENT BT_HCI_CODING_FORMAT_TRANSPARENT
|
||||
/*!< LC3 Coding Format */
|
||||
#define ESP_BLE_ISO_CODING_FORMAT_LC3 BT_HCI_CODING_FORMAT_LC3
|
||||
|
||||
/*!< The ISO packet is valid */
|
||||
#define ESP_BLE_ISO_FLAGS_VALID BT_ISO_FLAGS_VALID
|
||||
/*!< The ISO packet may possibly contain errors */
|
||||
#define ESP_BLE_ISO_FLAGS_ERROR BT_ISO_FLAGS_ERROR
|
||||
/*!< The ISO packet was lost */
|
||||
#define ESP_BLE_ISO_FLAGS_LOST BT_ISO_FLAGS_LOST
|
||||
/*!< Timestamp is valid */
|
||||
#define ESP_BLE_ISO_FLAGS_TS BT_ISO_FLAGS_TS
|
||||
|
||||
/*!< LE 1M PHY */
|
||||
#define ESP_BLE_ISO_PHY_1M BT_GAP_LE_PHY_1M
|
||||
/*!< LE 2M PHY */
|
||||
#define ESP_BLE_ISO_PHY_2M BT_GAP_LE_PHY_2M
|
||||
/*!< LE Coded PHY, coding scheme not specified */
|
||||
#define ESP_BLE_ISO_PHY_CODED BT_GAP_LE_PHY_CODED
|
||||
|
||||
/*!< Unknown */
|
||||
#define ESP_BLE_ISO_SCA_UNKNOWN BT_GAP_SCA_UNKNOWN
|
||||
/*!< 251 ppm to 500 ppm */
|
||||
#define ESP_BLE_ISO_SCA_251_500 BT_GAP_SCA_251_500
|
||||
/*!< 151 ppm to 250 ppm */
|
||||
#define ESP_BLE_ISO_SCA_151_250 BT_GAP_SCA_151_250
|
||||
/*!< 101 ppm to 150 ppm */
|
||||
#define ESP_BLE_ISO_SCA_101_150 BT_GAP_SCA_101_150
|
||||
/*!< 76 ppm to 100 ppm */
|
||||
#define ESP_BLE_ISO_SCA_76_100 BT_GAP_SCA_76_100
|
||||
/*!< 51 ppm to 75 ppm */
|
||||
#define ESP_BLE_ISO_SCA_51_75 BT_GAP_SCA_51_75
|
||||
/*!< 31 ppm to 50 ppm */
|
||||
#define ESP_BLE_ISO_SCA_31_50 BT_GAP_SCA_31_50
|
||||
/*!< 21 ppm to 30 ppm */
|
||||
#define ESP_BLE_ISO_SCA_21_30 BT_GAP_SCA_21_30
|
||||
/*!< 0 ppm to 20 ppm */
|
||||
#define ESP_BLE_ISO_SCA_0_20 BT_GAP_SCA_0_20
|
||||
|
||||
/*!< Security Level 1: No encryption and no authentication */
|
||||
#define ESP_BLE_ISO_SECURITY_NONE BT_SECURITY_L1
|
||||
/*!< Security Level 2: Encryption and no authentication (no MITM) */
|
||||
#define ESP_BLE_ISO_SECURITY_NO_MITM BT_SECURITY_L2
|
||||
/*!< Security Level 3: Encryption and authentication (MITM) */
|
||||
#define ESP_BLE_ISO_SECURITY_MITM BT_SECURITY_L3
|
||||
|
||||
/** Connection structure. */
|
||||
typedef struct bt_conn esp_ble_conn_t;
|
||||
|
||||
/** ISO Channel structure. */
|
||||
typedef struct bt_iso_chan esp_ble_iso_chan_t;
|
||||
|
||||
/** ISO Channel operations structure. */
|
||||
typedef struct bt_iso_chan_ops esp_ble_iso_chan_ops_t;
|
||||
|
||||
/** ISO Channel QoS structure. */
|
||||
typedef struct bt_iso_chan_qos esp_ble_iso_chan_qos_t;
|
||||
|
||||
/** ISO Channel IO QoS structure. */
|
||||
typedef struct bt_iso_chan_io_qos esp_ble_iso_chan_io_qos_t;
|
||||
|
||||
/** ISO Channel Data Path structure. */
|
||||
typedef struct bt_iso_chan_path esp_ble_iso_chan_path_t;
|
||||
|
||||
/** Connected Isochronous Group (CIG). */
|
||||
typedef struct bt_iso_cig esp_ble_iso_cig_t;
|
||||
|
||||
/** Connected Isochronous Group (CIG) parameters. */
|
||||
typedef struct bt_iso_cig_param esp_ble_iso_cig_param_t;
|
||||
|
||||
/** ISO connection parameters structure. */
|
||||
typedef struct bt_iso_connect_param esp_ble_iso_connect_param_t;
|
||||
|
||||
/** ISO Accept Info Structure. */
|
||||
typedef struct bt_iso_accept_info esp_ble_iso_accept_info_t;
|
||||
|
||||
/** ISO Server structure. */
|
||||
typedef struct bt_iso_server esp_ble_iso_server_t;
|
||||
|
||||
/** ISO Unicast Info Structure. */
|
||||
typedef struct bt_iso_unicast_info esp_ble_iso_unicast_info_t;
|
||||
|
||||
/** ISO Unicast TX Info Structure. */
|
||||
typedef struct bt_iso_unicast_tx_info esp_ble_iso_unicast_tx_info_t;
|
||||
|
||||
/** ISO Broadcast callbacks */
|
||||
typedef struct bt_iso_big_cb esp_ble_iso_big_cb_t;
|
||||
|
||||
/** Broadcast Isochronous Group (BIG). */
|
||||
typedef struct bt_iso_big esp_ble_iso_big_t;
|
||||
|
||||
/** Broadcast Isochronous Group (BIG) creation parameters. */
|
||||
typedef struct bt_iso_big_create_param esp_ble_iso_big_create_param_t;
|
||||
|
||||
/** Broadcast Isochronous Group (BIG) Sync Parameters. */
|
||||
typedef struct bt_iso_big_sync_param esp_ble_iso_big_sync_param_t;
|
||||
|
||||
/** Broadcast Isochronous Group (BIG) information. */
|
||||
typedef struct bt_iso_biginfo esp_ble_iso_biginfo_t;
|
||||
|
||||
/** ISO Broadcaster Info Structure. */
|
||||
typedef struct bt_iso_broadcaster_info esp_ble_iso_broadcaster_info_t;
|
||||
|
||||
/** ISO Synchronized Receiver Info Structure. */
|
||||
typedef struct bt_iso_sync_receiver_info esp_ble_iso_sync_receiver_info_t;
|
||||
|
||||
/** ISO channel Info Structure. */
|
||||
typedef struct bt_iso_info esp_ble_iso_info_t;
|
||||
|
||||
/** ISO Meta Data structure for received ISO packets. */
|
||||
typedef struct bt_iso_recv_info esp_ble_iso_recv_info_t;
|
||||
|
||||
/** ISO Meta Data structure for transmitted ISO packets. */
|
||||
typedef struct bt_iso_tx_info esp_ble_iso_tx_info_t;
|
||||
|
||||
/** ISO Unicast & Broadcast TX Callback Info Structure. */
|
||||
typedef struct bt_iso_tx_cb_info esp_ble_iso_tx_cb_info_t;
|
||||
|
||||
/** Extended advertising information structure */
|
||||
typedef struct {
|
||||
uint8_t adv_handle; /*!< Handle for the advertising set */
|
||||
} esp_ble_iso_ext_adv_info_t;
|
||||
|
||||
/**
|
||||
* @brief Helper for parsing length-type-value data.
|
||||
*
|
||||
* @param ltv Length-type-value (LTV) encoded data.
|
||||
* @param size Size of the @p ltv data.
|
||||
* @param func Callback function which will be called for each element
|
||||
* that's found in the data. The callback should return
|
||||
* true to continue parsing, or false to stop parsing.
|
||||
* @param user_data User data to be passed to the callback.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_iso_data_parse(const uint8_t ltv[], size_t size,
|
||||
bool (*func)(uint8_t type,
|
||||
const uint8_t *data,
|
||||
uint8_t data_len,
|
||||
void *user_data),
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Register an ISO server.
|
||||
*
|
||||
* @param server Pointer to the ISO server structure.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_iso_server_register(esp_ble_iso_server_t *server);
|
||||
|
||||
/**
|
||||
* @brief Unregister an ISO server.
|
||||
*
|
||||
* @param server Pointer to the ISO server structure.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_iso_server_unregister(esp_ble_iso_server_t *server);
|
||||
|
||||
/**
|
||||
* @brief Create a Connected ISO Group (CIG).
|
||||
*
|
||||
* @param param Parameters for CIG creation.
|
||||
* @param out_cig Pointer to store created CIG.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_iso_cig_create(esp_ble_iso_cig_param_t *param,
|
||||
esp_ble_iso_cig_t **out_cig);
|
||||
|
||||
/**
|
||||
* @brief Reconfigure a Connected ISO Group.
|
||||
*
|
||||
* @param cig Pointer to the CIG to reconfigure.
|
||||
* @param param New parameters for the CIG.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_iso_cig_reconfigure(esp_ble_iso_cig_t *cig,
|
||||
esp_ble_iso_cig_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief Terminate a Connected ISO Group.
|
||||
*
|
||||
* @param cig Pointer to the CIG to terminate.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_iso_cig_terminate(esp_ble_iso_cig_t *cig);
|
||||
|
||||
/**
|
||||
* @brief Connect ISO channels.
|
||||
*
|
||||
* @param param Connection parameters.
|
||||
* @param conn_handle Connection handle.
|
||||
* @param count Number of channels to connect.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_iso_chan_connect(esp_ble_iso_connect_param_t *param,
|
||||
uint16_t conn_handle, size_t count);
|
||||
|
||||
/**
|
||||
* @brief Disconnect an ISO channel.
|
||||
*
|
||||
* @param chan Pointer to the ISO channel.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_iso_chan_disconnect(esp_ble_iso_chan_t *chan);
|
||||
|
||||
/**
|
||||
* @brief Set up the ISO data path for an ISO channel.
|
||||
*
|
||||
* The channel must be associated with a BIS or CIS handle first which it is when the
|
||||
* esp_ble_iso_chan_ops_t.connected() callback is called.
|
||||
*
|
||||
* @param chan The channel to setup the ISO data path for.
|
||||
* @param dir The direction to setup, either ESP_BLE_ISO_DATA_PATH_DIR_INPUT
|
||||
* or ESP_BLE_ISO_DATA_PATH_DIR_OUTPUT.
|
||||
* For ISO broadcast channels this can only be
|
||||
* ESP_BLE_ISO_DATA_PATH_DIR_INPUT, and for ISO sync receiver
|
||||
* channels this can only be ESP_BLE_ISO_DATA_PATH_DIR_OUTPUT.
|
||||
* @param path The data path.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_iso_setup_data_path(const esp_ble_iso_chan_t *chan, uint8_t dir,
|
||||
const esp_ble_iso_chan_path_t *path);
|
||||
|
||||
/**
|
||||
* @brief Removes the ISO data path for an ISO channel.
|
||||
*
|
||||
* Removes the ISO data path configured by esp_ble_iso_setup_data_path() for the provided
|
||||
* @p dir.
|
||||
*
|
||||
* The data paths of CIS for Peripherals are deleted by the controller, and thus it is not
|
||||
* necessary (or possible) to remove data paths of CIS after they have disconnected for a
|
||||
* Peripheral, as per Bluetooth Core specification 6.0, Vol 4, Part E, Section 7.7.5.
|
||||
* The data paths for CIS for a Central remain valid, even after a disconnection, and thus
|
||||
* a Central device should call bt_iso_remove_data_path() on disconnect if it no longer
|
||||
* wants to use that CIS.
|
||||
* All data paths created by a Central are removed when the CIG is removed with
|
||||
* esp_ble_iso_cig_terminate().
|
||||
*
|
||||
* Any data paths associated with an ISO Sync Receiver BIG are removed by the controller
|
||||
* when the BIG sync is lost or terminated, and thus it is not necessary (or possible) to
|
||||
* remove data paths of ISO channels associated with a BIG for a Sync Receiver, as per
|
||||
* Bluetooth Core specification 6.0, Vol 4, Part E, Section 7.7.65.30.
|
||||
*
|
||||
* All data paths associated with an ISO Broadcaster BIG are removed when the BIG is
|
||||
* terminated by esp_ble_iso_big_terminate(), and thus it is not necessary (or possible)
|
||||
* to remove data paths of ISO channels associated with a BIG for a Broadcaster,
|
||||
* as per Bluetooth Core specification 6.0, Vol 4, Part E, Section 7.8.105.
|
||||
*
|
||||
* @param chan The channel to setup the ISO data path for.
|
||||
* @param dir The direction to setup, either ESP_BLE_ISO_DATA_PATH_DIR_INPUT or
|
||||
* ESP_BLE_ISO_DATA_PATH_DIR_OUTPUT. For ISO broadcast channels this
|
||||
* can only be ESP_BLE_ISO_DATA_PATH_DIR_INPUT, and for ISO sync
|
||||
* receiver channels this can only be ESP_BLE_ISO_DATA_PATH_DIR_OUTPUT.
|
||||
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_iso_remove_data_path(const esp_ble_iso_chan_t *chan, uint8_t dir);
|
||||
|
||||
/**
|
||||
* @brief Registers callbacks for Broadcast Sources.
|
||||
*
|
||||
* @param cb Pointer to the callback structure.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_iso_big_register_cb(esp_ble_iso_big_cb_t *cb);
|
||||
|
||||
/**
|
||||
* @brief Add extended advertising for BIG.
|
||||
*
|
||||
* @param info Extended advertising information.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_iso_big_ext_adv_add(esp_ble_iso_ext_adv_info_t *info);
|
||||
|
||||
/**
|
||||
* @brief Delete extended advertising for BIG.
|
||||
*
|
||||
* @param info Extended advertising information.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_iso_big_ext_adv_delete(esp_ble_iso_ext_adv_info_t *info);
|
||||
|
||||
/**
|
||||
* @brief Create a Broadcast ISO Group (BIG).
|
||||
*
|
||||
* @param adv_handle Advertising handle.
|
||||
* @param param Parameters for BIG creation.
|
||||
* @param out_big Pointer to store created BIG.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_iso_big_create(uint8_t adv_handle,
|
||||
esp_ble_iso_big_create_param_t *param,
|
||||
esp_ble_iso_big_t **out_big);
|
||||
|
||||
/**
|
||||
* @brief Synchronize with a Broadcast ISO Group.
|
||||
*
|
||||
* @param sync_handle Sync handle.
|
||||
* @param param Sync parameters.
|
||||
* @param out_big Pointer to store synchronized BIG.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_iso_big_sync(uint16_t sync_handle,
|
||||
esp_ble_iso_big_sync_param_t *param,
|
||||
esp_ble_iso_big_t **out_big);
|
||||
|
||||
/**
|
||||
* @brief Terminate a Broadcast ISO Group.
|
||||
*
|
||||
* @param big Pointer to the BIG to terminate.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_iso_big_terminate(esp_ble_iso_big_t *big);
|
||||
|
||||
/**
|
||||
* @brief Get ISO channel information.
|
||||
*
|
||||
* @param chan Pointer to the ISO channel.
|
||||
* @param info Pointer to store channel information.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_iso_chan_get_info(esp_ble_iso_chan_t *chan,
|
||||
esp_ble_iso_info_t *info);
|
||||
|
||||
/**
|
||||
* @brief Get TX sync information for an ISO channel.
|
||||
*
|
||||
* @param chan Pointer to the ISO channel.
|
||||
* @param info Pointer to store TX sync information.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_iso_chan_get_tx_sync(esp_ble_iso_chan_t *chan,
|
||||
esp_ble_iso_tx_info_t *info);
|
||||
|
||||
/**
|
||||
* @brief Send data over an ISO channel.
|
||||
*
|
||||
* @param chan Pointer to the ISO channel.
|
||||
* @param sdu Pointer to the SDU data.
|
||||
* @param sdu_len Length of the SDU.
|
||||
* @param seq_num Sequence number.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_iso_chan_send(esp_ble_iso_chan_t *chan,
|
||||
const uint8_t *sdu,
|
||||
uint16_t sdu_len,
|
||||
uint16_t seq_num);
|
||||
|
||||
/**
|
||||
* @brief Send timestamped data over an ISO channel.
|
||||
*
|
||||
* @param chan Pointer to the ISO channel.
|
||||
* @param sdu Pointer to the SDU data.
|
||||
* @param sdu_len Length of the SDU.
|
||||
* @param seq_num Sequence number.
|
||||
* @param ts Timestamp.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_iso_chan_send_ts(esp_ble_iso_chan_t *chan,
|
||||
const uint8_t *sdu,
|
||||
uint16_t sdu_len,
|
||||
uint16_t seq_num,
|
||||
uint32_t ts);
|
||||
|
||||
/*!< ISO GAP Extended Scan Recv event */
|
||||
#define ESP_BLE_ISO_GAP_EVENT_EXT_SCAN_RECV BT_LE_GAP_APP_EVENT_EXT_SCAN_RECV
|
||||
/*!< ISO GAP Periodic Sync Established event */
|
||||
#define ESP_BLE_ISO_GAP_EVENT_PA_SYNC BT_LE_GAP_APP_EVENT_PA_SYNC
|
||||
/*!< ISO GAP Periodic Sync Lost event */
|
||||
#define ESP_BLE_ISO_GAP_EVENT_PA_SYNC_LOST BT_LE_GAP_APP_EVENT_PA_SYNC_LOST
|
||||
/*!< ISO GAP Connection Complete event */
|
||||
#define ESP_BLE_ISO_GAP_EVENT_ACL_CONNECT BT_LE_GAP_APP_EVENT_ACL_CONNECT
|
||||
/*!< ISO GAP Disconnection Complete event */
|
||||
#define ESP_BLE_ISO_GAP_EVENT_ACL_DISCONNECT BT_LE_GAP_APP_EVENT_ACL_DISCONNECT
|
||||
/*!< ISO GAP Security Changed event */
|
||||
#define ESP_BLE_ISO_GAP_EVENT_SECURITY_CHANGE BT_LE_GAP_APP_EVENT_SECURITY_CHANGE
|
||||
/*!< ISO GAP BIGInfo Adv Report event */
|
||||
#define ESP_BLE_ISO_GAP_EVENT_BIGINFO_RECV BT_LE_GAP_APP_EVENT_BIGINFO_RECV
|
||||
/** ISO GAP application event structure */
|
||||
typedef struct bt_le_gap_app_event esp_ble_iso_gap_app_event_t;
|
||||
|
||||
/** ISO initialization information structure */
|
||||
typedef struct {
|
||||
bt_le_gap_app_cb gap_cb; /*!< GAP event callbacks */
|
||||
} esp_ble_iso_init_info_t;
|
||||
|
||||
/**
|
||||
* @brief Post an application-layer GAP event for ISO internal usage.
|
||||
*
|
||||
* @note This function is only needed while using NimBLE Host.
|
||||
*
|
||||
* @param type Event type.
|
||||
* @param param Event parameters.
|
||||
*/
|
||||
void esp_ble_iso_gap_app_post_event(uint8_t type, void *param);
|
||||
|
||||
/**
|
||||
* @brief Initialize ISO common functionality.
|
||||
*
|
||||
* @param info Initialization information.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_iso_common_init(esp_ble_iso_init_info_t *info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_BLE_ISO_COMMON_API_H_ */
|
||||
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/bluetooth/buf.h>
|
||||
#include <zephyr/bluetooth/hci.h>
|
||||
|
||||
#include <../host/hci_core.h>
|
||||
#include <../host/iso_internal.h>
|
||||
|
||||
#include "host/ble_gap.h"
|
||||
#include "services/gap/ble_svc_gap.h"
|
||||
|
||||
#include "common/host.h"
|
||||
#include "common/app/gap.h"
|
||||
|
||||
void bt_le_nimble_gap_post_event(void *param)
|
||||
{
|
||||
struct bt_le_gap_app_param *qev;
|
||||
struct ble_gap_conn_desc desc;
|
||||
struct ble_gap_event *ev;
|
||||
int err;
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
ev = param;
|
||||
|
||||
if (ev->type != BLE_GAP_EVENT_EXT_DISC &&
|
||||
ev->type != BLE_GAP_EVENT_PERIODIC_REPORT) {
|
||||
LOG_DBG("[N]PostGapEvt[%u]", ev->type);
|
||||
}
|
||||
|
||||
/* TODO:
|
||||
* - Limit the adv report posted to ISO task;
|
||||
* - Limit the extended adv report posted to ISO task;
|
||||
* - Limit the periodic adv report posted to ISO task;
|
||||
* - E.g. If the adv report contains any information interested by LE Audio.
|
||||
*/
|
||||
|
||||
switch (ev->type) {
|
||||
case BLE_GAP_EVENT_EXT_DISC:
|
||||
qev->type = BT_LE_GAP_APP_PARAM_EXT_SCAN_RECV;
|
||||
|
||||
qev->ext_scan_recv.event_type = (ev->ext_disc.data_status << 5) | ev->ext_disc.props;
|
||||
qev->ext_scan_recv.addr.type = ev->ext_disc.addr.type;
|
||||
memcpy(qev->ext_scan_recv.addr.val, ev->ext_disc.addr.val, BT_ADDR_SIZE);
|
||||
qev->ext_scan_recv.rssi = ev->ext_disc.rssi;
|
||||
qev->ext_scan_recv.tx_power = ev->ext_disc.tx_power;
|
||||
qev->ext_scan_recv.sid = ev->ext_disc.sid;
|
||||
qev->ext_scan_recv.pri_phy = ev->ext_disc.prim_phy;
|
||||
qev->ext_scan_recv.sec_phy = ev->ext_disc.sec_phy;
|
||||
qev->ext_scan_recv.per_adv_itvl = ev->ext_disc.periodic_adv_itvl;
|
||||
qev->ext_scan_recv.data_len = ev->ext_disc.length_data;
|
||||
|
||||
if (qev->ext_scan_recv.data_len) {
|
||||
qev->ext_scan_recv.data = calloc(1, qev->ext_scan_recv.data_len);
|
||||
assert(qev->ext_scan_recv.data);
|
||||
|
||||
memcpy(qev->ext_scan_recv.data, ev->ext_disc.data, qev->ext_scan_recv.data_len);
|
||||
}
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVENT_PERIODIC_SYNC:
|
||||
qev->type = BT_LE_GAP_APP_PARAM_PA_SYNC;
|
||||
|
||||
qev->pa_sync.status = ev->periodic_sync.status;
|
||||
qev->pa_sync.sync_handle = ev->periodic_sync.sync_handle;
|
||||
qev->pa_sync.addr.type = ev->periodic_sync.adv_addr.type;
|
||||
memcpy(qev->pa_sync.addr.val, ev->periodic_sync.adv_addr.val, BT_ADDR_SIZE);
|
||||
qev->pa_sync.sid = ev->periodic_sync.sid;
|
||||
qev->pa_sync.adv_phy = ev->periodic_sync.adv_phy;
|
||||
qev->pa_sync.per_adv_itvl = ev->periodic_sync.per_adv_ival;
|
||||
qev->pa_sync.adv_ca = ev->periodic_sync.adv_clk_accuracy;
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVENT_PERIODIC_SYNC_LOST:
|
||||
qev->type = BT_LE_GAP_APP_PARAM_PA_SYNC_LOST;
|
||||
|
||||
qev->pa_sync_lost.sync_handle = ev->periodic_sync_lost.sync_handle;
|
||||
qev->pa_sync_lost.reason = ev->periodic_sync_lost.reason;
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVENT_PERIODIC_REPORT:
|
||||
qev->type = BT_LE_GAP_APP_PARAM_PA_SYNC_RECV;
|
||||
|
||||
qev->pa_sync_recv.sync_handle = ev->periodic_report.sync_handle;
|
||||
qev->pa_sync_recv.tx_power = ev->periodic_report.tx_power;
|
||||
qev->pa_sync_recv.rssi = ev->periodic_report.rssi;
|
||||
qev->pa_sync_recv.data_status = ev->periodic_report.data_status;
|
||||
qev->pa_sync_recv.data_len = ev->periodic_report.data_length;
|
||||
|
||||
if (qev->pa_sync_recv.data_len) {
|
||||
qev->pa_sync_recv.data = calloc(1, qev->pa_sync_recv.data_len);
|
||||
assert(qev->pa_sync_recv.data);
|
||||
|
||||
memcpy(qev->pa_sync_recv.data, ev->periodic_report.data, qev->pa_sync_recv.data_len);
|
||||
}
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVENT_CONNECT:
|
||||
qev->type = BT_LE_GAP_APP_PARAM_ACL_CONNECT;
|
||||
|
||||
qev->acl_connect.status = ev->connect.status;
|
||||
if (qev->acl_connect.status == 0) {
|
||||
err = ble_gap_conn_find(ev->connect.conn_handle, &desc);
|
||||
assert(err == 0);
|
||||
|
||||
qev->acl_connect.conn_handle = desc.conn_handle;
|
||||
qev->acl_connect.role = desc.role;
|
||||
qev->acl_connect.dst.type = desc.peer_id_addr.type;
|
||||
memcpy(qev->acl_connect.dst.val, desc.peer_id_addr.val, BT_ADDR_SIZE);
|
||||
}
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVENT_DISCONNECT:
|
||||
qev->type = BT_LE_GAP_APP_PARAM_ACL_DISCONNECT;
|
||||
|
||||
qev->acl_disconnect.conn_handle = ev->disconnect.conn.conn_handle;
|
||||
qev->acl_disconnect.reason = ev->disconnect.reason;
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVENT_ENC_CHANGE:
|
||||
qev->type = BT_LE_GAP_APP_PARAM_SECURITY_CHANGE;
|
||||
|
||||
qev->security_change.status = ev->enc_change.status;
|
||||
if (qev->security_change.status == 0) {
|
||||
err = ble_gap_conn_find(ev->enc_change.conn_handle, &desc);
|
||||
assert(err == 0);
|
||||
|
||||
qev->security_change.conn_handle = ev->enc_change.conn_handle;
|
||||
qev->security_change.role = desc.role;
|
||||
qev->security_change.sec_level = BT_SECURITY_L3;
|
||||
qev->security_change.dst.type = desc.peer_id_addr.type;
|
||||
memcpy(qev->security_change.dst.val, desc.peer_id_addr.val, BT_ADDR_SIZE);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
free(qev);
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
err = bt_le_iso_task_post(ISO_QUEUE_ITEM_TYPE_GAP_EVENT, qev, sizeof(*qev));
|
||||
if (err) {
|
||||
LOG_ERR("[N]GapPostEvtFail[%d][%u]", err, qev->type);
|
||||
goto free;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
free:
|
||||
switch (qev->type) {
|
||||
case BT_LE_GAP_APP_PARAM_EXT_SCAN_RECV:
|
||||
if (qev->ext_scan_recv.data) {
|
||||
free(qev->ext_scan_recv.data);
|
||||
qev->ext_scan_recv.data = NULL;
|
||||
}
|
||||
break;
|
||||
case BT_LE_GAP_APP_PARAM_PA_SYNC_RECV:
|
||||
if (qev->pa_sync_recv.data) {
|
||||
free(qev->pa_sync_recv.data);
|
||||
qev->pa_sync_recv.data = NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
free(qev);
|
||||
}
|
||||
|
||||
int bt_le_nimble_scan_start(const struct bt_le_scan_param *param, ble_gap_event_fn *cb)
|
||||
{
|
||||
struct ble_gap_disc_params scan_param = {0};
|
||||
|
||||
scan_param.itvl = param->interval;
|
||||
scan_param.window = param->window;
|
||||
scan_param.filter_policy = 0;
|
||||
scan_param.limited = 0;
|
||||
scan_param.passive = !param->type;
|
||||
scan_param.filter_duplicates = 0;
|
||||
|
||||
return ble_gap_disc(BLE_OWN_ADDR_PUBLIC, BLE_HS_FOREVER, &scan_param, cb, NULL);
|
||||
}
|
||||
|
||||
int bt_le_nimble_scan_stop(void)
|
||||
{
|
||||
return ble_gap_disc_cancel();
|
||||
}
|
||||
|
||||
int bt_le_nimble_iso_disconnect(uint16_t conn_handle, uint8_t reason)
|
||||
{
|
||||
return ble_gap_iso_disconnect(conn_handle, reason);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef HOST_NIMBLE_APP_GAP_H_
|
||||
#define HOST_NIMBLE_APP_GAP_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "host/ble_gap.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void bt_le_nimble_gap_post_event(void *param);
|
||||
|
||||
int bt_le_nimble_scan_start(const struct bt_le_scan_param *param, ble_gap_event_fn *cb);
|
||||
|
||||
int bt_le_nimble_scan_stop(void);
|
||||
|
||||
int bt_le_nimble_iso_disconnect(uint16_t conn_handle, uint8_t reason);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HOST_NIMBLE_APP_GAP_H_ */
|
||||
@@ -0,0 +1,525 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <zephyr/autoconf.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/bluetooth/bluetooth.h>
|
||||
#include <zephyr/bluetooth/conn.h>
|
||||
#include <zephyr/bluetooth/gatt.h>
|
||||
#include <zephyr/bluetooth/common/bt_str.h>
|
||||
|
||||
#include <../host/conn_internal.h>
|
||||
|
||||
#include "host/ble_hs.h"
|
||||
#include "host/ble_att.h"
|
||||
#include "host/ble_gatt.h"
|
||||
#include "host/ble_hs_mbuf.h"
|
||||
|
||||
#include "common/host.h"
|
||||
#include "common/app/gatt.h"
|
||||
|
||||
void bt_le_nimble_gatt_post_event(void *param)
|
||||
{
|
||||
struct bt_le_gatt_event_param *qev;
|
||||
struct ble_gap_event *ev;
|
||||
int err;
|
||||
|
||||
ev = param;
|
||||
|
||||
/* LOG_DBG("[N]PostGattEvt[%u]", ev->type); */
|
||||
|
||||
/* Currently we only handle this event for indication */
|
||||
if (ev->type == BLE_GAP_EVENT_NOTIFY_TX && ev->notify_tx.indication == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
switch (ev->type) {
|
||||
case BLE_GAP_EVENT_MTU:
|
||||
qev->type = BT_LE_GATT_MTU_CHANGE_EVENT;
|
||||
|
||||
qev->gatt_mtu_change.conn_handle = ev->mtu.conn_handle;
|
||||
qev->gatt_mtu_change.mtu = ev->mtu.value;
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVENT_SUBSCRIBE:
|
||||
qev->type = BT_LE_GATTS_SUBSCRIBE_EVENT;
|
||||
|
||||
qev->gatts_subscribe.conn_handle = ev->subscribe.conn_handle;
|
||||
qev->gatts_subscribe.attr_handle = ev->subscribe.attr_handle;
|
||||
qev->gatts_subscribe.prev_notify = ev->subscribe.prev_notify;
|
||||
qev->gatts_subscribe.cur_notify = ev->subscribe.cur_notify;
|
||||
qev->gatts_subscribe.prev_indicate = ev->subscribe.prev_indicate;
|
||||
qev->gatts_subscribe.cur_indicate = ev->subscribe.cur_indicate;
|
||||
qev->gatts_subscribe.reason = ev->subscribe.reason;
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVENT_NOTIFY_RX:
|
||||
qev->type = BT_LE_GATTC_NOTIFY_RX_EVENT;
|
||||
|
||||
qev->gattc_notify_rx.conn_handle = ev->notify_rx.conn_handle;
|
||||
qev->gattc_notify_rx.attr_handle = ev->notify_rx.attr_handle;
|
||||
qev->gattc_notify_rx.is_notify = (ev->notify_rx.indication == 0);
|
||||
|
||||
if (ev->notify_rx.om && OS_MBUF_PKTLEN(ev->notify_rx.om)) {
|
||||
uint16_t total_len = OS_MBUF_PKTLEN(ev->notify_rx.om);
|
||||
qev->gattc_notify_rx.len = total_len;
|
||||
|
||||
qev->gattc_notify_rx.value = calloc(1, total_len);
|
||||
assert(qev->gattc_notify_rx.value);
|
||||
|
||||
os_mbuf_copydata(ev->notify_rx.om, 0, total_len, qev->gattc_notify_rx.value);
|
||||
}
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVENT_NOTIFY_TX:
|
||||
qev->type = BT_LE_GATTS_NOTIFY_TX_EVENT;
|
||||
|
||||
qev->gatts_notify_tx.is_notify = (ev->notify_tx.indication == 0);
|
||||
qev->gatts_notify_tx.conn_handle = ev->notify_tx.conn_handle;
|
||||
qev->gatts_notify_tx.attr_handle = ev->notify_tx.attr_handle;
|
||||
qev->gatts_notify_tx.status = ev->notify_tx.status;
|
||||
break;
|
||||
|
||||
default:
|
||||
free(qev);
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
err = bt_le_iso_task_post(ISO_QUEUE_ITEM_TYPE_GATT_EVENT, qev, sizeof(*qev));
|
||||
if (err) {
|
||||
LOG_ERR("[N]GattPostEvtFail[%d][%u]", err, qev->type);
|
||||
|
||||
if (qev->type == BT_LE_GATTC_NOTIFY_RX_EVENT &&
|
||||
qev->gattc_notify_rx.value) {
|
||||
free(qev->gattc_notify_rx.value);
|
||||
qev->gattc_notify_rx.value = NULL;
|
||||
}
|
||||
|
||||
free(qev);
|
||||
}
|
||||
}
|
||||
|
||||
int bt_le_nimble_gatt_post_disc_event(uint16_t conn_handle, ble_uuid16_t *uuid,
|
||||
struct bt_gatt_discover_params *params,
|
||||
uint8_t type)
|
||||
{
|
||||
struct bt_le_gatt_event_param *qev;
|
||||
int err;
|
||||
|
||||
LOG_DBG("[N]GattcDiscHdlr[%u][%u]", conn_handle, type);
|
||||
|
||||
if (type == GATTC_DISC_TYPE_DUMMY || type >= GATTC_DISC_TYPE_MAX) {
|
||||
LOG_ERR("[N]InvDiscType[%u]", type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
qev->type = BT_LE_GATTC_DISCOVER_EVENT;
|
||||
|
||||
qev->gattc_discover.type = type;
|
||||
qev->gattc_discover.conn_handle = conn_handle;
|
||||
qev->gattc_discover.uuid = (uuid ? uuid->value : 0x0000);
|
||||
qev->gattc_discover.params = params;
|
||||
|
||||
err = bt_le_iso_task_post(ISO_QUEUE_ITEM_TYPE_GATT_EVENT, qev, sizeof(*qev));
|
||||
if (err) {
|
||||
LOG_ERR("[N]GattPostDiscEvtFail[%d][%u]", err, type);
|
||||
free(qev);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_le_nimble_gatt_post_disc_cmpl_event(uint16_t conn_handle, uint8_t status)
|
||||
{
|
||||
struct bt_le_gatt_event_param *qev;
|
||||
int err;
|
||||
|
||||
LOG_DBG("[N]GattcDiscCmplEvtHdlr[%u][%02x]", conn_handle, status);
|
||||
|
||||
qev = calloc(1, sizeof(*qev));
|
||||
assert(qev);
|
||||
|
||||
qev->type = BT_LE_GATTC_DISC_CMPL_EVENT;
|
||||
|
||||
qev->gattc_disc_cmpl.status = status;
|
||||
qev->gattc_disc_cmpl.conn_handle = conn_handle;
|
||||
|
||||
err = bt_le_iso_task_post(ISO_QUEUE_ITEM_TYPE_GATT_EVENT, qev, sizeof(*qev));
|
||||
if (err) {
|
||||
LOG_ERR("[N]GattPostDiscCmplEvtFail[%d][%u][%02x]", err, conn_handle, status);
|
||||
free(qev);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void handle_gatts_subscribe_event_safe(struct bt_le_gatts_subscribe_event *event)
|
||||
{
|
||||
/* LOG_DBG("[N]HdlGattsSubEvt[%u][%u][%u][%u][%02x]", */
|
||||
/* event->conn_handle, event->attr_handle, event->cur_notify, */
|
||||
/* event->cur_indicate, event->reason); */
|
||||
|
||||
/* Note:
|
||||
* For NimBLE Host, the attr_handle is the handle of characteristic value
|
||||
* declaration. For CCCD, its attr_handle shall be incremented with 1.
|
||||
*/
|
||||
bt_le_host_lock();
|
||||
|
||||
bt_gatts_sub_changed(event->conn_handle,
|
||||
event->attr_handle + 1,
|
||||
event->cur_notify,
|
||||
event->cur_indicate,
|
||||
event->reason);
|
||||
|
||||
bt_le_host_unlock();
|
||||
|
||||
bt_le_gatts_app_subscribe_event(event);
|
||||
}
|
||||
|
||||
static void handle_gattc_notify_rx_event_safe(struct bt_le_gattc_notify_rx_event *event)
|
||||
{
|
||||
struct bt_gatt_subscribe_params *params;
|
||||
struct gattc_sub *sub;
|
||||
struct bt_conn *conn;
|
||||
|
||||
LOG_DBG("[N]HdlGattcNtfRxEvt[%u][%u][%u]",
|
||||
event->conn_handle, event->attr_handle, event->len);
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(event->conn_handle);
|
||||
if (conn == NULL || conn->state != BT_CONN_CONNECTED) {
|
||||
LOG_ERR("[N]NotConn[%d]", __LINE__);
|
||||
goto end;
|
||||
}
|
||||
|
||||
sub = bt_gattc_sub_find(conn);
|
||||
if (sub == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER(&sub->list, params, node) {
|
||||
if (params->ccc_handle != BT_GATT_AUTO_DISCOVER_CCC_HANDLE &&
|
||||
params->value_handle == event->attr_handle) {
|
||||
if (params->notify) {
|
||||
params->notify(conn, params, event->value, event->len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
if (event->value) {
|
||||
free(event->value);
|
||||
}
|
||||
|
||||
bt_le_host_unlock();
|
||||
}
|
||||
|
||||
static void handle_gatts_notify_tx_event_safe(struct bt_le_gatts_notify_tx_event *event)
|
||||
{
|
||||
LOG_DBG("[N]HdlGattsNtfTxEvt[%u][%u][%u][%02x]",
|
||||
event->conn_handle, event->attr_handle, event->is_notify, event->status);
|
||||
|
||||
/* Currently we only handle this event for indication */
|
||||
if (event->is_notify) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* The event->status could be:
|
||||
* - 0: Indication is sent successfully;
|
||||
* - BLE_HS_EDONE: Confirm is received;
|
||||
* - BLE_HS_ENOTCONN: Not connected;
|
||||
* - BLE_HS_ETIMEOUT: ATT procedure times out.
|
||||
*/
|
||||
bt_le_host_lock();
|
||||
|
||||
bt_le_nimble_gatts_nrp_indicate_cb(event->conn_handle, event->attr_handle, event->status);
|
||||
|
||||
bt_le_host_unlock();
|
||||
}
|
||||
|
||||
void bt_le_nimble_gatt_handle_event(uint8_t *data, size_t data_len)
|
||||
{
|
||||
struct bt_le_gatt_event_param *param;
|
||||
|
||||
param = (struct bt_le_gatt_event_param *)data;
|
||||
|
||||
/* LOG_DBG("[N]HdlGattEvt[%u]", param->type); */
|
||||
|
||||
switch (param->type) {
|
||||
case BT_LE_GATT_MTU_CHANGE_EVENT:
|
||||
bt_le_gatt_app_mtu_change_event(param->gatt_mtu_change.conn_handle,
|
||||
param->gatt_mtu_change.mtu);
|
||||
break;
|
||||
|
||||
case BT_LE_GATTC_DISCOVER_EVENT:
|
||||
handle_gattc_db_disc_event_safe(¶m->gattc_discover);
|
||||
break;
|
||||
|
||||
case BT_LE_GATTC_DISC_CMPL_EVENT:
|
||||
bt_le_gattc_app_disc_cmpl_event(¶m->gattc_disc_cmpl);
|
||||
break;
|
||||
|
||||
case BT_LE_GATTS_SUBSCRIBE_EVENT:
|
||||
handle_gatts_subscribe_event_safe(¶m->gatts_subscribe);
|
||||
break;
|
||||
|
||||
case BT_LE_GATTC_NOTIFY_RX_EVENT:
|
||||
handle_gattc_notify_rx_event_safe(¶m->gattc_notify_rx);
|
||||
break;
|
||||
|
||||
case BT_LE_GATTS_NOTIFY_TX_EVENT:
|
||||
handle_gatts_notify_tx_event_safe(¶m->gatts_notify_tx);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
free(data);
|
||||
}
|
||||
|
||||
uint16_t bt_le_nimble_gatt_get_mtu(struct bt_conn *conn)
|
||||
{
|
||||
LOG_DBG("[N]GattGetMtu[%u]", conn->handle);
|
||||
|
||||
return ble_att_mtu(conn->handle);
|
||||
}
|
||||
|
||||
ssize_t bt_le_nimble_gatts_attr_read(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||
void *buf, uint16_t buf_len, uint16_t offset,
|
||||
const void *value, uint16_t value_len)
|
||||
{
|
||||
uint16_t len;
|
||||
|
||||
if (buf_len == UINT16_MAX) {
|
||||
/* TODO: A better solution for using a variable for the cb pointer */
|
||||
struct bt_le_nimble_gatt_read_cb *cb = buf;
|
||||
assert(cb->read_cb);
|
||||
|
||||
len = cb->read_cb(cb->read_arg, offset, value, value_len);
|
||||
} else {
|
||||
assert(attr);
|
||||
|
||||
LOG_DBG("[N]Hdl[%u]", attr->handle);
|
||||
|
||||
if (offset >= value_len) {
|
||||
LOG_WRN("[N]OffsetTooLarge[%u][%u]", offset, value_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = MIN(buf_len, value_len - offset);
|
||||
memcpy(buf, (uint8_t *)value + offset, len);
|
||||
}
|
||||
|
||||
LOG_DBG("[N]GattsAttrRd[%u]", len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int gatts_notify(struct bt_conn *conn, struct bt_gatt_notify_params *params)
|
||||
{
|
||||
struct notify_data data;
|
||||
struct bt_conn *conns;
|
||||
uint8_t conns_count;
|
||||
struct os_mbuf *om;
|
||||
int rc = 0;
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
data.attr = params->attr;
|
||||
data.handle = bt_gatt_attr_get_handle(data.attr);
|
||||
|
||||
/* Lookup UUID if it was given */
|
||||
if (params->uuid) {
|
||||
if (bt_gatts_find_attr_by_uuid(&data, params->uuid) == false) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
params->attr = data.attr;
|
||||
} else {
|
||||
if (data.handle == 0) {
|
||||
LOG_WRN("[N]DataHdlZero");
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if attribute is a characteristic then adjust the handle */
|
||||
if (bt_uuid_cmp(data.attr->uuid, BT_UUID_GATT_CHRC) == 0) {
|
||||
struct bt_gatt_chrc *chrc;
|
||||
|
||||
assert(data.attr->user_data);
|
||||
chrc = data.attr->user_data;
|
||||
|
||||
if ((chrc->properties & BT_GATT_CHRC_NOTIFY) == 0) {
|
||||
LOG_WRN("[N]NtfNotSupp[%u][%02x]", data.handle, chrc->properties);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
data.handle = bt_gatt_attr_value_handle(data.attr);
|
||||
|
||||
LOG_INF("[N]DataHdl[%u][%u]", data.attr->handle, data.handle);
|
||||
}
|
||||
|
||||
if (conn) {
|
||||
om = ble_hs_mbuf_from_flat(params->data, params->len);
|
||||
if (om == NULL) {
|
||||
LOG_ERR("[N]NoMemForNtf[%u]", params->len);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rc = ble_gatts_notify_custom(conn->handle, data.handle, om);
|
||||
if (rc && rc != BLE_HS_ENOTCONN) {
|
||||
LOG_ERR("[N]GattsNtfCustomFail[%d]", rc);
|
||||
}
|
||||
} else {
|
||||
bt_conn_get_acl_conns(&conns, &conns_count);
|
||||
|
||||
for (size_t i = 0; i < conns_count; i++) {
|
||||
if (conns[i].state == BT_CONN_CONNECTED) {
|
||||
om = ble_hs_mbuf_from_flat(params->data, params->len);
|
||||
if (om == NULL) {
|
||||
LOG_ERR("[N]NoMemForNtf[%u]", params->len);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rc = ble_gatts_notify_custom(conns[i].handle, data.handle, om);
|
||||
if (rc && rc != BLE_HS_ENOTCONN) {
|
||||
LOG_ERR("[N]GattsNtfCustomFail[%d]", rc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* For sending notifications to all connected peers, always return success */
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int bt_le_nimble_gatts_notify(struct bt_conn *conn, struct bt_gatt_notify_params *params)
|
||||
{
|
||||
LOG_DBG("[N]GattsNtf[%u]", conn ? conn->handle : UINT16_MAX);
|
||||
|
||||
return gatts_notify(conn, params);
|
||||
}
|
||||
|
||||
int bt_le_nimble_gatts_indicate(struct bt_conn *conn, struct bt_gatt_indicate_params *params)
|
||||
{
|
||||
LOG_DBG("[N]GattsInd[%u]", conn ? conn->handle : UINT16_MAX);
|
||||
|
||||
return bt_le_nimble_gatt_nrp_insert(conn, GATTS_NRP_INDICATE, params);
|
||||
}
|
||||
|
||||
int bt_le_nimble_gattc_disc_start(uint16_t conn_handle)
|
||||
{
|
||||
LOG_DBG("[N]GattcDiscStart[%u]", conn_handle);
|
||||
|
||||
return bt_le_nimble_gattc_db_auto_disc(conn_handle);
|
||||
}
|
||||
|
||||
int bt_le_nimble_gattc_discover(struct bt_conn *conn, struct bt_gatt_discover_params *params)
|
||||
{
|
||||
ble_uuid16_t uuid = {0};
|
||||
|
||||
LOG_DBG("[N]GattcDisc[%u]", conn->handle);
|
||||
|
||||
if (params->uuid) {
|
||||
uuid.u.type = BLE_UUID_TYPE_16;
|
||||
uuid.value = BT_UUID_16(params->uuid)->val;
|
||||
}
|
||||
|
||||
switch (params->type) {
|
||||
case BT_GATT_DISCOVER_PRIMARY:
|
||||
if (params->uuid) {
|
||||
return bt_le_nimble_gattc_db_disc_svc_by_uuid(conn, &uuid, params);
|
||||
}
|
||||
|
||||
LOG_ERR("[N]NotSuppDiscAllPrimarySvcs");
|
||||
return -ENOTSUP;
|
||||
|
||||
case BT_GATT_DISCOVER_INCLUDE:
|
||||
return bt_le_nimble_gattc_db_find_inc_svcs(conn, params);
|
||||
|
||||
case BT_GATT_DISCOVER_CHARACTERISTIC:
|
||||
if (params->uuid) {
|
||||
return bt_le_nimble_gattc_db_disc_chrs_by_uuid(conn, &uuid, params);
|
||||
}
|
||||
|
||||
return bt_le_nimble_gattc_db_disc_all_chrs(conn, params);
|
||||
|
||||
case BT_GATT_DISCOVER_DESCRIPTOR:
|
||||
assert(params->uuid);
|
||||
|
||||
/* Only descriptors can be filtered */
|
||||
if (bt_uuid_cmp(params->uuid, BT_UUID_GATT_PRIMARY) == 0 ||
|
||||
bt_uuid_cmp(params->uuid, BT_UUID_GATT_SECONDARY) == 0 ||
|
||||
bt_uuid_cmp(params->uuid, BT_UUID_GATT_INCLUDE) == 0 ||
|
||||
bt_uuid_cmp(params->uuid, BT_UUID_GATT_CHRC) == 0) {
|
||||
LOG_ERR("[N]InvDscToDisc[%02x]", params->uuid->type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return bt_le_nimble_gattc_db_disc_all_dscs(conn, params);
|
||||
|
||||
default:
|
||||
LOG_ERR("[N]DiscNotSupp[%u]", params->type);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
int bt_le_nimble_gattc_read(struct bt_conn *conn, struct bt_gatt_read_params *params)
|
||||
{
|
||||
uint8_t type;
|
||||
|
||||
if (params->handle_count == 0) {
|
||||
type = GATTC_NRP_READ_BY_UUID;
|
||||
} else if (params->single.offset) {
|
||||
type = GATTC_NRP_READ_LONG;
|
||||
} else {
|
||||
type = GATTC_NRP_READ_SINGLE;
|
||||
}
|
||||
|
||||
LOG_DBG("[N]GattcRd[%u][%u]", conn->handle, type);
|
||||
|
||||
return bt_le_nimble_gatt_nrp_insert(conn, type, params);
|
||||
}
|
||||
|
||||
int bt_le_nimble_gattc_write(struct bt_conn *conn, struct bt_gatt_write_params *params)
|
||||
{
|
||||
LOG_DBG("[N]GattcWr[%u]", conn->handle);
|
||||
|
||||
return bt_le_nimble_gatt_nrp_insert(conn, GATTC_NRP_WRITE_REQ, params);
|
||||
}
|
||||
|
||||
int bt_le_nimble_gattc_write_without_rsp(struct bt_conn *conn, uint16_t handle,
|
||||
const void *data, uint16_t length)
|
||||
{
|
||||
LOG_DBG("[N]GattcWrCmd[%u][%u][%u]", conn->handle, handle, length);
|
||||
|
||||
return ble_gattc_write_no_rsp_flat(conn->handle, handle, data, length);
|
||||
}
|
||||
|
||||
int bt_le_nimble_gattc_write_ccc(struct bt_conn *conn, struct bt_gatt_subscribe_params *params)
|
||||
{
|
||||
/* LOG_DBG("[N]GattcWrCcc[%u]", conn->handle); */
|
||||
|
||||
return bt_le_nimble_gatt_nrp_insert(conn, GATTC_NRP_SUBSCRIBE, params);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef HOST_NIMBLE_GATT_H_
|
||||
#define HOST_NIMBLE_GATT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <zephyr/bluetooth/uuid.h>
|
||||
|
||||
#include "host/ble_uuid.h"
|
||||
#include "host/ble_gatt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct bt_le_nimble_gatt_read_cb {
|
||||
int (*read_cb)(void *arg, uint16_t offset, const void *data, uint16_t len);
|
||||
void *read_arg;
|
||||
};
|
||||
|
||||
static inline uint8_t BT_LE_NIMBLE_GATT_UUID_TO_Z(uint8_t type)
|
||||
{
|
||||
/* Used to convert NimBLE UUID to Zephyr UUID */
|
||||
|
||||
if (type == BLE_UUID_TYPE_16) {
|
||||
return BT_UUID_TYPE_16;
|
||||
} else if (type == BLE_UUID_TYPE_32) {
|
||||
return BT_UUID_TYPE_32;
|
||||
} else if (type == BLE_UUID_TYPE_128) {
|
||||
return BT_UUID_TYPE_128;
|
||||
} else {
|
||||
assert(0);
|
||||
return BT_UUID_TYPE_16;
|
||||
}
|
||||
}
|
||||
|
||||
void bt_le_nimble_gatt_post_event(void *event);
|
||||
|
||||
int bt_le_nimble_gatt_post_disc_event(uint16_t conn_handle, ble_uuid16_t *uuid,
|
||||
struct bt_gatt_discover_params *params,
|
||||
uint8_t type);
|
||||
|
||||
int bt_le_nimble_gatt_post_disc_cmpl_event(uint16_t conn_handle, uint8_t status);
|
||||
|
||||
void bt_le_nimble_gatt_handle_event(uint8_t *data, size_t data_len);
|
||||
|
||||
uint16_t bt_le_nimble_gatt_get_mtu(struct bt_conn *conn);
|
||||
|
||||
ssize_t bt_le_nimble_gatts_attr_read(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||
void *buf, uint16_t buf_len, uint16_t offset,
|
||||
const void *value, uint16_t value_len);
|
||||
|
||||
int bt_le_nimble_gatts_notify(struct bt_conn *conn, struct bt_gatt_notify_params *params);
|
||||
|
||||
int bt_le_nimble_gatts_indicate(struct bt_conn *conn, struct bt_gatt_indicate_params *params);
|
||||
|
||||
int bt_le_nimble_gattc_disc_start(uint16_t conn_handle);
|
||||
|
||||
int bt_le_nimble_gattc_discover(struct bt_conn *conn, struct bt_gatt_discover_params *params);
|
||||
|
||||
int bt_le_nimble_gattc_read(struct bt_conn *conn, struct bt_gatt_read_params *params);
|
||||
|
||||
int bt_le_nimble_gattc_write(struct bt_conn *conn, struct bt_gatt_write_params *params);
|
||||
|
||||
int bt_le_nimble_gattc_write_without_rsp(struct bt_conn *conn, uint16_t handle,
|
||||
const void *data, uint16_t length);
|
||||
|
||||
int bt_le_nimble_gattc_write_ccc(struct bt_conn *conn, struct bt_gatt_subscribe_params *params);
|
||||
|
||||
struct bt_le_gattc_discover_event;
|
||||
|
||||
void handle_gattc_db_disc_event_safe(struct bt_le_gattc_discover_event *event);
|
||||
|
||||
int bt_le_nimble_gattc_db_disc_svc_by_uuid(struct bt_conn *conn, ble_uuid16_t *uuid,
|
||||
struct bt_gatt_discover_params *params);
|
||||
|
||||
int bt_le_nimble_gattc_db_find_inc_svcs(struct bt_conn *conn,
|
||||
struct bt_gatt_discover_params *params);
|
||||
|
||||
int bt_le_nimble_gattc_db_disc_chrs_by_uuid(struct bt_conn *conn, ble_uuid16_t *uuid,
|
||||
struct bt_gatt_discover_params *params);
|
||||
|
||||
int bt_le_nimble_gattc_db_disc_all_chrs(struct bt_conn *conn,
|
||||
struct bt_gatt_discover_params *params);
|
||||
|
||||
int bt_le_nimble_gattc_db_disc_all_dscs(struct bt_conn *conn,
|
||||
struct bt_gatt_discover_params *params);
|
||||
|
||||
int bt_le_nimble_gattc_db_auto_disc(uint16_t conn_handle);
|
||||
|
||||
void bt_le_nimble_gattc_db_remove(uint16_t conn_handle);
|
||||
|
||||
enum {
|
||||
GATTC_NRP_READ_BY_UUID,
|
||||
GATTC_NRP_READ_LONG,
|
||||
GATTC_NRP_READ_SINGLE,
|
||||
GATTC_NRP_WRITE_REQ,
|
||||
GATTC_NRP_SUBSCRIBE,
|
||||
GATTS_NRP_INDICATE,
|
||||
|
||||
GATT_NRP_MAX_NUM,
|
||||
};
|
||||
|
||||
void bt_le_nimble_gatts_nrp_indicate_cb(uint16_t conn_handle,
|
||||
int16_t attr_handle,
|
||||
uint8_t status);
|
||||
|
||||
int bt_le_nimble_gatt_nrp_insert(struct bt_conn *conn, uint8_t type, void *params);
|
||||
|
||||
int bt_le_nimble_gatt_nrp_remove(struct bt_conn *conn, uint8_t type, void *params);
|
||||
|
||||
void bt_le_nimble_gatt_nrp_clear(uint16_t conn_handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HOST_NIMBLE_GATT_H_ */
|
||||
@@ -0,0 +1,901 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <zephyr/autoconf.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/bluetooth/bluetooth.h>
|
||||
#include <zephyr/bluetooth/conn.h>
|
||||
#include <zephyr/bluetooth/gatt.h>
|
||||
#include <zephyr/bluetooth/common/bt_str.h>
|
||||
|
||||
#include <../host/conn_internal.h>
|
||||
|
||||
#include "host/ble_hs.h"
|
||||
#include "host/ble_att.h"
|
||||
#include "host/ble_gatt.h"
|
||||
#include "host/ble_hs_mbuf.h"
|
||||
|
||||
#include "common/host.h"
|
||||
|
||||
struct gatt_nrp_node {
|
||||
uint8_t type;
|
||||
|
||||
union {
|
||||
struct {
|
||||
struct bt_gatt_read_params *params;
|
||||
} read_by_uuid;
|
||||
|
||||
struct {
|
||||
struct bt_gatt_read_params *params;
|
||||
} read_long;
|
||||
|
||||
struct {
|
||||
struct bt_gatt_read_params *params;
|
||||
} read_single;
|
||||
|
||||
struct {
|
||||
struct bt_gatt_write_params *params;
|
||||
} write_req;
|
||||
|
||||
struct {
|
||||
struct bt_gatt_subscribe_params *params;
|
||||
} subscribe;
|
||||
|
||||
struct {
|
||||
struct bt_gatt_indicate_params *params;
|
||||
} indicate;
|
||||
};
|
||||
|
||||
sys_snode_t node;
|
||||
};
|
||||
|
||||
static struct gatt_nrp {
|
||||
uint16_t conn_handle;
|
||||
|
||||
sys_slist_t list; /* List of GATT need response pdu (e.g., read req, write req, indication, etc.) */
|
||||
} gatt_nrp[CONFIG_BT_MAX_CONN] = {
|
||||
[0 ...(CONFIG_BT_MAX_CONN - 1)] = {
|
||||
.conn_handle = UINT16_MAX,
|
||||
},
|
||||
};
|
||||
|
||||
static int gattc_nrp_read_by_uuid_cb_safe(uint16_t conn_handle,
|
||||
const struct ble_gatt_error *error,
|
||||
struct ble_gatt_attr *attr,
|
||||
void *arg)
|
||||
{
|
||||
struct bt_gatt_read_params *read_params;
|
||||
struct bt_conn *conn;
|
||||
int rc = 0;
|
||||
|
||||
read_params = arg;
|
||||
assert(read_params);
|
||||
assert(read_params->func);
|
||||
assert(read_params->handle_count == 0);
|
||||
assert(read_params->by_uuid.uuid);
|
||||
assert(read_params->by_uuid.uuid->type == BT_UUID_TYPE_16);
|
||||
|
||||
LOG_DBG("[N]GattcNrpRdByUuidCb[%u][%04x][%s]",
|
||||
conn_handle, error->status, bt_uuid_str(read_params->by_uuid.uuid));
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL || conn->state != BT_CONN_CONNECTED) {
|
||||
LOG_ERR("[N]GattcNrpNotConn[%d]", __LINE__);
|
||||
rc = -ENOTCONN;
|
||||
/* Note:
|
||||
* Cannot remove NRP node or invoke callback without valid conn.
|
||||
* Consider if bt_le_nimble_gatt_nrp_clear() should be invoked.
|
||||
*/
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Shall be invoked before the read_params->func is invoked */
|
||||
bt_le_nimble_gatt_nrp_remove(conn, GATTC_NRP_READ_BY_UUID, read_params);
|
||||
|
||||
switch (error->status) {
|
||||
case 0:
|
||||
assert(attr);
|
||||
assert(attr->om);
|
||||
|
||||
LOG_DBG("[N]GattcNrpHdl[%u][%u][%u]Len[%u]",
|
||||
attr->handle, read_params->by_uuid.start_handle,
|
||||
read_params->by_uuid.end_handle, attr->om->om_len);
|
||||
|
||||
if (read_params->by_uuid.start_handle == BT_ATT_FIRST_ATTRIBUTE_HANDLE) {
|
||||
read_params->by_uuid.start_handle = attr->handle;
|
||||
}
|
||||
|
||||
read_params->func(conn, 0, read_params, attr->om->om_data, attr->om->om_len);
|
||||
break;
|
||||
|
||||
case BLE_HS_EDONE:
|
||||
read_params->func(conn, 0, read_params, NULL, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_WRN("[N]GattcNrpStatus[%04x]", error->status);
|
||||
|
||||
if (error->status & BLE_HS_ERR_ATT_BASE) {
|
||||
read_params->func(conn, (uint8_t)error->status, read_params, NULL, 0);
|
||||
} else {
|
||||
/* Note: for other errors, currently we just ignore it. */
|
||||
}
|
||||
|
||||
rc = error->status;
|
||||
break;
|
||||
}
|
||||
|
||||
end:
|
||||
bt_le_host_unlock();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int gattc_nrp_read_long_cb_safe(uint16_t conn_handle,
|
||||
const struct ble_gatt_error *error,
|
||||
struct ble_gatt_attr *attr,
|
||||
void *arg)
|
||||
{
|
||||
struct bt_gatt_read_params *read_params;
|
||||
struct bt_conn *conn;
|
||||
int rc = 0;
|
||||
|
||||
read_params = arg;
|
||||
assert(read_params);
|
||||
assert(read_params->func);
|
||||
assert(read_params->handle_count == 1);
|
||||
assert(read_params->single.offset != 0);
|
||||
|
||||
LOG_DBG("[N]GattcNrpRdLongCb[%u][%04x]", conn_handle, error->status);
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL || conn->state != BT_CONN_CONNECTED) {
|
||||
LOG_ERR("[N]GattcNrpNotConn[%d]", __LINE__);
|
||||
rc = -ENOTCONN;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Shall be invoked before the read_params->func is invoked */
|
||||
bt_le_nimble_gatt_nrp_remove(conn, GATTC_NRP_READ_LONG, read_params);
|
||||
|
||||
switch (error->status) {
|
||||
case 0:
|
||||
assert(attr);
|
||||
assert(attr->om);
|
||||
|
||||
LOG_DBG("[N]GattcNrpHdl[%u][%u]Offset[%u]Len[%u]",
|
||||
attr->handle, read_params->single.handle, attr->offset, attr->om->om_len);
|
||||
|
||||
read_params->func(conn, 0, read_params, attr->om->om_data, attr->om->om_len);
|
||||
break;
|
||||
|
||||
case BLE_HS_EDONE:
|
||||
read_params->func(conn, 0, read_params, NULL, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_WRN("[N]GattcNrpStatus[%04x]", error->status);
|
||||
|
||||
if (error->status & BLE_HS_ERR_ATT_BASE) {
|
||||
read_params->func(conn, (uint8_t)error->status, read_params, NULL, 0);
|
||||
} else {
|
||||
/* Note: for other errors, currently we just ignore it. */
|
||||
}
|
||||
|
||||
rc = error->status;
|
||||
break;
|
||||
}
|
||||
|
||||
end:
|
||||
bt_le_host_unlock();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int gattc_nrp_read_single_cb_safe(uint16_t conn_handle,
|
||||
const struct ble_gatt_error *error,
|
||||
struct ble_gatt_attr *attr,
|
||||
void *arg)
|
||||
{
|
||||
struct bt_gatt_read_params *read_params;
|
||||
struct bt_conn *conn;
|
||||
int rc = 0;
|
||||
|
||||
read_params = arg;
|
||||
assert(read_params);
|
||||
assert(read_params->func);
|
||||
assert(read_params->handle_count == 1);
|
||||
assert(read_params->single.offset == 0);
|
||||
|
||||
LOG_DBG("[N]GattcNrpRdSingleCb[%u][%04x]", conn_handle, error->status);
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL || conn->state != BT_CONN_CONNECTED) {
|
||||
LOG_ERR("[N]GattcNrpNotConn[%d]", __LINE__);
|
||||
rc = -ENOTCONN;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Shall be invoked before the read_params->func is invoked */
|
||||
bt_le_nimble_gatt_nrp_remove(conn, GATTC_NRP_READ_SINGLE, read_params);
|
||||
|
||||
switch (error->status) {
|
||||
case 0:
|
||||
assert(attr);
|
||||
assert(attr->om);
|
||||
|
||||
LOG_DBG("[N]GattcNrpHdl[%u][%u]Len[%u]",
|
||||
attr->handle, read_params->single.handle, attr->om->om_len);
|
||||
|
||||
if (read_params->func(conn, 0, read_params,
|
||||
attr->om->om_data,
|
||||
attr->om->om_len) == BT_GATT_ITER_CONTINUE) {
|
||||
/* Workaround for completing the handling of ATT Read Response
|
||||
* by BAP Unicast Client.
|
||||
*/
|
||||
read_params->func(conn, 0, read_params, NULL, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case BLE_HS_EDONE:
|
||||
read_params->func(conn, 0, read_params, NULL, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_WRN("[N]GattcNrpStatus[%04x]", error->status);
|
||||
|
||||
if (error->status & BLE_HS_ERR_ATT_BASE) {
|
||||
read_params->func(conn, (uint8_t)error->status, read_params, NULL, 0);
|
||||
} else {
|
||||
/* Note: for other errors, currently we just ignore it. */
|
||||
}
|
||||
|
||||
rc = error->status;
|
||||
break;
|
||||
}
|
||||
|
||||
end:
|
||||
bt_le_host_unlock();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int gattc_nrp_read(struct bt_conn *conn, struct bt_gatt_read_params *params)
|
||||
{
|
||||
int rc;
|
||||
|
||||
LOG_DBG("[N]GattcNrpRd[%u][%u]", conn->handle, params->handle_count);
|
||||
|
||||
if (params->handle_count == 0) {
|
||||
LOG_DBG("[N]GattcNrpByUuid[%u][%u][%s]",
|
||||
params->by_uuid.start_handle, params->by_uuid.end_handle,
|
||||
bt_uuid_str(params->by_uuid.uuid));
|
||||
|
||||
ble_uuid16_t uuid = {
|
||||
.u.type = BLE_UUID_TYPE_16,
|
||||
.value = BT_UUID_16(params->by_uuid.uuid)->val,
|
||||
};
|
||||
|
||||
rc = ble_gattc_read_by_uuid(conn->handle,
|
||||
params->by_uuid.start_handle,
|
||||
params->by_uuid.end_handle,
|
||||
&uuid.u,
|
||||
gattc_nrp_read_by_uuid_cb_safe,
|
||||
params);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]GattcNrpRdByUuidFail[%d]", rc);
|
||||
}
|
||||
} else if (params->single.offset) {
|
||||
LOG_DBG("[N]GattcNrpLong[%u][%u]", params->single.handle, params->single.offset);
|
||||
|
||||
rc = ble_gattc_read_long(conn->handle,
|
||||
params->single.handle,
|
||||
params->single.offset,
|
||||
gattc_nrp_read_long_cb_safe,
|
||||
params);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]GattcNrpRdLongFail[%d]", rc);
|
||||
}
|
||||
} else {
|
||||
LOG_DBG("[N]GattcNrpSingle[%u]", params->single.handle);
|
||||
|
||||
rc = ble_gattc_read(conn->handle,
|
||||
params->single.handle,
|
||||
gattc_nrp_read_single_cb_safe,
|
||||
params);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]GattcNrpRdFail[%d]", rc);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int gattc_nrp_write_cb_safe(uint16_t conn_handle,
|
||||
const struct ble_gatt_error *error,
|
||||
struct ble_gatt_attr *attr,
|
||||
void *arg)
|
||||
{
|
||||
struct bt_gatt_write_params *write_params;
|
||||
struct bt_conn *conn;
|
||||
int rc = 0;
|
||||
|
||||
write_params = arg;
|
||||
assert(write_params);
|
||||
assert(write_params->func);
|
||||
|
||||
LOG_DBG("[N]GattcNrpWrCb[%u][%04x]", conn_handle, error->status);
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL || conn->state != BT_CONN_CONNECTED) {
|
||||
LOG_ERR("[N]GattcNrpNotConn[%d]", __LINE__);
|
||||
rc = -ENOTCONN;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Shall be invoked before the write_params->func is invoked */
|
||||
bt_le_nimble_gatt_nrp_remove(conn, GATTC_NRP_WRITE_REQ, write_params);
|
||||
|
||||
switch (error->status) {
|
||||
case 0:
|
||||
assert(attr);
|
||||
LOG_DBG("[N]GattcNrpHdl[%u][%u]", attr->handle, write_params->handle);
|
||||
|
||||
write_params->func(conn, 0, write_params);
|
||||
break;
|
||||
|
||||
case BLE_HS_EDONE:
|
||||
/* Note: for sending write request, the EDONE status will not be reported. */
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_WRN("[N]GattcNrpStatus[%04x]", error->status);
|
||||
|
||||
if (error->status & BLE_HS_ERR_ATT_BASE) {
|
||||
write_params->func(conn, (uint8_t)error->status, write_params);
|
||||
} else {
|
||||
/* Note: for other errors, currently we just ignore it. */
|
||||
}
|
||||
|
||||
rc = error->status;
|
||||
break;
|
||||
}
|
||||
|
||||
end:
|
||||
bt_le_host_unlock();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int gattc_nrp_write(struct bt_conn *conn, struct bt_gatt_write_params *params)
|
||||
{
|
||||
int rc;
|
||||
|
||||
LOG_DBG("[N]GattcNrpWr[%u][%u][%u]",
|
||||
conn->handle, params->handle, params->length);
|
||||
|
||||
rc = ble_gattc_write_flat(conn->handle,
|
||||
params->handle,
|
||||
params->data,
|
||||
params->length,
|
||||
gattc_nrp_write_cb_safe,
|
||||
params);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]GattcNrpWrFlatFail[%d]", rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int gattc_nrp_subscribe_cb_safe(uint16_t conn_handle,
|
||||
const struct ble_gatt_error *error,
|
||||
struct ble_gatt_attr *attr,
|
||||
void *arg)
|
||||
{
|
||||
struct bt_gatt_subscribe_params *sub_params;
|
||||
struct bt_conn *conn;
|
||||
int rc = 0;
|
||||
|
||||
sub_params = arg;
|
||||
assert(sub_params);
|
||||
|
||||
LOG_DBG("[N]GattcNrpSubCb[%u][%04x]", conn_handle, error->status);
|
||||
|
||||
bt_le_host_lock();
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL || conn->state != BT_CONN_CONNECTED) {
|
||||
LOG_ERR("[N]GattcNrpNotConn[%d]", __LINE__);
|
||||
rc = -ENOTCONN;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Should be invoked here */
|
||||
bt_le_nimble_gatt_nrp_remove(conn, GATTC_NRP_SUBSCRIBE, sub_params);
|
||||
|
||||
switch (error->status) {
|
||||
case 0:
|
||||
assert(attr);
|
||||
LOG_DBG("[N]GattcNrpHdl[%u]", attr->handle);
|
||||
|
||||
#if 0
|
||||
/* Mask the callback invocation for now.
|
||||
* Check the bt_gatt_subscribe function for details.
|
||||
*/
|
||||
if (sub_params->subscribe) {
|
||||
sub_params->subscribe(conn, 0, sub_params);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case BLE_HS_EDONE:
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_WRN("[N]GattcNrpStatus[%04x]", error->status);
|
||||
|
||||
#if 0
|
||||
/* Mask the callback invocation for now.
|
||||
* Check the bt_gatt_subscribe function for details.
|
||||
*/
|
||||
if (sub_params->subscribe && (error->status & BLE_HS_ERR_ATT_BASE)) {
|
||||
sub_params->subscribe(conn, (uint8_t)error->status, sub_params);
|
||||
}
|
||||
#endif
|
||||
|
||||
rc = error->status;
|
||||
break;
|
||||
}
|
||||
|
||||
end:
|
||||
bt_le_host_unlock();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int gattc_nrp_subscribe(struct bt_conn *conn, struct bt_gatt_subscribe_params *params)
|
||||
{
|
||||
int rc;
|
||||
|
||||
LOG_DBG("[N]GattcNrpSub[%u][%u][%04x]",
|
||||
conn->handle, params->ccc_handle, params->value);
|
||||
|
||||
rc = ble_gattc_write_flat(conn->handle,
|
||||
params->ccc_handle,
|
||||
¶ms->value,
|
||||
sizeof(params->value),
|
||||
gattc_nrp_subscribe_cb_safe,
|
||||
params);
|
||||
if (rc && rc != BLE_HS_ENOTCONN) {
|
||||
LOG_ERR("[N]GattcNrpSubFail[%d]", rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void bt_le_nimble_gatts_nrp_indicate_cb(uint16_t conn_handle,
|
||||
int16_t attr_handle,
|
||||
uint8_t status)
|
||||
{
|
||||
struct bt_gatt_indicate_params params = {0};
|
||||
struct bt_gatt_attr attr = {0};
|
||||
struct bt_conn *conn;
|
||||
|
||||
LOG_DBG("[N]GattsNrpIndCb[%u][%u][%u]", conn_handle, attr_handle, status);
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL || conn->state != BT_CONN_CONNECTED) {
|
||||
LOG_ERR("[N]GattsNrpNotConn[%d]", __LINE__);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case BLE_HS_EDONE:
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_WRN("[N]GattsNrpIndCbStatus[%u]", status);
|
||||
break;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
attr.handle = attr_handle;
|
||||
params.attr = &attr;
|
||||
|
||||
bt_le_nimble_gatt_nrp_remove(conn, GATTS_NRP_INDICATE, ¶ms);
|
||||
}
|
||||
}
|
||||
|
||||
static int gatts_nrp_indicate(struct bt_conn *conn, struct bt_gatt_indicate_params *params)
|
||||
{
|
||||
struct notify_data data = {0};
|
||||
struct os_mbuf *om = NULL;
|
||||
int rc;
|
||||
|
||||
assert(conn && params);
|
||||
assert(params->attr);
|
||||
assert(params->data);
|
||||
assert(params->len);
|
||||
|
||||
data.attr = params->attr;
|
||||
data.handle = bt_gatt_attr_get_handle(data.attr);
|
||||
|
||||
LOG_DBG("[N]GattsNrpInd[%u][%u]", conn->handle, data.handle);
|
||||
|
||||
/* Lookup UUID if it was given */
|
||||
if (params->uuid) {
|
||||
if (bt_gatts_find_attr_by_uuid(&data, params->uuid) == false) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
params->attr = data.attr;
|
||||
} else {
|
||||
if (data.handle == 0) {
|
||||
LOG_WRN("[N]GattsNrpDataHdlZero");
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if attribute is a characteristic then adjust the handle */
|
||||
if (bt_uuid_cmp(data.attr->uuid, BT_UUID_GATT_CHRC) == 0) {
|
||||
struct bt_gatt_chrc *chrc;
|
||||
|
||||
assert(data.attr->user_data);
|
||||
chrc = data.attr->user_data;
|
||||
|
||||
if ((chrc->properties & BT_GATT_CHRC_INDICATE) == 0) {
|
||||
LOG_WRN("[N]GattsNrpIndNotSupp[%u][%02x]", data.handle, chrc->properties);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
data.handle = bt_gatt_attr_value_handle(data.attr);
|
||||
|
||||
LOG_INF("[N]GattsNrpDataHdl[%u][%u]", data.attr->handle, data.handle);
|
||||
}
|
||||
|
||||
om = ble_hs_mbuf_from_flat(params->data, params->len);
|
||||
if (om == NULL) {
|
||||
LOG_ERR("[N]GattsNrpNoMemForInd[%u]", params->len);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rc = ble_gatts_indicate_custom(conn->handle, data.handle, om);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]GattsNrpIndCustomFail[%d]", rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct gatt_nrp *gatt_nrp_add(uint16_t conn_handle)
|
||||
{
|
||||
for (size_t i = 0; i < ARRAY_SIZE(gatt_nrp); i++) {
|
||||
if (gatt_nrp[i].conn_handle == UINT16_MAX) {
|
||||
gatt_nrp[i].conn_handle = conn_handle;
|
||||
sys_slist_init(&gatt_nrp[i].list);
|
||||
|
||||
return &gatt_nrp[i];
|
||||
}
|
||||
}
|
||||
|
||||
LOG_ERR("[N]GattNrpNoFreeGattNrp[%u]", conn_handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct gatt_nrp *gatt_nrp_find(uint16_t conn_handle)
|
||||
{
|
||||
for (size_t i = 0; i < ARRAY_SIZE(gatt_nrp); i++) {
|
||||
if (gatt_nrp[i].conn_handle == conn_handle) {
|
||||
LOG_DBG("[N]GattNrpFound[%u]", conn_handle);
|
||||
return &gatt_nrp[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void gatt_nrp_del(struct gatt_nrp *nrp)
|
||||
{
|
||||
struct gatt_nrp_node *nrp_head;
|
||||
sys_snode_t *node;
|
||||
|
||||
assert(nrp);
|
||||
|
||||
while (1) {
|
||||
node = sys_slist_get(&nrp->list);
|
||||
if (node == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
nrp_head = CONTAINER_OF(node, struct gatt_nrp_node, node);
|
||||
|
||||
LOG_DBG("[N]GattNrpFree[%p]", nrp_head);
|
||||
|
||||
free(nrp_head);
|
||||
}
|
||||
|
||||
nrp->conn_handle = UINT16_MAX;
|
||||
}
|
||||
|
||||
static int gatt_nrp_insert(struct bt_conn *conn, uint8_t type, void *params)
|
||||
{
|
||||
struct gatt_nrp_node *nrp_node;
|
||||
struct gatt_nrp *nrp;
|
||||
int rc = 0;
|
||||
|
||||
LOG_DBG("[N]GattNrpInsert[%u][%u]", conn->handle, type);
|
||||
|
||||
nrp = gatt_nrp_find(conn->handle);
|
||||
if (nrp == NULL) {
|
||||
nrp = gatt_nrp_add(conn->handle);
|
||||
}
|
||||
|
||||
if (nrp == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
nrp_node = calloc(1, sizeof(*nrp_node));
|
||||
assert(nrp_node);
|
||||
|
||||
nrp_node->type = type;
|
||||
|
||||
switch (type) {
|
||||
case GATTC_NRP_READ_BY_UUID:
|
||||
nrp_node->read_by_uuid.params = params;
|
||||
break;
|
||||
case GATTC_NRP_READ_LONG:
|
||||
nrp_node->read_long.params = params;
|
||||
break;
|
||||
case GATTC_NRP_READ_SINGLE:
|
||||
nrp_node->read_single.params = params;
|
||||
break;
|
||||
case GATTC_NRP_WRITE_REQ:
|
||||
nrp_node->write_req.params = params;
|
||||
break;
|
||||
case GATTC_NRP_SUBSCRIBE:
|
||||
nrp_node->subscribe.params = params;
|
||||
break;
|
||||
case GATTS_NRP_INDICATE:
|
||||
nrp_node->indicate.params = params;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (sys_slist_is_empty(&nrp->list)) {
|
||||
LOG_DBG("[N]GattNrpListEmpty");
|
||||
|
||||
if (type == GATTC_NRP_READ_BY_UUID ||
|
||||
type == GATTC_NRP_READ_LONG ||
|
||||
type == GATTC_NRP_READ_SINGLE) {
|
||||
rc = gattc_nrp_read(conn, params);
|
||||
} else if (type == GATTC_NRP_WRITE_REQ) {
|
||||
rc = gattc_nrp_write(conn, params);
|
||||
} else if (type == GATTC_NRP_SUBSCRIBE) {
|
||||
rc = gattc_nrp_subscribe(conn, params);
|
||||
} else if (type == GATTS_NRP_INDICATE) {
|
||||
rc = gatts_nrp_indicate(conn, params);
|
||||
}
|
||||
} else {
|
||||
LOG_DBG("[N]GattNrpListNotEmpty");
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
LOG_DBG("[N]GattNrpAppend[%p]", nrp_node);
|
||||
sys_slist_append(&nrp->list, &nrp_node->node);
|
||||
} else {
|
||||
LOG_ERR("[N]GattNrpInsertFail[%d]", rc);
|
||||
free(nrp_node);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int gatts_nrp_indicate_insert(struct bt_conn *conn, struct bt_gatt_indicate_params *params)
|
||||
{
|
||||
struct bt_conn *conns;
|
||||
uint8_t conns_count;
|
||||
int rc = 0;
|
||||
|
||||
LOG_DBG("[N]GattsNrpIndInsert[%p]", conn);
|
||||
|
||||
if (conn) {
|
||||
return gatt_nrp_insert(conn, GATTS_NRP_INDICATE, params);
|
||||
}
|
||||
|
||||
bt_conn_get_acl_conns(&conns, &conns_count);
|
||||
|
||||
for (size_t i = 0; i < conns_count; i++) {
|
||||
LOG_DBG("[N]GattsNrpConn[%u][%u][%u]", i, conns[i].handle, conns[i].state);
|
||||
|
||||
if (conns[i].state == BT_CONN_CONNECTED) {
|
||||
rc = gatt_nrp_insert(&conns[i], GATTS_NRP_INDICATE, params);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_le_nimble_gatt_nrp_insert(struct bt_conn *conn, uint8_t type, void *params)
|
||||
{
|
||||
int rc;
|
||||
if (type == GATTS_NRP_INDICATE) {
|
||||
rc = gatts_nrp_indicate_insert(conn, params);
|
||||
} else {
|
||||
rc = gatt_nrp_insert(conn, type, params);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int bt_le_nimble_gatt_nrp_remove(struct bt_conn *conn, uint8_t type, void *params)
|
||||
{
|
||||
struct gatt_nrp_node *nrp_head;
|
||||
struct gatt_nrp *nrp;
|
||||
sys_snode_t *node;
|
||||
int rc = 0;
|
||||
|
||||
LOG_DBG("[N]GattNrpRemove[%u][%u]", conn->handle, type);
|
||||
|
||||
nrp = gatt_nrp_find(conn->handle);
|
||||
if (nrp == NULL) {
|
||||
LOG_ERR("[N]GattNrpNotFound[%u]", conn->handle);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Fetch and remove the first node from list */
|
||||
node = sys_slist_get(&nrp->list);
|
||||
assert(node);
|
||||
|
||||
nrp_head = CONTAINER_OF(node, struct gatt_nrp_node, node);
|
||||
assert(nrp_head->type == type);
|
||||
|
||||
switch (type) {
|
||||
case GATTC_NRP_READ_BY_UUID:
|
||||
assert(nrp_head->read_by_uuid.params == params);
|
||||
break;
|
||||
case GATTC_NRP_READ_LONG:
|
||||
assert(nrp_head->read_long.params == params);
|
||||
break;
|
||||
case GATTC_NRP_READ_SINGLE:
|
||||
assert(nrp_head->read_single.params == params);
|
||||
break;
|
||||
case GATTC_NRP_WRITE_REQ:
|
||||
assert(nrp_head->write_req.params == params);
|
||||
break;
|
||||
case GATTC_NRP_SUBSCRIBE:
|
||||
assert(nrp_head->subscribe.params == params);
|
||||
break;
|
||||
case GATTS_NRP_INDICATE:
|
||||
assert(nrp_head->indicate.params);
|
||||
|
||||
if (nrp_head->indicate.params->attr->handle !=
|
||||
((struct bt_gatt_indicate_params *)params)->attr->handle) {
|
||||
LOG_ERR("[N]GattNrpMismatchIndHdl[%u][%u]",
|
||||
((struct bt_gatt_indicate_params *)params)->attr->handle,
|
||||
nrp_head->indicate.params->attr->handle);
|
||||
assert(0); /* Should not happen */
|
||||
}
|
||||
|
||||
/* Note:
|
||||
* The params may be shared by multiple connections. And currently
|
||||
* in this case, the params will not be updated in the func callback.
|
||||
*/
|
||||
nrp_head->indicate.params->func(conn, nrp_head->indicate.params, 0);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
LOG_DBG("[N]GattNrpFree[%p]", nrp_head);
|
||||
free(nrp_head);
|
||||
|
||||
while (1) {
|
||||
if (sys_slist_is_empty(&nrp->list)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Fetch the first node from list */
|
||||
node = sys_slist_peek_head(&nrp->list);
|
||||
|
||||
nrp_head = CONTAINER_OF(node, struct gatt_nrp_node, node);
|
||||
|
||||
if (nrp_head->type == GATTC_NRP_READ_BY_UUID) {
|
||||
rc = gattc_nrp_read(conn, nrp_head->read_by_uuid.params);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]GattcNrpRdByUuidFail[%d]", rc);
|
||||
|
||||
assert(nrp_head->read_by_uuid.params->func);
|
||||
nrp_head->read_by_uuid.params->func(conn, rc, nrp_head->read_by_uuid.params, NULL, 0);
|
||||
}
|
||||
} else if (nrp_head->type == GATTC_NRP_READ_LONG) {
|
||||
rc = gattc_nrp_read(conn, nrp_head->read_long.params);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]GattcNrpRdLongFail[%d]", rc);
|
||||
|
||||
assert(nrp_head->read_long.params->func);
|
||||
nrp_head->read_long.params->func(conn, rc, nrp_head->read_long.params, NULL, 0);
|
||||
}
|
||||
} else if (nrp_head->type == GATTC_NRP_READ_SINGLE) {
|
||||
rc = gattc_nrp_read(conn, nrp_head->read_single.params);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]GattcNrpRdSingleFail[%d]", rc);
|
||||
|
||||
assert(nrp_head->read_single.params->func);
|
||||
nrp_head->read_single.params->func(conn, rc, nrp_head->read_single.params, NULL, 0);
|
||||
}
|
||||
} else if (nrp_head->type == GATTC_NRP_WRITE_REQ) {
|
||||
rc = gattc_nrp_write(conn, nrp_head->write_req.params);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]GattcNrpWrFail[%d]", rc);
|
||||
|
||||
assert(nrp_head->write_req.params->func);
|
||||
nrp_head->write_req.params->func(conn, rc, nrp_head->write_req.params);
|
||||
}
|
||||
} else if (nrp_head->type == GATTC_NRP_SUBSCRIBE) {
|
||||
rc = gattc_nrp_subscribe(conn, nrp_head->subscribe.params);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]GattcNrpSubFail[%d]", rc);
|
||||
}
|
||||
} else if (nrp_head->type == GATTS_NRP_INDICATE) {
|
||||
rc = gatts_nrp_indicate(conn, nrp_head->indicate.params);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]GattsNrpIndFail[%d]", rc);
|
||||
|
||||
assert(nrp_head->indicate.params->func);
|
||||
nrp_head->indicate.params->func(conn, nrp_head->indicate.params, rc);
|
||||
}
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
LOG_DBG("[N]GattNrpOnGoing[%p]", nrp_head);
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_DBG("[N]GattNrpRemoveAndFree[%p]", nrp_head);
|
||||
|
||||
/* If this nrp operation failed, then remove it from list,
|
||||
* peek the next node and start.
|
||||
*/
|
||||
sys_slist_remove(&nrp->list, NULL, node);
|
||||
|
||||
free(nrp_head);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bt_le_nimble_gatt_nrp_clear(uint16_t conn_handle)
|
||||
{
|
||||
struct gatt_nrp *nrp;
|
||||
|
||||
LOG_DBG("[N]GattNrpClear[%u]", conn_handle);
|
||||
|
||||
nrp = gatt_nrp_find(conn_handle);
|
||||
if (nrp == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
gatt_nrp_del(nrp);
|
||||
}
|
||||
@@ -0,0 +1,455 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include <zephyr/sys/util.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/bluetooth/audio/vcp.h>
|
||||
|
||||
#include "host/ble_gatt.h"
|
||||
#include "services/gap/ble_svc_gap.h"
|
||||
#include "services/gatt/ble_svc_gatt.h"
|
||||
|
||||
#include "nimble/init.h"
|
||||
#include "common/init.h"
|
||||
|
||||
#include "../../../lib/include/audio.h"
|
||||
|
||||
#if CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT
|
||||
#define ASCS_ASE_SNK_CCCD_COUNT CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT
|
||||
#else /* CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT */
|
||||
#define ASCS_ASE_SNK_CCCD_COUNT 0
|
||||
#endif /* CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT */
|
||||
|
||||
#if CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT
|
||||
#define ASCS_ASE_SRC_CCCD_COUNT CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT
|
||||
#else /* CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT */
|
||||
#define ASCS_ASE_SRC_CCCD_COUNT 0
|
||||
#endif /* CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT */
|
||||
|
||||
#if CONFIG_BT_PAC_SNK_NOTIFIABLE
|
||||
#define PAC_SNK_CCCD_COUNT 1
|
||||
#else /* CONFIG_BT_PAC_SNK_NOTIFIABLE */
|
||||
#define PAC_SNK_CCCD_COUNT 0
|
||||
#endif /* CONFIG_BT_PAC_SNK_NOTIFIABLE */
|
||||
|
||||
#if CONFIG_BT_PAC_SNK_LOC_NOTIFIABLE
|
||||
#define PAC_SNK_LOC_CCCD_COUNT 1
|
||||
#else /* CONFIG_BT_PAC_SNK_LOC_NOTIFIABLE */
|
||||
#define PAC_SNK_LOC_CCCD_COUNT 0
|
||||
#endif /* CONFIG_BT_PAC_SNK_LOC_NOTIFIABLE */
|
||||
|
||||
#if CONFIG_BT_PAC_SRC_NOTIFIABLE
|
||||
#define PAC_SRC_CCCD_COUNT 1
|
||||
#else /* CONFIG_BT_PAC_SRC_NOTIFIABLE */
|
||||
#define PAC_SRC_CCCD_COUNT 0
|
||||
#endif /* CONFIG_BT_PAC_SRC_NOTIFIABLE */
|
||||
|
||||
#if CONFIG_BT_PAC_SRC_LOC_NOTIFIABLE
|
||||
#define PAC_SRC_LOC_CCCD_COUNT 1
|
||||
#else /* CONFIG_BT_PAC_SRC_LOC_NOTIFIABLE */
|
||||
#define PAC_SRC_LOC_CCCD_COUNT 0
|
||||
#endif /* CONFIG_BT_PAC_SRC_LOC_NOTIFIABLE */
|
||||
|
||||
#if CONFIG_BT_PACS_SUPPORTED_CONTEXT_NOTIFIABLE
|
||||
#define PACS_SUPPORTED_CONTEXT_CCCD_COUNT 1
|
||||
#else /* CONFIG_BT_PACS_SUPPORTED_CONTEXT_NOTIFIABLE */
|
||||
#define PACS_SUPPORTED_CONTEXT_CCCD_COUNT 0
|
||||
#endif /* CONFIG_BT_PACS_SUPPORTED_CONTEXT_NOTIFIABLE */
|
||||
|
||||
#if CONFIG_BT_BAP_SCAN_DELEGATOR_RECV_STATE_COUNT
|
||||
#define SCAN_DELEGATOR_RECV_STATE_CCCD_COUNT CONFIG_BT_BAP_SCAN_DELEGATOR_RECV_STATE_COUNT
|
||||
#else /* CONFIG_BT_BAP_SCAN_DELEGATOR_RECV_STATE_COUNT */
|
||||
#define SCAN_DELEGATOR_RECV_STATE_CCCD_COUNT 0
|
||||
#endif /* CONFIG_BT_BAP_SCAN_DELEGATOR_RECV_STATE_COUNT */
|
||||
|
||||
#if CONFIG_BT_CSIP_SET_MEMBER_SIRK_NOTIFIABLE
|
||||
#define CSIP_SET_MEMBER_CCCD_COUNT 1
|
||||
#else /* CONFIG_BT_CSIP_SET_MEMBER_SIRK_NOTIFIABLE */
|
||||
#define CSIP_SET_MEMBER_CCCD_COUNT 0
|
||||
#endif /* CONFIG_BT_CSIP_SET_MEMBER_SIRK_NOTIFIABLE */
|
||||
|
||||
#if CONFIG_BT_VCP_VOL_REND_VOL_FLAGS_NOTIFIABLE
|
||||
#define VCP_VOL_REND_VOL_FLAGS_CCCD_COUNT 1
|
||||
#else /* CONFIG_BT_VCP_VOL_REND_VOL_FLAGS_NOTIFIABLE */
|
||||
#define VCP_VOL_REND_VOL_FLAGS_CCCD_COUNT 0
|
||||
#endif /* CONFIG_BT_VCP_VOL_REND_VOL_FLAGS_NOTIFIABLE */
|
||||
|
||||
#if CONFIG_BT_VOCS_MAX_INSTANCE_COUNT
|
||||
#define VOCS_CCCD_COUNT (CONFIG_BT_VOCS_MAX_INSTANCE_COUNT * 3)
|
||||
#else /* CONFIG_BT_VOCS_MAX_INSTANCE_COUNT */
|
||||
#define VOCS_CCCD_COUNT 0
|
||||
#endif /* CONFIG_BT_VOCS_MAX_INSTANCE_COUNT */
|
||||
|
||||
#if CONFIG_BT_AICS_MAX_INSTANCE_COUNT
|
||||
#define AICS_CCCD_COUNT (CONFIG_BT_AICS_MAX_INSTANCE_COUNT * 3)
|
||||
#else /* CONFIG_BT_AICS_MAX_INSTANCE_COUNT */
|
||||
#define AICS_CCCD_COUNT 0
|
||||
#endif /* CONFIG_BT_AICS_MAX_INSTANCE_COUNT */
|
||||
|
||||
#if CONFIG_BT_HAS_FEATURES_NOTIFIABLE
|
||||
#define HAS_FEATURES_CCCD_COUNT 1
|
||||
#else /* CONFIG_BT_HAS_FEATURES_NOTIFIABLE */
|
||||
#define HAS_FEATURES_CCCD_COUNT 0
|
||||
#endif /* CONFIG_BT_HAS_FEATURES_NOTIFIABLE */
|
||||
|
||||
#if CONFIG_BT_HAS_PRESET_CONTROL_POINT_NOTIFIABLE
|
||||
#define HAS_PRESET_CONTROL_POINT_CCCD_COUNT 1
|
||||
#else /* CONFIG_BT_HAS_PRESET_CONTROL_POINT_NOTIFIABLE */
|
||||
#define HAS_PRESET_CONTROL_POINT_CCCD_COUNT 0
|
||||
#endif /* CONFIG_BT_HAS_PRESET_CONTROL_POINT_NOTIFIABLE */
|
||||
|
||||
#if CONFIG_BT_HAS_ACTIVE_PRESET_INDEX
|
||||
#define HAS_ACTIVE_PRESET_INDEX_CCCD_COUNT 1
|
||||
#else /* CONFIG_BT_HAS_ACTIVE_PRESET_INDEX */
|
||||
#define HAS_ACTIVE_PRESET_INDEX_CCCD_COUNT 0
|
||||
#endif /* CONFIG_BT_HAS_ACTIVE_PRESET_INDEX */
|
||||
|
||||
#if CONFIG_BT_OTS
|
||||
#define OTS_CCCD_COUNT (CONFIG_BT_OTS_MAX_INST_CNT * 2)
|
||||
#else /* CONFIG_BT_OTS */
|
||||
#define OTS_CCCD_COUNT 0
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
|
||||
/* 6 is reserved for other GATT services.
|
||||
* TODO:
|
||||
* - OTS
|
||||
* - MCS (GMCS is used for now)
|
||||
* - TBS (GTBS is used for now)
|
||||
*/
|
||||
#define TOTAL_CCCDS_COUNT (6 + \
|
||||
(IS_ENABLED(CONFIG_BT_ASCS) ? (1 + ASCS_ASE_SNK_CCCD_COUNT + \
|
||||
ASCS_ASE_SRC_CCCD_COUNT) : 0) + \
|
||||
(IS_ENABLED(CONFIG_BT_PACS) ? (PAC_SNK_CCCD_COUNT + PAC_SNK_LOC_CCCD_COUNT + \
|
||||
PAC_SRC_CCCD_COUNT + PAC_SRC_LOC_CCCD_COUNT + \
|
||||
1 + PACS_SUPPORTED_CONTEXT_CCCD_COUNT) : 0) + \
|
||||
(IS_ENABLED(CONFIG_BT_BAP_SCAN_DELEGATOR) ? SCAN_DELEGATOR_RECV_STATE_CCCD_COUNT : 0) + \
|
||||
(IS_ENABLED(CONFIG_BT_MCS) ? 11 : 0) + \
|
||||
(IS_ENABLED(CONFIG_BT_CSIP_SET_MEMBER) ? (CSIP_SET_MEMBER_CCCD_COUNT + 2) : 0) + \
|
||||
(IS_ENABLED(CONFIG_BT_VCP_VOL_REND) ? (1 + VCP_VOL_REND_VOL_FLAGS_CCCD_COUNT) : 0) + \
|
||||
VOCS_CCCD_COUNT + \
|
||||
AICS_CCCD_COUNT + \
|
||||
(IS_ENABLED(CONFIG_BT_TBS) ? 12 : 0) + \
|
||||
(IS_ENABLED(CONFIG_BT_HAS) ? (HAS_FEATURES_CCCD_COUNT + \
|
||||
HAS_PRESET_CONTROL_POINT_CCCD_COUNT + \
|
||||
HAS_ACTIVE_PRESET_INDEX_CCCD_COUNT) : 0) + \
|
||||
(IS_ENABLED(CONFIG_BT_OTS) ? OTS_CCCD_COUNT : 0))
|
||||
|
||||
_Static_assert(TOTAL_CCCDS_COUNT <= CONFIG_BT_NIMBLE_MAX_CCCDS, "Too small BT_NIMBLE_MAX_CCCDS");
|
||||
|
||||
int bt_le_nimble_audio_init(void)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
err = ble_att_set_preferred_mtu(BLE_AUDIO_ATT_MTU_MIN);
|
||||
if (err) {
|
||||
LOG_ERR("[N]SetPrefMtuFail[%d]", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
ble_svc_gap_init();
|
||||
|
||||
ble_svc_gatt_init();
|
||||
|
||||
#if CONFIG_BT_PACS
|
||||
err = bt_le_nimble_pacs_init();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_PACS */
|
||||
|
||||
#if (BLE_AUDIO_SVC_SEP_ADD == 0)
|
||||
#if CONFIG_BT_ASCS
|
||||
err = bt_le_nimble_ascs_init();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_ASCS */
|
||||
|
||||
#if CONFIG_BT_BAP_SCAN_DELEGATOR
|
||||
err = bt_le_nimble_bass_init();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_BAP_SCAN_DELEGATOR */
|
||||
|
||||
#if CONFIG_BT_TMAP
|
||||
err = bt_le_nimble_tmas_init();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_TMAP */
|
||||
|
||||
#if CONFIG_BT_TBS
|
||||
err = bt_le_nimble_gtbs_init();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS */
|
||||
|
||||
#if CONFIG_BT_HAS
|
||||
err = bt_le_nimble_has_init();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_HAS */
|
||||
#endif /* (BLE_AUDIO_SVC_SEP_ADD == 0) */
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nimble_gatt_attr_handle_set(void)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
#if CONFIG_BT_ASCS
|
||||
err = bt_le_nimble_ascs_attr_handle_set();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_ASCS */
|
||||
|
||||
#if CONFIG_BT_PACS
|
||||
err = bt_le_nimble_pacs_attr_handle_set();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_PACS */
|
||||
|
||||
#if CONFIG_BT_BAP_SCAN_DELEGATOR
|
||||
err = bt_le_nimble_bass_attr_handle_set();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_BAP_SCAN_DELEGATOR */
|
||||
|
||||
#if CONFIG_BT_CAP_ACCEPTOR
|
||||
err = bt_le_nimble_cas_attr_handle_set();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_CAP_ACCEPTOR */
|
||||
|
||||
#if CONFIG_BT_TMAP
|
||||
err = bt_le_nimble_tmas_attr_handle_set();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_TMAP */
|
||||
|
||||
#if CONFIG_BT_CSIP_SET_MEMBER
|
||||
err = bt_le_nimble_csis_attr_handle_set();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_CSIP_SET_MEMBER */
|
||||
|
||||
#if CONFIG_BT_VCP_VOL_REND
|
||||
err = bt_le_nimble_vcs_attr_handle_set();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_VCP_VOL_REND */
|
||||
|
||||
#if CONFIG_BT_MICP_MIC_DEV
|
||||
err = bt_le_nimble_mics_attr_handle_set();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_MICP_MIC_DEV */
|
||||
|
||||
#if CONFIG_BT_MCS
|
||||
err = bt_le_nimble_gmcs_attr_handle_set();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCS */
|
||||
|
||||
#if CONFIG_BT_TBS
|
||||
err = bt_le_nimble_gtbs_attr_handle_set();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS */
|
||||
|
||||
#if CONFIG_BT_HAS
|
||||
err = bt_le_nimble_has_attr_handle_set();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_HAS */
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_CSIP_SET_MEMBER
|
||||
static int nimble_gatt_csis_init(struct bt_le_audio_start_info *info,
|
||||
struct bt_gatt_service **inc_csis_svc)
|
||||
{
|
||||
struct bt_gatt_service *csis_svc[CONFIG_BT_CSIP_SET_MEMBER_MAX_INSTANCE_COUNT];
|
||||
uint8_t count;
|
||||
int err;
|
||||
|
||||
if (info == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*inc_csis_svc = NULL;
|
||||
count = 0;
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(info->csis_insts); i++) {
|
||||
if (info->csis_insts[i].svc_inst == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
csis_svc[count] = lib_csip_set_member_svc_get(info->csis_insts[i].svc_inst);
|
||||
assert(csis_svc[count]);
|
||||
|
||||
if (info->csis_insts[i].included_by_cas) {
|
||||
if (*inc_csis_svc == NULL) {
|
||||
*inc_csis_svc = csis_svc[count];
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
err = bt_le_nimble_csis_init(csis_svc, count);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_BT_CSIP_SET_MEMBER */
|
||||
|
||||
#if CONFIG_BT_MCS
|
||||
int bt_le_nimble_media_proxy_pl_init(void)
|
||||
{
|
||||
/* Note:
|
||||
* Currently the existence of some characteristics within GMCS
|
||||
* are determined by the enabling of OTS.
|
||||
*/
|
||||
#if CONFIG_BT_OTS
|
||||
return bt_le_nimble_gmcs_init(true);
|
||||
#else /* CONFIG_BT_OTS */
|
||||
return bt_le_nimble_gmcs_init(false);
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
}
|
||||
#endif /* CONFIG_BT_MCS */
|
||||
|
||||
#if CONFIG_BT_VCP_VOL_REND
|
||||
int bt_le_nimble_vcp_vol_rend_init(void)
|
||||
{
|
||||
struct bt_vcp_included vcp_included;
|
||||
int err;
|
||||
|
||||
memset(&vcp_included, 0, sizeof(vcp_included));
|
||||
|
||||
err = bt_vcp_vol_rend_included_get_safe(&vcp_included);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = bt_le_nimble_vcs_init(&vcp_included);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_BT_VCP_VOL_REND */
|
||||
|
||||
#if CONFIG_BT_MICP_MIC_DEV
|
||||
int bt_le_nimble_micp_mic_dev_init(void)
|
||||
{
|
||||
struct bt_micp_included micp_included;
|
||||
int err;
|
||||
|
||||
memset(&micp_included, 0, sizeof(micp_included));
|
||||
|
||||
err = bt_micp_mic_dev_included_get_safe(&micp_included);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = bt_le_nimble_mics_init(&micp_included);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_BT_MICP_MIC_DEV */
|
||||
|
||||
int bt_le_nimble_audio_start(void *info)
|
||||
{
|
||||
struct bt_gatt_service *inc_csis_svc = NULL;
|
||||
int err = 0;
|
||||
|
||||
#if CONFIG_BT_CSIP_SET_MEMBER
|
||||
/* Note:
|
||||
* Should add CSIS before CAS in case one CSIS instance
|
||||
* is included by CAS.
|
||||
*/
|
||||
err = nimble_gatt_csis_init(info, &inc_csis_svc);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_CSIP_SET_MEMBER */
|
||||
|
||||
#if CONFIG_BT_CAP_ACCEPTOR
|
||||
err = bt_le_nimble_cas_init(inc_csis_svc);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#else /* CONFIG_BT_CAP_ACCEPTOR */
|
||||
ARG_UNUSED(inc_csis_svc);
|
||||
#endif /* CONFIG_BT_CAP_ACCEPTOR */
|
||||
|
||||
#if (BLE_AUDIO_SVC_SEP_ADD == 0)
|
||||
#if CONFIG_BT_MCS
|
||||
err = bt_le_nimble_media_proxy_pl_init();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCS */
|
||||
|
||||
#if CONFIG_BT_VCP_VOL_REND
|
||||
err = bt_le_nimble_vcp_vol_rend_init();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_VCP_VOL_REND */
|
||||
|
||||
#if CONFIG_BT_MICP_MIC_DEV
|
||||
err = bt_le_nimble_micp_mic_dev_init();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_MICP_MIC_DEV */
|
||||
#endif /* (BLE_AUDIO_SVC_SEP_ADD == 0) */
|
||||
|
||||
err = ble_gatts_start();
|
||||
if (err) {
|
||||
LOG_ERR("[N]GattsStartFail[%d]", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = nimble_gatt_attr_handle_set();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef HOST_NIMBLE_INIT_H_
|
||||
#define HOST_NIMBLE_INIT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "nimble/profiles/ascs.h"
|
||||
#include "nimble/profiles/bass.h"
|
||||
#include "nimble/profiles/cas.h"
|
||||
#include "nimble/profiles/csis.h"
|
||||
#include "nimble/profiles/mcs.h"
|
||||
#include "nimble/profiles/mics.h"
|
||||
#include "nimble/profiles/pacs.h"
|
||||
#include "nimble/profiles/tbs.h"
|
||||
#include "nimble/profiles/tmas.h"
|
||||
#include "nimble/profiles/vcs.h"
|
||||
#include "nimble/profiles/has.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int bt_le_nimble_audio_init(void);
|
||||
|
||||
int bt_le_nimble_media_proxy_pl_init(void);
|
||||
|
||||
int bt_le_nimble_vcp_vol_rend_init(void);
|
||||
|
||||
int bt_le_nimble_micp_mic_dev_init(void);
|
||||
|
||||
int bt_le_nimble_audio_start(void *info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HOST_NIMBLE_INIT_H_ */
|
||||
@@ -0,0 +1,861 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include <../host/conn_internal.h>
|
||||
#include <../host/iso_internal.h>
|
||||
|
||||
#include "../src/ble_hs_priv.h"
|
||||
#include "host/ble_hs_iso.h"
|
||||
#include "host/ble_hs_iso_hci.h"
|
||||
|
||||
#include "common/host.h"
|
||||
|
||||
extern int ble_hs_iso_evt_rx_cb_set(void *cb);
|
||||
#if CONFIG_BT_ISO_RX
|
||||
extern int ble_hs_iso_pkt_rx_cb_set(ble_hs_iso_pkt_rx_fn cb);
|
||||
#endif /* CONFIG_BT_ISO_RX */
|
||||
|
||||
static int hci_cmd_read_iso_tx_sync(struct net_buf *buf, struct net_buf **rsp)
|
||||
{
|
||||
uint16_t packet_seq_num = 0;
|
||||
uint32_t tx_time_stamp = 0;
|
||||
uint32_t time_offset = 0;
|
||||
uint16_t conn_handle;
|
||||
int status;
|
||||
|
||||
assert(rsp);
|
||||
|
||||
assert(buf->len >= 5);
|
||||
|
||||
conn_handle = sys_get_le16(buf->data + 3);
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
status = ble_hs_hci_read_iso_tx_sync(conn_handle,
|
||||
&packet_seq_num,
|
||||
&tx_time_stamp,
|
||||
&time_offset);
|
||||
if (status) {
|
||||
LOG_ERR("[N]RdIsoTxSyncFail[%u][%02x]", conn_handle, status);
|
||||
}
|
||||
|
||||
ble_hs_unlock();
|
||||
|
||||
if (status) {
|
||||
net_buf_unref(buf);
|
||||
*rsp = NULL;
|
||||
} else {
|
||||
net_buf_reset(buf);
|
||||
net_buf_add_u8(buf, status);
|
||||
net_buf_add_le16(buf, conn_handle);
|
||||
net_buf_add_le16(buf, packet_seq_num);
|
||||
net_buf_add_le32(buf, tx_time_stamp);
|
||||
net_buf_add_le24(buf, time_offset);
|
||||
*rsp = buf;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int hci_cmd_set_cig_params(struct net_buf *buf, struct net_buf **rsp)
|
||||
{
|
||||
struct ble_hci_le_cis_params *cis_params = NULL;
|
||||
uint32_t sdu_interval_c_to_p;
|
||||
uint32_t sdu_interval_p_to_c;
|
||||
uint8_t worst_case_sca;
|
||||
uint16_t mtl_c_to_p;
|
||||
uint16_t mtl_p_to_c;
|
||||
uint8_t cis_count;
|
||||
uint8_t packing;
|
||||
uint8_t framing;
|
||||
uint8_t cig_id;
|
||||
uint8_t rp_len;
|
||||
uint8_t *rp;
|
||||
int status;
|
||||
|
||||
assert(rsp);
|
||||
|
||||
assert(buf->len >= 18);
|
||||
|
||||
cig_id = buf->data[3];
|
||||
sdu_interval_c_to_p = sys_get_le24(buf->data + 4);
|
||||
sdu_interval_p_to_c = sys_get_le24(buf->data + 7);
|
||||
worst_case_sca = buf->data[10];
|
||||
packing = buf->data[11];
|
||||
framing = buf->data[12];
|
||||
mtl_c_to_p = sys_get_le16(buf->data + 13);
|
||||
mtl_p_to_c = sys_get_le16(buf->data + 15);
|
||||
cis_count = buf->data[17];
|
||||
|
||||
assert(buf->len >= 18 + cis_count * sizeof(struct ble_hci_le_cis_params));
|
||||
|
||||
/* The cis_count can be 0 */
|
||||
if (cis_count) {
|
||||
cis_params = calloc(1, cis_count * sizeof(struct ble_hci_le_cis_params));
|
||||
assert(cis_params);
|
||||
}
|
||||
|
||||
rp_len = sizeof(struct ble_hci_le_set_cig_params_rp) + cis_count * 2;
|
||||
rp = calloc(1, rp_len);
|
||||
assert(rp);
|
||||
|
||||
for (size_t i = 0; i < cis_count; i++) {
|
||||
cis_params[i].cis_id = buf->data[18 + i * sizeof(struct ble_hci_le_cis_params)];
|
||||
cis_params[i].max_sdu_c_to_p = sys_get_le16(buf->data + 19 + i * sizeof(struct ble_hci_le_cis_params));
|
||||
cis_params[i].max_sdu_p_to_c = sys_get_le16(buf->data + 21 + i * sizeof(struct ble_hci_le_cis_params));
|
||||
cis_params[i].phy_c_to_p = buf->data[23 + i * sizeof(struct ble_hci_le_cis_params)];
|
||||
cis_params[i].phy_p_to_c = buf->data[24 + i * sizeof(struct ble_hci_le_cis_params)];
|
||||
cis_params[i].rtn_c_to_p = buf->data[25 + i * sizeof(struct ble_hci_le_cis_params)];
|
||||
cis_params[i].rtn_p_to_c = buf->data[26 + i * sizeof(struct ble_hci_le_cis_params)];
|
||||
}
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
status = ble_hs_hci_set_cig_params(cig_id,
|
||||
sdu_interval_c_to_p,
|
||||
sdu_interval_p_to_c,
|
||||
worst_case_sca,
|
||||
packing,
|
||||
framing,
|
||||
mtl_c_to_p,
|
||||
mtl_p_to_c,
|
||||
cis_count,
|
||||
cis_params,
|
||||
rp,
|
||||
rp_len);
|
||||
if (status) {
|
||||
LOG_ERR("[N]SetCigParamsFail[%u][%02x]", cig_id, status);
|
||||
}
|
||||
|
||||
ble_hs_unlock();
|
||||
|
||||
if (status) {
|
||||
net_buf_unref(buf);
|
||||
*rsp = NULL;
|
||||
} else {
|
||||
net_buf_reset(buf);
|
||||
net_buf_add_u8(buf, status);
|
||||
net_buf_add_u8(buf, rp[0]);
|
||||
net_buf_add_u8(buf, rp[1]);
|
||||
for (size_t i = 0; i < cis_count; i++) {
|
||||
net_buf_add_le16(buf, sys_get_le16(rp + sizeof(struct ble_hci_le_set_cig_params_rp) + i * 2));
|
||||
}
|
||||
*rsp = buf;
|
||||
}
|
||||
|
||||
free(cis_params);
|
||||
free(rp);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int hci_cmd_set_cig_params_test(struct net_buf *buf, struct net_buf **rsp)
|
||||
{
|
||||
struct ble_hci_le_cis_params_test *cis_params = NULL;
|
||||
uint32_t sdu_interval_c_to_p;
|
||||
uint32_t sdu_interval_p_to_c;
|
||||
uint8_t worst_case_sca;
|
||||
uint16_t iso_interval;
|
||||
uint8_t ft_c_to_p;
|
||||
uint8_t ft_p_to_c;
|
||||
uint8_t cis_count;
|
||||
uint8_t packing;
|
||||
uint8_t framing;
|
||||
uint8_t cig_id;
|
||||
uint8_t rp_len;
|
||||
uint8_t *rp;
|
||||
int status;
|
||||
|
||||
assert(rsp);
|
||||
|
||||
assert(buf->len >= 18);
|
||||
|
||||
cig_id = buf->data[3];
|
||||
sdu_interval_c_to_p = sys_get_le24(buf->data + 4);
|
||||
sdu_interval_p_to_c = sys_get_le24(buf->data + 7);
|
||||
ft_c_to_p = buf->data[10];
|
||||
ft_p_to_c = buf->data[11];
|
||||
iso_interval = sys_get_le16(buf->data + 12);
|
||||
worst_case_sca = buf->data[14];
|
||||
packing = buf->data[15];
|
||||
framing = buf->data[16];
|
||||
cis_count = buf->data[17];
|
||||
|
||||
assert(buf->len >= 18 + cis_count * sizeof(struct ble_hci_le_cis_params_test));
|
||||
|
||||
/* The cis_count can be 0 */
|
||||
if (cis_count) {
|
||||
cis_params = calloc(1, cis_count * sizeof(struct ble_hci_le_cis_params_test));
|
||||
assert(cis_params);
|
||||
}
|
||||
|
||||
rp_len = sizeof(struct ble_hci_le_set_cig_params_test_rp) + cis_count * 2;
|
||||
rp = calloc(1, rp_len);
|
||||
assert(rp);
|
||||
|
||||
for (size_t i = 0; i < cis_count; i++) {
|
||||
cis_params[i].cis_id = buf->data[18 + i * sizeof(struct ble_hci_le_cis_params_test)];
|
||||
cis_params[i].nse = buf->data[19 + i * sizeof(struct ble_hci_le_cis_params_test)];
|
||||
cis_params[i].max_sdu_c_to_p = sys_get_le16(buf->data + 20 + i * sizeof(struct ble_hci_le_cis_params_test));
|
||||
cis_params[i].max_sdu_p_to_c = sys_get_le16(buf->data + 22 + i * sizeof(struct ble_hci_le_cis_params_test));
|
||||
cis_params[i].max_pdu_c_to_p = sys_get_le16(buf->data + 24 + i * sizeof(struct ble_hci_le_cis_params_test));
|
||||
cis_params[i].max_pdu_p_to_c = sys_get_le16(buf->data + 26 + i * sizeof(struct ble_hci_le_cis_params_test));
|
||||
cis_params[i].phy_c_to_p = buf->data[28 + i * sizeof(struct ble_hci_le_cis_params_test)];
|
||||
cis_params[i].phy_p_to_c = buf->data[29 + i * sizeof(struct ble_hci_le_cis_params_test)];
|
||||
cis_params[i].bn_c_to_p = buf->data[30 + i * sizeof(struct ble_hci_le_cis_params_test)];
|
||||
cis_params[i].bn_p_to_c = buf->data[31 + i * sizeof(struct ble_hci_le_cis_params_test)];
|
||||
}
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
status = ble_hs_hci_set_cig_params_test(cig_id,
|
||||
sdu_interval_c_to_p,
|
||||
sdu_interval_p_to_c,
|
||||
ft_c_to_p,
|
||||
ft_p_to_c,
|
||||
iso_interval,
|
||||
worst_case_sca,
|
||||
packing,
|
||||
framing,
|
||||
cis_count,
|
||||
cis_params,
|
||||
rp,
|
||||
rp_len);
|
||||
if (status) {
|
||||
LOG_ERR("[N]SetCigParamsTestFail[%u][%02x]", cig_id, status);
|
||||
}
|
||||
|
||||
ble_hs_unlock();
|
||||
|
||||
if (status) {
|
||||
net_buf_unref(buf);
|
||||
*rsp = NULL;
|
||||
} else {
|
||||
net_buf_reset(buf);
|
||||
net_buf_add_u8(buf, status);
|
||||
net_buf_add_u8(buf, rp[0]);
|
||||
net_buf_add_u8(buf, rp[1]);
|
||||
for (size_t i = 0; i < cis_count; i++) {
|
||||
net_buf_add_le16(buf, sys_get_le16(rp + sizeof(struct ble_hci_le_set_cig_params_test_rp) + i * 2));
|
||||
}
|
||||
*rsp = buf;
|
||||
}
|
||||
|
||||
free(cis_params);
|
||||
free(rp);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int hci_cmd_create_cis(struct net_buf *buf, struct net_buf **rsp)
|
||||
{
|
||||
struct ble_hci_le_create_cis_params *cis_params;
|
||||
uint8_t cis_count;
|
||||
int status;
|
||||
|
||||
ARG_UNUSED(rsp);
|
||||
|
||||
assert(buf->len >= 4);
|
||||
|
||||
/* The cis_count shall be at least 1 */
|
||||
cis_count = buf->data[3];
|
||||
|
||||
assert(buf->len >= 4 + cis_count * sizeof(struct ble_hci_le_create_cis_params));
|
||||
|
||||
cis_params = calloc(1, cis_count * sizeof(struct ble_hci_le_create_cis_params));
|
||||
assert(cis_params);
|
||||
|
||||
for (size_t i = 0; i < cis_count; i++) {
|
||||
cis_params[i].cis_handle = sys_get_le16(buf->data + 4 + i * sizeof(struct ble_hci_le_create_cis_params));
|
||||
cis_params[i].conn_handle = sys_get_le16(buf->data + 6 + i * sizeof(struct ble_hci_le_create_cis_params));
|
||||
}
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
status = ble_hs_hci_create_cis(cis_count, cis_params);
|
||||
if (status) {
|
||||
LOG_ERR("[N]CreateCisFail[%u][%02x]", cis_count, status);
|
||||
}
|
||||
|
||||
ble_hs_unlock();
|
||||
|
||||
net_buf_unref(buf);
|
||||
free(cis_params);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int hci_cmd_remove_cig(struct net_buf *buf, struct net_buf **rsp)
|
||||
{
|
||||
uint8_t cig_id;
|
||||
int status;
|
||||
|
||||
ARG_UNUSED(rsp);
|
||||
|
||||
assert(buf->len >= 4);
|
||||
|
||||
cig_id = buf->data[3];
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
status = ble_hs_hci_remove_cig(cig_id);
|
||||
if (status) {
|
||||
LOG_ERR("[N]RemoveCigFail[%u][%02x]", cig_id, status);
|
||||
}
|
||||
|
||||
ble_hs_unlock();
|
||||
|
||||
net_buf_unref(buf);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int hci_cmd_accept_cis_req(struct net_buf *buf, struct net_buf **rsp)
|
||||
{
|
||||
uint16_t cis_handle;
|
||||
int status;
|
||||
|
||||
ARG_UNUSED(rsp);
|
||||
|
||||
assert(buf->len >= 5);
|
||||
|
||||
cis_handle = sys_get_le16(buf->data + 3);
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
status = ble_hs_hci_accept_cis_request(cis_handle);
|
||||
if (status) {
|
||||
LOG_ERR("[N]AcceptCisReqFail[%u][%02x]", cis_handle, status);
|
||||
}
|
||||
|
||||
ble_hs_unlock();
|
||||
|
||||
net_buf_unref(buf);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int hci_cmd_reject_cis_req(struct net_buf *buf, struct net_buf **rsp)
|
||||
{
|
||||
uint16_t cis_handle;
|
||||
uint8_t reason;
|
||||
int status;
|
||||
|
||||
ARG_UNUSED(rsp);
|
||||
|
||||
assert(buf->len >= 6);
|
||||
|
||||
cis_handle = sys_get_le16(buf->data + 3);
|
||||
reason = buf->data[5];
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
status = ble_hs_hci_reject_cis_request(cis_handle, reason);
|
||||
if (status) {
|
||||
LOG_ERR("[N]RejectCisReqFail[%u][%02x]", cis_handle, status);
|
||||
}
|
||||
|
||||
ble_hs_unlock();
|
||||
|
||||
net_buf_unref(buf);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int hci_cmd_create_big(struct net_buf *buf, struct net_buf **rsp)
|
||||
{
|
||||
uint8_t big_handle;
|
||||
uint8_t adv_handle;
|
||||
uint8_t num_bis;
|
||||
uint32_t sdu_interval;
|
||||
uint16_t max_sdu;
|
||||
uint16_t mtl;
|
||||
uint8_t rtn;
|
||||
uint8_t phy;
|
||||
uint8_t packing;
|
||||
uint8_t framing;
|
||||
uint8_t encryption;
|
||||
uint8_t *bst_code;
|
||||
int status;
|
||||
|
||||
ARG_UNUSED(rsp);
|
||||
|
||||
assert(buf->len >= 34);
|
||||
|
||||
big_handle = buf->data[3];
|
||||
adv_handle = buf->data[4];
|
||||
num_bis = buf->data[5];
|
||||
sdu_interval = sys_get_le24(buf->data + 6);
|
||||
max_sdu = sys_get_le16(buf->data + 9);
|
||||
mtl = sys_get_le16(buf->data + 11);
|
||||
rtn = buf->data[13];
|
||||
phy = buf->data[14];
|
||||
packing = buf->data[15];
|
||||
framing = buf->data[16];
|
||||
encryption = buf->data[17];
|
||||
bst_code = buf->data + 18;
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
status = ble_hs_hci_create_big(big_handle,
|
||||
adv_handle,
|
||||
num_bis,
|
||||
sdu_interval,
|
||||
max_sdu,
|
||||
mtl,
|
||||
rtn,
|
||||
phy,
|
||||
packing,
|
||||
framing,
|
||||
encryption,
|
||||
bst_code);
|
||||
if (status) {
|
||||
LOG_ERR("[N]CreateBigFail[%u][%02x]", big_handle, status);
|
||||
}
|
||||
|
||||
ble_hs_unlock();
|
||||
|
||||
net_buf_unref(buf);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int hci_cmd_create_big_test(struct net_buf *buf, struct net_buf **rsp)
|
||||
{
|
||||
uint8_t big_handle;
|
||||
uint8_t adv_handle;
|
||||
uint8_t num_bis;
|
||||
uint32_t sdu_interval;
|
||||
uint16_t iso_interval;
|
||||
uint16_t max_sdu;
|
||||
uint16_t max_pdu;
|
||||
uint8_t nse;
|
||||
uint8_t phy;
|
||||
uint8_t packing;
|
||||
uint8_t framing;
|
||||
uint8_t bn;
|
||||
uint8_t irc;
|
||||
uint8_t pto;
|
||||
uint8_t encryption;
|
||||
uint8_t *bst_code;
|
||||
int status;
|
||||
|
||||
ARG_UNUSED(rsp);
|
||||
|
||||
assert(buf->len >= 39);
|
||||
|
||||
big_handle = buf->data[3];
|
||||
adv_handle = buf->data[4];
|
||||
num_bis = buf->data[5];
|
||||
sdu_interval = sys_get_le24(buf->data + 6);
|
||||
iso_interval = sys_get_le16(buf->data + 9);
|
||||
nse = buf->data[11];
|
||||
max_sdu = sys_get_le16(buf->data + 12);
|
||||
max_pdu = sys_get_le16(buf->data + 14);
|
||||
phy = buf->data[16];
|
||||
packing = buf->data[17];
|
||||
framing = buf->data[18];
|
||||
bn = buf->data[19];
|
||||
irc = buf->data[20];
|
||||
pto = buf->data[21];
|
||||
encryption = buf->data[22];
|
||||
bst_code = buf->data + 23;
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
status = ble_hs_hci_create_big_test(big_handle,
|
||||
adv_handle,
|
||||
num_bis,
|
||||
sdu_interval,
|
||||
iso_interval,
|
||||
nse,
|
||||
max_sdu,
|
||||
max_pdu,
|
||||
phy,
|
||||
packing,
|
||||
framing,
|
||||
bn,
|
||||
irc,
|
||||
pto,
|
||||
encryption,
|
||||
bst_code);
|
||||
if (status) {
|
||||
LOG_ERR("[N]CreateBigTestFail[%u][%02x]", big_handle, status);
|
||||
}
|
||||
|
||||
ble_hs_unlock();
|
||||
|
||||
net_buf_unref(buf);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int hci_cmd_terminate_big(struct net_buf *buf, struct net_buf **rsp)
|
||||
{
|
||||
uint8_t big_handle;
|
||||
uint8_t reason;
|
||||
int status;
|
||||
|
||||
ARG_UNUSED(rsp);
|
||||
|
||||
assert(buf->len >= 5);
|
||||
|
||||
big_handle = buf->data[3];
|
||||
reason = buf->data[4];
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
status = ble_hs_hci_terminate_big(big_handle, reason);
|
||||
if (status) {
|
||||
LOG_ERR("[N]TerminateBigFail[%u][%02x]", big_handle, status);
|
||||
}
|
||||
|
||||
ble_hs_unlock();
|
||||
|
||||
net_buf_unref(buf);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int hci_cmd_big_create_sync(struct net_buf *buf, struct net_buf **rsp)
|
||||
{
|
||||
uint16_t sync_timeout;
|
||||
uint16_t sync_handle;
|
||||
uint8_t big_handle;
|
||||
uint8_t encryption;
|
||||
uint8_t *bst_code;
|
||||
uint8_t num_bis;
|
||||
uint8_t *bis;
|
||||
uint8_t mse;
|
||||
int status;
|
||||
|
||||
ARG_UNUSED(rsp);
|
||||
|
||||
assert(buf->len >= 27);
|
||||
|
||||
big_handle = buf->data[3];
|
||||
sync_handle = sys_get_le16(buf->data + 4);
|
||||
encryption = buf->data[6];
|
||||
bst_code = buf->data + 7;
|
||||
mse = buf->data[23];
|
||||
sync_timeout = sys_get_le16(buf->data + 24);
|
||||
num_bis = buf->data[26];
|
||||
bis = buf->data + 27;
|
||||
|
||||
assert(buf->len >= 27 + num_bis);
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
status = ble_hs_hci_big_create_sync(big_handle,
|
||||
sync_handle,
|
||||
encryption,
|
||||
bst_code,
|
||||
mse,
|
||||
sync_timeout,
|
||||
num_bis,
|
||||
bis);
|
||||
if (status) {
|
||||
LOG_ERR("[N]BigCreateSyncFail[%u][%02x]", big_handle, status);
|
||||
}
|
||||
|
||||
ble_hs_unlock();
|
||||
|
||||
net_buf_unref(buf);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int hci_cmd_big_terminate_sync(struct net_buf *buf, struct net_buf **rsp)
|
||||
{
|
||||
uint8_t big_handle;
|
||||
int status;
|
||||
|
||||
assert(rsp);
|
||||
|
||||
assert(buf->len >= 4);
|
||||
|
||||
big_handle = buf->data[3];
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
status = ble_hs_hci_big_terminate_sync(big_handle);
|
||||
if (status) {
|
||||
LOG_ERR("[N]BigTerminateSyncFail[%u][%02x]", big_handle, status);
|
||||
}
|
||||
|
||||
ble_hs_unlock();
|
||||
|
||||
if (status) {
|
||||
net_buf_unref(buf);
|
||||
*rsp = NULL;
|
||||
} else {
|
||||
net_buf_reset(buf);
|
||||
net_buf_add_u8(buf, status);
|
||||
net_buf_add_u8(buf, big_handle);
|
||||
*rsp = buf;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int hci_cmd_setup_iso_data_path(struct net_buf *buf, struct net_buf **rsp)
|
||||
{
|
||||
uint8_t data_path_direction;
|
||||
uint32_t controller_delay;
|
||||
uint16_t conn_handle;
|
||||
uint8_t data_path_id;
|
||||
uint8_t coding_format;
|
||||
uint16_t company_id;
|
||||
uint16_t vs_codec_id;
|
||||
uint8_t codec_cfg_len;
|
||||
uint8_t *codec_cfg;
|
||||
int status;
|
||||
|
||||
assert(rsp);
|
||||
|
||||
assert(buf->len >= 16);
|
||||
|
||||
conn_handle = sys_get_le16(buf->data + 3);
|
||||
data_path_direction = buf->data[5];
|
||||
data_path_id = buf->data[6];
|
||||
coding_format = buf->data[7];
|
||||
company_id = sys_get_le16(buf->data + 8);
|
||||
vs_codec_id = sys_get_le16(buf->data + 10);
|
||||
controller_delay = sys_get_le24(buf->data + 12);
|
||||
codec_cfg_len = buf->data[15];
|
||||
codec_cfg = buf->data + 16;
|
||||
|
||||
assert(buf->len >= 16 + codec_cfg_len);
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
status = ble_hs_hci_setup_iso_data_path(conn_handle,
|
||||
data_path_direction,
|
||||
data_path_id,
|
||||
coding_format,
|
||||
company_id,
|
||||
vs_codec_id,
|
||||
controller_delay,
|
||||
codec_cfg_len,
|
||||
codec_cfg);
|
||||
if (status) {
|
||||
LOG_ERR("[N]SetupIsoDataPathFail[%u][%02x]", conn_handle, status);
|
||||
}
|
||||
|
||||
ble_hs_unlock();
|
||||
|
||||
if (status) {
|
||||
net_buf_unref(buf);
|
||||
*rsp = NULL;
|
||||
} else {
|
||||
net_buf_reset(buf);
|
||||
net_buf_add_u8(buf, status);
|
||||
net_buf_add_le16(buf, conn_handle);
|
||||
*rsp = buf;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int hci_cmd_remove_iso_data_path(struct net_buf *buf, struct net_buf **rsp)
|
||||
{
|
||||
uint8_t data_path_direction;
|
||||
uint16_t conn_handle;
|
||||
int status;
|
||||
|
||||
assert(rsp);
|
||||
|
||||
assert(buf->len >= 6);
|
||||
|
||||
conn_handle = sys_get_le16(buf->data + 3);
|
||||
data_path_direction = buf->data[5];
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
status = ble_hs_hci_remove_iso_data_path(conn_handle, data_path_direction);
|
||||
if (status) {
|
||||
LOG_ERR("[N]RemoveIsoDataPathFail[%u][%02x]", conn_handle, status);
|
||||
}
|
||||
|
||||
ble_hs_unlock();
|
||||
|
||||
if (status) {
|
||||
net_buf_unref(buf);
|
||||
*rsp = NULL;
|
||||
} else {
|
||||
net_buf_reset(buf);
|
||||
net_buf_add_u8(buf, status);
|
||||
net_buf_add_le16(buf, conn_handle);
|
||||
*rsp = buf;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int bt_le_nimble_iso_cmd_send_sync(uint16_t opcode,
|
||||
struct net_buf *buf,
|
||||
struct net_buf **rsp)
|
||||
{
|
||||
switch (opcode) {
|
||||
case BT_HCI_OP_LE_READ_ISO_TX_SYNC:
|
||||
return hci_cmd_read_iso_tx_sync(buf, rsp);
|
||||
|
||||
case BT_HCI_OP_LE_SET_CIG_PARAMS:
|
||||
return hci_cmd_set_cig_params(buf, rsp);
|
||||
|
||||
case BT_HCI_OP_LE_SET_CIG_PARAMS_TEST:
|
||||
return hci_cmd_set_cig_params_test(buf, rsp);
|
||||
|
||||
case BT_HCI_OP_LE_CREATE_CIS:
|
||||
return hci_cmd_create_cis(buf, rsp);
|
||||
|
||||
case BT_HCI_OP_LE_REMOVE_CIG:
|
||||
return hci_cmd_remove_cig(buf, rsp);
|
||||
|
||||
case BT_HCI_OP_LE_ACCEPT_CIS:
|
||||
return hci_cmd_accept_cis_req(buf, rsp);
|
||||
|
||||
case BT_HCI_OP_LE_REJECT_CIS:
|
||||
return hci_cmd_reject_cis_req(buf, rsp);
|
||||
|
||||
case BT_HCI_OP_LE_CREATE_BIG:
|
||||
return hci_cmd_create_big(buf, rsp);
|
||||
|
||||
case BT_HCI_OP_LE_CREATE_BIG_TEST:
|
||||
return hci_cmd_create_big_test(buf, rsp);
|
||||
|
||||
case BT_HCI_OP_LE_TERMINATE_BIG:
|
||||
return hci_cmd_terminate_big(buf, rsp);
|
||||
|
||||
case BT_HCI_OP_LE_BIG_CREATE_SYNC:
|
||||
return hci_cmd_big_create_sync(buf, rsp);
|
||||
|
||||
case BT_HCI_OP_LE_BIG_TERMINATE_SYNC:
|
||||
return hci_cmd_big_terminate_sync(buf, rsp);
|
||||
|
||||
case BT_HCI_OP_LE_SETUP_ISO_PATH:
|
||||
return hci_cmd_setup_iso_data_path(buf, rsp);
|
||||
|
||||
case BT_HCI_OP_LE_REMOVE_ISO_PATH:
|
||||
return hci_cmd_remove_iso_data_path(buf, rsp);
|
||||
|
||||
default:
|
||||
LOG_ERR("[N]IsoCmdNotSupp[%04x]", opcode);
|
||||
net_buf_unref(buf);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
static void iso_evt_rx(uint8_t event, const void *data,
|
||||
unsigned int len, bool le_meta)
|
||||
{
|
||||
size_t qdata_len;
|
||||
uint8_t *qdata;
|
||||
int err;
|
||||
|
||||
if (event != BT_HCI_EVT_LE_BIGINFO_ADV_REPORT) {
|
||||
LOG_DBG("[N]ISOEvtRx[%02x][%u][%u]", event, len, le_meta);
|
||||
}
|
||||
|
||||
qdata_len = len + 2;
|
||||
|
||||
qdata = calloc(1, qdata_len);
|
||||
assert(qdata);
|
||||
|
||||
qdata[0] = le_meta;
|
||||
qdata[1] = event;
|
||||
memcpy(qdata + 2, data, len);
|
||||
|
||||
err = bt_le_iso_task_post(ISO_QUEUE_ITEM_TYPE_ISO_HCI_EVENT, qdata, qdata_len);
|
||||
if (err) {
|
||||
LOG_ERR("[N]IsoPostEvtFail[%d][%02x]", err, event);
|
||||
free(qdata);
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_BT_ISO_UNICAST
|
||||
static int iso_enable_cis(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
err = ble_hs_hci_set_host_feature(32, 1);
|
||||
if (err) {
|
||||
LOG_ERR("[N]IsoEnableCisFail[%d]", err);
|
||||
}
|
||||
|
||||
ble_hs_unlock();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int iso_disable_cis(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
err = ble_hs_hci_set_host_feature(32, 0);
|
||||
if (err) {
|
||||
LOG_ERR("[N]IsoDisableCisFail[%d]", err);
|
||||
}
|
||||
|
||||
ble_hs_unlock();
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_ISO_UNICAST */
|
||||
|
||||
int bt_le_nimble_iso_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = ble_hs_iso_evt_rx_cb_set(iso_evt_rx);
|
||||
if (err) {
|
||||
LOG_ERR("[N]IsoEvtRxCbSetFail[%d]", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_ISO_RX
|
||||
err = ble_hs_iso_pkt_rx_cb_set(bt_le_iso_rx);
|
||||
if (err) {
|
||||
LOG_ERR("[N]IsoPktRxCbSetFail[%d]", err);
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_ISO_RX */
|
||||
|
||||
#if CONFIG_BT_ISO_UNICAST
|
||||
/* Set Connected Isochronous Streams - Host support */
|
||||
err = iso_enable_cis();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_ISO_UNICAST */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bt_le_nimble_iso_deinit(void)
|
||||
{
|
||||
LOG_DBG("IsoDeinit");
|
||||
|
||||
ble_hs_iso_evt_rx_cb_set(NULL);
|
||||
|
||||
#if CONFIG_BT_ISO_RX
|
||||
ble_hs_iso_pkt_rx_cb_set(NULL);
|
||||
#endif /* CONFIG_BT_ISO_RX */
|
||||
|
||||
#if CONFIG_BT_ISO_UNICAST
|
||||
iso_disable_cis();
|
||||
#endif /* CONFIG_BT_ISO_UNICAST */
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef HOST_NIMBLE_ISO_H_
|
||||
#define HOST_NIMBLE_ISO_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int bt_le_nimble_iso_cmd_send_sync(uint16_t opcode,
|
||||
struct net_buf *buf,
|
||||
struct net_buf **rsp);
|
||||
|
||||
int bt_le_nimble_iso_init(void);
|
||||
|
||||
void bt_le_nimble_iso_deinit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HOST_NIMBLE_ISO_H_ */
|
||||
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/bluetooth/l2cap.h>
|
||||
|
||||
#include <../host/conn_internal.h>
|
||||
|
||||
#include "host/ble_hs.h"
|
||||
#include "host/ble_l2cap.h"
|
||||
#include "host/ble_hs_mbuf.h"
|
||||
#include "../../../nimble/host/src/ble_l2cap_priv.h"
|
||||
|
||||
#include "common/host.h"
|
||||
|
||||
_Static_assert(CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM && "At least one L2CAP coc shall be supported");
|
||||
|
||||
#define OTS_L2CAP_BUF_COUNT (3 * CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM)
|
||||
#define OTS_L2CAP_MEM_SIZE OS_MEMPOOL_SIZE(OTS_L2CAP_BUF_COUNT, L2CAP_LE_OTS_MTU * 2)
|
||||
|
||||
static os_membuf_t ots_mem[OTS_L2CAP_MEM_SIZE];
|
||||
static struct os_mempool ots_mbuf_mempool;
|
||||
static struct os_mbuf_pool ots_mbuf_pool;
|
||||
|
||||
static struct ble_l2cap_chan *ots_chan;
|
||||
|
||||
static int ots_l2cap_recv_ready(struct ble_l2cap_chan *chan)
|
||||
{
|
||||
struct os_mbuf *sdu_rx;
|
||||
int rc;
|
||||
|
||||
LOG_DBG("[N]OtsRecvReady");
|
||||
|
||||
sdu_rx = os_mbuf_get_pkthdr(&ots_mbuf_pool, 0);
|
||||
if (sdu_rx == NULL) {
|
||||
LOG_ERR("[N]NoBufForL2capRecv");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rc = ble_l2cap_recv_ready(chan, sdu_rx);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]L2capRecvFail[%d]", rc);
|
||||
|
||||
os_mbuf_free_chain(sdu_rx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ots_l2cap_event_cb(struct ble_l2cap_event *event, void *arg)
|
||||
{
|
||||
struct ble_l2cap_chan_info chan_info;
|
||||
uint16_t result = 0;
|
||||
size_t sdu_len;
|
||||
uint8_t *sdu;
|
||||
int err;
|
||||
|
||||
LOG_DBG("[N]OtsEvtCb[%u]", event->type);
|
||||
|
||||
switch (event->type) {
|
||||
case BLE_L2CAP_EVENT_COC_CONNECTED:
|
||||
if (event->connect.status) {
|
||||
LOG_ERR("[N]CocConnectFail[%d]", event->connect.status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ots_chan) {
|
||||
LOG_ERR("[N]CocChanExist");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ots_chan = event->connect.chan;
|
||||
|
||||
if (ble_l2cap_get_chan_info(event->connect.chan, &chan_info)) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
LOG_DBG("[N]CocConnect[%u][%04x][%04x][%04x][%u][%u][%u][%u]",
|
||||
event->connect.conn_handle, chan_info.scid, chan_info.dcid,
|
||||
chan_info.psm, chan_info.our_l2cap_mtu, chan_info.peer_l2cap_mtu,
|
||||
chan_info.our_coc_mtu, chan_info.peer_coc_mtu);
|
||||
|
||||
bt_le_l2cap_connected(event->connect.conn_handle, chan_info.psm,
|
||||
chan_info.dcid, chan_info.peer_coc_mtu,
|
||||
chan_info.scid, chan_info.our_coc_mtu);
|
||||
return 0;
|
||||
|
||||
case BLE_L2CAP_EVENT_COC_DISCONNECTED:
|
||||
if (ots_chan != event->disconnect.chan) {
|
||||
LOG_ERR("[N]DisconnectInvCocChan");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG_DBG("[N]CocDisconnect[%u][%04x]",
|
||||
event->disconnect.conn_handle, event->disconnect.chan->psm);
|
||||
|
||||
bt_le_l2cap_disconnected(event->disconnect.conn_handle, event->disconnect.chan->psm);
|
||||
|
||||
ots_chan = NULL;
|
||||
return 0;
|
||||
|
||||
case BLE_L2CAP_EVENT_COC_ACCEPT:
|
||||
if (event->accept.peer_sdu_size > L2CAP_LE_OTS_MTU) {
|
||||
LOG_ERR("[N]InvAcceptMtu[%u][%u]",
|
||||
event->accept.peer_sdu_size, L2CAP_LE_OTS_MTU);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
LOG_DBG("[N]CocAccept[%u][%04x][%04x][%u][%u][%u][%u]",
|
||||
event->accept.conn_handle, event->accept.chan->psm,
|
||||
event->accept.chan->dcid, event->accept.chan->coc_tx.mtu,
|
||||
event->accept.chan->peer_coc_mps, event->accept.peer_sdu_size,
|
||||
event->accept.chan->coc_tx.credits);
|
||||
|
||||
err = bt_le_l2cap_accept(event->accept.conn_handle,
|
||||
event->accept.chan->psm,
|
||||
event->accept.chan->dcid,
|
||||
event->accept.chan->coc_tx.mtu,
|
||||
event->accept.chan->peer_coc_mps,
|
||||
event->accept.chan->coc_tx.credits,
|
||||
&result);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
ARG_UNUSED(result);
|
||||
|
||||
return ots_l2cap_recv_ready(event->accept.chan);
|
||||
|
||||
case BLE_L2CAP_EVENT_COC_DATA_RECEIVED:
|
||||
if (ots_chan != event->receive.chan) {
|
||||
LOG_ERR("[N]RecvOnInvCocChan");
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(event->receive.sdu_rx);
|
||||
|
||||
LOG_DBG("[N]CocReceive[%u][%04x][%u]",
|
||||
event->receive.conn_handle, event->receive.chan->psm,
|
||||
event->receive.sdu_rx->om_len);
|
||||
|
||||
sdu_len = OS_MBUF_PKTLEN(event->receive.sdu_rx);
|
||||
|
||||
sdu = calloc(1, sdu_len);
|
||||
assert(sdu);
|
||||
|
||||
err = os_mbuf_copydata(event->receive.sdu_rx, 0, sdu_len, sdu);
|
||||
assert(err == 0);
|
||||
|
||||
bt_le_l2cap_received(event->receive.conn_handle,
|
||||
event->receive.chan->psm,
|
||||
sdu, sdu_len);
|
||||
|
||||
os_mbuf_free_chain(event->receive.sdu_rx);
|
||||
free(sdu);
|
||||
|
||||
return ots_l2cap_recv_ready(event->receive.chan);
|
||||
|
||||
case BLE_L2CAP_EVENT_COC_TX_UNSTALLED:
|
||||
if (ots_chan != event->tx_unstalled.chan) {
|
||||
LOG_ERR("[N]TxUnstalledOnInvCocChan");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG_DBG("[N]CocTxUnstalled[%u][%d]",
|
||||
event->tx_unstalled.conn_handle, event->tx_unstalled.status);
|
||||
|
||||
/* TODO: transmit the remaining data */
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int bt_le_nimble_l2cap_chan_connect(uint16_t conn_handle)
|
||||
{
|
||||
struct os_mbuf *sdu_rx;
|
||||
int rc;
|
||||
|
||||
if (ots_chan) {
|
||||
LOG_WRN("[N]OtsChanExist");
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
sdu_rx = os_mbuf_get_pkthdr(&ots_mbuf_pool, 0);
|
||||
if (sdu_rx == NULL) {
|
||||
LOG_ERR("[N]NoBufForL2capConnect");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rc = ble_l2cap_connect(conn_handle, L2CAP_LE_OTS_PSM, L2CAP_LE_OTS_MTU,
|
||||
sdu_rx, ots_l2cap_event_cb, NULL);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]L2capConnectFail[%d]", rc);
|
||||
|
||||
os_mbuf_free_chain(sdu_rx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_le_nimble_l2cap_chan_disconnect(struct bt_l2cap_chan *chan)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (ots_chan == NULL) {
|
||||
LOG_WRN("[N]NoOtsChan");
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
if (ble_l2cap_get_conn_handle(ots_chan) != chan->conn->handle) {
|
||||
LOG_ERR("[N]UnexpOtsChan[%u][%u]",
|
||||
ble_l2cap_get_conn_handle(ots_chan), chan->conn->handle);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = ble_l2cap_disconnect(ots_chan);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]L2capDisconnectFail[%d]", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_le_nimble_l2cap_chan_send(struct bt_l2cap_chan *chan, struct net_buf *buf)
|
||||
{
|
||||
struct os_mbuf *sdu_tx;
|
||||
int rc;
|
||||
|
||||
if (ots_chan == NULL) {
|
||||
LOG_WRN("[N]NoOtsChan");
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
if (ble_l2cap_get_conn_handle(ots_chan) != chan->conn->handle) {
|
||||
LOG_ERR("[N]UnexpOtsChan[%u][%u]",
|
||||
ble_l2cap_get_conn_handle(ots_chan), chan->conn->handle);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sdu_tx = os_mbuf_get_pkthdr(&ots_mbuf_pool, 0);
|
||||
if (sdu_tx == NULL) {
|
||||
LOG_ERR("[N]NoBufForL2capSend");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rc = os_mbuf_append(sdu_tx, buf->data, buf->len);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]AppendBufFail[%d]", rc);
|
||||
os_mbuf_free_chain(sdu_tx);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
rc = ble_l2cap_send(ots_chan, sdu_tx);
|
||||
if (rc) {
|
||||
if (rc == BLE_HS_ESTALLED) {
|
||||
/* TODO:
|
||||
* Wait for the BLE_L2CAP_EVENT_COC_TX_UNSTALLED event and continue.
|
||||
*/
|
||||
LOG_WRN("[N]MoreCreditsForL2capSend");
|
||||
} else {
|
||||
LOG_ERR("[N]L2capSendFail[%d]", rc);
|
||||
}
|
||||
|
||||
os_mbuf_free_chain(sdu_tx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_le_nimble_l2cap_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = os_mempool_init(&ots_mbuf_mempool, OTS_L2CAP_BUF_COUNT, L2CAP_LE_OTS_MTU * 2, ots_mem, "ots_pool");
|
||||
if (rc) {
|
||||
LOG_ERR("[N]InitOtsMempoolFail[%d]", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = os_mbuf_pool_init(&ots_mbuf_pool, &ots_mbuf_mempool, L2CAP_LE_OTS_MTU, OTS_L2CAP_BUF_COUNT);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]InitOtsMbufPoolFail[%d]", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_OTS
|
||||
rc = ble_l2cap_create_server(L2CAP_LE_OTS_PSM, L2CAP_LE_OTS_MTU, ots_l2cap_event_cb, NULL);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]CreateL2capSrvFail[%d]", rc);
|
||||
return rc;
|
||||
}
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bt_le_nimble_l2cap_deinit(void)
|
||||
{
|
||||
LOG_DBG("NimbleL2capDeinit");
|
||||
|
||||
/* TODO: free the ots_mbuf_pool and ots_mbuf_mempool */
|
||||
|
||||
#if CONFIG_BT_OTS
|
||||
/* TODO: destroy the server */
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef HOST_NIMBLE_L2CAP_H_
|
||||
#define HOST_NIMBLE_L2CAP_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <zephyr/bluetooth/l2cap.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int bt_le_nimble_l2cap_chan_connect(uint16_t conn_handle);
|
||||
|
||||
int bt_le_nimble_l2cap_chan_disconnect(struct bt_l2cap_chan *chan);
|
||||
|
||||
int bt_le_nimble_l2cap_chan_send(struct bt_l2cap_chan *chan, struct net_buf *buf);
|
||||
|
||||
int bt_le_nimble_l2cap_init(void);
|
||||
|
||||
void bt_le_nimble_l2cap_deinit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HOST_NIMBLE_L2CAP_H_ */
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <zephyr/autoconf.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/bluetooth/uuid.h>
|
||||
#include <zephyr/bluetooth/gatt.h>
|
||||
|
||||
#include <../host/conn_internal.h>
|
||||
|
||||
#include "os/os_mbuf.h"
|
||||
#include "os/os_mempool.h"
|
||||
#include "host/ble_att.h"
|
||||
#include "host/ble_gatt.h"
|
||||
#include "host/ble_hs_mbuf.h"
|
||||
|
||||
#include "nimble/profiles/server.h"
|
||||
|
||||
#include "common/host.h"
|
||||
|
||||
#include "../../../lib/include/audio.h"
|
||||
|
||||
static const ble_uuid16_t ascs_uuid_ase_cp = BLE_UUID16_INIT(BT_UUID_ASCS_ASE_CP_VAL);
|
||||
static const ble_uuid16_t ascs_uuid_ase_snk = BLE_UUID16_INIT(BT_UUID_ASCS_ASE_SNK_VAL);
|
||||
static const ble_uuid16_t ascs_uuid_ase_src = BLE_UUID16_INIT(BT_UUID_ASCS_ASE_SRC_VAL);
|
||||
|
||||
static uint16_t ase_control_point_handle;
|
||||
static uint16_t ase_snk_handle[CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT];
|
||||
static uint16_t ase_src_handle[CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT];
|
||||
|
||||
static struct ble_gatt_svc_def gatt_svc_ascs[] = {
|
||||
{
|
||||
/* Audio Stream Control Service */
|
||||
.type = BLE_GATT_SVC_TYPE_PRIMARY,
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_ASCS_VAL),
|
||||
.includes = NULL,
|
||||
.characteristics = NULL,
|
||||
},
|
||||
{
|
||||
0, /* No more services. */
|
||||
},
|
||||
};
|
||||
|
||||
static void ascs_svc_add_ase_cp_chr(struct ble_gatt_chr_def *chr)
|
||||
{
|
||||
LOG_DBG("[N]AscsSvcAddAseCpChr");
|
||||
|
||||
chr->uuid = &ascs_uuid_ase_cp.u;
|
||||
chr->access_cb = bt_le_nimble_gatts_access_cb_safe;
|
||||
chr->arg = NULL;
|
||||
chr->descriptors = NULL; /* NULL if no descriptors. Do not include CCCD */
|
||||
chr->flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_NO_RSP | \
|
||||
BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_WRITE_ENC;
|
||||
chr->min_key_size = 16;
|
||||
chr->val_handle = &ase_control_point_handle;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT > 0
|
||||
static void ascs_svc_add_ase_snk_chr(struct ble_gatt_chr_def *chrs)
|
||||
{
|
||||
for (size_t i = 0 ; i < CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT; i++) {
|
||||
struct ble_gatt_chr_def *chr = chrs + i;
|
||||
|
||||
LOG_DBG("[N]AscsSvcAddAseSnkChr[%u]", i);
|
||||
|
||||
chr->uuid = &ascs_uuid_ase_snk.u;
|
||||
chr->access_cb = bt_le_nimble_gatts_access_cb_safe;
|
||||
chr->arg = UINT_TO_POINTER(i);
|
||||
chr->descriptors = NULL; /* NULL if no descriptors. Do not include CCCD */
|
||||
chr->flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC;
|
||||
chr->min_key_size = 16;
|
||||
chr->val_handle = &ase_snk_handle[i];
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT > 0 */
|
||||
|
||||
#if CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT > 0
|
||||
static void ascs_svc_add_ase_src_chr(struct ble_gatt_chr_def *chrs)
|
||||
{
|
||||
for (size_t i = 0 ; i < CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT; i++) {
|
||||
struct ble_gatt_chr_def *chr = chrs + i;
|
||||
|
||||
LOG_DBG("[N]AscsSvcAddAseSrcChr[%u]", i);
|
||||
|
||||
chr->uuid = &ascs_uuid_ase_src.u;
|
||||
chr->access_cb = bt_le_nimble_gatts_access_cb_safe;
|
||||
chr->arg = UINT_TO_POINTER(i);
|
||||
chr->descriptors = NULL; /* NULL if no descriptors. Do not include CCCD */
|
||||
chr->flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC;
|
||||
chr->min_key_size = 16;
|
||||
chr->val_handle = &ase_src_handle[i];
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT > 0 */
|
||||
|
||||
int bt_le_nimble_ascs_attr_handle_set(void)
|
||||
{
|
||||
struct bt_gatt_service *ascs_svc;
|
||||
struct bt_gatt_attr *attr;
|
||||
uint16_t start_handle;
|
||||
uint16_t end_handle;
|
||||
|
||||
ascs_svc = lib_ascs_svc_get();
|
||||
assert(ascs_svc);
|
||||
|
||||
assert(ase_control_point_handle >= 2);
|
||||
start_handle = ase_control_point_handle - 2; /* server attr handle & char def handle */
|
||||
#if CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT > 0
|
||||
end_handle = ase_src_handle[CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT - 1] + 1; /* cccd attr handle */
|
||||
#elif CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT > 0
|
||||
end_handle = ase_snk_handle[CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT - 1] + 1; /* cccd attr handle */
|
||||
#else
|
||||
end_handle = ase_control_point_handle + 1; /* cccd attr handle */
|
||||
#endif
|
||||
|
||||
LOG_DBG("[N]AscsAttrHdlSet[%u][%u][%u]",
|
||||
start_handle, end_handle, ascs_svc->attr_count);
|
||||
|
||||
for (size_t i = 0; i < ascs_svc->attr_count; i++) {
|
||||
(ascs_svc->attrs + i)->handle = start_handle + i;
|
||||
}
|
||||
|
||||
/* Last attribute in ASCS */
|
||||
attr = ascs_svc->attrs + ascs_svc->attr_count - 1;
|
||||
|
||||
if (attr->handle != end_handle) {
|
||||
LOG_ERR("[N]AscsMismatchAttrHhl[%u][%u][%u][%u]",
|
||||
start_handle, end_handle, attr->handle, ascs_svc->attr_count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ascs_svc_check(void)
|
||||
{
|
||||
struct bt_gatt_service *ascs_svc;
|
||||
const struct bt_uuid_16 *uuid;
|
||||
bool chr_found;
|
||||
|
||||
/* This function is used to make sure the characteristics within
|
||||
* the service exist in the service defined by Zephyr.
|
||||
*/
|
||||
|
||||
ascs_svc = lib_ascs_svc_get();
|
||||
assert(ascs_svc);
|
||||
|
||||
LOG_DBG("[N]AscsSvcCheck");
|
||||
|
||||
for (const struct ble_gatt_chr_def *chr = gatt_svc_ascs[0].characteristics;
|
||||
chr && chr->uuid; chr++) {
|
||||
const ble_uuid16_t *check = (const ble_uuid16_t *)chr->uuid;
|
||||
|
||||
chr_found = false;
|
||||
|
||||
for (size_t i = 0; i < ascs_svc->attr_count; i++) {
|
||||
uuid = (const struct bt_uuid_16 *)(ascs_svc->attrs + i)->uuid;
|
||||
|
||||
if (uuid && uuid->uuid.type == BT_LE_NIMBLE_GATT_UUID_TO_Z(check->u.type) &&
|
||||
uuid->val == check->value) {
|
||||
chr_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (chr_found == false) {
|
||||
LOG_ERR("[N]AscsChrNotFound[%04x]", check->value);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_le_nimble_ascs_init(void)
|
||||
{
|
||||
uint16_t chr_count;
|
||||
int rc;
|
||||
|
||||
/* An additional characteristic consist of all 0s indicating end of characteristics */
|
||||
chr_count = 1 + CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT + CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT + 1;
|
||||
|
||||
LOG_DBG("[N]AscsInit[%u]", chr_count);
|
||||
|
||||
gatt_svc_ascs[0].characteristics = calloc(chr_count, sizeof(struct ble_gatt_chr_def));
|
||||
assert(gatt_svc_ascs[0].characteristics);
|
||||
|
||||
ascs_svc_add_ase_cp_chr((void *)(gatt_svc_ascs[0].characteristics + 0));
|
||||
|
||||
#if CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT > 0
|
||||
ascs_svc_add_ase_snk_chr((void *)(gatt_svc_ascs[0].characteristics + 1));
|
||||
#endif /* CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT > 0 */
|
||||
|
||||
#if CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT > 0
|
||||
ascs_svc_add_ase_src_chr((void *)(gatt_svc_ascs[0].characteristics + 1 + CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT));
|
||||
#endif /* CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT > 0 */
|
||||
|
||||
rc = ble_gatts_count_cfg(gatt_svc_ascs);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]AscsCountCfgFail[%d]", rc);
|
||||
goto free;
|
||||
}
|
||||
|
||||
rc = ble_gatts_add_svcs(gatt_svc_ascs);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]AscsAddSvcsFail[%d]", rc);
|
||||
goto free;
|
||||
}
|
||||
|
||||
rc = ascs_svc_check();
|
||||
if (rc) {
|
||||
goto free;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
free:
|
||||
free((void *)gatt_svc_ascs[0].characteristics);
|
||||
gatt_svc_ascs[0].characteristics = NULL;
|
||||
return rc;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef HOST_NIMBLE_PROFILE_ASCS_H_
|
||||
#define HOST_NIMBLE_PROFILE_ASCS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int bt_le_nimble_ascs_attr_handle_set(void);
|
||||
|
||||
int bt_le_nimble_ascs_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HOST_NIMBLE_PROFILE_ASCS_H_ */
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <zephyr/autoconf.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/bluetooth/uuid.h>
|
||||
#include <zephyr/bluetooth/gatt.h>
|
||||
|
||||
#include <../host/conn_internal.h>
|
||||
|
||||
#include "os/os_mbuf.h"
|
||||
#include "os/os_mempool.h"
|
||||
#include "host/ble_att.h"
|
||||
#include "host/ble_gatt.h"
|
||||
#include "host/ble_hs_mbuf.h"
|
||||
|
||||
#include "nimble/profiles/server.h"
|
||||
|
||||
#include "common/host.h"
|
||||
|
||||
#include "../../../lib/include/audio.h"
|
||||
|
||||
static const ble_uuid16_t bass_uuid_control_point = BLE_UUID16_INIT(BT_UUID_BASS_CONTROL_POINT_VAL);
|
||||
static const ble_uuid16_t bass_uuid_recv_state = BLE_UUID16_INIT(BT_UUID_BASS_RECV_STATE_VAL);
|
||||
|
||||
static uint16_t bass_control_point_handle;
|
||||
static uint16_t bass_recv_state_handle[CONFIG_BT_BAP_SCAN_DELEGATOR_RECV_STATE_COUNT];
|
||||
|
||||
static struct ble_gatt_svc_def gatt_svc_bass[] = {
|
||||
{
|
||||
/* Broadcast Audio Scan Service */
|
||||
.type = BLE_GATT_SVC_TYPE_PRIMARY,
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_BASS_VAL),
|
||||
.includes = NULL,
|
||||
.characteristics = NULL,
|
||||
},
|
||||
{
|
||||
0, /* No more services. */
|
||||
},
|
||||
};
|
||||
|
||||
static void bass_svc_add_control_point_chr(struct ble_gatt_chr_def *chr)
|
||||
{
|
||||
LOG_DBG("[N]BassSvcAddControlPointChr");
|
||||
|
||||
chr->uuid = &bass_uuid_control_point.u;
|
||||
chr->access_cb = bt_le_nimble_gatts_access_cb_safe;
|
||||
chr->arg = NULL;
|
||||
chr->descriptors = NULL; /* NULL if no descriptors. Do not include CCCD */
|
||||
chr->flags = BLE_GATT_CHR_F_WRITE_NO_RSP | BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_ENC;
|
||||
chr->min_key_size = 16;
|
||||
chr->val_handle = &bass_control_point_handle;
|
||||
}
|
||||
|
||||
static void bass_svc_add_recv_state_chr(struct ble_gatt_chr_def *chrs)
|
||||
{
|
||||
for (size_t i = 0 ; i < CONFIG_BT_BAP_SCAN_DELEGATOR_RECV_STATE_COUNT; i++) {
|
||||
struct ble_gatt_chr_def *chr = chrs + i;
|
||||
|
||||
LOG_DBG("[N]BassSvcAddRecvStateChr[%u]", i);
|
||||
|
||||
chr->uuid = &bass_uuid_recv_state.u;
|
||||
chr->access_cb = bt_le_nimble_gatts_access_cb_safe;
|
||||
chr->arg = UINT_TO_POINTER(i);
|
||||
chr->descriptors = NULL; /* NULL if no descriptors. Do not include CCCD */
|
||||
chr->flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC;
|
||||
chr->min_key_size = 16;
|
||||
chr->val_handle = &bass_recv_state_handle[i];
|
||||
}
|
||||
}
|
||||
|
||||
int bt_le_nimble_bass_attr_handle_set(void)
|
||||
{
|
||||
struct bt_gatt_service *bass_svc;
|
||||
struct bt_gatt_attr *attr;
|
||||
uint16_t start_handle;
|
||||
uint16_t end_handle;
|
||||
|
||||
bass_svc = lib_bap_bass_svc_get();
|
||||
assert(bass_svc);
|
||||
|
||||
assert(bass_control_point_handle >= 2);
|
||||
start_handle = bass_control_point_handle - 2; /* server attr handle & char def handle */
|
||||
end_handle = bass_recv_state_handle[CONFIG_BT_BAP_SCAN_DELEGATOR_RECV_STATE_COUNT - 1] + 1; /* cccd attr handle */
|
||||
|
||||
LOG_DBG("[N]BassAttrHdlSet[%u][%u][%u]",
|
||||
start_handle, end_handle, bass_svc->attr_count);
|
||||
|
||||
for (size_t i = 0; i < bass_svc->attr_count; i++) {
|
||||
(bass_svc->attrs + i)->handle = start_handle + i;
|
||||
}
|
||||
|
||||
/* Last attribute in BASS */
|
||||
attr = bass_svc->attrs + bass_svc->attr_count - 1;
|
||||
|
||||
if (attr->handle != end_handle) {
|
||||
LOG_ERR("[N]BassMismatchAttrHdl[%u][%u][%u][%u]",
|
||||
start_handle, end_handle, attr->handle, bass_svc->attr_count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bass_svc_check(void)
|
||||
{
|
||||
struct bt_gatt_service *bass_svc;
|
||||
const struct bt_uuid_16 *uuid;
|
||||
bool chr_found;
|
||||
|
||||
/* This function is used to make sure the characteristics within
|
||||
* the service exist in the service defined by Zephyr.
|
||||
*/
|
||||
|
||||
bass_svc = lib_bap_bass_svc_get();
|
||||
assert(bass_svc);
|
||||
|
||||
LOG_DBG("[N]BassSvcCheck");
|
||||
|
||||
for (const struct ble_gatt_chr_def *chr = gatt_svc_bass->characteristics;
|
||||
chr && chr->uuid; chr++) {
|
||||
const ble_uuid16_t *check = (const ble_uuid16_t *)chr->uuid;
|
||||
|
||||
chr_found = false;
|
||||
|
||||
for (size_t i = 0; i < bass_svc->attr_count; i++) {
|
||||
uuid = (const struct bt_uuid_16 *)(bass_svc->attrs + i)->uuid;
|
||||
|
||||
if (uuid->uuid.type == BT_LE_NIMBLE_GATT_UUID_TO_Z(check->u.type) &&
|
||||
uuid->val == check->value) {
|
||||
chr_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (chr_found == false) {
|
||||
LOG_ERR("[N]BassChrNotFound[%04x]", check->value);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_le_nimble_bass_init(void)
|
||||
{
|
||||
uint16_t chr_count;
|
||||
int rc;
|
||||
|
||||
/* An additional characteristic consist of all 0s indicating end of characteristics */
|
||||
chr_count = 1 + CONFIG_BT_BAP_SCAN_DELEGATOR_RECV_STATE_COUNT + 1;
|
||||
|
||||
LOG_DBG("[N]BassInit[%u]", chr_count);
|
||||
|
||||
gatt_svc_bass->characteristics = calloc(chr_count, sizeof(struct ble_gatt_chr_def));
|
||||
assert(gatt_svc_bass->characteristics);
|
||||
|
||||
bass_svc_add_control_point_chr((void *)(gatt_svc_bass->characteristics + 0));
|
||||
|
||||
bass_svc_add_recv_state_chr((void *)(gatt_svc_bass->characteristics + 1));
|
||||
|
||||
rc = ble_gatts_count_cfg(gatt_svc_bass);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]BassCountCfgFail[%d]", rc);
|
||||
goto free;
|
||||
}
|
||||
|
||||
rc = ble_gatts_add_svcs(gatt_svc_bass);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]BassAddSvcsFail[%d]", rc);
|
||||
goto free;
|
||||
}
|
||||
|
||||
rc = bass_svc_check();
|
||||
if (rc) {
|
||||
goto free;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
free:
|
||||
free((void *)gatt_svc_bass->characteristics);
|
||||
gatt_svc_bass->characteristics = NULL;
|
||||
return rc;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef HOST_NIMBLE_PROFILE_BASS_H_
|
||||
#define HOST_NIMBLE_PROFILE_BASS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int bt_le_nimble_bass_attr_handle_set(void);
|
||||
|
||||
int bt_le_nimble_bass_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HOST_NIMBLE_PROFILE_BASS_H_ */
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <zephyr/autoconf.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/bluetooth/uuid.h>
|
||||
#include <zephyr/bluetooth/gatt.h>
|
||||
|
||||
#include <../host/conn_internal.h>
|
||||
|
||||
#include "host/ble_gatt.h"
|
||||
|
||||
#include "common/host.h"
|
||||
|
||||
#include "../../../lib/include/audio.h"
|
||||
|
||||
#if CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER
|
||||
extern struct ble_gatt_svc_def *cas_get_included_csis(void *csis_svc_p);
|
||||
|
||||
static struct bt_gatt_service *inc_csis_svc;
|
||||
|
||||
static struct ble_gatt_svc_def *cas_inc_svcs[] = {
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
#endif /* CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER */
|
||||
|
||||
static struct ble_gatt_svc_def gatt_svc_cas[] = {
|
||||
{
|
||||
/* Published Audio Capabilities Service */
|
||||
.type = BLE_GATT_SVC_TYPE_PRIMARY,
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_CAS_VAL),
|
||||
.includes = NULL,
|
||||
.characteristics = NULL,
|
||||
},
|
||||
{
|
||||
0, /* No more services. */
|
||||
},
|
||||
};
|
||||
|
||||
int bt_le_nimble_cas_attr_handle_set(void)
|
||||
{
|
||||
struct bt_gatt_service *cas_svc;
|
||||
uint16_t handle;
|
||||
int rc;
|
||||
|
||||
cas_svc = lib_cas_svc_get();
|
||||
assert(cas_svc);
|
||||
|
||||
LOG_DBG("[N]CasAttrHdlSet[%u]", cas_svc->attr_count);
|
||||
|
||||
rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_CAS_VAL), &handle);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]CasNotFound[%d]", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
LOG_DBG("[N]Hdl[%u]", handle);
|
||||
|
||||
for (size_t i = 0; i < cas_svc->attr_count; i++) {
|
||||
(cas_svc->attrs + i)->handle = handle + i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_le_nimble_cas_init(void *csis_svc_p)
|
||||
{
|
||||
int rc;
|
||||
|
||||
LOG_DBG("[N]CasInit[%p]", csis_svc_p);
|
||||
|
||||
#if CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER
|
||||
/* The instance of CSIS is included by CAS */
|
||||
if (csis_svc_p) {
|
||||
cas_inc_svcs[0] = cas_get_included_csis(csis_svc_p);
|
||||
if (cas_inc_svcs[0] == NULL) {
|
||||
LOG_ERR("[N]CasIncCsisNotFound");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Terminate the included service array with NULL */
|
||||
cas_inc_svcs[1] = NULL;
|
||||
|
||||
gatt_svc_cas[0].includes = (const struct ble_gatt_svc_def **)cas_inc_svcs;
|
||||
|
||||
inc_csis_svc = csis_svc_p;
|
||||
}
|
||||
#else /* CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER */
|
||||
ARG_UNUSED(csis_svc_p);
|
||||
#endif /* CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER */
|
||||
|
||||
rc = ble_gatts_count_cfg(gatt_svc_cas);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]CasCountCfgFail[%d]", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = ble_gatts_add_svcs(gatt_svc_cas);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]CasAddSvcsFail[%d]", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if !CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER
|
||||
struct bt_gatt_service *cas_svc;
|
||||
|
||||
cas_svc = lib_cas_svc_get();
|
||||
assert(cas_svc);
|
||||
|
||||
/* Insert CAS to the GATT db list */
|
||||
rc = bt_gatt_service_register_safe(cas_svc);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]CasSvcRegFail[%d]", rc);
|
||||
}
|
||||
#endif /* !CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER */
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef HOST_NIMBLE_PROFILE_CAS_H_
|
||||
#define HOST_NIMBLE_PROFILE_CAS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int bt_le_nimble_cas_attr_handle_set(void);
|
||||
|
||||
int bt_le_nimble_cas_init(void *csis_svc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HOST_NIMBLE_PROFILE_CAS_H_ */
|
||||
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <zephyr/autoconf.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/bluetooth/uuid.h>
|
||||
#include <zephyr/bluetooth/gatt.h>
|
||||
|
||||
#include <zephyr/bluetooth/audio/csip.h>
|
||||
|
||||
#include <../host/conn_internal.h>
|
||||
|
||||
#include "os/os_mbuf.h"
|
||||
#include "os/os_mempool.h"
|
||||
#include "host/ble_att.h"
|
||||
#include "host/ble_gatt.h"
|
||||
#include "host/ble_hs_mbuf.h"
|
||||
|
||||
#include "nimble/profiles/server.h"
|
||||
|
||||
#include "common/host.h"
|
||||
|
||||
#include "../../../lib/include/audio.h"
|
||||
|
||||
#define CSIS_SVC_COUNT CONFIG_BT_CSIP_SET_MEMBER_MAX_INSTANCE_COUNT
|
||||
|
||||
#define CSIS_CHR_COUNT (4 + 1)
|
||||
|
||||
#if CONFIG_BT_CSIP_SET_MEMBER_SIRK_NOTIFIABLE
|
||||
#define CSIS_CHR_FLAGS_SIRK \
|
||||
(BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC)
|
||||
#else /* CONFIG_BT_CSIP_SET_MEMBER_SIRK_NOTIFIABLE */
|
||||
#define CSIS_CHR_FLAGS_SIRK \
|
||||
(BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC)
|
||||
#endif /* CONFIG_BT_CSIP_SET_MEMBER_SIRK_NOTIFIABLE */
|
||||
|
||||
#define CSIS_CHR_FLAGS_SET_SIZE \
|
||||
(BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC)
|
||||
|
||||
#define CSIS_CHR_FLAGS_SET_LOCK \
|
||||
(BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_WRITE | \
|
||||
BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE_ENC)
|
||||
|
||||
#define CSIS_CHR_FLAGS_RANK \
|
||||
(BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC)
|
||||
|
||||
static const ble_uuid16_t csis_uuid_svc = BLE_UUID16_INIT(BT_UUID_CSIS_VAL);
|
||||
static const ble_uuid16_t csis_uuid_sirk = BLE_UUID16_INIT(BT_UUID_CSIS_SIRK_VAL);
|
||||
static const ble_uuid16_t csis_uuid_set_size = BLE_UUID16_INIT(BT_UUID_CSIS_SET_SIZE_VAL);
|
||||
static const ble_uuid16_t csis_uuid_set_lock = BLE_UUID16_INIT(BT_UUID_CSIS_SET_LOCK_VAL);
|
||||
static const ble_uuid16_t csis_uuid_rank = BLE_UUID16_INIT(BT_UUID_CSIS_RANK_VAL);
|
||||
|
||||
static struct csis_inst {
|
||||
struct bt_gatt_service *svc_p;
|
||||
uint16_t sirk_handle;
|
||||
uint16_t set_size_handle;
|
||||
uint16_t set_lock_handle;
|
||||
uint16_t rank_handle;
|
||||
} csis_insts[CSIS_SVC_COUNT];
|
||||
|
||||
static uint8_t csis_svc_count;
|
||||
|
||||
/* Extra one for terminating the CSIS service array */
|
||||
static struct ble_gatt_svc_def gatt_svc_csis[CSIS_SVC_COUNT + 1];
|
||||
|
||||
struct ble_gatt_svc_def *cas_get_included_csis(void *csis_svc_p)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
LOG_DBG("[N]CasGetIncCsis[%u]", csis_svc_count);
|
||||
|
||||
for (i = 0; i < csis_svc_count; i++) {
|
||||
if (csis_insts[i].svc_p == csis_svc_p) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == csis_svc_count) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &gatt_svc_csis[i];
|
||||
}
|
||||
|
||||
static int csis_svc_check(void)
|
||||
{
|
||||
const struct bt_uuid_16 *uuid;
|
||||
bool chr_found;
|
||||
|
||||
/* This function is used to make sure the characteristics within
|
||||
* the service exist in the service defined by Zephyr.
|
||||
*/
|
||||
|
||||
LOG_DBG("[N]CsisSvcCheck[%u]", csis_svc_count);
|
||||
|
||||
for (size_t i = 0; i < csis_svc_count; i++) {
|
||||
struct ble_gatt_svc_def *csis = &gatt_svc_csis[i];
|
||||
struct bt_gatt_service *svc = csis_insts[i].svc_p;
|
||||
|
||||
assert(svc);
|
||||
|
||||
for (const struct ble_gatt_chr_def *chr = csis->characteristics;
|
||||
chr && chr->uuid; chr++) {
|
||||
const ble_uuid16_t *check = (const ble_uuid16_t *)chr->uuid;
|
||||
|
||||
chr_found = false;
|
||||
|
||||
for (size_t j = 0; j < svc->attr_count; j++) {
|
||||
uuid = (const struct bt_uuid_16 *)(svc->attrs + j)->uuid;
|
||||
|
||||
if (uuid->uuid.type == BT_LE_NIMBLE_GATT_UUID_TO_Z(check->u.type) &&
|
||||
uuid->val == check->value) {
|
||||
chr_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (chr_found == false) {
|
||||
LOG_ERR("[N]CsisChrNotFound[%u][%04x]", i, check->value);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_le_nimble_csis_attr_handle_set(void)
|
||||
{
|
||||
struct bt_gatt_attr *attr;
|
||||
uint16_t start_handle;
|
||||
uint16_t end_handle;
|
||||
|
||||
LOG_DBG("[N]CsisAttrHdlSet[%u]", csis_svc_count);
|
||||
|
||||
for (size_t i = 0; i < csis_svc_count; i++) {
|
||||
assert(csis_insts[i].svc_p);
|
||||
|
||||
assert(csis_insts[i].sirk_handle >= 2);
|
||||
start_handle = csis_insts[i].sirk_handle - 2; /* server attr handle & char def handle */
|
||||
end_handle = csis_insts[i].rank_handle; /* no cccd for chr Set Member Rank */
|
||||
|
||||
LOG_DBG("[N]CsisInst[%u][%u][%u][%u]",
|
||||
i, start_handle, end_handle, csis_insts[i].svc_p->attr_count);
|
||||
|
||||
for (size_t j = 0; j < csis_insts[i].svc_p->attr_count; j++) {
|
||||
(csis_insts[i].svc_p->attrs + j)->handle = start_handle + j;
|
||||
}
|
||||
|
||||
/* Last attribute in CSIS */
|
||||
attr = csis_insts[i].svc_p->attrs + csis_insts[i].svc_p->attr_count - 1;
|
||||
|
||||
if (attr->handle != end_handle) {
|
||||
LOG_ERR("[N]CsisMismatchAttrHdl[%u][%u][%u][%u][%u]",
|
||||
i, start_handle, end_handle, attr->handle,
|
||||
csis_insts[i].svc_p->attr_count);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void csis_chr_init(struct ble_gatt_chr_def *chr,
|
||||
const ble_uuid16_t *uuid,
|
||||
uint16_t *val_handle,
|
||||
ble_gatt_chr_flags flags)
|
||||
{
|
||||
LOG_DBG("[N]CsisChrInit[%04x]", uuid->value);
|
||||
|
||||
chr->uuid = &uuid->u;
|
||||
chr->access_cb = bt_le_nimble_gatts_access_cb_safe;
|
||||
chr->arg = NULL;
|
||||
chr->descriptors = NULL; /* NULL if no descriptors. Do not include CCCD */
|
||||
chr->flags = flags;
|
||||
chr->min_key_size = 16;
|
||||
chr->val_handle = val_handle;
|
||||
}
|
||||
|
||||
static void csis_svc_init(struct csis_inst *inst,
|
||||
struct ble_gatt_svc_def *svc)
|
||||
{
|
||||
LOG_DBG("[N]CsisSvcInit");
|
||||
|
||||
svc->type = BLE_GATT_SVC_TYPE_PRIMARY;
|
||||
svc->uuid = &csis_uuid_svc.u;
|
||||
svc->includes = NULL;
|
||||
|
||||
svc->characteristics = calloc(CSIS_CHR_COUNT, sizeof(struct ble_gatt_chr_def));
|
||||
assert(svc->characteristics);
|
||||
|
||||
/* Characteristic - Set Identity Resolving Key */
|
||||
csis_chr_init((void *)&svc->characteristics[0],
|
||||
&csis_uuid_sirk,
|
||||
&inst->sirk_handle,
|
||||
CSIS_CHR_FLAGS_SIRK);
|
||||
|
||||
/* Characteristic - Coordinated Set Size */
|
||||
csis_chr_init((void *)&svc->characteristics[1],
|
||||
&csis_uuid_set_size,
|
||||
&inst->set_size_handle,
|
||||
CSIS_CHR_FLAGS_SET_SIZE);
|
||||
|
||||
/* Characteristic - Set Member Lock */
|
||||
csis_chr_init((void *)&svc->characteristics[2],
|
||||
&csis_uuid_set_lock,
|
||||
&inst->set_lock_handle,
|
||||
CSIS_CHR_FLAGS_SET_LOCK);
|
||||
|
||||
/* Characteristic - Set Member Rank */
|
||||
csis_chr_init((void *)&svc->characteristics[3],
|
||||
&csis_uuid_rank,
|
||||
&inst->rank_handle,
|
||||
CSIS_CHR_FLAGS_RANK);
|
||||
}
|
||||
|
||||
int bt_le_nimble_csis_init(void *svc, uint8_t count)
|
||||
{
|
||||
int rc;
|
||||
|
||||
LOG_DBG("[N]CsisInit[%u]", count);
|
||||
|
||||
if (count > CSIS_SVC_COUNT) {
|
||||
LOG_ERR("[N]InvCsisCount[%u][%u]", count, CSIS_SVC_COUNT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
csis_svc_count = count;
|
||||
|
||||
for (size_t i = 0; i < csis_svc_count; i++) {
|
||||
csis_svc_init(&csis_insts[i], &gatt_svc_csis[i]);
|
||||
|
||||
csis_insts[i].svc_p = ((struct bt_gatt_service **)svc)[i];
|
||||
}
|
||||
|
||||
rc = ble_gatts_count_cfg(gatt_svc_csis);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]CsisCountCfgFail[%d]", rc);
|
||||
goto free;
|
||||
}
|
||||
|
||||
rc = ble_gatts_add_svcs(gatt_svc_csis);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]CsisAddSvcsFail[%d]", rc);
|
||||
goto free;
|
||||
}
|
||||
|
||||
rc = csis_svc_check();
|
||||
if (rc) {
|
||||
goto free;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
free:
|
||||
for (size_t i = 0; i < csis_svc_count; i++) {
|
||||
free((void *)gatt_svc_csis[i].characteristics);
|
||||
gatt_svc_csis[i].characteristics = NULL;
|
||||
}
|
||||
csis_svc_count = 0;
|
||||
return rc;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef HOST_NIMBLE_PROFILE_CSIS_H_
|
||||
#define HOST_NIMBLE_PROFILE_CSIS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <zephyr/bluetooth/audio/audio.h>
|
||||
#include <zephyr/bluetooth/audio/csip.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int bt_le_nimble_csis_attr_handle_set(void);
|
||||
|
||||
int bt_le_nimble_csis_init(void *csis_svc, uint8_t count);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HOST_NIMBLE_PROFILE_CSIS_H_ */
|
||||
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <zephyr/autoconf.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/bluetooth/uuid.h>
|
||||
#include <zephyr/bluetooth/gatt.h>
|
||||
|
||||
#include <../host/conn_internal.h>
|
||||
|
||||
#include "os/os_mbuf.h"
|
||||
#include "os/os_mempool.h"
|
||||
#include "host/ble_att.h"
|
||||
#include "host/ble_gatt.h"
|
||||
#include "host/ble_hs_mbuf.h"
|
||||
|
||||
#include "nimble/profiles/server.h"
|
||||
|
||||
#include "common/host.h"
|
||||
|
||||
#include "../../../lib/include/audio.h"
|
||||
|
||||
static const ble_uuid16_t has_uuid_features = BLE_UUID16_INIT(BT_UUID_HAS_HEARING_AID_FEATURES_VAL);
|
||||
static const ble_uuid16_t has_uuid_control_point = BLE_UUID16_INIT(BT_UUID_HAS_PRESET_CONTROL_POINT_VAL);
|
||||
static const ble_uuid16_t has_uuid_preset_index = BLE_UUID16_INIT(BT_UUID_HAS_ACTIVE_PRESET_INDEX_VAL);
|
||||
|
||||
static uint16_t has_features_handle;
|
||||
static uint16_t has_control_point_handle;
|
||||
static uint16_t has_preset_index_handle;
|
||||
|
||||
static struct ble_gatt_svc_def gatt_svc_has[] = {
|
||||
{
|
||||
/* Hearing Access Service */
|
||||
.type = BLE_GATT_SVC_TYPE_PRIMARY,
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_HAS_VAL),
|
||||
.includes = NULL,
|
||||
.characteristics = NULL,
|
||||
},
|
||||
{
|
||||
0, /* No more services. */
|
||||
},
|
||||
};
|
||||
|
||||
static void has_svc_add_features_chr(struct ble_gatt_chr_def *chr)
|
||||
{
|
||||
chr->uuid = &has_uuid_features.u;
|
||||
chr->access_cb = bt_le_nimble_gatts_access_cb_safe;
|
||||
chr->arg = NULL;
|
||||
chr->descriptors = NULL; /* NULL if no descriptors. Do not include CCCD */
|
||||
#if CONFIG_BT_HAS_FEATURES_NOTIFIABLE
|
||||
chr->flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC;
|
||||
#else /* CONFIG_BT_HAS_FEATURES_NOTIFIABLE */
|
||||
chr->flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC;
|
||||
#endif /* CONFIG_BT_HAS_FEATURES_NOTIFIABLE */
|
||||
chr->min_key_size = 16;
|
||||
chr->val_handle = &has_features_handle;
|
||||
|
||||
LOG_DBG("[N]HasSvcAddFeatChr[%04x]", chr->flags);
|
||||
}
|
||||
|
||||
static void has_svc_add_control_point_chr(struct ble_gatt_chr_def *chr)
|
||||
{
|
||||
chr->uuid = &has_uuid_control_point.u;
|
||||
chr->access_cb = bt_le_nimble_gatts_access_cb_safe;
|
||||
chr->arg = NULL;
|
||||
chr->descriptors = NULL; /* NULL if no descriptors. Do not include CCCD */
|
||||
#if CONFIG_BT_HAS_PRESET_CONTROL_POINT_NOTIFIABLE
|
||||
chr->flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_INDICATE |
|
||||
BLE_GATT_CHR_F_WRITE_ENC | BLE_GATT_CHR_F_NOTIFY;
|
||||
#else /* CONFIG_BT_HAS_PRESET_CONTROL_POINT_NOTIFIABLE */
|
||||
chr->flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_INDICATE | BLE_GATT_CHR_F_WRITE_ENC;
|
||||
#endif /* CONFIG_BT_HAS_PRESET_CONTROL_POINT_NOTIFIABLE */
|
||||
chr->min_key_size = 16;
|
||||
chr->val_handle = &has_control_point_handle;
|
||||
|
||||
LOG_DBG("[N]HasSvcAddControlPointChr[%04x]", chr->flags);
|
||||
}
|
||||
|
||||
#if CONFIG_BT_HAS_ACTIVE_PRESET_INDEX
|
||||
static void has_svc_add_preset_index_chr(struct ble_gatt_chr_def *chr)
|
||||
{
|
||||
LOG_DBG("[N]HasSvcAddPresetIndexChr");
|
||||
|
||||
chr->uuid = &has_uuid_preset_index.u;
|
||||
chr->access_cb = bt_le_nimble_gatts_access_cb_safe;
|
||||
chr->arg = NULL;
|
||||
chr->descriptors = NULL; /* NULL if no descriptors. Do not include CCCD */
|
||||
chr->flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC;
|
||||
chr->min_key_size = 16;
|
||||
chr->val_handle = &has_preset_index_handle;
|
||||
}
|
||||
#endif /* CONFIG_BT_HAS_ACTIVE_PRESET_INDEX */
|
||||
|
||||
int bt_le_nimble_has_attr_handle_set(void)
|
||||
{
|
||||
struct bt_gatt_service *has_svc;
|
||||
struct bt_gatt_attr *attr;
|
||||
uint16_t start_handle = 0;
|
||||
uint16_t end_handle = 0;
|
||||
int rc;
|
||||
|
||||
has_svc = lib_has_svc_get();
|
||||
assert(has_svc);
|
||||
|
||||
LOG_DBG("[N]HasAttrHdlSet[%u]", has_svc->attr_count);
|
||||
assert(has_svc->attr_count > 0);
|
||||
|
||||
rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_HAS_VAL), &start_handle);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]HasNotFound[%d]", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
end_handle = start_handle + has_svc->attr_count - 1;
|
||||
|
||||
LOG_DBG("[N]Hdl[%u][%u]", start_handle, end_handle);
|
||||
|
||||
for (size_t i = 0; i < has_svc->attr_count; i++) {
|
||||
(has_svc->attrs + i)->handle = start_handle + i;
|
||||
}
|
||||
|
||||
/* Last attribute in HAS */
|
||||
attr = has_svc->attrs + has_svc->attr_count - 1;
|
||||
|
||||
if (attr->handle != end_handle) {
|
||||
LOG_ERR("[N]HasMismatchAttrHdl (%u %u %u %u)",
|
||||
start_handle, end_handle, attr->handle, has_svc->attr_count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int has_svc_check(void)
|
||||
{
|
||||
struct bt_gatt_service *has_svc;
|
||||
const struct bt_uuid_16 *uuid;
|
||||
bool chr_found;
|
||||
|
||||
/* This function is used to make sure the characteristics within
|
||||
* the service exist in the service defined by Zephyr.
|
||||
*/
|
||||
|
||||
has_svc = lib_has_svc_get();
|
||||
assert(has_svc);
|
||||
|
||||
LOG_DBG("[N]HasSvcCheck");
|
||||
|
||||
for (const struct ble_gatt_chr_def *chr = gatt_svc_has[0].characteristics;
|
||||
chr && chr->uuid; chr++) {
|
||||
const ble_uuid16_t *check = (const ble_uuid16_t *)chr->uuid;
|
||||
|
||||
chr_found = false;
|
||||
|
||||
for (size_t i = 0; i < has_svc->attr_count; i++) {
|
||||
uuid = (const struct bt_uuid_16 *)(has_svc->attrs + i)->uuid;
|
||||
|
||||
if (uuid->uuid.type == BT_LE_NIMBLE_GATT_UUID_TO_Z(check->u.type) &&
|
||||
uuid->val == check->value) {
|
||||
chr_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (chr_found == false) {
|
||||
LOG_ERR("[N]HasChrNotFound[%04x]", check->value);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_le_nimble_has_init(void)
|
||||
{
|
||||
uint8_t chr_count;
|
||||
int rc;
|
||||
|
||||
/* An additional characteristic consist of all 0s indicating end of characteristics */
|
||||
#if CONFIG_BT_HAS_ACTIVE_PRESET_INDEX
|
||||
chr_count = 1 + 1 + 1 + 1;
|
||||
#else /* CONFIG_BT_HAS_ACTIVE_PRESET_INDEX */
|
||||
chr_count = 1 + 1 + 1;
|
||||
#endif /* CONFIG_BT_HAS_ACTIVE_PRESET_INDEX */
|
||||
|
||||
LOG_DBG("[N]HasInit[%u]", chr_count);
|
||||
|
||||
gatt_svc_has->characteristics = calloc(chr_count, sizeof(struct ble_gatt_chr_def));
|
||||
assert(gatt_svc_has->characteristics);
|
||||
|
||||
has_svc_add_features_chr((void *)(gatt_svc_has->characteristics + 0));
|
||||
|
||||
has_svc_add_control_point_chr((void *)(gatt_svc_has->characteristics + 1));
|
||||
|
||||
#if CONFIG_BT_HAS_ACTIVE_PRESET_INDEX
|
||||
has_svc_add_preset_index_chr((void *)(gatt_svc_has->characteristics + 2));
|
||||
#endif /* CONFIG_BT_HAS_ACTIVE_PRESET_INDEX */
|
||||
|
||||
rc = ble_gatts_count_cfg(gatt_svc_has);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]HasCountCfgFail[%d]", rc);
|
||||
goto free;
|
||||
}
|
||||
|
||||
rc = ble_gatts_add_svcs(gatt_svc_has);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]HasAddSvcsFail[%d]", rc);
|
||||
goto free;
|
||||
}
|
||||
|
||||
rc = has_svc_check();
|
||||
if (rc) {
|
||||
goto free;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
free:
|
||||
free((void *)gatt_svc_has->characteristics);
|
||||
gatt_svc_has->characteristics = NULL;
|
||||
return rc;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef HOST_NIMBLE_PROFILE_HAS_H_
|
||||
#define HOST_NIMBLE_PROFILE_HAS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <zephyr/bluetooth/audio/audio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int bt_le_nimble_has_attr_handle_set(void);
|
||||
|
||||
int bt_le_nimble_has_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HOST_NIMBLE_PROFILE_HAS_H_ */
|
||||
@@ -0,0 +1,705 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <zephyr/autoconf.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/bluetooth/uuid.h>
|
||||
#include <zephyr/bluetooth/gatt.h>
|
||||
#include <zephyr/bluetooth/services/ots.h>
|
||||
#include <zephyr/bluetooth/audio/media_proxy.h>
|
||||
|
||||
#if CONFIG_BT_OTS
|
||||
#include "ots_internal.h"
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
|
||||
#include <../host/conn_internal.h>
|
||||
|
||||
#include "os/os_mbuf.h"
|
||||
#include "os/os_mempool.h"
|
||||
#include "host/ble_att.h"
|
||||
#include "host/ble_gatt.h"
|
||||
#include "host/ble_hs_mbuf.h"
|
||||
|
||||
#include "nimble/profiles/server.h"
|
||||
|
||||
#include "common/host.h"
|
||||
|
||||
#include "../../../lib/include/audio.h"
|
||||
|
||||
#if CONFIG_BT_OTS
|
||||
#define INC_OTS_CHR_COUNT 8 /* - OTS Feature (M)
|
||||
* - Object Name (M)
|
||||
* - Object Type (M)
|
||||
* - Object Size (M)
|
||||
* - Object ID (C.1)
|
||||
* - Object Properties (M)
|
||||
* - Object Action Control Point (M)
|
||||
* - Object List Control Point (C.1)
|
||||
*/
|
||||
|
||||
#define INC_OTS_CHR_FLAGS_FEATURE \
|
||||
(BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC)
|
||||
|
||||
#if CONFIG_BT_OTS_OBJ_NAME_WRITE_SUPPORT
|
||||
#define INC_OTS_CHR_FLAGS_NAME \
|
||||
(BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_ENC)
|
||||
#else /* CONFIG_BT_OTS_OBJ_NAME_WRITE_SUPPORT */
|
||||
#define INC_OTS_CHR_FLAGS_NAME \
|
||||
(BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC)
|
||||
#endif /* CONFIG_BT_OTS_OBJ_NAME_WRITE_SUPPORT */
|
||||
|
||||
#define INC_OTS_CHR_FLAGS_TYPE \
|
||||
(BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC)
|
||||
|
||||
#define INC_OTS_CHR_FLAGS_SIZE \
|
||||
(BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC)
|
||||
|
||||
#define INC_OTS_CHR_FLAGS_ID \
|
||||
(BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC)
|
||||
|
||||
#define INC_OTS_CHR_FLAGS_PROPS \
|
||||
(BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC)
|
||||
|
||||
#define INC_OTS_CHR_FLAGS_ACTION_CP \
|
||||
(BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_INDICATE | BLE_GATT_CHR_F_WRITE_ENC)
|
||||
|
||||
#define INC_OTS_CHR_FLAGS_LIST_CP \
|
||||
(BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_INDICATE | BLE_GATT_CHR_F_WRITE_ENC)
|
||||
|
||||
static uint8_t inc_ots_svc_count;
|
||||
|
||||
static struct bt_ots *ots;
|
||||
static uint16_t inc_ots_chr_feature_handle;
|
||||
static uint16_t inc_ots_chr_name_handle;
|
||||
static uint16_t inc_ots_chr_type_handle;
|
||||
static uint16_t inc_ots_chr_size_handle;
|
||||
static uint16_t inc_ots_chr_id_handle;
|
||||
static uint16_t inc_ots_chr_props_handle;
|
||||
static uint16_t inc_ots_chr_action_cp_handle;
|
||||
static uint16_t inc_ots_chr_list_cp_handle;
|
||||
|
||||
static struct ble_gatt_svc_def *gatt_svc_inc_ots;
|
||||
|
||||
static struct ble_gatt_svc_def **gmcs_inc_svcs;
|
||||
|
||||
static const ble_uuid16_t inc_ots_uuid_svc = BLE_UUID16_INIT(BT_UUID_OTS_VAL);
|
||||
static const ble_uuid16_t inc_ots_uuid_feature = BLE_UUID16_INIT(BT_UUID_OTS_FEATURE_VAL);
|
||||
static const ble_uuid16_t inc_ots_uuid_name = BLE_UUID16_INIT(BT_UUID_OTS_NAME_VAL);
|
||||
static const ble_uuid16_t inc_ots_uuid_type = BLE_UUID16_INIT(BT_UUID_OTS_TYPE_VAL);
|
||||
static const ble_uuid16_t inc_ots_uuid_size = BLE_UUID16_INIT(BT_UUID_OTS_SIZE_VAL);
|
||||
static const ble_uuid16_t inc_ots_uuid_id = BLE_UUID16_INIT(BT_UUID_OTS_ID_VAL);
|
||||
static const ble_uuid16_t inc_ots_uuid_props = BLE_UUID16_INIT(BT_UUID_OTS_PROPERTIES_VAL);
|
||||
static const ble_uuid16_t inc_ots_uuid_action_cp = BLE_UUID16_INIT(BT_UUID_OTS_ACTION_CP_VAL);
|
||||
static const ble_uuid16_t inc_ots_uuid_list_cp = BLE_UUID16_INIT(BT_UUID_OTS_LIST_CP_VAL);
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
|
||||
static uint16_t mcs_player_name_handle;
|
||||
#if CONFIG_BT_OTS
|
||||
static uint16_t mcs_icon_obj_id_handle;
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
static uint16_t mcs_icon_url_handle;
|
||||
static uint16_t mcs_track_changed_handle;
|
||||
static uint16_t mcs_track_title_handle;
|
||||
static uint16_t mcs_track_duration_handle;
|
||||
static uint16_t mcs_track_position_handle;
|
||||
static uint16_t mcs_playback_speed_handle;
|
||||
static uint16_t mcs_seeking_speed_handle;
|
||||
#if CONFIG_BT_OTS
|
||||
static uint16_t mcs_track_segments_obj_id_handle;
|
||||
static uint16_t mcs_current_track_obj_id_handle;
|
||||
static uint16_t mcs_next_track_obj_id_handle;
|
||||
static uint16_t mcs_parent_group_obj_id_handle;
|
||||
static uint16_t mcs_current_group_obj_id_handle;
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
static uint16_t mcs_playing_order_handle;
|
||||
static uint16_t mcs_playing_orders_handle;
|
||||
static uint16_t mcs_media_state_handle;
|
||||
static uint16_t mcs_media_control_point_handle;
|
||||
static uint16_t mcs_media_control_opcodes_handle;
|
||||
#if CONFIG_BT_OTS
|
||||
static uint16_t mcs_search_control_point_handle;
|
||||
static uint16_t mcs_search_results_obj_id_handle;
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
static uint16_t ccid_handle;
|
||||
|
||||
static struct ble_gatt_svc_def gatt_svc_gmcs[] = {
|
||||
{
|
||||
/* Published Audio Capabilities Service */
|
||||
.type = BLE_GATT_SVC_TYPE_PRIMARY,
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_GMCS_VAL),
|
||||
.includes = NULL,
|
||||
.characteristics = (struct ble_gatt_chr_def[])
|
||||
{
|
||||
{
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MCS_PLAYER_NAME_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &mcs_player_name_handle,
|
||||
},
|
||||
#if CONFIG_BT_OTS
|
||||
{
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MCS_ICON_OBJ_ID_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &mcs_icon_obj_id_handle,
|
||||
},
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
{
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MCS_ICON_URL_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &mcs_icon_url_handle,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MCS_TRACK_CHANGED_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_NOTIFY,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &mcs_track_changed_handle,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MCS_TRACK_TITLE_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &mcs_track_title_handle,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MCS_TRACK_DURATION_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &mcs_track_duration_handle,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MCS_TRACK_POSITION_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | \
|
||||
BLE_GATT_CHR_F_WRITE_NO_RSP | BLE_GATT_CHR_F_NOTIFY | \
|
||||
BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &mcs_track_position_handle,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MCS_PLAYBACK_SPEED_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | \
|
||||
BLE_GATT_CHR_F_WRITE_NO_RSP | BLE_GATT_CHR_F_NOTIFY | \
|
||||
BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &mcs_playback_speed_handle,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MCS_SEEKING_SPEED_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &mcs_seeking_speed_handle,
|
||||
},
|
||||
#if CONFIG_BT_OTS
|
||||
{
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MCS_TRACK_SEGMENTS_OBJ_ID_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &mcs_track_segments_obj_id_handle,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MCS_CURRENT_TRACK_OBJ_ID_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | \
|
||||
BLE_GATT_CHR_F_WRITE_NO_RSP | BLE_GATT_CHR_F_NOTIFY | \
|
||||
BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &mcs_current_track_obj_id_handle,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MCS_NEXT_TRACK_OBJ_ID_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | \
|
||||
BLE_GATT_CHR_F_WRITE_NO_RSP | BLE_GATT_CHR_F_NOTIFY | \
|
||||
BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &mcs_next_track_obj_id_handle,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MCS_PARENT_GROUP_OBJ_ID_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &mcs_parent_group_obj_id_handle,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MCS_CURRENT_GROUP_OBJ_ID_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | \
|
||||
BLE_GATT_CHR_F_WRITE_NO_RSP | BLE_GATT_CHR_F_NOTIFY | \
|
||||
BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &mcs_current_group_obj_id_handle,
|
||||
},
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
{
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MCS_PLAYING_ORDER_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | \
|
||||
BLE_GATT_CHR_F_WRITE_NO_RSP | BLE_GATT_CHR_F_NOTIFY | \
|
||||
BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &mcs_playing_order_handle,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MCS_PLAYING_ORDERS_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &mcs_playing_orders_handle,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MCS_MEDIA_STATE_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &mcs_media_state_handle,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MCS_MEDIA_CONTROL_POINT_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_NO_RSP | \
|
||||
BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_WRITE_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &mcs_media_control_point_handle,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MCS_MEDIA_CONTROL_OPCODES_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &mcs_media_control_opcodes_handle,
|
||||
},
|
||||
#if CONFIG_BT_OTS
|
||||
{
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MCS_SEARCH_CONTROL_POINT_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_NO_RSP | \
|
||||
BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_WRITE_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &mcs_search_control_point_handle,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MCS_SEARCH_RESULTS_OBJ_ID_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &mcs_search_results_obj_id_handle,
|
||||
},
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
{
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_CCID_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &ccid_handle,
|
||||
}, {
|
||||
0, /* No more characteristics in this service. */
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
0, /* No more services. */
|
||||
},
|
||||
};
|
||||
|
||||
#if CONFIG_BT_OTS
|
||||
static int inc_ots_attr_handle_set(void)
|
||||
{
|
||||
struct bt_gatt_attr *attr;
|
||||
uint16_t start_handle;
|
||||
uint16_t end_handle;
|
||||
|
||||
assert(ots && ots->service);
|
||||
|
||||
assert(inc_ots_chr_feature_handle >= 2);
|
||||
start_handle = inc_ots_chr_feature_handle - 2; /* server attr handle & char def handle */
|
||||
end_handle = inc_ots_chr_list_cp_handle + 1; /* cccd for chr Object List Control Point */
|
||||
|
||||
LOG_DBG("[N]IncOtsAttrHdlSet[%u][%u][%u]",
|
||||
start_handle, end_handle, ots->service->attr_count);
|
||||
|
||||
for (size_t i = 0; i < ots->service->attr_count; i++) {
|
||||
(ots->service->attrs + i)->handle = start_handle + i;
|
||||
}
|
||||
|
||||
/* Last attribute in included OTS */
|
||||
attr = ots->service->attrs + ots->service->attr_count - 1;
|
||||
|
||||
if (attr->handle != end_handle) {
|
||||
LOG_ERR("[N]IncOtsMismatchAttrHdl[%u][%u][%u][%u]",
|
||||
start_handle, end_handle, attr->handle, ots->service->attr_count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
|
||||
int bt_le_nimble_gmcs_attr_handle_set(void)
|
||||
{
|
||||
struct bt_gatt_service *gmcs_svc;
|
||||
struct bt_gatt_attr *attr;
|
||||
uint16_t start_handle = 0;
|
||||
uint16_t end_handle = 0;
|
||||
int rc;
|
||||
|
||||
gmcs_svc = lib_mcs_svc_get();
|
||||
assert(gmcs_svc);
|
||||
|
||||
LOG_DBG("[N]GmcsAttrHdlSet[%u]", gmcs_svc->attr_count);
|
||||
|
||||
rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_GMCS_VAL), &start_handle);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]GmcsNotFound[%d]", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
end_handle = start_handle + gmcs_svc->attr_count - 1;
|
||||
|
||||
LOG_DBG("[N]Hdl[%u][%u]", start_handle, end_handle);
|
||||
|
||||
for (size_t i = 0; i < gmcs_svc->attr_count; i++) {
|
||||
(gmcs_svc->attrs + i)->handle = start_handle + i;
|
||||
}
|
||||
|
||||
/* Last attribute in MCS */
|
||||
attr = gmcs_svc->attrs + gmcs_svc->attr_count - 1;
|
||||
|
||||
if (attr->handle != end_handle) {
|
||||
LOG_ERR("[N]GmcsMismatchAttrHdl[%u][%u][%u][%u]",
|
||||
start_handle, end_handle, attr->handle, gmcs_svc->attr_count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_OTS
|
||||
if (inc_ots_svc_count) {
|
||||
rc = inc_ots_attr_handle_set();
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gmcs_svc_check(void)
|
||||
{
|
||||
struct bt_gatt_service *gmcs_svc;
|
||||
const struct bt_uuid_16 *uuid;
|
||||
bool chr_found;
|
||||
|
||||
/* This function is used to make sure the characteristics within
|
||||
* the service exist in the service defined by Zephyr.
|
||||
*/
|
||||
|
||||
gmcs_svc = lib_mcs_svc_get();
|
||||
assert(gmcs_svc);
|
||||
|
||||
LOG_DBG("[N]GmcsSvcCheck");
|
||||
|
||||
for (const struct ble_gatt_chr_def *chr = gatt_svc_gmcs[0].characteristics;
|
||||
chr && chr->uuid; chr++) {
|
||||
const ble_uuid16_t *check = (const ble_uuid16_t *)chr->uuid;
|
||||
|
||||
chr_found = false;
|
||||
|
||||
for (size_t i = 0; i < gmcs_svc->attr_count; i++) {
|
||||
uuid = (const struct bt_uuid_16 *)(gmcs_svc->attrs + i)->uuid;
|
||||
|
||||
if (uuid->uuid.type == BT_LE_NIMBLE_GATT_UUID_TO_Z(check->u.type) &&
|
||||
uuid->val == check->value) {
|
||||
chr_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (chr_found == false) {
|
||||
LOG_ERR("[N]GmcsChrNotFound[%04x]", check->value);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_OTS
|
||||
static int inc_ots_svc_check(void)
|
||||
{
|
||||
const struct bt_uuid_16 *uuid;
|
||||
bool chr_found;
|
||||
|
||||
/* This function is used to make sure the characteristics within
|
||||
* the service exist in the service defined by Zephyr.
|
||||
*/
|
||||
|
||||
assert(gatt_svc_inc_ots);
|
||||
assert(ots && ots->service);
|
||||
|
||||
LOG_DBG("[N]IncOtsSvcCheck");
|
||||
|
||||
for (const struct ble_gatt_chr_def *chr = gatt_svc_inc_ots[0].characteristics;
|
||||
chr && chr->uuid; chr++) {
|
||||
const ble_uuid16_t *check = (const ble_uuid16_t *)chr->uuid;
|
||||
|
||||
chr_found = false;
|
||||
|
||||
for (size_t i = 0; i < ots->service->attr_count; i++) {
|
||||
uuid = (const struct bt_uuid_16 *)(ots->service->attrs + i)->uuid;
|
||||
|
||||
if (uuid->uuid.type == BT_LE_NIMBLE_GATT_UUID_TO_Z(check->u.type) &&
|
||||
uuid->val == check->value) {
|
||||
chr_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (chr_found == false) {
|
||||
LOG_ERR("[N]IncOtsChrNotFound[%04x]", check->value);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void inc_ots_chr_init(struct ble_gatt_chr_def *chr,
|
||||
const ble_uuid16_t *uuid,
|
||||
uint16_t *val_handle,
|
||||
ble_gatt_chr_flags flags)
|
||||
{
|
||||
LOG_DBG("[N]IncOtsChrInit[%04x]", uuid->value);
|
||||
|
||||
chr->uuid = &uuid->u;
|
||||
chr->access_cb = bt_le_nimble_gatts_access_cb_safe;
|
||||
chr->arg = NULL;
|
||||
chr->descriptors = NULL; /* NULL if no descriptors. Do not include CCCD */
|
||||
chr->flags = flags;
|
||||
chr->min_key_size = 16;
|
||||
chr->val_handle = val_handle;
|
||||
}
|
||||
|
||||
static int inc_ots_svc_init(void)
|
||||
{
|
||||
struct ble_gatt_svc_def *svc;
|
||||
struct bt_gatt_attr *attrs;
|
||||
uint8_t chr_count;
|
||||
|
||||
attrs = bt_ots_svc_decl_get(ots);
|
||||
assert(attrs);
|
||||
|
||||
chr_count = 0;
|
||||
|
||||
for (size_t i = 0; i < ots->service->attr_count; i++) {
|
||||
if (bt_uuid_cmp(attrs[i].uuid, BT_UUID_GATT_CHRC) == 0) {
|
||||
chr_count++;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DBG("[N]IncOtsSvcInit[%u]", chr_count);
|
||||
|
||||
if (chr_count != INC_OTS_CHR_COUNT) {
|
||||
LOG_ERR("[N]InvOtsChrCount[%u][%u]", chr_count, INC_OTS_CHR_COUNT);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
svc = &gatt_svc_inc_ots[0];
|
||||
|
||||
svc->type = BLE_GATT_SVC_TYPE_SECONDARY;
|
||||
svc->uuid = &inc_ots_uuid_svc.u;
|
||||
svc->includes = NULL;
|
||||
|
||||
/* An additional characteristic consist of all 0s indicating end of characteristics */
|
||||
svc->characteristics = calloc(INC_OTS_CHR_COUNT + 1, sizeof(struct ble_gatt_chr_def));
|
||||
assert(svc->characteristics);
|
||||
|
||||
/* Characteristic - OTS Feature */
|
||||
inc_ots_chr_init((void *)&svc->characteristics[0],
|
||||
&inc_ots_uuid_feature,
|
||||
&inc_ots_chr_feature_handle,
|
||||
INC_OTS_CHR_FLAGS_FEATURE);
|
||||
|
||||
/* Characteristic - Object Name */
|
||||
inc_ots_chr_init((void *)&svc->characteristics[1],
|
||||
&inc_ots_uuid_name,
|
||||
&inc_ots_chr_name_handle,
|
||||
INC_OTS_CHR_FLAGS_NAME);
|
||||
|
||||
/* Characteristic - Object Type */
|
||||
inc_ots_chr_init((void *)&svc->characteristics[2],
|
||||
&inc_ots_uuid_type,
|
||||
&inc_ots_chr_type_handle,
|
||||
INC_OTS_CHR_FLAGS_TYPE);
|
||||
|
||||
/* Characteristic - Object Size */
|
||||
inc_ots_chr_init((void *)&svc->characteristics[3],
|
||||
&inc_ots_uuid_size,
|
||||
&inc_ots_chr_size_handle,
|
||||
INC_OTS_CHR_FLAGS_SIZE);
|
||||
|
||||
/* Characteristic - Object ID */
|
||||
inc_ots_chr_init((void *)&svc->characteristics[4],
|
||||
&inc_ots_uuid_id,
|
||||
&inc_ots_chr_id_handle,
|
||||
INC_OTS_CHR_FLAGS_ID);
|
||||
|
||||
/* Characteristic - Object Properties */
|
||||
inc_ots_chr_init((void *)&svc->characteristics[5],
|
||||
&inc_ots_uuid_props,
|
||||
&inc_ots_chr_props_handle,
|
||||
INC_OTS_CHR_FLAGS_PROPS);
|
||||
|
||||
/* Characteristic - Object Action Control Point */
|
||||
inc_ots_chr_init((void *)&svc->characteristics[6],
|
||||
&inc_ots_uuid_action_cp,
|
||||
&inc_ots_chr_action_cp_handle,
|
||||
INC_OTS_CHR_FLAGS_ACTION_CP);
|
||||
|
||||
/* Characteristic - Object List Control Point */
|
||||
inc_ots_chr_init((void *)&svc->characteristics[7],
|
||||
&inc_ots_uuid_list_cp,
|
||||
&inc_ots_chr_list_cp_handle,
|
||||
INC_OTS_CHR_FLAGS_LIST_CP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
|
||||
int bt_le_nimble_gmcs_init(bool ots_included)
|
||||
{
|
||||
int rc;
|
||||
|
||||
LOG_DBG("[N]GmcsInit[%u]", ots_included);
|
||||
|
||||
#if CONFIG_BT_OTS
|
||||
if (ots_included) {
|
||||
inc_ots_svc_count = 1;
|
||||
|
||||
/* Extra one for terminating the included service array with NULL */
|
||||
gmcs_inc_svcs = calloc(2, sizeof(struct ble_gatt_svc_def *));
|
||||
assert(gmcs_inc_svcs);
|
||||
|
||||
/* Extra one for terminating the OTS service array */
|
||||
gatt_svc_inc_ots = calloc(2, sizeof(struct ble_gatt_svc_def));
|
||||
assert(gatt_svc_inc_ots);
|
||||
|
||||
ots = lib_mcs_get_ots();
|
||||
assert(ots && ots->service);
|
||||
|
||||
rc = inc_ots_svc_init();
|
||||
if (rc) {
|
||||
goto free;
|
||||
}
|
||||
|
||||
gmcs_inc_svcs[0] = &gatt_svc_inc_ots[0];
|
||||
|
||||
rc = ble_gatts_count_cfg(gatt_svc_inc_ots);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]IncOtsCountCfgFail[%d]", rc);
|
||||
goto free;
|
||||
}
|
||||
|
||||
rc = ble_gatts_add_svcs(gatt_svc_inc_ots);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]IncOtsAddSvcsFail[%d]", rc);
|
||||
goto free;
|
||||
}
|
||||
|
||||
rc = inc_ots_svc_check();
|
||||
if (rc) {
|
||||
goto free;
|
||||
}
|
||||
|
||||
/* Terminate the included service array with NULL */
|
||||
gmcs_inc_svcs[1] = NULL;
|
||||
}
|
||||
|
||||
gatt_svc_gmcs[0].includes = (const struct ble_gatt_svc_def **)gmcs_inc_svcs;
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
|
||||
rc = ble_gatts_count_cfg(gatt_svc_gmcs);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]GmcsCountCfgFail[%d]", rc);
|
||||
goto free;
|
||||
}
|
||||
|
||||
rc = ble_gatts_add_svcs(gatt_svc_gmcs);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]GmcsAddSvcsFail[%d]", rc);
|
||||
goto free;
|
||||
}
|
||||
|
||||
rc = gmcs_svc_check();
|
||||
if (rc) {
|
||||
goto free;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
free:
|
||||
#if CONFIG_BT_OTS
|
||||
if (ots_included) {
|
||||
inc_ots_svc_count = 0;
|
||||
|
||||
free(gmcs_inc_svcs);
|
||||
gmcs_inc_svcs = NULL;
|
||||
|
||||
if (gatt_svc_inc_ots[0].characteristics) {
|
||||
free((void *)gatt_svc_inc_ots[0].characteristics);
|
||||
gatt_svc_inc_ots[0].characteristics = NULL;
|
||||
}
|
||||
free(gatt_svc_inc_ots);
|
||||
gatt_svc_inc_ots = NULL;
|
||||
}
|
||||
gatt_svc_gmcs[0].includes = NULL;
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
return rc;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef HOST_NIMBLE_PROFILE_MCS_H_
|
||||
#define HOST_NIMBLE_PROFILE_MCS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <zephyr/bluetooth/audio/audio.h>
|
||||
#include <zephyr/bluetooth/audio/mcs.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int bt_le_nimble_gmcs_attr_handle_set(void);
|
||||
|
||||
int bt_le_nimble_gmcs_init(bool ots_included);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HOST_NIMBLE_PROFILE_MCS_H_ */
|
||||
@@ -0,0 +1,447 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <zephyr/autoconf.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/bluetooth/uuid.h>
|
||||
#include <zephyr/bluetooth/gatt.h>
|
||||
#include <zephyr/bluetooth/audio/micp.h>
|
||||
|
||||
#include <../host/conn_internal.h>
|
||||
|
||||
#include "os/os_mbuf.h"
|
||||
#include "os/os_mempool.h"
|
||||
#include "host/ble_att.h"
|
||||
#include "host/ble_gatt.h"
|
||||
#include "host/ble_hs_mbuf.h"
|
||||
|
||||
#include "nimble/profiles/server.h"
|
||||
|
||||
#include "common/host.h"
|
||||
|
||||
#include "../../../lib/include/audio.h"
|
||||
|
||||
#define INC_AICS_CHR_COUNT (6 + 1)
|
||||
|
||||
#define INC_AICS_CHR_FLAGS_STATE \
|
||||
(BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC)
|
||||
|
||||
#define INC_AICS_CHR_FLAGS_GAIN \
|
||||
(BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC)
|
||||
|
||||
#define INC_AICS_CHR_FLAGS_TYPE \
|
||||
(BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC)
|
||||
|
||||
#define INC_AICS_CHR_FLAGS_STATUS \
|
||||
(BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC)
|
||||
|
||||
#define INC_AICS_CHR_FLAGS_CONTROL \
|
||||
(BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_ENC)
|
||||
|
||||
#define INC_AICS_CHR_FLAGS_DESCRIPTION \
|
||||
(BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_WRITE_NO_RSP | \
|
||||
BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE_ENC)
|
||||
|
||||
static uint8_t inc_aics_svc_count;
|
||||
|
||||
static struct inc_aics_inst {
|
||||
struct bt_gatt_service *svc_p;
|
||||
uint16_t state_handle;
|
||||
uint16_t gain_handle;
|
||||
uint16_t type_handle;
|
||||
uint16_t status_handle;
|
||||
uint16_t control_handle;
|
||||
uint16_t description_handle;
|
||||
} *inc_aics_insts;
|
||||
|
||||
static struct ble_gatt_svc_def *gatt_svc_inc_aics;
|
||||
|
||||
static const ble_uuid16_t inc_aics_uuid_svc = BLE_UUID16_INIT(BT_UUID_AICS_VAL);
|
||||
static const ble_uuid16_t inc_aics_uuid_state = BLE_UUID16_INIT(BT_UUID_AICS_STATE_VAL);
|
||||
static const ble_uuid16_t inc_aics_uuid_gain = BLE_UUID16_INIT(BT_UUID_AICS_GAIN_SETTINGS_VAL);
|
||||
static const ble_uuid16_t inc_aics_uuid_type = BLE_UUID16_INIT(BT_UUID_AICS_INPUT_TYPE_VAL);
|
||||
static const ble_uuid16_t inc_aics_uuid_status = BLE_UUID16_INIT(BT_UUID_AICS_INPUT_STATUS_VAL);
|
||||
static const ble_uuid16_t inc_aics_uuid_control = BLE_UUID16_INIT(BT_UUID_AICS_CONTROL_VAL);
|
||||
static const ble_uuid16_t inc_aics_uuid_description = BLE_UUID16_INIT(BT_UUID_AICS_DESCRIPTION_VAL);
|
||||
|
||||
static struct ble_gatt_svc_def **mics_inc_svcs;
|
||||
|
||||
static uint16_t mics_mute_handle;
|
||||
|
||||
static struct ble_gatt_svc_def gatt_svc_mics[] = {
|
||||
{
|
||||
/* Microphone Control Service */
|
||||
.type = BLE_GATT_SVC_TYPE_PRIMARY,
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MICS_VAL),
|
||||
.includes = NULL,
|
||||
.characteristics = (struct ble_gatt_chr_def[])
|
||||
{
|
||||
{
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_MICS_MUTE_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | \
|
||||
BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ_ENC | \
|
||||
BLE_GATT_CHR_F_WRITE_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &mics_mute_handle,
|
||||
}, {
|
||||
0, /* No more characteristics in this service. */
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
0, /* No more services. */
|
||||
}
|
||||
};
|
||||
|
||||
static int inc_aics_svc_check(void)
|
||||
{
|
||||
const struct bt_uuid_16 *uuid;
|
||||
bool chr_found;
|
||||
|
||||
/* This function is used to make sure the characteristics within
|
||||
* the service exist in the service defined by Zephyr.
|
||||
*/
|
||||
|
||||
assert(gatt_svc_inc_aics);
|
||||
assert(inc_aics_insts);
|
||||
|
||||
LOG_DBG("[N]IncAicsSvcCheck[%u]", inc_aics_svc_count);
|
||||
|
||||
for (size_t i = 0; i < inc_aics_svc_count; i++) {
|
||||
struct ble_gatt_svc_def *aics = &gatt_svc_inc_aics[i];
|
||||
struct bt_gatt_service *svc = inc_aics_insts[i].svc_p;
|
||||
|
||||
assert(svc);
|
||||
|
||||
for (const struct ble_gatt_chr_def *chr = aics->characteristics;
|
||||
chr && chr->uuid; chr++) {
|
||||
const ble_uuid16_t *check = (const ble_uuid16_t *)chr->uuid;
|
||||
|
||||
chr_found = false;
|
||||
|
||||
for (size_t j = 0; j < svc->attr_count; j++) {
|
||||
uuid = (const struct bt_uuid_16 *)(svc->attrs + j)->uuid;
|
||||
|
||||
if (uuid->uuid.type == BT_LE_NIMBLE_GATT_UUID_TO_Z(check->u.type) &&
|
||||
uuid->val == check->value) {
|
||||
chr_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (chr_found == false) {
|
||||
LOG_ERR("[N]IncAicsChrNotFound[%u][%04x]", i, check->value);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mics_svc_check(void)
|
||||
{
|
||||
struct bt_gatt_service *mics_svc;
|
||||
const struct bt_uuid_16 *uuid;
|
||||
bool chr_found;
|
||||
|
||||
mics_svc = lib_mics_svc_get();
|
||||
assert(mics_svc);
|
||||
|
||||
LOG_DBG("[N]MicsSvcCheck");
|
||||
|
||||
for (const struct ble_gatt_chr_def *chr = gatt_svc_mics->characteristics;
|
||||
chr && chr->uuid; chr++) {
|
||||
const ble_uuid16_t *check = (const ble_uuid16_t *)chr->uuid;
|
||||
|
||||
chr_found = false;
|
||||
|
||||
for (size_t i = 0; i < mics_svc->attr_count; i++) {
|
||||
uuid = (const struct bt_uuid_16 *)(mics_svc->attrs + i)->uuid;
|
||||
|
||||
if (uuid->uuid.type == BT_LE_NIMBLE_GATT_UUID_TO_Z(check->u.type) &&
|
||||
uuid->val == check->value) {
|
||||
chr_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (chr_found == false) {
|
||||
LOG_ERR("[N]MicsChrNotFound[%04x]", check->value);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int inc_aics_attr_handle_set(void)
|
||||
{
|
||||
struct bt_gatt_attr *attr;
|
||||
uint16_t start_handle;
|
||||
uint16_t end_handle;
|
||||
|
||||
assert(inc_aics_insts);
|
||||
|
||||
LOG_DBG("[N]IncAicsAttrHdlSet[%u]", inc_aics_svc_count);
|
||||
|
||||
for (size_t i = 0; i < inc_aics_svc_count; i++) {
|
||||
assert(inc_aics_insts[i].svc_p);
|
||||
|
||||
assert(inc_aics_insts[i].state_handle >= 2);
|
||||
start_handle = inc_aics_insts[i].state_handle - 2; /* server attr handle & char def handle */
|
||||
end_handle = inc_aics_insts[i].description_handle + 1; /* cccd for chr Audio Input Description */
|
||||
|
||||
LOG_DBG("[N]IncAicsInst[%u][%u][%u][%u]",
|
||||
i, start_handle, end_handle, inc_aics_insts[i].svc_p->attr_count);
|
||||
|
||||
for (size_t j = 0; j < inc_aics_insts[i].svc_p->attr_count; j++) {
|
||||
(inc_aics_insts[i].svc_p->attrs + j)->handle = start_handle + j;
|
||||
}
|
||||
|
||||
/* Last attribute in included AICS */
|
||||
attr = inc_aics_insts[i].svc_p->attrs + inc_aics_insts[i].svc_p->attr_count - 1;
|
||||
|
||||
if (attr->handle != end_handle) {
|
||||
LOG_ERR("[N]IncAicsMismatchAttrHdl[%u][%u][%u][%u]",
|
||||
start_handle, end_handle, attr->handle,
|
||||
inc_aics_insts[i].svc_p->attr_count);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_le_nimble_mics_attr_handle_set(void)
|
||||
{
|
||||
struct bt_gatt_service *mics_svc;
|
||||
struct bt_gatt_attr *attr;
|
||||
uint16_t start_handle = 0;
|
||||
uint16_t end_handle = 0;
|
||||
int rc;
|
||||
|
||||
mics_svc = lib_mics_svc_get();
|
||||
assert(mics_svc);
|
||||
|
||||
LOG_DBG("[N]MicsAttrHdlSet[%u]", mics_svc->attr_count);
|
||||
|
||||
rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MICS_VAL), &start_handle);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]MicsNotFound[%d]", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
end_handle = start_handle + mics_svc->attr_count - 1;
|
||||
|
||||
LOG_DBG("[N]Hdl[%u][%u]", start_handle, end_handle);
|
||||
|
||||
for (size_t i = 0; i < mics_svc->attr_count; i++) {
|
||||
(mics_svc->attrs + i)->handle = start_handle + i;
|
||||
}
|
||||
|
||||
/* Last attribute in MICS */
|
||||
attr = mics_svc->attrs + mics_svc->attr_count - 1;
|
||||
|
||||
if (attr->handle != end_handle) {
|
||||
LOG_ERR("[N]MicsMismatchAttrHdl[%u][%u][%u][%u]",
|
||||
start_handle, end_handle, attr->handle, mics_svc->attr_count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (inc_aics_svc_count) {
|
||||
rc = inc_aics_attr_handle_set();
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void inc_aics_chr_init(struct ble_gatt_chr_def *chr,
|
||||
const ble_uuid16_t *uuid,
|
||||
uint16_t *val_handle,
|
||||
ble_gatt_chr_flags flags)
|
||||
{
|
||||
LOG_DBG("[N]IncAicsChrInit[%04x]", uuid->value);
|
||||
|
||||
chr->uuid = &uuid->u;
|
||||
chr->access_cb = bt_le_nimble_gatts_access_cb_safe;
|
||||
chr->arg = NULL;
|
||||
chr->descriptors = NULL; /* NULL if no descriptors. Do not include CCCD */
|
||||
chr->flags = flags;
|
||||
chr->min_key_size = 16;
|
||||
chr->val_handle = val_handle;
|
||||
}
|
||||
|
||||
static void inc_aics_svc_init(struct inc_aics_inst *inst,
|
||||
struct ble_gatt_svc_def *svc)
|
||||
{
|
||||
LOG_DBG("[N]IncAicsSvcInit");
|
||||
|
||||
svc->type = BLE_GATT_SVC_TYPE_SECONDARY;
|
||||
svc->uuid = &inc_aics_uuid_svc.u;
|
||||
svc->includes = NULL;
|
||||
|
||||
svc->characteristics = calloc(INC_AICS_CHR_COUNT, sizeof(struct ble_gatt_chr_def));
|
||||
assert(svc->characteristics);
|
||||
|
||||
/* Characteristic - Audio Input State */
|
||||
inc_aics_chr_init((void *)&svc->characteristics[0],
|
||||
&inc_aics_uuid_state,
|
||||
&inst->state_handle,
|
||||
INC_AICS_CHR_FLAGS_STATE);
|
||||
|
||||
/* Characteristic - Gain Setting Properties */
|
||||
inc_aics_chr_init((void *)&svc->characteristics[1],
|
||||
&inc_aics_uuid_gain,
|
||||
&inst->gain_handle,
|
||||
INC_AICS_CHR_FLAGS_GAIN);
|
||||
|
||||
/* Characteristic - Audio Input Type */
|
||||
inc_aics_chr_init((void *)&svc->characteristics[2],
|
||||
&inc_aics_uuid_type,
|
||||
&inst->type_handle,
|
||||
INC_AICS_CHR_FLAGS_TYPE);
|
||||
|
||||
/* Characteristic - Audio Input Status */
|
||||
inc_aics_chr_init((void *)&svc->characteristics[3],
|
||||
&inc_aics_uuid_status,
|
||||
&inst->status_handle,
|
||||
INC_AICS_CHR_FLAGS_STATUS);
|
||||
|
||||
/* Characteristic - Audio Input Control Point */
|
||||
inc_aics_chr_init((void *)&svc->characteristics[4],
|
||||
&inc_aics_uuid_control,
|
||||
&inst->control_handle,
|
||||
INC_AICS_CHR_FLAGS_CONTROL);
|
||||
|
||||
/* Characteristic - Audio Input Description */
|
||||
inc_aics_chr_init((void *)&svc->characteristics[5],
|
||||
&inc_aics_uuid_description,
|
||||
&inst->description_handle,
|
||||
INC_AICS_CHR_FLAGS_DESCRIPTION);
|
||||
}
|
||||
|
||||
int bt_le_nimble_mics_init(void *micp_inc)
|
||||
{
|
||||
struct bt_micp_included *micp_included;
|
||||
uint8_t inc_count;
|
||||
int rc;
|
||||
|
||||
LOG_DBG("[N]MicsInit[%p]", micp_inc);
|
||||
|
||||
micp_included = micp_inc;
|
||||
|
||||
if (micp_included) {
|
||||
LOG_DBG("[N]MicpIncCount[%u]", micp_included->aics_cnt);
|
||||
|
||||
if (micp_included->aics_cnt > CONFIG_BT_MICP_MIC_DEV_AICS_INSTANCE_COUNT) {
|
||||
LOG_ERR("[N]InvMicpIncCount[%u][%u]",
|
||||
micp_included->aics_cnt, CONFIG_BT_MICP_MIC_DEV_AICS_INSTANCE_COUNT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
inc_aics_svc_count = micp_included->aics_cnt;
|
||||
|
||||
/* Extra one for terminating the included service array with NULL */
|
||||
inc_count = inc_aics_svc_count + 1;
|
||||
|
||||
mics_inc_svcs = calloc(inc_count, sizeof(struct ble_gatt_svc_def *));
|
||||
assert(mics_inc_svcs);
|
||||
|
||||
/* MICS may include zero or more instances of AICS */
|
||||
if (inc_aics_svc_count) {
|
||||
inc_aics_insts = calloc(inc_aics_svc_count, sizeof(struct inc_aics_inst));
|
||||
assert(inc_aics_insts);
|
||||
|
||||
/* Extra one for terminating the AICS service array */
|
||||
gatt_svc_inc_aics = calloc(inc_aics_svc_count + 1, sizeof(struct ble_gatt_svc_def));
|
||||
assert(gatt_svc_inc_aics);
|
||||
|
||||
for (size_t i = 0; i < inc_aics_svc_count; i++) {
|
||||
inc_aics_svc_init(&inc_aics_insts[i], &gatt_svc_inc_aics[i]);
|
||||
|
||||
inc_aics_insts[i].svc_p = lib_aics_svc_get(micp_included->aics[i]);
|
||||
|
||||
mics_inc_svcs[i] = &gatt_svc_inc_aics[i];
|
||||
}
|
||||
|
||||
rc = ble_gatts_count_cfg(gatt_svc_inc_aics);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]IncAicsCountCfgFail[%d]", rc);
|
||||
goto free;
|
||||
}
|
||||
|
||||
rc = ble_gatts_add_svcs(gatt_svc_inc_aics);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]IncAicsAddSvcsFail[%d]", rc);
|
||||
goto free;
|
||||
}
|
||||
|
||||
rc = inc_aics_svc_check();
|
||||
if (rc) {
|
||||
goto free;
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminate the included service array with NULL */
|
||||
mics_inc_svcs[inc_count - 1] = NULL;
|
||||
}
|
||||
|
||||
gatt_svc_mics[0].includes = (const struct ble_gatt_svc_def **)mics_inc_svcs;
|
||||
|
||||
rc = ble_gatts_count_cfg(gatt_svc_mics);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]MicsCountCfgFail[%d]", rc);
|
||||
goto free;
|
||||
}
|
||||
|
||||
rc = ble_gatts_add_svcs(gatt_svc_mics);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]MicsAddSvcsFail[%d]", rc);
|
||||
goto free;
|
||||
}
|
||||
|
||||
rc = mics_svc_check();
|
||||
if (rc) {
|
||||
goto free;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
free:
|
||||
if (micp_included) {
|
||||
free(mics_inc_svcs);
|
||||
mics_inc_svcs = NULL;
|
||||
|
||||
if (inc_aics_svc_count) {
|
||||
free(inc_aics_insts);
|
||||
inc_aics_insts = NULL;
|
||||
|
||||
for (size_t i = 0; i < inc_aics_svc_count; i++) {
|
||||
free((void *)gatt_svc_inc_aics[i].characteristics);
|
||||
gatt_svc_inc_aics[i].characteristics = NULL;
|
||||
}
|
||||
|
||||
free(gatt_svc_inc_aics);
|
||||
gatt_svc_inc_aics = NULL;
|
||||
|
||||
inc_aics_svc_count = 0;
|
||||
}
|
||||
}
|
||||
gatt_svc_mics[0].includes = NULL;
|
||||
return rc;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef HOST_NIMBLE_PROFILE_MICS_H_
|
||||
#define HOST_NIMBLE_PROFILE_MICS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <zephyr/bluetooth/audio/audio.h>
|
||||
#include <zephyr/bluetooth/audio/micp.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int bt_le_nimble_mics_attr_handle_set(void);
|
||||
|
||||
int bt_le_nimble_mics_init(void *micp_inc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HOST_NIMBLE_PROFILE_MICS_H_ */
|
||||
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <zephyr/autoconf.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/bluetooth/uuid.h>
|
||||
#include <zephyr/bluetooth/gatt.h>
|
||||
|
||||
#include <../host/conn_internal.h>
|
||||
|
||||
#include "os/os_mbuf.h"
|
||||
#include "os/os_mempool.h"
|
||||
#include "host/ble_att.h"
|
||||
#include "host/ble_gatt.h"
|
||||
#include "host/ble_hs_mbuf.h"
|
||||
|
||||
#include "nimble/profiles/server.h"
|
||||
|
||||
#include "common/host.h"
|
||||
|
||||
#include "../../../lib/include/audio.h"
|
||||
|
||||
#if CONFIG_BT_PAC_SNK
|
||||
static uint16_t pacs_snk_handle;
|
||||
#if CONFIG_BT_PAC_SNK_LOC
|
||||
static uint16_t pacs_snk_loc_handle;
|
||||
#endif /* CONFIG_BT_PAC_SNK_LOC */
|
||||
#endif /* CONFIG_BT_PAC_SNK */
|
||||
|
||||
#if CONFIG_BT_PAC_SRC
|
||||
static uint16_t pacs_src_handle;
|
||||
#if CONFIG_BT_PAC_SRC_LOC
|
||||
static uint16_t pacs_src_loc_handle;
|
||||
#endif /* CONFIG_BT_PAC_SRC_LOC */
|
||||
#endif /* CONFIG_BT_PAC_SRC */
|
||||
|
||||
static uint16_t pacs_ava_ctx_handle;
|
||||
static uint16_t pacs_sup_ctx_handle;
|
||||
|
||||
static const struct ble_gatt_svc_def gatt_svc_pacs[] = {
|
||||
{
|
||||
/* Published Audio Capabilities Service */
|
||||
.type = BLE_GATT_SVC_TYPE_PRIMARY,
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_PACS_VAL),
|
||||
.includes = NULL,
|
||||
.characteristics = (struct ble_gatt_chr_def[])
|
||||
{
|
||||
#if CONFIG_BT_PAC_SNK
|
||||
{
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_PACS_SNK_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
#if CONFIG_BT_PAC_SNK_NOTIFIABLE
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
#else /* CONFIG_BT_PAC_SNK_NOTIFIABLE */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC,
|
||||
#endif /* CONFIG_BT_PAC_SNK_NOTIFIABLE */
|
||||
.min_key_size = 16,
|
||||
.val_handle = &pacs_snk_handle,
|
||||
},
|
||||
#if CONFIG_BT_PAC_SNK_LOC
|
||||
{
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_PACS_SNK_LOC_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
#if CONFIG_BT_PAC_SNK_LOC_WRITEABLE && CONFIG_BT_PAC_SNK_LOC_NOTIFIABLE
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | \
|
||||
BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC | \
|
||||
BLE_GATT_CHR_F_WRITE_ENC,
|
||||
#elif CONFIG_BT_PAC_SNK_LOC_WRITEABLE && !CONFIG_BT_PAC_SNK_LOC_NOTIFIABLE
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | \
|
||||
BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE_ENC,
|
||||
#elif !CONFIG_BT_PAC_SNK_LOC_WRITEABLE && CONFIG_BT_PAC_SNK_LOC_NOTIFIABLE
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
#else /* !CONFIG_BT_PAC_SNK_LOC_WRITEABLE && !CONFIG_BT_PAC_SNK_LOC_NOTIFIABLE */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC,
|
||||
#endif /* CONFIG_BT_PAC_SNK_LOC_WRITEABLE && CONFIG_BT_PAC_SNK_LOC_NOTIFIABLE */
|
||||
.min_key_size = 16,
|
||||
.val_handle = &pacs_snk_loc_handle,
|
||||
},
|
||||
#endif /* CONFIG_BT_PAC_SNK_LOC */
|
||||
#endif /* CONFIG_BT_PAC_SNK */
|
||||
#if CONFIG_BT_PAC_SRC
|
||||
{
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_PACS_SRC_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
#if CONFIG_BT_PAC_SRC_NOTIFIABLE
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
#else /* CONFIG_BT_PAC_SRC_NOTIFIABLE */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC,
|
||||
#endif /* CONFIG_BT_PAC_SRC_NOTIFIABLE */
|
||||
.min_key_size = 16,
|
||||
.val_handle = &pacs_src_handle,
|
||||
},
|
||||
#if CONFIG_BT_PAC_SRC_LOC
|
||||
{
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_PACS_SRC_LOC_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
#if CONFIG_BT_PAC_SRC_LOC_WRITEABLE && CONFIG_BT_PAC_SRC_LOC_NOTIFIABLE
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | \
|
||||
BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC | \
|
||||
BLE_GATT_CHR_F_WRITE_ENC,
|
||||
#elif CONFIG_BT_PAC_SRC_LOC_WRITEABLE && !CONFIG_BT_PAC_SRC_LOC_NOTIFIABLE
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | \
|
||||
BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE_ENC,
|
||||
#elif !CONFIG_BT_PAC_SRC_LOC_WRITEABLE && CONFIG_BT_PAC_SRC_LOC_NOTIFIABLE
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
#else /* !CONFIG_BT_PAC_SRC_LOC_WRITEABLE && !CONFIG_BT_PAC_SRC_LOC_NOTIFIABLE */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC,
|
||||
#endif /* CONFIG_BT_PAC_SRC_LOC_WRITEABLE && CONFIG_BT_PAC_SRC_LOC_NOTIFIABLE */
|
||||
.min_key_size = 16,
|
||||
.val_handle = &pacs_src_loc_handle,
|
||||
},
|
||||
#endif /* CONFIG_BT_PAC_SRC_LOC */
|
||||
#endif /* CONFIG_BT_PAC_SRC */
|
||||
{
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_PACS_AVAILABLE_CONTEXT_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
.val_handle = &pacs_ava_ctx_handle,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_PACS_SUPPORTED_CONTEXT_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
#if CONFIG_BT_PACS_SUPPORTED_CONTEXT_NOTIFIABLE
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
#else /* CONFIG_BT_PACS_SUPPORTED_CONTEXT_NOTIFIABLE */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC,
|
||||
#endif /* CONFIG_BT_PACS_SUPPORTED_CONTEXT_NOTIFIABLE */
|
||||
.min_key_size = 16,
|
||||
.val_handle = &pacs_sup_ctx_handle,
|
||||
}, {
|
||||
0, /* No more characteristics in this service. */
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
0, /* No more services. */
|
||||
},
|
||||
};
|
||||
|
||||
int bt_le_nimble_pacs_attr_handle_set(void)
|
||||
{
|
||||
struct bt_gatt_service *pacs_svc;
|
||||
struct bt_gatt_attr *attr;
|
||||
uint16_t start_handle;
|
||||
uint16_t end_handle;
|
||||
|
||||
pacs_svc = lib_pacs_svc_get();
|
||||
assert(pacs_svc);
|
||||
|
||||
#if CONFIG_BT_PAC_SNK
|
||||
assert(pacs_snk_handle >= 2);
|
||||
start_handle = pacs_snk_handle - 2; /* server attr handle & char def handle */
|
||||
#elif CONFIG_BT_PAC_SRC
|
||||
assert(pacs_src_handle >= 2);
|
||||
start_handle = pacs_src_handle - 2; /* server attr handle & char def handle */
|
||||
#else
|
||||
assert(pacs_ava_ctx_handle >= 2);
|
||||
start_handle = pacs_ava_ctx_handle - 2; /* server attr handle & char def handle */
|
||||
#endif
|
||||
#if CONFIG_BT_PACS_SUPPORTED_CONTEXT_NOTIFIABLE
|
||||
end_handle = pacs_sup_ctx_handle + 1; /* cccd attr handle */
|
||||
#else /* CONFIG_BT_PACS_SUPPORTED_CONTEXT_NOTIFIABLE */
|
||||
end_handle = pacs_sup_ctx_handle; /* char value attr handle */
|
||||
#endif /* CONFIG_BT_PACS_SUPPORTED_CONTEXT_NOTIFIABLE */
|
||||
|
||||
LOG_DBG("[N]PacsAttrHdlSet[%u][%u][%u][%u]",
|
||||
start_handle, end_handle, pacs_sup_ctx_handle, pacs_svc->attr_count);
|
||||
|
||||
for (size_t i = 0; i < pacs_svc->attr_count; i++) {
|
||||
(pacs_svc->attrs + i)->handle = start_handle + i;
|
||||
}
|
||||
|
||||
/* Last attribute in PACS */
|
||||
attr = pacs_svc->attrs + pacs_svc->attr_count - 1;
|
||||
|
||||
if (attr->handle != end_handle) {
|
||||
LOG_ERR("[N]PacsMismatchAttrHdl[%u][%u][%u][%u]",
|
||||
start_handle, end_handle, attr->handle, pacs_svc->attr_count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pacs_svc_check(void)
|
||||
{
|
||||
struct bt_gatt_service *pacs_svc;
|
||||
const struct bt_uuid_16 *uuid;
|
||||
bool chr_found;
|
||||
|
||||
/* This function is used to make sure the characteristics within
|
||||
* the service exist in the service defined by Zephyr.
|
||||
*/
|
||||
|
||||
pacs_svc = lib_pacs_svc_get();
|
||||
assert(pacs_svc);
|
||||
|
||||
LOG_DBG("[N]PacsSvcCheck");
|
||||
|
||||
for (const struct ble_gatt_chr_def *chr = gatt_svc_pacs[0].characteristics;
|
||||
chr && chr->uuid; chr++) {
|
||||
const ble_uuid16_t *check = (const ble_uuid16_t *)chr->uuid;
|
||||
|
||||
chr_found = false;
|
||||
|
||||
for (size_t i = 0; i < pacs_svc->attr_count; i++) {
|
||||
uuid = (const struct bt_uuid_16 *)(pacs_svc->attrs + i)->uuid;
|
||||
|
||||
if (uuid->uuid.type == BT_LE_NIMBLE_GATT_UUID_TO_Z(check->u.type) &&
|
||||
uuid->val == check->value) {
|
||||
chr_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (chr_found == false) {
|
||||
LOG_ERR("[N]PacsChrNotFound[%04x]", check->value);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_le_nimble_pacs_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
LOG_DBG("[N]PacsInit");
|
||||
|
||||
rc = ble_gatts_count_cfg(gatt_svc_pacs);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]PacsCountCfgFail[%d]", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = ble_gatts_add_svcs(gatt_svc_pacs);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]PacsAddSvcsFail[%d]", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = pacs_svc_check();
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef HOST_NIMBLE_PROFILE_PACS_H_
|
||||
#define HOST_NIMBLE_PROFILE_PACS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <zephyr/bluetooth/audio/audio.h>
|
||||
#include <zephyr/bluetooth/audio/pacs.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int bt_le_nimble_pacs_attr_handle_set(void);
|
||||
|
||||
int bt_le_nimble_pacs_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HOST_NIMBLE_PROFILE_PACS_H_ */
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <zephyr/autoconf.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/bluetooth/uuid.h>
|
||||
#include <zephyr/bluetooth/gatt.h>
|
||||
|
||||
#include <../host/conn_internal.h>
|
||||
|
||||
#include "os/os_mbuf.h"
|
||||
#include "os/os_mempool.h"
|
||||
#include "host/ble_hs.h"
|
||||
#include "host/ble_att.h"
|
||||
#include "host/ble_gatt.h"
|
||||
#include "host/ble_hs_mbuf.h"
|
||||
|
||||
#include "common/host.h"
|
||||
|
||||
static ssize_t gatts_read_cb(void *arg, uint16_t offset, const void *data, uint16_t len)
|
||||
{
|
||||
struct os_mbuf *om;
|
||||
int rc;
|
||||
|
||||
ARG_UNUSED(offset);
|
||||
|
||||
om = (struct os_mbuf *)arg;
|
||||
assert(om);
|
||||
|
||||
LOG_DBG("[N]GattsRdCb[%u][%u]", offset, len);
|
||||
|
||||
if (data == NULL || len == 0) {
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = os_mbuf_append(om, data, len);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]MbufAppendFail[%d]", rc);
|
||||
}
|
||||
}
|
||||
|
||||
return (rc == 0 ? len : 0);
|
||||
}
|
||||
|
||||
static int gatts_access_cb(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctx, void *arg)
|
||||
{
|
||||
struct bt_le_nimble_gatt_read_cb cb;
|
||||
const struct bt_gatt_attr *attr;
|
||||
struct bt_conn *conn;
|
||||
uint8_t *data;
|
||||
ssize_t rc;
|
||||
|
||||
assert(ctx);
|
||||
|
||||
LOG_DBG("[N]GattsAccessCb[%u][%u][%02x]", conn_handle, attr_handle, ctx->op);
|
||||
|
||||
conn = bt_le_acl_conn_find(conn_handle);
|
||||
if (conn == NULL || conn->state != BT_CONN_CONNECTED) {
|
||||
LOG_ERR("[N]NotConn[%d]", __LINE__);
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
switch (ctx->op) {
|
||||
case BLE_GATT_ACCESS_OP_READ_CHR:
|
||||
attr = bt_gatts_find_attr_by_handle(attr_handle);
|
||||
if (attr == NULL) {
|
||||
LOG_WRN("[N]RdInvHdl[%u]", attr_handle);
|
||||
return BT_GATT_ERR(BT_ATT_ERR_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
if (attr->read == NULL) {
|
||||
LOG_WRN("[N]RdNotPermit");
|
||||
return BT_GATT_ERR(BT_ATT_ERR_READ_NOT_PERMITTED);
|
||||
}
|
||||
|
||||
cb.read_cb = gatts_read_cb;
|
||||
cb.read_arg = ctx->om;
|
||||
|
||||
rc = attr->read(conn, attr, (void *)&cb, UINT16_MAX, 0);
|
||||
if (rc < 0) {
|
||||
LOG_ERR("[N]RdFail[%u][%d]", attr_handle, rc);
|
||||
return BT_GATT_ERR(rc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
case BLE_GATT_ACCESS_OP_WRITE_CHR:
|
||||
attr = bt_gatts_find_attr_by_handle(attr_handle);
|
||||
if (attr == NULL) {
|
||||
LOG_WRN("[N]WrInvHdl[%u]", attr_handle);
|
||||
return BT_GATT_ERR(BT_ATT_ERR_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
if (attr->write == NULL) {
|
||||
LOG_WRN("[N]WrNotPermit");
|
||||
return BT_GATT_ERR(BT_ATT_ERR_WRITE_NOT_PERMITTED);
|
||||
}
|
||||
|
||||
if (BT_UUID_16(attr->uuid)->val == BT_UUID_BASS_CONTROL_POINT_VAL) {
|
||||
/* Receive Write Long Characteristic for assistant adding source.
|
||||
* TODO:
|
||||
* Check if the following operation could be directly used?
|
||||
* "write(conn, attr, ctx->om->om_data, OS_MBUF_PKTLEN(ctx->om), 0, 0)"
|
||||
*/
|
||||
uint16_t alloc_len = 16 + CONFIG_BT_BAP_BASS_MAX_SUBGROUPS *
|
||||
(5 + CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE);
|
||||
|
||||
LOG_DBG("[N]WrBassControlPoint[%u]", alloc_len);
|
||||
|
||||
if (OS_MBUF_PKTLEN(ctx->om) > alloc_len) {
|
||||
LOG_ERR("[N]WrBassCtrlPtTooLong[%u > %u]",
|
||||
OS_MBUF_PKTLEN(ctx->om), alloc_len);
|
||||
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
|
||||
}
|
||||
|
||||
data = calloc(1, alloc_len);
|
||||
assert(data);
|
||||
|
||||
rc = os_mbuf_copydata(ctx->om, 0, OS_MBUF_PKTLEN(ctx->om), data);
|
||||
assert(rc == 0);
|
||||
|
||||
rc = attr->write(conn, attr, data, OS_MBUF_PKTLEN(ctx->om), 0, 0);
|
||||
|
||||
free(data);
|
||||
data = NULL;
|
||||
} else {
|
||||
LOG_DBG("[N]Wr[%u]", OS_MBUF_PKTLEN(ctx->om));
|
||||
|
||||
data = calloc(1, OS_MBUF_PKTLEN(ctx->om));
|
||||
assert(data);
|
||||
|
||||
rc = os_mbuf_copydata(ctx->om, 0, OS_MBUF_PKTLEN(ctx->om), data);
|
||||
assert(rc == 0);
|
||||
|
||||
rc = attr->write(conn, attr, data, OS_MBUF_PKTLEN(ctx->om), 0, 0);
|
||||
|
||||
free(data);
|
||||
data = NULL;
|
||||
}
|
||||
if (rc < 0) {
|
||||
LOG_ERR("[N]WrFail[%u][%d]", attr_handle, rc);
|
||||
return BT_GATT_ERR(rc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
case BLE_GATT_ACCESS_OP_READ_DSC:
|
||||
return 0;
|
||||
|
||||
case BLE_GATT_ACCESS_OP_WRITE_DSC:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return BLE_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
}
|
||||
|
||||
int bt_le_nimble_gatts_access_cb_safe(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctx, void *arg)
|
||||
{
|
||||
int err;
|
||||
bt_le_host_lock();
|
||||
err = gatts_access_cb(conn_handle, attr_handle, ctx, arg);
|
||||
bt_le_host_unlock();
|
||||
return err;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef HOST_NIMBLE_SERVER_H_
|
||||
#define HOST_NIMBLE_SERVER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "host/ble_gatt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int bt_le_nimble_gatts_access_cb_safe(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctx, void *arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HOST_NIMBLE_SERVER_H_ */
|
||||
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <zephyr/autoconf.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/bluetooth/uuid.h>
|
||||
#include <zephyr/bluetooth/gatt.h>
|
||||
|
||||
#include <../host/conn_internal.h>
|
||||
|
||||
#include "os/os_mbuf.h"
|
||||
#include "os/os_mempool.h"
|
||||
#include "host/ble_att.h"
|
||||
#include "host/ble_gatt.h"
|
||||
#include "host/ble_hs_mbuf.h"
|
||||
|
||||
#include "nimble/profiles/server.h"
|
||||
|
||||
#include "common/host.h"
|
||||
|
||||
#include "../../../lib/include/audio.h"
|
||||
|
||||
static const struct ble_gatt_svc_def gatt_svc_gtbs[] = {
|
||||
{
|
||||
/* Generic Telephone Bearer Service */
|
||||
.type = BLE_GATT_SVC_TYPE_PRIMARY,
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_GTBS_VAL),
|
||||
.includes = NULL,
|
||||
.characteristics = (struct ble_gatt_chr_def[])
|
||||
{
|
||||
{
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_TBS_PROVIDER_NAME_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_TBS_UCI_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_TBS_TECHNOLOGY_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_TBS_URI_LIST_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_TBS_SIGNAL_STRENGTH_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_TBS_SIGNAL_INTERVAL_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | \
|
||||
BLE_GATT_CHR_F_WRITE_NO_RSP | BLE_GATT_CHR_F_READ_ENC | \
|
||||
BLE_GATT_CHR_F_WRITE_ENC,
|
||||
.min_key_size = 16,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_TBS_LIST_CURRENT_CALLS_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_CCID_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_TBS_STATUS_FLAGS_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_TBS_INCOMING_URI_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_TBS_CALL_STATE_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_TBS_CALL_CONTROL_POINT_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_WRITE_NO_RSP | BLE_GATT_CHR_F_WRITE | \
|
||||
BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_WRITE_ENC,
|
||||
.min_key_size = 16,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_TBS_OPTIONAL_OPCODES_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_TBS_TERMINATE_REASON_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_NOTIFY,
|
||||
.min_key_size = 16,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_TBS_INCOMING_CALL_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_TBS_FRIENDLY_NAME_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC,
|
||||
.min_key_size = 16,
|
||||
}, {
|
||||
0, /* No more characteristics in this service. */
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
0, /* No more services. */
|
||||
},
|
||||
};
|
||||
|
||||
int bt_le_nimble_gtbs_attr_handle_set(void)
|
||||
{
|
||||
struct bt_gatt_service *gtbs_svc;
|
||||
uint16_t handle;
|
||||
int rc;
|
||||
|
||||
gtbs_svc = lib_gtbs_svc_get();
|
||||
assert(gtbs_svc);
|
||||
|
||||
LOG_DBG("[N]GtbsAttrHdlSet[%u]", gtbs_svc->attr_count);
|
||||
|
||||
rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_GTBS_VAL), &handle);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]GtbsNotFound[%d]", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
LOG_DBG("[N]Hdl[%u]", handle);
|
||||
|
||||
for (size_t i = 0; i < gtbs_svc->attr_count; i++) {
|
||||
(gtbs_svc->attrs + i)->handle = handle + i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gtbs_svc_check(void)
|
||||
{
|
||||
struct bt_gatt_service *gtbs_svc;
|
||||
const struct bt_uuid_16 *uuid;
|
||||
bool chr_found;
|
||||
|
||||
/* This function is used to make sure the characteristics within
|
||||
* the service exist in the service defined by Zephyr.
|
||||
*/
|
||||
|
||||
gtbs_svc = lib_gtbs_svc_get();
|
||||
assert(gtbs_svc);
|
||||
|
||||
LOG_DBG("[N]GtbsSvcCheck");
|
||||
|
||||
for (const struct ble_gatt_chr_def *chr = gatt_svc_gtbs[0].characteristics;
|
||||
chr && chr->uuid; chr++) {
|
||||
const ble_uuid16_t *check = (const ble_uuid16_t *)chr->uuid;
|
||||
|
||||
chr_found = false;
|
||||
|
||||
for (size_t i = 0; i < gtbs_svc->attr_count; i++) {
|
||||
uuid = (const struct bt_uuid_16 *)(gtbs_svc->attrs + i)->uuid;
|
||||
|
||||
if (uuid->uuid.type == BT_LE_NIMBLE_GATT_UUID_TO_Z(check->u.type) &&
|
||||
uuid->val == check->value) {
|
||||
chr_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (chr_found == false) {
|
||||
LOG_ERR("[N]GtbsChrNotFound[%04x]", check->value);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_le_nimble_gtbs_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
LOG_DBG("[N]GtbsInit");
|
||||
|
||||
rc = ble_gatts_count_cfg(gatt_svc_gtbs);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]GtbsCountCfgFail[%d]", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = ble_gatts_add_svcs(gatt_svc_gtbs);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]GtbsAddSvcsFail[%d]", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = gtbs_svc_check();
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef HOST_NIMBLE_PROFILE_TBS_H_
|
||||
#define HOST_NIMBLE_PROFILE_TBS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int bt_le_nimble_gtbs_attr_handle_set(void);
|
||||
|
||||
int bt_le_nimble_gtbs_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HOST_NIMBLE_PROFILE_TBS_H_ */
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <zephyr/autoconf.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/bluetooth/uuid.h>
|
||||
#include <zephyr/bluetooth/gatt.h>
|
||||
|
||||
#include <../host/conn_internal.h>
|
||||
|
||||
#include "os/os_mbuf.h"
|
||||
#include "os/os_mempool.h"
|
||||
#include "host/ble_att.h"
|
||||
#include "host/ble_gatt.h"
|
||||
#include "host/ble_hs_mbuf.h"
|
||||
|
||||
#include "nimble/profiles/server.h"
|
||||
|
||||
#include "common/host.h"
|
||||
|
||||
#include "../../../lib/include/audio.h"
|
||||
|
||||
static const struct ble_gatt_svc_def gatt_svc_tmas[] = {
|
||||
{
|
||||
/* Telephony and Media Audio Service */
|
||||
.type = BLE_GATT_SVC_TYPE_PRIMARY,
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_TMAS_VAL),
|
||||
.includes = NULL,
|
||||
.characteristics = (struct ble_gatt_chr_def[])
|
||||
{
|
||||
{
|
||||
.uuid = BLE_UUID16_DECLARE(BT_UUID_GATT_TMAPR_VAL),
|
||||
.access_cb = bt_le_nimble_gatts_access_cb_safe,
|
||||
.arg = NULL,
|
||||
.descriptors = NULL, /* NULL if no descriptors. Do not include CCCD */
|
||||
.flags = BLE_GATT_CHR_F_READ,
|
||||
.min_key_size = 0,
|
||||
.val_handle = NULL,
|
||||
}, {
|
||||
0, /* No more characteristics in this service. */
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
0, /* No more services. */
|
||||
},
|
||||
};
|
||||
|
||||
int bt_le_nimble_tmas_attr_handle_set(void)
|
||||
{
|
||||
struct bt_gatt_service *tmas_svc;
|
||||
uint16_t handle;
|
||||
int rc;
|
||||
|
||||
tmas_svc = lib_tmas_svc_get();
|
||||
assert(tmas_svc);
|
||||
|
||||
LOG_DBG("[N]TmasAttrHdlSet[%u]", tmas_svc->attr_count);
|
||||
|
||||
rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_TMAS_VAL), &handle);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]TmasNotFound[%d]", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
LOG_DBG("[N]Hdl[%u]", handle);
|
||||
|
||||
for (size_t i = 0; i < tmas_svc->attr_count; i++) {
|
||||
(tmas_svc->attrs + i)->handle = handle + i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tmas_svc_check(void)
|
||||
{
|
||||
struct bt_gatt_service *tmas_svc;
|
||||
const struct bt_uuid_16 *uuid;
|
||||
bool chr_found;
|
||||
|
||||
/* This function is used to make sure the characteristics within
|
||||
* the service exist in the service defined by Zephyr.
|
||||
*/
|
||||
|
||||
tmas_svc = lib_tmas_svc_get();
|
||||
assert(tmas_svc);
|
||||
|
||||
LOG_DBG("[N]TmasSvcCheck");
|
||||
|
||||
for (const struct ble_gatt_chr_def *chr = gatt_svc_tmas[0].characteristics;
|
||||
chr && chr->uuid; chr++) {
|
||||
const ble_uuid16_t *check = (const ble_uuid16_t *)chr->uuid;
|
||||
|
||||
chr_found = false;
|
||||
|
||||
for (size_t i = 0; i < tmas_svc->attr_count; i++) {
|
||||
uuid = (const struct bt_uuid_16 *)(tmas_svc->attrs + i)->uuid;
|
||||
|
||||
if (uuid->uuid.type == BT_LE_NIMBLE_GATT_UUID_TO_Z(check->u.type) &&
|
||||
uuid->val == check->value) {
|
||||
chr_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (chr_found == false) {
|
||||
LOG_ERR("[N]TmasChrNotFound[%04x]", check->value);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_le_nimble_tmas_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
LOG_DBG("[N]TmasInit");
|
||||
|
||||
rc = ble_gatts_count_cfg(gatt_svc_tmas);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]TmasCountCfgFail[%d]", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = ble_gatts_add_svcs(gatt_svc_tmas);
|
||||
if (rc) {
|
||||
LOG_ERR("[N]TmasAddSvcsFail[%d]", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = tmas_svc_check();
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef HOST_NIMBLE_PROFILE_TMAS_H_
|
||||
#define HOST_NIMBLE_PROFILE_TMAS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int bt_le_nimble_tmas_attr_handle_set(void);
|
||||
|
||||
int bt_le_nimble_tmas_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HOST_NIMBLE_PROFILE_TMAS_H_ */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user