?? callctrl.cpp
字號:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*++
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.
Module Name:
callctrl.cpp
Abstract:
Notes:
--*/
#include "precomp.h"
#include <rilbacklight.h>
//
// Call status values
//
static const DWORD g_rgdwCallStats[] =
{
RIL_CALLSTAT_ACTIVE, // 0
RIL_CALLSTAT_ONHOLD, // 1
RIL_CALLSTAT_DIALING, // 2
RIL_CALLSTAT_ALERTING, // 3
RIL_CALLSTAT_INCOMING, // 4
RIL_CALLSTAT_WAITING, // 5
};
#define NUM_CALLSTATS (sizeof(g_rgdwCallStats) / sizeof(DWORD))
//
// Call type values
//
const DWORD g_rgdwCallTypes[] =
{
RIL_CALLTYPE_VOICE, // 0
RIL_CALLTYPE_DATA, // 1
RIL_CALLTYPE_FAX, // 2
RIL_CALLTYPE_PTT, // 3
RIL_CALLTYPE_VT, // 4
RIL_CALLTYPE_UNKNOWN, // 5
RIL_CALLTYPE_UNKNOWN, // 6
RIL_CALLTYPE_UNKNOWN, // 7
RIL_CALLTYPE_UNKNOWN, // 8
RIL_CALLTYPE_UNKNOWN, // 9
};
const UINT NUM_CALLTYPES = (sizeof(g_rgdwCallTypes) / sizeof(DWORD));
//
// Line status values
//
static const DWORD g_rgdwLineStats[] =
{
RIL_LINESTAT_READY, // 0
RIL_LINESTAT_UNAVAILABLE, // 1
RIL_LINESTAT_UNKNOWN, // 2
RIL_LINESTAT_RINGING, // 3
RIL_LINESTAT_CALLINPROGRESS, // 4
RIL_LINESTAT_ASLEEP, // 5
};
#define NUM_LINESTATS (sizeof(g_rgdwLineStats) / sizeof(DWORD))
// Defines an arbitrary maximum string length for the dial command.
// This maximum is not strictly enforced. It is used only as an aid
// for reporting a more specific error (RIL_E_DIALSTRINGTOOLONG) if
// the radio returns an error that is too generic.
#define MAX_DIAL_STRING_LENGTH 43
extern BOOL g_rfExternalCalltypeDetermination;
BOOL g_rgfCalltypeChecked[RIL_MAX_TRACKED_CALL_ID] = { FALSE }; // Initialize to FALSE
DWORD g_rgctCalltype[RIL_MAX_TRACKED_CALL_ID] = { 0 }; // Initialize to 0
DIALEDCALLDATA g_rcdDialedCallData;
extern CRITICAL_SECTION g_csDialedCallData;
extern RINGINGCALLDATA g_rcdRingingCallData;
extern CRITICAL_SECTION g_csRingingCallData;
// Define a global call type for call dialing, answering and hanging up
DWORD g_dwCallType = RIL_CALLTYPE_UNKNOWN;
VOID SetCalltypeFromCallInfo(RILCALLINFO *prci);
RILCALLINFO g_rgfCallStates[RIL_MAX_TRACKED_CALL_ID] = { 0 };
DWORD g_dwNumCallsInCallList = 0;
extern CRilHandle* g_pRilHandleDevice;
//
//
//
HRESULT RILDrv_Dial(DWORD dwParam, LPCSTR szAddress, DWORD dwType, DWORD dwOptions)
{
FUNCTION_TRACE(RILDrv_Dial);
#if defined (NODIALING) && !defined (SHIP_BUILD)
bool fNoDialing;
bool fNoEmergencyDialing;
#endif // NODIALING
CNotificationData* pnd = NULL;
RILCONNECTINFO rci; memset(&rci,0,sizeof(rci)); // zero struct
char szCmd[MAX_PATH];
LPSTR szWalk = szCmd;
const char *szDialStringStart = NULL;
HRESULT hr = S_OK;
LPCSTR szAddrWalk;
DWORD dwDialOpts = CMDOPT_DIAL|CMDOPT_RETRYONSIMLOCKED;
CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
if (!pHandle || !szAddress) {
hr = E_FAIL;
goto Error;
}
#if defined (NODIALING) && !defined (SHIP_BUILD)
// See if we want to disable dialing
if (GetRegistryBoolean(HKEY_LOCAL_MACHINE, g_tszRegKeyRIL, TEXT("NoDialing"), &fNoDialing) && fNoDialing) {
// We can't allow any dialing (for stress tests)
#ifndef SHIP_BUILD
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : RILDrv_Dial : Dialing is prevented: %s\r\n"), TString(szAddress)));
#endif // !SHIP_BUILD
hr = E_FAIL;
goto Error;
}
// See if we want to disable emergency dialing
if (GetRegistryBoolean(HKEY_LOCAL_MACHINE, g_tszRegKeyRIL, TEXT("NoEmergencyDialing"), &fNoEmergencyDialing) &&
fNoEmergencyDialing) {
if (!strcmp(szAddress, "911") || !strcmp(szAddress, "112") || !strcmp(szAddress, "08")) {
// We can't allow dialing of emergency numbers (for stress tests)
#ifndef SHIP_BUILD
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : RILDrv_Dial : Dialing of an emergency number is prevented: %s\r\n"), TString(szAddress)));
#endif // !SHIP_BUILD
hr = E_FAIL;
goto Error;
}
}
#endif // NODIALING
szWalk = BeginLineSpecificCommand(szCmd, MAX_PATH, 0);
// Remember the current call type.
g_dwCallType = dwType;
switch (dwType)
{
case RIL_CALLTYPE_VOICE:
case RIL_CALLTYPE_PTT:
pnd = new CNotificationData;
if (pnd) {
rci.cbSize = sizeof(RILCONNECTINFO);
rci.dwParams = RIL_PARAM_CNI_CALLTYPE;
rci.dwCallType = dwType;
if (!pnd->InitFromRealBlob(RIL_NOTIFY_CONNECT, &rci, sizeof(RILCONNECTINFO))) {
delete pnd;
pnd = NULL;
}
}
__fallthrough;
case RIL_CALLTYPE_DATA:
strncpyz(szWalk,"D",MAX_PATH - (szWalk - szCmd));
break;
case RIL_CALLTYPE_VT:
// Currently VT is not supported.
hr = E_NOTIMPL;
goto Error;
case RIL_CALLTYPE_FAX:
(void)strncpyz(szWalk, "+FCLASS+1;D", MAX_PATH - (szWalk - szCmd));
break;
default:
// This should have been caught in the proxy
DEBUGCHK(FALSE);
__fallthrough;
case RIL_CALLTYPE_UNKNOWN:
hr = E_INVALIDARG;
goto Error;
}
szWalk = strchr(szWalk, '\0'); // NO_TYPO: 27
DEBUGCHK(NULL != szWalk);
szDialStringStart = szWalk;
// Copy the number in
szAddrWalk = szAddress;
const char * const pcszCmdEnd = &szCmd[ ARRAY_LENGTH(szCmd)-1 ];
while( szWalk < pcszCmdEnd && *szAddrWalk != '\0' )
{
// Only allow characters in the set specified by GSM 07.07 section 6.2
if (strchr("1234567890*#+ABCD,TP!W@",*szAddrWalk))
{
*szWalk++ = *szAddrWalk;
}
szAddrWalk++;
}
// If the dial string is really long, make a note in case the
// command fails with a generic error. We can then guess that
// the real error is that the dial string was too long.
if ((szWalk - szDialStringStart) > MAX_DIAL_STRING_LENGTH)
{
dwDialOpts |= CMDOPT_LONGDIALSTRING;
}
if ( szWalk == szDialStringStart )
{
// No valid chars processed
hr = E_INVALIDARG;
goto Error;
}
// Remember to paste on the terminating '\0'
*szWalk='\0';
if (dwOptions & RIL_DIALOPT_CLOSEDGROUP) {
(void)strncpyz(szWalk, "G", MAX_PATH - (szWalk - szCmd));
szWalk++;
}
if (dwOptions & RIL_DIALOPT_RESTRICTID) {
(void)strncpyz(szWalk, "I", MAX_PATH - (szWalk - szCmd));
szWalk++;
}
else if (dwOptions & RIL_DIALOPT_PRESENTID) {
(void)strncpyz(szWalk, "i", MAX_PATH - (szWalk - szCmd));
szWalk++;
}
// If it's not a data call, terminate with a ; character
if ((dwType==RIL_CALLTYPE_VOICE)||(dwType==RIL_CALLTYPE_PTT))
{
(void)strncpyz(szWalk, ";", MAX_PATH - (szWalk - szCmd));
szWalk++;
}
else if (dwType==RIL_CALLTYPE_DATA)
{
dwDialOpts |= CMDOPT_DELAYCONNECTRSP;
}
(void)strncpyz(szWalk, "\r", MAX_PATH - (szWalk - szCmd));
// perform external calltype determination processing
if (g_rfExternalCalltypeDetermination)
{
// There is no call id associated with the the dialed call yet,
// so store the calltype so it can be used later
EnterCriticalSection(&g_csDialedCallData);
g_rcdDialedCallData.fValid = TRUE;
g_rcdDialedCallData.dwCalltype = dwType;
MultiByteToWideChar(CP_ACP, 0, szAddress, MAXLENGTH_ADDRESS, g_rcdDialedCallData.wszAddress, MAXLENGTH_ADDRESS);
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : RILDrv_Dial : Setting g_rcdDialedCallData calltype = %d, address = %s.\r\n"), g_rcdDialedCallData.dwCalltype, g_rcdDialedCallData.wszAddress));
LeaveCriticalSection(&g_csDialedCallData);
}
if ((dwType==RIL_CALLTYPE_VOICE)||(dwType==RIL_CALLTYPE_PTT))
{
// Indicate call is active to audio driver
IndicateCallActivityToAudioSubsystem(TRUE, FALSE);
}
if (!QueueCmd(pHandle, szCmd, dwDialOpts, APIID_DIAL, NULL, pnd, hr)) {
hr = E_FAIL;
goto Error;
}
pnd = NULL;
Error:
if ( E_FAIL == hr )
{
// Indicate call is inactive to audio driver only if call list is empty
IndicateCallActivityToAudioSubsystem(FALSE, TRUE);
}
return hr;
}
//
//
//
HRESULT RILDrv_Answer(DWORD dwParam)
{
FUNCTION_TRACE(RILDrv_Answer);
CNotificationData* pnd = NULL;
RILCONNECTINFO rci; memset(&rci,0,sizeof(rci)); // zero struct
HRESULT hr = S_OK;
CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
if (!pHandle) {
hr = E_FAIL;
goto Error;
}
// Set up the voice connect notification. If incoming call is a data call,
// we will get a "CONNECT" instead of "OK", which will prevent this notification
// from being sent
pnd = new CNotificationData;
if (pnd) {
rci.cbSize = sizeof(RILCONNECTINFO);
rci.dwParams = RIL_PARAM_CNI_CALLTYPE;
rci.dwCallType = g_dwCallType;
// check for externally determined calltype
if (g_rfExternalCalltypeDetermination)
{
// There may be no call id associated with the call yet,
// so use the previously stored calltype
EnterCriticalSection(&g_csRingingCallData);
if (g_rcdRingingCallData.fCalltypeValid)
{
rci.dwCallType = g_rcdRingingCallData.dwCalltype;
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : RILDrv_Answer : using calltype %d.\r\n"), g_rcdRingingCallData.dwCalltype));
g_rcdRingingCallData.dwCalltype = RIL_CALLTYPE_UNKNOWN;
g_rcdRingingCallData.fCalltypeValid = FALSE;
// Just in case there was a call id, clear the associated ringing call globals
g_rcdRingingCallData.fCallIdValid = FALSE;
g_rcdRingingCallData.dwCallId = RIL_MAX_TRACKED_CALL_ID;
}
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : RILDrv_Answer : Ringing Call TypeValid = %d, type = %d, IdValid = %d, Id = %d, \r\n"),
g_rcdRingingCallData.fCalltypeValid, g_rcdRingingCallData.dwCalltype,g_rcdRingingCallData.fCallIdValid,g_rcdRingingCallData.dwCallId));
LeaveCriticalSection(&g_csRingingCallData);
}
if (!pnd->InitFromRealBlob(RIL_NOTIFY_CONNECT, &rci, sizeof(RILCONNECTINFO))) {
delete pnd;
pnd = NULL;
}
}
// Indicate call is active to audio driver
IndicateCallActivityToAudioSubsystem(TRUE, FALSE);
if ( RIL_CALLTYPE_VT == g_dwCallType )
{
// Currently VT is not supported.
delete pnd;
pnd = NULL;
hr = E_FAIL;
goto Error;
}
else if (!QueueCmd(pHandle, "ATA\r", CMDOPT_ANSWER, APIID_ANSWER, NULL, pnd, hr)) {
hr = E_FAIL;
goto Error;
}
pnd = NULL;
Error:
if (E_FAIL == hr)
{
// Indicate call is inactive to audio driver only if call list is empty
IndicateCallActivityToAudioSubsystem(FALSE, TRUE);
}
if ( RIL_CALLTYPE_VT == g_dwCallType )
{
// Currently VT is not supported.
hr = E_NOTIMPL;
}
return hr;
}
//
//
//
HRESULT RILDrv_Hangup(DWORD dwParam)
{
FUNCTION_TRACE(RILDrv_Hangup);
CNotificationData* pnd = NULL;
BOOL fSuccess;
HRESULT hr = S_OK;
CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
if (!pHandle) {
hr = E_FAIL;
goto Error;
}
pnd = new CNotificationData;
if (pnd) {
if (pHandle->FPreferred()) {
fSuccess = pnd->InitFromRealBlob(RIL_NOTIFY_EMERGENCYHANGUP, NULL, 0);
} else {
// must notify of disconnect here since this lets drivers go to lower power state
fSuccess = pnd->InitFromDWORDBlob(RIL_NOTIFY_DISCONNECT, RIL_DISCINIT_LOCAL);
}
if (!fSuccess) {
delete pnd;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -