Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH BlueZ 1/2] input: Reset report map state on detach
@ 2026-09-25 17:42 Giuseppe Piscitelli
  2026-09-25 17:43 ` [PATCH BlueZ 2/2] unit: Test HoG report map reads after reconnect Giuseppe Piscitelli
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Giuseppe Piscitelli @ 2026-09-25 17:42 UTC (permalink / raw)
  To: linux-bluetooth

From: Giuseppe Piscitelli <35407790+ooonea@users.noreply.github.com>

read_report_map() leaves report_map_id set after a failed read. Detach
cancels queued GATT operations but retains that ID, so a later attach
cannot request the report map again and never creates the UHID device.

Clear the ID when cancelling GATT operations on detach. This also lets
a reconnect retry a read that was still pending at disconnection.

A socketpair reproducer fails to read the map after either an ATT error
or cancellation before this change; both cases create UHID afterwards.
The existing HoG and UHID unit tests also pass.

Assisted-by: OpenAI Codex:gpt-6
---
 profiles/input/hog-lib.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/profiles/input/hog-lib.c b/profiles/input/hog-lib.c
index 6c75c60..2b6dcae 100644
--- a/profiles/input/hog-lib.c
+++ b/profiles/input/hog-lib.c
@@ -1908,6 +1908,7 @@ void bt_hog_detach(struct bt_hog *hog, bool force)
 	}

 	queue_remove_all(hog->gatt_op, cancel_gatt_req, hog, destroy_gatt_req);
+	hog->report_map_id = 0;
 	g_attrib_unref(hog->attrib);
 	hog->attrib = NULL;

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

* [PATCH BlueZ 2/2] unit: Test HoG report map reads after reconnect
  2026-09-25 17:42 [PATCH BlueZ 1/2] input: Reset report map state on detach Giuseppe Piscitelli
@ 2026-09-25 17:43 ` Giuseppe Piscitelli
  2026-09-25 20:05 ` [BlueZ,1/2] input: Reset report map state on detach bluez.test.bot
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Giuseppe Piscitelli @ 2026-09-25 17:43 UTC (permalink / raw)
  To: linux-bluetooth

From: Giuseppe Piscitelli <35407790+ooonea@users.noreply.github.com>

Exercise reconnect after an ATT error and after cancelling a pending
Report Map read. Require a fresh read and validate the resulting
UHID_CREATE2 descriptor on a simulated transport.

Stub Bluetooth address lookup for the Unix socketpair fixture. Both
cases fail without resetting report_map_id on detach.

Assisted-by: OpenAI Codex:gpt-6
---
 Makefile.am     |   2 +-
 unit/test-hog.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 140 insertions(+), 1 deletion(-)

diff --git a/Makefile.am b/Makefile.am
index 1d46b9b..1621794 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -767,7 +767,7 @@ unit_test_gatt_LDADD = src/libshared-glib.la \
 unit_tests += unit/test-hog

 unit_test_hog_SOURCES = unit/test-hog.c \
-			$(btio_sources) \
+			btio/btio.h \
 			profiles/input/hog-lib.h profiles/input/hog-lib.c \
 			profiles/scanparam/scpp.h profiles/scanparam/scpp.c \
 			profiles/battery/bas.h profiles/battery/bas.c \
diff --git a/unit/test-hog.c b/unit/test-hog.c
index 45ffe71..405af8a 100644
--- a/unit/test-hog.c
+++ b/unit/test-hog.c
@@ -17,6 +17,8 @@
 #include <string.h>
 #include <sys/socket.h>
 #include <fcntl.h>
+#include <stdarg.h>
+#include <linux/uhid.h>

 #include <glib.h>

@@ -30,9 +32,28 @@
 #include "src/shared/gatt-db.h"

 #include "attrib/gattrib.h"
+#include "btio/btio.h"

 #include "profiles/input/hog-lib.h"

+gboolean bt_io_get(GIOChannel *io, GError **error, BtIOOption opt, ...)
+{
+	va_list args;
+
+	va_start(args, opt);
+
+	while (opt != BT_IO_OPT_INVALID) {
+		g_assert(opt == BT_IO_OPT_SOURCE_BDADDR ||
+					opt == BT_IO_OPT_DEST_BDADDR);
+		memset(va_arg(args, bdaddr_t *), 0, sizeof(bdaddr_t));
+		opt = va_arg(args, int);
+	}
+
+	va_end(args);
+
+	return TRUE;
+}
+
 struct test_pdu {
 	bool valid;
 	const uint8_t *data;
@@ -211,10 +232,128 @@ static void test_hog(gconstpointer data)
 	g_assert(bt_hog_attach(context->hog, context->attrib));
 }

+static ssize_t receive(int fd, void *buf, size_t size)
+{
+	gint64 deadline = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
+	ssize_t len;
+
+	do {
+		while (g_main_context_iteration(NULL, FALSE))
+			;
+
+		len = recv(fd, buf, size, MSG_DONTWAIT);
+		if (len >= 0)
+			return len;
+
+		g_usleep(1000);
+	} while (g_get_monotonic_time() < deadline);
+
+	return -1;
+}
+
+static void expect_read(int fd, uint8_t handle)
+{
+	uint8_t buf[32];
+	ssize_t len = receive(fd, buf, sizeof(buf));
+
+	g_assert_cmpint(len, ==, 3);
+	g_assert_cmpuint(buf[0], ==, BT_ATT_OP_READ_REQ);
+	g_assert_cmpuint(buf[1], ==, handle);
+	g_assert_cmpuint(buf[2], ==, 0);
+}
+
+static void respond(int fd, const void *buf, size_t size)
+{
+	g_assert_cmpint(send(fd, buf, size, 0), ==, size);
+}
+
+static void test_reconnect(gconstpointer data)
+{
+	const uint8_t info[] = { 0x0b, 0x11, 0x01, 0x00, 0x00 };
+	const uint8_t error[] = { 0x01, 0x0a, 0x05, 0x00, 0x0e };
+	const uint8_t map[] = { 0x0b, 0x05, 0x01, 0x09, 0x02, 0xa1, 0x01,
+				0x09, 0x30, 0x15, 0x81, 0x25, 0x7f, 0x75,
+				0x08, 0x95, 0x01, 0x81, 0x06, 0xc0 };
+	struct gatt_db *db = gatt_db_new();
+	struct gatt_db_attribute *service;
+	struct bt_hog *hog;
+	struct uhid_event ev;
+	GIOChannel *channel;
+	GAttrib *attrib;
+	bt_uuid_t uuid;
+	int att[2], uhid[2];
+	bool cancel = GPOINTER_TO_INT(data);
+
+	g_assert_cmpint(socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK,
+							0, att), ==, 0);
+	g_assert_cmpint(socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK,
+							0, uhid), ==, 0);
+	bt_uuid16_create(&uuid, 0x1812);
+	service = gatt_db_add_service(db, &uuid, true, 5);
+	g_assert(service);
+	bt_uuid16_create(&uuid, 0x2a4a);
+	g_assert(gatt_db_service_add_characteristic(service, &uuid,
+				BT_ATT_PERM_READ, 0x02, NULL, NULL, NULL));
+	bt_uuid16_create(&uuid, 0x2a4b);
+	g_assert(gatt_db_service_add_characteristic(service, &uuid,
+				BT_ATT_PERM_READ, 0x02, NULL, NULL, NULL));
+	gatt_db_service_set_active(service, true);
+	channel = g_io_channel_unix_new(att[0]);
+	g_io_channel_set_close_on_unref(channel, TRUE);
+	attrib = g_attrib_new(channel, 23, false);
+	g_io_channel_unref(channel);
+	hog = bt_hog_new(uhid[0], "report-map-test", 1, 1, 1, 0, db);
+	g_assert(hog);
+	g_assert(bt_hog_attach(hog, attrib));
+	expect_read(att[1], 3);
+	respond(att[1], info, sizeof(info));
+	expect_read(att[1], 5);
+
+	if (!cancel) {
+		respond(att[1], error, sizeof(error));
+
+		while (g_main_context_iteration(NULL, FALSE))
+			;
+	}
+
+	bt_hog_detach(hog, false);
+	g_attrib_unref(attrib);
+	close(att[1]);
+	g_assert_cmpint(socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK,
+							0, att), ==, 0);
+	channel = g_io_channel_unix_new(att[0]);
+	g_io_channel_set_close_on_unref(channel, TRUE);
+	attrib = g_attrib_new(channel, 23, false);
+	g_io_channel_unref(channel);
+	g_assert(bt_hog_attach(hog, attrib));
+	expect_read(att[1], 3);
+	respond(att[1], info, sizeof(info));
+	expect_read(att[1], 5);
+	respond(att[1], map, sizeof(map));
+	g_assert_cmpint(receive(uhid[1], &ev, sizeof(ev)), ==, sizeof(ev));
+	g_assert_cmpuint(ev.type, ==, UHID_CREATE2);
+	g_assert_cmpuint(ev.u.create2.rd_size, ==, sizeof(map) - 1);
+	g_assert_cmpmem(ev.u.create2.rd_data, ev.u.create2.rd_size,
+						map + 1, sizeof(map) - 1);
+	bt_hog_detach(hog, true);
+	bt_hog_unref(hog);
+	g_attrib_unref(attrib);
+	gatt_db_unref(db);
+	close(att[1]);
+	close(uhid[0]);
+	close(uhid[1]);
+	tester_test_passed();
+}
+
 int main(int argc, char *argv[])
 {
 	tester_init(&argc, &argv);

+	tester_add("/hog/report-map/error-reconnect", GINT_TO_POINTER(false),
+					NULL, test_reconnect, NULL);
+	tester_add("/hog/report-map/cancel-reconnect", GINT_TO_POINTER(true),
+					NULL, test_reconnect, NULL);
+
 	define_test("/TP/HGRF/RH/BV-01-I", test_hog,
 		raw_pdu(0x10, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28),
 		raw_pdu(0x11, 0x06, 0x01, 0x00, 0x04, 0x00, 0x12,


On Fri, 25 Sep 2026 12:42:44 -0500, Giuseppe Piscitelli
<ooonea@gmail.com> wrote:
> From: Giuseppe Piscitelli <35407790+ooonea@users.noreply.github.com>
>
> read_report_map() leaves report_map_id set after a failed read. Detach
> cancels queued GATT operations but retains that ID, so a later attach
> cannot request the report map again and never creates the UHID device.
>
> Clear the ID when cancelling GATT operations on detach. This also lets
> a reconnect retry a read that was still pending at disconnection.
>
> A socketpair reproducer fails to read the map after either an ATT error
> or cancellation before this change; both cases create UHID afterwards.
> The existing HoG and UHID unit tests also pass.
>
> Assisted-by: OpenAI Codex:gpt-6
> ---
>  profiles/input/hog-lib.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/profiles/input/hog-lib.c b/profiles/input/hog-lib.c
> index 6c75c60..2b6dcae 100644
> --- a/profiles/input/hog-lib.c
> +++ b/profiles/input/hog-lib.c
> @@ -1908,6 +1908,7 @@ void bt_hog_detach(struct bt_hog *hog, bool force)
>  	}
>
>  	queue_remove_all(hog->gatt_op, cancel_gatt_req, hog, destroy_gatt_req);
> +	hog->report_map_id = 0;
>  	g_attrib_unref(hog->attrib);
>  	hog->attrib = NULL;

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

* RE: [BlueZ,1/2] input: Reset report map state on detach
  2026-09-25 17:42 [PATCH BlueZ 1/2] input: Reset report map state on detach Giuseppe Piscitelli
  2026-09-25 17:43 ` [PATCH BlueZ 2/2] unit: Test HoG report map reads after reconnect Giuseppe Piscitelli
