Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH BlueZ 0/1] Add configurable default LE PHY policy
@ 2026-05-24 22:14 Tarjei Bitustøyl
  2026-05-24 22:14 ` [PATCH BlueZ 1/1] adapter: Add configurable default LE PHYs Tarjei Bitustøyl
                   ` (3 more replies)
  0 siblings, 4 replies; 14+ messages in thread
From: Tarjei Bitustøyl @ 2026-05-24 22:14 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Tarjei Bitustøyl

This patch adds an opt-in bluetoothd configuration for the adapter's
default LE PHY policy.

It is motivated by a reproduced AX210 controller failure with a
Frostbay BLE device. In that setup, LE discovery fails unless the
adapter is limited to LE 1M TX/RX. A btmon trace shows the peer
returning a valid ATT Exchange MTU Response, but the controller/kernel
path reports it with the wrong ACL packet boundary flag, which leaves
service resolution incomplete.

Rather than adding a peer-specific quirk, this patch exposes a
generic [LE] DefaultPHYs setting in main.conf and applies it through
the existing mgmt PHY configuration interface.

The setting is adapter-wide, so it affects LE scanning and connection
establishment initiated through bluetoothd, including desktop clients
such as GNOME. Only configurable LE PHY bits are changed, and
mandatory controller-selected PHYs are preserved.

This may also be relevant to unresolved Intel-controller LE
interoperability reports such as BlueZ issues #1193 and #1557, but
those have not been re-tested with this patch and are not claimed as
fixed here.

Tarjei Bitustøyl (1):
  adapter: Add configurable default LE PHYs

 src/adapter.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/btd.h     |  2 ++
 src/main.c    | 61 +++++++++++++++++++++++++++++++++++++++++
 src/main.conf |  8 ++++++
 4 files changed, 147 insertions(+)

-- 
2.43.0


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

* [PATCH BlueZ 1/1] adapter: Add configurable default LE PHYs
  2026-05-24 22:14 [PATCH BlueZ 0/1] Add configurable default LE PHY policy Tarjei Bitustøyl
@ 2026-05-24 22:14 ` Tarjei Bitustøyl
  2026-05-24 23:07   ` Add configurable default LE PHY policy bluez.test.bot
  2026-05-26 14:27   ` [PATCH BlueZ 1/1] adapter: Add configurable default LE PHYs Luiz Augusto von Dentz
  2026-05-25  6:50 ` [PATCH BlueZ v2 0/1] Add configurable default LE PHY policy Tarjei Bitustøyl
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 14+ messages in thread
From: Tarjei Bitustøyl @ 2026-05-24 22:14 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Tarjei Bitustøyl

Some controllers mis-handle LE procedures on specific PHYs with
certain peers. On an Intel AX210-class controller, connecting to a
Frostbay BLE device can fail during early ATT/GATT setup unless the
adapter is limited to LE 1M TX/RX.

Add an opt-in [LE] DefaultPHYs setting to bluetoothd and apply it at
adapter startup using MGMT_OP_GET/SET_PHY_CONFIGURATION while
preserving non-configurable PHY bits.

This provides a generic, adapter-wide workaround for controller-
specific LE PHY interoperability problems affecting scanning and
connection establishment, without adding device-specific quirks.
---
 src/adapter.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/btd.h     |  2 ++
 src/main.c    | 61 +++++++++++++++++++++++++++++++++++++++++
 src/main.conf |  8 ++++++
 4 files changed, 147 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index 20f7c3e03..fcbb65e38 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -4972,6 +4972,81 @@ done:
 	mgmt_tlv_list_free(list);
 }
 
+static void set_default_le_phys_complete(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct btd_adapter *adapter = user_data;
+
+	if (status != MGMT_STATUS_SUCCESS)
+		btd_error(adapter->dev_id,
+				"Failed to set default LE PHYs for hci%u: %s (0x%02x)",
+				adapter->dev_id, mgmt_errstr(status), status);
+}
+
+static void get_default_le_phys_complete(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct btd_adapter *adapter = user_data;
+	const struct mgmt_rp_get_phy_confguration *rp = param;
+	struct mgmt_cp_set_phy_confguration cp;
+	uint32_t configurable_phys;
+	uint32_t selected_phys;
+	uint32_t next_phys;
+
+	if (status != MGMT_STATUS_SUCCESS) {
+		btd_error(adapter->dev_id,
+				"Failed to read PHY configuration for hci%u: %s (0x%02x)",
+				adapter->dev_id, mgmt_errstr(status), status);
+		return;
+	}
+
+	if (length < sizeof(*rp)) {
+		btd_error(adapter->dev_id,
+				"Too small get PHY configuration response for hci%u",
+				adapter->dev_id);
+		return;
+	}
+
+	configurable_phys = btohl(rp->configurable_phys);
+	selected_phys = btohl(rp->selected_phys);
+
+	configurable_phys &= MGMT_PHY_LE_TX_MASK | MGMT_PHY_LE_RX_MASK;
+	next_phys = selected_phys & ~configurable_phys;
+	next_phys |= btd_opts.default_le_phys & configurable_phys;
+
+	if (next_phys == selected_phys)
+		return;
+
+	cp.selected_phys = cpu_to_le32(next_phys);
+
+	if (mgmt_send(adapter->mgmt, MGMT_OP_SET_PHY_CONFIGURATION,
+			adapter->dev_id, sizeof(cp), &cp,
+			set_default_le_phys_complete, adapter, NULL) > 0)
+		return;
+
+	btd_error(adapter->dev_id,
+			"Failed to set default LE PHYs for hci%u",
+			adapter->dev_id);
+}
+
+static void load_default_le_phys(struct btd_adapter *adapter)
+{
+	if (!btd_opts.default_le_phys_configured)
+		return;
+
+	if (!(adapter->supported_settings & MGMT_SETTING_LE))
+		return;
+
+	if (mgmt_send(adapter->mgmt, MGMT_OP_GET_PHY_CONFIGURATION,
+			adapter->dev_id, 0, NULL,
+			get_default_le_phys_complete, adapter, NULL) > 0)
+		return;
+
+	btd_error(adapter->dev_id,
+			"Failed to read PHY configuration for hci%u",
+			adapter->dev_id);
+}
+
 static void load_devices(struct btd_adapter *adapter)
 {
 	char dirname[PATH_MAX];
@@ -9455,6 +9530,7 @@ load:
 	btd_profile_foreach(probe_profile, adapter);
 	clear_blocked(adapter);
 	load_defaults(adapter);
+	load_default_le_phys(adapter);
 	load_devices(adapter);
 
 	/* restore Service Changed CCC value for bonded devices */
diff --git a/src/btd.h b/src/btd.h
index db2e81239..59f44dc8c 100644
--- a/src/btd.h
+++ b/src/btd.h
@@ -140,6 +140,8 @@ struct btd_opts {
 	bool		device_privacy;
 	uint32_t	name_request_retry_delay;
 	uint8_t		secure_conn;
+	uint32_t	default_le_phys;
+	bool		default_le_phys_configured;
 
 	struct btd_defaults defaults;
 
diff --git a/src/main.c b/src/main.c
index 8aa19a3e3..97c64845b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -32,6 +32,7 @@
 #include <dbus/dbus.h>
 
 #include "bluetooth/bluetooth.h"
+#include "bluetooth/mgmt.h"
 #include "bluetooth/sdp.h"
 
 #include "gdbus/gdbus.h"
@@ -132,6 +133,7 @@ static const char *le_options[] = {
 	"Autoconnecttimeout",
 	"AdvMonAllowlistScanDuration",
 	"AdvMonNoFilterScanDuration",
+	"DefaultPHYs",
 	"EnableAdvMonInterleaveScan",
 	NULL
 };
@@ -145,6 +147,8 @@ static const char *policy_options[] = {
 	NULL
 };
 
+static void parse_default_le_phys(GKeyFile *config);
+
 static const char *gatt_options[] = {
 	"Cache",
 	"KeySize",
@@ -751,6 +755,7 @@ static void parse_le_config(GKeyFile *config)
 		return;
 
 	parse_mode_config(config, "LE", params, ARRAY_SIZE(params));
+	parse_default_le_phys(config);
 }
 
 static bool match_experimental(const void *data, const void *match_data)
@@ -966,6 +971,62 @@ static void parse_repairing(GKeyFile *config)
 	g_free(str);
 }
 
+struct phy_config_entry {
+	const char *name;
+	uint32_t bit;
+};
+
+static const struct phy_config_entry le_phy_configs[] = {
+	{ "LE1MTX", MGMT_PHY_LE_1M_TX },
+	{ "LE1MRX", MGMT_PHY_LE_1M_RX },
+	{ "LE2MTX", MGMT_PHY_LE_2M_TX },
+	{ "LE2MRX", MGMT_PHY_LE_2M_RX },
+	{ "LECODEDTX", MGMT_PHY_LE_CODED_TX },
+	{ "LECODEDRX", MGMT_PHY_LE_CODED_RX },
+};
+
+static void parse_default_le_phys(GKeyFile *config)
+{
+	char *str = NULL;
+	char **tokens;
+	uint32_t phys = 0;
+	bool valid = false;
+	int i;
+
+	if (!parse_config_string(config, "LE", "DefaultPHYs", &str))
+		return;
+
+	tokens = g_strsplit_set(str, ", \t", -1);
+
+	for (i = 0; tokens[i]; i++) {
+		const char *token = tokens[i];
+		size_t j;
+
+		if (!token[0])
+			continue;
+
+		for (j = 0; j < ARRAY_SIZE(le_phy_configs); j++) {
+			if (strcasecmp(le_phy_configs[j].name, token) != 0)
+				continue;
+
+			phys |= le_phy_configs[j].bit;
+			valid = true;
+			break;
+		}
+
+		if (j == ARRAY_SIZE(le_phy_configs))
+			warn("Invalid DefaultPHYs token: %s", token);
+	}
+
+	if (valid) {
+		btd_opts.default_le_phys = phys;
+		btd_opts.default_le_phys_configured = true;
+	}
+
+	g_strfreev(tokens);
+	g_free(str);
+}
+
 static bool parse_config_hex(GKeyFile *config, char *group,
 					const char *key, uint32_t *val)
 {
diff --git a/src/main.conf b/src/main.conf
index 5846ef92d..ed955897e 100644
--- a/src/main.conf
+++ b/src/main.conf
@@ -247,6 +247,14 @@
 # Default: 500
 #AdvMonNoFilterScanDuration=
 
+# Configure the controller's default LE PHY policy used for scanning and
+# connection establishment. Only configurable LE PHYs are changed; mandatory
+# PHYs remain selected automatically.
+# Possible values: comma or space separated list of LE1MTX, LE1MRX, LE2MTX,
+# LE2MRX, LECODEDTX, LECODEDRX.
+# Example: keep LE on 1M only.
+#DefaultPHYs = LE1MTX LE1MRX
+
 # Enable/Disable Advertisement Monitor interleave scan for power saving.
 # 0: disable
 # 1: enable
-- 
2.43.0


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

* RE: Add configurable default LE PHY policy
  2026-05-24 22:14 ` [PATCH BlueZ 1/1] adapter: Add configurable default LE PHYs Tarjei Bitustøyl
@ 2026-05-24 23:07   ` bluez.test.bot
  2026-05-26 14:27   ` [PATCH BlueZ 1/1] adapter: Add configurable default LE PHYs Luiz Augusto von Dentz
  1 sibling, 0 replies; 14+ messages in thread
From: bluez.test.bot @ 2026-05-24 23:07 UTC (permalink / raw)
  To: linux-bluetooth, tarjeib

[-- Attachment #1: Type: text/plain, Size: 993 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/project/bluetooth/list/?series=1100107

---Test result---

Test Summary:
CheckPatch                    PASS      0.39 seconds
GitLint                       PASS      0.22 seconds
BuildEll                      PASS      15.83 seconds
BluezMake                     PASS      497.32 seconds
CheckSmatch                   WARNING   252.29 seconds
bluezmakeextell               PASS      127.97 seconds
IncrementalBuild              PASS      492.03 seconds
ScanBuild                     PASS      721.90 seconds

Details
##############################
Test: CheckSmatch - WARNING
Desc: Run smatch tool with source
Output:
src/main.c: note: in included file (through src/device.h):


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

---
Regards,
Linux Bluetooth


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

* [PATCH BlueZ v2 0/1] Add configurable default LE PHY policy
  2026-05-24 22:14 [PATCH BlueZ 0/1] Add configurable default LE PHY policy Tarjei Bitustøyl
  2026-05-24 22:14 ` [PATCH BlueZ 1/1] adapter: Add configurable default LE PHYs Tarjei Bitustøyl
@ 2026-05-25  6:50 ` Tarjei Bitustøyl
  2026-05-25  6:50   ` [PATCH BlueZ v2 1/1] adapter: Add configurable default LE PHYs Tarjei Bitustøyl
  2026-05-25 11:37 ` [PATCH BlueZ v3 0/1] " Tarjei Bitustøyl
  2026-05-25 14:50 ` [PATCH BlueZ v4 0/1] " Tarjei Bitustøyl
  3 siblings, 1 reply; 14+ messages in thread
From: Tarjei Bitustøyl @ 2026-05-25  6:50 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Tarjei Bitustøyl

This adds an opt-in bluetoothd setting for the adapter's default LE PHY
policy.

v2:
- Check MGMT_SETTING_PHY_CONFIGURATION before sending PHY
  configuration commands.

Tarjei Bitustøyl (1):
  adapter: Add configurable default LE PHYs

 src/adapter.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/btd.h     |  2 ++
 src/main.c    | 61 +++++++++++++++++++++++++++++++++++++++
 src/main.conf |  8 ++++++
 4 files changed, 150 insertions(+)

-- 
2.43.0


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

* [PATCH BlueZ v2 1/1] adapter: Add configurable default LE PHYs
  2026-05-25  6:50 ` [PATCH BlueZ v2 0/1] Add configurable default LE PHY policy Tarjei Bitustøyl
@ 2026-05-25  6:50   ` Tarjei Bitustøyl
  2026-05-25 11:04     ` Add configurable default LE PHY policy bluez.test.bot
  0 siblings, 1 reply; 14+ messages in thread
From: Tarjei Bitustøyl @ 2026-05-25  6:50 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Tarjei Bitustøyl

Some controllers mis-handle LE procedures on specific PHYs with
certain peers. On an Intel AX210-class controller, connecting to a
Frostbay BLE device can fail during early ATT/GATT setup unless the
adapter is limited to LE 1M TX/RX.

Add an opt-in [LE] DefaultPHYs setting to bluetoothd and apply it at
adapter startup using MGMT_OP_GET/SET_PHY_CONFIGURATION while
preserving non-configurable PHY bits.

This provides a generic, adapter-wide workaround for controller-
specific LE PHY interoperability problems affecting scanning and
connection establishment, without adding device-specific quirks.

v2:
- Check MGMT_SETTING_PHY_CONFIGURATION before sending PHY
  configuration commands.
---
 src/adapter.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/btd.h     |  2 ++
 src/main.c    | 61 +++++++++++++++++++++++++++++++++++++++
 src/main.conf |  8 ++++++
 4 files changed, 150 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index 20f7c3e03..46df362c5 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -4972,6 +4972,84 @@ done:
 	mgmt_tlv_list_free(list);
 }
 
+static void set_default_le_phys_complete(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct btd_adapter *adapter = user_data;
+
+	if (status != MGMT_STATUS_SUCCESS)
+		btd_error(adapter->dev_id,
+				"Failed to set default LE PHYs for hci%u: %s (0x%02x)",
+				adapter->dev_id, mgmt_errstr(status), status);
+}
+
+static void get_default_le_phys_complete(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct btd_adapter *adapter = user_data;
+	const struct mgmt_rp_get_phy_confguration *rp = param;
+	struct mgmt_cp_set_phy_confguration cp;
+	uint32_t configurable_phys;
+	uint32_t selected_phys;
+	uint32_t next_phys;
+
+	if (status != MGMT_STATUS_SUCCESS) {
+		btd_error(adapter->dev_id,
+				"Failed to read PHY configuration for hci%u: %s (0x%02x)",
+				adapter->dev_id, mgmt_errstr(status), status);
+		return;
+	}
+
+	if (length < sizeof(*rp)) {
+		btd_error(adapter->dev_id,
+				"Too small get PHY configuration response for hci%u",
+				adapter->dev_id);
+		return;
+	}
+
+	configurable_phys = btohl(rp->configurable_phys);
+	selected_phys = btohl(rp->selected_phys);
+
+	configurable_phys &= MGMT_PHY_LE_TX_MASK | MGMT_PHY_LE_RX_MASK;
+	next_phys = selected_phys & ~configurable_phys;
+	next_phys |= btd_opts.default_le_phys & configurable_phys;
+
+	if (next_phys == selected_phys)
+		return;
+
+	cp.selected_phys = cpu_to_le32(next_phys);
+
+	if (mgmt_send(adapter->mgmt, MGMT_OP_SET_PHY_CONFIGURATION,
+			adapter->dev_id, sizeof(cp), &cp,
+			set_default_le_phys_complete, adapter, NULL) > 0)
+		return;
+
+	btd_error(adapter->dev_id,
+			"Failed to set default LE PHYs for hci%u",
+			adapter->dev_id);
+}
+
+static void load_default_le_phys(struct btd_adapter *adapter)
+{
+	if (!btd_opts.default_le_phys_configured)
+		return;
+
+	if (!(adapter->supported_settings & MGMT_SETTING_LE))
+		return;
+
+	if (!(adapter->supported_settings & MGMT_SETTING_PHY_CONFIGURATION))
+		return;
+
+	if (mgmt_send(adapter->mgmt, MGMT_OP_GET_PHY_CONFIGURATION,
+			adapter->dev_id, 0, NULL,
+			get_default_le_phys_complete, adapter, NULL) > 0)
+		return;
+
+	btd_error(adapter->dev_id,
+			"Failed to read PHY configuration for hci%u",
+			adapter->dev_id);
+}
+
 static void load_devices(struct btd_adapter *adapter)
 {
 	char dirname[PATH_MAX];
@@ -9455,6 +9533,7 @@ load:
 	btd_profile_foreach(probe_profile, adapter);
 	clear_blocked(adapter);
 	load_defaults(adapter);
+	load_default_le_phys(adapter);
 	load_devices(adapter);
 
 	/* restore Service Changed CCC value for bonded devices */
diff --git a/src/btd.h b/src/btd.h
index db2e81239..59f44dc8c 100644
--- a/src/btd.h
+++ b/src/btd.h
@@ -140,6 +140,8 @@ struct btd_opts {
 	bool		device_privacy;
 	uint32_t	name_request_retry_delay;
 	uint8_t		secure_conn;
+	uint32_t	default_le_phys;
+	bool		default_le_phys_configured;
 
 	struct btd_defaults defaults;
 
diff --git a/src/main.c b/src/main.c
index 8aa19a3e3..97c64845b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -32,6 +32,7 @@
 #include <dbus/dbus.h>
 
 #include "bluetooth/bluetooth.h"
+#include "bluetooth/mgmt.h"
 #include "bluetooth/sdp.h"
 
 #include "gdbus/gdbus.h"
@@ -132,6 +133,7 @@ static const char *le_options[] = {
 	"Autoconnecttimeout",
 	"AdvMonAllowlistScanDuration",
 	"AdvMonNoFilterScanDuration",
+	"DefaultPHYs",
 	"EnableAdvMonInterleaveScan",
 	NULL
 };
@@ -145,6 +147,8 @@ static const char *policy_options[] = {
 	NULL
 };
 
+static void parse_default_le_phys(GKeyFile *config);
+
 static const char *gatt_options[] = {
 	"Cache",
 	"KeySize",
@@ -751,6 +755,7 @@ static void parse_le_config(GKeyFile *config)
 		return;
 
 	parse_mode_config(config, "LE", params, ARRAY_SIZE(params));
+	parse_default_le_phys(config);
 }
 
 static bool match_experimental(const void *data, const void *match_data)
@@ -966,6 +971,62 @@ static void parse_repairing(GKeyFile *config)
 	g_free(str);
 }
 
+struct phy_config_entry {
+	const char *name;
+	uint32_t bit;
+};
+
+static const struct phy_config_entry le_phy_configs[] = {
+	{ "LE1MTX", MGMT_PHY_LE_1M_TX },
+	{ "LE1MRX", MGMT_PHY_LE_1M_RX },
+	{ "LE2MTX", MGMT_PHY_LE_2M_TX },
+	{ "LE2MRX", MGMT_PHY_LE_2M_RX },
+	{ "LECODEDTX", MGMT_PHY_LE_CODED_TX },
+	{ "LECODEDRX", MGMT_PHY_LE_CODED_RX },
+};
+
+static void parse_default_le_phys(GKeyFile *config)
+{
+	char *str = NULL;
+	char **tokens;
+	uint32_t phys = 0;
+	bool valid = false;
+	int i;
+
+	if (!parse_config_string(config, "LE", "DefaultPHYs", &str))
+		return;
+
+	tokens = g_strsplit_set(str, ", \t", -1);
+
+	for (i = 0; tokens[i]; i++) {
+		const char *token = tokens[i];
+		size_t j;
+
+		if (!token[0])
+			continue;
+
+		for (j = 0; j < ARRAY_SIZE(le_phy_configs); j++) {
+			if (strcasecmp(le_phy_configs[j].name, token) != 0)
+				continue;
+
+			phys |= le_phy_configs[j].bit;
+			valid = true;
+			break;
+		}
+
+		if (j == ARRAY_SIZE(le_phy_configs))
+			warn("Invalid DefaultPHYs token: %s", token);
+	}
+
+	if (valid) {
+		btd_opts.default_le_phys = phys;
+		btd_opts.default_le_phys_configured = true;
+	}
+
+	g_strfreev(tokens);
+	g_free(str);
+}
+
 static bool parse_config_hex(GKeyFile *config, char *group,
 					const char *key, uint32_t *val)
 {
diff --git a/src/main.conf b/src/main.conf
index 5846ef92d..ed955897e 100644
--- a/src/main.conf
+++ b/src/main.conf
@@ -247,6 +247,14 @@
 # Default: 500
 #AdvMonNoFilterScanDuration=
 
+# Configure the controller's default LE PHY policy used for scanning and
+# connection establishment. Only configurable LE PHYs are changed; mandatory
+# PHYs remain selected automatically.
+# Possible values: comma or space separated list of LE1MTX, LE1MRX, LE2MTX,
+# LE2MRX, LECODEDTX, LECODEDRX.
+# Example: keep LE on 1M only.
+#DefaultPHYs = LE1MTX LE1MRX
+
 # Enable/Disable Advertisement Monitor interleave scan for power saving.
 # 0: disable
 # 1: enable
-- 
2.43.0


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

* RE: Add configurable default LE PHY policy
  2026-05-25  6:50   ` [PATCH BlueZ v2 1/1] adapter: Add configurable default LE PHYs Tarjei Bitustøyl
@ 2026-05-25 11:04     ` bluez.test.bot
  0 siblings, 0 replies; 14+ messages in thread
From: bluez.test.bot @ 2026-05-25 11:04 UTC (permalink / raw)
  To: linux-bluetooth, tarjeib

[-- Attachment #1: Type: text/plain, Size: 993 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/project/bluetooth/list/?series=1100262

---Test result---

Test Summary:
CheckPatch                    PASS      0.58 seconds
GitLint                       PASS      0.33 seconds
BuildEll                      PASS      20.00 seconds
BluezMake                     PASS      621.23 seconds
CheckSmatch                   WARNING   323.73 seconds
bluezmakeextell               PASS      164.72 seconds
IncrementalBuild              PASS      622.45 seconds
ScanBuild                     PASS      920.21 seconds

Details
##############################
Test: CheckSmatch - WARNING
Desc: Run smatch tool with source
Output:
src/main.c: note: in included file (through src/device.h):


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

---
Regards,
Linux Bluetooth


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

* [PATCH BlueZ v3 0/1] Add configurable default LE PHY policy
  2026-05-24 22:14 [PATCH BlueZ 0/1] Add configurable default LE PHY policy Tarjei Bitustøyl
  2026-05-24 22:14 ` [PATCH BlueZ 1/1] adapter: Add configurable default LE PHYs Tarjei Bitustøyl
  2026-05-25  6:50 ` [PATCH BlueZ v2 0/1] Add configurable default LE PHY policy Tarjei Bitustøyl
@ 2026-05-25 11:37 ` Tarjei Bitustøyl
  2026-05-25 11:37   ` [PATCH BlueZ v3 1/1] adapter: Add configurable default LE PHYs Tarjei Bitustøyl
  2026-05-25 14:50 ` [PATCH BlueZ v4 0/1] " Tarjei Bitustøyl
  3 siblings, 1 reply; 14+ messages in thread
From: Tarjei Bitustøyl @ 2026-05-25 11:37 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Tarjei Bitustøyl

This adds an opt-in bluetoothd setting for the adapter's default LE PHY
policy.

v3:
- Match the queue header include spelling in main.c with device.h to
  avoid the Sparse redefinition warning seen in CI.

v2:
- Check MGMT_SETTING_PHY_CONFIGURATION before sending PHY
  configuration commands.

Tarjei Bitustøyl (1):
  adapter: Add configurable default LE PHYs

 src/adapter.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/btd.h     |  2 ++
 src/main.c    | 63 +++++++++++++++++++++++++++++++++++++++-
 src/main.conf |  8 ++++++
 4 files changed, 151 insertions(+), 1 deletion(-)

-- 
2.43.0


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

* [PATCH BlueZ v3 1/1] adapter: Add configurable default LE PHYs
  2026-05-25 11:37 ` [PATCH BlueZ v3 0/1] " Tarjei Bitustøyl
@ 2026-05-25 11:37   ` Tarjei Bitustøyl
  2026-05-25 14:33     ` Add configurable default LE PHY policy bluez.test.bot
  0 siblings, 1 reply; 14+ messages in thread
From: Tarjei Bitustøyl @ 2026-05-25 11:37 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Tarjei Bitustøyl

Some controllers mis-handle LE procedures on specific PHYs with
certain peers. On an Intel AX210-class controller, connecting to a
Frostbay BLE device can fail during early ATT/GATT setup unless the
adapter is limited to LE 1M TX/RX.

Add an opt-in [LE] DefaultPHYs setting to bluetoothd and apply it at
adapter startup using MGMT_OP_GET/SET_PHY_CONFIGURATION while
preserving non-configurable PHY bits.

This provides a generic, adapter-wide workaround for controller-
specific LE PHY interoperability problems affecting scanning and
connection establishment, without adding device-specific quirks.

v3:
- Match the queue header include spelling in main.c with device.h to
	avoid the Sparse redefinition warning seen in CI.

v2:
- Check MGMT_SETTING_PHY_CONFIGURATION before sending PHY
	configuration commands.
---
 src/adapter.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/btd.h     |  2 ++
 src/main.c    | 63 +++++++++++++++++++++++++++++++++++++++-
 src/main.conf |  8 ++++++
 4 files changed, 151 insertions(+), 1 deletion(-)

diff --git a/src/adapter.c b/src/adapter.c
index 20f7c3e03..46df362c5 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -4972,6 +4972,84 @@ done:
 	mgmt_tlv_list_free(list);
 }
 
+static void set_default_le_phys_complete(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct btd_adapter *adapter = user_data;
+
+	if (status != MGMT_STATUS_SUCCESS)
+		btd_error(adapter->dev_id,
+				"Failed to set default LE PHYs for hci%u: %s (0x%02x)",
+				adapter->dev_id, mgmt_errstr(status), status);
+}
+
+static void get_default_le_phys_complete(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct btd_adapter *adapter = user_data;
+	const struct mgmt_rp_get_phy_confguration *rp = param;
+	struct mgmt_cp_set_phy_confguration cp;
+	uint32_t configurable_phys;
+	uint32_t selected_phys;
+	uint32_t next_phys;
+
+	if (status != MGMT_STATUS_SUCCESS) {
+		btd_error(adapter->dev_id,
+				"Failed to read PHY configuration for hci%u: %s (0x%02x)",
+				adapter->dev_id, mgmt_errstr(status), status);
+		return;
+	}
+
+	if (length < sizeof(*rp)) {
+		btd_error(adapter->dev_id,
+				"Too small get PHY configuration response for hci%u",
+				adapter->dev_id);
+		return;
+	}
+
+	configurable_phys = btohl(rp->configurable_phys);
+	selected_phys = btohl(rp->selected_phys);
+
+	configurable_phys &= MGMT_PHY_LE_TX_MASK | MGMT_PHY_LE_RX_MASK;
+	next_phys = selected_phys & ~configurable_phys;
+	next_phys |= btd_opts.default_le_phys & configurable_phys;
+
+	if (next_phys == selected_phys)
+		return;
+
+	cp.selected_phys = cpu_to_le32(next_phys);
+
+	if (mgmt_send(adapter->mgmt, MGMT_OP_SET_PHY_CONFIGURATION,
+			adapter->dev_id, sizeof(cp), &cp,
+			set_default_le_phys_complete, adapter, NULL) > 0)
+		return;
+
+	btd_error(adapter->dev_id,
+			"Failed to set default LE PHYs for hci%u",
+			adapter->dev_id);
+}
+
+static void load_default_le_phys(struct btd_adapter *adapter)
+{
+	if (!btd_opts.default_le_phys_configured)
+		return;
+
+	if (!(adapter->supported_settings & MGMT_SETTING_LE))
+		return;
+
+	if (!(adapter->supported_settings & MGMT_SETTING_PHY_CONFIGURATION))
+		return;
+
+	if (mgmt_send(adapter->mgmt, MGMT_OP_GET_PHY_CONFIGURATION,
+			adapter->dev_id, 0, NULL,
+			get_default_le_phys_complete, adapter, NULL) > 0)
+		return;
+
+	btd_error(adapter->dev_id,
+			"Failed to read PHY configuration for hci%u",
+			adapter->dev_id);
+}
+
 static void load_devices(struct btd_adapter *adapter)
 {
 	char dirname[PATH_MAX];
@@ -9455,6 +9533,7 @@ load:
 	btd_profile_foreach(probe_profile, adapter);
 	clear_blocked(adapter);
 	load_defaults(adapter);
+	load_default_le_phys(adapter);
 	load_devices(adapter);
 
 	/* restore Service Changed CCC value for bonded devices */
diff --git a/src/btd.h b/src/btd.h
index db2e81239..59f44dc8c 100644
--- a/src/btd.h
+++ b/src/btd.h
@@ -140,6 +140,8 @@ struct btd_opts {
 	bool		device_privacy;
 	uint32_t	name_request_retry_delay;
 	uint8_t		secure_conn;
+	uint32_t	default_le_phys;
+	bool		default_le_phys_configured;
 
 	struct btd_defaults defaults;
 
diff --git a/src/main.c b/src/main.c
index 8aa19a3e3..83be19be3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -32,6 +32,7 @@
 #include <dbus/dbus.h>
 
 #include "bluetooth/bluetooth.h"
+#include "bluetooth/mgmt.h"
 #include "bluetooth/sdp.h"
 
 #include "gdbus/gdbus.h"
@@ -43,7 +44,7 @@
 #include "shared/att-types.h"
 #include "shared/mainloop.h"
 #include "shared/timeout.h"
-#include "shared/queue.h"
+#include "src/shared/queue.h"
 #include "shared/crypto.h"
 #include "bluetooth/uuid.h"
 #include "shared/util.h"
@@ -132,6 +133,7 @@ static const char *le_options[] = {
 	"Autoconnecttimeout",
 	"AdvMonAllowlistScanDuration",
 	"AdvMonNoFilterScanDuration",
+	"DefaultPHYs",
 	"EnableAdvMonInterleaveScan",
 	NULL
 };
@@ -145,6 +147,8 @@ static const char *policy_options[] = {
 	NULL
 };
 
+static void parse_default_le_phys(GKeyFile *config);
+
 static const char *gatt_options[] = {
 	"Cache",
 	"KeySize",
@@ -751,6 +755,7 @@ static void parse_le_config(GKeyFile *config)
 		return;
 
 	parse_mode_config(config, "LE", params, ARRAY_SIZE(params));
+	parse_default_le_phys(config);
 }
 
 static bool match_experimental(const void *data, const void *match_data)
@@ -966,6 +971,62 @@ static void parse_repairing(GKeyFile *config)
 	g_free(str);
 }
 
+struct phy_config_entry {
+	const char *name;
+	uint32_t bit;
+};
+
+static const struct phy_config_entry le_phy_configs[] = {
+	{ "LE1MTX", MGMT_PHY_LE_1M_TX },
+	{ "LE1MRX", MGMT_PHY_LE_1M_RX },
+	{ "LE2MTX", MGMT_PHY_LE_2M_TX },
+	{ "LE2MRX", MGMT_PHY_LE_2M_RX },
+	{ "LECODEDTX", MGMT_PHY_LE_CODED_TX },
+	{ "LECODEDRX", MGMT_PHY_LE_CODED_RX },
+};
+
+static void parse_default_le_phys(GKeyFile *config)
+{
+	char *str = NULL;
+	char **tokens;
+	uint32_t phys = 0;
+	bool valid = false;
+	int i;
+
+	if (!parse_config_string(config, "LE", "DefaultPHYs", &str))
+		return;
+
+	tokens = g_strsplit_set(str, ", \t", -1);
+
+	for (i = 0; tokens[i]; i++) {
+		const char *token = tokens[i];
+		size_t j;
+
+		if (!token[0])
+			continue;
+
+		for (j = 0; j < ARRAY_SIZE(le_phy_configs); j++) {
+			if (strcasecmp(le_phy_configs[j].name, token) != 0)
+				continue;
+
+			phys |= le_phy_configs[j].bit;
+			valid = true;
+			break;
+		}
+
+		if (j == ARRAY_SIZE(le_phy_configs))
+			warn("Invalid DefaultPHYs token: %s", token);
+	}
+
+	if (valid) {
+		btd_opts.default_le_phys = phys;
+		btd_opts.default_le_phys_configured = true;
+	}
+
+	g_strfreev(tokens);
+	g_free(str);
+}
+
 static bool parse_config_hex(GKeyFile *config, char *group,
 					const char *key, uint32_t *val)
 {
diff --git a/src/main.conf b/src/main.conf
index 5846ef92d..ed955897e 100644
--- a/src/main.conf
+++ b/src/main.conf
@@ -247,6 +247,14 @@
 # Default: 500
 #AdvMonNoFilterScanDuration=
 
+# Configure the controller's default LE PHY policy used for scanning and
+# connection establishment. Only configurable LE PHYs are changed; mandatory
+# PHYs remain selected automatically.
+# Possible values: comma or space separated list of LE1MTX, LE1MRX, LE2MTX,
+# LE2MRX, LECODEDTX, LECODEDRX.
+# Example: keep LE on 1M only.
+#DefaultPHYs = LE1MTX LE1MRX
+
 # Enable/Disable Advertisement Monitor interleave scan for power saving.
 # 0: disable
 # 1: enable
-- 
2.43.0


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

* RE: Add configurable default LE PHY policy
  2026-05-25 11:37   ` [PATCH BlueZ v3 1/1] adapter: Add configurable default LE PHYs Tarjei Bitustøyl
@ 2026-05-25 14:33     ` bluez.test.bot
  0 siblings, 0 replies; 14+ messages in thread
From: bluez.test.bot @ 2026-05-25 14:33 UTC (permalink / raw)
  To: linux-bluetooth, tarjeib

[-- Attachment #1: Type: text/plain, Size: 1144 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/project/bluetooth/list/?series=1100433

---Test result---

Test Summary:
CheckPatch                    PASS      0.39 seconds
GitLint                       FAIL      0.21 seconds
BuildEll                      PASS      19.92 seconds
BluezMake                     PASS      646.41 seconds
CheckSmatch                   PASS      354.93 seconds
bluezmakeextell               PASS      182.02 seconds
IncrementalBuild              PASS      665.89 seconds
ScanBuild                     PASS      1045.30 seconds

Details
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[BlueZ,v3,1/1] adapter: Add configurable default LE PHYs

18: B3 Line contains hard tab characters (\t): "	avoid the Sparse redefinition warning seen in CI."
22: B3 Line contains hard tab characters (\t): "	configuration commands."


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

---
Regards,
Linux Bluetooth


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

* [PATCH BlueZ v4 0/1] Add configurable default LE PHY policy
  2026-05-24 22:14 [PATCH BlueZ 0/1] Add configurable default LE PHY policy Tarjei Bitustøyl
                   ` (2 preceding siblings ...)
  2026-05-25 11:37 ` [PATCH BlueZ v3 0/1] " Tarjei Bitustøyl
@ 2026-05-25 14:50 ` Tarjei Bitustøyl
  2026-05-25 14:50   ` [PATCH BlueZ v4 1/1] adapter: Add configurable default LE PHYs Tarjei Bitustøyl
  3 siblings, 1 reply; 14+ messages in thread
From: Tarjei Bitustøyl @ 2026-05-25 14:50 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Tarjei Bitustøyl

This adds an opt-in bluetoothd setting for the adapter's default LE PHY
policy.

v4:
- Replace the hard tabs in the changelog continuation lines with spaces
  to satisfy GitLint.

v3:
- Match the queue header include spelling in main.c with device.h to
  avoid the Sparse redefinition warning seen in CI.

v2:
- Check MGMT_SETTING_PHY_CONFIGURATION before sending PHY
  configuration commands.

Tarjei Bitustøyl (1):
  adapter: Add configurable default LE PHYs

 src/adapter.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/btd.h     |  2 ++
 src/main.c    | 63 +++++++++++++++++++++++++++++++++++++++-
 src/main.conf |  8 ++++++
 4 files changed, 151 insertions(+), 1 deletion(-)

-- 
2.43.0


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

* [PATCH BlueZ v4 1/1] adapter: Add configurable default LE PHYs
  2026-05-25 14:50 ` [PATCH BlueZ v4 0/1] " Tarjei Bitustøyl
@ 2026-05-25 14:50   ` Tarjei Bitustøyl
  2026-05-25 16:55     ` Add configurable default LE PHY policy bluez.test.bot
  0 siblings, 1 reply; 14+ messages in thread
From: Tarjei Bitustøyl @ 2026-05-25 14:50 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Tarjei Bitustøyl

Some controllers mis-handle LE procedures on specific PHYs with
certain peers. On an Intel AX210-class controller, connecting to a
Frostbay BLE device can fail during early ATT/GATT setup unless the
adapter is limited to LE 1M TX/RX.

Add an opt-in [LE] DefaultPHYs setting to bluetoothd and apply it at
adapter startup using MGMT_OP_GET/SET_PHY_CONFIGURATION while
preserving non-configurable PHY bits.

This provides a generic, adapter-wide workaround for controller-
specific LE PHY interoperability problems affecting scanning and
connection establishment, without adding device-specific quirks.

v4:
- Replace the hard tabs in the changelog continuation lines with spaces
  to satisfy GitLint.

v3:
- Match the queue header include spelling in main.c with device.h to
  avoid the Sparse redefinition warning seen in CI.

v2:
- Check MGMT_SETTING_PHY_CONFIGURATION before sending PHY
  configuration commands.
---
 src/adapter.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/btd.h     |  2 ++
 src/main.c    | 63 +++++++++++++++++++++++++++++++++++++++-
 src/main.conf |  8 ++++++
 4 files changed, 151 insertions(+), 1 deletion(-)

diff --git a/src/adapter.c b/src/adapter.c
index 20f7c3e03..46df362c5 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -4972,6 +4972,84 @@ done:
 	mgmt_tlv_list_free(list);
 }
 
+static void set_default_le_phys_complete(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct btd_adapter *adapter = user_data;
+
+	if (status != MGMT_STATUS_SUCCESS)
+		btd_error(adapter->dev_id,
+				"Failed to set default LE PHYs for hci%u: %s (0x%02x)",
+				adapter->dev_id, mgmt_errstr(status), status);
+}
+
+static void get_default_le_phys_complete(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct btd_adapter *adapter = user_data;
+	const struct mgmt_rp_get_phy_confguration *rp = param;
+	struct mgmt_cp_set_phy_confguration cp;
+	uint32_t configurable_phys;
+	uint32_t selected_phys;
+	uint32_t next_phys;
+
+	if (status != MGMT_STATUS_SUCCESS) {
+		btd_error(adapter->dev_id,
+				"Failed to read PHY configuration for hci%u: %s (0x%02x)",
+				adapter->dev_id, mgmt_errstr(status), status);
+		return;
+	}
+
+	if (length < sizeof(*rp)) {
+		btd_error(adapter->dev_id,
+				"Too small get PHY configuration response for hci%u",
+				adapter->dev_id);
+		return;
+	}
+
+	configurable_phys = btohl(rp->configurable_phys);
+	selected_phys = btohl(rp->selected_phys);
+
+	configurable_phys &= MGMT_PHY_LE_TX_MASK | MGMT_PHY_LE_RX_MASK;
+	next_phys = selected_phys & ~configurable_phys;
+	next_phys |= btd_opts.default_le_phys & configurable_phys;
+
+	if (next_phys == selected_phys)
+		return;
+
+	cp.selected_phys = cpu_to_le32(next_phys);
+
+	if (mgmt_send(adapter->mgmt, MGMT_OP_SET_PHY_CONFIGURATION,
+			adapter->dev_id, sizeof(cp), &cp,
+			set_default_le_phys_complete, adapter, NULL) > 0)
+		return;
+
+	btd_error(adapter->dev_id,
+			"Failed to set default LE PHYs for hci%u",
+			adapter->dev_id);
+}
+
+static void load_default_le_phys(struct btd_adapter *adapter)
+{
+	if (!btd_opts.default_le_phys_configured)
+		return;
+
+	if (!(adapter->supported_settings & MGMT_SETTING_LE))
+		return;
+
+	if (!(adapter->supported_settings & MGMT_SETTING_PHY_CONFIGURATION))
+		return;
+
+	if (mgmt_send(adapter->mgmt, MGMT_OP_GET_PHY_CONFIGURATION,
+			adapter->dev_id, 0, NULL,
+			get_default_le_phys_complete, adapter, NULL) > 0)
+		return;
+
+	btd_error(adapter->dev_id,
+			"Failed to read PHY configuration for hci%u",
+			adapter->dev_id);
+}
+
 static void load_devices(struct btd_adapter *adapter)
 {
 	char dirname[PATH_MAX];
@@ -9455,6 +9533,7 @@ load:
 	btd_profile_foreach(probe_profile, adapter);
 	clear_blocked(adapter);
 	load_defaults(adapter);
+	load_default_le_phys(adapter);
 	load_devices(adapter);
 
 	/* restore Service Changed CCC value for bonded devices */
diff --git a/src/btd.h b/src/btd.h
index db2e81239..59f44dc8c 100644
--- a/src/btd.h
+++ b/src/btd.h
@@ -140,6 +140,8 @@ struct btd_opts {
 	bool		device_privacy;
 	uint32_t	name_request_retry_delay;
 	uint8_t		secure_conn;
+	uint32_t	default_le_phys;
+	bool		default_le_phys_configured;
 
 	struct btd_defaults defaults;
 
diff --git a/src/main.c b/src/main.c
index 8aa19a3e3..83be19be3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -32,6 +32,7 @@
 #include <dbus/dbus.h>
 
 #include "bluetooth/bluetooth.h"
+#include "bluetooth/mgmt.h"
 #include "bluetooth/sdp.h"
 
 #include "gdbus/gdbus.h"
@@ -43,7 +44,7 @@
 #include "shared/att-types.h"
 #include "shared/mainloop.h"
 #include "shared/timeout.h"
-#include "shared/queue.h"
+#include "src/shared/queue.h"
 #include "shared/crypto.h"
 #include "bluetooth/uuid.h"
 #include "shared/util.h"
@@ -132,6 +133,7 @@ static const char *le_options[] = {
 	"Autoconnecttimeout",
 	"AdvMonAllowlistScanDuration",
 	"AdvMonNoFilterScanDuration",
+	"DefaultPHYs",
 	"EnableAdvMonInterleaveScan",
 	NULL
 };
@@ -145,6 +147,8 @@ static const char *policy_options[] = {
 	NULL
 };
 
+static void parse_default_le_phys(GKeyFile *config);
+
 static const char *gatt_options[] = {
 	"Cache",
 	"KeySize",
@@ -751,6 +755,7 @@ static void parse_le_config(GKeyFile *config)
 		return;
 
 	parse_mode_config(config, "LE", params, ARRAY_SIZE(params));
+	parse_default_le_phys(config);
 }
 
 static bool match_experimental(const void *data, const void *match_data)
@@ -966,6 +971,62 @@ static void parse_repairing(GKeyFile *config)
 	g_free(str);
 }
 
+struct phy_config_entry {
+	const char *name;
+	uint32_t bit;
+};
+
+static const struct phy_config_entry le_phy_configs[] = {
+	{ "LE1MTX", MGMT_PHY_LE_1M_TX },
+	{ "LE1MRX", MGMT_PHY_LE_1M_RX },
+	{ "LE2MTX", MGMT_PHY_LE_2M_TX },
+	{ "LE2MRX", MGMT_PHY_LE_2M_RX },
+	{ "LECODEDTX", MGMT_PHY_LE_CODED_TX },
+	{ "LECODEDRX", MGMT_PHY_LE_CODED_RX },
+};
+
+static void parse_default_le_phys(GKeyFile *config)
+{
+	char *str = NULL;
+	char **tokens;
+	uint32_t phys = 0;
+	bool valid = false;
+	int i;
+
+	if (!parse_config_string(config, "LE", "DefaultPHYs", &str))
+		return;
+
+	tokens = g_strsplit_set(str, ", \t", -1);
+
+	for (i = 0; tokens[i]; i++) {
+		const char *token = tokens[i];
+		size_t j;
+
+		if (!token[0])
+			continue;
+
+		for (j = 0; j < ARRAY_SIZE(le_phy_configs); j++) {
+			if (strcasecmp(le_phy_configs[j].name, token) != 0)
+				continue;
+
+			phys |= le_phy_configs[j].bit;
+			valid = true;
+			break;
+		}
+
+		if (j == ARRAY_SIZE(le_phy_configs))
+			warn("Invalid DefaultPHYs token: %s", token);
+	}
+
+	if (valid) {
+		btd_opts.default_le_phys = phys;
+		btd_opts.default_le_phys_configured = true;
+	}
+
+	g_strfreev(tokens);
+	g_free(str);
+}
+
 static bool parse_config_hex(GKeyFile *config, char *group,
 					const char *key, uint32_t *val)
 {
diff --git a/src/main.conf b/src/main.conf
index 5846ef92d..ed955897e 100644
--- a/src/main.conf
+++ b/src/main.conf
@@ -247,6 +247,14 @@
 # Default: 500
 #AdvMonNoFilterScanDuration=
 
+# Configure the controller's default LE PHY policy used for scanning and
+# connection establishment. Only configurable LE PHYs are changed; mandatory
+# PHYs remain selected automatically.
+# Possible values: comma or space separated list of LE1MTX, LE1MRX, LE2MTX,
+# LE2MRX, LECODEDTX, LECODEDRX.
+# Example: keep LE on 1M only.
+#DefaultPHYs = LE1MTX LE1MRX
+
 # Enable/Disable Advertisement Monitor interleave scan for power saving.
 # 0: disable
 # 1: enable
-- 
2.43.0


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

* RE: Add configurable default LE PHY policy
  2026-05-25 14:50   ` [PATCH BlueZ v4 1/1] adapter: Add configurable default LE PHYs Tarjei Bitustøyl
@ 2026-05-25 16:55     ` bluez.test.bot
  0 siblings, 0 replies; 14+ messages in thread
From: bluez.test.bot @ 2026-05-25 16:55 UTC (permalink / raw)
  To: linux-bluetooth, tarjeib

[-- Attachment #1: Type: text/plain, Size: 825 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/project/bluetooth/list/?series=1100512

---Test result---

Test Summary:
CheckPatch                    PASS      0.58 seconds
GitLint                       PASS      0.33 seconds
BuildEll                      PASS      20.48 seconds
BluezMake                     PASS      632.11 seconds
CheckSmatch                   PASS      328.33 seconds
bluezmakeextell               PASS      167.60 seconds
IncrementalBuild              PASS      620.54 seconds
ScanBuild                     PASS      923.33 seconds



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

---
Regards,
Linux Bluetooth


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

* Re: [PATCH BlueZ 1/1] adapter: Add configurable default LE PHYs
  2026-05-24 22:14 ` [PATCH BlueZ 1/1] adapter: Add configurable default LE PHYs Tarjei Bitustøyl
  2026-05-24 23:07   ` Add configurable default LE PHY policy bluez.test.bot
@ 2026-05-26 14:27   ` Luiz Augusto von Dentz
  2026-05-26 18:58     ` Tarjei Bitustøyl
  1 sibling, 1 reply; 14+ messages in thread
From: Luiz Augusto von Dentz @ 2026-05-26 14:27 UTC (permalink / raw)
  To: Tarjei Bitustøyl; +Cc: linux-bluetooth

Hi Tarjei,

On Sun, May 24, 2026 at 6:14 PM Tarjei Bitustøyl <tarjeib@gmail.com> wrote:
>
> Some controllers mis-handle LE procedures on specific PHYs with
> certain peers. On an Intel AX210-class controller, connecting to a
> Frostbay BLE device can fail during early ATT/GATT setup unless the
> adapter is limited to LE 1M TX/RX.

Perhaps there should be a GitHub issue explaining exactly what the
problem is with btmon logs, etc, Then we can evaluate if this needs a
workaround like this or if we should detect that certain PHYs should
not be used.

> Add an opt-in [LE] DefaultPHYs setting to bluetoothd and apply it at
> adapter startup using MGMT_OP_GET/SET_PHY_CONFIGURATION while
> preserving non-configurable PHY bits.
>
> This provides a generic, adapter-wide workaround for controller-
> specific LE PHY interoperability problems affecting scanning and
> connection establishment, without adding device-specific quirks.

Well it is not really controller specific though, since it applies to
any controller on the system. Also, I believe this could be a device
specific problem so you might be taking away 2M support entirely when
it could actually be supported with another device.

> ---
>  src/adapter.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  src/btd.h     |  2 ++
>  src/main.c    | 61 +++++++++++++++++++++++++++++++++++++++++
>  src/main.conf |  8 ++++++
>  4 files changed, 147 insertions(+)
>
> diff --git a/src/adapter.c b/src/adapter.c
> index 20f7c3e03..fcbb65e38 100644
> --- a/src/adapter.c
> +++ b/src/adapter.c
> @@ -4972,6 +4972,81 @@ done:
>         mgmt_tlv_list_free(list);
>  }
>
> +static void set_default_le_phys_complete(uint8_t status, uint16_t length,
> +                                       const void *param, void *user_data)
> +{
> +       struct btd_adapter *adapter = user_data;
> +
> +       if (status != MGMT_STATUS_SUCCESS)
> +               btd_error(adapter->dev_id,
> +                               "Failed to set default LE PHYs for hci%u: %s (0x%02x)",
> +                               adapter->dev_id, mgmt_errstr(status), status);
> +}
> +
> +static void get_default_le_phys_complete(uint8_t status, uint16_t length,
> +                                       const void *param, void *user_data)
> +{
> +       struct btd_adapter *adapter = user_data;
> +       const struct mgmt_rp_get_phy_confguration *rp = param;
> +       struct mgmt_cp_set_phy_confguration cp;
> +       uint32_t configurable_phys;
> +       uint32_t selected_phys;
> +       uint32_t next_phys;
> +
> +       if (status != MGMT_STATUS_SUCCESS) {
> +               btd_error(adapter->dev_id,
> +                               "Failed to read PHY configuration for hci%u: %s (0x%02x)",
> +                               adapter->dev_id, mgmt_errstr(status), status);
> +               return;
> +       }
> +
> +       if (length < sizeof(*rp)) {
> +               btd_error(adapter->dev_id,
> +                               "Too small get PHY configuration response for hci%u",
> +                               adapter->dev_id);
> +               return;
> +       }
> +
> +       configurable_phys = btohl(rp->configurable_phys);
> +       selected_phys = btohl(rp->selected_phys);
> +
> +       configurable_phys &= MGMT_PHY_LE_TX_MASK | MGMT_PHY_LE_RX_MASK;
> +       next_phys = selected_phys & ~configurable_phys;
> +       next_phys |= btd_opts.default_le_phys & configurable_phys;
> +
> +       if (next_phys == selected_phys)
> +               return;
> +
> +       cp.selected_phys = cpu_to_le32(next_phys);
> +
> +       if (mgmt_send(adapter->mgmt, MGMT_OP_SET_PHY_CONFIGURATION,
> +                       adapter->dev_id, sizeof(cp), &cp,
> +                       set_default_le_phys_complete, adapter, NULL) > 0)
> +               return;
> +
> +       btd_error(adapter->dev_id,
> +                       "Failed to set default LE PHYs for hci%u",
> +                       adapter->dev_id);
> +}
> +
> +static void load_default_le_phys(struct btd_adapter *adapter)
> +{
> +       if (!btd_opts.default_le_phys_configured)
> +               return;
> +
> +       if (!(adapter->supported_settings & MGMT_SETTING_LE))
> +               return;
> +
> +       if (mgmt_send(adapter->mgmt, MGMT_OP_GET_PHY_CONFIGURATION,
> +                       adapter->dev_id, 0, NULL,
> +                       get_default_le_phys_complete, adapter, NULL) > 0)
> +               return;
> +
> +       btd_error(adapter->dev_id,
> +                       "Failed to read PHY configuration for hci%u",
> +                       adapter->dev_id);
> +}
> +
>  static void load_devices(struct btd_adapter *adapter)
>  {
>         char dirname[PATH_MAX];
> @@ -9455,6 +9530,7 @@ load:
>         btd_profile_foreach(probe_profile, adapter);
>         clear_blocked(adapter);
>         load_defaults(adapter);
> +       load_default_le_phys(adapter);
>         load_devices(adapter);
>
>         /* restore Service Changed CCC value for bonded devices */
> diff --git a/src/btd.h b/src/btd.h
> index db2e81239..59f44dc8c 100644
> --- a/src/btd.h
> +++ b/src/btd.h
> @@ -140,6 +140,8 @@ struct btd_opts {
>         bool            device_privacy;
>         uint32_t        name_request_retry_delay;
>         uint8_t         secure_conn;
> +       uint32_t        default_le_phys;
> +       bool            default_le_phys_configured;
>
>         struct btd_defaults defaults;
>
> diff --git a/src/main.c b/src/main.c
> index 8aa19a3e3..97c64845b 100644
> --- a/src/main.c
> +++ b/src/main.c
> @@ -32,6 +32,7 @@
>  #include <dbus/dbus.h>
>
>  #include "bluetooth/bluetooth.h"
> +#include "bluetooth/mgmt.h"
>  #include "bluetooth/sdp.h"
>
>  #include "gdbus/gdbus.h"
> @@ -132,6 +133,7 @@ static const char *le_options[] = {
>         "Autoconnecttimeout",
>         "AdvMonAllowlistScanDuration",
>         "AdvMonNoFilterScanDuration",
> +       "DefaultPHYs",
>         "EnableAdvMonInterleaveScan",
>         NULL
>  };
> @@ -145,6 +147,8 @@ static const char *policy_options[] = {
>         NULL
>  };
>
> +static void parse_default_le_phys(GKeyFile *config);
> +
>  static const char *gatt_options[] = {
>         "Cache",
>         "KeySize",
> @@ -751,6 +755,7 @@ static void parse_le_config(GKeyFile *config)
>                 return;
>
>         parse_mode_config(config, "LE", params, ARRAY_SIZE(params));
> +       parse_default_le_phys(config);
>  }
>
>  static bool match_experimental(const void *data, const void *match_data)
> @@ -966,6 +971,62 @@ static void parse_repairing(GKeyFile *config)
>         g_free(str);
>  }
>
> +struct phy_config_entry {
> +       const char *name;
> +       uint32_t bit;
> +};
> +
> +static const struct phy_config_entry le_phy_configs[] = {
> +       { "LE1MTX", MGMT_PHY_LE_1M_TX },
> +       { "LE1MRX", MGMT_PHY_LE_1M_RX },
> +       { "LE2MTX", MGMT_PHY_LE_2M_TX },
> +       { "LE2MRX", MGMT_PHY_LE_2M_RX },
> +       { "LECODEDTX", MGMT_PHY_LE_CODED_TX },
> +       { "LECODEDRX", MGMT_PHY_LE_CODED_RX },
> +};
> +
> +static void parse_default_le_phys(GKeyFile *config)
> +{
> +       char *str = NULL;
> +       char **tokens;
> +       uint32_t phys = 0;
> +       bool valid = false;
> +       int i;
> +
> +       if (!parse_config_string(config, "LE", "DefaultPHYs", &str))
> +               return;
> +
> +       tokens = g_strsplit_set(str, ", \t", -1);
> +
> +       for (i = 0; tokens[i]; i++) {
> +               const char *token = tokens[i];
> +               size_t j;
> +
> +               if (!token[0])
> +                       continue;
> +
> +               for (j = 0; j < ARRAY_SIZE(le_phy_configs); j++) {
> +                       if (strcasecmp(le_phy_configs[j].name, token) != 0)
> +                               continue;
> +
> +                       phys |= le_phy_configs[j].bit;
> +                       valid = true;
> +                       break;
> +               }
> +
> +               if (j == ARRAY_SIZE(le_phy_configs))
> +                       warn("Invalid DefaultPHYs token: %s", token);
> +       }
> +
> +       if (valid) {
> +               btd_opts.default_le_phys = phys;
> +               btd_opts.default_le_phys_configured = true;
> +       }
> +
> +       g_strfreev(tokens);
> +       g_free(str);
> +}
> +
>  static bool parse_config_hex(GKeyFile *config, char *group,
>                                         const char *key, uint32_t *val)
>  {
> diff --git a/src/main.conf b/src/main.conf
> index 5846ef92d..ed955897e 100644
> --- a/src/main.conf
> +++ b/src/main.conf
> @@ -247,6 +247,14 @@
>  # Default: 500
>  #AdvMonNoFilterScanDuration=
>
> +# Configure the controller's default LE PHY policy used for scanning and
> +# connection establishment. Only configurable LE PHYs are changed; mandatory
> +# PHYs remain selected automatically.
> +# Possible values: comma or space separated list of LE1MTX, LE1MRX, LE2MTX,
> +# LE2MRX, LECODEDTX, LECODEDRX.
> +# Example: keep LE on 1M only.
> +#DefaultPHYs = LE1MTX LE1MRX
> +
>  # Enable/Disable Advertisement Monitor interleave scan for power saving.
>  # 0: disable
>  # 1: enable
> --
> 2.43.0
>
>


-- 
Luiz Augusto von Dentz

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

* Re: [PATCH BlueZ 1/1] adapter: Add configurable default LE PHYs
  2026-05-26 14:27   ` [PATCH BlueZ 1/1] adapter: Add configurable default LE PHYs Luiz Augusto von Dentz
@ 2026-05-26 18:58     ` Tarjei Bitustøyl
  0 siblings, 0 replies; 14+ messages in thread
From: Tarjei Bitustøyl @ 2026-05-26 18:58 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

Yea you're right, I assumed too much here. I have only identified it
with my Frostbay device, not any other device. I've made a GitHub
issue with btmon logs and others that should show the issue.
I do still suspect that this is an issue for other BLE devices on the
Intel AX210 though.
Issue is 2155.

Regards,
Tarjei


tir. 26. mai 2026 kl. 16:27 skrev Luiz Augusto von Dentz <luiz.dentz@gmail.com>:
>
> Hi Tarjei,
>
> On Sun, May 24, 2026 at 6:14 PM Tarjei Bitustøyl <tarjeib@gmail.com> wrote:
> >
> > Some controllers mis-handle LE procedures on specific PHYs with
> > certain peers. On an Intel AX210-class controller, connecting to a
> > Frostbay BLE device can fail during early ATT/GATT setup unless the
> > adapter is limited to LE 1M TX/RX.
>
> Perhaps there should be a GitHub issue explaining exactly what the
> problem is with btmon logs, etc, Then we can evaluate if this needs a
> workaround like this or if we should detect that certain PHYs should
> not be used.
>
> > Add an opt-in [LE] DefaultPHYs setting to bluetoothd and apply it at
> > adapter startup using MGMT_OP_GET/SET_PHY_CONFIGURATION while
> > preserving non-configurable PHY bits.
> >
> > This provides a generic, adapter-wide workaround for controller-
> > specific LE PHY interoperability problems affecting scanning and
> > connection establishment, without adding device-specific quirks.
>
> Well it is not really controller specific though, since it applies to
> any controller on the system. Also, I believe this could be a device
> specific problem so you might be taking away 2M support entirely when
> it could actually be supported with another device.
>
> > ---
> >  src/adapter.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++
> >  src/btd.h     |  2 ++
> >  src/main.c    | 61 +++++++++++++++++++++++++++++++++++++++++
> >  src/main.conf |  8 ++++++
> >  4 files changed, 147 insertions(+)
> >
> > diff --git a/src/adapter.c b/src/adapter.c
> > index 20f7c3e03..fcbb65e38 100644
> > --- a/src/adapter.c
> > +++ b/src/adapter.c
> > @@ -4972,6 +4972,81 @@ done:
> >         mgmt_tlv_list_free(list);
> >  }
> >
> > +static void set_default_le_phys_complete(uint8_t status, uint16_t length,
> > +                                       const void *param, void *user_data)
> > +{
> > +       struct btd_adapter *adapter = user_data;
> > +
> > +       if (status != MGMT_STATUS_SUCCESS)
> > +               btd_error(adapter->dev_id,
> > +                               "Failed to set default LE PHYs for hci%u: %s (0x%02x)",
> > +                               adapter->dev_id, mgmt_errstr(status), status);
> > +}
> > +
> > +static void get_default_le_phys_complete(uint8_t status, uint16_t length,
> > +                                       const void *param, void *user_data)
> > +{
> > +       struct btd_adapter *adapter = user_data;
> > +       const struct mgmt_rp_get_phy_confguration *rp = param;
> > +       struct mgmt_cp_set_phy_confguration cp;
> > +       uint32_t configurable_phys;
> > +       uint32_t selected_phys;
> > +       uint32_t next_phys;
> > +
> > +       if (status != MGMT_STATUS_SUCCESS) {
> > +               btd_error(adapter->dev_id,
> > +                               "Failed to read PHY configuration for hci%u: %s (0x%02x)",
> > +                               adapter->dev_id, mgmt_errstr(status), status);
> > +               return;
> > +       }
> > +
> > +       if (length < sizeof(*rp)) {
> > +               btd_error(adapter->dev_id,
> > +                               "Too small get PHY configuration response for hci%u",
> > +                               adapter->dev_id);
> > +               return;
> > +       }
> > +
> > +       configurable_phys = btohl(rp->configurable_phys);
> > +       selected_phys = btohl(rp->selected_phys);
> > +
> > +       configurable_phys &= MGMT_PHY_LE_TX_MASK | MGMT_PHY_LE_RX_MASK;
> > +       next_phys = selected_phys & ~configurable_phys;
> > +       next_phys |= btd_opts.default_le_phys & configurable_phys;
> > +
> > +       if (next_phys == selected_phys)
> > +               return;
> > +
> > +       cp.selected_phys = cpu_to_le32(next_phys);
> > +
> > +       if (mgmt_send(adapter->mgmt, MGMT_OP_SET_PHY_CONFIGURATION,
> > +                       adapter->dev_id, sizeof(cp), &cp,
> > +                       set_default_le_phys_complete, adapter, NULL) > 0)
> > +               return;
> > +
> > +       btd_error(adapter->dev_id,
> > +                       "Failed to set default LE PHYs for hci%u",
> > +                       adapter->dev_id);
> > +}
> > +
> > +static void load_default_le_phys(struct btd_adapter *adapter)
> > +{
> > +       if (!btd_opts.default_le_phys_configured)
> > +               return;
> > +
> > +       if (!(adapter->supported_settings & MGMT_SETTING_LE))
> > +               return;
> > +
> > +       if (mgmt_send(adapter->mgmt, MGMT_OP_GET_PHY_CONFIGURATION,
> > +                       adapter->dev_id, 0, NULL,
> > +                       get_default_le_phys_complete, adapter, NULL) > 0)
> > +               return;
> > +
> > +       btd_error(adapter->dev_id,
> > +                       "Failed to read PHY configuration for hci%u",
> > +                       adapter->dev_id);
> > +}
> > +
> >  static void load_devices(struct btd_adapter *adapter)
> >  {
> >         char dirname[PATH_MAX];
> > @@ -9455,6 +9530,7 @@ load:
> >         btd_profile_foreach(probe_profile, adapter);
> >         clear_blocked(adapter);
> >         load_defaults(adapter);
> > +       load_default_le_phys(adapter);
> >         load_devices(adapter);
> >
> >         /* restore Service Changed CCC value for bonded devices */
> > diff --git a/src/btd.h b/src/btd.h
> > index db2e81239..59f44dc8c 100644
> > --- a/src/btd.h
> > +++ b/src/btd.h
> > @@ -140,6 +140,8 @@ struct btd_opts {
> >         bool            device_privacy;
> >         uint32_t        name_request_retry_delay;
> >         uint8_t         secure_conn;
> > +       uint32_t        default_le_phys;
> > +       bool            default_le_phys_configured;
> >
> >         struct btd_defaults defaults;
> >
> > diff --git a/src/main.c b/src/main.c
> > index 8aa19a3e3..97c64845b 100644
> > --- a/src/main.c
> > +++ b/src/main.c
> > @@ -32,6 +32,7 @@
> >  #include <dbus/dbus.h>
> >
> >  #include "bluetooth/bluetooth.h"
> > +#include "bluetooth/mgmt.h"
> >  #include "bluetooth/sdp.h"
> >
> >  #include "gdbus/gdbus.h"
> > @@ -132,6 +133,7 @@ static const char *le_options[] = {
> >         "Autoconnecttimeout",
> >         "AdvMonAllowlistScanDuration",
> >         "AdvMonNoFilterScanDuration",
> > +       "DefaultPHYs",
> >         "EnableAdvMonInterleaveScan",
> >         NULL
> >  };
> > @@ -145,6 +147,8 @@ static const char *policy_options[] = {
> >         NULL
> >  };
> >
> > +static void parse_default_le_phys(GKeyFile *config);
> > +
> >  static const char *gatt_options[] = {
> >         "Cache",
> >         "KeySize",
> > @@ -751,6 +755,7 @@ static void parse_le_config(GKeyFile *config)
> >                 return;
> >
> >         parse_mode_config(config, "LE", params, ARRAY_SIZE(params));
> > +       parse_default_le_phys(config);
> >  }
> >
> >  static bool match_experimental(const void *data, const void *match_data)
> > @@ -966,6 +971,62 @@ static void parse_repairing(GKeyFile *config)
> >         g_free(str);
> >  }
> >
> > +struct phy_config_entry {
> > +       const char *name;
> > +       uint32_t bit;
> > +};
> > +
> > +static const struct phy_config_entry le_phy_configs[] = {
> > +       { "LE1MTX", MGMT_PHY_LE_1M_TX },
> > +       { "LE1MRX", MGMT_PHY_LE_1M_RX },
> > +       { "LE2MTX", MGMT_PHY_LE_2M_TX },
> > +       { "LE2MRX", MGMT_PHY_LE_2M_RX },
> > +       { "LECODEDTX", MGMT_PHY_LE_CODED_TX },
> > +       { "LECODEDRX", MGMT_PHY_LE_CODED_RX },
> > +};
> > +
> > +static void parse_default_le_phys(GKeyFile *config)
> > +{
> > +       char *str = NULL;
> > +       char **tokens;
> > +       uint32_t phys = 0;
> > +       bool valid = false;
> > +       int i;
> > +
> > +       if (!parse_config_string(config, "LE", "DefaultPHYs", &str))
> > +               return;
> > +
> > +       tokens = g_strsplit_set(str, ", \t", -1);
> > +
> > +       for (i = 0; tokens[i]; i++) {
> > +               const char *token = tokens[i];
> > +               size_t j;
> > +
> > +               if (!token[0])
> > +                       continue;
> > +
> > +               for (j = 0; j < ARRAY_SIZE(le_phy_configs); j++) {
> > +                       if (strcasecmp(le_phy_configs[j].name, token) != 0)
> > +                               continue;
> > +
> > +                       phys |= le_phy_configs[j].bit;
> > +                       valid = true;
> > +                       break;
> > +               }
> > +
> > +               if (j == ARRAY_SIZE(le_phy_configs))
> > +                       warn("Invalid DefaultPHYs token: %s", token);
> > +       }
> > +
> > +       if (valid) {
> > +               btd_opts.default_le_phys = phys;
> > +               btd_opts.default_le_phys_configured = true;
> > +       }
> > +
> > +       g_strfreev(tokens);
> > +       g_free(str);
> > +}
> > +
> >  static bool parse_config_hex(GKeyFile *config, char *group,
> >                                         const char *key, uint32_t *val)
> >  {
> > diff --git a/src/main.conf b/src/main.conf
> > index 5846ef92d..ed955897e 100644
> > --- a/src/main.conf
> > +++ b/src/main.conf
> > @@ -247,6 +247,14 @@
> >  # Default: 500
> >  #AdvMonNoFilterScanDuration=
> >
> > +# Configure the controller's default LE PHY policy used for scanning and
> > +# connection establishment. Only configurable LE PHYs are changed; mandatory
> > +# PHYs remain selected automatically.
> > +# Possible values: comma or space separated list of LE1MTX, LE1MRX, LE2MTX,
> > +# LE2MRX, LECODEDTX, LECODEDRX.
> > +# Example: keep LE on 1M only.
> > +#DefaultPHYs = LE1MTX LE1MRX
> > +
> >  # Enable/Disable Advertisement Monitor interleave scan for power saving.
> >  # 0: disable
> >  # 1: enable
> > --
> > 2.43.0
> >
> >
>
>
> --
> Luiz Augusto von Dentz

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

end of thread, other threads:[~2026-05-26 18:58 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-24 22:14 [PATCH BlueZ 0/1] Add configurable default LE PHY policy Tarjei Bitustøyl
2026-05-24 22:14 ` [PATCH BlueZ 1/1] adapter: Add configurable default LE PHYs Tarjei Bitustøyl
2026-05-24 23:07   ` Add configurable default LE PHY policy bluez.test.bot
2026-05-26 14:27   ` [PATCH BlueZ 1/1] adapter: Add configurable default LE PHYs Luiz Augusto von Dentz
2026-05-26 18:58     ` Tarjei Bitustøyl
2026-05-25  6:50 ` [PATCH BlueZ v2 0/1] Add configurable default LE PHY policy Tarjei Bitustøyl
2026-05-25  6:50   ` [PATCH BlueZ v2 1/1] adapter: Add configurable default LE PHYs Tarjei Bitustøyl
2026-05-25 11:04     ` Add configurable default LE PHY policy bluez.test.bot
2026-05-25 11:37 ` [PATCH BlueZ v3 0/1] " Tarjei Bitustøyl
2026-05-25 11:37   ` [PATCH BlueZ v3 1/1] adapter: Add configurable default LE PHYs Tarjei Bitustøyl
2026-05-25 14:33     ` Add configurable default LE PHY policy bluez.test.bot
2026-05-25 14:50 ` [PATCH BlueZ v4 0/1] " Tarjei Bitustøyl
2026-05-25 14:50   ` [PATCH BlueZ v4 1/1] adapter: Add configurable default LE PHYs Tarjei Bitustøyl
2026-05-25 16:55     ` Add configurable default LE PHY policy 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