1 /*
2  * Copyright (c) 2021 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <stddef.h>
9 #include <zephyr/ztest.h>
10 
11 #include <zephyr/bluetooth/bluetooth.h>
12 #include <zephyr/bluetooth/hci.h>
13 #include <zephyr/sys/byteorder.h>
14 #include <host/hci_core.h>
15 
16 #include <bt_common.h>
17 #include <bt_conn_common.h>
18 #include "test_cte_set_rx_params.h"
19 
20 struct ut_bt_df_conn_cte_request_data {
21 	uint8_t cte_request_interval;
22 	uint8_t requested_cte_length;
23 	uint8_t requested_cte_type;
24 };
25 
26 static uint16_t g_conn_handle;
27 
28 static struct ut_bt_df_conn_cte_request_data g_data;
29 
30 /* Macros delivering common values for unit tests */
31 #define CONN_HANDLE_INVALID (CONFIG_BT_MAX_CONN + 1)
32 #define CONN_PERIPH_LATENCY 7 /* arbitrary latency value */
33 #define REQUEST_INTERVAL_OK (CONN_PERIPH_LATENCY)
34 #define REQUEST_INTERVAL_TOO_LOW (CONN_PERIPH_LATENCY - 1)
35 
36 /* CTE length is stored in 1 octet. If BT Core spec. extends the max value to UINT8_MAX
37  * expected failures may not be checked. If storage size is increased, tests shall be updated.
38  */
39 BUILD_ASSERT(BT_HCI_LE_CTE_LEN_MAX < UINT8_MAX,
40 	     "Can't test expected failures for CTE length value longer than or "
41 	     "equal to UINT8_MAX.");
42 #define REQUEST_CTE_LEN_TOO_LONG (BT_HCI_LE_CTE_LEN_MAX + 1)
43 
44 BUILD_ASSERT(BT_HCI_LE_CTE_LEN_MIN > 0x0,
45 	     "Can't test expected failures for CTE length value smaller or equal to zero");
46 #define REQUEST_CTE_LEN_TOO_SHORT (BT_HCI_LE_CTE_LEN_MIN - 1)
47 
48 /* Arbitrary value different than values allowed BT Core spec. */
49 #define REQUEST_CTE_TYPE_INVALID 0xFF
50 
51 /* @brief Function sends HCI_LE_Set_Connectionless_CTE_Sampling_Enable
52  *        to controller.
53  *
54  * @param conn_handle                 Connection instance handle.
55  * @param data                        CTE request data.
56  * @param enable                      Enable or disable CTE request.
57  *
58  * @return Zero if success, non-zero value in case of failure.
59  */
send_conn_cte_req_enable(uint16_t conn_handle,const struct ut_bt_df_conn_cte_request_data * data,bool enable)60 int send_conn_cte_req_enable(uint16_t conn_handle,
61 			     const struct ut_bt_df_conn_cte_request_data *data, bool enable)
62 {
63 	struct bt_hci_cp_le_conn_cte_req_enable *cp;
64 	struct net_buf *buf;
65 
66 	buf = bt_hci_cmd_create(BT_HCI_OP_LE_CONN_CTE_REQ_ENABLE, sizeof(*cp));
67 	if (!buf) {
68 		return -ENOBUFS;
69 	}
70 
71 	cp = net_buf_add(buf, sizeof(*cp));
72 	(void)memset(cp, 0, sizeof(*cp));
73 	cp->handle = sys_cpu_to_le16(conn_handle);
74 	cp->enable = enable ? 1 : 0;
75 	if (data != NULL) {
76 		cp->cte_request_interval = data->cte_request_interval;
77 		cp->requested_cte_length = data->requested_cte_length;
78 		cp->requested_cte_type = data->requested_cte_type;
79 	}
80 
81 	return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CONN_CTE_REQ_ENABLE, buf, NULL);
82 }
83 
ZTEST(test_hci_set_conn_cte_rx_params_with_conn_set,test_set_conn_cte_req_enable_invalid_conn_handle)84 ZTEST(test_hci_set_conn_cte_rx_params_with_conn_set,
85 	test_set_conn_cte_req_enable_invalid_conn_handle)
86 {
87 	int err;
88 
89 	err = send_conn_cte_req_enable(CONN_HANDLE_INVALID, &g_data, true);
90 	zassert_equal(err, -EIO,
91 		      "Unexpected error value for CTE request enable with wrong conn handle");
92 }
93 
ZTEST(test_hci_set_conn_cte_rx_params_with_conn_set,test_set_conn_cte_req_enable_before_set_rx_params)94 ZTEST(test_hci_set_conn_cte_rx_params_with_conn_set,
95 	test_set_conn_cte_req_enable_before_set_rx_params)
96 {
97 	int err;
98 
99 	err = send_conn_cte_req_enable(g_conn_handle, &g_data, true);
100 	zassert_equal(err, -EACCES,
101 		      "Unexpected error value for CTE request enable before set rx params");
102 }
103 
ZTEST(test_hci_set_conn_cte_rx_params_with_rx_param_set,test_set_conn_cte_req_enable_with_too_short_interval)104 ZTEST(test_hci_set_conn_cte_rx_params_with_rx_param_set,
105 	test_set_conn_cte_req_enable_with_too_short_interval)
106 {
107 	int err;
108 
109 	g_data.cte_request_interval = REQUEST_INTERVAL_TOO_LOW;
110 
111 	err = send_conn_cte_req_enable(g_conn_handle, &g_data, true);
112 	zassert_equal(err, -EACCES,
113 		      "Unexpected error value for CTE request enable with too short request"
114 		      " interval");
115 }
116 
ZTEST(test_hci_set_conn_cte_rx_params_with_rx_param_set,test_set_conn_cte_req_enable_with_too_long_requested_length)117 ZTEST(test_hci_set_conn_cte_rx_params_with_rx_param_set,
118 	test_set_conn_cte_req_enable_with_too_long_requested_length)
119 {
120 	int err;
121 
122 	g_data.requested_cte_length = REQUEST_CTE_LEN_TOO_LONG;
123 
124 	err = send_conn_cte_req_enable(g_conn_handle, &g_data, true);
125 	zassert_equal(err, -EIO,
126 		      "Unexpected error value for CTE request enable with too long requested CTE"
127 		      " length");
128 }
129 
ZTEST(test_hci_set_conn_cte_rx_params_with_rx_param_set,test_set_conn_cte_req_enable_with_too_short_requested_length)130 ZTEST(test_hci_set_conn_cte_rx_params_with_rx_param_set,
131 	test_set_conn_cte_req_enable_with_too_short_requested_length)
132 {
133 	int err;
134 
135 	g_data.requested_cte_length = REQUEST_CTE_LEN_TOO_SHORT;
136 
137 	err = send_conn_cte_req_enable(g_conn_handle, &g_data, true);
138 	zassert_equal(err, -EIO,
139 		      "Unexpected error value for CTE request enable with too short requested CTE"
140 		      " length");
141 }
142 
ZTEST(test_hci_set_conn_cte_rx_params_with_rx_param_set,test_set_conn_cte_req_enable_with_invalid_cte_type)143 ZTEST(test_hci_set_conn_cte_rx_params_with_rx_param_set,
144 	test_set_conn_cte_req_enable_with_invalid_cte_type)
145 {
146 	int err;
147 
148 	g_data.requested_cte_type = REQUEST_CTE_LEN_TOO_LONG;
149 
150 	err = send_conn_cte_req_enable(g_conn_handle, &g_data, true);
151 	zassert_equal(err, -EIO,
152 		      "Unexpected error value for CTE request enable with invalid CTE type");
153 }
154 
ZTEST(test_hci_set_conn_cte_rx_params_with_rx_param_set,test_set_conn_cte_req_enable)155 ZTEST(test_hci_set_conn_cte_rx_params_with_rx_param_set, test_set_conn_cte_req_enable)
156 {
157 	int err;
158 
159 	err = send_conn_cte_req_enable(g_conn_handle, &g_data, true);
160 	zassert_equal(err, 0, "Unexpected error value for CTE request enable");
161 }
162 
ZTEST(test_hci_set_conn_cte_rx_params_with_cte_req_set,test_set_conn_cte_req_disable)163 ZTEST(test_hci_set_conn_cte_rx_params_with_cte_req_set, test_set_conn_cte_req_disable)
164 {
165 	int err;
166 
167 	err = send_conn_cte_req_enable(g_conn_handle, NULL, false);
168 	zassert_equal(err, 0, "Unexpected error value for CTE request disable");
169 }
cte_req_params_set(void)170 static void cte_req_params_set(void)
171 {
172 	g_data.cte_request_interval = REQUEST_INTERVAL_OK;
173 	g_data.requested_cte_length = BT_HCI_LE_CTE_LEN_MAX;
174 	g_data.requested_cte_type = BT_HCI_LE_AOD_CTE_2US;
175 }
176 
connection_setup(void * data)177 static void connection_setup(void *data)
178 {
179 	cte_req_params_set();
180 
181 	g_conn_handle = ut_bt_create_connection();
182 }
183 
connection_teardown(void * data)184 static void connection_teardown(void *data) { ut_bt_destroy_connection(g_conn_handle); }
185 
cte_rx_param_setup(void * data)186 static void cte_rx_param_setup(void *data)
187 {
188 	/* Arbitrary antenna IDs. May be random for test purposes. */
189 	static uint8_t ant_ids[] = { 0x1, 0x2, 0x3, 0x4, 0x5 };
190 
191 	/* Use arbitrary values that allow enable CTE receive and sampling. */
192 	struct ut_bt_df_conn_cte_rx_params cte_rx_params = {
193 		.slot_durations = BT_HCI_LE_ANTENNA_SWITCHING_SLOT_1US,
194 		.switch_pattern_len = ARRAY_SIZE(ant_ids),
195 		.ant_ids = ant_ids
196 	};
197 
198 	cte_req_params_set();
199 
200 	g_conn_handle = ut_bt_create_connection();
201 	ut_bt_set_periph_latency(g_conn_handle, CONN_PERIPH_LATENCY);
202 
203 	send_set_conn_cte_rx_params(g_conn_handle, &cte_rx_params, true);
204 }
205 
cte_req_setup(void * data)206 static void cte_req_setup(void *data)
207 {
208 	cte_rx_param_setup(data);
209 
210 	send_conn_cte_req_enable(g_conn_handle, &g_data, true);
211 }
212 
cte_rx_param_teardown(void * data)213 static void cte_rx_param_teardown(void *data)
214 {
215 	connection_teardown(data);
216 
217 	send_set_conn_cte_rx_params(g_conn_handle, NULL, false);
218 }
219 
cte_req_teardown(void * data)220 static void cte_req_teardown(void *data)
221 {
222 	send_conn_cte_req_enable(g_conn_handle, NULL, false);
223 
224 	cte_rx_param_teardown(data);
225 }
226 
227 ZTEST_SUITE(test_hci_set_conn_cte_rx_params_with_conn_set, NULL, ut_bt_setup, connection_setup,
228 	    connection_teardown, ut_bt_teardown);
229 ZTEST_SUITE(test_hci_set_conn_cte_rx_params_with_rx_param_set, NULL, ut_bt_setup,
230 	    cte_rx_param_setup, cte_rx_param_teardown, ut_bt_teardown);
231 ZTEST_SUITE(test_hci_set_conn_cte_rx_params_with_cte_req_set, NULL, ut_bt_setup, cte_req_setup,
232 	    cte_req_teardown, ut_bt_teardown);
233