Bluetooth: CAP: Add verification of CCIDs as the initiator
When the initiator provides CCID in the metadata, we verify that the CCIDs exist on the device. Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
parent
a422e1d8fb
commit
779f725db3
@ -10,6 +10,7 @@
|
||||
#include <zephyr/bluetooth/audio/cap.h>
|
||||
#include <zephyr/bluetooth/audio/tbs.h>
|
||||
#include "cap_internal.h"
|
||||
#include "ccid_internal.h"
|
||||
#include "csip_internal.h"
|
||||
#include "bap_endpoint.h"
|
||||
|
||||
@ -38,9 +39,14 @@ int bt_cap_initiator_register_cb(const struct bt_cap_initiator_cb *cb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct valid_metadata_param {
|
||||
bool stream_context_found;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
static bool data_func_cb(struct bt_data *data, void *user_data)
|
||||
{
|
||||
bool *stream_context_found = (bool *)user_data;
|
||||
struct valid_metadata_param *metadata_param = (struct valid_metadata_param *)user_data;
|
||||
|
||||
LOG_DBG("type %u len %u data %s", data->type, data->data_len,
|
||||
bt_hex(data->data, data->data_len));
|
||||
@ -50,8 +56,21 @@ static bool data_func_cb(struct bt_data *data, void *user_data)
|
||||
return false;
|
||||
}
|
||||
|
||||
*stream_context_found = true;
|
||||
return false;
|
||||
metadata_param->stream_context_found = true;
|
||||
} else if (IS_ENABLED(CONFIG_BT_CCID) && data->type == BT_AUDIO_METADATA_TYPE_CCID_LIST) {
|
||||
/* If the application supplies a CCID list, we verify that the CCIDs exist on our
|
||||
* device
|
||||
*/
|
||||
for (uint8_t i = 0U; i < data->data_len; i++) {
|
||||
const uint8_t ccid = data->data[i];
|
||||
|
||||
if (bt_ccid_find_attr(ccid) == NULL) {
|
||||
LOG_DBG("Unknown characterstic for CCID 0x%02X", ccid);
|
||||
metadata_param->valid = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -59,21 +78,24 @@ static bool data_func_cb(struct bt_data *data, void *user_data)
|
||||
|
||||
static bool cap_initiator_valid_metadata(const uint8_t meta[], size_t meta_len)
|
||||
{
|
||||
bool stream_context_found = false;
|
||||
struct valid_metadata_param metadata_param = {
|
||||
.stream_context_found = false,
|
||||
.valid = true,
|
||||
};
|
||||
int err;
|
||||
|
||||
LOG_DBG("meta %p len %zu", meta, meta_len);
|
||||
|
||||
err = bt_audio_data_parse(meta, meta_len, data_func_cb, &stream_context_found);
|
||||
err = bt_audio_data_parse(meta, meta_len, data_func_cb, &metadata_param);
|
||||
if (err != 0 && err != -ECANCELED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!stream_context_found) {
|
||||
if (!metadata_param.stream_context_found) {
|
||||
LOG_DBG("No streaming context supplied");
|
||||
}
|
||||
|
||||
return stream_context_found;
|
||||
return metadata_param.stream_context_found && metadata_param.valid;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
|
||||
|
||||
@ -6,6 +6,9 @@
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <zephyr/bluetooth/att.h>
|
||||
#include <zephyr/bluetooth/gatt.h>
|
||||
#include <zephyr/bluetooth/uuid.h>
|
||||
|
||||
#include "ccid_internal.h"
|
||||
|
||||
@ -23,3 +26,41 @@ uint8_t bt_ccid_get_value(void)
|
||||
|
||||
return ccid_value++;
|
||||
}
|
||||
|
||||
struct ccid_search_param {
|
||||
const struct bt_gatt_attr *attr;
|
||||
uint8_t ccid;
|
||||
};
|
||||
|
||||
static uint8_t ccid_attr_cb(const struct bt_gatt_attr *attr, uint16_t handle, void *user_data)
|
||||
{
|
||||
struct ccid_search_param *search_param = user_data;
|
||||
|
||||
if (attr->read != NULL) {
|
||||
uint8_t ccid = 0U;
|
||||
ssize_t res;
|
||||
|
||||
res = attr->read(NULL, attr, &ccid, sizeof(ccid), 0);
|
||||
|
||||
if (res == sizeof(ccid) && search_param->ccid == ccid) {
|
||||
search_param->attr = attr;
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
const struct bt_gatt_attr *bt_ccid_find_attr(uint8_t ccid)
|
||||
{
|
||||
struct ccid_search_param search_param = {
|
||||
.attr = NULL,
|
||||
.ccid = ccid,
|
||||
};
|
||||
|
||||
bt_gatt_foreach_attr_type(BT_ATT_FIRST_ATTRIBUTE_HANDLE, BT_ATT_LAST_ATTRIBUTE_HANDLE,
|
||||
BT_UUID_CCID, NULL, 0, ccid_attr_cb, &search_param);
|
||||
|
||||
return search_param.attr;
|
||||
}
|
||||
|
||||
@ -23,4 +23,16 @@
|
||||
*/
|
||||
uint8_t bt_ccid_get_value(void);
|
||||
|
||||
/**
|
||||
* @brief Get the GATT attribute of a CCID value
|
||||
*
|
||||
* Searches the current GATT database for a CCID characteristic that has the supplied CCID value.
|
||||
*
|
||||
* @param ccid The CCID the search for
|
||||
*
|
||||
* @retval NULL if none was found
|
||||
* @retval A pointer to a GATT attribute if found
|
||||
*/
|
||||
const struct bt_gatt_attr *bt_ccid_find_attr(uint8_t ccid);
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_BLUETOOTH_CCID_H_ */
|
||||
|
||||
@ -406,11 +406,18 @@ static void test_broadcast_audio_update_inval(struct bt_cap_broadcast_source *br
|
||||
|
||||
static void test_broadcast_audio_update(struct bt_cap_broadcast_source *broadcast_source)
|
||||
{
|
||||
const uint16_t mock_ccid = 0xAB;
|
||||
#if defined(CONFIG_BT_TBS)
|
||||
/* TODO: We do not have a way to get the CCID value of GTBS, but for now set to 0x00 as we
|
||||
* know that it is the first content control service initialized
|
||||
*/
|
||||
const uint16_t gtbs_ccid = 0x00;
|
||||
#endif /* CONFIG_BT_TBS */
|
||||
const uint8_t new_metadata[] = {
|
||||
BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT,
|
||||
BT_BYTES_LIST_LE16(BT_AUDIO_CONTEXT_TYPE_MEDIA)),
|
||||
BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_CCID_LIST, mock_ccid),
|
||||
BT_BYTES_LIST_LE16(BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL)),
|
||||
#if defined(CONFIG_BT_TBS)
|
||||
BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_CCID_LIST, gtbs_ccid),
|
||||
#endif /* CONFIG_BT_TBS */
|
||||
};
|
||||
int err;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user