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