userlibandfileserver/fileserver/shostmassstorage/server/controller/cusbhostmsdevice.cpp
changeset 0 a41df078684a
child 31 56f325a607ea
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/userlibandfileserver/fileserver/shostmassstorage/server/controller/cusbhostmsdevice.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,363 @@
+// 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 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:
+//
+
+/**
+ @file
+ @internalTechnology
+*/
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <d32usbdi.h>
+
+#include <d32usbtransfers.h>
+#include "msctypes.h"
+#include "mscutils.h"
+#include "shared.h"
+#include "msgservice.h"
+#include "botmsctypes.h"
+#include "mprotocol.h"
+#include "mtransport.h"
+#include "cbulkonlytransport.h"
+#include "cusbhostmslogicalunit.h"
+#include "cusbhostmsdevice.h"
+#include "cusbmssuspendresume.h"
+
+#include "msdebug.h"
+#include "debug.h"
+
+
+CUsbHostMsDevice* CUsbHostMsDevice::NewL(THostMassStorageConfig& aConfig)
+    {
+    __MSFNSLOG
+	CUsbHostMsDevice* r = new (ELeave) CUsbHostMsDevice(aConfig);
+	CleanupStack::PushL(r);
+	r->ConstructL();
+	CleanupStack::Pop();
+	return r;
+	}
+
+void CUsbHostMsDevice::ConstructL()
+    {
+    __MSFNLOG
+	iTimer = CPeriodic::NewL(CActive::EPriorityStandard);
+	iTimerRunning = EFalse;
+    }
+
+
+CUsbHostMsDevice::CUsbHostMsDevice(THostMassStorageConfig& aConfig)
+:	iConfig(aConfig),
+	iState(EActive)
+    {
+    __MSFNLOG
+
+	}
+
+
+CUsbHostMsDevice::~CUsbHostMsDevice()
+    {
+    __MSFNLOG
+	delete iTransport;
+	delete iDeviceSuspendResume;
+	if (iTimer && iTimerRunning)
+		{
+		iTimer->Cancel();
+		}
+	delete iTimer;
+	}
+
+
+MTransport* CUsbHostMsDevice::InitialiseTransportL(TTransportType aTransportId)
+    {
+    __MSFNLOG
+	switch(aTransportId)
+        {
+	case BulkOnlyTransport:
+		return CBulkOnlyTransport::NewL(iConfig.iInterfaceToken);
+	default:
+	//		Panic;
+		__HOSTPRINT(_L("Unsupported Transport class requested"));
+		User::Leave(KErrNotSupported);
+		return NULL;
+        }
+    }
+
+void CUsbHostMsDevice::InitialiseL(const RMessage2& aMessage)
+	{
+    __MSFNLOG
+	iTransport = InitialiseTransportL((TTransportType) iConfig.iTransportId);
+	TRAPD(r, iDeviceSuspendResume = CUsbMsIfaceSuspendResume::NewL(iTransport, this));
+	if(r != KErrNone)
+		{
+		delete iTransport;
+		User::Leave(r);
+		}
+	iTransport->GetMaxLun(&iMaxLun, aMessage);
+	}
+
+
+void CUsbHostMsDevice::UnInitialiseL()
+    {
+    __MSFNLOG
+	StopTimer();
+    iLuList.RemoveAllLuL();
+    }
+
+
+TInt CUsbHostMsDevice::AddLunL(TLun aLun)
+    {
+    __MSFNLOG
+    TInt r = KErrNone;
+	StartTimer();
+    CUsbHostMsLogicalUnit* lu = CUsbHostMsLogicalUnit::NewL(aLun);
+    CleanupStack::PushL(lu);
+
+    TRAP(r, lu->InitialiseProtocolL(aLun, iConfig, *iTransport));
+
+	if (r == KErrNone)
+		{
+		TRAP(r, iLuList.AddLuL(lu));
+		}
+
+    if (r != KErrNone)
+        {
+        CleanupStack::PopAndDestroy(lu);
+        }
+    else
+        {
+        CleanupStack::Pop(lu);
+        }
+    return r;
+    }
+
+
+void CUsbHostMsDevice::RemoveLunL(TLun aLun)
+    {
+    __MSFNLOG
+	if(iLuList.Count() <= 1)
+		StopTimer();
+	iLuList.RemoveLuL(aLun);
+    }
+
+
+void CUsbHostMsDevice::InitLunL(TLun aLun)
+	{
+    __MSFNLOG
+	SetLunL(aLun);
+    iLuList.GetLuL(aLun).InitL();
+	}
+
+
+void CUsbHostMsDevice::SuspendLunL(TLun aLun)
+	{
+    __MSFNLOG
+	iLuList.GetLuL(aLun).ReadyToSuspend();
+
+    // check whether all the luns are suspended, if so then request usb
+    // interface suspension to the transport layer
+	for (TInt i = 0; i < iLuList.Count(); i++)
+		{
+		CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i);
+	   	if (!lu.IsReadyToSuspend() && lu.IsConnected())
+	   		return;
+		}
+
+	for (TInt i = 0; i < iLuList.Count(); i++)
+		{
+		CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i);
+		SetLunL(lu.Lun());
+		lu.SuspendL();
+		}
+
+	StopTimer();
+	iDeviceSuspendResume->Suspend();
+	iState = ESuspended;
+	}
+
+TBool CUsbHostMsDevice::IsActive()
+	{
+    __MSFNLOG
+	return (iState == EActive)? ETrue : EFalse;
+	}
+
+TBool CUsbHostMsDevice::IsSuspended()
+	{
+    __MSFNLOG
+	return (iState == ESuspended)? ETrue : EFalse;
+	}
+
+void CUsbHostMsDevice::ResumeL(TRequestStatus &aStatus)
+	{
+    __MSFNLOG
+	if (iState == ESuspended)
+		{
+		StartTimer();
+		iDeviceSuspendResume->Resume(aStatus);
+		}
+	else
+		{
+        __HOSTPRINT(_L("CUsbHostMsDevice: Wierd we are not suspended but were asked to resume"));
+		}
+	}
+
+
+TLun CUsbHostMsDevice::GetAndSetLunL(const RMessage2& aMessage)
+	{
+    __MSFNLOG
+	// Subssessions need a positive value to store in the handles. We represent Luns as LunId+1
+	// We represent LunId in MSC from 0 to MaxLun-1 as represented in BOT so subtract 1 from the Id
+    // received from RMessage
+
+    TInt lun = aMessage.Int3() - 1;
+    if (lun < 0)
+        {
+        User::Leave(KErrArgument);
+        }
+	SetLunL(static_cast<TLun>(lun));
+	return static_cast<TLun>(lun);
+	}
+
+
+CUsbHostMsLogicalUnit& CUsbHostMsDevice::GetLuL(TInt aLunNum) const
+    {
+    return iLuList.GetLuL(aLunNum);
+    }
+
+void CUsbHostMsDevice::SetLunL(TLun aLun)
+	{
+    __MSFNLOG
+	if (aLun <= iMaxLun)
+        {
+        __HOSTPRINT1(_L("SetLun %d"), aLun);
+        iTransport->SetLun(aLun);
+        CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(aLun);
+		if (lu.IsReadyToSuspend())
+			{
+			lu.CancelReadyToSuspend();
+			}
+		}
+	}
+
+/**
+Starts timer to periodically check LUN. If the timer is not yet running then
+start it.
+*/
+void CUsbHostMsDevice::StartTimer()
+	{
+    __MSFNLOG
+	if (!iTimerRunning)
+		{
+		// Period of the LUN Ready check
+		const TTimeIntervalMicroSeconds32 KInterval = iConfig.iStatusPollingInterval * 1000 * 1000;
+		TCallBack callback(TimerCallback, this);
+		__HOSTPRINT(_L("Starting timer"));
+		iTimer->Start(KInterval, KInterval, callback);
+		iTimerRunning = ETrue;
+		}
+	}
+
+
+/**
+Ensure that the Timer is stopped
+*/
+void CUsbHostMsDevice::StopTimer()
+	{
+    __MSFNLOG
+	if (iTimer && iTimerRunning)
+		{
+		__HOSTPRINT(_L("Stopping timer"));
+		if (iTimer->IsActive())
+			{
+			iTimer->Cancel();
+			}
+		iTimerRunning = EFalse;
+		}
+	}
+
+/**
+A static wrapper for the DoLunReadyCheckEvent member function for use as a timer
+callback function.
+
+@param obj 'this' pointer
+@return not used in CPeriodic callback (see TCallback)
+*/
+TInt CUsbHostMsDevice::TimerCallback(TAny* obj)
+	{
+    __MSFNSLOG
+    CUsbHostMsDevice* device = static_cast<CUsbHostMsDevice*>(obj);
+	TRAPD(err, device->DoLunReadyCheckEventL());
+	return err;
+	}
+
+void CUsbHostMsDevice::DoLunReadyCheckEventL()
+	{
+    __MSFNLOG
+	TInt err;
+	for (TInt i = 0; i < iLuList.Count(); i++)
+		{
+		CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i);
+		SetLunL(lu.Lun());
+		TRAP(err, lu.DoLunReadyCheckL());
+		}
+	}
+
+void CUsbHostMsDevice::DoHandleRemoteWakeupL()
+	{
+    __MSFNLOG
+	DoResumeLogicalUnitsL();
+	DoLunReadyCheckEventL();	// For remote wakeup we do not wait for timer to expire
+
+    // check whether all the luns are suspended, if so then request usb
+    // interface suspension to the transport layer
+	for (TInt i = 0; i < iLuList.Count(); i++)
+		{
+		CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i);
+		// Has any of the logical units have got its state changed?
+	   	if ( (lu.IsReadyToSuspend() && !lu.IsConnected()) ||
+				(!lu.IsReadyToSuspend() && lu.IsConnected()) )
+			{
+			StartTimer(); // Now start the timer
+	   		return;
+			}
+		}
+
+	for (TInt i = 0; i < iLuList.Count(); i++)
+		{
+		CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i);
+		SetLunL(lu.Lun());
+		lu.SuspendL();
+		}
+
+	iDeviceSuspendResume->Suspend();
+	iState = ESuspended;
+	}
+
+void CUsbHostMsDevice::DoResumeLogicalUnitsL()
+	{
+    __MSFNLOG
+	for (TInt i = 0; i < iLuList.Count(); i++)
+		{
+		CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i);
+		SetLunL(lu.Lun());
+		lu.ResumeL();
+		}
+	}
+
+void CUsbHostMsDevice::ResumeCompletedL()
+	{
+    __MSFNLOG
+	iState = EActive;
+	DoResumeLogicalUnitsL();
+	}