sl@0: // Copyright (c) 2007-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: // CTestCase0461.cpp
sl@0: // @internalComponent
sl@0: // 
sl@0: //
sl@0: 
sl@0: #include <e32std.h>
sl@0: #include <e32std_private.h>
sl@0: #include <u32std.h> 	// unicode builds
sl@0: #include <e32base.h>
sl@0: #include <e32base_private.h>
sl@0: #include <e32Test.h>	// RTest headder
sl@0: #include "testcaseroot.h"
sl@0: #include "testcasewd.h"
sl@0: #include "testcase0461.h"
sl@0: 
sl@0: 
sl@0: 
sl@0: // the name below is used to add a pointer to our construction method to a pointer MAP in 
sl@0: // the class factory
sl@0: _LIT(KTestCaseId,"PBASE-USB_OTGDI-0461");
sl@0: const TTestCaseFactoryReceipt<CTestCase0461> CTestCase0461::iFactoryReceipt(KTestCaseId);	
sl@0: 
sl@0: CTestCase0461* CTestCase0461::NewL(TBool aHost)
sl@0: 	{
sl@0: 	LOG_FUNC
sl@0: 	CTestCase0461* self = new (ELeave) CTestCase0461(aHost);
sl@0: 	CleanupStack::PushL(self);
sl@0: 	self->ConstructL();
sl@0: 	CleanupStack::Pop(self);
sl@0: 	return self;
sl@0: 	}
sl@0: 	
sl@0: 
sl@0: CTestCase0461::CTestCase0461(TBool aHost)
sl@0: :	CTestCaseRoot(KTestCaseId, aHost)
sl@0: 	{
sl@0: 	LOG_FUNC
sl@0: 		
sl@0: 	} 
sl@0: 
sl@0: 
sl@0: /**
sl@0:  ConstructL
sl@0: */
sl@0: void CTestCase0461::ConstructL()
sl@0: 	{
sl@0: 	LOG_FUNC
sl@0: 	iRepeats = KOperationRetriesMax;
sl@0: 	BaseConstructL();
sl@0: 	
sl@0: 	iWDTimer = CTestCaseWatchdog::NewL();
sl@0: 	}
sl@0: 
sl@0: 
sl@0: CTestCase0461::~CTestCase0461()
sl@0: 	{
sl@0: 	LOG_FUNC
sl@0: 
sl@0: 	Cancel();
sl@0: 	delete iWDTimer;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: void CTestCase0461::ExecuteTestCaseL()
sl@0: 	{
sl@0: 	LOG_FUNC
sl@0: 	iCaseStep = ELoadLdd;
sl@0: 	
sl@0: 	CActiveScheduler::Add(this);
sl@0: 	SelfComplete();
sl@0: 
sl@0: 	}
sl@0: 
sl@0: 
sl@0: void CTestCase0461::DescribePreconditions()
sl@0: 	{
sl@0: 	test.Printf(_L("Insert 'A' connector beforehand.\n"));
sl@0: 	}
sl@0: 
sl@0: 	
sl@0: void CTestCase0461::DoCancel()
sl@0: 	{
sl@0: 	LOG_FUNC
sl@0: 
sl@0: 	// cancel our timer
sl@0: 	iTimer.Cancel();
sl@0: 	}
sl@0: 	
sl@0: void CTestCase0461::CancelKB(CTestCaseRoot *pThis)
sl@0: 	{
sl@0: 	CTestCase0461 * p = REINTERPRET_CAST(CTestCase0461 *,pThis);
sl@0: 	// cancel any pending call, and then complete our active obj with a timeout value
sl@0: 
sl@0: 	p->iConsole->ReadCancel();
sl@0: 	
sl@0: 	}	
sl@0: 
sl@0: // handle event completion	
sl@0: void CTestCase0461::RunStepL()
sl@0: 	{
sl@0: 	LOG_FUNC
sl@0: 	// Obtain the completion code for this CActive obj.
sl@0: 	TInt completionCode(iStatus.Int()); 
sl@0: 	TBuf<MAX_DSTRLEN> aDescription;
sl@0: 		
sl@0: 	switch(iCaseStep)
sl@0: 		{
sl@0: 		case EPreconditions:
sl@0: 			iCaseStep = ELoadLdd;
sl@0: 			if (iAutomated)
sl@0: 				{
sl@0: 				iCaseStep = ELoadLdd;
sl@0: 				SelfComplete();
sl@0: 				break;
sl@0: 				}
sl@0: 			// prompt to insert connector
sl@0: 			test.Printf(KInsertAConnectorPrompt);
sl@0: 			test.Printf(KPressAnyKeyToContinue);
sl@0: 			RequestCharacter();			
sl@0: 			break;
sl@0: 			
sl@0: 		case ELoadLdd:
sl@0: 			if (!StepLoadLDD())
sl@0: 				{
sl@0: 				break;
sl@0: 				}
sl@0: 
sl@0: 			iCaseStep = ERegisterForEvents;
sl@0: 			SelfComplete();
sl@0: 			iDequeAttempts = 0;	
sl@0: 			break;
sl@0: 			
sl@0: 			// 2. Prepare to wait on ID_PIN
sl@0: 		case ERegisterForEvents:
sl@0: 			// prompt to remove connector
sl@0: 			test.Printf(KRemoveAConnectorPrompt);		
sl@0: 			if (iDequeAttempts > 3)
sl@0: 				{
sl@0: 				return (TestFailed(KErrCorrupt, _L("<Error> too many irrelevant/incorrect events")));
sl@0: 				}
sl@0: 
sl@0: 			otgQueueOtgEventRequest( iOTGEvent, iStatus);
sl@0: 			iIDcheckStart.HomeTime();
sl@0: 			iCaseStep = EGetAndCancelEvent;
sl@0: 			SetActive();
sl@0: 			break;
sl@0: 			
sl@0: 			// 3. pick up events already buffered when we start
sl@0: 		case EEmptyQueue:
sl@0: 			{
sl@0: 			
sl@0: 			TInt aMillisec;
sl@0: 			iIDcheckEnd.HomeTime();
sl@0: 			TTimeIntervalMicroSeconds ivlMicro(iIDcheckEnd.MicroSecondsFrom(iIDcheckStart));
sl@0: 			aMillisec = (TInt)(ivlMicro.Int64())/1000;	// USB times are in uSec, but in ms for the user layer
sl@0: 			iCaseStep = EGetAndCancelEvent;
sl@0: 			// test if too quick!
sl@0: 			if ((aMillisec < KDelayDurationForQEmpty) &&(!gSemiAutomated)) // use 200ms - clocked at 17ms
sl@0: 				{
sl@0: 				iCaseStep = ERegisterForEvents;
sl@0: 				iDequeAttempts++;
sl@0: 				SelfComplete();
sl@0: 				break;
sl@0: 				}
sl@0: 			}// drop through to next step
sl@0: 		case EGetAndCancelEvent: //4.
sl@0: 			OtgEventString(iOTGEvent, aDescription);
sl@0: 			test.Printf(_L("Received event %d '%S' status(%d)"), iOTGEvent, &aDescription, completionCode);
sl@0: 			if (RUsbOtgDriver::EEventAPlugRemoved == iOTGEvent)
sl@0: 				{
sl@0: 				otgQueueOtgEventRequest( iOTGEvent, iStatus);
sl@0: 				// cancel it and then go into a loop
sl@0: 				otgCancelOtgEventRequest();
sl@0: 				// swallow the cancelation now
sl@0: 				User::WaitForRequest(iStatus);
sl@0: 
sl@0: 				iCaseStep = ECancelNotify;
sl@0: 				}
sl@0: 			else
sl@0: 				{			
sl@0: 				// wrong event in the Q already, keep at it
sl@0: 				iCaseStep = ERegisterForEvents;	
sl@0: 				iDequeAttempts++;
sl@0: 				}
sl@0: 			SelfComplete();
sl@0: 			break;
sl@0: 			
sl@0: 			// 5. prepare to go into a loop
sl@0: 		case ECancelNotify:  // insert 'A'
sl@0: 			iRepeats = 3;	// #times to insert+remove
sl@0: 			iExpectedEvents = 0;
sl@0: 			iEventsInQueue = 0;
sl@0: 			iCaseStep = EInsertA;
sl@0: 			SelfComplete();
sl@0: 			break;
sl@0: 			
sl@0: 			// 6
sl@0: 		case EInsertA: // insert 'A' plug
sl@0: 			iWDTimer->Cancel();
sl@0: 			iConsole->ReadCancel();
sl@0: 			test.Printf(KInsertAConnectorPrompt);
sl@0: 			iCaseStep = ERemoveA;
sl@0: 			test.Printf(KPressAnyKeyToContinue);
sl@0: 			
sl@0: 			RequestCharacter();
sl@0: 			iWDTimer->IssueRequest(KDelayDurationForUserActivityMS, this, &CancelKB);			
sl@0: 
sl@0: 			iExpectedEvents++;
sl@0: 			break;
sl@0: 			
sl@0: 			// 7. remove 'A' plug
sl@0: 		case ERemoveA:
sl@0: 			iWDTimer->Cancel();
sl@0: 			iConsole->ReadCancel();
sl@0: 			test.Printf(KRemoveAConnectorPrompt);
sl@0: 			if (iRepeats-- >0)
sl@0: 				{
sl@0: 				// Do it again please
sl@0: 				iCaseStep = EInsertA;
sl@0: 				}
sl@0: 			else
sl@0: 				{ // got enough events in Q, let's count them up
sl@0: 				iCaseStep = ETallyEvents;
sl@0: 				}
sl@0: 			test.Printf(KPressAnyKeyToContinue);
sl@0: 
sl@0: 			RequestCharacter();			
sl@0: 			iWDTimer->IssueRequest(KDelayDurationForUserActivityMS, this, &CancelKB);			
sl@0: 			iExpectedEvents++;
sl@0: 			break;
sl@0: 			
sl@0: 			// 8.
sl@0: 		case ETallyEvents:
sl@0: 			// Getting here tests if the object does not get double-signalled.
sl@0: 			// a stray signal anywhere would Panic the scheduler when we self complete
sl@0: 			iCaseStep = ETallyNewEvent;
sl@0: 			iStatus = KRequestPending;
sl@0: 			otgQueueOtgEventRequest( iOTGEvent, iStatus);
sl@0: 			SetActive();
sl@0: 			break;
sl@0: 			// 9.
sl@0: 		case ETallyNewEvent:
sl@0: 			iEventsInQueue++;	// got one, add it
sl@0: 			if (iExpectedEvents == iEventsInQueue)
sl@0: 				{
sl@0: 				iCaseStep = EUnloadLdd;	
sl@0: 				}
sl@0: 			else
sl@0: 				{
sl@0: 				iCaseStep = ETallyEvents;
sl@0: 				}
sl@0: 			SelfComplete();
sl@0: 			break;
sl@0: 			
sl@0: 		case EUnloadLdd:
sl@0: 		case ELastStep:
sl@0: 			if (EFalse == StepUnloadLDD())
sl@0: 				return TestFailed(KErrAbort,_L("unload Ldd failure"));	
sl@0: 			
sl@0: 			return TestPassed();
sl@0: 
sl@0: 		default:
sl@0: 			test.Printf(_L("<Error> unknown test step"));
sl@0: 			Cancel();
sl@0: 			return (TestFailed(KErrCorrupt, _L("<Error> unknown test step")));
sl@0: 
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: