1094332d3Sopenharmony_ci/*
2094332d3Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3094332d3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4094332d3Sopenharmony_ci * you may not use this file except in compliance with the License.
5094332d3Sopenharmony_ci * You may obtain a copy of the License at
6094332d3Sopenharmony_ci *
7094332d3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8094332d3Sopenharmony_ci *
9094332d3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10094332d3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11094332d3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12094332d3Sopenharmony_ci * See the License for the specific language governing permissions and
13094332d3Sopenharmony_ci * limitations under the License.
14094332d3Sopenharmony_ci */
15094332d3Sopenharmony_ci
16094332d3Sopenharmony_ci#include "audio_mixer.h"
17094332d3Sopenharmony_ci
18094332d3Sopenharmony_ci#include <assert.h>
19094332d3Sopenharmony_ci#include <ctype.h>
20094332d3Sopenharmony_ci#include <dlfcn.h>
21094332d3Sopenharmony_ci#include <errno.h>
22094332d3Sopenharmony_ci#include <limits.h>
23094332d3Sopenharmony_ci#include <string.h>
24094332d3Sopenharmony_ci#include <strings.h>
25094332d3Sopenharmony_ci#include <stdio.h>
26094332d3Sopenharmony_ci#include <stdlib.h>
27094332d3Sopenharmony_ci#include <unistd.h>
28094332d3Sopenharmony_ci
29094332d3Sopenharmony_ci#include "hdf_base.h"
30094332d3Sopenharmony_ci#include "securec.h"
31094332d3Sopenharmony_ci
32094332d3Sopenharmony_ci#define AUDIO_UTIL_VERSION_STR "V1.0.0"
33094332d3Sopenharmony_ci
34094332d3Sopenharmony_ci#define AUDIO_DEV_FILE_PATH    "/dev/"
35094332d3Sopenharmony_ci#define CTL_SRV_NAME_PRE       "hdf_audio_control"
36094332d3Sopenharmony_ci#define CTL_SRV_DEFAULT        CTL_SRV_NAME_PRE
37094332d3Sopenharmony_ci#define MIXER_SRV_NAME_PRE     "hdf_audio_codec_"
38094332d3Sopenharmony_ci#define MIXER_SRV_NAME         MIXER_SRV_NAME_PRE "%s_dev%i"
39094332d3Sopenharmony_ci#define MIXER_SRV_NAME_DEFAULT MIXER_SRV_NAME_PRE "primary_dev0"
40094332d3Sopenharmony_ci#define SERVICE_NAME_LEN       64
41094332d3Sopenharmony_ci#define BUF_SIZE_T             256
42094332d3Sopenharmony_ci#define CHN_MONO               (1 << 0)
43094332d3Sopenharmony_ci#define CHN_STEREO             (1 << 1)
44094332d3Sopenharmony_ci#define OUTPUT_ALIGN           16
45094332d3Sopenharmony_ci#define BIT_VALULE_OFFSET      31
46094332d3Sopenharmony_ci#define STRTOL_BASE            10
47094332d3Sopenharmony_ci
48094332d3Sopenharmony_ci#define IFACE(v) [AUDIO_CTL_ELEM_IFACE_##v] = #v
49094332d3Sopenharmony_ci#define TYPE(v)  [AUDIO_CTL_ELEM_TYPE_##v] = #v
50094332d3Sopenharmony_ci
51094332d3Sopenharmony_cistatic struct AudioMixer g_audioMixer;
52094332d3Sopenharmony_cistatic struct AudioMixerContents g_mixerCts;
53094332d3Sopenharmony_ci
54094332d3Sopenharmony_cistatic const char *g_capLibPath = HDF_LIBRARY_FULL_PATH("libaudio_capture_adapter");
55094332d3Sopenharmony_cistatic const char *g_renLibPath = HDF_LIBRARY_FULL_PATH("libaudio_render_adapter");
56094332d3Sopenharmony_cistatic void *g_soHandle = NULL;
57094332d3Sopenharmony_cistatic AudioPcmType g_pcmT = PCM_RENDER;
58094332d3Sopenharmony_cistatic bool g_debugFlag = false;
59094332d3Sopenharmony_ci
60094332d3Sopenharmony_cistatic const char * const ctlEIfNames[] = {
61094332d3Sopenharmony_ci    IFACE(CARD),
62094332d3Sopenharmony_ci    IFACE(PCM),
63094332d3Sopenharmony_ci    IFACE(MIXER),
64094332d3Sopenharmony_ci};
65094332d3Sopenharmony_ci
66094332d3Sopenharmony_cistatic const char * const ctlElemTypeNames[] = {
67094332d3Sopenharmony_ci    TYPE(NONE),
68094332d3Sopenharmony_ci    TYPE(BOOLEAN),
69094332d3Sopenharmony_ci    TYPE(INTEGER),
70094332d3Sopenharmony_ci    TYPE(ENUMERATED),
71094332d3Sopenharmony_ci    TYPE(BYTES),
72094332d3Sopenharmony_ci};
73094332d3Sopenharmony_ci
74094332d3Sopenharmony_civoid DebugLog(bool flag)
75094332d3Sopenharmony_ci{
76094332d3Sopenharmony_ci    g_debugFlag = flag;
77094332d3Sopenharmony_ci}
78094332d3Sopenharmony_ci
79094332d3Sopenharmony_cistatic void *CallLibFunction(const char *funcName)
80094332d3Sopenharmony_ci{
81094332d3Sopenharmony_ci    void *func = NULL;
82094332d3Sopenharmony_ci    char *error = NULL;
83094332d3Sopenharmony_ci
84094332d3Sopenharmony_ci    if (g_soHandle == NULL) {
85094332d3Sopenharmony_ci        DEBUG_LOG("Invalid dynamic library handle!\n");
86094332d3Sopenharmony_ci        return NULL;
87094332d3Sopenharmony_ci    }
88094332d3Sopenharmony_ci
89094332d3Sopenharmony_ci    (void)dlerror(); /* Clear any existing error */
90094332d3Sopenharmony_ci    func = dlsym(g_soHandle, funcName);
91094332d3Sopenharmony_ci    error = dlerror();
92094332d3Sopenharmony_ci    if (error != NULL) {
93094332d3Sopenharmony_ci        DEBUG_LOG("%s\n", error);
94094332d3Sopenharmony_ci        printf("%s\n", error);
95094332d3Sopenharmony_ci        return NULL;
96094332d3Sopenharmony_ci    }
97094332d3Sopenharmony_ci
98094332d3Sopenharmony_ci    return func;
99094332d3Sopenharmony_ci}
100094332d3Sopenharmony_ci
101094332d3Sopenharmony_cistatic int32_t AudioMixerList(const struct HdfIoService *service, struct AudioMixerContents *mixerCts)
102094332d3Sopenharmony_ci{
103094332d3Sopenharmony_ci    int32_t (*AmixerCtlElemList)(AudioPcmType, const struct HdfIoService *, struct AudioMixerContents *);
104094332d3Sopenharmony_ci
105094332d3Sopenharmony_ci    AmixerCtlElemList = CallLibFunction("AudioMixerCtlElem");
106094332d3Sopenharmony_ci    if (AmixerCtlElemList == NULL) {
107094332d3Sopenharmony_ci        return U_FAILURE;
108094332d3Sopenharmony_ci    }
109094332d3Sopenharmony_ci
110094332d3Sopenharmony_ci    return AmixerCtlElemList(g_pcmT, service, mixerCts);
111094332d3Sopenharmony_ci}
112094332d3Sopenharmony_ci
113094332d3Sopenharmony_cistatic int32_t AudioMixerGet(const struct HdfIoService *service, struct AudioMixerCtlElemInfo *infoData)
114094332d3Sopenharmony_ci{
115094332d3Sopenharmony_ci    int32_t (*AmixerGetCtlElem)(AudioPcmType, const struct HdfIoService *, struct AudioMixerCtlElemInfo *);
116094332d3Sopenharmony_ci
117094332d3Sopenharmony_ci    AmixerGetCtlElem = CallLibFunction("AudioMixerCtlGetElem");
118094332d3Sopenharmony_ci    if (AmixerGetCtlElem == NULL) {
119094332d3Sopenharmony_ci        return U_FAILURE;
120094332d3Sopenharmony_ci    }
121094332d3Sopenharmony_ci
122094332d3Sopenharmony_ci    return AmixerGetCtlElem(g_pcmT, service, infoData);
123094332d3Sopenharmony_ci}
124094332d3Sopenharmony_ci
125094332d3Sopenharmony_cistatic int32_t AudioMixerSet(const struct HdfIoService *service, struct AudioMixerCtlElemInfo *infoData)
126094332d3Sopenharmony_ci{
127094332d3Sopenharmony_ci    int32_t (*AmixerSetCtlElem)(AudioPcmType, const struct HdfIoService *, struct AudioMixerCtlElemInfo *);
128094332d3Sopenharmony_ci
129094332d3Sopenharmony_ci    AmixerSetCtlElem = CallLibFunction("AudioMixerCtlSetElem");
130094332d3Sopenharmony_ci    if (AmixerSetCtlElem == NULL) {
131094332d3Sopenharmony_ci        return U_FAILURE;
132094332d3Sopenharmony_ci    }
133094332d3Sopenharmony_ci
134094332d3Sopenharmony_ci    return AmixerSetCtlElem(g_pcmT, service, infoData);
135094332d3Sopenharmony_ci}
136094332d3Sopenharmony_ci
137094332d3Sopenharmony_cistatic int32_t GetSoHandle(const char *filename)
138094332d3Sopenharmony_ci{
139094332d3Sopenharmony_ci    char buf[PATH_MAX] = {0};
140094332d3Sopenharmony_ci
141094332d3Sopenharmony_ci    if (realpath(filename, buf) == NULL) {
142094332d3Sopenharmony_ci        return U_FAILURE;
143094332d3Sopenharmony_ci    }
144094332d3Sopenharmony_ci
145094332d3Sopenharmony_ci    if (g_soHandle != NULL) {
146094332d3Sopenharmony_ci        DEBUG_LOG("It's been initialized!\n");
147094332d3Sopenharmony_ci        return U_SUCCESS;
148094332d3Sopenharmony_ci    }
149094332d3Sopenharmony_ci
150094332d3Sopenharmony_ci    g_soHandle = dlopen(buf, RTLD_LAZY);
151094332d3Sopenharmony_ci    if (g_soHandle == NULL) {
152094332d3Sopenharmony_ci        DEBUG_LOG("%s\n", dlerror());
153094332d3Sopenharmony_ci        printf("%s\n", dlerror());
154094332d3Sopenharmony_ci        return U_FAILURE;
155094332d3Sopenharmony_ci    }
156094332d3Sopenharmony_ci
157094332d3Sopenharmony_ci    return U_SUCCESS;
158094332d3Sopenharmony_ci}
159094332d3Sopenharmony_ci
160094332d3Sopenharmony_ciint32_t GetLibsoHandle(AudioPcmType pcm)
161094332d3Sopenharmony_ci{
162094332d3Sopenharmony_ci    int32_t ret;
163094332d3Sopenharmony_ci
164094332d3Sopenharmony_ci    g_pcmT = pcm;
165094332d3Sopenharmony_ci    switch (pcm) {
166094332d3Sopenharmony_ci        default:
167094332d3Sopenharmony_ci            DEBUG_LOG("Wrong PCM type!\n");
168094332d3Sopenharmony_ci            /* fall through */
169094332d3Sopenharmony_ci            __attribute__((fallthrough));
170094332d3Sopenharmony_ci        case PCM_RENDER:
171094332d3Sopenharmony_ci            ret = GetSoHandle(g_renLibPath);
172094332d3Sopenharmony_ci            if (ret != U_SUCCESS) {
173094332d3Sopenharmony_ci                DEBUG_LOG("Failed to open the render dynamic library!\n");
174094332d3Sopenharmony_ci            }
175094332d3Sopenharmony_ci            break;
176094332d3Sopenharmony_ci        case PCM_CAPTURE:
177094332d3Sopenharmony_ci            ret = GetSoHandle(g_capLibPath);
178094332d3Sopenharmony_ci            if (ret != U_SUCCESS) {
179094332d3Sopenharmony_ci                DEBUG_LOG("Failed to open the capture dynamic library!\n");
180094332d3Sopenharmony_ci            }
181094332d3Sopenharmony_ci            break;
182094332d3Sopenharmony_ci    }
183094332d3Sopenharmony_ci
184094332d3Sopenharmony_ci    return ret;
185094332d3Sopenharmony_ci}
186094332d3Sopenharmony_ci
187094332d3Sopenharmony_civoid CloseLibsoHandle(void)
188094332d3Sopenharmony_ci{
189094332d3Sopenharmony_ci    if (g_soHandle != NULL) {
190094332d3Sopenharmony_ci        (void)dlclose(g_soHandle);
191094332d3Sopenharmony_ci        g_soHandle = NULL;
192094332d3Sopenharmony_ci    }
193094332d3Sopenharmony_ci}
194094332d3Sopenharmony_ci
195094332d3Sopenharmony_civoid AudioMixerOpsInit(void)
196094332d3Sopenharmony_ci{
197094332d3Sopenharmony_ci    g_audioMixer.GetElemList = AudioMixerList;
198094332d3Sopenharmony_ci    g_audioMixer.GetElemProp = AudioMixerGet;
199094332d3Sopenharmony_ci    g_audioMixer.SetElemProp = AudioMixerSet;
200094332d3Sopenharmony_ci
201094332d3Sopenharmony_ci    g_mixerCts.data = NULL;
202094332d3Sopenharmony_ci    g_mixerCts.elemNum = 0;
203094332d3Sopenharmony_ci    (void)memset_s(g_mixerCts.cardServiceName, AUDIO_CARD_SRV_NAME_LEN, 0x0, AUDIO_CARD_SRV_NAME_LEN);
204094332d3Sopenharmony_ci}
205094332d3Sopenharmony_ci
206094332d3Sopenharmony_ciconst char *ShowVersion(void)
207094332d3Sopenharmony_ci{
208094332d3Sopenharmony_ci    return AUDIO_UTIL_VERSION_STR;
209094332d3Sopenharmony_ci}
210094332d3Sopenharmony_ci
211094332d3Sopenharmony_cistatic bool CheckMixerDevFile(const char *file)
212094332d3Sopenharmony_ci{
213094332d3Sopenharmony_ci    char buf[PATH_MAX] = {0};
214094332d3Sopenharmony_ci
215094332d3Sopenharmony_ci    if (realpath(file, buf) == NULL) {
216094332d3Sopenharmony_ci        DEBUG_LOG("%s\n", strerror(errno));
217094332d3Sopenharmony_ci        return false;
218094332d3Sopenharmony_ci    }
219094332d3Sopenharmony_ci
220094332d3Sopenharmony_ci    if (access(file, F_OK)) {
221094332d3Sopenharmony_ci        DEBUG_LOG("%s\n", strerror(errno));
222094332d3Sopenharmony_ci        return false;
223094332d3Sopenharmony_ci    }
224094332d3Sopenharmony_ci
225094332d3Sopenharmony_ci    return true;
226094332d3Sopenharmony_ci}
227094332d3Sopenharmony_ci
228094332d3Sopenharmony_cistruct HdfIoService *MixerBindCrlSrvDefault(void)
229094332d3Sopenharmony_ci{
230094332d3Sopenharmony_ci    int ret;
231094332d3Sopenharmony_ci    char buf[BUF_SIZE_T + 1] = {0};
232094332d3Sopenharmony_ci    struct HdfIoService *(*SrvBindDef)(const char *);
233094332d3Sopenharmony_ci
234094332d3Sopenharmony_ci    ret = snprintf_s(buf, BUF_SIZE_T, BUF_SIZE_T, "%s%s", AUDIO_DEV_FILE_PATH, MIXER_SRV_NAME_DEFAULT);
235094332d3Sopenharmony_ci    if (ret < 0) {
236094332d3Sopenharmony_ci        DEBUG_LOG("Failed to synthesize the service path!\n");
237094332d3Sopenharmony_ci        return NULL;
238094332d3Sopenharmony_ci    }
239094332d3Sopenharmony_ci
240094332d3Sopenharmony_ci    if (!CheckMixerDevFile(buf)) {
241094332d3Sopenharmony_ci        /* The sound card service file does not exist */
242094332d3Sopenharmony_ci        return NULL;
243094332d3Sopenharmony_ci    }
244094332d3Sopenharmony_ci
245094332d3Sopenharmony_ci    SrvBindDef = CallLibFunction("HdfIoServiceBindName");
246094332d3Sopenharmony_ci    if (SrvBindDef == NULL) {
247094332d3Sopenharmony_ci        return NULL;
248094332d3Sopenharmony_ci    }
249094332d3Sopenharmony_ci
250094332d3Sopenharmony_ci    return SrvBindDef(CTL_SRV_DEFAULT);
251094332d3Sopenharmony_ci}
252094332d3Sopenharmony_ci
253094332d3Sopenharmony_cistruct HdfIoService *MixerBindCrlSrv(const char *serviceName)
254094332d3Sopenharmony_ci{
255094332d3Sopenharmony_ci    int ret;
256094332d3Sopenharmony_ci    char path[BUF_SIZE_T + 1] = {0};
257094332d3Sopenharmony_ci    struct HdfIoService *(*SrvBind)(const char *);
258094332d3Sopenharmony_ci
259094332d3Sopenharmony_ci    if (serviceName == NULL) {
260094332d3Sopenharmony_ci        DEBUG_LOG("Invalid parameters!\n");
261094332d3Sopenharmony_ci        return NULL;
262094332d3Sopenharmony_ci    }
263094332d3Sopenharmony_ci
264094332d3Sopenharmony_ci    if (strncmp(serviceName, MIXER_SRV_NAME_PRE, strlen(MIXER_SRV_NAME_PRE))) {
265094332d3Sopenharmony_ci        DEBUG_LOG("The service name does not match!\n");
266094332d3Sopenharmony_ci        return NULL;
267094332d3Sopenharmony_ci    }
268094332d3Sopenharmony_ci
269094332d3Sopenharmony_ci    ret = snprintf_s(path, BUF_SIZE_T, BUF_SIZE_T, "%s%s", AUDIO_DEV_FILE_PATH, serviceName);
270094332d3Sopenharmony_ci    if (ret < 0) {
271094332d3Sopenharmony_ci        DEBUG_LOG("Failed to synthesize the service path!\n");
272094332d3Sopenharmony_ci        return NULL;
273094332d3Sopenharmony_ci    }
274094332d3Sopenharmony_ci    if (!CheckMixerDevFile(path)) {
275094332d3Sopenharmony_ci        /* The sound card service file does not exist */
276094332d3Sopenharmony_ci        return NULL;
277094332d3Sopenharmony_ci    }
278094332d3Sopenharmony_ci
279094332d3Sopenharmony_ci    SrvBind = CallLibFunction("HdfIoServiceBindName");
280094332d3Sopenharmony_ci    if (SrvBind == NULL) {
281094332d3Sopenharmony_ci        return NULL;
282094332d3Sopenharmony_ci    }
283094332d3Sopenharmony_ci
284094332d3Sopenharmony_ci    return SrvBind(CTL_SRV_DEFAULT);
285094332d3Sopenharmony_ci}
286094332d3Sopenharmony_ci
287094332d3Sopenharmony_civoid MixerRecycleCrlSrv(struct HdfIoService *srv)
288094332d3Sopenharmony_ci{
289094332d3Sopenharmony_ci    void (*SrvRecycle)(struct HdfIoService *);
290094332d3Sopenharmony_ci
291094332d3Sopenharmony_ci    if (srv != NULL) {
292094332d3Sopenharmony_ci        SrvRecycle = CallLibFunction("AudioCloseServiceSub");
293094332d3Sopenharmony_ci        if (SrvRecycle != NULL) {
294094332d3Sopenharmony_ci            SrvRecycle(srv);
295094332d3Sopenharmony_ci        }
296094332d3Sopenharmony_ci    }
297094332d3Sopenharmony_ci}
298094332d3Sopenharmony_ci
299094332d3Sopenharmony_cistatic const char *CtlElemIfaceName(AudioCtlElemIfaceType iface)
300094332d3Sopenharmony_ci{
301094332d3Sopenharmony_ci    return ctlEIfNames[iface];
302094332d3Sopenharmony_ci}
303094332d3Sopenharmony_ci
304094332d3Sopenharmony_cistatic const char *CtlElemName(struct AudioHwCtlElemIndex *id)
305094332d3Sopenharmony_ci{
306094332d3Sopenharmony_ci    return (const char *)id->eId.name;
307094332d3Sopenharmony_ci}
308094332d3Sopenharmony_ci
309094332d3Sopenharmony_cistatic void PrintCtlElemInfo(struct AudioHwCtlElemId *id)
310094332d3Sopenharmony_ci{
311094332d3Sopenharmony_ci    printf("iface=%s, name='%s'\n", CtlElemIfaceName(id->iface), id->name);
312094332d3Sopenharmony_ci}
313094332d3Sopenharmony_ci
314094332d3Sopenharmony_cistatic void PrintCtlElemInfoidx(struct MixerCtsElemIdx *eidx)
315094332d3Sopenharmony_ci{
316094332d3Sopenharmony_ci    printf("index=%u, numid=%u, ", eidx->index, eidx->index + 1);
317094332d3Sopenharmony_ci    PrintCtlElemInfo(eidx->id);
318094332d3Sopenharmony_ci}
319094332d3Sopenharmony_ci
320094332d3Sopenharmony_cistatic void PrintCtlElemList(struct AudioMixerContents *contents)
321094332d3Sopenharmony_ci{
322094332d3Sopenharmony_ci    uint32_t num, idx;
323094332d3Sopenharmony_ci    struct MixerCtsElemIdx eidx;
324094332d3Sopenharmony_ci    struct AudioHwCtlElemId *id = NULL;
325094332d3Sopenharmony_ci
326094332d3Sopenharmony_ci    num = contents->elemNum;
327094332d3Sopenharmony_ci    id = (struct AudioHwCtlElemId *)contents->data;
328094332d3Sopenharmony_ci    for (idx = 0; idx < num; idx++) {
329094332d3Sopenharmony_ci        eidx.id = id++;
330094332d3Sopenharmony_ci        eidx.index = idx;
331094332d3Sopenharmony_ci        PrintCtlElemInfoidx(&eidx);
332094332d3Sopenharmony_ci    }
333094332d3Sopenharmony_ci}
334094332d3Sopenharmony_ci
335094332d3Sopenharmony_civoid ReleaseCtlElemList(void)
336094332d3Sopenharmony_ci{
337094332d3Sopenharmony_ci    if (g_mixerCts.data != NULL) {
338094332d3Sopenharmony_ci        free(g_mixerCts.data);
339094332d3Sopenharmony_ci        g_mixerCts.data = NULL;
340094332d3Sopenharmony_ci    }
341094332d3Sopenharmony_ci    g_mixerCts.elemNum = 0;
342094332d3Sopenharmony_ci    (void)memset_s(g_mixerCts.cardServiceName, AUDIO_CARD_SRV_NAME_LEN, 0x0, AUDIO_CARD_SRV_NAME_LEN);
343094332d3Sopenharmony_ci}
344094332d3Sopenharmony_ci
345094332d3Sopenharmony_cistatic int32_t MctlListSub(const struct HdfIoService *service, const char *cardSrv)
346094332d3Sopenharmony_ci{
347094332d3Sopenharmony_ci    int32_t ret;
348094332d3Sopenharmony_ci
349094332d3Sopenharmony_ci    ret = strncpy_s(g_mixerCts.cardServiceName, AUDIO_CARD_SRV_NAME_LEN - 1, cardSrv, AUDIO_CARD_SRV_NAME_LEN - 1);
350094332d3Sopenharmony_ci    if (ret != 0) {
351094332d3Sopenharmony_ci        DEBUG_LOG("strncpy_s fail!\n");
352094332d3Sopenharmony_ci        return U_FAILURE;
353094332d3Sopenharmony_ci    }
354094332d3Sopenharmony_ci    g_mixerCts.cardServiceName[AUDIO_CARD_SRV_NAME_LEN - 1] = '\0';
355094332d3Sopenharmony_ci    if (g_audioMixer.GetElemList == NULL) {
356094332d3Sopenharmony_ci        DEBUG_LOG("The callback function is NULL!\n");
357094332d3Sopenharmony_ci        return U_FAILURE;
358094332d3Sopenharmony_ci    }
359094332d3Sopenharmony_ci
360094332d3Sopenharmony_ci    if (g_mixerCts.data != NULL && g_mixerCts.elemNum > 0) {
361094332d3Sopenharmony_ci        /* The list of control elements has been obtained */
362094332d3Sopenharmony_ci        return U_SUCCESS;
363094332d3Sopenharmony_ci    }
364094332d3Sopenharmony_ci
365094332d3Sopenharmony_ci    if (g_mixerCts.data != NULL) {
366094332d3Sopenharmony_ci        free(g_mixerCts.data);
367094332d3Sopenharmony_ci        g_mixerCts.data = NULL;
368094332d3Sopenharmony_ci    }
369094332d3Sopenharmony_ci    g_mixerCts.elemNum = 0;
370094332d3Sopenharmony_ci
371094332d3Sopenharmony_ci    ret = g_audioMixer.GetElemList(service, &g_mixerCts);
372094332d3Sopenharmony_ci    if (ret != U_SUCCESS) {
373094332d3Sopenharmony_ci        return ret;
374094332d3Sopenharmony_ci    }
375094332d3Sopenharmony_ci    if (g_mixerCts.data == NULL) {
376094332d3Sopenharmony_ci        g_mixerCts.elemNum = 0;
377094332d3Sopenharmony_ci        (void)memset_s(g_mixerCts.cardServiceName, AUDIO_CARD_SRV_NAME_LEN, 0x0, AUDIO_CARD_SRV_NAME_LEN);
378094332d3Sopenharmony_ci        DEBUG_LOG("Failed to obtain data!\n");
379094332d3Sopenharmony_ci        return U_FAILURE;
380094332d3Sopenharmony_ci    }
381094332d3Sopenharmony_ci    if (g_mixerCts.elemNum == 0) {
382094332d3Sopenharmony_ci        free(g_mixerCts.data);
383094332d3Sopenharmony_ci        g_mixerCts.data = NULL;
384094332d3Sopenharmony_ci        (void)memset_s(g_mixerCts.cardServiceName, AUDIO_CARD_SRV_NAME_LEN, 0x0, AUDIO_CARD_SRV_NAME_LEN);
385094332d3Sopenharmony_ci        DEBUG_LOG("Description Failed to obtain the number of data!\n");
386094332d3Sopenharmony_ci        return U_FAILURE;
387094332d3Sopenharmony_ci    }
388094332d3Sopenharmony_ci
389094332d3Sopenharmony_ci    return U_SUCCESS;
390094332d3Sopenharmony_ci}
391094332d3Sopenharmony_ci
392094332d3Sopenharmony_ciint32_t MctlList(const struct HdfIoService *service, const char *cardSrv)
393094332d3Sopenharmony_ci{
394094332d3Sopenharmony_ci    int32_t ret;
395094332d3Sopenharmony_ci
396094332d3Sopenharmony_ci    if (service == NULL || cardSrv == NULL) {
397094332d3Sopenharmony_ci        DEBUG_LOG("Invalid parameters!\n");
398094332d3Sopenharmony_ci        return U_INVALID_PARAM;
399094332d3Sopenharmony_ci    }
400094332d3Sopenharmony_ci
401094332d3Sopenharmony_ci    ret = MctlListSub(service, cardSrv);
402094332d3Sopenharmony_ci    if (ret != U_SUCCESS) {
403094332d3Sopenharmony_ci        return ret;
404094332d3Sopenharmony_ci    }
405094332d3Sopenharmony_ci    PrintCtlElemList(&g_mixerCts);
406094332d3Sopenharmony_ci
407094332d3Sopenharmony_ci    return U_SUCCESS;
408094332d3Sopenharmony_ci}
409094332d3Sopenharmony_ci
410094332d3Sopenharmony_ciint32_t MctlInfo(const struct HdfIoService *service, const char *cardSrv)
411094332d3Sopenharmony_ci{
412094332d3Sopenharmony_ci    int32_t ret;
413094332d3Sopenharmony_ci    uint32_t num;
414094332d3Sopenharmony_ci    struct AudioHwCtlElemId *id;
415094332d3Sopenharmony_ci
416094332d3Sopenharmony_ci    if (g_mixerCts.data == NULL || g_mixerCts.elemNum == 0) {
417094332d3Sopenharmony_ci        ReleaseCtlElemList();
418094332d3Sopenharmony_ci        ret = MctlListSub(service, cardSrv);
419094332d3Sopenharmony_ci        if (ret != U_SUCCESS) {
420094332d3Sopenharmony_ci            DEBUG_LOG("No reference data\n");
421094332d3Sopenharmony_ci            return ret;
422094332d3Sopenharmony_ci        }
423094332d3Sopenharmony_ci    }
424094332d3Sopenharmony_ci
425094332d3Sopenharmony_ci    /* The list of control elements has been obtained */
426094332d3Sopenharmony_ci    num = g_mixerCts.elemNum;
427094332d3Sopenharmony_ci    id = (struct AudioHwCtlElemId *)g_mixerCts.data;
428094332d3Sopenharmony_ci    while (num--) {
429094332d3Sopenharmony_ci        PrintCtlElemInfo(id++);
430094332d3Sopenharmony_ci    }
431094332d3Sopenharmony_ci    ReleaseCtlElemList();
432094332d3Sopenharmony_ci
433094332d3Sopenharmony_ci    return U_SUCCESS;
434094332d3Sopenharmony_ci}
435094332d3Sopenharmony_ci
436094332d3Sopenharmony_cibool MixerFindSelem(const struct HdfIoService *srv, const char *cardSrv, const struct AudioHwCtlElemId *eId)
437094332d3Sopenharmony_ci{
438094332d3Sopenharmony_ci    int32_t ret;
439094332d3Sopenharmony_ci    uint32_t index;
440094332d3Sopenharmony_ci    struct AudioHwCtlElemId *findElem;
441094332d3Sopenharmony_ci
442094332d3Sopenharmony_ci    if (eId == NULL) {
443094332d3Sopenharmony_ci        DEBUG_LOG("Invalid parameters\n");
444094332d3Sopenharmony_ci        return false;
445094332d3Sopenharmony_ci    }
446094332d3Sopenharmony_ci
447094332d3Sopenharmony_ci    if (g_mixerCts.elemNum == 0 || g_mixerCts.data == NULL) {
448094332d3Sopenharmony_ci        ReleaseCtlElemList();
449094332d3Sopenharmony_ci        ret = MctlListSub(srv, cardSrv);
450094332d3Sopenharmony_ci        if (ret != U_SUCCESS) {
451094332d3Sopenharmony_ci            DEBUG_LOG("No reference data\n");
452094332d3Sopenharmony_ci            return false;
453094332d3Sopenharmony_ci        }
454094332d3Sopenharmony_ci    }
455094332d3Sopenharmony_ci
456094332d3Sopenharmony_ci    findElem = g_mixerCts.data;
457094332d3Sopenharmony_ci    for (index = 0; index < g_mixerCts.elemNum; index++) {
458094332d3Sopenharmony_ci        if (strcmp(eId->name, findElem[index].name) == 0) {
459094332d3Sopenharmony_ci            break;
460094332d3Sopenharmony_ci        }
461094332d3Sopenharmony_ci    }
462094332d3Sopenharmony_ci    if (index == g_mixerCts.elemNum) {
463094332d3Sopenharmony_ci        DEBUG_LOG("The corresponding control does not match!\n");
464094332d3Sopenharmony_ci        ReleaseCtlElemList();
465094332d3Sopenharmony_ci        return false;
466094332d3Sopenharmony_ci    }
467094332d3Sopenharmony_ci    ReleaseCtlElemList();
468094332d3Sopenharmony_ci
469094332d3Sopenharmony_ci    return true;
470094332d3Sopenharmony_ci}
471094332d3Sopenharmony_ci
472094332d3Sopenharmony_cistatic AudioCtlElemIfaceType GetCtlElemIface(struct AudioHwCtlElemIndex *id)
473094332d3Sopenharmony_ci{
474094332d3Sopenharmony_ci    return id->eId.iface;
475094332d3Sopenharmony_ci}
476094332d3Sopenharmony_ci
477094332d3Sopenharmony_cistatic unsigned int CtlElemGetIdx(struct AudioHwCtlElemIndex *id)
478094332d3Sopenharmony_ci{
479094332d3Sopenharmony_ci    return id->index;
480094332d3Sopenharmony_ci}
481094332d3Sopenharmony_ci
482094332d3Sopenharmony_cistatic unsigned int CtlElemInfoCnt(struct AudioMixerCtlElemInfo *info)
483094332d3Sopenharmony_ci{
484094332d3Sopenharmony_ci    return info->count;
485094332d3Sopenharmony_ci}
486094332d3Sopenharmony_ci
487094332d3Sopenharmony_cistatic AudioCtlElemType CtlElemGetInfoType(struct AudioMixerCtlElemInfo *info)
488094332d3Sopenharmony_ci{
489094332d3Sopenharmony_ci    return info->type;
490094332d3Sopenharmony_ci}
491094332d3Sopenharmony_ci
492094332d3Sopenharmony_cistatic const char *CtlElemTypeName(AudioCtlElemType type)
493094332d3Sopenharmony_ci{
494094332d3Sopenharmony_ci    return ctlElemTypeNames[type];
495094332d3Sopenharmony_ci}
496094332d3Sopenharmony_ci
497094332d3Sopenharmony_cistatic const char *MixerCtlType(struct AudioMixerCtlElemInfo *info)
498094332d3Sopenharmony_ci{
499094332d3Sopenharmony_ci    return CtlElemTypeName(CtlElemGetInfoType(info));
500094332d3Sopenharmony_ci}
501094332d3Sopenharmony_ci
502094332d3Sopenharmony_cistatic int32_t CtlElemInfoGetMin(struct AudioMixerCtlElemInfo *info)
503094332d3Sopenharmony_ci{
504094332d3Sopenharmony_ci    return info->value.intVal.min;
505094332d3Sopenharmony_ci}
506094332d3Sopenharmony_ci
507094332d3Sopenharmony_cistatic int32_t CtlElemInfoGetMax(struct AudioMixerCtlElemInfo *info)
508094332d3Sopenharmony_ci{
509094332d3Sopenharmony_ci    return info->value.intVal.max;
510094332d3Sopenharmony_ci}
511094332d3Sopenharmony_ci
512094332d3Sopenharmony_cistatic int32_t CtlElemInfoGetStep(struct AudioMixerCtlElemInfo *info)
513094332d3Sopenharmony_ci{
514094332d3Sopenharmony_ci    return info->value.intVal.step;
515094332d3Sopenharmony_ci}
516094332d3Sopenharmony_ci
517094332d3Sopenharmony_cistatic long *CtlElemInfoGetVals(struct AudioMixerCtlElemInfo *info)
518094332d3Sopenharmony_ci{
519094332d3Sopenharmony_ci    return info->value.intVal.vals;
520094332d3Sopenharmony_ci}
521094332d3Sopenharmony_ci
522094332d3Sopenharmony_cistatic void CtlElemInfoSetItem(struct AudioMixerCtlElemInfo *info, uint32_t val)
523094332d3Sopenharmony_ci{
524094332d3Sopenharmony_ci    info->value.enumVal.item = val;
525094332d3Sopenharmony_ci}
526094332d3Sopenharmony_ci
527094332d3Sopenharmony_cistatic uint32_t CtlElemInfoGetItems(struct AudioMixerCtlElemInfo *info)
528094332d3Sopenharmony_ci{
529094332d3Sopenharmony_ci    return info->value.enumVal.items;
530094332d3Sopenharmony_ci}
531094332d3Sopenharmony_ci
532094332d3Sopenharmony_cistatic uint32_t CtlElemInfoGetItem(struct AudioMixerCtlElemInfo *info)
533094332d3Sopenharmony_ci{
534094332d3Sopenharmony_ci    return info->value.enumVal.item;
535094332d3Sopenharmony_ci}
536094332d3Sopenharmony_ci
537094332d3Sopenharmony_cistatic char *CtlElemInfoGetItemName(struct AudioMixerCtlElemInfo *info)
538094332d3Sopenharmony_ci{
539094332d3Sopenharmony_ci    return info->value.enumVal.name;
540094332d3Sopenharmony_ci}
541094332d3Sopenharmony_ci
542094332d3Sopenharmony_cistatic int32_t CtlElemValueGetBoolean(struct AudioMixerCtlElemInfo *info, uint32_t idx)
543094332d3Sopenharmony_ci{
544094332d3Sopenharmony_ci    if (idx > BIT_VALULE_OFFSET - 1) {
545094332d3Sopenharmony_ci        return 0;
546094332d3Sopenharmony_ci    }
547094332d3Sopenharmony_ci
548094332d3Sopenharmony_ci    return ((info->value.intVal.max >> idx) & 0x1);
549094332d3Sopenharmony_ci}
550094332d3Sopenharmony_ci
551094332d3Sopenharmony_cistatic int32_t CtlElemValueGetInt(struct AudioMixerCtlElemInfo *info, uint32_t idx)
552094332d3Sopenharmony_ci{
553094332d3Sopenharmony_ci    return CtlElemValueGetBoolean(info, idx);
554094332d3Sopenharmony_ci}
555094332d3Sopenharmony_ci
556094332d3Sopenharmony_cistatic char CtlElemValueGetByte(struct AudioMixerCtlElemInfo *info, uint32_t idx)
557094332d3Sopenharmony_ci{
558094332d3Sopenharmony_ci    if (idx >= RESERVED_BUF_LEN) {
559094332d3Sopenharmony_ci        return '?';
560094332d3Sopenharmony_ci    }
561094332d3Sopenharmony_ci
562094332d3Sopenharmony_ci    return info->value.reserved[idx];
563094332d3Sopenharmony_ci}
564094332d3Sopenharmony_ci
565094332d3Sopenharmony_cistatic unsigned char *CtlElemValueGetBytes(struct AudioMixerCtlElemInfo *info)
566094332d3Sopenharmony_ci{
567094332d3Sopenharmony_ci    return info->value.reserved;
568094332d3Sopenharmony_ci}
569094332d3Sopenharmony_ci
570094332d3Sopenharmony_cistatic uint32_t CtlElemValueGetEnum(struct AudioMixerCtlElemInfo *info, uint32_t idx)
571094332d3Sopenharmony_ci{
572094332d3Sopenharmony_ci    if (idx > BIT_VALULE_OFFSET) {
573094332d3Sopenharmony_ci        return 0;
574094332d3Sopenharmony_ci    }
575094332d3Sopenharmony_ci
576094332d3Sopenharmony_ci    return ((info->value.enumVal.item >> idx) & 0x1);
577094332d3Sopenharmony_ci}
578094332d3Sopenharmony_ci
579094332d3Sopenharmony_cistatic void PrintOtherVal(struct AudioMixerCtlElemInfo *info)
580094332d3Sopenharmony_ci{
581094332d3Sopenharmony_ci    uint32_t idx;
582094332d3Sopenharmony_ci    unsigned int count;
583094332d3Sopenharmony_ci    AudioCtlElemType type;
584094332d3Sopenharmony_ci
585094332d3Sopenharmony_ci    type = CtlElemGetInfoType(info);
586094332d3Sopenharmony_ci    count = CtlElemInfoCnt(info);
587094332d3Sopenharmony_ci    for (idx = 0; idx < count; idx++) {
588094332d3Sopenharmony_ci        if (idx > 0) {
589094332d3Sopenharmony_ci            printf(", ");
590094332d3Sopenharmony_ci        }
591094332d3Sopenharmony_ci
592094332d3Sopenharmony_ci        switch (type) {
593094332d3Sopenharmony_ci            case AUDIO_CTL_ELEM_TYPE_BOOLEAN:
594094332d3Sopenharmony_ci                printf("%s", CtlElemValueGetBoolean(info, idx) ? "on" : "off");
595094332d3Sopenharmony_ci                break;
596094332d3Sopenharmony_ci            case AUDIO_CTL_ELEM_TYPE_BYTES:
597094332d3Sopenharmony_ci                printf("0x%02x", CtlElemValueGetByte(info, idx));
598094332d3Sopenharmony_ci                break;
599094332d3Sopenharmony_ci            case AUDIO_CTL_ELEM_TYPE_INTEGER:
600094332d3Sopenharmony_ci                printf("%i", CtlElemValueGetInt(info, idx));
601094332d3Sopenharmony_ci                break;
602094332d3Sopenharmony_ci            case AUDIO_CTL_ELEM_TYPE_ENUMERATED:
603094332d3Sopenharmony_ci                printf("%u", CtlElemValueGetEnum(info, idx));
604094332d3Sopenharmony_ci                break;
605094332d3Sopenharmony_ci            default:
606094332d3Sopenharmony_ci                printf("?");
607094332d3Sopenharmony_ci                break;
608094332d3Sopenharmony_ci        }
609094332d3Sopenharmony_ci    }
610094332d3Sopenharmony_ci    printf("\n");
611094332d3Sopenharmony_ci}
612094332d3Sopenharmony_ci
613094332d3Sopenharmony_cistatic void PrintValue(struct AudioMixerCtlElemInfo *info)
614094332d3Sopenharmony_ci{
615094332d3Sopenharmony_ci    long *ptr;
616094332d3Sopenharmony_ci    uint32_t idx, items;
617094332d3Sopenharmony_ci    AudioCtlElemType type;
618094332d3Sopenharmony_ci
619094332d3Sopenharmony_ci    type = CtlElemGetInfoType(info);
620094332d3Sopenharmony_ci    switch (type) {
621094332d3Sopenharmony_ci        case AUDIO_CTL_ELEM_TYPE_INTEGER:
622094332d3Sopenharmony_ci            printf(", min=%i, max=%i, step=%i\n",
623094332d3Sopenharmony_ci                CtlElemInfoGetMin(info),
624094332d3Sopenharmony_ci                CtlElemInfoGetMax(info),
625094332d3Sopenharmony_ci                CtlElemInfoGetStep(info));
626094332d3Sopenharmony_ci            ptr = CtlElemInfoGetVals(info);
627094332d3Sopenharmony_ci            printf("  : values=");
628094332d3Sopenharmony_ci            for (idx = 0; idx < info->count; idx++) {
629094332d3Sopenharmony_ci                if (idx > 0) {
630094332d3Sopenharmony_ci                    printf(", ");
631094332d3Sopenharmony_ci                }
632094332d3Sopenharmony_ci                printf("%i", (int)ptr[idx]);
633094332d3Sopenharmony_ci            }
634094332d3Sopenharmony_ci            printf("\n");
635094332d3Sopenharmony_ci            break;
636094332d3Sopenharmony_ci        case AUDIO_CTL_ELEM_TYPE_ENUMERATED:
637094332d3Sopenharmony_ci            {
638094332d3Sopenharmony_ci                items = CtlElemInfoGetItems(info);
639094332d3Sopenharmony_ci                printf(", items=%u\n", items);
640094332d3Sopenharmony_ci                for (idx = 0; idx < items; idx++) {
641094332d3Sopenharmony_ci                    CtlElemInfoSetItem(info, idx);
642094332d3Sopenharmony_ci                    printf("%s; Item #%u '%s'\n", "  ", idx, CtlElemInfoGetItemName(info));
643094332d3Sopenharmony_ci                }
644094332d3Sopenharmony_ci                printf("  : values=%u\n", CtlElemInfoGetItem(info));
645094332d3Sopenharmony_ci            }
646094332d3Sopenharmony_ci            break;
647094332d3Sopenharmony_ci        case AUDIO_CTL_ELEM_TYPE_BOOLEAN:
648094332d3Sopenharmony_ci            printf("\n  : values=");
649094332d3Sopenharmony_ci            PrintOtherVal(info);
650094332d3Sopenharmony_ci            break;
651094332d3Sopenharmony_ci        case AUDIO_CTL_ELEM_TYPE_BYTES:
652094332d3Sopenharmony_ci            printf("  : values=%s\n", CtlElemValueGetBytes(info));
653094332d3Sopenharmony_ci            break;
654094332d3Sopenharmony_ci        default:
655094332d3Sopenharmony_ci            DEBUG_LOG("Mismatched control value type!\n");
656094332d3Sopenharmony_ci            break;
657094332d3Sopenharmony_ci    }
658094332d3Sopenharmony_ci}
659094332d3Sopenharmony_ci
660094332d3Sopenharmony_cistatic void ShowIntVal(struct AudioMixerCtlElemInfo *info)
661094332d3Sopenharmony_ci{
662094332d3Sopenharmony_ci    int32_t ret;
663094332d3Sopenharmony_ci    uint32_t index;
664094332d3Sopenharmony_ci    unsigned int count;
665094332d3Sopenharmony_ci    const char *iface;
666094332d3Sopenharmony_ci    const char *space = "  ";
667094332d3Sopenharmony_ci    char buf[BUF_SIZE_T + 1] = {0};
668094332d3Sopenharmony_ci
669094332d3Sopenharmony_ci    index = CtlElemGetIdx(&info->eIndexId);
670094332d3Sopenharmony_ci    iface = CtlElemIfaceName(GetCtlElemIface(&info->eIndexId));
671094332d3Sopenharmony_ci    if (index > 0) {
672094332d3Sopenharmony_ci        ret = snprintf_s(buf, BUF_SIZE_T, BUF_SIZE_T, "index=%u, iface=%s, name=%s",
673094332d3Sopenharmony_ci            index, iface, CtlElemName(&info->eIndexId));
674094332d3Sopenharmony_ci    } else {
675094332d3Sopenharmony_ci        ret = snprintf_s(buf, BUF_SIZE_T, BUF_SIZE_T, "iface=%s, name=%s",
676094332d3Sopenharmony_ci            iface, CtlElemName(&info->eIndexId));
677094332d3Sopenharmony_ci    }
678094332d3Sopenharmony_ci    if (ret < 0) {
679094332d3Sopenharmony_ci        DEBUG_LOG("Failed to snprintf_s!\n");
680094332d3Sopenharmony_ci        return;
681094332d3Sopenharmony_ci    }
682094332d3Sopenharmony_ci
683094332d3Sopenharmony_ci    buf[BUF_SIZE_T] = '\0';
684094332d3Sopenharmony_ci    printf("%s\n", buf);
685094332d3Sopenharmony_ci
686094332d3Sopenharmony_ci    count = CtlElemInfoCnt(info);
687094332d3Sopenharmony_ci    printf("%s; type=%s, values=%u", space, MixerCtlType(info), count);
688094332d3Sopenharmony_ci    PrintValue(info);
689094332d3Sopenharmony_ci}
690094332d3Sopenharmony_ci
691094332d3Sopenharmony_cistatic void ShowEnumVal(struct AudioMixerCtlElemInfo *info)
692094332d3Sopenharmony_ci{
693094332d3Sopenharmony_ci    printf("  : values=%u\n", CtlElemInfoGetItem(info));
694094332d3Sopenharmony_ci}
695094332d3Sopenharmony_ci
696094332d3Sopenharmony_cistatic void ShowBytesVal(const unsigned char *data)
697094332d3Sopenharmony_ci{
698094332d3Sopenharmony_ci    int i;
699094332d3Sopenharmony_ci    const unsigned char *p = data;
700094332d3Sopenharmony_ci
701094332d3Sopenharmony_ci    printf("\ndata:\t");
702094332d3Sopenharmony_ci    for (i = 0; i < RESERVED_BUF_LEN; i++) {
703094332d3Sopenharmony_ci        if (*p == '\0') {
704094332d3Sopenharmony_ci            break;
705094332d3Sopenharmony_ci        }
706094332d3Sopenharmony_ci
707094332d3Sopenharmony_ci        if ((i % OUTPUT_ALIGN) == 0) {
708094332d3Sopenharmony_ci            printf("\n");
709094332d3Sopenharmony_ci        }
710094332d3Sopenharmony_ci        printf("0x%02x \n", *p++);
711094332d3Sopenharmony_ci    }
712094332d3Sopenharmony_ci    printf("\n");
713094332d3Sopenharmony_ci    printf("string: %s\n", data);
714094332d3Sopenharmony_ci}
715094332d3Sopenharmony_ci
716094332d3Sopenharmony_cistatic void ShowElemInfo(struct AudioMixerCtlElemInfo *info)
717094332d3Sopenharmony_ci{
718094332d3Sopenharmony_ci    switch (info->type) {
719094332d3Sopenharmony_ci        case AUDIO_CTL_ELEM_TYPE_INTEGER:
720094332d3Sopenharmony_ci        case AUDIO_CTL_ELEM_TYPE_BOOLEAN:
721094332d3Sopenharmony_ci            ShowIntVal(info);
722094332d3Sopenharmony_ci            break;
723094332d3Sopenharmony_ci        case AUDIO_CTL_ELEM_TYPE_ENUMERATED:
724094332d3Sopenharmony_ci            ShowEnumVal(info);
725094332d3Sopenharmony_ci            break;
726094332d3Sopenharmony_ci        case AUDIO_CTL_ELEM_TYPE_BYTES:
727094332d3Sopenharmony_ci            ShowBytesVal(info->value.reserved);
728094332d3Sopenharmony_ci            break;
729094332d3Sopenharmony_ci        default:
730094332d3Sopenharmony_ci            DEBUG_LOG("Mismatched control value type!\n");
731094332d3Sopenharmony_ci            break;
732094332d3Sopenharmony_ci    }
733094332d3Sopenharmony_ci}
734094332d3Sopenharmony_ci
735094332d3Sopenharmony_ciint32_t MctlGetElem(const struct HdfIoService *service, struct MixerCardCtlInfo *ctlInfo)
736094332d3Sopenharmony_ci{
737094332d3Sopenharmony_ci    int32_t ret;
738094332d3Sopenharmony_ci    struct AudioMixerCtlElemInfo info;
739094332d3Sopenharmony_ci
740094332d3Sopenharmony_ci    if (service == NULL || ctlInfo == NULL) {
741094332d3Sopenharmony_ci        DEBUG_LOG("Invalid parameters!\n");
742094332d3Sopenharmony_ci        return U_INVALID_PARAM;
743094332d3Sopenharmony_ci    }
744094332d3Sopenharmony_ci
745094332d3Sopenharmony_ci    ret = strncpy_s(info.cardSrvName, AUDIO_CARD_SRV_NAME_LEN - 1, ctlInfo->cardSrvName, AUDIO_CARD_SRV_NAME_LEN - 1);
746094332d3Sopenharmony_ci    if (ret != 0) {
747094332d3Sopenharmony_ci        DEBUG_LOG("strncpy_s cardSrvName fail!\n");
748094332d3Sopenharmony_ci        return U_FAILURE;
749094332d3Sopenharmony_ci    }
750094332d3Sopenharmony_ci    info.cardSrvName[AUDIO_CARD_SRV_NAME_LEN - 1] = '\0';
751094332d3Sopenharmony_ci    ret = strncpy_s(info.eIndexId.eId.name, AUDIO_ELEM_NAME_LEN - 1, ctlInfo->edx.eId.name, AUDIO_ELEM_NAME_LEN - 1);
752094332d3Sopenharmony_ci    if (ret != 0) {
753094332d3Sopenharmony_ci        DEBUG_LOG("strncpy_s element name fail!\n");
754094332d3Sopenharmony_ci        return U_FAILURE;
755094332d3Sopenharmony_ci    }
756094332d3Sopenharmony_ci    info.eIndexId.eId.name[AUDIO_ELEM_NAME_LEN - 1] = '\0';
757094332d3Sopenharmony_ci    info.eIndexId.eId.iface = ctlInfo->edx.eId.iface;
758094332d3Sopenharmony_ci    // need info.type
759094332d3Sopenharmony_ci    info.type = AUDIO_CTL_ELEM_TYPE_INTEGER;
760094332d3Sopenharmony_ci
761094332d3Sopenharmony_ci    if (g_audioMixer.GetElemProp == NULL) {
762094332d3Sopenharmony_ci        DEBUG_LOG("The callback function is NULL!\n");
763094332d3Sopenharmony_ci        return U_FAILURE;
764094332d3Sopenharmony_ci    }
765094332d3Sopenharmony_ci    ret = g_audioMixer.GetElemProp(service, &info);
766094332d3Sopenharmony_ci    if (ret != U_SUCCESS) {
767094332d3Sopenharmony_ci        DEBUG_LOG("Failed to get control!\n");
768094332d3Sopenharmony_ci        return U_FAILURE;
769094332d3Sopenharmony_ci    }
770094332d3Sopenharmony_ci    ShowElemInfo(&info);
771094332d3Sopenharmony_ci
772094332d3Sopenharmony_ci    return U_SUCCESS;
773094332d3Sopenharmony_ci}
774094332d3Sopenharmony_ci
775094332d3Sopenharmony_cistatic const struct ChannelMask g_chnMask[] = {
776094332d3Sopenharmony_ci    {"frontleft",   1 << AMIXER_CHN_FRONT_LEFT                                    },
777094332d3Sopenharmony_ci    {"frontright",  1 << AMIXER_CHN_FRONT_RIGHT                                   },
778094332d3Sopenharmony_ci    {"frontcenter", 1 << AMIXER_CHN_FRONT_CENTER                                  },
779094332d3Sopenharmony_ci    {"front",       ((1 << AMIXER_CHN_FRONT_LEFT) | (1 << AMIXER_CHN_FRONT_RIGHT))},
780094332d3Sopenharmony_ci    {"center",      1 << AMIXER_CHN_FRONT_CENTER                                  },
781094332d3Sopenharmony_ci    {"rearleft",    1 << AMIXER_CHN_REAR_LEFT                                     },
782094332d3Sopenharmony_ci    {"rearright",   1 << AMIXER_CHN_REAR_RIGHT                                    },
783094332d3Sopenharmony_ci    {"rear",        ((1 << AMIXER_CHN_REAR_LEFT) | (1 << AMIXER_CHN_REAR_RIGHT))  },
784094332d3Sopenharmony_ci    {"woofer",      1 << AMIXER_CHN_WOOFER                                        },
785094332d3Sopenharmony_ci    {NULL,          0                                                             }
786094332d3Sopenharmony_ci};
787094332d3Sopenharmony_ci
788094332d3Sopenharmony_cistatic uint32_t ChannelsMask(char **ptr, unsigned int chns)
789094332d3Sopenharmony_ci{
790094332d3Sopenharmony_ci    const struct ChannelMask *msk;
791094332d3Sopenharmony_ci
792094332d3Sopenharmony_ci    for (msk = g_chnMask; msk->name != NULL; msk++) {
793094332d3Sopenharmony_ci        if (strncasecmp(*ptr, msk->name, strlen(msk->name)) == 0) {
794094332d3Sopenharmony_ci            /* Stop loop at specified character. */
795094332d3Sopenharmony_ci            while (**ptr != '\0' && **ptr != ',' && **ptr != ' ' && **ptr != '\t') {
796094332d3Sopenharmony_ci                (*ptr)++;
797094332d3Sopenharmony_ci            }
798094332d3Sopenharmony_ci            /* Skip the specified character. */
799094332d3Sopenharmony_ci            if (**ptr == ',' || **ptr == ' ' || **ptr == '\t') {
800094332d3Sopenharmony_ci                (*ptr)++;
801094332d3Sopenharmony_ci            }
802094332d3Sopenharmony_ci
803094332d3Sopenharmony_ci            return msk->mask;
804094332d3Sopenharmony_ci        }
805094332d3Sopenharmony_ci    }
806094332d3Sopenharmony_ci
807094332d3Sopenharmony_ci    return chns;
808094332d3Sopenharmony_ci}
809094332d3Sopenharmony_ci
810094332d3Sopenharmony_cistatic uint32_t DirMask(char **ptr, unsigned int dir)
811094332d3Sopenharmony_ci{
812094332d3Sopenharmony_ci    int find = 0;
813094332d3Sopenharmony_ci
814094332d3Sopenharmony_ci    /* Stop loop at specified character. */
815094332d3Sopenharmony_ci    while (**ptr != '\0' && **ptr != ',' && **ptr != ' ' && **ptr != '\t') {
816094332d3Sopenharmony_ci        (*ptr)++;
817094332d3Sopenharmony_ci    }
818094332d3Sopenharmony_ci
819094332d3Sopenharmony_ci    /* Skip the specified character. */
820094332d3Sopenharmony_ci    if (**ptr == ',' || **ptr == ' ' || **ptr == '\t') {
821094332d3Sopenharmony_ci        (*ptr)++;
822094332d3Sopenharmony_ci    }
823094332d3Sopenharmony_ci
824094332d3Sopenharmony_ci    if (strncasecmp(*ptr, "render", strlen("render")) == 0) {
825094332d3Sopenharmony_ci        dir = find = PCM_RENDER + 1;
826094332d3Sopenharmony_ci    } else if (strncasecmp(*ptr, "capture", strlen("capture")) == 0) {
827094332d3Sopenharmony_ci        dir = find = PCM_CAPTURE + 1;
828094332d3Sopenharmony_ci    }
829094332d3Sopenharmony_ci
830094332d3Sopenharmony_ci    if (find) {
831094332d3Sopenharmony_ci        /* Stop loop at specified character. */
832094332d3Sopenharmony_ci        while (**ptr != '\0' && **ptr != ',' && **ptr != ' ' && **ptr != '\t') {
833094332d3Sopenharmony_ci            (*ptr)++;
834094332d3Sopenharmony_ci        }
835094332d3Sopenharmony_ci
836094332d3Sopenharmony_ci        /* Skip the specified character. */
837094332d3Sopenharmony_ci        if (**ptr == ',' || **ptr == ' ' || **ptr == '\t') {
838094332d3Sopenharmony_ci            (*ptr)++;
839094332d3Sopenharmony_ci        }
840094332d3Sopenharmony_ci    }
841094332d3Sopenharmony_ci
842094332d3Sopenharmony_ci    return dir;
843094332d3Sopenharmony_ci}
844094332d3Sopenharmony_ci
845094332d3Sopenharmony_cistatic bool IsRenderChannel(AudioMixerChannelIdType chn)
846094332d3Sopenharmony_ci{
847094332d3Sopenharmony_ci    return !!(chn);
848094332d3Sopenharmony_ci}
849094332d3Sopenharmony_ci
850094332d3Sopenharmony_cistatic bool IsCaptureChannel(AudioMixerChannelIdType chn)
851094332d3Sopenharmony_ci{
852094332d3Sopenharmony_ci    return !(chn);
853094332d3Sopenharmony_ci}
854094332d3Sopenharmony_ci
855094332d3Sopenharmony_cistatic int32_t FillChnmap(struct AudioMixerCtlElemInfo *info, uint32_t chns, uint32_t dir, char **ptr)
856094332d3Sopenharmony_ci{
857094332d3Sopenharmony_ci    char *sp;
858094332d3Sopenharmony_ci    AudioMixerChannelIdType chn;
859094332d3Sopenharmony_ci
860094332d3Sopenharmony_ci    /* Matches the specified channel. */
861094332d3Sopenharmony_ci    for (chn = AMIXER_CHN_FRONT_LEFT; chn < AMIXER_CHN_LAST; chn++) {
862094332d3Sopenharmony_ci        sp = NULL;
863094332d3Sopenharmony_ci        if (!(chns & (1 << (uint32_t)chn))) {
864094332d3Sopenharmony_ci            continue;
865094332d3Sopenharmony_ci        }
866094332d3Sopenharmony_ci
867094332d3Sopenharmony_ci        if (!((dir & PCM_RENDER) && IsRenderChannel(chn)) && !((dir & PCM_CAPTURE) && IsCaptureChannel(chn))) {
868094332d3Sopenharmony_ci            DEBUG_LOG("Unable to set channel!\n");
869094332d3Sopenharmony_ci            return U_FAILURE;
870094332d3Sopenharmony_ci        }
871094332d3Sopenharmony_ci
872094332d3Sopenharmony_ci        info->value.enumVal.item |= (chns & (1 << chn));
873094332d3Sopenharmony_ci        /* Search for the next channel. */
874094332d3Sopenharmony_ci        while (**ptr != '\0' && **ptr != ',') {
875094332d3Sopenharmony_ci            (*ptr)++;
876094332d3Sopenharmony_ci        }
877094332d3Sopenharmony_ci        if (**ptr == '\0') {
878094332d3Sopenharmony_ci            break;
879094332d3Sopenharmony_ci        }
880094332d3Sopenharmony_ci        (*ptr)++; // skip ','
881094332d3Sopenharmony_ci        DEBUG_LOG("skip, = %s\n", *ptr);
882094332d3Sopenharmony_ci    }
883094332d3Sopenharmony_ci
884094332d3Sopenharmony_ci    if (info->value.enumVal.item > CHN_STEREO) {
885094332d3Sopenharmony_ci        info->value.enumVal.item = CHN_STEREO;
886094332d3Sopenharmony_ci    } else {
887094332d3Sopenharmony_ci        info->value.enumVal.item = CHN_MONO;
888094332d3Sopenharmony_ci    }
889094332d3Sopenharmony_ci    DEBUG_LOG("chns = %i\n", info->value.enumVal.item);
890094332d3Sopenharmony_ci
891094332d3Sopenharmony_ci    return U_SUCCESS;
892094332d3Sopenharmony_ci}
893094332d3Sopenharmony_ci
894094332d3Sopenharmony_cistatic int32_t FillChnlsIntVal(struct AudioMixerCtlElemInfo *info, unsigned int argc, char *argv)
895094332d3Sopenharmony_ci{
896094332d3Sopenharmony_ci    bool mchns;
897094332d3Sopenharmony_ci    int32_t ret;
898094332d3Sopenharmony_ci    char *ptr = NULL;
899094332d3Sopenharmony_ci    uint32_t dir = 3;
900094332d3Sopenharmony_ci    uint32_t chns = ~0U;
901094332d3Sopenharmony_ci
902094332d3Sopenharmony_ci    ptr = argv;
903094332d3Sopenharmony_ci    chns = ChannelsMask(&ptr, chns);
904094332d3Sopenharmony_ci    if (*ptr == '\0') {
905094332d3Sopenharmony_ci        DEBUG_LOG("Channels Mask = %u\n", chns);
906094332d3Sopenharmony_ci        return U_FAILURE;
907094332d3Sopenharmony_ci    }
908094332d3Sopenharmony_ci
909094332d3Sopenharmony_ci    dir = DirMask(&ptr, dir);
910094332d3Sopenharmony_ci    if (*ptr == '\0') {
911094332d3Sopenharmony_ci        DEBUG_LOG("Direct Mask = %u\n", chns);
912094332d3Sopenharmony_ci        return U_FAILURE;
913094332d3Sopenharmony_ci    }
914094332d3Sopenharmony_ci
915094332d3Sopenharmony_ci    mchns = (strchr(ptr, ',') != NULL);
916094332d3Sopenharmony_ci    if (!mchns) {
917094332d3Sopenharmony_ci        info->value.enumVal.item = CHN_MONO;
918094332d3Sopenharmony_ci        return U_SUCCESS;
919094332d3Sopenharmony_ci    }
920094332d3Sopenharmony_ci
921094332d3Sopenharmony_ci    ret = FillChnmap(info, chns, dir, &ptr);
922094332d3Sopenharmony_ci    if (ret != U_SUCCESS) {
923094332d3Sopenharmony_ci        return ret;
924094332d3Sopenharmony_ci    }
925094332d3Sopenharmony_ci
926094332d3Sopenharmony_ci    return U_SUCCESS;
927094332d3Sopenharmony_ci}
928094332d3Sopenharmony_ci
929094332d3Sopenharmony_ciint32_t SetChannels(const struct HdfIoService *srv, const char *cardSrv, unsigned int argc, char *argv)
930094332d3Sopenharmony_ci{
931094332d3Sopenharmony_ci    int32_t ret;
932094332d3Sopenharmony_ci    struct AudioMixerCtlElemInfo infoData;
933094332d3Sopenharmony_ci
934094332d3Sopenharmony_ci    if (srv == NULL || cardSrv == NULL || argc == 0) {
935094332d3Sopenharmony_ci        DEBUG_LOG("Invalid parameters!\n");
936094332d3Sopenharmony_ci        return U_INVALID_PARAM;
937094332d3Sopenharmony_ci    }
938094332d3Sopenharmony_ci
939094332d3Sopenharmony_ci    DEBUG_LOG("argc = %u, argv = %s\n", argc, argv);
940094332d3Sopenharmony_ci    (void)memset_s(infoData.cardSrvName, AUDIO_CARD_SRV_NAME_LEN, 0, AUDIO_CARD_SRV_NAME_LEN);
941094332d3Sopenharmony_ci    ret = strncpy_s(infoData.cardSrvName, AUDIO_CARD_SRV_NAME_LEN, cardSrv, strlen(cardSrv) + 1);
942094332d3Sopenharmony_ci    if (ret != 0) {
943094332d3Sopenharmony_ci        DEBUG_LOG("strncpy_s card service name is faild!\n");
944094332d3Sopenharmony_ci        return U_FAILURE;
945094332d3Sopenharmony_ci    }
946094332d3Sopenharmony_ci    infoData.cardSrvName[AUDIO_CARD_SRV_NAME_LEN - 1] = '\0';
947094332d3Sopenharmony_ci
948094332d3Sopenharmony_ci    (void)memset_s(infoData.eIndexId.eId.name, AUDIO_ELEM_NAME_LEN, 0, AUDIO_ELEM_NAME_LEN);
949094332d3Sopenharmony_ci    ret = strncpy_s(
950094332d3Sopenharmony_ci        infoData.eIndexId.eId.name, AUDIO_ELEM_NAME_LEN, "Captrue Channel Mode", strlen("Captrue Channel Mode") + 1);
951094332d3Sopenharmony_ci    if (ret != 0) {
952094332d3Sopenharmony_ci        DEBUG_LOG("strncpy_s element name is failed!\n");
953094332d3Sopenharmony_ci        return U_FAILURE;
954094332d3Sopenharmony_ci    }
955094332d3Sopenharmony_ci    infoData.eIndexId.eId.iface = AUDIO_CTL_ELEM_IFACE_MIXER;
956094332d3Sopenharmony_ci    infoData.type = AUDIO_CTL_ELEM_TYPE_INTEGER;
957094332d3Sopenharmony_ci    ret = FillChnlsIntVal(&infoData, argc, argv);
958094332d3Sopenharmony_ci    if (ret != U_SUCCESS) {
959094332d3Sopenharmony_ci        return ret;
960094332d3Sopenharmony_ci    }
961094332d3Sopenharmony_ci
962094332d3Sopenharmony_ci    if (g_audioMixer.SetElemProp == NULL) {
963094332d3Sopenharmony_ci        DEBUG_LOG("The callback function is NULL!\n");
964094332d3Sopenharmony_ci        return U_FAILURE;
965094332d3Sopenharmony_ci    }
966094332d3Sopenharmony_ci    ret = g_audioMixer.SetElemProp(srv, &infoData);
967094332d3Sopenharmony_ci    if (ret != U_SUCCESS) {
968094332d3Sopenharmony_ci        return ret;
969094332d3Sopenharmony_ci    }
970094332d3Sopenharmony_ci
971094332d3Sopenharmony_ci    ret = strncpy_s(
972094332d3Sopenharmony_ci        infoData.eIndexId.eId.name, AUDIO_ELEM_NAME_LEN, "Render Channel Mode", strlen("Render Channel Mode") + 1);
973094332d3Sopenharmony_ci    if (ret != 0) {
974094332d3Sopenharmony_ci        DEBUG_LOG("strncpy_s element name is failed!\n");
975094332d3Sopenharmony_ci        return U_FAILURE;
976094332d3Sopenharmony_ci    }
977094332d3Sopenharmony_ci
978094332d3Sopenharmony_ci    return g_audioMixer.SetElemProp(srv, &infoData);
979094332d3Sopenharmony_ci}
980094332d3Sopenharmony_ci
981094332d3Sopenharmony_cistatic int32_t FillIntVal(struct AudioMixerCtlElemInfo *info, unsigned int argc, char *argv[])
982094332d3Sopenharmony_ci{
983094332d3Sopenharmony_ci    char *vals, *minPtr, *maxPtr, *stepPtr;
984094332d3Sopenharmony_ci    char *ptr = NULL;
985094332d3Sopenharmony_ci    char *outPtr = NULL;
986094332d3Sopenharmony_ci
987094332d3Sopenharmony_ci    if (argc != 2) {    // 2 for numbers of argc
988094332d3Sopenharmony_ci        DEBUG_LOG("Unable to set too much value!\n");
989094332d3Sopenharmony_ci        return U_FAILURE;
990094332d3Sopenharmony_ci    }
991094332d3Sopenharmony_ci
992094332d3Sopenharmony_ci    ptr = argv[argc - 1];
993094332d3Sopenharmony_ci    DEBUG_LOG("argv[%u] = %s\n", argc - 1, ptr);
994094332d3Sopenharmony_ci    vals = strtok_r(ptr, ",", &outPtr);
995094332d3Sopenharmony_ci    if (outPtr == NULL) {
996094332d3Sopenharmony_ci        info->value.intVal.vals[0] = strtol(ptr, NULL, STRTOL_BASE);
997094332d3Sopenharmony_ci        info->value.intVal.min = 0;
998094332d3Sopenharmony_ci        info->value.intVal.step = 0;
999094332d3Sopenharmony_ci
1000094332d3Sopenharmony_ci        return U_SUCCESS;
1001094332d3Sopenharmony_ci    }
1002094332d3Sopenharmony_ci
1003094332d3Sopenharmony_ci    info->value.intVal.vals[0] = strtol(vals, NULL, STRTOL_BASE);
1004094332d3Sopenharmony_ci    maxPtr = strtok_r(NULL, ",", &outPtr);
1005094332d3Sopenharmony_ci    if (outPtr == NULL) {
1006094332d3Sopenharmony_ci        info->value.intVal.max = (int32_t)strtol(maxPtr, NULL, STRTOL_BASE);
1007094332d3Sopenharmony_ci        info->value.intVal.min = 0;
1008094332d3Sopenharmony_ci        info->value.intVal.step = 0;
1009094332d3Sopenharmony_ci
1010094332d3Sopenharmony_ci        return U_SUCCESS;
1011094332d3Sopenharmony_ci    }
1012094332d3Sopenharmony_ci
1013094332d3Sopenharmony_ci    info->value.intVal.max = (int32_t)strtol(maxPtr, NULL, STRTOL_BASE);
1014094332d3Sopenharmony_ci    minPtr = strtok_r(NULL, ",", &outPtr);
1015094332d3Sopenharmony_ci    if (outPtr != NULL) {
1016094332d3Sopenharmony_ci        info->value.intVal.min = (int32_t)strtol(minPtr, NULL, STRTOL_BASE);
1017094332d3Sopenharmony_ci        stepPtr = strtok_r(NULL, ",", &outPtr);
1018094332d3Sopenharmony_ci        info->value.intVal.step = outPtr != NULL ? (int32_t)strtol(stepPtr, NULL, STRTOL_BASE) : 0;
1019094332d3Sopenharmony_ci    } else {
1020094332d3Sopenharmony_ci        info->value.intVal.min = (int32_t)strtol(minPtr, NULL, STRTOL_BASE);
1021094332d3Sopenharmony_ci        info->value.intVal.step = 0;
1022094332d3Sopenharmony_ci    }
1023094332d3Sopenharmony_ci
1024094332d3Sopenharmony_ci    return U_SUCCESS;
1025094332d3Sopenharmony_ci}
1026094332d3Sopenharmony_ci
1027094332d3Sopenharmony_cistatic int32_t FillEnumVal(struct AudioMixerCtlElemInfo *info, unsigned int argc, char *argv[])
1028094332d3Sopenharmony_ci{
1029094332d3Sopenharmony_ci    int32_t ret;
1030094332d3Sopenharmony_ci    unsigned int idx;
1031094332d3Sopenharmony_ci    char *ptr = NULL;
1032094332d3Sopenharmony_ci
1033094332d3Sopenharmony_ci    printf("\n");
1034094332d3Sopenharmony_ci    /* Multiple enumerated values are output line by line. */
1035094332d3Sopenharmony_ci    for (idx = 1; idx < argc; idx++) {
1036094332d3Sopenharmony_ci        ptr = argv[idx];
1037094332d3Sopenharmony_ci        // Control Settings with enumerated values.
1038094332d3Sopenharmony_ci        ret = strcpy_s(info->value.enumVal.name, AUDIO_ELEM_NAME_LEN - 1, ptr);
1039094332d3Sopenharmony_ci        if (ret != EOK) {
1040094332d3Sopenharmony_ci            printf("strcpy_s failed: argv = %s\n", ptr);
1041094332d3Sopenharmony_ci        } else {
1042094332d3Sopenharmony_ci            printf("%s\n", ptr);
1043094332d3Sopenharmony_ci        }
1044094332d3Sopenharmony_ci    }
1045094332d3Sopenharmony_ci
1046094332d3Sopenharmony_ci    return U_SUCCESS;
1047094332d3Sopenharmony_ci}
1048094332d3Sopenharmony_ci
1049094332d3Sopenharmony_cistatic int32_t FillBytesVal(unsigned char *buf, unsigned int argc, char *argv[])
1050094332d3Sopenharmony_ci{
1051094332d3Sopenharmony_ci    int32_t ret;
1052094332d3Sopenharmony_ci    size_t len;
1053094332d3Sopenharmony_ci    unsigned int idx;
1054094332d3Sopenharmony_ci    unsigned char *ptr = buf;
1055094332d3Sopenharmony_ci    char *sptr = NULL;
1056094332d3Sopenharmony_ci    size_t size = RESERVED_BUF_LEN;
1057094332d3Sopenharmony_ci
1058094332d3Sopenharmony_ci    /* Multiple input parameters are separated and combined with a ",". */
1059094332d3Sopenharmony_ci    for (idx = 1; idx < argc; idx++) {
1060094332d3Sopenharmony_ci        sptr = argv[idx];
1061094332d3Sopenharmony_ci        len = strlen(argv[idx]);
1062094332d3Sopenharmony_ci        if (size <= len) {
1063094332d3Sopenharmony_ci            DEBUG_LOG("The callback function is NULL!\n");
1064094332d3Sopenharmony_ci            break;
1065094332d3Sopenharmony_ci        }
1066094332d3Sopenharmony_ci        ret = strncpy_s((char *)ptr, RESERVED_BUF_LEN - 1, sptr, len);
1067094332d3Sopenharmony_ci        if (ret != 0) {
1068094332d3Sopenharmony_ci            DEBUG_LOG("strncpy_s faild!\n");
1069094332d3Sopenharmony_ci            return U_FAILURE;
1070094332d3Sopenharmony_ci        }
1071094332d3Sopenharmony_ci        ptr += len;
1072094332d3Sopenharmony_ci        *ptr++ = ',';
1073094332d3Sopenharmony_ci        size -= len + 1;
1074094332d3Sopenharmony_ci    }
1075094332d3Sopenharmony_ci    if (idx < argc) {
1076094332d3Sopenharmony_ci        DEBUG_LOG("Unable to set too much data!\n");
1077094332d3Sopenharmony_ci        return U_FAILURE;
1078094332d3Sopenharmony_ci    }
1079094332d3Sopenharmony_ci    printf("data buf = %s\n", buf);
1080094332d3Sopenharmony_ci
1081094332d3Sopenharmony_ci    return U_SUCCESS;
1082094332d3Sopenharmony_ci}
1083094332d3Sopenharmony_ci
1084094332d3Sopenharmony_ci
1085094332d3Sopenharmony_ciint32_t MctlSetElem(const struct HdfIoService *srv,
1086094332d3Sopenharmony_ci                    struct MixerCardCtlInfo *ctlInfo,
1087094332d3Sopenharmony_ci                    unsigned int argc, char *argv[])
1088094332d3Sopenharmony_ci{
1089094332d3Sopenharmony_ci    int32_t ret;
1090094332d3Sopenharmony_ci    struct AudioMixerCtlElemInfo infoData;
1091094332d3Sopenharmony_ci
1092094332d3Sopenharmony_ci    if (srv == NULL || ctlInfo == NULL || argc == 0) {
1093094332d3Sopenharmony_ci        DEBUG_LOG("Invalid parameters!\n");
1094094332d3Sopenharmony_ci        return U_INVALID_PARAM;
1095094332d3Sopenharmony_ci    }
1096094332d3Sopenharmony_ci
1097094332d3Sopenharmony_ci    ret = strncpy_s(infoData.cardSrvName, AUDIO_CARD_SRV_NAME_LEN, ctlInfo->cardSrvName, AUDIO_CARD_SRV_NAME_LEN);
1098094332d3Sopenharmony_ci    if (ret != 0) {
1099094332d3Sopenharmony_ci        DEBUG_LOG("strncpy_s card service name is faild!\n");
1100094332d3Sopenharmony_ci        return U_FAILURE;
1101094332d3Sopenharmony_ci    }
1102094332d3Sopenharmony_ci    infoData.cardSrvName[AUDIO_CARD_SRV_NAME_LEN - 1] = '\0';
1103094332d3Sopenharmony_ci
1104094332d3Sopenharmony_ci    ret = strncpy_s(infoData.eIndexId.eId.name, AUDIO_ELEM_NAME_LEN, ctlInfo->edx.eId.name, AUDIO_ELEM_NAME_LEN);
1105094332d3Sopenharmony_ci    if (ret != 0) {
1106094332d3Sopenharmony_ci        DEBUG_LOG("strncpy_s element name is failed!\n");
1107094332d3Sopenharmony_ci        return U_FAILURE;
1108094332d3Sopenharmony_ci    }
1109094332d3Sopenharmony_ci    infoData.eIndexId.eId.name[AUDIO_ELEM_NAME_LEN - 1] = '\0';
1110094332d3Sopenharmony_ci    infoData.eIndexId.eId.iface = AUDIO_CTL_ELEM_IFACE_MIXER;
1111094332d3Sopenharmony_ci
1112094332d3Sopenharmony_ci    // First, read the value type.(infoData.type)
1113094332d3Sopenharmony_ci    infoData.type = AUDIO_CTL_ELEM_TYPE_INTEGER;
1114094332d3Sopenharmony_ci    switch (infoData.type) {
1115094332d3Sopenharmony_ci        case AUDIO_CTL_ELEM_TYPE_INTEGER:
1116094332d3Sopenharmony_ci        case AUDIO_CTL_ELEM_TYPE_BOOLEAN:
1117094332d3Sopenharmony_ci            ret = FillIntVal(&infoData, argc, argv);
1118094332d3Sopenharmony_ci            break;
1119094332d3Sopenharmony_ci        case AUDIO_CTL_ELEM_TYPE_ENUMERATED:
1120094332d3Sopenharmony_ci            ret = FillEnumVal(&infoData, argc, argv);
1121094332d3Sopenharmony_ci            break;
1122094332d3Sopenharmony_ci        case AUDIO_CTL_ELEM_TYPE_BYTES:
1123094332d3Sopenharmony_ci            ret = FillBytesVal(infoData.value.reserved, argc, argv);
1124094332d3Sopenharmony_ci            break;
1125094332d3Sopenharmony_ci        default:
1126094332d3Sopenharmony_ci            ret = U_FAILURE;
1127094332d3Sopenharmony_ci            break;
1128094332d3Sopenharmony_ci    }
1129094332d3Sopenharmony_ci    if (ret != U_SUCCESS) {
1130094332d3Sopenharmony_ci        DEBUG_LOG("The value type does not match!\n");
1131094332d3Sopenharmony_ci        return U_FAILURE;
1132094332d3Sopenharmony_ci    }
1133094332d3Sopenharmony_ci
1134094332d3Sopenharmony_ci    if (g_audioMixer.SetElemProp == NULL) {
1135094332d3Sopenharmony_ci        DEBUG_LOG("The callback function is NULL!\n");
1136094332d3Sopenharmony_ci        return U_FAILURE;
1137094332d3Sopenharmony_ci    }
1138094332d3Sopenharmony_ci
1139094332d3Sopenharmony_ci    return g_audioMixer.SetElemProp(srv, &infoData);
1140094332d3Sopenharmony_ci}
1141094332d3Sopenharmony_ci
1142094332d3Sopenharmony_cistatic char *SkipSpecifyStr(const char *src, const char *needle)
1143094332d3Sopenharmony_ci{
1144094332d3Sopenharmony_ci    char *p = NULL;
1145094332d3Sopenharmony_ci
1146094332d3Sopenharmony_ci    p = strstr(src, needle);
1147094332d3Sopenharmony_ci    if (p != NULL) {
1148094332d3Sopenharmony_ci        p += strlen(needle);
1149094332d3Sopenharmony_ci    }
1150094332d3Sopenharmony_ci
1151094332d3Sopenharmony_ci    return p;
1152094332d3Sopenharmony_ci}
1153094332d3Sopenharmony_ci
1154094332d3Sopenharmony_cistatic int32_t GetSndCardType(const char *name, char *buf, uint32_t len)
1155094332d3Sopenharmony_ci{
1156094332d3Sopenharmony_ci    int32_t ret;
1157094332d3Sopenharmony_ci    char *ptr = NULL;
1158094332d3Sopenharmony_ci    char *out = NULL;
1159094332d3Sopenharmony_ci
1160094332d3Sopenharmony_ci    if (name == NULL || buf == NULL || len == 0) {
1161094332d3Sopenharmony_ci        DEBUG_LOG("Invalid parameters!\n");
1162094332d3Sopenharmony_ci        return U_INVALID_PARAM;
1163094332d3Sopenharmony_ci    }
1164094332d3Sopenharmony_ci
1165094332d3Sopenharmony_ci    ptr = SkipSpecifyStr(name, MIXER_SRV_NAME_PRE);
1166094332d3Sopenharmony_ci    if (ptr == NULL) {
1167094332d3Sopenharmony_ci        DEBUG_LOG("No found card type!\n");
1168094332d3Sopenharmony_ci        return U_FAILURE;
1169094332d3Sopenharmony_ci    }
1170094332d3Sopenharmony_ci
1171094332d3Sopenharmony_ci    ret = memcpy_s(buf, len, ptr, strlen(ptr) + 1);
1172094332d3Sopenharmony_ci    if (ret != EOK) {
1173094332d3Sopenharmony_ci        DEBUG_LOG("memcpy_s fail!\n");
1174094332d3Sopenharmony_ci        return U_FAILURE;
1175094332d3Sopenharmony_ci    }
1176094332d3Sopenharmony_ci    ptr = strtok_r(buf, "_", &out);
1177094332d3Sopenharmony_ci    ret = memcpy_s(buf, len, ptr, strlen(ptr) + 1);
1178094332d3Sopenharmony_ci    if (ret != EOK) {
1179094332d3Sopenharmony_ci        DEBUG_LOG("memcpy_s fail!\n");
1180094332d3Sopenharmony_ci        return U_FAILURE;
1181094332d3Sopenharmony_ci    }
1182094332d3Sopenharmony_ci
1183094332d3Sopenharmony_ci    return U_SUCCESS;
1184094332d3Sopenharmony_ci}
1185094332d3Sopenharmony_ci
1186094332d3Sopenharmony_cistatic void ShowAllAdapters(struct SndCardsList *sndList)
1187094332d3Sopenharmony_ci{
1188094332d3Sopenharmony_ci    int32_t i, ret;
1189094332d3Sopenharmony_ci    uint32_t cnums;
1190094332d3Sopenharmony_ci    char ctype[AUDIO_BASE_LEN] = {0};
1191094332d3Sopenharmony_ci    struct AudioCardId *clist = NULL;
1192094332d3Sopenharmony_ci
1193094332d3Sopenharmony_ci    if (sndList->cardNums == 0 || sndList->cardsList == NULL) {
1194094332d3Sopenharmony_ci        DEBUG_LOG("No sound cards found...!\n");
1195094332d3Sopenharmony_ci        goto end;
1196094332d3Sopenharmony_ci    }
1197094332d3Sopenharmony_ci
1198094332d3Sopenharmony_ci    cnums = sndList->cardNums;
1199094332d3Sopenharmony_ci    clist = sndList->cardsList;
1200094332d3Sopenharmony_ci    printf("****** List of Audio Hardware Devices ******\n");
1201094332d3Sopenharmony_ci    /* To keep the primary sound card always in front of the total,
1202094332d3Sopenharmony_ci     * output it in the following order.
1203094332d3Sopenharmony_ci     */
1204094332d3Sopenharmony_ci    for (i = (int32_t)cnums - 1; i >= 0; i--) {
1205094332d3Sopenharmony_ci        (void)memset_s(ctype, AUDIO_BASE_LEN, 0, AUDIO_BASE_LEN);
1206094332d3Sopenharmony_ci        ret = GetSndCardType(clist[i].cardName, ctype, AUDIO_BASE_LEN);
1207094332d3Sopenharmony_ci        if (ret != U_SUCCESS) {
1208094332d3Sopenharmony_ci            goto end;
1209094332d3Sopenharmony_ci        }
1210094332d3Sopenharmony_ci        printf("card %i: %s [%s], device 0\n", clist[i].index, ctype, clist[i].cardName);
1211094332d3Sopenharmony_ci        printf("  Subdevices: 1/1\n");
1212094332d3Sopenharmony_ci        printf("  Subdevice #0: subdevice #0\n");
1213094332d3Sopenharmony_ci    }
1214094332d3Sopenharmony_ci
1215094332d3Sopenharmony_ciend:
1216094332d3Sopenharmony_ci    if (sndList->cardsList != NULL) {
1217094332d3Sopenharmony_ci        free(sndList->cardsList);
1218094332d3Sopenharmony_ci        sndList->cardsList = NULL;
1219094332d3Sopenharmony_ci    }
1220094332d3Sopenharmony_ci}
1221094332d3Sopenharmony_ci
1222094332d3Sopenharmony_ciint32_t GetAllCards(const struct HdfIoService *service)
1223094332d3Sopenharmony_ci{
1224094332d3Sopenharmony_ci    int32_t ret;
1225094332d3Sopenharmony_ci    struct SndCardsList sndcards;
1226094332d3Sopenharmony_ci    int32_t (*GetAllAdapters)(const struct HdfIoService *, struct SndCardsList *);
1227094332d3Sopenharmony_ci
1228094332d3Sopenharmony_ci    if (service == NULL) {
1229094332d3Sopenharmony_ci        DEBUG_LOG("Invalid parameter!\n");
1230094332d3Sopenharmony_ci        return U_INVALID_PARAM;
1231094332d3Sopenharmony_ci    }
1232094332d3Sopenharmony_ci
1233094332d3Sopenharmony_ci    GetAllAdapters = CallLibFunction("AudioMixerGetAllAdapters");
1234094332d3Sopenharmony_ci    if (GetAllAdapters == NULL) {
1235094332d3Sopenharmony_ci        return U_FAILURE;
1236094332d3Sopenharmony_ci    }
1237094332d3Sopenharmony_ci
1238094332d3Sopenharmony_ci    (void)memset_s(&sndcards, sizeof(struct SndCardsList), 0, sizeof(struct SndCardsList));
1239094332d3Sopenharmony_ci    ret = GetAllAdapters(service, &sndcards);
1240094332d3Sopenharmony_ci    if (ret != U_SUCCESS) {
1241094332d3Sopenharmony_ci        DEBUG_LOG("Description Failed to obtain the sound card list!\n");
1242094332d3Sopenharmony_ci        return U_FAILURE;
1243094332d3Sopenharmony_ci    }
1244094332d3Sopenharmony_ci    ShowAllAdapters(&sndcards);
1245094332d3Sopenharmony_ci
1246094332d3Sopenharmony_ci    return U_SUCCESS;
1247094332d3Sopenharmony_ci}
1248094332d3Sopenharmony_ci
1249094332d3Sopenharmony_cistatic char *FindSpecificCardName(int card, struct SndCardsList *cardList)
1250094332d3Sopenharmony_ci{
1251094332d3Sopenharmony_ci    int32_t i;
1252094332d3Sopenharmony_ci    uint32_t cnums;
1253094332d3Sopenharmony_ci    struct AudioCardId *clist = NULL;
1254094332d3Sopenharmony_ci
1255094332d3Sopenharmony_ci    if (cardList->cardNums == 0 || cardList->cardsList == NULL) {
1256094332d3Sopenharmony_ci        DEBUG_LOG("No sound cards found...!\n");
1257094332d3Sopenharmony_ci        goto end;
1258094332d3Sopenharmony_ci    }
1259094332d3Sopenharmony_ci
1260094332d3Sopenharmony_ci    cnums = cardList->cardNums;
1261094332d3Sopenharmony_ci    clist = cardList->cardsList;
1262094332d3Sopenharmony_ci    for (i = 0; i < (int32_t)cnums; i++) {
1263094332d3Sopenharmony_ci        if (card == clist[i].index) {
1264094332d3Sopenharmony_ci            DEBUG_LOG("I found this sound card. [card%i: %s]\n", card, clist[i].cardName);
1265094332d3Sopenharmony_ci            return clist[i].cardName;
1266094332d3Sopenharmony_ci        }
1267094332d3Sopenharmony_ci    }
1268094332d3Sopenharmony_ci
1269094332d3Sopenharmony_ciend:
1270094332d3Sopenharmony_ci    if (cardList->cardsList != NULL) {
1271094332d3Sopenharmony_ci        free(cardList->cardsList);
1272094332d3Sopenharmony_ci        cardList->cardsList = NULL;
1273094332d3Sopenharmony_ci    }
1274094332d3Sopenharmony_ci    cardList->cardNums = 0;
1275094332d3Sopenharmony_ci
1276094332d3Sopenharmony_ci    return NULL;
1277094332d3Sopenharmony_ci}
1278094332d3Sopenharmony_ci
1279094332d3Sopenharmony_civoid UpdateCardSname(int card, const struct HdfIoService *srv, char * const sname, size_t snameLen)
1280094332d3Sopenharmony_ci{
1281094332d3Sopenharmony_ci    int32_t ret;
1282094332d3Sopenharmony_ci    struct SndCardsList cardList;
1283094332d3Sopenharmony_ci    int32_t (*GetAllCardsFunc)(const struct HdfIoService *, struct SndCardsList *);
1284094332d3Sopenharmony_ci    char *cname = NULL;
1285094332d3Sopenharmony_ci
1286094332d3Sopenharmony_ci    if (card < 0 || srv == NULL || sname == NULL || snameLen == 0) {
1287094332d3Sopenharmony_ci        DEBUG_LOG("Invalid parameter!\n");
1288094332d3Sopenharmony_ci        return;
1289094332d3Sopenharmony_ci    }
1290094332d3Sopenharmony_ci
1291094332d3Sopenharmony_ci    GetAllCardsFunc = CallLibFunction("AudioMixerGetAllAdapters");
1292094332d3Sopenharmony_ci    if (GetAllCardsFunc == NULL) {
1293094332d3Sopenharmony_ci        DEBUG_LOG("Description Failed to obtain the current sound card list of the system!\n");
1294094332d3Sopenharmony_ci        return;
1295094332d3Sopenharmony_ci    }
1296094332d3Sopenharmony_ci
1297094332d3Sopenharmony_ci    (void)memset_s(&cardList, sizeof(struct SndCardsList), 0, sizeof(struct SndCardsList));
1298094332d3Sopenharmony_ci    ret = GetAllCardsFunc(srv, &cardList);
1299094332d3Sopenharmony_ci    if (ret != U_SUCCESS) {
1300094332d3Sopenharmony_ci        DEBUG_LOG("Update failed: Description Failed to obtain the sound card list!\n");
1301094332d3Sopenharmony_ci        return;
1302094332d3Sopenharmony_ci    }
1303094332d3Sopenharmony_ci
1304094332d3Sopenharmony_ci    cname = FindSpecificCardName(card, &cardList);
1305094332d3Sopenharmony_ci    if (cname == NULL) {
1306094332d3Sopenharmony_ci        DEBUG_LOG("Update failed: The corresponding sound card cannot be matched!\n");
1307094332d3Sopenharmony_ci        return;
1308094332d3Sopenharmony_ci    }
1309094332d3Sopenharmony_ci
1310094332d3Sopenharmony_ci    ret = memcpy_s(sname, snameLen, cname, strlen(cname) + 1);
1311094332d3Sopenharmony_ci    if (ret != EOK) {
1312094332d3Sopenharmony_ci        DEBUG_LOG("Update failed: memcpy_s fail!\n");
1313094332d3Sopenharmony_ci    }
1314094332d3Sopenharmony_ci    sname[snameLen - 1] = '\0';
1315094332d3Sopenharmony_ci    if (g_debugFlag) {
1316094332d3Sopenharmony_ci        printf("|--> [%s]\n", sname);
1317094332d3Sopenharmony_ci    }
1318094332d3Sopenharmony_ci
1319094332d3Sopenharmony_ci    if (cardList.cardsList != NULL) {
1320094332d3Sopenharmony_ci        free(cardList.cardsList);
1321094332d3Sopenharmony_ci        cardList.cardsList = NULL;
1322094332d3Sopenharmony_ci    }
1323094332d3Sopenharmony_ci    cardList.cardNums = 0;
1324094332d3Sopenharmony_ci}
1325