|
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 |