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: // @file PBASE-T_USBDI-0473.cpp sl@0: // @internalComponent sl@0: // sl@0: // sl@0: sl@0: #include "PBASE-T_USBDI-0473.h" sl@0: #include sl@0: #include "testdebug.h" sl@0: #include "modelleddevices.h" sl@0: #include "TestPolicy.h" sl@0: sl@0: namespace NUnitTesting_USBDI sl@0: { sl@0: sl@0: _LIT(KTestCaseId,"PBASE-T_USBDI-0473"); sl@0: const TFunctorTestCase CUT_PBASE_T_USBDI_0473::iFunctor(KTestCaseId); sl@0: sl@0: CUT_PBASE_T_USBDI_0473* CUT_PBASE_T_USBDI_0473::NewL(TBool aHostRole) sl@0: { sl@0: CUT_PBASE_T_USBDI_0473* self = new (ELeave) CUT_PBASE_T_USBDI_0473(aHostRole); 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: CUT_PBASE_T_USBDI_0473::CUT_PBASE_T_USBDI_0473(TBool aHostRole) sl@0: : CBaseTestCase(KTestCaseId,aHostRole), sl@0: iSuspendedI0(EFalse), sl@0: iSuspendedI1(EFalse), sl@0: iDeviceNotificationPending(ETrue) sl@0: { sl@0: } sl@0: sl@0: sl@0: void CUT_PBASE_T_USBDI_0473::ConstructL() sl@0: { sl@0: iTestDevice = new RUsbDeviceA(this); sl@0: BaseConstructL(); sl@0: } sl@0: sl@0: sl@0: CUT_PBASE_T_USBDI_0473::~CUT_PBASE_T_USBDI_0473() sl@0: { sl@0: LOG_FUNC sl@0: sl@0: // Cancel any async operations sl@0: sl@0: Cancel(); // Cancel host timer sl@0: sl@0: // Destroy the watchers sl@0: // they still use opened interfaces to cancel the suspend if active sl@0: delete iInterface1Watcher; sl@0: delete iInterface0Watcher; sl@0: sl@0: // Close the interfaces sl@0: iUsbInterface1.Close(); sl@0: iUsbInterface0.Close(); sl@0: sl@0: delete iControlEp0; sl@0: delete iActorFDF; sl@0: if(!IsHost() && iTestDevice) sl@0: { sl@0: iTestDevice->Close(); sl@0: } sl@0: delete iTestDevice; sl@0: } sl@0: sl@0: sl@0: void CUT_PBASE_T_USBDI_0473::ExecuteHostTestCaseL() sl@0: { sl@0: LOG_FUNC sl@0: iCaseStep = EStepSuspend; sl@0: iActorFDF = CActorFDF::NewL(*this); sl@0: iControlEp0 = new (ELeave) CEp0Transfer(iUsbInterface0); sl@0: iInterface0Watcher = new (ELeave) CInterfaceWatcher(iUsbInterface0,TCallBack(CUT_PBASE_T_USBDI_0473::Interface0ResumedL,this)); sl@0: iInterface1Watcher = new (ELeave) CInterfaceWatcher(iUsbInterface1,TCallBack(CUT_PBASE_T_USBDI_0473::Interface1ResumedL,this)); sl@0: sl@0: // Monitor for device connections sl@0: iActorFDF->Monitor(); sl@0: sl@0: // Start the connection timeout sl@0: TimeoutIn(30); sl@0: } sl@0: sl@0: void CUT_PBASE_T_USBDI_0473::ExecuteDeviceTestCaseL() sl@0: { sl@0: LOG_FUNC sl@0: sl@0: // Construct the device for the test case sl@0: iTestDevice->OpenL(TestCaseId()); sl@0: iTestDevice->SubscribeToReports(iStatus); sl@0: SetActive(); sl@0: sl@0: // Connect the test device sl@0: iTestDevice->SoftwareConnect(); sl@0: } sl@0: sl@0: sl@0: void CUT_PBASE_T_USBDI_0473::HostDoCancel() sl@0: { sl@0: LOG_FUNC sl@0: sl@0: // Cancel the timeout timer sl@0: CancelTimeout(); sl@0: } sl@0: sl@0: sl@0: void CUT_PBASE_T_USBDI_0473::DeviceDoCancel() sl@0: { sl@0: LOG_FUNC sl@0: sl@0: // Cancel the device sl@0: iTestDevice->CancelSubscriptionToReports(); sl@0: } sl@0: sl@0: void CUT_PBASE_T_USBDI_0473::DeviceInsertedL(TUint aDeviceHandle) sl@0: { sl@0: LOG_FUNC sl@0: sl@0: Cancel(); // Cancel the timer sl@0: TInt err(KErrNone); sl@0: iDeviceHandle = aDeviceHandle; sl@0: iActorFDF->Monitor(); sl@0: sl@0: // Validate that device is as expected sl@0: CUsbTestDevice& testDevice = iActorFDF->DeviceL(aDeviceHandle); sl@0: if(testDevice.SerialNumber().Compare(TestCaseId()) != 0) sl@0: { sl@0: // Incorrect device for this test case sl@0: sl@0: RDebug::Printf(" Incorrect device serial number (%S) connected for this test case (%S)", sl@0: KErrNotFound,&testDevice.SerialNumber(),&TestCaseId()); sl@0: sl@0: // Start the connection timeout again sl@0: TimeoutIn(30); sl@0: return; sl@0: } sl@0: // Check tree now sl@0: CHECK(CheckTreeAfterDeviceInsertion(testDevice, _L("RDeviceA")) == KErrNone); sl@0: sl@0: // Perform the correct test step sl@0: switch(iCaseStep) sl@0: { sl@0: case EStepSuspend: sl@0: { sl@0: TUint32 token1(0); sl@0: TUint32 token2(0); sl@0: sl@0: RDebug::Printf("Obtaining token for interface 0"); sl@0: err = testDevice.Device().GetTokenForInterface(0,token1); sl@0: if(err != KErrNone) sl@0: { sl@0: RDebug::Printf(" Token for interface 0 could not be retrieved",err); sl@0: return TestFailed(err); sl@0: } sl@0: RDebug::Printf("Token 1 (%d) retrieved",token1); sl@0: RDebug::Printf("Opening interface 0"); sl@0: err = iUsbInterface0.Open(token1); // Alternate interface setting 0 sl@0: if(err != KErrNone) sl@0: { sl@0: RDebug::Printf(" Interface 0 could not be opened",err); sl@0: return TestFailed(err); sl@0: } sl@0: RDebug::Printf("Interface 0 opened"); sl@0: sl@0: sl@0: RDebug::Printf("Obtaining token for interface 1"); sl@0: err = testDevice.Device().GetTokenForInterface(1,token2); sl@0: if(err != KErrNone) sl@0: { sl@0: RDebug::Printf(" Token for interface 1 could not be retrieved",err); sl@0: return TestFailed(err); sl@0: } sl@0: RDebug::Printf("Opening interface 1"); sl@0: err = iUsbInterface1.Open(token2); // Alternate interface setting 0 sl@0: if(err != KErrNone) sl@0: { sl@0: RDebug::Printf(" Interface 1 could not be opened",err); sl@0: return TestFailed(err); sl@0: } sl@0: RDebug::Printf("Interface 1 opened"); sl@0: sl@0: // close it sl@0: iUsbInterface1.Close(); sl@0: RDebug::Printf("Interface 1 closed"); sl@0: sl@0: //re-open now sl@0: err = iUsbInterface1.Open(token2); // Alternate interface setting 0 sl@0: if(err != KErrNone) sl@0: { sl@0: RDebug::Printf(" Interface 1 could not be re-opened",err); sl@0: return TestFailed(err); sl@0: } sl@0: RDebug::Printf("Interface 1 re-opened"); sl@0: sl@0: sl@0: // Suspend interface 0 sl@0: RDebug::Printf("Suspending interface 0"); sl@0: iInterface0Watcher->SuspendAndWatch(); sl@0: iSuspendedI0 = ETrue; sl@0: sl@0: // Suspend interface 1 sl@0: RDebug::Printf("Suspending interface 1"); sl@0: iInterface1Watcher->SuspendAndWatch(); sl@0: iSuspendedI1 = ETrue; sl@0: sl@0: iCaseStep = EValidateSuspendingInterfaces; sl@0: TimeoutIn(10); // Give 10 seconds for device to suspend sl@0: } sl@0: break; sl@0: sl@0: default: sl@0: TestFailed(KErrCorrupt); sl@0: break; sl@0: } sl@0: } sl@0: sl@0: sl@0: TInt CUT_PBASE_T_USBDI_0473::Interface0ResumedL(TAny* aPtr) sl@0: { sl@0: LOG_CFUNC sl@0: RDebug::Printf("Interface 0 resumed"); sl@0: CUT_PBASE_T_USBDI_0473* self = reinterpret_cast(aPtr); sl@0: RDebug::Printf("watcher 0 iStatus=%d",self->iInterface0Watcher->CompletionCode()); sl@0: self->iSuspendedI0 = EFalse; sl@0: return self->CheckForAllResumedNotificationsAndContinueFSM(); sl@0: } sl@0: sl@0: sl@0: TInt CUT_PBASE_T_USBDI_0473::Interface1ResumedL(TAny* aPtr) sl@0: { sl@0: LOG_CFUNC sl@0: RDebug::Printf("Interface 1 resumed"); sl@0: CUT_PBASE_T_USBDI_0473* self = reinterpret_cast(aPtr); sl@0: RDebug::Printf("watcher 1 iStatus=%d",self->iInterface1Watcher->CompletionCode()); sl@0: self->iSuspendedI1 = EFalse; sl@0: return self->CheckForAllResumedNotificationsAndContinueFSM(); sl@0: } sl@0: sl@0: sl@0: void CUT_PBASE_T_USBDI_0473::DeviceRemovedL(TUint aDeviceHandle) sl@0: { sl@0: LOG_FUNC sl@0: sl@0: // The test device should not be removed until the test case has passed sl@0: // so this test case has not completed, and state this event as an error sl@0: sl@0: TestFailed(KErrDisconnected); sl@0: } sl@0: sl@0: sl@0: void CUT_PBASE_T_USBDI_0473::BusErrorL(TInt aError) sl@0: { sl@0: LOG_FUNC sl@0: sl@0: // This test case handles no failiures on the bus sl@0: sl@0: TestFailed(aError); sl@0: } sl@0: sl@0: TInt CUT_PBASE_T_USBDI_0473::CheckForAllResumedNotificationsAndContinueFSM() sl@0: { sl@0: LOG_FUNC sl@0: TBool readyToContinueFSM= ETrue; sl@0: if( iInterface0Watcher->IsActive() sl@0: || iInterface0Watcher->iStatus == KRequestPending) sl@0: { sl@0: RDebug::Printf("Interface 0 watcher still pending"); sl@0: readyToContinueFSM= EFalse; sl@0: } sl@0: sl@0: if( iInterface1Watcher->IsActive() sl@0: || iInterface1Watcher->iStatus == KRequestPending) sl@0: { sl@0: RDebug::Printf("Interface 1 watcher still pending"); sl@0: readyToContinueFSM= EFalse; sl@0: } sl@0: sl@0: if( iDeviceNotificationPending) sl@0: { sl@0: readyToContinueFSM= EFalse; sl@0: } sl@0: sl@0: if( readyToContinueFSM) sl@0: { sl@0: return ContinueFSMAfterAllResumedNotifications(); sl@0: } sl@0: else sl@0: { sl@0: return KErrNone; sl@0: } sl@0: } sl@0: sl@0: TInt CUT_PBASE_T_USBDI_0473::ContinueFSMAfterAllResumedNotifications() sl@0: { sl@0: LOG_FUNC sl@0: iDeviceNotificationPending= ETrue; sl@0: if(iSuspendedI0) sl@0: { sl@0: RDebug::Printf(" Interface 0 still suspended",KErrCompletion); sl@0: TestFailed(KErrCompletion); sl@0: return KErrCompletion; sl@0: } sl@0: sl@0: if(iSuspendedI1) sl@0: { sl@0: RDebug::Printf(" Interface 1 still suspended",KErrCompletion); sl@0: TestFailed(KErrCompletion); sl@0: return KErrCompletion; sl@0: } sl@0: sl@0: switch(iCaseStep) sl@0: { sl@0: case EValidateResumptionAfterInterfaceSuspension: sl@0: { sl@0: // Device is resumed, send request to client: Remote wake up in 6 secs sl@0: TInt err= iUsbInterface1.PermitRemoteWakeup(ETrue); sl@0: sl@0: if(err != KErrNone) sl@0: { sl@0: RDebug::Printf(" Unable to permit remote device wakeup",err); sl@0: iCaseStep = EFailed; sl@0: TTestCaseFailed request(err,_L8("Unable to permit remote device wakeup")); sl@0: iControlEp0->SendRequest(request,this); sl@0: } sl@0: else sl@0: { sl@0: RDebug::Printf("Device is resumed, send request to client: Remote wake up in 6 secs"); sl@0: sl@0: TRemoteWakeupRequest request(6); sl@0: iControlEp0->SendRequest(request,this); sl@0: iCaseStep = ESuspendForRemoteWakeup; sl@0: } sl@0: } sl@0: break; sl@0: sl@0: case EValidateResumptionAfterWakeup: sl@0: { sl@0: if(iStoredNewState == RUsbDevice::EDeviceActive) sl@0: { sl@0: // Now suspend the device again after resumption from remote wakeup sl@0: sl@0: RDebug::Printf("Suspending interface 0"); sl@0: iInterface0Watcher->SuspendAndWatch(); sl@0: iSuspendedI0 = ETrue; sl@0: sl@0: RDebug::Printf("Suspending interface 1"); sl@0: iInterface1Watcher->SuspendAndWatch(); sl@0: iSuspendedI1 = ETrue; sl@0: sl@0: iCaseStep = EValidateSuspendAfterWakeup; sl@0: } sl@0: else sl@0: { sl@0: RDebug::Printf(" Device is still suspended",KErrCompletion); sl@0: TestFailed(KErrCompletion); sl@0: return KErrCompletion; sl@0: } sl@0: } sl@0: break; sl@0: sl@0: default: sl@0: RDebug::Printf("CUT_PBASE_T_USBDI_0473::ContinueFSMAfterAllResumedNotifications: Invalid state %d", iCaseStep); sl@0: TestFailed(KErrCompletion); sl@0: return KErrCompletion; sl@0: } sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: void CUT_PBASE_T_USBDI_0473::DeviceStateChangeL(RUsbDevice::TDeviceState aPreviousState,RUsbDevice::TDeviceState aNewState,TInt aCompletionCode) sl@0: { sl@0: LOG_FUNC sl@0: Cancel(); sl@0: sl@0: RDebug::Printf("Device State change from %d to %d err=%d",aPreviousState,aNewState,aCompletionCode); sl@0: sl@0: switch(iCaseStep) sl@0: { sl@0: sl@0: // Validate that the device was suspended by individual interface suspension sl@0: sl@0: case EValidateSuspendingInterfaces: sl@0: { sl@0: if(aNewState == RUsbDevice::EDeviceSuspended) sl@0: { sl@0: // Device state is suspended now resume it by resuming one of the interfaces sl@0: sl@0: RDebug::Printf("Device is suspended now resume device by resuming one of the interfaces"); sl@0: iUsbInterface0.CancelPermitSuspend(); sl@0: iCaseStep = EValidateResumptionAfterInterfaceSuspension; sl@0: } sl@0: else sl@0: { sl@0: RDebug::Printf(" State was not suspended",KErrCompletion); sl@0: sl@0: // Since the device is not suspended, send test case failed to the device sl@0: sl@0: iCaseStep = EFailed; sl@0: TTestCaseFailed request(KErrCompletion,_L8("The device was not in the expected suspend state")); sl@0: iControlEp0->SendRequest(request,this); sl@0: } sl@0: } sl@0: break; sl@0: sl@0: // Validate that device is now active after resuming one of the interfaces sl@0: sl@0: case EValidateResumptionAfterInterfaceSuspension: sl@0: { sl@0: iDeviceNotificationPending= EFalse; sl@0: sl@0: if(aNewState == RUsbDevice::EDeviceActive) sl@0: { sl@0: CheckForAllResumedNotificationsAndContinueFSM(); sl@0: } sl@0: else sl@0: { sl@0: RDebug::Printf(" Device is still suspended",KErrCompletion); sl@0: return TestFailed(KErrCompletion); sl@0: } sl@0: } sl@0: break; sl@0: sl@0: // Validate that the device is now suspended for the device to remote-wakeup sl@0: case EValidateSuspendForRemoteWakeup: sl@0: { sl@0: if(aNewState == RUsbDevice::EDeviceSuspended) sl@0: { sl@0: // Now awaiting a remote wake up state change notification sl@0: sl@0: RDebug::Printf("Now awaiting a remote wake up state change notification"); sl@0: sl@0: CancelTimeout(); sl@0: iTimer.After(iStatus,10000000); // Give 10 seconds for device to signal remote wake-up sl@0: iCaseStep = EValidateResumptionAfterWakeup; sl@0: SetActive(); sl@0: } sl@0: else sl@0: { sl@0: RDebug::Printf(" State was not suspended",KErrCompletion); sl@0: sl@0: // Since the device is not suspended, send test case failed to the device sl@0: sl@0: iCaseStep = EFailed; sl@0: TTestCaseFailed request(KErrCompletion,_L8("State was not suspended")); sl@0: iControlEp0->SendRequest(request,this); sl@0: } sl@0: } sl@0: break; sl@0: sl@0: // This step should never be reached as ep0 complete traps this step, but if it does test fails. sl@0: case ESuspendForRemoteWakeup: sl@0: { sl@0: RDebug::Printf("Resumed before suspended"); sl@0: iCaseStep = EFailed; sl@0: TTestCaseFailed request(KErrCompletion,_L8("State was not suspended")); sl@0: iControlEp0->SendRequest(request,this); sl@0: break; sl@0: } sl@0: sl@0: // Validate that the device is now active from a remote wakeup sl@0: case EValidateResumptionAfterWakeup: sl@0: { sl@0: iDeviceNotificationPending= EFalse; sl@0: iStoredNewState= aNewState; sl@0: CheckForAllResumedNotificationsAndContinueFSM(); sl@0: } sl@0: break; sl@0: sl@0: // Validate that the device can be suspended after a remote wakeup sl@0: sl@0: case EValidateSuspendAfterWakeup: sl@0: { sl@0: // Successfully suspended after a remote wake up event sl@0: if(aNewState == RUsbDevice::EDeviceSuspended) sl@0: { sl@0: // Device is now suspended, now activate the device again to send test case sl@0: // completed request to device sl@0: sl@0: RDebug::Printf("Device is now suspended, now activate the device again to send test case completed request to device"); sl@0: sl@0: CUsbTestDevice& testDevice = iActorFDF->DeviceL(iDeviceHandle); sl@0: sl@0: RDebug::Printf("Resuming at device level"); sl@0: TInt err(testDevice.Device().Resume()); sl@0: if(err != KErrNone) sl@0: { sl@0: RDebug::Printf(" Unable to suspend the device",err); sl@0: iCaseStep = EFailed; sl@0: TTestCaseFailed request(err,_L8("Unable to suspend the device")); sl@0: iControlEp0->SendRequest(request,this); sl@0: } sl@0: sl@0: iCaseStep = EPassed; sl@0: } sl@0: else sl@0: { sl@0: RDebug::Printf(" State was not suspended",KErrCompletion); sl@0: sl@0: // Since the device is not suspended, send test case failed to the device sl@0: sl@0: iCaseStep = EFailed; sl@0: TTestCaseFailed request(KErrCompletion,_L8("State was not suspended")); sl@0: iControlEp0->SendRequest(request,this); sl@0: } sl@0: } sl@0: break; sl@0: sl@0: // Validate that the device is now active again sl@0: sl@0: case EPassed: sl@0: { sl@0: if(aNewState == RUsbDevice::EDeviceActive) sl@0: { sl@0: RDebug::Printf("Device is active again, test case passed"); sl@0: TTestCasePassed request; sl@0: iControlEp0->SendRequest(request,this); sl@0: } sl@0: else sl@0: { sl@0: RDebug::Printf(" Device is still suspended",KErrCompletion); sl@0: return TestFailed(KErrCompletion); sl@0: } sl@0: } sl@0: break; sl@0: sl@0: default: sl@0: break; sl@0: } sl@0: } sl@0: sl@0: sl@0: void CUT_PBASE_T_USBDI_0473::Ep0TransferCompleteL(TInt aCompletionCode) sl@0: { sl@0: LOG_FUNC sl@0: RDebug::Printf("Ep0TransferCompleteL with aCompletionCode = %d",aCompletionCode); sl@0: switch(iCaseStep) sl@0: { sl@0: case ESuspendForRemoteWakeup: sl@0: { sl@0: // Suspend device again so a remote wakeup can be achieved sl@0: RDebug::Printf("Suspend device again so a remote wakeup can be achieved"); sl@0: sl@0: // Suspend interface 0 sl@0: RDebug::Printf("Suspending interface 0"); sl@0: iInterface0Watcher->SuspendAndWatch(); sl@0: iSuspendedI0 = ETrue; sl@0: sl@0: // Suspend interface 1 sl@0: RDebug::Printf("Suspending interface 1"); sl@0: iInterface1Watcher->SuspendAndWatch(); sl@0: iSuspendedI1 = ETrue; sl@0: sl@0: iCaseStep = EValidateSuspendForRemoteWakeup; sl@0: TimeoutIn(10); // Give 10 seconds for device to suspend sl@0: } sl@0: break; sl@0: sl@0: // Fail the test case sl@0: sl@0: default: sl@0: case EFailed: sl@0: TestFailed(KErrCompletion); sl@0: break; sl@0: sl@0: // Pass the test case sl@0: sl@0: case EPassed: sl@0: TestPassed(); sl@0: break; sl@0: } sl@0: } sl@0: sl@0: sl@0: void CUT_PBASE_T_USBDI_0473::HostRunL() sl@0: { sl@0: LOG_FUNC sl@0: sl@0: // Obtain the completion code sl@0: TInt completionCode(iStatus.Int()); sl@0: sl@0: if(completionCode == KErrNone) sl@0: { sl@0: // Action timeout sl@0: RDebug::Printf(" Action timeout"); sl@0: TestFailed(KErrTimedOut); sl@0: } sl@0: else sl@0: { sl@0: RDebug::Printf(" Timeout timer could not complete",completionCode); sl@0: TestFailed(completionCode); sl@0: } sl@0: } sl@0: sl@0: sl@0: void CUT_PBASE_T_USBDI_0473::DeviceRunL() sl@0: { sl@0: LOG_FUNC sl@0: sl@0: // Disconnect the device sl@0: sl@0: iTestDevice->SoftwareDisconnect(); sl@0: sl@0: // Complete the test case request sl@0: sl@0: TestPolicy().SignalTestComplete(iStatus.Int()); sl@0: } sl@0: sl@0: sl@0: }