Bluetooth: Host: Find by type should accept 128bit UUIDs
Find by type does only accept a UUID with the same length as the UUID which is stored in the internal list. If a UUID is stored in the short 16 bit format then a request with 128 bit UUID will fail. Add support for the missing formats. Signed-off-by: Kim Sekkelund <ksek@oticon.com>
This commit is contained in:
parent
d1dff7129b
commit
87c3db9e0b
3 changed files with 110 additions and 28 deletions
|
@ -465,6 +465,38 @@ struct bt_uuid_128 {
|
|||
*/
|
||||
int bt_uuid_cmp(const struct bt_uuid *u1, const struct bt_uuid *u2);
|
||||
|
||||
/** @brief Copy UUID from packet data (LE) to internal bt_uuid.
|
||||
*
|
||||
* Copy UUID from packet data in little endian format to internal bt_uuid
|
||||
* format. The data_len parameter is used to determine whether the received
|
||||
* UUID is of 16 or 128 bit format (length 2 or 16). 32 bit format is not
|
||||
* allowed over the air.
|
||||
*
|
||||
* @param uuid Pointer to where to write the Bluetooth UUID
|
||||
* @param data pointer to location of the UUID in the packet
|
||||
* @param data_len length of the UUID in the packet
|
||||
*
|
||||
* @return true if the data was valid and the UUID was successfully created.
|
||||
*/
|
||||
bool bt_uuid_create_le(struct bt_uuid *uuid, const u8_t *data, u8_t data_len);
|
||||
|
||||
/** @brief Copy UUID from internal variable to internal bt_uuid.
|
||||
*
|
||||
* Copy UUID from internal variable pointer to internal bt_uuid format.
|
||||
* The data parameter points to a variable (originally stored in bt_uuid_128,
|
||||
* bt_uuid_32 or bt_uuid_16 format) and therefore take into account of
|
||||
* alignment of the val member.
|
||||
* The data_len parameter is used to determine whether to copy the UUID from
|
||||
* 16, 32 or 128 bit format (length 2, 4 or 16).
|
||||
*
|
||||
* @param uuid Pointer to where to write the Bluetooth UUID
|
||||
* @param data pointer to location of the UUID variable
|
||||
* @param data_len length of the UUID in the packet
|
||||
*
|
||||
* @return true if the data was valid and the UUID was successfully created.
|
||||
*/
|
||||
bool bt_uuid_create(struct bt_uuid *uuid, u8_t *data, u8_t data_len);
|
||||
|
||||
#if defined(CONFIG_BT_DEBUG)
|
||||
/** @brief Convert Bluetooth UUID to string.
|
||||
*
|
||||
|
|
|
@ -580,8 +580,7 @@ static u8_t find_type_cb(const struct bt_gatt_attr *attr, void *user_data)
|
|||
|
||||
/* Skip secondary services */
|
||||
if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_SECONDARY)) {
|
||||
data->group = NULL;
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
goto skip;
|
||||
}
|
||||
|
||||
/* Update group end_handle if not a primary service */
|
||||
|
@ -607,14 +606,29 @@ static u8_t find_type_cb(const struct bt_gatt_attr *attr, void *user_data)
|
|||
* Since we don't know if it is the service with requested UUID,
|
||||
* we cannot respond with an error to this request.
|
||||
*/
|
||||
data->group = NULL;
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
goto skip;
|
||||
}
|
||||
|
||||
/* Check if data matches */
|
||||
if (read != data->value_len || memcmp(data->value, uuid, read)) {
|
||||
data->group = NULL;
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
if (read != data->value_len) {
|
||||
/* Use bt_uuid_cmp() to compare UUIDs of different form. */
|
||||
struct bt_uuid_128 ref_uuid;
|
||||
struct bt_uuid_128 recvd_uuid;
|
||||
|
||||
if (!bt_uuid_create_le(&recvd_uuid.uuid, data->value,
|
||||
data->value_len)) {
|
||||
BT_WARN("Unable to create UUID: size %u", data->value_len);
|
||||
goto skip;
|
||||
}
|
||||
if (!bt_uuid_create(&ref_uuid.uuid, uuid, read)) {
|
||||
BT_WARN("Unable to create UUID: size %d", read);
|
||||
goto skip;
|
||||
}
|
||||
if (bt_uuid_cmp(&recvd_uuid.uuid, &ref_uuid.uuid)) {
|
||||
goto skip;
|
||||
}
|
||||
} else if (memcmp(data->value, uuid, read)) {
|
||||
goto skip;
|
||||
}
|
||||
|
||||
/* If service has been found, error should be cleared */
|
||||
|
@ -627,6 +641,10 @@ static u8_t find_type_cb(const struct bt_gatt_attr *attr, void *user_data)
|
|||
|
||||
/* continue to find the end_handle */
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
|
||||
skip:
|
||||
data->group = NULL;
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
static u8_t att_find_type_rsp(struct bt_att *att, u16_t start_handle,
|
||||
|
@ -705,22 +723,6 @@ static u8_t att_find_type_req(struct bt_att *att, struct net_buf *buf)
|
|||
buf->len);
|
||||
}
|
||||
|
||||
static bool uuid_create(struct bt_uuid *uuid, struct net_buf *buf)
|
||||
{
|
||||
switch (buf->len) {
|
||||
case 2:
|
||||
uuid->type = BT_UUID_TYPE_16;
|
||||
BT_UUID_16(uuid)->val = net_buf_pull_le16(buf);
|
||||
return true;
|
||||
case 16:
|
||||
uuid->type = BT_UUID_TYPE_128;
|
||||
memcpy(BT_UUID_128(uuid)->val, buf->data, buf->len);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static u8_t check_perm(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||
u8_t mask)
|
||||
{
|
||||
|
@ -891,9 +893,10 @@ static u8_t att_read_type_req(struct bt_att *att, struct net_buf *buf)
|
|||
struct bt_uuid_16 u16;
|
||||
struct bt_uuid_128 u128;
|
||||
} u;
|
||||
u8_t uuid_len = buf->len - sizeof(*req);
|
||||
|
||||
/* Type can only be UUID16 or UUID128 */
|
||||
if (buf->len != sizeof(*req) + 2 && buf->len != sizeof(*req) + 16) {
|
||||
if (uuid_len != 2 && uuid_len != 16) {
|
||||
return BT_ATT_ERR_INVALID_PDU;
|
||||
}
|
||||
|
||||
|
@ -901,8 +904,7 @@ static u8_t att_read_type_req(struct bt_att *att, struct net_buf *buf)
|
|||
|
||||
start_handle = sys_le16_to_cpu(req->start_handle);
|
||||
end_handle = sys_le16_to_cpu(req->end_handle);
|
||||
|
||||
if (!uuid_create(&u.uuid, buf)) {
|
||||
if (!bt_uuid_create_le(&u.uuid, req->uuid, uuid_len)) {
|
||||
return BT_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
|
||||
|
@ -1197,9 +1199,10 @@ static u8_t att_read_group_req(struct bt_att *att, struct net_buf *buf)
|
|||
struct bt_uuid_16 u16;
|
||||
struct bt_uuid_128 u128;
|
||||
} u;
|
||||
u8_t uuid_len = buf->len - sizeof(*req);
|
||||
|
||||
/* Type can only be UUID16 or UUID128 */
|
||||
if (buf->len != sizeof(*req) + 2 && buf->len != sizeof(*req) + 16) {
|
||||
if (uuid_len != 2 && uuid_len != 16) {
|
||||
return BT_ATT_ERR_INVALID_PDU;
|
||||
}
|
||||
|
||||
|
@ -1208,7 +1211,7 @@ static u8_t att_read_group_req(struct bt_att *att, struct net_buf *buf)
|
|||
start_handle = sys_le16_to_cpu(req->start_handle);
|
||||
end_handle = sys_le16_to_cpu(req->end_handle);
|
||||
|
||||
if (!uuid_create(&u.uuid, buf)) {
|
||||
if (!bt_uuid_create_le(&u.uuid, req->uuid, uuid_len)) {
|
||||
return BT_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
|
||||
|
|
|
@ -80,6 +80,53 @@ int bt_uuid_cmp(const struct bt_uuid *u1, const struct bt_uuid *u2)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
bool bt_uuid_create_le(struct bt_uuid *uuid, const u8_t *data, u8_t data_len)
|
||||
{
|
||||
/* Copy UUID from packet data to internal bt_uuid */
|
||||
switch (data_len) {
|
||||
case 2:
|
||||
uuid->type = BT_UUID_TYPE_16;
|
||||
BT_UUID_16(uuid)->val = sys_get_le16(data);
|
||||
break;
|
||||
case 16:
|
||||
uuid->type = BT_UUID_TYPE_128;
|
||||
memcpy(&BT_UUID_128(uuid)->val, data, 16);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bt_uuid_create(struct bt_uuid *uuid, u8_t *data, u8_t data_len)
|
||||
{
|
||||
/* Copy UUID from internal variable to internal bt_uuid */
|
||||
union {
|
||||
u16_t *u16;
|
||||
u32_t *u32;
|
||||
u8_t *u128;
|
||||
} v;
|
||||
|
||||
v.u128 = data;
|
||||
switch (data_len) {
|
||||
case 2:
|
||||
uuid->type = BT_UUID_TYPE_16;
|
||||
BT_UUID_16(uuid)->val = *v.u16;
|
||||
break;
|
||||
case 4:
|
||||
uuid->type = BT_UUID_TYPE_32;
|
||||
BT_UUID_32(uuid)->val = *v.u32;
|
||||
break;
|
||||
case 16:
|
||||
uuid->type = BT_UUID_TYPE_128;
|
||||
memcpy(&BT_UUID_128(uuid)->val, v.u128, 16);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_DEBUG)
|
||||
void bt_uuid_to_str(const struct bt_uuid *uuid, char *str, size_t len)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue