diff -r 000000000000 -r 3553901f7fa8 telephonyserverplugins/multimodetsy/test/Te_LoopBack/Te_LoopBackATIO.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/telephonyserverplugins/multimodetsy/test/Te_LoopBack/Te_LoopBackATIO.CPP Tue Feb 02 01:41:59 2010 +0200 @@ -0,0 +1,692 @@ +// 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: +// This file defines classes to handle serial port input/output and implement +// the "expect string" handling. These "expect strings" are strings +// that are expected to be received on the serial line with the +// relevant callbacks. This is a portion of code that has been reused +// from the GSM TSY. In this component, it is a bit like taking a +// sledgehammer to crack a nut, but it does do the job. +// +// + +/** + @file + @note There are mulitple classes implemented in this file. + @note These classes are CCompletionEntry and CATIO +*/ + +#include "Te_LoopBackATIO.H" +#include "Te_LoopBackATBASE.H" +#include "Te_LoopBackSLOGGER.H" + +CCompletionEntry* CCompletionEntry::NewL(CCommChatString* aCs, CATBase* aAtCommand) +/** + * This method creates an instance of CCompletionEntry. + * + * @param aCS: pointer to expected string response from the GSM TSY. + * @param aAtCommand: pointer to the script engine processing the line of script. + * @leave Leaves if out-of-memory. + * @return pointer to the instance of "CCompletionEntry". + */ + { + return new(ELeave) CCompletionEntry(aCs,aAtCommand); + } + +CCompletionEntry::CCompletionEntry(CCommChatString* aCs, CATBase* aAtCommand) : iCs(aCs), iAtCommand(aAtCommand) +/** + * This method is the constructor for CCompletionEntry. + * + * @param aCS: pointer to expected string response from the GSM TSY. + * @param aAtCommand: pointer to the script engine processing the line of script. + * @note Initializes private data "iCs" and "iAtCommand" to received parameters. + */ + {} + +CCompletionEntry::~CCompletionEntry() +/** + * This method is the Destructor for CCompletionEntry. + */ + {} + +// +// CATIo +// +CATIO* CATIO::NewL(const TDesC& aCsy, const TDesC& aPort) +/** + * 2 Phase Constructor + * + * This method creates an instance of CATIO. + * + * @param aCsy: reference to a DLL name of the CSY. + * @param aPort: reference to the port name. + * @leave Leaves if out-of-memory. + * @return pointer to the instance of "CATIO". + */ + { + CATIO* atIo=new(ELeave) CATIO(); + CleanupStack::PushL(atIo); + atIo->ConstructL(aCsy,aPort); + CleanupStack::Pop(); + return atIo; + } + +CATIO::CATIO() +/** + * This method is the constructor for CATIO. Private data is initialized and + * a new value for the byte offset into the class for member data iLink is retrieved. + */ + { + __DECLARE_NAME(_S("CATIO")); + iExpectList.SetOffset(_FOFF(CCompletionEntry,iLink)); + iReadPending=EFalse; + iWritePending=EFalse; + iWaitTimerPending=EFalse; + } + +void CATIO::ConstructL(const TDesC& aCsy, const TDesC& aPort) +/** + * This method is used to implement the 2 Phase Constructor for CATIO. + * This method sets up new iCommReader and iCommWriter data for CATIO. + * It also sets up a new iChat for and creates the buffer for iChat. + * The Comm port indicated by the DLL and port name is then opened with + * as a shared resource. + * + * @param aCsy: reference to a DLL name of the CSY. + * @param aPort: reference to the port name. + * @leave Leaves if comm port can not be opened or if out-of-memory when creating other objects. + * @return pointer to the instance of "CATIO". + */ + { + CommConstructL(KCommReadPriority,KCommWritePriority); + iChat = new (ELeave) CCommChatter(this, KChatterPriority); + iChat->CreateL(KChatBufferSize); + User::LeaveIfError(CommOpen(aCsy, aPort, ECommShared)); + iChatStringFound= new(ELeave) CArrayFixFlat(5); + } + +CATIO::~CATIO() +/** + * This method is used to delete the instantion of CATIO. This method + * initiates the removal of the intantiations of iChatStringFound and iChat + * that were created for this CATIO. + * + * @param None. + * @return None. + * @note None. + */ + { + delete iChatStringFound; + delete iChat; + } + +TInt CATIO::ConfigurePort(TCommConfig aConfiguration) +/** + * This method is used to update the comm port configuration with data received + * from the input parameter. + * + * @param aConfiguration: reference to port configuration data. + * @return error value for attempt to configure port. + */ + { + TInt ret; + TCommConfig cbuf; + TCommConfigV01 &cfg=cbuf(); + iCommPort.Config(cbuf); // Get the Configuration + + // overwrite port configuration with input configuration + TCommConfigV01 &newCfg=aConfiguration(); + cfg.iRate=newCfg.iRate; + cfg.iDataBits=newCfg.iDataBits; + cfg.iStopBits=newCfg.iStopBits; + cfg.iParity=newCfg.iParity; + cfg.iHandshake=newCfg.iHandshake; + ret = iCommPort.SetConfig(cbuf); // Set the Configuration + if(ret!=KErrNone) + { + LOGTEXT2(_L8("CATIO:\tError %d configuring port"),ret); + return ret; + } + return KErrNone; + } + +TInt CATIO::Start(CATBase* aCompletionClass) +/** + * This method is used to make sure the comm port is ready and a read is outstanding on + * the comm port. This is done by making sure the comm port is initialized for both read + * and write capabilities. After the comm port is initialized for read and write, a read + * is posted to the comm port to have a read outstanding for CATIO. + * + * @param aCompletionClass: pointer to a CATBase class indicating port and data. + * @return error value for attempt to read port. + */ + { + iControllingClass=aCompletionClass; + CommReadReady(); + LOGTEXT(_S8("CATIO::Start() - ReadReady Completed")); + CommWriteReady(); + LOGTEXT(_S8("CATIO::Start() - WriteReady Completed")); + return Read(); + } + +void CATIO::GetExcessData(TDes8& aBuffer) +/** + * This function is currently not used by the Etel regression test harness. + */ + { + TPtrC8 des(iRxBuf.Ptr()+iRxBufOffset, iRxBuf.Length()-iRxBufOffset); + aBuffer.Copy(des); + } + +void CATIO::MarkRxBuffer(TInputBufferMark& aBufferMarker) +/** + * Set markers for last character received from the GSM TSY. + * + * @param aBufferMark: reference to markers in buffer for last character received from comm port. + * @return None. + */ + { + iChat->GetChatBufferMarker(aBufferMarker); + } + +TPtrC8 CATIO::GetRxBufferLC(TInputBufferMark& aBufferMarker) +/** + * This function is currently not used by the Etel regression test harness. + * + * @note: This function is designed to return a descriptor for the buffer between the + * marker passed as a parameter and the current append marker. + */ + { + return iChat->GetChatBufferLC(aBufferMarker); + } + +void CATIO::CommReadComplete(TInt aStatus) +/** + * This method is invoked by the RunL of the active object to complete a read. + * When read complete is for KErrCommsLineFail, then a check will be made to make sure + * there have been 2 KErrCommsLineFail's in succession before signaling the line error. + * When no errors or 1st KErrCommsLineFail, call ProcessReadCharsL to process the + * characters read from the comm port. If an error occurs processing the comm port + * read buffer characters, the ProcessReadCharsL method will leave and will be trapped + * in this function and the call is canceled. + * + * @param aStatus: status from server indicating why read completed. + * @return None. + */ + { + LOGTEXT(_S8("CATIO Read Completion")); + __ASSERT_ALWAYS(iReadPending,HayesPanic(EATCommand_IllegalCompletionReadNotExpected)); +// if(!iReadPending) + // + // { + // SignalCommandsWithError(KErrIllegalReadComplete); + // return; + // } + if (aStatus==KErrCommsLineFail) + { + if (iSecondChanceForCommsError++!=1) + aStatus=KErrNone; // only signal error if get 2 KErrCommsLineFail's in succession + else + iSecondChanceForCommsError=0; + } + if (aStatus!=KErrNone) + { + SignalCommandsWithError(aStatus); + return; + } + iReadPending = EFalse; + TRAPD(ret,ProcessReadCharsL()); + if(ret!=KErrNone) + { + Cancel(); // This error cannot be related to a command - so they'll all be cleaned up. + iChat->DeleteAllAndStop(); + } + } + +void CATIO::SignalCommandsWithError(TInt aStatus) +// +// Complete all current AT commands with the error and call the error handler +// +/** + * This method is invoked when an error is detected. All current strings with the + * error are removed and iControllingClass->GenericEventSignal method is called to + * signal EReadCompletion. + * + * @param aStatus: status indicating error of the read. + * @return None. + */ + { + LOGTEXT2(_L8("Received an error of %d"),aStatus); + Cancel(); + CCompletionEntry* ce; + TDblQueIter iter(iExpectList); + while (ce = iter, ce!=NULL) + { + ce->iAtCommand->GenericEventSignal(EReadCompletion,aStatus); + iter.SetToLast(); + CCompletionEntry* removeSimilar; + while (removeSimilar=iter--, removeSimilar!=ce) + { + if(removeSimilar->iAtCommand==ce->iAtCommand) + { + iChat->RemoveString(removeSimilar->iCs); + delete removeSimilar->iCs; + removeSimilar->iLink.Deque(); + delete removeSimilar; + } + } + iChat->RemoveString(ce->iCs); + delete ce->iCs; + ce->iLink.Deque(); + delete ce; + iter.SetToFirst(); + } + if(iControllingClass!=NULL) + iControllingClass->GenericEventSignal(EReadCompletion,aStatus); + } + +void CATIO::ProcessReadCharsL() +/** + * This method processes the characters read from the comm port. It uses + * these characters to lookup any string from the script to complete. + * If the string to complete is not found, this method will leave. + * If the string to complete is found, a read complete is signaled and + * another read is queued. + * + * @leave Leaves if string to complete is not found in the expected list. + */ + { + LOGTEXT3(_L8("Rx:\t(%d) %S"),iRxBuf.Length(),&iRxBuf); + LOGTEXTREL2(_L8("Rx:\t%S"),&iRxBuf); + + TBool hitFlag=EFalse; + TInt len; + + for (iRxBufOffset=0; iRxBufOffsetAddCharL(iRxBuf[iRxBufOffset]); +// Check for hits and one up-call per hit NOW + if((len=iChatStringFound->Count())>0) + { + for(TInt i=0;i iter(iExpectList); + TBool aFoundFlag=EFalse; + while (ce = iter++, ce!=NULL) + { + if(ce->iCs==iChatStringFound->At(i)) + { + iCurrentFoundChatString=ce->iCs; + ce->iAtCommand->GenericEventSignal(EReadCompletion,KErrNone); + aFoundFlag=ETrue; + break; + } + } + if(!aFoundFlag) + { + LOGTEXT(_S8("CATIO Internal Error - Chat String signalled, but not found")); + User::Leave(KErrGeneral); + } + } + iChatStringFound->Delete(0,iChatStringFound->Count()); + } + } + if(hitFlag) + { + //iReadPending=EFalse; + Read(); // Queue Another... + } + else + { + iReadPending = ETrue; + CommReadOneOrMore(iRxBuf); + } + } + +CCommChatString* CATIO::FoundChatString() +/** + * This returns a pointer to the string from the script to complete. + * + * @param None. + * @return pointer to CComChatString containing string to complete.. + */ + { + return iCurrentFoundChatString; + } + +CCommChatString* CATIO::AddExpectString(CATBase* aATBase, const TDesC8& aString) +/** + * This method is used to instantiate a CCompletionEntry object with a + * CCommChatString object containing the expected string to complete the + * string from the GSM TSY. This CCompletionEntry is then added to + * the end of the expected list of strings from the GSM TSY. + * + * @param aATBase: pointer to the script engine processing the line of script. + * @param aString: reference to the expected string for aATBase to be returned from the GSM TSY. + * @return pointer to the chat string used in the instatiated CCompletionEntry. + */ + { + CCommChatString* cs=iChat->AddString(aString); + CCompletionEntry* completionEntry=NULL; + TRAP_IGNORE(completionEntry=CCompletionEntry::NewL(cs,aATBase)); // TRAP but ignore error + if(completionEntry) + iExpectList.AddLast(*completionEntry); + return cs; + } + +void CATIO::RemoveExpectString(CCommChatString* aExpectString) +/** + * This method uses the CCommChatString input parameter to remove a single + * CCompletionEntry from the list of expected completion strings. + * + * @param aExpectString: reference to the string in the list of expected string returned from the GSM TSY. + */ + { +// Find the AT Command to complete + CCompletionEntry* ce; + TDblQueIter iter(iExpectList); + while (ce = iter++, ce!=NULL) + { + if(ce->iCs==aExpectString) + { + iChat->RemoveString(ce->iCs); + delete ce->iCs; + ce->iLink.Deque(); + delete ce; + break; + } + } + } + +void CATIO::RemoveExpectStrings(CATBase* aATBase) +/** + * This method uses the CATBase input parameter to remove all of the + * CCompletionEntry(s) that have the same CATBase-derived callback class + * from the list of expected completion strings. + * + * @param aTBase: reference to the string in the list of expected string returned from the GSM TSY. + */ + { +// Find the AT Command to complete + CCompletionEntry* ce; + TDblQueIter iter(iExpectList); + while (ce = iter++, ce!=NULL) + { + if(ce->iAtCommand==aATBase) + { + iChat->RemoveString(ce->iCs); + delete ce->iCs; + ce->iLink.Deque(); + delete ce; + } + } + } + +void CATIO::CommWriteComplete(TInt aStatus) +/** + * This method is used to indicate a write to the comm port has completed. + * The timer is stopped and if a write is NOT pending, then PANIC. + * Set the write pending flag to EFalse and signal the write completion event + * with the status from the input parameter. + * + * @param aStatus: status indicating reason for write complete. + */ + { + LOGTEXT(_S8("CATIO Comm Write Completion")); + iChat->StopTimer(); + __ASSERT_ALWAYS(iWritePending,HayesPanic(EATCommand_IllegalCompletionWriteNotExpected)); + iWritePending=EFalse; + iWriteCommand->GenericEventSignal(EWriteCompletion,aStatus); + } + +void CATIO::ChatStringMatchL(CCommChatString* aCs) +/** + * This method is used to append the input string onto a list of found strings. + * + * @param aCs: pointer to the chat string matched. + * @leave Leaves if can not place string on end of found string list. + */ + { + LOGTEXT(_S8("CATIO Found Match.")); + iStringFound=ETrue; + iChatStringFound->AppendL(aCs); + } + +void CATIO::ChatTimeout() +/** + * This method is used to indicate a chat time-out has completed. + * If a timer is NOT pending, then PANIC. When the timer is pending, + * set the timer pending flag to EFalse and signal the timeout completion event. + */ + { + LOGTEXT(_S8("CATIO Chat Time-out Completion")); + if(iWaitTimerPending) + { + iWaitTimerPending=EFalse; + iTimeOutCommand->GenericEventSignal(ETimeOutCompletion,KErrNone); + } + else + HayesPanic(EATCommand_IllegalWaitCompletion); + } + +void CATIO::SetTimeOut(CATBase* aCompletionClass, TUint aTimePeriodMillisec) +/* + * This method starts the timer with the command in the input aCompletionClass + * for the input specified period. The indicater for timer pending is set to ETrue. + * + * @param aCompletionClass: pointer to object containing the time-out command. + * @param aTimePeriodMillisec: time-out period in milliseconds. + */ + { + iTimeOutCommand=aCompletionClass; + iChat->StartTimer(aTimePeriodMillisec*1000); + iWaitTimerPending=ETrue; + } + +TInt CATIO::Read() +/* + * This method attempts to read from the comm port only if there is currently + * not a read pending. If a read is pending, this method simply returns without + * attempting a read. If no read is pending, this routing attempts to read as + * much data as is ready up to the maximum length specified in the descriptor, iRxBuf. + * The data is read into the iRxBuf. + */ + { + if(iReadPending==EFalse) + { + iReadPending=ETrue; + iStringFound=EFalse; + CommReadOneOrMore(iRxBuf); + iRxBufOffset = 0; + LOGTEXT(_S8("CATIO Queued a Read")); + } + return KErrNone; + } + +TInt CATIO::Write(CATBase* aCompletionClass, const TDesC8& aString) +/* + * This method attempts to write the input data into comm port using the + * write command in the input aCompletionClass. + * + * @param aCompletionClass: pointer to object containing function to call when the write completes. + * @param aString, a descriptor reference containing the data to be written to the port. + */ + { + iWriteCommand=aCompletionClass; + iWritePending=ETrue; + CommWrite(aString); + LOGTEXT2(_L8("Tx:\t%S"),&aString); + LOGTEXTREL2(_L8("Tx:\t%S"),&aString); + LOGTEXT(_S8("CATIO Queued a Transmission")); + return KErrNone; + } + +TBool CATIO::RWPending() +/* + * This method returns to the caller a boolean indicating True when + * either a Write is Pending OR a ReadPending is pending. + * + * @return Boolean indicating either a Write is Pending OR a Read is Pending. + */ + { + return (iWritePending)||(iReadPending); + } + +TBool CATIO::ReadPending() +/* + * This method returns to the caller a boolean indicating True when + * a ReadPending is pending. + * + * @return Boolean indicating if a Read is Pending. + */ + { + return iReadPending; + } + +void CATIO::Disconnect() +/** + * This function is currently not used by the Etel regression test harness. + */ + { + TCommConfig cbuf; + TCommConfigV01 &cfg=cbuf(); + iCommPort.Config(cbuf); + cfg.iHandshake = KConfigFreeRTS | KConfigFreeDTR; + iCommPort.SetConfig(cbuf); + iCommPort.SetSignalsToSpace(KSignalRTS | KSignalDTR); + CommClose(); + } + +void CATIO::Cancel() +/** + * This function is currently not used by the Etel regression test harness. + */ + { + LOGTEXT(_S8("CATIO CATIO:\tCancel called")); + CommCancel(); + iReadPending = EFalse; + iWritePending = EFalse; + iChat->StopTimer(); + } + +void CATIO::WriteAndTimerCancel(CATBase* aATBase) +/** + * This method is used by the caller to either cancel a write command or stop a timer. + * The action to be taken is determined by the command type received as a parameter. + * + * @param aATBase: pointer to the command type to be processed. + */ + { + if (aATBase==iWriteCommand) + { + CommWriteCancel(); + } + if (aATBase==iTimeOutCommand) + { + iChat->StopTimer(); + } + } + +void CATIO::WriteAndTimerCancelAll() +/** + * This function is currently not used by the Etel regression test harness. + */ + { + CommWriteCancel(); + iChat->StopTimer(); + } + +void CATIO::DropDtr() +/** + * This function is currently not used by the Etel regression test harness. + */ + { + LOGTEXT(_S8("CATIO Dropping DTR")); + iCommPort.SetSignals(0,KSignalDTR); + } + +void CATIO::RaiseDTR() +/** + * This function is currently not used by the Etel regression test harness. + */ + { + LOGTEXT(_S8("CATIO Raising DTR")); + iCommPort.SetSignals(KSignalDTR,0); + } + +void CATIO::ResetReadAndWriteBuffers() +/** + * This function is currently not used by the Etel regression test harness. + */ + { + iCommPort.ResetBuffers(); + } + +TInt CATIO::GetSizeOfRxBuffer() +/** + * This function is currently not used by the Etel regression test harness. + */ + { + return iCommPort.QueryReceiveBuffer(); + } + +TUint CATIO::Signals() +/** + * This function is currently not used by the Etel regression test harness. + */ + { + return iCommPort.Signals(); + } + +void CATIO::DropRTS() +/** + * This function is currently not used by the Etel regression test harness. + */ + { + LOGTEXT(_S8("CATIO Dropping RTS")); + iCommPort.SetSignals(0,KSignalRTS); + } + +void CATIO::RaiseRTS() +/** + * This function is currently not used by the Etel regression test harness. + */ + { + LOGTEXT(_S8("CATIO Raising RTS")); + iCommPort.SetSignals(KSignalRTS,0); + } + +void CATIO::SignalMark (TUint aSignal) +/** + * This method is used by the caller on the emulator side to assert signals. + * + * @param aSignal: integer indicating the signal to assert. + */ + { + LOGTEXT2(_L8("CATIO CATIO::SignalSet(%x)"),aSignal); + iCommPort.SetSignalsToMark(aSignal); + } + +void CATIO::SignalSpace (TUint aSignal) +/** + * This method is used by the caller on the emulator side to deassert signals. + * + * @param aSignal: integer indicating the signal to deassert. + */ + { + LOGTEXT2(_L8("CATIO CATIO::SignalClear(%x)"),aSignal); + iCommPort.SetSignalsToSpace (aSignal); + }