1 /* Bluetooth Audio Content Control */
2
3 /*
4 * Copyright (c) 2020 Bose Corporation
5 * Copyright (c) 2021 Nordic Semiconductor ASA
6 *
7 * SPDX-License-Identifier: Apache-2.0
8 */
9 #include <stddef.h>
10 #include <stdint.h>
11 #include <sys/types.h>
12
13 #include <zephyr/bluetooth/att.h>
14 #include <zephyr/bluetooth/gatt.h>
15 #include <zephyr/bluetooth/uuid.h>
16 #include <zephyr/sys/__assert.h>
17
18 #include "ccid_internal.h"
19
bt_ccid_get_value(void)20 uint8_t bt_ccid_get_value(void)
21 {
22 static uint8_t ccid_value;
23
24 /* By spec, the CCID can take all values up to and including 0xFF.
25 * But since this is a value we provide, we do not have to use all of
26 * them. 254 CCID values on a device should be plenty, the last one
27 * can be used to prevent wraparound.
28 */
29 __ASSERT(ccid_value != UINT8_MAX,
30 "Cannot allocate any more control control IDs");
31
32 return ccid_value++;
33 }
34
35 struct ccid_search_param {
36 const struct bt_gatt_attr *attr;
37 uint8_t ccid;
38 };
39
ccid_attr_cb(const struct bt_gatt_attr * attr,uint16_t handle,void * user_data)40 static uint8_t ccid_attr_cb(const struct bt_gatt_attr *attr, uint16_t handle, void *user_data)
41 {
42 struct ccid_search_param *search_param = user_data;
43
44 if (attr->read != NULL) {
45 uint8_t ccid = 0U;
46 ssize_t res;
47
48 res = attr->read(NULL, attr, &ccid, sizeof(ccid), 0);
49
50 if (res == sizeof(ccid) && search_param->ccid == ccid) {
51 search_param->attr = attr;
52
53 return BT_GATT_ITER_STOP;
54 }
55 }
56
57 return BT_GATT_ITER_CONTINUE;
58 }
59
bt_ccid_find_attr(uint8_t ccid)60 const struct bt_gatt_attr *bt_ccid_find_attr(uint8_t ccid)
61 {
62 struct ccid_search_param search_param = {
63 .attr = NULL,
64 .ccid = ccid,
65 };
66
67 bt_gatt_foreach_attr_type(BT_ATT_FIRST_ATTRIBUTE_HANDLE, BT_ATT_LAST_ATTRIBUTE_HANDLE,
68 BT_UUID_CCID, NULL, 0, ccid_attr_cb, &search_param);
69
70 return search_param.attr;
71 }
72