client/player: Add broadcast sink endpoint
authorClaudia Draghicescu <claudia.rosu@nxp.com>
Tue, 8 Aug 2023 11:50:34 +0000 (14:50 +0300)
committerAyush Garg <ayush.garg@samsung.com>
Fri, 5 Jan 2024 13:34:03 +0000 (19:04 +0530)
Added support for broadcast sink registration using the 0x1851 UUID.
Added support for remote endpoint creation when a broadcast source
is discovered.
Added support for creating a local endpoint when the broadcast sink
endpoint was registered from an external application (Pipewire).
To test this feature use the following commands:

[bluetooth]# endpoint.register 00001851-0000-1000-8000-00805f9b34fb 0x06
[bluetooth]# scan on
[NEW] Endpoint /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/pac_bcast0
[bluetooth]# endpoint.config
/org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/pac_bcast0
/local/endpoint/ep0 16_2_1

client/player.c

index 136ef3034df5141989f8ab6a46b6d800be80337f..092348c6b64c4038868d411a07cabcbd92c41b2e 100644 (file)
@@ -1182,6 +1182,17 @@ static const struct capabilities {
        CODEC_CAPABILITIES(BCAA_SERVICE_UUID, LC3_ID,
                                        LC3_DATA(LC3_FREQ_ANY, LC3_DURATION_ANY,
                                                3u, 30, 240)),
+
+       /* Broadcast LC3 Sink:
+        *
+        * Frequencies: 8Khz 11Khz 16Khz 22Khz 24Khz 32Khz 44.1Khz 48Khz
+        * Duration: 7.5 ms 10 ms
+        * Channel count: 3
+        * Frame length: 30-240
+        */
+       CODEC_CAPABILITIES(BAA_SERVICE_UUID, LC3_ID,
+                                       LC3_DATA(LC3_FREQ_ANY, LC3_DURATION_ANY,
+                                               3u, 30, 240)),
 };
 
 struct codec_qos {
@@ -1464,6 +1475,7 @@ static struct preset {
        PRESET(PAC_SINK_UUID, LC3_ID, lc3_presets, 3),
        PRESET(PAC_SOURCE_UUID, LC3_ID, lc3_presets, 3),
        PRESET(BCAA_SERVICE_UUID,  LC3_ID, lc3_presets, 3),
+       PRESET(BAA_SERVICE_UUID,  LC3_ID, lc3_presets, 3),
 };
 
 static void parse_vendor_codec(const char *codec, uint16_t *vid, uint16_t *cid)
@@ -2284,6 +2296,9 @@ static void register_endpoint_setup(DBusMessageIter *iter, void *user_data)
                bt_shell_hexdump(ep->meta->iov_base, ep->meta->iov_len);
        }
 
+       g_dbus_dict_append_entry(&dict, "Broadcast", DBUS_TYPE_BOOLEAN,
+                               &ep->broadcast);
+
        dbus_message_iter_close_container(iter, &dict);
 }
 
@@ -2454,7 +2469,8 @@ static void endpoint_auto_accept(const char *input, void *user_data)
 {
        struct endpoint *ep = user_data;
 
-       if (!strcmp(ep->uuid, BCAA_SERVICE_UUID)) {
+       if (!strcmp(ep->uuid, BCAA_SERVICE_UUID) ||
+               !strcmp(ep->uuid, BAA_SERVICE_UUID)) {
                ep->broadcast = true;
        } else {
                ep->broadcast = false;
@@ -2727,13 +2743,20 @@ static void endpoint_config(const char *input, void *user_data)
        endpoint_set_config(cfg);
 }
 
+static struct endpoint *endpoint_new(const struct capabilities *cap);
+
 static void cmd_config_endpoint(int argc, char *argv[])
 {
        struct endpoint_config *cfg;
        const struct codec_preset *preset;
+       const struct capabilities *cap;
+       char *uuid;
+       uint8_t codec_id;
+       bool broadcast = false;
 
        cfg = new0(struct endpoint_config, 1);
 
+       /* Search for the remote endpoint name on DBUS */
        cfg->proxy = g_dbus_proxy_lookup(endpoints, NULL, argv[1],
                                                BLUEZ_MEDIA_ENDPOINT_INTERFACE);
        if (!cfg->proxy) {
@@ -2741,16 +2764,36 @@ static void cmd_config_endpoint(int argc, char *argv[])
                goto fail;
        }
 
+       /* Search for the local endpoint */
        cfg->ep = endpoint_find(argv[2]);
        if (!cfg->ep) {
-               bt_shell_printf("Local Endpoint %s not found\n", argv[2]);
-               goto fail;
+
+               /* When the local endpoint was not found either we received
+                * UUID, or the provided local endpoint is not available
+                */
+               uuid = argv[2];
+               codec_id = strtol(argv[3], NULL, 0);
+               cap = find_capabilities(uuid, codec_id);
+               if (cap) {
+                       broadcast = true;
+                       cfg->ep = endpoint_new(cap);
+                       cfg->ep->preset = find_presets_name(uuid, argv[3]);
+                       if (!cfg->ep->preset)
+                               bt_shell_printf("Preset not found\n");
+               } else {
+                       bt_shell_printf("Local Endpoint %s,"
+                               "or capabilities not found\n", uuid);
+                       goto fail;
+               }
        }
 
-       if (argc > 3) {
-               preset = preset_find_name(cfg->ep->preset, argv[3]);
+       if (((broadcast == false) && (argc > 3)) ||
+               ((broadcast == true) && (argc > 4))) {
+               char *preset_name = (broadcast == false)?argv[3]:argv[4];
+
+               preset = preset_find_name(cfg->ep->preset, preset_name);
                if (!preset) {
-                       bt_shell_printf("Preset %s not found\n", argv[3]);
+                       bt_shell_printf("Preset %s not found\n", preset_name);
                        goto fail;
                }
 
@@ -3171,7 +3214,8 @@ static const struct bt_shell_menu endpoint_menu = {
        { "unregister",   "<UUID/object>", cmd_unregister_endpoint,
                                                "Register Endpoint",
                                                local_endpoint_generator },
-       { "config",       "<endpoint> <local endpoint> [preset]",
+       { "config",
+               "<endpoint> [local endpoint/UUID] [preset/codec id] [preset]",
                                                cmd_config_endpoint,
                                                "Configure Endpoint",
                                                endpoint_generator },
@@ -3188,7 +3232,8 @@ static struct endpoint *endpoint_new(const struct capabilities *cap)
 
        ep = new0(struct endpoint, 1);
        ep->uuid = g_strdup(cap->uuid);
-       ep->broadcast = strcmp(cap->uuid, BCAA_SERVICE_UUID) ? false : true;
+       ep->broadcast = (strcmp(cap->uuid, BCAA_SERVICE_UUID) &&
+                       strcmp(cap->uuid, BAA_SERVICE_UUID)) ? false : true;
        ep->codec = cap->codec_id;
        ep->path = g_strdup_printf("%s/ep%u", BLUEZ_MEDIA_ENDPOINT_PATH,
                                        g_list_length(local_endpoints));