Bluetooth: controller: Create HCI stubs for CIG/CIS and ISO tests

Put infrastructure for the following HCI commands/events in place:
* LE Setup ISO Data Path command
* LE Remove ISO Data Path command
* Configure Data Path command
* LE Set CIG Parameters Test command
* LE ISO Read Test Counters command
* LE ISO Receive Test command
* LE ISO Test End command
* LE ISO Transmit Test command

Signed-off-by: Asger Munk Nielsen <asmk@oticon.com>
This commit is contained in:
Asger Munk Nielsen 2020-11-13 14:28:27 +01:00 committed by Carles Cufí
commit 3df64a306b
6 changed files with 506 additions and 0 deletions

View file

@ -568,6 +568,18 @@ struct bt_hci_rp_write_auth_payload_timeout {
uint16_t handle;
} __packed;
#define BT_HCI_OP_CONFIGURE_DATA_PATH BT_OP(BT_OGF_BASEBAND, 0x0083)
struct bt_hci_cp_configure_data_path {
uint8_t data_path_dir;
uint8_t data_path_id;
uint8_t vs_config_len;
uint8_t vs_config[0];
} __packed;
struct bt_hci_rp_configure_data_path {
uint8_t status;
} __packed;
/* HCI version from Assigned Numbers */
#define BT_HCI_VERSION_1_0B 0
#define BT_HCI_VERSION_1_1 1
@ -1459,6 +1471,39 @@ struct bt_hci_rp_le_set_cig_params {
} __packed;
#define BT_HCI_OP_LE_SET_CIG_PARAMS_TEST BT_OP(BT_OGF_LE, 0x0063)
struct bt_hci_cis_params_test {
uint8_t cis_id;
uint8_t nse;
uint16_t m_sdu;
uint16_t s_sdu;
uint16_t m_pdu;
uint16_t s_pdu;
uint8_t m_phy;
uint8_t s_phy;
uint8_t m_bn;
uint8_t s_bn;
} __packed;
struct bt_hci_cp_le_set_cig_params_test {
uint8_t cig_id;
uint8_t m_interval[3];
uint8_t s_interval[3];
uint8_t m_ft;
uint8_t s_ft;
uint16_t iso_interval;
uint8_t sca;
uint8_t packing;
uint8_t framing;
uint8_t num_cis;
struct bt_hci_cis_params_test cis[0];
} __packed;
struct bt_hci_rp_le_set_cig_params_test {
uint8_t status;
uint8_t cig_id;
uint8_t num_handles;
uint16_t handle[0];
} __packed;
#define BT_HCI_OP_LE_CREATE_CIS BT_OP(BT_OGF_LE, 0x0064)
struct bt_hci_cis {
@ -1596,12 +1641,52 @@ struct bt_hci_rp_le_remove_iso_path {
} __packed;
#define BT_HCI_OP_LE_ISO_TRANSMIT_TEST BT_OP(BT_OGF_LE, 0x0070)
struct bt_hci_cp_le_iso_transmit_test {
uint16_t handle;
uint8_t payload_type;
} __packed;
struct bt_hci_rp_le_iso_transmit_test {
uint8_t status;
uint16_t handle;
} __packed;
#define BT_HCI_OP_LE_ISO_RECEIVE_TEST BT_OP(BT_OGF_LE, 0x0071)
struct bt_hci_cp_le_iso_receive_test {
uint16_t handle;
uint8_t payload_type;
} __packed;
struct bt_hci_rp_le_iso_receive_test {
uint8_t status;
uint16_t handle;
} __packed;
#define BT_HCI_OP_LE_ISO_READ_TEST_COUNTERS BT_OP(BT_OGF_LE, 0x0072)
struct bt_hci_cp_le_read_test_counters {
uint16_t handle;
} __packed;
struct bt_hci_rp_le_read_test_counters {
uint8_t status;
uint16_t handle;
uint32_t received_cnt;
uint32_t missed_cnt;
uint32_t failed_cnt;
} __packed;
#define BT_HCI_OP_LE_ISO_TEST_END BT_OP(BT_OGF_LE, 0x0073)
struct bt_hci_cp_le_iso_test_end {
uint16_t handle;
} __packed;
struct bt_hci_rp_le_iso_test_end {
uint8_t status;
uint16_t handle;
uint32_t received_cnt;
uint32_t missed_cnt;
uint32_t failed_cnt;
} __packed;
#define BT_HCI_OP_LE_SET_HOST_FEATURE BT_OP(BT_OGF_LE, 0x0074)
struct bt_hci_cp_le_set_host_feature {

View file

@ -84,6 +84,14 @@ if(CONFIG_BT_LL_SW_SPLIT)
)
endif()
endif()
if(CONFIG_BT_CTLR_ADV_ISO OR
CONFIG_BT_CTLR_SYNC_ISO OR
CONFIG_BT_CTLR_PERIPHERAL_ISO OR
CONFIG_BT_CTLR_CENTRAL_ISO)
zephyr_library_sources(
ll_sw/ull_iso.c
)
endif()
if(CONFIG_BT_CONN OR
CONFIG_BT_CTLR_ADV_PERIODIC OR
CONFIG_BT_CTLR_SYNC_PERIODIC)

View file

@ -476,6 +476,29 @@ static void write_auth_payload_timeout(struct net_buf *buf,
}
#endif /* CONFIG_BT_CTLR_LE_PING */
#if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) || \
defined(CONFIG_BT_CTLR_CENTRAL_ISO)
static void configure_data_path(struct net_buf *buf,
struct net_buf **evt)
{
struct bt_hci_cp_configure_data_path *cmd = (void *)buf->data;
struct bt_hci_rp_configure_data_path *rp;
uint8_t *vs_config;
uint8_t status;
vs_config = &cmd->vs_config[0];
status = ll_configure_data_path(cmd->data_path_dir,
cmd->data_path_id,
cmd->vs_config_len,
vs_config);
rp = hci_cmd_complete(evt, sizeof(*rp));
rp->status = status;
}
#endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO || CONFIG_BT_CTLR_CENTRAL_ISO */
#if defined(CONFIG_BT_CONN)
static void read_tx_power_level(struct net_buf *buf, struct net_buf **evt)
{
@ -544,6 +567,13 @@ static int ctrl_bb_cmd_handle(uint16_t ocf, struct net_buf *cmd,
break;
#endif /* CONFIG_BT_CTLR_LE_PING */
#if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) || \
defined(CONFIG_BT_CTLR_CENTRAL_ISO)
case BT_OCF(BT_HCI_OP_CONFIGURE_DATA_PATH):
configure_data_path(cmd, evt);
break;
#endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO || CONFIG_BT_CTLR_CENTRAL_ISO */
default:
return -EINVAL;
}
@ -1363,6 +1393,67 @@ static void le_set_cig_parameters(struct net_buf *buf, struct net_buf **evt)
rp->status = status;
}
static void le_set_cig_params_test(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_set_cig_params_test *cmd = (void *)buf->data;
struct bt_hci_rp_le_set_cig_params_test *rp;
uint32_t m_interval;
uint32_t s_interval;
uint16_t iso_interval;
uint8_t status;
uint8_t i;
m_interval = sys_get_le24(cmd->m_interval);
s_interval = sys_get_le24(cmd->s_interval);
iso_interval = sys_le16_to_cpu(cmd->iso_interval);
/* Create CIG or start modifying existing CIG */
status = ll_cig_parameters_test_open(cmd->cig_id, m_interval,
s_interval, cmd->m_ft,
cmd->s_ft, iso_interval,
cmd->sca, cmd->packing,
cmd->framing,
cmd->num_cis);
rp = hci_cmd_complete(evt, sizeof(*rp) +
cmd->num_cis * sizeof(uint16_t));
rp->cig_id = cmd->cig_id;
rp->num_handles = cmd->num_cis;
/* Configure individual CISes */
for (i = 0; !status && i < cmd->num_cis; i++) {
struct bt_hci_cis_params_test *params = cmd->cis;
uint16_t handle;
uint16_t m_sdu;
uint16_t s_sdu;
uint16_t m_pdu;
uint16_t s_pdu;
m_sdu = sys_le16_to_cpu(params->m_sdu);
s_sdu = sys_le16_to_cpu(params->s_sdu);
m_pdu = sys_le16_to_cpu(params->m_pdu);
s_pdu = sys_le16_to_cpu(params->s_pdu);
status = ll_cis_parameters_test_set(params->cis_id,
m_sdu, s_sdu,
m_pdu, s_pdu,
params->m_phy,
params->s_phy,
params->m_bn,
params->s_bn,
&handle);
rp->handle[i] = sys_cpu_to_le16(handle);
}
/* Only apply parameters if all went well */
if (!status) {
status = ll_cig_parameters_commit(cmd->cig_id);
}
rp->status = status;
}
static void le_create_cis(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_create_cis *cmd = (void *)buf->data;
@ -1425,6 +1516,128 @@ static void le_remove_cig(struct net_buf *buf, struct net_buf **evt)
#endif /* CONFIG_BT_CENTRAL */
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO) || \
defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
static void le_setup_iso_path(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_setup_iso_path *cmd = (void *)buf->data;
struct bt_hci_rp_le_setup_iso_path *rp;
uint8_t status;
uint16_t handle;
uint16_t company_id;
uint16_t vendor_id;
uint32_t controller_delay;
uint8_t *codec_config;
handle = sys_le16_to_cpu(cmd->handle);
company_id = sys_le16_to_cpu(cmd->company_id);
vendor_id = sys_le16_to_cpu(cmd->vendor_id);
controller_delay = sys_get_le24(cmd->controller_delay);
codec_config = &cmd->codec_config[0];
status = ll_setup_iso_path(handle, cmd->path_dir, cmd->path_id,
cmd->coding_format, company_id, vendor_id,
controller_delay, cmd->codec_config_len,
codec_config);
rp = hci_cmd_complete(evt, sizeof(*rp));
rp->status = status;
rp->handle = cmd->handle;
}
static void le_remove_iso_path(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_remove_iso_path *cmd = (void *)buf->data;
struct bt_hci_rp_le_remove_iso_path *rp;
uint8_t status;
uint16_t handle;
handle = sys_le16_to_cpu(cmd->handle);
status = ll_remove_iso_path(handle, cmd->path_dir);
rp = hci_cmd_complete(evt, sizeof(*rp));
rp->status = status;
rp->handle = cmd->handle;
}
static void le_iso_receive_test(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_iso_receive_test *cmd = (void *)buf->data;
struct bt_hci_rp_le_iso_receive_test *rp;
uint8_t status;
uint16_t handle;
handle = sys_le16_to_cpu(cmd->handle);
status = ll_iso_receive_test(handle, cmd->payload_type);
rp = hci_cmd_complete(evt, sizeof(*rp));
rp->status = status;
rp->handle = cmd->handle;
}
static void le_iso_transmit_test(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_iso_transmit_test *cmd = (void *)buf->data;
struct bt_hci_rp_le_iso_transmit_test *rp;
uint8_t status;
uint16_t handle;
handle = sys_le16_to_cpu(cmd->handle);
status = ll_iso_transmit_test(handle, cmd->payload_type);
rp = hci_cmd_complete(evt, sizeof(*rp));
rp->status = status;
rp->handle = cmd->handle;
}
static void le_iso_test_end(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_iso_test_end *cmd = (void *)buf->data;
struct bt_hci_rp_le_iso_test_end *rp;
uint8_t status;
uint16_t handle;
uint32_t received_cnt;
uint32_t missed_cnt;
uint32_t failed_cnt;
handle = sys_le16_to_cpu(cmd->handle);
status = ll_iso_test_end(handle, &received_cnt, &missed_cnt,
&failed_cnt);
rp = hci_cmd_complete(evt, sizeof(*rp));
rp->status = status;
rp->handle = cmd->handle;
rp->received_cnt = sys_cpu_to_le32(received_cnt);
rp->missed_cnt = sys_cpu_to_le32(missed_cnt);
rp->failed_cnt = sys_cpu_to_le32(failed_cnt);
}
static void le_iso_read_test_counters(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_read_test_counters *cmd = (void *)buf->data;
struct bt_hci_rp_le_read_test_counters *rp;
uint8_t status;
uint16_t handle;
uint32_t received_cnt;
uint32_t missed_cnt;
uint32_t failed_cnt;
handle = sys_le16_to_cpu(cmd->handle);
status = ll_iso_read_test_counters(handle, &received_cnt,
&missed_cnt, &failed_cnt);
rp = hci_cmd_complete(evt, sizeof(*rp));
rp->status = status;
rp->handle = cmd->handle;
rp->received_cnt = sys_cpu_to_le32(received_cnt);
rp->missed_cnt = sys_cpu_to_le32(missed_cnt);
rp->failed_cnt = sys_cpu_to_le32(failed_cnt);
}
#endif /* CONFIG_BT_CTLR_CENTRAL_ISO || CONFIG_BT_CTLR_PERIPHERAL_ISO */
#if defined(CONFIG_BT_PERIPHERAL)
#if defined(CONFIG_BT_CTLR_LE_ENC)
static void le_ltk_req_reply(struct net_buf *buf, struct net_buf **evt)
@ -2606,6 +2819,9 @@ static int controller_cmd_handle(uint16_t ocf, struct net_buf *cmd,
case BT_OCF(BT_HCI_OP_LE_SET_CIG_PARAMS):
le_set_cig_parameters(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_SET_CIG_PARAMS_TEST):
le_set_cig_params_test(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_CREATE_CIS):
le_create_cis(cmd, evt);
break;
@ -2636,6 +2852,34 @@ static int controller_cmd_handle(uint16_t ocf, struct net_buf *cmd,
#endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO */
#endif /* CONFIG_BT_PERIPHERAL */
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO) || \
defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
case BT_OCF(BT_HCI_OP_LE_SETUP_ISO_PATH):
le_setup_iso_path(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_REMOVE_ISO_PATH):
le_remove_iso_path(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_ISO_RECEIVE_TEST):
le_iso_receive_test(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_ISO_TRANSMIT_TEST):
le_iso_transmit_test(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_ISO_TEST_END):
le_iso_test_end(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_ISO_READ_TEST_COUNTERS):
le_iso_read_test_counters(cmd, evt);
break;
#endif /* CONFIG_BT_CTLR_CENTRAL_ISO || CONFIG_BT_CTLR_PERIPHERAL_ISO */
case BT_OCF(BT_HCI_OP_LE_READ_CHAN_MAP):
le_read_chan_map(cmd, evt);
break;

View file

@ -137,6 +137,38 @@ uint8_t ll_cis_parameters_set(uint8_t cis_id,
uint8_t m_rtn, uint8_t s_rtn,
uint16_t *handle);
uint8_t ll_cig_parameters_commit(uint8_t cig_id);
uint8_t ll_cig_parameters_test_open(uint8_t cig_id,
uint32_t m_interval,
uint32_t s_interval,
uint8_t m_ft,
uint8_t s_ft,
uint16_t iso_interval,
uint8_t sca,
uint8_t packing,
uint8_t framing,
uint8_t num_cis);
uint8_t ll_cis_parameters_test_set(uint8_t cis_id,
uint16_t m_sdu, uint16_t s_sdu,
uint16_t m_pdu, uint16_t s_pdu,
uint8_t m_phy, uint8_t s_phy,
uint8_t m_bn, uint8_t s_bn,
uint16_t *handle);
uint8_t ll_configure_data_path(uint8_t data_path_dir,
uint8_t data_path_id,
uint8_t vs_config_len,
uint8_t *vs_config);
uint8_t ll_setup_iso_path(uint16_t handle, uint8_t path_dir, uint8_t path_id,
uint8_t coding_format, uint16_t company_id,
uint16_t vendor_id, uint32_t controller_delay,
uint8_t codec_config_len, uint8_t *codec_config);
uint8_t ll_remove_iso_path(uint16_t handle, uint8_t path_dir);
uint8_t ll_iso_receive_test(uint16_t handle, uint8_t payload_type);
uint8_t ll_iso_transmit_test(uint16_t handle, uint8_t payload_type);
uint8_t ll_iso_test_end(uint16_t handle, uint32_t *received_cnt,
uint32_t *missed_cnt, uint32_t *failed_cnt);
uint8_t ll_iso_read_test_counters(uint16_t handle, uint32_t *received_cnt,
uint32_t *missed_cnt,
uint32_t *failed_cnt);
uint8_t ll_cig_remove(uint8_t cig_id);

View file

@ -49,6 +49,52 @@ uint8_t ll_cis_parameters_set(uint8_t cis_id,
return BT_HCI_ERR_CMD_DISALLOWED;
}
uint8_t ll_cig_parameters_test_open(uint8_t cig_id,
uint32_t m_interval,
uint32_t s_interval,
uint8_t m_ft,
uint8_t s_ft,
uint16_t iso_interval,
uint8_t sca,
uint8_t packing,
uint8_t framing,
uint8_t num_cis)
{
ARG_UNUSED(cig_id);
ARG_UNUSED(m_interval);
ARG_UNUSED(s_interval);
ARG_UNUSED(m_ft);
ARG_UNUSED(s_ft);
ARG_UNUSED(iso_interval);
ARG_UNUSED(sca);
ARG_UNUSED(packing);
ARG_UNUSED(framing);
ARG_UNUSED(num_cis);
return BT_HCI_ERR_CMD_DISALLOWED;
}
uint8_t ll_cis_parameters_test_set(uint8_t cis_id,
uint16_t m_sdu, uint16_t s_sdu,
uint16_t m_pdu, uint16_t s_pdu,
uint8_t m_phy, uint8_t s_phy,
uint8_t m_bn, uint8_t s_bn,
uint16_t *handle)
{
ARG_UNUSED(cis_id);
ARG_UNUSED(m_sdu);
ARG_UNUSED(s_sdu);
ARG_UNUSED(m_pdu);
ARG_UNUSED(s_pdu);
ARG_UNUSED(m_phy);
ARG_UNUSED(s_phy);
ARG_UNUSED(m_bn);
ARG_UNUSED(s_bn);
ARG_UNUSED(handle);
return BT_HCI_ERR_CMD_DISALLOWED;
}
uint8_t ll_cig_parameters_commit(uint8_t cig_id)
{
ARG_UNUSED(cig_id);

View file

@ -0,0 +1,91 @@
/*
* Copyright (c) 2020 Demant
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
#define LOG_MODULE_NAME bt_ctlr_ull_iso
#include "common/log.h"
#include "hal/debug.h"
/* Contains vendor specific argument, function to be implemented by vendors */
__weak uint8_t ll_configure_data_path(uint8_t data_path_dir,
uint8_t data_path_id,
uint8_t vs_config_len,
uint8_t *vs_config)
{
ARG_UNUSED(data_path_dir);
ARG_UNUSED(data_path_id);
ARG_UNUSED(vs_config_len);
ARG_UNUSED(vs_config);
return BT_HCI_ERR_CMD_DISALLOWED;
}
uint8_t ll_setup_iso_path(uint16_t handle, uint8_t path_dir, uint8_t path_id,
uint8_t coding_format, uint16_t company_id,
uint16_t vendor_id, uint32_t controller_delay,
uint8_t codec_config_len, uint8_t *codec_config)
{
ARG_UNUSED(handle);
ARG_UNUSED(path_dir);
ARG_UNUSED(path_id);
ARG_UNUSED(coding_format);
ARG_UNUSED(company_id);
ARG_UNUSED(vendor_id);
ARG_UNUSED(controller_delay);
ARG_UNUSED(codec_config_len);
ARG_UNUSED(codec_config);
return BT_HCI_ERR_CMD_DISALLOWED;
}
uint8_t ll_remove_iso_path(uint16_t handle, uint8_t path_dir)
{
ARG_UNUSED(handle);
ARG_UNUSED(path_dir);
return BT_HCI_ERR_CMD_DISALLOWED;
}
uint8_t ll_iso_receive_test(uint16_t handle, uint8_t payload_type)
{
ARG_UNUSED(handle);
ARG_UNUSED(payload_type);
return BT_HCI_ERR_CMD_DISALLOWED;
}
uint8_t ll_iso_transmit_test(uint16_t handle, uint8_t payload_type)
{
ARG_UNUSED(handle);
ARG_UNUSED(payload_type);
return BT_HCI_ERR_CMD_DISALLOWED;
}
uint8_t ll_iso_test_end(uint16_t handle, uint32_t *received_cnt,
uint32_t *missed_cnt, uint32_t *failed_cnt)
{
ARG_UNUSED(handle);
ARG_UNUSED(received_cnt);
ARG_UNUSED(missed_cnt);
ARG_UNUSED(failed_cnt);
return BT_HCI_ERR_CMD_DISALLOWED;
}
uint8_t ll_iso_read_test_counters(uint16_t handle, uint32_t *received_cnt,
uint32_t *missed_cnt,
uint32_t *failed_cnt)
{
ARG_UNUSED(handle);
ARG_UNUSED(received_cnt);
ARG_UNUSED(missed_cnt);
ARG_UNUSED(failed_cnt);
return BT_HCI_ERR_CMD_DISALLOWED;
}