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