This registers a BAP stream state changed callback inside BASS, to monitor the state of BAP streams created by the Scan Delegator and to notify the peer Broadcast Assistants about updates. The bluetoothctl log below shows a Scan Delegator creating a media transport for a BIS added by a Broadcast Assistant through the Add Source operation. The transport is then acquired and then released: 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 [00-60-37-31-7E-3F]# Endpoint: SetConfiguration [00-60-37-31-7E-3F]# Transport /org/bluez/hci1/dev_03_E2_C0_11_57_DA/bis1/fd0 [00-60-37-31-7E-3F]# Properties.Device: /org/bluez/hci1/dev_03_E2_C0_11_57_DA [00-60-37-31-7E-3F]# Auto Accepting... [00-60-37-31-7E-3F]# transport.select /org/bluez/hci1/dev_03_E2_C0_11_57_DA/bis1/fd0 [00-60-37-31-7E-3F]# [CHG] Transport /org/bluez/hci1/dev_03_E2_C0_11_57_DA/bis1/fd0 State: broadcasting [00-60-37-31-7E-3F]# transport.acquire /org/bluez/hci1/dev_03_E2_C0_11_57_DA/bis1/fd0 auto acquiring... Transport /org/bluez/hci1/dev_03_E2_C0_11_57_DA/bis1/fd0 acquiring [00-60-37-31-7E-3F]# Transport /org/bluez/hci1/dev_03_E2_C0_11_57_DA/bis1/fd0 acquiring complete [00-60-37-31-7E-3F]# Acquire successful: fd 8 MTU 40:0 [00-60-37-31-7E-3F]# [CHG] Transport /org/bluez/hci1/dev_03_E2_C0_11_57_DA/bis1/fd0 State: active [00-60-37-31-7E-3F]# transport.release /org/bluez/hci1/dev_03_E2_C0_11_57_DA/bis1/fd0 [00-60-37-31-7E-3F]# Transport fd disconnected [00-60-37-31-7E-3F]# [CHG] Transport /org/bluez/hci1/dev_03_E2_C0_11_57_DA/bis1/fd0 State: idle [00-60-37-31-7E-3F]# Release successful The btmon log below shows the Scan Delegator notifying the peer each time the state of the stream changes: > 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 bluetoothd[4636]: < ACL Data TX: Handle 0 flags 0x00 dlen 29 ATT: Handle Multiple Value Notification (0x23) len 24 Length: 0x0014 Handle: 0x003a Type: Broadcast Receive State (0x2bc8) Data[20]: 0101da5711c0e203001a2d560200010000000000 Source_ID: 1 Source_Address_Type: 1 Source_Address: 03:E2:C0:11:57:DA Source_Adv_SID: 0 Broadcast_ID: 0x562d1a PA_Sync_State: Synchronized to PA BIG_Encryption: Not encrypted Num_Subgroups: 1 Subgroup #0: BIS_Sync State: 0x00000000 < HCI Command: LE Broadcast Isochronous Group Create Sync (0x08|0x006b) BIG Handle: 0x00 BIG Sync Handle: 0x0000 Encryption: Unencrypted (0x00) Broadcast Code[16]: 00000000000000000000000000000000 Maximum Number Subevents: 0x00 Timeout: 20000 ms (0x07d0) Number of BIS: 1 BIS ID: 0x01 > HCI Event: Command Status (0x0f) plen 4 LE Broadcast Isochronous Group Create Sync (0x08|0x006b) ncmd 1 Status: Success (0x00 > HCI Event: LE Meta Event (0x3e) plen 17 LE Broadcast Isochronous Group Sync Estabilished (0x1d) Status: Success (0x00) BIG Handle: 0x00 Transport Latency: 912 us (0x000390) NSE: 3 BN: 1 PTO: 1 IRC: 3 Maximum PDU: 40 ISO Interval: 10.00 msec (0x0008) Connection Handle #0: 10 < HCI Command: LE Setup Isochronous Data Path (0x08|0x006e) plen 13 Handle: 10 Data Path Direction: Output (Controller to Host) (0x01) Data Path: HCI (0x00) Coding Format: Transparent (0x03) Company Codec ID: Ericsson Technology Licensing (0) Vendor Codec ID: 0 Controller Delay: 0 us (0x000000) Codec Configuration Length: 0 Codec Configuration[0]: > HCI Event: Command Complete (0x0e) plen 6 LE Setup Isochronous Data Path (0x08|0x006e) ncmd 1 Status: Success (0x00) Handle: 10 bluetoothd[4636]: < ACL Data TX: Handle 0 flags 0x00 dlen 29 ATT: Handle Multiple Value Notification (0x23) len 24 Length: 0x0014 Handle: 0x003a Type: Broadcast Receive State (0x2bc8) Data[20]: 0101da5711c0e203001a2d560200010100000000 Source_ID: 1 Source_Address_Type: 1 Source_Address: 03:E2:C0:11:57:DA Source_Adv_SID: 0 Broadcast_ID: 0x562d1a PA_Sync_State: Synchronized to PA BIG_Encryption: Not encrypted Num_Subgroups: 1 Subgroup #0: BIS_Sync State: 0x00000001 bluetoothd[4636]: < ACL Data TX: Handle 0 flags 0x00 dlen 29 ATT: Handle Multiple Value Notification (0x23) len 24 Length: 0x0014 Handle: 0x003a Type: Broadcast Receive State (0x2bc8) Data[20]: 0101da5711c0e203001a2d560200010000000000 Source_ID: 1 Source_Address_Type: 1 Source_Address: 03:E2:C0:11:57:DA Source_Adv_SID: 0 Broadcast_ID: 0x562d1a PA_Sync_State: Synchronized to PA BIG_Encryption: Not encrypted Num_Subgroups: 1 Subgroup #0: BIS_Sync State: 0x00000000 < HCI Command: LE Broadcast Isochronous Group Terminate Sync (0x08|0x006c) BIG Handle: 0x00 > HCI Event: Command Complete (0x0e) plen 5 LE Broadcast Isochronous Group Terminate Sync (0x08|0x006c) ncmd 1 Status: Success (0x00) --- profiles/audio/bass.c | 58 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/profiles/audio/bass.c b/profiles/audio/bass.c index 22e8d1c9b..47445b4b5 100644 --- a/profiles/audio/bass.c +++ b/profiles/audio/bass.c @@ -103,6 +103,7 @@ struct bass_delegator { struct btd_device *device; /* Broadcast source device */ struct bt_bcast_src *src; struct bt_bap *bap; + unsigned int state_id; }; static struct queue *sessions; @@ -124,6 +125,54 @@ static bool delegator_match_device(const void *data, const void *match_data) return dg->device == device; } +static void bap_state_changed(struct bt_bap_stream *stream, uint8_t old_state, + uint8_t new_state, void *user_data) +{ + struct bass_delegator *dg = user_data; + int bis; + char *path = bt_bap_stream_get_user_data(stream); + struct bt_bap *bap = bt_bap_stream_get_session(stream); + const char *strbis; + int err; + + if (dg->bap != bap) + return; + + strbis = strstr(path, "/bis"); + if (strbis == NULL) { + DBG("bis index cannot be found"); + return; + } + + err = sscanf(strbis, "/bis%d", &bis); + if (err < 0) { + DBG("sscanf error"); + return; + } + + DBG("stream %p: %s(%u) -> %s(%u)", stream, + bt_bap_stream_statestr(old_state), old_state, + bt_bap_stream_statestr(new_state), new_state); + + switch (new_state) { + case BT_BAP_STREAM_STATE_STREAMING: + /* BAP stream was started. Mark BIS index as synced inside the + * Broadcast Receive State characteristic and notify peers about + * the update. + */ + bt_bass_set_bis_sync(dg->src, bis); + break; + case BT_BAP_STREAM_STATE_CONFIG: + if (old_state == BT_BAP_STREAM_STATE_STREAMING) + /* BAP stream was disabled. Clear BIS index from the + * bitmask inside the Broadcast Receive State + * characteristic and notify peers about the update. + */ + bt_bass_clear_bis_sync(dg->src, bis); + break; + } +} + bool bass_bcast_probe(struct btd_device *device, struct bt_bap *bap) { struct bass_delegator *dg; @@ -142,6 +191,12 @@ bool bass_bcast_probe(struct btd_device *device, struct bt_bap *bap) if (bt_bass_set_pa_sync(dg->src, BT_BASS_SYNCHRONIZED_TO_PA)) DBG("Failed to update Broadcast Receive State characteristic"); + /* Register BAP stream state changed callback, to keep up to + * date with BIG/PA sync state. + */ + dg->state_id = bt_bap_state_register(bap, bap_state_changed, + NULL, dg, NULL); + return true; } @@ -161,6 +216,9 @@ bool bass_bcast_remove(struct btd_device *device) if (bt_bass_set_pa_sync(dg->src, BT_BASS_NOT_SYNCHRONIZED_TO_PA)) DBG("Failed to update Broadcast Receive State characteristic"); + /* Unregister BAP stream state changed callback. */ + bt_bap_state_unregister(dg->bap, dg->state_id); + free(dg); return true; -- 2.39.2