Bluetooth: controller: Create HCI stubs for CIG/CIS creation and removal

Put infrastructure for the following HCI commands/events in place:
* LE Set CIG Parameters command
* LE Remove CIG command
* LE Create CIS command
* LE Accept CIS Request command
* LE Reject CIS Request command
* LE CIS Established event
* LE CIS Request event

Signed-off-by: Wolfgang Puffitsch <wopu@demant.com>
This commit is contained in:
Wolfgang Puffitsch 2020-11-04 13:26:45 +01:00 committed by Alberto Escolar
commit f68d7863e5
9 changed files with 384 additions and 3 deletions

View file

@ -64,11 +64,19 @@ if(CONFIG_BT_LL_SW_SPLIT)
zephyr_library_sources(
ll_sw/ull_slave.c
)
zephyr_library_sources_ifdef(
CONFIG_BT_CTLR_PERIPHERAL_ISO
ll_sw/ull_peripheral_iso.c
)
endif()
if(CONFIG_BT_CENTRAL)
zephyr_library_sources(
ll_sw/ull_master.c
)
zephyr_library_sources_ifdef(
CONFIG_BT_CTLR_CENTRAL_ISO
ll_sw/ull_central_iso.c
)
endif()
if(CONFIG_BT_CTLR_SCHED_ADVANCED)
zephyr_library_sources(

View file

@ -99,6 +99,11 @@ static struct k_poll_signal *hbuf_signal;
static uint32_t conn_count;
#endif
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO)
static uint32_t cis_pending_count;
#endif
#define DEFAULT_EVENT_MASK 0x1fffffffffff
#define DEFAULT_EVENT_MASK_PAGE_2 0x0
#define DEFAULT_LE_EVENT_MASK 0x1f
@ -307,6 +312,10 @@ static void reset(struct net_buf *buf, struct net_buf **evt)
conn_count = 0U;
#endif
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO)
cis_pending_count = 0U;
#endif
#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
hci_hbuf_total = 0;
hci_hbuf_sent = 0U;
@ -1301,6 +1310,119 @@ static void le_start_encryption(struct net_buf *buf, struct net_buf **evt)
*evt = cmd_status(status);
}
#endif /* CONFIG_BT_CTLR_LE_ENC */
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO)
static void le_set_cig_parameters(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_set_cig_params *cmd = (void *)buf->data;
struct bt_hci_rp_le_set_cig_params *rp;
uint32_t m_interval;
uint32_t s_interval;
uint16_t m_latency;
uint16_t s_latency;
uint8_t status;
uint8_t i;
m_interval = sys_get_le24(cmd->m_interval);
s_interval = sys_get_le24(cmd->s_interval);
m_latency = sys_le16_to_cpu(cmd->m_latency);
s_latency = sys_le16_to_cpu(cmd->s_latency);
/* Create CIG or start modifying existing CIG */
status = ll_cig_parameters_open(cmd->cig_id, m_interval, s_interval,
cmd->sca, cmd->packing, cmd->framing,
m_latency, s_latency, 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 *params = cmd->cis;
uint16_t handle;
uint16_t m_sdu;
uint16_t s_sdu;
m_sdu = sys_le16_to_cpu(params->m_sdu);
s_sdu = sys_le16_to_cpu(params->s_sdu);
status = ll_cis_parameters_set(params->cis_id, m_sdu, s_sdu,
params->m_phy, params->s_phy,
params->m_rtn, params->s_rtn,
&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;
uint8_t status;
uint8_t i;
/*
* Creating new CISes is disallowed until all previous CIS
* established events have been generated
*/
if (cis_pending_count) {
*evt = cmd_status(BT_HCI_ERR_CMD_DISALLOWED);
return;
}
/* Check all handles before actually starting to create CISes */
status = 0x00;
for (i = 0; !status && i < cmd->num_cis; i++) {
uint16_t cis_handle;
uint16_t acl_handle;
cis_handle = sys_le16_to_cpu(cmd->cis[i].cis_handle);
acl_handle = sys_le16_to_cpu(cmd->cis[i].acl_handle);
status = ll_cis_create_check(cis_handle, acl_handle);
}
*evt = cmd_status(status);
if (!status) {
return;
}
/*
* Actually create CISes, any errors are to be reported
* through CIS established events
*/
cis_pending_count = cmd->num_cis;
for (i = 0; i < cmd->num_cis; i++) {
uint16_t cis_handle;
uint16_t acl_handle;
cis_handle = sys_le16_to_cpu(cmd->cis[i].cis_handle);
acl_handle = sys_le16_to_cpu(cmd->cis[i].acl_handle);
ll_cis_create(cis_handle, acl_handle);
}
}
static void le_remove_cig(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_remove_cig *cmd = (void *)buf->data;
struct bt_hci_rp_le_remove_cig *rp;
uint8_t status;
status = ll_cig_remove(cmd->cig_id);
rp = hci_cmd_complete(evt, sizeof(*rp));
rp->status = status;
rp->cig_id = cmd->cig_id;
}
#endif /* CONFIG_BT_CTLR_CENTRAL_ISO */
#endif /* CONFIG_BT_CENTRAL */
#if defined(CONFIG_BT_PERIPHERAL)
@ -1336,6 +1458,35 @@ static void le_ltk_req_neg_reply(struct net_buf *buf, struct net_buf **evt)
rp->handle = sys_le16_to_cpu(handle);
}
#endif /* CONFIG_BT_CTLR_LE_ENC */
#if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
static void le_accept_cis(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_accept_cis *cmd = (void *)buf->data;
uint16_t handle;
uint8_t status;
handle = sys_le16_to_cpu(cmd->handle);
status = ll_cis_accept(handle);
*evt = cmd_status(status);
}
static void le_reject_cis(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_reject_cis *cmd = (void *)buf->data;
struct bt_hci_rp_le_reject_cis *rp;
uint16_t handle;
uint8_t status;
handle = sys_le16_to_cpu(cmd->handle);
status = ll_cis_reject(handle, cmd->reason);
rp = hci_cmd_complete(evt, sizeof(*rp));
rp->status = status;
rp->handle = sys_cpu_to_le16(handle);
}
#endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO */
#endif /* CONFIG_BT_PERIPHERAL */
static void le_read_remote_features(struct net_buf *buf, struct net_buf **evt)
@ -2302,6 +2453,29 @@ static void le_ext_create_connection(struct net_buf *buf, struct net_buf **evt)
#endif /* CONFIG_BT_CENTRAL */
#endif /* CONFIG_BT_CTLR_ADV_EXT */
#if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
static void le_cis_request(struct pdu_data *pdu_data,
struct node_rx_pdu *node_rx,
struct net_buf *buf)
{
/* TODO: generate event and fill in data from LL */
}
#endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO */
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO) || \
defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
static void le_cis_established(struct pdu_data *pdu_data,
struct node_rx_pdu *node_rx,
struct net_buf *buf)
{
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO)
cis_pending_count--;
#endif /* CONFIG_BT_CTLR_CENTRAL_ISO */
/* TODO: generate event and fill in data from LL */
}
#endif /* CONFIG_BT_CTLR_CENTRAL_ISO || CONFIG_BT_CTLR_PERIPHERAL_ISO */
static int controller_cmd_handle(uint16_t ocf, struct net_buf *cmd,
struct net_buf **evt, void **node_rx)
{
@ -2427,6 +2601,18 @@ static int controller_cmd_handle(uint16_t ocf, struct net_buf *cmd,
le_start_encryption(cmd, evt);
break;
#endif /* CONFIG_BT_CTLR_LE_ENC */
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO)
case BT_OCF(BT_HCI_OP_LE_SET_CIG_PARAMS):
le_set_cig_parameters(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_CREATE_CIS):
le_create_cis(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_REMOVE_CIG):
le_remove_cig(cmd, evt);
break;
#endif /* CONFIG_BT_CTLR_CENTRAL_ISO */
#endif /* CONFIG_BT_CENTRAL */
#if defined(CONFIG_BT_PERIPHERAL)
@ -2439,6 +2625,15 @@ static int controller_cmd_handle(uint16_t ocf, struct net_buf *cmd,
le_ltk_req_neg_reply(cmd, evt);
break;
#endif /* CONFIG_BT_CTLR_LE_ENC */
#if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
case BT_OCF(BT_HCI_OP_LE_ACCEPT_CIS):
le_accept_cis(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_REJECT_CIS):
le_reject_cis(cmd, evt);
break;
#endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO */
#endif /* CONFIG_BT_PERIPHERAL */
case BT_OCF(BT_HCI_OP_LE_READ_CHAN_MAP):
@ -4415,6 +4610,20 @@ static void encode_control(struct node_rx_pdu *node_rx,
pdu_data->rssi);
return;
#endif /* CONFIG_BT_CTLR_CONN_RSSI_EVENT */
#if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
case NODE_RX_TYPE_CIS_REQUEST:
le_cis_request(pdu_data, node_rx, buf);
return;
#endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO */
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO) || \
defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
case NODE_RX_TYPE_CIS_ESTABLISHED:
le_cis_established(pdu_data, node_rx, buf);
return;
#endif /* CONFIG_BT_CTLR_CENTRAL_ISO || CONFIG_BT_CTLR_PERIPHERAL_ISO */
#endif /* CONFIG_BT_CONN */
#if defined(CONFIG_BT_CTLR_ADV_INDICATION)
@ -4811,6 +5020,14 @@ uint8_t hci_get_class(struct node_rx_pdu *node_rx)
#if defined(CONFIG_BT_CONN)
case NODE_RX_TYPE_CONNECTION:
#if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
case NODE_RX_TYPE_CIS_REQUEST:
#endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO */
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO) || \
defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
case NODE_RX_TYPE_CIS_ESTABLISHED:
#endif /* CONFIG_BT_CTLR_CENTRAL_ISO || CONFIG_BT_CTLR_PERIPHERAL_ISO */
return HCI_CLASS_EVT_REQUIRED;
case NODE_RX_TYPE_TERMINATE:

