• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 namespace bluetooth::le_audio {
52 using types::acs_ac_record;
53 using types::LeAudioContextType;
54 
55 namespace types {
56 using types::CodecConfigSetting;
57 using types::kLeAudioCodingFormatLC3;
58 using types::LeAudioCoreCodecConfig;
59 
GetOctetsPerFrame() const60 uint16_t CodecConfigSetting::GetOctetsPerFrame() const {
61   switch (id.coding_format) {
62     case kLeAudioCodingFormatLC3:
63       return params.GetAsCoreCodecConfig().GetOctetsPerFrame();
64     default:
65       log::warn(", invalid codec id: 0x{:02x}", id.coding_format);
66       return 0;
67   }
68 }
69 
GetSamplingFrequencyHz() const70 uint32_t CodecConfigSetting::GetSamplingFrequencyHz() const {
71   // We also mandate the sampling frequency parameter for vendor spec. codecs
72   return params.GetAsCoreCodecConfig().GetSamplingFrequencyHz();
73 }
74 
GetDataIntervalUs() const75 uint32_t CodecConfigSetting::GetDataIntervalUs() const {
76   switch (id.coding_format) {
77     case kLeAudioCodingFormatLC3:
78       return params.GetAsCoreCodecConfig().GetFrameDurationUs() *
79              params.GetAsCoreCodecConfig().codec_frames_blocks_per_sdu.value_or(1);
80     default:
81       log::warn(", invalid codec id: 0x{:02x}", id.coding_format);
82       return 0;
83   }
84 }
85 
GetBitsPerSample() const86 uint8_t CodecConfigSetting::GetBitsPerSample() const {
87   switch (id.coding_format) {
88     case kLeAudioCodingFormatLC3:
89       /* XXX LC3 supports 16, 24, 32 */
90       return 16;
91     default:
92       log::warn(", invalid codec id: 0x{:02x}", id.coding_format);
93       return 0;
94   }
95 }
96 
operator <<(std::ostream & os,const QosConfigSetting & config)97 std::ostream& operator<<(std::ostream& os, const QosConfigSetting& config) {
98   os << "QosConfigSetting{";
99   os << "targetLatency: " << (int)config.target_latency;
100   os << ", retransmissionNum: " << (int)config.retransmission_number;
101   os << ", maxTransportLatency: " << (int)config.max_transport_latency;
102   os << ", sduIntervalUs: " << (int)config.sduIntervalUs;
103   os << ", maxSdu: " << (int)config.maxSdu;
104   os << "}";
105   return os;
106 }
107 
operator <<(std::ostream & os,const AseConfiguration & config)108 std::ostream& operator<<(std::ostream& os, const AseConfiguration& config) {
109   os << "AseConfiguration{";
110   os << "dataPath: " << config.data_path_configuration;
111   os << ", codec: " << config.codec;
112   os << ", qos: " << config.qos;
113   os << "}";
114   return os;
115 }
116 
operator <<(std::ostream & os,const AudioSetConfiguration & config)117 std::ostream& operator<<(std::ostream& os, const AudioSetConfiguration& config) {
118   os << "AudioSetConfiguration{";
119   os << "name: " << config.name;
120   os << ", packing: " << (int)config.packing;
121   os << ", sinkConfs: [";
122   for (auto const& conf : config.confs.sink) {
123     os << conf;
124     os << ", ";
125   }
126   os << "], sourceConfs: [";
127   for (auto const& conf : config.confs.source) {
128     os << conf;
129     os << ", ";
130   }
131   os << "]}";
132   return os;
133 }
134 
operator <<(std::ostream & os,const CodecConfigSetting & config)135 std::ostream& operator<<(std::ostream& os, const CodecConfigSetting& config) {
136   os << "CodecConfigSetting{";
137   os << ", id: " << config.id;
138   os << ", codecSpecParams: " << config.params.GetAsCoreCodecConfig();
139   os << ", bitsPerSample: " << (int)config.GetBitsPerSample();
140   os << ", channelCountPerIsoStream: " << (int)config.GetChannelCountPerIsoStream();
141   if (!config.vendor_params.empty()) {
142     os << ", vendorParams: "
143        << base::HexEncode(config.vendor_params.data(), config.vendor_params.size());
144   }
145   os << "}";
146   return os;
147 }
148 
149 /* Helper map for matching various frequency notations */
150 const std::map<uint8_t, uint32_t> LeAudioCoreCodecConfig::sampling_freq_map = {
151         {codec_spec_conf::kLeAudioSamplingFreq8000Hz, LeAudioCodecConfiguration::kSampleRate8000},
152         {codec_spec_conf::kLeAudioSamplingFreq16000Hz, LeAudioCodecConfiguration::kSampleRate16000},
153         {codec_spec_conf::kLeAudioSamplingFreq24000Hz, LeAudioCodecConfiguration::kSampleRate24000},
154         {codec_spec_conf::kLeAudioSamplingFreq32000Hz, LeAudioCodecConfiguration::kSampleRate32000},
155         {codec_spec_conf::kLeAudioSamplingFreq44100Hz, LeAudioCodecConfiguration::kSampleRate44100},
156         {codec_spec_conf::kLeAudioSamplingFreq48000Hz,
157          LeAudioCodecConfiguration::kSampleRate48000}};
158 
159 /* Helper map for matching various frequency notations */
160 const std::map<uint32_t, uint8_t> LeAudioCoreCodecConfig::sample_rate_map = {
161         {LeAudioCodecConfiguration::kSampleRate8000, codec_spec_conf::kLeAudioSamplingFreq8000Hz},
162         {LeAudioCodecConfiguration::kSampleRate16000, codec_spec_conf::kLeAudioSamplingFreq16000Hz},
163         {LeAudioCodecConfiguration::kSampleRate24000, codec_spec_conf::kLeAudioSamplingFreq24000Hz},
164         {LeAudioCodecConfiguration::kSampleRate32000, codec_spec_conf::kLeAudioSamplingFreq32000Hz},
165         {LeAudioCodecConfiguration::kSampleRate44100, codec_spec_conf::kLeAudioSamplingFreq44100Hz},
166         {LeAudioCodecConfiguration::kSampleRate48000, codec_spec_conf::kLeAudioSamplingFreq48000Hz},
167 };
168 
169 /* Helper map for matching various frame durations notations */
170 const std::map<uint8_t, uint32_t> LeAudioCoreCodecConfig::frame_duration_map = {
171         {codec_spec_conf::kLeAudioCodecFrameDur7500us, LeAudioCodecConfiguration::kInterval7500Us},
172         {codec_spec_conf::kLeAudioCodecFrameDur10000us,
173          LeAudioCodecConfiguration::kInterval10000Us}};
174 
175 /* Helper map for matching various frame durations notations */
176 const std::map<uint32_t, uint8_t> LeAudioCoreCodecConfig::data_interval_map = {
177         {LeAudioCodecConfiguration::kInterval7500Us, codec_spec_conf::kLeAudioCodecFrameDur7500us},
178         {LeAudioCodecConfiguration::kInterval10000Us,
179          codec_spec_conf::kLeAudioCodecFrameDur10000us},
180 };
181 
CapabilityTypeToStr(const uint8_t & type)182 static std::string CapabilityTypeToStr(const uint8_t& type) {
183   switch (type) {
184     case codec_spec_caps::kLeAudioLtvTypeSupportedSamplingFrequencies:
185       return "Supported Sampling Frequencies";
186     case codec_spec_caps::kLeAudioLtvTypeSupportedFrameDurations:
187       return "Supported Frame Durations";
188     case codec_spec_caps::kLeAudioLtvTypeSupportedAudioChannelCounts:
189       return "Supported Audio Channel Count";
190     case codec_spec_caps::kLeAudioLtvTypeSupportedOctetsPerCodecFrame:
191       return "Supported Octets Per Codec Frame";
192     case codec_spec_caps::kLeAudioLtvTypeSupportedMaxCodecFramesPerSdu:
193       return "Supported Max Codec Frames Per SDU";
194     default:
195       return "Unknown";
196   }
197 }
198 
CapabilityValueToStr(const uint8_t & type,const std::vector<uint8_t> & value)199 static std::string CapabilityValueToStr(const uint8_t& type, const std::vector<uint8_t>& value) {
200   std::string string = "";
201 
202   switch (type) {
203     case codec_spec_conf::kLeAudioLtvTypeSamplingFreq: {
204       if (value.size() != 2) {
205         return "Invalid size";
206       }
207 
208       uint16_t u16_val = VEC_UINT8_TO_UINT16(value);
209 
210       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq8000Hz) {
211         string += "8";
212       }
213       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq11025Hz) {
214         string += std::string(string.empty() ? "" : "|") + "11.025";
215       }
216       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq16000Hz) {
217         string += std::string(string.empty() ? "" : "|") + "16";
218       }
219       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq22050Hz) {
220         string += std::string(string.empty() ? "" : "|") + "22.050";
221       }
222       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq24000Hz) {
223         string += std::string(string.empty() ? "" : "|") + "24";
224       }
225       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq32000Hz) {
226         string += std::string(string.empty() ? "" : "|") + "32";
227       }
228       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq44100Hz) {
229         string += std::string(string.empty() ? "" : "|") + "44.1";
230       }
231       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq48000Hz) {
232         string += std::string(string.empty() ? "" : "|") + "48";
233       }
234       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq88200Hz) {
235         string += std::string(string.empty() ? "" : "|") + "88.2";
236       }
237       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq96000Hz) {
238         string += std::string(string.empty() ? "" : "|") + "96";
239       }
240       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq176400Hz) {
241         string += std::string(string.empty() ? "" : "|") + "176.4";
242       }
243       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq192000Hz) {
244         string += std::string(string.empty() ? "" : "|") + "192";
245       }
246       if (u16_val & codec_spec_caps::kLeAudioSamplingFreq384000Hz) {
247         string += std::string(string.empty() ? "" : "|") + "384";
248       }
249 
250       return string += " [kHz]\n";
251     }
252     case codec_spec_conf::kLeAudioLtvTypeFrameDuration: {
253       if (value.size() != 1) {
254         return "Invalid size";
255       }
256 
257       uint8_t u8_val = VEC_UINT8_TO_UINT8(value);
258 
259       if (u8_val & codec_spec_caps::kLeAudioCodecFrameDur7500us) {
260         string += "7.5";
261       }
262       if (u8_val & codec_spec_caps::kLeAudioCodecFrameDur10000us) {
263         string += std::string(string.empty() ? "" : "|") + "10";
264       }
265       if (u8_val & codec_spec_caps::kLeAudioCodecFrameDurPrefer7500us) {
266         string += std::string(string.empty() ? "" : "|") + "7.5 preferred";
267       }
268       if (u8_val & codec_spec_caps::kLeAudioCodecFrameDurPrefer10000us) {
269         string += std::string(string.empty() ? "" : "|") + "10 preferred";
270       }
271 
272       return string += " [ms]\n";
273     }
274     case codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation: {
275       if (value.size() != 1) {
276         return "Invalid size";
277       }
278 
279       uint8_t u8_val = VEC_UINT8_TO_UINT8(value);
280 
281       if (u8_val & codec_spec_caps::kLeAudioCodecChannelCountNone) {
282         string += "0";
283       }
284       if (u8_val & codec_spec_caps::kLeAudioCodecChannelCountSingleChannel) {
285         string += std::string(string.empty() ? "" : "|") + "1";
286       }
287       if (u8_val & codec_spec_caps::kLeAudioCodecChannelCountTwoChannel) {
288         string += std::string(string.empty() ? "" : "|") + "2";
289       }
290       if (u8_val & codec_spec_caps::kLeAudioCodecChannelCountThreeChannel) {
291         string += std::string(string.empty() ? "" : "|") + "3";
292       }
293       if (u8_val & codec_spec_caps::kLeAudioCodecChannelCountFourChannel) {
294         string += std::string(string.empty() ? "" : "|") + "4";
295       }
296       if (u8_val & codec_spec_caps::kLeAudioCodecChannelCountFiveChannel) {
297         string += std::string(string.empty() ? "" : "|") + "5";
298       }
299       if (u8_val & codec_spec_caps::kLeAudioCodecChannelCountSixChannel) {
300         string += std::string(string.empty() ? "" : "|") + "6";
301       }
302       if (u8_val & codec_spec_caps::kLeAudioCodecChannelCountSevenChannel) {
303         string += std::string(string.empty() ? "" : "|") + "7";
304       }
305       if (u8_val & codec_spec_caps::kLeAudioCodecChannelCountEightChannel) {
306         string += std::string(string.empty() ? "" : "|") + "8";
307       }
308 
309       return string += " channel/s\n";
310     }
311     case codec_spec_conf::kLeAudioLtvTypeOctetsPerCodecFrame: {
312       if (value.size() != 4) {
313         return "Invalid size";
314       }
315 
316       uint16_t u16_min_number_of_octets = VEC_UINT8_TO_UINT16(value);
317       uint16_t u16_max_number_of_octets =
318               OFF_VEC_UINT8_TO_UINT16(value, sizeof(u16_min_number_of_octets));
319 
320       string += "Minimum: " + std::to_string(u16_min_number_of_octets);
321       string += ", Maximum: " + std::to_string(u16_max_number_of_octets) + "\n";
322 
323       return string;
324     }
325     case codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu: {
326       if (value.size() != 1) {
327         return "Invalid size";
328       }
329 
330       uint8_t u8_val = VEC_UINT8_TO_UINT8(value);
331 
332       string += std::to_string(u8_val) + " frame/s\n";
333 
334       return string;
335     }
336     default:
337       return base::HexEncode(value.data(), value.size()) + "\n";
338   }
339 }
340 
CodecCapabilitiesLtvFormat(const uint8_t & type,const std::vector<uint8_t> & value)341 std::string CodecCapabilitiesLtvFormat(const uint8_t& type, const std::vector<uint8_t>& value) {
342   std::string string = "";
343 
344   string += CapabilityTypeToStr(type) + ": ";
345   string += CapabilityValueToStr(type, value);
346 
347   return string;
348 }
349 
Find(uint8_t type) const350 std::optional<std::vector<uint8_t>> LeAudioLtvMap::Find(uint8_t type) const {
351   auto iter = std::find_if(values.cbegin(), values.cend(),
352                            [type](const auto& value) { return value.first == type; });
353 
354   if (iter == values.cend()) {
355     return std::nullopt;
356   }
357 
358   return iter->second;
359 }
360 
RawPacket(uint8_t * p_buf) const361 uint8_t* LeAudioLtvMap::RawPacket(uint8_t* p_buf) const {
362   for (auto const& value : values) {
363     UINT8_TO_STREAM(p_buf, value.second.size() + 1);
364     UINT8_TO_STREAM(p_buf, value.first);
365     ARRAY_TO_STREAM(p_buf, value.second.data(), static_cast<int>(value.second.size()));
366   }
367 
368   return p_buf;
369 }
370 
RawPacket() const371 std::vector<uint8_t> LeAudioLtvMap::RawPacket() const {
372   std::vector<uint8_t> data(RawPacketSize());
373   RawPacket(data.data());
374   return data;
375 }
376 
Append(const LeAudioLtvMap & other)377 void LeAudioLtvMap::Append(const LeAudioLtvMap& other) {
378   /* This will override values for the already existing keys */
379   for (auto& el : other.values) {
380     values[el.first] = el.second;
381   }
382 
383   invalidate();
384 }
385 
Parse(const uint8_t * p_value,uint8_t len,bool & success)386 LeAudioLtvMap LeAudioLtvMap::Parse(const uint8_t* p_value, uint8_t len, bool& success) {
387   LeAudioLtvMap ltv_map;
388   success = ltv_map.Parse(p_value, len);
389   if (!success) {
390     log::error("Error parsing LTV map");
391   }
392   return ltv_map;
393 }
394 
Parse(const uint8_t * p_value,uint8_t len)395 bool LeAudioLtvMap::Parse(const uint8_t* p_value, uint8_t len) {
396   if (len > 0) {
397     const auto p_value_end = p_value + len;
398 
399     while ((p_value_end - p_value) > 0) {
400       uint8_t ltv_len;
401       STREAM_TO_UINT8(ltv_len, p_value);
402 
403       // Unusual, but possible case
404       if (ltv_len == 0) {
405         continue;
406       }
407 
408       if (p_value_end < (p_value + ltv_len)) {
409         log::error("Invalid ltv_len: {}", static_cast<int>(ltv_len));
410         invalidate();
411         return false;
412       }
413 
414       uint8_t ltv_type;
415       STREAM_TO_UINT8(ltv_type, p_value);
416       ltv_len -= sizeof(ltv_type);
417 
418       const auto p_temp = p_value;
419       p_value += ltv_len;
420 
421       std::vector<uint8_t> ltv_value(p_temp, p_value);
422       values.emplace(ltv_type, std::move(ltv_value));
423     }
424   }
425   invalidate();
426 
427   return true;
428 }
429 
RawPacketSize() const430 size_t LeAudioLtvMap::RawPacketSize() const {
431   size_t bytes = 0;
432 
433   for (auto const& value : values) {
434     bytes += (/* ltv_len + ltv_type */ 2 + value.second.size());
435   }
436 
437   return bytes;
438 }
439 
ToString(const std::string & indent_string,std::string (* format)(const uint8_t &,const std::vector<uint8_t> &)) const440 std::string LeAudioLtvMap::ToString(const std::string& indent_string,
441                                     std::string (*format)(const uint8_t&,
442                                                           const std::vector<uint8_t>&)) const {
443   std::string debug_str;
444 
445   for (const auto& value : values) {
446     std::stringstream sstream;
447 
448     if (format == nullptr) {
449       sstream << indent_string + "type: " << std::to_string(value.first)
450               << "\tlen: " << std::to_string(value.second.size())
451               << "\tdata: " << base::HexEncode(value.second.data(), value.second.size()) + "\n";
452     } else {
453       sstream << indent_string + format(value.first, value.second);
454     }
455 
456     debug_str += sstream.str();
457   }
458 
459   return debug_str;
460 }
461 
GetAsCoreCodecConfig() const462 const struct LeAudioCoreCodecConfig& LeAudioLtvMap::GetAsCoreCodecConfig() const {
463   log::assert_that(!core_capabilities, "LTVs were already parsed for capabilities!");
464   log::assert_that(!metadata, "LTVs were already parsed for metadata!");
465 
466   if (!core_config) {
467     core_config = LtvMapToCoreCodecConfig(*this);
468   }
469   return *core_config;
470 }
471 
GetAsCoreCodecCapabilities() const472 const struct LeAudioCoreCodecCapabilities& LeAudioLtvMap::GetAsCoreCodecCapabilities() const {
473   log::assert_that(!core_config, "LTVs were already parsed for configurations!");
474   log::assert_that(!metadata, "LTVs were already parsed for metadata!");
475 
476   if (!core_capabilities) {
477     core_capabilities = LtvMapToCoreCodecCapabilities(*this);
478   }
479   return *core_capabilities;
480 }
481 
GetAsLeAudioMetadata() const482 const struct LeAudioMetadata& LeAudioLtvMap::GetAsLeAudioMetadata() const {
483   log::assert_that(!core_config, "LTVs were already parsed for configurations!");
484   log::assert_that(!core_capabilities, "LTVs were already parsed for capabilities!");
485 
486   if (!metadata) {
487     metadata = LtvMapToMetadata(*this);
488   }
489   return *metadata;
490 }
491 
RemoveAllTypes(const LeAudioLtvMap & other)492 void LeAudioLtvMap::RemoveAllTypes(const LeAudioLtvMap& other) {
493   for (auto const& [key, _] : other.values) {
494     Remove(key);
495   }
496 }
497 
GetIntersection(const LeAudioLtvMap & other) const498 LeAudioLtvMap LeAudioLtvMap::GetIntersection(const LeAudioLtvMap& other) const {
499   LeAudioLtvMap result;
500   for (auto const& [key, value] : values) {
501     auto entry = other.Find(key);
502     if (entry->size() != value.size()) {
503       continue;
504     }
505     if (memcmp(entry->data(), value.data(), value.size()) == 0) {
506       result.Add(key, value);
507     }
508   }
509   return result;
510 }
511 
512 }  // namespace types
513 
AppendMetadataLtvEntryForCcidList(std::vector<uint8_t> & metadata,const std::vector<uint8_t> & ccid_list)514 void AppendMetadataLtvEntryForCcidList(std::vector<uint8_t>& metadata,
515                                        const std::vector<uint8_t>& ccid_list) {
516   if (ccid_list.size() == 0) {
517     log::warn("Empty CCID list.");
518     return;
519   }
520 
521   metadata.push_back(static_cast<uint8_t>(types::kLeAudioMetadataTypeLen + ccid_list.size()));
522   metadata.push_back(static_cast<uint8_t>(types::kLeAudioMetadataTypeCcidList));
523 
524   metadata.insert(metadata.end(), ccid_list.begin(), ccid_list.end());
525 }
526 
AppendMetadataLtvEntryForStreamingContext(std::vector<uint8_t> & metadata,types::AudioContexts context_type)527 void AppendMetadataLtvEntryForStreamingContext(std::vector<uint8_t>& metadata,
528                                                types::AudioContexts context_type) {
529   std::vector<uint8_t> streaming_context_ltv_entry;
530 
531   streaming_context_ltv_entry.resize(types::kLeAudioMetadataTypeLen +
532                                      types::kLeAudioMetadataLenLen +
533                                      types::kLeAudioMetadataStreamingAudioContextLen);
534   uint8_t* streaming_context_ltv_entry_buf = streaming_context_ltv_entry.data();
535 
536   UINT8_TO_STREAM(streaming_context_ltv_entry_buf,
537                   types::kLeAudioMetadataTypeLen + types::kLeAudioMetadataStreamingAudioContextLen);
538   UINT8_TO_STREAM(streaming_context_ltv_entry_buf,
539                   types::kLeAudioMetadataTypeStreamingAudioContext);
540   UINT16_TO_STREAM(streaming_context_ltv_entry_buf, context_type.value());
541 
542   metadata.insert(metadata.end(), streaming_context_ltv_entry.begin(),
543                   streaming_context_ltv_entry.end());
544 }
545 
GetMaxCodecFramesPerSduFromPac(const acs_ac_record * pac)546 uint8_t GetMaxCodecFramesPerSduFromPac(const acs_ac_record* pac) {
547   if (utils::IsCodecUsingLtvFormat(pac->codec_id)) {
548     auto tlv_ent = pac->codec_spec_caps.Find(
549             codec_spec_caps::kLeAudioLtvTypeSupportedMaxCodecFramesPerSdu);
550 
551     if (tlv_ent) {
552       return VEC_UINT8_TO_UINT8(tlv_ent.value());
553     }
554   }
555 
556   return 1;
557 }
558 
559 namespace types {
operator <<(std::ostream & os,const CisState & state)560 std::ostream& operator<<(std::ostream& os, const CisState& state) {
561   static const char* char_value_[5] = {"IDLE", "ASSIGNED", "CONNECTING", "CONNECTED",
562                                        "DISCONNECTING"};
563 
564   os << char_value_[static_cast<uint8_t>(state)] << " (" << "0x" << std::setfill('0')
565      << std::setw(2) << static_cast<int>(state) << ")";
566   return os;
567 }
operator <<(std::ostream & os,const DataPathState & state)568 std::ostream& operator<<(std::ostream& os, const DataPathState& state) {
569   static const char* char_value_[4] = {"IDLE", "CONFIGURING", "CONFIGURED", "REMOVING"};
570 
571   os << char_value_[static_cast<uint8_t>(state)] << " (" << "0x" << std::setfill('0')
572      << std::setw(2) << static_cast<int>(state) << ")";
573   return os;
574 }
operator <<(std::ostream & os,const types::CigState & state)575 std::ostream& operator<<(std::ostream& os, const types::CigState& state) {
576   static const char* char_value_[5] = {"NONE", "CREATING", "CREATED", "REMOVING", "RECOVERING"};
577 
578   os << char_value_[static_cast<uint8_t>(state)] << " (" << "0x" << std::setfill('0')
579      << std::setw(2) << static_cast<int>(state) << ")";
580   return os;
581 }
operator <<(std::ostream & os,const types::AseState & state)582 std::ostream& operator<<(std::ostream& os, const types::AseState& state) {
583   static const char* char_value_[7] = {
584           "IDLE",      "CODEC_CONFIGURED", "QOS_CONFIGURED", "ENABLING",
585           "STREAMING", "DISABLING",        "RELEASING",
586   };
587 
588   os << char_value_[static_cast<uint8_t>(state)] << " (" << "0x" << std::setfill('0')
589      << std::setw(2) << static_cast<int>(state) << ")";
590   return os;
591 }
592 
operator <<(std::ostream & os,const LeAudioCodecId & codec_id)593 std::ostream& operator<<(std::ostream& os, const LeAudioCodecId& codec_id) {
594   os << "LeAudioCodecId{CodingFormat: " << loghex(codec_id.coding_format)
595      << ", CompanyId: " << loghex(codec_id.vendor_company_id)
596      << ", CodecId: " << loghex(codec_id.vendor_codec_id) << "}";
597   return os;
598 }
599 
operator <<(std::ostream & os,const types::LeAudioCoreCodecConfig & config)600 std::ostream& operator<<(std::ostream& os, const types::LeAudioCoreCodecConfig& config) {
601   os << "LeAudioCoreCodecConfig{SamplFreq: " << loghex(*config.sampling_frequency)
602      << ", FrameDur: " << loghex(*config.frame_duration)
603      << ", OctetsPerFrame: " << int(*config.octets_per_codec_frame)
604      << ", CodecFramesBlocksPerSDU: " << int(*config.codec_frames_blocks_per_sdu)
605      << ", AudioChanLoc: " << loghex(*config.audio_channel_allocation) << "}";
606   return os;
607 }
608 
contextTypeToStr(const LeAudioContextType & context)609 std::string contextTypeToStr(const LeAudioContextType& context) {
610   switch (context) {
611     case LeAudioContextType::UNINITIALIZED:
612       return "UNINITIALIZED";
613     case LeAudioContextType::UNSPECIFIED:
614       return "UNSPECIFIED";
615     case LeAudioContextType::CONVERSATIONAL:
616       return "CONVERSATIONAL";
617     case LeAudioContextType::MEDIA:
618       return "MEDIA";
619     case LeAudioContextType::GAME:
620       return "GAME";
621     case LeAudioContextType::INSTRUCTIONAL:
622       return "INSTRUCTIONAL";
623     case LeAudioContextType::VOICEASSISTANTS:
624       return "VOICEASSISTANTS";
625     case LeAudioContextType::LIVE:
626       return "LIVE";
627     case LeAudioContextType::SOUNDEFFECTS:
628       return "SOUNDEFFECTS";
629     case LeAudioContextType::NOTIFICATIONS:
630       return "NOTIFICATIONS";
631     case LeAudioContextType::RINGTONE:
632       return "RINGTONE";
633     case LeAudioContextType::ALERTS:
634       return "ALERTS";
635     case LeAudioContextType::EMERGENCYALARM:
636       return "EMERGENCYALARM";
637     default:
638       return "UNKNOWN";
639   }
640 }
641 
operator <<(std::ostream & os,const LeAudioContextType & context)642 std::ostream& operator<<(std::ostream& os, const LeAudioContextType& context) {
643   os << contextTypeToStr(context);
644   return os;
645 }
646 
operator |(std::underlying_type<LeAudioContextType>::type lhs,const LeAudioContextType rhs)647 AudioContexts operator|(std::underlying_type<LeAudioContextType>::type lhs,
648                         const LeAudioContextType rhs) {
649   using T = std::underlying_type<LeAudioContextType>::type;
650   return AudioContexts(lhs | static_cast<T>(rhs));
651 }
652 
operator |=(AudioContexts & lhs,AudioContexts const & rhs)653 AudioContexts& operator|=(AudioContexts& lhs, AudioContexts const& rhs) {
654   lhs = AudioContexts(lhs.value() | rhs.value());
655   return lhs;
656 }
657 
operator &=(AudioContexts & lhs,AudioContexts const & rhs)658 AudioContexts& operator&=(AudioContexts& lhs, AudioContexts const& rhs) {
659   lhs = AudioContexts(lhs.value() & rhs.value());
660   return lhs;
661 }
662 
ToHexString(const LeAudioContextType & value)663 std::string ToHexString(const LeAudioContextType& value) {
664   using T = std::underlying_type<LeAudioContextType>::type;
665   return bluetooth::common::ToHexString(static_cast<T>(value));
666 }
667 
to_string() const668 std::string AudioContexts::to_string() const {
669   std::stringstream s;
670   s << bluetooth::common::ToHexString(mValue);
671   if (mValue != 0) {
672     s << " [";
673     auto initial_pos = s.tellp();
674     for (auto ctx : bluetooth::le_audio::types::kLeAudioContextAllTypesArray) {
675       if (test(ctx)) {
676         if (s.tellp() != initial_pos) {
677           s << " | ";
678         }
679         s << ctx;
680       }
681     }
682     s << "]";
683   }
684   return s.str();
685 }
686 
operator <<(std::ostream & os,const AudioContexts & contexts)687 std::ostream& operator<<(std::ostream& os, const AudioContexts& contexts) {
688   os << contexts.to_string();
689   return os;
690 }
691 
692 /* Bidirectional getter trait for AudioContexts bidirectional pair */
693 template <>
get_bidirectional(BidirectionalPair<AudioContexts> p)694 AudioContexts get_bidirectional(BidirectionalPair<AudioContexts> p) {
695   return p.sink | p.source;
696 }
697 
698 template <>
get_bidirectional(BidirectionalPair<std::vector<uint8_t>> bidir)699 std::vector<uint8_t> get_bidirectional(BidirectionalPair<std::vector<uint8_t>> bidir) {
700   std::vector<uint8_t> res = bidir.sink;
701   res.insert(std::end(res), std::begin(bidir.source), std::end(bidir.source));
702   return res;
703 }
704 
705 template <>
get_bidirectional(BidirectionalPair<AudioLocations> bidir)706 AudioLocations get_bidirectional(BidirectionalPair<AudioLocations> bidir) {
707   return bidir.sink | bidir.source;
708 }
709 
operator <<(std::ostream & os,const le_audio::types::IsoDataPathConfiguration & config)710 std::ostream& operator<<(std::ostream& os,
711                          const le_audio::types::IsoDataPathConfiguration& config) {
712   os << "IsoDataPathCfg{codecId: " << config.codecId << ", isTransparent: " << config.isTransparent
713      << ", controllerDelayUs: " << config.controllerDelayUs
714      << ", configuration.size: " << config.configuration.size() << "}";
715   return os;
716 }
717 
operator <<(std::ostream & os,const le_audio::types::DataPathConfiguration & config)718 std::ostream& operator<<(std::ostream& os, const le_audio::types::DataPathConfiguration& config) {
719   os << "DataPathCfg{datapathId: " << +config.dataPathId
720      << ", dataPathCfg.size: " << +config.dataPathConfig.size()
721      << ", isoDataPathCfg: " << config.isoDataPathConfig << "}";
722   return os;
723 }
724 
operator <<(std::ostream & os,const LeAudioMetadata & config)725 std::ostream& operator<<(std::ostream& os, const LeAudioMetadata& config) {
726   os << "LeAudioMetadata{";
727   if (config.preferred_audio_context) {
728     os << "preferred_audio_context: ";
729     os << AudioContexts(config.preferred_audio_context.value());
730   }
731   if (config.streaming_audio_context) {
732     os << ", streaming_audio_context: ";
733     os << AudioContexts(config.streaming_audio_context.value());
734   }
735   if (config.program_info) {
736     os << ", program_info: ";
737     os << config.program_info.value();
738   }
739   if (config.language) {
740     os << ", language: ";
741     os << config.language.value();
742   }
743   if (config.ccid_list) {
744     os << ", ccid_list: ";
745     os << base::HexEncode(config.ccid_list.value().data(), config.ccid_list.value().size());
746   }
747   if (config.parental_rating) {
748     os << ", parental_rating: ";
749     os << (int)config.parental_rating.value();
750   }
751   if (config.program_info_uri) {
752     os << ", program_info_uri: ";
753     os << config.program_info_uri.value();
754   }
755   if (config.extended_metadata) {
756     os << ", extended_metadata: ";
757     os << base::HexEncode(config.extended_metadata.value().data(),
758                           config.extended_metadata.value().size());
759   }
760   if (config.vendor_specific) {
761     os << ", vendor_specific: ";
762     os << base::HexEncode(config.vendor_specific.value().data(),
763                           config.vendor_specific.value().size());
764   }
765   if (config.audio_active_state) {
766     os << ", audio_active_state: ";
767     os << config.audio_active_state.value();
768   }
769   if (config.broadcast_audio_immediate_rendering) {
770     os << ", broadcast_audio_immediate_rendering: ";
771     os << config.broadcast_audio_immediate_rendering.value();
772   }
773   os << "}";
774   return os;
775 }
776 
777 }  // namespace types
778 }  // namespace bluetooth::le_audio
779