bass: Register cp handler for Add Source cmd
authorIulia Tanasescu <iulia.tanasescu@nxp.com>
Thu, 29 Aug 2024 12:49:10 +0000 (15:49 +0300)
committerWootak Jung <wootak.jung@samsung.com>
Thu, 20 Feb 2025 07:43:22 +0000 (16:43 +0900)
This registers a control point handler with shared/bass, for each
eastablished BASS session. For now, only the Add Source opcode is
handled.

Using the parameters provided from shared/bass, a device
is created for the Broadcaster address. The device is then
probed with BAP, where long-lived PA sync will be established.
After parsing the BASE, transports are created for each BIS,
as if the Broadcast Sink scanned the Broadacaster autonomously.

Below is a bluetoothctl log which shows a Scan Delegator starting
to advertise, connecting to a Broadcast Assistant, receiving the
Add Source command for a Broadcaster streaming one BIS, creating
a device for the Broadcaster and then creating a transport for
the BIS:

client/bluetoothctl
[bluetooth]# endpoint.register 00001851-0000-1000-8000-00805f9b34fb 0x06
[/local/endpoint/ep0] Auto Accept (yes/no): y
[/local/endpoint/ep0] Max Transports (auto/value): a
[/local/endpoint/ep0] Locations: 1
[/local/endpoint/ep0] Supported Context (value): 1
[bluetooth]# Endpoint /local/endpoint/ep0 registered
[bluetooth]# advertise on
[bluetooth]# [NEW] Device 00:60:37:31:7E:3F 00-60-37-31-7E-3F
[00-60-37-31-7E-3F]# [NEW] Device 03:E2:C0:11:57:DA 03-E2-C0-11-57-DA
[00-60-37-31-7E-3F]# [NEW] Transport
    /org/bluez/hci1/dev_03_E2_C0_11_57_DA/bis1/fd0

The btmon log below shows the GATT write command with the Add Source
opcode, which was received from the Broadcast Assistant. It also
shows the long-lived PA sync performed by BAP:

> ACL Data RX: Handle 0 flags 0x01 dlen 1
      ATT: Write Command (0x52) len 23
        Handle: 0x0040 Type: Broadcast Audio Scan Control Point (0x2bc7)
          Data[21]: 0201da5711c0e203001a2d5602ffff010100000000
            Opcode: Add Source (0x02)
            Source_Address_Type: 1
            Source_Address: 03:E2:C0:11:57:DA
            Source_Adv_SID: 0
            Broadcast_ID: 0x562d1a
            PA_Sync_State: Synchronize to PA - PAST not available
            PA_Interval: 0xffff
            Num_Subgroups: 1
            Subgroup #0:
              BIS_Sync State: 0x00000001
< HCI Command: LE Periodic Advertising Create Sync (0x08|0x0044)
        Options: 0x0000
        Use advertising SID, Advertiser Address Type and address
        Reporting initially enabled
        SID: 0x00
        Adv address type: Random (0x01)
        Adv address: 03:E2:C0:11:57:DA (Non-Resolvable)
        Skip: 0x0000
        Sync timeout: 20000 msec (0x07d0)
        Sync CTE type: 0x0000
> HCI Event: Command Status (0x0f) plen 4
      LE Periodic Advertising Create Sync (0x08|0x0044) ncmd 1
        Status: Success (0x00)
> HCI Event: LE Meta Event (0x3e) plen 16
      LE Periodic Advertising Sync Established (0x0e)
        Status: Success (0x00)
        Sync handle: 0
        Advertising SID: 0x00
        Advertiser address type: Random (0x01)
        Advertiser address: 03:E2:C0:11:57:DA (Non-Resolvable)
        Advertiser PHY: LE 2M (0x02)
        Periodic advertising interval: 10.00 msec (0x0008)
        Advertiser clock accuracy: 0x07
> HCI Event: LE Meta Event (0x3e) plen 42
      LE Periodic Advertising Report (0x0f)
        Sync handle: 0
        TX power: 127 dbm (0x7f)
        RSSI: -64 dBm (0xc0)
        CTE Type: No Constant Tone Extension (0xff)
        Data status: Complete
        Data length: 0x22
        Service Data: Basic Audio Announcement (0x1851)
          Presetation Delay: 40000
          Number of Subgroups: 1
            Subgroup #0:
            Number of BIS(s): 1
            Codec: LC3 (0x06)
            Codec Specific Configuration: #0: len 0x02 type 0x01
            Codec Specific Configuration: Sampling Frequency: 16 Khz
            Codec Specific Configuration: #1: len 0x02 type 0x02
            Codec Specific Configuration: Frame Duration: 10 ms (0x01)
            Codec Specific Configuration: #2: len 0x03 type 0x04
            Codec Specific Configuration: Frame Length: 40 (0x0028)
            Codec Specific Configuration: #3: len 0x05 type 0x03
            Codec Specific Configuration: Location: 0x00000001
            Codec Specific Configuration: Location: Front Left
              BIS #0:
              Index: 1
