2023-05-05 20:33:38

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 1/2] monitor/att: Attempt to insert discovered attributes

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

This attempts to insert discovered attributes into monitor gatt_db
instance if their respective discover procedures are used which enables
decoding traces injected by user via unit testing:

> sudo unit/test-bap -m -s "34

= test-bap: BAP/UCL/SCC/BV-034-C [UCL SNK Config Codec, VS] - run
> test-bap: User Data RX
ATT: Read Request (0x0a) len 2
Handle: 0x0003 Type: Sink PAC (0x2bc9)
< test-bap: User Data TX
ATT: Read Response (0x0b) len 8
Handle: 0x0003 Type: Sink PAC (0x2bc9)
Value: 01ff010001000000
Number of PAC(s): 1
PAC #0:
Codec: Vendor specific (0xff)
Codec Company ID: Nokia Mobile Phones (0x0001)
Codec Vendor ID: 0x0001
> test-bap: User Data RX
ATT: Read Request (0x0a) len 2
Handle: 0x0006 Type: Sink Audio Locations (0x2bca)
< test-bap: User Data TX
ATT: Read Response (0x0b) len 4
Handle: 0x0006 Type: Sink Audio Locations (0x2bca)
Value: 03000000
Location: 0x00000003
Front Left (0x00000001)
Front Right (0x00000002)
> test-bap: User Data RX
ATT: Read Request (0x0a) len 2
Handle: 0x0009 Type: Source PAC (0x2bcb)
< test-bap: User Data TX
ATT: Read Response (0x0b) len 8
Handle: 0x0009 Type: Source PAC (0x2bcb)
Value: 01ff010001000000
Number of PAC(s): 1
PAC #0:
Codec: Vendor specific (0xff)
Codec Company ID: Nokia Mobile Phones (0x0001)
Codec Vendor ID: 0x0001
> test-bap: User Data RX
ATT: Read Request (0x0a) len 2
Handle: 0x000c Type: Source Audio Locations (0x2bcc)
< test-bap: User Data TX
ATT: Read Response (0x0b) len 4
Handle: 0x000c Type: Source Audio Locations (0x2bcc)
Value: 03000000
Location: 0x00000003
Front Left (0x00000001)
Front Right (0x00000002)
> test-bap: User Data RX
ATT: Read Request (0x0a) len 2
Handle: 0x000f Type: Available Audio Contexts (0x2bcd)
< test-bap: User Data TX
ATT: Read Response (0x0b) len 4
Handle: 0x000f Type: Available Audio Contexts (0x2bcd)
Value: ff0f0e00
Sink Context: 0x0fff
Unspecified (0x0001)
Conversational (0x0002)
Media (0x0004)
Game (0x0008)
Instructional (0x0010)
Voice Assistants (0x0020)
Live (0x0040)
Sound Effects (0x0080)
Notifications (0x0100)
Ringtone (0x0200)
Alerts (0x0400)
Emergency alarm (0x0800)
Source Context: 0x000e
Conversational (0x0002)
Media (0x0004)
Game (0x0008)
> test-bap: User Data RX
ATT: Read Request (0x0a) len 2
Handle: 0x0012 Type: Supported Audio Contexts (0x2bce)
< test-bap: User Data TX
ATT: Read Response (0x0b) len 4
Handle: 0x0012 Type: Supported Audio Contexts (0x2bce)
Value: ff0f0e00
Sink Context: 0x0fff
Unspecified (0x0001)
Conversational (0x0002)
Media (0x0004)
Game (0x0008)
Instructional (0x0010)
Voice Assistants (0x0020)
Live (0x0040)
Sound Effects (0x0080)
Notifications (0x0100)
Ringtone (0x0200)
Alerts (0x0400)
Emergency alarm (0x0800)
Source Context: 0x000e
Conversational (0x0002)
Media (0x0004)
Game (0x0008)
> test-bap: User Data RX
ATT: Read Request (0x0a) len 2
Handle: 0x0016 Type: Sink ASE (0x2bc4)
< test-bap: User Data TX
ATT: Read Response (0x0b) len 2
Handle: 0x0016 Type: Sink ASE (0x2bc4)
Value: 0100
ASE ID: 1
State: Idle (0x00)
> test-bap: User Data RX
ATT: Write Request (0x12) len 4
Handle: 0x0017
Data: 0100
< test-bap: User Data TX
ATT: Write Response (0x13) len 0
> test-bap: User Data RX
ATT: Read Request (0x0a) len 2
Handle: 0x0019 Type: Sink ASE (0x2bc4)
< test-bap: User Data TX
ATT: Read Response (0x0b) len 2
Handle: 0x0019 Type: Sink ASE (0x2bc4)
Value: 0200
ASE ID: 2
State: Idle (0x00)
> test-bap: User Data RX
ATT: Write Request (0x12) len 4
Handle: 0x001a
Data: 0100
< test-bap: User Data TX
ATT: Write Response (0x13) len 0
> test-bap: User Data RX
ATT: Read Request (0x0a) len 2
Handle: 0x001c Type: Source ASE (0x2bc5)
< test-bap: User Data TX
ATT: Read Response (0x0b) len 2
Handle: 0x001c Type: Source ASE (0x2bc5)
Value: 0300
ASE ID: 3
State: Idle (0x00)
> test-bap: User Data RX
ATT: Write Request (0x12) len 4
Handle: 0x001d
Data: 0100
< test-bap: User Data TX
ATT: Write Response (0x13) len 0
> test-bap: User Data RX
ATT: Read Request (0x0a) len 2
Handle: 0x001f Type: Source ASE (0x2bc5)
< test-bap: User Data TX
ATT: Read Response (0x0b) len 2
Handle: 0x001f Type: Source ASE (0x2bc5)
Value: 0400
ASE ID: 4
State: Idle (0x00)
> test-bap: User Data RX
ATT: Write Request (0x12) len 4
Handle: 0x0020
Data: 0100
< test-bap: User Data TX
ATT: Write Response (0x13) len 0
> test-bap: User Data RX
ATT: Write Request (0x12) len 4
Handle: 0x0023
Data: 0100
< test-bap: User Data TX
ATT: Write Response (0x13) len 0
> test-bap: User Data RX
ATT: Write Command (0x52) len 13
Handle: 0x0022 Type: ASE Control Point (0x2bc6)
Data: 0101030202ff0100010000
Opcode: Codec Configuration (0x01)
Number of ASE(s): 1
ASE: #0
ASE ID: 0x03
Target Latency: Balance Latency/Reliability (0x02)
PHY: 0x02
LE 2M PHY (0x02)
Codec: Vendor specific (0xff)
Codec Company ID: Nokia Mobile Phones (0x0001)
Codec Vendor ID: 0x0001
< test-bap: User Data TX
ATT: Handle Value Notification (0x1b) len 7
Handle: 0x0022 Type: ASE Control Point (0x2bc6)
Data: 0101030000
Opcode: Codec Configuration (0x01)
Number of ASE(s): 1
ASE: #0
ASE ID: 0x03
ASE Response Code: Success (0x00)
ASE Response Reason: None (0x00)
< test-bap: User Data TX
ATT: Handle Value Notification (0x1b) len 27
Handle: 0x001c Type: Source ASE (0x2bc5)
Data: 03010102010a00204e00409c00204e00409c00ff0100010000
ASE ID: 3
State: Codec Configured (0x01)
Framing: Unframed PDUs not supported (0x01)
PHY: 0x02
LE 2M PHY preffered (0x02)
RTN: 1
Max Transport Latency: 10
Presentation Delay Min: 20000 us
Presentation Delay Max: 40000 us
Preferred Presentation Delay Min: 20000 us
Preferred Presentation Delay Max: 40000 us
Codec: Vendor specific (0xff)
Codec Company ID: Nokia Mobile Phones (0x0001)
Codec Vendor ID: 0x0001
---
monitor/att.c | 538 ++++++++++++++++++++++++++++++++------------------
1 file changed, 345 insertions(+), 193 deletions(-)

