• 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 
27 #include "audio_hal_client/audio_hal_client.h"
28 #include "bt_types.h"
29 #include "bta_api.h"
30 #include "bta_le_audio_api.h"
31 #include "client_parser.h"
32 #include "gd/common/strings.h"
33 
34 namespace le_audio {
35 using types::acs_ac_record;
36 using types::LeAudioContextType;
37 
38 namespace set_configurations {
39 using set_configurations::CodecCapabilitySetting;
40 using types::CodecLocation;
41 using types::kLeAudioCodingFormatLC3;
42 using types::kLeAudioDirectionSink;
43 using types::kLeAudioDirectionSource;
44 using types::LeAudioLc3Config;
45 
min_req_devices_cnt(const AudioSetConfiguration * audio_set_conf)46 static uint8_t min_req_devices_cnt(
47     const AudioSetConfiguration* audio_set_conf) {
48   std::pair<uint8_t /* sink */, uint8_t /* source */> snk_src_pair(0, 0);
49 
50   for (auto ent : (*audio_set_conf).confs) {
51     if (ent.direction == kLeAudioDirectionSink)
52       snk_src_pair.first += ent.device_cnt;
53     if (ent.direction == kLeAudioDirectionSource)
54       snk_src_pair.second += ent.device_cnt;
55   }
56 
57   return std::max(snk_src_pair.first, snk_src_pair.second);
58 }
59 
min_req_devices_cnt(const AudioSetConfigurations * audio_set_confs)60 static uint8_t min_req_devices_cnt(
61     const AudioSetConfigurations* audio_set_confs) {
62   uint8_t curr_min_req_devices_cnt = 0xff;
63 
64   for (auto ent : *audio_set_confs) {
65     uint8_t req_devices_cnt = min_req_devices_cnt(ent);
66     if (req_devices_cnt < curr_min_req_devices_cnt)
67       curr_min_req_devices_cnt = req_devices_cnt;
68   }
69 
70   return curr_min_req_devices_cnt;
71 }
72 
get_cis_count(const AudioSetConfiguration & audio_set_conf,int expected_device_cnt,types::LeAudioConfigurationStrategy strategy,int avail_group_sink_ase_count,int avail_group_source_ase_count,uint8_t & out_current_cis_count_bidir,uint8_t & out_current_cis_count_unidir_sink,uint8_t & out_current_cis_count_unidir_source)73 inline void get_cis_count(const AudioSetConfiguration& audio_set_conf,
74                           int expected_device_cnt,
75                           types::LeAudioConfigurationStrategy strategy,
76                           int avail_group_sink_ase_count,
77                           int avail_group_source_ase_count,
78                           uint8_t& out_current_cis_count_bidir,
79                           uint8_t& out_current_cis_count_unidir_sink,
80                           uint8_t& out_current_cis_count_unidir_source) {
81   LOG_INFO("%s", audio_set_conf.name.c_str());
82 
83   /* Sum up the requirements from all subconfigs. They usually have different
84    * directions.
85    */
86   types::BidirectionalPair<uint8_t> config_ase_count = {0, 0};
87   int config_device_cnt = 0;
88 
89   for (auto ent : audio_set_conf.confs) {
90     if ((ent.direction == kLeAudioDirectionSink) &&
91         (ent.strategy != strategy)) {
92       LOG_DEBUG("Strategy does not match (%d != %d)- skip this configuration",
93                 static_cast<int>(ent.strategy), static_cast<int>(strategy));
94       return;
95     }
96 
97     /* Sum up sink and source ases */
98     if (ent.direction == kLeAudioDirectionSink) {
99       config_ase_count.sink += ent.ase_cnt;
100     }
101     if (ent.direction == kLeAudioDirectionSource) {
102       config_ase_count.source += ent.ase_cnt;
103     }
104 
105     /* Calculate the max device count */
106     config_device_cnt =
107         std::max(static_cast<uint8_t>(config_device_cnt), ent.device_cnt);
108   }
109 
110   LOG_DEBUG("Config sink ases: %d, source ases: %d, device count: %d",
111             config_ase_count.sink, config_ase_count.source, config_device_cnt);
112 
113   /* Reject configurations not matching our device count */
114   if (expected_device_cnt != config_device_cnt) {
115     LOG_DEBUG(" Device cnt %d != %d", expected_device_cnt, config_device_cnt);
116     return;
117   }
118 
119   /* Reject configurations requiring sink ASES if our group has none */
120   if ((avail_group_sink_ase_count == 0) && (config_ase_count.sink > 0)) {
121     LOG_DEBUG("Group does not have sink ASEs");
122     return;
123   }
124 
125   /* Reject configurations requiring source ASES if our group has none */
126   if ((avail_group_source_ase_count == 0) && (config_ase_count.source > 0)) {
127     LOG_DEBUG("Group does not have source ASEs");
128     return;
129   }
130 
131   /* If expected group size is 1, then make sure device has enough ASEs */
132   if (expected_device_cnt == 1) {
133     if ((config_ase_count.sink > avail_group_sink_ase_count) ||
134         (config_ase_count.source > avail_group_source_ase_count)) {
135       LOG_DEBUG("Single device group with not enought sink/source ASEs");
136       return;
137     }
138   }
139 
140   /* Configuration list is set in the prioritized order.
141    * it might happen that a higher prio configuration can be supported
142    * and is already taken into account (out_current_cis_count_* is non zero).
143    * Now let's try to ignore ortogonal configuration which would just
144    * increase our demant on number of CISes but will never happen
145    */
146   if (config_ase_count.sink == 0 && (out_current_cis_count_unidir_sink > 0 ||
147                                      out_current_cis_count_bidir > 0)) {
148     LOG_INFO(
149         "Higher prio configuration using sink ASEs has been taken into "
150         "account");
151     return;
152   }
153 
154   if (config_ase_count.source == 0 &&
155       (out_current_cis_count_unidir_source > 0 ||
156        out_current_cis_count_bidir > 0)) {
157     LOG_INFO(
158         "Higher prio configuration using source ASEs has been taken into "
159         "account");
160     return;
161   }
162 
163   /* Check how many bidirectional cises we can use */
164   uint8_t config_bidir_cis_count =
165       std::min(config_ase_count.sink, config_ase_count.source);
166   /* Count the remaining unidirectional cises */
167   uint8_t config_unidir_sink_cis_count =
168       config_ase_count.sink - config_bidir_cis_count;
169   uint8_t config_unidir_source_cis_count =
170       config_ase_count.source - config_bidir_cis_count;
171 
172   /* WARNING: Minipolicy which prioritizes bidirectional configs */
173   if (config_bidir_cis_count > out_current_cis_count_bidir) {
174     /* Correct all counters to represent this single config */
175     out_current_cis_count_bidir = config_bidir_cis_count;
176     out_current_cis_count_unidir_sink = config_unidir_sink_cis_count;
177     out_current_cis_count_unidir_source = config_unidir_source_cis_count;
178 
179   } else if (out_current_cis_count_bidir == 0) {
180     /* No bidirectionals possible yet. Calculate for unidirectional cises. */
181     if ((out_current_cis_count_unidir_sink == 0) &&
182         (out_current_cis_count_unidir_source == 0)) {
183       out_current_cis_count_unidir_sink = config_unidir_sink_cis_count;
184       out_current_cis_count_unidir_source = config_unidir_source_cis_count;
185     }
186   }
187 }
188 
get_cis_count(const AudioSetConfigurations & audio_set_confs,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)189 void get_cis_count(const AudioSetConfigurations& audio_set_confs,
190                    int expected_device_cnt,
191                    types::LeAudioConfigurationStrategy strategy,
192                    int avail_group_ase_snk_cnt, int avail_group_ase_src_count,
193                    uint8_t& out_cis_count_bidir,
194                    uint8_t& out_cis_count_unidir_sink,
195                    uint8_t& out_cis_count_unidir_source) {
196   LOG_INFO(
197       " strategy %d, group avail sink ases: %d, group avail source ases %d "
198       "expected_device_count %d",
199       static_cast<int>(strategy), avail_group_ase_snk_cnt,
200       avail_group_ase_src_count, expected_device_cnt);
201 
202   /* Look for the most optimal configuration and store the needed cis counts */
203   for (auto audio_set_conf : audio_set_confs) {
204     get_cis_count(*audio_set_conf, expected_device_cnt, strategy,
205                   avail_group_ase_snk_cnt, avail_group_ase_src_count,
206                   out_cis_count_bidir, out_cis_count_unidir_sink,
207                   out_cis_count_unidir_source);
208 
209     LOG_DEBUG(
210         "Intermediate step:  Bi-Directional: %d,"
211         " Uni-Directional Sink: %d, Uni-Directional Source: %d ",
212         out_cis_count_bidir, out_cis_count_unidir_sink,
213         out_cis_count_unidir_source);
214   }
215 
216   LOG_INFO(
217       " Maximum CIS count, Bi-Directional: %d,"
218       " Uni-Directional Sink: %d, Uni-Directional Source: %d",
219       out_cis_count_bidir, out_cis_count_unidir_sink,
220       out_cis_count_unidir_source);
221 }
222 
check_if_may_cover_scenario(const AudioSetConfigurations * audio_set_confs,uint8_t group_size)223 bool check_if_may_cover_scenario(const AudioSetConfigurations* audio_set_confs,
224                                  uint8_t group_size) {
225   if (!audio_set_confs) {
226     LOG(ERROR) << __func__ << ", no audio requirements for group";
227     return false;
228   }
229 
230   return group_size >= min_req_devices_cnt(audio_set_confs);
231 }
232 
check_if_may_cover_scenario(const AudioSetConfiguration * audio_set_conf,uint8_t group_size)233 bool check_if_may_cover_scenario(const AudioSetConfiguration* audio_set_conf,
234                                  uint8_t group_size) {
235   if (!audio_set_conf) {
236     LOG(ERROR) << __func__ << ", no audio requirement for group";
237     return false;
238   }
239 
240   return group_size >= min_req_devices_cnt(audio_set_conf);
241 }
242 
get_num_of_devices_in_configuration(const AudioSetConfiguration * audio_set_conf)243 uint8_t get_num_of_devices_in_configuration(
244     const AudioSetConfiguration* audio_set_conf) {
245   return min_req_devices_cnt(audio_set_conf);
246 }
247 
IsCodecConfigurationSupported(const types::LeAudioLtvMap & pacs,const LeAudioLc3Config & lc3_config)248 static bool IsCodecConfigurationSupported(const types::LeAudioLtvMap& pacs,
249                                           const LeAudioLc3Config& lc3_config) {
250   const auto& reqs = lc3_config.GetAsLtvMap();
251   uint8_t u8_req_val, u8_pac_val;
252   uint16_t u16_req_val, u16_pac_val;
253 
254   /* Sampling frequency */
255   auto req = reqs.Find(codec_spec_conf::kLeAudioCodecLC3TypeSamplingFreq);
256   auto pac = pacs.Find(codec_spec_caps::kLeAudioCodecLC3TypeSamplingFreq);
257   if (!req || !pac) {
258     LOG_DEBUG(", lack of sampling frequency fields");
259     return false;
260   }
261 
262   u8_req_val = VEC_UINT8_TO_UINT8(req.value());
263   u16_pac_val = VEC_UINT8_TO_UINT16(pac.value());
264 
265   /* TODO: Integrate with codec capabilities */
266   if (!(u16_pac_val &
267         codec_spec_caps::SamplingFreqConfig2Capability(u8_req_val))) {
268     /*
269      * Note: Requirements are in the codec configuration specification which
270      * are values coming from Assigned Numbers: Codec_Specific_Configuration
271      */
272     LOG_DEBUG(
273         " Req:SamplFreq= 0x%04x (Assigned Numbers: "
274         "Codec_Specific_Configuration)",
275         u8_req_val);
276     /* NOTE: Below is Codec specific cababilities comes from Assigned Numbers:
277      * Codec_Specific_Capabilities
278      */
279     LOG_DEBUG(
280         " Pac:SamplFreq= 0x%04x  (Assigned numbers: "
281         "Codec_Specific_Capabilities - bitfield)",
282         u16_pac_val);
283 
284     LOG_DEBUG(", sampling frequency not supported");
285     return false;
286   }
287 
288   /* Frame duration */
289   req = reqs.Find(codec_spec_conf::kLeAudioCodecLC3TypeFrameDuration);
290   pac = pacs.Find(codec_spec_caps::kLeAudioCodecLC3TypeFrameDuration);
291   if (!req || !pac) {
292     LOG_DEBUG(", lack of frame duration fields");
293     return false;
294   }
295 
296   u8_req_val = VEC_UINT8_TO_UINT8(req.value());
297   u8_pac_val = VEC_UINT8_TO_UINT8(pac.value());
298 
299   if ((u8_req_val != codec_spec_conf::kLeAudioCodecLC3FrameDur7500us &&
300        u8_req_val != codec_spec_conf::kLeAudioCodecLC3FrameDur10000us) ||
301       !(u8_pac_val &
302         (codec_spec_caps::FrameDurationConfig2Capability(u8_req_val)))) {
303     LOG_DEBUG(" Req:FrameDur=0x%04x", u8_req_val);
304     LOG_DEBUG(" Pac:FrameDur=0x%04x", u8_pac_val);
305     LOG_DEBUG(", frame duration not supported");
306     return false;
307   }
308 
309   uint8_t required_audio_chan_num = lc3_config.GetChannelCount();
310   pac = pacs.Find(codec_spec_caps::kLeAudioCodecLC3TypeAudioChannelCounts);
311 
312   /*
313    * BAP_Validation_r07 1.9.2 Audio channel support requirements
314    * "The Unicast Server shall support an Audio_Channel_Counts value of 0x01
315    * (0b00000001 = one channel) and may support other values defined by an
316    * implementation or by a higher-layer specification."
317    *
318    * Thus if Audio_Channel_Counts is not present in PAC LTV structure, we assume
319    * the Unicast Server supports mandatory one channel.
320    */
321   if (!pac) {
322     LOG_DEBUG(", no Audio_Channel_Counts field in PAC, using default 0x01");
323     u8_pac_val = 0x01;
324   } else {
325     u8_pac_val = VEC_UINT8_TO_UINT8(pac.value());
326   }
327 
328   if (!((1 << (required_audio_chan_num - 1)) & u8_pac_val)) {
329     LOG_DEBUG(" Req:AudioChanCnt=0x%04x", 1 << (required_audio_chan_num - 1));
330     LOG_DEBUG(" Pac:AudioChanCnt=0x%04x", u8_pac_val);
331     LOG_DEBUG(", channel count warning");
332     return false;
333   }
334 
335   /* Octets per frame */
336   req = reqs.Find(codec_spec_conf::kLeAudioCodecLC3TypeOctetPerFrame);
337   pac = pacs.Find(codec_spec_caps::kLeAudioCodecLC3TypeOctetPerFrame);
338 
339   if (!req || !pac) {
340     LOG_DEBUG(", lack of octet per frame fields");
341     return false;
342   }
343 
344   u16_req_val = VEC_UINT8_TO_UINT16(req.value());
345   /* Minimal value 0-1 byte */
346   u16_pac_val = VEC_UINT8_TO_UINT16(pac.value());
347   if (u16_req_val < u16_pac_val) {
348     LOG_DEBUG(" Req:OctetsPerFrame=%d", int(u16_req_val));
349     LOG_DEBUG(" Pac:MinOctetsPerFrame=%d", int(u16_pac_val));
350     LOG_DEBUG(", octet per frame below minimum");
351     return false;
352   }
353 
354   /* Maximal value 2-3 byte */
355   u16_pac_val = OFF_VEC_UINT8_TO_UINT16(pac.value(), 2);
356   if (u16_req_val > u16_pac_val) {
357     LOG_DEBUG(" Req:MaxOctetsPerFrame=%d", int(u16_req_val));
358     LOG_DEBUG(" Pac:MaxOctetsPerFrame=%d", int(u16_pac_val));
359     LOG_DEBUG(", octet per frame above maximum");
360     return false;
361   }
362 
363   return true;
364 }
365 
IsCodecCapabilitySettingSupported(const acs_ac_record & pac,const CodecCapabilitySetting & codec_capability_setting)366 bool IsCodecCapabilitySettingSupported(
367     const acs_ac_record& pac,
368     const CodecCapabilitySetting& codec_capability_setting) {
369   const auto& codec_id = codec_capability_setting.id;
370 
371   if (codec_id != pac.codec_id) return false;
372 
373   LOG_DEBUG(": Settings for format: 0x%02x ", codec_id.coding_format);
374 
375   switch (codec_id.coding_format) {
376     case kLeAudioCodingFormatLC3:
377       return IsCodecConfigurationSupported(
378           pac.codec_spec_caps,
379           std::get<LeAudioLc3Config>(codec_capability_setting.config));
380     default:
381       return false;
382   }
383 }
384 
GetConfigSamplingFrequency() const385 uint32_t CodecCapabilitySetting::GetConfigSamplingFrequency() const {
386   switch (id.coding_format) {
387     case kLeAudioCodingFormatLC3:
388       return std::get<types::LeAudioLc3Config>(config).GetSamplingFrequencyHz();
389     default:
390       LOG_WARN(", invalid codec id: 0x%02x", id.coding_format);
391       return 0;
392   }
393 };
394 
GetConfigDataIntervalUs() const395 uint32_t CodecCapabilitySetting::GetConfigDataIntervalUs() const {
396   switch (id.coding_format) {
397     case kLeAudioCodingFormatLC3:
398       return std::get<types::LeAudioLc3Config>(config).GetFrameDurationUs();
399     default:
400       LOG_WARN(", invalid codec id: 0x%02x", id.coding_format);
401       return 0;
402   }
403 };
404 
GetConfigBitsPerSample() const405 uint8_t CodecCapabilitySetting::GetConfigBitsPerSample() const {
406   switch (id.coding_format) {
407     case kLeAudioCodingFormatLC3:
408       /* XXX LC3 supports 16, 24, 32 */
409       return 16;
410     default:
411       LOG_WARN(", invalid codec id: 0x%02x", id.coding_format);
412       return 0;
413   }
414 };
415 
GetConfigChannelCount() const416 uint8_t CodecCapabilitySetting::GetConfigChannelCount() const {
417   switch (id.coding_format) {
418     case kLeAudioCodingFormatLC3:
419       LOG_DEBUG("count = %d",
420                 static_cast<int>(
421                     std::get<types::LeAudioLc3Config>(config).channel_count));
422       return std::get<types::LeAudioLc3Config>(config).channel_count;
423     default:
424       LOG_WARN(", invalid codec id: 0x%02x", id.coding_format);
425       return 0;
426   }
427 }
428 }  // namespace set_configurations
429 
430 namespace types {
431 /* Helper map for matching various frequency notations */
432 const std::map<uint8_t, uint32_t> LeAudioLc3Config::sampling_freq_map = {
433     {codec_spec_conf::kLeAudioSamplingFreq8000Hz,
434      LeAudioCodecConfiguration::kSampleRate8000},
435     {codec_spec_conf::kLeAudioSamplingFreq16000Hz,
436      LeAudioCodecConfiguration::kSampleRate16000},
437     {codec_spec_conf::kLeAudioSamplingFreq24000Hz,
438      LeAudioCodecConfiguration::kSampleRate24000},
439     {codec_spec_conf::kLeAudioSamplingFreq32000Hz,
440      LeAudioCodecConfiguration::kSampleRate32000},
441     {codec_spec_conf::kLeAudioSamplingFreq44100Hz,
442      LeAudioCodecConfiguration::kSampleRate44100},
443     {codec_spec_conf::kLeAudioSamplingFreq48000Hz,
444      LeAudioCodecConfiguration::kSampleRate48000}};
445 
446 /* Helper map for matching various frame durations notations */
447 const std::map<uint8_t, uint32_t> LeAudioLc3Config::frame_duration_map = {
448     {codec_spec_conf::kLeAudioCodecLC3FrameDur7500us,
449      LeAudioCodecConfiguration::kInterval7500Us},
450     {codec_spec_conf::kLeAudioCodecLC3FrameDur10000us,
451      LeAudioCodecConfiguration::kInterval10000Us}};
452 
Find(uint8_t type) const453 std::optional<std::vector<uint8_t>> LeAudioLtvMap::Find(uint8_t type) const {
454   auto iter =
455       std::find_if(values.cbegin(), values.cend(),
456                    [type](const auto& value) { return value.first == type; });
457 
458   if (iter == values.cend()) return std::nullopt;
459 
460   return iter->second;
461 }
462 
RawPacket(uint8_t * p_buf) const463 uint8_t* LeAudioLtvMap::RawPacket(uint8_t* p_buf) const {
464   for (auto const& value : values) {
465     UINT8_TO_STREAM(p_buf, value.second.size() + 1);
466     UINT8_TO_STREAM(p_buf, value.first);
467     ARRAY_TO_STREAM(p_buf, value.second.data(),
468                     static_cast<int>(value.second.size()));
469   }
470 
471   return p_buf;
472 }
473 
RawPacket() const474 std::vector<uint8_t> LeAudioLtvMap::RawPacket() const {
475   std::vector<uint8_t> data(RawPacketSize());
476   RawPacket(data.data());
477   return data;
478 }
479 
Append(const LeAudioLtvMap & other)480 void LeAudioLtvMap::Append(const LeAudioLtvMap& other) {
481   /* This will override values for the already existing keys */
482   for (auto& el : other.values) {
483     values[el.first] = el.second;
484   }
485 }
486 
Parse(const uint8_t * p_value,uint8_t len,bool & success)487 LeAudioLtvMap LeAudioLtvMap::Parse(const uint8_t* p_value, uint8_t len,
488                                    bool& success) {
489   LeAudioLtvMap ltv_map;
490 
491   if (len > 0) {
492     const auto p_value_end = p_value + len;
493 
494     while ((p_value_end - p_value) > 0) {
495       uint8_t ltv_len;
496       STREAM_TO_UINT8(ltv_len, p_value);
497 
498       // Unusual, but possible case
499       if (ltv_len == 0) continue;
500 
501       if (p_value_end < (p_value + ltv_len)) {
502         LOG(ERROR) << __func__
503                    << " Invalid ltv_len: " << static_cast<int>(ltv_len);
504         success = false;
505         return LeAudioLtvMap();
506       }
507 
508       uint8_t ltv_type;
509       STREAM_TO_UINT8(ltv_type, p_value);
510       ltv_len -= sizeof(ltv_type);
511 
512       const auto p_temp = p_value;
513       p_value += ltv_len;
514 
515       std::vector<uint8_t> ltv_value(p_temp, p_value);
516       ltv_map.values.emplace(ltv_type, std::move(ltv_value));
517     }
518   }
519 
520   success = true;
521   return ltv_map;
522 }
523 
RawPacketSize() const524 size_t LeAudioLtvMap::RawPacketSize() const {
525   size_t bytes = 0;
526 
527   for (auto const& value : values) {
528     bytes += (/* ltv_len + ltv_type */ 2 + value.second.size());
529   }
530 
531   return bytes;
532 }
533 
ToString() const534 std::string LeAudioLtvMap::ToString() const {
535   std::string debug_str;
536 
537   for (const auto& value : values) {
538     std::stringstream sstream;
539 
540     sstream << "\ttype: " << std::to_string(value.first)
541             << "\tlen: " << std::to_string(value.second.size()) << "\tdata: "
542             << base::HexEncode(value.second.data(), value.second.size()) + "\n";
543 
544     debug_str += sstream.str();
545   }
546 
547   return debug_str;
548 }
549 
550 }  // namespace types
551 
AppendMetadataLtvEntryForCcidList(std::vector<uint8_t> & metadata,const std::vector<uint8_t> & ccid_list)552 void AppendMetadataLtvEntryForCcidList(std::vector<uint8_t>& metadata,
553                                        const std::vector<uint8_t>& ccid_list) {
554   if (ccid_list.size() == 0) {
555     LOG_WARN("Empty CCID list.");
556     return;
557   }
558 
559   metadata.push_back(
560       static_cast<uint8_t>(types::kLeAudioMetadataTypeLen + ccid_list.size()));
561   metadata.push_back(static_cast<uint8_t>(types::kLeAudioMetadataTypeCcidList));
562 
563   metadata.insert(metadata.end(), ccid_list.begin(), ccid_list.end());
564 }
565 
AppendMetadataLtvEntryForStreamingContext(std::vector<uint8_t> & metadata,types::AudioContexts context_type)566 void AppendMetadataLtvEntryForStreamingContext(
567     std::vector<uint8_t>& metadata, types::AudioContexts context_type) {
568   std::vector<uint8_t> streaming_context_ltv_entry;
569 
570   streaming_context_ltv_entry.resize(
571       types::kLeAudioMetadataTypeLen + types::kLeAudioMetadataLenLen +
572       types::kLeAudioMetadataStreamingAudioContextLen);
573   uint8_t* streaming_context_ltv_entry_buf = streaming_context_ltv_entry.data();
574 
575   UINT8_TO_STREAM(streaming_context_ltv_entry_buf,
576                   types::kLeAudioMetadataTypeLen +
577                       types::kLeAudioMetadataStreamingAudioContextLen);
578   UINT8_TO_STREAM(streaming_context_ltv_entry_buf,
579                   types::kLeAudioMetadataTypeStreamingAudioContext);
580   UINT16_TO_STREAM(streaming_context_ltv_entry_buf, context_type.value());
581 
582   metadata.insert(metadata.end(), streaming_context_ltv_entry.begin(),
583                   streaming_context_ltv_entry.end());
584 }
585 
GetMaxCodecFramesPerSduFromPac(const acs_ac_record * pac)586 uint8_t GetMaxCodecFramesPerSduFromPac(const acs_ac_record* pac) {
587   auto tlv_ent = pac->codec_spec_caps.Find(
588       codec_spec_caps::kLeAudioCodecLC3TypeMaxCodecFramesPerSdu);
589 
590   if (tlv_ent) return VEC_UINT8_TO_UINT8(tlv_ent.value());
591 
592   return 1;
593 }
594 
AdjustAllocationForOffloader(uint32_t allocation)595 uint32_t AdjustAllocationForOffloader(uint32_t allocation) {
596   if ((allocation & codec_spec_conf::kLeAudioLocationAnyLeft) &&
597       (allocation & codec_spec_conf::kLeAudioLocationAnyRight)) {
598     return codec_spec_conf::kLeAudioLocationStereo;
599   }
600   if (allocation & codec_spec_conf::kLeAudioLocationAnyLeft) {
601     return codec_spec_conf::kLeAudioLocationFrontLeft;
602   }
603 
604   if (allocation & codec_spec_conf::kLeAudioLocationAnyRight) {
605     return codec_spec_conf::kLeAudioLocationFrontRight;
606   }
607   return 0;
608 }
609 
610 namespace types {
operator <<(std::ostream & os,const AudioStreamDataPathState & state)611 std::ostream& operator<<(std::ostream& os,
612                          const AudioStreamDataPathState& state) {
613   static const char* char_value_[6] = {
614       "IDLE",        "CIS_DISCONNECTING", "CIS_ASSIGNED",
615       "CIS_PENDING", "CIS_ESTABLISHED",   "DATA_PATH_ESTABLISHED"};
616 
617   os << char_value_[static_cast<uint8_t>(state)] << " ("
618      << "0x" << std::setfill('0') << std::setw(2) << static_cast<int>(state)
619      << ")";
620   return os;
621 }
operator <<(std::ostream & os,const types::CigState & state)622 std::ostream& operator<<(std::ostream& os, const types::CigState& state) {
623   static const char* char_value_[5] = {"NONE", "CREATING", "CREATED",
624                                        "REMOVING", "RECOVERING"};
625 
626   os << char_value_[static_cast<uint8_t>(state)] << " ("
627      << "0x" << std::setfill('0') << std::setw(2) << static_cast<int>(state)
628      << ")";
629   return os;
630 }
operator <<(std::ostream & os,const types::AseState & state)631 std::ostream& operator<<(std::ostream& os, const types::AseState& state) {
632   static const char* char_value_[7] = {
633       "IDLE",      "CODEC_CONFIGURED", "QOS_CONFIGURED", "ENABLING",
634       "STREAMING", "DISABLING",        "RELEASING",
635   };
636 
637   os << char_value_[static_cast<uint8_t>(state)] << " ("
638      << "0x" << std::setfill('0') << std::setw(2) << static_cast<int>(state)
639      << ")";
640   return os;
641 }
642 
operator <<(std::ostream & os,const types::LeAudioLc3Config & config)643 std::ostream& operator<<(std::ostream& os,
644                          const types::LeAudioLc3Config& config) {
645   os << " LeAudioLc3Config(SamplFreq=" << loghex(*config.sampling_frequency)
646      << ", FrameDur=" << loghex(*config.frame_duration)
647      << ", OctetsPerFrame=" << int(*config.octets_per_codec_frame)
648      << ", CodecFramesBlocksPerSDU=" << int(*config.codec_frames_blocks_per_sdu)
649      << ", AudioChanLoc=" << loghex(*config.audio_channel_allocation) << ")";
650   return os;
651 }
operator <<(std::ostream & os,const LeAudioContextType & context)652 std::ostream& operator<<(std::ostream& os, const LeAudioContextType& context) {
653   switch (context) {
654     case LeAudioContextType::UNINITIALIZED:
655       os << "UNINITIALIZED";
656       break;
657     case LeAudioContextType::UNSPECIFIED:
658       os << "UNSPECIFIED";
659       break;
660     case LeAudioContextType::CONVERSATIONAL:
661       os << "CONVERSATIONAL";
662       break;
663     case LeAudioContextType::MEDIA:
664       os << "MEDIA";
665       break;
666     case LeAudioContextType::GAME:
667       os << "GAME";
668       break;
669     case LeAudioContextType::INSTRUCTIONAL:
670       os << "INSTRUCTIONAL";
671       break;
672     case LeAudioContextType::VOICEASSISTANTS:
673       os << "VOICEASSISTANTS";
674       break;
675     case LeAudioContextType::LIVE:
676       os << "LIVE";
677       break;
678     case LeAudioContextType::SOUNDEFFECTS:
679       os << "SOUNDEFFECTS";
680       break;
681     case LeAudioContextType::NOTIFICATIONS:
682       os << "NOTIFICATIONS";
683       break;
684     case LeAudioContextType::RINGTONE:
685       os << "RINGTONE";
686       break;
687     case LeAudioContextType::ALERTS:
688       os << "ALERTS";
689       break;
690     case LeAudioContextType::EMERGENCYALARM:
691       os << "EMERGENCYALARM";
692       break;
693     default:
694       os << "UNKNOWN";
695       break;
696   }
697   return os;
698 }
699 
operator |(std::underlying_type<LeAudioContextType>::type lhs,const LeAudioContextType rhs)700 AudioContexts operator|(std::underlying_type<LeAudioContextType>::type lhs,
701                         const LeAudioContextType rhs) {
702   using T = std::underlying_type<LeAudioContextType>::type;
703   return AudioContexts(lhs | static_cast<T>(rhs));
704 }
705 
operator |=(AudioContexts & lhs,AudioContexts const & rhs)706 AudioContexts& operator|=(AudioContexts& lhs, AudioContexts const& rhs) {
707   lhs = AudioContexts(lhs.value() | rhs.value());
708   return lhs;
709 }
710 
operator &=(AudioContexts & lhs,AudioContexts const & rhs)711 AudioContexts& operator&=(AudioContexts& lhs, AudioContexts const& rhs) {
712   lhs = AudioContexts(lhs.value() & rhs.value());
713   return lhs;
714 }
715 
ToHexString(const LeAudioContextType & value)716 std::string ToHexString(const LeAudioContextType& value) {
717   using T = std::underlying_type<LeAudioContextType>::type;
718   return bluetooth::common::ToHexString(static_cast<T>(value));
719 }
720 
to_string() const721 std::string AudioContexts::to_string() const {
722   std::stringstream s;
723   for (auto ctx : le_audio::types::kLeAudioContextAllTypesArray) {
724     if (test(ctx)) {
725       if (s.tellp() != 0) s << " | ";
726       s << ctx;
727     }
728   }
729   s << " (" << bluetooth::common::ToHexString(mValue) << ")";
730   return s.str();
731 }
732 
operator <<(std::ostream & os,const AudioContexts & contexts)733 std::ostream& operator<<(std::ostream& os, const AudioContexts& contexts) {
734   os << contexts.to_string();
735   return os;
736 }
737 
738 /* Bidirectional getter trait for AudioContexts bidirectional pair */
739 template <>
get_bidirectional(BidirectionalPair<AudioContexts> p)740 AudioContexts get_bidirectional(BidirectionalPair<AudioContexts> p) {
741   return p.sink | p.source;
742 }
743 
744 }  // namespace types
745 }  // namespace le_audio
746