* [RESEND RFC PATCH] l2cap-tester: Check compatible interval preferences
@ 2026-10-31 18:13 Kyle Pepper
2026-10-31 18:58 ` [RESEND,RFC] " bluez.test.bot
2026-10-31 19:37 ` [RFC PATCH v2] " Kyle Pepper
0 siblings, 2 replies; 4+ messages in thread
From: Kyle Pepper @ 2026-10-31 18:13 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Marcel Holtmann, Luiz Augusto von Dentz
Load local connection preferences and check both the peer's L2CAP
response and the resulting HCI Connection Update range. Cover overlap,
fast HID and slow idle fallback, and an exact-range control.
Assisted-by: OpenCode:gpt-6.1-sol
---
Resent after the earlier BlueZ PR was closed for inactivity.
Companion Linux RFC v3:
https://lore.kernel.org/linux-bluetooth/20261015181041.42873-1-cochcoder@proton.me/
This standalone BlueZ test patch requires that Linux soft-preference change
for the overlap case to pass. It is independent of ASHA STATUS, STOP, the
stream gate and credit changes. It does not add a BlueZ runtime fix.
Each case loads local preferences through MGMT, sends a peer L2CAP parameter
request, and checks both an accepted peer response and the selected HCI
Connection Update range. The cases cover overlap preference, fast HID and
slow idle outside the local preference, and an exact match.
Saved native controls:
- Unpatched kernel: 3/4, failing only the expected narrower-overlap selection.
- Strict-bound negative control: 2/4, rejecting the HID and idle requests.
- Soft-preference revision: 4/4; full reference-guest L2CAP suite 115/115,
without skips or captured KASAN/lockdep alerts.
This standalone source also passes 35/35 ordinary unit binaries. The newer
combined Arch package port passes all four interval controls on the saved
soft-preference guest, but that package port is not this submission's source.
No real-controller, firmware, acoustic, paired-device or remote-CI claim is
made for this standalone test patch. The companion remains an RFC; kernel acceptance is not established.
tools/l2cap-tester.c | 159 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 159 insertions(+)
diff --git a/tools/l2cap-tester.c b/tools/l2cap-tester.c
index f2d3e56b87..a4701071e7 100644
--- a/tools/l2cap-tester.c
+++ b/tools/l2cap-tester.c
@@ -54,6 +54,7 @@ struct test_data {
int step;
struct queue *io_channels;
struct tx_tstamp_data tx_ts;
+ unsigned int interval_events;
};
struct l2cap_conn_subrate {
@@ -132,6 +133,7 @@ struct l2cap_data {
/* Change security level to this after connecting */
int change_sec_level;
+ const struct interval_test *interval;
};
static void print_debug(const char *str, void *user_data)
@@ -3497,6 +3499,154 @@ done:
close(sk);
}
+struct interval_test {
+ uint16_t local_min;
+ uint16_t local_max;
+ uint16_t peer_min;
+ uint16_t peer_max;
+ uint16_t expect_min;
+ uint16_t expect_max;
+};
+
+static const struct interval_test interval_cases[] = {
+ { 16, 16, 16, 24, 16, 16 },
+ { 24, 40, 6, 6, 6, 6 },
+ { 16, 24, 80, 160, 80, 160 },
+ { 16, 16, 16, 16, 16, 16 },
+};
+
+static const struct l2cap_data interval_data[] = {
+ { .interval = &interval_cases[0] },
+ { .interval = &interval_cases[1] },
+ { .interval = &interval_cases[2] },
+ { .interval = &interval_cases[3] },
+};
+
+static void interval_complete(struct test_data *data, unsigned int event)
+{
+ data->interval_events |= event;
+
+ if (data->interval_events == 3)
+ tester_test_passed();
+}
+
+static void interval_command(uint16_t opcode, const void *param, uint8_t len,
+ void *user_data)
+{
+ struct test_data *data = user_data;
+ const struct l2cap_data *l2data = data->test_data;
+ const struct interval_test *test = l2data->interval;
+ const struct bt_hci_cmd_le_conn_update *cp = param;
+
+ if (opcode != BT_HCI_CMD_LE_CONN_UPDATE)
+ return;
+
+ if (len != sizeof(*cp) ||
+ get_le16(&cp->min_interval) != test->expect_min ||
+ get_le16(&cp->max_interval) != test->expect_max ||
+ get_le16(&cp->latency) ||
+ get_le16(&cp->supv_timeout) != 600) {
+ tester_warn("Unexpected LE Connection Update parameters");
+ tester_test_failed();
+ return;
+ }
+
+ interval_complete(data, 1);
+}
+
+static void interval_response(uint8_t code, const void *param, uint16_t len,
+ void *user_data)
+{
+ struct test_data *data = user_data;
+
+ if (code != 0x13 || len != 2 || get_le16(param)) {
+ tester_warn("Connection Parameter Update was not accepted");
+ tester_test_failed();
+ return;
+ }
+
+ interval_complete(data, 2);
+}
+
+static void interval_connected(uint16_t handle, void *user_data)
+{
+ struct test_data *data = user_data;
+ const struct l2cap_data *l2data = data->test_data;
+ const struct interval_test *test = l2data->interval;
+ struct bthost *host = hciemu_client_get_host(data->hciemu);
+ uint8_t request[8];
+
+ put_le16(test->peer_min, request);
+ put_le16(test->peer_max, request + 2);
+ put_le16(0, request + 4);
+ put_le16(600, request + 6);
+
+ if (!bthost_l2cap_req(host, handle, 0x12, request, sizeof(request),
+ interval_response, data))
+ tester_test_failed();
+}
+
+static void interval_loaded(uint8_t status, uint16_t len, const void *param,
+ void *user_data)
+{
+ struct test_data *data = user_data;
+ struct bthost *host = hciemu_client_get_host(data->hciemu);
+ GIOChannel *io;
+ int sk;
+
+ if (status) {
+ tester_warn("Could not load connection preferences");
+ tester_test_failed();
+ return;
+ }
+
+ bthost_set_connect_cb(host, interval_connected, data);
+ bthost_add_l2cap_server(host, 0x0080, NULL, NULL, NULL);
+ hciemu_add_central_post_command_hook(data->hciemu,
+ interval_command, data);
+ sk = create_l2cap_sock(data, 0, 0, 0, BT_MODE_LE_FLOWCTL);
+
+ if (sk < 0) {
+ tester_test_failed();
+ return;
+ }
+
+ if (connect_l2cap_sock(data, sk, 0x0080, 0) < 0) {
+ close(sk);
+ tester_test_failed();
+ return;
+ }
+
+ io = g_io_channel_unix_new(sk);
+ g_io_channel_set_close_on_unref(io, TRUE);
+ data->io_channels = queue_new();
+ queue_push_tail(data->io_channels, io);
+}
+
+static void test_interval_preferences(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+ const struct l2cap_data *l2data = data->test_data;
+ const struct interval_test *test = l2data->interval;
+ uint8_t buf[sizeof(struct mgmt_cp_load_conn_param) +
+ sizeof(struct mgmt_conn_param)];
+ struct mgmt_cp_load_conn_param *cp = (void *) buf;
+ struct mgmt_conn_param *param = cp->params;
+
+ memset(buf, 0, sizeof(buf));
+ cp->param_count = cpu_to_le16(1);
+ memcpy(¶m->addr.bdaddr,
+ hciemu_get_client_bdaddr(data->hciemu), 6);
+ param->addr.type = BDADDR_LE_PUBLIC;
+ param->min_interval = cpu_to_le16(test->local_min);
+ param->max_interval = cpu_to_le16(test->local_max);
+ param->timeout = cpu_to_le16(600);
+
+ if (!mgmt_send(data->mgmt, MGMT_OP_LOAD_CONN_PARAM, data->mgmt_index,
+ sizeof(buf), buf, interval_loaded, data, NULL))
+ tester_test_failed();
+}
+
static void test_l2cap_ethtool_get_ts_info(const void *test_data)
{
struct test_data *data = tester_get_data();
@@ -3508,6 +3658,15 @@ int main(int argc, char *argv[])
{
tester_init(&argc, &argv);
+ test_l2cap_le("L2CAP Interval - Prefer overlap", &interval_data[0],
+ setup_powered_client, test_interval_preferences);
+ test_l2cap_le("L2CAP Interval - Fast HID fallback", &interval_data[1],
+ setup_powered_client, test_interval_preferences);
+ test_l2cap_le("L2CAP Interval - Slow idle fallback", &interval_data[2],
+ setup_powered_client, test_interval_preferences);
+ test_l2cap_le("L2CAP Interval - Exact match", &interval_data[3],
+ setup_powered_client, test_interval_preferences);
+
test_l2cap_bredr("Basic L2CAP Socket - Success", NULL,
setup_powered_client, test_basic);
test_l2cap_bredr("Non-connected getpeername - Failure", NULL,
^ permalink raw reply related [flat|nested] 4+ messages in thread
* RE: [RESEND,RFC] l2cap-tester: Check compatible interval preferences
2026-10-31 18:13 [RESEND RFC PATCH] l2cap-tester: Check compatible interval preferences Kyle Pepper
@ 2026-10-31 18:58 ` bluez.test.bot
2026-10-31 19:37 ` [RFC PATCH v2] " Kyle Pepper
1 sibling, 0 replies; 4+ messages in thread
From: bluez.test.bot @ 2026-10-31 18:58 UTC (permalink / raw)
To: linux-bluetooth, cochcoder
[-- Attachment #1: Type: text/plain, Size: 25999 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/1197860/
---Test result---
Test Summary:
CheckPatch PASS 0.43 seconds
GitLint FAIL 0.28 seconds
BuildEll PASS 13.97 seconds
BluezMake FAIL 40.94 seconds
CheckSmatch FAIL 55.78 seconds
bluezmakeextell FAIL 16.34 seconds
TestFunctional ERROR 41.55 seconds
IncrementalBuild FAIL 44.96 seconds
ScanBuild FAIL 73.11 seconds
Details
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[RESEND,RFC] l2cap-tester: Check compatible interval preferences
32: B1 Line exceeds max length (104>80): "made for this standalone test patch. The companion remains an RFC; kernel acceptance is not established."
##############################
Test: BluezMake - FAIL
Desc: Build BlueZ
Output:
tools/l2cap-tester.c: In function ‘interval_loaded’:
tools/l2cap-tester.c:3619:9: error: unknown type name ‘GIOChannel’
3619 | GIOChannel *io;
| ^~~~~~~~~~
tools/l2cap-tester.c:3645:14: error: implicit declaration of function ‘g_io_channel_unix_new’; did you mean ‘io_channel_unref’? [-Wimplicit-function-declaration]
3645 | io = g_io_channel_unix_new(sk);
| ^~~~~~~~~~~~~~~~~~~~~
| io_channel_unref
tools/l2cap-tester.c:3645:12: error: assignment to ‘int *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
3645 | io = g_io_channel_unix_new(sk);
| ^
tools/l2cap-tester.c:3646:9: error: implicit declaration of function ‘g_io_channel_set_close_on_unref’ [-Wimplicit-function-declaration]
3646 | g_io_channel_set_close_on_unref(io, TRUE);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/l2cap-tester.c:3646:45: error: ‘TRUE’ undeclared (first use in this function)
3646 | g_io_channel_set_close_on_unref(io, TRUE);
| ^~~~
tools/l2cap-tester.c:3646:45: note: each undeclared identifier is reported only once for each function it appears in
make[1]: *** [Makefile:7191: tools/l2cap-tester.o] Error 1
make[1]: *** Waiting for unfinished jobs....
tools/mgmt-tester.c: In function ‘main’:
tools/mgmt-tester.c:14256:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without
14256 | int main(int argc, char *argv[])
| ^~~~
make: *** [Makefile:4282: all] Error 2
##############################
Test: CheckSmatch - FAIL
Desc: Run smatch tool with source
Output:
src/shared/crypto.c:271:21: warning: Variable length array is used.
src/shared/crypto.c:272:23: warning: Variable length array is used.
src/shared/gatt-helpers.c:764:31: warning: Variable length array is used.
src/shared/gatt-helpers.c:842:31: warning: Variable length array is used.
src/shared/gatt-helpers.c:1335:31: warning: Variable length array is used.
src/shared/gatt-helpers.c:1366:23: warning: Variable length array is used.
src/shared/bap.c:309:25: warning: array of flexible structures
src/shared/bap.c: note: in included file:
./src/shared/ascs.h:88:25: warning: array of flexible structures
src/shared/shell.c: note: in included file (through /usr/include/x86_64-linux-gnu//sys/ioctl.h, /usr/include/x86_64-linux-gnu//sys/epoll.h, src/shared/mainloop.h):
/usr/include/x86_64-linux-gnu//sys/ttydefaults.h:55:9: warning: preprocessor token CTRL redefined
src/shared/shell.c: note: in included file (through /usr/include/readline/keymaps.h, /usr/include/readline/readline.h):
/usr/include/readline/chardefs.h:51:9: this was the original definition
src/shared/crypto.c:271:21: warning: Variable length array is used.
src/shared/crypto.c:272:23: warning: Variable length array is used.
src/shared/gatt-helpers.c:764:31: warning: Variable length array is used.
src/shared/gatt-helpers.c:842:31: warning: Variable length array is used.
src/shared/gatt-helpers.c:1335:31: warning: Variable length array is used.
src/shared/gatt-helpers.c:1366:23: warning: Variable length array is used.
src/shared/bap.c:309:25: warning: array of flexible structures
src/shared/bap.c: note: in included file:
./src/shared/ascs.h:88:25: warning: array of flexible structures
src/shared/shell.c: note: in included file (through /usr/include/x86_64-linux-gnu//sys/ioctl.h, /usr/include/x86_64-linux-gnu//sys/epoll.h, src/shared/mainloop.h):
/usr/include/x86_64-linux-gnu//sys/ttydefaults.h:55:9: warning: preprocessor token CTRL redefined
src/shared/shell.c: note: in included file (through /usr/include/readline/keymaps.h, /usr/include/readline/readline.h):
/usr/include/readline/chardefs.h:51:9: this was the original definition
tools/mesh-cfgtest.c:1453:17: warning: unknown escape sequence: '\%'
tools/l2cap-tester.c:3620:9: warning: mixing declarations and code
tools/sco-tester.c: note: in included file:
./lib/bluetooth/bluetooth.h:232:15: warning: array of flexible structures
./lib/bluetooth/bluetooth.h:237:31: warning: array of flexible structures
tools/l2cap-tester.c: In function ‘interval_loaded’:
tools/l2cap-tester.c:3619:9: error: unknown type name ‘GIOChannel’
3619 | GIOChannel *io;
| ^~~~~~~~~~
tools/l2cap-tester.c:3645:14: error: implicit declaration of function ‘g_io_channel_unix_new’; did you mean ‘io_channel_unref’? [-Wimplicit-function-declaration]
3645 | io = g_io_channel_unix_new(sk);
| ^~~~~~~~~~~~~~~~~~~~~
| io_channel_unref
tools/l2cap-tester.c:3645:12: error: assignment to ‘int *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
3645 | io = g_io_channel_unix_new(sk);
| ^
tools/l2cap-tester.c:3646:9: error: implicit declaration of function ‘g_io_channel_set_close_on_unref’ [-Wimplicit-function-declaration]
3646 | g_io_channel_set_close_on_unref(io, TRUE);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/l2cap-tester.c:3646:45: error: ‘TRUE’ undeclared (first use in this function)
3646 | g_io_channel_set_close_on_unref(io, TRUE);
| ^~~~
tools/l2cap-tester.c:3646:45: note: each undeclared identifier is reported only once for each function it appears in
make[1]: *** [Makefile:7191: tools/l2cap-tester.o] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:4282: all] Error 2
##############################
Test: bluezmakeextell - FAIL
Desc: Build Bluez with External ELL
Output:
tools/l2cap-tester.c: In function ‘interval_loaded’:
tools/l2cap-tester.c:3619:9: error: unknown type name ‘GIOChannel’
3619 | GIOChannel *io;
| ^~~~~~~~~~
tools/l2cap-tester.c:3645:14: error: implicit declaration of function ‘g_io_channel_unix_new’; did you mean ‘io_channel_unref’? [-Wimplicit-function-declaration]
3645 | io = g_io_channel_unix_new(sk);
| ^~~~~~~~~~~~~~~~~~~~~
| io_channel_unref
tools/l2cap-tester.c:3645:12: error: assignment to ‘int *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
3645 | io = g_io_channel_unix_new(sk);
| ^
tools/l2cap-tester.c:3646:9: error: implicit declaration of function ‘g_io_channel_set_close_on_unref’ [-Wimplicit-function-declaration]
3646 | g_io_channel_set_close_on_unref(io, TRUE);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/l2cap-tester.c:3646:45: error: ‘TRUE’ undeclared (first use in this function)
3646 | g_io_channel_set_close_on_unref(io, TRUE);
| ^~~~
tools/l2cap-tester.c:3646:45: note: each undeclared identifier is reported only once for each function it appears in
make[1]: *** [Makefile:7191: tools/l2cap-tester.o] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:4282: all] Error 2
##############################
Test: TestFunctional - ERROR
Desc: Run test-functional
Output:
Failed to build BlueZ:
Failed to build BlueZ
##############################
Test: IncrementalBuild - FAIL
Desc: Incremental build with the patches in the series
Output:
tools/l2cap-tester.c: In function ‘interval_loaded’:
tools/l2cap-tester.c:3619:9: error: unknown type name ‘GIOChannel’
3619 | GIOChannel *io;
| ^~~~~~~~~~
tools/l2cap-tester.c:3645:14: error: implicit declaration of function ‘g_io_channel_unix_new’; did you mean ‘io_channel_unref’? [-Wimplicit-function-declaration]
3645 | io = g_io_channel_unix_new(sk);
| ^~~~~~~~~~~~~~~~~~~~~
| io_channel_unref
tools/l2cap-tester.c:3645:12: error: assignment to ‘int *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
3645 | io = g_io_channel_unix_new(sk);
| ^
tools/l2cap-tester.c:3646:9: error: implicit declaration of function ‘g_io_channel_set_close_on_unref’ [-Wimplicit-function-declaration]
3646 | g_io_channel_set_close_on_unref(io, TRUE);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/l2cap-tester.c:3646:45: error: ‘TRUE’ undeclared (first use in this function)
3646 | g_io_channel_set_close_on_unref(io, TRUE);
| ^~~~
tools/l2cap-tester.c:3646:45: note: each undeclared identifier is reported only once for each function it appears in
make[1]: *** [Makefile:7191: tools/l2cap-tester.o] Error 1
make[1]: *** Waiting for unfinished jobs....
tools/mgmt-tester.c: In function ‘main’:
tools/mgmt-tester.c:14256:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without
14256 | int main(int argc, char *argv[])
| ^~~~
make: *** [Makefile:4282: all] Error 2
[RESEND,RFC] l2cap-tester: Check compatible interval preferences
tools/l2cap-tester.c: In function ‘interval_loaded’:
tools/l2cap-tester.c:3619:9: error: unknown type name ‘GIOChannel’
3619 | GIOChannel *io;
| ^~~~~~~~~~
tools/l2cap-tester.c:3645:14: error: implicit declaration of function ‘g_io_channel_unix_new’; did you mean ‘io_channel_unref’? [-Wimplicit-function-declaration]
3645 | io = g_io_channel_unix_new(sk);
| ^~~~~~~~~~~~~~~~~~~~~
| io_channel_unref
tools/l2cap-tester.c:3645:12: error: assignment to ‘int *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
3645 | io = g_io_channel_unix_new(sk);
| ^
tools/l2cap-tester.c:3646:9: error: implicit declaration of function ‘g_io_channel_set_close_on_unref’ [-Wimplicit-function-declaration]
3646 | g_io_channel_set_close_on_unref(io, TRUE);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/l2cap-tester.c:3646:45: error: ‘TRUE’ undeclared (first use in this function)
3646 | g_io_channel_set_close_on_unref(io, TRUE);
| ^~~~
tools/l2cap-tester.c:3646:45: note: each undeclared identifier is reported only once for each function it appears in
make[1]: *** [Makefile:7191: tools/l2cap-tester.o] Error 1
make[1]: *** Waiting for unfinished jobs....
tools/mgmt-tester.c: In function ‘main’:
tools/mgmt-tester.c:14256:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without
14256 | int main(int argc, char *argv[])
| ^~~~
make: *** [Makefile:4282: all] Error 2
##############################
Test: ScanBuild - FAIL
Desc: Run Scan Build
Output:
src/shared/gatt-client.c:458:21: warning: Use of memory after it is freed [unix.Malloc]
458 | gatt_db_unregister(op->client->db, op->db_id);
| ^~~~~~~~~~
src/shared/gatt-client.c:703:2: warning: Use of memory after it is freed [unix.Malloc]
703 | discovery_op_complete(op, false, att_ecode);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1109:2: warning: Use of memory after it is freed [unix.Malloc]
1109 | discovery_op_complete(op, success, att_ecode);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1309:2: warning: Use of memory after it is freed [unix.Malloc]
1309 | discovery_op_complete(op, success, att_ecode);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1374:2: warning: Use of memory after it is freed [unix.Malloc]
1374 | discovery_op_complete(op, success, att_ecode);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1649:6: warning: Use of memory after it is freed [unix.Malloc]
1649 | if (read_db_hash(op)) {
| ^~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1654:2: warning: Use of memory after it is freed [unix.Malloc]
1654 | discover_all(op);
| ^~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1709:56: warning: Use of memory after it is freed [unix.Malloc]
1709 | notify_data->chrc->ccc_write_id = notify_data->att_id = att_id;
| ~~~~~~~~~~~~~~~~~~~ ^
src/shared/gatt-client.c:2176:6: warning: Use of memory after it is freed [unix.Malloc]
2176 | if (read_db_hash(op)) {
| ^~~~~~~~~~~~~~~~
src/shared/gatt-client.c:2184:8: warning: Use of memory after it is freed [unix.Malloc]
2184 | discovery_op_ref(op),
| ^~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:3370:2: warning: Use of memory after it is freed [unix.Malloc]
3370 | complete_write_long_op(req, success, 0, false);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:3392:2: warning: Use of memory after it is freed [unix.Malloc]
3392 | request_unref(req);
| ^~~~~~~~~~~~~~~~~~
12 warnings generated.
src/shared/rap.c:3936:30: warning: Assigned value is uninitialized [core.uninitialized.Assign]
3936 | out->tone_pct[k].i_sample = tone_pct_i[k];
| ^ ~~~~~~~~~~~~~
src/shared/rap.c:4981:13: warning: Use of memory after it is freed [unix.Malloc]
4981 | attached = queue_find(sessions, NULL, rap);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 warnings generated.
src/shared/bap.c:1534:8: warning: Use of memory after it is freed [unix.Malloc]
1534 | bap = bt_bap_ref_safe(bap);
| ^~~~~~~~~~~~~~~~~~~~
src/shared/bap.c:2350:20: warning: Use of memory after it is freed [unix.Malloc]
2350 | return queue_find(stream->bap->streams, NULL, stream);
| ^~~~~~~~~~~~~~~~~~~~
2 warnings generated.
src/shared/gatt-client.c:458:21: warning: Use of memory after it is freed [unix.Malloc]
458 | gatt_db_unregister(op->client->db, op->db_id);
| ^~~~~~~~~~
src/shared/gatt-client.c:703:2: warning: Use of memory after it is freed [unix.Malloc]
703 | discovery_op_complete(op, false, att_ecode);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1109:2: warning: Use of memory after it is freed [unix.Malloc]
1109 | discovery_op_complete(op, success, att_ecode);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1309:2: warning: Use of memory after it is freed [unix.Malloc]
1309 | discovery_op_complete(op, success, att_ecode);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1374:2: warning: Use of memory after it is freed [unix.Malloc]
1374 | discovery_op_complete(op, success, att_ecode);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1649:6: warning: Use of memory after it is freed [unix.Malloc]
1649 | if (read_db_hash(op)) {
| ^~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1654:2: warning: Use of memory after it is freed [unix.Malloc]
1654 | discover_all(op);
| ^~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1709:56: warning: Use of memory after it is freed [unix.Malloc]
1709 | notify_data->chrc->ccc_write_id = notify_data->att_id = att_id;
| ~~~~~~~~~~~~~~~~~~~ ^
src/shared/gatt-client.c:2176:6: warning: Use of memory after it is freed [unix.Malloc]
2176 | if (read_db_hash(op)) {
| ^~~~~~~~~~~~~~~~
src/shared/gatt-client.c:2184:8: warning: Use of memory after it is freed [unix.Malloc]
2184 | discovery_op_ref(op),
| ^~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:3370:2: warning: Use of memory after it is freed [unix.Malloc]
3370 | complete_write_long_op(req, success, 0, false);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:3392:2: warning: Use of memory after it is freed [unix.Malloc]
3392 | request_unref(req);
| ^~~~~~~~~~~~~~~~~~
12 warnings generated.
tools/hciattach.c:817:7: warning: Although the value stored to 'n' is used in the enclosing expression, the value is never actually read from 'n' [deadcode.DeadStores]
817 | if ((n = read_hci_event(fd, resp, 10)) < 0) {
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/hciattach.c:865:7: warning: Although the value stored to 'n' is used in the enclosing expression, the value is never actually read from 'n' [deadcode.DeadStores]
865 | if ((n = read_hci_event(fd, resp, 4)) < 0) {
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/hciattach.c:887:8: warning: Although the value stored to 'n' is used in the enclosing expression, the value is never actually read from 'n' [deadcode.DeadStores]
887 | if ((n = read_hci_event(fd, resp, 10)) < 0) {
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/hciattach.c:909:7: warning: Although the value stored to 'n' is used in the enclosing expression, the value is never actually read from 'n' [deadcode.DeadStores]
909 | if ((n = read_hci_event(fd, resp, 4)) < 0) {
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/hciattach.c:930:7: warning: Although the value stored to 'n' is used in the enclosing expression, the value is never actually read from 'n' [deadcode.DeadStores]
930 | if ((n = read_hci_event(fd, resp, 4)) < 0) {
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/hciattach.c:974:7: warning: Although the value stored to 'n' is used in the enclosing expression, the value is never actually read from 'n' [deadcode.DeadStores]
974 | if ((n = read_hci_event(fd, resp, 6)) < 0) {
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 warnings generated.
tools/hciattach_ath3k.c:530:9: warning: File position of the stream might be 'indeterminate' after a failed operation. Can cause undefined behavior [unix.Stream]
530 | if (!fgets(byte, 3, stream))
| ^~~~~~~~~~~~~~~~~~~~~~
tools/hciattach_ath3k.c:530:9: warning: Read function called when stream is in EOF state. Function has no effect [unix.Stream]
530 | if (!fgets(byte, 3, stream))
| ^~~~~~~~~~~~~~~~~~~~~~
2 warnings generated.
src/shared/rap.c:3936:30: warning: Assigned value is uninitialized [core.uninitialized.Assign]
3936 | out->tone_pct[k].i_sample = tone_pct_i[k];
| ^ ~~~~~~~~~~~~~
src/shared/rap.c:4981:13: warning: Use of memory after it is freed [unix.Malloc]
4981 | attached = queue_find(sessions, NULL, rap);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 warnings generated.
src/shared/bap.c:1534:8: warning: Use of memory after it is freed [unix.Malloc]
1534 | bap = bt_bap_ref_safe(bap);
| ^~~~~~~~~~~~~~~~~~~~
src/shared/bap.c:2350:20: warning: Use of memory after it is freed [unix.Malloc]
2350 | return queue_find(stream->bap->streams, NULL, stream);
| ^~~~~~~~~~~~~~~~~~~~
2 warnings generated.
src/oui.c:50:2: warning: Value stored to 'hwdb' is never read [deadcode.DeadStores]
50 | hwdb = udev_hwdb_unref(hwdb);
| ^ ~~~~~~~~~~~~~~~~~~~~~
src/oui.c:53:2: warning: Value stored to 'udev' is never read [deadcode.DeadStores]
53 | udev = udev_unref(udev);
| ^ ~~~~~~~~~~~~~~~~
2 warnings generated.
tools/rfcomm.c:234:3: warning: Value stored to 'i' is never read [deadcode.DeadStores]
234 | i = execvp(cmdargv[0], cmdargv);
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/rfcomm.c:234:7: warning: Null pointer passed to 1st parameter expecting 'nonnull' [core.NonNullParamChecker]
234 | i = execvp(cmdargv[0], cmdargv);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/rfcomm.c:354:8: warning: Although the value stored to 'fd' is used in the enclosing expression, the value is never actually read from 'fd' [deadcode.DeadStores]
354 | if ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/rfcomm.c:473:6: warning: The 1st argument to 'getsockname' is -1 but should be >= 0 [unix.StdCLibraryFunctions]
473 | if (getsockname(nsk, (struct sockaddr *)&laddr, &alen) < 0) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/rfcomm.c:497:14: warning: Assigned value is uninitialized [core.uninitialized.Assign]
497 | req.channel = raddr.rc_channel;
| ^ ~~~~~~~~~~~~~~~~
tools/rfcomm.c:515:8: warning: Although the value stored to 'fd' is used in the enclosing expression, the value is never actually read from 'fd' [deadcode.DeadStores]
515 | if ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 warnings generated.
tools/ciptool.c:351:7: warning: 5th function call argument is an uninitialized value [core.CallAndMessage]
351 | sk = do_connect(ctl, dev_id, &src, &dst, psm, (1 << CMTP_LOOPBACK));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 warning generated.
tools/l2cap-tester.c: In function ‘interval_loaded’:
tools/l2cap-tester.c:3619:9: error: unknown type name ‘GIOChannel’
3619 | GIOChannel *io;
| ^~~~~~~~~~
tools/l2cap-tester.c:3645:14: error: implicit declaration of function ‘g_io_channel_unix_new’; did you mean ‘io_channel_unref’? [-Wimplicit-function-declaration]
3645 | io = g_io_channel_unix_new(sk);
| ^~~~~~~~~~~~~~~~~~~~~
| io_channel_unref
tools/l2cap-tester.c:3645:12: error: assignment to ‘int *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
3645 | io = g_io_channel_unix_new(sk);
| ^
tools/l2cap-tester.c:3646:9: error: implicit declaration of function ‘g_io_channel_set_close_on_unref’ [-Wimplicit-function-declaration]
3646 | g_io_channel_set_close_on_unref(io, TRUE);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tools/l2cap-tester.c:3646:45: error: ‘TRUE’ undeclared (first use in this function)
3646 | g_io_channel_set_close_on_unref(io, TRUE);
| ^~~~
tools/l2cap-tester.c:3646:45: note: each undeclared identifier is reported only once for each function it appears in
make[1]: *** [Makefile:7191: tools/l2cap-tester.o] Error 1
make[1]: *** Waiting for unfinished jobs....
tools/sdptool.c:941:26: warning: Result of 'malloc' is converted to a pointer of type 'uint32_t', which is incompatible with sizeof operand type 'int' [unix.MallocSizeof]
941 | uint32_t *value_int = malloc(sizeof(int));
| ~~~~~~~~~~ ^~~~~~ ~~~~~~~~~~~
tools/sdptool.c:980:4: warning: 1st function call argument is an uninitialized value [core.CallAndMessage]
980 | free(allocArray[i]);
| ^~~~~~~~~~~~~~~~~~~
tools/sdptool.c:3777:2: warning: Potential leak of memory pointed to by 'si.name' [unix.Malloc]
3777 | return add_service(0, &si);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
tools/sdptool.c:4112:4: warning: Potential leak of memory pointed to by 'context.svc' [unix.Malloc]
4112 | return -1;
| ^~~~~~~~~
4 warnings generated.
src/sdp-xml.c:129:10: warning: Assigned value is uninitialized [core.uninitialized.Assign]
129 | buf[1] = data[i + 1];
| ^ ~~~~~~~~~~~
src/sdp-xml.c:309:11: warning: Assigned value is uninitialized [core.uninitialized.Assign]
309 | buf[1] = data[i + 1];
| ^ ~~~~~~~~~~~
src/sdp-xml.c:347:11: warning: Assigned value is uninitialized [core.uninitialized.Assign]
347 | buf[1] = data[i + 1];
| ^ ~~~~~~~~~~~
3 warnings generated.
make: *** [Makefile:4282: all] Error 2
https://github.com/bluez/bluez/pull/2743
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 4+ messages in thread
* [RFC PATCH v2] l2cap-tester: Check compatible interval preferences
2026-10-31 18:13 [RESEND RFC PATCH] l2cap-tester: Check compatible interval preferences Kyle Pepper
2026-10-31 18:58 ` [RESEND,RFC] " bluez.test.bot
@ 2026-10-31 19:37 ` Kyle Pepper
2026-10-31 22:56 ` [RFC,v2] " bluez.test.bot
1 sibling, 1 reply; 4+ messages in thread
From: Kyle Pepper @ 2026-10-31 19:37 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Marcel Holtmann, Luiz Augusto von Dentz
Load local connection preferences and check both the peer's L2CAP
response and the resulting HCI Connection Update range. Cover overlap,
fast HID and slow idle fallback, and an exact-range control.
Assisted-by: OpenCode:gpt-6.1-sol
Assisted-by: Codex:GPT-6
---
Changes in v2:
- Use the tester I/O wrapper introduced since the original test was written.
- Wrap the long note reported by GitLint.
Companion Linux RFC v3:
https://lore.kernel.org/r/20261015181041.42873-1-cochcoder@proton.me
The overlap test requires the Linux soft-preference RFC. Its acceptance is
not established. With the earlier test source, the saved guest controls
passed 4/4 on that RFC, 3/4 on the unpatched kernel, and 2/4 with a strict
intersection control. The full guest L2CAP suite passed 115/115 with the
soft-preference kernel. These results predate the tester I/O conversion.
On BlueZ master 14bd6ab65f4a, this revision builds with bundled and external
ELL, passes all 35 ordinary unit tests, and passes checkpatch. A socketpair
control verifies that the tester wrapper keeps the socket until queue teardown.
The revised native interval tests have not been rerun: the saved guest panics
at init without KVM in this environment. No real-controller testing is claimed.
tools/l2cap-tester.c | 159 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 159 insertions(+)
diff --git a/tools/l2cap-tester.c b/tools/l2cap-tester.c
index 4002ca5..758aeba 100644
--- a/tools/l2cap-tester.c
+++ b/tools/l2cap-tester.c
@@ -56,6 +56,7 @@ struct test_data {
int step;
struct queue *io_channels;
struct tx_tstamp_data tx_ts;
+ unsigned int interval_events;
};
struct l2cap_conn_subrate {
@@ -134,6 +135,7 @@ struct l2cap_data {
/* Change security level to this after connecting */
int change_sec_level;
+ const struct interval_test *interval;
};
static void print_debug(const char *str, void *user_data)
@@ -3522,6 +3524,154 @@ done:
close(sk);
}
+struct interval_test {
+ uint16_t local_min;
+ uint16_t local_max;
+ uint16_t peer_min;
+ uint16_t peer_max;
+ uint16_t expect_min;
+ uint16_t expect_max;
+};
+
+static const struct interval_test interval_cases[] = {
+ { 16, 16, 16, 24, 16, 16 },
+ { 24, 40, 6, 6, 6, 6 },
+ { 16, 24, 80, 160, 80, 160 },
+ { 16, 16, 16, 16, 16, 16 },
+};
+
+static const struct l2cap_data interval_data[] = {
+ { .interval = &interval_cases[0] },
+ { .interval = &interval_cases[1] },
+ { .interval = &interval_cases[2] },
+ { .interval = &interval_cases[3] },
+};
+
+static void interval_complete(struct test_data *data, unsigned int event)
+{
+ data->interval_events |= event;
+
+ if (data->interval_events == 3)
+ tester_test_passed();
+}
+
+static void interval_command(uint16_t opcode, const void *param, uint8_t len,
+ void *user_data)
+{
+ struct test_data *data = user_data;
+ const struct l2cap_data *l2data = data->test_data;
+ const struct interval_test *test = l2data->interval;
+ const struct bt_hci_cmd_le_conn_update *cp = param;
+
+ if (opcode != BT_HCI_CMD_LE_CONN_UPDATE)
+ return;
+
+ if (len != sizeof(*cp) ||
+ get_le16(&cp->min_interval) != test->expect_min ||
+ get_le16(&cp->max_interval) != test->expect_max ||
+ get_le16(&cp->latency) ||
+ get_le16(&cp->supv_timeout) != 600) {
+ tester_warn("Unexpected LE Connection Update parameters");
+ tester_test_failed();
+ return;
+ }
+
+ interval_complete(data, 1);
+}
+
+static void interval_response(uint8_t code, const void *param, uint16_t len,
+ void *user_data)
+{
+ struct test_data *data = user_data;
+
+ if (code != 0x13 || len != 2 || get_le16(param)) {
+ tester_warn("Connection Parameter Update was not accepted");
+ tester_test_failed();
+ return;
+ }
+
+ interval_complete(data, 2);
+}
+
+static void interval_connected(uint16_t handle, void *user_data)
+{
+ struct test_data *data = user_data;
+ const struct l2cap_data *l2data = data->test_data;
+ const struct interval_test *test = l2data->interval;
+ struct bthost *host = hciemu_client_get_host(data->hciemu);
+ uint8_t request[8];
+
+ put_le16(test->peer_min, request);
+ put_le16(test->peer_max, request + 2);
+ put_le16(0, request + 4);
+ put_le16(600, request + 6);
+
+ if (!bthost_l2cap_req(host, handle, 0x12, request, sizeof(request),
+ interval_response, data))
+ tester_test_failed();
+}
+
+static void interval_loaded(uint8_t status, uint16_t len, const void *param,
+ void *user_data)
+{
+ struct test_data *data = user_data;
+ struct bthost *host = hciemu_client_get_host(data->hciemu);
+ struct tester_io *io;
+ int sk;
+
+ if (status) {
+ tester_warn("Could not load connection preferences");
+ tester_test_failed();
+ return;
+ }
+
+ bthost_set_connect_cb(host, interval_connected, data);
+ bthost_add_l2cap_server(host, 0x0080, NULL, NULL, NULL);
+ hciemu_add_central_post_command_hook(data->hciemu,
+ interval_command, data);
+ sk = create_l2cap_sock(data, 0, 0, 0, BT_MODE_LE_FLOWCTL);
+
+ if (sk < 0) {
+ tester_test_failed();
+ return;
+ }
+
+ if (connect_l2cap_sock(data, sk, 0x0080, 0) < 0) {
+ close(sk);
+ tester_test_failed();
+ return;
+ }
+
+ io = tester_io_new(sk);
+ tester_io_set_close_on_unref(io, true);
+ data->io_channels = queue_new();
+ queue_push_tail(data->io_channels, io);
+}
+
+static void test_interval_preferences(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+ const struct l2cap_data *l2data = data->test_data;
+ const struct interval_test *test = l2data->interval;
+ uint8_t buf[sizeof(struct mgmt_cp_load_conn_param) +
+ sizeof(struct mgmt_conn_param)];
+ struct mgmt_cp_load_conn_param *cp = (void *) buf;
+ struct mgmt_conn_param *param = cp->params;
+
+ memset(buf, 0, sizeof(buf));
+ cp->param_count = cpu_to_le16(1);
+ memcpy(¶m->addr.bdaddr,
+ hciemu_get_client_bdaddr(data->hciemu), 6);
+ param->addr.type = BDADDR_LE_PUBLIC;
+ param->min_interval = cpu_to_le16(test->local_min);
+ param->max_interval = cpu_to_le16(test->local_max);
+ param->timeout = cpu_to_le16(600);
+
+ if (!mgmt_send(data->mgmt, MGMT_OP_LOAD_CONN_PARAM, data->mgmt_index,
+ sizeof(buf), buf, interval_loaded, data, NULL))
+ tester_test_failed();
+}
+
static void test_l2cap_ethtool_get_ts_info(const void *test_data)
{
struct test_data *data = tester_get_data();
@@ -3533,6 +3683,15 @@ int main(int argc, char *argv[])
{
tester_init(&argc, &argv);
+ test_l2cap_le("L2CAP Interval - Prefer overlap", &interval_data[0],
+ setup_powered_client, test_interval_preferences);
+ test_l2cap_le("L2CAP Interval - Fast HID fallback", &interval_data[1],
+ setup_powered_client, test_interval_preferences);
+ test_l2cap_le("L2CAP Interval - Slow idle fallback", &interval_data[2],
+ setup_powered_client, test_interval_preferences);
+ test_l2cap_le("L2CAP Interval - Exact match", &interval_data[3],
+ setup_powered_client, test_interval_preferences);
+
test_l2cap_bredr("Basic L2CAP Socket - Success", NULL,
setup_powered_client, test_basic);
test_l2cap_bredr("Non-connected getpeername - Failure", NULL,
--
2.56.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* RE: [RFC,v2] l2cap-tester: Check compatible interval preferences
2026-10-31 19:37 ` [RFC PATCH v2] " Kyle Pepper
@ 2026-10-31 22:56 ` bluez.test.bot
0 siblings, 0 replies; 4+ messages in thread
From: bluez.test.bot @ 2026-10-31 22:56 UTC (permalink / raw)
To: linux-bluetooth, cochcoder
[-- Attachment #1: Type: text/plain, Size: 859 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/1197875/
---Test result---
Test Summary:
CheckPatch PASS 0.62 seconds
GitLint PASS 0.34 seconds
BuildEll PASS 20.50 seconds
BluezMake PASS 304.90 seconds
CheckSmatch PASS 311.65 seconds
bluezmakeextell PASS 100.94 seconds
TestFunctional PASS 1168.27 seconds
IncrementalBuild PASS 305.30 seconds
ScanBuild PASS 1156.20 seconds
https://github.com/bluez/bluez/pull/2744
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-31 22:56 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-31 18:13 [RESEND RFC PATCH] l2cap-tester: Check compatible interval preferences Kyle Pepper
2026-10-31 18:58 ` [RESEND,RFC] " bluez.test.bot
2026-10-31 19:37 ` [RFC PATCH v2] " Kyle Pepper
2026-10-31 22:56 ` [RFC,v2] " bluez.test.bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox