usbmgmt/usbmgrtest/usbcontrolapp/usbviewer/usbviewer.cpp
changeset 0 c9bc50fca66e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbmgmt/usbmgrtest/usbcontrolapp/usbviewer/usbviewer.cpp	Tue Feb 02 02:02:59 2010 +0200
@@ -0,0 +1,1553 @@
+/*
+* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "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:
+*
+*/
+
+#include "usbviewer.h"
+
+#include <e32cons.h>
+#include <e32debug.h>
+
+#include <d32otgdi_errors.h>
+#include <d32usbdi_errors.h>
+#include <usb/usbshared.h>
+// For moving windows using scancode events
+#include "e32event.h"
+#include "e32svr.h" 
+
+
+#define PANIC Panic(__LINE__)
+#define LOG(A,B) RDebug::Print(_L("UsbViewer: " L##A),B)
+#define PNT(A)	 RDebug::Print(_L("UsbViewer: " L##A))
+
+void Panic(TInt aLine)
+	{
+	RDebug::Printf("UsbViewer: PANIC line=%d", aLine);
+	User::Panic(_L("USBVIEWER"), aLine);
+	}
+
+void RunViewerL()
+	{
+	CUsbViewer* viewer = CUsbViewer::NewLC();
+	viewer->Start();
+	CleanupStack::PopAndDestroy(viewer);
+	}
+
+TInt E32Main()
+	{
+	__UHEAP_MARK;
+	CTrapCleanup* cleanup = CTrapCleanup::New();
+	CActiveScheduler* activeScheduler = new CActiveScheduler;
+	TInt err = KErrNoMemory;
+	if(cleanup && activeScheduler)
+		{
+		CActiveScheduler::Install(activeScheduler);
+		PNT("*** UsbViewer E32Main ***\n");
+		TRAP(err, RunViewerL());
+		}
+	delete activeScheduler;
+	delete cleanup;
+	__UHEAP_MARKEND;
+	return err;
+	}
+
+
+XUsbViewerEvent::~XUsbViewerEvent()
+	{
+	iLink.Deque();
+	iEvent.Close();
+	}
+	
+	
+
+CUsbViewer* CUsbViewer::NewLC()
+	{
+	PNT("CUsbViewer::NewLC");
+	CUsbViewer* self = new(ELeave) CUsbViewer;
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	PNT("CUsbViewer::NewLC - Constructed Viewer");
+	return self;
+	}
+	
+CUsbViewer::~CUsbViewer()
+	{
+	PNT("CUsbViewer::~CUsbViewer");
+
+	delete iShutdownMonitor;
+
+	delete iMessageWatcher;
+	delete iHostEventWatcher;
+	delete iOtgStateWatcher;
+	delete iConnIdleWatcher;
+	delete iVBusWatcher;
+	delete iIdPinWatcher;
+	delete iDeviceStateWatcher;
+	delete iServiceStateWatcher;
+
+	delete iUserMsgQWatcher;
+	iUserMsgQ.Close();
+
+	TDblQueIter<XUsbViewerEvent> iter(iEventList);
+	XUsbViewerEvent* event = NULL;
+	while((event = iter++) != NULL)
+		{
+		delete event;
+		} 
+
+	Cancel();
+
+	PNT("Closing USB Session");
+	iUsb.Close();
+	delete iConsole;
+	}
+
+CUsbViewer::CUsbViewer()
+	: CActive(EPriorityLow) // Low so all notifications that want to be serviced will be done first
+	, iAutoSrpResponse(EFalse)
+	, iDeviceType(ENoDevice)
+	, iEventList(_FOFF(XUsbViewerEvent, iLink))
+	{
+	CActiveScheduler::Add(this);
+	}
+
+void CUsbViewer::ConstructL()
+	{
+	PNT("CUsbViewer::ConstructL");
+	iConsole = Console::NewL(KUsbViewerTitle, TSize(KViewerNumCharactersOnLine, KNumLinesInWindow));
+	Move(-3, -3);
+	User::LeaveIfError(iUsb.Connect());
+	
+	for(TInt i=0; i<KNumEventsInWindow; ++i)
+		{
+        XUsbViewerEvent* nullEvent = new(ELeave) XUsbViewerEvent;
+		iEventList.AddFirst(*nullEvent);
+		}
+
+	// Open message queue to display user messages
+	User::LeaveIfError(iUserMsgQ.OpenGlobal(KControlAppViewerMsgQName));
+	iUserMsgQWatcher = CUserMsgQWatcher::NewL(*this);
+
+	iServiceStateWatcher = CServiceStateWatcher::NewL(*this);
+	iDeviceStateWatcher = CDeviceStateWatcher::NewL(*this);
+	iIdPinWatcher = CIdPinWatcher::NewL(*this);
+	iVBusWatcher = CVBusWatcher::NewL(*this);
+	iConnIdleWatcher = CConnectionIdleWatcher::NewL(*this);
+	iOtgStateWatcher = COtgStateWatcher::NewL(*this);
+	iHostEventWatcher = CHostEventWatcher::NewL(*this);
+	iMessageWatcher = CMessageWatcher::NewL(*this);
+	SetDriverLoading(EUnknown);
+	SetDeviceType(ENoDevice);
+
+	iShutdownMonitor = CShutdownMonitor::NewL(*this);
+	}
+
+void CUsbViewer::Move(TInt aX, TInt aY)
+	{
+	TRawEvent event;
+
+	event.Set(TRawEvent::EKeyDown, EStdKeyLeftShift);
+	UserSvr::AddEvent(event);
+
+	if (aX)
+		{
+		if ( aX > 0 )
+			{
+			// Move to the right...
+			for(TInt i=aX; i; i--)
+				{
+				event.Set(TRawEvent::EKeyDown, EStdKeyRightArrow);
+				UserSvr::AddEvent(event);
+				event.Set(TRawEvent::EKeyUp, EStdKeyRightArrow);
+				UserSvr::AddEvent(event);
+				}
+			}
+		else
+			{
+			// Move to the Left...
+			for(TInt i=aX; i; i++)
+				{
+				event.Set(TRawEvent::EKeyDown, EStdKeyLeftArrow);
+				UserSvr::AddEvent(event);
+				event.Set(TRawEvent::EKeyUp, EStdKeyLeftArrow);
+				UserSvr::AddEvent(event);
+				}
+			}
+		}
+	
+	if (aY)
+		{
+		if ( aY > 0 )
+			{
+			// Move downwards...
+			for(TInt i=aY; i; i--)
+				{
+				event.Set(TRawEvent::EKeyDown, EStdKeyDownArrow);
+				UserSvr::AddEvent(event);
+				event.Set(TRawEvent::EKeyUp, EStdKeyDownArrow);
+				UserSvr::AddEvent(event);
+				}
+			}
+		else
+			{
+			// Move upwards...
+			for(TInt i=aY; i; i++)
+				{
+				event.Set(TRawEvent::EKeyDown, EStdKeyUpArrow);
+				UserSvr::AddEvent(event);
+				event.Set(TRawEvent::EKeyUp, EStdKeyUpArrow);
+				UserSvr::AddEvent(event);
+				}
+			}
+		}
+
+	event.Set(TRawEvent::EKeyUp, EStdKeyLeftShift);
+	UserSvr::AddEvent(event);
+	}
+
+void CUsbViewer::Start()
+	{
+	// Get everything running
+	CActiveScheduler::Start();
+	}
+	
+void CUsbViewer::Stop() const
+	{
+	CActiveScheduler::Stop();
+	}
+
+void CUsbViewer::DoCancel()
+	{
+	// Don't need to do anything as the AO is completed straight away.
+	}
+
+void CUsbViewer::RunL()
+	{
+	__ASSERT_ALWAYS(iStatus.Int() == KErrNone, PANIC);
+	Draw();
+	}
+
+void CUsbViewer::ScheduleDraw()
+	{
+	PNT("CUsbViewer::ScheduleDraw");
+	if(!IsActive())
+		{
+		SetActive();
+		TRequestStatus* status = &iStatus;
+		User::RequestComplete(status, KErrNone);
+
+		TSize size = iConsole->ScreenSize();
+		iConsole->SetCursorPosAbs(TPoint(size.iWidth-1, 0));
+		iConsole->Write(_L("*"));
+		}
+	}
+	
+RUsb& CUsbViewer::Usb()
+	{
+	return iUsb;
+	}
+
+RMsgQueue<TBuf<KViewerNumCharactersOnLine> >& CUsbViewer::UserMsgQ()
+	{
+	return iUserMsgQ;
+	}
+	
+void CUsbViewer::SetServiceState(TUsbServiceState aServiceState)
+	{
+	switch(aServiceState)
+		{
+    case EUsbServiceIdle:
+    	iServStatus =
+    		//  12345678901
+			_L("Idle       ");
+    	break;
+
+	case EUsbServiceStarting:
+    	iServStatus =
+    		//  12345678901
+			_L("Starting   ");
+		break;
+
+	case EUsbServiceStarted:
+	    iServStatus =
+    		//  12345678901
+			_L("Started    ");
+		break;
+
+	case EUsbServiceStopping:
+    	iServStatus =
+    		//  12345678901
+			_L("Stopping   ");
+		break;
+
+	case EUsbServiceFatalError:
+    	iServStatus =
+    		//  12345678901
+			_L("Error      ");
+		break;
+
+	default:
+		PANIC;
+		break;
+		}
+	LOG("Service State => %S", &iServStatus);
+	ScheduleDraw();
+	}
+	
+void CUsbViewer::SetDeviceState(TUsbDeviceState aDeviceState)
+	{
+	switch(aDeviceState)
+		{
+	case EUsbDeviceStateUndefined:
+		iDevStatus =
+    		//  12345678901
+			_L("Undefined  ");
+		break;
+
+	case EUsbDeviceStateDefault:
+		iDevStatus =
+    		//  12345678901
+			_L("Default    ");
+		break;
+
+	case EUsbDeviceStateAttached:
+		iDevStatus =
+    		//  12345678901
+			_L("Attached   ");
+		break;
+
+	case EUsbDeviceStatePowered:
+		iDevStatus =
+    		//  12345678901
+			_L("Powered    ");
+		break;
+
+	case EUsbDeviceStateConfigured:
+		iDevStatus =
+    		//  12345678901
+			_L("Configured ");
+		break;
+
+	case EUsbDeviceStateAddress:
+		iDevStatus =
+    		//  12345678901
+			_L("Address    ");
+		break;
+
+	case EUsbDeviceStateSuspended:
+		iDevStatus =
+    		//  12345678901
+			_L("Suspended  ");
+		break;
+
+	default:
+		PANIC;
+		break;
+		}
+	LOG("Device State => %S", &iDevStatus);
+	ScheduleDraw();
+	}
+	
+void CUsbViewer::SetIdPin(TInt aIdPin)
+	{
+	switch(aIdPin)
+		{
+	case 0:
+		iIdPin =
+    		//  12345
+			_L("-    ");
+		break;
+
+	case 1:
+		iIdPin =
+    		//  12345
+			_L("+    ");
+		break;
+
+	default:
+		PANIC;
+		break;
+		}
+	LOG("Id Pin => %S", &iIdPin);
+	ScheduleDraw();
+	}
+	
+void CUsbViewer::SetVBus(TInt aVBus)
+	{
+	switch(aVBus)
+		{
+	case 0:
+		iVBus =
+    		//  12345
+			_L("-    ");
+		break;
+
+	case 1:
+		iVBus =
+    		//  12345
+			_L("+    ");
+		break;
+
+	default:
+		PANIC;
+		break;
+		}
+	LOG("VBus => %S", &iVBus);
+	ScheduleDraw();
+	}
+
+void CUsbViewer::SetConnectionIdle(TInt aConnIdle)
+	{
+	switch(aConnIdle)
+		{
+	case 0:
+		iConnIdle =
+    		//  12345
+			_L("-    ");
+		break;
+
+	case 1:
+		iConnIdle =
+    		//  12345
+			_L("+    ");
+		break;
+
+	default:
+		PANIC;
+		break;
+		}
+	LOG("Connection Idle => %S", &iConnIdle);
+	ScheduleDraw();
+	}
+
+void CUsbViewer::SetOtgState(TInt aOtgState)
+	{
+	switch(aOtgState)
+		{
+	case 0x01:
+		iOtgState =
+    		//  123456789012
+			_L("Reset       ");
+		break;
+
+	case 0x02:
+		iOtgState =
+    		//  123456789012
+			_L("A-Idle      ");
+		break;
+
+	case 0x04:
+		iOtgState =
+    		//  123456789012
+			_L("A-Host      ");
+		break;
+
+	case 0x08:
+		iOtgState =
+    		//  1234567890123
+			_L("A-Peripheral");
+		break;
+
+	case 0x10:
+		iOtgState =
+    		//  123456789012
+			_L("A-Vbus Error");
+		break;
+
+	case 0x20:
+		iOtgState =
+    		//  123456789012
+			_L("B-Idle      ");
+		break;
+
+	case 0x40:
+		iOtgState =
+    		//  1234567890123
+			_L("B-Peripheral");
+		break;
+
+	case 0x80:
+		iOtgState =
+    		//  1234567890123
+			_L("B-Host      ");
+		break;
+		
+	default:
+		iOtgState =
+    		//  1234567890123
+			_L("Don't Panic!");
+		break;
+		}
+	LOG("OTG State => %S", &iOtgState);
+	ScheduleDraw();
+	}
+
+void CUsbViewer::SetDriverLoading(TFdfDriverLoadingState aDriverLoading)
+	{
+	switch(aDriverLoading)
+		{
+	case EUnknown:
+		iDriverLoading =
+			//  123
+			_L("???");
+		break;
+	case EDisabled:
+		iDriverLoading =
+			//  123
+			_L("Off");
+		break;
+	case EEnabled:
+		iDriverLoading =
+			//  123
+			_L("On ");
+		break;
+	default:
+		PANIC;
+		break;
+		}
+	LOG("Driver Loading => %S", &iDriverLoading);
+	ScheduleDraw();
+	}
+	
+void CUsbViewer::SetAttachedDevices(TUint aAttachedDevices)
+	{
+	if(aAttachedDevices > 999)
+		{
+		iAttachedDevices =
+			//  123
+			_L("xxx");
+		}
+	else
+		{
+		iAttachedDevices.NumFixedWidthUC(aAttachedDevices, EDecimal, 3);
+		}
+	LOG("Attached Devices => %S", &iAttachedDevices);
+	ScheduleDraw();
+	}
+
+void CUsbViewer::SetDeviceType(TDeviceType aDeviceType)
+	{
+	iDeviceType = aDeviceType;
+
+	switch ( aDeviceType )
+		{
+	case ENoDevice:
+		iAttachedDevice =
+			//  12345
+			_L("     ");
+		break;
+	case EGenericDevice:
+		iAttachedDevice =
+			//  12345
+			_L("<   >");
+		break;
+	case ELogitechHeadset:
+		iAttachedDevice =
+			//  12345
+			_L("<<A>>");
+		break;
+		}
+	LOG("Audio Device => [%S]", &iAttachedDevice);
+	ScheduleDraw();
+	}
+
+void CUsbViewer::NotifyEvent(XUsbViewerEvent* aEvent)
+	{
+	LOG("CUsbViewer::NotifyEvent	event length = %d", aEvent->iEvent.Length());
+	__ASSERT_ALWAYS(aEvent, PANIC);
+	__ASSERT_ALWAYS(aEvent->iEvent.Length() <= KViewerNumCharactersOnLine, PANIC);
+
+	iEventList.AddFirst(*aEvent);
+	delete iEventList.Last();
+
+	LOG("Event => %S", &(aEvent->iEvent));
+	ScheduleDraw();
+	}
+
+void CUsbViewer::Draw()
+	{
+	PNT("CUsbViewer::Draw");
+	iConsole->ClearScreen();
+
+	iConsole->Printf(_L(
+//          1         2         3  
+// 12345678901234567890123456789012
+//               
+//        12345         12345678901
+  "IdPin: %S" L"SrvSt : %S\n"      
+//        12345         12345678901
+ L"VBus : %S" L"DevSt : %S\n"
+//        123           123
+ L"DLoad: %S  " L"# Devs: %S\n"   
+//        12345         1234
+ L"Dev  : %S" L"        \n"
+//        12345        1234567890123
+ L"C.Idl: %S" L"OTG  : %S \n"   
+	),
+	&iIdPin,			&iServStatus, 
+	&iVBus,				&iDevStatus, 
+	&iDriverLoading,	&iAttachedDevices,
+	&iAttachedDevice,	
+	&iConnIdle,			&iOtgState
+	);
+
+	// Events...
+	TDblQueIter<XUsbViewerEvent> iter(iEventList);
+	XUsbViewerEvent* event = NULL;
+	while((event = iter++) != NULL)
+		{
+		iConsole->Printf(_L("\n"));
+		iConsole->Printf(event->iEvent.Left(KViewerNumCharactersOnLine));
+		}
+	}
+	
+
+
+CShutdownMonitor* CShutdownMonitor::NewL(MShutdownInterface& aParentUsbViewer)
+	{
+	CShutdownMonitor* self = new(ELeave) CShutdownMonitor(aParentUsbViewer);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CShutdownMonitor::CShutdownMonitor(MShutdownInterface& aParentUsbViewer)
+	: CActive(EPriorityLow) // Low so all notifications that want to be serviced will be done first
+	, iParentUsbViewer(aParentUsbViewer)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+void CShutdownMonitor::ConstructL()
+	{
+	// Monitor the KUsbControlAppShutdownKey property to tell us when to shut down
+	TInt err = iShutdownProp.Attach(KUidUsbControlAppCategory, KUsbControlAppShutdownKey);
+	LOG("CShutdownMonitor::ConstructL	 iShutdownProp.Attach() => %d", err);
+	User::LeaveIfError(err);
+	iShutdownProp.Subscribe(iStatus);
+	SetActive();
+	TInt val;
+	// Make sure the cuurent value is 0 - shut down when this changes to 1
+	err = iShutdownProp.Get(val);
+	LOG("CShutdownMonitor::ConstructL()	 iShutdownProp.Get(val)		val => %d", val);
+	LOG("CShutdownMonitor::ConstructL()	 iShutdownProp.Get(val)		err => %d", err);
+	User::LeaveIfError(err);
+	__ASSERT_ALWAYS(val==0, PANIC);
+	}
+
+CShutdownMonitor::~CShutdownMonitor()
+	{
+	iShutdownProp.Close();
+	}
+
+void CShutdownMonitor::RunL()
+	{
+	// Request to shut everything down made in USB Aware App
+	TInt val;
+	TInt err = iShutdownProp.Get(val);
+	LOG("CShutdownMonitor::RunL	 iShutdownProp.Get(val) err => %d", err);
+	LOG("CShutdownMonitor::RunL	 iShutdownProp.Get(val) val => %d", val);
+	Cancel(); // Not interested in any more notifications
+	iParentUsbViewer.Stop(); // Stopping Active Scheduler will results in the destructor getting called
+	}
+
+void CShutdownMonitor::DoCancel()
+	{
+	iShutdownProp.Cancel();
+	}
+	
+
+
+CEventNotifier::CEventNotifier(TInt aPriority)
+	: CActive(aPriority)
+	{
+	}
+
+XUsbViewerEvent* CEventNotifier::NewViewerEventL()
+	{
+	XUsbViewerEvent* event = new(ELeave) XUsbViewerEvent;
+	CleanupStack::PushL(event);
+	User::LeaveIfError(event->iEvent.Create(KViewerNumCharactersOnLine));
+	CleanupStack::Pop();
+	return event;
+	}
+
+void CEventNotifier::RunL()
+	{
+	DoRunL(NewViewerEventL());
+	}
+
+
+
+
+CServiceStateWatcher* CServiceStateWatcher::NewL(CUsbViewer& aUsbViewer)
+	{
+	CServiceStateWatcher* self = new(ELeave) CServiceStateWatcher(aUsbViewer);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CServiceStateWatcher::~CServiceStateWatcher()
+	{
+	Cancel();
+	}
+
+CServiceStateWatcher::CServiceStateWatcher(CUsbViewer& aUsbViewer)
+	: CEventNotifier(EPriorityStandard)
+	, iUsbViewer(aUsbViewer)
+	, iServiceState(EUsbServiceIdle)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+void CServiceStateWatcher::ConstructL()
+	{
+	iUsbViewer.Usb().ServiceStateNotification(iServiceState, iStatus);
+	SetActive();
+
+	TUsbServiceState serviceState;
+	User::LeaveIfError(iUsbViewer.Usb().GetServiceState(serviceState));
+	iUsbViewer.SetServiceState(serviceState);
+	}
+
+void CServiceStateWatcher::DoCancel()
+	{
+	iUsbViewer.Usb().ServiceStateNotificationCancel();
+	}
+
+void CServiceStateWatcher::DoRunL(XUsbViewerEvent* aEvent)
+	{
+	iUsbViewer.SetServiceState(iServiceState);
+	TPtrC res(NULL, 0);
+	_LIT(KIdle,     "Idle");
+	_LIT(KStarting, "Starting");
+	_LIT(KStarted,  "Started");
+	_LIT(KStopping, "Stopping");
+	_LIT(KError,    "Error");
+	switch(iServiceState)
+		{
+	case EUsbServiceIdle:
+		res.Set(KIdle);
+		break;
+	case EUsbServiceStarting:
+		res.Set(KStarting);
+		break;
+	case EUsbServiceStarted:
+		res.Set(KStarted);
+		break;
+	case EUsbServiceStopping:
+		res.Set(KStopping);
+		break;
+	case EUsbServiceFatalError:
+		res.Set(KError);
+		break;
+	default:
+		PANIC;
+		break;
+		}
+		
+	iUsbViewer.Usb().ServiceStateNotification(iServiceState, iStatus);
+	SetActive();
+//                                  16              8 1 -> 25
+	aEvent->iEvent.AppendFormat(_L("D:ServiceState [%S]"), &res);
+	iUsbViewer.NotifyEvent(aEvent);
+
+	// RunL call may have been delayed: ensure viewer has the very latest information
+	TUsbServiceState serviceState;
+	User::LeaveIfError(iUsbViewer.Usb().GetServiceState(serviceState));
+
+	iUsbViewer.SetServiceState(serviceState);
+	}
+
+	
+CDeviceStateWatcher* CDeviceStateWatcher::NewL(CUsbViewer& aUsbViewer)
+	{
+	CDeviceStateWatcher* self = new(ELeave) CDeviceStateWatcher(aUsbViewer);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CDeviceStateWatcher::~CDeviceStateWatcher()
+	{
+	Cancel();
+	}
+
+CDeviceStateWatcher::CDeviceStateWatcher(CUsbViewer& aUsbViewer)
+	: CEventNotifier(EPriorityStandard)
+	, iUsbViewer(aUsbViewer)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+void CDeviceStateWatcher::ConstructL()
+	{
+	iUsbViewer.Usb().DeviceStateNotification(0xffffffff, iDeviceState, iStatus);
+	SetActive();
+
+	TUsbDeviceState deviceState;
+	User::LeaveIfError(iUsbViewer.Usb().GetDeviceState(deviceState));
+	iUsbViewer.SetDeviceState(deviceState);
+	}
+
+void CDeviceStateWatcher::DoCancel()
+	{
+	iUsbViewer.Usb().DeviceStateNotificationCancel();
+	}
+
+void CDeviceStateWatcher::DoRunL(XUsbViewerEvent* aEvent)
+	{
+	iUsbViewer.SetDeviceState(iDeviceState);
+	TPtrC res(NULL, 0);
+	_LIT(KUndefined,  "Undefined");
+    _LIT(KDefault,    "Default");
+    _LIT(KAttached,   "Attached");
+    _LIT(KPowered,    "Powered");
+    _LIT(KConfigured, "Configured");
+    _LIT(KAddress,    "Address");
+    _LIT(KSuspended,  "Suspended");
+	switch(iDeviceState)
+		{
+	case EUsbDeviceStateUndefined:
+		res.Set(KUndefined);
+		break;
+	case EUsbDeviceStateDefault:
+		res.Set(KDefault);
+		break;
+	case EUsbDeviceStateAttached:
+		res.Set(KAttached);
+		break;
+	case EUsbDeviceStatePowered:
+		res.Set(KPowered);
+		break;
+	case EUsbDeviceStateConfigured:
+		res.Set(KConfigured);
+		break;
+	case EUsbDeviceStateAddress:
+		res.Set(KAddress);
+		break;
+	case EUsbDeviceStateSuspended:
+		res.Set(KSuspended);
+		break;
+	default:
+		PANIC;
+		break;
+		}
+
+    iUsbViewer.Usb().DeviceStateNotification(0xffffffff, iDeviceState, iStatus);
+	SetActive();
+//                                  15            10 1 -> 26
+	aEvent->iEvent.AppendFormat(_L("D:DeviceState [%S]"), &res);
+	iUsbViewer.NotifyEvent(aEvent);
+
+	// RunL call may have been delayed: ensure viewer has the very latest information
+	TUsbDeviceState deviceState;
+	User::LeaveIfError(iUsbViewer.Usb().GetDeviceState(deviceState));
+
+	iUsbViewer.SetDeviceState(deviceState);
+	}
+	
+	
+CIdPinWatcher* CIdPinWatcher::NewL(CUsbViewer& aUsbViewer)
+	{
+	CIdPinWatcher* self = new(ELeave) CIdPinWatcher(aUsbViewer);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CIdPinWatcher::~CIdPinWatcher()
+	{
+	Cancel();
+	iIdPinProp.Close();
+	}
+
+CIdPinWatcher::CIdPinWatcher(CUsbViewer& aUsbViewer)
+	: CEventNotifier(EPriorityStandard)
+	, iUsbViewer(aUsbViewer)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+void CIdPinWatcher::ConstructL()
+	{
+	User::LeaveIfError(iIdPinProp.Attach(KUidUsbManCategory, KUsbOtgIdPinPresentProperty));
+	iIdPinProp.Subscribe(iStatus);
+	SetActive();
+
+	TInt val;
+	TInt err = iIdPinProp.Get(val);
+	LOG("CIdPinWatcher::ConstructL iIdPinProp.Get(val) => %d",err);
+	User::LeaveIfError(err);
+	iUsbViewer.SetIdPin(val);
+	}
+
+void CIdPinWatcher::DoCancel()
+	{
+	iIdPinProp.Cancel();
+	}
+
+void CIdPinWatcher::DoRunL(XUsbViewerEvent* aEvent)
+	{
+	CleanupStack::PushL(aEvent);
+
+	iIdPinProp.Subscribe(iStatus);
+	SetActive();
+
+	TInt val;
+	User::LeaveIfError(iIdPinProp.Get(val));
+
+	TPtrC res(NULL, 0);
+	_LIT(KIdPinInserted, "Inserted");
+	_LIT(KIdPinRemoved,  "Removed");
+	switch(val)
+		{
+	case 0:
+		res.Set(KIdPinRemoved);
+		break;
+
+	case 1:
+		res.Set(KIdPinInserted);
+		break;
+
+	default:
+		PANIC;
+		break;
+		}
+	CleanupStack::Pop();
+//                                  9        8 1 -> 18
+	aEvent->iEvent.AppendFormat(_L("O:IdPin [%S]"), &res);
+	iUsbViewer.SetIdPin(val);
+	iUsbViewer.NotifyEvent(aEvent);
+	}
+	
+	
+CVBusWatcher* CVBusWatcher::NewL(CUsbViewer& aUsbViewer)
+	{
+	CVBusWatcher* self = new(ELeave) CVBusWatcher(aUsbViewer);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CVBusWatcher::~CVBusWatcher()
+	{
+	Cancel();
+	iVBusProp.Close();
+	}
+
+CVBusWatcher::CVBusWatcher(CUsbViewer& aUsbViewer)
+	: CEventNotifier(EPriorityStandard)
+	, iUsbViewer(aUsbViewer)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+void CVBusWatcher::ConstructL()
+	{
+	User::LeaveIfError(iVBusProp.Attach(KUidUsbManCategory, KUsbOtgVBusPoweredProperty));
+	iVBusProp.Subscribe(iStatus);
+	SetActive();
+
+	TInt val;
+	User::LeaveIfError(iVBusProp.Get(val));
+	iUsbViewer.SetVBus(val);
+	}
+
+void CVBusWatcher::DoCancel()
+	{
+	iVBusProp.Cancel();
+	}
+
+void CVBusWatcher::DoRunL(XUsbViewerEvent* aEvent)
+	{
+	CleanupStack::PushL(aEvent);
+
+	iVBusProp.Subscribe(iStatus);
+	SetActive();
+
+	TInt val;
+	User::LeaveIfError(iVBusProp.Get(val));
+
+	TPtrC res(NULL, 0);
+	_LIT(KVBusRaised,  "Raised");
+	_LIT(KVBusDropped, "Dropped");
+	switch(val)
+		{
+	case 0:
+		res.Set(KVBusDropped);
+		break;
+
+	case 1:
+		res.Set(KVBusRaised);
+		break;
+
+	default:
+		PANIC;
+		break;
+		}
+	CleanupStack::Pop();
+//									8       7 1 -> 16
+	aEvent->iEvent.AppendFormat(_L("O:VBus [%S]"), &res);
+	iUsbViewer.SetVBus(val);
+	iUsbViewer.NotifyEvent(aEvent);
+	}
+
+
+CConnectionIdleWatcher* CConnectionIdleWatcher::NewL(CUsbViewer& aUsbViewer)
+	{
+	CConnectionIdleWatcher* self = new(ELeave) CConnectionIdleWatcher(aUsbViewer);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CConnectionIdleWatcher::~CConnectionIdleWatcher()
+	{
+	Cancel();
+	iConnIdleProp.Close();
+	}
+
+CConnectionIdleWatcher::CConnectionIdleWatcher(CUsbViewer& aUsbViewer)
+	: CEventNotifier(EPriorityStandard)
+	, iUsbViewer(aUsbViewer)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+void CConnectionIdleWatcher::ConstructL()
+	{
+	User::LeaveIfError(iConnIdleProp.Attach(KUidUsbManCategory, KUsbOtgConnectionIdleProperty));
+	iConnIdleProp.Subscribe(iStatus);
+	SetActive();
+
+	TInt val;
+	TInt err = iConnIdleProp.Get(val);
+	LOG("CConnectionIdleWatcher::ConstructL iConnIdleProp.Get(val) => %d",err);
+	User::LeaveIfError(err);
+	iUsbViewer.SetConnectionIdle(val);
+	}
+
+void CConnectionIdleWatcher::DoCancel()
+	{
+	iConnIdleProp.Cancel();
+	}
+
+void CConnectionIdleWatcher::DoRunL(XUsbViewerEvent* aEvent)
+	{
+	CleanupStack::PushL(aEvent);
+
+	iConnIdleProp.Subscribe(iStatus);
+	SetActive();
+
+	TInt val;
+	User::LeaveIfError(iConnIdleProp.Get(val));
+
+	TPtrC res(NULL, 0);
+	_LIT(KConnIdle,		"Idle");
+	_LIT(KConnActive,	"Active");
+	switch(val)
+		{
+	case 0:
+		res.Set(KConnActive);
+		break;
+
+	case 1:
+		res.Set(KConnIdle);
+		break;
+
+	default:
+		PANIC;
+		break;
+		}
+	CleanupStack::Pop();
+//                                  12          6 1 -> 19
+	aEvent->iEvent.AppendFormat(_L("O:ConnIdle [%S]"), &res);
+	iUsbViewer.SetConnectionIdle(val);
+	iUsbViewer.NotifyEvent(aEvent);
+	}
+
+	
+COtgStateWatcher* COtgStateWatcher::NewL(CUsbViewer& aUsbViewer)
+	{
+	COtgStateWatcher* self = new(ELeave) COtgStateWatcher(aUsbViewer);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+COtgStateWatcher::~COtgStateWatcher()
+	{
+	Cancel();
+	iOtgStateProp.Close();
+	}
+
+COtgStateWatcher::COtgStateWatcher(CUsbViewer& aUsbViewer)
+	: CEventNotifier(EPriorityStandard)
+	, iUsbViewer(aUsbViewer)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+void COtgStateWatcher::ConstructL()
+	{
+	User::LeaveIfError(iOtgStateProp.Attach(KUidUsbManCategory, KUsbOtgStateProperty));
+	iOtgStateProp.Subscribe(iStatus);
+	SetActive();
+
+	TInt val;
+	User::LeaveIfError(iOtgStateProp.Get(val));
+	iUsbViewer.SetOtgState(val);
+	}
+
+void COtgStateWatcher::DoCancel()
+	{
+	iOtgStateProp.Cancel();
+	}
+
+void COtgStateWatcher::DoRunL(XUsbViewerEvent* aEvent)
+	{
+	CleanupStack::PushL(aEvent);
+
+	iOtgStateProp.Subscribe(iStatus);
+	SetActive();
+
+	TInt val;
+	User::LeaveIfError(iOtgStateProp.Get(val));
+
+	TPtrC res(NULL, 0);
+	
+	_LIT(KReset, 		"Reset"			);
+
+	_LIT(KAIdle, 		"A-Idle"		);
+	_LIT(KAHost, 		"A-Host"		);
+	_LIT(KAPeripheral, 	"A-Peripheral"	);
+	_LIT(KABusError, 	"A-Bus Error"	);
+	
+	_LIT(KBIdle, 		"B-Idle"		);
+	_LIT(KBPeripheral, 	"B-Peripheral"	);
+	_LIT(KBHost, 		"B-Host"		);
+	
+	_LIT(KUnknown, 		"Unknown"		);
+
+	switch(val)
+		{
+	case EUsbOtgStateReset:
+		res.Set(KReset);
+		break;
+
+	case EUsbOtgStateAIdle:
+		res.Set(KAIdle);
+		break;
+
+	case EUsbOtgStateAHost:
+		res.Set(KAHost);
+		break;
+
+	case EUsbOtgStateAPeripheral:
+		res.Set(KAPeripheral);
+		break;
+
+	case EUsbOtgStateAVbusError:
+		res.Set(KABusError);
+		break;
+
+	case EUsbOtgStateBIdle:
+		res.Set(KBIdle);
+		break;
+
+	case EUsbOtgStateBPeripheral:
+		res.Set(KBPeripheral);
+		break;
+		
+	case EUsbOtgStateBHost:
+		res.Set(KBHost);
+		break;
+
+	default:
+		res.Set(KUnknown);
+		break;
+		}
+	CleanupStack::Pop();
+
+//                                  12         12 1 -> 25
+	aEvent->iEvent.AppendFormat(_L("O:OtgState [%S]"), &res);
+	iUsbViewer.SetOtgState(val);
+	iUsbViewer.NotifyEvent(aEvent);
+	}
+
+CHostEventWatcher* CHostEventWatcher::NewL(CUsbViewer& aUsbViewer)
+	{
+	CHostEventWatcher* self = new(ELeave) CHostEventWatcher(aUsbViewer);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CHostEventWatcher::~CHostEventWatcher()
+	{
+	Cancel();
+	}
+
+CHostEventWatcher::CHostEventWatcher(CUsbViewer& aUsbViewer)
+	: CEventNotifier(EPriorityStandard)
+	, iUsbViewer(aUsbViewer)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+void CHostEventWatcher::ConstructL()
+	{
+	iUsbViewer.Usb().HostEventNotification(iStatus, iDeviceInfo);
+	SetActive();
+	iUsbViewer.SetAttachedDevices(0);
+	}
+
+void CHostEventWatcher::DoCancel()
+	{
+	iUsbViewer.Usb().HostEventNotificationCancel();
+	}
+
+void CHostEventWatcher::DoRunL(XUsbViewerEvent* aEvent)
+	{
+	CleanupStack::PushL(aEvent);
+
+	switch(iDeviceInfo.iEventType)
+		{
+	case EDeviceAttachment:
+			{
+			if(iDeviceInfo.iError == KErrNone)
+				{
+				User::LeaveIfError(iAttachedDevices.Append(iDeviceInfo.iDeviceId));
+				}
+//										    5    8    6     4    1 4   1 -> 29
+			aEvent->iEvent.AppendFormat(_L("H:At[%.08x] V,P[%.04x,%.04x]"), iDeviceInfo.iDeviceId, iDeviceInfo.iVid, iDeviceInfo.iPid);
+			
+			if (  (iDeviceInfo.iVid == 0x046D)
+			    &&(iDeviceInfo.iPid == 0x0A02)
+			   )
+				{
+				iUsbViewer.SetDeviceType(CUsbViewer::ELogitechHeadset);
+				}
+			else
+				{
+				iUsbViewer.SetDeviceType(CUsbViewer::EGenericDevice);
+				}
+			}
+		break;
+
+	case EDriverLoad:
+			{
+			TPtrC res(NULL, 0);
+			_LIT(KDriverLoadSuccess, "Success");
+			_LIT(KDriverLoadPartialSuccess, "Warning");
+			_LIT(KDriverLoadFailure, "Failure");
+			switch(iDeviceInfo.iDriverLoadStatus)
+				{
+			case EDriverLoadSuccess:
+				res.Set(KDriverLoadSuccess);
+				break;
+			case EDriverLoadPartialSuccess:
+				res.Set(KDriverLoadPartialSuccess);
+				break;
+			case EDriverLoadFailure:
+				res.Set(KDriverLoadFailure);
+				break;
+			default:
+				PANIC;
+				break;
+				}
+//                                          7      8    6     3   5    1  1 -> 31
+			aEvent->iEvent.AppendFormat(_L("H:Load[%.08x] Err[%.3d] St[%1S]"), iDeviceInfo.iDeviceId, iDeviceInfo.iError, &res);
+			}
+		break;
+
+	case EDeviceDetachment:
+			{
+//											10        8	   1 -> 19
+			aEvent->iEvent.AppendFormat(_L("H:Detach [%.08x]"), iDeviceInfo.iDeviceId);
+			TInt ix = iAttachedDevices.Find(iDeviceInfo.iDeviceId);
+			if(ix == KErrNotFound)
+				{
+				// This is probably caused by starting a new instance of the test console.
+				break;
+				}
+			iAttachedDevices.Remove(ix);
+			iUsbViewer.SetDeviceType(CUsbViewer::ENoDevice);
+			}
+		break;
+	default:
+		PANIC;
+		break;
+		}
+	CleanupStack::Pop();
+	iUsbViewer.SetAttachedDevices(iAttachedDevices.Count());
+	iUsbViewer.NotifyEvent(aEvent);
+	iUsbViewer.Usb().HostEventNotification(iStatus, iDeviceInfo);
+	SetActive();
+	}
+	
+	
+CMessageWatcher* CMessageWatcher::NewL(CUsbViewer& aUsbViewer)
+	{
+	CMessageWatcher* self = new(ELeave) CMessageWatcher(aUsbViewer);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CMessageWatcher::~CMessageWatcher()
+	{
+	Cancel();
+	}
+
+CMessageWatcher::CMessageWatcher(CUsbViewer& aUsbViewer)
+	: CEventNotifier(EPriorityStandard)
+	, iUsbViewer(aUsbViewer)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+void CMessageWatcher::ConstructL()
+	{
+	iUsbViewer.Usb().MessageNotification(iStatus, iMessage);
+	SetActive();
+	}
+
+void CMessageWatcher::DoCancel()
+	{
+	iUsbViewer.Usb().MessageNotificationCancel();
+	}
+
+void CMessageWatcher::DoRunL(XUsbViewerEvent* aEvent)
+	{
+	TInt err = iStatus.Int();
+	
+	if (err)
+		{
+		aEvent->iEvent.AppendFormat(_L("O:Err! [%d] [%d]"), iMessage, err); // 32 chars max
+		}
+	else
+		{
+		TPtrC text(NULL, 0);
+
+		// OTGDI
+		_LIT(KMessOtgdiEventQueueOverflow,			"O:Event Queue Overflow"			);
+		_LIT(KMessOtgdiStateQueueOverflow,			"O:State Queue Overflow"			);
+		_LIT(KMessOtgdiMessageQueueOverflow,		"O:Message Queue Overflow"			);
+		_LIT(KMessOtgdiBadState,					"O:Bad State"						);
+		_LIT(KMessOtgdiStackNotStarted,				"O:Stack Not Started"				);
+		_LIT(KMessOtgdiVbusAlreadyRaised,			"O:VBUS Already Raised"				);
+		_LIT(KMessOtgdiSrpForbidden,				"O:SRP Forbidden"					);
+		_LIT(KMessOtgdiBusControlProblem,			"O:Bus Control Problem"				);
+		_LIT(KMessOtgdiVbusError,					"O:VBUS Error"						);
+		_LIT(KMessOtgdiSrpTimeout,					"O:SRP Timeout"						);
+		_LIT(KMessOtgdiSrpActive,					"O:SRP Already Active"				);
+		_LIT(KMessOtgdiSrpNotPermitted,				"O:SRP Not Permitted"				);
+		_LIT(KMessOtgdiHnpNotPermitted,				"O:HNP Not Permitted"				);
+		_LIT(KMessOtgdiHnpNotEnabled,				"O:HNP Not Enabled"					);
+		_LIT(KMessOtgdiHnpNotSuspended,				"O:HNP Not Suspended"				);
+		_LIT(KMessOtgdiVbusPowerUpNotPermitted,		"O:VBUS Power Up Not Permitted"		);
+		_LIT(KMessOtgdiVbusPowerDownNotPermitted,	"O:VBUS Power Down Not Permitted"	);
+		_LIT(KMessOtgdiVbusClearErrorNotPermitted,	"O:VBUS Clear Error Not Permitted"	);
+
+		// USBDI - Main
+
+		_LIT(KMessUsbdiRequestsPending,				"U:Requests Pending"				);		
+		_LIT(KMessUsbdiBadAddress,					"U:Bad Address"						);
+		_LIT(KMessUsbdiNoAddress,					"U:No Address"						);
+		_LIT(KMessUsbdiSetAddrFailed,				"U:Set Address Failed"				);
+		_LIT(KMessUsbdiNoPower,						"U:No Power"						);
+		_LIT(KMessUsbdiTooDeep,						"U:Too Deep"						);
+		_LIT(KMessUsbdiIOError,						"U:IO Error"						);
+		_LIT(KMessUsbdiNotConfigured,				"U:Not Configured"					);
+		_LIT(KMessUsbdiTimeout,						"U:Timeout"							);
+		_LIT(KMessUsbdiStalled,						"U:Stalled"							);
+		_LIT(KMessUsbdiTestFailure,					"U:Test Failure"					);
+		_LIT(KMessUsbdiBadState,					"U:Bad State"						);
+		_LIT(KMessUsbdiDeviceSuspended,				"U:Device Suspended"				);
+
+		// USBDI - Descriptors
+
+		_LIT(KMessUsbdiBadDescriptorTopology,		"U:Bad Descriptor Topology"			);
+
+		// USBDI - DevMon
+
+		_LIT(KMessUsbdiDeviceRejected,				"U:Device Rejected"					);
+		_LIT(KMessUsbdiDeviceFailed,				"U:Device failed"					);
+		_LIT(KMessUsbdiBadDevice,					"U:Bad Device"						);
+		_LIT(KMessUsbdiBadHubPosition,				"U:Bad Hub Position"				);
+		_LIT(KMessUsbdiBadHub,						"U:Bad Hub"							);
+		_LIT(KMessUsbdiEventOverflow,				"U:Event Overflow"					);
+		
+		// USBMAN
+		
+		_LIT(KMessUsbmanSrpInitiated,				"M:SRP Initiated"					);
+		_LIT(KMessUsbmanSrpReceived,				"M:SRP Received"					);
+		_LIT(KMessUsbmanHnpDisabled,				"M:HNP Disabled"					);
+		_LIT(KMessUsbmanHnpEnabled,					"M:HNP Enabled"						);
+		_LIT(KMessUsbmanVbusRaised,					"M:VBUS Raised"						);
+		_LIT(KMessUsbmanVbusDropped,				"M:VBUS Dropped"					);
+		_LIT(KMessUsbmanRequestSession,				"M:Request Session"					);
+
+		_LIT(KMessUnknown, 							"*:Unknown"							);
+
+		switch(iMessage)
+			{
+			// OTGDI
+
+			case KErrUsbOtgEventQueueOverflow:			text.Set(KMessOtgdiEventQueueOverflow);			break;
+			case KErrUsbOtgStateQueueOverflow:	       	text.Set(KMessOtgdiStateQueueOverflow);			break;
+			case KErrUsbOtgMessageQueueOverflow:		text.Set(KMessOtgdiMessageQueueOverflow)	;	break;
+			case KErrUsbOtgBadState:					text.Set(KMessOtgdiBadState);					break;		
+			case KErrUsbOtgStackNotStarted:				text.Set(KMessOtgdiStackNotStarted);			break;	
+			case KErrUsbOtgVbusAlreadyRaised:	       	text.Set(KMessOtgdiVbusAlreadyRaised);			break;
+			case KErrUsbOtgSrpForbidden:				text.Set(KMessOtgdiSrpForbidden);				break;	
+			case KErrUsbOtgBusControlProblem:	       	text.Set(KMessOtgdiBusControlProblem);			break;
+			case KErrUsbOtgVbusError:			       	text.Set(KMessOtgdiVbusError);					break;		
+			case KErrUsbOtgSrpTimeout:			       	text.Set(KMessOtgdiSrpTimeout);					break;		
+			case KErrUsbOtgSrpActive:			       	text.Set(KMessOtgdiSrpActive);					break;		
+			case KErrUsbOtgSrpNotPermitted:				text.Set(KMessOtgdiSrpNotPermitted);			break;
+			case KErrUsbOtgHnpNotPermitted:				text.Set(KMessOtgdiHnpNotPermitted);			break;
+			case KErrUsbOtgHnpNotEnabled:				text.Set(KMessOtgdiHnpNotEnabled);				break;
+			case KErrUsbOtgHnpNotSuspended:				text.Set(KMessOtgdiHnpNotSuspended);			break;
+			case KErrUsbOtgVbusPowerUpNotPermitted:  	text.Set(KMessOtgdiVbusPowerUpNotPermitted);	break;
+			case KErrUsbOtgVbusPowerDownNotPermitted:	text.Set(KMessOtgdiVbusPowerDownNotPermitted);	break;
+			case KErrUsbOtgVbusClearErrorNotPermitted:	text.Set(KMessOtgdiVbusClearErrorNotPermitted);	break;
+
+			// USBDI - Main
+
+			case KErrUsbRequestsPending:				text.Set(KMessUsbdiRequestsPending);			break;		
+			case KErrUsbBadAddress:						text.Set(KMessUsbdiBadAddress); 				break;			
+			case KErrUsbNoAddress:						text.Set(KMessUsbdiNoAddress); 					break;			
+			case KErrUsbSetAddrFailed:					text.Set(KMessUsbdiSetAddrFailed); 				break;		
+			case KErrUsbNoPower:						text.Set(KMessUsbdiNoPower); 					break;				
+			case KErrUsbTooDeep:						text.Set(KMessUsbdiTooDeep); 					break;				
+			case KErrUsbIOError:						text.Set(KMessUsbdiIOError); 					break;				
+			case KErrUsbNotConfigured:					text.Set(KMessUsbdiNotConfigured); 				break;		
+			case KErrUsbTimeout:						text.Set(KMessUsbdiTimeout); 					break;				
+			case KErrUsbStalled:						text.Set(KMessUsbdiStalled); 					break;				
+			case KErrUsbTestFailure:					text.Set(KMessUsbdiTestFailure); 				break;			
+			case KErrUsbBadState:						text.Set(KMessUsbdiBadState); 					break;			
+			case KErrUsbDeviceSuspended:				text.Set(KMessUsbdiDeviceSuspended); 			break;		
+																									
+			// USBDI - Descriptors																	
+			
+			case KErrUsbBadDescriptorTopology:			text.Set(KMessUsbdiBadDescriptorTopology); 		break;
+
+			// USBDI - DevMon
+			
+			case KErrUsbDeviceRejected:					text.Set(KMessUsbdiDeviceRejected); 			break;		
+			case KErrUsbDeviceFailed:					text.Set(KMessUsbdiDeviceFailed); 				break;		
+			case KErrUsbBadDevice:						text.Set(KMessUsbdiBadDevice); 					break;			
+			case KErrUsbBadHubPosition:					text.Set(KMessUsbdiBadHubPosition); 			break;		
+			case KErrUsbBadHub:							text.Set(KMessUsbdiBadHub); 					break;				
+			case KErrUsbEventOverflow:					text.Set(KMessUsbdiEventOverflow); 				break;		
+																										
+			// USBMAN																					
+																										
+			case KUsbMessageSrpInitiated:				text.Set(KMessUsbmanSrpInitiated);				break;
+			case KUsbMessageSrpReceived:				text.Set(KMessUsbmanSrpReceived);				break;
+			case KUsbMessageHnpDisabled:				text.Set(KMessUsbmanHnpDisabled);				break;
+			case KUsbMessageHnpEnabled:					text.Set(KMessUsbmanHnpEnabled);				break;
+			case KUsbMessageVbusRaised:					text.Set(KMessUsbmanVbusRaised);				break;
+			case KUsbMessageVbusDropped:				text.Set(KMessUsbmanVbusDropped);				break;
+			case KUsbMessageRequestSession:				text.Set(KMessUsbmanRequestSession);			break;
+																										
+			default:									text.Set(KMessUnknown);							break;
+			} // switch(iMessage)																							
+
+		// The message number can be positive (USBMAN) or negative (OTGDI/USBDI)
+		
+		LOG("CMessageWatcher::DoRunL iMessage = [%d]",iMessage);
+		LOG("CMessageWatcher::DoRunL text     = [%S]",&text);
+
+		if ( iMessage > 0 )
+			{
+			//								4   1 4   3   19  1 -> 32
+			aEvent->iEvent.AppendFormat(_L("Msg[+%4.4d] [%.19S]"), iMessage, &text); // 32 chars max
+			}
+		else
+			{
+			//								4   1 4   3   19  1 -> 32
+			aEvent->iEvent.AppendFormat(_L("Msg[-%4.4d] [%.19S]"), -iMessage, &text); // 32 chars max
+			}
+		} // else
+
+	iUsbViewer.Usb().MessageNotification(iStatus, iMessage);
+	SetActive();
+	iUsbViewer.NotifyEvent(aEvent);
+	}
+
+
+
+
+CUserMsgQWatcher* CUserMsgQWatcher::NewL(CUsbViewer& aUsbViewer)
+	{
+	CUserMsgQWatcher* self = new(ELeave) CUserMsgQWatcher(aUsbViewer);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CUserMsgQWatcher::~CUserMsgQWatcher()
+	{
+	Cancel();
+	}
+
+CUserMsgQWatcher::CUserMsgQWatcher(CUsbViewer& aUsbViewer)
+	: CEventNotifier(EPriorityStandard)
+	, iUsbViewer(aUsbViewer)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+void CUserMsgQWatcher::ConstructL()
+	{
+	iUsbViewer.UserMsgQ().NotifyDataAvailable(iStatus);
+	SetActive();
+	}
+
+void CUserMsgQWatcher::DoCancel()
+	{
+	iUsbViewer.UserMsgQ().CancelDataAvailable();
+	}
+
+void CUserMsgQWatcher::DoRunL(XUsbViewerEvent* aEvent)
+	{
+	CleanupStack::PushL(aEvent);
+
+	User::LeaveIfError(iUsbViewer.UserMsgQ().Receive(iUserMsgLine));
+	LOG("CUserMsgQWatcher::DoRunL		iUsbViewer.UserMsgQ().Receive => %S", &iUserMsgLine);
+	CleanupStack::Pop();
+
+	aEvent->iEvent.AppendFormat(_L("%S"), &iUserMsgLine);
+	iUsbViewer.NotifyEvent(aEvent);
+
+	iUsbViewer.UserMsgQ().NotifyDataAvailable(iStatus); // Re-subscribe
+	SetActive();
+	}
+