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