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