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&, 43 std::vector<uint8_t>&); 44 45 void PrepareAdvertisingData( 46 bool is_public, const std::string& broadcast_name, 47 bluetooth::le_audio::BroadcastId& broadcast_id, 48 const bluetooth::le_audio::PublicBroadcastAnnouncementData& 49 public_announcement, 50 std::vector<uint8_t>& adv_data); 51 void PreparePeriodicData( 52 const bluetooth::le_audio::BasicAudioAnnouncementData& announcement, 53 std::vector<uint8_t>& periodic_data); 54 55 struct BroadcastSubgroupBisCodecConfig { 56 BroadcastSubgroupBisCodecConfig( 57 uint8_t num_bis, uint8_t bis_channel_cnt, 58 types::LeAudioLtvMap codec_specific, 59 std::optional<std::vector<uint8_t>> vendor_codec_specific = std::nullopt) num_bis_BroadcastSubgroupBisCodecConfig60 : num_bis_(num_bis), 61 bis_channel_cnt_(bis_channel_cnt), 62 codec_specific_(codec_specific), 63 vendor_codec_specific_(vendor_codec_specific) {} 64 65 bool operator==(const BroadcastSubgroupBisCodecConfig& other) const { 66 return (num_bis_ == other.num_bis_) && 67 (bis_channel_cnt_ == other.bis_channel_cnt_) && 68 (codec_specific_ == other.codec_specific_) && 69 (vendor_codec_specific_ == other.vendor_codec_specific_); 70 } 71 72 bool operator!=(const BroadcastSubgroupBisCodecConfig& other) const { 73 return !(*this == other); 74 } 75 GetNumBisBroadcastSubgroupBisCodecConfig76 uint8_t GetNumBis() const { return num_bis_; } 77 GetCodecSpecDataBroadcastSubgroupBisCodecConfig78 const types::LeAudioLtvMap& GetCodecSpecData() const { 79 return codec_specific_; 80 }; 81 GetVendorCodecSpecificBroadcastSubgroupBisCodecConfig82 const std::optional<std::vector<uint8_t>>& GetVendorCodecSpecific() const { 83 return vendor_codec_specific_; 84 } 85 HasVendorCodecSpecificBroadcastSubgroupBisCodecConfig86 bool HasVendorCodecSpecific() const { 87 return vendor_codec_specific_.has_value(); 88 } 89 GetNumChannelsBroadcastSubgroupBisCodecConfig90 uint8_t GetNumChannels() const { return num_bis_ * GetNumChannelsPerBis(); } 91 GetSamplingFrequencyHzBroadcastSubgroupBisCodecConfig92 uint32_t GetSamplingFrequencyHz() const { 93 return codec_specific_.GetAsCoreCodecConfig().GetSamplingFrequencyHz(); 94 } 95 GetNumChannelsPerBisBroadcastSubgroupBisCodecConfig96 uint8_t GetNumChannelsPerBis() const { return bis_channel_cnt_; } 97 98 private: 99 uint8_t num_bis_; 100 uint8_t bis_channel_cnt_; 101 /* Codec Specific Configuration */ 102 types::LeAudioLtvMap codec_specific_; 103 std::optional<std::vector<uint8_t>> vendor_codec_specific_; 104 }; 105 106 std::ostream& operator<<( 107 std::ostream& os, 108 const le_audio::broadcaster::BroadcastSubgroupBisCodecConfig& config); 109 110 struct BroadcastSubgroupCodecConfig { 111 BroadcastSubgroupCodecConfig( 112 types::LeAudioCodecId codec_id, 113 std::vector<BroadcastSubgroupBisCodecConfig> bis_codec_configs, 114 uint8_t bits_per_sample, 115 std::optional<std::vector<uint8_t>> subgroup_vendor_codec_config = 116 std::nullopt) codec_id_BroadcastSubgroupCodecConfig117 : codec_id_(codec_id), 118 bis_codec_configs_(bis_codec_configs), 119 subgroup_vendor_codec_config_(subgroup_vendor_codec_config), 120 bits_per_sample_(bits_per_sample) {} 121 122 bool operator==(const BroadcastSubgroupCodecConfig& other) const { 123 if (subgroup_vendor_codec_config_.has_value() != 124 other.subgroup_vendor_codec_config_.has_value()) 125 return false; 126 127 if (subgroup_vendor_codec_config_.has_value()) { 128 if (subgroup_vendor_codec_config_->size() != 129 other.subgroup_vendor_codec_config_->size()) { 130 return false; 131 } 132 133 if (0 != memcmp(subgroup_vendor_codec_config_->data(), 134 other.subgroup_vendor_codec_config_->data(), 135 subgroup_vendor_codec_config_->size())) { 136 return false; 137 } 138 } 139 140 return (codec_id_ == other.codec_id_) && 141 (bis_codec_configs_ == other.bis_codec_configs_) && 142 (bits_per_sample_ == other.bits_per_sample_); 143 } 144 145 bool operator!=(const BroadcastSubgroupCodecConfig& other) const { 146 return !(*this == other); 147 } 148 GetCommonBisCodecSpecDataBroadcastSubgroupCodecConfig149 types::LeAudioLtvMap GetCommonBisCodecSpecData() const { 150 if (bis_codec_configs_.empty()) return types::LeAudioLtvMap(); 151 auto common_ltv = bis_codec_configs_[0].GetCodecSpecData(); 152 for (auto it = bis_codec_configs_.begin() + 1; 153 it != bis_codec_configs_.end(); ++it) { 154 common_ltv = it->GetCodecSpecData().GetIntersection(common_ltv); 155 } 156 return common_ltv; 157 } 158 GetVendorCodecSpecDataBroadcastSubgroupCodecConfig159 std::optional<std::vector<uint8_t>> GetVendorCodecSpecData() const { 160 return subgroup_vendor_codec_config_; 161 } 162 GetBisVendorCodecSpecDataBroadcastSubgroupCodecConfig163 std::optional<std::vector<uint8_t>> GetBisVendorCodecSpecData( 164 uint8_t bis_idx) const { 165 if (bis_codec_configs_.empty()) return std::nullopt; 166 auto config = bis_codec_configs_.at(0); 167 if ((bis_idx != 0) && (bis_idx < bis_codec_configs_.size())) { 168 config = bis_codec_configs_.at(bis_idx); 169 } 170 171 if (config.HasVendorCodecSpecific()) { 172 return config.GetVendorCodecSpecific().value(); 173 } 174 175 return std::nullopt; 176 } 177 GetBisOctetsPerCodecFrameBroadcastSubgroupCodecConfig178 uint16_t GetBisOctetsPerCodecFrame(uint8_t bis_idx) const { 179 // Check the subgroup level parameters first, then the specific BIS 180 auto num_octets = GetCommonBisCodecSpecData() 181 .GetAsCoreCodecConfig() 182 .octets_per_codec_frame.value_or(0); 183 if (num_octets) return num_octets; 184 185 // Currently not a single software vendor codec was integrated and only the 186 // LTVs parameters are understood by the BT stack. 187 auto opt_ltvs = GetBisCodecSpecData(bis_idx, 0); 188 if (opt_ltvs) { 189 return opt_ltvs->GetAsCoreCodecConfig().octets_per_codec_frame.value_or( 190 0) * 191 opt_ltvs->GetAsCoreCodecConfig() 192 .codec_frames_blocks_per_sdu.value_or(0); 193 } 194 195 return 0; 196 } 197 198 /* Note: this should be used for tests only */ GetBisCodecConfigsBroadcastSubgroupCodecConfig199 const std::vector<BroadcastSubgroupBisCodecConfig>& GetBisCodecConfigs() 200 const { 201 return bis_codec_configs_; 202 } 203 GetBisCodecSpecDataBroadcastSubgroupCodecConfig204 std::optional<types::LeAudioLtvMap> GetBisCodecSpecData( 205 uint8_t bis_idx, uint8_t bis_config_idx) const { 206 if (bis_codec_configs_.empty()) return std::nullopt; 207 log::assert_that(bis_config_idx < bis_codec_configs_.size(), 208 "Invalid bis config index"); 209 auto config = bis_codec_configs_.at(bis_config_idx); 210 if ((bis_idx != 0) && (bis_idx < bis_codec_configs_.size())) { 211 config = bis_codec_configs_.at(bis_idx); 212 } 213 214 if (config.HasVendorCodecSpecific()) { 215 return std::nullopt; 216 } 217 218 auto cfg = config.GetCodecSpecData(); 219 /* Set the audio locations if not set */ 220 if (!cfg.Find(codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation)) { 221 switch (bis_config_idx + bis_idx) { 222 case 0: 223 cfg.Add(codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation, 224 codec_spec_conf::kLeAudioLocationFrontLeft); 225 break; 226 case 1: 227 cfg.Add(codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation, 228 codec_spec_conf::kLeAudioLocationFrontRight); 229 break; 230 default: 231 break; 232 } 233 } 234 return cfg; 235 } 236 GetLeAudioCodecIdBroadcastSubgroupCodecConfig237 const types::LeAudioCodecId& GetLeAudioCodecId() const { return codec_id_; } 238 GetNumBisBroadcastSubgroupCodecConfig239 uint8_t GetNumBis() const { 240 uint8_t value = 0; 241 // Iterate over BISes 242 for (auto const& cfg : bis_codec_configs_) { 243 value += cfg.GetNumBis(); 244 } 245 return value; 246 } 247 GetNumBisBroadcastSubgroupCodecConfig248 uint8_t GetNumBis(uint8_t bis_idx) const { 249 if (bis_idx < bis_codec_configs_.size()) { 250 return bis_codec_configs_.at(bis_idx).GetNumBis(); 251 } 252 return 0; 253 } 254 GetNumChannelsTotalBroadcastSubgroupCodecConfig255 uint8_t GetNumChannelsTotal() const { 256 uint8_t value = 0; 257 // Iterate over BISes 258 for (auto const& cfg : bis_codec_configs_) { 259 value += cfg.GetNumChannels(); 260 } 261 return value; 262 } 263 GetSamplingFrequencyHzMaxBroadcastSubgroupCodecConfig264 uint32_t GetSamplingFrequencyHzMax() const { 265 uint32_t value = 0; 266 // Iterate over BISes 267 for (auto const& cfg : bis_codec_configs_) { 268 value += cfg.GetSamplingFrequencyHz(); 269 } 270 return value; 271 } 272 273 // Local audio source sample resolution GetBitsPerSampleBroadcastSubgroupCodecConfig274 uint8_t GetBitsPerSample() const { return bits_per_sample_; } 275 GetAllBisConfigCountBroadcastSubgroupCodecConfig276 size_t GetAllBisConfigCount() const { return bis_codec_configs_.size(); } 277 278 friend std::ostream& operator<<( 279 std::ostream& os, 280 const le_audio::broadcaster::BroadcastSubgroupCodecConfig& config); 281 282 private: 283 types::LeAudioCodecId codec_id_; 284 /* A list of distinct BIS configurations - each config can be allied to 285 * num_bis number of BISes 286 */ 287 std::vector<BroadcastSubgroupBisCodecConfig> bis_codec_configs_; 288 std::optional<std::vector<uint8_t>> subgroup_vendor_codec_config_; 289 290 /* Local audio source sample resolution - this should consider the HW 291 * offloader requirements 292 */ 293 uint8_t bits_per_sample_; 294 }; 295 296 std::ostream& operator<<( 297 std::ostream& os, 298 const bluetooth::le_audio::broadcaster::BroadcastSubgroupCodecConfig& 299 config); 300 301 struct BroadcastQosConfig { BroadcastQosConfigBroadcastQosConfig302 BroadcastQosConfig(uint8_t retransmission_number, 303 uint16_t max_transport_latency) 304 : retransmission_number_(retransmission_number), 305 max_transport_latency_(max_transport_latency) {} 306 307 bool operator==(const BroadcastQosConfig& other) const { 308 return (retransmission_number_ == other.retransmission_number_) && 309 (max_transport_latency_ == other.max_transport_latency_); 310 } 311 312 bool operator!=(const BroadcastQosConfig& other) const { 313 return !(*this == other); 314 } 315 getRetransmissionNumberBroadcastQosConfig316 uint8_t getRetransmissionNumber() const { return retransmission_number_; } getMaxTransportLatencyBroadcastQosConfig317 uint16_t getMaxTransportLatency() const { return max_transport_latency_; } 318 319 private: 320 uint8_t retransmission_number_; 321 uint16_t max_transport_latency_; 322 }; 323 324 std::ostream& operator<<( 325 std::ostream& os, 326 const bluetooth::le_audio::broadcaster::BroadcastQosConfig& config); 327 328 struct BroadcastConfiguration { 329 bool operator==(const BroadcastConfiguration& other) const { 330 if ((sduIntervalUs != other.sduIntervalUs) || 331 (maxSduOctets != other.maxSduOctets) || (phy != other.phy) || 332 (packing != other.packing) || (framing != other.framing)) { 333 return false; 334 } 335 336 if (qos != other.qos) return false; 337 if (data_path != other.data_path) return false; 338 if (subgroups.size() != other.subgroups.size()) return false; 339 340 for (auto const& subgroup : subgroups) { 341 if (std::find(other.subgroups.begin(), other.subgroups.end(), subgroup) == 342 other.subgroups.end()) { 343 return false; 344 } 345 } 346 347 return true; 348 } 349 350 bool operator!=(const BroadcastConfiguration& other) const { 351 return !(*this == other); 352 } 353 GetNumBisTotalBroadcastConfiguration354 uint8_t GetNumBisTotal() const { 355 auto count = 0; 356 // Iterate over subgroups 357 for (auto const& cfg : subgroups) { 358 count += cfg.GetNumBis(); 359 } 360 return count; 361 } 362 GetNumChannelsMaxBroadcastConfiguration363 uint8_t GetNumChannelsMax() const { 364 uint8_t value = 0; 365 for (auto const& cfg : subgroups) { 366 if (cfg.GetNumChannelsTotal() > value) value = cfg.GetNumChannelsTotal(); 367 } 368 return value; 369 } 370 GetSamplingFrequencyHzMaxBroadcastConfiguration371 uint32_t GetSamplingFrequencyHzMax() const { 372 uint32_t value = 0; 373 for (auto const& cfg : subgroups) { 374 if (cfg.GetSamplingFrequencyHzMax() > value) 375 value = cfg.GetSamplingFrequencyHzMax(); 376 } 377 return value; 378 } 379 GetSduIntervalUsBroadcastConfiguration380 uint32_t GetSduIntervalUs() const { return sduIntervalUs; } 381 GetMaxSduOctetsBroadcastConfiguration382 uint16_t GetMaxSduOctets() const { return maxSduOctets; } 383 384 LeAudioCodecConfiguration GetAudioHalClientConfig() const; 385 386 std::vector<BroadcastSubgroupCodecConfig> subgroups; 387 BroadcastQosConfig qos; 388 389 types::DataPathConfiguration data_path; 390 391 uint32_t sduIntervalUs; 392 uint16_t maxSduOctets; 393 uint8_t phy; 394 uint8_t packing; 395 uint8_t framing; 396 }; 397 398 std::ostream& operator<<( 399 std::ostream& os, 400 const le_audio::broadcaster::BroadcastConfiguration& config); 401 402 } // namespace broadcaster 403 } // namespace bluetooth::le_audio 404 405 /* BroadcastAnnouncements compare helper */ 406 namespace bluetooth::le_audio { 407 bool operator==(const BasicAudioAnnouncementData& lhs, 408 const BasicAudioAnnouncementData& rhs); 409 bool operator==(const PublicBroadcastAnnouncementData& lhs, 410 const PublicBroadcastAnnouncementData& rhs); 411 } // namespace bluetooth::le_audio 412