1 /* Copyright (c) 2023 Nordic Semiconductor ASA
2  * SPDX-License-Identifier: Apache-2.0
3  */
4 
5 #include <argparse.h>
6 #include <zephyr/bluetooth/gatt.h>
7 #include <zephyr/logging/log.h>
8 #include <zephyr/sys/__assert.h>
9 #include <zephyr/settings/settings.h>
10 #include <zephyr/sys/byteorder.h>
11 #include <zephyr/bluetooth/bluetooth.h>
12 
13 #include "testlib/adv.h"
14 #include "testlib/att_read.h"
15 #include "testlib/att_write.h"
16 #include "bs_macro.h"
17 #include "bs_sync.h"
18 #include <testlib/conn.h>
19 #include "testlib/log_utils.h"
20 #include "testlib/scan.h"
21 #include "testlib/security.h"
22 
23 /* This test uses system asserts to fail tests. */
24 BUILD_ASSERT(__ASSERT_ON);
25 
26 #define CENTRAL_DEVICE_NBR    0
27 #define PERIPHERAL_DEVICE_NBR 1
28 
29 LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG);
30 
31 #define UUID_1                                                                                     \
32 	BT_UUID_DECLARE_128(0xdb, 0x1f, 0xe2, 0x52, 0xf3, 0xc6, 0x43, 0x66, 0xb3, 0x92, 0x5d,      \
33 			    0xc6, 0xe7, 0xc9, 0x59, 0x9d)
34 
35 #define UUID_2                                                                                     \
36 	BT_UUID_DECLARE_128(0x3f, 0xa4, 0x7f, 0x44, 0x2e, 0x2a, 0x43, 0x05, 0xab, 0x38, 0x07,      \
37 			    0x8d, 0x16, 0xbf, 0x99, 0xf1)
38 
read_mtu_validation_chrc(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t buf_len,uint16_t offset)39 static ssize_t read_mtu_validation_chrc(struct bt_conn *conn, const struct bt_gatt_attr *attr,
40 					void *buf, uint16_t buf_len, uint16_t offset)
41 {
42 	ssize_t read_len;
43 
44 	LOG_INF("Server side buf_len %u", buf_len);
45 
46 	/* Note: We assume `buf_len` is equal to the usable payload
47 	 * capacity of the response PDU. I.e. `(ATT_MTU - 1)` for
48 	 * BT_ATT_OP_READ_RSP and BT_ATT_OP_READ_BLOB_RSP.
49 	 */
50 
51 	/* Send back a full PDU on the first read (on offset 0). Then an
52 	 * not full one for the second read to conlude the long read..
53 	 */
54 	read_len = buf_len;
55 	if (offset > 0) {
56 		__ASSERT_NO_MSG(read_len > 0);
57 		/* The second PDU is one-less-than-full to test for off
58 		 * by one errors.
59 		 */
60 		read_len -= 1;
61 	}
62 
63 	/* If the ATT_MTU is too large, sending a one-less-than-full
64 	 * response would exeed the max attribute length limit.
65 	 */
66 	__ASSERT(buf_len < (BT_ATT_MAX_ATTRIBUTE_LEN / 2),
67 		 "The EATT buffer is too large for this test.");
68 
69 	/* Ensure the padding bytes (that are not overwritten later in
70 	 * this function) are initialized.
71 	 */
72 	memset(buf, 0, read_len);
73 
74 	/* Echo back the requested read size in the first two bytes of
75 	 * each read.
76 	 */
77 	__ASSERT_NO_MSG(read_len >= 2);
78 	sys_put_le16(read_len, buf);
79 
80 	return read_len;
81 }
82 
83 static struct bt_gatt_attr attrs[] = {
84 	BT_GATT_PRIMARY_SERVICE(UUID_1),
85 	BT_GATT_CHARACTERISTIC(UUID_2, BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
86 			       read_mtu_validation_chrc, NULL, NULL),
87 };
88 
89 static struct bt_gatt_service svc = {
90 	.attrs = attrs,
91 	.attr_count = ARRAY_SIZE(attrs),
92 };
93 
find_the_chrc(struct bt_conn * conn,uint16_t * chrc_value_handle)94 static void find_the_chrc(struct bt_conn *conn, uint16_t *chrc_value_handle)
95 {
96 	uint16_t svc_handle;
97 	uint16_t svc_end_handle;
98 	uint16_t chrc_end_handle;
99 
100 	EXPECT_ZERO(bt_testlib_gatt_discover_primary(&svc_handle, &svc_end_handle, conn, UUID_1, 1,
101 						     0xffff));
102 
103 	LOG_INF("svc_handle: %u, svc_end_handle: %u", svc_handle, svc_end_handle);
104 
105 	EXPECT_ZERO(bt_testlib_gatt_discover_characteristic(chrc_value_handle, &chrc_end_handle,
106 							    NULL, conn, UUID_2, (svc_handle + 1),
107 							    svc_end_handle));
108 
109 	LOG_INF("chrc_value_handle: %u, chrc_end_handle: %u", *chrc_value_handle, chrc_end_handle);
110 }
111 
bs_sync_all_log(char * log_msg)112 static void bs_sync_all_log(char *log_msg)
113 {
114 	/* Everyone meets here. */
115 	bt_testlib_bs_sync_all();
116 
117 	if (get_device_nbr() == 0) {
118 		LOG_WRN("Sync point: %s", log_msg);
119 	}
120 
121 	/* Everyone waits for d0 to finish logging. */
122 	bt_testlib_bs_sync_all();
123 }
124 
bt_enable_quiet(void)125 static inline void bt_enable_quiet(void)
126 {
127 	bt_testlib_log_level_set("bt_hci_core", LOG_LEVEL_ERR);
128 	bt_testlib_log_level_set("bt_id", LOG_LEVEL_ERR);
129 
130 	EXPECT_ZERO(bt_enable(NULL));
131 
132 	bt_testlib_log_level_set("bt_hci_core", LOG_LEVEL_INF);
133 	bt_testlib_log_level_set("bt_id", LOG_LEVEL_INF);
134 }
135 
test_long_read(enum bt_att_chan_opt bearer,uint16_t chrc_value_handle,struct bt_conn * conn)136 static void test_long_read(enum bt_att_chan_opt bearer, uint16_t chrc_value_handle,
137 			   struct bt_conn *conn)
138 {
139 	bool central = (get_device_nbr() == CENTRAL_DEVICE_NBR);
140 
141 	if (central) {
142 		size_t read_count;
143 
144 		NET_BUF_SIMPLE_DEFINE(attr_value_buf, BT_ATT_MAX_ATTRIBUTE_LEN);
145 
146 		/* Perform the whole long read operation. */
147 		EXPECT_ZERO(bt_testlib_gatt_long_read(&attr_value_buf, NULL, NULL, conn, bearer,
148 						      chrc_value_handle, 0));
149 
150 		/* Parse the read attribute value to verify the
151 		 * integrity of the transfer.
152 		 *
153 		 * Each response starts with the length of the whole
154 		 * response and the rest is zero-padded.
155 		 */
156 		for (read_count = 0; attr_value_buf.len; read_count++) {
157 			uint16_t encoded_len;
158 			uint16_t padding_size;
159 
160 			LOG_INF("Verifying read %u", read_count);
161 
162 			__ASSERT(attr_value_buf.len >= sizeof(encoded_len),
163 				 "Incomplete encoded length");
164 			encoded_len = net_buf_simple_pull_le16(&attr_value_buf);
165 
166 			padding_size = (encoded_len - sizeof(uint16_t));
167 			LOG_INF("Padding size %u", padding_size);
168 
169 			/* Check and discard padding. */
170 			for (uint16_t i = 0; i < padding_size; i++) {
171 				__ASSERT(attr_value_buf.len, "Unexpected end of buffer");
172 				__ASSERT(net_buf_simple_pull_u8(&attr_value_buf) == 0,
173 					 "Expected a padding byte at %u", i);
174 			}
175 		}
176 		LOG_INF("Verified %u reads", read_count);
177 		__ASSERT(read_count > 1, "Expected at least two reads");
178 	}
179 }
180 
the_test(void)181 void the_test(void)
182 {
183 	bool central = (get_device_nbr() == CENTRAL_DEVICE_NBR);
184 	bool peripheral = (get_device_nbr() == PERIPHERAL_DEVICE_NBR);
185 	bt_addr_le_t adva;
186 	struct bt_conn *conn = NULL;
187 	uint16_t chrc_value_handle = 0;
188 
189 	if (peripheral) {
190 		EXPECT_ZERO(bt_gatt_service_register(&svc));
191 	}
192 
193 	bt_enable_quiet();
194 
195 	if (peripheral) {
196 		EXPECT_ZERO(bt_set_name("peripheral"));
197 		EXPECT_ZERO(bt_testlib_adv_conn(&conn, BT_ID_DEFAULT, bt_get_name()));
198 	}
199 
200 	if (central) {
201 		EXPECT_ZERO(bt_testlib_scan_find_name(&adva, "peripheral"));
202 		EXPECT_ZERO(bt_testlib_connect(&adva, &conn));
203 
204 		/* Establish EATT bearers. */
205 		EXPECT_ZERO(bt_testlib_secure(conn, BT_SECURITY_L2));
206 
207 		while (bt_eatt_count(conn) == 0) {
208 			k_msleep(100);
209 		};
210 	}
211 
212 	bs_sync_all_log("Connected");
213 
214 	/* Perform discovery. */
215 	if (central) {
216 		find_the_chrc(conn, &chrc_value_handle);
217 	}
218 
219 	bs_sync_all_log("Testing UATT");
220 	test_long_read(BT_ATT_CHAN_OPT_UNENHANCED_ONLY, chrc_value_handle, conn);
221 
222 	bs_sync_all_log("Testing EATT");
223 	test_long_read(BT_ATT_CHAN_OPT_ENHANCED_ONLY, chrc_value_handle, conn);
224 
225 	bs_sync_all_log("Test Complete");
226 
227 	PASS("Test complete\n");
228 }
229