/* * Copyright (c) 2014-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 * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of The Linux Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define LOG_TAG "audio_ext_hw_plugin" #define LOG_NDEBUG 0 #include #include #include #include #include #include "audio_extn.h" #include "platform_api.h" #include "platform.h" #include "audio_hal_plugin.h" #ifdef EXT_HW_PLUGIN_ENABLED 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 */ #define LIB_PLUGIN_DRIVER "libaudiohalplugin.so" void* audio_extn_ext_hw_plugin_init(struct audio_device *adev) { 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; (void)audio_extn_auto_hal_enable_hostless(); 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 audio_extn_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); audio_extn_auto_hal_disable_hostless(); 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: *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_FM_VIRTUAL: *plugin_usecase = AUDIO_HAL_PLUGIN_USECASE_DEFAULT_CAPTURE; break; case USECASE_AUDIO_HFP_SCO: case USECASE_AUDIO_HFP_SCO_WB: *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; default: ret = -EINVAL; } return ret; } int32_t audio_extn_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->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)) { 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->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 audio_extn_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->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->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 = 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>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 = 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 audio_extn_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); 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 audio_extn_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); 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 audio_extn_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 audio_extn_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 audio_extn_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; } #endif /* EXT_HW_PLUGIN_ENABLED */