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