• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_capture.h"
18 
19 #define HDF_LOG_TAG HDF_AUDIO_HAL_CAPTURE
20 
21 #define AUDIO_TIMESTAMP_FREQ 8 /* Hz */
22 #define AUDIO_SAMPLE_FREQ    48000
23 #define AUDIO_PERIOD         ((AUDIO_SAMPLE_FREQ) / (AUDIO_TIMESTAMP_FREQ))
24 #define AUDIO_PCM_WAIT       100
25 #define AUDIO_RESUME_POLL    (10 * (AUDIO_PCM_WAIT)) // 1s
26 #define ALSA_CAP_BUFFER_SIZE (2 * 2 * 6000)        // format(S16LE) * channels(2) * period.
27 
28 #define POLL_EVENT_DEF false
29 #define AUDIO_BUFFER_TIME_DEF 500000
30 #define AUDIO_PERIOD_TIME_DEF 100000
31 
32 static struct AlsaCapture *g_alsaCaptureList = NULL;
33 static void RegisterCaptureImpl(struct AlsaCapture *captureIns);
34 
CaptureSetPriData(struct AlsaCapture * captureIns,CapturePriData data)35 void  CaptureSetPriData(struct AlsaCapture *captureIns, CapturePriData data)
36 {
37     captureIns->priData = data;
38 }
39 
CaptureGetPriData(struct AlsaCapture * captureIns)40 CapturePriData CaptureGetPriData(struct AlsaCapture *captureIns)
41 {
42     return captureIns->priData;
43 }
44 
CaptureFreeMemory(void)45 static int32_t CaptureFreeMemory(void)
46 {
47     int32_t i;
48 
49     if (g_alsaCaptureList != NULL) {
50         for (i = 0; i < MAX_CARD_NUM; i++) {
51             if (g_alsaCaptureList[i].soundCard.cardStatus != 0) {
52                 AUDIO_FUNC_LOGE("refCount is not zero, Sound card in use!");
53                 return HDF_ERR_DEVICE_BUSY;
54             }
55             if (g_alsaCaptureList[i].priData != NULL) {
56                 OsalMemFree(g_alsaCaptureList[i].priData);
57                 g_alsaCaptureList[i].priData = NULL;
58             }
59         }
60         AudioMemFree((void **)&g_alsaCaptureList);
61         g_alsaCaptureList = NULL;
62     }
63 
64     return HDF_SUCCESS;
65 }
66 
SetHWParamsSub(struct AlsaSoundCard * cardIns,snd_pcm_hw_params_t * params,snd_pcm_access_t access)67 static int32_t SetHWParamsSub(
68     struct AlsaSoundCard *cardIns, snd_pcm_hw_params_t *params, snd_pcm_access_t access)
69 {
70     int32_t ret;
71     snd_pcm_format_t pcmFormat;
72     snd_pcm_t *handle = cardIns->pcmHandle;
73     struct AlsaCapture *captureIns = (struct AlsaCapture *)cardIns;
74     CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
75     CHECK_NULL_PTR_RETURN_DEFAULT(params);
76 
77     ret = snd_pcm_hw_params_set_rate_resample(handle, params, captureIns->resample);
78     if (ret < 0) {
79         AUDIO_FUNC_LOGE("Resampling setup failed for capture: %{public}s", snd_strerror(ret));
80         return HDF_FAILURE;
81     }
82 
83     /* set the interleaved read/write format */
84     ret = snd_pcm_hw_params_set_access(handle, params, access);
85     if (ret < 0) {
86         AUDIO_FUNC_LOGE("Access type not available for capture: %{public}s", snd_strerror(ret));
87         return HDF_FAILURE;
88     }
89     ret = SndConverAlsaPcmFormat(&cardIns->hwParams, &pcmFormat);
90     if (ret != HDF_SUCCESS) {
91         AUDIO_FUNC_LOGE("SndConverAlsaPcmFormat error.");
92         return ret;
93     }
94 
95     /* set the sample format */
96     ret = snd_pcm_hw_params_set_format(handle, params, pcmFormat);
97     if (ret < 0) {
98         AUDIO_FUNC_LOGE("Sample format not available for capture: %{public}s", snd_strerror(ret));
99         return HDF_FAILURE;
100     }
101 
102     /* set the count of channels */
103     ret = snd_pcm_hw_params_set_channels(handle, params, cardIns->hwParams.channels);
104     if (ret < 0) {
105         AUDIO_FUNC_LOGE("Channels count (%{public}u) not available for capture: %{public}s", cardIns->hwParams.channels,
106             snd_strerror(ret));
107         return HDF_FAILURE;
108     }
109 
110     return HDF_SUCCESS;
111 }
112 
SetHWRate(struct AlsaSoundCard * cardIns,snd_pcm_hw_params_t * params)113 static int32_t SetHWRate(struct AlsaSoundCard *cardIns, snd_pcm_hw_params_t *params)
114 {
115     int32_t ret;
116     uint32_t rRate;
117     int32_t dir = 0; /* dir Value range (-1,0,1) */
118     CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
119     CHECK_NULL_PTR_RETURN_DEFAULT(params);
120 
121     /* set the stream rate */
122     rRate = cardIns->hwParams.rate;
123     ret = snd_pcm_hw_params_set_rate_near(cardIns->pcmHandle, params, &rRate, &dir);
124     if (ret < 0) {
125         AUDIO_FUNC_LOGE("Rate %{public}uHz not available for capture: %{public}s",
126             cardIns->hwParams.rate, snd_strerror(ret));
127         return HDF_FAILURE;
128     }
129 
130     if (rRate != cardIns->hwParams.rate) {
131         ret = snd_pcm_hw_params_set_rate_near(cardIns->pcmHandle, params, &rRate, &dir);
132         if (ret < 0) {
133             AUDIO_FUNC_LOGE("Rate %{public}uHz not available for capture: %{public}s",
134                 cardIns->hwParams.rate, snd_strerror(ret));
135             return HDF_FAILURE;
136         }
137     }
138     /* Update to hardware supported rate */
139     cardIns->hwParams.rate = rRate;
140 
141     return HDF_SUCCESS;
142 }
143 
SetHWBuffer(struct AlsaSoundCard * cardIns,snd_pcm_hw_params_t * params)144 static int32_t SetHWBuffer(struct AlsaSoundCard *cardIns, snd_pcm_hw_params_t *params)
145 {
146     int32_t ret;
147     int32_t dir = 0; /* dir Value range (-1,0,1) */
148     snd_pcm_uframes_t size = 0;
149     struct AlsaCapture *captureIns = (struct AlsaCapture *)cardIns;
150     CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
151     CHECK_NULL_PTR_RETURN_DEFAULT(params);
152 
153     ret = snd_pcm_hw_params_set_buffer_time_near(cardIns->pcmHandle, params, &captureIns->bufferTime, &dir);
154     if (ret < 0) {
155         AUDIO_FUNC_LOGE("Unable to set buffer time %{public}u for capture: %{public}s",
156             captureIns->bufferTime, snd_strerror(ret));
157         return HDF_FAILURE;
158     }
159 
160     ret = snd_pcm_hw_params_get_buffer_size(params, &size);
161     if (ret < 0) {
162         AUDIO_FUNC_LOGE("Unable to get buffer size for capture: %{public}s", snd_strerror(ret));
163         return HDF_FAILURE;
164     }
165     captureIns->bufferSize = size;
166 
167     return HDF_SUCCESS;
168 }
169 
SetHWPeriod(struct AlsaSoundCard * cardIns,snd_pcm_hw_params_t * params)170 static int32_t SetHWPeriod(struct AlsaSoundCard *cardIns, snd_pcm_hw_params_t *params)
171 {
172     int32_t ret;
173     int32_t dir = 0; /* dir Value range (-1,0,1) */
174     snd_pcm_uframes_t size = 0;
175     struct AlsaCapture *captureIns = (struct AlsaCapture*)cardIns;
176     CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
177     CHECK_NULL_PTR_RETURN_DEFAULT(params);
178 
179     ret = snd_pcm_hw_params_set_period_time_near(cardIns->pcmHandle, params, &captureIns->periodTime, &dir);
180     if (ret < 0) {
181         AUDIO_FUNC_LOGE("Unable to set period time %{public}u for capture: %{public}s",
182             captureIns->periodTime, snd_strerror(ret));
183         return HDF_FAILURE;
184     }
185 
186     ret = snd_pcm_hw_params_get_period_size(params, &size, &dir);
187     if (ret < 0) {
188         AUDIO_FUNC_LOGE("Unable to get period size for capture: %{public}s", snd_strerror(ret));
189         return HDF_FAILURE;
190     }
191     captureIns->periodSize = size;
192 
193     return HDF_SUCCESS;
194 }
195 
SetHWParams(struct AlsaSoundCard * cardIns,snd_pcm_access_t access)196 static int32_t SetHWParams(struct AlsaSoundCard *cardIns, snd_pcm_access_t access)
197 {
198     int32_t ret;
199     snd_pcm_hw_params_t *hwParams = NULL;
200     snd_pcm_t *handle = cardIns->pcmHandle;
201     CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
202     CHECK_NULL_PTR_RETURN_DEFAULT(handle);
203 
204     snd_pcm_hw_params_alloca(&hwParams);
205     ret = snd_pcm_hw_params_any(handle, hwParams); // choose all parameters
206     if (ret < 0) {
207         AUDIO_FUNC_LOGE("Broken configuration for capture: no configurations available: %{public}s.",
208             snd_strerror(ret));
209         return HDF_FAILURE;
210     }
211 
212     ret = SetHWParamsSub(cardIns, hwParams, access);
213     if (ret != HDF_SUCCESS) {
214         AUDIO_FUNC_LOGE("SetHWParamsSub failed!");
215         return ret;
216     }
217 
218     ret = SetHWRate(cardIns, hwParams);
219     if (ret != HDF_SUCCESS) {
220         AUDIO_FUNC_LOGE("SetHWRate failed!");
221         return ret;
222     }
223 
224     ret = SetHWBuffer(cardIns, hwParams);
225     if (ret != HDF_SUCCESS) {
226         AUDIO_FUNC_LOGE("SetHWBuffer failed!");
227         return ret;
228     }
229 
230     ret = SetHWPeriod(cardIns, hwParams);
231     if (ret != HDF_SUCCESS) {
232         AUDIO_FUNC_LOGE("SetHWPeriod failed!");
233         return ret;
234     }
235 
236     /* write the parameters to device. */
237     ret = snd_pcm_hw_params(handle, hwParams);
238     if (ret < 0) {
239         AUDIO_FUNC_LOGE("Unable to set hw params for capture: %{public}s", snd_strerror(ret));
240         return HDF_FAILURE;
241     }
242 
243     cardIns->canPause = snd_pcm_hw_params_can_pause(hwParams);
244     AUDIO_FUNC_LOGI("hardware driver %{public}s support pause",cardIns->canPause ? "is" : "is not");
245 
246     return HDF_SUCCESS;
247 }
248 
SetSWParams(struct AlsaSoundCard * cardIns)249 static int32_t SetSWParams(struct AlsaSoundCard *cardIns)
250 {
251     int32_t ret;
252     /* The time when the application starts reading data */
253     snd_pcm_sframes_t startThresholdSize = 1;
254     snd_pcm_sw_params_t *swParams = NULL;
255     snd_pcm_t *handle = cardIns->pcmHandle;
256     struct AlsaCapture *captureIns = (struct AlsaCapture *)cardIns;
257     CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
258     CHECK_NULL_PTR_RETURN_DEFAULT(handle);
259 
260     snd_pcm_sw_params_alloca(&swParams);
261     /* get the current swparams */
262     ret = snd_pcm_sw_params_current(handle, swParams);
263     if (ret < 0) {
264         AUDIO_FUNC_LOGE("Unable to determine current swparams for capture: %{public}s.", snd_strerror(ret));
265         return HDF_FAILURE;
266     }
267     if (captureIns->periodSize == 0) {
268         AUDIO_FUNC_LOGE("error: g_periodSize cannot be zero!");
269         return HDF_FAILURE;
270     }
271     /* start the transfer when the buffer is 1 frames */
272     ret = snd_pcm_sw_params_set_start_threshold(handle, swParams, startThresholdSize);
273     if (ret < 0) {
274         AUDIO_FUNC_LOGE("Unable to set start threshold mode for capture: %{public}s.", snd_strerror(ret));
275         return HDF_FAILURE;
276     }
277 
278     /* allow the transfer when at least period_size samples can be processed */
279     /* or disable this mechanism when period event is enabled (aka interrupt like style processing) */
280     ret = snd_pcm_sw_params_set_avail_min(handle, swParams,
281         captureIns->periodEvent ? captureIns->bufferSize : captureIns->periodSize);
282     if (ret < 0) {
283         AUDIO_FUNC_LOGE("Unable to set avail min for capture: %{public}s", snd_strerror(ret));
284         return HDF_FAILURE;
285     }
286 
287     /* enable period events when requested */
288     if (captureIns->periodEvent) {
289         ret = snd_pcm_sw_params_set_period_event(handle, swParams, 1);
290         if (ret < 0) {
291             AUDIO_FUNC_LOGE("Unable to set period event: %{public}s", snd_strerror(ret));
292             return HDF_FAILURE;
293         }
294     }
295     /* write the parameters to the capture device */
296     ret = snd_pcm_sw_params(handle, swParams);
297     if (ret < 0) {
298         AUDIO_FUNC_LOGE("Unable to set sw params for capture: %{public}s", snd_strerror(ret));
299         return HDF_FAILURE;
300     }
301 
302     return HDF_SUCCESS;
303 }
304 
ResetCaptureParams(struct AlsaSoundCard * cardIns,snd_pcm_access_t access)305 static int32_t ResetCaptureParams(struct AlsaSoundCard *cardIns, snd_pcm_access_t access)
306 {
307     int32_t ret;
308     CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
309     CHECK_NULL_PTR_RETURN_DEFAULT(cardIns->pcmHandle);
310 
311     ret = SetHWParams(cardIns, access);
312     if (ret != HDF_SUCCESS) {
313         AUDIO_FUNC_LOGE("Setting of hwparams failed: %{public}d.", ret);
314         return ret;
315     }
316 
317     ret = SetSWParams(cardIns);
318     if (ret != HDF_SUCCESS) {
319         AUDIO_FUNC_LOGE("Setting of swparams failed: %{public}d.", ret);
320         return ret;
321     }
322 
323     return HDF_SUCCESS;
324 }
325 
UpdateSetParams(struct AlsaSoundCard * cardIns)326 static int32_t UpdateSetParams(struct AlsaSoundCard *cardIns)
327 {
328     int32_t ret;
329     CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
330     CHECK_NULL_PTR_RETURN_DEFAULT(cardIns->pcmHandle);
331 
332     cardIns->mmapFlag = false;
333     ret = ResetCaptureParams(cardIns, SND_PCM_ACCESS_MMAP_INTERLEAVED);
334     if (ret != HDF_SUCCESS) {
335         AUDIO_FUNC_LOGE("AudioSetParamsMmap failed!");
336         return ret;
337     }
338 
339     ret = snd_pcm_start(cardIns->pcmHandle);
340     if (ret < 0) {
341         AUDIO_FUNC_LOGE("snd_pcm_start fail. %{public}s.", snd_strerror(ret));
342         return HDF_FAILURE;
343     }
344 
345     return HDF_SUCCESS;
346 }
347 
SaveHwParams(struct AlsaSoundCard * cardIns,const struct AudioHwCaptureParam * handleData)348 static int32_t SaveHwParams(struct AlsaSoundCard *cardIns, const struct AudioHwCaptureParam *handleData)
349 {
350     CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
351     CHECK_NULL_PTR_RETURN_DEFAULT(handleData);
352 
353     cardIns->hwParams.streamType = AUDIO_CAPTURE_STREAM;
354     cardIns->hwParams.channels = handleData->frameCaptureMode.attrs.channelCount;
355     cardIns->hwParams.rate = handleData->frameCaptureMode.attrs.sampleRate;
356     cardIns->hwParams.periodSize = handleData->frameCaptureMode.periodSize;
357     cardIns->hwParams.periodCount = handleData->frameCaptureMode.periodCount;
358     cardIns->hwParams.format = handleData->frameCaptureMode.attrs.format;
359     cardIns->hwParams.period = handleData->frameCaptureMode.attrs.period;
360     cardIns->hwParams.frameSize = handleData->frameCaptureMode.attrs.frameSize;
361     cardIns->hwParams.isBigEndian = handleData->frameCaptureMode.attrs.isBigEndian;
362     cardIns->hwParams.isSignedData = handleData->frameCaptureMode.attrs.isSignedData;
363     cardIns->hwParams.startThreshold = handleData->frameCaptureMode.attrs.startThreshold;
364     cardIns->hwParams.stopThreshold = handleData->frameCaptureMode.attrs.stopThreshold;
365     cardIns->hwParams.silenceThreshold = handleData->frameCaptureMode.attrs.silenceThreshold;
366 
367     return HDF_SUCCESS;
368 }
369 
CaptureSetParams(struct AlsaCapture * captureIns,const struct AudioHwCaptureParam * handleData)370 int32_t CaptureSetParams(struct AlsaCapture *captureIns, const struct AudioHwCaptureParam *handleData)
371 {
372     int32_t ret;
373     struct AlsaSoundCard *cardIns = (struct AlsaSoundCard *)captureIns;
374     CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
375     CHECK_NULL_PTR_RETURN_DEFAULT(handleData);
376 
377     SaveHwParams(cardIns, handleData);
378     ret = SetHWParams(cardIns, SND_PCM_ACCESS_RW_INTERLEAVED);
379     if (ret < 0) {
380         AUDIO_FUNC_LOGE("Setting of hwparams failed.");
381         return HDF_FAILURE;
382     }
383 
384     ret = SetSWParams(cardIns);
385     if (ret < 0) {
386         AUDIO_FUNC_LOGE("Setting of swparams failed.");
387         return HDF_FAILURE;
388     }
389 
390     return HDF_SUCCESS;
391 }
392 
GetCaptureInsByName(const char * adapterName)393 static struct AlsaCapture *GetCaptureInsByName(const char *adapterName)
394 {
395     int32_t ret;
396     int32_t i;
397     struct AlsaCapture *captureIns = NULL;
398     struct AlsaSoundCard *alsaSnd = NULL;
399 
400     /*
401     fine the instance with the corresponding adapter name, or create one if none.
402     */
403     for (i = 0; i < MAX_CARD_NUM; i++) {
404         alsaSnd = (struct AlsaSoundCard *)&g_alsaCaptureList[i];
405         if (alsaSnd->cardStatus) {
406             if (0 == strcmp(alsaSnd->adapterName, adapterName)) {
407                 return &g_alsaCaptureList[i];
408             }
409         }
410     }
411 
412     for (i = 0; i < MAX_CARD_NUM; i++) {
413         captureIns = &g_alsaCaptureList[i];
414         alsaSnd = (struct AlsaSoundCard *)&g_alsaCaptureList[i];
415         if (alsaSnd->cardStatus == 0) {
416             (void)memset_s(captureIns, sizeof(struct AlsaCapture), 0, sizeof(struct AlsaCapture));
417             ret = strncpy_s(alsaSnd->adapterName, MAX_CARD_NAME_LEN + 1, adapterName, strlen(adapterName));
418             if (ret != 0) {
419                 AUDIO_FUNC_LOGE("strncpy_s failed!");
420                 return NULL;
421             }
422             alsaSnd->cardStatus++;
423             captureIns->periodEvent = POLL_EVENT_DEF;
424             captureIns->periodTime = AUDIO_PERIOD_TIME_DEF;
425             captureIns->bufferTime = AUDIO_BUFFER_TIME_DEF;
426             captureIns->descPins = PIN_NONE;
427             captureIns->resample = 1;
428             return captureIns;
429         }
430     }
431     AUDIO_FUNC_LOGE("Failed to AddCardIns!");
432     return NULL;
433 }
434 
CaptureCreateInstance(const char * adapterName)435 struct AlsaCapture *CaptureCreateInstance(const char* adapterName)
436 {
437     int32_t ret;
438     struct AlsaCapture *captureIns = NULL;
439     if (adapterName == NULL || strlen(adapterName) == 0) {
440         AUDIO_FUNC_LOGE("Invalid adapterName!");
441         return NULL;
442     }
443 
444     if (g_alsaCaptureList == NULL) {
445         g_alsaCaptureList = (struct AlsaCapture *)OsalMemCalloc(MAX_CARD_NUM * sizeof(struct AlsaCapture));
446         if (g_alsaCaptureList == NULL) {
447             AUDIO_FUNC_LOGE("Failed to allocate memory!");
448             return NULL;
449         }
450     }
451 
452     captureIns = GetCaptureInsByName(adapterName);
453     if (captureIns == NULL) {
454         AUDIO_FUNC_LOGE("Get capture instance failed.");
455         return NULL;
456     }
457     RegisterCaptureImpl(captureIns);
458 
459     ret = SndSaveCardListInfo(SND_PCM_STREAM_CAPTURE);
460     if (ret != HDF_SUCCESS) {
461         AUDIO_FUNC_LOGE("Failed to save card device info.");
462         return NULL;
463     }
464 
465     ret = SndMatchSelAdapter(&captureIns->soundCard, adapterName);
466     if (ret != HDF_SUCCESS) {
467         SndCloseHandle(&captureIns->soundCard);
468         CaptureFreeMemory();
469         return NULL;
470     }
471     CaptureOverrideFunc(captureIns);
472 
473     return captureIns;
474 }
475 
CaptureGetInstance(const char * adapterName)476 struct AlsaCapture *CaptureGetInstance(const char *adapterName)
477 {
478     int32_t i;
479 
480     if (adapterName == NULL || strlen(adapterName) == 0) {
481         AUDIO_FUNC_LOGE("Invalid cardName!");
482         return NULL;
483     }
484 
485     if (g_alsaCaptureList == NULL) {
486         AUDIO_FUNC_LOGE("g_alsaCaptureList is NULL!");
487         return NULL;
488     }
489 
490     for (i = 0; i < MAX_CARD_NUM; i++) {
491         if (strcmp(g_alsaCaptureList[i].soundCard.adapterName, adapterName) == 0) {
492             return &(g_alsaCaptureList[i]);
493         }
494     }
495 
496     return NULL;
497 }
498 
CheckCapFrameBufferSize(struct AudioHwCaptureParam * handleData,snd_pcm_uframes_t * periodSize)499 static int32_t CheckCapFrameBufferSize(struct AudioHwCaptureParam *handleData, snd_pcm_uframes_t *periodSize)
500 {
501     uint32_t capFrameSize;
502     uint64_t capReqBufferSize;
503     CHECK_NULL_PTR_RETURN_DEFAULT(handleData);
504     CHECK_NULL_PTR_RETURN_DEFAULT(periodSize);
505 
506     capFrameSize = handleData->frameCaptureMode.attrs.channelCount * handleData->frameCaptureMode.attrs.format;
507     if (capFrameSize == 0) {
508         AUDIO_FUNC_LOGE("Capture frame size is zero!");
509         return HDF_FAILURE;
510     }
511     capReqBufferSize = capFrameSize * (*periodSize);
512     if (capReqBufferSize > FRAME_DATA) {
513         *periodSize = FRAME_DATA / capFrameSize;
514     }
515 
516     return HDF_SUCCESS;
517 }
518 
CheckPcmStatus(snd_pcm_t * capturePcmHandle)519 static int32_t CheckPcmStatus(snd_pcm_t *capturePcmHandle)
520 {
521     int32_t ret;
522     CHECK_NULL_PTR_RETURN_DEFAULT(capturePcmHandle);
523 
524     ret = snd_pcm_wait(capturePcmHandle, -1); /* -1 for timeout, Waiting forever */
525     if (ret < 0) {
526         AUDIO_FUNC_LOGE("snd_pcm_wait failed: %{public}s.", snd_strerror(ret));
527         return HDF_FAILURE;
528     }
529 
530     if (snd_pcm_state(capturePcmHandle) == SND_PCM_STATE_SETUP) {
531         ret = snd_pcm_prepare(capturePcmHandle);
532         if (ret < 0) {
533             AUDIO_FUNC_LOGE("snd_pcm_prepare fail: %{public}s", snd_strerror(ret));
534             return HDF_FAILURE;
535         }
536     }
537 
538     return HDF_SUCCESS;
539 }
540 
CapturePcmReadi(snd_pcm_t * pcm,uint64_t * frameCnt,char * dataBuf,snd_pcm_uframes_t bufSize)541 static int32_t CapturePcmReadi(snd_pcm_t *pcm, uint64_t *frameCnt, char *dataBuf, snd_pcm_uframes_t bufSize)
542 {
543     int32_t ret;
544     long frames;
545     int32_t tryNum = AUDIO_ALSALIB_RETYR;
546     CHECK_NULL_PTR_RETURN_DEFAULT(pcm);
547     CHECK_NULL_PTR_RETURN_DEFAULT(frameCnt);
548     CHECK_NULL_PTR_RETURN_DEFAULT(dataBuf);
549     if (bufSize == 0) {
550         AUDIO_FUNC_LOGE("Capture data buf is empty.");
551         return HDF_FAILURE;
552     }
553 
554     do {
555         /* Read interleaved frames to a PCM. */
556         frames = snd_pcm_readi(pcm, dataBuf, bufSize);
557         if (frames > 0) {
558             *frameCnt = (uint64_t)frames;
559             return HDF_SUCCESS;
560         }
561 
562         if (frames == -EBADFD) {
563             AUDIO_FUNC_LOGE("Capture PCM is not in the right state: %{public}s", snd_strerror(frames));
564             ret = snd_pcm_prepare(pcm);
565             if (ret < 0) {
566                 AUDIO_FUNC_LOGE("Capture snd_pcm_prepare fail: %{public}s", snd_strerror(ret));
567                 return HDF_FAILURE;
568             }
569         } else {
570             /* -ESTRPIPE: a suspend event occurred,
571              * stream is suspended and waiting for an application recovery.
572              * -EPIPE: an underrun occurred.
573              */
574             ret = snd_pcm_recover(pcm, frames, 0); // 0 for open capture recover log.
575             if (ret < 0) {
576                 AUDIO_FUNC_LOGE("snd_pcm_readi failed: %{public}s", snd_strerror(ret));
577                 return HDF_FAILURE;
578             }
579         }
580         ret = snd_pcm_start(pcm);
581         if (ret < 0) {
582             AUDIO_FUNC_LOGE("snd_pcm_start fail. %{public}s", snd_strerror(ret));
583             return HDF_FAILURE;
584         }
585         tryNum--;
586     } while (tryNum > 0);
587 
588     return HDF_SUCCESS;
589 }
590 
CaptureDataCopy(struct AudioHwCaptureParam * handleData,char * buffer,uint64_t frames)591 static int32_t CaptureDataCopy(struct AudioHwCaptureParam *handleData, char *buffer, uint64_t frames)
592 {
593     int32_t ret;
594     uint32_t channels;
595     uint32_t format;
596     uint64_t recvDataSize;
597     CHECK_NULL_PTR_RETURN_DEFAULT(handleData);
598     CHECK_NULL_PTR_RETURN_DEFAULT(buffer);
599     if (frames == 0) {
600         AUDIO_FUNC_LOGE("Capture buffer size is empty!");
601         return HDF_FAILURE;
602     }
603 
604     if (handleData->frameCaptureMode.buffer == NULL) {
605         AUDIO_FUNC_LOGE("frameCaptureMode.buffer is NULL!");
606         return HDF_FAILURE;
607     }
608     channels = handleData->frameCaptureMode.attrs.channelCount;
609     format = (uint32_t)handleData->frameCaptureMode.attrs.format;
610     recvDataSize = (uint64_t)(frames * channels * format);
611     ret = memcpy_s(handleData->frameCaptureMode.buffer, FRAME_DATA, buffer, recvDataSize);
612     if (ret != EOK) {
613         AUDIO_FUNC_LOGE("memcpy frame data failed!");
614         return HDF_FAILURE;
615     }
616     handleData->frameCaptureMode.bufferSize = recvDataSize;
617     handleData->frameCaptureMode.bufferFrameSize = frames;
618 
619     return HDF_SUCCESS;
620 }
621 
CaptureOpenImpl(struct AlsaCapture * captureIns)622 static int32_t CaptureOpenImpl(struct AlsaCapture *captureIns)
623 {
624     int32_t ret;
625     CHECK_NULL_PTR_RETURN_DEFAULT(captureIns);
626 
627     if (SndisBusy(&captureIns->soundCard)) {
628         AUDIO_FUNC_LOGE("Resource busy!!");
629         SndCloseHandle(&captureIns->soundCard);
630         return HDF_ERR_DEVICE_BUSY;
631     }
632 
633     ret = snd_pcm_open(&captureIns->soundCard.pcmHandle, captureIns->soundCard.devName,
634         SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
635     if (ret < 0) {
636         AUDIO_FUNC_LOGE("snd_pcm_open fail: %{public}s!", snd_strerror(ret));
637         CaptureFreeMemory();
638         return HDF_FAILURE;
639     }
640 
641     ret = snd_pcm_nonblock(captureIns->soundCard.pcmHandle, 1);
642     if (ret < 0) {
643         AUDIO_FUNC_LOGE("snd_pcm_nonblock fail: %{public}s!", snd_strerror(ret));
644         SndCloseHandle(&captureIns->soundCard);
645         CaptureFreeMemory();
646         return HDF_FAILURE;
647     }
648 
649     ret = SndOpenMixer(&captureIns->soundCard);
650     if (ret != HDF_SUCCESS) {
651         AUDIO_FUNC_LOGE("SndOpenMixer failed");
652         SndCloseHandle(&captureIns->soundCard);
653         CaptureFreeMemory();
654         return HDF_FAILURE;
655     }
656 
657     return HDF_SUCCESS;
658 }
659 
CaptureCloseImpl(struct AlsaCapture * captureIns)660 static int32_t CaptureCloseImpl(struct AlsaCapture *captureIns)
661 {
662     CHECK_NULL_PTR_RETURN_DEFAULT(captureIns);
663     SndCloseHandle(&captureIns->soundCard);
664     CaptureFreeMemory();
665     return HDF_SUCCESS;
666 }
667 
CaptureCheckMmapMode(struct AlsaSoundCard * cardIns)668 static int32_t CaptureCheckMmapMode(struct AlsaSoundCard *cardIns)
669 {
670     int32_t ret;
671     CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
672 
673     if (!cardIns->mmapFlag) {
674         ret = ResetCaptureParams(cardIns, SND_PCM_ACCESS_RW_INTERLEAVED);
675         if (ret != HDF_SUCCESS) {
676             AUDIO_FUNC_LOGE("AudioSetParamsMmap failed!");
677             return ret;
678         }
679 
680         ret = snd_pcm_start(cardIns->pcmHandle);
681         if (ret < 0) {
682             AUDIO_FUNC_LOGE("snd_pcm_start fail. %{public}s", snd_strerror(ret));
683             return HDF_FAILURE;
684         }
685         cardIns->mmapFlag = true;
686     }
687     return HDF_SUCCESS;
688 }
689 
CaptureReadImpl(struct AlsaCapture * captureIns,struct AudioHwCaptureParam * handleData)690 static int32_t CaptureReadImpl(struct AlsaCapture *captureIns, struct AudioHwCaptureParam *handleData)
691 {
692     int32_t ret;
693     uint64_t frames = 0;
694     char *buffer = NULL;
695     snd_pcm_uframes_t bufferSize = 0;
696     snd_pcm_uframes_t periodSize = 0;
697     struct AlsaSoundCard *cardIns = (struct AlsaSoundCard *)captureIns;
698     CHECK_NULL_PTR_RETURN_DEFAULT(captureIns);
699     CHECK_NULL_PTR_RETURN_DEFAULT(handleData);
700 
701     if (cardIns->pauseState) {
702         AUDIO_FUNC_LOGE("Currently in pause, please check!");
703         return HDF_FAILURE;
704     }
705 
706     ret = snd_pcm_get_params(cardIns->pcmHandle, &bufferSize, &periodSize);
707     if (ret < 0) {
708         AUDIO_FUNC_LOGE("Get capture params error: %{public}s.", snd_strerror(ret));
709         return HDF_FAILURE;
710     }
711     if (CaptureCheckMmapMode(cardIns) != HDF_SUCCESS) {
712         return HDF_FAILURE;
713     }
714 
715     if (CheckCapFrameBufferSize(handleData, &periodSize) != HDF_SUCCESS) {
716         AUDIO_FUNC_LOGE("CheckCapFrameBufferSize failed.");
717         return HDF_FAILURE;
718     }
719     if (CheckPcmStatus(cardIns->pcmHandle) != HDF_SUCCESS) {
720         AUDIO_FUNC_LOGE("CheckPcmStatus failed.");
721         return HDF_FAILURE;
722     }
723     buffer = OsalMemCalloc(ALSA_CAP_BUFFER_SIZE);
724     if (buffer == NULL) {
725         AUDIO_FUNC_LOGE("Failed to Calloc buffer");
726         return HDF_FAILURE;
727     }
728     ret = CapturePcmReadi(cardIns->pcmHandle, &frames, buffer, periodSize);
729     if (ret != HDF_SUCCESS) {
730         AUDIO_FUNC_LOGE("CapturePcmReadi is error!");
731         AudioMemFree((void **)&buffer);
732         return ret;
733     }
734     ret = CaptureDataCopy(handleData, buffer, frames);
735     if (ret != HDF_SUCCESS) {
736         AUDIO_FUNC_LOGE("Failed to copy data. It may be paused. Check the status!");
737         AudioMemFree((void **)&buffer);
738         return ret;
739     }
740 
741     AudioMemFree((void **)&buffer);
742     return HDF_SUCCESS;
743 }
744 
CaptureGetMmapPositionImpl(struct AlsaCapture * captureIns)745 static int32_t CaptureGetMmapPositionImpl(struct AlsaCapture *captureIns)
746 {
747     return captureIns->soundCard.mmapFrames;
748 }
749 
CaptureMmapReadImpl(struct AlsaCapture * captureIns,const struct AudioHwCaptureParam * handleData)750 static int32_t CaptureMmapReadImpl(struct AlsaCapture *captureIns, const struct AudioHwCaptureParam *handleData)
751 {
752     char *mmapAddr;
753     uint32_t frameSize;
754     snd_pcm_sframes_t xfer;
755     snd_pcm_uframes_t size;
756     struct AlsaSoundCard *cardIns = (struct AlsaSoundCard *)captureIns;
757     CHECK_NULL_PTR_RETURN_DEFAULT(captureIns);
758     CHECK_NULL_PTR_RETURN_DEFAULT(handleData);
759 
760     if (cardIns->pauseState) {
761         AUDIO_FUNC_LOGE("Currently in pause, please check!");
762         return HDF_FAILURE;
763     }
764 
765     if (UpdateSetParams(cardIns) != HDF_SUCCESS) {
766         AUDIO_FUNC_LOGE("Update set params failed!");
767         return HDF_FAILURE;
768     }
769 
770     mmapAddr = (char *)handleData->frameCaptureMode.mmapBufDesc.memoryAddress;
771     if (mmapAddr == NULL) {
772         AUDIO_FUNC_LOGE("mmapAddr is NULL!");
773         return HDF_FAILURE;
774     }
775     size = (snd_pcm_sframes_t)handleData->frameCaptureMode.mmapBufDesc.totalBufferFrames;
776     frameSize = handleData->frameCaptureMode.attrs.channelCount * handleData->frameCaptureMode.attrs.format;
777     while (size > 0) {
778         xfer = snd_pcm_mmap_readi(cardIns->pcmHandle, mmapAddr, size);
779         if (xfer < 0) {
780             if (xfer == -EAGAIN) {
781                 snd_pcm_wait(cardIns->pcmHandle, AUDIO_PCM_WAIT);
782                 continue;
783             }
784             AUDIO_FUNC_LOGE("snd_pcm_mmap_readi: %{public}s", snd_strerror(xfer));
785             return HDF_FAILURE;
786         }
787 
788         if (xfer > 0) {
789             mmapAddr += xfer * frameSize;
790             size -= xfer;
791             cardIns->mmapFrames += xfer;
792         }
793     }
794 
795     return HDF_SUCCESS;
796 }
797 
CaptureInitImpl(struct AlsaCapture * captureIns)798 static int32_t CaptureInitImpl(struct AlsaCapture* captureIns)
799 {
800     AUDIO_FUNC_LOGE("Not yet realized");
801     return HDF_SUCCESS;
802 }
803 
CaptureSelectSceneImpl(struct AlsaCapture * captureIns,enum AudioPortPin descPins,const struct PathDeviceInfo * deviceInfo)804 static int32_t CaptureSelectSceneImpl(struct AlsaCapture *captureIns, enum AudioPortPin descPins,
805     const struct PathDeviceInfo *deviceInfo)
806 {
807     AUDIO_FUNC_LOGE("Not yet realized");
808     return HDF_SUCCESS;
809 }
810 
CaptureStartImpl(struct AlsaCapture * captureIns)811 static int32_t CaptureStartImpl(struct AlsaCapture *captureIns)
812 {
813     AUDIO_FUNC_LOGE("Not yet realized");
814     return HDF_SUCCESS;
815 }
816 
CaptureStopImpl(struct AlsaCapture * captureIns)817 static int32_t CaptureStopImpl(struct AlsaCapture *captureIns)
818 {
819     AUDIO_FUNC_LOGE("Not yet realized");
820     return HDF_SUCCESS;
821 }
822 
CaptureGetVolThresholdImpl(struct AlsaCapture * captureIns,long * volMin,long * volMax)823 static int32_t CaptureGetVolThresholdImpl(struct AlsaCapture *captureIns, long *volMin, long *volMax)
824 {
825     AUDIO_FUNC_LOGE("Not yet realized");
826     return HDF_SUCCESS;
827 }
828 
CaptureGetVolumeImpl(struct AlsaCapture * captureIns,long * volume)829 static int32_t CaptureGetVolumeImpl(struct AlsaCapture *captureIns, long *volume)
830 {
831     AUDIO_FUNC_LOGE("Not yet realized");
832     return HDF_SUCCESS;
833 }
834 
CaptureSetVolumeImpl(struct AlsaCapture * captureIns,long volume)835 static int32_t CaptureSetVolumeImpl(struct AlsaCapture *captureIns, long volume)
836 {
837     AUDIO_FUNC_LOGE("Not yet realized");
838     return HDF_SUCCESS;
839 }
840 
CaptureGetGainThresholdImpl(struct AlsaCapture * captureIns,float * gainMin,float * gainMax)841 static int32_t CaptureGetGainThresholdImpl(struct AlsaCapture *captureIns, float *gainMin, float *gainMax)
842 {
843     AUDIO_FUNC_LOGE("Not yet realized");
844     return HDF_SUCCESS;
845 }
846 
CaptureGetGainImpl(struct AlsaCapture * captureIns,float * gain)847 static int32_t CaptureGetGainImpl(struct AlsaCapture *captureIns, float *gain)
848 {
849     AUDIO_FUNC_LOGE("Not yet realized");
850     return HDF_SUCCESS;
851 }
852 
CaptureSetGainImpl(struct AlsaCapture * captureIns,float gain)853 static int32_t CaptureSetGainImpl(struct AlsaCapture *captureIns, float gain)
854 {
855     AUDIO_FUNC_LOGE("Not yet realized");
856     return HDF_SUCCESS;
857 }
858 
CaptureGetMuteImpl(struct AlsaCapture * captureIns)859 static bool CaptureGetMuteImpl(struct AlsaCapture *captureIns)
860 {
861     AUDIO_FUNC_LOGE("Not yet realized");
862     return false;
863 }
864 
CaptureSetMuteImpl(struct AlsaCapture * captureIns,bool muteFlag)865 static int32_t CaptureSetMuteImpl(struct AlsaCapture *captureIns, bool muteFlag)
866 {
867     AUDIO_FUNC_LOGE("Not yet realized");
868     return HDF_SUCCESS;
869 }
870 
CaptureSetPauseStateImpl(struct AlsaCapture * captureIns,bool pauseFlag)871 static int32_t CaptureSetPauseStateImpl(struct AlsaCapture *captureIns, bool pauseFlag)
872 {
873     int32_t ret;
874     int pause = pauseFlag ? AUDIO_ALSALIB_IOCTRL_PAUSE : AUDIO_ALSALIB_IOCTRL_RESUME;
875     struct AlsaSoundCard *cardIns = (struct AlsaSoundCard *)captureIns;
876 
877     if (cardIns->canPause) {
878         ret = snd_pcm_pause(cardIns->pcmHandle, pause);
879         if (ret < 0) {
880             AUDIO_FUNC_LOGE("snd_pcm_pause failed!");
881             return HDF_FAILURE;
882         }
883     } else {
884         if (pause == AUDIO_ALSALIB_IOCTRL_RESUME) {
885             ret = snd_pcm_prepare(cardIns->pcmHandle);
886             if (ret < 0) {
887                 AUDIO_FUNC_LOGE("snd_pcm_prepare fail: %{public}s", snd_strerror(ret));
888                 return HDF_FAILURE;
889             }
890             ret = snd_pcm_start(cardIns->pcmHandle);
891             if (ret < 0) {
892                 AUDIO_FUNC_LOGE("snd_pcm_start fail. %{public}s", snd_strerror(ret));
893                 return HDF_FAILURE;
894             }
895         }
896         if (pause == AUDIO_ALSALIB_IOCTRL_PAUSE) {
897             ret = snd_pcm_drop(cardIns->pcmHandle);
898             if (ret < 0) {
899                 AUDIO_FUNC_LOGE("Pause fail: %{public}s", snd_strerror(ret));
900                 return HDF_FAILURE;
901             }
902         }
903     }
904     cardIns->pauseState = pauseFlag;
905 
906     return HDF_SUCCESS;
907 }
908 
RegisterCaptureImpl(struct AlsaCapture * captureIns)909 static void RegisterCaptureImpl(struct AlsaCapture *captureIns)
910 {
911     if (captureIns == NULL) {
912         AUDIO_FUNC_LOGE("captureIns is NULL!");
913     }
914 
915     captureIns->Init = CaptureInitImpl;
916     captureIns->Open = CaptureOpenImpl;
917     captureIns->Close = CaptureCloseImpl;
918     captureIns->SelectScene = CaptureSelectSceneImpl;
919     captureIns->Start = CaptureStartImpl;
920     captureIns->Stop = CaptureStopImpl;
921     captureIns->Read = CaptureReadImpl;
922     captureIns->GetMmapPosition = CaptureGetMmapPositionImpl;
923     captureIns->MmapRead = CaptureMmapReadImpl;
924     captureIns->GetVolThreshold = CaptureGetVolThresholdImpl;
925     captureIns->GetVolume = CaptureGetVolumeImpl;
926     captureIns->SetVolume = CaptureSetVolumeImpl;
927     captureIns->GetGainThreshold = CaptureGetGainThresholdImpl;
928     captureIns->GetGain = CaptureGetGainImpl;
929     captureIns->SetGain = CaptureSetGainImpl;
930     captureIns->GetMute = CaptureGetMuteImpl;
931     captureIns->SetMute = CaptureSetMuteImpl;
932     captureIns->SetPauseState = CaptureSetPauseStateImpl;
933 }
934