kerneltest/e32test/usbho/t_otgdi/inc/b2bwatchers.h
author Slion
Tue, 08 Dec 2009 08:11:42 +0100
branchanywhere
changeset 19 f6d3d9676ee4
parent 0 a41df078684a
child 253 d37db4dcc88d
permissions -rw-r--r--
Trying to figure out how to implement my WINC like compatibility layer. Going the emulation way is probably not so smart. We should not use the kernel but rather hook native functions in the Exec calls.

#ifndef B2BWATCHERS_H
#define B2BWATCHERS_H
// 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:
// @internalComponent
// 
//


#include <d32otgdi.h>	// OTGDI thunk headder (under test)
#include <d32usbc.h>
#include "debugmacros.h"
#include "testcasefactory.h"
#include "testpolicy.h"
#include "testcaseroot.h"


// forward:
class CNotifyWatcherBase;	

// types:
enum TWatcherNotifyType
	{
	EWatcherTimeouts	=1,	// step watchdog event
	EWatcherState,			// OTG states
	EWatcherEvent,			// ... events
	EWatcherMessage,		// ... messages
	EWatcherPeripheralState,// Peripheral device state (undefined, attached, powered etc.)
	EWatcherAConnectionIdle,// (A-Device only) whether the connection is idle or busy
	EWatcherInvalid
	};

/* Applicable values in the value member - these are identical to the RUsbOtgDriver enum values, 
* but are passed as TInt to be generic
*	enum TOtgEvent
*		{
*		EEventAPlugInserted		,
*		EEventAPlugRemoved		,
*		EEventVbusRaised		,
*		EEventVbusDropped		,
*		EEventSrpInitiated		,
*		EEventSrpReceived		,
*		EEventHnpEnabled		,
*		EEventHnpDisabled		,
*		EEventHnpSupported		,
*		EEventHnpAltSupported	,
*		EEventRoleChangedToHost	,
*		EEventRoleChangedToDevice,
*		EEventRoleChangedToIdle								
*		};
*
*	enum TOtgState
*		{
*		EStateReset					,
*		EStateAIdle					,
*		EStateAHost					,
*		EStateAPeripheral			,
*		EStateAVbusError			,						
*		EStateBIdle					,
*		EStateBPeripheral			,
*		EStateBHost					
*		};
*
*	enum TOtgMessage
*		{
*		EEventQueueOverflow					,
*		EStateQueueOverflow					,
*		EMessageQueueOverflow				,
*		EMessageBadState					,
*		EMessageStackNotStarted				,
*		EMessageVbusAlreadyRaised			,
*		EMessageSrpForbidden				,
*		EMessageBusControlProblem			,
*		EMessageVbusError					,
*		EMessageSrpTimeout					,
*		EMessageSrpActive					,
*		EMessageSrpNotPermitted				,
*		EMessageHnpNotPermitted				,
*		EMessageHnpNotEnabled				,
*		EMessageHnpNotSuspended				,
*		EMessageVbusPowerUpNotPermitted		,
*		EMessageVbusPowerUpError			,
*		EMessageVbusPowerDownNotPermitted	,
*		EMessageVbusClearErrorNotPermitted	,
*		};
  */	

/*
From d32usbc.h : Device states available from client stack

enum TUsbcDeviceState
	{
	EUsbcDeviceStateUndefined,								// 0
	EUsbcDeviceStateAttached,								// 1
	EUsbcDeviceStatePowered,								// 2
	EUsbcDeviceStateDefault,								// 3
	EUsbcDeviceStateAddress,								// 4
	EUsbcDeviceStateConfigured,								// 5
	EUsbcDeviceStateSuspended,								// 6
 	EUsbcNoState = 0xff										// 255 (used as a place holder)
	};

*/

/* Used to save,encapsulate events so we can validate them at the end of a step
 */
class TOtgObservedEvent
	{
public:
	TOtgObservedEvent() {iValue = EWatcherInvalid;};
	
	TOtgObservedEvent(TWatcherNotifyType aType, TInt aValue) : iType(aType), iValue(aValue) {};
	TBool operator == (const TOtgObservedEvent&other) {return(other.iType==iType && other.iValue==iValue);};
	
	// getters
	TWatcherNotifyType 	GetType() {return(iType);};
	TInt 				GetValue() {return(iValue);};
private:	
	TWatcherNotifyType iType; 
	TInt iValue;
	};


/* OTG generic mixin. fires when otg event/state recieved - the Base class auto re-issues 
 * the request after handling the event by calling IssueAgain()
 */ 
class MOtgNotificationHandler
	{
public:
	virtual void HandleEvent(TWatcherNotifyType aType, TInt aNotificationValue)=0; 
	};


/* Sets up and then Collects notifications the user wanted
 * Become active when the last event we wanted fires
 */
class CNotifyCollector : public MOtgNotificationHandler
	{
public:
	CNotifyCollector(TRequestStatus &aStatus);
	virtual ~CNotifyCollector();

	// Create and start the observers
	void CreateObserversL(COtgRoot &aOtgDriver);
	// Stop and destroy the observers
	void DestroyObservers();
	
	// add an object to the Q
	void AddRequiredNotification(const TWatcherNotifyType aType, TInt aValue);

	//	Add an event to the list of events that indicates an instant failure
	//	(e.g. the B-Device becoming configured during a short-circuit role swap)
	void AddFailureNotification(const TWatcherNotifyType aType, TInt aValue);

	/* Ppecify a step timeout in MILLISECONDS */
	void AddStepTimeout(TInt aTimeoutMs) {
		AddRequiredNotification(EWatcherTimeouts, aTimeoutMs);};
	
	void ClearAllEvents(TBool aClearRecieved =ETrue, TBool aClearRequired =ETrue); 
	
	
	TBool EventReceivedAlready(const TOtgObservedEvent &aEvent);
	
	// from MOtgNotificationHandler
	// ... process the event, if all the needed events are satisfied, complete the object
	void HandleEvent(TWatcherNotifyType aType, TInt aNotificationValue); 
	
	// getters
	CNotifyWatcherBase* GetWatcher(TWatcherNotifyType aType);
	
	TInt DurationElapsed();

private:
	void AddRequiredOrFailureNotification(TWatcherNotifyType aType, TInt aValue, TBool aEventMeansFailure);
	TBool IsFailureEvent(TOtgObservedEvent& aEvent);
	
	void CompleteStep(TInt aCompletionCode);

private:
	TRequestStatus	&iStatusStep;	// KTestCaseWatchdogTO = failure, the test-step waits on this. 

	RArray<CNotifyWatcherBase*> iNotifyObjects;	// observers
	
	RArray<TOtgObservedEvent>   iRequiredEvents;
	RArray<TOtgObservedEvent>	iReceivedEvents;
	RArray<TOtgObservedEvent>	iFailureEvents;
	
	// duration timer
	TTime iTimeStarted;
	};


/* -----------------------------------------------------------------------------------------------
 * OTG Notification handler Base (Generic). We call these notification watchers, because they abstract 
 * OTG Messages, OTG Events, OTG States or a Watchdog timeout
 */
class CNotifyWatcherBase : public CActive
	{
public:
	virtual ~CNotifyWatcherBase() {LOG_FUNC  };
	
	virtual void StartWatching(TInt aInterval) {LOG_FUNC  TInt n(aInterval); IssueAgain(); SetActive(); };
	// getter
	TWatcherNotifyType GetType() {return(iWatchType);};		
	
protected:
	CNotifyWatcherBase (MOtgNotificationHandler &aHandler, const TWatcherNotifyType aWatchType, COtgRoot &aRoot) : 
				iOtgRoot(aRoot), 
				iWatchType(aWatchType),
				iHandler(aHandler),	
				CActive(EPriorityStandard) { CActiveScheduler::Add(this); };
	
	// from CActive
		void RunL();
 
	// override in child

public:		
	virtual TInt GetEventValue() =0;
	virtual TInt IssueAgain()    =0; 	// override 
	virtual void DisplayEvent()  =0;		
	
protected:
	MOtgNotificationHandler & iHandler;
	COtgRoot 				&iOtgRoot; 	// driver
	TWatcherNotifyType 		iWatchType; 
	};


