|
|
|
@@ -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;
|
|
|
|
|
}
|
|
|
|
|