kerneltest/e32test/ethernet/pump/etherpump.cpp
changeset 9 96e5fb8b040d
equal deleted inserted replaced
-1:000000000000 9:96e5fb8b040d
       
     1 // Copyright (c) 1996-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 the License "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 // e32test\ethernet\etherpump.cpp
       
    15 // Abbreviations - PSP (Professional Symbian Programming)
       
    16 // 
       
    17 //
       
    18 
       
    19 #define __USE_LDDPDD__
       
    20 #define __USE_TIMER__
       
    21 
       
    22 #include <e32base.h>
       
    23 #include <e32base_private.h>
       
    24 #include <e32cons.h>
       
    25 #include <e32svr.h>
       
    26 
       
    27 #include <d32ethernet.h>
       
    28 
       
    29 #include "activeio.h"
       
    30 
       
    31 #define LDD_NAME _L("Enet")
       
    32 #if (!defined __WINS__)
       
    33 #define PDD_NAME _L("Ethernet")
       
    34 #else
       
    35 
       
    36 //#define PDD_NAME _L("EthernetWins")
       
    37 #define PDD_NAME _L("Ethernet")
       
    38 #endif
       
    39 
       
    40 
       
    41 // changed from const to static
       
    42 //const TUint8 DestMacAddr[] = {0x00,0x50,0xDA,0xE9,0x69,0xCA};
       
    43 
       
    44 // MAC address with second bit 1
       
    45 static TUint8 DestMacAddr[] = {0x02,0xB0,0xD0,0x64,0x98,0x02};
       
    46 
       
    47 
       
    48 // for random functions
       
    49 #include <e32math.h>
       
    50 
       
    51 
       
    52 void StripeMem(TUint8 *aBuf, TInt aStartPos, TInt anEndPos, TUint aStartChar, TUint anEndChar, TInt aOffset)
       
    53 //
       
    54 // Mark a buffer with repeating byte pattern
       
    55 //
       
    56     {
       
    57     TUint character=aStartChar+(aOffset%((anEndChar+1)-aStartChar));
       
    58 
       
    59     for (TInt i=aStartPos;i<anEndPos;i++)
       
    60 	{
       
    61 	aBuf[i]=(TText8)character;
       
    62 	if(++character>anEndChar)
       
    63 	    character=aStartChar;
       
    64 	}
       
    65     }
       
    66 
       
    67 void StripeDes(TDes8 &aBuf, TInt aStartPos, TInt anEndPos, TUint aStartChar, TUint anEndChar, TInt aOffset)
       
    68     {
       
    69     StripeMem((TUint8 *)aBuf.Ptr(), aStartPos, anEndPos, aStartChar, anEndChar, aOffset);
       
    70     }
       
    71 
       
    72 TBool CheckMem(TUint8 *aBuf, TInt aStartPos, TInt anEndPos, TUint aStartChar, TUint anEndChar, TInt aOffset)
       
    73 //
       
    74 // Mark a buffer with repeating byte pattern
       
    75 //
       
    76     {
       
    77     TUint character=aStartChar+(aOffset%((anEndChar+1)-aStartChar));
       
    78 
       
    79     for (TInt i=aStartPos;i<anEndPos;i++)
       
    80 	{
       
    81 	if (aBuf[i]!=(TText8)character)
       
    82 	    return EFalse;
       
    83 	if(++character>anEndChar)
       
    84 	    character=aStartChar;
       
    85 	}
       
    86     return ETrue;
       
    87     }
       
    88 
       
    89 TBool CheckDes(TDes8 &aBuf, TInt aStartPos, TInt anEndPos, TUint aStartChar, TUint anEndChar, TInt aOffset)
       
    90     {
       
    91     return CheckMem((TUint8 *)aBuf.Ptr(), aStartPos, anEndPos, aStartChar, anEndChar, aOffset);
       
    92     }
       
    93 
       
    94 
       
    95 void StripeMem32(TUint *aBuf, TInt aStartPos, TInt aEndPos)
       
    96 //
       
    97 // Mark a buffer with repeating byte pattern
       
    98 //
       
    99     {
       
   100     aStartPos >>= 2;
       
   101     aEndPos >>= 2;
       
   102 	
       
   103     for (TInt i=aStartPos;i<aEndPos;i++)
       
   104 	{
       
   105 	aBuf[i]=i<<2;
       
   106 	}
       
   107     }
       
   108 
       
   109 void StripeDes32(TDes8 &aBuf, TInt aStartPos, TInt anEndPos)
       
   110     {
       
   111     StripeMem32((TUint*)aBuf.Ptr(), aStartPos, anEndPos);
       
   112     }
       
   113 
       
   114 // Standard Epoc32 Library Console class
       
   115 static CConsoleBase* console;
       
   116 
       
   117 
       
   118 // xxxLC means method can Leave and has pushed something on the Cleanup stack
       
   119 // Caller is responsible for popping it.
       
   120 CDemoControl* CDemoControl::NewLC()
       
   121     {
       
   122     CDemoControl* self = new (ELeave) CDemoControl(EPriorityNormal);
       
   123     CleanupStack::PushL(self);
       
   124     self->ConstructL();
       
   125     return self;
       
   126     }
       
   127 TInt CDemoControl::Callback(TAny* aControl)
       
   128 // Callback function for timer expiry
       
   129 // Just pump another packet at the server
       
   130 // It's a static so call a class member to access private data
       
   131     {
       
   132     CIOBuffer* buf = ((CDemoControl*)aControl)->CreateSendPacketL();
       
   133 
       
   134     ((CDemoControl*)aControl)->iWriteQueue.AddLast(*buf);
       
   135     ((CDemoControl*)aControl)->iWriter->WriteL(buf->Ptr());
       
   136 
       
   137     return KErrNone;
       
   138     }
       
   139 
       
   140 
       
   141 void CDemoControl::ConstructL()
       
   142 // Second Phase construction
       
   143     {
       
   144     // Add us to the Active Scheduler for the thread
       
   145     CActiveScheduler::Add(this);
       
   146     // Create the Read and Write Active Objects
       
   147     // The 'this' pointer is the MxxxNotify callback interface that CDemoControl is derived from
       
   148     // Pass a reference to the Server session so they can make read and write requests
       
   149 
       
   150     iWriter = CDemoWriter::NewL(*this,iCard);
       
   151     iReader = CDemoReader::NewL(*this,iCard);
       
   152 
       
   153     User::LoadPhysicalDevice(PDD_NAME);
       
   154     User::LoadLogicalDevice(LDD_NAME);
       
   155 
       
   156 #if (defined __USE_TIMER__)
       
   157     iIfState = EIdle;
       
   158     iTimer = CPeriodic::NewL(EPriorityNormal);
       
   159 #endif
       
   160 
       
   161     iWriteQueue.SetOffset(CIOBuffer::LinkOffset());
       
   162 
       
   163     HelpText();
       
   164 
       
   165     }
       
   166 
       
   167 void CDemoControl::EmptyWriteQueue()
       
   168     {
       
   169     TSglQueIter<CIOBuffer> iter(iWriteQueue);
       
   170     CIOBuffer* buf;
       
   171     while (buf = iter++, buf!=NULL)
       
   172 	{
       
   173 	iWriteQueue.Remove(*buf);
       
   174 	delete buf;
       
   175 	}
       
   176     }
       
   177 
       
   178 CDemoControl::~CDemoControl()
       
   179     {
       
   180     // Cancel this classes read request to the Console
       
   181     Cancel();
       
   182     if(iIfState != EIdle)
       
   183 	{
       
   184 	EmptyWriteQueue();
       
   185 	StopCard();
       
   186 	}
       
   187 
       
   188     User::FreeLogicalDevice(LDD_NAME);
       
   189     User::FreePhysicalDevice(PDD_NAME);
       
   190 
       
   191 
       
   192 #if (defined __USE_TIMER__)
       
   193     iTimer->Cancel();
       
   194     delete iTimer;
       
   195 #endif
       
   196 
       
   197     delete iWriter;
       
   198     delete iReader;
       
   199     }
       
   200 
       
   201 void CDemoControl::RequestCharacter()
       
   202 // Request a character from the CConsoleBase class and set us to Active
       
   203     {
       
   204     // Read() will result in our iStatus being set to KRequestPending 0x80000001
       
   205     console->Read(iStatus);
       
   206     // SetActive sets our iActive to ETrue
       
   207     SetActive();
       
   208     }
       
   209 
       
   210 void CDemoControl::RunL()
       
   211 // Mandatory override of pure virtual called from active scheduler Start()
       
   212 // Key method called when the Active Scheduler semaphore is
       
   213 // signalled and the iStatus has been completed for this Active Object
       
   214     {
       
   215     ProcessKeyPress(TChar(console->KeyCode()));
       
   216     RequestCharacter();
       
   217     // We now return control to the scheduler loop
       
   218     }
       
   219 
       
   220 void CDemoControl::DoCancel()
       
   221 // Mandatory override of pure virtual, called from Cancel()
       
   222     {
       
   223     // Cancels an outstanding request to the console
       
   224     console->ReadCancel();
       
   225     }
       
   226 
       
   227 static const TUint KEscChar = 0x1b;
       
   228 void CDemoControl::ProcessKeyPress(TChar aChar)
       
   229 // Process commands from the console
       
   230 // Executes in the context of the class RunL()
       
   231     {
       
   232     TInt err = KErrNone;
       
   233     if(aChar == KEscChar)
       
   234 	{
       
   235 	// Modifies loop control flag value so the scheduler loop exits
       
   236 	CActiveScheduler::Stop();
       
   237 	}
       
   238     else if(aChar == 'h' || aChar == 'H')
       
   239 	{
       
   240 	HelpText();
       
   241 	}
       
   242     else
       
   243 	{
       
   244 	// Add Command Handler Methods here
       
   245 	switch(aChar)
       
   246 	    {
       
   247 	    case 'p'	:
       
   248 	    case 'P'	:
       
   249 		TRAP(err,PumpL());
       
   250 		break;
       
   251 	    case 'e'	:
       
   252 	    case 'E'	:
       
   253 		TRAP(err,EchoL());
       
   254 		break;
       
   255 	    case 'r'	:
       
   256 	    case 'R'	:
       
   257 		TRAP(err,ReadL());
       
   258 		break;
       
   259 	    case 's'	:
       
   260 	    case 'S'	:
       
   261 		TRAP(err,StopL());
       
   262 		break;
       
   263 		case 'c'	:
       
   264 		case 'C'	:
       
   265 		TRAP(err,SendAndCompareEchoL());
       
   266 		break;
       
   267 		case 'd'	:
       
   268 		case 'D'	:
       
   269 		TRAP(err,ReadAndSetDestMacL());
       
   270 		break;
       
   271 		case 'm'	:
       
   272 		case 'M'	:
       
   273 			ReadAndDisplaySettings();
       
   274 		break;				
       
   275 	    default		:
       
   276 		break;
       
   277 	    }
       
   278 
       
   279 	if(err != KErrNone)
       
   280 	    {
       
   281 	    PrintError(aChar);
       
   282 	    }
       
   283 	else
       
   284 	    {
       
   285 	    _LIT(KMess,"State = %d\r\n");
       
   286 	    console->ClearScreen();
       
   287 	    console->SetPos(0,0);
       
   288 	    console->Printf(KMess,iIfState);
       
   289 	    }
       
   290 	}
       
   291     }
       
   292 
       
   293 void CDemoControl::HelpText() const
       
   294     {
       
   295 	_LIT(KMess,"Press 'Esc' to exit \r\nPress 'H' for Help \r\nPress 'P' for Data Pump \r\nPress 'E' for Echo \r\nPress 'R' for Read \r\nPress 'C' for send and Compare echo \r\nPress 'D' to set dest MAC\r\nPress 'M' to display Settings\r\nPress 'S' to Stop");
       
   296 	console->ClearScreen();
       
   297     console->SetPos(0,5);
       
   298     console->Printf(KMess);
       
   299     }
       
   300 
       
   301 void CDemoControl::PrintError(TChar aChar)
       
   302     {
       
   303     //_LIT(KMess,"Command Error = %c State = %d\r\n1 = Idle\r\n2 = Echo\r\n3 = Read\r\n4 = Pump");
       
   304 	_LIT(KMess,"Command Error = %c State = %d\r\n0 = Idle\r\n1 = Echo\r\n2 = Read\r\n3 = Pump\r\n4 = send & Compare echo");
       
   305 	console->ClearScreen();
       
   306     console->SetPos(0,5);
       
   307     console->Printf(KMess,(char)aChar,iIfState);	
       
   308     }
       
   309 
       
   310 void CDemoControl::EchoL()
       
   311     {
       
   312     if(iIfState != EIdle)
       
   313 	{
       
   314 	User::Leave(KErrInUse);
       
   315 	}
       
   316     StartCardL();
       
   317 
       
   318     iReadBuffer.SetMax();
       
   319     iReadBuffer.FillZ();
       
   320     iReader->ReadL(iReadBuffer);
       
   321 
       
   322     iIfState = EEcho;
       
   323     }
       
   324 
       
   325 void CDemoControl::PumpL()
       
   326     {
       
   327     console->ClearScreen();
       
   328 
       
   329     if(iIfState != EIdle)
       
   330 	{
       
   331 	User::Leave(KErrInUse);
       
   332 	}
       
   333 #if (defined __USE_TIMER__)
       
   334     iTimer->Start(0,1,TCallBack(Callback,this));
       
   335 #endif
       
   336     StartCardL();
       
   337 	
       
   338     iReadBuffer.SetMax();
       
   339     iReadBuffer.FillZ();
       
   340     iReader->ReadL(iReadBuffer);
       
   341 
       
   342 #if (!defined __USE_TIMER__)
       
   343     CIOBuffer* buf = CreateSendPacketL();
       
   344 
       
   345     iWriteQueue.AddLast(*buf);
       
   346     iWriter->WriteL(buf->Ptr());
       
   347 #endif
       
   348 
       
   349     iIfState = EPump;
       
   350     }
       
   351 
       
   352 void CDemoControl::ReadAndDisplaySettings()
       
   353 //
       
   354 // Read and display the current config
       
   355 //
       
   356     {
       
   357     TBuf8<32> config;
       
   358 
       
   359     User::LeaveIfError(iCard.Open(0));
       
   360     User::After(2000);
       
   361 
       
   362     // MAC Address starts at the 4th byte
       
   363     config.SetMax();
       
   364     iCard.Config(config);
       
   365 
       
   366 
       
   367     console->Printf(_L("\n\nEthernet Speed :"));
       
   368     switch (config[0])
       
   369 	{
       
   370 	case KEthSpeedUnknown:
       
   371 	    console->Printf(_L(" Unknown\n"));
       
   372 	    break;
       
   373 	case KEthSpeedAuto:
       
   374 	    console->Printf(_L(" Auto\n"));
       
   375 	    break;
       
   376 	case KEthSpeed10BaseT:
       
   377 	    console->Printf(_L(" 10 MBit\n"));
       
   378 	    break;
       
   379 	case KEthSpeed100BaseTX:
       
   380 	    console->Printf(_L(" 100 MBit\n"));
       
   381 	    break;
       
   382 	default:
       
   383 	    console->Printf(_L(" ERROR\n"));
       
   384 	}
       
   385 
       
   386     console->Printf(_L("Duplex Setting :"));
       
   387     switch (config[1])
       
   388 	{
       
   389 	case KEthDuplexUnknown:
       
   390 	    console->Printf(_L(" Unknown\n"));
       
   391 	    break;
       
   392 	case KEthDuplexAuto:
       
   393 	    console->Printf(_L(" Auto\n"));
       
   394 	    break;
       
   395 	case KEthDuplexFull:
       
   396 	    console->Printf(_L(" Full\n"));
       
   397 	    break;
       
   398 	case KEthDuplexHalf:
       
   399 	    console->Printf(_L(" Half\n"));
       
   400 	    break;
       
   401 	default:
       
   402 	    console->Printf(_L(" ERROR\n"));
       
   403 	}
       
   404 
       
   405     console->Printf(_L("MAC :"));
       
   406     console->Printf(_L(" %2x:%2x:%2x:%2x:%2x:%2x\n\n"),
       
   407 		 config[2], config[3],
       
   408 		 config[4], config[5],
       
   409 		 config[6], config[7]);
       
   410 
       
   411 	console->Printf(_L("\nPress any key to continue..\n") );
       
   412 
       
   413 	console->Getch();
       
   414 
       
   415 	iCard.Close();
       
   416     }
       
   417 
       
   418 
       
   419 CIOBuffer* CDemoControl::CreateSendPacketL()
       
   420     {
       
   421     CIOBuffer* buf = CIOBuffer::NewL(1500);
       
   422     // Copy in the Destination mac address
       
   423     buf->Ptr().SetLength(6);
       
   424     buf->Ptr().Copy(DestMacAddr,6);
       
   425 
       
   426     // Copy in the source mac address read from the driver
       
   427     //buf->Ptr().Append(&iConfig[3],6);
       
   428 	buf->Ptr().Append(&iConfig[2],6);
       
   429 	
       
   430     // EtherII framing
       
   431     buf->Ptr().Append(0x08);
       
   432     buf->Ptr().Append(0x06);
       
   433     buf->Ptr().SetMax();
       
   434     StripeDes(buf->Ptr(), 14, buf->Ptr().Length(), '@', 'Z',0);
       
   435     return buf;
       
   436     }
       
   437 
       
   438 void CDemoControl::ReadL()
       
   439     {
       
   440     if(iIfState != EIdle)
       
   441 	{
       
   442 	User::Leave(KErrInUse);
       
   443 	}
       
   444 	
       
   445     StartCardL();
       
   446 	
       
   447     iReadBuffer.SetMax();
       
   448     iReadBuffer.FillZ();
       
   449     iReader->ReadL(iReadBuffer);
       
   450 
       
   451     iIfState = ERead;
       
   452     }
       
   453 
       
   454 
       
   455 
       
   456 
       
   457 CIOBuffer* CDemoControl::CreateRandomPacketL(TInt aOffset)
       
   458 	{
       
   459 	CIOBuffer* buf = CIOBuffer::NewL(1500);
       
   460 	// Copy in the Destination mac address
       
   461 	buf->Ptr().SetLength(6);
       
   462 	buf->Ptr().Copy(DestMacAddr,6);
       
   463 #if (defined __USE_LDDPDD__)
       
   464 	// Copy in the source mac address read from the driver
       
   465 	//buf->Ptr().Append(&iConfig[3],6);
       
   466 	buf->Ptr().Append(&iConfig[2],6);
       
   467 #else
       
   468 	buf->Ptr().Append(DummyMac,6);
       
   469 #endif
       
   470 	// EtherII framing
       
   471 	buf->Ptr().Append(0x08);
       
   472 	buf->Ptr().Append(0x06);
       
   473 	buf->Ptr().SetMax();
       
   474 	
       
   475 	StripeDes(buf->Ptr(), 14, buf->Ptr().Length(), '@', 'Z',aOffset);
       
   476 	return buf;
       
   477 }
       
   478 
       
   479 
       
   480 TInt CDemoControl::iSendAndEchoCmpCounter = 0;
       
   481 
       
   482 void CDemoControl::CompareEcho()
       
   483 {
       
   484 	iSendAndEchoSame = 
       
   485 		CheckDes(iReadBuffer, 14, /*iReadBuffer.Length() - 4*/ 1500 - 4, '@', 'Z', iIntRandomOffset);
       
   486 										// - 4 for trailer
       
   487 	console->Printf(_L("\r\nSent & Received Random Packet no: %d \r\n"), iSendAndEchoCmpCounter );
       
   488 	
       
   489 	if( iSendAndEchoSame )
       
   490 		console->Printf( _L("Echo Same: TRUE \r\n") );
       
   491 	else
       
   492 		console->Printf( _L("Echo Same: FALSE \r\n") );
       
   493 	
       
   494 
       
   495 }
       
   496 
       
   497 void CDemoControl::SendAndCompareEchoL()
       
   498 {
       
   499 	if(iIfState != EIdle)
       
   500 		{
       
   501 		User::Leave(KErrInUse);
       
   502 		}
       
   503 
       
   504 	iSendAndEchoSame = EFalse;
       
   505 
       
   506 	StartCardL();
       
   507 	
       
   508 	// empty write buffer before start - nothing else should write 
       
   509 	// when iIfState = ESendAndCmpEcho
       
   510 	EmptyWriteQueue();
       
   511 	
       
   512 	iIfState = ESendAndCmpEcho;
       
   513 
       
   514 	// time for generating seed for rand function
       
   515 	TTime time;
       
   516 	time.HomeTime(); 
       
   517 
       
   518 	// change seed after 10 frames sent
       
   519 	if( 0 == (iSendAndEchoCmpCounter % 10) )
       
   520 	{
       
   521 		iIntSeed = time.Int64();
       
   522 	}
       
   523 
       
   524 	iIntRandomOffset = Math::Rand( iIntSeed );
       
   525 
       
   526 	CIOBuffer* buf = CreateRandomPacketL( iIntRandomOffset );
       
   527 	
       
   528 	iWriteQueue.AddLast(*buf);
       
   529 	iWriter->WriteL(buf->Ptr());
       
   530 }
       
   531 
       
   532 void CDemoControl::HandleWriteCompleteSndCmpEchoModeL()
       
   533 {
       
   534 	
       
   535 	CIOBuffer* buf = iWriteQueue.First();
       
   536 	iWriteQueue.Remove(*buf);
       
   537 	delete buf;
       
   538 
       
   539 	iSendAndEchoCmpCounter = ++iSendAndEchoCmpCounter;
       
   540 		
       
   541 	// empty read buffer
       
   542 	iReadBuffer.SetMax();
       
   543 	iReadBuffer.FillZ();	
       
   544 	// read echo
       
   545 	iReader->ReadL(iReadBuffer);
       
   546 }
       
   547 
       
   548 void CDemoControl::HandleReadCompleteSndCmpEchoModeL()
       
   549 {
       
   550 	CompareEcho();
       
   551 
       
   552 	// empty read buffer
       
   553 	iReadBuffer.SetMax();
       
   554     iReadBuffer.FillZ();
       
   555 
       
   556 //	iIfState = EIdle;
       
   557 }
       
   558 
       
   559 void CDemoControl::ReadAndSetDestMacL()
       
   560 {
       
   561 	
       
   562 	TUint8 upper=0;
       
   563 	TInt i =0;
       
   564 	//TInt consPos = 0;
       
   565 	TChar c;
       
   566 	TInt pos; 
       
   567 	TUint8 value;
       
   568 
       
   569 	TBuf<20> validChars(_L("0123456789abcdef"));
       
   570 
       
   571 	TUint8 newDestMacAddr[] = {0x00,0x00,0x00,0x00,0x00,0x00};
       
   572 
       
   573 	_LIT(KMess,"Type new dest MAC (12 hexagonal digits):\r\n");
       
   574 	console->ClearScreen();
       
   575 	console->SetPos(0,0);
       
   576 	console->Printf(KMess,iIfState);
       
   577 
       
   578 	for(i = 0; i < 12; i++)
       
   579 	{
       
   580 		c = console->Getch();
       
   581 		c.LowerCase();
       
   582 		if((pos = validChars.Locate(c))==KErrNotFound)
       
   583 		    {
       
   584 		    //pos = upper;
       
   585 			User::Leave(KErrNotFound); 
       
   586 		    //break;
       
   587 		    }
       
   588 		console->SetPos(i, 1);
       
   589 		console->Printf(_L("%c"), (char)c);
       
   590 		if(i%2)
       
   591 		{
       
   592 			upper = newDestMacAddr[i / 2];
       
   593 			value = (TUint8)pos;
       
   594 			//value = (TUint8)((upper<<4) | value);
       
   595 			newDestMacAddr[i / 2] = (TUint8)((upper<<4) | value);
       
   596 		}
       
   597 		else
       
   598 			newDestMacAddr[i / 2] = (TUint8)pos;
       
   599 		
       
   600 	}
       
   601 
       
   602 	for(i = 0; i < 6; i++)
       
   603 		DestMacAddr[i] = newDestMacAddr[i];
       
   604 
       
   605 	console->Printf(_L("\nSetting MAC to %2x:%2x:%2x:%2x:%2x:%2x\n"),
       
   606 			 DestMacAddr[0], DestMacAddr[1], DestMacAddr[2],
       
   607 			 DestMacAddr[3], DestMacAddr[4], DestMacAddr[5]);
       
   608 
       
   609 	console->Printf(_L("\nPress any key to continue..\n") );
       
   610 
       
   611 	console->Getch();
       
   612 
       
   613    return; 
       
   614 }
       
   615 
       
   616 //-jk
       
   617 
       
   618 void CDemoControl::StopL()
       
   619     {
       
   620     if(iIfState == EIdle)
       
   621 		{
       
   622 		User::Leave(KErrInUse);
       
   623 		}
       
   624 
       
   625     EmptyWriteQueue();
       
   626 #if (defined __USE_TIMER__)
       
   627     if(iIfState == EPump)
       
   628 	{
       
   629 		iTimer->Cancel();
       
   630 		_LIT(KMess,"\r\nPackets Pumped = %d\r\n");
       
   631 		console->Printf(KMess,iPacketsWritten);
       
   632 		console->Printf(_L("\r\nPress any key to continue..\r\n") );
       
   633 		console->Getch();
       
   634 	}
       
   635 #endif
       
   636     StopCard();
       
   637 
       
   638     iIfState = EIdle;
       
   639     }
       
   640 
       
   641 void CDemoControl::StartCardL()
       
   642     {
       
   643 //	User::LeaveIfError(iCard.Open(iCard.VersionRequired(),0,NULL));
       
   644     User::LeaveIfError(iCard.Open(0));
       
   645     User::After(2000000);
       
   646 //	TBuf8<8> ioctlBuf;
       
   647 //	ioctlBuf.SetLength(1);
       
   648 //	ioctlBuf[0] = KIoControlGetStatus;
       
   649 //	TRequestStatus status;
       
   650 //	iCard.IOControl(iStatus,ioctlBuf);
       
   651 //	User::WaitForRequest(status);
       
   652 //	if(ioctlBuf[0] != KEventPCCardReady)
       
   653 //		{
       
   654 //		iCard.Close();
       
   655 //		User::Leave(KErrNotReady);
       
   656 //		}
       
   657     // MAC Address starts at the 2nd byte
       
   658     iConfig.SetMax();
       
   659     iCard.Config(iConfig);
       
   660 
       
   661     iPacketsRead = 0;
       
   662     iPacketsWritten = 0;
       
   663     console->ClearScreen();
       
   664     }
       
   665 
       
   666 void CDemoControl::StopCard()
       
   667     {
       
   668 	
       
   669     iCard.ReadCancel();
       
   670     iCard.WriteCancel();
       
   671     iWriter->Cancel();
       
   672     iReader->Cancel();
       
   673 	
       
   674     iCard.Close();
       
   675 		
       
   676     }
       
   677 
       
   678 void CDemoControl::ReadCompleteL(const TInt aStatus)
       
   679 // Read completed by the server
       
   680     {
       
   681     iPacketsRead++;
       
   682     console->SetPos(0,1);
       
   683     _LIT(KMess,"Read  Complete Status = %d Packets Read    = %d\r\n");
       
   684     console->Printf(KMess,aStatus,iPacketsRead);
       
   685 	RDebug::Print(KMess,aStatus,iPacketsRead);
       
   686     // Validate the received buffer with what we sent
       
   687 
       
   688     switch(iIfState)
       
   689 	{
       
   690 	case EPump:
       
   691 	    HandleReadCompletePumpModeL();
       
   692 	    break;
       
   693 
       
   694 	case EEcho:
       
   695 	    HandleReadCompleteEchoModeL();
       
   696 	    break;
       
   697 		
       
   698 	case ERead:
       
   699 	    HandleReadCompleteReadModeL();
       
   700 	    break;
       
   701 
       
   702 	case ESendAndCmpEcho:
       
   703 		HandleReadCompleteSndCmpEchoModeL();
       
   704 		break;
       
   705 		
       
   706 	default:
       
   707 	    break;
       
   708 	}
       
   709     iReadBuffer.SetMax();
       
   710     iReadBuffer.FillZ();
       
   711     iReader->ReadL(iReadBuffer);
       
   712     }
       
   713 
       
   714 void CDemoControl::WriteCompleteL(const TInt aStatus)
       
   715 // Write completed by the server
       
   716     {
       
   717     iPacketsWritten++;
       
   718     console->SetPos(0,0);
       
   719     _LIT(KMess,"Write Complete Status = %d Packets Written = %d\r\n");
       
   720     console->Printf(KMess,aStatus,iPacketsWritten);
       
   721 
       
   722     switch(iIfState)
       
   723 	{
       
   724 	case EPump:
       
   725 	    HandleWriteCompletePumpModeL();
       
   726 	    break;
       
   727 
       
   728 	case EEcho:
       
   729 	    HandleWriteCompleteEchoModeL();
       
   730 	    break;
       
   731 
       
   732 	case ESendAndCmpEcho:
       
   733 			HandleWriteCompleteSndCmpEchoModeL();
       
   734 			break;
       
   735 	
       
   736 	default:
       
   737 	    break;
       
   738 	}
       
   739     }
       
   740 
       
   741 void CDemoControl::HandleWriteCompleteEchoModeL()
       
   742     {
       
   743     CIOBuffer* buf = iWriteQueue.First();
       
   744     iWriteQueue.Remove(*buf);
       
   745     delete buf;
       
   746     if(!iWriteQueue.IsEmpty())
       
   747 	{
       
   748 	buf = iWriteQueue.First();
       
   749 	iWriter->WriteL(buf->Ptr());
       
   750 	}
       
   751     }
       
   752 
       
   753 void CDemoControl::HandleReadCompleteEchoModeL()
       
   754     // In echo mode we send out what we receive and there could potentialy be a write
       
   755     // outstanding.
       
   756     // Get a new CIOBuffer copy the read data to the new write buffer
       
   757     // Queue it but only WriteL() it if the queue was empty
       
   758     {
       
   759     TBool sendNow = EFalse;
       
   760     (iWriteQueue.IsEmpty()) ? (sendNow = ETrue) : (sendNow = EFalse);
       
   761     // Add it to the queue
       
   762     CIOBuffer* buf = CIOBuffer::NewL(iReadBuffer.Length());
       
   763 	
       
   764     buf->Ptr() = iReadBuffer;
       
   765 
       
   766     // Flip Mac Addresses in buf
       
   767     FlipMacAddresses(buf->Ptr());
       
   768 
       
   769     iWriteQueue.AddLast(*buf);
       
   770     if(sendNow)
       
   771 	{
       
   772 	iWriter->WriteL(buf->Ptr());
       
   773 	}
       
   774     }
       
   775 
       
   776 void CDemoControl::FlipMacAddresses(TDes8& aBuf)
       
   777     {
       
   778     TUint32 length = aBuf.Length();
       
   779     aBuf.SetLength(6);
       
   780     TBuf8<6> dest(aBuf);
       
   781     aBuf.SetLength(12);
       
   782     aBuf.Copy(&aBuf[6],6);
       
   783     aBuf.SetLength(6);
       
   784     aBuf.Append(dest);
       
   785     aBuf.SetLength(length);
       
   786     }
       
   787 
       
   788 void CDemoControl::HandleWriteCompletePumpModeL()
       
   789     // In pump mode we never need to queue so just reuse the last buffer
       
   790     {
       
   791 #if (defined __USE_TIMER__)
       
   792     CIOBuffer* buf = iWriteQueue.First();
       
   793     iWriteQueue.Remove(*buf);
       
   794     delete buf;
       
   795 #else
       
   796     CIOBuffer* buf = iWriteQueue.First();
       
   797     iWriter->WriteL(buf->Ptr());
       
   798 #endif
       
   799     }
       
   800 
       
   801 void CDemoControl::HandleReadCompletePumpModeL()
       
   802     {
       
   803     }
       
   804 
       
   805 void CDemoControl::HandleReadCompleteReadModeL()
       
   806     {
       
   807     }
       
   808 
       
   809 //////////////
       
   810 
       
   811 CDemoWriter* CDemoWriter::NewL(MWriterNotify& aNotify,RBusDevEthernet& aCard)
       
   812 // Standard CBase derived creation of the Writer object
       
   813     {
       
   814     CDemoWriter* self = new (ELeave) CDemoWriter(EPriorityNormal);
       
   815     CleanupStack::PushL(self);
       
   816     self->ConstructL(aNotify,aCard);
       
   817     CleanupStack::Pop();
       
   818     return self;
       
   819     }
       
   820 
       
   821 
       
   822 void CDemoWriter::WriteL(const TDesC8& aBuffer)
       
   823 // Write data to the server
       
   824     {
       
   825     // Sanity check on the state of the active object
       
   826     if(IsActive())
       
   827 	{
       
   828 #if (defined __USE_TIMER__)
       
   829 	return;
       
   830 #else
       
   831 	User::Leave(KErrNotReady);
       
   832 #endif
       
   833 	}
       
   834     RDebug::Print(_L("About to write\n"));
       
   835     iCard->Write(iStatus,aBuffer);
       
   836 
       
   837     SetActive();
       
   838     }
       
   839 
       
   840 CDemoWriter::~CDemoWriter()
       
   841     {
       
   842     // Just in case, does not hurt to call if object is not active
       
   843     Cancel();
       
   844     }
       
   845 
       
   846 
       
   847 void CDemoWriter::ConstructL(MWriterNotify& aNotify,RBusDevEthernet& aCard)
       
   848 // Second phase construction. Does not actually leave 
       
   849     {
       
   850     CActiveScheduler::Add(this);
       
   851     iNotify = &aNotify;
       
   852     iCard = &aCard;
       
   853     }
       
   854 
       
   855 
       
   856 void CDemoWriter::RunL()
       
   857 // Just call back into the parent to notify Write completion
       
   858     {
       
   859     // Pass the status
       
   860     iNotify->WriteCompleteL(iStatus.Int());
       
   861     }
       
   862 
       
   863 void CDemoWriter::DoCancel()
       
   864 // Called by the CActive base class Cancel()
       
   865 // Only called if our TRequestStatus is still active 
       
   866     {
       
   867     }
       
   868 
       
   869 ///////
       
   870 
       
   871 
       
   872 CDemoReader* CDemoReader::NewL(MReaderNotify& aNotify,RBusDevEthernet& aCard)
       
   873 // Standard CBase derived creation of the Reader object
       
   874     {
       
   875     CDemoReader* self = new (ELeave) CDemoReader(EPriorityNormal+1);
       
   876     CleanupStack::PushL(self);
       
   877     self->ConstructL(aNotify,aCard);
       
   878     CleanupStack::Pop();
       
   879     return self;
       
   880     }
       
   881 
       
   882 
       
   883 void CDemoReader::ReadL(TDes8& aBuffer)
       
   884     {
       
   885     // Sanity Check
       
   886     if(IsActive())
       
   887 	{
       
   888 	User::Leave(KErrNotReady);
       
   889 	}
       
   890     RDebug::Print(_L("About to read\n"));
       
   891     iCard->Read(iStatus,aBuffer);
       
   892 
       
   893     SetActive();
       
   894     }
       
   895 
       
   896 CDemoReader::~CDemoReader()
       
   897     {
       
   898     // Just in case, does not hurt to call if object is not active
       
   899     Cancel();
       
   900     }
       
   901 
       
   902 
       
   903 void CDemoReader::ConstructL(MReaderNotify& aNotify,RBusDevEthernet& aCard)
       
   904 // Second phase construction. Does not actually leave 
       
   905     {
       
   906     CActiveScheduler::Add(this);
       
   907     iNotify = &aNotify;
       
   908     iCard = &aCard;
       
   909     }
       
   910 
       
   911 
       
   912 void CDemoReader::RunL()
       
   913 // Just call back into the parent to notify read completion
       
   914     {
       
   915     // Pass the status
       
   916     iNotify->ReadCompleteL(iStatus.Int());
       
   917     }
       
   918 
       
   919 void CDemoReader::DoCancel()
       
   920 // Called by the CActive base class Cancel()
       
   921 // Only called if our TRequestStatus is still active 
       
   922     {
       
   923     }
       
   924 
       
   925 ///////
       
   926 
       
   927 static void DriveEngineL()
       
   928     {
       
   929     // Create an Active Scheduler for the thread
       
   930     // Only one Active Scheduler per thread
       
   931     CActiveScheduler* myActiveScheduler = new(ELeave) CActiveScheduler;
       
   932     CleanupStack::PushL(myActiveScheduler);
       
   933     // Install the Active Scheduler
       
   934     CActiveScheduler::Install(myActiveScheduler);
       
   935     // Create of program control class derived from CActive
       
   936     // The ConstructL() of CDemoControl adds itself to the Active Scheduler
       
   937     RDebug::Print(_L("New demo Cntrol\n"));
       
   938     CDemoControl* demo = CDemoControl::NewLC();
       
   939     // Request a character from the the console to kick the
       
   940     // Active scheduler into life. If this is not done then we will block on the
       
   941     // Scheduler loop semaphore forever.
       
   942     RDebug::Print(_L("demo Control request char\n"));
       
   943     demo->RequestCharacter();
       
   944     // Active scheduler now enters its control loop
       
   945     // We can exit this loop and hence the program by calling CActiveScheduler::Stop()
       
   946     // from a RunL().
       
   947     // IMPORTANT :-
       
   948     // From now on all this thread's processing takes place from the RunL()'s of
       
   949     // the Active objects that have been added to the Active Scheduler
       
   950     RDebug::Print(_L("Start scheduler\n"));
       
   951     myActiveScheduler->Start();
       
   952     // Remove and delete demo and myActiveScheduler
       
   953     CleanupStack::PopAndDestroy(2);	
       
   954     }
       
   955 
       
   956 static void MainL()
       
   957     {
       
   958     // String Literal MACRO initialises a Descriptor
       
   959     //_LIT(KTitle,"EtherPump");
       
   960     //console=Console::NewL(KTitle,TSize(KDefaultConsWidth,KDefaultConsHeight));
       
   961     console=Console::NewL(_L("EtherPump"),TSize(KConsFullScreen,KConsFullScreen));
       
   962     RDebug::Print(_L("Console created\n"));
       
   963     CleanupStack::PushL(console);
       
   964     RDebug::Print(_L("and put on cu stack\n"));
       
   965     // TRAP
       
   966     TRAPD(err,DriveEngineL());
       
   967     if(err != KErrNone)
       
   968 	{
       
   969 	_LIT(KErrText,"Function Leave Code = %d\r\n");
       
   970 	console->Printf(KErrText,err);
       
   971 	}
       
   972 
       
   973     _LIT(KAnyKey,"Hit Any Key to Exit");
       
   974     console->ClearScreen();
       
   975     console->Printf(KAnyKey);
       
   976     console->Getch();
       
   977     CleanupStack::PopAndDestroy(1);
       
   978     }
       
   979 
       
   980 // Entry point for all Epoc32 executables
       
   981 // See PSP Chapter 2 Getting Started
       
   982 GLDEF_C TInt E32Main()
       
   983     {
       
   984     // Heap balance checking
       
   985     // See PSP Chapter 6 Error Handling
       
   986     RDebug::Print(_L("create cu stack\n"));
       
   987     __UHEAP_MARK;
       
   988     CTrapCleanup* cleanup = CTrapCleanup::New();
       
   989     if(cleanup == NULL)
       
   990 	{
       
   991 	return KErrNoMemory;
       
   992 	}
       
   993     RDebug::Print(_L("Run mainL\n"));
       
   994     TRAPD(err,MainL());
       
   995     _LIT(KPanic,"Etherpump");
       
   996     __ASSERT_ALWAYS(!err, User::Panic(KPanic,err));
       
   997     delete cleanup;
       
   998     __UHEAP_MARKEND;
       
   999     return KErrNone;
       
  1000     }
       
  1001 ///////////////////////
       
  1002 
       
  1003 // Generic Buffer class
       
  1004 // Currently used for transmit buffers
       
  1005 CIOBuffer::CIOBuffer() : iBufPtr(NULL,0)
       
  1006     {
       
  1007     }
       
  1008 
       
  1009 CIOBuffer::~CIOBuffer()
       
  1010 // Free the HBuf if there is one
       
  1011     {
       
  1012     FreeData();
       
  1013     }
       
  1014 
       
  1015 TPtr8& CIOBuffer::Ptr()
       
  1016     {
       
  1017     return iBufPtr;
       
  1018     }
       
  1019 
       
  1020 CIOBuffer* CIOBuffer::NewL(const TInt aSize)
       
  1021 // Creation where we new the HBuf
       
  1022     {
       
  1023     CIOBuffer * self = new (ELeave) CIOBuffer;
       
  1024     CleanupStack::PushL(self);
       
  1025     self->ConstructL(aSize);
       
  1026     CleanupStack::Pop();
       
  1027     return self;
       
  1028     }
       
  1029 
       
  1030 void CIOBuffer::ConstructL(const TInt aSize)
       
  1031 // Construction where we new the HBuf
       
  1032     {
       
  1033     iBuf = HBufC8::NewL(aSize);
       
  1034     TPtr8 temp=iBuf->Des();
       
  1035     iBufPtr.Set(temp);
       
  1036     }
       
  1037 
       
  1038 CIOBuffer* CIOBuffer::NewL(HBufC8* aBuf)
       
  1039 // HBuf provided
       
  1040     {
       
  1041     CIOBuffer * self = new (ELeave) CIOBuffer;
       
  1042     CleanupStack::PushL(self);
       
  1043     self->ConstructL(aBuf);
       
  1044     CleanupStack::Pop();
       
  1045     return self;
       
  1046     }
       
  1047 
       
  1048 void CIOBuffer::ConstructL(HBufC8* aBuffer)
       
  1049     {
       
  1050     Assign(aBuffer);
       
  1051     }
       
  1052 
       
  1053 TInt CIOBuffer::LinkOffset()
       
  1054     {
       
  1055     return _FOFF(CIOBuffer,iLink);	
       
  1056     }
       
  1057 
       
  1058 void CIOBuffer::Assign(HBufC8* aBuffer)
       
  1059     {
       
  1060     iBuf = aBuffer;
       
  1061     if(aBuffer)
       
  1062 	{
       
  1063 	TPtr8 temp=iBuf->Des();
       
  1064 	iBufPtr.Set(temp);
       
  1065 	}
       
  1066     }
       
  1067 
       
  1068 HBufC8*	CIOBuffer::Data() const
       
  1069     {
       
  1070     return iBuf;
       
  1071     }
       
  1072 
       
  1073 void CIOBuffer::FreeData()
       
  1074     {
       
  1075     if(iBuf)
       
  1076 	{
       
  1077 	delete iBuf;
       
  1078 	iBuf = NULL;
       
  1079 	}
       
  1080     }