telephonyserverplugins/multimodetsy/test/Te_LoopBack/Te_LoopBackScriptEng.cpp
changeset 0 3553901f7fa8
equal deleted inserted replaced
-1:000000000000 0:3553901f7fa8
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // This file contains the scripting engine which processes a given script on demand.  It
       
    15 // uses services from the ATBase Class and the CATio Class.  All commands from the enumeration
       
    16 // TScriptCommands must be represented in the switch statement in the method ProcessScriptLine.
       
    17 // Any command not represented is ignored.
       
    18 // Scripting Engine Code
       
    19 // 
       
    20 //
       
    21 
       
    22 /**
       
    23  @file
       
    24 */
       
    25 
       
    26 #include "Te_LoopBackScriptEng.h"
       
    27 #include "Te_LoopBackrestartsignal.h"
       
    28 
       
    29 #define EForever (1==1)
       
    30 
       
    31 const TInt KStandardTxTimeout=5000;	// Five seconds
       
    32 
       
    33 // A completion signal that can be passed through the error channel without ambiguity
       
    34 // I.e. any non-zero positive number
       
    35 const TInt KScriptCompletionSignal=99;
       
    36 
       
    37 CATScriptEng::CATScriptEng()
       
    38 /**
       
    39  * The standard constructor for this class for scripts without a variable delay.
       
    40  */
       
    41 	{}
       
    42 
       
    43 CATScriptEng::CATScriptEng(TInt aVarDelay) : iDelay(aVarDelay)
       
    44 /**
       
    45  * The constructor for this class for scripts with a variable delay.
       
    46  */
       
    47 	{}
       
    48 
       
    49 CATScriptEng::~CATScriptEng()
       
    50 /**
       
    51  * The standard destructor for this class.
       
    52  */
       
    53 	{
       
    54 	delete iRestartSignal;
       
    55 	}
       
    56 
       
    57 void CATScriptEng::ConstructL()
       
    58 /**
       
    59  * The second stage contructor for the CATScriptEngClass.  It simply calls the second stage
       
    60  * constructor for the CATBase class.
       
    61  *
       
    62  * @return	None
       
    63  * @note	This ConstructL routine does not appear to be referenced.
       
    64  */
       
    65 	{
       
    66 	CATBase::ConstructL();
       
    67 	iRestartSignal=CRestartSignal::NewL(this);
       
    68 	}
       
    69 
       
    70 void CATScriptEng::StartRestart(TRequestStatus** aStatus)
       
    71 	{
       
    72 	iRestartSignal->Start(aStatus);
       
    73 	}
       
    74 
       
    75 TInt CATScriptEng::StartScript(const TScript* aScript)
       
    76 /**
       
    77  * This method starts a specified script.  The script is passed in as a parameter.
       
    78  * The CATScriptEng::StartScript method first invokes the Start method of the CATIO class.
       
    79  * It saves the parameter in private member data of the CATScriptEng class.
       
    80  * It then invokes the method ProcessMultipleScriptLines to begin processing
       
    81  * the referenced script.
       
    82  *
       
    83  * @param	aScript - a constant script pointer specified by the invoked test.
       
    84  *
       
    85  * @return	KErrNone
       
    86  */
       
    87 	{
       
    88 	iIo->Start(this);
       
    89 	iStartScriptPnt=iScriptPnt=aScript;
       
    90 	ProcessMultipleScriptLines();
       
    91 	return KErrNone;
       
    92 	}
       
    93 
       
    94 void CATScriptEng::EventSignal(TEventSource aEventSource)
       
    95 /**
       
    96  * This method is called when the completion event is signaled.  The appropriate
       
    97  * action is taken based on the event source.  This method handles the events defined in
       
    98  * the TCompletionEvent enumeration.  These events include a transmit event, a receive event,
       
    99  * a timeout event and a failure if timeout event.  If the script has specified to fail if
       
   100  * a timeout occurs (EFailIfTimeOut completion event), this routine will call the Complete
       
   101  * method specified by the test (normally the active scheduler is stopped by this method)
       
   102  * with the error KErrTimedOut.  This event method is used for active object read completions,
       
   103  * write completions, and timeouts via the CATBase::GenericEventSignal method.
       
   104  *
       
   105  * The iCompletionEvent member of the current script line (pointed to by iScriptPnt) is used
       
   106  * to test the incoming event.  Unless the EKeepExpectStrings flag is specified in the event,
       
   107  * the expect strings used by the scripting engine are removed.  This is the normal mode of 
       
   108  * operation.  The event ERxEvent is associated with the EReadCompletion event source
       
   109  * (the aEventSource parameter), the event ETxEvent is associated with the EWriteCompletion
       
   110  * event source, and the ETimeout event is associated with the ETimeOutCompletion event source.
       
   111  * In the case of the Read and TimeOut Completions, there is an attempt to cancel outstanding
       
   112  * commands.
       
   113  *
       
   114  * If an invalid completion event is specified or an invalid event source is passed into this
       
   115  * function, it will panic.
       
   116  *
       
   117  * @param	aEventSource, an event source from the TEventSource enumeration.
       
   118  *
       
   119  * @return	None
       
   120  */
       
   121 	{
       
   122 	if(aEventSource==ERestartSignal)
       
   123 		{
       
   124 		iIo->Cancel();
       
   125 		iIo->RemoveExpectStrings(this);
       
   126 		iJmpChatString=NULL;
       
   127 		StartScript(iStartScriptPnt);
       
   128 		return;
       
   129 		}
       
   130 
       
   131 	TCompletionEvent ev=(TCompletionEvent)iScriptPnt->iCompletionEvent;
       
   132 
       
   133 	if((ev&EFailIfTimeOut)&&(aEventSource==ETimeOutCompletion))
       
   134 		{
       
   135 		Complete(KErrTimedOut);
       
   136 		return;
       
   137 		}
       
   138 
       
   139 //
       
   140 // Check if a conditional jump may be required
       
   141 //
       
   142 	if((ev&ERxEvent)&&(iJmpChatString))
       
   143 		{
       
   144 		LOGTEXT(_S8("TsyLb:\tJmp Chat String defined, but not necessarily found yet"));
       
   145 		if(iIo->FoundChatString()==iJmpChatString)
       
   146 			{
       
   147 			LOGTEXT(_S8("TsyLb:\tFound Jmp Chat String, Jumping..."));
       
   148 			iScriptPnt=iStartScriptPnt+iJmpAbsolute-1;		// Subtract one because it will be incremented below
       
   149 			}
       
   150 		}
       
   151 
       
   152 //
       
   153 // Should the Expect Strings be kept
       
   154 //
       
   155 	if(!(ev&EKeepExpectStrings))
       
   156 		{
       
   157 		iIo->RemoveExpectStrings(this);
       
   158 		iJmpChatString=NULL;
       
   159 		}
       
   160 
       
   161 	if((ev&ERxEvent)&&(aEventSource==EReadCompletion))
       
   162 		{
       
   163 		iScriptPnt++;
       
   164 		ProcessMultipleScriptLines();
       
   165 		return;
       
   166 		}
       
   167 
       
   168 	if(	((ev&ETxEvent)&&(aEventSource==EWriteCompletion)) ||
       
   169 		((ev&ETimeOutEvent)&&(aEventSource==ETimeOutCompletion)) )
       
   170 		{
       
   171 		iIo->WriteAndTimerCancel(this);
       
   172 		iScriptPnt++;
       
   173 		ProcessMultipleScriptLines();
       
   174 		return;
       
   175 		}
       
   176 
       
   177 	HayesPanic(EATCommand_IllegalCompletionWriteNotExpected);
       
   178 	}
       
   179 
       
   180 void CATScriptEng::ProcessMultipleScriptLines()
       
   181 //
       
   182 // Process multiple script lines
       
   183 //
       
   184 /**
       
   185  * This method is used to drive the processing of the script.  A loop is entered which calls
       
   186  * another method to process a single line.  The member data iCurrentLineScript is set to
       
   187  * the current line of the script.  If an error is returned from the ProcessScriptLine method,
       
   188  * the loop is exited without moving the current line in the script.  If the current line in
       
   189  * the script specifies a non-zero completion event, the loop is exited without moving the
       
   190  * current line.  In the event that a non-zero completion event is specified, the event handling
       
   191  * code will move the current pointer and then call this method again.  A zero completion event
       
   192  * means that the command is completed when it has been issued.  There is no need to wait for
       
   193  * any event before continuing.  An example of this type of event is the EComplete command.  When
       
   194  * a zero completion event was specified, the iScriptPnt is incremented and the next line is
       
   195  * immediately processed.
       
   196  * Most transmits and receives require an event to complete the command (i.e., a read or write
       
   197  * completion).  This is noted by a non-zero completion event.  In this case, the script pointer
       
   198  * is not moved (until the command is completed).
       
   199  *
       
   200  * @return	None
       
   201  */
       
   202 	{
       
   203 	for(;;)
       
   204 		{
       
   205 		iCurrentScriptLine=*iScriptPnt;
       
   206 		LOGTEXT(_S8("------------CurrentScriptLine---------------")) ;
       
   207 		if(ProcessScriptLine()!=KErrNone)
       
   208 			break;
       
   209 		if(iCurrentScriptLine.iCompletionEvent!=0)
       
   210 			break;
       
   211 		iScriptPnt++;
       
   212 		}
       
   213 	}
       
   214 
       
   215 TInt CATScriptEng::ProcessScriptLine()
       
   216 //
       
   217 // Process a single line of the script
       
   218 //
       
   219 
       
   220 /**
       
   221  *
       
   222  * This method processes a single line from a script.  It switches on the command type
       
   223  * which is set up in the script itself.  Command types are documented in ScriptEng.h.
       
   224  * The member data iCurrentScriptLine is a variable of type TScript.  TScript is a
       
   225  * structure with several member.  There is a member (iCommand) which is an integer from the
       
   226  * enumeration TScriptCommands.  The second member is a pointer to a string (iText).  This is
       
   227  * text to be used to execute the command.  The third member is a parameter (iParam) which is
       
   228  * command specific.  A common use for iParam is a time-out value.  The fourth member is a
       
   229  * completion event (iCompletionEvent) which contains a value or set of flags that indicates
       
   230  * when it is okay to move to the next state in the script.  When this is a non-zero value it
       
   231  * is a member of the enumeration TCompletionEvent.
       
   232  *
       
   233  * The script commands cause different actions to occur.  The transmit commands (ETxString,
       
   234  * ETxStringWithoutCrLf and ETxStringOK) result in writes into the tsy (as the modem would 
       
   235  * normally write to the tsy).  The command ERxString results in the script engine looking for
       
   236  * output from the tsy (as the tsy would normally write to the modem).  The command EIfRxStringJmp
       
   237  * allows for rudimentary branching.  In this case the script engine will wait for the specified
       
   238  * text before branching to the script array element specified in the iParam entry of this 
       
   239  * script line.  The EWait command causes a timer to be started for the time frame specified in
       
   240  * the command script line via iParam.  The EExecuteSpecial command executes a test specific 
       
   241  * algorithm.  The EComplete command is used to notify the script engine that the script is
       
   242  * complete.  When the EComplete command is processed, the Complete method is called.  Each test
       
   243  * must define the Complete method as it is a pure virtual function in the CATScriptEng
       
   244  * class.  Many of the tests simply set a return value and stop the active scheduler in their
       
   245  * Complete routines.
       
   246  *
       
   247  * @return		KErrNone
       
   248  * @return		KScriptCompletionSignal in response to the EComplete Command
       
   249  * @return		Variable exceptions possible in response to the EExecuteSpecial command.  In
       
   250  *				this case, the return value is specified by the test specific algorithm.
       
   251  *
       
   252  * 
       
   253  */
       
   254 	{
       
   255 	TInt ret=KErrNone;
       
   256 
       
   257 	// Log the the logfile the current script line which is being executed
       
   258 	{
       
   259 	TInt32 scriptLine=reinterpret_cast<TInt32>(iScriptPnt);
       
   260 	scriptLine-=reinterpret_cast<TInt32>(iStartScriptPnt);
       
   261 	scriptLine/=sizeof(TScript);
       
   262 	LOGTEXT2(_L8("TsyLb:\tCurrentScriptLine=%d"),scriptLine);
       
   263 	}
       
   264 
       
   265 	switch(iCurrentScriptLine.iCommand)
       
   266 		{
       
   267 		case ESignalMark:
       
   268 				{
       
   269 				LOGTEXT(_S8("TsyLb:\tESignalSet command"));
       
   270 				iIo->SignalMark(iCurrentScriptLine.iParam);
       
   271 				}
       
   272 			break;
       
   273 
       
   274 		case ESignalSpace:
       
   275 				{
       
   276 				LOGTEXT(_S8("TsyLb:\tESignalClear command"));
       
   277 				iIo->SignalSpace(iCurrentScriptLine.iParam);
       
   278 				}
       
   279 			break;
       
   280 
       
   281 		case ETxString:
       
   282 				{
       
   283 				LOGTEXT(_S8("TsyLb:\tETxString command"));
       
   284 				TBuf8<KTxBufferSize> outputString((TText8*)iCurrentScriptLine.iText);
       
   285 				iTxBuffer.Copy(outputString);
       
   286 				iTxBuffer.Append('\n');
       
   287 				iTxBuffer.Append('\r');
       
   288 				iIo->Write(this, iTxBuffer);
       
   289 				TInt timeout=KStandardTxTimeout;
       
   290 				if(iCurrentScriptLine.iParam!=0)
       
   291 					timeout=iCurrentScriptLine.iParam*1000;
       
   292 				iIo->SetTimeOut(this, timeout);
       
   293 				}
       
   294 			break;
       
   295 
       
   296 		case ETxStringWithoutCrLf:
       
   297 				{
       
   298 				LOGTEXT(_S8("TsyLb:\tETxStringWithoutCrLf command"));
       
   299 				TBuf8<KTxBufferSize> outputString((TText8*)iCurrentScriptLine.iText);
       
   300 				iTxBuffer.Copy(outputString);
       
   301 				iIo->Write(this, iTxBuffer);
       
   302 				TInt timeout=KStandardTxTimeout;
       
   303 				if(iCurrentScriptLine.iParam!=0)
       
   304 					timeout=iCurrentScriptLine.iParam*1000;
       
   305 				iIo->SetTimeOut(this, timeout);
       
   306 				}
       
   307 			break;
       
   308 
       
   309 		case ETxStringOK:
       
   310 				{
       
   311 				LOGTEXT(_S8("TsyLb:\tETxStringOK command"));
       
   312 				_LIT8(KOKString,"\nOK\r\n");
       
   313 				iIo->Write(this, KOKString);
       
   314 				TInt timeout=KStandardTxTimeout;
       
   315 				if(iCurrentScriptLine.iParam!=0)
       
   316 					timeout=iCurrentScriptLine.iParam*1000;
       
   317 				iIo->SetTimeOut(this, timeout);
       
   318 				}
       
   319 			break;
       
   320 
       
   321 		case ERxString:
       
   322 				{
       
   323 				TBuf8<KRxBufferSize> expectString((TText8*)iCurrentScriptLine.iText);
       
   324 				iIo->AddExpectString(this,expectString);
       
   325 				LOGTEXT2(_L8("TsyLb:\tERxString command: %S"),&expectString);
       
   326 				iIo->MarkRxBuffer(iBufferMarker);
       
   327 				}
       
   328 			break;
       
   329 
       
   330 		case EIfRxStringJmp:
       
   331 				{
       
   332 				LOGTEXT(_S8("TsyLb:\tEIfRxStringJmp command"));
       
   333 				TBuf8<KRxBufferSize> expectString((TText8*)iCurrentScriptLine.iText);
       
   334 				iJmpChatString=iIo->AddExpectString(this,expectString);
       
   335 				iJmpAbsolute=iCurrentScriptLine.iParam;
       
   336 				iIo->MarkRxBuffer(iBufferMarker);
       
   337 				}
       
   338 			break;
       
   339 
       
   340 		case EIfRxStringRelativeJmp:
       
   341 				{
       
   342 				LOGTEXT(_S8("TsyLb:\tEIfRxStringJmp command"));
       
   343 				TBuf8<KRxBufferSize> expectString((TText8*)iCurrentScriptLine.iText);
       
   344 				iJmpChatString=iIo->AddExpectString(this,expectString);
       
   345 				//hack to calculate current position in array.
       
   346 				//Why developers not use indexes for arrays, did not?
       
   347 				iJmpAbsolute = (iScriptPnt - iStartScriptPnt)+iCurrentScriptLine.iParam;
       
   348 				iIo->MarkRxBuffer(iBufferMarker);
       
   349 				}
       
   350 			break;
       
   351 
       
   352 		case EWait:
       
   353 			LOGTEXT(_S8("TsyLb:\tEWait command"));
       
   354 			if (-1 == iCurrentScriptLine.iParam)
       
   355 				iIo->SetTimeOut(this, iDelay*1000);
       
   356 			else
       
   357 				iIo->SetTimeOut(this, iCurrentScriptLine.iParam*1000);
       
   358 			break;
       
   359 
       
   360 		case EExecuteSpecial:
       
   361 			{
       
   362 			LOGTEXT(_S8("TsyLb:\tEExecuteSpecial command"));
       
   363 			TRAP(ret,SpecificAlgorithmL(iCurrentScriptLine.iParam));
       
   364 			if(ret!=KErrNone)
       
   365 				Complete(ret);
       
   366 			break;
       
   367 			}
       
   368 			
       
   369 		case EComplete:
       
   370 				{
       
   371 				LOGTEXT(_S8("TsyLb:\tEComplete command"));
       
   372 				iIo->RemoveExpectStrings(this);
       
   373 				iOKExpectString = NULL;
       
   374 				iErrorExpectString = NULL;
       
   375 				ret=KScriptCompletionSignal;
       
   376 				iRestartSignal->Cancel();
       
   377 				TInt r=KErrNone;
       
   378 				Complete(r);
       
   379 				}
       
   380 			break;
       
   381 
       
   382 		default:
       
   383 			break;
       
   384 		}
       
   385 	return ret;
       
   386 	}
       
   387 
       
   388 void CATScriptEng::Restart()
       
   389 	{
       
   390 	EventSignal(ERestartSignal);
       
   391 	}
       
   392