Skip to content

Commit

Permalink
Bluetooth: GATT: Make bt_gatt_discover perform discover all procedure
Browse files Browse the repository at this point in the history
This makes bt_gatt_discover perform discover all proceduce if no UUID
is given in the parameters.

Fixes #9713

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
  • Loading branch information
Vudentz authored and jhedberg committed Sep 19, 2018
1 parent 0d1724b commit e2362e1
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 1 deletion.
11 changes: 11 additions & 0 deletions subsys/bluetooth/host/att.c
Expand Up @@ -1648,6 +1648,13 @@ static u8_t att_handle_read_mult_rsp(struct bt_att *att, struct net_buf *buf)
}
#endif /* CONFIG_BT_GATT_READ_MULTIPLE */

static u8_t att_handle_read_group_rsp(struct bt_att *att, struct net_buf *buf)
{
BT_DBG("");

return att_handle_rsp(att, buf->data, buf->len, 0);
}

static u8_t att_handle_write_rsp(struct bt_att *att, struct net_buf *buf)
{
BT_DBG("");
Expand Down Expand Up @@ -1786,6 +1793,10 @@ static const struct att_handler {
sizeof(struct bt_att_read_group_req),
ATT_REQUEST,
att_read_group_req },
{ BT_ATT_OP_READ_GROUP_RSP,
sizeof(struct bt_att_read_group_rsp),
ATT_RESPONSE,
att_handle_read_group_rsp },
{ BT_ATT_OP_WRITE_REQ,
sizeof(struct bt_att_write_req),
ATT_REQUEST,
Expand Down
136 changes: 135 additions & 1 deletion subsys/bluetooth/host/gatt.c
Expand Up @@ -1579,6 +1579,137 @@ static int gatt_read_type(struct bt_conn *conn,
return gatt_send(conn, buf, gatt_read_type_rsp, params, NULL);
}

static u16_t parse_service(struct bt_conn *conn, const void *pdu,
struct bt_gatt_discover_params *params,
u16_t length)
{
const struct bt_att_read_group_rsp *rsp = pdu;
u16_t start_handle, end_handle = 0;
union {
struct bt_uuid uuid;
struct bt_uuid_16 u16;
struct bt_uuid_128 u128;
} u;

/* Data can be either in UUID16 or UUID128 */
switch (rsp->len) {
case 6: /* UUID16 */
u.uuid.type = BT_UUID_TYPE_16;
break;
case 20: /* UUID128 */
u.uuid.type = BT_UUID_TYPE_128;
break;
default:
BT_ERR("Invalid data len %u", rsp->len);
goto done;
}

/* Parse services found */
for (length--, pdu = rsp->data; length >= rsp->len;
length -= rsp->len, pdu += rsp->len) {
struct bt_gatt_attr attr = {};
struct bt_gatt_service_val value;
const struct bt_att_group_data *data = pdu;

start_handle = sys_le16_to_cpu(data->start_handle);
if (!start_handle) {
goto done;
}

end_handle = sys_le16_to_cpu(data->end_handle);
if (!end_handle || end_handle < start_handle) {
goto done;
}

switch (u.uuid.type) {
case BT_UUID_TYPE_16:
memcpy(&u.u16.val, data->value, sizeof(u.u16.val));
u.u16.val = sys_le16_to_cpu(u.u16.val);
break;
case BT_UUID_TYPE_128:
memcpy(u.u128.val, data->value, sizeof(u.u128.val));
break;
}

BT_DBG("start_handle 0x%04x end_handle 0x%04x uuid %s",
start_handle, end_handle, bt_uuid_str(&u.uuid));

if (params->type == BT_GATT_DISCOVER_PRIMARY) {
attr.uuid = BT_UUID_GATT_PRIMARY;
} else {
attr.uuid = BT_UUID_GATT_SECONDARY;
}

value.end_handle = end_handle;
value.uuid = &u.uuid;

attr.handle = start_handle;
attr.user_data = &value;

if (params->func(conn, &attr, params) == BT_GATT_ITER_STOP) {
return 0;
}
}

/* Whole PDU read without error */
if (length == 0 && end_handle) {
return end_handle;
}

done:
params->func(conn, NULL, params);
return 0;
}

static void gatt_read_group_rsp(struct bt_conn *conn, u8_t err,
const void *pdu, u16_t length,
void *user_data)
{
struct bt_gatt_discover_params *params = user_data;
u16_t handle;

BT_DBG("err 0x%02x", err);

if (err) {
params->func(conn, NULL, params);
return;
}

handle = parse_service(conn, pdu, params, length);
if (!handle) {
return;
}

gatt_discover_next(conn, handle, params);
}

static int gatt_read_group(struct bt_conn *conn,
struct bt_gatt_discover_params *params)
{
struct net_buf *buf;
struct bt_att_read_group_req *req;

buf = bt_att_create_pdu(conn, BT_ATT_OP_READ_GROUP_REQ, sizeof(*req));
if (!buf) {
return -ENOMEM;
}

req = net_buf_add(buf, sizeof(*req));
req->start_handle = sys_cpu_to_le16(params->start_handle);
req->end_handle = sys_cpu_to_le16(params->end_handle);

if (params->type == BT_GATT_DISCOVER_PRIMARY) {
net_buf_add_le16(buf, BT_UUID_16(BT_UUID_GATT_PRIMARY)->val);
} else {
net_buf_add_le16(buf, BT_UUID_16(BT_UUID_GATT_SECONDARY)->val);
}

BT_DBG("start_handle 0x%04x end_handle 0x%04x", params->start_handle,
params->end_handle);

return gatt_send(conn, buf, gatt_read_group_rsp, params, NULL);
}

static void gatt_find_info_rsp(struct bt_conn *conn, u8_t err,
const void *pdu, u16_t length,
void *user_data)
Expand Down Expand Up @@ -1702,7 +1833,10 @@ int bt_gatt_discover(struct bt_conn *conn,
switch (params->type) {
case BT_GATT_DISCOVER_PRIMARY:
case BT_GATT_DISCOVER_SECONDARY:
return gatt_find_type(conn, params);
if (params->uuid) {
return gatt_find_type(conn, params);
}
return gatt_read_group(conn, params);
case BT_GATT_DISCOVER_INCLUDE:
case BT_GATT_DISCOVER_CHARACTERISTIC:
return gatt_read_type(conn, params);
Expand Down

0 comments on commit e2362e1

Please sign in to comment.