Skip to content
Permalink
Browse files

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>
  • Loading branch information...
kimsekkelund authored and aescolar committed Jul 24, 2019
1 parent d1dff71 commit 87c3db9e0be68b9344ee980de7c3340468530773
Showing with 110 additions and 28 deletions.
  1. +32 −0 include/bluetooth/uuid.h
  2. +31 −28 subsys/bluetooth/host/att.c
  3. +47 −0 subsys/bluetooth/host/uuid.c
@@ -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,18 +893,18 @@ 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;
}

req = net_buf_pull_mem(buf, sizeof(*req));

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)
{

0 comments on commit 87c3db9

Please sign in to comment.
You can’t perform that action at this time.