Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h)
Have multiple extension sections in the bld.inf, one for each version
of the compiler. The RVCT version building the tools will build the
runtime libraries for its version, but make sure we extract all the other
versions from zip archives. Also add the archive for RVCT4.
// 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 <e32std.h>
#include <e32std_private.h>
#include <u32std.h> // unicode builds
#include <e32base.h>
#include <e32base_private.h>
#include <e32cons.h>
#include <e32Test.h> // RTest header
#include <e32ver.h>
#include <e32def.h>
#include <e32def_private.h>
#include <d32otgdi.h> // OTGDI header
#include <d32usbc.h> // 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<MAX_DSTRLEN> aDescription;
// print a usefull debug message
switch (aType)
{
case EWatcherTimeouts:
break;
case EWatcherState:
COtgRoot::OtgStateString(static_cast<RUsbOtgDriver::TOtgState>(aValue), aDescription);
LOG_VERBOSE3(_L("AddRequiredNotification() State %d '%S' wanted\n"), aValue, &aDescription);
break;
case EWatcherEvent:
COtgRoot::OtgEventString(static_cast<RUsbOtgDriver::TOtgEvent>(aValue), aDescription);
LOG_VERBOSE3(_L("AddRequiredNotification() Event %d '%S' wanted\n"), aValue, &aDescription);
break;
case EWatcherMessage:
COtgRoot::OtgMessageString(static_cast<RUsbOtgDriver::TOtgMessage>(aValue), aDescription);
LOG_VERBOSE3(_L("AddRequiredNotification() Message %d '%S' wanted\n"), aValue, &aDescription);
break;
case EWatcherPeripheralState:
COtgRoot::PeripheralStateString(static_cast<TUint>(aValue), aDescription);
LOG_VERBOSE3(_L("AddRequiredNotification() Peripheral State %d '%S' wanted\n"), aValue, &aDescription);
break;
case EWatcherAConnectionIdle:
COtgRoot::AConnectionIdleString(static_cast<RUsbOtgDriver::TOtgConnection>(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<MAX_DSTRLEN> 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<MAX_DSTRLEN> 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<MAX_DSTRLEN> 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<MAX_DSTRLEN> 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<MAX_DSTRLEN> aDescription;
iOtgRoot.AConnectionIdleString(iAConnectionIdle, aDescription);
test.Printf(_L("AConnectionIdle %d '%S'\n"), iAConnectionIdle, &aDescription);
}