diff --git a/include/zephyr/bluetooth/audio/pbp.h b/include/zephyr/bluetooth/audio/pbp.h index 2ea85564fa7..acc53adb5ad 100644 --- a/include/zephyr/bluetooth/audio/pbp.h +++ b/include/zephyr/bluetooth/audio/pbp.h @@ -59,15 +59,19 @@ int bt_pbp_get_announcement(const uint8_t meta[], size_t meta_len, * @brief Parses the received advertising data corresponding to a Public Broadcast * Announcement. Returns the advertised Public Broadcast Announcement features and metadata. * - * @param data Advertising data to be checked - * @param features Public broadcast source features - * @param meta Pointer to copy the metadata present in the advertising data + * @param[in] data Advertising data to be checked + * @param[out] features Pointer to public broadcast source features to store the parsed features in + * @param[out] meta Pointer to the metadata present in the advertising data * - * @return parsed metadata length on success or an appropriate error code + * @return parsed metadata length on success. + * @retval -EINVAL if @p data, @p features or @p meta are NULL. + * @retval -ENOENT if @p data is not of type @ref BT_DATA_SVC_DATA16 or if the UUID in the service + * data is not @ref BT_UUID_PBA. + * @retval -EMSGSIZE if @p data is not large enough to contain a PBP announcement. + * @retval -EBADMSG if the @p data contains invalid data. */ -uint8_t bt_pbp_parse_announcement(struct bt_data *data, - enum bt_pbp_announcement_feature *features, - uint8_t *meta); +int bt_pbp_parse_announcement(struct bt_data *data, enum bt_pbp_announcement_feature *features, + uint8_t **meta); #ifdef __cplusplus } diff --git a/samples/bluetooth/public_broadcast_sink/src/main.c b/samples/bluetooth/public_broadcast_sink/src/main.c index 1331ffbeded..52d1cadbad7 100644 --- a/samples/bluetooth/public_broadcast_sink/src/main.c +++ b/samples/bluetooth/public_broadcast_sink/src/main.c @@ -29,7 +29,6 @@ #define INVALID_BROADCAST_ID 0xFFFFFFFF static bool pbs_found; -static uint8_t meta[CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE]; static K_SEM_DEFINE(sem_pa_synced, 0U, 1U); static K_SEM_DEFINE(sem_base_received, 0U, 1U); @@ -160,11 +159,11 @@ static void sync_broadcast_pa(const struct bt_le_scan_recv_info *info, static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data) { + enum bt_pbp_announcement_feature source_features; uint32_t *broadcast_id = user_data; struct bt_uuid_16 adv_uuid; - enum bt_pbp_announcement_feature source_features = 0U; - - memset(meta, 0, ARRAY_SIZE(meta)); + uint8_t *tmp_meta = NULL; + int ret; if (data->type != BT_DATA_SVC_DATA16) { return true; @@ -179,16 +178,18 @@ static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data) return true; } - if (!bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_PBA)) { - bt_pbp_parse_announcement(data, &source_features, meta); + ret = bt_pbp_parse_announcement(data, &source_features, &tmp_meta); + if (ret >= 0) { if (!(source_features & BT_PBP_ANNOUNCEMENT_FEATURE_HIGH_QUALITY)) { /* This is a Standard Quality Public Broadcast Audio stream */ printk("This is a Standard Quality Public Broadcast Audio stream\n"); pbs_found = false; - return true; + return false; } - printk("Found Suitable Public Broadcast Announcement\n"); + + printk("Found Suitable Public Broadcast Announcement with %d octets of metadata\n", + ret); pbs_found = true; /** @@ -198,8 +199,6 @@ static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data) if (*broadcast_id == INVALID_BROADCAST_ID) { return true; } - - return false; } return true; diff --git a/subsys/bluetooth/audio/pbp.c b/subsys/bluetooth/audio/pbp.c index 9cb589c9095..3b624045de2 100644 --- a/subsys/bluetooth/audio/pbp.c +++ b/subsys/bluetooth/audio/pbp.c @@ -45,37 +45,43 @@ int bt_pbp_get_announcement(const uint8_t meta[], size_t meta_len, return 0; } -uint8_t bt_pbp_parse_announcement(struct bt_data *data, - enum bt_pbp_announcement_feature *features, - uint8_t *meta) +int bt_pbp_parse_announcement(struct bt_data *data, enum bt_pbp_announcement_feature *features, + uint8_t **meta) { - uint8_t meta_len = 0; struct bt_uuid_16 adv_uuid; + struct net_buf_simple buf; + uint8_t meta_len = 0; + void *uuid; CHECKIF(!data || !features || !meta) { return -EINVAL; } - if (data->data_len < BT_PBP_MIN_PBA_SIZE) { - return -EBADMSG; - } - if (data->type != BT_DATA_SVC_DATA16) { - return -EINVAL; + return -ENOENT; } - if (!bt_uuid_create(&adv_uuid.uuid, data->data, BT_UUID_SIZE_16)) { - return -EINVAL; + if (data->data_len < BT_PBP_MIN_PBA_SIZE) { + return -EMSGSIZE; } + net_buf_simple_init_with_data(&buf, (void *)data->data, data->data_len); + uuid = net_buf_simple_pull_mem(&buf, BT_UUID_SIZE_16); + + (void)bt_uuid_create(&adv_uuid.uuid, uuid, BT_UUID_SIZE_16); /* cannot fail */ + if (bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_PBA)) { - return -EBADMSG; + return -ENOENT; } /* Copy source features, metadata length and metadata from the Announcement */ - *features = data->data[BT_UUID_SIZE_16]; - meta_len = data->data[BT_UUID_SIZE_16 + sizeof(uint8_t)]; - memcpy(meta, data->data + BT_PBP_MIN_PBA_SIZE, meta_len); + *features = net_buf_simple_pull_u8(&buf); + meta_len = net_buf_simple_pull_u8(&buf); + if (buf.len < meta_len) { + return -EBADMSG; + } + + *meta = (uint8_t *)net_buf_simple_pull_mem(&buf, meta_len); return meta_len; } diff --git a/tests/bsim/bluetooth/audio/src/pbp_public_broadcast_sink_test.c b/tests/bsim/bluetooth/audio/src/pbp_public_broadcast_sink_test.c index 6154fae570e..c1e0a0f2e00 100644 --- a/tests/bsim/bluetooth/audio/src/pbp_public_broadcast_sink_test.c +++ b/tests/bsim/bluetooth/audio/src/pbp_public_broadcast_sink_test.c @@ -264,9 +264,10 @@ static void sync_broadcast_pa(const struct bt_le_scan_recv_info *info) static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data) { + enum bt_pbp_announcement_feature source_features; struct bt_uuid_16 adv_uuid; - uint8_t source_features = 0U; - uint8_t meta[50]; + uint8_t *tmp_meta; + int ret; if (data->type != BT_DATA_SVC_DATA16) { return true; @@ -288,17 +289,18 @@ static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data) } } - if (!bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_PBA)) { - bt_pbp_parse_announcement(data, &source_features, meta); + ret = bt_pbp_parse_announcement(data, &source_features, &tmp_meta); + if (ret >= 0) { if (!(source_features & BT_PBP_ANNOUNCEMENT_FEATURE_HIGH_QUALITY)) { /* This is a Standard Quality Public Broadcast Audio stream - do not sync */ printk("This is a Standard Quality Public Broadcast Audio stream\n"); pbs_found = false; - return true; + return false; } - printk("Found Suitable Public Broadcast Announcement\n"); + printk("Found Suitable Public Broadcast Announcement with %d octets of metadata\n", + ret); pbs_found = true; /* Continue parsing if Broadcast Audio Announcement Service was not found */