1 /*
2  * Copyright (c) 2022 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * EATT notification reliability test:
7  * A central acting as a GATT client scans and connects
8  * to a peripheral acting as a GATT server.
9  * The GATT client will then attempt to connect a number of CONFIG_BT_EATT_MAX bearers
10  * over EATT, send notifications, disconnect all bearers and reconnect EATT_BEARERS_TEST
11  * and send start a transaction with a request, then send a lot of notifications
12  * before the response is received.
13  * The test might be expanded by checking that all the notifications all transmitted
14  * on EATT channels.
15  */
16 
17 #include <stddef.h>
18 #include <errno.h>
19 #include <zephyr/kernel.h>
20 #include <zephyr/types.h>
21 #include <zephyr/bluetooth/bluetooth.h>
22 #include <zephyr/bluetooth/hci.h>
23 #include <zephyr/bluetooth/conn.h>
24 #include <zephyr/bluetooth/uuid.h>
25 #include <zephyr/bluetooth/gatt.h>
26 #include <zephyr/bluetooth/att.h>
27 
28 #include "babblekit/testcase.h"
29 #include "babblekit/flags.h"
30 #include "babblekit/sync.h"
31 #include "common.h"
32 
33 DEFINE_FLAG_STATIC(flag_is_connected);
34 DEFINE_FLAG_STATIC(flag_discover_complete);
35 DEFINE_FLAG_STATIC(flag_is_encrypted);
36 
37 static struct bt_conn *g_conn;
38 static const struct bt_gatt_attr *local_attr;
39 static const struct bt_uuid *test_svc_uuid = TEST_SERVICE_UUID;
40 
41 #define NUM_NOTIF 100
42 #define SAMPLE_DATA 1
43 #define EATT_BEARERS_TEST 1
44 
45 volatile int num_eatt_channels;
46 
connected(struct bt_conn * conn,uint8_t err)47 static void connected(struct bt_conn *conn, uint8_t err)
48 {
49 	char addr[BT_ADDR_LE_STR_LEN];
50 
51 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
52 
53 	if (err != 0) {
54 		TEST_FAIL("Failed to connect to %s (%u)", addr, err);
55 		return;
56 	}
57 
58 	printk("Connected to %s\n", addr);
59 	SET_FLAG(flag_is_connected);
60 }
61 
disconnected(struct bt_conn * conn,uint8_t reason)62 static void disconnected(struct bt_conn *conn, uint8_t reason)
63 {
64 	char addr[BT_ADDR_LE_STR_LEN];
65 
66 	if (conn != g_conn) {
67 		return;
68 	}
69 
70 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
71 
72 	printk("Disconnected: %s (reason 0x%02x)\n", addr, reason);
73 
74 	bt_conn_unref(g_conn);
75 
76 	g_conn = NULL;
77 	UNSET_FLAG(flag_is_connected);
78 }
79 
security_changed(struct bt_conn * conn,bt_security_t level,enum bt_security_err security_err)80 static void security_changed(struct bt_conn *conn, bt_security_t level,
81 			     enum bt_security_err security_err)
82 {
83 	if (security_err == BT_SECURITY_ERR_SUCCESS && level > BT_SECURITY_L1) {
84 		SET_FLAG(flag_is_encrypted);
85 	}
86 }
87 
88 BT_CONN_CB_DEFINE(conn_callbacks) = {
89 	.connected = connected,
90 	.disconnected = disconnected,
91 	.security_changed = security_changed,
92 };
93 
device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)94 void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
95 		  struct net_buf_simple *ad)
96 {
97 	char addr_str[BT_ADDR_LE_STR_LEN];
98 	int err;
99 
100 	if (g_conn != NULL) {
101 		return;
102 	}
103 
104 	/* We're only interested in connectable events */
105 	if (type != BT_HCI_ADV_IND && type != BT_HCI_ADV_DIRECT_IND) {
106 		return;
107 	}
108 
109 	bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
110 	printk("Device found: %s (RSSI %d)\n", addr_str, rssi);
111 
112 	printk("Stopping scan\n");
113 	err = bt_le_scan_stop();
114 	if (err != 0) {
115 		TEST_FAIL("Could not stop scan: %d");
116 		return;
117 	}
118 
119 	err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
120 				BT_LE_CONN_PARAM_DEFAULT, &g_conn);
121 	if (err != 0) {
122 		TEST_FAIL("Could not connect to peer: %d", err);
123 	}
124 }
125 
send_notification(void)126 void send_notification(void)
127 {
128 	const uint8_t sample_dat = SAMPLE_DATA;
129 	int err;
130 
131 	do {
132 		err = bt_gatt_notify(g_conn, local_attr, &sample_dat, sizeof(sample_dat));
133 		if (!err) {
134 			return;
135 		} else if (err != -ENOMEM) {
136 			printk("GATT notify failed (err %d)\n", err);
137 			return;
138 		}
139 		k_sleep(K_TICKS(1));
140 	} while (err == -ENOMEM);
141 }
142 
discover_func(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * params)143 static uint8_t discover_func(struct bt_conn *conn,
144 		const struct bt_gatt_attr *attr,
145 		struct bt_gatt_discover_params *params)
146 {
147 	SET_FLAG(flag_discover_complete);
148 	printk("Discover complete\n");
149 
150 	return BT_GATT_ITER_STOP;
151 }
152 
gatt_discover(void)153 static void gatt_discover(void)
154 {
155 	static struct bt_gatt_discover_params discover_params;
156 	int err;
157 
158 	printk("Discovering services and characteristics\n");
159 
160 	discover_params.uuid = test_svc_uuid;
161 	discover_params.func = discover_func;
162 	discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
163 	discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
164 	discover_params.type = BT_GATT_DISCOVER_PRIMARY;
165 	discover_params.chan_opt = BT_ATT_CHAN_OPT_NONE;
166 
167 	err = bt_gatt_discover(g_conn, &discover_params);
168 	if (err != 0) {
169 		TEST_FAIL("Discover failed(err %d)", err);
170 	}
171 }
172 
173 BT_GATT_SERVICE_DEFINE(g_svc,
174 	BT_GATT_PRIMARY_SERVICE(TEST_SERVICE_UUID),
175 	BT_GATT_CHARACTERISTIC(TEST_CHRC_UUID, BT_GATT_CHRC_NOTIFY,
176 			       BT_GATT_PERM_READ, NULL, NULL, NULL),
177 	BT_GATT_CCC(NULL,
178 		    BT_GATT_PERM_READ | BT_GATT_PERM_WRITE));
179 
test_main(void)180 static void test_main(void)
181 {
182 	int err;
183 
184 	TEST_ASSERT(bk_sync_init() == 0, "Failed to open backchannel");
185 
186 	err = bt_enable(NULL);
187 	if (err != 0) {
188 		TEST_FAIL("Bluetooth enable failed (err %d)", err);
189 	}
190 
191 	err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found);
192 	if (err != 0) {
193 		TEST_FAIL("Scanning failed to start (err %d)", err);
194 	}
195 
196 	printk("Scanning successfully started\n");
197 
198 	WAIT_FOR_FLAG(flag_is_connected);
199 
200 	err = bt_conn_set_security(g_conn, BT_SECURITY_L2);
201 	if (err) {
202 		TEST_FAIL("Failed to start encryption procedure");
203 	}
204 
205 	WAIT_FOR_FLAG(flag_is_encrypted);
206 
207 	err = bt_eatt_connect(g_conn, CONFIG_BT_EATT_MAX);
208 	if (err) {
209 		TEST_FAIL("Sending credit based connection request failed (err %d)", err);
210 	}
211 
212 	/* Wait for the channels to be connected */
213 	while (bt_eatt_count(g_conn) < CONFIG_BT_EATT_MAX) {
214 		k_sleep(K_TICKS(1));
215 	}
216 
217 	printk("Waiting for sync\n");
218 	bk_sync_wait();
219 
220 	local_attr = &g_svc.attrs[1];
221 
222 	printk("############# Notification test\n");
223 	for (int idx = 0; idx < NUM_NOTIF; idx++) {
224 		printk("Notification %d\n", idx);
225 		send_notification();
226 	}
227 
228 	printk("############# Disconnect and reconnect\n");
229 	for (int idx = 0; idx < CONFIG_BT_EATT_MAX; idx++) {
230 		bt_eatt_disconnect_one(g_conn);
231 		while (bt_eatt_count(g_conn) != (CONFIG_BT_EATT_MAX - idx)) {
232 			k_sleep(K_TICKS(1));
233 		}
234 	}
235 
236 	printk("Connecting %d bearers\n", EATT_BEARERS_TEST);
237 	err = bt_eatt_connect(g_conn, EATT_BEARERS_TEST);
238 	if (err) {
239 		TEST_FAIL("Sending credit based connection request failed (err %d)", err);
240 	}
241 
242 	/* Wait for the channels to be connected */
243 	while (bt_eatt_count(g_conn) < EATT_BEARERS_TEST) {
244 		k_sleep(K_TICKS(1));
245 	}
246 
247 	printk("############# Send notifications during discovery request\n");
248 	gatt_discover();
249 	while (!IS_FLAG_SET(flag_discover_complete)) {
250 		printk("Notifying...\n");
251 		send_notification();
252 	}
253 
254 	printk("Sending final sync\n");
255 	bk_sync_send();
256 
257 	TEST_PASS("Client Passed");
258 }
259 
260 static const struct bst_test_instance test_vcs[] = {
261 	{
262 		.test_id = "client",
263 		.test_main_f = test_main
264 	},
265 	BSTEST_END_MARKER
266 };
267 
test_client_install(struct bst_test_list * tests)268 struct bst_test_list *test_client_install(struct bst_test_list *tests)
269 {
270 	return bst_add_tests(tests, test_vcs);
271 }
272