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>
#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"
struct btd_service *service;
struct bt_bass *bass;
unsigned int src_id;
+ unsigned int cp_id;
};
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);
}
bt_bass_src_unregister(data->bass, data->src_id);
+ bt_bass_cp_handler_unregister(data->bass, data->cp_id);
bt_bass_unref(data->bass);
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, ¶ms->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;
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);
}
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;
}