author | Arnaud Lenoir |
Thu, 18 Mar 2010 15:26:01 +0000 | |
branch | RCL_3 |
changeset 79 | 5e2688cee105 |
parent 31 | 56f325a607ea |
child 97 | 41f0cfe18c80 |
permissions | -rw-r--r-- |
// 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 <d32usbdi.h> #include <d32usbtransfers.h> #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<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 = EReady; DoResumeLogicalUnitsL(); }