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 
47 static cJSON *g_cJsonObj = NULL;
48 
AudioPathSelGetConfToJsonObj(void)49 int32_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 
AudioPathSelGetDeviceType(enum AudioPortPin pin)99 static 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 
AudioPathSelGetUseCase(enum AudioCategory type)127 static 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 
SetRenderPathDefaultValue(cJSON * renderSwObj,struct AudioHwRenderParam * renderParam)143 static 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 
SetCapturePathDefaultValue(cJSON * captureSwObj,struct AudioHwCaptureParam * captureParam)185 static 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 
SetRenderPathValue(int32_t tpins,cJSON * renderObj,struct AudioHwRenderParam * renderParam,int32_t value)226 static 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 
SetMatchRenderDevicePath(int32_t tpins,struct AudioHwRenderParam * renderParam,cJSON * cJsonObj,const char * deviceType,int32_t value)280 static 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 
SetMatchRenderDefaultDevicePath(struct AudioHwRenderParam * renderParam,cJSON * cJsonObj)297 static 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 
SetMatchRenderOtherDevicePath(int32_t tpins,struct AudioHwRenderParam * renderParam,cJSON * cJsonObj,int32_t value)322 static 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 
AudioRenderParseDevice(struct AudioHwRenderParam * renderParam,cJSON * cJsonObj)342 static 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 
AudioRenderParseUsecase(struct AudioHwRenderParam * renderParam,const char * useCase)400 static 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 
AudioPathSelGetPlanRender(struct AudioHwRenderParam * renderParam)445 static 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 
SetCapturePathValue(int32_t tpins,cJSON * captureSwitchObj,struct AudioHwCaptureParam * captureParam,int32_t value)459 static 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 
SetMatchCaptureDevicePath(struct AudioHwCaptureParam * captureParam,cJSON * cJsonObj,int32_t tpins,char * deviceType,int32_t value)511 static 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 
SetMatchCaptureDefaultDevicePath(struct AudioHwCaptureParam * captureParam,cJSON * cJsonObj)528 static 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 
SetMatchCaptureOtherDevicePath(struct AudioHwCaptureParam * captureParam,cJSON * cJsonObj,int32_t tpins,int32_t value)555 static 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 
AudioCaptureParseDevice(struct AudioHwCaptureParam * captureParam,cJSON * cJsonObj)576 static 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 
AudioCaptureParseUsecase(struct AudioHwCaptureParam * captureParam,const char * useCase)628 static 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 
AudioPathSelGetPlanCapture(struct AudioHwCaptureParam * captureParam)675 static 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 
AudioPathSelRenderChkScene(struct AudioHwRenderParam * renderSceneParam)698 static int32_t AudioPathSelRenderChkScene(struct AudioHwRenderParam *renderSceneParam)
699 {
700     return AudioPathSelGetPlanRender(renderSceneParam);
701 }
702 
AudioPathSelCaptureChkScene(struct AudioHwCaptureParam * captureSceneParam)703 static int32_t AudioPathSelCaptureChkScene(struct AudioHwCaptureParam *captureSceneParam)
704 {
705     return AudioPathSelGetPlanCapture(captureSceneParam);
706 }
707 
AudioPathSelAnalysisJson(const AudioHandle adapterParam,enum AudioAdaptType adaptType)708 int32_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