1 /*
2  * Copyright (c) 2022 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/bluetooth/bluetooth.h>
8 #include <zephyr/bluetooth/gatt.h>
9 
10 #include "common.h"
11 
12 CREATE_FLAG(flag_is_connected);
13 CREATE_FLAG(flag_discover_complete);
14 CREATE_FLAG(flag_security_changed);
15 CREATE_FLAG(flag_write_complete);
16 CREATE_FLAG(flag_read_complete);
17 
18 static struct bt_conn *g_conn;
19 static uint16_t chrc_handle;
20 static uint16_t long_chrc_handle;
21 static uint16_t enc_chrc_handle;
22 static uint16_t lesc_chrc_handle;
23 static uint8_t att_err;
24 static const struct bt_uuid *test_svc_uuid = TEST_SERVICE_UUID;
25 
26 #define ARRAY_ITEM(i, _) i
27 static uint8_t chrc_data[] = { LISTIFY(CHRC_SIZE, ARRAY_ITEM, (,)) }; /* 1, 2, 3 ... */
28 static uint8_t long_chrc_data[] = { LISTIFY(LONG_CHRC_SIZE, ARRAY_ITEM, (,)) }; /* 1, 2, 3 ... */
29 static uint8_t data_received[LONG_CHRC_SIZE];
30 static uint16_t data_received_size;
31 
connected(struct bt_conn * conn,uint8_t err)32 static void connected(struct bt_conn *conn, uint8_t err)
33 {
34 	char addr[BT_ADDR_LE_STR_LEN];
35 
36 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
37 
38 	if (err != 0) {
39 		FAIL("Failed to connect to %s (%u)\n", addr, err);
40 		return;
41 	}
42 
43 	printk("Connected to %s\n", addr);
44 
45 	__ASSERT_NO_MSG(g_conn == conn);
46 
47 	SET_FLAG(flag_is_connected);
48 }
49 
disconnected(struct bt_conn * conn,uint8_t reason)50 static void disconnected(struct bt_conn *conn, uint8_t reason)
51 {
52 	char addr[BT_ADDR_LE_STR_LEN];
53 
54 	if (conn != g_conn) {
55 		return;
56 	}
57 
58 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
59 
60 	printk("Disconnected: %s (reason 0x%02x)\n", addr, reason);
61 
62 	bt_conn_unref(g_conn);
63 
64 	g_conn = NULL;
65 	UNSET_FLAG(flag_is_connected);
66 }
67 
security_changed(struct bt_conn * conn,bt_security_t level,enum bt_security_err err)68 static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err)
69 {
70 	if (err != BT_SECURITY_ERR_SUCCESS) {
71 		FAIL("Security failed (err %d)\n", err);
72 	} else {
73 		SET_FLAG(flag_security_changed);
74 	}
75 }
76 
77 static struct bt_conn_cb conn_callbacks = {
78 	.connected = connected,
79 	.disconnected = disconnected,
80 	.security_changed = security_changed,
81 };
82 
device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)83 void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
84 		  struct net_buf_simple *ad)
85 {
86 	char addr_str[BT_ADDR_LE_STR_LEN];
87 	int err;
88 
89 	if (g_conn != NULL) {
90 		return;
91 	}
92 
93 	/* We're only interested in connectable events */
94 	if (type != BT_HCI_ADV_IND && type != BT_HCI_ADV_DIRECT_IND) {
95 		return;
96 	}
97 
98 	bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
99 	printk("Device found: %s (RSSI %d)\n", addr_str, rssi);
100 
101 	printk("Stopping scan\n");
102 	err = bt_le_scan_stop();
103 	if (err != 0) {
104 		FAIL("Could not stop scan: %d\n");
105 		return;
106 	}
107 
108 	err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
109 				BT_LE_CONN_PARAM_DEFAULT, &g_conn);
110 	if (err != 0) {
111 		FAIL("Could not connect to peer: %d\n", err);
112 	}
113 }
114 
discover_func(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * params)115 static uint8_t discover_func(struct bt_conn *conn,
116 		const struct bt_gatt_attr *attr,
117 		struct bt_gatt_discover_params *params)
118 {
119 	int err;
120 
121 	if (attr == NULL) {
122 		if (chrc_handle == 0 || long_chrc_handle == 0) {
123 			FAIL("Did not discover chrc (%x) or long_chrc (%x)\n", chrc_handle,
124 			     long_chrc_handle);
125 		}
126 
127 		(void)memset(params, 0, sizeof(*params));
128 
129 		SET_FLAG(flag_discover_complete);
130 
131 		return BT_GATT_ITER_STOP;
132 	}
133 
134 	printk("[ATTRIBUTE] handle %u\n", attr->handle);
135 
136 	if (params->type == BT_GATT_DISCOVER_PRIMARY &&
137 	    bt_uuid_cmp(params->uuid, TEST_SERVICE_UUID) == 0) {
138 		printk("Found test service\n");
139 		params->uuid = NULL;
140 		params->start_handle = attr->handle + 1;
141 		params->type = BT_GATT_DISCOVER_CHARACTERISTIC;
142 
143 		err = bt_gatt_discover(conn, params);
144 		if (err != 0) {
145 			FAIL("Discover failed (err %d)\n", err);
146 		}
147 
148 		return BT_GATT_ITER_STOP;
149 	} else if (params->type == BT_GATT_DISCOVER_CHARACTERISTIC) {
150 		struct bt_gatt_chrc *chrc = (struct bt_gatt_chrc *)attr->user_data;
151 
152 		if (bt_uuid_cmp(chrc->uuid, TEST_CHRC_UUID) == 0) {
153 			printk("Found chrc\n");
154 			chrc_handle = chrc->value_handle;
155 		} else if (bt_uuid_cmp(chrc->uuid, TEST_LONG_CHRC_UUID) == 0) {
156 			printk("Found long_chrc\n");
157 			long_chrc_handle = chrc->value_handle;
158 		} else if (bt_uuid_cmp(chrc->uuid, TEST_ENC_CHRC_UUID) == 0) {
159 			printk("Found enc_chrc_handle\n");
160 			enc_chrc_handle = chrc->value_handle;
161 		} else if (bt_uuid_cmp(chrc->uuid, TEST_LESC_CHRC_UUID) == 0) {
162 			printk("Found lesc_chrc_handle\n");
163 			lesc_chrc_handle = chrc->value_handle;
164 		}
165 	}
166 
167 	return BT_GATT_ITER_CONTINUE;
168 }
169 
gatt_discover(void)170 static void gatt_discover(void)
171 {
172 	static struct bt_gatt_discover_params discover_params;
173 	int err;
174 
175 	printk("Discovering services and characteristics\n");
176 
177 	discover_params.uuid = test_svc_uuid;
178 	discover_params.func = discover_func;
179 	discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
180 	discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
181 	discover_params.type = BT_GATT_DISCOVER_PRIMARY;
182 
183 	err = bt_gatt_discover(g_conn, &discover_params);
184 	if (err != 0) {
185 		FAIL("Discover failed(err %d)\n", err);
186 	}
187 
188 	WAIT_FOR_FLAG(flag_discover_complete);
189 	printk("Discover complete\n");
190 }
191 
update_security(void)192 static void update_security(void)
193 {
194 	int err;
195 
196 	printk("Updating security\n");
197 	err = bt_conn_set_security(g_conn, BT_SECURITY_L2);
198 	if (err != 0) {
199 		FAIL("Set security failed (err %d)\n", err);
200 	}
201 
202 	WAIT_FOR_FLAG(flag_security_changed);
203 	printk("Security changed\n");
204 }
205 
gatt_write_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_write_params * params)206 static void gatt_write_cb(struct bt_conn *conn, uint8_t err, struct bt_gatt_write_params *params)
207 {
208 	(void)memset(params, 0, sizeof(*params));
209 	att_err = err;
210 
211 	SET_FLAG(flag_write_complete);
212 }
213 
gatt_write(uint16_t handle,uint8_t expect_att_err)214 static void gatt_write(uint16_t handle, uint8_t expect_att_err)
215 {
216 	static struct bt_gatt_write_params write_params;
217 	int err;
218 
219 	if (handle == chrc_handle) {
220 		printk("Writing to chrc and expecting 0x%02X\n", expect_att_err);
221 		write_params.data = chrc_data;
222 		write_params.length = sizeof(chrc_data);
223 	} else if (handle == long_chrc_handle) {
224 		printk("Writing to long_chrc and expecting 0x%02X\n", expect_att_err);
225 		write_params.data = long_chrc_data;
226 		write_params.length = sizeof(long_chrc_data);
227 	} else if (handle == enc_chrc_handle) {
228 		printk("Writing to enc_chrc and expecting 0x%02X\n", expect_att_err);
229 		write_params.data = chrc_data;
230 		write_params.length = sizeof(chrc_data);
231 	} else if (handle == lesc_chrc_handle) {
232 		printk("Writing to lesc_chrc and expecting 0x%02X\n", expect_att_err);
233 		write_params.data = chrc_data;
234 		write_params.length = sizeof(chrc_data);
235 	}
236 
237 	write_params.func = gatt_write_cb;
238 	write_params.handle = handle;
239 
240 	UNSET_FLAG(flag_write_complete);
241 
242 	err = bt_gatt_write(g_conn, &write_params);
243 	if (err != 0) {
244 		FAIL("bt_gatt_write failed: %d\n", err);
245 	}
246 
247 	WAIT_FOR_FLAG(flag_write_complete);
248 
249 	if (att_err != expect_att_err) {
250 		FAIL("Write failed: 0x%02X\n", att_err);
251 	}
252 
253 	printk("success\n");
254 }
255 
gatt_read_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * params,const void * data,uint16_t length)256 static uint8_t gatt_read_cb(struct bt_conn *conn, uint8_t err,
257 			    struct bt_gatt_read_params *params,
258 			    const void *data, uint16_t length)
259 {
260 	att_err = err;
261 
262 	if (err != BT_ATT_ERR_SUCCESS) {
263 		printk("Read failed: 0x%02X\n", err);
264 
265 		(void)memset(params, 0, sizeof(*params));
266 		SET_FLAG(flag_read_complete);
267 
268 		return BT_GATT_ITER_STOP;
269 	}
270 
271 	if (data != NULL) {
272 		if (data_received_size + length > sizeof(data_received)) {
273 			FAIL("Invalid amount of data received: %u\n", data_received_size + length);
274 		} else {
275 			memcpy(&data_received[data_received_size], data, length);
276 			data_received_size += length;
277 		}
278 
279 		return BT_GATT_ITER_CONTINUE;
280 	}
281 
282 	if (params->single.handle == chrc_handle) {
283 		if (data_received_size != CHRC_SIZE ||
284 		    memcmp(data_received, chrc_data, data_received_size) != 0) {
285 			FAIL("chrc data different than expected (%u %u)\n", length, CHRC_SIZE);
286 		}
287 	} else if (params->single.handle == long_chrc_handle) {
288 		if (data_received_size != LONG_CHRC_SIZE ||
289 		    memcmp(data_received, long_chrc_data, data_received_size) != 0) {
290 			FAIL("long_chrc data different than expected (%u %u)\n", length,
291 			     LONG_CHRC_SIZE);
292 		}
293 	} else if (params->single.handle == enc_chrc_handle) {
294 		if (data_received_size != CHRC_SIZE ||
295 		    memcmp(data_received, chrc_data, data_received_size) != 0) {
296 			FAIL("enc_chrc data different than expected (%u %u)\n", length, CHRC_SIZE);
297 		}
298 	} else if (params->single.handle == lesc_chrc_handle) {
299 		if (data_received_size != CHRC_SIZE ||
300 		    memcmp(data_received, chrc_data, data_received_size) != 0) {
301 			FAIL("lesc_chrc data different than expected (%u %u)\n", length, CHRC_SIZE);
302 		}
303 	}
304 
305 	(void)memset(params, 0, sizeof(*params));
306 	SET_FLAG(flag_read_complete);
307 
308 	return BT_GATT_ITER_STOP;
309 }
310 
gatt_read(uint16_t handle,uint8_t expect_att_err)311 static void gatt_read(uint16_t handle, uint8_t expect_att_err)
312 {
313 	static struct bt_gatt_read_params read_params;
314 	int err;
315 
316 	data_received_size = 0;
317 	memset(data_received, 0, sizeof(data_received));
318 
319 	if (handle == chrc_handle) {
320 		printk("Reading chrc and expecting 0x%02X\n", expect_att_err);
321 	} else if (handle == long_chrc_handle) {
322 		printk("Reading long_chrc and expecting 0x%02X\n", expect_att_err);
323 	} else if (handle == enc_chrc_handle) {
324 		printk("Reading enc_chrc and expecting 0x%02X\n", expect_att_err);
325 	} else if (handle == lesc_chrc_handle) {
326 		printk("Reading lesc_chrc and expecting 0x%02X\n", expect_att_err);
327 	}
328 
329 	read_params.func = gatt_read_cb;
330 	read_params.handle_count = 1;
331 	read_params.single.handle = handle;
332 	read_params.single.offset = 0;
333 
334 	UNSET_FLAG(flag_read_complete);
335 
336 	err = bt_gatt_read(g_conn, &read_params);
337 	if (err != 0) {
338 		FAIL("bt_gatt_read failed: %d\n", err);
339 	}
340 
341 	WAIT_FOR_FLAG(flag_read_complete);
342 
343 	if (att_err != expect_att_err) {
344 		FAIL("Read failed: 0x%02X\n", att_err);
345 	}
346 
347 	printk("success\n");
348 }
349 
test_main(void)350 static void test_main(void)
351 {
352 	int err;
353 
354 	bt_conn_cb_register(&conn_callbacks);
355 
356 	err = bt_enable(NULL);
357 	if (err != 0) {
358 		FAIL("Bluetooth discover failed (err %d)\n", err);
359 	}
360 
361 	err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found);
362 	if (err != 0) {
363 		FAIL("Scanning failed to start (err %d)\n", err);
364 	}
365 
366 	printk("Scanning successfully started\n");
367 
368 	WAIT_FOR_FLAG(flag_is_connected);
369 
370 	gatt_discover();
371 
372 	/* Write and read a few times to ensure stateless behavior */
373 	for (size_t i = 0; i < 3; i++) {
374 		gatt_write(chrc_handle, BT_ATT_ERR_SUCCESS);
375 		gatt_read(chrc_handle, BT_ATT_ERR_SUCCESS);
376 		gatt_write(long_chrc_handle, BT_ATT_ERR_SUCCESS);
377 		gatt_read(long_chrc_handle, BT_ATT_ERR_SUCCESS);
378 	}
379 
380 	gatt_write(enc_chrc_handle, BT_ATT_ERR_AUTHENTICATION);
381 	gatt_read(enc_chrc_handle, BT_ATT_ERR_AUTHENTICATION);
382 	gatt_write(lesc_chrc_handle, BT_ATT_ERR_AUTHENTICATION);
383 	gatt_read(lesc_chrc_handle, BT_ATT_ERR_AUTHENTICATION);
384 
385 	update_security();
386 
387 	gatt_write(enc_chrc_handle, BT_ATT_ERR_SUCCESS);
388 	gatt_read(enc_chrc_handle, BT_ATT_ERR_SUCCESS);
389 	gatt_write(lesc_chrc_handle, BT_ATT_ERR_SUCCESS);
390 	gatt_read(lesc_chrc_handle, BT_ATT_ERR_SUCCESS);
391 
392 	PASS("GATT client Passed\n");
393 }
394 
395 static const struct bst_test_instance test_vcs[] = {
396 	{
397 		.test_id = "gatt_client",
398 		.test_pre_init_f = test_init,
399 		.test_tick_f = test_tick,
400 		.test_main_f = test_main
401 	},
402 	BSTEST_END_MARKER
403 };
404 
test_gatt_client_install(struct bst_test_list * tests)405 struct bst_test_list *test_gatt_client_install(struct bst_test_list *tests)
406 {
407 	return bst_add_tests(tests, test_vcs);
408 }
409