Skip to content

Commit 0f01fe7

Browse files
Vudentznashif
authored andcommitted
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 <[email protected]>
1 parent fb199a2 commit 0f01fe7

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

include/bluetooth/gatt.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,6 +1002,14 @@ struct bt_gatt_read_params {
10021002
*
10031003
* This procedure read the attribute value and return it to the callback.
10041004
*
1005+
* When reading attributes by UUID the callback can be called multiple times
1006+
* depending on how many instances of given the UUID exists with the
1007+
* start_handle being updated for each instance.
1008+
*
1009+
* If an instance does contain a long value which cannot be read entirely the
1010+
* caller will need to read the remaining data separately using the handle and
1011+
* offset.
1012+
*
10051013
* Note: This procedure is asynchronous therefore the parameters need to
10061014
* remains valid while it is active.
10071015
*

subsys/bluetooth/host/gatt.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2378,6 +2378,51 @@ int bt_gatt_discover(struct bt_conn *conn,
23782378
return -EINVAL;
23792379
}
23802380

2381+
static void parse_read_by_uuid(struct bt_conn *conn,
2382+
struct bt_gatt_read_params *params,
2383+
const void *pdu, u16_t length)
2384+
{
2385+
const struct bt_att_read_type_rsp *rsp = pdu;
2386+
2387+
/* Parse values found */
2388+
for (length--, pdu = rsp->data; length;
2389+
length -= rsp->len, pdu = (const u8_t *)pdu + rsp->len) {
2390+
const struct bt_att_data *data = pdu;
2391+
u16_t handle;
2392+
u8_t len;
2393+
2394+
handle = sys_le16_to_cpu(data->handle);
2395+
2396+
/* Handle 0 is invalid */
2397+
if (!handle) {
2398+
BT_ERR("Invalid handle");
2399+
return;
2400+
}
2401+
2402+
len = rsp->len > length ? length - 2 : rsp->len - 2;
2403+
2404+
BT_DBG("handle 0x%04x len %u value %u", handle, rsp->len, len);
2405+
2406+
/* Update start_handle */
2407+
params->by_uuid.start_handle = handle;
2408+
2409+
if (params->func(conn, 0, params, data->value, len) ==
2410+
BT_GATT_ITER_STOP) {
2411+
return;
2412+
}
2413+
2414+
/* Check if long attribute */
2415+
if (rsp->len > length) {
2416+
break;
2417+
}
2418+
}
2419+
2420+
/* Continue reading the attributes */
2421+
if (bt_gatt_read(conn, params) < 0) {
2422+
params->func(conn, BT_ATT_ERR_UNLIKELY, params, NULL, 0);
2423+
}
2424+
}
2425+
23812426
static void gatt_read_rsp(struct bt_conn *conn, u8_t err, const void *pdu,
23822427
u16_t length, void *user_data)
23832428
{
@@ -2390,6 +2435,11 @@ static void gatt_read_rsp(struct bt_conn *conn, u8_t err, const void *pdu,
23902435
return;
23912436
}
23922437

2438+
if (!params->handle_count) {
2439+
parse_read_by_uuid(conn, params, pdu, length);
2440+
return;
2441+
}
2442+
23932443
if (params->func(conn, 0, params, pdu, length) == BT_GATT_ITER_STOP) {
23942444
return;
23952445
}

0 commit comments

Comments
 (0)