• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA -
3  * www.ehima.com
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #pragma once
19 
20 #include <bluetooth/log.h>
21 
22 #include <array>
23 #include <bitset>
24 #include <map>
25 #include <optional>
26 #include <ostream>
27 #include <vector>
28 
29 #include "types/raw_address.h"
30 
31 namespace bluetooth {
32 namespace le_audio {
33 
34 enum class LeAudioHealthBasedAction {
35   NONE = 0,
36   DISABLE,
37   CONSIDER_DISABLING,
38   INACTIVATE_GROUP,
39 };
40 
41 inline std::ostream& operator<<(std::ostream& os, const LeAudioHealthBasedAction action) {
42   switch (action) {
43     case LeAudioHealthBasedAction::NONE:
44       os << "NONE";
45       break;
46     case LeAudioHealthBasedAction::DISABLE:
47       os << "DISABLE";
48       break;
49     case LeAudioHealthBasedAction::CONSIDER_DISABLING:
50       os << "CONSIDER_DISABLING";
51       break;
52     case LeAudioHealthBasedAction::INACTIVATE_GROUP:
53       os << "INACTIVATE_GROUP";
54       break;
55     default:
56       os << "UNKNOWN";
57       break;
58   }
59   return os;
60 }
61 
62 enum class ConnectionState { DISCONNECTED = 0, CONNECTING, CONNECTED, DISCONNECTING };
63 
64 enum class GroupStatus {
65   INACTIVE = 0,
66   ACTIVE,
67   TURNED_IDLE_DURING_CALL,
68 };
69 
70 enum class GroupStreamStatus {
71   IDLE = 0,
72   STREAMING,
73   RELEASING,
74   RELEASING_AUTONOMOUS,
75   SUSPENDING,
76   SUSPENDED,
77   CONFIGURED_AUTONOMOUS,
78   CONFIGURED_BY_USER,
79   DESTROYED,
80 };
81 
82 inline std::ostream& operator<<(std::ostream& os, const GroupStreamStatus& state) {
83   switch (state) {
84     case GroupStreamStatus::IDLE:
85       os << "IDLE";
86       break;
87     case GroupStreamStatus::STREAMING:
88       os << "STREAMING";
89       break;
90     case GroupStreamStatus::RELEASING:
91       os << "RELEASING";
92       break;
93     case GroupStreamStatus::RELEASING_AUTONOMOUS:
94       os << "RELEASING_AUTONOMOUS";
95       break;
96     case GroupStreamStatus::SUSPENDING:
97       os << "SUSPENDING";
98       break;
99     case GroupStreamStatus::SUSPENDED:
100       os << "SUSPENDED";
101       break;
102     case GroupStreamStatus::CONFIGURED_AUTONOMOUS:
103       os << "CONFIGURED_AUTONOMOUS";
104       break;
105     case GroupStreamStatus::CONFIGURED_BY_USER:
106       os << "CONFIGURED_BY_USER";
107       break;
108     case GroupStreamStatus::DESTROYED:
109       os << "DESTROYED";
110       break;
111     default:
112       os << "UNKNOWN";
113       break;
114   }
115   return os;
116 }
117 
118 enum class GroupNodeStatus {
119   ADDED = 1,
120   REMOVED,
121 };
122 
123 enum class UnicastMonitorModeStatus {
124   STREAMING_REQUESTED = 0,
125   STREAMING,
126   STREAMING_SUSPENDED,
127   STREAMING_REQUESTED_NO_CONTEXT_VALIDATE,
128 };
129 
130 typedef enum {
131   LE_AUDIO_CODEC_INDEX_SOURCE_LC3 = 0,
132   LE_AUDIO_CODEC_INDEX_SOURCE_INVALID = 1000 * 1000,
133 } btle_audio_codec_index_t;
134 
135 typedef enum { QUALITY_STANDARD = 0, QUALITY_HIGH } btle_audio_quality_t;
136 
137 typedef enum {
138   LE_AUDIO_SAMPLE_RATE_INDEX_NONE = 0,
139   LE_AUDIO_SAMPLE_RATE_INDEX_8000HZ = 0x01 << 0,
140   LE_AUDIO_SAMPLE_RATE_INDEX_11025HZ = 0x01 << 1,
141   LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ = 0x01 << 2,
142   LE_AUDIO_SAMPLE_RATE_INDEX_22050HZ = 0x01 << 3,
143   LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ = 0x01 << 4,
144   LE_AUDIO_SAMPLE_RATE_INDEX_32000HZ = 0x01 << 5,
145   LE_AUDIO_SAMPLE_RATE_INDEX_44100HZ = 0x01 << 6,
146   LE_AUDIO_SAMPLE_RATE_INDEX_48000HZ = 0x01 << 7,
147   LE_AUDIO_SAMPLE_RATE_INDEX_88200HZ = 0x01 << 8,
148   LE_AUDIO_SAMPLE_RATE_INDEX_96000HZ = 0x01 << 9,
149   LE_AUDIO_SAMPLE_RATE_INDEX_176400HZ = 0x01 << 10,
150   LE_AUDIO_SAMPLE_RATE_INDEX_192000HZ = 0x01 << 11,
151   LE_AUDIO_SAMPLE_RATE_INDEX_384000HZ = 0x01 << 12
152 } btle_audio_sample_rate_index_t;
153 
154 typedef enum {
155   LE_AUDIO_BITS_PER_SAMPLE_INDEX_NONE = 0,
156   LE_AUDIO_BITS_PER_SAMPLE_INDEX_16 = 0x01 << 0,
157   LE_AUDIO_BITS_PER_SAMPLE_INDEX_24 = 0x01 << 1,
158   LE_AUDIO_BITS_PER_SAMPLE_INDEX_32 = 0x01 << 3
159 } btle_audio_bits_per_sample_index_t;
160 
161 typedef enum {
162   LE_AUDIO_CHANNEL_COUNT_INDEX_NONE = 0,
163   LE_AUDIO_CHANNEL_COUNT_INDEX_1 = 0x01 << 0,
164   LE_AUDIO_CHANNEL_COUNT_INDEX_2 = 0x01 << 1
165 } btle_audio_channel_count_index_t;
166 
167 typedef enum {
168   LE_AUDIO_FRAME_DURATION_INDEX_NONE = 0,
169   LE_AUDIO_FRAME_DURATION_INDEX_7500US = 0x01 << 0,
170   LE_AUDIO_FRAME_DURATION_INDEX_10000US = 0x01 << 1
171 } btle_audio_frame_duration_index_t;
172 
173 typedef struct btle_audio_codec_config {
174   btle_audio_codec_index_t codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_INVALID;
175   btle_audio_sample_rate_index_t sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_NONE;
176   btle_audio_bits_per_sample_index_t bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_NONE;
177   btle_audio_channel_count_index_t channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_NONE;
178   btle_audio_frame_duration_index_t frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_NONE;
179   uint8_t codec_frame_blocks_per_sdu = 0;
180   uint16_t octets_per_frame = 0;
181   int32_t codec_priority = 0;
182 
183   bool operator!=(const btle_audio_codec_config& other) const {
184     if (codec_type != other.codec_type) {
185       return true;
186     }
187     if (sample_rate != other.sample_rate) {
188       return true;
189     }
190     if (bits_per_sample != other.bits_per_sample) {
191       return true;
192     }
193     if (channel_count != other.channel_count) {
194       return true;
195     }
196     if (frame_duration != other.frame_duration) {
197       return true;
198     }
199     if (octets_per_frame != other.octets_per_frame) {
200       return true;
201     }
202     if (codec_priority != other.codec_priority) {
203       return true;
204     }
205     return false;
206   }
207   bool operator==(const btle_audio_codec_config& other) const { return !(*this != other); }
208 
ToStringbtle_audio_codec_config209   std::string ToString() const {
210     std::string codec_name_str;
211     std::string sample_rate_str;
212     std::string bits_per_sample_str;
213     std::string channel_count_str;
214     std::string frame_duration_str;
215     std::string octets_per_frame_str;
216     std::string codec_priority_str;
217 
218     switch (codec_type) {
219       case LE_AUDIO_CODEC_INDEX_SOURCE_LC3:
220         codec_name_str = "LC3";
221         break;
222       default:
223         codec_name_str = "Unknown LE codec " + std::to_string(codec_type);
224         break;
225     }
226 
227     switch (sample_rate) {
228       case LE_AUDIO_SAMPLE_RATE_INDEX_NONE:
229         sample_rate_str = "none";
230         break;
231       case LE_AUDIO_SAMPLE_RATE_INDEX_8000HZ:
232         sample_rate_str = "8000 hz";
233         break;
234       case LE_AUDIO_SAMPLE_RATE_INDEX_11025HZ:
235         sample_rate_str = "11025 hz";
236         break;
237       case LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ:
238         sample_rate_str = "16000 hz";
239         break;
240       case LE_AUDIO_SAMPLE_RATE_INDEX_22050HZ:
241         sample_rate_str = "22050 hz";
242         break;
243       case LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ:
244         sample_rate_str = "24000 hz";
245         break;
246       case LE_AUDIO_SAMPLE_RATE_INDEX_32000HZ:
247         sample_rate_str = "32000 hz";
248         break;
249       case LE_AUDIO_SAMPLE_RATE_INDEX_44100HZ:
250         sample_rate_str = "44100 hz";
251         break;
252       case LE_AUDIO_SAMPLE_RATE_INDEX_48000HZ:
253         sample_rate_str = "48000 hz";
254         break;
255       case LE_AUDIO_SAMPLE_RATE_INDEX_88200HZ:
256         sample_rate_str = "88200 hz";
257         break;
258       case LE_AUDIO_SAMPLE_RATE_INDEX_96000HZ:
259         sample_rate_str = "96000 hz";
260         break;
261       case LE_AUDIO_SAMPLE_RATE_INDEX_176400HZ:
262         sample_rate_str = "176400 hz";
263         break;
264       case LE_AUDIO_SAMPLE_RATE_INDEX_192000HZ:
265         sample_rate_str = "192000 hz";
266         break;
267       case LE_AUDIO_SAMPLE_RATE_INDEX_384000HZ:
268         sample_rate_str = "384000 hz";
269         break;
270       default:
271         sample_rate_str = "Unknown LE sample rate " + std::to_string(sample_rate);
272         break;
273     }
274 
275     switch (bits_per_sample) {
276       case LE_AUDIO_BITS_PER_SAMPLE_INDEX_NONE:
277         bits_per_sample_str = "none";
278         break;
279       case LE_AUDIO_BITS_PER_SAMPLE_INDEX_16:
280         bits_per_sample_str = "16";
281         break;
282       case LE_AUDIO_BITS_PER_SAMPLE_INDEX_24:
283         bits_per_sample_str = "24";
284         break;
285       case LE_AUDIO_BITS_PER_SAMPLE_INDEX_32:
286         bits_per_sample_str = "32";
287         break;
288       default:
289         bits_per_sample_str = "Unknown LE bits per sample " + std::to_string(bits_per_sample);
290         break;
291     }
292 
293     switch (channel_count) {
294       case LE_AUDIO_CHANNEL_COUNT_INDEX_NONE:
295         channel_count_str = "none";
296         break;
297       case LE_AUDIO_CHANNEL_COUNT_INDEX_1:
298         channel_count_str = "1";
299         break;
300       case LE_AUDIO_CHANNEL_COUNT_INDEX_2:
301         channel_count_str = "2";
302         break;
303       default:
304         channel_count_str = "Unknown LE channel count " + std::to_string(channel_count);
305         break;
306     }
307 
308     switch (frame_duration) {
309       case LE_AUDIO_FRAME_DURATION_INDEX_NONE:
310         frame_duration_str = "none";
311         break;
312       case LE_AUDIO_FRAME_DURATION_INDEX_7500US:
313         frame_duration_str = "7500 us";
314         break;
315       case LE_AUDIO_FRAME_DURATION_INDEX_10000US:
316         frame_duration_str = "10000 us";
317         break;
318       default:
319         frame_duration_str = "Unknown LE frame duration " + std::to_string(frame_duration);
320         break;
321     }
322 
323     if (octets_per_frame < 0) {
324       octets_per_frame_str = "Unknown LE octets per frame " + std::to_string(octets_per_frame);
325     } else {
326       octets_per_frame_str = std::to_string(octets_per_frame);
327     }
328 
329     if (codec_priority < -1) {
330       codec_priority_str = "Unknown LE codec priority " + std::to_string(codec_priority);
331     } else {
332       codec_priority_str = std::to_string(codec_priority);
333     }
334 
335     return "codec: " + codec_name_str + ", sample rate: " + sample_rate_str +
336            ", bits per sample: " + bits_per_sample_str + ", channel count: " + channel_count_str +
337            ", frame duration: " + frame_duration_str +
338            ", octets per frame: " + octets_per_frame_str + ", codec priroty: " + codec_priority_str;
339   }
340 } btle_audio_codec_config_t;
341 
342 class LeAudioClientCallbacks {
343 public:
344   virtual ~LeAudioClientCallbacks() = default;
345 
346   /* Callback to notify Java that stack is ready */
347   virtual void OnInitialized(void) = 0;
348 
349   /** Callback for profile connection state change */
350   virtual void OnConnectionState(ConnectionState state, const RawAddress& address) = 0;
351 
352   /* Callback with group status update */
353   virtual void OnGroupStatus(int group_id, GroupStatus group_status) = 0;
354 
355   /* Callback with node status update */
356   virtual void OnGroupNodeStatus(const RawAddress& bd_addr, int group_id,
357                                  GroupNodeStatus node_status) = 0;
358   /* Callback for newly recognized or reconfigured existing le audio group */
359   virtual void OnAudioConf(uint8_t direction, int group_id,
360                            std::optional<std::bitset<32>> snk_audio_location,
361                            std::optional<std::bitset<32>> src_audio_location,
362                            uint16_t avail_cont) = 0;
363   /* Callback for sink audio location recognized */
364   virtual void OnSinkAudioLocationAvailable(const RawAddress& address,
365                                             std::optional<std::bitset<32>> snk_audio_location) = 0;
366   /* Callback with local codec capabilities */
367   virtual void OnAudioLocalCodecCapabilities(
368           std::vector<btle_audio_codec_config_t> local_input_capa_codec_conf,
369           std::vector<btle_audio_codec_config_t> local_output_capa_codec_conf) = 0;
370   /* Callback with current group codec configurations. Should change when PACs
371    * changes */
372   virtual void OnAudioGroupCurrentCodecConf(int group_id,
373                                             btle_audio_codec_config_t input_codec_conf,
374                                             btle_audio_codec_config_t output_codec_conf) = 0;
375   /* Callback with selectable group codec configurations. Should change when
376    * context changes */
377   virtual void OnAudioGroupSelectableCodecConf(
378           int group_id, std::vector<btle_audio_codec_config_t> input_selectable_codec_conf,
379           std::vector<btle_audio_codec_config_t> output_selectable_codec_conf) = 0;
380   virtual void OnHealthBasedRecommendationAction(const RawAddress& address,
381                                                  LeAudioHealthBasedAction action) = 0;
382   virtual void OnHealthBasedGroupRecommendationAction(int group_id,
383                                                       LeAudioHealthBasedAction action) = 0;
384 
385   virtual void OnUnicastMonitorModeStatus(uint8_t direction, UnicastMonitorModeStatus status) = 0;
386 
387   /* Callback with group stream status update */
388   virtual void OnGroupStreamStatus(int group_id, GroupStreamStatus group_stream_status) = 0;
389 };
390 
391 class LeAudioClientInterface {
392 public:
393   virtual ~LeAudioClientInterface() = default;
394 
395   /* Register the LeAudio callbacks */
396   virtual void Initialize(LeAudioClientCallbacks* callbacks,
397                           const std::vector<btle_audio_codec_config_t>& offloading_preference) = 0;
398 
399   /** Connect to LEAudio */
400   virtual void Connect(const RawAddress& address) = 0;
401 
402   /** Disconnect from LEAudio */
403   virtual void Disconnect(const RawAddress& address) = 0;
404 
405   /* Set enable/disable State for the LeAudio device */
406   virtual void SetEnableState(const RawAddress& address, bool enabled) = 0;
407 
408   /* Cleanup the LeAudio */
409   virtual void Cleanup(void) = 0;
410 
411   /* Called when LeAudio is unbonded. */
412   virtual void RemoveDevice(const RawAddress& address) = 0;
413 
414   /* Attach le audio node to group */
415   virtual void GroupAddNode(int group_id, const RawAddress& addr) = 0;
416 
417   /* Detach le audio node from a group */
418   virtual void GroupRemoveNode(int group_id, const RawAddress& addr) = 0;
419 
420   /* Set active le audio group */
421   virtual void GroupSetActive(int group_id) = 0;
422 
423   /* Set codec config preference */
424   virtual void SetCodecConfigPreference(int group_id, btle_audio_codec_config_t input_codec_config,
425                                         btle_audio_codec_config_t output_codec_config) = 0;
426 
427   /* Set Ccid for context type */
428   virtual void SetCcidInformation(int ccid, int context_type) = 0;
429 
430   /* Set In call flag */
431   virtual void SetInCall(bool in_call) = 0;
432 
433   /* Set Sink listening mode flag */
434   virtual void SetUnicastMonitorMode(uint8_t direction, bool enable) = 0;
435 
436   /* Sends a preferred audio profiles change */
437   virtual void SendAudioProfilePreferences(int group_id, bool is_output_preference_le_audio,
438                                            bool is_duplex_preference_le_audio) = 0;
439 
440   /* Set allowed to stream context */
441   virtual void SetGroupAllowedContextMask(int group_id, int sink_context_types,
442                                           int source_context_types) = 0;
443 };
444 
445 /* Represents the broadcast source state. */
446 enum class BroadcastState {
447   STOPPED = 0,
448   CONFIGURING,
449   CONFIGURED,
450   ENABLING,
451   DISABLING,
452   STOPPING,
453   STREAMING,
454 };
455 
456 using BroadcastId = uint32_t;
457 static constexpr BroadcastId kBroadcastIdInvalid = 0x00000000;
458 using BroadcastCode = std::array<uint8_t, 16>;
459 
460 /* Content Metadata LTV Types */
461 constexpr uint8_t kLeAudioMetadataTypePreferredAudioContext = 0x01;
462 constexpr uint8_t kLeAudioMetadataTypeStreamingAudioContext = 0x02;
463 constexpr uint8_t kLeAudioMetadataTypeProgramInfo = 0x03;
464 constexpr uint8_t kLeAudioMetadataTypeLanguage = 0x04;
465 constexpr uint8_t kLeAudioMetadataTypeCcidList = 0x05;
466 
467 /* Codec specific LTV Types */
468 constexpr uint8_t kLeAudioLtvTypeSamplingFreq = 0x01;
469 constexpr uint8_t kLeAudioLtvTypeFrameDuration = 0x02;
470 constexpr uint8_t kLeAudioLtvTypeAudioChannelAllocation = 0x03;
471 constexpr uint8_t kLeAudioLtvTypeOctetsPerCodecFrame = 0x04;
472 constexpr uint8_t kLeAudioLtvTypeCodecFrameBlocksPerSdu = 0x05;
473 
474 /* Audio quality configuration in public broadcast announcement */
475 constexpr uint8_t kLeAudioQualityStandard = 0x1 << 1;
476 constexpr uint8_t kLeAudioQualityHigh = 0x1 << 2;
477 
478 /* Unknown RSSI value 0x7F - 127 */
479 constexpr uint8_t kLeAudioSourceRssiUnknown = 0x7F;
480 
481 struct BasicAudioAnnouncementCodecConfig {
482   /* 5 octets for the Codec ID */
483   uint8_t codec_id;
484   uint16_t vendor_company_id;
485   uint16_t vendor_codec_id;
486 
487   /* Codec params - series of LTV formatted triplets */
488   std::map<uint8_t, std::vector<uint8_t>> codec_specific_params;
489   std::optional<std::vector<uint8_t>> vendor_codec_specific_params;
490 };
491 
492 struct BasicAudioAnnouncementBisConfig {
493   std::map<uint8_t, std::vector<uint8_t>> codec_specific_params;
494   std::optional<std::vector<uint8_t>> vendor_codec_specific_params;
495 
496   uint8_t bis_index;
497 };
498 
499 struct BasicAudioAnnouncementSubgroup {
500   /* Subgroup specific codec configuration and metadata */
501   BasicAudioAnnouncementCodecConfig codec_config;
502   // Content metadata
503   std::map<uint8_t, std::vector<uint8_t>> metadata;
504   // Broadcast channel configuration
505   std::vector<BasicAudioAnnouncementBisConfig> bis_configs;
506 };
507 
508 struct BasicAudioAnnouncementData {
509   /* Announcement Header fields */
510   uint32_t presentation_delay_us;
511 
512   /* Subgroup specific configurations */
513   std::vector<BasicAudioAnnouncementSubgroup> subgroup_configs;
514 };
515 
516 struct PublicBroadcastAnnouncementData {
517   // Public Broadcast Announcement features bitmap
518   uint8_t features;
519   // Metadata
520   std::map<uint8_t, std::vector<uint8_t>> metadata;
521 };
522 
523 struct BroadcastMetadata {
524   bool is_public;
525   uint16_t pa_interval;
526   RawAddress addr;
527   uint8_t addr_type;
528   uint8_t adv_sid;
529 
530   BroadcastId broadcast_id;
531   std::string broadcast_name;
532   std::optional<BroadcastCode> broadcast_code;
533 
534   PublicBroadcastAnnouncementData public_announcement;
535   /* Presentation delay and subgroup configurations */
536   BasicAudioAnnouncementData basic_audio_announcement;
537 };
538 
539 class LeAudioBroadcasterCallbacks {
540 public:
541   virtual ~LeAudioBroadcasterCallbacks() = default;
542   /* Callback for the newly created broadcast event. */
543   virtual void OnBroadcastCreated(uint32_t broadcast_id, bool success) = 0;
544 
545   /* Callback for the destroyed broadcast event. */
546   virtual void OnBroadcastDestroyed(uint32_t broadcast_id) = 0;
547   /* Callback for the broadcast source state event. */
548   virtual void OnBroadcastStateChanged(uint32_t broadcast_id, BroadcastState state) = 0;
549   /* Callback for the broadcast metadata change. */
550   virtual void OnBroadcastMetadataChanged(uint32_t broadcast_id,
551                                           const BroadcastMetadata& broadcast_metadata) = 0;
552   /* Callback for broadcast audio session create event. */
553   virtual void OnBroadcastAudioSessionCreated(bool success) = 0;
554 };
555 
556 class LeAudioBroadcasterInterface {
557 public:
558   virtual ~LeAudioBroadcasterInterface() = default;
559   /* Register the LeAudio Broadcaster callbacks */
560   virtual void Initialize(LeAudioBroadcasterCallbacks* callbacks) = 0;
561   /* Stop the LeAudio Broadcaster and all active broadcasts */
562   virtual void Stop(void) = 0;
563   /* Cleanup the LeAudio Broadcaster */
564   virtual void Cleanup(void) = 0;
565   /* Create Broadcast instance */
566   virtual void CreateBroadcast(bool is_public, std::string broadcast_name,
567                                std::optional<BroadcastCode> broadcast_code,
568                                std::vector<uint8_t> public_metadata,
569                                std::vector<uint8_t> subgroup_quality,
570                                std::vector<std::vector<uint8_t>> subgroup_metadata) = 0;
571   /* Update the ongoing Broadcast metadata */
572   virtual void UpdateMetadata(uint32_t broadcast_id, std::string broadcast_name,
573                               std::vector<uint8_t> public_metadata,
574                               std::vector<std::vector<uint8_t>> subgroup_metadata) = 0;
575 
576   /* Start the existing Broadcast stream */
577   virtual void StartBroadcast(uint32_t broadcast_id) = 0;
578   /* Pause the ongoing Broadcast stream */
579   virtual void PauseBroadcast(uint32_t broadcast_id) = 0;
580   /* Stop the Broadcast (no stream, no periodic advertisements */
581   virtual void StopBroadcast(uint32_t broadcast_id) = 0;
582   /* Destroy the existing Broadcast instance */
583   virtual void DestroyBroadcast(uint32_t broadcast_id) = 0;
584   /* Get Broadcast Metadata */
585   virtual void GetBroadcastMetadata(uint32_t broadcast_id) = 0;
586 };
587 
588 } /* namespace le_audio */
589 } /* namespace bluetooth */
590 
591 namespace std {
592 template <>
593 struct formatter<bluetooth::le_audio::btle_audio_codec_index_t>
594     : enum_formatter<bluetooth::le_audio::btle_audio_codec_index_t> {};
595 template <>
596 struct formatter<bluetooth::le_audio::btle_audio_sample_rate_index_t>
597     : enum_formatter<bluetooth::le_audio::btle_audio_sample_rate_index_t> {};
598 template <>
599 struct formatter<bluetooth::le_audio::btle_audio_bits_per_sample_index_t>
600     : enum_formatter<bluetooth::le_audio::btle_audio_bits_per_sample_index_t> {};
601 template <>
602 struct formatter<bluetooth::le_audio::btle_audio_channel_count_index_t>
603     : enum_formatter<bluetooth::le_audio::btle_audio_channel_count_index_t> {};
604 template <>
605 struct formatter<bluetooth::le_audio::btle_audio_frame_duration_index_t>
606     : enum_formatter<bluetooth::le_audio::btle_audio_frame_duration_index_t> {};
607 template <>
608 struct formatter<bluetooth::le_audio::GroupStreamStatus>
609     : enum_formatter<bluetooth::le_audio::GroupStreamStatus> {};
610 }  // namespace std
611