@ 2026-09-25 20:05 ` bluez.test.bot
  2026-09-25 22:03 ` [PATCH BlueZ v2 1/2] " Giuseppe Piscitelli
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: bluez.test.bot @ 2026-09-25 20:05 UTC (permalink / raw)
  To: linux-bluetooth, ooonea

[-- Attachment #1: Type: text/plain, Size: 1581 bytes --]

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/series/1173956/

---Test result---

Test Summary:
CheckPatch                    PASS      6.93 seconds
GitLint                       FAIL      0.73 seconds
BuildEll                      PASS      20.05 seconds
BluezMake                     PASS      389.15 seconds
MakeCheck                     PASS      14.40 seconds
MakeDistcheck                 PASS      148.33 seconds
CheckValgrind                 PASS      238.68 seconds
CheckSmatch                   PASS      293.29 seconds
bluezmakeextell               PASS      97.60 seconds
TestFunctional                PASS      1109.69 seconds
IncrementalBuild              PASS      397.03 seconds
ScanBuild                     PASS      1146.09 seconds

Details
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[BlueZ,2/2] unit: Test HoG report map reads after reconnect

45: B3 Line contains hard tab characters (\t): ">  	}"
47: B3 Line contains hard tab characters (\t): ">  	queue_remove_all(hog->gatt_op, cancel_gatt_req, hog, destroy_gatt_req);"
48: B3 Line contains hard tab characters (\t): "> +	hog->report_map_id = 0;"
49: B3 Line contains hard tab characters (\t): ">  	g_attrib_unref(hog->attrib);"
50: B3 Line contains hard tab characters (\t): ">  	hog->attrib = NULL;"


https://github.com/bluez/bluez/pull/2590

---
Regards,
Linux Bluetooth


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

* [PATCH BlueZ v2 1/2] input: Reset report map state on detach
  2026-09-25 17:42 [PATCH BlueZ 1/2] input: Reset report map state on detach Giuseppe Piscitelli
  2026-09-25 17:43 ` [PATCH BlueZ 2/2] unit: Test HoG report map reads after reconnect Giuseppe Piscitelli
  2026-09-25 20:05 ` [BlueZ,1/2] input: Reset report map state on detach bluez.test.bot
@ 2026-09-25 22:03 ` Giuseppe Piscitelli
  2026-09-26  1:30   ` [BlueZ,v2,1/2] " bluez.test.bot
  2026-09-25 22:03 ` [PATCH BlueZ v2 2/2] unit: Test HoG report map reads after reconnect Giuseppe Piscitelli
  2026-09-28 17:48 ` [PATCH BlueZ 1/2] input: Reset report map state on detach Luiz Augusto von Dentz
  4 siblings, 1 reply; 8+ messages in thread
From: Giuseppe Piscitelli @ 2026-09-25 22:03 UTC (permalink / raw)
  To: linux-bluetooth

From: Giuseppe Piscitelli <35407790+ooonea@users.noreply.github.com>

read_report_map() leaves report_map_id set after a failed read. Detach
cancels queued GATT operations but retains that ID, so a later attach
cannot request the report map again and never creates the UHID device.

Clear the ID when cancelling GATT operations on detach. This also lets
a reconnect retry a read that was still pending at disconnection.

A socketpair reproducer fails to read the map after either an ATT error
or cancellation before this change; both cases create UHID afterwards.
The existing HoG and UHID unit tests also pass.

Assisted-by: OpenAI Codex:gpt-6
---
v2: Resend without quoted email history; code unchanged.

 profiles/input/hog-lib.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/profiles/input/hog-lib.c b/profiles/input/hog-lib.c
index 6c75c60..2b6dcae 100644
--- a/profiles/input/hog-lib.c
+++ b/profiles/input/hog-lib.c
@@ -1908,6 +1908,7 @@ void bt_hog_detach(struct bt_hog *hog, bool force)
 	}

 	queue_remove_all(hog->gatt_op, cancel_gatt_req, hog, destroy_gatt_req);