diff --git a/monitor/att.c b/monitor/att.c
index e67887861448..0e12ee352078 100644
--- a/monitor/att.c
+++ b/monitor/att.c
@@ -365,10 +365,11 @@ static void att_error_response(const struct l2cap_frame *frame)
print_field("Handle: 0x%4.4x", le16_to_cpu(pdu->handle));
print_field("Error: %s (0x%2.2x)", str, pdu->error);

- /* Read/Read By Type may create a read object which needs to be dequeued
- * and freed in case the operation fails.
+ /* Read/Read By Type/Read By Group Type may create a read object which
+ * needs to be dequeued and freed in case the operation fails.
*/
- if (pdu->request == 0x08 || pdu->request == 0x0a)
+ if (pdu->request == 0x08 || pdu->request == 0x0a ||
+ pdu->request == 0x10)
free(att_get_read(frame));
}

@@ -384,10 +385,202 @@ static const struct bitfield_data chrc_prop_table[] = {
{ }
};

+static void att_conn_data_free(void *data)
+{
+ struct att_conn_data *att_data = data;
+
+ gatt_db_unref(att_data->rdb);
+ gatt_db_unref(att_data->ldb);
+ queue_destroy(att_data->reads, free);
+ free(att_data);
+}
+
+static struct att_conn_data *att_get_conn_data(struct packet_conn_data *conn)
+{
+ struct att_conn_data *data;
+
+ if (!conn)
+ return NULL;
+
+ data = conn->data;
+
+ if (data)
+ return data;
+
+ data = new0(struct att_conn_data, 1);
+ data->rdb = gatt_db_new();
+ data->ldb = gatt_db_new();
+ conn->data = data;
+ conn->destroy = att_conn_data_free;
+
+ return data;
+}
+
+static void gatt_load_db(struct gatt_db *db, const char *filename,
+ struct timespec *mtim)
+{
+ struct stat st;
+
+ if (lstat(filename, &st))
+ return;
+
+ if (!gatt_db_isempty(db)) {
+ /* Check if file has been modified since last time */
+ if (st.st_mtim.tv_sec == mtim->tv_sec &&
+ st.st_mtim.tv_nsec == mtim->tv_nsec)
+ return;
+ /* Clear db before reloading */
+ gatt_db_clear(db);
+ }
+
+ *mtim = st.st_mtim;
+
+ btd_settings_gatt_db_load(db, filename);
+}
+
+static void load_gatt_db(struct packet_conn_data *conn)
+{
+ struct att_conn_data *data = att_get_conn_data(conn);
+ char filename[PATH_MAX];
+ char local[18];
+ char peer[18];
+ uint8_t id[6], id_type;
+
+ ba2str((bdaddr_t *)conn->src, local);
+
+ if (keys_resolve_identity(conn->dst, id, &id_type))
+ ba2str((bdaddr_t *)id, peer);
+ else
+ ba2str((bdaddr_t *)conn->dst, peer);
+
+ create_filename(filename, PATH_MAX, "/%s/attributes", local);
+ gatt_load_db(data->ldb, filename, &data->ldb_mtim);
+
+ create_filename(filename, PATH_MAX, "/%s/cache/%s", local, peer);
+ gatt_load_db(data->rdb, filename, &data->rdb_mtim);
+}
+
+static struct gatt_db *get_db(const struct l2cap_frame *frame, bool rsp)
+{
+ struct packet_conn_data *conn;
+ struct att_conn_data *data;
+ struct gatt_db *db;
+
+ conn = packet_get_conn_data(frame->handle);
+ if (!conn)
+ return NULL;
+
+ /* Try loading local and remote gatt_db if not loaded yet */
+ load_gatt_db(conn);
+
+ data = conn->data;
+ if (!data)
+ return NULL;
+
+ if (frame->in) {
+ if (rsp)
+ db = data->rdb;
+ else
+ db = data->ldb;
+ } else {
+ if (rsp)
+ db = data->ldb;
+ else
+ db = data->rdb;
+ }
+
+ return db;
+}
+
+static struct gatt_db_attribute *insert_chrc(const struct l2cap_frame *frame,
+ uint16_t handle,
+ bt_uuid_t *uuid, uint8_t prop,
+ bool rsp)
+{
+ struct gatt_db *db;
+
+ db = get_db(frame, rsp);
+ if (!db)
+ return NULL;
+
+ return gatt_db_insert_characteristic(db, handle, uuid, 0, prop, NULL,
+ NULL, NULL);
+}
+
+static int bt_uuid_from_data(bt_uuid_t *uuid, const void *data, uint16_t size)
+{
+ uint128_t u128;
+
+ if (!uuid)
+ return -EINVAL;
+
+ switch (size) {
+ case 2:
+ return bt_uuid16_create(uuid, get_le16(data));
+ case 4:
+ return bt_uuid32_create(uuid, get_le32(data));
+ case 16:
+ memcpy(u128.data, data, sizeof(u128.data));
+ return bt_uuid128_create(uuid, u128);
+ }
+
+ return -EINVAL;
+}
+
+static bool svc_read(const struct l2cap_frame *frame, uint16_t *start,
+ uint16_t *end, bt_uuid_t *uuid)
+{
+ if (!l2cap_frame_get_le16((void *)frame, start))
+ return false;
+
+ if (!l2cap_frame_get_le16((void *)frame, end))
+ return false;
+
+ return !bt_uuid_from_data(uuid, frame->data, frame->size);
+}
+
+static struct gatt_db_attribute *insert_svc(const struct l2cap_frame *frame,
+ uint16_t handle,
+ bt_uuid_t *uuid, bool primary,
+ bool rsp, uint16_t num_handles)
+{
+ struct gatt_db *db;
+
+ db = get_db(frame, rsp);
+ if (!db)
+ return NULL;
+
+ return gatt_db_insert_service(db, handle, uuid, primary, num_handles);
+}
+
+static void pri_svc_read(const struct l2cap_frame *frame)
+{
+ uint16_t start, end;
+ bt_uuid_t uuid;
+
+ if (!svc_read(frame, &start, &end, &uuid))
+ return;
+
+ insert_svc(frame, start, &uuid, true, true, end - start + 1);
+}
+
+static void sec_svc_read(const struct l2cap_frame *frame)
+{
+ uint16_t start, end;
+ bt_uuid_t uuid;
+
+ if (!svc_read(frame, &start, &end, &uuid))
+ return;
+
+ insert_svc(frame, start, &uuid, true, false, end - start + 1);
+}
+
static void print_chrc(const struct l2cap_frame *frame)
{
uint8_t prop;
uint8_t mask;
+ uint16_t handle;
+ bt_uuid_t uuid;

if (!l2cap_frame_get_u8((void *)frame, &prop)) {
print_text(COLOR_ERROR, "Property: invalid size");
@@ -401,10 +594,16 @@ static void print_chrc(const struct l2cap_frame *frame)
print_text(COLOR_WHITE_BG, " Unknown fields (0x%2.2x)",
mask);

- if (!l2cap_frame_print_le16((void *)frame, " Value Handle"))
+ if (!l2cap_frame_get_le16((void *)frame, &handle)) {
+ print_text(COLOR_ERROR, " Value Handle: invalid size");
return;
+ }

+ print_field(" Value Handle: 0x%4.4x", handle);
print_uuid(" Value UUID", frame->data, frame->size);
+ bt_uuid_from_data(&uuid, frame->data, frame->size);
+
+ insert_chrc(frame, handle, &uuid, prop, true);
}

static void chrc_read(const struct l2cap_frame *frame)
@@ -2988,6 +3187,8 @@ struct gatt_handler {
void (*write)(const struct l2cap_frame *frame);
void (*notify)(const struct l2cap_frame *frame);
} gatt_handlers[] = {
+ GATT_HANDLER(0x2800, pri_svc_read, NULL, NULL),
+ GATT_HANDLER(0x2801, sec_svc_read, NULL, NULL),
GATT_HANDLER(0x2803, chrc_read, NULL, NULL),
GATT_HANDLER(0x2902, ccc_read, ccc_write, NULL),
GATT_HANDLER(0x2bc4, ase_read, NULL, ase_notify),
@@ -3035,6 +3236,9 @@ static struct gatt_handler *get_handler_uuid(const bt_uuid_t *uuid)
{
size_t i;

+ if (!uuid)
+ return NULL;
+
for (i = 0; i < ARRAY_SIZE(gatt_handlers); i++) {
struct gatt_handler *handler = &gatt_handlers[i];

@@ -3081,45 +3285,96 @@ static const char *att_format_str(uint8_t format)
}
}

-static uint16_t print_info_data_16(const void *data, uint16_t len)
+static struct gatt_db_attribute *insert_desc(const struct l2cap_frame *frame,
+ uint16_t handle,
+ bt_uuid_t *uuid, bool rsp)
{
- while (len >= 4) {
- print_field("Handle: 0x%4.4x", get_le16(data));
- print_uuid("UUID", data + 2, 2);
- data += 4;
- len -= 4;
- }
+ struct gatt_db *db;

- return len;
+ db = get_db(frame, rsp);
+ if (!db)
+ return NULL;
+
+ return gatt_db_insert_descriptor(db, handle, uuid, 0, NULL, NULL, NULL);
}

-static uint16_t print_info_data_128(const void *data, uint16_t len)
+static void att_find_info_rsp_16(const struct l2cap_frame *frame)
{
- while (len >= 18) {
- print_field("Handle: 0x%4.4x", get_le16(data));
- print_uuid("UUID", data + 2, 16);
- data += 18;
- len -= 18;
- }
+ while (frame->size >= 4) {
+ uint16_t handle;
+ uint16_t u16;
+ bt_uuid_t uuid;

- return len;
+ if (!l2cap_frame_get_le16((void *)frame, &handle)) {
+ print_text(COLOR_ERROR, " Handle: invalid size");
+ return;
+ }
+
+ if (!l2cap_frame_get_le16((void *)frame, &u16)) {
+ print_text(COLOR_ERROR, " UUID: invalid size");
+ return;
+ }
+
+ print_field("Handle: 0x%4.4x", handle);
+ print_uuid("UUID", &u16, 2);
+
+ bt_uuid16_create(&uuid, u16);
+
+ insert_desc(frame, handle, &uuid, true);
+ }
+}
+
+static void att_find_info_rsp_128(const struct l2cap_frame *frame)
+{
+ while (frame->size >= 18) {
+ uint16_t handle;
+ bt_uuid_t uuid;
+
+ if (!l2cap_frame_get_le16((void *)frame, &handle)) {
+ print_text(COLOR_ERROR, " Handle: invalid size");
+ return;
+ }
+
+ if (frame->size < 16) {
+ print_text(COLOR_ERROR, " UUID: invalid size");
+ return;
+ }
+
+ print_field("Handle: 0x%4.4x", handle);
+ print_uuid("UUID", frame->data, 16);
+
+ bt_uuid_from_data(&uuid, frame->data, 16);
+
+ if (!l2cap_frame_pull((void *)frame, frame, 16))
+ return;
+
+ insert_desc(frame, handle, &uuid, true);
+ }
}

static void att_find_info_rsp(const struct l2cap_frame *frame)
{
- const uint8_t *format = frame->data;
- uint16_t len;
+ uint8_t format;

- print_field("Format: %s (0x%2.2x)", att_format_str(*format), *format);
+ if (!l2cap_frame_get_u8((void *)frame, &format)) {
+ print_text(COLOR_ERROR, " Format: invalid size");
+ goto done;
+ }

- if (*format == 0x01)
- len = print_info_data_16(frame->data + 1, frame->size - 1);
- else if (*format == 0x02)
- len = print_info_data_128(frame->data + 1, frame->size - 1);
- else
- len = frame->size - 1;
+ print_field("Format: %s (0x%2.2x)", att_format_str(format), format);

- packet_hexdump(frame->data + (frame->size - len), len);
+ switch (format) {
+ case 0x01:
+ att_find_info_rsp_16(frame);
+ break;
+ case 0x02:
+ att_find_info_rsp_128(frame);
+ break;
+ }
+
+done:
+ if (frame->size)
+ packet_hexdump(frame->data, frame->size);
}

static void att_find_by_type_val_req(const struct l2cap_frame *frame)
@@ -3146,69 +3401,34 @@ static void att_find_by_type_val_rsp(const struct l2cap_frame *frame)
packet_hexdump(ptr, len);
}

-static int bt_uuid_from_data(bt_uuid_t *uuid, const void *data, uint16_t size)
+static struct gatt_db_attribute *get_attribute(const struct l2cap_frame *frame,
+ uint16_t handle, bool rsp)
{
- uint128_t u128;
+ struct gatt_db *db;

- switch (size) {
- case 2:
- return bt_uuid16_create(uuid, get_le16(data));
- case 4:
- return bt_uuid32_create(uuid, get_le32(data));
- case 16:
- memcpy(u128.data, data, sizeof(u128.data));
- return bt_uuid128_create(uuid, u128);
- }
-
- return -EINVAL;
-}
-
-static void att_conn_data_free(void *data)
-{
- struct att_conn_data *att_data = data;
-
- gatt_db_unref(att_data->rdb);
- gatt_db_unref(att_data->ldb);
- queue_destroy(att_data->reads, free);
- free(att_data);
-}
-
-static struct att_conn_data *att_get_conn_data(struct packet_conn_data *conn)
-{
- struct att_conn_data *data;
-
- if (!conn)
+ db = get_db(frame, rsp);
+ if (!db)
return NULL;

- data = conn->data;
-
- if (data)
- return data;
-
- data = new0(struct att_conn_data, 1);
- data->rdb = gatt_db_new();
- data->ldb = gatt_db_new();
- conn->data = data;
- conn->destroy = att_conn_data_free;
-
- return data;
+ return gatt_db_get_attribute(db, handle);
}

-static void att_read_type_req(const struct l2cap_frame *frame)
+static void queue_read(const struct l2cap_frame *frame, bt_uuid_t *uuid,
+ uint16_t handle)
{
- bt_uuid_t uuid;
struct packet_conn_data *conn;
struct att_conn_data *data;
struct att_read *read;
+ struct gatt_db_attribute *attr = NULL;
struct gatt_handler *handler;

- print_handle_range("Handle range", frame->data);
- print_uuid("Attribute type", frame->data + 4, frame->size - 4);
+ if (handle) {
+ attr = get_attribute(frame, handle, false);
+ if (!attr)
+ return;
+ }

- if (bt_uuid_from_data(&uuid, frame->data + 4, frame->size - 4))
- return;
-
- handler = get_handler_uuid(&uuid);
+ handler = attr ? get_handler(attr) : get_handler_uuid(uuid);
if (!handler || !handler->read)
return;

@@ -3221,6 +3441,7 @@ static void att_read_type_req(const struct l2cap_frame *frame)
data->reads = queue_new();

read = new0(struct att_read, 1);
+ read->attr = attr;
read->in = frame->in;
read->chan = frame->chan;
read->func = handler->read;
@@ -3228,6 +3449,19 @@ static void att_read_type_req(const struct l2cap_frame *frame)
queue_push_tail(data->reads, read);
}

+static void att_read_type_req(const struct l2cap_frame *frame)
+{
+ bt_uuid_t uuid;
+
+ print_handle_range("Handle range", frame->data);
+ print_uuid("Attribute type", frame->data + 4, frame->size - 4);
+
+ if (bt_uuid_from_data(&uuid, frame->data + 4, frame->size - 4))
+ return;
+
+ queue_read(frame, &uuid, 0x0000);
+}
+
static void att_read_type_rsp(const struct l2cap_frame *frame)
{
uint8_t len;
@@ -3241,83 +3475,6 @@ static void att_read_type_rsp(const struct l2cap_frame *frame)
print_data_list("Attribute data list", len, frame);
}

-static void gatt_load_db(struct gatt_db *db, const char *filename,
- struct timespec *mtim)
-{
- struct stat st;
-
- if (lstat(filename, &st))
- return;
-
- if (!gatt_db_isempty(db)) {
- /* Check if file has been modified since last time */
- if (st.st_mtim.tv_sec == mtim->tv_sec &&
- st.st_mtim.tv_nsec == mtim->tv_nsec)
- return;
- /* Clear db before reloading */
- gatt_db_clear(db);
- }
-
- *mtim = st.st_mtim;
-
- btd_settings_gatt_db_load(db, filename);
-}
-
-static void load_gatt_db(struct packet_conn_data *conn)
-{
- struct att_conn_data *data = att_get_conn_data(conn);
- char filename[PATH_MAX];
- char local[18];
- char peer[18];
- uint8_t id[6], id_type;
-
- ba2str((bdaddr_t *)conn->src, local);
-
- if (keys_resolve_identity(conn->dst, id, &id_type))
- ba2str((bdaddr_t *)id, peer);
- else
- ba2str((bdaddr_t *)conn->dst, peer);
-
- create_filename(filename, PATH_MAX, "/%s/attributes", local);
- gatt_load_db(data->ldb, filename, &data->ldb_mtim);
-
- create_filename(filename, PATH_MAX, "/%s/cache/%s", local, peer);
- gatt_load_db(data->rdb, filename, &data->rdb_mtim);
-}
-
-static struct gatt_db_attribute *get_attribute(const struct l2cap_frame *frame,
- uint16_t handle, bool rsp)
-{
- struct packet_conn_data *conn;
- struct att_conn_data *data;
- struct gatt_db *db;
-
- conn = packet_get_conn_data(frame->handle);
- if (!conn)
- return NULL;
-
- /* Try loading local and remote gatt_db if not loaded yet */
- load_gatt_db(conn);
-
- data = conn->data;
- if (!data)
- return NULL;
-
- if (frame->in) {
- if (rsp)
- db = data->rdb;
- else
- db = data->ldb;
- } else {
- if (rsp)
- db = data->ldb;
- else
- db = data->rdb;
- }
-
- return gatt_db_get_attribute(db, handle);
-}
-
static void print_handle(const struct l2cap_frame *frame, uint16_t handle,
bool rsp)
{
@@ -3336,38 +3493,13 @@ static void att_read_req(const struct l2cap_frame *frame)
{
const struct bt_l2cap_att_read_req *pdu = frame->data;
uint16_t handle;
- struct packet_conn_data *conn;
- struct att_conn_data *data;
- struct att_read *read;
- struct gatt_db_attribute *attr;
- struct gatt_handler *handler;

l2cap_frame_pull((void *)frame, frame, sizeof(*pdu));

handle = le16_to_cpu(pdu->handle);
print_handle(frame, handle, false);

- attr = get_attribute(frame, handle, false);
- if (!attr)
- return;
-
- handler = get_handler(attr);
- if (!handler || !handler->read)
- return;
-
- conn = packet_get_conn_data(frame->handle);
- data = conn->data;
-
- if (!data->reads)
- data->reads = queue_new();
-
- read = new0(struct att_read, 1);
- read->attr = attr;
- read->in = frame->in;
- read->chan = frame->chan;
- read->func = handler->read;
-
- queue_push_tail(data->reads, read);
+ queue_read(frame, NULL, handle);
}

static void att_read_rsp(const struct l2cap_frame *frame)
@@ -3409,40 +3541,60 @@ static void att_read_multiple_req(const struct l2cap_frame *frame)

static void att_read_group_type_req(const struct l2cap_frame *frame)
{
+ bt_uuid_t uuid;
+
print_handle_range("Handle range", frame->data);
print_uuid("Attribute group type", frame->data + 4, frame->size - 4);
+
+ if (bt_uuid_from_data(&uuid, frame->data + 4, frame->size - 4))
+ return;
+
+ queue_read(frame, &uuid, 0x0000);
}

static void print_group_list(const char *label, uint8_t length,
- const void *data, uint16_t size)
+ const struct l2cap_frame *frame)
{
+ struct att_read *read;
uint8_t count;

if (length == 0)
return;

- count = size / length;
+ read = att_get_read(frame);
+
+ count = frame->size / length;

print_field("%s: %u entr%s", label, count, count == 1 ? "y" : "ies");

- while (size >= length) {
- print_handle_range("Handle range", data);
- print_uuid("UUID", data + 4, length - 4);
+ while (frame->size >= length) {
+ print_handle_range("Handle range", frame->data);
+ print_uuid("UUID", frame->data + 4, length - 4);

- data += length;
- size -= length;
+ if (read) {
+ struct l2cap_frame f;
+
+ l2cap_frame_clone_size(&f, frame, length);
+
+ read->func(&f);
+ }
+
+ if (!l2cap_frame_pull((void *)frame, frame, length))
+ break;
}

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

static void att_read_group_type_rsp(const struct l2cap_frame *frame)
{
const struct bt_l2cap_att_read_group_type_rsp *pdu = frame->data;

+ l2cap_frame_pull((void *)frame, frame, sizeof(*pdu));
+
print_field("Attribute data length: %d", pdu->length);
- print_group_list("Attribute group list", pdu->length,
- frame->data + 1, frame->size - 1);
+ print_group_list("Attribute group list", pdu->length, frame);
}

static void print_write(const struct l2cap_frame *frame, uint16_t handle,
--
2.40.0


2023-05-05 22:01:49

by bluez.test.bot

[permalink] [raw]
Subject: RE: [BlueZ,1/2] monitor/att: Attempt to insert discovered attributes

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=745389

---Test result---

Test Summary:
CheckPatch FAIL 1.55 seconds
GitLint PASS 0.64 seconds
BuildEll PASS 32.30 seconds
BluezMake PASS 1012.15 seconds
MakeCheck PASS 13.45 seconds
MakeDistcheck PASS 186.69 seconds
CheckValgrind PASS 300.63 seconds
CheckSmatch WARNING 403.87 seconds
bluezmakeextell PASS 123.37 seconds
IncrementalBuild PASS 1661.30 seconds
ScanBuild PASS 1239.79 seconds

Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[BlueZ,2/2] monitor: Fix misaligment errors
WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#106: FILE: monitor/packet.c:11948:
+} __attribute__((packed));

/github/workspace/src/src/13233010.patch total: 0 errors, 1 warnings, 17 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/src/13233010.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.


##############################
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.monitor/packet.c: note: in included file:monitor/display.h:82:26: warning: Variable length array is used.monitor/packet.c:1800:26: warning: Variable length array is used.monitor/packet.c: note: in included file:monitor/bt.h:3552:52: warning: array of flexible structuresmonitor/bt.h:3540:40: warning: array of flexible structures


---
Regards,
Linux Bluetooth

2023-05-09 00:31:05

by patchwork-bot+bluetooth

[permalink] [raw]
Subject: Re: [PATCH BlueZ 1/2] monitor/att: Attempt to insert discovered attributes

Hello:

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

On Fri, 5 May 2023 13:31:55 -0700 you wrote:
> From: Luiz Augusto von Dentz <[email protected]>
>
> This attempts to insert discovered attributes into monitor gatt_db
> instance if their respective discover procedures are used which enables
> decoding traces injected by user via unit testing:
>
> > sudo unit/test-bap -m -s "34
>
> [...]

Here is the summary with links:
- [BlueZ,1/2] monitor/att: Attempt to insert discovered attributes
(no matching commit)
- [BlueZ,2/2] monitor: Fix misaligment errors
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=acfa41dedb47

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