1/*
2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "audio_pathselect.h"
17#include "audio_uhdf_log.h"
18#include "cJSON.h"
19#include "osal_mem.h"
20#include "securec.h"
21
22#ifdef IDL_MODE
23#define HDF_LOG_TAG AUDIO_HDI_IMPL
24#else
25#define HDF_LOG_TAG HDF_AUDIO_HAL_IMPL
26#endif
27
28#define SPEAKER                   "Speaker"
29#define HEADPHONES                "Headphones"
30#define MIC                       "MIC"
31#define HS_MIC                    "micHs"
32#define EARPIECE                  "earpiece"
33#define BLUETOOTH_SCO             "Bluetooth"
34#define BLUETOOTH_SCO_HEADSET     "Bluetooth_SCO_Headset"
35#define JSON_UNPRINT 1
36
37#define OUTPUT_MASK   0xFFF
38#define OUTPUT_OFFSET 12
39#define INPUT_MASK    0x80000FF
40#define INPUT_OFFSET  27
41
42#define AUDIO_DEV_ON  1
43#define AUDIO_DEV_OFF 0
44
45#define HDF_PATH_NUM_MAX 32
46
47static cJSON *g_cJsonObj = NULL;
48
49int32_t AudioPathSelGetConfToJsonObj(void)
50{
51    FILE *fpJson = NULL;
52    char *pJsonStr = NULL;
53    if (g_cJsonObj != NULL) {
54        return HDF_SUCCESS;
55    }
56    fpJson = fopen(CJSONFILE_CONFIG_PATH, "r");
57    if (fpJson == NULL) {
58        AUDIO_FUNC_LOGE("open %{pulbic}s fail!", CJSONFILE_CONFIG_PATH);
59        return HDF_FAILURE;
60    }
61    if (fseek(fpJson, 0, SEEK_END) != HDF_SUCCESS) {
62        AUDIO_FUNC_LOGE("fseek fail!");
63        (void)fclose(fpJson);
64        return HDF_FAILURE;
65    }
66    int32_t jsonStrSize = ftell(fpJson);
67    rewind(fpJson);
68    if (jsonStrSize <= 0) {
69        (void)fclose(fpJson);
70        return HDF_FAILURE;
71    }
72    pJsonStr = (char *)OsalMemCalloc(jsonStrSize + 1);
73    if (pJsonStr == NULL) {
74        (void)fclose(fpJson);
75        return HDF_FAILURE;
76    }
77    if (fread(pJsonStr, jsonStrSize, 1, fpJson) != 1) {
78        AUDIO_FUNC_LOGE("read to file fail!");
79        (void)fclose(fpJson);
80        fpJson = NULL;
81        OsalMemFree(pJsonStr);
82        return HDF_FAILURE;
83    }
84    (void)fclose(fpJson);
85    fpJson = NULL;
86#ifndef JSON_UNPRINT
87    AUDIO_FUNC_LOGI("pJsonStr = %{public}s", pJsonStr);
88#endif
89    g_cJsonObj = cJSON_Parse(pJsonStr);
90    if (g_cJsonObj == NULL) {
91        AUDIO_FUNC_LOGE("cJSON_GetErrorPtr() = %{public}s", cJSON_GetErrorPtr());
92        OsalMemFree(pJsonStr);
93        return HDF_FAILURE;
94    }
95    OsalMemFree(pJsonStr);
96    return HDF_SUCCESS;
97}
98
99static const char *AudioPathSelGetDeviceType(enum AudioPortPin pin)
100{
101    if (pin < PIN_OUT_SPEAKER || pin > PIN_IN_BLUETOOTH_SCO_HEADSET) {
102        return NULL;
103    }
104    switch (pin) {
105        case PIN_OUT_SPEAKER:
106        case PIN_OUT_BLUETOOTH_A2DP:
107            return SPEAKER;
108        case PIN_OUT_HEADSET:
109            return HEADPHONES;
110        case PIN_IN_MIC:
111            return MIC;
112        case PIN_IN_HS_MIC:
113            return HS_MIC;
114        case PIN_OUT_EARPIECE:
115            return EARPIECE;
116        case PIN_OUT_BLUETOOTH_SCO:
117            return BLUETOOTH_SCO;
118        case PIN_IN_BLUETOOTH_SCO_HEADSET:
119            return BLUETOOTH_SCO_HEADSET;
120        default:
121            AUDIO_FUNC_LOGE("UseCase not support!");
122            break;
123    }
124    return NULL;
125}
126
127static const char *AudioPathSelGetUseCase(enum AudioCategory type)
128{
129    static const char *usecaseType[AUDIO_MMAP_NOIRQ + 1] = {
130        [AUDIO_IN_MEDIA] = "deep-buffer-playback",
131        [AUDIO_IN_COMMUNICATION] = "low-latency-communication",
132        [AUDIO_IN_RINGTONE] = "ringtone-playback",
133        [AUDIO_IN_CALL] = "voice-call",
134        [AUDIO_MMAP_NOIRQ] = "low-latency-noirq-playback",
135    };
136
137    if (type < 0 || type > AUDIO_MMAP_NOIRQ) {
138        return NULL;
139    }
140    return usecaseType[type];
141}
142
143static int32_t SetRenderPathDefaultValue(cJSON *renderSwObj, struct AudioHwRenderParam *renderParam)
144{
145    if (renderSwObj == NULL || renderParam == NULL) {
146        AUDIO_FUNC_LOGE("param Is NULL");
147        return HDF_ERR_INVALID_PARAM;
148    }
149    char *devKey = NULL;
150    int32_t renderDevNum;
151
152    renderDevNum = renderParam->renderMode.hwInfo.pathSelect.deviceInfo.deviceNum;
153    int32_t renderPathNum = cJSON_GetArraySize(renderSwObj);
154    if (renderPathNum < 0 || renderPathNum > HDF_PATH_NUM_MAX) {
155        AUDIO_FUNC_LOGE("renderPathNum is invalid!");
156        return HDF_FAILURE;
157    }
158    for (int32_t i = 0; i < renderPathNum; i++) {
159        cJSON *tmpValue = cJSON_GetArrayItem(renderSwObj, i);
160        cJSON *renderSwName = tmpValue->child;
161        cJSON *renderSwVal = renderSwName->next;
162        if (renderSwName->valuestring == NULL) {
163            AUDIO_FUNC_LOGE("renderSwName->valuestring is null!");
164            return HDF_FAILURE;
165        }
166
167        devKey = renderSwName->valuestring;
168        (void)memset_s(renderParam->renderMode.hwInfo.pathSelect.deviceInfo.deviceSwitchs[renderDevNum].deviceSwitch,
169            PATHPLAN_LEN, 0, PATHPLAN_LEN);
170        int32_t ret =
171            strncpy_s(renderParam->renderMode.hwInfo.pathSelect.deviceInfo.deviceSwitchs[renderDevNum].deviceSwitch,
172                PATHPLAN_COUNT, devKey, strlen(devKey) + 1);
173        if (ret != 0) {
174            AUDIO_FUNC_LOGE("strcpy_s failed!");
175            return HDF_FAILURE;
176        }
177
178        renderParam->renderMode.hwInfo.pathSelect.deviceInfo.deviceSwitchs[renderDevNum].value = renderSwVal->valueint;
179        renderDevNum++;
180    }
181    renderParam->renderMode.hwInfo.pathSelect.deviceInfo.deviceNum = renderDevNum;
182    return HDF_SUCCESS;
183}
184
185static int32_t SetCapturePathDefaultValue(cJSON *captureSwObj, struct AudioHwCaptureParam *captureParam)
186{
187    if (captureSwObj == NULL || captureParam == NULL) {
188        AUDIO_FUNC_LOGE("param Is NULL");
189        return HDF_ERR_INVALID_PARAM;
190    }
191    char *devKey = NULL;
192
193    int32_t devNum = captureParam->captureMode.hwInfo.pathSelect.deviceInfo.deviceNum;
194    int32_t pathNum = cJSON_GetArraySize(captureSwObj);
195    if (pathNum < 0 || pathNum > HDF_PATH_NUM_MAX) {
196        AUDIO_FUNC_LOGE("pathNum is invalid!");
197        return HDF_FAILURE;
198    }
199    for (int32_t i = 0; i < pathNum; i++) {
200        cJSON *tmpValue = cJSON_GetArrayItem(captureSwObj, i);
201        cJSON *captureSwName = tmpValue->child;
202        cJSON *captureSwVal = captureSwName->next;
203        if (captureSwName->valuestring == NULL) {
204            AUDIO_FUNC_LOGE("captureSwName->valuestring is null!");
205            return HDF_FAILURE;
206        }
207
208        devKey = captureSwName->valuestring;
209        (void)memset_s(captureParam->captureMode.hwInfo.pathSelect.deviceInfo.deviceSwitchs[devNum].deviceSwitch,
210            PATHPLAN_LEN, 0, PATHPLAN_LEN);
211        int32_t ret =
212            strncpy_s(captureParam->captureMode.hwInfo.pathSelect.deviceInfo.deviceSwitchs[devNum].deviceSwitch,
213                PATHPLAN_COUNT, devKey, strlen(devKey) + 1);
214        if (ret != 0) {
215            AUDIO_FUNC_LOGE("strcpy_s failed!");
216            return HDF_FAILURE;
217        }
218        captureParam->captureMode.hwInfo.pathSelect.deviceInfo.deviceSwitchs[devNum].value = captureSwVal->valueint;
219
220        devNum++;
221    }
222    captureParam->captureMode.hwInfo.pathSelect.deviceInfo.deviceNum = devNum;
223    return HDF_SUCCESS;
224}
225
226static int32_t SetRenderPathValue(
227    int32_t tpins, cJSON *renderObj, struct AudioHwRenderParam *renderParam, int32_t value)
228{
229    if (renderObj == NULL || renderParam == NULL) {
230        AUDIO_FUNC_LOGE("param Is NULL");
231        return HDF_ERR_INVALID_PARAM;
232    }
233    char *devKey = NULL;
234    int32_t devNum;
235    const char *renderDeviceType = AudioPathSelGetDeviceType(tpins);
236    if (renderDeviceType == NULL) {
237        AUDIO_FUNC_LOGE("DeviceType not found.");
238        return HDF_FAILURE;
239    }
240    devNum = renderParam->renderMode.hwInfo.pathSelect.deviceInfo.deviceNum;
241    /* pins = 0, parse default value */
242    if (strcasecmp(renderDeviceType, renderObj->string) == 0) {
243        int32_t pathNum = cJSON_GetArraySize(renderObj);
244        if (pathNum < 0 || pathNum > HDF_PATH_NUM_MAX) {
245            AUDIO_FUNC_LOGE("pathNum is invalid!");
246            return HDF_FAILURE;
247        }
248        for (int32_t i = 0; i < pathNum; i++) {
249            cJSON *tmpValue = cJSON_GetArrayItem(renderObj, i);
250            cJSON *swName = tmpValue->child;
251            cJSON *swVal = swName->next;
252            if (swName->valuestring == NULL) {
253                AUDIO_FUNC_LOGE("ValueString is null!");
254                return HDF_FAILURE;
255            }
256
257            devKey = swName->valuestring;
258            (void)memset_s(renderParam->renderMode.hwInfo.pathSelect.deviceInfo.deviceSwitchs[devNum].deviceSwitch,
259                PATHPLAN_LEN, 0, PATHPLAN_LEN);
260            int32_t ret =
261                strncpy_s(renderParam->renderMode.hwInfo.pathSelect.deviceInfo.deviceSwitchs[devNum].deviceSwitch,
262                    PATHPLAN_COUNT, devKey, strlen(devKey) + 1);
263            if (ret != 0) {
264                AUDIO_FUNC_LOGE("strcpy_s failed!");
265                return HDF_FAILURE;
266            }
267            if (swVal->valueint > AUDIO_DEV_ON) {
268                /* alsa Adaptation */
269                renderParam->renderMode.hwInfo.pathSelect.deviceInfo.deviceSwitchs[devNum].value = swVal->valueint;
270            } else {
271                renderParam->renderMode.hwInfo.pathSelect.deviceInfo.deviceSwitchs[devNum].value = value;
272            }
273            devNum++;
274        }
275        renderParam->renderMode.hwInfo.pathSelect.deviceInfo.deviceNum = devNum;
276    }
277    return HDF_SUCCESS;
278}
279
280static int32_t SetMatchRenderDevicePath(
281    int32_t tpins, struct AudioHwRenderParam *renderParam, cJSON *cJsonObj, const char *deviceType, int32_t value)
282{
283    if (cJsonObj == NULL || renderParam == NULL) {
284        AUDIO_FUNC_LOGE("param Is NULL");
285        return HDF_ERR_INVALID_PARAM;
286    }
287    if (strcasecmp(cJsonObj->string, deviceType) == 0) {
288        int32_t ret = SetRenderPathValue(tpins, cJsonObj, renderParam, value);
289        if (ret != HDF_SUCCESS) {
290            AUDIO_FUNC_LOGE("set value failed!");
291            return ret;
292        }
293    }
294    return HDF_SUCCESS;
295}
296
297static int32_t SetMatchRenderDefaultDevicePath(struct AudioHwRenderParam *renderParam, cJSON *cJsonObj)
298{
299    int32_t ret;
300    if (cJsonObj == NULL || renderParam == NULL) {
301        AUDIO_FUNC_LOGE("param Is NULL");
302        return HDF_ERR_INVALID_PARAM;
303    }
304    for (uint32_t i = PIN_OUT_SPEAKER; i <= PIN_OUT_EARPIECE; i = i << 1) {
305        const char *deviceType = AudioPathSelGetDeviceType((int32_t)i);
306        if (deviceType == NULL) {
307            AUDIO_FUNC_LOGE("DeviceType not found.");
308            return HDF_FAILURE;
309        }
310        if (strcasecmp(deviceType, cJsonObj->string) == 0) {
311            ret = SetRenderPathDefaultValue(cJsonObj, renderParam);
312            if (ret != HDF_SUCCESS) {
313                AUDIO_FUNC_LOGE("set default value failed!");
314                return ret;
315            }
316            break;
317        }
318    }
319    return HDF_SUCCESS;
320}
321
322static int32_t SetMatchRenderOtherDevicePath(
323    int32_t tpins, struct AudioHwRenderParam *renderParam, cJSON *cJsonObj, int32_t value)
324{
325    int32_t ret;
326    if (cJsonObj == NULL || renderParam == NULL) {
327        AUDIO_FUNC_LOGE("param Is NULL");
328        return HDF_ERR_INVALID_PARAM;
329    }
330    for (uint32_t j = PIN_OUT_SPEAKER; j <= PIN_OUT_EARPIECE; j = j << 1) {
331        if ((j & tpins) == j) {
332            ret = SetRenderPathValue((int32_t)j, cJsonObj, renderParam, AUDIO_DEV_ON);
333            if (ret != HDF_SUCCESS) {
334                AUDIO_FUNC_LOGW("set value failed!");
335                continue;
336            }
337        }
338    }
339    return HDF_SUCCESS;
340}
341
342static int32_t AudioRenderParseDevice(struct AudioHwRenderParam *renderParam, cJSON *cJsonObj)
343{
344    int32_t ret;
345    if (cJsonObj == NULL || renderParam == NULL) {
346        AUDIO_FUNC_LOGE("param Is NULL");
347        return HDF_ERR_INVALID_PARAM;
348    }
349    uint32_t pins = renderParam->renderMode.hwInfo.deviceDescript.pins;
350
351    int32_t tpins = pins & OUTPUT_MASK;
352    if ((pins >> OUTPUT_OFFSET) != 0) {
353        AUDIO_FUNC_LOGE("pins: %d, error!\n", pins);
354        return HDF_FAILURE;
355    }
356
357    if (strcasecmp(cJsonObj->string, MIC) == 0 || strcasecmp(cJsonObj->string, HS_MIC) == 0 ||
358        strcasecmp(cJsonObj->string, BLUETOOTH_SCO_HEADSET) == 0) {
359        return HDF_SUCCESS;
360    }
361
362    switch (tpins) {
363        case PIN_NONE:
364            /* pins = 0, parse default value */
365            ret = SetMatchRenderDefaultDevicePath(renderParam, cJsonObj);
366            break;
367        case PIN_OUT_SPEAKER:
368        case PIN_OUT_BLUETOOTH_A2DP:
369            /* 1.open speaker */
370            ret = SetMatchRenderDevicePath(tpins, renderParam, cJsonObj, SPEAKER, AUDIO_DEV_ON);
371#ifndef ALSA_LIB_MODE
372            /* 2.close headphones */
373            ret |= SetMatchRenderDevicePath(PIN_OUT_HEADSET, renderParam, cJsonObj, HEADPHONES, AUDIO_DEV_OFF);
374#endif
375            break;
376        case PIN_OUT_HEADSET:
377            /* 1、open headphone */
378            ret = SetMatchRenderDevicePath(tpins, renderParam, cJsonObj, HEADPHONES, AUDIO_DEV_ON);
379#ifndef ALSA_LIB_MODE
380            /* 2、close speaker */
381            ret |= SetMatchRenderDevicePath(PIN_OUT_SPEAKER, renderParam, cJsonObj, SPEAKER, AUDIO_DEV_OFF);
382#endif
383            break;
384        case PIN_OUT_EARPIECE:
385            /* 1、open earpiece */
386            ret = SetMatchRenderDevicePath(tpins, renderParam, cJsonObj, EARPIECE, AUDIO_DEV_ON);
387            break;
388        case PIN_OUT_BLUETOOTH_SCO:
389            /* 1、open bluetooth */
390            ret = SetMatchRenderDevicePath(tpins, renderParam, cJsonObj, BLUETOOTH_SCO, AUDIO_DEV_ON);
391            break;
392        default:
393            ret = SetMatchRenderOtherDevicePath(tpins, renderParam, cJsonObj, AUDIO_DEV_ON);
394            break;
395    }
396
397    return ret;
398}
399
400static int32_t AudioRenderParseUsecase(struct AudioHwRenderParam *renderParam, const char *useCase)
401{
402    /* reset path numbers */
403    renderParam->renderMode.hwInfo.pathSelect.deviceInfo.deviceNum = 0;
404
405    cJSON *cardNode = cJSON_GetObjectItem(g_cJsonObj, renderParam->renderMode.hwInfo.cardServiceName);
406    if (cardNode == NULL) {
407        AUDIO_FUNC_LOGE(
408            "failed to check item when [%{public}s] gets object!", renderParam->renderMode.hwInfo.cardServiceName);
409        return HDF_FAILURE;
410    }
411    cJSON *cardList = cardNode->child;
412    if (cardList == NULL) {
413        AUDIO_FUNC_LOGE("no child when [%{public}s] gets object!", renderParam->renderMode.hwInfo.cardServiceName);
414        return HDF_FAILURE;
415    }
416
417    cJSON *useCaseNode = cJSON_GetObjectItem(cardList, useCase);
418    if (useCaseNode == NULL) {
419        AUDIO_FUNC_LOGE("failed to check item when [%{public}s] gets object!", useCase);
420        return HDF_FAILURE;
421    }
422
423    cJSON *useCaseList = useCaseNode->child;
424    if (useCaseList == NULL) {
425        AUDIO_FUNC_LOGE("no child when [%{public}s] gets object!", useCase);
426        return HDF_FAILURE;
427    }
428
429    int32_t len = cJSON_GetArraySize(useCaseList);
430    if (len < 0 || len > HDF_PATH_NUM_MAX) {
431        AUDIO_FUNC_LOGE("len is invalid!");
432        return HDF_FAILURE;
433    }
434    for (int32_t i = 0; i < len; i++) {
435        cJSON *tmpValue = cJSON_GetArrayItem(useCaseList, i);
436        /* Each device in the incoming scene */
437        int32_t ret = AudioRenderParseDevice(renderParam, tmpValue);
438        if (ret != HDF_SUCCESS) {
439            return ret;
440        }
441    }
442    return HDF_SUCCESS;
443}
444
445static int32_t AudioPathSelGetPlanRender(struct AudioHwRenderParam *renderParam)
446{
447    if (renderParam == NULL) {
448        AUDIO_FUNC_LOGE("param Is NULL");
449        return HDF_ERR_INVALID_PARAM;
450    }
451    const char *useCase = AudioPathSelGetUseCase(renderParam->frameRenderMode.attrs.type);
452    if (useCase == NULL) {
453        AUDIO_FUNC_LOGE("useCase not support!");
454        return HDF_FAILURE;
455    }
456    return AudioRenderParseUsecase(renderParam, useCase);
457}
458
459static int32_t SetCapturePathValue(
460    int32_t tpins, cJSON *captureSwitchObj, struct AudioHwCaptureParam *captureParam, int32_t value)
461{
462    if (captureParam == NULL || captureSwitchObj == NULL) {
463        AUDIO_FUNC_LOGE("param Is NULL");
464        return HDF_ERR_INVALID_PARAM;
465    }
466    const char *captureDeviceType = AudioPathSelGetDeviceType(tpins);
467    if (captureDeviceType == NULL) {
468        AUDIO_FUNC_LOGE("DeviceType not found.");
469        return HDF_FAILURE;
470    }
471
472    int32_t devNum = captureParam->captureMode.hwInfo.pathSelect.deviceInfo.deviceNum;
473    if (strcasecmp(captureDeviceType, captureSwitchObj->string) == 0) {
474        int32_t pathNum = cJSON_GetArraySize(captureSwitchObj);
475        if (pathNum < 0 || pathNum > HDF_PATH_NUM_MAX) {
476            AUDIO_FUNC_LOGE("pathNum is invalid!");
477            return HDF_FAILURE;
478        }
479        for (int32_t i = 0; i < pathNum; i++) {
480            cJSON *captureTmpValue = cJSON_GetArrayItem(captureSwitchObj, i);
481            cJSON *swName = captureTmpValue->child;
482            cJSON *swVal = swName->next;
483            if (swName->valuestring == NULL) {
484                AUDIO_FUNC_LOGE("ValueString is null!");
485                return HDF_FAILURE;
486            }
487
488            (void)memset_s(captureParam->captureMode.hwInfo.pathSelect.deviceInfo.deviceSwitchs[devNum].deviceSwitch,
489                PATHPLAN_LEN, 0, PATHPLAN_LEN);
490            int32_t ret =
491                strncpy_s(captureParam->captureMode.hwInfo.pathSelect.deviceInfo.deviceSwitchs[devNum].deviceSwitch,
492                    PATHPLAN_COUNT, swName->valuestring, strlen(swName->valuestring) + 1);
493            if (ret != 0) {
494                AUDIO_FUNC_LOGE("strcpy_s failed!");
495                return HDF_FAILURE;
496            }
497            if (swVal->valueint > AUDIO_DEV_ON) {
498                /* alsa Adaptation */
499                captureParam->captureMode.hwInfo.pathSelect.deviceInfo.deviceSwitchs[devNum].value = swVal->valueint;
500            } else {
501                captureParam->captureMode.hwInfo.pathSelect.deviceInfo.deviceSwitchs[devNum].value = value;
502            }
503
504            devNum++;
505        }
506        captureParam->captureMode.hwInfo.pathSelect.deviceInfo.deviceNum = devNum;
507    }
508    return HDF_SUCCESS;
509}
510
511static int32_t SetMatchCaptureDevicePath(
512    struct AudioHwCaptureParam *captureParam, cJSON *cJsonObj, int32_t tpins, char *deviceType, int32_t value)
513{
514    if (captureParam == NULL || cJsonObj == NULL) {
515        AUDIO_FUNC_LOGE("param Is NULL");
516        return HDF_ERR_INVALID_PARAM;
517    }
518    if (strcasecmp(cJsonObj->string, deviceType) == 0) {
519        int32_t ret = SetCapturePathValue(tpins, cJsonObj, captureParam, value);
520        if (ret != HDF_SUCCESS) {
521            AUDIO_FUNC_LOGE("set value failed!");
522            return ret;
523        }
524    }
525    return HDF_SUCCESS;
526}
527
528static int32_t SetMatchCaptureDefaultDevicePath(struct AudioHwCaptureParam *captureParam, cJSON *cJsonObj)
529{
530    int32_t ret;
531    if (captureParam == NULL || cJsonObj == NULL) {
532        AUDIO_FUNC_LOGE("param Is NULL");
533        return HDF_ERR_INVALID_PARAM;
534    }
535    for (uint32_t i = PIN_IN_MIC; i <= PIN_IN_BLUETOOTH_SCO_HEADSET;
536         i = (1 << INPUT_OFFSET) | ((i & OUTPUT_MASK) << 1)) {
537        const char *deviceType = AudioPathSelGetDeviceType((int32_t)i);
538        if (deviceType == NULL) {
539            AUDIO_FUNC_LOGE("DeviceType not found.");
540            return HDF_FAILURE;
541        }
542
543        if (strcasecmp(deviceType, cJsonObj->string) == 0) {
544            ret = SetCapturePathDefaultValue(cJsonObj, captureParam);
545            if (ret != HDF_SUCCESS) {
546                AUDIO_FUNC_LOGE("set default value failed!");
547                return ret;
548            }
549            break;
550        }
551    }
552    return HDF_SUCCESS;
553}
554
555static int32_t SetMatchCaptureOtherDevicePath(
556    struct AudioHwCaptureParam *captureParam, cJSON *cJsonObj, int32_t tpins, int32_t value)
557{
558    int32_t ret;
559    uint32_t i;
560    if (captureParam == NULL || cJsonObj == NULL) {
561        AUDIO_FUNC_LOGE("param Is NULL");
562        return HDF_ERR_INVALID_PARAM;
563    }
564    for (i = PIN_IN_MIC; i <= PIN_IN_BLUETOOTH_SCO_HEADSET; i = (1 << INPUT_OFFSET) | ((i & OUTPUT_MASK) << 1)) {
565        if ((i & tpins) == i) { /* Select which device to open and get the pin of which device */
566            ret = SetCapturePathValue((int32_t)i, cJsonObj, captureParam, value);
567            if (ret != HDF_SUCCESS) {
568                AUDIO_FUNC_LOGE("set value failed!");
569                continue;
570            }
571        }
572    }
573    return HDF_SUCCESS;
574}
575
576static int32_t AudioCaptureParseDevice(struct AudioHwCaptureParam *captureParam, cJSON *cJsonObj)
577{
578    int32_t ret;
579    if (captureParam == NULL || cJsonObj == NULL) {
580        AUDIO_FUNC_LOGE("param Is NULL");
581        return HDF_ERR_INVALID_PARAM;
582    }
583    uint32_t pins = captureParam->captureMode.hwInfo.deviceDescript.pins;
584
585    if (!((pins >> INPUT_OFFSET) & 0x01)) {
586        AUDIO_FUNC_LOGE("pins: %{public}d, error!", pins);
587        return HDF_FAILURE;
588    }
589
590    if (strcasecmp(cJsonObj->string, SPEAKER) == 0 || strcasecmp(cJsonObj->string, HEADPHONES) == 0 ||
591        strcasecmp(cJsonObj->string, EARPIECE) == 0  || strcasecmp(cJsonObj->string, BLUETOOTH_SCO) == 0) {
592        return HDF_SUCCESS;
593    }
594
595    int32_t tpins = pins & INPUT_MASK;
596    switch (tpins) {
597        case (1 << INPUT_OFFSET):
598            /* pins = 0, parse default value */
599            ret = SetMatchCaptureDefaultDevicePath(captureParam, cJsonObj);
600            break;
601        case PIN_IN_MIC:
602            /* 1.open main mic */
603            ret = SetMatchCaptureDevicePath(captureParam, cJsonObj, tpins, MIC, AUDIO_DEV_ON);
604#ifndef ALSA_LIB_MODE
605            /* 2.close headset mic */
606            ret |= SetMatchCaptureDevicePath(captureParam, cJsonObj, PIN_IN_HS_MIC, HS_MIC, AUDIO_DEV_OFF);
607#endif
608            break;
609        case PIN_IN_HS_MIC:
610            /* 1、open headset mic */
611            ret = SetMatchCaptureDevicePath(captureParam, cJsonObj, tpins, HS_MIC, AUDIO_DEV_ON);
612#ifndef ALSA_LIB_MODE
613            /* 2、close main mic */
614            ret |= SetMatchCaptureDevicePath(captureParam, cJsonObj, PIN_IN_MIC, MIC, AUDIO_DEV_OFF);
615#endif
616            break;
617        case PIN_IN_BLUETOOTH_SCO_HEADSET:
618            /* 1、open bluetooth sco headset mic */
619            ret = SetMatchCaptureDevicePath(captureParam, cJsonObj, tpins, BLUETOOTH_SCO_HEADSET, AUDIO_DEV_ON);
620            break;
621        default:
622            ret = SetMatchCaptureOtherDevicePath(captureParam, cJsonObj, tpins, AUDIO_DEV_ON);
623            break;
624    }
625    return ret;
626}
627
628static int32_t AudioCaptureParseUsecase(struct AudioHwCaptureParam *captureParam, const char *useCase)
629{
630    if (captureParam == NULL || useCase == NULL) {
631        AUDIO_FUNC_LOGE("param Is NULL");
632        return HDF_ERR_INVALID_PARAM;
633    }
634    /* reset path numbers */
635    captureParam->captureMode.hwInfo.pathSelect.deviceInfo.deviceNum = 0;
636
637    cJSON *cardNode = cJSON_GetObjectItem(g_cJsonObj, captureParam->captureMode.hwInfo.cardServiceName);
638    if (cardNode == NULL) {
639        AUDIO_FUNC_LOGE(
640            "failed to check item when [%{public}s] gets object!", captureParam->captureMode.hwInfo.cardServiceName);
641        return HDF_FAILURE;
642    }
643    cJSON *cardList = cardNode->child;
644    if (cardList == NULL) {
645        AUDIO_FUNC_LOGE("no child when [%{public}s] gets object!", captureParam->captureMode.hwInfo.cardServiceName);
646        return HDF_FAILURE;
647    }
648
649    cJSON *useCaseNode = cJSON_GetObjectItem(cardList, useCase);
650    if (useCaseNode == NULL) {
651        AUDIO_FUNC_LOGE("failed to check item when [%{public}s] gets object!", useCase);
652        return HDF_FAILURE;
653    }
654    cJSON *useCaseList = useCaseNode->child;
655    if (useCaseList == NULL) {
656        AUDIO_FUNC_LOGE("no child when [%{public}s] gets object!", useCase);
657        return HDF_FAILURE;
658    }
659
660    int32_t len = cJSON_GetArraySize(useCaseList);
661    if (len < 0 || len > HDF_PATH_NUM_MAX) {
662        AUDIO_FUNC_LOGE("len is invalid!");
663        return HDF_FAILURE;
664    }
665    for (int32_t i = 0; i < len; i++) {
666        cJSON *tmpValue = cJSON_GetArrayItem(useCaseList, i);
667        int32_t ret = AudioCaptureParseDevice(captureParam, tmpValue);
668        if (ret != HDF_SUCCESS) {
669            return ret;
670        }
671    }
672    return HDF_SUCCESS;
673}
674
675static int32_t AudioPathSelGetPlanCapture(struct AudioHwCaptureParam *captureParam)
676{
677    enum AudioCategory type = captureParam->frameCaptureMode.attrs.type;
678
679    if (type == AUDIO_IN_RINGTONE) {
680        AUDIO_FUNC_LOGE("useCase not support!");
681        return HDF_ERR_NOT_SUPPORT;
682    }
683
684    if (type == AUDIO_MMAP_NOIRQ) {
685        AUDIO_FUNC_LOGE("useCase set as AUDIO_IN_MEDIA");
686        type = AUDIO_IN_MEDIA;
687    }
688
689    const char *useCase = AudioPathSelGetUseCase(type);
690    if (useCase == NULL) {
691        AUDIO_FUNC_LOGE("useCase not support!");
692        return HDF_FAILURE;
693    }
694
695    return AudioCaptureParseUsecase(captureParam, useCase);
696}
697
698static int32_t AudioPathSelRenderChkScene(struct AudioHwRenderParam *renderSceneParam)
699{
700    return AudioPathSelGetPlanRender(renderSceneParam);
701}
702
703static int32_t AudioPathSelCaptureChkScene(struct AudioHwCaptureParam *captureSceneParam)
704{
705    return AudioPathSelGetPlanCapture(captureSceneParam);
706}
707
708int32_t AudioPathSelAnalysisJson(const AudioHandle adapterParam, enum AudioAdaptType adaptType)
709{
710    AUDIO_FUNC_LOGI();
711    if (adaptType < 0 || adapterParam == NULL) {
712        AUDIO_FUNC_LOGE("Param Invaild!");
713        return HDF_ERR_INVALID_PARAM;
714    }
715    struct AudioHwRenderParam *renderParam = NULL;
716    struct AudioHwCaptureParam *captureParam = NULL;
717    struct AudioHwRenderParam *renderSceneCheck = NULL;
718    struct AudioHwCaptureParam *captureScenceCheck = NULL;
719    switch (adaptType) {
720        case RENDER_PATH_SELECT:
721            renderParam = (struct AudioHwRenderParam *)adapterParam;
722            if (strcasecmp(renderParam->renderMode.hwInfo.adapterName, USB) == 0 ||
723                strcasecmp(renderParam->renderMode.hwInfo.adapterName, HDMI) == 0) {
724                return HDF_SUCCESS;
725            }
726            return (AudioPathSelGetPlanRender(renderParam));
727        case CAPTURE_PATH_SELECT:
728            captureParam = (struct AudioHwCaptureParam *)adapterParam;
729            if (strcasecmp(captureParam->captureMode.hwInfo.adapterName, USB) == 0 ||
730                strcasecmp(captureParam->captureMode.hwInfo.adapterName, HDMI) == 0) {
731                return HDF_SUCCESS;
732            }
733            return (AudioPathSelGetPlanCapture(captureParam));
734        /* Scene is supported */
735        case CHECKSCENE_PATH_SELECT:
736            renderSceneCheck = (struct AudioHwRenderParam *)adapterParam;
737            if (strcasecmp(renderSceneCheck->renderMode.hwInfo.adapterName, USB) == 0 ||
738                strcasecmp(renderSceneCheck->renderMode.hwInfo.adapterName, HDMI) == 0) {
739                return HDF_SUCCESS;
740            }
741            return (AudioPathSelRenderChkScene(renderSceneCheck));
742        case CHECKSCENE_PATH_SELECT_CAPTURE:
743            captureScenceCheck = (struct AudioHwCaptureParam *)adapterParam;
744            if (strcasecmp(captureScenceCheck->captureMode.hwInfo.adapterName, USB) == 0 ||
745                strcasecmp(captureScenceCheck->captureMode.hwInfo.adapterName, HDMI) == 0) {
746                return HDF_SUCCESS;
747            }
748            return (AudioPathSelCaptureChkScene(captureScenceCheck));
749        default:
750            AUDIO_FUNC_LOGE("Path select mode invalid");
751            break;
752    }
753    return HDF_FAILURE;
754}
755