• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Unionman Technology 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 <linux/soundcard.h>
17 #include "sound/asound.h"
18 
19 #include "hdf_log.h"
20 #include "tinyalsa/asoundlib.h"
21 
22 #include "audio_interface_lib_render.h"
23 
24 #define HDF_LOG_TAG HDI_AUDIO_R_ALSA
25 
26 // treat hats.
27 #define PLEASURE_HATS
28 
29 #define SOUND_CARD_ID (0)
30 #define SOUND_DEV_ID (1)
31 
32 #define VOLUME_DEFAULT (50)
33 
34 struct AlsaCtx {
35     struct pcm *pcmHandler;
36     struct pcm_config config;
37     struct mixer *mixerHandler;
38 
39     int initFlag;
40     int renderRefCount;
41     int ctlRefCount;
42     int volume; // volume in db [ (volMax - volMin) / 2 * log10(Vol) + volMin]
43     int volMin;
44     int volMax;
45 
46     float gain;
47     float gainMin;
48     float gainMax;
49 
50     bool mute;
51 };
52 
53 static struct AlsaCtx s_alsaCtx = {.initFlag = 0};
54 
55 struct AlsaDevObject {
56     char serviceName[64];
57     struct AlsaCtx *pAlsaCtx;
58 };
59 
ConvertFormatToAlsa(enum AudioFormat format)60 static enum pcm_format ConvertFormatToAlsa(enum AudioFormat format)
61 {
62     switch (format) {
63         case AUDIO_FORMAT_TYPE_PCM_8_BIT:
64             return PCM_FORMAT_S8;
65         case AUDIO_FORMAT_TYPE_PCM_16_BIT:
66             return PCM_FORMAT_S16_LE;
67         case AUDIO_FORMAT_TYPE_PCM_24_BIT:
68             return PCM_FORMAT_S24_LE;
69         case AUDIO_FORMAT_TYPE_PCM_32_BIT:
70             return PCM_FORMAT_S32_LE;
71         case AUDIO_FORMAT_TYPE_AAC_MAIN:
72         case AUDIO_FORMAT_TYPE_AAC_LC:
73         case AUDIO_FORMAT_TYPE_AAC_LD:
74         case AUDIO_FORMAT_TYPE_AAC_ELD:
75         case AUDIO_FORMAT_TYPE_AAC_HE_V1:
76         case AUDIO_FORMAT_TYPE_AAC_HE_V2:
77         case AUDIO_FORMAT_TYPE_G711A:
78         case AUDIO_FORMAT_TYPE_G711U:
79         case AUDIO_FORMAT_TYPE_G726:
80         default:
81             return PCM_FORMAT_INVALID;
82     }
83 }
84 
MixerInit(struct mixer * mixer)85 static int32_t MixerInit(struct mixer *mixer)
86 {
87     int32_t ret = 0;
88 
89     if (!mixer) {
90         HDF_LOGE("Error: mixer is NULL.");
91         return -1;
92     }
93 
94     // config audio path
95     ret |= mixer_ctl_set_value(
96         mixer_get_ctl_by_name(mixer, "FRDDR_B SRC 1 EN Switch"), 0, 1);
97     ret |= mixer_ctl_set_enum_by_string(
98         mixer_get_ctl_by_name(mixer, "FRDDR_B SINK 1 SEL"), "OUT 1");
99     ret |= mixer_ctl_set_enum_by_string(
100         mixer_get_ctl_by_name(mixer, "TDMOUT_B SRC SEL"), "IN 1");
101 
102     ret |= mixer_ctl_set_value(mixer_get_ctl_by_name(mixer, "TOHDMITX Switch"),
103                                0, 1);
104     ret |= mixer_ctl_set_enum_by_string(
105         mixer_get_ctl_by_name(mixer, "TOHDMITX I2S SRC"), "I2S B");
106 
107     ret |= mixer_ctl_set_value(
108         mixer_get_ctl_by_name(mixer, "TOACODEC OUT EN Switch"), 0, 1);
109     ret |= mixer_ctl_set_enum_by_string(
110         mixer_get_ctl_by_name(mixer, "TOACODEC SRC"), "I2S B");
111 
112     // config volume
113     ret |= mixer_ctl_set_value(
114         mixer_get_ctl_by_name(mixer, "ACODEC Playback Volume"), 0, 255U);
115     ret |= mixer_ctl_set_value(
116         mixer_get_ctl_by_name(mixer, "ACODEC Playback Volume"), 1, 255U);
117     ret |= mixer_ctl_set_value(
118         mixer_get_ctl_by_name(mixer, "ACODEC Mute Ramp Switch"), 0, 1);
119     ret |= mixer_ctl_set_value(
120         mixer_get_ctl_by_name(mixer, "ACODEC Unmute Ramp Switch"), 0, 1);
121 
122     ret |= mixer_ctl_set_value(
123         mixer_get_ctl_by_name(mixer, "TDMOUT_B Gain Enable Switch"), 0, 1);
124 
125     return ret;
126 }
127 
AlsaVolumeUpdate(struct AlsaCtx * aCtx)128 static int32_t AlsaVolumeUpdate(struct AlsaCtx *aCtx)
129 {
130     int32_t ret = 0;
131     int volumeSet = 0;
132 
133     if (!aCtx->mixerHandler) {
134         return -1;
135     }
136 
137     if (aCtx->mute) {
138         volumeSet = 0;
139     } else {
140         volumeSet = aCtx->volume * 255U /
141                     (aCtx->volMax - aCtx->volMin); // need adjustment
142     }
143 
144     ret |= mixer_ctl_set_value(
145         mixer_get_ctl_by_name(aCtx->mixerHandler, "TDMOUT_B Lane 0 Volume"), 0,
146         volumeSet);
147     ret |= mixer_ctl_set_value(
148         mixer_get_ctl_by_name(aCtx->mixerHandler, "TDMOUT_B Lane 0 Volume"), 1,
149         volumeSet);
150 
151     HDF_LOGV("Set Volume: volume=%{public}d, mute=%{public}d, "
152              "volumeSet=%{public}d, ret=%{public}d",
153              aCtx->volume, aCtx->mute, volumeSet, ret);
154 
155     return ret;
156 }
157 
AlsaCtxInstanceGet(void)158 static struct AlsaCtx *AlsaCtxInstanceGet(void)
159 {
160     if (!s_alsaCtx.initFlag) {
161         memset_s(&s_alsaCtx, sizeof(s_alsaCtx), 0, sizeof(s_alsaCtx));
162         s_alsaCtx.renderRefCount = 0;
163         s_alsaCtx.pcmHandler = NULL;
164         s_alsaCtx.volMax = 100U;
165         s_alsaCtx.volMin = 0;
166         s_alsaCtx.volume = VOLUME_DEFAULT;
167         s_alsaCtx.gainMin = 0.0;
168         s_alsaCtx.gainMax = 15.0f;
169         s_alsaCtx.gain = s_alsaCtx.gainMax;
170         s_alsaCtx.mute = false;
171         s_alsaCtx.mixerHandler = mixer_open(SOUND_CARD_ID);
172         MixerInit(s_alsaCtx.mixerHandler);
173         s_alsaCtx.initFlag = 1;
174 
175         AlsaVolumeUpdate(&s_alsaCtx);
176     }
177 
178     return &s_alsaCtx;
179 }
180 
AlsaOpen(struct AlsaCtx * aCtx)181 static int AlsaOpen(struct AlsaCtx *aCtx)
182 {
183     int sound_card_id = SOUND_CARD_ID;
184     int sound_dev_id = SOUND_DEV_ID;
185 
186     HDF_LOGI(
187         "%{public}s() rate=%{public}d, channels=%{public}d, format=%{public}d",
188         __func__, aCtx->config.rate, aCtx->config.channels,
189         aCtx->config.format);
190 
191     if (aCtx->pcmHandler) {
192         HDF_LOGW("Alsa is opened already.");
193         return 0;
194     }
195 
196     struct pcm_config config;
197     (void)memcpy_s(&config, sizeof(config), &aCtx->config, sizeof(config));
198     struct pcm *pcm = pcm_open(sound_card_id, sound_dev_id, PCM_OUT, &config);
199     if (!pcm_is_ready(pcm)) {
200         HDF_LOGE("Error: %{public}s() Cannot open pcm_out(card %{public}d, "
201                  "device %{public}d): %{public}s",
202                  __func__, sound_card_id, sound_dev_id, pcm_get_error(pcm));
203         pcm_close(pcm);
204 
205         return -1;
206     }
207 
208     aCtx->pcmHandler = pcm;
209 
210     HDF_LOGI("Open Alsa Success.");
211 
212     return 0;
213 }
214 
AlsaClose(struct AlsaCtx * aCtx)215 static int AlsaClose(struct AlsaCtx *aCtx)
216 {
217     if (aCtx->pcmHandler) {
218         pcm_close(aCtx->pcmHandler);
219         aCtx->pcmHandler = NULL;
220     }
221 
222     HDF_LOGI("Close Alsa Success.");
223 
224     return 0;
225 }
226 
CheckHwParam(struct AudioHwRenderParam * handleData)227 static int CheckHwParam(struct AudioHwRenderParam *handleData)
228 {
229     if (handleData == NULL) {
230         HDF_LOGE("Error: handleData is NULL!");
231         return -1;
232     }
233 
234     if (handleData->frameRenderMode.attrs.channelCount != 1U &&
235         handleData->frameRenderMode.attrs.channelCount != 2U) {
236         HDF_LOGE("Error: Unsupported channel count: %{public}d",
237                  handleData->frameRenderMode.attrs.channelCount);
238         return -1;
239     }
240 
241     if (handleData->frameRenderMode.attrs.format == AUDIO_FORMAT_TYPE_PCM_8_BIT &&
242         handleData->frameRenderMode.attrs.sampleRate == 8000U)
243         return -1;
244 
245     if (handleData->frameRenderMode.attrs.format == AUDIO_FORMAT_TYPE_PCM_32_BIT &&
246         handleData->frameRenderMode.attrs.sampleRate == 11025U)
247         return -1;
248 
249     return 0;
250 }
251 
AlsaConfig(struct AlsaCtx * aCtx,struct AudioHwRenderParam * handleData)252 static int AlsaConfig(struct AlsaCtx *aCtx, struct AudioHwRenderParam *handleData)
253 {
254     struct pcm_config config;
255     enum pcm_format format;
256 
257     if (CheckHwParam(handleData)) {
258         return -1;
259     }
260 
261     format = ConvertFormatToAlsa(handleData->frameRenderMode.attrs.format);
262     if (PCM_FORMAT_INVALID == format) {
263         HDF_LOGE("Error: Unsupported format: %{public}d", handleData->frameRenderMode.attrs.format);
264         return -1;
265     }
266 
267     memset_s(&config, sizeof(config), 0, sizeof(config));
268 
269     config.channels = handleData->frameRenderMode.attrs.channelCount;
270     config.rate = handleData->frameRenderMode.attrs.sampleRate;
271     config.format = format;
272     config.period_count = handleData->frameRenderMode.periodCount; // 6
273     config.period_size = handleData->frameRenderMode.periodSize;   // 512
274     config.start_threshold = handleData->frameRenderMode.attrs.startThreshold;
275     config.stop_threshold = handleData->frameRenderMode.attrs.stopThreshold;
276     config.silence_threshold = handleData->frameRenderMode.attrs.silenceThreshold;
277 
278 #ifdef PLEASURE_HATS
279     if (config.rate == 12000) {
280         config.rate = 8000;
281     } else if (config.rate == 24000) {
282         config.rate = 22050;
283     }
284 #endif
285 
286     HDF_LOGV("DUMP Alsa Config 1#: channels=%{public}d, rate=%{public}d, "
287              "format=%{public}d, period_count=%{public}d, period_size=%{public}d",
288              config.channels, config.rate, config.format, config.period_count, config.period_size);
289 
290     HDF_LOGV("DUMP Alsa OldConfig 1#: channels=%{public}d, rate=%{public}d, "
291              "format=%{public}d, period_count=%{public}d, period_size=%{public}d",
292              aCtx->config.channels, aCtx->config.rate, aCtx->config.format,
293              aCtx->config.period_count, aCtx->config.period_size);
294 
295     if (aCtx->pcmHandler && !memcmp(&config, &aCtx->config, sizeof(config))) {
296         HDF_LOGW("Warn: Same Audio Hw config. No need to change.");
297         return 0;
298     }
299 
300     (void)memcpy_s(&aCtx->config, sizeof(aCtx->config), &config, sizeof(config));
301 
302     AlsaClose(aCtx);
303     if (AlsaOpen(aCtx) < 0) {
304         HDF_LOGE("Error: in %{public}s, AlsaOpen() failed.", __func__);
305         return -1;
306     }
307 
308     HDF_LOGV("Config Alsa SUCCESS.");
309 
310     return 0;
311 }
312 
DoCtlRenderSetVolume(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)313 static int32_t DoCtlRenderSetVolume(const struct DevHandle *handle, int cmdId,
314                                     struct AudioHwRenderParam *handleData)
315 {
316     struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
317 
318     HDF_LOGV("INFO: enter %{public}s(). volume=%{public}f", __func__,
319              handleData->renderMode.ctlParam.volume);
320 
321     int volume = (int)handleData->renderMode.ctlParam.volume;
322 
323     if (volume < aCtx->volMin || volume > aCtx->volMax) {
324         HDF_LOGE("Error: Invalid volume: %{public}d", volume);
325         return HDF_FAILURE;
326     }
327 
328     aCtx->volume = volume;
329 
330     return AlsaVolumeUpdate(aCtx);
331 }
332 
DoCtlRenderGetVolume(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)333 static int32_t DoCtlRenderGetVolume(const struct DevHandle *handle, int cmdId,
334                                     struct AudioHwRenderParam *handleData)
335 {
336     struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
337 
338     handleData->renderMode.ctlParam.volume = aCtx->volume;
339 
340     return HDF_SUCCESS;
341 }
342 
DoCtlRenderSetPauseStu(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)343 static int32_t DoCtlRenderSetPauseStu(const struct DevHandle *handle, int cmdId,
344                                       struct AudioHwRenderParam *handleData)
345 {
346     struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
347 
348     if (!((struct AlsaCtx *)aCtx)->pcmHandler) {
349         HDF_LOGE("Error: in %{public}s, Pcm is not opened!", __func__);
350         return HDF_FAILURE;
351     }
352 
353     if (pcm_ioctl(aCtx->pcmHandler, SNDRV_PCM_IOCTL_PAUSE,
354                   handleData->renderMode.ctlParam.pause ? 1 : 0) < 0) {
355         HDF_LOGE("Error: pcm_ioctl(SNDRV_PCM_IOCTL_PAUSE) failed: %{public}s\n",
356                  pcm_get_error(aCtx->pcmHandler));
357         return HDF_FAILURE;
358     }
359 
360     return HDF_SUCCESS;
361 }
362 
DoCtlRenderSetMuteStu(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)363 static int32_t DoCtlRenderSetMuteStu(const struct DevHandle *handle, int cmdId,
364                                      struct AudioHwRenderParam *handleData)
365 {
366     struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
367 
368     aCtx->mute = handleData->renderMode.ctlParam.mute;
369 
370     return AlsaVolumeUpdate(aCtx);
371 }
372 
DoCtlRenderGetMuteStu(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)373 static int32_t DoCtlRenderGetMuteStu(const struct DevHandle *handle, int cmdId,
374                                      struct AudioHwRenderParam *handleData)
375 {
376     struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
377 
378     handleData->renderMode.ctlParam.mute = aCtx->mute;
379 
380     return HDF_SUCCESS;
381 }
382 
DoCtlRenderSetGainStu(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)383 static int32_t DoCtlRenderSetGainStu(const struct DevHandle *handle, int cmdId,
384                                      struct AudioHwRenderParam *handleData)
385 {
386     struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
387 
388     float gain = handleData->renderMode.ctlParam.audioGain.gain;
389 
390     if (gain < aCtx->gainMin || gain > aCtx->gainMax) {
391         HDF_LOGE("Error: Invalid gain: %{public}f", gain);
392         return HDF_FAILURE;
393     }
394 
395     aCtx->gain = gain;
396 
397     return HDF_SUCCESS;
398 }
399 
DoCtlRenderGetGainStu(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)400 static int32_t DoCtlRenderGetGainStu(const struct DevHandle *handle, int cmdId,
401                                      struct AudioHwRenderParam *handleData)
402 {
403     struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
404 
405     handleData->renderMode.ctlParam.audioGain.gain = aCtx->gain;
406 
407     return HDF_SUCCESS;
408 }
409 
DoCtlRenderSceneSelect(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)410 static int32_t DoCtlRenderSceneSelect(const struct DevHandle *handle, int cmdId,
411                                       struct AudioHwRenderParam *handleData)
412 {
413     HDF_LOGV("INFO: enter %{public}s(). portId=%{public}d", __func__,
414              handleData->renderMode.hwInfo.deviceDescript.portId);
415 
416     HDF_LOGV("DUMP AudioHwRenderParam: %{public}d, %{public}d, %{public}d, "
417              "%{public}d, %{public}d, %{public}d, "
418              "%{public}d, %{public}d",
419              handleData->frameRenderMode.attrs.channelCount,
420              handleData->frameRenderMode.attrs.sampleRate,
421              handleData->frameRenderMode.attrs.format,
422              handleData->frameRenderMode.periodCount,
423              handleData->frameRenderMode.periodSize,
424              handleData->frameRenderMode.attrs.startThreshold,
425              handleData->frameRenderMode.attrs.stopThreshold,
426              handleData->frameRenderMode.attrs.silenceThreshold);
427 
428     return HDF_SUCCESS;
429 }
430 
DoCtlRenderSceneGetGainThreshold(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)431 static int32_t DoCtlRenderSceneGetGainThreshold(const struct DevHandle *handle, int cmdId,
432                                                 struct AudioHwRenderParam *handleData)
433 {
434     struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
435 
436     handleData->renderMode.ctlParam.audioGain.gainMax = aCtx->gainMax;
437     handleData->renderMode.ctlParam.audioGain.gainMin = aCtx->gainMin;
438 
439     return HDF_SUCCESS;
440 }
441 
DoCtlRenderGetVolThreshold(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)442 static int32_t DoCtlRenderGetVolThreshold(const struct DevHandle *handle,
443                                           int cmdId,
444                                           struct AudioHwRenderParam *handleData)
445 {
446     struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
447 
448     handleData->renderMode.ctlParam.volThreshold.volMax = aCtx->volMax;
449     handleData->renderMode.ctlParam.volThreshold.volMin = aCtx->volMin;
450 
451     return HDF_SUCCESS;
452 }
453 
DoCtlRenderSetChannelMode(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)454 static int32_t DoCtlRenderSetChannelMode(const struct DevHandle *handle,
455                                          int cmdId,
456                                          struct AudioHwRenderParam *handleData)
457 {
458     return HDF_SUCCESS;
459 }
460 
DoCtlRenderGetChannelMode(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)461 static int32_t DoCtlRenderGetChannelMode(const struct DevHandle *handle,
462                                          int cmdId,
463                                          struct AudioHwRenderParam *handleData)
464 {
465     handleData->frameRenderMode.mode = AUDIO_CHANNEL_NORMAL;
466     return HDF_SUCCESS;
467 }
468 
DoCtlRenderSetAcodecMode(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)469 static int32_t DoCtlRenderSetAcodecMode(const struct DevHandle *handle,
470                                         int cmdId,
471                                         struct AudioHwRenderParam *handleData)
472 {
473     return HDF_SUCCESS;
474 }
475 
HandleCtlRenderCmd(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)476 static int32_t HandleCtlRenderCmd(const struct DevHandle *handle, int cmdId,
477                                   struct AudioHwRenderParam *handleData)
478 {
479     switch (cmdId) {
480         case AUDIODRV_CTL_IOCTL_ELEM_READ:
481             return DoCtlRenderGetVolume(handle, cmdId, handleData);
482         case AUDIODRV_CTL_IOCTL_ELEM_WRITE:
483             return DoCtlRenderSetVolume(handle, cmdId, handleData);
484         case AUDIODRV_CTL_IOCTL_MUTE_READ:
485             return DoCtlRenderGetMuteStu(handle, cmdId, handleData);
486         case AUDIODRV_CTL_IOCTL_MUTE_WRITE:
487             return DoCtlRenderSetMuteStu(handle, cmdId, handleData);
488         case AUDIODRV_CTL_IOCTL_CHANNEL_MODE_READ:
489             return DoCtlRenderGetChannelMode(handle, cmdId, handleData);
490         case AUDIODRV_CTL_IOCTL_CHANNEL_MODE_WRITE:
491             return DoCtlRenderSetChannelMode(handle, cmdId, handleData);
492         case AUDIODRV_CTL_IOCTL_GAIN_WRITE:
493             return DoCtlRenderSetGainStu(handle, cmdId, handleData);
494         case AUDIODRV_CTL_IOCTL_GAIN_READ:
495             return DoCtlRenderGetGainStu(handle, cmdId, handleData);
496         case AUDIODRV_CTL_IOCTL_SCENESELECT_WRITE:
497             return DoCtlRenderSceneSelect(handle, cmdId, handleData);
498         case AUDIODRV_CTL_IOCTL_GAINTHRESHOLD_READ:
499             return DoCtlRenderSceneGetGainThreshold(handle, cmdId, handleData);
500         case AUDIODRV_CTL_IOCTL_ACODEC_CHANGE_IN:
501         case AUDIODRV_CTL_IOCTL_ACODEC_CHANGE_OUT:
502             return DoCtlRenderSetAcodecMode(handle, cmdId, handleData);
503         case AUDIODRV_CTL_IOCTL_VOL_THRESHOLD_READ:
504             return DoCtlRenderGetVolThreshold(handle, cmdId, handleData);
505         default:
506             HDF_LOGE("Error: Output Mode not support!");
507             break;
508     }
509 
510     return HDF_FAILURE;
511 }
512 
DoOutputRenderHwParams(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)513 static int32_t DoOutputRenderHwParams(const struct DevHandle *handle, int cmdId,
514                                       struct AudioHwRenderParam *handleData)
515 {
516     struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
517 
518     HDF_LOGV("INFO: enter %{public}s()", __func__);
519 
520     if (AlsaConfig(aCtx, handleData) < 0) {
521         HDF_LOGE("Error: in %{public}s, AlsaConfig() failed.", __func__);
522         return HDF_FAILURE;
523     }
524 
525     return HDF_SUCCESS;
526 }
527 
DoOutputRenderWrite(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)528 static int32_t DoOutputRenderWrite(const struct DevHandle *handle, int cmdId,
529                                    struct AudioHwRenderParam *handleData)
530 {
531     struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
532 
533     if (!((struct AlsaCtx *)aCtx)->pcmHandler) {
534         HDF_LOGE("Error: in %{public}s, Pcm is not opened!", __func__);
535         return HDF_FAILURE;
536     }
537 
538     if (!handleData->frameRenderMode.buffer ||
539         handleData->frameRenderMode.bufferSize == 0) {
540         HDF_LOGE("Error: %{public}s, empty buf", __func__);
541         return HDF_FAILURE;
542     }
543 
544     if (pcm_write(aCtx->pcmHandler, handleData->frameRenderMode.buffer,
545                   handleData->frameRenderMode.bufferSize) < 0) {
546         HDF_LOGE("Error: pcm_write() failed: %{public}s\n",
547                  pcm_get_error(aCtx->pcmHandler));
548         return HDF_FAILURE;
549     }
550 
551     return HDF_SUCCESS;
552 }
553 
DoOutputRenderStartPrepare(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)554 static int32_t DoOutputRenderStartPrepare(const struct DevHandle *handle,
555                                           int cmdId,
556                                           struct AudioHwRenderParam *handleData)
557 {
558     struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
559 
560     HDF_LOGV("INFO: enter %{public}s()", __func__);
561 
562     AlsaOpen(aCtx);
563 
564     if (!((struct AlsaCtx *)aCtx)->pcmHandler) {
565         HDF_LOGE("Error: in %{public}s, Pcm is not opened!", __func__);
566         return HDF_FAILURE;
567     }
568 
569     // NOTE: depop here
570     int bufsize = aCtx->config.period_count * aCtx->config.period_size;
571     char *buf = calloc(1, bufsize);
572     if (buf) {
573         pcm_write(aCtx->pcmHandler, buf, bufsize);
574         free(buf);
575     }
576 
577     usleep(10000);
578 
579     return HDF_SUCCESS;
580 }
581 
DoOutputRenderStop(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)582 static int32_t DoOutputRenderStop(const struct DevHandle *handle, int cmdId,
583                                   struct AudioHwRenderParam *handleData)
584 {
585     struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
586 
587     HDF_LOGV("INFO: enter %{public}s()", __func__);
588 
589     if (!((struct AlsaCtx *)aCtx)->pcmHandler) {
590         HDF_LOGE("Error: in %{public}s, Pcm is not opened!", __func__);
591         return HDF_FAILURE;
592     }
593 
594     AlsaClose(aCtx);
595 
596     return HDF_SUCCESS;
597 }
598 
DoOutputRenderReqMmapBuffer(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)599 static int32_t DoOutputRenderReqMmapBuffer(const struct DevHandle *handle, int cmdId,
600                                            struct AudioHwRenderParam *handleData)
601 {
602     return HDF_SUCCESS;
603 }
604 
DoOutputRenderGetMmapPosition(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)605 static int32_t DoOutputRenderGetMmapPosition(const struct DevHandle *handle, int cmdId,
606                                              struct AudioHwRenderParam *handleData)
607 {
608     return HDF_SUCCESS;
609 }
610 
DoOutputRenderOpen(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)611 static int32_t DoOutputRenderOpen(const struct DevHandle *handle, int cmdId,
612                                   struct AudioHwRenderParam *handleData)
613 {
614     return HDF_SUCCESS;
615 }
616 
DoOutputRenderClose(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)617 static int32_t DoOutputRenderClose(const struct DevHandle *handle, int cmdId,
618                                    struct AudioHwRenderParam *handleData)
619 {
620     struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
621 
622     HDF_LOGV("INFO: enter %{public}s()", __func__);
623 
624     AlsaClose(aCtx);
625 
626     return HDF_SUCCESS;
627 }
628 
HandleOutputRenderCmd(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)629 static int32_t HandleOutputRenderCmd(const struct DevHandle *handle, int cmdId,
630                                      struct AudioHwRenderParam *handleData)
631 {
632     int32_t ret;
633     switch (cmdId) {
634         case AUDIO_DRV_PCM_IOCTL_HW_PARAMS:
635             ret = DoOutputRenderHwParams(handle, cmdId, handleData);
636             break;
637         case AUDIO_DRV_PCM_IOCTL_WRITE:
638             ret = DoOutputRenderWrite(handle, cmdId, handleData);
639             break;
640         case AUDIO_DRV_PCM_IOCTRL_STOP:
641             ret = DoOutputRenderStop(handle, cmdId, handleData);
642             break;
643         case AUDIO_DRV_PCM_IOCTRL_START:
644         case AUDIO_DRV_PCM_IOCTL_PREPARE:
645             ret = DoOutputRenderStartPrepare(handle, cmdId, handleData);
646             break;
647         case AUDIODRV_CTL_IOCTL_PAUSE_WRITE:
648             ret = DoCtlRenderSetPauseStu(handle, cmdId, handleData);
649             break;
650         case AUDIO_DRV_PCM_IOCTL_MMAP_BUFFER:
651             ret = DoOutputRenderReqMmapBuffer(handle, cmdId, handleData);
652             break;
653         case AUDIO_DRV_PCM_IOCTL_MMAP_POSITION:
654             ret = DoOutputRenderGetMmapPosition(handle, cmdId, handleData);
655             break;
656         case AUDIO_DRV_PCM_IOCTRL_RENDER_OPEN:
657             ret = DoOutputRenderOpen(handle, cmdId, handleData);
658             break;
659         case AUDIO_DRV_PCM_IOCTRL_RENDER_CLOSE:
660             ret = DoOutputRenderClose(handle, cmdId, handleData);
661             break;
662         default:
663             HDF_LOGE("Error: Output Mode not support!");
664             ret = HDF_FAILURE;
665             break;
666     }
667     return ret;
668 }
669 
670 /************************************************************************************
671     Exported Interface
672 *************************************************************************************/
673 
674 /* CreatRender for Bind handle */
AudioBindServiceRender(const char * name)675 struct DevHandle *AudioBindServiceRender(const char *name)
676 {
677     struct DevHandle *handle = NULL;
678     if (!name) {
679         HDF_LOGE("Error: service name NULL!");
680         return NULL;
681     }
682 
683     HDF_LOGD("AudioBindServiceRender() name=%{public}s", name);
684 
685     if (!strcmp(name, "render")) {
686         if (AlsaCtxInstanceGet()->renderRefCount > 0) {
687             HDF_LOGE("Error: Audio Render can only be bound to 1 handle.");
688             return NULL;
689         }
690     } else if (!strcmp(name, "control")) {
691         if (AlsaCtxInstanceGet()->ctlRefCount > 0) {
692             HDF_LOGE("Error: Audio Controler can only be bound to 1 handle.");
693             return NULL;
694         }
695     } else {
696         HDF_LOGE("Error: invalid service name.");
697         return NULL;
698     }
699 
700     handle = (struct DevHandle *)calloc(1, sizeof(struct DevHandle));
701     if (!handle) {
702         HDF_LOGE("Error: Failed to OsalMemCalloc handle");
703         return NULL;
704     }
705 
706     struct AlsaDevObject *devObject = calloc(1, sizeof(struct AlsaDevObject));
707     if (!devObject) {
708         HDF_LOGE("Error: alloc AlsaDevObject failed.");
709         free(handle);
710         return NULL;
711     }
712 
713     (void)sprintf_s(devObject->serviceName, sizeof(devObject->serviceName),
714                     "%s", name);
715     devObject->pAlsaCtx = AlsaCtxInstanceGet();
716     if (!strcmp(devObject->serviceName, "render")) {
717         devObject->pAlsaCtx->renderRefCount++;
718     } else {
719         devObject->pAlsaCtx->ctlRefCount++;
720     }
721 
722     handle->object = devObject;
723 
724     HDF_LOGI("BIND SERVICE SUCCESS!");
725 
726     return handle;
727 }
728 
AudioCloseServiceRender(const struct DevHandle * handle)729 void AudioCloseServiceRender(const struct DevHandle *handle)
730 {
731     if (!handle || !handle->object) {
732         HDF_LOGE("Error: Render handle or handle->object is NULL");
733         return;
734     }
735 
736     struct AlsaDevObject *devObject = (struct AlsaDevObject *)handle->object;
737     if (!strcmp(devObject->serviceName, "render")) {
738         if (--devObject->pAlsaCtx->renderRefCount <= 0) {
739             // Do somthing here.
740             devObject->pAlsaCtx->renderRefCount = 0;
741         }
742     } else {
743         if (--devObject->pAlsaCtx->ctlRefCount <= 0) {
744             // Do somthing here.
745             devObject->pAlsaCtx->ctlRefCount = 0;
746         }
747     }
748 
749     HDF_LOGD("AudioCloseServiceRender(), name=%{public}s",
750              devObject->serviceName);
751 
752     free((void *)handle->object);
753     free((void *)handle);
754 
755     HDF_LOGD("CLOSE SERVICE SUCCESS!");
756 
757     return;
758 }
759 
AudioInterfaceLibModeRender(const struct DevHandle * handle,struct AudioHwRenderParam * handleData,int cmdId)760 int32_t AudioInterfaceLibModeRender(const struct DevHandle *handle,
761                                     struct AudioHwRenderParam *handleData,
762                                     int cmdId)
763 {
764     if (!handle || !handle->object || !handleData) {
765         HDF_LOGE("Error: paras is NULL!");
766         return HDF_FAILURE;
767     }
768 
769     if (AUDIO_DRV_PCM_IOCTL_WRITE != cmdId) {
770         HDF_LOGE("AudioInterfaceLibModeRender(cmdid=%{public}d)", cmdId);
771     }
772 
773     switch (cmdId) {
774         case AUDIO_DRV_PCM_IOCTL_HW_PARAMS:
775         case AUDIO_DRV_PCM_IOCTL_WRITE:
776         case AUDIO_DRV_PCM_IOCTRL_STOP:
777         case AUDIO_DRV_PCM_IOCTRL_START:
778         case AUDIO_DRV_PCM_IOCTL_PREPARE:
779         case AUDIODRV_CTL_IOCTL_PAUSE_WRITE:
780         case AUDIO_DRV_PCM_IOCTL_MMAP_BUFFER:
781         case AUDIO_DRV_PCM_IOCTL_MMAP_POSITION:
782         case AUDIO_DRV_PCM_IOCTRL_RENDER_OPEN:
783         case AUDIO_DRV_PCM_IOCTRL_RENDER_CLOSE:
784             return HandleOutputRenderCmd(handle, cmdId, handleData);
785         case AUDIODRV_CTL_IOCTL_ELEM_WRITE:
786         case AUDIODRV_CTL_IOCTL_ELEM_READ:
787         case AUDIODRV_CTL_IOCTL_MUTE_WRITE:
788         case AUDIODRV_CTL_IOCTL_MUTE_READ:
789         case AUDIODRV_CTL_IOCTL_GAIN_WRITE:
790         case AUDIODRV_CTL_IOCTL_GAIN_READ:
791         case AUDIODRV_CTL_IOCTL_CHANNEL_MODE_WRITE:
792         case AUDIODRV_CTL_IOCTL_CHANNEL_MODE_READ:
793         case AUDIODRV_CTL_IOCTL_SCENESELECT_WRITE:
794         case AUDIODRV_CTL_IOCTL_GAINTHRESHOLD_READ:
795         case AUDIODRV_CTL_IOCTL_ACODEC_CHANGE_IN:
796         case AUDIODRV_CTL_IOCTL_ACODEC_CHANGE_OUT:
797         case AUDIODRV_CTL_IOCTL_VOL_THRESHOLD_READ:
798             return HandleCtlRenderCmd(handle, cmdId, handleData);
799         default:
800             HDF_LOGE("Error: Mode Error!");
801             break;
802     }
803 
804     return HDF_ERR_NOT_SUPPORT;
805 }
806