1 /*
2  * Copyright 2023 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <errno.h>
7 #include <stddef.h>
8 #include <stdint.h>
9 
10 #include <zephyr/autoconf.h>
11 #include <zephyr/bluetooth/audio/audio.h>
12 #include <zephyr/bluetooth/audio/pbp.h>
13 #include <zephyr/bluetooth/bluetooth.h>
14 #include <zephyr/bluetooth/gap.h>
15 #include <zephyr/bluetooth/uuid.h>
16 #include <zephyr/logging/log.h>
17 #include <zephyr/net/buf.h>
18 #include <zephyr/sys/byteorder.h>
19 #include <zephyr/sys/check.h>
20 #include <zephyr/types.h>
21 
22 LOG_MODULE_REGISTER(bt_pbp, CONFIG_BT_PBP_LOG_LEVEL);
23 
bt_pbp_get_announcement(const uint8_t meta[],size_t meta_len,enum bt_pbp_announcement_feature features,struct net_buf_simple * pba_data_buf)24 int bt_pbp_get_announcement(const uint8_t meta[], size_t meta_len,
25 			    enum bt_pbp_announcement_feature features,
26 			    struct net_buf_simple *pba_data_buf)
27 {
28 	CHECKIF(pba_data_buf == NULL) {
29 		LOG_DBG("No buffer provided for advertising data!\n");
30 
31 		return -EINVAL;
32 	}
33 
34 	CHECKIF((meta == NULL && meta_len != 0) || (meta != NULL && meta_len == 0)) {
35 		LOG_DBG("Invalid metadata combination: %p %zu", meta, meta_len);
36 
37 		return -EINVAL;
38 	}
39 
40 	CHECKIF(pba_data_buf->size < (meta_len + BT_PBP_MIN_PBA_SIZE)) {
41 		LOG_DBG("Buffer size needs to be at least %d!\n", meta_len + BT_PBP_MIN_PBA_SIZE);
42 
43 		return -EINVAL;
44 	}
45 
46 	/* Fill Announcement data */
47 	net_buf_simple_add_le16(pba_data_buf, BT_UUID_PBA_VAL);
48 	net_buf_simple_add_u8(pba_data_buf, features);
49 	net_buf_simple_add_u8(pba_data_buf, meta_len);
50 	net_buf_simple_add_mem(pba_data_buf, meta, meta_len);
51 
52 	return 0;
53 }
54 
bt_pbp_parse_announcement(struct bt_data * data,enum bt_pbp_announcement_feature * features,uint8_t ** meta)55 int bt_pbp_parse_announcement(struct bt_data *data, enum bt_pbp_announcement_feature *features,
56 			      uint8_t **meta)
57 {
58 	struct bt_uuid_16 adv_uuid;
59 	struct net_buf_simple buf;
60 	uint8_t meta_len = 0;
61 	void *uuid;
62 
63 	CHECKIF(!data || !features || !meta) {
64 		return -EINVAL;
65 	}
66 
67 	if (data->type != BT_DATA_SVC_DATA16) {
68 		return -ENOENT;
69 	}
70 
71 	if (data->data_len < BT_PBP_MIN_PBA_SIZE) {
72 		return -EMSGSIZE;
73 	}
74 
75 	net_buf_simple_init_with_data(&buf, (void *)data->data, data->data_len);
76 	uuid = net_buf_simple_pull_mem(&buf, BT_UUID_SIZE_16);
77 
78 	(void)bt_uuid_create(&adv_uuid.uuid, uuid, BT_UUID_SIZE_16); /* cannot fail */
79 
80 	if (bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_PBA)) {
81 		return -ENOENT;
82 	}
83 
84 	/* Copy source features, metadata length and metadata from the Announcement */
85 	*features = net_buf_simple_pull_u8(&buf);
86 	meta_len = net_buf_simple_pull_u8(&buf);
87 	if (buf.len < meta_len) {
88 		return -EBADMSG;
89 	}
90 
91 	*meta = (uint8_t *)net_buf_simple_pull_mem(&buf, meta_len);
92 
93 	return meta_len;
94 }
95