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