|
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 } |