1 /*
2 * Copyright 2016 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 /**
18 * Vendor Specific A2DP Codecs Support
19 */
20
21 #define LOG_TAG "bluetooth-a2dp"
22
23 #include "a2dp_vendor.h"
24
25 #include <cstddef>
26 #include <cstdint>
27 #include <string>
28
29 #include "a2dp_codec_api.h"
30 #include "a2dp_constants.h"
31 #include "a2dp_vendor_aptx.h"
32 #include "a2dp_vendor_aptx_constants.h"
33 #include "a2dp_vendor_aptx_hd.h"
34 #include "a2dp_vendor_aptx_hd_constants.h"
35 #include "a2dp_vendor_ldac.h"
36 #include "a2dp_vendor_ldac_constants.h"
37 #include "a2dp_vendor_opus.h"
38 #include "a2dp_vendor_opus_constants.h"
39 #include "avdt_api.h"
40 #include "hardware/bt_av.h"
41 #include "stack/include/bt_hdr.h"
42
A2DP_IsVendorSourceCodecValid(const uint8_t * p_codec_info)43 bool A2DP_IsVendorSourceCodecValid(const uint8_t* p_codec_info) {
44 uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
45 uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
46
47 // Check for aptX
48 if (vendor_id == A2DP_APTX_VENDOR_ID &&
49 codec_id == A2DP_APTX_CODEC_ID_BLUETOOTH) {
50 return A2DP_IsCodecValidAptx(p_codec_info);
51 }
52
53 // Check for aptX-HD
54 if (vendor_id == A2DP_APTX_HD_VENDOR_ID &&
55 codec_id == A2DP_APTX_HD_CODEC_ID_BLUETOOTH) {
56 return A2DP_IsCodecValidAptxHd(p_codec_info);
57 }
58
59 // Check for LDAC
60 if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
61 return A2DP_IsCodecValidLdac(p_codec_info);
62 }
63
64 // Check for Opus
65 if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) {
66 return A2DP_IsCodecValidOpus(p_codec_info);
67 }
68
69 // Add checks based on <vendor_id, codec_id>
70
71 return false;
72 }
73
A2DP_IsVendorPeerSourceCodecValid(const uint8_t * p_codec_info)74 bool A2DP_IsVendorPeerSourceCodecValid(const uint8_t* p_codec_info) {
75 uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
76 uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
77
78 // Add checks based on <vendor_id, codec_id>
79 // NOTE: Should be done only for local Sink codecs.
80
81 // Check for LDAC
82 if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
83 return A2DP_IsCodecValidLdac(p_codec_info);
84 }
85
86 // Check for Opus
87 if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) {
88 return A2DP_IsCodecValidOpus(p_codec_info);
89 }
90
91 return false;
92 }
93
A2DP_IsVendorPeerSinkCodecValid(const uint8_t * p_codec_info)94 bool A2DP_IsVendorPeerSinkCodecValid(const uint8_t* p_codec_info) {
95 uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
96 uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
97
98 // Check for aptX
99 if (vendor_id == A2DP_APTX_VENDOR_ID &&
100 codec_id == A2DP_APTX_CODEC_ID_BLUETOOTH) {
101 return A2DP_IsCodecValidAptx(p_codec_info);
102 }
103
104 // Check for aptX-HD
105 if (vendor_id == A2DP_APTX_HD_VENDOR_ID &&
106 codec_id == A2DP_APTX_HD_CODEC_ID_BLUETOOTH) {
107 return A2DP_IsCodecValidAptxHd(p_codec_info);
108 }
109
110 // Check for LDAC
111 if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
112 return A2DP_IsCodecValidLdac(p_codec_info);
113 }
114
115 // Check for Opus
116 if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) {
117 return A2DP_IsCodecValidOpus(p_codec_info);
118 }
119
120 // Add checks based on <vendor_id, codec_id>
121
122 return false;
123 }
124
A2DP_IsVendorSinkCodecSupported(const uint8_t * p_codec_info)125 tA2DP_STATUS A2DP_IsVendorSinkCodecSupported(const uint8_t* p_codec_info) {
126 uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
127 uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
128
129 // Add checks based on <vendor_id, codec_id>
130 // NOTE: Should be done only for local Sink codecs.
131
132 // Check for Opus
133 if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) {
134 return A2DP_IsVendorSinkCodecSupportedOpus(p_codec_info);
135 }
136
137 return A2DP_NOT_SUPPORTED_CODEC_TYPE;
138 }
139
A2DP_VendorUsesRtpHeader(bool content_protection_enabled,const uint8_t * p_codec_info)140 bool A2DP_VendorUsesRtpHeader(bool content_protection_enabled, const uint8_t* p_codec_info) {
141 uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
142 uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
143
144 // Check for aptX
145 if (vendor_id == A2DP_APTX_VENDOR_ID && codec_id == A2DP_APTX_CODEC_ID_BLUETOOTH) {
146 return A2DP_VendorUsesRtpHeaderAptx(content_protection_enabled, p_codec_info);
147 }
148
149 // Check for aptX-HD
150 if (vendor_id == A2DP_APTX_HD_VENDOR_ID && codec_id == A2DP_APTX_HD_CODEC_ID_BLUETOOTH) {
151 return A2DP_VendorUsesRtpHeaderAptxHd(content_protection_enabled, p_codec_info);
152 }
153
154 // Check for LDAC
155 if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
156 return A2DP_VendorUsesRtpHeaderLdac(content_protection_enabled, p_codec_info);
157 }
158
159 // Check for Opus
160 if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) {
161 return A2DP_VendorUsesRtpHeaderOpus(content_protection_enabled, p_codec_info);
162 }
163
164 // Add checks based on <content_protection_enabled, vendor_id, codec_id>
165
166 return true;
167 }
168
A2DP_VendorCodecName(const uint8_t * p_codec_info)169 const char* A2DP_VendorCodecName(const uint8_t* p_codec_info) {
170 uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
171 uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
172
173 // Check for aptX
174 if (vendor_id == A2DP_APTX_VENDOR_ID && codec_id == A2DP_APTX_CODEC_ID_BLUETOOTH) {
175 return A2DP_VendorCodecNameAptx(p_codec_info);
176 }
177
178 // Check for aptX-HD
179 if (vendor_id == A2DP_APTX_HD_VENDOR_ID && codec_id == A2DP_APTX_HD_CODEC_ID_BLUETOOTH) {
180 return A2DP_VendorCodecNameAptxHd(p_codec_info);
181 }
182
183 // Check for LDAC
184 if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
185 return A2DP_VendorCodecNameLdac(p_codec_info);
186 }
187
188 // Check for Opus
189 if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) {
190 return A2DP_VendorCodecNameOpus(p_codec_info);
191 }
192
193 // Add checks based on <vendor_id, codec_id>
194
195 return "UNKNOWN VENDOR CODEC";
196 }
197
A2DP_VendorCodecTypeEquals(const uint8_t * p_codec_info_a,const uint8_t * p_codec_info_b)198 bool A2DP_VendorCodecTypeEquals(const uint8_t* p_codec_info_a, const uint8_t* p_codec_info_b) {
199 tA2DP_CODEC_TYPE codec_type_a = A2DP_GetCodecType(p_codec_info_a);
200 tA2DP_CODEC_TYPE codec_type_b = A2DP_GetCodecType(p_codec_info_b);
201
202 if ((codec_type_a != codec_type_b) || (codec_type_a != A2DP_MEDIA_CT_NON_A2DP)) {
203 return false;
204 }
205
206 uint32_t vendor_id_a = A2DP_VendorCodecGetVendorId(p_codec_info_a);
207 uint16_t codec_id_a = A2DP_VendorCodecGetCodecId(p_codec_info_a);
208 uint32_t vendor_id_b = A2DP_VendorCodecGetVendorId(p_codec_info_b);
209 uint16_t codec_id_b = A2DP_VendorCodecGetCodecId(p_codec_info_b);
210
211 if (vendor_id_a != vendor_id_b || codec_id_a != codec_id_b) {
212 return false;
213 }
214
215 // Check for aptX
216 if (vendor_id_a == A2DP_APTX_VENDOR_ID && codec_id_a == A2DP_APTX_CODEC_ID_BLUETOOTH) {
217 return A2DP_VendorCodecTypeEqualsAptx(p_codec_info_a, p_codec_info_b);
218 }
219
220 // Check for aptX-HD
221 if (vendor_id_a == A2DP_APTX_HD_VENDOR_ID && codec_id_a == A2DP_APTX_HD_CODEC_ID_BLUETOOTH) {
222 return A2DP_VendorCodecTypeEqualsAptxHd(p_codec_info_a, p_codec_info_b);
223 }
224
225 // Check for LDAC
226 if (vendor_id_a == A2DP_LDAC_VENDOR_ID && codec_id_a == A2DP_LDAC_CODEC_ID) {
227 return A2DP_VendorCodecTypeEqualsLdac(p_codec_info_a, p_codec_info_b);
228 }
229
230 // Check for Opus
231 if (vendor_id_a == A2DP_OPUS_VENDOR_ID && codec_id_a == A2DP_OPUS_CODEC_ID) {
232 return A2DP_VendorCodecTypeEqualsOpus(p_codec_info_a, p_codec_info_b);
233 }
234
235 // OPTIONAL: Add extra vendor-specific checks based on the
236 // vendor-specific data stored in "p_codec_info_a" and "p_codec_info_b".
237
238 return true;
239 }
240
A2DP_VendorGetBitRate(const uint8_t * p_codec_info)241 int A2DP_VendorGetBitRate(const uint8_t* p_codec_info) {
242 uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
243 uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
244
245 // Check for aptX
246 if (vendor_id == A2DP_APTX_VENDOR_ID && codec_id == A2DP_APTX_CODEC_ID_BLUETOOTH) {
247 return A2DP_VendorGetBitRateAptx(p_codec_info);
248 }
249
250 // Check for aptX-HD
251 if (vendor_id == A2DP_APTX_HD_VENDOR_ID && codec_id == A2DP_APTX_HD_CODEC_ID_BLUETOOTH) {
252 return A2DP_VendorGetBitRateAptxHd(p_codec_info);
253 }
254
255 // Check for LDAC
256 if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
257 return A2DP_VendorGetBitRateLdac(p_codec_info);
258 }
259
260 // Check for Opus
261 if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) {
262 return A2DP_VendorGetBitRateOpus(p_codec_info);
263 }
264
265 // Add checks based on <vendor_id, codec_id>
266
267 return -1;
268 }
269
A2DP_VendorGetSinkTrackChannelType(const uint8_t * p_codec_info)270 int A2DP_VendorGetSinkTrackChannelType(const uint8_t* p_codec_info) {
271 uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
272 uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
273
274 // Add checks based on <vendor_id, codec_id>
275 // NOTE: Should be done only for local Sink codecs.
276
277 // Check for Opus
278 if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) {
279 return A2DP_VendorGetSinkTrackChannelTypeOpus(p_codec_info);
280 }
281
282 return -1;
283 }
284
A2DP_VendorBuildCodecHeader(const uint8_t * p_codec_info,BT_HDR * p_buf,uint16_t frames_per_packet)285 bool A2DP_VendorBuildCodecHeader(const uint8_t* p_codec_info, BT_HDR* p_buf,
286 uint16_t frames_per_packet) {
287 uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
288 uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
289
290 // Check for aptX
291 if (vendor_id == A2DP_APTX_VENDOR_ID && codec_id == A2DP_APTX_CODEC_ID_BLUETOOTH) {
292 return A2DP_VendorBuildCodecHeaderAptx(p_codec_info, p_buf, frames_per_packet);
293 }
294
295 // Check for aptX-HD
296 if (vendor_id == A2DP_APTX_HD_VENDOR_ID && codec_id == A2DP_APTX_HD_CODEC_ID_BLUETOOTH) {
297 return A2DP_VendorBuildCodecHeaderAptxHd(p_codec_info, p_buf, frames_per_packet);
298 }
299
300 // Check for LDAC
301 if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
302 return A2DP_VendorBuildCodecHeaderLdac(p_codec_info, p_buf, frames_per_packet);
303 }
304
305 // Check for Opus
306 if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) {
307 return A2DP_VendorBuildCodecHeaderOpus(p_codec_info, p_buf, frames_per_packet);
308 }
309
310 // Add checks based on <vendor_id, codec_id>
311
312 return false;
313 }
314
A2DP_VendorGetEncoderInterface(const uint8_t * p_codec_info)315 const tA2DP_ENCODER_INTERFACE* A2DP_VendorGetEncoderInterface(const uint8_t* p_codec_info) {
316 uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
317 uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
318
319 // Check for aptX
320 if (vendor_id == A2DP_APTX_VENDOR_ID && codec_id == A2DP_APTX_CODEC_ID_BLUETOOTH) {
321 return A2DP_VendorGetEncoderInterfaceAptx(p_codec_info);
322 }
323
324 // Check for aptX-HD
325 if (vendor_id == A2DP_APTX_HD_VENDOR_ID && codec_id == A2DP_APTX_HD_CODEC_ID_BLUETOOTH) {
326 return A2DP_VendorGetEncoderInterfaceAptxHd(p_codec_info);
327 }
328
329 // Check for LDAC
330 if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
331 return A2DP_VendorGetEncoderInterfaceLdac(p_codec_info);
332 }
333
334 // Check for Opus
335 if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) {
336 return A2DP_VendorGetEncoderInterfaceOpus(p_codec_info);
337 }
338
339 // Add checks based on <vendor_id, codec_id>
340
341 return NULL;
342 }
343
A2DP_VendorGetDecoderInterface(const uint8_t * p_codec_info)344 const tA2DP_DECODER_INTERFACE* A2DP_VendorGetDecoderInterface(const uint8_t* p_codec_info) {
345 uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
346 uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
347
348 // Add checks based on <vendor_id, codec_id>
349 // NOTE: Should be done only for local Sink codecs.
350
351 // Check for Opus
352 if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) {
353 return A2DP_VendorGetDecoderInterfaceOpus(p_codec_info);
354 }
355
356 return NULL;
357 }
358
A2DP_VendorAdjustCodec(uint8_t * p_codec_info)359 bool A2DP_VendorAdjustCodec(uint8_t* p_codec_info) {
360 uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
361 uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
362
363 // Check for aptX
364 if (vendor_id == A2DP_APTX_VENDOR_ID && codec_id == A2DP_APTX_CODEC_ID_BLUETOOTH) {
365 return A2DP_VendorAdjustCodecAptx(p_codec_info);
366 }
367
368 // Check for aptX-HD
369 if (vendor_id == A2DP_APTX_HD_VENDOR_ID && codec_id == A2DP_APTX_HD_CODEC_ID_BLUETOOTH) {
370 return A2DP_VendorAdjustCodecAptxHd(p_codec_info);
371 }
372
373 // Check for LDAC
374 if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
375 return A2DP_VendorAdjustCodecLdac(p_codec_info);
376 }
377
378 // Check for Opus
379 if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) {
380 return A2DP_VendorAdjustCodecOpus(p_codec_info);
381 }
382
383 // Add checks based on <vendor_id, codec_id>
384
385 return false;
386 }
387
A2DP_VendorSourceCodecIndex(const uint8_t * p_codec_info)388 btav_a2dp_codec_index_t A2DP_VendorSourceCodecIndex(const uint8_t* p_codec_info) {
389 uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
390 uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
391
392 // Check for aptX
393 if (vendor_id == A2DP_APTX_VENDOR_ID && codec_id == A2DP_APTX_CODEC_ID_BLUETOOTH) {
394 return A2DP_VendorSourceCodecIndexAptx(p_codec_info);
395 }
396
397 // Check for aptX-HD
398 if (vendor_id == A2DP_APTX_HD_VENDOR_ID && codec_id == A2DP_APTX_HD_CODEC_ID_BLUETOOTH) {
399 return A2DP_VendorSourceCodecIndexAptxHd(p_codec_info);
400 }
401
402 // Check for LDAC
403 if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
404 return A2DP_VendorSourceCodecIndexLdac(p_codec_info);
405 }
406
407 // Check for Opus
408 if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) {
409 return A2DP_VendorSourceCodecIndexOpus(p_codec_info);
410 }
411
412 // Add checks based on <vendor_id, codec_id>
413
414 return BTAV_A2DP_CODEC_INDEX_MAX;
415 }
416
A2DP_VendorSinkCodecIndex(const uint8_t * p_codec_info)417 btav_a2dp_codec_index_t A2DP_VendorSinkCodecIndex(const uint8_t* p_codec_info) {
418 uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
419 uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
420
421 // Add checks based on <vendor_id, codec_id>
422 // NOTE: Should be done only for local Sink codecs.
423
424 // Check for Opus
425 if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) {
426 return A2DP_VendorSinkCodecIndexOpus(p_codec_info);
427 }
428
429 return BTAV_A2DP_CODEC_INDEX_MAX;
430 }
431
A2DP_VendorCodecIndexStr(btav_a2dp_codec_index_t codec_index)432 const char* A2DP_VendorCodecIndexStr(btav_a2dp_codec_index_t codec_index) {
433 // Add checks based on codec_index
434 switch (codec_index) {
435 case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
436 case BTAV_A2DP_CODEC_INDEX_SINK_SBC:
437 case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
438 case BTAV_A2DP_CODEC_INDEX_SINK_AAC:
439 break; // These are not vendor-specific codecs
440 case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX:
441 return A2DP_VendorCodecIndexStrAptx();
442 case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD:
443 return A2DP_VendorCodecIndexStrAptxHd();
444 case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC:
445 return A2DP_VendorCodecIndexStrLdac();
446 case BTAV_A2DP_CODEC_INDEX_SOURCE_LC3:
447 return "LC3 not implemented";
448 case BTAV_A2DP_CODEC_INDEX_SOURCE_OPUS:
449 return A2DP_VendorCodecIndexStrOpus();
450 case BTAV_A2DP_CODEC_INDEX_SINK_OPUS:
451 return A2DP_VendorCodecIndexStrOpusSink();
452 // Add a switch statement for each vendor-specific codec
453 case BTAV_A2DP_CODEC_INDEX_MAX:
454 break;
455 case BTAV_A2DP_CODEC_INDEX_SOURCE_EXT_MIN:
456 case BTAV_A2DP_CODEC_INDEX_SINK_EXT_MIN:
457 break;
458 }
459
460 return "UNKNOWN CODEC INDEX";
461 }
462
A2DP_VendorInitCodecConfig(btav_a2dp_codec_index_t codec_index,AvdtpSepConfig * p_cfg)463 bool A2DP_VendorInitCodecConfig(btav_a2dp_codec_index_t codec_index, AvdtpSepConfig* p_cfg) {
464 // Add checks based on codec_index
465 switch (codec_index) {
466 case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
467 case BTAV_A2DP_CODEC_INDEX_SINK_SBC:
468 case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
469 case BTAV_A2DP_CODEC_INDEX_SINK_AAC:
470 break; // These are not vendor-specific codecs
471 case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX:
472 return A2DP_VendorInitCodecConfigAptx(p_cfg);
473 case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD:
474 return A2DP_VendorInitCodecConfigAptxHd(p_cfg);
475 case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC:
476 return A2DP_VendorInitCodecConfigLdac(p_cfg);
477 case BTAV_A2DP_CODEC_INDEX_SOURCE_LC3:
478 break; // not implemented
479 case BTAV_A2DP_CODEC_INDEX_SOURCE_OPUS:
480 return A2DP_VendorInitCodecConfigOpus(p_cfg);
481 case BTAV_A2DP_CODEC_INDEX_SINK_OPUS:
482 return A2DP_VendorInitCodecConfigOpusSink(p_cfg);
483 // Add a switch statement for each vendor-specific codec
484 case BTAV_A2DP_CODEC_INDEX_MAX:
485 break;
486 case BTAV_A2DP_CODEC_INDEX_SOURCE_EXT_MIN:
487 case BTAV_A2DP_CODEC_INDEX_SINK_EXT_MIN:
488 break;
489 }
490
491 return false;
492 }
493
A2DP_VendorCodecInfoString(const uint8_t * p_codec_info)494 std::string A2DP_VendorCodecInfoString(const uint8_t* p_codec_info) {
495 uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
496 uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
497
498 // Check for aptX
499 if (vendor_id == A2DP_APTX_VENDOR_ID && codec_id == A2DP_APTX_CODEC_ID_BLUETOOTH) {
500 return A2DP_VendorCodecInfoStringAptx(p_codec_info);
501 }
502
503 // Check for aptX-HD
504 if (vendor_id == A2DP_APTX_HD_VENDOR_ID && codec_id == A2DP_APTX_HD_CODEC_ID_BLUETOOTH) {
505 return A2DP_VendorCodecInfoStringAptxHd(p_codec_info);
506 }
507
508 // Check for LDAC
509 if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
510 return A2DP_VendorCodecInfoStringLdac(p_codec_info);
511 }
512
513 // Check for Opus
514 if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) {
515 return A2DP_VendorCodecInfoStringOpus(p_codec_info);
516 }
517
518 // Add checks based on <vendor_id, codec_id>
519
520 return std::format("Unsupported codec vendor_id: 0x{:x} codec_id: 0x{:x}", vendor_id, codec_id);
521 }
522