|
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 // |
|
15 |
|
16 #include "FAXSERV.H" |
|
17 #include "fax_reversebytes.h" |
|
18 #include "FONT8X16.DAT" |
|
19 #include "ZEROS.DAT" |
|
20 #include "FAXMDRV.H" |
|
21 #include "FAXMODEM.H" |
|
22 |
|
23 #include "FAXLOG.H" |
|
24 #include <et_phone.h> |
|
25 |
|
26 const TInt KLineReadTimeout=6; // < The time-out (in secs) for a line read |
|
27 const TInt KECMLineReadTimeout=132; // < The time-out (in secs) for a line read when using Error Correction Mode |
|
28 const TInt KSubsequentLineReadTimeout=10; // < The time-out (in secs) for a subsequent line read |
|
29 const TInt KSubsequentECMLineReadTimeout=140; // < The time-out (in secs) for a subsequent line read when using Error Correction Mode |
|
30 |
|
31 /********************************************************************/ |
|
32 |
|
33 // we need to keep a local pointer to the current TDialstorModemPreferences in order to |
|
34 // do whatever is required |
|
35 |
|
36 void CFaxModemDriver::ConstructL (TFaxServerSessionSettings * iFaxServerSessionSettings, RFax::TProgress & aProgress) |
|
37 { |
|
38 iModem = CFaxModem::NewL (iFaxServerSessionSettings, aProgress); |
|
39 } |
|
40 /********************************************************************/ |
|
41 |
|
42 |
|
43 CFaxModemDriver::CFaxModemDriver() |
|
44 :CBase(), iSharedHandles(NULL) |
|
45 { |
|
46 } |
|
47 |
|
48 CFaxModemDriver::~CFaxModemDriver () |
|
49 { |
|
50 delete iModem; |
|
51 } |
|
52 /********************************************************************/ |
|
53 |
|
54 // function to check that we don't send commands out when there's less than half a second |
|
55 // before the next RING comes in |
|
56 |
|
57 |
|
58 /** |
|
59 * function to check that we don't send commands out when there's less than half a second |
|
60 * before the next RING comes in. |
|
61 * This function has been modified by Dmitry Lyokhin for the sake of PIA-586KGE defect fix |
|
62 * |
|
63 * @param aCommand - contains the command to be sent to the modem. |
|
64 * |
|
65 * @see ExportL function |
|
66 * |
|
67 * @return number of symbols sent to the modem. |
|
68 * |
|
69 * |
|
70 */ |
|
71 TInt CFaxModemDriver::CheckCadenceExportL(const TDesC8 & aCommand) |
|
72 { |
|
73 |
|
74 |
|
75 const TInt RingTimeout_Sec = 5; //-- 5 sec. waiting for 'RING' timeout |
|
76 const TInt RingCadence_uSec = 3000000; //-- 3 sec. time span after 'RING' receiving during that commands |
|
77 //-- can be sent to the modem |
|
78 |
|
79 const TInt CmdSendDelay_uSec= 100000; //-- 100 ms delay between adjacent commands to the modem |
|
80 |
|
81 TTime CurrentTime; |
|
82 |
|
83 __FLOG_FAXSRV( _L8("-CFaxModemDriver::CheckCadenceExportL entering")); |
|
84 |
|
85 |
|
86 //-- @note iCadence now is used like a flag. If its value is 0 (thai is set initially) we will |
|
87 //-- try to wait for 'RING' indication i.e synchronize with incoming rings. Otherwise - no. |
|
88 while( iCadence.Int64() == 0 ) |
|
89 { |
|
90 if(iTimeOfLastRing.Int64() == 0) |
|
91 {//-- we need to wait for 'RING' from the modem |
|
92 |
|
93 __FLOG_FAXSRV( _L8("-CFaxModemDriver::CheckCadenceExportL waiting for RING")); |
|
94 |
|
95 //-- wait for 'RING' from modem |
|
96 if( iModem->GetMatchL (_L8 ("RING"), RingTimeout_Sec) == 0) |
|
97 { //User::Leave(KFaxErrReceiveTimeout); //-- 'RING' waiting timeout, leaving |
|
98 |
|
99 //-- There is no 'RING'indication, no we will not leave, instead of that |
|
100 //-- disable sync. with incoming rings and pass on to sending commands to the modem straightforward. |
|
101 iCadence = 1; |
|
102 break; |
|
103 } |
|
104 |
|
105 iTimeOfLastRing.UniversalTime(); //-- note the time |
|
106 } |
|
107 |
|
108 //-- get current time and check if we are in time to send a command to the modem |
|
109 CurrentTime.UniversalTime (); |
|
110 |
|
111 if( CurrentTime < iTimeOfLastRing + TTimeIntervalMicroSeconds32(RingCadence_uSec) ) |
|
112 break; //-- send the command |
|
113 else |
|
114 { //-- wait for the next 'RING' |
|
115 __FLOG_FAXSRV( _L8("-CFaxModemDriver::CheckCadenceExportL Resetting")); |
|
116 iTimeOfLastRing = 0; |
|
117 } |
|
118 } |
|
119 |
|
120 //-- I had to introduce this delay between sending adjacent commands to the modem because |
|
121 //-- some modems (e.g. Nokia9210) lose data. |
|
122 iModem->Silence(CmdSendDelay_uSec); |
|
123 |
|
124 //-- send the command |
|
125 return iModem->ExportL (aCommand); |
|
126 } |
|
127 |
|
128 /********************************************************************/ |
|
129 |
|
130 // if we have called FaxInL with a dial request, it calls this routine |
|
131 // to dial up a fax on demand service |
|
132 // |
|
133 // if not polling, we end with a colon to return to command mode and then |
|
134 // we delay for whatever time has been requested by the user |
|
135 // before returning, at which point FaxInL continues with ATA |
|
136 |
|
137 void CFaxModemDriver::DialFaxOnDemandL () |
|
138 { |
|
139 iModem->ExportL (_L8 ("ATD")); |
|
140 iModem->ExportL (iFaxServerSessionSettings->iPhoneNumber); |
|
141 |
|
142 if (iFaxServerSessionSettings->iMode & KFaxPoll) |
|
143 iModem->TxcharL (Kreturn); |
|
144 else |
|
145 { |
|
146 iModem->ExportL (_L8 (";")); |
|
147 iModem->TxcharL (Kreturn); |
|
148 if ((iModem->GetMatchL (_L8 ("OK"), KDialTimeout)) == 0) |
|
149 User::Leave (KFaxErrNoDial); |
|
150 iModem->Silence (CLK_TCK * iFaxServerSessionSettings->iFaxOnDemandDelay); |
|
151 } |
|
152 } |
|
153 /********************************************************************/ |
|
154 |
|
155 // now the routines to add a header line to the top of each fax page |
|
156 |
|
157 /********************************************************************/ |
|
158 |
|
159 // we send four blank scan lines |
|
160 // we create a line of text containing time and date, |
|
161 // the Fax ID and Username, |
|
162 // the page number and total number of pages, |
|
163 // we digitize that, and send it out |
|
164 // our font height is 16 so that means 20 scan lines |
|
165 // are added to the top of each sent fax |
|
166 |
|
167 void CFaxModemDriver::SendFaxHeaderL () |
|
168 { |
|
169 TFaxHeaderInfo faxHeader; |
|
170 TRawScanLine headline; |
|
171 TRawScanLine fontline; |
|
172 TBuf8 < KFaxT4MaxDesLength > encodedHeadLine; |
|
173 TTime timeOfTransmission; |
|
174 TBuf < 12 > timeText; |
|
175 |
|
176 timeOfTransmission.HomeTime(); |
|
177 timeOfTransmission.FormatL (timeText, (_L ("%F%D%M%Y%H%T"))); |
|
178 |
|
179 iModem->iOurMessage.Format (_L8 ("Sending page header")); |
|
180 iModem->ProgressUpdateL (); |
|
181 |
|
182 for (TInt r = iModem->iProgress.iResolution ; r >= 0; r--) |
|
183 { |
|
184 for (TInt x = 0, y = 4 ; x < 4; x++) |
|
185 { |
|
186 iModem->iTransmitBuffer.Append (0x00); |
|
187 if (iModem->iProgress.iCompression) |
|
188 { |
|
189 iModem->iTransmitBuffer.Append (Invert (0x00)); |
|
190 iModem->iTransmitBuffer.Append (Invert (0x34)); |
|
191 y = 5; |
|
192 } |
|
193 else |
|
194 iModem->iTransmitBuffer.Append (Invert (0x14)); |
|
195 iModem->iTransmitBuffer.Append (Invert (0xD9)); |
|
196 iModem->iTransmitBuffer.Append (Invert (0xA8)); |
|
197 padLineL (y); |
|
198 } |
|
199 } |
|
200 |
|
201 CFaxT4 * faxT4 =CFaxT4::NewLC(); |
|
202 faxT4->PageInitialize (iModem->iProgress.iResolution, iModem->iProgress.iCompression); |
|
203 if(!iSharedHandles) |
|
204 { |
|
205 User::Leave(KErrBadHandle); |
|
206 } |
|
207 CFaxHeaderLines * faxheader = CFaxHeaderLines::NewLC (&iSharedHandles->File()); |
|
208 |
|
209 faxheader->ReadFaxHeaderInfoL (faxHeader); |
|
210 for (TInt n = 0; n < 12; n++) |
|
211 timeText[n] -= '0'; |
|
212 |
|
213 // Forces 2 digit day - 2 digit month - 4 digit year - 2 digit hour - 2 digit minute |
|
214 |
|
215 for (TInt scanline = 0; scanline < faxHeader.iHeaderFontHeightInLines; scanline++) |
|
216 { |
|
217 faxheader->ReadRawHeaderLineL (scanline, headline); |
|
218 faxheader->ReadRawFontLineL (scanline, fontline); |
|
219 for (TInt fontByte = 0; fontByte < faxHeader.iHeaderFontWidthInBytes; fontByte++) |
|
220 { |
|
221 headline[((faxHeader.iOffsetToDay) * faxHeader.iHeaderFontWidthInBytes) + fontByte] = fontline[(timeText[0] * faxHeader.iHeaderFontWidthInBytes) + fontByte]; |
|
222 headline[((faxHeader.iOffsetToDay + 1) * faxHeader.iHeaderFontWidthInBytes) + fontByte] = fontline[(timeText[1] * faxHeader.iHeaderFontWidthInBytes) + fontByte]; |
|
223 headline[((faxHeader.iOffsetToMonth) * faxHeader.iHeaderFontWidthInBytes) + fontByte] = fontline[(timeText[2] * faxHeader.iHeaderFontWidthInBytes) + fontByte]; |
|
224 headline[((faxHeader.iOffsetToMonth + 1) * faxHeader.iHeaderFontWidthInBytes) + fontByte] = fontline[(timeText[3] * faxHeader.iHeaderFontWidthInBytes) + fontByte]; |
|
225 headline[((faxHeader.iOffsetToYear) * faxHeader.iHeaderFontWidthInBytes) + fontByte] = fontline[(timeText[4] * faxHeader.iHeaderFontWidthInBytes) + fontByte]; |
|
226 headline[((faxHeader.iOffsetToYear + 1) * faxHeader.iHeaderFontWidthInBytes) + fontByte] = fontline[(timeText[5] * faxHeader.iHeaderFontWidthInBytes) + fontByte]; |
|
227 headline[((faxHeader.iOffsetToYear + 2) * faxHeader.iHeaderFontWidthInBytes) + fontByte] = fontline[(timeText[6] * faxHeader.iHeaderFontWidthInBytes) + fontByte]; |
|
228 headline[((faxHeader.iOffsetToYear + 3) * faxHeader.iHeaderFontWidthInBytes) + fontByte] = fontline[(timeText[7] * faxHeader.iHeaderFontWidthInBytes) + fontByte]; |
|
229 headline[((faxHeader.iOffsetToHour) * faxHeader.iHeaderFontWidthInBytes) + fontByte] = fontline[(timeText[8] * faxHeader.iHeaderFontWidthInBytes) + fontByte]; |
|
230 headline[((faxHeader.iOffsetToHour + 1) * faxHeader.iHeaderFontWidthInBytes) + fontByte] = fontline[(timeText[9] * faxHeader.iHeaderFontWidthInBytes) + fontByte]; |
|
231 headline[((faxHeader.iOffsetToMinute) * faxHeader.iHeaderFontWidthInBytes) + fontByte] = fontline[(timeText[10] * faxHeader.iHeaderFontWidthInBytes) + fontByte]; |
|
232 headline[((faxHeader.iOffsetToMinute + 1) * faxHeader.iHeaderFontWidthInBytes) + fontByte] = fontline[(timeText[11] * faxHeader.iHeaderFontWidthInBytes) + fontByte]; |
|
233 |
|
234 // put the page info in |
|
235 |
|
236 |
|
237 if (iModem->iProgress.iPage > 9) |
|
238 headline[((faxHeader.iOffsetToCurrentPage) * faxHeader.iHeaderFontWidthInBytes) + fontByte] = fontline[((iModem->iProgress.iPage / 10) * faxHeader.iHeaderFontWidthInBytes) + fontByte]; |
|
239 headline[((faxHeader.iOffsetToCurrentPage + 1) * faxHeader.iHeaderFontWidthInBytes) + fontByte] = fontline[((iModem->iProgress.iPage % 10) * faxHeader.iHeaderFontWidthInBytes) + fontByte]; |
|
240 if (iFaxServerSessionSettings->iTxPages > 9) |
|
241 headline[((faxHeader.iOffsetToTotalPages) * faxHeader.iHeaderFontWidthInBytes) + fontByte] = fontline[((iFaxServerSessionSettings->iTxPages / 10) * faxHeader.iHeaderFontWidthInBytes) + fontByte]; |
|
242 headline[((faxHeader.iOffsetToTotalPages + 1) * faxHeader.iHeaderFontWidthInBytes) + fontByte] = fontline[((iFaxServerSessionSettings->iTxPages % 10) * faxHeader.iHeaderFontWidthInBytes) + fontByte]; |
|
243 } |
|
244 |
|
245 // we send the line once in normal resolution but twice in fine resolution |
|
246 |
|
247 for (TInt r = iModem->iProgress.iResolution ; r >= 0; r--) |
|
248 { |
|
249 faxT4->EncodeScanLine (headline, encodedHeadLine); |
|
250 |
|
251 // always add the extra null at the start for the initial eol |
|
252 |
|
253 iModem->iTransmitBuffer.Append (Knul); |
|
254 |
|
255 // and then invert and finally send the encoded line |
|
256 |
|
257 const TUint8 *px = CONST_CAST (TUint8 *, encodedHeadLine.Ptr ()); |
|
258 const TUint8 *ex = px + encodedHeadLine.Length ();; |
|
259 TUint8 thisChar; |
|
260 TInt bytesSent = 0; |
|
261 while (px < ex) |
|
262 { |
|
263 thisChar = Invert (*px++); |
|
264 iModem->iTransmitBuffer.Append (thisChar); |
|
265 if (thisChar == Kdle) |
|
266 iModem->iTransmitBuffer.Append (Kdle); |
|
267 iModem->SendTransmitBufferL (); |
|
268 bytesSent++; |
|
269 } |
|
270 padLineL (bytesSent); |
|
271 } |
|
272 } |
|
273 |
|
274 CleanupStack::PopAndDestroy(faxheader); |
|
275 CleanupStack::PopAndDestroy(faxT4); |
|
276 } |
|
277 |
|
278 /********************************************************************/ |
|
279 |
|
280 // this function handles line padding out for minimum scan line times |
|
281 // this feature should really only be needed on class 1 modems ... |
|
282 // it takes a single integer parameter, which is the number of bytes sent |
|
283 |
|
284 void CFaxModemDriver::padLineL (TInt aByteCount) |
|
285 { |
|
286 if (iFaxServerSessionSettings->iFaxClass == EClass1) |
|
287 { |
|
288 while (iMinlinelength > aByteCount) |
|
289 { |
|
290 aByteCount++; |
|
291 iModem->iTransmitBuffer.Append (Knul); |
|
292 iModem->SendTransmitBufferL (); |
|
293 } |
|
294 } |
|
295 } |
|
296 /********************************************************************/ |
|
297 |
|
298 // rewritten to avoid using any AT commands August 1997 Andrew Margolis |
|
299 // pointer arithmetic courtesy of Andrew Thoelke |
|
300 // Though this doesn't use any AT command but it does need to know |
|
301 // about the various modem classes ... GetFaxDataL is in the same boat |
|
302 |
|
303 // the client has buffered up lines to minimize interaction |
|
304 // aData starts with a TInt containing the number of lines |
|
305 // Each line follows, preceded with a TInt containing its length |
|
306 // which must be copied as it might not be aligned on a 4-byte |
|
307 // boundary |
|
308 |
|
309 TInt CFaxModemDriver::SendFaxDataL (const TDesC8 * aData) |
|
310 { |
|
311 TUint8 thisChar; |
|
312 TInt ticks; |
|
313 TInt numberOfLines; |
|
314 TInt lengthOfLine; |
|
315 |
|
316 TUint8 *thisLine = CONST_CAST (TUint8 *, (*aData).Ptr ()); |
|
317 Mem::Copy (&numberOfLines, thisLine, sizeof (TInt)); |
|
318 thisLine += sizeof (TInt); |
|
319 |
|
320 // buffering debug message |
|
321 |
|
322 iModem->iOurMessage.Format (_L8 ("%u lines in buffer taking up %u bytes"), numberOfLines, (*aData).Length ()); |
|
323 iModem->ProgressUpdateL (); |
|
324 |
|
325 while (numberOfLines--) |
|
326 { |
|
327 Mem::Copy (&lengthOfLine, thisLine, sizeof (TInt)); |
|
328 thisLine += sizeof (TInt); |
|
329 iModem->iProgress.iLines++; |
|
330 |
|
331 TInt bytesSent = 0; |
|
332 const TUint8 *px = thisLine; |
|
333 const TUint8 *ex = px + lengthOfLine; |
|
334 while (px < ex) |
|
335 { |
|
336 thisChar = Invert (*px++); |
|
337 iModem->iTransmitBuffer.Append (thisChar); |
|
338 if (thisChar == Kdle) |
|
339 iModem->iTransmitBuffer.Append (Kdle); |
|
340 iModem->SendTransmitBufferL (); |
|
341 bytesSent++; |
|
342 } |
|
343 padLineL (bytesSent); |
|
344 |
|
345 // we must check for cancel commands from the modem in class 2.0 transmission |
|
346 |
|
347 if (iFaxServerSessionSettings->iFaxClass == EClass2point0) |
|
348 { |
|
349 while (iModem->Rxstat () != 0) |
|
350 { |
|
351 ticks = CLK_TCK; |
|
352 iModem->RxcharWaitL (ticks); |
|
353 if (iModem->iReadone[0] == Kcan) |
|
354 { |
|
355 iModem->TxcharL (Kdle); |
|
356 iModem->TxcharL (Ketx); |
|
357 iModem->CommitTransmitBufferL (); |
|
358 iModem->Xonoff (); |
|
359 iModem->GetMatchL (_L8 ("OK"), 5); |
|
360 return (KFaxErrModemDisconnect); |
|
361 } |
|
362 } |
|
363 } |
|
364 thisLine += lengthOfLine; |
|
365 } |
|
366 return (KErrNone); |
|
367 } |
|
368 /********************************************************************/ |
|
369 // This function takes a pointer to a binary data buffer. |
|
370 // We are guaranteed that the buffer is big enough to take |
|
371 // two entire scan lines up to KMaxT4Des in size. |
|
372 |
|
373 // We call GetLineL to fill the buffer up with scan lines, and |
|
374 // we keep a count of the number of lines received as an integer |
|
375 // at the start of the buffer. We return when either we haven't |
|
376 // enough room to guarantee another line, or when we have received |
|
377 // a line of zero length, which means an end of page. The descriptor |
|
378 // is set to the correct length on return |
|
379 |
|
380 // So on return, aData starts with a TInt containing the number of lines |
|
381 // Each line follows, preceded with a TInt containing its length |
|
382 // which must be copied as it might not be aligned on a 4-byte |
|
383 // boundary - a line of zero length indicates we have reached |
|
384 // the end of the page |
|
385 |
|
386 void CFaxModemDriver::GetFaxDataL (TDes8 * aData) |
|
387 { |
|
388 TUint8 *startData; |
|
389 TUint8 *lineData; |
|
390 const TUint8 *maxData; |
|
391 TInt lineLength; |
|
392 TInt numberOfLines = 0; |
|
393 |
|
394 lineData = startData = CONST_CAST (TUint8 *, (*aData).Ptr ()); |
|
395 maxData = startData + (*aData).MaxLength () - KMaxT4Des - sizeof (TInt); |
|
396 |
|
397 (*aData).SetMax (); |
|
398 lineData += sizeof (TInt); |
|
399 |
|
400 for (;;) |
|
401 { |
|
402 numberOfLines++; |
|
403 lineLength = GetLineL (lineData); |
|
404 Mem::Copy (lineData, &lineLength, sizeof (TInt)); |
|
405 lineData += sizeof (TInt); |
|
406 lineData += lineLength; |
|
407 if (lineData > maxData) |
|
408 break; |
|
409 if (lineLength == 0) |
|
410 break; |
|
411 } |
|
412 Mem::Copy (startData, &numberOfLines, sizeof (TInt)); |
|
413 (*aData).SetLength (lineData - startData); |
|
414 |
|
415 // buffering debug message |
|
416 |
|
417 iModem->iOurMessage.Format (_L8 ("%u lines in buffer taking up %u bytes"), numberOfLines, (*aData).Length ()); |
|
418 iModem->ProgressUpdateL (); |
|
419 } |
|
420 /********************************************************************/ |
|
421 // This function takes a pointer to a binary data buffer. |
|
422 // We are guaranteed that the buffer is big enough to take |
|
423 // an entire scan line up to KMaxT4Des in size. |
|
424 // We receive the scan line, with a leave if we timeout. |
|
425 // We return with the length of the scan line and the buffer has |
|
426 // a space for this to be placed as an integer by the caller, |
|
427 // followed by the scan line data. If the length of the scan line |
|
428 // is zero, we have reached the end of the page |
|
429 |
|
430 TInt CFaxModemDriver::GetLineL (TUint8 * aFaxData) |
|
431 { |
|
432 TUint8 *lineStart; |
|
433 TUint8 *lineEnd; |
|
434 TUint8 *currentByte; |
|
435 |
|
436 lineStart = currentByte = (aFaxData + sizeof (TInt)); |
|
437 lineEnd = lineStart + KMaxT4Des; |
|
438 |
|
439 TUint8 thisChar = 0; |
|
440 TUint8 leading0s = 0; |
|
441 TUint8 trailing0s = 0; |
|
442 TInt nullcount = 0; |
|
443 |
|
444 TInt ticks = CLK_TCK * KLineReadTimeout; |
|
445 if (iModem->iProgress.iECM != 0) |
|
446 ticks = CLK_TCK * KECMLineReadTimeout; |
|
447 |
|
448 iModem->iProgress.iLines++; |
|
449 |
|
450 TInt bol = 1; |
|
451 TUint8 lastChar = 0xff; |
|
452 |
|
453 // lastChar set to 0xff flags the entry to the function |
|
454 // during iterations lastChar must be either 0 or 1 |
|
455 // we always come here just after detecting an EOL, and the character |
|
456 // which contains the EOL bit is guaranteed to be re-readable |
|
457 // lastChar set to 0xff indicates that's is not been read, |
|
458 // so we re-read it, set its trailing0s, and put it in the buffer |
|
459 // without bothering to do any dle checking (we already know it's ok) |
|
460 |
|
461 for (;;) |
|
462 { |
|
463 if (lastChar == 0xff) |
|
464 { |
|
465 lastChar = 0; |
|
466 thisChar = iModem->iReadone[0]; |
|
467 } |
|
468 else |
|
469 { |
|
470 if ((iModem->RxcharWaitL (ticks)) == 0) |
|
471 User::Leave (KFaxErrReceiveTimeout); |
|
472 thisChar = iModem->iReadone[0]; |
|
473 |
|
474 // check if we have the character after a leading dle |
|
475 // if we have unmark the last character as being a dle - |
|
476 // dle etx is end of data |
|
477 // dle dle is a shielded dle |
|
478 // dle sub is two times dle for class 2.0 only |
|
479 // dle and anything else we ignore |
|
480 |
|
481 if (lastChar == Kdle) |
|
482 { |
|
483 lastChar = 0; |
|
484 |
|
485 if (thisChar == Ketx) |
|
486 { |
|
487 iModem->iOurMessage.Format (_L8 ("<dle><etx> detected after %u lines"), iModem->iProgress.iLines); |
|
488 iModem->ProgressUpdateL (); |
|
489 return (0); |
|
490 } |
|
491 |
|
492 if (iFaxServerSessionSettings->iFaxClass == EClass2point0) |
|
493 { |
|
494 if (thisChar == 0x1a) |
|
495 { |
|
496 thisChar = Kdle; |
|
497 *currentByte++ = Invert (thisChar); // invert class 2.0 |
|
498 if (currentByte == lineEnd) |
|
499 { |
|
500 return (KMaxT4Des); |
|
501 } |
|
502 trailing0s = 4; |
|
503 } |
|
504 } |
|
505 |
|
506 if (thisChar != Kdle) |
|
507 continue; |
|
508 } // drop through only with a data dle |
|
509 |
|
510 // if not a trailing dle |
|
511 // check if this character is itself a leading dle |
|
512 // drop through only if it isn't |
|
513 |
|
514 else if (thisChar == Kdle) |
|
515 { |
|
516 lastChar = Kdle; |
|
517 continue; |
|
518 } |
|
519 } |
|
520 |
|
521 // if we've received six EOL codes already, ignore everything |
|
522 // till dle etx arrives |
|
523 |
|
524 if (bol == 6) |
|
525 continue; |
|
526 |
|
527 // have we a null ? if yes we ignore nulls if they come in |
|
528 // anything more than pairs - if no, we zero nullcount and |
|
529 // invert the byte back the right way for non-class 2 modems |
|
530 // THIS LAST IS IMPORTANT |
|
531 |
|
532 if (thisChar == Knul) |
|
533 { |
|
534 if (nullcount == 2) |
|
535 continue; |
|
536 else |
|
537 nullcount++; |
|
538 } |
|
539 else |
|
540 { |
|
541 nullcount = 0; |
|
542 if (iFaxServerSessionSettings->iFaxClass != EClass2) |
|
543 thisChar = Invert (thisChar); |
|
544 } |
|
545 |
|
546 // count the leading zeros in this byte |
|
547 |
|
548 leading0s = zerotable[thisChar][0]; |
|
549 |
|
550 // if the leading zeros in this byte and the trailing zeros in the |
|
551 // previous byte total 11 or more we have ourselves an EOL |
|
552 // so we write the data we have so far as an entire line |
|
553 // we are guaranteed than an eol will span at least two bytes |
|
554 // so the data we have must include the end of the last line |
|
555 // if this is a nul we don't write anything yet as we haven't |
|
556 // detected a proper eol code |
|
557 // we don't write anything for consecutibe eols |
|
558 |
|
559 if (((trailing0s + leading0s) > 10) && (thisChar != Knul)) |
|
560 { |
|
561 bol++; |
|
562 if ((bol == 1) && (currentByte != lineStart)) |
|
563 { |
|
564 return (currentByte - lineStart); |
|
565 } |
|
566 if (iModem->iProgress.iECM == 0) |
|
567 ticks = CLK_TCK * KSubsequentLineReadTimeout; |
|
568 else |
|
569 ticks = CLK_TCK * KSubsequentECMLineReadTimeout; // 11/1/01 AMC: ECM requires longer time-outs due to retries |
|
570 } |
|
571 |
|
572 // else if we had received an eol and this character is not nul |
|
573 // we have ourselves a new line start |
|
574 |
|
575 else |
|
576 { |
|
577 if (bol) |
|
578 if (thisChar != Knul) |
|
579 bol = 0; |
|
580 } |
|
581 |
|
582 // if we have a nul, add 8 to our trailing zero bits |
|
583 // else count them by hand |
|
584 |
|
585 if (thisChar == Knul) |
|
586 trailing0s += 8; |
|
587 else |
|
588 trailing0s = zerotable[thisChar][1]; |
|
589 |
|
590 // ignore multiple eols |
|
591 |
|
592 if (bol > 1) |
|
593 continue; |
|
594 |
|
595 // save everything else - we've already inverted the data if needed |
|
596 |
|
597 *currentByte++ = thisChar; |
|
598 if (currentByte == lineEnd) |
|
599 { |
|
600 return (KMaxT4Des); |
|
601 } |
|
602 } |
|
603 } |
|
604 /********************************************************************/ |
|
605 |
|
606 TInt CFaxModemDriver::TxStartPageL () |
|
607 { |
|
608 iModem->iProgress.iPhase = EDataTransfer; |
|
609 iModem->iProgress.iLines = 0; |
|
610 iModem->iOurMessage.Format (_L8 ("About to send page %u"), ++iModem->iProgress.iPage); |
|
611 iModem->ProgressUpdateL (); |
|
612 iModem->Xonon (); |
|
613 |
|
614 // for class 1 modems we start each page with a short burst of binary 1s |
|
615 |
|
616 if (iFaxServerSessionSettings->iFaxClass == EClass1) |
|
617 { |
|
618 for (TInt x = (iActualFaxSpeed * 20 / 8); x; x--) |
|
619 { |
|
620 iModem->iTransmitBuffer.Append (0xff); |
|
621 iModem->SendTransmitBufferL (); |
|
622 } |
|
623 iModem->CommitTransmitBufferL (); |
|
624 } |
|
625 |
|
626 // we're now in phase C so we start the page by sending the fax header |
|
627 |
|
628 SendFaxHeaderL (); |
|
629 return (KErrNone); |
|
630 } |
|
631 /********************************************************************/ |
|
632 |
|
633 TInt CFaxModemDriver::RxStartPageL () |
|
634 { |
|
635 TUint8 thisChar, leading0s, trailing0s = 0; |
|
636 TInt ticks = CLK_TCK * KLineReadTimeout; |
|
637 if (iModem->iProgress.iECM != 0) |
|
638 ticks = CLK_TCK * KECMLineReadTimeout; // ECM mode requires longer time-outs due to retries |
|
639 |
|
640 iModem->iProgress.iPhase = EDataTransfer; |
|
641 iModem->iProgress.iLines = 0; |
|
642 iModem->iOurMessage.Format (_L8 ("Awaiting page %u"), ++iModem->iProgress.iPage); |
|
643 iModem->ProgressUpdateL (); |
|
644 trailing0s = 0; |
|
645 |
|
646 // this function looks for the start of the received fax |
|
647 // this is the first EOL code - we invert bytes for non-class 2 modems |
|
648 |
|
649 for (;;) |
|
650 { |
|
651 if ((iModem->RxcharWaitL (ticks)) == 0) |
|
652 return (KFaxErrReceiveTimeout); |
|
653 thisChar = iModem->iReadone[0]; |
|
654 if (iFaxServerSessionSettings->iFaxClass != EClass2) |
|
655 thisChar = Invert (thisChar); |
|
656 leading0s = zerotable[thisChar][0]; |
|
657 if (((trailing0s + leading0s) > 10) && (thisChar != 0)) |
|
658 break; |
|
659 if (thisChar == Knul) |
|
660 trailing0s += 8; |
|
661 else |
|
662 trailing0s = zerotable[thisChar][1]; |
|
663 } |
|
664 |
|
665 // we've found the first EOL - it's left in iModem->iReadone[0] |
|
666 |
|
667 iModem->iOurMessage.Format (_L8 ("Receiving data .... ")); |
|
668 iModem->ProgressUpdateL (); |
|
669 return (KErrNone); |
|
670 } |
|
671 /********************************************************************/ |
|
672 |
|
673 TInt CFaxModemDriver::RxConnectL () |
|
674 { |
|
675 return (KFaxErrWrongModemType); |
|
676 } |
|
677 TInt CFaxModemDriver::RxPrePageL () |
|
678 { |
|
679 return (KFaxErrWrongModemType); |
|
680 } |
|
681 TInt CFaxModemDriver::RxPostPageL () |
|
682 { |
|
683 return (KFaxErrWrongModemType); |
|
684 } |
|
685 TInt CFaxModemDriver::TxConnectL () |
|
686 { |
|
687 return (KFaxErrWrongModemType); |
|
688 } |
|
689 TInt CFaxModemDriver::TxPrePageL () |
|
690 { |
|
691 return (KFaxErrWrongModemType); |
|
692 } |
|
693 TInt CFaxModemDriver::TxPostPageL () |
|
694 { |
|
695 return (KFaxErrWrongModemType); |
|
696 } |
|
697 /********************************************************************/ |
|
698 |
|
699 |
|
700 |
|
701 |