diff --git a/bumble/profiles/bap.py b/bumble/profiles/bap.py index dd57f01c..b54ad1dc 100644 --- a/bumble/profiles/bap.py +++ b/bumble/profiles/bap.py @@ -24,8 +24,9 @@ import enum import struct import functools import logging -from typing import Optional, List, Union, Type, Dict, Any, Tuple, cast +from typing import Optional, List, Union, Type, Dict, Any, Tuple +from bumble import core from bumble import colors from bumble import device from bumble import hci @@ -228,6 +229,14 @@ class SupportedFrameDuration(enum.IntFlag): DURATION_10000_US_PREFERRED = 0b0010 +class AnnouncementType(enum.IntEnum): + '''Basic Audio Profile, 3.5.3. Additional Audio Stream Control Service requirements''' + + # fmt: off + GENERAL = 0x00 + TARGETED = 0x01 + + # ----------------------------------------------------------------------------- # ASE Operations # ----------------------------------------------------------------------------- @@ -453,6 +462,34 @@ class AudioRole(enum.IntEnum): SOURCE = hci.HCI_LE_Setup_ISO_Data_Path_Command.Direction.HOST_TO_CONTROLLER +@dataclasses.dataclass +class UnicastServerAdvertisingData: + """Advertising Data for ASCS.""" + + announcement_type: AnnouncementType = AnnouncementType.TARGETED + available_audio_contexts: ContextType = ContextType.MEDIA + metadata: bytes = b'' + + def __bytes__(self) -> bytes: + return bytes( + core.AdvertisingData( + [ + ( + core.AdvertisingData.SERVICE_DATA_16_BIT_UUID, + struct.pack( + '<2sBIB', + gatt.GATT_AUDIO_STREAM_CONTROL_SERVICE.to_bytes(), + self.announcement_type, + self.available_audio_contexts, + len(self.metadata), + ) + + self.metadata, + ) + ] + ) + ) + + # ----------------------------------------------------------------------------- # Utils # ----------------------------------------------------------------------------- diff --git a/examples/run_unicast_server.py b/examples/run_unicast_server.py index 4fac1d68..60d2f4ae 100644 --- a/examples/run_unicast_server.py +++ b/examples/run_unicast_server.py @@ -22,14 +22,14 @@ import os import struct import secrets from bumble.core import AdvertisingData -from bumble.device import Device, CisLink, AdvertisingParameters +from bumble.device import Device, CisLink from bumble.hci import ( CodecID, CodingFormat, - OwnAddressType, HCI_IsoDataPacket, ) from bumble.profiles.bap import ( + UnicastServerAdvertisingData, CodecSpecificCapabilities, ContextType, AudioLocation, @@ -141,6 +141,7 @@ async def main() -> None: ) ) + csis.get_advertising_data() + + bytes(UnicastServerAdvertisingData()) ) subprocess = await asyncio.create_subprocess_shell( f'dlc3 | ffplay pipe:0', @@ -178,7 +179,7 @@ async def main() -> None: device.once('cis_establishment', on_cis) - advertising_set = await device.create_advertising_set( + await device.create_advertising_set( advertising_data=advertising_data, ) diff --git a/examples/run_vcp_renderer.py b/examples/run_vcp_renderer.py index b695956b..9da0bbe3 100644 --- a/examples/run_vcp_renderer.py +++ b/examples/run_vcp_renderer.py @@ -31,6 +31,7 @@ from bumble.hci import ( OwnAddressType, ) from bumble.profiles.bap import ( + UnicastServerAdvertisingData, CodecSpecificCapabilities, ContextType, AudioLocation, @@ -151,6 +152,7 @@ async def main() -> None: ) ) + csis.get_advertising_data() + + bytes(UnicastServerAdvertisingData()) ) await device.create_advertising_set(