|
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 // Telephony Fax Test base test code. |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 @internalComponent |
|
21 */ |
|
22 |
|
23 #include "faxdefn.h" |
|
24 #include "fax_reversebytes.h" |
|
25 #include "FAXSET.H" |
|
26 #include "CFAX32.H" |
|
27 |
|
28 #include "TE_FaxBase.h" |
|
29 |
|
30 #include <commsdattypesv1_1.h> |
|
31 |
|
32 using namespace CommsDat; |
|
33 |
|
34 |
|
35 // |
|
36 // Constants... |
|
37 // |
|
38 const TInt KFaxTestLogPeriod = 5*1000000; |
|
39 _LIT(KTEFaxINIFileName, "Z:\\TestData\\Configs\\TE_Fax.INI"); |
|
40 _LIT8(KTEFaxINIDestNumber, "DestPhoneNumber"); |
|
41 |
|
42 |
|
43 /** |
|
44 * Default constructor. |
|
45 */ |
|
46 CFaxTestStep::CFaxTestStep() |
|
47 { |
|
48 // NOP |
|
49 } // CFaxTestStep::CFaxTestStep |
|
50 |
|
51 |
|
52 /** |
|
53 * Default destructor. |
|
54 */ |
|
55 CFaxTestStep::~CFaxTestStep() |
|
56 { |
|
57 // NOP |
|
58 } // CFaxTestStep::~CFaxTestStep |
|
59 |
|
60 |
|
61 /** |
|
62 * Pre-amble function called before all tests. |
|
63 * |
|
64 * @return Test verdict for this test. |
|
65 */ |
|
66 TVerdict CFaxTestStep::doTestStepPreambleL() |
|
67 { |
|
68 // |
|
69 // Mark for memory leaks!!! |
|
70 // |
|
71 __UHEAP_MARK; |
|
72 |
|
73 // |
|
74 // Create an Active Scheduler... |
|
75 // |
|
76 iScheduler = new(ELeave) CActiveScheduler(); |
|
77 CActiveScheduler::Install(iScheduler); |
|
78 |
|
79 return TestStepResult(); |
|
80 } // CFaxTestStep::doTestStepPreambleL |
|
81 |
|
82 |
|
83 /** |
|
84 * Post-amble function called before all tests. |
|
85 * |
|
86 * @return Test verdict for this test. |
|
87 */ |
|
88 TVerdict CFaxTestStep::doTestStepPostambleL() |
|
89 { |
|
90 delete iScheduler; |
|
91 iScheduler = NULL; |
|
92 |
|
93 // |
|
94 // Check the heap for memory leaks... |
|
95 // |
|
96 __UHEAP_MARKEND; |
|
97 |
|
98 return TestStepResult(); |
|
99 } // CFaxTestStep::doTestStepPostambleL |
|
100 |
|
101 |
|
102 /** |
|
103 * Initialise the Fax settings based on default values and CommDB settings. |
|
104 * |
|
105 * @param aFaxSettings Fax Settings stucture to initialise. |
|
106 */ |
|
107 void CFaxTestStep::ReadDestPhoneNumberFromIniFileL(TDes8& aPhoneNumber) |
|
108 { |
|
109 // |
|
110 // Open the INI file... |
|
111 // |
|
112 RFs fs; |
|
113 RFile file; |
|
114 TInt result; |
|
115 |
|
116 result = fs.Connect(); |
|
117 TESTCHECKL(result, KErrNone); |
|
118 CleanupClosePushL(fs); |
|
119 |
|
120 result = file.Open(fs, KTEFaxINIFileName, EFileShareAny | EFileRead); |
|
121 if (result != KErrNone) |
|
122 { |
|
123 INFO_PRINTF2(_L("Cannot load TE_Fax.ini file! (Error %d)"), result); |
|
124 TESTCHECKL(result, KErrNone); |
|
125 } |
|
126 CleanupClosePushL(file); |
|
127 |
|
128 // |
|
129 // Get the file size and and then load the file into memory... |
|
130 // |
|
131 TInt fileSize; |
|
132 |
|
133 result = file.Size(fileSize); |
|
134 TESTCHECKL(result, KErrNone); |
|
135 TESTL(fileSize > 0); |
|
136 |
|
137 HBufC8* fileContents = HBufC8::NewLC(fileSize); |
|
138 TPtr8 fileContentsPtr(fileContents->Des()); |
|
139 |
|
140 result = file.Read(0, fileContentsPtr); |
|
141 TESTCHECKL(result, KErrNone); |
|
142 |
|
143 // |
|
144 // Parse the contents of the file... |
|
145 // |
|
146 TLex8 lexInput(fileContentsPtr); |
|
147 |
|
148 while (!lexInput.Eos()) |
|
149 { |
|
150 TPtrC8 token(lexInput.NextToken()); |
|
151 lexInput.SkipSpace(); |
|
152 |
|
153 if (token.Find(KTEFaxINIDestNumber) == KErrNone) |
|
154 { |
|
155 lexInput.SkipSpaceAndMark(); |
|
156 |
|
157 TPtrC8 phoneNumberPtr(lexInput.NextToken()); |
|
158 TBuf<32> phoneNumber; |
|
159 |
|
160 phoneNumber.Copy(phoneNumberPtr); |
|
161 INFO_PRINTF2(_L("Phone number read from INI file as \"%S\"."), &phoneNumber); |
|
162 |
|
163 aPhoneNumber.Copy(phoneNumber); |
|
164 } |
|
165 } |
|
166 |
|
167 // |
|
168 // Done, clean up... |
|
169 // |
|
170 CleanupStack::PopAndDestroy(fileContents); |
|
171 CleanupStack::PopAndDestroy(&file); |
|
172 CleanupStack::PopAndDestroy(&fs); |
|
173 } // CFaxTestStep::ReadDestPhoneNumberFromIniFileL |
|
174 |
|
175 |
|
176 /** |
|
177 * Initialise the Fax settings based on default values and CommDB settings. |
|
178 * |
|
179 * @param aFaxSettings Fax Settings stucture to initialise. |
|
180 */ |
|
181 void CFaxTestStep::ReadFaxCommDBSettingsL(TFaxSettings& aFaxSettings) |
|
182 { |
|
183 INFO_PRINTF1(_L("Reading Fax settings from the CommDB.")); |
|
184 |
|
185 // |
|
186 // Initialise the default values... |
|
187 // |
|
188 aFaxSettings.iFaxId.Zero(); |
|
189 aFaxSettings.iMaxSpeed = 14400; |
|
190 aFaxSettings.iMinSpeed = 2400; |
|
191 aFaxSettings.iPreferredResolution = EFaxFine; |
|
192 aFaxSettings.iPreferredCompression = EModifiedHuffman; |
|
193 aFaxSettings.iPreferredECM = EFalse; |
|
194 aFaxSettings.iFaxOnDemandDelay = 20; |
|
195 aFaxSettings.iVerbose = 1; |
|
196 |
|
197 // |
|
198 // Now we now read the Comm DB modem settings - we must have |
|
199 // these to run... |
|
200 // |
|
201 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY |
|
202 CMDBSession* db = CMDBSession::NewL(KCDVersion1_2); |
|
203 #else |
|
204 CMDBSession* db = CMDBSession::NewL(KCDVersion1_1); |
|
205 #endif |
|
206 CleanupStack::PushL(db); |
|
207 |
|
208 // |
|
209 // Read the currently selected connection preference and find preferred IAP... |
|
210 // |
|
211 TInt prefRank = 1; |
|
212 |
|
213 CCDConnectionPrefsRecord *connectionPrefs = |
|
214 static_cast<CCDConnectionPrefsRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdConnectionPrefsRecord)); |
|
215 CleanupStack::PushL(connectionPrefs); |
|
216 connectionPrefs->iRanking = prefRank; |
|
217 connectionPrefs->iDirection = ECommDbConnectionDirectionOutgoing; |
|
218 connectionPrefs->FindL(*db); |
|
219 |
|
220 // The following code is a temporary solution until an issue has been resolved in CommsDat |
|
221 // start |
|
222 CCDIAPRecord* tempPIapRecord = |
|
223 static_cast<CCDIAPRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdIAPRecord)); |
|
224 tempPIapRecord->SetRecordId(connectionPrefs->iDefaultIAP); |
|
225 connectionPrefs->iDefaultIAP.iLinkedRecord = tempPIapRecord; |
|
226 |
|
227 CCDIAPRecord* pIapRecord = (CCDIAPRecord*)connectionPrefs->iDefaultIAP.iLinkedRecord; |
|
228 pIapRecord->SetRecordId(connectionPrefs->iDefaultIAP); |
|
229 pIapRecord->LoadL(*db); |
|
230 |
|
231 CCDBearerRecordBase* tempBearerRecord = |
|
232 static_cast<CCDBearerRecordBase*>(CCDRecordBase::RecordFactoryL(KCDTIdModemBearerRecord)); |
|
233 tempBearerRecord->SetRecordId(pIapRecord->iBearer); |
|
234 pIapRecord->iBearer.iLinkedRecord = tempBearerRecord; |
|
235 |
|
236 CCDBearerRecordBase* pBearerRecord = (CCDBearerRecordBase*) pIapRecord->iBearer.iLinkedRecord; |
|
237 pBearerRecord->SetRecordId(pIapRecord->iBearer); |
|
238 pBearerRecord->LoadL(*db); |
|
239 // end |
|
240 |
|
241 TUint32 iapId = pBearerRecord->iRecordTag; |
|
242 |
|
243 // |
|
244 // Get bearer number from IAP table, it is assumed bearer type will be a modem... |
|
245 // |
|
246 CMDBField<TUint32>* bearerField = new(ELeave) CMDBField<TUint32>(KCDTIdIAPBearer); |
|
247 CleanupStack::PushL(bearerField); |
|
248 bearerField->SetRecordId(iapId); |
|
249 bearerField->LoadL(*db); |
|
250 TUint32 modemId = *bearerField; |
|
251 CleanupStack::PopAndDestroy(bearerField); |
|
252 |
|
253 // |
|
254 // Get modem parameters... |
|
255 // |
|
256 CCDModemBearerRecord *modemRecord = |
|
257 static_cast<CCDModemBearerRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdModemBearerRecord)); |
|
258 CleanupStack::PushL(modemRecord); |
|
259 modemRecord->SetRecordId(modemId); |
|
260 modemRecord->LoadL(*db); |
|
261 iPortDriverName = modemRecord->iCsyName; |
|
262 iCommPortName = modemRecord->iPortName; |
|
263 iFaxInitString = modemRecord->iFaxInitString; |
|
264 iModemInitString = modemRecord->iModemInitString; |
|
265 |
|
266 TUint32 faxClass; |
|
267 faxClass = modemRecord->iFaxClassPref; |
|
268 aFaxSettings.iFaxClass = (TFaxClass) faxClass; |
|
269 |
|
270 CleanupStack::PopAndDestroy(3); // db, connectionPrefs, modemId |
|
271 |
|
272 } // CFaxTestStep::ReadFaxCommDBSettingsL |
|
273 |
|
274 |
|
275 /** |
|
276 * Begin Fax Transfer. We only launch it once the elements of |
|
277 * session->iFaxSessionParameters are all set up. We call it with a |
|
278 * TRequestStatus and while waiting for the fax to end, we also display |
|
279 * the status of the fax every second. |
|
280 * |
|
281 * @param aFaxSession Fax Session already in use. |
|
282 */ |
|
283 TInt CFaxTestStep::BeginFaxTransfer(CFaxTransfer* aFaxSession) |
|
284 { |
|
285 TRequestStatus threadStatus; |
|
286 TRequestStatus timerStatus; |
|
287 RTimer timer; |
|
288 TFaxPhase lastPhase = ENotYetStarted; |
|
289 TInt result; |
|
290 |
|
291 result = aFaxSession->Start(threadStatus); |
|
292 if (result == KErrNone) |
|
293 { |
|
294 timer.CreateLocal (); |
|
295 timer.After(timerStatus, KFaxTestLogPeriod); |
|
296 |
|
297 for (;;) |
|
298 { |
|
299 User::WaitForRequest(timerStatus, threadStatus); |
|
300 if (timerStatus != KRequestPending) |
|
301 { |
|
302 if (aFaxSession->Progress()) |
|
303 { |
|
304 INFO_PRINTF1(_L("Cancelling - no progress!")); |
|
305 aFaxSession->Cancel(); |
|
306 } |
|
307 else |
|
308 { |
|
309 lastPhase = aFaxSession->iProgress.iPhase; |
|
310 if (lastPhase != ENotYetStarted) |
|
311 { |
|
312 INFO_PRINTF6(_L("Phase %c Speed %d Resolution %d Compression %dD ECM %d"), |
|
313 aFaxSession->iProgress.iPhase, |
|
314 aFaxSession->iProgress.iSpeed, |
|
315 aFaxSession->iProgress.iResolution, |
|
316 aFaxSession->iProgress.iCompression+1, |
|
317 aFaxSession->iProgress.iECM); |
|
318 INFO_PRINTF4(_L("Line %d Page %d Connected to \"%S\""), |
|
319 aFaxSession->iProgress.iLines, |
|
320 aFaxSession->iProgress.iPage, |
|
321 &aFaxSession->iProgress.iAnswerback); |
|
322 } |
|
323 timer.After(timerStatus, KFaxTestLogPeriod); |
|
324 } |
|
325 } |
|
326 else if (threadStatus != KRequestPending) |
|
327 { |
|
328 aFaxSession->Stop(); |
|
329 |
|
330 timer.Cancel(); |
|
331 User::WaitForRequest(timerStatus); |
|
332 timer.Close (); |
|
333 |
|
334 result = threadStatus.Int(); |
|
335 break; |
|
336 } |
|
337 } |
|
338 } |
|
339 |
|
340 if (result == KFaxErrNoHangup) |
|
341 { |
|
342 // |
|
343 // KFaxErrNoHangup is a phase E error and can be safely ignored. |
|
344 // |
|
345 result = KErrNone; |
|
346 } |
|
347 |
|
348 return (result); |
|
349 } // CFaxTestStep::BeginFaxTransfer() |
|
350 |
|
351 |
|
352 void CFaxTestStep::GenerateHeaderFileL(TFaxSettings& aFaxSettings, const TUint8* aFont, |
|
353 TInt aWidth, TInt aHeight) |
|
354 { |
|
355 TFaxHeaderInfo faxHeader; |
|
356 |
|
357 // |
|
358 // Declare the font size... |
|
359 // |
|
360 faxHeader.iHeaderFontWidthInBytes = aWidth; |
|
361 faxHeader.iHeaderFontHeightInLines = aHeight; |
|
362 |
|
363 // |
|
364 // Work out the number of characters we can get in the scan line, so that we can |
|
365 // create a modifiable buffer to hold the header line and fill it with spaces |
|
366 // |
|
367 TInt charactersPerLine = KFaxBytesPerScanLine / faxHeader.iHeaderFontWidthInBytes; |
|
368 HBufC8* textBuff = HBufC8::New(charactersPerLine); |
|
369 CleanupStack::PushL(textBuff); |
|
370 |
|
371 if (!textBuff) |
|
372 { |
|
373 User::Leave (KErrNoMemory); |
|
374 } |
|
375 |
|
376 TPtr8 textLine = textBuff->Des(); |
|
377 textLine.Fill(' ', charactersPerLine); |
|
378 |
|
379 // |
|
380 // Work out the margin we leave on each side of the page in characters |
|
381 // this is specified as 74 pixels in T.4. |
|
382 // |
|
383 TInt margin = (74 / (8 * faxHeader.iHeaderFontWidthInBytes)); |
|
384 |
|
385 // |
|
386 // THE FOLLOWING LAYOUT IS PURELY FOR TEST PURPOSES AND SHOULDN'T |
|
387 // BE TAKEN TO BE A DEFINITIVE HEADER LAYOUT |
|
388 // |
|
389 // |
|
390 // assume we have the date and time on the lefthand side as dd/mm/yyyy hh:mm |
|
391 // 0000000001111111 |
|
392 // 1234567890123456 |
|
393 // fill in the separators |
|
394 // |
|
395 textLine.Replace(margin + 3, 1, _L8 ("/")); |
|
396 textLine.Replace(margin + 6, 1, _L8 ("/")); |
|
397 textLine.Replace(margin + 14, 1, _L8 (":")); |
|
398 |
|
399 // |
|
400 // Set up the offsets to the data... |
|
401 // |
|
402 faxHeader.iOffsetToDay = margin + 1; |
|
403 faxHeader.iOffsetToMonth = margin + 4; |
|
404 faxHeader.iOffsetToYear = margin + 7; |
|
405 faxHeader.iOffsetToHour = margin + 12; |
|
406 faxHeader.iOffsetToMinute = margin + 15; |
|
407 |
|
408 // |
|
409 // Assume we have the page info on the righthand side as pp/tt |
|
410 // 54321 |
|
411 // fill in the separator |
|
412 // |
|
413 textLine.Replace(charactersPerLine - margin - 3, 1, _L8 ("/")); |
|
414 |
|
415 // |
|
416 // Set up the offsets to the data |
|
417 // |
|
418 faxHeader.iOffsetToTotalPages = charactersPerLine - margin - 2; |
|
419 faxHeader.iOffsetToCurrentPage = charactersPerLine - margin - 5; |
|
420 |
|
421 // |
|
422 // Fill the header line with appropriate information |
|
423 // |
|
424 textLine.Replace(faxHeader.iOffsetToMinute + 4, aFaxSettings.iFaxId.Length (), |
|
425 aFaxSettings.iFaxId); |
|
426 |
|
427 // |
|
428 // HEADER LAYOUT NOW FINISHED |
|
429 // |
|
430 // Now we can write the fax header info to the header info file |
|
431 // |
|
432 CFaxHeaderLines* testheader = CFaxHeaderLines::NewL(); |
|
433 CleanupStack::PushL(testheader); |
|
434 |
|
435 testheader->WriteFaxHeaderInfoL(faxHeader); |
|
436 |
|
437 // |
|
438 // Now we generate the scan line and write the header line bitmap |
|
439 // via a loop for each rowInFont in the font. |
|
440 // |
|
441 TInt rowInFont; |
|
442 |
|
443 for (rowInFont = 0; rowInFont < faxHeader.iHeaderFontHeightInLines; rowInFont++) |
|
444 { |
|
445 TRawScanLine image; |
|
446 |
|
447 image.SetMax (); |
|
448 image.FillZ (); |
|
449 |
|
450 TInt offsetInImage = 0; |
|
451 |
|
452 for (TInt characterPosition = 0; characterPosition < charactersPerLine; characterPosition++) |
|
453 { |
|
454 for (TInt fontByte = 0; fontByte < faxHeader.iHeaderFontWidthInBytes; fontByte++) |
|
455 { |
|
456 image[offsetInImage++] = (TUint8) ~ KReverseByte[*(aFont + ((textLine[characterPosition] - 32) * faxHeader.iHeaderFontHeightInLines * faxHeader.iHeaderFontWidthInBytes) + (rowInFont * faxHeader.iHeaderFontWidthInBytes) + fontByte)]; |
|
457 } |
|
458 } |
|
459 testheader->WriteRawHeaderLineL(rowInFont, image); |
|
460 } |
|
461 |
|
462 // |
|
463 // Now we replace the first ten characters in the header text line with digits |
|
464 // and write out the font line... |
|
465 // |
|
466 textLine.Replace(0, 10, _L8 ("0123456789")); |
|
467 |
|
468 for (rowInFont = 0; rowInFont < faxHeader.iHeaderFontHeightInLines; rowInFont++) |
|
469 { |
|
470 TRawScanLine image; |
|
471 |
|
472 image.SetMax (); |
|
473 image.FillZ (); |
|
474 |
|
475 TInt offsetInImage = 0; |
|
476 |
|
477 for (TInt characterPosition = 0; characterPosition < charactersPerLine; characterPosition++) |
|
478 { |
|
479 for (TInt fontByte = 0; fontByte < faxHeader.iHeaderFontWidthInBytes; fontByte++) |
|
480 { |
|
481 image[offsetInImage++] = (TUint8) ~ KReverseByte[*(aFont + ((textLine[characterPosition] - 32) * faxHeader.iHeaderFontHeightInLines * faxHeader.iHeaderFontWidthInBytes) + (rowInFont * faxHeader.iHeaderFontWidthInBytes) + fontByte)]; |
|
482 } |
|
483 } |
|
484 testheader->WriteRawFontLineL(rowInFont, image); |
|
485 } |
|
486 |
|
487 CleanupStack::PopAndDestroy(testheader); |
|
488 CleanupStack::PopAndDestroy(textBuff); |
|
489 } // CFaxTestStep::GenerateHeaderFileL |
|
490 |