1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "audio_mixer.h"
17
18 #include <assert.h>
19 #include <ctype.h>
20 #include <dlfcn.h>
21 #include <errno.h>
22 #include <limits.h>
23 #include <string.h>
24 #include <strings.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28
29 #include "hdf_base.h"
30 #include "securec.h"
31
32 #define AUDIO_UTIL_VERSION_STR "V1.0.0"
33
34 #define AUDIO_DEV_FILE_PATH "/dev/"
35 #define CTL_SRV_NAME_PRE "hdf_audio_control"
36 #define CTL_SRV_DEFAULT CTL_SRV_NAME_PRE
37 #define MIXER_SRV_NAME_PRE "hdf_audio_codec_"
38 #define MIXER_SRV_NAME MIXER_SRV_NAME_PRE "%s_dev%i"
39 #define MIXER_SRV_NAME_DEFAULT MIXER_SRV_NAME_PRE "primary_dev0"
40 #define SERVICE_NAME_LEN 64
41 #define BUF_SIZE_T 256
42 #define CHN_MONO (1 << 0)
43 #define CHN_STEREO (1 << 1)
44 #define OUTPUT_ALIGN 16
45 #define BIT_VALULE_OFFSET 31
46 #define STRTOL_BASE 10
47
48 #define IFACE(v) [AUDIO_CTL_ELEM_IFACE_##v] = #v
49 #define TYPE(v) [AUDIO_CTL_ELEM_TYPE_##v] = #v
50
51 static struct AudioMixer g_audioMixer;
52 static struct AudioMixerContents g_mixerCts;
53
54 static const char *g_capLibPath = HDF_LIBRARY_FULL_PATH("libaudio_capture_adapter");
55 static const char *g_renLibPath = HDF_LIBRARY_FULL_PATH("libaudio_render_adapter");
56 static void *g_soHandle = NULL;
57 static AudioPcmType g_pcmT = PCM_RENDER;
58 static bool g_debugFlag = false;
59
60 static const char * const ctlEIfNames[] = {
61 IFACE(CARD),
62 IFACE(PCM),
63 IFACE(MIXER),
64 };
65
66 static const char * const ctlElemTypeNames[] = {
67 TYPE(NONE),
68 TYPE(BOOLEAN),
69 TYPE(INTEGER),
70 TYPE(ENUMERATED),
71 TYPE(BYTES),
72 };
73
DebugLog(bool flag)74 void DebugLog(bool flag)
75 {
76 g_debugFlag = flag;
77 }
78
CallLibFunction(const char * funcName)79 static void *CallLibFunction(const char *funcName)
80 {
81 void *func = NULL;
82 char *error = NULL;
83
84 if (g_soHandle == NULL) {
85 DEBUG_LOG("Invalid dynamic library handle!\n");
86 return NULL;
87 }
88
89 (void)dlerror(); /* Clear any existing error */
90 func = dlsym(g_soHandle, funcName);
91 error = dlerror();
92 if (error != NULL) {
93 DEBUG_LOG("%s\n", error);
94 printf("%s\n", error);
95 return NULL;
96 }
97
98 return func;
99 }
100
AudioMixerList(const struct HdfIoService * service,struct AudioMixerContents * mixerCts)101 static int32_t AudioMixerList(const struct HdfIoService *service, struct AudioMixerContents *mixerCts)
102 {
103 int32_t (*AmixerCtlElemList)(AudioPcmType, const struct HdfIoService *, struct AudioMixerContents *);
104
105 AmixerCtlElemList = CallLibFunction("AudioMixerCtlElem");
106 if (AmixerCtlElemList == NULL) {
107 return U_FAILURE;
108 }
109
110 return AmixerCtlElemList(g_pcmT, service, mixerCts);
111 }
112
AudioMixerGet(const struct HdfIoService * service,struct AudioMixerCtlElemInfo * infoData)113 static int32_t AudioMixerGet(const struct HdfIoService *service, struct AudioMixerCtlElemInfo *infoData)
114 {
115 int32_t (*AmixerGetCtlElem)(AudioPcmType, const struct HdfIoService *, struct AudioMixerCtlElemInfo *);
116
117 AmixerGetCtlElem = CallLibFunction("AudioMixerCtlGetElem");
118 if (AmixerGetCtlElem == NULL) {
119 return U_FAILURE;
120 }
121
122 return AmixerGetCtlElem(g_pcmT, service, infoData);
123 }
124
AudioMixerSet(const struct HdfIoService * service,struct AudioMixerCtlElemInfo * infoData)125 static int32_t AudioMixerSet(const struct HdfIoService *service, struct AudioMixerCtlElemInfo *infoData)
126 {
127 int32_t (*AmixerSetCtlElem)(AudioPcmType, const struct HdfIoService *, struct AudioMixerCtlElemInfo *);
128
129 AmixerSetCtlElem = CallLibFunction("AudioMixerCtlSetElem");
130 if (AmixerSetCtlElem == NULL) {
131 return U_FAILURE;
132 }
133
134 return AmixerSetCtlElem(g_pcmT, service, infoData);
135 }
136
GetSoHandle(const char * filename)137 static int32_t GetSoHandle(const char *filename)
138 {
139 char buf[PATH_MAX] = {0};
140
141 if (realpath(filename, buf) == NULL) {
142 return U_FAILURE;
143 }
144
145 if (g_soHandle != NULL) {
146 DEBUG_LOG("It's been initialized!\n");
147 return U_SUCCESS;
148 }
149
150 g_soHandle = dlopen(buf, RTLD_LAZY);
151 if (g_soHandle == NULL) {
152 DEBUG_LOG("%s\n", dlerror());
153 printf("%s\n", dlerror());
154 return U_FAILURE;
155 }
156
157 return U_SUCCESS;
158 }
159
GetLibsoHandle(AudioPcmType pcm)160 int32_t GetLibsoHandle(AudioPcmType pcm)
161 {
162 int32_t ret;
163
164 g_pcmT = pcm;
165 switch (pcm) {
166 default:
167 DEBUG_LOG("Wrong PCM type!\n");
168 /* fall through */
169 __attribute__((fallthrough));
170 case PCM_RENDER:
171 ret = GetSoHandle(g_renLibPath);
172 if (ret != U_SUCCESS) {
173 DEBUG_LOG("Failed to open the render dynamic library!\n");
174 }
175 break;
176 case PCM_CAPTURE:
177 ret = GetSoHandle(g_capLibPath);
178 if (ret != U_SUCCESS) {
179 DEBUG_LOG("Failed to open the capture dynamic library!\n");
180 }
181 break;
182 }
183
184 return ret;
185 }
186
CloseLibsoHandle(void)187 void CloseLibsoHandle(void)
188 {
189 if (g_soHandle != NULL) {
190 (void)dlclose(g_soHandle);
191 g_soHandle = NULL;
192 }
193 }
194
AudioMixerOpsInit(void)195 void AudioMixerOpsInit(void)
196 {
197 g_audioMixer.GetElemList = AudioMixerList;
198 g_audioMixer.GetElemProp = AudioMixerGet;
199 g_audioMixer.SetElemProp = AudioMixerSet;
200
201 g_mixerCts.data = NULL;
202 g_mixerCts.elemNum = 0;
203 (void)memset_s(g_mixerCts.cardServiceName, AUDIO_CARD_SRV_NAME_LEN, 0x0, AUDIO_CARD_SRV_NAME_LEN);
204 }
205
ShowVersion(void)206 const char *ShowVersion(void)
207 {
208 return AUDIO_UTIL_VERSION_STR;
209 }
210
CheckMixerDevFile(const char * file)211 static bool CheckMixerDevFile(const char *file)
212 {
213 char buf[PATH_MAX] = {0};
214
215 if (realpath(file, buf) == NULL) {
216 DEBUG_LOG("%s\n", strerror(errno));
217 return false;
218 }
219
220 if (access(file, F_OK)) {
221 DEBUG_LOG("%s\n", strerror(errno));
222 return false;
223 }
224
225 return true;
226 }
227
MixerBindCrlSrvDefault(void)228 struct HdfIoService *MixerBindCrlSrvDefault(void)
229 {
230 int ret;
231 char buf[BUF_SIZE_T + 1] = {0};
232 struct HdfIoService *(*SrvBindDef)(const char *);
233
234 ret = snprintf_s(buf, BUF_SIZE_T, BUF_SIZE_T, "%s%s", AUDIO_DEV_FILE_PATH, MIXER_SRV_NAME_DEFAULT);
235 if (ret < 0) {
236 DEBUG_LOG("Failed to synthesize the service path!\n");
237 return NULL;
238 }
239
240 if (!CheckMixerDevFile(buf)) {
241 /* The sound card service file does not exist */
242 return NULL;
243 }
244
245 SrvBindDef = CallLibFunction("HdfIoServiceBindName");
246 if (SrvBindDef == NULL) {
247 return NULL;
248 }
249
250 return SrvBindDef(CTL_SRV_DEFAULT);
251 }
252
MixerBindCrlSrv(const char * serviceName)253 struct HdfIoService *MixerBindCrlSrv(const char *serviceName)
254 {
255 int ret;
256 char path[BUF_SIZE_T + 1] = {0};
257 struct HdfIoService *(*SrvBind)(const char *);
258
259 if (serviceName == NULL) {
260 DEBUG_LOG("Invalid parameters!\n");
261 return NULL;
262 }
263
264 if (strncmp(serviceName, MIXER_SRV_NAME_PRE, strlen(MIXER_SRV_NAME_PRE))) {
265 DEBUG_LOG("The service name does not match!\n");
266 return NULL;
267 }
268
269 ret = snprintf_s(path, BUF_SIZE_T, BUF_SIZE_T, "%s%s", AUDIO_DEV_FILE_PATH, serviceName);
270 if (ret < 0) {
271 DEBUG_LOG("Failed to synthesize the service path!\n");
272 return NULL;
273 }
274 if (!CheckMixerDevFile(path)) {
275 /* The sound card service file does not exist */
276 return NULL;
277 }
278
279 SrvBind = CallLibFunction("HdfIoServiceBindName");
280 if (SrvBind == NULL) {
281 return NULL;
282 }
283
284 return SrvBind(CTL_SRV_DEFAULT);
285 }
286
MixerRecycleCrlSrv(struct HdfIoService * srv)287 void MixerRecycleCrlSrv(struct HdfIoService *srv)
288 {
289 void (*SrvRecycle)(struct HdfIoService *);
290
291 if (srv != NULL) {
292 SrvRecycle = CallLibFunction("AudioCloseServiceSub");
293 if (SrvRecycle != NULL) {
294 SrvRecycle(srv);
295 }
296 }
297 }
298
CtlElemIfaceName(AudioCtlElemIfaceType iface)299 static const char *CtlElemIfaceName(AudioCtlElemIfaceType iface)
300 {
301 return ctlEIfNames[iface];
302 }
303
CtlElemName(struct AudioHwCtlElemIndex * id)304 static const char *CtlElemName(struct AudioHwCtlElemIndex *id)
305 {
306 return (const char *)id->eId.name;
307 }
308
PrintCtlElemInfo(struct AudioHwCtlElemId * id)309 static void PrintCtlElemInfo(struct AudioHwCtlElemId *id)
310 {
311 printf("iface=%s, name='%s'\n", CtlElemIfaceName(id->iface), id->name);
312 }
313
PrintCtlElemInfoidx(struct MixerCtsElemIdx * eidx)314 static void PrintCtlElemInfoidx(struct MixerCtsElemIdx *eidx)
315 {
316 printf("index=%u, numid=%u, ", eidx->index, eidx->index + 1);
317 PrintCtlElemInfo(eidx->id);
318 }
319
PrintCtlElemList(struct AudioMixerContents * contents)320 static void PrintCtlElemList(struct AudioMixerContents *contents)
321 {
322 uint32_t num, idx;
323 struct MixerCtsElemIdx eidx;
324 struct AudioHwCtlElemId *id = NULL;
325
326 num = contents->elemNum;
327 id = (struct AudioHwCtlElemId *)contents->data;
328 for (idx = 0; idx < num; idx++) {
329 eidx.id = id++;
330 eidx.index = idx;
331 PrintCtlElemInfoidx(&eidx);
332 }
333 }
334
ReleaseCtlElemList(void)335 void ReleaseCtlElemList(void)
336 {
337 if (g_mixerCts.data != NULL) {
338 free(g_mixerCts.data);
339 g_mixerCts.data = NULL;
340 }
341 g_mixerCts.elemNum = 0;
342 (void)memset_s(g_mixerCts.cardServiceName, AUDIO_CARD_SRV_NAME_LEN, 0x0, AUDIO_CARD_SRV_NAME_LEN);
343 }
344
MctlListSub(const struct HdfIoService * service,const char * cardSrv)345 static int32_t MctlListSub(const struct HdfIoService *service, const char *cardSrv)
346 {
347 int32_t ret;
348
349 ret = strncpy_s(g_mixerCts.cardServiceName, AUDIO_CARD_SRV_NAME_LEN - 1, cardSrv, AUDIO_CARD_SRV_NAME_LEN - 1);
350 if (ret != 0) {
351 DEBUG_LOG("strncpy_s fail!\n");
352 return U_FAILURE;
353 }
354 g_mixerCts.cardServiceName[AUDIO_CARD_SRV_NAME_LEN - 1] = '\0';
355 if (g_audioMixer.GetElemList == NULL) {
356 DEBUG_LOG("The callback function is NULL!\n");
357 return U_FAILURE;
358 }
359
360 if (g_mixerCts.data != NULL && g_mixerCts.elemNum > 0) {
361 /* The list of control elements has been obtained */
362 return U_SUCCESS;
363 }
364
365 if (g_mixerCts.data != NULL) {
366 free(g_mixerCts.data);
367 g_mixerCts.data = NULL;
368 }
369 g_mixerCts.elemNum = 0;
370
371 ret = g_audioMixer.GetElemList(service, &g_mixerCts);
372 if (ret != U_SUCCESS) {
373 return ret;
374 }
375 if (g_mixerCts.data == NULL) {
376 g_mixerCts.elemNum = 0;
377 (void)memset_s(g_mixerCts.cardServiceName, AUDIO_CARD_SRV_NAME_LEN, 0x0, AUDIO_CARD_SRV_NAME_LEN);
378 DEBUG_LOG("Failed to obtain data!\n");
379 return U_FAILURE;
380 }
381 if (g_mixerCts.elemNum == 0) {
382 free(g_mixerCts.data);
383 g_mixerCts.data = NULL;
384 (void)memset_s(g_mixerCts.cardServiceName, AUDIO_CARD_SRV_NAME_LEN, 0x0, AUDIO_CARD_SRV_NAME_LEN);
385 DEBUG_LOG("Description Failed to obtain the number of data!\n");
386 return U_FAILURE;
387 }
388
389 return U_SUCCESS;
390 }
391
MctlList(const struct HdfIoService * service,const char * cardSrv)392 int32_t MctlList(const struct HdfIoService *service, const char *cardSrv)
393 {
394 int32_t ret;
395
396 if (service == NULL || cardSrv == NULL) {
397 DEBUG_LOG("Invalid parameters!\n");
398 return U_INVALID_PARAM;
399 }
400
401 ret = MctlListSub(service, cardSrv);
402 if (ret != U_SUCCESS) {
403 return ret;
404 }
405 PrintCtlElemList(&g_mixerCts);
406
407 return U_SUCCESS;
408 }
409
MctlInfo(const struct HdfIoService * service,const char * cardSrv)410 int32_t MctlInfo(const struct HdfIoService *service, const char *cardSrv)
411 {
412 int32_t ret;
413 uint32_t num;
414 struct AudioHwCtlElemId *id;
415
416 if (g_mixerCts.data == NULL || g_mixerCts.elemNum == 0) {
417 ReleaseCtlElemList();
418 ret = MctlListSub(service, cardSrv);
419 if (ret != U_SUCCESS) {
420 DEBUG_LOG("No reference data\n");
421 return ret;
422 }
423 }
424
425 /* The list of control elements has been obtained */
426 num = g_mixerCts.elemNum;
427 id = (struct AudioHwCtlElemId *)g_mixerCts.data;
428 while (num--) {
429 PrintCtlElemInfo(id++);
430 }
431 ReleaseCtlElemList();
432
433 return U_SUCCESS;
434 }
435
MixerFindSelem(const struct HdfIoService * srv,const char * cardSrv,const struct AudioHwCtlElemId * eId)436 bool MixerFindSelem(const struct HdfIoService *srv, const char *cardSrv, const struct AudioHwCtlElemId *eId)
437 {
438 int32_t ret;
439 uint32_t index;
440 struct AudioHwCtlElemId *findElem;
441
442 if (eId == NULL) {
443 DEBUG_LOG("Invalid parameters\n");
444 return false;
445 }
446
447 if (g_mixerCts.elemNum == 0 || g_mixerCts.data == NULL) {
448 ReleaseCtlElemList();
449 ret = MctlListSub(srv, cardSrv);
450 if (ret != U_SUCCESS) {
451 DEBUG_LOG("No reference data\n");
452 return false;
453 }
454 }
455
456 findElem = g_mixerCts.data;
457 for (index = 0; index < g_mixerCts.elemNum; index++) {
458 if (strcmp(eId->name, findElem[index].name) == 0) {
459 break;
460 }
461 }
462 if (index == g_mixerCts.elemNum) {
463 DEBUG_LOG("The corresponding control does not match!\n");
464 ReleaseCtlElemList();
465 return false;
466 }
467 ReleaseCtlElemList();
468
469 return true;
470 }
471
GetCtlElemIface(struct AudioHwCtlElemIndex * id)472 static AudioCtlElemIfaceType GetCtlElemIface(struct AudioHwCtlElemIndex *id)
473 {
474 return id->eId.iface;
475 }
476
CtlElemGetIdx(struct AudioHwCtlElemIndex * id)477 static unsigned int CtlElemGetIdx(struct AudioHwCtlElemIndex *id)
478 {
479 return id->index;
480 }
481
CtlElemInfoCnt(struct AudioMixerCtlElemInfo * info)482 static unsigned int CtlElemInfoCnt(struct AudioMixerCtlElemInfo *info)
483 {
484 return info->count;
485 }
486
CtlElemGetInfoType(struct AudioMixerCtlElemInfo * info)487 static AudioCtlElemType CtlElemGetInfoType(struct AudioMixerCtlElemInfo *info)
488 {
489 return info->type;
490 }
491
CtlElemTypeName(AudioCtlElemType type)492 static const char *CtlElemTypeName(AudioCtlElemType type)
493 {
494 return ctlElemTypeNames[type];
495 }
496
MixerCtlType(struct AudioMixerCtlElemInfo * info)497 static const char *MixerCtlType(struct AudioMixerCtlElemInfo *info)
498 {
499 return CtlElemTypeName(CtlElemGetInfoType(info));
500 }
501
CtlElemInfoGetMin(struct AudioMixerCtlElemInfo * info)502 static int32_t CtlElemInfoGetMin(struct AudioMixerCtlElemInfo *info)
503 {
504 return info->value.intVal.min;
505 }
506
CtlElemInfoGetMax(struct AudioMixerCtlElemInfo * info)507 static int32_t CtlElemInfoGetMax(struct AudioMixerCtlElemInfo *info)
508 {
509 return info->value.intVal.max;
510 }
511
CtlElemInfoGetStep(struct AudioMixerCtlElemInfo * info)512 static int32_t CtlElemInfoGetStep(struct AudioMixerCtlElemInfo *info)
513 {
514 return info->value.intVal.step;
515 }
516
CtlElemInfoGetVals(struct AudioMixerCtlElemInfo * info)517 static long *CtlElemInfoGetVals(struct AudioMixerCtlElemInfo *info)
518 {
519 return info->value.intVal.vals;
520 }
521
CtlElemInfoSetItem(struct AudioMixerCtlElemInfo * info,uint32_t val)522 static void CtlElemInfoSetItem(struct AudioMixerCtlElemInfo *info, uint32_t val)
523 {
524 info->value.enumVal.item = val;
525 }
526
CtlElemInfoGetItems(struct AudioMixerCtlElemInfo * info)527 static uint32_t CtlElemInfoGetItems(struct AudioMixerCtlElemInfo *info)
528 {
529 return info->value.enumVal.items;
530 }
531
CtlElemInfoGetItem(struct AudioMixerCtlElemInfo * info)532 static uint32_t CtlElemInfoGetItem(struct AudioMixerCtlElemInfo *info)
533 {
534 return info->value.enumVal.item;
535 }
536
CtlElemInfoGetItemName(struct AudioMixerCtlElemInfo * info)537 static char *CtlElemInfoGetItemName(struct AudioMixerCtlElemInfo *info)
538 {
539 return info->value.enumVal.name;
540 }
541
CtlElemValueGetBoolean(struct AudioMixerCtlElemInfo * info,uint32_t idx)542 static int32_t CtlElemValueGetBoolean(struct AudioMixerCtlElemInfo *info, uint32_t idx)
543 {
544 if (idx > BIT_VALULE_OFFSET - 1) {
545 return 0;
546 }
547
548 return ((info->value.intVal.max >> idx) & 0x1);
549 }
550
CtlElemValueGetInt(struct AudioMixerCtlElemInfo * info,uint32_t idx)551 static int32_t CtlElemValueGetInt(struct AudioMixerCtlElemInfo *info, uint32_t idx)
552 {
553 return CtlElemValueGetBoolean(info, idx);
554 }
555
CtlElemValueGetByte(struct AudioMixerCtlElemInfo * info,uint32_t idx)556 static char CtlElemValueGetByte(struct AudioMixerCtlElemInfo *info, uint32_t idx)
557 {
558 if (idx >= RESERVED_BUF_LEN) {
559 return '?';
560 }
561
562 return info->value.reserved[idx];
563 }
564
CtlElemValueGetBytes(struct AudioMixerCtlElemInfo * info)565 static unsigned char *CtlElemValueGetBytes(struct AudioMixerCtlElemInfo *info)
566 {
567 return info->value.reserved;
568 }
569
CtlElemValueGetEnum(struct AudioMixerCtlElemInfo * info,uint32_t idx)570 static uint32_t CtlElemValueGetEnum(struct AudioMixerCtlElemInfo *info, uint32_t idx)
571 {
572 if (idx > BIT_VALULE_OFFSET) {
573 return 0;
574 }
575
576 return ((info->value.enumVal.item >> idx) & 0x1);
577 }
578
PrintOtherVal(struct AudioMixerCtlElemInfo * info)579 static void PrintOtherVal(struct AudioMixerCtlElemInfo *info)
580 {
581 uint32_t idx;
582 unsigned int count;
583 AudioCtlElemType type;
584
585 type = CtlElemGetInfoType(info);
586 count = CtlElemInfoCnt(info);
587 for (idx = 0; idx < count; idx++) {
588 if (idx > 0) {
589 printf(", ");
590 }
591
592 switch (type) {
593 case AUDIO_CTL_ELEM_TYPE_BOOLEAN:
594 printf("%s", CtlElemValueGetBoolean(info, idx) ? "on" : "off");
595 break;
596 case AUDIO_CTL_ELEM_TYPE_BYTES:
597 printf("0x%02x", CtlElemValueGetByte(info, idx));
598 break;
599 case AUDIO_CTL_ELEM_TYPE_INTEGER:
600 printf("%i", CtlElemValueGetInt(info, idx));
601 break;
602 case AUDIO_CTL_ELEM_TYPE_ENUMERATED:
603 printf("%u", CtlElemValueGetEnum(info, idx));
604 break;
605 default:
606 printf("?");
607 break;
608 }
609 }
610 printf("\n");
611 }
612
PrintValue(struct AudioMixerCtlElemInfo * info)613 static void PrintValue(struct AudioMixerCtlElemInfo *info)
614 {
615 long *ptr;
616 uint32_t idx, items;
617 AudioCtlElemType type;
618
619 type = CtlElemGetInfoType(info);
620 switch (type) {
621 case AUDIO_CTL_ELEM_TYPE_INTEGER:
622 printf(", min=%i, max=%i, step=%i\n",
623 CtlElemInfoGetMin(info),
624 CtlElemInfoGetMax(info),
625 CtlElemInfoGetStep(info));
626 ptr = CtlElemInfoGetVals(info);
627 printf(" : values=");
628 for (idx = 0; idx < info->count; idx++) {
629 if (idx > 0) {
630 printf(", ");
631 }
632 printf("%i", (int)ptr[idx]);
633 }
634 printf("\n");
635 break;
636 case AUDIO_CTL_ELEM_TYPE_ENUMERATED:
637 {
638 items = CtlElemInfoGetItems(info);
639 printf(", items=%u\n", items);
640 for (idx = 0; idx < items; idx++) {
641 CtlElemInfoSetItem(info, idx);
642 printf("%s; Item #%u '%s'\n", " ", idx, CtlElemInfoGetItemName(info));
643 }
644 printf(" : values=%u\n", CtlElemInfoGetItem(info));
645 }
646 break;
647 case AUDIO_CTL_ELEM_TYPE_BOOLEAN:
648 printf("\n : values=");
649 PrintOtherVal(info);
650 break;
651 case AUDIO_CTL_ELEM_TYPE_BYTES:
652 printf(" : values=%s\n", CtlElemValueGetBytes(info));
653 break;
654 default:
655 DEBUG_LOG("Mismatched control value type!\n");
656 break;
657 }
658 }
659
ShowIntVal(struct AudioMixerCtlElemInfo * info)660 static void ShowIntVal(struct AudioMixerCtlElemInfo *info)
661 {
662 int32_t ret;
663 uint32_t index;
664 unsigned int count;
665 const char *iface;
666 const char *space = " ";
667 char buf[BUF_SIZE_T + 1] = {0};
668
669 index = CtlElemGetIdx(&info->eIndexId);
670 iface = CtlElemIfaceName(GetCtlElemIface(&info->eIndexId));
671 if (index > 0) {
672 ret = snprintf_s(buf, BUF_SIZE_T, BUF_SIZE_T, "index=%u, iface=%s, name=%s",
673 index, iface, CtlElemName(&info->eIndexId));
674 } else {
675 ret = snprintf_s(buf, BUF_SIZE_T, BUF_SIZE_T, "iface=%s, name=%s",
676 iface, CtlElemName(&info->eIndexId));
677 }
678 if (ret < 0) {
679 DEBUG_LOG("Failed to snprintf_s!\n");
680 return;
681 }
682
683 buf[BUF_SIZE_T] = '\0';
684 printf("%s\n", buf);
685
686 count = CtlElemInfoCnt(info);
687 printf("%s; type=%s, values=%u", space, MixerCtlType(info), count);
688 PrintValue(info);
689 }
690
ShowEnumVal(struct AudioMixerCtlElemInfo * info)691 static void ShowEnumVal(struct AudioMixerCtlElemInfo *info)
692 {
693 printf(" : values=%u\n", CtlElemInfoGetItem(info));
694 }
695
ShowBytesVal(const unsigned char * data)696 static void ShowBytesVal(const unsigned char *data)
697 {
698 int i;
699 const unsigned char *p = data;
700
701 printf("\ndata:\t");
702 for (i = 0; i < RESERVED_BUF_LEN; i++) {
703 if (*p == '\0') {
704 break;
705 }
706
707 if ((i % OUTPUT_ALIGN) == 0) {
708 printf("\n");
709 }
710 printf("0x%02x \n", *p++);
711 }
712 printf("\n");
713 printf("string: %s\n", data);
714 }
715
ShowElemInfo(struct AudioMixerCtlElemInfo * info)716 static void ShowElemInfo(struct AudioMixerCtlElemInfo *info)
717 {
718 switch (info->type) {
719 case AUDIO_CTL_ELEM_TYPE_INTEGER:
720 case AUDIO_CTL_ELEM_TYPE_BOOLEAN:
721 ShowIntVal(info);
722 break;
723 case AUDIO_CTL_ELEM_TYPE_ENUMERATED:
724 ShowEnumVal(info);
725 break;
726 case AUDIO_CTL_ELEM_TYPE_BYTES:
727 ShowBytesVal(info->value.reserved);
728 break;
729 default:
730 DEBUG_LOG("Mismatched control value type!\n");
731 break;
732 }
733 }
734
MctlGetElem(const struct HdfIoService * service,struct MixerCardCtlInfo * ctlInfo)735 int32_t MctlGetElem(const struct HdfIoService *service, struct MixerCardCtlInfo *ctlInfo)
736 {
737 int32_t ret;
738 struct AudioMixerCtlElemInfo info;
739
740 if (service == NULL || ctlInfo == NULL) {
741 DEBUG_LOG("Invalid parameters!\n");
742 return U_INVALID_PARAM;
743 }
744
745 ret = strncpy_s(info.cardSrvName, AUDIO_CARD_SRV_NAME_LEN - 1, ctlInfo->cardSrvName, AUDIO_CARD_SRV_NAME_LEN - 1);
746 if (ret != 0) {
747 DEBUG_LOG("strncpy_s cardSrvName fail!\n");
748 return U_FAILURE;
749 }
750 info.cardSrvName[AUDIO_CARD_SRV_NAME_LEN - 1] = '\0';
751 ret = strncpy_s(info.eIndexId.eId.name, AUDIO_ELEM_NAME_LEN - 1, ctlInfo->edx.eId.name, AUDIO_ELEM_NAME_LEN - 1);
752 if (ret != 0) {
753 DEBUG_LOG("strncpy_s element name fail!\n");
754 return U_FAILURE;
755 }
756 info.eIndexId.eId.name[AUDIO_ELEM_NAME_LEN - 1] = '\0';
757 info.eIndexId.eId.iface = ctlInfo->edx.eId.iface;
758 // need info.type
759 info.type = AUDIO_CTL_ELEM_TYPE_INTEGER;
760
761 if (g_audioMixer.GetElemProp == NULL) {
762 DEBUG_LOG("The callback function is NULL!\n");
763 return U_FAILURE;
764 }
765 ret = g_audioMixer.GetElemProp(service, &info);
766 if (ret != U_SUCCESS) {
767 DEBUG_LOG("Failed to get control!\n");
768 return U_FAILURE;
769 }
770 ShowElemInfo(&info);
771
772 return U_SUCCESS;
773 }
774
775 static const struct ChannelMask g_chnMask[] = {
776 {"frontleft", 1 << AMIXER_CHN_FRONT_LEFT },
777 {"frontright", 1 << AMIXER_CHN_FRONT_RIGHT },
778 {"frontcenter", 1 << AMIXER_CHN_FRONT_CENTER },
779 {"front", ((1 << AMIXER_CHN_FRONT_LEFT) | (1 << AMIXER_CHN_FRONT_RIGHT))},
780 {"center", 1 << AMIXER_CHN_FRONT_CENTER },
781 {"rearleft", 1 << AMIXER_CHN_REAR_LEFT },
782 {"rearright", 1 << AMIXER_CHN_REAR_RIGHT },
783 {"rear", ((1 << AMIXER_CHN_REAR_LEFT) | (1 << AMIXER_CHN_REAR_RIGHT)) },
784 {"woofer", 1 << AMIXER_CHN_WOOFER },
785 {NULL, 0 }
786 };
787
ChannelsMask(char ** ptr,unsigned int chns)788 static uint32_t ChannelsMask(char **ptr, unsigned int chns)
789 {
790 const struct ChannelMask *msk;
791
792 for (msk = g_chnMask; msk->name != NULL; msk++) {
793 if (strncasecmp(*ptr, msk->name, strlen(msk->name)) == 0) {
794 /* Stop loop at specified character. */
795 while (**ptr != '\0' && **ptr != ',' && **ptr != ' ' && **ptr != '\t') {
796 (*ptr)++;
797 }
798 /* Skip the specified character. */
799 if (**ptr == ',' || **ptr == ' ' || **ptr == '\t') {
800 (*ptr)++;
801 }
802
803 return msk->mask;
804 }
805 }
806
807 return chns;
808 }
809
DirMask(char ** ptr,unsigned int dir)810 static uint32_t DirMask(char **ptr, unsigned int dir)
811 {
812 int find = 0;
813
814 /* Stop loop at specified character. */
815 while (**ptr != '\0' && **ptr != ',' && **ptr != ' ' && **ptr != '\t') {
816 (*ptr)++;
817 }
818
819 /* Skip the specified character. */
820 if (**ptr == ',' || **ptr == ' ' || **ptr == '\t') {
821 (*ptr)++;
822 }
823
824 if (strncasecmp(*ptr, "render", strlen("render")) == 0) {
825 dir = find = PCM_RENDER + 1;
826 } else if (strncasecmp(*ptr, "capture", strlen("capture")) == 0) {
827 dir = find = PCM_CAPTURE + 1;
828 }
829
830 if (find) {
831 /* Stop loop at specified character. */
832 while (**ptr != '\0' && **ptr != ',' && **ptr != ' ' && **ptr != '\t') {
833 (*ptr)++;
834 }
835
836 /* Skip the specified character. */
837 if (**ptr == ',' || **ptr == ' ' || **ptr == '\t') {
838 (*ptr)++;
839 }
840 }
841
842 return dir;
843 }
844
IsRenderChannel(AudioMixerChannelIdType chn)845 static bool IsRenderChannel(AudioMixerChannelIdType chn)
846 {
847 return !!(chn);
848 }
849
IsCaptureChannel(AudioMixerChannelIdType chn)850 static bool IsCaptureChannel(AudioMixerChannelIdType chn)
851 {
852 return !(chn);
853 }
854
FillChnmap(struct AudioMixerCtlElemInfo * info,uint32_t chns,uint32_t dir,char ** ptr)855 static int32_t FillChnmap(struct AudioMixerCtlElemInfo *info, uint32_t chns, uint32_t dir, char **ptr)
856 {
857 char *sp;
858 AudioMixerChannelIdType chn;
859
860 /* Matches the specified channel. */
861 for (chn = AMIXER_CHN_FRONT_LEFT; chn < AMIXER_CHN_LAST; chn++) {
862 sp = NULL;
863 if (!(chns & (1 << (uint32_t)chn))) {
864 continue;
865 }
866
867 if (!((dir & PCM_RENDER) && IsRenderChannel(chn)) && !((dir & PCM_CAPTURE) && IsCaptureChannel(chn))) {
868 DEBUG_LOG("Unable to set channel!\n");
869 return U_FAILURE;
870 }
871
872 info->value.enumVal.item |= (chns & (1 << chn));
873 /* Search for the next channel. */
874 while (**ptr != '\0' && **ptr != ',') {
875 (*ptr)++;
876 }
877 if (**ptr == '\0') {
878 break;
879 }
880 (*ptr)++; // skip ','
881 DEBUG_LOG("skip, = %s\n", *ptr);
882 }
883
884 if (info->value.enumVal.item > CHN_STEREO) {
885 info->value.enumVal.item = CHN_STEREO;
886 } else {
887 info->value.enumVal.item = CHN_MONO;
888 }
889 DEBUG_LOG("chns = %i\n", info->value.enumVal.item);
890
891 return U_SUCCESS;
892 }
893
FillChnlsIntVal(struct AudioMixerCtlElemInfo * info,unsigned int argc,char * argv)894 static int32_t FillChnlsIntVal(struct AudioMixerCtlElemInfo *info, unsigned int argc, char *argv)
895 {
896 bool mchns;
897 int32_t ret;
898 char *ptr = NULL;
899 uint32_t dir = 3;
900 uint32_t chns = ~0U;
901
902 ptr = argv;
903 chns = ChannelsMask(&ptr, chns);
904 if (*ptr == '\0') {
905 DEBUG_LOG("Channels Mask = %u\n", chns);
906 return U_FAILURE;
907 }
908
909 dir = DirMask(&ptr, dir);
910 if (*ptr == '\0') {
911 DEBUG_LOG("Direct Mask = %u\n", chns);
912 return U_FAILURE;
913 }
914
915 mchns = (strchr(ptr, ',') != NULL);
916 if (!mchns) {
917 info->value.enumVal.item = CHN_MONO;
918 return U_SUCCESS;
919 }
920
921 ret = FillChnmap(info, chns, dir, &ptr);
922 if (ret != U_SUCCESS) {
923 return ret;
924 }
925
926 return U_SUCCESS;
927 }
928
SetChannels(const struct HdfIoService * srv,const char * cardSrv,unsigned int argc,char * argv)929 int32_t SetChannels(const struct HdfIoService *srv, const char *cardSrv, unsigned int argc, char *argv)
930 {
931 int32_t ret;
932 struct AudioMixerCtlElemInfo infoData;
933
934 if (srv == NULL || cardSrv == NULL || argc == 0) {
935 DEBUG_LOG("Invalid parameters!\n");
936 return U_INVALID_PARAM;
937 }
938
939 DEBUG_LOG("argc = %u, argv = %s\n", argc, argv);
940 (void)memset_s(infoData.cardSrvName, AUDIO_CARD_SRV_NAME_LEN, 0, AUDIO_CARD_SRV_NAME_LEN);
941 ret = strncpy_s(infoData.cardSrvName, AUDIO_CARD_SRV_NAME_LEN, cardSrv, strlen(cardSrv) + 1);
942 if (ret != 0) {
943 DEBUG_LOG("strncpy_s card service name is faild!\n");
944 return U_FAILURE;
945 }
946 infoData.cardSrvName[AUDIO_CARD_SRV_NAME_LEN - 1] = '\0';
947
948 (void)memset_s(infoData.eIndexId.eId.name, AUDIO_ELEM_NAME_LEN, 0, AUDIO_ELEM_NAME_LEN);
949 ret = strncpy_s(
950 infoData.eIndexId.eId.name, AUDIO_ELEM_NAME_LEN, "Captrue Channel Mode", strlen("Captrue Channel Mode") + 1);
951 if (ret != 0) {
952 DEBUG_LOG("strncpy_s element name is failed!\n");
953 return U_FAILURE;
954 }
955 infoData.eIndexId.eId.iface = AUDIO_CTL_ELEM_IFACE_MIXER;
956 infoData.type = AUDIO_CTL_ELEM_TYPE_INTEGER;
957 ret = FillChnlsIntVal(&infoData, argc, argv);
958 if (ret != U_SUCCESS) {
959 return ret;
960 }
961
962 if (g_audioMixer.SetElemProp == NULL) {
963 DEBUG_LOG("The callback function is NULL!\n");
964 return U_FAILURE;
965 }
966 ret = g_audioMixer.SetElemProp(srv, &infoData);
967 if (ret != U_SUCCESS) {
968 return ret;
969 }
970
971 ret = strncpy_s(
972 infoData.eIndexId.eId.name, AUDIO_ELEM_NAME_LEN, "Render Channel Mode", strlen("Render Channel Mode") + 1);
973 if (ret != 0) {
974 DEBUG_LOG("strncpy_s element name is failed!\n");
975 return U_FAILURE;
976 }
977
978 return g_audioMixer.SetElemProp(srv, &infoData);
979 }
980
FillIntVal(struct AudioMixerCtlElemInfo * info,unsigned int argc,char * argv[])981 static int32_t FillIntVal(struct AudioMixerCtlElemInfo *info, unsigned int argc, char *argv[])
982 {
983 char *vals, *minPtr, *maxPtr, *stepPtr;
984 char *ptr = NULL;
985 char *outPtr = NULL;
986
987 if (argc != 2) { // 2 for numbers of argc
988 DEBUG_LOG("Unable to set too much value!\n");
989 return U_FAILURE;
990 }
991
992 ptr = argv[argc - 1];
993 DEBUG_LOG("argv[%u] = %s\n", argc - 1, ptr);
994 vals = strtok_r(ptr, ",", &outPtr);
995 if (outPtr == NULL) {
996 info->value.intVal.vals[0] = strtol(ptr, NULL, STRTOL_BASE);
997 info->value.intVal.min = 0;
998 info->value.intVal.step = 0;
999
1000 return U_SUCCESS;
1001 }
1002
1003 info->value.intVal.vals[0] = strtol(vals, NULL, STRTOL_BASE);
1004 maxPtr = strtok_r(NULL, ",", &outPtr);
1005 if (outPtr == NULL) {
1006 info->value.intVal.max = (int32_t)strtol(maxPtr, NULL, STRTOL_BASE);
1007 info->value.intVal.min = 0;
1008 info->value.intVal.step = 0;
1009
1010 return U_SUCCESS;
1011 }
1012
1013 info->value.intVal.max = (int32_t)strtol(maxPtr, NULL, STRTOL_BASE);
1014 minPtr = strtok_r(NULL, ",", &outPtr);
1015 if (outPtr != NULL) {
1016 info->value.intVal.min = (int32_t)strtol(minPtr, NULL, STRTOL_BASE);
1017 stepPtr = strtok_r(NULL, ",", &outPtr);
1018 info->value.intVal.step = outPtr != NULL ? (int32_t)strtol(stepPtr, NULL, STRTOL_BASE) : 0;
1019 } else {
1020 info->value.intVal.min = (int32_t)strtol(minPtr, NULL, STRTOL_BASE);
1021 info->value.intVal.step = 0;
1022 }
1023
1024 return U_SUCCESS;
1025 }
1026
FillEnumVal(struct AudioMixerCtlElemInfo * info,unsigned int argc,char * argv[])1027 static int32_t FillEnumVal(struct AudioMixerCtlElemInfo *info, unsigned int argc, char *argv[])
1028 {
1029 int32_t ret;
1030 unsigned int idx;
1031 char *ptr = NULL;
1032
1033 printf("\n");
1034 /* Multiple enumerated values are output line by line. */
1035 for (idx = 1; idx < argc; idx++) {
1036 ptr = argv[idx];
1037 // Control Settings with enumerated values.
1038 ret = strcpy_s(info->value.enumVal.name, AUDIO_ELEM_NAME_LEN - 1, ptr);
1039 if (ret != EOK) {
1040 printf("strcpy_s failed: argv = %s\n", ptr);
1041 } else {
1042 printf("%s\n", ptr);
1043 }
1044 }
1045
1046 return U_SUCCESS;
1047 }
1048
FillBytesVal(unsigned char * buf,unsigned int argc,char * argv[])1049 static int32_t FillBytesVal(unsigned char *buf, unsigned int argc, char *argv[])
1050 {
1051 int32_t ret;
1052 size_t len;
1053 unsigned int idx;
1054 unsigned char *ptr = buf;
1055 char *sptr = NULL;
1056 size_t size = RESERVED_BUF_LEN;
1057
1058 /* Multiple input parameters are separated and combined with a ",". */
1059 for (idx = 1; idx < argc; idx++) {
1060 sptr = argv[idx];
1061 len = strlen(argv[idx]);
1062 if (size <= len) {
1063 DEBUG_LOG("The callback function is NULL!\n");
1064 break;
1065 }
1066 ret = strncpy_s((char *)ptr, RESERVED_BUF_LEN - 1, sptr, len);
1067 if (ret != 0) {
1068 DEBUG_LOG("strncpy_s faild!\n");
1069 return U_FAILURE;
1070 }
1071 ptr += len;
1072 *ptr++ = ',';
1073 size -= len + 1;
1074 }
1075 if (idx < argc) {
1076 DEBUG_LOG("Unable to set too much data!\n");
1077 return U_FAILURE;
1078 }
1079 printf("data buf = %s\n", buf);
1080
1081 return U_SUCCESS;
1082 }
1083
1084
MctlSetElem(const struct HdfIoService * srv,struct MixerCardCtlInfo * ctlInfo,unsigned int argc,char * argv[])1085 int32_t MctlSetElem(const struct HdfIoService *srv,
1086 struct MixerCardCtlInfo *ctlInfo,
1087 unsigned int argc, char *argv[])
1088 {
1089 int32_t ret;
1090 struct AudioMixerCtlElemInfo infoData;
1091
1092 if (srv == NULL || ctlInfo == NULL || argc == 0) {
1093 DEBUG_LOG("Invalid parameters!\n");
1094 return U_INVALID_PARAM;
1095 }
1096
1097 ret = strncpy_s(infoData.cardSrvName, AUDIO_CARD_SRV_NAME_LEN, ctlInfo->cardSrvName, AUDIO_CARD_SRV_NAME_LEN);
1098 if (ret != 0) {
1099 DEBUG_LOG("strncpy_s card service name is faild!\n");
1100 return U_FAILURE;
1101 }
1102 infoData.cardSrvName[AUDIO_CARD_SRV_NAME_LEN - 1] = '\0';
1103
1104 ret = strncpy_s(infoData.eIndexId.eId.name, AUDIO_ELEM_NAME_LEN, ctlInfo->edx.eId.name, AUDIO_ELEM_NAME_LEN);
1105 if (ret != 0) {
1106 DEBUG_LOG("strncpy_s element name is failed!\n");
1107 return U_FAILURE;
1108 }
1109 infoData.eIndexId.eId.name[AUDIO_ELEM_NAME_LEN - 1] = '\0';
1110 infoData.eIndexId.eId.iface = AUDIO_CTL_ELEM_IFACE_MIXER;
1111
1112 // First, read the value type.(infoData.type)
1113 infoData.type = AUDIO_CTL_ELEM_TYPE_INTEGER;
1114 switch (infoData.type) {
1115 case AUDIO_CTL_ELEM_TYPE_INTEGER:
1116 case AUDIO_CTL_ELEM_TYPE_BOOLEAN:
1117 ret = FillIntVal(&infoData, argc, argv);
1118 break;
1119 case AUDIO_CTL_ELEM_TYPE_ENUMERATED:
1120 ret = FillEnumVal(&infoData, argc, argv);
1121 break;
1122 case AUDIO_CTL_ELEM_TYPE_BYTES:
1123 ret = FillBytesVal(infoData.value.reserved, argc, argv);
1124 break;
1125 default:
1126 ret = U_FAILURE;
1127 break;
1128 }
1129 if (ret != U_SUCCESS) {
1130 DEBUG_LOG("The value type does not match!\n");
1131 return U_FAILURE;
1132 }
1133
1134 if (g_audioMixer.SetElemProp == NULL) {
1135 DEBUG_LOG("The callback function is NULL!\n");
1136 return U_FAILURE;
1137 }
1138
1139 return g_audioMixer.SetElemProp(srv, &infoData);
1140 }
1141
SkipSpecifyStr(const char * src,const char * needle)1142 static char *SkipSpecifyStr(const char *src, const char *needle)
1143 {
1144 char *p = NULL;
1145
1146 p = strstr(src, needle);
1147 if (p != NULL) {
1148 p += strlen(needle);
1149 }
1150
1151 return p;
1152 }
1153
GetSndCardType(const char * name,char * buf,uint32_t len)1154 static int32_t GetSndCardType(const char *name, char *buf, uint32_t len)
1155 {
1156 int32_t ret;
1157 char *ptr = NULL;
1158 char *out = NULL;
1159
1160 if (name == NULL || buf == NULL || len == 0) {
1161 DEBUG_LOG("Invalid parameters!\n");
1162 return U_INVALID_PARAM;
1163 }
1164
1165 ptr = SkipSpecifyStr(name, MIXER_SRV_NAME_PRE);
1166 if (ptr == NULL) {
1167 DEBUG_LOG("No found card type!\n");
1168 return U_FAILURE;
1169 }
1170
1171 ret = memcpy_s(buf, len, ptr, strlen(ptr) + 1);
1172 if (ret != EOK) {
1173 DEBUG_LOG("memcpy_s fail!\n");
1174 return U_FAILURE;
1175 }
1176 ptr = strtok_r(buf, "_", &out);
1177 ret = memcpy_s(buf, len, ptr, strlen(ptr) + 1);
1178 if (ret != EOK) {
1179 DEBUG_LOG("memcpy_s fail!\n");
1180 return U_FAILURE;
1181 }
1182
1183 return U_SUCCESS;
1184 }
1185
ShowAllAdapters(struct SndCardsList * sndList)1186 static void ShowAllAdapters(struct SndCardsList *sndList)
1187 {
1188 int32_t i, ret;
1189 uint32_t cnums;
1190 char ctype[AUDIO_BASE_LEN] = {0};
1191 struct AudioCardId *clist = NULL;
1192
1193 if (sndList->cardNums == 0 || sndList->cardsList == NULL) {
1194 DEBUG_LOG("No sound cards found...!\n");
1195 goto end;
1196 }
1197
1198 cnums = sndList->cardNums;
1199 clist = sndList->cardsList;
1200 printf("****** List of Audio Hardware Devices ******\n");
1201 /* To keep the primary sound card always in front of the total,
1202 * output it in the following order.
1203 */
1204 for (i = (int32_t)cnums - 1; i >= 0; i--) {
1205 (void)memset_s(ctype, AUDIO_BASE_LEN, 0, AUDIO_BASE_LEN);
1206 ret = GetSndCardType(clist[i].cardName, ctype, AUDIO_BASE_LEN);
1207 if (ret != U_SUCCESS) {
1208 goto end;
1209 }
1210 printf("card %i: %s [%s], device 0\n", clist[i].index, ctype, clist[i].cardName);
1211 printf(" Subdevices: 1/1\n");
1212 printf(" Subdevice #0: subdevice #0\n");
1213 }
1214
1215 end:
1216 if (sndList->cardsList != NULL) {
1217 free(sndList->cardsList);
1218 sndList->cardsList = NULL;
1219 }
1220 }
1221
GetAllCards(const struct HdfIoService * service)1222 int32_t GetAllCards(const struct HdfIoService *service)
1223 {
1224 int32_t ret;
1225 struct SndCardsList sndcards;
1226 int32_t (*GetAllAdapters)(const struct HdfIoService *, struct SndCardsList *);
1227
1228 if (service == NULL) {
1229 DEBUG_LOG("Invalid parameter!\n");
1230 return U_INVALID_PARAM;
1231 }
1232
1233 GetAllAdapters = CallLibFunction("AudioMixerGetAllAdapters");
1234 if (GetAllAdapters == NULL) {
1235 return U_FAILURE;
1236 }
1237
1238 (void)memset_s(&sndcards, sizeof(struct SndCardsList), 0, sizeof(struct SndCardsList));
1239 ret = GetAllAdapters(service, &sndcards);
1240 if (ret != U_SUCCESS) {
1241 DEBUG_LOG("Description Failed to obtain the sound card list!\n");
1242 return U_FAILURE;
1243 }
1244 ShowAllAdapters(&sndcards);
1245
1246 return U_SUCCESS;
1247 }
1248
FindSpecificCardName(int card,struct SndCardsList * cardList)1249 static char *FindSpecificCardName(int card, struct SndCardsList *cardList)
1250 {
1251 int32_t i;
1252 uint32_t cnums;
1253 struct AudioCardId *clist = NULL;
1254
1255 if (cardList->cardNums == 0 || cardList->cardsList == NULL) {
1256 DEBUG_LOG("No sound cards found...!\n");
1257 goto end;
1258 }
1259
1260 cnums = cardList->cardNums;
1261 clist = cardList->cardsList;
1262 for (i = 0; i < (int32_t)cnums; i++) {
1263 if (card == clist[i].index) {
1264 DEBUG_LOG("I found this sound card. [card%i: %s]\n", card, clist[i].cardName);
1265 return clist[i].cardName;
1266 }
1267 }
1268
1269 end:
1270 if (cardList->cardsList != NULL) {
1271 free(cardList->cardsList);
1272 cardList->cardsList = NULL;
1273 }
1274 cardList->cardNums = 0;
1275
1276 return NULL;
1277 }
1278
UpdateCardSname(int card,const struct HdfIoService * srv,char * const sname,size_t snameLen)1279 void UpdateCardSname(int card, const struct HdfIoService *srv, char * const sname, size_t snameLen)
1280 {
1281 int32_t ret;
1282 struct SndCardsList cardList;
1283 int32_t (*GetAllCardsFunc)(const struct HdfIoService *, struct SndCardsList *);
1284 char *cname = NULL;
1285
1286 if (card < 0 || srv == NULL || sname == NULL || snameLen == 0) {
1287 DEBUG_LOG("Invalid parameter!\n");
1288 return;
1289 }
1290
1291 GetAllCardsFunc = CallLibFunction("AudioMixerGetAllAdapters");
1292 if (GetAllCardsFunc == NULL) {
1293 DEBUG_LOG("Description Failed to obtain the current sound card list of the system!\n");
1294 return;
1295 }
1296
1297 (void)memset_s(&cardList, sizeof(struct SndCardsList), 0, sizeof(struct SndCardsList));
1298 ret = GetAllCardsFunc(srv, &cardList);
1299 if (ret != U_SUCCESS) {
1300 DEBUG_LOG("Update failed: Description Failed to obtain the sound card list!\n");
1301 return;
1302 }
1303
1304 cname = FindSpecificCardName(card, &cardList);
1305 if (cname == NULL) {
1306 DEBUG_LOG("Update failed: The corresponding sound card cannot be matched!\n");
1307 return;
1308 }
1309
1310 ret = memcpy_s(sname, snameLen, cname, strlen(cname) + 1);
1311 if (ret != EOK) {
1312 DEBUG_LOG("Update failed: memcpy_s fail!\n");
1313 }
1314 sname[snameLen - 1] = '\0';
1315 if (g_debugFlag) {
1316 printf("|--> [%s]\n", sname);
1317 }
1318
1319 if (cardList.cardsList != NULL) {
1320 free(cardList.cardsList);
1321 cardList.cardsList = NULL;
1322 }
1323 cardList.cardNums = 0;
1324 }
1325