Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH BlueZ v2 0/3] Add Role property to org.bluez.Bearer.LE1
@ 2026-10-08 17:29 Kevin Dewald
  2026-10-08 17:29 ` [PATCH BlueZ v2 1/3] org.bluez.Bearer: Add Role property Kevin Dewald
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Kevin Dewald @ 2026-10-08 17:29 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Luiz Augusto von Dentz, Kevin Dewald

Applications acting as a peripheral, or in both roles, cannot tell
whether a connected device is a central that connected to the adapter
or a peripheral the adapter connected to. When several applications
share the adapter, a device object can appear because of any of them,
so the order of events does not answer it either.

bluetoothd already tracks this per bearer from the Device Connected
event. This series exposes it as a Role property on
org.bluez.Bearer.LE1, "central" or "peripheral", present only while
the device is connected over LE, and prints it as LE.Role in
bluetoothctl info. The documentation states that it is the link layer
role and says nothing about GATT client and server roles.

Like the rest of the bearer interfaces, the property is experimental,
so applications only see it when bluetoothd runs with -E, which few
systems do. Is there a plan to promote the bearer interfaces, or some
of their properties, to stable? I would be glad to help with whatever
that needs.

Tested with two btvirt controllers, where the advertising side reports
the other as "central" and the connecting side reports it as
"peripheral", and with a real adapter connecting to an nRF52840. The
property goes away when the connection does.

Changes in v2:
- Move the property from org.bluez.Device1 to org.bluez.Bearer.LE1, so
  it is clearly per connection (Luiz)
- State in the documentation that it says nothing about GATT roles
  (Luiz)

Kevin Dewald (3):
  org.bluez.Bearer: Add Role property
  bearer: Add Role property
  client: Print LE.Role in info

 client/main.c               |  1 +
 doc/org.bluez.Bearer.LE.rst | 24 +++++++++++++++++++++
 src/bearer.c                | 42 +++++++++++++++++++++++++++++++++++++
 src/device.c                |  5 +++++
 src/device.h                |  1 +
 5 files changed, 73 insertions(+)

-- 
2.54.0 (Apple Git-157)


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

* [PATCH BlueZ v2 1/3] org.bluez.Bearer: Add Role property
  2026-10-08 17:29 [PATCH BlueZ v2 0/3] Add Role property to org.bluez.Bearer.LE1 Kevin Dewald
@ 2026-10-08 17:29 ` Kevin Dewald
  2026-10-08 22:35   ` Add Role property to org.bluez.Bearer.LE1 bluez.test.bot
  2026-10-08 17:29 ` [PATCH BlueZ v2 2/3] bearer: Add Role property Kevin Dewald
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Kevin Dewald @ 2026-10-08 17:29 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Luiz Augusto von Dentz, Kevin Dewald

This adds Role property to org.bluez.Bearer.LE1 which indicates whether
the remote device is the central or the peripheral of the current LE
connection, so applications can tell a central that connected to the
adapter from a peripheral the adapter connected to.

Assisted-by: Claude:claude-opus-5.5
---
 doc/org.bluez.Bearer.LE.rst | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/doc/org.bluez.Bearer.LE.rst b/doc/org.bluez.Bearer.LE.rst
index ec92a5ce5..dfd809739 100644
--- a/doc/org.bluez.Bearer.LE.rst
+++ b/doc/org.bluez.Bearer.LE.rst
@@ -153,3 +153,27 @@ The property is only present once the device has been discovered or connected
 over LE bearer.
 
 A PropertiesChanged signal indicate changes to this status.
+
+string Role [readonly, optional, experimental]
+``````````````````````````````````````````````
+
+Indicates the role of the remote device in the current connection on LE bearer.
+It is only present while the remote device is connected over LE bearer.
+
+It is the link layer role of the connection. It does not imply which side acts
+as GATT client or server, as GATT roles are independent of it and both may be
+used at the same time.
+
+Possible values:
+
+:"central":
+
+	The remote device initiated the connection, and the adapter is the
+	peripheral.
+
+:"peripheral":
+
+	The adapter initiated the connection, and the remote device is the
+	peripheral.
+
+A PropertiesChanged signal indicate changes to this status.
-- 
2.54.0 (Apple Git-157)


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

