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
next prev parent 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