• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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