* [PATCH BlueZ v2 2/3] bearer: Add Role property
  2026-10-08 17:29 [PATCH BlueZ v2 0/3] Add Role property to org.bluez.Bearer.LE1 Kevin Dewald
  2026-10-08 17:29 ` [PATCH BlueZ v2 1/3] org.bluez.Bearer: Add Role property Kevin Dewald
@ 2026-10-08 17:29 ` Kevin Dewald
  2026-10-08 17:30 ` [PATCH BlueZ v2 3/3] client: Print LE.Role in info Kevin Dewald
  2026-10-08 19:10 ` [PATCH BlueZ v2 0/3] Add Role property to org.bluez.Bearer.LE1 Luiz Augusto von Dentz
  3 siblings, 0 replies; 8+ messages in thread
From: Kevin Dewald @ 2026-10-08 17:29 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Luiz Augusto von Dentz, Kevin Dewald

This implements Role property for the LE bearer using the initiator
flag of the Device Connected event, which the kernel sets when the
adapter created the connection as central, and emits PropertiesChanged
along with Connected.

Assisted-by: Claude:claude-opus-5.5
---
 src/bearer.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 src/device.c |  5 +++++
 src/device.h |  1 +
 3 files changed, 48 insertions(+)

diff --git a/src/bearer.c b/src/bearer.c
index f3b7a2337..25224dcc7 100644
--- a/src/bearer.c
+++ b/src/bearer.c
@@ -274,6 +274,34 @@ static gboolean bearer_connectable_exists(const GDBusPropertyTable *property,
 	return btd_device_bdaddr_type_seen(bearer->device, bearer->type);
 }
 
+static gboolean bearer_get_role(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct btd_bearer *bearer = data;
+	const char *role;
+
+	/* The initiator of an LE connection is always the central */
+	if (btd_device_bdaddr_type_initiator(bearer->device, bearer->type))
+		role = "peripheral";
+	else
+		role = "central";
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &role);
+
+	return TRUE;
+}
+
+static gboolean bearer_role_exists(const GDBusPropertyTable *property,
+								void *data)
+{
+	struct btd_bearer *bearer = data;
+
+	if (bearer->type == BDADDR_BREDR)
+		return FALSE;
+
+	return btd_device_bdaddr_type_connected(bearer->device, bearer->type);
+}
+
 static const GDBusSignalTable bearer_signals[] = {
 	{ GDBUS_SIGNAL("Disconnected",
 			GDBUS_ARGS({ "name", "s" }, { "message", "s" })) },
@@ -292,6 +320,8 @@ static const GDBusPropertyTable bearer_properties[] = {
 	{ "Connectable", "b", bearer_get_connectable, NULL,
 			bearer_connectable_exists,
 			G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "Role", "s", bearer_get_role, NULL, bearer_role_exists,
+			G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
 	{}
 };
 
@@ -416,6 +446,12 @@ void btd_bearer_connected(struct btd_bearer *bearer, int err)
 	g_dbus_emit_property_changed(btd_get_dbus_connection(), bearer->path,
 					bearer_interface(bearer->type),
 					"Connected");
+
+	if (!err && bearer->type != BDADDR_BREDR)
+		g_dbus_emit_property_changed(btd_get_dbus_connection(),
+					bearer->path,
+					bearer_interface(bearer->type),
+					"Role");
 }
 
 void btd_bearer_disconnected(struct btd_bearer *bearer, uint8_t reason)
@@ -444,6 +480,12 @@ void btd_bearer_disconnected(struct btd_bearer *bearer, uint8_t reason)
 					bearer_interface(bearer->type),
 					"Connected");
 
