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