View file

@ -126,6 +126,26 @@ uint8_t ll_big_sync_terminate(uint8_t big_handle);
uint8_t ll_scan_enable(uint8_t enable);
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
uint8_t ll_cig_parameters_open(uint8_t cig_id,
uint32_t m_interval, uint32_t s_interval,
uint8_t sca, uint8_t packing, uint8_t framing,
uint16_t m_latency, uint16_t s_latency,
uint8_t num_cis);
uint8_t ll_cis_parameters_set(uint8_t cis_id,
uint16_t m_sdu, uint16_t s_sdu,
uint8_t m_phy, uint8_t s_phy,
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_remove(uint8_t cig_id);
uint8_t ll_cis_create_check(uint16_t cis_handle, uint16_t acl_handle);
void ll_cis_create(uint16_t cis_handle, uint16_t acl_handle);
uint8_t ll_cis_accept(uint16_t handle);
uint8_t ll_cis_reject(uint16_t handle, uint8_t reason);
uint8_t ll_wl_size_get(void);
uint8_t ll_wl_clear(void);
uint8_t ll_wl_add(bt_addr_le_t *addr);

View file

@ -220,14 +220,23 @@ enum node_rx_type {
NODE_RX_TYPE_SCAN_INDICATION = 0x17,
#endif /* CONFIG_BT_CTLR_SCAN_INDICATION */
#if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
NODE_RX_TYPE_CIS_REQUEST = 0x18,
#endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO */
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO) || \
defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
NODE_RX_TYPE_CIS_ESTABLISHED = 0x19,
#endif /* CONFIG_BT_CTLR_CENTRAL_ISO || CONFIG_BT_CTLR_PERIPHERAL_ISO */
#if defined(CONFIG_BT_HCI_MESH_EXT)
NODE_RX_TYPE_MESH_ADV_CPLT = 0x18,
NODE_RX_TYPE_MESH_REPORT = 0x19,
NODE_RX_TYPE_MESH_ADV_CPLT = 0x1a,
NODE_RX_TYPE_MESH_REPORT = 0x1b,
#endif /* CONFIG_BT_HCI_MESH_EXT */
/* Following proprietary defines must be at end of enum range */
#if defined(CONFIG_BT_CTLR_USER_EXT)
NODE_RX_TYPE_USER_START = 0x1a,
NODE_RX_TYPE_USER_START = 0x1c,
NODE_RX_TYPE_USER_END = NODE_RX_TYPE_USER_START +
CONFIG_BT_CTLR_USER_EVT_RANGE,
#endif /* CONFIG_BT_CTLR_USER_EXT */

View file

@ -0,0 +1,78 @@
/*
* 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_central_iso
#include "common/log.h"
#include "hal/debug.h"
uint8_t ll_cig_parameters_open(uint8_t cig_id,
uint32_t m_interval, uint32_t s_interval,
uint8_t sca, uint8_t packing, uint8_t framing,
uint16_t m_latency, uint16_t s_latency,
uint8_t num_cis)
{
ARG_UNUSED(cig_id);
ARG_UNUSED(m_interval);
ARG_UNUSED(s_interval);
ARG_UNUSED(sca);
ARG_UNUSED(packing);
ARG_UNUSED(framing);
ARG_UNUSED(m_latency);
ARG_UNUSED(s_latency);
ARG_UNUSED(num_cis);
return BT_HCI_ERR_CMD_DISALLOWED;
}
uint8_t ll_cis_parameters_set(uint8_t cis_id,
uint16_t m_sdu, uint16_t s_sdu,
uint8_t m_phy, uint8_t s_phy,
uint8_t m_rtn, uint8_t s_rtn,
uint16_t *handle)
{
ARG_UNUSED(cis_id);
ARG_UNUSED(m_sdu);
ARG_UNUSED(s_sdu);
ARG_UNUSED(m_phy);
ARG_UNUSED(s_phy);
ARG_UNUSED(m_rtn);
ARG_UNUSED(s_rtn);
ARG_UNUSED(handle);
return BT_HCI_ERR_CMD_DISALLOWED;
}
uint8_t ll_cig_parameters_commit(uint8_t cig_id)
{
ARG_UNUSED(cig_id);
return BT_HCI_ERR_CMD_DISALLOWED;
}
uint8_t ll_cig_remove(uint8_t cig_id)
{
ARG_UNUSED(cig_id);
return BT_HCI_ERR_CMD_DISALLOWED;
}
uint8_t ll_cis_create_check(uint16_t cis_handle, uint16_t acl_handle)
{
ARG_UNUSED(cis_handle);
ARG_UNUSED(acl_handle);
return BT_HCI_ERR_CMD_DISALLOWED;
}
void ll_cis_create(uint16_t cis_handle, uint16_t acl_handle)
{
ARG_UNUSED(cis_handle);
ARG_UNUSED(acl_handle);
}

View file

@ -0,0 +1,27 @@
/*
* 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_peripheral_iso
#include "common/log.h"
#include "hal/debug.h"
uint8_t ll_cis_accept(uint16_t handle)
{
ARG_UNUSED(handle);
return BT_HCI_ERR_CMD_DISALLOWED;
}
uint8_t ll_cis_reject(uint16_t handle, uint8_t reason)
{
ARG_UNUSED(handle);
ARG_UNUSED(reason);
return BT_HCI_ERR_CMD_DISALLOWED;
}

View file

@ -0,0 +1,7 @@
CONFIG_BT=y
CONFIG_BT_CTLR=y
CONFIG_BT_CENTRAL=y
CONFIG_BT_LL_SW_SPLIT=y
CONFIG_BT_AUDIO_UNICAST=y
CONFIG_BT_CTLR_CENTRAL_ISO=y
CONFIG_ZTEST=y

View file

@ -0,0 +1,7 @@
CONFIG_BT=y
CONFIG_BT_CTLR=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_LL_SW_SPLIT=y
CONFIG_BT_AUDIO_UNICAST=y
CONFIG_BT_CTLR_PERIPHERAL_ISO=y
CONFIG_ZTEST=y

View file

@ -129,6 +129,14 @@ tests:
extra_args: CONF_FILE=prj_ctlr_per_sync.conf
platform_allow: nrf52840dk_nrf52840 nrf52dk_nrf52832
nrf51dk_nrf51422
bluetooth.init.test_ctlr_peripheral_iso:
extra_args: CONF_FILE=prj_ctlr_peripheral_iso.conf
platform_allow: nrf52840dk_nrf52840 nrf52dk_nrf52832
nrf51dk_nrf51422
bluetooth.init.test_ctlr_central_iso:
extra_args: CONF_FILE=prj_ctlr_central_iso.conf
platform_allow: nrf52840dk_nrf52840 nrf52dk_nrf52832
nrf51dk_nrf51422
bluetooth.init.test_h5:
extra_args: CONF_FILE=prj_h5.conf
platform_allow: qemu_cortex_m3