blob: 393dba9172ee03fcafb1a38310441bec8ca13f60 [file] [log] [blame]
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301/*
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05302* Copyright (c) 2016-2017, 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>
40#include "qahw_api.h"
41
42#define NO_ERROR 0
43#define MAX_MODULE_NAME_LENGTH 100
44
45/*
46 * The current HAL API version.
47 */
48#define QAHW_MODULE_API_VERSION_CURRENT QAHW_MODULE_API_VERSION_0_0
49
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +053050typedef uint64_t (*qahwi_in_read_v2_t)(audio_stream_in_t *in, void* buffer,
Dhananjay Kumar23a3bec2017-01-11 18:38:09 +053051 size_t bytes, int64_t *timestamp);
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +053052
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +053053typedef int (*qahwi_get_param_data_t) (const audio_hw_device_t *,
54 qahw_param_id, qahw_param_payload *);
55
56typedef int (*qahwi_set_param_data_t) (audio_hw_device_t *,
57 qahw_param_id, qahw_param_payload *);
58
Manish Dewanganb8c83a42016-09-23 15:10:48 +053059typedef struct {
60 audio_hw_device_t *audio_device;
61 char module_name[MAX_MODULE_NAME_LENGTH];
62 struct listnode module_list;
63 struct listnode in_list;
64 struct listnode out_list;
65 pthread_mutex_t lock;
66 uint32_t ref_count;
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +053067 const hw_module_t* module;
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +053068 qahwi_get_param_data_t qahwi_get_param_data;
69 qahwi_set_param_data_t qahwi_set_param_data;
Manish Dewanganb8c83a42016-09-23 15:10:48 +053070} qahw_module_t;
71
72typedef struct {
73 qahw_module_t *module;
74 struct listnode module_list;
75 pthread_mutex_t lock;
76} qahw_module_instances_t;
77
78typedef struct {
79 audio_stream_out_t *stream;
80 qahw_module_t *module;
81 struct listnode list;
82 pthread_mutex_t lock;
83} qahw_stream_out_t;
84
85typedef struct {
86 audio_stream_in_t *stream;
87 qahw_module_t *module;
88 struct listnode list;
89 pthread_mutex_t lock;
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +053090 qahwi_in_read_v2_t qahwi_in_read_v2;
Manish Dewanganb8c83a42016-09-23 15:10:48 +053091} qahw_stream_in_t;
92
93typedef enum {
94 STREAM_DIR_IN,
95 STREAM_DIR_OUT,
96} qahw_stream_direction_t;
97
98static struct listnode qahw_module_list;
99static int qahw_list_count;
100static pthread_mutex_t qahw_module_init_lock = PTHREAD_MUTEX_INITIALIZER;
101
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +0530102
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530103/** Start of internal functions */
104/******************************************************************************/
105
106/* call this function without anylock held */
107static bool is_valid_qahw_stream(void *qahw_stream,
108 qahw_stream_direction_t dir)
109{
110
111 int is_valid = false;
112 struct listnode *module_node = NULL;
113 struct listnode *stream_node = NULL;
114 struct listnode *list_node = NULL;
115 void *stream = NULL;
116 qahw_module_t *qahw_module = NULL;
117
118 if (qahw_stream == NULL) {
119 ALOGE("%s:: Invalid stream", __func__);
120 goto exit;
121 }
122
123 if ((dir != STREAM_DIR_OUT) && (dir != STREAM_DIR_IN)) {
124 ALOGE("%s:: Invalid stream direction %d", __func__, dir);
125 goto exit;
126 }
127
128 /* go through all the modules and check for valid stream */
129 pthread_mutex_lock(&qahw_module_init_lock);
130 list_for_each(module_node, &qahw_module_list) {
131 qahw_module = node_to_item(module_node, qahw_module_t, module_list);
132 pthread_mutex_lock(&qahw_module->lock);
133 if(dir == STREAM_DIR_OUT)
134 list_node = &qahw_module->out_list;
135 else
136 list_node = &qahw_module->in_list;
137 list_for_each(stream_node, list_node) {
138 if(dir == STREAM_DIR_OUT)
139 stream = (void *)node_to_item(stream_node,
140 qahw_stream_out_t,
141 list);
142 else
143 stream = (void *)node_to_item(stream_node,
144 qahw_stream_in_t,
145 list);
146 if(stream == qahw_stream) {
147 is_valid = true;
148 break;
149 }
150 }
151 pthread_mutex_unlock(&qahw_module->lock);
152 if(is_valid)
153 break;
154 }
155 pthread_mutex_unlock(&qahw_module_init_lock);
156
157exit:
158 return is_valid;
159}
160
161/* call this fucntion with ahw_module_init_lock held*/
162static qahw_module_t* get_qahw_module_by_ptr(qahw_module_t *qahw_module)
163{
164 struct listnode *node = NULL;
165 qahw_module_t *module = NULL, *module_temp = NULL;
166
167 if (qahw_module == NULL)
168 goto exit;
169
170 list_for_each(node, &qahw_module_list) {
171 module_temp = node_to_item(node, qahw_module_t, module_list);
172 if (module_temp == qahw_module) {
173 module = module_temp;
174 break;
175 }
176 }
177exit:
178 return module;
179}
180
181/* call this function with qahw_module_init_lock held*/
182static qahw_module_t* get_qahw_module_by_name(const char *qahw_name)
183{
184 struct listnode *node = NULL;
185 qahw_module_t *module = NULL, *module_temp = NULL;
186
187 if (qahw_name == NULL)
188 goto exit;
189
190 list_for_each(node, &qahw_module_list) {
191 module_temp = node_to_item(node, qahw_module_t, module_list);
192 if(!strncmp(qahw_name, module_temp->module_name, MAX_MODULE_NAME_LENGTH)) {
193 module = module_temp;
194 break;
195 }
196 }
197exit:
198 return module;
199}
200/* End of of internal functions */
201
202/*
203 * Return the sampling rate in Hz - eg. 44100.
204 */
205uint32_t qahw_out_get_sample_rate(const qahw_stream_handle_t *out_handle)
206{
207 uint32_t rate = 0;
208 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
209 audio_stream_out_t *out = NULL;
210
211 if (!is_valid_qahw_stream((void *)qahw_stream_out, STREAM_DIR_OUT)) {
212 ALOGV("%s::Invalid out handle %p", __func__, out_handle);
213 goto exit;
214 }
215
216 pthread_mutex_lock(&qahw_stream_out->lock);
217 out = qahw_stream_out->stream;
218 if (out->common.get_sample_rate)
219 rate = out->common.get_sample_rate(&out->common);
220 else
221 ALOGW("%s not supported", __func__);
222 pthread_mutex_unlock(&qahw_stream_out->lock);
223
224exit:
225 return rate;
226}
227
228/*
229 * currently unused - use set_parameters with key
230 * AUDIO_PARAMETER_STREAM_SAMPLING_RATE
231 */
232int qahw_out_set_sample_rate(qahw_stream_handle_t *out_handle, uint32_t rate)
233{
234 int32_t rc = -EINVAL;
235 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
236 audio_stream_out_t *out = NULL;
237
238 if (!is_valid_qahw_stream((void *)qahw_stream_out, STREAM_DIR_OUT)) {
239 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
240 goto exit;
241 }
242 pthread_mutex_lock(&qahw_stream_out->lock);
243 out = qahw_stream_out->stream;
244 if (out->common.set_sample_rate) {
245 rc = out->common.set_sample_rate(&out->common, rate);
246 } else {
247 rc = -ENOSYS;
248 ALOGW("%s not supported", __func__);
249 }
250 pthread_mutex_unlock(&qahw_stream_out->lock);
251exit:
252 return rc;
253}
254
255size_t qahw_out_get_buffer_size(const qahw_stream_handle_t *out_handle)
256{
257 size_t buf_size = 0;
258 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
259 audio_stream_out_t *out = NULL;
260
261 if (!is_valid_qahw_stream((void *)qahw_stream_out, STREAM_DIR_OUT)) {
262 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
263 goto exit;
264 }
265 pthread_mutex_lock(&qahw_stream_out->lock);
266 out = qahw_stream_out->stream;
267 if (out->common.get_buffer_size) {
268 buf_size = out->common.get_buffer_size(&out->common);
269 } else {
270 ALOGW("%s not supported", __func__);
271 }
272 pthread_mutex_unlock(&qahw_stream_out->lock);
273
274exit:
275 return buf_size;
276}
277
278audio_channel_mask_t qahw_out_get_channels(const qahw_stream_handle_t *out_handle)
279{
280 audio_channel_mask_t ch_mask = 0;
281 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
282 audio_stream_out_t *out = NULL;
283
284 if (!is_valid_qahw_stream((void *)qahw_stream_out, STREAM_DIR_OUT)) {
285 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
286 goto exit;
287 }
288 pthread_mutex_lock(&qahw_stream_out->lock);
289 out = qahw_stream_out->stream;
290 if (out->common.get_channels) {
291 ch_mask = out->common.get_channels(&out->common);
292 } else {
293 ALOGW("%s not supported", __func__);
294 }
295 pthread_mutex_unlock(&qahw_stream_out->lock);
296
297exit:
298 return ch_mask;
299}
300
301audio_format_t qahw_out_get_format(const qahw_stream_handle_t *out_handle)
302{
303 audio_format_t format = AUDIO_FORMAT_INVALID;
304 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
305 audio_stream_out_t *out = NULL;
306
307 if (!is_valid_qahw_stream((void *)qahw_stream_out, STREAM_DIR_OUT)) {
308 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
309 goto exit;
310 }
311 pthread_mutex_lock(&qahw_stream_out->lock);
312 out = qahw_stream_out->stream;
313 if (out->common.get_format) {
314 format = out->common.get_format(&out->common);
315 } else {
316 ALOGW("%s not supported", __func__);
317 }
318 pthread_mutex_unlock(&qahw_stream_out->lock);
319
320exit:
321 return format;
322}
323
324int qahw_out_standby(qahw_stream_handle_t *out_handle)
325{
326 int32_t rc = -EINVAL;
327 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
328 audio_stream_out_t *out = NULL;
329
330 if (!is_valid_qahw_stream((void *)qahw_stream_out, STREAM_DIR_OUT)) {
331 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
332 goto exit;
333 }
334
335 pthread_mutex_lock(&qahw_stream_out->lock);
336 out = qahw_stream_out->stream;
337 if (out->common.standby) {
338 rc = out->common.standby(&out->common);
339 } else {
340 rc = -ENOSYS;
341 ALOGW("%s not supported", __func__);
342 }
343 pthread_mutex_unlock(&qahw_stream_out->lock);
344
345exit:
346 return rc;
347}
348
349int qahw_out_set_parameters(qahw_stream_handle_t *out_handle, const char *kv_pairs)
350{
351 int rc = NO_ERROR;
352 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
353 audio_stream_out_t *out = NULL;
354
355 if (!is_valid_qahw_stream((void *)qahw_stream_out, STREAM_DIR_OUT)) {
356 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
357 rc = -EINVAL;
358 goto exit;
359 }
360
361 pthread_mutex_lock(&qahw_stream_out->lock);
362 out = qahw_stream_out->stream;
363 if (out->common.set_parameters) {
364 rc = out->common.set_parameters(&out->common, kv_pairs);
365 } else {
366 rc = -ENOSYS;
367 ALOGW("%s not supported", __func__);
368 }
369 pthread_mutex_unlock(&qahw_stream_out->lock);
370
371exit:
372 return rc;
373}
374
375char *qahw_out_get_parameters(const qahw_stream_handle_t *out_handle,
376 const char *keys)
377{
378 char *str_param = NULL;
379 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
380 audio_stream_out_t *out = NULL;
381
382 if (!is_valid_qahw_stream((void *)qahw_stream_out, STREAM_DIR_OUT)) {
383 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
384 goto exit;
385 }
386
387 pthread_mutex_lock(&qahw_stream_out->lock);
388 out = qahw_stream_out->stream;
389 if (out->common.get_parameters) {
390 str_param = out->common.get_parameters(&out->common, keys);
391 } else {
392 ALOGW("%s not supported", __func__);
393 }
394 pthread_mutex_unlock(&qahw_stream_out->lock);
395
396exit:
397 return str_param;
398}
399
400uint32_t qahw_out_get_latency(const qahw_stream_handle_t *out_handle)
401{
402 uint32_t latency = 0;
403 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
404 audio_stream_out_t *out = NULL;
405
406 if (!is_valid_qahw_stream((void *)qahw_stream_out, STREAM_DIR_OUT)) {
407 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
408 goto exit;
409 }
410
411 pthread_mutex_lock(&qahw_stream_out->lock);
412 out = qahw_stream_out->stream;
413 if (out->get_latency) {
414 latency = out->get_latency(out);
415 } else {
416 ALOGW("%s not supported", __func__);
417 }
418 pthread_mutex_unlock(&qahw_stream_out->lock);
419
420exit:
421 return latency;
422}
423
424int qahw_out_set_volume(qahw_stream_handle_t *out_handle, float left, float right)
425{
426 int rc = -EINVAL;
427 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
428 audio_stream_out_t *out = NULL;
429
430 if (!is_valid_qahw_stream((void *)qahw_stream_out, STREAM_DIR_OUT)) {
431 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
432 goto exit;
433 }
434
435 pthread_mutex_lock(&qahw_stream_out->lock);
436 out = qahw_stream_out->stream;
437 if (out->set_volume) {
438 rc = out->set_volume(out, left, right);
439 } else {
440 rc = -ENOSYS;
441 ALOGW("%s not supported", __func__);
442 }
443 pthread_mutex_unlock(&qahw_stream_out->lock);
444
445exit:
446 return rc;
447}
448
449ssize_t qahw_out_write(qahw_stream_handle_t *out_handle,
450 qahw_out_buffer_t *out_buf)
451{
452 int rc = -EINVAL;
453 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
454 audio_stream_out_t *out = NULL;
455
456 if ((out_buf == NULL) || (out_buf->buffer == NULL)) {
457 ALOGE("%s::Invalid meta data %p", __func__, out_buf);
458 goto exit;
459 }
460
461 if (!is_valid_qahw_stream((void *)qahw_stream_out, STREAM_DIR_OUT)) {
462 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
463 goto exit;
464 }
465
466 /*TBD:: validate other meta data parameters */
467
468 pthread_mutex_lock(&qahw_stream_out->lock);
469 out = qahw_stream_out->stream;
470 if (out->write) {
471 rc = out->write(out, out_buf->buffer, out_buf->bytes);
472 } else {
473 rc = -ENOSYS;
474 ALOGW("%s not supported", __func__);
475 }
476 pthread_mutex_unlock(&qahw_stream_out->lock);
477exit:
478 return rc;
479}
480
481int qahw_out_get_render_position(const qahw_stream_handle_t *out_handle,
482 uint32_t *dsp_frames)
483{
484 int rc = -EINVAL;
485 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
486 audio_stream_out_t *out = NULL;
487
488 if (!is_valid_qahw_stream((void *)qahw_stream_out, STREAM_DIR_OUT)) {
489 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
490 goto exit;
491 }
492
493 pthread_mutex_lock(&qahw_stream_out->lock);
494 out = qahw_stream_out->stream;
495 if (out->get_render_position) {
496 rc = out->get_render_position(out, dsp_frames);
497 } else {
498 rc = -ENOSYS;
499 ALOGW("%s not supported", __func__);
500 }
501 pthread_mutex_unlock(&qahw_stream_out->lock);
502exit:
503 return rc;
504}
505
506int qahw_out_set_callback(qahw_stream_handle_t *out_handle,
507 qahw_stream_callback_t callback,
508 void *cookie)
509{
510 /*TBD:load hal func pointer and call */
511 int rc = -EINVAL;
512 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
513 audio_stream_out_t *out = NULL;
514
515 if (!is_valid_qahw_stream((void *)qahw_stream_out, STREAM_DIR_OUT)) {
516 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
517 goto exit;
518 }
519
520 pthread_mutex_lock(&qahw_stream_out->lock);
521 out = qahw_stream_out->stream;
522 if (out->set_callback) {
523 rc = out->set_callback(out, (stream_callback_t)callback, cookie);
524 } else {
525 rc = -ENOSYS;
526 ALOGW("%s not supported", __func__);
527 }
528 pthread_mutex_unlock(&qahw_stream_out->lock);
529
530exit:
531 return rc;
532}
533
534int qahw_out_pause(qahw_stream_handle_t *out_handle)
535{
536 /*TBD:load hal func pointer and call */
537 int rc = -EINVAL;
538 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
539 audio_stream_out_t *out = NULL;
540
541 if (!is_valid_qahw_stream((void *)qahw_stream_out, STREAM_DIR_OUT)) {
542 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
543 goto exit;
544 }
545
546 pthread_mutex_lock(&qahw_stream_out->lock);
547 out = qahw_stream_out->stream;
548 if (out->pause) {
549 rc = out->pause(out);
550 } else {
551 rc = -ENOSYS;
552 ALOGW("%s not supported", __func__);
553 }
554 pthread_mutex_unlock(&qahw_stream_out->lock);
555
556exit:
557 return rc;
558}
559
560int qahw_out_resume(qahw_stream_handle_t *out_handle)
561{
562 /*TBD:load hal func pointer and call */
563 int rc = -EINVAL;
564 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
565 audio_stream_out_t *out = NULL;
566
567 if (!is_valid_qahw_stream((void *)qahw_stream_out, STREAM_DIR_OUT)) {
568 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
569 goto exit;
570 }
571
572 pthread_mutex_lock(&qahw_stream_out->lock);
573 out = qahw_stream_out->stream;
574 if (out->resume) {
575 rc = out->resume(out);
576 } else {
577 rc = -ENOSYS;
578 ALOGW("%s not supported", __func__);
579 }
580 pthread_mutex_unlock(&qahw_stream_out->lock);
581
582exit:
583 return rc;
584}
585
586int qahw_out_drain(qahw_stream_handle_t *out_handle, qahw_drain_type_t type )
587{
588 /*TBD:load hal func pointer and call */
589 int rc = -EINVAL;
590 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
591 audio_stream_out_t *out = NULL;
592
593 if (!is_valid_qahw_stream((void *)qahw_stream_out, STREAM_DIR_OUT)) {
594 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
595 goto exit;
596 }
597
598 pthread_mutex_lock(&qahw_stream_out->lock);
599 out = qahw_stream_out->stream;
600 if (out->drain) {
601 rc = out->drain(out,(audio_drain_type_t)type);
602 } else {
603 rc = -ENOSYS;
604 ALOGW("%s not supported", __func__);
605 }
606 pthread_mutex_unlock(&qahw_stream_out->lock);
607
608exit:
609 return rc;
610}
611
612int qahw_out_flush(qahw_stream_handle_t *out_handle)
613{
614 int rc = -EINVAL;
615 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
616 audio_stream_out_t *out = NULL;
617
618 if (!is_valid_qahw_stream((void *)qahw_stream_out, STREAM_DIR_OUT)) {
619 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
620 goto exit;
621 }
622
623 pthread_mutex_lock(&qahw_stream_out->lock);
624 out = qahw_stream_out->stream;
625 if (out->flush) {
626 rc = out->flush(out);
627 } else {
628 rc = -ENOSYS;
629 ALOGW("%s not supported", __func__);
630 }
631 pthread_mutex_unlock(&qahw_stream_out->lock);
632
633exit:
634 return rc;
635}
636
637int qahw_out_get_presentation_position(const qahw_stream_handle_t *out_handle,
638 uint64_t *frames, struct timespec *timestamp)
639{
640 int rc = -EINVAL;
641 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
642 audio_stream_out_t *out = NULL;
643
644 if (!is_valid_qahw_stream((void *)qahw_stream_out, STREAM_DIR_OUT)) {
645 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
646 goto exit;
647 }
648
649 pthread_mutex_lock(&qahw_stream_out->lock);
650 out = qahw_stream_out->stream;
651 if (out->get_presentation_position) {
652 rc = out->get_presentation_position(out, frames, timestamp);
653 } else {
654 rc = -ENOSYS;
655 ALOGW("%s not supported", __func__);
656 }
657 pthread_mutex_unlock(&qahw_stream_out->lock);
658
659exit:
660 return rc;
661}
662
663/* Input stream specific APIs */
664uint32_t qahw_in_get_sample_rate(const qahw_stream_handle_t *in_handle)
665{
666 uint32_t rate = 0;
667 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
668 audio_stream_in_t *in = NULL;
669
670 if (!is_valid_qahw_stream((void *)qahw_stream_in, STREAM_DIR_IN)) {
671 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
672 goto exit;
673 }
674
675 pthread_mutex_lock(&qahw_stream_in->lock);
676 in = qahw_stream_in->stream;
677 if (in->common.get_sample_rate) {
678 rate = in->common.get_sample_rate(&in->common);
679 } else {
680 ALOGW("%s not supported", __func__);
681 }
682 pthread_mutex_unlock(&qahw_stream_in->lock);
683
684exit:
685 return rate;
686}
687
688/*
689 * currently unused - use set_parameters with key
690 * AUDIO_PARAMETER_STREAM_SAMPLING_RATE
691 */
692int qahw_in_set_sample_rate(qahw_stream_handle_t *in_handle, uint32_t rate)
693{
694 int rc = -EINVAL;
695 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
696 audio_stream_in_t *in = NULL;
697
698 if (!is_valid_qahw_stream((void *)qahw_stream_in, STREAM_DIR_IN)) {
699 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
700 goto exit;
701 }
702
703 pthread_mutex_lock(&qahw_stream_in->lock);
704 in = qahw_stream_in->stream;
705 if (in->common.set_sample_rate) {
706 rc = in->common.set_sample_rate(&in->common, rate);
707 } else {
708 rc = -ENOSYS;
709 ALOGW("%s not supported", __func__);
710 }
711 pthread_mutex_unlock(&qahw_stream_in->lock);
712
713exit:
714 return rc;
715}
716
717size_t qahw_in_get_buffer_size(const qahw_stream_handle_t *in_handle)
718{
719 size_t buf_size = 0;
720 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
721 audio_stream_in_t *in = NULL;
722
723 if (!is_valid_qahw_stream((void *)qahw_stream_in, STREAM_DIR_IN)) {
724 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
725 goto exit;
726 }
727
728 pthread_mutex_lock(&qahw_stream_in->lock);
729 in = qahw_stream_in->stream;
730 if (in->common.get_sample_rate) {
731 buf_size = in->common.get_buffer_size(&in->common);
732 } else {
733 ALOGW("%s not supported", __func__);
734 }
735 pthread_mutex_unlock(&qahw_stream_in->lock);
736
737exit:
738 return buf_size;
739}
740
741
742audio_channel_mask_t qahw_in_get_channels(const qahw_stream_handle_t *in_handle)
743{
744 audio_channel_mask_t ch_mask = 0;;
745 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
746 audio_stream_in_t *in = NULL;
747
748 if (!is_valid_qahw_stream((void *)qahw_stream_in, STREAM_DIR_IN)) {
749 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
750 goto exit;
751 }
752
753 pthread_mutex_lock(&qahw_stream_in->lock);
754 in = qahw_stream_in->stream;
755 if (in->common.get_channels) {
756 ch_mask = in->common.get_channels(&in->common);
757 } else {
758 ALOGW("%s not supported", __func__);
759 }
760 pthread_mutex_unlock(&qahw_stream_in->lock);
761
762exit:
763 return ch_mask;
764}
765
766audio_format_t qahw_in_get_format(const qahw_stream_handle_t *in_handle)
767{
768 audio_format_t format = AUDIO_FORMAT_INVALID;
769 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
770 audio_stream_in_t *in = NULL;
771
772 if (!is_valid_qahw_stream((void *)qahw_stream_in, STREAM_DIR_IN)) {
773 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
774 goto exit;
775 }
776
777 pthread_mutex_lock(&qahw_stream_in->lock);
778 in = qahw_stream_in->stream;
779 if (in->common.get_format) {
780 format = in->common.get_format(&in->common);
781 } else {
782 ALOGW("%s not supported", __func__);
783 }
784 pthread_mutex_unlock(&qahw_stream_in->lock);
785
786exit:
787 return format;
788}
789
790/*
791 * currently unused - use set_parameters with key
792 * AUDIO_PARAMETER_STREAM_FORMAT
793 */
794int qahw_in_set_format(qahw_stream_handle_t *in_handle, audio_format_t format)
795{
796 int rc = -EINVAL;
797 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
798 audio_stream_in_t *in = NULL;
799
800 if (!is_valid_qahw_stream((void *)qahw_stream_in, STREAM_DIR_IN)) {
801 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
802 goto exit;
803 }
804
805 pthread_mutex_lock(&qahw_stream_in->lock);
806 in = qahw_stream_in->stream;
807 if (in->common.set_format) {
808 rc = in->common.set_format(&in->common, format);
809 } else {
810 rc = -ENOSYS;
811 ALOGW("%s not supported", __func__);
812 }
813 pthread_mutex_unlock(&qahw_stream_in->lock);
814
815exit:
816 return rc;
817}
818
819int qahw_in_standby(qahw_stream_handle_t *in_handle)
820{
821 int rc = -EINVAL;
822 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
823 audio_stream_in_t *in = NULL;
824
825 if (!is_valid_qahw_stream((void *)qahw_stream_in, STREAM_DIR_IN)) {
826 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
827 goto exit;
828 }
829
830 pthread_mutex_lock(&qahw_stream_in->lock);
831 in = qahw_stream_in->stream;
832 if (in->common.standby) {
833 rc = in->common.standby(&in->common);
834 } else {
835 rc = -ENOSYS;
836 ALOGW("%s not supported", __func__);
837 }
838 pthread_mutex_unlock(&qahw_stream_in->lock);
839
840exit:
841 return rc;
842}
843
844/*
845 * set/get audio stream parameters. The function accepts a list of
846 * parameter key value pairs in the form: key1=value1;key2=value2;...
847 *
848 * Some keys are reserved for standard parameters (See AudioParameter class)
849 *
850 * If the implementation does not accept a parameter change while
851 * the output is active but the parameter is acceptable otherwise, it must
852 * return -ENOSYS.
853 *
854 * The audio flinger will put the stream in standby and then change the
855 * parameter value.
856 */
857int qahw_in_set_parameters(qahw_stream_handle_t *in_handle, const char *kv_pairs)
858{
859 int rc = -EINVAL;
860 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
861 audio_stream_in_t *in = NULL;
862
863 if (!is_valid_qahw_stream((void *)qahw_stream_in, STREAM_DIR_IN)) {
864 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
865 goto exit;
866 }
867
868 pthread_mutex_lock(&qahw_stream_in->lock);
869 in = qahw_stream_in->stream;
870 if (in->common.set_parameters) {
871 rc = in->common.set_parameters(&in->common, kv_pairs);
872 } else {
873 rc = -ENOSYS;
874 ALOGW("%s not supported", __func__);
875 }
876 pthread_mutex_unlock(&qahw_stream_in->lock);
877exit:
878 return rc;
879}
880
881/*
882 * Returns a pointer to a heap allocated string. The caller is responsible
883 * for freeing the memory for it using free().
884 */
885char * qahw_in_get_parameters(const qahw_stream_handle_t *in_handle,
886 const char *keys)
887{
888 char *str_param = NULL;
889 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
890 audio_stream_in_t *in = NULL;
891
892 if (!is_valid_qahw_stream((void *)qahw_stream_in, STREAM_DIR_IN)) {
893 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
894 goto exit;
895 }
896
897 pthread_mutex_lock(&qahw_stream_in->lock);
898 in = qahw_stream_in->stream;
899 if (in->common.get_parameters) {
900 str_param = in->common.get_parameters(&in->common, keys);
901 } else {
902 ALOGW("%s not supported", __func__);
903 }
904 pthread_mutex_unlock(&qahw_stream_in->lock);
905
906exit:
907 return str_param;
908}
909
910/*
911 * Read audio buffer in from audio driver. Returns number of bytes read, or a
912 * negative status_t. If at least one frame was read prior to the error,
913 * read should return that byte count and then return an error in the subsequent call.
914 */
915ssize_t qahw_in_read(qahw_stream_handle_t *in_handle,
916 qahw_in_buffer_t *in_buf)
917{
918 int rc = -EINVAL;
919 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
920 audio_stream_in_t *in = NULL;
921
922 if ((in_buf == NULL) || (in_buf->buffer == NULL)) {
923 ALOGE("%s::Invalid meta data %p", __func__, in_buf);
924 goto exit;
925 }
926
927 if (!is_valid_qahw_stream((void *)qahw_stream_in, STREAM_DIR_IN)) {
928 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
929 goto exit;
930 }
931
932 pthread_mutex_lock(&qahw_stream_in->lock);
933 in = qahw_stream_in->stream;
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +0530934 if (qahw_stream_in->qahwi_in_read_v2) {
935 rc = qahw_stream_in->qahwi_in_read_v2(in, in_buf->buffer,
936 in_buf->bytes, in_buf->timestamp);
937 in_buf->offset = 0;
938 } else if (in->read) {
Manish Dewanganb8c83a42016-09-23 15:10:48 +0530939 rc = in->read(in, in_buf->buffer, in_buf->bytes);
940 in_buf->offset = 0;
941 } else {
942 rc = -ENOSYS;
943 ALOGW("%s not supported", __func__);
944 }
945 pthread_mutex_unlock(&qahw_stream_in->lock);
946
947exit:
948 return rc;
949}
950
951/*
952 * Return the amount of input frames lost in the audio driver since the
953 * last call of this function.
954 * Audio driver is expected to reset the value to 0 and restart counting
955 * upon returning the current value by this function call.
956 * Such loss typically occurs when the user space process is blocked
957 * longer than the capacity of audio driver buffers.
958 *
959 * Unit: the number of input audio frames
960 */
961uint32_t qahw_in_get_input_frames_lost(qahw_stream_handle_t *in_handle)
962{
963 uint32_t rc = 0;
964 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
965 audio_stream_in_t *in = NULL;
966
967 if (!is_valid_qahw_stream((void *)qahw_stream_in, STREAM_DIR_IN)) {
968 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
969 goto exit;
970 }
971
972 pthread_mutex_lock(&qahw_stream_in->lock);
973 in = qahw_stream_in->stream;
974 if (in->get_input_frames_lost) {
975 rc = in->get_input_frames_lost(in);
976 } else {
977 rc = -ENOSYS;
978 ALOGW("%s not supported", __func__);
979 }
980 pthread_mutex_unlock(&qahw_stream_in->lock);
981
982exit:
983 return rc;
984}
985
986/*
987 * Return a recent count of the number of audio frames received and
988 * the clock time associated with that frame count.
989 *
990 * frames is the total frame count received. This should be as early in
991 * the capture pipeline as possible. In general,
992 * frames should be non-negative and should not go "backwards".
993 *
994 * time is the clock MONOTONIC time when frames was measured. In general,
995 * time should be a positive quantity and should not go "backwards".
996 *
997 * The status returned is 0 on success, -ENOSYS if the device is not
998 * ready/available, or -EINVAL if the arguments are null or otherwise invalid.
999 */
1000int qahw_in_get_capture_position(const qahw_stream_handle_t *in_handle __unused,
1001 int64_t *frames __unused, int64_t *time __unused)
1002{
1003 /*TBD:: do we need this*/
1004 return -ENOSYS;
1005}
1006
1007/*
1008 * check to see if the audio hardware interface has been initialized.
1009 * returns 0 on success, -ENODEV on failure.
1010 */
1011int qahw_init_check(const qahw_module_handle_t *hw_module)
1012{
1013 int rc = -EINVAL;
1014 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1015 qahw_module_t *qahw_module_temp;
1016
1017 pthread_mutex_lock(&qahw_module_init_lock);
1018 qahw_module_temp = get_qahw_module_by_ptr(qahw_module);
1019 pthread_mutex_unlock(&qahw_module_init_lock);
1020 if (qahw_module_temp == NULL) {
1021 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1022 goto exit;
1023 }
1024
1025 pthread_mutex_lock(&qahw_module->lock);
1026 if (qahw_module->audio_device->init_check) {
1027 rc = qahw_module->audio_device->init_check(qahw_module->audio_device);
1028 } else {
1029 rc = -ENOSYS;
1030 ALOGW("%s not supported", __func__);
1031 }
1032 pthread_mutex_unlock(&qahw_module->lock);
1033
1034exit:
1035 return rc;
1036}
1037/* set the audio volume of a voice call. Range is between 0.0 and 1.0 */
1038int qahw_set_voice_volume(qahw_module_handle_t *hw_module, float volume)
1039{
1040 int rc = -EINVAL;
1041 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1042 qahw_module_t *qahw_module_temp;
1043
1044 pthread_mutex_lock(&qahw_module_init_lock);
1045 qahw_module_temp = get_qahw_module_by_ptr(qahw_module);
1046 pthread_mutex_unlock(&qahw_module_init_lock);
1047 if (qahw_module_temp == NULL) {
1048 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1049 goto exit;
1050 }
1051
1052 pthread_mutex_lock(&qahw_module->lock);
1053 if (qahw_module->audio_device->set_voice_volume) {
1054 rc = qahw_module->audio_device->set_voice_volume(qahw_module->audio_device,
1055 volume);
1056 } else {
1057 rc = -ENOSYS;
1058 ALOGW("%s not supported", __func__);
1059 }
1060 pthread_mutex_unlock(&qahw_module->lock);
1061
1062exit:
1063 return rc;
1064}
1065
1066/*
1067 * set_mode is called when the audio mode changes. AUDIO_MODE_NORMAL mode
1068 * is for standard audio playback, AUDIO_MODE_RINGTONE when a ringtone is
1069 * playing, and AUDIO_MODE_IN_CALL when a call is in progress.
1070 */
1071int qahw_set_mode(qahw_module_handle_t *hw_module, audio_mode_t mode)
1072{
1073 int rc = -EINVAL;
1074 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1075 qahw_module_t *qahw_module_temp;
1076
1077 pthread_mutex_lock(&qahw_module_init_lock);
1078 qahw_module_temp = get_qahw_module_by_ptr(qahw_module);
1079 pthread_mutex_unlock(&qahw_module_init_lock);
1080 if (qahw_module_temp == NULL) {
1081 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1082 goto exit;
1083 }
1084
1085 pthread_mutex_lock(&qahw_module->lock);
1086 if (qahw_module->audio_device->set_mode) {
1087 rc = qahw_module->audio_device->set_mode(qahw_module->audio_device,
1088 mode);
1089 } else {
1090 rc = -ENOSYS;
1091 ALOGW("%s not supported", __func__);
1092 }
1093 pthread_mutex_unlock(&qahw_module->lock);
1094
1095exit:
1096 return rc;
1097}
1098
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301099int qahw_set_mic_mute(qahw_module_handle_t *hw_module, bool state)
1100{
1101 int rc = -EINVAL;
1102 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1103 qahw_module_t *qahw_module_temp;
1104
1105 pthread_mutex_lock(&qahw_module_init_lock);
1106 qahw_module_temp = get_qahw_module_by_ptr(qahw_module);
1107 pthread_mutex_unlock(&qahw_module_init_lock);
1108 if (qahw_module_temp == NULL) {
1109 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1110 goto exit;
1111 }
1112
1113 pthread_mutex_lock(&qahw_module->lock);
1114 if (qahw_module->audio_device->set_mic_mute) {
1115 rc = qahw_module->audio_device->set_mic_mute(qahw_module->audio_device,
1116 state);
1117 } else {
1118 rc = -ENOSYS;
1119 ALOGW("%s not supported", __func__);
1120 }
1121 pthread_mutex_unlock(&qahw_module->lock);
1122
1123exit:
1124 return rc;
1125}
1126
1127int qahw_get_mic_mute(qahw_module_handle_t *hw_module, bool *state)
1128{
1129 size_t rc = 0;
1130 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1131 qahw_module_t *qahw_module_temp;
1132 audio_hw_device_t *audio_device;
1133
1134 pthread_mutex_lock(&qahw_module_init_lock);
1135 qahw_module_temp = get_qahw_module_by_ptr(qahw_module);
1136 pthread_mutex_unlock(&qahw_module_init_lock);
1137 if (qahw_module_temp == NULL) {
1138 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1139 goto exit;
1140 }
1141
1142 pthread_mutex_lock(&qahw_module->lock);
1143 audio_device = qahw_module->audio_device;
1144 if (qahw_module->audio_device->get_mic_mute) {
Dhananjay Kumar23a3bec2017-01-11 18:38:09 +05301145 rc = audio_device->get_mic_mute(qahw_module->audio_device, state);
Dhanalakshmi Siddani93b79ec2016-11-24 17:01:22 +05301146 } else {
1147 rc = -ENOSYS;
1148 ALOGW("%s not supported", __func__);
1149 }
1150 pthread_mutex_unlock(&qahw_module->lock);
1151
1152exit:
1153 return rc;
1154}
1155
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301156/* set/get global audio parameters */
1157int qahw_set_parameters(qahw_module_handle_t *hw_module, const char *kv_pairs)
1158{
1159 int rc = -EINVAL;
1160 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1161 qahw_module_t *qahw_module_temp;
1162 audio_hw_device_t *audio_device;
1163
1164 pthread_mutex_lock(&qahw_module_init_lock);
1165 qahw_module_temp = get_qahw_module_by_ptr(qahw_module);
1166 pthread_mutex_unlock(&qahw_module_init_lock);
1167 if (qahw_module_temp == NULL) {
1168 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1169 goto exit;
1170 }
1171
1172 pthread_mutex_lock(&qahw_module->lock);
1173 audio_device = qahw_module->audio_device;
1174 if (qahw_module->audio_device->set_parameters) {
1175 rc = audio_device->set_parameters(qahw_module->audio_device, kv_pairs);
1176 } else {
1177 rc = -ENOSYS;
1178 ALOGW("%s not supported", __func__);
1179 }
1180 pthread_mutex_unlock(&qahw_module->lock);
1181
1182exit:
1183 return rc;
1184}
1185
1186/*
1187 * Returns a pointer to a heap allocated string. The caller is responsible
1188 * for freeing the memory for it using free().
1189 */
1190char * qahw_get_parameters(const qahw_module_handle_t *hw_module,
1191 const char *keys)
1192{
1193 char *str_param = NULL;
1194 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1195 qahw_module_t *qahw_module_temp;
1196 audio_hw_device_t *audio_device;
1197
1198 pthread_mutex_lock(&qahw_module_init_lock);
1199 qahw_module_temp = get_qahw_module_by_ptr(qahw_module);
1200 pthread_mutex_unlock(&qahw_module_init_lock);
1201 if (qahw_module_temp == NULL) {
1202 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1203 goto exit;
1204 }
1205
1206 pthread_mutex_lock(&qahw_module->lock);
1207 audio_device = qahw_module->audio_device;
1208 if (qahw_module->audio_device->get_parameters) {
1209 str_param = audio_device->get_parameters(qahw_module->audio_device, keys);
1210 } else {
1211 ALOGW("%s not supported", __func__);
1212 }
1213 pthread_mutex_unlock(&qahw_module->lock);
1214
1215exit:
1216 return str_param;
1217}
1218
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301219/* Api to implement get parameters based on keyword param_id
1220 * and store data in payload.
1221 */
1222int qahw_get_param_data(const qahw_module_handle_t *hw_module,
1223 qahw_param_id param_id,
1224 qahw_param_payload *payload)
1225{
1226 int ret = 0;
1227 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1228 qahw_module_t *qahw_module_temp;
1229
1230 pthread_mutex_lock(&qahw_module_init_lock);
1231 qahw_module_temp = get_qahw_module_by_ptr(qahw_module);
1232 pthread_mutex_unlock(&qahw_module_init_lock);
1233 if (qahw_module_temp == NULL) {
1234 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1235 goto exit;
1236 }
1237
1238 pthread_mutex_lock(&qahw_module->lock);
1239
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301240 if (qahw_module->qahwi_get_param_data){
1241 ret = qahw_module->qahwi_get_param_data (qahw_module->audio_device,
1242 param_id, payload);
1243 } else {
1244 ret = -ENOSYS;
1245 ALOGE("%s not supported\n",__func__);
1246 }
1247 pthread_mutex_unlock(&qahw_module->lock);
1248
1249exit:
1250 return ret;
1251}
1252
1253/* Api to implement set parameters based on keyword param_id
1254 * and data present in payload.
1255 */
1256int qahw_set_param_data(const qahw_module_handle_t *hw_module,
1257 qahw_param_id param_id,
1258 qahw_param_payload *payload)
1259{
1260 int ret = 0;
1261 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1262 qahw_module_t *qahw_module_temp;
1263
1264 pthread_mutex_lock(&qahw_module_init_lock);
1265 qahw_module_temp = get_qahw_module_by_ptr(qahw_module);
1266 pthread_mutex_unlock(&qahw_module_init_lock);
1267 if (qahw_module_temp == NULL) {
1268 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1269 goto exit;
1270 }
1271
1272 pthread_mutex_lock(&qahw_module->lock);
1273
1274 if (qahw_module->qahwi_set_param_data){
1275 ret = qahw_module->qahwi_set_param_data (qahw_module->audio_device,
1276 param_id, payload);
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301277 } else {
1278 ret = -ENOSYS;
1279 ALOGE("%s not supported\n",__func__);
1280 }
1281 pthread_mutex_unlock(&qahw_module->lock);
1282
1283exit:
1284 return ret;
1285}
1286
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301287/* Returns audio input buffer size according to parameters passed or
1288 * 0 if one of the parameters is not supported.
1289 * See also get_buffer_size which is for a particular stream.
1290 */
1291size_t qahw_get_input_buffer_size(const qahw_module_handle_t *hw_module,
1292 const struct audio_config *config)
1293{
1294 size_t rc = 0;
1295 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1296 qahw_module_t *qahw_module_temp;
1297 audio_hw_device_t *audio_device;
1298
1299 pthread_mutex_lock(&qahw_module_init_lock);
1300 qahw_module_temp = get_qahw_module_by_ptr(qahw_module);
1301 pthread_mutex_unlock(&qahw_module_init_lock);
1302 if (qahw_module_temp == NULL) {
1303 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1304 goto exit;
1305 }
1306
1307 pthread_mutex_lock(&qahw_module->lock);
1308 audio_device = qahw_module->audio_device;
1309 if (qahw_module->audio_device->get_input_buffer_size) {
1310 rc = audio_device->get_input_buffer_size(qahw_module->audio_device,
1311 config);
1312 } else {
1313 rc = -ENOSYS;
1314 ALOGW("%s not supported", __func__);
1315 }
1316 pthread_mutex_unlock(&qahw_module->lock);
1317
1318exit:
1319 return rc;
1320}
1321
1322/*
1323 * This method creates and opens the audio hardware output stream.
1324 * The "address" parameter qualifies the "devices" audio device type if needed.
1325 * The format format depends on the device type:
1326 * - Bluetooth devices use the MAC address of the device in the form "00:11:22:AA:BB:CC"
1327 * - USB devices use the ALSA card and device numbers in the form "card=X;device=Y"
1328 * - Other devices may use a number or any other string.
1329 */
1330int qahw_open_output_stream(qahw_module_handle_t *hw_module,
1331 audio_io_handle_t handle,
1332 audio_devices_t devices,
1333 audio_output_flags_t flags,
1334 struct audio_config *config,
1335 qahw_stream_handle_t **out_handle,
1336 const char *address)
1337{
1338 int rc = -EINVAL;
1339 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1340 qahw_module_t *qahw_module_temp = NULL;
1341 audio_hw_device_t *audio_device = NULL;
1342 qahw_stream_out_t *qahw_stream_out = NULL;
1343
1344 pthread_mutex_lock(&qahw_module_init_lock);
1345 qahw_module_temp = get_qahw_module_by_ptr(qahw_module);
1346 pthread_mutex_unlock(&qahw_module_init_lock);
1347 if (qahw_module_temp == NULL) {
1348 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1349 return rc;
1350 }
1351
1352 pthread_mutex_lock(&qahw_module->lock);
1353 audio_device = qahw_module->audio_device;
1354 qahw_stream_out = (qahw_stream_out_t *)calloc(1, sizeof(qahw_stream_out_t));
1355 if (qahw_stream_out == NULL) {
1356 ALOGE("%s:: calloc failed for out stream_out_t",__func__);
1357 rc = -ENOMEM;
1358 goto exit;
1359 }
1360
1361 rc = audio_device->open_output_stream(audio_device,
1362 handle,
1363 devices,
1364 flags,
1365 config,
1366 &qahw_stream_out->stream,
1367 address);
1368 if (rc) {
1369 ALOGE("%s::open output stream failed %d",__func__, rc);
1370 free(qahw_stream_out);
1371 } else {
1372 qahw_stream_out->module = hw_module;
1373 *out_handle = (void *)qahw_stream_out;
1374 pthread_mutex_init(&qahw_stream_out->lock, (const pthread_mutexattr_t *)NULL);
1375 list_add_tail(&qahw_module->out_list, &qahw_stream_out->list);
1376 }
1377
1378exit:
1379 pthread_mutex_unlock(&qahw_module->lock);
1380 return rc;
1381}
1382
1383int qahw_close_output_stream(qahw_stream_handle_t *out_handle)
1384{
1385
1386 int rc = 0;
1387 qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
1388 qahw_module_t *qahw_module = NULL;
1389 audio_hw_device_t *audio_device = NULL;
1390
1391 if (!is_valid_qahw_stream((void *)qahw_stream_out, STREAM_DIR_OUT)) {
1392 ALOGE("%s::Invalid out handle %p", __func__, out_handle);
1393 rc = -EINVAL;
1394 goto exit;
1395 }
1396
1397 ALOGV("%s::calling device close_output_stream %p", __func__, out_handle);
1398 pthread_mutex_lock(&qahw_stream_out->lock);
1399 qahw_module = qahw_stream_out->module;
1400 audio_device = qahw_module->audio_device;
1401 audio_device->close_output_stream(audio_device,
1402 qahw_stream_out->stream);
1403
1404 pthread_mutex_lock(&qahw_module->lock);
1405 list_remove(&qahw_stream_out->list);
1406 pthread_mutex_unlock(&qahw_module->lock);
1407
1408 pthread_mutex_unlock(&qahw_stream_out->lock);
1409
1410 pthread_mutex_destroy(&qahw_stream_out->lock);
1411 free(qahw_stream_out);
1412
1413exit:
1414 return rc;
1415}
1416
1417/* This method creates and opens the audio hardware input stream */
1418int qahw_open_input_stream(qahw_module_handle_t *hw_module,
1419 audio_io_handle_t handle,
1420 audio_devices_t devices,
1421 struct audio_config *config,
1422 qahw_stream_handle_t **in_handle,
1423 audio_input_flags_t flags,
1424 const char *address,
1425 audio_source_t source)
1426{
1427 int rc = -EINVAL;
1428 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1429 qahw_module_t *qahw_module_temp = NULL;
1430 audio_hw_device_t *audio_device = NULL;
1431 qahw_stream_in_t *qahw_stream_in = NULL;
1432
1433 pthread_mutex_lock(&qahw_module_init_lock);
1434 qahw_module_temp = get_qahw_module_by_ptr(qahw_module);
1435 pthread_mutex_unlock(&qahw_module_init_lock);
1436 if (qahw_module_temp == NULL) {
1437 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1438 return rc;
1439 }
1440
1441 pthread_mutex_lock(&qahw_module->lock);
1442 audio_device = qahw_module->audio_device;
1443 qahw_stream_in = (qahw_stream_in_t *)calloc(1, sizeof(qahw_stream_in_t));
1444 if (qahw_stream_in == NULL) {
1445 ALOGE("%s:: calloc failed for in stream_in_t",__func__);
1446 rc = -ENOMEM;
1447 goto exit;
1448 }
1449
1450 rc = audio_device->open_input_stream(audio_device,
1451 handle,
1452 devices,
1453 config,
1454 &qahw_stream_in->stream,
1455 flags,
1456 address,
1457 source);
1458 if (rc) {
1459 ALOGE("%s::open input stream failed %d",__func__, rc);
1460 free(qahw_stream_in);
1461 } else {
1462 qahw_stream_in->module = hw_module;
1463 *in_handle = (void *)qahw_stream_in;
1464 pthread_mutex_init(&qahw_stream_in->lock, (const pthread_mutexattr_t *)NULL);
1465 list_add_tail(&qahw_module->in_list, &qahw_stream_in->list);
1466 }
1467
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +05301468 /* dlsym qahwi_in_read_v2 if timestamp flag is used */
1469 if (!rc && (flags & QAHW_INPUT_FLAG_TIMESTAMP)) {
1470 const char *error;
1471
1472 /* clear any existing errors */
1473 dlerror();
1474 qahw_stream_in->qahwi_in_read_v2 = (qahwi_in_read_v2_t)
1475 dlsym(qahw_module->module->dso, "qahwi_in_read_v2");
1476 if ((error = dlerror()) != NULL) {
1477 ALOGI("%s: dlsym error %s for qahwi_in_read_v2", __func__, error);
1478 qahw_stream_in->qahwi_in_read_v2 = NULL;
1479 }
1480 }
1481
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301482exit:
1483 pthread_mutex_unlock(&qahw_module->lock);
1484 return rc;
1485}
1486
1487int qahw_close_input_stream(qahw_stream_handle_t *in_handle)
1488{
1489 int rc = 0;
1490 qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
1491 qahw_module_t *qahw_module = NULL;
1492 audio_hw_device_t *audio_device = NULL;
1493
1494 if (!is_valid_qahw_stream((void *)qahw_stream_in, STREAM_DIR_IN)) {
1495 ALOGV("%s::Invalid in handle %p", __func__, in_handle);
1496 rc = -EINVAL;
1497 goto exit;
1498 }
1499
1500 ALOGV("%s:: calling device close_input_stream %p", __func__, in_handle);
1501 pthread_mutex_lock(&qahw_stream_in->lock);
1502 qahw_module = qahw_stream_in->module;
1503 audio_device = qahw_module->audio_device;
1504 audio_device->close_input_stream(audio_device,
1505 qahw_stream_in->stream);
1506
1507 pthread_mutex_lock(&qahw_module->lock);
1508 list_remove(&qahw_stream_in->list);
1509 pthread_mutex_unlock(&qahw_module->lock);
1510
1511 pthread_mutex_unlock(&qahw_stream_in->lock);
1512
1513 pthread_mutex_destroy(&qahw_stream_in->lock);
1514 free(qahw_stream_in);
1515
1516exit:
1517 return rc;
1518}
1519
1520/*returns current QTI HAL verison */
1521int qahw_get_version() {
1522 return QAHW_MODULE_API_VERSION_CURRENT;
1523}
1524
1525/* convenience API for opening and closing an audio HAL module */
1526
1527qahw_module_handle_t *qahw_load_module(const char *hw_module_id)
1528{
1529 int rc = -EINVAL;
1530 qahw_module_handle_t *qahw_mod_handle = NULL;
1531 qahw_module_t *qahw_module = NULL;
1532 char *ahal_name = NULL;
1533 const hw_module_t* module = NULL;
1534 audio_hw_device_t* audio_device = NULL;
1535
1536 if (hw_module_id == NULL) {
1537 ALOGE("%s::module id is NULL",__func__);
1538 goto exit;
1539 }
1540
1541 if (!strcmp(hw_module_id, QAHW_MODULE_ID_PRIMARY)) {
1542 ahal_name = "primary";
1543 } else if (!strcmp(hw_module_id, QAHW_MODULE_ID_A2DP)) {
1544 ahal_name = "a2dp";
1545 } else if (!strcmp(hw_module_id, QAHW_MODULE_ID_USB)) {
1546 ahal_name = "usb";
1547 } else {
1548 ALOGE("%s::Invalid Module id %s", __func__, hw_module_id);
1549 goto exit;
1550 }
1551
1552 /* return exiting module ptr if already loaded */
1553 pthread_mutex_lock(&qahw_module_init_lock);
1554 if (qahw_list_count > 0) {
1555 qahw_module = get_qahw_module_by_name(hw_module_id);
1556 if(qahw_module != NULL) {
1557 qahw_mod_handle = (void *)qahw_module;
1558 pthread_mutex_lock(&qahw_module->lock);
1559 qahw_module->ref_count++;
1560 pthread_mutex_unlock(&qahw_module->lock);
1561 goto error_exit;
1562 }
1563 }
1564
1565 rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, ahal_name, &module);
1566 if(rc) {
1567 ALOGE("%s::HAL Loading failed %d", __func__, rc);
1568 goto error_exit;
1569 }
1570
1571 rc = audio_hw_device_open(module, &audio_device);
1572 if(rc) {
1573 ALOGE("%s::HAL Device open failed %d", __func__, rc);
1574 goto error_exit;
1575 }
1576
1577 qahw_module = (qahw_module_t *)calloc(1, sizeof(qahw_module_t));
1578 if(qahw_module == NULL) {
1579 ALOGE("%s::calloc failed", __func__);
1580 audio_hw_device_close(audio_device);
1581 goto error_exit;
1582 }
Dhananjay Kumarbbb34ae2016-10-25 18:03:42 +05301583 qahw_module->module = module;
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301584 ALOGD("%s::Loaded HAL %s module %p", __func__, ahal_name, qahw_module);
1585
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301586 qahw_module->qahwi_get_param_data = (qahwi_get_param_data_t) dlsym (module->dso,
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301587 "qahwi_get_param_data");
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301588 if (!qahw_module->qahwi_get_param_data)
Sachin Mohan Gadage24b9672016-11-08 15:32:13 +05301589 ALOGD("%s::qahwi_get_param_data api is not defined\n",__func__);
1590
Sachin Mohan Gadag53ea1582016-12-29 11:40:06 +05301591 qahw_module->qahwi_set_param_data = (qahwi_set_param_data_t) dlsym (module->dso,
1592 "qahwi_set_param_data");
1593 if (!qahw_module->qahwi_set_param_data)
1594 ALOGD("%s::qahwi_set_param_data api is not defined\n",__func__);
1595
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301596 if (!qahw_list_count)
1597 list_init(&qahw_module_list);
1598 qahw_list_count++;
1599
1600 pthread_mutex_init(&qahw_module->lock, (const pthread_mutexattr_t *) NULL);
1601 pthread_mutex_lock(&qahw_module->lock);
1602 qahw_module->ref_count++;
1603 pthread_mutex_unlock(&qahw_module->lock);
1604
1605 list_init(&qahw_module->out_list);
1606 list_init(&qahw_module->in_list);
1607
1608 /* update qahw_module */
1609 qahw_module->audio_device = audio_device;
1610 strlcpy(&qahw_module->module_name[0], hw_module_id, MAX_MODULE_NAME_LENGTH);
1611
1612 qahw_mod_handle = (void *)qahw_module;
1613
1614 /* Add module list to global module list */
1615 list_add_tail(&qahw_module_list, &qahw_module->module_list);
1616
1617
1618error_exit:
1619 pthread_mutex_unlock(&qahw_module_init_lock);
1620
1621exit:
1622 return qahw_mod_handle;
1623}
1624
1625int qahw_unload_module(qahw_module_handle_t *hw_module)
1626{
1627 int rc = -EINVAL;
1628 bool is_empty = false;
1629 qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
1630 qahw_module_t *qahw_module_temp = NULL;
1631
1632 /* close HW device if its valid and all the streams on
1633 * it is closed
1634 */
1635 pthread_mutex_lock(&qahw_module_init_lock);
1636 qahw_module_temp = get_qahw_module_by_ptr(qahw_module);
1637 if (qahw_module_temp == NULL) {
1638 ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
1639 goto error_exit;
1640 }
1641
1642 pthread_mutex_lock(&qahw_module->lock);
1643 qahw_module->ref_count--;
1644 if (qahw_module->ref_count > 0) {
1645 rc = 0;
1646 ALOGE("%s:: skipping module unload of %p count %d", __func__,
1647 qahw_module,
1648 qahw_module->ref_count);
1649 pthread_mutex_unlock(&qahw_module->lock);
1650 goto error_exit;
1651 }
1652
1653 is_empty = (list_empty(&qahw_module->out_list) &&
1654 list_empty(&qahw_module->in_list));
1655 if (is_empty) {
1656 rc = audio_hw_device_close(qahw_module->audio_device);
1657 if(rc) {
1658 ALOGE("%s::HAL Device close failed Error %d Module %p",__func__,
1659 rc, qahw_module);
1660 rc = 0;
1661 }
1662 qahw_list_count--;
1663 list_remove(&qahw_module->module_list);
1664 pthread_mutex_unlock(&qahw_module->lock);
1665 pthread_mutex_destroy(&qahw_module->lock);
1666 free(qahw_module);
1667 } else {
1668 pthread_mutex_unlock(&qahw_module->lock);
1669 ALOGE("%s::failed as all the streams on this module"
1670 "is not closed", __func__);
1671 rc = -EINVAL;
1672 }
1673
1674error_exit:
1675 pthread_mutex_unlock(&qahw_module_init_lock);
1676
Manish Dewanganb8c83a42016-09-23 15:10:48 +05301677 return rc;
1678}
1679
1680__END_DECLS