fax/faxclientandserver/FAXSVR/CFAX2.CPP
changeset 0 3553901f7fa8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fax/faxclientandserver/FAXSVR/CFAX2.CPP	Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,609 @@
+// 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:
+//
+
+#include "FAXSERV.H"
+#include "fax_reversebytes.h"
+#include "FAXMODEM.H"
+#include "FAXMDRV.H"
+
+#include "FAXLOG.H"
+
+
+const TInt KClass2HangupStatusTimer=20;	// < Time used to wait for final +FHNG: report.
+
+// this module has three parts
+// first receive routines rx
+// second transmit routines tx
+// third utilities
+
+/********************************************************************/
+
+CFaxModemDriver *CFaxClass2::NewLC (TFaxServerSessionSettings * aFaxServerSessionSettings, RFax::TProgress & aProgress)
+{
+	CFaxModemDriver *self = new (ELeave) CFaxClass2;
+	CleanupStack::PushL (self);
+	self->ConstructL (aFaxServerSessionSettings, aProgress);
+	return self;
+}
+
+CFaxModemDriver *CFaxClass2::NewL (TFaxServerSessionSettings * aFaxServerSessionSettings, RFax::TProgress & aProgress)
+{
+	CFaxModemDriver *self = NewLC (aFaxServerSessionSettings, aProgress);
+	CleanupStack::Pop ();
+	return self;
+}
+/********************************************************************/
+
+TInt CFaxClass2::RxConnectL ()
+{
+	__FLOG_FAXSRV( _L8("CFaxClass2::RxConnectL entering"));
+	
+	CheckCadenceExportL (_L8 ("AT+FDCC=?\r"));
+	if (!(iModem->ImportL (iResults, 35)))
+		return (KFaxErrModemNotWorking);
+
+	iModem->iOurMessage.Format (_L8 ("%S"), &iResults);
+	iModem->ProgressUpdateL ();
+	ParseResults (iResults);
+
+	iModem->GetMatchL (_L8 ("OK"), 2);
+
+	if (iFaxServerSessionSettings->iRxResolution == EFaxNormal)
+		iModem->iProgress.iResolution = EFaxNormal;
+	else
+		iModem->iProgress.iResolution = EFaxFine;
+
+	if (iFaxServerSessionSettings->iRxCompression == EModifiedRead)
+		iModem->iProgress.iCompression = EModifiedRead;
+	else
+		iModem->iProgress.iCompression = EModifiedHuffman;
+	iActualFaxSpeed = iModem->iProgress.iSpeed;
+	if (iActualFaxSpeed > iFaxServerSessionSettings->iMaxSpeed)
+		iActualFaxSpeed = iFaxServerSessionSettings->iMaxSpeed;
+
+	iResults.Copy (_L8 ("AT+FDCC=0,0,0,2,0,0,0,0\r"));
+
+	iResults[8] = (TUint8) (iResults[8] + iModem->iProgress.iResolution);
+	iResults[10] = (TUint8) (((iActualFaxSpeed / 2400) - 1) + '0');
+	iResults[16] = (TUint8) (iResults[16] + iModem->iProgress.iCompression);
+	CheckCadenceExportL (iResults);
+	if ((iModem->GetMatchL (_L8 ("OK"), 3)) == 0)
+		return (KFaxErrModemNotWorking);
+	CheckCadenceExportL (_L8 ("AT+FAA=0\r"));
+	if ((iModem->GetMatchL (_L8 ("OK"), 5)) == 0)
+		return (KFaxErrNoReceiveMode);
+	
+	TBuf8<RCall::KFaxIdUserNameMaxSize> narrowBuf;
+	narrowBuf.Copy(iFaxServerSessionSettings->iFaxId);
+	
+	//-- By Dmitry Lyokhin. concerns PIA-58ELQK defect.
+	if( narrowBuf.Length() < 1 ) narrowBuf.Append(' ');
+
+
+	if (iFaxServerSessionSettings->iMode & KFaxPoll)
+		{
+		iModem->ExportL (_L8 ("AT+FSPL=1\r"));
+		if ((iModem->GetMatchL (_L8 ("OK"), 5)) == 0)
+			return (KFaxPollingUnsupported);
+		iModem->ExportL (_L8 ("AT+FCIG=\""));
+		iModem->ExportL (narrowBuf);
+		iModem->ExportL (_L8 ("\"\r"));
+		if ((iModem->GetMatchL (_L8 ("OK"), 3)) == 0)
+			return (KFaxPollingUnsupported);
+		}
+	else
+		{
+		CheckCadenceExportL (_L8 ("AT+FCR=1\r"));
+		if ((iModem->GetMatchL (_L8 ("OK"), 5)) == 0)
+			return (KFaxErrNoReceiveMode);
+		CheckCadenceExportL (_L8 ("AT+FLID=\""));
+		iModem->ExportL (narrowBuf);
+		iModem->ExportL (_L8 ("\"\r"));
+		if ((iModem->GetMatchL (_L8 ("OK"), 3)) == 0)
+			return (KFaxErrModemNotWorking);
+		}
+
+	if (iFaxServerSessionSettings->iMode & KFaxWaitForRing)
+		{
+//		while ((iModem->GetMatchL (_L8 ("RING"), 3)) == 0);
+//		iTimeOfLastRing.UniversalTime();
+		}
+	else
+		{
+		if ((iFaxServerSessionSettings->iMode & KFaxOffHook) == 0)
+			DialFaxOnDemandL ();
+		}
+
+	if ((iFaxServerSessionSettings->iMode & KFaxPoll) == 0)
+		{
+		iModem->Silence (CLK_TCK);
+		CheckCadenceExportL (_L8 ("ATA\r"));
+		}
+
+	iModem->iProgress.iPhase = ECallEstablishment;
+
+	TInt pollDocsAvailable = 0;
+
+	for (;;)
+		{
+		if (!(iModem->ImportL (iResults, 35)))
+			return (KFaxErrCannotAnswer);
+
+		iModem->iOurMessage.Format (_L8 ("%S"), &iResults);
+		iModem->ProgressUpdateL ();
+
+		if ((iResults.FindF (_L8 ("NO DIALTONE"))) >= 0 ||
+			iResults.FindF (_L8 ("NO DIAL TONE")) >= 0)
+			return (KFaxErrNoDialTone);
+		if ((iResults.FindF (_L8 ("BUSY"))) >= 0)
+			return (KFaxErrBusy);
+		if ((iResults.FindF (_L8 ("NO ANSWER"))) >= 0)
+			return (KFaxErrNoAnswer);
+		if ((iResults.FindF (_L8 ("NO CARRIER"))) >= 0)
+			return (KFaxErrNoCarrier);
+		if ((iResults.FindF (_L8 ("OK"))) >= 0)
+			break;
+		if ((iResults.FindF (_L8 ("FHNG"))) >= 0)
+			return (KFaxErrPrematureHangup);
+		if ((iResults.FindF (_L8 ("FCON"))) >= 0)
+			iModem->iProgress.iPhase = ESessionNegotiation;
+		else if ((iResults.FindF (_L8 ("FPOLL"))) >= 0)
+			pollDocsAvailable = 1;
+		else if ((iResults.FindF (_L8 ("FTSI"))) >= 0)
+			ExtractAnswerback (iResults);
+		else if ((iResults.FindF (_L8 ("FDCS"))) >= 0)
+			ParseResults (iResults);
+		}
+
+	if ((iFaxServerSessionSettings->iMode & KFaxPoll) && (pollDocsAvailable == 0))
+		return (KFaxNothingToPoll);
+
+	iModem->iOurMessage.Format (_L8 ("about to receive fax"));
+	iModem->ProgressUpdateL ();
+	return (RxPrePageL ());
+}
+
+/********************************************************************/
+TInt CFaxClass2::RxPrePageL ()
+{
+	__FLOG_FAXSRV( _L8("CFaxClass2::RxPrePageL entering"));
+
+	iModem->ExportL (_L8 ("AT+FDR\r"));
+	for (;;)
+		{
+		if (!(iModem->ImportL (iResults, 35)))
+			return (KFaxErrCannotConnect);
+
+		iModem->iOurMessage.Format (_L8 ("%S"), &iResults);
+		iModem->ProgressUpdateL ();
+
+		if ((iResults.FindF (_L8 ("ERROR"))) >= 0)
+			return (KFaxErrNoReceiveMode);
+		if ((iResults.FindF (_L8 ("FHNG"))) >= 0)
+			return (KFaxErrPrematureHangup);
+		if ((iResults.FindF (_L8 ("CONNECT"))) >= 0)
+			break;
+		if ((iResults.FindF (_L8 ("FDCS"))) >= 0)
+			ParseResults (iResults);
+		}
+
+	iModem->TxcharL (Kdc2);
+	return (RxStartPageL ());
+}
+/********************************************************************/
+TInt CFaxClass2::RxPostPageL ()
+{
+	__FLOG_FAXSRV(_L8("CFaxClass2::RxPostPageL entering"));
+
+	iModem->iProgress.iPhase = EPostPageStatus;
+	iModem->ProgressUpdateL ();
+	for (;;)
+		{
+		if (!(iModem->ImportL (iResults, 20)))
+			return (KFaxErrModemResponse);
+
+		iModem->iOurMessage.Format (_L8 ("%S"), &iResults);
+		iModem->ProgressUpdateL ();
+
+		if ((iResults.FindF (_L8 ("OK"))) >= 0)
+			return (KFaxErrPrematureOK);
+		if ((iResults.FindF (_L8 ("FHNG"))) >= 0)
+			return (KFaxErrPrematureHangup);
+		if ((iResults.FindF (_L8 ("FET"))) >= 0)
+			break;
+		}
+	if (iModem->GetMatchL (_L8 ("OK"), 5) == 0)
+		return (KFaxErrNoFinalOK);
+
+	if ((iResults.FindF (_L8 ("0"))) >= 0)
+		{
+		iModem->iOurMessage.Format (_L8 ("page %u successfully received"), iModem->iProgress.iPage);
+		iModem->ProgressUpdateL ();
+		return (RxPrePageL ());
+		}
+	if ((iResults.FindF (_L8 ("1"))) >= 0)
+		{
+		iModem->iOurMessage.Format (_L8 ("page %u successfully received : end of document"), iModem->iProgress.iPage);
+		iModem->ProgressUpdateL ();
+		iModem->iOurMessage.Format (_L8 ("Next fax awaited"));
+		iModem->ProgressUpdateL ();
+		return (RxPrePageL ());
+		}
+	if ((iResults.FindF (_L8 ("2"))) >= 0)
+		{
+		iModem->iOurMessage.Format (_L8 ("Final page %u successfully received"), iModem->iProgress.iPage);
+		iModem->ProgressUpdateL ();
+		iModem->iProgress.iPhase = EDisconnection;
+		iModem->ExportL (_L8 ("AT+FDR\r"));
+		if (iModem->GetMatchL (_L8 ("FHNG"), KClass2HangupStatusTimer) == 0)
+			return (KFaxErrNoHangup);
+		if (iModem->GetMatchL (_L8 ("OK"), 5) == 0)
+			return (KFaxErrNoFinalOK);
+		return (KErrNone);
+		}
+	return (KFaxErrUnknownPageCode);
+}
+/********************************************************************/
+
+TInt CFaxClass2::TxConnectL ()
+{
+	// we always use direct bit order when sending
+	// we always use reversed bit order when receiving
+	// this is in accordance with the rockwell bug.
+	// if a modem doesn't have the rockwell bug then
+	// the fax init string AT+FBOR=1 will force the
+	// use of reversed bit ordering on reception.
+	// since we have here a hardwired default AT+FBOR=0
+	// on transmission this will override the init string
+	// which will therefore only be used (as needed) for
+	// reception, and everything will work again
+
+    __FLOG_FAXSRV( _L8("CFaxClass2::TxConnectL entering"));
+
+	iModem->ExportL (_L8 ("AT+FBOR=0\r"));
+	iModem->GetMatchL (_L8 ("OK"), 3);
+
+	TBuf8<RCall::KFaxIdUserNameMaxSize> narrowBuf;
+	narrowBuf.Copy(iFaxServerSessionSettings->iFaxId);
+	
+	//-- if the fax local id string is empty, insert blank
+	//-- PIA-58ELQK defect fix by Dmitry Lyokhin 26.03.2001
+	if( narrowBuf.Length() < 1 ) narrowBuf.Append(' ');
+
+
+	iModem->ExportL (_L8 ("AT+FLID=\""));
+	iModem->ExportL (narrowBuf);
+	iModem->ExportL (_L8 ("\"\r"));
+	if ((iModem->GetMatchL (_L8 ("OK"), 3)) == 0)
+		return (KFaxErrModemNotWorking);
+
+	iModem->ExportL (_L8 ("AT+FDCC=?\r"));
+	if (!(iModem->ImportL (iResults, 35)))
+		return (KFaxErrModemNotWorking);
+
+	iModem->iOurMessage.Format (_L8 ("%S"), &iResults);
+	iModem->ProgressUpdateL ();
+	ParseResults (iResults);
+
+	iModem->GetMatchL (_L8 ("OK"), 2);
+
+	iActualFaxSpeed = iModem->iProgress.iSpeed;
+	if (iActualFaxSpeed > iFaxServerSessionSettings->iMaxSpeed)
+		iActualFaxSpeed = iFaxServerSessionSettings->iMaxSpeed;
+
+	iResults.Copy (_L8 ("AT+FDCC=0,0,0,2,0,0,0,0\r"));
+
+	iResults[8] = (TUint8) (iResults[8] + iFaxServerSessionSettings->iTxResolution);
+	iResults[10] = (TUint8) (((iActualFaxSpeed / 2400) - 1) + '0');
+
+
+	// added to support 2Dfaxing using class 2
+	if (iModem->iProgress.iCompression==EModifiedRead)
+		iResults[16] = (TUint8) (iResults[16] + iFaxServerSessionSettings->iTxCompression);
+	else
+		iResults[16] = (TUint8) (iResults[16] + EModifiedHuffman);
+
+	iModem->ExportL (iResults);
+	if ((iModem->GetMatchL (_L8 ("OK"), 3)) == 0)
+		return (KFaxErrModemNotWorking);
+
+	iModem->ExportL (_L8 ("ATD"));
+	if ((iFaxServerSessionSettings->iMode & KFaxOffHook) == 0)
+		iModem->ExportL (iFaxServerSessionSettings->iPhoneNumber);
+	iModem->TxcharL (Kreturn);
+
+	iModem->iProgress.iPhase = ECallEstablishment;
+	for (;;)
+		{
+		if (!(iModem->ImportL (iResults, KDialTimeout)))
+			return (KFaxErrNoDial);
+
+		iModem->iOurMessage.Format (_L8 ("%S"), &iResults);
+		iModem->ProgressUpdateL ();
+
+		if ((iResults.FindF (_L8 ("NO DIALTONE"))) >= 0 ||
+			iResults.FindF (_L8 ("NO DIAL TONE")) >= 0)
+			return (KFaxErrNoDialTone);
+		if ((iResults.FindF (_L8 ("BUSY"))) >= 0)
+			return (KFaxErrBusy);
+		if ((iResults.FindF (_L8 ("NO ANSWER"))) >= 0)
+			return (KFaxErrNoAnswer);
+		if ((iResults.FindF (_L8 ("NO CARRIER"))) >= 0)
+			return (KFaxErrNoCarrier);
+		if ((iResults.FindF (_L8 ("FHNG"))) >= 0)
+			return (KFaxErrNoNegotiate);
+		if ((iResults.FindF (_L8 ("OK"))) >= 0)
+			break;
+		if ((iResults.FindF (_L8 ("FCON"))) >= 0)
+			iModem->iProgress.iPhase = ESessionNegotiation;
+		else if ((iResults.FindF (_L8 ("FCSI"))) >= 0)
+			ExtractAnswerback (iResults);
+		}
+	return (TxPrePageL ());
+}
+/********************************************************************/
+TInt CFaxClass2::TxPrePageL ()
+{
+    __FLOG_FAXSRV( _L8("CFaxClass2::TxPrePageL entering"));
+
+	iModem->ExportL (_L8 ("AT+FDT\r"));
+	for (;;)
+		{
+		if (!(iModem->ImportL (iResults, 30)))
+			return (KFaxErrNoNegotiate);
+
+		iModem->iOurMessage.Format (_L8 ("%S"), &iResults);
+		iModem->ProgressUpdateL ();
+
+		if ((iResults.FindF (_L8 ("FHNG"))) >= 0)
+			return (KFaxErrNoNegotiate);
+		if ((iResults.FindF (_L8 ("CONNECT"))) >= 0)
+			break;
+		if ((iResults.FindF (_L8 ("FDCS"))) >= 0)
+			ParseResults (iResults);
+		}
+
+	for (;;)
+		{
+		
+		//TInt ticks = CLK_TCK * 10;
+		//-- PIA-58ELQK defect fix by Dmitry Lyokhin 26.03.2001
+		TInt XonTimeoutSec = CLK_TCK * 3; 
+		
+		if ((iModem->RxcharWaitL (XonTimeoutSec)) == 0)
+		{
+			//-- XON character sending timeout. Ignore. 
+			//-- PIA-58ELQK defect fix by Dmitry Lyokhin 26.03.2001
+			//return (KFaxNoClass2Xon);
+			break;
+		}
+
+		if (iModem->iReadone[0] == Kxon)
+			break;
+		}
+	return (TxStartPageL ());
+}
+/********************************************************************/
+
+//
+ // TxPostPage should return either with
+ //
+ // a) an error code and iPhase set to RFax::EPostPageStatus, in which case the send returns with the error
+ // b) KErrNone and iPhase set to RFax::EDataTransfer, in which case we send the next page
+ // c) KErrNone and iPhase set to RFax::EDisconnection, in which case the send returns with KErrNone
+ //
+
+TInt CFaxClass2::TxPostPageL ()
+{
+	
+	iModem->iTransmitBuffer.Append (Kdle);
+	iModem->iTransmitBuffer.Append (Ketx);
+	iModem->CommitTransmitBufferL ();
+
+	iModem->iOurMessage.Format (_L8 ("<dle><etx> transmitted after %d lines"), iModem->iProgress.iLines);
+	
+    __FLOG_FAXSRV(iModem->iOurMessage);
+
+	iModem->iProgress.iPhase = EPostPageStatus;
+	iModem->ProgressUpdateL ();
+	while (iModem->Txstat () != 0)
+		;
+
+	// we've just ended phase C data, so we need to wait for the modem to respond with OK
+
+
+
+	if (iModem->GetMatchL (_L8 ("OK"), (32 * 1024) / (iModem->iProgress.iSpeed / 10)) == 0)
+		return (KFaxErrCannotEndData);
+
+	iModem->Xonoff ();
+
+	if (iFaxServerSessionSettings->iTxPages == iModem->iProgress.iPage)
+		{
+		iModem->ExportL (_L8 ("AT+FET=2\r"));
+		iModem->iOurMessage.Format (_L8 ("End of document transmitted EOP frame"));
+		}
+	else
+		{
+		iModem->ExportL (_L8 ("AT+FET=0\r"));
+		iModem->iOurMessage.Format (_L8 ("End of page %u transmitted MPS frame"), iModem->iProgress.iPage);
+		}
+	iModem->ProgressUpdateL ();
+
+	for (;;)
+		{
+		
+//#if defined (__WINS__)
+//		RDebug::Print(_L("NOW"));
+//#endif
+
+
+		if (!(iModem->ImportL (iResults, 30)))
+		{
+			return (KFaxErrModemResponse);
+		}
+
+		iModem->iOurMessage.Format (_L8 ("%S"), &iResults);
+		iModem->ProgressUpdateL ();
+
+		if ((iResults.FindF (_L8 ("FHNG"))) >= 0)
+			{
+			if (iResults[7] == '0')
+				break;
+			return (KFaxErrNoNegotiate);
+			}
+
+		if ((iResults.FindF (_L8 ("FPTS"))) >= 0)
+			{
+				
+				if (iResults.FindF (_L8("1"))==6)		// 6 is the position of the error code in descriptor
+					{
+						iModem->iOurMessage.Append (_L8("FPTS:1  MCF frame"));
+						iModem->ProgressUpdateL ();	
+						break;
+					}
+				else if (iResults.FindF(_L8("2"))==6)
+					{
+						iModem->iOurMessage.Append (_L8("FPTS:2  RTN frame"));
+						iModem->ProgressUpdateL ();	
+						break;
+					}
+				else if (iResults.FindF(_L8("3"))==6)
+					{
+						iModem->iOurMessage.Append (_L8("FPTS:3  RTP frame"));
+						iModem->ProgressUpdateL ();	
+						break;
+					}
+				else if (iResults.FindF(_L8("4"))==6)
+					{
+						iModem->iOurMessage.Append (_L8("FPTS:4  PIN frame"));
+						iModem->ProgressUpdateL ();	
+						break;
+					}
+				else if (iResults.FindF(_L8("5"))==6)
+					{
+						iModem->iOurMessage.Append (_L8("FPTS:5  PIP frame"));
+						iModem->ProgressUpdateL ();	
+						break;
+					}  
+				break;
+	
+			}
+	} // for(;;) ends here
+
+	if (iModem->GetMatchL (_L8 ("OK"), 5) == 0)
+		return (KFaxErrNoFinalOK);
+
+	if ((((iResults.FindF (_L8 ("2"))) >= 0) || (iResults.FindF (_L8 ("4")) >= 0)) && (iRepeatPage <= 3))  //RTN and 
+	{																								       //PIN  responses
+		iModem->iProgress.iPhase = ESessionNegotiation;
+		iRepeatPage++;
+		iModem->iProgress.iPage--;
+		return (TxPrePageL ());
+		}
+	if (iFaxServerSessionSettings->iTxPages != iModem->iProgress.iPage)
+		{
+		iRepeatPage = 0;
+		return (TxPrePageL ());
+		}
+	iModem->iProgress.iPhase = EDisconnection;
+	return (KErrNone);
+}
+/********************************************************************/
+
+// this routine parses both class 2 and class 2.0
+ // T.30 session subparameter strings, from both interrogatories
+ // and reports - for interrogatories, we assume that later capabilities
+ // (inside the brackets) are preferable to earlier ones
+
+// amended July 1998 to support ECM for class 2.0
+
+void CFaxClass2::ParseResults (TDesC8 & aResults)
+{
+	TInt x, field, inbracket;
+	static const TInt minscans[][2] =
+		{
+			{0, 0
+			},
+			{5, 5
+			},
+			{10, 5
+			},
+			{10, 10
+			},
+			{20, 10
+			},
+			{20, 20
+			},
+			{40, 20
+			},
+			{40, 40
+			}
+		};
+
+	for ( x = 0, field = 0, inbracket = 0; x < aResults.Length (); x++)
+		{
+		if ((aResults[x] > '0' - 1) && (aResults[x] < '9' + 1))
+			{
+			if (field == 0)
+				iModem->iProgress.iResolution = TFaxResolution (aResults[x] & 1);
+			else if (field == 1)
+				iModem->iProgress.iSpeed = (aResults[x] - '0' + 1) * 2400;
+			else if (field == 4)
+				iModem->iProgress.iCompression = TFaxCompression (aResults[x] & 1);
+			else if (field == 5)
+				iModem->iProgress.iECM = (aResults[x] - '0');
+			else if (field == 7)
+				{
+				iMinscan = minscans[aResults[x] - '0'][iModem->iProgress.iResolution];
+				if (iMinscan == 0)
+					iMinlinelength = 0;
+				else
+					iMinlinelength = ((iModem->iProgress.iSpeed / (1000 / iMinscan)) / 8) + 1;
+				}
+			}
+		if (aResults[x] == 0)
+			break;
+		if (aResults[x] == 0x28)
+			inbracket = 1;
+		if (aResults[x] == 0x29)
+			inbracket = 0;
+		if ((aResults[x] == 0x2c) && (inbracket == 0))
+			field++;
+		if (field == 8)
+			break;
+		}
+	if (iFaxServerSessionSettings->iFaxClass == EClass2)
+		iModem->iProgress.iECM = 0;       // no ECM using class 2
+	if (iModem->iProgress.iECM)
+		iModem->iProgress.iECM = 1;       // and treat EC as a boolean
+}
+/********************************************************************/
+
+// this routine extract an ID string from a result code
+
+void CFaxClass2::ExtractAnswerback (TDesC8 & aResults)
+{
+	TInt startID = aResults.Locate (0x22);
+	if (startID != KErrNotFound)
+		{
+		startID++;
+		TInt maxIDlength = (aResults.Length () - startID);
+		if (maxIDlength > 20)
+			maxIDlength = 20;
+		iModem->iProgress.iAnswerback.Copy (aResults.Mid (startID, maxIDlength));
+		}
+}
+/********************************************************************/