> HCI Event: LE Meta Event (0x3e) plen 20
      LE Broadcast Isochronous Group Info Advertising Report (0x22)
        Sync Handle: 0x0000
        Number BIS: 1
        NSE: 3
        ISO Interval: 10.00 msec (0x0008)
        BN: 1
        PTO: 1
        IRC: 3
        Maximum PDU: 40
        SDU Interval: 10000 us (0x002710)
        Maximum SDU: 40
        PHY: LE 2M (0x02)
        Framing: Unframed (0x00)
        Encryption: 0x00

Signed-off-by: Anuj Jain <anuj01.jain@samsung.com>
profiles/audio/bass.c

index c7c9b423ea760bbe101587036ed991043d57c720..ed833cb2cae2de034d28e7ada16aca2c42fba2b1 100644 (file)
@@ -52,6 +52,7 @@
 #include "bap.h"
 
 #define BASS_UUID_STR "0000184f-0000-1000-8000-00805f9b34fb"
+#define BCAAS_UUID_STR "00001852-0000-1000-8000-00805f9b34fb"
 
 #define MEDIA_ASSISTANT_INTERFACE "org.bluez.MediaAssistant1"
 
@@ -80,6 +81,7 @@ struct bass_data {
        struct btd_service *service;
        struct bt_bass *bass;
        unsigned int src_id;
+       unsigned int cp_id;
 };
 
 struct bass_assistant {
@@ -95,8 +97,14 @@ struct bass_assistant {
        char *path;
 };
 
+struct bass_delegator {
+       struct btd_device *device;      /* Broadcast source device */
+       struct bt_bcast_src *src;
+};
+
 static struct queue *sessions;
 static struct queue *assistants;
+static struct queue *delegators;
 
 static const char *state2str(enum assistant_state state);
 
@@ -580,6 +588,7 @@ static void bass_data_free(struct bass_data *data)
        }
 
        bt_bass_src_unregister(data->bass, data->src_id);
+       bt_bass_cp_handler_unregister(data->bass, data->cp_id);
 
        bt_bass_unref(data->bass);
 
@@ -625,6 +634,70 @@ static void bass_detached(struct bt_bass *bass, void *user_data)
        bass_data_remove(data);
 }
 
+static int handle_add_src_req(struct bt_bcast_src *bcast_src,
+                       struct bt_bass_add_src_params *params,
+                       struct bass_data *data)
+{
+       struct btd_adapter *adapter = device_get_adapter(data->device);
+       struct btd_device *device;
+       struct bass_delegator *dg;
+
+       /* Create device for Broadcast Source using the parameters
+        * provided by Broadcast Assistant.
+        */
+       device = btd_adapter_get_device(adapter, &params->addr,
+                                               params->addr_type);
+       if (!device) {
+               DBG("Unable to get device");
+               return -EINVAL;
+       }
+
+       DBG("device %p", device);
+
+       /* Probe Broadcast Source, if it has not already been
+        * autonomously probed inside BAP.
+        */
+       if (!btd_device_get_service(device, BCAAS_UUID_STR))
+               goto probe;
+
+       return 0;
+
+probe:
+       dg = new0(struct bass_delegator, 1);
+       if (!dg)
+               return -ENOMEM;
+
+       dg->device = device;
+       dg->src = bcast_src;
+
+       if (!delegators)
+               delegators = queue_new();
+
+       queue_push_tail(delegators, dg);
+
+       DBG("delegator %p", dg);
+
+       /* Probe device with BAP. */
+       bap_scan_delegator_probe(device);
+
+       return 0;
+}
+
+static int cp_handler(struct bt_bcast_src *bcast_src, uint8_t op, void *params,
+               void *user_data)
+{
+       struct bass_data *data = user_data;
+       int err = 0;
+
+       switch (op) {
+       case BT_BASS_ADD_SRC:
+               err = handle_add_src_req(bcast_src, params, data);
+               break;
+       }
+
+       return err;
+}
+
 static void bass_attached(struct bt_bass *bass, void *user_data)
 {
        struct bass_data *data;
@@ -650,6 +723,9 @@ static void bass_attached(struct bt_bass *bass, void *user_data)
        data = bass_data_new(device);
        data->bass = bass;
 
+       data->cp_id = bt_bass_cp_handler_register(data->bass,
+                       cp_handler, NULL, data);
+
        bass_data_add(data);
 }
 
@@ -778,6 +854,9 @@ static int bass_probe(struct btd_service *service)
        data->src_id = bt_bass_src_register(data->bass, bass_src_changed,
                                                data, NULL);
 
+       data->cp_id = bt_bass_cp_handler_register(data->bass,
+                       cp_handler, NULL, data);
+
        return 0;
 }