client/player: Add support for Metadata in BAP Profile
authorAbhay Maheta <abhay.maheshbhai.maheta@intel.com>
Thu, 29 Dec 2022 15:53:05 +0000 (21:23 +0530)
committerAyush Garg <ayush.garg@samsung.com>
Fri, 5 Jan 2024 10:41:34 +0000 (16:11 +0530)
This adds support for Metadata in BAP profile.
In order to register zero Metadata, 0 shall be
entered when prompted.

[bluetooth]# endpoint.register 00002bc9-0000-1000-8000-00805f9b34fb 0x06
[/local/endpoint/ep0] Enter Metadata (value/no): n
[/local/endpoint/ep0] Auto Accept (yes/no): y
[/local/endpoint/ep0] CIG (auto/value): a
[/local/endpoint/ep0] CIS (auto/value): a
Capabilities:
  03 01 ff 00 02 02 03 02 03 03 05 04 1e 00 f0 00  ................
Endpoint /local/endpoint/ep0 registered

client/player.c

index 3894ebf..c936a6e 100644 (file)
@@ -69,6 +69,7 @@ struct endpoint {
        uint16_t cid;
        uint16_t vid;
        struct iovec *caps;
+       struct iovec *meta;
        bool auto_accept;
        bool acquiring;
        uint8_t cig;
@@ -1581,6 +1582,7 @@ struct endpoint_config {
        GDBusProxy *proxy;
        struct endpoint *ep;
        struct iovec *caps;
+       struct iovec *meta;
        uint8_t target_latency;
        const struct codec_qos *qos;
 };
@@ -1591,6 +1593,7 @@ static void append_properties(DBusMessageIter *iter,
        DBusMessageIter dict;
        struct codec_qos *qos = (void *)cfg->qos;
        const char *key = "Capabilities";
+       const char *meta = "Metadata";
 
        dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{sv}", &dict);
 
@@ -1601,6 +1604,15 @@ static void append_properties(DBusMessageIter *iter,
                                        DBUS_TYPE_BYTE, &cfg->caps->iov_base,
                                        cfg->caps->iov_len);
 
+       if (cfg->meta->iov_len) {
+               g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING, &meta,
+                               DBUS_TYPE_BYTE, &cfg->meta->iov_base,
+                               cfg->meta->iov_len);
+
+               bt_shell_printf("Metadata:\n");
+               bt_shell_hexdump(cfg->meta->iov_base, cfg->meta->iov_len);
+       }
+
        if (!qos)
                goto done;
 
@@ -1698,6 +1710,9 @@ static DBusMessage *endpoint_select_properties_reply(struct endpoint *ep,
        iov_append(&cfg->caps, preset->data.iov_base, preset->data.iov_len);
        cfg->target_latency = preset->target_latency;
 
+       /* Copy metadata */
+       iov_append(&cfg->meta, cfg->ep->meta->iov_base, cfg->ep->meta->iov_len);
+
        if (preset->qos.phy)
                /* Set QoS parameters */
                cfg->qos = &preset->qos;
@@ -1846,6 +1861,12 @@ static void endpoint_free(void *data)
                g_free(ep->caps);
        }
 
+       if (ep->meta) {
+               if (ep->meta->iov_base)
+                       g_free(ep->meta->iov_base);
+               g_free(ep->meta);
+       }
+
        if (ep->msg)
                dbus_message_unref(ep->msg);
 
@@ -1916,10 +1937,38 @@ static gboolean endpoint_vendor_exists(const GDBusPropertyTable *property,
        return ep->cid && ep->vid;
 }
 
+static gboolean endpoint_get_metadata(const GDBusPropertyTable *property,
+                                       DBusMessageIter *iter, void *data)
+{
+       struct endpoint *ep = data;
+       DBusMessageIter array;
+
+       dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+                               DBUS_TYPE_BYTE_AS_STRING, &array);
+
+       dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
+                               &ep->meta->iov_base,
+                               ep->meta->iov_len);
+
+       dbus_message_iter_close_container(iter, &array);
+
+       return TRUE;
+}
+
+static gboolean endpoint_metadata_exists(const GDBusPropertyTable *property,
+                                                       void *data)
+{
+       struct endpoint *ep = data;
+
+       return ep->meta ? TRUE : FALSE;
+}
+
 static const GDBusPropertyTable endpoint_properties[] = {
        { "UUID", "s", endpoint_get_uuid, NULL, NULL },
        { "Codec", "y", endpoint_get_codec, NULL, NULL },
        { "Capabilities", "ay", endpoint_get_capabilities, NULL, NULL },
+       { "Metadata", "ay", endpoint_get_metadata, NULL,
+                               endpoint_metadata_exists },
        { "Vendor", "u", endpoint_get_vendor, NULL, endpoint_vendor_exists },
        { }
 };
@@ -1929,6 +1978,7 @@ static void register_endpoint_setup(DBusMessageIter *iter, void *user_data)
        struct endpoint *ep = user_data;
        DBusMessageIter dict;
        const char *key = "Capabilities";
+       const char *meta = "Metadata";
 
        dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &ep->path);
 
@@ -1954,6 +2004,15 @@ static void register_endpoint_setup(DBusMessageIter *iter, void *user_data)
                bt_shell_hexdump(ep->caps->iov_base, ep->caps->iov_len);
        }
 
+       if (ep->meta) {
+               g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING, &meta,
+                               DBUS_TYPE_BYTE, &ep->meta->iov_base,
+                               ep->meta->iov_len);
+
+               bt_shell_printf("Metadata:\n");
+               bt_shell_hexdump(ep->meta->iov_base, ep->meta->iov_len);
+       }
+
        dbus_message_iter_close_container(iter, &dict);
 }
 
@@ -2071,6 +2130,30 @@ static void endpoint_auto_accept(const char *input, void *user_data)
        bt_shell_prompt_input(ep->path, "CIG (auto/value):", endpoint_cig, ep);
 }
 
+static void endpoint_set_metadata(const char *input, void *user_data)
+{
+       struct endpoint *ep = user_data;
+
+       if (!strcasecmp(input, "n") || !strcasecmp(input, "no")) {
+               free(ep->meta->iov_base);
+               ep->meta = NULL;
+               goto done;
+       }
+
+       if (!ep->meta)
+               ep->meta = g_new0(struct iovec, 1);
+
+       ep->meta->iov_base = str2bytearray((char *) input, &ep->meta->iov_len);
+       if (!ep->meta->iov_base) {
+               free(ep->meta);
+               ep->meta = NULL;
+       }
+
+done:
+       bt_shell_prompt_input(ep->path, "Auto Accept (yes/no):",
+                                       endpoint_auto_accept, ep);
+}
+
 static void endpoint_set_capabilities(const char *input, void *user_data)
 {
        struct endpoint *ep = user_data;
@@ -2090,8 +2173,8 @@ static void endpoint_set_capabilities(const char *input, void *user_data)
                ep->caps->iov_len = 0x00;
        }
 
-       bt_shell_prompt_input(ep->path, "Auto Accept (yes/no):",
-                                               endpoint_auto_accept, ep);
+       bt_shell_prompt_input(ep->path, "Enter Metadata (value/no):",
+                                       endpoint_set_metadata, ep);
 }
 
 static char *uuid_generator(const char *text, int state)