| /* |
| * Copyright (c) 2023 Demant A/S |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <zephyr/bluetooth/audio/cap.h> |
| #include <zephyr/bluetooth/audio/csip.h> |
| |
| #include "common.h" |
| |
| extern enum bst_result_t bst_result; |
| |
| static struct bt_csip_set_member_svc_inst *svc_inst; |
| |
| static bool is_peer_subscribed(struct bt_conn *conn) |
| { |
| struct bt_gatt_attr *attr; |
| |
| attr = bt_gatt_find_by_uuid(NULL, 0, BT_UUID_CSIS_SET_LOCK); |
| if (!attr) { |
| printk("No BT_UUID_PACS_SNK attribute found\n"); |
| return false; |
| } |
| |
| return bt_gatt_is_subscribed(conn, attr, BT_GATT_CCC_NOTIFY); |
| } |
| |
| static void csip_set_member_lock_changed_cb(struct bt_conn *conn, |
| struct bt_csip_set_member_svc_inst *svc_inst, |
| bool locked) |
| { |
| printk("Client %p %s the lock\n", conn, locked ? "locked" : "released"); |
| } |
| |
| static struct bt_csip_set_member_cb csip_cb = { |
| .lock_changed = csip_set_member_lock_changed_cb, |
| }; |
| |
| static void test_main(void) |
| { |
| int err; |
| const struct bt_data ad[] = { |
| BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), |
| }; |
| struct bt_csip_set_member_register_param csip_params = { |
| .set_size = 1, |
| .rank = 1, |
| .lockable = true, |
| .cb = &csip_cb, |
| }; |
| |
| printk("Enabling Bluetooth\n"); |
| err = bt_enable(NULL); |
| if (err != 0) { |
| FAIL("Bluetooth enable failed (err %d)\n", err); |
| return; |
| } |
| |
| printk("Registering CSIP Set Member\n"); |
| |
| err = bt_cap_acceptor_register(&csip_params, &svc_inst); |
| if (err != 0) { |
| printk("Failed to register csip\n"); |
| return; |
| } |
| |
| printk("Start Advertising\n"); |
| err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0); |
| if (err != 0) { |
| FAIL("Advertising failed to start (err %d)\n", err); |
| return; |
| } |
| |
| printk("Waiting to be connected\n"); |
| WAIT_FOR_FLAG(flag_connected); |
| printk("Connected\n"); |
| printk("Waiting to be subscribed\n"); |
| |
| while (!is_peer_subscribed(default_conn)) { |
| (void)k_sleep(K_MSEC(10)); |
| } |
| printk("Subscribed\n"); |
| |
| err = bt_csip_set_member_lock(svc_inst, true, false); |
| if (err != 0) { |
| FAIL("Failed to set lock (err %d)\n", err); |
| return; |
| } |
| |
| /* Now wait for client to disconnect, then stop adv so it does not reconnect */ |
| printk("Wait for client disconnect\n"); |
| WAIT_FOR_UNSET_FLAG(flag_connected); |
| printk("Client disconnected\n"); |
| |
| err = bt_le_adv_stop(); |
| if (err != 0) { |
| FAIL("Advertising failed to stop (err %d)\n", err); |
| return; |
| } |
| |
| /* Trigger changes while device is disconnected */ |
| err = bt_csip_set_member_lock(svc_inst, false, false); |
| if (err != 0) { |
| FAIL("Failed to set lock (err %d)\n", err); |
| return; |
| } |
| |
| printk("Start Advertising\n"); |
| err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0); |
| if (err != 0) { |
| FAIL("Advertising failed to start (err %d)\n", err); |
| return; |
| } |
| |
| WAIT_FOR_FLAG(flag_connected); |
| WAIT_FOR_UNSET_FLAG(flag_connected); |
| |
| PASS("CSIP Notify Server passed\n"); |
| } |
| |
| static const struct bst_test_instance test_csip_notify_server[] = { |
| { |
| .test_id = "csip_notify_server", |
| .test_post_init_f = test_init, |
| .test_tick_f = test_tick, |
| .test_main_f = test_main, |
| }, |
| BSTEST_END_MARKER, |
| }; |
| |
| struct bst_test_list *test_csip_notify_server_install(struct bst_test_list *tests) |
| { |
| return bst_add_tests(tests, test_csip_notify_server); |
| } |