usbmgmt/usbmgrtest/t_usb_cable_detect/src/t_usb_cable_detect.cpp
changeset 0 c9bc50fca66e
child 25 4ddb65515edd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbmgmt/usbmgrtest/t_usb_cable_detect/src/t_usb_cable_detect.cpp	Tue Feb 02 02:02:59 2010 +0200
@@ -0,0 +1,311 @@
+/*
+* Copyright (c) 2003-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:
+* This is a simple program which demonstrates how to start USB services when
+* the cable is plugged in, and stop them when it's unplugged. A couple of
+* caveats:
+* 1. This mechanism will only work on certain hardware platforms (eg. Lubbock).
+* 2. The USB Manager will be loaded for the lifetime of this program.
+*
+*/
+
+#include <e32base.h>
+#include <e32math.h>
+#include <e32cons.h>
+#include <badesca.h>
+#include <c32comm.h>
+#include <usbman.h>
+
+// The name of the logical device driver to load.
+_LIT(KUsbLddName, "EUSBC");
+
+// An argument which, when passed to this program, means "don't run another
+// instance of yourself in the background".
+_LIT(KForkFlag, "f");
+
+class CUsbCableDetector : public CActive
+/**
+ * This class provides a USB cable detection service. It monitors the state of
+ * the USB cable and starts and stops USB services appropriately.
+ */
+	{
+public:
+	enum TReqState
+		{
+		EIdle = 0,
+		ENotifyDeviceStateChange,
+		EStart,
+		EStop
+		};
+
+	static CUsbCableDetector* NewL();
+	static CUsbCableDetector* NewLC();
+	virtual ~CUsbCableDetector();
+
+	void CheckAndMonitorCableL();
+	void MonitorCable();
+	void RunL();
+
+protected:
+	CUsbCableDetector();
+	void ConstructL();
+
+	void DoCancel();
+	TInt RunError(TInt aError);
+
+private:
+	RUsb iUsbMan;
+	TUsbDeviceState iDeviceState;
+	TReqState iReqState;
+	};
+
+
+CUsbCableDetector::CUsbCableDetector()
+	: CActive(EPriorityStandard)
+/**
+ * Constructor. Performs standard active object setup.
+ */
+	{
+	CActiveScheduler::Add(this);
+	}
+
+CUsbCableDetector* CUsbCableDetector::NewLC()
+/**
+ * Factory function which leaves the new object on the cleanup stack.
+ *
+ * @return a new CUsbCableDetector which is still on the cleanup stack
+ */
+	{
+	CUsbCableDetector* self = new (ELeave) CUsbCableDetector;
+	CleanupStack::PushL(self);
+	self->ConstructL();
+
+	return self;
+	}
+
+CUsbCableDetector* CUsbCableDetector::NewL()
+/**
+ * Factory function.
+ *
+ * @return a new CUsbCableDetector
+ */
+	{
+	CUsbCableDetector* self = CUsbCableDetector::NewLC();
+	CleanupStack::Pop(self);
+
+	return self;
+	}
+
+void CUsbCableDetector::ConstructL()
+/**
+ * Connects to the USB Manager and gets the current device state.
+ */
+	{
+	User::LeaveIfError(iUsbMan.Connect());
+	User::LeaveIfError(iUsbMan.GetDeviceState(iDeviceState));
+	}
+
+CUsbCableDetector::~CUsbCableDetector()
+/**
+ * Destructor. Cleans up all resources.
+ */
+	{
+	Cancel();
+	iUsbMan.Close();
+	}
+
+void CUsbCableDetector::CheckAndMonitorCableL()
+/**
+ * Checks that the current USB service state is consistent with the state of
+ * the cable. If the cable is unplugged and USB services are started, we want
+ * to stop them. If the cable is plugged in and USB services are stopped, we
+ * want to stop them. In any other situation, we just want to go on monitoring.
+ */
+	{
+	TUsbServiceState serviceState;
+	User::LeaveIfError(iUsbMan.GetServiceState(serviceState));
+
+//	RDebug::Print(_L("Service state: %d. Device state: %d"), serviceState, iDeviceState);
+
+	if ((serviceState != EUsbServiceIdle) &&
+		(iDeviceState == EUsbDeviceStateUndefined))
+		{
+		iReqState = EStop;
+		iUsbMan.Stop(iStatus);
+		SetActive();
+		}
+	else if ((serviceState != EUsbServiceStarted) &&
+		(iDeviceState != EUsbDeviceStateUndefined))
+		{
+		iReqState = EStart;
+		iUsbMan.Start(iStatus);
+		SetActive();
+		}
+	else
+		{
+		MonitorCable();
+		}
+	}
+
+void CUsbCableDetector::MonitorCable()
+/**
+ * Requests a notification from the USB Manager when the device state changes.
+ */
+	{
+	iReqState = ENotifyDeviceStateChange;
+	iUsbMan.DeviceStateNotification(KMaxTInt, iDeviceState, iStatus);
+	SetActive();
+	}
+
+void CUsbCableDetector::RunL()
+/**
+ * An asynchronous request has completed. The way we handle this depends on our
+ * current state.
+ */
+	{
+	User::LeaveIfError(iStatus.Int());
+
+	switch (iReqState)
+		{
+	case ENotifyDeviceStateChange:
+		CheckAndMonitorCableL();
+		break;
+
+	case EStart:
+	case EStop:
+		MonitorCable();
+		break;
+
+	default:
+		break;
+		}
+	}
+
+void CUsbCableDetector::DoCancel()
+/**
+ * Cancels the current asynchronous request.
+ */
+	{
+	switch (iReqState)
+		{
+	case ENotifyDeviceStateChange:
+		iUsbMan.DeviceStateNotificationCancel();
+		break;
+
+	case EStart:
+		iUsbMan.StartCancel();
+		break;
+
+	case EStop:
+		iUsbMan.StopCancel();
+		break;
+
+	default:
+		break;
+		}
+	}
+
+TInt CUsbCableDetector::RunError(TInt /*aError*/)
+/**
+ * Error handler. Stops the active scheduler, which will cause this program to
+ * terminate.
+ *
+ * @param aError Unused
+ * @return Always KErrNone to avoid a panic
+ */
+	{
+	CActiveScheduler::Stop();
+	return KErrNone;
+	}
+
+
+void UsbCableDetectL()
+/**
+ * Starts USB cable detection. This function will never return unless an error
+ * occurs.
+ */
+	{
+	TInt ret;
+
+	// Load the USB logical device driver.
+	ret = User::LoadLogicalDevice(KUsbLddName);
+	if ((ret != KErrNone) && (ret != KErrAlreadyExists))
+		User::Leave(ret);
+
+	// Start the C32 process (in which the USB Manager currently lives).
+	ret = StartC32();
+	if ((ret != KErrNone) && (ret != KErrAlreadyExists))
+		User::Leave(ret);
+
+	// Create an active scheduler for the cable detector object.
+	CActiveScheduler* scheduler = new (ELeave) CActiveScheduler;
+	CleanupStack::PushL(scheduler);
+
+	CActiveScheduler::Install(scheduler);
+
+	// Prepare to start monitoring cable state.
+	CUsbCableDetector* cableDetector = CUsbCableDetector::NewLC();
+	cableDetector->CheckAndMonitorCableL();
+
+	// Action!
+	CActiveScheduler::Start();
+
+	// Clean everything up. We'll only get here if an error occurred.
+	CleanupStack::PopAndDestroy(2); // scheduler, cableDetector
+	}
+
+void mainL()
+/**
+ * Main function. If run without any arguments, creates another instance of
+ * this process with an argument which signifies that it should start cable
+ * detection. This allows the program to be fired off from the command-line.
+ */
+	{
+	RProcess thisProcess;
+
+	// Create a buffer big enough for the command-line arguments.
+	HBufC* commandLine = HBufC::NewLC(User::CommandLineLength());
+	TPtr commandLinePtr = commandLine->Des();
+	
+	// Get the command-line arguments.
+	User::CommandLine(commandLinePtr);
+
+	if (commandLinePtr == KForkFlag)
+		{
+		UsbCableDetectL();
+		}
+	else
+		{
+		thisProcess.Create(thisProcess.FileName(), KForkFlag);
+		thisProcess.Resume();
+		}
+
+	CleanupStack::PopAndDestroy(commandLine);
+	}
+
+GLDEF_C TInt E32Main()
+/**
+ * Symbian OS entry point. Creates a cleanup stack and runs the rest of the
+ * program.
+ *
+ * @return Always 0
+ */
+	{
+	__UHEAP_MARK;
+	CTrapCleanup* cleanupStack=CTrapCleanup::New();
+	TRAP_IGNORE(mainL());
+	delete cleanupStack;
+	__UHEAP_MARKEND;
+	return 0;
+	}