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 "alsa_snd_render.h"
18 #include "osal_time.h"
19 
20 #define HDF_LOG_TAG HDF_AUDIO_HAL_RENDER
21 
22 #define MAX_PERIOD_SIZE                (8 * 1024)
23 #define MIN_PERIOD_SIZE                (4 * 1024)
24 #define AUDIO_RENDER_RECOVER_DELAY     (10 * 1000)
25 #define POLL_EVENT_DEF false
26 #define AUDIO_BUFFER_TIME_DEF 500000
27 #define AUDIO_PERIOD_TIME_DEF 100000
28 #define AUDIO_PERIOD_TIME_RATIO 4
29 #define BIT_COUNT_OF_BYTE       8
30 #define PCM_WAIT_TIMEOUT_MS     100
31 #ifdef SUPPORT_ALSA_CHMAP
32 #define CHMAP_NAME_LENGHT_MAX      256
33 
34 /* channel map list type */
35 #define CHANNEL_MAP_TYPE_FIXED    "FIXED"  /* fixed channel position */
36 #define CHANNEL_MAP_TYPE_VAR      "VAR"    /* freely swappable channel position */
37 #define CHANNEL_MAP_TYPE_PAIRED   "PAIRED" /* pair-wise swappable channel position */
38 #endif
39 
40 static struct AlsaRender *g_alsaRenderList = NULL;
41 static void RegisterRenderImpl(struct AlsaRender *renderIns);
42 
RenderSetPriData(struct AlsaRender * renderIns,RenderPriData data)43 void RenderSetPriData(struct AlsaRender *renderIns, RenderPriData data)
44 {
45     renderIns->priData = data;
46 }
47 
RenderGetPriData(struct AlsaRender * renderIns)48 RenderPriData RenderGetPriData(struct AlsaRender *renderIns)
49 {
50     return renderIns->priData;
51 }
52 
CreateRenderIns(void)53 static int32_t CreateRenderIns(void)
54 {
55     if (g_alsaRenderList == NULL) {
56         g_alsaRenderList = (struct AlsaRender *)OsalMemCalloc(MAX_CARD_NUM * sizeof(struct AlsaRender));
57         if (g_alsaRenderList == NULL) {
58             AUDIO_FUNC_LOGE("Failed to allocate memory!");
59             return HDF_FAILURE;
60         }
61     }
62     return HDF_SUCCESS;
63 }
64 
RenderFreeMemory(void)65 static int32_t RenderFreeMemory(void)
66 {
67     if (g_alsaRenderList != NULL) {
68         for (int32_t i = 0; i < MAX_CARD_NUM; i++) {
69             if (g_alsaRenderList[i].soundCard.cardStatus != 0) {
70                 AUDIO_FUNC_LOGE("refCount is not zero, Sound card in use!");
71                 return HDF_ERR_DEVICE_BUSY;
72             }
73 
74             if (g_alsaRenderList[i].priData != NULL) {
75                 OsalMemFree(g_alsaRenderList[i].priData);
76                 g_alsaRenderList[i].priData = NULL;
77             }
78         }
79         AudioMemFree((void **)&g_alsaRenderList);
80         g_alsaRenderList = NULL;
81     }
82 
83     return HDF_SUCCESS;
84 }
85 
SetHWParamsSub(snd_pcm_t * handle,snd_pcm_hw_params_t * params,const struct AudioPcmHwParams * hwParams,snd_pcm_access_t access)86 static int32_t SetHWParamsSub(
87     snd_pcm_t *handle, snd_pcm_hw_params_t *params, const struct AudioPcmHwParams *hwParams, snd_pcm_access_t access)
88 {
89     snd_pcm_format_t pcmFormat = SND_PCM_FORMAT_S16_LE;
90     CHECK_NULL_PTR_RETURN_DEFAULT(handle);
91     CHECK_NULL_PTR_RETURN_DEFAULT(params);
92 
93     /* set hardware resampling,enable alsa-lib resampling */
94     int32_t ret = snd_pcm_hw_params_set_rate_resample(handle, params, 1);
95     if (ret < 0) {
96         AUDIO_FUNC_LOGE("Resampling setup failed for playback: %{public}s", snd_strerror(ret));
97         return HDF_FAILURE;
98     }
99     /* set the interleaved read/write format */
100     ret = snd_pcm_hw_params_set_access(handle, params, access);
101     if (ret < 0) {
102         AUDIO_FUNC_LOGE("Access type not available for playback: %{public}s", snd_strerror(ret));
103         return HDF_FAILURE;
104     }
105     ret = SndConverAlsaPcmFormat(hwParams, &pcmFormat);
106     if (ret < 0) {
107         AUDIO_FUNC_LOGE("SndConverAlsaPcmFormat error.");
108         return HDF_FAILURE;
109     }
110     /* set the sample format */
111     ret = snd_pcm_hw_params_set_format(handle, params, pcmFormat);
112     if (ret < 0) {
113         AUDIO_FUNC_LOGE("Sample format not available for playback: %{public}s, format: %{public}d",
114             snd_strerror(ret), pcmFormat);
115         return HDF_FAILURE;
116     }
117     /* set the count of channels */
118     ret = snd_pcm_hw_params_set_channels(handle, params, hwParams->channels);
119     if (ret < 0) {
120         AUDIO_FUNC_LOGE("Channels count (%{public}u) not available for playbacks: %{public}s", hwParams->channels,
121             snd_strerror(ret));
122         return HDF_FAILURE;
123     }
124 
125     return HDF_SUCCESS;
126 }
127 
SetHWRate(snd_pcm_t * handle,snd_pcm_hw_params_t * params,uint32_t * rate)128 static int32_t SetHWRate(snd_pcm_t *handle, snd_pcm_hw_params_t *params, uint32_t *rate)
129 {
130     int dir = 0; /* dir Value range (-1,0,1) */
131     CHECK_NULL_PTR_RETURN_DEFAULT(handle);
132     CHECK_NULL_PTR_RETURN_DEFAULT(params);
133     CHECK_NULL_PTR_RETURN_DEFAULT(rate);
134 
135     /* set the stream rate */
136     uint32_t rRate = *rate;
137     int32_t ret = snd_pcm_hw_params_set_rate_near(handle, params, &rRate, &dir);
138     if (ret < 0) {
139         AUDIO_FUNC_LOGE("Rate %{public}uHz not available for playback: %{public}s.", *rate, snd_strerror(ret));
140         return HDF_FAILURE;
141     }
142 
143     if (rRate != *rate) {
144         ret = snd_pcm_hw_params_set_rate_near(handle, params, &rRate, &dir);
145         if (ret < 0) {
146             AUDIO_FUNC_LOGE("Rate %{public}uHz not available for playback: %{public}s.", *rate, snd_strerror(ret));
147             return HDF_FAILURE;
148         }
149     }
150     /* Update to hardware supported rate */
151     *rate = rRate;
152 
153     return HDF_SUCCESS;
154 }
155 
SetHWParams(struct AlsaSoundCard * cardIns,snd_pcm_access_t access)156 static int32_t SetHWParams(struct AlsaSoundCard *cardIns, snd_pcm_access_t access)
157 {
158     int dir = 0; /* dir Value range (-1,0,1) */
159     snd_pcm_uframes_t size;
160     snd_pcm_hw_params_t *hwParams = NULL;
161     struct AlsaRender *renderIns = (struct AlsaRender*)cardIns;
162     CHECK_NULL_PTR_RETURN_DEFAULT(cardIns->pcmHandle);
163 
164     snd_pcm_hw_params_alloca(&hwParams);
165     if (snd_pcm_hw_params_any(cardIns->pcmHandle, hwParams) < 0) {
166         AUDIO_FUNC_LOGE("No configurations available");
167         return HDF_FAILURE;
168     }
169     if (SetHWParamsSub(cardIns->pcmHandle, hwParams, &cardIns->hwParams, access) != HDF_SUCCESS) {
170         AUDIO_FUNC_LOGE("SetHWParamsSub failed!");
171         return HDF_FAILURE;
172     }
173     if (SetHWRate(cardIns->pcmHandle, hwParams, &(cardIns->hwParams.rate)) != HDF_SUCCESS) {
174         AUDIO_FUNC_LOGE("SetHWRate failed!");
175         return HDF_FAILURE;
176     }
177     snd_pcm_hw_params_get_buffer_time_max(hwParams, &renderIns->bufferTime, &dir);
178     if (renderIns->bufferTime > AUDIO_BUFFER_TIME_DEF) {
179         renderIns->bufferTime = AUDIO_BUFFER_TIME_DEF;
180     }
181     renderIns->periodTime = renderIns->bufferTime / AUDIO_PERIOD_TIME_RATIO;
182     if (snd_pcm_hw_params_set_buffer_time_near(cardIns->pcmHandle, hwParams, &renderIns->bufferTime, &dir) < 0) {
183         AUDIO_FUNC_LOGE("Set buffer time %{public}u failed", renderIns->bufferTime);
184         return HDF_FAILURE;
185     }
186     if (snd_pcm_hw_params_get_buffer_size(hwParams, &size) < 0) {
187         AUDIO_FUNC_LOGE("Unable to get buffer size for playback");
188         return HDF_FAILURE;
189     }
190     renderIns->bufferSize = size;
191     if (snd_pcm_hw_params_set_period_time_near(cardIns->pcmHandle, hwParams, &renderIns->periodTime, &dir) < 0) {
192         AUDIO_FUNC_LOGE("Set period time %{public}u failed", renderIns->bufferTime);
193         return HDF_FAILURE;
194     }
195     if (snd_pcm_hw_params_get_period_size(hwParams, &size, &dir) < 0) {
196         AUDIO_FUNC_LOGE("Unable to get period size for playback");
197         return HDF_FAILURE;
198     }
199     renderIns->periodSize = size;
200     if (snd_pcm_hw_params(cardIns->pcmHandle, hwParams) < 0) {
201         AUDIO_FUNC_LOGE("Unable to set hw params for playback");
202         return HDF_FAILURE;
203     }
204 
205     cardIns->canPause = snd_pcm_hw_params_can_pause(hwParams);
206     return HDF_SUCCESS;
207 }
208 
SetSWParams(struct AlsaSoundCard * cardIns)209 static int32_t SetSWParams(struct AlsaSoundCard *cardIns)
210 {
211     snd_pcm_sw_params_t *swParams = NULL;
212     snd_pcm_t *handle = cardIns->pcmHandle;
213     struct AlsaRender *renderIns = (struct AlsaRender *)cardIns;
214     CHECK_NULL_PTR_RETURN_DEFAULT(handle);
215 
216     snd_pcm_sw_params_alloca(&swParams);
217 
218     /* get the current swparams */
219     int32_t ret = snd_pcm_sw_params_current(handle, swParams);
220     if (ret < 0) {
221         AUDIO_FUNC_LOGE("Unable to determine current swparams for playback: %{public}s", snd_strerror(ret));
222         return HDF_FAILURE;
223     }
224     /* start the transfer when the buffer is almost full: */
225     /* (buffer_size / avail_min) * avail_min */
226     if (renderIns->periodSize == 0) {
227         AUDIO_FUNC_LOGE("g_periodSize=0");
228         return HDF_FAILURE;
229     }
230     ret = snd_pcm_sw_params_set_start_threshold(handle, swParams,
231         (renderIns->bufferSize / renderIns->periodSize) * renderIns->periodSize);
232     if (ret < 0) {
233         AUDIO_FUNC_LOGE("Unable to set start threshold mode for playback: %{public}s", snd_strerror(ret));
234         return HDF_FAILURE;
235     }
236     /* allow the transfer when at least period_size samples can be processed */
237     /* or disable this mechanism when period event is enabled (aka interrupt like style processing) */
238     ret = snd_pcm_sw_params_set_avail_min(handle, swParams,
239         renderIns->periodEvent ? renderIns->bufferSize : renderIns->periodSize);
240     if (ret < 0) {
241         AUDIO_FUNC_LOGE("Unable to set avail min for playback: %{public}s", snd_strerror(ret));
242         return HDF_FAILURE;
243     }
244 
245     /* enable period events when requested */
246     if (renderIns->periodEvent) {
247         int32_t val = 1; /* val 0 = disable period event, 1 = enable period event */
248         ret = snd_pcm_sw_params_set_period_event(handle, swParams, val);
249         if (ret < 0) {
250             AUDIO_FUNC_LOGE("Unable to set period event: %{public}s", snd_strerror(ret));
251             return HDF_FAILURE;
252         }
253     }
254 
255     /* write the parameters to the playback device */
256     ret = snd_pcm_sw_params(handle, swParams);
257     if (ret < 0) {
258         AUDIO_FUNC_LOGE("Unable to set sw params for playback: %{public}s", snd_strerror(ret));
259         return HDF_FAILURE;
260     }
261 
262     return HDF_SUCCESS;
263 }
264 
ResetRenderParams(struct AlsaSoundCard * cardIns,snd_pcm_access_t access)265 static int32_t ResetRenderParams(struct AlsaSoundCard *cardIns, snd_pcm_access_t access)
266 {
267     CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
268 
269     int32_t ret = SetHWParams(cardIns, access);
270     if (ret != HDF_SUCCESS) {
271         AUDIO_FUNC_LOGE("Setting of hwparams failed.");
272         return ret;
273     }
274 
275     ret = SetSWParams(cardIns);
276     if (ret != HDF_SUCCESS) {
277         AUDIO_FUNC_LOGE("Setting of swparams failed.");
278         return ret;
279     }
280 
281     return HDF_SUCCESS;
282 }
283 
GetRenderInsByName(const char * adapterName)284 static struct AlsaRender *GetRenderInsByName(const char *adapterName)
285 {
286     struct AlsaRender *renderIns = NULL;
287     struct AlsaSoundCard *alsaSnd = NULL;
288 
289     /*
290     fine the instance with the corresponding adapter name, or create one if none.
291     */
292     for (int32_t i = 0; i < MAX_CARD_NUM; i++) {
293         alsaSnd = (struct AlsaSoundCard *)&g_alsaRenderList[i];
294         if (alsaSnd->cardStatus) {
295             if (0 == strcmp(alsaSnd->adapterName, adapterName)) {
296                 return &g_alsaRenderList[i];
297             }
298         }
299     }
300 
301     for (int32_t i = 0; i < MAX_CARD_NUM; i++) {
302         renderIns = &g_alsaRenderList[i];
303         alsaSnd = (struct AlsaSoundCard *)&g_alsaRenderList[i];
304         if (alsaSnd->cardStatus == 0) {
305             (void)memset_s(renderIns, sizeof(struct AlsaRender), 0, sizeof(struct AlsaRender));
306             int32_t ret = strncpy_s(alsaSnd->adapterName, MAX_CARD_NAME_LEN + 1, adapterName, strlen(adapterName));
307             if (ret != 0) {
308                 AUDIO_FUNC_LOGE("strncpy_s failed!");
309                 return NULL;
310             }
311             alsaSnd->cardStatus++;
312             renderIns->periodEvent = POLL_EVENT_DEF;
313             renderIns->periodTime = AUDIO_PERIOD_TIME_DEF;
314             renderIns->bufferTime = AUDIO_BUFFER_TIME_DEF;
315             renderIns->descPins = PIN_NONE;
316             renderIns->resample = 1;
317             return renderIns;
318         }
319     }
320     AUDIO_FUNC_LOGE("Failed to AddCardIns!");
321     return NULL;
322 }
323 
RenderCreateInstance(const char * adapterName)324 struct AlsaRender *RenderCreateInstance(const char* adapterName)
325 {
326     struct AlsaRender *renderIns = NULL;
327     if (adapterName == NULL || strlen(adapterName) == 0) {
328         AUDIO_FUNC_LOGE("Invalid adapterName!");
329         return NULL;
330     }
331 
332     int32_t ret = CreateRenderIns();
333     if (ret != HDF_SUCCESS) {
334         AUDIO_FUNC_LOGE("Failed to create render instance.");
335         return NULL;
336     }
337 
338     renderIns = GetRenderInsByName(adapterName);
339     if (renderIns == NULL) {
340         AUDIO_FUNC_LOGE("get render instance failed.");
341         return NULL;
342     }
343     RegisterRenderImpl(renderIns);
344 
345     ret = SndSaveCardListInfo(SND_PCM_STREAM_PLAYBACK);
346     if (ret != HDF_SUCCESS) {
347         AUDIO_FUNC_LOGE("Failed to save card device info.");
348         return NULL;
349     }
350 
351     ret = SndMatchSelAdapter(&renderIns->soundCard, adapterName);
352     if (ret != HDF_SUCCESS) {
353         SndCloseHandle(&renderIns->soundCard);
354         RenderFreeMemory();
355         return NULL;
356     }
357 
358     RenderOverrideFunc(renderIns);
359     return renderIns;
360 }
361 
RenderGetInstance(const char * adapterName)362 struct AlsaRender *RenderGetInstance(const char *adapterName)
363 {
364     if (adapterName == NULL || strlen(adapterName) == 0) {
365         AUDIO_FUNC_LOGE("Invalid adapterName!");
366         return NULL;
367     }
368 
369     if (g_alsaRenderList == NULL) {
370         AUDIO_FUNC_LOGE("g_alsaRenderList is NULL!");
371         return NULL;
372     }
373 
374     for (int32_t i = 0; i < MAX_CARD_NUM; i++) {
375         if (strcmp(g_alsaRenderList[i].soundCard.adapterName, adapterName) == 0) {
376             return &(g_alsaRenderList[i]);
377         }
378     }
379 
380     return NULL;
381 }
382 
383 #ifdef SUPPORT_ALSA_CHMAP
GetChannelsNameFromUser(struct AlsaSoundCard * cardIns,const char * channelsName)384 static int32_t GetChannelsNameFromUser(struct AlsaSoundCard *cardIns, const char *channelsName)
385 {
386     if (channelsName == NULL) {
387         AUDIO_FUNC_LOGE("channelsName is NULL!");
388         return HDF_ERR_INVALID_PARAM;
389     }
390 
391     if (cardIns->hwParams.channelsName == NULL) {
392         cardIns->hwParams.channelsName = (char *)OsalMemCalloc(CHMAP_NAME_LENGHT_MAX);
393         if (cardIns->hwParams.channelsName == NULL) {
394             AUDIO_FUNC_LOGE("Failed to allocate memory!");
395             return HDF_ERR_MALLOC_FAIL;
396         }
397     }
398 
399     (void)memset_s(cardIns->hwParams.channelsName, CHMAP_NAME_LENGHT_MAX, 0, CHMAP_NAME_LENGHT_MAX);
400     int32_t ret = strncpy_s(cardIns->hwParams.channelsName, CHMAP_NAME_LENGHT_MAX - 1,
401         channelsName, strlen(channelsName));
402     if (ret != HDF_SUCCESS) {
403         AUDIO_FUNC_LOGE("strncpy_s failed!");
404         AudioMemFree((void **)&(cardIns->hwParams.channelsName));
405         return HDF_FAILURE;
406     }
407 
408     return HDF_SUCCESS;
409 }
410 #endif
411 
SaveHwParams(struct AlsaSoundCard * cardIns,const struct AudioHwRenderParam * handleData)412  static int32_t SaveHwParams(struct AlsaSoundCard *cardIns, const struct AudioHwRenderParam *handleData)
413 {
414     CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
415     CHECK_NULL_PTR_RETURN_DEFAULT(handleData);
416 
417     cardIns->hwParams.streamType = AUDIO_RENDER_STREAM;
418     cardIns->hwParams.channels = handleData->frameRenderMode.attrs.channelCount;
419     cardIns->hwParams.rate = handleData->frameRenderMode.attrs.sampleRate;
420     cardIns->hwParams.periodSize = handleData->frameRenderMode.periodSize;
421     cardIns->hwParams.periodCount = handleData->frameRenderMode.periodCount;
422     cardIns->hwParams.format = handleData->frameRenderMode.attrs.format;
423     cardIns->hwParams.period = handleData->frameRenderMode.attrs.period;
424     cardIns->hwParams.frameSize = handleData->frameRenderMode.attrs.frameSize;
425     cardIns->hwParams.isBigEndian = handleData->frameRenderMode.attrs.isBigEndian;
426     cardIns->hwParams.isSignedData = handleData->frameRenderMode.attrs.isSignedData;
427     cardIns->hwParams.startThreshold = handleData->frameRenderMode.attrs.startThreshold;
428     cardIns->hwParams.stopThreshold = handleData->frameRenderMode.attrs.stopThreshold;
429     cardIns->hwParams.silenceThreshold = handleData->frameRenderMode.attrs.silenceThreshold;
430 #ifdef SUPPORT_ALSA_CHMAP
431     /* param 2 by handleData->frameRenderMode.attrs.channelsName, sample channelsName is "FL, FR" */
432     if (GetChannelsNameFromUser(cardIns, "FL, FR") != HDF_SUCCESS) {
433         AUDIO_FUNC_LOGE("GetChannelsNameFromUser failed");
434         return HDF_FAILURE;
435     }
436 #endif
437 
438     return HDF_SUCCESS;
439 }
440 
441 #ifdef SUPPORT_ALSA_CHMAP
PrintChannels(const snd_pcm_chmap_t * map)442 static void PrintChannels(const snd_pcm_chmap_t *map)
443 {
444     char tmp[CHMAP_NAME_LENGHT_MAX] = {0};
445     if (snd_pcm_chmap_print(map, sizeof(tmp), tmp) > 0) {
446         HDF_LOGI("print_channels: %{public}s.", tmp);
447     }
448 }
449 
QueryChmaps(snd_pcm_t * pcm)450 static int32_t QueryChmaps(snd_pcm_t *pcm)
451 {
452     snd_pcm_chmap_query_t **pChmap = NULL;
453     snd_pcm_chmap_query_t *chmap = NULL;
454     const char *champType = NULL;
455     snd_pcm_chmap_query_t **hwChmap = snd_pcm_query_chmaps(pcm);
456     if (hwChmap == NULL) {
457         AUDIO_FUNC_LOGE("This sound card has no chmap component, cannot query maps.");
458         return HDF_FAILURE;
459     }
460 
461     for (pChmap = hwChmap; (chmap = *pChmap) != NULL; pChmap++) {
462         champType = snd_pcm_chmap_type_name(chmap->type);
463         HDF_LOGI("Channel Type = %{public}s, Channels = %{public}d.", champType, chmap->map.channels);
464         if (strncmp(champType, CHANNEL_MAP_TYPE_FIXED, strlen(CHANNEL_MAP_TYPE_FIXED)) == 0) {
465             HDF_LOGW("Fixed channel type does not support modification temporarily!");
466         }
467         PrintChannels(&chmap->map);
468     }
469 
470     snd_pcm_free_chmaps(hwChmap);
471     return HDF_SUCCESS;
472 }
473 
SetChmap(snd_pcm_t * pcm,struct AudioPcmHwParams * hwRenderParams)474 static int32_t SetChmap(snd_pcm_t *pcm, struct AudioPcmHwParams *hwRenderParams)
475 {
476     if (hwRenderParams == NULL || hwRenderParams->channelsName == NULL) {
477         AUDIO_FUNC_LOGE("Parameter is NULL!");
478         return HDF_FAILURE;
479     }
480 
481     snd_pcm_chmap_t *chmap = snd_pcm_chmap_parse_string(hwRenderParams->channelsName);
482     if (chmap == NULL) {
483         AUDIO_FUNC_LOGE("parse chmap error!");
484         return HDF_FAILURE;
485     }
486 
487     if (snd_pcm_set_chmap(pcm, chmap) < 0) {
488         AUDIO_FUNC_LOGE("Cannot set chmap!");
489         free((void *)chmap);
490         return HDF_ERR_NOT_SUPPORT;
491     }
492     free((void *)chmap);
493 
494     chmap = snd_pcm_get_chmap(pcm);
495     if (chmap == NULL) {
496         AUDIO_FUNC_LOGE("Cannot get chmap!");
497         return HDF_ERR_NOT_SUPPORT;
498     }
499 
500     PrintChannels(chmap);
501     free((void *)chmap);
502     return HDF_SUCCESS;
503 }
504 
RenderHwParamsChmaps(struct AlsaSoundCard * cardIns)505 static int32_t RenderHwParamsChmaps(struct AlsaSoundCard *cardIns)
506 {
507     if (QueryChmaps(cardIns->pcmHandle) != HDF_SUCCESS) {
508         AUDIO_FUNC_LOGW("QueryChmaps failed.");
509         return HDF_SUCCESS;
510     }
511     if (SetChmap(cardIns->pcmHandle, &cardIns->hwParams) != HDF_SUCCESS) {
512         AUDIO_FUNC_LOGW("SetChmap failed.");
513     }
514 
515     return HDF_SUCCESS;
516 }
517 #endif
518 
RenderSetParams(struct AlsaRender * renderIns,const struct AudioHwRenderParam * handleData)519 int32_t RenderSetParams(struct AlsaRender *renderIns, const struct AudioHwRenderParam *handleData)
520 {
521     struct AlsaSoundCard *cardIns = (struct AlsaSoundCard *)renderIns;
522     CHECK_NULL_PTR_RETURN_DEFAULT(renderIns);
523     CHECK_NULL_PTR_RETURN_DEFAULT(handleData);
524 
525     SaveHwParams(&renderIns->soundCard, handleData);
526     int32_t ret = SetHWParams(cardIns, SND_PCM_ACCESS_RW_INTERLEAVED);
527     if (ret < 0) {
528         AUDIO_FUNC_LOGE("Setting of hwparams failed.");
529         return HDF_FAILURE;
530     }
531 
532     ret = SetSWParams(cardIns);
533     if (ret < 0) {
534         AUDIO_FUNC_LOGE("Setting of swparams failed.");
535         return HDF_FAILURE;
536     }
537 
538 #ifdef SUPPORT_ALSA_CHMAP
539     ret = RenderHwParamsChmaps(&renderIns->soundCard);
540     if (ret < 0) {
541         AUDIO_FUNC_LOGE("Setting of chmaps failed.");
542     }
543 #endif
544     snd_pcm_format_t fmt;
545     SndConverAlsaPcmFormat(&cardIns->hwParams, &fmt);
546     int bitsPerSample = snd_pcm_format_physical_width(fmt);
547     cardIns->hwParams.bitsPerFrame = bitsPerSample * cardIns->hwParams.channels;
548 
549     return HDF_SUCCESS;
550 }
551 
RenderWritei(snd_pcm_t * pcm,const struct AudioHwRenderParam * handleData,const struct AudioPcmHwParams * hwParams)552 static int32_t RenderWritei(snd_pcm_t *pcm, const struct AudioHwRenderParam *handleData,
553     const struct AudioPcmHwParams *hwParams)
554 {
555     int32_t ret = HDF_SUCCESS;
556     int32_t tryNum = AUDIO_ALSALIB_RETYR;
557 
558     /* Check whether the PCM status is normal */
559     snd_pcm_state_t state = snd_pcm_state(pcm);
560     if (state == SND_PCM_STATE_SETUP) {
561         ret = snd_pcm_prepare(pcm);
562         if (ret < 0) {
563             AUDIO_FUNC_LOGE("snd_pcm_prepare fail: %{public}s", snd_strerror(ret));
564             return HDF_FAILURE;
565         }
566     }
567 
568     size_t sbufFrameSize = (size_t)handleData->frameRenderMode.bufferFrameSize;
569     char *dataBuf = handleData->frameRenderMode.buffer;
570     int32_t offset = hwParams->bitsPerFrame / BIT_COUNT_OF_BYTE;
571     while (sbufFrameSize > 0) {
572         long frames = snd_pcm_writei(pcm, dataBuf, sbufFrameSize);
573         if (frames > 0) {
574             sbufFrameSize -= frames;
575             dataBuf += frames * offset;
576         } else if (frames == -EAGAIN) {
577             snd_pcm_wait(pcm, PCM_WAIT_TIMEOUT_MS);
578             tryNum--;
579             if (tryNum == 0) {
580                 return HDF_SUCCESS;
581             }
582         } else if (frames == -EBADFD) {
583             /* not #SND_PCM_STATE_PREPARED or #SND_PCM_STATE_RUNNING */
584             AUDIO_FUNC_LOGE("render PCM is not in the right state: %{public}s", snd_strerror(frames));
585             snd_pcm_prepare(pcm);
586             return HDF_FAILURE;
587         } else {
588             /* -ESTRPIPE: a suspend event occurred,
589              * stream is suspended and waiting for an application recovery.
590              * -EPIPE: an underrun occurred.
591              */
592             AUDIO_FUNC_LOGI("err: %{public}s", snd_strerror(ret));
593             ret = snd_pcm_recover(pcm, frames, 0); // 0 for open render recover log.
594             if (ret < 0) {
595                 AUDIO_FUNC_LOGE("snd_pcm_writei failed: %{public}s", snd_strerror(ret));
596                 return HDF_FAILURE;
597             }
598         }
599     }
600 
601     return HDF_SUCCESS;
602 }
603 
RenderWriteiMmap(struct AlsaSoundCard * cardIns,const struct AudioHwRenderParam * handleData)604 static int32_t RenderWriteiMmap(struct AlsaSoundCard *cardIns, const struct AudioHwRenderParam *handleData)
605 {
606     uint32_t looper = 0;
607     int32_t count = 0;
608     struct AudioMmapBufferDescriptor *mmapBufDesc = NULL;
609     CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
610     CHECK_NULL_PTR_RETURN_DEFAULT(handleData);
611 
612     cardIns->mmapFlag = false;
613     int32_t ret = ResetRenderParams(cardIns, SND_PCM_ACCESS_MMAP_INTERLEAVED);
614     if (ret < 0) {
615         AUDIO_FUNC_LOGE("AudioSetParamsMmap failed!");
616         return HDF_FAILURE;
617     }
618 
619     uint32_t frameSize = cardIns->hwParams.channels * cardIns->hwParams.format;
620     if (frameSize == 0) {
621         AUDIO_FUNC_LOGE("frame size = 0!");
622         return HDF_FAILURE;
623     }
624     mmapBufDesc = (struct AudioMmapBufferDescriptor *)&(handleData->frameRenderMode.mmapBufDesc);
625     uint32_t totalSize = (uint32_t)mmapBufDesc->totalBufferFrames * frameSize;
626     uint32_t lastBuffSize = ((totalSize % MIN_PERIOD_SIZE) == 0) ? MIN_PERIOD_SIZE : (totalSize % MIN_PERIOD_SIZE);
627     uint32_t loopTimes = (lastBuffSize == MIN_PERIOD_SIZE) ?
628         (totalSize / MIN_PERIOD_SIZE) : (totalSize / MIN_PERIOD_SIZE + 1);
629     while (looper < loopTimes) {
630         uint32_t copyLen = (looper < (loopTimes - 1)) ? MIN_PERIOD_SIZE : lastBuffSize;
631         snd_pcm_uframes_t frames = (snd_pcm_uframes_t)(copyLen / frameSize);
632         ret = snd_pcm_mmap_writei(
633             cardIns->pcmHandle, (char *)mmapBufDesc->memoryAddress + mmapBufDesc->offset, frames);
634         if (ret == -EAGAIN) {
635             count++;
636             if (count > AUDIO_ALSALIB_MMAP_MAX) {
637                 AUDIO_FUNC_LOGE("loop > max !");
638                 return HDF_FAILURE;
639             }
640             continue;
641         }
642         count = 0;
643         if (ret < 0) {
644             AUDIO_FUNC_LOGE("Write error: %{public}s\n", snd_strerror(ret));
645             return HDF_FAILURE;
646         }
647         looper++;
648         mmapBufDesc->offset += copyLen;
649         cardIns->mmapFrames += (uint64_t)frames;
650     }
651 
652     return HDF_SUCCESS;
653 }
654 
RenderOpenImpl(struct AlsaRender * renderIns)655 static int32_t RenderOpenImpl(struct AlsaRender *renderIns)
656 {
657     struct AlsaSoundCard *cardIns = (struct AlsaSoundCard *)renderIns;
658     CHECK_NULL_PTR_RETURN_DEFAULT(renderIns);
659 
660     if (SndisBusy(&renderIns->soundCard)) {
661         AUDIO_FUNC_LOGE("Resource busy!!");
662         return HDF_ERR_DEVICE_BUSY;
663     }
664 
665     int32_t ret = snd_pcm_open(&cardIns->pcmHandle, cardIns->devName,
666         SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
667     if (ret < 0) {
668         AUDIO_FUNC_LOGE("snd_pcm_open fail: %{public}s!", snd_strerror(ret));
669         RenderFreeMemory();
670         return HDF_FAILURE;
671     }
672 
673     ret = snd_pcm_nonblock(cardIns->pcmHandle, 1);
674     if (ret < 0) {
675         AUDIO_FUNC_LOGE("snd_pcm_nonblock fail: %{public}s!", snd_strerror(ret));
676         SndCloseHandle(&renderIns->soundCard);
677         RenderFreeMemory();
678         return HDF_FAILURE;
679     }
680 
681     ret = SndOpenMixer(&renderIns->soundCard);
682     if (ret != HDF_SUCCESS) {
683         AUDIO_FUNC_LOGE("SndOpenMixer failed");
684         SndCloseHandle(&renderIns->soundCard);
685         RenderFreeMemory();
686         return HDF_FAILURE;
687     }
688 
689     return HDF_SUCCESS;
690 }
691 
RenderCloseImpl(struct AlsaRender * renderIns)692 static int32_t RenderCloseImpl(struct AlsaRender *renderIns)
693 {
694     CHECK_NULL_PTR_RETURN_DEFAULT(renderIns);
695 #ifdef SUPPORT_ALSA_CHMAP
696     AudioMemFree((void **)&renderIns->soundCard.hwParams.channelsName);
697 #endif
698     SndCloseHandle(&renderIns->soundCard);
699     RenderFreeMemory();
700     return HDF_SUCCESS;
701 }
702 
RenderWriteImpl(struct AlsaRender * renderIns,const struct AudioHwRenderParam * handleData)703 int32_t RenderWriteImpl(struct AlsaRender *renderIns, const struct AudioHwRenderParam *handleData)
704 {
705     int32_t ret = HDF_SUCCESS;
706     struct AlsaSoundCard *cardIns = (struct AlsaSoundCard*)renderIns;
707     CHECK_NULL_PTR_RETURN_DEFAULT(renderIns);
708 
709     if (cardIns->pauseState) {
710         AUDIO_FUNC_LOGE("Currently in pause, please check!");
711         return HDF_FAILURE;
712     }
713 
714     if (!cardIns->mmapFlag) {
715         ret = ResetRenderParams(cardIns, SND_PCM_ACCESS_RW_INTERLEAVED);
716         if (ret < 0) {
717             AUDIO_FUNC_LOGE("ResetRenderParams failed!");
718             return HDF_FAILURE;
719         }
720         cardIns->mmapFlag = true;
721     }
722 
723     ret = RenderWritei(cardIns->pcmHandle, handleData, &cardIns->hwParams);
724     if (ret != HDF_SUCCESS) {
725         AUDIO_FUNC_LOGE("RenderWritei failed!");
726         return HDF_FAILURE;
727     }
728 
729     return HDF_SUCCESS;
730 }
731 
RenderGetMmapPositionImpl(struct AlsaRender * renderIns)732 int32_t RenderGetMmapPositionImpl(struct AlsaRender *renderIns)
733 {
734     return renderIns->soundCard.mmapFrames;
735 }
736 
RenderMmapWriteImpl(struct AlsaRender * renderIns,const struct AudioHwRenderParam * handleData)737 int32_t RenderMmapWriteImpl(struct AlsaRender *renderIns, const struct AudioHwRenderParam *handleData)
738 {
739     struct AlsaSoundCard *cardIns = (struct AlsaSoundCard *)renderIns;
740     CHECK_NULL_PTR_RETURN_DEFAULT(renderIns);
741     CHECK_NULL_PTR_RETURN_DEFAULT(handleData);
742 
743     if (cardIns->pauseState) {
744         AUDIO_FUNC_LOGE("Currently in pause, please check!");
745         return HDF_FAILURE;
746     }
747 
748     cardIns->mmapFlag = false;
749     int32_t ret = ResetRenderParams(cardIns, SND_PCM_ACCESS_MMAP_INTERLEAVED);
750     if (ret < 0) {
751         AUDIO_FUNC_LOGE("ResetRenderParams failed!");
752         return HDF_FAILURE;
753     }
754 
755     ret = RenderWriteiMmap(cardIns, handleData);
756     if (ret < 0) {
757         AUDIO_FUNC_LOGE("RenderWriteiMmap error!");
758         return HDF_FAILURE;
759     }
760     return HDF_SUCCESS;
761 }
762 
RenderInitImpl(struct AlsaRender * renderIns)763 static int32_t RenderInitImpl(struct AlsaRender* renderIns)
764 {
765     AUDIO_FUNC_LOGE("Not yet realized");
766     return HDF_SUCCESS;
767 }
768 
RenderSelectSceneImpl(struct AlsaRender * renderIns,enum AudioPortPin descPins,const struct PathDeviceInfo * deviceInfo)769 static int32_t RenderSelectSceneImpl(struct AlsaRender *renderIns, enum AudioPortPin descPins,
770     const struct PathDeviceInfo *deviceInfo)
771 {
772     AUDIO_FUNC_LOGE("Not yet realized");
773     return HDF_SUCCESS;
774 }
775 
RenderStartImpl(struct AlsaRender * renderIns)776 static int32_t RenderStartImpl(struct AlsaRender *renderIns)
777 {
778     AUDIO_FUNC_LOGE("Not yet realized");
779     return HDF_SUCCESS;
780 }
781 
RenderStopImpl(struct AlsaRender * renderIns)782 static int32_t RenderStopImpl(struct AlsaRender *renderIns)
783 {
784     AUDIO_FUNC_LOGE("Not yet realized");
785     return HDF_SUCCESS;
786 }
787 
RenderGetVolThresholdImpl(struct AlsaRender * renderIns,long * volMin,long * volMax)788 static int32_t RenderGetVolThresholdImpl(struct AlsaRender *renderIns, long *volMin, long *volMax)
789 {
790     AUDIO_FUNC_LOGE("Not yet realized");
791     return HDF_SUCCESS;
792 }
793 
RenderGetVolumeImpl(struct AlsaRender * renderIns,long * volume)794 static int32_t RenderGetVolumeImpl(struct AlsaRender *renderIns, long *volume)
795 {
796     AUDIO_FUNC_LOGE("Not yet realized");
797     return HDF_SUCCESS;
798 }
799 
RenderSetVolumeImpl(struct AlsaRender * renderIns,long volume)800 static int32_t RenderSetVolumeImpl(struct AlsaRender *renderIns, long volume)
801 {
802     AUDIO_FUNC_LOGE("Not yet realized");
803     return HDF_SUCCESS;
804 }
805 
RenderGetGainThresholdImpl(struct AlsaRender * renderIns,float * gainMin,float * gainMax)806 static int32_t RenderGetGainThresholdImpl(struct AlsaRender *renderIns, float *gainMin, float *gainMax)
807 {
808     AUDIO_FUNC_LOGE("Not yet realized");
809     return HDF_SUCCESS;
810 }
811 
RenderGetGainImpl(struct AlsaRender * renderIns,float * volume)812 static int32_t RenderGetGainImpl(struct AlsaRender *renderIns, float *volume)
813 {
814     AUDIO_FUNC_LOGE("Not yet realized");
815     return HDF_SUCCESS;
816 }
817 
RenderSetGainImpl(struct AlsaRender * renderIns,float volume)818 static int32_t RenderSetGainImpl(struct AlsaRender *renderIns, float volume)
819 {
820     AUDIO_FUNC_LOGE("Not yet realized");
821     return HDF_SUCCESS;
822 }
823 
RenderGetMuteImpl(struct AlsaRender * renderIns)824 static bool RenderGetMuteImpl(struct AlsaRender *renderIns)
825 {
826     AUDIO_FUNC_LOGE("Not yet realized");
827     return false;
828 }
829 
RenderSetMuteImpl(struct AlsaRender * renderIns,bool muteFlag)830 static int32_t RenderSetMuteImpl(struct AlsaRender *renderIns, bool muteFlag)
831 {
832     AUDIO_FUNC_LOGE("Not yet realized");
833     return HDF_SUCCESS;
834 }
835 
RenderSetPauseStateImpl(struct AlsaRender * renderIns,bool pauseFlag)836 static int32_t RenderSetPauseStateImpl(struct AlsaRender *renderIns, bool pauseFlag)
837 {
838     int enable = pauseFlag ? AUDIO_ALSALIB_IOCTRL_PAUSE : AUDIO_ALSALIB_IOCTRL_RESUME;
839     struct AlsaSoundCard *cardIns = (struct AlsaSoundCard *)renderIns;
840 
841     if (cardIns->canPause) {
842         int32_t ret = snd_pcm_pause(cardIns->pcmHandle, enable);
843         if (ret < 0) {
844             AUDIO_FUNC_LOGE("snd_pcm_pause failed!");
845             return HDF_FAILURE;
846         }
847     } else {
848         if (enable == AUDIO_ALSALIB_IOCTRL_PAUSE) {
849             snd_pcm_drain(cardIns->pcmHandle);
850         } else {
851             snd_pcm_prepare(cardIns->pcmHandle);
852         }
853     }
854     cardIns->pauseState = pauseFlag;
855 
856     return HDF_SUCCESS;
857 }
858 
RenderGetChannelModeImpl(struct AlsaRender * renderIns,enum AudioChannelMode * mode)859 static int32_t RenderGetChannelModeImpl(struct AlsaRender *renderIns, enum AudioChannelMode *mode)
860 {
861     AUDIO_FUNC_LOGE("Not yet realized");
862     return HDF_SUCCESS;
863 }
864 
RenderSetChannelModeImpl(struct AlsaRender * renderIns,enum AudioChannelMode mode)865 static int32_t RenderSetChannelModeImpl(struct AlsaRender *renderIns, enum AudioChannelMode mode)
866 {
867     AUDIO_FUNC_LOGE("Not yet realized");
868     return HDF_SUCCESS;
869 }
870 
RegisterRenderImpl(struct AlsaRender * renderIns)871 static void RegisterRenderImpl(struct AlsaRender *renderIns)
872 {
873     if (renderIns == NULL) {
874         AUDIO_FUNC_LOGE("renderIns is NULL!");
875         return;
876     }
877 
878     renderIns->Init = RenderInitImpl;
879     renderIns->Open = RenderOpenImpl;
880     renderIns->SelectScene = RenderSelectSceneImpl;
881     renderIns->Start = RenderStartImpl;
882     renderIns->Stop = RenderStopImpl;
883     renderIns->Close = RenderCloseImpl;
884     renderIns->Write = RenderWriteImpl;
885     renderIns->MmapWrite = RenderMmapWriteImpl;
886     renderIns->GetMmapPosition = RenderGetMmapPositionImpl;
887     renderIns->GetVolThreshold = RenderGetVolThresholdImpl;
888     renderIns->GetVolume = RenderGetVolumeImpl;
889     renderIns->SetVolume = RenderSetVolumeImpl;
890     renderIns->GetGainThreshold = RenderGetGainThresholdImpl;
891     renderIns->GetGain = RenderGetGainImpl;
892     renderIns->SetGain = RenderSetGainImpl;
893     renderIns->GetMute = RenderGetMuteImpl;
894     renderIns->SetMute = RenderSetMuteImpl;
895     renderIns->SetPauseState = RenderSetPauseStateImpl;
896     renderIns->GetChannelMode = RenderGetChannelModeImpl;
897     renderIns->SetChannelMode = RenderSetChannelModeImpl;
898 }
899 
900