* [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