os/kernelhwsrv/userlibandfileserver/fileserver/shostmassstorage/server/controller/cusbhostmsdevice.cpp
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/userlibandfileserver/fileserver/shostmassstorage/server/controller/cusbhostmsdevice.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,345 @@
1.4 +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +/**
1.20 + @file
1.21 + @internalTechnology
1.22 +*/
1.23 +
1.24 +#include <e32base.h>
1.25 +#include <d32usbdi.h>
1.26 +
1.27 +#include <d32usbtransfers.h>
1.28 +#include "msctypes.h"
1.29 +#include "shared.h"
1.30 +#include "msgservice.h"
1.31 +#include "botmsctypes.h"
1.32 +#include "mprotocol.h"
1.33 +#include "mtransport.h"
1.34 +#include "cbulkonlytransport.h"
1.35 +#include "cusbhostmslogicalunit.h"
1.36 +#include "cusbhostmsdevice.h"
1.37 +#include "cusbmssuspendresume.h"
1.38 +
1.39 +#include "msdebug.h"
1.40 +#include "debug.h"
1.41 +
1.42 +
1.43 +CUsbHostMsDevice* CUsbHostMsDevice::NewL(THostMassStorageConfig& aConfig)
1.44 + {
1.45 + __MSFNSLOG
1.46 + CUsbHostMsDevice* r = new (ELeave) CUsbHostMsDevice(aConfig);
1.47 + CleanupStack::PushL(r);
1.48 + r->ConstructL();
1.49 + CleanupStack::Pop();
1.50 + return r;
1.51 + }
1.52 +
1.53 +void CUsbHostMsDevice::ConstructL()
1.54 + {
1.55 + __MSFNLOG
1.56 + iTimer = CPeriodic::NewL(CActive::EPriorityStandard);
1.57 + iTimerRunning = EFalse;
1.58 + }
1.59 +
1.60 +
1.61 +CUsbHostMsDevice::CUsbHostMsDevice(THostMassStorageConfig& aConfig)
1.62 +: iConfig(aConfig),
1.63 + iState(EReady)
1.64 + {
1.65 + __MSFNLOG
1.66 + }
1.67 +
1.68 +
1.69 +CUsbHostMsDevice::~CUsbHostMsDevice()
1.70 + {
1.71 + __MSFNLOG
1.72 + delete iTransport;
1.73 + delete iDeviceSuspendResume;
1.74 + if (iTimer && iTimerRunning)
1.75 + {
1.76 + iTimer->Cancel();
1.77 + }
1.78 + delete iTimer;
1.79 + }
1.80 +
1.81 +
1.82 +MTransport* CUsbHostMsDevice::InitialiseTransportL(TTransportType aTransportId)
1.83 + {
1.84 + __MSFNLOG
1.85 + switch(aTransportId)
1.86 + {
1.87 + case BulkOnlyTransport:
1.88 + return CBulkOnlyTransport::NewL(iConfig.iInterfaceToken);
1.89 + default:
1.90 + // Panic;
1.91 + __HOSTPRINT(_L("Unsupported Transport class requested"));
1.92 + User::Leave(KErrNotSupported);
1.93 + return NULL;
1.94 + }
1.95 + }
1.96 +
1.97 +void CUsbHostMsDevice::InitialiseL(const RMessage2& aMessage)
1.98 + {
1.99 + __MSFNLOG
1.100 + iTransport = InitialiseTransportL((TTransportType) iConfig.iTransportId);
1.101 + TRAPD(r, iDeviceSuspendResume = CUsbMsIfaceSuspendResume::NewL(iTransport, this));
1.102 + if(r != KErrNone)
1.103 + {
1.104 + delete iTransport;
1.105 + User::Leave(r);
1.106 + }
1.107 + iTransport->GetMaxLun(&iMaxLun, aMessage);
1.108 + }
1.109 +
1.110 +
1.111 +void CUsbHostMsDevice::UnInitialiseL()
1.112 + {
1.113 + __MSFNLOG
1.114 + StopTimer();
1.115 + iLuList.RemoveAllLuL();
1.116 + }
1.117 +
1.118 +
1.119 +TInt CUsbHostMsDevice::AddLunL(TLun aLun)
1.120 + {
1.121 + __MSFNLOG
1.122 + TInt r = KErrNone;
1.123 + StartTimer();
1.124 + CUsbHostMsLogicalUnit* lu = CUsbHostMsLogicalUnit::NewL(aLun);
1.125 + CleanupStack::PushL(lu);
1.126 +
1.127 + TRAP(r, lu->InitialiseProtocolL(aLun, iConfig, *iTransport));
1.128 +
1.129 + if (r == KErrNone)
1.130 + {
1.131 + TRAP(r, iLuList.AddLuL(lu));
1.132 + }
1.133 +
1.134 + if (r != KErrNone)
1.135 + {
1.136 + CleanupStack::PopAndDestroy(lu);
1.137 + }
1.138 + else
1.139 + {
1.140 + CleanupStack::Pop(lu);
1.141 + }
1.142 + return r;
1.143 + }
1.144 +
1.145 +
1.146 +void CUsbHostMsDevice::RemoveLunL(TLun aLun)
1.147 + {
1.148 + __MSFNLOG
1.149 + if(iLuList.Count() <= 1)
1.150 + StopTimer();
1.151 + iLuList.RemoveLuL(aLun);
1.152 + }
1.153 +
1.154 +
1.155 +void CUsbHostMsDevice::InitLunL(TLun aLun)
1.156 + {
1.157 + __MSFNLOG
1.158 + SetLunL(aLun);
1.159 + iLuList.GetLuL(aLun).InitL();
1.160 + }
1.161 +
1.162 +
1.163 +void CUsbHostMsDevice::SuspendLunL(TLun aLun)
1.164 + {
1.165 + __MSFNLOG
1.166 + iLuList.GetLuL(aLun).ReadyToSuspend();
1.167 +
1.168 + // check whether all the luns are suspended, if so then request usb
1.169 + // interface suspension to the transport layer
1.170 + for (TInt i = 0; i < iLuList.Count(); i++)
1.171 + {
1.172 + CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i);
1.173 + if (!lu.IsReadyToSuspend() && lu.IsConnected())
1.174 + return;
1.175 + }
1.176 +
1.177 + for (TInt i = 0; i < iLuList.Count(); i++)
1.178 + {
1.179 + CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i);
1.180 + SetLunL(lu.Lun());
1.181 + lu.SuspendL();
1.182 + }
1.183 +
1.184 + StopTimer();
1.185 + iDeviceSuspendResume->Suspend();
1.186 + iState = ESuspended;
1.187 + }
1.188 +
1.189 +
1.190 +void CUsbHostMsDevice::Resume(TRequestStatus& aStatus)
1.191 + {
1.192 + __MSFNLOG
1.193 + if (iState == ESuspended)
1.194 + {
1.195 + StartTimer();
1.196 + iDeviceSuspendResume->Resume(aStatus);
1.197 + }
1.198 + }
1.199 +
1.200 +
1.201 +TLun CUsbHostMsDevice::GetAndSetLunL(const RMessage2& aMessage)
1.202 + {
1.203 + __MSFNLOG
1.204 + // Subssessions need a positive value to store in the handles. We represent Luns as LunId+1
1.205 + // We represent LunId in MSC from 0 to MaxLun-1 as represented in BOT so subtract 1 from the Id
1.206 + // received from RMessage
1.207 +
1.208 + TInt lun = aMessage.Int3() - 1;
1.209 + if (lun < 0)
1.210 + {
1.211 + User::Leave(KErrArgument);
1.212 + }
1.213 + SetLunL(static_cast<TLun>(lun));
1.214 + return static_cast<TLun>(lun);
1.215 + }
1.216 +
1.217 +
1.218 +CUsbHostMsLogicalUnit& CUsbHostMsDevice::GetLuL(TInt aLunNum) const
1.219 + {
1.220 + return iLuList.GetLuL(aLunNum);
1.221 + }
1.222 +
1.223 +void CUsbHostMsDevice::SetLunL(TLun aLun)
1.224 + {
1.225 + __MSFNLOG
1.226 + if (aLun <= iMaxLun)
1.227 + {
1.228 + __HOSTPRINT1(_L("SetLun %d"), aLun);
1.229 + iTransport->SetLun(aLun);
1.230 + CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(aLun);
1.231 + if (lu.IsReadyToSuspend())
1.232 + {
1.233 + lu.CancelReadyToSuspend();
1.234 + }
1.235 + }
1.236 + }
1.237 +
1.238 +/**
1.239 +Starts timer to periodically check LUN. If the timer is not yet running then
1.240 +start it.
1.241 +*/
1.242 +void CUsbHostMsDevice::StartTimer()
1.243 + {
1.244 + __MSFNLOG
1.245 + if (!iTimerRunning)
1.246 + {
1.247 + // Period of the LUN Ready check
1.248 + const TTimeIntervalMicroSeconds32 KInterval = iConfig.iStatusPollingInterval * 1000 * 1000;
1.249 + TCallBack callback(TimerCallback, this);
1.250 + __HOSTPRINT(_L("Starting timer"));
1.251 + iTimer->Start(KInterval, KInterval, callback);
1.252 + iTimerRunning = ETrue;
1.253 + }
1.254 + }
1.255 +
1.256 +
1.257 +/**
1.258 +Ensure that the Timer is stopped
1.259 +*/
1.260 +void CUsbHostMsDevice::StopTimer()
1.261 + {
1.262 + __MSFNLOG
1.263 + if (iTimer && iTimerRunning)
1.264 + {
1.265 + __HOSTPRINT(_L("Stopping timer"));
1.266 + if (iTimer->IsActive())
1.267 + {
1.268 + iTimer->Cancel();
1.269 + }
1.270 + iTimerRunning = EFalse;
1.271 + }
1.272 + }
1.273 +
1.274 +/**
1.275 +A static wrapper for the DoLunReadyCheckEvent member function for use as a timer
1.276 +callback function.
1.277 +
1.278 +@param obj 'this' pointer
1.279 +@return not used in CPeriodic callback (see TCallback)
1.280 +*/
1.281 +TInt CUsbHostMsDevice::TimerCallback(TAny* obj)
1.282 + {
1.283 + __MSFNSLOG
1.284 + CUsbHostMsDevice* device = static_cast<CUsbHostMsDevice*>(obj);
1.285 + TRAPD(err, device->DoLunReadyCheckEventL());
1.286 + return err;
1.287 + }
1.288 +
1.289 +void CUsbHostMsDevice::DoLunReadyCheckEventL()
1.290 + {
1.291 + __MSFNLOG
1.292 + TInt err;
1.293 + for (TInt i = 0; i < iLuList.Count(); i++)
1.294 + {
1.295 + CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i);
1.296 + SetLunL(lu.Lun());
1.297 + TRAP(err, lu.DoLunReadyCheckL());
1.298 + }
1.299 + }
1.300 +
1.301 +void CUsbHostMsDevice::DoHandleRemoteWakeupL()
1.302 + {
1.303 + __MSFNLOG
1.304 + DoResumeLogicalUnitsL();
1.305 + DoLunReadyCheckEventL(); // For remote wakeup we do not wait for timer to expire
1.306 +
1.307 + // check whether all the luns are suspended, if so then request usb
1.308 + // interface suspension to the transport layer
1.309 + for (TInt i = 0; i < iLuList.Count(); i++)
1.310 + {
1.311 + CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i);
1.312 + // Has any of the logical units have got its state changed?
1.313 + if ( (lu.IsReadyToSuspend() && !lu.IsConnected()) ||
1.314 + (!lu.IsReadyToSuspend() && lu.IsConnected()) )
1.315 + {
1.316 + StartTimer(); // Now start the timer
1.317 + return;
1.318 + }
1.319 + }
1.320 +
1.321 + for (TInt i = 0; i < iLuList.Count(); i++)
1.322 + {
1.323 + CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i);
1.324 + SetLunL(lu.Lun());
1.325 + lu.SuspendL();
1.326 + }
1.327 +
1.328 + iDeviceSuspendResume->Suspend();
1.329 + iState = ESuspended;
1.330 + }
1.331 +
1.332 +void CUsbHostMsDevice::DoResumeLogicalUnitsL()
1.333 + {
1.334 + __MSFNLOG
1.335 + for (TInt i = 0; i < iLuList.Count(); i++)
1.336 + {
1.337 + CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i);
1.338 + SetLunL(lu.Lun());
1.339 + lu.ResumeL();
1.340 + }
1.341 + }
1.342 +
1.343 +void CUsbHostMsDevice::ResumeCompletedL()
1.344 + {
1.345 + __MSFNLOG
1.346 + iState = EReady;
1.347 + DoResumeLogicalUnitsL();
1.348 + }