All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH BlueZ v2 0/8] Add HID over GATT functional tests
@ 2026-09-24 13:55 Luiz Augusto von Dentz
  2026-09-24 13:55 ` [PATCH BlueZ v2 1/8] attrib: Fix unregistering notifications registered with bt_gatt_client Luiz Augusto von Dentz
                   ` (7 more replies)
  0 siblings, 8 replies; 12+ messages in thread
From: Luiz Augusto von Dentz @ 2026-09-24 13:55 UTC (permalink / raw)
  To: linux-bluetooth

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

This adds functional tests for HID over GATT (HoG), with bluetoothctl
registering a HID Service acting as a keyboard, with and without
Shorter Connection Interval (SCI) support, using the new
client/scripts/hog-device*.bt scripts, and the HID host:

 - checking HID Information, HID SCI Mode and HID SCI Information over
   GATT with gatt.select-attribute/gatt.read
 - receiving a few Input Reports notified by the HID device
 - with SCI support, changing the SCI mode, followed by the connection
   rate with mgmt.conn-subrate, and receiving the notification from
   the HID device confirming the mode has been changed

The tests are documented in doc/functional-hog.rst.

To support them:

 - bluetoothctl can now set descriptor values from scripts, and prints
   the MGMT Connection Subrate event
 - btvirt defaults to the latest BR/EDR+LE version (6.2), so Shorter
   Connection Intervals are supported by the emulated controllers,
   with the new -C/--core option to emulate older versions

Also, with -n auto, the number of functional test workers is now
limited by the memory available instead of one per CPU, since running
out of memory with so many VM instances made tests fail at random, and
check-functional uses -n auto by default (override with
CHECK_FUNCTIONAL_JOBS).

v2:
 - Add "attrib: Fix unregistering notifications registered with
   bt_gatt_client", fixing the heap-use-after-free in
   report_notify_destroy reported by TestFunctional on the HoG tests:
   g_attrib_unregister did not unregister the notifications registered
   with bt_gatt_client, so their destroy callback was called after
   HoG had freed its reports.

Luiz Augusto von Dentz (8):
  attrib: Fix unregistering notifications registered with bt_gatt_client
  client/gatt: Fix setting descriptor value from scripts
  client/mgmt: Print Connection Subrate event
  emulator: Default to the latest BR/EDR+LE version
  client/scripts: Add HoG device scripts
  doc: Add functional-hog documentation
  test: functional: add HoG tests
  test: functional: limit the workers by the memory available

 Makefile.am                      |   8 +-
 attrib/gattrib.c                 |  90 +++++++----
 client/gatt.c                    |  25 ++-
 client/mgmt.c                    |  31 ++++
 client/scripts/hog-device-sci.bt |  49 ++++++
 client/scripts/hog-device.bt     |  38 +++++
 doc/functional-hog.rst           | 188 +++++++++++++++++++++++
 doc/functional-testing.rst       |   1 +
 doc/test-functional.rst          |  25 +++
 emulator/main.c                  |  54 ++++++-
 emulator/server.c                |  15 +-
 emulator/server.h                |   2 +
 test/functional/conftest.py      |  46 ++++++
 test/functional/test_hog.py      | 252 +++++++++++++++++++++++++++++++
 14 files changed, 785 insertions(+), 39 deletions(-)
 create mode 100644 client/scripts/hog-device-sci.bt
 create mode 100644 client/scripts/hog-device.bt
 create mode 100644 doc/functional-hog.rst
 create mode 100644 test/functional/test_hog.py

-- 
2.55.0


^ permalink raw reply	[flat|nested] 12+ messages in thread
* [PATCH BlueZ v3 1/9] shared/gatt-client: Fix calling destroy after unregistering notify
@ 2026-09-24 15:46 Luiz Augusto von Dentz
  2026-09-24 19:16 ` Add HID over GATT functional tests bluez.test.bot
  0 siblings, 1 reply; 12+ messages in thread
From: Luiz Augusto von Dentz @ 2026-09-24 15:46 UTC (permalink / raw)
  To: linux-bluetooth

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

bt_gatt_client_unregister_notify resets the callbacks of the
notification but not its destroy callback, which is called once the
notify_data is freed. If a procedure is still pending at that point,
e.g. the write of the CCC to disable the notifications, it holds a
reference to notify_data so destroy is called later, once the user data
may have been freed, e.g. the reports of HoG:

 ERROR: AddressSanitizer: heap-use-after-free
 #11 report_notify_destroy profiles/input/hog-lib.c:359
 #12 attrib_callbacks_destroy attrib/gattrib.c:130
 #13 notify_data_unref src/shared/gatt-client.c:256
 #15 destroy_write_op src/shared/gatt-client.c:3189
 #16 request_unref src/shared/gatt-client.c:201
 #17 destroy_att_send_op src/shared/att.c:215
 #18 bt_att_cancel src/shared/att.c:1925
 #19 cancel_request src/shared/gatt-client.c:2783
 ...
 #21 bt_gatt_client_cancel_all src/shared/gatt-client.c:2811
 #22 bt_gatt_client_free src/shared/gatt-client.c:2290

Call destroy when unregistering instead.
---
 src/shared/gatt-client.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index 92ad7c39c115..cd4270291827 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -3858,6 +3858,15 @@ bool bt_gatt_client_unregister_notify(struct bt_gatt_client *client,
 	notify_data->callback = NULL;
 	notify_data->notify = NULL;
 
+	/* Call destroy now as the user data may be freed once unregistered,
+	 * while notify_data may still be referenced by a pending procedure,
+	 * e.g. the write of the CCC.
+	 */
+	if (notify_data->destroy) {
+		notify_data->destroy(notify_data->user_data);
+		notify_data->destroy = NULL;
+	}
+
 	complete_unregister_notify(notify_data);
 	return true;
 }
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread
* [PATCH BlueZ v1 1/7] client/gatt: Fix setting descriptor value from scripts
@ 2026-09-23 19:31 Luiz Augusto von Dentz
  2026-09-23 22:30 ` Add HID over GATT functional tests bluez.test.bot
  0 siblings, 1 reply; 12+ messages in thread
From: Luiz Augusto von Dentz @ 2026-09-23 19:31 UTC (permalink / raw)
  To: linux-bluetooth

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

gatt.register-descriptor completed the command right after prompting
for the value, so when run from a script the line with the value was
executed as a command instead of being passed to the prompt, causing
the descriptor to be unregistered.

Complete the command once the value is set, as done for
characteristics, and parse a copy of the value so the input line is
not truncated by strsep while still in use by the shell.
---
 client/gatt.c | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/client/gatt.c b/client/gatt.c
index 6dc80e2a31cd..ebbe4e3c7a32 100644
--- a/client/gatt.c
+++ b/client/gatt.c
@@ -700,13 +700,20 @@ void gatt_read_local_attribute(char *data, int argc, char *argv[])
 	return bt_shell_noninteractive_quit(EXIT_FAILURE);
 }
 
-static uint8_t *str2bytearray(char *arg, size_t *val_len)
+static uint8_t *str2bytearray(const char *arg, size_t *val_len)
 {
 	uint8_t value[MAX_ATTR_VAL_LEN];
-	char *entry;
+	char *str, *next, *entry;
 	unsigned int i;
 
-	for (i = 0; (entry = strsep(&arg, " \t")) != NULL; i++) {
+	/* Parse a copy as strsep modifies the string, which may still be
+	 * in use by the caller, e.g. the shell printing the input line.
+	 */
+	str = next = strdup(arg);
+	if (!str)
+		return NULL;
+
+	for (i = 0; (entry = strsep(&next, " \t")) != NULL; i++) {
 		long val;
 		char *endptr = NULL;
 
@@ -715,18 +722,22 @@ static uint8_t *str2bytearray(char *arg, size_t *val_len)
 
 		if (i >= G_N_ELEMENTS(value)) {
 			bt_shell_printf("Too much data\n");
+			free(str);
 			return NULL;
 		}
 
 		val = strtol(entry, &endptr, 0);
 		if (!endptr || *endptr != '\0' || val > UINT8_MAX) {
 			bt_shell_printf("Invalid value at index %d\n", i);
+			free(str);
 			return NULL;
 		}
 
 		value[i] = val;
 	}
 
+	free(str);
+
 	*val_len = i;
 
 	return util_memdup(value, i);
@@ -2788,7 +2799,7 @@ static void chrc_set_value(const char *input, void *user_data)
 
 	g_free(chrc->value);
 
-	chrc->value = str2bytearray((char *) input, &chrc->value_len);
+	chrc->value = str2bytearray(input, &chrc->value_len);
 
 	if (!chrc->value) {
 		print_chrc(chrc, COLORED_DEL);
@@ -3078,7 +3089,7 @@ static void desc_set_value(const char *input, void *user_data)
 
 	g_free(desc->value);
 
-	desc->value = str2bytearray((char *) input, &desc->value_len);
+	desc->value = str2bytearray(input, &desc->value_len);
 
 	if (!desc->value) {
 		print_desc(desc, COLORED_DEL);
@@ -3086,6 +3097,8 @@ static void desc_set_value(const char *input, void *user_data)
 	}
 
 	desc->max_val_len = desc->value_len;
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
 }
 
 void gatt_register_desc(DBusConnection *conn, GDBusProxy *proxy,
@@ -3134,8 +3147,6 @@ void gatt_register_desc(DBusConnection *conn, GDBusProxy *proxy,
 	print_desc(desc, COLORED_NEW);
 
 	bt_shell_prompt_input(desc->path, "Enter value:", desc_set_value, desc);
-
-	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
 }
 
 static struct desc *desc_find(const char *pattern)
-- 
2.55.0


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

end of thread, other threads:[~2026-09-24 19:16 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-24 13:55 [PATCH BlueZ v2 0/8] Add HID over GATT functional tests Luiz Augusto von Dentz
2026-09-24 13:55 ` [PATCH BlueZ v2 1/8] attrib: Fix unregistering notifications registered with bt_gatt_client Luiz Augusto von Dentz
2026-09-24 15:25   ` Add HID over GATT functional tests bluez.test.bot
2026-09-24 13:55 ` [PATCH BlueZ v2 2/8] client/gatt: Fix setting descriptor value from scripts Luiz Augusto von Dentz
2026-09-24 13:55 ` [PATCH BlueZ v2 3/8] client/mgmt: Print Connection Subrate event Luiz Augusto von Dentz
2026-09-24 13:55 ` [PATCH BlueZ v2 4/8] emulator: Default to the latest BR/EDR+LE version Luiz Augusto von Dentz
2026-09-24 13:55 ` [PATCH BlueZ v2 5/8] client/scripts: Add HoG device scripts Luiz Augusto von Dentz
2026-09-24 13:55 ` [PATCH BlueZ v2 6/8] doc: Add functional-hog documentation Luiz Augusto von Dentz
2026-09-24 13:56 ` [PATCH BlueZ v2 7/8] test: functional: add HoG tests Luiz Augusto von Dentz
2026-09-24 13:56 ` [PATCH BlueZ v2 8/8] test: functional: limit the workers by the memory available Luiz Augusto von Dentz
  -- strict thread matches above, loose matches on Subject: below --
2026-09-24 15:46 [PATCH BlueZ v3 1/9] shared/gatt-client: Fix calling destroy after unregistering notify Luiz Augusto von Dentz
2026-09-24 19:16 ` Add HID over GATT functional tests bluez.test.bot
2026-09-23 19:31 [PATCH BlueZ v1 1/7] client/gatt: Fix setting descriptor value from scripts Luiz Augusto von Dentz
2026-09-23 22:30 ` Add HID over GATT functional tests bluez.test.bot

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.