diff mbox series

[BlueZ,06/14] bass: Register cp handler for Add Source cmd

Message ID 20240821145602.92083-7-iulia.tanasescu@nxp.com
State Superseded
Headers show
Series Add Scan Delegator support for Add Source op | expand

Commit Message

Iulia Tanasescu Aug. 21, 2024, 2:55 p.m. UTC
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 BCAA service UUID is
then added to this device and the service is probed inside BAP, as
if the Broadcast Sink scanned the Broadcaster device autonomously.
The BAP plugin will then perform short-lived PA sync and it will
create streams for each BIS found inside the BASE.

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 short-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
---
 profiles/audio/bass.c | 81 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)
diff mbox series

Patch

diff --git a/profiles/audio/bass.c b/profiles/audio/bass.c
index b3740f64e..5aadb0dc8 100644
--- a/profiles/audio/bass.c
+++ b/profiles/audio/bass.c
@@ -54,6 +54,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"
 
@@ -82,6 +83,7 @@  struct bass_data {
 	struct btd_service *service;
 	struct bt_bass *bass;
 	unsigned int src_id;
+	unsigned int cp_id;
 };
 
 struct bass_assistant {
@@ -97,8 +99,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);
 
@@ -582,6 +590,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);
 
@@ -627,6 +636,72 @@  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);
+
+	/* Add Broadcast Audio Announcement Service UUID
+	 * to device and probe service inside BAP.
+	 */
+	btd_device_add_uuid(device, BCAAS_UUID_STR);
+
+	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;
@@ -652,6 +727,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);
 }
 
@@ -780,6 +858,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;
 }