blob: 14991ce1f67990676078b8da5f62f255c0b80017 [file] [log] [blame]
/*
* Copyright (c) 2020 Demant
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/types.h>
#include <zephyr/ztest.h>
#define ULL_LLCP_UNITTEST
#include <zephyr/bluetooth/hci.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/sys/slist.h>
#include <zephyr/sys/util.h>
#include "hal/ccm.h"
#include "util/util.h"
#include "util/mem.h"
#include "util/memq.h"
#include "util/dbuf.h"
#include "pdu.h"
#include "ll.h"
#include "ll_settings.h"
#include "lll.h"
#include "lll_df_types.h"
#include "lll_conn.h"
#include "lll_conn_iso.h"
#include "ull_tx_queue.h"
#include "isoal.h"
#include "ull_iso_types.h"
#include "ull_conn_iso_types.h"
#include "ull_conn_types.h"
#include "ull_llcp.h"
#include "ull_conn_internal.h"
#include "ull_llcp_internal.h"
#include "helper_pdu.h"
#include "helper_util.h"
/* Default connection values */
#define INTVL_MIN 6U /* multiple of 1.25 ms (min 6, max 3200) */
#define INTVL_MAX 6U /* multiple of 1.25 ms (min 6, max 3200) */
#define LATENCY 1U
#define TIMEOUT 10U /* multiple of 10 ms (min 10, max 3200) */
/* Default conn_update_ind PDU */
struct pdu_data_llctrl_conn_update_ind conn_update_ind = { .win_size = 1U,
.win_offset = 0U,
.interval = INTVL_MAX,
.latency = LATENCY,
.timeout = TIMEOUT,
.instant = 6U };
/* Default conn_param_req PDU */
struct pdu_data_llctrl_conn_param_req conn_param_req = { .interval_min = INTVL_MIN,
.interval_max = INTVL_MAX,
.latency = LATENCY,
.timeout = TIMEOUT,
.preferred_periodicity = 0U,
.reference_conn_event_count = 0u,
.offset0 = 0x0000U,
.offset1 = 0xffffU,
.offset2 = 0xffffU,
.offset3 = 0xffffU,
.offset4 = 0xffffU,
.offset5 = 0xffffU };
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
/* Default conn_param_rsp PDU */
struct pdu_data_llctrl_conn_param_rsp conn_param_rsp = { .interval_min = INTVL_MIN,
.interval_max = INTVL_MAX,
.latency = LATENCY,
.timeout = TIMEOUT,
.preferred_periodicity = 0U,
.reference_conn_event_count = 0u,
.offset0 = 0x0000U,
.offset1 = 0xffffU,
.offset2 = 0xffffU,
.offset3 = 0xffffU,
.offset4 = 0xffffU,
.offset5 = 0xffffU };
/* Invalid conn_param_req PDU */
struct pdu_data_llctrl_conn_param_req conn_param_req_invalid = { .interval_min = INTVL_MIN - 1,
.interval_max = INTVL_MAX + 1,
.latency = LATENCY,
.timeout = TIMEOUT - 1,
.preferred_periodicity = 0U,
.reference_conn_event_count = 0u,
.offset0 = 0x0000U,
.offset1 = 0xffffU,
.offset2 = 0xffffU,
.offset3 = 0xffffU,
.offset4 = 0xffffU,
.offset5 = 0xffffU };
/* Invalid conn_param_rsp PDU */
struct pdu_data_llctrl_conn_param_rsp conn_param_rsp_invalid = { .interval_min = INTVL_MIN - 1,
.interval_max = INTVL_MAX + 1,
.latency = LATENCY,
.timeout = TIMEOUT - 1,
.preferred_periodicity = 0U,
.reference_conn_event_count = 0u,
.offset0 = 0x0000U,
.offset1 = 0xffffU,
.offset2 = 0xffffU,
.offset3 = 0xffffU,
.offset4 = 0xffffU,
.offset5 = 0xffffU };
/* Different PDU contents for (B) */
/* Default conn_param_req PDU (B) */
struct pdu_data_llctrl_conn_param_req conn_param_req_B = {
.interval_min = INTVL_MIN,
.interval_max = INTVL_MAX,
.latency = LATENCY + 1U, /* differentiate parameter */
.timeout = TIMEOUT + 1U, /* differentiate parameter */
.preferred_periodicity = 0U,
.reference_conn_event_count = 0u,
.offset0 = 0x0000U,
.offset1 = 0xffffU,
.offset2 = 0xffffU,
.offset3 = 0xffffU,
.offset4 = 0xffffU,
.offset5 = 0xffffU
};
/* Default conn_param_rsp PDU (B) */
struct pdu_data_llctrl_conn_param_rsp conn_param_rsp_B = {
.interval_min = INTVL_MIN,
.interval_max = INTVL_MAX,
.latency = LATENCY + 1U, /* differentiate parameter */
.timeout = TIMEOUT + 1U, /* differentiate parameter */
.preferred_periodicity = 0U,
.reference_conn_event_count = 0u,
.offset0 = 0x0000U,
.offset1 = 0xffffU,
.offset2 = 0xffffU,
.offset3 = 0xffffU,
.offset4 = 0xffffU,
.offset5 = 0xffffU
};
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
/* Default conn_update_ind PDU (B) */
struct pdu_data_llctrl_conn_update_ind conn_update_ind_B = {
.win_size = 1U,
.win_offset = 0U,
.interval = INTVL_MAX,
.latency = LATENCY + 1U, /* differentiate parameter */
.timeout = TIMEOUT + 1U, /* differentiate parameter */
.instant = 6U
};
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
struct pdu_data_llctrl_conn_param_req *req_B = &conn_param_req_B;
struct pdu_data_llctrl_conn_param_rsp *rsp_B = &conn_param_rsp_B;
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
struct pdu_data_llctrl_conn_update_ind *cu_ind_B = &conn_update_ind_B;
static struct ll_conn conn;
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
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);
}
static bool test_get_feature_conn_param_req(struct ll_conn *conn)
{
return (conn->llcp.fex.features_used & BIT64(BT_LE_FEAT_BIT_CONN_PARAM_REQ));
}
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
static void setup(void)
{
test_setup(&conn);
/* Initialize lll conn parameters (different from new) */
struct lll_conn *lll = &conn.lll;
lll->interval = 0;
lll->latency = 0;
conn.supervision_reload = 1U;
}
static bool is_instant_reached(struct ll_conn *conn, uint16_t instant)
{
return ((event_counter(conn) - instant) & 0xFFFF) <= 0x7FFF;
}
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
/*
* Central-initiated Connection Parameters Request procedure.
* Central requests change in LE connection parameters, peripheral’s Host accepts.
*
* +-----+ +-------+ +-----+
* | UT | | LL_C | | LT |
* +-----+ +-------+ +-----+
* | | |
* | LE Connection Update | |
* |-------------------------->| |
* | | LL_CONNECTION_PARAM_REQ |
* | |-------------------------->|
* | | |
* | | LL_CONNECTION_PARAM_RSP |
* | |<--------------------------|
* | | |
* | | LL_CONNECTION_UPDATE_IND |
* | |-------------------------->|
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| |
* | | |
*/
void test_conn_update_central_loc_accept(void)
{
uint8_t err;
struct node_tx *tx;
struct node_rx_pdu *ntf;
struct pdu_data *pdu;
uint16_t instant;
struct node_rx_pu cu = { .status = BT_HCI_ERR_SUCCESS };
/* Role */
test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT);
zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
conn_param_req.reference_conn_event_count = event_counter(&conn);
lt_rx(LL_CONNECTION_PARAM_REQ, &conn, &tx, &conn_param_req);
lt_rx_q_is_empty(&conn);
/* Rx */
conn_param_rsp.reference_conn_event_count = conn_param_req.reference_conn_event_count;
lt_tx(LL_CONNECTION_PARAM_RSP, &conn, &conn_param_rsp);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
conn_update_ind.instant = event_counter(&conn) + 6U;
lt_rx(LL_CONNECTION_UPDATE_IND, &conn, &tx, &conn_update_ind);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* Save Instant */
pdu = (struct pdu_data *)tx->pdu;
instant = sys_le16_to_cpu(pdu->llctrl.conn_update_ind.instant);
/* 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 one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Central-initiated Connection Parameters Request procedure.
* Central requests change in LE connection parameters, peripheral’s Host accepts.
* Parallel CPRs attemtped and rejected/cached
*
* +-----+ +-------+ +-----+
* | UT | | LL_C | | LT |
* +-----+ +-------+ +-----+
* | | |
* | LE Connection Update | |
* |-------------------------->| |
* | | LL_CONNECTION_PARAM_REQ |
* | |-------------------------->|
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* ~~~~~ parallel remote CPR is attempted and rejected ~~~~~~~
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | | LL_CONNECTION_PARAM_RSP |
* | |<--------------------------|
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* ~~~~~ parallel remote CPR is attempted and rejected ~~~~~~~
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* ~~~~~ parallel local CPR is attempted and cached ~~~~~~~
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | | LL_CONNECTION_UPDATE_IND |
* | |-------------------------->|
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| |
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* ~~~~~~~~~ parallel local CPR is now started ~~~~~~~~~~~~
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
*/
void test_conn_update_central_loc_accept_reject_2nd_cpr(void)
{
struct ll_conn conn_2nd;
struct ll_conn conn_3rd;
uint8_t err;
struct node_tx *tx;
struct node_rx_pdu *ntf;
struct pdu_data *pdu;
uint16_t instant;
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
};
struct node_rx_pu cu = { .status = BT_HCI_ERR_SUCCESS };
/* Initialize extra connections */
test_setup_idx(&conn_2nd, 1);
test_setup_idx(&conn_3rd, 2);
/* Role */
test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
/* Role */
test_set_role(&conn_2nd, BT_HCI_ROLE_PERIPHERAL);
/* Role */
test_set_role(&conn_3rd, BT_HCI_ROLE_PERIPHERAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Connect */
ull_cp_state_set(&conn_2nd, ULL_CP_CONNECTED);
/* Connect */
ull_cp_state_set(&conn_3rd, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT);
zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
conn_param_req.reference_conn_event_count = event_counter(&conn);
lt_rx(LL_CONNECTION_PARAM_REQ, &conn, &tx, &conn_param_req);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* Now CPR is active on 'conn' so let 'conn_2nd' attempt to start a CPR */
/* Prepare */
event_prepare(&conn_2nd);
/* Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn_2nd);
/* Rx */
lt_tx(LL_CONNECTION_PARAM_REQ, &conn_2nd, &conn_param_req);
/* Done */
event_done(&conn_2nd);
/* Prepare */
event_prepare(&conn_2nd);
/* Tx Queue should have one LL Control PDU */
lt_rx(LL_REJECT_EXT_IND, &conn_2nd, &tx, &reject_ext_ind);
lt_rx_q_is_empty(&conn_2nd);
/* Done */
event_done(&conn_2nd);
/* Release Tx */
ull_cp_release_tx(&conn_2nd, tx);
/* Rx */
conn_param_rsp.reference_conn_event_count = conn_param_req.reference_conn_event_count;
lt_tx(LL_CONNECTION_PARAM_RSP, &conn, &conn_param_rsp);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* Now CPR is active on 'conn' so let 'conn_2nd' attempt to start a CPR again */
/* Prepare */
event_prepare(&conn_3rd);
/* Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn_3rd);
/* Rx */
lt_tx(LL_CONNECTION_PARAM_REQ, &conn_3rd, &conn_param_req);
/* Done */
event_done(&conn_3rd);
/* Prepare */
event_prepare(&conn_3rd);
/* Tx Queue should have one LL Control PDU */
lt_rx(LL_REJECT_EXT_IND, &conn_3rd, &tx, &reject_ext_ind);
lt_rx_q_is_empty(&conn_3rd);
/* Done */
event_done(&conn_3rd);
/* Release Tx */
ull_cp_release_tx(&conn_3rd, tx);
/* Initiate a parallel Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn_3rd, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT);
zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL);
/* Prepare */
event_prepare(&conn_3rd);
/* Tx Queue should have no LL Control PDU */
lt_rx_q_is_empty(&conn_3rd);
/* Done */
event_done(&conn_3rd);
/* Prepare */
event_prepare(&conn_3rd);
/* Tx Queue should have no LL Control PDU */
lt_rx_q_is_empty(&conn_3rd);
/* Done */
event_done(&conn_3rd);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
conn_update_ind.instant = event_counter(&conn) + 6U;
lt_rx(LL_CONNECTION_UPDATE_IND, &conn, &tx, &conn_update_ind);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* Save Instant */
pdu = (struct pdu_data *)tx->pdu;
instant = sys_le16_to_cpu(pdu->llctrl.conn_update_ind.instant);
/* 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 on conn_3rd for parallel CPR */
event_prepare(&conn_3rd);
/* Tx Queue should have no LL Control PDU */
lt_rx_q_is_empty(&conn_3rd);
/* Done on conn_3rd for parallel CPR */
event_done(&conn_3rd);
}
/* 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 one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu);
ut_rx_q_is_empty();
/* Now the locally initiated CPR on conn_3rd should be allowed to run */
/* Prepare */
event_prepare(&conn_3rd);
/* Tx Queue should have one LL Control PDU, indicating parallel CPR is now active */
conn_param_req.reference_conn_event_count = event_counter(&conn_3rd);
lt_rx(LL_CONNECTION_PARAM_REQ, &conn_3rd, &tx, &conn_param_req);
lt_rx_q_is_empty(&conn_3rd);
/* Done */
event_done(&conn_3rd);
/* Release Tx */
ull_cp_release_tx(&conn_3rd, tx);
/* Release Ntf */
ull_cp_release_ntf(ntf);
/* One less CTXs as the conn_3rd CPR is still 'running' */
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt()-1,
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Central-initiated Connection Parameters Request procedure.
* Central requests change in LE connection parameters, peripheral
* responds with invalid params
*
* +-----+ +-------+ +-----+
* | UT | | LL_C | | LT |
* +-----+ +-------+ +-----+
* | | |
* | LE Connection Update | |
* |-------------------------->| |
* | | LL_CONNECTION_PARAM_REQ |
* | |-------------------------->|
* | | |
* | | LL_CONNECTION_PARAM_RSP |
* | |<--------------------------|
* | | |
* | | LL_REJECT_EXT_IND |
* | |-------------------------->|
* | | |
* | | |
* | | |
*/
void test_conn_update_central_loc_invalid_param_rsp(void)
{
uint8_t err;
struct node_tx *tx;
struct pdu_data_llctrl_reject_ext_ind reject_ext_ind = {
.reject_opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_RSP,
.error_code = BT_HCI_ERR_INVALID_LL_PARAM
};
/* Role */
test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT);
zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
conn_param_req.reference_conn_event_count = event_counter(&conn);
lt_rx(LL_CONNECTION_PARAM_REQ, &conn, &tx, &conn_param_req);
lt_rx_q_is_empty(&conn);
/* Rx */
lt_tx(LL_CONNECTION_PARAM_RSP, &conn, &conn_param_rsp_invalid);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* 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);
/* Done */
event_done(&conn);
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Central-initiated Connection Parameters Request procedure.
* Central requests change in LE connection parameters, peripheral’s Host accepts.
*
* +-----+ +-------+ +-----+
* | UT | | LL_C | | LT |
* +-----+ +-------+ +-----+
* | | |
* | LE Connection Update | |
* |-------------------------->| |
* | | LL_CONNECTION_PARAM_REQ |
* | |-------------------------->|
* | | |
* | | LL_REJECT_IND |
* | |<--------------------------|
* | | |
* ~~~~~~~~~~~~~~~~~~ TERMINATE CONNECTION ~~~~~~~~~~~~~~~~~
* | | |
* | | |
*/
void test_conn_update_central_loc_invalid_rsp(void)
{
uint8_t err;
struct node_tx *tx;
struct pdu_data_llctrl_reject_ind reject_ind = {
.error_code = BT_HCI_ERR_LL_PROC_COLLISION
};
/* Role */
test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT);
zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
conn_param_req.reference_conn_event_count = event_counter(&conn);
lt_rx(LL_CONNECTION_PARAM_REQ, &conn, &tx, &conn_param_req);
lt_rx_q_is_empty(&conn);
/* Rx */
lt_tx(LL_REJECT_IND, &conn, &reject_ind);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* Termination 'triggered' */
zassert_equal(conn.llcp_terminate.reason_final, BT_HCI_ERR_LMP_PDU_NOT_ALLOWED,
"Terminate reason %d", conn.llcp_terminate.reason_final);
/* There should be no host notifications */
ut_rx_q_is_empty();
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Central-initiated Connection Parameters Request procedure.
* Central requests change in LE connection parameters, peripheral’s Host rejects.
*
* +-----+ +-------+ +-----+
* | UT | | LL_C | | LT |
* +-----+ +-------+ +-----+
* | | |
* | LE Connection Update | |
* |-------------------------->| |
* | | LL_CONNECTION_PARAM_REQ |
* | |-------------------------->|
* | | |
* | | LL_REJECT_EXT_IND |
* | |<--------------------------|
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| |
* | | |
*/
void test_conn_update_central_loc_reject(void)
{
uint8_t err;
struct node_tx *tx;
struct node_rx_pdu *ntf;
struct pdu_data_llctrl_reject_ext_ind reject_ext_ind = {
.reject_opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ,
.error_code = BT_HCI_ERR_UNACCEPT_CONN_PARAM
};
struct node_rx_pu cu = { .status = BT_HCI_ERR_UNACCEPT_CONN_PARAM };
/* Role */
test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT);
zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
conn_param_req.reference_conn_event_count = event_counter(&conn);
lt_rx(LL_CONNECTION_PARAM_REQ, &conn, &tx, &conn_param_req);
lt_rx_q_is_empty(&conn);
/* Rx */
lt_tx(LL_REJECT_EXT_IND, &conn, &reject_ext_ind);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* There should be one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Central-initiated Connection Parameters Request procedure.
* Central requests change in LE connection parameters, peripheral’s Host is legacy.
*
* +-----+ +-------+ +-----+
* | UT | | LL_C | | LT |
* +-----+ +-------+ +-----+
* | | |
* | LE Connection Update | |
* |-------------------------->| |
* | | LL_CONNECTION_PARAM_REQ |
* | |-------------------------->|
* | | |
* | | LL_REJECT_EXT_IND |
* | |<--------------------------|
* | | |
* | | LL_CONNECTION_UPDATE_IND |
* | |-------------------------->|
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| |
* | | |
*/
void test_conn_update_central_loc_remote_legacy(void)
{
bool feature_bit_param_req;
uint8_t err;
struct node_tx *tx;
struct node_rx_pdu *ntf;
struct pdu_data *pdu;
uint16_t instant;
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_REMOTE_FEATURE
};
struct node_rx_pu cu = { .status = BT_HCI_ERR_SUCCESS };
/* Role */
test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT);
zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
conn_param_req.reference_conn_event_count = event_counter(&conn);
lt_rx(LL_CONNECTION_PARAM_REQ, &conn, &tx, &conn_param_req);
lt_rx_q_is_empty(&conn);
/* Rx */
lt_tx(LL_REJECT_EXT_IND, &conn, &reject_ext_ind);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* Prepare */
event_prepare(&conn);
/* Check that feature Param Reg. is unmasked */
feature_bit_param_req = test_get_feature_conn_param_req(&conn);
zassert_equal(feature_bit_param_req, false, "Feature bit not unmasked");
/* Tx Queue should have one LL Control PDU */
conn_update_ind.instant = event_counter(&conn) + 6U;
lt_rx(LL_CONNECTION_UPDATE_IND, &conn, &tx, &conn_update_ind);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* Save Instant */
pdu = (struct pdu_data *)tx->pdu;
instant = sys_le16_to_cpu(pdu->llctrl.conn_update_ind.instant);
/* 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 one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Central-initiated Connection Parameters Request procedure.
* Central requests change in LE connection parameters, peripheral’s Controller do not
* support Connection Parameters Request procedure, features not exchanged.
*
* +-----+ +-------+ +-----+
* | UT | | LL_C | | LT |
* +-----+ +-------+ +-----+
* | | |
* | LE Connection Update | |
* |-------------------------->| |
* | | LL_CONNECTION_PARAM_REQ |
* | |-------------------------->|
* | | |
* | | LL_UNKNOWN_RSP |
* | |<--------------------------|
* | | |
* | | LL_CONNECTION_UPDATE_IND |
* | |-------------------------->|
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| |
* | | |
*/
void test_conn_update_central_loc_unsupp_wo_feat_exch(void)
{
bool feature_bit_param_req;
uint8_t err;
struct node_tx *tx;
struct node_rx_pdu *ntf;
struct pdu_data *pdu;
uint16_t instant;
struct pdu_data_llctrl_unknown_rsp unknown_rsp = {
.type = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ
};
struct node_rx_pu cu = { .status = BT_HCI_ERR_SUCCESS };
/* Role */
test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT);
zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
conn_param_req.reference_conn_event_count = event_counter(&conn);
lt_rx(LL_CONNECTION_PARAM_REQ, &conn, &tx, &conn_param_req);
lt_rx_q_is_empty(&conn);
/* Rx */
lt_tx(LL_UNKNOWN_RSP, &conn, &unknown_rsp);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* Prepare */
event_prepare(&conn);
/* Check that feature Param Reg. is unmasked */
feature_bit_param_req = test_get_feature_conn_param_req(&conn);
zassert_equal(feature_bit_param_req, false, "Feature bit not unmasked");
/* Tx Queue should have one LL Control PDU */
conn_update_ind.instant = event_counter(&conn) + 6U;
lt_rx(LL_CONNECTION_UPDATE_IND, &conn, &tx, &conn_update_ind);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* Save Instant */
pdu = (struct pdu_data *)tx->pdu;
instant = sys_le16_to_cpu(pdu->llctrl.conn_update_ind.instant);
/* 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 one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Central-initiated Connection Parameters Request procedure.
* Central requests change in LE connection parameters, peripheral’s Controller do not
* support Connection Parameters Request procedure, features exchanged.
*
* +-----+ +-------+ +-----+
* | UT | | LL_C | | LT |
* +-----+ +-------+ +-----+
* | | |
* | LE Connection Update | |
* |-------------------------->| |
* | | LL_CONNECTION_UPDATE_IND |
* | |-------------------------->|
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| |
* | | |
*/
void test_conn_update_central_loc_unsupp_w_feat_exch(void)
{
uint8_t err;
struct node_tx *tx;
struct node_rx_pdu *ntf;
struct pdu_data *pdu;
uint16_t instant;
struct node_rx_pu cu = { .status = BT_HCI_ERR_SUCCESS };
/* Disable feature */
test_unmask_feature_conn_param_req(&conn);
/* Role */
test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT);
zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
conn_update_ind.instant = event_counter(&conn) + 6U;
lt_rx(LL_CONNECTION_UPDATE_IND, &conn, &tx, &conn_update_ind);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* Save Instant */
pdu = (struct pdu_data *)tx->pdu;
instant = sys_le16_to_cpu(pdu->llctrl.conn_update_ind.instant);
/* */
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 one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* (A)
* Central-initiated Connection Parameters Request procedure.
* Central requests change in LE connection parameters, peripheral’s Host accepts.
*
* and
*
* (B)
* Peripheral-initiated Connection Parameters Request procedure.
* Procedure collides and is rejected.
*
* +-----+ +-------+ +-----+
* | UT | | LL_C | | LT |
* +-----+ +-------+ +-----+
* | | |
* | LE Connection Update | |
* |-------------------------->| |
* | | LL_CONNECTION_PARAM_REQ | (A)
* | |-------------------------->|
* | | |
* | | LL_CONNECTION_PARAM_REQ | (B)
* | |<--------------------------|
* | | |
* | <---------------------> |
* | < PROCEDURE COLLISION > |
* | <---------------------> |
* | | |
* | | LL_REJECT_EXT_IND | (B)
* | |-------------------------->|
* | | |
* | | LL_CONNECTION_PARAM_RSP | (A)
* | |<--------------------------|
* | | |
* | | LL_CONNECTION_UPDATE_IND | (A)
* | |-------------------------->|
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| |
* | | |
*/
void test_conn_update_central_loc_collision(void)
{
uint8_t err;
struct node_tx *tx;
struct node_rx_pdu *ntf;
struct pdu_data *pdu;
uint16_t instant;
struct node_rx_pu cu = { .status = BT_HCI_ERR_SUCCESS };
struct pdu_data_llctrl_reject_ext_ind reject_ext_ind = {
.reject_opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ,
.error_code = BT_HCI_ERR_LL_PROC_COLLISION
};
/* Role */
test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
/* Emulate valid feature exchange */
conn.llcp.fex.valid = 1;
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* (A) Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT);
zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL);
/* Prepare */
event_prepare(&conn);
/* (A) Tx Queue should have one LL Control PDU */
conn_param_req.reference_conn_event_count = event_counter(&conn);
lt_rx(LL_CONNECTION_PARAM_REQ, &conn, &tx, &conn_param_req);
lt_rx_q_is_empty(&conn);
/* (B) Rx */
lt_tx(LL_CONNECTION_PARAM_REQ, &conn, req_B);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* Prepare */
event_prepare(&conn);
/* (B) 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);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/**/
/* Prepare */
event_prepare(&conn);
/* (B) Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* (A) Rx */
lt_tx(LL_CONNECTION_PARAM_RSP, &conn, &conn_param_rsp);
/* Done */
event_done(&conn);
/* Prepare */
event_prepare(&conn);
/* (A) Tx Queue should have one LL Control PDU */
conn_update_ind.instant = event_counter(&conn) + 6U;
lt_rx(LL_CONNECTION_UPDATE_IND, &conn, &tx, &conn_update_ind);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* Save Instant */
pdu = (struct pdu_data *)tx->pdu;
instant = sys_le16_to_cpu(pdu->llctrl.conn_update_ind.instant);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* */
while (!is_instant_reached(&conn, instant)) {
/* Prepare */
event_prepare(&conn);
/* (A) Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* (A) There should NOT be a host notification */
ut_rx_q_is_empty();
}
/* Prepare */
event_prepare(&conn);
/* (A) Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* (A) There should be one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Peripheral-initiated Connection Parameters Request procedure.
* Peripheral requests change in LE connection parameters, central’s Host accepts.
*
* +-----+ +-------+ +-----+
* | UT | | LL_C | | LT |
* +-----+ +-------+ +-----+
* | | |
* | | LL_CONNECTION_PARAM_REQ |
* | |<--------------------------|
* | | |
* | LE Remote Connection | |
* | Parameter Request | |
* |<--------------------------| |
* | LE Remote Connection | |
* | Parameter Request | |
* | Reply | |
* |-------------------------->| |
* | | |
* | | LL_CONNECTION_UPDATE_IND |
* | |-------------------------->|
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| |
* | | |
*/
void test_conn_update_central_rem_accept(void)
{
struct node_tx *tx;
struct node_rx_pdu *ntf;
struct pdu_data *pdu;
uint16_t instant;
struct node_rx_pu cu = { .status = BT_HCI_ERR_SUCCESS };
/* Role */
test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Prepare */
event_prepare(&conn);
/* Rx */
lt_tx(LL_CONNECTION_PARAM_REQ, &conn, &conn_param_req);
/* Done */
event_done(&conn);
/*******************/
/* There should be one host notification */
ut_rx_pdu(LL_CONNECTION_PARAM_REQ, &ntf, &conn_param_req);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
/*******************/
ull_cp_conn_param_req_reply(&conn);
/*******************/
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
conn_update_ind.instant = event_counter(&conn) + 6U;
lt_rx(LL_CONNECTION_UPDATE_IND, &conn, &tx, &conn_update_ind);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* Save Instant */
pdu = (struct pdu_data *)tx->pdu;
instant = sys_le16_to_cpu(pdu->llctrl.conn_update_ind.instant);
/* 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 one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Peripheral-initiated Connection Parameters Request procedure.
* Peripheral requests change in LE connection with invalid parameters,
*
* +-----+ +-------+ +-----+
* | UT | | LL_C | | LT |
* +-----+ +-------+ +-----+
* | | |
* | | LL_CONNECTION_PARAM_REQ |
* | |<--------------------------|
* | | |
* | | |
* | | LL_REJECT_EXT_IND |
* | |-------------------------->|
* | | |
* | | |
*/
void test_conn_update_central_rem_invalid_req(void)
{
struct node_tx *tx;
struct pdu_data_llctrl_reject_ext_ind reject_ext_ind = {
.reject_opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ,
.error_code = BT_HCI_ERR_INVALID_LL_PARAM
};
/* Role */
test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Prepare */
event_prepare(&conn);
/* Rx */
lt_tx(LL_CONNECTION_PARAM_REQ, &conn, &conn_param_req_invalid);
/* Done */
event_done(&conn);
/* 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);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Peripheral-initiated Connection Parameters Request procedure.
* Peripheral requests change in LE connection parameters, central’s Host rejects.
*
* +-----+ +-------+ +-----+
* | UT | | LL_C | | LT |
* +-----+ +-------+ +-----+
* | | |
* | | LL_CONNECTION_PARAM_REQ |
* | |<--------------------------|
* | | |
* | LE Remote Connection | |
* | Parameter Request | |
* |<--------------------------| |
* | LE Remote Connection | |
* | Parameter Request | |
* | Negative Reply | |
* |-------------------------->| |
* | | |
* | | LL_REJECT_EXT_IND |
* | |-------------------------->|
* | | |
*/
void test_conn_update_central_rem_reject(void)
{
struct node_tx *tx;
struct node_rx_pdu *ntf;
struct pdu_data_llctrl_reject_ext_ind reject_ext_ind = {
.reject_opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ,
.error_code = BT_HCI_ERR_UNACCEPT_CONN_PARAM
};
/* Role */
test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Prepare */
event_prepare(&conn);
/* Rx */
lt_tx(LL_CONNECTION_PARAM_REQ, &conn, &conn_param_req);
/* Done */
event_done(&conn);
/*******************/
/* There should be one host notification */
ut_rx_pdu(LL_CONNECTION_PARAM_REQ, &ntf, &conn_param_req);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
/*******************/
ull_cp_conn_param_req_neg_reply(&conn, BT_HCI_ERR_UNACCEPT_CONN_PARAM);
/*******************/
/* 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);
/* Done */
event_done(&conn);
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* (A)
* Peripheral-initiated Connection Parameters Request procedure.
* Peripheral requests change in LE connection parameters, central’s Host accepts.
*
* and
*
* (B)
* Central-initiated Connection Parameters Request procedure.
* Central requests change in LE connection parameters, peripheral’s Host accepts.
*
* NOTE:
* Central-initiated Connection Parameters Request procedure is paused.
* Peripheral-initiated Connection Parameters Request procedure is finished.
* Central-initiated Connection Parameters Request procedure is resumed.
*
* +-----+ +-------+ +-----+
* | UT | | LL_C | | LT |
* +-----+ +-------+ +-----+
* | | |
* | | LL_CONNECTION_PARAM_REQ |
* | |<--------------------------| (A)
* | | |
* | LE Connection Update | |
* |-------------------------->| | (B)
* | | |
* | <------------------------> |
* | < LOCAL PROCEDURE PAUSED > |
* | <------------------------> |
* | | |
* | LE Remote Connection | |
* | Parameter Request | |
* |<--------------------------| | (A)
* | LE Remote Connection | |
* | Parameter Request | |
* | Reply | |
* |-------------------------->| | (A)
* | | |
* | | LL_CONNECTION_UPDATE_IND |
* | |-------------------------->| (A)
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| | (A)
* | | |
* | <-------------------------> |
* | < LOCAL PROCEDURE RESUMED > |
* | <-------------------------> |
* | | |
* | | LL_CONNECTION_PARAM_REQ |
* | |-------------------------->| (B)
* | | |
* | | LL_CONNECTION_PARAM_RSP |
* | |<--------------------------| (B)
* | | |
* | | LL_CONNECTION_UPDATE_IND |
* | |-------------------------->| (B)
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| | (B)
* | | |
*/
void test_conn_update_central_rem_collision(void)
{
uint8_t err;
struct node_tx *tx;
struct node_rx_pdu *ntf;
struct pdu_data *pdu;
uint16_t instant;
struct node_rx_pu cu = { .status = BT_HCI_ERR_SUCCESS };
/* Role */
test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/*******************/
/* Prepare */
event_prepare(&conn);
/* (A) Rx */
lt_tx(LL_CONNECTION_PARAM_REQ, &conn, &conn_param_req);
/* Done */
event_done(&conn);
/*******************/
/* (B) Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, req_B->interval_min, req_B->interval_max, req_B->latency,
req_B->timeout);
zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL);
/* Prepare */
event_prepare(&conn);
/* (B) Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/*******************/
/* (A) There should be one host notification */
ut_rx_pdu(LL_CONNECTION_PARAM_REQ, &ntf, &conn_param_req);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
/*******************/
/* (A) */
ull_cp_conn_param_req_reply(&conn);
/*******************/
/* Prepare */
event_prepare(&conn);
/* (A) Tx Queue should have one LL Control PDU */
conn_update_ind.instant = event_counter(&conn) + 6U;
lt_rx(LL_CONNECTION_UPDATE_IND, &conn, &tx, &conn_update_ind);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* Save Instant */
pdu = (struct pdu_data *)tx->pdu;
instant = sys_le16_to_cpu(pdu->llctrl.conn_update_ind.instant);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* */
while (!is_instant_reached(&conn, instant)) {
/* Prepare */
event_prepare(&conn);
/* (A) Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* (A) There should NOT be a host notification */
ut_rx_q_is_empty();
}
/* Prepare */
event_prepare(&conn);
/* (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_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* (A) There should be one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
/* Prepare */
event_prepare(&conn);
/* (B) Rx */
lt_tx(LL_CONNECTION_PARAM_RSP, &conn, rsp_B);
/* Done */
event_done(&conn);
/* Prepare */
event_prepare(&conn);
/* (B) Tx Queue should have one LL Control PDU */
conn_update_ind_B.instant = event_counter(&conn) + 6U;
lt_rx(LL_CONNECTION_UPDATE_IND, &conn, &tx, &conn_update_ind_B);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* Save Instant */
pdu = (struct pdu_data *)tx->pdu;
instant = sys_le16_to_cpu(pdu->llctrl.conn_update_ind.instant);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* */
while (!is_instant_reached(&conn, instant)) {
/* Prepare */
event_prepare(&conn);
/* (B) Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* (B) There should NOT be a host notification */
ut_rx_q_is_empty();
}
/* Prepare */
event_prepare(&conn);
/* (B) Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* (B) There should be one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Peripheral-initiated Connection Parameters Request procedure.
* Peripheral requests change in LE connection parameters, central’s Host accepts.
*
* +-----+ +-------+ +-----+
* | UT | | LL_P | | LT |
* +-----+ +-------+ +-----+
* | | |
* | LE Connection Update | |
* |-------------------------->| |
* | | LL_CONNECTION_PARAM_REQ |
* | |-------------------------->|
* | | |
* | | LL_CONNECTION_UPDATE_IND |
* | |<--------------------------|
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| |
* | | |
*/
void test_conn_update_periph_loc_accept(void)
{
uint8_t err;
struct node_tx *tx;
struct node_rx_pdu *ntf;
uint16_t instant;
struct node_rx_pu cu = { .status = BT_HCI_ERR_SUCCESS };
/* Role */
test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT);
zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
lt_rx(LL_CONNECTION_PARAM_REQ, &conn, &tx, &conn_param_req);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&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);
/* */
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 one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Peripheral-initiated Connection Parameters Request procedure.
* Peripheral requests change in LE connection parameters, central’s Host rejects.
*
* +-----+ +-------+ +-----+
* | UT | | LL_P | | LT |
* +-----+ +-------+ +-----+
* | | |
* | LE Connection Update | |
* |-------------------------->| |
* | | LL_CONNECTION_PARAM_REQ |
* | |-------------------------->|
* | | |
* | | LL_REJECT_EXT_IND |
* | |<--------------------------|
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| |
* | | |
*/
void test_conn_update_periph_loc_reject(void)
{
uint8_t err;
struct node_tx *tx;
struct node_rx_pdu *ntf;
struct node_rx_pu cu = { .status = BT_HCI_ERR_UNACCEPT_CONN_PARAM };
struct pdu_data_llctrl_reject_ext_ind reject_ext_ind = {
.reject_opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ,
.error_code = BT_HCI_ERR_UNACCEPT_CONN_PARAM
};
/* Role */
test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT);
zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
lt_rx(LL_CONNECTION_PARAM_REQ, &conn, &tx, &conn_param_req);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Rx */
lt_tx(LL_REJECT_EXT_IND, &conn, &reject_ext_ind);
/* Done */
event_done(&conn);
/* There should be one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Peripheral-initiated Connection Parameters Request procedure.
* Peripheral requests change in LE connection parameters, central’s Controller do not
* support Connection Parameters Request procedure, features not exchanged.
*
* +-----+ +-------+ +-----+
* | UT | | LL_P | | LT |
* +-----+ +-------+ +-----+
* | | |
* | LE Connection Update | |
* |-------------------------->| |
* | | LL_CONNECTION_PARAM_REQ |
* | |-------------------------->|
* | | |
* | | LL_UNKNOWN_RSP |
* | |<--------------------------|
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| |
* | | |
*/
void test_conn_update_periph_loc_unsupp_feat_wo_feat_exch(void)
{
uint8_t err;
struct node_tx *tx;
struct node_rx_pdu *ntf;
struct node_rx_pu cu = { .status = BT_HCI_ERR_UNSUPP_REMOTE_FEATURE };
struct pdu_data_llctrl_unknown_rsp unknown_rsp = {
.type = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ
};
/* Role */
test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT);
zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
lt_rx(LL_CONNECTION_PARAM_REQ, &conn, &tx, &conn_param_req);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Rx */
lt_tx(LL_UNKNOWN_RSP, &conn, &unknown_rsp);
/* Done */
event_done(&conn);
/* There should be one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Peripheral-initiated Connection Parameters Request procedure.
* Peripheral requests change in LE connection parameters, central’s Controller do not
* support Connection Parameters Request procedure, features exchanged.
*
* +-----+ +-------+ +-----+
* | UT | | LL_P | | LT |
* +-----+ +-------+ +-----+
* | | |
* | LE Connection Update | |
* |-------------------------->| |
* | | LL_CONNECTION_UPDATE_IND |
* | |-------------------------->|
* | | |
*/
void test_conn_update_periph_loc_unsupp_feat_w_feat_exch(void)
{
uint8_t err;
/* Disable feature */
test_unmask_feature_conn_param_req(&conn);
/* Role */
test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT);
zassert_equal(err, BT_HCI_ERR_UNSUPP_REMOTE_FEATURE, NULL);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have no 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());
}
/*
* (A)
* Peripheral-initiated Connection Parameters Request procedure.
* Procedure collides and is rejected.
*
* and
*
* (B)
* Central-initiated Connection Parameters Request procedure.
* Central requests change in LE connection parameters, peripheral’s Host accepts.
*
* +-----+ +-------+ +-----+
* | UT | | LL_P | | LT |
* +-----+ +-------+ +-----+
* | | |
* | LE Connection Update | |
* |-------------------------->| | (A)
* | | LL_CONNECTION_PARAM_REQ |
* | |-------------------------->| (A)
* | | |
* | | LL_CONNECTION_PARAM_REQ |
* | |<--------------------------| (B)
* | | |
* | <---------------------> |
* | < PROCEDURE COLLISION > |
* | <---------------------> |
* | | |
* | LE Remote Connection | |
* | Parameter Request | |
* |<--------------------------| | (B)
* | | |
* | LE Remote Connection | |
* | Parameter Request | |
* | Reply | |
* |-------------------------->| | (B)
* | | |
* | | LL_REJECT_EXT_IND |
* | |<--------------------------| (A)
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| | (A)
* | | |
* | | LL_CONNECTION_UPDATE_IND |
* | |<--------------------------| (B)
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| | (B)
*/
void test_conn_update_periph_loc_collision(void)
{
uint8_t err;
struct node_tx *tx;
struct node_rx_pdu *ntf;
uint16_t instant;
struct node_rx_pu cu1 = { .status = BT_HCI_ERR_LL_PROC_COLLISION };
struct node_rx_pu cu2 = { .status = BT_HCI_ERR_SUCCESS };
struct pdu_data_llctrl_reject_ext_ind reject_ext_ind = {
.reject_opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ,
.error_code = BT_HCI_ERR_LL_PROC_COLLISION
};
/* Role */
test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* (A) Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT);
zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL);
/* Prepare */
event_prepare(&conn);
/* (A) Tx Queue should have one LL Control PDU */
conn_param_req.reference_conn_event_count = event_counter(&conn);
lt_rx(LL_CONNECTION_PARAM_REQ, &conn, &tx, &conn_param_req);
lt_rx_q_is_empty(&conn);
/* (B) Rx */
lt_tx(LL_CONNECTION_PARAM_REQ, &conn, req_B);
/* Done */
event_done(&conn);
/* Prepare */
event_prepare(&conn);
/* Done */
event_done(&conn);
/* Prepare */
event_prepare(&conn);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/*******************/
/* (B) There should be one host notification */
ut_rx_pdu(LL_CONNECTION_PARAM_REQ, &ntf, req_B);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
/*******************/
/* (B) */
ull_cp_conn_param_req_reply(&conn);
/*******************/
/* Prepare */
event_prepare(&conn);
/* (B) Tx Queue should have one LL Control PDU */
rsp_B->reference_conn_event_count = req_B->reference_conn_event_count;
lt_rx(LL_CONNECTION_PARAM_RSP, &conn, &tx, rsp_B);
lt_rx_q_is_empty(&conn);
/* (A) Rx */
lt_tx(LL_REJECT_EXT_IND, &conn, &reject_ext_ind);
/* Done */
event_done(&conn);
/* (A) There should be one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu1);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
/* Prepare */
event_prepare(&conn);
/* (B) Rx */
cu_ind_B->instant = instant = event_counter(&conn) + 6;
lt_tx(LL_CONNECTION_UPDATE_IND, &conn, cu_ind_B);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* */
while (!is_instant_reached(&conn, instant)) {
/* Prepare */
event_prepare(&conn);
/* (B) Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* (B) There should NOT be a host notification */
ut_rx_q_is_empty();
}
/* Prepare */
event_prepare(&conn);
/* (B) Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* (B) There should be one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu2);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Central-initiated Connection Parameters Request procedure.
* Central requests change in LE connection parameters, peripheral’s Host accepts.
*
* +-----+ +-------+ +-----+
* | UT | | LL_P | | LT |
* +-----+ +-------+ +-----+
* | | |
* | | LL_CONNECTION_PARAM_REQ |
* | |<--------------------------|
* | | |
* | LE Remote Connection | |
* | Parameter Request | |
* |<--------------------------| |
* | LE Remote Connection | |
* | Parameter Request | |
* | Reply | |
* |-------------------------->| |
* | | |
* | | LL_CONNECTION_PARAM_RSP |
* | |-------------------------->|
* | | |
* | | LL_CONNECTION_UPDATE_IND |
* | |<--------------------------|
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| |
* | | |
*/
void test_conn_update_periph_rem_accept(void)
{
struct node_tx *tx;
struct node_rx_pdu *ntf;
uint16_t instant;
struct node_rx_pu cu = { .status = BT_HCI_ERR_SUCCESS };
/* Role */
test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* 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);
/* Done */
event_done(&conn);
/*******************/
/* There should be one host notification */
ut_rx_pdu(LL_CONNECTION_PARAM_REQ, &ntf, &conn_param_req);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
/*******************/
ull_cp_conn_param_req_reply(&conn);
/*******************/
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
lt_rx(LL_CONNECTION_PARAM_RSP, &conn, &tx, &conn_param_rsp);
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 one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* (A)
* Peripheral-initiated Connection Parameters Request procedure.
* Procedure collides and is rejected.
*
* and
*
* (B)
* Central-initiated Connection Parameters Request procedure.
* Central requests change in LE connection parameters, peripheral’s Host accepts.
*
* +-----+ +-------+ +-----+
* | UT | | LL_P | | LT |
* +-----+ +-------+ +-----+
* | | |
* | LE Connection Update | |
* |-------------------------->| | (A)
* | | LL_CONNECTION_PARAM_REQ |
* | |-------------------------->| (A)
* | | |
* | | LL_CONNECTION_PARAM_REQ |
* | |<--------------------------| (B)
* | | |
* | <---------------------> |
* | < PROCEDURE COLLISION > |
* | <---------------------> |
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* ~~~~~ parallel remote CPRs attempted and rejected ~~~~~~~
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | | |
* | LE Remote Connection | |
* | Parameter Request | |
* |<--------------------------| | (B)
* | | |
* | LE Remote Connection | |
* | Parameter Request | |
* | Reply | |
* |-------------------------->| | (B)
* | | |
* | | LL_REJECT_EXT_IND |
* | |<--------------------------| (A)
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| | (A)
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* ~~~~~ parallel local CPR is attempted and cached ~~~~~~~
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | LL_CONNECTION_UPDATE_IND |
* | |<--------------------------| (B)
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| | (B)
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* ~~~~~~~~~ parallel local CPR is now started ~~~~~~~~~~~~
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
*/
void test_conn_update_periph_loc_collision_reject_2nd_cpr(void)
{
struct ll_conn conn_2nd;
struct ll_conn conn_3rd;
uint8_t err;
struct node_tx *tx, *tx1;
struct node_rx_pdu *ntf;
uint16_t instant;
struct node_rx_pu cu1 = { .status = BT_HCI_ERR_LL_PROC_COLLISION };
struct node_rx_pu cu2 = { .status = BT_HCI_ERR_SUCCESS };
struct pdu_data_llctrl_reject_ext_ind reject_ext_ind = {
.reject_opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ,
.error_code = BT_HCI_ERR_LL_PROC_COLLISION
};
struct pdu_data_llctrl_reject_ext_ind parallel_reject_ext_ind = {
.reject_opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ,
.error_code = BT_HCI_ERR_UNSUPP_LL_PARAM_VAL
};
/* Initialize extra connections */
test_setup_idx(&conn_2nd, 1);
test_setup_idx(&conn_3rd, 2);
/* Role */
test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
/* Role */
test_set_role(&conn_2nd, BT_HCI_ROLE_PERIPHERAL);
/* Role */
test_set_role(&conn_3rd, BT_HCI_ROLE_CENTRAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Connect */
ull_cp_state_set(&conn_2nd, ULL_CP_CONNECTED);
/* Connect */
ull_cp_state_set(&conn_3rd, ULL_CP_CONNECTED);
/* (A) Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT);
zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL);
/* Prepare */
event_prepare(&conn);
/* (A) Tx Queue should have one LL Control PDU */
lt_rx(LL_CONNECTION_PARAM_REQ, &conn, &tx1, &conn_param_req);
lt_rx_q_is_empty(&conn);
/* (B) Rx */
lt_tx(LL_CONNECTION_PARAM_REQ, &conn, req_B);
/* Done */
event_done(&conn);
{
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt()-2,
"Free CTX buffers %d", ctx_buffers_free());
/* Parallel CPR from central */
/* Now CPR is active on 'conn' so let 'conn_2nd' attempt to start a CPR */
/* Prepare */
event_prepare(&conn_2nd);
/* Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn_2nd);
/* Rx */
lt_tx(LL_CONNECTION_PARAM_REQ, &conn_2nd, &conn_param_req);
/* Done */
event_done(&conn_2nd);
/* Tx Queue should have one LL Control PDU */
lt_rx(LL_REJECT_EXT_IND, &conn_2nd, &tx, &parallel_reject_ext_ind);
lt_rx_q_is_empty(&conn_2nd);
/* Release Tx */
ull_cp_release_tx(&conn_2nd, tx);
/* There should be no 'extra' procedure on acount of the parallel CPR */
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt()-2,
"Free CTX buffers %d", ctx_buffers_free());
}
/* Prepare */
event_prepare(&conn);
/* Done */
event_done(&conn);
{
/* Parallel CPR from peripheral */
/* Now CPR is active on 'conn' so let 'conn_3rd' attempt to start a CPR */
/* Prepare */
event_prepare(&conn_3rd);
/* Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn_3rd);
/* Rx */
lt_tx(LL_CONNECTION_PARAM_REQ, &conn_3rd, &conn_param_req);
/* Done */
event_done(&conn_3rd);
/* Tx Queue should have one LL Control PDU */
lt_rx(LL_REJECT_EXT_IND, &conn_3rd, &tx, &parallel_reject_ext_ind);
lt_rx_q_is_empty(&conn_3rd);
/* Release Tx */
ull_cp_release_tx(&conn_3rd, tx);
/* There should be no 'extra' procedure on acount of the parallel CPR */
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt()-2,
"Free CTX buffers %d", ctx_buffers_free());
}
/* Prepare */
event_prepare(&conn);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx1);
/*******************/
/* (B) There should be one host notification */
ut_rx_pdu(LL_CONNECTION_PARAM_REQ, &ntf, req_B);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
/*******************/
/* (B) */
ull_cp_conn_param_req_reply(&conn);
/*******************/
/* Prepare */
event_prepare(&conn);
/* (B) Tx Queue should have one LL Control PDU */
rsp_B->reference_conn_event_count = req_B->reference_conn_event_count;
lt_rx(LL_CONNECTION_PARAM_RSP, &conn, &tx, rsp_B);
lt_rx_q_is_empty(&conn);
/* (A) Rx */
lt_tx(LL_REJECT_EXT_IND, &conn, &reject_ext_ind);
/* Done */
event_done(&conn);
/* (A) There should be one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu1);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
{
/* Initiate a parallel local Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn_2nd, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT);
zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL);
/* Prepare */
event_prepare(&conn_2nd);
/* Tx Queue should have no LL Control PDU */
lt_rx_q_is_empty(&conn_2nd);
/* Done */
event_done(&conn_2nd);
/* Prepare */
event_prepare(&conn_2nd);
/* Tx Queue should have no LL Control PDU */
lt_rx_q_is_empty(&conn_2nd);
/* Done */
event_done(&conn_2nd);
}
/* Prepare */
event_prepare(&conn);
/* (B) Rx */
cu_ind_B->instant = instant = event_counter(&conn) + 6;
lt_tx(LL_CONNECTION_UPDATE_IND, &conn, cu_ind_B);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* */
while (!is_instant_reached(&conn, instant)) {
/* Prepare */
event_prepare(&conn);
/* (B) Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* (B) There should NOT be a host notification */
ut_rx_q_is_empty();
}
/* Prepare */
event_prepare(&conn);
/* (B) Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* (B) There should be one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu2);
ut_rx_q_is_empty();
{
/* Now the locally initiated CPR on conn_3rd should be allowed to run */
/* Prepare */
event_prepare(&conn_2nd);
/* Tx Queue should have one LL Control PDU, indicating parallel CPR is now active */
conn_param_req.reference_conn_event_count = event_counter(&conn_2nd);
lt_rx(LL_CONNECTION_PARAM_REQ, &conn_2nd, &tx, &conn_param_req);
lt_rx_q_is_empty(&conn_2nd);
/* Done */
event_done(&conn_2nd);
/* Release Tx */
ull_cp_release_tx(&conn_2nd, tx);
}
/* Release Ntf */
ull_cp_release_ntf(ntf);
/* One less CTXs as the conn_2nd CPR is still 'running' */
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt()-1,
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Central-initiated Connection Parameters Request procedure.
* Central requests change in LE connection parameters, peripheral’s Host accepts.
*
* +-----+ +-------+ +-----+
* | UT | | LL_P | | LT |
* +-----+ +-------+ +-----+
* | | |
* | | LL_CONNECTION_PARAM_REQ |
* | |<--------------------------|
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* ~~~~~ parallel remote CPR is attempted and rejected ~~~~~~~
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | LE Remote Connection | |
* | Parameter Request | |
* |<--------------------------| |
* | LE Remote Connection | |
* | Parameter Request | |
* | Reply | |
* |-------------------------->| |
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* ~~~~~ parallel local CPR is attempted and cached ~~~~~~~
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | | LL_CONNECTION_PARAM_RSP |
* | |-------------------------->|
* | | |
* | | LL_CONNECTION_UPDATE_IND |
* | |<--------------------------|
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| |
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* ~~~~~~~~~ parallel local CPR is now started ~~~~~~~~~~~~
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
*/
void test_conn_update_periph_rem_accept_reject_2nd_cpr(void)
{
uint8_t err;
struct ll_conn conn_2nd;
struct ll_conn conn_3rd;
struct node_tx *tx;
struct node_rx_pdu *ntf;
uint16_t instant;
struct pdu_data_llctrl_reject_ext_ind parallel_reject_ext_ind = {
.reject_opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ,
.error_code = BT_HCI_ERR_UNSUPP_LL_PARAM_VAL
};
struct node_rx_pu cu = { .status = BT_HCI_ERR_SUCCESS };
/* Initialize extra connections */
test_setup_idx(&conn_2nd, 1);
test_setup_idx(&conn_3rd, 2);
/* Role */
test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
/* Role */
test_set_role(&conn_2nd, BT_HCI_ROLE_PERIPHERAL);
/* Role */
test_set_role(&conn_3rd, BT_HCI_ROLE_CENTRAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Connect */
ull_cp_state_set(&conn_2nd, ULL_CP_CONNECTED);
/* Connect */
ull_cp_state_set(&conn_3rd, ULL_CP_CONNECTED);
/* 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);
/* Done */
event_done(&conn);
{
/* Parallel CPR from central */
/* Now CPR is active on 'conn' so let 'conn_2nd' attempt to start a CPR */
/* Prepare */
event_prepare(&conn_2nd);
/* Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn_2nd);
/* Rx */
lt_tx(LL_CONNECTION_PARAM_REQ, &conn_2nd, &conn_param_req);
/* Done */
event_done(&conn_2nd);
/* Tx Queue should have one LL Control PDU */
lt_rx(LL_REJECT_EXT_IND, &conn_2nd, &tx, &parallel_reject_ext_ind);
lt_rx_q_is_empty(&conn_2nd);
/* Release Tx */
ull_cp_release_tx(&conn_2nd, tx);
/* There should be no 'extra' procedure on acount of the parallel CPR */
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt()-1,
"Free CTX buffers %d", ctx_buffers_free());
}
/* Prepare */
event_prepare(&conn);
/* Done */
event_done(&conn);
{
/* Parallel CPR from peripheral */
/* Now CPR is active on 'conn' so let 'conn_3rd' attempt to start a CPR */
/* Prepare */
event_prepare(&conn_3rd);
/* Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn_3rd);
/* Rx */
lt_tx(LL_CONNECTION_PARAM_REQ, &conn_3rd, &conn_param_req);
/* Done */
event_done(&conn_3rd);
/* Tx Queue should have one LL Control PDU */
lt_rx(LL_REJECT_EXT_IND, &conn_3rd, &tx, &parallel_reject_ext_ind);
lt_rx_q_is_empty(&conn_3rd);
/* Release Tx */
ull_cp_release_tx(&conn_3rd, tx);
/* There should be no 'extra' procedure on acount of the parallel CPR */
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt()-1,
"Free CTX buffers %d", ctx_buffers_free());
}
/* There should be one host notification */
ut_rx_pdu(LL_CONNECTION_PARAM_REQ, &ntf, &conn_param_req);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
/*******************/
ull_cp_conn_param_req_reply(&conn);
{
/* Initiate a parallel local Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn_2nd, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT);
zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL);
/* Prepare */
event_prepare(&conn_2nd);
/* Tx Queue should have no LL Control PDU */
lt_rx_q_is_empty(&conn_2nd);
/* Done */
event_done(&conn_2nd);
/* Prepare */
event_prepare(&conn_2nd);
/* Tx Queue should have no LL Control PDU */
lt_rx_q_is_empty(&conn_2nd);
/* Done */
event_done(&conn_2nd);
}
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
lt_rx(LL_CONNECTION_PARAM_RSP, &conn, &tx, &conn_param_rsp);
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 one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu);
ut_rx_q_is_empty();
{
/* Now the locally initiated CPR on conn_3rd should be allowed to run */
/* Prepare */
event_prepare(&conn_2nd);
/* Tx Queue should have one LL Control PDU, indicating parallel CPR is now active */
conn_param_req.reference_conn_event_count = event_counter(&conn_2nd);
lt_rx(LL_CONNECTION_PARAM_REQ, &conn_2nd, &tx, &conn_param_req);
lt_rx_q_is_empty(&conn_2nd);
/* Done */
event_done(&conn_2nd);
/* Release Tx */
ull_cp_release_tx(&conn_2nd, tx);
}
/* Release Ntf */
ull_cp_release_ntf(ntf);
/* One less CTXs as the conn_2nd CPR is still 'running' */
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt()-1,
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Central-initiated Connection Parameters Request procedure.
* Central requests change in LE connection with invalid parameters,
*
* +-----+ +-------+ +-----+
* | UT | | LL_P | | LT |
* +-----+ +-------+ +-----+
* | | |
* | | LL_CONNECTION_PARAM_REQ |
* | |<--------------------------|
* | | |
* | | |
* | | LL_REJECT_EXT_IND |
* | |-------------------------->|
* | | |
* | | |
*/
void test_conn_update_periph_rem_invalid_req(void)
{
struct node_tx *tx;
struct pdu_data_llctrl_reject_ext_ind reject_ext_ind = {
.reject_opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ,
.error_code = BT_HCI_ERR_INVALID_LL_PARAM
};
/* Role */
test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Prepare */
event_prepare(&conn);
/* Rx */
lt_tx(LL_CONNECTION_PARAM_REQ, &conn, &conn_param_req_invalid);
/* Done */
event_done(&conn);
/* 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);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Central-initiated Connection Parameters Request procedure.
* Central requests change in LE connection parameters, peripheral’s Host accepts.
*
* +-----+ +-------+ +-----+
* | UT | | LL_S | | LT |
* +-----+ +-------+ +-----+
* | | |
* | | LL_CONNECTION_PARAM_REQ |
* | |<--------------------------|
* | | |
* | LE Remote Connection | |
* | Parameter Request | |
* |<--------------------------| |
* | LE Remote Connection | |
* | Parameter Request | |
* | Reply | |
* |-------------------------->| |
* | | |
* | | LL_CONNECTION_PARAM_RSP |
* | |-------------------------->|
* | | |
* | | LL_<INVALID_IND> |
* | |<--------------------------|
* | | |
* ~~~~~~~~~~~~~~~~~ TERMINATE CONNECTION ~~~~~~~~~~~~~~~~~~
* | | |
* | | |
*/
void test_conn_update_periph_rem_invalid_ind(void)
{
struct node_tx *tx;
struct node_rx_pdu *ntf;
struct pdu_data_llctrl_reject_ind reject_ind = {
.error_code = BT_HCI_ERR_LL_PROC_COLLISION
};
struct pdu_data_llctrl_reject_ext_ind reject_ext_ind = {
.reject_opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_RSP,
.error_code = BT_HCI_ERR_LL_PROC_COLLISION
};
struct pdu_data_llctrl_unknown_rsp unknown_rsp = {
.type = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_RSP
};
/* Role */
test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* 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);
/* Done */
event_done(&conn);
/*******************/
/* There should be one host notification */
ut_rx_pdu(LL_CONNECTION_PARAM_REQ, &ntf, &conn_param_req);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
/*******************/
ull_cp_conn_param_req_reply(&conn);
/*******************/
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
lt_rx(LL_CONNECTION_PARAM_RSP, &conn, &tx, &conn_param_rsp);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* Prepare */
event_prepare(&conn);
/* Rx */
lt_tx(LL_REJECT_IND, &conn, &reject_ind);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* Termination 'triggered' */
zassert_equal(conn.llcp_terminate.reason_final, BT_HCI_ERR_LMP_PDU_NOT_ALLOWED,
"Terminate reason %d", conn.llcp_terminate.reason_final);
/* Clear termination flag for subsequent test cycle */
conn.llcp_terminate.reason_final = 0;
/* There should be no host notifications */
ut_rx_q_is_empty();
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
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);
/* Done */
event_done(&conn);
/*******************/
/* There should be one host notification */
ut_rx_pdu(LL_CONNECTION_PARAM_REQ, &ntf, &conn_param_req);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
/*******************/
ull_cp_conn_param_req_reply(&conn);
/*******************/
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
lt_rx(LL_CONNECTION_PARAM_RSP, &conn, &tx, &conn_param_rsp);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* Prepare */
event_prepare(&conn);
/* Rx */
lt_tx(LL_REJECT_EXT_IND, &conn, &reject_ext_ind);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* Termination 'triggered' */
zassert_equal(conn.llcp_terminate.reason_final, BT_HCI_ERR_LMP_PDU_NOT_ALLOWED,
"Terminate reason %d", conn.llcp_terminate.reason_final);
/* Clear termination flag for subsequent test cycle */
conn.llcp_terminate.reason_final = 0;
/* There should be no host notifications */
ut_rx_q_is_empty();
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
/* 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);
/* Done */
event_done(&conn);
/*******************/
/* There should be one host notification */
ut_rx_pdu(LL_CONNECTION_PARAM_REQ, &ntf, &conn_param_req);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
/*******************/
ull_cp_conn_param_req_reply(&conn);
/*******************/
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
lt_rx(LL_CONNECTION_PARAM_RSP, &conn, &tx, &conn_param_rsp);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* Prepare */
event_prepare(&conn);
/* Rx */
lt_tx(LL_UNKNOWN_RSP, &conn, &unknown_rsp);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* Termination 'triggered' */
zassert_equal(conn.llcp_terminate.reason_final, BT_HCI_ERR_LMP_PDU_NOT_ALLOWED,
"Terminate reason %d", conn.llcp_terminate.reason_final);
/* There should be no host notifications */
ut_rx_q_is_empty();
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Central-initiated Connection Parameters Request procedure.
* Central requests change in LE connection parameters, peripheral’s Host rejects.
*
* +-----+ +-------+ +-----+
* | UT | | LL_P | | LT |
* +-----+ +-------+ +-----+
* | | |
* | | LL_CONNECTION_PARAM_REQ |
* | |<--------------------------|
* | | |
* | LE Remote Connection | |
* | Parameter Request | |
* |<--------------------------| |
* | LE Remote Connection | |
* | Parameter Request | |
* | Negative Reply | |
* |-------------------------->| |
* | | |
* | | LL_REJECT_EXT_IND |
* | |-------------------------->|
* | | |
*/
void test_conn_update_periph_rem_reject(void)
{
struct node_tx *tx;
struct node_rx_pdu *ntf;
struct pdu_data_llctrl_reject_ext_ind reject_ext_ind = {
.reject_opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ,
.error_code = BT_HCI_ERR_UNACCEPT_CONN_PARAM
};
/* Role */
test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* 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);
/* Done */
event_done(&conn);
/*******************/
/* There should be one host notification */
ut_rx_pdu(LL_CONNECTION_PARAM_REQ, &ntf, &conn_param_req);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
/*******************/
ull_cp_conn_param_req_neg_reply(&conn, BT_HCI_ERR_UNACCEPT_CONN_PARAM);
/*******************/
/* 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);
/* Done */
event_done(&conn);
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* (A)
* Central-initiated Connection Parameters Request procedure.
* Central requests change in LE connection parameters, peripheral’s Host accepts.
*
* and
*
* (B)
* Peripheral-initiated Connection Parameters Request procedure.
* Peripheral requests change in LE connection parameters, central’s Host accepts.
*
* NOTE:
* Peripheral-initiated Connection Parameters Request procedure is paused.
* Central-initiated Connection Parameters Request procedure is finished.
* Peripheral-initiated Connection Parameters Request procedure is resumed.
*
* +-----+ +-------+ +-----+
* | UT | | LL_P | | LT |
* +-----+ +-------+ +-----+
* | | |
* | | LL_CONNECTION_PARAM_REQ |
* | |<--------------------------| (A)
* | | |
* | LE Connection Update | |
* |-------------------------->| | (B)
* | | |
* | <------------------------> |
* | < LOCAL PROCEDURE PAUSED > |
* | <------------------------> |
* | | |
* | LE Remote Connection | |
* | Parameter Request | |
* |<--------------------------| | (A)
* | LE Remote Connection | |
* | Parameter Request | |
* | Reply | |
* |-------------------------->| | (A)
* | | |
* | | LL_CONNECTION_PARAM_RSP |
* | |-------------------------->| (A)
* | | |
* | | LL_CONNECTION_UPDATE_IND |
* | |<--------------------------| (A)
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| | (A)
* | | |
* | <-------------------------> |
* | < LOCAL PROCEDURE RESUMED > |
* | <-------------------------> |
* | | |
* | | LL_CONNECTION_PARAM_REQ |
* | |-------------------------->| (B)
* | | |
* | | LL_CONNECTION_UPDATE_IND |
* | |<--------------------------| (B)
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| | (B)
* | | |
*/
void test_conn_update_periph_rem_collision(void)
{
uint8_t err;
struct node_tx *tx;
struct node_rx_pdu *ntf;
uint16_t instant;
struct node_rx_pu cu = { .status = BT_HCI_ERR_SUCCESS };
/* Role */
test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/*******************/
/* Prepare */
event_prepare(&conn);
/* (A) Rx */
lt_tx(LL_CONNECTION_PARAM_REQ, &conn, &conn_param_req);
/* Done */
event_done(&conn);
/*******************/
/* (B) Initiate a Connection Parameter Request Procedure */
err = ull_cp_conn_update(&conn, req_B->interval_min, req_B->interval_max, req_B->latency,
req_B->timeout);
zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL);
/*******************/
/* Prepare */
event_prepare(&conn);
/* (B) Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/*******************/
/* (A) There should be one host notification */
ut_rx_pdu(LL_CONNECTION_PARAM_REQ, &ntf, &conn_param_req);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
/*******************/
/* (A) */
ull_cp_conn_param_req_reply(&conn);
/*******************/
/* Prepare */
event_prepare(&conn);
/* (A) Tx Queue should have one LL Control PDU */
lt_rx(LL_CONNECTION_PARAM_RSP, &conn, &tx, &conn_param_rsp);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* Prepare */
event_prepare(&conn);
/* (A) Rx */
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);
/* (A) Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* (A) There should NOT be a host notification */
ut_rx_q_is_empty();
}
/* Prepare */
event_prepare(&conn);
/* (B) Tx Queue should have one LL Control PDU */
lt_rx(LL_CONNECTION_PARAM_REQ, &conn, &tx, req_B);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* (A) There should be one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
/* Prepare */
event_prepare(&conn);
/* (B) Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* (B) Rx */
cu_ind_B->instant = instant = event_counter(&conn) + 6;
lt_tx(LL_CONNECTION_UPDATE_IND, &conn, cu_ind_B);
/* Done */
event_done(&conn);
/* */
while (!is_instant_reached(&conn, instant)) {
/* Prepare */
event_prepare(&conn);
/* (B) Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* (B) There should NOT be a host notification */
ut_rx_q_is_empty();
}
/* Prepare */
event_prepare(&conn);
/* (B) Tx Queue should NOT have a LL Control PDU */
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* (B) There should be one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
/*
* Parameter Request Procedure not supported.
* Central-initiated Connection Update procedure.
* Central requests update of LE connection.
*
* +-----+ +-------+ +-----+
* | UT | | LL_C | | LT |
* +-----+ +-------+ +-----+
* | | |
* | LE Connection Update | |
* |-------------------------->| |
* | | LL_CONNECTION_UPDATE_IND |
* | |-------------------------->|
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| |
* | | |
* | (If conn. parameters are | |
* | unchanged, host should | |
* | not receive a ntf.) | |
* | | |
*/
void test_conn_update_central_loc_accept_no_param_req(void)
{
uint8_t err;
struct node_tx *tx;
struct node_rx_pdu *ntf;
struct pdu_data *pdu;
uint16_t instant;
/* Test with and without parameter change */
uint8_t parameters_changed = 1U;
struct node_rx_pu cu = { .status = BT_HCI_ERR_SUCCESS };
/* Role */
test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
do {
/* Initiate a Connection Update Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT);
zassert_equal(err, BT_HCI_ERR_SUCCESS, NULL);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
conn_update_ind.instant = event_counter(&conn) + 6U;
lt_rx(LL_CONNECTION_UPDATE_IND, &conn, &tx, &conn_update_ind);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* Release Tx */
ull_cp_release_tx(&conn, tx);
/* Save Instant */
pdu = (struct pdu_data *)tx->pdu;
instant = sys_le16_to_cpu(pdu->llctrl.conn_update_ind.instant);
/* */
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);
if (parameters_changed == 0U) {
/* There should NOT be a host notification */
ut_rx_q_is_empty();
} else {
/* There should be one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
}
} while (parameters_changed-- > 0U);
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Parameter Request Procedure not supported.
* Peripheral-initiated Connection Update/Connection Parameter Request procedure
* Central receives Connection Update parameters.
*
* +-----+ +-------+ +-----+
* | UT | | LL_C | | LT |
* +-----+ +-------+ +-----+
* | | |
* | | LL_CONNECTION_UPDATE_IND |
* | |<--------------------------|
* | | |
* | | LL_UNKNOWN_RSP |
* | |-------------------------->|
* | | |
* | | |
* | | LL_CONNECTION_PARAM_REQ |
* | |<--------------------------|
* | | |
* | | LL_UNKNOWN_RSP |
* | |-------------------------->|
* | | |
* | | |
*/
void test_conn_update_central_rem_unknown_no_param_req(void)
{
struct node_tx *tx;
struct pdu_data_llctrl_unknown_rsp unknown_rsp = {
.type = PDU_DATA_LLCTRL_TYPE_CONN_UPDATE_IND
};
/* Role */
test_set_role(&conn, BT_HCI_ROLE_CENTRAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Prepare */
event_prepare(&conn);
/* Rx */
lt_tx(LL_CONNECTION_UPDATE_IND, &conn, &conn_update_ind);
/* Done */
event_done(&conn);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
lt_rx(LL_UNKNOWN_RSP, &conn, &tx, &unknown_rsp);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* There should NOT be a host notification */
ut_rx_q_is_empty();
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
/* Check UNKNOWN_RSP on Connection Parameter Request */
unknown_rsp.type = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ;
/* Prepare */
event_prepare(&conn);
/* Rx */
lt_tx(LL_CONNECTION_PARAM_REQ, &conn, &conn_param_req);
/* Done */
event_done(&conn);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
lt_rx(LL_UNKNOWN_RSP, &conn, &tx, &unknown_rsp);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* There should NOT be a host notification */
ut_rx_q_is_empty();
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Parameter Request Procedure not supported.
* Peripheral-initiated Connection Update/Connection Parameter Request procedure
* Central receives Connection Update parameters.
*
* +-----+ +-------+ +-----+
* | UT | | LL_M | | LT |
* +-----+ +-------+ +-----+
* | | |
* | | |
* | | LL_CONNECTION_PARAM_REQ |
* | |<--------------------------|
* | | |
* | | LL_UNKNOWN_RSP |
* | |-------------------------->|
* | | |
* | | |
*/
void test_conn_update_periph_rem_unknown_no_param_req(void)
{
struct node_tx *tx;
struct pdu_data_llctrl_unknown_rsp unknown_rsp = {
.type = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ
};
/* Role */
test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Prepare */
event_prepare(&conn);
/* Rx */
lt_tx(LL_CONNECTION_PARAM_REQ, &conn, &conn_param_req);
/* Done */
event_done(&conn);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have one LL Control PDU */
lt_rx(LL_UNKNOWN_RSP, &conn, &tx, &unknown_rsp);
lt_rx_q_is_empty(&conn);
/* Done */
event_done(&conn);
/* There should NOT be a host notification */
ut_rx_q_is_empty();
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Parameter Request Procedure not supported.
* Central-initiated Connection Update procedure.
* Peripheral receives Connection Update parameters.
*
* +-----+ +-------+ +-----+
* | UT | | LL_P | | LT |
* +-----+ +-------+ +-----+
* | | |
* | | LL_CONNECTION_UPDATE_IND |
* | |<--------------------------|
* | | |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | |
* | LE Connection Update | |
* | Complete | |
* |<--------------------------| |
* | | |
* | (If conn. parameters are | |
* | unchanged, host should | |
* | not receive a ntf.) | |
* | | |
*/
void test_conn_update_periph_rem_accept_no_param_req(void)
{
struct node_rx_pdu *ntf;
uint16_t instant;
/* Test with and without parameter change */
uint8_t parameters_changed = 1U;
struct node_rx_pu cu = { .status = BT_HCI_ERR_SUCCESS };
/* Role */
test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
do {
/* 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);
/* */
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);
if (parameters_changed == 0U) {
/* There should NOT be a host notification */
ut_rx_q_is_empty();
} else {
/* There should be one host notification */
ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu);
ut_rx_q_is_empty();
/* Release Ntf */
ull_cp_release_ntf(ntf);
}
} while (parameters_changed-- > 0U);
zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
"Free CTX buffers %d", ctx_buffers_free());
}
/*
* Parameter Request Procedure not supported.
* Peripheral-initiated Connection Update procedure (not allowed).
*
* +-----+ +-------+ +-----+
* | UT | | LL_P | | LT |
* +-----+ +-------+ +-----+
* | | |
* | LE Connection Update | |
* |-------------------------->| |
* | | |
* | ERR CMD Disallowed | |
* |<--------------------------| |
* | | |
*/
void test_conn_update_periph_loc_disallowed_no_param_req(void)
{
uint8_t err;
/* Role */
test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL);
/* Connect */
ull_cp_state_set(&conn, ULL_CP_CONNECTED);
/* Initiate a Connection Update Procedure */
err = ull_cp_conn_update(&conn, INTVL_MIN, INTVL_MAX, LATENCY, TIMEOUT);
zassert_equal(err, BT_HCI_ERR_CMD_DISALLOWED, NULL);
/* Prepare */
event_prepare(&conn);
/* Tx Queue should have no 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());
}
void test_main(void)
{
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
ztest_test_suite(
central_loc,
ztest_unit_test_setup_teardown(test_conn_update_central_loc_accept,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_central_loc_invalid_param_rsp,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_central_loc_invalid_rsp,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_central_loc_reject,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_central_loc_accept_reject_2nd_cpr,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_central_loc_remote_legacy,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_central_loc_unsupp_wo_feat_exch,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_central_loc_unsupp_w_feat_exch,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_central_loc_collision,
setup, unit_test_noop));
ztest_test_suite(central_rem,
ztest_unit_test_setup_teardown(test_conn_update_central_rem_accept,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_central_rem_invalid_req,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_central_rem_reject,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_central_rem_collision,
setup, unit_test_noop));
ztest_test_suite(
periph_loc,
ztest_unit_test_setup_teardown(test_conn_update_periph_loc_accept,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_periph_loc_reject,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_periph_loc_unsupp_feat_wo_feat_exch,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_periph_loc_unsupp_feat_w_feat_exch,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_periph_loc_collision_reject_2nd_cpr,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_periph_loc_collision,
setup, unit_test_noop));
ztest_test_suite(
periph_rem,
ztest_unit_test_setup_teardown(test_conn_update_periph_rem_accept,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_periph_rem_invalid_req,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_periph_rem_invalid_ind,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_periph_rem_collision,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_periph_rem_accept_reject_2nd_cpr,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(test_conn_update_periph_rem_reject,
setup, unit_test_noop));
ztest_run_test_suite(central_loc);
ztest_run_test_suite(central_rem);
ztest_run_test_suite(periph_loc);
ztest_run_test_suite(periph_rem);
#else /* !CONFIG_BT_CTLR_CONN_PARAM_REQ */
ztest_test_suite(central_loc_no_param_req, ztest_unit_test_setup_teardown(
test_conn_update_central_loc_accept_no_param_req,
setup, unit_test_noop));
ztest_test_suite(central_rem_no_param_req, ztest_unit_test_setup_teardown(
test_conn_update_central_rem_unknown_no_param_req,
setup, unit_test_noop));
ztest_test_suite(
periph_loc_no_param_req,
ztest_unit_test_setup_teardown(test_conn_update_periph_loc_disallowed_no_param_req,
setup, unit_test_noop));
ztest_test_suite(periph_rem_no_param_req,
ztest_unit_test_setup_teardown(
test_conn_update_periph_rem_accept_no_param_req,
setup, unit_test_noop),
ztest_unit_test_setup_teardown(
test_conn_update_periph_rem_unknown_no_param_req,
setup, unit_test_noop));
ztest_run_test_suite(central_loc_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_rem_no_param_req);
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
}