sl@0: // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32test\ethernet\etherpump.cpp sl@0: // Abbreviations - PSP (Professional Symbian Programming) sl@0: // sl@0: // sl@0: sl@0: #define __USE_LDDPDD__ sl@0: #define __USE_TIMER__ sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #include sl@0: sl@0: #include "activeio.h" sl@0: sl@0: #define LDD_NAME _L("Enet") sl@0: #if (!defined __WINS__) sl@0: #define PDD_NAME _L("Ethernet") sl@0: #else sl@0: sl@0: //#define PDD_NAME _L("EthernetWins") sl@0: #define PDD_NAME _L("Ethernet") sl@0: #endif sl@0: sl@0: sl@0: // changed from const to static sl@0: //const TUint8 DestMacAddr[] = {0x00,0x50,0xDA,0xE9,0x69,0xCA}; sl@0: sl@0: // MAC address with second bit 1 sl@0: static TUint8 DestMacAddr[] = {0x02,0xB0,0xD0,0x64,0x98,0x02}; sl@0: sl@0: sl@0: // for random functions sl@0: #include sl@0: sl@0: sl@0: void StripeMem(TUint8 *aBuf, TInt aStartPos, TInt anEndPos, TUint aStartChar, TUint anEndChar, TInt aOffset) sl@0: // sl@0: // Mark a buffer with repeating byte pattern sl@0: // sl@0: { sl@0: TUint character=aStartChar+(aOffset%((anEndChar+1)-aStartChar)); sl@0: sl@0: for (TInt i=aStartPos;ianEndChar) sl@0: character=aStartChar; sl@0: } sl@0: } sl@0: sl@0: void StripeDes(TDes8 &aBuf, TInt aStartPos, TInt anEndPos, TUint aStartChar, TUint anEndChar, TInt aOffset) sl@0: { sl@0: StripeMem((TUint8 *)aBuf.Ptr(), aStartPos, anEndPos, aStartChar, anEndChar, aOffset); sl@0: } sl@0: sl@0: TBool CheckMem(TUint8 *aBuf, TInt aStartPos, TInt anEndPos, TUint aStartChar, TUint anEndChar, TInt aOffset) sl@0: // sl@0: // Mark a buffer with repeating byte pattern sl@0: // sl@0: { sl@0: TUint character=aStartChar+(aOffset%((anEndChar+1)-aStartChar)); sl@0: sl@0: for (TInt i=aStartPos;ianEndChar) sl@0: character=aStartChar; sl@0: } sl@0: return ETrue; sl@0: } sl@0: sl@0: TBool CheckDes(TDes8 &aBuf, TInt aStartPos, TInt anEndPos, TUint aStartChar, TUint anEndChar, TInt aOffset) sl@0: { sl@0: return CheckMem((TUint8 *)aBuf.Ptr(), aStartPos, anEndPos, aStartChar, anEndChar, aOffset); sl@0: } sl@0: sl@0: sl@0: void StripeMem32(TUint *aBuf, TInt aStartPos, TInt aEndPos) sl@0: // sl@0: // Mark a buffer with repeating byte pattern sl@0: // sl@0: { sl@0: aStartPos >>= 2; sl@0: aEndPos >>= 2; sl@0: sl@0: for (TInt i=aStartPos;iConstructL(); sl@0: return self; sl@0: } sl@0: TInt CDemoControl::Callback(TAny* aControl) sl@0: // Callback function for timer expiry sl@0: // Just pump another packet at the server sl@0: // It's a static so call a class member to access private data sl@0: { sl@0: CIOBuffer* buf = ((CDemoControl*)aControl)->CreateSendPacketL(); sl@0: sl@0: ((CDemoControl*)aControl)->iWriteQueue.AddLast(*buf); sl@0: ((CDemoControl*)aControl)->iWriter->WriteL(buf->Ptr()); sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: void CDemoControl::ConstructL() sl@0: // Second Phase construction sl@0: { sl@0: // Add us to the Active Scheduler for the thread sl@0: CActiveScheduler::Add(this); sl@0: // Create the Read and Write Active Objects sl@0: // The 'this' pointer is the MxxxNotify callback interface that CDemoControl is derived from sl@0: // Pass a reference to the Server session so they can make read and write requests sl@0: sl@0: iWriter = CDemoWriter::NewL(*this,iCard); sl@0: iReader = CDemoReader::NewL(*this,iCard); sl@0: sl@0: User::LoadPhysicalDevice(PDD_NAME); sl@0: User::LoadLogicalDevice(LDD_NAME); sl@0: sl@0: #if (defined __USE_TIMER__) sl@0: iIfState = EIdle; sl@0: iTimer = CPeriodic::NewL(EPriorityNormal); sl@0: #endif sl@0: sl@0: iWriteQueue.SetOffset(CIOBuffer::LinkOffset()); sl@0: sl@0: HelpText(); sl@0: sl@0: } sl@0: sl@0: void CDemoControl::EmptyWriteQueue() sl@0: { sl@0: TSglQueIter iter(iWriteQueue); sl@0: CIOBuffer* buf; sl@0: while (buf = iter++, buf!=NULL) sl@0: { sl@0: iWriteQueue.Remove(*buf); sl@0: delete buf; sl@0: } sl@0: } sl@0: sl@0: CDemoControl::~CDemoControl() sl@0: { sl@0: // Cancel this classes read request to the Console sl@0: Cancel(); sl@0: if(iIfState != EIdle) sl@0: { sl@0: EmptyWriteQueue(); sl@0: StopCard(); sl@0: } sl@0: sl@0: User::FreeLogicalDevice(LDD_NAME); sl@0: User::FreePhysicalDevice(PDD_NAME); sl@0: sl@0: sl@0: #if (defined __USE_TIMER__) sl@0: iTimer->Cancel(); sl@0: delete iTimer; sl@0: #endif sl@0: sl@0: delete iWriter; sl@0: delete iReader; sl@0: } sl@0: sl@0: void CDemoControl::RequestCharacter() sl@0: // Request a character from the CConsoleBase class and set us to Active sl@0: { sl@0: // Read() will result in our iStatus being set to KRequestPending 0x80000001 sl@0: console->Read(iStatus); sl@0: // SetActive sets our iActive to ETrue sl@0: SetActive(); sl@0: } sl@0: sl@0: void CDemoControl::RunL() sl@0: // Mandatory override of pure virtual called from active scheduler Start() sl@0: // Key method called when the Active Scheduler semaphore is sl@0: // signalled and the iStatus has been completed for this Active Object sl@0: { sl@0: ProcessKeyPress(TChar(console->KeyCode())); sl@0: RequestCharacter(); sl@0: // We now return control to the scheduler loop sl@0: } sl@0: sl@0: void CDemoControl::DoCancel() sl@0: // Mandatory override of pure virtual, called from Cancel() sl@0: { sl@0: // Cancels an outstanding request to the console sl@0: console->ReadCancel(); sl@0: } sl@0: sl@0: static const TUint KEscChar = 0x1b; sl@0: void CDemoControl::ProcessKeyPress(TChar aChar) sl@0: // Process commands from the console sl@0: // Executes in the context of the class RunL() sl@0: { sl@0: TInt err = KErrNone; sl@0: if(aChar == KEscChar) sl@0: { sl@0: // Modifies loop control flag value so the scheduler loop exits sl@0: CActiveScheduler::Stop(); sl@0: } sl@0: else if(aChar == 'h' || aChar == 'H') sl@0: { sl@0: HelpText(); sl@0: } sl@0: else sl@0: { sl@0: // Add Command Handler Methods here sl@0: switch(aChar) sl@0: { sl@0: case 'p' : sl@0: case 'P' : sl@0: TRAP(err,PumpL()); sl@0: break; sl@0: case 'e' : sl@0: case 'E' : sl@0: TRAP(err,EchoL()); sl@0: break; sl@0: case 'r' : sl@0: case 'R' : sl@0: TRAP(err,ReadL()); sl@0: break; sl@0: case 's' : sl@0: case 'S' : sl@0: TRAP(err,StopL()); sl@0: break; sl@0: case 'c' : sl@0: case 'C' : sl@0: TRAP(err,SendAndCompareEchoL()); sl@0: break; sl@0: case 'd' : sl@0: case 'D' : sl@0: TRAP(err,ReadAndSetDestMacL()); sl@0: break; sl@0: case 'm' : sl@0: case 'M' : sl@0: ReadAndDisplaySettings(); sl@0: break; sl@0: default : sl@0: break; sl@0: } sl@0: sl@0: if(err != KErrNone) sl@0: { sl@0: PrintError(aChar); sl@0: } sl@0: else sl@0: { sl@0: _LIT(KMess,"State = %d\r\n"); sl@0: console->ClearScreen(); sl@0: console->SetPos(0,0); sl@0: console->Printf(KMess,iIfState); sl@0: } sl@0: } sl@0: } sl@0: sl@0: void CDemoControl::HelpText() const sl@0: { sl@0: _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"); sl@0: console->ClearScreen(); sl@0: console->SetPos(0,5); sl@0: console->Printf(KMess); sl@0: } sl@0: sl@0: void CDemoControl::PrintError(TChar aChar) sl@0: { sl@0: //_LIT(KMess,"Command Error = %c State = %d\r\n1 = Idle\r\n2 = Echo\r\n3 = Read\r\n4 = Pump"); sl@0: _LIT(KMess,"Command Error = %c State = %d\r\n0 = Idle\r\n1 = Echo\r\n2 = Read\r\n3 = Pump\r\n4 = send & Compare echo"); sl@0: console->ClearScreen(); sl@0: console->SetPos(0,5); sl@0: console->Printf(KMess,(char)aChar,iIfState); sl@0: } sl@0: sl@0: void CDemoControl::EchoL() sl@0: { sl@0: if(iIfState != EIdle) sl@0: { sl@0: User::Leave(KErrInUse); sl@0: } sl@0: StartCardL(); sl@0: sl@0: iReadBuffer.SetMax(); sl@0: iReadBuffer.FillZ(); sl@0: iReader->ReadL(iReadBuffer); sl@0: sl@0: iIfState = EEcho; sl@0: } sl@0: sl@0: void CDemoControl::PumpL() sl@0: { sl@0: console->ClearScreen(); sl@0: sl@0: if(iIfState != EIdle) sl@0: { sl@0: User::Leave(KErrInUse); sl@0: } sl@0: #if (defined __USE_TIMER__) sl@0: iTimer->Start(0,1,TCallBack(Callback,this)); sl@0: #endif sl@0: StartCardL(); sl@0: sl@0: iReadBuffer.SetMax(); sl@0: iReadBuffer.FillZ(); sl@0: iReader->ReadL(iReadBuffer); sl@0: sl@0: #if (!defined __USE_TIMER__) sl@0: CIOBuffer* buf = CreateSendPacketL(); sl@0: sl@0: iWriteQueue.AddLast(*buf); sl@0: iWriter->WriteL(buf->Ptr()); sl@0: #endif sl@0: sl@0: iIfState = EPump; sl@0: } sl@0: sl@0: void CDemoControl::ReadAndDisplaySettings() sl@0: // sl@0: // Read and display the current config sl@0: // sl@0: { sl@0: TBuf8<32> config; sl@0: sl@0: User::LeaveIfError(iCard.Open(0)); sl@0: User::After(2000); sl@0: sl@0: // MAC Address starts at the 4th byte sl@0: config.SetMax(); sl@0: iCard.Config(config); sl@0: sl@0: sl@0: console->Printf(_L("\n\nEthernet Speed :")); sl@0: switch (config[0]) sl@0: { sl@0: case KEthSpeedUnknown: sl@0: console->Printf(_L(" Unknown\n")); sl@0: break; sl@0: case KEthSpeedAuto: sl@0: console->Printf(_L(" Auto\n")); sl@0: break; sl@0: case KEthSpeed10BaseT: sl@0: console->Printf(_L(" 10 MBit\n")); sl@0: break; sl@0: case KEthSpeed100BaseTX: sl@0: console->Printf(_L(" 100 MBit\n")); sl@0: break; sl@0: default: sl@0: console->Printf(_L(" ERROR\n")); sl@0: } sl@0: sl@0: console->Printf(_L("Duplex Setting :")); sl@0: switch (config[1]) sl@0: { sl@0: case KEthDuplexUnknown: sl@0: console->Printf(_L(" Unknown\n")); sl@0: break; sl@0: case KEthDuplexAuto: sl@0: console->Printf(_L(" Auto\n")); sl@0: break; sl@0: case KEthDuplexFull: sl@0: console->Printf(_L(" Full\n")); sl@0: break; sl@0: case KEthDuplexHalf: sl@0: console->Printf(_L(" Half\n")); sl@0: break; sl@0: default: sl@0: console->Printf(_L(" ERROR\n")); sl@0: } sl@0: sl@0: console->Printf(_L("MAC :")); sl@0: console->Printf(_L(" %2x:%2x:%2x:%2x:%2x:%2x\n\n"), sl@0: config[2], config[3], sl@0: config[4], config[5], sl@0: config[6], config[7]); sl@0: sl@0: console->Printf(_L("\nPress any key to continue..\n") ); sl@0: sl@0: console->Getch(); sl@0: sl@0: iCard.Close(); sl@0: } sl@0: sl@0: sl@0: CIOBuffer* CDemoControl::CreateSendPacketL() sl@0: { sl@0: CIOBuffer* buf = CIOBuffer::NewL(1500); sl@0: // Copy in the Destination mac address sl@0: buf->Ptr().SetLength(6); sl@0: buf->Ptr().Copy(DestMacAddr,6); sl@0: sl@0: // Copy in the source mac address read from the driver sl@0: //buf->Ptr().Append(&iConfig[3],6); sl@0: buf->Ptr().Append(&iConfig[2],6); sl@0: sl@0: // EtherII framing sl@0: buf->Ptr().Append(0x08); sl@0: buf->Ptr().Append(0x06); sl@0: buf->Ptr().SetMax(); sl@0: StripeDes(buf->Ptr(), 14, buf->Ptr().Length(), '@', 'Z',0); sl@0: return buf; sl@0: } sl@0: sl@0: void CDemoControl::ReadL() sl@0: { sl@0: if(iIfState != EIdle) sl@0: { sl@0: User::Leave(KErrInUse); sl@0: } sl@0: sl@0: StartCardL(); sl@0: sl@0: iReadBuffer.SetMax(); sl@0: iReadBuffer.FillZ(); sl@0: iReader->ReadL(iReadBuffer); sl@0: sl@0: iIfState = ERead; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: CIOBuffer* CDemoControl::CreateRandomPacketL(TInt aOffset) sl@0: { sl@0: CIOBuffer* buf = CIOBuffer::NewL(1500); sl@0: // Copy in the Destination mac address sl@0: buf->Ptr().SetLength(6); sl@0: buf->Ptr().Copy(DestMacAddr,6); sl@0: #if (defined __USE_LDDPDD__) sl@0: // Copy in the source mac address read from the driver sl@0: //buf->Ptr().Append(&iConfig[3],6); sl@0: buf->Ptr().Append(&iConfig[2],6); sl@0: #else sl@0: buf->Ptr().Append(DummyMac,6); sl@0: #endif sl@0: // EtherII framing sl@0: buf->Ptr().Append(0x08); sl@0: buf->Ptr().Append(0x06); sl@0: buf->Ptr().SetMax(); sl@0: sl@0: StripeDes(buf->Ptr(), 14, buf->Ptr().Length(), '@', 'Z',aOffset); sl@0: return buf; sl@0: } sl@0: sl@0: sl@0: TInt CDemoControl::iSendAndEchoCmpCounter = 0; sl@0: sl@0: void CDemoControl::CompareEcho() sl@0: { sl@0: iSendAndEchoSame = sl@0: CheckDes(iReadBuffer, 14, /*iReadBuffer.Length() - 4*/ 1500 - 4, '@', 'Z', iIntRandomOffset); sl@0: // - 4 for trailer sl@0: console->Printf(_L("\r\nSent & Received Random Packet no: %d \r\n"), iSendAndEchoCmpCounter ); sl@0: sl@0: if( iSendAndEchoSame ) sl@0: console->Printf( _L("Echo Same: TRUE \r\n") ); sl@0: else sl@0: console->Printf( _L("Echo Same: FALSE \r\n") ); sl@0: sl@0: sl@0: } sl@0: sl@0: void CDemoControl::SendAndCompareEchoL() sl@0: { sl@0: if(iIfState != EIdle) sl@0: { sl@0: User::Leave(KErrInUse); sl@0: } sl@0: sl@0: iSendAndEchoSame = EFalse; sl@0: sl@0: StartCardL(); sl@0: sl@0: // empty write buffer before start - nothing else should write sl@0: // when iIfState = ESendAndCmpEcho sl@0: EmptyWriteQueue(); sl@0: sl@0: iIfState = ESendAndCmpEcho; sl@0: sl@0: // time for generating seed for rand function sl@0: TTime time; sl@0: time.HomeTime(); sl@0: sl@0: // change seed after 10 frames sent sl@0: if( 0 == (iSendAndEchoCmpCounter % 10) ) sl@0: { sl@0: iIntSeed = time.Int64(); sl@0: } sl@0: sl@0: iIntRandomOffset = Math::Rand( iIntSeed ); sl@0: sl@0: CIOBuffer* buf = CreateRandomPacketL( iIntRandomOffset ); sl@0: sl@0: iWriteQueue.AddLast(*buf); sl@0: iWriter->WriteL(buf->Ptr()); sl@0: } sl@0: sl@0: void CDemoControl::HandleWriteCompleteSndCmpEchoModeL() sl@0: { sl@0: sl@0: CIOBuffer* buf = iWriteQueue.First(); sl@0: iWriteQueue.Remove(*buf); sl@0: delete buf; sl@0: sl@0: iSendAndEchoCmpCounter = ++iSendAndEchoCmpCounter; sl@0: sl@0: // empty read buffer sl@0: iReadBuffer.SetMax(); sl@0: iReadBuffer.FillZ(); sl@0: // read echo sl@0: iReader->ReadL(iReadBuffer); sl@0: } sl@0: sl@0: void CDemoControl::HandleReadCompleteSndCmpEchoModeL() sl@0: { sl@0: CompareEcho(); sl@0: sl@0: // empty read buffer sl@0: iReadBuffer.SetMax(); sl@0: iReadBuffer.FillZ(); sl@0: sl@0: // iIfState = EIdle; sl@0: } sl@0: sl@0: void CDemoControl::ReadAndSetDestMacL() sl@0: { sl@0: sl@0: TUint8 upper=0; sl@0: TInt i =0; sl@0: //TInt consPos = 0; sl@0: TChar c; sl@0: TInt pos; sl@0: TUint8 value; sl@0: sl@0: TBuf<20> validChars(_L("0123456789abcdef")); sl@0: sl@0: TUint8 newDestMacAddr[] = {0x00,0x00,0x00,0x00,0x00,0x00}; sl@0: sl@0: _LIT(KMess,"Type new dest MAC (12 hexagonal digits):\r\n"); sl@0: console->ClearScreen(); sl@0: console->SetPos(0,0); sl@0: console->Printf(KMess,iIfState); sl@0: sl@0: for(i = 0; i < 12; i++) sl@0: { sl@0: c = console->Getch(); sl@0: c.LowerCase(); sl@0: if((pos = validChars.Locate(c))==KErrNotFound) sl@0: { sl@0: //pos = upper; sl@0: User::Leave(KErrNotFound); sl@0: //break; sl@0: } sl@0: console->SetPos(i, 1); sl@0: console->Printf(_L("%c"), (char)c); sl@0: if(i%2) sl@0: { sl@0: upper = newDestMacAddr[i / 2]; sl@0: value = (TUint8)pos; sl@0: //value = (TUint8)((upper<<4) | value); sl@0: newDestMacAddr[i / 2] = (TUint8)((upper<<4) | value); sl@0: } sl@0: else sl@0: newDestMacAddr[i / 2] = (TUint8)pos; sl@0: sl@0: } sl@0: sl@0: for(i = 0; i < 6; i++) sl@0: DestMacAddr[i] = newDestMacAddr[i]; sl@0: sl@0: console->Printf(_L("\nSetting MAC to %2x:%2x:%2x:%2x:%2x:%2x\n"), sl@0: DestMacAddr[0], DestMacAddr[1], DestMacAddr[2], sl@0: DestMacAddr[3], DestMacAddr[4], DestMacAddr[5]); sl@0: sl@0: console->Printf(_L("\nPress any key to continue..\n") ); sl@0: sl@0: console->Getch(); sl@0: sl@0: return; sl@0: } sl@0: sl@0: //-jk sl@0: sl@0: void CDemoControl::StopL() sl@0: { sl@0: if(iIfState == EIdle) sl@0: { sl@0: User::Leave(KErrInUse); sl@0: } sl@0: sl@0: EmptyWriteQueue(); sl@0: #if (defined __USE_TIMER__) sl@0: if(iIfState == EPump) sl@0: { sl@0: iTimer->Cancel(); sl@0: _LIT(KMess,"\r\nPackets Pumped = %d\r\n"); sl@0: console->Printf(KMess,iPacketsWritten); sl@0: console->Printf(_L("\r\nPress any key to continue..\r\n") ); sl@0: console->Getch(); sl@0: } sl@0: #endif sl@0: StopCard(); sl@0: sl@0: iIfState = EIdle; sl@0: } sl@0: sl@0: void CDemoControl::StartCardL() sl@0: { sl@0: // User::LeaveIfError(iCard.Open(iCard.VersionRequired(),0,NULL)); sl@0: User::LeaveIfError(iCard.Open(0)); sl@0: User::After(2000000); sl@0: // TBuf8<8> ioctlBuf; sl@0: // ioctlBuf.SetLength(1); sl@0: // ioctlBuf[0] = KIoControlGetStatus; sl@0: // TRequestStatus status; sl@0: // iCard.IOControl(iStatus,ioctlBuf); sl@0: // User::WaitForRequest(status); sl@0: // if(ioctlBuf[0] != KEventPCCardReady) sl@0: // { sl@0: // iCard.Close(); sl@0: // User::Leave(KErrNotReady); sl@0: // } sl@0: // MAC Address starts at the 2nd byte sl@0: iConfig.SetMax(); sl@0: iCard.Config(iConfig); sl@0: sl@0: iPacketsRead = 0; sl@0: iPacketsWritten = 0; sl@0: console->ClearScreen(); sl@0: } sl@0: sl@0: void CDemoControl::StopCard() sl@0: { sl@0: sl@0: iCard.ReadCancel(); sl@0: iCard.WriteCancel(); sl@0: iWriter->Cancel(); sl@0: iReader->Cancel(); sl@0: sl@0: iCard.Close(); sl@0: sl@0: } sl@0: sl@0: void CDemoControl::ReadCompleteL(const TInt aStatus) sl@0: // Read completed by the server sl@0: { sl@0: iPacketsRead++; sl@0: console->SetPos(0,1); sl@0: _LIT(KMess,"Read Complete Status = %d Packets Read = %d\r\n"); sl@0: console->Printf(KMess,aStatus,iPacketsRead); sl@0: RDebug::Print(KMess,aStatus,iPacketsRead); sl@0: // Validate the received buffer with what we sent sl@0: sl@0: switch(iIfState) sl@0: { sl@0: case EPump: sl@0: HandleReadCompletePumpModeL(); sl@0: break; sl@0: sl@0: case EEcho: sl@0: HandleReadCompleteEchoModeL(); sl@0: break; sl@0: sl@0: case ERead: sl@0: HandleReadCompleteReadModeL(); sl@0: break; sl@0: sl@0: case ESendAndCmpEcho: sl@0: HandleReadCompleteSndCmpEchoModeL(); sl@0: break; sl@0: sl@0: default: sl@0: break; sl@0: } sl@0: iReadBuffer.SetMax(); sl@0: iReadBuffer.FillZ(); sl@0: iReader->ReadL(iReadBuffer); sl@0: } sl@0: sl@0: void CDemoControl::WriteCompleteL(const TInt aStatus) sl@0: // Write completed by the server sl@0: { sl@0: iPacketsWritten++; sl@0: console->SetPos(0,0); sl@0: _LIT(KMess,"Write Complete Status = %d Packets Written = %d\r\n"); sl@0: console->Printf(KMess,aStatus,iPacketsWritten); sl@0: sl@0: switch(iIfState) sl@0: { sl@0: case EPump: sl@0: HandleWriteCompletePumpModeL(); sl@0: break; sl@0: sl@0: case EEcho: sl@0: HandleWriteCompleteEchoModeL(); sl@0: break; sl@0: sl@0: case ESendAndCmpEcho: sl@0: HandleWriteCompleteSndCmpEchoModeL(); sl@0: break; sl@0: sl@0: default: sl@0: break; sl@0: } sl@0: } sl@0: sl@0: void CDemoControl::HandleWriteCompleteEchoModeL() sl@0: { sl@0: CIOBuffer* buf = iWriteQueue.First(); sl@0: iWriteQueue.Remove(*buf); sl@0: delete buf; sl@0: if(!iWriteQueue.IsEmpty()) sl@0: { sl@0: buf = iWriteQueue.First(); sl@0: iWriter->WriteL(buf->Ptr()); sl@0: } sl@0: } sl@0: sl@0: void CDemoControl::HandleReadCompleteEchoModeL() sl@0: // In echo mode we send out what we receive and there could potentialy be a write sl@0: // outstanding. sl@0: // Get a new CIOBuffer copy the read data to the new write buffer sl@0: // Queue it but only WriteL() it if the queue was empty sl@0: { sl@0: TBool sendNow = EFalse; sl@0: (iWriteQueue.IsEmpty()) ? (sendNow = ETrue) : (sendNow = EFalse); sl@0: // Add it to the queue sl@0: CIOBuffer* buf = CIOBuffer::NewL(iReadBuffer.Length()); sl@0: sl@0: buf->Ptr() = iReadBuffer; sl@0: sl@0: // Flip Mac Addresses in buf sl@0: FlipMacAddresses(buf->Ptr()); sl@0: sl@0: iWriteQueue.AddLast(*buf); sl@0: if(sendNow) sl@0: { sl@0: iWriter->WriteL(buf->Ptr()); sl@0: } sl@0: } sl@0: sl@0: void CDemoControl::FlipMacAddresses(TDes8& aBuf) sl@0: { sl@0: TUint32 length = aBuf.Length(); sl@0: aBuf.SetLength(6); sl@0: TBuf8<6> dest(aBuf); sl@0: aBuf.SetLength(12); sl@0: aBuf.Copy(&aBuf[6],6); sl@0: aBuf.SetLength(6); sl@0: aBuf.Append(dest); sl@0: aBuf.SetLength(length); sl@0: } sl@0: sl@0: void CDemoControl::HandleWriteCompletePumpModeL() sl@0: // In pump mode we never need to queue so just reuse the last buffer sl@0: { sl@0: #if (defined __USE_TIMER__) sl@0: CIOBuffer* buf = iWriteQueue.First(); sl@0: iWriteQueue.Remove(*buf); sl@0: delete buf; sl@0: #else sl@0: CIOBuffer* buf = iWriteQueue.First(); sl@0: iWriter->WriteL(buf->Ptr()); sl@0: #endif sl@0: } sl@0: sl@0: void CDemoControl::HandleReadCompletePumpModeL() sl@0: { sl@0: } sl@0: sl@0: void CDemoControl::HandleReadCompleteReadModeL() sl@0: { sl@0: } sl@0: sl@0: ////////////// sl@0: sl@0: CDemoWriter* CDemoWriter::NewL(MWriterNotify& aNotify,RBusDevEthernet& aCard) sl@0: // Standard CBase derived creation of the Writer object sl@0: { sl@0: CDemoWriter* self = new (ELeave) CDemoWriter(EPriorityNormal); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aNotify,aCard); sl@0: CleanupStack::Pop(); sl@0: return self; sl@0: } sl@0: sl@0: sl@0: void CDemoWriter::WriteL(const TDesC8& aBuffer) sl@0: // Write data to the server sl@0: { sl@0: // Sanity check on the state of the active object sl@0: if(IsActive()) sl@0: { sl@0: #if (defined __USE_TIMER__) sl@0: return; sl@0: #else sl@0: User::Leave(KErrNotReady); sl@0: #endif sl@0: } sl@0: RDebug::Print(_L("About to write\n")); sl@0: iCard->Write(iStatus,aBuffer); sl@0: sl@0: SetActive(); sl@0: } sl@0: sl@0: CDemoWriter::~CDemoWriter() sl@0: { sl@0: // Just in case, does not hurt to call if object is not active sl@0: Cancel(); sl@0: } sl@0: sl@0: sl@0: void CDemoWriter::ConstructL(MWriterNotify& aNotify,RBusDevEthernet& aCard) sl@0: // Second phase construction. Does not actually leave sl@0: { sl@0: CActiveScheduler::Add(this); sl@0: iNotify = &aNotify; sl@0: iCard = &aCard; sl@0: } sl@0: sl@0: sl@0: void CDemoWriter::RunL() sl@0: // Just call back into the parent to notify Write completion sl@0: { sl@0: // Pass the status sl@0: iNotify->WriteCompleteL(iStatus.Int()); sl@0: } sl@0: sl@0: void CDemoWriter::DoCancel() sl@0: // Called by the CActive base class Cancel() sl@0: // Only called if our TRequestStatus is still active sl@0: { sl@0: } sl@0: sl@0: /////// sl@0: sl@0: sl@0: CDemoReader* CDemoReader::NewL(MReaderNotify& aNotify,RBusDevEthernet& aCard) sl@0: // Standard CBase derived creation of the Reader object sl@0: { sl@0: CDemoReader* self = new (ELeave) CDemoReader(EPriorityNormal+1); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aNotify,aCard); sl@0: CleanupStack::Pop(); sl@0: return self; sl@0: } sl@0: sl@0: sl@0: void CDemoReader::ReadL(TDes8& aBuffer) sl@0: { sl@0: // Sanity Check sl@0: if(IsActive()) sl@0: { sl@0: User::Leave(KErrNotReady); sl@0: } sl@0: RDebug::Print(_L("About to read\n")); sl@0: iCard->Read(iStatus,aBuffer); sl@0: sl@0: SetActive(); sl@0: } sl@0: sl@0: CDemoReader::~CDemoReader() sl@0: { sl@0: // Just in case, does not hurt to call if object is not active sl@0: Cancel(); sl@0: } sl@0: sl@0: sl@0: void CDemoReader::ConstructL(MReaderNotify& aNotify,RBusDevEthernet& aCard) sl@0: // Second phase construction. Does not actually leave sl@0: { sl@0: CActiveScheduler::Add(this); sl@0: iNotify = &aNotify; sl@0: iCard = &aCard; sl@0: } sl@0: sl@0: sl@0: void CDemoReader::RunL() sl@0: // Just call back into the parent to notify read completion sl@0: { sl@0: // Pass the status sl@0: iNotify->ReadCompleteL(iStatus.Int()); sl@0: } sl@0: sl@0: void CDemoReader::DoCancel() sl@0: // Called by the CActive base class Cancel() sl@0: // Only called if our TRequestStatus is still active sl@0: { sl@0: } sl@0: sl@0: /////// sl@0: sl@0: static void DriveEngineL() sl@0: { sl@0: // Create an Active Scheduler for the thread sl@0: // Only one Active Scheduler per thread sl@0: CActiveScheduler* myActiveScheduler = new(ELeave) CActiveScheduler; sl@0: CleanupStack::PushL(myActiveScheduler); sl@0: // Install the Active Scheduler sl@0: CActiveScheduler::Install(myActiveScheduler); sl@0: // Create of program control class derived from CActive sl@0: // The ConstructL() of CDemoControl adds itself to the Active Scheduler sl@0: RDebug::Print(_L("New demo Cntrol\n")); sl@0: CDemoControl* demo = CDemoControl::NewLC(); sl@0: // Request a character from the the console to kick the sl@0: // Active scheduler into life. If this is not done then we will block on the sl@0: // Scheduler loop semaphore forever. sl@0: RDebug::Print(_L("demo Control request char\n")); sl@0: demo->RequestCharacter(); sl@0: // Active scheduler now enters its control loop sl@0: // We can exit this loop and hence the program by calling CActiveScheduler::Stop() sl@0: // from a RunL(). sl@0: // IMPORTANT :- sl@0: // From now on all this thread's processing takes place from the RunL()'s of sl@0: // the Active objects that have been added to the Active Scheduler sl@0: RDebug::Print(_L("Start scheduler\n")); sl@0: myActiveScheduler->Start(); sl@0: // Remove and delete demo and myActiveScheduler sl@0: CleanupStack::PopAndDestroy(2); sl@0: } sl@0: sl@0: static void MainL() sl@0: { sl@0: // String Literal MACRO initialises a Descriptor sl@0: //_LIT(KTitle,"EtherPump"); sl@0: //console=Console::NewL(KTitle,TSize(KDefaultConsWidth,KDefaultConsHeight)); sl@0: console=Console::NewL(_L("EtherPump"),TSize(KConsFullScreen,KConsFullScreen)); sl@0: RDebug::Print(_L("Console created\n")); sl@0: CleanupStack::PushL(console); sl@0: RDebug::Print(_L("and put on cu stack\n")); sl@0: // TRAP sl@0: TRAPD(err,DriveEngineL()); sl@0: if(err != KErrNone) sl@0: { sl@0: _LIT(KErrText,"Function Leave Code = %d\r\n"); sl@0: console->Printf(KErrText,err); sl@0: } sl@0: sl@0: _LIT(KAnyKey,"Hit Any Key to Exit"); sl@0: console->ClearScreen(); sl@0: console->Printf(KAnyKey); sl@0: console->Getch(); sl@0: CleanupStack::PopAndDestroy(1); sl@0: } sl@0: sl@0: // Entry point for all Epoc32 executables sl@0: // See PSP Chapter 2 Getting Started sl@0: GLDEF_C TInt E32Main() sl@0: { sl@0: // Heap balance checking sl@0: // See PSP Chapter 6 Error Handling sl@0: RDebug::Print(_L("create cu stack\n")); sl@0: __UHEAP_MARK; sl@0: CTrapCleanup* cleanup = CTrapCleanup::New(); sl@0: if(cleanup == NULL) sl@0: { sl@0: return KErrNoMemory; sl@0: } sl@0: RDebug::Print(_L("Run mainL\n")); sl@0: TRAPD(err,MainL()); sl@0: _LIT(KPanic,"Etherpump"); sl@0: __ASSERT_ALWAYS(!err, User::Panic(KPanic,err)); sl@0: delete cleanup; sl@0: __UHEAP_MARKEND; sl@0: return KErrNone; sl@0: } sl@0: /////////////////////// sl@0: sl@0: // Generic Buffer class sl@0: // Currently used for transmit buffers sl@0: CIOBuffer::CIOBuffer() : iBufPtr(NULL,0) sl@0: { sl@0: } sl@0: sl@0: CIOBuffer::~CIOBuffer() sl@0: // Free the HBuf if there is one sl@0: { sl@0: FreeData(); sl@0: } sl@0: sl@0: TPtr8& CIOBuffer::Ptr() sl@0: { sl@0: return iBufPtr; sl@0: } sl@0: sl@0: CIOBuffer* CIOBuffer::NewL(const TInt aSize) sl@0: // Creation where we new the HBuf sl@0: { sl@0: CIOBuffer * self = new (ELeave) CIOBuffer; sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aSize); sl@0: CleanupStack::Pop(); sl@0: return self; sl@0: } sl@0: sl@0: void CIOBuffer::ConstructL(const TInt aSize) sl@0: // Construction where we new the HBuf sl@0: { sl@0: iBuf = HBufC8::NewL(aSize); sl@0: TPtr8 temp=iBuf->Des(); sl@0: iBufPtr.Set(temp); sl@0: } sl@0: sl@0: CIOBuffer* CIOBuffer::NewL(HBufC8* aBuf) sl@0: // HBuf provided sl@0: { sl@0: CIOBuffer * self = new (ELeave) CIOBuffer; sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aBuf); sl@0: CleanupStack::Pop(); sl@0: return self; sl@0: } sl@0: sl@0: void CIOBuffer::ConstructL(HBufC8* aBuffer) sl@0: { sl@0: Assign(aBuffer); sl@0: } sl@0: sl@0: TInt CIOBuffer::LinkOffset() sl@0: { sl@0: return _FOFF(CIOBuffer,iLink); sl@0: } sl@0: sl@0: void CIOBuffer::Assign(HBufC8* aBuffer) sl@0: { sl@0: iBuf = aBuffer; sl@0: if(aBuffer) sl@0: { sl@0: TPtr8 temp=iBuf->Des(); sl@0: iBufPtr.Set(temp); sl@0: } sl@0: } sl@0: sl@0: HBufC8* CIOBuffer::Data() const sl@0: { sl@0: return iBuf; sl@0: } sl@0: sl@0: void CIOBuffer::FreeData() sl@0: { sl@0: if(iBuf) sl@0: { sl@0: delete iBuf; sl@0: iBuf = NULL; sl@0: } sl@0: }