diff -r 6b1d113cdff3 -r 6638e7f4bd8f telephonyserverplugins/multimodetsy/hayes/ATBASE.CPP --- a/telephonyserverplugins/multimodetsy/hayes/ATBASE.CPP Mon May 03 13:37:20 2010 +0300 +++ b/telephonyserverplugins/multimodetsy/hayes/ATBASE.CPP Thu May 06 15:10:38 2010 +0100 @@ -1,682 +1,682 @@ -// 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: -// AT Command Base Class -// -// - -#include "PHONE.H" -#include "ATIO.H" -#include "mSLOGGER.H" -#include "ATINIT.H" -#include "ATESCAPE.H" -#include "LINE.H" -#include "NOTIFY.H" -#include "sms_rx_queue.h" // for CReceiveSmsQueue - -// Specific GSM Error String Response -_LIT8(KCmsErrorString,"+CMS ERROR:*"); - -// -// CATParamListEntry -// A pointer to a meaningful result in the received buffer from the modem -// -CATParamListEntry::CATParamListEntry(const TDesC8& aDes) : - iResultPtr(aDes) - { - } - -CATParamListEntry::~CATParamListEntry() - {} - -void CATParamListEntry::Deque() - { - iLink.Deque(); - } - -void CATParamListEntry::EntryValL(CATParamListEntry* aEntry,TInt& aValue) - { - if (aEntry==NULL) - User::Leave(KErrGeneral); - TLex8 lex(aEntry->iResultPtr); - (void)User::LeaveIfError(lex.Val(aValue)); - aEntry->Deque(); - delete aEntry; - } - -TInt CATParamListEntry::EntryValL(CATParamListEntry* aEntry) - { - TInt val; - EntryValL(aEntry,val); - return val; - } - - -// -// Async One Shot to call RelinquishOwnershipComplete(). -// If RelinquishOwnershipComplete() is called synchronously, it destroys the CATIO object -// before the latter has finished processing. -// -CCompleteRelinquish* CCompleteRelinquish::New(CTelObject* aTelObject) -// -// Create the Relinquish Complete async one shot -// - { - // The below TRAP is used to stop leavescan errors occurring. - // This is not the best solution, but I am pressed for time ;-( - CCompleteRelinquish* ptr=NULL; - TRAP_IGNORE(ptr=new(ELeave)CCompleteRelinquish(aTelObject)); - return ptr; - } - -CCompleteRelinquish::CCompleteRelinquish(CTelObject* aTelObject) -// -// C'tor -// - :CAsyncOneShot(CActive::EPriorityLow), iTelObject(aTelObject) - { - __DECLARE_NAME(_S("CCompleteRelinquish")); - } - - -CCompleteRelinquish::~CCompleteRelinquish() - { - Cancel(); - } - -void CCompleteRelinquish::RunL() -// -// Call RelinquishOwnershipCompleted() or RecoverDataPortAndRelinquishOwnershipCompleted() -// after CATIO has finished its processing -// - { - __ASSERT_ALWAYS(iPanicOccurred!=ENoPanicOccurred,Panic(EIllegalPanicOccurredValue)); - if (iPanicOccurred == EPanicOccurredWithoutDataPortLoan) - { - REINTERPRET_CAST(CCallBase*,iTelObject)->RelinquishOwnershipCompleted(KErrNone); - } - if (iPanicOccurred == EPanicOccurredDuringDataPortLoan) - { - REINTERPRET_CAST(CCallBase*,iTelObject)->RecoverDataPortAndRelinquishOwnershipCompleted(KErrNone); - } - delete this; - } -// -// The Command Base Class -// -CATBase::CATBase(CATIO* aIo, CTelObject* aTelObject,CPhoneGlobals* aPhoneGlobals) - : iIo(aIo),iPhoneGlobals(aPhoneGlobals),iComplete(NULL),iTelObject(aTelObject),iCallInfo(NULL) - { - iRxResults.SetOffset(_FOFF(CATParamListEntry,iLink)); - } - -CATBase::~CATBase() -// -// Assumes CATIO pointer is still valid -// - { - if(!iRxResults.IsEmpty()) - { - CATParamListEntry* entry; - TDblQueIter iter(iRxResults); - while (entry = iter++,entry!=NULL) - { - entry->Deque(); - delete entry; - } - } - } - -void CATBase::GenericEventSignal(TEventSource aEventSource, TInt aStatus) -// -// If an IO error has occurred, complete this ATBase-object with the error. -// - { - if (aStatus!=KErrNone) - { - LOGTEXT2(_L8("EventSignal received error status %d"),aStatus); - CompleteWithIOError(aEventSource,aStatus); - } - else - { - EventSignal(aEventSource); - } - } - -void CATBase::AddStdExpectStrings() - { - if (!iOKExpectString) - iOKExpectString=iIo->AddExpectString(this,KOkString); - if (!iErrorExpectString) - iErrorExpectString=iIo->AddExpectString(this,KErrorString); - } - - -TInt CATBase::ValidateExpectString() -/** - * New version ValidateExpectStringL which returns an error code - * as opposed to leaving. - * Use of this new code should hopefully remove alot of - * unesseccary TRAP harness in the TSY. - */ - { - TInt ret(KErrNone); - - if(iIo->FoundChatString()!=iOKExpectString) - { - if(iIo->FoundChatString()==iErrorExpectString) - { - LOGTEXT(_L8("Modem returned ERROR in response to command")); - ret=KErrGeneral; - } - else - { - LOGTEXT(_L8("Modem returned unexpected response to command")); - ret=KErrUnknown; - } - } - - return ret; - } - -void CATBase::RemoveStdExpectStrings() - { - LOGTEXT(_L8("RemoveStdExpectStrings()")); - iIo->RemoveExpectString(iOKExpectString); - iOKExpectString=NULL; - iIo->RemoveExpectString(iErrorExpectString); - iErrorExpectString=NULL; - } - -void CATBase::RemoveUnsolicitedStrings() - { - LOGTEXT(_L8("RemoveUnsolicitedStrings()")); - - _LIT8(KNetworkRegistration,"+CREG:"); // Network registration - _LIT8(KIncomingCallIndication,"RING"); // Normal Ring - _LIT8(KIncomingExtCallIndication,"+CRING:"); // Extended format call - _LIT8(KIncomingExtNTCallParameter,"REL"); // Non-Transparent parameter - _LIT8(KIncomingExtAlternatingCallParameter,"ALT"); // Unsupported Alternating parameter - _LIT8(KIncomingExtVoiceRelCallParameter,"VOICE/REL"); // NT Voice parameter - - if(!iRxResults.IsEmpty()) - { - TInt aQueueSteps = NULL; - CATParamListEntry* entry; - TDblQueIter iter(iRxResults); - // Step along the queue looking for an unsolicited strings - while (entry = iter++,entry!=NULL) - { - TPtrC8 aResult(entry->iResultPtr); - // If a match is found, we dequeue it and all its expected parameters - if (aResult==KIncomingCallIndication) // 0 Params - { - // Remove the "RING" - entry->Deque(); delete entry; - LOGTEXT2(_L8("Unsolicited >%S< Removed"),&aResult); - } - else if (aResult==KIncomingExtCallIndication) // 1/2 Params - { - // Remove the "+CRING:" - entry->Deque(); delete entry; entry = iter++; - LOGTEXT2(_L8("Unsolicited >%S< Removed"),&aResult); - // We know we should be getting at least one and maybee two parameters - TPtrC8 aFirstParameterResult(entry->iResultPtr); - if (aFirstParameterResult==KIncomingExtNTCallParameter - || aFirstParameterResult==KIncomingExtVoiceRelCallParameter - || aFirstParameterResult==KIncomingExtAlternatingCallParameter) - { - // We have an "ALT" or a "REL" so we have two parameters - entry->Deque(); delete entry; entry = iter++; - TPtrC8 aSecondParameterResult(entry->iResultPtr); - entry->Deque(); delete entry; // If recognised parameter - remove - LOGTEXT3(_L8("Unsolicited Parameter >%S %S< Removed"),&aFirstParameterResult,&aSecondParameterResult); aSecondParameterResult==KIncomingCallIndication; // Quick fix to remove unused parameters make warning - } - else - { - // We only have one parameter - entry->Deque(); delete entry; // If recognised parameter - remove - LOGTEXT2(_L8("Unsolicited Parameter >%S< Removed"),&aFirstParameterResult); - } - } - else if (aResult==KNetworkRegistration) // 2 Params - { - // Remove the "+CREG:" - entry->Deque(); delete entry; entry = iter++; - LOGTEXT2(_L8("Unsolicited >%S< Removed"),&aResult); - // Remove both parameters - TPtrC8 aFirstParameterResult(entry->iResultPtr); - entry->Deque(); delete entry; entry = iter++; - TPtrC8 aSecondParameterResult(entry->iResultPtr); - entry->Deque(); delete entry; - LOGTEXT3(_L8("Unsolicited Parameters >%S,%S< Removed"),&aFirstParameterResult,&aSecondParameterResult); aFirstParameterResult==KIncomingCallIndication; aSecondParameterResult==KIncomingCallIndication; // Quick fix to remove unused parameters make warning - } - - // Increment the queue step counter - else aQueueSteps++; - } - // Now we have to retrace the list, ignoring dequeued entries - for (TInt aLoop=NULL;aLoop(aCATBase); - TDblQueIter iter(p->iRxResults); - CATParamListEntry* entry=iter++; - while (entry!=NULL) - { - entry->Deque(); - delete entry; - entry=iter++; - } - } - -void CATBase::RxResultsPushLC() - { - TCleanupItem cleanup(CleanupRxResults,this); - CleanupStack::PushL(cleanup); - } - -void CATBase::ParseBufferLC(TBool aReportLists, TUint aSeparatorChar) -// -// Parses buffer. Treats aSeparatorChar like a comma -// - { - LOGTEXT(_L8("Parse the Buffer List")); - - if (iIo->CurrentLine()==KOkString) - iIo->ClearCurrentLine(); // remove trailing "OK" - - iBuffer.Set(iIo->Buffer()); - iIo->ClearBuffer(); - - ParseLC(aReportLists, aSeparatorChar); - } - -void CATBase::ParseLineLC(TBool aReportLists, TUint aSeparatorChar) -// -// Parses current line. Treats aSeparatorChar like a comma -// - { - LOGTEXT(_L8("Parse the current line")); - - iBuffer.Set(iIo->CurrentLine()); - iIo->ClearCurrentLine(); - ParseLC(aReportLists, aSeparatorChar); - } - -void CATBase::AddParamL(const TDesC8 &aPtr) - { - CATParamListEntry* aParamListEntry = new (ELeave) CATParamListEntry(aPtr); - iRxResults.AddLast(*aParamListEntry); - } - -void CATBase::ParseLC(TBool aReportLists, TUint aSeparatorChar) -// -// Does the actual parsing of iBuffer, set up from ParseLineLC or ParseBufferLC -// - { -_LIT8(KOpenBracket, "("); -_LIT8(KCloseBracket, ")"); - -#ifdef __LOGDEB__ - TPtrC8 buf(iBuffer); - if (buf.Length()>180) - { - buf.Set(buf.Left(180)); - LOGTEXT2(_L8("buffer to parse >%S< and so on ..."),&buf); - } - else - LOGTEXT2(_L8("buffer to parse >%S<"),&buf); -#endif - - RxResultsPushLC(); - TLex8 yyLex(iBuffer); - - // Move cursor past any spaces or open brackets - yyLex.SkipSpace(); - TChar peek=yyLex.Peek(); - if (peek=='(' || peek=='[' || peek=='{') - yyLex.Inc(); - - if (aReportLists && peek=='(') - { - AddParamL(KOpenBracket); - LOGTEXT2(_L8("list separator >%S<"),&iRxResults.Last()->iResultPtr); - } - do - { - // Skip all space and opening brackets - for (;;) - { - yyLex.SkipSpace(); - if (yyLex.Eos()) - return; - peek = yyLex.Peek(); - if (peek!='(') - break; - if (aReportLists) - { - AddParamL(KOpenBracket); - LOGTEXT2(_L8("list separator >%S<"),&iRxResults.Last()->iResultPtr); - } - yyLex.Inc(); - } - - if (peek=='"') // start of quoted string - { - yyLex.Inc(); // step over the quote - yyLex.Mark(); - while (!yyLex.Eos()) - { - peek=yyLex.Peek(); - if (peek=='"') - break; - yyLex.Inc(); - } - - AddParamL(yyLex.MarkedToken()); - LOGTEXT2(_L8("quoted parameter >%S<"),&iRxResults.Last()->iResultPtr); - if (yyLex.Eos()) - return; - - // Skip all space and closing brackets - for (;;) - { - yyLex.Inc(); - yyLex.SkipSpace(); - if (yyLex.Eos()) - return; - peek = yyLex.Peek(); - if (peek!=')') - break; - if (aReportLists) - { - AddParamL(KCloseBracket); - LOGTEXT2(_L8("list separator >%S<"),&iRxResults.Last()->iResultPtr); - } - } - - // Skip any following separator - if (peek==',' || peek==aSeparatorChar) - { - yyLex.Inc(); - yyLex.SkipSpace(); - if (yyLex.Eos()) - return; - peek=yyLex.Peek(); - } - } - else // if (peek!=',' && peek !='(' && peek!='"' && peek!=aSeparatorChar) - { - yyLex.Mark(); - while (peek!=',' && !peek.IsSpace() && peek!=')' && peek!=']' && peek!='}' && peek!=aSeparatorChar) - { - yyLex.Inc(); - if (yyLex.Eos()) - break; - peek=yyLex.Peek(); - if ((peek==':')&&(aSeparatorChar!=':')) - { - yyLex.Inc(); - break; - } - } - - AddParamL(yyLex.MarkedToken()); - LOGTEXT2(_L8("normal parameter >%S<"),&iRxResults.Last()->iResultPtr); - if (yyLex.Eos()) - return; - // skip any whitespace and closing brackets - for (;;) - { - yyLex.SkipSpace(); - if (yyLex.Eos()) - return; - peek = yyLex.Peek(); - if (peek!=')') - break; - if (aReportLists) - { - AddParamL(KCloseBracket); - LOGTEXT2(_L8("list separator >%S<"),&iRxResults.Last()->iResultPtr); - } - yyLex.Inc(); - } - // Skip any following separator - if (peek==',' || peek==aSeparatorChar) - { - yyLex.Inc(); - yyLex.SkipSpace(); - if (yyLex.Eos()) - return; - peek=yyLex.Peek(); - } - } - } while (peek!=')'&& peek!=']'&& peek!='}'); - if (aReportLists && peek==')') - { - AddParamL(KCloseBracket); - LOGTEXT2(_L8("list separator >%S<"),&iRxResults.Last()->iResultPtr); - } - - } - -void CATBase::ChangeCallStatus(RMobileCall::TMobileCallStatus aCallStatus) -// -// This is called from a phone-based command as it is overloaded in CATCallAlterCommands. -// - { - if (iCallInfo->iMobileStatus != aCallStatus) - { - iCallInfo->iMobileStatus = aCallStatus; - if (aCallStatus == RMobileCall::EStatusIdle) - { - iCallInfo->iHookStatus = RCall::EHookStatusOn; - iPhoneGlobals->iNotificationStore->CheckNotification(iTelObject,EBecomeIdle); - } - else if (aCallStatus != RMobileCall::EStatusUnknown && aCallStatus != RMobileCall::EStatusRinging) - { - iCallInfo->iHookStatus = RCall::EHookStatusOff; - } - } - } - -void CATBase::ChangeLineStatus(RCall::TStatus aLineStatus) - { - iPhoneGlobals->iPhoneStatus.iLineStatus = aLineStatus; - } - -void CATBase::SetToNotInitialised() - { - iPhoneGlobals->iPhoneStatus.iMode = RPhone::EModeUnknown; - iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags = RPhone::KCapsUnknown; - iPhoneGlobals->iPhoneStatus.iInitStatus = EPhoneNotInitialised; - } - -void CATBase::StandardWriteCompletionHandler(TEventSource aSource,TInt aTimeOut) - { - __ASSERT_ALWAYS(aSource==EWriteCompletion,Panic(EATCommand_IllegalCompletionWriteExpected)); - iIo->SetTimeOut(this,aTimeOut * KOneSecondPause); - AddStdExpectStrings(); - } - -void CATBase::Write(const TDesC8& aCommand,TInt aTimeOut) - { - iTxBuffer.Format(KStringFormatString,&aCommand); - iIo->Write(this,iTxBuffer); - iIo->SetTimeOut(this,aTimeOut * KOneSecondPause); - } - -void CATBase::Write(const TDesC8& aCommand,TInt aTimeOut,TInt aValue) - { - iTxBuffer.Format(KStringAndIntegerFormatString,&aCommand,aValue); - iIo->Write(this,iTxBuffer); - iIo->SetTimeOut(this,aTimeOut * KOneSecondPause); - } - -void CATBase::Write(const TInt aTimeOut) -{ - iIo->Write(this,iTxBuffer); - iIo->SetTimeOut(this,aTimeOut * KOneSecondPause); -} - -void CATBase::WriteExpectingResults(const TDesC8& aCommand,TInt aTimeOut) - { - iIo->ClearBuffer(); - Write(aCommand,aTimeOut); - } - -void CATBase::AppendWildCardChar(TDes8& aString) -// -// A utility function to append a '*' to aString if there's not one already there -// - { - _LIT8(KAsterisk,"*"); - if(aString.Right(1)!=KAsterisk) - aString.Append(KAsterisk); - } - -void CATBase::AddCmsErrorExpectString() -// -// Add the "+CMS ERROR:" expect string -// - { - iCmsExpectString=iIo->AddExpectString(this,KCmsErrorString); - LOGTEXT(_L8("Added \"+CMS ERROR:\" string.")); - } - -void CATBase::RemoveCmsErrorExpectString() -// -// Remove the "+CMS ERROR:" expect string -// - { - iIo->RemoveExpectString(iCmsExpectString); - iCmsExpectString=NULL; - LOGTEXT(_L8("Removed \"+CMS ERROR:\" string.")); - } - -CTelObject* CATBase::Owner() - { - return iTelObject; - } - -TCallInfoTSY* CATBase::CallInfo() - { - return iCallInfo; - } - -// -// CATCommands class -// -CATCommands::CATCommands(CATIO* aIo, CTelObject* aTelObject, CATInit* aInit, CPhoneGlobals* aPhoneGlobals) - : CATBase(aIo,aTelObject,aPhoneGlobals), iInit(aInit) - {} - -void CATCommands::ConstructL() - { - iATSetToOnlineCommandMode=CATSetToOnlineCommandMode::NewL(iIo,iTelObject,iPhoneGlobals); - } - -CATCommands::~CATCommands() - { - delete iATSetToOnlineCommandMode; - } - -void CATCommands::ExecuteCommand(TTsyReqHandle aTsyReqHandle, TAny* aParams) -// -// Ensures that phone is initialised and not in on-line data mode -// - { - if (iPhoneGlobals->iPhoneStatus.iInitStatus==EPhoneNotInitialised) - { - iInit->StartInit(this,aTsyReqHandle,aParams); - } - else if (iPhoneGlobals->iPhoneStatus.iMode==RPhone::EModeOnlineData) - { - iATSetToOnlineCommandMode->StartEscapeSequence(this,aTsyReqHandle,aParams); - } - else - { - if (iPhoneGlobals->iEventSignalActive) - { - // Make sure request only completed if we have a valid request handle - // Signal that request could not be executed - if (aTsyReqHandle) - iTelObject->ReqCompleted(aTsyReqHandle, KErrInUse); - } - else - { - iPhoneGlobals->iEventSignalActive = ETrue; - Start(aTsyReqHandle, aParams); - } - } - } - -void CATCommands::ExecuteCommand(TTsyReqHandle aTsyReqHandle, TAny* aParams,TCallInfoTSY* aCallInfo) -// -// Overloaded function for CCallHayes-originated commands, so that the status can be -// changed for CCallHayes->iCallInfo -// - { - iCallInfo = aCallInfo; - ExecuteCommand(aTsyReqHandle,aParams); - } - -void CATCommands::CancelCommand(TTsyReqHandle aTsyReqHandle) - { - if(iInit->CheckActiveReqHandle(aTsyReqHandle)) - { - iInit->StopInit(aTsyReqHandle); - } - else if (iPhoneGlobals->iPhoneStatus.iMode==RPhone::EModeOnlineData) - { - iATSetToOnlineCommandMode->StopEscapeSequence(aTsyReqHandle); - } - else - { - Stop(aTsyReqHandle); - } - } - -void CATCommands::Complete(TInt aError,TEventSource /*aSource*/) -// -// Should be called by all Complete()'s before ReqCompleted() -// - { - LOGTEXT(_L8("CATCommands::Complete called")); - - if (aError==KErrTimedOut) - { - LOGTEXT(_L8("CATCommands::Complete KErrTimedOut error, setting EPhoneNotIntialised")); - iPhoneGlobals->iPhoneStatus.iInitStatus = EPhoneNotInitialised; - } - - // Clear the flow control flag to show no AT commands are writing to the - // serial port. - iPhoneGlobals->iEventSignalActive = EFalse; - - // Allow the CReceiveSmsQueue object to read PDUs from the phones memory, if needed - if(iPhoneGlobals->iReceiveSmsQueuePtr) - iPhoneGlobals->iReceiveSmsQueuePtr->ReadPDUFromPhone(); - - // Check the flow control flag, as the previous lines may have started off a - // AT command. - // If the flow control is clear then allow the Check ForChangeOfNetwork to have - // a go at updating its status and writing to the serial port. - if (!(iPhoneGlobals->iEventSignalActive)) - iPhoneGlobals->CheckForChangeOfNetwork(); - } +// 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: +// AT Command Base Class +// +// + +#include "PHONE.H" +#include "ATIO.H" +#include "mSLOGGER.H" +#include "ATINIT.H" +#include "ATESCAPE.H" +#include "LINE.H" +#include "NOTIFY.H" +#include "sms_rx_queue.h" // for CReceiveSmsQueue + +// Specific GSM Error String Response +_LIT8(KCmsErrorString,"+CMS ERROR:*"); + +// +// CATParamListEntry +// A pointer to a meaningful result in the received buffer from the modem +// +CATParamListEntry::CATParamListEntry(const TDesC8& aDes) : + iResultPtr(aDes) + { + } + +CATParamListEntry::~CATParamListEntry() + {} + +void CATParamListEntry::Deque() + { + iLink.Deque(); + } + +void CATParamListEntry::EntryValL(CATParamListEntry* aEntry,TInt& aValue) + { + if (aEntry==NULL) + User::Leave(KErrGeneral); + TLex8 lex(aEntry->iResultPtr); + (void)User::LeaveIfError(lex.Val(aValue)); + aEntry->Deque(); + delete aEntry; + } + +TInt CATParamListEntry::EntryValL(CATParamListEntry* aEntry) + { + TInt val; + EntryValL(aEntry,val); + return val; + } + + +// +// Async One Shot to call RelinquishOwnershipComplete(). +// If RelinquishOwnershipComplete() is called synchronously, it destroys the CATIO object +// before the latter has finished processing. +// +CCompleteRelinquish* CCompleteRelinquish::New(CTelObject* aTelObject) +// +// Create the Relinquish Complete async one shot +// + { + // The below TRAP is used to stop leavescan errors occurring. + // This is not the best solution, but I am pressed for time ;-( + CCompleteRelinquish* ptr=NULL; + TRAP_IGNORE(ptr=new(ELeave)CCompleteRelinquish(aTelObject)); + return ptr; + } + +CCompleteRelinquish::CCompleteRelinquish(CTelObject* aTelObject) +// +// C'tor +// + :CAsyncOneShot(CActive::EPriorityLow), iTelObject(aTelObject) + { + __DECLARE_NAME(_S("CCompleteRelinquish")); + } + + +CCompleteRelinquish::~CCompleteRelinquish() + { + Cancel(); + } + +void CCompleteRelinquish::RunL() +// +// Call RelinquishOwnershipCompleted() or RecoverDataPortAndRelinquishOwnershipCompleted() +// after CATIO has finished its processing +// + { + __ASSERT_ALWAYS(iPanicOccurred!=ENoPanicOccurred,Panic(EIllegalPanicOccurredValue)); + if (iPanicOccurred == EPanicOccurredWithoutDataPortLoan) + { + REINTERPRET_CAST(CCallBase*,iTelObject)->RelinquishOwnershipCompleted(KErrNone); + } + if (iPanicOccurred == EPanicOccurredDuringDataPortLoan) + { + REINTERPRET_CAST(CCallBase*,iTelObject)->RecoverDataPortAndRelinquishOwnershipCompleted(KErrNone); + } + delete this; + } +// +// The Command Base Class +// +CATBase::CATBase(CATIO* aIo, CTelObject* aTelObject,CPhoneGlobals* aPhoneGlobals) + : iIo(aIo),iPhoneGlobals(aPhoneGlobals),iComplete(NULL),iTelObject(aTelObject),iCallInfo(NULL) + { + iRxResults.SetOffset(_FOFF(CATParamListEntry,iLink)); + } + +CATBase::~CATBase() +// +// Assumes CATIO pointer is still valid +// + { + if(!iRxResults.IsEmpty()) + { + CATParamListEntry* entry; + TDblQueIter iter(iRxResults); + while (entry = iter++,entry!=NULL) + { + entry->Deque(); + delete entry; + } + } + } + +void CATBase::GenericEventSignal(TEventSource aEventSource, TInt aStatus) +// +// If an IO error has occurred, complete this ATBase-object with the error. +// + { + if (aStatus!=KErrNone) + { + LOGTEXT2(_L8("EventSignal received error status %d"),aStatus); + CompleteWithIOError(aEventSource,aStatus); + } + else + { + EventSignal(aEventSource); + } + } + +void CATBase::AddStdExpectStrings() + { + if (!iOKExpectString) + iOKExpectString=iIo->AddExpectString(this,KOkString); + if (!iErrorExpectString) + iErrorExpectString=iIo->AddExpectString(this,KErrorString); + } + + +TInt CATBase::ValidateExpectString() +/** + * New version ValidateExpectStringL which returns an error code + * as opposed to leaving. + * Use of this new code should hopefully remove alot of + * unesseccary TRAP harness in the TSY. + */ + { + TInt ret(KErrNone); + + if(iIo->FoundChatString()!=iOKExpectString) + { + if(iIo->FoundChatString()==iErrorExpectString) + { + LOGTEXT(_L8("Modem returned ERROR in response to command")); + ret=KErrGeneral; + } + else + { + LOGTEXT(_L8("Modem returned unexpected response to command")); + ret=KErrUnknown; + } + } + + return ret; + } + +void CATBase::RemoveStdExpectStrings() + { + LOGTEXT(_L8("RemoveStdExpectStrings()")); + iIo->RemoveExpectString(iOKExpectString); + iOKExpectString=NULL; + iIo->RemoveExpectString(iErrorExpectString); + iErrorExpectString=NULL; + } + +void CATBase::RemoveUnsolicitedStrings() + { + LOGTEXT(_L8("RemoveUnsolicitedStrings()")); + + _LIT8(KNetworkRegistration,"+CREG:"); // Network registration + _LIT8(KIncomingCallIndication,"RING"); // Normal Ring + _LIT8(KIncomingExtCallIndication,"+CRING:"); // Extended format call + _LIT8(KIncomingExtNTCallParameter,"REL"); // Non-Transparent parameter + _LIT8(KIncomingExtAlternatingCallParameter,"ALT"); // Unsupported Alternating parameter + _LIT8(KIncomingExtVoiceRelCallParameter,"VOICE/REL"); // NT Voice parameter + + if(!iRxResults.IsEmpty()) + { + TInt aQueueSteps = NULL; + CATParamListEntry* entry; + TDblQueIter iter(iRxResults); + // Step along the queue looking for an unsolicited strings + while (entry = iter++,entry!=NULL) + { + TPtrC8 aResult(entry->iResultPtr); + // If a match is found, we dequeue it and all its expected parameters + if (aResult==KIncomingCallIndication) // 0 Params + { + // Remove the "RING" + entry->Deque(); delete entry; + LOGTEXT2(_L8("Unsolicited >%S< Removed"),&aResult); + } + else if (aResult==KIncomingExtCallIndication) // 1/2 Params + { + // Remove the "+CRING:" + entry->Deque(); delete entry; entry = iter++; + LOGTEXT2(_L8("Unsolicited >%S< Removed"),&aResult); + // We know we should be getting at least one and maybee two parameters + TPtrC8 aFirstParameterResult(entry->iResultPtr); + if (aFirstParameterResult==KIncomingExtNTCallParameter + || aFirstParameterResult==KIncomingExtVoiceRelCallParameter + || aFirstParameterResult==KIncomingExtAlternatingCallParameter) + { + // We have an "ALT" or a "REL" so we have two parameters + entry->Deque(); delete entry; entry = iter++; + TPtrC8 aSecondParameterResult(entry->iResultPtr); + entry->Deque(); delete entry; // If recognised parameter - remove + LOGTEXT3(_L8("Unsolicited Parameter >%S %S< Removed"),&aFirstParameterResult,&aSecondParameterResult); aSecondParameterResult==KIncomingCallIndication; // Quick fix to remove unused parameters make warning + } + else + { + // We only have one parameter + entry->Deque(); delete entry; // If recognised parameter - remove + LOGTEXT2(_L8("Unsolicited Parameter >%S< Removed"),&aFirstParameterResult); + } + } + else if (aResult==KNetworkRegistration) // 2 Params + { + // Remove the "+CREG:" + entry->Deque(); delete entry; entry = iter++; + LOGTEXT2(_L8("Unsolicited >%S< Removed"),&aResult); + // Remove both parameters + TPtrC8 aFirstParameterResult(entry->iResultPtr); + entry->Deque(); delete entry; entry = iter++; + TPtrC8 aSecondParameterResult(entry->iResultPtr); + entry->Deque(); delete entry; + LOGTEXT3(_L8("Unsolicited Parameters >%S,%S< Removed"),&aFirstParameterResult,&aSecondParameterResult); aFirstParameterResult==KIncomingCallIndication; aSecondParameterResult==KIncomingCallIndication; // Quick fix to remove unused parameters make warning + } + + // Increment the queue step counter + else aQueueSteps++; + } + // Now we have to retrace the list, ignoring dequeued entries + for (TInt aLoop=NULL;aLoop(aCATBase); + TDblQueIter iter(p->iRxResults); + CATParamListEntry* entry=iter++; + while (entry!=NULL) + { + entry->Deque(); + delete entry; + entry=iter++; + } + } + +void CATBase::RxResultsPushLC() + { + TCleanupItem cleanup(CleanupRxResults,this); + CleanupStack::PushL(cleanup); + } + +void CATBase::ParseBufferLC(TBool aReportLists, TUint aSeparatorChar) +// +// Parses buffer. Treats aSeparatorChar like a comma +// + { + LOGTEXT(_L8("Parse the Buffer List")); + + if (iIo->CurrentLine()==KOkString) + iIo->ClearCurrentLine(); // remove trailing "OK" + + iBuffer.Set(iIo->Buffer()); + iIo->ClearBuffer(); + + ParseLC(aReportLists, aSeparatorChar); + } + +void CATBase::ParseLineLC(TBool aReportLists, TUint aSeparatorChar) +// +// Parses current line. Treats aSeparatorChar like a comma +// + { + LOGTEXT(_L8("Parse the current line")); + + iBuffer.Set(iIo->CurrentLine()); + iIo->ClearCurrentLine(); + ParseLC(aReportLists, aSeparatorChar); + } + +void CATBase::AddParamL(const TDesC8 &aPtr) + { + CATParamListEntry* aParamListEntry = new (ELeave) CATParamListEntry(aPtr); + iRxResults.AddLast(*aParamListEntry); + } + +void CATBase::ParseLC(TBool aReportLists, TUint aSeparatorChar) +// +// Does the actual parsing of iBuffer, set up from ParseLineLC or ParseBufferLC +// + { +_LIT8(KOpenBracket, "("); +_LIT8(KCloseBracket, ")"); + +#ifdef __LOGDEB__ + TPtrC8 buf(iBuffer); + if (buf.Length()>180) + { + buf.Set(buf.Left(180)); + LOGTEXT2(_L8("buffer to parse >%S< and so on ..."),&buf); + } + else + LOGTEXT2(_L8("buffer to parse >%S<"),&buf); +#endif + + RxResultsPushLC(); + TLex8 yyLex(iBuffer); + + // Move cursor past any spaces or open brackets + yyLex.SkipSpace(); + TChar peek=yyLex.Peek(); + if (peek=='(' || peek=='[' || peek=='{') + yyLex.Inc(); + + if (aReportLists && peek=='(') + { + AddParamL(KOpenBracket); + LOGTEXT2(_L8("list separator >%S<"),&iRxResults.Last()->iResultPtr); + } + do + { + // Skip all space and opening brackets + for (;;) + { + yyLex.SkipSpace(); + if (yyLex.Eos()) + return; + peek = yyLex.Peek(); + if (peek!='(') + break; + if (aReportLists) + { + AddParamL(KOpenBracket); + LOGTEXT2(_L8("list separator >%S<"),&iRxResults.Last()->iResultPtr); + } + yyLex.Inc(); + } + + if (peek=='"') // start of quoted string + { + yyLex.Inc(); // step over the quote + yyLex.Mark(); + while (!yyLex.Eos()) + { + peek=yyLex.Peek(); + if (peek=='"') + break; + yyLex.Inc(); + } + + AddParamL(yyLex.MarkedToken()); + LOGTEXT2(_L8("quoted parameter >%S<"),&iRxResults.Last()->iResultPtr); + if (yyLex.Eos()) + return; + + // Skip all space and closing brackets + for (;;) + { + yyLex.Inc(); + yyLex.SkipSpace(); + if (yyLex.Eos()) + return; + peek = yyLex.Peek(); + if (peek!=')') + break; + if (aReportLists) + { + AddParamL(KCloseBracket); + LOGTEXT2(_L8("list separator >%S<"),&iRxResults.Last()->iResultPtr); + } + } + + // Skip any following separator + if (peek==',' || peek==aSeparatorChar) + { + yyLex.Inc(); + yyLex.SkipSpace(); + if (yyLex.Eos()) + return; + peek=yyLex.Peek(); + } + } + else // if (peek!=',' && peek !='(' && peek!='"' && peek!=aSeparatorChar) + { + yyLex.Mark(); + while (peek!=',' && !peek.IsSpace() && peek!=')' && peek!=']' && peek!='}' && peek!=aSeparatorChar) + { + yyLex.Inc(); + if (yyLex.Eos()) + break; + peek=yyLex.Peek(); + if ((peek==':')&&(aSeparatorChar!=':')) + { + yyLex.Inc(); + break; + } + } + + AddParamL(yyLex.MarkedToken()); + LOGTEXT2(_L8("normal parameter >%S<"),&iRxResults.Last()->iResultPtr); + if (yyLex.Eos()) + return; + // skip any whitespace and closing brackets + for (;;) + { + yyLex.SkipSpace(); + if (yyLex.Eos()) + return; + peek = yyLex.Peek(); + if (peek!=')') + break; + if (aReportLists) + { + AddParamL(KCloseBracket); + LOGTEXT2(_L8("list separator >%S<"),&iRxResults.Last()->iResultPtr); + } + yyLex.Inc(); + } + // Skip any following separator + if (peek==',' || peek==aSeparatorChar) + { + yyLex.Inc(); + yyLex.SkipSpace(); + if (yyLex.Eos()) + return; + peek=yyLex.Peek(); + } + } + } while (peek!=')'&& peek!=']'&& peek!='}'); + if (aReportLists && peek==')') + { + AddParamL(KCloseBracket); + LOGTEXT2(_L8("list separator >%S<"),&iRxResults.Last()->iResultPtr); + } + + } + +void CATBase::ChangeCallStatus(RMobileCall::TMobileCallStatus aCallStatus) +// +// This is called from a phone-based command as it is overloaded in CATCallAlterCommands. +// + { + if (iCallInfo->iMobileStatus != aCallStatus) + { + iCallInfo->iMobileStatus = aCallStatus; + if (aCallStatus == RMobileCall::EStatusIdle) + { + iCallInfo->iHookStatus = RCall::EHookStatusOn; + iPhoneGlobals->iNotificationStore->CheckNotification(iTelObject,EBecomeIdle); + } + else if (aCallStatus != RMobileCall::EStatusUnknown && aCallStatus != RMobileCall::EStatusRinging) + { + iCallInfo->iHookStatus = RCall::EHookStatusOff; + } + } + } + +void CATBase::ChangeLineStatus(RCall::TStatus aLineStatus) + { + iPhoneGlobals->iPhoneStatus.iLineStatus = aLineStatus; + } + +void CATBase::SetToNotInitialised() + { + iPhoneGlobals->iPhoneStatus.iMode = RPhone::EModeUnknown; + iPhoneGlobals->iPhoneStatus.iDataAndFaxFlags = RPhone::KCapsUnknown; + iPhoneGlobals->iPhoneStatus.iInitStatus = EPhoneNotInitialised; + } + +void CATBase::StandardWriteCompletionHandler(TEventSource aSource,TInt aTimeOut) + { + __ASSERT_ALWAYS(aSource==EWriteCompletion,Panic(EATCommand_IllegalCompletionWriteExpected)); + iIo->SetTimeOut(this,aTimeOut * KOneSecondPause); + AddStdExpectStrings(); + } + +void CATBase::Write(const TDesC8& aCommand,TInt aTimeOut) + { + iTxBuffer.Format(KStringFormatString,&aCommand); + iIo->Write(this,iTxBuffer); + iIo->SetTimeOut(this,aTimeOut * KOneSecondPause); + } + +void CATBase::Write(const TDesC8& aCommand,TInt aTimeOut,TInt aValue) + { + iTxBuffer.Format(KStringAndIntegerFormatString,&aCommand,aValue); + iIo->Write(this,iTxBuffer); + iIo->SetTimeOut(this,aTimeOut * KOneSecondPause); + } + +void CATBase::Write(const TInt aTimeOut) +{ + iIo->Write(this,iTxBuffer); + iIo->SetTimeOut(this,aTimeOut * KOneSecondPause); +} + +void CATBase::WriteExpectingResults(const TDesC8& aCommand,TInt aTimeOut) + { + iIo->ClearBuffer(); + Write(aCommand,aTimeOut); + } + +void CATBase::AppendWildCardChar(TDes8& aString) +// +// A utility function to append a '*' to aString if there's not one already there +// + { + _LIT8(KAsterisk,"*"); + if(aString.Right(1)!=KAsterisk) + aString.Append(KAsterisk); + } + +void CATBase::AddCmsErrorExpectString() +// +// Add the "+CMS ERROR:" expect string +// + { + iCmsExpectString=iIo->AddExpectString(this,KCmsErrorString); + LOGTEXT(_L8("Added \"+CMS ERROR:\" string.")); + } + +void CATBase::RemoveCmsErrorExpectString() +// +// Remove the "+CMS ERROR:" expect string +// + { + iIo->RemoveExpectString(iCmsExpectString); + iCmsExpectString=NULL; + LOGTEXT(_L8("Removed \"+CMS ERROR:\" string.")); + } + +CTelObject* CATBase::Owner() + { + return iTelObject; + } + +TCallInfoTSY* CATBase::CallInfo() + { + return iCallInfo; + } + +// +// CATCommands class +// +CATCommands::CATCommands(CATIO* aIo, CTelObject* aTelObject, CATInit* aInit, CPhoneGlobals* aPhoneGlobals) + : CATBase(aIo,aTelObject,aPhoneGlobals), iInit(aInit) + {} + +void CATCommands::ConstructL() + { + iATSetToOnlineCommandMode=CATSetToOnlineCommandMode::NewL(iIo,iTelObject,iPhoneGlobals); + } + +CATCommands::~CATCommands() + { + delete iATSetToOnlineCommandMode; + } + +void CATCommands::ExecuteCommand(TTsyReqHandle aTsyReqHandle, TAny* aParams) +// +// Ensures that phone is initialised and not in on-line data mode +// + { + if (iPhoneGlobals->iPhoneStatus.iInitStatus==EPhoneNotInitialised) + { + iInit->StartInit(this,aTsyReqHandle,aParams); + } + else if (iPhoneGlobals->iPhoneStatus.iMode==RPhone::EModeOnlineData) + { + iATSetToOnlineCommandMode->StartEscapeSequence(this,aTsyReqHandle,aParams); + } + else + { + if (iPhoneGlobals->iEventSignalActive) + { + // Make sure request only completed if we have a valid request handle + // Signal that request could not be executed + if (aTsyReqHandle) + iTelObject->ReqCompleted(aTsyReqHandle, KErrInUse); + } + else + { + iPhoneGlobals->iEventSignalActive = ETrue; + Start(aTsyReqHandle, aParams); + } + } + } + +void CATCommands::ExecuteCommand(TTsyReqHandle aTsyReqHandle, TAny* aParams,TCallInfoTSY* aCallInfo) +// +// Overloaded function for CCallHayes-originated commands, so that the status can be +// changed for CCallHayes->iCallInfo +// + { + iCallInfo = aCallInfo; + ExecuteCommand(aTsyReqHandle,aParams); + } + +void CATCommands::CancelCommand(TTsyReqHandle aTsyReqHandle) + { + if(iInit->CheckActiveReqHandle(aTsyReqHandle)) + { + iInit->StopInit(aTsyReqHandle); + } + else if (iPhoneGlobals->iPhoneStatus.iMode==RPhone::EModeOnlineData) + { + iATSetToOnlineCommandMode->StopEscapeSequence(aTsyReqHandle); + } + else + { + Stop(aTsyReqHandle); + } + } + +void CATCommands::Complete(TInt aError,TEventSource /*aSource*/) +// +// Should be called by all Complete()'s before ReqCompleted() +// + { + LOGTEXT(_L8("CATCommands::Complete called")); + + if (aError==KErrTimedOut) + { + LOGTEXT(_L8("CATCommands::Complete KErrTimedOut error, setting EPhoneNotIntialised")); + iPhoneGlobals->iPhoneStatus.iInitStatus = EPhoneNotInitialised; + } + + // Clear the flow control flag to show no AT commands are writing to the + // serial port. + iPhoneGlobals->iEventSignalActive = EFalse; + + // Allow the CReceiveSmsQueue object to read PDUs from the phones memory, if needed + if(iPhoneGlobals->iReceiveSmsQueuePtr) + iPhoneGlobals->iReceiveSmsQueuePtr->ReadPDUFromPhone(); + + // Check the flow control flag, as the previous lines may have started off a + // AT command. + // If the flow control is clear then allow the Check ForChangeOfNetwork to have + // a go at updating its status and writing to the serial port. + if (!(iPhoneGlobals->iEventSignalActive)) + iPhoneGlobals->CheckForChangeOfNetwork(); + }