1 /* 2 * Copyright 2021 HIMSA II K/S - www.himsa.com. 3 * Represented by EHIMA - 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 <optional> 23 24 #include "bta/include/bta_le_audio_api.h" 25 #include "bta/include/bta_le_audio_broadcaster_api.h" 26 #include "bta/le_audio/le_audio_types.h" 27 28 /* Types used internally by various modules of the broadcaster but not exposed 29 * in the API. 30 */ 31 32 namespace bluetooth::le_audio { 33 struct LeAudioCodecConfiguration; 34 35 namespace broadcaster { 36 static const uint16_t kBroadcastAudioAnnouncementServiceUuid = 0x1852; 37 static const uint16_t kBasicAudioAnnouncementServiceUuid = 0x1851; 38 static const uint16_t kPublicBroadcastAnnouncementServiceUuid = 0x1856; 39 40 static const uint8_t kBisIndexInvalid = 0; 41 42 bool ToRawPacket(bluetooth::le_audio::BasicAudioAnnouncementData const&, std::vector<uint8_t>&); 43 44 void PrepareAdvertisingData( 45 bool is_public, const std::string& broadcast_name, 46 bluetooth::le_audio::BroadcastId& broadcast_id, 47 const bluetooth::le_audio::PublicBroadcastAnnouncementData& public_announcement, 48 std::vector<uint8_t>& adv_data); 49 void PreparePeriodicData(const bluetooth::le_audio::BasicAudioAnnouncementData& announcement, 50 std::vector<uint8_t>& periodic_data); 51 52 struct BroadcastSubgroupBisCodecConfig { 53 BroadcastSubgroupBisCodecConfig( 54 uint8_t num_bis, uint8_t bis_channel_cnt, types::LeAudioLtvMap codec_specific, 55 std::optional<std::vector<uint8_t>> vendor_codec_specific = std::nullopt) num_bis_BroadcastSubgroupBisCodecConfig56 : num_bis_(num_bis), 57 bis_channel_cnt_(bis_channel_cnt), 58 codec_specific_(codec_specific), 59 vendor_codec_specific_(vendor_codec_specific) {} 60 61 bool operator==(const BroadcastSubgroupBisCodecConfig& other) const { 62 return (num_bis_ == other.num_bis_) && (bis_channel_cnt_ == other.bis_channel_cnt_) && 63 (codec_specific_ == other.codec_specific_) && 64 (vendor_codec_specific_ == other.vendor_codec_specific_); 65 } 66 67 bool operator!=(const BroadcastSubgroupBisCodecConfig& other) const { return !(*this == other); } 68 GetNumBisBroadcastSubgroupBisCodecConfig69 uint8_t GetNumBis() const { return num_bis_; } 70 GetCodecSpecDataBroadcastSubgroupBisCodecConfig71 const types::LeAudioLtvMap& GetCodecSpecData() const { return codec_specific_; } 72 GetVendorCodecSpecificBroadcastSubgroupBisCodecConfig73 const std::optional<std::vector<uint8_t>>& GetVendorCodecSpecific() const { 74 return vendor_codec_specific_; 75 } 76 HasVendorCodecSpecificBroadcastSubgroupBisCodecConfig77 bool HasVendorCodecSpecific() const { return vendor_codec_specific_.has_value(); } 78 GetNumChannelsBroadcastSubgroupBisCodecConfig79 uint8_t GetNumChannels() const { return num_bis_ * GetNumChannelsPerBis(); } 80 GetSamplingFrequencyHzBroadcastSubgroupBisCodecConfig81 uint32_t GetSamplingFrequencyHz() const { 82 return codec_specific_.GetAsCoreCodecConfig().GetSamplingFrequencyHz(); 83 } 84 GetNumChannelsPerBisBroadcastSubgroupBisCodecConfig85 uint8_t GetNumChannelsPerBis() const { return bis_channel_cnt_; } 86 87 private: 88 uint8_t num_bis_; 89 uint8_t bis_channel_cnt_; 90 /* Codec Specific Configuration */ 91 types::LeAudioLtvMap codec_specific_; 92 std::optional<std::vector<uint8_t>> vendor_codec_specific_; 93 }; 94 95 std::ostream& operator<<(std::ostream& os, 96 const le_audio::broadcaster::BroadcastSubgroupBisCodecConfig& config); 97 98 struct BroadcastSubgroupCodecConfig { 99 BroadcastSubgroupCodecConfig( 100 types::LeAudioCodecId codec_id, 101 std::vector<BroadcastSubgroupBisCodecConfig> bis_codec_configs, uint8_t bits_per_sample, 102 std::optional<std::vector<uint8_t>> subgroup_vendor_codec_config = std::nullopt) codec_id_BroadcastSubgroupCodecConfig103 : codec_id_(codec_id), 104 bis_codec_configs_(bis_codec_configs), 105 subgroup_vendor_codec_config_(subgroup_vendor_codec_config), 106 bits_per_sample_(bits_per_sample) {} 107 108 bool operator==(const BroadcastSubgroupCodecConfig& other) const { 109 if (subgroup_vendor_codec_config_.has_value() != 110 other.subgroup_vendor_codec_config_.has_value()) { 111 return false; 112 } 113 114 if (subgroup_vendor_codec_config_.has_value()) { 115 if (subgroup_vendor_codec_config_->size() != other.subgroup_vendor_codec_config_->size()) { 116 return false; 117 } 118 119 if (0 != memcmp(subgroup_vendor_codec_config_->data(), 120 other.subgroup_vendor_codec_config_->data(), 121 subgroup_vendor_codec_config_->size())) { 122 return false; 123 } 124 } 125 126 return (codec_id_ == other.codec_id_) && (bis_codec_configs_ == other.bis_codec_configs_) && 127 (bits_per_sample_ == other.bits_per_sample_); 128 } 129 130 bool operator!=(const BroadcastSubgroupCodecConfig& other) const { return !(*this == other); } 131 GetCommonBisCodecSpecDataBroadcastSubgroupCodecConfig132 types::LeAudioLtvMap GetCommonBisCodecSpecData() const { 133 if (bis_codec_configs_.empty()) { 134 return types::LeAudioLtvMap(); 135 } 136 auto common_ltv = bis_codec_configs_[0].GetCodecSpecData(); 137 for (auto it = bis_codec_configs_.begin() + 1; it != bis_codec_configs_.end(); ++it) { 138 common_ltv = it->GetCodecSpecData().GetIntersection(common_ltv); 139 } 140 return common_ltv; 141 } 142 GetVendorCodecSpecDataBroadcastSubgroupCodecConfig143 std::optional<std::vector<uint8_t>> GetVendorCodecSpecData() const { 144 return subgroup_vendor_codec_config_; 145 } 146 GetBisVendorCodecSpecDataBroadcastSubgroupCodecConfig147 std::optional<std::vector<uint8_t>> GetBisVendorCodecSpecData(uint8_t bis_idx) const { 148 if (bis_codec_configs_.empty()) { 149 return std::nullopt; 150 } 151 auto config = bis_codec_configs_.at(0); 152 if ((bis_idx != 0) && (bis_idx < bis_codec_configs_.size())) { 153 config = bis_codec_configs_.at(bis_idx); 154 } 155 156 if (config.HasVendorCodecSpecific()) { 157 return config.GetVendorCodecSpecific().value(); 158 } 159 160 return std::nullopt; 161 } 162 GetBisOctetsPerCodecFrameBroadcastSubgroupCodecConfig163 uint16_t GetBisOctetsPerCodecFrame(uint8_t bis_idx) const { 164 // Check the subgroup level parameters first, then the specific BIS 165 auto num_octets = 166 GetCommonBisCodecSpecData().GetAsCoreCodecConfig().octets_per_codec_frame.value_or(0); 167 if (num_octets) { 168 return num_octets; 169 } 170 171 // Currently not a single software vendor codec was integrated and only the 172 // LTVs parameters are understood by the BT stack. 173 auto opt_ltvs = GetBisCodecSpecData(bis_idx, 0); 174 if (opt_ltvs) { 175 return opt_ltvs->GetAsCoreCodecConfig().octets_per_codec_frame.value_or(0) * 176 opt_ltvs->GetAsCoreCodecConfig().codec_frames_blocks_per_sdu.value_or(0); 177 } 178 179 return 0; 180 } 181 182 /* Note: this should be used for tests only */ GetBisCodecConfigsBroadcastSubgroupCodecConfig183 const std::vector<BroadcastSubgroupBisCodecConfig>& GetBisCodecConfigs() const { 184 return bis_codec_configs_; 185 } 186 GetBisCodecSpecDataBroadcastSubgroupCodecConfig187 std::optional<types::LeAudioLtvMap> GetBisCodecSpecData(uint8_t bis_idx, 188 uint8_t bis_config_idx) const { 189 if (bis_codec_configs_.empty()) { 190 return std::nullopt; 191 } 192 log::assert_that(bis_config_idx < bis_codec_configs_.size(), "Invalid bis config index"); 193 auto config = bis_codec_configs_.at(bis_config_idx); 194 if ((bis_idx != 0) && (bis_idx < bis_codec_configs_.size())) { 195 config = bis_codec_configs_.at(bis_idx); 196 } 197 198 if (config.HasVendorCodecSpecific()) { 199 return std::nullopt; 200 } 201 202 auto cfg = config.GetCodecSpecData(); 203 /* Set the audio locations if not set */ 204 if (!cfg.Find(codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation)) { 205 switch (bis_config_idx + bis_idx) { 206 case 0: 207 cfg.Add(codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation, 208 codec_spec_conf::kLeAudioLocationFrontLeft); 209 break; 210 case 1: 211 cfg.Add(codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation, 212 codec_spec_conf::kLeAudioLocationFrontRight); 213 break; 214 default: 215 break; 216 } 217 } 218 return cfg; 219 } 220 GetLeAudioCodecIdBroadcastSubgroupCodecConfig221 const types::LeAudioCodecId& GetLeAudioCodecId() const { return codec_id_; } 222 GetNumBisBroadcastSubgroupCodecConfig223 uint8_t GetNumBis() const { 224 uint8_t value = 0; 225 // Iterate over BISes 226 for (auto const& cfg : bis_codec_configs_) { 227 value += cfg.GetNumBis(); 228 } 229 return value; 230 } 231 GetNumBisBroadcastSubgroupCodecConfig232 uint8_t GetNumBis(uint8_t bis_idx) const { 233 if (bis_idx < bis_codec_configs_.size()) { 234 return bis_codec_configs_.at(bis_idx).GetNumBis(); 235 } 236 return 0; 237 } 238 GetNumChannelsTotalBroadcastSubgroupCodecConfig239 uint8_t GetNumChannelsTotal() const { 240 uint8_t value = 0; 241 // Iterate over BISes 242 for (auto const& cfg : bis_codec_configs_) { 243 value += cfg.GetNumChannels(); 244 } 245 return value; 246 } 247 GetSamplingFrequencyHzMaxBroadcastSubgroupCodecConfig248 uint32_t GetSamplingFrequencyHzMax() const { 249 uint32_t value = 0; 250 // Iterate over BISes 251 for (auto const& cfg : bis_codec_configs_) { 252 value += cfg.GetSamplingFrequencyHz(); 253 } 254 return value; 255 } 256 257 // Local audio source sample resolution GetBitsPerSampleBroadcastSubgroupCodecConfig258 uint8_t GetBitsPerSample() const { return bits_per_sample_; } 259 GetAllBisConfigCountBroadcastSubgroupCodecConfig260 size_t GetAllBisConfigCount() const { return bis_codec_configs_.size(); } 261 262 friend std::ostream& operator<<( 263 std::ostream& os, const le_audio::broadcaster::BroadcastSubgroupCodecConfig& config); 264 265 private: 266 types::LeAudioCodecId codec_id_; 267 /* A list of distinct BIS configurations - each config can be allied to 268 * num_bis number of BISes 269 */ 270 std::vector<BroadcastSubgroupBisCodecConfig> bis_codec_configs_; 271 std::optional<std::vector<uint8_t>> subgroup_vendor_codec_config_; 272 273 /* Local audio source sample resolution - this should consider the HW 274 * offloader requirements 275 */ 276 uint8_t bits_per_sample_; 277 }; 278 279 std::ostream& operator<<( 280 std::ostream& os, 281 const bluetooth::le_audio::broadcaster::BroadcastSubgroupCodecConfig& config); 282 283 struct BroadcastQosConfig { BroadcastQosConfigBroadcastQosConfig284 BroadcastQosConfig(uint8_t retransmission_number, uint16_t max_transport_latency) 285 : retransmission_number_(retransmission_number), 286 max_transport_latency_(max_transport_latency) {} 287 288 bool operator==(const BroadcastQosConfig& other) const { 289 return (retransmission_number_ == other.retransmission_number_) && 290 (max_transport_latency_ == other.max_transport_latency_); 291 } 292 293 bool operator!=(const BroadcastQosConfig& other) const { return !(*this == other); } 294 getRetransmissionNumberBroadcastQosConfig295 uint8_t getRetransmissionNumber() const { return retransmission_number_; } getMaxTransportLatencyBroadcastQosConfig296 uint16_t getMaxTransportLatency() const { return max_transport_latency_; } 297 298 private: 299 uint8_t retransmission_number_; 300 uint16_t max_transport_latency_; 301 }; 302 303 std::ostream& operator<<(std::ostream& os, 304 const bluetooth::le_audio::broadcaster::BroadcastQosConfig& config); 305 306 struct BroadcastConfiguration { 307 bool operator==(const BroadcastConfiguration& other) const { 308 if ((sduIntervalUs != other.sduIntervalUs) || (maxSduOctets != other.maxSduOctets) || 309 (phy != other.phy) || (packing != other.packing) || (framing != other.framing)) { 310 return false; 311 } 312 313 if (qos != other.qos) { 314 return false; 315 } 316 if (data_path != other.data_path) { 317 return false; 318 } 319 if (subgroups.size() != other.subgroups.size()) { 320 return false; 321 } 322 323 for (auto const& subgroup : subgroups) { 324 if (std::find(other.subgroups.begin(), other.subgroups.end(), subgroup) == 325 other.subgroups.end()) { 326 return false; 327 } 328 } 329 330 return true; 331 } 332 333 bool operator!=(const BroadcastConfiguration& other) const { return !(*this == other); } 334 GetNumBisTotalBroadcastConfiguration335 uint8_t GetNumBisTotal() const { 336 auto count = 0; 337 // Iterate over subgroups 338 for (auto const& cfg : subgroups) { 339 count += cfg.GetNumBis(); 340 } 341 return count; 342 } 343 GetNumChannelsMaxBroadcastConfiguration344 uint8_t GetNumChannelsMax() const { 345 uint8_t value = 0; 346 for (auto const& cfg : subgroups) { 347 if (cfg.GetNumChannelsTotal() > value) { 348 value = cfg.GetNumChannelsTotal(); 349 } 350 } 351 return value; 352 } 353 GetSamplingFrequencyHzMaxBroadcastConfiguration354 uint32_t GetSamplingFrequencyHzMax() const { 355 uint32_t value = 0; 356 for (auto const& cfg : subgroups) { 357 if (cfg.GetSamplingFrequencyHzMax() > value) { 358 value = cfg.GetSamplingFrequencyHzMax(); 359 } 360 } 361 return value; 362 } 363 GetSduIntervalUsBroadcastConfiguration364 uint32_t GetSduIntervalUs() const { return sduIntervalUs; } 365 GetMaxSduOctetsBroadcastConfiguration366 uint16_t GetMaxSduOctets() const { return maxSduOctets; } 367 368 LeAudioCodecConfiguration GetAudioHalClientConfig() const; 369 370 std::vector<BroadcastSubgroupCodecConfig> subgroups; 371 BroadcastQosConfig qos; 372 373 types::DataPathConfiguration data_path; 374 375 uint32_t sduIntervalUs; 376 uint16_t maxSduOctets; 377 uint8_t phy; 378 uint8_t packing; 379 uint8_t framing; 380 }; 381 382 std::ostream& operator<<(std::ostream& os, 383 const le_audio::broadcaster::BroadcastConfiguration& config); 384 385 } // namespace broadcaster 386 } // namespace bluetooth::le_audio 387 388 /* BroadcastAnnouncements compare helper */ 389 namespace bluetooth::le_audio { 390 bool operator==(const BasicAudioAnnouncementData& lhs, const BasicAudioAnnouncementData& rhs); 391 bool operator==(const PublicBroadcastAnnouncementData& lhs, 392 const PublicBroadcastAnnouncementData& rhs); 393 } // namespace bluetooth::le_audio 394