+	if (bearer->type != BDADDR_BREDR)
+		g_dbus_emit_property_changed(btd_get_dbus_connection(),
+					bearer->path,
+					bearer_interface(bearer->type),
+					"Role");
+
 	switch (reason) {
 	case MGMT_DEV_DISCONN_UNKNOWN:
 		name = "org.bluez.Reason.Unknown";
diff --git a/src/device.c b/src/device.c
index 1ab4e5342..4ccafd15a 100644
--- a/src/device.c
+++ b/src/device.c
@@ -3869,6 +3869,11 @@ bool btd_device_bdaddr_type_seen(struct btd_device *dev, uint8_t type)
 	return get_state(dev, type)->last_seen != 0;
 }
 
+bool btd_device_bdaddr_type_initiator(struct btd_device *dev, uint8_t type)
+{
+	return get_state(dev, type)->initiator;
+}
+
 static void clear_temporary_timer(struct btd_device *dev)
 {
 	if (dev->temporary_timer) {
diff --git a/src/device.h b/src/device.h
index 756540056..5ead73958 100644
--- a/src/device.h
+++ b/src/device.h
@@ -129,6 +129,7 @@ bool btd_device_bearer_is_connected(struct btd_device *dev);
 bool btd_device_bdaddr_type_connected(struct btd_device *dev, uint8_t type);
 bool btd_device_bdaddr_type_connectable(struct btd_device *dev, uint8_t type);
 bool btd_device_bdaddr_type_seen(struct btd_device *dev, uint8_t type);
+bool btd_device_bdaddr_type_initiator(struct btd_device *dev, uint8_t type);
 uint8_t btd_device_get_bdaddr_type(struct btd_device *dev);
 bool device_is_retrying(struct btd_device *device);
 void device_bonding_complete(struct btd_device *device, uint8_t bdaddr_type,
-- 
2.54.0 (Apple Git-157)


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

* [PATCH BlueZ v2 3/3] client: Print LE.Role in info
  2026-10-08 17:29 [PATCH BlueZ v2 0/3] Add Role property to org.bluez.Bearer.LE1 Kevin Dewald
  2026-10-08 17:29 ` [PATCH BlueZ v2 1/3] org.bluez.Bearer: Add Role property Kevin Dewald
  2026-10-08 17:29 ` [PATCH BlueZ v2 2/3] bearer: Add Role property Kevin Dewald
@ 2026-10-08 17:30 ` Kevin Dewald
  2026-10-08 19:10 ` [PATCH BlueZ v2 0/3] Add Role property to org.bluez.Bearer.LE1 Luiz Augusto von Dentz
  3 siblings, 0 replies; 8+ messages in thread
From: Kevin Dewald @ 2026-10-08 17:30 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Luiz Augusto von Dentz, Kevin Dewald

This prints the Role property of the LE bearer with the likes of info
command:

bluetoothctl> info <addr>
...
        LE.Connected: yes
        LE.Connectable: yes
        LE.Role: central

Assisted-by: Claude:claude-opus-5.5
---
 client/main.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/client/main.c b/client/main.c
index f5fdd7d12..d2d25b9f4 100644
--- a/client/main.c
+++ b/client/main.c
@@ -2097,6 +2097,7 @@ static void cmd_info(int argc, char *argv[])
 		print_property_with_label(bearer, "Connected", "LE.Connected");
 		print_property_with_label(bearer, "Connectable",
 							"LE.Connectable");
+		print_property_with_label(bearer, "Role", "LE.Role");
 	}
 
 	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
-- 
2.54.0 (Apple Git-157)


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

* Re: [PATCH BlueZ v2 0/3] Add Role property to org.bluez.Bearer.LE1
  2026-10-08 17:29 [PATCH BlueZ v2 0/3] Add Role property to org.bluez.Bearer.LE1 Kevin Dewald
                   ` (2 preceding siblings ...)
  2026-10-08 17:30 ` [PATCH BlueZ v2 3/3] client: Print LE.Role in info Kevin Dewald
@ 2026-10-08 19:10 ` Luiz Augusto von Dentz
  2026-10-09  3:45   ` Kevin Dewald
  3 siblings, 1 reply; 8+ messages in thread
From: Luiz Augusto von Dentz @ 2026-10-08 19:10 UTC (permalink / raw)
  To: Kevin Dewald; +Cc: linux-bluetooth

Hi Kevin,

On Thu, Oct 8, 2026 at 1:30 PM Kevin Dewald <kevin@simpleble.org> wrote:
>
> Applications acting as a peripheral, or in both roles, cannot tell
> whether a connected device is a central that connected to the adapter
> or a peripheral the adapter connected to. When several applications
> share the adapter, a device object can appear because of any of them,
> so the order of events does not answer it either.
>
> bluetoothd already tracks this per bearer from the Device Connected
> event. This series exposes it as a Role property on
> org.bluez.Bearer.LE1, "central" or "peripheral", present only while
> the device is connected over LE, and prints it as LE.Role in
> bluetoothctl info. The documentation states that it is the link layer
> role and says nothing about GATT client and server roles.
>
> Like the rest of the bearer interfaces, the property is experimental,
> so applications only see it when bluetoothd runs with -E, which few
> systems do. Is there a plan to promote the bearer interfaces, or some
> of their properties, to stable? I would be glad to help with whatever
> that needs.

Good question. Perhaps we should consider marking them stable, but
first we need to implement test automation using test-functional to
ensure they are truly stable.

> Tested with two btvirt controllers, where the advertising side reports
> the other as "central" and the connecting side reports it as
> "peripheral", and with a real adapter connecting to an nRF52840. The
> property goes away when the connection does.

For this type of testing we can use the test-functional framework
nowadays, so we just have to create a few tests to validate our
expectations. Prototyping something like doc/functional-bearer.rst for
testing the interfaces.

> Changes in v2:
> - Move the property from org.bluez.Device1 to org.bluez.Bearer.LE1, so
>   it is clearly per connection (Luiz)
> - State in the documentation that it says nothing about GATT roles
>   (Luiz)
>
> Kevin Dewald (3):
>   org.bluez.Bearer: Add Role property
>   bearer: Add Role property
>   client: Print LE.Role in info
>
>  client/main.c               |  1 +
>  doc/org.bluez.Bearer.LE.rst | 24 +++++++++++++++++++++
>  src/bearer.c                | 42 +++++++++++++++++++++++++++++++++++++
>  src/device.c                |  5 +++++
>  src/device.h                |  1 +
>  5 files changed, 73 insertions(+)
>
> --
> 2.54.0 (Apple Git-157)
>


-- 
Luiz Augusto von Dentz

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

* RE: Add Role property to org.bluez.Bearer.LE1
  2026-10-08 17:29 ` [PATCH BlueZ v2 1/3] org.bluez.Bearer: Add Role property Kevin Dewald
@ 2026-10-08 22:35   ` bluez.test.bot
  0 siblings, 0 replies; 8+ messages in thread
From: bluez.test.bot @ 2026-10-08 22:35 UTC (permalink / raw)
  To: linux-bluetooth, kevin

[-- Attachment #1: Type: text/plain, Size: 1156 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/series/1181777/

---Test result---

Test Summary:
CheckPatch                    PASS      1.14 seconds
GitLint                       PASS      0.79 seconds
BuildEll                      PASS      16.14 seconds
BluezMake                     PASS      281.25 seconds
MakeCheck                     PASS      13.74 seconds
MakeDistcheck                 PASS      117.94 seconds
CheckValgrind                 PASS      188.17 seconds
CheckSmatch                   PASS      202.45 seconds
bluezmakeextell               PASS      74.32 seconds
TestFunctional                PASS      961.44 seconds
IncrementalBuild              PENDING   350.27 seconds
ScanBuild                     PASS      822.65 seconds

Details
##############################
Test: IncrementalBuild - PENDING
Desc: Incremental build with the patches in the series
Output:



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

---
Regards,
Linux Bluetooth


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

* Re: [PATCH BlueZ v2 0/3] Add Role property to org.bluez.Bearer.LE1
  2026-10-08 19:10 ` [PATCH BlueZ v2 0/3] Add Role property to org.bluez.Bearer.LE1 Luiz Augusto von Dentz
@ 2026-10-09  3:45   ` Kevin Dewald
  2026-10-09 13:42     ` Luiz Augusto von Dentz
  0 siblings, 1 reply; 8+ messages in thread
From: Kevin Dewald @ 2026-10-09  3:45 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

Hi Luiz,

On Thu, Oct 8, 2026, Luiz Augusto von Dentz wrote:
> Good question. Perhaps we should consider marking them stable, but
> first we need to implement test automation using test-functional to
> ensure they are truly stable.
>
> For this type of testing we can use the test-functional framework
> nowadays, so we just have to create a few tests to validate our
> expectations. Prototyping something like doc/functional-bearer.rst for
> testing the interfaces.

I can write those: a test/functional/test_bearer.py with a matching
doc/functional-bearer.rst, covering Connect and Disconnect, Connected
and the Disconnected signal, Paired and Bonded on both bearers,
Connectable, and Role.

Would you like them added to this series as a v3, or sent separately so
this one can go in as it is?

Kevin

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

* Re: [PATCH BlueZ v2 0/3] Add Role property to org.bluez.Bearer.LE1
  2026-10-09  3:45   ` Kevin Dewald
@ 2026-10-09 13:42     ` Luiz Augusto von Dentz
  0 siblings, 0 replies; 8+ messages in thread
From: Luiz Augusto von Dentz @ 2026-10-09 13:42 UTC (permalink / raw)
  To: Kevin Dewald; +Cc: linux-bluetooth

Hi Kevin,

On Thu, Oct 8, 2026 at 11:45 PM Kevin Dewald <kevin@simpleble.org> wrote:
>
> Hi Luiz,
>
> On Thu, Oct 8, 2026, Luiz Augusto von Dentz wrote:
> > Good question. Perhaps we should consider marking them stable, but
> > first we need to implement test automation using test-functional to
> > ensure they are truly stable.
> >
> > For this type of testing we can use the test-functional framework
> > nowadays, so we just have to create a few tests to validate our
> > expectations. Prototyping something like doc/functional-bearer.rst for
> > testing the interfaces.
>
> I can write those: a test/functional/test_bearer.py with a matching
> doc/functional-bearer.rst, covering Connect and Disconnect, Connected
> and the Disconnected signal, Paired and Bonded on both bearers,
> Connectable, and Role.
>
> Would you like them added to this series as a v3, or sent separately so
> this one can go in as it is?

Either approach works; we only recommend splitting the series if it
grows too large (20+ commits).

> Kevin



-- 
Luiz Augusto von Dentz

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

end of thread, other threads:[~2026-10-09 13:43 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-08 17:29 [PATCH BlueZ v2 0/3] Add Role property to org.bluez.Bearer.LE1 Kevin Dewald
2026-10-08 17:29 ` [PATCH BlueZ v2 1/3] org.bluez.Bearer: Add Role property Kevin Dewald
2026-10-08 22:35   ` Add Role property to org.bluez.Bearer.LE1 bluez.test.bot
2026-10-08 17:29 ` [PATCH BlueZ v2 2/3] bearer: Add Role property Kevin Dewald
2026-10-08 17:30 ` [PATCH BlueZ v2 3/3] client: Print LE.Role in info Kevin Dewald
2026-10-08 19:10 ` [PATCH BlueZ v2 0/3] Add Role property to org.bluez.Bearer.LE1 Luiz Augusto von Dentz
2026-10-09  3:45   ` Kevin Dewald
2026-10-09 13:42     ` Luiz Augusto von Dentz

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