1/*
2 * Copyright (c) 2022 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 "alsa_soundcard.h"
17#include <ctype.h>
18#include "cJSON.h"
19
20#define HDF_LOG_TAG HDF_AUDIO_HAL_SND
21
22#define ALSA_CARD_CONFIG_FILE HDF_CONFIG_DIR "/alsa_adapter.json"
23#define ALSA_CONFIG_FILE_MAX  (2 * 1024) // 2KB
24#define SUPPORT_CAPTURE_OR_RENDER  1
25#define SUPPORT_CAPTURE_AND_RENDER 2
26#define MALLOC_MAX 100
27
28/* Define structure description alsa_adapter.hson information  */
29struct AlsaAdapterCfgInfo {
30    char adapterName[MAX_CARD_NAME_LEN];
31    int32_t cardId;
32    char cardName[MAX_CARD_NAME_LEN];
33};
34struct AlsaAdapterList {
35    int32_t num;
36    struct AlsaAdapterCfgInfo list[AUDIO_MAX_CARD_NUM];
37};
38static struct AlsaAdapterList g_alsaAdapterList[SND_CARD_MAX];
39
40struct AlsaDevInfo {
41    char cardId[MAX_CARD_NAME_LEN + 1];
42    char pcmInfoId[MAX_CARD_NAME_LEN + 1];
43    int32_t card;
44    int32_t device;
45};
46struct AlsaCardsList {
47    int32_t num;
48    struct AlsaDevInfo alsaDevIns[MAX_CARD_NUM];
49};
50static struct AlsaCardsList g_alsaCardsDevList;
51
52
53static char *CfgReadAdapterFile(const char *fpath)
54{
55    FILE *fp = NULL;
56    char *pJsonStr = NULL;
57    char pathBuf[PATH_MAX] = {0};
58
59    if (fpath == NULL) {
60        AUDIO_FUNC_LOGE("Parameter is null!!!");
61        return NULL;
62    }
63    if (realpath(fpath, pathBuf) == NULL) {
64        AUDIO_FUNC_LOGE("File path invalid!");
65        return NULL;
66    }
67
68    fp = fopen(pathBuf, "r");
69    if (fp == NULL) {
70        AUDIO_FUNC_LOGE("Can not open config file [ %{public}s ].", fpath);
71        return NULL;
72    }
73    if (fseek(fp, 0, SEEK_END) != 0) {
74        AUDIO_FUNC_LOGE("fseek configuration file error!");
75        (void)fclose(fp);
76        return NULL;
77    }
78    int32_t jsonStrSize = ftell(fp);
79    if (jsonStrSize <= 0) {
80        AUDIO_FUNC_LOGE("The configuration file size <= 0!");
81        (void)fclose(fp);
82        return NULL;
83    }
84    rewind(fp);
85    if (jsonStrSize > ALSA_CONFIG_FILE_MAX) {
86        AUDIO_FUNC_LOGE("The configuration file is too large to load!");
87        (void)fclose(fp);
88        return NULL;
89    }
90    pJsonStr = (char *)OsalMemCalloc((uint32_t)jsonStrSize + 1);
91    if (pJsonStr == NULL) {
92        AUDIO_FUNC_LOGE("OsalMemCalloc pJsonStr failed!");
93        (void)fclose(fp);
94        return NULL;
95    }
96    if (fread(pJsonStr, jsonStrSize, 1, fp) != 1) {
97        AUDIO_FUNC_LOGE("Read to config file failed!!!");
98        (void)fclose(fp);
99        AudioMemFree((void **)&pJsonStr);
100        return NULL;
101    }
102    (void)fclose(fp);
103
104    return pJsonStr;
105}
106
107static int32_t CfgGetAdapterCount()
108{
109    int32_t num = 0;
110    for (enum SndCardType type = SND_CARD_PRIMARY; type < SND_CARD_MAX; ++type) {
111        num += g_alsaAdapterList[type].num;
112    }
113    return num;
114}
115
116static enum SndCardType CfgGetAdapterCardType(const char* adapterName)
117{
118    if (adapterName == NULL) {
119        return SND_CARD_UNKNOWN;
120    }
121
122    struct AlsaAdapterCfgInfo *info;
123    for (enum SndCardType type = SND_CARD_PRIMARY; type < SND_CARD_MAX; ++type) {
124        for (int32_t i = 0; i < g_alsaAdapterList[type].num; ++i) {
125            info = &g_alsaAdapterList[type].list[i];
126            if (strncmp(adapterName, info->adapterName, strlen(info->adapterName)) == 0) {
127                return type;
128            }
129        }
130    }
131    return SND_CARD_UNKNOWN;
132}
133
134static int CfgGetAdapterInfo(const char* adapterName, struct AlsaAdapterCfgInfo infos[], int infoLen)
135{
136    if (adapterName == NULL) {
137        return 0;
138    }
139
140    struct AlsaAdapterCfgInfo *info;
141    int index = 0;
142    for (enum SndCardType type = SND_CARD_PRIMARY; type < SND_CARD_MAX; ++type) {
143        for (int32_t i = 0; i < g_alsaAdapterList[type].num; ++i) {
144            info = &g_alsaAdapterList[type].list[i];
145            if (strncmp(adapterName, info->adapterName, strlen(info->adapterName)) == 0
146                && index < infoLen) {
147                infos[index++] = *info;
148            }
149        }
150    }
151    return index;
152}
153
154static int32_t CfgDumpAdapterInfo(struct AlsaAdapterCfgInfo *info)
155{
156    enum SndCardType cardType = SND_CARD_UNKNOWN;
157    CHECK_NULL_PTR_RETURN_DEFAULT(info);
158
159    if (strcmp(info->adapterName, PRIMARY) == 0) {
160        cardType = SND_CARD_PRIMARY;
161    } else if (strcmp(info->adapterName, HDMI) == 0) {
162        cardType = SND_CARD_HDMI;
163    } else if (strcmp(info->adapterName, USB) == 0) {
164        cardType = SND_CARD_USB;
165    } else if (strcmp(info->adapterName, A2DP) == 0) {
166        cardType = SND_CARD_BT;
167    }
168
169    if (cardType == SND_CARD_UNKNOWN) {
170        AUDIO_FUNC_LOGE("Error: %{public}s is unspupported adapter name", info->adapterName);
171    }
172
173    int32_t idx = g_alsaAdapterList[cardType].num;
174    int32_t ret = memcpy_s((void*)&g_alsaAdapterList[cardType].list[idx], sizeof(struct AlsaAdapterCfgInfo),
175        (void*)info, sizeof(struct AlsaAdapterCfgInfo));
176    if (ret != EOK) {
177        AUDIO_FUNC_LOGE("memcpy_s g_alsaAdapterList fail!");
178        return HDF_FAILURE;
179    }
180    g_alsaAdapterList[cardType].num++;
181
182    AUDIO_FUNC_LOGI("cardId:%{public}d: adapterName:%{public}s, cardName:%{public}s",
183        g_alsaAdapterList[cardType].list[idx].cardId,
184        g_alsaAdapterList[cardType].list[idx].adapterName,
185        g_alsaAdapterList[cardType].list[idx].cardName);
186    return HDF_SUCCESS;
187}
188
189static int32_t CfgSaveAdapterStruct(cJSON *adapter, struct AlsaAdapterCfgInfo *info)
190{
191    CHECK_NULL_PTR_RETURN_DEFAULT(adapter);
192    CHECK_NULL_PTR_RETURN_DEFAULT(info);
193
194    cJSON *item = cJSON_GetObjectItem(adapter, "name");
195    if (item == NULL || item->valuestring == NULL) {
196        AUDIO_FUNC_LOGE("adapter name is null!");
197        return HDF_FAILURE;
198    }
199    int32_t ret = memcpy_s(info->adapterName, MAX_CARD_NAME_LEN - 1, item->valuestring, MAX_CARD_NAME_LEN - 1);
200    if (ret != EOK) {
201        AUDIO_FUNC_LOGE("memcpy_s adapterName fail!");
202        return HDF_FAILURE;
203    }
204
205    item = cJSON_GetObjectItem(adapter, "cardId");
206    if (item == NULL) {
207        AUDIO_FUNC_LOGE("cardId not set!");
208        return HDF_FAILURE;
209    }
210    info->cardId = item->valuedouble;
211
212    item = cJSON_GetObjectItem(adapter, "cardName");
213    if (item == NULL || item->valuestring == NULL) {
214        AUDIO_FUNC_LOGE("cardName is null!");
215        return HDF_FAILURE;
216    }
217    ret = memcpy_s(info->cardName, MAX_CARD_NAME_LEN - 1, item->valuestring, MAX_CARD_NAME_LEN - 1);
218    if (ret != EOK) {
219        AUDIO_FUNC_LOGE("memcpy_s cardName fail!");
220        return HDF_FAILURE;
221    }
222
223    return HDF_SUCCESS;
224}
225
226static int32_t CfgParseAdapterItems(cJSON *adapterObj)
227{
228    cJSON *adapterItems = NULL;
229
230    adapterItems = cJSON_GetObjectItem(adapterObj, "adapters");
231    if (adapterItems == NULL) {
232        AUDIO_FUNC_LOGE("Get adapterItems from json failed!\n");
233        return HDF_FAILURE;
234    }
235    int32_t adapterNum = cJSON_GetArraySize(adapterItems);
236    if (adapterNum <= 0) {
237        AUDIO_FUNC_LOGE("Get adapter number failed!");
238        return HDF_FAILURE;
239    } else if (adapterNum > MAX_CARD_NUM) {
240        AUDIO_FUNC_LOGE("Read adapters number is %{public}d over max num %{public}d!", adapterNum, MAX_CARD_NUM);
241        return HDF_FAILURE;
242    }
243
244    for (int32_t i = 0; i < adapterNum; ++i) {
245        cJSON *adapter;
246        struct AlsaAdapterCfgInfo info;
247        adapter = cJSON_GetArrayItem(adapterItems, i);
248        if (adapter == NULL) {
249            AUDIO_FUNC_LOGE("Get adapter item from array failed!");
250        }
251
252        int32_t ret = CfgSaveAdapterStruct(adapter, &info);
253        if (ret != HDF_SUCCESS) {
254            AUDIO_FUNC_LOGE("CfgSaveAdapterStruct failed!");
255            return HDF_FAILURE;
256        }
257
258        ret = CfgDumpAdapterInfo(&info);
259        if (ret != HDF_SUCCESS) {
260            AUDIO_FUNC_LOGE("CfgDumpAdapterInfo failed!");
261            return HDF_FAILURE;
262        }
263    }
264
265    return HDF_SUCCESS;
266}
267
268int32_t CfgSaveAdapterFromFile(void)
269{
270    cJSON *adapterObj = NULL;
271    char *configBuf = NULL;
272
273    configBuf = CfgReadAdapterFile(ALSA_CARD_CONFIG_FILE);
274    if (configBuf == NULL) {
275        AUDIO_FUNC_LOGE("CfgReadAdapterFile failed!");
276        return HDF_FAILURE;
277    }
278    adapterObj = cJSON_Parse(configBuf);
279    if (adapterObj == NULL) {
280        AUDIO_FUNC_LOGE("Parse json file failed!");
281        AudioMemFree((void **)&configBuf);
282        return HDF_FAILURE;
283    }
284    AudioMemFree((void **)&configBuf);
285
286    int32_t ret = CfgParseAdapterItems(adapterObj);
287    if (ret != HDF_SUCCESS) {
288        cJSON_Delete(adapterObj);
289        AUDIO_FUNC_LOGE("Parse adapter items failed!");
290        return HDF_FAILURE;
291    }
292
293    cJSON_Delete(adapterObj);
294    return HDF_SUCCESS;
295}
296
297static struct AlsaDevInfo *DevGetInfoByAdapter(struct AlsaAdapterCfgInfo infos[], int32_t size)
298{
299    struct AlsaDevInfo *info = NULL;
300    int num = g_alsaCardsDevList.num;
301    for (int i = 0; i < num; ++i) {
302        info = &g_alsaCardsDevList.alsaDevIns[i];
303        for (int j = 0; j < size; ++j) {
304            if (info->card == infos[j].cardId) {
305                return info;
306            }
307        }
308    }
309    return NULL;
310}
311
312static struct AlsaDevInfo *DevGetInfoByPcmInfoId(const char * name)
313{
314    struct AlsaDevInfo *info = NULL;
315    int num = g_alsaCardsDevList.num;
316    for (int i = 0; i < num; ++i) {
317        info = &g_alsaCardsDevList.alsaDevIns[i];
318        if (strcmp(name, info->pcmInfoId) == 0) {
319            return info;
320        }
321    }
322
323    return NULL;
324}
325
326static int32_t DevSaveCardPcmInfo(snd_ctl_t *handle, snd_pcm_stream_t stream, int card, const char *deviceName)
327{
328    int pcmDev = -1;
329    snd_ctl_card_info_t *info = NULL;
330    snd_pcm_info_t *pcminfo = NULL;
331    snd_ctl_card_info_alloca(&info);
332    snd_pcm_info_alloca(&pcminfo);
333
334    if (snd_ctl_card_info(handle, info) != 0) {
335        AUDIO_FUNC_LOGE("snd_ctl_card_info failed.");
336        return HDF_FAILURE;
337    }
338    if (snd_ctl_pcm_next_device(handle, &pcmDev) < 0 || pcmDev < 0) {
339        AUDIO_FUNC_LOGE("No pcm device found");
340        return HDF_FAILURE;
341    }
342    while (pcmDev >= 0) {
343        snd_pcm_info_set_device(pcminfo, pcmDev);
344        snd_pcm_info_set_subdevice(pcminfo, 0);
345        snd_pcm_info_set_stream(pcminfo, stream);
346        int32_t ret = snd_ctl_pcm_info(handle, pcminfo);
347        if (ret < 0) {
348            if (ret != -ENOENT) {
349                AUDIO_FUNC_LOGE("control digital audio info (%{public}d)", pcmDev);
350            }
351        } else {
352            struct AlsaDevInfo *devInfo = &g_alsaCardsDevList.alsaDevIns[g_alsaCardsDevList.num];
353            const char *cardId = snd_ctl_card_info_get_id(info);
354            const char *pcmInfoId = snd_pcm_info_get_id(pcminfo);
355            AUDIO_FUNC_LOGD("alsa cardName: %{public}s, pcmInfoId %{public}s", cardId, pcmInfoId);
356            devInfo->card = card;
357            devInfo->device = pcmDev;
358            if (strncpy_s(devInfo->cardId, MAX_CARD_NAME_LEN + 1, cardId, strlen(cardId)) != 0) {
359                AUDIO_FUNC_LOGE("strncpy_s failed!");
360                return HDF_FAILURE;
361            }
362            if (strncpy_s(devInfo->pcmInfoId, MAX_CARD_NAME_LEN + 1, pcmInfoId, strlen(pcmInfoId)) != 0) {
363                AUDIO_FUNC_LOGE("strncpy_s failed!");
364                return HDF_FAILURE;
365            }
366            g_alsaCardsDevList.num++;
367        }
368
369        if (snd_ctl_pcm_next_device(handle, &pcmDev) < 0) {
370            AUDIO_FUNC_LOGE("snd_ctl_pcm_next_device error!");
371            return HDF_FAILURE;
372        }
373        AUDIO_FUNC_LOGD("soundcard pcm device number: %{public}d.", pcmDev);
374    }
375    return HDF_SUCCESS;
376}
377
378static int32_t DevSaveDriverInfo(snd_pcm_stream_t stream)
379{
380    snd_ctl_t *handle = NULL;
381    int card = -1;
382    char deviceName[MAX_CARD_NAME_LEN] = {0};
383
384    int32_t ret = snd_card_next(&card);
385    if (ret < 0 || card < 0) {
386        AUDIO_FUNC_LOGE("No soundcards found: %{public}s.", snd_strerror(ret));
387        return HDF_FAILURE;
388    }
389
390    while (card >= 0) {
391        (void)memset_s(deviceName, MAX_CARD_NAME_LEN, 0, MAX_CARD_NAME_LEN);
392        ret = snprintf_s(deviceName, MAX_CARD_NAME_LEN, MAX_CARD_NAME_LEN - 1, "hw:%d", card);
393        if (ret < 0) {
394            AUDIO_FUNC_LOGE("snprintf_s failed");
395            snd_ctl_close(handle);
396            return HDF_FAILURE;
397        }
398
399        ret = snd_ctl_open(&handle, deviceName, 0);
400        if (ret != 0) {
401            AUDIO_FUNC_LOGE("snd_ctl_open failed.");
402            return HDF_FAILURE;
403        }
404
405        ret = DevSaveCardPcmInfo(handle, stream, card, deviceName);
406        if (ret != HDF_SUCCESS) {
407            AUDIO_FUNC_LOGE("save alsa sound cards %{public}s pcm info failed!", deviceName);
408        }
409
410        ret = snd_ctl_close(handle);
411        if (ret < 0) {
412            AUDIO_FUNC_LOGE("snd_ctl_close error: %{public}s.", snd_strerror(ret));
413            return HDF_FAILURE;
414        }
415
416        ret = snd_card_next(&card);
417        if (ret < 0) {
418            AUDIO_FUNC_LOGE("snd_card_next error: %{public}s", snd_strerror(ret));
419            return HDF_FAILURE;
420        }
421    }
422
423    return HDF_SUCCESS;
424}
425
426int32_t SndSaveCardListInfo(snd_pcm_stream_t stream)
427{
428    (void)memset_s(&g_alsaAdapterList, sizeof(struct AlsaAdapterList) * SND_CARD_MAX,
429        0, sizeof(struct AlsaAdapterList) * SND_CARD_MAX);
430    (void)memset_s(&g_alsaCardsDevList, sizeof(struct AlsaCardsList),
431        0, sizeof(struct AlsaCardsList));
432
433    /* Parse sound card from configuration file */
434    int32_t ret = CfgSaveAdapterFromFile();
435    if (ret != HDF_SUCCESS) {
436        AUDIO_FUNC_LOGE("parse config file failed! ret = %{public}d", ret);
437        return HDF_FAILURE;
438    }
439
440    /* Read sound card list from alsa hardware */
441    ret = DevSaveDriverInfo(stream);
442    if (ret != HDF_SUCCESS) {
443        AUDIO_FUNC_LOGE("failed to save alsa sound cards driver info");
444        return HDF_FAILURE;
445    }
446
447    /* if the alsa hardware include usb then add to adapter list */
448    struct AlsaDevInfo *devInfo = DevGetInfoByPcmInfoId(USB);
449    if (devInfo != NULL) {
450        g_alsaAdapterList[SND_CARD_USB].num = 1;
451        ret = memcpy_s((void*)&g_alsaAdapterList[SND_CARD_USB].list[0].adapterName, MAX_CARD_NAME_LEN,
452        USB, sizeof(USB));
453        if (ret != EOK) {
454            AUDIO_FUNC_LOGE("memcpy_s adapterName fail!");
455            return HDF_FAILURE;
456        }
457    }
458
459    return HDF_SUCCESS;
460}
461
462int32_t SndMatchSelAdapter(struct AlsaSoundCard *cardIns, const char *adapterName)
463{
464    struct AlsaDevInfo *devInfo = NULL;
465    CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
466    CHECK_NULL_PTR_RETURN_DEFAULT(adapterName);
467
468    enum SndCardType  cardType = CfgGetAdapterCardType(adapterName);
469    if (cardType == SND_CARD_UNKNOWN) {
470        AUDIO_FUNC_LOGE("unknow card type error.");
471        return HDF_FAILURE;
472    }
473    cardIns->cardType = cardType;
474
475    struct AlsaAdapterCfgInfo adapterInfos[g_alsaAdapterList[cardType].num];
476    int32_t num = CfgGetAdapterInfo(adapterName, adapterInfos, g_alsaAdapterList[cardType].num);
477    if (num == 0) {
478        AUDIO_FUNC_LOGE("adapter %{public}s is not exits.", cardIns->adapterName);
479        return HDF_FAILURE;
480    }
481
482    devInfo = DevGetInfoByAdapter(adapterInfos, num);
483    if (devInfo == NULL) {
484        AUDIO_FUNC_LOGE("adapter %{public}s cant not find sound card device.", cardIns->adapterName);
485        return HDF_FAILURE;
486    }
487
488    int32_t ret = snprintf_s(cardIns->devName, MAX_CARD_NAME_LEN, MAX_CARD_NAME_LEN - 1,
489        "hw:%d,%d", devInfo->card, devInfo->device);
490    if (ret < 0) {
491        AUDIO_FUNC_LOGE("%{public}s snprintf_s devName failed", cardIns->adapterName);
492        return HDF_FAILURE;
493    }
494    ret = snprintf_s(cardIns->ctrlName, MAX_CARD_NAME_LEN, MAX_CARD_NAME_LEN - 1, "hw:%d", devInfo->card);
495    if (ret < 0) {
496        AUDIO_FUNC_LOGE("%{public}s snprintf_s ctrlName failed", cardIns->adapterName);
497        return HDF_FAILURE;
498    }
499    ret = snprintf_s(cardIns->alsaCardId, MAX_CARD_NAME_LEN, MAX_CARD_NAME_LEN - 1, "%s", devInfo->cardId);
500    if (ret < 0) {
501        AUDIO_FUNC_LOGE("%{public}s snprintf_s alsaCardId failed", cardIns->adapterName);
502        return HDF_FAILURE;
503    }
504
505    return HDF_SUCCESS;
506}
507
508int32_t SndConverAlsaPcmFormat(const struct AudioPcmHwParams *hwParams, snd_pcm_format_t *alsaPcmFormat)
509{
510    CHECK_NULL_PTR_RETURN_DEFAULT(hwParams);
511    CHECK_NULL_PTR_RETURN_DEFAULT(alsaPcmFormat);
512    enum AudioFormat audioFormat = hwParams->format;
513    bool isBigEndian = hwParams->isBigEndian;
514
515    /** Little Endian */
516    if (!isBigEndian) {
517        switch (audioFormat) {
518            case AUDIO_FORMAT_TYPE_PCM_8_BIT:
519                *alsaPcmFormat = SND_PCM_FORMAT_S8; /** Signed 8 bit */
520                break;
521            case AUDIO_FORMAT_TYPE_PCM_16_BIT:
522                *alsaPcmFormat = SND_PCM_FORMAT_S16_LE; /** Signed 16 bit Little Endian */
523                break;
524            case AUDIO_FORMAT_TYPE_PCM_24_BIT:
525                *alsaPcmFormat = SND_PCM_FORMAT_S24_LE; /** Signed 24 bit Little Endian */
526                break;
527            case AUDIO_FORMAT_TYPE_PCM_32_BIT:
528                *alsaPcmFormat = SND_PCM_FORMAT_S32_LE; /** Signed 32 bit Little Endian */
529                break;
530            default:
531                AUDIO_FUNC_LOGE("not support format %{public}d", audioFormat);
532                return HDF_ERR_NOT_SUPPORT;
533        }
534    } else { /** Big Endian */
535        switch (audioFormat) {
536            case AUDIO_FORMAT_TYPE_PCM_8_BIT:
537                *alsaPcmFormat = SND_PCM_FORMAT_S8; /** Signed 8 bit */
538                break;
539            case AUDIO_FORMAT_TYPE_PCM_16_BIT:
540                *alsaPcmFormat = SND_PCM_FORMAT_S16_BE; /** Signed 16 bit Big Endian */
541                break;
542            case AUDIO_FORMAT_TYPE_PCM_24_BIT:
543                *alsaPcmFormat = SND_PCM_FORMAT_S24_BE; /** Signed 24 bit Big Endian */
544                break;
545            case AUDIO_FORMAT_TYPE_PCM_32_BIT:
546                *alsaPcmFormat = SND_PCM_FORMAT_S32_BE; /** Signed 32 bit Big Endian */
547                break;
548            default:
549                AUDIO_FUNC_LOGE("not support format %{public}d", audioFormat);
550                return HDF_ERR_NOT_SUPPORT;
551        }
552    }
553
554    return HDF_SUCCESS;
555}
556
557int32_t SndPcmPrepare(struct AlsaSoundCard *cardIns)
558{
559    CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
560    int32_t ret = snd_pcm_prepare(cardIns->pcmHandle);
561    if (ret < 0) {
562        AUDIO_FUNC_LOGE("snd_pcm_prepare fail: %{public}s", snd_strerror(ret));
563        return HDF_FAILURE;
564    }
565    return HDF_SUCCESS;
566}
567
568bool SndisBusy(struct AlsaSoundCard *cardIns)
569{
570    if (cardIns == NULL) {
571        return false;
572    }
573    return (cardIns->pcmHandle == NULL) ? false : true;
574}
575
576int32_t SndOpenMixer(struct AlsaSoundCard *cardIns)
577{
578    CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
579
580    if (strlen(cardIns->ctrlName) == 0) {
581        AUDIO_FUNC_LOGE("The soundcard ctrname is null.");
582        return HDF_FAILURE;
583    }
584
585    int32_t ret = snd_mixer_open(&cardIns->mixerHandle, 0);
586    if (ret < 0) {
587        AUDIO_FUNC_LOGE("Failed to open mixer: %{public}s.", snd_strerror(ret));
588        return HDF_FAILURE;
589    }
590
591    ret = snd_mixer_attach(cardIns->mixerHandle, cardIns->ctrlName);
592    if (ret < 0) {
593        AUDIO_FUNC_LOGE("Failed to attach mixer: %{public}s.", snd_strerror(ret));
594        ret = snd_mixer_close(cardIns->mixerHandle);
595        if (ret < 0) {
596            AUDIO_FUNC_LOGE("mixer close error: %{public}s.", snd_strerror(ret));
597        }
598        cardIns->mixerHandle = NULL;
599        return HDF_FAILURE;
600    }
601
602    ret = snd_mixer_selem_register(cardIns->mixerHandle, NULL, NULL);
603    if (ret < 0) {
604        AUDIO_FUNC_LOGE("Failed to register mixer element: %{public}s.", snd_strerror(ret));
605        ret = snd_mixer_close(cardIns->mixerHandle);
606        if (ret < 0) {
607            AUDIO_FUNC_LOGE("mixer close error: %{public}s.", snd_strerror(ret));
608        }
609        cardIns->mixerHandle = NULL;
610        return HDF_FAILURE;
611    }
612
613    ret = snd_mixer_load(cardIns->mixerHandle);
614    if (ret < 0) {
615        AUDIO_FUNC_LOGE("Failed to load mixer element: %{public}s.", snd_strerror(ret));
616        ret = snd_mixer_close(cardIns->mixerHandle);
617        if (ret < 0) {
618            AUDIO_FUNC_LOGE("mixer close error: %{public}s.", snd_strerror(ret));
619        }
620        cardIns->mixerHandle = NULL;
621        return HDF_FAILURE;
622    }
623    return HDF_SUCCESS;
624}
625
626snd_pcm_state_t SndGetRunState(struct AlsaSoundCard * cardIns)
627{
628    CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
629    return snd_pcm_state(cardIns->pcmHandle);
630}
631
632void SndCloseHandle(struct AlsaSoundCard *cardIns)
633{
634    if (cardIns == NULL) {
635        AUDIO_FUNC_LOGE("cardIns is NULL");
636        return;
637    }
638    if (cardIns->cardStatus > 0) {
639        cardIns->cardStatus -= 1;
640    }
641    if (cardIns->cardStatus == 0) {
642        int32_t ret;
643        if (cardIns->pcmHandle != NULL) {
644            ret = snd_pcm_close(cardIns->pcmHandle);
645            if (ret < 0) {
646                AUDIO_FUNC_LOGE("snd_pcm_close fail: %{public}s", snd_strerror(ret));
647            }
648            cardIns->pcmHandle = NULL;
649        }
650        if (cardIns->mixerHandle != NULL) {
651            ret = snd_mixer_close(cardIns->mixerHandle);
652            if (ret < 0) {
653                AUDIO_FUNC_LOGE("mixer close error: %{public}s.", snd_strerror(ret));
654            }
655            cardIns->mixerHandle = NULL;
656        }
657        (void)memset_s(cardIns, sizeof(struct AlsaSoundCard), 0, sizeof(struct AlsaSoundCard));
658    }
659}
660
661static void AudioInitPortOut(struct AudioPort *audioPort)
662{
663    audioPort->dir = PORT_OUT;
664    audioPort->portId = 0;
665    audioPort->portName = strdup("AOP");
666}
667
668static void AudioInitPortIn(struct AudioPort *audioPort)
669{
670    audioPort->dir = PORT_IN;
671    audioPort->portId = 0;
672    audioPort->portName = strdup("AIP");
673}
674
675static void AudioInitPortOutAndIn(struct AudioPort *audioPort)
676{
677    audioPort->dir = PORT_OUT_IN;
678    audioPort->portId = 0;
679    audioPort->portName = strdup("AIOP");
680}
681
682static int32_t AudioInitPorts(struct AudioAdapterDescriptor *desc, enum SndCardType type)
683{
684    uint8_t portNum = 0;
685    CHECK_NULL_PTR_RETURN_DEFAULT(desc);
686
687    switch (type) {
688        case SND_CARD_PRIMARY:
689            portNum = PORT_OUT_IN;
690            break;
691        case SND_CARD_HDMI:
692            portNum = PORT_OUT;
693            break;
694        case SND_CARD_USB:
695            portNum = PORT_IN;
696            break;
697        default:
698            AUDIO_FUNC_LOGE("Unknown sound card type does not support this sound card temporarily!");
699            return HDF_FAILURE;
700    }
701
702#ifndef AUDIO_HDI_SERVICE_MODE
703        desc->portNum = portNum;
704#else
705        desc->portsLen = portNum;
706#endif
707    if (portNum == 0) {
708        AUDIO_FUNC_LOGE("portNum is zero");
709        return HDF_FAILURE;
710    }
711    desc->ports = (struct AudioPort *)OsalMemCalloc(sizeof(struct AudioPort) * portNum);
712    if (desc->ports == NULL) {
713        AUDIO_FUNC_LOGE("OsalMemCalloc failed!");
714        return HDF_ERR_MALLOC_FAIL;
715    }
716
717    if (type == SND_CARD_PRIMARY) {
718        AudioInitPortOut(&desc->ports[0]);
719        AudioInitPortIn(&desc->ports[SUPPORT_CAPTURE_OR_RENDER]);
720        AudioInitPortOutAndIn(&desc->ports[SUPPORT_CAPTURE_AND_RENDER]);
721    } else if (type == SND_CARD_HDMI) {
722        AudioInitPortOut(&desc->ports[0]);
723    } else if (type == SND_CARD_USB) {
724        AudioInitPortOut(&desc->ports[0]);
725        AudioInitPortIn(&desc->ports[SUPPORT_CAPTURE_OR_RENDER]);
726    } else {
727        AUDIO_FUNC_LOGE("adapter list not support sound card type %{public}d", type);
728        return HDF_FAILURE;
729    }
730
731    return HDF_SUCCESS;
732}
733
734int32_t AudioGetAllCardInfo(struct AudioAdapterDescriptor **descs, int32_t *sndCardNum)
735{
736    CHECK_NULL_PTR_RETURN_DEFAULT(descs);
737    CHECK_NULL_PTR_RETURN_DEFAULT(sndCardNum);
738
739    int32_t ret = SndSaveCardListInfo(SND_PCM_STREAM_PLAYBACK);
740    if (ret != HDF_SUCCESS) {
741        return HDF_FAILURE;
742    }
743
744    int32_t adapterNum = CfgGetAdapterCount();
745    if (*descs == NULL && adapterNum > 0 && adapterNum < MALLOC_MAX) {
746        AUDIO_FUNC_LOGW("*descs is null, need memcalloc.");
747        *descs = (struct AudioAdapterDescriptor *)OsalMemCalloc(sizeof(struct AudioAdapterDescriptor) * adapterNum);
748        if (*descs == NULL) {
749            AUDIO_FUNC_LOGE("OsalMemCalloc descs is NULL");
750            return HDF_ERR_MALLOC_FAIL;
751        }
752    }
753    *sndCardNum = adapterNum;
754
755    int32_t idx = 0;
756    for (enum SndCardType type = SND_CARD_PRIMARY; type < SND_CARD_MAX; ++type) {
757        for (int32_t i = 0; i < g_alsaAdapterList[type].num; ++i) {
758            (*descs)[idx].adapterName = strdup(g_alsaAdapterList[type].list[i].adapterName);
759            AudioInitPorts(&(*descs)[idx], type);
760            AUDIO_FUNC_LOGI("adapter name : %{public}s", (*descs)[idx].adapterName);
761            idx++;
762        }
763    }
764
765    return HDF_SUCCESS;
766}
767
768struct HdfIoService *HdfIoServiceBindName(const char *serviceName)
769{
770    (void)serviceName;
771    /* Nothing to do */
772    static struct HdfIoService hdfIoService;
773    return &hdfIoService;
774}
775
776struct DevHandle *AudioBindService(const char *name)
777{
778    struct DevHandle *handle = NULL;
779
780    if (name == NULL) {
781        AUDIO_FUNC_LOGE("service name NULL!");
782        return NULL;
783    }
784
785    handle = (struct DevHandle *)OsalMemCalloc(sizeof(struct DevHandle));
786    if (handle == NULL) {
787        AUDIO_FUNC_LOGE("OsalMemCalloc handle failed!!!");
788        return NULL;
789    }
790
791    AUDIO_FUNC_LOGI("BIND SERVICE SUCCESS!");
792    return handle;
793}
794
795void AudioCloseService(const struct DevHandle *handle)
796{
797    if (handle != NULL) {
798        AudioMemFree((void **)&handle);
799    }
800}
801
802void SndElementItemInit(struct AlsaMixerCtlElement *m)
803{
804    m->iface = IFACE_MIXER;
805    m->index = 0;
806    m->device = 0;
807    m->subdevice = 0;
808}
809
810static snd_ctl_elem_iface_t ConvertIfaceType(enum SndIfaceType iface)
811{
812    snd_ctl_elem_iface_t snd_iface;
813    switch (iface) {
814        case IFACE_CARD:
815            snd_iface = SND_CTL_ELEM_IFACE_CARD;
816            break;
817        case IFACE_MIXER:
818            snd_iface = SND_CTL_ELEM_IFACE_MIXER;
819            break;
820        case IFACE_PCM:
821            snd_iface = SND_CTL_ELEM_IFACE_PCM;
822            break;
823        case IFACE_RAWMIDI:
824            snd_iface = SND_CTL_ELEM_IFACE_RAWMIDI;
825            break;
826        case IFACE_TIMER:
827            snd_iface = SND_CTL_ELEM_IFACE_TIMER;
828            break;
829        case IFACE_SEQUENCER:
830            snd_iface = SND_CTL_ELEM_IFACE_SEQUENCER;
831            break;
832        default:
833            snd_iface = SND_CTL_ELEM_IFACE_MIXER;
834            break;
835    }
836    return snd_iface;
837}
838
839static int32_t SetElementInfo(snd_ctl_t *alsaHandle, const struct AlsaMixerCtlElement *ctlElem,
840    snd_ctl_elem_info_t *info, snd_ctl_elem_id_t *id)
841{
842    CHECK_NULL_PTR_RETURN_DEFAULT(alsaHandle);
843    CHECK_NULL_PTR_RETURN_DEFAULT(ctlElem);
844    CHECK_NULL_PTR_RETURN_DEFAULT(info);
845    CHECK_NULL_PTR_RETURN_DEFAULT(id);
846
847    if (ctlElem->numid >= 0) {
848        snd_ctl_elem_id_set_numid(id, ctlElem->numid);
849    }
850    if (ctlElem->index >= 0) {
851        snd_ctl_elem_id_set_index(id, ctlElem->index);
852    }
853    if (ctlElem->device >= 0) {
854        snd_ctl_elem_id_set_device(id, ctlElem->device);
855    }
856    if (ctlElem->subdevice >= 0) {
857        snd_ctl_elem_id_set_subdevice(id, ctlElem->subdevice);
858    }
859
860    snd_ctl_elem_iface_t ifaceType = ConvertIfaceType(ctlElem->iface);
861    snd_ctl_elem_id_set_interface(id, ifaceType);
862    if (ctlElem->name) {
863        snd_ctl_elem_id_set_name(id, ctlElem->name);
864    }
865    snd_ctl_elem_info_set_id(info, id);
866    int32_t ret = snd_ctl_elem_info(alsaHandle, info);
867    if (ret < 0) {
868        AUDIO_FUNC_LOGE("Cannot find the given element from elem_value\n");
869        return HDF_FAILURE;
870    }
871    snd_ctl_elem_info_get_id(info, id);
872
873    return HDF_SUCCESS;
874}
875
876int32_t SndElementReadInt(struct AlsaSoundCard *cardIns,
877    const struct AlsaMixerCtlElement *ctlElem, long *value)
878{
879    snd_ctl_t *alsaHandle = NULL;
880    snd_ctl_elem_id_t *elem_id = NULL;
881    snd_ctl_elem_info_t *elem_info = NULL;
882    snd_ctl_elem_value_t *elem_value = NULL;
883
884    CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
885    CHECK_NULL_PTR_RETURN_DEFAULT(ctlElem);
886
887    int ret = snd_ctl_open(&alsaHandle, cardIns->ctrlName, 0);
888    if (ret < 0) {
889        AUDIO_FUNC_LOGE("snd_ctl_open error: %{public}s", snd_strerror(ret));
890        return HDF_FAILURE;
891    }
892
893    snd_ctl_elem_id_alloca(&elem_id);
894    snd_ctl_elem_info_alloca(&elem_info);
895    snd_ctl_elem_value_alloca(&elem_value);
896    ret = SetElementInfo(alsaHandle, ctlElem, elem_info, elem_id);
897    if (ret != HDF_SUCCESS) {
898        AUDIO_FUNC_LOGE("Set element %{public}s elem_info failed!\n", ctlElem->name);
899        return HDF_FAILURE;
900    }
901    snd_ctl_elem_value_set_id(elem_value, elem_id);
902
903    if (!snd_ctl_elem_info_is_readable(elem_info)) {
904        AUDIO_FUNC_LOGE("Element read enable\n");
905        return HDF_FAILURE;
906    }
907    ret = snd_ctl_elem_read(alsaHandle, elem_value);
908    if (ret < 0) {
909        AUDIO_FUNC_LOGE("Cannot read the given element from elem_value \n");
910        return HDF_FAILURE;
911    }
912
913    snd_ctl_elem_type_t type = snd_ctl_elem_info_get_type(elem_info);
914    if (type == SND_CTL_ELEM_TYPE_INTEGER) {
915        *value = snd_ctl_elem_value_get_integer(elem_value, 0);
916    } else if (type == SND_CTL_ELEM_TYPE_INTEGER64) {
917        *value = (long)snd_ctl_elem_value_get_integer64(elem_value, 0);
918    } else {
919        AUDIO_FUNC_LOGE("Element type is not interger\n");
920        return HDF_FAILURE;
921    }
922
923    return HDF_SUCCESS;
924}
925
926int32_t SndElementReadEnum(
927    struct AlsaSoundCard *cardIns, const struct AlsaMixerCtlElement *ctlElem, unsigned int *item)
928{
929    snd_ctl_t *alsaHandle = NULL;
930    snd_ctl_elem_id_t *elem_id = NULL;
931    snd_ctl_elem_info_t *elem_info = NULL;
932    snd_ctl_elem_value_t *elem_value = NULL;
933
934    CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
935    CHECK_NULL_PTR_RETURN_DEFAULT(ctlElem);
936
937    int ret = snd_ctl_open(&alsaHandle, cardIns->ctrlName, 0);
938    if (ret < 0) {
939        AUDIO_FUNC_LOGE("snd_ctl_open error: %{public}s", snd_strerror(ret));
940        return HDF_FAILURE;
941    }
942
943    snd_ctl_elem_id_alloca(&elem_id);
944    snd_ctl_elem_info_alloca(&elem_info);
945    snd_ctl_elem_value_alloca(&elem_value);
946    ret = SetElementInfo(alsaHandle, ctlElem, elem_info, elem_id);
947    if (ret != HDF_SUCCESS) {
948        AUDIO_FUNC_LOGE("Set element %{public}s elem_info failed!\n", ctlElem->name);
949        return HDF_FAILURE;
950    }
951    snd_ctl_elem_value_set_id(elem_value, elem_id);
952
953    if (!snd_ctl_elem_info_is_readable(elem_info)) {
954        AUDIO_FUNC_LOGE("Element read enable\n");
955        return HDF_FAILURE;
956    }
957    ret = snd_ctl_elem_read(alsaHandle, elem_value);
958    if (ret < 0) {
959        AUDIO_FUNC_LOGE("Cannot read the given element from elem_value \n");
960        return HDF_FAILURE;
961    }
962
963    snd_ctl_elem_type_t type = snd_ctl_elem_info_get_type(elem_info);
964    if (type == SND_CTL_ELEM_TYPE_ENUMERATED) {
965        *item = snd_ctl_elem_value_get_enumerated(elem_value, 0);
966    } else {
967        AUDIO_FUNC_LOGE("Element type is not enumerated\n");
968        return HDF_FAILURE;
969    }
970
971    return HDF_SUCCESS;
972}
973
974int32_t SndElementReadRange(
975    struct AlsaSoundCard * cardIns, const struct AlsaMixerCtlElement * ctlElem, long * mix, long * max)
976{
977    snd_ctl_t *alsaHandle = NULL;
978    snd_ctl_elem_id_t *elem_id = NULL;
979    snd_ctl_elem_info_t *elem_info = NULL;
980    snd_ctl_elem_value_t *elem_value = NULL;
981
982    CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
983    CHECK_NULL_PTR_RETURN_DEFAULT(ctlElem);
984
985    int ret = snd_ctl_open(&alsaHandle, cardIns->ctrlName, 0);
986    if (ret < 0) {
987        AUDIO_FUNC_LOGE("snd_ctl_open error: %{public}s", snd_strerror(ret));
988        return HDF_FAILURE;
989    }
990
991    snd_ctl_elem_id_alloca(&elem_id);
992    snd_ctl_elem_info_alloca(&elem_info);
993    snd_ctl_elem_value_alloca(&elem_value);
994    ret = SetElementInfo(alsaHandle, ctlElem, elem_info, elem_id);
995    if (ret != HDF_SUCCESS) {
996        AUDIO_FUNC_LOGE("Set element %{public}s elem_info failed!\n", ctlElem->name);
997        return HDF_FAILURE;
998    }
999    snd_ctl_elem_value_set_id(elem_value, elem_id);
1000
1001    if (!snd_ctl_elem_info_is_readable(elem_info)) {
1002        AUDIO_FUNC_LOGE("Element read enable\n");
1003        return HDF_FAILURE;
1004    }
1005    ret = snd_ctl_elem_read(alsaHandle, elem_value);
1006    if (ret < 0) {
1007        AUDIO_FUNC_LOGE("Cannot read the given element from elem_value \n");
1008        return HDF_FAILURE;
1009    }
1010
1011    snd_ctl_elem_type_t type = snd_ctl_elem_info_get_type(elem_info);
1012    if (type == SND_CTL_ELEM_TYPE_INTEGER) {
1013        *mix = snd_ctl_elem_info_get_min(elem_info);
1014        *max = snd_ctl_elem_info_get_max(elem_info);
1015    } else if (type == SND_CTL_ELEM_TYPE_INTEGER64) {
1016        *mix = (long)snd_ctl_elem_info_get_min64(elem_info);
1017        *max = (long)snd_ctl_elem_info_get_max64(elem_info);
1018    } else {
1019        AUDIO_FUNC_LOGE("Element value is not integer type!\n");
1020        return HDF_FAILURE;
1021    }
1022
1023    return HDF_SUCCESS;
1024}
1025
1026int32_t SndElementReadSwitch(
1027    struct AlsaSoundCard *cardIns, const struct AlsaMixerCtlElement *ctlElem, bool *on)
1028{
1029    snd_ctl_t *alsaHandle = NULL;
1030    snd_ctl_elem_id_t *elem_id = NULL;
1031    snd_ctl_elem_info_t *elem_info = NULL;
1032    snd_ctl_elem_value_t *elem_value = NULL;
1033
1034    CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
1035    CHECK_NULL_PTR_RETURN_DEFAULT(ctlElem);
1036
1037    int ret = snd_ctl_open(&alsaHandle, cardIns->ctrlName, 0);
1038    if (ret < 0) {
1039        AUDIO_FUNC_LOGE("snd_ctl_open error: %{public}s", snd_strerror(ret));
1040        return HDF_FAILURE;
1041    }
1042
1043    snd_ctl_elem_id_alloca(&elem_id);
1044    snd_ctl_elem_info_alloca(&elem_info);
1045    snd_ctl_elem_value_alloca(&elem_value);
1046    ret = SetElementInfo(alsaHandle, ctlElem, elem_info, elem_id);
1047    if (ret != HDF_SUCCESS) {
1048        AUDIO_FUNC_LOGE("Set element %{public}s elem_info failed!\n", ctlElem->name);
1049        return HDF_FAILURE;
1050    }
1051    snd_ctl_elem_value_set_id(elem_value, elem_id);
1052
1053    if (!snd_ctl_elem_info_is_readable(elem_info)) {
1054        AUDIO_FUNC_LOGE("Element read enable\n");
1055        return HDF_FAILURE;
1056    }
1057    ret = snd_ctl_elem_read(alsaHandle, elem_value);
1058    if (ret < 0) {
1059        AUDIO_FUNC_LOGE("Cannot read the given element from elem_value \n");
1060        return HDF_FAILURE;
1061    }
1062
1063    snd_ctl_elem_type_t type = snd_ctl_elem_info_get_type(elem_info);
1064    if (type == SND_CTL_ELEM_TYPE_BOOLEAN) {
1065        ret = snd_ctl_elem_value_get_boolean(elem_value, 0);
1066        *on = (ret > 0) ? true : false;
1067    } else {
1068        AUDIO_FUNC_LOGE("Element type is not boolean\n");
1069        return HDF_FAILURE;
1070    }
1071
1072    return HDF_SUCCESS;
1073}
1074
1075int32_t SndElementWriteInt(
1076    struct AlsaSoundCard *cardIns, const struct AlsaMixerCtlElement *ctlElem, long value)
1077{
1078    snd_ctl_t *alsaHandle = NULL;
1079    snd_ctl_elem_id_t *elem_id = NULL;
1080    snd_ctl_elem_info_t *elem_info = NULL;
1081    snd_ctl_elem_value_t *elem_value = NULL;
1082
1083    CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
1084    CHECK_NULL_PTR_RETURN_DEFAULT(ctlElem);
1085
1086    int ret = snd_ctl_open(&alsaHandle, cardIns->ctrlName, 0);
1087    if (ret < 0) {
1088        AUDIO_FUNC_LOGE("snd_ctl_open error: %{public}s", snd_strerror(ret));
1089        return HDF_FAILURE;
1090    }
1091
1092    snd_ctl_elem_id_alloca(&elem_id);
1093    snd_ctl_elem_info_alloca(&elem_info);
1094    snd_ctl_elem_value_alloca(&elem_value);
1095    ret = SetElementInfo(alsaHandle, ctlElem, elem_info, elem_id);
1096    if (ret != HDF_SUCCESS) {
1097        AUDIO_FUNC_LOGE("Set element %{public}s elem_info failed!\n", ctlElem->name);
1098        return HDF_FAILURE;
1099    }
1100
1101    if (!snd_ctl_elem_info_is_writable(elem_info)) {
1102        AUDIO_FUNC_LOGE("Element write enable\n");
1103        return HDF_FAILURE;
1104    }
1105
1106    snd_ctl_elem_value_set_id(elem_value, elem_id);
1107    snd_ctl_elem_type_t type = snd_ctl_elem_info_get_type(elem_info);
1108    if (type == SND_CTL_ELEM_TYPE_INTEGER) {
1109        snd_ctl_elem_value_set_integer(elem_value, 0, value);
1110    } else if (type == SND_CTL_ELEM_TYPE_INTEGER64) {
1111        snd_ctl_elem_value_set_integer64(elem_value, 0, (long long)value);
1112    } else {
1113        AUDIO_FUNC_LOGE("Element value is not integer type!\n");
1114        return HDF_FAILURE;
1115    }
1116
1117    ret = snd_ctl_elem_write(alsaHandle, elem_value);
1118    if (ret < 0) {
1119        AUDIO_FUNC_LOGE("snd_ctl_elem_write failed!\n");
1120        return HDF_FAILURE;
1121    }
1122
1123    return HDF_SUCCESS;
1124}
1125
1126int32_t SndElementWriteEnum(
1127    struct AlsaSoundCard *cardIns, const struct AlsaMixerCtlElement *ctlElem, unsigned int item)
1128{
1129    snd_ctl_t *alsaHandle = NULL;
1130    snd_ctl_elem_id_t *elem_id = NULL;
1131    snd_ctl_elem_info_t *elem_info = NULL;
1132    snd_ctl_elem_value_t *elem_value = NULL;
1133
1134    CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
1135    CHECK_NULL_PTR_RETURN_DEFAULT(ctlElem);
1136
1137    int ret = snd_ctl_open(&alsaHandle, cardIns->ctrlName, 0);
1138    if (ret < 0) {
1139        AUDIO_FUNC_LOGE("snd_ctl_open error: %{public}s", snd_strerror(ret));
1140        return HDF_FAILURE;
1141    }
1142
1143    snd_ctl_elem_id_alloca(&elem_id);
1144    snd_ctl_elem_info_alloca(&elem_info);
1145    snd_ctl_elem_value_alloca(&elem_value);
1146    ret = SetElementInfo(alsaHandle, ctlElem, elem_info, elem_id);
1147    if (ret != HDF_SUCCESS) {
1148        AUDIO_FUNC_LOGE("Set element %{public}s elem_info failed!\n", ctlElem->name);
1149        return HDF_FAILURE;
1150    }
1151
1152    if (!snd_ctl_elem_info_is_writable(elem_info)) {
1153        AUDIO_FUNC_LOGE("Element write enable\n");
1154        return HDF_FAILURE;
1155    }
1156
1157    snd_ctl_elem_value_set_id(elem_value, elem_id);
1158    snd_ctl_elem_type_t type = snd_ctl_elem_info_get_type(elem_info);
1159    if (type == SND_CTL_ELEM_TYPE_ENUMERATED) {
1160        snd_ctl_elem_value_set_enumerated(elem_value, 0, item);
1161    } else {
1162        AUDIO_FUNC_LOGE("Element value is not enum type!\n");
1163        return HDF_FAILURE;
1164    }
1165
1166    ret = snd_ctl_elem_write(alsaHandle, elem_value);
1167    if (ret < 0) {
1168        AUDIO_FUNC_LOGE("snd_ctl_elem_write failed!\n");
1169        return HDF_FAILURE;
1170    }
1171
1172    return HDF_SUCCESS;
1173}
1174
1175int32_t SndElementWriteSwitch(
1176    struct AlsaSoundCard *cardIns, const struct AlsaMixerCtlElement *ctlElem, bool on)
1177{
1178    snd_ctl_t *alsaHandle = NULL;
1179    snd_ctl_elem_id_t *elem_id;
1180    snd_ctl_elem_info_t *elem_info;
1181    snd_ctl_elem_value_t *elem_value;
1182
1183    CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
1184    CHECK_NULL_PTR_RETURN_DEFAULT(ctlElem);
1185
1186    int ret = snd_ctl_open(&alsaHandle, cardIns->ctrlName, 0);
1187    if (ret < 0) {
1188        AUDIO_FUNC_LOGE("snd_ctl_open error: %{public}s", snd_strerror(ret));
1189        return HDF_FAILURE;
1190    }
1191
1192    snd_ctl_elem_id_alloca(&elem_id);
1193    snd_ctl_elem_info_alloca(&elem_info);
1194    snd_ctl_elem_value_alloca(&elem_value);
1195    ret = SetElementInfo(alsaHandle, ctlElem, elem_info, elem_id);
1196    if (ret != HDF_SUCCESS) {
1197        AUDIO_FUNC_LOGE("Set element %{public}s elem_info failed!\n", ctlElem->name);
1198        return HDF_FAILURE;
1199    }
1200
1201    if (!snd_ctl_elem_info_is_writable(elem_info)) {
1202        AUDIO_FUNC_LOGE("Element write enable\n");
1203        return HDF_FAILURE;
1204    }
1205
1206    snd_ctl_elem_value_set_id(elem_value, elem_id);
1207    snd_ctl_elem_type_t type = snd_ctl_elem_info_get_type(elem_info);
1208    if (type == SND_CTL_ELEM_TYPE_BOOLEAN) {
1209        int value = on ? 1 : 0;
1210        snd_ctl_elem_value_set_boolean(elem_value, 0, value);
1211    } else {
1212        AUDIO_FUNC_LOGE("Element value is not boolean type!\n");
1213        return HDF_FAILURE;
1214    }
1215
1216    ret = snd_ctl_elem_write(alsaHandle, elem_value);
1217    if (ret < 0) {
1218        AUDIO_FUNC_LOGE("snd_ctl_elem_write failed!\n");
1219        return HDF_FAILURE;
1220    }
1221
1222    return HDF_SUCCESS;
1223}
1224
1225int32_t SndElementWrite(
1226    struct AlsaSoundCard *cardIns, const struct AlsaMixerCtlElement *ctlElem)
1227{
1228    snd_ctl_t *alsaHandle = NULL;
1229    snd_ctl_elem_id_t *elem_id = NULL;
1230    snd_ctl_elem_info_t *elem_info = NULL;
1231    snd_ctl_elem_value_t *elem_value = NULL;
1232
1233    CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
1234    CHECK_NULL_PTR_RETURN_DEFAULT(ctlElem);
1235
1236    int ret = snd_ctl_open(&alsaHandle, cardIns->ctrlName, 0);
1237    if (ret < 0) {
1238        AUDIO_FUNC_LOGE("snd_ctl_open error: %{public}s", snd_strerror(ret));
1239        return HDF_FAILURE;
1240    }
1241
1242    snd_ctl_elem_id_alloca(&elem_id);
1243    snd_ctl_elem_info_alloca(&elem_info);
1244    snd_ctl_elem_value_alloca(&elem_value);
1245    ret = SetElementInfo(alsaHandle, ctlElem, elem_info, elem_id);
1246    if (ret != HDF_SUCCESS) {
1247        AUDIO_FUNC_LOGE("Set element %{public}s elem_info failed!\n", ctlElem->name);
1248        return HDF_FAILURE;
1249    }
1250
1251    if (!snd_ctl_elem_info_is_writable(elem_info)) {
1252        AUDIO_FUNC_LOGE("Element write enable\n");
1253        return HDF_FAILURE;
1254    }
1255
1256    snd_ctl_elem_value_set_id(elem_value, elem_id);
1257    ret = snd_ctl_ascii_value_parse(alsaHandle, elem_value, elem_info, ctlElem->value);
1258    if (ret < 0) {
1259        AUDIO_FUNC_LOGE("Control parse error: %s\n", snd_strerror(ret));
1260        return HDF_FAILURE;
1261    }
1262    ret = snd_ctl_elem_write(alsaHandle, elem_value);
1263    if (ret < 0) {
1264        AUDIO_FUNC_LOGE("Control element write error: %s\n", snd_strerror(ret));
1265        return HDF_FAILURE;
1266    }
1267
1268    return HDF_SUCCESS;
1269}
1270
1271int32_t SndElementGroupWrite(
1272    struct AlsaSoundCard *cardIns, const struct AlsaMixerCtlElement* elemGroup, int32_t groupSize)
1273{
1274    CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
1275
1276    for (int i = 0; i < groupSize; ++i) {
1277        int err = SndElementWrite(cardIns, &elemGroup[i]);
1278        if (err < 0) {
1279            AUDIO_FUNC_LOGE("Cant't set element %{public}s", elemGroup[i].name);
1280        }
1281    }
1282
1283    return HDF_SUCCESS;
1284}
1285
1286int32_t SndTraversalMixerElement(struct AlsaSoundCard *cardIns,
1287    bool (*callback)(void *data, snd_ctl_elem_id_t *elem_id), void *data)
1288{
1289    snd_hctl_t *handle = NULL;
1290    snd_hctl_elem_t *elem = NULL;
1291    snd_ctl_elem_id_t *elem_id = NULL;
1292    snd_ctl_elem_info_t *elem_info = NULL;
1293    CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
1294    CHECK_NULL_PTR_RETURN_DEFAULT(callback);
1295
1296    int ret = snd_hctl_open(&handle, cardIns->ctrlName, 0);
1297    if (ret < 0) {
1298        AUDIO_FUNC_LOGE("Control %{public}s open error: %{public}s",
1299            cardIns->ctrlName, snd_strerror(ret));
1300        return HDF_FAILURE;
1301    }
1302    ret = snd_hctl_load(handle);
1303    if (ret < 0) {
1304        AUDIO_FUNC_LOGE("Control %{public}s local error: %{public}s\n",
1305            cardIns->ctrlName, snd_strerror(ret));
1306        return HDF_FAILURE;
1307    }
1308
1309    snd_ctl_elem_id_alloca(&elem_id);
1310    snd_ctl_elem_info_alloca(&elem_info);
1311    for (elem = snd_hctl_first_elem(handle); elem; elem = snd_hctl_elem_next(elem)) {
1312        ret = snd_hctl_elem_info(elem, elem_info);
1313        if (ret < 0) {
1314            AUDIO_FUNC_LOGE("Control %{public}s snd_hctl_elem_info error: %{public}s\n",
1315                cardIns->ctrlName, snd_strerror(ret));
1316            return HDF_FAILURE;
1317        }
1318        if (snd_ctl_elem_info_is_inactive(elem_info)) {
1319            continue;
1320        }
1321        snd_hctl_elem_get_id(elem, elem_id);
1322        if (callback(data, elem_id)) {
1323            (void)snd_hctl_close(handle);
1324            return HDF_SUCCESS;
1325        }
1326    }
1327    (void)snd_hctl_close(handle);
1328    return HDF_FAILURE;
1329}
1330