[PATCH BlueZ v1 10/12] l2cap-tester: Add SCI mode tests for LE client connections
Luiz Augusto von Dentz <[email protected]> Fri, 24 Jul 2026 15:12:23 -0400
| Newsgroups | org.kernel.vger.linux-bluetooth |
|---|---|
| Message-ID | <[email protected]> |
From: Luiz Augusto von Dentz <[email protected]> Add L2CAP LE client connection tests that load Connection Subrate parameters (via MGMT_OP_LOAD_CONN_SUBRATE) before establishing the connection, using the HOGP v1.2 recommended values for each of the four HID SCI modes: - Fast: interval 1.25-5 ms, latency 0, subrate 1-4, cont_num 3 - Default: interval 7.5-15 ms, latency 0, subrate 1-4, cont_num 0 - Low Power: interval 7.5-15 ms, latency 100, subrate 1-4, cont_num 0 - Full Range: interval 1.25-15 ms, latency 0, subrate 1-4, cont_num 1 Add the test_l2cap_le_62 macro (HCIEMU_TYPE_BREDRLE62) since SCI requires a 6.2 controller. The subrate parameters are loaded with the client's runtime bdaddr during setup_powered_client before the outgoing LE connection is initiated. --- tools/l2cap-tester.c | 130 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/tools/l2cap-tester.c b/tools/l2cap-tester.c index 2771aee65814..88bfd71bf580 100644 --- a/tools/l2cap-tester.c +++ b/tools/l2cap-tester.c @@ -54,6 +54,16 @@ struct test_data { struct tx_tstamp_data tx_ts; }; +struct l2cap_conn_subrate { + uint16_t min_interval; + uint16_t max_interval; + uint16_t subrate_min; + uint16_t subrate_max; + uint16_t max_latency; + uint16_t cont_num; + uint16_t supv_timeout; +}; + struct l2cap_data { uint16_t client_psm; uint16_t server_psm; @@ -112,6 +122,11 @@ struct l2cap_data { /* Set PHY */ uint32_t phy; + + /* Connection Subrate parameters to load before connecting. + * The address is filled in with the client bdaddr at runtime. + */ + const struct l2cap_conn_subrate *conn_subrate; }; static void print_debug(const char *str, void *user_data) @@ -298,6 +313,9 @@ static void test_data_free(void *test_data) #define test_l2cap_le_52(name, data, setup, func) \ test_l2cap(name, HCIEMU_TYPE_BREDRLE52, data, setup, func) +#define test_l2cap_le_62(name, data, setup, func) \ + test_l2cap(name, HCIEMU_TYPE_BREDRLE62, data, setup, func) + static uint8_t pair_device_pin[] = { 0x30, 0x30, 0x30, 0x30 }; /* "0000" */ static const struct l2cap_data client_connect_success_test = { @@ -654,6 +672,74 @@ static const struct l2cap_data le_client_connect_success_test_1 = { .server_psm = 0x0080, }; +/* HIDS 1.2 recommended SCI parameters (see HOGP v1.2 spec). + * Connection intervals are in units of 0.125 ms, supervision timeout in + * units of 10 ms. + */ +static const struct l2cap_conn_subrate conn_subrate_hids_fast = { + .min_interval = 0x000a, /* 1.25 ms */ + .max_interval = 0x0028, /* 5 ms */ + .subrate_min = 0x0001, + .subrate_max = 0x0004, + .max_latency = 0x0000, + .cont_num = 0x0003, + .supv_timeout = 0x0004, /* 40 ms */ +}; + +static const struct l2cap_conn_subrate conn_subrate_hids_default = { + .min_interval = 0x003c, /* 7.5 ms */ + .max_interval = 0x0078, /* 15 ms */ + .subrate_min = 0x0001, + .subrate_max = 0x0004, + .max_latency = 0x0000, + .cont_num = 0x0000, + .supv_timeout = 0x000c, /* 120 ms */ +}; + +static const struct l2cap_conn_subrate conn_subrate_hids_low_power = { + .min_interval = 0x003c, /* 7.5 ms */ + .max_interval = 0x0078, /* 15 ms */ + .subrate_min = 0x0001, + .subrate_max = 0x0004, + .max_latency = 0x0064, /* 100 */ + .cont_num = 0x0000, + .supv_timeout = 0x04bc, /* 12120 ms */ +}; + +static const struct l2cap_conn_subrate conn_subrate_hids_full_range = { + .min_interval = 0x000a, /* 1.25 ms */ + .max_interval = 0x0078, /* 15 ms */ + .subrate_min = 0x0001, + .subrate_max = 0x0004, + .max_latency = 0x0000, + .cont_num = 0x0001, + .supv_timeout = 0x000c, /* 120 ms */ +}; + +static const struct l2cap_data le_client_connect_subrate_fast_test = { + .client_psm = 0x0080, + .server_psm = 0x0080, + .conn_subrate = &conn_subrate_hids_fast, +}; + +static const struct l2cap_data le_client_connect_subrate_default_test = { + .client_psm = 0x0080, + .server_psm = 0x0080, + .conn_subrate = &conn_subrate_hids_default, +}; + +static const struct l2cap_data le_client_connect_subrate_low_power_test = { + .client_psm = 0x0080, + .server_psm = 0x0080, + .conn_subrate = &conn_subrate_hids_low_power, +}; + +static const struct l2cap_data le_client_connect_subrate_full_range_test = { + .client_psm = 0x0080, + .server_psm = 0x0080, + .conn_subrate = &conn_subrate_hids_full_range, +}; + static const struct l2cap_data le_client_connect_close_test_1 = { .client_psm = 0x0080, }; @@ -1512,6 +1598,37 @@ static void setup_powered_client(const void *test_data) mgmt_send(data->mgmt, MGMT_OP_SET_LE, data->mgmt_index, sizeof(param), param, NULL, NULL, NULL); + if (test && test->conn_subrate) { + const struct l2cap_conn_subrate *cs = test->conn_subrate; + const uint8_t *client_bdaddr; + struct { + struct mgmt_cp_load_conn_subrate cp; + struct mgmt_conn_subrate param; + } __attribute__((packed)) load; + + client_bdaddr = hciemu_get_client_bdaddr(data->hciemu); + if (!client_bdaddr) { + tester_setup_failed(); + return; + } + + memset(&load, 0, sizeof(load)); + load.cp.param_count = cpu_to_le16(1); + memcpy(&load.param.addr.bdaddr, client_bdaddr, 6); + load.param.addr.type = BDADDR_LE_PUBLIC; + load.param.min_interval = cpu_to_le16(cs->min_interval); + load.param.max_interval = cpu_to_le16(cs->max_interval); + load.param.subrate_min = cpu_to_le16(cs->subrate_min); + load.param.subrate_max = cpu_to_le16(cs->subrate_max); + load.param.max_latency = cpu_to_le16(cs->max_latency); + load.param.cont_num = cpu_to_le16(cs->cont_num); + load.param.supv_timeout = cpu_to_le16(cs->supv_timeout); + + mgmt_send(data->mgmt, MGMT_OP_LOAD_CONN_SUBRATE, + data->mgmt_index, sizeof(load), &load, + NULL, NULL, NULL); + } + mgmt_send(data->mgmt, MGMT_OP_SET_POWERED, data->mgmt_index, sizeof(param), param, setup_powered_client_callback, NULL, NULL); @@ -3118,6 +3235,19 @@ int main(int argc, char *argv[]) test_l2cap_le("L2CAP LE Client - Success", &le_client_connect_success_test_1, setup_powered_client, test_connect); + + test_l2cap_le_62("L2CAP LE Client - SCI Fast Mode", + &le_client_connect_subrate_fast_test, + setup_powered_client, test_connect); + test_l2cap_le_62("L2CAP LE Client - SCI Default Mode", + &le_client_connect_subrate_default_test, + setup_powered_client, test_connect); + test_l2cap_le_62("L2CAP LE Client - SCI Low Power Mode", + &le_client_connect_subrate_low_power_test, + setup_powered_client, test_connect); + test_l2cap_le_62("L2CAP LE Client - SCI Full Range Mode", + &le_client_connect_subrate_full_range_test, + setup_powered_client, test_connect); test_l2cap_le("L2CAP LE Client - Close", &le_client_connect_close_test_1, setup_powered_client, test_connect_close); -- 2.54.0