diff -r 000000000000 -r bde4ae8d615e os/kernelhwsrv/userlibandfileserver/fileserver/shostmassstorage/server/controller/cusbhostmsdevice.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/kernelhwsrv/userlibandfileserver/fileserver/shostmassstorage/server/controller/cusbhostmsdevice.cpp Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,345 @@ +// 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 +#include + +#include +#include "msctypes.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(EReady) + { + __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; + } + + +void CUsbHostMsDevice::Resume(TRequestStatus& aStatus) + { + __MSFNLOG + if (iState == ESuspended) + { + StartTimer(); + iDeviceSuspendResume->Resume(aStatus); + } + } + + +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(lun)); + return static_cast(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(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 = EReady; + DoResumeLogicalUnitsL(); + }