public inbox for linux-bluetooth@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] adapter: add DisableDiscoveryOnConnect option for combo chip coexistence
@ 2026-04-18 13:27 StefanCondorache
  2026-04-18 14:06 ` bluez.test.bot
  2026-04-19  2:28 ` [PATCH] " Luiz Augusto von Dentz
  0 siblings, 2 replies; 4+ messages in thread
From: StefanCondorache @ 2026-04-18 13:27 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: luiz.dentz, Bastien Nocera, StefanCondorache

From: Bastien Nocera <hadess@hadess.net>

On systems with combo chips (shared Wi-Fi/Bluetooth antenna), background
LE scanning for auto-connect devices competes with active connections,
causing audio stuttering and Wi-Fi packet loss due to antenna
multiplexing via Packet Traffic Arbitration (PTA).

Add a DisableDiscoveryOnConnect boolean option to the [General] section
of main.conf. When enabled and an active connection exists, the option
suppresses adding devices to the kernel auto-connect list in
adapter_auto_connect_add() on kernels supporting KERNEL_CONN_CONTROL,
and gates trigger_passive_scanning() on older kernels.

The option defaults to false to preserve existing behavior.

Signed-off-by: StefanCondorache <condorachest@gmail.com>
---
 client/mgmt.c             |  4 ----
 mesh/prov-initiator.c     |  3 +--
 src/adapter.c             | 24 ++++++++++++++++++++++++
 src/btd.h                 |  2 ++
 src/device.c              |  4 ----
 src/gatt-database.c       |  4 ----
 src/main.c                |  4 ++++
 src/main.conf             |  6 ++++++
 src/shared/gatt-client.c  |  8 --------
 src/shared/gatt-helpers.c |  4 ----
 src/shared/ringbuf.c      |  4 ----
 src/shared/uhid.c         |  4 ----
 src/shared/vcp.h          |  8 --------
 tools/advtest.c           |  3 ---
 tools/btgatt-server.c     |  4 ----
 tools/hcitool.c           |  4 ----
 tools/parser/rfcomm.h     |  2 --
 17 files changed, 37 insertions(+), 55 deletions(-)

diff --git a/client/mgmt.c b/client/mgmt.c
index 71fcd21ff..50558a313 100644
--- a/client/mgmt.c
+++ b/client/mgmt.c
@@ -67,10 +67,6 @@ static struct {
 
 static int pending_index = 0;
 
-#ifndef MIN
-#define MIN(x, y) ((x) < (y) ? (x) : (y))
-#endif
-
 static void mgmt_menu_pre_run(const struct bt_shell_menu *menu);
 
 #define PROMPT_ON	COLOR_BLUE "[mgmt]" COLOR_OFF "> "
diff --git a/mesh/prov-initiator.c b/mesh/prov-initiator.c
index d46081c7a..29c0be713 100644
--- a/mesh/prov-initiator.c
+++ b/mesh/prov-initiator.c
@@ -18,6 +18,7 @@
 
 #include "src/shared/ad.h"
 #include "src/shared/ecc.h"
+#include "src/shared/util.h"
 
 #include "mesh/mesh-defs.h"
 #include "mesh/util.h"
@@ -34,8 +35,6 @@
 #include "mesh/agent.h"
 #include "mesh/error.h"
 
-#define MIN(x, y) ((x) < (y) ? (x) : (y))
-
 /* Quick size sanity check */
 static const uint16_t expected_pdu_size[] = {
 	2,	/* PROV_INVITE */
diff --git a/src/adapter.c b/src/adapter.c
index 6df66b3e0..4a18adfe0 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1594,6 +1594,18 @@ static void trigger_passive_scanning(struct btd_adapter *adapter)
 	if (!adapter->connect_list)
 		return;
 
+	/*
+	 * If the user has enabled DisableDiscoveryOnConnect, suppress
+	 * passive scanning whenever there is at least one active connection.
+	 * This prevents antenna multiplexing conflicts on combo chips where
+	 * Wi-Fi and Bluetooth share the same 2.4 GHz radio, which causes
+	 * audio drops and Wi-Fi packet loss during background scans.
+	 */
+	if (btd_opts.disable_discovery_on_connect && adapter->connections) {
+		DBG("suppress passive scan: active connection present");
+		return;
+	}
+
 	adapter->passive_scan_timeout = timeout_add_seconds(CONN_SCAN_TIMEOUT,
 					passive_scanning_timeout, adapter,
 					NULL);
@@ -5717,6 +5729,18 @@ void adapter_auto_connect_add(struct btd_adapter *adapter,
 		return;
 	}
 
+	/*
+	 * If DisableDiscoveryOnConnect is enabled, suppress adding devices
+	 * to the kernel auto-connect list while an active connection exists.
+	 * On combo chips (shared Wi-Fi/Bluetooth antenna), the kernel's
+	 * background scanning for auto-connect devices competes with active
+	 * connections, causing audio drops and Wi-Fi packet loss.
+	 */
+	if (btd_opts.disable_discovery_on_connect && adapter->connections) {
+		DBG("suppress kernel auto-connect: active connection present");
+		return;
+	}
+
 	bdaddr = device_get_address(device);
 	bdaddr_type = btd_device_get_bdaddr_type(device);
 
diff --git a/src/btd.h b/src/btd.h
index c84a600d1..07c4d85ba 100644
--- a/src/btd.h
+++ b/src/btd.h
@@ -144,6 +144,8 @@ struct btd_opts {
 	bool		experimental;
 	bool		testing;
 	bool		filter_discoverable;
+	bool		disable_discovery_on_connect;
+
 	struct queue	*kernel;
 
 	uint16_t	did_source;
diff --git a/src/device.c b/src/device.c
index 470340c2d..28515054c 100644
--- a/src/device.c
+++ b/src/device.c
@@ -72,10 +72,6 @@
 #define DISCOVERY_TIMER		1
 #define INVALID_FLAGS		0xff
 
-#ifndef MIN
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#endif
-
 #define RSSI_THRESHOLD		8
 #define AUTH_FAILURES_THRESHOLD	3
 
diff --git a/src/gatt-database.c b/src/gatt-database.c
index 39e6a2593..680a52952 100644
--- a/src/gatt-database.c
+++ b/src/gatt-database.c
@@ -54,10 +54,6 @@
 #define UUID_GATT	0x1801
 #define UUID_DIS	0x180a
 
-#ifndef MIN
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#endif
-
 struct gatt_record {
 	struct btd_gatt_database *database;
 	uint32_t handle;
diff --git a/src/main.c b/src/main.c
index 818f7c06e..d7ddf5643 100644
--- a/src/main.c
+++ b/src/main.c
@@ -92,6 +92,7 @@ static const char *supported_options[] = {
 	"KernelExperimental",
 	"RemoteNameRequestRetryDelay",
 	"FilterDiscoverable",
+	"DisableDiscoveryOnConnect",
 	NULL
 };
 
@@ -1072,6 +1073,8 @@ static void parse_general(GKeyFile *config)
 					0, UINT32_MAX);
 	parse_config_bool(config, "General", "FilterDiscoverable",
 						&btd_opts.filter_discoverable);
+	parse_config_bool(config, "General", "DisableDiscoveryOnConnect",
+					&btd_opts.disable_discovery_on_connect);
 }
 
 static void parse_gatt_cache(GKeyFile *config)
@@ -1283,6 +1286,7 @@ static void init_defaults(void)
 	btd_opts.name_request_retry_delay = DEFAULT_NAME_REQUEST_RETRY_DELAY;
 	btd_opts.secure_conn = SC_ON;
 	btd_opts.filter_discoverable = true;
+	btd_opts.disable_discovery_on_connect = false;
 
 	btd_opts.defaults.num_entries = 0;
 	btd_opts.defaults.br.page_scan_type = 0xFFFF;
diff --git a/src/main.conf b/src/main.conf
index d31dd1b8f..22507c465 100644
--- a/src/main.conf
+++ b/src/main.conf
@@ -157,6 +157,12 @@
 # some stacks) or when testing bad/unintended behavior.
 #FilterDiscoverable = true
 
+# Disables background LE passive scanning when an active connection is
+# established. Recommended for combo chips (shared Wi-Fi/Bluetooth antenna)
+# to prevent audio stuttering and packet loss caused by antenna multiplexing.
+# Defaults to false.
+#DisableDiscoveryOnConnect = false
+
 [BR]
 # The following values are used to load default adapter parameters for BR/EDR.
 # BlueZ loads the values into the kernel before the adapter is powered if the
diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index df1541b88..a6abe8ac2 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -25,14 +25,6 @@
 #include <limits.h>
 #include <sys/uio.h>
 
-#ifndef MAX
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-#endif
-
-#ifndef MIN
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#endif
-
 #define UUID_BYTES (BT_GATT_UUID_SIZE * sizeof(uint8_t))
 
 #define GATT_SVC_UUID	0x1801
diff --git a/src/shared/gatt-helpers.c b/src/shared/gatt-helpers.c
index 8dee34a9e..b3d5d8f1a 100644
--- a/src/shared/gatt-helpers.c
+++ b/src/shared/gatt-helpers.c
@@ -20,10 +20,6 @@
 #include "src/shared/gatt-helpers.h"
 #include "src/shared/util.h"
 
-#ifndef MIN
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#endif
-
 struct bt_gatt_result {
 	uint8_t opcode;
 	void *pdu;
diff --git a/src/shared/ringbuf.c b/src/shared/ringbuf.c
index 957d355f9..7460dd483 100644
--- a/src/shared/ringbuf.c
+++ b/src/shared/ringbuf.c
@@ -21,10 +21,6 @@
 #include "src/shared/util.h"
 #include "src/shared/ringbuf.h"
 
-#ifndef MIN
-#define MIN(x,y) ((x)<(y)?(x):(y))
-#endif
-
 struct ringbuf {
 	void *buffer;
 	size_t size;
diff --git a/src/shared/uhid.c b/src/shared/uhid.c
index 207afa55e..919618a71 100644
--- a/src/shared/uhid.c
+++ b/src/shared/uhid.c
@@ -26,10 +26,6 @@
 
 #define UHID_DEVICE_FILE "/dev/uhid"
 
-#ifndef MIN
-#define MIN(x, y) ((x) < (y) ? (x) : (y))
-#endif
-
 struct uhid_replay {
 	bool active;
 	struct queue *out;
diff --git a/src/shared/vcp.h b/src/shared/vcp.h
index 89efaa09c..e031beafd 100644
--- a/src/shared/vcp.h
+++ b/src/shared/vcp.h
@@ -23,14 +23,6 @@
 #define BT_VCP_UNMUTE			0x05
 #define BT_VCP_MUTE			0x06
 
-#ifndef MAX
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-#endif
-
-#ifndef MIN
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#endif
-
 struct bt_vcp;
 
 typedef void (*bt_vcp_destroy_func_t)(void *user_data);
diff --git a/tools/advtest.c b/tools/advtest.c
index 7e744dca8..a67a03c43 100644
--- a/tools/advtest.c
+++ b/tools/advtest.c
@@ -39,9 +39,6 @@
 			"\xe1\x23\x99\xc1\xca\x9a\xc3\x31"
 #define SCAN_IRK	"\xfa\x73\x09\x11\x3f\x03\x37\x0f" \
 			"\xf4\xf9\x93\x1e\xf9\xa3\x63\xa6"
-#ifndef MIN
-#define MIN(x, y) ((x) < (y) ? (x) : (y))
-#endif
 
 static struct mgmt *mgmt;
 static uint16_t index1 = MGMT_INDEX_NONE;
diff --git a/tools/btgatt-server.c b/tools/btgatt-server.c
index 449c34203..18e8b9542 100644
--- a/tools/btgatt-server.c
+++ b/tools/btgatt-server.c
@@ -48,10 +48,6 @@
 		print_prompt(); \
 	} while (0)
 
-#ifndef MIN
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#endif
-
 #define COLOR_OFF	"\x1B[0m"
 #define COLOR_RED	"\x1B[0;91m"
 #define COLOR_GREEN	"\x1B[0;92m"
diff --git a/tools/hcitool.c b/tools/hcitool.c
index 834f83e7a..1903d859b 100644
--- a/tools/hcitool.c
+++ b/tools/hcitool.c
@@ -34,10 +34,6 @@
 
 #include "src/oui.h"
 
-#ifndef MIN
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#endif
-
 /* Unofficial value, might still change */
 #define LE_LINK		0x80
 
diff --git a/tools/parser/rfcomm.h b/tools/parser/rfcomm.h
index b1cb1741c..d1b093a90 100644
--- a/tools/parser/rfcomm.h
+++ b/tools/parser/rfcomm.h
@@ -33,8 +33,6 @@
 /* Returns the P/F-bit */
 #define GET_PF(ctr) (((ctr) >> 4) & 0x1)
 
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-
 /* Endian-swapping macros for structs */
 #define swap_long_frame(x) ((x)->h.length.val = le16_to_cpu((x)->h.length.val))
 #define swap_mcc_long_frame(x) (swap_long_frame(x))
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread
* [PATCH] adapter: add DisableDiscoveryOnConnect option for combo chip coexistence
@ 2026-04-18 14:11 StefanCondorache
  0 siblings, 0 replies; 4+ messages in thread
From: StefanCondorache @ 2026-04-18 14:11 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: luiz.dentz, StefanCondorache

On systems with combo chips (shared Wi-Fi/Bluetooth antenna), background
LE scanning for auto-connect devices competes with active connections,
causing audio stuttering and Wi-Fi packet loss due to antenna
multiplexing via Packet Traffic Arbitration (PTA).

Add a DisableDiscoveryOnConnect boolean option to the [General] section
of main.conf. When enabled and an active connection exists, the option
suppresses adding devices to the kernel auto-connect list in
adapter_auto_connect_add() on kernels supporting KERNEL_CONN_CONTROL,
and gates trigger_passive_scanning() on older kernels.

The option defaults to false to preserve existing behavior.

Signed-off-by: StefanCondorache <condorachest@gmail.com>
---
 src/adapter.c | 24 ++++++++++++++++++++++++
 src/btd.h     |  2 ++
 src/main.c    |  4 ++++
 src/main.conf |  6 ++++++
 4 files changed, 36 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index 6df66b3e0..4a18adfe0 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1594,6 +1594,18 @@ static void trigger_passive_scanning(struct btd_adapter *adapter)
 	if (!adapter->connect_list)
 		return;
 
+	/*
+	 * If the user has enabled DisableDiscoveryOnConnect, suppress
+	 * passive scanning whenever there is at least one active connection.
+	 * This prevents antenna multiplexing conflicts on combo chips where
+	 * Wi-Fi and Bluetooth share the same 2.4 GHz radio, which causes
+	 * audio drops and Wi-Fi packet loss during background scans.
+	 */
+	if (btd_opts.disable_discovery_on_connect && adapter->connections) {
+		DBG("suppress passive scan: active connection present");
+		return;
+	}
+
 	adapter->passive_scan_timeout = timeout_add_seconds(CONN_SCAN_TIMEOUT,
 					passive_scanning_timeout, adapter,
 					NULL);
@@ -5717,6 +5729,18 @@ void adapter_auto_connect_add(struct btd_adapter *adapter,
 		return;
 	}
 
+	/*
+	 * If DisableDiscoveryOnConnect is enabled, suppress adding devices
+	 * to the kernel auto-connect list while an active connection exists.
+	 * On combo chips (shared Wi-Fi/Bluetooth antenna), the kernel's
+	 * background scanning for auto-connect devices competes with active
+	 * connections, causing audio drops and Wi-Fi packet loss.
+	 */
+	if (btd_opts.disable_discovery_on_connect && adapter->connections) {
+		DBG("suppress kernel auto-connect: active connection present");
+		return;
+	}
+
 	bdaddr = device_get_address(device);
 	bdaddr_type = btd_device_get_bdaddr_type(device);
 
diff --git a/src/btd.h b/src/btd.h
index c84a600d1..07c4d85ba 100644
--- a/src/btd.h
+++ b/src/btd.h
@@ -144,6 +144,8 @@ struct btd_opts {
 	bool		experimental;
 	bool		testing;
 	bool		filter_discoverable;
+	bool		disable_discovery_on_connect;
+
 	struct queue	*kernel;
 
 	uint16_t	did_source;
diff --git a/src/main.c b/src/main.c
index 818f7c06e..d7ddf5643 100644
--- a/src/main.c
+++ b/src/main.c
@@ -92,6 +92,7 @@ static const char *supported_options[] = {
 	"KernelExperimental",
 	"RemoteNameRequestRetryDelay",
 	"FilterDiscoverable",
+	"DisableDiscoveryOnConnect",
 	NULL
 };
 
@@ -1072,6 +1073,8 @@ static void parse_general(GKeyFile *config)
 					0, UINT32_MAX);
 	parse_config_bool(config, "General", "FilterDiscoverable",
 						&btd_opts.filter_discoverable);
+	parse_config_bool(config, "General", "DisableDiscoveryOnConnect",
+					&btd_opts.disable_discovery_on_connect);
 }
 
 static void parse_gatt_cache(GKeyFile *config)
@@ -1283,6 +1286,7 @@ static void init_defaults(void)
 	btd_opts.name_request_retry_delay = DEFAULT_NAME_REQUEST_RETRY_DELAY;
 	btd_opts.secure_conn = SC_ON;
 	btd_opts.filter_discoverable = true;
+	btd_opts.disable_discovery_on_connect = false;
 
 	btd_opts.defaults.num_entries = 0;
 	btd_opts.defaults.br.page_scan_type = 0xFFFF;
diff --git a/src/main.conf b/src/main.conf
index d31dd1b8f..22507c465 100644
--- a/src/main.conf
+++ b/src/main.conf
@@ -157,6 +157,12 @@
 # some stacks) or when testing bad/unintended behavior.
 #FilterDiscoverable = true
 
+# Disables background LE passive scanning when an active connection is
+# established. Recommended for combo chips (shared Wi-Fi/Bluetooth antenna)
+# to prevent audio stuttering and packet loss caused by antenna multiplexing.
+# Defaults to false.
+#DisableDiscoveryOnConnect = false
+
 [BR]
 # The following values are used to load default adapter parameters for BR/EDR.
 # BlueZ loads the values into the kernel before the adapter is powered if the
-- 
2.53.0


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

end of thread, other threads:[~2026-04-19  2:28 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-18 13:27 [PATCH] adapter: add DisableDiscoveryOnConnect option for combo chip coexistence StefanCondorache
2026-04-18 14:06 ` bluez.test.bot
2026-04-19  2:28 ` [PATCH] " Luiz Augusto von Dentz
  -- strict thread matches above, loose matches on Subject: below --
2026-04-18 14:11 StefanCondorache

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox