Bluetooth: GATT: Fix not parsing result of Read by Type
When using the procedure Read By Type the response may contain multiple instances so it needs to be parsed properly. When dealing with long values only the beggining will be read, for the remaining bytes the application should issue another bt_gatt_read with offset so Read Blob procedure is used as recommended by the spec: BLUETOOTH CORE SPECIFICATION Version 5.1 | Vol 3, Part F page 2312: The Read Blob Request would be used to read the remaining octets of a long attribute value. Fixes #16107 Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
fc3270d09c
commit
852b1dca55
2 changed files with 58 additions and 0 deletions
|
@ -1029,6 +1029,14 @@ struct bt_gatt_read_params {
|
|||
*
|
||||
* This procedure read the attribute value and return it to the callback.
|
||||
*
|
||||
* When reading attributes by UUID the callback can be called multiple times
|
||||
* depending on how many instances of given the UUID exists with the
|
||||
* start_handle being updated for each instance.
|
||||
*
|
||||
* If an instance does contain a long value which cannot be read entirely the
|
||||
* caller will need to read the remaining data separately using the handle and
|
||||
* offset.
|
||||
*
|
||||
* Note: This procedure is asynchronous therefore the parameters need to
|
||||
* remains valid while it is active.
|
||||
*
|
||||
|
|
|
@ -2490,6 +2490,51 @@ int bt_gatt_discover(struct bt_conn *conn,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void parse_read_by_uuid(struct bt_conn *conn,
|
||||
struct bt_gatt_read_params *params,
|
||||
const void *pdu, u16_t length)
|
||||
{
|
||||
const struct bt_att_read_type_rsp *rsp = pdu;
|
||||
|
||||
/* Parse values found */
|
||||
for (length--, pdu = rsp->data; length;
|
||||
length -= rsp->len, pdu = (const u8_t *)pdu + rsp->len) {
|
||||
const struct bt_att_data *data = pdu;
|
||||
u16_t handle;
|
||||
u8_t len;
|
||||
|
||||
handle = sys_le16_to_cpu(data->handle);
|
||||
|
||||
/* Handle 0 is invalid */
|
||||
if (!handle) {
|
||||
BT_ERR("Invalid handle");
|
||||
return;
|
||||
}
|
||||
|
||||
len = rsp->len > length ? length - 2 : rsp->len - 2;
|
||||
|
||||
BT_DBG("handle 0x%04x len %u value %u", handle, rsp->len, len);
|
||||
|
||||
/* Update start_handle */
|
||||
params->by_uuid.start_handle = handle;
|
||||
|
||||
if (params->func(conn, 0, params, data->value, len) ==
|
||||
BT_GATT_ITER_STOP) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if long attribute */
|
||||
if (rsp->len > length) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Continue reading the attributes */
|
||||
if (bt_gatt_read(conn, params) < 0) {
|
||||
params->func(conn, BT_ATT_ERR_UNLIKELY, params, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void gatt_read_rsp(struct bt_conn *conn, u8_t err, const void *pdu,
|
||||
u16_t length, void *user_data)
|
||||
{
|
||||
|
@ -2502,6 +2547,11 @@ static void gatt_read_rsp(struct bt_conn *conn, u8_t err, const void *pdu,
|
|||
return;
|
||||
}
|
||||
|
||||
if (!params->handle_count) {
|
||||
parse_read_by_uuid(conn, params, pdu, length);
|
||||
return;
|
||||
}
|
||||
|
||||
if (params->func(conn, 0, params, pdu, length) == BT_GATT_ITER_STOP) {
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue