feat(ble_audio): Support Zephyr LE Audio v4.4.1

This commit is contained in:
Liu Linyan
2026-06-30 15:17:24 +08:00
committed by Linyan Liu
parent 1e58083bdf
commit 9b415a7d1f
29 changed files with 525 additions and 398 deletions
@@ -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);
}
+10 -1
View File
@@ -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)
{
+96 -235
View File
@@ -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
*