All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH BlueZ 1/6] monitor/att: Fix not dequeing att_read on error response
@ 2022-11-15  0:30 Luiz Augusto von Dentz
  2022-11-15  0:30 ` [PATCH BlueZ 2/6] shared/util: Add iovec helpers Luiz Augusto von Dentz
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2022-11-15  0:30 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

If a read/read by type fails it needs to be dequeued otherwise it can
cause the next operation of the same type to return the wrong request
and possible decoding as if it was a different attribute type.
---
 monitor/att.c | 109 +++++++++++++++++++++++++++-----------------------
 1 file changed, 58 insertions(+), 51 deletions(-)

diff --git a/monitor/att.c b/monitor/att.c
index efd840d51961..d14cbd165697 100644
--- a/monitor/att.c
+++ b/monitor/att.c
@@ -106,27 +106,66 @@ static bool match_read_frame(const void *data, const void *match_data)
 	return read->chan == frame->chan;
 }
 
-static void print_data_list(const char *label, uint8_t length,
-					const struct l2cap_frame *frame)
+static struct att_read *att_get_read(const struct l2cap_frame *frame)
 {
 	struct packet_conn_data *conn;
 	struct att_conn_data *data;
+
+	conn = packet_get_conn_data(frame->handle);
+	if (!conn)
+		return NULL;
+
+	data = conn->data;
+	if (!data)
+		return NULL;
+
+	return queue_remove_if(data->reads, match_read_frame, (void *)frame);
+}
+
+static void print_attribute(struct gatt_db_attribute *attr)
+{
+	uint16_t handle;
+	const bt_uuid_t *uuid;
+	char label[21];
+
+	handle = gatt_db_attribute_get_handle(attr);
+	if (!handle)
+		goto done;
+
+	uuid = gatt_db_attribute_get_type(attr);
+	if (!uuid)
+		goto done;
+
+	switch (uuid->type) {
+	case BT_UUID16:
+		sprintf(label, "Handle: 0x%4.4x Type", handle);
+		print_field("%s: %s (0x%4.4x)", label,
+				bt_uuid16_to_str(uuid->value.u16),
+				uuid->value.u16);
+		return;
+	case BT_UUID128:
+		sprintf(label, "Handle: 0x%4.4x Type", handle);
+		print_uuid(label, &uuid->value.u128, 16);
+		return;
+	case BT_UUID_UNSPEC:
+	case BT_UUID32:
+		break;
+	}
+
+done:
+	print_field("Handle: 0x%4.4x", handle);
+}
+
+static void print_data_list(const char *label, uint8_t length,
+					const struct l2cap_frame *frame)
+{
 	struct att_read *read;
 	uint8_t count;
 
 	if (length == 0)
 		return;
 
-	conn = packet_get_conn_data(frame->handle);
-	if (conn) {
-		data = conn->data;
-		if (data)
-			read = queue_remove_if(data->reads, match_read_frame,
-						(void *)frame);
-		else
-			read = NULL;
-	} else
-		read = NULL;
+	read = att_get_read(frame);
 
 	count = frame->size / length;
 
@@ -271,6 +310,12 @@ static void att_error_response(const struct l2cap_frame *frame)
 							pdu->request);
 	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.
+	 */
+	if (pdu->request == 0x08 || pdu->request == 0x0a)
+		free(att_get_read(frame));
 }
 
 static const struct bitfield_data chrc_prop_table[] = {
@@ -2662,36 +2707,6 @@ static struct gatt_db_attribute *get_attribute(const struct l2cap_frame *frame,
 	return gatt_db_get_attribute(db, handle);
 }
 
-static void print_attribute(struct gatt_db_attribute *attr)
-{
-	uint16_t handle = gatt_db_attribute_get_handle(attr);
-	const bt_uuid_t *uuid;
-	char label[21];
-
-	uuid = gatt_db_attribute_get_type(attr);
-	if (!uuid)
-		goto done;
-
-	switch (uuid->type) {
-	case BT_UUID16:
-		sprintf(label, "Handle: 0x%4.4x Type", handle);
-		print_field("%s: %s (0x%4.4x)", label,
-				bt_uuid16_to_str(uuid->value.u16),
-				uuid->value.u16);
-		return;
-	case BT_UUID128:
-		sprintf(label, "Handle: 0x%4.4x Type", handle);
-		print_uuid(label, &uuid->value.u128, 16);
-		return;
-	case BT_UUID_UNSPEC:
-	case BT_UUID32:
-		break;
-	}
-
-done:
-	print_field("Handle: 0x%4.4x", handle);
-}
-
 static void print_handle(const struct l2cap_frame *frame, uint16_t handle,
 								bool rsp)
 {
@@ -2746,19 +2761,11 @@ static void att_read_req(const struct l2cap_frame *frame)
 
 static void att_read_rsp(const struct l2cap_frame *frame)
 {
-	struct packet_conn_data *conn;
-	struct att_conn_data *data;
 	struct att_read *read;
 
 	print_hex_field("Value", frame->data, frame->size);
 
-	conn = packet_get_conn_data(frame->handle);
-	if (!conn)
-		return;
-
-	data = conn->data;
-
-	read = queue_remove_if(data->reads, match_read_frame, (void *)frame);
+	read = att_get_read(frame);
 	if (!read)
 		return;
 
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH BlueZ 2/6] shared/util: Add iovec helpers
  2022-11-15  0:30 [PATCH BlueZ 1/6] monitor/att: Fix not dequeing att_read on error response Luiz Augusto von Dentz
@ 2022-11-15  0:30 ` Luiz Augusto von Dentz
  2022-11-15  0:30 ` [PATCH BlueZ 3/6] shared/bap: Make use of util_iov helpers Luiz Augusto von Dentz
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2022-11-15  0:30 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This adds iovec helpers functions.
---
 src/shared/util.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++
 src/shared/util.h |  10 +++++
 2 files changed, 113 insertions(+)

diff --git a/src/shared/util.c b/src/shared/util.c
index 0a0308cb0786..333023e0dcac 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -189,6 +189,109 @@ void util_clear_uid(uint64_t *bitmap, uint8_t id)
 	*bitmap &= ~(((uint64_t)1) << (id - 1));
 }
 
+struct iovec *util_iov_dup(const struct iovec *iov, size_t cnt)
+{
+	struct iovec *dup;
+	size_t i;
+
+	if (!iov)
+		return NULL;
+
+	dup = new0(struct iovec, cnt);
+
+	for (i = 0; i < cnt; i++)
+		util_iov_memcpy(&dup[i], iov[i].iov_base, iov[i].iov_len);
+
+	return dup;
+}
+
+int util_iov_memcmp(const struct iovec *iov1, const struct iovec *iov2)
+{
+	if (!iov1)
+		return 1;
+
+	if (!iov2)
+		return -1;
+
+	if (iov1->iov_len != iov2->iov_len)
+		return iov1->iov_len - iov2->iov_len;
+
+	return memcmp(iov1->iov_base, iov2->iov_base, iov1->iov_len);
+}
+
+void util_iov_memcpy(struct iovec *iov, void *src, size_t len)
+{
+	if (!iov)
+		return;
+
+	iov->iov_base = realloc(iov->iov_base, len);
+	iov->iov_len = len;
+	memcpy(iov->iov_base, src, len);
+}
+
+void util_iov_free(struct iovec *iov, size_t cnt)
+{
+	size_t i;
+
+	if (!iov)
+		return;
+
+	for (i = 0; i < cnt; i++)
+		free(iov[i].iov_base);
+
+	free(iov);
+}
+
+void *util_iov_push(struct iovec *iov, size_t len)
+{
+	void *data;
+
+	if (!iov)
+		return NULL;
+
+	data = iov->iov_base + iov->iov_len;
+	iov->iov_len += len;
+
+	return data;
+}
+
+void *util_iov_push_mem(struct iovec *iov, size_t len, const void *data)
+{
+	void *p;
+
+	p = util_iov_push(iov, len);
+	if (!p)
+		return NULL;
+
+	memcpy(p, data, len);
+
+	return p;
+}
+
+void *util_iov_pull(struct iovec *iov, size_t len)
+{
+	if (!iov)
+		return NULL;
+
+	if (iov->iov_len < len)
+		return NULL;
+
+	iov->iov_base += len;
+	iov->iov_len -= len;
+
+	return iov->iov_base;
+}
+
+void *util_iov_pull_mem(struct iovec *iov, size_t len)
+{
+	void *data = iov->iov_base;
+
+	if (util_iov_pull(iov, len))
+		return data;
+
+	return NULL;
+}
+
 static const struct {
 	uint16_t uuid;
 	const char *str;
diff --git a/src/shared/util.h b/src/shared/util.h
index 554481e1e1ea..dc84f963588f 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -15,6 +15,7 @@
 #include <byteswap.h>
 #include <string.h>
 #include <sys/types.h>
+#include <sys/uio.h>
 
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
 #define BIT(n)  (1 << (n))
@@ -109,6 +110,15 @@ ssize_t util_getrandom(void *buf, size_t buflen, unsigned int flags);
 uint8_t util_get_uid(uint64_t *bitmap, uint8_t max);
 void util_clear_uid(uint64_t *bitmap, uint8_t id);
 
+struct iovec *util_iov_dup(const struct iovec *iov, size_t cnt);
+int util_iov_memcmp(const struct iovec *iov1, const struct iovec *iov2);
+void util_iov_memcpy(struct iovec *iov, void *src, size_t len);
+void *util_iov_push(struct iovec *iov, size_t len);
+void *util_iov_push_mem(struct iovec *iov, size_t len, const void *data);
+void *util_iov_pull(struct iovec *iov, size_t len);
+void *util_iov_pull_mem(struct iovec *iov, size_t len);
+void util_iov_free(struct iovec *iov, size_t cnt);
+
 const char *bt_uuid16_to_str(uint16_t uuid);
 const char *bt_uuid32_to_str(uint32_t uuid);
 const char *bt_uuid128_to_str(const uint8_t uuid[16]);
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH BlueZ 3/6] shared/bap: Make use of util_iov helpers
  2022-11-15  0:30 [PATCH BlueZ 1/6] monitor/att: Fix not dequeing att_read on error response Luiz Augusto von Dentz
  2022-11-15  0:30 ` [PATCH BlueZ 2/6] shared/util: Add iovec helpers Luiz Augusto von Dentz
