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