Bluetooth: controller: Implement local CIS Creation procedure
Local procedure for CIS central establishment. Calls yet unimplemented functions in ull_central. Changes are guarded by CONFIG_BT_CTLR_CENTRAL_ISO. Signed-off-by: Morten Priess <mtpr@oticon.com>
This commit is contained in:
parent
94458f88b9
commit
38a4e58d1f
8 changed files with 559 additions and 37 deletions
|
@ -7,3 +7,14 @@
|
||||||
/* Helper functions to initialize and reset ull_central_iso module */
|
/* Helper functions to initialize and reset ull_central_iso module */
|
||||||
int ull_central_iso_init(void);
|
int ull_central_iso_init(void);
|
||||||
int ull_central_iso_reset(void);
|
int ull_central_iso_reset(void);
|
||||||
|
|
||||||
|
void ull_central_iso_start(struct ll_conn *acl, uint32_t ticks_at_expire, uint16_t cis_handle);
|
||||||
|
uint16_t ull_central_iso_cis_offset_get(struct ll_conn_iso_stream *cis, uint32_t *cis_offset_min,
|
||||||
|
uint32_t *cis_offset_max);
|
||||||
|
uint8_t ull_central_iso_setup(uint16_t cis_handle,
|
||||||
|
uint32_t *cig_sync_delay,
|
||||||
|
uint32_t *cis_sync_delay,
|
||||||
|
uint32_t *cis_offset_min,
|
||||||
|
uint32_t *cis_offset_max,
|
||||||
|
uint16_t *conn_event_count,
|
||||||
|
uint8_t *access_addr);
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "ull_iso_types.h"
|
#include "ull_iso_types.h"
|
||||||
#include "ull_conn_iso_types.h"
|
#include "ull_conn_iso_types.h"
|
||||||
#include "ull_conn_iso_internal.h"
|
#include "ull_conn_iso_internal.h"
|
||||||
|
#include "ull_central_iso_internal.h"
|
||||||
|
|
||||||
#include "ull_internal.h"
|
#include "ull_internal.h"
|
||||||
#include "ull_conn_types.h"
|
#include "ull_conn_types.h"
|
||||||
|
@ -371,6 +372,11 @@ struct proc_ctx *llcp_create_local_procedure(enum llcp_proc proc)
|
||||||
llcp_lp_comm_init_proc(ctx);
|
llcp_lp_comm_init_proc(ctx);
|
||||||
break;
|
break;
|
||||||
#endif /* defined(CONFIG_BT_CTLR_CENTRAL_ISO) || defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) */
|
#endif /* defined(CONFIG_BT_CTLR_CENTRAL_ISO) || defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) */
|
||||||
|
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO)
|
||||||
|
case PROC_CIS_CREATE:
|
||||||
|
llcp_lp_comm_init_proc(ctx);
|
||||||
|
break;
|
||||||
|
#endif /* defined(CONFIG_BT_CTLR_CENTRAL_ISO) */
|
||||||
#if defined(CONFIG_BT_CTLR_SCA_UPDATE)
|
#if defined(CONFIG_BT_CTLR_SCA_UPDATE)
|
||||||
case PROC_SCA_UPDATE:
|
case PROC_SCA_UPDATE:
|
||||||
llcp_lp_comm_init_proc(ctx);
|
llcp_lp_comm_init_proc(ctx);
|
||||||
|
@ -861,6 +867,53 @@ uint8_t ull_cp_cis_terminate(struct ll_conn *conn,
|
||||||
}
|
}
|
||||||
#endif /* defined(CONFIG_BT_CTLR_CENTRAL_ISO) || defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) */
|
#endif /* defined(CONFIG_BT_CTLR_CENTRAL_ISO) || defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) */
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO)
|
||||||
|
uint8_t ull_cp_cis_create(struct ll_conn *conn, struct ll_conn_iso_stream *cis)
|
||||||
|
{
|
||||||
|
struct ll_conn_iso_group *cig;
|
||||||
|
struct proc_ctx *ctx;
|
||||||
|
|
||||||
|
if (conn->lll.handle != cis->lll.acl_handle) {
|
||||||
|
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = llcp_create_local_procedure(PROC_CIS_CREATE);
|
||||||
|
if (!ctx) {
|
||||||
|
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||||
|
}
|
||||||
|
|
||||||
|
cig = cis->group;
|
||||||
|
ctx->data.cis_create.cis_handle = cis->lll.handle;
|
||||||
|
|
||||||
|
ctx->data.cis_create.cig_id = cis->group->cig_id;
|
||||||
|
ctx->data.cis_create.cis_id = cis->cis_id;
|
||||||
|
ctx->data.cis_create.c_phy = cis->lll.tx.phy;
|
||||||
|
ctx->data.cis_create.p_phy = cis->lll.rx.phy;
|
||||||
|
ctx->data.cis_create.c_sdu_interval = cig->c_sdu_interval;
|
||||||
|
ctx->data.cis_create.p_sdu_interval = cig->p_sdu_interval;
|
||||||
|
ctx->data.cis_create.c_max_pdu = cis->lll.tx.max_octets;
|
||||||
|
ctx->data.cis_create.p_max_pdu = cis->lll.rx.max_octets;
|
||||||
|
ctx->data.cis_create.c_max_sdu = cis->c_max_sdu;
|
||||||
|
ctx->data.cis_create.p_max_sdu = cis->p_max_sdu;
|
||||||
|
ctx->data.cis_create.iso_interval = cig->iso_interval;
|
||||||
|
ctx->data.cis_create.framed = cis->framed;
|
||||||
|
ctx->data.cis_create.nse = cis->lll.num_subevents;
|
||||||
|
ctx->data.cis_create.sub_interval = cis->lll.sub_interval;
|
||||||
|
ctx->data.cis_create.c_bn = cis->lll.tx.burst_number;
|
||||||
|
ctx->data.cis_create.p_bn = cis->lll.rx.burst_number;
|
||||||
|
ctx->data.cis_create.c_ft = cis->lll.tx.flush_timeout;
|
||||||
|
ctx->data.cis_create.p_ft = cis->lll.rx.flush_timeout;
|
||||||
|
|
||||||
|
ctx->data.cis_create.conn_event_count =
|
||||||
|
ull_central_iso_cis_offset_get(cis, &ctx->data.cis_create.cis_offset_min,
|
||||||
|
&ctx->data.cis_create.cis_offset_max);
|
||||||
|
|
||||||
|
llcp_lr_enqueue(conn, ctx);
|
||||||
|
|
||||||
|
return BT_HCI_ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
#endif /* defined(CONFIG_BT_CTLR_CENTRAL_ISO) */
|
||||||
|
|
||||||
#if defined(CONFIG_BT_CENTRAL)
|
#if defined(CONFIG_BT_CENTRAL)
|
||||||
uint8_t ull_cp_chan_map_update(struct ll_conn *conn, const uint8_t chm[5])
|
uint8_t ull_cp_chan_map_update(struct ll_conn *conn, const uint8_t chm[5])
|
||||||
{
|
{
|
||||||
|
@ -1226,6 +1279,19 @@ void ull_cp_cc_reject(struct ll_conn *conn, uint8_t error_code)
|
||||||
}
|
}
|
||||||
#endif /* defined(CONFIG_BT_PERIPHERAL) && defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) */
|
#endif /* defined(CONFIG_BT_PERIPHERAL) && defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) */
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_CTLR_CENTRAL_ISO)
|
||||||
|
bool ull_lp_cc_is_active(struct ll_conn *conn)
|
||||||
|
{
|
||||||
|
struct proc_ctx *ctx;
|
||||||
|
|
||||||
|
ctx = llcp_lr_peek(conn);
|
||||||
|
if (ctx && ctx->proc == PROC_CIS_CREATE) {
|
||||||
|
return llcp_lp_cc_is_active(ctx);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif /* defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_CTLR_CENTRAL_ISO) */
|
||||||
|
|
||||||
static bool pdu_is_expected(struct pdu_data *pdu, struct proc_ctx *ctx)
|
static bool pdu_is_expected(struct pdu_data *pdu, struct proc_ctx *ctx)
|
||||||
{
|
{
|
||||||
return (ctx->rx_opcode == pdu->llctrl.opcode || ctx->rx_greedy);
|
return (ctx->rx_opcode == pdu->llctrl.opcode || ctx->rx_greedy);
|
||||||
|
|
|
@ -181,6 +181,11 @@ uint8_t ull_cp_terminate(struct ll_conn *conn, uint8_t error_code);
|
||||||
uint8_t ull_cp_cis_terminate(struct ll_conn *conn, struct ll_conn_iso_stream *cis,
|
uint8_t ull_cp_cis_terminate(struct ll_conn *conn, struct ll_conn_iso_stream *cis,
|
||||||
uint8_t error_code);
|
uint8_t error_code);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initiate a CIS Create Procedure.
|
||||||
|
*/
|
||||||
|
uint8_t ull_cp_cis_create(struct ll_conn *conn, struct ll_conn_iso_stream *cis);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Is ongoing create cis procedure expecting a reply?
|
* @brief Is ongoing create cis procedure expecting a reply?
|
||||||
*/
|
*/
|
||||||
|
@ -202,6 +207,16 @@ void ull_cp_cc_accept(struct ll_conn *conn);
|
||||||
*/
|
*/
|
||||||
void ull_cp_cc_reject(struct ll_conn *conn, uint8_t error_code);
|
void ull_cp_cc_reject(struct ll_conn *conn, uint8_t error_code);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CIS was established.
|
||||||
|
*/
|
||||||
|
void ull_cp_cc_established(struct ll_conn *conn, uint8_t error_code);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CIS creation ongoing.
|
||||||
|
*/
|
||||||
|
bool ull_lp_cc_is_active(struct ll_conn *conn);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initiate a Channel Map Update Procedure.
|
* @brief Initiate a Channel Map Update Procedure.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
#include "ull_iso_internal.h"
|
#include "ull_iso_internal.h"
|
||||||
#include "ull_conn_iso_internal.h"
|
#include "ull_conn_iso_internal.h"
|
||||||
#include "ull_peripheral_iso_internal.h"
|
#include "ull_peripheral_iso_internal.h"
|
||||||
|
#include "ull_central_iso_internal.h"
|
||||||
|
|
||||||
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
|
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
|
||||||
#define LOG_MODULE_NAME bt_ctlr_ull_llcp_cis
|
#define LOG_MODULE_NAME bt_ctlr_ull_llcp_cis
|
||||||
|
@ -51,6 +52,37 @@
|
||||||
#include <soc.h>
|
#include <soc.h>
|
||||||
#include "hal/debug.h"
|
#include "hal/debug.h"
|
||||||
|
|
||||||
|
static bool cc_check_cis_established_lll(struct proc_ctx *ctx)
|
||||||
|
{
|
||||||
|
const struct ll_conn_iso_stream *cis =
|
||||||
|
ll_conn_iso_stream_get(ctx->data.cis_create.cis_handle);
|
||||||
|
|
||||||
|
return cis->established;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cc_ntf_established(struct ll_conn *conn, struct proc_ctx *ctx)
|
||||||
|
{
|
||||||
|
struct node_rx_pdu *ntf;
|
||||||
|
struct node_rx_conn_iso_estab *pdu;
|
||||||
|
|
||||||
|
/* Allocate ntf node */
|
||||||
|
ntf = llcp_ntf_alloc();
|
||||||
|
LL_ASSERT(ntf);
|
||||||
|
|
||||||
|
ntf->hdr.type = NODE_RX_TYPE_CIS_ESTABLISHED;
|
||||||
|
ntf->hdr.handle = conn->lll.handle;
|
||||||
|
ntf->hdr.rx_ftr.param = ll_conn_iso_stream_get(ctx->data.cis_create.cis_handle);
|
||||||
|
|
||||||
|
pdu = (struct node_rx_conn_iso_estab *)ntf->pdu;
|
||||||
|
|
||||||
|
pdu->cis_handle = ctx->data.cis_create.cis_handle;
|
||||||
|
pdu->status = ctx->data.cis_create.error;
|
||||||
|
|
||||||
|
/* Enqueue notification towards LL */
|
||||||
|
ll_rx_put(ntf->hdr.link, ntf);
|
||||||
|
ll_rx_sched();
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_BT_PERIPHERAL)
|
#if defined(CONFIG_BT_PERIPHERAL)
|
||||||
static uint16_t cc_event_counter(struct ll_conn *conn)
|
static uint16_t cc_event_counter(struct ll_conn *conn)
|
||||||
{
|
{
|
||||||
|
@ -109,6 +141,7 @@ enum {
|
||||||
/* Unknown response received */
|
/* Unknown response received */
|
||||||
RP_CC_EVT_UNKNOWN,
|
RP_CC_EVT_UNKNOWN,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* LLCP Remote Procedure FSM
|
* LLCP Remote Procedure FSM
|
||||||
*/
|
*/
|
||||||
|
@ -174,36 +207,12 @@ static void rp_cc_ntf_create(struct ll_conn *conn, struct proc_ctx *ctx)
|
||||||
ll_rx_sched();
|
ll_rx_sched();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void rp_cc_ntf(struct ll_conn *conn, struct proc_ctx *ctx)
|
|
||||||
{
|
|
||||||
struct node_rx_pdu *ntf;
|
|
||||||
struct node_rx_conn_iso_estab *pdu;
|
|
||||||
|
|
||||||
/* Allocate ntf node */
|
|
||||||
ntf = llcp_ntf_alloc();
|
|
||||||
LL_ASSERT(ntf);
|
|
||||||
|
|
||||||
ntf->hdr.type = NODE_RX_TYPE_CIS_ESTABLISHED;
|
|
||||||
ntf->hdr.handle = conn->lll.handle;
|
|
||||||
ntf->hdr.rx_ftr.param = ll_conn_iso_stream_get(ctx->data.cis_create.cis_handle);
|
|
||||||
|
|
||||||
pdu = (struct node_rx_conn_iso_estab *)ntf->pdu;
|
|
||||||
|
|
||||||
pdu->cis_handle = ctx->data.cis_create.cis_handle;
|
|
||||||
pdu->status = ctx->data.cis_create.error;
|
|
||||||
|
|
||||||
/* Enqueue notification towards LL */
|
|
||||||
ll_rx_put(ntf->hdr.link, ntf);
|
|
||||||
ll_rx_sched();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rp_cc_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param)
|
static void rp_cc_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param)
|
||||||
{
|
{
|
||||||
if (!llcp_ntf_alloc_is_available()) {
|
if (!llcp_ntf_alloc_is_available()) {
|
||||||
ctx->state = RP_CC_STATE_WAIT_NTF;
|
ctx->state = RP_CC_STATE_WAIT_NTF;
|
||||||
} else {
|
} else {
|
||||||
rp_cc_ntf(conn, ctx);
|
cc_ntf_established(conn, ctx);
|
||||||
llcp_rr_complete(conn);
|
llcp_rr_complete(conn);
|
||||||
ctx->state = RP_CC_STATE_IDLE;
|
ctx->state = RP_CC_STATE_IDLE;
|
||||||
}
|
}
|
||||||
|
@ -296,14 +305,6 @@ static uint8_t rp_cc_check_phy(struct ll_conn *conn, struct proc_ctx *ctx,
|
||||||
return BT_HCI_ERR_SUCCESS;
|
return BT_HCI_ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool rp_cc_check_cis_established_lll(struct proc_ctx *ctx)
|
|
||||||
{
|
|
||||||
const struct ll_conn_iso_stream *cis =
|
|
||||||
ll_conn_iso_stream_get(ctx->data.cis_create.cis_handle);
|
|
||||||
|
|
||||||
return cis->established;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rp_cc_state_wait_rx_cis_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
|
static void rp_cc_state_wait_rx_cis_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
|
||||||
void *param)
|
void *param)
|
||||||
{
|
{
|
||||||
|
@ -495,7 +496,7 @@ static void rp_cc_state_wait_cis_established(struct ll_conn *conn, struct proc_c
|
||||||
switch (evt) {
|
switch (evt) {
|
||||||
case RP_CC_EVT_RUN:
|
case RP_CC_EVT_RUN:
|
||||||
/* Check for CIS state */
|
/* Check for CIS state */
|
||||||
if (rp_cc_check_cis_established_lll(ctx)) {
|
if (cc_check_cis_established_lll(ctx)) {
|
||||||
/* CIS was established, so let's got ahead and complete procedure */
|
/* CIS was established, so let's got ahead and complete procedure */
|
||||||
rp_cc_complete(conn, ctx, evt, param);
|
rp_cc_complete(conn, ctx, evt, param);
|
||||||
}
|
}
|
||||||
|
@ -599,3 +600,312 @@ void llcp_rp_cc_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param)
|
||||||
rp_cc_execute_fsm(conn, ctx, RP_CC_EVT_RUN, param);
|
rp_cc_execute_fsm(conn, ctx, RP_CC_EVT_RUN, param);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_BT_PERIPHERAL */
|
#endif /* CONFIG_BT_PERIPHERAL */
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_CENTRAL)
|
||||||
|
static void lp_cc_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param);
|
||||||
|
|
||||||
|
/* LLCP Local Procedure FSM states */
|
||||||
|
enum {
|
||||||
|
LP_CC_STATE_IDLE,
|
||||||
|
LP_CC_STATE_WAIT_TX_CIS_REQ,
|
||||||
|
LP_CC_STATE_WAIT_RX_CIS_RSP,
|
||||||
|
LP_CC_STATE_WAIT_TX_CIS_IND,
|
||||||
|
LP_CC_STATE_WAIT_INSTANT,
|
||||||
|
LP_CC_STATE_WAIT_ESTABLISHED,
|
||||||
|
LP_CC_STATE_WAIT_NTF,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* LLCP Local Procedure CIS Creation FSM events */
|
||||||
|
enum {
|
||||||
|
/* Procedure run */
|
||||||
|
LP_CC_EVT_RUN,
|
||||||
|
|
||||||
|
/* Response received */
|
||||||
|
LP_CC_EVT_CIS_RSP,
|
||||||
|
|
||||||
|
/* Reject response received */
|
||||||
|
LP_CC_EVT_REJECT,
|
||||||
|
|
||||||
|
/* Unknown response received */
|
||||||
|
LP_CC_EVT_UNKNOWN,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void lp_cc_tx(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t opcode)
|
||||||
|
{
|
||||||
|
struct node_tx *tx;
|
||||||
|
struct pdu_data *pdu;
|
||||||
|
|
||||||
|
/* Allocate tx node */
|
||||||
|
tx = llcp_tx_alloc(conn, ctx);
|
||||||
|
LL_ASSERT(tx);
|
||||||
|
|
||||||
|
pdu = (struct pdu_data *)tx->pdu;
|
||||||
|
|
||||||
|
/* Encode LL Control PDU */
|
||||||
|
switch (opcode) {
|
||||||
|
case PDU_DATA_LLCTRL_TYPE_CIS_REQ:
|
||||||
|
llcp_pdu_encode_cis_req(ctx, pdu);
|
||||||
|
break;
|
||||||
|
case PDU_DATA_LLCTRL_TYPE_CIS_IND:
|
||||||
|
llcp_pdu_encode_cis_ind(ctx, pdu);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Unknown opcode */
|
||||||
|
LL_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->tx_opcode = pdu->llctrl.opcode;
|
||||||
|
|
||||||
|
/* Enqueue LL Control PDU towards LLL */
|
||||||
|
llcp_tx_enqueue(conn, tx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void llcp_lp_cc_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx)
|
||||||
|
{
|
||||||
|
struct pdu_data *pdu = (struct pdu_data *)rx->pdu;
|
||||||
|
|
||||||
|
switch (pdu->llctrl.opcode) {
|
||||||
|
case PDU_DATA_LLCTRL_TYPE_CIS_RSP:
|
||||||
|
lp_cc_execute_fsm(conn, ctx, LP_CC_EVT_CIS_RSP, pdu);
|
||||||
|
break;
|
||||||
|
case PDU_DATA_LLCTRL_TYPE_REJECT_IND:
|
||||||
|
case PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND:
|
||||||
|
lp_cc_execute_fsm(conn, ctx, LP_CC_EVT_REJECT, pdu);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Unknown opcode */
|
||||||
|
LL_ASSERT(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lp_cc_send_cis_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
|
||||||
|
void *param)
|
||||||
|
{
|
||||||
|
if (llcp_lr_ispaused(conn) || !llcp_tx_alloc_peek(conn, ctx)) {
|
||||||
|
ctx->state = LP_CC_STATE_WAIT_TX_CIS_REQ;
|
||||||
|
} else {
|
||||||
|
lp_cc_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_CIS_REQ);
|
||||||
|
|
||||||
|
ctx->state = LP_CC_STATE_WAIT_RX_CIS_RSP;
|
||||||
|
ctx->rx_opcode = PDU_DATA_LLCTRL_TYPE_CIS_RSP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lp_cc_st_wait_tx_cis_req(struct ll_conn *conn, struct proc_ctx *ctx,
|
||||||
|
uint8_t evt, void *param)
|
||||||
|
{
|
||||||
|
switch (evt) {
|
||||||
|
case LP_CC_EVT_RUN:
|
||||||
|
lp_cc_send_cis_req(conn, ctx, evt, param);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Ignore other evts */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lp_cc_st_idle(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param)
|
||||||
|
{
|
||||||
|
switch (evt) {
|
||||||
|
case LP_CC_EVT_RUN:
|
||||||
|
switch (ctx->proc) {
|
||||||
|
case PROC_CIS_CREATE:
|
||||||
|
lp_cc_send_cis_req(conn, ctx, evt, param);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Unknown procedure */
|
||||||
|
LL_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Ignore other evts */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cc_prepare_cis_ind(struct ll_conn *conn, struct proc_ctx *ctx)
|
||||||
|
{
|
||||||
|
uint8_t err;
|
||||||
|
|
||||||
|
/* Setup central parameters based on CIS_RSP */
|
||||||
|
err = ull_central_iso_setup(ctx->data.cis_create.cis_handle,
|
||||||
|
&ctx->data.cis_create.cig_sync_delay,
|
||||||
|
&ctx->data.cis_create.cis_sync_delay,
|
||||||
|
&ctx->data.cis_create.cis_offset_min,
|
||||||
|
&ctx->data.cis_create.cis_offset_max,
|
||||||
|
&ctx->data.cis_create.conn_event_count,
|
||||||
|
ctx->data.cis_create.aa);
|
||||||
|
LL_ASSERT(!err);
|
||||||
|
|
||||||
|
ctx->state = LP_CC_STATE_WAIT_INSTANT;
|
||||||
|
ctx->rx_opcode = PDU_DATA_LLCTRL_TYPE_UNUSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lp_cc_send_cis_ind(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
|
||||||
|
void *param)
|
||||||
|
{
|
||||||
|
if (llcp_lr_ispaused(conn) || !llcp_tx_alloc_peek(conn, ctx)) {
|
||||||
|
ctx->state = LP_CC_STATE_WAIT_TX_CIS_IND;
|
||||||
|
} else {
|
||||||
|
cc_prepare_cis_ind(conn, ctx);
|
||||||
|
lp_cc_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_CIS_IND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lp_cc_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param)
|
||||||
|
{
|
||||||
|
if (!llcp_ntf_alloc_is_available()) {
|
||||||
|
ctx->state = LP_CC_STATE_WAIT_NTF;
|
||||||
|
} else {
|
||||||
|
cc_ntf_established(conn, ctx);
|
||||||
|
llcp_lr_complete(conn);
|
||||||
|
ctx->state = LP_CC_STATE_IDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lp_cc_st_wait_rx_cis_rsp(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
|
||||||
|
void *param)
|
||||||
|
{
|
||||||
|
struct pdu_data *pdu = (struct pdu_data *)param;
|
||||||
|
|
||||||
|
switch (evt) {
|
||||||
|
case LP_CC_EVT_CIS_RSP:
|
||||||
|
/* TODO: Reject response if outside offset range? */
|
||||||
|
llcp_pdu_decode_cis_rsp(ctx, param);
|
||||||
|
lp_cc_send_cis_ind(conn, ctx, evt, param);
|
||||||
|
break;
|
||||||
|
case LP_CC_EVT_UNKNOWN:
|
||||||
|
/* Unsupported in peer, so disable locally for this connection */
|
||||||
|
feature_unmask_features(conn, LL_FEAT_BIT_CIS_PERIPHERAL);
|
||||||
|
ctx->data.cis_create.error = BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
|
||||||
|
lp_cc_complete(conn, ctx, evt, param);
|
||||||
|
break;
|
||||||
|
case LP_CC_EVT_REJECT:
|
||||||
|
if (pdu->llctrl.reject_ext_ind.error_code == BT_HCI_ERR_UNSUPP_REMOTE_FEATURE) {
|
||||||
|
/* Unsupported in peer, so disable locally for this connection */
|
||||||
|
feature_unmask_features(conn, LL_FEAT_BIT_CIS_PERIPHERAL);
|
||||||
|
}
|
||||||
|
ctx->data.cis_create.error = pdu->llctrl.reject_ext_ind.error_code;
|
||||||
|
lp_cc_complete(conn, ctx, evt, param);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Ignore other evts */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lp_cc_st_wait_tx_cis_ind(struct ll_conn *conn, struct proc_ctx *ctx,
|
||||||
|
uint8_t evt, void *param)
|
||||||
|
{
|
||||||
|
switch (evt) {
|
||||||
|
case LP_CC_EVT_RUN:
|
||||||
|
lp_cc_send_cis_ind(conn, ctx, evt, param);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Ignore other evts */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lp_cc_check_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
|
||||||
|
void *param)
|
||||||
|
{
|
||||||
|
uint16_t event_counter = ull_conn_event_counter(conn);
|
||||||
|
|
||||||
|
if (is_instant_reached_or_passed(ctx->data.cis_create.conn_event_count, event_counter)) {
|
||||||
|
/* Start CIS */
|
||||||
|
ull_central_iso_start(conn, conn->llcp.prep.ticks_at_expire,
|
||||||
|
ctx->data.cis_create.cis_handle);
|
||||||
|
|
||||||
|
/* Now we can wait for CIS to become established */
|
||||||
|
ctx->state = LP_CC_STATE_WAIT_ESTABLISHED;
|
||||||
|
|
||||||
|
/* Stop procedure response timeout timer */
|
||||||
|
llcp_lr_prt_stop(conn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lp_cc_st_wait_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
|
||||||
|
void *param)
|
||||||
|
{
|
||||||
|
switch (evt) {
|
||||||
|
case LP_CC_EVT_RUN:
|
||||||
|
lp_cc_check_instant(conn, ctx, evt, param);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Ignore other evts */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lp_cc_st_wait_established(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
|
||||||
|
void *param)
|
||||||
|
{
|
||||||
|
switch (evt) {
|
||||||
|
case LP_CC_EVT_RUN:
|
||||||
|
if (cc_check_cis_established_lll(ctx)) {
|
||||||
|
/* CIS was established, so let's got ahead and complete procedure */
|
||||||
|
lp_cc_complete(conn, ctx, evt, param);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Ignore other evts */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lp_cc_st_wait_ntf(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param)
|
||||||
|
{
|
||||||
|
switch (evt) {
|
||||||
|
case LP_CC_EVT_RUN:
|
||||||
|
lp_cc_complete(conn, ctx, evt, param);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Ignore other evts */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lp_cc_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param)
|
||||||
|
{
|
||||||
|
switch (ctx->state) {
|
||||||
|
case LP_CC_STATE_IDLE:
|
||||||
|
lp_cc_st_idle(conn, ctx, evt, param);
|
||||||
|
break;
|
||||||
|
case LP_CC_STATE_WAIT_TX_CIS_REQ:
|
||||||
|
lp_cc_st_wait_tx_cis_req(conn, ctx, evt, param);
|
||||||
|
break;
|
||||||
|
case LP_CC_STATE_WAIT_RX_CIS_RSP:
|
||||||
|
lp_cc_st_wait_rx_cis_rsp(conn, ctx, evt, param);
|
||||||
|
break;
|
||||||
|
case LP_CC_STATE_WAIT_TX_CIS_IND:
|
||||||
|
lp_cc_st_wait_tx_cis_ind(conn, ctx, evt, param);
|
||||||
|
break;
|
||||||
|
case LP_CC_STATE_WAIT_INSTANT:
|
||||||
|
lp_cc_st_wait_instant(conn, ctx, evt, param);
|
||||||
|
break;
|
||||||
|
case LP_CC_STATE_WAIT_ESTABLISHED:
|
||||||
|
lp_cc_st_wait_established(conn, ctx, evt, param);
|
||||||
|
break;
|
||||||
|
case LP_CC_STATE_WAIT_NTF:
|
||||||
|
lp_cc_st_wait_ntf(conn, ctx, evt, param);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Unknown state */
|
||||||
|
LL_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void llcp_lp_cc_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param)
|
||||||
|
{
|
||||||
|
lp_cc_execute_fsm(conn, ctx, LP_CC_EVT_RUN, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool llcp_lp_cc_is_active(struct proc_ctx *ctx)
|
||||||
|
{
|
||||||
|
return ctx->state != LP_CC_STATE_IDLE;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_BT_CENTRAL */
|
||||||
|
|
|
@ -159,6 +159,26 @@ static inline bool feature_peer_smi_tx(struct ll_conn *conn)
|
||||||
return (conn->llcp.fex.features_peer & BIT64(BT_LE_FEAT_BIT_SMI_TX)) != 0;
|
return (conn->llcp.fex.features_peer & BIT64(BT_LE_FEAT_BIT_SMI_TX)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool feature_peer_iso_central(struct ll_conn *conn)
|
||||||
|
{
|
||||||
|
return (conn->llcp.fex.features_peer & LL_FEAT_BIT_CIS_CENTRAL) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool feature_iso_central(struct ll_conn *conn)
|
||||||
|
{
|
||||||
|
return LL_FEAT_BIT_CIS_CENTRAL != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool feature_peer_iso_peripheral(struct ll_conn *conn)
|
||||||
|
{
|
||||||
|
return (conn->llcp.fex.features_peer & LL_FEAT_BIT_CIS_PERIPHERAL) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool feature_iso_peripheral(struct ll_conn *conn)
|
||||||
|
{
|
||||||
|
return LL_FEAT_BIT_CIS_PERIPHERAL != 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following features are not yet defined in KConfig and do
|
* The following features are not yet defined in KConfig and do
|
||||||
* not have a bitfield defined in ll_feat.h
|
* not have a bitfield defined in ll_feat.h
|
||||||
|
|
|
@ -264,9 +264,8 @@ struct proc_ctx {
|
||||||
uint32_t host_request_to;
|
uint32_t host_request_to;
|
||||||
#endif /* defined(CONFIG_BT_PERIPHERAL) */
|
#endif /* defined(CONFIG_BT_PERIPHERAL) */
|
||||||
#if defined(CONFIG_BT_CENTRAL)
|
#if defined(CONFIG_BT_CENTRAL)
|
||||||
/* In case of a cis_req data decoded by ull_peripheral_iso_acquire, so
|
uint32_t cig_sync_delay;
|
||||||
* only need to store info in local create (ie central enabled device)
|
uint32_t cis_sync_delay;
|
||||||
*/
|
|
||||||
uint8_t c_phy;
|
uint8_t c_phy;
|
||||||
uint8_t p_phy;
|
uint8_t p_phy;
|
||||||
uint16_t c_max_sdu;
|
uint16_t c_max_sdu;
|
||||||
|
@ -283,6 +282,7 @@ struct proc_ctx {
|
||||||
uint8_t c_ft;
|
uint8_t c_ft;
|
||||||
uint8_t p_ft;
|
uint8_t p_ft;
|
||||||
uint16_t iso_interval;
|
uint16_t iso_interval;
|
||||||
|
uint8_t aa[4];
|
||||||
#endif /* defined(CONFIG_BT_CENTRAL) */
|
#endif /* defined(CONFIG_BT_CENTRAL) */
|
||||||
} cis_create;
|
} cis_create;
|
||||||
|
|
||||||
|
@ -705,6 +705,7 @@ void llcp_pdu_encode_cte_rsp(const struct proc_ctx *ctx, struct pdu_data *pdu);
|
||||||
void llcp_lp_cc_init_proc(struct proc_ctx *ctx);
|
void llcp_lp_cc_init_proc(struct proc_ctx *ctx);
|
||||||
void llcp_lp_cc_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx);
|
void llcp_lp_cc_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx);
|
||||||
void llcp_lp_cc_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param);
|
void llcp_lp_cc_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param);
|
||||||
|
bool llcp_lp_cc_is_active(struct proc_ctx *ctx);
|
||||||
|
|
||||||
void llcp_rp_cc_init_proc(struct proc_ctx *ctx);
|
void llcp_rp_cc_init_proc(struct proc_ctx *ctx);
|
||||||
void llcp_rp_cc_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx);
|
void llcp_rp_cc_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx);
|
||||||
|
@ -717,6 +718,9 @@ void llcp_pdu_decode_cis_req(struct proc_ctx *ctx, struct pdu_data *pdu);
|
||||||
void llcp_pdu_encode_cis_rsp(struct proc_ctx *ctx, struct pdu_data *pdu);
|
void llcp_pdu_encode_cis_rsp(struct proc_ctx *ctx, struct pdu_data *pdu);
|
||||||
void llcp_pdu_encode_cis_terminate_ind(struct proc_ctx *ctx, struct pdu_data *pdu);
|
void llcp_pdu_encode_cis_terminate_ind(struct proc_ctx *ctx, struct pdu_data *pdu);
|
||||||
void llcp_pdu_decode_cis_terminate_ind(struct proc_ctx *ctx, struct pdu_data *pdu);
|
void llcp_pdu_decode_cis_terminate_ind(struct proc_ctx *ctx, struct pdu_data *pdu);
|
||||||
|
void llcp_pdu_encode_cis_req(struct proc_ctx *ctx, struct pdu_data *pdu);
|
||||||
|
void llcp_pdu_encode_cis_ind(struct proc_ctx *ctx, struct pdu_data *pdu);
|
||||||
|
void llcp_pdu_decode_cis_rsp(struct proc_ctx *ctx, struct pdu_data *pdu);
|
||||||
|
|
||||||
#ifdef ZTEST_UNITTEST
|
#ifdef ZTEST_UNITTEST
|
||||||
bool lr_is_disconnected(struct ll_conn *conn);
|
bool lr_is_disconnected(struct ll_conn *conn);
|
||||||
|
|
|
@ -201,6 +201,11 @@ void llcp_lr_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *
|
||||||
llcp_lp_comm_rx(conn, ctx, rx);
|
llcp_lp_comm_rx(conn, ctx, rx);
|
||||||
break;
|
break;
|
||||||
#endif /* defined(CONFIG_BT_CTLR_CENTRAL_ISO) || defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) */
|
#endif /* defined(CONFIG_BT_CTLR_CENTRAL_ISO) || defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) */
|
||||||
|
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO)
|
||||||
|
case PROC_CIS_CREATE:
|
||||||
|
llcp_lp_cc_rx(conn, ctx, rx);
|
||||||
|
break;
|
||||||
|
#endif /* defined(CONFIG_BT_CTLR_CENTRAL_ISO) */
|
||||||
#if defined(CONFIG_BT_CTLR_SCA_UPDATE)
|
#if defined(CONFIG_BT_CTLR_SCA_UPDATE)
|
||||||
case PROC_SCA_UPDATE:
|
case PROC_SCA_UPDATE:
|
||||||
llcp_lp_comm_rx(conn, ctx, rx);
|
llcp_lp_comm_rx(conn, ctx, rx);
|
||||||
|
@ -321,6 +326,11 @@ static void lr_act_run(struct ll_conn *conn)
|
||||||
llcp_lp_comm_run(conn, ctx, NULL);
|
llcp_lp_comm_run(conn, ctx, NULL);
|
||||||
break;
|
break;
|
||||||
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */
|
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */
|
||||||
|
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO)
|
||||||
|
case PROC_CIS_CREATE:
|
||||||
|
llcp_lp_cc_run(conn, ctx, NULL);
|
||||||
|
break;
|
||||||
|
#endif /* CONFIG_BT_CTLR_CENTRAL_ISO */
|
||||||
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO) || defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
|
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO) || defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
|
||||||
case PROC_CIS_TERMINATE:
|
case PROC_CIS_TERMINATE:
|
||||||
llcp_lp_comm_run(conn, ctx, NULL);
|
llcp_lp_comm_run(conn, ctx, NULL);
|
||||||
|
|
|
@ -845,6 +845,92 @@ void llcp_pdu_encode_cis_rsp(struct proc_ctx *ctx, struct pdu_data *pdu)
|
||||||
p->conn_event_count = sys_cpu_to_le16(ctx->data.cis_create.conn_event_count);
|
p->conn_event_count = sys_cpu_to_le16(ctx->data.cis_create.conn_event_count);
|
||||||
}
|
}
|
||||||
#endif /* defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) */
|
#endif /* defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) */
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO)
|
||||||
|
void llcp_pdu_encode_cis_req(struct proc_ctx *ctx, struct pdu_data *pdu)
|
||||||
|
{
|
||||||
|
struct pdu_data_llctrl_cis_req *p;
|
||||||
|
|
||||||
|
pdu->ll_id = PDU_DATA_LLID_CTRL;
|
||||||
|
pdu->len = offsetof(struct pdu_data_llctrl, cis_req) +
|
||||||
|
sizeof(struct pdu_data_llctrl_cis_req);
|
||||||
|
pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_CIS_REQ;
|
||||||
|
|
||||||
|
p = &pdu->llctrl.cis_req;
|
||||||
|
|
||||||
|
p->cig_id = ctx->data.cis_create.cig_id;
|
||||||
|
p->cis_id = ctx->data.cis_create.cis_id;
|
||||||
|
p->c_phy = ctx->data.cis_create.c_phy;
|
||||||
|
p->p_phy = ctx->data.cis_create.p_phy;
|
||||||
|
p->nse = ctx->data.cis_create.nse;
|
||||||
|
p->c_bn = ctx->data.cis_create.c_bn;
|
||||||
|
p->p_bn = ctx->data.cis_create.p_bn;
|
||||||
|
p->c_ft = ctx->data.cis_create.c_ft;
|
||||||
|
p->p_ft = ctx->data.cis_create.p_ft;
|
||||||
|
|
||||||
|
sys_put_le24(ctx->data.cis_create.c_sdu_interval, p->c_sdu_interval);
|
||||||
|
sys_put_le24(ctx->data.cis_create.p_sdu_interval, p->p_sdu_interval);
|
||||||
|
sys_put_le24(ctx->data.cis_create.cis_offset_max, p->cis_offset_max);
|
||||||
|
sys_put_le24(ctx->data.cis_create.cis_offset_min, p->cis_offset_min);
|
||||||
|
sys_put_le24(ctx->data.cis_create.sub_interval, p->sub_interval);
|
||||||
|
|
||||||
|
p->c_max_pdu = sys_cpu_to_le16(ctx->data.cis_create.c_max_pdu);
|
||||||
|
p->p_max_pdu = sys_cpu_to_le16(ctx->data.cis_create.p_max_pdu);
|
||||||
|
p->iso_interval = sys_cpu_to_le16(ctx->data.cis_create.iso_interval);
|
||||||
|
p->conn_event_count = sys_cpu_to_le16(ctx->data.cis_create.conn_event_count);
|
||||||
|
|
||||||
|
p->c_max_sdu_packed[0] = ctx->data.cis_create.c_max_sdu & 0xFF;
|
||||||
|
p->c_max_sdu_packed[1] = ((ctx->data.cis_create.c_max_sdu >> 8) & 0x0F) |
|
||||||
|
(ctx->data.cis_create.framed << 7);
|
||||||
|
p->p_max_sdu[0] = ctx->data.cis_create.p_max_sdu & 0xFF;
|
||||||
|
p->p_max_sdu[1] = (ctx->data.cis_create.p_max_sdu >> 8) & 0x0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
void llcp_pdu_decode_cis_rsp(struct proc_ctx *ctx, struct pdu_data *pdu)
|
||||||
|
{
|
||||||
|
/* Limit response to valid range */
|
||||||
|
uint32_t cis_offset_min = sys_get_le24(pdu->llctrl.cis_rsp.cis_offset_min);
|
||||||
|
uint32_t cis_offset_max = sys_get_le24(pdu->llctrl.cis_rsp.cis_offset_max);
|
||||||
|
|
||||||
|
/* TODO: Fail procedure if offsets are invalid? */
|
||||||
|
if (cis_offset_min <= cis_offset_max &&
|
||||||
|
cis_offset_min >= ctx->data.cis_create.cis_offset_min &&
|
||||||
|
cis_offset_min <= ctx->data.cis_create.cis_offset_max &&
|
||||||
|
cis_offset_max <= ctx->data.cis_create.cis_offset_max &&
|
||||||
|
cis_offset_max >= ctx->data.cis_create.cis_offset_min) {
|
||||||
|
/* Offsets are valid */
|
||||||
|
ctx->data.cis_create.cis_offset_min = cis_offset_min;
|
||||||
|
ctx->data.cis_create.cis_offset_max = cis_offset_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->data.cis_create.conn_event_count =
|
||||||
|
sys_le16_to_cpu(pdu->llctrl.cis_rsp.conn_event_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void llcp_pdu_encode_cis_ind(struct proc_ctx *ctx, struct pdu_data *pdu)
|
||||||
|
{
|
||||||
|
struct pdu_data_llctrl_cis_ind *p;
|
||||||
|
|
||||||
|
pdu->ll_id = PDU_DATA_LLID_CTRL;
|
||||||
|
pdu->len = offsetof(struct pdu_data_llctrl, cis_ind) +
|
||||||
|
sizeof(struct pdu_data_llctrl_cis_ind);
|
||||||
|
pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_CIS_IND;
|
||||||
|
|
||||||
|
p = &pdu->llctrl.cis_ind;
|
||||||
|
|
||||||
|
p->aa[0] = ctx->data.cis_create.aa[0];
|
||||||
|
p->aa[1] = ctx->data.cis_create.aa[1];
|
||||||
|
p->aa[2] = ctx->data.cis_create.aa[2];
|
||||||
|
p->aa[3] = ctx->data.cis_create.aa[3];
|
||||||
|
|
||||||
|
sys_put_le24(ctx->data.cis_create.cis_offset_min, p->cis_offset);
|
||||||
|
sys_put_le24(ctx->data.cis_create.cig_sync_delay, p->cig_sync_delay);
|
||||||
|
sys_put_le24(ctx->data.cis_create.cis_sync_delay, p->cis_sync_delay);
|
||||||
|
|
||||||
|
p->conn_event_count = sys_cpu_to_le16(ctx->data.cis_create.conn_event_count);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_BT_CTLR_CENTRAL_ISO */
|
||||||
|
|
||||||
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO) || defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
|
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO) || defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
|
||||||
void llcp_pdu_encode_cis_terminate_ind(struct proc_ctx *ctx, struct pdu_data *pdu)
|
void llcp_pdu_encode_cis_terminate_ind(struct proc_ctx *ctx, struct pdu_data *pdu)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue