Linux bluetooth development
 help / color / mirror / Atom feed
From: "Frédéric Danis" <frederic.danis@collabora.com>
To: linux-bluetooth@vger.kernel.org
Subject: [PATCH BlueZ 1/2] btio: add BT_IO_OPT_FORCE_ACTIVE support for L2CAP sockets
Date: Wed, 26 Aug 2026 18:41:05 +0200	[thread overview]
Message-ID: <20260826164106.293951-2-frederic.danis@collabora.com> (raw)
In-Reply-To: <20260826164106.293951-1-frederic.danis@collabora.com>

Introduce BT_IO_OPT_FORCE_ACTIVE in btio and plumb it through option
parsing and L2CAP setup.

When set, btio now programs BT_POWER on the underlying socket, allowing
callers to explicitly control force-active behavior.
---
 btio/btio.c | 35 +++++++++++++++++++++++++++++++----
 btio/btio.h |  1 +
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/btio/btio.c b/btio/btio.c
index 4c69d6035..016035dff 100644
--- a/btio/btio.c
+++ b/btio/btio.c
@@ -68,6 +68,7 @@ struct set_opts {
 	int central;
 	uint8_t mode;
 	int flushable;
+	int force_active;
 	uint32_t priority;
 	uint16_t voice;
 	struct bt_iso_qos qos;
@@ -601,6 +602,17 @@ static int l2cap_set_flushable(int sock, gboolean flushable)
 	return 0;
 }
 
+static int l2cap_set_bt_power(int sock, int force_active)
+{
+	struct bt_power pwr = {0};
+
+	pwr.force_active = force_active;
+	if (setsockopt(sock, SOL_BLUETOOTH, BT_POWER, &pwr, sizeof(pwr)) < 0)
+		return -errno;
+
+	return 0;
+}
+
 static int set_priority(int sock, uint32_t prio)
 {
 	if (setsockopt(sock, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio)) < 0)
@@ -696,8 +708,8 @@ static gboolean set_le_mode(int sock, uint8_t mode, GError **err)
 
 static gboolean l2cap_set(int sock, uint8_t src_type, int sec_level,
 				int imtu, uint16_t omtu, uint8_t mode,
-				int central, int flushable, uint32_t priority,
-				GError **err)
+				int central, int flushable, int force_active,
+				uint32_t priority, GError **err)
 {
 	if (imtu != -1 || omtu || mode) {
 		gboolean ret = FALSE;
@@ -736,6 +748,11 @@ static gboolean l2cap_set(int sock, uint8_t src_type, int sec_level,
 		return FALSE;
 	}
 
+	if (force_active >= 0 && l2cap_set_bt_power(sock, force_active) < 0) {
+		ERROR_FAILED(err, "l2cap_set_bt_power", errno);
+		return FALSE;
+	}
+
 	if (priority > 0 && set_priority(sock, priority) < 0) {
 		ERROR_FAILED(err, "set_priority", errno);
 		return FALSE;
@@ -968,6 +985,7 @@ static gboolean parse_set_opts(struct set_opts *opts, GError **err,
 	opts->central = -1;
 	opts->mode = L2CAP_MODE_BASIC;
 	opts->flushable = -1;
+	opts->force_active = -1;
 	opts->priority = 0;
 	opts->src_type = BDADDR_BREDR;
 	opts->dst_type = BDADDR_BREDR;
@@ -1043,6 +1061,9 @@ static gboolean parse_set_opts(struct set_opts *opts, GError **err,
 		case BT_IO_OPT_FLUSHABLE:
 			opts->flushable = va_arg(args, gboolean);
 			break;
+		case BT_IO_OPT_FORCE_ACTIVE:
+			opts->force_active = va_arg(args, int);
+			break;
 		case BT_IO_OPT_PRIORITY:
 			opts->priority = va_arg(args, int);
 			break;
@@ -1387,6 +1408,7 @@ parse_opts:
 		case BT_IO_OPT_SOURCE_CHANNEL:
 		case BT_IO_OPT_DEST_CHANNEL:
 		case BT_IO_OPT_MTU:
+		case BT_IO_OPT_FORCE_ACTIVE:
 		case BT_IO_OPT_VOICE:
 		case BT_IO_OPT_QOS:
 		case BT_IO_OPT_BASE:
@@ -1544,6 +1566,7 @@ static gboolean rfcomm_get(int sock, GError **err, BtIOOption opt1,
 		case BT_IO_OPT_IMTU:
 		case BT_IO_OPT_MODE:
 		case BT_IO_OPT_FLUSHABLE:
+		case BT_IO_OPT_FORCE_ACTIVE:
 		case BT_IO_OPT_PRIORITY:
 		case BT_IO_OPT_VOICE:
 		case BT_IO_OPT_QOS:
@@ -1658,6 +1681,7 @@ static gboolean sco_get(int sock, GError **err, BtIOOption opt1, va_list args)
 		case BT_IO_OPT_CENTRAL:
 		case BT_IO_OPT_MODE:
 		case BT_IO_OPT_FLUSHABLE:
+		case BT_IO_OPT_FORCE_ACTIVE:
 		case BT_IO_OPT_PRIORITY:
 		case BT_IO_OPT_VOICE:
 		case BT_IO_OPT_QOS:
@@ -1795,6 +1819,7 @@ static gboolean iso_get(int sock, GError **err, BtIOOption opt1, va_list args)
 		case BT_IO_OPT_CENTRAL:
 		case BT_IO_OPT_MODE:
 		case BT_IO_OPT_FLUSHABLE:
+		case BT_IO_OPT_FORCE_ACTIVE:
 		case BT_IO_OPT_PRIORITY:
 		case BT_IO_OPT_VOICE:
 		case BT_IO_OPT_ISO_BC_NUM_BIS:
@@ -1963,7 +1988,8 @@ gboolean bt_io_set(GIOChannel *io, GError **err, BtIOOption opt1, ...)
 	case BT_IO_L2CAP:
 		return l2cap_set(sock, opts.src_type, opts.sec_level, opts.imtu,
 					opts.omtu, opts.mode, opts.central,
-					opts.flushable, opts.priority, err);
+					opts.flushable, opts.force_active,
+					opts.priority, err);
 	case BT_IO_RFCOMM:
 		return rfcomm_set(sock, opts.sec_level, opts.central, err);
 	case BT_IO_SCO:
@@ -2014,7 +2040,8 @@ static GIOChannel *create_io(gboolean server, struct set_opts *opts,
 			goto failed;
 		if (!l2cap_set(sock, opts->src_type, opts->sec_level,
 				opts->imtu, opts->omtu, opts->mode,
-				opts->central, opts->flushable, opts->priority,
+				opts->central, opts->flushable,
+				opts->force_active, opts->priority,
 				err))
 			goto failed;
 		break;
diff --git a/btio/btio.h b/btio/btio.h
index 3e69092b1..f088c3cd4 100644
--- a/btio/btio.h
+++ b/btio/btio.h
@@ -42,6 +42,7 @@ typedef enum {
 	BT_IO_OPT_CLASS,
 	BT_IO_OPT_MODE,
 	BT_IO_OPT_FLUSHABLE,
+	BT_IO_OPT_FORCE_ACTIVE,
 	BT_IO_OPT_PRIORITY,
 	BT_IO_OPT_VOICE,
 	BT_IO_OPT_PHY,
-- 
2.43.0


  reply	other threads:[~2026-08-26 16:41 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-26 16:41 [PATCH BlueZ 0/2] input: avoid NSP1 disconnects caused by Sniff/Exit Sniff churn Frédéric Danis
2026-08-26 16:41 ` Frédéric Danis [this message]
2026-08-26 19:13   ` bluez.test.bot
2026-08-26 16:41 ` [PATCH BlueZ 2/2] profiles/input: disable force-active for Nintendo Switch Pro v1 Frédéric Danis
2026-08-26 16:58 ` [PATCH BlueZ 0/2] input: avoid NSP1 disconnects caused by Sniff/Exit Sniff churn Luiz Augusto von Dentz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260826164106.293951-2-frederic.danis@collabora.com \
    --to=frederic.danis@collabora.com \
    --cc=linux-bluetooth@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox