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