kerneltest/e32test/device/t_loop.cpp
changeset 0 a41df078684a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/device/t_loop.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,1677 @@
+// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test\device\t_loop.cpp
+// 
+//
+
+//#define _DEBUG_DEVCOMM
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32test.h>
+#include <e32svr.h>
+#include <d32comm.h>
+#include <e32math.h>
+#include <e32uid.h>
+
+#if defined (__WINS__)
+#define __COMM_LDD _L("ECOMM")
+#define __COMM_PDD1 _L("ECDRV")
+#else
+#define __COMM_LDD _L("ECOMM")
+#define __COMM_PDD1 _L("EUART1")
+#define __COMM_PDD2 _L("EUART2")
+#endif
+
+const char KSpinner[]={'|','/','-','\\',};
+
+const TInt KKeyboardPriority	= 4;
+const TInt KTimerPriority		= 3;
+const TInt KWriterPriority		= 2;
+const TInt KReaderPriority		= 1;
+
+////////////////////////////////////////////////////////////////////////////////
+
+RTest Test(_L("T_LOOP"));
+
+#define TEST(a) __DoTest((a), __FILE__, __LINE__, 0)
+#define TESTERR(a,b) __DoTest((a), __FILE__, __LINE__, b)
+
+void __DoTest(TBool aCondition, char* aFile, TInt aLine, TInt aErr)
+	{
+	if (aCondition)
+		return;
+		
+	if (aErr==0)
+		Test.Printf(_L("\r\nCheckpoint Fail at %s:%d\r\n"), aFile, aLine);
+	else
+		Test.Printf(_L("\r\nCheckpoint Fail at %s:%d: Return code = %d (0x%x)\r\n"), aFile, aLine, aErr, aErr);
+	__DEBUGGER();
+	Test.Getch();
+	User::Exit(aErr);
+	}
+
+////////////////////////////////////////////////////////////////////////////////
+
+class CDevCommTestBase;
+
+// This needs:
+// inline void Read(TRequestStatus &aStatus) { iConsole->Read(aStatus); }
+// inline void ReadCancel() { iConsole->ReadCancel(); }
+// inline void TKeyCode KeyCode() { return iConsole->KeyCode(); }
+// adding to RTest
+
+class CKeyReader : public CActive
+	{
+public:
+	CKeyReader(CDevCommTestBase* aTester, RTest& aTest);
+	~CKeyReader();
+	void Start();
+protected:
+	void RunL();
+	void DoCancel();
+public:
+	RTest& iTest;
+	TKeyCode iKey;
+	CDevCommTestBase* iTester;
+	};
+
+class CDevCommIOBase : public CActive
+	{
+public:
+	CDevCommIOBase(CDevCommTestBase* aTester, TInt aPriority);
+	~CDevCommIOBase();
+	void CreateL(TInt aBufferSize);
+	void UpdateCount();
+	void ResetCount();
+public:
+	CDevCommTestBase* iTester;
+	TPtr8 iDes;
+	TUint8* iBuffer;
+	TInt iSize;
+	TInt iCount;
+	TInt iTotal;
+	};
+
+class CDevCommWriterBase : public CDevCommIOBase
+	{
+public:
+	CDevCommWriterBase(CDevCommTestBase* aTester);
+	~CDevCommWriterBase();
+	void Ready();
+	void Start();
+protected:
+	void RunL();
+	void DoCancel();
+	};
+
+class CDevCommReaderBase : public CDevCommIOBase
+	{
+public:
+	CDevCommReaderBase(CDevCommTestBase* aTester);
+	~CDevCommReaderBase();
+	void Ready();
+	void Start();
+protected:
+	void RunL();
+	void DoCancel();
+	};
+
+class CDevCommTimerBase : public CTimer
+	{
+public:
+	CDevCommTimerBase(CDevCommTestBase* aTester);
+	void CreateL();
+protected:
+	void RunL();
+public:
+	CDevCommTestBase* iTester;
+	};
+
+enum THandshakeMode
+	{
+	EHandshakeNone,
+	EHandshakeHardware,
+	EHandshakeSoftware
+	};
+
+class CDevCommTestBase : public CAsyncOneShot
+	{
+public:
+	CDevCommTestBase();
+	~CDevCommTestBase();
+	void CreateL(TInt aBufferSize);
+	TInt Open(TInt aPort);
+	void Close();
+	void Debug();
+	TInt SetHandshaking(THandshakeMode aMode);
+	TInt LineFailOn();
+	TInt LineFailOff();
+	TInt ZeroTerminate();
+	void ShowLoopSignals(TUint aOutState, TUint aInState);
+	virtual void ReadComplete(TInt aStatus);
+	virtual void WriteComplete(TInt aStatus);
+	virtual void TimeComplete(TInt aStatus);
+	virtual void KeyComplete(TKeyCode aKey);
+	void Start();
+public:
+	RBusDevComm iComm;
+	CDevCommWriterBase* iWriter;
+	CDevCommReaderBase* iReader;
+	CDevCommTimerBase* iTimer;
+	CKeyReader* iKeyboard;
+	TInt iBufferSize;
+	};
+
+
+CKeyReader::CKeyReader(CDevCommTestBase* aTester, RTest& aTest)
+	: CActive(KKeyboardPriority), iTest(aTest), iTester(aTester)
+	{
+	__DECLARE_NAME(_S("CKeyReader"));
+	CActiveScheduler::Add(this);
+	}
+
+CKeyReader::~CKeyReader()
+	{
+	Cancel();
+	}
+
+void CKeyReader::Start()
+	{
+	if (IsActive())
+		return;
+	SetActive();
+	iTest.Console()->Read(iStatus);
+	}
+
+void CKeyReader::RunL()
+	{
+	iKey = iTest.Console()->KeyCode();
+	iTester->KeyComplete(iKey);
+	Start();
+	}
+
+void CKeyReader::DoCancel()
+	{
+	iTest.Console()->ReadCancel();
+	}
+
+
+
+CDevCommIOBase::CDevCommIOBase(CDevCommTestBase* aTester, TInt aPriority)
+	: CActive(aPriority), iTester(aTester), iDes(NULL, 0)
+	{
+	__DECLARE_NAME(_S("CDevCommIOBase"));
+	CActiveScheduler::Add(this);
+	}
+
+CDevCommIOBase::~CDevCommIOBase()
+	{
+	if (iBuffer)
+		User::Free(iBuffer);
+	}
+
+void CDevCommIOBase::CreateL(TInt aSize)
+	{
+	iSize = aSize;
+	if (iSize>0)
+		iBuffer = (TUint8*)User::AllocL(iSize);
+	iDes.Set(iBuffer, iSize, iSize);
+	}
+
+void CDevCommIOBase::UpdateCount()
+	{
+	iCount += iDes.Length();
+	iTotal += iDes.Length();
+	}
+
+void CDevCommIOBase::ResetCount()
+	{
+	iCount = 0;
+	}
+
+CDevCommWriterBase::CDevCommWriterBase(CDevCommTestBase* aTester)
+	: CDevCommIOBase(aTester, KWriterPriority)
+	{
+	__DECLARE_NAME(_S("CDevCommWriterBase"));
+	}
+
+CDevCommWriterBase::~CDevCommWriterBase()
+	{
+	Cancel();
+	}
+
+void CDevCommWriterBase::Start()
+	{
+	__ASSERT_ALWAYS(iBuffer!=NULL, User::Panic(_L("No Buffer"), 0));
+	if (IsActive())
+		return;
+	SetActive();
+	iTester->iComm.Write(iStatus, iDes);
+	}
+
+void CDevCommWriterBase::Ready()
+	{
+	if (IsActive())
+		return;
+	SetActive();
+	iTester->iComm.Write(iStatus, TPtr8(NULL, 0));
+	}
+
+void CDevCommWriterBase::RunL()
+	{
+	UpdateCount();
+	iTester->WriteComplete(iStatus.Int());
+	}
+
+void CDevCommWriterBase::DoCancel()
+	{
+	iTester->iComm.WriteCancel();
+	}
+
+
+CDevCommReaderBase::CDevCommReaderBase(CDevCommTestBase* aTester)
+	: CDevCommIOBase(aTester, KReaderPriority)
+	{
+	__DECLARE_NAME(_S("CDevCommReaderBase"));
+	}
+
+CDevCommReaderBase::~CDevCommReaderBase()
+	{
+	Cancel();
+	}
+
+void CDevCommReaderBase::Start()
+	{
+	__ASSERT_ALWAYS(iBuffer!=NULL, User::Panic(_L("No Buffer"), 0));
+	if (IsActive())
+		return;
+	SetActive();
+	iDes.SetLength(iDes.MaxLength()-iCount);
+	iTester->iComm.Read(iStatus, iDes);
+	}
+
+void CDevCommReaderBase::Ready()
+	{
+	if (IsActive())
+		return;
+	SetActive();
+    TPtr8 ptr(NULL, 0);
+    iTester->iComm.Read(iStatus, ptr);
+	}
+
+void CDevCommReaderBase::RunL()
+	{
+	UpdateCount();
+	iTester->ReadComplete(iStatus.Int());
+	}
+
+void CDevCommReaderBase::DoCancel()
+	{
+	iTester->iComm.ReadCancel();
+	}
+
+CDevCommTimerBase::CDevCommTimerBase(CDevCommTestBase* aTester)
+	: CTimer(KTimerPriority), iTester(aTester)
+	{
+	__DECLARE_NAME(_S("CDevCommTestTimerBase"));
+	CActiveScheduler::Add(this);
+	}
+
+void CDevCommTimerBase::CreateL()
+	{
+	ConstructL();
+	}
+
+void CDevCommTimerBase::RunL()
+	{
+	iTester->TimeComplete(iStatus.Int());
+	}
+
+CDevCommTestBase::CDevCommTestBase()
+	: CAsyncOneShot(-1)
+	{
+	__DECLARE_NAME(_S("CDevCommTestBase"));
+	}
+
+CDevCommTestBase::~CDevCommTestBase()
+	{
+	delete iKeyboard;
+	delete iTimer;
+	delete iWriter;
+	delete iReader;
+	iComm.Close();
+	}
+
+void CDevCommTestBase::CreateL(TInt aBufferSize)
+	{
+	iBufferSize = aBufferSize;
+	iKeyboard = new (ELeave) CKeyReader(this, Test);
+	iTimer = new (ELeave) CDevCommTimerBase(this);
+	iWriter = new (ELeave) CDevCommWriterBase(this);
+	iReader = new (ELeave) CDevCommReaderBase(this);
+	iKeyboard->Start();
+	iWriter->CreateL(iBufferSize);
+	iTimer->CreateL();
+	iReader->CreateL(iBufferSize/16);
+	}
+
+void CDevCommTestBase::Start()
+	{
+	Call();
+	}
+
+TInt CDevCommTestBase::Open(TInt aPort)
+	{
+	TInt err;
+    if (err = iComm.Open(aPort), err!=KErrNone)
+		return err;
+
+    TCommConfig cBuf;
+	TCommConfigV01 &c=cBuf();
+	iComm.Config(cBuf);
+
+    c.iStopBits = EStop1;
+    c.iDataBits = EData8;
+    c.iParity = EParityNone;
+	c.iHandshake = 0
+//		| KConfigObeyXoff
+//		| KConfigSendXoff
+		| KConfigObeyCTS
+//		| KConfigFailCTS
+		| KConfigObeyDSR
+//		| KConfigFailDSR
+//		| KConfigObeyDCD
+//		| KConfigFailDCD
+//		| KConfigFreeRTS
+//		| KConfigFreeDTR
+		;
+    c.iRate = EBps115200;
+    c.iFifo = EFifoEnable;
+	c.iTerminatorCount = 0;
+	c.iTerminator[0] = 0x00;
+
+    if (err = iComm.SetConfig(cBuf), err!=KErrNone)
+		{
+		iComm.Close();
+		return err;
+		}
+	return KErrNone;
+	}
+
+
+TInt CDevCommTestBase::ZeroTerminate()
+	{
+	TCommConfig cBuf;
+	TCommConfigV01 &c=cBuf();
+	iComm.Config(cBuf);
+
+	c.iTerminatorCount = 1;
+	c.iTerminator[0] = 0x00;
+
+    return iComm.SetConfig(cBuf);
+	}
+
+void CDevCommTestBase::Close()
+	{
+	iTimer->Cancel();
+	iReader->Cancel();
+	iWriter->Cancel();
+	iComm.Close();
+	}
+
+TInt CDevCommTestBase::SetHandshaking(THandshakeMode aMode)
+	{
+    TCommConfig cBuf;
+	TCommConfigV01 &c=cBuf();
+	iComm.Config(cBuf);
+	
+	switch (aMode)
+		{
+	case EHandshakeNone:
+	c.iHandshake = 0
+//		| KConfigObeyXoff
+//		| KConfigSendXoff
+//		| KConfigObeyCTS
+//		| KConfigFailCTS
+//		| KConfigObeyDSR
+//		| KConfigFailDSR
+//		| KConfigObeyDCD
+//		| KConfigFailDCD
+		| KConfigFreeRTS
+		| KConfigFreeDTR
+		;
+		break;
+	case EHandshakeSoftware:
+	c.iXonChar=0x11;
+	c.iXoffChar=0x13;
+	c.iHandshake = 0
+		| KConfigObeyXoff
+		| KConfigSendXoff
+//		| KConfigObeyCTS
+//		| KConfigFailCTS
+//		| KConfigObeyDSR
+//		| KConfigFailDSR
+//		| KConfigObeyDCD
+//		| KConfigFailDCD
+		| KConfigFreeRTS
+		| KConfigFreeDTR
+		;
+		break;
+	case EHandshakeHardware:
+	c.iHandshake = 0
+//		| KConfigObeyXoff
+//		| KConfigSendXoff
+		| KConfigObeyCTS
+//		| KConfigFailCTS
+		| KConfigObeyDSR
+//		| KConfigFailDSR
+//		| KConfigObeyDCD
+//		| KConfigFailDCD
+//		| KConfigFreeRTS
+//		| KConfigFreeDTR
+		;
+		break;
+		}
+    return iComm.SetConfig(cBuf);
+	}
+
+TInt CDevCommTestBase::LineFailOn()
+	{
+    TCommConfig cBuf;
+	TCommConfigV01 &c=cBuf();
+	iComm.Config(cBuf);
+	c.iHandshake |= (KConfigFailDSR|KConfigFailDCD);
+    return iComm.SetConfig(cBuf);
+	}
+
+TInt CDevCommTestBase::LineFailOff()
+	{
+    TCommConfig cBuf;
+	TCommConfigV01 &c=cBuf();
+	iComm.Config(cBuf);
+	c.iHandshake &= ~(KConfigFailDSR|KConfigFailDCD);
+    return iComm.SetConfig(cBuf);
+	}
+
+void CDevCommTestBase::ShowLoopSignals(TUint aOutState, TUint aInState)
+	{
+	TPtrC cts, dsr, dcd;
+	TPtrC rts, dtr;
+	rts.Set(aOutState & KSignalRTS ? _L("RTS On ") : _L("RTS Off"));
+	dtr.Set(aOutState & KSignalDTR ? _L("DTR On ") : _L("DTR Off"));
+	Test.Printf(_L("%S, %S : "), &rts,  &dtr);
+	cts.Set(aInState & KSignalCTS ? _L("CTS On ") : _L("CTS Off"));
+	dsr.Set(aInState & KSignalDSR ? _L("DSR On ") : _L("DSR Off"));
+	dcd.Set(aInState & KSignalDCD ? _L("DCD On ") : _L("DCD Off"));
+	Test.Printf(_L("%S, %S, %S "), &cts, &dsr, &dcd);
+	rts.Set(aInState & KSignalRTS ? _L("RTS On ") : _L("RTS Off"));
+	dtr.Set(aInState & KSignalDTR ? _L("DTR On ") : _L("DTR Off"));
+	Test.Printf(_L("[%S, %S]\r\n"), &rts,  &dtr);
+	}
+
+#ifdef _DEBUG_DEVCOMM
+void CDevCommTestBase::Debug()
+	{
+	TCommDebugInfoPckg infopckg;
+	TCommDebugInfo& info = infopckg();
+	iComm.DebugInfo(infopckg);
+
+	Test.Printf(_L("  LDD State        :    TX         RX    \r\n"));
+	Test.Printf(_L("  Busy             : %10d %10d\r\n"), info.iTxBusy, info.iRxBusy);
+	Test.Printf(_L("  Held             : %10d %10d\r\n"), info.iTxHeld, info.iRxHeld);
+	Test.Printf(_L("  Length           : %10d %10d\r\n"), info.iTxLength, info.iRxLength);
+	Test.Printf(_L("  Offset           : %10d %10d\r\n"), info.iTxOffset, info.iRxOffset);
+	Test.Printf(_L("  Int Count        : %10d %10d\r\n"), info.iTxIntCount, info.iRxIntCount);
+	Test.Printf(_L("  Err Count        : %10d %10d\r\n"), info.iTxErrCount, info.iRxErrCount);
+	Test.Printf(_L("  Buf Count        : %10d %10d\r\n"), info.iTxBufCount, info.iRxBufCount);
+	Test.Printf(_L("  Fill/Drain       : %10d %10d\r\n"), info.iFillingTxBuf, info.iFillingTxBuf);
+	Test.Printf(_L("  XON              : %10d %10d\r\n"), info.iTxXon, info.iRxXon);
+	Test.Printf(_L("  XOFF             : %10d %10d\r\n"), info.iTxXoff, info.iRxXoff);
+	Test.Printf(_L("  Chars            : %10d %10d\r\n"), info.iTxChars, info.iRxChars);
+//	Test.Printf(_L("  DFC Pending      : %10d %10d\r\n"), info.iTxDfcPend, info.iTxDfcPend);
+//	Test.Printf(_L("  DFC Run/Count    : %10d %10d\r\n"), info.iRunningDfc, info.iDfcCount);
+//	Test.Printf(_L("  DFC Req/Do/Drain : %10d %10d %10d\r\n"), info.iDfcReqSeq, info.iDfcHandlerSeq, info.iDoDrainSeq);
+	}
+#else
+void CDevCommTestBase::Debug()
+	{
+	Test.Printf(_L("Debug Dump not available\r\n"));
+	}
+#endif
+
+void CDevCommTestBase::ReadComplete(TInt /*aStatus*/)
+	{}
+
+void CDevCommTestBase::WriteComplete(TInt /*aStatus*/)
+	{}
+
+void CDevCommTestBase::TimeComplete(TInt /*aStatus*/)
+	{}
+
+void CDevCommTestBase::KeyComplete(TKeyCode /*aKey*/)
+	{}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void StripeMem(TUint8 *aBuf, TInt aStartPos, TInt anEndPos, TUint aStartChar, TUint anEndChar, TInt aOffset=0)
+//
+// Mark a buffer with repeating byte pattern
+//
+	{
+	TUint character=aStartChar+(aOffset%((anEndChar+1)-aStartChar));
+
+	for (TInt i=aStartPos;i<anEndPos;i++)
+		{
+		aBuf[i]=(TText8)character;
+		if(++character>anEndChar)
+			character=aStartChar;
+		}
+	}
+
+inline void StripeDes(TDes8 &aBuf, TInt aStartPos, TInt anEndPos, TUint aStartChar, TUint anEndChar, TInt aOffset=0)
+	{
+	StripeMem((TUint8 *)aBuf.Ptr(), aStartPos, anEndPos, aStartChar, anEndChar, aOffset);
+	}
+
+TBool CheckMem(TUint8 *aBuf, TInt aStartPos, TInt anEndPos, TUint aStartChar, TUint anEndChar, TInt aOffset=0)
+//
+// Mark a buffer with repeating byte pattern
+//
+	{
+	TUint character=aStartChar+(aOffset%((anEndChar+1)-aStartChar));
+
+	for (TInt i=aStartPos;i<anEndPos;i++)
+		{
+		if (aBuf[i]!=(TText8)character)
+			return EFalse;
+		if(++character>anEndChar)
+			character=aStartChar;
+		}
+	return ETrue;
+	}
+
+inline TBool CheckDes(TDes8 &aBuf, TInt aStartPos, TInt anEndPos, TUint aStartChar, TUint anEndChar, TInt aOffset=0)
+	{
+	return CheckMem((TUint8 *)aBuf.Ptr(), aStartPos, anEndPos, aStartChar, anEndChar, aOffset);
+	}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void CommStart()
+	{
+	TInt ret;
+	Test.Printf(_L("Loading Drivers\r\n"));
+ 	ret = User::LoadPhysicalDevice(__COMM_PDD1);
+	TESTERR(ret==KErrNone || ret==KErrAlreadyExists, ret);
+// 	ret = User::LoadPhysicalDevice(__COMM_PDD2);
+//	TESTERR(ret==KErrNone || ret==KErrAlreadyExists, ret);
+	ret = User::LoadLogicalDevice(__COMM_LDD);
+	TESTERR(ret==KErrNone || ret==KErrAlreadyExists, ret);
+	Test.Printf(_L("OK\r\n"));
+	}
+
+////////////////////////////////////////////////////////////////////////////////
+	
+class CTestRandTerm : public CDevCommTestBase
+	{
+public:
+	enum TTestRandTermState	{ EIdle, EWaitReady, EWaitReset, EWaitIO };
+	enum TTestFailType { ETestFailBoth, ETestFailRead, ETestFailWrite, ETestBadData };
+public:
+	static CTestRandTerm* NewL(TInt aPort);
+	CTestRandTerm();
+	~CTestRandTerm();
+	virtual void ReadComplete(TInt aStatus);
+	virtual void WriteComplete(TInt aStatus);
+	virtual void TimeComplete(TInt aStatus);
+	virtual void KeyComplete(TKeyCode aKey);
+	void Reset();
+	void Write();
+	void Read();
+	TBool CheckRead();
+	void Halt();
+	void Fail(TTestFailType aType, TInt aError);
+protected:
+	virtual void RunL();
+public:
+	TTestRandTermState iState;
+	TInt64 iSeed;
+	TInt iCount;
+	TInt iOffset;
+	TInt iRetries;
+	TInt iPackets;
+	TInt iSpin;
+	TBool iTrace;
+	};
+
+CTestRandTerm::CTestRandTerm()
+	{
+	}
+
+CTestRandTerm::~CTestRandTerm()
+	{
+	}
+
+CTestRandTerm* CTestRandTerm::NewL(TInt aPort)
+	{
+	CTestRandTerm* tester = new (ELeave) CTestRandTerm;
+	CleanupStack::PushL(tester);
+	tester->CreateL(1000);
+	User::LeaveIfError(tester->Open(aPort));
+	CleanupStack::Pop();
+	return tester;
+	}
+
+void CTestRandTerm::Reset()
+	{
+    Test.Printf(_L("Resetting Port\r\n"));
+	iReader->Cancel();
+	iWriter->Cancel();
+	iTimer->Cancel();
+	LineFailOff();
+	iComm.ResetBuffers();
+	iTimer->After(1000000);
+	iState = EWaitReset;
+	}
+
+void CTestRandTerm::RunL()
+	{
+	iCount = 0;
+	iState = EIdle;
+	iSeed = 1;
+    Test.Printf(_L("Waiting for Port\r\n"));
+	ZeroTerminate();
+	iWriter->Ready();
+	iTimer->After(1000000);
+	iState = EWaitReady;
+	}
+
+void CTestRandTerm::ReadComplete(TInt aStatus)
+	{
+	if (iTrace)
+		Test.Printf(_L("CTestRandTerm::ReadComplete(%d) len = %d/%d\r\n"), aStatus, iWriter->iDes.Length(), iWriter->iDes.MaxLength());
+
+	if (aStatus!=KErrNone)
+		{
+		Fail(ETestFailRead, aStatus);
+		return;
+		}
+
+	switch (iState)
+		{
+	case EWaitIO:
+		iRetries = 0;
+		iTimer->Cancel();
+		if (CheckRead())
+			{
+			iPackets++;
+			if (iReader->iCount==iWriter->iCount)
+				{
+				iCount += iWriter->iCount;
+				Test.Printf(_L("%c %6d %d\r"), KSpinner[iSpin++ & 3], iPackets, iCount);
+				Write();
+				Read();
+				}
+			else
+				{
+				iOffset = iReader->iCount;
+				Test.Printf(_L("%c\r"), KSpinner[iSpin++ & 3]);
+				Read();
+				}
+			}
+		else
+			{
+			Fail(ETestBadData, KErrNone);
+			}
+		break;
+	default:
+		break;
+		}
+	}
+
+void CTestRandTerm::WriteComplete(TInt aStatus)
+	{
+	if (iTrace)
+		{
+		Test.Printf(_L("CTestRandTerm::WriteComplete(%d) len = %d/%d\r\n"), aStatus, iWriter->iDes.Length(), iWriter->iDes.MaxLength());
+		}
+
+	if (aStatus!=KErrNone)
+		{
+		Fail(ETestFailWrite, aStatus);
+		return;
+		}
+
+	switch (iState)
+		{
+	case EWaitReady:
+		iRetries = 0;
+		iTimer->Cancel();
+		iState = EWaitIO;
+		Test.Printf(_L("Port Ready\r\n"));
+		LineFailOn();
+		Write();
+		Read();
+		break;
+	case EWaitIO:
+		iRetries = 0;
+		if (iReader->iCount==iWriter->iCount)
+			{
+			Write();
+			Read();
+			}
+		break;
+	default:
+		break;
+		}
+	}
+
+void CTestRandTerm::TimeComplete(TInt aStatus)
+	{
+	if (iTrace)
+		Test.Printf(_L("CTestRandTerm::TimeComplete(%d)\r\n"), aStatus);
+
+	if (aStatus!=KErrNone)
+		{
+		__DEBUGGER();
+		return;
+		}
+
+	switch (iState)
+		{
+	case EWaitReset:
+	    Test.Printf(_L("Waiting for Port\r\n"));
+		iWriter->Ready();
+		iTimer->After(1000000);
+		iState = EWaitReady;
+		break;
+	case EWaitReady:
+		if (++iRetries>10)
+			{
+			Test.Printf(_L("Too many retries\r\n"));
+			Halt();
+			}
+		else
+			{
+			Test.Printf(_L("%c\r"), KSpinner[iSpin++ & 3]);
+			iWriter->Ready();
+			iTimer->After(1000000);
+			}
+		break;
+	case EWaitIO:
+		Fail(ETestFailBoth, KErrTimedOut);
+		break;
+	default:
+		Reset();
+		break;
+		}
+	}
+
+
+void CTestRandTerm::KeyComplete(TKeyCode aKey)
+	{
+	if (iTrace)
+		Test.Printf(_L("CTestRandTerm::KeyComplete(%d)\r\n"), aKey);
+
+	switch ((TInt)aKey)
+		{
+	case EKeyEscape:
+		Halt();
+		break;
+	case 'd':
+	case 'D':
+		Debug();
+		break;
+	case 'q':
+	case 'Q':
+		iTrace = 0;
+		break;
+	case 'v':
+	case 'V':
+		iTrace = 1;
+		break;
+    default:
+        break;
+        }
+	}
+
+
+void CTestRandTerm::Fail(TTestFailType aType, TInt aError)
+	{
+	switch (aType)
+		{
+	case ETestFailBoth:
+		Test.Printf(_L("Timeout at offset %d\r\n"), iOffset);
+		break;
+	case ETestFailRead:
+		Test.Printf(_L("Read fail (%d) at offset %d\r\n"), aError, iOffset);
+		break;
+	case ETestFailWrite:
+		Test.Printf(_L("Write fail (%d) at offset %d\r\n"), aError, iOffset);
+		break;
+	case ETestBadData:
+		Test.Printf(_L("Data verify failure at offset %d\r\n"), iOffset);
+		break;
+		}
+	Debug();
+	Reset();
+	}
+
+
+void CTestRandTerm::Write()
+	{
+	iOffset = 0;
+	iWriter->ResetCount();
+	iReader->ResetCount();
+
+	TInt i;
+	TInt j = 0;
+	StripeDes(iWriter->iDes, 0, iBufferSize, '@', 'Z');
+	while (j<iBufferSize)
+		{
+		i = Math::Rand(iSeed) % (iBufferSize/4);
+		if (j+i<iBufferSize)
+			iWriter->iDes[j+i] = '\0';
+		j += i;
+		}
+
+	iWriter->Start();
+	}
+
+
+void CTestRandTerm::Read()
+	{
+	iReader->Start();
+	iTimer->After(5000000);
+	}
+
+
+TBool CTestRandTerm::CheckRead()
+	{
+	TPtrC8 ref;
+	ref.Set(iWriter->iDes.Ptr()+iOffset, iReader->iDes.Length());
+	return ref.Compare(iReader->iDes)==0;
+	}
+
+void CTestRandTerm::Halt()
+	{
+	iReader->Cancel();
+	iWriter->Cancel();
+	iTimer->Cancel();
+	CActiveScheduler::Stop();
+	}
+
+////////////////////////////////////////////////////////////////////////////////
+	
+
+class CTestSignals : public CDevCommTestBase
+	{
+public:
+	enum TTestState	{ EAllOff, ERtsOn, EDtrOn, EAllOn, EMonitor };
+public:
+	static CTestSignals* NewL(TInt aPort);
+	CTestSignals();
+	~CTestSignals();
+	virtual void KeyComplete(TKeyCode aKey);
+	virtual void ReadComplete(TInt aStatus);
+	void Halt();
+	void DoSignals(TTestState aState);
+protected:
+	virtual void RunL();
+public:
+	TTestState iState;
+	};
+
+CTestSignals::CTestSignals()
+	{
+	}
+
+CTestSignals::~CTestSignals()
+	{
+	}
+
+CTestSignals* CTestSignals::NewL(TInt aPort)
+	{
+	CTestSignals* tester = new (ELeave) CTestSignals;
+	CleanupStack::PushL(tester);
+	tester->CreateL(0);
+	User::LeaveIfError(tester->Open(aPort));
+	CleanupStack::Pop();
+	return tester;
+	}
+
+void CTestSignals::RunL()
+	{
+    TCommConfig cBuf;
+	TCommConfigV01 &c=cBuf();
+	iComm.Config(cBuf);
+	c.iHandshake = KConfigFreeRTS | KConfigFreeDTR;
+    iComm.SetConfig(cBuf);
+	iReader->Ready();
+	}
+
+
+void CTestSignals::Halt()
+	{
+	Test.Printf(_L("                        \r"));
+	CActiveScheduler::Stop();
+	}
+
+void CTestSignals::ReadComplete(TInt /*aStatus*/)
+	{
+	DoSignals(EAllOff);
+	}
+
+void CTestSignals::KeyComplete(TKeyCode aKey)
+	{
+	switch (aKey)
+		{
+	case EKeyEscape:
+		Halt();
+		break;
+	default:
+		switch (iState)
+			{
+		case EAllOff:
+			DoSignals(ERtsOn);
+			break;
+		case ERtsOn:
+			DoSignals(EDtrOn);
+			break;
+		case EDtrOn:
+			DoSignals(EAllOn);
+			break;
+		case EAllOn:
+			DoSignals(EAllOff);
+			break;
+		default:
+			break;
+			}
+		}
+	}
+
+void CTestSignals::DoSignals(TTestState aState)
+	{
+	TUint set=0, clr=0;
+
+	switch (aState)
+		{
+	case EAllOff:
+		set = 0;
+		clr = KSignalRTS | KSignalDTR;
+		break;
+	case ERtsOn:
+		set = KSignalRTS;
+		clr = KSignalDTR;
+		break;
+	case EDtrOn:
+		set = KSignalDTR;
+		clr = KSignalRTS;
+		break;
+	case EAllOn:
+		set = KSignalRTS | KSignalDTR;
+		clr = 0;
+		break;
+	default:
+		set = 0;
+		clr = 0;
+		}
+	iComm.SetSignals(set, clr);
+	TUint sig = iComm.Signals();
+	ShowLoopSignals(set, sig);
+	iState = aState;	
+	Test.Printf(_L("Press key for next state\r"));
+	}
+
+////////////////////////////////////////////////////////////////////////////////
+
+class CTestPerf : public CDevCommTestBase
+	{
+public:
+	enum TTestRandTermState	{ EIdle, EWaitReady, EWaitReset, EWaitIO };
+	enum TTestFailType { ETestFailBoth, ETestFailRead, ETestFailWrite, ETestBadData };
+public:
+	static CTestPerf* NewL(TInt aPort);
+	CTestPerf();
+	~CTestPerf();
+	virtual void ReadComplete(TInt aStatus);
+	virtual void WriteComplete(TInt aStatus);
+	virtual void TimeComplete(TInt aStatus);
+	virtual void KeyComplete(TKeyCode aKey);
+	void Reset();
+	void Write();
+	void Read();
+	TBool CheckRead();
+	void Halt();
+	void Fail(TTestFailType aType, TInt aError);
+protected:
+	virtual void RunL();
+public:
+	TTestRandTermState iState;
+	TInt64 iSeed;
+	TInt iCount;
+	TInt iOffset;
+	TInt iRetries;
+	TInt iPackets;
+	TInt iSpin;
+	TBool iTrace;
+	TTime iStartTime;
+	TInt iRate;
+	TInt iSpeed;
+	};
+
+CTestPerf::CTestPerf()
+	{
+	}
+
+CTestPerf::~CTestPerf()
+	{
+	}
+
+CTestPerf* CTestPerf::NewL(TInt aPort)
+	{
+	CTestPerf* tester = new (ELeave) CTestPerf;
+	CleanupStack::PushL(tester);
+	tester->CreateL(250);
+	User::LeaveIfError(tester->Open(aPort));
+	CleanupStack::Pop();
+	StripeDes(tester->iWriter->iDes, 0, tester->iBufferSize, '@', 'Z');
+	return tester;
+	}
+
+void CTestPerf::Reset()
+	{
+    Test.Printf(_L("Resetting Port\r\n"));
+	iReader->Cancel();
+	iWriter->Cancel();
+	iTimer->Cancel();
+	LineFailOff();
+	iComm.ResetBuffers();
+	iTimer->After(1000000);
+	iState = EWaitReset;
+	}
+
+void CTestPerf::RunL()
+	{
+	iCount = 0;
+	iState = EIdle;
+	iSeed = 1;
+    Test.Printf(_L("Waiting for Port\r\n"));
+	ZeroTerminate();
+	iWriter->Ready();
+	iTimer->After(1000000);
+	iState = EWaitReady;
+	}
+
+void CTestPerf::ReadComplete(TInt aStatus)
+	{
+	if (iTrace)
+		Test.Printf(_L("CTestPerf::ReadComplete(%d) len = %d/%d\r\n"), aStatus, iWriter->iDes.Length(), iWriter->iDes.MaxLength());
+
+	if (aStatus!=KErrNone)
+		{
+		Fail(ETestFailRead, aStatus);
+		return;
+		}
+
+	switch (iState)
+		{
+	case EWaitIO:
+		iRetries = 0;
+		iTimer->Cancel();
+		iCount += iReader->iCount;
+		iPackets++;
+		{
+		TTime end;
+		end.UniversalTime();
+		TInt64 difftime = (end.MicroSecondsFrom(iStartTime).Int64()+TInt64(500000))/TInt64(1000000);
+		if (difftime==0)
+			difftime = 1;
+		TInt64 cps = MAKE_TINT64(0,iCount)/difftime;
+		TInt rate = (I64INT(cps)*10000)/11520;
+
+		iRate += rate;
+		iSpeed += I64INT(cps);
+		
+		Test.Printf(_L("%c %6d %d (%dbps=%d.%02d%%)\r"), KSpinner[iSpin++ & 3], iPackets, iCount, iSpeed/iPackets, (iRate/iPackets)/100, (iRate/iPackets)%100);
+		}
+		Read();
+		break;
+	default:
+		break;
+		}
+	}
+
+void CTestPerf::WriteComplete(TInt aStatus)
+	{
+	if (iTrace)
+		{
+		Test.Printf(_L("CTestPerf::WriteComplete(%d) len = %d/%d\r\n"), aStatus, iWriter->iDes.Length(), iWriter->iDes.MaxLength());
+		}
+
+	if (aStatus!=KErrNone)
+		{
+		Fail(ETestFailWrite, aStatus);
+		return;
+		}
+
+	switch (iState)
+		{
+	case EWaitReady:
+		iRetries = 0;
+		iTimer->Cancel();
+		iState = EWaitIO;
+		Test.Printf(_L("Port Ready\r\n"));
+		LineFailOn();
+		iStartTime.UniversalTime();;
+		Write();
+		Read();
+		break;
+	case EWaitIO:
+		iRetries = 0;
+		Write();
+		break;
+	default:
+		break;
+		}
+	}
+
+void CTestPerf::TimeComplete(TInt aStatus)
+	{
+	if (iTrace)
+		Test.Printf(_L("CTestPerf::TimeComplete(%d)\r\n"), aStatus);
+
+	if (aStatus!=KErrNone)
+		{
+		__DEBUGGER();
+		return;
+		}
+
+	switch (iState)
+		{
+	case EWaitReset:
+	    Test.Printf(_L("Waiting for Port\r\n"));
+		iWriter->Ready();
+		iTimer->After(1000000);
+		iState = EWaitReady;
+		break;
+	case EWaitReady:
+		if (++iRetries>10)
+			{
+			Test.Printf(_L("Too many retries\r\n"));
+			Halt();
+			}
+		else
+			{
+			Test.Printf(_L("%c\r"), KSpinner[iSpin++ & 3]);
+			iWriter->Ready();
+			iTimer->After(1000000);
+			}
+		break;
+	case EWaitIO:
+		Fail(ETestFailBoth, KErrTimedOut);
+		break;
+	default:
+		Reset();
+		break;
+		}
+	}
+
+
+void CTestPerf::KeyComplete(TKeyCode aKey)
+	{
+	if (iTrace)
+		Test.Printf(_L("CTestPerf::KeyComplete(%d)\r\n"), aKey);
+
+	switch ((TInt)aKey)
+		{
+	case EKeyEscape:
+		Halt();
+		break;
+	case 'd':
+	case 'D':
+		Test.Printf(_L("\r\n"));
+		Debug();
+		break;
+	case 'q':
+	case 'Q':
+		iTrace = 0;
+		break;
+	case 'v':
+	case 'V':
+		iTrace = 1;
+		break;
+	case 's':
+	case 'S':
+		Test.Printf(_L("\r\n"));
+		Test.Printf(_L("Keyboard : %08x, %d\r\n"), iKeyboard->iStatus.Int(), iKeyboard->IsActive());
+		Test.Printf(_L("Timer    : %08x, %d\r\n"), iTimer->iStatus.Int(), iTimer->IsActive());
+		Test.Printf(_L("Reader   : %08x, %d\r\n"), iReader->iStatus.Int(), iReader->IsActive());
+		Test.Printf(_L("Writer   : %08x, %d\r\n"), iWriter->iStatus.Int(), iWriter->IsActive());
+		break;
+    default:
+        break;
+        }
+	}
+
+
+void CTestPerf::Fail(TTestFailType aType, TInt aError)
+	{	
+	switch (aType)
+		{
+	case ETestFailBoth:
+		Test.Printf(_L("\r\nTimeout at offset %d\r\n"), iOffset);
+		break;
+	case ETestFailRead:
+		Test.Printf(_L("\r\nRead fail (%d) at offset %d\r\n"), aError, iOffset);
+		break;
+	case ETestFailWrite:
+		Test.Printf(_L("\r\nWrite fail (%d) at offset %d\r\n"), aError, iOffset);
+		break;
+	case ETestBadData:
+		Test.Printf(_L("\r\nData verify failure at offset %d\r\n"), iOffset);
+		break;
+		}
+	Debug();
+	Reset();
+	}
+
+
+void CTestPerf::Write()
+	{
+	iOffset = 0;
+	iWriter->ResetCount();
+	iWriter->Start();
+	}
+
+void CTestPerf::Read()
+	{
+	iReader->ResetCount();
+	iReader->Start();
+	iTimer->After(5000000);
+	}
+
+TBool CTestPerf::CheckRead()
+	{
+	TPtrC8 ref;
+	ref.Set(iWriter->iDes.Ptr()+iOffset, iReader->iDes.Length());
+	return ref.Compare(iReader->iDes)==0;
+	}
+
+void CTestPerf::Halt()
+	{
+	iReader->Cancel();
+	iWriter->Cancel();
+	iTimer->Cancel();
+	CActiveScheduler::Stop();
+	}
+
+////////////////////////////////////////////////////////////////////////////////
+
+class CTestXonXoff : public CDevCommTestBase
+	{
+public:
+	enum TTestRandTermState	{ EIdle, EWaitReady, EWaitReset, EWaitIO };
+	enum TTestFailType { ETestFailBoth, ETestFailRead, ETestFailWrite, ETestBadData };
+public:
+	static CTestXonXoff* NewL(TInt aPort);
+	CTestXonXoff();
+	~CTestXonXoff();
+	virtual void ReadComplete(TInt aStatus);
+	virtual void WriteComplete(TInt aStatus);
+	virtual void TimeComplete(TInt aStatus);
+	virtual void KeyComplete(TKeyCode aKey);
+	void Reset();
+	void Write();
+	void Read();
+	TBool CheckRead();
+	void Halt();
+	void Fail(TTestFailType aType, TInt aError);
+protected:
+	virtual void RunL();
+public:
+	TTestRandTermState iState;
+	TInt64 iSeed;
+	TInt iCount;
+	TInt iOffset;
+	TInt iRetries;
+	TInt iPackets;
+	TInt iSpin;
+	TBool iTrace;
+	TTime iStartTime;
+	TInt iRate;
+	TInt iSpeed;
+	};
+
+CTestXonXoff::CTestXonXoff()
+	{
+	}
+
+CTestXonXoff::~CTestXonXoff()
+	{
+	}
+
+CTestXonXoff* CTestXonXoff::NewL(TInt aPort)
+	{
+	CTestXonXoff* tester = new (ELeave) CTestXonXoff;
+	CleanupStack::PushL(tester);
+	tester->CreateL(16384);
+	User::LeaveIfError(tester->Open(aPort));
+	User::LeaveIfError(tester->SetHandshaking(EHandshakeSoftware));
+	CleanupStack::Pop();
+	StripeDes(tester->iWriter->iDes, 0, tester->iBufferSize, '@', 'Z');
+	return tester;
+	}
+
+void CTestXonXoff::Reset()
+	{
+    Test.Printf(_L("Resetting Port\r\n"));
+	iReader->Cancel();
+	iWriter->Cancel();
+	iTimer->Cancel();
+	LineFailOff();
+	iComm.ResetBuffers();
+	iTimer->After(1000000);
+	iState = EWaitReset;
+	}
+
+void CTestXonXoff::RunL()
+	{
+	iCount = 0;
+	iState = EIdle;
+	iSeed = 1;
+    Test.Printf(_L("Waiting for Port\r\n"));
+	ZeroTerminate();
+
+	iWriter->Ready();
+	iTimer->After(1000000);
+	
+//	iState = EWaitReady;
+//	WriteComplete(0);
+	}
+
+void CTestXonXoff::ReadComplete(TInt aStatus)
+	{
+	if (iTrace)
+		Test.Printf(_L("CTestXonXoff::ReadComplete(%d) len = %d/%d (%d)\r\n"), aStatus, iReader->iDes.Length(), iReader->iDes.MaxLength(), iReader->iTotal);
+
+	if (aStatus!=KErrNone)
+		{
+		Fail(ETestFailRead, aStatus);
+		return;
+		}
+
+	switch (iState)
+		{
+	case EWaitIO:
+		iRetries = 0;
+		iTimer->Cancel();
+		if (!CheckDes(iReader->iDes, 0, iReader->iDes.Length(), '@', 'Z', iCount & 0x3fff))
+			{
+			Fail(ETestBadData, aStatus);
+			return;
+			}
+		iCount += iReader->iCount;
+		iPackets++;
+		{
+		TTime end;
+		end.UniversalTime();
+		TInt64 difftime = (end.MicroSecondsFrom(iStartTime).Int64()+TInt64(500000))/TInt64(1000000);
+		if (difftime==0)
+			difftime = 1;
+		TInt64 cps = MAKE_TINT64(0,iCount)/difftime;
+		TInt rate = (I64INT(cps)*10000)/11520;
+		iRate += rate;
+		iSpeed += I64INT(cps);
+		Test.Printf(_L("%c %6d %d (%dbps=%d.%02d%%)\r"), KSpinner[iSpin++ & 3], iPackets, iCount, iSpeed/iPackets, (iRate/iPackets)/100, (iRate/iPackets)%100);
+		}
+		Read();
+		break;
+	default:
+		break;
+		}
+	}
+
+void CTestXonXoff::WriteComplete(TInt aStatus)
+	{
+	if (iTrace)
+		{
+		Test.Printf(_L("CTestXonXoff::WriteComplete(%d) len = %d/%d (%d)\r\n"), aStatus, iWriter->iDes.Length(), iWriter->iDes.MaxLength(), iWriter->iTotal);
+		}
+
+	if (aStatus!=KErrNone)
+		{
+		Fail(ETestFailWrite, aStatus);
+		return;
+		}
+
+	switch (iState)
+		{
+	case EWaitReady:
+		iRetries = 0;
+		iTimer->Cancel();
+		iState = EWaitIO;
+		Test.Printf(_L("Port Ready\r\n"));
+		LineFailOn();
+		iStartTime.UniversalTime();;
+		Write();
+		Read();
+		break;
+	case EWaitIO:
+		iRetries = 0;
+		Write();
+		break;
+	default:
+		break;
+		}
+	}
+
+void CTestXonXoff::TimeComplete(TInt aStatus)
+	{
+	if (iTrace)
+		Test.Printf(_L("CTestXonXoff::TimeComplete(%d)\r\n"), aStatus);
+
+	if (aStatus!=KErrNone)
+		{
+		__DEBUGGER();
+		return;
+		}
+
+	switch (iState)
+		{
+	case EWaitReset:
+	    Test.Printf(_L("Waiting for Port\r\n"));
+		iWriter->Ready();
+		iTimer->After(1000000);
+		iState = EWaitReady;
+		break;
+	case EWaitReady:
+		if (++iRetries>10)
+			{
+			Test.Printf(_L("Too many retries\r\n"));
+			Halt();
+			}
+		else
+			{
+			Test.Printf(_L("%c\r"), KSpinner[iSpin++ & 3]);
+			iWriter->Ready();
+			iTimer->After(1000000);
+			}
+		break;
+	case EWaitIO:
+		Fail(ETestFailBoth, KErrTimedOut);
+		break;
+	default:
+		Reset();
+		break;
+		}
+	}
+
+
+void CTestXonXoff::KeyComplete(TKeyCode aKey)
+	{
+	if (iTrace)
+		Test.Printf(_L("CTestXonXoff::KeyComplete(%d)\r\n"), aKey);
+
+	switch ((TInt)aKey)
+		{
+	case EKeyEscape:
+		Halt();
+		break;
+	case 'd':
+	case 'D':
+		Test.Printf(_L("\r\n"));
+		Debug();
+		break;
+	case 'q':
+	case 'Q':
+		iTrace = 0;
+		break;
+	case 'v':
+	case 'V':
+		iTrace = 1;
+		break;
+	case 's':
+	case 'S':
+		Test.Printf(_L("\r\n"));
+		Test.Printf(_L("Keyboard : %08x, %d\r\n"), iKeyboard->iStatus.Int(), iKeyboard->IsActive());
+		Test.Printf(_L("Timer    : %08x, %d\r\n"), iTimer->iStatus.Int(), iTimer->IsActive());
+		Test.Printf(_L("Reader   : %08x, %d\r\n"), iReader->iStatus.Int(), iReader->IsActive());
+		Test.Printf(_L("Writer   : %08x, %d\r\n"), iWriter->iStatus.Int(), iWriter->IsActive());
+		break;
+    default:
+        break;
+		}
+	}
+
+
+void CTestXonXoff::Fail(TTestFailType aType, TInt aError)
+	{
+	switch (aType)
+		{
+	case ETestFailBoth:
+		Test.Printf(_L("\r\nTimeout at offset %d\r\n"), iOffset);
+		break;
+	case ETestFailRead:
+		Test.Printf(_L("\r\nRead fail (%d) at offset %d\r\n"), aError, iOffset);
+		break;
+	case ETestFailWrite:
+		Test.Printf(_L("\r\nWrite fail (%d) at offset %d\r\n"), aError, iOffset);
+		break;
+	case ETestBadData:
+		Test.Printf(_L("\r\nData verify failure at offset %d\r\n"), iOffset);
+		break;
+		}
+	Debug();
+	Reset();
+	}
+
+
+void CTestXonXoff::Write()
+	{
+	iOffset = 0;
+	iWriter->ResetCount();
+	StripeDes(iWriter->iDes, 0, iWriter->iDes.Length(), '@', 'Z');
+	iWriter->Start();
+	}
+
+void CTestXonXoff::Read()
+	{
+	User::After(1000000);
+	iReader->ResetCount();
+	iReader->Start();
+	iTimer->After(5000000);
+	}
+
+TBool CTestXonXoff::CheckRead()
+	{
+	TPtrC8 ref;
+	ref.Set(iWriter->iDes.Ptr()+iOffset, iReader->iDes.Length());
+	return ref.Compare(iReader->iDes)==0;
+	}
+
+void CTestXonXoff::Halt()
+	{
+	iReader->Cancel();
+	iWriter->Cancel();
+	iTimer->Cancel();
+	CActiveScheduler::Stop();
+	}
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+TInt E32Main()
+	{
+	TInt err;
+	
+	Test.Start(_L("Comm Driver Tests"));
+	CommStart();
+    Test.Printf(_L("Insert plug in then press a key\r\n"));
+	Test.Getch();
+
+	TEST(CTrapCleanup::New()!=NULL);
+	CActiveScheduler* Scheduler = new CActiveScheduler;
+	TEST(Scheduler!=NULL);
+	CActiveScheduler::Install(Scheduler);
+/*
+	CTestSignals* testsignals = NULL;
+	TRAP(err, testsignals = CTestSignals::NewL(0));
+	TEST(err==KErrNone);
+	testsignals->Start();
+	Scheduler->Start();
+	delete testsignals;
+	
+	CTestRandTerm* testrandterm = NULL;
+	TRAP(err, testrandterm = CTestRandTerm::NewL(0));
+	TEST(err==KErrNone);
+	testrandterm->Start();
+	Scheduler->Start();
+	delete testrandterm;
+
+	CTestPerf* testperf = NULL;
+	TRAP(err, testperf = CTestPerf::NewL(0));
+	TEST(err==KErrNone);
+	testperf->Start();
+	Scheduler->Start();
+	delete testperf;
+*/
+
+	CTestXonXoff* testx = NULL;
+	TRAP(err, testx = CTestXonXoff::NewL(0));
+	TEST(err==KErrNone);
+	testx->Start();
+	Scheduler->Start();
+	delete testx;
+
+/*
+	CTestXonXoff* testx1 = NULL;
+	TRAP(err, testx1 = CTestXonXoff::NewL(0));
+	TEST(err==KErrNone);
+	testx1->Start();
+
+	CTestXonXoff* testx2 = NULL;
+	TRAP(err, testx2 = CTestXonXoff::NewL(1));
+	TEST(err==KErrNone);
+	testx2->Start();
+
+	Scheduler->Start();
+
+	delete testx1;
+	delete testx2;
+*/
+	Test.End();
+	return KErrNone;
+	}