From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx> The Read Multiple Variable Length Request is used to request that the server read two or more values of a set of attributes that have a variable or unknown value length and return their values in a Read Multiple Variable Length Response. --- src/shared/gatt-client.c | 42 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c index 2c5fe14dc..5b6723f97 100644 --- a/src/shared/gatt-client.c +++ b/src/shared/gatt-client.c @@ -2642,7 +2642,9 @@ static void read_multiple_cb(uint8_t opcode, const void *pdu, uint16_t length, uint8_t att_ecode; bool success; - if (opcode != BT_ATT_OP_READ_MULT_RSP || (!pdu && length)) { + if ((opcode != BT_ATT_OP_READ_MULT_RSP && + opcode != BT_ATT_OP_READ_MULT_VL_RSP) || + (!pdu && length)) { success = false; if (opcode == BT_ATT_OP_ERROR_RSP) @@ -2657,8 +2659,36 @@ static void read_multiple_cb(uint8_t opcode, const void *pdu, uint16_t length, att_ecode = 0; } - if (op->callback) + if (!op->callback) + return; + + if (opcode == BT_ATT_OP_READ_MULT_RSP || att_ecode) { op->callback(success, att_ecode, pdu, length, op->user_data); + return; + } + + if (length < 2) { + op->callback(success, att_ecode, pdu, length, op->user_data); + return; + } + + /* Parse response */ + while (length >= 2) { + uint16_t len; + + len = get_le16(pdu); + length -= 2; + pdu += 2; + + /* The Length Value Tuple List may be truncated within the + * first two octets of a tuple due to the size limits of the + * current ATT_MTU. + */ + if (len > length) + length = len; + + op->callback(success, att_ecode, pdu, len, op->user_data); + } } unsigned int bt_gatt_client_read_multiple(struct bt_gatt_client *client, @@ -2670,6 +2700,7 @@ unsigned int bt_gatt_client_read_multiple(struct bt_gatt_client *client, uint8_t pdu[num_handles * 2]; struct request *req; struct read_op *op; + uint8_t opcode; int i; if (!client) @@ -2699,8 +2730,11 @@ unsigned int bt_gatt_client_read_multiple(struct bt_gatt_client *client, for (i = 0; i < num_handles; i++) put_le16(handles[i], pdu + (2 * i)); - req->att_id = bt_att_send(client->att, BT_ATT_OP_READ_MULT_REQ, - pdu, sizeof(pdu), + opcode = bt_gatt_client_get_features(client) & + BT_GATT_CHRC_CLI_FEAT_EATT ? BT_ATT_OP_READ_MULT_VL_REQ : + BT_ATT_OP_READ_MULT_REQ; + + req->att_id = bt_att_send(client->att, opcode, pdu, sizeof(pdu), read_multiple_cb, req, request_unref); if (!req->att_id) { -- 2.21.1