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