| /* |
| * Copyright (c) 2014-2021 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. |
| * |
| * Changes from Qualcomm Innovation Center are provided under the following license: |
| * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. |
| * SPDX-License-Identifier: BSD-3-Clause-Clear |
| */ |
| |
| #define LOG_TAG "audio_ext_hw_plugin" |
| #define LOG_NDEBUG 0 |
| |
| #include <errno.h> |
| #include <pthread.h> |
| #include <dlfcn.h> |
| #include <log/log.h> |
| #include <audio_hw.h> |
| #include "audio_extn.h" |
| #include "platform_api.h" |
| #include "platform.h" |
| #include "audio_hal_plugin.h" |
| |
| //external feature dependency |
| static fp_b64decode_t fp_b64decode; |
| static fp_b64encode_t fp_b64encode; |
| |
| typedef int32_t (*audio_hal_plugin_init_t)(void); |
| typedef int32_t (*audio_hal_plugin_deinit_t)(void); |
| typedef int32_t (*audio_hal_plugin_send_msg_t)(audio_hal_plugin_msg_type_t, |
| void *, uint32_t); |
| |
| struct ext_hw_plugin_data { |
| struct audio_device *adev; |
| void *plugin_handle; |
| audio_hal_plugin_init_t audio_hal_plugin_init; |
| audio_hal_plugin_deinit_t audio_hal_plugin_deinit; |
| audio_hal_plugin_send_msg_t audio_hal_plugin_send_msg; |
| int32_t usecase_ref_count[AUDIO_HAL_PLUGIN_USECASE_MAX]; |
| snd_device_t out_snd_dev[AUDIO_HAL_PLUGIN_USECASE_MAX]; |
| snd_device_t in_snd_dev[AUDIO_HAL_PLUGIN_USECASE_MAX]; |
| bool mic_mute; |
| }; |
| |
| /* This can be defined in platform specific file or use compile flag */ |
| #ifdef DAEMON_SUPPORT_AUTO |
| #define LIB_PLUGIN_DRIVER "libaudiohalpluginclient.so" |
| #else |
| #define LIB_PLUGIN_DRIVER "libaudiohalplugin.so" |
| #endif |
| |
| void* ext_hw_plugin_init(struct audio_device *adev, ext_hw_plugin_init_config_t init_config) |
| { |
| int32_t ret = 0; |
| struct ext_hw_plugin_data *my_plugin = NULL; |
| |
| my_plugin = calloc(1, sizeof(struct ext_hw_plugin_data)); |
| |
| if (my_plugin == NULL) { |
| ALOGE("[%s] Memory allocation failed for plugin data",__func__); |
| return NULL; |
| } |
| |
| my_plugin->adev = adev; |
| |
| fp_b64decode = init_config.fp_b64decode; |
| fp_b64encode = init_config.fp_b64encode; |
| |
| my_plugin->plugin_handle = dlopen(LIB_PLUGIN_DRIVER, RTLD_NOW); |
| if (my_plugin->plugin_handle == NULL) { |
| ALOGE("%s: DLOPEN failed for %s", __func__, LIB_PLUGIN_DRIVER); |
| goto plugin_init_fail; |
| } else { |
| ALOGV("%s: DLOPEN successful for %s", __func__, LIB_PLUGIN_DRIVER); |
| my_plugin->audio_hal_plugin_init = (audio_hal_plugin_init_t)dlsym( |
| my_plugin->plugin_handle, "audio_hal_plugin_init"); |
| if (!my_plugin->audio_hal_plugin_init) { |
| ALOGE("%s: Could not find the symbol audio_hal_plugin_init from %s", |
| __func__, LIB_PLUGIN_DRIVER); |
| goto plugin_init_fail; |
| } |
| |
| my_plugin->audio_hal_plugin_deinit = (audio_hal_plugin_deinit_t)dlsym( |
| my_plugin->plugin_handle, "audio_hal_plugin_deinit"); |
| if (!my_plugin->audio_hal_plugin_deinit) { |
| ALOGE("%s: Could not find the symbol audio_hal_plugin_deinit from %s", |
| __func__, LIB_PLUGIN_DRIVER); |
| goto plugin_init_fail; |
| } |
| |
| my_plugin->audio_hal_plugin_send_msg = (audio_hal_plugin_send_msg_t) |
| dlsym(my_plugin->plugin_handle, "audio_hal_plugin_send_msg"); |
| if (!my_plugin->audio_hal_plugin_send_msg) { |
| ALOGE("%s: Could not find the symbol audio_hal_plugin_send_msg from %s", |
| __func__, LIB_PLUGIN_DRIVER); |
| goto plugin_init_fail; |
| } |
| |
| ret = my_plugin->audio_hal_plugin_init(); |
| if (ret) { |
| ALOGE("%s: audio_hal_plugin_init failed with ret = %d", |
| __func__, ret); |
| goto plugin_init_fail; |
| } |
| } |
| my_plugin->mic_mute = false; |
| return my_plugin; |
| |
| plugin_init_fail: |
| if (my_plugin->plugin_handle != NULL) |
| dlclose(my_plugin->plugin_handle); |
| free(my_plugin); |
| return NULL; |
| } |
| |
| int32_t ext_hw_plugin_deinit(void *plugin) |
| { |
| int32_t ret = 0; |
| struct ext_hw_plugin_data *my_plugin = (struct ext_hw_plugin_data *)plugin; |
| |
| if (my_plugin == NULL) { |
| ALOGE("[%s] NULL plugin pointer",__func__); |
| return -EINVAL; |
| } |
| if (my_plugin->audio_hal_plugin_deinit) { |
| ret = my_plugin->audio_hal_plugin_deinit(); |
| if (ret) { |
| ALOGE("%s: audio_hal_plugin_deinit failed with ret = %d", |
| __func__, ret); |
| } |
| } |
| if(my_plugin->plugin_handle != NULL) |
| dlclose(my_plugin->plugin_handle); |
| |
| free(my_plugin); |
| return ret; |
| } |
| |
| static int32_t ext_hw_plugin_check_plugin_usecase(audio_usecase_t hal_usecase, |
| audio_hal_plugin_usecase_type_t *plugin_usecase) |
| { |
| int32_t ret = 0; |
| |
| switch(hal_usecase) { |
| case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER: |
| case USECASE_AUDIO_PLAYBACK_LOW_LATENCY: |
| case USECASE_AUDIO_PLAYBACK_MULTI_CH: |
| case USECASE_AUDIO_PLAYBACK_OFFLOAD: |
| case USECASE_AUDIO_PLAYBACK_OFFLOAD2: |
| case USECASE_AUDIO_PLAYBACK_OFFLOAD3: |
| case USECASE_AUDIO_PLAYBACK_OFFLOAD4: |
| case USECASE_AUDIO_PLAYBACK_OFFLOAD5: |
| case USECASE_AUDIO_PLAYBACK_OFFLOAD6: |
| case USECASE_AUDIO_PLAYBACK_OFFLOAD7: |
| case USECASE_AUDIO_PLAYBACK_OFFLOAD8: |
| case USECASE_AUDIO_PLAYBACK_OFFLOAD9: |
| case USECASE_AUDIO_PLAYBACK_ULL: |
| case USECASE_AUDIO_PLAYBACK_MEDIA: |
| case USECASE_AUDIO_PLAYBACK_MEDIA_LL: |
| case USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION: |
| *plugin_usecase = AUDIO_HAL_PLUGIN_USECASE_DEFAULT_PLAYBACK; |
| break; |
| case USECASE_AUDIO_RECORD: |
| case USECASE_AUDIO_RECORD_COMPRESS: |
| case USECASE_AUDIO_RECORD_LOW_LATENCY: |
| case USECASE_AUDIO_RECORD_LOW_LATENCY2: |
| case USECASE_AUDIO_RECORD_FM_VIRTUAL: |
| case USECASE_AUDIO_RECORD_ECHO_REF_EXT: |
| *plugin_usecase = AUDIO_HAL_PLUGIN_USECASE_DEFAULT_CAPTURE; |
| break; |
| case USECASE_AUDIO_HFP_SCO: |
| case USECASE_AUDIO_HFP_SCO_WB: |
| case USECASE_AUDIO_HFP_SCO_DOWNLINK: |
| case USECASE_AUDIO_HFP_SCO_WB_DOWNLINK: |
| *plugin_usecase = AUDIO_HAL_PLUGIN_USECASE_HFP_VOICE_CALL; |
| break; |
| case USECASE_VOICE_CALL: |
| case USECASE_VOICEMMODE1_CALL: |
| *plugin_usecase = AUDIO_HAL_PLUGIN_USECASE_CS_VOICE_CALL; |
| break; |
| case USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE: |
| case USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE_LL: |
| *plugin_usecase = AUDIO_HAL_PLUGIN_USECASE_DRIVER_SIDE_PLAYBACK; |
| break; |
| case USECASE_AUDIO_PLAYBACK_PHONE: |
| case USECASE_AUDIO_PLAYBACK_PHONE_LL: |
| *plugin_usecase = AUDIO_HAL_PLUGIN_USECASE_PHONE_PLAYBACK; |
| break; |
| case USECASE_AUDIO_FM_TUNER_EXT: |
| *plugin_usecase = AUDIO_HAL_PLUGIN_USECASE_FM_TUNER; |
| break; |
| case USECASE_ICC_CALL: |
| *plugin_usecase = AUDIO_HAL_PLUGIN_USECASE_ICC; |
| break; |
| default: |
| ret = -EINVAL; |
| } |
| |
| return ret; |
| } |
| |
| int32_t ext_hw_plugin_usecase_start(void *plugin, struct audio_usecase *usecase) |
| { |
| int32_t ret = 0; |
| struct ext_hw_plugin_data *my_plugin = (struct ext_hw_plugin_data *)plugin; |
| |
| if ((my_plugin == NULL) || (usecase == NULL)) { |
| ALOGE("[%s] NULL input pointer",__func__); |
| return -EINVAL; |
| } |
| |
| if (my_plugin->audio_hal_plugin_send_msg) { |
| audio_hal_plugin_msg_type_t msg = AUDIO_HAL_PLUGIN_MSG_CODEC_ENABLE; |
| audio_hal_plugin_codec_enable_t codec_enable; |
| |
| ret = ext_hw_plugin_check_plugin_usecase(usecase->id, &codec_enable.usecase); |
| if(ret){ |
| ALOGI("%s: enable audio hal plugin skipped for audio usecase %d", |
| __func__, usecase->id); |
| return 0; |
| } |
| |
| if(usecase->id == USECASE_AUDIO_RECORD) { |
| if(usecase->in_snd_device == SND_DEVICE_IN_SPEAKER_QMIC_AEC) { |
| codec_enable.usecase = AUDIO_HAL_PLUGIN_USECASE_EC_CAPTURE; |
| } |
| } |
| |
| if(my_plugin->usecase_ref_count[codec_enable.usecase]){ |
| ALOGV("%s: plugin usecase %d already enabled", |
| __func__, codec_enable.usecase); |
| my_plugin->usecase_ref_count[codec_enable.usecase]++; |
| return 0; |
| } |
| |
| if (((usecase->type == PCM_CAPTURE) || (usecase->type == VOICE_CALL) || |
| (usecase->type == VOIP_CALL) || (usecase->type == PCM_HFP_CALL) || |
| (usecase->type == ICC_CALL) || (usecase->type == PCM_PASSTHROUGH)) && |
| (usecase->in_snd_device != SND_DEVICE_NONE)) { |
| codec_enable.snd_dev = usecase->in_snd_device; |
| /* TODO - below should be related with in_snd_dev */ |
| codec_enable.sample_rate = 48000; |
| codec_enable.bit_width = 16; |
| codec_enable.num_chs = 2; |
| |
| ALOGD("%s: enable audio hal plugin input, %d, %d, %d, %d, %d", |
| __func__, (int)codec_enable.usecase, |
| (int)codec_enable.snd_dev, |
| (int)codec_enable.sample_rate, |
| (int)codec_enable.bit_width, |
| (int)codec_enable.num_chs); |
| ret = my_plugin->audio_hal_plugin_send_msg(msg, |
| (void*)&codec_enable, sizeof(codec_enable)); |
| if (ret) { |
| ALOGE("%s: enable audio hal plugin input failed ret = %d", |
| __func__, ret); |
| return ret; |
| } |
| my_plugin->in_snd_dev[codec_enable.usecase] = codec_enable.snd_dev; |
| |
| if (my_plugin->mic_mute && |
| codec_enable.usecase == AUDIO_HAL_PLUGIN_USECASE_HFP_VOICE_CALL) { |
| int plugin_ret; |
| audio_hal_plugin_codec_set_pp_mute_t pp_mute; |
| |
| pp_mute.usecase = codec_enable.usecase; |
| pp_mute.snd_dev = codec_enable.snd_dev; |
| pp_mute.ch_mask = AUDIO_CHANNEL_IN_ALL; |
| pp_mute.flag = my_plugin->mic_mute; |
| |
| ALOGV("%s: sending codec pp mute msg to HAL plugin driver, %d, %d, %x, %d", |
| __func__, (int)pp_mute.usecase, (int)pp_mute.snd_dev, |
| (int)pp_mute.ch_mask, (int)pp_mute.flag); |
| plugin_ret = my_plugin->audio_hal_plugin_send_msg( |
| AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_MUTE, &pp_mute, |
| sizeof(pp_mute)); |
| if (plugin_ret) |
| ALOGE("%s: Failed to set plugin pp mute err: %d", __func__, plugin_ret); |
| } |
| } |
| |
| if (((usecase->type == PCM_CAPTURE) && |
| (usecase->id == USECASE_AUDIO_RECORD) && |
| (usecase->in_snd_device == SND_DEVICE_IN_SPEAKER_QMIC_AEC)) || |
| ((usecase->type == PCM_HFP_CALL) && |
| ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) && |
| (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) { |
| audio_hal_plugin_codec_enable_t codec_enable_ec = {0,}; |
| codec_enable_ec.snd_dev = usecase->in_snd_device; |
| // TODO - below should be related with in_snd_dev |
| codec_enable_ec.sample_rate = 48000; |
| codec_enable_ec.bit_width = 16; |
| codec_enable_ec.num_chs = 6; |
| codec_enable_ec.usecase = AUDIO_HAL_PLUGIN_USECASE_EC_REF_CAPTURE; |
| |
| ALOGD("%s: enable audio hal plugin input for echo reference, %d, %d, %d, %d, %d", |
| __func__, (int)codec_enable_ec.usecase, |
| (int)codec_enable_ec.snd_dev, |
| (int)codec_enable_ec.sample_rate, |
| (int)codec_enable_ec.bit_width, |
| (int)codec_enable_ec.num_chs); |
| ret = my_plugin->audio_hal_plugin_send_msg(msg, |
| (void*)&codec_enable_ec, sizeof(codec_enable_ec)); |
| if (ret) { |
| ALOGE("%s: enable audio hal plugin input failed ret = %d", |
| __func__, ret); |
| return ret; |
| } |
| } |
| |
| if (((usecase->type == PCM_PLAYBACK) || (usecase->type == VOICE_CALL) || |
| (usecase->type == VOIP_CALL) || (usecase->type == PCM_HFP_CALL) || |
| (usecase->type == ICC_CALL)) && (usecase->out_snd_device != SND_DEVICE_NONE)) { |
| codec_enable.snd_dev = usecase->out_snd_device; |
| /* TODO - below should be related with out_snd_dev */ |
| codec_enable.sample_rate = 48000; |
| codec_enable.bit_width = 24; |
| codec_enable.num_chs = 2; |
| |
| ALOGD("%s: enable audio hal plugin output, %d, %d, %d, %d, %d", |
| __func__, (int)codec_enable.usecase, |
| (int)codec_enable.snd_dev, |
| (int)codec_enable.sample_rate, |
| (int)codec_enable.bit_width, |
| (int)codec_enable.num_chs); |
| ret = my_plugin->audio_hal_plugin_send_msg(msg, |
| (void*)&codec_enable, sizeof(codec_enable)); |
| if (ret) { |
| ALOGE("%s: enable audio hal plugin output failed ret = %d", |
| __func__, ret); |
| return ret; |
| } |
| my_plugin->out_snd_dev[codec_enable.usecase] = codec_enable.snd_dev; |
| } |
| my_plugin->usecase_ref_count[codec_enable.usecase]++; |
| } |
| |
| ALOGD("%s: finished ext_hw_plugin usecase start", __func__); |
| |
| return ret; |
| } |
| |
| int32_t ext_hw_plugin_usecase_stop(void *plugin, struct audio_usecase *usecase) |
| { |
| int32_t ret = 0; |
| struct ext_hw_plugin_data *my_plugin = (struct ext_hw_plugin_data *)plugin; |
| |
| if ((my_plugin == NULL) || (usecase == NULL)) { |
| ALOGE("[%s] NULL input pointer",__func__); |
| return -EINVAL; |
| } |
| if (my_plugin->audio_hal_plugin_send_msg) { |
| audio_hal_plugin_msg_type_t msg = AUDIO_HAL_PLUGIN_MSG_CODEC_DISABLE; |
| audio_hal_plugin_codec_disable_t codec_disable; |
| |
| ret = ext_hw_plugin_check_plugin_usecase(usecase->id, &codec_disable.usecase); |
| if(ret){ |
| ALOGI("%s: disable audio hal plugin skipped for audio usecase %d", |
| __func__, usecase->id); |
| return 0; |
| } |
| |
| if((usecase->id == USECASE_AUDIO_RECORD) && |
| (usecase->in_snd_device == SND_DEVICE_IN_SPEAKER_QMIC_AEC)) |
| { |
| codec_disable.usecase = AUDIO_HAL_PLUGIN_USECASE_EC_CAPTURE; |
| } |
| if(my_plugin->usecase_ref_count[codec_disable.usecase] > 1){ |
| ALOGI("%s: plugin usecase %d still in use and can not be disabled", |
| __func__, codec_disable.usecase); |
| my_plugin->usecase_ref_count[codec_disable.usecase]--; |
| return 0; |
| } else if(my_plugin->usecase_ref_count[codec_disable.usecase] < 1){ |
| ALOGE("%s: plugin usecase %d not enabled", |
| __func__, codec_disable.usecase); |
| return -EINVAL; |
| } |
| |
| if (((usecase->type == PCM_PLAYBACK) || (usecase->type == VOICE_CALL) || |
| (usecase->type == VOIP_CALL) || (usecase->type == PCM_HFP_CALL) || |
| (usecase->type == ICC_CALL)) && (usecase->out_snd_device != SND_DEVICE_NONE)) { |
| codec_disable.snd_dev = usecase->out_snd_device; |
| |
| ALOGD("%s: disable audio hal plugin output, %d, %d", |
| __func__, (int)codec_disable.usecase, |
| (int)codec_disable.snd_dev); |
| ret = my_plugin->audio_hal_plugin_send_msg(msg, |
| (void*)&codec_disable, sizeof(codec_disable)); |
| if (ret) { |
| ALOGE("%s: disable audio hal plugin output failed ret = %d", |
| __func__, ret); |
| } |
| my_plugin->out_snd_dev[codec_disable.usecase] = 0; |
| } |
| if (((usecase->type == PCM_CAPTURE) || (usecase->type == VOICE_CALL) || |
| (usecase->type == VOIP_CALL) || (usecase->type == PCM_HFP_CALL) || |
| (usecase->type == PCM_PASSTHROUGH) || (usecase->type == ICC_CALL)) && |
| (usecase->in_snd_device != SND_DEVICE_NONE)) { |
| codec_disable.snd_dev = usecase->in_snd_device; |
| |
| ALOGD("%s: disable audio hal plugin input, %d, %d", |
| __func__, (int)codec_disable.usecase, |
| (int)codec_disable.snd_dev); |
| ret = my_plugin->audio_hal_plugin_send_msg(msg, |
| (void*)&codec_disable, sizeof(codec_disable)); |
| if (ret) { |
| ALOGE("%s: disable audio hal plugin input failed ret = %d", |
| __func__, ret); |
| } |
| my_plugin->in_snd_dev[codec_disable.usecase] = 0; |
| } |
| |
| if ((usecase->type == PCM_CAPTURE) && |
| (usecase->id == USECASE_AUDIO_RECORD) && |
| (usecase->in_snd_device == SND_DEVICE_IN_SPEAKER_QMIC_AEC)) { |
| audio_hal_plugin_codec_disable_t codec_disable_ec = {0,}; |
| codec_disable_ec.snd_dev = usecase->in_snd_device; |
| codec_disable_ec.usecase = AUDIO_HAL_PLUGIN_USECASE_EC_REF_CAPTURE; |
| |
| ALOGD("%s: disable audio hal plugin input for echo reference, %d, %d", |
| __func__, (int)codec_disable_ec.usecase, |
| (int)codec_disable_ec.snd_dev); |
| ret = my_plugin->audio_hal_plugin_send_msg(msg, |
| (void*)&codec_disable_ec, sizeof(codec_disable_ec)); |
| if (ret) { |
| ALOGE("%s: disable audio hal plugin input failed ret = %d", |
| __func__, ret); |
| return ret; |
| } |
| } |
| my_plugin->usecase_ref_count[codec_disable.usecase]--; |
| } |
| |
| ALOGD("%s: finished ext_hw_plugin usecase stop", __func__); |
| |
| return ret; |
| } |
| |
| static int32_t ext_hw_plugin_string_to_dword(char *string_value, void **dword_ptr, |
| uint32_t dword_len) |
| { |
| int32_t ret = 0; |
| uint32_t i,tmp; |
| uint8_t *dptr = NULL; |
| uint8_t *tmpptr = NULL; |
| int32_t dlen; |
| uint32_t *outptr = NULL; |
| |
| dlen = strlen(string_value); |
| if (dlen <= 0) { |
| ALOGE("%s: NULL data received", __func__); |
| return -EINVAL; |
| } |
| dptr = (uint8_t*) calloc(dlen, sizeof(uint8_t)); |
| if (dptr == NULL) { |
| ALOGE("%s: memory allocation failed", __func__); |
| return -ENOMEM; |
| } |
| dlen = fp_b64decode(string_value, strlen(string_value), dptr); |
| if ((dlen <= 0) || ((uint32_t)dlen != 4*dword_len)){ |
| ALOGE("%s: data decoding failed", __func__); |
| ret = -EINVAL; |
| goto done_string_to_dword; |
| } |
| |
| outptr = calloc(dword_len, sizeof(uint32_t)); |
| if (outptr == NULL) { |
| ALOGE("%s: memory allocation failed", __func__); |
| ret = -ENOMEM; |
| goto done_string_to_dword; |
| } |
| |
| for(i=0; i<dword_len; i++) { |
| tmpptr = dptr+4*i; |
| tmp = (uint32_t) *(tmpptr); |
| tmp |= ((uint32_t) *(tmpptr+1))<<8; |
| tmp |= ((uint32_t) *(tmpptr+2))<<16; |
| tmp |= ((uint32_t) *(tmpptr+3))<<24; |
| *(outptr + i) = tmp; |
| } |
| *dword_ptr = (void*)outptr; |
| |
| done_string_to_dword: |
| if (dptr != NULL) |
| free(dptr); |
| |
| return ret; |
| } |
| |
| static int32_t ext_hw_plugin_dword_to_string(uint32_t *dword_ptr, uint32_t dword_len, |
| char **string_ptr) |
| { |
| int32_t ret = 0; |
| uint32_t i,tmp; |
| uint8_t *dptr = NULL; |
| uint8_t *tmpptr = NULL; |
| int32_t dlen; |
| char *outptr = NULL; |
| |
| dptr = (uint8_t*)calloc(dword_len, sizeof(uint32_t)); |
| if(dptr == NULL) { |
| ALOGE("[%s] Memory allocation failed for dword length %d",__func__,dword_len); |
| return -ENOMEM; |
| } |
| |
| /* convert dword to byte array */ |
| for(i=0; i<dword_len; i++) { |
| tmp = *(dword_ptr + i); |
| tmpptr = dptr+4*i; |
| *tmpptr = (uint8_t) (tmp & 0xFF); |
| *(tmpptr + 1) = (uint8_t) ((tmp>>8) & 0xFF); |
| *(tmpptr + 2) = (uint8_t) ((tmp>>16) & 0xFF); |
| *(tmpptr + 3) = (uint8_t) ((tmp>>24) & 0xFF); |
| } |
| |
| /* Allocate memory for encoding */ |
| dlen = dword_len * 4; |
| outptr = (char*)calloc((dlen*2), sizeof(char)); |
| if(outptr == NULL) { |
| ALOGE("[%s] Memory allocation failed for size %d", |
| __func__, dlen*2); |
| ret = -ENOMEM; |
| goto done_dword_to_string; |
| } |
| |
| ret = fp_b64encode(dptr, dlen, outptr); |
| if(ret < 0) { |
| ALOGE("[%s] failed to convert data to string ret = %d", __func__, ret); |
| free(outptr); |
| ret = -EINVAL; |
| goto done_dword_to_string; |
| } |
| *string_ptr = outptr; |
| |
| done_dword_to_string: |
| if (dptr != NULL) |
| free(dptr); |
| |
| return ret; |
| } |
| |
| |
| int32_t ext_hw_plugin_set_parameters(void *plugin, struct str_parms *parms) |
| { |
| |
| char *value = NULL; |
| int32_t val, len = 0; |
| int32_t ret = 0, err; |
| char *kv_pairs = NULL; |
| struct ext_hw_plugin_data *my_plugin = NULL; |
| |
| if (plugin == NULL || parms == NULL) { |
| ALOGE("[%s] received null pointer",__func__); |
| return -EINVAL; |
| } |
| |
| my_plugin = (struct ext_hw_plugin_data *)plugin; |
| if (!my_plugin->audio_hal_plugin_send_msg) { |
| ALOGE("%s: NULL audio_hal_plugin_send_msg func ptr", __func__); |
| return -EINVAL; |
| } |
| |
| err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_MSG_TYPE, &val); |
| if (err < 0) { |
| ALOGE("%s: Invalid or missing TYPE param for plugin msg", __func__); |
| return -EINVAL; |
| } |
| ALOGD("%s: received plugin msg type (%d)", __func__, val); |
| str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_MSG_TYPE); |
| |
| if(val == AUDIO_HAL_PLUGIN_MSG_CODEC_TUNNEL_CMD || |
| val == AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_EQ) { |
| kv_pairs = str_parms_to_str(parms); |
| if (kv_pairs == NULL) { |
| ret = -EINVAL; |
| ALOGE("%s: key-value pair is NULL", __func__); |
| goto done; |
| } |
| len = strlen(kv_pairs); |
| value = (char*)calloc(len, sizeof(char)); |
| if (value == NULL) { |
| ret = -ENOMEM; |
| ALOGE("[%s] failed to allocate memory",__func__); |
| goto done; |
| } |
| } |
| |
| if (val == AUDIO_HAL_PLUGIN_MSG_CODEC_TUNNEL_CMD) { |
| uint32_t plsize; |
| int32_t *plptr = NULL; |
| |
| err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_SIZE, |
| (int*)&plsize); |
| if ((err < 0) || (!plsize)) { |
| ALOGE("%s: Invalid or missing size param for TUNNEL command", __func__); |
| ret = -EINVAL; |
| goto done; |
| } |
| str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_SIZE); |
| |
| err = str_parms_get_str(parms, |
| AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_DATA, value, len); |
| if (err < 0) { |
| ALOGE("%s: Invalid or missing band_data for TUNNEL command", __func__); |
| ret = -EINVAL; |
| goto done; |
| } |
| str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_DATA); |
| |
| ret = ext_hw_plugin_string_to_dword(value, (void**)&plptr, plsize); |
| if (ret) { |
| ALOGE("%s: Failed to parse payload for TUNNEL command", __func__); |
| ret = -EINVAL; |
| goto done_tunnel; |
| } |
| |
| audio_hal_plugin_msg_type_t msg = |
| AUDIO_HAL_PLUGIN_MSG_CODEC_TUNNEL_CMD; |
| |
| ALOGD("%s: sending codec tunnel cmd msg to HAL plugin driver,size = %d", |
| __func__, (int)plsize); |
| |
| ret = my_plugin->audio_hal_plugin_send_msg(msg, (void*)plptr, plsize); |
| if (ret) { |
| ALOGE("%s: Failed to send plugin tunnel cmd err: %d", __func__, ret); |
| } |
| |
| done_tunnel: |
| if (plptr!= NULL) |
| free(plptr); |
| } else { |
| audio_hal_plugin_usecase_type_t use_case; |
| audio_hal_plugin_direction_type_t dir; |
| snd_device_t snd_dev = 0; |
| |
| err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_UC, |
| &use_case); |
| if (err < 0) { |
| ALOGE("%s: Invalid or missing usecase param for plugin msg", __func__); |
| ret = -EINVAL; |
| /* TODO: do we need to support no use case in kvpair? */ |
| goto done; |
| } |
| str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_UC); |
| if ((use_case < 0) || (use_case >= AUDIO_HAL_PLUGIN_USECASE_MAX)) { |
| ALOGE("%s: Invalid usecase param for plugin msg", __func__); |
| ret = -EINVAL; |
| goto done; |
| } |
| |
| if (my_plugin->usecase_ref_count[use_case] == 0) { |
| /* allow param set when usecase not enabled */ |
| ALOGI("%s: plugin usecase (%d) is not enabled", __func__, use_case); |
| } else { |
| err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_DIRECTION, |
| &dir); |
| if (err < 0) { |
| if (my_plugin->out_snd_dev[use_case]) { |
| snd_dev = my_plugin->out_snd_dev[use_case]; |
| } else if (my_plugin->in_snd_dev[use_case]) { |
| snd_dev = my_plugin->in_snd_dev[use_case]; |
| } else { |
| ALOGE("%s: No valid snd_device found for the usecase (%d)", |
| __func__, use_case); |
| ret = -EINVAL; |
| goto done; |
| } |
| } else { |
| str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_DIRECTION); |
| |
| switch(dir) { |
| case AUDIO_HAL_PLUGIN_DIRECTION_PLAYBACK: |
| { |
| if (!my_plugin->out_snd_dev[use_case]) { |
| ALOGE("%s: No valid out_snd_device found for playback (%d)", |
| __func__, use_case); |
| ret = -EINVAL; |
| goto done; |
| } |
| snd_dev = my_plugin->out_snd_dev[use_case]; |
| break; |
| } |
| case AUDIO_HAL_PLUGIN_DIRECTION_CAPTURE: |
| { |
| if (!my_plugin->in_snd_dev[use_case]) { |
| ALOGE("%s: No valid in_snd_device found for capture (%d)", |
| __func__, use_case); |
| ret = -EINVAL; |
| goto done; |
| } |
| snd_dev = my_plugin->in_snd_dev[use_case]; |
| break; |
| } |
| default: |
| ALOGE("%s: Invalid direction param for plugin msg", __func__); |
| ret = -EINVAL; |
| goto done; |
| } |
| } |
| } |
| |
| switch(val) { |
| case AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_VOLUME: |
| { |
| audio_hal_plugin_codec_set_pp_vol_t pp_vol; |
| memset(&pp_vol,0,sizeof(pp_vol)); |
| err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_CMASK, |
| (int*)&pp_vol.ch_mask); |
| if ((err < 0)) { |
| /* TODO: properly handle no cmask param from client case */ |
| ALOGE("%s: Invalid or missing CMASK param for SET_PP_VOLUME", __func__); |
| ret = -EINVAL; |
| goto done; |
| } |
| str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_CMASK); |
| err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_GAIN, |
| (int*)&pp_vol.gain); |
| if ((err < 0)) { |
| /* TODO: properly handle no gain param from client case */ |
| ALOGE("%s: Invalid or missing GAIN param for SET_PP_VOLUME", __func__); |
| ret = -EINVAL; |
| goto done; |
| } |
| str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_GAIN); |
| |
| audio_hal_plugin_msg_type_t msg = |
| AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_VOLUME; |
| pp_vol.usecase = use_case; |
| pp_vol.snd_dev= snd_dev; |
| |
| ALOGD("%s: sending codec pp vol msg to HAL plugin driver, %d, %d, %d, %d", |
| __func__, (int)pp_vol.usecase, (int)pp_vol.snd_dev, |
| (int)pp_vol.ch_mask, (int)pp_vol.gain); |
| |
| ret = my_plugin->audio_hal_plugin_send_msg(msg, &pp_vol, sizeof(pp_vol)); |
| if (ret) { |
| ALOGE("%s: Failed to set plugin pp vol err: %d", __func__, ret); |
| } |
| break; |
| } |
| case AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_MUTE: |
| { |
| int32_t flag; |
| audio_hal_plugin_codec_set_pp_mute_t pp_mute; |
| memset(&pp_mute,0,sizeof(pp_mute)); |
| err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_CMASK, |
| (int*)&pp_mute.ch_mask); |
| if ((err < 0)) { |
| /* TODO: properly handle no cmask param from client case */ |
| ALOGE("%s: Invalid or missing CMASK param for SET_PP_MUTE", __func__); |
| ret = -EINVAL; |
| goto done; |
| } |
| str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_CMASK); |
| err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_MUTE_FLAG, |
| (int*)&flag); |
| if ((err < 0)) { |
| ALOGE("%s: Invalid or missing FLAG param for SET_PP_MUTE", __func__); |
| ret = -EINVAL; |
| goto done; |
| } |
| str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_MUTE_FLAG); |
| pp_mute.flag = (bool)flag; |
| |
| audio_hal_plugin_msg_type_t msg = |
| AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_MUTE; |
| pp_mute.usecase = use_case; |
| pp_mute.snd_dev= snd_dev; |
| |
| ALOGD("%s: sending codec pp mute msg to HAL plugin driver, %d, %d, %d, %d", |
| __func__, (int)pp_mute.usecase, (int)pp_mute.snd_dev, |
| (int)pp_mute.ch_mask, (int)pp_mute.flag); |
| |
| ret = my_plugin->audio_hal_plugin_send_msg(msg, &pp_mute, |
| sizeof(pp_mute)); |
| if (ret) { |
| ALOGE("%s: Failed to set plugin pp vol err: %d", __func__, ret); |
| } |
| break; |
| } |
| case AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_FADE: |
| { |
| audio_hal_plugin_codec_set_pp_fade_t pp_fade; |
| memset(&pp_fade,0,sizeof(pp_fade)); |
| err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_FADE, |
| (int*)&pp_fade.fade); |
| if ((err < 0)) { |
| ALOGE("%s: Invalid or missing FADE param for SET_PP_FADE", __func__); |
| ret = -EINVAL; |
| goto done; |
| } |
| str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_FADE); |
| |
| audio_hal_plugin_msg_type_t msg = |
| AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_FADE; |
| pp_fade.usecase = use_case; |
| pp_fade.snd_dev= snd_dev; |
| |
| ALOGD("%s: sending codec pp fade msg to HAL plugin driver, %d, %d, %d", |
| __func__, (int)pp_fade.usecase, (int)pp_fade.snd_dev, |
| (int)pp_fade.fade); |
| |
| ret = my_plugin->audio_hal_plugin_send_msg(msg, &pp_fade, |
| sizeof(pp_fade)); |
| if (ret) { |
| ALOGE("%s: Failed to set plugin pp fade err: %d", __func__, ret); |
| } |
| break; |
| } |
| case AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_BALANCE: |
| { |
| audio_hal_plugin_codec_set_pp_balance_t pp_balance; |
| memset(&pp_balance,0,sizeof(pp_balance)); |
| err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BALANCE, |
| (int*)&pp_balance.balance); |
| if ((err < 0)) { |
| ALOGE("%s: Invalid or missing balance param for SET_PP_BALANCE", __func__); |
| ret = -EINVAL; |
| goto done; |
| } |
| str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BALANCE); |
| |
| audio_hal_plugin_msg_type_t msg = |
| AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_BALANCE; |
| pp_balance.usecase = use_case; |
| pp_balance.snd_dev= snd_dev; |
| |
| ALOGD("%s: sending codec pp balance msg to HAL plugin driver, %d, %d, %d", |
| __func__, (int)pp_balance.usecase, (int)pp_balance.snd_dev, |
| (int)pp_balance.balance); |
| |
| ret = my_plugin->audio_hal_plugin_send_msg(msg, &pp_balance, |
| sizeof(pp_balance)); |
| if (ret) { |
| ALOGE("%s: Failed to set plugin pp balance err: %d", __func__, ret); |
| } |
| break; |
| } |
| case AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_BMT: |
| { |
| int32_t filter_type, enable_flag; |
| audio_hal_plugin_codec_set_pp_bmt_t pp_bmt; |
| memset(&pp_bmt,0,sizeof(pp_bmt)); |
| err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BMT_FTYPE, |
| (int*)&filter_type); |
| if ((err < 0)) { |
| ALOGE("%s: Invalid or missing filter type param for SET_PP_BMT", __func__); |
| ret = -EINVAL; |
| goto done; |
| } |
| str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BMT_FTYPE); |
| if ((filter_type <= AUDIO_HAL_PLUGIN_CODEC_PP_FILTER_TYPE_INVALID) && |
| (filter_type >= AUDIO_HAL_PLUGIN_CODEC_PP_FILTER_TYPE_MAX)) { |
| ALOGE("%s: Invalid filter type value for SET_PP_BMT", __func__); |
| ret = -EINVAL; |
| goto done; |
| } |
| pp_bmt.filter_type = filter_type; |
| err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BMT_FLAG, |
| (int*)&enable_flag); |
| if ((err < 0)) { |
| ALOGE("%s: Invalid or missing enable flag param for SET_PP_BMT", __func__); |
| ret = -EINVAL; |
| goto done; |
| } |
| str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BMT_FLAG); |
| pp_bmt.enable_flag = (bool)enable_flag; |
| err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BMT_VAL, |
| (int*)&pp_bmt.value); |
| if ((err < 0)) { |
| ALOGE("%s: Invalid or missing value param for SET_PP_BMT", __func__); |
| ret = -EINVAL; |
| goto done; |
| } |
| str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BMT_VAL); |
| |
| audio_hal_plugin_msg_type_t msg = |
| AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_BMT; |
| pp_bmt.usecase = use_case; |
| pp_bmt.snd_dev= snd_dev; |
| |
| ALOGD("%s: sending codec pp bmt msg to HAL plugin driver,%d,%d,%d,%d,%d", |
| __func__, (int)pp_bmt.usecase, (int)pp_bmt.snd_dev, |
| (int)pp_bmt.filter_type, (int)pp_bmt.enable_flag, |
| (int)pp_bmt.value); |
| |
| ret = my_plugin->audio_hal_plugin_send_msg(msg, &pp_bmt, |
| sizeof(pp_bmt)); |
| if (ret) { |
| ALOGE("%s: Failed to set plugin pp bmt err: %d", __func__, ret); |
| } |
| break; |
| } |
| case AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_EQ: |
| { |
| int32_t enable_flag; |
| audio_hal_plugin_codec_set_pp_eq_t pp_eq; |
| memset(&pp_eq,0,sizeof(pp_eq)); |
| |
| err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_FLAG, |
| (int*)&enable_flag); |
| if (err < 0) { |
| ALOGE("%s: Invalid or missing enable flag param for SET_PP_EQ", __func__); |
| ret = -EINVAL; |
| goto done; |
| } |
| str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_FLAG); |
| pp_eq.enable_flag = (bool)enable_flag; |
| |
| err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_ID, |
| (int*)&pp_eq.preset_id); |
| if (err < 0) { |
| ALOGE("%s: Invalid or missing preset_id param for SET_PP_EQ", __func__); |
| ret = -EINVAL; |
| goto done; |
| } |
| str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_ID); |
| if (pp_eq.preset_id < -1) { |
| ALOGE("%s: Invalid preset_id param for SET_PP_EQ", __func__); |
| ret = -EINVAL; |
| goto done; |
| } |
| |
| if (pp_eq.preset_id == -1) { |
| err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_NUM_BANDS, |
| (int*)&pp_eq.num_bands); |
| if (err < 0) { |
| ALOGE("%s: Invalid or missing num_bands param for SET_PP_EQ", __func__); |
| ret = -EINVAL; |
| goto done; |
| } |
| str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_NUM_BANDS); |
| if (!pp_eq.num_bands) { |
| ALOGE("%s: Invalid num_bands param for SET_PP_EQ", __func__); |
| ret = -EINVAL; |
| goto done; |
| } |
| |
| err = str_parms_get_str(parms, |
| AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_BAND_DATA, value, len); |
| if (err < 0) { |
| ALOGE("%s: Invalid or missing band_data for SET_PP_EQ", __func__); |
| ret = -EINVAL; |
| goto done; |
| } |
| str_parms_del(parms, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_BAND_DATA); |
| |
| ret = ext_hw_plugin_string_to_dword(value, (void**)&pp_eq.bands, |
| 3*pp_eq.num_bands); |
| if (ret) { |
| ALOGE("%s: Failed to parse band info for SET_PP_EQ", __func__); |
| ret = -EINVAL; |
| goto done_eq; |
| } |
| } |
| |
| audio_hal_plugin_msg_type_t msg = |
| AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_EQ; |
| pp_eq.usecase = use_case; |
| pp_eq.snd_dev= snd_dev; |
| |
| ALOGD("%s: sending codec pp eq msg to HAL plugin driver,%d,%d,%d,%d,%d", |
| __func__, (int)pp_eq.usecase, (int)pp_eq.snd_dev, |
| (int)pp_eq.enable_flag, (int)pp_eq.preset_id, |
| (int)pp_eq.num_bands); |
| |
| ret = my_plugin->audio_hal_plugin_send_msg(msg, &pp_eq, sizeof(pp_eq)); |
| if (ret) { |
| ALOGE("%s: Failed to set plugin pp eq err: %d", __func__, ret); |
| } |
| |
| done_eq: |
| if (pp_eq.bands != NULL) |
| free(pp_eq.bands); |
| break; |
| } |
| default: |
| ALOGE("%s: Invalid plugin message type: %d", __func__, val); |
| ret = -EINVAL; |
| } |
| } |
| |
| done: |
| ALOGI("%s: exit with code(%d)", __func__, ret); |
| if(kv_pairs != NULL) |
| free(kv_pairs); |
| if(value != NULL) |
| free(value); |
| return ret; |
| } |
| |
| int ext_hw_plugin_get_parameters(void *plugin, |
| struct str_parms *query, struct str_parms *reply) |
| { |
| char *value = NULL; |
| int32_t val, len = 0;; |
| int32_t ret = 0, err; |
| int32_t rbuf_dlen = 0; |
| uint32_t *rbuf_dptr = NULL; |
| char *rparms = NULL; |
| audio_hal_plugin_usecase_type_t use_case = AUDIO_HAL_PLUGIN_USECASE_INVALID; |
| snd_device_t snd_dev = 0; |
| struct ext_hw_plugin_data *my_plugin = NULL; |
| char *kv_pairs = NULL; |
| |
| if(plugin == NULL || query == NULL || reply == NULL) { |
| ALOGE("[%s] received null pointer",__func__); |
| return -EINVAL; |
| } |
| |
| err = str_parms_get_int(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_MSG_TYPE, &val); |
| if (err < 0) { |
| ALOGE("%s: Invalid or missing TYPE param for plugin msg", __func__); |
| return -EINVAL; |
| } |
| ALOGD("%s: received plugin msg type (%d)", __func__, val); |
| str_parms_del(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_MSG_TYPE); |
| |
| my_plugin = (struct ext_hw_plugin_data *)plugin; |
| if (!my_plugin->audio_hal_plugin_send_msg) { |
| ALOGE("%s: NULL audio_hal_plugin_send_msg func ptr", __func__); |
| ret = -EINVAL; |
| goto done_get_param; |
| } |
| |
| if(val == AUDIO_HAL_PLUGIN_MSG_CODEC_TUNNEL_GET_CMD) { |
| kv_pairs = str_parms_to_str(query); |
| if (kv_pairs == NULL) { |
| ret = -EINVAL; |
| ALOGE("%s: key-value pair is NULL", __func__); |
| goto done_get_param; |
| } |
| len = strlen(kv_pairs); |
| value = (char*)calloc(len, sizeof(char)); |
| if (value == NULL) { |
| ret = -ENOMEM; |
| ALOGE("[%s] failed to allocate memory",__func__); |
| goto done_get_param; |
| } |
| } else { |
| err = str_parms_get_int(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_UC, |
| &use_case); |
| if (err < 0) { |
| ALOGI("%s: Invalid or missing usecase param for plugin msg", __func__); |
| use_case = AUDIO_HAL_PLUGIN_USECASE_INVALID; |
| } else { |
| str_parms_del(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_UC); |
| |
| if ((use_case < 0) || (use_case >= AUDIO_HAL_PLUGIN_USECASE_MAX)) { |
| ALOGI("%s: Invalid usecase param for plugin msg", __func__); |
| use_case = AUDIO_HAL_PLUGIN_USECASE_INVALID; |
| goto done_get_param; |
| } |
| |
| if (my_plugin->usecase_ref_count[use_case] == 0) { |
| ALOGI("%s: plugin usecase (%d) is not enabled", |
| __func__, use_case); |
| } else { |
| /* TODO: confirm this handles all usecase */ |
| if (my_plugin->out_snd_dev[use_case]) { |
| snd_dev = my_plugin->out_snd_dev[use_case]; |
| } else if (my_plugin->in_snd_dev[use_case]) { |
| snd_dev = my_plugin->in_snd_dev[use_case]; |
| } else { |
| ALOGE("%s: No valid snd_device found for the usecase (%d)", |
| __func__, use_case); |
| ret = -EINVAL; |
| goto done_get_param; |
| } |
| } |
| } |
| } |
| |
| switch(val) { |
| case AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_VOLUME: |
| { |
| audio_hal_plugin_codec_get_pp_vol_t get_pp_vol; |
| memset(&get_pp_vol,0,sizeof(get_pp_vol)); |
| err = str_parms_get_int(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_CMASK, |
| (int*)&get_pp_vol.ch_mask); |
| if ((err < 0)) { |
| ALOGI("%s: Invalid or missing CMASK param for GET_PP_VOLUME", __func__); |
| get_pp_vol.ch_mask = AUDIO_CHANNEL_NONE; |
| } else { |
| str_parms_del(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_CMASK); |
| } |
| |
| audio_hal_plugin_msg_type_t msg = |
| AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_VOLUME; |
| get_pp_vol.usecase = use_case; |
| get_pp_vol.snd_dev = snd_dev; |
| |
| ALOGD("%s: sending get codec pp vol msg to HAL plugin driver, %d, %d, %d", |
| __func__, (int)get_pp_vol.usecase, (int)get_pp_vol.snd_dev, |
| (int)get_pp_vol.ch_mask); |
| |
| ret = my_plugin->audio_hal_plugin_send_msg(msg, &get_pp_vol, sizeof(get_pp_vol)); |
| if (ret) { |
| ALOGE("%s: Failed to get plugin pp vol err: %d", __func__, ret); |
| goto done_get_param; |
| } |
| |
| rbuf_dlen = sizeof(get_pp_vol.ret_gain)/sizeof(int32_t); |
| rbuf_dptr = calloc(rbuf_dlen, sizeof(uint32_t)); |
| if(rbuf_dptr == NULL) { |
| ALOGE("[%s] Memory allocation failed for dword length %d",__func__,rbuf_dlen); |
| ret = -ENOMEM; |
| goto done_get_param; |
| } |
| memcpy(rbuf_dptr, &get_pp_vol.ret_gain, sizeof(get_pp_vol.ret_gain)); |
| break; |
| } |
| case AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_FADE: |
| { |
| audio_hal_plugin_codec_get_pp_fade_t get_pp_fade; |
| memset(&get_pp_fade,0,sizeof(get_pp_fade)); |
| |
| audio_hal_plugin_msg_type_t msg = |
| AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_FADE; |
| get_pp_fade.usecase = use_case; |
| get_pp_fade.snd_dev = snd_dev; |
| |
| ALOGD("%s: sending get codec pp fade msg to HAL plugin driver, %d, %d", |
| __func__, (int)get_pp_fade.usecase, (int)get_pp_fade.snd_dev); |
| |
| ret = my_plugin->audio_hal_plugin_send_msg(msg, &get_pp_fade, sizeof(get_pp_fade)); |
| if (ret) { |
| ALOGE("%s: Failed to get plugin pp fade err: %d", __func__, ret); |
| goto done_get_param; |
| } |
| |
| rbuf_dlen = sizeof(get_pp_fade.ret_fade)/sizeof(int32_t); |
| rbuf_dptr = calloc(rbuf_dlen, sizeof(uint32_t)); |
| if(rbuf_dptr == NULL) { |
| ALOGE("[%s] Memory allocation failed for dword length %d",__func__,rbuf_dlen); |
| ret = -ENOMEM; |
| goto done_get_param; |
| } |
| memcpy(rbuf_dptr, &get_pp_fade.ret_fade, sizeof(get_pp_fade.ret_fade)); |
| break; |
| } |
| case AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_BALANCE: |
| { |
| audio_hal_plugin_codec_get_pp_balance_t get_pp_balance; |
| memset(&get_pp_balance,0,sizeof(get_pp_balance)); |
| |
| audio_hal_plugin_msg_type_t msg = |
| AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_BALANCE; |
| get_pp_balance.usecase = use_case; |
| get_pp_balance.snd_dev = snd_dev; |
| |
| ALOGD("%s: sending get codec pp balance msg to HAL plugin driver, %d, %d", |
| __func__, (int)get_pp_balance.usecase, (int)get_pp_balance.snd_dev); |
| |
| ret = my_plugin->audio_hal_plugin_send_msg(msg, &get_pp_balance, |
| sizeof(get_pp_balance)); |
| if (ret) { |
| ALOGE("%s: Failed to get plugin pp balance err: %d", __func__, ret); |
| goto done_get_param; |
| } |
| |
| rbuf_dlen = sizeof(get_pp_balance.ret_balance)/sizeof(int32_t); |
| rbuf_dptr = calloc(rbuf_dlen, sizeof(uint32_t)); |
| if(rbuf_dptr == NULL) { |
| ALOGE("[%s] Memory allocation failed for dword length %d",__func__,rbuf_dlen); |
| ret = -ENOMEM; |
| goto done_get_param; |
| } |
| memcpy(rbuf_dptr, &get_pp_balance.ret_balance, sizeof(get_pp_balance.ret_balance)); |
| break; |
| } |
| case AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_BMT: |
| { |
| int32_t filter_type; |
| audio_hal_plugin_codec_get_pp_bmt_t get_pp_bmt; |
| memset(&get_pp_bmt,0,sizeof(get_pp_bmt)); |
| err = str_parms_get_int(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BMT_FTYPE, |
| (int*)&filter_type); |
| if ((err < 0)) { |
| ALOGE("%s: Invalid or missing filter type param for GET_PP_BMT", __func__); |
| get_pp_bmt.filter_type = AUDIO_HAL_PLUGIN_CODEC_PP_FILTER_TYPE_INVALID; |
| } else { |
| str_parms_del(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_BMT_FTYPE); |
| |
| if ((filter_type <= AUDIO_HAL_PLUGIN_CODEC_PP_FILTER_TYPE_INVALID) && |
| (filter_type >= AUDIO_HAL_PLUGIN_CODEC_PP_FILTER_TYPE_MAX)) { |
| ALOGE("%s: Invalid filter type value for SET_PP_BMT", __func__); |
| get_pp_bmt.filter_type = AUDIO_HAL_PLUGIN_CODEC_PP_FILTER_TYPE_INVALID; |
| } else { |
| get_pp_bmt.filter_type = filter_type; |
| } |
| } |
| |
| audio_hal_plugin_msg_type_t msg = |
| AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_BMT; |
| get_pp_bmt.usecase = use_case; |
| get_pp_bmt.snd_dev = snd_dev; |
| |
| ALOGD("%s: sending get codec pp bmt msg to HAL plugin driver, %d, %d, %d", |
| __func__, (int)get_pp_bmt.usecase, (int)get_pp_bmt.snd_dev, |
| (int)get_pp_bmt.filter_type); |
| |
| ret = my_plugin->audio_hal_plugin_send_msg(msg, &get_pp_bmt, sizeof(get_pp_bmt)); |
| if (ret) { |
| ALOGE("%s: Failed to get plugin pp bmt err: %d", __func__, ret); |
| goto done_get_param; |
| } |
| |
| rbuf_dlen = sizeof(get_pp_bmt.ret_value)/sizeof(int32_t); |
| rbuf_dptr = calloc(rbuf_dlen, sizeof(uint32_t)); |
| if(rbuf_dptr == NULL) { |
| ALOGE("[%s] Memory allocation failed for dword length %d",__func__,rbuf_dlen); |
| ret = -ENOMEM; |
| goto done_get_param; |
| } |
| memcpy(rbuf_dptr, &get_pp_bmt.ret_value, sizeof(get_pp_bmt.ret_value)); |
| break; |
| } |
| case AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_EQ: |
| { |
| uint32_t rbuf_len = 0; |
| char *tmp_ptr = NULL; |
| audio_hal_plugin_codec_get_pp_eq_t get_pp_eq; |
| memset(&get_pp_eq,0,sizeof(get_pp_eq)); |
| |
| audio_hal_plugin_msg_type_t msg = AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_EQ; |
| get_pp_eq.usecase = use_case; |
| get_pp_eq.snd_dev = snd_dev; |
| |
| ALOGD("%s: sending get codec pp eq msg to HAL plugin driver, %d, %d", |
| __func__, (int)get_pp_eq.usecase, (int)get_pp_eq.snd_dev); |
| |
| ret = my_plugin->audio_hal_plugin_send_msg(msg, &get_pp_eq, sizeof(get_pp_eq)); |
| if (ret) { |
| ALOGE("%s: Failed to get plugin pp eq err: %d", __func__, ret); |
| goto done_get_param; |
| } |
| |
| rbuf_len = sizeof(get_pp_eq.ret_preset_id) + sizeof(get_pp_eq.ret_num_bands); |
| rbuf_dlen = rbuf_len / sizeof(uint32_t); |
| rbuf_dptr = calloc(rbuf_dlen, sizeof(uint32_t)); |
| if(rbuf_dptr == NULL) { |
| ALOGE("[%s] Memory allocation failed for dword length %d",__func__,rbuf_dlen); |
| ret = -ENOMEM; |
| goto done_get_param; |
| } |
| tmp_ptr = (char*)rbuf_dptr; |
| memcpy(tmp_ptr, &get_pp_eq.ret_preset_id, sizeof(get_pp_eq.ret_preset_id)); |
| tmp_ptr += sizeof(get_pp_eq.ret_preset_id); |
| memcpy(tmp_ptr, &get_pp_eq.ret_num_bands, sizeof(get_pp_eq.ret_num_bands)); |
| break; |
| } |
| case AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_EQ_SUBBANDS: |
| { |
| uint32_t rbuf_len = 0; |
| audio_hal_plugin_codec_get_pp_eq_subbands_t get_pp_eq_subbands; |
| memset(&get_pp_eq_subbands,0,sizeof(get_pp_eq_subbands)); |
| err = str_parms_get_int(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_NUM_BANDS, |
| (int*)&get_pp_eq_subbands.num_bands); |
| if ((err < 0)) { |
| ALOGE("%s: Invalid or missing num bands param for GET_PP_EQ_SUBBANDS", |
| __func__); |
| ret = -EINVAL; |
| goto done_get_param; |
| } else { |
| str_parms_del(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_EQ_NUM_BANDS); |
| |
| if(get_pp_eq_subbands.num_bands == 0) { |
| ALOGE("%s: Zero num bands param for GET_PP_EQ_SUBBANDS", |
| __func__); |
| ret = -EINVAL; |
| goto done_get_param; |
| } |
| } |
| rbuf_len = get_pp_eq_subbands.num_bands * |
| sizeof(audio_hal_plugin_pp_eq_subband_binfo_t); |
| |
| audio_hal_plugin_msg_type_t msg = AUDIO_HAL_PLUGIN_MSG_CODEC_GET_PP_EQ_SUBBANDS; |
| get_pp_eq_subbands.usecase = use_case; |
| get_pp_eq_subbands.snd_dev = snd_dev; |
| get_pp_eq_subbands.ret_bands = calloc(rbuf_len, 1); |
| if(get_pp_eq_subbands.ret_bands == NULL) { |
| ret = -ENOMEM; |
| ALOGE("[%s] failed to allocate memory",__func__); |
| goto done_get_param; |
| } |
| |
| ALOGD("%s: sending get codec pp eq subbands msg to plugin driver, %d, %d, %d", |
| __func__, (int)get_pp_eq_subbands.usecase, |
| (int)get_pp_eq_subbands.snd_dev, (int)get_pp_eq_subbands.num_bands); |
| |
| ret = my_plugin->audio_hal_plugin_send_msg(msg, &get_pp_eq_subbands, |
| sizeof(get_pp_eq_subbands)); |
| if (ret) { |
| ALOGE("%s: Failed to get plugin pp eq subbands err: %d", __func__, ret); |
| goto done_get_eq_subbands; |
| } |
| |
| rbuf_dlen = rbuf_len / sizeof(uint32_t); |
| rbuf_dptr = calloc(rbuf_dlen, sizeof(uint32_t)); |
| if(rbuf_dptr == NULL) { |
| ALOGE("[%s] Memory allocation failed for dword length %d",__func__,rbuf_dlen); |
| ret = -ENOMEM; |
| goto done_get_eq_subbands; |
| } |
| memcpy(rbuf_dptr, get_pp_eq_subbands.ret_bands, rbuf_len); |
| |
| done_get_eq_subbands: |
| if(get_pp_eq_subbands.ret_bands != NULL) |
| free(get_pp_eq_subbands.ret_bands); |
| break; |
| } |
| case AUDIO_HAL_PLUGIN_MSG_CODEC_TUNNEL_GET_CMD: |
| { |
| char *tmp_ptr = NULL; |
| audio_hal_plugin_codec_tunnel_get_t tunnel_get; |
| memset(&tunnel_get,0,sizeof(tunnel_get)); |
| |
| err = str_parms_get_int(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_SIZE, |
| (int*)&tunnel_get.param_size); |
| if ((err < 0) || (!tunnel_get.param_size)) { |
| ALOGE("%s: Invalid or missing size param for TUNNEL GET command", __func__); |
| ret = -EINVAL; |
| goto done_get_param; |
| } |
| str_parms_del(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_SIZE); |
| |
| err = str_parms_get_str(query, |
| AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_DATA, value, len); |
| if (err < 0) { |
| ALOGE("%s: Invalid or missing data param for TUNNEL GET command", __func__); |
| ret = -EINVAL; |
| goto done_get_param; |
| } |
| str_parms_del(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_DATA); |
| |
| err = str_parms_get_int(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_GET_SIZE, |
| (int*)&tunnel_get.size_to_get); |
| if (err < 0 || (!tunnel_get.size_to_get)) { |
| ALOGE("%s: Invalid or missing size_to_get param for TUNNEL GET command", |
| __func__); |
| ret = -EINVAL; |
| goto done_get_param; |
| } |
| str_parms_del(query, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_TUNNEL_GET_SIZE); |
| |
| ret = ext_hw_plugin_string_to_dword(value, (void**)&tunnel_get.param_data, |
| tunnel_get.param_size); |
| if (ret) { |
| ALOGE("%s: Failed to parse payload for TUNNEL GET command", __func__); |
| ret = -EINVAL; |
| goto done_tunnel_get; |
| } |
| |
| audio_hal_plugin_msg_type_t msg = |
| AUDIO_HAL_PLUGIN_MSG_CODEC_TUNNEL_GET_CMD; |
| tunnel_get.ret_data = calloc(tunnel_get.size_to_get, sizeof(int32_t)); |
| if(tunnel_get.ret_data == NULL) { |
| ret = -ENOMEM; |
| ALOGE("[%s] failed to allocate memory",__func__); |
| goto done_tunnel_get; |
| } |
| |
| ALOGD("%s: sending tunnel get cmd to plugin driver,size = %d, size_to_get = %d", |
| __func__, (int)tunnel_get.param_size, (int)tunnel_get.size_to_get); |
| |
| ret = my_plugin->audio_hal_plugin_send_msg(msg, (void*)&tunnel_get, |
| sizeof(tunnel_get)); |
| if (ret) { |
| ALOGE("%s: Failed to send plugin tunnel get cmd err: %d", __func__, ret); |
| goto done_tunnel_get; |
| } |
| if ((tunnel_get.ret_size == 0) || |
| (tunnel_get.ret_size > tunnel_get.size_to_get)) { |
| ret = -EINVAL; |
| ALOGE("[%s] Invalid tunnel get cmd return size: %d", |
| __func__, tunnel_get.ret_size); |
| goto done_tunnel_get; |
| } |
| |
| rbuf_dlen = tunnel_get.ret_size + 1; |
| rbuf_dptr = calloc(rbuf_dlen, sizeof(uint32_t)); |
| if(rbuf_dptr == NULL) { |
| ALOGE("[%s] Memory allocation failed for dword length %d",__func__,rbuf_dlen); |
| ret = -ENOMEM; |
| goto done_tunnel_get; |
| } |
| tmp_ptr = (char*)rbuf_dptr; |
| memcpy(tmp_ptr, &tunnel_get.ret_size, sizeof(uint32_t)); |
| tmp_ptr += sizeof(uint32_t); |
| memcpy(tmp_ptr, tunnel_get.ret_data, 4*tunnel_get.ret_size); |
| |
| done_tunnel_get: |
| if (tunnel_get.param_data!= NULL) |
| free(tunnel_get.param_data); |
| if (tunnel_get.ret_data!= NULL) |
| free(tunnel_get.ret_data); |
| break; |
| } |
| default: |
| ALOGE("%s: Invalid plugin message type: %d", __func__, val); |
| ret = -EINVAL; |
| } |
| |
| if(ret == 0) { |
| ret = ext_hw_plugin_dword_to_string(rbuf_dptr, rbuf_dlen, &rparms); |
| if (ret < 0) { |
| ALOGE("%s: Failed to convert param info for MSG_TYPE %d", __func__, val); |
| goto done_get_param; |
| } |
| ret = 0; |
| str_parms_add_int(reply, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_GETPARAM_RESULT, ret); |
| str_parms_add_str(reply, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_GETPARAM_DATA, rparms); |
| } |
| |
| done_get_param: |
| if(ret) { |
| str_parms_add_int(reply, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_GETPARAM_RESULT, ret); |
| str_parms_add_str(reply, AUDIO_PARAMETER_KEY_EXT_HW_PLUGIN_GETPARAM_DATA, ""); |
| } |
| if(rbuf_dptr!= NULL) |
| free(rbuf_dptr); |
| if(rparms!= NULL) |
| free(rparms); |
| |
| ALOGI("%s: exit with code(%d)", __func__, ret); |
| if(kv_pairs != NULL) |
| free(kv_pairs); |
| if(value != NULL) |
| free(value); |
| return ret; |
| } |
| |
| int ext_hw_plugin_set_mic_mute(void *plugin, bool mute) |
| { |
| struct ext_hw_plugin_data *my_plugin = NULL; |
| audio_hal_plugin_codec_set_pp_mute_t pp_mute; |
| int ret = 0; |
| |
| ALOGD("%s: received set mic mute (%d)", __func__, mute); |
| |
| if (plugin == NULL) { |
| ALOGE("[%s] received null pointer",__func__); |
| return -EINVAL; |
| } |
| |
| my_plugin = (struct ext_hw_plugin_data *)plugin; |
| if (!my_plugin->audio_hal_plugin_send_msg) { |
| ALOGE("%s: NULL audio_hal_plugin_send_msg func ptr", __func__); |
| return -EINVAL; |
| } |
| |
| my_plugin->mic_mute = mute; |
| |
| /* Set mic mute is currently supported only for HFP call use case. */ |
| if (my_plugin->usecase_ref_count[AUDIO_HAL_PLUGIN_USECASE_HFP_VOICE_CALL]) { |
| pp_mute.snd_dev= my_plugin->in_snd_dev[AUDIO_HAL_PLUGIN_USECASE_HFP_VOICE_CALL]; |
| pp_mute.usecase = AUDIO_HAL_PLUGIN_USECASE_HFP_VOICE_CALL; |
| pp_mute.ch_mask = AUDIO_CHANNEL_IN_ALL; |
| pp_mute.flag = mute; |
| |
| ALOGV("%s: sending codec pp mute msg to HAL plugin driver, %d, %d, %x, %d", |
| __func__, (int)pp_mute.usecase, (int)pp_mute.snd_dev, |
| (int)pp_mute.ch_mask, (int)pp_mute.flag); |
| ret = my_plugin->audio_hal_plugin_send_msg( |
| AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_MUTE, &pp_mute, |
| sizeof(pp_mute)); |
| if (ret) { |
| ALOGE("%s: Failed to set plugin pp mute err: %d", __func__, ret); |
| } |
| } |
| |
| return ret; |
| } |
| |
| int ext_hw_plugin_get_mic_mute(void *plugin, bool *mute) |
| { |
| struct ext_hw_plugin_data *my_plugin = (struct ext_hw_plugin_data *)plugin; |
| |
| if (my_plugin == NULL || mute == NULL) { |
| ALOGE("[%s] received null pointer", __func__); |
| return -EINVAL; |
| } |
| |
| *mute = my_plugin->mic_mute; |
| ALOGD("%s: received get mic mute (%d)", __func__, *mute); |
| |
| return 0; |
| } |
| |
| int ext_hw_plugin_set_audio_gain(void *plugin, |
| struct audio_usecase *usecase, uint32_t gain) |
| { |
| int32_t ret = 0; |
| struct ext_hw_plugin_data *my_plugin = (struct ext_hw_plugin_data *)plugin; |
| audio_hal_plugin_codec_set_pp_vol_t pp_vol; |
| |
| if ((my_plugin == NULL) || (usecase == NULL)) { |
| ALOGE("%s: NULL input pointer", __func__); |
| return -EINVAL; |
| } |
| |
| if (!my_plugin->audio_hal_plugin_send_msg) { |
| ALOGE("%s: NULL audio_hal_plugin_send_msg func ptr", __func__); |
| return -EINVAL; |
| } |
| |
| memset(&pp_vol, 0, sizeof(pp_vol)); |
| |
| ret = ext_hw_plugin_check_plugin_usecase(usecase->id, &pp_vol.usecase); |
| if (ret) { |
| ALOGI("%s: Set audio gain skipped for audio usecase %d", |
| __func__, usecase->id); |
| return 0; |
| } |
| |
| #if 0 |
| /* Skip active usecase check and continue vol set to plugin |
| * to allow volume cached per usecase in plugin. |
| */ |
| if (!my_plugin->usecase_ref_count[pp_vol.usecase]) { |
| ALOGV("%s: Plugin usecase %d is not enabled", |
| __func__, pp_vol.usecase); |
| return 0; |
| } |
| |
| if (my_plugin->out_snd_dev[pp_vol.usecase]) { |
| pp_vol.snd_dev = my_plugin->out_snd_dev[pp_vol.usecase]; |
| pp_vol.ch_mask = AUDIO_CHANNEL_OUT_ALL; |
| } else if (my_plugin->in_snd_dev[pp_vol.usecase]) { |
| pp_vol.snd_dev = my_plugin->in_snd_dev[pp_vol.usecase]; |
| pp_vol.ch_mask = AUDIO_CHANNEL_IN_ALL; |
| } else { |
| ALOGE("%s: No valid snd_device found for usecase %d", |
| __func__, pp_vol.usecase); |
| return -EINVAL; |
| } |
| #endif |
| |
| /* NOTE: Use in/out snd device from usecase to decide |
| * which direction pp_volume should apply. |
| */ |
| if (usecase->out_snd_device != SND_DEVICE_NONE) { |
| pp_vol.snd_dev = usecase->out_snd_device; |
| pp_vol.ch_mask = AUDIO_CHANNEL_OUT_ALL; |
| } else if (usecase->in_snd_device != SND_DEVICE_NONE) { |
| pp_vol.snd_dev = usecase->in_snd_device; |
| pp_vol.ch_mask = AUDIO_CHANNEL_IN_ALL; |
| } else { |
| ALOGE("%s: No valid snd_device found for usecase %d", |
| __func__, pp_vol.usecase); |
| return -EINVAL; |
| } |
| |
| pp_vol.gain = gain; |
| |
| ALOGD("%s: Sending codec pp vol msg to HAL plugin driver, %d, %d, %d, %d", |
| __func__, (int)pp_vol.usecase, (int)pp_vol.snd_dev, |
| (int)pp_vol.ch_mask, (int)pp_vol.gain); |
| ret = my_plugin->audio_hal_plugin_send_msg( |
| AUDIO_HAL_PLUGIN_MSG_CODEC_SET_PP_VOLUME, |
| &pp_vol, sizeof(pp_vol)); |
| if (ret) { |
| ALOGE("%s: Failed to set plugin pp vol err: %d", __func__, ret); |
| } |
| return ret; |
| } |