//-----------------------------------------------------------------------------------------
// watchdog watcher,
// this watcher converts a CTimer event into a Notification, NOTE: it does not re-Issue the timer
class COtgWatchdogWatcher : public CNotifyWatcherBase
		{
	public:
		static COtgWatchdogWatcher* NewL(MOtgNotificationHandler &wdHandler, 
										const TWatcherNotifyType aWatchType, 
										COtgRoot &aOtgRoot);
		void ConstructL();
		virtual ~COtgWatchdogWatcher() {LOG_FUNC ;Cancel();};
		
		void StartTimer(TInt aIntervalMs);
		void StartWatching(TInt aIntervalMs) {StartTimer(aIntervalMs); };
		
 
		
		TInt IssueAgain() { LOG_FUNC ASSERT(0); return(0);};
		void DoCancel() {LOG_FUNC ;iTimer.Cancel();};
		void DisplayEvent() {LOG_FUNC ASSERT(0); }; // should never fire this
	TInt GetEventValue() {return(iIntervalMs);};
	void StepExpired(TInt aInterval);		
	
protected:
	COtgWatchdogWatcher(MOtgNotificationHandler &aHandler, const TWatcherNotifyType aWatchType, COtgRoot &aOtgRoot) :
		CNotifyWatcherBase(aHandler, aWatchType, aOtgRoot)
			{};
	// from CNotifyWatcherBase
	void RunL();
		
protected:
	TInt 	iIntervalMs;
	RTimer 	iTimer;
	};


/*--------------------------------------------------------------------------------------------
 * STATE Watcher
 * Like the other OTG watchers, this watcher will renew (resubscribe) to the relevant notification
 * again after it has fired.
 */
class COtgStateWatcher : public CNotifyWatcherBase
	{
public:
	static COtgStateWatcher* NewL(MOtgNotificationHandler &wdHandler, const TWatcherNotifyType aWatchType, COtgRoot &aOtgRoot);
	void ConstructL() {};
	
	virtual ~COtgStateWatcher() {LOG_FUNC Cancel(); };
	
	TInt IssueAgain() { iOtgRoot.otgQueueOtgStateRequest(iState , iStatus); return(ETrue);};
	void DisplayEvent(); 

	TInt GetEventValue() {return(iState);};
	
	void DoCancel() {LOG_FUNC iOtgRoot.otgCancelOtgStateRequest();};

protected:
	COtgStateWatcher(MOtgNotificationHandler &aHandler, const TWatcherNotifyType aWatchType, COtgRoot &aOtgRoot) :
		CNotifyWatcherBase(aHandler, aWatchType, aOtgRoot)
			{};
	
	RUsbOtgDriver::TOtgState iState;
	};


//---------------------------------------
// EVENT Watcher
class COtgEventWatcher : public CNotifyWatcherBase
	{
public:
	static COtgEventWatcher* NewL(MOtgNotificationHandler &wdHandler, const TWatcherNotifyType aWatchType, COtgRoot &aOtgRoot);
	void ConstructL() {};
	virtual ~COtgEventWatcher() {LOG_FUNC Cancel(); };		
	
	TInt IssueAgain() { iOtgRoot.otgQueueOtgEventRequest(iEvent , iStatus); return(ETrue);};
	void DisplayEvent(); 
	TInt GetEventValue() {return(iEvent);};
	void DoCancel() { LOG_FUNC iOtgRoot.otgCancelOtgEventRequest();};

protected:
	COtgEventWatcher(MOtgNotificationHandler &aHandler, const TWatcherNotifyType aWatchType, COtgRoot &aOtgRoot) : 
		CNotifyWatcherBase(aHandler, aWatchType, aOtgRoot)
			{};
	
	RUsbOtgDriver::TOtgEvent iEvent;
	};


//---------------------------------------
// MESSAGE Watcher
class COtgMessageWatcher : public CNotifyWatcherBase
	{
public:
	static COtgMessageWatcher* NewL(MOtgNotificationHandler &wdHandler, const TWatcherNotifyType aWatchType, COtgRoot &aOtgRoot);
	void ConstructL() {};
	virtual ~COtgMessageWatcher() {LOG_FUNC Cancel(); };	
	
	TInt IssueAgain() { iOtgRoot.otgQueueOtgMessageRequest(iMessage, iStatus); return(ETrue);};
	void DisplayEvent();
	TInt GetEventValue() {return(iMessage);};
	void DoCancel() {LOG_FUNC iOtgRoot.otgCancelOtgMessageRequest();};

protected:
	COtgMessageWatcher(MOtgNotificationHandler &aHandler, const TWatcherNotifyType aWatchType, COtgRoot &aOtgRoot) : 
		CNotifyWatcherBase(aHandler, aWatchType, aOtgRoot)
			{};
	
	RUsbOtgDriver::TOtgMessage iMessage;
	};
	
// Client state watcher
class CPeripheralStateWatcher : public CNotifyWatcherBase
	{
public:
	static CPeripheralStateWatcher* NewL(MOtgNotificationHandler &wdHandler, const TWatcherNotifyType aWatchType, COtgRoot &aOtgRoot);
	void ConstructL() {};
	virtual ~CPeripheralStateWatcher() {LOG_FUNC Cancel(); };	
	
	TInt IssueAgain() { iOtgRoot.otgQueuePeripheralStateRequest(iPeripheralState, iStatus); return(ETrue);};
	void DisplayEvent();
	TInt GetEventValue() {return(iPeripheralState);};
	void DoCancel() {LOG_FUNC iOtgRoot.otgCancelPeripheralStateRequest();};

protected:
	CPeripheralStateWatcher(MOtgNotificationHandler &aHandler, const TWatcherNotifyType aWatchType, COtgRoot &aOtgRoot) : 
		CNotifyWatcherBase(aHandler, aWatchType, aOtgRoot)
			{};
	
	TUint iPeripheralState;	//	*usually* to be interpreted as TUsbcDeviceState, see RDevUsbcClient::AlternateDeviceStatusNotify
	};

// Client state watcher
class CAConnectionIdleWatcher : public CNotifyWatcherBase
	{
public:
	static CAConnectionIdleWatcher* NewL(MOtgNotificationHandler &wdHandler, const TWatcherNotifyType aWatchType, COtgRoot &aOtgRoot);
	void ConstructL() {};
	virtual ~CAConnectionIdleWatcher() {LOG_FUNC Cancel(); };	
	
	TInt IssueAgain() { iOtgRoot.otgQueueAConnectionIdleRequest(iAConnectionIdle, iStatus); return(ETrue);};
	void DisplayEvent();
	TInt GetEventValue() {return(iAConnectionIdle);};
	void DoCancel() {LOG_FUNC iOtgRoot.otgCancelAConnectionIdleRequest();};

protected:
	CAConnectionIdleWatcher(MOtgNotificationHandler &aHandler, const TWatcherNotifyType aWatchType, COtgRoot &aOtgRoot) : 
		CNotifyWatcherBase(aHandler, aWatchType, aOtgRoot)
			{};
	
	void RunL();	//	From CActive

	RUsbOtgDriver::TOtgConnection iAConnectionIdle;
	};


#endif // B2BWATCHERS_H