1 /* main.c - Application main entry point */
2 
3 /*
4  * Copyright (c) 2024 Nordic Semiconductor ASA
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 #include <errno.h>
9 #include <stddef.h>
10 #include <stdint.h>
11 #include <sys/types.h>
12 
13 #include <zephyr/bluetooth/audio/ccid.h>
14 #include <zephyr/bluetooth/conn.h>
15 #include <zephyr/bluetooth/gatt.h>
16 #include <zephyr/bluetooth/uuid.h>
17 #include <zephyr/fff.h>
18 #include <zephyr/sys/util.h>
19 #include <zephyr/sys/util_macro.h>
20 
21 #include <zephyr/ztest_test.h>
22 #include <zephyr/ztest_assert.h>
23 
24 DEFINE_FFF_GLOBALS;
25 
26 ZTEST_SUITE(audio_ccid_test_suite, NULL, NULL, NULL, NULL, NULL);
27 
28 #define MAX_CCID_CNT 256
29 
ZTEST(audio_ccid_test_suite,test_bt_ccid_alloc_value)30 static ZTEST(audio_ccid_test_suite, test_bt_ccid_alloc_value)
31 {
32 	const int ret = bt_ccid_alloc_value();
33 
34 	zassert_true(ret >= 0 && ret <= UINT8_MAX, "Unexpected return value %d", ret);
35 }
36 
ZTEST(audio_ccid_test_suite,test_bt_ccid_alloc_value_more_than_max)37 static ZTEST(audio_ccid_test_suite, test_bt_ccid_alloc_value_more_than_max)
38 {
39 	/* Verify that we can allocate more than max CCID if they are not registered */
40 	for (uint16_t i = 0U; i < MAX_CCID_CNT * 2; i++) {
41 		const int ret = bt_ccid_alloc_value();
42 
43 		zassert_true(ret >= 0 && ret <= UINT8_MAX, "Unexpected return value %d", ret);
44 	}
45 }
46 
read_ccid(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)47 static ssize_t read_ccid(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
48 			 uint16_t len, uint16_t offset)
49 {
50 	const unsigned int ccid = POINTER_TO_UINT(attr->user_data);
51 	const uint8_t ccid_u8 = (uint8_t)ccid;
52 
53 	zassert_true(ccid <= BT_CCID_MAX);
54 
55 	return bt_gatt_attr_read(conn, attr, buf, len, offset, &ccid_u8, sizeof(ccid_u8));
56 }
57 
58 #define CCID_DEFINE(_n, ...)                                                                       \
59 	BT_GATT_CHARACTERISTIC(BT_UUID_CCID, BT_GATT_CHRC_READ, BT_GATT_PERM_READ, read_ccid,      \
60 			       NULL, UINT_TO_POINTER(_n))
61 
62 /* BT_GATT_PRIMARY_SERVICE only works in the global scope */
63 static struct bt_gatt_attr test_attrs[] = {
64 	BT_GATT_PRIMARY_SERVICE(BT_UUID_TBS),
65 	LISTIFY(MAX_CCID_CNT, CCID_DEFINE, (,)),
66 };
67 
ZTEST(audio_ccid_test_suite,test_bt_ccid_alloc_value_all_allocated)68 static ZTEST(audio_ccid_test_suite, test_bt_ccid_alloc_value_all_allocated)
69 {
70 	struct bt_gatt_service test_svc = BT_GATT_SERVICE(test_attrs);
71 	int ret;
72 
73 	zassert_ok(bt_gatt_service_register(&test_svc));
74 
75 	/* Verify that CCID allocation fails if we have 255 characterstics with it */
76 	ret = bt_ccid_alloc_value();
77 
78 	zassert_ok(bt_gatt_service_unregister(&test_svc));
79 
80 	zassert_equal(ret, -ENOMEM, "Unexpected return value %d", ret);
81 }
82 
ZTEST(audio_ccid_test_suite,test_bt_ccid_find_attr)83 static ZTEST(audio_ccid_test_suite, test_bt_ccid_find_attr)
84 {
85 	struct bt_gatt_service test_svc = BT_GATT_SERVICE(test_attrs);
86 
87 	/* Service not registered, shall fail */
88 	zassert_is_null(bt_ccid_find_attr(0));
89 
90 	zassert_ok(bt_gatt_service_register(&test_svc));
91 
92 	/* Service registered, shall not fail */
93 	zassert_not_null(bt_ccid_find_attr(0));
94 
95 	zassert_ok(bt_gatt_service_unregister(&test_svc));
96 }
97