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