+	hog->report_map_id = 0;
 	g_attrib_unref(hog->attrib);
 	hog->attrib = NULL;

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

* [PATCH BlueZ v2 2/2] unit: Test HoG report map reads after reconnect
  2026-09-25 17:42 [PATCH BlueZ 1/2] input: Reset report map state on detach Giuseppe Piscitelli
                   ` (2 preceding siblings ...)
  2026-09-25 22:03 ` [PATCH BlueZ v2 1/2] " Giuseppe Piscitelli
@ 2026-09-25 22:03 ` Giuseppe Piscitelli
  2026-09-28 17:48 ` [PATCH BlueZ 1/2] input: Reset report map state on detach Luiz Augusto von Dentz
  4 siblings, 0 replies; 8+ messages in thread
From: Giuseppe Piscitelli @ 2026-09-25 22:03 UTC (permalink / raw)
  To: linux-bluetooth

From: Giuseppe Piscitelli <35407790+ooonea@users.noreply.github.com>

Exercise reconnect after an ATT error and after cancelling a pending
Report Map read. Require a fresh read and validate the resulting
UHID_CREATE2 descriptor on a simulated transport.

Stub Bluetooth address lookup for the Unix socketpair fixture. Both
cases fail without resetting report_map_id on detach.

Assisted-by: OpenAI Codex:gpt-6
---
v2: Resend without quoted email history; code unchanged.

 Makefile.am     |   2 +-
 unit/test-hog.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 140 insertions(+), 1 deletion(-)

diff --git a/Makefile.am b/Makefile.am
index 1d46b9b..1621794 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -767,7 +767,7 @@ unit_test_gatt_LDADD = src/libshared-glib.la \
 unit_tests += unit/test-hog

 unit_test_hog_SOURCES = unit/test-hog.c \
-			$(btio_sources) \
+			btio/btio.h \
 			profiles/input/hog-lib.h profiles/input/hog-lib.c \
 			profiles/scanparam/scpp.h profiles/scanparam/scpp.c \
 			profiles/battery/bas.h profiles/battery/bas.c \
diff --git a/unit/test-hog.c b/unit/test-hog.c
index 45ffe71..405af8a 100644
--- a/unit/test-hog.c
+++ b/unit/test-hog.c
@@ -17,6 +17,8 @@
 #include <string.h>
 #include <sys/socket.h>
 #include <fcntl.h>
+#include <stdarg.h>
+#include <linux/uhid.h>

 #include <glib.h>

@@ -30,9 +32,28 @@
 #include "src/shared/gatt-db.h"

 #include "attrib/gattrib.h"
+#include "btio/btio.h"

 #include "profiles/input/hog-lib.h"

+gboolean bt_io_get(GIOChannel *io, GError **error, BtIOOption opt, ...)
+{
+	va_list args;
+
+	va_start(args, opt);
+
+	while (opt != BT_IO_OPT_INVALID) {
+		g_assert(opt == BT_IO_OPT_SOURCE_BDADDR ||
+					opt == BT_IO_OPT_DEST_BDADDR);
+		memset(va_arg(args, bdaddr_t *), 0, sizeof(bdaddr_t));
+		opt = va_arg(args, int);
+	}
+
+	va_end(args);
+
+	return TRUE;
+}
+
 struct test_pdu {
 	bool valid;
 	const uint8_t *data;
@@ -211,10 +232,128 @@ static void test_hog(gconstpointer data)
 	g_assert(bt_hog_attach(context->hog, context->attrib));
 }

