Bluetooth: Add support for ATT Read Multiple

This adds parsing for ATT Read Multiple Request and Response:

> ACL Data RX: Handle 3585 flags 0x02 dlen 11
      ATT: Read Multiple Request (0x0e) len 6
        Handle: 0x0001
        Handle: 0x0002
        Handle: 0x0003
< ACL Data TX: Handle 3585 flags 0x00 dlen 27
      ATT: Read Multiple Response (0x0f) len 22
        00 18 02 03 00 00 2a 54 65 73 74 20 70 65 72 69  ......*Test peri
        70 68 65 72 61 6c                                pheral

Change-Id: I08efe2b73342423634c156f95baa2bba84bd50a9
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
Luiz Augusto von Dentz 2015-06-15 17:10:13 +03:00 committed by Anas Nashif
commit 801c09757e

View file

@ -616,13 +616,10 @@ static uint8_t read_cb(const struct bt_gatt_attr *attr, void *user_data)
}
static uint8_t att_read_rsp(struct bt_conn *conn, uint8_t op, uint8_t rsp,
uint16_t handle, uint16_t offset)
uint16_t *handles, size_t len, uint16_t offset)
{
struct read_data data;
if (!handle) {
return BT_ATT_ERR_INVALID_HANDLE;
}
size_t i;
memset(&data, 0, sizeof(data));
@ -634,13 +631,25 @@ static uint8_t att_read_rsp(struct bt_conn *conn, uint8_t op, uint8_t rsp,
data.conn = conn;
data.offset = offset;
bt_gatt_foreach_attr(handle, handle, read_cb, &data);
for (i = 0; i < len; i++) {
if (!handles[i]) {
data.err = BT_ATT_ERR_INVALID_HANDLE;
break;
}
bt_gatt_foreach_attr(handles[i], handles[i], read_cb, &data);
/* Stop reading in case of error */
if (data.err) {
break;
}
}
/* In case of error discard data and respond with an error */
if (data.err) {
bt_buf_put(data.buf);
/* Respond here since handle is set */
send_err_rsp(conn, op, handle, data.err);
send_err_rsp(conn, op, handles[i], data.err);
return 0;
}
@ -660,7 +669,7 @@ static uint8_t att_read_req(struct bt_conn *conn, struct bt_buf *data)
BT_DBG("handle %u\n", handle);
return att_read_rsp(conn, BT_ATT_OP_READ_REQ, BT_ATT_OP_READ_RSP,
handle, 0);
&handle, 1, 0);
}
static uint8_t att_read_blob_req(struct bt_conn *conn, struct bt_buf *data)
@ -676,27 +685,35 @@ static uint8_t att_read_blob_req(struct bt_conn *conn, struct bt_buf *data)
BT_DBG("handle %u offset %u\n", handle, offset);
return att_read_rsp(conn, BT_ATT_OP_READ_BLOB_REQ,
BT_ATT_OP_READ_BLOB_RSP, handle, offset);
BT_ATT_OP_READ_BLOB_RSP, &handle, 1, offset);
}
static uint8_t att_read_mult_req(struct bt_conn *conn, struct bt_buf *data)
{
struct bt_att_read_mult_req *req;
uint16_t handle1, handle2;
uint16_t handles[BT_BUF_MAX_DATA / sizeof(uint16_t)];
size_t i;
req = (void *)data->data;
handle1 = sys_le16_to_cpu(req->handle1);
handle2 = sys_le16_to_cpu(req->handle2);
if (data->len % sizeof(uint16_t)) {
return BT_ATT_ERR_INVALID_PDU;
}
BT_DBG("handle1 %u handle2 %u ...\n", handle1, handle2);
handles[0] = sys_le16_to_cpu(req->handle1);
handles[1] = sys_le16_to_cpu(req->handle2);
/* TODO: Generate proper response once a database is defined */
BT_DBG("handle1 %u handle2 %u\n", handles[0], handles[1]);
send_err_rsp(conn, BT_ATT_OP_READ_MULT_REQ, handle1,
BT_ATT_ERR_INVALID_HANDLE);
bt_buf_pull(data, sizeof(*req));
return 0;
for (i = 0; data->len; i++) {
handles[2 + i] = bt_buf_pull_le16(data);
BT_DBG("handle%d %u \n", 2 + i, handles[2 + i]);
}
return att_read_rsp(conn, BT_ATT_OP_READ_MULT_REQ,
BT_ATT_OP_READ_MULT_RSP, handles, 2 + i, 0);
}
struct read_group_data {