Bluetooth: Add ATT Read by Group Type Request skeleton

This adds the defines for Read by Group Type PDUs along with initial
code to parse them:

> ACL Data RX: Handle 3585 flags 0x02 dlen 11
      ATT: Read By Group Type Request (0x10) len 6
        Handle range: 0x0001-0xffff
        Attribute group type: Primary Service (0x2800)
< ACL Data TX: Handle 3585 flags 0x00 dlen 9
      ATT: Error Response (0x01) len 4
        Read By Group Type Request (0x10)
        Handle: 0x0001
        Error: Attribute Not Found (0x0a)

Change-Id: Iebc84e7a9c405fa58b7984602d2d27f79d6033a7
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
Luiz Augusto von Dentz 2015-05-07 13:57:46 +03:00 committed by Anas Nashif
commit 75aab47603
2 changed files with 82 additions and 0 deletions

View file

@ -338,6 +338,64 @@ static void att_read_mult_req(struct bt_conn *conn, struct bt_buf *data)
BT_ATT_ERR_INVALID_HANDLE); BT_ATT_ERR_INVALID_HANDLE);
} }
static void att_read_group_req(struct bt_conn *conn, struct bt_buf *data)
{
struct bt_att_read_group_req *req;
uint16_t start_handle, end_handle, err_handle;
struct bt_uuid uuid;
/* Type can only be UUID16 or UUID128 */
if (data->len != sizeof(*req) + sizeof(uuid.u16) &&
data->len != sizeof(*req) + sizeof(uuid.u128)) {
send_err_rsp(conn, BT_ATT_OP_READ_GROUP_REQ, 0,
BT_ATT_ERR_INVALID_PDU);
return;
}
req = (void *)data->data;
start_handle = sys_le16_to_cpu(req->start_handle);
end_handle = sys_le16_to_cpu(req->end_handle);
bt_buf_pull(data, sizeof(*req));
if (!uuid_create(&uuid, data->data, data->len)) {
send_err_rsp(conn, BT_ATT_OP_READ_GROUP_REQ, 0,
BT_ATT_ERR_UNLIKELY);
return;
}
BT_DBG("start_handle %u end_handle %u type %u\n",
start_handle, end_handle, uuid.u16);
if (!range_is_valid(start_handle, end_handle, &err_handle)) {
send_err_rsp(conn, BT_ATT_OP_FIND_TYPE_REQ, err_handle,
BT_ATT_ERR_INVALID_HANDLE);
return;
}
/* Core v4.2, Vol 3, sec 2.5.3 Attribute Grouping:
* Not all of the grouping attributes can be used in the ATT
* Read By Group Type Request. The «Primary Service» and «Secondary
* Service» grouping types may be used in the Read By Group Type
* Request. The «Characteristic» grouping type shall not be used in
* the ATT Read By Group Type Request.
*/
if (uuid.type == BT_UUID_16) {
if (uuid.u16 != 0x2800 && uuid.u16 != 0x2801) {
send_err_rsp(conn, BT_ATT_OP_READ_GROUP_REQ,
start_handle,
BT_ATT_ERR_UNSUPPORTED_GROUP_TYPE);
return;
}
} /* TODO: Add UUID helpers for UUID formats */
/* TODO: Generate proper response once a database is defined */
send_err_rsp(conn, BT_ATT_OP_READ_GROUP_REQ, start_handle,
BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
return;
}
void bt_att_recv(struct bt_conn *conn, struct bt_buf *buf) void bt_att_recv(struct bt_conn *conn, struct bt_buf *buf)
{ {
struct bt_att_hdr *hdr = (void *)buf->data; struct bt_att_hdr *hdr = (void *)buf->data;
@ -373,6 +431,9 @@ void bt_att_recv(struct bt_conn *conn, struct bt_buf *buf)
case BT_ATT_OP_READ_MULT_REQ: case BT_ATT_OP_READ_MULT_REQ:
att_read_mult_req(conn, buf); att_read_mult_req(conn, buf);
break; break;
case BT_ATT_OP_READ_GROUP_REQ:
att_read_group_req(conn, buf);
break;
default: default:
BT_DBG("Unhandled ATT code %u\n", hdr->code); BT_DBG("Unhandled ATT code %u\n", hdr->code);
send_err_rsp(conn, hdr->code, 0, BT_ATT_ERR_NOT_SUPPORTED); send_err_rsp(conn, hdr->code, 0, BT_ATT_ERR_NOT_SUPPORTED);

View file

@ -192,5 +192,26 @@ struct bt_att_read_mult_rsp {
uint8_t value[0]; uint8_t value[0];
} PACK_STRUCT; } PACK_STRUCT;
/* Read by Group Type Request */
#define BT_ATT_OP_READ_GROUP_REQ 0x10
struct bt_att_read_group_req {
uint16_t start_handle;
uint16_t end_handle;
uint8_t uuid[0];
} PACK_STRUCT;
struct bt_att_group_data {
uint16_t start_handle;
uint16_t end_handle;
uint8_t value[0];
} PACK_STRUCT;
/* Read by Group Type Response */
#define BT_ATT_OP_READ_GROUP_RSP 0x11
struct bt_att_read_group_rsp {
uint8_t len;
struct bt_att_group_data data[0];
} PACK_STRUCT;
void bt_att_recv(struct bt_conn *conn, struct bt_buf *buf); void bt_att_recv(struct bt_conn *conn, struct bt_buf *buf);
struct bt_buf *bt_att_create_pdu(struct bt_conn *conn, uint8_t op, size_t len); struct bt_buf *bt_att_create_pdu(struct bt_conn *conn, uint8_t op, size_t len);