+static ssize_t receive(int fd, void *buf, size_t size)
+{
+	gint64 deadline = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
+	ssize_t len;
+
+	do {
+		while (g_main_context_iteration(NULL, FALSE))
+			;
+
+		len = recv(fd, buf, size, MSG_DONTWAIT);
+		if (len >= 0)
+			return len;
+
+		g_usleep(1000);
+	} while (g_get_monotonic_time() < deadline);
+
+	return -1;
+}
+
+static void expect_read(int fd, uint8_t handle)
+{
+	uint8_t buf[32];
+	ssize_t len = receive(fd, buf, sizeof(buf));
+
+	g_assert_cmpint(len, ==, 3);
+	g_assert_cmpuint(buf[0], ==, BT_ATT_OP_READ_REQ);
+	g_assert_cmpuint(buf[1], ==, handle);
+	g_assert_cmpuint(buf[2], ==, 0);
+}
+
+static void respond(int fd, const void *buf, size_t size)
+{
+	g_assert_cmpint(send(fd, buf, size, 0), ==, size);
+}
+
+static void test_reconnect(gconstpointer data)
+{
+	const uint8_t info[] = { 0x0b, 0x11, 0x01, 0x00, 0x00 };
+	const uint8_t error[] = { 0x01, 0x0a, 0x05, 0x00, 0x0e };
+	const uint8_t map[] = { 0x0b, 0x05, 0x01, 0x09, 0x02, 0xa1, 0x01,
+				0x09, 0x30, 0x15, 0x81, 0x25, 0x7f, 0x75,
+				0x08, 0x95, 0x01, 0x81, 0x06, 0xc0 };
+	struct gatt_db *db = gatt_db_new();
+	struct gatt_db_attribute *service;
+	struct bt_hog *hog;
+	struct uhid_event ev;
+	GIOChannel *channel;
+	GAttrib *attrib;
+	bt_uuid_t uuid;
+	int att[2], uhid[2];
+	bool cancel = GPOINTER_TO_INT(data);
+
+	g_assert_cmpint(socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK,
+							0, att), ==, 0);
+	g_assert_cmpint(socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK,
+							0, uhid), ==, 0);
+	bt_uuid16_create(&uuid, 0x1812);
+	service = gatt_db_add_service(db, &uuid, true, 5);
+	g_assert(service);
+	bt_uuid16_create(&uuid, 0x2a4a);
+	g_assert(gatt_db_service_add_characteristic(service, &uuid,
+				BT_ATT_PERM_READ, 0x02, NULL, NULL, NULL));
+	bt_uuid16_create(&uuid, 0x2a4b);
+	g_assert(gatt_db_service_add_characteristic(service, &uuid,
+				BT_ATT_PERM_READ, 0x02, NULL, NULL, NULL));
+	gatt_db_service_set_active(service, true);
+	channel = g_io_channel_unix_new(att[0]);
+	g_io_channel_set_close_on_unref(channel, TRUE);
+	attrib = g_attrib_new(channel, 23, false);
+	g_io_channel_unref(channel);
+	hog = bt_hog_new(uhid[0], "report-map-test", 1, 1, 1, 0, db);
+	g_assert(hog);
+	g_assert(bt_hog_attach(hog, attrib));
+	expect_read(att[1], 3);
+	respond(att[1], info, sizeof(info));
+	expect_read(att[1], 5);
+
+	if (!cancel) {
+		respond(att[1], error, sizeof(error));
+
+		while (g_main_context_iteration(NULL, FALSE))
+			;
+	}
+
+	bt_hog_detach(hog, false);
+	g_attrib_unref(attrib);
+	close(att[1]);
+	g_assert_cmpint(socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK,
+							0, att), ==, 0);
+	channel = g_io_channel_unix_new(att[0]);
+	g_io_channel_set_close_on_unref(channel, TRUE);
+	attrib = g_attrib_new(channel, 23, false);
+	g_io_channel_unref(channel);
+	g_assert(bt_hog_attach(hog, attrib));
+	expect_read(att[1], 3);
+	respond(att[1], info, sizeof(info));
+	expect_read(att[1], 5);
+	respond(att[1], map, sizeof(map));
+	g_assert_cmpint(receive(uhid[1], &ev, sizeof(ev)), ==, sizeof(ev));
+	g_assert_cmpuint(ev.type, ==, UHID_CREATE2);
+	g_assert_cmpuint(ev.u.create2.rd_size, ==, sizeof(map) - 1);
+	g_assert_cmpmem(ev.u.create2.rd_data, ev.u.create2.rd_size,
+						map + 1, sizeof(map) - 1);
+	bt_hog_detach(hog, true);
+	bt_hog_unref(hog);
+	g_attrib_unref(attrib);
+	gatt_db_unref(db);
+	close(att[1]);
+	close(uhid[0]);
+	close(uhid[1]);
+	tester_test_passed();
+}
+
 int main(int argc, char *argv[])
 {
 	tester_init(&argc, &argv);

+	tester_add("/hog/report-map/error-reconnect", GINT_TO_POINTER(false),
+					NULL, test_reconnect, NULL);
+	tester_add("/hog/report-map/cancel-reconnect", GINT_TO_POINTER(true),
+					NULL, test_reconnect, NULL);
+
 	define_test("/TP/HGRF/RH/BV-01-I", test_hog,
 		raw_pdu(0x10, 0x01, 0x00, 0xff, 0xff, 0x00, 0x28),
 		raw_pdu(0x11, 0x06, 0x01, 0x00, 0x04, 0x00, 0x12,

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

* RE: [BlueZ,v2,1/2] input: Reset report map state on detach
  2026-09-25 22:03 ` [PATCH BlueZ v2 1/2] " Giuseppe Piscitelli
@ 2026-09-26  1:30   ` bluez.test.bot
  0 siblings, 0 replies; 8+ messages in thread
From: bluez.test.bot @ 2026-09-26  1:30 UTC (permalink / raw)
  To: linux-bluetooth, ooonea

[-- Attachment #1: Type: text/plain, Size: 1019 bytes --]

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/series/1174115/

---Test result---

Test Summary:
CheckPatch                    PASS      0.37 seconds
GitLint                       PASS      0.26 seconds
BuildEll                      PASS      17.11 seconds
BluezMake                     PASS      303.54 seconds
MakeCheck                     PASS      0.85 seconds
MakeDistcheck                 PASS      127.51 seconds
CheckValgrind                 PASS      131.50 seconds
CheckSmatch                   PASS      222.20 seconds
bluezmakeextell               PASS      83.48 seconds
TestFunctional                PASS      964.15 seconds
IncrementalBuild              PASS      305.70 seconds
ScanBuild                     PASS      881.88 seconds



https://github.com/bluez/bluez/pull/2592

---
Regards,
Linux Bluetooth


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

* Re: [PATCH BlueZ 1/2] input: Reset report map state on detach
  2026-09-25 17:42 [PATCH BlueZ 1/2] input: Reset report map state on detach Giuseppe Piscitelli
                   ` (3 preceding siblings ...)
  2026-09-25 22:03 ` [PATCH BlueZ v2 2/2] unit: Test HoG report map reads after reconnect Giuseppe Piscitelli
@ 2026-09-28 17:48 ` Luiz Augusto von Dentz
  2026-09-28 21:03   ` Giuseppe Piscitelli
  4 siblings, 1 reply; 8+ messages in thread
From: Luiz Augusto von Dentz @ 2026-09-28 17:48 UTC (permalink / raw)
  To: Giuseppe Piscitelli; +Cc: linux-bluetooth

Hi Giuseppe,

On Fri, Sep 25, 2026 at 1:42 PM Giuseppe Piscitelli <ooonea@gmail.com> wrote:
>
> From: Giuseppe Piscitelli <35407790+ooonea@users.noreply.github.com>
>
> read_report_map() leaves report_map_id set after a failed read. Detach
> cancels queued GATT operations but retains that ID, so a later attach
> cannot request the report map again and never creates the UHID device.
>
> Clear the ID when cancelling GATT operations on detach. This also lets
> a reconnect retry a read that was still pending at disconnection.
>
> A socketpair reproducer fails to read the map after either an ATT error
> or cancellation before this change; both cases create UHID afterwards.
> The existing HoG and UHID unit tests also pass.
>
> Assisted-by: OpenAI Codex:gpt-6
> ---
>  profiles/input/hog-lib.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/profiles/input/hog-lib.c b/profiles/input/hog-lib.c
> index 6c75c60..2b6dcae 100644
> --- a/profiles/input/hog-lib.c
> +++ b/profiles/input/hog-lib.c
> @@ -1908,6 +1908,7 @@ void bt_hog_detach(struct bt_hog *hog, bool force)
>         }
>
>         queue_remove_all(hog->gatt_op, cancel_gatt_req, hog, destroy_gatt_req);
> +       hog->report_map_id = 0;
>         g_attrib_unref(hog->attrib);
>         hog->attrib = NULL;

There is a set rewriting hog-lib with
src/shared/gatt-client.c:bt_gatt_client:
https://patchwork.kernel.org/project/bluetooth/patch/20260928173243.1073509-14-luiz.dentz@gmail.com/,
it is probably worth checking if that fixes this issue for you. (hmm,
that seem to not be the case because there is no use of
bt_gatt_client_clone to track HoG operations and then cancel it
properly on unref).

-- 
Luiz Augusto von Dentz

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

* Re: [PATCH BlueZ 1/2] input: Reset report map state on detach
  2026-09-28 17:48 ` [PATCH BlueZ 1/2] input: Reset report map state on detach Luiz Augusto von Dentz
@ 2026-09-28 21:03   ` Giuseppe Piscitelli
  0 siblings, 0 replies; 8+ messages in thread
From: Giuseppe Piscitelli @ 2026-09-28 21:03 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

Hi Luiz,

I tested the linked v5 series with both reconnect cases using simulated
ATT/UHID transports: an ATT error during the Report Map read, and detach
while that read is pending. Both request the map again and create UHID
after reconnect. A late response after cancellation is also ignored.

In patch 13/21 [1], report_map_read_cb() clears the ID on completion,
and bt_hog_detach() explicitly cancels and clears it. These paths cover
both cases without cloning the client. My one-line fix targets the
existing hog-lib.c; v5 already handles these two cases.

[1] https://patchwork.kernel.org/project/bluetooth/patch/20260928173243.1073509-14-luiz.dentz@gmail.com/

Assisted-by: OpenAI Codex:gpt-6

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

end of thread, other threads:[~2026-09-28 21:03 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-25 17:42 [PATCH BlueZ 1/2] input: Reset report map state on detach Giuseppe Piscitelli
2026-09-25 17:43 ` [PATCH BlueZ 2/2] unit: Test HoG report map reads after reconnect Giuseppe Piscitelli
2026-09-25 20:05 ` [BlueZ,1/2] input: Reset report map state on detach bluez.test.bot
2026-09-25 22:03 ` [PATCH BlueZ v2 1/2] " Giuseppe Piscitelli
2026-09-26  1:30   ` [BlueZ,v2,1/2] " bluez.test.bot
2026-09-25 22:03 ` [PATCH BlueZ v2 2/2] unit: Test HoG report map reads after reconnect Giuseppe Piscitelli
2026-09-28 17:48 ` [PATCH BlueZ 1/2] input: Reset report map state on detach Luiz Augusto von Dentz
2026-09-28 21:03   ` Giuseppe Piscitelli

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox