1 /*
2  * Copyright (c) 2023 Demant A/S
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <errno.h>
7 #include <stdint.h>
8 #include <string.h>
9 
10 #include <zephyr/bluetooth/att.h>
11 #include <zephyr/bluetooth/bluetooth.h>
12 #include <zephyr/bluetooth/conn.h>
13 #include <zephyr/bluetooth/gatt.h>
14 
15 #include "bstests.h"
16 #include "common.h"
17 #include "common/bt_str.h"
18 
19 #include <zephyr/bluetooth/hci_types.h>
20 #include <zephyr/bluetooth/uuid.h>
21 #include <zephyr/logging/log.h>
22 #include <zephyr/logging/log_core.h>
23 #include <zephyr/sys/__assert.h>
24 #include <zephyr/sys/util_macro.h>
25 LOG_MODULE_REGISTER(pacs_notify_client_test, LOG_LEVEL_DBG);
26 
27 struct pacs_instance_t {
28 	uint16_t start_handle;
29 	uint16_t end_handle;
30 
31 	struct bt_gatt_subscribe_params sink_pacs_sub;
32 	struct bt_gatt_subscribe_params source_pacs_sub;
33 	struct bt_gatt_subscribe_params sink_loc_sub;
34 	struct bt_gatt_subscribe_params source_loc_sub;
35 	struct bt_gatt_subscribe_params available_contexts_sub;
36 	struct bt_gatt_subscribe_params supported_contexts_sub;
37 
38 	struct bt_gatt_discover_params discover_params;
39 
40 	int notify_received_mask;
41 };
42 
43 extern enum bst_result_t bst_result;
44 
45 CREATE_FLAG(flag_pacs_snk_discovered);
46 CREATE_FLAG(flag_pacs_src_discovered);
47 CREATE_FLAG(flag_snk_loc_discovered);
48 CREATE_FLAG(flag_src_loc_discovered);
49 CREATE_FLAG(flag_available_contexts_discovered);
50 CREATE_FLAG(flag_supported_contexts_discovered);
51 CREATE_FLAG(flag_all_notifications_received);
52 CREATE_FLAG(flag_available_contexts_received);
53 
54 static struct bt_uuid_16 uuid = BT_UUID_INIT_16(0);
55 
56 static struct pacs_instance_t pacs_instance;
57 
pacs_notify_handler(struct bt_conn * conn,struct bt_gatt_subscribe_params * params,const void * data,uint16_t length)58 static uint8_t pacs_notify_handler(struct bt_conn *conn,
59 				  struct bt_gatt_subscribe_params *params,
60 				  const void *data, uint16_t length)
61 {
62 	LOG_DBG("%p", params);
63 
64 	if (params == &pacs_instance.sink_pacs_sub) {
65 		LOG_DBG("Received sink_pacs_sub notification");
66 		pacs_instance.notify_received_mask |= BIT(0);
67 	} else if (params == &pacs_instance.source_pacs_sub) {
68 		LOG_DBG("Received source_pacs_sub notification");
69 		pacs_instance.notify_received_mask |= BIT(1);
70 	} else if (params == &pacs_instance.sink_loc_sub) {
71 		LOG_DBG("Received sink_loc_sub notification");
72 		pacs_instance.notify_received_mask |= BIT(2);
73 	} else if (params == &pacs_instance.source_loc_sub) {
74 		LOG_DBG("Received source_loc_sub notification");
75 		pacs_instance.notify_received_mask |= BIT(3);
76 	} else if (params == &pacs_instance.available_contexts_sub) {
77 		LOG_DBG("Received available_contexts_sub notification");
78 		pacs_instance.notify_received_mask |= BIT(4);
79 		SET_FLAG(flag_available_contexts_received);
80 	} else if (params == &pacs_instance.supported_contexts_sub) {
81 		LOG_DBG("Received supported_contexts_sub notification");
82 		pacs_instance.notify_received_mask |= BIT(5);
83 	}
84 
85 	LOG_DBG("pacs_instance.notify_received_mask is %d", pacs_instance.notify_received_mask);
86 
87 	if (pacs_instance.notify_received_mask ==
88 	    (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5))) {
89 		pacs_instance.notify_received_mask = 0;
90 		SET_FLAG(flag_all_notifications_received);
91 	}
92 
93 	return BT_GATT_ITER_CONTINUE;
94 }
95 
discover_supported_contexts(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * params)96 static uint8_t discover_supported_contexts(struct bt_conn *conn, const struct bt_gatt_attr *attr,
97 			     struct bt_gatt_discover_params *params)
98 {
99 	struct bt_gatt_subscribe_params *subscribe_params;
100 	int err;
101 
102 	if (!attr) {
103 		LOG_DBG("Discover complete");
104 		(void)memset(params, 0, sizeof(*params));
105 		return BT_GATT_ITER_STOP;
106 	}
107 
108 	if (!bt_uuid_cmp(params->uuid, BT_UUID_PACS_SUPPORTED_CONTEXT)) {
109 		LOG_DBG("PACS Supported Contexts Characteristic handle at %d", attr->handle);
110 		subscribe_params = &pacs_instance.supported_contexts_sub;
111 		memcpy(&uuid, BT_UUID_GATT_CCC, sizeof(uuid));
112 		pacs_instance.discover_params.uuid = &uuid.uuid;
113 		pacs_instance.discover_params.start_handle = attr->handle + 2;
114 		pacs_instance.discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
115 		subscribe_params->value_handle = bt_gatt_attr_value_handle(attr);
116 
117 		err = bt_gatt_discover(conn, &pacs_instance.discover_params);
118 		if (err) {
119 			LOG_DBG("Discover failed (err %d)", err);
120 		}
121 	} else if (!bt_uuid_cmp(params->uuid, BT_UUID_GATT_CCC)) {
122 		LOG_DBG("CCC handle at %d", attr->handle);
123 		subscribe_params = &pacs_instance.supported_contexts_sub;
124 		subscribe_params->notify = pacs_notify_handler;
125 		subscribe_params->value = BT_GATT_CCC_NOTIFY;
126 		subscribe_params->ccc_handle = attr->handle;
127 
128 		err = bt_gatt_subscribe(conn, subscribe_params);
129 		if (err && err != -EALREADY) {
130 			LOG_DBG("Subscribe failed (err %d)", err);
131 		} else {
132 			SET_FLAG(flag_supported_contexts_discovered);
133 			LOG_DBG("[SUBSCRIBED]");
134 		}
135 	} else {
136 		LOG_DBG("Unknown handle at %d", attr->handle);
137 		return BT_GATT_ITER_CONTINUE;
138 	}
139 
140 	return BT_GATT_ITER_STOP;
141 }
142 
discover_and_subscribe_supported_contexts(void)143 static void discover_and_subscribe_supported_contexts(void)
144 {
145 	int err = 0;
146 
147 	LOG_DBG("");
148 
149 	memcpy(&uuid, BT_UUID_PACS_SUPPORTED_CONTEXT, sizeof(uuid));
150 	pacs_instance.discover_params.uuid = &uuid.uuid;
151 	pacs_instance.discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
152 	pacs_instance.discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
153 	pacs_instance.discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
154 	pacs_instance.discover_params.func = discover_supported_contexts;
155 
156 	err = bt_gatt_discover(default_conn, &pacs_instance.discover_params);
157 	if (err != 0) {
158 		FAIL("Service Discovery failed (err %d)", err);
159 		return;
160 	}
161 }
162 
discover_available_contexts(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * params)163 static uint8_t discover_available_contexts(struct bt_conn *conn, const struct bt_gatt_attr *attr,
164 			     struct bt_gatt_discover_params *params)
165 {
166 	struct bt_gatt_subscribe_params *subscribe_params;
167 	int err;
168 
169 	if (!attr) {
170 		LOG_DBG("Discover complete");
171 		(void)memset(params, 0, sizeof(*params));
172 		return BT_GATT_ITER_STOP;
173 	}
174 
175 	if (!bt_uuid_cmp(params->uuid, BT_UUID_PACS_AVAILABLE_CONTEXT)) {
176 		LOG_DBG("PACS Available Contexts Characteristic handle at %d", attr->handle);
177 		subscribe_params = &pacs_instance.available_contexts_sub;
178 		memcpy(&uuid, BT_UUID_GATT_CCC, sizeof(uuid));
179 		pacs_instance.discover_params.uuid = &uuid.uuid;
180 		pacs_instance.discover_params.start_handle = attr->handle + 2;
181 		pacs_instance.discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
182 		subscribe_params->value_handle = bt_gatt_attr_value_handle(attr);
183 
184 		err = bt_gatt_discover(conn, &pacs_instance.discover_params);
185 		if (err) {
186 			LOG_DBG("Discover failed (err %d)", err);
187 		}
188 	} else if (!bt_uuid_cmp(params->uuid, BT_UUID_GATT_CCC)) {
189 		LOG_DBG("CCC handle at %d", attr->handle);
190 		subscribe_params = &pacs_instance.available_contexts_sub;
191 		subscribe_params->notify = pacs_notify_handler;
192 		subscribe_params->value = BT_GATT_CCC_NOTIFY;
193 		subscribe_params->ccc_handle = attr->handle;
194 
195 		err = bt_gatt_subscribe(conn, subscribe_params);
196 		if (err && err != -EALREADY) {
197 			LOG_DBG("Subscribe failed (err %d)", err);
198 		} else {
199 			SET_FLAG(flag_available_contexts_discovered);
200 			LOG_DBG("[SUBSCRIBED]");
201 		}
202 	} else {
203 		LOG_DBG("Unknown handle at %d", attr->handle);
204 		return BT_GATT_ITER_CONTINUE;
205 	}
206 
207 	return BT_GATT_ITER_STOP;
208 }
209 
discover_and_subscribe_available_contexts(void)210 static void discover_and_subscribe_available_contexts(void)
211 {
212 	int err = 0;
213 
214 	LOG_DBG("");
215 
216 	memcpy(&uuid, BT_UUID_PACS_AVAILABLE_CONTEXT, sizeof(uuid));
217 	pacs_instance.discover_params.uuid = &uuid.uuid;
218 	pacs_instance.discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
219 	pacs_instance.discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
220 	pacs_instance.discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
221 	pacs_instance.discover_params.func = discover_available_contexts;
222 
223 	err = bt_gatt_discover(default_conn, &pacs_instance.discover_params);
224 	if (err != 0) {
225 		FAIL("Service Discovery failed (err %d)", err);
226 		return;
227 	}
228 }
229 
discover_src_loc(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * params)230 static uint8_t discover_src_loc(struct bt_conn *conn, const struct bt_gatt_attr *attr,
231 			     struct bt_gatt_discover_params *params)
232 {
233 	struct bt_gatt_subscribe_params *subscribe_params;
234 	int err;
235 
236 	if (!attr) {
237 		LOG_DBG("Discover complete");
238 		(void)memset(params, 0, sizeof(*params));
239 		return BT_GATT_ITER_STOP;
240 	}
241 
242 	if (!bt_uuid_cmp(params->uuid, BT_UUID_PACS_SRC_LOC)) {
243 		LOG_DBG("PACS Source Location Characteristic handle at %d", attr->handle);
244 		subscribe_params = &pacs_instance.source_loc_sub;
245 		memcpy(&uuid, BT_UUID_GATT_CCC, sizeof(uuid));
246 		pacs_instance.discover_params.uuid = &uuid.uuid;
247 		pacs_instance.discover_params.start_handle = attr->handle + 2;
248 		pacs_instance.discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
249 		subscribe_params->value_handle = bt_gatt_attr_value_handle(attr);
250 
251 		err = bt_gatt_discover(conn, &pacs_instance.discover_params);
252 		if (err) {
253 			LOG_DBG("Discover failed (err %d)", err);
254 		}
255 	} else if (!bt_uuid_cmp(params->uuid, BT_UUID_GATT_CCC)) {
256 		LOG_DBG("CCC handle at %d", attr->handle);
257 		subscribe_params = &pacs_instance.source_loc_sub;
258 		subscribe_params->notify = pacs_notify_handler;
259 		subscribe_params->value = BT_GATT_CCC_NOTIFY;
260 		subscribe_params->ccc_handle = attr->handle;
261 
262 		err = bt_gatt_subscribe(conn, subscribe_params);
263 		if (err && err != -EALREADY) {
264 			LOG_DBG("Subscribe failed (err %d)", err);
265 		} else {
266 			SET_FLAG(flag_src_loc_discovered);
267 			LOG_DBG("[SUBSCRIBED]");
268 		}
269 	} else {
270 		LOG_DBG("Unknown handle at %d", attr->handle);
271 		return BT_GATT_ITER_CONTINUE;
272 	}
273 
274 	return BT_GATT_ITER_STOP;
275 }
276 
discover_and_subscribe_src_loc(void)277 static void discover_and_subscribe_src_loc(void)
278 {
279 	int err = 0;
280 
281 	LOG_DBG("");
282 
283 	memcpy(&uuid, BT_UUID_PACS_SRC_LOC, sizeof(uuid));
284 	pacs_instance.discover_params.uuid = &uuid.uuid;
285 	pacs_instance.discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
286 	pacs_instance.discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
287 	pacs_instance.discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
288 	pacs_instance.discover_params.func = discover_src_loc;
289 
290 	err = bt_gatt_discover(default_conn, &pacs_instance.discover_params);
291 	if (err != 0) {
292 		FAIL("Service Discovery failed (err %d)", err);
293 		return;
294 	}
295 }
296 
discover_snk_loc(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * params)297 static uint8_t discover_snk_loc(struct bt_conn *conn, const struct bt_gatt_attr *attr,
298 			     struct bt_gatt_discover_params *params)
299 {
300 	struct bt_gatt_subscribe_params *subscribe_params;
301 	int err;
302 
303 	if (!attr) {
304 		LOG_DBG("Discover complete");
305 		(void)memset(params, 0, sizeof(*params));
306 		return BT_GATT_ITER_STOP;
307 	}
308 
309 	if (!bt_uuid_cmp(params->uuid, BT_UUID_PACS_SNK_LOC)) {
310 		LOG_DBG("PACS Sink Location Characteristic handle at %d", attr->handle);
311 		subscribe_params = &pacs_instance.sink_loc_sub;
312 		memcpy(&uuid, BT_UUID_GATT_CCC, sizeof(uuid));
313 		pacs_instance.discover_params.uuid = &uuid.uuid;
314 		pacs_instance.discover_params.start_handle = attr->handle + 2;
315 		pacs_instance.discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
316 		subscribe_params->value_handle = bt_gatt_attr_value_handle(attr);
317 
318 		err = bt_gatt_discover(conn, &pacs_instance.discover_params);
319 		if (err) {
320 			LOG_DBG("Discover failed (err %d)", err);
321 		}
322 	} else if (!bt_uuid_cmp(params->uuid, BT_UUID_GATT_CCC)) {
323 		LOG_DBG("CCC handle at %d", attr->handle);
324 		subscribe_params = &pacs_instance.sink_loc_sub;
325 		subscribe_params->notify = pacs_notify_handler;
326 		subscribe_params->value = BT_GATT_CCC_NOTIFY;
327 		subscribe_params->ccc_handle = attr->handle;
328 
329 		err = bt_gatt_subscribe(conn, subscribe_params);
330 		if (err && err != -EALREADY) {
331 			LOG_DBG("Subscribe failed (err %d)", err);
332 		} else {
333 			SET_FLAG(flag_snk_loc_discovered);
334 			LOG_DBG("[SUBSCRIBED]");
335 		}
336 	} else {
337 		LOG_DBG("Unknown handle at %d", attr->handle);
338 		return BT_GATT_ITER_CONTINUE;
339 	}
340 
341 	return BT_GATT_ITER_STOP;
342 }
343 
discover_and_subscribe_snk_loc(void)344 static void discover_and_subscribe_snk_loc(void)
345 {
346 	int err = 0;
347 
348 	LOG_DBG("");
349 
350 	memcpy(&uuid, BT_UUID_PACS_SNK_LOC, sizeof(uuid));
351 	pacs_instance.discover_params.uuid = &uuid.uuid;
352 	pacs_instance.discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
353 	pacs_instance.discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
354 	pacs_instance.discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
355 	pacs_instance.discover_params.func = discover_snk_loc;
356 
357 	err = bt_gatt_discover(default_conn, &pacs_instance.discover_params);
358 	if (err != 0) {
359 		FAIL("Service Discovery failed (err %d)", err);
360 		return;
361 	}
362 }
363 
discover_pacs_src(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * params)364 static uint8_t discover_pacs_src(struct bt_conn *conn, const struct bt_gatt_attr *attr,
365 			     struct bt_gatt_discover_params *params)
366 {
367 	struct bt_gatt_subscribe_params *subscribe_params;
368 	int err;
369 
370 	if (!attr) {
371 		LOG_DBG("Discover complete");
372 		(void)memset(params, 0, sizeof(*params));
373 		return BT_GATT_ITER_STOP;
374 	}
375 
376 	if (!bt_uuid_cmp(params->uuid, BT_UUID_PACS_SRC)) {
377 		LOG_DBG("PACS Source Characteristic handle at %d", attr->handle);
378 		subscribe_params = &pacs_instance.source_pacs_sub;
379 		memcpy(&uuid, BT_UUID_GATT_CCC, sizeof(uuid));
380 		pacs_instance.discover_params.uuid = &uuid.uuid;
381 		pacs_instance.discover_params.start_handle = attr->handle + 2;
382 		pacs_instance.discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
383 		subscribe_params->value_handle = bt_gatt_attr_value_handle(attr);
384 
385 		err = bt_gatt_discover(conn, &pacs_instance.discover_params);
386 		if (err) {
387 			LOG_DBG("Discover failed (err %d)", err);
388 		}
389 	} else if (!bt_uuid_cmp(params->uuid, BT_UUID_GATT_CCC)) {
390 		LOG_DBG("CCC handle at %d", attr->handle);
391 		subscribe_params = &pacs_instance.source_pacs_sub;
392 		subscribe_params->notify = pacs_notify_handler;
393 		subscribe_params->value = BT_GATT_CCC_NOTIFY;
394 		subscribe_params->ccc_handle = attr->handle;
395 
396 		err = bt_gatt_subscribe(conn, subscribe_params);
397 		if (err && err != -EALREADY) {
398 			LOG_DBG("Subscribe failed (err %d)", err);
399 		} else {
400 			SET_FLAG(flag_pacs_src_discovered);
401 			LOG_DBG("[SUBSCRIBED]");
402 		}
403 	} else {
404 		LOG_DBG("Unknown handle at %d", attr->handle);
405 		return BT_GATT_ITER_CONTINUE;
406 	}
407 
408 	return BT_GATT_ITER_STOP;
409 }
410 
discover_and_subscribe_src_pacs(void)411 static void discover_and_subscribe_src_pacs(void)
412 {
413 	int err = 0;
414 
415 	LOG_DBG("");
416 
417 	memcpy(&uuid, BT_UUID_PACS_SRC, sizeof(uuid));
418 	pacs_instance.discover_params.uuid = &uuid.uuid;
419 	pacs_instance.discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
420 	pacs_instance.discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
421 	pacs_instance.discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
422 	pacs_instance.discover_params.func = discover_pacs_src;
423 
424 	err = bt_gatt_discover(default_conn, &pacs_instance.discover_params);
425 	if (err != 0) {
426 		FAIL("Service Discovery failed (err %d)", err);
427 		return;
428 	}
429 }
430 
discover_pacs_snk(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * params)431 static uint8_t discover_pacs_snk(struct bt_conn *conn, const struct bt_gatt_attr *attr,
432 			     struct bt_gatt_discover_params *params)
433 {
434 	struct bt_gatt_subscribe_params *subscribe_params;
435 	int err;
436 
437 	if (!attr) {
438 		LOG_DBG("Discover complete");
439 		(void)memset(params, 0, sizeof(*params));
440 		return BT_GATT_ITER_STOP;
441 	}
442 
443 	if (!bt_uuid_cmp(params->uuid, BT_UUID_PACS_SNK)) {
444 		LOG_DBG("PACS Sink Characteristic handle at %d", attr->handle);
445 		subscribe_params = &pacs_instance.sink_pacs_sub;
446 		memcpy(&uuid, BT_UUID_GATT_CCC, sizeof(uuid));
447 		pacs_instance.discover_params.uuid = &uuid.uuid;
448 		pacs_instance.discover_params.start_handle = attr->handle + 2;
449 		pacs_instance.discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
450 		subscribe_params->value_handle = bt_gatt_attr_value_handle(attr);
451 
452 		err = bt_gatt_discover(conn, &pacs_instance.discover_params);
453 		if (err) {
454 			LOG_DBG("Discover failed (err %d)", err);
455 		}
456 	} else if (!bt_uuid_cmp(params->uuid, BT_UUID_GATT_CCC)) {
457 		LOG_DBG("CCC handle at %d", attr->handle);
458 		subscribe_params = &pacs_instance.sink_pacs_sub;
459 		subscribe_params->notify = pacs_notify_handler;
460 		subscribe_params->value = BT_GATT_CCC_NOTIFY;
461 		subscribe_params->ccc_handle = attr->handle;
462 
463 		err = bt_gatt_subscribe(conn, subscribe_params);
464 		if (err && err != -EALREADY) {
465 			LOG_DBG("Subscribe failed (err %d)", err);
466 		} else {
467 			SET_FLAG(flag_pacs_snk_discovered);
468 			LOG_DBG("[SUBSCRIBED]");
469 		}
470 	} else {
471 		LOG_DBG("Unknown handle at %d", attr->handle);
472 		return BT_GATT_ITER_CONTINUE;
473 	}
474 
475 	return BT_GATT_ITER_STOP;
476 }
477 
discover_and_subscribe_snk_pacs(void)478 static void discover_and_subscribe_snk_pacs(void)
479 {
480 	int err = 0;
481 
482 	LOG_DBG("");
483 
484 	memcpy(&uuid, BT_UUID_PACS_SNK, sizeof(uuid));
485 	pacs_instance.discover_params.uuid = &uuid.uuid;
486 	pacs_instance.discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
487 	pacs_instance.discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
488 	pacs_instance.discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
489 	pacs_instance.discover_params.func = discover_pacs_snk;
490 
491 	err = bt_gatt_discover(default_conn, &pacs_instance.discover_params);
492 	if (err != 0) {
493 		FAIL("Service Discovery failed (err %d)", err);
494 		return;
495 	}
496 }
497 
test_main(void)498 static void test_main(void)
499 {
500 	int err;
501 
502 	LOG_DBG("Enabling Bluetooth");
503 	err = bt_enable(NULL);
504 	if (err != 0) {
505 		FAIL("Bluetooth enable failed (err %d)", err);
506 		return;
507 	}
508 
509 	bt_le_scan_cb_register(&common_scan_cb);
510 
511 	LOG_DBG("Starting scan");
512 	err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL);
513 	if (err != 0) {
514 		FAIL("Could not start scanning (err %d)", err);
515 		return;
516 	}
517 
518 	WAIT_FOR_FLAG(flag_connected);
519 
520 	LOG_DBG("Raising security");
521 	err = bt_conn_set_security(default_conn, BT_SECURITY_L2);
522 	if (err) {
523 		FAIL("Failed to ser security level %d (err %d)", BT_SECURITY_L2, err);
524 		return;
525 	}
526 
527 	LOG_DBG("Starting Discovery");
528 
529 	discover_and_subscribe_snk_pacs();
530 	WAIT_FOR_FLAG(flag_pacs_snk_discovered);
531 
532 	discover_and_subscribe_snk_loc();
533 	WAIT_FOR_FLAG(flag_snk_loc_discovered);
534 
535 	discover_and_subscribe_src_pacs();
536 	WAIT_FOR_FLAG(flag_pacs_src_discovered);
537 
538 	discover_and_subscribe_src_loc();
539 	WAIT_FOR_FLAG(flag_src_loc_discovered);
540 
541 	discover_and_subscribe_available_contexts();
542 	WAIT_FOR_FLAG(flag_available_contexts_discovered);
543 
544 	discover_and_subscribe_supported_contexts();
545 	WAIT_FOR_FLAG(flag_supported_contexts_discovered);
546 
547 	LOG_DBG("Waiting for all notifications to be received");
548 
549 	WAIT_FOR_FLAG(flag_all_notifications_received);
550 
551 	/* Disconnect and wait for server to advertise again (after notifications are triggered) */
552 	UNSET_FLAG(flag_all_notifications_received);
553 	err = bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
554 	__ASSERT_NO_MSG(err == 0);
555 	WAIT_FOR_UNSET_FLAG(flag_connected);
556 
557 	LOG_DBG("Starting scan");
558 	err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL);
559 	if (err != 0) {
560 		FAIL("Could not start scanning (err %d)", err);
561 		return;
562 	}
563 
564 	WAIT_FOR_FLAG(flag_connected);
565 
566 	LOG_DBG("Raising security");
567 	err = bt_conn_set_security(default_conn, BT_SECURITY_L2);
568 	if (err) {
569 		FAIL("Failed to ser security level %d (err %d)", BT_SECURITY_L2, err);
570 		return;
571 	}
572 
573 	LOG_DBG("Waiting for all notifications to be received");
574 	WAIT_FOR_FLAG(flag_all_notifications_received);
575 
576 	err = bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
577 	__ASSERT_NO_MSG(err == 0);
578 	WAIT_FOR_UNSET_FLAG(flag_connected);
579 	UNSET_FLAG(flag_available_contexts_received);
580 
581 	LOG_DBG("Starting scan");
582 	err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL);
583 	if (err != 0) {
584 		FAIL("Could not start scanning (err %d)", err);
585 		return;
586 	}
587 
588 	WAIT_FOR_FLAG(flag_connected);
589 
590 	LOG_DBG("Raising security");
591 	err = bt_conn_set_security(default_conn, BT_SECURITY_L2);
592 	if (err) {
593 		FAIL("Failed to ser security level %d (err %d)", BT_SECURITY_L2, err);
594 		return;
595 	}
596 
597 	LOG_DBG("Waiting for available contexts notification to be received");
598 	WAIT_FOR_FLAG(flag_available_contexts_received);
599 
600 	err = bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
601 	__ASSERT_NO_MSG(err == 0);
602 	WAIT_FOR_UNSET_FLAG(flag_connected);
603 	UNSET_FLAG(flag_available_contexts_received);
604 
605 	LOG_DBG("Starting scan");
606 	err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL);
607 	if (err != 0) {
608 		FAIL("Could not start scanning (err %d)", err);
609 		return;
610 	}
611 
612 	WAIT_FOR_FLAG(flag_connected);
613 
614 	LOG_DBG("Raising security");
615 	err = bt_conn_set_security(default_conn, BT_SECURITY_L2);
616 	if (err) {
617 		FAIL("Failed to ser security level %d (err %d)", BT_SECURITY_L2, err);
618 		return;
619 	}
620 
621 	LOG_DBG("Waiting for available contexts notification to be received");
622 	WAIT_FOR_FLAG(flag_available_contexts_received);
623 
624 	err = bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
625 	__ASSERT_NO_MSG(err == 0);
626 	WAIT_FOR_UNSET_FLAG(flag_connected);
627 
628 	PASS("GATT client Passed\n");
629 }
630 
631 static const struct bst_test_instance test_pacs_notify_client[] = {
632 	{
633 		.test_id = "pacs_notify_client",
634 		.test_pre_init_f = test_init,
635 		.test_tick_f = test_tick,
636 		.test_main_f = test_main,
637 	},
638 	BSTEST_END_MARKER,
639 };
640 
test_pacs_notify_client_install(struct bst_test_list * tests)641 struct bst_test_list *test_pacs_notify_client_install(struct bst_test_list *tests)
642 {
643 	return bst_add_tests(tests, test_pacs_notify_client);
644 }
645