1 /*
2  * Copyright (c) 2023 Demant A/S
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdbool.h>
8 #include <stddef.h>
9 
10 #include <zephyr/bluetooth/audio/cap.h>
11 #include <zephyr/bluetooth/audio/csip.h>
12 #include <zephyr/bluetooth/bluetooth.h>
13 #include <zephyr/bluetooth/conn.h>
14 #include <zephyr/bluetooth/gap.h>
15 #include <zephyr/bluetooth/gatt.h>
16 #include <zephyr/bluetooth/uuid.h>
17 #include <zephyr/kernel.h>
18 #include <zephyr/sys/printk.h>
19 #include <zephyr/sys/util.h>
20 
21 #include "bstests.h"
22 #include "common.h"
23 
24 extern enum bst_result_t bst_result;
25 
26 static struct bt_csip_set_member_svc_inst *svc_inst;
27 
is_peer_subscribed(struct bt_conn * conn)28 static bool is_peer_subscribed(struct bt_conn *conn)
29 {
30 	struct bt_gatt_attr *attr;
31 
32 	attr = bt_gatt_find_by_uuid(NULL, 0, BT_UUID_CSIS_SET_LOCK);
33 	if (!attr) {
34 		printk("No BT_UUID_PACS_SNK attribute found\n");
35 		return false;
36 	}
37 
38 	return bt_gatt_is_subscribed(conn, attr, BT_GATT_CCC_NOTIFY);
39 }
40 
csip_set_member_lock_changed_cb(struct bt_conn * conn,struct bt_csip_set_member_svc_inst * svc_inst,bool locked)41 static void csip_set_member_lock_changed_cb(struct bt_conn *conn,
42 					    struct bt_csip_set_member_svc_inst *svc_inst,
43 					    bool locked)
44 {
45 	printk("Client %p %s the lock\n", conn, locked ? "locked" : "released");
46 }
47 
48 static struct bt_csip_set_member_cb csip_cb = {
49 	.lock_changed  = csip_set_member_lock_changed_cb,
50 };
51 
test_main(void)52 static void test_main(void)
53 {
54 	int err;
55 	struct bt_csip_set_member_register_param csip_params = {
56 		.set_size = 1,
57 		.rank = 1,
58 		.lockable = true,
59 		.cb = &csip_cb,
60 	};
61 	struct bt_le_ext_adv *ext_adv;
62 
63 	printk("Enabling Bluetooth\n");
64 	err = bt_enable(NULL);
65 	if (err != 0) {
66 		FAIL("Bluetooth enable failed (err %d)\n", err);
67 		return;
68 	}
69 
70 	printk("Registering CSIP Set Member\n");
71 
72 	err = bt_cap_acceptor_register(&csip_params, &svc_inst);
73 	if (err != 0) {
74 		printk("Failed to register csip\n");
75 		return;
76 	}
77 
78 	setup_connectable_adv(&ext_adv);
79 
80 	printk("Waiting to be connected\n");
81 	WAIT_FOR_FLAG(flag_connected);
82 	printk("Connected\n");
83 	printk("Waiting to be subscribed\n");
84 
85 	while (!is_peer_subscribed(default_conn)) {
86 		(void)k_sleep(K_MSEC(10));
87 	}
88 	printk("Subscribed\n");
89 
90 	err = bt_csip_set_member_lock(svc_inst, true, false);
91 	if (err != 0) {
92 		FAIL("Failed to set lock (err %d)\n", err);
93 		return;
94 	}
95 
96 	/* Now wait for client to disconnect */
97 	printk("Wait for client disconnect\n");
98 	WAIT_FOR_UNSET_FLAG(flag_connected);
99 	printk("Client disconnected\n");
100 
101 	/* Trigger changes while device is disconnected */
102 	err = bt_csip_set_member_lock(svc_inst, false, false);
103 	if (err != 0) {
104 		FAIL("Failed to set lock (err %d)\n", err);
105 		return;
106 	}
107 
108 	printk("Start Advertising\n");
109 	err = bt_le_ext_adv_start(ext_adv, BT_LE_EXT_ADV_START_DEFAULT);
110 	if (err != 0) {
111 		FAIL("Failed to start advertising set (err %d)\n", err);
112 
113 		bt_le_ext_adv_delete(ext_adv);
114 
115 		return;
116 	}
117 
118 	WAIT_FOR_FLAG(flag_connected);
119 	WAIT_FOR_UNSET_FLAG(flag_connected);
120 
121 	PASS("CSIP Notify Server passed\n");
122 }
123 
124 static const struct bst_test_instance test_csip_notify_server[] = {
125 	{
126 		.test_id = "csip_notify_server",
127 		.test_pre_init_f = test_init,
128 		.test_tick_f = test_tick,
129 		.test_main_f = test_main,
130 	},
131 	BSTEST_END_MARKER,
132 };
133 
test_csip_notify_server_install(struct bst_test_list * tests)134 struct bst_test_list *test_csip_notify_server_install(struct bst_test_list *tests)
135 {
136 	return bst_add_tests(tests, test_csip_notify_server);
137 }
138