blob: d03a57017d7bb8848731fbe6b52c76fa010c9526 [file] [log] [blame]
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301/*
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +05302* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
Manish Dewanganb8c83a42016-09-23 15:10:48 +05303*
4* Redistribution and use in source and binary forms, with or without
5* modification, are permitted provided that the following conditions are
6* met:
7* * Redistributions of source code must retain the above copyright
8* notice, this list of conditions and the following disclaimer.
9* * Redistributions in binary form must reproduce the above
10* copyright notice, this list of conditions and the following
11* disclaimer in the documentation and/or other materials provided
12* with the distribution.
13* * Neither the name of The Linux Foundation nor the names of its
14* contributors may be used to endorse or promote products derived
15* from this software without specific prior written permission.
16*
17* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*/
29
30#define LOG_TAG "qahw"
31/*#define LOG_NDEBUG 0*/
32#define LOG_NDDEBUG 0
33
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +053034#include <dlfcn.h>
Manish Dewanganb8c83a42016-09-23 15:10:48 +053035#include <utils/Log.h>
36#include <stdlib.h>
37#include <cutils/list.h>
38
39#include <hardware/audio.h>
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +053040#include <hardware/sound_trigger.h>
Sidipotu Ashok404f26d2017-10-10 22:27:51 +053041#include "qahw.h"
Manish Dewanganb8c83a42016-09-23 15:10:48 +053042
43#define NO_ERROR 0
44#define MAX_MODULE_NAME_LENGTH 100
45
46/*
47 * The current HAL API version.
48 */
49#define QAHW_MODULE_API_VERSION_CURRENT QAHW_MODULE_API_VERSION_0_0
50
Naresh Tanniruee3499a2017-01-05 14:05:35 +053051
52typedef uint64_t (*qahwi_out_write_v2_t)(audio_stream_out_t *out, const void* buffer,
53 size_t bytes, int64_t* timestamp);
54
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +053055typedef int (*qahwi_get_param_data_t) (const audio_hw_device_t *,
56 qahw_param_id, qahw_param_payload *);
57
58typedef int (*qahwi_set_param_data_t) (audio_hw_device_t *,
59 qahw_param_id, qahw_param_payload *);
60
Manish Dewangan3ccdea52017-02-13 19:31:54 +053061typedef uint64_t (*qahwi_in_read_v2_t)(audio_stream_in_t *in, void* buffer,
62 size_t bytes, int64_t *timestamp);
63
64typedef int (*qahwi_out_set_param_data_t)(struct audio_stream_out *out,
65 qahw_param_id param_id,
66 qahw_param_payload *payload);
67
68typedef int (*qahwi_out_get_param_data_t)(struct audio_stream_out *out,
69 qahw_param_id param_id,
70 qahw_param_payload *payload);
71
Manish Dewanganb8c83a42016-09-23 15:10:48 +053072typedef struct {
73 audio_hw_device_t *audio_device;
74 char module_name[MAX_MODULE_NAME_LENGTH];
75 struct listnode module_list;
76 struct listnode in_list;
77 struct listnode out_list;
78 pthread_mutex_t lock;
79 uint32_t ref_count;
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +053080 const hw_module_t* module;
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +053081 qahwi_get_param_data_t qahwi_get_param_data;
82 qahwi_set_param_data_t qahwi_set_param_data;
Manish Dewanganb8c83a42016-09-23 15:10:48 +053083} qahw_module_t;
84
85typedef struct {
86 qahw_module_t *module;
87 struct listnode module_list;
88 pthread_mutex_t lock;
89} qahw_module_instances_t;
90
91typedef struct {
92 audio_stream_out_t *stream;
93 qahw_module_t *module;
94 struct listnode list;
95 pthread_mutex_t lock;
Manish Dewangan3ccdea52017-02-13 19:31:54 +053096 qahwi_out_set_param_data_t qahwi_out_get_param_data;
97 qahwi_out_get_param_data_t qahwi_out_set_param_data;
Naresh Tanniruee3499a2017-01-05 14:05:35 +053098 qahwi_out_write_v2_t qahwi_out_write_v2;
Manish Dewanganb8c83a42016-09-23 15:10:48 +053099} qahw_stream_out_t;
100
101typedef struct {
102 audio_stream_in_t *stream;
103 qahw_module_t *module;
104 struct listnode list;
105 pthread_mutex_t lock;
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +0530106 qahwi_in_read_v2_t qahwi_in_read_v2;
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530107} qahw_stream_in_t;
108
109typedef enum {
110 STREAM_DIR_IN,
111 STREAM_DIR_OUT,
112} qahw_stream_direction_t;
113
114static struct listnode qahw_module_list;
115static int qahw_list_count;
116static pthread_mutex_t qahw_module_init_lock = PTHREAD_MUTEX_INITIALIZER;
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +0530117sound_trigger_hw_device_t *st_hw_device = NULL;
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530118
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +0530119
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530120/** Start of internal functions */
121/******************************************************************************/
122
123/* call this function without anylock held */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530124static bool is_valid_qahw_stream_l(void *qahw_stream,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530125 qahw_stream_direction_t dir)
126{
127
128 int is_valid = false;
129 struct listnode *module_node = NULL;
130 struct listnode *stream_node = NULL;
131 struct listnode *list_node = NULL;
132 void *stream = NULL;
133 qahw_module_t *qahw_module = NULL;
134
135 if (qahw_stream == NULL) {
136 ALOGE("%s:: Invalid stream", __func__);
137 goto exit;
138 }
139
140 if ((dir != STREAM_DIR_OUT) && (dir != STREAM_DIR_IN)) {
141 ALOGE("%s:: Invalid stream direction %d", __func__, dir);
142 goto exit;
143 }
144
145 /* go through all the modules and check for valid stream */
146 pthread_mutex_lock(&qahw_module_init_lock);
147 list_for_each(module_node, &qahw_module_list) {
148 qahw_module = node_to_item(module_node, qahw_module_t, module_list);
149 pthread_mutex_lock(&qahw_module->lock);
150 if(dir == STREAM_DIR_OUT)
151 list_node = &qahw_module->out_list;
152 else
153 list_node = &qahw_module->in_list;
154 list_for_each(stream_node, list_node) {
155 if(dir == STREAM_DIR_OUT)
156 stream = (void *)node_to_item(stream_node,
157 qahw_stream_out_t,
158 list);
159 else
160 stream = (void *)node_to_item(stream_node,
161 qahw_stream_in_t,
162 list);
163 if(stream == qahw_stream) {
164 is_valid = true;
165 break;
166 }
167 }
168 pthread_mutex_unlock(&qahw_module->lock);
169 if(is_valid)
170 break;
171 }
172 pthread_mutex_unlock(&qahw_module_init_lock);
173
174exit:
175 return is_valid;
176}
177
178/* call this fucntion with ahw_module_init_lock held*/
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530179static qahw_module_t* get_qahw_module_by_ptr_l(qahw_module_t *qahw_module)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530180{
181 struct listnode *node = NULL;
182 qahw_module_t *module = NULL, *module_temp = NULL;
183
184 if (qahw_module == NULL)
185 goto exit;
186
187 list_for_each(node, &qahw_module_list) {
188 module_temp = node_to_item(node, qahw_module_t, module_list);
189 if (module_temp == qahw_module) {
190 module = module_temp;
191 break;
192 }
193 }
194exit:
195 return module;
196}
197
198/* call this function with qahw_module_init_lock held*/
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530199static qahw_module_t* get_qahw_module_by_name_l(const char *qahw_name)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530200{
201 struct listnode *node = NULL;
202 qahw_module_t *module = NULL, *module_temp = NULL;
203
204 if (qahw_name == NULL)
205 goto exit;
206
207 list_for_each(node, &qahw_module_list) {
208 module_temp = node_to_item(node, qahw_module_t, module_list);
209 if(!strncmp(qahw_name, module_temp->module_name, MAX_MODULE_NAME_LENGTH)) {
210 module = module_temp;
211 break;
212 }
213 }
214exit:
215 return module;
216}
217/* End of of internal functions */
218
219/*
220 * Return the sampling rate in Hz - eg. 44100.
221 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530222uint32_t qahw_out_get_sample_rate_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530223{
224 uint32_t rate = 0;
225 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
226 audio_stream_out_t *out = NULL;
227
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530228 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530229 ALOGV("%s::Invalid out handle %p", __func__, out_handle);
230 goto exit;
231 }
232
233 pthread_mutex_lock(&qahw_stream_out->lock);
234 out = qahw_stream_out->stream;
235 if (out->common.get_sample_rate)
236 rate = out->common.get_sample_rate(&out->common);
237 else
238 ALOGW("%s not supported", __func__);
239 pthread_mutex_unlock(&qahw_stream_out->lock);
240
241exit:
242 return rate;
243}
244
245/*
246 * currently unused - use set_parameters with key
247 * AUDIO_PARAMETER_STREAM_SAMPLING_RATE
248 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530249int qahw_out_set_sample_rate_l(qahw_stream_handle_t *out_handle, uint32_t rate)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530250{
251 int32_t rc = -EINVAL;
252 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
253 audio_stream_out_t *out = NULL;
254
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530255 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530256 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
257 goto exit;
258 }
259 pthread_mutex_lock(&qahw_stream_out->lock);
260 out = qahw_stream_out->stream;
261 if (out->common.set_sample_rate) {
262 rc = out->common.set_sample_rate(&out->common, rate);
263 } else {
264 rc = -ENOSYS;
265 ALOGW("%s not supported", __func__);
266 }
267 pthread_mutex_unlock(&qahw_stream_out->lock);
268exit:
269 return rc;
270}
271
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530272size_t qahw_out_get_buffer_size_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530273{
274 size_t buf_size = 0;
275 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
276 audio_stream_out_t *out = NULL;
277
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530278 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530279 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
280 goto exit;
281 }
282 pthread_mutex_lock(&qahw_stream_out->lock);
283 out = qahw_stream_out->stream;
284 if (out->common.get_buffer_size) {
285 buf_size = out->common.get_buffer_size(&out->common);
286 } else {
287 ALOGW("%s not supported", __func__);
288 }
289 pthread_mutex_unlock(&qahw_stream_out->lock);
290
291exit:
292 return buf_size;
293}
294
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530295audio_channel_mask_t qahw_out_get_channels_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530296{
297 audio_channel_mask_t ch_mask = 0;
298 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
299 audio_stream_out_t *out = NULL;
300
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530301 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530302 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
303 goto exit;
304 }
305 pthread_mutex_lock(&qahw_stream_out->lock);
306 out = qahw_stream_out->stream;
307 if (out->common.get_channels) {
308 ch_mask = out->common.get_channels(&out->common);
309 } else {
310 ALOGW("%s not supported", __func__);
311 }
312 pthread_mutex_unlock(&qahw_stream_out->lock);
313
314exit:
315 return ch_mask;
316}
317
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530318audio_format_t qahw_out_get_format_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530319{
320 audio_format_t format = AUDIO_FORMAT_INVALID;
321 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
322 audio_stream_out_t *out = NULL;
323
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530324 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530325 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
326 goto exit;
327 }
328 pthread_mutex_lock(&qahw_stream_out->lock);
329 out = qahw_stream_out->stream;
330 if (out->common.get_format) {
331 format = out->common.get_format(&out->common);
332 } else {
333 ALOGW("%s not supported", __func__);
334 }
335 pthread_mutex_unlock(&qahw_stream_out->lock);
336
337exit:
338 return format;
339}
340
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530341int qahw_out_standby_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530342{
343 int32_t rc = -EINVAL;
344 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
345 audio_stream_out_t *out = NULL;
346
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530347 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530348 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
349 goto exit;
350 }
351
352 pthread_mutex_lock(&qahw_stream_out->lock);
353 out = qahw_stream_out->stream;
354 if (out->common.standby) {
355 rc = out->common.standby(&out->common);
356 } else {
357 rc = -ENOSYS;
358 ALOGW("%s not supported", __func__);
359 }
360 pthread_mutex_unlock(&qahw_stream_out->lock);
361
362exit:
363 return rc;
364}
365
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530366int qahw_out_set_parameters_l(qahw_stream_handle_t *out_handle, const char *kv_pairs)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530367{
368 int rc = NO_ERROR;
369 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
370 audio_stream_out_t *out = NULL;
371
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530372 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530373 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
374 rc = -EINVAL;
375 goto exit;
376 }
377
378 pthread_mutex_lock(&qahw_stream_out->lock);
379 out = qahw_stream_out->stream;
380 if (out->common.set_parameters) {
381 rc = out->common.set_parameters(&out->common, kv_pairs);
382 } else {
383 rc = -ENOSYS;
384 ALOGW("%s not supported", __func__);
385 }
386 pthread_mutex_unlock(&qahw_stream_out->lock);
387
388exit:
389 return rc;
390}
391
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530392char *qahw_out_get_parameters_l(const qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530393 const char *keys)
394{
395 char *str_param = NULL;
396 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
397 audio_stream_out_t *out = NULL;
398
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530399 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530400 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
401 goto exit;
402 }
403
404 pthread_mutex_lock(&qahw_stream_out->lock);
405 out = qahw_stream_out->stream;
406 if (out->common.get_parameters) {
407 str_param = out->common.get_parameters(&out->common, keys);
408 } else {
409 ALOGW("%s not supported", __func__);
410 }
411 pthread_mutex_unlock(&qahw_stream_out->lock);
412
413exit:
414 return str_param;
415}
416
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530417/* API to get playback stream specific config parameters */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530418int qahw_out_set_param_data_l(qahw_stream_handle_t *out_handle,
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530419 qahw_param_id param_id,
420 qahw_param_payload *payload)
421{
422 int rc = -EINVAL;
423 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
424 audio_stream_out_t *out = NULL;
425
426 if (!payload) {
427 ALOGE("%s::Invalid param", __func__);
428 goto exit;
429 }
430
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530431 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530432 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
433 goto exit;
434 }
435
436 pthread_mutex_lock(&qahw_stream_out->lock);
437 out = qahw_stream_out->stream;
438 if (qahw_stream_out->qahwi_out_set_param_data) {
439 rc = qahw_stream_out->qahwi_out_set_param_data(out, param_id, payload);
440 } else {
441 rc = -ENOSYS;
442 ALOGW("%s not supported", __func__);
443 }
444 pthread_mutex_unlock(&qahw_stream_out->lock);
445
446exit:
447 return rc;
448}
449
450/* API to get playback stream specific config parameters */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530451int qahw_out_get_param_data_l(qahw_stream_handle_t *out_handle,
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530452 qahw_param_id param_id,
453 qahw_param_payload *payload)
454{
455 int rc = -EINVAL;
456 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
457 audio_stream_out_t *out = NULL;
458
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530459 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewangan3ccdea52017-02-13 19:31:54 +0530460 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
461 goto exit;
462 }
463
464 pthread_mutex_lock(&qahw_stream_out->lock);
465 out = qahw_stream_out->stream;
466 if (qahw_stream_out->qahwi_out_get_param_data) {
467 rc = qahw_stream_out->qahwi_out_get_param_data(out, param_id, payload);
468 } else {
469 rc = -ENOSYS;
470 ALOGW("%s not supported", __func__);
471 }
472 pthread_mutex_unlock(&qahw_stream_out->lock);
473
474exit:
475 return rc;
476}
477
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530478uint32_t qahw_out_get_latency_l(const qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530479{
480 uint32_t latency = 0;
481 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
482 audio_stream_out_t *out = NULL;
483
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530484 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530485 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
486 goto exit;
487 }
488
489 pthread_mutex_lock(&qahw_stream_out->lock);
490 out = qahw_stream_out->stream;
491 if (out->get_latency) {
492 latency = out->get_latency(out);
493 } else {
494 ALOGW("%s not supported", __func__);
495 }
496 pthread_mutex_unlock(&qahw_stream_out->lock);
497
498exit:
499 return latency;
500}
501
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530502int qahw_out_set_volume_l(qahw_stream_handle_t *out_handle, float left, float right)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530503{
504 int rc = -EINVAL;
505 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
506 audio_stream_out_t *out = NULL;
507
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530508 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530509 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
510 goto exit;
511 }
512
513 pthread_mutex_lock(&qahw_stream_out->lock);
514 out = qahw_stream_out->stream;
515 if (out->set_volume) {
516 rc = out->set_volume(out, left, right);
517 } else {
518 rc = -ENOSYS;
519 ALOGW("%s not supported", __func__);
520 }
521 pthread_mutex_unlock(&qahw_stream_out->lock);
522
523exit:
524 return rc;
525}
526
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530527ssize_t qahw_out_write_l(qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530528 qahw_out_buffer_t *out_buf)
529{
530 int rc = -EINVAL;
531 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
532 audio_stream_out_t *out = NULL;
533
534 if ((out_buf == NULL) || (out_buf->buffer == NULL)) {
535 ALOGE("%s::Invalid meta data %p", __func__, out_buf);
536 goto exit;
537 }
538
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530539 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530540 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
541 goto exit;
542 }
543
544 /*TBD:: validate other meta data parameters */
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530545 pthread_mutex_lock(&qahw_stream_out->lock);
546 out = qahw_stream_out->stream;
Naresh Tanniruee3499a2017-01-05 14:05:35 +0530547 if (qahw_stream_out->qahwi_out_write_v2) {
548 rc = qahw_stream_out->qahwi_out_write_v2(out, out_buf->buffer,
549 out_buf->bytes, out_buf->timestamp);
550 out_buf->offset = 0;
551 } else if (out->write) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530552 rc = out->write(out, out_buf->buffer, out_buf->bytes);
553 } else {
554 rc = -ENOSYS;
555 ALOGW("%s not supported", __func__);
556 }
557 pthread_mutex_unlock(&qahw_stream_out->lock);
558exit:
559 return rc;
560}
561
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530562int qahw_out_get_render_position_l(const qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530563 uint32_t *dsp_frames)
564{
565 int rc = -EINVAL;
566 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
567 audio_stream_out_t *out = NULL;
568
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530569 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530570 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
571 goto exit;
572 }
573
574 pthread_mutex_lock(&qahw_stream_out->lock);
575 out = qahw_stream_out->stream;
576 if (out->get_render_position) {
577 rc = out->get_render_position(out, dsp_frames);
578 } else {
579 rc = -ENOSYS;
580 ALOGW("%s not supported", __func__);
581 }
582 pthread_mutex_unlock(&qahw_stream_out->lock);
583exit:
584 return rc;
585}
586
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530587int qahw_out_set_callback_l(qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530588 qahw_stream_callback_t callback,
589 void *cookie)
590{
591 /*TBD:load hal func pointer and call */
592 int rc = -EINVAL;
593 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
594 audio_stream_out_t *out = NULL;
595
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530596 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530597 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
598 goto exit;
599 }
600
601 pthread_mutex_lock(&qahw_stream_out->lock);
602 out = qahw_stream_out->stream;
603 if (out->set_callback) {
604 rc = out->set_callback(out, (stream_callback_t)callback, cookie);
605 } else {
606 rc = -ENOSYS;
607 ALOGW("%s not supported", __func__);
608 }
609 pthread_mutex_unlock(&qahw_stream_out->lock);
610
611exit:
612 return rc;
613}
614
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530615int qahw_out_pause_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530616{
617 /*TBD:load hal func pointer and call */
618 int rc = -EINVAL;
619 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
620 audio_stream_out_t *out = NULL;
621
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530622 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530623 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
624 goto exit;
625 }
626
627 pthread_mutex_lock(&qahw_stream_out->lock);
628 out = qahw_stream_out->stream;
629 if (out->pause) {
630 rc = out->pause(out);
631 } else {
632 rc = -ENOSYS;
633 ALOGW("%s not supported", __func__);
634 }
635 pthread_mutex_unlock(&qahw_stream_out->lock);
636
637exit:
638 return rc;
639}
640
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530641int qahw_out_resume_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530642{
643 /*TBD:load hal func pointer and call */
644 int rc = -EINVAL;
645 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
646 audio_stream_out_t *out = NULL;
647
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530648 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530649 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
650 goto exit;
651 }
652
653 pthread_mutex_lock(&qahw_stream_out->lock);
654 out = qahw_stream_out->stream;
655 if (out->resume) {
656 rc = out->resume(out);
657 } else {
658 rc = -ENOSYS;
659 ALOGW("%s not supported", __func__);
660 }
661 pthread_mutex_unlock(&qahw_stream_out->lock);
662
663exit:
664 return rc;
665}
666
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530667int qahw_out_drain_l(qahw_stream_handle_t *out_handle, qahw_drain_type_t type )
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530668{
669 /*TBD:load hal func pointer and call */
670 int rc = -EINVAL;
671 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
672 audio_stream_out_t *out = NULL;
673
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530674 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530675 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
676 goto exit;
677 }
678
679 pthread_mutex_lock(&qahw_stream_out->lock);
680 out = qahw_stream_out->stream;
681 if (out->drain) {
682 rc = out->drain(out,(audio_drain_type_t)type);
683 } else {
684 rc = -ENOSYS;
685 ALOGW("%s not supported", __func__);
686 }
687 pthread_mutex_unlock(&qahw_stream_out->lock);
688
689exit:
690 return rc;
691}
692
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530693int qahw_out_flush_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530694{
695 int rc = -EINVAL;
696 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
697 audio_stream_out_t *out = NULL;
698
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530699 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530700 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
701 goto exit;
702 }
703
704 pthread_mutex_lock(&qahw_stream_out->lock);
705 out = qahw_stream_out->stream;
706 if (out->flush) {
707 rc = out->flush(out);
708 } else {
709 rc = -ENOSYS;
710 ALOGW("%s not supported", __func__);
711 }
712 pthread_mutex_unlock(&qahw_stream_out->lock);
713
714exit:
715 return rc;
716}
717
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530718int qahw_out_get_presentation_position_l(const qahw_stream_handle_t *out_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530719 uint64_t *frames, struct timespec *timestamp)
720{
721 int rc = -EINVAL;
722 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
723 audio_stream_out_t *out = NULL;
724
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530725 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530726 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
727 goto exit;
728 }
729
730 pthread_mutex_lock(&qahw_stream_out->lock);
731 out = qahw_stream_out->stream;
732 if (out->get_presentation_position) {
733 rc = out->get_presentation_position(out, frames, timestamp);
734 } else {
735 rc = -ENOSYS;
736 ALOGW("%s not supported", __func__);
737 }
738 pthread_mutex_unlock(&qahw_stream_out->lock);
739
740exit:
741 return rc;
742}
743
744/* Input stream specific APIs */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530745uint32_t qahw_in_get_sample_rate_l(const qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530746{
747 uint32_t rate = 0;
748 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
749 audio_stream_in_t *in = NULL;
750
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530751 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530752 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
753 goto exit;
754 }
755
756 pthread_mutex_lock(&qahw_stream_in->lock);
757 in = qahw_stream_in->stream;
758 if (in->common.get_sample_rate) {
759 rate = in->common.get_sample_rate(&in->common);
760 } else {
761 ALOGW("%s not supported", __func__);
762 }
763 pthread_mutex_unlock(&qahw_stream_in->lock);
764
765exit:
766 return rate;
767}
768
769/*
770 * currently unused - use set_parameters with key
771 * AUDIO_PARAMETER_STREAM_SAMPLING_RATE
772 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530773int qahw_in_set_sample_rate_l(qahw_stream_handle_t *in_handle, uint32_t rate)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530774{
775 int rc = -EINVAL;
776 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
777 audio_stream_in_t *in = NULL;
778
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530779 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530780 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
781 goto exit;
782 }
783
784 pthread_mutex_lock(&qahw_stream_in->lock);
785 in = qahw_stream_in->stream;
786 if (in->common.set_sample_rate) {
787 rc = in->common.set_sample_rate(&in->common, rate);
788 } else {
789 rc = -ENOSYS;
790 ALOGW("%s not supported", __func__);
791 }
792 pthread_mutex_unlock(&qahw_stream_in->lock);
793
794exit:
795 return rc;
796}
797
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530798size_t qahw_in_get_buffer_size_l(const qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530799{
800 size_t buf_size = 0;
801 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
802 audio_stream_in_t *in = NULL;
803
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530804 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530805 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
806 goto exit;
807 }
808
809 pthread_mutex_lock(&qahw_stream_in->lock);
810 in = qahw_stream_in->stream;
811 if (in->common.get_sample_rate) {
812 buf_size = in->common.get_buffer_size(&in->common);
813 } else {
814 ALOGW("%s not supported", __func__);
815 }
816 pthread_mutex_unlock(&qahw_stream_in->lock);
817
818exit:
819 return buf_size;
820}
821
822
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530823audio_channel_mask_t qahw_in_get_channels_l(const qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530824{
825 audio_channel_mask_t ch_mask = 0;;
826 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
827 audio_stream_in_t *in = NULL;
828
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530829 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530830 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
831 goto exit;
832 }
833
834 pthread_mutex_lock(&qahw_stream_in->lock);
835 in = qahw_stream_in->stream;
836 if (in->common.get_channels) {
837 ch_mask = in->common.get_channels(&in->common);
838 } else {
839 ALOGW("%s not supported", __func__);
840 }
841 pthread_mutex_unlock(&qahw_stream_in->lock);
842
843exit:
844 return ch_mask;
845}
846
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530847audio_format_t qahw_in_get_format_l(const qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530848{
849 audio_format_t format = AUDIO_FORMAT_INVALID;
850 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
851 audio_stream_in_t *in = NULL;
852
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530853 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530854 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
855 goto exit;
856 }
857
858 pthread_mutex_lock(&qahw_stream_in->lock);
859 in = qahw_stream_in->stream;
860 if (in->common.get_format) {
861 format = in->common.get_format(&in->common);
862 } else {
863 ALOGW("%s not supported", __func__);
864 }
865 pthread_mutex_unlock(&qahw_stream_in->lock);
866
867exit:
868 return format;
869}
870
871/*
872 * currently unused - use set_parameters with key
873 * AUDIO_PARAMETER_STREAM_FORMAT
874 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530875int qahw_in_set_format_l(qahw_stream_handle_t *in_handle, audio_format_t format)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530876{
877 int rc = -EINVAL;
878 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
879 audio_stream_in_t *in = NULL;
880
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530881 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530882 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
883 goto exit;
884 }
885
886 pthread_mutex_lock(&qahw_stream_in->lock);
887 in = qahw_stream_in->stream;
888 if (in->common.set_format) {
889 rc = in->common.set_format(&in->common, format);
890 } else {
891 rc = -ENOSYS;
892 ALOGW("%s not supported", __func__);
893 }
894 pthread_mutex_unlock(&qahw_stream_in->lock);
895
896exit:
897 return rc;
898}
899
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530900int qahw_in_standby_l(qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530901{
902 int rc = -EINVAL;
903 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
904 audio_stream_in_t *in = NULL;
905
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530906 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530907 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
908 goto exit;
909 }
910
911 pthread_mutex_lock(&qahw_stream_in->lock);
912 in = qahw_stream_in->stream;
913 if (in->common.standby) {
914 rc = in->common.standby(&in->common);
915 } else {
916 rc = -ENOSYS;
917 ALOGW("%s not supported", __func__);
918 }
919 pthread_mutex_unlock(&qahw_stream_in->lock);
920
921exit:
922 return rc;
923}
924
925/*
926 * set/get audio stream parameters. The function accepts a list of
927 * parameter key value pairs in the form: key1=value1;key2=value2;...
928 *
929 * Some keys are reserved for standard parameters (See AudioParameter class)
930 *
931 * If the implementation does not accept a parameter change while
932 * the output is active but the parameter is acceptable otherwise, it must
933 * return -ENOSYS.
934 *
935 * The audio flinger will put the stream in standby and then change the
936 * parameter value.
937 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530938int qahw_in_set_parameters_l(qahw_stream_handle_t *in_handle, const char *kv_pairs)
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530939{
940 int rc = -EINVAL;
941 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
942 audio_stream_in_t *in = NULL;
943
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530944 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530945 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
946 goto exit;
947 }
948
949 pthread_mutex_lock(&qahw_stream_in->lock);
950 in = qahw_stream_in->stream;
951 if (in->common.set_parameters) {
952 rc = in->common.set_parameters(&in->common, kv_pairs);
953 } else {
954 rc = -ENOSYS;
955 ALOGW("%s not supported", __func__);
956 }
957 pthread_mutex_unlock(&qahw_stream_in->lock);
958exit:
959 return rc;
960}
961
962/*
963 * Returns a pointer to a heap allocated string. The caller is responsible
964 * for freeing the memory for it using free().
965 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530966char * qahw_in_get_parameters_l(const qahw_stream_handle_t *in_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530967 const char *keys)
968{
969 char *str_param = NULL;
970 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
971 audio_stream_in_t *in = NULL;
972
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530973 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530974 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
975 goto exit;
976 }
977
978 pthread_mutex_lock(&qahw_stream_in->lock);
979 in = qahw_stream_in->stream;
980 if (in->common.get_parameters) {
981 str_param = in->common.get_parameters(&in->common, keys);
982 } else {
983 ALOGW("%s not supported", __func__);
984 }
985 pthread_mutex_unlock(&qahw_stream_in->lock);
986
987exit:
988 return str_param;
989}
990
991/*
992 * Read audio buffer in from audio driver. Returns number of bytes read, or a
993 * negative status_t. If at least one frame was read prior to the error,
994 * read should return that byte count and then return an error in the subsequent call.
995 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +0530996ssize_t qahw_in_read_l(qahw_stream_handle_t *in_handle,
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530997 qahw_in_buffer_t *in_buf)
998{
999 int rc = -EINVAL;
1000 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
1001 audio_stream_in_t *in = NULL;
1002
1003 if ((in_buf == NULL) || (in_buf->buffer == NULL)) {
1004 ALOGE("%s::Invalid meta data %p", __func__, in_buf);
1005 goto exit;
1006 }
1007
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301008 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301009 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
1010 goto exit;
1011 }
1012
1013 pthread_mutex_lock(&qahw_stream_in->lock);
1014 in = qahw_stream_in->stream;
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +05301015 if (qahw_stream_in->qahwi_in_read_v2) {
1016 rc = qahw_stream_in->qahwi_in_read_v2(in, in_buf->buffer,
1017 in_buf->bytes, in_buf->timestamp);
1018 in_buf->offset = 0;
1019 } else if (in->read) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301020 rc = in->read(in, in_buf->buffer, in_buf->bytes);
1021 in_buf->offset = 0;
1022 } else {
1023 rc = -ENOSYS;
1024 ALOGW("%s not supported", __func__);
1025 }
1026 pthread_mutex_unlock(&qahw_stream_in->lock);
1027
1028exit:
1029 return rc;
1030}
1031
1032/*
1033 * Return the amount of input frames lost in the audio driver since the
1034 * last call of this function.
1035 * Audio driver is expected to reset the value to 0 and restart counting
1036 * upon returning the current value by this function call.
1037 * Such loss typically occurs when the user space process is blocked
1038 * longer than the capacity of audio driver buffers.
1039 *
1040 * Unit: the number of input audio frames
1041 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301042uint32_t qahw_in_get_input_frames_lost_l(qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301043{
1044 uint32_t rc = 0;
1045 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
1046 audio_stream_in_t *in = NULL;
1047
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301048 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301049 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
1050 goto exit;
1051 }
1052
1053 pthread_mutex_lock(&qahw_stream_in->lock);
1054 in = qahw_stream_in->stream;
1055 if (in->get_input_frames_lost) {
1056 rc = in->get_input_frames_lost(in);
1057 } else {
1058 rc = -ENOSYS;
1059 ALOGW("%s not supported", __func__);
1060 }
1061 pthread_mutex_unlock(&qahw_stream_in->lock);
1062
1063exit:
1064 return rc;
1065}
1066
1067/*
1068 * Return a recent count of the number of audio frames received and
1069 * the clock time associated with that frame count.
1070 *
1071 * frames is the total frame count received. This should be as early in
1072 * the capture pipeline as possible. In general,
1073 * frames should be non-negative and should not go "backwards".
1074 *
1075 * time is the clock MONOTONIC time when frames was measured. In general,
1076 * time should be a positive quantity and should not go "backwards".
1077 *
1078 * The status returned is 0 on success, -ENOSYS if the device is not
1079 * ready/available, or -EINVAL if the arguments are null or otherwise invalid.
1080 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301081int qahw_in_get_capture_position_l(const qahw_stream_handle_t *in_handle __unused,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301082 int64_t *frames __unused, int64_t *time __unused)
1083{
1084 /*TBD:: do we need this*/
1085 return -ENOSYS;
1086}
1087
1088/*
1089 * check to see if the audio hardware interface has been initialized.
1090 * returns 0 on success, -ENODEV on failure.
1091 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301092int qahw_init_check_l(const qahw_module_handle_t *hw_module)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301093{
1094 int rc = -EINVAL;
1095 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1096 qahw_module_t *qahw_module_temp;
1097
1098 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301099 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301100 pthread_mutex_unlock(&qahw_module_init_lock);
1101 if (qahw_module_temp == NULL) {
1102 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1103 goto exit;
1104 }
1105
1106 pthread_mutex_lock(&qahw_module->lock);
1107 if (qahw_module->audio_device->init_check) {
1108 rc = qahw_module->audio_device->init_check(qahw_module->audio_device);
1109 } else {
1110 rc = -ENOSYS;
1111 ALOGW("%s not supported", __func__);
1112 }
1113 pthread_mutex_unlock(&qahw_module->lock);
1114
1115exit:
1116 return rc;
1117}
1118/* set the audio volume of a voice call. Range is between 0.0 and 1.0 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301119int qahw_set_voice_volume_l(qahw_module_handle_t *hw_module, float volume)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301120{
1121 int rc = -EINVAL;
1122 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1123 qahw_module_t *qahw_module_temp;
1124
1125 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301126 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301127 pthread_mutex_unlock(&qahw_module_init_lock);
1128 if (qahw_module_temp == NULL) {
1129 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1130 goto exit;
1131 }
1132
1133 pthread_mutex_lock(&qahw_module->lock);
1134 if (qahw_module->audio_device->set_voice_volume) {
1135 rc = qahw_module->audio_device->set_voice_volume(qahw_module->audio_device,
1136 volume);
1137 } else {
1138 rc = -ENOSYS;
1139 ALOGW("%s not supported", __func__);
1140 }
1141 pthread_mutex_unlock(&qahw_module->lock);
1142
1143exit:
1144 return rc;
1145}
1146
1147/*
1148 * set_mode is called when the audio mode changes. AUDIO_MODE_NORMAL mode
1149 * is for standard audio playback, AUDIO_MODE_RINGTONE when a ringtone is
1150 * playing, and AUDIO_MODE_IN_CALL when a call is in progress.
1151 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301152int qahw_set_mode_l(qahw_module_handle_t *hw_module, audio_mode_t mode)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301153{
1154 int rc = -EINVAL;
1155 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1156 qahw_module_t *qahw_module_temp;
1157
1158 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301159 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301160 pthread_mutex_unlock(&qahw_module_init_lock);
1161 if (qahw_module_temp == NULL) {
1162 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1163 goto exit;
1164 }
1165
1166 pthread_mutex_lock(&qahw_module->lock);
1167 if (qahw_module->audio_device->set_mode) {
1168 rc = qahw_module->audio_device->set_mode(qahw_module->audio_device,
1169 mode);
1170 } else {
1171 rc = -ENOSYS;
1172 ALOGW("%s not supported", __func__);
1173 }
1174 pthread_mutex_unlock(&qahw_module->lock);
1175
1176exit:
1177 return rc;
1178}
1179
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301180int qahw_set_mic_mute_l(qahw_module_handle_t *hw_module, bool state)
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301181{
1182 int rc = -EINVAL;
1183 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1184 qahw_module_t *qahw_module_temp;
1185
1186 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301187 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301188 pthread_mutex_unlock(&qahw_module_init_lock);
1189 if (qahw_module_temp == NULL) {
1190 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1191 goto exit;
1192 }
1193
1194 pthread_mutex_lock(&qahw_module->lock);
1195 if (qahw_module->audio_device->set_mic_mute) {
1196 rc = qahw_module->audio_device->set_mic_mute(qahw_module->audio_device,
1197 state);
1198 } else {
1199 rc = -ENOSYS;
1200 ALOGW("%s not supported", __func__);
1201 }
1202 pthread_mutex_unlock(&qahw_module->lock);
1203
1204exit:
1205 return rc;
1206}
1207
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301208int qahw_get_mic_mute_l(qahw_module_handle_t *hw_module, bool *state)
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301209{
1210 size_t rc = 0;
1211 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1212 qahw_module_t *qahw_module_temp;
1213 audio_hw_device_t *audio_device;
1214
1215 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301216 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301217 pthread_mutex_unlock(&qahw_module_init_lock);
1218 if (qahw_module_temp == NULL) {
1219 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1220 goto exit;
1221 }
1222
1223 pthread_mutex_lock(&qahw_module->lock);
1224 audio_device = qahw_module->audio_device;
1225 if (qahw_module->audio_device->get_mic_mute) {
Dhananjay Kumar23a3bec2017-01-11 18:38:09 +05301226 rc = audio_device->get_mic_mute(qahw_module->audio_device, state);
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301227 } else {
1228 rc = -ENOSYS;
1229 ALOGW("%s not supported", __func__);
1230 }
1231 pthread_mutex_unlock(&qahw_module->lock);
1232
1233exit:
1234 return rc;
1235}
1236
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301237/* set/get global audio parameters */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301238int qahw_set_parameters_l(qahw_module_handle_t *hw_module, const char *kv_pairs)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301239{
1240 int rc = -EINVAL;
1241 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1242 qahw_module_t *qahw_module_temp;
1243 audio_hw_device_t *audio_device;
1244
1245 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301246 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301247 pthread_mutex_unlock(&qahw_module_init_lock);
1248 if (qahw_module_temp == NULL) {
1249 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1250 goto exit;
1251 }
1252
1253 pthread_mutex_lock(&qahw_module->lock);
1254 audio_device = qahw_module->audio_device;
1255 if (qahw_module->audio_device->set_parameters) {
1256 rc = audio_device->set_parameters(qahw_module->audio_device, kv_pairs);
1257 } else {
1258 rc = -ENOSYS;
1259 ALOGW("%s not supported", __func__);
1260 }
1261 pthread_mutex_unlock(&qahw_module->lock);
1262
1263exit:
1264 return rc;
1265}
1266
1267/*
1268 * Returns a pointer to a heap allocated string. The caller is responsible
1269 * for freeing the memory for it using free().
1270 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301271char * qahw_get_parameters_l(const qahw_module_handle_t *hw_module,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301272 const char *keys)
1273{
1274 char *str_param = NULL;
1275 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1276 qahw_module_t *qahw_module_temp;
1277 audio_hw_device_t *audio_device;
1278
1279 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301280 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301281 pthread_mutex_unlock(&qahw_module_init_lock);
1282 if (qahw_module_temp == NULL) {
1283 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1284 goto exit;
1285 }
1286
1287 pthread_mutex_lock(&qahw_module->lock);
1288 audio_device = qahw_module->audio_device;
1289 if (qahw_module->audio_device->get_parameters) {
1290 str_param = audio_device->get_parameters(qahw_module->audio_device, keys);
1291 } else {
1292 ALOGW("%s not supported", __func__);
1293 }
1294 pthread_mutex_unlock(&qahw_module->lock);
1295
1296exit:
1297 return str_param;
1298}
1299
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301300/* Api to implement get parameters based on keyword param_id
1301 * and store data in payload.
1302 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301303int qahw_get_param_data_l(const qahw_module_handle_t *hw_module,
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301304 qahw_param_id param_id,
1305 qahw_param_payload *payload)
1306{
1307 int ret = 0;
1308 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1309 qahw_module_t *qahw_module_temp;
1310
1311 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301312 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301313 pthread_mutex_unlock(&qahw_module_init_lock);
1314 if (qahw_module_temp == NULL) {
1315 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1316 goto exit;
1317 }
1318
1319 pthread_mutex_lock(&qahw_module->lock);
1320
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301321 if (qahw_module->qahwi_get_param_data){
1322 ret = qahw_module->qahwi_get_param_data (qahw_module->audio_device,
1323 param_id, payload);
1324 } else {
1325 ret = -ENOSYS;
1326 ALOGE("%s not supported\n",__func__);
1327 }
1328 pthread_mutex_unlock(&qahw_module->lock);
1329
1330exit:
1331 return ret;
1332}
1333
1334/* Api to implement set parameters based on keyword param_id
1335 * and data present in payload.
1336 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301337int qahw_set_param_data_l(const qahw_module_handle_t *hw_module,
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301338 qahw_param_id param_id,
1339 qahw_param_payload *payload)
1340{
1341 int ret = 0;
1342 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1343 qahw_module_t *qahw_module_temp;
1344
1345 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301346 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301347 pthread_mutex_unlock(&qahw_module_init_lock);
1348 if (qahw_module_temp == NULL) {
1349 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1350 goto exit;
1351 }
1352
1353 pthread_mutex_lock(&qahw_module->lock);
1354
1355 if (qahw_module->qahwi_set_param_data){
1356 ret = qahw_module->qahwi_set_param_data (qahw_module->audio_device,
1357 param_id, payload);
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301358 } else {
1359 ret = -ENOSYS;
1360 ALOGE("%s not supported\n",__func__);
1361 }
1362 pthread_mutex_unlock(&qahw_module->lock);
1363
1364exit:
1365 return ret;
1366}
1367
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301368/* Creates an audio patch between several source and sink ports.
1369 * The handle is allocated by the HAL and should be unique for this
1370 * audio HAL module.
1371 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301372int qahw_create_audio_patch_l(qahw_module_handle_t *hw_module,
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301373 unsigned int num_sources,
1374 const struct audio_port_config *sources,
1375 unsigned int num_sinks,
1376 const struct audio_port_config *sinks,
1377 audio_patch_handle_t *handle)
1378{
1379 int ret = 0;
1380 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1381 qahw_module_t *qahw_module_temp;
1382
1383 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301384 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301385 pthread_mutex_unlock(&qahw_module_init_lock);
1386 if (qahw_module_temp == NULL) {
1387 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1388 goto exit;
1389 }
1390
1391 pthread_mutex_lock(&qahw_module->lock);
1392 if (qahw_module->audio_device->create_audio_patch) {
1393 ret = qahw_module->audio_device->create_audio_patch(
1394 qahw_module->audio_device,
1395 num_sources,
1396 sources,
1397 num_sinks,
1398 sinks,
1399 handle);
1400 } else {
1401 ret = -ENOSYS;
1402 ALOGE("%s not supported\n",__func__);
1403 }
1404 pthread_mutex_unlock(&qahw_module->lock);
1405
1406exit:
1407 return ret;
1408}
1409
1410/* Release an audio patch */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301411int qahw_release_audio_patch_l(qahw_module_handle_t *hw_module,
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301412 audio_patch_handle_t handle)
1413{
1414 int ret = 0;
1415 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1416 qahw_module_t *qahw_module_temp;
1417
1418 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301419 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301420 pthread_mutex_unlock(&qahw_module_init_lock);
1421 if (qahw_module_temp == NULL) {
1422 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1423 goto exit;
1424 }
1425
1426 pthread_mutex_lock(&qahw_module->lock);
1427 if (qahw_module->audio_device->release_audio_patch) {
1428 ret = qahw_module->audio_device->release_audio_patch(
1429 qahw_module->audio_device,
1430 handle);
1431 } else {
1432 ret = -ENOSYS;
1433 ALOGE("%s not supported\n",__func__);
1434 }
1435 pthread_mutex_unlock(&qahw_module->lock);
1436
1437exit:
1438 return ret;
1439}
1440
1441/* Fills the list of supported attributes for a given audio port.
1442 * As input, "port" contains the information (type, role, address etc...)
1443 * needed by the HAL to identify the port.
1444 * As output, "port" contains possible attributes (sampling rates, formats,
1445 * channel masks, gain controllers...) for this port.
1446 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301447int qahw_get_audio_port_l(qahw_module_handle_t *hw_module,
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301448 struct audio_port *port)
1449{
1450 int ret = 0;
1451 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1452 qahw_module_t *qahw_module_temp;
1453
1454 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301455 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301456 pthread_mutex_unlock(&qahw_module_init_lock);
1457 if (qahw_module_temp == NULL) {
1458 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1459 goto exit;
1460 }
1461
1462 pthread_mutex_lock(&qahw_module->lock);
1463 if (qahw_module->audio_device->get_audio_port) {
1464 ret = qahw_module->audio_device->get_audio_port(
1465 qahw_module->audio_device,
1466 port);
1467 } else {
1468 ret = -ENOSYS;
1469 ALOGE("%s not supported\n",__func__);
1470 }
1471 pthread_mutex_unlock(&qahw_module->lock);
1472
1473exit:
1474 return ret;
1475}
1476
1477/* Set audio port configuration */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301478int qahw_set_audio_port_config_l(qahw_module_handle_t *hw_module,
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301479 const struct audio_port_config *config)
1480{
1481 int ret = 0;
1482 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1483 qahw_module_t *qahw_module_temp;
1484
1485 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301486 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301487 pthread_mutex_unlock(&qahw_module_init_lock);
1488 if (qahw_module_temp == NULL) {
1489 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1490 goto exit;
1491 }
1492
1493 pthread_mutex_lock(&qahw_module->lock);
1494 if (qahw_module->audio_device->set_audio_port_config) {
1495 ret = qahw_module->audio_device->set_audio_port_config(
1496 qahw_module->audio_device,
1497 config);
1498 } else {
1499 ret = -ENOSYS;
1500 ALOGE("%s not supported\n",__func__);
1501 }
1502 pthread_mutex_unlock(&qahw_module->lock);
1503
1504exit:
1505 return ret;
1506}
1507
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301508/* Returns audio input buffer size according to parameters passed or
1509 * 0 if one of the parameters is not supported.
1510 * See also get_buffer_size which is for a particular stream.
1511 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301512size_t qahw_get_input_buffer_size_l(const qahw_module_handle_t *hw_module,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301513 const struct audio_config *config)
1514{
1515 size_t rc = 0;
1516 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1517 qahw_module_t *qahw_module_temp;
1518 audio_hw_device_t *audio_device;
1519
1520 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301521 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301522 pthread_mutex_unlock(&qahw_module_init_lock);
1523 if (qahw_module_temp == NULL) {
1524 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1525 goto exit;
1526 }
1527
1528 pthread_mutex_lock(&qahw_module->lock);
1529 audio_device = qahw_module->audio_device;
1530 if (qahw_module->audio_device->get_input_buffer_size) {
1531 rc = audio_device->get_input_buffer_size(qahw_module->audio_device,
1532 config);
1533 } else {
1534 rc = -ENOSYS;
1535 ALOGW("%s not supported", __func__);
1536 }
1537 pthread_mutex_unlock(&qahw_module->lock);
1538
1539exit:
1540 return rc;
1541}
1542
1543/*
1544 * This method creates and opens the audio hardware output stream.
1545 * The "address" parameter qualifies the "devices" audio device type if needed.
1546 * The format format depends on the device type:
1547 * - Bluetooth devices use the MAC address of the device in the form "00:11:22:AA:BB:CC"
1548 * - USB devices use the ALSA card and device numbers in the form "card=X;device=Y"
1549 * - Other devices may use a number or any other string.
1550 */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301551int qahw_open_output_stream_l(qahw_module_handle_t *hw_module,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301552 audio_io_handle_t handle,
1553 audio_devices_t devices,
1554 audio_output_flags_t flags,
1555 struct audio_config *config,
1556 qahw_stream_handle_t **out_handle,
1557 const char *address)
1558{
1559 int rc = -EINVAL;
1560 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1561 qahw_module_t *qahw_module_temp = NULL;
1562 audio_hw_device_t *audio_device = NULL;
1563 qahw_stream_out_t *qahw_stream_out = NULL;
1564
1565 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301566 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301567 pthread_mutex_unlock(&qahw_module_init_lock);
1568 if (qahw_module_temp == NULL) {
1569 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1570 return rc;
1571 }
1572
1573 pthread_mutex_lock(&qahw_module->lock);
1574 audio_device = qahw_module->audio_device;
1575 qahw_stream_out = (qahw_stream_out_t *)calloc(1, sizeof(qahw_stream_out_t));
1576 if (qahw_stream_out == NULL) {
1577 ALOGE("%s:: calloc failed for out stream_out_t",__func__);
1578 rc = -ENOMEM;
1579 goto exit;
1580 }
1581
1582 rc = audio_device->open_output_stream(audio_device,
1583 handle,
1584 devices,
1585 flags,
1586 config,
1587 &qahw_stream_out->stream,
1588 address);
1589 if (rc) {
1590 ALOGE("%s::open output stream failed %d",__func__, rc);
1591 free(qahw_stream_out);
1592 } else {
1593 qahw_stream_out->module = hw_module;
1594 *out_handle = (void *)qahw_stream_out;
1595 pthread_mutex_init(&qahw_stream_out->lock, (const pthread_mutexattr_t *)NULL);
1596 list_add_tail(&qahw_module->out_list, &qahw_stream_out->list);
Manish Dewangan3ccdea52017-02-13 19:31:54 +05301597
1598 /* clear any existing errors */
1599 const char *error;
1600 dlerror();
1601 qahw_stream_out->qahwi_out_get_param_data = (qahwi_out_get_param_data_t)
1602 dlsym(qahw_module->module->dso,
1603 "qahwi_out_get_param_data");
1604 if ((error = dlerror()) != NULL) {
1605 ALOGI("%s: dlsym error %s for qahwi_out_get_param_data",
1606 __func__, error);
1607 qahw_stream_out->qahwi_out_get_param_data = NULL;
1608 }
1609
1610 dlerror();
1611 qahw_stream_out->qahwi_out_set_param_data = (qahwi_out_set_param_data_t)
1612 dlsym(qahw_module->module->dso,
1613 "qahwi_out_set_param_data");
1614 if ((error = dlerror()) != NULL) {
1615 ALOGI("%s: dlsym error %s for qahwi_out_set_param_data",
1616 __func__, error);
1617 qahw_stream_out->qahwi_out_set_param_data = NULL;
1618 }
1619}
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301620
Naresh Tanniruee3499a2017-01-05 14:05:35 +05301621 /* dlsym qahwi_out_write_v2 */
1622 if (!rc) {
1623 const char *error;
1624
1625 /* clear any existing errors */
1626 dlerror();
1627 qahw_stream_out->qahwi_out_write_v2 = (qahwi_out_write_v2_t)dlsym(qahw_module->module->dso, "qahwi_out_write_v2");
1628 if ((error = dlerror()) != NULL) {
1629 ALOGI("%s: dlsym error %s for qahwi_out_write_v2", __func__, error);
1630 qahw_stream_out->qahwi_out_write_v2 = NULL;
1631 }
1632 }
1633
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301634exit:
1635 pthread_mutex_unlock(&qahw_module->lock);
1636 return rc;
1637}
1638
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301639int qahw_close_output_stream_l(qahw_stream_handle_t *out_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301640{
1641
1642 int rc = 0;
1643 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
1644 qahw_module_t *qahw_module = NULL;
1645 audio_hw_device_t *audio_device = NULL;
1646
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301647 if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301648 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
1649 rc = -EINVAL;
1650 goto exit;
1651 }
1652
1653 ALOGV("%s::calling device close_output_stream %p", __func__, out_handle);
1654 pthread_mutex_lock(&qahw_stream_out->lock);
1655 qahw_module = qahw_stream_out->module;
1656 audio_device = qahw_module->audio_device;
1657 audio_device->close_output_stream(audio_device,
1658 qahw_stream_out->stream);
1659
1660 pthread_mutex_lock(&qahw_module->lock);
1661 list_remove(&qahw_stream_out->list);
1662 pthread_mutex_unlock(&qahw_module->lock);
1663
1664 pthread_mutex_unlock(&qahw_stream_out->lock);
1665
1666 pthread_mutex_destroy(&qahw_stream_out->lock);
1667 free(qahw_stream_out);
1668
1669exit:
1670 return rc;
1671}
1672
1673/* This method creates and opens the audio hardware input stream */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301674int qahw_open_input_stream_l(qahw_module_handle_t *hw_module,
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301675 audio_io_handle_t handle,
1676 audio_devices_t devices,
1677 struct audio_config *config,
1678 qahw_stream_handle_t **in_handle,
1679 audio_input_flags_t flags,
1680 const char *address,
1681 audio_source_t source)
1682{
1683 int rc = -EINVAL;
1684 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1685 qahw_module_t *qahw_module_temp = NULL;
1686 audio_hw_device_t *audio_device = NULL;
1687 qahw_stream_in_t *qahw_stream_in = NULL;
1688
1689 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301690 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301691 pthread_mutex_unlock(&qahw_module_init_lock);
1692 if (qahw_module_temp == NULL) {
1693 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1694 return rc;
1695 }
1696
1697 pthread_mutex_lock(&qahw_module->lock);
1698 audio_device = qahw_module->audio_device;
1699 qahw_stream_in = (qahw_stream_in_t *)calloc(1, sizeof(qahw_stream_in_t));
1700 if (qahw_stream_in == NULL) {
1701 ALOGE("%s:: calloc failed for in stream_in_t",__func__);
1702 rc = -ENOMEM;
1703 goto exit;
1704 }
1705
1706 rc = audio_device->open_input_stream(audio_device,
1707 handle,
1708 devices,
1709 config,
1710 &qahw_stream_in->stream,
1711 flags,
1712 address,
1713 source);
1714 if (rc) {
1715 ALOGE("%s::open input stream failed %d",__func__, rc);
1716 free(qahw_stream_in);
1717 } else {
1718 qahw_stream_in->module = hw_module;
1719 *in_handle = (void *)qahw_stream_in;
1720 pthread_mutex_init(&qahw_stream_in->lock, (const pthread_mutexattr_t *)NULL);
1721 list_add_tail(&qahw_module->in_list, &qahw_stream_in->list);
1722 }
1723
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +05301724 /* dlsym qahwi_in_read_v2 if timestamp flag is used */
1725 if (!rc && (flags & QAHW_INPUT_FLAG_TIMESTAMP)) {
1726 const char *error;
1727
1728 /* clear any existing errors */
1729 dlerror();
1730 qahw_stream_in->qahwi_in_read_v2 = (qahwi_in_read_v2_t)
1731 dlsym(qahw_module->module->dso, "qahwi_in_read_v2");
1732 if ((error = dlerror()) != NULL) {
1733 ALOGI("%s: dlsym error %s for qahwi_in_read_v2", __func__, error);
1734 qahw_stream_in->qahwi_in_read_v2 = NULL;
1735 }
1736 }
1737
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301738exit:
1739 pthread_mutex_unlock(&qahw_module->lock);
1740 return rc;
1741}
1742
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301743int qahw_close_input_stream_l(qahw_stream_handle_t *in_handle)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301744{
1745 int rc = 0;
1746 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
1747 qahw_module_t *qahw_module = NULL;
1748 audio_hw_device_t *audio_device = NULL;
1749
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301750 if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301751 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
1752 rc = -EINVAL;
1753 goto exit;
1754 }
1755
1756 ALOGV("%s:: calling device close_input_stream %p", __func__, in_handle);
1757 pthread_mutex_lock(&qahw_stream_in->lock);
1758 qahw_module = qahw_stream_in->module;
1759 audio_device = qahw_module->audio_device;
1760 audio_device->close_input_stream(audio_device,
1761 qahw_stream_in->stream);
1762
1763 pthread_mutex_lock(&qahw_module->lock);
1764 list_remove(&qahw_stream_in->list);
1765 pthread_mutex_unlock(&qahw_module->lock);
1766
1767 pthread_mutex_unlock(&qahw_stream_in->lock);
1768
1769 pthread_mutex_destroy(&qahw_stream_in->lock);
1770 free(qahw_stream_in);
1771
1772exit:
1773 return rc;
1774}
1775
1776/*returns current QTI HAL verison */
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301777int qahw_get_version_l() {
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301778 return QAHW_MODULE_API_VERSION_CURRENT;
1779}
1780
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +05301781/* Load AHAL module to run audio and sva concurrency */
1782static void load_st_hal()
1783{
1784#ifdef SVA_AUDIO_CONC
1785 int rc = -EINVAL;
1786 const hw_module_t* module = NULL;
1787
1788 rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, "primary", &module);
1789 if (rc) {
1790 ALOGE("%s: AHAL Loading failed %d", __func__, rc);
1791 goto error;
1792 }
1793
1794 rc = sound_trigger_hw_device_open(module, &st_hw_device);
1795 if (rc) {
1796 ALOGE("%s: AHAL Device open failed %d", __func__, rc);
1797 st_hw_device = NULL;
1798 }
1799error:
1800 return;
1801#else
1802 return;
1803#endif /*SVA_AUDIO_CONC*/
1804}
1805
1806static void unload_st_hal()
1807{
1808#ifdef SVA_AUDIO_CONC
1809 if (st_hw_device == NULL) {
1810 ALOGE("%s: audio device is NULL",__func__);
1811 return;
1812 }
1813 sound_trigger_hw_device_close(st_hw_device);
1814 st_hw_device = NULL;
1815#else
1816 return;
1817#endif /*SVA_AUDIO_CONC*/
1818}
1819
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301820/* convenience API for opening and closing an audio HAL module */
1821
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301822qahw_module_handle_t *qahw_load_module_l(const char *hw_module_id)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301823{
1824 int rc = -EINVAL;
1825 qahw_module_handle_t *qahw_mod_handle = NULL;
1826 qahw_module_t *qahw_module = NULL;
1827 char *ahal_name = NULL;
1828 const hw_module_t* module = NULL;
1829 audio_hw_device_t* audio_device = NULL;
1830
1831 if (hw_module_id == NULL) {
1832 ALOGE("%s::module id is NULL",__func__);
1833 goto exit;
1834 }
1835
1836 if (!strcmp(hw_module_id, QAHW_MODULE_ID_PRIMARY)) {
1837 ahal_name = "primary";
1838 } else if (!strcmp(hw_module_id, QAHW_MODULE_ID_A2DP)) {
1839 ahal_name = "a2dp";
1840 } else if (!strcmp(hw_module_id, QAHW_MODULE_ID_USB)) {
1841 ahal_name = "usb";
1842 } else {
1843 ALOGE("%s::Invalid Module id %s", __func__, hw_module_id);
1844 goto exit;
1845 }
1846
1847 /* return exiting module ptr if already loaded */
1848 pthread_mutex_lock(&qahw_module_init_lock);
1849 if (qahw_list_count > 0) {
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301850 qahw_module = get_qahw_module_by_name_l(hw_module_id);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301851 if(qahw_module != NULL) {
1852 qahw_mod_handle = (void *)qahw_module;
1853 pthread_mutex_lock(&qahw_module->lock);
1854 qahw_module->ref_count++;
1855 pthread_mutex_unlock(&qahw_module->lock);
1856 goto error_exit;
1857 }
1858 }
1859
1860 rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, ahal_name, &module);
1861 if(rc) {
1862 ALOGE("%s::HAL Loading failed %d", __func__, rc);
1863 goto error_exit;
1864 }
1865
1866 rc = audio_hw_device_open(module, &audio_device);
1867 if(rc) {
1868 ALOGE("%s::HAL Device open failed %d", __func__, rc);
1869 goto error_exit;
1870 }
1871
1872 qahw_module = (qahw_module_t *)calloc(1, sizeof(qahw_module_t));
1873 if(qahw_module == NULL) {
1874 ALOGE("%s::calloc failed", __func__);
1875 audio_hw_device_close(audio_device);
1876 goto error_exit;
1877 }
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +05301878 qahw_module->module = module;
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301879 ALOGD("%s::Loaded HAL %s module %p", __func__, ahal_name, qahw_module);
1880
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301881 qahw_module->qahwi_get_param_data = (qahwi_get_param_data_t) dlsym (module->dso,
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301882 "qahwi_get_param_data");
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301883 if (!qahw_module->qahwi_get_param_data)
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301884 ALOGD("%s::qahwi_get_param_data api is not defined\n",__func__);
1885
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301886 qahw_module->qahwi_set_param_data = (qahwi_set_param_data_t) dlsym (module->dso,
1887 "qahwi_set_param_data");
1888 if (!qahw_module->qahwi_set_param_data)
1889 ALOGD("%s::qahwi_set_param_data api is not defined\n",__func__);
1890
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301891 if (!qahw_list_count)
1892 list_init(&qahw_module_list);
1893 qahw_list_count++;
1894
1895 pthread_mutex_init(&qahw_module->lock, (const pthread_mutexattr_t *) NULL);
1896 pthread_mutex_lock(&qahw_module->lock);
1897 qahw_module->ref_count++;
1898 pthread_mutex_unlock(&qahw_module->lock);
1899
1900 list_init(&qahw_module->out_list);
1901 list_init(&qahw_module->in_list);
1902
1903 /* update qahw_module */
1904 qahw_module->audio_device = audio_device;
1905 strlcpy(&qahw_module->module_name[0], hw_module_id, MAX_MODULE_NAME_LENGTH);
1906
1907 qahw_mod_handle = (void *)qahw_module;
1908
1909 /* Add module list to global module list */
1910 list_add_tail(&qahw_module_list, &qahw_module->module_list);
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +05301911 load_st_hal();
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301912
1913error_exit:
1914 pthread_mutex_unlock(&qahw_module_init_lock);
1915
1916exit:
1917 return qahw_mod_handle;
1918}
1919
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301920int qahw_unload_module_l(qahw_module_handle_t *hw_module)
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301921{
1922 int rc = -EINVAL;
1923 bool is_empty = false;
1924 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1925 qahw_module_t *qahw_module_temp = NULL;
1926
1927 /* close HW device if its valid and all the streams on
1928 * it is closed
1929 */
1930 pthread_mutex_lock(&qahw_module_init_lock);
Sidipotu Ashok404f26d2017-10-10 22:27:51 +05301931 qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301932 if (qahw_module_temp == NULL) {
1933 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1934 goto error_exit;
1935 }
1936
1937 pthread_mutex_lock(&qahw_module->lock);
1938 qahw_module->ref_count--;
1939 if (qahw_module->ref_count > 0) {
1940 rc = 0;
1941 ALOGE("%s:: skipping module unload of %p count %d", __func__,
1942 qahw_module,
1943 qahw_module->ref_count);
1944 pthread_mutex_unlock(&qahw_module->lock);
1945 goto error_exit;
1946 }
1947
1948 is_empty = (list_empty(&qahw_module->out_list) &&
1949 list_empty(&qahw_module->in_list));
1950 if (is_empty) {
1951 rc = audio_hw_device_close(qahw_module->audio_device);
1952 if(rc) {
1953 ALOGE("%s::HAL Device close failed Error %d Module %p",__func__,
1954 rc, qahw_module);
1955 rc = 0;
1956 }
1957 qahw_list_count--;
1958 list_remove(&qahw_module->module_list);
1959 pthread_mutex_unlock(&qahw_module->lock);
1960 pthread_mutex_destroy(&qahw_module->lock);
1961 free(qahw_module);
1962 } else {
1963 pthread_mutex_unlock(&qahw_module->lock);
1964 ALOGE("%s::failed as all the streams on this module"
1965 "is not closed", __func__);
1966 rc = -EINVAL;
1967 }
Dhanalakshmi Siddani7764e3f2018-03-05 19:57:06 +05301968 unload_st_hal();
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301969
1970error_exit:
1971 pthread_mutex_unlock(&qahw_module_init_lock);
1972
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301973 return rc;
1974}
1975
1976__END_DECLS