1 /* main.c - Application main entry point */
2 
3 /*
4  * Copyright (c) 2019 Intel Corporation
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <zephyr/kernel.h>
10 #include <stddef.h>
11 #include <zephyr/ztest.h>
12 
13 #include <zephyr/bluetooth/buf.h>
14 #include <zephyr/bluetooth/bluetooth.h>
15 #include <zephyr/bluetooth/gatt.h>
16 
17 /* Custom Service Variables */
18 static struct bt_uuid_128 test_uuid = BT_UUID_INIT_128(
19 	0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
20 	0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
21 static struct bt_uuid_128 test_chrc_uuid = BT_UUID_INIT_128(
22 	0xf2, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
23 	0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
24 
25 static uint8_t test_value[] = { 'T', 'e', 's', 't', '\0' };
26 
27 static struct bt_uuid_128 test1_uuid = BT_UUID_INIT_128(
28 	0xf4, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
29 	0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
30 
31 static const struct bt_uuid_128 test1_nfy_uuid = BT_UUID_INIT_128(
32 	0xf5, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
33 	0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
34 
35 static uint8_t nfy_enabled;
36 
test1_ccc_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)37 static void test1_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
38 {
39 	nfy_enabled = (value == BT_GATT_CCC_NOTIFY) ? 1 : 0;
40 }
41 
read_test(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)42 static ssize_t read_test(struct bt_conn *conn, const struct bt_gatt_attr *attr,
43 			void *buf, uint16_t len, uint16_t offset)
44 {
45 	const char *value = attr->user_data;
46 
47 	return bt_gatt_attr_read(conn, attr, buf, len, offset, value,
48 				 strlen(value));
49 }
50 
write_test(struct bt_conn * conn,const struct bt_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags)51 static ssize_t write_test(struct bt_conn *conn, const struct bt_gatt_attr *attr,
52 			 const void *buf, uint16_t len, uint16_t offset,
53 			 uint8_t flags)
54 {
55 	uint8_t *value = attr->user_data;
56 
57 	if (offset + len > sizeof(test_value)) {
58 		return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
59 	}
60 
61 	memcpy(value + offset, buf, len);
62 
63 	return len;
64 }
65 
66 static struct bt_gatt_attr test_attrs[] = {
67 	/* Vendor Primary Service Declaration */
68 	BT_GATT_PRIMARY_SERVICE(&test_uuid),
69 
70 	BT_GATT_CHARACTERISTIC(&test_chrc_uuid.uuid,
71 			       BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
72 			       BT_GATT_PERM_READ_AUTHEN |
73 			       BT_GATT_PERM_WRITE_AUTHEN,
74 			       read_test, write_test, test_value),
75 };
76 
77 static struct bt_gatt_service test_svc = BT_GATT_SERVICE(test_attrs);
78 
79 static struct bt_gatt_attr test1_attrs[] = {
80 	/* Vendor Primary Service Declaration */
81 	BT_GATT_PRIMARY_SERVICE(&test1_uuid),
82 
83 	BT_GATT_CHARACTERISTIC(&test1_nfy_uuid.uuid,
84 			       BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_NONE,
85 			       NULL, NULL, &nfy_enabled),
86 	BT_GATT_CCC(test1_ccc_cfg_changed,
87 		    BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
88 };
89 
90 static struct bt_gatt_service test1_svc = BT_GATT_SERVICE(test1_attrs);
91 
92 ZTEST_SUITE(test_gatt, NULL, NULL, NULL, NULL, NULL);
93 
ZTEST(test_gatt,test_gatt_register)94 ZTEST(test_gatt, test_gatt_register)
95 {
96 	/* Ensure our test services are not already registered */
97 	bt_gatt_service_unregister(&test_svc);
98 	bt_gatt_service_unregister(&test1_svc);
99 
100 	/* Attempt to register services */
101 	zassert_false(bt_gatt_service_register(&test_svc),
102 		     "Test service registration failed");
103 	zassert_false(bt_gatt_service_register(&test1_svc),
104 		     "Test service1 registration failed");
105 
106 	/* Attempt to register already registered services */
107 	zassert_true(bt_gatt_service_register(&test_svc),
108 		     "Test service duplicate succeeded");
109 	zassert_true(bt_gatt_service_register(&test1_svc),
110 		     "Test service1 duplicate succeeded");
111 }
112 
ZTEST(test_gatt,test_gatt_unregister)113 ZTEST(test_gatt, test_gatt_unregister)
114 {
115 	/* Attempt to unregister last */
116 	zassert_false(bt_gatt_service_unregister(&test1_svc),
117 		     "Test service1 unregister failed");
118 	zassert_false(bt_gatt_service_register(&test1_svc),
119 		     "Test service1 re-registration failed");
120 
121 	/* Attempt to unregister first/middle */
122 	zassert_false(bt_gatt_service_unregister(&test_svc),
123 		     "Test service unregister failed");
124 	zassert_false(bt_gatt_service_register(&test_svc),
125 		     "Test service re-registration failed");
126 
127 	/* Attempt to unregister all reverse order */
128 	zassert_false(bt_gatt_service_unregister(&test1_svc),
129 		     "Test service1 unregister failed");
130 	zassert_false(bt_gatt_service_unregister(&test_svc),
131 		     "Test service unregister failed");
132 
133 	zassert_false(bt_gatt_service_register(&test_svc),
134 		     "Test service registration failed");
135 	zassert_false(bt_gatt_service_register(&test1_svc),
136 		     "Test service1 registration failed");
137 
138 	/* Attempt to unregister all same order */
139 	zassert_false(bt_gatt_service_unregister(&test_svc),
140 		     "Test service1 unregister failed");
141 	zassert_false(bt_gatt_service_unregister(&test1_svc),
142 		     "Test service unregister failed");
143 }
144 
count_attr(const struct bt_gatt_attr * attr,uint16_t handle,void * user_data)145 static uint8_t count_attr(const struct bt_gatt_attr *attr, uint16_t handle,
146 			  void *user_data)
147 {
148 	uint16_t *count = user_data;
149 
150 	(*count)++;
151 
152 	return BT_GATT_ITER_CONTINUE;
153 }
154 
find_attr(const struct bt_gatt_attr * attr,uint16_t handle,void * user_data)155 static uint8_t find_attr(const struct bt_gatt_attr *attr, uint16_t handle,
156 			 void *user_data)
157 {
158 	const struct bt_gatt_attr **tmp = user_data;
159 
160 	*tmp = attr;
161 
162 	return BT_GATT_ITER_CONTINUE;
163 }
164 
ZTEST(test_gatt,test_gatt_foreach)165 ZTEST(test_gatt, test_gatt_foreach)
166 {
167 	const struct bt_gatt_attr *attr;
168 	uint16_t num = 0;
169 
170 	/* Attempt to register services */
171 	zassert_false(bt_gatt_service_register(&test_svc),
172 		     "Test service registration failed");
173 	zassert_false(bt_gatt_service_register(&test1_svc),
174 		     "Test service1 registration failed");
175 
176 	/* Iterate attributes */
177 	bt_gatt_foreach_attr(test_attrs[0].handle, 0xffff, count_attr, &num);
178 	zassert_equal(num, 7, "Number of attributes don't match");
179 
180 	/* Iterate 1 attribute */
181 	num = 0;
182 	bt_gatt_foreach_attr_type(test_attrs[0].handle, 0xffff, NULL, NULL, 1,
183 				  count_attr, &num);
184 	zassert_equal(num, 1, "Number of attributes don't match");
185 
186 	/* Find attribute by UUID */
187 	attr = NULL;
188 	bt_gatt_foreach_attr_type(test_attrs[0].handle, 0xffff,
189 				  &test_chrc_uuid.uuid, NULL, 0, find_attr,
190 				  &attr);
191 	zassert_not_null(attr, "Attribute don't match");
192 	if (attr) {
193 		zassert_equal(attr->uuid, &test_chrc_uuid.uuid,
194 			      "Attribute UUID don't match");
195 	}
196 
197 	/* Find attribute by DATA */
198 	attr = NULL;
199 	bt_gatt_foreach_attr_type(test_attrs[0].handle, 0xffff, NULL,
200 				  test_value, 0, find_attr, &attr);
201 	zassert_not_null(attr, "Attribute don't match");
202 	if (attr) {
203 		zassert_equal(attr->user_data, test_value,
204 			      "Attribute value don't match");
205 	}
206 
207 	/* Find all characteristics */
208 	num = 0;
209 	bt_gatt_foreach_attr_type(test_attrs[0].handle, 0xffff,
210 				  BT_UUID_GATT_CHRC, NULL, 0, count_attr, &num);
211 	zassert_equal(num, 2, "Number of attributes don't match");
212 
213 	/* Find 1 characteristic */
214 	attr = NULL;
215 	bt_gatt_foreach_attr_type(test_attrs[0].handle, 0xffff,
216 				  BT_UUID_GATT_CHRC, NULL, 1, find_attr, &attr);
217 	zassert_not_null(attr, "Attribute don't match");
218 
219 	/* Find attribute by UUID and DATA */
220 	attr = NULL;
221 	bt_gatt_foreach_attr_type(test_attrs[0].handle, 0xffff,
222 				  &test1_nfy_uuid.uuid, &nfy_enabled, 1,
223 				  find_attr, &attr);
224 	zassert_not_null(attr, "Attribute don't match");
225 	if (attr) {
226 		zassert_equal(attr->uuid, &test1_nfy_uuid.uuid,
227 			      "Attribute UUID don't match");
228 		zassert_equal(attr->user_data, &nfy_enabled,
229 			      "Attribute value don't match");
230 	}
231 }
232 
ZTEST(test_gatt,test_gatt_read)233 ZTEST(test_gatt, test_gatt_read)
234 {
235 	const struct bt_gatt_attr *attr;
236 	uint8_t buf[256];
237 	ssize_t ret;
238 
239 	/* Find attribute by UUID */
240 	attr = NULL;
241 	bt_gatt_foreach_attr_type(test_attrs[0].handle, 0xffff,
242 				  &test_chrc_uuid.uuid, NULL, 0, find_attr,
243 				  &attr);
244 	zassert_not_null(attr, "Attribute don't match");
245 	zassert_equal(attr->uuid, &test_chrc_uuid.uuid,
246 			      "Attribute UUID don't match");
247 
248 	ret = attr->read(NULL, attr, (void *)buf, sizeof(buf), 0);
249 	zassert_equal(ret, strlen(test_value),
250 		      "Attribute read unexpected return");
251 	zassert_mem_equal(buf, test_value, ret,
252 			  "Attribute read value don't match");
253 }
254 
ZTEST(test_gatt,test_gatt_write)255 ZTEST(test_gatt, test_gatt_write)
256 {
257 	const struct bt_gatt_attr *attr;
258 	char *value = "    ";
259 	ssize_t ret;
260 
261 	/* Need our service to be registered */
262 	zassert_false(bt_gatt_service_register(&test_svc),
263 		     "Test service registration failed");
264 
265 	/* Find attribute by UUID */
266 	attr = NULL;
267 	bt_gatt_foreach_attr_type(test_attrs[0].handle, 0xffff,
268 				  &test_chrc_uuid.uuid, NULL, 0, find_attr,
269 				  &attr);
270 	zassert_not_null(attr, "Attribute don't match");
271 
272 	ret = attr->write(NULL, attr, (void *)value, strlen(value), 0, 0);
273 	zassert_equal(ret, strlen(value), "Attribute write unexpected return");
274 	zassert_mem_equal(value, test_value, ret,
275 			  "Attribute write value don't match");
276 }
277