1 /*
2  * Copyright 2024 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 #pragma once
17 
18 #include "bta/le_audio/broadcaster/broadcaster_types.h"
19 #include "bta/le_audio/le_audio_types.h"
20 
21 namespace bluetooth::le_audio {
22 namespace broadcaster {
23 
24 constexpr types::LeAudioCodecId kLeAudioCodecIdLc3 = {
25         .coding_format = types::kLeAudioCodingFormatLC3,
26         .vendor_company_id = types::kLeAudioVendorCompanyIdUndefined,
27         .vendor_codec_id = types::kLeAudioVendorCodecIdUndefined};
28 
29 // Quality subgroup configurations
30 static const BroadcastSubgroupCodecConfig lc3_mono_16_2 = BroadcastSubgroupCodecConfig(
31         kLeAudioCodecIdLc3,
32         {BroadcastSubgroupBisCodecConfig{
33                 // num_bis
34                 1,
35                 // bis_channel_cnt_
36                 1,
37                 // codec_specific
38                 types::LeAudioLtvMap({
39                         LTV_ENTRY_SAMPLING_FREQUENCY(codec_spec_conf::kLeAudioSamplingFreq16000Hz),
40                         LTV_ENTRY_FRAME_DURATION(codec_spec_conf::kLeAudioCodecFrameDur10000us),
41                         LTV_ENTRY_OCTETS_PER_CODEC_FRAME(40),
42                 }),
43         }},
44         // bits_per_sample
45         16);
46 
47 static const BroadcastSubgroupCodecConfig lc3_stereo_16_2 = BroadcastSubgroupCodecConfig(
48         kLeAudioCodecIdLc3,
49         {BroadcastSubgroupBisCodecConfig{
50                 // num_bis
51                 2,
52                 // bis_channel_cnt_
53                 1,
54                 // codec_specific
55                 types::LeAudioLtvMap({
56                         LTV_ENTRY_SAMPLING_FREQUENCY(codec_spec_conf::kLeAudioSamplingFreq16000Hz),
57                         LTV_ENTRY_FRAME_DURATION(codec_spec_conf::kLeAudioCodecFrameDur10000us),
58                         LTV_ENTRY_OCTETS_PER_CODEC_FRAME(40),
59                 }),
60         }},
61         // bits_per_sample
62         16);
63 
64 static const BroadcastSubgroupCodecConfig lc3_stereo_24_2 = BroadcastSubgroupCodecConfig(
65         kLeAudioCodecIdLc3,
66         {BroadcastSubgroupBisCodecConfig{
67                 // num_bis
68                 2,
69                 // bis_channel_cnt_
70                 1,
71                 // codec_specific
72                 types::LeAudioLtvMap({
73                         LTV_ENTRY_SAMPLING_FREQUENCY(codec_spec_conf::kLeAudioSamplingFreq24000Hz),
74                         LTV_ENTRY_FRAME_DURATION(codec_spec_conf::kLeAudioCodecFrameDur10000us),
75                         LTV_ENTRY_OCTETS_PER_CODEC_FRAME(60),
76                 }),
77         }},
78         // bits_per_sample
79         16);
80 
81 static const BroadcastSubgroupCodecConfig lc3_stereo_48_1 = BroadcastSubgroupCodecConfig(
82         kLeAudioCodecIdLc3,
83         {BroadcastSubgroupBisCodecConfig{
84                 // num_bis
85                 2,
86                 // bis_channel_cnt_
87                 1,
88                 // codec_specific
89                 types::LeAudioLtvMap({
90                         LTV_ENTRY_SAMPLING_FREQUENCY(codec_spec_conf::kLeAudioSamplingFreq48000Hz),
91                         LTV_ENTRY_FRAME_DURATION(codec_spec_conf::kLeAudioCodecFrameDur7500us),
92                         LTV_ENTRY_OCTETS_PER_CODEC_FRAME(75),
93                 }),
94         }},
95         // bits_per_sample
96         16);
97 
98 static const BroadcastSubgroupCodecConfig lc3_stereo_48_2 = BroadcastSubgroupCodecConfig(
99         kLeAudioCodecIdLc3,
100         {BroadcastSubgroupBisCodecConfig{
101                 // num_bis
102                 2,
103                 // bis_channel_cnt_
104                 1,
105                 // codec_specific
106                 types::LeAudioLtvMap({
107                         LTV_ENTRY_SAMPLING_FREQUENCY(codec_spec_conf::kLeAudioSamplingFreq48000Hz),
108                         LTV_ENTRY_FRAME_DURATION(codec_spec_conf::kLeAudioCodecFrameDur10000us),
109                         LTV_ENTRY_OCTETS_PER_CODEC_FRAME(100),
110                 }),
111         }},
112         // bits_per_sample
113         16);
114 
115 static const BroadcastSubgroupCodecConfig lc3_stereo_48_3 = BroadcastSubgroupCodecConfig(
116         kLeAudioCodecIdLc3,
117         {BroadcastSubgroupBisCodecConfig{
118                 // num_bis
119                 2,
120                 // bis_channel_cnt_
121                 1,
122                 // codec_specific
123                 types::LeAudioLtvMap({
124                         LTV_ENTRY_SAMPLING_FREQUENCY(codec_spec_conf::kLeAudioSamplingFreq48000Hz),
125                         LTV_ENTRY_FRAME_DURATION(codec_spec_conf::kLeAudioCodecFrameDur7500us),
126                         LTV_ENTRY_OCTETS_PER_CODEC_FRAME(90),
127                 }),
128         }},
129         // bits_per_sample
130         16);
131 
132 static const BroadcastSubgroupCodecConfig lc3_stereo_48_4 = BroadcastSubgroupCodecConfig(
133         kLeAudioCodecIdLc3,
134         {BroadcastSubgroupBisCodecConfig{
135                 // num_bis
136                 2,
137                 // bis_channel_cnt_
138                 1,
139                 // codec_specific
140                 types::LeAudioLtvMap({
141                         LTV_ENTRY_SAMPLING_FREQUENCY(codec_spec_conf::kLeAudioSamplingFreq48000Hz),
142                         LTV_ENTRY_FRAME_DURATION(codec_spec_conf::kLeAudioCodecFrameDur10000us),
143                         LTV_ENTRY_OCTETS_PER_CODEC_FRAME(120),
144                 }),
145         }},
146         // bits_per_sample
147         16);
148 
149 static const types::DataPathConfiguration lc3_data_path = {
150         .dataPathId = bluetooth::hci::iso_manager::kIsoDataPathHci,
151         .dataPathConfig = {},
152         .isoDataPathConfig =
153                 {
154                         .codecId = kLeAudioCodecIdLc3,
155                         .isTransparent = true,
156                         .controllerDelayUs = 0x00000000,  // irrlevant for transparent mode
157                         .configuration = {},
158                 },
159 };
160 
161 static const BroadcastQosConfig qos_config_2_10 = BroadcastQosConfig(2, 10);
162 static const BroadcastQosConfig qos_config_4_45 = BroadcastQosConfig(4, 45);
163 static const BroadcastQosConfig qos_config_4_50 = BroadcastQosConfig(4, 50);
164 static const BroadcastQosConfig qos_config_4_60 = BroadcastQosConfig(4, 60);
165 static const BroadcastQosConfig qos_config_4_65 = BroadcastQosConfig(4, 65);
166 
167 // Standard single subgroup configurations
168 static const BroadcastConfiguration lc3_mono_16_2_1 = {
169         // subgroup list, qos configuration, data path configuration
170         .subgroups = {lc3_mono_16_2},
171         .qos = qos_config_2_10,
172         .data_path = lc3_data_path,
173         .sduIntervalUs = 10000,
174         .maxSduOctets = 40,
175         .phy = 0x02,   // PHY_LE_2M
176         .packing = 0,  // Sequential
177         .framing = 0,  // Unframed
178 };
179 
180 static const BroadcastConfiguration lc3_mono_16_2_2 = {
181         // subgroup list, qos configuration, data path configuration
182         .subgroups = {lc3_mono_16_2},
183         .qos = qos_config_4_60,
184         .data_path = lc3_data_path,
185         .sduIntervalUs = 10000,
186         .maxSduOctets = 40,
187         .phy = 0x02,   // PHY_LE_2M
188         .packing = 0,  // Sequential
189         .framing = 0,  // Unframed
190 };
191 
192 static const BroadcastConfiguration lc3_stereo_16_2_2 = {
193         // subgroup list, qos configuration, data path configuration
194         .subgroups = {lc3_stereo_16_2},
195         .qos = qos_config_4_60,
196         .data_path = lc3_data_path,
197         .sduIntervalUs = 10000,
198         .maxSduOctets = 80,
199         .phy = 0x02,   // PHY_LE_2M
200         .packing = 0,  // Sequential
201         .framing = 0,  // Unframed
202 };
203 
204 static const BroadcastConfiguration lc3_stereo_24_2_1 = {
205         // subgroup list, qos configuration, data path configuration
206         .subgroups = {lc3_stereo_24_2},
207         .qos = qos_config_2_10,
208         .data_path = lc3_data_path,
209         .sduIntervalUs = 10000,
210         .maxSduOctets = 120,
211         .phy = 0x02,   // PHY_LE_2M
212         .packing = 0,  // Sequential
213         .framing = 0,  // Unframed
214 };
215 
216 static const BroadcastConfiguration lc3_stereo_24_2_2 = {
217         // subgroup list, qos configuration, data path configuration
218         .subgroups = {lc3_stereo_24_2},
219         .qos = qos_config_4_60,
220         .data_path = lc3_data_path,
221         .sduIntervalUs = 10000,
222         .maxSduOctets = 120,
223         .phy = 0x02,   // PHY_LE_2M
224         .packing = 0,  // Sequential
225         .framing = 0,  // Unframed
226 };
227 
228 static const BroadcastConfiguration lc3_stereo_48_1_2 = {
229         // subgroup list, qos configuration, data path configuration
230         .subgroups = {lc3_stereo_48_1},
231         .qos = qos_config_4_50,
232         .data_path = lc3_data_path,
233         .sduIntervalUs = 10000,
234         .maxSduOctets = 150,
235         .phy = 0x02,   // PHY_LE_2M
236         .packing = 0,  // Sequential
237         .framing = 0   // Unframed,
238 };
239 
240 static const BroadcastConfiguration lc3_stereo_48_2_2 = {
241         // subgroup list, qos configuration, data path configuration
242         .subgroups = {lc3_stereo_48_2},
243         .qos = qos_config_4_65,
244         .data_path = lc3_data_path,
245         .sduIntervalUs = 10000,
246         .maxSduOctets = 200,
247         .phy = 0x02,   // PHY_LE_2M
248         .packing = 0,  // Sequential
249         .framing = 0   // Unframed,
250 };
251 
252 static const BroadcastConfiguration lc3_stereo_48_3_2 = {
253         // subgroup list, qos configuration, data path configuration
254         .subgroups = {lc3_stereo_48_3},
255         .qos = qos_config_4_50,
256         .data_path = lc3_data_path,
257         .sduIntervalUs = 10000,
258         .maxSduOctets = 180,
259         .phy = 0x02,   // PHY_LE_2M
260         .packing = 0,  // Sequential
261         .framing = 0   // Unframed,
262 };
263 
264 static const BroadcastConfiguration lc3_stereo_48_4_2 = {
265         // subgroup list, qos configuration, data path configuration
266         .subgroups = {lc3_stereo_48_4},
267         .qos = qos_config_4_65,
268         .data_path = lc3_data_path,
269         .sduIntervalUs = 10000,
270         .maxSduOctets = 240,
271         .phy = 0x02,   // PHY_LE_2M
272         .packing = 0,  // Sequential
273         .framing = 0   // Unframed,
274 };
275 
276 // Takes a list of subgroup requirements (audio context, quality index)
277 BroadcastConfiguration GetBroadcastConfig(
278         const std::vector<std::pair<types::LeAudioContextType, uint8_t>>& subgroup_quality);
279 
280 }  // namespace broadcaster
281 }  // namespace bluetooth::le_audio
282