1 /*
2  * Copyright 2020 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 /*
19  * This file contains definitions for Basic Audio Profile / Audio Stream Control
20  * and Published Audio Capabilities definitions, structures etc.
21  */
22 
23 #include "le_audio_types.h"
24 
25 #include <base/strings/string_number_conversions.h>
26 #include <bluetooth/log.h>
27 
28 #include <algorithm>
29 #include <cstddef>
30 #include <cstdint>
31 #include <cstring>
32 #include <iomanip>
33 #include <iterator>
34 #include <map>
35 #include <memory>
36 #include <optional>
37 #include <ostream>
38 #include <sstream>
39 #include <string>
40 #include <type_traits>
41 #include <utility>
42 #include <vector>
43 
44 #include "audio_hal_client/audio_hal_client.h"
45 #include "common/strings.h"
46 #include "hardware/bt_le_audio.h"
47 #include "internal_include/bt_trace.h"
48 #include "le_audio_utils.h"
49 #include "stack/include/bt_types.h"
50 
51 // TODO(b/369381361) Enfore -Wmissing-prototypes
52 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
53 
54 namespace bluetooth::le_audio {
55 using types::acs_ac_record;
56 using types::LeAudioContextType;
57 
58 namespace set_configurations {
59 using set_configurations::CodecConfigSetting;
60 using types::kLeAudioCodingFormatLC3;
61 using types::LeAudioCoreCodecConfig;
62 
get_cis_count(LeAudioContextType context_type,uint8_t expected_remote_direction,int expected_device_cnt,types::LeAudioConfigurationStrategy strategy,int avail_group_ase_snk_cnt,int avail_group_ase_src_count,uint8_t & out_cis_count_bidir,uint8_t & out_cis_count_unidir_sink,uint8_t & out_cis_count_unidir_source)63 void get_cis_count(LeAudioContextType context_type, uint8_t expected_remote_direction,
64                    int expected_device_cnt, types::LeAudioConfigurationStrategy strategy,
65                    int avail_group_ase_snk_cnt, int avail_group_ase_src_count,
66                    uint8_t& out_cis_count_bidir, uint8_t& out_cis_count_unidir_sink,
67                    uint8_t& out_cis_count_unidir_source) {
68   log::info(
69           "{} expected_remote_direction {}, strategy {}, group avail sink ases: {}, "
70           "group avail source ases {} "
71           "expected_device_count {}",
72           bluetooth::common::ToString(context_type), expected_remote_direction,
73           static_cast<int>(strategy), avail_group_ase_snk_cnt, avail_group_ase_src_count,
74           expected_device_cnt);
75 
76   bool is_bidirectional = expected_remote_direction == types::kLeAudioDirectionBoth;
77   bool is_source_only = expected_remote_direction == types::kLeAudioDirectionSource;
78 
79   switch (strategy) {
80     case types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE:
81     /* This strategy is for the CSIS topology, e.g. two earbuds which are both
82      * connected with a Phone
83      */
84     case types::LeAudioConfigurationStrategy::STEREO_ONE_CIS_PER_DEVICE:
85       /* This strategy is for e.g. the banded headphones */
86       if (is_bidirectional) {
87         if ((avail_group_ase_snk_cnt > 0) && (avail_group_ase_src_count) > 0) {
88           /* Prepare CIG to enable all microphones */
89           out_cis_count_bidir = expected_device_cnt;
90         } else {
91           if (avail_group_ase_snk_cnt > 0) {
92             out_cis_count_unidir_sink = expected_device_cnt;
93           } else if (avail_group_ase_src_count > 0) {
94             out_cis_count_unidir_source = expected_device_cnt;
95           }
96         }
97       } else if (is_source_only) {
98         out_cis_count_unidir_source = expected_device_cnt;
99       } else {
100         out_cis_count_unidir_sink = expected_device_cnt;
101       }
102 
103       break;
104     case types::LeAudioConfigurationStrategy::STEREO_TWO_CISES_PER_DEVICE:
105       /* This strategy is for the old TWS topology. e.g. one earbud connected to
106        * the Phone but each channel is carried in separate CIS
107        */
108       if (is_bidirectional) {
109         if ((avail_group_ase_snk_cnt > 0) && (avail_group_ase_src_count) > 0) {
110           /* Prepare CIG to enable all microphones per device */
111           out_cis_count_bidir = expected_device_cnt;
112           if (avail_group_ase_src_count > 1) {
113             out_cis_count_bidir++;
114           } else {
115             out_cis_count_unidir_sink = expected_device_cnt;
116           }
117         } else {
118           if (avail_group_ase_snk_cnt > 0) {
119             out_cis_count_unidir_sink = 2 * expected_device_cnt;
120           } else if (avail_group_ase_src_count > 0) {
121             out_cis_count_unidir_source = 2 * expected_device_cnt;
122           }
123         }
124       } else if (is_source_only) {
125         out_cis_count_unidir_source = 2 * expected_device_cnt;
126       } else {
127         out_cis_count_unidir_sink = 2 * expected_device_cnt;
128       }
129       break;
130     case types::LeAudioConfigurationStrategy::RFU:
131       log::error("Should not happen;");
132       break;
133   }
134 
135   log::info(
136           "Required cis count: Bi-Directional: {}, Uni-Directional Sink: {}, "
137           "Uni-Directional Source: {}",
138           out_cis_count_bidir, out_cis_count_unidir_sink, out_cis_count_unidir_source);
139 }
140 
GetOctetsPerFrame() const141 uint16_t CodecConfigSetting::GetOctetsPerFrame() const {
142   switch (id.coding_format) {
143     case kLeAudioCodingFormatLC3:
144       return params.GetAsCoreCodecConfig().GetOctetsPerFrame();
145     default:
146       log::warn(", invalid codec id: 0x{:02x}", id.coding_format);
147       return 0;
148   }
149 }
150 
GetSamplingFrequencyHz() const151 uint32_t CodecConfigSetting::GetSamplingFrequencyHz() const {
152   // We also mandate the sampling frequency parameter for vendor spec. codecs
153   return params.GetAsCoreCodecConfig().GetSamplingFrequencyHz();
154 }
155 
GetDataIntervalUs() const156 uint32_t CodecConfigSetting::GetDataIntervalUs() const {
157   switch (id.coding_format) {
158     case kLeAudioCodingFormatLC3:
159       return params.GetAsCoreCodecConfig().GetFrameDurationUs() *
160              params.GetAsCoreCodecConfig().codec_frames_blocks_per_sdu.value_or(1);
161     default:
162       log::warn(", invalid codec id: 0x{:02x}", id.coding_format);
163       return 0;
164   }
165 }
166 
GetBitsPerSample() const167 uint8_t CodecConfigSetting::GetBitsPerSample() const {
168   switch (id.coding_format) {
169     case kLeAudioCodingFormatLC3:
170       /* XXX LC3 supports 16, 24, 32 */
171       return 16;
172     default:
173       log::warn(", invalid codec id: 0x{:02x}", id.coding_format);
174       return 0;
175   }
176 }
177 
operator <<(std::ostream & os,const QosConfigSetting & config)178 std::ostream& operator<<(std::ostream& os, const QosConfigSetting& config) {
179   os << "QosConfigSetting{";
180   os << "targetLatency: " << (int)config.target_latency;
181   os << ", retransmissionNum: " << (int)config.retransmission_number;
182   os << ", maxTransportLatency: " << (int)config.max_transport_latency;
183   os << ", sduIntervalUs: " << (int)config.sduIntervalUs;
184   os << ", maxSdu: " << (int)config.maxSdu;
185   os << "}";
186   return os;
187 }
188 
operator <<(std::ostream & os,const AseConfiguration & config)189 std::ostream& operator<<(std::ostream& os, const AseConfiguration& config) {
190   os << "AseConfiguration{";
191   os << "dataPath: " << config.data_path_configuration;
192   os << ", codec: " << config.codec;
193   os << ", qos: " << config.qos;
194   os << "}";
195   return os;
196 }
197 
operator <<(std::ostream & os,const AudioSetConfiguration & config)198 std::ostream& operator<<(std::ostream& os, const AudioSetConfiguration& config) {
199   os << "AudioSetConfiguration{";
200   os << "name: " << config.name;
201   os << ", packing: " << (int)config.packing;
202   os << ", sinkConfs: [";
203   for (auto const& conf : config.confs.sink) {
204     os << conf;
205     os << ", ";
206   }
207   os << "], sourceConfs: [";
208   for (auto const& conf : config.confs.source) {
209     os << conf;
210     os << ", ";
211   }
212   os << "]}";
213   return os;
214 }
215 
operator <<(std::ostream & os,const CodecConfigSetting & config)216 std::ostream& operator<<(std::ostream& os, const CodecConfigSetting& config) {
217   os << "CodecConfigSetting{";
218   os << ", id: " << config.id;
219   os << ", codecSpecParams: " << config.params.GetAsCoreCodecConfig();
220   os << ", bitsPerSample: " << (int)config.GetBitsPerSample();
221   os << ", channelCountPerIsoStream: " << (int)config.GetChannelCountPerIsoStream();
222   if (!config.vendor_params.empty()) {
223     os << ", vendorParams: "
224        << base::HexEncode(config.vendor_params.data(), config.vendor_params.size());
225   }
226   os << "}";
227   return os;
228 }
229 
230 }  // namespace set_configurations
231 
232 namespace types {
233 /* Helper map for matching various frequency notations */
234 const std::map<uint8_t, uint32_t> LeAudioCoreCodecConfig::sampling_freq_map = {
235         {codec_spec_conf::kLeAudioSamplingFreq8000Hz, LeAudioCodecConfiguration::kSampleRate8000},
236         {codec_spec_conf::kLeAudioSamplingFreq16000Hz, LeAudioCodecConfiguration::kSampleRate16000},
237         {codec_spec_conf::kLeAudioSamplingFreq24000Hz, LeAudioCodecConfiguration::kSampleRate24000},
238         {codec_spec_conf::kLeAudioSamplingFreq32000Hz, LeAudioCodecConfiguration::kSampleRate32000},
239         {codec_spec_conf::kLeAudioSamplingFreq44100Hz, LeAudioCodecConfiguration::kSampleRate44100},
240         {codec_spec_conf::kLeAudioSamplingFreq48000Hz,
241          LeAudioCodecConfiguration::kSampleRate48000}};
242 
243 /* Helper map for matching various frequency notations */
244 const std::map<uint32_t, uint8_t> LeAudioCoreCodecConfig::sample_rate_map = {
245         {LeAudioCodecConfiguration::kSampleRate8000, codec_spec_conf::kLeAudioSamplingFreq8000Hz},
246         {LeAudioCodecConfiguration::kSampleRate16000, codec_spec_conf::kLeAudioSamplingFreq16000Hz},
247         {LeAudioCodecConfiguration::kSampleRate24000, codec_spec_conf::kLeAudioSamplingFreq24000Hz},
248         {LeAudioCodecConfiguration::kSampleRate32000, codec_spec_conf::kLeAudioSamplingFreq32000Hz},
249         {LeAudioCodecConfiguration::kSampleRate44100, codec_spec_conf::kLeAudioSamplingFreq44100Hz},
250         {LeAudioCodecConfiguration::kSampleRate48000, codec_spec_conf::kLeAudioSamplingFreq48000Hz},
251 };
252 
253 /* Helper map for matching various frame durations notations */
254 const std::map<uint8_t, uint32_t> LeAudioCoreCodecConfig::frame_duration_map = {
255         {codec_spec_conf::kLeAudioCodecFrameDur7500us, LeAudioCodecConfiguration::kInterval7500Us},
256         {codec_spec_conf::kLeAudioCodecFrameDur10000us,
257          LeAudioCodecConfiguration::kInterval10000Us}};
258 
259 /* Helper map for matching various frame durations notations */
260 const std::map<uint32_t, uint8_t> LeAudioCoreCodecConfig::data_interval_map = {
261         {LeAudioCodecConfiguration::kInterval7500Us, codec_spec_conf::kLeAudioCodecFrameDur7500us},
262         {LeAudioCodecConfiguration::kInterval10000Us,
263          codec_spec_conf::kLeAudioCodecFrameDur10000us},
264 };
265 
CapabilityTypeToStr(const uint8_t & type)266 std::string CapabilityTypeToStr(const uint8_t& type) {
267   switch (type) {
268     case codec_spec_caps::kLeAudioLtvTypeSupportedSamplingFrequencies:
269       return "Supported Sampling Frequencies";
270     case codec_spec_caps::kLeAudioLtvTypeSupportedFrameDurations:
271       return "Supported Frame Durations";
272     case codec_spec_caps::kLeAudioLtvTypeSupportedAudioChannelCounts:
273       return "Supported Audio Channel Count";
274     case codec_spec_caps::kLeAudioLtvTypeSupportedOctetsPerCodecFrame:
275       return "Supported Octets Per Codec Frame";
276     case codec_spec_caps::kLeAudioLtvTypeSupportedMaxCodecFramesPerSdu:
277       return "Supported Max Codec Frames Per SDU";
278     default:
279       return "Unknown";
280   }
281 }
282 
CapabilityValueToStr(const uint8_t & type,const std::vector<uint8_t> & value)283 std::string CapabilityValueToStr(const uint8_t& type, const std::vector<uint8_t>& value) {
284   std::string string = "";
285 
286   switch (type) {
287     case codec_spec_conf::kLeAudioLtvTypeSamplingFreq: {
288       if (value.size() != 2) {
289         return "Invalid size";
290       }
291 
292       uint16_t u16_val = VEC_UINT8_TO_UINT16(value);
293 
294       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq8000Hz) {
295         string += "8";
296       }
297       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq11025Hz) {
298         string += std::string(string.empty() ? "" : "|") + "11.025";
299       }
300       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq16000Hz) {
301         string += std::string(string.empty() ? "" : "|") + "16";
302       }
303       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq22050Hz) {
304         string += std::string(string.empty() ? "" : "|") + "22.050";
305       }
306       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq24000Hz) {
307         string += std::string(string.empty() ? "" : "|") + "24";
308       }
309       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq32000Hz) {
310         string += std::string(string.empty() ? "" : "|") + "32";
311       }
312       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq44100Hz) {
313         string += std::string(string.empty() ? "" : "|") + "44.1";
314       }
315       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq48000Hz) {
316         string += std::string(string.empty() ? "" : "|") + "48";
317       }
318       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq88200Hz) {
319         string += std::string(string.empty() ? "" : "|") + "88.2";
320       }
321       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq96000Hz) {
322         string += std::string(string.empty() ? "" : "|") + "96";
323       }
324       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq176400Hz) {
325         string += std::string(string.empty() ? "" : "|") + "176.4";
326       }
327       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq192000Hz) {
328         string += std::string(string.empty() ? "" : "|") + "192";
329       }
330       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq384000Hz) {
331         string += std::string(string.empty() ? "" : "|") + "384";
332       }
333 
334       return string += " [kHz]\n";
335     }
336     case codec_spec_conf::kLeAudioLtvTypeFrameDuration: {
337       if (value.size() != 1) {
338         return "Invalid size";
339       }
340 
341       uint8_t u8_val = VEC_UINT8_TO_UINT8(value);
342 
343       if (u8_val & codec_spec_caps::kLeAudioCodecFrameDur7500us) {
344         string += "7.5";
345       }
346       if (u8_val & codec_spec_caps::kLeAudioCodecFrameDur10000us) {
347         string += std::string(string.empty() ? "" : "|") + "10";
348       }
349       if (u8_val & codec_spec_caps::kLeAudioCodecFrameDurPrefer7500us) {
350         string += std::string(string.empty() ? "" : "|") + "7.5 preferred";
351       }
352       if (u8_val & codec_spec_caps::kLeAudioCodecFrameDurPrefer10000us) {
353         string += std::string(string.empty() ? "" : "|") + "10 preferred";
354       }
355 
356       return string += " [ms]\n";
357     }
358     case codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation: {
359       if (value.size() != 1) {
360         return "Invalid size";
361       }
362 
363       uint8_t u8_val = VEC_UINT8_TO_UINT8(value);
364 
365       if (u8_val & codec_spec_caps::kLeAudioCodecChannelCountNone) {
366         string += "0";
367       }
368       if (u8_val & codec_spec_caps::kLeAudioCodecChannelCountSingleChannel) {
369         string += std::string(string.empty() ? "" : "|") + "1";
370       }
371       if (u8_val & codec_spec_caps::kLeAudioCodecChannelCountTwoChannel) {
372         string += std::string(string.empty() ? "" : "|") + "2";
373       }
374       if (u8_val & codec_spec_caps::kLeAudioCodecChannelCountThreeChannel) {
375         string += std::string(string.empty() ? "" : "|") + "3";
376       }
377       if (u8_val & codec_spec_caps::kLeAudioCodecChannelCountFourChannel) {
378         string += std::string(string.empty() ? "" : "|") + "4";
379       }
380       if (u8_val & codec_spec_caps::kLeAudioCodecChannelCountFiveChannel) {
381         string += std::string(string.empty() ? "" : "|") + "5";
382       }
383       if (u8_val & codec_spec_caps::kLeAudioCodecChannelCountSixChannel) {
384         string += std::string(string.empty() ? "" : "|") + "6";
385       }
386       if (u8_val & codec_spec_caps::kLeAudioCodecChannelCountSevenChannel) {
387         string += std::string(string.empty() ? "" : "|") + "7";
388       }
389       if (u8_val & codec_spec_caps::kLeAudioCodecChannelCountEightChannel) {
390         string += std::string(string.empty() ? "" : "|") + "8";
391       }
392 
393       return string += " channel/s\n";
394     }
395     case codec_spec_conf::kLeAudioLtvTypeOctetsPerCodecFrame: {
396       if (value.size() != 4) {
397         return "Invalid size";
398       }
399 
400       uint16_t u16_min_number_of_octets = VEC_UINT8_TO_UINT16(value);
401       uint16_t u16_max_number_of_octets =
402               OFF_VEC_UINT8_TO_UINT16(value, sizeof(u16_min_number_of_octets));
403 
404       string += "Minimum: " + std::to_string(u16_min_number_of_octets);
405       string += ", Maximum: " + std::to_string(u16_max_number_of_octets) + "\n";
406 
407       return string;
408     }
409     case codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu: {
410       if (value.size() != 1) {
411         return "Invalid size";
412       }
413 
414       uint8_t u8_val = VEC_UINT8_TO_UINT8(value);
415 
416       string += std::to_string(u8_val) + " frame/s\n";
417 
418       return string;
419     }
420     default:
421       return base::HexEncode(value.data(), value.size()) + "\n";
422   }
423 }
424 
CodecCapabilitiesLtvFormat(const uint8_t & type,const std::vector<uint8_t> & value)425 std::string CodecCapabilitiesLtvFormat(const uint8_t& type, const std::vector<uint8_t>& value) {
426   std::string string = "";
427 
428   string += CapabilityTypeToStr(type) + ": ";
429   string += CapabilityValueToStr(type, value);
430 
431   return string;
432 }
433 
Find(uint8_t type) const434 std::optional<std::vector<uint8_t>> LeAudioLtvMap::Find(uint8_t type) const {
435   auto iter = std::find_if(values.cbegin(), values.cend(),
436                            [type](const auto& value) { return value.first == type; });
437 
438   if (iter == values.cend()) {
439     return std::nullopt;
440   }
441 
442   return iter->second;
443 }
444 
RawPacket(uint8_t * p_buf) const445 uint8_t* LeAudioLtvMap::RawPacket(uint8_t* p_buf) const {
446   for (auto const& value : values) {
447     UINT8_TO_STREAM(p_buf, value.second.size() + 1);
448     UINT8_TO_STREAM(p_buf, value.first);
449     ARRAY_TO_STREAM(p_buf, value.second.data(), static_cast<int>(value.second.size()));
450   }
451 
452   return p_buf;
453 }
454 
RawPacket() const455 std::vector<uint8_t> LeAudioLtvMap::RawPacket() const {
456   std::vector<uint8_t> data(RawPacketSize());
457   RawPacket(data.data());
458   return data;
459 }
460 
Append(const LeAudioLtvMap & other)461 void LeAudioLtvMap::Append(const LeAudioLtvMap& other) {
462   /* This will override values for the already existing keys */
463   for (auto& el : other.values) {
464     values[el.first] = el.second;
465   }
466 
467   invalidate();
468 }
469 
Parse(const uint8_t * p_value,uint8_t len,bool & success)470 LeAudioLtvMap LeAudioLtvMap::Parse(const uint8_t* p_value, uint8_t len, bool& success) {
471   LeAudioLtvMap ltv_map;
472   success = ltv_map.Parse(p_value, len);
473   if (!success) {
474     log::error("Error parsing LTV map");
475   }
476   return ltv_map;
477 }
478 
Parse(const uint8_t * p_value,uint8_t len)479 bool LeAudioLtvMap::Parse(const uint8_t* p_value, uint8_t len) {
480   if (len > 0) {
481     const auto p_value_end = p_value + len;
482 
483     while ((p_value_end - p_value) > 0) {
484       uint8_t ltv_len;
485       STREAM_TO_UINT8(ltv_len, p_value);
486 
487       // Unusual, but possible case
488       if (ltv_len == 0) {
489         continue;
490       }
491 
492       if (p_value_end < (p_value + ltv_len)) {
493         log::error("Invalid ltv_len: {}", static_cast<int>(ltv_len));
494         invalidate();
495         return false;
496       }
497 
498       uint8_t ltv_type;
499       STREAM_TO_UINT8(ltv_type, p_value);
500       ltv_len -= sizeof(ltv_type);
501 
502       const auto p_temp = p_value;
503       p_value += ltv_len;
504 
505       std::vector<uint8_t> ltv_value(p_temp, p_value);
506       values.emplace(ltv_type, std::move(ltv_value));
507     }
508   }
509   invalidate();
510 
511   return true;
512 }
513 
RawPacketSize() const514 size_t LeAudioLtvMap::RawPacketSize() const {
515   size_t bytes = 0;
516 
517   for (auto const& value : values) {
518     bytes += (/* ltv_len + ltv_type */ 2 + value.second.size());
519   }
520 
521   return bytes;
522 }
523 
ToString(const std::string & indent_string,std::string (* format)(const uint8_t &,const std::vector<uint8_t> &)) const524 std::string LeAudioLtvMap::ToString(const std::string& indent_string,
525                                     std::string (*format)(const uint8_t&,
526                                                           const std::vector<uint8_t>&)) const {
527   std::string debug_str;
528 
529   for (const auto& value : values) {
530     std::stringstream sstream;
531 
532     if (format == nullptr) {
533       sstream << indent_string + "type: " << std::to_string(value.first)
534               << "\tlen: " << std::to_string(value.second.size())
535               << "\tdata: " << base::HexEncode(value.second.data(), value.second.size()) + "\n";
536     } else {
537       sstream << indent_string + format(value.first, value.second);
538     }
539 
540     debug_str += sstream.str();
541   }
542 
543   return debug_str;
544 }
545 
GetAsCoreCodecConfig() const546 const struct LeAudioCoreCodecConfig& LeAudioLtvMap::GetAsCoreCodecConfig() const {
547   log::assert_that(!core_capabilities, "LTVs were already parsed for capabilities!");
548   log::assert_that(!metadata, "LTVs were already parsed for metadata!");
549 
550   if (!core_config) {
551     core_config = LtvMapToCoreCodecConfig(*this);
552   }
553   return *core_config;
554 }
555 
GetAsCoreCodecCapabilities() const556 const struct LeAudioCoreCodecCapabilities& LeAudioLtvMap::GetAsCoreCodecCapabilities() const {
557   log::assert_that(!core_config, "LTVs were already parsed for configurations!");
558   log::assert_that(!metadata, "LTVs were already parsed for metadata!");
559 
560   if (!core_capabilities) {
561     core_capabilities = LtvMapToCoreCodecCapabilities(*this);
562   }
563   return *core_capabilities;
564 }
565 
GetAsLeAudioMetadata() const566 const struct LeAudioMetadata& LeAudioLtvMap::GetAsLeAudioMetadata() const {
567   log::assert_that(!core_config, "LTVs were already parsed for configurations!");
568   log::assert_that(!core_capabilities, "LTVs were already parsed for capabilities!");
569 
570   if (!metadata) {
571     metadata = LtvMapToMetadata(*this);
572   }
573   return *metadata;
574 }
575 
RemoveAllTypes(const LeAudioLtvMap & other)576 void LeAudioLtvMap::RemoveAllTypes(const LeAudioLtvMap& other) {
577   for (auto const& [key, _] : other.values) {
578     Remove(key);
579   }
580 }
581 
GetIntersection(const LeAudioLtvMap & other) const582 LeAudioLtvMap LeAudioLtvMap::GetIntersection(const LeAudioLtvMap& other) const {
583   LeAudioLtvMap result;
584   for (auto const& [key, value] : values) {
585     auto entry = other.Find(key);
586     if (entry->size() != value.size()) {
587       continue;
588     }
589     if (memcmp(entry->data(), value.data(), value.size()) == 0) {
590       result.Add(key, value);
591     }
592   }
593   return result;
594 }
595 
596 }  // namespace types
597 
AppendMetadataLtvEntryForCcidList(std::vector<uint8_t> & metadata,const std::vector<uint8_t> & ccid_list)598 void AppendMetadataLtvEntryForCcidList(std::vector<uint8_t>& metadata,
599                                        const std::vector<uint8_t>& ccid_list) {
600   if (ccid_list.size() == 0) {
601     log::warn("Empty CCID list.");
602     return;
603   }
604 
605   metadata.push_back(static_cast<uint8_t>(types::kLeAudioMetadataTypeLen + ccid_list.size()));
606   metadata.push_back(static_cast<uint8_t>(types::kLeAudioMetadataTypeCcidList));
607 
608   metadata.insert(metadata.end(), ccid_list.begin(), ccid_list.end());
609 }
610 
AppendMetadataLtvEntryForStreamingContext(std::vector<uint8_t> & metadata,types::AudioContexts context_type)611 void AppendMetadataLtvEntryForStreamingContext(std::vector<uint8_t>& metadata,
612                                                types::AudioContexts context_type) {
613   std::vector<uint8_t> streaming_context_ltv_entry;
614 
615   streaming_context_ltv_entry.resize(types::kLeAudioMetadataTypeLen +
616                                      types::kLeAudioMetadataLenLen +
617                                      types::kLeAudioMetadataStreamingAudioContextLen);
618   uint8_t* streaming_context_ltv_entry_buf = streaming_context_ltv_entry.data();
619 
620   UINT8_TO_STREAM(streaming_context_ltv_entry_buf,
621                   types::kLeAudioMetadataTypeLen + types::kLeAudioMetadataStreamingAudioContextLen);
622   UINT8_TO_STREAM(streaming_context_ltv_entry_buf,
623                   types::kLeAudioMetadataTypeStreamingAudioContext);
624   UINT16_TO_STREAM(streaming_context_ltv_entry_buf, context_type.value());
625 
626   metadata.insert(metadata.end(), streaming_context_ltv_entry.begin(),
627                   streaming_context_ltv_entry.end());
628 }
629 
GetMaxCodecFramesPerSduFromPac(const acs_ac_record * pac)630 uint8_t GetMaxCodecFramesPerSduFromPac(const acs_ac_record* pac) {
631   if (utils::IsCodecUsingLtvFormat(pac->codec_id)) {
632     auto tlv_ent = pac->codec_spec_caps.Find(
633             codec_spec_caps::kLeAudioLtvTypeSupportedMaxCodecFramesPerSdu);
634 
635     if (tlv_ent) {
636       return VEC_UINT8_TO_UINT8(tlv_ent.value());
637     }
638   }
639 
640   return 1;
641 }
642 
643 namespace types {
operator <<(std::ostream & os,const CisState & state)644 std::ostream& operator<<(std::ostream& os, const CisState& state) {
645   static const char* char_value_[5] = {"IDLE", "ASSIGNED", "CONNECTING", "CONNECTED",
646                                        "DISCONNECTING"};
647 
648   os << char_value_[static_cast<uint8_t>(state)] << " (" << "0x" << std::setfill('0')
649      << std::setw(2) << static_cast<int>(state) << ")";
650   return os;
651 }
operator <<(std::ostream & os,const DataPathState & state)652 std::ostream& operator<<(std::ostream& os, const DataPathState& state) {
653   static const char* char_value_[4] = {"IDLE", "CONFIGURING", "CONFIGURED", "REMOVING"};
654 
655   os << char_value_[static_cast<uint8_t>(state)] << " (" << "0x" << std::setfill('0')
656      << std::setw(2) << static_cast<int>(state) << ")";
657   return os;
658 }
operator <<(std::ostream & os,const types::CigState & state)659 std::ostream& operator<<(std::ostream& os, const types::CigState& state) {
660   static const char* char_value_[5] = {"NONE", "CREATING", "CREATED", "REMOVING", "RECOVERING"};
661 
662   os << char_value_[static_cast<uint8_t>(state)] << " (" << "0x" << std::setfill('0')
663      << std::setw(2) << static_cast<int>(state) << ")";
664   return os;
665 }
operator <<(std::ostream & os,const types::AseState & state)666 std::ostream& operator<<(std::ostream& os, const types::AseState& state) {
667   static const char* char_value_[7] = {
668           "IDLE",      "CODEC_CONFIGURED", "QOS_CONFIGURED", "ENABLING",
669           "STREAMING", "DISABLING",        "RELEASING",
670   };
671 
672   os << char_value_[static_cast<uint8_t>(state)] << " (" << "0x" << std::setfill('0')
673      << std::setw(2) << static_cast<int>(state) << ")";
674   return os;
675 }
676 
operator <<(std::ostream & os,const LeAudioCodecId & codec_id)677 std::ostream& operator<<(std::ostream& os, const LeAudioCodecId& codec_id) {
678   os << "LeAudioCodecId{CodingFormat: " << loghex(codec_id.coding_format)
679      << ", CompanyId: " << loghex(codec_id.vendor_company_id)
680      << ", CodecId: " << loghex(codec_id.vendor_codec_id) << "}";
681   return os;
682 }
683 
operator <<(std::ostream & os,const types::LeAudioCoreCodecConfig & config)684 std::ostream& operator<<(std::ostream& os, const types::LeAudioCoreCodecConfig& config) {
685   os << "LeAudioCoreCodecConfig{SamplFreq: " << loghex(*config.sampling_frequency)
686      << ", FrameDur: " << loghex(*config.frame_duration)
687      << ", OctetsPerFrame: " << int(*config.octets_per_codec_frame)
688      << ", CodecFramesBlocksPerSDU: " << int(*config.codec_frames_blocks_per_sdu)
689      << ", AudioChanLoc: " << loghex(*config.audio_channel_allocation) << "}";
690   return os;
691 }
692 
contextTypeToStr(const LeAudioContextType & context)693 std::string contextTypeToStr(const LeAudioContextType& context) {
694   switch (context) {
695     case LeAudioContextType::UNINITIALIZED:
696       return "UNINITIALIZED";
697     case LeAudioContextType::UNSPECIFIED:
698       return "UNSPECIFIED";
699     case LeAudioContextType::CONVERSATIONAL:
700       return "CONVERSATIONAL";
701     case LeAudioContextType::MEDIA:
702       return "MEDIA";
703     case LeAudioContextType::GAME:
704       return "GAME";
705     case LeAudioContextType::INSTRUCTIONAL:
706       return "INSTRUCTIONAL";
707     case LeAudioContextType::VOICEASSISTANTS:
708       return "VOICEASSISTANTS";
709     case LeAudioContextType::LIVE:
710       return "LIVE";
711     case LeAudioContextType::SOUNDEFFECTS:
712       return "SOUNDEFFECTS";
713     case LeAudioContextType::NOTIFICATIONS:
714       return "NOTIFICATIONS";
715     case LeAudioContextType::RINGTONE:
716       return "RINGTONE";
717     case LeAudioContextType::ALERTS:
718       return "ALERTS";
719     case LeAudioContextType::EMERGENCYALARM:
720       return "EMERGENCYALARM";
721     default:
722       return "UNKNOWN";
723   }
724 }
725 
operator <<(std::ostream & os,const LeAudioContextType & context)726 std::ostream& operator<<(std::ostream& os, const LeAudioContextType& context) {
727   os << contextTypeToStr(context);
728   return os;
729 }
730 
operator |(std::underlying_type<LeAudioContextType>::type lhs,const LeAudioContextType rhs)731 AudioContexts operator|(std::underlying_type<LeAudioContextType>::type lhs,
732                         const LeAudioContextType rhs) {
733   using T = std::underlying_type<LeAudioContextType>::type;
734   return AudioContexts(lhs | static_cast<T>(rhs));
735 }
736 
operator |=(AudioContexts & lhs,AudioContexts const & rhs)737 AudioContexts& operator|=(AudioContexts& lhs, AudioContexts const& rhs) {
738   lhs = AudioContexts(lhs.value() | rhs.value());
739   return lhs;
740 }
741 
operator &=(AudioContexts & lhs,AudioContexts const & rhs)742 AudioContexts& operator&=(AudioContexts& lhs, AudioContexts const& rhs) {
743   lhs = AudioContexts(lhs.value() & rhs.value());
744   return lhs;
745 }
746 
ToHexString(const LeAudioContextType & value)747 std::string ToHexString(const LeAudioContextType& value) {
748   using T = std::underlying_type<LeAudioContextType>::type;
749   return bluetooth::common::ToHexString(static_cast<T>(value));
750 }
751 
to_string() const752 std::string AudioContexts::to_string() const {
753   std::stringstream s;
754   s << bluetooth::common::ToHexString(mValue);
755   if (mValue != 0) {
756     s << " [";
757     auto initial_pos = s.tellp();
758     for (auto ctx : bluetooth::le_audio::types::kLeAudioContextAllTypesArray) {
759       if (test(ctx)) {
760         if (s.tellp() != initial_pos) {
761           s << " | ";
762         }
763         s << ctx;
764       }
765     }
766     s << "]";
767   }
768   return s.str();
769 }
770 
operator <<(std::ostream & os,const AudioContexts & contexts)771 std::ostream& operator<<(std::ostream& os, const AudioContexts& contexts) {
772   os << contexts.to_string();
773   return os;
774 }
775 
776 template <typename T>
get(uint8_t direction) const777 const T& BidirectionalPair<T>::get(uint8_t direction) const {
778   log::assert_that(direction < types::kLeAudioDirectionBoth,
779                    "Unsupported complex direction. Consider using "
780                    "get_bidirectional<>() instead.");
781   return (direction == types::kLeAudioDirectionSink) ? sink : source;
782 }
783 
784 template <typename T>
get(uint8_t direction)785 T& BidirectionalPair<T>::get(uint8_t direction) {
786   log::assert_that(direction < types::kLeAudioDirectionBoth,
787                    "Unsupported complex direction. Reference to a single "
788                    "complex direction value is not supported.");
789   return (direction == types::kLeAudioDirectionSink) ? sink : source;
790 }
791 
792 /* Bidirectional getter trait for AudioContexts bidirectional pair */
793 template <>
get_bidirectional(BidirectionalPair<AudioContexts> p)794 AudioContexts get_bidirectional(BidirectionalPair<AudioContexts> p) {
795   return p.sink | p.source;
796 }
797 
798 template <>
get_bidirectional(BidirectionalPair<std::vector<uint8_t>> bidir)799 std::vector<uint8_t> get_bidirectional(BidirectionalPair<std::vector<uint8_t>> bidir) {
800   std::vector<uint8_t> res = bidir.sink;
801   res.insert(std::end(res), std::begin(bidir.source), std::end(bidir.source));
802   return res;
803 }
804 
805 template <>
get_bidirectional(BidirectionalPair<AudioLocations> bidir)806 AudioLocations get_bidirectional(BidirectionalPair<AudioLocations> bidir) {
807   return bidir.sink | bidir.source;
808 }
809 
operator <<(std::ostream & os,const le_audio::types::IsoDataPathConfiguration & config)810 std::ostream& operator<<(std::ostream& os,
811                          const le_audio::types::IsoDataPathConfiguration& config) {
812   os << "IsoDataPathCfg{codecId: " << config.codecId << ", isTransparent: " << config.isTransparent
813      << ", controllerDelayUs: " << config.controllerDelayUs
814      << ", configuration.size: " << config.configuration.size() << "}";
815   return os;
816 }
817 
operator <<(std::ostream & os,const le_audio::types::DataPathConfiguration & config)818 std::ostream& operator<<(std::ostream& os, const le_audio::types::DataPathConfiguration& config) {
819   os << "DataPathCfg{datapathId: " << +config.dataPathId
820      << ", dataPathCfg.size: " << +config.dataPathConfig.size()
821      << ", isoDataPathCfg: " << config.isoDataPathConfig << "}";
822   return os;
823 }
824 
operator <<(std::ostream & os,const LeAudioMetadata & config)825 std::ostream& operator<<(std::ostream& os, const LeAudioMetadata& config) {
826   os << "LeAudioMetadata{";
827   if (config.preferred_audio_context) {
828     os << "preferred_audio_context: ";
829     os << AudioContexts(config.preferred_audio_context.value());
830   }
831   if (config.streaming_audio_context) {
832     os << ", streaming_audio_context: ";
833     os << AudioContexts(config.streaming_audio_context.value());
834   }
835   if (config.program_info) {
836     os << ", program_info: ";
837     os << config.program_info.value();
838   }
839   if (config.language) {
840     os << ", language: ";
841     os << config.language.value();
842   }
843   if (config.ccid_list) {
844     os << ", ccid_list: ";
845     os << base::HexEncode(config.ccid_list.value().data(), config.ccid_list.value().size());
846   }
847   if (config.parental_rating) {
848     os << ", parental_rating: ";
849     os << (int)config.parental_rating.value();
850   }
851   if (config.program_info_uri) {
852     os << ", program_info_uri: ";
853     os << config.program_info_uri.value();
854   }
855   if (config.extended_metadata) {
856     os << ", extended_metadata: ";
857     os << base::HexEncode(config.extended_metadata.value().data(),
858                           config.extended_metadata.value().size());
859   }
860   if (config.vendor_specific) {
861     os << ", vendor_specific: ";
862     os << base::HexEncode(config.vendor_specific.value().data(),
863                           config.vendor_specific.value().size());
864   }
865   if (config.audio_active_state) {
866     os << ", audio_active_state: ";
867     os << config.audio_active_state.value();
868   }
869   if (config.broadcast_audio_immediate_rendering) {
870     os << ", broadcast_audio_immediate_rendering: ";
871     os << config.broadcast_audio_immediate_rendering.value();
872   }
873   os << "}";
874   return os;
875 }
876 
877 template struct BidirectionalPair<AudioContexts>;
878 template struct BidirectionalPair<AudioLocations>;
879 template struct BidirectionalPair<CisType>;
880 template struct BidirectionalPair<LeAudioConfigurationStrategy>;
881 template struct BidirectionalPair<ase*>;
882 template struct BidirectionalPair<std::string>;
883 template struct BidirectionalPair<std::vector<uint8_t>>;
884 template struct BidirectionalPair<stream_configuration>;
885 template struct BidirectionalPair<stream_parameters>;
886 template struct BidirectionalPair<uint16_t>;
887 template struct BidirectionalPair<uint8_t>;
888 template struct BidirectionalPair<bool>;
889 template struct BidirectionalPair<int>;
890 template struct BidirectionalPair<std::vector<set_configurations::AseConfiguration>>;
891 template struct BidirectionalPair<set_configurations::QosConfigSetting>;
892 template struct BidirectionalPair<
893         std::unique_ptr<const bluetooth::le_audio::btle_audio_codec_config_t>>;
894 
895 }  // namespace types
896 }  // namespace bluetooth::le_audio
897