mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
Merge branch 'idf/ble_audio_4.4.1_v6.1' into 'release/v6.1'
feat(ble_audio): Support Zephyr LE Audio v4.4.1 (v6.1) See merge request espressif/esp-idf!50187
This commit is contained in:
@@ -175,7 +175,7 @@ if BT_BAP_BROADCAST_SINK
|
||||
config BT_BAP_BROADCAST_SNK_COUNT
|
||||
int "Basic Audio Broadcaster Sink count"
|
||||
default 1
|
||||
range 0 BT_ISO_MAX_BIG
|
||||
range 1 BT_ISO_MAX_BIG
|
||||
help
|
||||
This option sets the number of broadcast sinks to support.
|
||||
One broadcast sink can receive multiple streams
|
||||
|
||||
@@ -249,4 +249,11 @@ if BT_TBS || BT_TBS_CLIENT
|
||||
help
|
||||
Sets the maximum length of the bearer provider name.
|
||||
|
||||
config BT_TBS_MAX_FRIENDLY_NAME_LENGTH
|
||||
int "The maximum length of the friendly name supported"
|
||||
default 30
|
||||
range 1 512
|
||||
help
|
||||
Sets the maximum length of the friendly name in octets (without NULL terminator).
|
||||
|
||||
endif # BT_TBS || BT_TBS_CLIENT
|
||||
|
||||
@@ -73,7 +73,7 @@ esp_err_t esp_ble_audio_ccp_call_control_server_set_bearer_provider_name(
|
||||
}
|
||||
|
||||
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_ble_audio_ccp_call_control_server_bearer_t *bearer, char *name, size_t name_size)
|
||||
{
|
||||
esp_err_t err;
|
||||
|
||||
@@ -81,7 +81,31 @@ esp_err_t esp_ble_audio_ccp_call_control_server_get_bearer_provider_name(
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_ccp_call_control_server_get_bearer_provider_name_safe(bearer, name);
|
||||
err = bt_ccp_call_control_server_get_bearer_provider_name_safe(bearer, name, name_size);
|
||||
if (err) {
|
||||
switch (err) {
|
||||
case -EFAULT:
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
case -ENOMEM:
|
||||
return ESP_ERR_NO_MEM;
|
||||
default:
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_ccp_call_control_server_get_bearer_uci(
|
||||
esp_ble_audio_ccp_call_control_server_bearer_t *bearer, char *uci)
|
||||
{
|
||||
esp_err_t err;
|
||||
|
||||
if (bearer == NULL || uci == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_ccp_call_control_server_get_bearer_uci_safe(bearer, uci);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
@@ -231,19 +231,16 @@ esp_err_t esp_ble_audio_tbs_set_status_flags(uint8_t bearer_index, uint16_t stat
|
||||
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)
|
||||
esp_err_t esp_ble_audio_tbs_set_uri_scheme_list(uint8_t bearer_index, const char *uri_scheme_list)
|
||||
{
|
||||
uint8_t count = CONFIG_BT_TBS_BEARER_COUNT;
|
||||
int err;
|
||||
|
||||
if (count == 0 || bearer_index >= count ||
|
||||
(uri_count && uri_list == NULL)) {
|
||||
if (count == 0 || bearer_index >= count || uri_scheme_list == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
err = bt_tbs_set_uri_scheme_list_safe(bearer_index, uri_list, uri_count);
|
||||
err = bt_tbs_set_uri_scheme_list_safe(bearer_index, uri_scheme_list);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@@ -994,4 +991,23 @@ unlock:
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_CCID */
|
||||
|
||||
esp_ble_audio_tbs_instance_t *esp_ble_audio_tbs_client_get_by_index(uint16_t conn_handle, uint8_t index)
|
||||
{
|
||||
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_index(conn, index);
|
||||
|
||||
unlock:
|
||||
bt_le_host_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT */
|
||||
|
||||
@@ -99,13 +99,25 @@ esp_err_t esp_ble_audio_ccp_call_control_server_set_bearer_provider_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.
|
||||
* @param bearer The bearer to get the name for.
|
||||
* @param name Buffer that will be populated with the bearer provider name.
|
||||
* @param name_size The size of the @p name buffer.
|
||||
*
|
||||
* @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);
|
||||
esp_ble_audio_ccp_call_control_server_bearer_t *bearer, char *name, size_t name_size);
|
||||
|
||||
/**
|
||||
* @brief Get the bearer UCI.
|
||||
*
|
||||
* @param bearer The bearer to get the UCI for.
|
||||
* @param uci Buffer of size BT_TBS_MAX_UCI_SIZE that the bearer UCI will be written to.
|
||||
*
|
||||
* @return ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_ccp_call_control_server_get_bearer_uci(
|
||||
esp_ble_audio_ccp_call_control_server_bearer_t *bearer, char *uci);
|
||||
|
||||
/**
|
||||
* @brief Discovers the Telephone Bearer Service (TBS) support on a remote device.
|
||||
|
||||
@@ -318,15 +318,12 @@ esp_err_t esp_ble_audio_tbs_set_status_flags(uint8_t bearer_index, uint16_t stat
|
||||
/**
|
||||
* @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.
|
||||
* @param bearer_index The index of the Telephone Bearer.
|
||||
* @param uri_scheme_list Comma-separated list of URI prefixes (e.g. "skype,tel").
|
||||
*
|
||||
* @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);
|
||||
esp_err_t esp_ble_audio_tbs_set_uri_scheme_list(uint8_t bearer_index, const char *uri_scheme_list);
|
||||
|
||||
/**
|
||||
* @brief Register the callbacks for TBS.
|
||||
@@ -628,6 +625,16 @@ esp_err_t esp_ble_audio_tbs_client_register_cb(esp_ble_audio_tbs_client_cb_t *cb
|
||||
*/
|
||||
esp_ble_audio_tbs_instance_t *esp_ble_audio_tbs_client_get_by_ccid(uint16_t conn_handle, uint8_t ccid);
|
||||
|
||||
/**
|
||||
* @brief Look up Telephone Bearer Service instance by index.
|
||||
*
|
||||
* @param conn_handle Connection handle.
|
||||
* @param index The index 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_index(uint16_t conn_handle, uint8_t index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -45,8 +45,13 @@ LOG_MODULE_REGISTER(LEA_CSIS, CONFIG_BT_ISO_LOG_LEVEL);
|
||||
(BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC)
|
||||
#endif /* CONFIG_BT_CSIP_SET_MEMBER_SIRK_NOTIFIABLE */
|
||||
|
||||
#if CONFIG_BT_CSIP_SET_MEMBER_SIZE_NOTIFIABLE
|
||||
#define CSIS_CHR_FLAGS_SET_SIZE \
|
||||
(BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_READ_ENC)
|
||||
#else /* CONFIG_BT_CSIP_SET_MEMBER_SIZE_NOTIFIABLE */
|
||||
#define CSIS_CHR_FLAGS_SET_SIZE \
|
||||
(BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC)
|
||||
#endif /* CONFIG_BT_CSIP_SET_MEMBER_SIZE_NOTIFIABLE */
|
||||
|
||||
#define CSIS_CHR_FLAGS_SET_LOCK \
|
||||
(BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_WRITE | \
|
||||
@@ -138,34 +143,60 @@ static int csis_svc_check(void)
|
||||
|
||||
int bt_le_nimble_csis_attr_handle_set(void)
|
||||
{
|
||||
struct bt_gatt_attr *attr;
|
||||
uint16_t start_handle = 0;
|
||||
uint16_t end_handle = 0;
|
||||
|
||||
LOG_DBG("[N]CsisAttrHdlSet[%u]", csis_svc_count);
|
||||
|
||||
for (size_t i = 0; i < csis_svc_count; i++) {
|
||||
assert(csis_insts[i].svc_p);
|
||||
struct bt_gatt_service *zsvc = csis_insts[i].svc_p;
|
||||
|
||||
assert(zsvc);
|
||||
assert(csis_insts[i].sirk_handle >= 2);
|
||||
|
||||
/* SIRK is always the first characteristic, so its value handle anchors the range. */
|
||||
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);
|
||||
LOG_DBG("[N]CsisInst[%u][%u][%u]", i, start_handle, zsvc->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;
|
||||
for (size_t j = 0; j < zsvc->attr_count; j++) {
|
||||
(zsvc->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;
|
||||
/* Cross-check the last characteristic value against the handle NimBLE assigned, to
|
||||
* catch divergence between the lib's attribute layout and NimBLE's registration. The
|
||||
* last characteristic is no longer necessarily Rank, as optional ones may be absent.
|
||||
*/
|
||||
for (size_t j = zsvc->attr_count; j-- > 0;) {
|
||||
const struct bt_uuid_16 *uuid = (const struct bt_uuid_16 *)(zsvc->attrs + j)->uuid;
|
||||
uint16_t chr_handle = 0;
|
||||
|
||||
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;
|
||||
if (uuid->uuid.type != BT_UUID_TYPE_16) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (uuid->val) {
|
||||
case BT_UUID_CSIS_SIRK_VAL:
|
||||
chr_handle = csis_insts[i].sirk_handle;
|
||||
break;
|
||||
case BT_UUID_CSIS_SET_SIZE_VAL:
|
||||
chr_handle = csis_insts[i].set_size_handle;
|
||||
break;
|
||||
case BT_UUID_CSIS_SET_LOCK_VAL:
|
||||
chr_handle = csis_insts[i].set_lock_handle;
|
||||
break;
|
||||
case BT_UUID_CSIS_RANK_VAL:
|
||||
chr_handle = csis_insts[i].rank_handle;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((zsvc->attrs + j)->handle != chr_handle) {
|
||||
LOG_ERR("[N]CsisMismatchAttrHdl[%u][%u][%u]",
|
||||
i, (zsvc->attrs + j)->handle, chr_handle);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,8 +220,11 @@ static inline void csis_chr_init(struct ble_gatt_chr_def *chr,
|
||||
}
|
||||
|
||||
static void csis_svc_init(struct csis_inst *inst,
|
||||
struct ble_gatt_svc_def *svc)
|
||||
struct ble_gatt_svc_def *svc,
|
||||
const struct bt_gatt_service *zsvc)
|
||||
{
|
||||
size_t chr_cnt = 0U;
|
||||
|
||||
LOG_DBG("[N]CsisSvcInit");
|
||||
|
||||
svc->type = BLE_GATT_SVC_TYPE_PRIMARY;
|
||||
@@ -200,29 +234,47 @@ static void csis_svc_init(struct csis_inst *inst,
|
||||
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);
|
||||
/* Build the NimBLE characteristics from the ones actually present in the Zephyr
|
||||
* service. Optional characteristics (set size, lock, rank) may be absent depending
|
||||
* on the registration parameters, so the layout is data-driven rather than fixed.
|
||||
*/
|
||||
for (size_t i = 0; i < zsvc->attr_count; i++) {
|
||||
const struct bt_uuid_16 *uuid = (const struct bt_uuid_16 *)zsvc->attrs[i].uuid;
|
||||
|
||||
/* Characteristic - Coordinated Set Size */
|
||||
csis_chr_init((void *)&svc->characteristics[1],
|
||||
&csis_uuid_set_size,
|
||||
&inst->set_size_handle,
|
||||
CSIS_CHR_FLAGS_SET_SIZE);
|
||||
if (uuid->uuid.type != BT_UUID_TYPE_16) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Characteristic - Set Member Lock */
|
||||
csis_chr_init((void *)&svc->characteristics[2],
|
||||
&csis_uuid_set_lock,
|
||||
&inst->set_lock_handle,
|
||||
CSIS_CHR_FLAGS_SET_LOCK);
|
||||
switch (uuid->val) {
|
||||
case BT_UUID_CSIS_SIRK_VAL:
|
||||
csis_chr_init((void *)&svc->characteristics[chr_cnt++], &csis_uuid_sirk,
|
||||
&inst->sirk_handle, CSIS_CHR_FLAGS_SIRK);
|
||||
break;
|
||||
case BT_UUID_CSIS_SET_SIZE_VAL:
|
||||
csis_chr_init((void *)&svc->characteristics[chr_cnt++], &csis_uuid_set_size,
|
||||
&inst->set_size_handle, CSIS_CHR_FLAGS_SET_SIZE);
|
||||
break;
|
||||
case BT_UUID_CSIS_SET_LOCK_VAL:
|
||||
csis_chr_init((void *)&svc->characteristics[chr_cnt++], &csis_uuid_set_lock,
|
||||
&inst->set_lock_handle, CSIS_CHR_FLAGS_SET_LOCK);
|
||||
break;
|
||||
case BT_UUID_CSIS_RANK_VAL:
|
||||
csis_chr_init((void *)&svc->characteristics[chr_cnt++], &csis_uuid_rank,
|
||||
&inst->rank_handle, CSIS_CHR_FLAGS_RANK);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Characteristic - Set Member Rank */
|
||||
csis_chr_init((void *)&svc->characteristics[3],
|
||||
&csis_uuid_rank,
|
||||
&inst->rank_handle,
|
||||
CSIS_CHR_FLAGS_RANK);
|
||||
/* svc->characteristics has CSIS_CHR_COUNT (= 4 + 1) slots: up to 4 real chars plus
|
||||
* a trailing zeroed slot that NimBLE requires as the NULL-uuid array terminator.
|
||||
* chr_cnt is the real-char count written via [chr_cnt++], so it must stay strictly
|
||||
* below CSIS_CHR_COUNT — chr_cnt == CSIS_CHR_COUNT means a write already clobbered
|
||||
* the terminator slot. Trips if the switch matches a 5th char: a new CSIS case added
|
||||
* without bumping the (4 + 1), or a duplicate UUID in the Zephyr service table.
|
||||
*/
|
||||
assert(chr_cnt < CSIS_CHR_COUNT);
|
||||
}
|
||||
|
||||
int bt_le_nimble_csis_init(void *svc, uint8_t count)
|
||||
@@ -239,9 +291,9 @@ int bt_le_nimble_csis_init(void *svc, uint8_t count)
|
||||
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];
|
||||
|
||||
csis_svc_init(&csis_insts[i], &gatt_svc_csis[i], csis_insts[i].svc_p);
|
||||
}
|
||||
|
||||
rc = ble_gatts_count_cfg(gatt_svc_csis);
|
||||
|
||||
@@ -182,7 +182,7 @@ static const uint16_t ext_structs[] = {
|
||||
sizeof(struct bt_bond_info),
|
||||
};
|
||||
|
||||
#define LEA_VERSION (0x20260616)
|
||||
#define LEA_VERSION (0x20260624)
|
||||
|
||||
struct lib_ext_cfgs {
|
||||
/* BLE */
|
||||
@@ -401,6 +401,7 @@ struct lib_ext_cfgs {
|
||||
bool config_tbs_client_call_friendly_name;
|
||||
uint8_t config_tbs_max_uri_length;
|
||||
uint16_t config_tbs_max_provider_name_length;
|
||||
uint16_t config_tbs_max_friendly_name_length;
|
||||
|
||||
/* TMAP (Telephony and Media Audio Profile) */
|
||||
bool config_tmap_cg_supported;
|
||||
@@ -893,6 +894,7 @@ static const struct lib_ext_cfgs ext_cfgs = {
|
||||
#if CONFIG_BT_TBS || CONFIG_BT_TBS_CLIENT
|
||||
.config_tbs_max_uri_length = CONFIG_BT_TBS_MAX_URI_LENGTH,
|
||||
.config_tbs_max_provider_name_length = CONFIG_BT_TBS_MAX_PROVIDER_NAME_LENGTH,
|
||||
.config_tbs_max_friendly_name_length = CONFIG_BT_TBS_MAX_FRIENDLY_NAME_LENGTH,
|
||||
#endif /* CONFIG_BT_TBS || CONFIG_BT_TBS_CLIENT */
|
||||
|
||||
/* TMAP (Telephony and Media Audio Profile) */
|
||||
@@ -1083,6 +1085,7 @@ struct lib_ext_funcs {
|
||||
void *data);
|
||||
int (*_conn_get_info)(const struct bt_conn *conn, struct bt_conn_info *info);
|
||||
uint8_t (*_conn_index)(const struct bt_conn *conn);
|
||||
struct bt_conn *(*_conn_lookup_index)(uint8_t index);
|
||||
const bt_addr_le_t *(*_conn_get_dst)(const struct bt_conn *conn);
|
||||
struct bt_conn *(*_conn_ref)(struct bt_conn *conn);
|
||||
void (*_conn_unref)(struct bt_conn *conn);
|
||||
@@ -1299,6 +1302,7 @@ static const struct lib_ext_funcs ext_funcs = {
|
||||
._conn_foreach = (void *)bt_conn_foreach,
|
||||
._conn_get_info = (void *)bt_conn_get_info,
|
||||
._conn_index = (void *)bt_conn_index,
|
||||
._conn_lookup_index = (void *)bt_conn_lookup_index,
|
||||
._conn_get_dst = (void *)bt_conn_get_dst,
|
||||
._conn_ref = (void *)bt_conn_ref,
|
||||
._conn_unref = (void *)bt_conn_unref,
|
||||
@@ -1363,6 +1367,7 @@ struct lib_funcs {
|
||||
|
||||
/* BAP Unicast Client */
|
||||
bool (*_bap_unicast_client_has_ep)(const struct bt_bap_ep *ep);
|
||||
struct bt_conn *(*_bap_unicast_client_ep_get_conn)(const struct bt_bap_ep *ep);
|
||||
int (*_bap_unicast_client_register_cb)(struct bt_bap_unicast_client_cb *cb);
|
||||
int (*_bap_unicast_client_config)(struct bt_bap_stream *stream,
|
||||
const struct bt_audio_codec_cfg *codec_cfg);
|
||||
@@ -1375,6 +1380,7 @@ struct lib_funcs {
|
||||
|
||||
/* BAP Unicast Server */
|
||||
bool (*_bap_unicast_server_has_ep)(const struct bt_bap_ep *ep);
|
||||
struct bt_conn *(*_bap_unicast_server_ep_get_conn)(const struct bt_bap_ep *ep);
|
||||
int (*_bap_unicast_server_reconfig)(struct bt_bap_stream *stream,
|
||||
const struct bt_audio_codec_cfg *codec_cfg);
|
||||
int (*_bap_unicast_server_start)(struct bt_bap_stream *stream);
|
||||
@@ -1407,11 +1413,11 @@ struct lib_funcs {
|
||||
/* CAP Handover */
|
||||
bool (*_cap_common_handover_is_active)(void);
|
||||
bool (*_cap_handover_is_handover_broadcast_source)(const struct bt_cap_broadcast_source *cap_broadcast_source);
|
||||
void (*_cap_handover_complete)(void);
|
||||
void (*_cap_handover_unicast_proc_complete)(void);
|
||||
void (*_cap_handover_complete)(struct bt_cap_common_proc *active_proc);
|
||||
void (*_cap_handover_unicast_proc_complete)(struct bt_cap_common_proc *active_proc);
|
||||
void (*_cap_handover_broadcast_source_stopped)(uint8_t reason);
|
||||
void (*_cap_handover_unicast_to_broadcast_reception_start)(void);
|
||||
int (*_cap_handover_broadcast_reception_stopped)(void);
|
||||
int (*_cap_handover_broadcast_reception_stopped)(struct bt_cap_common_proc *active_proc);
|
||||
void (*_cap_handover_receive_state_updated)(const struct bt_conn *conn,
|
||||
const struct bt_bap_scan_delegator_recv_state *state);
|
||||
|
||||
@@ -1503,6 +1509,8 @@ struct lib_funcs {
|
||||
int (*_tbs_client_primary_discover_gtbs)(struct bt_conn *conn);
|
||||
struct bt_tbs_instance *(*_tbs_client_get_by_ccid)(const struct bt_conn *conn,
|
||||
uint8_t ccid);
|
||||
struct bt_tbs_instance *(*_tbs_client_get_by_index)(const struct bt_conn *conn,
|
||||
uint8_t index);
|
||||
|
||||
/* VCP Volume Controller */
|
||||
void (*_vcp_vol_ctlr_aics_init)(void);
|
||||
@@ -1551,6 +1559,7 @@ static const struct lib_funcs lib_funcs = {
|
||||
|
||||
#if CONFIG_BT_BAP_UNICAST_CLIENT
|
||||
._bap_unicast_client_has_ep = lib_bap_unicast_client_has_ep,
|
||||
._bap_unicast_client_ep_get_conn = lib_bap_unicast_client_ep_get_conn,
|
||||
._bap_unicast_client_register_cb = lib_bap_unicast_client_register_cb,
|
||||
._bap_unicast_client_config = lib_bap_unicast_client_config,
|
||||
._bap_unicast_client_metadata = lib_bap_unicast_client_metadata,
|
||||
@@ -1562,6 +1571,7 @@ static const struct lib_funcs lib_funcs = {
|
||||
|
||||
#if CONFIG_BT_BAP_UNICAST_SERVER
|
||||
._bap_unicast_server_has_ep = lib_bap_unicast_server_has_ep,
|
||||
._bap_unicast_server_ep_get_conn = lib_bap_unicast_server_ep_get_conn,
|
||||
._bap_unicast_server_reconfig = lib_bap_unicast_server_reconfig,
|
||||
._bap_unicast_server_start = lib_bap_unicast_server_start,
|
||||
._bap_unicast_server_metadata = lib_bap_unicast_server_metadata,
|
||||
@@ -1697,6 +1707,10 @@ static const struct lib_funcs lib_funcs = {
|
||||
._tbs_client_get_by_ccid = lib_tbs_client_get_by_ccid,
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_CCID */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT
|
||||
._tbs_client_get_by_index = lib_tbs_client_get_by_index,
|
||||
#endif /* CONFIG_BT_TBS_CLIENT */
|
||||
|
||||
#if CONFIG_BT_VCP_VOL_CTLR_AICS
|
||||
._vcp_vol_ctlr_aics_init = lib_vcp_vol_ctlr_aics_init,
|
||||
#endif /* CONFIG_BT_VCP_VOL_CTLR_AICS */
|
||||
|
||||
@@ -125,7 +125,10 @@ extern "C" {
|
||||
#define BT_AICS_ERR_GAIN_MODE_NOT_ALLOWED 0x84
|
||||
/** @} */
|
||||
|
||||
/** @brief Opaque Audio Input Control Service instance. */
|
||||
/**
|
||||
* @struct bt_aics
|
||||
* @brief Opaque Audio Input Control Service instance.
|
||||
*/
|
||||
struct bt_aics;
|
||||
|
||||
/** @brief Structure for initializing a Audio Input Control Service instance. */
|
||||
|
||||
@@ -619,16 +619,28 @@ struct bt_bap_ascs_rsp {
|
||||
*/
|
||||
#define BT_BAP_ASCS_RSP(c, r) (struct bt_bap_ascs_rsp) { .code = c, .reason = r }
|
||||
|
||||
/** @brief Abstract Audio Broadcast Source structure. */
|
||||
/**
|
||||
* @struct bt_bap_broadcast_source
|
||||
* @brief Abstract Audio Broadcast Source structure.
|
||||
*/
|
||||
struct bt_bap_broadcast_source;
|
||||
|
||||
/** @brief Abstract Audio Broadcast Sink structure. */
|
||||
/**
|
||||
* @struct bt_bap_broadcast_sink
|
||||
* @brief Abstract Audio Broadcast Sink structure.
|
||||
*/
|
||||
struct bt_bap_broadcast_sink;
|
||||
|
||||
/** @brief Abstract Audio Unicast Group structure. */
|
||||
/**
|
||||
* @struct bt_bap_unicast_group
|
||||
* @brief Abstract Audio Unicast Group structure.
|
||||
*/
|
||||
struct bt_bap_unicast_group;
|
||||
|
||||
/** @brief Abstract Audio Endpoint structure. */
|
||||
/**
|
||||
* @struct bt_bap_ep
|
||||
* @brief Abstract Audio Endpoint structure.
|
||||
*/
|
||||
struct bt_bap_ep;
|
||||
|
||||
/** Struct to hold subgroup specific information for the receive state */
|
||||
@@ -871,6 +883,22 @@ struct bt_bap_ep_info {
|
||||
*/
|
||||
int bt_bap_ep_get_info_safe(const struct bt_bap_ep *ep, struct bt_bap_ep_info *info);
|
||||
|
||||
/**
|
||||
* @brief Get the pointer to the ACL connection of an endpoint
|
||||
*
|
||||
* The caller gets a new reference to the connection object, if not NULL, which must be
|
||||
* released with bt_conn_unref() once done using the object.
|
||||
*
|
||||
* @param ep The endpoint to get the ACL connection of
|
||||
*
|
||||
* @return The ACL connection pointer, or NULL if:
|
||||
* - @p ep is NULL
|
||||
* - @p ep is a broadcast endpoint
|
||||
* - @p ep is a Unicast Server endpoint not yet configured by a remote client
|
||||
* - @p ep is a Unicast Client endpoint not yet discovered on a remote server
|
||||
*/
|
||||
struct bt_conn *bt_bap_ep_get_conn(const struct bt_bap_ep *ep);
|
||||
|
||||
/**
|
||||
* @brief Basic Audio Profile stream structure.
|
||||
*
|
||||
@@ -1189,7 +1217,7 @@ int bt_bap_stream_disable_safe(struct bt_bap_stream *stream);
|
||||
* @retval 0 in case of success
|
||||
* @retval -EINVAL if the stream, endpoint, ISO channel or connection is NULL
|
||||
* @retval -EBADMSG if the stream or ISO channel is in an invalid state for connection
|
||||
* @retval -EOPNOTSUPP if the role of the stream is not @ref BT_HCI_ROLE_CENTRAL
|
||||
* @retval -EOPNOTSUPP if the role of the stream is not @ref BT_CONN_ROLE_CENTRAL
|
||||
* @retval -EALREADY if the ISO channel is already connecting or connected
|
||||
* @retval -EBUSY if another ISO channel is connecting
|
||||
* @retval -ENOEXEC if otherwise rejected by the ISO layer
|
||||
@@ -1233,7 +1261,7 @@ int bt_bap_stream_start_safe(struct bt_bap_stream *stream);
|
||||
*
|
||||
* @retval 0 Success
|
||||
* @retval -EINVAL The @p stream does not have an endpoint or a connection, of the stream's
|
||||
* connection's role is not @p BT_HCI_ROLE_CENTRAL
|
||||
* connection's role is not @p BT_CONN_ROLE_CENTRAL
|
||||
* @retval -EBADMSG The state of the @p stream endpoint is not @ref BT_BAP_EP_STATE_DISABLING
|
||||
* @retval -EALREADY The CIS state of the @p is not in a connected state, and thus is already
|
||||
* stopping
|
||||
@@ -1530,8 +1558,11 @@ int bt_bap_unicast_server_unregister_cb_safe(const struct bt_bap_unicast_server_
|
||||
*
|
||||
* @param ep The structure object with endpoint info.
|
||||
* @param user_data Data to pass to the function.
|
||||
*
|
||||
* @retval true Continue iterating.
|
||||
* @retval false Stop iterating.
|
||||
*/
|
||||
typedef void (*bt_bap_ep_func_t)(struct bt_bap_ep *ep, void *user_data);
|
||||
typedef bool (*bt_bap_ep_func_t)(struct bt_bap_ep *ep, void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Iterate through all endpoints of the given connection.
|
||||
@@ -1539,8 +1570,12 @@ typedef void (*bt_bap_ep_func_t)(struct bt_bap_ep *ep, void *user_data);
|
||||
* @param conn Connection object
|
||||
* @param func Function to call for each endpoint.
|
||||
* @param user_data Data to pass to the callback function.
|
||||
*
|
||||
* @retval 0 Success
|
||||
* @retval -ECANCELED Iteration was stopped by the callback function before complete.
|
||||
* @retval -EINVAL @p conn or @p func were NULL.
|
||||
*/
|
||||
void bt_bap_unicast_server_foreach_ep(struct bt_conn *conn, bt_bap_ep_func_t func, void *user_data);
|
||||
int bt_bap_unicast_server_foreach_ep(struct bt_conn *conn, bt_bap_ep_func_t func, void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Initialize and configure a new ASE.
|
||||
@@ -1711,8 +1746,8 @@ int bt_bap_unicast_group_delete_safe(struct bt_bap_unicast_group *unicast_group)
|
||||
* @param stream The audio stream
|
||||
* @param user_data User data
|
||||
*
|
||||
* @retval true Stop iterating.
|
||||
* @retval false Continue iterating.
|
||||
* @retval true Continue iterating.
|
||||
* @retval false Stop iterating.
|
||||
*/
|
||||
typedef bool (*bt_bap_unicast_group_foreach_stream_func_t)(struct bt_bap_stream *stream,
|
||||
void *user_data);
|
||||
@@ -1770,11 +1805,22 @@ struct bt_bap_unicast_client_cb {
|
||||
* @param conn Connection to the remote unicast server.
|
||||
* @param dir Direction of the location.
|
||||
* @param loc The location bitfield value.
|
||||
*
|
||||
* @return 0 in case of success or negative value in case of error.
|
||||
*/
|
||||
void (*location)(struct bt_conn *conn, enum bt_audio_dir dir, enum bt_audio_location loc);
|
||||
|
||||
/**
|
||||
* @brief Remote Unicast Server Supported Contexts
|
||||
*
|
||||
* This callback is called whenever the supported contexts are read
|
||||
* from the server or otherwise notified to the client.
|
||||
*
|
||||
* @param conn Connection to the remote unicast server.
|
||||
* @param snk_ctx The sink context bitfield value.
|
||||
* @param src_ctx The source context bitfield value.
|
||||
*/
|
||||
void (*supported_contexts)(struct bt_conn *conn, enum bt_audio_context snk_ctx,
|
||||
enum bt_audio_context src_ctx);
|
||||
|
||||
/**
|
||||
* @brief Remote Unicast Server Available Contexts
|
||||
*
|
||||
@@ -1784,8 +1830,6 @@ struct bt_bap_unicast_client_cb {
|
||||
* @param conn Connection to the remote unicast server.
|
||||
* @param snk_ctx The sink context bitfield value.
|
||||
* @param src_ctx The source context bitfield value.
|
||||
*
|
||||
* @return 0 in case of success or negative value in case of error.
|
||||
*/
|
||||
void (*available_contexts)(struct bt_conn *conn, enum bt_audio_context snk_ctx,
|
||||
enum bt_audio_context src_ctx);
|
||||
@@ -2453,8 +2497,8 @@ int bt_bap_broadcast_source_get_base_safe(struct bt_bap_broadcast_source *source
|
||||
* @param stream The audio stream
|
||||
* @param user_data User data
|
||||
*
|
||||
* @retval true Stop iterating.
|
||||
* @retval false Continue iterating.
|
||||
* @retval true Continue iterating.
|
||||
* @retval false Stop iterating.
|
||||
*/
|
||||
typedef bool (*bt_bap_broadcast_source_foreach_stream_func_t)(struct bt_bap_stream *stream,
|
||||
void *user_data);
|
||||
@@ -2467,7 +2511,7 @@ typedef bool (*bt_bap_broadcast_source_foreach_stream_func_t)(struct bt_bap_stre
|
||||
* @param user_data User specified data that is sent to the callback function
|
||||
*
|
||||
* @retval 0 Success (even if no streams exists in the broadcast source).
|
||||
* @retval -ECANCELED The @p func returned true.
|
||||
* @retval -ECANCELED The @p func returned false and stopped the iteration.
|
||||
* @retval -EINVAL @p source or @p func were NULL.
|
||||
*/
|
||||
int bt_bap_broadcast_source_foreach_stream_safe(struct bt_bap_broadcast_source *source,
|
||||
@@ -2539,7 +2583,7 @@ struct bt_bap_broadcast_sink_cb {
|
||||
* It is possible to register multiple struct of callbacks, but a single struct can only be
|
||||
* registered once.
|
||||
* Registering the same callback multiple times is undefined behavior and may break the stack.
|
||||
*
|
||||
|
||||
* @param cb Broadcast sink callback structure.
|
||||
*
|
||||
* @retval 0 on success
|
||||
@@ -2956,7 +3000,8 @@ int bt_bap_broadcast_assistant_discover_safe(struct bt_conn *conn);
|
||||
* @retval -ENOMEM Could not allocated memory for the request
|
||||
* @retval -ENOEXEC Unexpected scan or GATT error
|
||||
*/
|
||||
int bt_bap_broadcast_assistant_scan_start(struct bt_conn *conn, bool start_scan);
|
||||
int bt_bap_broadcast_assistant_scan_start(struct bt_conn *conn,
|
||||
bool start_scan);
|
||||
int bt_bap_broadcast_assistant_scan_start_safe(struct bt_conn *conn,
|
||||
bool start_scan);
|
||||
|
||||
|
||||
@@ -47,10 +47,16 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Abstract Audio Broadcast Source structure. */
|
||||
/**
|
||||
* @struct bt_cap_broadcast_source
|
||||
* @brief Abstract Audio Broadcast Source structure.
|
||||
*/
|
||||
struct bt_cap_broadcast_source;
|
||||
|
||||
/** @brief Abstract CAP Unicast Group structure. */
|
||||
/**
|
||||
* @struct bt_cap_unicast_group
|
||||
* @brief Abstract CAP Unicast Group structure.
|
||||
*/
|
||||
struct bt_cap_unicast_group;
|
||||
|
||||
/**
|
||||
@@ -394,13 +400,13 @@ int bt_cap_unicast_group_add_streams_safe(struct bt_cap_unicast_group *unicast_g
|
||||
*/
|
||||
int bt_cap_unicast_group_delete_safe(struct bt_cap_unicast_group *unicast_group);
|
||||
|
||||
/** Callback function for bt_bap_unicast_group_foreach_stream()
|
||||
/** Callback function for bt_cap_unicast_group_foreach_stream()
|
||||
*
|
||||
* @param stream The audio stream
|
||||
* @param user_data User data
|
||||
*
|
||||
* @retval true Stop iterating.
|
||||
* @retval false Continue iterating.
|
||||
* @retval true Continue iterating.
|
||||
* @retval false Stop iterating.
|
||||
*/
|
||||
typedef bool (*bt_cap_unicast_group_foreach_stream_func_t)(struct bt_cap_stream *stream,
|
||||
void *user_data);
|
||||
@@ -413,7 +419,7 @@ typedef bool (*bt_cap_unicast_group_foreach_stream_func_t)(struct bt_cap_stream
|
||||
* @param user_data User specified data that is sent to the callback function
|
||||
*
|
||||
* @retval 0 Success (even if no streams exists in the group).
|
||||
* @retval -ECANCELED The @p func returned true.
|
||||
* @retval -ECANCELED The @p func returned false and stopped the iteration.
|
||||
* @retval -EINVAL @p unicast_group or @p func were NULL.
|
||||
*/
|
||||
int bt_cap_unicast_group_foreach_stream_safe(struct bt_cap_unicast_group *unicast_group,
|
||||
@@ -832,8 +838,8 @@ int bt_cap_initiator_broadcast_get_base_safe(struct bt_cap_broadcast_source *bro
|
||||
* @param stream The audio stream
|
||||
* @param user_data User data
|
||||
*
|
||||
* @retval true Stop iterating.
|
||||
* @retval false Continue iterating.
|
||||
* @retval true Continue iterating.
|
||||
* @retval false Stop iterating.
|
||||
*/
|
||||
typedef bool (*bt_cap_initiator_broadcast_foreach_stream_func_t)(struct bt_cap_stream *stream,
|
||||
void *user_data);
|
||||
@@ -846,7 +852,7 @@ typedef bool (*bt_cap_initiator_broadcast_foreach_stream_func_t)(struct bt_cap_s
|
||||
* @param user_data User specified data that is sent to the callback function.
|
||||
*
|
||||
* @retval 0 Success (even if no streams exists in the group).
|
||||
* @retval -ECANCELED The @p func returned true.
|
||||
* @retval -ECANCELED The @p func returned false and stopped the iteration.
|
||||
* @retval -EINVAL @p broadcast_source or @p func were NULL.
|
||||
*/
|
||||
int bt_cap_initiator_broadcast_foreach_stream_safe(struct bt_cap_broadcast_source *broadcast_source,
|
||||
@@ -887,6 +893,20 @@ struct bt_cap_handover_unicast_to_broadcast_param {
|
||||
|
||||
/** Callback structure for CAP procedures */
|
||||
struct bt_cap_handover_cb {
|
||||
/**
|
||||
* @brief The broadcast source has been created for handover
|
||||
*
|
||||
* When this is called, the broadcast source has been created and the BASE can be
|
||||
* generated by bt_cap_initiator_broadcast_get_base(). To continue with the broadcast
|
||||
* reception part of the procedure, the application shall enable extended and periodic
|
||||
* advertising and set the BASE in the periodic advertising data with
|
||||
* bt_le_per_adv_set_data(). The procedure will finish once the CAP acceptors have synced
|
||||
* to the newly created broadcast source.
|
||||
*
|
||||
* @param broadcast_source Pointer to newly created broadcast source.
|
||||
*/
|
||||
void (*unicast_to_broadcast_created)(struct bt_cap_broadcast_source *broadcast_source);
|
||||
|
||||
/**
|
||||
* @brief The unicast to broadcast handover procedure has finished
|
||||
*
|
||||
|
||||
@@ -47,7 +47,10 @@ extern "C" {
|
||||
* @ingroup bt_ccp
|
||||
* @{
|
||||
*/
|
||||
/** @brief Abstract Call Control Server Telephone Bearer structure. */
|
||||
/**
|
||||
* @struct bt_ccp_call_control_server_bearer
|
||||
* @brief Abstract Call Control Server Telephone Bearer structure.
|
||||
*/
|
||||
struct bt_ccp_call_control_server_bearer;
|
||||
|
||||
/**
|
||||
@@ -101,8 +104,10 @@ int bt_ccp_call_control_server_unregister_bearer_safe(struct bt_ccp_call_control
|
||||
*
|
||||
* @retval 0 Success
|
||||
* @retval -EINVAL @p bearer or @p name is NULL, or @p name is the empty string or @p name is larger
|
||||
* than @kconfig{CONFIG_BT_TBS_MAX_PROVIDER_NAME_LENGTH}
|
||||
* than @kconfig{CONFIG_BT_CCP_CALL_CONTROL_SERVER_PROVIDER_NAME_MAX_LEN}
|
||||
* @retval -EFAULT @p bearer is not registered
|
||||
* @retval -EBUSY The TBS instance of @p bearer is busy
|
||||
* @retval -ENOEXEC The TBS instance of @p bearer returned unexpected error
|
||||
*/
|
||||
int bt_ccp_call_control_server_set_bearer_provider_name_safe(
|
||||
struct bt_ccp_call_control_server_bearer *bearer, const char *name);
|
||||
@@ -111,14 +116,32 @@ int bt_ccp_call_control_server_set_bearer_provider_name_safe(
|
||||
* @brief Get the bearer provider name.
|
||||
*
|
||||
* @param[in] bearer The bearer to get the name for.
|
||||
* @param[out] name Pointer that will be updated to be the bearer provider name.
|
||||
* @param[out] name Pointer a buffer that will be populated with the bearer provider name.
|
||||
* @param name_size The size of the @p name buffer. The suggested size is
|
||||
* @kconfig{CONFIG_BT_CCP_CALL_CONTROL_SERVER_PROVIDER_NAME_MAX_LEN} + 1 to
|
||||
* ensure that the name always fits.
|
||||
*
|
||||
* @retval 0 Success
|
||||
* @retval -EINVAL @p bearer or @p name is NULL
|
||||
* @retval -EFAULT @p bearer is not registered
|
||||
* @retval -ENOMEM @p name_size is insufficient to hold the bearer name (including null terminator)
|
||||
*/
|
||||
int bt_ccp_call_control_server_get_bearer_provider_name_safe(
|
||||
struct bt_ccp_call_control_server_bearer *bearer, const char **name);
|
||||
struct bt_ccp_call_control_server_bearer *bearer, char *name, size_t name_size);
|
||||
|
||||
/**
|
||||
* @brief Get the bearer UCI.
|
||||
*
|
||||
* @param[in] bearer The bearer to get the UCI for.
|
||||
* @param[out] uci Pointer to a buffer of size @ref BT_TBS_MAX_UCI_SIZE that the bearer UCI will be
|
||||
* written to.
|
||||
*
|
||||
* @retval 0 Success
|
||||
* @retval -EINVAL @p bearer or @p uci is NULL
|
||||
* @retval -EFAULT @p bearer is not registered
|
||||
*/
|
||||
int bt_ccp_call_control_server_get_bearer_uci_safe(struct bt_ccp_call_control_server_bearer *bearer,
|
||||
char uci[BT_TBS_MAX_UCI_SIZE]);
|
||||
|
||||
/** @} */ /* End of group bt_ccp_call_control_server */
|
||||
|
||||
@@ -127,10 +150,17 @@ int bt_ccp_call_control_server_get_bearer_provider_name_safe(
|
||||
* @ingroup bt_ccp
|
||||
* @{
|
||||
*/
|
||||
/** Abstract Call Control Client structure. */
|
||||
|
||||
/**
|
||||
* @struct bt_ccp_call_control_client
|
||||
* @brief Abstract Call Control Client structure.
|
||||
*/
|
||||
struct bt_ccp_call_control_client;
|
||||
|
||||
/** Abstract Call Control Client bearer structure. */
|
||||
/**
|
||||
* @struct bt_ccp_call_control_client_bearer
|
||||
* @brief Abstract Call Control Client bearer structure.
|
||||
*/
|
||||
struct bt_ccp_call_control_client_bearer;
|
||||
|
||||
/** Struct with information about bearers of a client */
|
||||
@@ -159,23 +189,29 @@ struct bt_ccp_call_control_client_cb {
|
||||
* @param client Call Control Client pointer.
|
||||
* @param err Error value. 0 on success, GATT error on positive
|
||||
* value or errno on negative value.
|
||||
* @param bearers The bearers found.
|
||||
* @param bearers The bearers found. Value must be copied if used after return.
|
||||
* @param user_data User data stored in the callback struct.
|
||||
*/
|
||||
void (*discover)(struct bt_ccp_call_control_client *client, int err,
|
||||
struct bt_ccp_call_control_client_bearers *bearers);
|
||||
struct bt_ccp_call_control_client_bearers *bearers, void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Callback function for bt_ccp_call_control_client_read_bearer_provider_name().
|
||||
*
|
||||
* This callback is called once the read bearer provider name procedure is completed.
|
||||
*
|
||||
* @param client Call Control Client instance pointer.
|
||||
* @param err Error value. 0 on success, GATT error on positive
|
||||
* value or errno on negative value.
|
||||
* @param name The bearer provider name. NULL if @p err is not 0.
|
||||
* @param bearer Call Control Client bearer instance pointer.
|
||||
* @param err Error value. 0 on success, GATT error on positive
|
||||
* value or errno on negative value.
|
||||
* @param name The bearer provider name. NULL if @p err is not 0.
|
||||
* Value must be copied if used after return.
|
||||
* @param user_data User data stored in the callback struct.
|
||||
*/
|
||||
void (*bearer_provider_name)(struct bt_ccp_call_control_client_bearer *bearer, int err,
|
||||
const char *name);
|
||||
const char *name, void *user_data);
|
||||
|
||||
/** User data that will be supplied to all callbacks */
|
||||
void *user_data;
|
||||
|
||||
/** @cond INTERNAL_HIDDEN */
|
||||
/** Internally used field for list handling */
|
||||
|
||||
@@ -83,7 +83,10 @@ extern "C" {
|
||||
*/
|
||||
#define BT_CSIP_DATA_RSI(_rsi) BT_DATA(BT_DATA_CSIS_RSI, _rsi, BT_CSIP_RSI_SIZE)
|
||||
|
||||
/** @brief Opaque Coordinated Set Identification Service instance. */
|
||||
/**
|
||||
* @struct bt_csip_set_member_svc_inst
|
||||
* @brief Opaque Coordinated Set Identification Service instance.
|
||||
*/
|
||||
struct bt_csip_set_member_svc_inst;
|
||||
|
||||
/** Callback structure for the Coordinated Set Identification Service */
|
||||
@@ -224,6 +227,8 @@ int bt_csip_set_member_sirk_safe(struct bt_csip_set_member_svc_inst *svc_inst,
|
||||
* 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.
|
||||
* The rank of a device cannot be modified on its own, and a new rank can only be set if the @p size
|
||||
* is different from the current set size.
|
||||
*
|
||||
* If @kconfig{CONFIG_BT_CSIP_SET_MEMBER_SIZE_NOTIFIABLE} is enabled, this will also send a
|
||||
* notification to all connected or bonded clients.
|
||||
@@ -234,7 +239,7 @@ int bt_csip_set_member_sirk_safe(struct bt_csip_set_member_svc_inst *svc_inst,
|
||||
*
|
||||
* @retval -EINVAL @p svc_inst is NULL, @p size is less than 1, @p rank is less than 1 or higher
|
||||
* than @p size for a lockable @p svc_inst.
|
||||
* @retval -EALREADY @p size and @p rank are already the provided values.
|
||||
* @retval -EALREADY @p size is already set.
|
||||
* @retval 0 Success.
|
||||
*/
|
||||
int bt_csip_set_member_set_size_and_rank_safe(struct bt_csip_set_member_svc_inst *svc_inst, uint8_t size,
|
||||
|
||||
@@ -56,7 +56,10 @@ extern "C" {
|
||||
/** Preset name maximum length */
|
||||
#define BT_HAS_PRESET_NAME_MAX 40
|
||||
|
||||
/** @brief Opaque Hearing Access Service object. */
|
||||
/**
|
||||
* @struct bt_has
|
||||
* @brief Opaque Hearing Access Service object.
|
||||
*/
|
||||
struct bt_has;
|
||||
|
||||
/** Hearing Aid device type */
|
||||
@@ -424,14 +427,6 @@ int bt_has_preset_available_safe(uint8_t index);
|
||||
*/
|
||||
int bt_has_preset_unavailable_safe(uint8_t index);
|
||||
|
||||
/** Enum for return values for @ref bt_has_preset_func_t functions */
|
||||
enum {
|
||||
/** Stop iterating */
|
||||
BT_HAS_PRESET_ITER_STOP = 0,
|
||||
/** Continue iterating */
|
||||
BT_HAS_PRESET_ITER_CONTINUE,
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef bt_has_preset_func_t
|
||||
* @brief Preset iterator callback.
|
||||
@@ -441,11 +436,11 @@ enum {
|
||||
* @param name Preset name.
|
||||
* @param user_data Data given.
|
||||
*
|
||||
* @return BT_HAS_PRESET_ITER_CONTINUE if should continue to the next preset.
|
||||
* @return BT_HAS_PRESET_ITER_STOP to stop.
|
||||
* @retval true Continue iterating.
|
||||
* @retval false Stop iterating.
|
||||
*/
|
||||
typedef uint8_t (*bt_has_preset_func_t)(uint8_t index, enum bt_has_properties properties,
|
||||
const char *name, void *user_data);
|
||||
typedef bool (*bt_has_preset_func_t)(uint8_t index, enum bt_has_properties properties,
|
||||
const char *name, void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Preset iterator.
|
||||
@@ -455,8 +450,12 @@ typedef uint8_t (*bt_has_preset_func_t)(uint8_t index, enum bt_has_properties pr
|
||||
* @param index Preset index, passing @ref BT_HAS_PRESET_INDEX_NONE skips index matching.
|
||||
* @param func Callback function.
|
||||
* @param user_data Data to pass to the callback.
|
||||
*
|
||||
* @retval 0 Success
|
||||
* @retval -ECANCELED Iteration was stopped by the callback function before complete.
|
||||
* @retval -EINVAL @p func was NULL.
|
||||
*/
|
||||
void bt_has_preset_foreach_safe(uint8_t index, bt_has_preset_func_t func, void *user_data);
|
||||
int bt_has_preset_foreach_safe(uint8_t index, bt_has_preset_func_t func, void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Set active preset.
|
||||
|
||||
@@ -54,7 +54,10 @@ extern "C" {
|
||||
#define BT_MICP_MUTE_DISABLED 0x02
|
||||
/** @} */
|
||||
|
||||
/** @brief Opaque Microphone Controller instance. */
|
||||
/**
|
||||
* @struct bt_micp_mic_ctlr
|
||||
* @brief Opaque Microphone Controller instance.
|
||||
*/
|
||||
struct bt_micp_mic_ctlr;
|
||||
|
||||
/** @brief Register parameters structure for Microphone Control Service */
|
||||
|
||||
@@ -201,7 +201,17 @@ extern "C" {
|
||||
*/
|
||||
#define BT_TBS_GTBS_INDEX 0xFF
|
||||
|
||||
/** @brief Opaque Telephone Bearer Service instance. */
|
||||
/** Maximum size of bearer uniform caller identifier (UCI)
|
||||
*
|
||||
* Includes the NULL terminator.
|
||||
* Allowed values are defined by Bluetooth Assigned Numbers.
|
||||
*/
|
||||
#define BT_TBS_MAX_UCI_SIZE 6
|
||||
|
||||
/**
|
||||
* @struct bt_tbs_instance
|
||||
* @brief Opaque Telephone Bearer Service instance.
|
||||
*/
|
||||
struct bt_tbs_instance;
|
||||
|
||||
/**
|
||||
@@ -453,13 +463,11 @@ int bt_tbs_set_status_flags_safe(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.
|
||||
* @param uri_scheme_list Comma-separated list of URI prefixes (e.g. "skype,tel").
|
||||
*
|
||||
* @return BT_TBS_RESULT_CODE_* if positive or 0, errno value if negative.
|
||||
*/
|
||||
int bt_tbs_set_uri_scheme_list_safe(uint8_t bearer_index, const char **uri_list,
|
||||
uint8_t uri_count);
|
||||
int bt_tbs_set_uri_scheme_list_safe(uint8_t bearer_index, const char *uri_scheme_list);
|
||||
/**
|
||||
* @brief Register the callbacks for TBS.
|
||||
*
|
||||
@@ -1086,7 +1094,8 @@ int bt_tbs_client_read_friendly_name_safe(struct bt_conn *conn, uint8_t inst_ind
|
||||
* @note @kconfig{CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES} must be set
|
||||
* for this function to be effective.
|
||||
*/
|
||||
int bt_tbs_client_read_optional_opcodes(struct bt_conn *conn, uint8_t inst_index);
|
||||
int bt_tbs_client_read_optional_opcodes(struct bt_conn *conn,
|
||||
uint8_t inst_index);
|
||||
int bt_tbs_client_read_optional_opcodes_safe(struct bt_conn *conn,
|
||||
uint8_t inst_index);
|
||||
|
||||
@@ -1115,6 +1124,16 @@ int bt_tbs_client_register_cb_safe(struct bt_tbs_client_cb *cbs);
|
||||
struct bt_tbs_instance *bt_tbs_client_get_by_ccid_safe(const struct bt_conn *conn,
|
||||
uint8_t ccid);
|
||||
|
||||
/**
|
||||
* @brief Look up Telephone Bearer Service instance by index
|
||||
*
|
||||
* @param conn The connection to the TBS server.
|
||||
* @param index The index to lookup a service instance for.
|
||||
*
|
||||
* @return Pointer to a Telephone Bearer Service instance if found else NULL.
|
||||
*/
|
||||
struct bt_tbs_instance *bt_tbs_client_get_by_index_safe(const struct bt_conn *conn, uint8_t index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -61,7 +61,10 @@ extern "C" {
|
||||
#define BT_VCP_STATE_MUTED 0x01
|
||||
/** @} */
|
||||
|
||||
/** @brief Opaque Volume Control Service instance. */
|
||||
/**
|
||||
* @struct bt_vcp_vol_ctlr
|
||||
* @brief Opaque Volume Control Service instance.
|
||||
*/
|
||||
struct bt_vcp_vol_ctlr;
|
||||
|
||||
/** Register structure for Volume Control Service */
|
||||
|
||||
@@ -66,7 +66,10 @@ extern "C" {
|
||||
#define BT_VOCS_MAX_OFFSET 255
|
||||
/** @} */
|
||||
|
||||
/** @brief Opaque Volume Offset Control Service instance. */
|
||||
/**
|
||||
* @struct bt_vocs
|
||||
* @brief Opaque Volume Offset Control Service instance.
|
||||
*/
|
||||
struct bt_vocs;
|
||||
|
||||
/** @brief Structure for registering a Volume Offset Control Service instance. */
|
||||
|
||||
@@ -551,7 +551,10 @@ struct bt_ots_obj_metadata {
|
||||
uint32_t props;
|
||||
};
|
||||
|
||||
/** @brief Opaque OTS instance. */
|
||||
/**
|
||||
* @struct bt_ots
|
||||
* @brief Opaque OTS instance.
|
||||
*/
|
||||
struct bt_ots;
|
||||
|
||||
/** @brief Descriptor for OTS object addition */
|
||||
|
||||
@@ -134,6 +134,7 @@ enum bt_cap_common_subproc_type;
|
||||
enum bt_cap_common_proc_type;
|
||||
struct bt_cap_stream;
|
||||
struct bt_cap_broadcast_source;
|
||||
struct bt_cap_common_proc;
|
||||
|
||||
struct bt_ots;
|
||||
struct bt_ots_client;
|
||||
@@ -174,6 +175,7 @@ extern bool lib_bap_broadcast_source_has_ep(const struct bt_bap_ep *ep);
|
||||
|
||||
#if CONFIG_BT_BAP_UNICAST_CLIENT
|
||||
extern bool lib_bap_unicast_client_has_ep(const struct bt_bap_ep *ep);
|
||||
extern struct bt_conn *lib_bap_unicast_client_ep_get_conn(const struct bt_bap_ep *ep);
|
||||
extern int lib_bap_unicast_client_register_cb(struct bt_bap_unicast_client_cb *cb);
|
||||
extern int lib_bap_unicast_client_config(struct bt_bap_stream *stream,
|
||||
const struct bt_audio_codec_cfg *codec_cfg);
|
||||
@@ -187,6 +189,7 @@ extern int lib_bap_unicast_client_release(struct bt_bap_stream *stream);
|
||||
|
||||
#if CONFIG_BT_BAP_UNICAST_SERVER
|
||||
extern bool lib_bap_unicast_server_has_ep(const struct bt_bap_ep *ep);
|
||||
extern struct bt_conn *lib_bap_unicast_server_ep_get_conn(const struct bt_bap_ep *ep);
|
||||
extern int lib_bap_unicast_server_reconfig(struct bt_bap_stream *stream,
|
||||
const struct bt_audio_codec_cfg *codec_cfg);
|
||||
extern int lib_bap_unicast_server_start(struct bt_bap_stream *stream);
|
||||
@@ -222,11 +225,11 @@ extern void lib_cap_initiator_released(struct bt_cap_stream *cap_stream);
|
||||
#if CONFIG_BT_CAP_HANDOVER
|
||||
extern bool lib_cap_common_handover_is_active(void);
|
||||
extern bool lib_cap_handover_is_handover_broadcast_source(const struct bt_cap_broadcast_source *cap_broadcast_source);
|
||||
extern void lib_cap_handover_complete(void);
|
||||
extern void lib_cap_handover_unicast_proc_complete(void);
|
||||
extern void lib_cap_handover_complete(struct bt_cap_common_proc *active_proc);
|
||||
extern void lib_cap_handover_unicast_proc_complete(struct bt_cap_common_proc *active_proc);
|
||||
extern void lib_cap_handover_broadcast_source_stopped(uint8_t reason);
|
||||
extern void lib_cap_handover_unicast_to_broadcast_reception_start(void);
|
||||
extern int lib_cap_handover_broadcast_reception_stopped(void);
|
||||
extern int lib_cap_handover_broadcast_reception_stopped(struct bt_cap_common_proc *active_proc);
|
||||
extern void lib_cap_handover_receive_state_updated(const struct bt_conn *conn,
|
||||
const struct bt_bap_scan_delegator_recv_state *state);
|
||||
#endif /* CONFIG_BT_CAP_HANDOVER */
|
||||
@@ -340,6 +343,11 @@ extern struct bt_tbs_instance *lib_tbs_client_get_by_ccid(const struct bt_conn *
|
||||
uint8_t ccid);
|
||||
#endif /* CONFIG_BT_TBS_CLIENT_CCID */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT
|
||||
extern struct bt_tbs_instance *lib_tbs_client_get_by_index(const struct bt_conn *conn,
|
||||
uint8_t index);
|
||||
#endif /* CONFIG_BT_TBS_CLIENT */
|
||||
|
||||
#if CONFIG_BT_VCP_VOL_CTLR_AICS
|
||||
extern void lib_vcp_vol_ctlr_aics_init(void);
|
||||
#endif /* CONFIG_BT_VCP_VOL_CTLR_AICS */
|
||||
|
||||
Submodule components/bt/esp_ble_audio/lib/lib updated: 77cf36bd77...8af2910982
@@ -1851,7 +1851,7 @@ static void handle_gatts_read_event(struct bt_le_gatts_read_event *event)
|
||||
} else {
|
||||
ret = attr->read(conn, attr, (void *)rsp, GATT_MAX_ATTR_LEN, 0);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("[B]GattsRdEvtFail[%u][%d]", event->attr_handle, ret);
|
||||
LOG_DBG("[B]GattsRdEvtErr[%u][%d]", event->attr_handle, ret);
|
||||
|
||||
status = BT_GATT_ERR(ret);
|
||||
}
|
||||
@@ -1942,7 +1942,7 @@ static void handle_gatts_write_event(struct bt_le_gatts_write_event *event)
|
||||
} else {
|
||||
ret = attr->write(conn, attr, event->value, event->len, 0, 0);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("[B]GattsWrEvtFail[%u][%d]", event->attr_handle, ret);
|
||||
LOG_DBG("[B]GattsWrEvtErr[%u][%d]", event->attr_handle, ret);
|
||||
|
||||
status = BT_GATT_ERR(ret);
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ int bt_conn_get_info(const struct bt_conn *conn, struct bt_conn_info *info)
|
||||
info->id = conn->id;
|
||||
info->state = conn_internal_to_public_state(conn->state);
|
||||
info->le.dst = &conn->le.dst;
|
||||
info->le.interval = conn->le.interval;
|
||||
info->le.interval_us = conn->le.interval_us;
|
||||
|
||||
if (conn->encrypt) {
|
||||
/* Currently the flags is updated for lib usage.
|
||||
@@ -330,6 +330,15 @@ struct bt_conn *bt_conn_lookup_handle(uint16_t handle, enum bt_conn_type type)
|
||||
return conn;
|
||||
}
|
||||
|
||||
struct bt_conn *bt_conn_lookup_index(uint8_t index)
|
||||
{
|
||||
if (index >= ARRAY_SIZE(acl_conns)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return bt_conn_ref(&acl_conns[index]);
|
||||
}
|
||||
|
||||
_IDF_ONLY
|
||||
struct bt_conn *bt_le_acl_conn_find(uint16_t conn_handle)
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Intel Corporation
|
||||
* SPDX-FileCopyrightText: 2021-2025 Nordic Semiconductor ASA
|
||||
* SPDX-FileCopyrightText: 2021-2026 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <zephyr/bluetooth/conn.h>
|
||||
#include <zephyr/bluetooth/hci_types.h>
|
||||
#include <zephyr/bluetooth/iso.h>
|
||||
#include <zephyr/bluetooth/common/bt_str.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/net_buf.h>
|
||||
@@ -61,6 +62,8 @@ struct bt_conn iso_conns[CONFIG_BT_ISO_MAX_CHAN];
|
||||
struct bt_iso_cig cigs[CONFIG_BT_ISO_MAX_CIG];
|
||||
|
||||
static struct bt_iso_cig *get_cig(const struct bt_iso_chan *iso_chan);
|
||||
static int hci_le_create_cis(const struct bt_iso_connect_param *param, size_t count);
|
||||
|
||||
#endif /* CONFIG_BT_ISO_CENTRAL */
|
||||
|
||||
#if defined(CONFIG_BT_ISO_PERIPHERAL)
|
||||
@@ -220,65 +223,65 @@ static int validate_iso_setup_data_path_parms(const struct bt_iso_chan *chan, ui
|
||||
struct bt_conn *iso;
|
||||
|
||||
CHECKIF(chan == NULL) {
|
||||
LOG_DBG("ChanNull");
|
||||
LOG_ERR("ChanNull");
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
CHECKIF(path == NULL) {
|
||||
LOG_DBG("PathNull");
|
||||
LOG_ERR("PathNull");
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
CHECKIF(dir != BT_HCI_DATAPATH_DIR_HOST_TO_CTLR &&
|
||||
dir != BT_HCI_DATAPATH_DIR_CTLR_TO_HOST) {
|
||||
LOG_DBG("InvDir[%u]", dir);
|
||||
LOG_ERR("InvDir[%u]", dir);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
iso = chan->iso;
|
||||
if (iso == NULL) {
|
||||
LOG_DBG("ChanNotAssociated[%p]", chan);
|
||||
LOG_ERR("ChanNotAssociated[%p]", chan);
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!iso->iso.info.can_recv && dir == BT_HCI_DATAPATH_DIR_CTLR_TO_HOST) {
|
||||
LOG_DBG("InvDirForChanCannotRecv[%u][%p]", dir, chan);
|
||||
LOG_ERR("InvDirForChanCannotRecv[%u][%p]", dir, chan);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!iso->iso.info.can_send && dir == BT_HCI_DATAPATH_DIR_HOST_TO_CTLR) {
|
||||
LOG_DBG("InvDirForChanCannotSend[%u][%p]", dir, chan);
|
||||
LOG_ERR("InvDirForChanCannotSend[%u][%p]", dir, chan);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
CHECKIF(path->pid != BT_ISO_DATA_PATH_HCI &&
|
||||
!IN_RANGE(path->pid, BT_ISO_DATA_PATH_VS_ID_MIN, BT_ISO_DATA_PATH_VS_ID_MAX)) {
|
||||
LOG_DBG("InvPid[%u]", path->pid);
|
||||
LOG_ERR("InvPid[%u]", path->pid);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
CHECKIF(path->format > BT_HCI_CODING_FORMAT_G729A &&
|
||||
path->format != BT_HCI_CODING_FORMAT_VS) {
|
||||
LOG_DBG("InvFormat[%u]", path->format);
|
||||
LOG_ERR("InvFormat[%u]", path->format);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
CHECKIF(path->delay > BT_ISO_CONTROLLER_DELAY_MAX) {
|
||||
LOG_DBG("InvDelay[%u]", path->delay);
|
||||
LOG_ERR("InvDelay[%u]", path->delay);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
CHECKIF(path->cc_len > 0U && path->cc == NULL) {
|
||||
LOG_DBG("NoCcProvidedForCcLen[%u]", path->cc_len);
|
||||
LOG_ERR("NoCcProvidedForCcLen[%u]", path->cc_len);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -300,14 +303,14 @@ int bt_iso_setup_data_path(const struct bt_iso_chan *chan, uint8_t dir,
|
||||
|
||||
err = hci_le_setup_iso_data_path(chan->iso, dir, path);
|
||||
if (err != 0) {
|
||||
LOG_DBG("SetDataPathFail[%d]", err);
|
||||
LOG_ERR("SetDataPathFail[%d]", err);
|
||||
|
||||
/* Return known possible errors */
|
||||
if (err == -ENOBUFS || err == -EIO || err == -EACCES) {
|
||||
return err;
|
||||
}
|
||||
|
||||
LOG_DBG("UnkErrFromSetupIsoDataPath[%d]", err);
|
||||
LOG_ERR("UnkErrFromSetupIsoDataPath[%d]", err);
|
||||
|
||||
return -ENOEXEC;
|
||||
}
|
||||
@@ -360,21 +363,21 @@ static int validate_iso_remove_data_path(const struct bt_iso_chan *chan, uint8_t
|
||||
struct bt_conn *iso;
|
||||
|
||||
CHECKIF(chan == NULL) {
|
||||
LOG_DBG("ChanNull");
|
||||
LOG_ERR("ChanNull");
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
CHECKIF(dir != BT_HCI_DATAPATH_DIR_HOST_TO_CTLR &&
|
||||
dir != BT_HCI_DATAPATH_DIR_CTLR_TO_HOST) {
|
||||
LOG_DBG("InvDir[%u]", dir);
|
||||
LOG_ERR("InvDir[%u]", dir);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
iso = chan->iso;
|
||||
if (iso == NULL) {
|
||||
LOG_DBG("ChanNotAssociated[%p]", chan);
|
||||
LOG_ERR("ChanNotAssociated[%p]", chan);
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
@@ -393,14 +396,14 @@ int bt_iso_remove_data_path(const struct bt_iso_chan *chan, uint8_t dir)
|
||||
|
||||
err = hci_le_remove_iso_data_path(chan->iso, dir);
|
||||
if (err != 0) {
|
||||
LOG_DBG("RemoveDataPathFail[%d]", err);
|
||||
LOG_ERR("RemoveDataPathFail[%d]", err);
|
||||
|
||||
/* Return known possible errors */
|
||||
if (err == -ENOBUFS || err == -EIO || err == -EACCES) {
|
||||
return err;
|
||||
}
|
||||
|
||||
LOG_DBG("UnkErrFromRemoveIsoDataPath[%d]", err);
|
||||
LOG_ERR("UnkErrFromRemoveIsoDataPath[%d]", err);
|
||||
|
||||
return -ENOEXEC;
|
||||
}
|
||||
@@ -438,7 +441,7 @@ static void bt_iso_chan_disconnected(struct bt_iso_chan *chan, uint8_t reason)
|
||||
|
||||
const uint8_t conn_type = chan->iso->iso.info.type;
|
||||
|
||||
LOG_DBG("IsoChanDisconnected[%02x]", reason);
|
||||
LOG_INF("IsoChanDisconnected[%02x]", reason);
|
||||
|
||||
bt_iso_chan_set_state(chan, BT_ISO_STATE_DISCONNECTED);
|
||||
bt_conn_set_state(chan->iso, BT_CONN_DISCONNECT_COMPLETE);
|
||||
@@ -492,6 +495,7 @@ static void bt_iso_chan_disconnected(struct bt_iso_chan *chan, uint8_t reason)
|
||||
* complete in the same way as ACL and CIS do. Call bt_conn_tx_notify directly here
|
||||
* to flush the chan->iso->tx_complete for each disconnected BIS
|
||||
*/
|
||||
/* TBD: do we need to clean the BIS tx list here? */
|
||||
} else {
|
||||
/* No special handling for BT_ISO_CHAN_TYPE_SYNC_RECEIVER */
|
||||
}
|
||||
@@ -525,8 +529,6 @@ const char *bt_iso_chan_state_str(uint8_t state)
|
||||
return "disconnected";
|
||||
case BT_ISO_STATE_CONNECTING:
|
||||
return "connecting";
|
||||
case BT_ISO_STATE_ENCRYPT_PENDING:
|
||||
return "encryption pending";
|
||||
case BT_ISO_STATE_CONNECTED:
|
||||
return "connected";
|
||||
case BT_ISO_STATE_DISCONNECTING:
|
||||
@@ -547,8 +549,6 @@ void bt_iso_chan_set_state_debug(struct bt_iso_chan *chan, enum bt_iso_state sta
|
||||
case BT_ISO_STATE_DISCONNECTED:
|
||||
/* regardless of old state always allows this states */
|
||||
break;
|
||||
case BT_ISO_STATE_ENCRYPT_PENDING:
|
||||
__fallthrough;
|
||||
case BT_ISO_STATE_CONNECTING:
|
||||
if (chan->state != BT_ISO_STATE_DISCONNECTED) {
|
||||
LOG_WRN("InvTransition[%s][%d]", func, line);
|
||||
@@ -691,8 +691,8 @@ static bool valid_chan_io_qos(const struct bt_iso_chan_io_qos *io_qos, bool is_t
|
||||
LOG_DBG("ValidChanIoQos[%u][%u][%u]", is_tx, is_broadcast, advanced);
|
||||
|
||||
if (io_qos->phy != BT_GAP_LE_PHY_1M &&
|
||||
io_qos->phy != BT_GAP_LE_PHY_2M &&
|
||||
io_qos->phy != BT_GAP_LE_PHY_CODED) {
|
||||
io_qos->phy != BT_GAP_LE_PHY_2M &&
|
||||
io_qos->phy != BT_GAP_LE_PHY_CODED) {
|
||||
LOG_ERR("InvPhy[%u]", io_qos->phy);
|
||||
|
||||
return false;
|
||||
@@ -816,17 +816,6 @@ int bt_iso_chan_disconnect(struct bt_iso_chan *chan)
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
if (chan->state == BT_ISO_STATE_ENCRYPT_PENDING) {
|
||||
LOG_WRN("ChanAlreadyDisconnected");
|
||||
bt_iso_chan_set_state(chan, BT_ISO_STATE_DISCONNECTED);
|
||||
|
||||
if (chan->ops->disconnected) {
|
||||
chan->ops->disconnected(chan, BT_HCI_ERR_LOCALHOST_TERM_CONN);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (chan->state == BT_ISO_STATE_DISCONNECTING) {
|
||||
LOG_WRN("AlreadyDisconnecting");
|
||||
|
||||
@@ -950,14 +939,14 @@ static void store_cis_info(const struct bt_hci_evt_le_cis_established *evt, stru
|
||||
|
||||
central->bn = evt->c_bn;
|
||||
central->phy = bt_get_phy(evt->c_phy);
|
||||
central->latency = sys_get_le16(evt->c_latency);
|
||||
central->latency = sys_get_le24(evt->c_latency);
|
||||
central->max_pdu = sys_le16_to_cpu(evt->c_max_pdu);
|
||||
/* Transform to n * 1.25ms */
|
||||
central->flush_timeout = info->iso_interval * evt->c_ft;
|
||||
|
||||
peripheral->bn = evt->p_bn;
|
||||
peripheral->phy = bt_get_phy(evt->p_phy);
|
||||
peripheral->latency = sys_get_le16(evt->p_latency);
|
||||
peripheral->latency = sys_get_le24(evt->p_latency);
|
||||
peripheral->max_pdu = sys_le16_to_cpu(evt->p_max_pdu);
|
||||
/* Transform to n * 1.25ms */
|
||||
peripheral->flush_timeout = info->iso_interval * evt->p_ft;
|
||||
@@ -1155,17 +1144,6 @@ int bt_iso_server_register(struct bt_iso_server *server)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_SMP)
|
||||
if (server->sec_level > BT_SECURITY_L3) {
|
||||
LOG_ERR("InvSrvSecLevel[%u]", server->sec_level);
|
||||
return -EINVAL;
|
||||
} else if (server->sec_level < BT_SECURITY_L1) {
|
||||
LOG_DBG("SrvSecLevelUpdatedToL1");
|
||||
/* Level 0 is only applicable for BR/EDR */
|
||||
server->sec_level = BT_SECURITY_L1;
|
||||
}
|
||||
#endif /* CONFIG_BT_SMP */
|
||||
|
||||
iso_server = server;
|
||||
|
||||
return 0;
|
||||
@@ -1218,10 +1196,6 @@ static int iso_accept(struct bt_conn *acl, struct bt_conn *iso)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_SMP)
|
||||
chan->required_sec_level = iso_server->sec_level;
|
||||
#endif /* CONFIG_BT_SMP */
|
||||
|
||||
bt_iso_chan_add(iso, chan);
|
||||
bt_iso_chan_set_state(chan, BT_ISO_STATE_CONNECTING);
|
||||
|
||||
@@ -1277,32 +1251,12 @@ static int hci_le_accept_cis(uint16_t handle)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t iso_server_check_security(struct bt_conn *conn)
|
||||
{
|
||||
LOG_DBG("IsoSrvCheckSec[%u][%u]", conn->sec_level, iso_server->sec_level);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CONN_DISABLE_SECURITY)) {
|
||||
return BT_HCI_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_SMP)
|
||||
if (conn->sec_level >= iso_server->sec_level) {
|
||||
return BT_HCI_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
return BT_HCI_ERR_INSUFFICIENT_SECURITY;
|
||||
#else
|
||||
return BT_HCI_ERR_SUCCESS;
|
||||
#endif /* CONFIG_BT_SMP */
|
||||
}
|
||||
|
||||
void hci_le_cis_req(struct net_buf *buf)
|
||||
{
|
||||
struct bt_hci_evt_le_cis_req *evt = (void *)buf->data;
|
||||
uint16_t acl_handle = sys_le16_to_cpu(evt->acl_handle);
|
||||
uint16_t cis_handle = sys_le16_to_cpu(evt->cis_handle);
|
||||
struct bt_conn *acl, *iso;
|
||||
uint8_t sec_err;
|
||||
int err;
|
||||
|
||||
LOG_DBG("CisReqEvt[%u][%u][%u][%u]",
|
||||
@@ -1331,18 +1285,6 @@ void hci_le_cis_req(struct net_buf *buf)
|
||||
return;
|
||||
}
|
||||
|
||||
sec_err = iso_server_check_security(acl);
|
||||
if (sec_err != BT_HCI_ERR_SUCCESS) {
|
||||
LOG_DBG("InsuffSec[%u]", sec_err);
|
||||
err = hci_le_reject_cis(cis_handle, sec_err);
|
||||
if (err != 0) {
|
||||
LOG_ERR("RejectCisFail[%d]", err);
|
||||
}
|
||||
|
||||
bt_conn_unref(acl);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add ISO connection */
|
||||
iso = bt_conn_add_iso(acl);
|
||||
|
||||
@@ -1361,7 +1303,7 @@ void hci_le_cis_req(struct net_buf *buf)
|
||||
/* Request application to accept */
|
||||
err = iso_accept(acl, iso);
|
||||
if (err) {
|
||||
LOG_DBG("AppRejectedCis[%d]", err);
|
||||
LOG_INF("AppRejectedCis[%d]", err);
|
||||
bt_iso_cleanup_acl(iso);
|
||||
bt_conn_unref(iso);
|
||||
hci_le_reject_cis(cis_handle, BT_HCI_ERR_INSUFFICIENT_RESOURCES);
|
||||
@@ -1412,17 +1354,17 @@ static bool valid_chan_qos(const struct bt_iso_chan_qos *qos, bool advanced)
|
||||
#endif /* CONFIG_BT_ISO_TEST_PARAMS */
|
||||
|
||||
if (qos->rx == NULL && qos->tx == NULL) {
|
||||
LOG_DBG("BothRxAndTxQosNull");
|
||||
LOG_ERR("BothRxAndTxQosNull");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (qos->rx != NULL && !valid_chan_io_qos(qos->rx, false, false, advanced)) {
|
||||
LOG_DBG("InvRxQos");
|
||||
LOG_ERR("InvRxQos");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (qos->tx != NULL && !valid_chan_io_qos(qos->tx, true, false, advanced)) {
|
||||
LOG_DBG("InvTxQos");
|
||||
LOG_ERR("InvTxQos");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1459,7 +1401,7 @@ static struct net_buf *hci_le_set_cig_params(const struct bt_iso_cig *cig,
|
||||
struct net_buf *rsp;
|
||||
int i, err;
|
||||
|
||||
LOG_DBG("SetCigParams[%u]", cig->id);
|
||||
LOG_INF("SetCigParams[%u]", cig->id);
|
||||
|
||||
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CIG_PARAMS,
|
||||
sizeof(*req) + sizeof(*cis_param) * param->num_cis);
|
||||
@@ -1482,7 +1424,7 @@ static struct net_buf *hci_le_set_cig_params(const struct bt_iso_cig *cig,
|
||||
req->framing = param->framing;
|
||||
req->num_cis = param->num_cis;
|
||||
|
||||
LOG_DBG("[%u][%u][%u][%u][%u][%u][%u][%u][%u]",
|
||||
LOG_INF("[%u][%u][%u][%u][%u][%u][%u][%u][%u]",
|
||||
cig->id, param->c_to_p_latency, param->p_to_c_latency,
|
||||
param->c_to_p_interval, param->p_to_c_interval, param->sca,
|
||||
param->packing, param->framing, param->num_cis);
|
||||
@@ -1526,7 +1468,7 @@ static struct net_buf *hci_le_set_cig_params(const struct bt_iso_cig *cig,
|
||||
cis_param->p_rtn = qos->rx->rtn;
|
||||
}
|
||||
|
||||
LOG_DBG("[%d]:[%u][%u][%u][%u][%u][%u][%u]",
|
||||
LOG_INF("[%d]:[%u][%u][%u][%u][%u][%u][%u]",
|
||||
i, cis_param->cis_id, cis_param->c_phy, cis_param->c_sdu,
|
||||
cis_param->c_rtn, cis_param->p_phy, cis_param->p_sdu,
|
||||
cis_param->p_rtn);
|
||||
@@ -1550,7 +1492,7 @@ static struct net_buf *hci_le_set_cig_test_params(const struct bt_iso_cig *cig,
|
||||
struct net_buf *rsp;
|
||||
int err;
|
||||
|
||||
LOG_DBG("SetCigTestParams");
|
||||
LOG_INF("SetCigTestParams");
|
||||
|
||||
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CIG_PARAMS_TEST,
|
||||
sizeof(*req) + sizeof(*cis_param) * param->num_cis);
|
||||
@@ -1574,7 +1516,7 @@ static struct net_buf *hci_le_set_cig_test_params(const struct bt_iso_cig *cig,
|
||||
req->framing = param->framing;
|
||||
req->num_cis = param->num_cis;
|
||||
|
||||
LOG_DBG("[%u][%u][%u][%u][%u][%u][%u][%u][%u][%u]",
|
||||
LOG_INF("[%u][%u][%u][%u][%u][%u][%u][%u][%u][%u]",
|
||||
cig->id, param->c_to_p_interval, param->p_to_c_interval,
|
||||
param->c_to_p_ft, param->p_to_c_ft, param->iso_interval,
|
||||
param->sca, param->packing, param->framing, param->num_cis);
|
||||
@@ -1621,7 +1563,7 @@ static struct net_buf *hci_le_set_cig_test_params(const struct bt_iso_cig *cig,
|
||||
cis_param->p_bn = qos->rx->burst_number;
|
||||
}
|
||||
|
||||
LOG_DBG("[%d]:[%u][%u][%u][%u][%u][%u][%u][%u][%u][%u]",
|
||||
LOG_INF("[%d]:[%u][%u][%u][%u][%u][%u][%u][%u][%u][%u]",
|
||||
i, cis_param->cis_id, cis_param->nse, cis_param->c_sdu,
|
||||
cis_param->p_sdu, cis_param->c_pdu, cis_param->p_pdu,
|
||||
cis_param->c_phy, cis_param->p_phy, cis_param->c_bn,
|
||||
@@ -1638,7 +1580,7 @@ static struct net_buf *hci_le_set_cig_test_params(const struct bt_iso_cig *cig,
|
||||
|
||||
static bool is_advanced_cig_param(const struct bt_iso_cig_param *param)
|
||||
{
|
||||
LOG_DBG("IsAdvancedCigParam[%u][%u][%u]",
|
||||
LOG_INF("IsAdvancedCigParam[%u][%u][%u]",
|
||||
param->c_to_p_ft, param->p_to_c_ft, param->iso_interval);
|
||||
|
||||
if (param->c_to_p_ft != 0U || param->p_to_c_ft != 0U || param->iso_interval != 0U) {
|
||||
@@ -1673,7 +1615,7 @@ static bool is_advanced_cig_param(const struct bt_iso_cig_param *param)
|
||||
|
||||
static struct bt_iso_cig *get_cig(const struct bt_iso_chan *iso_chan)
|
||||
{
|
||||
LOG_DBG("GetCig[%p]", iso_chan);
|
||||
LOG_INF("GetCig[%p]", iso_chan);
|
||||
|
||||
if (iso_chan == NULL || iso_chan->iso == NULL) {
|
||||
return NULL;
|
||||
@@ -1688,19 +1630,19 @@ static struct bt_iso_cig *get_free_cig(void)
|
||||
{
|
||||
/* We can use the index in the `cigs` array as CIG ID */
|
||||
|
||||
LOG_DBG("GetFreeCig");
|
||||
LOG_INF("GetFreeCig");
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(cigs); i++) {
|
||||
if (cigs[i].state == BT_ISO_CIG_STATE_IDLE) {
|
||||
cigs[i].state = BT_ISO_CIG_STATE_CONFIGURED;
|
||||
cigs[i].id = i;
|
||||
sys_slist_init(&cigs[i].cis_channels);
|
||||
LOG_DBG("CigNew[%zu]", i);
|
||||
LOG_INF("CigNew[%zu]", i);
|
||||
return &cigs[i];
|
||||
}
|
||||
}
|
||||
|
||||
LOG_ERR("NoFreeCig");
|
||||
LOG_WRN("NoFreeCig");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1716,7 +1658,7 @@ static bool cis_is_in_cig(const struct bt_iso_cig *cig, const struct bt_iso_chan
|
||||
|
||||
static int cig_init_cis(struct bt_iso_cig *cig, const struct bt_iso_cig_param *param)
|
||||
{
|
||||
LOG_DBG("CigInitCis[%u]", cig->id);
|
||||
LOG_INF("CigInitCis[%u]", cig->id);
|
||||
|
||||
for (uint8_t i = 0; i < param->num_cis; i++) {
|
||||
struct bt_iso_chan *cis = param->cis_channels[i];
|
||||
@@ -1726,7 +1668,7 @@ static int cig_init_cis(struct bt_iso_cig *cig, const struct bt_iso_cig_param *p
|
||||
|
||||
cis->iso = iso_new();
|
||||
if (cis->iso == NULL) {
|
||||
LOG_ERR("NoFreeCis");
|
||||
LOG_WRN("NoFreeCis");
|
||||
return -ENOMEM;
|
||||
}
|
||||
iso_conn = &cis->iso->iso;
|
||||
@@ -1748,7 +1690,7 @@ static void cleanup_cig(struct bt_iso_cig *cig)
|
||||
{
|
||||
struct bt_iso_chan *cis, *tmp;
|
||||
|
||||
LOG_DBG("CleanupCig");
|
||||
LOG_INF("CleanupCig");
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&cig->cis_channels, cis, tmp, node) {
|
||||
if (cis->iso != NULL) {
|
||||
@@ -1818,6 +1760,15 @@ static bool valid_cig_param(const struct bt_iso_cig_param *param, bool advanced,
|
||||
if (cis->qos->tx != NULL && cis->qos->tx->sdu != 0U) {
|
||||
is_c_to_p = true;
|
||||
}
|
||||
|
||||
/* Validate the current CIS, not the cumulative is_*_to_* flags: once an
|
||||
* earlier CIS sets a direction the flags would mask a later CIS that has none.
|
||||
*/
|
||||
if ((cis->qos->rx == NULL || cis->qos->rx->sdu == 0U) &&
|
||||
(cis->qos->tx == NULL || cis->qos->tx->sdu == 0U)) {
|
||||
LOG_ERR("InvNoSduDir[%u]", i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (param->framing != BT_ISO_FRAMING_UNFRAMED && param->framing != BT_ISO_FRAMING_FRAMED) {
|
||||
@@ -1941,7 +1892,7 @@ int bt_iso_cig_create(const struct bt_iso_cig_param *param, struct bt_iso_cig **
|
||||
|
||||
err = cig_init_cis(cig, param);
|
||||
if (err) {
|
||||
LOG_DBG("InitCisFail[%d]", err);
|
||||
LOG_WRN("InitCisFail[%d]", err);
|
||||
cleanup_cig(cig);
|
||||
return err;
|
||||
}
|
||||
@@ -1984,7 +1935,7 @@ int bt_iso_cig_create(const struct bt_iso_cig_param *param, struct bt_iso_cig **
|
||||
|
||||
*out_cig = cig;
|
||||
|
||||
LOG_DBG("OutCig[%u]", cig->id);
|
||||
LOG_INF("OutCig[%u]", cig->id);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -1994,7 +1945,7 @@ static void restore_cig(struct bt_iso_cig *cig, uint8_t existing_num_cis)
|
||||
struct bt_iso_chan *cis, *tmp;
|
||||
sys_snode_t *prev = NULL;
|
||||
|
||||
LOG_DBG("RestoreCig[%u][%u]", cig->id, existing_num_cis);
|
||||
LOG_INF("RestoreCig[%u][%u]", cig->id, existing_num_cis);
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&cig->cis_channels, cis, tmp, node) {
|
||||
/* Remove all newly added by comparing the cis_id to the number
|
||||
@@ -2045,7 +1996,7 @@ int bt_iso_cig_reconfigure(struct bt_iso_cig *cig, const struct bt_iso_cig_param
|
||||
#endif /* CONFIG_BT_ISO_TEST_PARAMS */
|
||||
|
||||
CHECKIF(!valid_cig_param(param, advanced, cig)) {
|
||||
LOG_DBG("InvCigParams");
|
||||
LOG_ERR("InvCigParams");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -2054,7 +2005,7 @@ int bt_iso_cig_reconfigure(struct bt_iso_cig *cig, const struct bt_iso_cig_param
|
||||
|
||||
err = cig_init_cis(cig, param);
|
||||
if (err != 0) {
|
||||
LOG_DBG("InitCisFail[%d]", err);
|
||||
LOG_ERR("InitCisFail[%d]", err);
|
||||
restore_cig(cig, existing_num_cis);
|
||||
return err;
|
||||
}
|
||||
@@ -2111,7 +2062,7 @@ int bt_iso_cig_terminate(struct bt_iso_cig *cig)
|
||||
{
|
||||
int err;
|
||||
|
||||
LOG_DBG("IsoCigTerminate");
|
||||
LOG_INF("IsoCigTerminate");
|
||||
|
||||
CHECKIF(cig == NULL) {
|
||||
LOG_ERR("CigNull");
|
||||
@@ -2140,7 +2091,7 @@ static int hci_le_create_cis(const struct bt_iso_connect_param *param, size_t co
|
||||
struct bt_hci_cp_le_create_cis *req;
|
||||
struct net_buf *buf;
|
||||
|
||||
LOG_DBG("CreateCis[%u]", count);
|
||||
LOG_INF("CreateCis[%u]", count);
|
||||
|
||||
buf = bt_hci_cmd_create(BT_HCI_OP_LE_CREATE_CIS, sizeof(*req) + sizeof(*cis) * count);
|
||||
if (!buf) {
|
||||
@@ -2153,12 +2104,6 @@ static int hci_le_create_cis(const struct bt_iso_connect_param *param, size_t co
|
||||
|
||||
/* Program the cis parameters */
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
struct bt_iso_chan *iso_chan = param[i].iso_chan;
|
||||
|
||||
if (iso_chan->state == BT_ISO_STATE_ENCRYPT_PENDING) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cis = net_buf_add(buf, sizeof(*cis));
|
||||
|
||||
memset(cis, 0, sizeof(*cis));
|
||||
@@ -2168,90 +2113,25 @@ static int hci_le_create_cis(const struct bt_iso_connect_param *param, size_t co
|
||||
req->num_cis++;
|
||||
}
|
||||
|
||||
/* If all CIS are pending for security, do nothing,
|
||||
* but return a recognizable return value
|
||||
*/
|
||||
if (req->num_cis == 0) {
|
||||
net_buf_unref(buf);
|
||||
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CREATE_CIS, buf, NULL);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_SMP)
|
||||
static int iso_chan_connect_security(const struct bt_iso_connect_param *param, size_t count)
|
||||
{
|
||||
/* conn_idx_handled is an array of booleans for which conn indexes
|
||||
* already have been used to call bt_conn_set_security.
|
||||
* Using indexes avoids looping the array when checking if it has been
|
||||
* handled.
|
||||
*/
|
||||
bool conn_idx_handled[CONFIG_BT_MAX_CONN];
|
||||
|
||||
LOG_DBG("IsoChanConnectSec[%u]", count);
|
||||
|
||||
memset(conn_idx_handled, false, sizeof(conn_idx_handled));
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
struct bt_iso_chan *iso_chan = param[i].iso_chan;
|
||||
struct bt_conn *acl = param[i].acl;
|
||||
uint8_t conn_idx = bt_conn_index(acl);
|
||||
|
||||
LOG_DBG("SecLevel[%zu][%u][%u]",
|
||||
i, acl->sec_level, iso_chan->required_sec_level);
|
||||
|
||||
if (acl->sec_level < iso_chan->required_sec_level) {
|
||||
if (!conn_idx_handled[conn_idx]) {
|
||||
int err;
|
||||
|
||||
err = bt_conn_set_security(acl, iso_chan->required_sec_level);
|
||||
if (err != 0) {
|
||||
LOG_ERR("SetSecFail[%zu][%d]", i, err);
|
||||
|
||||
/* Restore states */
|
||||
for (size_t j = 0; j < i; j++) {
|
||||
iso_chan = param[j].iso_chan;
|
||||
|
||||
if (iso_chan->state == BT_ISO_STATE_ENCRYPT_PENDING) {
|
||||
bt_iso_cleanup_acl(iso_chan->iso);
|
||||
bt_iso_chan_set_state(iso_chan,
|
||||
BT_ISO_STATE_DISCONNECTED);
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
conn_idx_handled[conn_idx] = true;
|
||||
}
|
||||
|
||||
iso_chan->iso->iso.acl = bt_conn_ref(acl);
|
||||
bt_iso_chan_set_state(iso_chan, BT_ISO_STATE_ENCRYPT_PENDING);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_BT_SMP */
|
||||
|
||||
static bool iso_chans_connecting(void)
|
||||
{
|
||||
LOG_DBG("IsoChansConnecting");
|
||||
LOG_INF("IsoChansConnecting");
|
||||
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(iso_conns); i++) {
|
||||
const struct bt_conn *iso = &iso_conns[i];
|
||||
const struct bt_iso_chan *iso_chan;
|
||||
|
||||
if (!(iso->iso.info.type == BT_ISO_CHAN_TYPE_CENTRAL ||
|
||||
iso->iso.info.type == BT_ISO_CHAN_TYPE_PERIPHERAL)) {
|
||||
iso->iso.info.type == BT_ISO_CHAN_TYPE_PERIPHERAL)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
iso_chan = iso_chan(iso);
|
||||
if (iso_chan != NULL &&
|
||||
(iso_chan->state == BT_ISO_STATE_CONNECTING ||
|
||||
iso_chan->state == BT_ISO_STATE_ENCRYPT_PENDING)) {
|
||||
iso_chan->state == BT_ISO_STATE_CONNECTING) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -2263,7 +2143,7 @@ int bt_iso_chan_connect(const struct bt_iso_connect_param *param, size_t count)
|
||||
{
|
||||
int err;
|
||||
|
||||
LOG_DBG("IsoChanConnect[%u]", count);
|
||||
LOG_INF("IsoChanConnect[%u]", count);
|
||||
|
||||
CHECKIF(param == NULL) {
|
||||
LOG_ERR("ParamNull");
|
||||
@@ -2313,23 +2193,8 @@ int bt_iso_chan_connect(const struct bt_iso_connect_param *param, size_t count)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_SMP)
|
||||
/* Check for and initiate security for all channels that have
|
||||
* requested encryption if the ACL link is not already secured
|
||||
*/
|
||||
err = iso_chan_connect_security(param, count);
|
||||
if (err != 0) {
|
||||
LOG_ERR("InitSecForCisFail[%d]", err);
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_SMP */
|
||||
|
||||
err = hci_le_create_cis(param, count);
|
||||
if (err == -ECANCELED) {
|
||||
LOG_DBG("CisPendingOnSec");
|
||||
|
||||
return 0;
|
||||
} else if (err != 0) {
|
||||
if (err != 0) {
|
||||
LOG_ERR("ConnectCisFail[%d]", err);
|
||||
|
||||
return err;
|
||||
@@ -2340,10 +2205,6 @@ int bt_iso_chan_connect(const struct bt_iso_connect_param *param, size_t count)
|
||||
struct bt_iso_chan *iso_chan = param[i].iso_chan;
|
||||
struct bt_iso_cig *cig;
|
||||
|
||||
if (iso_chan->state == BT_ISO_STATE_ENCRYPT_PENDING) {
|
||||
continue;
|
||||
}
|
||||
|
||||
iso_chan->iso->iso.acl = bt_conn_ref(param[i].acl);
|
||||
bt_conn_set_state(iso_chan->iso, BT_CONN_INITIATING);
|
||||
bt_iso_chan_set_state(iso_chan, BT_ISO_STATE_CONNECTING);
|
||||
@@ -2379,12 +2240,12 @@ static struct bt_iso_big *get_free_big(void)
|
||||
if (!atomic_test_and_set_bit(bigs[i].flags, BT_BIG_INITIALIZED)) {
|
||||
bigs[i].handle = i;
|
||||
sys_slist_init(&bigs[i].bis_channels);
|
||||
LOG_DBG("BigNew[%u]", i);
|
||||
LOG_INF("BigNew[%u]", i);
|
||||
return &bigs[i];
|
||||
}
|
||||
}
|
||||
|
||||
LOG_ERR("NoFreeBig");
|
||||
LOG_WRN("NoFreeBig");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -2428,7 +2289,7 @@ static void big_disconnect(struct bt_iso_big *big, uint8_t reason)
|
||||
{
|
||||
struct bt_iso_chan *bis;
|
||||
|
||||
LOG_DBG("BigDisconnect[%02x]", reason);
|
||||
LOG_INF("BigDisconnect[%02x]", reason);
|
||||
|
||||
atomic_set_bit(big->flags, BT_BIG_BUSY);
|
||||
|
||||
@@ -2457,13 +2318,13 @@ static void big_disconnect(struct bt_iso_big *big, uint8_t reason)
|
||||
static int big_init_bis(struct bt_iso_big *big, struct bt_iso_chan *bis, uint8_t bis_number,
|
||||
bool broadcaster)
|
||||
{
|
||||
LOG_DBG("BigInitBis[%u][%u][%u]", big->handle, bis_number, broadcaster);
|
||||
LOG_INF("BigInitBis[%u][%u][%u]", big->handle, bis_number, broadcaster);
|
||||
|
||||
struct bt_conn_iso *iso_conn;
|
||||
|
||||
bis->iso = iso_new();
|
||||
if (bis->iso == NULL) {
|
||||
LOG_ERR("NoFreeBis");
|
||||
LOG_WRN("NoFreeBis");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -2494,13 +2355,13 @@ static int big_init_bis(struct bt_iso_big *big, struct bt_iso_chan *bis, uint8_t
|
||||
int bt_iso_big_register_cb(struct bt_iso_big_cb *cb)
|
||||
{
|
||||
CHECKIF(cb == NULL) {
|
||||
LOG_DBG("BigCbNull");
|
||||
LOG_ERR("BigCbNull");
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (sys_slist_find(&iso_big_cbs, &cb->_node, NULL)) {
|
||||
LOG_DBG("BigCbAlreadyReg[%p]", cb);
|
||||
LOG_WRN("BigCbAlreadyReg[%p]", cb);
|
||||
|
||||
return -EEXIST;
|
||||
}
|
||||
@@ -2520,7 +2381,7 @@ static int hci_le_create_big(struct bt_le_ext_adv *padv, struct bt_iso_big *big,
|
||||
int err;
|
||||
struct bt_iso_chan *bis;
|
||||
|
||||
LOG_DBG("CreateBig");
|
||||
LOG_INF("CreateBig");
|
||||
|
||||
buf = bt_hci_cmd_create(BT_HCI_OP_LE_CREATE_BIG, sizeof(*req));
|
||||
|
||||
@@ -2552,12 +2413,12 @@ static int hci_le_create_big(struct bt_le_ext_adv *padv, struct bt_iso_big *big,
|
||||
memset(req->bcode, 0, sizeof(req->bcode));
|
||||
}
|
||||
|
||||
LOG_DBG("[%u][%u][%u][%u][%u][%u][%u][%u][%u][%u][%u]",
|
||||
LOG_INF("[%u][%u][%u][%u][%u][%u][%u][%u][%u][%u][%u]",
|
||||
req->big_handle, req->adv_handle, req->num_bis, param->interval,
|
||||
req->max_sdu, req->max_latency, req->rtn, req->phy, req->packing,
|
||||
req->framing, req->encryption);
|
||||
if (req->encryption) {
|
||||
LOG_DBG("[%s]", bt_hex(req->bcode, sizeof(req->bcode)));
|
||||
LOG_INF("[%s]", bt_hex(req->bcode, sizeof(req->bcode)));
|
||||
}
|
||||
|
||||
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_CREATE_BIG, buf, NULL);
|
||||
@@ -2583,7 +2444,7 @@ static int hci_le_create_big_test(const struct bt_le_ext_adv *padv, struct bt_is
|
||||
struct net_buf *buf;
|
||||
int err;
|
||||
|
||||
LOG_DBG("CreateBigTest");
|
||||
LOG_INF("CreateBigTest");
|
||||
|
||||
buf = bt_hci_cmd_create(BT_HCI_OP_LE_CREATE_BIG_TEST, sizeof(*req));
|
||||
|
||||
@@ -2619,13 +2480,13 @@ static int hci_le_create_big_test(const struct bt_le_ext_adv *padv, struct bt_is
|
||||
memset(req->bcode, 0, sizeof(req->bcode));
|
||||
}
|
||||
|
||||
LOG_DBG("[%u][%u][%u][%u][%u][%u][%u][%u][%u][%u][%u][%u][%u][%u][%u]",
|
||||
LOG_INF("[%u][%u][%u][%u][%u][%u][%u][%u][%u][%u][%u][%u][%u][%u][%u]",
|
||||
req->big_handle, req->adv_handle, req->num_bis, param->interval,
|
||||
param->iso_interval, req->nse, req->max_sdu, req->max_pdu,
|
||||
req->phy, req->packing, req->framing, req->bn, req->irc,
|
||||
req->pto, req->encryption);
|
||||
if (req->encryption) {
|
||||
LOG_DBG("[%s]", bt_hex(req->bcode, sizeof(req->bcode)));
|
||||
LOG_INF("[%s]", bt_hex(req->bcode, sizeof(req->bcode)));
|
||||
}
|
||||
|
||||
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_CREATE_BIG_TEST, buf, NULL);
|
||||
@@ -2642,7 +2503,7 @@ static int hci_le_create_big_test(const struct bt_le_ext_adv *padv, struct bt_is
|
||||
|
||||
static bool is_advanced_big_param(const struct bt_iso_big_create_param *param)
|
||||
{
|
||||
LOG_DBG("IsAdvancedBigParam[%u][%u]", param->irc, param->iso_interval);
|
||||
LOG_INF("IsAdvancedBigParam[%u][%u]", param->irc, param->iso_interval);
|
||||
|
||||
if (param->irc != 0U || param->iso_interval != 0U) {
|
||||
return true;
|
||||
@@ -2823,7 +2684,7 @@ int bt_iso_big_create(struct bt_le_ext_adv *padv, struct bt_iso_big_create_param
|
||||
|
||||
err = big_init_bis(big, bis_channels[i], bis_number, true);
|
||||
if (err != 0) {
|
||||
LOG_DBG("InitBisFail[%u][%d]", i, err);
|
||||
LOG_ERR("InitBisFail[%u][%d]", i, err);
|
||||
cleanup_big(big);
|
||||
|
||||
return err;
|
||||
@@ -2848,7 +2709,7 @@ int bt_iso_big_create(struct bt_le_ext_adv *padv, struct bt_iso_big_create_param
|
||||
|
||||
*out_big = big;
|
||||
|
||||
LOG_DBG("OutBig[%u]", big->handle);
|
||||
LOG_INF("OutBig[%u]", big->handle);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -2877,7 +2738,7 @@ static void store_bis_broadcaster_info(const struct bt_hci_evt_le_big_complete *
|
||||
info->can_send = true;
|
||||
info->can_recv = false;
|
||||
|
||||
LOG_DBG("StoreBisInfo[%u]", broadcaster_info->pto);
|
||||
LOG_INF("StoreBisInfo[%u]", broadcaster_info->pto);
|
||||
}
|
||||
|
||||
void hci_le_big_complete(struct net_buf *buf)
|
||||
@@ -2887,8 +2748,8 @@ void hci_le_big_complete(struct net_buf *buf)
|
||||
struct bt_iso_big *big;
|
||||
int i;
|
||||
|
||||
LOG_DBG("BigComp");
|
||||
LOG_DBG("Evt[%02x][%u][%u][%u][%u][%u][%u][%u][%u][%u][%u][%u]",
|
||||
LOG_INF("BigComp");
|
||||
LOG_INF("Evt[%02x][%u][%u][%u][%u][%u][%u][%u][%u][%u][%u][%u]",
|
||||
evt->status, evt->big_handle, sys_get_le24(evt->sync_delay),
|
||||
sys_get_le24(evt->latency), evt->phy, evt->nse, evt->bn,
|
||||
evt->pto, evt->irc, evt->max_pdu, evt->iso_interval,
|
||||
@@ -2925,7 +2786,7 @@ void hci_le_big_complete(struct net_buf *buf)
|
||||
const uint16_t handle = evt->handle[i++];
|
||||
struct bt_conn *iso_conn = bis->iso;
|
||||
|
||||
LOG_DBG("BisHdl[%04x]", handle);
|
||||
LOG_INF("BisHdl[%04x]", handle);
|
||||
|
||||
iso_conn->handle = sys_le16_to_cpu(handle);
|
||||
store_bis_broadcaster_info(evt, iso_conn);
|
||||
@@ -2950,7 +2811,7 @@ void hci_le_big_terminate(struct net_buf *buf)
|
||||
struct bt_hci_evt_le_big_terminate *evt = (void *)buf->data;
|
||||
struct bt_iso_big *big;
|
||||
|
||||
LOG_DBG("BigTerminateEvt[%u][%02x]", evt->big_handle, evt->reason);
|
||||
LOG_INF("BigTerminateEvt[%u][%02x]", evt->big_handle, evt->reason);
|
||||
|
||||
if (evt->big_handle >= ARRAY_SIZE(bigs)) {
|
||||
LOG_ERR("InvBigHdl[%u][%u]", evt->big_handle, ARRAY_SIZE(bigs));
|
||||
@@ -3041,7 +2902,7 @@ int bt_iso_big_terminate(struct bt_iso_big *big)
|
||||
}
|
||||
|
||||
if (atomic_test_bit(big->flags, BT_BIG_BUSY)) {
|
||||
LOG_DBG("BigBusy[%u]", big->handle);
|
||||
LOG_WRN("BigBusy[%u]", big->handle);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
@@ -3111,8 +2972,8 @@ void hci_le_big_sync_established(struct net_buf *buf)
|
||||
struct bt_iso_big *big;
|
||||
int i;
|
||||
|
||||
LOG_DBG("BigSyncEstab");
|
||||
LOG_DBG("Evt[%02x][%u][%u][%u][%u][%u][%u][%u][%u][%u]",
|
||||
LOG_INF("BigSyncEstab");
|
||||
LOG_INF("Evt[%02x][%u][%u][%u][%u][%u][%u][%u][%u][%u]",
|
||||
evt->status, evt->big_handle, sys_get_le24(evt->latency),
|
||||
evt->nse, evt->bn, evt->pto, evt->irc, evt->max_pdu,
|
||||
evt->iso_interval, evt->num_bis);
|
||||
@@ -3148,7 +3009,7 @@ void hci_le_big_sync_established(struct net_buf *buf)
|
||||
const uint16_t handle = evt->handle[i++];
|
||||
struct bt_conn *iso_conn = bis->iso;
|
||||
|
||||
LOG_DBG("BisHdl[%04x]", handle);
|
||||
LOG_INF("BisHdl[%04x]", handle);
|
||||
|
||||
iso_conn->handle = sys_le16_to_cpu(handle);
|
||||
store_bis_sync_receiver_info(evt, iso_conn);
|
||||
@@ -3173,7 +3034,7 @@ void hci_le_big_sync_lost(struct net_buf *buf)
|
||||
struct bt_hci_evt_le_big_sync_lost *evt = (void *)buf->data;
|
||||
struct bt_iso_big *big;
|
||||
|
||||
LOG_DBG("BigSyncLostEvt[%u][%02x]", evt->big_handle, evt->reason);
|
||||
LOG_INF("BigSyncLostEvt[%u][%02x]", evt->big_handle, evt->reason);
|
||||
|
||||
if (evt->big_handle >= ARRAY_SIZE(bigs)) {
|
||||
LOG_ERR("InvBigHdl[%u][%u]", evt->big_handle, ARRAY_SIZE(bigs));
|
||||
@@ -3195,7 +3056,7 @@ static int hci_le_big_create_sync(const struct bt_le_per_adv_sync *sync, struct
|
||||
int err;
|
||||
uint8_t bit_idx = 0;
|
||||
|
||||
LOG_DBG("BigCreateSync[%u][%u]", big->handle, big->num_bis);
|
||||
LOG_INF("BigCreateSync[%u][%u]", big->handle, big->num_bis);
|
||||
|
||||
buf = bt_hci_cmd_create(BT_HCI_OP_LE_BIG_CREATE_SYNC, sizeof(*req) + big->num_bis);
|
||||
if (!buf) {
|
||||
@@ -3346,7 +3207,7 @@ int bt_iso_big_sync(struct bt_le_per_adv_sync *sync, struct bt_iso_big_sync_para
|
||||
*/
|
||||
err = big_init_bis(big, bis_channels[i], bis_number, false);
|
||||
if (err != 0) {
|
||||
LOG_DBG("InitBisFail[%u]: %d", i, err);
|
||||
LOG_ERR("InitBisFail[%u]: %d", i, err);
|
||||
cleanup_big(big);
|
||||
|
||||
return err;
|
||||
@@ -3357,7 +3218,7 @@ int bt_iso_big_sync(struct bt_le_per_adv_sync *sync, struct bt_iso_big_sync_para
|
||||
|
||||
err = hci_le_big_create_sync(sync, big, param);
|
||||
if (err) {
|
||||
LOG_DBG("CreateBigSyncFail[%d]", err);
|
||||
LOG_ERR("CreateBigSyncFail[%d]", err);
|
||||
cleanup_big(big);
|
||||
return err;
|
||||
}
|
||||
@@ -3368,7 +3229,7 @@ int bt_iso_big_sync(struct bt_le_per_adv_sync *sync, struct bt_iso_big_sync_para
|
||||
|
||||
*out_big = big;
|
||||
|
||||
LOG_DBG("OutBig[%u]", big->handle);
|
||||
LOG_INF("OutBig[%u]", big->handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ typedef enum __packed {
|
||||
struct bt_conn_le {
|
||||
bt_addr_le_t dst;
|
||||
|
||||
uint16_t interval;
|
||||
uint32_t interval_us;
|
||||
|
||||
/** @brief Remote LE features
|
||||
*
|
||||
@@ -114,5 +114,7 @@ bool bt_conn_is_peer_addr_le(const struct bt_conn *conn, uint8_t id,
|
||||
*/
|
||||
#define BT_CONN_INDEX_INVALID 0xff
|
||||
|
||||
struct bt_conn *bt_conn_lookup_index(uint8_t index);
|
||||
|
||||
/* Set connection object in certain state and perform action related to state */
|
||||
void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state);
|
||||
|
||||
@@ -112,7 +112,7 @@ struct bt_conn_le_info {
|
||||
* Address (RPA) before identity has been resolved.
|
||||
*/
|
||||
const bt_addr_le_t *dst;
|
||||
uint16_t interval; /**< Connection interval */
|
||||
uint32_t interval_us; /**< Connection interval in microseconds */
|
||||
};
|
||||
|
||||
/** @brief Convert connection interval to milliseconds
|
||||
|
||||
@@ -182,8 +182,6 @@ extern "C" {
|
||||
enum bt_iso_state {
|
||||
/** Channel disconnected */
|
||||
BT_ISO_STATE_DISCONNECTED,
|
||||
/** Channel is pending ACL encryption before connecting */
|
||||
BT_ISO_STATE_ENCRYPT_PENDING,
|
||||
/** Channel in connecting state */
|
||||
BT_ISO_STATE_CONNECTING,
|
||||
/** Channel ready for upper layer traffic on it */
|
||||
@@ -213,17 +211,6 @@ struct bt_iso_chan {
|
||||
struct bt_iso_chan_qos *qos;
|
||||
/** Channel state */
|
||||
enum bt_iso_state state;
|
||||
/**
|
||||
* @brief The required security level of the channel
|
||||
*
|
||||
* This value can be set as the central before connecting a CIS
|
||||
* with bt_iso_chan_connect().
|
||||
* The value is overwritten to @ref bt_iso_server::sec_level for the
|
||||
* peripheral once a channel has been accepted.
|
||||
*
|
||||
* Only available when @kconfig{CONFIG_BT_SMP} is enabled.
|
||||
*/
|
||||
bt_security_t required_sec_level;
|
||||
/** @internal Node used internally by the stack */
|
||||
sys_snode_t node;
|
||||
};
|
||||
@@ -783,13 +770,6 @@ struct bt_iso_accept_info {
|
||||
|
||||
/** @brief ISO Server structure. */
|
||||
struct bt_iso_server {
|
||||
/**
|
||||
* @brief Required minimum security level.
|
||||
*
|
||||
* Only available when @kconfig{CONFIG_BT_SMP} is enabled.
|
||||
*/
|
||||
bt_security_t sec_level;
|
||||
|
||||
/**
|
||||
* @brief Server accept callback
|
||||
*
|
||||
|
||||
@@ -120,7 +120,6 @@ static esp_ble_iso_chan_qos_t iso_qos = {
|
||||
static esp_ble_iso_chan_t iso_chan = {
|
||||
.ops = &iso_ops,
|
||||
.qos = &iso_qos,
|
||||
.required_sec_level = SECURITY_LEVEL,
|
||||
};
|
||||
|
||||
static void create_cig_and_cis(uint16_t acl_handle)
|
||||
@@ -253,8 +252,8 @@ static void acl_connect(esp_ble_iso_gap_app_event_t *event)
|
||||
event->acl_connect.conn_handle, event->acl_connect.role,
|
||||
EXAMPLE_BT_ADDR_PRINT_ARGS(event->acl_connect.dst.val));
|
||||
|
||||
if (iso_chan.required_sec_level == ESP_BLE_ISO_SECURITY_NO_MITM ||
|
||||
iso_chan.required_sec_level == ESP_BLE_ISO_SECURITY_MITM) {
|
||||
if (SECURITY_LEVEL == ESP_BLE_ISO_SECURITY_NO_MITM ||
|
||||
SECURITY_LEVEL == ESP_BLE_ISO_SECURITY_MITM) {
|
||||
err = pairing_start(event->acl_connect.conn_handle);
|
||||
if (err) {
|
||||
ESP_LOGE(TAG, "Failed to initiate security, err %d", err);
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
|
||||
#include "peripheral.h"
|
||||
|
||||
#define SECURITY_LEVEL ESP_BLE_ISO_SECURITY_NO_MITM
|
||||
|
||||
#define CIS_SDU_SIZE 120
|
||||
|
||||
static uint8_t ext_adv_data[3 + 2 + LOCAL_DEVICE_NAME_LEN];
|
||||
@@ -95,7 +93,6 @@ static int iso_accept(const esp_ble_iso_accept_info_t *info,
|
||||
}
|
||||
|
||||
static esp_ble_iso_server_t iso_server = {
|
||||
.sec_level = SECURITY_LEVEL,
|
||||
.accept = iso_accept,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user