diff mbox series

[BlueZ,v2,2/2] media: implement SupportedFeatures property

Message ID 78f20a0242e5633c13ae8fdf2252498eb174522d.1745762308.git.pav@iki.fi
State New
Headers show
Series [BlueZ,v2,1/2] org.bluez.Media: add SupportedFeatures | expand

Commit Message

Pauli Virtanen April 27, 2025, 2:03 p.m. UTC
Add org.bluez.Media.SupportedFeatures. Add feature tx-timestamping.
---

Notes:
    v2:
    - use SIOCETHTOOL to get kernel support

 profiles/audio/media.c | 71 ++++++++++++++++++++++++++++++++++++++++++
 src/adapter.h          |  3 ++
 2 files changed, 74 insertions(+)
diff mbox series

Patch

diff --git a/profiles/audio/media.c b/profiles/audio/media.c
index 69c6dc671..3b25e5d97 100644
--- a/profiles/audio/media.c
+++ b/profiles/audio/media.c
@@ -18,6 +18,14 @@ 
 #include <errno.h>
 #include <inttypes.h>
 
+#include <time.h>
+#include <linux/errqueue.h>
+#include <linux/net_tstamp.h>
+#include <linux/ethtool.h>
+#include <linux/sockios.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+
 #include <glib.h>
 
 #include "lib/bluetooth.h"
@@ -81,6 +89,7 @@  struct media_adapter {
 #ifdef HAVE_AVRCP
 	GSList			*players;	/* Players list */
 #endif
+	int			so_timestamping;
 };
 
 struct endpoint_request {
@@ -3340,8 +3349,69 @@  static gboolean supported_uuids(const GDBusPropertyTable *property,
 	return TRUE;
 }
 
+static bool probe_tx_timestamping(struct media_adapter *adapter)
+{
+	struct ifreq ifr = {};
+	struct ethtool_ts_info cmd = {};
+	int sk = -1;
+
+	if (adapter->so_timestamping != -1)
+		goto done;
+
+	snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "hci%u",
+				btd_adapter_get_index(adapter->btd_adapter));
+	ifr.ifr_data = (void *)&cmd;
+	cmd.cmd = ETHTOOL_GET_TS_INFO;
+
+	sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
+	if (sk < 0)
+		goto error;
+	if (ioctl(sk, SIOCETHTOOL, &ifr))
+		goto error;
+	close(sk);
+
+	adapter->so_timestamping = cmd.so_timestamping;
+
+done:
+	return adapter->so_timestamping & SOF_TIMESTAMPING_TX_SOFTWARE;
+
+error:
+	if (sk >= 0)
+		close(sk);
+	adapter->so_timestamping = 0;
+	return false;
+}
+
+static const struct {
+	const char *name;
+	bool (*probe)(struct media_adapter *adapter);
+} features[] = {
+	{ "tx-timestamping", probe_tx_timestamping },
+};
+
+static gboolean supported_features(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct media_adapter *adapter = data;
+	DBusMessageIter entry;
+	size_t i;
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+				DBUS_TYPE_STRING_AS_STRING, &entry);
+
+	for (i = 0; i < ARRAY_SIZE(features); ++i)
+		if (features[i].probe(adapter))
+			dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
+							&features[i].name);
+
+	dbus_message_iter_close_container(iter, &entry);
+
+	return TRUE;
+}
+
 static const GDBusPropertyTable media_properties[] = {
 	{ "SupportedUUIDs", "as", supported_uuids },
+	{ "SupportedFeatures", "as", supported_features },
 	{ }
 };
 
@@ -3383,6 +3453,7 @@  int media_register(struct btd_adapter *btd_adapter)
 	adapter = g_new0(struct media_adapter, 1);
 	adapter->btd_adapter = btd_adapter_ref(btd_adapter);
 	adapter->apps = queue_new();
+	adapter->so_timestamping = -1;
 
 	if (!g_dbus_register_interface(btd_get_dbus_connection(),
 					adapter_get_path(btd_adapter),
diff --git a/src/adapter.h b/src/adapter.h
index 6b2bc28f6..9371cdefb 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -262,6 +262,9 @@  bool btd_le_connect_before_pairing(void);
 
 bool btd_adapter_has_settings(struct btd_adapter *adapter, uint32_t settings);
 
+int btd_adapter_get_so_timestamping(struct btd_adapter *adapter, int proto,
+							int *so_timestamping);
+
 enum experimental_features {
 	EXP_FEAT_DEBUG			= 1 << 0,
 	EXP_FEAT_LE_SIMULT_ROLES	= 1 << 1,