@ 2022-11-15  0:30 ` Luiz Augusto von Dentz
  2022-11-15  0:30 ` [PATCH BlueZ 4/6] shared/tester: Add tester_io_set_complete_func Luiz Augusto von Dentz
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2022-11-15  0:30 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This make use of util_iov helpers instead of reimplementing them.
---
 src/shared/bap.c | 183 +++++++++++++----------------------------------
 1 file changed, 51 insertions(+), 132 deletions(-)

diff --git a/src/shared/bap.c b/src/shared/bap.c
index c3c0d596fe91..25369e619051 100644
--- a/src/shared/bap.c
+++ b/src/shared/bap.c
@@ -262,76 +262,6 @@ static bool bap_db_match(const void *data, const void *match_data)
 	return (bdb->db == db);
 }
 
-static void *iov_add(struct iovec *iov, size_t len)
-{
-	void *data;
-
-	data = iov->iov_base + iov->iov_len;
-	iov->iov_len += len;
-
-	return data;
-}
-
-static void *iov_add_mem(struct iovec *iov, size_t len, const void *d)
-{
-	void *data;
-
-	data = iov->iov_base + iov->iov_len;
-	iov->iov_len += len;
-
-	memcpy(data, d, len);
-
-	return data;
-}
-
-static void iov_free(void *data)
-{
-	struct iovec *iov = data;
-
-	if (!iov)
-		return;
-
-	free(iov->iov_base);
-	free(iov);
-}
-
-static void iov_memcpy(struct iovec *iov, void *src, size_t len)
-{
-	iov->iov_base = realloc(iov->iov_base, len);
-	iov->iov_len = len;
-	memcpy(iov->iov_base, src, len);
-}
-
-static int iov_memcmp(struct iovec *iov1, struct iovec *iov2)
-{
-	if (!iov1)
-		return 1;
-
-	if (!iov2)
-		return -1;
-
-	if (iov1->iov_len != iov2->iov_len)
-		return iov1->iov_len - iov2->iov_len;
-
-	return memcmp(iov1->iov_base, iov2->iov_base, iov1->iov_len);
-}
-
-static struct iovec *iov_dup(struct iovec *iov, size_t len)
-{
-	struct iovec *dup;
-	size_t i;
-
-	if (!iov)
-		return NULL;
-
-	dup = new0(struct iovec, len);
-
-	for (i = 0; i < len; i++)
-		iov_memcpy(&dup[i], iov[i].iov_base, iov[i].iov_len);
-
-	return dup;
-}
-
 unsigned int bt_bap_pac_register(bt_bap_pac_func_t added,
 				bt_bap_pac_func_t removed, void *user_data,
 				bt_bap_destroy_func_t destroy)
@@ -407,27 +337,27 @@ static void pac_foreach(void *data, void *user_data)
 	struct bt_pac_metadata *meta;
 
 	if (!iov->iov_len) {
-		rsp = iov_add(iov, sizeof(*rsp));
+		rsp = util_iov_push(iov, sizeof(*rsp));
 		rsp->num_pac = 0;
 	} else
 		rsp = iov->iov_base;
 
 	rsp->num_pac++;
 
-	p = iov_add(iov, sizeof(*p));
+	p = util_iov_push(iov, sizeof(*p));
 	p->codec.id = pac->codec.id;
 
 	if (pac->data) {
 		p->cc_len = pac->data->iov_len;
-		iov_add_mem(iov, p->cc_len, pac->data->iov_base);
+		util_iov_push_mem(iov, p->cc_len, pac->data->iov_base);
 	} else
 		p->cc_len = 0;
 
-	meta = iov_add(iov, sizeof(*meta));
+	meta = util_iov_push(iov, sizeof(*meta));
 
 	if (pac->metadata) {
 		meta->len = pac->metadata->iov_len;
-		iov_add_mem(iov, meta->len, pac->metadata->iov_base);
+		util_iov_push_mem(iov, meta->len, pac->metadata->iov_base);
 	} else
 		meta->len = 0;
 }
@@ -814,19 +744,6 @@ static void ase_new(struct bt_ascs *ascs, int i)
 	ascs->ase[i] = ase;
 }
 
-static void *iov_pull_mem(struct iovec *iov, size_t len)
-{
-	void *data = iov->iov_base;
-
-	if (iov->iov_len < len)
-		return NULL;
-
-	iov->iov_base += len;
-	iov->iov_len -= len;
-
-	return data;
-}
-
 static bool bap_codec_equal(const struct bt_bap_codec *c1,
 				const struct bt_bap_codec *c2)
 {
@@ -852,7 +769,7 @@ static struct bt_bap_stream *bap_stream_new(struct bt_bap *bap,
 	ep->stream = stream;
 	stream->lpac = lpac;
 	stream->rpac = rpac;
-	stream->cc = iov_dup(data, 1);
+	stream->cc = util_iov_dup(data, 1);
 	stream->client = client;
 
 	queue_push_tail(bap->streams, stream);
@@ -1050,8 +967,8 @@ static void bap_stream_free(void *data)
 	queue_foreach(stream->links, bap_stream_unlink, stream);
 	queue_destroy(stream->links, NULL);
 	stream_io_unref(stream->io);
-	iov_free(stream->cc);
-	iov_free(stream->meta);
+	util_iov_free(stream->cc, 1);
+	util_iov_free(stream->meta, 1);
 	free(stream);
 }
 
@@ -1454,13 +1371,13 @@ static uint8_t stream_config(struct bt_bap_stream *stream, struct iovec *cc,
 	/* TODO: Wait for pac->ops response */
 	ascs_ase_rsp_success(rsp, stream->ep->id);
 
-	if (!iov_memcmp(stream->cc, cc)) {
+	if (!util_iov_memcmp(stream->cc, cc)) {
 		stream_set_state(stream, BT_BAP_STREAM_STATE_CONFIG);
 		return 0;
 	}
 
-	iov_free(stream->cc);
-	stream->cc = iov_dup(cc, 1);
+	util_iov_free(stream->cc, 1);
+	stream->cc = util_iov_dup(cc, 1);
 
 	if (pac->ops && pac->ops->config)
 		pac->ops->config(stream, cc, NULL, ep_config_cb,
@@ -1497,7 +1414,7 @@ static uint8_t ep_config(struct bt_bap_endpoint *ep, struct bt_bap *bap,
 	if (iov->iov_len < req->cc_len)
 		return BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
 
-	cc.iov_base = iov_pull_mem(iov, req->cc_len);
+	cc.iov_base = util_iov_pull_mem(iov, req->cc_len);
 	cc.iov_len = req->cc_len;
 
 	if (!bap_print_cc(cc.iov_base, cc.iov_len, bap->debug_func,
@@ -1548,7 +1465,7 @@ static uint8_t ascs_config(struct bt_ascs *ascs, struct bt_bap *bap,
 	struct bt_bap_endpoint *ep;
 	struct bt_ascs_config *req;
 
-	req = iov_pull_mem(iov, sizeof(*req));
+	req = util_iov_pull_mem(iov, sizeof(*req));
 
 	DBG(bap, "codec 0x%02x phy 0x%02x latency %u", req->codec.id, req->phy,
 							req->latency);
@@ -1616,7 +1533,7 @@ static uint8_t ascs_qos(struct bt_ascs *ascs, struct bt_bap *bap,
 	struct bt_ascs_qos *req;
 	struct bt_bap_qos qos;
 
-	req = iov_pull_mem(iov, sizeof(*req));
+	req = util_iov_pull_mem(iov, sizeof(*req));
 
 	memset(&qos, 0, sizeof(qos));
 
@@ -1653,8 +1570,8 @@ static uint8_t stream_enable(struct bt_bap_stream *stream, struct iovec *meta,
 
 	ascs_ase_rsp_success(rsp, stream->ep->id);
 
-	iov_free(stream->meta);
-	stream->meta = iov_dup(meta, 1);
+	util_iov_free(stream->meta, 1);
+	stream->meta = util_iov_dup(meta, 1);
 
 	stream_set_state(stream, BT_BAP_STREAM_STATE_ENABLING);
 
@@ -1677,7 +1594,7 @@ static bool bap_print_ltv(const char *label, void *data, size_t len,
 	util_debug(func, user_data, "Length %zu", iov.iov_len);
 
 	for (i = 0; iov.iov_len > 1; i++) {
-		struct bt_ltv *ltv = iov_pull_mem(&iov, sizeof(*ltv));
+		struct bt_ltv *ltv = util_iov_pull_mem(&iov, sizeof(*ltv));
 		uint8_t *data;
 
 		if (!ltv) {
@@ -1689,7 +1606,7 @@ static bool bap_print_ltv(const char *label, void *data, size_t len,
 		util_debug(func, user_data, "%s #%u: len %u type %u",
 					label, i, ltv->len, ltv->type);
 
-		data = iov_pull_mem(&iov, ltv->len - 1);
+		data = util_iov_pull_mem(&iov, ltv->len - 1);
 		if (!data) {
 			util_debug(func, user_data, "Unable to parse %s",
 								label);
@@ -1728,7 +1645,7 @@ static uint8_t ep_enable(struct bt_bap_endpoint *ep, struct bt_bap *bap,
 		return 0;
 	}
 
-	meta.iov_base = iov_pull_mem(iov, req->meta.len);
+	meta.iov_base = util_iov_pull_mem(iov, req->meta.len);
 	meta.iov_len = req->meta.len;
 
 	if (!bap_print_metadata(meta.iov_base, meta.iov_len, bap->debug_func,
@@ -1756,7 +1673,7 @@ static uint8_t ascs_enable(struct bt_ascs *ascs, struct bt_bap *bap,
 	struct bt_bap_endpoint *ep;
 	struct bt_ascs_enable *req;
 
-	req = iov_pull_mem(iov, sizeof(*req));
+	req = util_iov_pull_mem(iov, sizeof(*req));
 
 	ep = bap_get_endpoint_id(bap, bap->ldb, req->meta.ase);
 	if (!ep) {
@@ -1820,7 +1737,7 @@ static uint8_t ascs_start(struct bt_ascs *ascs, struct bt_bap *bap,
 	struct bt_bap_endpoint *ep;
 	struct bt_ascs_start *req;
 
-	req = iov_pull_mem(iov, sizeof(*req));
+	req = util_iov_pull_mem(iov, sizeof(*req));
 
 	ep = bap_get_endpoint_id(bap, bap->ldb, req->ase);
 	if (!ep) {
@@ -1892,7 +1809,7 @@ static uint8_t ascs_disable(struct bt_ascs *ascs, struct bt_bap *bap,
 	struct bt_bap_endpoint *ep;
 	struct bt_ascs_disable *req;
 
-	req = iov_pull_mem(iov, sizeof(*req));
+	req = util_iov_pull_mem(iov, sizeof(*req));
 
 	ep = bap_get_endpoint_id(bap, bap->ldb, req->ase);
 	if (!ep) {
@@ -1967,7 +1884,7 @@ static uint8_t ascs_stop(struct bt_ascs *ascs, struct bt_bap *bap,
 	struct bt_bap_endpoint *ep;
 	struct bt_ascs_stop *req;
 
-	req = iov_pull_mem(iov, sizeof(*req));
+	req = util_iov_pull_mem(iov, sizeof(*req));
 
 	ep = bap_get_endpoint_id(bap, bap->ldb, req->ase);
 	if (!ep) {
@@ -1995,8 +1912,8 @@ static uint8_t stream_metadata(struct bt_bap_stream *stream, struct iovec *meta,
 
 	ascs_ase_rsp_success(rsp, stream->ep->id);
 
-	iov_free(stream->meta);
-	stream->meta = iov_dup(meta, 1);
+	util_iov_free(stream->meta, 1);
+	stream->meta = util_iov_dup(meta, 1);
 
 	return 0;
 }
@@ -2032,7 +1949,7 @@ static uint8_t ascs_metadata(struct bt_ascs *ascs, struct bt_bap *bap,
 	struct bt_bap_endpoint *ep;
 	struct bt_ascs_metadata *req;
 
-	req = iov_pull_mem(iov, sizeof(*req));
+	req = util_iov_pull_mem(iov, sizeof(*req));
 
 	ep = bap_get_endpoint_id(bap, bap->ldb, req->ase);
 	if (!ep) {
@@ -2076,7 +1993,7 @@ static uint8_t ascs_release(struct bt_ascs *ascs, struct bt_bap *bap,
 	struct bt_bap_endpoint *ep;
 	struct bt_ascs_release *req;
 
-	req = iov_pull_mem(iov, sizeof(*req));
+	req = util_iov_pull_mem(iov, sizeof(*req));
 
 	ep = bap_get_endpoint_id(bap, bap->ldb, req->ase);
 	if (!ep) {
@@ -2177,7 +2094,7 @@ static void ascs_ase_cp_write(struct gatt_db_attribute *attrib,
 		return;
 	}
 
-	hdr = iov_pull_mem(&iov, sizeof(*hdr));
+	hdr = util_iov_pull_mem(&iov, sizeof(*hdr));
 	rsp = ascs_ase_cp_rsp_new(hdr->op);
 
 	for (handler = handlers; handler && handler->str; handler++) {
@@ -2214,7 +2131,7 @@ respond:
 	gatt_db_attribute_notify(attrib, rsp->iov_base, rsp->iov_len, att);
 	gatt_db_attribute_write_result(attrib, id, ret);
 
-	iov_free(rsp);
+	util_iov_free(rsp, 1);
 }
 
 static struct bt_ascs *ascs_new(struct gatt_db *db)
@@ -2333,8 +2250,8 @@ static struct bt_bap_pac *bap_pac_new(struct bt_bap_db *bdb, const char *name,
 	pac->name = name ? strdup(name) : NULL;
 	pac->type = type;
 	pac->codec = *codec;
-	pac->data = iov_dup(data, 1);
-	pac->metadata = iov_dup(metadata, 1);
+	pac->data = util_iov_dup(data, 1);
+	pac->metadata = util_iov_dup(metadata, 1);
 
 	if (qos)
 		pac->qos = *qos;
@@ -2347,8 +2264,8 @@ static void bap_pac_free(void *data)
 	struct bt_bap_pac *pac = data;
 
 	free(pac->name);
-	iov_free(pac->metadata);
-	iov_free(pac->data);
+	util_iov_free(pac->metadata, 1);
+	util_iov_free(pac->data, 1);
 	free(pac);
 }
 
@@ -2769,7 +2686,7 @@ static void bap_parse_pacs(struct bt_bap *bap, uint8_t type,
 	};
 	int i;
 
-	rsp = iov_pull_mem(&iov, sizeof(*rsp));
+	rsp = util_iov_pull_mem(&iov, sizeof(*rsp));
 	if (!rsp) {
 		DBG(bap, "Unable to parse PAC");
 		return;
@@ -2784,7 +2701,7 @@ static void bap_parse_pacs(struct bt_bap *bap, uint8_t type,
 		struct bt_pac_metadata *meta;
 		struct iovec data, metadata;
 
-		p = iov_pull_mem(&iov, sizeof(*p));
+		p = util_iov_pull_mem(&iov, sizeof(*p));
 		if (!p) {
 			DBG(bap, "Unable to parse PAC");
 			return;
@@ -2796,13 +2713,13 @@ static void bap_parse_pacs(struct bt_bap *bap, uint8_t type,
 					bap->debug_data))
 			return;
 
-		cc = iov_pull_mem(&iov, p->cc_len);
+		cc = util_iov_pull_mem(&iov, p->cc_len);
 		if (!cc) {
 			DBG(bap, "Unable to parse PAC codec capabilities");
 			return;
 		}
 
-		meta = iov_pull_mem(&iov, sizeof(*meta));
+		meta = util_iov_pull_mem(&iov, sizeof(*meta));
 		if (!meta) {
 			DBG(bap, "Unable to parse PAC metadata");
 			return;
@@ -2814,7 +2731,7 @@ static void bap_parse_pacs(struct bt_bap *bap, uint8_t type,
 		metadata.iov_len = meta->len;
 		metadata.iov_base = meta->data;
 
-		iov_pull_mem(&iov, meta->len);
+		util_iov_pull_mem(&iov, meta->len);
 
 		pac = bap_pac_new(bap->rdb, NULL, type, &p->codec, NULL, &data,
 								&metadata);
@@ -3089,7 +3006,7 @@ static void ep_status_config(struct bt_bap *bap, struct bt_bap_endpoint *ep,
 	uint32_t pd_min, pd_max, ppd_min, ppd_max;
 	int i;
 
-	cfg = iov_pull_mem(iov, sizeof(*cfg));
+	cfg = util_iov_pull_mem(iov, sizeof(*cfg));
 	if (!cfg) {
 		DBG(bap, "Unable to parse Config Status");
 		return;
@@ -3113,14 +3030,14 @@ static void ep_status_config(struct bt_bap *bap, struct bt_bap_endpoint *ep,
 	}
 
 	for (i = 0; iov->iov_len >= sizeof(*cc); i++) {
-		cc = iov_pull_mem(iov, sizeof(*cc));
+		cc = util_iov_pull_mem(iov, sizeof(*cc));
 		if (!cc)
 			break;
 
 		DBG(bap, "Codec Config #%u: type 0x%02x len %u", i,
 						cc->type, cc->len);
 
-		iov_pull_mem(iov, cc->len - 1);
+		util_iov_pull_mem(iov, cc->len - 1);
 	}
 
 	/* Any previously applied codec configuration may be cached by the
@@ -3160,7 +3077,7 @@ static void ep_status_config(struct bt_bap *bap, struct bt_bap_endpoint *ep,
 	if (!ep->stream->cc)
 		ep->stream->cc = new0(struct iovec, 1);
 
-	iov_memcpy(ep->stream->cc, cfg->cc, cfg->cc_len);
+	util_iov_memcpy(ep->stream->cc, cfg->cc, cfg->cc_len);
 }
 
 static void bap_stream_config_cfm_cb(struct bt_bap_stream *stream, int err)
@@ -3200,7 +3117,7 @@ static void ep_status_qos(struct bt_bap *bap, struct bt_bap_endpoint *ep,
 	uint16_t sdu;
 	uint16_t latency;
 
-	qos = iov_pull_mem(iov, sizeof(*qos));
+	qos = util_iov_pull_mem(iov, sizeof(*qos));
 	if (!qos) {
 		DBG(bap, "Unable to parse QoS Status");
 		return;
@@ -3236,7 +3153,7 @@ static void ep_status_metadata(struct bt_bap *bap, struct bt_bap_endpoint *ep,
 {
 	struct bt_ascs_ase_status_metadata *meta;
 
-	meta = iov_pull_mem(iov, sizeof(*meta));
+	meta = util_iov_pull_mem(iov, sizeof(*meta));
 	if (!meta) {
 		DBG(bap, "Unable to parse Metadata Status");
 		return;
@@ -3255,7 +3172,7 @@ static void bap_ep_set_status(struct bt_bap *bap, struct bt_bap_endpoint *ep,
 		.iov_len = length,
 	};
 
-	rsp = iov_pull_mem(&iov, sizeof(*rsp));
+	rsp = util_iov_pull_mem(&iov, sizeof(*rsp));
 	if (!rsp)
 		return;
 
@@ -3391,7 +3308,8 @@ static void append_group(void *data, void *user_data)
 	size_t i;
 
 	for (i = 0; i < req->len; i++)
-		iov_add_mem(iov, req->iov[i].iov_len, req->iov[i].iov_base);
+		util_iov_push_mem(iov, req->iov[i].iov_len,
+					req->iov[i].iov_base);
 }
 
 static bool bap_send(struct bt_bap *bap, struct bt_bap_req *req)
@@ -3414,10 +3332,11 @@ static bool bap_send(struct bt_bap *bap, struct bt_bap_req *req)
 	hdr.op = req->op;
 	hdr.num = 1 + queue_length(req->group);
 
-	iov_add_mem(&iov, sizeof(hdr), &hdr);
+	util_iov_push_mem(&iov, sizeof(hdr), &hdr);
 
 	for (i = 0; i < req->len; i++)
-		iov_add_mem(&iov, req->iov[i].iov_len, req->iov[i].iov_base);
+		util_iov_push_mem(&iov, req->iov[i].iov_len,
+					req->iov[i].iov_base);
 
 	/* Append the request group with the same opcode */
 	queue_foreach(req->group, append_group, &iov);
@@ -4011,7 +3930,7 @@ static struct bt_bap_req *bap_req_new(struct bt_bap_stream *stream,
 	req->id = ++id;
 	req->stream = stream;
 	req->op = op;
-	req->iov = iov_dup(iov, len);
+	req->iov = util_iov_dup(iov, len);
 	req->len = len;
 	req->func = func;
 	req->user_data = user_data;
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH BlueZ 4/6] shared/tester: Add tester_io_set_complete_func
  2022-11-15  0:30 [PATCH BlueZ 1/6] monitor/att: Fix not dequeing att_read on error response Luiz Augusto von Dentz
  2022-11-15  0:30 ` [PATCH BlueZ 2/6] shared/util: Add iovec helpers Luiz Augusto von Dentz
  2022-11-15  0:30 ` [PATCH BlueZ 3/6] shared/bap: Make use of util_iov helpers Luiz Augusto von Dentz
@ 2022-11-15  0:30 ` Luiz Augusto von Dentz
  2022-11-15  0:30 ` [PATCH BlueZ 5/6] shared/bap: Fix crash when canceling requests Luiz Augusto von Dentz
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2022-11-15  0:30 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This adds tester_io_set_complete_func which can be used to set a
callback when all iovec has been sent/received.
---
 src/shared/tester.c | 16 ++++++++++++++++
 src/shared/tester.h |  1 +
 2 files changed, 17 insertions(+)

diff --git a/src/shared/tester.c b/src/shared/tester.c
index e88dfabdc37c..1feaba48335c 100644
--- a/src/shared/tester.c
+++ b/src/shared/tester.c
@@ -89,6 +89,7 @@ struct test_case {
 	tester_data_func_t test_func;
 	tester_data_func_t teardown_func;
 	tester_data_func_t post_teardown_func;
+	tester_data_func_t io_complete_func;
 	gdouble start_time;
 	gdouble end_time;
 	unsigned int timeout;
@@ -913,6 +914,9 @@ static bool test_io_send(struct io *io, void *user_data)
 
 	g_assert_cmpint(len, ==, iov->iov_len);
 
+	if (!test->iovcnt && test->io_complete_func)
+		test->io_complete_func(test->test_data);
+
 	return false;
 }
 
@@ -937,10 +941,15 @@ static bool test_io_recv(struct io *io, void *user_data)
 
 	g_assert_cmpint(len, ==, iov->iov_len);
 
+	if (memcmp(buf, iov->iov_base, len))
+		tester_monitor('!', 0x0004, 0x0000, iov->iov_base, len);
+
 	g_assert(memcmp(buf, iov->iov_base, len) == 0);
 
 	if (test->iovcnt)
 		io_set_write_handler(io, test_io_send, NULL, NULL);
+	else if (test->io_complete_func)
+		test->io_complete_func(test->test_data);
 
 	return true;
 }
@@ -1004,6 +1013,13 @@ void tester_io_send(void)
 		io_set_write_handler(ios[1], test_io_send, NULL, NULL);
 }
 
+void tester_io_set_complete_func(tester_data_func_t func)
+{
+	struct test_case *test = tester_get_test();
+
+	test->io_complete_func = func;
+}
+
 int tester_run(void)
 {
 	int ret;
diff --git a/src/shared/tester.h b/src/shared/tester.h
index c28f61e7fd6b..49610185a444 100644
--- a/src/shared/tester.h
+++ b/src/shared/tester.h
@@ -78,3 +78,4 @@ void tester_wait(unsigned int seconds, tester_wait_func_t func,
 
 struct io *tester_setup_io(const struct iovec *iov, int iovcnt);
 void tester_io_send(void);
+void tester_io_set_complete_func(tester_data_func_t func);
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH BlueZ 5/6] shared/bap: Fix crash when canceling requests
  2022-11-15  0:30 [PATCH BlueZ 1/6] monitor/att: Fix not dequeing att_read on error response Luiz Augusto von Dentz
                   ` (2 preceding siblings ...)
  2022-11-15  0:30 ` [PATCH BlueZ 4/6] shared/tester: Add tester_io_set_complete_func Luiz Augusto von Dentz
@ 2022-11-15  0:30 ` Luiz Augusto von Dentz
  2022-11-15  0:30 ` [PATCH BlueZ 6/6] unit: Introduce test-bap Luiz Augusto von Dentz
  2022-11-15 19:40 ` [PATCH BlueZ 1/6] monitor/att: Fix not dequeing att_read on error response patchwork-bot+bluetooth
  5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2022-11-15  0:30 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

If bt_bap_unref/bap_free is called while there is an ongoing pending
request it may endup calling into bap_notify_ready which will try to
notify ready callbacks while holding a reference, but in case the
reference is already 0 that means it would switch to 1 and back 0
causing a double free.

To prevent that bap_notify_ready now checks that the reference is not 0
with use of bt_bap_ref_safe.
---
 src/shared/bap.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/src/shared/bap.c b/src/shared/bap.c
index 25369e619051..21aa8aa6c5ca 100644
--- a/src/shared/bap.c
+++ b/src/shared/bap.c
@@ -2638,6 +2638,14 @@ struct bt_bap *bt_bap_ref(struct bt_bap *bap)
 	return bap;
 }
 
+static struct bt_bap *bt_bap_ref_safe(struct bt_bap *bap)
+{
+	if (!bap || !bap->ref_count)
+		return NULL;
+
+	return bt_bap_ref(bap);
+}
+
 void bt_bap_unref(struct bt_bap *bap)
 {
 	if (!bap)
@@ -2656,7 +2664,8 @@ static void bap_notify_ready(struct bt_bap *bap)
 	if (!queue_isempty(bap->pending))
 		return;
 
-	bt_bap_ref(bap);
+	if (!bt_bap_ref_safe(bap))
+		return;
 
 	for (entry = queue_get_entries(bap->ready_cbs); entry;
 							entry = entry->next) {
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH BlueZ 6/6] unit: Introduce test-bap
  2022-11-15  0:30 [PATCH BlueZ 1/6] monitor/att: Fix not dequeing att_read on error response Luiz Augusto von Dentz
                   ` (3 preceding siblings ...)
  2022-11-15  0:30 ` [PATCH BlueZ 5/6] shared/bap: Fix crash when canceling requests Luiz Augusto von Dentz
@ 2022-11-15  0:30 ` Luiz Augusto von Dentz
  2022-11-15 19:40 ` [PATCH BlueZ 1/6] monitor/att: Fix not dequeing att_read on error response patchwork-bot+bluetooth
  5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2022-11-15  0:30 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Test Summary
------------
BAP/UCL/DISC/BV-01-C                                 Passed
BAP/UCL/DISC/BV-02-C                                 Passed
BAP/UCL/DISC/BV-06-C                                 Passed
BAP/UCL/DISC/BV-05-C                                 Passed
BAP/UCL/DISC/BV-03-C                                 Passed
BAP/UCL/DISC/BV-04-C                                 Passed
Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0
---
 Makefile.am     |   6 +
 unit/test-bap.c | 568 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 574 insertions(+)
 create mode 100644 unit/test-bap.c

diff --git a/Makefile.am b/Makefile.am
index 7041f8eeb52b..aa3a5e053cd8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -569,6 +569,12 @@ unit_test_gattrib_LDADD = lib/libbluetooth-internal.la \
 			src/libshared-glib.la \
 			$(GLIB_LIBS) $(DBUS_LIBS) -ldl -lrt
 
+unit_tests += unit/test-bap
+
+unit_test_bap_SOURCES = unit/test-bap.c
+unit_test_bap_LDADD = src/libshared-glib.la \
+				lib/libbluetooth-internal.la $(GLIB_LIBS)
+
 if MIDI
 unit_tests += unit/test-midi
 unit_test_midi_CPPFLAGS = $(AM_CPPFLAGS) $(ALSA_CFLAGS) -DMIDI_TEST
diff --git a/unit/test-bap.c b/unit/test-bap.c
new file mode 100644
index 000000000000..afeefac84091
--- /dev/null
+++ b/unit/test-bap.c
@@ -0,0 +1,568 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2022  Intel Corporation.
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+
+#include <glib.h>
+
+#include "lib/bluetooth.h"
+#include "lib/uuid.h"
+#include "src/shared/util.h"
+#include "src/shared/io.h"
+#include "src/shared/tester.h"
+#include "src/shared/queue.h"
+#include "src/shared/att.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-client.h"
+#include "src/shared/bap.h"
+
+struct test_data {
+	struct bt_gatt_client *client;
+	struct bt_bap *bap;
+	size_t iovcnt;
+	struct iovec *iov;
+};
+
+#define iov_data(args...) ((const struct iovec[]) { args })
+
+#define define_test(name, function, args...)			\
+	do {							\
+		const struct iovec iov[] = { args };		\
+		static struct test_data data;			\
+		data.iovcnt = ARRAY_SIZE(iov_data(args));	\
+		data.iov = util_iov_dup(iov, ARRAY_SIZE(iov_data(args))); \
+		tester_add(name, &data, test_setup, function,	\
+				test_teardown);			\
+	} while (0)
+
+static void client_ready_cb(bool success, uint8_t att_ecode, void *user_data)
+{
+	if (!success)
+		tester_setup_failed();
+	else
+		tester_setup_complete();
+}
+
+/* GATT Discover All procedure */
+static const struct iovec setup_data[] = {
+	/* ATT: Exchange MTU Response (0x03) len 2
+	 *   Server RX MTU: 64
+	 */
+	IOV_DATA(0x02, 0x40, 0x00),
+	/* ATT: Exchange MTU Request (0x02) len 2
+	 *    Client RX MTU: 64
+	 */
+	IOV_DATA(0x03, 0x40, 0x00),
+	/* ATT: Read By Type Request (0x08) len 6
+	 *   Handle range: 0x0001-0xffff
+	 *   Attribute type: Server Supported Features (0x2b3a)
+	 */
+	IOV_DATA(0x08, 0x01, 0x00, 0xff, 0xff, 0x3a, 0x2b),
+	/* ATT: Error Response (0x01) len 4
+	 *   Read By Type Request (0x08)
+	 *   Handle: 0x0001
+	 *   Error: Attribute Not Found (0x0a)
+	 */
+	IOV_DATA(0x01, 0x08, 0x01, 0x00, 0x0a),
+	/*
+	 * ATT: Read By Group Type Request (0x10) len 6
+	 *   Handle range: 0x0001-0xffff
+	 *   Attribute group type: Primary Service (0x2800)
+	 */
+	IOV_DATA(0x10, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28),
+	/*
+	 * ATT: Read By Group Type Response (0x11) len 37
+	 *   Attribute data length: 6
+	 *   Attribute group list: 2 entries
+	 *   Handle range: 0x0001-0x0013
+	 *   UUID: Published Audio Capabilities (0x1850)
+	 *   Handle range: 0x0014-0x0023
+	 *   UUID: Audio Stream Control (0x184e)
+	 */
+	IOV_DATA(0x11, 0x06,
+		0x01, 0x00, 0x13, 0x00, 0x50, 0x18,
+		0x14, 0x00, 0x23, 0x00, 0x4e, 0x18),
+	/* ATT: Read By Group Type Request (0x10) len 6
+	 *   Handle range: 0x0024-0xffff
+	 *   Attribute group type: Primary Service (0x2800)
+	 */
+	IOV_DATA(0x10, 0x24, 0x00, 0xff, 0xff, 0x00, 0x28),
+	/* ATT: Error Response (0x01) len 4
+	 *   Read By Group Type Request (0x10)
+	 *   Handle: 0x0024
+	 *   Error: Attribute Not Found (0x0a)
+	 */
+	IOV_DATA(0x01, 0x10, 0x24, 0x00, 0x0a),
+	/* ATT: Read By Group Type Request (0x10) len 6
+	 *   Handle range: 0x0001-0xffff
+	 *   Attribute group type: Secondary Service (0x2801)
+	 */
+	IOV_DATA(0x10, 0x01, 0x00, 0xff, 0xff, 0x01, 0x28),
+	/* ATT: Error Response (0x01) len 4
+	 *   Read By Group Type Request (0x10)
+	 *   Handle: 0x0001
+	 *   Error: Attribute Not Found (0x0a)
+	 */
+	IOV_DATA(0x01, 0x10, 0x01, 0x00, 0x0a),
+	/* ATT: Read By Type Request (0x08) len 6
+	 *   Handle range: 0x0001-0x0023
+	 *   Attribute group type: Include (0x2802)
+	 */
+	IOV_DATA(0x08, 0x01, 0x00, 0x23, 0x00, 0x02, 0x28),
+	/* ATT: Error Response (0x01) len 4
+	 *   Read By Group Type Request (0x10)
+	 *   Handle: 0x0001
+	 *   Error: Attribute Not Found (0x0a)
+	 */
+	IOV_DATA(0x01, 0x08, 0x01, 0x00, 0x0a),
+	/* ATT: Read By Type Request (0x08) len 6
+	 *   Handle range: 0x0001-0x0023
+	 *   Attribute type: Characteristic (0x2803)
+	 */
+	IOV_DATA(0x08, 0x01, 0x00, 0x23, 0x00, 0x03, 0x28),
+	/* ATT: Read By Type Response (0x09) len 57
+	 * Attribute data length: 7
+	 * Attribute data list: 8 entries
+	 *   Handle: 0x0002
+	 *   Value: 120300c92b
+	 *   Properties: 0x12
+	 *     Read (0x02)
+	 *     Notify (0x10)
+	 *   Value Handle: 0x0003
+	 *   Value UUID: Sink PAC (0x2bc9)
+	 *   Handle: 0x0005
+	 *   Value: 120600ca2b
+	 *   Properties: 0x12
+	 *     Read (0x02)
+	 *     Notify (0x10)
+	 *   Value Handle: 0x0006
+	 *   Value UUID: Sink Audio Locations (0x2bca)
+	 *   Handle: 0x0008
+	 *   Value: 120900cb2b
+	 *   Properties: 0x12
+	 *     Read (0x02)
+	 *     Notify (0x10)
+	 *   Value Handle: 0x0009
+	 *   Value UUID: Source PAC (0x2bcb)
+	 *   Handle: 0x000b
+	 *   Value: 120c00cc2b
+	 *   Properties: 0x12
+	 *     Read (0x02)
+	 *     Notify (0x10)
+	 *  Value Handle: 0x000c
+	 *  Value UUID: Source Audio Locations (0x2bcc)
+	 *  Handle: 0x000e
+	 *  Value: 120f00cd2b
+	 *  Properties: 0x12
+	 *    Read (0x02)
+	 *    Notify (0x10)
+	 *  Value Handle: 0x000f
+	 *  Value UUID: Available Audio Contexts (0x2bcd)
+	 *  Handle: 0x0011
+	 *  Value: 121200ce2b
+	 *  Properties: 0x12
+	 *    Read (0x02)
+	 *    Notify (0x10)
+	 *  Value Handle: 0x0012
+	 *  Value UUID: Supported Audio Contexts (0x2bce)
+	 *  Handle: 0x0015
+	 *  Value: 121600c42b
+	 *  Properties: 0x12
+	 *    Read (0x02)
+	 *    Notify (0x10)
+	 *  Value Handle: 0x0016
+	 *  Value UUID: Sink ASE (0x2bc4)
+	 *  Handle: 0x0018
+	 *  Value: 121900c42b
+	 *  Properties: 0x12
+	 *    Read (0x02)
+	 *    Notify (0x10)
+	 *  Value Handle: 0x0019
+	 *  Value UUID: Sink ASE (0x2bc4)
+	 */
+	IOV_DATA(0x09, 0x07,
+		0x02, 0x00, 0x12, 0x03, 0x00, 0xc9, 0x2b,
+		0x05, 0x00, 0x12, 0x06, 0x00, 0xca, 0x2b,
+		0x08, 0x00, 0x12, 0x09, 0x00, 0xcb, 0x2b,
+		0x0b, 0x00, 0x12, 0x0c, 0x00, 0xcc, 0x2b,
+		0x0e, 0x00, 0x12, 0x0f, 0x00, 0xcd, 0x2b,
+		0x11, 0x00, 0x12, 0x12, 0x00, 0xce, 0x2b,
+		0x15, 0x00, 0x12, 0x16, 0x00, 0xc4, 0x2b,
+		0x18, 0x00, 0x12, 0x19, 0x00, 0xc4, 0x2b),
+	/* ATT: Read By Type Request (0x08) len 6
+	 *   Handle range: 0x0001-0x0023
+	 *   Attribute type: Characteristic (0x2803)
+	 */
+	IOV_DATA(0x08, 0x19, 0x00, 0x23, 0x00, 0x03, 0x28),
+	/* ATT: Read By Type Response (0x09) len 22
+	 * Attribute data length: 7
+	 * Attribute data list: 3 entries
+	 *   Handle: 0x001b
+	 *   Value: 121c00c52b
+	 *   Properties: 0x12
+	 *     Read (0x02)
+	 *     Notify (0x10)
+	 *   Value Handle: 0x001c
+	 *   Value UUID: Source ASE (0x2bc5)
+	 *   Handle: 0x001e
+	 *   Value: 121f00c52b
+	 *   Properties: 0x12
+	 *     Read (0x02)
+	 *     Notify (0x10)
+	 *   Value Handle: 0x001f
+	 *   Value UUID: Source ASE (0x2bc5)
+	 *   Handle: 0x0021
+	 *   Value: 182200c62b
+	 *   Properties: 0x18
+	 *     Write (0x08)
+	 *     Notify (0x10)
+	 *   Value Handle: 0x0022
+	 *   Value UUID: ASE Control Point (0x2bc6)
+	 */
+	IOV_DATA(0x09, 0x07,
+		0x1b, 0x00, 0x12, 0x1c, 0x00, 0xc5, 0x2b,
+		0x1e, 0x00, 0x12, 0x1f, 0x00, 0xc5, 0x2b,
+		0x21, 0x00, 0x18, 0x22, 0x00, 0xc6, 0x2b),
+	/* ATT: Read By Type Request (0x08) len 6
+	 *   Handle range: 0x0022-0x0023
+	 *   Attribute type: Characteristic (0x2803)
+	 */
+	IOV_DATA(0x08, 0x22, 0x00, 0x23, 0x00, 0x03, 0x28),
+	/* ATT: Error Response (0x01) len 4
+	 *   Read By Type Request (0x08)
+	 *   Handle: 0x0022
+	 *   Error: Attribute Not Found (0x0a)
+	 */
+	IOV_DATA(0x01, 0x08, 0x23, 0x00, 0x0a),
+	/* ACL Data TX: Handle 42 flags 0x00 dlen 11
+	 *   ATT: Read By Type Request (0x08) len 6
+	 *   Handle range: 0x0001-0xffff
+	 *   Attribute type: Database Hash (0x2b2a)
+	 */
+	IOV_DATA(0x08, 0x01, 0x00, 0xff, 0xff, 0x2a, 0x2b),
+	/* ATT: Error Response (0x01) len 4
+	 *   Read By Type Request (0x08)
+	 *   Handle: 0x0001
+	 *   Error: Attribute Not Found (0x0a)
+	 */
+	IOV_DATA(0x01, 0x08, 0x01, 0x00, 0x0a),
+};
+
+static void print_debug(const char *str, void *user_data)
+{
+	const char *prefix = user_data;
+
+	if (tester_use_debug())
+		tester_debug("%s%s", prefix, str);
+}
+
+static void test_setup(const void *user_data)
+{
+	struct test_data *data = (void *)user_data;
+	struct bt_att *att;
+	struct gatt_db *db;
+	struct io *io;
+
+	io = tester_setup_io(setup_data, ARRAY_SIZE(setup_data));
+	g_assert(io);
+
+	att = bt_att_new(io_get_fd(io), false);
+	g_assert(att);
+
+	bt_att_set_debug(att, BT_ATT_DEBUG, print_debug, "bt_att:", NULL);
+
+	db = gatt_db_new();
+	g_assert(db);
+
+	data->client = bt_gatt_client_new(db, att, 64, 0);
+	g_assert(data->client);
+
+	bt_gatt_client_set_debug(data->client, print_debug, "bt_gatt_client:",
+						NULL);
+
+	bt_gatt_client_ready_register(data->client, client_ready_cb, data,
+						NULL);
+
+	bt_att_unref(att);
+	gatt_db_unref(db);
+}
+
+static void test_complete_cb(const void *user_data)
+{
+	tester_test_passed();
+}
+
+static void test_client(const void *user_data)
+{
+	struct test_data *data = (void *)user_data;
+	struct io *io;
+	struct gatt_db *db;
+
+	io = tester_setup_io(data->iov, data->iovcnt);
+	g_assert(io);
+
+	tester_io_set_complete_func(test_complete_cb);
+
+	db = gatt_db_new();
+	g_assert(db);
+
+	data->bap = bt_bap_new(db, bt_gatt_client_get_db(data->client));
+	g_assert(data->bap);
+
+	bt_bap_set_debug(data->bap, print_debug, "bt_bap:", NULL);
+
+	bt_bap_attach(data->bap, data->client);
+}
+
+static void test_teardown(const void *user_data)
+{
+	struct test_data *data = (void *)user_data;
+
+	bt_bap_unref(data->bap);
+	bt_gatt_client_unref(data->client);
+	util_iov_free(data->iov, data->iovcnt);
+
+	tester_teardown_complete();
+}
+
+/* ATT: Read Request (0x0a) len 2
+ *   Handle: 0x0003 Type: Sink PAC (0x2bc9)
+ * ATT: Read Response (0x0b) len 24
+ *   Value: 010600000000100301ff0002020302030305041e00f00000
+ *   Handle: 0x0003 Type: Sink PAC (0x2bc9)
+ *     Number of PAC(s): 1
+ *       PAC #0:
+ *         Codec: LC3 (0x06)
+ *         Codec Specific Capabilities #0: len 0x03 type 0x01
+ *         Sampling Frequencies: 0x00ff
+ *           8 Khz (0x0001)
+ *           11.25 Khz (0x0002)
+ *           16 Khz (0x0004)
+ *           22.05 Khz (0x0008)
+ *           24 Khz (0x0010)
+ *           32 Khz (0x0020)
+ *           44.1 Khz (0x0040)
+ *           48 Khz (0x0080)
+ *       Codec Specific Capabilities #1: len 0x02 type 0x02
+ *         Frame Duration: 0x0003
+ *           7.5 ms (0x01)
+ *           10 ms (0x02)
+ *       Codec Specific Capabilities #2: len 0x02 type 0x03
+ *         Audio Channel Count: 0x03
+ *           1 channel (0x01)
+ *           2 channels (0x02)
+ *       Codec Specific Capabilities #3: len 0x05 type 0x04
+ *         Frame Length: 30 (0x001e) - 240 (0x00f0)
+ * ATT: Read Request (0x0a) len 2
+ *   Handle: 0x0006 Type: Sink Audio Location (0x2bca)
+ * ATT: Read Response (0x0b) len 4
+ *   Value: 03000000
+ *   Handle: 0x0006 Type: Sink Audio Locations (0x2bca)
+ *     Location: 0x00000003
+ *       Front Left (0x00000001)
+ *       Front Right (0x00000002)
+ */
+#define DISC_SINK_PAC \
+	IOV_DATA(0x0a, 0x03, 0x00), \
+	IOV_DATA(0x0b, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x01, \
+		0xff, 0x00, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x05, 0x04, \
+		0x1e, 0x00, 0xf0, 0x00, 0x00), \
+	IOV_DATA(0x0a, 0x06, 0x00), \
+	IOV_DATA(0x0b, 0x03, 0x00, 0x00, 0x00)
+
+/* ATT: Read Request (0x0a) len 2
+ *   Handle: 0x0009 Type: Source PAC (0x2bcb)
+ * ATT: Read Response (0x0b) len 24
+ *   Value: 010600000000100301ff0002020302030305041e00f00000
+ *   Handle: 0x0009 Type: Source PAC (0x2bcb)
+ *     Number of PAC(s): 1
+ *       PAC #0:
+ *         Codec: LC3 (0x06)
+ *         Codec Specific Capabilities #0: len 0x03 type 0x01
+ *         Sampling Frequencies: 0x00ff
+ *           8 Khz (0x0001)
+ *           11.25 Khz (0x0002)
+ *           16 Khz (0x0004)
+ *           22.05 Khz (0x0008)
+ *           24 Khz (0x0010)
+ *           32 Khz (0x0020)
+ *           44.1 Khz (0x0040)
+ *           48 Khz (0x0080)
+ *       Codec Specific Capabilities #1: len 0x02 type 0x02
+ *         Frame Duration: 0x0003
+ *           7.5 ms (0x01)
+ *           10 ms (0x02)
+ *       Codec Specific Capabilities #2: len 0x02 type 0x03
+ *         Audio Channel Count: 0x03
+ *           1 channel (0x01)
+ *           2 channels (0x02)
+ *       Codec Specific Capabilities #3: len 0x05 type 0x04
+ *         Frame Length: 30 (0x001e) - 240 (0x00f0)
+ * ATT: Read Request (0x0a) len 2
+ *   Handle: 0x000c Type: Source Audio Location (0x2bcc)
+ * ATT: Read Response (0x0b) len 4
+ *   Value: 03000000
+ *   Handle: 0x000c Type: Source Audio Locations (0x2bcc)
+ *     Location: 0x00000003
+ *       Front Left (0x00000001)
+ *       Front Right (0x00000002)
+ */
+#define DISC_SOURCE_PAC \
+	DISC_SINK_PAC, \
+	IOV_DATA(0x0a, 0x09, 0x00), \
+	IOV_DATA(0x0b, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x01, \
+		0xff, 0x00, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x05, 0x04, \
+		0x1e, 0x00, 0xf0, 0x00, 0x00), \
+	IOV_DATA(0x0a, 0x0c, 0x00), \
+	IOV_DATA(0x0b, 0x03, 0x00, 0x00, 0x00)
+
+/* ATT: Read Request (0x0a) len 2
+ *   Handle: 0x000f Type: Available Audio Contexts (0x2bcd)
+ * ATT: Read Response (0x0b) len 4
+ *   Value: ff0f0e00
+ *   Handle: 0x000f Type: Available Audio Contexts (0x2bcd)
+ */
+#define DISC_CTX \
+	DISC_SOURCE_PAC, \
+	IOV_DATA(0x0a, 0x0f, 0x00), \
+	IOV_DATA(0x0b, 0xff, 0x0f, 0x0e, 0x00)
+
+/* ATT: Read Request (0x0a) len 2
+ *   Handle: 0x0012 Type: Supported Audio Contexts (0x2bce)
+ * ATT: Read Response (0x0b) len 4
+ *   Value: ff0f0e00
+ *   Handle: 0x0012 Type: Supported Audio Contexts (0x2bce)
+ */
+#define DISC_SUP_CTX \
+	DISC_CTX, \
+	IOV_DATA(0x0a, 0x12, 0x00), \
+	IOV_DATA(0x0b, 0xff, 0x0f, 0x0e, 0x00)
+
+/* ATT: Read Request (0x0a) len 2
+ *   Handle: 0x0016 Type: Sink ASE (0x2bc4)
+ * ATT: Read Response (0x0b) len 4
+ *   Value: 0100
+ *   Handle: 0x0016 Type: Sink ASE (0x2bc4)
+ * ATT: Write Request (0x12) len 4
+ *   Handle: 0x0017 Type: Client Characteristic Configuration (0x2902)
+ *     Data: 0100
+ *       Notification (0x01)
+ * ATT: Write Response (0x13) len 0
+ * ATT: Read Request (0x0a) len 2
+ *   Handle: 0x0019 Type: Sink ASE (0x2bc4)
+ * ATT: Read Response (0x0b) len 4
+ *   Value: 0200
+ *   Handle: 0x0019 Type: Sink ASE (0x2bc4)
+ * ATT: Write Request (0x12) len 4
+ *   Handle: 0x001a Type: Client Characteristic Configuration (0x2902)
+ *     Data: 0100
+ *       Notification (0x01)
+ * ATT: Write Response (0x13) len 0
+ */
+#define DISC_SINK_ASE \
+	DISC_SUP_CTX, \
+	IOV_DATA(0x0a, 0x16, 0x00), \
+	IOV_DATA(0x0b, 0x01, 0x00), \
+	IOV_DATA(0x12, 0x17, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x0a, 0x19, 0x00), \
+	IOV_DATA(0x0b, 0x02, 0x00), \
+	IOV_DATA(0x12, 0x1a, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13)
+
+/* ATT: Read Request (0x0a) len 2
+ *   Handle: 0x001c Type: Source ASE (0x2bc5)
+ * ATT: Read Response (0x0b) len 4
+ *   Value: 0300
+ *   Handle: 0x001c Type: Source ASE (0x2bc5)
+ * ATT: Write Request (0x12) len 4
+ *   Handle: 0x001d Type: Client Characteristic Configuration (0x2902)
+ *     Data: 0100
+ *       Notification (0x01)
+ * ATT: Write Response (0x13) len 0
+ * ATT: Read Request (0x0a) len 2
+ *   Handle: 0x001f Type: Source ASE (0x2bc5)
+ * ATT: Read Response (0x0b) len 4
+ *   Value: 0400
+ *   Handle: 0x001f Type: Source ASE (0x2bc5)
+ * ATT: Write Request (0x12) len 4
+ *   Handle: 0x0020 Type: Client Characteristic Configuration (0x2902)
+ *     Data: 0100
+ *       Notification (0x01)
+ * ATT: Write Response (0x13) len 0
+ * ATT: Write Request (0x12) len 4
+ *   Handle: 0x0023 Type: Client Characteristic Configuration (0x2902)
+ *     Data: 0100
+ *       Notification (0x01)
+ * ATT: Write Response (0x13) len 0
+ */
+#define DISC_SOURCE_ASE \
+	DISC_SINK_ASE, \
+	IOV_DATA(0x0a, 0x1c, 0x00), \
+	IOV_DATA(0x0b, 0x03, 0x00), \
+	IOV_DATA(0x12, 0x1d, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x0a, 0x1f, 0x00), \
+	IOV_DATA(0x0b, 0x04, 0x00), \
+	IOV_DATA(0x12, 0x20, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13), \
+	IOV_DATA(0x12, 0x23, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13)
+
+static void test_disc(void)
+{
+	/* The IUT discovers the characteristics specified in the PAC
+	 * Characteristic and Location Characteristic columns in Table 4.4.
+	 * The IUT reads the values of the characteristics specified in the PAC
+	 * Characteristic and Location Characteristic columns.
+	 */
+	define_test("BAP/UCL/DISC/BV-01-C", test_client, DISC_SINK_PAC);
+	define_test("BAP/UCL/DISC/BV-02-C", test_client, DISC_SOURCE_PAC);
+
+	/* BAP/UCL/DISC/BV-06-C [Discover Available Audio Contexts]
+	 *
+	 * The IUT successfully reads the value of the Available Audio Contexts
+	 * characteristic on the LowerTester.
+	 */
+	define_test("BAP/UCL/DISC/BV-06-C", test_client, DISC_CTX);
+
+	/* BAP/UCL/DISC/BV-05-C [Discover Supported Audio Contexts]
+	 *
+	 * The IUT successfully reads the value of the Supported Audio Contexts
+	 * characteristic on the Lower Tester.
+	 */
+	define_test("BAP/UCL/DISC/BV-05-C", test_client, DISC_SUP_CTX);
+
+	/* BAP/UCL/DISC/BV-03-C [Discover Sink ASE_ID]
+	 * BAP/UCL/DISC/BV-04-C [Discover Source ASE_ID]
+	 *
+	 * The IUT successfully reads the ASE_ID values of each discovered ASE
+	 * characteristic on the LowerTester.
+	 */
+	define_test("BAP/UCL/DISC/BV-03-C", test_client, DISC_SINK_ASE);
+	define_test("BAP/UCL/DISC/BV-04-C", test_client, DISC_SOURCE_ASE);
+}
+
+int main(int argc, char *argv[])
+{
+	tester_init(&argc, &argv);
+
+	test_disc();
+
+	return tester_run();
+}
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH BlueZ 1/6] monitor/att: Fix not dequeing att_read on error response
  2022-11-15  0:30 [PATCH BlueZ 1/6] monitor/att: Fix not dequeing att_read on error response Luiz Augusto von Dentz
                   ` (4 preceding siblings ...)
  2022-11-15  0:30 ` [PATCH BlueZ 6/6] unit: Introduce test-bap Luiz Augusto von Dentz
@ 2022-11-15 19:40 ` patchwork-bot+bluetooth
  5 siblings, 0 replies; 7+ messages in thread
From: patchwork-bot+bluetooth @ 2022-11-15 19:40 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

Hello:

This series was applied to bluetooth/bluez.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:

On Mon, 14 Nov 2022 16:30:33 -0800 you wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> 
> If a read/read by type fails it needs to be dequeued otherwise it can
> cause the next operation of the same type to return the wrong request
> and possible decoding as if it was a different attribute type.
> ---
>  monitor/att.c | 109 +++++++++++++++++++++++++++-----------------------
>  1 file changed, 58 insertions(+), 51 deletions(-)

Here is the summary with links:
  - [BlueZ,1/6] monitor/att: Fix not dequeing att_read on error response
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=b3a8f8fea99b
  - [BlueZ,2/6] shared/util: Add iovec helpers
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=7c2e276d9e7c
  - [BlueZ,3/6] shared/bap: Make use of util_iov helpers
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=f96bccd80979
  - [BlueZ,4/6] shared/tester: Add tester_io_set_complete_func
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=918c73acb778
  - [BlueZ,5/6] shared/bap: Fix crash when canceling requests
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=7fcd6889fb13
  - [BlueZ,6/6] unit: Introduce test-bap
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=1ebbfee34517

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



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-11-15 19:40 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-15  0:30 [PATCH BlueZ 1/6] monitor/att: Fix not dequeing att_read on error response Luiz Augusto von Dentz
2022-11-15  0:30 ` [PATCH BlueZ 2/6] shared/util: Add iovec helpers Luiz Augusto von Dentz
2022-11-15  0:30 ` [PATCH BlueZ 3/6] shared/bap: Make use of util_iov helpers Luiz Augusto von Dentz
2022-11-15  0:30 ` [PATCH BlueZ 4/6] shared/tester: Add tester_io_set_complete_func Luiz Augusto von Dentz
2022-11-15  0:30 ` [PATCH BlueZ 5/6] shared/bap: Fix crash when canceling requests Luiz Augusto von Dentz
2022-11-15  0:30 ` [PATCH BlueZ 6/6] unit: Introduce test-bap Luiz Augusto von Dentz
2022-11-15 19:40 ` [PATCH BlueZ 1/6] monitor/att: Fix not dequeing att_read on error response patchwork-bot+bluetooth

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.