* [PATCH BlueZ v3 2/5] bearer: Add Role property
2026-10-09 18:04 [PATCH BlueZ v3 0/5] Add Role property to org.bluez.Bearer.LE1 Kevin Dewald
2026-10-09 18:04 ` [PATCH BlueZ v3 1/5] org.bluez.Bearer: Add Role property Kevin Dewald
@ 2026-10-09 18:04 ` Kevin Dewald
2026-10-09 18:04 ` [PATCH BlueZ v3 3/5] client: Print LE.Role in info Kevin Dewald
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Kevin Dewald @ 2026-10-09 18:04 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 v3 4/5] doc: Add functional-bearer documentation
2026-10-09 18:04 [PATCH BlueZ v3 0/5] Add Role property to org.bluez.Bearer.LE1 Kevin Dewald
` (2 preceding siblings ...)
2026-10-09 18:04 ` [PATCH BlueZ v3 3/5] client: Print LE.Role in info Kevin Dewald
@ 2026-10-09 18:04 ` Kevin Dewald
2026-10-09 18:04 ` [PATCH BlueZ v3 5/5] test: functional: add bearer tests Kevin Dewald
2026-10-09 20:50 ` [PATCH BlueZ v3 0/5] Add Role property to org.bluez.Bearer.LE1 patchwork-bot+bluetooth
5 siblings, 0 replies; 8+ messages in thread
From: Kevin Dewald @ 2026-10-09 18:04 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Luiz Augusto von Dentz, Kevin Dewald
Document the bearer functional tests, where two hosts connect or pair
over LE or BR/EDR and each checks the org.bluez.Bearer.LE1 and
org.bluez.Bearer.BREDR1 properties of the device object it has for the
other:
- Connected and Role on both sides of an LE connection, and the
Disconnected signal with its reason on both sides
- Connectable for a connectable advertiser and for a broadcaster
- Paired, Bonded and Connected after LE and BR/EDR pairing, Role being
only reported for LE
Assisted-by: Claude:claude-opus-5.5
---
Makefile.am | 1 +
doc/functional-bearer.rst | 141 +++++++++++++++++++++++++++++++++++++
doc/functional-testing.rst | 1 +
3 files changed, 143 insertions(+)
create mode 100644 doc/functional-bearer.rst
diff --git a/Makefile.am b/Makefile.am
index 71f93d2f1..f742458d1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -499,6 +499,7 @@ EXTRA_DIST += doc/assigned-numbers.rst doc/supported-features.txt \
doc/functional-a2dp.rst \
doc/functional-avrcp.rst \
doc/functional-bap.rst \
+ doc/functional-bearer.rst \
doc/functional-hog.rst \
doc/functional-mpris-proxy.rst \
doc/functional-obex.rst \
diff --git a/doc/functional-bearer.rst b/doc/functional-bearer.rst
new file mode 100644
index 000000000..79fed9db3
--- /dev/null
+++ b/doc/functional-bearer.rst
@@ -0,0 +1,141 @@
+=================
+functional-bearer
+=================
+
+DESCRIPTION
+===========
+
+Bearer functional tests, `test/functional/test_bearer.py`, covering the
+**org.bluez.Bearer.LE(5)** and **org.bluez.Bearer.BREDR(5)** interfaces
+of the device objects. See **functional-testing(7)** for the conventions
+used here, and **test-functional(1)** for how to run the suite.
+
+SETUP
+=====
+
+Two hosts, both running **bluetoothd(8)** with ``Experimental = true``,
+as the bearer interfaces are experimental, and with the MIDI plugin
+disabled (``-P midi``), as the MIDI profile would ask to pair as soon as
+it finds the MIDI service the other host exports:
+
+.. code-block::
+
+ +------------------------+ +------------------------+
+ | host0 | LE or BR/EDR | host1 |
+ | bluetoothd, agent | --------------> | bluetoothd, agent |
+ | connects or pairs | | advertises (LE) or is |
+ | | | discoverable (BR/EDR) |
+ +------------------------+ +------------------------+
+
+ --> connection is initiated by
+
+The LE tests run **bluetoothd(8)** with ``ControllerMode = le`` and have
+host1 register a connectable advertisement, as bluetoothd does not
+advertise on its own in that mode. Both hosts register an agent with
+the ``NoInputNoOutput`` capability, so pairing is Just Works.
+
+Each host reads the bearer properties of the device object it has for
+the other host, and records the ``Disconnected`` signals of the bearer
+interfaces.
+
+TEST CASES
+==========
+
+test_bearer_le_connect
+----------------------
+
+:Setup: As above, over LE.
+
+:Steps:
+ 1. host0 calls ``org.bluez.Adapter1.StartDiscovery`` and waits for a
+ device object for host1.
+ 2. host0 calls ``org.bluez.Bearer.LE1.Connect`` on it.
+ 3. Both hosts read ``Connected`` and ``Role`` on the LE bearer.
+ 4. host0 calls ``org.bluez.Bearer.LE1.Disconnect``.
+
+:Expected:
+ 1. host1 is discovered.
+ 2. ``Connect`` replies.
+ 3. ``Connected`` is true on both hosts. ``Role`` is ``peripheral`` on
+ host0, which initiated the connection, and ``central`` on host1.
+ 4. ``Disconnect`` replies, and the LE bearer emits ``Disconnected``
+ with ``org.bluez.Reason.Local`` on host0 and
+ ``org.bluez.Reason.Remote`` on host1. ``Connected`` is false on
+ both hosts and ``Role`` is no longer present.
+
+test_bearer_le_connectable
+--------------------------
+
+:Setup: As above, over LE.
+
+:Steps: host0 discovers host1, as in test_bearer_le_connect, and reads
+ ``Connectable`` on the LE bearer.
+
+:Expected: ``Connectable`` is true, as host1 advertises connectable.
+
+test_bearer_le_not_connectable
+------------------------------
+
+:Setup: As above, over LE, except host1 registers an advertisement of
+ type ``broadcast`` that is not discoverable, i.e. it advertises as a
+ broadcaster, with the service UUID
+ ``6e2c1d84-7a3b-4f50-9c1e-5b8d2a7f0e13``, and runs no agent. host0
+ runs **bluetoothd(8)** with ``FilterDiscoverable = false``, as
+ otherwise it only creates device objects for discoverable
+ advertisers.
+
+:Steps:
+ 1. host0 calls ``org.bluez.Adapter1.StartDiscovery`` and waits for a
+ device object advertising the service UUID.
+ 2. host0 reads ``Connectable`` on its LE bearer.
+
+:Expected:
+ 1. The device is discovered.
+ 2. ``Connectable`` is false.
+
+:Notes: The kernel sends non-connectable advertising from a
+ non-resolvable private address, so the device object has that
+ address rather than host1's, and host0 finds it by the advertised
+ service UUID instead.
+
+test_bearer_le_pair
+-------------------
+
+:Setup: As above, over LE.
+
+:Steps:
+ 1. host0 pairs with host1, which authorizes the pairing.
+ 2. Both hosts read ``Paired``, ``Bonded`` and ``Connected`` on the LE
+ bearer, and ``Paired`` on the BR/EDR bearer.
+
+:Expected:
+ 1. ``org.bluez.Device1.Pair`` replies.
+ 2. ``Paired``, ``Bonded`` and ``Connected`` are true on the LE bearer
+ of both hosts. The BR/EDR bearer is not present, as bluetoothd
+ runs with ``ControllerMode = le``.
+
+test_bearer_bredr_pair
+----------------------
+
+:Setup: As above, over BR/EDR.
+
+:Steps:
+ 1. host0 pairs with host1 as in test_agent_pair_bredr[accept], see
+ **functional-testing(7)**.
+ 2. Both hosts read ``Paired``, ``Bonded``, ``Connected``,
+ ``Connectable`` and ``Role`` on the BR/EDR bearer.
+ 3. host0 calls ``org.bluez.Bearer.BREDR1.Disconnect``.
+
+:Expected:
+ 1. Both agents confirm the same passkey and ``Pair`` replies.
+ 2. ``Paired``, ``Bonded``, ``Connected`` and ``Connectable`` are true
+ on both hosts, and ``Role`` is not present, as it is only
+ reported for LE.
+ 3. ``Disconnect`` replies, and the BR/EDR bearer emits
+ ``Disconnected`` with ``org.bluez.Reason.Local`` on host0 and
+ ``org.bluez.Reason.Remote`` on host1. ``Connected`` is false on
+ both hosts.
+
+:Notes: The ACL link is terminated a short time after the profiles are
+ disconnected, so the ``Disconnected`` signal follows the reply to
+ ``Disconnect``.
diff --git a/doc/functional-testing.rst b/doc/functional-testing.rst
index 7b3cad1c6..371258261 100644
--- a/doc/functional-testing.rst
+++ b/doc/functional-testing.rst
@@ -15,6 +15,7 @@ are documented separately:
- **functional-a2dp(7)**: `test/functional/test_a2dp.py`
- **functional-avrcp(7)**: `test/functional/test_avrcp.py`
- **functional-bap(7)**: `test/functional/test_bap.py`
+- **functional-bearer(7)**: `test/functional/test_bearer.py`
- **functional-hog(7)**: `test/functional/test_hog.py`
- **functional-mpris-proxy(7)**: `test/functional/test_mpris_proxy.py`
- **functional-obex(7)**: `test/functional/test_obex.py`
--
2.54.0 (Apple Git-157)
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH BlueZ v3 5/5] test: functional: add bearer tests
2026-10-09 18:04 [PATCH BlueZ v3 0/5] Add Role property to org.bluez.Bearer.LE1 Kevin Dewald
` (3 preceding siblings ...)
2026-10-09 18:04 ` [PATCH BlueZ v3 4/5] doc: Add functional-bearer documentation Kevin Dewald
@ 2026-10-09 18:04 ` Kevin Dewald
2026-10-09 20:50 ` [PATCH BlueZ v3 0/5] Add Role property to org.bluez.Bearer.LE1 patchwork-bot+bluetooth
5 siblings, 0 replies; 8+ messages in thread
From: Kevin Dewald @ 2026-10-09 18:04 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Luiz Augusto von Dentz, Kevin Dewald
Add tests where host0 connects to or pairs with host1 over LE or
BR/EDR, and both hosts check the properties and the Disconnected
signal of the bearer interfaces of the device object they have for the
other, including the LE Role of each side of the connection.
See doc/functional-bearer.rst for details.
Assisted-by: Claude:claude-opus-5.5
---
test/functional/test_bearer.py | 302 +++++++++++++++++++++++++++++++++
1 file changed, 302 insertions(+)
create mode 100644 test/functional/test_bearer.py
diff --git a/test/functional/test_bearer.py b/test/functional/test_bearer.py
new file mode 100644
index 000000000..9d2f3346d
--- /dev/null
+++ b/test/functional/test_bearer.py
@@ -0,0 +1,302 @@
+# -*- coding: utf-8; mode: python; eval: (blacken-mode); -*-
+# SPDX-License-Identifier: GPL-2.0-or-later
+"""
+Tests for the org.bluez.Bearer.LE1 and org.bluez.Bearer.BREDR1 interfaces
+
+host0 connects to or pairs with host1, and each host checks the bearer
+interfaces of the device object it has for the other.
+"""
+
+import logging
+
+import dbus
+import pytest
+
+from pytest_bluezenv import (
+ Agent,
+ Bluetoothd,
+ EventPluginMixin,
+ HostPlugin,
+ get_dbus,
+ host_config,
+ mainloop_wrap,
+ wait_until,
+)
+
+from .le_utils import LeAdvertiser, pair_le
+from .test_agent import test_agent_pair_bredr as pair_bredr
+
+pytestmark = [pytest.mark.vm]
+
+BUS_NAME = "org.bluez"
+PROPS_INTERFACE = "org.freedesktop.DBus.Properties"
+DEVICE_INTERFACE = "org.bluez.Device1"
+LE_INTERFACE = "org.bluez.Bearer.LE1"
+BREDR_INTERFACE = "org.bluez.Bearer.BREDR1"
+
+# The bearer interfaces are experimental
+CONF = "[General]\nExperimental = true\n"
+LE_CONF = CONF + "ControllerMode = le\n"
+
+# bluetoothd only creates device objects for advertisers that are
+# discoverable, which a broadcaster is not
+SCANNER_CONF = LE_CONF + "FilterDiscoverable = false\n"
+
+# Identifies the broadcast advertisement of host1 on host0, as it is sent
+# from a non-resolvable private address rather than from host1's address
+BROADCAST_UUID = "6e2c1d84-7a3b-4f50-9c1e-5b8d2a7f0e13"
+
+# The MIDI profile asks to pair as soon as it finds the MIDI service the
+# other host exports, which would need an agent reply in every test
+ARGS = ("-P", "midi")
+
+
+class Bearers(HostPlugin, EventPluginMixin):
+ """
+ Host plugin calling the bearer interfaces of remote devices, reading
+ their properties and recording their Disconnected signals.
+ """
+
+ name = "bearers"
+ depends = [Bluetoothd()]
+
+ @mainloop_wrap
+ def setup(self, impl):
+ EventPluginMixin.setup(self, impl)
+
+ self.log = logging.getLogger(self.name)
+ self.bus = get_dbus(private=True)
+ self.disconnected = []
+
+ self.bus.add_signal_receiver(
+ self._disconnected,
+ signal_name="Disconnected",
+ bus_name=BUS_NAME,
+ path_keyword="path",
+ interface_keyword="interface",
+ )
+
+ def _disconnected(self, reason, message, path=None, interface=None):
+ if interface not in (LE_INTERFACE, BREDR_INTERFACE):
+ return
+
+ self.log.info(f"{path} {interface}.Disconnected: {reason}")
+ self.disconnected.append((str(path), str(interface), str(reason)))
+
+ def _devices(self):
+ manager = dbus.Interface(
+ self.bus.get_object(BUS_NAME, "/"), "org.freedesktop.DBus.ObjectManager"
+ )
+
+ for path, ifaces in manager.GetManagedObjects().items():
+ device = ifaces.get(DEVICE_INTERFACE)
+ if device is not None:
+ yield str(path), device
+
+ def _device_path(self, address):
+ for path, device in self._devices():
+ if device["Address"].lower() == address.lower():
+ return path
+
+ return None
+
+ @mainloop_wrap
+ def find_address(self, uuid):
+ """
+ Return the address of the device advertising the given service
+ UUID, or None if there is none.
+ """
+ for path, device in self._devices():
+ if uuid in [str(u).lower() for u in device.get("UUIDs", [])]:
+ return str(device["Address"])
+
+ return None
+
+ @mainloop_wrap
+ def get(self, address, interface, name):
+ """
+ Return a bearer property of the device with the given address, or
+ None if the device, the bearer or the property is not there.
+ """
+ path = self._device_path(address)
+ if path is None:
+ return None
+
+ props = dbus.Interface(self.bus.get_object(BUS_NAME, path), PROPS_INTERFACE)
+ try:
+ value = props.Get(interface, name)
+ except dbus.exceptions.DBusException:
+ return None
+
+ if isinstance(value, dbus.Boolean):
+ return bool(value)
+
+ return str(value)
+
+ @mainloop_wrap
+ def call(self, address, interface, method):
+ """
+ Call a bearer method of the device with the given address.
+
+ Events:
+ Event(kind="{interface}.{method}:reply")
+ """
+ path = self._device_path(address)
+ bearer = dbus.Interface(self.bus.get_object(BUS_NAME, path), interface)
+ self._object_method(bearer, method)
+
+ @mainloop_wrap
+ def disconnect_reasons(self, address, interface):
+ """
+ Return the reasons of the Disconnected signals received on the
+ given bearer of the device with the given address, in order.
+ """
+ path = f"/org/bluez/hci0/dev_{address.upper().replace(':', '_')}"
+ return [r for p, i, r in self.disconnected if p == path and i == interface]
+
+
+le_config = host_config(
+ [
+ Bluetoothd(conf=LE_CONF, args=ARGS),
+ Agent(capability="NoInputNoOutput"),
+ Bearers(),
+ ],
+ [
+ Bluetoothd(conf=LE_CONF, args=ARGS),
+ LeAdvertiser(),
+ Agent(capability="NoInputNoOutput"),
+ Bearers(),
+ ],
+)
+
+bredr_config = host_config(
+ [Bluetoothd(conf=CONF, args=ARGS), Agent(), Bearers()],
+ [Bluetoothd(conf=CONF, args=ARGS), Agent(), Bearers()],
+)
+
+
+def start_discovery(host):
+ host.agent.adapter_method("StartDiscovery")
+ host.agent.expect("org.bluez.Adapter1.StartDiscovery:reply")
+
+
+def discover(host, remote):
+ start_discovery(host)
+ wait_until(host.agent.has_device, remote.bdaddr)
+
+
+def peers(host0, host1):
+ """Both hosts, each with the other"""
+ return ((host0, host1), (host1, host0))
+
+
+def disconnect(host0, host1, interface):
+ """
+ Disconnect the bearer from host0, and check it is reported as
+ disconnected on both hosts with the reason seen from each side.
+ """
+ host0.bearers.call(host1.bdaddr, interface, "Disconnect")
+ host0.bearers.expect(f"{interface}.Disconnect:reply")
+
+ for host, remote, reason in (
+ (host0, host1, "org.bluez.Reason.Local"),
+ (host1, host0, "org.bluez.Reason.Remote"),
+ ):
+ wait_until(
+ lambda: host.bearers.disconnect_reasons(remote.bdaddr, interface)
+ == [reason]
+ )
+ assert host.bearers.get(remote.bdaddr, interface, "Connected") is False
+
+
+@le_config
+def test_bearer_le_connect(hosts):
+ host0, host1 = hosts
+
+ discover(host0, host1)
+
+ host0.bearers.call(host1.bdaddr, LE_INTERFACE, "Connect")
+ host0.bearers.expect(f"{LE_INTERFACE}.Connect:reply")
+
+ for host, remote in peers(host0, host1):
+ wait_until(
+ lambda: host.bearers.get(remote.bdaddr, LE_INTERFACE, "Connected") is True
+ )
+
+ assert host0.bearers.get(host1.bdaddr, LE_INTERFACE, "Role") == "peripheral"
+ assert host1.bearers.get(host0.bdaddr, LE_INTERFACE, "Role") == "central"
+
+ disconnect(host0, host1, LE_INTERFACE)
+
+ for host, remote in peers(host0, host1):
+ assert host.bearers.get(remote.bdaddr, LE_INTERFACE, "Role") is None
+
+
+@host_config(
+ [Bluetoothd(conf=SCANNER_CONF, args=ARGS), Agent(), Bearers()],
+ # A broadcaster, so neither connectable nor discoverable
+ [
+ Bluetoothd(conf=LE_CONF, args=ARGS),
+ LeAdvertiser(
+ adv_type="broadcast",
+ service_uuids=[BROADCAST_UUID],
+ discoverable=False,
+ ),
+ ],
+)
+def test_bearer_le_not_connectable(hosts):
+ host0, host1 = hosts
+
+ start_discovery(host0)
+ wait_until(lambda: host0.bearers.find_address(BROADCAST_UUID) is not None)
+ address = host0.bearers.find_address(BROADCAST_UUID)
+
+ wait_until(
+ lambda: host0.bearers.get(address, LE_INTERFACE, "Connectable") is not None
+ )
+ assert host0.bearers.get(address, LE_INTERFACE, "Connectable") is False
+
+
+@le_config
+def test_bearer_le_connectable(hosts):
+ host0, host1 = hosts
+
+ discover(host0, host1)
+
+ wait_until(
+ lambda: host0.bearers.get(host1.bdaddr, LE_INTERFACE, "Connectable") is not None
+ )
+ assert host0.bearers.get(host1.bdaddr, LE_INTERFACE, "Connectable") is True
+
+
+@le_config
+def test_bearer_le_pair(hosts):
+ host0, host1 = hosts
+
+ pair_le(host0, host1)
+
+ for host, remote in peers(host0, host1):
+ for name in ("Paired", "Bonded", "Connected"):
+ wait_until(
+ lambda: host.bearers.get(remote.bdaddr, LE_INTERFACE, name) is True
+ )
+
+ assert host.bearers.get(remote.bdaddr, BREDR_INTERFACE, "Paired") is None
+
+
+@bredr_config
+def test_bearer_bredr_pair(hosts):
+ host0, host1 = hosts
+
+ pair_bredr(hosts, True)
+
+ for host, remote in peers(host0, host1):
+ for name in ("Paired", "Bonded", "Connected", "Connectable"):
+ wait_until(
+ lambda: host.bearers.get(remote.bdaddr, BREDR_INTERFACE, name) is True
+ )
+
+ # Role is only reported for LE
+ assert host.bearers.get(remote.bdaddr, BREDR_INTERFACE, "Role") is None
+
+ disconnect(host0, host1, BREDR_INTERFACE)
--
2.54.0 (Apple Git-157)
^ permalink raw reply related [flat|nested] 8+ messages in thread