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