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