Bluetooth: Add implementation of ATT Read by Type Response
Read attributes matching UUID and handle range generating a proper response: < ACL Data TX: Handle 3585 flags 0x00 dlen 20 ATT: Read By Type Response (0x09) len 15 Attribute data length: 7 Attribute data list: 2 entries Handle: 0x0002 Value: 020300002a Handle: 0x0004 Value: 020500012a Change-Id: Iaf4b0c963765a7769a17144a4d394dce8555c2d3 Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
7c14248061
commit
9a09a5d329
1 changed files with 79 additions and 5 deletions
|
@ -245,6 +245,84 @@ static bool uuid_create(struct bt_uuid *uuid, struct bt_buf *data)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct read_type_data {
|
||||||
|
struct bt_conn *conn;
|
||||||
|
struct bt_uuid *uuid;
|
||||||
|
struct bt_buf *buf;
|
||||||
|
struct bt_att_read_type_rsp *rsp;
|
||||||
|
struct bt_att_data *item;
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint8_t read_type_cb(const struct bt_gatt_attr *attr, void *user_data)
|
||||||
|
{
|
||||||
|
struct read_type_data *data = user_data;
|
||||||
|
struct bt_att *att = data->conn->att;
|
||||||
|
int read;
|
||||||
|
|
||||||
|
/* Skip if doesn't match */
|
||||||
|
if (bt_uuid_cmp(attr->uuid, data->uuid)) {
|
||||||
|
return BT_GATT_ITER_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BT_DBG("handle %u\n", attr->handle);
|
||||||
|
|
||||||
|
/* Fast foward to next item position */
|
||||||
|
data->item = bt_buf_add(data->buf, sizeof(*data->item));
|
||||||
|
data->item->handle = sys_cpu_to_le16(attr->handle);
|
||||||
|
|
||||||
|
/* Read attribute value and store in the buffer */
|
||||||
|
read = attr->read(attr, data->buf->data + data->buf->len,
|
||||||
|
att->mtu - data->buf->len, 0);
|
||||||
|
if (read < 0) {
|
||||||
|
/* TODO: Handle read errors */
|
||||||
|
return BT_GATT_ITER_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data->rsp->len) {
|
||||||
|
/* Set len to be the first item found */
|
||||||
|
data->rsp->len = read + sizeof(*data->item);
|
||||||
|
} else if (data->rsp->len != read + sizeof(*data->item)) {
|
||||||
|
/* All items should have the same size */
|
||||||
|
data->buf->len -= sizeof(*data->item);
|
||||||
|
return BT_GATT_ITER_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_buf_add(data->buf, read);
|
||||||
|
|
||||||
|
/* return true only if there are still space for more items */
|
||||||
|
return att->mtu - data->buf->len > data->rsp->len ?
|
||||||
|
BT_GATT_ITER_CONTINUE : BT_GATT_ITER_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void att_read_type_rsp(struct bt_conn *conn, struct bt_uuid *uuid,
|
||||||
|
uint16_t start_handle, uint16_t end_handle)
|
||||||
|
{
|
||||||
|
struct read_type_data data;
|
||||||
|
|
||||||
|
memset(&data, 0, sizeof(data));
|
||||||
|
|
||||||
|
data.buf = bt_att_create_pdu(conn, BT_ATT_OP_READ_TYPE_RSP,
|
||||||
|
sizeof(*data.rsp));
|
||||||
|
if (!data.buf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.uuid = uuid;
|
||||||
|
data.rsp = bt_buf_add(data.buf, sizeof(*data.rsp));
|
||||||
|
data.rsp->len = 0;
|
||||||
|
|
||||||
|
bt_gatt_foreach_attr(start_handle, end_handle, read_type_cb, &data);
|
||||||
|
|
||||||
|
if (!data.rsp->len) {
|
||||||
|
bt_buf_put(data.buf);
|
||||||
|
send_err_rsp(conn, BT_ATT_OP_READ_TYPE_REQ, start_handle,
|
||||||
|
BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_l2cap_send(conn, BT_L2CAP_CID_ATT, data.buf);
|
||||||
|
}
|
||||||
|
|
||||||
static void att_read_type_req(struct bt_conn *conn, struct bt_buf *data)
|
static void att_read_type_req(struct bt_conn *conn, struct bt_buf *data)
|
||||||
{
|
{
|
||||||
struct bt_att_read_type_req *req;
|
struct bt_att_read_type_req *req;
|
||||||
|
@ -280,11 +358,7 @@ static void att_read_type_req(struct bt_conn *conn, struct bt_buf *data)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Generate proper response once a database is defined */
|
att_read_type_rsp(conn, &uuid, start_handle, end_handle);
|
||||||
|
|
||||||
send_err_rsp(conn, BT_ATT_OP_READ_TYPE_REQ, start_handle,
|
|
||||||
BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void att_read_req(struct bt_conn *conn, struct bt_buf *data)
|
static void att_read_req(struct bt_conn *conn, struct bt_buf *data)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue