From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
To: linux-bluetooth@vger.kernel.org
Subject: [PATCH BlueZ v1 5/6] client: connect a device that is already paired
Date: Mon, 21 Sep 2026 17:01:22 -0400 [thread overview]
Message-ID: <20260921210123.3690449-6-luiz.dentz@gmail.com> (raw)
In-Reply-To: <20260921210123.3690449-1-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Pairing a device that is already paired is rejected by the daemon with
AlreadyExists, which is of no use to the user: the bond asked for is
already there, and what pairing it anew takes is removing it first.
Connect it instead, telling what happened, so pairing a device is a way
of getting to it whether it is known already or not.
The documentation already described this behaviour, though as removing
the pairing first, which is not what happened either.
Assisted-by: opencode:claude-opus-5
---
client/main.c | 40 ++++++++++++++++++++++++++++++++++++++++
doc/bluetoothctl.rst | 6 ++++--
2 files changed, 44 insertions(+), 2 deletions(-)
diff --git a/client/main.c b/client/main.c
index 3fef1e9a5179..314aead8c9bb 100644
--- a/client/main.c
+++ b/client/main.c
@@ -2068,6 +2068,9 @@ static void cmd_info(int argc, char *argv[])
return bt_shell_noninteractive_quit(EXIT_SUCCESS);
}
+static const char *proxy_address(GDBusProxy *proxy);
+static void connect_device(GDBusProxy *proxy);
+
static void pair_reply(DBusMessage *message, void *user_data)
{
DBusError error;
@@ -2101,11 +2104,31 @@ static const char *proxy_address(GDBusProxy *proxy)
static void cmd_pair(int argc, char *argv[])
{
GDBusProxy *proxy;
+ DBusMessageIter iter;
+ dbus_bool_t paired;
proxy = find_device(argc, argv);
if (!proxy)
return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ /* Pairing a device that is already paired is rejected with
+ * AlreadyExists, so connect it instead: the bond is there, which
+ * is what pairing it again would be for, and removing it first is
+ * what actually pairs it anew.
+ */
+ if (g_dbus_proxy_get_property(proxy, "Paired", &iter)) {
+ dbus_message_iter_get_basic(&iter, &paired);
+
+ if (paired) {
+ bt_shell_printf("Device %s is already paired, "
+ "connecting instead, remove it first "
+ "to pair it again\n",
+ proxy_address(proxy));
+ connect_device(proxy);
+ return;
+ }
+ }
+
if (g_dbus_proxy_method_call(proxy, "Pair", NULL, pair_reply,
NULL, NULL) == FALSE) {
bt_shell_printf("Failed to pair\n");
@@ -2365,6 +2388,23 @@ static void connect_reply(DBusMessage *message, void *user_data)
return bt_shell_noninteractive_quit(EXIT_SUCCESS);
}
+static void connect_device(GDBusProxy *proxy)
+{
+ struct connection_data *data;
+
+ data = new0(struct connection_data, 1);
+ data->proxy = proxy;
+
+ if (g_dbus_proxy_method_call(proxy, "Connect", connection_setup,
+ connect_reply, data, NULL) == FALSE) {
+ bt_shell_printf("Failed to connect\n");
+ g_free(data);
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
+ bt_shell_printf("Attempting to connect to %s\n", proxy_address(proxy));
+}
+
static void prompt_scan_connect(const char *input, void *user_data)
{
char *address = user_data;
diff --git a/doc/bluetoothctl.rst b/doc/bluetoothctl.rst
index cc58e1f5be19..23f92a512911 100644
--- a/doc/bluetoothctl.rst
+++ b/doc/bluetoothctl.rst
@@ -207,7 +207,8 @@ pair
Pair with device.
This will pair with a device and then trust and connect to it. If the device is
-already paired this will first remove the pairing.
+already paired this will connect to it instead, as the bond is already in
+place: use **remove** first to pair it again.
The command can either be used while the controller is in the connected or not
connected state.
@@ -221,7 +222,8 @@ Before pairing the agent must be selected to choose the authentication
mechanism.
:Usage: **> pair [dev]**
-:Uses: **org.bluez.Device(5)** method **Pair**
+:Uses: **org.bluez.Device(5)** method **Pair**, or **Connect** if the device is
+ already paired
:[dev]: Device MAC address (XX:XX:XX:XX:XX:XX) (optional, uses current device if omitted)
:Example Pair with device using MAC address:
| **> pair 00:11:22:33:44:55**
--
2.55.0
next prev parent reply other threads:[~2026-09-21 21:02 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-21 21:01 [PATCH BlueZ v1 0/6] Add true wireless BAP broadcast tests Luiz Augusto von Dentz
2026-09-21 21:01 ` [PATCH BlueZ v1 1/6] doc: describe the true wireless broadcast test cases Luiz Augusto von Dentz
2026-09-21 23:47 ` Add true wireless BAP broadcast tests bluez.test.bot
2026-09-21 21:01 ` [PATCH BlueZ v1 2/6] doc: describe the true wireless broadcast assistant test case Luiz Augusto von Dentz
2026-09-21 21:01 ` [PATCH BlueZ v1 3/6] test: functional: add the true wireless broadcast tests Luiz Augusto von Dentz
2026-09-21 21:01 ` [PATCH BlueZ v1 4/6] bass: keep the push target per MediaAssistant object Luiz Augusto von Dentz
2026-09-21 21:01 ` Luiz Augusto von Dentz [this message]
2026-09-21 21:01 ` [PATCH BlueZ v1 6/6] test: functional: add the true wireless broadcast assistant test Luiz Augusto von Dentz
2026-09-22 15:00 ` [PATCH BlueZ v1 0/6] Add true wireless BAP broadcast tests patchwork-bot+bluetooth
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=20260921210123.3690449-6-luiz.dentz@gmail.com \
--to=luiz.dentz@gmail.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