2024-03-27 15:25:31

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ v1] monitor/att: Add support for decoding GATT Long Reads

From: Luiz Augusto von Dentz <[email protected]>

This adds support for decoding GATT Long Reads:

< ACL Data TX: Handle 3585 flags 0x00 dlen 7
ATT: Read Request (0x0a) len 2
Handle: 0x0028 Type: Report Map (0x2a4b)
> ACL Data RX: Handle 3585 flags 0x02 dlen 27
ATT: Read Response (0x0b) len 22
Value[22]: 05010902a10185020901a10095107501150025010509
Long Value[22]: 05010902a10185020901a10095107501150025010509
< ACL Data TX: Handle 3585 flags 0x00 dlen 9
ATT: Read Blob Request (0x0c) len 4
Handle: 0x0028 Type: Report Map (0x2a4b)
Offset: 0x0016
> ACL Data RX: Handle 3585 flags 0x02 dlen 27
ATT: Read Blob Response (0x0d) len 22
Value[22]: 19012910810205011601f826ff07750c950209300931
Long Value[44]: 05010902a10185020901a1009510750115002501050919
012910810205011601f826ff07750c950209300931
< ACL Data TX: Handle 3585 flags 0x00 dlen 9
ATT: Read Blob Request (0x0c) len 4
Handle: 0x0028 Type: Report Map (0x2a4b)
Offset: 0x002c
> ACL Data RX: Handle 3585 flags 0x02 dlen 27
ATT: Read Blob Response (0x0d) len 22
Value[22]: 81061581257f75089501093881069501050c0a380281
Long Value[66]: 05010902a10185020901a1009510750115002501050919
012910810205011601f826ff07750c9502093009318106
1581257f75089501
< ACL Data TX: Handle 3585 flags 0x00 dlen 9
ATT: Read Blob Request (0x0c) len 4
Handle: 0x0028 Type: Report Map (0x2a4b)
Offset: 0x0042
> ACL Data RX: Handle 3585 flags 0x02 dlen 27
ATT: Read Blob Response (0x0d) len 22
Value[22]: 06c0c00643ff0a0202a101851175089513150026ff00
Long Value[88]: 05010902a10185020901a1009510750115002501050919
012910810205011601f826ff07750c9502093009318106
1581257f75089501093881069501050c0a38028106c0c0
0643ff0a0202a101851175089513150026ff00
< ACL Data TX: Handle 3585 flags 0x00 dlen 9
ATT: Read Blob Request (0x0c) len 4
Handle: 0x0028 Type: Report Map (0x2a4b)
Offset: 0x0058
> ACL Data RX: Handle 3585 flags 0x02 dlen 14
ATT: Read Blob Response (0x0d) len 9
Value[9]: 0902810009029100c0
Handle: 0x0028 Type: Report Map (0x2a4b)
Value[97]: 05010902a10185020901a1009510750115002501050919
012910810205011601f826ff07750c9502093009318106
1581257f75089501093881069501050c0a38028106c0c0
0643ff0a0202a101851175089513150026ff0009028100
09029100c0
---
monitor/att.c | 125 +++++++++++++++++++++++++++++++++++++++-------
monitor/display.h | 2 +-
2 files changed, 108 insertions(+), 19 deletions(-)

diff --git a/monitor/att.c b/monitor/att.c
index 4628db44b139..3e5d7f12d182 100644
--- a/monitor/att.c
+++ b/monitor/att.c
@@ -46,10 +46,12 @@
#include "keys.h"

struct att_read {
+ struct att_conn_data *conn;
struct gatt_db_attribute *attr;
bool in;
uint16_t chan;
void (*func)(const struct l2cap_frame *frame);
+ struct iovec *iov;
};

struct att_conn_data {
@@ -58,6 +60,7 @@ struct att_conn_data {
struct gatt_db *rdb;
struct timespec rdb_mtim;
struct queue *reads;
+ uint16_t mtu;
};

static void print_uuid(const char *label, const void *data, uint16_t size)
@@ -210,6 +213,15 @@ done:
print_field("Handle: 0x%4.4x", handle);
}

+static void att_read_free(struct att_read *read)
+{
+ if (!read)
+ return;
+
+ util_iov_free(read->iov, 1);
+ free(read);
+}
+
static void print_data_list(const char *label, uint8_t length,
const struct l2cap_frame *frame)
{
@@ -231,7 +243,7 @@ static void print_data_list(const char *label, uint8_t length,

print_hex_field("Value", frame->data, length - 2);

- if (read) {
+ if (read && read->func) {
struct l2cap_frame f;

l2cap_frame_clone_size(&f, frame, length - 2);
@@ -244,7 +256,7 @@ static void print_data_list(const char *label, uint8_t length,
}

packet_hexdump(frame->data, frame->size);
- free(read);
+ att_read_free(read);
}

static void print_attribute_info(uint16_t type, const void *data, uint16_t len)
@@ -370,7 +382,7 @@ static void att_error_response(const struct l2cap_frame *frame)
*/
if (pdu->request == 0x08 || pdu->request == 0x0a ||
pdu->request == 0x10)
- free(att_get_read(frame));
+ att_read_free(att_get_read(frame));
}

static const struct bitfield_data chrc_prop_table[] = {
@@ -4095,9 +4107,23 @@ static void att_exchange_mtu_req(const struct l2cap_frame *frame)

static void att_exchange_mtu_rsp(const struct l2cap_frame *frame)
{
- const struct bt_l2cap_att_exchange_mtu_rsp *pdu = frame->data;
+ struct packet_conn_data *conn;
+ struct att_conn_data *data;
+ uint16_t mtu;

- print_field("Server RX MTU: %d", le16_to_cpu(pdu->mtu));
+ if (!l2cap_frame_get_le16((void *)frame, &mtu)) {
+ print_text(COLOR_ERROR, " invalid size");
+ return;
+ }
+
+ print_field("Server RX MTU: %d", mtu);
+
+ conn = packet_get_conn_data(frame->handle);
+ data = att_get_conn_data(conn);
+ if (!data)
+ return;
+
+ data->mtu = mtu;
}

static void att_find_info_req(const struct l2cap_frame *frame)
@@ -4261,8 +4287,6 @@ static void queue_read(const struct l2cap_frame *frame, bt_uuid_t *uuid,
}

handler = attr ? get_handler(attr) : get_handler_uuid(uuid);
- if (!handler || !handler->read)
- return;

conn = packet_get_conn_data(frame->handle);
data = att_get_conn_data(conn);
@@ -4273,10 +4297,11 @@ static void queue_read(const struct l2cap_frame *frame, bt_uuid_t *uuid,
data->reads = queue_new();

read = new0(struct att_read, 1);
+ read->conn = data;
read->attr = attr;
read->in = frame->in;
read->chan = frame->chan;
- read->func = handler->read;
+ read->func = handler ? handler->read : NULL;

queue_push_tail(data->reads, read);
}
@@ -4334,31 +4359,95 @@ static void att_read_req(const struct l2cap_frame *frame)
queue_read(frame, NULL, handle);
}

+static void att_read_append(struct att_read *read,
+ const struct l2cap_frame *frame)
+{
+ if (!read->iov)
+ read->iov = new0(struct iovec, 1);
+ util_iov_append(read->iov, frame->data, frame->size);
+}
+
+static void att_read_func(struct att_read *read,
+ const struct l2cap_frame *frame)
+{
+ att_read_append(read, frame);
+
+ print_attribute(read->attr);
+ print_hex_field("Value", read->iov->iov_base, read->iov->iov_len);
+
+ if (read->func) {
+ struct l2cap_frame f = *frame;
+
+ f.data = read->iov->iov_base;
+ f.size = read->iov->iov_len;
+
+ read->func(&f);
+ }
+
+ att_read_free(read);
+}
+
static void att_read_rsp(const struct l2cap_frame *frame)
{
struct att_read *read;

+ print_hex_field("Value", frame->data, frame->size);
+
read = att_get_read(frame);
if (!read)
return;

- print_attribute(read->attr);
- print_hex_field("Value", frame->data, frame->size);
+ /* Check if the data size is equal to the MTU then read long procedure
+ * maybe used.
+ */
+ if (frame->size == read->conn->mtu - 1) {
+ att_read_append(read, frame);
+ print_hex_field("Long Value", read->iov->iov_base,
+ read->iov->iov_len);
+ queue_push_head(read->conn->reads, read);
+ return;
+ }

- read->func(frame);
-
- free(read);
+ att_read_func(read, frame);
}

static void att_read_blob_req(const struct l2cap_frame *frame)
{
- print_handle(frame, get_le16(frame->data), false);
- print_field("Offset: 0x%4.4x", get_le16(frame->data + 2));
+ uint16_t handle, offset;
+ struct att_read *read;
+
+ if (!l2cap_frame_get_le16((void *)frame, &handle)) {
+ print_text(COLOR_ERROR, "invalid size");
+ return;
+ }
+
+ if (!l2cap_frame_get_le16((void *)frame, &offset)) {
+ print_text(COLOR_ERROR, "invalid size");
+ return;
+ }
+
+ print_handle(frame, handle, false);
+ print_field("Offset: 0x%4.4x", offset);
+
+ read = att_get_read(frame);
+ if (!read)
+ return;
+
+ /* Check if attribute handle and offset match so the read object shall
+ * be keeped.
+ */
+ if (gatt_db_attribute_get_handle(read->attr) == handle &&
+ offset == read->iov->iov_len) {
+ queue_push_head(read->conn->reads, read);
+ return;
+ }
+
+ att_read_func(read, frame);
}

static void att_read_blob_rsp(const struct l2cap_frame *frame)
{
- packet_hexdump(frame->data, frame->size);
+ att_read_rsp(frame);
}

static void att_read_multiple_req(const struct l2cap_frame *frame)
@@ -4403,7 +4492,7 @@ static void print_group_list(const char *label, uint8_t length,
print_handle_range("Handle range", frame->data);
print_uuid("UUID", frame->data + 4, length - 4);

- if (read) {
+ if (read && read->func) {
struct l2cap_frame f;

l2cap_frame_clone_size(&f, frame, length);
@@ -4416,7 +4505,7 @@ static void print_group_list(const char *label, uint8_t length,
}

packet_hexdump(frame->data, frame->size);
- free(read);
+ att_read_free(read);
}

static void att_read_group_type_rsp(const struct l2cap_frame *frame)
diff --git a/monitor/display.h b/monitor/display.h
index 5a82f8e6fd93..ee076448cc31 100644
--- a/monitor/display.h
+++ b/monitor/display.h
@@ -87,7 +87,7 @@ static inline void print_hex_field(const char *label, const uint8_t *data,
for (i = 0; i < len; i++)
sprintf(str + (i * 2), "%2.2x", data[i]);

- print_field("%s: %s", label, str);
+ print_field("%s[%u]: %s", label, len, str);
}

void set_default_pager_num_columns(int num_columns);
--
2.44.0



2024-03-27 16:40:35

by bluez.test.bot

[permalink] [raw]
Subject: RE: [BlueZ,v1] monitor/att: Add support for decoding GATT Long Reads

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=838923

---Test result---

Test Summary:
CheckPatch PASS 0.37 seconds
GitLint PASS 0.20 seconds
BuildEll PASS 24.24 seconds
BluezMake PASS 1703.79 seconds
MakeCheck PASS 12.85 seconds
MakeDistcheck PASS 180.49 seconds
CheckValgrind PASS 248.42 seconds
CheckSmatch WARNING 350.76 seconds
bluezmakeextell PASS 121.56 seconds
IncrementalBuild PASS 1460.36 seconds
ScanBuild PASS 1006.26 seconds

Details
##############################
Test: CheckSmatch - WARNING
Desc: Run smatch tool with source
Output:
monitor/att.c: note: in included file:monitor/display.h:82:26: warning: Variable length array is used.


---
Regards,
Linux Bluetooth

2024-03-28 14:40:47

by patchwork-bot+bluetooth

[permalink] [raw]
Subject: Re: [PATCH BlueZ v1] monitor/att: Add support for decoding GATT Long Reads

Hello:

This patch was applied to bluetooth/bluez.git (master)
by Luiz Augusto von Dentz <[email protected]>:

On Wed, 27 Mar 2024 11:07:27 -0400 you wrote:
> From: Luiz Augusto von Dentz <[email protected]>
>
> This adds support for decoding GATT Long Reads:
>
> < ACL Data TX: Handle 3585 flags 0x00 dlen 7
> ATT: Read Request (0x0a) len 2
> Handle: 0x0028 Type: Report Map (0x2a4b)
> > ACL Data RX: Handle 3585 flags 0x02 dlen 27
> ATT: Read Response (0x0b) len 22
> Value[22]: 05010902a10185020901a10095107501150025010509
> Long Value[22]: 05010902a10185020901a10095107501150025010509
> < ACL Data TX: Handle 3585 flags 0x00 dlen 9
> ATT: Read Blob Request (0x0c) len 4
> Handle: 0x0028 Type: Report Map (0x2a4b)
> Offset: 0x0016
> > ACL Data RX: Handle 3585 flags 0x02 dlen 27
> ATT: Read Blob Response (0x0d) len 22
> Value[22]: 19012910810205011601f826ff07750c950209300931
> Long Value[44]: 05010902a10185020901a1009510750115002501050919
> 012910810205011601f826ff07750c950209300931
> < ACL Data TX: Handle 3585 flags 0x00 dlen 9
> ATT: Read Blob Request (0x0c) len 4
> Handle: 0x0028 Type: Report Map (0x2a4b)
> Offset: 0x002c
> > ACL Data RX: Handle 3585 flags 0x02 dlen 27
> ATT: Read Blob Response (0x0d) len 22
> Value[22]: 81061581257f75089501093881069501050c0a380281
> Long Value[66]: 05010902a10185020901a1009510750115002501050919
> 012910810205011601f826ff07750c9502093009318106
> 1581257f75089501
> < ACL Data TX: Handle 3585 flags 0x00 dlen 9
> ATT: Read Blob Request (0x0c) len 4
> Handle: 0x0028 Type: Report Map (0x2a4b)
> Offset: 0x0042
> > ACL Data RX: Handle 3585 flags 0x02 dlen 27
> ATT: Read Blob Response (0x0d) len 22
> Value[22]: 06c0c00643ff0a0202a101851175089513150026ff00
> Long Value[88]: 05010902a10185020901a1009510750115002501050919
> 012910810205011601f826ff07750c9502093009318106
> 1581257f75089501093881069501050c0a38028106c0c0
> 0643ff0a0202a101851175089513150026ff00
> < ACL Data TX: Handle 3585 flags 0x00 dlen 9
> ATT: Read Blob Request (0x0c) len 4
> Handle: 0x0028 Type: Report Map (0x2a4b)
> Offset: 0x0058
> > ACL Data RX: Handle 3585 flags 0x02 dlen 14
> ATT: Read Blob Response (0x0d) len 9
> Value[9]: 0902810009029100c0
> Handle: 0x0028 Type: Report Map (0x2a4b)
> Value[97]: 05010902a10185020901a1009510750115002501050919
> 012910810205011601f826ff07750c9502093009318106
> 1581257f75089501093881069501050c0a38028106c0c0
> 0643ff0a0202a101851175089513150026ff0009028100
> 09029100c0
>
> [...]

Here is the summary with links:
- [BlueZ,v1] monitor/att: Add support for decoding GATT Long Reads
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=cd22ff6a1fef

You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html