Skip to content

Commit

Permalink
Bluetooth: Host: Find by type should accept 128bit UUIDs
Browse files Browse the repository at this point in the history
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 Aug 7, 2019
1 parent d1dff71 commit 87c3db9
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 28 deletions.
32 changes: 32 additions & 0 deletions include/bluetooth/uuid.h
Expand Up @@ -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.
*
Expand Down
59 changes: 31 additions & 28 deletions subsys/bluetooth/host/att.c
Expand Up @@ -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 */
Expand All @@ -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 */
Expand All @@ -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,
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand Down
47 changes: 47 additions & 0 deletions subsys/bluetooth/host/uuid.c
Expand Up @@ -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)
{
Expand Down

0 comments on commit 87c3db9

Please sign in to comment.