1 /*
2 * Copyright 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "le_audio_utils.h"
18
19 #include <bluetooth/log.h>
20
21 #include "common/strings.h"
22 #include "le_audio_types.h"
23 #include "os/log.h"
24
25 using bluetooth::common::ToString;
26 using bluetooth::le_audio::types::AudioContexts;
27 using bluetooth::le_audio::types::LeAudioContextType;
28
29 namespace fmt {
30 template <>
31 struct formatter<audio_usage_t> : enum_formatter<audio_usage_t> {};
32 template <>
33 struct formatter<audio_content_type_t> : enum_formatter<audio_content_type_t> {
34 };
35 template <>
36 struct formatter<audio_source_t> : enum_formatter<audio_source_t> {};
37 template <>
38 struct formatter<audio_devices_t> : enum_formatter<audio_devices_t> {};
39 } // namespace fmt
40
41 namespace bluetooth::le_audio {
42 namespace utils {
43
44 /* The returned LeAudioContextType should have its entry in the
45 * AudioSetConfigurationProvider's ContextTypeToScenario mapping table.
46 * Otherwise the AudioSetConfigurationProvider will fall back
47 * to default scenario.
48 */
AudioContentToLeAudioContext(audio_content_type_t content_type,audio_usage_t usage)49 LeAudioContextType AudioContentToLeAudioContext(
50 audio_content_type_t content_type, audio_usage_t usage) {
51 /* Check audio attribute usage of stream */
52 switch (usage) {
53 case AUDIO_USAGE_MEDIA:
54 return LeAudioContextType::MEDIA;
55 case AUDIO_USAGE_ASSISTANT:
56 return LeAudioContextType::VOICEASSISTANTS;
57 case AUDIO_USAGE_VOICE_COMMUNICATION:
58 case AUDIO_USAGE_CALL_ASSISTANT:
59 return LeAudioContextType::CONVERSATIONAL;
60 case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
61 if (content_type == AUDIO_CONTENT_TYPE_SPEECH) {
62 return LeAudioContextType::CONVERSATIONAL;
63 }
64
65 if (content_type == AUDIO_CONTENT_TYPE_SONIFICATION) {
66 return LeAudioContextType::RINGTONE;
67 }
68
69 return LeAudioContextType::MEDIA;
70 case AUDIO_USAGE_GAME:
71 return LeAudioContextType::GAME;
72 case AUDIO_USAGE_NOTIFICATION:
73 return LeAudioContextType::NOTIFICATIONS;
74 case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
75 return LeAudioContextType::RINGTONE;
76 case AUDIO_USAGE_ALARM:
77 return LeAudioContextType::ALERTS;
78 case AUDIO_USAGE_EMERGENCY:
79 return LeAudioContextType::EMERGENCYALARM;
80 case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
81 return LeAudioContextType::INSTRUCTIONAL;
82 case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
83 return LeAudioContextType::SOUNDEFFECTS;
84 default:
85 break;
86 }
87
88 return LeAudioContextType::MEDIA;
89 }
90
usageToString(audio_usage_t usage)91 static std::string usageToString(audio_usage_t usage) {
92 switch (usage) {
93 case AUDIO_USAGE_UNKNOWN:
94 return "USAGE_UNKNOWN";
95 case AUDIO_USAGE_MEDIA:
96 return "USAGE_MEDIA";
97 case AUDIO_USAGE_VOICE_COMMUNICATION:
98 return "USAGE_VOICE_COMMUNICATION";
99 case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
100 return "USAGE_VOICE_COMMUNICATION_SIGNALLING";
101 case AUDIO_USAGE_ALARM:
102 return "USAGE_ALARM";
103 case AUDIO_USAGE_NOTIFICATION:
104 return "USAGE_NOTIFICATION";
105 case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
106 return "USAGE_NOTIFICATION_TELEPHONY_RINGTONE";
107 case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
108 return "USAGE_NOTIFICATION_COMMUNICATION_REQUEST";
109 case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
110 return "USAGE_NOTIFICATION_COMMUNICATION_INSTANT";
111 case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
112 return "USAGE_NOTIFICATION_COMMUNICATION_DELAYED";
113 case AUDIO_USAGE_NOTIFICATION_EVENT:
114 return "USAGE_NOTIFICATION_EVENT";
115 case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
116 return "USAGE_ASSISTANCE_ACCESSIBILITY";
117 case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
118 return "USAGE_ASSISTANCE_NAVIGATION_GUIDANCE";
119 case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
120 return "USAGE_ASSISTANCE_SONIFICATION";
121 case AUDIO_USAGE_GAME:
122 return "USAGE_GAME";
123 case AUDIO_USAGE_ASSISTANT:
124 return "USAGE_ASSISTANT";
125 case AUDIO_USAGE_CALL_ASSISTANT:
126 return "USAGE_CALL_ASSISTANT";
127 case AUDIO_USAGE_EMERGENCY:
128 return "USAGE_EMERGENCY";
129 case AUDIO_USAGE_SAFETY:
130 return "USAGE_SAFETY";
131 case AUDIO_USAGE_VEHICLE_STATUS:
132 return "USAGE_VEHICLE_STATUS";
133 case AUDIO_USAGE_ANNOUNCEMENT:
134 return "USAGE_ANNOUNCEMENT";
135 default:
136 return "unknown usage ";
137 }
138 }
139
contentTypeToString(audio_content_type_t content_type)140 static std::string contentTypeToString(audio_content_type_t content_type) {
141 switch (content_type) {
142 case AUDIO_CONTENT_TYPE_UNKNOWN:
143 return "CONTENT_TYPE_UNKNOWN";
144 case AUDIO_CONTENT_TYPE_SPEECH:
145 return "CONTENT_TYPE_SPEECH";
146 case AUDIO_CONTENT_TYPE_MUSIC:
147 return "CONTENT_TYPE_MUSIC";
148 case AUDIO_CONTENT_TYPE_MOVIE:
149 return "CONTENT_TYPE_MOVIE";
150 case AUDIO_CONTENT_TYPE_SONIFICATION:
151 return "CONTENT_TYPE_SONIFICATION";
152 default:
153 return "unknown content type ";
154 }
155 }
156
audioSourceToStr(audio_source_t source)157 static const char* audioSourceToStr(audio_source_t source) {
158 const char* strArr[] = {
159 "AUDIO_SOURCE_DEFAULT", "AUDIO_SOURCE_MIC",
160 "AUDIO_SOURCE_VOICE_UPLINK", "AUDIO_SOURCE_VOICE_DOWNLINK",
161 "AUDIO_SOURCE_VOICE_CALL", "AUDIO_SOURCE_CAMCORDER",
162 "AUDIO_SOURCE_VOICE_RECOGNITION", "AUDIO_SOURCE_VOICE_COMMUNICATION",
163 "AUDIO_SOURCE_REMOTE_SUBMIX", "AUDIO_SOURCE_UNPROCESSED",
164 "AUDIO_SOURCE_VOICE_PERFORMANCE"};
165
166 if (static_cast<uint32_t>(source) < (sizeof(strArr) / sizeof(strArr[0])))
167 return strArr[source];
168 return "UNKNOWN";
169 }
170
isMetadataTagPresent(const char * tags,const char * tag)171 static bool isMetadataTagPresent(const char* tags, const char* tag) {
172 std::istringstream iss(tags);
173 std::string t;
174 while (std::getline(iss, t, AUDIO_ATTRIBUTES_TAGS_SEPARATOR)) {
175 log::verbose("Tag {}", t);
176 if (t.compare(tag) == 0) {
177 return true;
178 }
179 }
180 return false;
181 }
182
GetAudioContextsFromSourceMetadata(const std::vector<struct playback_track_metadata_v7> & source_metadata)183 AudioContexts GetAudioContextsFromSourceMetadata(
184 const std::vector<struct playback_track_metadata_v7>& source_metadata) {
185 AudioContexts track_contexts;
186 for (const auto& entry : source_metadata) {
187 auto track = entry.base;
188 if (track.content_type == 0 && track.usage == 0) continue;
189
190 log::info("usage={}({}), content_type={}({}), gain={:f}, tag:{}",
191 usageToString(track.usage), track.usage,
192 contentTypeToString(track.content_type),
193 track.content_type, track.gain, entry.tags);
194
195 if (isMetadataTagPresent(entry.tags, "VX_AOSP_SAMPLESOUND")) {
196 track_contexts.set(LeAudioContextType::SOUNDEFFECTS);
197 } else {
198 track_contexts.set(
199 AudioContentToLeAudioContext(track.content_type, track.usage));
200 }
201 }
202 return track_contexts;
203 }
204
GetAudioContextsFromSinkMetadata(const std::vector<struct record_track_metadata_v7> & sink_metadata)205 AudioContexts GetAudioContextsFromSinkMetadata(
206 const std::vector<struct record_track_metadata_v7>& sink_metadata) {
207 AudioContexts all_track_contexts;
208
209 for (const auto& entry : sink_metadata) {
210 auto track = entry.base;
211 if (track.source == AUDIO_SOURCE_INVALID) continue;
212 LeAudioContextType track_context;
213
214 log::debug(
215 "source={}(0x{:02x}), gain={:f}, destination device=0x{:08x}, "
216 "destination device address={:32s}",
217 audioSourceToStr(track.source), track.source, track.gain,
218 track.dest_device, track.dest_device_address);
219
220 if (track.source == AUDIO_SOURCE_MIC) {
221 track_context = LeAudioContextType::LIVE;
222
223 } else if (track.source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
224 track_context = LeAudioContextType::CONVERSATIONAL;
225
226 } else {
227 /* Fallback to voice assistant
228 * This will handle also a case when the device is
229 * AUDIO_SOURCE_VOICE_RECOGNITION
230 */
231 track_context = LeAudioContextType::VOICEASSISTANTS;
232 log::warn(
233 "Could not match the recording track type to group available "
234 "context. Using context {}.",
235 ToString(track_context));
236 }
237
238 all_track_contexts.set(track_context);
239 }
240
241 if (all_track_contexts.none()) {
242 all_track_contexts = AudioContexts(
243 static_cast<std::underlying_type<LeAudioContextType>::type>(
244 LeAudioContextType::UNSPECIFIED));
245 log::debug(
246 "Unable to find supported audio source context for the remote audio "
247 "sink device. This may result in voice back channel malfunction.");
248 }
249
250 log::info("Allowed contexts from sink metadata: {} (0x{:08x})",
251 bluetooth::common::ToString(all_track_contexts),
252 all_track_contexts.value());
253 return all_track_contexts;
254 }
255
256 bluetooth::le_audio::btle_audio_codec_index_t
translateBluetoothCodecFormatToCodecType(uint8_t codec_format)257 translateBluetoothCodecFormatToCodecType(uint8_t codec_format) {
258 switch (codec_format) {
259 case types::kLeAudioCodingFormatLC3:
260 return bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3;
261 }
262 return bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_INVALID;
263 }
264
265 bluetooth::le_audio::btle_audio_sample_rate_index_t
translateToBtLeAudioCodecConfigSampleRate(uint32_t sample_rate)266 translateToBtLeAudioCodecConfigSampleRate(uint32_t sample_rate) {
267 log::info("{}", sample_rate);
268 switch (sample_rate) {
269 case LeAudioCodecConfiguration::kSampleRate8000:
270 return LE_AUDIO_SAMPLE_RATE_INDEX_8000HZ;
271 case LeAudioCodecConfiguration::kSampleRate16000:
272 return LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ;
273 case LeAudioCodecConfiguration::kSampleRate24000:
274 return LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ;
275 case LeAudioCodecConfiguration::kSampleRate32000:
276 return LE_AUDIO_SAMPLE_RATE_INDEX_32000HZ;
277 case LeAudioCodecConfiguration::kSampleRate44100:
278 return LE_AUDIO_SAMPLE_RATE_INDEX_44100HZ;
279 case LeAudioCodecConfiguration::kSampleRate48000:
280 return LE_AUDIO_SAMPLE_RATE_INDEX_48000HZ;
281 }
282
283 return LE_AUDIO_SAMPLE_RATE_INDEX_NONE;
284 }
285
286 bluetooth::le_audio::btle_audio_bits_per_sample_index_t
translateToBtLeAudioCodecConfigBitPerSample(uint8_t bits_per_sample)287 translateToBtLeAudioCodecConfigBitPerSample(uint8_t bits_per_sample) {
288 switch (bits_per_sample) {
289 case 16:
290 return bluetooth::le_audio::LE_AUDIO_BITS_PER_SAMPLE_INDEX_16;
291 case 24:
292 return bluetooth::le_audio::LE_AUDIO_BITS_PER_SAMPLE_INDEX_24;
293 case 32:
294 return bluetooth::le_audio::LE_AUDIO_BITS_PER_SAMPLE_INDEX_32;
295 }
296 return bluetooth::le_audio::LE_AUDIO_BITS_PER_SAMPLE_INDEX_NONE;
297 }
298
299 bluetooth::le_audio::btle_audio_channel_count_index_t
translateToBtLeAudioCodecConfigChannelCount(uint8_t channel_count)300 translateToBtLeAudioCodecConfigChannelCount(uint8_t channel_count) {
301 switch (channel_count) {
302 case 1:
303 return bluetooth::le_audio::LE_AUDIO_CHANNEL_COUNT_INDEX_1;
304 case 2:
305 return bluetooth::le_audio::LE_AUDIO_CHANNEL_COUNT_INDEX_2;
306 }
307 return bluetooth::le_audio::LE_AUDIO_CHANNEL_COUNT_INDEX_NONE;
308 }
309
310 bluetooth::le_audio::btle_audio_frame_duration_index_t
translateToBtLeAudioCodecConfigFrameDuration(int frame_duration)311 translateToBtLeAudioCodecConfigFrameDuration(int frame_duration) {
312 switch (frame_duration) {
313 case 7500:
314 return bluetooth::le_audio::LE_AUDIO_FRAME_DURATION_INDEX_7500US;
315 case 10000:
316 return bluetooth::le_audio::LE_AUDIO_FRAME_DURATION_INDEX_10000US;
317 }
318 return bluetooth::le_audio::LE_AUDIO_FRAME_DURATION_INDEX_NONE;
319 }
320
fillStreamParamsToBtLeAudioCodecConfig(const std::vector<struct set_configurations::AseConfiguration> & confs,bluetooth::le_audio::btle_audio_codec_config_t & out_config)321 void fillStreamParamsToBtLeAudioCodecConfig(
322 const std::vector<struct set_configurations::AseConfiguration>& confs,
323 bluetooth::le_audio::btle_audio_codec_config_t& out_config) {
324 if (confs.size() == 0) {
325 log::warn("Stream params are null");
326 return;
327 }
328
329 auto config = confs.at(0).codec;
330
331 out_config.codec_type =
332 translateBluetoothCodecFormatToCodecType(config.id.coding_format);
333 if (out_config.codec_type !=
334 bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3) {
335 return;
336 }
337
338 out_config.sample_rate = translateToBtLeAudioCodecConfigSampleRate(
339 config.GetSamplingFrequencyHz());
340 out_config.bits_per_sample = translateToBtLeAudioCodecConfigBitPerSample(16);
341 out_config.frame_duration =
342 translateToBtLeAudioCodecConfigFrameDuration(config.GetDataIntervalUs());
343 out_config.octets_per_frame = config.GetOctectsPerFrame();
344 out_config.channel_count = translateToBtLeAudioCodecConfigChannelCount(
345 config.GetChannelCountPerIsoStream());
346 }
347
is_known_codec(const types::LeAudioCodecId & codec_id)348 static bool is_known_codec(const types::LeAudioCodecId& codec_id) {
349 switch (codec_id.coding_format) {
350 case types::kLeAudioCodingFormatLC3:
351 return true;
352 }
353 return false;
354 }
355
fillRemotePacsCapabitiliesToBtLeAudioCodecConfig(const struct types::acs_ac_record & record,std::vector<bluetooth::le_audio::btle_audio_codec_config_t> & vec)356 static void fillRemotePacsCapabitiliesToBtLeAudioCodecConfig(
357 const struct types::acs_ac_record& record,
358 std::vector<bluetooth::le_audio::btle_audio_codec_config_t>& vec) {
359 if (!utils::IsCodecUsingLtvFormat(record.codec_id)) {
360 log::warn(
361 "Unknown codec capability format. Unable to report known codec "
362 "parameters.");
363 return;
364 }
365 log::assert_that(!record.codec_spec_caps.IsEmpty(),
366 "Codec specific capabilities are not parsed approprietly.");
367
368 const struct types::LeAudioCoreCodecCapabilities capa =
369 record.codec_spec_caps.GetAsCoreCodecCapabilities();
370 for (uint8_t freq_bit = codec_spec_conf::kLeAudioSamplingFreq8000Hz;
371 freq_bit <= codec_spec_conf::kLeAudioSamplingFreq384000Hz; freq_bit++) {
372 if (!capa.IsSamplingFrequencyConfigSupported(freq_bit)) continue;
373 for (uint8_t fd_bit = codec_spec_conf::kLeAudioCodecFrameDur7500us;
374 fd_bit <= codec_spec_conf::kLeAudioCodecFrameDur10000us; fd_bit++) {
375 if (!capa.IsFrameDurationConfigSupported(fd_bit)) continue;
376 if (!capa.HasSupportedAudioChannelCounts()) {
377 bluetooth::le_audio::btle_audio_codec_config_t config = {
378 .codec_type = utils::translateBluetoothCodecFormatToCodecType(
379 record.codec_id.coding_format),
380 .sample_rate = utils::translateToBtLeAudioCodecConfigSampleRate(
381 types::LeAudioCoreCodecConfig::GetSamplingFrequencyHz(
382 freq_bit)),
383 .bits_per_sample =
384 utils::translateToBtLeAudioCodecConfigBitPerSample(16),
385 .channel_count =
386 utils::translateToBtLeAudioCodecConfigChannelCount(1),
387 .frame_duration =
388 utils::translateToBtLeAudioCodecConfigFrameDuration(
389 types::LeAudioCoreCodecConfig::GetFrameDurationUs(fd_bit)),
390 };
391 vec.push_back(config);
392 } else {
393 for (int chan_bit = 1; chan_bit <= 2; chan_bit++) {
394 if (!capa.IsAudioChannelCountsSupported(chan_bit)) continue;
395
396 bluetooth::le_audio::btle_audio_codec_config_t config = {
397 .codec_type = utils::translateBluetoothCodecFormatToCodecType(
398 record.codec_id.coding_format),
399 .sample_rate = utils::translateToBtLeAudioCodecConfigSampleRate(
400 types::LeAudioCoreCodecConfig::GetSamplingFrequencyHz(
401 freq_bit)),
402 .bits_per_sample =
403 utils::translateToBtLeAudioCodecConfigBitPerSample(16),
404 .channel_count =
405 utils::translateToBtLeAudioCodecConfigChannelCount(chan_bit),
406 .frame_duration =
407 utils::translateToBtLeAudioCodecConfigFrameDuration(
408 types::LeAudioCoreCodecConfig::GetFrameDurationUs(
409 fd_bit)),
410 };
411 vec.push_back(config);
412 }
413 }
414 }
415 }
416 }
417
418 std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
GetRemoteBtLeAudioCodecConfigFromPac(const types::PublishedAudioCapabilities & group_pacs)419 GetRemoteBtLeAudioCodecConfigFromPac(
420 const types::PublishedAudioCapabilities& group_pacs) {
421 std::vector<bluetooth::le_audio::btle_audio_codec_config_t> vec;
422
423 for (auto& [handles, pacs_record] : group_pacs) {
424 for (auto& pac : pacs_record) {
425 if (!is_known_codec(pac.codec_id)) continue;
426
427 fillRemotePacsCapabitiliesToBtLeAudioCodecConfig(pac, vec);
428 }
429 }
430 return vec;
431 }
432
IsCodecUsingLtvFormat(const types::LeAudioCodecId & codec_id)433 bool IsCodecUsingLtvFormat(const types::LeAudioCodecId& codec_id) {
434 if (codec_id == set_configurations::LeAudioCodecIdLc3) {
435 return true;
436 }
437 return false;
438 }
439
440 ::bluetooth::le_audio::LeAudioCodecConfiguration
GetAudioSessionCodecConfigFromAudioSetConfiguration(const bluetooth::le_audio::set_configurations::AudioSetConfiguration & audio_set_conf,uint8_t remote_direction)441 GetAudioSessionCodecConfigFromAudioSetConfiguration(
442 const bluetooth::le_audio::set_configurations::AudioSetConfiguration&
443 audio_set_conf,
444 uint8_t remote_direction) {
445 /* Note: For now we expect that each ASE in a particular direction needs
446 * exactly the same audio codec parameters.
447 */
448
449 LeAudioCodecConfiguration group_config = {0, 0, 0, 0};
450 for (const auto& conf : audio_set_conf.confs.get(remote_direction)) {
451 if (group_config.sample_rate != 0 &&
452 conf.codec.GetSamplingFrequencyHz() != group_config.sample_rate) {
453 log::warn(
454 "Stream configuration could not be determined (multiple, different "
455 "sampling frequencies) for remote_direction: {:#x}",
456 remote_direction);
457 break;
458 }
459 group_config.sample_rate = conf.codec.GetSamplingFrequencyHz();
460
461 if (group_config.data_interval_us != 0 &&
462 conf.codec.GetDataIntervalUs() != group_config.data_interval_us) {
463 log::warn(
464 "Stream configuration could not be determined (multiple, different "
465 "data intervals) for remote_direction: {:#x}",
466 remote_direction);
467 break;
468 }
469 group_config.data_interval_us = conf.codec.GetDataIntervalUs();
470
471 if (group_config.bits_per_sample != 0 &&
472 conf.codec.GetBitsPerSample() != group_config.bits_per_sample) {
473 log::warn(
474 "Stream configuration could not be determined (multiple, different "
475 "bits per sample) for remote_direction: {:#x}",
476 remote_direction);
477 break;
478 }
479 group_config.bits_per_sample = conf.codec.GetBitsPerSample();
480 group_config.num_channels += conf.codec.GetChannelCountPerIsoStream();
481 }
482 if (group_config.num_channels > 2) group_config.num_channels = 2;
483
484 return group_config;
485 }
486
GetStrategyForAseConfig(const std::vector<le_audio::set_configurations::AseConfiguration> & cfgs,uint8_t device_cnt)487 types::LeAudioConfigurationStrategy GetStrategyForAseConfig(
488 const std::vector<le_audio::set_configurations::AseConfiguration>& cfgs,
489 uint8_t device_cnt) {
490 if (cfgs.size() == 0) {
491 return types::LeAudioConfigurationStrategy::RFU;
492 }
493
494 /* Banded headphones or the Classic TWS style topology (a single device) */
495 if (device_cnt == 1) {
496 if (cfgs.at(0).codec.GetChannelCountPerIsoStream() == 1) {
497 /* One mono ASE - could be a single channel microphone */
498 if (cfgs.size() == 1) {
499 return types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE;
500 }
501
502 /* Each channel on a dedicated ASE - TWS style split channel re-routing */
503 return types::LeAudioConfigurationStrategy::STEREO_TWO_CISES_PER_DEVICE;
504 }
505
506 /* Banded headphones with 1 ASE - requires two channels per CIS */
507 return types::LeAudioConfigurationStrategy::STEREO_ONE_CIS_PER_DEVICE;
508 }
509
510 // We need at least 2 ASEs in the group config to set up more than one device
511 if (cfgs.size() == 1) {
512 return types::LeAudioConfigurationStrategy::RFU;
513 }
514
515 /* The common one channel per device topology */
516 return types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE;
517 }
518
IsCodecConfigSupported(const types::LeAudioLtvMap & pacs,const types::LeAudioLtvMap & reqs,uint8_t channel_cnt_per_ase)519 static bool IsCodecConfigSupported(const types::LeAudioLtvMap& pacs,
520 const types::LeAudioLtvMap& reqs,
521 uint8_t channel_cnt_per_ase) {
522 auto caps = pacs.GetAsCoreCodecCapabilities();
523 auto config = reqs.GetAsCoreCodecConfig();
524
525 /* Sampling frequency */
526 if (!caps.HasSupportedSamplingFrequencies() || !config.sampling_frequency) {
527 log::debug("Missing supported sampling frequencies capability");
528 return false;
529 }
530 if (!caps.IsSamplingFrequencyConfigSupported(
531 config.sampling_frequency.value())) {
532 log::debug("Cfg: SamplingFrequency= {:#x}",
533 config.sampling_frequency.value());
534 log::debug("Cap: SupportedSamplingFrequencies= {:#x}",
535 caps.supported_sampling_frequencies.value());
536 log::debug("Sampling frequency not supported");
537 return false;
538 }
539
540 /* Channel counts */
541 if (!caps.IsAudioChannelCountsSupported(channel_cnt_per_ase)) {
542 log::debug("Cfg: Allocated channel count= {:#x}", channel_cnt_per_ase);
543 log::debug("Cap: Supported channel counts= {:#x}",
544 caps.supported_audio_channel_counts.value_or(1));
545 log::debug("Channel count not supported");
546 return false;
547 }
548
549 /* Frame duration */
550 if (!caps.HasSupportedFrameDurations() || !config.frame_duration) {
551 log::debug("Missing supported frame durations capability");
552 return false;
553 }
554 if (!caps.IsFrameDurationConfigSupported(config.frame_duration.value())) {
555 log::debug("Cfg: FrameDuration= {:#x}", config.frame_duration.value());
556 log::debug("Cap: SupportedFrameDurations= {:#x}",
557 caps.supported_frame_durations.value());
558 log::debug("Frame duration not supported");
559 return false;
560 }
561
562 /* Octets per frame */
563 if (!caps.HasSupportedOctetsPerCodecFrame() ||
564 !config.octets_per_codec_frame) {
565 log::debug("Missing supported octets per codec frame");
566 return false;
567 }
568 if (!caps.IsOctetsPerCodecFrameConfigSupported(
569 config.octets_per_codec_frame.value())) {
570 log::debug("Cfg: Octets per frame={}",
571 config.octets_per_codec_frame.value());
572 log::debug("Cap: Min octets per frame={}",
573 caps.supported_min_octets_per_codec_frame.value());
574 log::debug("Cap: Max octets per frame={}",
575 caps.supported_max_octets_per_codec_frame.value());
576 log::debug("Octets per codec frame outside the capabilities");
577 return false;
578 }
579
580 return true;
581 }
582
IsCodecConfigSettingSupported(const types::acs_ac_record & pac,const set_configurations::CodecConfigSetting & codec_config_setting)583 static bool IsCodecConfigSettingSupported(
584 const types::acs_ac_record& pac,
585 const set_configurations::CodecConfigSetting& codec_config_setting) {
586 const auto& codec_id = codec_config_setting.id;
587 if (codec_id != pac.codec_id) return false;
588
589 log::debug(": Settings for format: 0x{:#02x} ", codec_id.coding_format);
590
591 if (utils::IsCodecUsingLtvFormat(codec_id)) {
592 log::assert_that(
593 !pac.codec_spec_caps.IsEmpty(),
594 "Codec specific capabilities are not parsed approprietly.");
595 return IsCodecConfigSupported(
596 pac.codec_spec_caps, codec_config_setting.params,
597 codec_config_setting.GetChannelCountPerIsoStream());
598 }
599
600 log::error("Codec {}, seems to be not supported here.",
601 bluetooth::common::ToString(codec_id));
602 return false;
603 }
604
GetConfigurationSupportedPac(const types::PublishedAudioCapabilities & pacs,const set_configurations::CodecConfigSetting & codec_config_setting)605 const struct types::acs_ac_record* GetConfigurationSupportedPac(
606 const types::PublishedAudioCapabilities& pacs,
607 const set_configurations::CodecConfigSetting& codec_config_setting) {
608 for (const auto& pac_tuple : pacs) {
609 for (const auto& pac : std::get<1>(pac_tuple)) {
610 if (utils::IsCodecConfigSettingSupported(pac, codec_config_setting))
611 return &pac;
612 };
613 }
614 /* Doesn't match required configuration with any PAC */
615 if (pacs.size() == 0) log::error("No PAC records");
616 return nullptr;
617 }
618 } // namespace utils
619 } // namespace bluetooth::le_audio
620