From e0d36beb722f4b901e08fda75853b8d7d187f1ff Mon Sep 17 00:00:00 2001 From: Mariusz Skamra Date: Mon, 25 Jul 2022 09:56:23 +0200 Subject: [PATCH] Bluetooth: audio: Add security requirements check The LE Audio related profiles define specific security requirements that client have to met to gain access to related characteristics. This introduces internal wrapper API for GATT characteristics and CCC descriptors to ensure the security. Signed-off-by: Mariusz Skamra --- subsys/bluetooth/audio/CMakeLists.txt | 1 + subsys/bluetooth/audio/Kconfig.ascs | 1 - subsys/bluetooth/audio/Kconfig.bass | 1 - subsys/bluetooth/audio/Kconfig.csis | 2 - subsys/bluetooth/audio/Kconfig.has | 2 - subsys/bluetooth/audio/Kconfig.pacs | 1 - subsys/bluetooth/audio/aics.c | 148 +++++----- subsys/bluetooth/audio/ascs.c | 64 ++--- subsys/bluetooth/audio/audio.c | 99 +++++++ subsys/bluetooth/audio/audio_internal.h | 60 +++++ subsys/bluetooth/audio/bass.c | 23 +- subsys/bluetooth/audio/csis.c | 56 ++-- subsys/bluetooth/audio/has.c | 27 +- subsys/bluetooth/audio/mcs.c | 254 ++++++++---------- subsys/bluetooth/audio/micp_mic_dev.c | 13 +- subsys/bluetooth/audio/pacs.c | 87 +++--- subsys/bluetooth/audio/tbs.c | 241 ++++++++--------- subsys/bluetooth/audio/vcs.c | 31 ++- subsys/bluetooth/audio/vocs.c | 104 +++---- .../bsim_bt/bsim_test_audio/prj.conf | 2 - tests/bluetooth/shell/audio.conf | 2 - 21 files changed, 646 insertions(+), 573 deletions(-) create mode 100644 subsys/bluetooth/audio/audio.c create mode 100644 subsys/bluetooth/audio/audio_internal.h diff --git a/subsys/bluetooth/audio/CMakeLists.txt b/subsys/bluetooth/audio/CMakeLists.txt index 3e96eba69cf..568d68e2217 100644 --- a/subsys/bluetooth/audio/CMakeLists.txt +++ b/subsys/bluetooth/audio/CMakeLists.txt @@ -1,6 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_library() +zephyr_library_sources(audio.c) if (CONFIG_BT_VOCS OR CONFIG_BT_VOCS_CLIENT) zephyr_library_sources(vocs.c) diff --git a/subsys/bluetooth/audio/Kconfig.ascs b/subsys/bluetooth/audio/Kconfig.ascs index dd3db017ad5..64c5a22a792 100644 --- a/subsys/bluetooth/audio/Kconfig.ascs +++ b/subsys/bluetooth/audio/Kconfig.ascs @@ -8,7 +8,6 @@ config BT_ASCS bool "Audio Stream Control Service Support" - select BT_SMP_SC_PAIR_ONLY help This option enables support for Audio Stream Control Service. diff --git a/subsys/bluetooth/audio/Kconfig.bass b/subsys/bluetooth/audio/Kconfig.bass index c1c05c2f2ee..3356ffdc168 100644 --- a/subsys/bluetooth/audio/Kconfig.bass +++ b/subsys/bluetooth/audio/Kconfig.bass @@ -15,7 +15,6 @@ config BT_BASS select BT_OBSERVER select BT_EXT_ADV select BT_PER_ADV_SYNC - select BT_SMP_SC_PAIR_ONLY select BT_ISO_SYNC_RECEIVER help This option enables support for the Broadcast Audio Scan Service. diff --git a/subsys/bluetooth/audio/Kconfig.csis b/subsys/bluetooth/audio/Kconfig.csis index ab725ac5f7b..b845fc92761 100644 --- a/subsys/bluetooth/audio/Kconfig.csis +++ b/subsys/bluetooth/audio/Kconfig.csis @@ -31,7 +31,6 @@ config BT_CSIS_TEST_SAMPLE_DATA config BT_CSIS_ENC_SIRK_SUPPORT bool "Support for encrypted SIRK" default y - select BT_SMP_SC_PAIR_ONLY help Enables support encrypting the SIRK. @@ -92,7 +91,6 @@ config BT_CSIS_CLIENT_MAX_CSIS_INSTANCES config BT_CSIS_CLIENT_ENC_SIRK_SUPPORT bool "Support for encrypted SIRK" default y - select BT_SMP_SC_PAIR_ONLY help Enables support encrypting the SIRK. diff --git a/subsys/bluetooth/audio/Kconfig.has b/subsys/bluetooth/audio/Kconfig.has index db63cc9fe26..81ea6d1b38a 100644 --- a/subsys/bluetooth/audio/Kconfig.has +++ b/subsys/bluetooth/audio/Kconfig.has @@ -8,8 +8,6 @@ menuconfig BT_HAS bool "Hearing Access Service support [EXPERIMENTAL]" select EXPERIMENTAL select UTF8 - depends on BT_SMP_SC_PAIR_ONLY - depends on BT_SMP_MIN_ENC_KEY_SIZE = 16 depends on BT_AUDIO_UNICAST_SERVER help This option enables support for Hearing Access Service. diff --git a/subsys/bluetooth/audio/Kconfig.pacs b/subsys/bluetooth/audio/Kconfig.pacs index 58a004da6e2..db822ce9585 100644 --- a/subsys/bluetooth/audio/Kconfig.pacs +++ b/subsys/bluetooth/audio/Kconfig.pacs @@ -87,7 +87,6 @@ endif # BT_PAC_SRC config BT_PACS def_bool BT_PAC_SNK || BT_PAC_SRC - select BT_SMP_SC_PAIR_ONLY config BT_DEBUG_PACS bool "Published Audio Capabilities Service debug" diff --git a/subsys/bluetooth/audio/aics.c b/subsys/bluetooth/audio/aics.c index 5bda106ffd3..559e2a26f90 100644 --- a/subsys/bluetooth/audio/aics.c +++ b/subsys/bluetooth/audio/aics.c @@ -18,6 +18,7 @@ #include #include "aics_internal.h" +#include "audio_internal.h" #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_AICS) #define LOG_MODULE_NAME bt_aics @@ -65,36 +66,33 @@ static ssize_t read_description(struct bt_conn *conn, #define BT_AICS_SERVICE_DEFINITION(_aics) { \ BT_GATT_SECONDARY_SERVICE(BT_UUID_AICS), \ - BT_GATT_CHARACTERISTIC(BT_UUID_AICS_STATE, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_LESC, \ - read_aics_state, NULL, &_aics), \ - BT_GATT_CCC(aics_state_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_LESC), \ - BT_GATT_CHARACTERISTIC(BT_UUID_AICS_GAIN_SETTINGS, \ - BT_GATT_CHRC_READ, \ - BT_GATT_PERM_READ_LESC, \ - read_aics_gain_settings, NULL, &_aics), \ - BT_GATT_CHARACTERISTIC(BT_UUID_AICS_INPUT_TYPE, \ - BT_GATT_CHRC_READ, \ - BT_GATT_PERM_READ_LESC, \ - read_type, NULL, &_aics), \ - BT_GATT_CHARACTERISTIC(BT_UUID_AICS_INPUT_STATUS, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_LESC, \ - read_input_status, NULL, &_aics), \ - BT_GATT_CCC(aics_input_status_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_LESC), \ - BT_GATT_CHARACTERISTIC(BT_UUID_AICS_CONTROL, \ - BT_GATT_CHRC_WRITE, \ - BT_GATT_PERM_WRITE_LESC, \ - NULL, write_aics_control, &_aics), \ - BT_GATT_CHARACTERISTIC(BT_UUID_AICS_DESCRIPTION, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_LESC, \ - read_description, NULL, &_aics), \ - BT_GATT_CCC(aics_description_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_LESC) \ + BT_AUDIO_CHRC(BT_UUID_AICS_STATE, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_aics_state, NULL, &_aics), \ + BT_AUDIO_CCC(aics_state_cfg_changed), \ + BT_AUDIO_CHRC(BT_UUID_AICS_GAIN_SETTINGS, \ + BT_GATT_CHRC_READ, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_aics_gain_settings, NULL, &_aics), \ + BT_AUDIO_CHRC(BT_UUID_AICS_INPUT_TYPE, \ + BT_GATT_CHRC_READ, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_type, NULL, &_aics), \ + BT_AUDIO_CHRC(BT_UUID_AICS_INPUT_STATUS, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_input_status, NULL, &_aics), \ + BT_AUDIO_CCC(aics_input_status_cfg_changed), \ + BT_AUDIO_CHRC(BT_UUID_AICS_CONTROL, \ + BT_GATT_CHRC_WRITE, \ + BT_GATT_PERM_WRITE_ENCRYPT, \ + NULL, write_aics_control, &_aics), \ + BT_AUDIO_CHRC(BT_UUID_AICS_DESCRIPTION, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_description, write_description, &_aics), \ + BT_AUDIO_CCC(aics_description_cfg_changed) \ } @@ -114,7 +112,7 @@ static ssize_t read_aics_state(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { - struct bt_aics *inst = attr->user_data; + struct bt_aics *inst = BT_AUDIO_CHRC_USER_DATA(attr); BT_DBG("gain %d, mute %u, gain_mode %u, counter %u", inst->srv.state.gain, inst->srv.state.mute, @@ -128,7 +126,7 @@ static ssize_t read_aics_gain_settings(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { - struct bt_aics *inst = attr->user_data; + struct bt_aics *inst = BT_AUDIO_CHRC_USER_DATA(attr); BT_DBG("units %u, min %d, max %d", inst->srv.gain_settings.units, inst->srv.gain_settings.minimum, @@ -142,7 +140,7 @@ static ssize_t read_aics_gain_settings(struct bt_conn *conn, static ssize_t read_type(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { - struct bt_aics *inst = attr->user_data; + struct bt_aics *inst = BT_AUDIO_CHRC_USER_DATA(attr); BT_DBG("%u", inst->srv.type); @@ -160,7 +158,7 @@ static ssize_t read_input_status(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { - struct bt_aics *inst = attr->user_data; + struct bt_aics *inst = BT_AUDIO_CHRC_USER_DATA(attr); BT_DBG("%u", inst->srv.status); @@ -175,7 +173,7 @@ static ssize_t write_aics_control(struct bt_conn *conn, const void *buf, uint16_t len, uint16_t offset, uint8_t flags) { - struct bt_aics *inst = attr->user_data; + struct bt_aics *inst = BT_AUDIO_CHRC_USER_DATA(attr); const struct bt_aics_gain_control *cp = buf; bool notify = false; @@ -297,7 +295,7 @@ static ssize_t write_description(struct bt_conn *conn, const void *buf, uint16_t len, uint16_t offset, uint8_t flags) { - struct bt_aics *inst = attr->user_data; + struct bt_aics *inst = BT_AUDIO_CHRC_USER_DATA(attr); if (len >= sizeof(inst->srv.description)) { BT_DBG("Output desc was clipped from length %u to %zu", @@ -327,12 +325,35 @@ static ssize_t write_description(struct bt_conn *conn, return len; } +static int aics_write(struct bt_aics *inst, + ssize_t (*write)(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + const void *buf, uint16_t len, + uint16_t offset, uint8_t flags), + const void *buf, uint16_t len) +{ + struct bt_audio_attr_user_data user_data = { + .user_data = inst, + }; + struct bt_gatt_attr attr = { + .user_data = &user_data, + }; + int err; + + err = write(NULL, &attr, buf, len, 0, 0); + if (err < 0) { + return err; + } + + return 0; +} + #if defined(CONFIG_BT_AICS) static ssize_t read_description(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { - struct bt_aics *inst = attr->user_data; + struct bt_aics *inst = BT_AUDIO_CHRC_USER_DATA(attr); BT_DBG("%s", inst->srv.description); @@ -455,8 +476,7 @@ int bt_aics_register(struct bt_aics *aics, struct bt_aics_register_param *param) struct bt_gatt_chrc *chrc; chrc = aics->srv.service_p->attrs[i - 1].user_data; - attr->write = write_description; - attr->perm |= BT_GATT_PERM_WRITE_LESC; + attr->perm |= BT_GATT_PERM_WRITE_ENCRYPT; chrc->properties |= BT_GATT_CHRC_WRITE_WITHOUT_RESP; break; @@ -638,18 +658,12 @@ int bt_aics_unmute(struct bt_aics *inst) if (IS_ENABLED(CONFIG_BT_AICS_CLIENT) && inst->client_instance) { return bt_aics_client_unmute(inst); } else if (IS_ENABLED(CONFIG_BT_AICS) && !inst->client_instance) { - struct bt_gatt_attr attr; struct bt_aics_control cp; - int err; cp.opcode = BT_AICS_OPCODE_UNMUTE; cp.counter = inst->srv.state.change_counter; - attr.user_data = inst; - - err = write_aics_control(NULL, &attr, &cp, sizeof(cp), 0, 0); - - return err > 0 ? 0 : err; + return aics_write(inst, write_aics_control, &cp, sizeof(cp)); } return -ENOTSUP; @@ -665,18 +679,12 @@ int bt_aics_mute(struct bt_aics *inst) if (IS_ENABLED(CONFIG_BT_AICS_CLIENT) && inst->client_instance) { return bt_aics_client_mute(inst); } else if (IS_ENABLED(CONFIG_BT_AICS) && !inst->client_instance) { - struct bt_gatt_attr attr; struct bt_aics_control cp; - int err; cp.opcode = BT_AICS_OPCODE_MUTE; cp.counter = inst->srv.state.change_counter; - attr.user_data = inst; - - err = write_aics_control(NULL, &attr, &cp, sizeof(cp), 0, 0); - - return err > 0 ? 0 : err; + return aics_write(inst, write_aics_control, &cp, sizeof(cp)); } return -ENOTSUP; @@ -692,18 +700,12 @@ int bt_aics_manual_gain_set(struct bt_aics *inst) if (IS_ENABLED(CONFIG_BT_AICS_CLIENT) && inst->client_instance) { return bt_aics_client_manual_gain_set(inst); } else if (IS_ENABLED(CONFIG_BT_AICS) && !inst->client_instance) { - struct bt_gatt_attr attr; struct bt_aics_control cp; - int err; cp.opcode = BT_AICS_OPCODE_SET_MANUAL; cp.counter = inst->srv.state.change_counter; - attr.user_data = inst; - - err = write_aics_control(NULL, &attr, &cp, sizeof(cp), 0, 0); - - return err > 0 ? 0 : err; + return aics_write(inst, write_aics_control, &cp, sizeof(cp)); } return -ENOTSUP; @@ -719,18 +721,12 @@ int bt_aics_automatic_gain_set(struct bt_aics *inst) if (IS_ENABLED(CONFIG_BT_AICS_CLIENT) && inst->client_instance) { return bt_aics_client_automatic_gain_set(inst); } else if (IS_ENABLED(CONFIG_BT_AICS) && !inst->client_instance) { - struct bt_gatt_attr attr; struct bt_aics_control cp; - int err; cp.opcode = BT_AICS_OPCODE_SET_AUTO; cp.counter = inst->srv.state.change_counter; - attr.user_data = inst; - - err = write_aics_control(NULL, &attr, &cp, sizeof(cp), 0, 0); - - return err > 0 ? 0 : err; + return aics_write(inst, write_aics_control, &cp, sizeof(cp)); } return -ENOTSUP; @@ -746,19 +742,13 @@ int bt_aics_gain_set(struct bt_aics *inst, int8_t gain) if (IS_ENABLED(CONFIG_BT_AICS_CLIENT) && inst->client_instance) { return bt_aics_client_gain_set(inst, gain); } else if (IS_ENABLED(CONFIG_BT_AICS) && !inst->client_instance) { - struct bt_gatt_attr attr; struct bt_aics_gain_control cp; - int err; cp.cp.opcode = BT_AICS_OPCODE_SET_GAIN; cp.cp.counter = inst->srv.state.change_counter; cp.gain_setting = gain; - attr.user_data = inst; - - err = write_aics_control(NULL, &attr, &cp, sizeof(cp), 0, 0); - - return err > 0 ? 0 : err; + return aics_write(inst, write_aics_control, &cp, sizeof(cp)); } return -ENOTSUP; @@ -801,15 +791,7 @@ int bt_aics_description_set(struct bt_aics *inst, const char *description) if (IS_ENABLED(CONFIG_BT_AICS_CLIENT) && inst->client_instance) { return bt_aics_client_description_set(inst, description); } else if (IS_ENABLED(CONFIG_BT_AICS) && !inst->client_instance) { - struct bt_gatt_attr attr; - int err; - - attr.user_data = inst; - - err = write_description(NULL, &attr, description, - strlen(description), 0, 0); - - return err > 0 ? 0 : err; + return aics_write(inst, write_description, description, strlen(description)); } return -ENOTSUP; diff --git a/subsys/bluetooth/audio/ascs.c b/subsys/bluetooth/audio/ascs.c index 0ed1a3a9b07..de351f750d2 100644 --- a/subsys/bluetooth/audio/ascs.c +++ b/subsys/bluetooth/audio/ascs.c @@ -27,6 +27,7 @@ #include "../host/hci_core.h" #include "../host/conn_internal.h" +#include "audio_internal.h" #include "endpoint.h" #include "unicast_server.h" #include "pacs_internal.h" @@ -932,7 +933,7 @@ static uint8_t ase_attr_cb(const struct bt_gatt_attr *attr, uint16_t handle, { struct bt_ascs_ase *ase = user_data; - if (ase->ep.status.id == POINTER_TO_UINT(attr->user_data)) { + if (ase->ep.status.id == POINTER_TO_UINT(BT_AUDIO_CHRC_USER_DATA(attr))) { ase->ep.server.attr = attr; return BT_GATT_ITER_STOP; @@ -1067,7 +1068,7 @@ static ssize_t ascs_ase_read(struct bt_conn *conn, return BT_GATT_ERR(BT_ATT_ERR_UNLIKELY); } - ase = ase_get(ascs, POINTER_TO_UINT(attr->user_data)); + ase = ase_get(ascs, POINTER_TO_UINT(BT_AUDIO_CHRC_USER_DATA(attr))); if (!ase) { BT_ERR("Unable to get ASE"); return BT_GATT_ERR(BT_ATT_ERR_UNLIKELY); @@ -2298,47 +2299,38 @@ respond: BT_GATT_SERVICE_DEFINE(ascs_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_ASCS), #if CONFIG_BT_ASCS_ASE_SNK_COUNT > 0 - BT_GATT_CHARACTERISTIC(BT_UUID_ASCS_ASE_SNK, - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, - BT_GATT_PERM_READ_ENCRYPT, - ascs_ase_read, NULL, UINT_TO_POINTER(1)), - BT_GATT_CCC(ascs_ase_cfg_changed, - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), + BT_AUDIO_CHRC(BT_UUID_ASCS_ASE_SNK, + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, + BT_GATT_PERM_READ_ENCRYPT, + ascs_ase_read, NULL, UINT_TO_POINTER(1)), + BT_AUDIO_CCC(ascs_ase_cfg_changed), #endif #if CONFIG_BT_ASCS_ASE_SNK_COUNT > 1 - BT_GATT_CHARACTERISTIC(BT_UUID_ASCS_ASE_SNK, - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, - BT_GATT_PERM_READ_ENCRYPT, - ascs_ase_read, NULL, UINT_TO_POINTER(2)), - BT_GATT_CCC(ascs_ase_cfg_changed, - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), + BT_AUDIO_CHRC(BT_UUID_ASCS_ASE_SNK, + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, + BT_GATT_PERM_READ_ENCRYPT, + ascs_ase_read, NULL, UINT_TO_POINTER(2)), + BT_AUDIO_CCC(ascs_ase_cfg_changed), #endif #if CONFIG_BT_ASCS_ASE_SRC_COUNT > 0 - BT_GATT_CHARACTERISTIC(BT_UUID_ASCS_ASE_SRC, - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, - BT_GATT_PERM_READ_ENCRYPT, - ascs_ase_read, NULL, - UINT_TO_POINTER(CONFIG_BT_ASCS_ASE_SNK_COUNT + 1)), - BT_GATT_CCC(ascs_ase_cfg_changed, - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), + BT_AUDIO_CHRC(BT_UUID_ASCS_ASE_SRC, + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, + BT_GATT_PERM_READ_ENCRYPT, + ascs_ase_read, NULL, UINT_TO_POINTER(CONFIG_BT_ASCS_ASE_SNK_COUNT + 1)), + BT_AUDIO_CCC(ascs_ase_cfg_changed), #endif #if CONFIG_BT_ASCS_ASE_SRC_COUNT > 1 - BT_GATT_CHARACTERISTIC(BT_UUID_ASCS_ASE_SRC, - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, - BT_GATT_PERM_READ_ENCRYPT, - ascs_ase_read, NULL, - UINT_TO_POINTER(CONFIG_BT_ASCS_ASE_SNK_COUNT + 2)), - BT_GATT_CCC(ascs_ase_cfg_changed, - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), + BT_AUDIO_CHRC(BT_UUID_ASCS_ASE_SRC, + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, + BT_GATT_PERM_READ_ENCRYPT, + ascs_ase_read, NULL, UINT_TO_POINTER(CONFIG_BT_ASCS_ASE_SNK_COUNT + 2)), + BT_AUDIO_CCC(ascs_ase_cfg_changed), #endif - BT_GATT_CHARACTERISTIC(BT_UUID_ASCS_ASE_CP, - BT_GATT_CHRC_WRITE | - BT_GATT_CHRC_WRITE_WITHOUT_RESP | - BT_GATT_CHRC_NOTIFY, - BT_GATT_PERM_WRITE_ENCRYPT, - NULL, ascs_cp_write, NULL), - BT_GATT_CCC(ascs_cp_cfg_changed, - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT) + BT_AUDIO_CHRC(BT_UUID_ASCS_ASE_CP, + BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP | BT_GATT_CHRC_NOTIFY, + BT_GATT_PERM_WRITE_ENCRYPT, + NULL, ascs_cp_write, NULL), + BT_AUDIO_CCC(ascs_cp_cfg_changed), ); #endif /* BT_AUDIO_UNICAST_SERVER */ diff --git a/subsys/bluetooth/audio/audio.c b/subsys/bluetooth/audio/audio.c new file mode 100644 index 00000000000..18c03110f2b --- /dev/null +++ b/subsys/bluetooth/audio/audio.c @@ -0,0 +1,99 @@ +/* Common functions for LE Audio services */ + +/* + * Copyright (c) 2022 Codecoup + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "audio_internal.h" + +static uint8_t bt_audio_security_check(const struct bt_conn *conn) +{ + struct bt_conn_info info; + int err; + + err = bt_conn_get_info(conn, &info); + if (err < 0) { + return BT_ATT_ERR_UNLIKELY; + } + + /* Require an encryption key with at least 128 bits of entropy, derived from SC or OOB + * method. + */ + if ((info.security.flags & (BT_SECURITY_FLAG_OOB | BT_SECURITY_FLAG_SC)) == 0) { + /* If the client has insufficient security to read/write the requested attribute + * then an ATT_ERROR_RSP PDU shall be sent with the Error Code parameter set to + * Insufficient Authentication (0x05). + */ + return BT_ATT_ERR_AUTHENTICATION; + } + + if (info.security.enc_key_size < BT_ENC_KEY_SIZE_MAX) { + return BT_ATT_ERR_ENCRYPTION_KEY_SIZE; + } + + return BT_ATT_ERR_SUCCESS; +} + +ssize_t bt_audio_read_chrc(struct bt_conn *conn, const struct bt_gatt_attr *attr, + void *buf, uint16_t len, uint16_t offset) +{ + const struct bt_audio_attr_user_data *user_data = attr->user_data; + + if (user_data->read == NULL) { + return BT_GATT_ERR(BT_ATT_ERR_READ_NOT_PERMITTED); + } + + if (conn != NULL) { + uint8_t err; + + err = bt_audio_security_check(conn); + if (err != 0) { + return BT_GATT_ERR(err); + } + } + + return user_data->read(conn, attr, buf, len, offset); +} + +ssize_t bt_audio_write_chrc(struct bt_conn *conn, const struct bt_gatt_attr *attr, + const void *buf, uint16_t len, uint16_t offset, uint8_t flags) +{ + const struct bt_audio_attr_user_data *user_data = attr->user_data; + + if (user_data->write == NULL) { + return BT_GATT_ERR(BT_ATT_ERR_WRITE_NOT_PERMITTED); + } + + if (conn != NULL) { + uint8_t err; + + err = bt_audio_security_check(conn); + if (err != 0) { + return BT_GATT_ERR(err); + } + } + + return user_data->write(conn, attr, buf, len, offset, flags); +} + +ssize_t bt_audio_ccc_cfg_write(struct bt_conn *conn, const struct bt_gatt_attr *attr, + uint16_t value) +{ + if (conn != NULL) { + uint8_t err; + + err = bt_audio_security_check(conn); + if (err != 0) { + return BT_GATT_ERR(err); + } + } + + return sizeof(value); +} diff --git a/subsys/bluetooth/audio/audio_internal.h b/subsys/bluetooth/audio/audio_internal.h new file mode 100644 index 00000000000..2f440c64ace --- /dev/null +++ b/subsys/bluetooth/audio/audio_internal.h @@ -0,0 +1,60 @@ +/* @file + * @brief Internal APIs for LE Audio + * + * Copyright (c) 2022 Codecoup + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/** @brief LE Audio Attribute User Data. */ +struct bt_audio_attr_user_data { + /** Attribute read callback */ + ssize_t (*read)(struct bt_conn *conn, const struct bt_gatt_attr *attr, + void *buf, uint16_t len, uint16_t offset); + + /** Attribute write callback */ + ssize_t (*write)(struct bt_conn *conn, const struct bt_gatt_attr *attr, + const void *buf, uint16_t len, uint16_t offset, + uint8_t flags); + + /** Attribute user data */ + void *user_data; +}; + +/** LE Audio Read Characteristic value helper. */ +ssize_t bt_audio_read_chrc(struct bt_conn *conn, const struct bt_gatt_attr *attr, + void *buf, uint16_t len, uint16_t offset); + +/** LE Audio Write Characteristic value helper. */ +ssize_t bt_audio_write_chrc(struct bt_conn *conn, const struct bt_gatt_attr *attr, + const void *buf, uint16_t len, uint16_t offset, uint8_t flags); + +#define BT_AUDIO_ATTR_USER_DATA_INIT(_read, _write, _user_data) \ +{ \ + .read = _read, \ + .write = _write, \ + .user_data = _user_data, \ +} + +/** Helper to define LE Audio characteristic. */ +#define BT_AUDIO_CHRC(_uuid, _props, _perm, _read, _write, _user_data) \ + BT_GATT_CHARACTERISTIC(_uuid, _props, _perm, bt_audio_read_chrc, bt_audio_write_chrc, \ + ((struct bt_audio_attr_user_data[]) { \ + BT_AUDIO_ATTR_USER_DATA_INIT(_read, _write, _user_data), \ + })) + +#define BT_AUDIO_CHRC_USER_DATA(_attr) \ + (((struct bt_audio_attr_user_data *)(_attr)->user_data)->user_data) + +/** LE Audio Write CCCD value helper. */ +ssize_t bt_audio_ccc_cfg_write(struct bt_conn *conn, const struct bt_gatt_attr *attr, + uint16_t value); + +/** Helper to define LE Audio CCC descriptor. */ +#define BT_AUDIO_CCC(_changed) \ + BT_GATT_CCC_MANAGED(((struct _bt_gatt_ccc[]) \ + {BT_GATT_CCC_INITIALIZER(_changed, bt_audio_ccc_cfg_write, NULL)}), \ + (BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT)) diff --git a/subsys/bluetooth/audio/bass.c b/subsys/bluetooth/audio/bass.c index 5f8f6758bba..e01df9aed16 100644 --- a/subsys/bluetooth/audio/bass.c +++ b/subsys/bluetooth/audio/bass.c @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -23,6 +24,7 @@ #define LOG_MODULE_NAME bt_bass #include "common/log.h" +#include "audio_internal.h" #include "bass_internal.h" #include "../host/conn_internal.h" #include "../host/hci_core.h" @@ -1223,7 +1225,7 @@ static ssize_t read_recv_state(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { - uint8_t idx = (uint8_t)(uintptr_t)attr->user_data; + uint8_t idx = POINTER_TO_UINT(BT_AUDIO_CHRC_USER_DATA(attr)); struct bass_recv_state_internal *recv_state = &bass_inst.recv_states[idx]; struct bt_bass_recv_state *state = &recv_state->state; @@ -1244,19 +1246,18 @@ static ssize_t read_recv_state(struct bt_conn *conn, } #define RECEIVE_STATE_CHARACTERISTIC(idx) \ - BT_GATT_CHARACTERISTIC(BT_UUID_BASS_RECV_STATE, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,\ - BT_GATT_PERM_READ_ENCRYPT, \ - read_recv_state, NULL, (void *)idx), \ - BT_GATT_CCC(recv_state_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT) + BT_AUDIO_CHRC(BT_UUID_BASS_RECV_STATE, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,\ + BT_GATT_PERM_READ_ENCRYPT, \ + read_recv_state, NULL, UINT_TO_POINTER(idx)), \ + BT_AUDIO_CCC(recv_state_cfg_changed) BT_GATT_SERVICE_DEFINE(bass_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_BASS), - BT_GATT_CHARACTERISTIC(BT_UUID_BASS_CONTROL_POINT, - BT_GATT_CHRC_WRITE_WITHOUT_RESP | BT_GATT_CHRC_WRITE, - BT_GATT_PERM_WRITE_ENCRYPT, - NULL, write_control_point, NULL), + BT_AUDIO_CHRC(BT_UUID_BASS_CONTROL_POINT, + BT_GATT_CHRC_WRITE_WITHOUT_RESP | BT_GATT_CHRC_WRITE, + BT_GATT_PERM_WRITE_ENCRYPT, + NULL, write_control_point, NULL), RECEIVE_STATE_CHARACTERISTIC(0), #if CONFIG_BT_BASS_RECV_STATE_COUNT > 1 RECEIVE_STATE_CHARACTERISTIC(1), diff --git a/subsys/bluetooth/audio/csis.c b/subsys/bluetooth/audio/csis.c index 2e130a81221..93455c0f2db 100644 --- a/subsys/bluetooth/audio/csis.c +++ b/subsys/bluetooth/audio/csis.c @@ -20,6 +20,8 @@ #include #include #include + +#include "audio_internal.h" #include "csis_internal.h" #include "csis_crypto.h" #include "../host/conn_internal.h" @@ -298,7 +300,7 @@ static ssize_t read_set_sirk(struct bt_conn *conn, { struct bt_csis_set_sirk enc_sirk; struct bt_csis_set_sirk *sirk; - struct bt_csis *csis = attr->user_data; + struct bt_csis *csis = BT_AUDIO_CHRC_USER_DATA(attr); if (csis->srv.cb != NULL && csis->srv.cb->sirk_read_req != NULL) { uint8_t cb_rsp; @@ -354,7 +356,7 @@ static ssize_t read_set_size(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { - struct bt_csis *csis = attr->user_data; + struct bt_csis *csis = BT_AUDIO_CHRC_USER_DATA(attr); BT_DBG("%u", csis->srv.set_size); @@ -373,7 +375,7 @@ static ssize_t read_set_lock(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { - struct bt_csis *csis = attr->user_data; + struct bt_csis *csis = BT_AUDIO_CHRC_USER_DATA(attr); BT_DBG("%u", csis->srv.set_lock); @@ -389,7 +391,7 @@ static ssize_t write_set_lock(struct bt_conn *conn, { uint8_t val; bool notify; - struct bt_csis *csis = attr->user_data; + struct bt_csis *csis = BT_AUDIO_CHRC_USER_DATA(attr); if (offset != 0) { return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET); @@ -460,7 +462,7 @@ static void set_lock_cfg_changed(const struct bt_gatt_attr *attr, static ssize_t read_rank(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { - struct bt_csis *csis = attr->user_data; + struct bt_csis *csis = BT_AUDIO_CHRC_USER_DATA(attr); BT_DBG("%u", csis->srv.rank); @@ -792,31 +794,25 @@ static void adv_connected(struct bt_le_ext_adv *adv, #define BT_CSIS_SERVICE_DEFINITION(_csis) {\ BT_GATT_PRIMARY_SERVICE(BT_UUID_CSIS), \ - BT_GATT_CHARACTERISTIC(BT_UUID_CSIS_SET_SIRK, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_set_sirk, NULL, &_csis), \ - BT_GATT_CCC(set_sirk_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), \ - BT_GATT_CHARACTERISTIC(BT_UUID_CSIS_SET_SIZE, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_set_size, NULL, &_csis), \ - BT_GATT_CCC(set_size_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), \ - BT_GATT_CHARACTERISTIC(BT_UUID_CSIS_SET_LOCK, \ - BT_GATT_CHRC_READ | \ - BT_GATT_CHRC_NOTIFY | \ - BT_GATT_CHRC_WRITE, \ - BT_GATT_PERM_READ_ENCRYPT | \ - BT_GATT_PERM_WRITE_ENCRYPT, \ - read_set_lock, write_set_lock, &_csis), \ - BT_GATT_CCC(set_lock_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), \ - BT_GATT_CHARACTERISTIC(BT_UUID_CSIS_RANK, \ - BT_GATT_CHRC_READ, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_rank, NULL, &_csis) \ + BT_AUDIO_CHRC(BT_UUID_CSIS_SET_SIRK, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_set_sirk, NULL, &_csis), \ + BT_AUDIO_CCC(set_sirk_cfg_changed), \ + BT_AUDIO_CHRC(BT_UUID_CSIS_SET_SIZE, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_set_size, NULL, &_csis), \ + BT_AUDIO_CCC(set_size_cfg_changed), \ + BT_AUDIO_CHRC(BT_UUID_CSIS_SET_LOCK, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY | BT_GATT_CHRC_WRITE, \ + BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT, \ + read_set_lock, write_set_lock, &_csis), \ + BT_AUDIO_CCC(set_lock_cfg_changed), \ + BT_AUDIO_CHRC(BT_UUID_CSIS_RANK, \ + BT_GATT_CHRC_READ, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_rank, NULL, &_csis) \ } BT_GATT_SERVICE_INSTANCE_DEFINE(csis_service_list, csis_insts, diff --git a/subsys/bluetooth/audio/has.c b/subsys/bluetooth/audio/has.c index dc0ee529713..c548483582c 100644 --- a/subsys/bluetooth/audio/has.c +++ b/subsys/bluetooth/audio/has.c @@ -18,6 +18,7 @@ #include "../bluetooth/host/conn_internal.h" #include "../bluetooth/host/hci_core.h" +#include "audio_internal.h" #include "has_internal.h" #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HAS) @@ -71,21 +72,25 @@ static ssize_t read_features(struct bt_conn *conn, const struct bt_gatt_attr *at /* Hearing Access Service GATT Attributes */ BT_GATT_SERVICE_DEFINE(has_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_HAS), - BT_GATT_CHARACTERISTIC(BT_UUID_HAS_HEARING_AID_FEATURES, BT_GATT_CHRC_READ, - BT_GATT_PERM_READ_ENCRYPT, read_features, NULL, NULL), + BT_AUDIO_CHRC(BT_UUID_HAS_HEARING_AID_FEATURES, + BT_GATT_CHRC_READ, + BT_GATT_PERM_READ_ENCRYPT, + read_features, NULL, NULL), #if defined(CONFIG_BT_HAS_PRESET_SUPPORT) - BT_GATT_CHARACTERISTIC(BT_UUID_HAS_PRESET_CONTROL_POINT, + BT_AUDIO_CHRC(BT_UUID_HAS_PRESET_CONTROL_POINT, #if defined(CONFIG_BT_EATT) - BT_GATT_CHRC_WRITE | BT_GATT_CHRC_INDICATE | BT_GATT_CHRC_NOTIFY, + BT_GATT_CHRC_WRITE | BT_GATT_CHRC_INDICATE | BT_GATT_CHRC_NOTIFY, #else - BT_GATT_CHRC_WRITE | BT_GATT_CHRC_INDICATE, + BT_GATT_CHRC_WRITE | BT_GATT_CHRC_INDICATE, #endif /* CONFIG_BT_EATT */ - BT_GATT_PERM_WRITE_ENCRYPT, NULL, write_control_point, NULL), - BT_GATT_CCC(ccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), - BT_GATT_CHARACTERISTIC(BT_UUID_HAS_ACTIVE_PRESET_INDEX, - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ_ENCRYPT, - read_active_preset_index, NULL, NULL), - BT_GATT_CCC(ccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), + BT_GATT_PERM_WRITE_ENCRYPT, + NULL, write_control_point, NULL), + BT_AUDIO_CCC(ccc_cfg_changed), + BT_AUDIO_CHRC(BT_UUID_HAS_ACTIVE_PRESET_INDEX, + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, + BT_GATT_PERM_READ_ENCRYPT, + read_active_preset_index, NULL, NULL), + BT_AUDIO_CCC(ccc_cfg_changed), #endif /* CONFIG_BT_HAS_PRESET_SUPPORT */ ); diff --git a/subsys/bluetooth/audio/mcs.c b/subsys/bluetooth/audio/mcs.c index 551f5460d48..0638f8672ab 100644 --- a/subsys/bluetooth/audio/mcs.c +++ b/subsys/bluetooth/audio/mcs.c @@ -23,6 +23,7 @@ #include #include +#include "audio_internal.h" #include "media_proxy_internal.h" #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_MCS) @@ -620,62 +621,49 @@ static ssize_t read_content_ctrl_id(struct bt_conn *conn, /* Defines for OTS-dependent characteristics - empty if no OTS */ #ifdef CONFIG_BT_OTS #define ICON_OBJ_ID_CHARACTERISTIC_IF_OTS \ - BT_GATT_CHARACTERISTIC(BT_UUID_MCS_ICON_OBJ_ID, \ - BT_GATT_CHRC_READ, BT_GATT_PERM_READ_ENCRYPT, \ - read_icon_id, NULL, NULL), + BT_AUDIO_CHRC(BT_UUID_MCS_ICON_OBJ_ID, \ + BT_GATT_CHRC_READ, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_icon_id, NULL, NULL), #define SEGMENTS_TRACK_GROUP_ID_CHARACTERISTICS_IF_OTS \ - BT_GATT_CHARACTERISTIC(BT_UUID_MCS_TRACK_SEGMENTS_OBJ_ID, \ - BT_GATT_CHRC_READ, BT_GATT_PERM_READ_ENCRYPT, \ - read_track_segments_id, NULL, NULL), \ - BT_GATT_CHARACTERISTIC(BT_UUID_MCS_CURRENT_TRACK_OBJ_ID, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | \ - BT_GATT_CHRC_WRITE_WITHOUT_RESP | \ - BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT | \ - BT_GATT_PERM_WRITE_ENCRYPT, \ - read_current_track_id, write_current_track_id, \ - NULL), \ - BT_GATT_CCC(current_track_id_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), \ - BT_GATT_CHARACTERISTIC(BT_UUID_MCS_NEXT_TRACK_OBJ_ID, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | \ - BT_GATT_CHRC_WRITE_WITHOUT_RESP | \ - BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT | \ - BT_GATT_PERM_WRITE_ENCRYPT, \ - read_next_track_id, write_next_track_id, NULL), \ - BT_GATT_CCC(next_track_id_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), \ - BT_GATT_CHARACTERISTIC(BT_UUID_MCS_PARENT_GROUP_OBJ_ID, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_parent_group_id, NULL, NULL), \ - BT_GATT_CCC(parent_group_id_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), \ - BT_GATT_CHARACTERISTIC(BT_UUID_MCS_CURRENT_GROUP_OBJ_ID, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | \ - BT_GATT_CHRC_WRITE_WITHOUT_RESP | \ - BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT | \ - BT_GATT_PERM_WRITE_ENCRYPT, \ - read_current_group_id, write_current_group_id, NULL), \ - BT_GATT_CCC(current_group_id_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), + BT_AUDIO_CHRC(BT_UUID_MCS_TRACK_SEGMENTS_OBJ_ID, \ + BT_GATT_CHRC_READ, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_track_segments_id, NULL, NULL), \ + BT_AUDIO_CHRC(BT_UUID_MCS_CURRENT_TRACK_OBJ_ID, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | \ + BT_GATT_CHRC_WRITE_WITHOUT_RESP | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT, \ + read_current_track_id, write_current_track_id, NULL), \ + BT_AUDIO_CCC(current_track_id_cfg_changed), \ + BT_AUDIO_CHRC(BT_UUID_MCS_NEXT_TRACK_OBJ_ID, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | \ + BT_GATT_CHRC_WRITE_WITHOUT_RESP | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT, \ + read_next_track_id, write_next_track_id, NULL), \ + BT_AUDIO_CCC(next_track_id_cfg_changed), \ + BT_AUDIO_CHRC(BT_UUID_MCS_PARENT_GROUP_OBJ_ID, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_parent_group_id, NULL, NULL), \ + BT_AUDIO_CCC(parent_group_id_cfg_changed), \ + BT_AUDIO_CHRC(BT_UUID_MCS_CURRENT_GROUP_OBJ_ID, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | \ + BT_GATT_CHRC_WRITE_WITHOUT_RESP | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT, \ + read_current_group_id, write_current_group_id, NULL), \ + BT_AUDIO_CCC(current_group_id_cfg_changed), #define SEARCH_CHARACTERISTICS_IF_OTS \ - BT_GATT_CHARACTERISTIC(BT_UUID_MCS_SEARCH_CONTROL_POINT, \ - BT_GATT_CHRC_WRITE | \ - BT_GATT_CHRC_WRITE_WITHOUT_RESP | \ - BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_WRITE_ENCRYPT, \ - NULL, write_search_control_point, NULL), \ - BT_GATT_CCC(search_control_point_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), \ - BT_GATT_CHARACTERISTIC(BT_UUID_MCS_SEARCH_RESULTS_OBJ_ID, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_search_results_id, NULL, NULL), \ - BT_GATT_CCC(search_results_id_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), + BT_AUDIO_CHRC(BT_UUID_MCS_SEARCH_CONTROL_POINT, \ + BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_WRITE_ENCRYPT, \ + NULL, write_search_control_point, NULL), \ + BT_AUDIO_CCC(search_control_point_cfg_changed), \ + BT_AUDIO_CHRC(BT_UUID_MCS_SEARCH_RESULTS_OBJ_ID, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_search_results_id, NULL, NULL), \ + BT_AUDIO_CCC(search_results_id_cfg_changed), #else #define ICON_OBJ_ID_CHARACTERISTIC_IF_OTS @@ -687,97 +675,79 @@ static ssize_t read_content_ctrl_id(struct bt_conn *conn, #define BT_MCS_SERVICE_DEFINITION \ BT_GATT_PRIMARY_SERVICE(BT_UUID_GMCS), \ BT_GATT_INCLUDE_SERVICE(NULL), /* To be overwritten */ \ - BT_GATT_CHARACTERISTIC(BT_UUID_MCS_PLAYER_NAME, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_player_name, NULL, NULL), \ - BT_GATT_CCC(player_name_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), \ + BT_AUDIO_CHRC(BT_UUID_MCS_PLAYER_NAME, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_player_name, NULL, NULL), \ + BT_AUDIO_CCC(player_name_cfg_changed), \ ICON_OBJ_ID_CHARACTERISTIC_IF_OTS \ - BT_GATT_CHARACTERISTIC(BT_UUID_MCS_ICON_URL, \ - BT_GATT_CHRC_READ, BT_GATT_PERM_READ_ENCRYPT, \ - read_icon_url, NULL, NULL), \ - BT_GATT_CHARACTERISTIC(BT_UUID_MCS_TRACK_CHANGED, \ - BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_NONE, \ - NULL, NULL, NULL), \ - BT_GATT_CCC(track_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), \ - BT_GATT_CHARACTERISTIC(BT_UUID_MCS_TRACK_TITLE, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_track_title, NULL, NULL), \ - BT_GATT_CCC(track_title_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), \ - BT_GATT_CHARACTERISTIC(BT_UUID_MCS_TRACK_DURATION, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_track_duration, NULL, NULL), \ - BT_GATT_CCC(track_duration_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), \ - BT_GATT_CHARACTERISTIC(BT_UUID_MCS_TRACK_POSITION, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | \ - BT_GATT_CHRC_WRITE_WITHOUT_RESP | \ - BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT | \ - BT_GATT_PERM_WRITE_ENCRYPT, \ - read_track_position, \ - write_track_position, NULL), \ - BT_GATT_CCC(track_position_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), \ - BT_GATT_CHARACTERISTIC(BT_UUID_MCS_PLAYBACK_SPEED, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | \ - BT_GATT_CHRC_WRITE_WITHOUT_RESP | \ - BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT | \ - BT_GATT_PERM_WRITE_ENCRYPT, \ - read_playback_speed, write_playback_speed, \ - NULL), \ - BT_GATT_CCC(playback_speed_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), \ - BT_GATT_CHARACTERISTIC(BT_UUID_MCS_SEEKING_SPEED, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_seeking_speed, NULL, NULL), \ - BT_GATT_CCC(seeking_speed_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), \ + BT_AUDIO_CHRC(BT_UUID_MCS_ICON_URL, \ + BT_GATT_CHRC_READ, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_icon_url, NULL, NULL), \ + BT_AUDIO_CHRC(BT_UUID_MCS_TRACK_CHANGED, \ + BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_NONE, \ + NULL, NULL, NULL), \ + BT_AUDIO_CCC(track_cfg_changed), \ + BT_AUDIO_CHRC(BT_UUID_MCS_TRACK_TITLE, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_track_title, NULL, NULL), \ + BT_AUDIO_CCC(track_title_cfg_changed), \ + BT_AUDIO_CHRC(BT_UUID_MCS_TRACK_DURATION, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_track_duration, NULL, NULL), \ + BT_AUDIO_CCC(track_duration_cfg_changed), \ + BT_AUDIO_CHRC(BT_UUID_MCS_TRACK_POSITION, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | \ + BT_GATT_CHRC_WRITE_WITHOUT_RESP | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT, \ + read_track_position, write_track_position, NULL), \ + BT_AUDIO_CCC(track_position_cfg_changed), \ + BT_AUDIO_CHRC(BT_UUID_MCS_PLAYBACK_SPEED, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | \ + BT_GATT_CHRC_WRITE_WITHOUT_RESP | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT, \ + read_playback_speed, write_playback_speed, NULL), \ + BT_AUDIO_CCC(playback_speed_cfg_changed), \ + BT_AUDIO_CHRC(BT_UUID_MCS_SEEKING_SPEED, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_seeking_speed, NULL, NULL), \ + BT_AUDIO_CCC(seeking_speed_cfg_changed), \ SEGMENTS_TRACK_GROUP_ID_CHARACTERISTICS_IF_OTS \ - BT_GATT_CHARACTERISTIC(BT_UUID_MCS_PLAYING_ORDER, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | \ - BT_GATT_CHRC_WRITE_WITHOUT_RESP | \ - BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT | \ - BT_GATT_PERM_WRITE_ENCRYPT, \ - read_playing_order, write_playing_order, NULL), \ - BT_GATT_CCC(playing_order_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), \ - BT_GATT_CHARACTERISTIC(BT_UUID_MCS_PLAYING_ORDERS, \ - BT_GATT_CHRC_READ, BT_GATT_PERM_READ_ENCRYPT, \ - read_playing_orders_supported, NULL, NULL), \ - BT_GATT_CHARACTERISTIC(BT_UUID_MCS_MEDIA_STATE, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_media_state, NULL, NULL), \ - BT_GATT_CCC(media_state_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), \ - BT_GATT_CHARACTERISTIC(BT_UUID_MCS_MEDIA_CONTROL_POINT, \ - BT_GATT_CHRC_WRITE | \ - BT_GATT_CHRC_WRITE_WITHOUT_RESP | \ - BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_WRITE_ENCRYPT, \ - NULL, write_control_point, NULL), \ - BT_GATT_CCC(control_point_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), \ - BT_GATT_CHARACTERISTIC(BT_UUID_MCS_MEDIA_CONTROL_OPCODES, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_opcodes_supported, NULL, NULL), \ - BT_GATT_CCC(opcodes_supported_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), \ + BT_AUDIO_CHRC(BT_UUID_MCS_PLAYING_ORDER, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | \ + BT_GATT_CHRC_WRITE_WITHOUT_RESP | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT, \ + read_playing_order, write_playing_order, NULL), \ + BT_AUDIO_CCC(playing_order_cfg_changed), \ + BT_AUDIO_CHRC(BT_UUID_MCS_PLAYING_ORDERS, \ + BT_GATT_CHRC_READ, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_playing_orders_supported, NULL, NULL), \ + BT_AUDIO_CHRC(BT_UUID_MCS_MEDIA_STATE, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_media_state, NULL, NULL), \ + BT_AUDIO_CCC(media_state_cfg_changed), \ + BT_AUDIO_CHRC(BT_UUID_MCS_MEDIA_CONTROL_POINT, \ + BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_WRITE_ENCRYPT, \ + NULL, write_control_point, NULL), \ + BT_AUDIO_CCC(control_point_cfg_changed), \ + BT_AUDIO_CHRC(BT_UUID_MCS_MEDIA_CONTROL_OPCODES, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_opcodes_supported, NULL, NULL), \ + BT_AUDIO_CCC(opcodes_supported_cfg_changed), \ SEARCH_CHARACTERISTICS_IF_OTS \ - BT_GATT_CHARACTERISTIC(BT_UUID_CCID, \ - BT_GATT_CHRC_READ, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_content_ctrl_id, NULL, NULL) + BT_AUDIO_CHRC(BT_UUID_CCID, \ + BT_GATT_CHRC_READ, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_content_ctrl_id, NULL, NULL) static struct bt_gatt_attr svc_attrs[] = { BT_MCS_SERVICE_DEFINITION }; static struct bt_gatt_service mcs; diff --git a/subsys/bluetooth/audio/micp_mic_dev.c b/subsys/bluetooth/audio/micp_mic_dev.c index a132c32edc6..3b882b4d744 100644 --- a/subsys/bluetooth/audio/micp_mic_dev.c +++ b/subsys/bluetooth/audio/micp_mic_dev.c @@ -19,6 +19,8 @@ #include #include +#include "audio_internal.h" + #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_MICP_MIC_DEV) #define LOG_MODULE_NAME bt_micp #include "common/log.h" @@ -94,12 +96,11 @@ static ssize_t write_mute(struct bt_conn *conn, const struct bt_gatt_attr *attr, #define BT_MICP_SERVICE_DEFINITION \ BT_GATT_PRIMARY_SERVICE(BT_UUID_MICS), \ AICS_INCLUDES(CONFIG_BT_MICP_MIC_DEV_AICS_INSTANCE_COUNT) \ - BT_GATT_CHARACTERISTIC(BT_UUID_MICS_MUTE, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT, \ - read_mute, write_mute, NULL), \ - BT_GATT_CCC(mute_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT) + BT_AUDIO_CHRC(BT_UUID_MICS_MUTE, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT, \ + read_mute, write_mute, NULL), \ + BT_AUDIO_CCC(mute_cfg_changed) #define MICS_ATTR_COUNT \ ARRAY_SIZE(((struct bt_gatt_attr []){ BT_MICP_SERVICE_DEFINITION })) diff --git a/subsys/bluetooth/audio/pacs.c b/subsys/bluetooth/audio/pacs.c index 05264b8daa2..aea7e3963fc 100644 --- a/subsys/bluetooth/audio/pacs.c +++ b/subsys/bluetooth/audio/pacs.c @@ -27,6 +27,7 @@ #define LOG_MODULE_NAME bt_pacs #include "common/log.h" +#include "audio_internal.h" #include "pacs_internal.h" #include "unicast_server.h" @@ -437,63 +438,53 @@ static void src_loc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value) BT_GATT_SERVICE_DEFINE(pacs_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_PACS), #if defined(CONFIG_BT_PAC_SNK) - BT_GATT_CHARACTERISTIC(BT_UUID_PACS_SNK, - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, - BT_GATT_PERM_READ_ENCRYPT, - snk_read, NULL, NULL), - BT_GATT_CCC(snk_cfg_changed, - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), + BT_AUDIO_CHRC(BT_UUID_PACS_SNK, + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, + BT_GATT_PERM_READ_ENCRYPT, + snk_read, NULL, NULL), + BT_AUDIO_CCC(snk_cfg_changed), #if defined(CONFIG_BT_PAC_SNK_LOC_WRITEABLE) - BT_GATT_CHARACTERISTIC(BT_UUID_PACS_SNK_LOC, - BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | - BT_GATT_CHRC_NOTIFY, - BT_GATT_PERM_READ_ENCRYPT | - BT_GATT_PERM_WRITE_ENCRYPT, - snk_loc_read, snk_loc_write, NULL), + BT_AUDIO_CHRC(BT_UUID_PACS_SNK_LOC, + BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | BT_GATT_CHRC_NOTIFY, + BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT, + snk_loc_read, snk_loc_write, NULL), #elif defined(CONFIG_BT_PAC_SNK_LOC) - BT_GATT_CHARACTERISTIC(BT_UUID_PACS_SNK_LOC, - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, - BT_GATT_PERM_READ_ENCRYPT, - snk_loc_read, NULL, NULL), + BT_AUDIO_CHRC(BT_UUID_PACS_SNK_LOC, + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, + BT_GATT_PERM_READ_ENCRYPT, + snk_loc_read, NULL, NULL), #endif /* CONFIG_BT_PAC_SNK_LOC_WRITEABLE */ - BT_GATT_CCC(snk_loc_cfg_changed, - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), + BT_AUDIO_CCC(snk_loc_cfg_changed), #endif /* CONFIG_BT_PAC_SNK */ #if defined(CONFIG_BT_PAC_SRC) - BT_GATT_CHARACTERISTIC(BT_UUID_PACS_SRC, - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, - BT_GATT_PERM_READ_ENCRYPT, - src_read, NULL, NULL), - BT_GATT_CCC(src_cfg_changed, - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), + BT_AUDIO_CHRC(BT_UUID_PACS_SRC, + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, + BT_GATT_PERM_READ_ENCRYPT, + src_read, NULL, NULL), + BT_AUDIO_CCC(src_cfg_changed), #if defined(CONFIG_BT_PAC_SRC_LOC_WRITEABLE) - BT_GATT_CHARACTERISTIC(BT_UUID_PACS_SRC_LOC, - BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | - BT_GATT_CHRC_NOTIFY, - BT_GATT_PERM_READ_ENCRYPT | - BT_GATT_PERM_WRITE_ENCRYPT, - src_loc_read, src_loc_write, NULL), + BT_AUDIO_CHRC(BT_UUID_PACS_SRC_LOC, + BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | BT_GATT_CHRC_NOTIFY, + BT_GATT_PERM_READ_ENCRYPT BT_GATT_PERM_WRITE_ENCRYPT, + src_loc_read, src_loc_write, NULL), #elif defined(CONFIG_BT_PAC_SRC_LOC) - BT_GATT_CHARACTERISTIC(BT_UUID_PACS_SRC_LOC, - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, - BT_GATT_PERM_READ_ENCRYPT, - src_loc_read, NULL, NULL), + BT_AUDIO_CHRC(BT_UUID_PACS_SRC_LOC, + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, + BT_GATT_PERM_READ_ENCRYPT, + src_loc_read, NULL, NULL), #endif /* CONFIG_BT_PAC_SRC_LOC_WRITEABLE */ - BT_GATT_CCC(src_loc_cfg_changed, - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), + BT_AUDIO_CCC(src_loc_cfg_changed), #endif /* CONFIG_BT_PAC_SRC */ - BT_GATT_CHARACTERISTIC(BT_UUID_PACS_AVAILABLE_CONTEXT, - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, - BT_GATT_PERM_READ_ENCRYPT, - available_contexts_read, NULL, NULL), - BT_GATT_CCC(available_context_cfg_changed, - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), - BT_GATT_CHARACTERISTIC(BT_UUID_PACS_SUPPORTED_CONTEXT, - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, - BT_GATT_PERM_READ_ENCRYPT, - supported_context_read, NULL, NULL), - BT_GATT_CCC(supported_context_cfg_changed, - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT) + BT_AUDIO_CHRC(BT_UUID_PACS_AVAILABLE_CONTEXT, + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, + BT_GATT_PERM_READ_ENCRYPT, + available_contexts_read, NULL, NULL), + BT_AUDIO_CCC(available_context_cfg_changed), + BT_AUDIO_CHRC(BT_UUID_PACS_SUPPORTED_CONTEXT, + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, + BT_GATT_PERM_READ_ENCRYPT, + supported_context_read, NULL, NULL), + BT_AUDIO_CCC(supported_context_cfg_changed) ); static struct k_work_delayable *bt_pacs_get_work(enum bt_audio_dir dir) diff --git a/subsys/bluetooth/audio/tbs.c b/subsys/bluetooth/audio/tbs.c index ce1c4bac90f..c028047e1f3 100644 --- a/subsys/bluetooth/audio/tbs.c +++ b/subsys/bluetooth/audio/tbs.c @@ -17,6 +17,7 @@ #include #include +#include "audio_internal.h" #include "tbs_internal.h" #include "ccid_internal.h" @@ -25,6 +26,8 @@ #include "common/log.h" #define BT_TBS_VALID_STATUS_FLAGS(val) ((val) <= (BIT(0) | BIT(1))) +#define IS_GTBS_CHRC(_attr) \ + IS_ENABLED(CONFIG_BT_GTBS) && BT_AUDIO_CHRC_USER_DATA(_attr) == >bs_inst /* TODO: Have tbs_service_inst include gtbs_service_inst and use CONTAINER_OF * to get a specific TBS instance from a GTBS pointer. @@ -500,11 +503,11 @@ static ssize_t read_provider_name(struct bt_conn *conn, { const char *provider_name; - if (IS_ENABLED(CONFIG_BT_GTBS) && attr->user_data == >bs_inst) { + if (IS_GTBS_CHRC(attr)) { provider_name = gtbs_inst.provider_name; BT_DBG("GTBS: Provider name %s", provider_name); } else { - const struct tbs_service_inst *inst = (struct tbs_service_inst *)attr->user_data; + const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr); provider_name = inst->provider_name; BT_DBG("Index %u, Provider name %s", @@ -533,11 +536,11 @@ static ssize_t read_uci(struct bt_conn *conn, const struct bt_gatt_attr *attr, { const char *uci; - if (IS_ENABLED(CONFIG_BT_GTBS) && attr->user_data == >bs_inst) { + if (IS_GTBS_CHRC(attr)) { uci = gtbs_inst.uci; BT_DBG("GTBS: UCI %s", uci); } else { - const struct tbs_service_inst *inst = (struct tbs_service_inst *)attr->user_data; + const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr); uci = inst->uci; BT_DBG("Index %u: UCI %s", inst->index, uci); @@ -553,11 +556,11 @@ static ssize_t read_technology(struct bt_conn *conn, { uint8_t technology; - if (IS_ENABLED(CONFIG_BT_GTBS) && attr->user_data == >bs_inst) { + if (IS_GTBS_CHRC(attr)) { technology = gtbs_inst.technology; BT_DBG("GTBS: Technology 0x%02X", technology); } else { - const struct tbs_service_inst *inst = (struct tbs_service_inst *)attr->user_data; + const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr); technology = inst->technology; BT_DBG("Index %u: Technology 0x%02X", inst->index, technology); @@ -585,7 +588,7 @@ static ssize_t read_uri_scheme_list(struct bt_conn *conn, { net_buf_simple_reset(&read_buf); - if (IS_ENABLED(CONFIG_BT_GTBS) && attr->user_data == >bs_inst) { + if (IS_GTBS_CHRC(attr)) { /* TODO: Make uri schemes unique */ for (size_t i = 0; i < ARRAY_SIZE(svc_insts); i++) { size_t uri_len = strlen(svc_insts[i].uri_scheme_list); @@ -604,7 +607,7 @@ static ssize_t read_uri_scheme_list(struct bt_conn *conn, read_buf.data[read_buf.len] = '\0'; BT_DBG("GTBS: URI scheme %s", read_buf.data); } else { - const struct tbs_service_inst *inst = (struct tbs_service_inst *)attr->user_data; + const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr); net_buf_simple_add_mem(&read_buf, inst->uri_scheme_list, strlen(inst->uri_scheme_list)); @@ -636,11 +639,11 @@ static ssize_t read_signal_strength(struct bt_conn *conn, { uint8_t signal_strength; - if (IS_ENABLED(CONFIG_BT_GTBS) && attr->user_data == >bs_inst) { + if (IS_GTBS_CHRC(attr)) { signal_strength = gtbs_inst.signal_strength; BT_DBG("GTBS: Signal strength 0x%02x", signal_strength); } else { - const struct tbs_service_inst *inst = (struct tbs_service_inst *)attr->user_data; + const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr); signal_strength = inst->signal_strength; BT_DBG("Index %u: Signal strength 0x%02x", @@ -674,12 +677,12 @@ static ssize_t read_signal_strength_interval(struct bt_conn *conn, return BT_GATT_ERR(BT_ATT_ERR_AUTHORIZATION); } - if (IS_ENABLED(CONFIG_BT_GTBS) && attr->user_data == >bs_inst) { + if (IS_GTBS_CHRC(attr)) { signal_strength_interval = gtbs_inst.signal_strength_interval; BT_DBG("GTBS: Signal strength interval 0x%02x", signal_strength_interval); } else { - const struct tbs_service_inst *inst = (struct tbs_service_inst *)attr->user_data; + const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr); signal_strength_interval = inst->signal_strength_interval; BT_DBG("Index %u: Signal strength interval 0x%02x", @@ -714,11 +717,11 @@ static ssize_t write_signal_strength_interval(struct bt_conn *conn, net_buf_simple_init_with_data(&net_buf, (void *)buf, len); signal_strength_interval = net_buf_simple_pull_u8(&net_buf); - if (IS_ENABLED(CONFIG_BT_GTBS) && attr->user_data == >bs_inst) { + if (IS_GTBS_CHRC(attr)) { gtbs_inst.signal_strength_interval = signal_strength_interval; BT_DBG("GTBS: 0x%02x", signal_strength_interval); } else { - struct tbs_service_inst *inst = (struct tbs_service_inst *)attr->user_data; + struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr); inst->signal_strength_interval = signal_strength_interval; BT_DBG("Index %u: 0x%02x", @@ -746,12 +749,12 @@ static ssize_t read_current_calls(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { - net_buf_put_current_calls(attr->user_data); + net_buf_put_current_calls(BT_AUDIO_CHRC_USER_DATA(attr)); - if (IS_ENABLED(CONFIG_BT_GTBS) && attr->user_data == >bs_inst) { + if (IS_GTBS_CHRC(attr)) { BT_DBG("GTBS"); } else { - const struct tbs_service_inst *inst = (struct tbs_service_inst *)attr->user_data; + const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr); BT_DBG("Index %u", inst->index); } @@ -770,11 +773,11 @@ static ssize_t read_ccid(struct bt_conn *conn, { uint8_t ccid; - if (IS_ENABLED(CONFIG_BT_GTBS) && attr->user_data == >bs_inst) { + if (IS_GTBS_CHRC(attr)) { ccid = gtbs_inst.ccid; BT_DBG("GTBS: CCID 0x%02X", ccid); } else { - const struct tbs_service_inst *inst = (struct tbs_service_inst *)attr->user_data; + const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr); ccid = inst->ccid; BT_DBG("Index %u: CCID 0x%02X", inst->index, ccid); @@ -790,11 +793,11 @@ static ssize_t read_status_flags(struct bt_conn *conn, { uint16_t status_flags; - if (IS_ENABLED(CONFIG_BT_GTBS) && attr->user_data == >bs_inst) { + if (IS_GTBS_CHRC(attr)) { status_flags = gtbs_inst.status_flags; BT_DBG("GTBS: status_flags 0x%04X", status_flags); } else { - const struct tbs_service_inst *inst = (struct tbs_service_inst *)attr->user_data; + const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr); status_flags = inst->status_flags; BT_DBG("Index %u: status_flags 0x%04X", @@ -825,13 +828,13 @@ static ssize_t read_incoming_uri(struct bt_conn *conn, const struct bt_tbs_in_uri *inc_call_target; size_t val_len; - if (IS_ENABLED(CONFIG_BT_GTBS) && attr->user_data == >bs_inst) { + if (IS_GTBS_CHRC(attr)) { inc_call_target = >bs_inst.incoming_uri; BT_DBG("GTBS: call index 0x%02X, URI %s", inc_call_target->call_index, inc_call_target->uri); } else { - const struct tbs_service_inst *inst = (struct tbs_service_inst *)attr->user_data; + const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr); inc_call_target = &inst->incoming_uri; BT_DBG("Index %u: call index 0x%02X, URI %s", @@ -868,12 +871,12 @@ static ssize_t read_call_state(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { - net_buf_put_call_state(attr->user_data); + net_buf_put_call_state(BT_AUDIO_CHRC_USER_DATA(attr)); - if (IS_ENABLED(CONFIG_BT_GTBS) && attr->user_data == >bs_inst) { + if (IS_GTBS_CHRC(attr)) { BT_DBG("GTBS"); } else { - const struct tbs_service_inst *inst = (struct tbs_service_inst *)attr->user_data; + const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr); BT_DBG("Index %u", inst->index); } @@ -1278,8 +1281,7 @@ static ssize_t write_call_cp(struct bt_conn *conn, const union bt_tbs_call_cp_t *ccp = (union bt_tbs_call_cp_t *)buf; uint8_t status; uint8_t call_index = 0; - const bool is_gtbs = IS_ENABLED(CONFIG_BT_GTBS) && - attr->user_data == >bs_inst; + const bool is_gtbs = IS_GTBS_CHRC(attr); if (!is_authorized(conn)) { return BT_GATT_ERR(BT_ATT_ERR_AUTHORIZATION); @@ -1297,7 +1299,8 @@ static ssize_t write_call_cp(struct bt_conn *conn, BT_DBG("GTBS: Processing the %s opcode", bt_tbs_opcode_str(ccp->opcode)); } else { - inst = (struct tbs_service_inst *)attr->user_data; + inst = BT_AUDIO_CHRC_USER_DATA(attr); + BT_DBG("Index %u: Processing the %s opcode", inst->index, bt_tbs_opcode_str(ccp->opcode)); } @@ -1485,11 +1488,11 @@ static ssize_t read_optional_opcodes(struct bt_conn *conn, { uint16_t optional_opcodes; - if (IS_ENABLED(CONFIG_BT_GTBS) && attr->user_data == >bs_inst) { + if (IS_GTBS_CHRC(attr)) { optional_opcodes = gtbs_inst.optional_opcodes; BT_DBG("GTBS: Supported opcodes 0x%02x", optional_opcodes); } else { - const struct tbs_service_inst *inst = (struct tbs_service_inst *)attr->user_data; + const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr); optional_opcodes = inst->optional_opcodes; BT_DBG("Index %u: Supported opcodes 0x%02x", @@ -1519,13 +1522,13 @@ static ssize_t read_friendly_name(struct bt_conn *conn, const struct bt_tbs_in_uri *friendly_name; size_t val_len; - if (IS_ENABLED(CONFIG_BT_GTBS) && attr->user_data == >bs_inst) { + if (IS_GTBS_CHRC(attr)) { friendly_name = >bs_inst.friendly_name; BT_DBG("GTBS: call index 0x%02X, URI %s", friendly_name->call_index, friendly_name->uri); } else { - const struct tbs_service_inst *inst = (struct tbs_service_inst *)attr->user_data; + const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr); friendly_name = &inst->friendly_name; BT_DBG("Index %u: call index 0x%02X, URI %s", @@ -1564,12 +1567,12 @@ static ssize_t read_incoming_call(struct bt_conn *conn, const struct bt_tbs_in_uri *remote_uri; size_t val_len; - if (IS_ENABLED(CONFIG_BT_GTBS) && attr->user_data == >bs_inst) { + if (IS_GTBS_CHRC(attr)) { remote_uri = >bs_inst.in_call; BT_DBG("GTBS: call index 0x%02X, URI %s", remote_uri->call_index, remote_uri->uri); } else { - const struct tbs_service_inst *inst = (struct tbs_service_inst *)attr->user_data; + const struct tbs_service_inst *inst = BT_AUDIO_CHRC_USER_DATA(attr); remote_uri = &inst->in_call; BT_DBG("Index %u: call index 0x%02X, URI %s", @@ -1602,128 +1605,112 @@ static void in_call_cfg_changed(const struct bt_gatt_attr *attr, } #define BT_TBS_CHR_PROVIDER_NAME(inst) \ - BT_GATT_CHARACTERISTIC(BT_UUID_TBS_PROVIDER_NAME, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_provider_name, NULL, inst), \ - BT_GATT_CCC(provider_name_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT) + BT_AUDIO_CHRC(BT_UUID_TBS_PROVIDER_NAME, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_provider_name, NULL, inst), \ + BT_AUDIO_CCC(provider_name_cfg_changed) #define BT_TBS_CHR_UCI(inst) \ - BT_GATT_CHARACTERISTIC(BT_UUID_TBS_UCI, \ - BT_GATT_CHRC_READ, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_uci, NULL, inst) + BT_AUDIO_CHRC(BT_UUID_TBS_UCI, \ + BT_GATT_CHRC_READ, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_uci, NULL, inst) #define BT_TBS_CHR_TECHNOLOGY(inst) \ - BT_GATT_CHARACTERISTIC(BT_UUID_TBS_TECHNOLOGY, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_technology, NULL, inst), \ - BT_GATT_CCC(technology_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT) + BT_AUDIO_CHRC(BT_UUID_TBS_TECHNOLOGY, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_technology, NULL, inst), \ + BT_AUDIO_CCC(technology_cfg_changed) #define BT_TBS_CHR_URI_LIST(inst) \ - BT_GATT_CHARACTERISTIC(BT_UUID_TBS_URI_LIST, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_uri_scheme_list, NULL, inst), \ - BT_GATT_CCC(uri_scheme_list_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT) + BT_AUDIO_CHRC(BT_UUID_TBS_URI_LIST, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_uri_scheme_list, NULL, inst), \ + BT_AUDIO_CCC(uri_scheme_list_cfg_changed) #define BT_TBS_CHR_SIGNAL_STRENGTH(inst) \ - BT_GATT_CHARACTERISTIC(BT_UUID_TBS_SIGNAL_STRENGTH, /* Optional */ \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_signal_strength, NULL, inst), \ - BT_GATT_CCC(signal_strength_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT) + BT_AUDIO_CHRC(BT_UUID_TBS_SIGNAL_STRENGTH, /* Optional */ \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_signal_strength, NULL, inst), \ + BT_AUDIO_CCC(signal_strength_cfg_changed) #define BT_TBS_CHR_SIGNAL_INTERVAL(inst) \ - BT_GATT_CHARACTERISTIC(BT_UUID_TBS_SIGNAL_INTERVAL, /* Conditional */ \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | \ - BT_GATT_CHRC_WRITE_WITHOUT_RESP, \ - BT_GATT_PERM_READ_ENCRYPT | \ - BT_GATT_PERM_WRITE_ENCRYPT, \ - read_signal_strength_interval, \ - write_signal_strength_interval, inst) + BT_AUDIO_CHRC(BT_UUID_TBS_SIGNAL_INTERVAL, /* Conditional */ \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP, \ + BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT, \ + read_signal_strength_interval, write_signal_strength_interval, inst) #define BT_TBS_CHR_CURRENT_CALLS(inst) \ - BT_GATT_CHARACTERISTIC(BT_UUID_TBS_LIST_CURRENT_CALLS, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_current_calls, NULL, inst), \ - BT_GATT_CCC(current_calls_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT) + BT_AUDIO_CHRC(BT_UUID_TBS_LIST_CURRENT_CALLS, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_current_calls, NULL, inst), \ + BT_AUDIO_CCC(current_calls_cfg_changed) #define BT_TBS_CHR_CCID(inst) \ - BT_GATT_CHARACTERISTIC(BT_UUID_CCID, \ - BT_GATT_CHRC_READ, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_ccid, NULL, inst) + BT_AUDIO_CHRC(BT_UUID_CCID, \ + BT_GATT_CHRC_READ, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_ccid, NULL, inst) #define BT_TBS_CHR_STATUS_FLAGS(inst) \ - BT_GATT_CHARACTERISTIC(BT_UUID_TBS_STATUS_FLAGS, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_status_flags, NULL, inst), \ - BT_GATT_CCC(status_flags_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT) + BT_AUDIO_CHRC(BT_UUID_TBS_STATUS_FLAGS, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_status_flags, NULL, inst), \ + BT_AUDIO_CCC(status_flags_cfg_changed) #define BT_TBS_CHR_INCOMING_URI(inst) \ - BT_GATT_CHARACTERISTIC(BT_UUID_TBS_INCOMING_URI, /* Optional */ \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_incoming_uri, NULL, inst), \ - BT_GATT_CCC(incoming_uri_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT) + BT_AUDIO_CHRC(BT_UUID_TBS_INCOMING_URI, /* Optional */ \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_incoming_uri, NULL, inst), \ + BT_AUDIO_CCC(incoming_uri_cfg_changed) #define BT_TBS_CHR_CALL_STATE(inst) \ - BT_GATT_CHARACTERISTIC(BT_UUID_TBS_CALL_STATE, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_call_state, NULL, inst), \ - BT_GATT_CCC(call_state_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT) + BT_AUDIO_CHRC(BT_UUID_TBS_CALL_STATE, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_call_state, NULL, inst), \ + BT_AUDIO_CCC(call_state_cfg_changed) #define BT_TBS_CHR_CONTROL_POINT(inst) \ - BT_GATT_CHARACTERISTIC(BT_UUID_TBS_CALL_CONTROL_POINT, \ - BT_GATT_CHRC_WRITE | BT_GATT_CHRC_NOTIFY | \ - BT_GATT_CHRC_WRITE_WITHOUT_RESP, \ - BT_GATT_PERM_WRITE_ENCRYPT, \ - NULL, write_call_cp, inst), \ - BT_GATT_CCC(call_cp_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT) + BT_AUDIO_CHRC(BT_UUID_TBS_CALL_CONTROL_POINT, \ + BT_GATT_CHRC_WRITE | BT_GATT_CHRC_NOTIFY | BT_GATT_CHRC_WRITE_WITHOUT_RESP, \ + BT_GATT_PERM_WRITE_ENCRYPT, \ + NULL, write_call_cp, inst), \ + BT_AUDIO_CCC(call_cp_cfg_changed) #define BT_TBS_CHR_OPTIONAL_OPCODES(inst) \ - BT_GATT_CHARACTERISTIC(BT_UUID_TBS_OPTIONAL_OPCODES, \ - BT_GATT_CHRC_READ, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_optional_opcodes, NULL, inst) \ + BT_AUDIO_CHRC(BT_UUID_TBS_OPTIONAL_OPCODES, \ + BT_GATT_CHRC_READ, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_optional_opcodes, NULL, inst) \ #define BT_TBS_CHR_TERMINATE_REASON(inst) \ - BT_GATT_CHARACTERISTIC(BT_UUID_TBS_TERMINATE_REASON, \ - BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - NULL, NULL, inst), \ - BT_GATT_CCC(terminate_reason_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT) + BT_AUDIO_CHRC(BT_UUID_TBS_TERMINATE_REASON, \ + BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + NULL, NULL, inst), \ + BT_AUDIO_CCC(terminate_reason_cfg_changed) #define BT_TBS_CHR_INCOMING_CALL(inst) \ - BT_GATT_CHARACTERISTIC(BT_UUID_TBS_INCOMING_CALL, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_incoming_call, NULL, inst), \ - BT_GATT_CCC(in_call_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT) + BT_AUDIO_CHRC(BT_UUID_TBS_INCOMING_CALL, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_incoming_call, NULL, inst), \ + BT_AUDIO_CCC(in_call_cfg_changed) #define BT_TBS_CHR_FRIENDLY_NAME(inst) \ - BT_GATT_CHARACTERISTIC(BT_UUID_TBS_FRIENDLY_NAME, /* Optional */ \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_friendly_name, NULL, inst), \ - BT_GATT_CCC(friendly_name_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT) + BT_AUDIO_CHRC(BT_UUID_TBS_FRIENDLY_NAME, /* Optional */ \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_friendly_name, NULL, inst), \ + BT_AUDIO_CCC(friendly_name_cfg_changed) #define BT_TBS_SERVICE_DEFINITION(inst) {\ BT_GATT_PRIMARY_SERVICE(BT_UUID_TBS), \ diff --git a/subsys/bluetooth/audio/vcs.c b/subsys/bluetooth/audio/vcs.c index ce87b08f9cd..77c56d219e8 100644 --- a/subsys/bluetooth/audio/vcs.c +++ b/subsys/bluetooth/audio/vcs.c @@ -20,6 +20,7 @@ #include #include +#include "audio_internal.h" #include "vcs_internal.h" #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_VCS) @@ -249,22 +250,20 @@ static ssize_t read_flags(struct bt_conn *conn, const struct bt_gatt_attr *attr, BT_GATT_PRIMARY_SERVICE(BT_UUID_VCS), \ VOCS_INCLUDES(CONFIG_BT_VCS_VOCS_INSTANCE_COUNT) \ AICS_INCLUDES(CONFIG_BT_VCS_AICS_INSTANCE_COUNT) \ - BT_GATT_CHARACTERISTIC(BT_UUID_VCS_STATE, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_vol_state, NULL, NULL), \ - BT_GATT_CCC(volume_state_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), \ - BT_GATT_CHARACTERISTIC(BT_UUID_VCS_CONTROL, \ - BT_GATT_CHRC_WRITE, \ - BT_GATT_PERM_WRITE_ENCRYPT, \ - NULL, write_vcs_control, NULL), \ - BT_GATT_CHARACTERISTIC(BT_UUID_VCS_FLAGS, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_flags, NULL, NULL), \ - BT_GATT_CCC(flags_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT) + BT_AUDIO_CHRC(BT_UUID_VCS_STATE, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_vol_state, NULL, NULL), \ + BT_AUDIO_CCC(volume_state_cfg_changed), \ + BT_AUDIO_CHRC(BT_UUID_VCS_CONTROL, \ + BT_GATT_CHRC_WRITE, \ + BT_GATT_PERM_WRITE_ENCRYPT, \ + NULL, write_vcs_control, NULL), \ + BT_AUDIO_CHRC(BT_UUID_VCS_FLAGS, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_flags, NULL, NULL), \ + BT_AUDIO_CCC(flags_cfg_changed) static struct bt_gatt_attr vcs_attrs[] = { BT_VCS_SERVICE_DEFINITION }; static struct bt_gatt_service vcs_svc; diff --git a/subsys/bluetooth/audio/vocs.c b/subsys/bluetooth/audio/vocs.c index e00ef88ede6..c0bd977de18 100644 --- a/subsys/bluetooth/audio/vocs.c +++ b/subsys/bluetooth/audio/vocs.c @@ -17,6 +17,7 @@ #include #include +#include "audio_internal.h" #include "vocs_internal.h" #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_VOCS) @@ -34,7 +35,7 @@ static void offset_state_cfg_changed(const struct bt_gatt_attr *attr, uint16_t v static ssize_t read_offset_state(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { - struct bt_vocs *inst = attr->user_data; + struct bt_vocs *inst = BT_AUDIO_CHRC_USER_DATA(attr); BT_DBG("offset %d, counter %u", inst->srv.state.offset, inst->srv.state.change_counter); return bt_gatt_attr_read(conn, attr, buf, len, offset, &inst->srv.state, @@ -51,7 +52,7 @@ static void location_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value static ssize_t write_location(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, uint16_t len, uint16_t offset, uint8_t flags) { - struct bt_vocs *inst = attr->user_data; + struct bt_vocs *inst = BT_AUDIO_CHRC_USER_DATA(attr); uint32_t old_location = inst->srv.location; if (offset) { @@ -83,7 +84,7 @@ static ssize_t write_location(struct bt_conn *conn, const struct bt_gatt_attr *a static ssize_t read_location(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { - struct bt_vocs *inst = attr->user_data; + struct bt_vocs *inst = BT_AUDIO_CHRC_USER_DATA(attr); BT_DBG("0x%08x", inst->srv.location); return bt_gatt_attr_read(conn, attr, buf, len, offset, &inst->srv.location, @@ -94,7 +95,7 @@ static ssize_t read_location(struct bt_conn *conn, const struct bt_gatt_attr *at static ssize_t write_vocs_control(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, uint16_t len, uint16_t offset, uint8_t flags) { - struct bt_vocs *inst = attr->user_data; + struct bt_vocs *inst = BT_AUDIO_CHRC_USER_DATA(attr); const struct bt_vocs_control *cp = buf; bool notify = false; @@ -166,7 +167,7 @@ static void output_desc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t va static ssize_t write_output_desc(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, uint16_t len, uint16_t offset, uint8_t flags) { - struct bt_vocs *inst = attr->user_data; + struct bt_vocs *inst = BT_AUDIO_CHRC_USER_DATA(attr); if (offset) { return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET); @@ -198,11 +199,34 @@ static ssize_t write_output_desc(struct bt_conn *conn, const struct bt_gatt_attr return len; } +static int vocs_write(struct bt_vocs *inst, + ssize_t (*write)(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + const void *buf, uint16_t len, + uint16_t offset, uint8_t flags), + const void *buf, uint16_t len) +{ + struct bt_audio_attr_user_data user_data = { + .user_data = inst, + }; + struct bt_gatt_attr attr = { + .user_data = &user_data, + }; + int err; + + err = write(NULL, &attr, buf, len, 0, 0); + if (err < 0) { + return err; + } + + return 0; +} + #if defined(CONFIG_BT_VOCS) static ssize_t read_output_desc(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { - struct bt_vocs *inst = attr->user_data; + struct bt_vocs *inst = BT_AUDIO_CHRC_USER_DATA(attr); BT_DBG("%s", inst->srv.output_desc); return bt_gatt_attr_read(conn, attr, buf, len, offset, &inst->srv.output_desc, @@ -211,28 +235,25 @@ static ssize_t read_output_desc(struct bt_conn *conn, const struct bt_gatt_attr #define BT_VOCS_SERVICE_DEFINITION(_vocs) { \ BT_GATT_SECONDARY_SERVICE(BT_UUID_VOCS), \ - BT_GATT_CHARACTERISTIC(BT_UUID_VOCS_STATE, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_offset_state, NULL, &_vocs), \ - BT_GATT_CCC(offset_state_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), \ - BT_GATT_CHARACTERISTIC(BT_UUID_VOCS_LOCATION, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_location, NULL, &_vocs), \ - BT_GATT_CCC(location_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT), \ - BT_GATT_CHARACTERISTIC(BT_UUID_VOCS_CONTROL, \ - BT_GATT_CHRC_WRITE, \ - BT_GATT_PERM_WRITE_ENCRYPT, \ - NULL, write_vocs_control, &_vocs), \ - BT_GATT_CHARACTERISTIC(BT_UUID_VOCS_DESCRIPTION, \ - BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ - BT_GATT_PERM_READ_ENCRYPT, \ - read_output_desc, NULL, &_vocs), \ - BT_GATT_CCC(output_desc_cfg_changed, \ - BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT) \ + BT_AUDIO_CHRC(BT_UUID_VOCS_STATE, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_offset_state, NULL, &_vocs), \ + BT_AUDIO_CCC(offset_state_cfg_changed), \ + BT_AUDIO_CHRC(BT_UUID_VOCS_LOCATION, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_location, write_location, &_vocs), \ + BT_AUDIO_CCC(location_cfg_changed), \ + BT_AUDIO_CHRC(BT_UUID_VOCS_CONTROL, \ + BT_GATT_CHRC_WRITE, \ + BT_GATT_PERM_WRITE_ENCRYPT, \ + NULL, write_vocs_control, &_vocs), \ + BT_AUDIO_CHRC(BT_UUID_VOCS_DESCRIPTION, \ + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \ + BT_GATT_PERM_READ_ENCRYPT, \ + read_output_desc, write_output_desc, &_vocs), \ + BT_AUDIO_CCC(output_desc_cfg_changed) \ } static struct bt_vocs vocs_insts[CONFIG_BT_VOCS_MAX_INSTANCE_COUNT]; @@ -327,14 +348,12 @@ int bt_vocs_register(struct bt_vocs *vocs, if (param->location_writable && !bt_uuid_cmp(attr->uuid, BT_UUID_VOCS_LOCATION)) { /* Update attr and chrc to be writable */ chrc = vocs->srv.service_p->attrs[i - 1].user_data; - attr->write = write_location; attr->perm |= BT_GATT_PERM_WRITE_ENCRYPT; chrc->properties |= BT_GATT_CHRC_WRITE_WITHOUT_RESP; } else if (param->desc_writable && !bt_uuid_cmp(attr->uuid, BT_UUID_VOCS_DESCRIPTION)) { /* Update attr and chrc to be writable */ chrc = vocs->srv.service_p->attrs[i - 1].user_data; - attr->write = write_output_desc; attr->perm |= BT_GATT_PERM_WRITE_ENCRYPT; chrc->properties |= BT_GATT_CHRC_WRITE_WITHOUT_RESP; } @@ -399,14 +418,7 @@ int bt_vocs_location_set(struct bt_vocs *inst, uint32_t location) if (IS_ENABLED(CONFIG_BT_VOCS_CLIENT) && inst->client_instance) { return bt_vocs_client_location_set(inst, location); } else if (IS_ENABLED(CONFIG_BT_VOCS) && !inst->client_instance) { - struct bt_gatt_attr attr; - int err; - - attr.user_data = inst; - - err = write_location(NULL, &attr, &location, sizeof(location), 0, 0); - - return err > 0 ? 0 : err; + return vocs_write(inst, write_location, &location, sizeof(location)); } return -ENOTSUP; @@ -422,19 +434,13 @@ int bt_vocs_state_set(struct bt_vocs *inst, int16_t offset) if (IS_ENABLED(CONFIG_BT_VOCS_CLIENT) && inst->client_instance) { return bt_vocs_client_state_set(inst, offset); } else if (IS_ENABLED(CONFIG_BT_VOCS) && !inst->client_instance) { - struct bt_gatt_attr attr; struct bt_vocs_control cp; - int err; cp.opcode = BT_VOCS_OPCODE_SET_OFFSET; cp.counter = inst->srv.state.change_counter; cp.offset = sys_cpu_to_le16(offset); - attr.user_data = inst; - - err = write_vocs_control(NULL, &attr, &cp, sizeof(cp), 0, 0); - - return err > 0 ? 0 : err; + return vocs_write(inst, write_vocs_control, &cp, sizeof(cp)); } return -ENOTSUP; @@ -474,13 +480,7 @@ int bt_vocs_description_set(struct bt_vocs *inst, const char *description) if (IS_ENABLED(CONFIG_BT_VOCS_CLIENT) && inst->client_instance) { return bt_vocs_client_description_set(inst, description); } else if (IS_ENABLED(CONFIG_BT_VOCS) && !inst->client_instance) { - struct bt_gatt_attr attr; - int err; - - attr.user_data = inst; - - err = write_output_desc(NULL, &attr, description, strlen(description), 0, 0); - return err > 0 ? 0 : err; + return vocs_write(inst, write_output_desc, description, strlen(description)); } return -ENOTSUP; diff --git a/tests/bluetooth/bsim_bt/bsim_test_audio/prj.conf b/tests/bluetooth/bsim_bt/bsim_test_audio/prj.conf index c6f7ef4f4ca..85f2b58aff5 100644 --- a/tests/bluetooth/bsim_bt/bsim_test_audio/prj.conf +++ b/tests/bluetooth/bsim_bt/bsim_test_audio/prj.conf @@ -95,8 +95,6 @@ CONFIG_BT_BASS_CLIENT=y CONFIG_BT_HAS=y CONFIG_BT_HAS_CLIENT=y CONFIG_BT_HAS_HEARING_AID_MONAURAL=y -CONFIG_BT_SMP_SC_PAIR_ONLY=y -CONFIG_BT_SMP_MIN_ENC_KEY_SIZE=16 # Common Audio Profile CONFIG_BT_CAP_ACCEPTOR=y diff --git a/tests/bluetooth/shell/audio.conf b/tests/bluetooth/shell/audio.conf index 19865f85988..a2e9c293f7e 100644 --- a/tests/bluetooth/shell/audio.conf +++ b/tests/bluetooth/shell/audio.conf @@ -103,8 +103,6 @@ CONFIG_BT_HAS=y CONFIG_BT_HAS_HEARING_AID_MONAURAL=y CONFIG_BT_HAS_PRESET_NAME_DYNAMIC=y CONFIG_BT_HAS_PRESET_COUNT=4 -CONFIG_BT_SMP_SC_PAIR_ONLY=y -CONFIG_BT_SMP_MIN_ENC_KEY_SIZE=16 CONFIG_BT_HAS_CLIENT=y # Common Audio Profile