diff --git a/configure.ac b/configure.ac index 572e07da..89326c0e 100755 --- a/configure.ac +++ b/configure.ac @@ -141,6 +141,7 @@ AM_CONDITIONAL([CUSTOM_STEREO], [test x$AUDIO_FEATURE_ENABLED_CUSTOM_STEREO = xt AM_CONDITIONAL([RUN_KEEP_ALIVE_IN_ARM_FFV], [test x$AUDIO_FEATURE_ENABLED_KEEP_ALIVE_ARM_FFV = xtrue]) AM_CONDITIONAL([INSTANCE_ID], [test x$AUDIO_FEATURE_ENABLED_INSTANCE_ID = xtrue]) AM_CONDITIONAL([LL_AS_PRIMARY_OUTPUT], [test x$AUDIO_USE_LL_AS_PRIMARY_OUTPUT = xtrue]) +AM_CONDITIONAL([QAHW_V1], [test x$AUDIO_FEATURE_ENABLED_QAHW_1_0 = xtrue]) AC_CONFIG_FILES([ \ Makefile \ diff --git a/qahw/Makefile.am b/qahw/Makefile.am index b78c9b78..fccf0039 100644 --- a/qahw/Makefile.am +++ b/qahw/Makefile.am @@ -17,6 +17,10 @@ if SVA_AUDIO_CONCURRENCY AM_CFLAGS += -DSVA_AUDIO_CONC endif +if QAHW_V1 +AM_CFLAGS += -DQAHW_V1 +endif + libqahwwrapper_la_CFLAGS = $(AM_CFLAGS) libqahwwrapper_la_CFLAGS += -include stddef.h libqahwwrapper_la_CFLAGS += -Dstrlcpy=g_strlcpy $(GLIB_CFLAGS) -include glib.h diff --git a/qahw/configure.ac b/qahw/configure.ac index 5bd3a229..94ca645a 100644 --- a/qahw/configure.ac +++ b/qahw/configure.ac @@ -30,6 +30,7 @@ AC_PROG_MAKE_SET PKG_PROG_PKG_CONFIG AM_CONDITIONAL([SVA_AUDIO_CONCURRENCY],[test x$BOARD_SUPPORTS_SVA_AUDIO_CONCURRENCY = xtrue]) +AM_CONDITIONAL([QAHW_V1], [test x$AUDIO_FEATURE_ENABLED_QAHW_1_0 = xtrue]) AC_ARG_WITH([glib], AC_HELP_STRING([--with-glib], [enable glib, Build against glib. Use this when building for HLOS systems which use glib])) diff --git a/qahw/inc/qahw.h b/qahw/inc/qahw.h index 5020c8f2..dd920e2f 100644 --- a/qahw/inc/qahw.h +++ b/qahw/inc/qahw.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * Not a Contribution. * * Copyright (C) 2011 The Android Open Source Project * @@ -45,6 +45,9 @@ __BEGIN_DECLS /* First generation of audio devices had version hardcoded to 0. all devices with * versions < 1.0 will be considered of first generation API. */ +#if QAHW_V1 +#define QAHW_MODULE_API_VERSION_1_0 QAHW_MAKE_API_VERSION(1, 0) +#endif #define QAHW_MODULE_API_VERSION_0_0 QAHW_MAKE_API_VERSION(0, 0) /* Minimal QTI audio HAL version supported by the audio framework */ diff --git a/qahw/inc/qahw_defs.h b/qahw/inc/qahw_defs.h index 7d136d2d..b0eb332a 100644 --- a/qahw/inc/qahw_defs.h +++ b/qahw/inc/qahw_defs.h @@ -18,6 +18,7 @@ #include #include +#include #ifndef QTI_AUDIO_HAL_DEFS_H #define QTI_AUDIO_HAL_DEFS_H @@ -171,6 +172,9 @@ __BEGIN_DECLS #define QAHW_INPUT_FLAG_TIMESTAMP 0x80000000 #define QAHW_INPUT_FLAG_COMPRESS 0x40000000 #define QAHW_INPUT_FLAG_PASSTHROUGH 0x20000000 +#define QAHW_OUTPUT_FLAG_INCALL_MUSIC 0x80000000 +#define QAHW_AUDIO_FLAG_HPCM_TX 0x00020000 +#define QAHW_AUDIO_FLAG_HPCM_RX 0x00040000 /* Query fm volume */ #define QAHW_PARAMETER_KEY_FM_VOLUME "fm_volume" @@ -267,6 +271,14 @@ typedef struct { uint32_t reserved[64]; /*reserved for future */ } qahw_in_buffer_t; +typedef struct { + void *buffer; /* write buffer pointer */ + size_t size; /* 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 */ +} qahw_buffer_t; + #define MAX_SECTORS 8 struct qahw_source_tracking_param { @@ -391,6 +403,42 @@ typedef struct qahw_license_params { char license[QAHW_LICENCE_STR_MAX_LENGTH + 1]; } qahw_license_params_t; +typedef struct qahw_dtmf_gen_params { + bool enable; + uint16_t low_freq; + uint16_t high_freq; + uint16_t gain; +} qahw_dtmf_gen_params_t; + +enum { + QAHW_TTY_MODE_OFF, + QAHW_TTY_MODE_FULL, + QAHW_TTY_MODE_VCO, + QAHW_TTY_MODE_HCO, + QAHW_TTY_MODE_MAX, +}; + +typedef struct qahw_tty_params { + uint32_t mode; +} qahw_tty_params_t; + +typedef enum { + QAHW_HPCM_TAP_POINT_RX = 1, + QAHW_HPCM_TAP_POINT_TX = 2, + QAHW_HPCM_TAP_POINT_RX_TX = 3, +} qahw_hpcm_tap_point; + +typedef enum { + QAHW_HPCM_DIRECTION_OUT, + QAHW_HPCM_DIRECTION_IN, + QAHW_HPCM_DIRECTION_OUT_IN, +} qahw_hpcm_direction; + +typedef struct qahw_hpcm_params { + qahw_hpcm_tap_point tap_point; + qahw_hpcm_direction direction; +} qahw_hpcm_params_t; + typedef union { struct qahw_source_tracking_param st_params; struct qahw_sound_focus_param sf_params; @@ -406,6 +454,9 @@ typedef union { struct qahw_mix_matrix_params mix_matrix_params; struct qahw_license_params license_params; struct qahw_out_presentation_position_param pos_param; + struct qahw_dtmf_gen_params dtmf_gen_params; + struct qahw_tty_params tty_mode_params; + struct qahw_hpcm_params hpcm_params; } qahw_param_payload; typedef enum { @@ -426,6 +477,9 @@ typedef enum { QAHW_PARAM_CH_MIX_MATRIX_PARAMS, QAHW_PARAM_LICENSE_PARAMS, QAHW_PARAM_OUT_PRESENTATION_POSITION, + QAHW_PARAM_DTMF_GEN, + QAHW_PARAM_TTY_MODE, + QAHW_PARAM_HPCM, } qahw_param_id; typedef union { @@ -436,6 +490,94 @@ typedef enum { QAHW_PARAM_LOOPBACK_RENDER_WINDOW /* PARAM to set render window */ } qahw_loopback_param_id; +/** stream direction enumeration */ +typedef enum { + QAHW_STREAM_INPUT, + QAHW_STREAM_OUTPUT, + QAHW_STREAM_INPUT_OUTPUT, +} qahw_stream_direction; + +/** stream types */ +typedef enum { + QAHW_STREAM_TYPE_INVALID, + QAHW_AUDIO_PLAYBACK_LOW_LATENCY, /**< low latency, higher power*/ + QAHW_AUDIO_PLAYBACK_DEEP_BUFFER, /**< low power, higher latency*/ + QAHW_AUDIO_PLAYBACK_COMPRESSED, /**< compresssed audio*/ + QAHW_AUDIO_PLAYBACK_VOIP, /**< pcm voip audio*/ + QAHW_AUDIO_PLAYBACK_VOICE_CALL_MUSIC, /**< pcm voip audio*/ + + QAHW_AUDIO_CAPTURE_LOW_LATENCY, /**< low latency, higher power*/ + QAHW_AUDIO_CAPTURE_DEEP_BUFFER, /**< low power, higher latency*/ + QAHW_AUDIO_CAPTURE_COMPRESSED, /**< compresssed audio*/ + QAHW_AUDIO_CAPTURE_RAW, /**< pcm no post processing*/ + QAHW_AUDIO_CAPTURE_VOIP, /**< pcm voip audio*/ + QAHW_AUDIO_CAPTURE_VOICE_ACTIVATION, /**< voice activation*/ + QAHW_AUDIO_CAPTURE_VOICE_CALL_RX, /**< incall record, downlink */ + QAHW_AUDIO_CAPTURE_VOICE_CALL_TX, /**< incall record, uplink */ + QAHW_AUDIO_CAPTURE_VOICE_CALL_RX_TX, /**< incall record, uplink & Downlink */ + + QAHW_VOICE_CALL, /**< voice call */ + + QAHW_AUDIO_TRANSCODE, /**< audio transcode */ + QAHW_AUDIO_HOST_PCM_TX, + QAHW_AUDIO_HOST_PCM_RX, + QAHW_AUDIO_HOST_PCM_TX_RX, + QAHW_AUDIO_STREAM_TYPE_MAX, +} qahw_audio_stream_type; + +typedef uint32_t qahw_device_t; + +/**< Key value pair to identify the topology of a usecase from default */ +struct qahw_modifier_kv { + uint32_t key; + uint32_t value; +}; + +struct qahw_shared_attributes{ + audio_config_t config; +}; +struct qahw_voice_attributes{ + audio_config_t config; + const char *vsid; +}; + +struct qahw_audio_attributes{ + audio_config_t config; +}; + +typedef union { + struct qahw_shared_attributes shared; + struct qahw_voice_attributes voice; + struct qahw_audio_attributes audio; +} qahw_stream_attributes_config; + +struct qahw_stream_attributes { + qahw_audio_stream_type type; + qahw_stream_direction direction; + qahw_stream_attributes_config attr; +}; + +typedef enum { + QAHW_CHANNEL_L = 0, /*left channel*/ + QAHW_CHANNEL_R = 1, /*right channel*/ + QAHW_CHANNELS_MAX = 2, /*max number of supported streams*/ +} qahw_channel_map; + +struct qahw_channel_vol { + qahw_channel_map channel; + float vol; +}; + +struct qahw_volume_data { + uint32_t num_of_channels; + struct qahw_channel_vol *vol_pair; +}; + +struct qahw_mute_data { + bool enable; + qahw_stream_direction direction; +}; + __END_DECLS #endif // QTI_AUDIO_HAL_DEFS_H diff --git a/qahw/src/qahw.c b/qahw/src/qahw.c index ceec6579..2ae69062 100644 --- a/qahw/src/qahw.c +++ b/qahw/src/qahw.c @@ -1,5 +1,5 @@ /* -* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. +* Copyright (c) 2016-2019, 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 @@ -45,8 +45,13 @@ /* * The current HAL API version. + * version 1.0 has support for voice only in new stream based APIS */ +#ifdef QAHW_MODULE_API_VERSION_1_0 +#define QAHW_MODULE_API_VERSION_CURRENT QAHW_MODULE_API_VERSION_1_0 +#else #define QAHW_MODULE_API_VERSION_CURRENT QAHW_MODULE_API_VERSION_0_0 +#endif typedef uint64_t (*qahwi_out_write_v2_t)(audio_stream_out_t *out, const void* buffer, diff --git a/qahw_api/Makefile.am b/qahw_api/Makefile.am index 38506b83..e4cbdb51 100644 --- a/qahw_api/Makefile.am +++ b/qahw_api/Makefile.am @@ -22,8 +22,13 @@ libqahw_la_CPPFLAGS := $(AM_CPPFLAGS) libqahw_la_CPPFLAGS += -std=c++11 -DHAVE_PTHREADS -DHAVE_ANDROID_OS libqahw_la_CPPFLAGS += -DDEBUG_REFS_CALLSTACK_ENABLED=0 libqahw_la_CPPFLAGS += -DNDEBUG -libqahw_la_LDFLAGS = -ltinyalsa -lhardware -lexpat -lcutils -llog -ldl -shared -avoid-version -lpthread -lutils +libqahw_la_CPPFLAGS += $(GLIB_CFLAGS) -include glib.h +libqahw_la_LDFLAGS = -ltinyalsa -lhardware -lexpat -lcutils -llog -ldl -shared -avoid-version -lpthread -lutils $(GLIB_LIBS) if QTI_AUDIO_SERVER_ENABLED AM_CPPFLAGS += -DQTI_AUDIO_SERVER_ENABLED libqahw_la_LDFLAGS += -lqtiaudioserver -lbinder endif +if QAHW_V1 +AM_CPPFLAGS += -DQAHW_V1 +endif + diff --git a/qahw_api/inc/qahw_api.h b/qahw_api/inc/qahw_api.h index b37757d1..80d9c645 100644 --- a/qahw_api/inc/qahw_api.h +++ b/qahw_api/inc/qahw_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * Not a Contribution. * * Copyright (C) 2011 The Android Open Source Project * @@ -485,6 +485,75 @@ int qahw_set_audio_port_config(qahw_module_handle_t *hw_module, void qahw_register_qas_death_notify_cb(audio_error_callback cb, void* context); +/* updated new stream APIs to support voice and Audio use cases */ + +int qahw_stream_open(qahw_module_handle_t *hw_module, + struct qahw_stream_attributes attr, + uint32_t num_of_devices, + qahw_device_t *devices, + uint32_t no_of_modifiers, + struct qahw_modifier_kv *modifiers, + qahw_stream_callback_t cb, + void *cookie, + qahw_stream_handle_t **stream_handle); + +int qahw_stream_close(qahw_stream_handle_t *stream_handle); + +int qahw_stream_start(qahw_stream_handle_t *stream_handle); + +int qahw_stream_stop(qahw_stream_handle_t *stream_handle); + +int qahw_stream_set_device(qahw_stream_handle_t *stream_handle, + uint32_t num_of_dev, + qahw_device_t *devices); + +int qahw_stream_get_device(qahw_stream_handle_t *stream_handle, + uint32_t *num_of_dev, + qahw_device_t **devices); + +int qahw_stream_set_volume(qahw_stream_handle_t *stream_handle, + struct qahw_volume_data vol_data); + +int qahw_stream_get_volume(qahw_stream_handle_t *stream_handle, + struct qahw_volume_data **vol_data); + +int qahw_stream_set_mute(qahw_stream_handle_t *stream_handle, + struct qahw_mute_data mute_data); + +int qahw_stream_get_mute(qahw_stream_handle_t *stream_handle, + struct qahw_mute_data *mute_data); + +ssize_t qahw_stream_read(qahw_stream_handle_t *stream_handle, + qahw_buffer_t *in_buf); + +ssize_t qahw_stream_write(qahw_stream_handle_t *stream_handle, + qahw_buffer_t *out_buf); + +int32_t qahw_stream_pause(qahw_stream_handle_t *stream_handle); + +int32_t qahw_stream_standby(qahw_stream_handle_t *stream_handle); + +int32_t qahw_stream_resume(qahw_stream_handle_t *stream_handle); + +int32_t qahw_stream_flush(qahw_stream_handle_t *stream_handle); + +int32_t qahw_stream_drain(qahw_stream_handle_t *stream_handle, + qahw_drain_type_t type); + +int32_t qahw_stream_get_buffer_size(const qahw_stream_handle_t *stream_handle, + size_t *in_buffer, size_t *out_buffer); + +int32_t qahw_stream_set_buffer_size(const qahw_stream_handle_t *stream_handle, + size_t in_buffer, size_t out_buffer); + +int32_t qahw_stream_set_parameters(qahw_stream_handle_t *stream_handle, + uint32_t param_id, + qahw_param_payload *param_payload); + +int32_t qahw_stream_get_parameters(qahw_stream_handle_t *stream_handle, + uint32_t param_id, + qahw_param_payload *param_payload); + __END_DECLS #endif // QTI_AUDIO_QAHW_API_H diff --git a/qahw_api/inc/qahw_defs.h b/qahw_api/inc/qahw_defs.h index 7bd51185..f979013a 100644 --- a/qahw_api/inc/qahw_defs.h +++ b/qahw_api/inc/qahw_defs.h @@ -18,6 +18,7 @@ #include #include +#include #ifndef QTI_AUDIO_HAL_DEFS_H #define QTI_AUDIO_HAL_DEFS_H @@ -171,6 +172,9 @@ __BEGIN_DECLS #define QAHW_INPUT_FLAG_TIMESTAMP 0x80000000 #define QAHW_INPUT_FLAG_COMPRESS 0x40000000 #define QAHW_INPUT_FLAG_PASSTHROUGH 0x20000000 +#define QAHW_OUTPUT_FLAG_INCALL_MUSIC 0x80000000 +#define QAHW_AUDIO_FLAG_HPCM_TX 0x00020000 +#define QAHW_AUDIO_FLAG_HPCM_RX 0x00040000 /* Query fm volume */ #define QAHW_PARAMETER_KEY_FM_VOLUME "fm_volume" @@ -245,6 +249,14 @@ typedef struct { uint32_t reserved[64]; /*reserved for future */ } qahw_in_buffer_t; +typedef struct { + void *buffer; /* write buffer pointer */ + size_t size; /* 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 */ +} qahw_buffer_t; + #define MAX_SECTORS 8 struct qahw_source_tracking_param { @@ -370,6 +382,42 @@ typedef struct qahw_license_params { char license[QAHW_LICENCE_STR_MAX_LENGTH + 1]; } qahw_license_params_t; +typedef struct qahw_dtmf_gen_params { + bool enable; + uint16_t low_freq; + uint16_t high_freq; + uint16_t gain; +} qahw_dtmf_gen_params_t; + +enum { + QAHW_TTY_MODE_OFF, + QAHW_TTY_MODE_FULL, + QAHW_TTY_MODE_VCO, + QAHW_TTY_MODE_HCO, + QAHW_TTY_MODE_MAX, +}; + +typedef struct qahw_tty_params { + uint32_t mode; +} qahw_tty_params_t; + +typedef enum { + QAHW_HPCM_TAP_POINT_RX = 1, + QAHW_HPCM_TAP_POINT_TX = 2, + QAHW_HPCM_TAP_POINT_RX_TX = 3, +} qahw_hpcm_tap_point; + +typedef enum { + QAHW_HPCM_DIRECTION_OUT, + QAHW_HPCM_DIRECTION_IN, + QAHW_HPCM_DIRECTION_OUT_IN, +} qahw_hpcm_direction; + +typedef struct qahw_hpcm_params { + qahw_hpcm_tap_point tap_point; + qahw_hpcm_direction direction; +} qahw_hpcm_params_t; + typedef union { struct qahw_source_tracking_param st_params; struct qahw_sound_focus_param sf_params; @@ -385,6 +433,9 @@ typedef union { struct qahw_mix_matrix_params mix_matrix_params; struct qahw_license_params license_params; struct qahw_out_presentation_position_param pos_param; + struct qahw_dtmf_gen_params dtmf_gen_params; + struct qahw_tty_params tty_mode_params; + struct qahw_hpcm_params hpcm_params; } qahw_param_payload; typedef enum { @@ -405,6 +456,9 @@ typedef enum { QAHW_PARAM_CH_MIX_MATRIX_PARAMS, QAHW_PARAM_LICENSE_PARAMS, QAHW_PARAM_OUT_PRESENTATION_POSITION, + QAHW_PARAM_DTMF_GEN, + QAHW_PARAM_TTY_MODE, + QAHW_PARAM_HPCM, } qahw_param_id; @@ -416,6 +470,94 @@ typedef enum { QAHW_PARAM_LOOPBACK_RENDER_WINDOW /* PARAM to set render window */ } qahw_loopback_param_id; +/** stream direction enumeration */ +typedef enum { + QAHW_STREAM_INPUT, + QAHW_STREAM_OUTPUT, + QAHW_STREAM_INPUT_OUTPUT, +} qahw_stream_direction; + +/** stream types */ +typedef enum { + QAHW_STREAM_TYPE_INVALID, + QAHW_AUDIO_PLAYBACK_LOW_LATENCY, /**< low latency, higher power*/ + QAHW_AUDIO_PLAYBACK_DEEP_BUFFER, /**< low power, higher latency*/ + QAHW_AUDIO_PLAYBACK_COMPRESSED, /**< compresssed audio*/ + QAHW_AUDIO_PLAYBACK_VOIP, /**< pcm voip audio*/ + QAHW_AUDIO_PLAYBACK_VOICE_CALL_MUSIC, /**< pcm voip audio*/ + + QAHW_AUDIO_CAPTURE_LOW_LATENCY, /**< low latency, higher power*/ + QAHW_AUDIO_CAPTURE_DEEP_BUFFER, /**< low power, higher latency*/ + QAHW_AUDIO_CAPTURE_COMPRESSED, /**< compresssed audio*/ + QAHW_AUDIO_CAPTURE_RAW, /**< pcm no post processing*/ + QAHW_AUDIO_CAPTURE_VOIP, /**< pcm voip audio*/ + QAHW_AUDIO_CAPTURE_VOICE_ACTIVATION, /**< voice activation*/ + QAHW_AUDIO_CAPTURE_VOICE_CALL_RX, /**< incall record, downlink */ + QAHW_AUDIO_CAPTURE_VOICE_CALL_TX, /**< incall record, uplink */ + QAHW_AUDIO_CAPTURE_VOICE_CALL_RX_TX, /**< incall record, uplink & Downlink */ + + QAHW_VOICE_CALL, /**< voice call */ + + QAHW_AUDIO_TRANSCODE, /**< audio transcode */ + QAHW_AUDIO_HOST_PCM_TX, + QAHW_AUDIO_HOST_PCM_RX, + QAHW_AUDIO_HOST_PCM_TX_RX, + QAHW_AUDIO_STREAM_TYPE_MAX, +} qahw_audio_stream_type; + +typedef uint32_t qahw_device_t; + +/**< Key value pair to identify the topology of a usecase from default */ +struct qahw_modifier_kv { + uint32_t key; + uint32_t value; +}; + +struct qahw_shared_attributes{ + audio_config_t config; +}; +struct qahw_voice_attributes{ + audio_config_t config; + const char *vsid; +}; + +struct qahw_audio_attributes{ + audio_config_t config; +}; + +typedef union { + struct qahw_shared_attributes shared; + struct qahw_voice_attributes voice; + struct qahw_audio_attributes audio; +} qahw_stream_attributes_config; + +struct qahw_stream_attributes { + qahw_audio_stream_type type; + qahw_stream_direction direction; + qahw_stream_attributes_config attr; +}; + +typedef enum { + QAHW_CHANNEL_L = 0, /*left channel*/ + QAHW_CHANNEL_R = 1, /*right channel*/ + QAHW_CHANNELS_MAX = 2, /*max number of supported streams*/ +} qahw_channel_map; + +struct qahw_channel_vol { + qahw_channel_map channel; + float vol; +}; + +struct qahw_volume_data { + uint32_t num_of_channels; + struct qahw_channel_vol *vol_pair; +}; + +struct qahw_mute_data { + bool enable; + qahw_stream_direction direction; +}; + __END_DECLS #endif // QTI_AUDIO_HAL_DEFS_H diff --git a/qahw_api/src/qahw_api.cpp b/qahw_api/src/qahw_api.cpp index 0810ede3..cbde5e30 100644 --- a/qahw_api/src/qahw_api.cpp +++ b/qahw_api/src/qahw_api.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. +* Copyright (c) 2016-2019, 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 @@ -37,11 +37,99 @@ #include #include #include +#include #include #include #include "qahw_api.h" #include "qahw.h" +#include + +#ifndef ANDROID +#define strlcpy g_strlcpy +#define strlcat g_strlcat +#endif + +#if QAHW_V1 +#define QAHW_DEV_ROUTE_LENGTH 15 +#define QAHW_KV_PAIR_LENGTH 255 +#define QAHW_NUM_OF_ROUTINGS 4 +#define QAHW_NUM_OF_SESSIONS 4 +#define QAHW_NAMES_PER_SESSION 2 +#define QAHW_SESSION_NAME_MAX_LEN 255 +#define QAHW_MAX_INT_STRING 12 +#define QAHW_NUM_OF_MUTE_TYPES 4 + +#define MAX_NUM_DEVICES 10 + +typedef struct { + qahw_stream_handle_t *out_stream; + qahw_stream_handle_t *in_stream; + qahw_module_handle_t *hw_module; + uint32_t num_of_devices; + audio_devices_t devices[MAX_NUM_DEVICES]; + qahw_stream_direction dir; + qahw_audio_stream_type type; + struct qahw_volume_data vol; + struct qahw_mute_data out_mute; + struct qahw_mute_data in_mute; +} qahw_api_stream_t; + +/* Array to store sound devices */ +static const char * const stream_name_map[QAHW_AUDIO_STREAM_TYPE_MAX] = { + [QAHW_STREAM_TYPE_INVALID] = "", + [QAHW_AUDIO_PLAYBACK_LOW_LATENCY]= "playback-low-latency", + [QAHW_AUDIO_PLAYBACK_DEEP_BUFFER]= "playback-deep-buffer", + [QAHW_AUDIO_PLAYBACK_COMPRESSED]= "playback-compressed", + [QAHW_AUDIO_PLAYBACK_VOIP]= "playback-voip", + [QAHW_AUDIO_PLAYBACK_VOICE_CALL_MUSIC]= "playback-in-call-music", + [QAHW_AUDIO_CAPTURE_LOW_LATENCY]= "capture-low-latency", + [QAHW_AUDIO_CAPTURE_DEEP_BUFFER]= "capture-deep-buffer", + [QAHW_AUDIO_CAPTURE_COMPRESSED]= "capture-compressed", + [QAHW_AUDIO_CAPTURE_RAW]= "capture-raw", + [QAHW_AUDIO_CAPTURE_VOIP]= "capture-voip", + [QAHW_AUDIO_CAPTURE_VOICE_ACTIVATION]= "capture-voice-activation", + [QAHW_AUDIO_CAPTURE_VOICE_CALL_RX]= "capture-voice-rx", + [QAHW_AUDIO_CAPTURE_VOICE_CALL_TX]= "capture-voice-tx", + [QAHW_AUDIO_CAPTURE_VOICE_CALL_RX_TX]= "capture-voice-rx-tx", + [QAHW_VOICE_CALL]= "voice-call", + [QAHW_AUDIO_TRANSCODE]= "audio-transcode", + [QAHW_AUDIO_HOST_PCM_TX]= "host-pcm-tx", + [QAHW_AUDIO_HOST_PCM_RX]= "host-pcm-rx", + [QAHW_AUDIO_HOST_PCM_TX_RX]= "host-pcm-tx-rx", +}; + +static const char * const tty_mode_map[QAHW_TTY_MODE_MAX] = { + [QAHW_TTY_MODE_OFF] = "tty_mode=tty_off", + [QAHW_TTY_MODE_FULL] = "tty_mode=tty_full", + [QAHW_TTY_MODE_VCO] = "tty_mode=tty_vco", + [QAHW_TTY_MODE_HCO] = "tty_mode=tty_hco", +}; + +typedef struct { + char sess_id[QAHW_NAMES_PER_SESSION][QAHW_SESSION_NAME_MAX_LEN + 1]; + char sess_id_call_state[QAHW_KV_PAIR_LENGTH]; +} session_info_t; + +static session_info_t session_info[QAHW_NUM_OF_SESSIONS] = { + {{"default mmodevoice1", "11C05000"}, "vsid=297816064;call_state=2"}, + {{"default mmodevoice2", "11DC5000"}, "vsid=299651072;call_state=2"}, + {{"default modem voice", "10C01000"}, "vsid=281022464;call_state=2"}, + {{"default volte voice", "10C02000"}, "vsid=281026560;call_state=2"} +}; + +typedef struct { + struct qahw_mute_data mute; + char mute_state[QAHW_KV_PAIR_LENGTH]; +} qahw_mute_info_t; + +static qahw_mute_info_t mute_info[QAHW_NUM_OF_MUTE_TYPES] = { + {{1, QAHW_STREAM_INPUT}, "device_mute=true;direction=tx" }, + {{0, QAHW_STREAM_INPUT}, "device_mute=false;direction=tx" }, + {{1, QAHW_STREAM_OUTPUT}, "device_mute=true;direction=rx" }, + {{0, QAHW_STREAM_OUTPUT}, "device_mute=false;direction=rx" }, +}; +#endif #if QTI_AUDIO_SERVER_ENABLED #include @@ -1817,4 +1905,1062 @@ qahw_module_handle_t *qahw_load_module(const char *hw_module_id) ALOGV("%d:%s",__LINE__, __func__); return qahw_load_module_l(hw_module_id); } + +#if QAHW_V1 +char * qahw_get_session_id(const char* vsid) +{ + int i = 0; + int j = 0; + char *ret = "vsid=281022464;call_state=2"; + + for(i = 0; i < QAHW_NUM_OF_SESSIONS; i++) { + for(j = 0; j < QAHW_NAMES_PER_SESSION; j++) { + if(!strcmp(vsid,session_info[i].sess_id[j])) { + ret = session_info[i].sess_id_call_state; + ALOGV("%s: vsid %s\n", __func__, vsid); + break; + } + } + } + ALOGV("%s: sess_id_call_state %s\n", __func__, ret); + return ret; +} + +int qahw_add_flags_source(struct qahw_stream_attributes attr, + int *flags, audio_source_t *source) { + int rc = 0; + /*default source */ + if (source && flags) { + *source = AUDIO_SOURCE_MIC; + /*default flag*/ + *flags = 0; + } else + return -EINVAL; + + switch (attr.type) { + case QAHW_AUDIO_PLAYBACK_LOW_LATENCY: + /*TODO*/ + break; + case QAHW_AUDIO_PLAYBACK_DEEP_BUFFER: + *flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER; + break; + case QAHW_AUDIO_PLAYBACK_COMPRESSED: + *flags = AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD; + break; + case QAHW_AUDIO_PLAYBACK_VOIP: + /*TODO*/ + break; + case QAHW_AUDIO_PLAYBACK_VOICE_CALL_MUSIC: + *flags = QAHW_OUTPUT_FLAG_INCALL_MUSIC; + break; + case QAHW_AUDIO_CAPTURE_LOW_LATENCY: + /*TODO*/ + break; + case QAHW_AUDIO_CAPTURE_DEEP_BUFFER: + /*TODO*/ + break; + case QAHW_AUDIO_CAPTURE_COMPRESSED: + /*TODO*/ + break; + case QAHW_AUDIO_CAPTURE_RAW: + /*TODO*/ + break; + case QAHW_AUDIO_CAPTURE_VOIP: + break; + case QAHW_AUDIO_CAPTURE_VOICE_ACTIVATION: + /*TODO*/ + break; + case QAHW_AUDIO_CAPTURE_VOICE_CALL_RX: + *source = AUDIO_SOURCE_VOICE_DOWNLINK; + break; + case QAHW_AUDIO_CAPTURE_VOICE_CALL_TX: + *source = AUDIO_SOURCE_VOICE_UPLINK; + break; + case QAHW_AUDIO_CAPTURE_VOICE_CALL_RX_TX: + /*unsupported */ + break; + case QAHW_VOICE_CALL: + *flags = AUDIO_OUTPUT_FLAG_PRIMARY; + break; + case QAHW_AUDIO_TRANSCODE: + /*TODO*/ + break; + case QAHW_AUDIO_HOST_PCM_TX: + *flags = QAHW_AUDIO_FLAG_HPCM_TX; + break; + case QAHW_AUDIO_HOST_PCM_RX: + *flags = QAHW_AUDIO_FLAG_HPCM_RX; + break; + case QAHW_AUDIO_HOST_PCM_TX_RX: + /*TODO*/ + break; + default: + rc = -EINVAL; + break; + } + + return rc; +} + +int qahw_stream_open(qahw_module_handle_t *hw_module, + struct qahw_stream_attributes attr, + uint32_t num_of_devices, + qahw_device_t *devices, + uint32_t no_of_modifiers, + struct qahw_modifier_kv *modifiers, + qahw_stream_callback_t cb, + void *cookie, + qahw_stream_handle_t **stream_handle) { + + audio_io_handle_t handle = 0x999; + int rc = -EINVAL; + const char *address = stream_name_map[attr.type]; + const char *session_id; + int flags = 0; + audio_source_t source = AUDIO_SOURCE_MIC; + qahw_api_stream_t *stream; + struct qahw_channel_vol *vols; + + /* validate number of devices */ + if (num_of_devices > MAX_NUM_DEVICES) + { + ALOGE("%s: invalid number of devices for stream", __func__); + return rc; + } + /* validate direction for voice stream */ + if (attr.type == QAHW_VOICE_CALL && + attr.direction != QAHW_STREAM_INPUT_OUTPUT) { + ALOGE("%s: invalid direction for a voice stream", __func__); + return rc; + } + /* add flag*/ + rc = qahw_add_flags_source(attr, &flags, &source); + + if (rc) { + ALOGE("%s: invalid type %d", __func__, attr.type); + return rc; + } + + stream = (qahw_api_stream_t *)calloc(1, sizeof(qahw_api_stream_t)); + if (!stream) { + ALOGE("%s: stream allocation failed ", __func__); + return -ENOMEM; + } + vols = (struct qahw_channel_vol *) + calloc(1, sizeof(struct qahw_channel_vol)*QAHW_CHANNELS_MAX); + if (!vols) { + ALOGE("%s: vol allocation failed ", __func__); + return -ENOMEM; + } + + memset(stream, 0, sizeof(qahw_api_stream_t)); + memset(vols, 0, sizeof(struct qahw_channel_vol)*QAHW_CHANNELS_MAX); + stream->dir = attr.direction; + stream->hw_module = hw_module; + stream->num_of_devices = num_of_devices; + memset(&stream->devices[0], 0, sizeof(stream->devices)); + memcpy(&stream->devices[0], devices, num_of_devices); + stream->type = attr.type; + stream->vol.vol_pair = vols; + /* if voice call stream, num_of_channels set to 1 */ + if (attr.type == QAHW_VOICE_CALL) + stream->vol.num_of_channels = 1; + else + stream->vol.num_of_channels = QAHW_CHANNELS_MAX; + + switch (attr.direction) { + case QAHW_STREAM_INPUT_OUTPUT: + /*for now only support one stream to one device*/ + if (num_of_devices != 2 && attr.type != QAHW_VOICE_CALL) { + ALOGE("%s: invalid num of streams %d for dir %d", + __func__, num_of_devices, attr.direction); + return rc; + } + rc = qahw_open_output_stream(hw_module, handle, devices[0], + (audio_output_flags_t)flags, + &(attr.attr.shared.config), + &stream->out_stream, + address); + /*set cb function */ + if (rc) + rc = qahw_out_set_callback(stream->out_stream, cb, cookie); + if (rc) + ALOGE("%s: setting callback failed %d \n", __func__, rc); + + if (attr.type != QAHW_VOICE_CALL) { + rc = qahw_open_input_stream(hw_module, handle, devices[1], + &(attr.attr.shared.config), + &stream->in_stream, + (audio_input_flags_t)flags, + address, + source); + } + break; + case QAHW_STREAM_OUTPUT: + if (num_of_devices != 1) { + ALOGE("%s: invalid num of streams %d for dir %d", + __func__, num_of_devices, attr.direction); + return rc; + } + rc = qahw_open_output_stream(hw_module, handle, devices[0], + (audio_output_flags_t)flags, + &(attr.attr.shared.config), + &stream->out_stream, + address); + /*set cb function */ + if (rc) + rc = qahw_out_set_callback(stream->out_stream, cb, cookie); + if (rc) + ALOGE("%s: setting callback failed %d \n", __func__, rc); + break; + case QAHW_STREAM_INPUT: + if (num_of_devices != 1) { + ALOGE("%s: invalid num of streams %d for dir %d", + __func__, num_of_devices, attr.direction); + return rc; + } + rc = qahw_open_input_stream(hw_module, handle, devices[0], + &(attr.attr.shared.config), + &stream->in_stream, + (audio_input_flags_t)flags, + address, + source); + break; + default: + ALOGE("%s: invalid stream direction %d ", __func__, attr.direction); + return rc; + } + /*set the stream type as the handle add to list*/ + *stream_handle = (qahw_stream_handle_t *)stream; + + /*if voice call set vsid and call state/mode*/ + if (attr.type == QAHW_VOICE_CALL) { + session_id = qahw_get_session_id(attr.attr.voice.vsid); + + rc = qahw_set_parameters(hw_module, session_id); + if (rc) { + ALOGE("%s: setting vsid failed %d \n", __func__, rc); + } + } + + if(no_of_modifiers){ + ALOGE("%s: modifiers not currently supported\n", __func__); + } + return rc; +} + +int qahw_stream_close(qahw_stream_handle_t *stream_handle) { + int rc = -EINVAL; + qahw_stream_direction dir; + qahw_api_stream_t *stream = (qahw_api_stream_t *)stream_handle; + + if (stream) { + switch (stream->dir) { + case QAHW_STREAM_OUTPUT: + ALOGV("%s: closing output stream\n", __func__); + rc = qahw_close_output_stream(stream->out_stream); + break; + case QAHW_STREAM_INPUT: + ALOGV("%s: closing input stream\n", __func__); + rc = qahw_close_input_stream(stream->in_stream); + break; + case QAHW_STREAM_INPUT_OUTPUT: + rc = qahw_close_output_stream(stream->out_stream); + if (rc) + ALOGE("%s: closing output stream failed\n", __func__); + /*if not voice call close input stream*/ + if (stream->type != QAHW_VOICE_CALL) { + rc = qahw_close_input_stream(stream->in_stream); + if (rc) + ALOGE("%s: closing output stream failed\n", __func__); + } + break; + default: + ALOGE("%s: invalid dir close failed\n", __func__); + } + } else + ALOGE("%s: null stream handle\n", __func__); + + free(stream->vol.vol_pair); + free(stream); + return rc; +} + +int qahw_stream_start(qahw_stream_handle_t *stream_handle) { + int rc = -EINVAL; + qahw_audio_stream_type type; + qahw_api_stream_t *stream = (qahw_api_stream_t *)stream_handle; + + if (!stream) { + ALOGE("%d:%s invalid stream handle", __LINE__, __func__); + return rc; + } + /*set call state and call mode for voice */ + if (stream->type == QAHW_VOICE_CALL) { + rc = qahw_set_mode(stream->hw_module, AUDIO_MODE_IN_CALL); + } + + qahw_stream_set_device(stream, stream->num_of_devices, stream->devices); + return rc; +} + +int qahw_stream_stop(qahw_stream_handle_t *stream_handle) { + int rc = -EINVAL; + qahw_audio_stream_type type; + qahw_api_stream_t *stream = (qahw_api_stream_t *)stream_handle; + + /*reset call state and call mode for voice */ + if (stream->type == QAHW_VOICE_CALL) { + rc = qahw_set_parameters(stream->hw_module, "call_state=1"); + rc = qahw_set_mode(stream->hw_module, AUDIO_MODE_NORMAL); + } + return rc; +} + +int qahw_stream_set_device(qahw_stream_handle_t *stream_handle, + uint32_t num_of_devices, + qahw_device_t *devices) { + int rc = -EINVAL; + char dev_s[QAHW_MAX_INT_STRING]; + char device_route[QAHW_MAX_INT_STRING]; + qahw_api_stream_t *stream = (qahw_api_stream_t *)stream_handle; + bool is_voice = false; + + strlcpy(device_route, "routing=", QAHW_MAX_INT_STRING); + + if (stream && num_of_devices && devices) { + if (stream->type == QAHW_VOICE_CALL) + is_voice = true; + + switch (stream->dir) { + case QAHW_STREAM_OUTPUT: + if (num_of_devices != 1 || !devices) { + ALOGE("%s: invalid device params\n", __func__); + return rc; + } + + snprintf(dev_s, QAHW_MAX_INT_STRING, "%d", devices[0]); + strlcat(device_route, dev_s, QAHW_MAX_INT_STRING); + rc = qahw_out_set_parameters(stream->out_stream, + device_route); + break; + case QAHW_STREAM_INPUT: + if (num_of_devices != 1 || !devices) { + ALOGE("%s: invalid device params\n", __func__); + return rc; + } + + snprintf(dev_s, QAHW_MAX_INT_STRING, "%d", devices[0]); + strlcat(device_route, dev_s, QAHW_MAX_INT_STRING); + rc = qahw_in_set_parameters(stream->in_stream, + device_route); + break; + case QAHW_STREAM_INPUT_OUTPUT: + if (!devices) { + ALOGE("%s: invalid device params\n", __func__); + return rc; + } + snprintf(dev_s, QAHW_MAX_INT_STRING, "%d", devices[0]); + strlcat(device_route, dev_s, QAHW_MAX_INT_STRING); + rc = qahw_out_set_parameters(stream->out_stream, + device_route); + if (rc) + ALOGE("%s: failed to set out device\n", __func__); + /*if not voice set input stream*/ + if (!is_voice) { + strlcpy(device_route, "routing=", QAHW_MAX_INT_STRING); + snprintf(dev_s, QAHW_MAX_INT_STRING, "%d", devices[1]); + strlcat(device_route, dev_s, QAHW_MAX_INT_STRING); + rc = qahw_in_set_parameters(stream->in_stream, + device_route); + if (rc) + ALOGE("%s: failed to set in device\n", __func__); + } + break; + default: + ALOGE("%s: invalid dir close failed\n", __func__); + } + } + + if (!rc) + { + stream->num_of_devices = num_of_devices; + memset(&stream->devices[0], 0, sizeof(stream->devices)); + memcpy(&stream->devices[0], devices, num_of_devices); + } + + return rc; +} + +int qahw_stream_get_device(qahw_stream_handle_t *stream_handle, uint32_t *num_of_dev, + qahw_device_t **devices) { + int rc = 0; + qahw_api_stream_t *stream = (qahw_api_stream_t *)stream_handle; + + if (stream && num_of_dev && devices) { + *num_of_dev = stream->num_of_devices; + *devices = stream->devices; + } else { + ALOGE("%s: invalid params\n", __func__); + rc = -EINVAL; + } + + return rc; +} + +int qahw_stream_set_volume(qahw_stream_handle_t *stream_handle, + struct qahw_volume_data vol_data) { + int rc = -EINVAL; + qahw_audio_stream_type type; + qahw_api_stream_t *stream = (qahw_api_stream_t *)stream_handle; + float left; + float right; + bool l_found = false; + bool r_found = false; + int i; + + if(stream) { + /*currently max 2 channels is supported */ + if ( vol_data.num_of_channels > QAHW_CHANNELS_MAX) { + return -ENOTSUP; + } + + /*set voice call vol*/ + if (stream->type == QAHW_VOICE_CALL && + (vol_data.vol_pair && (vol_data.num_of_channels == 1))) { + ALOGV("%s: calling voice set volume with vol value %f\n", + __func__, vol_data.vol_pair[0].vol); + rc = qahw_set_voice_volume(stream->hw_module, + vol_data.vol_pair[0].vol); + /* Voice Stream picks up only single channel */ + stream->vol.num_of_channels = vol_data.num_of_channels; + stream->vol.vol_pair[0] = vol_data.vol_pair[0]; + } /*currently HAL requires 2 channels only */ + else if (vol_data.num_of_channels == QAHW_CHANNELS_MAX && + vol_data.vol_pair) { + for(i=0; i < vol_data.num_of_channels; i++) { + if(vol_data.vol_pair[i].channel == QAHW_CHANNEL_L) { + left = vol_data.vol_pair[i].vol; + l_found = true; + } + if(vol_data.vol_pair[i].channel == QAHW_CHANNEL_R) { + right = vol_data.vol_pair[i].vol; + r_found = true; + } + } + if(l_found && r_found) { + rc = qahw_out_set_volume(stream->out_stream, + left, right); + /* Cache volume if applied successfully */ + if (!rc) { + for(i=0; i < vol_data.num_of_channels; i++) { + stream->vol.vol_pair[i] = vol_data.vol_pair[i]; + } + } + } else + ALOGE("%s: setting vol requires left and right channel vol\n", + __func__); + } else { + ALOGE("%s: invalid input \n", __func__); + } + } else + ALOGE("%s: null stream handle\n", __func__); + + return rc; +} + +int qahw_stream_get_volume(qahw_stream_handle_t *stream_handle, + struct qahw_volume_data **vol_data) { + int rc = 0; + qahw_api_stream_t *stream = (qahw_api_stream_t *)stream_handle; + if (stream) + *vol_data = &stream->vol; + else + rc = -EINVAL; + + return rc; +} + +char *qahw_get_device_mute_info(struct qahw_mute_data mute) { + int i = 0; + char *ret = NULL; + + for (i=0; i < QAHW_NUM_OF_MUTE_TYPES; i++) { + if ((mute.enable == mute_info[i].mute.enable) && + (mute.direction == mute_info[i].mute.direction)) { + ret = mute_info[i].mute_state; + break; + } + } + ALOGV("%s mute_state %s \n", __func__, ret == NULL ? "null" : ret); + + return ret; +} + +int qahw_stream_set_mute(qahw_stream_handle_t *stream_handle, + struct qahw_mute_data mute_data) { + int rc = -EINVAL; + qahw_module_handle_t *hw_module; + qahw_api_stream_t *stream = (qahw_api_stream_t *)stream_handle; + char *mute_param; + + if(stream) { + mute_param = qahw_get_device_mute_info(mute_data); + + if (mute_param == NULL) + return rc; + + rc = qahw_set_parameters(stream->hw_module, mute_param); + + if(!rc){ + switch(mute_data.direction) { + case QAHW_STREAM_INPUT_OUTPUT: + stream->out_mute.enable = mute_data.enable; + stream->in_mute.enable = mute_data.enable; + break; + case QAHW_STREAM_OUTPUT: + stream->out_mute.enable = mute_data.enable; + break; + case QAHW_STREAM_INPUT: + stream->in_mute.enable = mute_data.enable; + break; + default: + ALOGE("%s: invalid dir mute failed\n", __func__); + break; + } + } + } + return rc; +} + +int qahw_stream_get_mute(qahw_stream_handle_t *stream_handle, + struct qahw_mute_data *mute_data) { + int rc = 0; + qahw_api_stream_t *stream = (qahw_api_stream_t *)stream_handle; + + if(stream && mute_data){ + switch(mute_data->direction) { + case QAHW_STREAM_OUTPUT: + mute_data->enable = stream->out_mute.enable; + break; + case QAHW_STREAM_INPUT: + mute_data->enable = stream->in_mute.enable; + break; + default: + ALOGE("%s: invalid mute dir get failed\n", __func__); + rc = -EINVAL; + break; + } + } + + return rc; +} + +ssize_t qahw_stream_read(qahw_stream_handle_t *stream_handle, + qahw_buffer_t *in_buf) { + ssize_t rc = 0; + qahw_api_stream_t *stream = (qahw_api_stream_t *)stream_handle; + qahw_in_buffer_t buff; + + if(in_buf) { + buff.buffer = in_buf->buffer; + buff.bytes = in_buf->size; + buff.offset = in_buf->offset; + buff.timestamp = in_buf->timestamp; + } + + if (stream && stream->in_stream) { + rc = qahw_in_read(stream->in_stream, &buff); + } else { + ALOGE("%d:%s input stream invalid, read failed", __LINE__, __func__); + rc = -ENODEV; + } + return rc; +} + +ssize_t qahw_stream_write(qahw_stream_handle_t *stream_handle, + qahw_buffer_t *out_buf) { + ssize_t rc = 0; + qahw_api_stream_t *stream = (qahw_api_stream_t *)stream_handle; + qahw_out_buffer_t buff; + + if(out_buf) { + buff.buffer = out_buf->buffer; + buff.bytes = out_buf->size; + buff.offset = out_buf->offset; + buff.timestamp = out_buf->timestamp; + buff.flags = out_buf->flags; + } + + if (stream && stream->out_stream) { + rc = qahw_out_write(stream->out_stream, &buff); + } else { + ALOGE("%d:%s out stream invalid, write failed", __LINE__, __func__); + rc = -ENODEV; + } + return rc; +} + +int qahw_stream_standby(qahw_stream_handle_t *stream_handle) { + int rc = -EINVAL; + qahw_api_stream_t *stream = (qahw_api_stream_t *)stream_handle; + if (stream) { + switch (stream->dir) { + case QAHW_STREAM_OUTPUT: + if (stream->out_stream) + rc = qahw_out_standby(stream->out_stream); + else + ALOGE("%d:%s out stream invalid, cannot put in standby" + , __LINE__, __func__); + break; + case QAHW_STREAM_INPUT: + if (stream->in_stream) + rc = qahw_in_standby(stream->in_stream); + else + ALOGE("%d:%s in stream invalid, cannot put in standby" + , __LINE__, __func__); + break; + case QAHW_STREAM_INPUT_OUTPUT: + if (stream->in_stream) + rc = qahw_in_standby(stream->in_stream); + else + ALOGE("%d:%s in stream invalid, cannot put in standby" + , __LINE__, __func__); + if (stream->out_stream) + rc = qahw_out_standby(stream->out_stream); + else + ALOGE("%d:%s out stream invalid, cannot put in standby" + , __LINE__, __func__); + break; + } + } else + ALOGE("%d:%s invalid stream handle, standby failed" + , __LINE__, __func__); + return rc; +} + +int qahw_stream_pause(qahw_stream_handle_t *stream_handle) { + int rc = -EINVAL; + qahw_api_stream_t *stream = (qahw_api_stream_t *)stream_handle; + if (stream) { + switch (stream->dir) { + case QAHW_STREAM_OUTPUT: + if (stream->out_stream) + rc = qahw_out_pause(stream->out_stream); + else + ALOGE("%d:%s out stream invalid, cannot put in pause" + , __LINE__, __func__); + break; + case QAHW_STREAM_INPUT: + ALOGE("%d:%s cannot pause input stream" + , __LINE__, __func__); + break; + case QAHW_STREAM_INPUT_OUTPUT: + if (stream->out_stream) + rc = qahw_out_pause(stream->out_stream); + else + ALOGE("%d:%s out stream invalid, cannot put in pause" + , __LINE__, __func__); + break; + } + } else + ALOGE("%d:%s invalid stream handle, pause failed" + , __LINE__, __func__); + return rc; +} + +int qahw_stream_resume(qahw_stream_handle_t *stream_handle) { + int rc = -EINVAL; + qahw_api_stream_t *stream = (qahw_api_stream_t *)stream_handle; + if (stream) { + switch (stream->dir) { + case QAHW_STREAM_OUTPUT: + if (stream->out_stream) + rc = qahw_out_resume(stream->out_stream); + else + ALOGE("%d:%s out stream invalid, cannot put in resume" + , __LINE__, __func__); + break; + case QAHW_STREAM_INPUT: + ALOGE("%d:%s cannot resume input stream" + , __LINE__, __func__); + break; + case QAHW_STREAM_INPUT_OUTPUT: + if (stream->out_stream) + rc = qahw_out_resume(stream->out_stream); + else + ALOGE("%d:%s out stream invalid, cannot put in resume" + , __LINE__, __func__); + break; + } + } else + ALOGE("%d:%s invalid stream handle, resume failed" + , __LINE__, __func__); + return rc; +} + +int qahw_stream_flush(qahw_stream_handle_t *stream_handle) { + int rc = -EINVAL; + qahw_api_stream_t *stream = (qahw_api_stream_t *)stream_handle; + if (stream) { + switch (stream->dir) { + case QAHW_STREAM_OUTPUT: + if (stream->out_stream) + rc = qahw_out_flush(stream->out_stream); + else + ALOGE("%d:%s out stream invalid, cannot flush" + , __LINE__, __func__); + case QAHW_STREAM_INPUT: + ALOGE("%d:%s cannot flush input stream" + , __LINE__, __func__); + case QAHW_STREAM_INPUT_OUTPUT: + if (stream->out_stream) + rc = qahw_out_flush(stream->out_stream); + else + ALOGE("%d:%s out stream invalid, cannot flush" + , __LINE__, __func__); + } + } else + ALOGE("%d:%s invalid stream handle, flush failed" + , __LINE__, __func__); + return rc; +} + +int32_t qahw_stream_drain(qahw_stream_handle_t *stream_handle, + qahw_drain_type_t type) { + int rc = -EINVAL; + qahw_api_stream_t *stream = (qahw_api_stream_t *)stream_handle; + if (stream) { + switch (stream->dir) { + case QAHW_STREAM_OUTPUT: + if (stream->out_stream) + rc = qahw_out_drain(stream->out_stream, type); + else + ALOGE("%d:%s out stream invalid, cannot drain" + , __LINE__, __func__); + case QAHW_STREAM_INPUT: + ALOGE("%d:%s cannot drain input stream" + , __LINE__, __func__); + case QAHW_STREAM_INPUT_OUTPUT: + if (stream->out_stream) + rc = qahw_out_drain(stream->out_stream, type); + else + ALOGE("%d:%s out stream invalid, cannot drain" + , __LINE__, __func__); + } + } else + ALOGE("%d:%s invalid stream handle, drain failed" + , __LINE__, __func__); + return rc; +} + +int32_t qahw_stream_get_buffer_size(const qahw_stream_handle_t *stream_handle, + size_t *in_buffer, size_t *out_buffer) { + int32_t rc = 0; + qahw_api_stream_t *stream = (qahw_api_stream_t *)stream_handle; + if (stream) { + switch (stream->dir) { + case QAHW_STREAM_OUTPUT: + if (stream->out_stream) + *out_buffer = qahw_out_get_buffer_size(stream->out_stream); + else { + ALOGE("%d:%s out stream invalid, cannot get size" + , __LINE__, __func__); + rc = -EINVAL; + } + case QAHW_STREAM_INPUT: + if (stream->in_stream) + *in_buffer = qahw_in_get_buffer_size(stream->in_stream); + else { + ALOGE("%d:%s in stream invalid, cannot get size" + , __LINE__, __func__); + rc = -EINVAL; + } + case QAHW_STREAM_INPUT_OUTPUT: + if (stream->out_stream) + *out_buffer = qahw_out_get_buffer_size(stream->out_stream); + else { + ALOGE("%d:%s out stream invalid, cannot get size" + , __LINE__, __func__); + rc = -EINVAL; + } + if (stream->in_stream) + *in_buffer = qahw_in_get_buffer_size(stream->in_stream); + else { + ALOGE("%d:%s in stream invalid, cannot get size" + , __LINE__, __func__); + rc = -EINVAL; + } + } + } else { + ALOGE("%d:%s invalid stream handle, get size failed failed" + , __LINE__, __func__); + rc = -EINVAL; + } + return rc; +} + +int32_t qahw_stream_set_buffer_size(const qahw_stream_handle_t *stream_handle, + size_t in_buffer, size_t out_buffer){ + return -ENOTSUP; +} + +int32_t qahw_stream_set_dtmf_gen_params(qahw_api_stream_t *stream, + struct qahw_dtmf_gen_params *dtmf_params){ + int32_t rc = -EINVAL; + char kv[QAHW_KV_PAIR_LENGTH]; + + if(stream->type == QAHW_VOICE_CALL) { + if(dtmf_params->enable) { + snprintf(kv, QAHW_KV_PAIR_LENGTH, + "dtmf_low_freq=%d;dtmf_high_freq=%d;dtmf_tone_gain=%d", + dtmf_params->low_freq, + dtmf_params->high_freq, + dtmf_params->gain); + ALOGV("%d:%s kv set is %s", __LINE__, __func__, kv); + } else + snprintf(kv, QAHW_KV_PAIR_LENGTH, "dtmf_tone_off"); + rc = qahw_out_set_parameters(stream->out_stream,kv); + } else + ALOGE("%d:%s cannot set dtmf on non voice stream", __LINE__, __func__); + return rc; +} + +int32_t qahw_stream_set_tty_mode_params(qahw_api_stream_t *stream, + struct qahw_tty_params *tty_params){ + int32_t rc = -EINVAL; + + if(stream->type == QAHW_VOICE_CALL) { + if(tty_params->mode >= QAHW_TTY_MODE_MAX) { + ALOGE("%d:%s invalid tty mode", __LINE__, __func__); + return rc; + } + + ALOGV("%d:%s kv set is %s", __LINE__, __func__, + tty_mode_map[tty_params->mode]); + /*currently tty is set on the dev */ + rc = qahw_set_parameters(stream->hw_module, + tty_mode_map[tty_params->mode]); + } else + ALOGE("%d:%s cannot set tty mode on non voice stream", __LINE__, + __func__); + return rc; +} + +int32_t qahw_stream_set_hpcm_params(qahw_api_stream_t *stream, + struct qahw_hpcm_params *hpcm_params){ + int32_t rc = -EINVAL; + char kv[QAHW_KV_PAIR_LENGTH]; + int32_t tp; + + if(stream->type == QAHW_VOICE_CALL) { + /*if rx and tx call both mixer commands */ + if(hpcm_params->tap_point == QAHW_HPCM_TAP_POINT_RX_TX) { + snprintf(kv, QAHW_KV_PAIR_LENGTH, + "hpcm_tp=%d;hpcm_dir=%d", + QAHW_HPCM_TAP_POINT_RX, + hpcm_params->direction); + ALOGV("%d:%s kv set is %s", __LINE__, __func__, kv); + rc = qahw_out_set_parameters(stream->out_stream, kv); + if(rc) { + ALOGE("%d:%s failed to set hpcm on RX Path", __LINE__, + __func__); + } + snprintf(kv, QAHW_KV_PAIR_LENGTH, + "hpcm_tp=%d;hpcm_dir=%d", + QAHW_HPCM_TAP_POINT_TX, + hpcm_params->direction); + ALOGV("%d:%s kv set is %s", __LINE__, __func__, kv); + rc = qahw_out_set_parameters(stream->out_stream, kv); + if(rc) { + ALOGE("%d:%s failed to set hpcm on TX Path", __LINE__, + __func__); + } + } else { + snprintf(kv, QAHW_KV_PAIR_LENGTH, + "hpcm_tp=%d;hpcm_dir=%d", + hpcm_params->tap_point, + hpcm_params->direction); + ALOGV("%d:%s kv set is %s", __LINE__, __func__, kv); + rc = qahw_out_set_parameters(stream->out_stream, kv); + if(rc) { + ALOGE("%d:%s failed to set hpcm params", __LINE__, + __func__); + } + } + } else + ALOGE("%d:%s cannot set hpcm params on non voice stream", + __LINE__, __func__); + return rc; +} + +int32_t qahw_stream_set_parameters(qahw_stream_handle_t *stream_handle, + uint32_t param_id, + qahw_param_payload *param_payload) { + int32_t rc = -EINVAL; + qahw_api_stream_t *stream = (qahw_api_stream_t *)stream_handle; + + if(stream && param_payload) { + switch(param_id){ + case QAHW_PARAM_DTMF_GEN: + rc = qahw_stream_set_dtmf_gen_params(stream, + ¶m_payload->dtmf_gen_params); + break; + case QAHW_PARAM_TTY_MODE: + rc = qahw_stream_set_tty_mode_params(stream, + ¶m_payload->tty_mode_params); + break; + case QAHW_PARAM_HPCM: + rc = qahw_stream_set_hpcm_params(stream, + ¶m_payload->hpcm_params); + break; + default: + ALOGE("%d:%s unsupported param id %d" + ,__LINE__, __func__, param_id); + break; + } + } else + ALOGE("%d:%s invalid stream handle, cannot set param" + , __LINE__, __func__); + return rc; +} + +int32_t qahw_stream_get_parameters(qahw_stream_handle_t *stream_handle, + uint32_t param_id, + qahw_param_payload *param_payload) { + ALOGE("%s is an unsupported api", __func__); + return -ENOTSUP; +} +#else +int qahw_stream_open(qahw_module_handle_t *hw_module, + struct qahw_stream_attributes attr, + uint32_t num_of_devices, + qahw_device_t *devices, + uint32_t no_of_modifiers, + struct qahw_modifier_kv *modifiers, + qahw_stream_callback_t cb, + void *cookie, + qahw_stream_handle_t **stream_handle){ + ALOGE("%s is an unsupported api", __func__); + return -ENOTSUP; +} + +int qahw_stream_close(qahw_stream_handle_t *stream_handle){ + ALOGE("%s is an unsupported api", __func__); + return -ENOTSUP; +} + +int qahw_stream_start(qahw_stream_handle_t *stream_handle){ + ALOGE("%s is an unsupported api", __func__); + return -ENOTSUP; +} + +int qahw_stream_stop(qahw_stream_handle_t *stream_handle){ + ALOGE("%s is an unsupported api", __func__); + return -ENOTSUP; +} + +int qahw_stream_set_device(qahw_stream_handle_t *stream_handle, + uint32_t num_of_dev, + qahw_device_t *devices){ + ALOGE("%s is an unsupported api", __func__); + return -ENOTSUP; +} + +int qahw_stream_get_device(qahw_stream_handle_t *stream_handle, + uint32_t *num_of_dev, + qahw_device_t **devices){ + ALOGE("%s is an unsupported api", __func__); + return -ENOTSUP; +} + +int qahw_stream_set_volume(qahw_stream_handle_t *stream_handle, + struct qahw_volume_data vol_data){ + ALOGE("%s is an unsupported api", __func__); + return -ENOTSUP; +} + +int qahw_stream_get_volume(qahw_stream_handle_t *stream_handle, + struct qahw_volume_data **vol_data){ + ALOGE("%s is an unsupported api", __func__); + return -ENOTSUP; +} + +int qahw_stream_set_mute(qahw_stream_handle_t *stream_handle, + struct qahw_mute_data mute_data){ + ALOGE("%s is an unsupported api", __func__); + return -ENOTSUP; +} + +int qahw_stream_get_mute(qahw_stream_handle_t *stream_handle, + struct qahw_mute_data *mute_data){ + ALOGE("%s is an unsupported api", __func__); + return -ENOTSUP; +} + +ssize_t qahw_stream_read(qahw_stream_handle_t *stream_handle, + qahw_buffer_t *in_buf){ + ALOGE("%s is an unsupported api", __func__); + return -ENOTSUP; +} + +ssize_t qahw_stream_write(qahw_stream_handle_t *stream_handle, + qahw_buffer_t *out_buf){ + ALOGE("%s is an unsupported api", __func__); + return -ENOTSUP; +} + +int32_t qahw_stream_pause(qahw_stream_handle_t *stream_handle){ + ALOGE("%s is an unsupported api", __func__); + return -ENOTSUP; +} + +int32_t qahw_stream_standby(qahw_stream_handle_t *stream_handle){ + ALOGE("%s is an unsupported api", __func__); + return -ENOTSUP; +} + +int32_t qahw_stream_resume(qahw_stream_handle_t *stream_handle){ + ALOGE("%s is an unsupported api", __func__); + return -ENOTSUP; +} + +int32_t qahw_stream_flush(qahw_stream_handle_t *stream_handle){ + ALOGE("%s is an unsupported api", __func__); + return -ENOTSUP; +} + +int32_t qahw_stream_drain(qahw_stream_handle_t *stream_handle, + qahw_drain_type_t type){ + ALOGE("%s is an unsupported api", __func__); + return -ENOTSUP; +} + +int32_t qahw_stream_get_buffer_size(const qahw_stream_handle_t *stream_handle, + size_t *in_buffer, size_t *out_buffer){ + ALOGE("%s is an unsupported api", __func__); + return -ENOTSUP; +} + +int32_t qahw_stream_set_buffer_size(const qahw_stream_handle_t *stream_handle, + size_t in_buffer, size_t out_buffer){ + ALOGE("%s is an unsupported api", __func__); + return -ENOTSUP; +} + +int32_t qahw_stream_set_parameters(qahw_stream_handle_t *stream_handle, + uint32_t param_id, + qahw_param_payload *param_payload){ + ALOGE("%s is an unsupported api", __func__); + return -ENOTSUP; +} + +int32_t qahw_stream_get_parameters(qahw_stream_handle_t *stream_handle, + uint32_t param_id, + qahw_param_payload *param_payload){ + ALOGE("%s is an unsupported api", __func__); + return -ENOTSUP; +} +#endif + #endif