[PATCH BlueZ v2 3/5] bearer: Add initial implementation of org.bluez.Bearer.{BREDR, LE}

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx>

This adds initial implementation of org.bluez.Bearer{BREDR, LE}(5)
interfaces.
---
 Makefile.am  |   3 +-
 src/bearer.c | 260 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/bearer.h |  22 +++++
 src/device.c |  66 ++++++++++---
 4 files changed, 339 insertions(+), 12 deletions(-)
 create mode 100644 src/bearer.c
 create mode 100644 src/bearer.h

diff --git a/Makefile.am b/Makefile.am
index b75125e8887f..c70d6543e133 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -330,7 +330,8 @@ src_bluetoothd_SOURCES = $(builtin_sources) \
 			src/adv_monitor.h src/adv_monitor.c \
 			src/battery.h src/battery.c \
 			src/settings.h src/settings.c \
-			src/set.h src/set.c
+			src/set.h src/set.c \
+			src/bearer.h src/bearer.c
 src_bluetoothd_LDADD = lib/libbluetooth-internal.la \
 			gdbus/libgdbus-internal.la \
 			src/libshared-glib.la \
diff --git a/src/bearer.c b/src/bearer.c
new file mode 100644
index 000000000000..d4286b431583
--- /dev/null
+++ b/src/bearer.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2025  Intel Corporation
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+
+#include "lib/bluetooth.h"
+#include "lib/mgmt.h"
+
+#include "gdbus/gdbus.h"
+#include "src/shared/util.h"
+
+#include "log.h"
+#include "error.h"
+#include "adapter.h"
+#include "device.h"
+#include "dbus-common.h"
+#include "bearer.h"
+
+struct btd_bearer {
+	struct btd_device *device;
+	uint8_t type;
+	const char *path;
+};
+
+static void bearer_free(void *data)
+{
+	struct btd_bearer *bearer = data;
+
+	free(bearer);
+}
+
+static DBusMessage *bearer_connect(DBusConnection *conn, DBusMessage *msg,
+							void *user_data)
+{
+	/* TODO */
+	return NULL;
+}
+
+static DBusMessage *bearer_disconnect(DBusConnection *conn, DBusMessage *msg,
+							void *user_data)
+{
+	/* TODO */
+	return NULL;
+}
+
+static const GDBusMethodTable bearer_methods[] = {
+	{ GDBUS_EXPERIMENTAL_ASYNC_METHOD("Connect", NULL, NULL,
+						bearer_connect) },
+	{ GDBUS_EXPERIMENTAL_ASYNC_METHOD("Disconnect", NULL, NULL,
+						bearer_disconnect) },
+	{}
+};
+
+static gboolean bearer_get_adapter(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct btd_bearer *bearer = data;
+	struct btd_adapter *adapter = device_get_adapter(bearer->device);
+	const char *path = adapter_get_path(adapter);
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
+
+	return TRUE;
+}
+
+static gboolean bearer_get_paired(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct btd_bearer *bearer = data;
+	dbus_bool_t paired = device_is_paired(bearer->device, bearer->type);
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &paired);
+
+	return TRUE;
+}
+
+static gboolean bearer_get_bonded(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct btd_bearer *bearer = data;
+	dbus_bool_t bonded = device_is_bonded(bearer->device, bearer->type);
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &bonded);
+
+	return TRUE;
+}
+
+static gboolean bearer_get_connected(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct btd_bearer *bearer = data;
+	dbus_bool_t connected = btd_device_bdaddr_type_connected(bearer->device,
+								bearer->type);
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &connected);
+
+	return TRUE;
+}
+
+static const GDBusSignalTable bearer_signals[] = {
+	{ GDBUS_SIGNAL("Disconnected",
+			GDBUS_ARGS({ "name", "s" }, { "message", "s" })) },
+	{ }
+};
+
+static const GDBusPropertyTable bearer_properties[] = {
+	{ "Adapter", "o", bearer_get_adapter, NULL, NULL,
+			G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "Paired", "b", bearer_get_paired, NULL, NULL,
+			G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "Bonded", "b", bearer_get_bonded, NULL, NULL,
+			G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{ "Connected", "b", bearer_get_connected, NULL, NULL,
+			G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+	{}
+};
+
+static const char *bearer_interface(uint8_t type)
+{
+	if (type == BDADDR_BREDR)
+		return BTD_BEARER_BREDR_INTERFACE;
+	else
+		return BTD_BEARER_LE_INTERFACE;
+}
+
+struct btd_bearer *btd_bearer_new(struct btd_device *device, uint8_t type)
+{
+	struct btd_bearer *bearer;
+
+	bearer = new0(struct btd_bearer, 1);
+	bearer->device = device;
+	bearer->type = type;
+	bearer->path = device_get_path(device);
+
+	if (!g_dbus_register_interface(btd_get_dbus_connection(),
+					bearer->path, bearer_interface(type),
+					bearer_methods, bearer_signals,
+					bearer_properties,
+					bearer, bearer_free)) {
+		error("Unable to register BREDR interface");
+		bearer->path = NULL;
+	}
+
+	return bearer;
+}
+
+void btd_bearer_destroy(struct btd_bearer *bearer)
+{
+	if (!bearer)
+		return;
+
+	if (!bearer->path) {
+		bearer_free(bearer);
+		return;
+	}
+
+	g_dbus_unregister_interface(btd_get_dbus_connection(), bearer->path,
+					bearer_interface(bearer->type));
+}
+
+void btd_bearer_paired(struct btd_bearer *bearer)
+{
+	if (!bearer || !bearer->path)
+		return;
+
+	g_dbus_emit_property_changed(btd_get_dbus_connection(), bearer->path,
+					bearer_interface(bearer->type),
+					"Paired");
+}
+
+void btd_bearer_bonded(struct btd_bearer *bearer)
+{
+	if (!bearer || !bearer->path)
+		return;
+
+	g_dbus_emit_property_changed(btd_get_dbus_connection(), bearer->path,
+					bearer_interface(bearer->type),
+					"Bonded");
+}
+
+void btd_bearer_connected(struct btd_bearer *bearer)
+{
+	if (!bearer || !bearer->path)
+		return;
+
+	g_dbus_emit_property_changed(btd_get_dbus_connection(), bearer->path,
+					bearer_interface(bearer->type),
+					"Connected");
+}
+
+void btd_bearer_disconnected(struct btd_bearer *bearer, uint8_t reason)
+{
+	const char *name;
+	const char *message;
+
+	if (!bearer || !bearer->path)
+		return;
+
+	g_dbus_emit_property_changed(btd_get_dbus_connection(), bearer->path,
+					bearer_interface(bearer->type),
+					"Connected");
+
+	switch (reason) {
+	case MGMT_DEV_DISCONN_UNKNOWN:
+		name = "org.bluez.Reason.Unknown";
+		message = "Unspecified";
+		break;
+	case MGMT_DEV_DISCONN_TIMEOUT:
+		name = "org.bluez.Reason.Timeout";
+		message = "Connection timeout";
+		break;
+	case MGMT_DEV_DISCONN_LOCAL_HOST:
+		name = "org.bluez.Reason.Local";
+		message = "Connection terminated by local host";
+		break;
+	case MGMT_DEV_DISCONN_REMOTE:
+		name = "org.bluez.Reason.Remote";
+		message = "Connection terminated by remote user";
+		break;
+	case MGMT_DEV_DISCONN_AUTH_FAILURE:
+		name = "org.bluez.Reason.Authentication";
+		message = "Connection terminated due to authentication failure";
+		break;
+	case MGMT_DEV_DISCONN_LOCAL_HOST_SUSPEND:
+		name = "org.bluez.Reason.Suspend";
+		message = "Connection terminated by local host for suspend";
+		break;
+	default:
+		warn("Unknown disconnection value: %u", reason);
+		name = "org.bluez.Reason.Unknown";
+		message = "Unspecified";
+	}
+
+	g_dbus_emit_signal(btd_get_dbus_connection(), bearer->path,
+					bearer_interface(bearer->type),
+					"Disconnected",
+					DBUS_TYPE_STRING, &name,
+					DBUS_TYPE_STRING, &message,
+					DBUS_TYPE_INVALID);
+}
diff --git a/src/bearer.h b/src/bearer.h
new file mode 100644
index 000000000000..4a39dcdd047e
--- /dev/null
+++ b/src/bearer.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2025  Intel Corporation
+ *
+ *
+ */
+
+#define BTD_BEARER_BREDR_INTERFACE	"org.bluez.Bearer.BREDR1"
+#define BTD_BEARER_LE_INTERFACE		"org.bluez.Bearer.LE1"
+
+struct btd_bearer;
+
+struct btd_bearer *btd_bearer_new(struct btd_device *device, uint8_t type);
+void btd_bearer_destroy(struct btd_bearer *bearer);
+
+void btd_bearer_paired(struct btd_bearer *bearer);
+void btd_bearer_bonded(struct btd_bearer *bearer);
+void btd_bearer_connected(struct btd_bearer *bearer);
+void btd_bearer_disconnected(struct btd_bearer *bearer, uint8_t reason);
diff --git a/src/device.c b/src/device.c
index eed2edcf0dfc..7e62112615e4 100644
--- a/src/device.c
+++ b/src/device.c
@@ -66,6 +66,7 @@
 #include "eir.h"
 #include "settings.h"
 #include "set.h"
+#include "bearer.h"
 
 #define DISCONNECT_TIMER	2
 #define DISCOVERY_TIMER		1
@@ -205,8 +206,8 @@ struct btd_device {
 	uint8_t		bdaddr_type;
 	bool		rpa;
 	char		*path;
-	bool		bredr;
-	bool		le;
+	struct btd_bearer *bredr;
+	struct btd_bearer *le;
 	bool		pending_paired;		/* "Paired" waiting for SDP */
 	bool		svc_refreshed;
 	bool		refresh_discovery;
@@ -949,6 +950,9 @@ static void device_free(gpointer user_data)
 
 	queue_destroy(device->sirks, free);
 
+	btd_bearer_destroy(device->bredr);
+	btd_bearer_destroy(device->le);
+
 	g_free(device->local_csrk);
 	g_free(device->remote_csrk);
 	free(device->ltk);
@@ -2981,6 +2985,11 @@ static void browse_request_complete(struct browse_req *req, uint8_t type,
 		}
 
 		if (dev->pending_paired) {
+			if (bdaddr_type == BDADDR_BREDR)
+				btd_bearer_paired(dev->bredr);
+			else
+				btd_bearer_paired(dev->le);
+
 			g_dbus_emit_property_changed(dbus_conn, dev->path,
 						DEVICE_INTERFACE, "Paired");
 			dev->pending_paired = false;
@@ -3072,6 +3081,11 @@ static void device_svc_resolved(struct btd_device *dev, uint8_t browse_type,
 	dev->eir_uuids = NULL;
 
 	if (dev->pending_paired) {
+		if (bdaddr_type == BDADDR_BREDR)
+			btd_bearer_paired(dev->bredr);
+		else
+			btd_bearer_paired(dev->le);
+
 		g_dbus_emit_property_changed(dbus_conn, dev->path,
 						DEVICE_INTERFACE, "Paired");
 		dev->pending_paired = false;
@@ -3698,10 +3712,13 @@ void device_add_connection(struct btd_device *dev, uint8_t bdaddr_type,
 	dev->conn_bdaddr_type = dev->bdaddr_type;
 
 	/* If this is the first connection over this bearer */
-	if (bdaddr_type == BDADDR_BREDR)
+	if (bdaddr_type == BDADDR_BREDR) {
 		device_set_bredr_support(dev);
-	else
+		btd_bearer_connected(dev->bredr);
+	} else {
 		device_set_le_support(dev, bdaddr_type);
+		btd_bearer_connected(dev->le);
+	}
 
 	state->connected = true;
 	state->initiator = flags & BIT(3);
@@ -3833,6 +3850,12 @@ void device_remove_connection(struct btd_device *device, uint8_t bdaddr_type,
 		device->connect = NULL;
 	}
 
+	/* Update bearer interface */
+	if (bdaddr_type == BDADDR_BREDR)
+		btd_bearer_disconnected(device->bredr, reason);
+	else
+		btd_bearer_disconnected(device->le, reason);
+
 	/* Check paired status of both bearers since it's possible to be
 	 * paired but not connected via link key to LTK conversion.
 	 */
@@ -3843,6 +3866,7 @@ void device_remove_connection(struct btd_device *device, uint8_t bdaddr_type,
 						BDADDR_BREDR);
 		device->bredr_state.paired = false;
 		paired_status_updated = true;
+		btd_bearer_paired(device->bredr);
 	}
 
 	if (!device->le_state.connected && device->le_state.paired &&
@@ -3852,6 +3876,7 @@ void device_remove_connection(struct btd_device *device, uint8_t bdaddr_type,
 						device->bdaddr_type);
 		device->le_state.paired = false;
 		paired_status_updated = true;
+		btd_bearer_paired(device->le);
 	}
 
 	/* report change only if both bearers are unpaired */
@@ -4191,9 +4216,9 @@ static void load_info(struct btd_device *device, const char *local,
 
 	for (t = techno; *t; t++) {
 		if (g_str_equal(*t, "BR/EDR"))
-			device->bredr = true;
+			device->bredr = btd_bearer_new(device, BDADDR_BREDR);
 		else if (g_str_equal(*t, "LE"))
-			device->le = true;
+			device->le = btd_bearer_new(device, BDADDR_LE_PUBLIC);
 		else
 			error("Unknown device technology");
 	}
@@ -4834,9 +4859,9 @@ struct btd_device *device_create(struct btd_adapter *adapter,
 	device->bdaddr_type = bdaddr_type;
 
 	if (bdaddr_type == BDADDR_BREDR)
-		device->bredr = true;
+		device->bredr = btd_bearer_new(device, BDADDR_BREDR);
 	else
-		device->le = true;
+		device->le = btd_bearer_new(device, BDADDR_LE_PUBLIC);
 
 	storage_dir = btd_adapter_get_storage_dir(adapter);
 	str = load_cached_name(device, storage_dir, dst);
@@ -4986,7 +5011,8 @@ void device_update_addr(struct btd_device *device, const bdaddr_t *bdaddr,
 	/* Since this function is only used for LE SMP Identity
 	 * Resolving purposes we can now assume LE is supported.
 	 */
-	device->le = true;
+	if (!device->le)
+		device->le = btd_bearer_new(device, BDADDR_LE_PUBLIC);
 
 	/* Remove old address from accept/auto-connect list since its address
 	 * will be changed.
@@ -5016,7 +5042,8 @@ void device_set_bredr_support(struct btd_device *device)
 	if (btd_opts.mode == BT_MODE_LE || device->bredr)
 		return;
 
-	device->bredr = true;
+	if (!device->bredr)
+		device->bredr = btd_bearer_new(device, BDADDR_BREDR);
 
 	if (device->le)
 		g_dbus_emit_property_changed(dbus_conn, device->path,
@@ -5030,7 +5057,9 @@ void device_set_le_support(struct btd_device *device, uint8_t bdaddr_type)
 	if (btd_opts.mode == BT_MODE_BREDR || device->le)
 		return;
 
-	device->le = true;
+	if (!device->le)
+		device->le = btd_bearer_new(device, BDADDR_LE_PUBLIC);
+
 	device->bdaddr_type = bdaddr_type;
 
 	g_dbus_emit_property_changed(dbus_conn, device->path,
@@ -6613,6 +6642,11 @@ void device_set_bonded(struct btd_device *device, uint8_t bdaddr_type)
 
 	state->bonded = true;
 
+	if (bdaddr_type == BDADDR_BREDR)
+		btd_bearer_bonded(device->bredr);
+	else
+		btd_bearer_bonded(device->le);
+
 	btd_device_set_temporary(device, false);
 
 	/* If the other bearer state was already true we don't need to
@@ -6863,6 +6897,11 @@ void device_set_paired(struct btd_device *dev, uint8_t bdaddr_type)
 
 	state->paired = true;
 
+	if (bdaddr_type == BDADDR_BREDR)
+		btd_bearer_paired(dev->bredr);
+	else
+		btd_bearer_paired(dev->le);
+
 	/* If the other bearer state was already true we don't need to
 	 * send any property signals.
 	 */
@@ -6887,6 +6926,11 @@ void device_set_unpaired(struct btd_device *dev, uint8_t bdaddr_type)
 
 	state->paired = false;
 
+	if (bdaddr_type == BDADDR_BREDR)
+		btd_bearer_paired(dev->bredr);
+	else
+		btd_bearer_paired(dev->le);
+
 	/*
 	 * If the other bearer state is still true we don't need to
 	 * send any property signals or remove device.
-- 
2.50.0





[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux