📄 voice.cpp
字号:
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995-1999 Microsoft Corporation
Module Name:
voice.cpp
Abstract:
Notes:
--*/
//------------------------------------------------------------------------------
// Revision History
// Date Author Activity ID Activity Headline
// 2007-05-22 fengguisen CEDB200055583 add new code for cc of Cynthia850
// 2007-11-06 Wangxiaogang WM600020329 [important]一路通话,测试机打开扬声器且声音最低,依然可通话
// 2007-11-07 qinxuetao WM600021934 fix CMUT issues
//------------------------------------------------------------------------------
#include "precomp.h"
#if defined(WAVECOM_DRIVER) || defined(OEM1_DRIVER) || defined(OEM2_DRIVER)
#include <gsmradio.h>
#include "wavext.h"
#else
#define IOCTL_SPKR_ENABLE 0
#define IOCTL_SPKR_DISABLE 0
#endif
extern BOOL g_rgfCallsInProgress[RIL_MAX_TRACKED_CALL_ID];
extern RILCALLINFO g_rgfCallStates[RIL_MAX_TRACKED_CALL_ID];
extern BOOL g_rgfTCHAssigned[RIL_MAX_TRACKED_CALL_ID];
#ifdef OEM1_DRIVER
extern HANDLE g_hWavDev;
#endif
#if defined(OEM1_DRIVER) || defined(OEM2_DRIVER)
// This driver doesn't have a way to query current
// uplink and downlink volume, so we have to cache them.
DWORD g_dwCacheUplinkVolume;
DWORD g_dwCacheDownlinkVolume;
#endif
// display current MS mute state
BOOL g_fSetAudioMuting = FALSE;
//
//
//
static HRESULT ParseGetAudioGain(LPCSTR szRsp, void*& pBlob, UINT& cbBlob)
{
FUNCTION_TRACE(ParseGetAudioGain);
UINT nValue;
RILGAININFO* prgi = NULL;
HRESULT hr = S_OK;
pBlob = NULL;
cbBlob = 0;
prgi = (RILGAININFO*)AllocBlob(sizeof(RILGAININFO));
if (!prgi) {
hr = E_OUTOFMEMORY;
goto Error;
}
memset(prgi, 0x00, sizeof(RILGAININFO));
prgi->cbSize = sizeof(RILGAININFO);
#if defined(OEM1_DRIVER)
nValue = g_dwCacheDownlinkVolume;
#elif defined(OEM2_DRIVER)
nValue = (g_dwCacheDownlinkVolume * 255) / 100;
#else
// Parse "<prefix>+VGR: <gain><postfix>"
if (!ParseRspPrefix(szRsp, szRsp) ||
!MatchStringBeginning(szRsp, "+VGR: ", szRsp) ||
!ParseUInt(szRsp, TRUE, nValue, szRsp) ||
!ParseRspPostfix(szRsp, szRsp)) {
hr = E_FAIL;
goto Error;
}
#endif
#if defined(WAVECOM_DRIVER)
prgi->dwRxGain = ((255 - nValue) << 24) | ((255 - nValue) << 16) | ((255 - nValue) << 8) | (255 - nValue);
#else
prgi->dwRxGain = (nValue << 24) | (nValue << 16) | (nValue << 8) | (nValue);
#endif
prgi->dwParams |= RIL_PARAM_GI_RXGAIN;
#if defined(OEM1_DRIVER) || defined(OEM2_DRIVER)
nValue = g_dwCacheUplinkVolume; // For OEM1 and OEM2, only cache TxGain value in gsm driver, no AT command is sent out.
#else
// Parse "<prefix>+VGT: <gain><postfix>"
if (!ParseRspPrefix(szRsp, szRsp) ||
!MatchStringBeginning(szRsp, "+VGT: ", szRsp) ||
!ParseUInt(szRsp, TRUE, nValue, szRsp) ||
!ParseRspPostfix(szRsp, szRsp)) {
hr = E_FAIL;
goto Error;
}
#endif
#ifndef OEM2_DRIVER // OEM2 does not offer a transmit gain AT command by default
prgi->dwTxGain = (nValue << 24) | (nValue << 16) | (nValue << 8) | (nValue);
prgi->dwParams |= RIL_PARAM_GI_TXGAIN;
#endif
pBlob = (void*)prgi;
cbBlob = sizeof(RILGAININFO);
Error:
if (FAILED(hr)) {
FreeBlob(prgi);
}
return hr;
}
//
//
//
HRESULT RILDrv_GetAudioGain(DWORD dwParam)
{
FUNCTION_TRACE(RILDrv_GetAudioGain);
HRESULT hr = S_OK;
CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
if (!pHandle) {
hr = E_FAIL;
goto Error;
}
#if defined(OEM1_DRIVER) || defined(OEM2_DRIVER)
if (!QueueCmd(pHandle, "AT\r", CMDOPT_NONE, APIID_GETAUDIOGAIN, ParseGetAudioGain, NULL, hr)) {
#else
if (!QueueCmd(pHandle, "AT+VGR?;+VGT?\r", CMDOPT_NONE, APIID_GETAUDIOGAIN, ParseGetAudioGain, NULL, hr)) {
#endif
hr = E_FAIL;
goto Error;
}
Error:
return hr;
}
//
//
//
HRESULT RILDrv_SetAudioGain(DWORD dwParam, const RILGAININFO* lpGainInfo)
{
FUNCTION_TRACE(RILDrv_SetAudioGain);
char szCmd[MAX_PATH];
LPSTR szWalk = szCmd;
HRESULT hr = S_OK;
CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
if (!pHandle || !lpGainInfo) {
hr = E_FAIL;
goto Error;
}
if (!(lpGainInfo->dwParams & RIL_PARAM_GI_RXGAIN) && !(lpGainInfo->dwParams & RIL_PARAM_GI_TXGAIN)) {
hr = E_INVALIDARG;
goto Error;
}
(void)strncpyz(szWalk, "AT", MAX_PATH - (szWalk - szCmd));
szWalk = strchr(szWalk, '\0'); // NO_TYPO: 27
DEBUGCHK(NULL != szWalk);
if (lpGainInfo->dwParams & RIL_PARAM_GI_RXGAIN) {
#if defined(WAVECOM_DRIVER)
// Wavecom module specifies gain opposite GSM 07.07, C.2.4
(void)_snprintfz(szWalk, MAX_PATH - (szWalk - szCmd), "+VGR=%u", 255 - (lpGainInfo->dwRxGain >> 24));
#else // Standard GSM case, used for OEM1 and OEM2
g_dwCacheDownlinkVolume = (lpGainInfo->dwRxGain >> 24);
//In order to synchronize the lowest volume between TI and DF, don't allow TI no voice
if(g_dwCacheDownlinkVolume == 0)
{
g_dwCacheDownlinkVolume = 25;
}
#ifdef OEM2_DRIVER
// downlink volume on OEM2 is in the range 0-100, not 0-255, so nomalize here.
g_dwCacheDownlinkVolume = (g_dwCacheDownlinkVolume*100)/255;
#endif // OEM2_DRIVER
(void)_snprintfz(szWalk, MAX_PATH - (szWalk - szCmd), "+CLVL=%u", g_dwCacheDownlinkVolume);
#endif // Standard GSM case
szWalk = strchr(szWalk, '\0'); // NO_TYPO: 27
DEBUGCHK(NULL != szWalk);
#if !defined(OEM2_DRIVER) && !defined(OEM1_DRIVER)
if (lpGainInfo->dwParams & RIL_PARAM_GI_TXGAIN) {
(void)strncpyz(szWalk, ";", MAX_PATH - (szWalk - szCmd));
szWalk = strchr(szWalk, '\0'); // NO_TYPO: 27
DEBUGCHK(NULL != szWalk);
}
#endif
}
#if !defined(OEM2_DRIVER) && !defined(OEM1_DRIVER) // OEM1 and OEM2 do not support an AT command to modify Tx gain
if (lpGainInfo->dwParams & RIL_PARAM_GI_TXGAIN) {
(void)_snprintfz(szWalk, MAX_PATH - (szWalk - szCmd), "+VGT=%u", (lpGainInfo->dwTxGain >> 24));
szWalk = strchr(szWalk, '\0'); // NO_TYPO: 27
DEBUGCHK(NULL != szWalk);
}
#else // OEM1 and OEM2
g_dwCacheUplinkVolume = lpGainInfo->dwTxGain; // For OEM1 and OEM2, only cache TxGain value in gsm driver, no AT command is sent out.
#endif
(void)strncpyz(szWalk, "\r", MAX_PATH - (szWalk - szCmd)); // NO_TYPO: 30
if (!QueueCmd(pHandle, szCmd, CMDOPT_NONE, APIID_SETAUDIOGAIN, NULL, NULL, hr)) {
hr = E_FAIL;
goto Error;
}
Error:
return hr;
}
//
//
//
HRESULT RILDrv_SetAudioDevices(DWORD dwParam, const RILAUDIODEVICEINFO* lpAudioDeviceInfo)
{
FUNCTION_TRACE(RILDrv_SetAudioDevices);
#if defined(WAVECOM_DRIVER) || defined(OEM1_DRIVER)
// HW-SPECIFIC: This uses WaveCom-specific IOCTLs
DWORD dwDummy;
CComHandle* pComDevice;
HRESULT hr = S_OK;
CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
if (!pHandle || !lpAudioDeviceInfo) {
hr = E_FAIL;
goto Error;
}
if (!(lpAudioDeviceInfo->dwParams & RIL_PARAM_ADI_TXDEVICE) &&
!(lpAudioDeviceInfo->dwParams & RIL_PARAM_ADI_RXDEVICE)) {
hr = E_INVALIDARG;
goto Error;
}
if (lpAudioDeviceInfo->dwParams & RIL_PARAM_ADI_TXDEVICE) {
DEBUGCHK(NULL != pHandle->GetDevice());
DEBUGCHK(NULL != pHandle->GetDevice()->GetComDevice());
pComDevice = pHandle->GetDevice()->GetComDevice();
if (RIL_AUDIO_NONE == lpAudioDeviceInfo->dwTxDevice) {
(void)pComDevice->IOControl(IOCTL_SPKR_DISABLE, NULL, 0, NULL, 0, dwDummy);
} else {
(void)pComDevice->IOControl(IOCTL_SPKR_ENABLE, NULL, 0, NULL, 0, dwDummy);
}
}
// Send a no-op AT command to force an OK response
if (!QueueCmd(pHandle, NULL, CMDOPT_NOOP, APIID_SETAUDIODEVICES, NULL, NULL, hr)) {
hr = E_FAIL;
goto Error;
}
Error:
#else // defined(WAVECOM_DRIVER) || defined(OEM1_DRIVER)
HRESULT hr = E_NOTIMPL;
#endif // defined(WAVECOM_DRIVER) || defined(OEM1_DRIVER)
return hr;
}
//
//
//
static HRESULT ParseGetAudioMuting(LPCSTR szRsp, void*& pBlob, UINT& cbBlob)
{
FUNCTION_TRACE(ParseGetAudioMuting);
BOOL* pfEnabled = NULL;
HRESULT hr = S_OK;
pBlob = NULL;
cbBlob = 0;
pfEnabled = (BOOL*)AllocBlob(sizeof(BOOL));
if (!pfEnabled) {
hr = E_OUTOFMEMORY;
goto Error;
}
memset(pfEnabled, 0x00, sizeof(BOOL));
UINT nValue;
// Parse "<prefix>+CMUT: <enabled><postfix>"
if (!ParseRspPrefix(szRsp, szRsp) ||
!MatchStringBeginning(szRsp, "+CMUT: ", szRsp) ||
!ParseUIntAndVerifyAbove(szRsp, TRUE, 2, nValue, szRsp) ||
!ParseRspPostfix(szRsp, szRsp)) {
hr = E_FAIL;
goto Error;
}
*pfEnabled = (1 == nValue);
pBlob = (void*)pfEnabled;
cbBlob = sizeof(BOOL);
Error:
if (FAILED(hr)) {
FreeBlob(pfEnabled);
}
return hr;
}
//
//
//
HRESULT RILDrv_GetAudioMuting(DWORD dwParam)
{
FUNCTION_TRACE(RILDrv_GetAudioMuting);
HRESULT hr = S_OK;
CALLCTRL_SHARE_MEMORY_OPTION stShareMemOpt;
BOOL bCallInProgress = FALSE;
CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
if (!pHandle) {
hr = E_FAIL;
goto Error;
}
#ifdef RIL_RADIO_RESILIENCE
if (ShouldSpoofCommand())
{
// If the radio was reset recently, just return unmuted. Otherwise this may get
// queued up after all the init commands, and take a long time to execute
// This is bad, since we want to handle the RIL_NOTIFY_DISCONNECT
// that is sent up during reset so the UI can be updated quickly
BOOL* pfEnabled = (BOOL*)AllocBlob(sizeof(BOOL));
if (!pfEnabled) {
hr = E_OUTOFMEMORY;
goto Error;
}
hr = pHandle->GetDevice()->GetNextCmdID();
*pfEnabled = FALSE;
pHandle->Notify(RIL_RESULT_OK, hr, pfEnabled, sizeof(BOOL));
}
else
#endif // RIL_RADIO_RESILIENCE
{
if(RILDrv_CC_GetShareMemOpt(stShareMemOpt))
{
if((RILDrv_CC_IsCallExist(stShareMemOpt.nRILDriver1CallFlag,CALL_FLAG_VOICE_FIRST)
||RILDrv_CC_IsCallExist(stShareMemOpt.nRILDriver1CallFlag,CALL_FLAG_CSD))
&& !RILDrv_CC_IsCallStatusExist(stShareMemOpt.nRILDriver1CallStatus,CALL_STATUS_UNKNOWN))
{
bCallInProgress = TRUE;
}
else if((RILDrv_CC_IsCallExist(stShareMemOpt.nRILDriver2CallFlag,CALL_FLAG_VOICE_FIRST)
||RILDrv_CC_IsCallExist(stShareMemOpt.nRILDriver2CallFlag,CALL_FLAG_CSD))
&& !RILDrv_CC_IsCallStatusExist(stShareMemOpt.nRILDriver2CallStatus,CALL_STATUS_UNKNOWN))
{
bCallInProgress = TRUE;
}
}
if(g_fSetAudioMuting&&(bCallInProgress))//only df active
{
if (!QueueCmd(pHandle, "AT+CMUT?\r", CMDOPT_NONE, APIID_GETAUDIOMUTING, ParseGetAudioMuting, NULL, hr))
{
hr = E_FAIL;
goto Error;
}
}
else
{
g_fSetAudioMuting = FALSE;
if (!QueueCmd(pHandle, "AT+CMUT=0;+CMUT?\r", CMDOPT_NONE, APIID_GETAUDIOMUTING, ParseGetAudioMuting, NULL, hr))
{
hr = E_FAIL;
goto Error;
}
//signal audio driver that mic mute state is changed
if( (g_hWavDev != NULL) && (g_hWavDev != INVALID_HANDLE_VALUE) )
{
DWORD dwRet;
DeviceIoControl(g_hWavDev, IOCTL_MIC_UNMUTE, 0, 0, NULL, 0, &dwRet, NULL);
}
//end modify
}
}
Error:
return hr;
}
//
//
//
HRESULT RILDrv_SetAudioMuting(DWORD dwParam, BOOL fEnable)
{
FUNCTION_TRACE(RILDrv_SetAudioMuting);
char szCmd[MAX_PATH];
HRESULT hr = S_OK;
CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
if (!pHandle) {
hr = E_FAIL;
goto Error;
}
g_fSetAudioMuting = fEnable;
(void)_snprintfz(szCmd, MAX_PATH, "AT+CMUT=%u\r", (fEnable ? 1 : 0));
if (!QueueCmd(pHandle, szCmd, CMDOPT_NONE|CMDOPT_IGNORERADIOOFF, APIID_SETAUDIOMUTING, NULL, NULL, hr)) {
hr = E_FAIL;
goto Error;
}
//signal audio driver that mic mute state is changed
if( (g_hWavDev != NULL) && (g_hWavDev != INVALID_HANDLE_VALUE) )
{
DWORD dwRet;
if (fEnable)
{
DeviceIoControl (g_hWavDev, IOCTL_MIC_MUTE, 0, 0, NULL, 0, &dwRet, NULL);
}
else
{
DeviceIoControl (g_hWavDev, IOCTL_MIC_UNMUTE, 0, 0, NULL, 0, &dwRet, NULL);
}
}
Error:
return hr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -