Bluetooth: controller: Adding user ext. anchor point move to ctrl/CPR

Adding support for allowing user extension code to support deferring
anchor point moves. Refactored LLCP only.
Note: This is NOT supported by LEGACY LLCP impl.
KConfig'd by BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE
Modified ll_conn_update API, to accommodate passing offsets
Modified CPR/CU context data structure
Modified CPR/CU procedure to handle anchor point move wait state
Fixed up unit tests, adding anchor point move cases to CPR/CU test

Signed-off-by: Erik Brockhoff <erbr@oticon.com>
This commit is contained in:
Erik Brockhoff 2022-08-16 14:01:18 +02:00 committed by Carles Cufí
commit c180afec11
15 changed files with 842 additions and 84 deletions

View file

@ -914,6 +914,14 @@ config BT_CTLR_USER_CPR_INTERVAL_MIN
When enabled, controller will accept Connection Parameter Request When enabled, controller will accept Connection Parameter Request
intervals down to a proprietary minimum value. intervals down to a proprietary minimum value.
config BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE
bool "Proprietary handling of anchor point movement"
depends on BT_CTLR_USER_EXT && BT_CTLR_CONN_PARAM_REQ && BT_PERIPHERAL
help
When enabled, defer accept/reject of Connection Parameter Request with only
anchor point movement to proprietary logic.
Only applicable for peripheral.
endmenu endmenu
comment "BLE Controller debug configuration" comment "BLE Controller debug configuration"

View file

@ -2481,7 +2481,7 @@ static void le_conn_update(struct net_buf *buf, struct net_buf **evt)
status = ll_conn_update(handle, 0, 0, conn_interval_min, status = ll_conn_update(handle, 0, 0, conn_interval_min,
conn_interval_max, conn_latency, conn_interval_max, conn_latency,
supervision_timeout); supervision_timeout, NULL);
*evt = cmd_status(status); *evt = cmd_status(status);
} }
@ -2505,7 +2505,7 @@ static void le_conn_param_req_reply(struct net_buf *buf, struct net_buf **evt)
timeout = sys_le16_to_cpu(cmd->timeout); timeout = sys_le16_to_cpu(cmd->timeout);
status = ll_conn_update(handle, 2, 0, interval_min, interval_max, status = ll_conn_update(handle, 2, 0, interval_min, interval_max,
latency, timeout); latency, timeout, NULL);
rp = hci_cmd_complete(evt, sizeof(*rp)); rp = hci_cmd_complete(evt, sizeof(*rp));
rp->status = status; rp->status = status;
@ -2521,7 +2521,7 @@ static void le_conn_param_req_neg_reply(struct net_buf *buf,
uint8_t status; uint8_t status;
handle = sys_le16_to_cpu(cmd->handle); handle = sys_le16_to_cpu(cmd->handle);
status = ll_conn_update(handle, 2, cmd->reason, 0, 0, 0, 0); status = ll_conn_update(handle, 2, cmd->reason, 0, 0, 0, 0, NULL);
rp = hci_cmd_complete(evt, sizeof(*rp)); rp = hci_cmd_complete(evt, sizeof(*rp));
rp->status = status; rp->status = status;
@ -8401,7 +8401,7 @@ static void le_conn_param_req(struct pdu_data *pdu_data, uint16_t handle,
!(le_event_mask & BT_EVT_MASK_LE_CONN_PARAM_REQ)) { !(le_event_mask & BT_EVT_MASK_LE_CONN_PARAM_REQ)) {
/* event masked, reject the conn param req */ /* event masked, reject the conn param req */
ll_conn_update(handle, 2, BT_HCI_ERR_UNSUPP_REMOTE_FEATURE, 0, ll_conn_update(handle, 2, BT_HCI_ERR_UNSUPP_REMOTE_FEATURE, 0,
0, 0, 0); 0, 0, 0, NULL);
return; return;
} }

View file

@ -239,7 +239,7 @@ uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window,
#endif /* !CONFIG_BT_CTLR_ADV_EXT */ #endif /* !CONFIG_BT_CTLR_ADV_EXT */
uint8_t ll_connect_disable(void **rx); uint8_t ll_connect_disable(void **rx);
uint8_t ll_conn_update(uint16_t handle, uint8_t cmd, uint8_t status, uint16_t interval_min, uint8_t ll_conn_update(uint16_t handle, uint8_t cmd, uint8_t status, uint16_t interval_min,
uint16_t interval_max, uint16_t latency, uint16_t timeout); uint16_t interval_max, uint16_t latency, uint16_t timeout, uint16_t *offset);
uint8_t ll_chm_update(uint8_t const *const chm); uint8_t ll_chm_update(uint8_t const *const chm);
uint8_t ll_chm_get(uint16_t handle, uint8_t *const chm); uint8_t ll_chm_get(uint16_t handle, uint8_t *const chm);
uint8_t ll_enc_req_send(uint16_t handle, uint8_t const *const rand_num, uint8_t const *const ediv, uint8_t ll_enc_req_send(uint16_t handle, uint8_t const *const rand_num, uint8_t const *const ediv,

View file

@ -390,7 +390,7 @@ int ll_tx_mem_enqueue(uint16_t handle, void *tx)
} }
uint8_t ll_conn_update(uint16_t handle, uint8_t cmd, uint8_t status, uint16_t interval_min, uint8_t ll_conn_update(uint16_t handle, uint8_t cmd, uint8_t status, uint16_t interval_min,
uint16_t interval_max, uint16_t latency, uint16_t timeout) uint16_t interval_max, uint16_t latency, uint16_t timeout, uint16_t *offset)
{ {
struct ll_conn *conn; struct ll_conn *conn;
@ -400,6 +400,8 @@ uint8_t ll_conn_update(uint16_t handle, uint8_t cmd, uint8_t status, uint16_t in
} }
#if defined(CONFIG_BT_LL_SW_LLCP_LEGACY) #if defined(CONFIG_BT_LL_SW_LLCP_LEGACY)
/* Anchor point move not supported in Legacy LLCP */
ARG_UNUSED(offset);
if (!cmd) { if (!cmd) {
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ) #if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
if (!conn->llcp_conn_param.disabled && if (!conn->llcp_conn_param.disabled &&
@ -476,7 +478,8 @@ uint8_t ll_conn_update(uint16_t handle, uint8_t cmd, uint8_t status, uint16_t in
if (cmd == 0U) { if (cmd == 0U) {
uint8_t err; uint8_t err;
err = ull_cp_conn_update(conn, interval_min, interval_max, latency, timeout); err = ull_cp_conn_update(conn, interval_min, interval_max, latency, timeout,
offset);
if (err) { if (err) {
return err; return err;
} }

View file

@ -15,6 +15,30 @@
#define CONN_INTERVAL_MIN(x) (MAX(ull_conn_interval_min_get(x), 1)) #define CONN_INTERVAL_MIN(x) (MAX(ull_conn_interval_min_get(x), 1))
#endif /* CONFIG_BT_CTLR_USER_CPR_INTERVAL_MIN */ #endif /* CONFIG_BT_CTLR_USER_CPR_INTERVAL_MIN */
/**
* User deferance of CPR Anchor Point Move
*/
#if !defined(CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE)
#define DEFER_APM_CHECK(x, y, z) (false)
#else
/* Proprietary handling of peripheral CPR Anchor Point Movement Response
*
* When returning TRUE the LLCP system changes to a
* USER_WAIT state and an EXTERNAL trigger must kick the LLCP system
* to continue to either accept (with possibly changed offsets) or reject CPR
*
* When returning FALSE the LLCP system will automatically
* continue and thus respond immediately
*
* Possibly modified LLCP internal status/error state will determine the type of 'response'
* 0U - Accept CPR (possibly with changed offsets)
* BT_HCI_ERR_UNSUPP_LL_PARAM_VAL - Reject CPR
*/
struct ll_conn;
extern bool ull_handle_cpr_anchor_point_move(struct ll_conn *conn, uint16_t *offsets,
uint8_t *status);
#define DEFER_APM_CHECK(x, y, z) (ull_handle_cpr_anchor_point_move(x, y, z))
#endif /* CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE */
/* Macro to convert time in us to connection interval units */ /* Macro to convert time in us to connection interval units */
#define RADIO_CONN_EVENTS(x, y) ((uint16_t)(((x) + (y) - 1) / (y))) #define RADIO_CONN_EVENTS(x, y) ((uint16_t)(((x) + (y) - 1) / (y)))

View file

@ -972,7 +972,7 @@ uint8_t ull_cp_ltk_req_neq_reply(struct ll_conn *conn)
#endif /* CONFIG_BT_CTLR_LE_ENC */ #endif /* CONFIG_BT_CTLR_LE_ENC */
uint8_t ull_cp_conn_update(struct ll_conn *conn, uint16_t interval_min, uint16_t interval_max, uint8_t ull_cp_conn_update(struct ll_conn *conn, uint16_t interval_min, uint16_t interval_max,
uint16_t latency, uint16_t timeout) uint16_t latency, uint16_t timeout, uint16_t *offsets)
{ {
struct proc_ctx *ctx; struct proc_ctx *ctx;
@ -1006,6 +1006,12 @@ uint8_t ull_cp_conn_update(struct ll_conn *conn, uint16_t interval_min, uint16_t
ctx->data.cu.interval_max = interval_max; ctx->data.cu.interval_max = interval_max;
ctx->data.cu.latency = latency; ctx->data.cu.latency = latency;
ctx->data.cu.timeout = timeout; ctx->data.cu.timeout = timeout;
ctx->data.cu.offsets[0] = offsets ? offsets[0] : 0x0000;
ctx->data.cu.offsets[1] = offsets ? offsets[1] : 0xffff;
ctx->data.cu.offsets[2] = offsets ? offsets[2] : 0xffff;
ctx->data.cu.offsets[3] = offsets ? offsets[3] : 0xffff;
ctx->data.cu.offsets[4] = offsets ? offsets[4] : 0xffff;
ctx->data.cu.offsets[5] = offsets ? offsets[5] : 0xffff;
if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
(conn->lll.role == BT_HCI_ROLE_PERIPHERAL)) { (conn->lll.role == BT_HCI_ROLE_PERIPHERAL)) {
@ -1064,6 +1070,51 @@ uint8_t ull_cp_remote_cpr_pending(struct ll_conn *conn)
return (ctx && ctx->proc == PROC_CONN_PARAM_REQ); return (ctx && ctx->proc == PROC_CONN_PARAM_REQ);
} }
#if defined(CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE)
bool ull_cp_remote_cpr_apm_awaiting_reply(struct ll_conn *conn)
{
struct proc_ctx *ctx;
ctx = llcp_rr_peek(conn);
if (ctx && ctx->proc == PROC_CONN_PARAM_REQ) {
return llcp_rp_conn_param_req_apm_awaiting_reply(ctx);
}
return false;
}
void ull_cp_remote_cpr_apm_reply(struct ll_conn *conn, uint16_t *offsets)
{
struct proc_ctx *ctx;
ctx = llcp_rr_peek(conn);
if (ctx && ctx->proc == PROC_CONN_PARAM_REQ) {
ctx->data.cu.offsets[0] = offsets[0];
ctx->data.cu.offsets[1] = offsets[1];
ctx->data.cu.offsets[2] = offsets[2];
ctx->data.cu.offsets[3] = offsets[3];
ctx->data.cu.offsets[4] = offsets[4];
ctx->data.cu.offsets[5] = offsets[5];
ctx->data.cu.error = 0U;
llcp_rp_conn_param_req_apm_reply(conn, ctx);
}
}
void ull_cp_remote_cpr_apm_neg_reply(struct ll_conn *conn, uint8_t error_code)
{
struct proc_ctx *ctx;
ctx = llcp_rr_peek(conn);
if (ctx && ctx->proc == PROC_CONN_PARAM_REQ) {
ctx->data.cu.error = error_code;
llcp_rp_conn_param_req_apm_reply(conn, ctx);
}
}
#endif /* CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE */
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */ #endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP) #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP)

View file

@ -129,7 +129,7 @@ uint8_t ull_cp_phy_update(struct ll_conn *conn, uint8_t tx, uint8_t flags, uint8
* @brief Initiate a Connection Parameter Request Procedure or Connection Update Procedure * @brief Initiate a Connection Parameter Request Procedure or Connection Update Procedure
*/ */
uint8_t ull_cp_conn_update(struct ll_conn *conn, uint16_t interval_min, uint16_t interval_max, uint8_t ull_cp_conn_update(struct ll_conn *conn, uint16_t interval_min, uint16_t interval_max,
uint16_t latency, uint16_t timeout); uint16_t latency, uint16_t timeout, uint16_t *offsets);
/** /**
* @brief Accept the remote devices request to change connection parameters. * @brief Accept the remote devices request to change connection parameters.
@ -152,6 +152,24 @@ uint8_t ull_cp_remote_dle_pending(struct ll_conn *conn);
*/ */
uint8_t ull_cp_remote_cpr_pending(struct ll_conn *conn); uint8_t ull_cp_remote_cpr_pending(struct ll_conn *conn);
/**
* @brief Check if a remote connection param reg is expecting an
* anchor point move response.
*/
bool ull_cp_remote_cpr_apm_awaiting_reply(struct ll_conn *conn);
/**
* @brief Repsond to anchor point move of remote connection
* param reg.
*/
void ull_cp_remote_cpr_apm_reply(struct ll_conn *conn, uint16_t *offsets);
/**
* @brief Reject anchor point move of remote connection param
* reg.
*/
void ull_cp_remote_cpr_apm_neg_reply(struct ll_conn *conn, uint8_t error_code);
/** /**
* @brief Initiate a Termination Procedure. * @brief Initiate a Termination Procedure.
*/ */

View file

@ -115,6 +115,7 @@ enum {
RP_CU_STATE_WAIT_CONN_PARAM_REQ_REPLY, RP_CU_STATE_WAIT_CONN_PARAM_REQ_REPLY,
RP_CU_STATE_WAIT_CONN_PARAM_REQ_REPLY_CONTINUE, RP_CU_STATE_WAIT_CONN_PARAM_REQ_REPLY_CONTINUE,
RP_CU_STATE_WAIT_TX_REJECT_EXT_IND, RP_CU_STATE_WAIT_TX_REJECT_EXT_IND,
RP_CU_STATE_WAIT_USER_REPLY,
RP_CU_STATE_WAIT_TX_CONN_PARAM_RSP, RP_CU_STATE_WAIT_TX_CONN_PARAM_RSP,
RP_CU_STATE_WAIT_TX_CONN_UPDATE_IND, RP_CU_STATE_WAIT_TX_CONN_UPDATE_IND,
RP_CU_STATE_WAIT_RX_CONN_UPDATE_IND, RP_CU_STATE_WAIT_RX_CONN_UPDATE_IND,
@ -139,6 +140,9 @@ enum {
/* CONN_PARAM_REQ negative reply */ /* CONN_PARAM_REQ negative reply */
RP_CU_EVT_CONN_PARAM_REQ_NEG_REPLY, RP_CU_EVT_CONN_PARAM_REQ_NEG_REPLY,
/* CONN_PARAM_REQ Ancjor Point Move reply */
RP_CU_EVT_CONN_PARAM_REQ_USER_REPLY,
}; };
/* /*
@ -197,7 +201,6 @@ static void cu_prepare_update_ind(struct ll_conn *conn, struct proc_ctx *ctx)
ctx->data.cu.win_size = 1U; ctx->data.cu.win_size = 1U;
ctx->data.cu.win_offset_us = 0U; ctx->data.cu.win_offset_us = 0U;
ctx->data.cu.instant = ull_conn_event_counter(conn) + conn->lll.latency + ctx->data.cu.instant = ull_conn_event_counter(conn) + conn->lll.latency +
CONN_UPDATE_INSTANT_DELTA; CONN_UPDATE_INSTANT_DELTA;
} }
@ -336,12 +339,6 @@ static void lp_cu_send_conn_param_req(struct ll_conn *conn, struct proc_ctx *ctx
ctx->data.cu.reference_conn_event_count = event_counter; ctx->data.cu.reference_conn_event_count = event_counter;
ctx->data.cu.preferred_periodicity = 0U; ctx->data.cu.preferred_periodicity = 0U;
ctx->data.cu.offset0 = 0x0000U;
ctx->data.cu.offset1 = 0xffffU;
ctx->data.cu.offset2 = 0xffffU;
ctx->data.cu.offset3 = 0xffffU;
ctx->data.cu.offset4 = 0xffffU;
ctx->data.cu.offset5 = 0xffffU;
/* Mark CPR as active */ /* Mark CPR as active */
cpr_active_set(conn); cpr_active_set(conn);
@ -908,6 +905,16 @@ static void rp_cu_st_wait_conn_param_req_available(struct ll_conn *conn, struct
if (params_changed) { if (params_changed) {
rp_cu_send_conn_param_req_ntf(conn, ctx, evt, param); rp_cu_send_conn_param_req_ntf(conn, ctx, evt, param);
} else { } else {
#if defined(CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE)
/* Handle APM as a vendor specific user extension */
if (conn->lll.role == BT_HCI_ROLE_PERIPHERAL &&
DEFER_APM_CHECK(conn, ctx->data.cu.offsets,
&ctx->data.cu.error)) {
/* Wait for user response */
ctx->state = RP_CU_STATE_WAIT_USER_REPLY;
break;
}
#endif /* CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE */
ctx->state = RP_CU_STATE_WAIT_CONN_PARAM_REQ_REPLY_CONTINUE; ctx->state = RP_CU_STATE_WAIT_CONN_PARAM_REQ_REPLY_CONTINUE;
} }
} }
@ -917,8 +924,8 @@ static void rp_cu_st_wait_conn_param_req_available(struct ll_conn *conn, struct
} }
} }
static void rp_cu_st_wait_rx_conn_param_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, static void rp_cu_st_wait_rx_conn_param_req(struct ll_conn *conn, struct proc_ctx *ctx,
void *param) uint8_t evt, void *param)
{ {
switch (evt) { switch (evt) {
case RP_CU_EVT_CONN_PARAM_REQ: case RP_CU_EVT_CONN_PARAM_REQ:
@ -981,7 +988,13 @@ static void rp_cu_state_wait_conn_param_req_reply_continue(struct ll_conn *conn,
if (conn->lll.role == BT_HCI_ROLE_CENTRAL) { if (conn->lll.role == BT_HCI_ROLE_CENTRAL) {
rp_cu_send_conn_update_ind(conn, ctx, evt, param); rp_cu_send_conn_update_ind(conn, ctx, evt, param);
} else if (conn->lll.role == BT_HCI_ROLE_PERIPHERAL) { } else if (conn->lll.role == BT_HCI_ROLE_PERIPHERAL) {
rp_cu_send_conn_param_rsp(conn, ctx, evt, param); if (!ctx->data.cu.error) {
rp_cu_send_conn_param_rsp(conn, ctx, evt, param);
} else {
ctx->data.cu.rejected_opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ;
rp_cu_send_reject_ext_ind(conn, ctx, evt, param);
}
} else { } else {
/* Unknown role */ /* Unknown role */
LL_ASSERT(0); LL_ASSERT(0);
@ -1018,6 +1031,22 @@ static void rp_cu_st_wait_tx_conn_param_rsp(struct ll_conn *conn, struct proc_ct
break; break;
} }
} }
#if defined(CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE)
static void rp_cu_st_wait_user_response(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param)
{
switch (evt) {
case RP_CU_EVT_CONN_PARAM_REQ_USER_REPLY:
/* Continue procedure in next prepare run */
ctx->state = RP_CU_STATE_WAIT_CONN_PARAM_REQ_REPLY_CONTINUE;
break;
default:
/* Ignore other evts */
break;
}
}
#endif /* CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE */
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */ #endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
static void rp_cu_st_wait_tx_conn_update_ind(struct ll_conn *conn, struct proc_ctx *ctx, static void rp_cu_st_wait_tx_conn_update_ind(struct ll_conn *conn, struct proc_ctx *ctx,
@ -1151,6 +1180,11 @@ static void rp_cu_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint8_
case RP_CU_STATE_WAIT_TX_CONN_PARAM_RSP: case RP_CU_STATE_WAIT_TX_CONN_PARAM_RSP:
rp_cu_st_wait_tx_conn_param_rsp(conn, ctx, evt, param); rp_cu_st_wait_tx_conn_param_rsp(conn, ctx, evt, param);
break; break;
#if defined(CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE)
case RP_CU_STATE_WAIT_USER_REPLY:
rp_cu_st_wait_user_response(conn, ctx, evt, param);
break;
#endif /* CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE */
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */ #endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
case RP_CU_STATE_WAIT_TX_CONN_UPDATE_IND: case RP_CU_STATE_WAIT_TX_CONN_UPDATE_IND:
rp_cu_st_wait_tx_conn_update_ind(conn, ctx, evt, param); rp_cu_st_wait_tx_conn_update_ind(conn, ctx, evt, param);
@ -1213,4 +1247,16 @@ void llcp_rp_conn_param_req_neg_reply(struct ll_conn *conn, struct proc_ctx *ctx
{ {
rp_cu_execute_fsm(conn, ctx, RP_CU_EVT_CONN_PARAM_REQ_NEG_REPLY, NULL); rp_cu_execute_fsm(conn, ctx, RP_CU_EVT_CONN_PARAM_REQ_NEG_REPLY, NULL);
} }
#if defined(CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE)
bool llcp_rp_conn_param_req_apm_awaiting_reply(struct proc_ctx *ctx)
{
return (ctx->state == RP_CU_STATE_WAIT_USER_REPLY);
}
void llcp_rp_conn_param_req_apm_reply(struct ll_conn *conn, struct proc_ctx *ctx)
{
rp_cu_execute_fsm(conn, ctx, RP_CU_EVT_CONN_PARAM_REQ_USER_REPLY, NULL);
}
#endif /* CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE */
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */ #endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */

View file

@ -219,12 +219,7 @@ struct proc_ctx {
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ) #if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
uint8_t preferred_periodicity; uint8_t preferred_periodicity;
uint16_t reference_conn_event_count; uint16_t reference_conn_event_count;
uint16_t offset0; uint16_t offsets[6];
uint16_t offset1;
uint16_t offset2;
uint16_t offset3;
uint16_t offset4;
uint16_t offset5;
#endif /* defined(CONFIG_BT_CTLR_CONN_PARAM_REQ) */ #endif /* defined(CONFIG_BT_CTLR_CONN_PARAM_REQ) */
} cu; } cu;
@ -498,6 +493,8 @@ void llcp_rp_cu_init_proc(struct proc_ctx *ctx);
void llcp_rp_cu_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param); void llcp_rp_cu_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param);
void llcp_rp_conn_param_req_reply(struct ll_conn *conn, struct proc_ctx *ctx); void llcp_rp_conn_param_req_reply(struct ll_conn *conn, struct proc_ctx *ctx);
void llcp_rp_conn_param_req_neg_reply(struct ll_conn *conn, struct proc_ctx *ctx); void llcp_rp_conn_param_req_neg_reply(struct ll_conn *conn, struct proc_ctx *ctx);
bool llcp_rp_conn_param_req_apm_awaiting_reply(struct proc_ctx *ctx);
void llcp_rp_conn_param_req_apm_reply(struct ll_conn *conn, struct proc_ctx *ctx);
/* /*
* Terminate Helper * Terminate Helper

View file

@ -505,12 +505,12 @@ void llcp_pdu_encode_conn_param_req(struct proc_ctx *ctx, struct pdu_data *pdu)
p->timeout = sys_cpu_to_le16(ctx->data.cu.timeout); p->timeout = sys_cpu_to_le16(ctx->data.cu.timeout);
p->preferred_periodicity = ctx->data.cu.preferred_periodicity; p->preferred_periodicity = ctx->data.cu.preferred_periodicity;
p->reference_conn_event_count = sys_cpu_to_le16(ctx->data.cu.reference_conn_event_count); p->reference_conn_event_count = sys_cpu_to_le16(ctx->data.cu.reference_conn_event_count);
p->offset0 = sys_cpu_to_le16(ctx->data.cu.offset0); p->offset0 = sys_cpu_to_le16(ctx->data.cu.offsets[0]);
p->offset1 = sys_cpu_to_le16(ctx->data.cu.offset1); p->offset1 = sys_cpu_to_le16(ctx->data.cu.offsets[1]);
p->offset2 = sys_cpu_to_le16(ctx->data.cu.offset2); p->offset2 = sys_cpu_to_le16(ctx->data.cu.offsets[2]);
p->offset3 = sys_cpu_to_le16(ctx->data.cu.offset3); p->offset3 = sys_cpu_to_le16(ctx->data.cu.offsets[3]);
p->offset4 = sys_cpu_to_le16(ctx->data.cu.offset4); p->offset4 = sys_cpu_to_le16(ctx->data.cu.offsets[4]);
p->offset5 = sys_cpu_to_le16(ctx->data.cu.offset5); p->offset5 = sys_cpu_to_le16(ctx->data.cu.offsets[5]);
} }
void llcp_pdu_encode_conn_param_rsp(struct proc_ctx *ctx, struct pdu_data *pdu) void llcp_pdu_encode_conn_param_rsp(struct proc_ctx *ctx, struct pdu_data *pdu)
@ -528,12 +528,12 @@ void llcp_pdu_encode_conn_param_rsp(struct proc_ctx *ctx, struct pdu_data *pdu)
p->timeout = sys_cpu_to_le16(ctx->data.cu.timeout); p->timeout = sys_cpu_to_le16(ctx->data.cu.timeout);
p->preferred_periodicity = ctx->data.cu.preferred_periodicity; p->preferred_periodicity = ctx->data.cu.preferred_periodicity;
p->reference_conn_event_count = sys_cpu_to_le16(ctx->data.cu.reference_conn_event_count); p->reference_conn_event_count = sys_cpu_to_le16(ctx->data.cu.reference_conn_event_count);
p->offset0 = sys_cpu_to_le16(ctx->data.cu.offset0); p->offset0 = sys_cpu_to_le16(ctx->data.cu.offsets[0]);
p->offset1 = sys_cpu_to_le16(ctx->data.cu.offset1); p->offset1 = sys_cpu_to_le16(ctx->data.cu.offsets[1]);
p->offset2 = sys_cpu_to_le16(ctx->data.cu.offset2); p->offset2 = sys_cpu_to_le16(ctx->data.cu.offsets[2]);
p->offset3 = sys_cpu_to_le16(ctx->data.cu.offset3); p->offset3 = sys_cpu_to_le16(ctx->data.cu.offsets[3]);
p->offset4 = sys_cpu_to_le16(ctx->data.cu.offset4); p->offset4 = sys_cpu_to_le16(ctx->data.cu.offsets[4]);
p->offset5 = sys_cpu_to_le16(ctx->data.cu.offset5); p->offset5 = sys_cpu_to_le16(ctx->data.cu.offsets[5]);
} }
void llcp_pdu_decode_conn_param_req(struct proc_ctx *ctx, struct pdu_data *pdu) void llcp_pdu_decode_conn_param_req(struct proc_ctx *ctx, struct pdu_data *pdu)
@ -547,12 +547,12 @@ void llcp_pdu_decode_conn_param_req(struct proc_ctx *ctx, struct pdu_data *pdu)
ctx->data.cu.timeout = sys_le16_to_cpu(p->timeout); ctx->data.cu.timeout = sys_le16_to_cpu(p->timeout);
ctx->data.cu.preferred_periodicity = p->preferred_periodicity; ctx->data.cu.preferred_periodicity = p->preferred_periodicity;
ctx->data.cu.reference_conn_event_count = sys_le16_to_cpu(p->reference_conn_event_count); ctx->data.cu.reference_conn_event_count = sys_le16_to_cpu(p->reference_conn_event_count);
ctx->data.cu.offset0 = sys_le16_to_cpu(p->offset0); ctx->data.cu.offsets[0] = sys_le16_to_cpu(p->offset0);
ctx->data.cu.offset1 = sys_le16_to_cpu(p->offset1); ctx->data.cu.offsets[1] = sys_le16_to_cpu(p->offset1);
ctx->data.cu.offset2 = sys_le16_to_cpu(p->offset2); ctx->data.cu.offsets[2] = sys_le16_to_cpu(p->offset2);
ctx->data.cu.offset3 = sys_le16_to_cpu(p->offset3); ctx->data.cu.offsets[3] = sys_le16_to_cpu(p->offset3);
ctx->data.cu.offset4 = sys_le16_to_cpu(p->offset4); ctx->data.cu.offsets[4] = sys_le16_to_cpu(p->offset4);
ctx->data.cu.offset5 = sys_le16_to_cpu(p->offset5); ctx->data.cu.offsets[5] = sys_le16_to_cpu(p->offset5);
} }
void llcp_pdu_decode_conn_param_rsp(struct proc_ctx *ctx, struct pdu_data *pdu) void llcp_pdu_decode_conn_param_rsp(struct proc_ctx *ctx, struct pdu_data *pdu)
@ -566,12 +566,12 @@ void llcp_pdu_decode_conn_param_rsp(struct proc_ctx *ctx, struct pdu_data *pdu)
ctx->data.cu.timeout = sys_le16_to_cpu(p->timeout); ctx->data.cu.timeout = sys_le16_to_cpu(p->timeout);
ctx->data.cu.preferred_periodicity = p->preferred_periodicity; ctx->data.cu.preferred_periodicity = p->preferred_periodicity;
ctx->data.cu.reference_conn_event_count = sys_le16_to_cpu(p->reference_conn_event_count); ctx->data.cu.reference_conn_event_count = sys_le16_to_cpu(p->reference_conn_event_count);
ctx->data.cu.offset0 = sys_le16_to_cpu(p->offset0); ctx->data.cu.offsets[0] = sys_le16_to_cpu(p->offset0);
ctx->data.cu.offset1 = sys_le16_to_cpu(p->offset1); ctx->data.cu.offsets[1] = sys_le16_to_cpu(p->offset1);
ctx->data.cu.offset2 = sys_le16_to_cpu(p->offset2); ctx->data.cu.offsets[2] = sys_le16_to_cpu(p->offset2);
ctx->data.cu.offset3 = sys_le16_to_cpu(p->offset3); ctx->data.cu.offsets[3] = sys_le16_to_cpu(p->offset3);
ctx->data.cu.offset4 = sys_le16_to_cpu(p->offset4); ctx->data.cu.offsets[4] = sys_le16_to_cpu(p->offset4);
ctx->data.cu.offset5 = sys_le16_to_cpu(p->offset5); ctx->data.cu.offsets[5] = sys_le16_to_cpu(p->offset5);
} }
#endif /* defined(CONFIG_BT_CTLR_CONN_PARAM_REQ) */ #endif /* defined(CONFIG_BT_CTLR_CONN_PARAM_REQ) */

View file

@ -204,9 +204,6 @@ static void test_cc_create_periph_rem_host_accept(void)
/* Done */ /* Done */
event_done(&conn); event_done(&conn);
/* There should NOT be a host notification */
ut_rx_q_is_empty();
/* Prepare */ /* Prepare */
event_prepare(&conn); event_prepare(&conn);

View file

@ -0,0 +1,13 @@
/*
* Copyright (c) 2021 Demant
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* Override common Kconfig settings
*/
#ifndef CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE
#define CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE
#endif

View file

@ -165,7 +165,16 @@ struct pdu_data_llctrl_conn_update_ind *cu_ind_B = &conn_update_ind_B;
static struct ll_conn conn; static struct ll_conn conn;
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ) #if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
#if defined(CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE)
bool ull_handle_cpr_anchor_point_move(struct ll_conn *conn, uint16_t *offsets, uint8_t *status)
{
ztest_copy_return_data(status, 1);
return ztest_get_return_value();
}
#endif /* CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE */
static void test_unmask_feature_conn_param_req(struct ll_conn *conn) static void test_unmask_feature_conn_param_req(struct ll_conn *conn)
{ {
conn->llcp.fex.features_used &= ~BIT64(BT_LE_FEAT_BIT_CONN_PARAM_REQ); conn->llcp.fex.features_used &= ~BIT64(BT_LE_FEAT_BIT_CONN_PARAM_REQ);
@ -187,6 +196,7 @@ static void setup(void)
lll->interval = 0; lll->interval = 0;
lll->latency = 0; lll->latency = 0;
conn.supervision_reload = 1U; conn.supervision_reload = 1U;
lll->event_counter = 0;
} }
static bool is_instant_reached(struct ll_conn *conn, uint16_t instant) static bool is_instant_reached(struct ll_conn *conn, uint16_t instant)
@ -238,7 +248,7 @@ void test_conn_update_central_loc_accept(void)
ull_cp_state_set(&conn, ULL_CP_CONNECTED); ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */ /* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT); err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT, NULL);
zassert_equal(err, BT_HCI_ERR_SUCCESS); zassert_equal(err, BT_HCI_ERR_SUCCESS);
/* Prepare */ /* Prepare */
@ -311,6 +321,7 @@ void test_conn_update_central_loc_accept(void)
"Free CTX buffers %d", ctx_buffers_free()); "Free CTX buffers %d", ctx_buffers_free());
} }
/* /*
* Central-initiated Connection Parameters Request procedure. * Central-initiated Connection Parameters Request procedure.
* Central requests change in LE connection parameters, peripherals Host accepts. * Central requests change in LE connection parameters, peripherals Host accepts.
@ -390,7 +401,7 @@ void test_conn_update_central_loc_accept_reject_2nd_cpr(void)
ull_cp_state_set(&conn_3rd, ULL_CP_CONNECTED); ull_cp_state_set(&conn_3rd, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */ /* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT); err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT, NULL);
zassert_equal(err, BT_HCI_ERR_SUCCESS); zassert_equal(err, BT_HCI_ERR_SUCCESS);
/* Prepare */ /* Prepare */
@ -473,7 +484,7 @@ void test_conn_update_central_loc_accept_reject_2nd_cpr(void)
ull_cp_release_tx(&conn_3rd, tx); ull_cp_release_tx(&conn_3rd, tx);
/* Initiate a parallel Connection Parameter Request Procedure */ /* Initiate a parallel Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn_3rd, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT); err = ull_cp_conn_update(&conn_3rd, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT, NULL);
zassert_equal(err, BT_HCI_ERR_SUCCESS); zassert_equal(err, BT_HCI_ERR_SUCCESS);
/* Prepare */ /* Prepare */
@ -611,7 +622,7 @@ void test_conn_update_central_loc_invalid_param_rsp(void)
ull_cp_state_set(&conn, ULL_CP_CONNECTED); ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */ /* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT); err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT, NULL);
zassert_equal(err, BT_HCI_ERR_SUCCESS); zassert_equal(err, BT_HCI_ERR_SUCCESS);
/* Prepare */ /* Prepare */
@ -680,7 +691,7 @@ void test_conn_update_central_loc_invalid_rsp(void)
ull_cp_state_set(&conn, ULL_CP_CONNECTED); ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */ /* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT); err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT, NULL);
zassert_equal(err, BT_HCI_ERR_SUCCESS); zassert_equal(err, BT_HCI_ERR_SUCCESS);
/* Prepare */ /* Prepare */
@ -753,7 +764,7 @@ void test_conn_update_central_loc_reject(void)
ull_cp_state_set(&conn, ULL_CP_CONNECTED); ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */ /* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT); err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT, NULL);
zassert_equal(err, BT_HCI_ERR_SUCCESS); zassert_equal(err, BT_HCI_ERR_SUCCESS);
/* Prepare */ /* Prepare */
@ -832,7 +843,7 @@ void test_conn_update_central_loc_remote_legacy(void)
ull_cp_state_set(&conn, ULL_CP_CONNECTED); ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */ /* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT); err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT, NULL);
zassert_equal(err, BT_HCI_ERR_SUCCESS); zassert_equal(err, BT_HCI_ERR_SUCCESS);
/* Prepare */ /* Prepare */
@ -957,7 +968,7 @@ void test_conn_update_central_loc_unsupp_wo_feat_exch(void)
ull_cp_state_set(&conn, ULL_CP_CONNECTED); ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */ /* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT); err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT, NULL);
zassert_equal(err, BT_HCI_ERR_SUCCESS); zassert_equal(err, BT_HCI_ERR_SUCCESS);
/* Prepare */ /* Prepare */
@ -1074,7 +1085,7 @@ void test_conn_update_central_loc_unsupp_w_feat_exch(void)
ull_cp_state_set(&conn, ULL_CP_CONNECTED); ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */ /* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT); err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT, NULL);
zassert_equal(err, BT_HCI_ERR_SUCCESS); zassert_equal(err, BT_HCI_ERR_SUCCESS);
/* Prepare */ /* Prepare */
@ -1197,7 +1208,7 @@ void test_conn_update_central_loc_collision(void)
ull_cp_state_set(&conn, ULL_CP_CONNECTED); ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* (A) Initiate a Connection Parameter Request Procedure */ /* (A) Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT); err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT, NULL);
zassert_equal(err, BT_HCI_ERR_SUCCESS); zassert_equal(err, BT_HCI_ERR_SUCCESS);
/* Prepare */ /* Prepare */
@ -1648,7 +1659,7 @@ void test_conn_update_central_rem_collision(void)
/* (B) Initiate a Connection Parameter Request Procedure */ /* (B) Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, req_B->interval_min, req_B->interval_max, req_B->latency, err = ull_cp_conn_update(&conn, req_B->interval_min, req_B->interval_max, req_B->latency,
req_B->timeout); req_B->timeout, NULL);
zassert_equal(err, BT_HCI_ERR_SUCCESS); zassert_equal(err, BT_HCI_ERR_SUCCESS);
/* Prepare */ /* Prepare */
@ -1830,7 +1841,7 @@ void test_conn_update_periph_loc_accept(void)
ull_cp_state_set(&conn, ULL_CP_CONNECTED); ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */ /* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT); err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT, NULL);
zassert_equal(err, BT_HCI_ERR_SUCCESS); zassert_equal(err, BT_HCI_ERR_SUCCESS);
/* Prepare */ /* Prepare */
@ -1935,7 +1946,7 @@ void test_conn_update_periph_loc_reject(void)
ull_cp_state_set(&conn, ULL_CP_CONNECTED); ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */ /* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT); err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT, NULL);
zassert_equal(err, BT_HCI_ERR_SUCCESS); zassert_equal(err, BT_HCI_ERR_SUCCESS);
/* Prepare */ /* Prepare */
@ -2014,7 +2025,7 @@ void test_conn_update_periph_loc_unsupp_feat_wo_feat_exch(void)
ull_cp_state_set(&conn, ULL_CP_CONNECTED); ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */ /* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT); err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT, NULL);
zassert_equal(err, BT_HCI_ERR_SUCCESS); zassert_equal(err, BT_HCI_ERR_SUCCESS);
/* Prepare */ /* Prepare */
@ -2081,7 +2092,7 @@ void test_conn_update_periph_loc_unsupp_feat_w_feat_exch(void)
ull_cp_state_set(&conn, ULL_CP_CONNECTED); ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */ /* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT); err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT, NULL);
zassert_equal(err, BT_HCI_ERR_UNSUPP_REMOTE_FEATURE); zassert_equal(err, BT_HCI_ERR_UNSUPP_REMOTE_FEATURE);
/* Prepare */ /* Prepare */
@ -2175,7 +2186,7 @@ void test_conn_update_periph_loc_collision(void)
ull_cp_state_set(&conn, ULL_CP_CONNECTED); ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* (A) Initiate a Connection Parameter Request Procedure */ /* (A) Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT); err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT, NULL);
zassert_equal(err, BT_HCI_ERR_SUCCESS); zassert_equal(err, BT_HCI_ERR_SUCCESS);
/* Prepare */ /* Prepare */
@ -2422,6 +2433,584 @@ void test_conn_update_periph_rem_accept(void)
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(), zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free()); "Free CTX buffers %d", ctx_buffers_free());
} }
#define RADIO_CONN_EVENTS(x, y) ((uint16_t)(((x) + (y) - 1) / (y)))
/*
* Central-initiated Connection Parameters Request procedure - only anchor point move.
* Central requests change in anchor point only on LE connection, peripherals Host accepts.
*
* +-----+ +-------+ +-----+
* | UT | | LL_P | | LT |
* +-----+ +-------+ +-----+
* | | |
* | | LL_CONNECTION_PARAM_REQ |
* | | (only apm) |
* | |<--------------------------|
* | | |
* | Defered APM disabled | |
* | '<---------' | |
* | So accepted right away | |
* | '--------->' | |
* | | |
* | | LL_CONNECTION_PARAM_RSP |
* | |-------------------------->|
* | | |
* | | LL_CONNECTION_UPDATE_IND |
* | |<--------------------------|
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | | |
*/
void test_conn_update_periph_rem_apm_accept_right_away(void)
{
#if defined(CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE)
struct node_tx *tx;
uint16_t instant;
/* Default conn_param_req PDU */
struct pdu_data_llctrl_conn_param_req conn_param_req_apm = { .interval_min = INTVL_MIN,
.interval_max = INTVL_MAX,
.latency = LATENCY,
.timeout = TIMEOUT,
.preferred_periodicity = 0U,
.reference_conn_event_count = 0u,
.offset0 = 0x0008U,
.offset1 = 0xffffU,
.offset2 = 0xffffU,
.offset3 = 0xffffU,
.offset4 = 0xffffU,
.offset5 = 0xffffU };
/* Default conn_param_rsp PDU */
struct pdu_data_llctrl_conn_param_rsp conn_param_rsp_apm = { .interval_min = INTVL_MIN,
.interval_max = INTVL_MAX,
.latency = LATENCY,
.timeout = TIMEOUT,
.preferred_periodicity = 0U,
.reference_conn_event_count = 0u,
.offset0 = 0x008U,
.offset1 = 0xffffU,
.offset2 = 0xffffU,
.offset3 = 0xffffU,
.offset4 = 0xffffU,
.offset5 = 0xffffU };
uint8_t error = 0;
/* Prepare mocked call to ull_handle_cpr_anchor_point_move */
/* No APM deferance, accept with error == 0 */
ztest_returns_value(ull_handle_cpr_anchor_point_move, false);
ztest_return_data(ull_handle_cpr_anchor_point_move, status, &error);
/* Role */
test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
conn.lll.interval = conn_param_req_apm.interval_max;
conn.lll.latency = conn_param_req_apm.latency;
conn.supervision_reload = RADIO_CONN_EVENTS(TIMEOUT * 10000U, conn.lll.interval *
CONN_INT_UNIT_US);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Rx */
lt_tx(LL_CONNECTION_PARAM_REQ, &conn, &conn_param_req_apm);
/* Done */
event_done(&conn);
/*******************/
/* There should be no host notification */
ut_rx_q_is_empty();
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
lt_rx(LL_CONNECTION_PARAM_RSP, &conn, &tx, &conn_param_rsp_apm);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* Prepare */
event_prepare(&conn);
/* Rx */
conn_update_ind.instant = event_counter(&conn) + 6U;
instant = conn_update_ind.instant;
lt_tx(LL_CONNECTION_UPDATE_IND, &conn, &conn_update_ind);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* */
while (!is_instant_reached(&conn, instant)) {
/* Prepare */
event_prepare(&conn);
/* Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* There should NOT be a host notification */
ut_rx_q_is_empty();
}
/* Prepare */
event_prepare(&conn);
/* Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* There should be no host notification */
ut_rx_q_is_empty();
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
#endif
}
/*
* Central-initiated Connection Parameters Request procedure - only anchor point move.
* Central requests change in anchor point only on LE connection, peripherals Host accepts.
*
* +-----+ +-------+ +-----+
* | UT | | LL_P | | LT |
* +-----+ +-------+ +-----+
* | | |
* | | LL_CONNECTION_PARAM_REQ |
* | | (only apm) |
* | |<--------------------------|
* | | |
* | Defered APM disabled | |
* | '<---------' | |
* | So accepted right away | |
* | but with error | |
* | '--------->' | |
* | | |
* | | LL_REJECT_EXT_IND |
* | |-------------------------->|
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | | |
*/
void test_conn_update_periph_rem_apm_reject_right_away(void)
{
#if defined(CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE)
struct node_tx *tx;
/* Default conn_param_req PDU */
struct pdu_data_llctrl_conn_param_req conn_param_req_apm = { .interval_min = INTVL_MIN,
.interval_max = INTVL_MAX,
.latency = LATENCY,
.timeout = TIMEOUT,
.preferred_periodicity = 0U,
.reference_conn_event_count = 0u,
.offset0 = 0x0008U,
.offset1 = 0xffffU,
.offset2 = 0xffffU,
.offset3 = 0xffffU,
.offset4 = 0xffffU,
.offset5 = 0xffffU };
struct pdu_data_llctrl_reject_ext_ind reject_ext_ind = {
.reject_opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ,
.error_code = BT_HCI_ERR_UNSUPP_LL_PARAM_VAL + 1
};
uint8_t error = reject_ext_ind.error_code;
/* Prepare mocked call to ull_handle_cpr_anchor_point_move */
/* No APM deferance, reject with some error code */
ztest_returns_value(ull_handle_cpr_anchor_point_move, false);
ztest_return_data(ull_handle_cpr_anchor_point_move, status, &error);
/* Role */
test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
conn.lll.interval = conn_param_req_apm.interval_max;
conn.lll.latency = conn_param_req_apm.latency;
conn.supervision_reload = RADIO_CONN_EVENTS(TIMEOUT * 10000U, conn.lll.interval *
CONN_INT_UNIT_US);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Rx */
lt_tx(LL_CONNECTION_PARAM_REQ, &conn, &conn_param_req_apm);
/* Done */
event_done(&conn);
/*******************/
/* There should be no host notification */
ut_rx_q_is_empty();
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
lt_rx(LL_REJECT_EXT_IND, &conn, &tx, &reject_ext_ind);
lt_rx_q_is_empty(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* Done */
event_done(&conn);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* There should be no host notification */
ut_rx_q_is_empty();
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
#endif
}
/*
* Central-initiated Connection Parameters Request procedure - only anchor point move.
* Central requests change in anchor point only on LE connection, peripherals Host accepts.
*
* +-----+ +-------+ +-----+
* | UT | | LL_P | | LT |
* +-----+ +-------+ +-----+
* | | |
* | | LL_CONNECTION_PARAM_REQ |
* | | (only apm) |
* | |<--------------------------|
* | | |
* | Defered APM | |
* | '<---------' | |
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | Defered accept | |
* | '--------->' | |
* | | |
* | | LL_CONNECTION_PARAM_RSP |
* | |-------------------------->|
* | | |
* | | LL_CONNECTION_UPDATE_IND |
* | |<--------------------------|
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | | |
*/
void test_conn_update_periph_rem_apm_accept_defered(void)
{
#if defined(CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE)
uint16_t offsets[6] = {
0x0008U,
0xffffU,
0xffffU,
0xffffU,
0xffffU,
0xffffU
};
struct node_tx *tx;
uint16_t instant;
/* Default conn_param_req PDU */
struct pdu_data_llctrl_conn_param_req conn_param_req_apm = { .interval_min = INTVL_MIN,
.interval_max = INTVL_MAX,
.latency = LATENCY,
.timeout = TIMEOUT,
.preferred_periodicity = 0U,
.reference_conn_event_count = 0u,
.offset0 = 0x0004U,
.offset1 = 0xffffU,
.offset2 = 0xffffU,
.offset3 = 0xffffU,
.offset4 = 0xffffU,
.offset5 = 0xffffU };
/* Default conn_param_rsp PDU */
struct pdu_data_llctrl_conn_param_rsp conn_param_rsp_apm = { .interval_min = INTVL_MIN,
.interval_max = INTVL_MAX,
.latency = LATENCY,
.timeout = TIMEOUT,
.preferred_periodicity = 0U,
.reference_conn_event_count = 0u,
.offset0 = 0x008U,
.offset1 = 0xffffU,
.offset2 = 0xffffU,
.offset3 = 0xffffU,
.offset4 = 0xffffU,
.offset5 = 0xffffU };
uint8_t error = 0;
/* Prepare mocked call to ull_handle_cpr_anchor_point_move */
/* Defer APM */
ztest_returns_value(ull_handle_cpr_anchor_point_move, true);
ztest_return_data(ull_handle_cpr_anchor_point_move, status, &error);
/* Role */
test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
conn.lll.interval = conn_param_req_apm.interval_max;
conn.lll.latency = conn_param_req_apm.latency;
conn.supervision_reload = RADIO_CONN_EVENTS(TIMEOUT * 10000U, conn.lll.interval *
CONN_INT_UNIT_US);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Rx */
lt_tx(LL_CONNECTION_PARAM_REQ, &conn, &conn_param_req_apm);
/* Done */
event_done(&conn);
/* Run a few events */
for (int i = 0; i < 10; i++) {
/* Prepare */
event_prepare(&conn);
zassert_equal(true, ull_cp_remote_cpr_apm_awaiting_reply(&conn), NULL);
/* There should be no host notification */
ut_rx_q_is_empty();
/* Done */
event_done(&conn);
}
ull_cp_remote_cpr_apm_reply(&conn, offsets);
/* There should be no host notification */
ut_rx_q_is_empty();
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
lt_rx(LL_CONNECTION_PARAM_RSP, &conn, &tx, &conn_param_rsp_apm);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* Prepare */
event_prepare(&conn);
/* Rx */
conn_update_ind.instant = event_counter(&conn) + 6U;
instant = conn_update_ind.instant;
lt_tx(LL_CONNECTION_UPDATE_IND, &conn, &conn_update_ind);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* */
while (!is_instant_reached(&conn, instant)) {
/* Prepare */
event_prepare(&conn);
/* Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* There should NOT be a host notification */
ut_rx_q_is_empty();
}
/* Prepare */
event_prepare(&conn);
/* Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* There should be no host notification */
ut_rx_q_is_empty();
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
#endif
}
/*
* Central-initiated Connection Parameters Request procedure - only anchor point move.
* Central requests change in anchor point only on LE connection, peripherals Host accepts.
*
* +-----+ +-------+ +-----+
* | UT | | LL_P | | LT |
* +-----+ +-------+ +-----+
* | | |
* | | LL_CONNECTION_PARAM_REQ |
* | | (only apm) |
* | |<--------------------------|
* | | |
* | Defered APM | |
* | '<---------' | |
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | Defered accept | |
* | but with error | |
* | '--------->' | |
* | | |
* | | LL_REJECT_EXT_IND |
* | |-------------------------->|
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | | |
*/
void test_conn_update_periph_rem_apm_reject_defered(void)
{
#if defined(CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE)
struct node_tx *tx;
/* Default conn_param_req PDU */
struct pdu_data_llctrl_conn_param_req conn_param_req_apm = { .interval_min = INTVL_MIN,
.interval_max = INTVL_MAX,
.latency = LATENCY,
.timeout = TIMEOUT,
.preferred_periodicity = 0U,
.reference_conn_event_count = 0u,
.offset0 = 0x0008U,
.offset1 = 0xffffU,
.offset2 = 0xffffU,
.offset3 = 0xffffU,
.offset4 = 0xffffU,
.offset5 = 0xffffU };
struct pdu_data_llctrl_reject_ext_ind reject_ext_ind = {
.reject_opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ,
.error_code = BT_HCI_ERR_UNSUPP_LL_PARAM_VAL
};
uint8_t error = 0U;
/* Prepare mocked call to ull_handle_cpr_anchor_point_move */
/* Defer APM */
ztest_returns_value(ull_handle_cpr_anchor_point_move, true);
ztest_return_data(ull_handle_cpr_anchor_point_move, status, &error);
/* Role */
test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
conn.lll.interval = conn_param_req_apm.interval_max;
conn.lll.latency = conn_param_req_apm.latency;
conn.supervision_reload = RADIO_CONN_EVENTS(TIMEOUT * 10000U, conn.lll.interval *
CONN_INT_UNIT_US);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Rx */
lt_tx(LL_CONNECTION_PARAM_REQ, &conn, &conn_param_req_apm);
/* Done */
event_done(&conn);
/* Run a few events */
for (int i = 0; i < 10; i++) {
/* Prepare */
event_prepare(&conn);
zassert_equal(true, ull_cp_remote_cpr_apm_awaiting_reply(&conn), NULL);
/* There should be no host notification */
ut_rx_q_is_empty();
/* Done */
event_done(&conn);
}
ull_cp_remote_cpr_apm_neg_reply(&conn, BT_HCI_ERR_UNSUPP_LL_PARAM_VAL);
/* Prepare */
event_prepare(&conn);
/* Done */
event_done(&conn);
/*******************/
/* There should be no host notification */
ut_rx_q_is_empty();
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
lt_rx(LL_REJECT_EXT_IND, &conn, &tx, &reject_ext_ind);
lt_rx_q_is_empty(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* Done */
event_done(&conn);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* There should be no host notification */
ut_rx_q_is_empty();
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
#endif /* CONFIG_BT_CTLR_USER_CPR_ANCHOR_POINT_MOVE */
}
/* /*
* (A) * (A)
@ -2527,7 +3116,7 @@ void test_conn_update_periph_loc_collision_reject_2nd_cpr(void)
ull_cp_state_set(&conn_3rd, ULL_CP_CONNECTED); ull_cp_state_set(&conn_3rd, ULL_CP_CONNECTED);
/* (A) Initiate a Connection Parameter Request Procedure */ /* (A) Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT); err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT, NULL);
zassert_equal(err, BT_HCI_ERR_SUCCESS); zassert_equal(err, BT_HCI_ERR_SUCCESS);
/* Prepare */ /* Prepare */
@ -2654,7 +3243,7 @@ void test_conn_update_periph_loc_collision_reject_2nd_cpr(void)
{ {
/* Initiate a parallel local Connection Parameter Request Procedure */ /* Initiate a parallel local Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn_2nd, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT); err = ull_cp_conn_update(&conn_2nd, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT, NULL);
zassert_equal(err, BT_HCI_ERR_SUCCESS); zassert_equal(err, BT_HCI_ERR_SUCCESS);
/* Prepare */ /* Prepare */
@ -2904,7 +3493,7 @@ void test_conn_update_periph_rem_accept_reject_2nd_cpr(void)
{ {
/* Initiate a parallel local Connection Parameter Request Procedure */ /* Initiate a parallel local Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn_2nd, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT); err = ull_cp_conn_update(&conn_2nd, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT, NULL);
zassert_equal(err, BT_HCI_ERR_SUCCESS); zassert_equal(err, BT_HCI_ERR_SUCCESS);
/* Prepare */ /* Prepare */
@ -3470,7 +4059,7 @@ void test_conn_update_periph_rem_collision(void)
/* (B) Initiate a Connection Parameter Request Procedure */ /* (B) Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, req_B->interval_min, req_B->interval_max, req_B->latency, err = ull_cp_conn_update(&conn, req_B->interval_min, req_B->interval_max, req_B->latency,
req_B->timeout); req_B->timeout, NULL);
zassert_equal(err, BT_HCI_ERR_SUCCESS); zassert_equal(err, BT_HCI_ERR_SUCCESS);
/*******************/ /*******************/
@ -3514,6 +4103,7 @@ void test_conn_update_periph_rem_collision(void)
event_prepare(&conn); event_prepare(&conn);
/* (A) Rx */ /* (A) Rx */
conn_update_ind.instant = event_counter(&conn) + 6U;
instant = conn_update_ind.instant; instant = conn_update_ind.instant;
lt_tx(LL_CONNECTION_UPDATE_IND, &conn, &conn_update_ind); lt_tx(LL_CONNECTION_UPDATE_IND, &conn, &conn_update_ind);
@ -3542,6 +4132,7 @@ void test_conn_update_periph_rem_collision(void)
event_prepare(&conn); event_prepare(&conn);
/* (B) Tx Queue should have one LL Control PDU */ /* (B) Tx Queue should have one LL Control PDU */
req_B->reference_conn_event_count = event_counter(&conn) - 1;
lt_rx(LL_CONNECTION_PARAM_REQ, &conn, &tx, req_B); lt_rx(LL_CONNECTION_PARAM_REQ, &conn, &tx, req_B);
lt_rx_q_is_empty(&conn); lt_rx_q_is_empty(&conn);
@ -3649,7 +4240,7 @@ void test_conn_update_central_loc_accept_no_param_req(void)
do { do {
/* Initiate a Connection Update Procedure */ /* Initiate a Connection Update Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT); err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT, NULL);
zassert_equal(err, BT_HCI_ERR_SUCCESS); zassert_equal(err, BT_HCI_ERR_SUCCESS);
/* Prepare */ /* Prepare */
@ -3980,7 +4571,7 @@ void test_conn_update_periph_loc_disallowed_no_param_req(void)
ull_cp_state_set(&conn, ULL_CP_CONNECTED); ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Update Procedure */ /* Initiate a Connection Update Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT); err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT, NULL);
zassert_equal(err, BT_HCI_ERR_CMD_DISALLOWED); zassert_equal(err, BT_HCI_ERR_CMD_DISALLOWED);
/* Prepare */ /* Prepare */
@ -4052,6 +4643,14 @@ void test_main(void)
periph_rem, periph_rem,
ztest_unit_test_setup_teardown(test_conn_update_periph_rem_accept, ztest_unit_test_setup_teardown(test_conn_update_periph_rem_accept,
setup, unit_test_noop), setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_periph_rem_apm_accept_right_away,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_periph_rem_apm_reject_right_away,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_periph_rem_apm_accept_defered,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_periph_rem_apm_reject_defered,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_periph_rem_invalid_req, ztest_unit_test_setup_teardown(test_conn_update_periph_rem_invalid_req,
setup, unit_test_noop), setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_periph_rem_invalid_ind, ztest_unit_test_setup_teardown(test_conn_update_periph_rem_invalid_ind,
@ -4067,9 +4666,7 @@ void test_main(void)
ztest_run_test_suite(central_rem); ztest_run_test_suite(central_rem);
ztest_run_test_suite(periph_loc); ztest_run_test_suite(periph_loc);
ztest_run_test_suite(periph_rem); ztest_run_test_suite(periph_rem);
#else /* !CONFIG_BT_CTLR_CONN_PARAM_REQ */ #else /* !CONFIG_BT_CTLR_CONN_PARAM_REQ */
ztest_test_suite(central_loc_no_param_req, ztest_unit_test_setup_teardown( ztest_test_suite(central_loc_no_param_req, ztest_unit_test_setup_teardown(
test_conn_update_central_loc_accept_no_param_req, test_conn_update_central_loc_accept_no_param_req,
setup, unit_test_noop)); setup, unit_test_noop));
@ -4095,6 +4692,5 @@ void test_main(void)
ztest_run_test_suite(central_rem_no_param_req); ztest_run_test_suite(central_rem_no_param_req);
ztest_run_test_suite(periph_loc_no_param_req); ztest_run_test_suite(periph_loc_no_param_req);
ztest_run_test_suite(periph_rem_no_param_req); ztest_run_test_suite(periph_rem_no_param_req);
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */ #endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
} }

View file

@ -4,6 +4,10 @@ tests:
bluetooth.controller.ctrl_conn_update.test: bluetooth.controller.ctrl_conn_update.test:
type: unit type: unit
bluetooth.controller.ctrl_conn_update.apm_test:
type: unit
extra_args: KCONFIG_OVERRIDE_FILE="kconfig_override_apm.h"
bluetooth.controller.ctrl_conn_update.no_param_req_test: bluetooth.controller.ctrl_conn_update.no_param_req_test:
type: unit type: unit
extra_args: KCONFIG_OVERRIDE_FILE="kconfig_override.h" extra_args: KCONFIG_OVERRIDE_FILE="kconfig_override.h"

View file

@ -368,7 +368,7 @@ void test_hci_conn_update(void)
uint8_t err; uint8_t err;
uint8_t cmd, status; uint8_t cmd, status;
uint16_t interval_min, interval_max, latency, timeout; uint16_t interval_min, interval_max, latency, timeout, *offsets;
uint8_t unknown_cmds[3U] = { 1U, 3U, 255U }; uint8_t unknown_cmds[3U] = { 1U, 3U, 255U };
@ -378,6 +378,7 @@ void test_hci_conn_update(void)
interval_max = 100U; interval_max = 100U;
latency = 5U; latency = 5U;
timeout = 1000U; timeout = 1000U;
offsets = NULL;
conn_handle = ll_conn_handle_get(conn_from_pool); conn_handle = ll_conn_handle_get(conn_from_pool);
@ -387,38 +388,38 @@ void test_hci_conn_update(void)
/* Unknown Connection ID */ /* Unknown Connection ID */
err = ll_conn_update(conn_handle + 1, cmd, status, interval_min, interval_max, latency, err = ll_conn_update(conn_handle + 1, cmd, status, interval_min, interval_max, latency,
timeout); timeout, offsets);
zassert_equal(err, BT_HCI_ERR_UNKNOWN_CONN_ID, "Errorcode %d", err); zassert_equal(err, BT_HCI_ERR_UNKNOWN_CONN_ID, "Errorcode %d", err);
/* Unknown commands */ /* Unknown commands */
for (uint8_t i = 0U; i < sizeof(unknown_cmds); i++) { for (uint8_t i = 0U; i < sizeof(unknown_cmds); i++) {
err = ll_conn_update(conn_handle, unknown_cmds[i], status, interval_min, err = ll_conn_update(conn_handle, unknown_cmds[i], status, interval_min,
interval_max, latency, timeout); interval_max, latency, timeout, offsets);
zassert_equal(err, BT_HCI_ERR_UNKNOWN_CMD, "Errorcode %d", err); zassert_equal(err, BT_HCI_ERR_UNKNOWN_CMD, "Errorcode %d", err);
} }
/* Connection Update or Connection Parameter Req. */ /* Connection Update or Connection Parameter Req. */
conn_from_pool->llcp.fex.features_used |= BIT64(BT_LE_FEAT_BIT_CONN_PARAM_REQ); conn_from_pool->llcp.fex.features_used |= BIT64(BT_LE_FEAT_BIT_CONN_PARAM_REQ);
err = ll_conn_update(conn_handle, cmd, status, interval_min, interval_max, latency, err = ll_conn_update(conn_handle, cmd, status, interval_min, interval_max, latency,
timeout); timeout, offsets);
zassert_equal(err, BT_HCI_ERR_SUCCESS, "Errorcode %d", err); zassert_equal(err, BT_HCI_ERR_SUCCESS, "Errorcode %d", err);
conn_from_pool->llcp.fex.features_used &= ~BIT64(BT_LE_FEAT_BIT_CONN_PARAM_REQ); conn_from_pool->llcp.fex.features_used &= ~BIT64(BT_LE_FEAT_BIT_CONN_PARAM_REQ);
err = ll_conn_update(conn_handle, cmd, status, interval_min, interval_max, latency, err = ll_conn_update(conn_handle, cmd, status, interval_min, interval_max, latency,
timeout); timeout, offsets);
zassert_equal(err, BT_HCI_ERR_SUCCESS, "Errorcode %d", err); zassert_equal(err, BT_HCI_ERR_SUCCESS, "Errorcode %d", err);
/* Connection Parameter Req. Reply */ /* Connection Parameter Req. Reply */
cmd = 2U; cmd = 2U;
conn_from_pool->llcp.fex.features_used |= BIT64(BT_LE_FEAT_BIT_CONN_PARAM_REQ); conn_from_pool->llcp.fex.features_used |= BIT64(BT_LE_FEAT_BIT_CONN_PARAM_REQ);
err = ll_conn_update(conn_handle, cmd, status, interval_min, interval_max, latency, err = ll_conn_update(conn_handle, cmd, status, interval_min, interval_max, latency,
timeout); timeout, offsets);
zassert_equal(err, BT_HCI_ERR_SUCCESS, "Errorcode %d", err); zassert_equal(err, BT_HCI_ERR_SUCCESS, "Errorcode %d", err);
/* Connection Parameter Req. Neg. Reply */ /* Connection Parameter Req. Neg. Reply */
status = 0x01; status = 0x01;
conn_from_pool->llcp.fex.features_used |= BIT64(BT_LE_FEAT_BIT_CONN_PARAM_REQ); conn_from_pool->llcp.fex.features_used |= BIT64(BT_LE_FEAT_BIT_CONN_PARAM_REQ);
err = ll_conn_update(conn_handle, cmd, status, 0U, 0U, 0U, 0U); err = ll_conn_update(conn_handle, cmd, status, 0U, 0U, 0U, 0U, NULL);
zassert_equal(err, BT_HCI_ERR_SUCCESS, "Errorcode %d", err); zassert_equal(err, BT_HCI_ERR_SUCCESS, "Errorcode %d", err);
} }