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: // testcaseb2broot.cpp sl@0: // @internalComponent sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: #include // unicode builds sl@0: #include sl@0: #include sl@0: #include sl@0: #include // RTest header sl@0: #include sl@0: #include sl@0: #include sl@0: #include // OTGDI header sl@0: #include // USBCC header sl@0: #include "testcaseroot.h" sl@0: #include "b2bwatchers.h" sl@0: sl@0: sl@0: sl@0: void CNotifyWatcherBase::RunL() sl@0: { sl@0: DisplayEvent(); sl@0: iHandler.HandleEvent(iWatchType, GetEventValue()); // report the event upwards sl@0: sl@0: IssueAgain(); sl@0: SetActive(); sl@0: } sl@0: sl@0: sl@0: CNotifyCollector::CNotifyCollector(TRequestStatus &aStatus) : iStatusStep(aStatus) sl@0: { sl@0: LOG_FUNC sl@0: TTimeIntervalDays oneday(1); sl@0: iTimeStarted.HomeTime(); sl@0: iTimeStarted += (oneday); // force all durations to produce a negative (invalid) value sl@0: } sl@0: sl@0: sl@0: /*************************************************************** sl@0: * ~CNotifyCollector sl@0: */ sl@0: CNotifyCollector::~CNotifyCollector() sl@0: { sl@0: LOG_FUNC sl@0: sl@0: ClearAllEvents(); // free event arrays sl@0: sl@0: iNotifyObjects.Close(); sl@0: iFailureEvents.Close(); sl@0: iRequiredEvents.Close(); sl@0: iReceivedEvents.Close(); sl@0: } sl@0: sl@0: sl@0: /* The test-case calls this to clear the events stored. sl@0: * Both the expected and already recieved events get cleared, this method sl@0: * is typically called at the start of each test-step sl@0: */ sl@0: void CNotifyCollector::ClearAllEvents(TBool aClearRecieved/*=ETrue*/, TBool aClearRequired /*=ETrue*/) sl@0: { sl@0: //LOG_FUNC sl@0: if (aClearRequired) sl@0: { sl@0: iRequiredEvents.Reset(); sl@0: iFailureEvents.Reset(); sl@0: } sl@0: if (aClearRecieved) sl@0: { sl@0: iReceivedEvents.Reset(); sl@0: } sl@0: } sl@0: sl@0: sl@0: /* Creates and starts all 4 observers sl@0: * Note: The Watchdog does not get started, because it needs an interval sl@0: */ sl@0: void CNotifyCollector::CreateObserversL(COtgRoot &aOtgDriver) sl@0: { sl@0: LOG_FUNC sl@0: TInt watchType; sl@0: ASSERT(aOtgDriver.LddLoaded()); sl@0: sl@0: for (watchType=EWatcherTimeouts; watchType < EWatcherInvalid; watchType++) sl@0: { sl@0: CNotifyWatcherBase *pWatcher=0; sl@0: switch ((TWatcherNotifyType )watchType) sl@0: { sl@0: case EWatcherTimeouts: sl@0: pWatcher = COtgWatchdogWatcher::NewL(*this, EWatcherTimeouts, aOtgDriver); sl@0: break; sl@0: case EWatcherState: sl@0: pWatcher = COtgStateWatcher::NewL(*this , EWatcherState, aOtgDriver); sl@0: break; sl@0: case EWatcherEvent: sl@0: pWatcher = COtgEventWatcher::NewL(*this, EWatcherEvent, aOtgDriver); sl@0: break; sl@0: case EWatcherMessage: sl@0: pWatcher = COtgMessageWatcher::NewL(*this, EWatcherMessage, aOtgDriver); sl@0: break; sl@0: case EWatcherPeripheralState: sl@0: pWatcher = CPeripheralStateWatcher::NewL(*this, EWatcherPeripheralState, aOtgDriver); sl@0: break; sl@0: case EWatcherAConnectionIdle: sl@0: pWatcher = CAConnectionIdleWatcher::NewL(*this, EWatcherAConnectionIdle, aOtgDriver); sl@0: break; sl@0: sl@0: } sl@0: // the TRequest object is added to scheduler in it's own constructor sl@0: sl@0: // add it to our list so we can kill them after the test. sl@0: iNotifyObjects.Append(pWatcher); sl@0: //LOG_VERBOSE3(_L("Added watcher type %d, TRequest= %08X.\n"), iType, (TInt)(&pWatcher->iStatus)); sl@0: sl@0: // start all watchers, except for the watchdog sl@0: if (watchType != EWatcherTimeouts) sl@0: { sl@0: pWatcher->StartWatching(-1); sl@0: } sl@0: } sl@0: test.Printf(_L("\n")); sl@0: } sl@0: sl@0: sl@0: /* NOTE: OTG must still be loaded or else we cannot cancel the outstanding event watches here! sl@0: */ sl@0: void CNotifyCollector::DestroyObservers() sl@0: { sl@0: LOG_FUNC sl@0: sl@0: // Free the Watchers sl@0: for (TInt idx=0; idx < iNotifyObjects.Count(); idx++) sl@0: { sl@0: LOG_VERBOSE2(_L(".. %d .."), idx); sl@0: delete iNotifyObjects[idx]; // they will call their own Cancel() methods sl@0: } sl@0: iNotifyObjects.Close(); sl@0: } sl@0: sl@0: sl@0: void CNotifyCollector::AddRequiredNotification(TWatcherNotifyType aType, TInt aValue) sl@0: { sl@0: AddRequiredOrFailureNotification(aType, aValue, EFalse); sl@0: } sl@0: sl@0: void CNotifyCollector:: AddFailureNotification(const TWatcherNotifyType aType, TInt aValue) sl@0: { sl@0: AddRequiredOrFailureNotification(aType, aValue, ETrue); sl@0: } sl@0: sl@0: /* Checks that a watcher for the event exists, and then adds it to a list of events required for a PASS condition sl@0: * The timout event does not get added to this list. sl@0: * If the parameter is a time, the timer gets started sl@0: * If aEventMeansFailure is set True, then the reception of the event will cause the current test step to fail sl@0: */ sl@0: void CNotifyCollector::AddRequiredOrFailureNotification(TWatcherNotifyType aType, TInt aValue, TBool aEventMeansFailure) sl@0: { sl@0: CNotifyWatcherBase *pWatcher=0; sl@0: TInt index=0; sl@0: TBuf aDescription; sl@0: sl@0: // print a usefull debug message sl@0: switch (aType) sl@0: { sl@0: case EWatcherTimeouts: sl@0: break; sl@0: case EWatcherState: sl@0: COtgRoot::OtgStateString(static_cast(aValue), aDescription); sl@0: LOG_VERBOSE3(_L("AddRequiredNotification() State %d '%S' wanted\n"), aValue, &aDescription); sl@0: break; sl@0: case EWatcherEvent: sl@0: COtgRoot::OtgEventString(static_cast(aValue), aDescription); sl@0: LOG_VERBOSE3(_L("AddRequiredNotification() Event %d '%S' wanted\n"), aValue, &aDescription); sl@0: break; sl@0: case EWatcherMessage: sl@0: COtgRoot::OtgMessageString(static_cast(aValue), aDescription); sl@0: LOG_VERBOSE3(_L("AddRequiredNotification() Message %d '%S' wanted\n"), aValue, &aDescription); sl@0: break; sl@0: case EWatcherPeripheralState: sl@0: COtgRoot::PeripheralStateString(static_cast(aValue), aDescription); sl@0: LOG_VERBOSE3(_L("AddRequiredNotification() Peripheral State %d '%S' wanted\n"), aValue, &aDescription); sl@0: break; sl@0: case EWatcherAConnectionIdle: sl@0: COtgRoot::AConnectionIdleString(static_cast(aValue), aDescription); sl@0: LOG_VERBOSE3(_L("AddRequiredNotification() AConnectionIdle %d '%S' wanted\n"), aValue, &aDescription); sl@0: break; sl@0: sl@0: } sl@0: sl@0: // Find the watcher if possible sl@0: while (index < iNotifyObjects.Count()) sl@0: { sl@0: sl@0: TEST_ASSERTION(iNotifyObjects[index]!=NULL, _L("iNotifyObjects element gone!")); sl@0: sl@0: if (iNotifyObjects[index]->GetType() == aType) sl@0: { sl@0: pWatcher = iNotifyObjects[index]; sl@0: break; sl@0: } sl@0: index++; sl@0: } sl@0: sl@0: TEST_ASSERTION(pWatcher!=NULL, _L("pWatcher=0!")); sl@0: if (aType == EWatcherTimeouts) sl@0: { // other watchers are already running, but we start the timer now sl@0: pWatcher->StartWatching(aValue); sl@0: } sl@0: else sl@0: { // timeouts are not added to the Q sl@0: TOtgObservedEvent evt(aType, aValue); sl@0: if(aEventMeansFailure) sl@0: { sl@0: iFailureEvents.Append(evt); sl@0: } sl@0: else sl@0: { sl@0: iRequiredEvents.Append(evt); sl@0: } sl@0: } sl@0: // flag as pending sl@0: iStatusStep = KRequestPending; sl@0: iTimeStarted.HomeTime(); sl@0: } sl@0: sl@0: sl@0: /* Return the number of milliseconds since the last call to AddRequiredNotification() sl@0: */ sl@0: TInt CNotifyCollector::DurationElapsed() sl@0: { sl@0: TTime TimeEnd; sl@0: TInt Millisec; sl@0: sl@0: TimeEnd.HomeTime(); sl@0: TTimeIntervalMicroSeconds ivlMicro(TimeEnd.MicroSecondsFrom(iTimeStarted)); sl@0: Millisec = (TInt)(ivlMicro.Int64())/1000; // USB times are in uSec, but in ms for the user layer sl@0: sl@0: if (Millisec < 0) sl@0: Millisec = -1; // TRUE for when the Notifiers are not yet being used. sl@0: return(Millisec); sl@0: } sl@0: sl@0: sl@0: /* Search for an event in the received Q sl@0: * @return :TRUE if the specified event has been received sl@0: */ sl@0: TBool CNotifyCollector::EventReceivedAlready(const TOtgObservedEvent& aEvent) sl@0: { sl@0: for (TInt idx=0; idx < iReceivedEvents.Count(); idx++) sl@0: if (iReceivedEvents[idx] == aEvent) sl@0: return(ETrue); sl@0: return(EFalse); sl@0: } sl@0: sl@0: /* Search for an event in the failure event queue sl@0: * @return :TRUE if the specified event does denote a failure sl@0: */ sl@0: TBool CNotifyCollector::IsFailureEvent(TOtgObservedEvent &aEvent) sl@0: { sl@0: for (TInt idx=0; idx < iFailureEvents.Count(); idx++) sl@0: if (iFailureEvents[idx] == aEvent) sl@0: return(ETrue); sl@0: return(EFalse); sl@0: } sl@0: sl@0: /* @return 0 if the watcher has not yet been created. (for instance early in the test) sl@0: */ sl@0: CNotifyWatcherBase* CNotifyCollector::GetWatcher(TWatcherNotifyType aType) sl@0: { sl@0: CNotifyWatcherBase *pWatcher=0; sl@0: // Find the watcher sl@0: TInt index=0; sl@0: sl@0: while (index < iNotifyObjects.Count()) sl@0: { sl@0: sl@0: TEST_ASSERTION(iNotifyObjects[index]!=NULL, _L("iNotifyObjects element gone!")); sl@0: sl@0: if (iNotifyObjects[index]->GetType() == aType) sl@0: { sl@0: pWatcher = iNotifyObjects[index]; sl@0: break; sl@0: } sl@0: index++; sl@0: } sl@0: sl@0: return(pWatcher); sl@0: } sl@0: sl@0: sl@0: /* Process the event. The OTG watchers are responsible for renewing themselves sl@0: * but the Timer event does not renew sl@0: */ sl@0: void CNotifyCollector::HandleEvent(TWatcherNotifyType aType, TInt aValue) sl@0: { sl@0: if (aType == EWatcherTimeouts) sl@0: { sl@0: test.Printf(_L("Step timed out..(%dms).\n\n"), GetWatcher(aType)->GetEventValue()); sl@0: CompleteStep(KTestCaseWatchdogTO); sl@0: return; sl@0: } sl@0: sl@0: TOtgObservedEvent evt(aType, aValue); sl@0: TInt start=0; sl@0: iReceivedEvents.Append(evt); // store incomming evt sl@0: sl@0: // Check to see whether the event denotes a failure for this event sl@0: if (IsFailureEvent(evt)) sl@0: { sl@0: test.Printf(_L("This event denotes failure for this test\n")); sl@0: CompleteStep(KTestCaseFailureEventReceived); sl@0: return; sl@0: } sl@0: sl@0: if (iRequiredEvents.Count()) sl@0: { sl@0: // itterate all required events, search for each one in the incomming events list sl@0: while (start< iRequiredEvents.Count()) sl@0: { sl@0: //LOG_VERBOSE3(_L("Search for=[%d,%d] :"), sl@0: // iRequiredEvents[start].GetType(), iRequiredEvents[start].GetValue()); sl@0: sl@0: if (!EventReceivedAlready(iRequiredEvents[start])) sl@0: return; // missing still, continue sl@0: start++; sl@0: } sl@0: // found all the required events sl@0: LOG_VERBOSE1(_L("Found all.\n")); sl@0: CompleteStep(KErrNone); sl@0: } sl@0: else sl@0: { sl@0: test.Printf(_L("Warning : No required events!\n")); sl@0: } sl@0: } sl@0: sl@0: // Complete the test step's TRequestStatus (checking it is currently KRequestPending sl@0: // to try and avoid multiple completions). sl@0: // sl@0: void CNotifyCollector::CompleteStep(TInt aCompletionCode) sl@0: { sl@0: if(iStatusStep.Int() != KRequestPending) sl@0: { sl@0: test.Printf(_L("Can't complete step - not KRequestPending!\n")); sl@0: } sl@0: else sl@0: { sl@0: TRequestStatus *StatusStepPtr = &iStatusStep; sl@0: User::RequestComplete(StatusStepPtr, aCompletionCode); sl@0: } sl@0: } sl@0: sl@0: /**************************************************************************** sl@0: * COtg Watchdog Watcher sl@0: */ sl@0: COtgWatchdogWatcher *COtgWatchdogWatcher::NewL(MOtgNotificationHandler &wdHandler, sl@0: const TWatcherNotifyType aWatchType, sl@0: COtgRoot &aOtgRoot) sl@0: { sl@0: LOG_FUNC sl@0: COtgWatchdogWatcher* self = new (ELeave) COtgWatchdogWatcher(wdHandler, aWatchType, aOtgRoot); 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: void COtgWatchdogWatcher::ConstructL() sl@0: { sl@0: LOG_FUNC sl@0: sl@0: iTimer.CreateLocal(); sl@0: iIntervalMs = -1; sl@0: } sl@0: sl@0: sl@0: void COtgWatchdogWatcher::StepExpired(TInt aInterval) sl@0: { sl@0: LOG_FUNC ; sl@0: iHandler.HandleEvent(EWatcherTimeouts, aInterval) ; sl@0: } sl@0: sl@0: sl@0: void COtgWatchdogWatcher::RunL() sl@0: { sl@0: //LOG_FUNC sl@0: StepExpired(iIntervalMs); sl@0: } sl@0: sl@0: sl@0: void COtgWatchdogWatcher::StartTimer(TInt aIntervalMs) sl@0: { sl@0: LOG_FUNC ; sl@0: sl@0: iIntervalMs = aIntervalMs; // save value for printing latter sl@0: if (IsActive()) //cancel the last timer we set, this is easier than cancelling it in each test-step sl@0: { sl@0: iTimer.Cancel(); sl@0: User::WaitForRequest(iStatus); // swallow it sl@0: iTimer.After(iStatus, aIntervalMs*1000); sl@0: } sl@0: else sl@0: { sl@0: iTimer.After(iStatus, aIntervalMs*1000); sl@0: SetActive(); sl@0: } sl@0: LOG_VERBOSE2(_L("wd Timer %dms\n"), aIntervalMs) sl@0: } sl@0: sl@0: sl@0: /**************************************************************************** sl@0: * OTG Event/State/Message Watchers sl@0: */ sl@0: COtgMessageWatcher* COtgMessageWatcher::NewL(MOtgNotificationHandler &wdHandler, sl@0: const TWatcherNotifyType aWatchType, sl@0: COtgRoot &aOtgRoot) sl@0: { sl@0: LOG_FUNC sl@0: COtgMessageWatcher* self = new (ELeave) COtgMessageWatcher(wdHandler, aWatchType, aOtgRoot); 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: void COtgMessageWatcher::DisplayEvent() sl@0: { sl@0: TBuf aDescription; sl@0: iOtgRoot.OtgMessageString(iMessage, aDescription); sl@0: test.Printf(_L("Received Message %d '%S'\n"), iMessage, &aDescription); sl@0: } sl@0: sl@0: sl@0: COtgStateWatcher* COtgStateWatcher::NewL(MOtgNotificationHandler &wdHandler, sl@0: const TWatcherNotifyType aWatchType, sl@0: COtgRoot &aOtgRoot) sl@0: { sl@0: LOG_FUNC sl@0: COtgStateWatcher* self = new (ELeave) COtgStateWatcher(wdHandler, aWatchType, aOtgRoot); 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: void COtgStateWatcher::DisplayEvent() sl@0: { sl@0: //LOG_FUNC sl@0: TBuf aDescription; sl@0: iOtgRoot.OtgStateString(iState, aDescription); sl@0: test.Printf(_L("Received State %d '%S'\n"), iState, &aDescription); sl@0: } sl@0: sl@0: sl@0: COtgEventWatcher* COtgEventWatcher::NewL(MOtgNotificationHandler &wdHandler, sl@0: const TWatcherNotifyType aWatchType, sl@0: COtgRoot &aOtgRoot) sl@0: { sl@0: //LOG_FUNC sl@0: COtgEventWatcher* self = new (ELeave) COtgEventWatcher(wdHandler, aWatchType, aOtgRoot); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: void COtgEventWatcher::DisplayEvent() sl@0: { sl@0: TBuf aDescription; sl@0: iOtgRoot.OtgEventString(iEvent, aDescription); sl@0: test.Printf(_L("Received Event %d '%S'\n"), iEvent, &aDescription); sl@0: } sl@0: sl@0: CPeripheralStateWatcher* CPeripheralStateWatcher::NewL(MOtgNotificationHandler &wdHandler, sl@0: const TWatcherNotifyType aWatchType, sl@0: COtgRoot &aOtgRoot) sl@0: { sl@0: //LOG_FUNC sl@0: CPeripheralStateWatcher* self = new (ELeave) CPeripheralStateWatcher(wdHandler, aWatchType, aOtgRoot); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: void CPeripheralStateWatcher::DisplayEvent() sl@0: { sl@0: TBuf aDescription; sl@0: iOtgRoot.PeripheralStateString(iPeripheralState, aDescription); sl@0: test.Printf(_L("Peripheral State %d '%S'\n"), iPeripheralState, &aDescription); sl@0: } sl@0: sl@0: CAConnectionIdleWatcher* CAConnectionIdleWatcher::NewL(MOtgNotificationHandler &wdHandler, sl@0: const TWatcherNotifyType aWatchType, sl@0: COtgRoot &aOtgRoot) sl@0: { sl@0: //LOG_FUNC sl@0: CAConnectionIdleWatcher* self = new (ELeave) CAConnectionIdleWatcher(wdHandler, aWatchType, aOtgRoot); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: void CAConnectionIdleWatcher::RunL() sl@0: { sl@0: // We need to override the RunL for this event type, as sl@0: // the semantics of the asynchronous function are somewhat sl@0: // different to the rest of the ones being serviced by sl@0: // CNotifyWatcherBase. sl@0: // sl@0: // In the case of QueueOtgConnectionNotification, the value sl@0: // passed in is updated *immediately* to reflect the current sl@0: // activity or otherwise of the connection (unlike the other sl@0: // async functions which update the value on completion). sl@0: // The completion in the case of QueueOtgConnectionNotification sl@0: // is used to indicate that the value has changed, and sl@0: // another request should be queued to pick up this new value. sl@0: // sl@0: // The practical upshot of this is that the IssueAgain needs sl@0: // to happen before the event is displayed and handled... sl@0: sl@0: IssueAgain(); sl@0: DisplayEvent(); sl@0: iHandler.HandleEvent(iWatchType, GetEventValue()); // report the event upwards sl@0: SetActive(); sl@0: } sl@0: sl@0: sl@0: void CAConnectionIdleWatcher::DisplayEvent() sl@0: { sl@0: TBuf aDescription; sl@0: iOtgRoot.AConnectionIdleString(iAConnectionIdle, aDescription); sl@0: test.Printf(_L("AConnectionIdle %d '%S'\n"), iAConnectionIdle, &aDescription); sl@0: }