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