1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 #include <string.h>
21 #include "os/os.h"
22 #include "testutil/testutil.h"
23 #include "nimble/hci_common.h"
24 #include "nimble/ble_hci_trans.h"
25 #include "host/ble_hs_test.h"
26 #include "host/ble_gap.h"
27 #include "ble_hs_test_util.h"
28
29 #define BLE_OS_TEST_STACK_SIZE 256
30 #define BLE_OS_TEST_APP_STACK_SIZE 256
31
32 #define BLE_OS_TEST_APP_PRIO 9
33 #define BLE_OS_TEST_TASK_PRIO 10
34
35 static struct os_task ble_os_test_task;
36 static struct os_task ble_os_test_app_task;
37 static os_stack_t ble_os_test_stack[OS_STACK_ALIGN(BLE_OS_TEST_STACK_SIZE)];
38
39 static os_stack_t
40 ble_os_test_app_stack[OS_STACK_ALIGN(BLE_OS_TEST_APP_STACK_SIZE)];
41
42 static uint8_t ble_os_test_peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
43
44 static void ble_os_test_app_task_handler(void *arg);
45
46 static int ble_os_test_gap_event_type;
47
48 static void
ble_os_test_init_app_task(void)49 ble_os_test_init_app_task(void)
50 {
51 int rc;
52
53 rc = os_task_init(&ble_os_test_app_task,
54 "ble_gap_terminate_test_task",
55 ble_os_test_app_task_handler, NULL,
56 BLE_OS_TEST_APP_PRIO, OS_WAIT_FOREVER,
57 ble_os_test_app_stack,
58 OS_STACK_ALIGN(BLE_OS_TEST_APP_STACK_SIZE));
59 TEST_ASSERT_FATAL(rc == 0);
60 }
61
62 static void
ble_os_test_misc_init(void)63 ble_os_test_misc_init(void)
64 {
65 extern os_time_t g_os_time;
66
67 ble_hs_test_util_init_no_start();
68
69 /* Allow the OS to approach tick rollover. This will help ensure host
70 * timers don't break when the tick counter resets.
71 */
72 g_os_time = UINT32_MAX - 10 * OS_TICKS_PER_SEC;
73
74 /* Receive acknowledgements for the startup sequence. We sent the
75 * corresponding requests when the host task was started.
76 */
77 ble_hs_test_util_hci_ack_set_startup();
78
79 ble_os_test_init_app_task();
80 }
81
82 static int
ble_os_test_misc_conn_exists(uint16_t conn_handle)83 ble_os_test_misc_conn_exists(uint16_t conn_handle)
84 {
85 struct ble_hs_conn *conn;
86
87 ble_hs_lock();
88
89 if (conn_handle == BLE_HS_CONN_HANDLE_NONE) {
90 conn = ble_hs_conn_first();
91 } else {
92 conn = ble_hs_conn_find(conn_handle);
93 }
94
95 ble_hs_unlock();
96
97 return conn != NULL;
98 }
99
100 static int
ble_gap_direct_connect_test_connect_cb(struct ble_gap_event * event,void * arg)101 ble_gap_direct_connect_test_connect_cb(struct ble_gap_event *event, void *arg)
102 {
103 struct ble_gap_conn_desc desc;
104 int *cb_called;
105 int rc;
106
107 cb_called = arg;
108 *cb_called = 1;
109
110 TEST_ASSERT(event->type == BLE_GAP_EVENT_CONNECT);
111 TEST_ASSERT(event->connect.status == 0);
112 TEST_ASSERT(event->connect.conn_handle == 2);
113
114 rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
115 TEST_ASSERT_FATAL(rc == 0);
116 TEST_ASSERT(desc.peer_id_addr.type == BLE_ADDR_PUBLIC);
117 TEST_ASSERT(memcmp(desc.peer_id_addr.val, ble_os_test_peer_addr, 6) == 0);
118
119 return 0;
120 }
121
122 static void
ble_gap_direct_connect_test_task_handler(void * arg)123 ble_gap_direct_connect_test_task_handler(void *arg)
124 {
125 struct hci_le_conn_complete evt;
126 ble_addr_t addr = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 }};
127 int cb_called;
128 int rc;
129
130 /* Set the connect callback so we can verify that it gets called with the
131 * proper arguments.
132 */
133 cb_called = 0;
134
135 /* Make sure there are no created connections and no connections in
136 * progress.
137 */
138 TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
139
140 /* Initiate a direct connection. */
141 ble_hs_test_util_connect(BLE_OWN_ADDR_PUBLIC, &addr, 0, NULL,
142 ble_gap_direct_connect_test_connect_cb,
143 &cb_called, 0);
144 TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
145 TEST_ASSERT(!cb_called);
146
147 /* ble_gap_rx_conn_complete() will send extra HCI command, need phony ack */
148 ble_hs_test_util_hci_ack_set(ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
149 BLE_HCI_OCF_LE_RD_REM_FEAT), 0);
150
151 /* Receive an HCI connection-complete event. */
152 memset(&evt, 0, sizeof evt);
153 evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
154 evt.status = BLE_ERR_SUCCESS;
155 evt.connection_handle = 2;
156 memcpy(evt.peer_addr, addr.val, 6);
157 rc = ble_gap_rx_conn_complete(&evt, 0);
158 TEST_ASSERT(rc == 0);
159
160 /* The connection should now be created. */
161 TEST_ASSERT(ble_os_test_misc_conn_exists(2));
162 TEST_ASSERT(cb_called);
163
164 tu_restart();
165 }
166
TEST_CASE(ble_gap_direct_connect_test_case)167 TEST_CASE(ble_gap_direct_connect_test_case)
168 {
169 ble_os_test_misc_init();
170
171 os_task_init(&ble_os_test_task,
172 "ble_gap_direct_connect_test_task",
173 ble_gap_direct_connect_test_task_handler, NULL,
174 BLE_OS_TEST_TASK_PRIO, OS_WAIT_FOREVER, ble_os_test_stack,
175 OS_STACK_ALIGN(BLE_OS_TEST_STACK_SIZE));
176
177 os_start();
178 }
179
180 static int
ble_os_disc_test_cb(struct ble_gap_event * event,void * arg)181 ble_os_disc_test_cb(struct ble_gap_event *event, void *arg)
182 {
183 int *cb_called;
184
185 cb_called = arg;
186 *cb_called = 1;
187
188 TEST_ASSERT(event->type == BLE_GAP_EVENT_DISC_COMPLETE);
189
190 return 0;
191 }
192
193 static void
ble_os_disc_test_task_handler(void * arg)194 ble_os_disc_test_task_handler(void *arg)
195 {
196 struct ble_gap_disc_params disc_params;
197 int cb_called;
198 int rc;
199
200 /* Receive acknowledgements for the startup sequence. We sent the
201 * corresponding requests when the host task was started.
202 */
203 ble_hs_test_util_hci_ack_set_startup();
204
205 /* Set the connect callback so we can verify that it gets called with the
206 * proper arguments.
207 */
208 cb_called = 0;
209
210 os_time_delay(10);
211
212 /* Make sure there are no created connections and no connections in
213 * progress.
214 */
215 TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
216 TEST_ASSERT(!ble_gap_master_in_progress());
217
218 /* Initiate the general discovery procedure with a 300 ms timeout. */
219 memset(&disc_params, 0, sizeof disc_params);
220 rc = ble_hs_test_util_disc(BLE_OWN_ADDR_PUBLIC, 300, &disc_params,
221 ble_os_disc_test_cb,
222 &cb_called, 0, 0);
223 TEST_ASSERT(rc == 0);
224 TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
225 TEST_ASSERT(ble_gap_master_in_progress());
226 TEST_ASSERT(!cb_called);
227
228 /* Receive acks from the controller. */
229 TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
230 TEST_ASSERT(ble_gap_master_in_progress());
231 TEST_ASSERT(!cb_called);
232
233 /* Wait 100 ms; verify scan still in progress. */
234 os_time_delay(100 * OS_TICKS_PER_SEC / 1000);
235 TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
236 TEST_ASSERT(ble_gap_master_in_progress());
237 TEST_ASSERT(!cb_called);
238
239 ble_hs_test_util_hci_ack_set(
240 ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
241 BLE_HCI_OCF_LE_SET_SCAN_ENABLE),
242 0);
243
244 /* Wait 250 more ms; verify scan completed. */
245 os_time_delay(250 * OS_TICKS_PER_SEC / 1000);
246 TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
247 TEST_ASSERT(!ble_gap_master_in_progress());
248 TEST_ASSERT(cb_called);
249
250 tu_restart();
251 }
252
TEST_CASE(ble_os_disc_test_case)253 TEST_CASE(ble_os_disc_test_case)
254 {
255 ble_os_test_misc_init();
256
257 os_task_init(&ble_os_test_task,
258 "ble_os_disc_test_task",
259 ble_os_disc_test_task_handler, NULL,
260 BLE_OS_TEST_TASK_PRIO, OS_WAIT_FOREVER, ble_os_test_stack,
261 OS_STACK_ALIGN(BLE_OS_TEST_STACK_SIZE));
262
263 os_start();
264 }
265
266 static int
ble_gap_terminate_cb(struct ble_gap_event * event,void * arg)267 ble_gap_terminate_cb(struct ble_gap_event *event, void *arg)
268 {
269 int *disconn_handle;
270
271 ble_os_test_gap_event_type = event->type;
272
273 if (event->type == BLE_GAP_EVENT_DISCONNECT) {
274 disconn_handle = arg;
275 *disconn_handle = event->disconnect.conn.conn_handle;
276 }
277
278 return 0;
279 }
280
281 static void
ble_gap_terminate_test_task_handler(void * arg)282 ble_gap_terminate_test_task_handler(void *arg)
283 {
284 struct hci_disconn_complete disconn_evt;
285 struct hci_le_conn_complete conn_evt;
286 ble_addr_t addr1 = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 }};
287 ble_addr_t addr2 = { BLE_ADDR_PUBLIC, { 2, 3, 4, 5, 6, 7 }};
288 int disconn_handle;
289 int rc;
290
291 /* Receive acknowledgements for the startup sequence. We sent the
292 * corresponding requests when the host task was started.
293 */
294 ble_hs_test_util_hci_ack_set_startup();
295
296 /* Set the connect callback so we can verify that it gets called with the
297 * proper arguments.
298 */
299 disconn_handle = 0;
300
301 /* Make sure there are no created connections and no connections in
302 * progress.
303 */
304 TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
305 TEST_ASSERT(!ble_gap_master_in_progress());
306
307 /* Create two direct connections. */
308 ble_hs_test_util_connect(BLE_OWN_ADDR_PUBLIC,
309 &addr1, 0, NULL, ble_gap_terminate_cb,
310 &disconn_handle, 0);
311 /* ble_gap_rx_conn_complete() will send extra HCI command, need phony ack */
312 ble_hs_test_util_hci_ack_set(ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
313 BLE_HCI_OCF_LE_RD_REM_FEAT), 0);
314 memset(&conn_evt, 0, sizeof conn_evt);
315 conn_evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
316 conn_evt.status = BLE_ERR_SUCCESS;
317 conn_evt.connection_handle = 1;
318 memcpy(conn_evt.peer_addr, addr1.val, 6);
319 rc = ble_gap_rx_conn_complete(&conn_evt, 0);
320 TEST_ASSERT(rc == 0);
321
322 ble_hs_test_util_connect(BLE_OWN_ADDR_PUBLIC,
323 &addr2, 0, NULL, ble_gap_terminate_cb,
324 &disconn_handle, 0);
325 /* ble_gap_rx_conn_complete() will send extra HCI command, need phony ack */
326 ble_hs_test_util_hci_ack_set(ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
327 BLE_HCI_OCF_LE_RD_REM_FEAT), 0);
328 memset(&conn_evt, 0, sizeof conn_evt);
329 conn_evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
330 conn_evt.status = BLE_ERR_SUCCESS;
331 conn_evt.connection_handle = 2;
332 memcpy(conn_evt.peer_addr, addr2.val, 6);
333 rc = ble_gap_rx_conn_complete(&conn_evt, 0);
334 TEST_ASSERT(rc == 0);
335
336 TEST_ASSERT_FATAL(ble_os_test_misc_conn_exists(1));
337 TEST_ASSERT_FATAL(ble_os_test_misc_conn_exists(2));
338
339 /* Terminate the first one. */
340 rc = ble_hs_test_util_conn_terminate(1, 0);
341 TEST_ASSERT(rc == 0);
342 disconn_evt.connection_handle = 1;
343 disconn_evt.status = 0;
344 disconn_evt.reason = BLE_ERR_REM_USER_CONN_TERM;
345 ble_hs_test_util_hci_rx_disconn_complete_event(&disconn_evt);
346 TEST_ASSERT(ble_os_test_gap_event_type == BLE_GAP_EVENT_DISCONNECT);
347 TEST_ASSERT(disconn_handle == 1);
348 TEST_ASSERT_FATAL(!ble_os_test_misc_conn_exists(1));
349 TEST_ASSERT_FATAL(ble_os_test_misc_conn_exists(2));
350
351 /* Terminate the second one. */
352 rc = ble_hs_test_util_conn_terminate(2, 0);
353 TEST_ASSERT(rc == 0);
354 disconn_evt.connection_handle = 2;
355 disconn_evt.status = 0;
356 disconn_evt.reason = BLE_ERR_REM_USER_CONN_TERM;
357 ble_hs_test_util_hci_rx_disconn_complete_event(&disconn_evt);
358 TEST_ASSERT(ble_os_test_gap_event_type == BLE_GAP_EVENT_DISCONNECT);
359 TEST_ASSERT(disconn_handle == 2);
360 TEST_ASSERT_FATAL(!ble_os_test_misc_conn_exists(1));
361 TEST_ASSERT_FATAL(!ble_os_test_misc_conn_exists(2));
362
363 tu_restart();
364 }
365
366 static void
ble_os_test_app_task_handler(void * arg)367 ble_os_test_app_task_handler(void *arg)
368 {
369 while (1) {
370 os_eventq_run(os_eventq_dflt_get());
371 }
372 }
373
TEST_CASE(ble_gap_terminate_test_case)374 TEST_CASE(ble_gap_terminate_test_case)
375 {
376 ble_os_test_misc_init();
377
378 os_task_init(&ble_os_test_task,
379 "ble_gap_terminate_test_task",
380 ble_gap_terminate_test_task_handler, NULL,
381 BLE_OS_TEST_TASK_PRIO, OS_WAIT_FOREVER, ble_os_test_stack,
382 OS_STACK_ALIGN(BLE_OS_TEST_STACK_SIZE));
383
384 os_start();
385 }
386
TEST_SUITE(ble_os_test_suite)387 TEST_SUITE(ble_os_test_suite)
388 {
389 tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
390
391 ble_os_disc_test_case();
392 ble_gap_direct_connect_test_case();
393 ble_gap_terminate_test_case();
394 }
395
396 int
ble_os_test_all(void)397 ble_os_test_all(void)
398 {
399 ble_os_test_suite();
400 return tu_any_failed;
401 }
402