| /* |
| * Copyright (c) 2021 Nordic Semiconductor ASA |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <zephyr/kernel.h> |
| #include <stddef.h> |
| #include <zephyr/ztest.h> |
| |
| #include <zephyr/bluetooth/bluetooth.h> |
| #include <zephyr/bluetooth/hci.h> |
| #include <zephyr/sys/byteorder.h> |
| #include <host/hci_core.h> |
| |
| #include <bt_common.h> |
| #include <bt_conn_common.h> |
| #include "test_cte_set_rx_params.h" |
| |
| struct ut_bt_df_conn_cte_request_data { |
| uint8_t cte_request_interval; |
| uint8_t requested_cte_length; |
| uint8_t requested_cte_type; |
| }; |
| |
| static uint16_t g_conn_handle; |
| |
| static struct ut_bt_df_conn_cte_request_data g_data; |
| |
| /* Macros delivering common values for unit tests */ |
| #define CONN_HANDLE_INVALID (CONFIG_BT_MAX_CONN + 1) |
| #define CONN_PERIPH_LATENCY 7 /* arbitrary latency value */ |
| #define REQUEST_INTERVAL_OK (CONN_PERIPH_LATENCY) |
| #define REQUEST_INTERVAL_TOO_LOW (CONN_PERIPH_LATENCY - 1) |
| |
| /* CTE length is stored in 1 octet. If BT Core spec. extends the max value to UINT8_MAX |
| * expected failures may not be checked. If storage size is increased, tests shall be updated. |
| */ |
| BUILD_ASSERT(BT_HCI_LE_CTE_LEN_MAX < UINT8_MAX, |
| "Can't test expected failures for CTE length value longer than or " |
| "equal to UINT8_MAX."); |
| #define REQUEST_CTE_LEN_TOO_LONG (BT_HCI_LE_CTE_LEN_MAX + 1) |
| |
| BUILD_ASSERT(BT_HCI_LE_CTE_LEN_MIN > 0x0, |
| "Can't test expected failures for CTE length value smaller or equal to zero"); |
| #define REQUEST_CTE_LEN_TOO_SHORT (BT_HCI_LE_CTE_LEN_MIN - 1) |
| |
| /* Arbitrary value different than values allowed BT Core spec. */ |
| #define REQUEST_CTE_TYPE_INVALID 0xFF |
| |
| /* @brief Function sends HCI_LE_Set_Connectionless_CTE_Sampling_Enable |
| * to controller. |
| * |
| * @param conn_handle Connection instance handle. |
| * @param data CTE request data. |
| * @param enable Enable or disable CTE request. |
| * |
| * @return Zero if success, non-zero value in case of failure. |
| */ |
| int send_conn_cte_req_enable(uint16_t conn_handle, |
| const struct ut_bt_df_conn_cte_request_data *data, bool enable) |
| { |
| struct bt_hci_cp_le_conn_cte_req_enable *cp; |
| struct net_buf *buf; |
| |
| buf = bt_hci_cmd_create(BT_HCI_OP_LE_CONN_CTE_REQ_ENABLE, sizeof(*cp)); |
| if (!buf) { |
| return -ENOBUFS; |
| } |
| |
| cp = net_buf_add(buf, sizeof(*cp)); |
| (void)memset(cp, 0, sizeof(*cp)); |
| cp->handle = sys_cpu_to_le16(conn_handle); |
| cp->enable = enable ? 1 : 0; |
| if (data != NULL) { |
| cp->cte_request_interval = data->cte_request_interval; |
| cp->requested_cte_length = data->requested_cte_length; |
| cp->requested_cte_type = data->requested_cte_type; |
| } |
| |
| return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CONN_CTE_REQ_ENABLE, buf, NULL); |
| } |
| |
| ZTEST(test_hci_set_conn_cte_rx_params_with_conn_set, |
| test_set_conn_cte_req_enable_invalid_conn_handle) |
| { |
| int err; |
| |
| err = send_conn_cte_req_enable(CONN_HANDLE_INVALID, &g_data, true); |
| zassert_equal(err, -EIO, |
| "Unexpected error value for CTE request enable with wrong conn handle"); |
| } |
| |
| ZTEST(test_hci_set_conn_cte_rx_params_with_conn_set, |
| test_set_conn_cte_req_enable_before_set_rx_params) |
| { |
| int err; |
| |
| err = send_conn_cte_req_enable(g_conn_handle, &g_data, true); |
| zassert_equal(err, -EIO, |
| "Unexpected error value for CTE request enable before set rx params"); |
| } |
| |
| ZTEST(test_hci_set_conn_cte_rx_params_with_rx_param_set, |
| test_set_conn_cte_req_enable_with_too_short_interval) |
| { |
| int err; |
| |
| g_data.cte_request_interval = REQUEST_INTERVAL_TOO_LOW; |
| |
| err = send_conn_cte_req_enable(g_conn_handle, &g_data, true); |
| zassert_equal(err, -EIO, |
| "Unexpected error value for CTE request enable with too short request" |
| " interval"); |
| } |
| |
| ZTEST(test_hci_set_conn_cte_rx_params_with_rx_param_set, |
| test_set_conn_cte_req_enable_with_too_long_requested_length) |
| { |
| int err; |
| |
| g_data.requested_cte_length = REQUEST_CTE_LEN_TOO_LONG; |
| |
| err = send_conn_cte_req_enable(g_conn_handle, &g_data, true); |
| zassert_equal(err, -EIO, |
| "Unexpected error value for CTE request enable with too long requested CTE" |
| " length"); |
| } |
| |
| ZTEST(test_hci_set_conn_cte_rx_params_with_rx_param_set, |
| test_set_conn_cte_req_enable_with_too_short_requested_length) |
| { |
| int err; |
| |
| g_data.requested_cte_length = REQUEST_CTE_LEN_TOO_SHORT; |
| |
| err = send_conn_cte_req_enable(g_conn_handle, &g_data, true); |
| zassert_equal(err, -EIO, |
| "Unexpected error value for CTE request enable with too short requested CTE" |
| " length"); |
| } |
| |
| ZTEST(test_hci_set_conn_cte_rx_params_with_rx_param_set, |
| test_set_conn_cte_req_enable_with_invalid_cte_type) |
| { |
| int err; |
| |
| g_data.requested_cte_type = REQUEST_CTE_LEN_TOO_LONG; |
| |
| err = send_conn_cte_req_enable(g_conn_handle, &g_data, true); |
| zassert_equal(err, -EIO, |
| "Unexpected error value for CTE request enable with invalid CTE type"); |
| } |
| |
| ZTEST(test_hci_set_conn_cte_rx_params_with_rx_param_set, test_set_conn_cte_req_enable) |
| { |
| int err; |
| |
| err = send_conn_cte_req_enable(g_conn_handle, &g_data, true); |
| zassert_equal(err, 0, "Unexpected error value for CTE request enable"); |
| } |
| |
| ZTEST(test_hci_set_conn_cte_rx_params_with_cte_req_set, test_set_conn_cte_req_disable) |
| { |
| int err; |
| |
| err = send_conn_cte_req_enable(g_conn_handle, NULL, false); |
| zassert_equal(err, 0, "Unexpected error value for CTE request disable"); |
| } |
| static void cte_req_params_set(void) |
| { |
| g_data.cte_request_interval = REQUEST_INTERVAL_OK; |
| g_data.requested_cte_length = BT_HCI_LE_CTE_LEN_MAX; |
| g_data.requested_cte_type = BT_HCI_LE_AOD_CTE_2US; |
| } |
| |
| static void connection_setup(void *data) |
| { |
| cte_req_params_set(); |
| |
| g_conn_handle = ut_bt_create_connection(); |
| } |
| |
| static void connection_teardown(void *data) { ut_bt_destroy_connection(g_conn_handle); } |
| |
| static void cte_rx_param_setup(void *data) |
| { |
| /* Arbitrary antenna IDs. May be random for test purposes. */ |
| static uint8_t ant_ids[] = { 0x1, 0x2, 0x3, 0x4, 0x5 }; |
| |
| /* Use arbitrary values that allow enable CTE receive and sampling. */ |
| struct ut_bt_df_conn_cte_rx_params cte_rx_params = { |
| .slot_durations = BT_HCI_LE_ANTENNA_SWITCHING_SLOT_1US, |
| .switch_pattern_len = ARRAY_SIZE(ant_ids), |
| .ant_ids = ant_ids |
| }; |
| |
| cte_req_params_set(); |
| |
| g_conn_handle = ut_bt_create_connection(); |
| ut_bt_set_periph_latency(g_conn_handle, CONN_PERIPH_LATENCY); |
| |
| send_set_conn_cte_rx_params(g_conn_handle, &cte_rx_params, true); |
| } |
| |
| static void cte_req_setup(void *data) |
| { |
| cte_rx_param_setup(data); |
| |
| send_conn_cte_req_enable(g_conn_handle, &g_data, true); |
| } |
| |
| static void cte_rx_param_teardown(void *data) |
| { |
| connection_teardown(data); |
| |
| send_set_conn_cte_rx_params(g_conn_handle, NULL, false); |
| } |
| |
| static void cte_req_teardown(void *data) |
| { |
| send_conn_cte_req_enable(g_conn_handle, NULL, false); |
| |
| cte_rx_param_teardown(data); |
| } |
| |
| ZTEST_SUITE(test_hci_set_conn_cte_rx_params_with_conn_set, NULL, ut_bt_setup, connection_setup, |
| connection_teardown, ut_bt_teardown); |
| ZTEST_SUITE(test_hci_set_conn_cte_rx_params_with_rx_param_set, NULL, ut_bt_setup, |
| cte_rx_param_setup, cte_rx_param_teardown, ut_bt_teardown); |
| ZTEST_SUITE(test_hci_set_conn_cte_rx_params_with_cte_req_set, NULL, ut_bt_setup, cte_req_setup, |
| cte_req_teardown, ut_bt_teardown); |