Bluetooth: PBP: Fix parsing and return issue with bt_pbp_parse_announcement
bt_pbp_parse_announcement was defined as uint8_t return value function, but returned errno values, so it was modified to return an int instead. The return values are also now more granular and documented. The function also triggered a coverity issue with the way that it parsed the data->data, as it would be marked as tainted. This should be fixed by using the net_buf_simple API, which also improves on some other parts of the code. Finally the meta argument for the function was changed from an unknown sized buffer, where the caller somehow had to know the size of the metadata before calling the parsing function, to an output pointer. This also omits the requirement for the caller to always copy the metadata, where now it just gets a pointer to the metadata in the bt_data struct. The application can now always decide whether to continue to parse the metadata or to copy it, using the pointer and the return value of the function. Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
parent
044529d0cd
commit
01d0f1a566
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue