summaryrefslogtreecommitdiff
path: root/qahw
diff options
context:
space:
mode:
authorSidipotu Ashok <sashok@codeaurora.org>2017-10-10 22:27:51 +0530
committerDhanalakshmi Siddani <dsiddani@codeaurora.org>2017-11-16 11:08:30 +0530
commit404f26d1f68e5cf7cfd120ef3ae191356d5eb535 (patch)
treed918d3054f364800304adb727002fee037904fe7 /qahw
parent386d1871308e018cc5180e0d62863b2fac63e412 (diff)
qahw: Add binder support for Audio HAL
- Bring in a new cpp source file which HAL clients talk to - This code in turn makes the binder proxy/clients side calls - The binder server calls into the existing qahw.c Change-Id: I45625bcb2d8a2eb858c68d24f0cad3202d754244
Diffstat (limited to 'qahw')
-rw-r--r--qahw/Android.mk38
-rw-r--r--qahw/Makefile.am20
-rw-r--r--qahw/configure.ac36
-rw-r--r--qahw/inc/qahw.h482
-rw-r--r--qahw/inc/qahw_defs.h393
-rw-r--r--qahw/inc/qahw_effect_api.h845
-rw-r--r--qahw/src/qahw.c1934
-rw-r--r--qahw/src/qahw_effect.c321
8 files changed, 4069 insertions, 0 deletions
diff --git a/qahw/Android.mk b/qahw/Android.mk
new file mode 100644
index 00000000..c7df9e3e
--- /dev/null
+++ b/qahw/Android.mk
@@ -0,0 +1,38 @@
+ifeq ($(strip $(BOARD_SUPPORTS_QAHW)),true)
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+libqahw-inc := $(LOCAL_PATH)/inc
+
+LOCAL_MODULE := libqahwwrapper
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES := $(libqahw-inc)
+
+LOCAL_SRC_FILES := \
+ src/qahw.c \
+ src/qahw_effect.c
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libcutils \
+ libhardware \
+ libdl
+
+LOCAL_CFLAGS += -Wall -Werror
+
+LOCAL_COPY_HEADERS_TO := mm-audio/qahw/inc
+LOCAL_COPY_HEADERS := inc/qahw.h
+LOCAL_COPY_HEADERS += inc/qahw_effect_api.h
+
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_COPY_HEADERS_TO := mm-audio/qahw_api/inc
+LOCAL_COPY_HEADERS := inc/qahw_defs.h
+
+include $(BUILD_COPY_HEADERS)
+endif
diff --git a/qahw/Makefile.am b/qahw/Makefile.am
new file mode 100644
index 00000000..b6ebd8b5
--- /dev/null
+++ b/qahw/Makefile.am
@@ -0,0 +1,20 @@
+AM_CFLAGS = -I $(top_srcdir)/inc
+
+h_sources = inc/qahw.h \
+ inc/qahw_effect_api.h
+
+qahw_include_HEADERS = $(h_sources)
+qahw_includedir = $(includedir)/mm-audio/qahw/inc
+
+qahw_api_include_HEADERS = inc/qahw_defs.h
+qahw_api_includedir = $(includedir)/mm-audio/qahw_api/inc
+
+lib_LTLIBRARIES = libqahwwrapper.la
+libqahwwrapper_la_SOURCES = src/qahw.c \
+ src/qahw_effect.c
+
+libqahwwrapper_la_CFLAGS = $(AM_CFLAGS)
+libqahwwrapper_la_CFLAGS += -include stddef.h
+libqahwwrapper_la_CFLAGS += -D__unused=__attribute__\(\(__unused__\)\)
+libqahwwrapper_la_CFLAGS += -Werror
+libqahwwrapper_la_LDFLAGS = -shared -avoid-version -llog -lcutils -lhardware
diff --git a/qahw/configure.ac b/qahw/configure.ac
new file mode 100644
index 00000000..c87447ea
--- /dev/null
+++ b/qahw/configure.ac
@@ -0,0 +1,36 @@
+# -*- Autoconf -*-
+# configure.ac -- Autoconf script for halinterface
+#
+
+# Process this file with autoconf to produce a configure script.
+
+# Requires autoconf tool later than 2.61
+AC_PREREQ([2.69])
+# Initialize the audiohalwrapper-interface package version 1.0.0
+AC_INIT(audiohalwrapperinterface,1.0.0)
+# Does not strictly follow GNU Coding standards
+AM_INIT_AUTOMAKE([foreign])
+# Disables auto rebuilding of configure, Makefile.ins
+#AM_MAINTAINER_MODE
+# defines some macros variable to be included by source
+AC_CONFIG_HEADERS([config.h])
+# defines some macros variable to be included by source
+AC_CONFIG_MACRO_DIR([m4])
+
+# Checks for programs.
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_PROG_CXX
+AC_PROG_LIBTOOL
+AC_PROG_AWK
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+PKG_PROG_PKG_CONFIG
+
+AC_CONFIG_FILES([ \
+ Makefile
+ ])
+
+AC_OUTPUT
diff --git a/qahw/inc/qahw.h b/qahw/inc/qahw.h
new file mode 100644
index 00000000..b7088ed5
--- /dev/null
+++ b/qahw/inc/qahw.h
@@ -0,0 +1,482 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 2011 The Android Open Source Project *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef QTI_AUDIO_QAHW_H
+#define QTI_AUDIO_QAHW_H
+
+#include <stdint.h>
+#include <strings.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <cutils/bitops.h>
+#include <system/audio.h>
+#include "qahw_defs.h"
+
+__BEGIN_DECLS
+/*
+ * Helper macros for module implementors.
+ *
+ * The derived modules should provide convenience macros for supported
+ * versions so that implementations can explicitly specify module
+ * versions at definition time.
+ */
+
+#define QAHW_MAKE_API_VERSION(maj,min) \
+ ((((maj) & 0xff) << 8) | ((min) & 0xff))
+
+/* First generation of audio devices had version hardcoded to 0. all devices with
+ * versions < 1.0 will be considered of first generation API.
+ */
+#define QAHW_MODULE_API_VERSION_0_0 QAHW_MAKE_API_VERSION(0, 0)
+
+/* Minimal QTI audio HAL version supported by the audio framework */
+#define QAHW_MODULE_API_VERSION_MIN QAHW_MODULE_API_VERSION_0_0
+
+/**
+ * List of known audio HAL modules. This is the base name of the audio HAL
+ * library composed of the "audio." prefix, one of the base names below and
+ * a suffix specific to the device.
+ * e.g: audio.primary.goldfish.so or audio.a2dp.default.so
+ */
+
+#define QAHW_MODULE_ID_PRIMARY "audio.primary"
+#define QAHW_MODULE_ID_A2DP "audio.a2dp"
+#define QAHW_MODULE_ID_USB "audio.usb"
+
+typedef void qahw_module_handle_t;
+typedef void qahw_stream_handle_t;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/**************************************/
+/* Output stream specific APIs **/
+
+/*
+ * This method creates and opens the audio hardware output stream.
+ * The "address" parameter qualifies the "devices" audio device type if needed.
+ * The format format depends on the device type:
+ * - Bluetooth devices use the MAC address of the device in the form "00:11:22:AA:BB:CC"
+ * - USB devices use the ALSA card and device numbers in the form "card=X;device=Y"
+ * - Other devices may use a number or any other string.
+ */
+
+int qahw_open_output_stream_l(qahw_module_handle_t *hw_module,
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ audio_output_flags_t flags,
+ struct audio_config *config,
+ qahw_stream_handle_t **out_handle,
+ const char *address);
+
+int qahw_close_output_stream_l(qahw_stream_handle_t *out_handle);
+
+/*
+ * Return the sampling rate in Hz - eg. 44100.
+ */
+uint32_t qahw_out_get_sample_rate_l(const qahw_stream_handle_t *stream);
+
+/*
+ * use set_parameters with key QAHW_PARAMETER_STREAM_SAMPLING_RATE
+ */
+int qahw_out_set_sample_rate_l(qahw_stream_handle_t *stream, uint32_t rate);
+
+/*
+ * Return size of input/output buffer in bytes for this stream - eg. 4800.
+ * It should be a multiple of the frame size. See also get_input_buffer_size.
+ */
+size_t qahw_out_get_buffer_size_l(const qahw_stream_handle_t *stream);
+
+/*
+ * Return the channel mask -
+ * e.g. AUDIO_CHANNEL_OUT_STEREO or AUDIO_CHANNEL_IN_STEREO
+ */
+audio_channel_mask_t qahw_out_get_channels_l(const qahw_stream_handle_t *stream);
+
+/*
+ * Return the audio format - e.g. AUDIO_FORMAT_PCM_16_BIT
+ */
+audio_format_t qahw_out_get_format_l(const qahw_stream_handle_t *stream);
+
+/*
+ * Put the audio hardware input/output into standby mode.
+ * Driver should exit from standby mode at the next I/O operation.
+ * Returns 0 on success and <0 on failure.
+ */
+int qahw_out_standby_l(qahw_stream_handle_t *stream);
+
+/*
+ * set/get audio stream parameters. The function accepts a list of
+ * parameter key value pairs in the form: key1=value1;key2=value2;...
+ *
+ * Some keys are reserved for standard parameters (See AudioParameter class)
+ *
+ * If the implementation does not accept a parameter change while
+ * the output is active but the parameter is acceptable otherwise, it must
+ * return -ENOSYS.
+ *
+ * The audio flinger will put the stream in standby and then change the
+ * parameter value.
+ */
+int qahw_out_set_parameters_l(qahw_stream_handle_t *stream, const char*kv_pairs);
+
+/*
+ * Returns a pointer to a heap allocated string. The caller is responsible
+ * for freeing the memory for it using free().
+ */
+char* qahw_out_get_parameters_l(const qahw_stream_handle_t *stream,
+ const char *keys);
+
+/* API to set playback stream specific config parameters */
+int qahw_out_set_param_data_l(qahw_stream_handle_t *out_handle,
+ qahw_param_id param_id,
+ qahw_param_payload *payload);
+
+/* API to get playback stream specific config parameters */
+int qahw_out_get_param_data_l(qahw_stream_handle_t *out_handle,
+ qahw_param_id param_id,
+ qahw_param_payload *payload);
+
+/*
+ * Return the audio hardware driver estimated latency in milliseconds.
+ */
+uint32_t qahw_out_get_latency_l(const qahw_stream_handle_t *stream);
+
+/*
+ * Use this method in situations where audio mixing is done in the
+ * hardware. This method serves as a direct interface with hardware,
+ * allowing you to directly set the volume as apposed to via the framework.
+ * This method might produce multiple PCM outputs or hardware accelerated
+ * codecs, such as MP3 or AAC.
+ */
+int qahw_out_set_volume_l(qahw_stream_handle_t *stream, float left, float right);
+
+/*
+ * Write audio buffer present in meta_data starting from offset
+ * along with timestamp to driver. Returns number of bytes
+ * written or a negative status_t. If at least one frame was written successfully
+ * prior to the error, it is suggested that the driver return that successful
+ * (short) byte count and then return an error in the subsequent call.
+ * timestamp is only sent driver is session has been opened with timestamp flag
+ * otherwise its ignored.
+ *
+ * If set_callback() has previously been called to enable non-blocking mode
+ * the write() is not allowed to block. It must write only the number of
+ * bytes that currently fit in the driver/hardware buffer and then return
+ * this byte count. If this is less than the requested write size the
+ * callback function must be called when more space is available in the
+ * driver/hardware buffer.
+ */
+ssize_t qahw_out_write_l(qahw_stream_handle_t *stream,
+ qahw_out_buffer_t *out_buf);
+
+/*
+ * return the number of audio frames written by the audio dsp to DAC since
+ * the output has exited standby
+ */
+int qahw_out_get_render_position_l(const qahw_stream_handle_t *stream,
+ uint32_t *dsp_frames);
+
+/*
+ * set the callback function for notifying completion of non-blocking
+ * write and drain.
+ * Calling this function implies that all future rite() and drain()
+ * must be non-blocking and use the callback to signal completion.
+ */
+int qahw_out_set_callback_l(qahw_stream_handle_t *stream,
+ qahw_stream_callback_t callback,
+ void *cookie);
+
+/*
+ * Notifies to the audio driver to stop playback however the queued buffers are
+ * retained by the hardware. Useful for implementing pause/resume. Empty implementation
+ * if not supported however should be implemented for hardware with non-trivial
+ * latency. In the pause state audio hardware could still be using power. User may
+ * consider calling suspend after a timeout.
+ *
+ * Implementation of this function is mandatory for offloaded playback.
+ */
+int qahw_out_pause_l(qahw_stream_handle_t *out_handle);
+
+/*
+ * Notifies to the audio driver to resume playback following a pause.
+ * Returns error if called without matching pause.
+ *
+ * Implementation of this function is mandatory for offloaded playback.
+ */
+int qahw_out_resume_l(qahw_stream_handle_t *out_handle);
+
+/*
+ * Requests notification when data buffered by the driver/hardware has
+ * been played. If set_callback() has previously been called to enable
+ * non-blocking mode, the drain() must not block, instead it should return
+ * quickly and completion of the drain is notified through the callback.
+ * If set_callback() has not been called, the drain() must block until
+ * completion.
+ * If type==AUDIO_DRAIN_ALL, the drain completes when all previously written
+ * data has been played.
+ * If type==AUDIO_DRAIN_EARLY_NOTIFY, the drain completes shortly before all
+ * data for the current track has played to allow time for the framework
+ * to perform a gapless track switch.
+ *
+ * Drain must return immediately on stop() and flush() call
+ *
+ * Implementation of this function is mandatory for offloaded playback.
+ */
+int qahw_out_drain_l(qahw_stream_handle_t *out_handle, qahw_drain_type_t type);
+
+/*
+ * Notifies to the audio driver to flush the queued data. Stream must already
+ * be paused before calling flush().
+ *
+ * Implementation of this function is mandatory for offloaded playback.
+ */
+int qahw_out_flush_l(qahw_stream_handle_t *out_handle);
+
+/*
+ * Return a recent count of the number of audio frames presented to an external observer.
+ * This excludes frames which have been written but are still in the pipeline.
+ * The count is not reset to zero when output enters standby.
+ * Also returns the value of CLOCK_MONOTONIC as of this presentation count.
+ * The returned count is expected to be 'recent',
+ * but does not need to be the most recent possible value.
+ * However, the associated time should correspond to whatever count is returned.
+ * Example: assume that N+M frames have been presented, where M is a 'small' number.
+ * Then it is permissible to return N instead of N+M,
+ * and the timestamp should correspond to N rather than N+M.
+ * The terms 'recent' and 'small' are not defined.
+ * They reflect the quality of the implementation.
+ *
+ * 3.0 and higher only.
+ */
+int qahw_out_get_presentation_position_l(const qahw_stream_handle_t *out_handle,
+ uint64_t *frames, struct timespec *timestamp);
+
+/* Input stream specific APIs */
+
+/* This method creates and opens the audio hardware input stream */
+int qahw_open_input_stream_l(qahw_module_handle_t *hw_module,
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ struct audio_config *config,
+ qahw_stream_handle_t **stream_in,
+ audio_input_flags_t flags,
+ const char *address,
+ audio_source_t source);
+
+int qahw_close_input_stream_l(qahw_stream_handle_t *in_handle);
+
+/*
+ * Return the sampling rate in Hz - eg. 44100.
+ */
+uint32_t qahw_in_get_sample_rate_l(const qahw_stream_handle_t *in_handle);
+
+/*
+ * currently unused - use set_parameters with key
+ * QAHW_PARAMETER_STREAM_SAMPLING_RATE
+ */
+int qahw_in_set_sample_rate_l(qahw_stream_handle_t *in_handle, uint32_t rate);
+
+/*
+ * Return size of input/output buffer in bytes for this stream - eg. 4800.
+ * It should be a multiple of the frame size. See also get_input_buffer_size.
+ */
+size_t qahw_in_get_buffer_size_l(const qahw_stream_handle_t *in_handle);
+
+/*
+ * Return the channel mask -
+ * e.g. AUDIO_CHANNEL_OUT_STEREO or AUDIO_CHANNEL_IN_STEREO
+ */
+audio_channel_mask_t qahw_in_get_channels_l(const qahw_stream_handle_t *in_handle);
+
+/*
+ * Return the audio format - e.g. AUDIO_FORMAT_PCM_16_BIT
+ */
+audio_format_t qahw_in_get_format_l(const qahw_stream_handle_t *in_handle);
+
+/*
+ * currently unused - use set_parameters with key
+ * QAHW_PARAMETER_STREAM_FORMAT
+ */
+int qahw_in_set_format_l(qahw_stream_handle_t *in_handle, audio_format_t format);
+
+/*
+ * Put the audio hardware input/output into standby mode.
+ * Driver should exit from standby mode at the next I/O operation.
+ * Returns 0 on success and <0 on failure.
+ */
+int qahw_in_standby_l(qahw_stream_handle_t *in_handle);
+
+/*
+ * set/get audio stream parameters. The function accepts a list of
+ * parameter key value pairs in the form: key1=value1;key2=value2;...
+ *
+ * Some keys are reserved for standard parameters (See AudioParameter class)
+ *
+ * If the implementation does not accept a parameter change while
+ * the output is active but the parameter is acceptable otherwise, it must
+ * return -ENOSYS.
+ *
+ * The audio flinger will put the stream in standby and then change the
+ * parameter value.
+ */
+int qahw_in_set_parameters_l(qahw_stream_handle_t *in_handle, const char *kv_pairs);
+
+/*
+ * Returns a pointer to a heap allocated string. The caller is responsible
+ * for freeing the memory for it using free().
+ */
+char* qahw_in_get_parameters_l(const qahw_stream_handle_t *in_handle,
+ const char *keys);
+/*
+ * Read audio buffer in from audio driver. Returns number of bytes read, or a
+ * negative status_t. meta_data structure is filled buffer pointer, start
+ * offset and valid catpure timestamp (if session is opened with timetamp flag)
+ * and buffer. if at least one frame was read prior to the error,
+ * read should return that byte count and then return an error in the
+ * subsequent call.
+ */
+ssize_t qahw_in_read_l(qahw_stream_handle_t *in_handle,
+ qahw_in_buffer_t *in_buf);
+/*
+ * Return the amount of input frames lost in the audio driver since the
+ * last call of this function.
+ * Audio driver is expected to reset the value to 0 and restart counting
+ * upon returning the current value by this function call.
+ * Such loss typically occurs when the user space process is blocked
+ * longer than the capacity of audio driver buffers.
+ *
+ * Unit: the number of input audio frames
+ */
+uint32_t qahw_in_get_input_frames_lost_l(qahw_stream_handle_t *in_handle);
+
+/*
+ * Return a recent count of the number of audio frames received and
+ * the clock time associated with that frame count.
+ *
+ * frames is the total frame count received. This should be as early in
+ * the capture pipeline as possible. In general,
+ * frames should be non-negative and should not go "backwards".
+ *
+ * time is the clock MONOTONIC time when frames was measured. In general,
+ * time should be a positive quantity and should not go "backwards".
+ *
+ * The status returned is 0 on success, -ENOSYS if the device is not
+ * ready/available, or -EINVAL if the arguments are null or otherwise invalid.
+ */
+int qahw_in_get_capture_position_l(const qahw_stream_handle_t *in_handle,
+ int64_t *frames, int64_t *time);
+
+/* Module specific APIs */
+
+/* convenience API for opening and closing an audio HAL module */
+qahw_module_handle_t *qahw_load_module_l(const char *hw_module_id);
+
+int qahw_unload_module_l(qahw_module_handle_t *hw_module);
+
+/*
+ * check to see if the audio hardware interface has been initialized.
+ * returns 0 on success, -ENODEV on failure.
+ */
+int qahw_init_check_l(const qahw_module_handle_t *hw_module);
+
+/* set the audio volume of a voice call. Range is between 0.0 and 1.0 */
+int qahw_set_voice_volume_l(qahw_module_handle_t *hw_module, float volume);
+
+/*
+ * set_mode is called when the audio mode changes. AUDIO_MODE_NORMAL mode
+ * is for standard audio playback, AUDIO_MODE_RINGTONE when a ringtone is
+ * playing, and AUDIO_MODE_IN_CALL when a call is in progress.
+ */
+int qahw_set_mode_l(qahw_module_handle_t *hw_module, audio_mode_t mode);
+
+/* Mute/unmute mic during voice/voip/HFP call */
+int qahw_set_mic_mute_l(qahw_module_handle_t *hw_module, bool state);
+
+/* Get mute/unmute status of mic during voice call */
+int qahw_get_mic_mute_l(qahw_module_handle_t *hw_module, bool *state);
+
+/* set/get global audio parameters */
+int qahw_set_parameters_l(qahw_module_handle_t *hw_module, const char *kv_pairs);
+
+/*
+ * Returns a pointer to a heap allocated string. The caller is responsible
+ * for freeing the memory for it using free().
+ */
+char* qahw_get_parameters_l(const qahw_module_handle_t *hw_module,
+ const char *keys);
+
+/* Returns audio input buffer size according to parameters passed or
+ * 0 if one of the parameters is not supported.
+ * See also get_buffer_size which is for a particular stream.
+ */
+size_t qahw_get_input_buffer_size_l(const qahw_module_handle_t *hw_module,
+ const struct audio_config *config);
+
+/*returns current QTI HAL version */
+int qahw_get_version_l();
+
+/* Api to implement get parameters based on keyword param_id
+ * and store data in payload.
+ */
+int qahw_get_param_data_l(const qahw_module_handle_t *hw_module,
+ qahw_param_id param_id,
+ qahw_param_payload *payload);
+
+/* Api to implement set parameters based on keyword param_id
+ * and data present in payload.
+ */
+int qahw_set_param_data_l(const qahw_module_handle_t *hw_module,
+ qahw_param_id param_id,
+ qahw_param_payload *payload);
+
+/* Creates an audio patch between several source and sink ports.
+ * The handle is allocated by the HAL and should be unique for this
+ * audio HAL module.
+ */
+int qahw_create_audio_patch_l(qahw_module_handle_t *hw_module,
+ unsigned int num_sources,
+ const struct audio_port_config *sources,
+ unsigned int num_sinks,
+ const struct audio_port_config *sinks,
+ audio_patch_handle_t *handle);
+
+/* Release an audio patch */
+int qahw_release_audio_patch_l(qahw_module_handle_t *hw_module,
+ audio_patch_handle_t handle);
+/* Fills the list of supported attributes for a given audio port.
+ * As input, "port" contains the information (type, role, address etc...)
+ * needed by the HAL to identify the port.
+ * As output, "port" contains possible attributes (sampling rates, formats,
+ * channel masks, gain controllers...) for this port.
+ */
+int qahw_get_audio_port_l(qahw_module_handle_t *hw_module,
+ struct audio_port *port);
+
+/* Set audio port configuration */
+int qahw_set_audio_port_config_l(qahw_module_handle_t *hw_module,
+ const struct audio_port_config *config);
+#ifdef __cplusplus
+}
+#endif
+
+__END_DECLS
+
+#endif // QTI_AUDIO_QAHW_H
diff --git a/qahw/inc/qahw_defs.h b/qahw/inc/qahw_defs.h
new file mode 100644
index 00000000..c13a1a44
--- /dev/null
+++ b/qahw/inc/qahw_defs.h
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 2011 The Android Open Source Project *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/cdefs.h>
+#include <stdint.h>
+
+#ifndef QTI_AUDIO_HAL_DEFS_H
+#define QTI_AUDIO_HAL_DEFS_H
+
+__BEGIN_DECLS
+
+/**************************************/
+
+/**
+ * standard audio parameters that the HAL may need to handle
+ */
+
+/**
+ * audio device parameters
+ */
+
+/* BT SCO Noise Reduction + Echo Cancellation parameters */
+#define QAHW_PARAMETER_KEY_BT_NREC "bt_headset_nrec"
+#define QAHW_PARAMETER_VALUE_ON "on"
+#define QAHW_PARAMETER_VALUE_OFF "off"
+
+/* TTY mode selection */
+#define QAHW_PARAMETER_KEY_TTY_MODE "tty_mode"
+#define QAHW_PARAMETER_VALUE_TTY_OFF "tty_off"
+#define QAHW_PARAMETER_VALUE_TTY_VCO "tty_vco"
+#define QAHW_PARAMETER_VALUE_TTY_HCO "tty_hco"
+#define QAHW_PARAMETER_VALUE_TTY_FULL "tty_full"
+
+/* Hearing Aid Compatibility - Telecoil (HAC-T) mode on/off
+ Strings must be in sync with CallFeaturesSetting.java */
+#define QAHW_PARAMETER_KEY_HAC "HACSetting"
+#define QAHW_PARAMETER_VALUE_HAC_ON "ON"
+#define QAHW_PARAMETER_VALUE_HAC_OFF "OFF"
+
+/* A2DP sink address set by framework */
+#define QAHW_PARAMETER_A2DP_SINK_ADDRESS "a2dp_sink_address"
+
+/* A2DP source address set by framework */
+#define QAHW_PARAMETER_A2DP_SOURCE_ADDRESS "a2dp_source_address"
+
+/* Screen state */
+#define QAHW_PARAMETER_KEY_SCREEN_STATE "screen_state"
+
+/* Bluetooth SCO wideband */
+#define QAHW_PARAMETER_KEY_BT_SCO_WB "bt_wbs"
+
+/* Get a new HW synchronization source identifier.
+ * Return a valid source (positive integer) or AUDIO_HW_SYNC_INVALID if an error occurs
+ * or no HW sync is available. */
+#define QAHW_PARAMETER_HW_AV_SYNC "hw_av_sync"
+
+/**
+ * audio stream parameters
+ */
+
+#define QAHW_PARAMETER_STREAM_ROUTING "routing" /* audio_devices_t */
+#define QAHW_PARAMETER_STREAM_FORMAT "format" /* audio_format_t */
+#define QAHW_PARAMETER_STREAM_CHANNELS "channels" /* audio_channel_mask_t */
+#define QAHW_PARAMETER_STREAM_FRAME_COUNT "frame_count" /* size_t */
+#define QAHW_PARAMETER_STREAM_INPUT_SOURCE "input_source" /* audio_source_t */
+#define QAHW_PARAMETER_STREAM_SAMPLING_RATE "sampling_rate" /* uint32_t */
+
+#define QAHW_PARAMETER_DEVICE_CONNECT "connect" /* audio_devices_t */
+#define QAHW_PARAMETER_DEVICE_DISCONNECT "disconnect" /* audio_devices_t */
+
+/* Query supported formats. The response is a '|' separated list of strings from
+ * audio_format_t enum e.g: "sup_formats=AUDIO_FORMAT_PCM_16_BIT" */
+#define QAHW_PARAMETER_STREAM_SUP_FORMATS "sup_formats"
+
+/* Query supported channel masks. The response is a '|' separated list of
+ * strings from audio_channel_mask_t enum
+ * e.g: "sup_channels=AUDIO_CHANNEL_OUT_STEREO|AUDIO_CHANNEL_OUT_MONO" */
+#define QAHW_PARAMETER_STREAM_SUP_CHANNELS "sup_channels"
+
+/* Query supported sampling rates. The response is a '|' separated list of
+ * integer values e.g: "sup_sampling_rates=44100|48000" */
+#define QAHW_PARAMETER_STREAM_SUP_SAMPLING_RATES "sup_sampling_rates"
+
+/* Set the HW synchronization source for an output stream. */
+#define QAHW_PARAMETER_STREAM_HW_AV_SYNC "hw_av_sync"
+
+/* Enable mono audio playback if 1, else should be 0. */
+#define QAHW_PARAMETER_MONO_OUTPUT "mono_output"
+
+/**
+ * audio codec parameters
+ */
+
+#define QAHW_OFFLOAD_CODEC_PARAMS "music_offload_codec_param"
+#define QAHW_OFFLOAD_CODEC_BIT_PER_SAMPLE "music_offload_bit_per_sample"
+#define QAHW_OFFLOAD_CODEC_BIT_RATE "music_offload_bit_rate"
+#define QAHW_OFFLOAD_CODEC_AVG_BIT_RATE "music_offload_avg_bit_rate"
+#define QAHW_OFFLOAD_CODEC_ID "music_offload_codec_id"
+#define QAHW_OFFLOAD_CODEC_BLOCK_ALIGN "music_offload_block_align"
+#define QAHW_OFFLOAD_CODEC_SAMPLE_RATE "music_offload_sample_rate"
+#define QAHW_OFFLOAD_CODEC_ENCODE_OPTION "music_offload_encode_option"
+#define QAHW_OFFLOAD_CODEC_NUM_CHANNEL "music_offload_num_channels"
+#define QAHW_OFFLOAD_CODEC_DOWN_SAMPLING "music_offload_down_sampling"
+#define QAHW_OFFLOAD_CODEC_DELAY_SAMPLES "delay_samples"
+#define QAHW_OFFLOAD_CODEC_PADDING_SAMPLES "padding_samples"
+
+/**
+ * extended audio codec parameters
+ */
+
+#define QAHW_OFFLOAD_CODEC_WMA_FORMAT_TAG "music_offload_wma_format_tag"
+#define QAHW_OFFLOAD_CODEC_WMA_BLOCK_ALIGN "music_offload_wma_block_align"
+#define QAHW_OFFLOAD_CODEC_WMA_BIT_PER_SAMPLE "music_offload_wma_bit_per_sample"
+#define QAHW_OFFLOAD_CODEC_WMA_CHANNEL_MASK "music_offload_wma_channel_mask"
+#define QAHW_OFFLOAD_CODEC_WMA_ENCODE_OPTION "music_offload_wma_encode_option"
+#define QAHW_OFFLOAD_CODEC_WMA_ENCODE_OPTION1 "music_offload_wma_encode_option1"
+#define QAHW_OFFLOAD_CODEC_WMA_ENCODE_OPTION2 "music_offload_wma_encode_option2"
+
+#define QAHW_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE "music_offload_flac_min_blk_size"
+#define QAHW_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE "music_offload_flac_max_blk_size"
+#define QAHW_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE "music_offload_flac_min_frame_size"
+#define QAHW_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE "music_offload_flac_max_frame_size"
+
+#define QAHW_OFFLOAD_CODEC_ALAC_FRAME_LENGTH "music_offload_alac_frame_length"
+#define QAHW_OFFLOAD_CODEC_ALAC_COMPATIBLE_VERSION "music_offload_alac_compatible_version"
+#define QAHW_OFFLOAD_CODEC_ALAC_BIT_DEPTH "music_offload_alac_bit_depth"
+#define QAHW_OFFLOAD_CODEC_ALAC_PB "music_offload_alac_pb"
+#define QAHW_OFFLOAD_CODEC_ALAC_MB "music_offload_alac_mb"
+#define QAHW_OFFLOAD_CODEC_ALAC_KB "music_offload_alac_kb"
+#define QAHW_OFFLOAD_CODEC_ALAC_NUM_CHANNELS "music_offload_alac_num_channels"
+#define QAHW_OFFLOAD_CODEC_ALAC_MAX_RUN "music_offload_alac_max_run"
+#define QAHW_OFFLOAD_CODEC_ALAC_MAX_FRAME_BYTES "music_offload_alac_max_frame_bytes"
+#define QAHW_OFFLOAD_CODEC_ALAC_AVG_BIT_RATE "music_offload_alac_avg_bit_rate"
+#define QAHW_OFFLOAD_CODEC_ALAC_SAMPLING_RATE "music_offload_alac_sampling_rate"
+#define QAHW_OFFLOAD_CODEC_ALAC_CHANNEL_LAYOUT_TAG "music_offload_alac_channel_layout_tag"
+
+#define QAHW_OFFLOAD_CODEC_APE_COMPATIBLE_VERSION "music_offload_ape_compatible_version"
+#define QAHW_OFFLOAD_CODEC_APE_COMPRESSION_LEVEL "music_offload_ape_compression_level"
+#define QAHW_OFFLOAD_CODEC_APE_FORMAT_FLAGS "music_offload_ape_format_flags"
+#define QAHW_OFFLOAD_CODEC_APE_BLOCKS_PER_FRAME "music_offload_ape_blocks_per_frame"
+#define QAHW_OFFLOAD_CODEC_APE_FINAL_FRAME_BLOCKS "music_offload_ape_final_frame_blocks"
+#define QAHW_OFFLOAD_CODEC_APE_TOTAL_FRAMES "music_offload_ape_total_frames"
+#define QAHW_OFFLOAD_CODEC_APE_BITS_PER_SAMPLE "music_offload_ape_bits_per_sample"
+#define QAHW_OFFLOAD_CODEC_APE_NUM_CHANNELS "music_offload_ape_num_channels"
+#define QAHW_OFFLOAD_CODEC_APE_SAMPLE_RATE "music_offload_ape_sample_rate"
+#define QAHW_OFFLOAD_CODEC_APE_SEEK_TABLE_PRESENT "music_offload_seek_table_present"
+
+#define QAHW_OFFLOAD_CODEC_VORBIS_BITSTREAM_FMT "music_offload_vorbis_bitstream_fmt"
+
+/* Set or Query stream profile type */
+#define QAHW_PARAMETER_STREAM_PROFILE "audio_stream_profile"
+
+/* audio input flags for compress and timestamp mode.
+ * check other input flags defined in audio.h for conflicts
+ */
+#define QAHW_INPUT_FLAG_TIMESTAMP 0x80000000
+#define QAHW_INPUT_FLAG_COMPRESS 0x40000000
+
+/* Query fm volume */
+#define QAHW_PARAMETER_KEY_FM_VOLUME "fm_volume"
+
+/* Query if a2dp is supported */
+#define QAHW_PARAMETER_KEY_HANDLE_A2DP_DEVICE "isA2dpDeviceSupported"
+
+#define MAX_OUT_CHANNELS 8
+#define MAX_INP_CHANNELS 8
+
+#define QAHW_PCM_CHANNEL_FL 1 /* Front left channel. */
+#define QAHW_PCM_CHANNEL_FR 2 /* Front right channel. */
+#define QAHW_PCM_CHANNEL_FC 3 /* Front center channel. */
+#define QAHW_PCM_CHANNEL_LS 4 /* Left surround channel. */
+#define QAHW_PCM_CHANNEL_RS 5 /* Right surround channel. */
+#define QAHW_PCM_CHANNEL_LFE 6 /* Low frequency effect channel. */
+#define QAHW_PCM_CHANNEL_CS 7 /* Center surround channel; Rear center channel. */
+#define QAHW_PCM_CHANNEL_LB 8 /* Left back channel; Rear left channel. */
+#define QAHW_PCM_CHANNEL_RB 9 /* Right back channel; Rear right channel. */
+#define QAHW_PCM_CHANNEL_TS 10 /* Top surround channel. */
+#define QAHW_PCM_CHANNEL_CVH 11 /* Center vertical height channel. */
+#define QAHW_PCM_CHANNEL_MS 12 /* Mono surround channel. */
+#define QAHW_PCM_CHANNEL_FLC 13 /* Front left of center. */
+#define QAHW_PCM_CHANNEL_FRC 14 /* Front right of center. */
+#define QAHW_PCM_CHANNEL_RLC 15 /* Rear left of center. */
+#define QAHW_PCM_CHANNEL_RRC 16 /* Rear right of center. */
+
+/* type of asynchronous write callback events. Mutually exclusive */
+typedef enum {
+ QAHW_STREAM_CBK_EVENT_WRITE_READY, /* non blocking write completed */
+ QAHW_STREAM_CBK_EVENT_DRAIN_READY, /* drain completed */
+ QAHW_STREAM_CBK_EVENT_ERROR, /* stream hit some error */
+
+ QAHW_STREAM_CBK_EVENT_ADSP = 0x100 /* callback event from ADSP PP,
+ * corresponding payload will be
+ * sent as is to the client
+ */
+} qahw_stream_callback_event_t;
+
+typedef int qahw_stream_callback_t(qahw_stream_callback_event_t event,
+ void *param,
+ void *cookie);
+
+/* type of drain requested to audio_stream_out->drain(). Mutually exclusive */
+typedef enum {
+ QAHW_DRAIN_ALL, /* drain() returns when all data has been played */
+ QAHW_DRAIN_EARLY_NOTIFY /* drain() returns a short time before all data
+ from the current track has been played to
+ give time for gapless track switch */
+} qahw_drain_type_t;
+
+/* meta data flags */
+/*TBD: Extend this based on stb requirement*/
+typedef enum {
+ QAHW_META_DATA_FLAGS_NONE = 0,
+} qahw_meta_data_flags_t;
+
+typedef struct {
+ const void *buffer; /* write buffer pointer */
+ size_t bytes; /* size of buffer */
+ size_t offset; /* offset in buffer from where valid byte starts */
+ int64_t *timestamp; /* timestmap */
+ qahw_meta_data_flags_t flags; /* meta data flags */
+ uint32_t reserved[64]; /*reserved for future */
+} qahw_out_buffer_t;
+
+typedef struct {
+ void *buffer; /* read buffer pointer */
+ size_t bytes; /* size of buffer */
+ size_t offset; /* offset in buffer from where valid byte starts */
+ int64_t *timestamp; /* timestmap */
+ uint32_t reserved[64]; /*reserved for future */
+} qahw_in_buffer_t;
+
+#define MAX_SECTORS 8
+
+struct qahw_source_tracking_param {
+ uint8_t vad[MAX_SECTORS];
+ uint16_t doa_speech;
+ uint16_t doa_noise[3];
+ uint8_t polar_activity[360];
+};
+
+struct qahw_sound_focus_param {
+ uint16_t start_angle[MAX_SECTORS];
+ uint8_t enable[MAX_SECTORS];
+ uint16_t gain_step;
+};
+
+struct aptx_dec_bt_addr {
+ uint32_t nap;
+ uint32_t uap;
+ uint32_t lap;
+};
+
+struct qahw_aptx_dec_param {
+ struct aptx_dec_bt_addr bt_addr;
+};
+
+struct qahw_avt_device_drift_param {
+ /* Flag to indicate if resync is required on the client side for
+ * drift correction. Flag is set to TRUE for the first get_param response
+ * after device interface starts. This flag value can be used by client
+ * to identify if device interface restart has happened and if any
+ * re-sync is required at their end for drift correction.
+ */
+ uint32_t resync_flag;
+ /* Accumulated drift value in microseconds.
+ * Positive drift value indicates AV timer is running faster than device.
+ * Negative drift value indicates AV timer is running slower than device.
+ */
+ int32_t avt_device_drift_value;
+ /* 64-bit absolute timestamp of reference */
+ uint64_t ref_timer_abs_ts;
+};
+
+/*use these for setting infine window.i.e free run mode */
+#define QAHW_MAX_RENDER_START_WINDOW 0x8000000000000000
+#define QAHW_MAX_RENDER_END_WINDOW 0x7FFFFFFFFFFFFFFF
+
+struct qahw_out_render_window_param {
+ uint64_t render_ws; /* render window start value microseconds*/
+ uint64_t render_we; /* render window end value microseconds*/
+};
+
+struct qahw_out_start_delay_param {
+ uint64_t start_delay; /* session start delay in microseconds*/
+};
+
+struct qahw_out_enable_drift_correction {
+ bool enable; /* enable drift correction*/
+};
+
+struct qahw_out_correct_drift {
+ /*
+ * adjust time in microseconds, a positive value
+ * to advance the clock or a negative value to
+ * delay the clock.
+ */
+ int64_t adjust_time;
+};
+
+#define QAHW_MAX_ADSP_STREAM_CMD_PAYLOAD_LEN 512
+
+typedef enum {
+ QAHW_STREAM_PP_EVENT = 0,
+ QAHW_STREAM_ENCDEC_EVENT = 1,
+} qahw_event_id;
+
+/* payload format for HAL parameter
+ * QAHW_PARAM_ADSP_STREAM_CMD
+ */
+struct qahw_adsp_event {
+ qahw_event_id event_type; /* type of the event */
+ uint32_t payload_length; /* length in bytes of the payload */
+ void *payload; /* the actual payload */
+};
+
+struct qahw_out_channel_map_param {
+ uint8_t channels; /* Input Channels */
+ uint8_t channel_map[AUDIO_CHANNEL_COUNT_MAX]; /* Input Channel Map */
+};
+
+struct qahw_device_cfg_param {
+ uint32_t sample_rate;
+ uint32_t channels;
+ uint32_t bit_width;
+ audio_format_t format;
+ audio_devices_t device;
+ uint8_t channel_map[AUDIO_CHANNEL_COUNT_MAX];
+ uint16_t channel_allocation;
+};
+
+typedef struct qahw_mix_matrix_params {
+ uint16_t num_output_channels;
+ uint16_t num_input_channels;
+ uint8_t has_output_channel_map;
+ uint32_t output_channel_map[AUDIO_CHANNEL_COUNT_MAX];
+ uint8_t has_input_channel_map;
+ uint32_t input_channel_map[AUDIO_CHANNEL_COUNT_MAX];
+ uint8_t has_mixer_coeffs;
+ float mixer_coeffs[AUDIO_CHANNEL_COUNT_MAX][AUDIO_CHANNEL_COUNT_MAX];
+} qahw_mix_matrix_params_t;
+
+typedef union {
+ struct qahw_source_tracking_param st_params;
+ struct qahw_sound_focus_param sf_params;
+ struct qahw_aptx_dec_param aptx_params;
+ struct qahw_avt_device_drift_param drift_params;
+ struct qahw_out_render_window_param render_window_params;
+ struct qahw_out_start_delay_param start_delay;
+ struct qahw_out_enable_drift_correction drift_enable_param;
+ struct qahw_out_correct_drift drift_correction_param;
+ struct qahw_adsp_event adsp_event_params;
+ struct qahw_out_channel_map_param channel_map_params;
+ struct qahw_device_cfg_param device_cfg_params;
+ struct qahw_mix_matrix_params mix_matrix_params;
+} qahw_param_payload;
+
+typedef enum {
+ QAHW_PARAM_SOURCE_TRACK,
+ QAHW_PARAM_SOUND_FOCUS,
+ QAHW_PARAM_APTX_DEC,
+ QAHW_PARAM_AVT_DEVICE_DRIFT, /* PARAM to query AV timer vs device drift */
+ QAHW_PARAM_OUT_RENDER_WINDOW, /* PARAM to set render window */
+ QAHW_PARAM_OUT_START_DELAY, /* PARAM to set session start delay*/
+ /* enable adsp drift correction this must be called before out_write */
+ QAHW_PARAM_OUT_ENABLE_DRIFT_CORRECTION,
+ /* param to set drift value to be adjusted by dsp */
+ QAHW_PARAM_OUT_CORRECT_DRIFT,
+ QAHW_PARAM_ADSP_STREAM_CMD,
+ QAHW_PARAM_OUT_CHANNEL_MAP, /* PARAM to set i/p channel map */
+ QAHW_PARAM_DEVICE_CONFIG, /* PARAM to set device config */
+ QAHW_PARAM_OUT_MIX_MATRIX_PARAMS,
+ QAHW_PARAM_CH_MIX_MATRIX_PARAMS,
+} qahw_param_id;
+
+__END_DECLS
+
+#endif // QTI_AUDIO_HAL_DEFS_H
+
diff --git a/qahw/inc/qahw_effect_api.h b/qahw/inc/qahw_effect_api.h
new file mode 100644
index 00000000..de53cd3c
--- /dev/null
+++ b/qahw/inc/qahw_effect_api.h
@@ -0,0 +1,845 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef ANDROID_AUDIO_QAHW_EFFECT_H
+#define ANDROID_AUDIO_QAHW_EFFECT_H
+
+#include <errno.h>
+#include <stdint.h>
+#include <strings.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <cutils/bitops.h>
+
+#include <system/audio.h>
+
+#include "qahw.h"
+
+__BEGIN_DECLS
+
+#define QAHW_EFFECT_API_VERSION_0_0 QAHW_MAKE_API_VERSION(0, 0)
+#define QAHW_EFFECT_API_VERSION_MIN QAHW_EFFECT_API_VERSION_0_0
+
+/////////////////////////////////////////////////
+// Common Definitions
+/////////////////////////////////////////////////
+
+//
+//--- Effect descriptor structure qahw_effect_descriptor_t
+//
+
+// Unique effect ID (can be generated from the following site:
+// http://www.itu.int/ITU-T/asn1/uuid.html)
+// This format is used for both "type" and "uuid" fields of the effect descriptor structure.
+// - When used for effect type and the engine is implementing and effect corresponding to a standard
+// OpenSL ES interface, this ID must be the one defined in OpenSLES_IID.h for that interface.
+// - When used as uuid, it should be a unique UUID for this particular implementation.
+typedef struct qahw_effect_uuid_s {
+ uint32_t timeLow;
+ uint16_t timeMid;
+ uint16_t timeHiAndVersion;
+ uint16_t clockSeq;
+ uint8_t node[6];
+} qahw_effect_uuid_t;
+
+// Maximum length of character strings in structures defines by this API.
+#define QAHW_EFFECT_STRING_LEN_MAX 64
+
+// NULL UUID definition (matches SL_IID_NULL_)
+#define QAHW_EFFECT_UUID_INITIALIZER { 0xec7178ec, 0xe5e1, 0x4432, 0xa3f4, \
+ { 0x46, 0x57, 0xe6, 0x79, 0x52, 0x10 } }
+static const qahw_effect_uuid_t QAHW_EFFECT_UUID_NULL_ = QAHW_EFFECT_UUID_INITIALIZER;
+static const qahw_effect_uuid_t * const QAHW_EFFECT_UUID_NULL = &QAHW_EFFECT_UUID_NULL_;
+static const char * const QAHW_EFFECT_UUID_NULL_STR = "ec7178ec-e5e1-4432-a3f4-4657e6795210";
+
+
+// The effect descriptor contains necessary information to facilitate the enumeration of the effect
+// engines present in a library.
+typedef struct qahw_effect_descriptor_s {
+ qahw_effect_uuid_t type; // UUID of to the OpenSL ES interface implemented by this effect
+ qahw_effect_uuid_t uuid; // UUID for this particular implementation
+ uint32_t apiVersion; // Version of the effect control API implemented
+ uint32_t flags; // effect engine capabilities/requirements flags (see below)
+ uint16_t cpuLoad; // CPU load indication (see below)
+ uint16_t memoryUsage; // Data Memory usage (see below)
+ char name[QAHW_EFFECT_STRING_LEN_MAX]; // human readable effect name
+ char implementor[QAHW_EFFECT_STRING_LEN_MAX]; // human readable effect implementor name
+} qahw_effect_descriptor_t;
+
+#define QAHW_EFFECT_MAKE_API_VERSION(M, m) (((M)<<16) | ((m) & 0xFFFF))
+#define QAHW_EFFECT_API_VERSION_MAJOR(v) ((v)>>16)
+#define QAHW_EFFECT_API_VERSION_MINOR(v) ((m) & 0xFFFF)
+
+
+/////////////////////////////////////////////////
+// Effect control interface
+/////////////////////////////////////////////////
+
+// Effect control interface version 2.0
+#define QAHW_EFFECT_CONTROL_API_VERSION QAHW_EFFECT_MAKE_API_VERSION(2,0)
+
+typedef void* qahw_effect_handle_t;
+
+
+// Forward definition of type qahw_audio_buffer_t
+typedef struct qahw_audio_buffer_s qahw_audio_buffer_t;
+
+
+//
+//--- Standardized command codes for command() function
+//
+enum qahw_effect_command_e {
+ QAHW_EFFECT_CMD_INIT, // initialize effect engine
+ QAHW_EFFECT_CMD_SET_CONFIG, // configure effect engine (see effect_config_t)
+ QAHW_EFFECT_CMD_RESET, // reset effect engine
+ QAHW_EFFECT_CMD_ENABLE, // enable effect process
+ QAHW_EFFECT_CMD_DISABLE, // disable effect process
+ QAHW_EFFECT_CMD_SET_PARAM, // set parameter immediately (see effect_param_t)
+ QAHW_EFFECT_CMD_SET_PARAM_DEFERRED, // set parameter deferred
+ QAHW_EFFECT_CMD_SET_PARAM_COMMIT, // commit previous set parameter deferred
+ QAHW_EFFECT_CMD_GET_PARAM, // get parameter
+ QAHW_EFFECT_CMD_SET_DEVICE, // set audio device (see audio.h, audio_devices_t)
+ QAHW_EFFECT_CMD_SET_VOLUME, // set volume
+ QAHW_EFFECT_CMD_SET_AUDIO_MODE, // set the audio mode (normal, ring, ...)
+ QAHW_EFFECT_CMD_SET_CONFIG_REVERSE, // configure effect engine reverse stream
+ // (see effect_config_t)
+ QAHW_EFFECT_CMD_SET_INPUT_DEVICE, // set capture device (see audio.h, audio_devices_t)
+ QAHW_EFFECT_CMD_GET_CONFIG, // read effect engine configuration
+ QAHW_EFFECT_CMD_GET_CONFIG_REVERSE, // read configure effect engine reverse stream
+ // configuration
+ QAHW_EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS, // get all supported configurations for
+ // a feature.
+ QAHW_EFFECT_CMD_GET_FEATURE_CONFIG, // get current feature configuration
+ QAHW_EFFECT_CMD_SET_FEATURE_CONFIG, // set current feature configuration
+ QAHW_EFFECT_CMD_SET_AUDIO_SOURCE, // set the audio source (see audio.h, audio_source_t)
+ QAHW_EFFECT_CMD_OFFLOAD, // set if effect thread is an offload one,
+ // send the ioHandle of the effect thread
+ QAHW_EFFECT_CMD_FIRST_PROPRIETARY = 0x10000 // first proprietary command code
+};
+
+//==================================================================================================
+// command: QAHW_EFFECT_CMD_INIT
+//--------------------------------------------------------------------------------------------------
+// description:
+// Initialize effect engine: All configurations return to default
+//--------------------------------------------------------------------------------------------------
+// command format:
+// size: 0
+// data: N/A
+//--------------------------------------------------------------------------------------------------
+// reply format:
+// size: sizeof(int)
+// data: status
+//==================================================================================================
+// command: QAHW_EFFECT_CMD_SET_CONFIG
+//--------------------------------------------------------------------------------------------------
+// description:
+// Apply new audio parameters configurations for input and output buffers
+//--------------------------------------------------------------------------------------------------
+// command format:
+// size: sizeof(effect_config_t)
+// data: effect_config_t
+//--------------------------------------------------------------------------------------------------
+// reply format:
+// size: sizeof(int)
+// data: status
+//==================================================================================================
+// command: QAHW_EFFECT_CMD_RESET
+//--------------------------------------------------------------------------------------------------
+// description:
+// Reset the effect engine. Keep configuration but resets state and buffer content
+//--------------------------------------------------------------------------------------------------
+// command format:
+// size: 0
+// data: N/A
+//--------------------------------------------------------------------------------------------------
+// reply format:
+// size: 0
+// data: N/A
+//==================================================================================================
+// command: QAHW_EFFECT_CMD_ENABLE
+//--------------------------------------------------------------------------------------------------
+// description:
+// Enable the process. Called by the framework before the first call to process()
+//--------------------------------------------------------------------------------------------------
+// command format:
+// size: 0
+// data: N/A
+//--------------------------------------------------------------------------------------------------
+// reply format:
+// size: sizeof(int)
+// data: status
+//==================================================================================================
+// command: QAHW_EFFECT_CMD_DISABLE
+//--------------------------------------------------------------------------------------------------
+// description:
+// Disable the process. Called by the framework after the last call to process()
+//--------------------------------------------------------------------------------------------------
+// command format:
+// size: 0
+// data: N/A
+//--------------------------------------------------------------------------------------------------
+// reply format:
+// size: sizeof(int)
+// data: status
+//==================================================================================================
+// command: QAHW_EFFECT_CMD_SET_PARAM
+//--------------------------------------------------------------------------------------------------
+// description:
+// Set a parameter and apply it immediately
+//--------------------------------------------------------------------------------------------------
+// command format:
+// size: sizeof(effect_param_t) + size of param and value
+// data: effect_param_t + param + value. See effect_param_t definition below for value offset
+//--------------------------------------------------------------------------------------------------
+// reply format:
+// size: sizeof(int)
+// data: status
+//==================================================================================================
+// command: QAHW_EFFECT_CMD_SET_PARAM_DEFERRED
+//--------------------------------------------------------------------------------------------------
+// description:
+// Set a parameter but apply it only when receiving QAHW_EFFECT_CMD_SET_PARAM_COMMIT command
+//--------------------------------------------------------------------------------------------------
+// command format:
+// size: sizeof(effect_param_t) + size of param and value
+// data: effect_param_t + param + value. See effect_param_t definition below for value offset
+//--------------------------------------------------------------------------------------------------
+// reply format:
+// size: 0
+// data: N/A
+//==================================================================================================
+// command: QAHW_EFFECT_CMD_SET_PARAM_COMMIT
+//--------------------------------------------------------------------------------------------------
+// description:
+// Apply all previously received QAHW_EFFECT_CMD_SET_PARAM_DEFERRED commands
+//--------------------------------------------------------------------------------------------------
+// command format:
+// size: 0
+// data: N/A
+//--------------------------------------------------------------------------------------------------
+// reply format:
+// size: sizeof(int)
+// data: status
+//==================================================================================================
+// command: QAHW_EFFECT_CMD_GET_PARAM
+//--------------------------------------------------------------------------------------------------
+// description:
+// Get a parameter value
+//--------------------------------------------------------------------------------------------------
+// command format:
+// size: sizeof(effect_param_t) + size of param
+// data: effect_param_t + param
+//--------------------------------------------------------------------------------------------------
+// reply format:
+// size: sizeof(effect_param_t) + size of param and value
+// data: effect_param_t + param + value. See effect_param_t definition below for value offset
+//==================================================================================================
+// command: QAHW_EFFECT_CMD_SET_DEVICE
+//--------------------------------------------------------------------------------------------------
+// description:
+// Set the rendering device the audio output path is connected to. See audio.h, audio_devices_t
+// for device values.
+// The effect implementation must set QAHW_EFFECT_FLAG_DEVICE_IND flag in its descriptor to
+// receive this command when the device changes
+//--------------------------------------------------------------------------------------------------
+// command format:
+// size: sizeof(uint32_t)
+// data: uint32_t
+//--------------------------------------------------------------------------------------------------
+// reply format:
+// size: 0
+// data: N/A
+//==================================================================================================
+// command: QAHW_EFFECT_CMD_SET_VOLUME
+//--------------------------------------------------------------------------------------------------
+// description:
+// Set and get volume. Used by audio framework to delegate volume control to effect engine.
+// The effect implementation must set QAHW_EFFECT_FLAG_VOLUME_IND or QAHW_EFFECT_FLAG_VOLUME_CTRL
+// flag in its descriptor to receive this command before every call to process() function
+// If QAHW_EFFECT_FLAG_VOLUME_CTRL flag is set in the effect descriptor, the effect engine must
+// return the volume that should be applied before the effect is processed. The overall volume
+// (the volume actually applied by the effect engine multiplied by the returned value) should
+// match the value indicated in the command.
+//--------------------------------------------------------------------------------------------------
+// command format:
+// size: n * sizeof(uint32_t)
+// data: volume for each channel defined in effect_config_t for output buffer expressed in
+// 8.24 fixed point format
+//--------------------------------------------------------------------------------------------------
+// reply format:
+// size: n * sizeof(uint32_t) / 0
+// data: - if QAHW_EFFECT_FLAG_VOLUME_CTRL is set in effect descriptor:
+// volume for each channel defined in effect_config_t for output buffer expressed in
+// 8.24 fixed point format
+// - if QAHW_EFFECT_FLAG_VOLUME_CTRL is not set in effect descriptor:
+// N/A
+// It is legal to receive a null pointer as pReplyData in which case the effect framework has
+// delegated volume control to another effect
+//==================================================================================================
+// command: QAHW_EFFECT_CMD_SET_AUDIO_MODE
+//--------------------------------------------------------------------------------------------------
+// description:
+// Set the audio mode. The effect implementation must set QAHW_EFFECT_FLAG_AUDIO_MODE_IND flag
+// in its descriptor to receive this command when the audio mode changes.
+//--------------------------------------------------------------------------------------------------
+// command format:
+// size: sizeof(uint32_t)
+// data: audio_mode_t
+//--------------------------------------------------------------------------------------------------
+// reply format:
+// size: 0
+// data: N/A
+//==================================================================================================
+// command: QAHW_EFFECT_CMD_SET_CONFIG_REVERSE
+//--------------------------------------------------------------------------------------------------
+// description:
+// Apply new audio parameters configurations for input and output buffers of reverse stream.
+// An example of reverse stream is the echo reference supplied to an Acoustic Echo Canceler.
+//--------------------------------------------------------------------------------------------------
+// command format:
+// size: sizeof(effect_config_t)
+// data: effect_config_t
+//--------------------------------------------------------------------------------------------------
+// reply format:
+// size: sizeof(int)
+// data: status
+//==================================================================================================
+// command: QAHW_EFFECT_CMD_SET_INPUT_DEVICE
+//--------------------------------------------------------------------------------------------------
+// description:
+// Set the capture device the audio input path is connected to. See audio.h, audio_devices_t
+// for device values.
+// The effect implementation must set QAHW_EFFECT_FLAG_DEVICE_IND flag in its descriptor to
+// receive this command when the device changes
+//--------------------------------------------------------------------------------------------------
+// command format:
+// size: sizeof(uint32_t)
+// data: uint32_t
+//--------------------------------------------------------------------------------------------------
+// reply format:
+// size: 0
+// data: N/A
+//==================================================================================================
+// command: QAHW_EFFECT_CMD_GET_CONFIG
+//--------------------------------------------------------------------------------------------------
+// description:
+// Read audio parameters configurations for input and output buffers
+//--------------------------------------------------------------------------------------------------
+// command format:
+// size: 0
+// data: N/A
+//--------------------------------------------------------------------------------------------------
+// reply format:
+// size: sizeof(effect_config_t)
+// data: effect_config_t
+//==================================================================================================
+// command: QAHW_EFFECT_CMD_GET_CONFIG_REVERSE
+//--------------------------------------------------------------------------------------------------
+// description:
+// Read audio parameters configurations for input and output buffers of reverse stream
+//--------------------------------------------------------------------------------------------------
+// command format:
+// size: 0
+// data: N/A
+//--------------------------------------------------------------------------------------------------
+// reply format:
+// size: sizeof(effect_config_t)
+// data: effect_config_t
+//==================================================================================================
+// command: QAHW_EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS
+//--------------------------------------------------------------------------------------------------
+// description:
+// Queries for supported configurations for a particular feature (e.g. get the supported
+// combinations of main and auxiliary channels for a noise suppressor).
+// The command parameter is the feature identifier (See effect_feature_e for a list of defined
+// features) followed by the maximum number of configuration descriptor to return.
+// The reply is composed of:
+// - status (uint32_t):
+// - 0 if feature is supported
+// - -ENOSYS if the feature is not supported,
+// - -ENOMEM if the feature is supported but the total number of supported configurations
+// exceeds the maximum number indicated by the caller.
+// - total number of supported configurations (uint32_t)
+// - an array of configuration descriptors.
+// The actual number of descriptors returned must not exceed the maximum number indicated by
+// the caller.
+//--------------------------------------------------------------------------------------------------
+// command format:
+// size: 2 x sizeof(uint32_t)
+// data: effect_feature_e + maximum number of configurations to return
+//--------------------------------------------------------------------------------------------------
+// reply format:
+// size: 2 x sizeof(uint32_t) + n x sizeof (<config descriptor>)
+// data: status + total number of configurations supported + array of n config descriptors
+//==================================================================================================
+// command: QAHW_EFFECT_CMD_GET_FEATURE_CONFIG
+//--------------------------------------------------------------------------------------------------
+// description:
+// Retrieves current configuration for a given feature.
+// The reply status is:
+// - 0 if feature is supported
+// - -ENOSYS if the feature is not supported,
+//--------------------------------------------------------------------------------------------------
+// command format:
+// size: sizeof(uint32_t)
+// data: effect_feature_e
+//--------------------------------------------------------------------------------------------------
+// reply format:
+// size: sizeof(uint32_t) + sizeof (<config descriptor>)
+// data: status + config descriptor
+//==================================================================================================
+// command: QAHW_EFFECT_CMD_SET_FEATURE_CONFIG
+//--------------------------------------------------------------------------------------------------
+// description:
+// Sets current configuration for a given feature.
+// The reply status is:
+// - 0 if feature is supported
+// - -ENOSYS if the feature is not supported,
+// - -EINVAL if the configuration is invalid
+//--------------------------------------------------------------------------------------------------
+// command format:
+// size: sizeof(uint32_t) + sizeof (<config descriptor>)
+// data: effect_feature_e + config descriptor
+//--------------------------------------------------------------------------------------------------
+// reply format:
+// size: sizeof(uint32_t)
+// data: status
+//==================================================================================================
+// command: QAHW_EFFECT_CMD_SET_AUDIO_SOURCE
+//--------------------------------------------------------------------------------------------------
+// description:
+// Set the audio source the capture path is configured for (Camcorder, voice recognition...).
+// See audio.h, audio_source_t for values.
+//--------------------------------------------------------------------------------------------------
+// command format:
+// size: sizeof(uint32_t)
+// data: uint32_t
+//--------------------------------------------------------------------------------------------------
+// reply format:
+// size: 0
+// data: N/A
+//==================================================================================================
+// command: QAHW_EFFECT_CMD_OFFLOAD
+//--------------------------------------------------------------------------------------------------
+// description:
+// 1.indicate if the playback thread the effect is attached to is offloaded or not
+// 2.update the io handle of the playback thread the effect is attached to
+//--------------------------------------------------------------------------------------------------
+// command format:
+// size: sizeof(effect_offload_param_t)
+// data: effect_offload_param_t
+//--------------------------------------------------------------------------------------------------
+// reply format:
+// size: sizeof(uint32_t)
+// data: uint32_t
+//--------------------------------------------------------------------------------------------------
+// command: QAHW_EFFECT_CMD_FIRST_PROPRIETARY
+//--------------------------------------------------------------------------------------------------
+// description:
+// All proprietary effect commands must use command codes above this value. The size and format of
+// command and response fields is free in this case
+//==================================================================================================
+
+
+// Audio buffer descriptor used by process(), bufferProvider() functions and buffer_config_t
+// structure. Multi-channel audio is always interleaved. The channel order is from LSB to MSB with
+// regard to the channel mask definition in audio.h, audio_channel_mask_t e.g :
+// Stereo: left, right
+// 5 point 1: front left, front right, front center, low frequency, back left, back right
+// The buffer size is expressed in frame count, a frame being composed of samples for all
+// channels at a given time. Frame size for unspecified format (AUDIO_FORMAT_OTHER) is 8 bit by
+// definition
+struct qahw_audio_buffer_s {
+ size_t frameCount; // number of frames in buffer
+ union {
+ void* raw; // raw pointer to start of buffer
+ int32_t* s32; // pointer to signed 32 bit data at start of buffer
+ int16_t* s16; // pointer to signed 16 bit data at start of buffer
+ uint8_t* u8; // pointer to unsigned 8 bit data at start of buffer
+ };
+};
+
+// The buffer_provider_s structure contains functions that can be used
+// by the effect engine process() function to query and release input
+// or output audio buffer.
+// The getBuffer() function is called to retrieve a buffer where data
+// should read from or written to by process() function.
+// The releaseBuffer() function MUST be called when the buffer retrieved
+// with getBuffer() is not needed anymore.
+// The process function should use the buffer provider mechanism to retrieve
+// input or output buffer if the in_buffer or out_buffer passed as argument is NULL
+// and the buffer configuration (buffer_config_t) given by the QAHW_EFFECT_CMD_SET_CONFIG
+// command did not specify an audio buffer.
+
+typedef int32_t (* qahw_buffer_function_t)(void *cookie, qahw_audio_buffer_t *buffer);
+
+typedef struct qahw_buffer_provider_s {
+ qahw_buffer_function_t getBuffer; // retrieve next buffer
+ qahw_buffer_function_t releaseBuffer; // release used buffer
+ void *cookie; // for use by client of buffer provider functions
+} qahw_buffer_provider_t;
+
+
+// The qahw_buffer_config_s structure specifies the input or output audio format
+// to be used by the effect engine. It is part of the effect_config_t
+// structure that defines both input and output buffer configurations and is
+// passed by the QAHW_EFFECT_CMD_SET_CONFIG or QAHW_EFFECT_CMD_SET_CONFIG_REVERSE command.
+typedef struct qahw_buffer_config_s {
+ qahw_audio_buffer_t buffer; // buffer for use by process() function if not passed explicitly
+ uint32_t samplingRate; // sampling rate
+ uint32_t channels; // channel mask (see audio_channel_mask_t in audio.h)
+ qahw_buffer_provider_t bufferProvider; // buffer provider
+ uint8_t format; // Audio format (see audio_format_t in audio.h)
+ uint8_t accessMode; // read/write or accumulate in buffer (qahw_effect_buffer_access_e)
+ uint16_t mask; // indicates which of the above fields is valid
+} qahw_buffer_config_t;
+
+// Values for "accessMode" field of buffer_config_t:
+// overwrite, read only, accumulate (read/modify/write)
+enum qahw_effect_buffer_access_e {
+ QAHW_EFFECT_BUFFER_ACCESS_WRITE,
+ QAHW_EFFECT_BUFFER_ACCESS_READ,
+ QAHW_EFFECT_BUFFER_ACCESS_ACCUMULATE
+
+};
+
+// feature identifiers for QAHW_EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS command
+enum qahw_effect_feature_e {
+ QAHW_EFFECT_FEATURE_AUX_CHANNELS, // supports auxiliary channels
+ // (e.g. dual mic noise suppressor)
+ QAHW_EFFECT_FEATURE_CNT
+};
+
+// QAHW_EFFECT_FEATURE_AUX_CHANNELS feature configuration descriptor. Describe a combination
+// of main and auxiliary channels supported
+typedef struct qahw_channel_config_s {
+ audio_channel_mask_t main_channels; // channel mask for main channels
+ audio_channel_mask_t aux_channels; // channel mask for auxiliary channels
+} qahw_channel_config_t;
+
+
+// Values for bit field "mask" in buffer_config_t. If a bit is set, the corresponding field
+// in buffer_config_t must be taken into account when executing the QAHW_EFFECT_CMD_SET_CONFIG
+// command
+#define QAHW_EFFECT_CONFIG_BUFFER 0x0001 // buffer field must be taken into account
+#define QAHW_EFFECT_CONFIG_SMP_RATE 0x0002 // samplingRate field must be taken into account
+#define QAHW_EFFECT_CONFIG_CHANNELS 0x0004 // channels field must be taken into account
+#define QAHW_EFFECT_CONFIG_FORMAT 0x0008 // format field must be taken into account
+#define QAHW_EFFECT_CONFIG_ACC_MODE 0x0010 // accessMode field must be taken into account
+#define QAHW_EFFECT_CONFIG_PROVIDER 0x0020 // bufferProvider field must be taken into account
+#define QAHW_EFFECT_CONFIG_ALL (QAHW_EFFECT_CONFIG_BUFFER | QAHW_EFFECT_CONFIG_SMP_RATE | \
+ QAHW_EFFECT_CONFIG_CHANNELS | QAHW_EFFECT_CONFIG_FORMAT | \
+ QAHW_EFFECT_CONFIG_ACC_MODE | QAHW_EFFECT_CONFIG_PROVIDER)
+
+
+// effect_config_s structure describes the format of the pCmdData argument of
+// QAHW_EFFECT_CMD_SET_CONFIG command to configure audio parameters and buffers for effect
+// engine input and output.
+typedef struct qahw_effect_config_s {
+ qahw_buffer_config_t input_cfg;
+ qahw_buffer_config_t output_cfg;
+} qahw_effect_config_t;
+
+
+// effect_param_s structure describes the format of the pCmdData argument of
+// QAHW_EFFECT_CMD_SET_PARAM command and pCmdData and pReplyData of QAHW_EFFECT_CMD_GET_PARAM
+// command. psize and vsize represent the actual size of parameter and value.
+//
+// NOTE: the start of value field inside the data field is always on a 32 bit boundary:
+//
+// +-----------+
+// | status | sizeof(int)
+// +-----------+
+// | psize | sizeof(int)
+// +-----------+
+// | vsize | sizeof(int)
+// +-----------+
+// | | | |
+// ~ parameter ~ > psize |
+// | | | > ((psize - 1)/sizeof(int) + 1) * sizeof(int)
+// +-----------+ |
+// | padding | |
+// +-----------+
+// | | |
+// ~ value ~ > vsize
+// | | |
+// +-----------+
+
+typedef struct qahw_effect_param_s {
+ int32_t status; // Transaction status (unused for command, used for reply)
+ uint32_t psize; // Parameter size
+ uint32_t vsize; // Value size
+ char data[]; // Start of Parameter + Value data
+} qahw_effect_param_t;
+
+// structure used by QAHW_EFFECT_CMD_OFFLOAD command
+typedef struct qahw_effect_offload_param_s {
+ bool isOffload; // true if the playback thread the effect is attached to is offloaded
+ int ioHandle; // io handle of the playback thread the effect is attached to
+} qahw_effect_offload_param_t;
+
+
+/////////////////////////////////////////////////
+// Effect library interface
+/////////////////////////////////////////////////
+
+// Effect library interface version 3.0
+// Note that EffectsFactory.c only checks the major version component, so changes to the minor
+// number can only be used for fully backwards compatible changes
+#define QAHW_EFFECT_LIBRARY_API_VERSION QAHW_EFFECT_MAKE_API_VERSION(3, 0)
+
+typedef void* qahw_effect_lib_handle_t;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Function: qahw_effect_load_library
+//
+// Description: Loads an effect library
+//
+// Input:
+// lib_name: Effect library name.
+//
+// Output:
+// returned value: NULL if fails to load library.
+// valid effect library handle
+//
+////////////////////////////////////////////////////////////////////////////////
+qahw_effect_lib_handle_t qahw_effect_load_library(const char *lib_name);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Function: qahw_effect_unload_library
+//
+// Description: Unload the audio effect library
+//
+// Input:
+// handle: Effect library handle.
+//
+// Output:
+// returned value: 0 successful operation.
+// -EINVAL invalid effect library handle
+//
+////////////////////////////////////////////////////////////////////////////////
+int32_t qahw_effect_unload_library(qahw_effect_lib_handle_t handle);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Function: qahw_effect_create
+//
+// Description: Creates an effect engine of the specified implementation uuid and
+// returns an effect control interface on this engine. The function will allocate the
+// resources for an instance of the requested effect engine and return
+// a handle on the effect control interface.
+//
+// Input:
+// handle: handle on the effect library.
+// uuid: pointer to the effect uuid.
+// sessionId: audio session to which this effect instance will be attached.
+// All effects created with the same session ID are connected in series
+// and process the same signal stream. Knowing that two effects are part
+// of the same effect chain can help the library implement some kind of
+// optimizations.
+// io_handle: identifies the output or input stream this effect is directed to in
+// audio HAL.
+// For future use especially with tunneled HW accelerated effects
+//
+// Input/Output:
+// effect_handle: address where to return the effect interface handle.
+//
+// Output:
+// returned value: 0 successful operation.
+// -ENODEV library failed to initialize
+// -EINVAL invalid pEffectUuid or effect_handle
+// -ENOENT no effect with this uuid found
+// *effect_handle: updated with the effect interface handle.
+//
+////////////////////////////////////////////////////////////////////////////////
+int32_t qahw_effect_create(qahw_effect_lib_handle_t handle,
+ const qahw_effect_uuid_t *uuid,
+ int32_t io_handle,
+ qahw_effect_handle_t *effect_handle);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Function: qahw_effect_release
+//
+// Description: Releases the effect engine whose handle is given as argument.
+// All resources allocated to this particular instance of the effect are
+// released.
+//
+// Input:
+// handle: handle on the effect library.
+// effect_handle: handle on the effect interface to be released.
+//
+// Output:
+// returned value: 0 successful operation.
+// -EINVAL invalid interface handle
+//
+////////////////////////////////////////////////////////////////////////////////
+int32_t qahw_effect_release(qahw_effect_lib_handle_t handle,
+ qahw_effect_handle_t effect_handle);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Function: qahw_effect_get_descriptor
+//
+// Description: Returns the descriptor of the effect engine which implementation UUID is
+// given as argument.
+//
+// Input/Output:
+// handle: handle on the effect library.
+// uuid: pointer to the effect uuid.
+// effect_desc: address where to return the effect descriptor.
+//
+// Output:
+// returned value: 0 successful operation.
+// -ENODEV library failed to initialize
+// -EINVAL invalid effect_desc or uuid
+// *effect_desc: updated with the effect descriptor.
+//
+////////////////////////////////////////////////////////////////////////////////
+int32_t qahw_effect_get_descriptor(qahw_effect_lib_handle_t handle,
+ const qahw_effect_uuid_t *uuid,
+ qahw_effect_descriptor_t *effect_desc);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Function: qahw_effect_get_version
+//
+// Description: Get version of IOT effect APIs.
+//
+// Output:
+// returned value: version number
+//
+////////////////////////////////////////////////////////////////////////////////
+int32_t qahw_effect_get_version();
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Function: qahw_effect_process
+//
+// Description: Effect process function. Takes input samples as specified
+// (count and location) in input buffer descriptor and output processed
+// samples as specified in output buffer descriptor. If the buffer descriptor
+// is not specified the function must use either the buffer or the
+// buffer provider function installed by the QAHW_EFFECT_CMD_SET_CONFIG command.
+// The effect framework will call the process() function after the QAHW_EFFECT_CMD_ENABLE
+// command is received and until the QAHW_EFFECT_CMD_DISABLE is received. When the engine
+// receives the QAHW_EFFECT_CMD_DISABLE command it should turn off the effect gracefully
+// and when done indicate that it is OK to stop calling the process() function by
+// returning the -ENODATA status.
+//
+// NOTE: the process() function implementation should be "real-time safe" that is
+// it should not perform blocking calls: malloc/free, sleep, read/write/open/close,
+// pthread_cond_wait/pthread_mutex_lock...
+//
+// Input:
+// self: handle to the effect interface this function is called on.
+// in_buffer: buffer descriptor indicating where to read samples to process.
+// If NULL, use the configuration passed by QAHW_EFFECT_CMD_SET_CONFIG command.
+// out_buffer: buffer descriptor indicating where to write processed samples.
+// If NULL, use the configuration passed by QAHW_EFFECT_CMD_SET_CONFIG command.
+//
+// Output:
+// returned value: 0 successful operation
+// -ENODATA the engine has finished the disable phase and the framework
+// can stop calling process()
+// -EINVAL invalid interface handle or
+// invalid input/output buffer description
+////////////////////////////////////////////////////////////////////////////////
+int32_t qahw_effect_process(qahw_effect_handle_t self,
+ qahw_audio_buffer_t *in_buffer,
+ qahw_audio_buffer_t *out_buffer);
+////////////////////////////////////////////////////////////////////////////////
+//
+// Function: qahw_effect_command
+//
+// Description: Send a command and receive a response to/from effect engine.
+//
+// Input:
+// self: handle to the effect interface this function is called on.
+// cmd_code: command code: the command can be a standardized command defined in
+// qahw_effect_command_e (see below) or a proprietary command.
+// cmd_size: size of command in bytes
+// cmd_data: pointer to command data
+// reply_data: pointer to reply data
+//
+// Input/Output:
+// reply_size: maximum size of reply data as input
+// actual size of reply data as output
+//
+// Output:
+// returned value: 0 successful operation
+// -EINVAL invalid interface handle or
+// invalid command/reply size or format according to
+// command code
+// The return code should be restricted to indicate problems related to this API
+// specification. Status related to the execution of a particular command should be
+// indicated as part of the reply field.
+//
+// *reply_data updated with command response
+//
+////////////////////////////////////////////////////////////////////////////////
+int32_t qahw_effect_command(qahw_effect_handle_t self,
+ uint32_t cmd_code,
+ uint32_t cmd_size,
+ void *cmd_data,
+ uint32_t *reply_size,
+ void *reply_data);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Function: qahw_effect_process_reverse
+//
+// Description: Process reverse stream function. This function is used to pass
+// a reference stream to the effect engine. If the engine does not need a reference
+// stream, this function pointer can be set to NULL.
+// This function would typically implemented by an Echo Canceler.
+//
+// Input:
+// self: handle to the effect interface this function is called on.
+// in_buffer: buffer descriptor indicating where to read samples to process.
+// If NULL, use the configuration passed by
+// QAHW_EFFECT_CMD_SET_CONFIG_REVERSE command.
+//
+// out_buffer: buffer descriptor indicating where to write processed samples.
+// If NULL, use the configuration passed by
+// QAHW_EFFECT_CMD_SET_CONFIG_REVERSE command.
+// If the buffer and buffer provider in the configuration received by
+// QAHW_EFFECT_CMD_SET_CONFIG_REVERSE are also NULL, do not return modified reverse
+// stream data
+//
+// Output:
+// returned value: 0 successful operation
+// -ENODATA the engine has finished the disable phase and the framework
+// can stop calling process_reverse()
+// -EINVAL invalid interface handle or
+// invalid input/output buffer description
+////////////////////////////////////////////////////////////////////////////////
+int32_t qahw_effect_process_reverse(qahw_effect_handle_t self,
+ qahw_audio_buffer_t *in_buffer,
+ qahw_audio_buffer_t *out_buffer);
+
+
+__END_DECLS
+
+#endif // ANDROID_AUDIO_QAHW_EFFECT_H
diff --git a/qahw/src/qahw.c b/qahw/src/qahw.c
new file mode 100644
index 00000000..91fc5bfc
--- /dev/null
+++ b/qahw/src/qahw.c
@@ -0,0 +1,1934 @@
+/*
+* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#define LOG_TAG "qahw"
+/*#define LOG_NDEBUG 0*/
+#define LOG_NDDEBUG 0
+
+#include <dlfcn.h>
+#include <utils/Log.h>
+#include <stdlib.h>
+#include <cutils/list.h>
+
+#include <hardware/audio.h>
+#include "qahw.h"
+
+#define NO_ERROR 0
+#define MAX_MODULE_NAME_LENGTH 100
+
+/*
+ * The current HAL API version.
+ */
+#define QAHW_MODULE_API_VERSION_CURRENT QAHW_MODULE_API_VERSION_0_0
+
+
+typedef uint64_t (*qahwi_out_write_v2_t)(audio_stream_out_t *out, const void* buffer,
+ size_t bytes, int64_t* timestamp);
+
+typedef int (*qahwi_get_param_data_t) (const audio_hw_device_t *,
+ qahw_param_id, qahw_param_payload *);
+
+typedef int (*qahwi_set_param_data_t) (audio_hw_device_t *,
+ qahw_param_id, qahw_param_payload *);
+
+typedef uint64_t (*qahwi_in_read_v2_t)(audio_stream_in_t *in, void* buffer,
+ size_t bytes, int64_t *timestamp);
+
+typedef int (*qahwi_out_set_param_data_t)(struct audio_stream_out *out,
+ qahw_param_id param_id,
+ qahw_param_payload *payload);
+
+typedef int (*qahwi_out_get_param_data_t)(struct audio_stream_out *out,
+ qahw_param_id param_id,
+ qahw_param_payload *payload);
+
+typedef struct {
+ audio_hw_device_t *audio_device;
+ char module_name[MAX_MODULE_NAME_LENGTH];
+ struct listnode module_list;
+ struct listnode in_list;
+ struct listnode out_list;
+ pthread_mutex_t lock;
+ uint32_t ref_count;
+ const hw_module_t* module;
+ qahwi_get_param_data_t qahwi_get_param_data;
+ qahwi_set_param_data_t qahwi_set_param_data;
+} qahw_module_t;
+
+typedef struct {
+ qahw_module_t *module;
+ struct listnode module_list;
+ pthread_mutex_t lock;
+} qahw_module_instances_t;
+
+typedef struct {
+ audio_stream_out_t *stream;
+ qahw_module_t *module;
+ struct listnode list;
+ pthread_mutex_t lock;
+ qahwi_out_set_param_data_t qahwi_out_get_param_data;
+ qahwi_out_get_param_data_t qahwi_out_set_param_data;
+ qahwi_out_write_v2_t qahwi_out_write_v2;
+} qahw_stream_out_t;
+
+typedef struct {
+ audio_stream_in_t *stream;
+ qahw_module_t *module;
+ struct listnode list;
+ pthread_mutex_t lock;
+ qahwi_in_read_v2_t qahwi_in_read_v2;
+} qahw_stream_in_t;
+
+typedef enum {
+ STREAM_DIR_IN,
+ STREAM_DIR_OUT,
+} qahw_stream_direction_t;
+
+static struct listnode qahw_module_list;
+static int qahw_list_count;
+static pthread_mutex_t qahw_module_init_lock = PTHREAD_MUTEX_INITIALIZER;
+
+
+/** Start of internal functions */
+/******************************************************************************/
+
+/* call this function without anylock held */
+static bool is_valid_qahw_stream_l(void *qahw_stream,
+ qahw_stream_direction_t dir)
+{
+
+ int is_valid = false;
+ struct listnode *module_node = NULL;
+ struct listnode *stream_node = NULL;
+ struct listnode *list_node = NULL;
+ void *stream = NULL;
+ qahw_module_t *qahw_module = NULL;
+
+ if (qahw_stream == NULL) {
+ ALOGE("%s:: Invalid stream", __func__);
+ goto exit;
+ }
+
+ if ((dir != STREAM_DIR_OUT) && (dir != STREAM_DIR_IN)) {
+ ALOGE("%s:: Invalid stream direction %d", __func__, dir);
+ goto exit;
+ }
+
+ /* go through all the modules and check for valid stream */
+ pthread_mutex_lock(&qahw_module_init_lock);
+ list_for_each(module_node, &qahw_module_list) {
+ qahw_module = node_to_item(module_node, qahw_module_t, module_list);
+ pthread_mutex_lock(&qahw_module->lock);
+ if(dir == STREAM_DIR_OUT)
+ list_node = &qahw_module->out_list;
+ else
+ list_node = &qahw_module->in_list;
+ list_for_each(stream_node, list_node) {
+ if(dir == STREAM_DIR_OUT)
+ stream = (void *)node_to_item(stream_node,
+ qahw_stream_out_t,
+ list);
+ else
+ stream = (void *)node_to_item(stream_node,
+ qahw_stream_in_t,
+ list);
+ if(stream == qahw_stream) {
+ is_valid = true;
+ break;
+ }
+ }
+ pthread_mutex_unlock(&qahw_module->lock);
+ if(is_valid)
+ break;
+ }
+ pthread_mutex_unlock(&qahw_module_init_lock);
+
+exit:
+ return is_valid;
+}
+
+/* call this fucntion with ahw_module_init_lock held*/
+static qahw_module_t* get_qahw_module_by_ptr_l(qahw_module_t *qahw_module)
+{
+ struct listnode *node = NULL;
+ qahw_module_t *module = NULL, *module_temp = NULL;
+
+ if (qahw_module == NULL)
+ goto exit;
+
+ list_for_each(node, &qahw_module_list) {
+ module_temp = node_to_item(node, qahw_module_t, module_list);
+ if (module_temp == qahw_module) {
+ module = module_temp;
+ break;
+ }
+ }
+exit:
+ return module;
+}
+
+/* call this function with qahw_module_init_lock held*/
+static qahw_module_t* get_qahw_module_by_name_l(const char *qahw_name)
+{
+ struct listnode *node = NULL;
+ qahw_module_t *module = NULL, *module_temp = NULL;
+
+ if (qahw_name == NULL)
+ goto exit;
+
+ list_for_each(node, &qahw_module_list) {
+ module_temp = node_to_item(node, qahw_module_t, module_list);
+ if(!strncmp(qahw_name, module_temp->module_name, MAX_MODULE_NAME_LENGTH)) {
+ module = module_temp;
+ break;
+ }
+ }
+exit:
+ return module;
+}
+/* End of of internal functions */
+
+/*
+ * Return the sampling rate in Hz - eg. 44100.
+ */
+uint32_t qahw_out_get_sample_rate_l(const qahw_stream_handle_t *out_handle)
+{
+ uint32_t rate = 0;
+ qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
+ audio_stream_out_t *out = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
+ ALOGV("%s::Invalid out handle %p", __func__, out_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_out->lock);
+ out = qahw_stream_out->stream;
+ if (out->common.get_sample_rate)
+ rate = out->common.get_sample_rate(&out->common);
+ else
+ ALOGW("%s not supported", __func__);
+ pthread_mutex_unlock(&qahw_stream_out->lock);
+
+exit:
+ return rate;
+}
+
+/*
+ * currently unused - use set_parameters with key
+ * AUDIO_PARAMETER_STREAM_SAMPLING_RATE
+ */
+int qahw_out_set_sample_rate_l(qahw_stream_handle_t *out_handle, uint32_t rate)
+{
+ int32_t rc = -EINVAL;
+ qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
+ audio_stream_out_t *out = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
+ ALOGE("%s::Invalid out handle %p", __func__, out_handle);
+ goto exit;
+ }
+ pthread_mutex_lock(&qahw_stream_out->lock);
+ out = qahw_stream_out->stream;
+ if (out->common.set_sample_rate) {
+ rc = out->common.set_sample_rate(&out->common, rate);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_out->lock);
+exit:
+ return rc;
+}
+
+size_t qahw_out_get_buffer_size_l(const qahw_stream_handle_t *out_handle)
+{
+ size_t buf_size = 0;
+ qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
+ audio_stream_out_t *out = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
+ ALOGE("%s::Invalid out handle %p", __func__, out_handle);
+ goto exit;
+ }
+ pthread_mutex_lock(&qahw_stream_out->lock);
+ out = qahw_stream_out->stream;
+ if (out->common.get_buffer_size) {
+ buf_size = out->common.get_buffer_size(&out->common);
+ } else {
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_out->lock);
+
+exit:
+ return buf_size;
+}
+
+audio_channel_mask_t qahw_out_get_channels_l(const qahw_stream_handle_t *out_handle)
+{
+ audio_channel_mask_t ch_mask = 0;
+ qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
+ audio_stream_out_t *out = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
+ ALOGE("%s::Invalid out handle %p", __func__, out_handle);
+ goto exit;
+ }
+ pthread_mutex_lock(&qahw_stream_out->lock);
+ out = qahw_stream_out->stream;
+ if (out->common.get_channels) {
+ ch_mask = out->common.get_channels(&out->common);
+ } else {
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_out->lock);
+
+exit:
+ return ch_mask;
+}
+
+audio_format_t qahw_out_get_format_l(const qahw_stream_handle_t *out_handle)
+{
+ audio_format_t format = AUDIO_FORMAT_INVALID;
+ qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
+ audio_stream_out_t *out = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
+ ALOGE("%s::Invalid out handle %p", __func__, out_handle);
+ goto exit;
+ }
+ pthread_mutex_lock(&qahw_stream_out->lock);
+ out = qahw_stream_out->stream;
+ if (out->common.get_format) {
+ format = out->common.get_format(&out->common);
+ } else {
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_out->lock);
+
+exit:
+ return format;
+}
+
+int qahw_out_standby_l(qahw_stream_handle_t *out_handle)
+{
+ int32_t rc = -EINVAL;
+ qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
+ audio_stream_out_t *out = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
+ ALOGE("%s::Invalid out handle %p", __func__, out_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_out->lock);
+ out = qahw_stream_out->stream;
+ if (out->common.standby) {
+ rc = out->common.standby(&out->common);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_out->lock);
+
+exit:
+ return rc;
+}
+
+int qahw_out_set_parameters_l(qahw_stream_handle_t *out_handle, const char *kv_pairs)
+{
+ int rc = NO_ERROR;
+ qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
+ audio_stream_out_t *out = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
+ ALOGE("%s::Invalid out handle %p", __func__, out_handle);
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_out->lock);
+ out = qahw_stream_out->stream;
+ if (out->common.set_parameters) {
+ rc = out->common.set_parameters(&out->common, kv_pairs);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_out->lock);
+
+exit:
+ return rc;
+}
+
+char *qahw_out_get_parameters_l(const qahw_stream_handle_t *out_handle,
+ const char *keys)
+{
+ char *str_param = NULL;
+ qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
+ audio_stream_out_t *out = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
+ ALOGE("%s::Invalid out handle %p", __func__, out_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_out->lock);
+ out = qahw_stream_out->stream;
+ if (out->common.get_parameters) {
+ str_param = out->common.get_parameters(&out->common, keys);
+ } else {
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_out->lock);
+
+exit:
+ return str_param;
+}
+
+/* API to get playback stream specific config parameters */
+int qahw_out_set_param_data_l(qahw_stream_handle_t *out_handle,
+ qahw_param_id param_id,
+ qahw_param_payload *payload)
+{
+ int rc = -EINVAL;
+ qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
+ audio_stream_out_t *out = NULL;
+
+ if (!payload) {
+ ALOGE("%s::Invalid param", __func__);
+ goto exit;
+ }
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
+ ALOGE("%s::Invalid out handle %p", __func__, out_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_out->lock);
+ out = qahw_stream_out->stream;
+ if (qahw_stream_out->qahwi_out_set_param_data) {
+ rc = qahw_stream_out->qahwi_out_set_param_data(out, param_id, payload);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_out->lock);
+
+exit:
+ return rc;
+}
+
+/* API to get playback stream specific config parameters */
+int qahw_out_get_param_data_l(qahw_stream_handle_t *out_handle,
+ qahw_param_id param_id,
+ qahw_param_payload *payload)
+{
+ int rc = -EINVAL;
+ qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
+ audio_stream_out_t *out = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
+ ALOGE("%s::Invalid out handle %p", __func__, out_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_out->lock);
+ out = qahw_stream_out->stream;
+ if (qahw_stream_out->qahwi_out_get_param_data) {
+ rc = qahw_stream_out->qahwi_out_get_param_data(out, param_id, payload);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_out->lock);
+
+exit:
+ return rc;
+}
+
+uint32_t qahw_out_get_latency_l(const qahw_stream_handle_t *out_handle)
+{
+ uint32_t latency = 0;
+ qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
+ audio_stream_out_t *out = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
+ ALOGE("%s::Invalid out handle %p", __func__, out_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_out->lock);
+ out = qahw_stream_out->stream;
+ if (out->get_latency) {
+ latency = out->get_latency(out);
+ } else {
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_out->lock);
+
+exit:
+ return latency;
+}
+
+int qahw_out_set_volume_l(qahw_stream_handle_t *out_handle, float left, float right)
+{
+ int rc = -EINVAL;
+ qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
+ audio_stream_out_t *out = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
+ ALOGE("%s::Invalid out handle %p", __func__, out_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_out->lock);
+ out = qahw_stream_out->stream;
+ if (out->set_volume) {
+ rc = out->set_volume(out, left, right);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_out->lock);
+
+exit:
+ return rc;
+}
+
+ssize_t qahw_out_write_l(qahw_stream_handle_t *out_handle,
+ qahw_out_buffer_t *out_buf)
+{
+ int rc = -EINVAL;
+ qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
+ audio_stream_out_t *out = NULL;
+
+ if ((out_buf == NULL) || (out_buf->buffer == NULL)) {
+ ALOGE("%s::Invalid meta data %p", __func__, out_buf);
+ goto exit;
+ }
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
+ ALOGE("%s::Invalid out handle %p", __func__, out_handle);
+ goto exit;
+ }
+
+ /*TBD:: validate other meta data parameters */
+ pthread_mutex_lock(&qahw_stream_out->lock);
+ out = qahw_stream_out->stream;
+ if (qahw_stream_out->qahwi_out_write_v2) {
+ rc = qahw_stream_out->qahwi_out_write_v2(out, out_buf->buffer,
+ out_buf->bytes, out_buf->timestamp);
+ out_buf->offset = 0;
+ } else if (out->write) {
+ rc = out->write(out, out_buf->buffer, out_buf->bytes);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_out->lock);
+exit:
+ return rc;
+}
+
+int qahw_out_get_render_position_l(const qahw_stream_handle_t *out_handle,
+ uint32_t *dsp_frames)
+{
+ int rc = -EINVAL;
+ qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
+ audio_stream_out_t *out = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
+ ALOGE("%s::Invalid out handle %p", __func__, out_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_out->lock);
+ out = qahw_stream_out->stream;
+ if (out->get_render_position) {
+ rc = out->get_render_position(out, dsp_frames);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_out->lock);
+exit:
+ return rc;
+}
+
+int qahw_out_set_callback_l(qahw_stream_handle_t *out_handle,
+ qahw_stream_callback_t callback,
+ void *cookie)
+{
+ /*TBD:load hal func pointer and call */
+ int rc = -EINVAL;
+ qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
+ audio_stream_out_t *out = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
+ ALOGE("%s::Invalid out handle %p", __func__, out_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_out->lock);
+ out = qahw_stream_out->stream;
+ if (out->set_callback) {
+ rc = out->set_callback(out, (stream_callback_t)callback, cookie);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_out->lock);
+
+exit:
+ return rc;
+}
+
+int qahw_out_pause_l(qahw_stream_handle_t *out_handle)
+{
+ /*TBD:load hal func pointer and call */
+ int rc = -EINVAL;
+ qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
+ audio_stream_out_t *out = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
+ ALOGE("%s::Invalid out handle %p", __func__, out_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_out->lock);
+ out = qahw_stream_out->stream;
+ if (out->pause) {
+ rc = out->pause(out);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_out->lock);
+
+exit:
+ return rc;
+}
+
+int qahw_out_resume_l(qahw_stream_handle_t *out_handle)
+{
+ /*TBD:load hal func pointer and call */
+ int rc = -EINVAL;
+ qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
+ audio_stream_out_t *out = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
+ ALOGE("%s::Invalid out handle %p", __func__, out_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_out->lock);
+ out = qahw_stream_out->stream;
+ if (out->resume) {
+ rc = out->resume(out);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_out->lock);
+
+exit:
+ return rc;
+}
+
+int qahw_out_drain_l(qahw_stream_handle_t *out_handle, qahw_drain_type_t type )
+{
+ /*TBD:load hal func pointer and call */
+ int rc = -EINVAL;
+ qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
+ audio_stream_out_t *out = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
+ ALOGE("%s::Invalid out handle %p", __func__, out_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_out->lock);
+ out = qahw_stream_out->stream;
+ if (out->drain) {
+ rc = out->drain(out,(audio_drain_type_t)type);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_out->lock);
+
+exit:
+ return rc;
+}
+
+int qahw_out_flush_l(qahw_stream_handle_t *out_handle)
+{
+ int rc = -EINVAL;
+ qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
+ audio_stream_out_t *out = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
+ ALOGE("%s::Invalid out handle %p", __func__, out_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_out->lock);
+ out = qahw_stream_out->stream;
+ if (out->flush) {
+ rc = out->flush(out);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_out->lock);
+
+exit:
+ return rc;
+}
+
+int qahw_out_get_presentation_position_l(const qahw_stream_handle_t *out_handle,
+ uint64_t *frames, struct timespec *timestamp)
+{
+ int rc = -EINVAL;
+ qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
+ audio_stream_out_t *out = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
+ ALOGE("%s::Invalid out handle %p", __func__, out_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_out->lock);
+ out = qahw_stream_out->stream;
+ if (out->get_presentation_position) {
+ rc = out->get_presentation_position(out, frames, timestamp);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_out->lock);
+
+exit:
+ return rc;
+}
+
+/* Input stream specific APIs */
+uint32_t qahw_in_get_sample_rate_l(const qahw_stream_handle_t *in_handle)
+{
+ uint32_t rate = 0;
+ qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
+ audio_stream_in_t *in = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
+ ALOGV("%s::Invalid in handle %p", __func__, in_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_in->lock);
+ in = qahw_stream_in->stream;
+ if (in->common.get_sample_rate) {
+ rate = in->common.get_sample_rate(&in->common);
+ } else {
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_in->lock);
+
+exit:
+ return rate;
+}
+
+/*
+ * currently unused - use set_parameters with key
+ * AUDIO_PARAMETER_STREAM_SAMPLING_RATE
+ */
+int qahw_in_set_sample_rate_l(qahw_stream_handle_t *in_handle, uint32_t rate)
+{
+ int rc = -EINVAL;
+ qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
+ audio_stream_in_t *in = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
+ ALOGV("%s::Invalid in handle %p", __func__, in_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_in->lock);
+ in = qahw_stream_in->stream;
+ if (in->common.set_sample_rate) {
+ rc = in->common.set_sample_rate(&in->common, rate);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_in->lock);
+
+exit:
+ return rc;
+}
+
+size_t qahw_in_get_buffer_size_l(const qahw_stream_handle_t *in_handle)
+{
+ size_t buf_size = 0;
+ qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
+ audio_stream_in_t *in = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
+ ALOGV("%s::Invalid in handle %p", __func__, in_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_in->lock);
+ in = qahw_stream_in->stream;
+ if (in->common.get_sample_rate) {
+ buf_size = in->common.get_buffer_size(&in->common);
+ } else {
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_in->lock);
+
+exit:
+ return buf_size;
+}
+
+
+audio_channel_mask_t qahw_in_get_channels_l(const qahw_stream_handle_t *in_handle)
+{
+ audio_channel_mask_t ch_mask = 0;;
+ qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
+ audio_stream_in_t *in = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
+ ALOGV("%s::Invalid in handle %p", __func__, in_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_in->lock);
+ in = qahw_stream_in->stream;
+ if (in->common.get_channels) {
+ ch_mask = in->common.get_channels(&in->common);
+ } else {
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_in->lock);
+
+exit:
+ return ch_mask;
+}
+
+audio_format_t qahw_in_get_format_l(const qahw_stream_handle_t *in_handle)
+{
+ audio_format_t format = AUDIO_FORMAT_INVALID;
+ qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
+ audio_stream_in_t *in = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
+ ALOGV("%s::Invalid in handle %p", __func__, in_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_in->lock);
+ in = qahw_stream_in->stream;
+ if (in->common.get_format) {
+ format = in->common.get_format(&in->common);
+ } else {
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_in->lock);
+
+exit:
+ return format;
+}
+
+/*
+ * currently unused - use set_parameters with key
+ * AUDIO_PARAMETER_STREAM_FORMAT
+ */
+int qahw_in_set_format_l(qahw_stream_handle_t *in_handle, audio_format_t format)
+{
+ int rc = -EINVAL;
+ qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
+ audio_stream_in_t *in = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
+ ALOGV("%s::Invalid in handle %p", __func__, in_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_in->lock);
+ in = qahw_stream_in->stream;
+ if (in->common.set_format) {
+ rc = in->common.set_format(&in->common, format);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_in->lock);
+
+exit:
+ return rc;
+}
+
+int qahw_in_standby_l(qahw_stream_handle_t *in_handle)
+{
+ int rc = -EINVAL;
+ qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
+ audio_stream_in_t *in = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
+ ALOGV("%s::Invalid in handle %p", __func__, in_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_in->lock);
+ in = qahw_stream_in->stream;
+ if (in->common.standby) {
+ rc = in->common.standby(&in->common);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_in->lock);
+
+exit:
+ return rc;
+}
+
+/*
+ * set/get audio stream parameters. The function accepts a list of
+ * parameter key value pairs in the form: key1=value1;key2=value2;...
+ *
+ * Some keys are reserved for standard parameters (See AudioParameter class)
+ *
+ * If the implementation does not accept a parameter change while
+ * the output is active but the parameter is acceptable otherwise, it must
+ * return -ENOSYS.
+ *
+ * The audio flinger will put the stream in standby and then change the
+ * parameter value.
+ */
+int qahw_in_set_parameters_l(qahw_stream_handle_t *in_handle, const char *kv_pairs)
+{
+ int rc = -EINVAL;
+ qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
+ audio_stream_in_t *in = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
+ ALOGV("%s::Invalid in handle %p", __func__, in_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_in->lock);
+ in = qahw_stream_in->stream;
+ if (in->common.set_parameters) {
+ rc = in->common.set_parameters(&in->common, kv_pairs);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_in->lock);
+exit:
+ return rc;
+}
+
+/*
+ * Returns a pointer to a heap allocated string. The caller is responsible
+ * for freeing the memory for it using free().
+ */
+char * qahw_in_get_parameters_l(const qahw_stream_handle_t *in_handle,
+ const char *keys)
+{
+ char *str_param = NULL;
+ qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
+ audio_stream_in_t *in = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
+ ALOGV("%s::Invalid in handle %p", __func__, in_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_in->lock);
+ in = qahw_stream_in->stream;
+ if (in->common.get_parameters) {
+ str_param = in->common.get_parameters(&in->common, keys);
+ } else {
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_in->lock);
+
+exit:
+ return str_param;
+}
+
+/*
+ * Read audio buffer in from audio driver. Returns number of bytes read, or a
+ * negative status_t. If at least one frame was read prior to the error,
+ * read should return that byte count and then return an error in the subsequent call.
+ */
+ssize_t qahw_in_read_l(qahw_stream_handle_t *in_handle,
+ qahw_in_buffer_t *in_buf)
+{
+ int rc = -EINVAL;
+ qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
+ audio_stream_in_t *in = NULL;
+
+ if ((in_buf == NULL) || (in_buf->buffer == NULL)) {
+ ALOGE("%s::Invalid meta data %p", __func__, in_buf);
+ goto exit;
+ }
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
+ ALOGV("%s::Invalid in handle %p", __func__, in_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_in->lock);
+ in = qahw_stream_in->stream;
+ if (qahw_stream_in->qahwi_in_read_v2) {
+ rc = qahw_stream_in->qahwi_in_read_v2(in, in_buf->buffer,
+ in_buf->bytes, in_buf->timestamp);
+ in_buf->offset = 0;
+ } else if (in->read) {
+ rc = in->read(in, in_buf->buffer, in_buf->bytes);
+ in_buf->offset = 0;
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_in->lock);
+
+exit:
+ return rc;
+}
+
+/*
+ * Return the amount of input frames lost in the audio driver since the
+ * last call of this function.
+ * Audio driver is expected to reset the value to 0 and restart counting
+ * upon returning the current value by this function call.
+ * Such loss typically occurs when the user space process is blocked
+ * longer than the capacity of audio driver buffers.
+ *
+ * Unit: the number of input audio frames
+ */
+uint32_t qahw_in_get_input_frames_lost_l(qahw_stream_handle_t *in_handle)
+{
+ uint32_t rc = 0;
+ qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
+ audio_stream_in_t *in = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
+ ALOGV("%s::Invalid in handle %p", __func__, in_handle);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_stream_in->lock);
+ in = qahw_stream_in->stream;
+ if (in->get_input_frames_lost) {
+ rc = in->get_input_frames_lost(in);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_stream_in->lock);
+
+exit:
+ return rc;
+}
+
+/*
+ * Return a recent count of the number of audio frames received and
+ * the clock time associated with that frame count.
+ *
+ * frames is the total frame count received. This should be as early in
+ * the capture pipeline as possible. In general,
+ * frames should be non-negative and should not go "backwards".
+ *
+ * time is the clock MONOTONIC time when frames was measured. In general,
+ * time should be a positive quantity and should not go "backwards".
+ *
+ * The status returned is 0 on success, -ENOSYS if the device is not
+ * ready/available, or -EINVAL if the arguments are null or otherwise invalid.
+ */
+int qahw_in_get_capture_position_l(const qahw_stream_handle_t *in_handle __unused,
+ int64_t *frames __unused, int64_t *time __unused)
+{
+ /*TBD:: do we need this*/
+ return -ENOSYS;
+}
+
+/*
+ * check to see if the audio hardware interface has been initialized.
+ * returns 0 on success, -ENODEV on failure.
+ */
+int qahw_init_check_l(const qahw_module_handle_t *hw_module)
+{
+ int rc = -EINVAL;
+ qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
+ qahw_module_t *qahw_module_temp;
+
+ pthread_mutex_lock(&qahw_module_init_lock);
+ qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
+ pthread_mutex_unlock(&qahw_module_init_lock);
+ if (qahw_module_temp == NULL) {
+ ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_module->lock);
+ if (qahw_module->audio_device->init_check) {
+ rc = qahw_module->audio_device->init_check(qahw_module->audio_device);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_module->lock);
+
+exit:
+ return rc;
+}
+/* set the audio volume of a voice call. Range is between 0.0 and 1.0 */
+int qahw_set_voice_volume_l(qahw_module_handle_t *hw_module, float volume)
+{
+ int rc = -EINVAL;
+ qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
+ qahw_module_t *qahw_module_temp;
+
+ pthread_mutex_lock(&qahw_module_init_lock);
+ qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
+ pthread_mutex_unlock(&qahw_module_init_lock);
+ if (qahw_module_temp == NULL) {
+ ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_module->lock);
+ if (qahw_module->audio_device->set_voice_volume) {
+ rc = qahw_module->audio_device->set_voice_volume(qahw_module->audio_device,
+ volume);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_module->lock);
+
+exit:
+ return rc;
+}
+
+/*
+ * set_mode is called when the audio mode changes. AUDIO_MODE_NORMAL mode
+ * is for standard audio playback, AUDIO_MODE_RINGTONE when a ringtone is
+ * playing, and AUDIO_MODE_IN_CALL when a call is in progress.
+ */
+int qahw_set_mode_l(qahw_module_handle_t *hw_module, audio_mode_t mode)
+{
+ int rc = -EINVAL;
+ qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
+ qahw_module_t *qahw_module_temp;
+
+ pthread_mutex_lock(&qahw_module_init_lock);
+ qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
+ pthread_mutex_unlock(&qahw_module_init_lock);
+ if (qahw_module_temp == NULL) {
+ ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_module->lock);
+ if (qahw_module->audio_device->set_mode) {
+ rc = qahw_module->audio_device->set_mode(qahw_module->audio_device,
+ mode);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_module->lock);
+
+exit:
+ return rc;
+}
+
+int qahw_set_mic_mute_l(qahw_module_handle_t *hw_module, bool state)
+{
+ int rc = -EINVAL;
+ qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
+ qahw_module_t *qahw_module_temp;
+
+ pthread_mutex_lock(&qahw_module_init_lock);
+ qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
+ pthread_mutex_unlock(&qahw_module_init_lock);
+ if (qahw_module_temp == NULL) {
+ ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_module->lock);
+ if (qahw_module->audio_device->set_mic_mute) {
+ rc = qahw_module->audio_device->set_mic_mute(qahw_module->audio_device,
+ state);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_module->lock);
+
+exit:
+ return rc;
+}
+
+int qahw_get_mic_mute_l(qahw_module_handle_t *hw_module, bool *state)
+{
+ size_t rc = 0;
+ qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
+ qahw_module_t *qahw_module_temp;
+ audio_hw_device_t *audio_device;
+
+ pthread_mutex_lock(&qahw_module_init_lock);
+ qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
+ pthread_mutex_unlock(&qahw_module_init_lock);
+ if (qahw_module_temp == NULL) {
+ ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_module->lock);
+ audio_device = qahw_module->audio_device;
+ if (qahw_module->audio_device->get_mic_mute) {
+ rc = audio_device->get_mic_mute(qahw_module->audio_device, state);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_module->lock);
+
+exit:
+ return rc;
+}
+
+/* set/get global audio parameters */
+int qahw_set_parameters_l(qahw_module_handle_t *hw_module, const char *kv_pairs)
+{
+ int rc = -EINVAL;
+ qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
+ qahw_module_t *qahw_module_temp;
+ audio_hw_device_t *audio_device;
+
+ pthread_mutex_lock(&qahw_module_init_lock);
+ qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
+ pthread_mutex_unlock(&qahw_module_init_lock);
+ if (qahw_module_temp == NULL) {
+ ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_module->lock);
+ audio_device = qahw_module->audio_device;
+ if (qahw_module->audio_device->set_parameters) {
+ rc = audio_device->set_parameters(qahw_module->audio_device, kv_pairs);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_module->lock);
+
+exit:
+ return rc;
+}
+
+/*
+ * Returns a pointer to a heap allocated string. The caller is responsible
+ * for freeing the memory for it using free().
+ */
+char * qahw_get_parameters_l(const qahw_module_handle_t *hw_module,
+ const char *keys)
+{
+ char *str_param = NULL;
+ qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
+ qahw_module_t *qahw_module_temp;
+ audio_hw_device_t *audio_device;
+
+ pthread_mutex_lock(&qahw_module_init_lock);
+ qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
+ pthread_mutex_unlock(&qahw_module_init_lock);
+ if (qahw_module_temp == NULL) {
+ ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_module->lock);
+ audio_device = qahw_module->audio_device;
+ if (qahw_module->audio_device->get_parameters) {
+ str_param = audio_device->get_parameters(qahw_module->audio_device, keys);
+ } else {
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_module->lock);
+
+exit:
+ return str_param;
+}
+
+/* Api to implement get parameters based on keyword param_id
+ * and store data in payload.
+ */
+int qahw_get_param_data_l(const qahw_module_handle_t *hw_module,
+ qahw_param_id param_id,
+ qahw_param_payload *payload)
+{
+ int ret = 0;
+ qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
+ qahw_module_t *qahw_module_temp;
+
+ pthread_mutex_lock(&qahw_module_init_lock);
+ qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
+ pthread_mutex_unlock(&qahw_module_init_lock);
+ if (qahw_module_temp == NULL) {
+ ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_module->lock);
+
+ if (qahw_module->qahwi_get_param_data){
+ ret = qahw_module->qahwi_get_param_data (qahw_module->audio_device,
+ param_id, payload);
+ } else {
+ ret = -ENOSYS;
+ ALOGE("%s not supported\n",__func__);
+ }
+ pthread_mutex_unlock(&qahw_module->lock);
+
+exit:
+ return ret;
+}
+
+/* Api to implement set parameters based on keyword param_id
+ * and data present in payload.
+ */
+int qahw_set_param_data_l(const qahw_module_handle_t *hw_module,
+ qahw_param_id param_id,
+ qahw_param_payload *payload)
+{
+ int ret = 0;
+ qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
+ qahw_module_t *qahw_module_temp;
+
+ pthread_mutex_lock(&qahw_module_init_lock);
+ qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
+ pthread_mutex_unlock(&qahw_module_init_lock);
+ if (qahw_module_temp == NULL) {
+ ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_module->lock);
+
+ if (qahw_module->qahwi_set_param_data){
+ ret = qahw_module->qahwi_set_param_data (qahw_module->audio_device,
+ param_id, payload);
+ } else {
+ ret = -ENOSYS;
+ ALOGE("%s not supported\n",__func__);
+ }
+ pthread_mutex_unlock(&qahw_module->lock);
+
+exit:
+ return ret;
+}
+
+/* Creates an audio patch between several source and sink ports.
+ * The handle is allocated by the HAL and should be unique for this
+ * audio HAL module.
+ */
+int qahw_create_audio_patch_l(qahw_module_handle_t *hw_module,
+ unsigned int num_sources,
+ const struct audio_port_config *sources,
+ unsigned int num_sinks,
+ const struct audio_port_config *sinks,
+ audio_patch_handle_t *handle)
+{
+ int ret = 0;
+ qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
+ qahw_module_t *qahw_module_temp;
+
+ pthread_mutex_lock(&qahw_module_init_lock);
+ qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
+ pthread_mutex_unlock(&qahw_module_init_lock);
+ if (qahw_module_temp == NULL) {
+ ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_module->lock);
+ if (qahw_module->audio_device->create_audio_patch) {
+ ret = qahw_module->audio_device->create_audio_patch(
+ qahw_module->audio_device,
+ num_sources,
+ sources,
+ num_sinks,
+ sinks,
+ handle);
+ } else {
+ ret = -ENOSYS;
+ ALOGE("%s not supported\n",__func__);
+ }
+ pthread_mutex_unlock(&qahw_module->lock);
+
+exit:
+ return ret;
+}
+
+/* Release an audio patch */
+int qahw_release_audio_patch_l(qahw_module_handle_t *hw_module,
+ audio_patch_handle_t handle)
+{
+ int ret = 0;
+ qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
+ qahw_module_t *qahw_module_temp;
+
+ pthread_mutex_lock(&qahw_module_init_lock);
+ qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
+ pthread_mutex_unlock(&qahw_module_init_lock);
+ if (qahw_module_temp == NULL) {
+ ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_module->lock);
+ if (qahw_module->audio_device->release_audio_patch) {
+ ret = qahw_module->audio_device->release_audio_patch(
+ qahw_module->audio_device,
+ handle);
+ } else {
+ ret = -ENOSYS;
+ ALOGE("%s not supported\n",__func__);
+ }
+ pthread_mutex_unlock(&qahw_module->lock);
+
+exit:
+ return ret;
+}
+
+/* Fills the list of supported attributes for a given audio port.
+ * As input, "port" contains the information (type, role, address etc...)
+ * needed by the HAL to identify the port.
+ * As output, "port" contains possible attributes (sampling rates, formats,
+ * channel masks, gain controllers...) for this port.
+ */
+int qahw_get_audio_port_l(qahw_module_handle_t *hw_module,
+ struct audio_port *port)
+{
+ int ret = 0;
+ qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
+ qahw_module_t *qahw_module_temp;
+
+ pthread_mutex_lock(&qahw_module_init_lock);
+ qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
+ pthread_mutex_unlock(&qahw_module_init_lock);
+ if (qahw_module_temp == NULL) {
+ ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_module->lock);
+ if (qahw_module->audio_device->get_audio_port) {
+ ret = qahw_module->audio_device->get_audio_port(
+ qahw_module->audio_device,
+ port);
+ } else {
+ ret = -ENOSYS;
+ ALOGE("%s not supported\n",__func__);
+ }
+ pthread_mutex_unlock(&qahw_module->lock);
+
+exit:
+ return ret;
+}
+
+/* Set audio port configuration */
+int qahw_set_audio_port_config_l(qahw_module_handle_t *hw_module,
+ const struct audio_port_config *config)
+{
+ int ret = 0;
+ qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
+ qahw_module_t *qahw_module_temp;
+
+ pthread_mutex_lock(&qahw_module_init_lock);
+ qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
+ pthread_mutex_unlock(&qahw_module_init_lock);
+ if (qahw_module_temp == NULL) {
+ ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_module->lock);
+ if (qahw_module->audio_device->set_audio_port_config) {
+ ret = qahw_module->audio_device->set_audio_port_config(
+ qahw_module->audio_device,
+ config);
+ } else {
+ ret = -ENOSYS;
+ ALOGE("%s not supported\n",__func__);
+ }
+ pthread_mutex_unlock(&qahw_module->lock);
+
+exit:
+ return ret;
+}
+
+/* Returns audio input buffer size according to parameters passed or
+ * 0 if one of the parameters is not supported.
+ * See also get_buffer_size which is for a particular stream.
+ */
+size_t qahw_get_input_buffer_size_l(const qahw_module_handle_t *hw_module,
+ const struct audio_config *config)
+{
+ size_t rc = 0;
+ qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
+ qahw_module_t *qahw_module_temp;
+ audio_hw_device_t *audio_device;
+
+ pthread_mutex_lock(&qahw_module_init_lock);
+ qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
+ pthread_mutex_unlock(&qahw_module_init_lock);
+ if (qahw_module_temp == NULL) {
+ ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
+ goto exit;
+ }
+
+ pthread_mutex_lock(&qahw_module->lock);
+ audio_device = qahw_module->audio_device;
+ if (qahw_module->audio_device->get_input_buffer_size) {
+ rc = audio_device->get_input_buffer_size(qahw_module->audio_device,
+ config);
+ } else {
+ rc = -ENOSYS;
+ ALOGW("%s not supported", __func__);
+ }
+ pthread_mutex_unlock(&qahw_module->lock);
+
+exit:
+ return rc;
+}
+
+/*
+ * This method creates and opens the audio hardware output stream.
+ * The "address" parameter qualifies the "devices" audio device type if needed.
+ * The format format depends on the device type:
+ * - Bluetooth devices use the MAC address of the device in the form "00:11:22:AA:BB:CC"
+ * - USB devices use the ALSA card and device numbers in the form "card=X;device=Y"
+ * - Other devices may use a number or any other string.
+ */
+int qahw_open_output_stream_l(qahw_module_handle_t *hw_module,
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ audio_output_flags_t flags,
+ struct audio_config *config,
+ qahw_stream_handle_t **out_handle,
+ const char *address)
+{
+ int rc = -EINVAL;
+ qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
+ qahw_module_t *qahw_module_temp = NULL;
+ audio_hw_device_t *audio_device = NULL;
+ qahw_stream_out_t *qahw_stream_out = NULL;
+
+ pthread_mutex_lock(&qahw_module_init_lock);
+ qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
+ pthread_mutex_unlock(&qahw_module_init_lock);
+ if (qahw_module_temp == NULL) {
+ ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
+ return rc;
+ }
+
+ pthread_mutex_lock(&qahw_module->lock);
+ audio_device = qahw_module->audio_device;
+ qahw_stream_out = (qahw_stream_out_t *)calloc(1, sizeof(qahw_stream_out_t));
+ if (qahw_stream_out == NULL) {
+ ALOGE("%s:: calloc failed for out stream_out_t",__func__);
+ rc = -ENOMEM;
+ goto exit;
+ }
+
+ rc = audio_device->open_output_stream(audio_device,
+ handle,
+ devices,
+ flags,
+ config,
+ &qahw_stream_out->stream,
+ address);
+ if (rc) {
+ ALOGE("%s::open output stream failed %d",__func__, rc);
+ free(qahw_stream_out);
+ } else {
+ qahw_stream_out->module = hw_module;
+ *out_handle = (void *)qahw_stream_out;
+ pthread_mutex_init(&qahw_stream_out->lock, (const pthread_mutexattr_t *)NULL);
+ list_add_tail(&qahw_module->out_list, &qahw_stream_out->list);
+
+ /* clear any existing errors */
+ const char *error;
+ dlerror();
+ qahw_stream_out->qahwi_out_get_param_data = (qahwi_out_get_param_data_t)
+ dlsym(qahw_module->module->dso,
+ "qahwi_out_get_param_data");
+ if ((error = dlerror()) != NULL) {
+ ALOGI("%s: dlsym error %s for qahwi_out_get_param_data",
+ __func__, error);
+ qahw_stream_out->qahwi_out_get_param_data = NULL;
+ }
+
+ dlerror();
+ qahw_stream_out->qahwi_out_set_param_data = (qahwi_out_set_param_data_t)
+ dlsym(qahw_module->module->dso,
+ "qahwi_out_set_param_data");
+ if ((error = dlerror()) != NULL) {
+ ALOGI("%s: dlsym error %s for qahwi_out_set_param_data",
+ __func__, error);
+ qahw_stream_out->qahwi_out_set_param_data = NULL;
+ }
+}
+
+ /* dlsym qahwi_out_write_v2 */
+ if (!rc) {
+ const char *error;
+
+ /* clear any existing errors */
+ dlerror();
+ qahw_stream_out->qahwi_out_write_v2 = (qahwi_out_write_v2_t)dlsym(qahw_module->module->dso, "qahwi_out_write_v2");
+ if ((error = dlerror()) != NULL) {
+ ALOGI("%s: dlsym error %s for qahwi_out_write_v2", __func__, error);
+ qahw_stream_out->qahwi_out_write_v2 = NULL;
+ }
+ }
+
+exit:
+ pthread_mutex_unlock(&qahw_module->lock);
+ return rc;
+}
+
+int qahw_close_output_stream_l(qahw_stream_handle_t *out_handle)
+{
+
+ int rc = 0;
+ qahw_stream_out_t *qahw_stream_out = (qahw_stream_out_t *)out_handle;
+ qahw_module_t *qahw_module = NULL;
+ audio_hw_device_t *audio_device = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_out, STREAM_DIR_OUT)) {
+ ALOGE("%s::Invalid out handle %p", __func__, out_handle);
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ ALOGV("%s::calling device close_output_stream %p", __func__, out_handle);
+ pthread_mutex_lock(&qahw_stream_out->lock);
+ qahw_module = qahw_stream_out->module;
+ audio_device = qahw_module->audio_device;
+ audio_device->close_output_stream(audio_device,
+ qahw_stream_out->stream);
+
+ pthread_mutex_lock(&qahw_module->lock);
+ list_remove(&qahw_stream_out->list);
+ pthread_mutex_unlock(&qahw_module->lock);
+
+ pthread_mutex_unlock(&qahw_stream_out->lock);
+
+ pthread_mutex_destroy(&qahw_stream_out->lock);
+ free(qahw_stream_out);
+
+exit:
+ return rc;
+}
+
+/* This method creates and opens the audio hardware input stream */
+int qahw_open_input_stream_l(qahw_module_handle_t *hw_module,
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ struct audio_config *config,
+ qahw_stream_handle_t **in_handle,
+ audio_input_flags_t flags,
+ const char *address,
+ audio_source_t source)
+{
+ int rc = -EINVAL;
+ qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
+ qahw_module_t *qahw_module_temp = NULL;
+ audio_hw_device_t *audio_device = NULL;
+ qahw_stream_in_t *qahw_stream_in = NULL;
+
+ pthread_mutex_lock(&qahw_module_init_lock);
+ qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
+ pthread_mutex_unlock(&qahw_module_init_lock);
+ if (qahw_module_temp == NULL) {
+ ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
+ return rc;
+ }
+
+ pthread_mutex_lock(&qahw_module->lock);
+ audio_device = qahw_module->audio_device;
+ qahw_stream_in = (qahw_stream_in_t *)calloc(1, sizeof(qahw_stream_in_t));
+ if (qahw_stream_in == NULL) {
+ ALOGE("%s:: calloc failed for in stream_in_t",__func__);
+ rc = -ENOMEM;
+ goto exit;
+ }
+
+ rc = audio_device->open_input_stream(audio_device,
+ handle,
+ devices,
+ config,
+ &qahw_stream_in->stream,
+ flags,
+ address,
+ source);
+ if (rc) {
+ ALOGE("%s::open input stream failed %d",__func__, rc);
+ free(qahw_stream_in);
+ } else {
+ qahw_stream_in->module = hw_module;
+ *in_handle = (void *)qahw_stream_in;
+ pthread_mutex_init(&qahw_stream_in->lock, (const pthread_mutexattr_t *)NULL);
+ list_add_tail(&qahw_module->in_list, &qahw_stream_in->list);
+ }
+
+ /* dlsym qahwi_in_read_v2 if timestamp flag is used */
+ if (!rc && (flags & QAHW_INPUT_FLAG_TIMESTAMP)) {
+ const char *error;
+
+ /* clear any existing errors */
+ dlerror();
+ qahw_stream_in->qahwi_in_read_v2 = (qahwi_in_read_v2_t)
+ dlsym(qahw_module->module->dso, "qahwi_in_read_v2");
+ if ((error = dlerror()) != NULL) {
+ ALOGI("%s: dlsym error %s for qahwi_in_read_v2", __func__, error);
+ qahw_stream_in->qahwi_in_read_v2 = NULL;
+ }
+ }
+
+exit:
+ pthread_mutex_unlock(&qahw_module->lock);
+ return rc;
+}
+
+int qahw_close_input_stream_l(qahw_stream_handle_t *in_handle)
+{
+ int rc = 0;
+ qahw_stream_in_t *qahw_stream_in = (qahw_stream_in_t *)in_handle;
+ qahw_module_t *qahw_module = NULL;
+ audio_hw_device_t *audio_device = NULL;
+
+ if (!is_valid_qahw_stream_l((void *)qahw_stream_in, STREAM_DIR_IN)) {
+ ALOGV("%s::Invalid in handle %p", __func__, in_handle);
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ ALOGV("%s:: calling device close_input_stream %p", __func__, in_handle);
+ pthread_mutex_lock(&qahw_stream_in->lock);
+ qahw_module = qahw_stream_in->module;
+ audio_device = qahw_module->audio_device;
+ audio_device->close_input_stream(audio_device,
+ qahw_stream_in->stream);
+
+ pthread_mutex_lock(&qahw_module->lock);
+ list_remove(&qahw_stream_in->list);
+ pthread_mutex_unlock(&qahw_module->lock);
+
+ pthread_mutex_unlock(&qahw_stream_in->lock);
+
+ pthread_mutex_destroy(&qahw_stream_in->lock);
+ free(qahw_stream_in);
+
+exit:
+ return rc;
+}
+
+/*returns current QTI HAL verison */
+int qahw_get_version_l() {
+ return QAHW_MODULE_API_VERSION_CURRENT;
+}
+
+/* convenience API for opening and closing an audio HAL module */
+
+qahw_module_handle_t *qahw_load_module_l(const char *hw_module_id)
+{
+ int rc = -EINVAL;
+ qahw_module_handle_t *qahw_mod_handle = NULL;
+ qahw_module_t *qahw_module = NULL;
+ char *ahal_name = NULL;
+ const hw_module_t* module = NULL;
+ audio_hw_device_t* audio_device = NULL;
+
+ if (hw_module_id == NULL) {
+ ALOGE("%s::module id is NULL",__func__);
+ goto exit;
+ }
+
+ if (!strcmp(hw_module_id, QAHW_MODULE_ID_PRIMARY)) {
+ ahal_name = "primary";
+ } else if (!strcmp(hw_module_id, QAHW_MODULE_ID_A2DP)) {
+ ahal_name = "a2dp";
+ } else if (!strcmp(hw_module_id, QAHW_MODULE_ID_USB)) {
+ ahal_name = "usb";
+ } else {
+ ALOGE("%s::Invalid Module id %s", __func__, hw_module_id);
+ goto exit;
+ }
+
+ /* return exiting module ptr if already loaded */
+ pthread_mutex_lock(&qahw_module_init_lock);
+ if (qahw_list_count > 0) {
+ qahw_module = get_qahw_module_by_name_l(hw_module_id);
+ if(qahw_module != NULL) {
+ qahw_mod_handle = (void *)qahw_module;
+ pthread_mutex_lock(&qahw_module->lock);
+ qahw_module->ref_count++;
+ pthread_mutex_unlock(&qahw_module->lock);
+ goto error_exit;
+ }
+ }
+
+ rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, ahal_name, &module);
+ if(rc) {
+ ALOGE("%s::HAL Loading failed %d", __func__, rc);
+ goto error_exit;
+ }
+
+ rc = audio_hw_device_open(module, &audio_device);
+ if(rc) {
+ ALOGE("%s::HAL Device open failed %d", __func__, rc);
+ goto error_exit;
+ }
+
+ qahw_module = (qahw_module_t *)calloc(1, sizeof(qahw_module_t));
+ if(qahw_module == NULL) {
+ ALOGE("%s::calloc failed", __func__);
+ audio_hw_device_close(audio_device);
+ goto error_exit;
+ }
+ qahw_module->module = module;
+ ALOGD("%s::Loaded HAL %s module %p", __func__, ahal_name, qahw_module);
+
+ qahw_module->qahwi_get_param_data = (qahwi_get_param_data_t) dlsym (module->dso,
+ "qahwi_get_param_data");
+ if (!qahw_module->qahwi_get_param_data)
+ ALOGD("%s::qahwi_get_param_data api is not defined\n",__func__);
+
+ qahw_module->qahwi_set_param_data = (qahwi_set_param_data_t) dlsym (module->dso,
+ "qahwi_set_param_data");
+ if (!qahw_module->qahwi_set_param_data)
+ ALOGD("%s::qahwi_set_param_data api is not defined\n",__func__);
+
+ if (!qahw_list_count)
+ list_init(&qahw_module_list);
+ qahw_list_count++;
+
+ pthread_mutex_init(&qahw_module->lock, (const pthread_mutexattr_t *) NULL);
+ pthread_mutex_lock(&qahw_module->lock);
+ qahw_module->ref_count++;
+ pthread_mutex_unlock(&qahw_module->lock);
+
+ list_init(&qahw_module->out_list);
+ list_init(&qahw_module->in_list);
+
+ /* update qahw_module */
+ qahw_module->audio_device = audio_device;
+ strlcpy(&qahw_module->module_name[0], hw_module_id, MAX_MODULE_NAME_LENGTH);
+
+ qahw_mod_handle = (void *)qahw_module;
+
+ /* Add module list to global module list */
+ list_add_tail(&qahw_module_list, &qahw_module->module_list);
+
+
+error_exit:
+ pthread_mutex_unlock(&qahw_module_init_lock);
+
+exit:
+ return qahw_mod_handle;
+}
+
+int qahw_unload_module_l(qahw_module_handle_t *hw_module)
+{
+ int rc = -EINVAL;
+ bool is_empty = false;
+ qahw_module_t *qahw_module = (qahw_module_t *)hw_module;
+ qahw_module_t *qahw_module_temp = NULL;
+
+ /* close HW device if its valid and all the streams on
+ * it is closed
+ */
+ pthread_mutex_lock(&qahw_module_init_lock);
+ qahw_module_temp = get_qahw_module_by_ptr_l(qahw_module);
+ if (qahw_module_temp == NULL) {
+ ALOGE("%s:: invalid hw module %p", __func__, qahw_module);
+ goto error_exit;
+ }
+
+ pthread_mutex_lock(&qahw_module->lock);
+ qahw_module->ref_count--;
+ if (qahw_module->ref_count > 0) {
+ rc = 0;
+ ALOGE("%s:: skipping module unload of %p count %d", __func__,
+ qahw_module,
+ qahw_module->ref_count);
+ pthread_mutex_unlock(&qahw_module->lock);
+ goto error_exit;
+ }
+
+ is_empty = (list_empty(&qahw_module->out_list) &&
+ list_empty(&qahw_module->in_list));
+ if (is_empty) {
+ rc = audio_hw_device_close(qahw_module->audio_device);
+ if(rc) {
+ ALOGE("%s::HAL Device close failed Error %d Module %p",__func__,
+ rc, qahw_module);
+ rc = 0;
+ }
+ qahw_list_count--;
+ list_remove(&qahw_module->module_list);
+ pthread_mutex_unlock(&qahw_module->lock);
+ pthread_mutex_destroy(&qahw_module->lock);
+ free(qahw_module);
+ } else {
+ pthread_mutex_unlock(&qahw_module->lock);
+ ALOGE("%s::failed as all the streams on this module"
+ "is not closed", __func__);
+ rc = -EINVAL;
+ }
+
+error_exit:
+ pthread_mutex_unlock(&qahw_module_init_lock);
+
+ return rc;
+}
+
+__END_DECLS
diff --git a/qahw/src/qahw_effect.c b/qahw/src/qahw_effect.c
new file mode 100644
index 00000000..cf7b3fd3
--- /dev/null
+++ b/qahw/src/qahw_effect.c
@@ -0,0 +1,321 @@
+/*
+* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#define LOG_TAG "qahw_effect"
+//#define LOG_NDEBUG 0
+#define LOG_NDDEBUG 0
+
+#include <cutils/list.h>
+#include <dlfcn.h>
+#include <utils/Log.h>
+#include <hardware/audio.h>
+#include <hardware/audio_effect.h>
+#include <stdlib.h>
+
+#include "qahw_effect_api.h"
+
+// The current effect API version.
+#define QAHW_EFFECT_API_VERSION_CURRENT QAHW_EFFECT_API_VERSION_0_0
+#define PATH_MAX 4096
+
+typedef struct {
+ char lib_path[PATH_MAX];
+ pthread_mutex_t lock;
+ uint32_t ref_count;
+ audio_effect_library_t *desc;
+ void *handle;
+ struct listnode lib_list;
+} qahw_effect_lib_t;
+
+// list of loaded effect libraries
+static struct listnode effect_libraries_list;
+static int effect_libraries_count = 0;
+static pthread_mutex_t effect_libraries_lock = PTHREAD_MUTEX_INITIALIZER;
+
+qahw_effect_lib_t *get_qahw_effect_lib_by_name(const char *lib_path) {
+ struct listnode *node = NULL;
+ qahw_effect_lib_t *effect_lib = NULL, *effect_lib_temp = NULL;
+
+ if (lib_path == NULL)
+ goto exit;
+
+ list_for_each(node, &effect_libraries_list) {
+ effect_lib_temp = node_to_item(node, qahw_effect_lib_t, lib_list);
+ if(!strncmp(lib_path, effect_lib_temp->lib_path, PATH_MAX)) {
+ effect_lib = effect_lib_temp;
+ break;
+ }
+ }
+exit:
+ return effect_lib;
+}
+
+
+qahw_effect_lib_t *get_qahw_effect_lib_by_desc(qahw_effect_lib_handle_t handle) {
+ struct listnode *node = NULL;
+ qahw_effect_lib_t *effect_lib = NULL, *effect_lib_temp = NULL;
+
+ if (handle == NULL)
+ goto exit;
+
+ list_for_each(node, &effect_libraries_list) {
+ effect_lib_temp = node_to_item(node, qahw_effect_lib_t, lib_list);
+ if (effect_lib_temp->desc == (audio_effect_library_t *)handle) {
+ effect_lib = effect_lib_temp;
+ break;
+ }
+ }
+exit:
+ return effect_lib;
+}
+
+
+qahw_effect_lib_handle_t qahw_effect_load_library(const char *lib_path) {
+ audio_effect_library_t *desc;
+ qahw_effect_lib_t *qahw_effect_lib;
+ void *handle;
+
+ if (strlen(lib_path) >= PATH_MAX -1) {
+ ALOGE("%s: effect libraries path too long", __func__);
+ return NULL;
+ }
+
+ /* return existing lib handler if already loaded */
+ pthread_mutex_lock(&effect_libraries_lock);
+ if (effect_libraries_count > 0) {
+ qahw_effect_lib = get_qahw_effect_lib_by_name(lib_path);
+ if (qahw_effect_lib != NULL) {
+ desc = qahw_effect_lib->desc;
+ pthread_mutex_lock(&qahw_effect_lib->lock);
+ qahw_effect_lib->ref_count++;
+ pthread_mutex_unlock(&qahw_effect_lib->lock);
+ goto done;
+ }
+ }
+
+ handle = dlopen(lib_path, RTLD_NOW);
+ if (handle == NULL) {
+ ALOGE("%s: failed to dlopen lib %s", __func__, lib_path);
+ goto error;
+ }
+
+ desc = (audio_effect_library_t *)dlsym(handle, AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR);
+ if (desc == NULL) {
+ ALOGE("%s: could not find symbol %s", __func__, AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR);
+ goto error;
+ }
+
+ if (AUDIO_EFFECT_LIBRARY_TAG != desc->tag) {
+ ALOGE("%s: bad tag %08x in lib info struct", __func__, desc->tag);
+ goto error;
+ }
+
+ if (EFFECT_API_VERSION_MAJOR(desc->version) !=
+ EFFECT_API_VERSION_MAJOR(EFFECT_LIBRARY_API_VERSION)) {
+ ALOGE("%s: bad lib version %08x", __func__, desc->version);
+ goto error;
+ }
+
+ qahw_effect_lib = (qahw_effect_lib_t *)calloc(1, sizeof(qahw_effect_lib_t));
+ if (qahw_effect_lib == NULL) {
+ ALOGE("%s: calloc failed", __func__);
+ goto error;
+ }
+
+ if (!effect_libraries_count)
+ list_init(&effect_libraries_list);
+ effect_libraries_count++;
+
+ /* init and load effect lib into global list */
+ strlcpy(qahw_effect_lib->lib_path, lib_path, PATH_MAX);
+ pthread_mutex_init(&qahw_effect_lib->lock, (const pthread_mutexattr_t *) NULL);
+ qahw_effect_lib->ref_count = 1;
+ qahw_effect_lib->desc = desc;
+ qahw_effect_lib->handle = handle;
+
+ list_add_tail(&effect_libraries_list, &qahw_effect_lib->lib_list);
+
+done:
+ pthread_mutex_unlock(&effect_libraries_lock);
+ return (qahw_effect_lib_handle_t)desc;
+
+error:
+ if (handle != NULL)
+ dlclose(handle);
+
+ pthread_mutex_unlock(&effect_libraries_lock);
+ return NULL;
+}
+
+
+int32_t qahw_effect_unload_library(qahw_effect_lib_handle_t handle) {
+ qahw_effect_lib_t *qahw_effect_lib;
+
+ pthread_mutex_lock(&effect_libraries_lock);
+ if (effect_libraries_count <= 0) {
+ ALOGW("%s: no valid libraries loaded", __func__);
+ pthread_mutex_unlock(&effect_libraries_lock);
+ return -EINVAL;
+ }
+
+ qahw_effect_lib = get_qahw_effect_lib_by_desc(handle);
+ if (qahw_effect_lib == NULL) {
+ ALOGW("%s: effect lib handle(%p) not in loaded queue", __func__, (void *)handle);
+ pthread_mutex_unlock(&effect_libraries_lock);
+ return -EINVAL;
+ }
+
+ pthread_mutex_lock(&qahw_effect_lib->lock);
+ qahw_effect_lib->ref_count--;
+ if (qahw_effect_lib->ref_count > 0) {
+ ALOGW("%s: skip unloading effect lib, ref count %d", __func__, qahw_effect_lib->ref_count);
+ pthread_mutex_unlock(&qahw_effect_lib->lock);
+ goto done;
+ }
+
+ if (qahw_effect_lib->handle)
+ dlclose(qahw_effect_lib->handle);
+ effect_libraries_count--;
+ list_remove(&qahw_effect_lib->lib_list);
+ pthread_mutex_unlock(&qahw_effect_lib->lock);
+ pthread_mutex_destroy(&qahw_effect_lib->lock);
+ free(qahw_effect_lib);
+
+done:
+ pthread_mutex_unlock(&effect_libraries_lock);
+ return 0;
+}
+
+
+int32_t qahw_effect_create(qahw_effect_lib_handle_t handle,
+ const qahw_effect_uuid_t *uuid,
+ int32_t io_handle,
+ qahw_effect_handle_t *effect_handle) {
+ int32_t rc = -EINVAL;
+ audio_effect_library_t *desc = (audio_effect_library_t *)handle;
+
+ if (desc != NULL) {
+ rc = desc->create_effect((const effect_uuid_t *)uuid, 0, io_handle,
+ (effect_handle_t *)effect_handle);
+ }
+
+ return rc;
+}
+
+
+int32_t qahw_effect_release(qahw_effect_lib_handle_t handle,
+ qahw_effect_handle_t effect_handle) {
+ int32_t rc = -EINVAL;
+ audio_effect_library_t *desc = (audio_effect_library_t *)handle;
+
+ if (desc != NULL) {
+ rc = desc->release_effect((effect_handle_t)effect_handle);
+ }
+
+ return rc;
+}
+
+
+int32_t qahw_effect_get_descriptor(qahw_effect_lib_handle_t handle,
+ const qahw_effect_uuid_t *uuid,
+ qahw_effect_descriptor_t *effect_desc) {
+ int32_t rc = -EINVAL;
+ audio_effect_library_t *desc = (audio_effect_library_t *)handle;
+
+ if (desc != NULL) {
+ rc = desc->get_descriptor((const effect_uuid_t *)uuid, (effect_descriptor_t *)effect_desc);
+ }
+
+ return rc;
+}
+
+
+int32_t qahw_effect_get_version() {
+ return QAHW_EFFECT_API_VERSION_CURRENT;
+}
+
+
+int32_t qahw_effect_process(qahw_effect_handle_t self,
+ qahw_audio_buffer_t *in_buffer,
+ qahw_audio_buffer_t *out_buffer) {
+ int32_t rc = -EINVAL;
+ struct effect_interface_s *itfe;
+
+ if (self) {
+ itfe = *((struct effect_interface_s **)self);
+ if (itfe) {
+ rc = itfe->process((effect_handle_t)self,
+ (audio_buffer_t *)in_buffer,
+ (audio_buffer_t *)out_buffer);
+ }
+ }
+
+ return rc;
+}
+
+
+int32_t qahw_effect_command(qahw_effect_handle_t self,
+ uint32_t cmd_code,
+ uint32_t cmd_size,
+ void *cmd_data,
+ uint32_t *reply_size,
+ void *reply_data) {
+ int32_t rc = -EINVAL;
+ struct effect_interface_s *itfe;
+
+ if (self) {
+ itfe = *((struct effect_interface_s **)self);
+ if (itfe) {
+ rc = itfe->command((effect_handle_t)self, cmd_code, cmd_size,
+ cmd_data, reply_size, reply_data);
+ }
+ }
+
+ return rc;
+}
+
+
+int32_t qahw_effect_process_reverse(qahw_effect_handle_t self,
+ qahw_audio_buffer_t *in_buffer,
+ qahw_audio_buffer_t *out_buffer) {
+ int32_t rc = -EINVAL;
+ struct effect_interface_s *itfe;
+
+ if (self) {
+ itfe = *((struct effect_interface_s **)self);
+ if (itfe) {
+ rc = itfe->process_reverse((effect_handle_t)self,
+ (audio_buffer_t *)in_buffer,
+ (audio_buffer_t *)out_buffer);
+ }
+ }
+
+ return rc;
+}
+