Bluetooth: Add implementation of ATT Read and Read Blob Response

Read attribute and generate a proper responses:

< ACL Data TX: Handle 3585 flags 0x00 dlen 6
      ATT: Read Response (0x0b) len 1
        Value: 01

< ACL Data TX: Handle 3585 flags 0x00 dlen 20
      ATT: Read Blob Response (0x0d) len 15
        54 65 73 74 20 50 65 72 69 70 68 65 72 61 6c     Test Peripheral

Change-Id: I5a644fd29ae46fdecdc32c6558591ce7a8d2d42c
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
Luiz Augusto von Dentz 2015-05-20 18:00:12 +03:00 committed by Anas Nashif
commit 32c50333b3

View file

@ -446,6 +446,71 @@ static void att_read_type_req(struct bt_conn *conn, struct bt_buf *data)
att_read_type_rsp(conn, &uuid, start_handle, end_handle); att_read_type_rsp(conn, &uuid, start_handle, end_handle);
} }
struct read_data {
struct bt_conn *conn;
uint16_t offset;
struct bt_buf *buf;
struct bt_att_read_rsp *rsp;
};
static uint8_t read_cb(const struct bt_gatt_attr *attr, void *user_data)
{
struct read_data *data = user_data;
struct bt_att *att = data->conn->att;
int read;
BT_DBG("handle %u\n", attr->handle);
data->rsp = bt_buf_add(data->buf, sizeof(*data->rsp));
if (!attr->read) {
/* TODO: Respond with BT_ATT_ERR_READ_NOT_PERMITTED */
return BT_GATT_ITER_STOP;
}
/* Read attribute value and store in the buffer */
read = attr->read(attr, data->buf->data + data->buf->len,
att->mtu - data->buf->len, data->offset);
if (read < 0) {
/* TODO: Handle read error */
return BT_GATT_ITER_STOP;
}
bt_buf_add(data->buf, read);
return BT_GATT_ITER_CONTINUE;
}
static void att_read_rsp(struct bt_conn *conn, uint8_t op, uint8_t rsp,
uint16_t handle, uint16_t offset)
{
struct read_data data;
if (!handle) {
send_err_rsp(conn, op, 0, BT_ATT_ERR_INVALID_HANDLE);
return;
}
memset(&data, 0, sizeof(data));
data.buf = bt_att_create_pdu(conn, rsp, 0);
if (!data.buf) {
return;
}
data.offset = offset;
bt_gatt_foreach_attr(handle, handle, read_cb, &data);
if (!data.rsp) {
bt_buf_put(data.buf);
send_err_rsp(conn, op, handle, BT_ATT_ERR_INVALID_HANDLE);
return;
}
bt_l2cap_send(conn, BT_L2CAP_CID_ATT, data.buf);
}
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)
{ {
struct bt_att_read_req *req; struct bt_att_read_req *req;
@ -463,16 +528,7 @@ static void att_read_req(struct bt_conn *conn, struct bt_buf *data)
BT_DBG("handle %u\n", handle); BT_DBG("handle %u\n", handle);
if (!handle) { att_read_rsp(conn, BT_ATT_OP_READ_REQ, BT_ATT_OP_READ_RSP, handle, 0);
send_err_rsp(conn, BT_ATT_OP_READ_REQ, 0,
BT_ATT_ERR_INVALID_HANDLE);
return;
}
/* TODO: Generate proper response once a database is defined */
send_err_rsp(conn, BT_ATT_OP_READ_REQ, handle,
BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
} }
static void att_read_blob_req(struct bt_conn *conn, struct bt_buf *data) static void att_read_blob_req(struct bt_conn *conn, struct bt_buf *data)
@ -493,10 +549,8 @@ static void att_read_blob_req(struct bt_conn *conn, struct bt_buf *data)
BT_DBG("handle %u offset %u\n", handle, offset); BT_DBG("handle %u offset %u\n", handle, offset);
/* TODO: Generate proper response once a database is defined */ att_read_rsp(conn, BT_ATT_OP_READ_BLOB_REQ, BT_ATT_OP_READ_BLOB_RSP,
handle, offset);
send_err_rsp(conn, BT_ATT_OP_READ_BLOB_REQ, handle,
BT_ATT_ERR_INVALID_HANDLE);
} }
static void att_read_mult_req(struct bt_conn *conn, struct bt_buf *data) static void att_read_mult_req(struct bt_conn *conn, struct bt_buf *data)