diff -r 000000000000 -r 3553901f7fa8 telephonyserverplugins/multimodetsy/hayes/ATWAIT.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/telephonyserverplugins/multimodetsy/hayes/ATWAIT.CPP Tue Feb 02 01:41:59 2010 +0200 @@ -0,0 +1,434 @@ +// Copyright (c) 1997-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: +// Wait for Incoming Call +// +// + +#include "NOTIFY.H" +#include "mSLOGGER.H" +#include "LINE.H" +#include "CALL.H" +#include "ATCALL.H" +#include "ATIO.H" +#include "PHONE.H" + +_LIT8(KIncomingExtCallIndication,"+CRING:*"); +_LIT8(KIncomingCallIndication,"RING"); +_LIT8(KNetworkRegistration,"+CREG:*"); + +// +// CTimer-derived class to switch line status to idle a fixed period after the last +// RING arrives. Use this rather than CATIO::SetTimeOut() because that has only one +// timer which could be cancelled by another concurrently running AT command +// +CSetLineToIdle* CSetLineToIdle::NewL(CATWaitForCall* aWait) +// +// Create the SetLineToIdle async one shot +// + { + CSetLineToIdle* setLineToIdle=new(ELeave) CSetLineToIdle(aWait); + CleanupStack::PushL(setLineToIdle); + setLineToIdle->ConstructL(); + CleanupStack::Pop(); + return setLineToIdle; + } + +CSetLineToIdle::CSetLineToIdle(CATWaitForCall* aWait) +// +// C'tor +// + :CTimer(CActive::EPriorityLow), iWait(aWait) + { + CActiveScheduler::Add(this); + } + + +CSetLineToIdle::~CSetLineToIdle() + { + Cancel(); + } + +void CSetLineToIdle::RunL() + { + iWait->EndRing(); + } + +void CSetLineToIdle::Start() + { + if (IsActive()) + Cancel(); + After(KTimeBetweenRings); + } + +void CSetLineToIdle::Stop() + { + Cancel(); + } + +// +// CATWaitForCall. Expects a RING constantly, and upon receiving one checks if either line +// wants to be notified. Sets all lines and calls ringing anyway, and a timer to switch +// them back to idle after a specified time has elapsed since the last RING. +// + +CATWaitForCall* CATWaitForCall::NewL(CATIO* aIo,CTelObject* aTelObject,CPhoneGlobals* aPhoneGlobals) + { + CATWaitForCall* waitForCall=new(ELeave) CATWaitForCall(aIo,aTelObject,aPhoneGlobals); + CleanupStack::PushL(waitForCall); + waitForCall->ConstructL(); + CleanupStack::Pop(); + return waitForCall; + } + +CATWaitForCall::CATWaitForCall(CATIO* aIo,CTelObject* aTelObject,CPhoneGlobals* aPhoneGlobals) + : CATBase(aIo,aTelObject,aPhoneGlobals) + {} + +void CATWaitForCall::ConstructL() + { + iSetLineToIdle = CSetLineToIdle::NewL(this); + iRingExpectString=NULL; + iCRingExpectString=NULL; + iRegExpectString=NULL; + iTailExpectString=NULL; + } + +CATWaitForCall::~CATWaitForCall() + { + iIo->RemoveExpectStrings(this); + iRingExpectString=NULL; + iCRingExpectString=NULL; + iRegExpectString=NULL; + iTailExpectString=NULL; + iIo->WriteAndTimerCancel(this); + delete iSetLineToIdle; + } + +void CATWaitForCall::StartWait() + { + if (iRingExpectString==NULL) + { + LOGTEXT(_L8("WaitForCall:\tStarting wait for incoming call")); + iCRingExpectString=iIo->AddExpectString(this,KIncomingExtCallIndication); + iRingExpectString=iIo->AddExpectString(this,KIncomingCallIndication); + iRegExpectString=iIo->AddExpectString(this,KNetworkRegistration); + iState=EATWaitForUnsolicited; + } + } + +void CATWaitForCall::EndRing() +// +// Only called from the RunL of CSetLineToIdle, which occurs a fixed period after the +// last RING. StopBothLinesRinging() sets the calls on both lines to idle +// + { + LOGTEXT(_L8("WaitForCall:\tRinging has stopped")); + ChangeLineStatus(RCall::EStatusIdle); + STATIC_CAST(CPhoneHayes*,iTelObject)->StopRinging(); + iRingCounter = 0; + iPhoneGlobals->iNotificationStore->CheckNotification(iTelObject,ERingStopped); + } + +void CATWaitForCall::ResetRingCounter() + { + iRingCounter = 0; + iSetLineToIdle->Stop(); + } + +void CATWaitForCall::CompleteWithIOError(TEventSource /*aSource*/,TInt /*aStatus*/) +// +// CATIO removes expect strings in event of IO error +// + { + iRingExpectString=NULL; + iCRingExpectString=NULL; + iRegExpectString=NULL; + iTailExpectString=NULL; + } + +void CATWaitForCall::EventSignal(TEventSource aSource) +// +// Completes Incoming Call Notification for every ring. +// This is different from the previous TSY, but is needed for the Nokia 7110 which does +// not supply multiple RING notifications. +// + { + __ASSERT_ALWAYS(aSource!=EWriteCompletion,Panic(EATCommand_IllegalCompletionWriteNotExpected)); + if (aSource!=EReadCompletion) + return; + switch (iState) + { + case EATWaitForUnsolicited: + if (iIo->FoundChatString()==iCRingExpectString) + { + LOGTEXT(_L8("CATWaitForCall::EventSignal +CRING detected")); + LOGTEXT(_L8("CATWaitForCall::EventSignal Will only process +CRING if phone is initialised...")); + if (iPhoneGlobals->iPhoneStatus.iInitStatus==EPhoneInitialised) + { + LOGTEXT(_L8("CATWaitForCall::EventSignal Processing +CRING")); + TInt index=KErrNotFound; + TRAPD(ret,index=ParseIncomingCallIndicationL()); + if (ret==KErrNone) + { + iRingCounter+=1; + if (iRingCounter==1) + { + LOGTEXT(_L8("CATWaitForCall::EventSignal This is 1st +CRING")); + // Only do this once + ChangeLineStatus(RCall::EStatusRinging); + STATIC_CAST(CPhoneHayes*,iTelObject)->SetCallRinging(index); + } + iSetLineToIdle->Start(); + } + } + } + else if (iIo->FoundChatString()==iRingExpectString) + { + LOGTEXT(_L8("WaitForCall:\tRING detected")); + if (iPhoneGlobals->iPhoneStatus.iInitStatus==EPhoneInitialised) + { + iRingCounter+=1; + if (iRingCounter==1) + { + // Only do this once + ChangeLineStatus(RCall::EStatusRinging); + STATIC_CAST(CPhoneHayes*,iTelObject)->SetAmbiguousDataFaxCallRinging(); + } + iSetLineToIdle->Start(); + } + } + else if (iIo->FoundChatString()==iRegExpectString) + { + LOGTEXT(_L8("WaitForCall:\t+CREG detected")); + TRAPD(ret,ParseNetworkRegistrationL()); + if (ret!=KErrNone) + { + LOGTEXT(_L8("WaitForCall:\tBad +CREG response?")); + } + } + else + { + LOGTEXT(_L8("WaitForCall:\tUnexpected string")); + iTelObject->ReqCompleted(iReqHandle,KErrGeneral); + iReqHandle = NULL; + break; + } + break; + + default: + break; + } + } + +// Compare with +CMTI handling in GSMSNOTI.CPP +// which has a similar problem +/** +* Parse incoming call indication string and return a value corresponding to the call type. +* +* @note modified by Dmitry Lyokhin 24.04.02 +* +* @return KFaxLineIndex for fax call +* KVoiceLineIndex for voice call +* KDataLineIndex for data call or if call modifier is not recognized +* +* @note This function can leave with code KErrUnknown +* if 'RING' token not found +*/ +TInt CATWaitForCall::ParseIncomingCallIndicationL() + { + //-- possible incoming call indication strings that can be parsed correctly + //-- string corresponds to + + // +CRING: VOICE -> voice call + // +CRING: FAX -> fax call + // +CRING: DATA -> data call + // +CRING: VOICE/xxx -> voice call + // RING -> data call + + //-- alternating mode calls + // +CRING: ALT FAX/VOICE -> fax call + // +CRING: ALT DATA/VOICE -> data call + // +CRING: ALT VOICE/FAX -> fax call + // +CRING: ALT VOICE/DATA -> data call + + + iBuffer.Set(iIo->CurrentLine()); + + TInt index = KErrNotFound; + TLex8 Lex1(iBuffer); + + Lex1.SkipSpace(); + + //-- the first token must be '+CRING' or 'RING' + if( Lex1.NextToken().Find(_L8("RING")) < 0 ) + { //-- the token not found, leave + LOGTEXT(_L8("CATWaitForCall::ParseIncomingCallIndicationL *RING not found")); + User::Leave(KErrUnknown); + } + + Lex1.SkipSpaceAndMark(); + Lex1.SkipCharacters(); + + //-- try to find 'ALT' token that indicates the alternatng mode call + if( Lex1.MarkedToken().Find(_L8("ALT")) >=0 ) + {//-- Alternating mode call, skip the token "ALT" + } + else Lex1.UnGetToMark(); + + Lex1.SkipSpace(); + + TPtrC8 CallStr=Lex1.RemainderFromMark(); + + _LIT8(KDataToken, "DATA"); + _LIT8(KFaxToken, "FAX"); + _LIT8(KVoiceToken, "VOICE"); + + if(CallStr.Find(KDataToken) >= 0) index=KDataLineIndex; //-- Data call detected + else + if(CallStr.Find(KFaxToken) >= 0) index=KFaxLineIndex; //-- Fax call detected + else + if(CallStr.Find(KVoiceToken) >= 0) index=KVoiceLineIndex; //-- Voice call detected + else + {//-- unmatched call type, assume data call by default + LOGTEXT(_L8("CATWaitForCall::ParseIncomingCallIndicationL +CRING has unmatched type!, assuming data")); + index=KDataLineIndex; + //User::Leave(KErrUnknown); + } + + iIo->ClearCurrentLine(); + LOGTEXT2(_L8("+CRING for line %d"),index); + + return index; + } + + +void CATWaitForCall::ParseNetworkRegistrationL() + { + // +CREG: , [, , ] -- solicited + // +CREG: [, , ] -- unsolicited + // number, number [, "hex", "hex" ] + + RMobilePhone::TMobilePhoneLocationAreaV1& locationInfo = iPhoneGlobals->iPhoneStatus.iLocationArea; + locationInfo.iAreaKnown= EFalse; + locationInfo.iLocationAreaCode=0; + locationInfo.iCellId=0; + + ParseLineLC(); + CATParamListEntry* entry; + TDblQueIter iter(iRxResults); + + entry=iter++; + if (entry==NULL) + User::Leave(KErrGeneral); + // should be +CREG: + + entry=iter++; + if (entry==NULL) + User::Leave(KErrGeneral); + TLex8 lex(entry->iResultPtr); + TInt number; + (void)User::LeaveIfError(lex.Val(number)); + + entry=iter++; + if (entry!=NULL) + { // is this in a solicited +CREG? + lex.Assign(entry->iResultPtr); + if (lex.Val(number)==KErrNone) + entry=iter++; // yes - has been replaced by + } + + // optional and + if (entry != NULL) + { + lex.Assign(entry->iResultPtr); + (void)User::LeaveIfError(lex.Val(locationInfo.iLocationAreaCode,EHex)); + locationInfo.iAreaKnown = ETrue; + entry=iter++; + } + if (entry!=NULL) + { + lex.Assign(entry->iResultPtr); + (void)User::LeaveIfError(lex.Val(locationInfo.iCellId,EHex)); + locationInfo.iAreaKnown = ETrue; + } + + + + if (number<0 || number > RMobilePhone::ERegisteredRoaming) + User::Leave(KErrGeneral); + + RMobilePhone::TMobilePhoneRegistrationStatus regstatus; + regstatus = MappingRegistrationStatusFromETSIToMM(&number); //Mapp the ETSI value number to MM enum for network registration status. + + RMobilePhone::TMobilePhoneRegistrationStatus newstatus = regstatus;// change number to be of type MobilePhone... + RMobilePhone::TMobilePhoneRegistrationStatus oldstatus = iPhoneGlobals->iPhoneStatus.iRegistrationStatus; + + if (oldstatus != newstatus) + { + LOGTEXT3(_L8("MmTsy:CATWaitForCall:\tRegistrationStatus changed %d->%d"), oldstatus, newstatus); + iPhoneGlobals->iPhoneStatus.iRegistrationStatus = newstatus; + + iPhoneGlobals->iNotificationStore->CheckNotification(iTelObject,ERegistrationStatusChanged); + + if ( (newstatus == RMobilePhone::ERegisteredOnHomeNetwork || newstatus == RMobilePhone::ERegisteredRoaming) + || (oldstatus == RMobilePhone::ERegisteredOnHomeNetwork || oldstatus == RMobilePhone::ERegisteredRoaming) + ) + { + // interesting transition - need new operator details + LOGTEXT(_L8("MmTsy:CATWaitForCall:\tCurrent Network has changed")); + iPhoneGlobals->iPhoneStatus.iNetworkChanged=ETrue; + if (iPhoneGlobals->iPhoneStatus.iInitStatus == EPhoneInitialised && + !iPhoneGlobals->iEventSignalActive) + { + // no current activity - fire up +COPS stuff immediately + LOGTEXT(_L8("MmTsy:CATWaitForCall:\tNo activity - Checking current network immediately")); + iPhoneGlobals->CheckForChangeOfNetwork(); + } + } + } + + CleanupStack::PopAndDestroy(); + } + +RMobilePhone::TMobilePhoneRegistrationStatus CATWaitForCall::MappingRegistrationStatusFromETSIToMM(TInt *aNumber) + // This function is mapping the ETSI standard format for the registartion status of the phone to multimode representation. + // TINT *number is the ETSI value for the registration value to be converted. + + { + RMobilePhone::TMobilePhoneRegistrationStatus regstatus = RMobilePhone::ERegistrationUnknown; + switch (*aNumber) + { + case 0: + regstatus = RMobilePhone::ENotRegisteredNoService; + break; + case 1: + regstatus = RMobilePhone::ERegisteredOnHomeNetwork; + break; + case 2: + regstatus = RMobilePhone::ENotRegisteredSearching; + break; + case 3: + regstatus = RMobilePhone::ERegistrationDenied; + break; + case 4: + regstatus = RMobilePhone::ERegistrationUnknown; + break; + case 5: + regstatus = RMobilePhone::ERegisteredRoaming; + break; + default: + break; + } + return regstatus; + }