diff -r 000000000000 -r 3553901f7fa8 telephonyprotocols/csdagt/src/ND_ETEL.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/telephonyprotocols/csdagt/src/ND_ETEL.CPP Tue Feb 02 01:41:59 2010 +0200 @@ -0,0 +1,742 @@ +// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// ETel Processor +// +// + +/** + @file Nd_etel.cpp +*/ + +#include "ND_DBACC.H" +#include "ND_STD.H" +#include "ND_ETEL.H" +#include "SLOGGER.H" + +/** +@internalComponent +*/ +_LIT(KDoubleColon,"::"); +_LIT(KTsyNameExtension,".tsy"); + +/** +@internalComponent +*/ +const TInt KDefaultMaxDialAttempts=0; + +// CTelServerProcessor definitions + +CTelServerProcessor* CTelServerProcessor::NewL(CCommsDbNetDialAccess* aDb,TInt aPriority) +/** +2 phased constructor for CTelServerProcessor, first phase. + +@param aDb a pointer to CommDB accessor. +@param aPriority is priority for this object. +@exception Leaves if ConstructL() leaves, or not enough memory is available. +@return a new CTelServerProcessor object. +*/ + { + CTelServerProcessor* r=new(ELeave) CTelServerProcessor(aDb,aPriority); + CleanupStack::PushL(r); + r->ConstructL(); + CleanupStack::Pop(); + return r; + } + +CTelServerProcessor::CTelServerProcessor(CCommsDbNetDialAccess* aDb,TInt aPriority) + : CActive(aPriority), iDb(aDb), iCallParamsPckg(iCallParams), + iMmCallParamsPckg(iMmCallParams), iMmDataCallParamsPckg(iMmDataCallParams), + iMmHscsdParamsPckg(iMmHscsdParams) +/** +Private constructor for CTelServerProcessor, used in the first phase of construction. + +@param aDb a pointer to CommDB accessor. +@param aPriority is priority for this object. +*/ + {} + +void CTelServerProcessor::ConstructL() +/** +Instantiate Member variable. +Add this object into active scheduler. +Connect to ETel server. + +@exception Leaves if ETel server Connect() returns error, or not enough memory is available. +*/ + { + CActiveScheduler::Add(this); + + __FLOG_STMT(_LIT8(logString,"NetDial:\tConnecting Etel Server");) + __FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString()); + User::LeaveIfError(iTelServer.Connect()); + iState=EIdle; + iCallType=EUnknown; + } + +CTelServerProcessor::~CTelServerProcessor() +/** +Destructor. +Close active call. +If TSY is loaded, call UnloadPhoneModule() to unload it. +Close ETel server connection. +*/ + { + __FLOG_STMT(_LIT8(logString1,"NetDial:\tClosing Call");) + __FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString1()); + CloseCall(); + __FLOG_STMT(_LIT8(logString2,"NetDial:\tClosing Etel Server");) + __FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString2()); + if(iTsyLoaded) + { + iTelServer.UnloadPhoneModule(iTsyName); + iTsyLoaded=EFalse; + } + iTelServer.Close(); + } + +void CTelServerProcessor::StartDialUpL(MNetDialEtelObserver& aObserver) +/** +Open call and set call parameters, resolve number and dial. +Call OpenNewCallL() to open call object from ETel server. +Call DoDiallingResolutionL() from CommDB accessor to get correct tel number. +Call DialL() from call object to dial the call. + +@param aObserver a reference to observer. +@exception Leaves if OpenNewCallL(), DoDiallingResolutionL() or DialL() leaves. +*/ + { + Assertions(); + iCurrentObserver=&aObserver; + OpenNewCallL(); + iDb->DoDiallingResolutionL(iTelNum); + DialL(); + } + +void CTelServerProcessor::DialL() +/** +Dial number and increment dial counter. +Call GetRedialAttempts() from CommDB accessor to get max dial attempt count. +Check call type (ECoreCallOnly, EMmDataCall or EMmHscsdCall), get corresponding call parameters +and dial the call. + +@exception Leaves if GetCallParamsL() leaves. +*/ + { + __FLOG_STMT(_LIT(logString,"NetDial:\tDialling %S");) + __FLOG_STATIC1(KNetDialLogFolder(),KNetDialLogFile(),TRefByValue(logString()),&iTelNum); + + TInt ret=iDb->GetRedialAttempts(iMaxDialAttempts); + if (ret!=KErrNone) + { + iMaxDialAttempts=KDefaultMaxDialAttempts; + } + if (iCallType==ECoreCallOnly) + { + iDb->GetCallParamsL(iCallParams); + iCall.Dial(iStatus,iCallParamsPckg,iTelNum); + } + else if (iCallType==EMmDataCall) + { + iDb->GetCallParamsL(iMmDataCallParams); + iDb->GetMmCallParams(iMmDataCallParams); // ignore return value, contimue without if they are not there + iMmCall.Dial(iStatus,iMmDataCallParamsPckg, iTelNum); + } + else if (iCallType==EMmHscsdCall) + { + // When the call is opened, HSCSD parameters are already read when + // it is required and if phone supports it! + iDb->GetCallParamsL(iMmHscsdParams); + iDb->GetMmCallParams(iMmHscsdParams); // ignore return value, contimue without if they are not there + iMmCall.Dial(iStatus,iMmHscsdParamsPckg, iTelNum); + } + else + { + NetDialPanic(EUnknownCallType); + } + + SetActive(); + iDialCounter++; + iState=EDialUp; + } + +void CTelServerProcessor::StartReconnectL(MNetDialEtelObserver& aObserver) +/** +Dial number and increment dial counter. +If comm port is loaned, call ReturnCommPortL() to recover comm port to ETel. +Start reconnection by calling DialL(). + +@param aObserver a reference to observer. +@exception Leaves if ReturnCommPortL() or DialL() leaves. +*/ + { + if (iLoaned) + ReturnCommPortL(); + + Assertions(); + __ASSERT_ALWAYS(iCallOpen, NetDialPanic(EEtelCallNotOpen)); + iCurrentObserver=&aObserver; + + DialL(); + } + +#ifdef SYMBIAN_NETWORKING_CSDAGENT_BCA_SUPPORT +void CTelServerProcessor::ListenForStatusChange(MNetDialEtelObserver& aObserver) +/** +Enable listening for a baseband disconnect +@param aObserver a reference to observer. +*/ + { + __FLOG_STMT(_LIT8(logString,"NetDial:\tListening For Call Status Change");) + __FLOG_STATIC(KNetDialLogFolder(), KNetDialLogFile(), logString()); + + __ASSERT_ALWAYS(EIdle == iState, NetDialPanic(EEtelServerNotIdle)); + __ASSERT_ALWAYS(iCallOpen, NetDialPanic(EEtelCallNotOpen)); + + iCurrentObserver = &aObserver; + ActiveCall().NotifyStatusChange(iStatus, iCallStatus); + SetActive(); + iState = EListenForStatusChange; + } + +void CTelServerProcessor::CancelListenForStatusChange() + { + __FLOG_STMT(_LIT8(logString,"NetDial:\tCancelListenForStatusChange. iState: [%d]. iStatus: [%d]");) + __FLOG_STATIC2(KNetDialLogFolder(), KNetDialLogFile(), logString(), iState, iStatus.Int()); + + __ASSERT_ALWAYS(iCallOpen, NetDialPanic(EEtelCallNotOpen)); + + Cancel(); + } + +void CTelServerProcessor::HandleStatusChange() +/** +Handle call status change. +If the call dropped, notify the observer, otherwise re-issue status +change notification +*/ + { + __FLOG_STMT(_LIT8(logString,"NetDial:\tCall Status Changed. CallStatus %d Error: %d");) + __FLOG_STATIC2(KNetDialLogFolder(), KNetDialLogFile(), logString(), iCallStatus, iStatus.Int()); + + // Ignore if subscribing to status change notification failed. + // It can be that the TSY doesn't support the feature etc. + if (KErrNone != iStatus.Int()) + { + iState = EIdle; + return; + } + + __ASSERT_ALWAYS(iCallOpen, NetDialPanic(EEtelCallNotOpen)); + + switch (iCallStatus) + { + case RCall::EStatusHangingUp: + case RCall::EStatusIdle: + { + iState = EIdle; + iCurrentObserver->TelFunctionComplete(iStatus.Int()); + break; + } + default: + { + iState = EListenForStatusChange; + ActiveCall().NotifyStatusChange(iStatus, iCallStatus); + SetActive(); + } + } + } +#endif // SYMBIAN_NETWORKING_CSDAGENT_BCA_SUPPORT +void CTelServerProcessor::WaitForIncomingCallL(MNetDialEtelObserver& aObserver) +/** +If comm port is loaned, call ReturnCommPortL() to recover comm port to ETel.for callback. +Call GetPhoneInfoL(). +If call is not opened, call OpenNewCallL() to open call object from ETel. +Check call type (ECoreCallOnly, EMmDataCall or EMmHscsdCall), get corresponding call parameters, +call AnswerIncomingCall() and start to wait for incoming call. + +@param aObserver a reference to observer. +@exception Leaves if GetPhoneInfoL() or GetCallParamsL()leaves. +*/ + { + if (iLoaned) + ReturnCommPortL(); + + Assertions(); + + iCurrentObserver=&aObserver; + RTelServer::TPhoneInfo info; + GetPhoneInfoL(info); + + if (!iCallOpen) + OpenNewCallL(); + + __FLOG_STMT(_LIT8(logString2,"NetDial:\tWaiting For Incoming Call");) + __FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString2()); + + if (iCallType==ECoreCallOnly) + { + iDb->GetCallParamsL(iCallParams); + iCall.AnswerIncomingCall(iStatus,iCallParamsPckg); + } + else if (iCallType==EMmDataCall) + { + iDb->GetCallParamsL(iMmDataCallParams); + iDb->GetMmCallParams(iMmDataCallParams); // ignore return value, contimue without if they are not there + iMmCall.AnswerIncomingCall(iStatus,iMmDataCallParamsPckg); + } + else if (iCallType==EMmHscsdCall) + { + // When the call is opened, HSCSD parameters are already read when + // it is required and if phone supports it! + iDb->GetCallParamsL(iMmHscsdParams); + iDb->GetMmCallParams(iMmHscsdParams); // ignore return value, contimue without if they are not there + iMmCall.AnswerIncomingCall(iStatus,iMmHscsdParamsPckg); + } + + else + NetDialPanic(EUnknownCallType); + + SetActive(); + iState=EWait; + } + +void CTelServerProcessor::StartHangUpAfterDialOut(MNetDialEtelObserver& aObserver) +/** +Call StartHangUp() to end the dialled call. + +@param aObserver a reference to observer. +*/ + { + iCurrentObserver=&aObserver; + StartHangUp(); + iState=EHangUpDialOut; + } + +void CTelServerProcessor::StartHangUpAfterDialIn(MNetDialEtelObserver& aObserver) +/** +Call StartHangUp() to end the dialled call. + +@param aObserver a reference to observer. +*/ + { + iCurrentObserver=&aObserver; + StartHangUp(); + iState=EHangUpDialIn; + } + +void CTelServerProcessor::StartHangUp() +/** +Call HangUp() from active call object. +Set object active to wait for completition of request. +*/ + { +#ifdef SYMBIAN_NETWORKING_CSDAGENT_BCA_SUPPORT + CancelListenForStatusChange(); +#endif + Assertions(); + + __FLOG_STMT(_LIT8(logString,"NetDial:\tHanging Up Call");) + __FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString()); + ActiveCall().HangUp(iStatus); + SetActive(); + } + +void CTelServerProcessor::GetCommPortL(RCall::TCommPort& aCommPort) +/** +Call LoanDataPort() to loan comm port from ETel server. +Call SetCommPortL() from CommDB accessor to set the comm port into CommDB. + +@param aCommPort returns reference to loaned comm port. +@exception Leaves if LoanDataPort() returns error or SetCommPortL leaves. +*/ + { + __FLOG_STMT(_LIT8(logString,"NetDial:\tLoaning Port From Etel");) + __FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString()); + User::LeaveIfError(ActiveCall().LoanDataPort(aCommPort)); + iDb->SetCommPortL(aCommPort); + iLoaned=ETrue; +#ifndef SYMBIAN_NETWORKING_CSDAGENT_BCA_SUPPORT + iState=EIdle; +#endif + } + +void CTelServerProcessor::ReturnCommPortL() +/** +Call RecoverDataPort() to return comm port to ETel server. + +@exception Leaves if RecoverDataPort() returns error. +*/ + { + __FLOG_STMT(_LIT8(logString,"NetDial:\tRecovering Port To Etel");) + __FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString()); + User::LeaveIfError(ActiveCall().RecoverDataPort()); + iLoaned=EFalse; +#ifndef SYMBIAN_NETWORKING_CSDAGENT_BCA_SUPPORT + iState=EIdle; +#endif + } + +void CTelServerProcessor::CloseCall() +/** +If comm port is loaned, call ReturnCommPortL() and trap error. +If call is open, call Close() from active call object. +*/ + { + __FLOG_STMT(_LIT8(logString,"NetDial:\tClosing Call");) + __FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString()); + if (iLoaned) + { + TRAPD(ret,ReturnCommPortL()); // can't do anything with the error, so just trap + if (KErrNone != ret) + { + __FLOG_STMT(_LIT8(logString2,"ReturnCommPort:\tError Occured");) + __FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString2()); + } + } + + if (iCallOpen) + { + ActiveCall().Close(); + iCallOpen=EFalse; + } + + iCallType=EUnknown; + } + +void CTelServerProcessor::DoCancel() +/** +Cancels active requests. +Ignore return value of cancels because we can't do anything with it! +*/ + { + switch (iState) + { + case EDialUp: + ActiveCall().DialCancel(); + break; + case EWait: + ActiveCall().AnswerIncomingCallCancel(); + break; + case EHangUpDialOut: + case EHangUpDialIn: + ActiveCall().HangUpCancel(); + break; +#ifdef SYMBIAN_NETWORKING_CSDAGENT_BCA_SUPPORT + case EListenForStatusChange: + ActiveCall().NotifyStatusChangeCancel(); + break; +#endif + default: + break; + } + + iDialCounter=0; + iState=EIdle; + } + +void CTelServerProcessor::RunL() +/** +Request completed. +Match internal state and act accordingly. +*/ + { + __ASSERT_ALWAYS(iCurrentObserver!=NULL, NetDialPanic(ENullCallBackContext)); + + switch (iState) + { + case EDialUp: + { + TBool ret=EFalse; + TRAPD(err,(ret=RepeatDialL())); + if (err!=KErrNone) + iStatus=err; + if (err!=KErrNone || !ret) + { + iState=EIdle; + iDialCounter=0; + iCurrentObserver->TelFunctionComplete(iStatus.Int()); + } + } + break; + case EWait: + iState=EIdle; + iCurrentObserver->TelFunctionComplete(iStatus.Int()); + break; + case EHangUpDialOut: + iState=EIdle; + iCurrentObserver->TelFunctionComplete(iStatus.Int()); + break; + case EHangUpDialIn: + iState=EIdle; + iCurrentObserver->TelFunctionComplete(iStatus.Int()); + break; +#ifdef SYMBIAN_NETWORKING_CSDAGENT_BCA_SUPPORT + case EListenForStatusChange: + HandleStatusChange(); + break; +#endif + default: + User::Leave(KErrNotFound); + break; + } + } + +TBool CTelServerProcessor::RepeatDialL() +/** +If iStatus.Int() is KErrEtelBusyDetected or KErrEtelNoAnswer and max dial count +is not exceeded, call DialL() to re-dial. + +@exception Leaves if DialL() leaves. +@return ETrue if DialL() is called, otherwise EFalse. +*/ + { + if ((iStatus.Int()==KErrEtelBusyDetected || iStatus.Int()==KErrEtelNoAnswer ) && (iDialCounter newTsyName; + iDb->GetTsyNameL(newTsyName); + // Remove unnecessary .TSY extension, if found + if (newTsyName.Right(4).CompareF(KTsyNameExtension) == 0) + newTsyName = newTsyName.Left(newTsyName.Length() - 4); + + TBool loaded=EFalse; + if (iTsyName.Length()!=0) + { + if (iTsyName.CompareF(newTsyName)==KErrNone) // the one we want is already loaded + loaded=ETrue; + else // unload the one we were using + { + User::LeaveIfError(iTelServer.UnloadPhoneModule(iTsyName)); + iTsyLoaded=EFalse; + } + } + + if (!loaded) + { + User::LeaveIfError(iTelServer.LoadPhoneModule(newTsyName)); + iTsyName=newTsyName; + iTsyLoaded=ETrue; + } + + if (iTelServer.SetExtendedErrorGranularity(RTelServer::EErrorExtended)!=KErrNone) + { + User::LeaveIfError(iTelServer.SetExtendedErrorGranularity(RTelServer::EErrorBasic)); + } + + RTelServer::TPhoneInfo info; + GetPhoneInfoL(info); + + TName callName; + callName.Zero(); + callName.Copy(info.iName); // phone name + callName.Append(KDoubleColon); + + RPhone::TLineInfo lineInfo; + GetLineInfoL(lineInfo,info.iName,RLine::KCapsData); + callName.Append(lineInfo.iName); + + callName.Append(KDoubleColon); + __FLOG_STMT(_LIT8(logString,"NetDial:\tOpening Call");) + __FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString()); + + iDb->CopyIspInitStringToModemL(); // will not leave if the field is blank + // Only MultimodeV1 and greater supported! + if (info.iExtensions>=(TUint)KETelExtMultimodeV1) + { + User::LeaveIfError(iMmCall.OpenNewCall(iTelServer,callName)); + iCallOpen=ETrue; + iCallType=EMmDataCall; + SetMmParametersL(); // may change call type to EMmHscsdCall + } + else + { + User::LeaveIfError(iCall.OpenNewCall(iTelServer,callName)); + iCallOpen=ETrue; + iCallType=ECoreCallOnly; + } + } + +void CTelServerProcessor::GetPhoneInfoL(RTelServer::TPhoneInfo& aInfo) + { + TInt count; + User::LeaveIfError(iTelServer.EnumeratePhones(count)); + if (count<=0) + { + __FLOG_STMT(_LIT(logString,"NetDial:\tGetPhoneInfoL(): no phones found - leaving with -1");) + __FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString()); + User::Leave(KErrNotFound); + } + TInt i; + TBool found=EFalse; + for (i=0; i currentTsyName; + User::LeaveIfError(iTelServer.GetTsyName(i,currentTsyName)); + // Remove unnecessary extension, if found + if (currentTsyName.Right(4).CompareF(KTsyNameExtension) == 0) + currentTsyName = currentTsyName.Left(currentTsyName.Length() - 4); + // Check for match in TSY names + if (currentTsyName.CompareF(iTsyName)==KErrNone) + { + User::LeaveIfError(iTelServer.GetPhoneInfo(i,aInfo)); + found=ETrue; + break; + } + } + + if (!found) + { + __FLOG_STMT(_LIT(logString,"NetDial:\tGetPhoneInfoL(): required phone not found - leaving with -1");) + __FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString()); + User::Leave(KErrNotFound); + } + } + +void CTelServerProcessor::GetLineInfoL(RPhone::TLineInfo& aInfo,const TDesC& aPhoneName, TUint aLineType) + { + RPhone phone; + User::LeaveIfError(phone.Open(iTelServer,aPhoneName)); + CleanupClosePushL(phone); + + TInt count = 0; + User::LeaveIfError(phone.EnumerateLines(count)); + if (count <= 0) + { + __FLOG_STMT(_LIT(logString,"NetDial:\tGetLineInfoL(): no line info available - leaving with -1");) + __FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString()); + User::Leave(KErrNotFound); + } + + TBool found = EFalse; + for (TInt i=0; iHscsdSettingsAvailableL()) + { + RMobileCall::TMobileCallDataCapsV1 mmDataCaps; + RMobileCall::TMobileCallDataCapsV1Pckg mmDataCapsPckg(mmDataCaps); + // Get the data caps from the phone + TInt ret = iMmCall.GetMobileDataCallCaps(mmDataCapsPckg); + if (KErrNone == ret) + { + // Check if the HSCSD is supported + if (mmDataCaps.iHscsdSupport != EFalse) + { + // Get the multimode HSCSD parameters and pass them in Dial. + iDb->GetMmHscsdParametersL(iMmHscsdParams); + iCallType=EMmHscsdCall; + } + } + else if (KErrNotSupported != ret) + User::Leave(ret); + } + } + +RCall& CTelServerProcessor::ActiveCall() +/** +If iCallType is ECoreCallOnly, return iCall. +If iCallType is EMmDataCall or EMmHscsdCall, return iMmCall. +Otherwise panic with EUnknownCallType. + +@return iCall or iMmCall. +*/ + { + if (iCallType==ECoreCallOnly) + return iCall; + + if (iCallType==EMmDataCall || iCallType==EMmHscsdCall) + return iMmCall; + + NetDialPanic(EUnknownCallType); + return iCall; // will never happen because of panic + } + +TBool CTelServerProcessor::CommPortLoaned() const +/** +@return iLoaned. +*/ + { + return iLoaned; + } + +TBool CTelServerProcessor::CallActive() const +/** +@return iCallType. +*/ + { + return (iCallType != EUnknown); + } +