/* alsa_default.cpp
**
** Copyright 2009 Wind River Systems
** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#define LOG_TAG "ALSAModule"
//#define LOG_NDEBUG 0
#define LOG_NDDEBUG 0
#include <utils/Log.h>
#include <cutils/properties.h>
#include <linux/ioctl.h>
#include "AudioUtil.h"
#include "AudioHardwareALSA.h"
#include <media/AudioRecord.h>
#include <dlfcn.h>
#ifdef QCOM_CSDCLIENT_ENABLED
extern "C" {
static int (*csd_disable_device)();
static int (*csd_enable_device)(int, int, uint32_t);
static int (*csd_volume)(int);
static int (*csd_mic_mute)(int);
static int (*csd_wide_voice)(uint8_t);
static int (*csd_slow_talk)(uint8_t);
static int (*csd_fens)(uint8_t);
static int (*csd_start_voice)();
static int (*csd_stop_voice)();
}
#endif
#ifndef ALSA_DEFAULT_SAMPLE_RATE
#define ALSA_DEFAULT_SAMPLE_RATE 44100 // in Hz
#endif
#define BTSCO_RATE_16KHZ 16000
#define USECASE_TYPE_RX 1
#define USECASE_TYPE_TX 2
#define MAX_HDMI_CHANNEL_CNT 6
namespace android_audio_legacy
{
static int s_device_open(const hw_module_t*, const char*, hw_device_t**);
static int s_device_close(hw_device_t*);
static status_t s_init(alsa_device_t *, ALSAHandleList &);
static status_t s_open(alsa_handle_t *);
static status_t s_close(alsa_handle_t *);
static status_t s_standby(alsa_handle_t *);
static status_t s_route(alsa_handle_t *, uint32_t, int);
static status_t s_start_voice_call(alsa_handle_t *);
static status_t s_start_voip_call(alsa_handle_t *);
static status_t s_start_fm(alsa_handle_t *);
static void s_set_voice_volume(int);
static void s_set_voip_volume(int);
static void s_set_mic_mute(int);
static void s_set_voip_mic_mute(int);
static void s_set_voip_config(int, int);
static status_t s_set_fm_vol(int);
static void s_set_btsco_rate(int);
static status_t s_set_lpa_vol(int);
static void s_enable_wide_voice(bool flag);
static void s_enable_fens(bool flag);
static void s_set_flags(uint32_t flags);
static status_t s_set_compressed_vol(int);
static void s_enable_slow_talk(bool flag);
static void s_set_voc_rec_mode(uint8_t mode);
static void s_set_volte_mic_mute(int state);
static void s_set_volte_volume(int vol);
static bool s_is_tmus();
#ifdef SEPERATED_AUDIO_INPUT
static void s_setInput(int);
static int input_source;
#endif
static int mccmnc;
#ifdef QCOM_CSDCLIENT_ENABLED
static void s_set_csd_handle(void*);
#endif
static char mic_type[25];
static char curRxUCMDevice[50];
static char curTxUCMDevice[50];
static int fluence_mode;
static int fmVolume;
#ifdef USES_FLUENCE_INCALL
static uint32_t mDevSettingsFlag = TTY_OFF | DMIC_FLAG;
#else
static uint32_t mDevSettingsFlag = TTY_OFF;
#endif
static int btsco_samplerate = 8000;
static ALSAUseCaseList mUseCaseList;
static void *csd_handle;
static hw_module_methods_t s_module_methods = {
open : s_device_open
};
extern "C" {
hw_module_t HAL_MODULE_INFO_SYM = {
tag : HARDWARE_MODULE_TAG,
version_major : 1,
version_minor : 0,
id : ALSA_HARDWARE_MODULE_ID,
name : "QCOM ALSA module",
author : "QuIC Inc",
methods : &s_module_methods,
dso : 0,
reserved : {0,},
};
}
static int s_device_open(const hw_module_t* module, const char* name,
hw_device_t** device)
{
char value[128];
alsa_device_t *dev;
dev = (alsa_device_t *) malloc(sizeof(*dev));
if (!dev) return -ENOMEM;
memset(dev, 0, sizeof(*dev));
/* initialize the procs */
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.version = 0;
dev->common.module = (hw_module_t *) module;
dev->common.close = s_device_close;
dev->init = s_init;
dev->open = s_open;
dev->close = s_close;
dev->route = s_route;
dev->standby = s_standby;
dev->startVoiceCall = s_start_voice_call;
dev->startVoipCall = s_start_voip_call;
dev->startFm = s_start_fm;
dev->setVoiceVolume = s_set_voice_volume;
dev->setVoipVolume = s_set_voip_volume;
dev->setMicMute = s_set_mic_mute;
dev->setVoipMicMute = s_set_voip_mic_mute;
dev->setVoipConfig = s_set_voip_config;
dev->setFmVolume = s_set_fm_vol;
dev->setBtscoRate = s_set_btsco_rate;
dev->setLpaVolume = s_set_lpa_vol;
dev->enableWideVoice = s_enable_wide_voice;
dev->enableFENS = s_enable_fens;
dev->setFlags = s_set_flags;
dev->setCompressedVolume = s_set_compressed_vol;
dev->enableSlowTalk = s_enable_slow_talk;
dev->setVocRecMode = s_set_voc_rec_mode;
dev->setVoLTEMicMute = s_set_volte_mic_mute;
dev->setVoLTEVolume = s_set_volte_volume;
#ifdef SEPERATED_AUDIO_INPUT
dev->setInput = s_setInput;
#endif
#ifdef QCOM_CSDCLIENT_ENABLED
dev->setCsdHandle = s_set_csd_handle;
#endif
*device = &dev->common;
property_get("persist.audio.handset.mic",value,"0");
strlcpy(mic_type, value, sizeof(mic_type));
property_get("persist.audio.fluence.mode",value,"0");
if (!strcmp("broadside", value)) {
fluence_mode = FLUENCE_MODE_BROADSIDE;
} else {
fluence_mode = FLUENCE_MODE_ENDFIRE;
}
strlcpy(curRxUCMDevice, "None", sizeof(curRxUCMDevice));
strlcpy(curTxUCMDevice, "None", sizeof(curTxUCMDevice));
ALOGV("ALSA module opened");
return 0;
}
static int s_device_close(hw_device_t* device)
{
free(device);
device = NULL;
return 0;
}
// ----------------------------------------------------------------------------
static const int DEFAULT_SAMPLE_RATE = ALSA_DEFAULT_SAMPLE_RATE;
static void switchDevice(alsa_handle_t *handle, uint32_t devices, uint32_t mode);
static char *getUCMDevice(uint32_t devices, int input, char *rxDevice);
static void disableDevice(alsa_handle_t *handle);
int getUseCaseType(const char *useCase);
static int callMode = AudioSystem::MODE_NORMAL;
// ----------------------------------------------------------------------------
bool platform_is_Fusion3()
{
char platform[128], baseband[128];
property_get("ro.board.platform", platform, "");
property_get("ro.baseband", baseband, "");
if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband))
return true;
else
return false;
}
int deviceName(alsa_handle_t *handle, unsigned flags, char **value)
{
int ret = 0;
char ident[70];
if (flags & PCM_IN) {
strlcpy(ident, "CapturePCM/", sizeof(ident));
} else {
strlcpy(ident, "PlaybackPCM/", sizeof(ident));
}
strlcat(ident, handle->useCase, sizeof(ident));
ret = snd_use_case_get(handle->ucMgr, ident, (const char **)value);
ALOGD("Device value returned is %s", (*value));
return ret;
}
status_t setHDMIChannelCount()
{
status_t err = NO_ERROR;
int channel_count = 0;
const char *channel_cnt_str = NULL;
EDID_AUDIO_INFO info = { 0 };
ALSAControl control("/dev/snd/controlC0");
if (AudioUtil::getHDMIAudioSinkCaps(&info)) {
for (int i = 0; i < info.nAudioBlocks && i < MAX_EDID_BLOCKS; i++) {
if (info.AudioBlocksArray[i].nChannels > channel_count &&
info.AudioBlocksArray[i].nChannels <= MAX_HDMI_CHANNEL_CNT) {
channel_count = info.AudioBlocksArray[i].nChannels;
}
}
}
switch (channel_count) {
case 6: channel_cnt_str = "Six"; break;
case 5: channel_cnt_str = "Five"; break;
case 4: channel_cnt_str = "Four"; break;
case 3: channel_cnt_str = "Three"; break;
default: channel_cnt_str = "Two"; break;
}
ALOGD("HDMI channel count: %s", channel_cnt_str);
control.set("HDMI_RX Channels", channel_cnt_str);
return err;
}
status_t setHardwareParams(alsa_handle_t *handle)
{
struct snd_pcm_hw_params *params;
unsigned long bufferSize, reqBuffSize;
unsigned int periodTime, bufferTime;
unsigned int requestedRate = handle->sampleRate;
int status = 0;
int channels = handle->channels;
snd_pcm_format_t format = SNDRV_PCM_FORMAT_S16_LE;
params = (snd_pcm_hw_params*) calloc(1, sizeof(struct snd_pcm_hw_params));
if (!params) {
ALOGE("Failed to allocate ALSA hardware parameters!");
return NO_INIT;
}
reqBuffSize = handle->bufferSize;
ALOGD("setHardwareParams: reqBuffSize %d channels %d sampleRate %d",
(int) reqBuffSize, handle->channels, handle->sampleRate);
#ifdef QCOM_SSR_ENABLED
if (channels == 6) {
if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
|| !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
ALOGV("HWParams: Use 4 channels in kernel for 5.1(%s) recording ", handle->useCase);
channels = 4;
}
}
#endif
param_init(params);
param_set_mask(params, SNDRV_PCM_HW_PARAM_ACCESS,
SNDRV_PCM_ACCESS_RW_INTERLEAVED);
if (handle->format != SNDRV_PCM_FORMAT_S16_LE) {
if (handle->format == AudioSystem::AMR_NB
|| handle->format == AudioSystem::AMR_WB
#ifdef QCOM_QCHAT_ENABLED
|| handle->format == AudioSystem::EVRC
|| handle->format == AudioSystem::EVRCB
|| handle->format == AudioSystem::EVRCWB
#endif
)
format = SNDRV_PCM_FORMAT_SPECIAL;
}
param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
format);
param_set_mask(params, SNDRV_PCM_HW_PARAM_SUBFORMAT,
SNDRV_PCM_SUBFORMAT_STD);
param_set_int(params, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, reqBuffSize);
param_set_int(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 16);
param_set_int(params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
channels * 16);
param_set_int(params, SNDRV_PCM_HW_PARAM_CHANNELS,
channels);
param_set_int(params, SNDRV_PCM_HW_PARAM_RATE, handle->sampleRate);
param_set_hw_refine(handle->handle, params);
if (param_set_hw_params(handle->handle, params)) {
ALOGE("cannot set hw params");
return NO_INIT;
}
param_dump(params);
handle->handle->buffer_size = pcm_buffer_size(params);
handle->handle->period_size = pcm_period_size(params);
handle->handle->period_cnt = handle->handle->buffer_size/handle->handle->period_size;
ALOGD("setHardwareParams: buffer_size %d, period_size %d, period_cnt %d",
handle->handle->buffer_size, handle->handle->period_size,
handle->handle->period_cnt);
handle->handle->rate = handle->sampleRate;
handle->handle->channels = handle->channels;
handle->periodSize = handle->handle->period_size;
if (strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC) &&
strcmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC) &&
(6 != handle->channels)) {
//Do not update buffersize for 5.1 recording
handle->bufferSize = handle->handle->period_size;
}
return NO_ERROR;
}
status_t setSoftwareParams(alsa_handle_t *handle)
{
struct snd_pcm_sw_params* params;
struct pcm* pcm = handle->handle;
unsigned long periodSize = pcm->period_size;
int channels = handle->channels;
params = (snd_pcm_sw_params*) calloc(1, sizeof(struct snd_pcm_sw_params));
if (!params) {
LOG_ALWAYS_FATAL("Failed to allocate ALSA software parameters!");
return NO_INIT;
}
#ifdef QCOM_SSR_ENABLED
if (channels == 6) {
if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
|| !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
ALOGV("SWParams: Use 4 channels in kernel for 5.1(%s) recording ", handle->useCase);
channels = 4;
}
}
#endif
// Get the current software parameters
params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
params->period_step = 1;
if(((!strcmp(handle->useCase,SND_USE_CASE_MOD_PLAY_VOIP)) ||
(!strcmp(handle->useCase,SND_USE_CASE_VERB_IP_VOICECALL)))){
ALOGV("setparam: start & stop threshold for Voip ");
params->avail_min = handle->channels - 1 ? periodSize/4 : periodSize/2;
params->start_threshold = periodSize/2;
params->stop_threshold = INT_MAX;
} else {
params->avail_min = periodSize/(channels * 2);
params->start_threshold = periodSize/(channels * 2);
params->stop_threshold = INT_MAX;
}
params->silence_threshold = 0;
params->silence_size = 0;
if (param_set_sw_params(handle->handle, params)) {
ALOGE("cannot set sw params");
return NO_INIT;
}
return NO_ERROR;
}
void switchDevice(alsa_handle_t *handle, uint32_t devices, uint32_t mode)
{
const char **mods_list;
use_case_t useCaseNode;
unsigned usecase_type = 0;
bool inCallDevSwitch = false;
char *rxDevice, *txDevice, ident[70], *use_case = NULL;
int err = 0, index, mods_size;
int rx_dev_id, tx_dev_id;
ALOGD("%s: device %d mode:%d", __FUNCTION__, devices, mode);
if ((mode == AudioSystem::MODE_IN_CALL) || (mode == AudioSystem::MODE_IN_COMMUNICATION)) {
if ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
(devices & AudioSystem::DEVICE_IN_WIRED_HEADSET)) {
devices = devices | (AudioSystem::DEVICE_OUT_WIRED_HEADSET |
AudioSystem::DEVICE_IN_WIRED_HEADSET);
} else if (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) {
devices = devices | (AudioSystem::DEVICE_OUT_WIRED_HEADPHONE |
AudioSystem::DEVICE_IN_BUILTIN_MIC);
} else if (devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) {
if (mode == AudioSystem::MODE_IN_CALL) {
devices |= AudioSystem::DEVICE_OUT_EARPIECE;
} else if (mode == AudioSystem::MODE_IN_COMMUNICATION) {
if (!strncmp(curRxUCMDevice, SND_USE_CASE_DEV_SPEAKER, MAX_LEN(curRxUCMDevice, SND_USE_CASE_DEV_SPEAKER))) {
devices &= ~AudioSystem::DEVICE_IN_BUILTIN_MIC;
devices |= AudioSystem::DEVICE_IN_BACK_MIC;
}
}
} else if (devices & AudioSystem::DEVICE_OUT_EARPIECE) {
devices = devices | AudioSystem::DEVICE_IN_BUILTIN_MIC;
} else if (devices & AudioSystem::DEVICE_OUT_SPEAKER) {
devices = devices | (AudioSystem::DEVICE_IN_BACK_MIC |
AudioSystem::DEVICE_OUT_SPEAKER);
} else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO) ||
(devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET) ||
(devices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
devices = devices | (AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET |
AudioSystem::DEVICE_OUT_BLUETOOTH_SCO);
#ifdef QCOM_ANC_HEADSET_ENABLED
} else if ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
(devices & AudioSystem::DEVICE_IN_ANC_HEADSET)) {
devices = devices | (AudioSystem::DEVICE_OUT_ANC_HEADSET |
AudioSystem::DEVICE_IN_ANC_HEADSET);
} else if (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE) {
devices = devices | (AudioSystem::DEVICE_OUT_ANC_HEADPHONE |
AudioSystem::DEVICE_IN_BUILTIN_MIC);
#endif
} else if (devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
if (mode == AudioSystem::MODE_IN_CALL)
devices = devices | (AudioSystem::DEVICE_IN_BACK_MIC |
AudioSystem::DEVICE_OUT_SPEAKER);
else
devices = devices | (AudioSystem::DEVICE_OUT_AUX_DIGITAL |
AudioSystem::DEVICE_IN_BACK_MIC);
#ifdef QCOM_PROXY_DEVICE_ENABLED
} else if ((devices & AudioSystem::DEVICE_OUT_PROXY) ||
(devices & AudioSystem::DEVICE_IN_PROXY)) {
devices = devices | (AudioSystem::DEVICE_OUT_PROXY |
AudioSystem::DEVICE_IN_PROXY);
#endif
}
}
#ifdef QCOM_SSR_ENABLED
if ((devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) && ( 6 == handle->channels)) {
if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
|| !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
ALOGV(" switchDevice , use ssr devices for channels:%d usecase:%s",handle->channels,handle->useCase);
s_set_flags(SSRQMIC_FLAG);
}
}
#endif
rxDevice = getUCMDevice(devices & AudioSystem::DEVICE_OUT_ALL, 0, NULL);
txDevice = getUCMDevice(devices & AudioSystem::DEVICE_IN_ALL, 1, rxDevice);
if ((rxDevice != NULL) && (txDevice != NULL)) {
if (((strncmp(rxDevice, curRxUCMDevice, MAX_STR_LEN)) ||
(strncmp(txDevice, curTxUCMDevice, MAX_STR_LEN))) &&
((mode == AudioSystem::MODE_IN_CALL) ||
(mode == AudioSystem::MODE_IN_COMMUNICATION)))
inCallDevSwitch = true;
}
#ifdef QCOM_CSDCLIENT_ENABLED
if (platform_is_Fusion3() && (inCallDevSwitch == true)) {
if (csd_disable_device == NULL) {
ALOGE("dlsym:Error:%s Loading csd_client_disable_device", dlerror());
} else {
err = csd_disable_device();
if (err < 0)
{
ALOGE("csd_client_disable_device, failed, error %d", err);
}
}
}
#endif
snd_use_case_get(handle->ucMgr, "_verb", (const char **)&use_case);
mods_size = snd_use_case_get_list(handle->ucMgr, "_enamods", &mods_list);
if (rxDevice != NULL) {
if ((strncmp(curRxUCMDevice, "None", 4)) &&
((strncmp(rxDevice, curRxUCMDevice, MAX_STR_LEN)) || (inCallDevSwitch == true))) {
if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
strlen(SND_USE_CASE_VERB_INACTIVE)))) {
usecase_type = getUseCaseType(use_case);
if (usecase_type & USECASE_TYPE_RX) {
ALOGD("Deroute use case %s type is %d\n", use_case, usecase_type);
strlcpy(useCaseNode.useCase, use_case, MAX_STR_LEN);
snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
mUseCaseList.push_front(useCaseNode);
}
}
if (mods_size) {
for(index = 0; index < mods_size; index++) {
usecase_type = getUseCaseType(mods_list[index]);
if (usecase_type & USECASE_TYPE_RX) {
ALOGD("Deroute use case %s type is %d\n", mods_list[index], usecase_type);
strlcpy(useCaseNode.useCase, mods_list[index], MAX_STR_LEN);
snd_use_case_set(handle->ucMgr, "_dismod", mods_list[index]);
mUseCaseList.push_back(useCaseNode);
}
}
}
snd_use_case_set(handle->ucMgr, "_disdev", curRxUCMDevice);
}
}
if (txDevice != NULL) {
if ((strncmp(curTxUCMDevice, "None", 4)) &&
((strncmp(txDevice, curTxUCMDevice, MAX_STR_LEN)) || (inCallDevSwitch == true))) {
if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
strlen(SND_USE_CASE_VERB_INACTIVE)))) {
usecase_type = getUseCaseType(use_case);
if ((usecase_type & USECASE_TYPE_TX) && (!(usecase_type & USECASE_TYPE_RX))) {
ALOGD("Deroute use case %s type is %d\n", use_case, usecase_type);
strlcpy(useCaseNode.useCase, use_case, MAX_STR_LEN);
snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
mUseCaseList.push_front(useCaseNode);
}
}
if (mods_size) {
for(index = 0; index < mods_size; index++) {
usecase_type = getUseCaseType(mods_list[index]);
if ((usecase_type & USECASE_TYPE_TX) && (!(usecase_type & USECASE_TYPE_RX))) {
ALOGD("Deroute use case %s type is %d\n", mods_list[index], usecase_type);
strlcpy(useCaseNode.useCase, mods_list[index], MAX_STR_LEN);
snd_use_case_set(handle->ucMgr, "_dismod", mods_list[index]);
mUseCaseList.push_back(useCaseNode);
}
}
}
snd_use_case_set(handle->ucMgr, "_disdev", curTxUCMDevice);
}
}
ALOGD("%s,rxDev:%s, txDev:%s, curRxDev:%s, curTxDev:%s\n", __FUNCTION__, rxDevice, txDevice, curRxUCMDevice, curTxUCMDevice);
if (rxDevice != NULL) {
snd_use_case_set(handle->ucMgr, "_enadev", rxDevice);
strlcpy(curRxUCMDevice, rxDevice, sizeof(curRxUCMDevice));
#ifdef QCOM_FM_ENABLED
if (devices & AudioSystem::DEVICE_OUT_FM)
s_set_fm_vol(fmVolume);
#endif
}
if (txDevice != NULL) {
snd_use_case_set(handle->ucMgr, "_enadev", txDevice);
strlcpy(curTxUCMDevice, txDevice, sizeof(curTxUCMDevice));
}
for(ALSAUseCaseList::iterator it = mUseCaseList.begin(); it != mUseCaseList.end(); ++it) {
ALOGD("Route use case %s\n", it->useCase);
if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
strlen(SND_USE_CASE_VERB_INACTIVE))) && (!strncmp(use_case, it->useCase, MAX_UC_LEN))) {
snd_use_case_set(handle->ucMgr, "_verb", it->useCase);
} else {
snd_use_case_set(handle->ucMgr, "_enamod", it->useCase);
}
}
if (!mUseCaseList.empty())
mUseCaseList.clear();
if (use_case != NULL) {
free(use_case);
use_case = NULL;
}
ALOGD("switchDevice: curTxUCMDevivce %s curRxDevDevice %s", curTxUCMDevice, curRxUCMDevice);
if (platform_is_Fusion3() && (inCallDevSwitch == true)) {
/* get tx acdb id */
memset(&ident,0,sizeof(ident));
strlcpy(ident, "ACDBID/", sizeof(ident));
strlcat(ident, curTxUCMDevice, sizeof(ident));
tx_dev_id = snd_use_case_get(handle->ucMgr, ident, NULL);
/* get rx acdb id */
memset(&ident,0,sizeof(ident));
strlcpy(ident, "ACDBID/", sizeof(ident));
strlcat(ident, curRxUCMDevice, sizeof(ident));
rx_dev_id = snd_use_case_get(handle->ucMgr, ident, NULL);
if (((rx_dev_id == DEVICE_SPEAKER_MONO_RX_ACDB_ID ) || (rx_dev_id == DEVICE_SPEAKER_STEREO_RX_ACDB_ID ))
&& tx_dev_id == DEVICE_HANDSET_TX_ACDB_ID) {
tx_dev_id = DEVICE_SPEAKER_TX_ACDB_ID;
}
#ifdef QCOM_CSDCLIENT_ENABLED
ALOGV("rx_dev_id=%d, tx_dev_id=%d\n", rx_dev_id, tx_dev_id);
if (csd_enable_device == NULL) {
ALOGE("dlsym:Error:%s Loading csd_client_enable_device", dlerror());
} else {
err = csd_enable_device(rx_dev_id, tx_dev_id, mDevSettingsFlag);
if (err < 0)
{
ALOGE("csd_client_disable_device failed, error %d", err);
}
}
#endif
}
if (rxDevice != NULL) {
free(rxDevice);
rxDevice = NULL;
}
if (txDevice != NULL) {
free(txDevice);
txDevice = NULL;
}
}
// ----------------------------------------------------------------------------
static status_t s_init(alsa_device_t *module, ALSAHandleList &list)
{
ALOGV("s_init: Initializing devices for ALSA module");
list.clear();
return NO_ERROR;
}
static status_t s_open(alsa_handle_t *handle)
{
char *devName;
unsigned flags = 0;
int err = NO_ERROR;
if(handle->devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
err = setHDMIChannelCount();
if(err != OK) {
ALOGE("setHDMIChannelCount err = %d", err);
return err;
}
}
/* No need to call s_close for LPA as pcm device open and close is handled by LPAPlayer in stagefright */
if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) || (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA))
||(!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) || (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))) {
ALOGV("s_open: Opening LPA /Tunnel playback");
return NO_ERROR;
}
s_close(handle);
ALOGV("s_open: handle %p", handle);
// ASoC multicomponent requires a valid path (frontend/backend) for
// the device to be opened
// The PCM stream is opened in blocking mode, per ALSA defaults. The
// AudioFlinger seems to assume blocking mode too, so asynchronous mode
// should not be used.
if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
(!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
(!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
(!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))) {
ALOGV("LPA/tunnel use case");
flags |= PCM_MMAP;
flags |= DEBUG_ON;
} else if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI)) ||
(!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI2)) ||
(!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) ||
(!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)) ||
(!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC2)) ||
(!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC))) {
ALOGV("Music case");
flags = PCM_OUT;
} else {
flags = PCM_IN;
}
if (handle->channels == 1) {
flags |= PCM_MONO;
}
else if (handle->channels == 4 ) {
flags |= PCM_QUAD;
} else if (handle->channels == 6 ) {
#ifdef QCOM_SSR_ENABLED
if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
|| !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
flags |= PCM_QUAD;
} else {
flags |= PCM_5POINT1;
}
#else
flags |= PCM_5POINT1;
#endif
}
else {
flags |= PCM_STEREO;
}
if (deviceName(handle, flags, &devName) < 0) {
ALOGE("Failed to get pcm device node: %s", devName);
return NO_INIT;
}
if (devName != NULL) {
handle->handle = pcm_open(flags, (char*)devName);
} else {
ALOGE("Failed to get pcm device node");
return NO_INIT;
}
if (!handle->handle) {
ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
free(devName);
return NO_INIT;
}
handle->handle->flags = flags;
err = setHardwareParams(handle);
if (err == NO_ERROR) {
err = setSoftwareParams(handle);
}
if(err != NO_ERROR) {
ALOGE("Set HW/SW params failed: Closing the pcm stream");
s_standby(handle);
}
free(devName);
return NO_ERROR;
}
static status_t s_start_voip_call(alsa_handle_t *handle)
{
char* devName;
char* devName1;
unsigned flags = 0;
int err = NO_ERROR;
uint8_t voc_pkt[VOIP_BUFFER_MAX_SIZE];
s_close(handle);
flags = PCM_OUT;
flags |= PCM_MONO;
ALOGV("s_open:s_start_voip_call handle %p", handle);
if (deviceName(handle, flags, &devName) < 0) {
ALOGE("Failed to get pcm device node");
return NO_INIT;
}
if (devName != NULL) {
handle->handle = pcm_open(flags, (char*)devName);
} else {
ALOGE("Failed to get pcm device node");
return NO_INIT;
}
if (!handle->handle) {
free(devName);
ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
return NO_INIT;
}
if (!pcm_ready(handle->handle)) {
ALOGE(" pcm ready failed");
}
handle->handle->flags = flags;
err = setHardwareParams(handle);
if (err == NO_ERROR) {
err = setSoftwareParams(handle);
}
err = pcm_prepare(handle->handle);
if(err != NO_ERROR) {
ALOGE("DEVICE_OUT_DIRECTOUTPUT: pcm_prepare failed");
}
/* first write required start dsp */
memset(&voc_pkt,0,sizeof(voc_pkt));
pcm_write(handle->handle,&voc_pkt,handle->handle->period_size);
handle->rxHandle = handle->handle;
free(devName);
ALOGV("s_open: DEVICE_IN_COMMUNICATION ");
flags = PCM_IN;
flags |= PCM_MONO;
handle->handle = 0;
if (deviceName(handle, flags, &devName1) < 0) {
ALOGE("Failed to get pcm device node");
return NO_INIT;
}
if (devName != NULL) {
handle->handle = pcm_open(flags, (char*)devName1);
} else {
ALOGE("Failed to get pcm device node");
return NO_INIT;
}
if (!handle->handle) {
free(devName);
ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
return NO_INIT;
}
if (!pcm_ready(handle->handle)) {
ALOGE(" pcm ready in failed");
}
handle->handle->flags = flags;
err = setHardwareParams(handle);
if (err == NO_ERROR) {
err = setSoftwareParams(handle);
}
err = pcm_prepare(handle->handle);
if(err != NO_ERROR) {
ALOGE("DEVICE_IN_COMMUNICATION: pcm_prepare failed");
}
/* first read required start dsp */
memset(&voc_pkt,0,sizeof(voc_pkt));
pcm_read(handle->handle,&voc_pkt,handle->handle->period_size);
return NO_ERROR;
}
static status_t s_start_voice_call(alsa_handle_t *handle)
{
char* devName;
unsigned flags = 0;
int err = NO_ERROR;
ALOGV("s_start_voice_call: handle %p", handle);
// ASoC multicomponent requires a valid path (frontend/backend) for
// the device to be opened
flags = PCM_OUT | PCM_MONO;
if (deviceName(handle, flags, &devName) < 0) {
ALOGE("Failed to get pcm device node");
return NO_INIT;
}
if (devName != NULL) {
handle->handle = pcm_open(flags, (char*)devName);
} else {
ALOGE("Failed to get pcm device node");
return NO_INIT;
}
if (!handle->handle) {
ALOGE("s_start_voicecall: could not open PCM device");
goto Error;
}
handle->handle->flags = flags;
err = setHardwareParams(handle);
if(err != NO_ERROR) {
ALOGE("s_start_voice_call: setHardwareParams failed");
goto Error;
}
err = setSoftwareParams(handle);
if(err != NO_ERROR) {
ALOGE("s_start_voice_call: setSoftwareParams failed");
goto Error;
}
err = pcm_prepare(handle->handle);
if(err != NO_ERROR) {
ALOGE("s_start_voice_call: pcm_prepare failed");
goto Error;
}
if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
ALOGE("s_start_voice_call:SNDRV_PCM_IOCTL_START failed\n");
goto Error;
}
// Store the PCM playback device pointer in rxHandle
handle->rxHandle = handle->handle;
free(devName);
// Open PCM capture device
flags = PCM_IN | PCM_MONO;
if (deviceName(handle, flags, &devName) < 0) {
ALOGE("Failed to get pcm device node");
goto Error;
}
if (devName != NULL) {
handle->handle = pcm_open(flags, (char*)devName);
} else {
ALOGE("Failed to get pcm device node");
return NO_INIT;
}
if (!handle->handle) {
free(devName);
goto Error;
}
handle->handle->flags = flags;
err = setHardwareParams(handle);
if(err != NO_ERROR) {
ALOGE("s_start_voice_call: setHardwareParams failed");
goto Error;
}
err = setSoftwareParams(handle);
if(err != NO_ERROR) {
ALOGE("s_start_voice_call: setSoftwareParams failed");
goto Error;
}
err = pcm_prepare(handle->handle);
if(err != NO_ERROR) {
ALOGE("s_start_voice_call: pcm_prepare failed");
goto Error;
}
if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
ALOGE("s_start_voice_call:SNDRV_PCM_IOCTL_START failed\n");
goto Error;
}
if (platform_is_Fusion3()) {
#ifdef QCOM_CSDCLIENT_ENABLED
if (csd_start_voice == NULL) {
ALOGE("dlsym:Error:%s Loading csd_client_start_voice", dlerror());
} else {
err = csd_start_voice();
if (err < 0){
ALOGE("s_start_voice_call: csd_client error %d\n", err);
goto Error;
}
}
#endif
}
free(devName);
return NO_ERROR;
Error:
ALOGE("s_start_voice_call: Failed to initialize ALSA device '%s'", devName);
free(devName);
s_close(handle);
return NO_INIT;
}
static status_t s_start_fm(alsa_handle_t *handle)
{
char *devName;
unsigned flags = 0;
int err = NO_ERROR;
ALOGV("s_start_fm: handle %p", handle);
// ASoC multicomponent requires a valid path (frontend/backend) for
// the device to be opened
flags = PCM_OUT | PCM_STEREO;
if (deviceName(handle, flags, &devName) < 0) {
ALOGE("Failed to get pcm device node");
goto Error;
}
if (devName != NULL) {
handle->handle = pcm_open(flags, (char*)devName);
} else {
ALOGE("Failed to get pcm device node");
return NO_INIT;
}
if (!handle->handle) {
ALOGE("s_start_fm: could not open PCM device");
goto Error;
}
handle->handle->flags = flags;
err = setHardwareParams(handle);
if(err != NO_ERROR) {
ALOGE("s_start_fm: setHardwareParams failed");
goto Error;
}
err = setSoftwareParams(handle);
if(err != NO_ERROR) {
ALOGE("s_start_fm: setSoftwareParams failed");
goto Error;
}
err = pcm_prepare(handle->handle);
if(err != NO_ERROR) {
ALOGE("s_start_fm: setSoftwareParams failed");
goto Error;
}
if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
ALOGE("s_start_fm: SNDRV_PCM_IOCTL_START failed\n");
goto Error;
}
// Store the PCM playback device pointer in rxHandle
handle->rxHandle = handle->handle;
free(devName);
// Open PCM capture device
flags = PCM_IN | PCM_STEREO;
if (deviceName(handle, flags, &devName) < 0) {
ALOGE("Failed to get pcm device node");
goto Error;
}
if (devName != NULL) {
handle->handle = pcm_open(flags, (char*)devName);
} else {
ALOGE("Failed to get pcm device node");
return NO_INIT;
}
if (!handle->handle) {
goto Error;
}
handle->handle->flags = flags;
err = setHardwareParams(handle);
if(err != NO_ERROR) {
ALOGE("s_start_fm: setHardwareParams failed");
goto Error;
}
err = setSoftwareParams(handle);
if(err != NO_ERROR) {
ALOGE("s_start_fm: setSoftwareParams failed");
goto Error;
}
err = pcm_prepare(handle->handle);
if(err != NO_ERROR) {
ALOGE("s_start_fm: pcm_prepare failed");
goto Error;
}
if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
ALOGE("s_start_fm: SNDRV_PCM_IOCTL_START failed\n");
goto Error;
}
s_set_fm_vol(fmVolume);
free(devName);
return NO_ERROR;
Error:
free(devName);
s_close(handle);
return NO_INIT;
}
static status_t s_set_fm_vol(int value)
{
status_t err = NO_ERROR;
ALSAControl control("/dev/snd/controlC0");
control.set("Internal FM RX Volume",value,0);
fmVolume = value;
return err;
}
static status_t s_set_lpa_vol(int value)
{
status_t err = NO_ERROR;
ALSAControl control("/dev/snd/controlC0");
control.set("LPA RX Volume",value,0);
return err;
}
static status_t s_start(alsa_handle_t *handle)
{
status_t err = NO_ERROR;
if(!handle->handle) {
ALOGE("No active PCM driver to start");
return err;
}
err = pcm_prepare(handle->handle);
return err;
}
static status_t s_close(alsa_handle_t *handle)
{
int ret;
status_t err = NO_ERROR;
struct pcm *h = handle->rxHandle;
handle->rxHandle = 0;
ALOGV("s_close: handle %p h %p", handle, h);
if (h) {
if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_VOICECALL) ||
!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_VOICE)) &&
platform_is_Fusion3()) {
#ifdef QCOM_CSDCLIENT_ENABLED
if (csd_stop_voice == NULL) {
ALOGE("dlsym:Error:%s Loading csd_client_disable_device", dlerror());
} else {
err = csd_stop_voice();
if (err < 0) {
ALOGE("s_close: csd_client error %d\n", err);
}
}
#endif
}
ALOGV("s_close rxHandle\n");
err = pcm_close(h);
if(err != NO_ERROR) {
ALOGE("s_close: pcm_close failed for rxHandle with err %d", err);
}
}
h = handle->handle;
handle->handle = 0;
if (h) {
ALOGV("s_close handle h %p\n", h);
err = pcm_close(h);
if(err != NO_ERROR) {
ALOGE("s_close: pcm_close failed for handle with err %d", err);
}
disableDevice(handle);
} else if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
(!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
(!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
(!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))){
disableDevice(handle);
}
return err;
}
/*
this is same as s_close, but don't discard
the device/mode info. This way we can still
close the device, hit idle and power-save, reopen the pcm
for the same device/mode after resuming
*/
static status_t s_standby(alsa_handle_t *handle)
{
int ret;
status_t err = NO_ERROR;
struct pcm *h = handle->rxHandle;
handle->rxHandle = 0;
ALOGV("s_standby: handle %p h %p", handle, h);
if (h) {
ALOGD("s_standby rxHandle\n");
err = pcm_close(h);
if(err != NO_ERROR) {
ALOGE("s_standby: pcm_close failed for rxHandle with err %d", err);
}
}
h = handle->handle;
handle->handle = 0;
if (h) {
ALOGV("s_standby handle h %p\n", h);
err = pcm_close(h);
if(err != NO_ERROR) {
ALOGE("s_standby: pcm_close failed for handle with err %d", err);
}
disableDevice(handle);
} else if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
(!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
(!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
(!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))) {
disableDevice(handle);
}
return err;
}
static status_t s_route(alsa_handle_t *handle, uint32_t devices, int mode)
{
status_t status = NO_ERROR;
ALOGD("s_route: devices 0x%x in mode %d", devices, mode);
callMode = mode;
switchDevice(handle, devices, mode);
return status;
}
int getUseCaseType(const char *useCase)
{
ALOGD("use case is %s\n", useCase);
if (!strncmp(useCase, SND_USE_CASE_VERB_HIFI,
MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI)) ||
!strncmp(useCase, SND_USE_CASE_VERB_HIFI2,
MAX_LEN(useCase, SND_USE_CASE_VERB_HIFI2)) ||
!strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC,
MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) ||
!strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER,
MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
!strncmp(useCase, SND_USE_CASE_VERB_HIFI_TUNNEL,
MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
!strncmp(useCase, SND_USE_CASE_VERB_HIFI2,
MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI2)) ||
!strncmp(useCase, SND_USE_CASE_VERB_DIGITAL_RADIO,
MAX_LEN(useCase,SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
!strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC,
MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_MUSIC)) ||
!strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC2,
MAX_LEN(useCase, SND_USE_CASE_MOD_PLAY_MUSIC2)) ||
!strncmp(useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC,
MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)) ||
!strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC2,
MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_MUSIC2)) ||
!strncmp(useCase, SND_USE_CASE_MOD_PLAY_LPA,
MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_LPA)) ||
!strncmp(useCase, SND_USE_CASE_MOD_PLAY_TUNNEL,
MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_TUNNEL)) ||
!strncmp(useCase, SND_USE_CASE_MOD_PLAY_FM,
MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_FM))) {
return USECASE_TYPE_RX;
} else if (!strncmp(useCase, SND_USE_CASE_VERB_HIFI_REC,
MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_REC)) ||
!strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC,
MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC)) ||
!strncmp(useCase, SND_USE_CASE_VERB_FM_REC,
MAX_LEN(useCase,SND_USE_CASE_VERB_FM_REC)) ||
!strncmp(useCase, SND_USE_CASE_VERB_FM_A2DP_REC,
MAX_LEN(useCase,SND_USE_CASE_VERB_FM_A2DP_REC)) ||
!strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC,
MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_MUSIC)) ||
!strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC,
MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC)) ||
!strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_FM,
MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_FM)) ||
!strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM,
MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_A2DP_FM))) {
return USECASE_TYPE_TX;
} else if (!strncmp(useCase, SND_USE_CASE_VERB_VOICECALL,
MAX_LEN(useCase,SND_USE_CASE_VERB_VOICECALL)) ||
!strncmp(useCase, SND_USE_CASE_VERB_IP_VOICECALL,
MAX_LEN(useCase,SND_USE_CASE_VERB_IP_VOICECALL)) ||
!strncmp(useCase, SND_USE_CASE_VERB_DL_REC,
MAX_LEN(useCase,SND_USE_CASE_VERB_DL_REC)) ||
!strncmp(useCase, SND_USE_CASE_VERB_UL_DL_REC,
MAX_LEN(useCase,SND_USE_CASE_VERB_UL_DL_REC)) ||
!strncmp(useCase, SND_USE_CASE_VERB_INCALL_REC,
MAX_LEN(useCase,SND_USE_CASE_VERB_INCALL_REC)) ||
!strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOICE,
MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_VOICE)) ||
!strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOIP,
MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_VOIP)) ||
!strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_DL,
MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_VOICE_DL)) ||
!strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL,
MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL)) ||
!strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
MAX_LEN(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE)) ||
!strncmp(useCase, SND_USE_CASE_VERB_VOLTE,
MAX_LEN(useCase,SND_USE_CASE_VERB_VOLTE)) ||
!strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
MAX_LEN(useCase, SND_USE_CASE_MOD_PLAY_VOLTE))) {
return (USECASE_TYPE_RX | USECASE_TYPE_TX);
} else {
ALOGE("unknown use case %s\n", useCase);
return 0;
}
}
static void disableDevice(alsa_handle_t *handle)
{
unsigned usecase_type = 0;
int i, mods_size;
char *useCase;
const char **mods_list;
snd_use_case_get(handle->ucMgr, "_verb", (const char **)&useCase);
if (useCase != NULL) {
if (!strncmp(useCase, handle->useCase, MAX_UC_LEN)) {
snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
} else {
snd_use_case_set(handle->ucMgr, "_dismod", handle->useCase);
}
free(useCase);
snd_use_case_get(handle->ucMgr, "_verb", (const char **)&useCase);
if (strncmp(useCase, SND_USE_CASE_VERB_INACTIVE,
strlen(SND_USE_CASE_VERB_INACTIVE)))
usecase_type |= getUseCaseType(useCase);
mods_size = snd_use_case_get_list(handle->ucMgr, "_enamods", &mods_list);
ALOGV("Number of modifiers %d\n", mods_size);
if (mods_size) {
for(i = 0; i < mods_size; i++) {
ALOGV("index %d modifier %s\n", i, mods_list[i]);
usecase_type |= getUseCaseType(mods_list[i]);
}
}
ALOGV("usecase_type is %d\n", usecase_type);
if (!(usecase_type & USECASE_TYPE_TX) && (strncmp(curTxUCMDevice, "None", 4)))
snd_use_case_set(handle->ucMgr, "_disdev", curTxUCMDevice);
if (!(usecase_type & USECASE_TYPE_RX) && (strncmp(curRxUCMDevice, "None", 4)))
snd_use_case_set(handle->ucMgr, "_disdev", curRxUCMDevice);
} else {
ALOGE("Invalid state, no valid use case found to disable");
}
free(useCase);
}
char *getUCMDevice(uint32_t devices, int input, char *rxDevice)
{
bool is_tmus = s_is_tmus();
if (!input) {
if (!(mDevSettingsFlag & TTY_OFF) &&
(callMode == AudioSystem::MODE_IN_CALL) &&
((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
(devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE))) {
#ifdef QCOM_ANC_HEADSET_ENABLED
||
(devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
(devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE))) {
#endif
if (mDevSettingsFlag & TTY_VCO) {
return strdup(SND_USE_CASE_DEV_TTY_HEADSET_RX);
} else if (mDevSettingsFlag & TTY_FULL) {
return strdup(SND_USE_CASE_DEV_TTY_FULL_RX);
} else if (mDevSettingsFlag & TTY_HCO) {
return strdup(SND_USE_CASE_DEV_TTY_HANDSET_RX); /* HANDSET RX */
}
}else if ((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET) ||
(devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)) {
return strdup(SND_USE_CASE_DEV_PROXY_RX); /* PROXY RX */
} else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
(devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE))) {
if (mDevSettingsFlag & ANC_FLAG) {
return strdup(SND_USE_CASE_DEV_SPEAKER_ANC_HEADSET); /* COMBO SPEAKER+ANC HEADSET RX */
} else {
return strdup(SND_USE_CASE_DEV_SPEAKER_HEADSET); /* COMBO SPEAKER+HEADSET RX */
}
} else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
((devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL))) {
return strdup(SND_USE_CASE_DEV_HDMI_SPEAKER);
#ifdef QCOM_ANC_HEADSET_ENABLED
} else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
(devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE))) {
return strdup(SND_USE_CASE_DEV_SPEAKER_ANC_HEADSET); /* COMBO SPEAKER+ANC HEADSET RX */
} else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
(devices & AudioSystem::DEVICE_OUT_FM_TX)) {
return strdup(SND_USE_CASE_DEV_SPEAKER_FM_TX); /* COMBO SPEAKER+FM_TX RX */
#endif
} else if (devices & AudioSystem::DEVICE_OUT_EARPIECE) {
if (callMode == AudioSystem::MODE_IN_CALL) {
if(is_tmus)
return strdup(SND_USE_CASE_DEV_VOC_EARPIECE_TMUS); /* Voice HANDSET RX for TMUS */
else
return strdup(SND_USE_CASE_DEV_VOC_EARPIECE); /* Voice HANDSET RX */
} else
return strdup(SND_USE_CASE_DEV_EARPIECE); /* HANDSET RX */
} else if (devices & AudioSystem::DEVICE_OUT_SPEAKER) {
if (callMode == AudioSystem::MODE_IN_CALL) {
return strdup(SND_USE_CASE_DEV_VOC_SPEAKER); /* Voice SPEAKER RX */
} else
return strdup(SND_USE_CASE_DEV_SPEAKER); /* SPEAKER RX */
} else if ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
(devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) {
if (mDevSettingsFlag & ANC_FLAG) {
if (callMode == AudioSystem::MODE_IN_CALL) {
return strdup(SND_USE_CASE_DEV_VOC_ANC_HEADSET); /* Voice ANC HEADSET RX */
} else
return strdup(SND_USE_CASE_DEV_ANC_HEADSET); /* ANC HEADSET RX */
} else {
if (callMode == AudioSystem::MODE_IN_CALL) {
return strdup(SND_USE_CASE_DEV_VOC_HEADPHONE); /* Voice HEADSET RX */
} else
return strdup(SND_USE_CASE_DEV_HEADPHONES); /* HEADSET RX */
}
#ifdef QCOM_ANC_HEADSET_ENABLED
} else if ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
(devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE)) {
if (callMode == AudioSystem::MODE_IN_CALL) {
return strdup(SND_USE_CASE_DEV_VOC_ANC_HEADSET); /* Voice ANC HEADSET RX */
} else
return strdup(SND_USE_CASE_DEV_ANC_HEADSET); /* ANC HEADSET RX */
#endif
} else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO) ||
(devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET) ||
(devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT)) {
if (btsco_samplerate == BTSCO_RATE_16KHZ)
return strdup(SND_USE_CASE_DEV_BTSCO_WB_RX); /* BTSCO RX*/
else
return strdup(SND_USE_CASE_DEV_BTSCO_NB_RX); /* BTSCO RX*/
} else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP) ||
(devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES) ||
#ifdef QCOM_VOIP_ENABLED
(devices & AudioSystem::DEVICE_OUT_DIRECTOUTPUT) ||
#endif
(devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) {
/* Nothing to be done, use current active device */
if (strncmp(curRxUCMDevice, "None", 4)) {
return strdup(curRxUCMDevice);
}
} else if (devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
return strdup(SND_USE_CASE_DEV_HDMI); /* HDMI RX */
#ifdef QCOM_PROXY_DEVICE_ENABLED
} else if (devices & AudioSystem::DEVICE_OUT_PROXY) {
return strdup(SND_USE_CASE_DEV_PROXY_RX); /* PROXY RX */
#endif
#ifdef QCOM_FM_TX_ENABLED
} else if (devices & AudioSystem::DEVICE_OUT_FM_TX) {
return strdup(SND_USE_CASE_DEV_FM_TX); /* FM Tx */
#endif
} else if (devices & AudioSystem::DEVICE_OUT_DEFAULT) {
if (callMode == AudioSystem::MODE_IN_CALL) {
return strdup(SND_USE_CASE_DEV_VOC_SPEAKER); /* Voice SPEAKER RX */
} else
return strdup(SND_USE_CASE_DEV_SPEAKER); /* SPEAKER RX */
} else {
ALOGD("No valid output device: %u", devices);
}
} else {
if (!(mDevSettingsFlag & TTY_OFF) &&
(callMode == AudioSystem::MODE_IN_CALL) &&
((devices & AudioSystem::DEVICE_IN_WIRED_HEADSET)
#ifdef QCOM_ANC_HEADSET_ENABLED
|| (devices & AudioSystem::DEVICE_IN_ANC_HEADSET)
#endif
)) {
if (mDevSettingsFlag & TTY_HCO) {
return strdup(SND_USE_CASE_DEV_TTY_HEADSET_TX);
} else if (mDevSettingsFlag & TTY_FULL) {
return strdup(SND_USE_CASE_DEV_TTY_FULL_TX);
} else if (mDevSettingsFlag & TTY_VCO) {
if (!strncmp(mic_type, "analog", 6)) {
return strdup(SND_USE_CASE_DEV_TTY_HANDSET_ANALOG_TX);
} else {
return strdup(SND_USE_CASE_DEV_TTY_HANDSET_TX);
}
}
} else if (devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) {
if (!strncmp(mic_type, "analog", 6)) {
return strdup(SND_USE_CASE_DEV_HANDSET); /* HANDSET TX */
} else {
if (mDevSettingsFlag & DMIC_FLAG) {
if(callMode == AudioSystem::MODE_IN_CALL) {
#ifdef USES_FLUENCE_INCALL
if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
if(is_tmus)
return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE_TMUS); /* DUALMIC EF TX */
else
return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
} else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
} else {
return strdup(SND_USE_CASE_DEV_HANDSET); /* BUILTIN-MIC TX */
}
#endif
}
if (((rxDevice != NULL) &&
!strncmp(rxDevice, SND_USE_CASE_DEV_SPEAKER,
(strlen(SND_USE_CASE_DEV_SPEAKER)+1))) ||
!strncmp(curRxUCMDevice, SND_USE_CASE_DEV_SPEAKER,
(strlen(SND_USE_CASE_DEV_SPEAKER)+1))) {
if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
if (input_source == AUDIO_SOURCE_VOICE_RECOGNITION) {
// TODO: check if different ACDB settings are needed when speaker is enabled
return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE_VREC);
} else {
return strdup(SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_ENDFIRE);
}
} else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
if (input_source == AUDIO_SOURCE_VOICE_RECOGNITION) {
return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE_VREC);
} else {
return strdup(SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_BROADSIDE);
}
}
} else {
if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
if (input_source == AUDIO_SOURCE_VOICE_RECOGNITION) {
return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE_VREC);
} else {
return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE);
}
} else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
if (input_source == AUDIO_SOURCE_VOICE_RECOGNITION) {
return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE_VREC);
} else {
return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE);
}
}
}
} else if (mDevSettingsFlag & QMIC_FLAG){
return strdup(SND_USE_CASE_DEV_QUAD_MIC);
}
#ifdef QCOM_SSR_ENABLED
else if (mDevSettingsFlag & SSRQMIC_FLAG){
ALOGV("return SSRQMIC_FLAG: 0x%x devices:0x%x",mDevSettingsFlag,devices);
// Mapping for quad mic input device.
return strdup(SND_USE_CASE_DEV_SSR_QUAD_MIC); /* SSR Quad MIC */
}
#endif
#ifdef SEPERATED_AUDIO_INPUT
if(input_source == AUDIO_SOURCE_VOICE_RECOGNITION) {
return strdup(SND_USE_CASE_DEV_VOICE_RECOGNITION ); /* VOICE RECOGNITION TX */
}
#endif
else {
return strdup(SND_USE_CASE_DEV_HANDSET); /* BUILTIN-MIC TX */
}
}
} else if (devices & AudioSystem::DEVICE_IN_AUX_DIGITAL) {
return strdup(SND_USE_CASE_DEV_HDMI_TX); /* HDMI TX */
#ifdef QCOM_ANC_HEADSET_ENABLED
} else if (devices & AudioSystem::DEVICE_IN_ANC_HEADSET) {
return strdup(SND_USE_CASE_DEV_HEADSET); /* HEADSET TX */
#endif
} else if (devices & AudioSystem::DEVICE_IN_WIRED_HEADSET) {
if (callMode == AudioSystem::MODE_IN_CALL) {
return strdup(SND_USE_CASE_DEV_VOC_HEADSET); /* Voice HEADSET TX */
} else
return strdup(SND_USE_CASE_DEV_HEADSET); /* HEADSET TX */
} else if (devices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
if (btsco_samplerate == BTSCO_RATE_16KHZ)
return strdup(SND_USE_CASE_DEV_BTSCO_WB_TX); /* BTSCO TX*/
else
return strdup(SND_USE_CASE_DEV_BTSCO_NB_TX); /* BTSCO TX*/
#ifdef QCOM_USBAUDIO_ENABLED
} else if ((devices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET) ||
(devices & AudioSystem::DEVICE_IN_PROXY)) {
return strdup(SND_USE_CASE_DEV_PROXY_TX); /* PROXY TX */
#endif
} else if ((devices & AudioSystem::DEVICE_IN_COMMUNICATION) ||
(devices & AudioSystem::DEVICE_IN_VOICE_CALL)) {
/* Nothing to be done, use current active device */
if (strncmp(curTxUCMDevice, "None", 4)) {
return strdup(curTxUCMDevice);
}
#ifdef QCOM_FM_ENABLED
} else if ((devices & AudioSystem::DEVICE_IN_FM_RX) ||
(devices & AudioSystem::DEVICE_IN_FM_RX_A2DP)) {
/* Nothing to be done, use current tx device or set dummy device */
if (strncmp(curTxUCMDevice, "None", 4)) {
return strdup(curTxUCMDevice);
} else {
return strdup(SND_USE_CASE_DEV_DUMMY_TX);
}
#endif
} else if ((devices & AudioSystem::DEVICE_IN_AMBIENT) ||
(devices & AudioSystem::DEVICE_IN_BACK_MIC)) {
ALOGI("No proper mapping found with UCM device list, setting default");
if (!strncmp(mic_type, "analog", 6)) {
return strdup(SND_USE_CASE_DEV_HANDSET); /* HANDSET TX */
} else {
if (callMode == AudioSystem::MODE_IN_CALL) {
return strdup(SND_USE_CASE_DEV_VOC_LINE); /* Voice BUILTIN-MIC TX */
#ifdef SEPERATED_AUDIO_INPUT
} else if(input_source == AUDIO_SOURCE_CAMCORDER) {
return strdup(SND_USE_CASE_DEV_CAMCORDER_TX ); /* CAMCORDER TX */
#endif
} else
return strdup(SND_USE_CASE_DEV_LINE); /* BUILTIN-MIC TX */
}
} else {
ALOGD("No valid input device: %u", devices);
}
}
return NULL;
}
void s_set_voice_volume(int vol)
{
int err = 0;
ALOGV("s_set_voice_volume: volume %d", vol);
ALSAControl control("/dev/snd/controlC0");
control.set("Voice Rx Volume", vol, 0);
if (platform_is_Fusion3()) {
#ifdef QCOM_CSDCLIENT_ENABLED
if (csd_volume == NULL) {
ALOGE("dlsym:Error:%s Loading csd_client_volume", dlerror());
} else {
err = csd_volume(vol);
if (err < 0) {
ALOGE("s_set_voice_volume: csd_client error %d", err);
}
}
#endif
}
}
void s_set_volte_volume(int vol)
{
ALOGV("s_set_volte_volume: volume %d", vol);
ALSAControl control("/dev/snd/controlC0");
control.set("VoLTE Rx Volume", vol, 0);
}
void s_set_voip_volume(int vol)
{
ALOGV("s_set_voip_volume: volume %d", vol);
ALSAControl control("/dev/snd/controlC0");
control.set("Voip Rx Volume", vol, 0);
}
void s_set_mic_mute(int state)
{
int err = 0;
ALOGV("s_set_mic_mute: state %d", state);
ALSAControl control("/dev/snd/controlC0");
control.set("Voice Tx Mute", state, 0);
if (platform_is_Fusion3()) {
#ifdef QCOM_CSDCLIENT_ENABLED
if (csd_mic_mute == NULL) {
ALOGE("dlsym:Error:%s Loading csd_mic_mute", dlerror());
} else {
err=csd_mic_mute(state);
if (err < 0) {
ALOGE("s_set_mic_mute: csd_client error %d", err);
}
}
#endif
}
}
void s_set_volte_mic_mute(int state)
{
ALOGV("s_set_volte_mic_mute: state %d", state);
ALSAControl control("/dev/snd/controlC0");
control.set("VoLTE Tx Mute", state, 0);
}
void s_set_voip_mic_mute(int state)
{
ALOGV("s_set_voip_mic_mute: state %d", state);
ALSAControl control("/dev/snd/controlC0");
control.set("Voip Tx Mute", state, 0);
}
void s_set_voip_config(int mode, int rate)
{
ALOGV("s_set_voip_config: mode %d,rate %d", mode, rate);
ALSAControl control("/dev/snd/controlC0");
char** setValues;
setValues = (char**)malloc(2*sizeof(char*));
if (setValues == NULL) {
return;
}
setValues[0] = (char*)malloc(4*sizeof(char));
if (setValues[0] == NULL) {
free(setValues);
return;
}
setValues[1] = (char*)malloc(8*sizeof(char));
if (setValues[1] == NULL) {
free(setValues);
free(setValues[0]);
return;
}
sprintf(setValues[0], "%d",mode);
sprintf(setValues[1], "%d",rate);
control.setext("Voip Mode Rate Config", 2, setValues);
free(setValues[1]);
free(setValues[0]);
free(setValues);
return;
}
void s_set_btsco_rate(int rate)
{
btsco_samplerate = rate;
}
void s_enable_wide_voice(bool flag)
{
int err = 0;
ALOGV("s_enable_wide_voice: flag %d", flag);
ALSAControl control("/dev/snd/controlC0");
if(flag == true) {
control.set("Widevoice Enable", 1, 0);
} else {
control.set("Widevoice Enable", 0, 0);
}
if (platform_is_Fusion3()) {
#ifdef QCOM_CSDCLIENT_ENABLED
if (csd_wide_voice == NULL) {
ALOGE("dlsym:Error:%s Loading csd_wide_voice", dlerror());
} else {
err = csd_wide_voice(flag);
if (err < 0) {
ALOGE("enableWideVoice: csd_client_wide_voice error %d", err);
}
}
#endif
}
}
void s_set_voc_rec_mode(uint8_t mode)
{
ALOGV("s_set_voc_rec_mode: mode %d", mode);
ALSAControl control("/dev/snd/controlC0");
control.set("Incall Rec Mode", mode, 0);
}
void s_enable_fens(bool flag)
{
int err = 0;
ALOGV("s_enable_fens: flag %d", flag);
ALSAControl control("/dev/snd/controlC0");
if(flag == true) {
control.set("FENS Enable", 1, 0);
} else {
control.set("FENS Enable", 0, 0);
}
if (platform_is_Fusion3()) {
#ifdef QCOM_CSDCLIENT_ENABLED
if (csd_fens == NULL) {
ALOGE("dlsym:Error:%s Loading csd_fens", dlerror());
} else {
err = csd_fens(flag);
if (err < 0) {
ALOGE("s_enable_fens: csd_client error %d", err);
}
}
#endif
}
}
void s_enable_slow_talk(bool flag)
{
int err = 0;
ALOGV("s_enable_slow_talk: flag %d", flag);
ALSAControl control("/dev/snd/controlC0");
if(flag == true) {
control.set("Slowtalk Enable", 1, 0);
} else {
control.set("Slowtalk Enable", 0, 0);
}
if (platform_is_Fusion3()) {
#ifdef QCOM_CSDCLIENT_ENABLED
if (csd_slow_talk == NULL) {
ALOGE("dlsym:Error:%s Loading csd_slow_talk", dlerror());
} else {
err = csd_slow_talk(flag);
if (err < 0) {
ALOGE("s_enable_slow_talk: csd_client error %d", err);
}
}
#endif
}
}
void s_set_flags(uint32_t flags)
{
ALOGV("s_set_flags: flags %d", flags);
mDevSettingsFlag = flags;
}
static status_t s_set_compressed_vol(int value)
{
status_t err = NO_ERROR;
ALSAControl control("/dev/snd/controlC0");
control.set("COMPRESSED RX Volume",value,0);
return err;
}
#ifdef SEPERATED_AUDIO_INPUT
void s_setInput(int input)
{
input_source = input;
ALOGD("s_setInput() : input_source = %d",input_source);
}
#endif
#ifdef QCOM_CSDCLIENT_ENABLED
static void s_set_csd_handle(void* handle)
{
csd_handle = static_cast<void*>(handle);
ALOGI("%s csd_handle: %p", __func__, csd_handle);
csd_disable_device = (int (*)())::dlsym(csd_handle,"csd_client_disable_device");
csd_enable_device = (int (*)(int,int,uint32_t))::dlsym(csd_handle,"csd_client_enable_device");
csd_start_voice = (int (*)())::dlsym(csd_handle,"csd_client_start_voice");
csd_stop_voice = (int (*)())::dlsym(csd_handle,"csd_client_stop_voice");
csd_volume = (int (*)(int))::dlsym(csd_handle,"csd_client_volume");
csd_mic_mute = (int (*)(int))::dlsym(csd_handle,"csd_client_mic_mute");
csd_wide_voice = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_wide_voice");
csd_fens = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_fens");
csd_slow_talk = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_slow_talk");
}
#endif
static bool s_is_tmus()
{
char value[128];
bool ret = false;
if (mccmnc == 0) {
property_get("gsm.sim.operator.numeric",value,"0");
mccmnc = atoi(value);
}
ALOGD("%s: mnc_mcc : %d", __FUNCTION__, mccmnc);
switch(mccmnc)
{
//TMUS MCC(310), MNC(490, 260, 026)
case 310490:
case 310260:
case 310026:
ret = true;
break;
default:
ret = false;
break;
}
return ret;
}
}