From: "Frédéric Danis" <frederic.danis@collabora.com>
To: linux-bluetooth@vger.kernel.org
Subject: [PATCH BlueZ v4 1/5] obexd: Add BIP client for AVRCP cover art download
Date: Tue, 17 Sep 2024 09:42:13 +0200 [thread overview]
Message-ID: <20240917074217.231677-2-frederic.danis@collabora.com> (raw)
In-Reply-To: <20240917074217.231677-1-frederic.danis@collabora.com>
The cover art image handle is available in the metadata of the track
when the OBEX BIP session is connected to the PSM port provided
in AVRCP SDP record and available as org.bluez.MediaPlayer property.
This service allows to get the thumbnail.
---
Makefile.obexd | 1 +
doc/org.bluez.obex.Client.rst | 1 +
obexd/client/bip.c | 171 ++++++++++++++++++++++++++++++++++
obexd/client/bip.h | 12 +++
obexd/client/manager.c | 2 +
5 files changed, 187 insertions(+)
create mode 100644 obexd/client/bip.c
create mode 100644 obexd/client/bip.h
diff --git a/Makefile.obexd b/Makefile.obexd
index 4cdce73af..866147dd1 100644
--- a/Makefile.obexd
+++ b/Makefile.obexd
@@ -81,6 +81,7 @@ obexd_src_obexd_SOURCES = $(btio_sources) $(gobex_sources) \
obexd/client/ftp.h obexd/client/ftp.c \
obexd/client/opp.h obexd/client/opp.c \
obexd/client/map.h obexd/client/map.c \
+ obexd/client/bip.h obexd/client/bip.c \
obexd/client/map-event.h obexd/client/map-event.c \
obexd/client/transfer.h obexd/client/transfer.c \
obexd/client/transport.h obexd/client/transport.c \
diff --git a/doc/org.bluez.obex.Client.rst b/doc/org.bluez.obex.Client.rst
index 5ae7cc5e8..f20dd5baa 100644
--- a/doc/org.bluez.obex.Client.rst
+++ b/doc/org.bluez.obex.Client.rst
@@ -43,6 +43,7 @@ object CreateSession(string destination, dict args)
:"opp":
:"pbap":
:"sync":
+ :"bip-avrcp":
:string Source:
diff --git a/obexd/client/bip.c b/obexd/client/bip.c
new file mode 100644
index 000000000..252bc4cec
--- /dev/null
+++ b/obexd/client/bip.c
@@ -0,0 +1,171 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ *
+ * OBEX Client
+ *
+ * Copyright (C) 2024 Collabora Ltd.
+ *
+ *
+ */
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "gdbus/gdbus.h"
+#include "gobex/gobex.h"
+
+#include "obexd/src/log.h"
+#include "transfer.h"
+#include "session.h"
+#include "driver.h"
+#include "bip.h"
+
+#define OBEX_BIP_AVRCP_UUID \
+ "\x71\x63\xDD\x54\x4A\x7E\x11\xE2\xB4\x7C\x00\x50\xC2\x49\x00\x48"
+#define OBEX_BIP_AVRCP_UUID_LEN 16
+
+#define IMAGE_INTERFACE "org.bluez.obex.Image1"
+#define ERROR_INTERFACE "org.bluez.obex.Error"
+#define IMAGE_UUID "0000111A-0000-1000-8000-00805f9b34fb"
+
+#define IMG_HANDLE_TAG 0x30
+
+static DBusConnection *conn;
+
+struct bip_avrcp_data {
+ struct obc_session *session;
+};
+
+static DBusMessage *get_thumbnail(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ struct bip_avrcp_data *bip_avrcp = user_data;
+ const char *handle = NULL, *image_path = NULL;
+ struct obc_transfer *transfer;
+ GObexHeader *header;
+ DBusMessage *reply = NULL;
+ GError *err = NULL;
+
+ DBG("");
+
+ if (dbus_message_get_args(message, NULL,
+ DBUS_TYPE_STRING, &image_path,
+ DBUS_TYPE_STRING, &handle,
+ DBUS_TYPE_INVALID) == FALSE) {
+ reply = g_dbus_create_error(message,
+ ERROR_INTERFACE ".InvalidArguments", NULL);
+ return reply;
+ }
+
+ transfer = obc_transfer_get("x-bt/img-thm", NULL, image_path, &err);
+ if (transfer == NULL)
+ goto fail;
+
+ header = g_obex_header_new_unicode(IMG_HANDLE_TAG, handle);
+ obc_transfer_add_header(transfer, header);
+
+ if (!obc_session_queue(bip_avrcp->session, transfer, NULL, NULL, &err))
+ goto fail;
+
+ return obc_transfer_create_dbus_reply(transfer, message);
+
+fail:
+ reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s",
+ err->message);
+ g_error_free(err);
+ return reply;
+}
+
+static const GDBusMethodTable bip_avrcp_methods[] = {
+ { GDBUS_ASYNC_METHOD("GetThumbnail",
+ GDBUS_ARGS({ "file", "s" }, { "handle", "s"}),
+ GDBUS_ARGS({ "transfer", "o" }, { "properties", "a{sv}" }),
+ get_thumbnail) },
+ { }
+};
+
+static void bip_avrcp_free(void *data)
+{
+ struct bip_avrcp_data *bip_avrcp = data;
+
+ obc_session_unref(bip_avrcp->session);
+ g_free(bip_avrcp);
+}
+
+static int bip_avrcp_probe(struct obc_session *session)
+{
+ struct bip_avrcp_data *bip_avrcp;
+ const char *path;
+
+ path = obc_session_get_path(session);
+
+ DBG("%s", path);
+
+ bip_avrcp = g_try_new0(struct bip_avrcp_data, 1);
+ if (!bip_avrcp)
+ return -ENOMEM;
+
+ bip_avrcp->session = obc_session_ref(session);
+
+ if (!g_dbus_register_interface(conn, path, IMAGE_INTERFACE,
+ bip_avrcp_methods,
+ NULL, NULL,
+ bip_avrcp, bip_avrcp_free)) {
+ bip_avrcp_free(bip_avrcp);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void bip_avrcp_remove(struct obc_session *session)
+{
+ const char *path = obc_session_get_path(session);
+
+ DBG("%s", path);
+
+ g_dbus_unregister_interface(conn, path, IMAGE_INTERFACE);
+}
+
+static struct obc_driver bip_avrcp = {
+ .service = "BIP-AVRCP",
+ .uuid = IMAGE_UUID,
+ .target = OBEX_BIP_AVRCP_UUID,
+ .target_len = OBEX_BIP_AVRCP_UUID_LEN,
+ .probe = bip_avrcp_probe,
+ .remove = bip_avrcp_remove
+};
+
+int bip_init(void)
+{
+ int err;
+
+ DBG("");
+
+ conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
+ if (!conn)
+ return -EIO;
+
+ err = obc_driver_register(&bip_avrcp);
+ if (err < 0)
+ goto failed;
+
+ return 0;
+
+failed:
+ dbus_connection_unref(conn);
+ conn = NULL;
+ return err;
+}
+
+void bip_exit(void)
+{
+ DBG("");
+
+ dbus_connection_unref(conn);
+ conn = NULL;
+
+ obc_driver_unregister(&bip_avrcp);
+}
diff --git a/obexd/client/bip.h b/obexd/client/bip.h
new file mode 100644
index 000000000..18e3360f3
--- /dev/null
+++ b/obexd/client/bip.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ *
+ * OBEX Client
+ *
+ * Copyright (C) 2024 Collabora Ltd.
+ *
+ *
+ */
+
+int bip_init(void);
+void bip_exit(void);
diff --git a/obexd/client/manager.c b/obexd/client/manager.c
index 52c00fb0c..52f4d0179 100644
--- a/obexd/client/manager.c
+++ b/obexd/client/manager.c
@@ -32,6 +32,7 @@
#include "pbap.h"
#include "sync.h"
#include "map.h"
+#include "bip.h"
#include "manager.h"
#define CLIENT_INTERFACE "org.bluez.obex.Client1"
@@ -258,6 +259,7 @@ static const struct obc_module {
{ "pbap", pbap_init, pbap_exit },
{ "sync", sync_init, sync_exit },
{ "map", map_init, map_exit },
+ { "bip", bip_init, bip_exit },
{ }
};
--
2.34.1
next prev parent reply other threads:[~2024-09-17 7:42 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-09-17 7:42 [PATCH BlueZ v4 0/5] Add BIP for AVRCP covert art OBEX client Frédéric Danis
2024-09-17 7:42 ` Frédéric Danis [this message]
2024-09-17 11:31 ` bluez.test.bot
2024-09-17 7:42 ` [PATCH BlueZ v4 2/5] obexd: Add Properties to org.bluez.obex.Image Frédéric Danis
2024-09-17 7:42 ` [PATCH BlueZ v4 3/5] obexd: Add Get " Frédéric Danis
2024-09-17 7:42 ` [PATCH BlueZ v4 4/5] avrcp: Update controller SDP record with cover art support Frédéric Danis
2024-09-17 7:42 ` [PATCH BlueZ v4 5/5] doc: Add description of org.bluez.obex.Image Frédéric Danis
2024-09-17 15:40 ` [PATCH BlueZ v4 0/5] Add BIP for AVRCP covert art OBEX client 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=20240917074217.231677-2-frederic.danis@collabora.com \
--to=frederic.danis@collabora.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