userlibandfileserver/fileserver/shostmassstorage/server/controller/cusbhostmsdevice.cpp
changeset 0 a41df078684a
child 4 56f325a607ea
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 /**
       
    17  @file
       
    18  @internalTechnology
       
    19 */
       
    20 
       
    21 #include <e32base.h>
       
    22 #include <e32base_private.h>
       
    23 #include <d32usbdi.h>
       
    24 
       
    25 #include <d32usbtransfers.h>
       
    26 #include "msctypes.h"
       
    27 #include "mscutils.h"
       
    28 #include "shared.h"
       
    29 #include "msgservice.h"
       
    30 #include "botmsctypes.h"
       
    31 #include "mprotocol.h"
       
    32 #include "mtransport.h"
       
    33 #include "cbulkonlytransport.h"
       
    34 #include "cusbhostmslogicalunit.h"
       
    35 #include "cusbhostmsdevice.h"
       
    36 #include "cusbmssuspendresume.h"
       
    37 
       
    38 #include "msdebug.h"
       
    39 #include "debug.h"
       
    40 
       
    41 
       
    42 CUsbHostMsDevice* CUsbHostMsDevice::NewL(THostMassStorageConfig& aConfig)
       
    43     {
       
    44     __MSFNSLOG
       
    45 	CUsbHostMsDevice* r = new (ELeave) CUsbHostMsDevice(aConfig);
       
    46 	CleanupStack::PushL(r);
       
    47 	r->ConstructL();
       
    48 	CleanupStack::Pop();
       
    49 	return r;
       
    50 	}
       
    51 
       
    52 void CUsbHostMsDevice::ConstructL()
       
    53     {
       
    54     __MSFNLOG
       
    55 	iTimer = CPeriodic::NewL(CActive::EPriorityStandard);
       
    56 	iTimerRunning = EFalse;
       
    57     }
       
    58 
       
    59 
       
    60 CUsbHostMsDevice::CUsbHostMsDevice(THostMassStorageConfig& aConfig)
       
    61 :	iConfig(aConfig),
       
    62 	iState(EActive)
       
    63     {
       
    64     __MSFNLOG
       
    65 
       
    66 	}
       
    67 
       
    68 
       
    69 CUsbHostMsDevice::~CUsbHostMsDevice()
       
    70     {
       
    71     __MSFNLOG
       
    72 	delete iTransport;
       
    73 	delete iDeviceSuspendResume;
       
    74 	if (iTimer && iTimerRunning)
       
    75 		{
       
    76 		iTimer->Cancel();
       
    77 		}
       
    78 	delete iTimer;
       
    79 	}
       
    80 
       
    81 
       
    82 MTransport* CUsbHostMsDevice::InitialiseTransportL(TTransportType aTransportId)
       
    83     {
       
    84     __MSFNLOG
       
    85 	switch(aTransportId)
       
    86         {
       
    87 	case BulkOnlyTransport:
       
    88 		return CBulkOnlyTransport::NewL(iConfig.iInterfaceToken);
       
    89 	default:
       
    90 	//		Panic;
       
    91 		__HOSTPRINT(_L("Unsupported Transport class requested"));
       
    92 		User::Leave(KErrNotSupported);
       
    93 		return NULL;
       
    94         }
       
    95     }
       
    96 
       
    97 void CUsbHostMsDevice::InitialiseL(const RMessage2& aMessage)
       
    98 	{
       
    99     __MSFNLOG
       
   100 	iTransport = InitialiseTransportL((TTransportType) iConfig.iTransportId);
       
   101 	TRAPD(r, iDeviceSuspendResume = CUsbMsIfaceSuspendResume::NewL(iTransport, this));
       
   102 	if(r != KErrNone)
       
   103 		{
       
   104 		delete iTransport;
       
   105 		User::Leave(r);
       
   106 		}
       
   107 	iTransport->GetMaxLun(&iMaxLun, aMessage);
       
   108 	}
       
   109 
       
   110 
       
   111 void CUsbHostMsDevice::UnInitialiseL()
       
   112     {
       
   113     __MSFNLOG
       
   114 	StopTimer();
       
   115     iLuList.RemoveAllLuL();
       
   116     }
       
   117 
       
   118 
       
   119 TInt CUsbHostMsDevice::AddLunL(TLun aLun)
       
   120     {
       
   121     __MSFNLOG
       
   122     TInt r = KErrNone;
       
   123 	StartTimer();
       
   124     CUsbHostMsLogicalUnit* lu = CUsbHostMsLogicalUnit::NewL(aLun);
       
   125     CleanupStack::PushL(lu);
       
   126 
       
   127     TRAP(r, lu->InitialiseProtocolL(aLun, iConfig, *iTransport));
       
   128 
       
   129 	if (r == KErrNone)
       
   130 		{
       
   131 		TRAP(r, iLuList.AddLuL(lu));
       
   132 		}
       
   133 
       
   134     if (r != KErrNone)
       
   135         {
       
   136         CleanupStack::PopAndDestroy(lu);
       
   137         }
       
   138     else
       
   139         {
       
   140         CleanupStack::Pop(lu);
       
   141         }
       
   142     return r;
       
   143     }
       
   144 
       
   145 
       
   146 void CUsbHostMsDevice::RemoveLunL(TLun aLun)
       
   147     {
       
   148     __MSFNLOG
       
   149 	if(iLuList.Count() <= 1)
       
   150 		StopTimer();
       
   151 	iLuList.RemoveLuL(aLun);
       
   152     }
       
   153 
       
   154 
       
   155 void CUsbHostMsDevice::InitLunL(TLun aLun)
       
   156 	{
       
   157     __MSFNLOG
       
   158 	SetLunL(aLun);
       
   159     iLuList.GetLuL(aLun).InitL();
       
   160 	}
       
   161 
       
   162 
       
   163 void CUsbHostMsDevice::SuspendLunL(TLun aLun)
       
   164 	{
       
   165     __MSFNLOG
       
   166 	iLuList.GetLuL(aLun).ReadyToSuspend();
       
   167 
       
   168     // check whether all the luns are suspended, if so then request usb
       
   169     // interface suspension to the transport layer
       
   170 	for (TInt i = 0; i < iLuList.Count(); i++)
       
   171 		{
       
   172 		CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i);
       
   173 	   	if (!lu.IsReadyToSuspend() && lu.IsConnected())
       
   174 	   		return;
       
   175 		}
       
   176 
       
   177 	for (TInt i = 0; i < iLuList.Count(); i++)
       
   178 		{
       
   179 		CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i);
       
   180 		SetLunL(lu.Lun());
       
   181 		lu.SuspendL();
       
   182 		}
       
   183 
       
   184 	StopTimer();
       
   185 	iDeviceSuspendResume->Suspend();
       
   186 	iState = ESuspended;
       
   187 	}
       
   188 
       
   189 TBool CUsbHostMsDevice::IsActive()
       
   190 	{
       
   191     __MSFNLOG
       
   192 	return (iState == EActive)? ETrue : EFalse;
       
   193 	}
       
   194 
       
   195 TBool CUsbHostMsDevice::IsSuspended()
       
   196 	{
       
   197     __MSFNLOG
       
   198 	return (iState == ESuspended)? ETrue : EFalse;
       
   199 	}
       
   200 
       
   201 void CUsbHostMsDevice::ResumeL(TRequestStatus &aStatus)
       
   202 	{
       
   203     __MSFNLOG
       
   204 	if (iState == ESuspended)
       
   205 		{
       
   206 		StartTimer();
       
   207 		iDeviceSuspendResume->Resume(aStatus);
       
   208 		}
       
   209 	else
       
   210 		{
       
   211         __HOSTPRINT(_L("CUsbHostMsDevice: Wierd we are not suspended but were asked to resume"));
       
   212 		}
       
   213 	}
       
   214 
       
   215 
       
   216 TLun CUsbHostMsDevice::GetAndSetLunL(const RMessage2& aMessage)
       
   217 	{
       
   218     __MSFNLOG
       
   219 	// Subssessions need a positive value to store in the handles. We represent Luns as LunId+1
       
   220 	// We represent LunId in MSC from 0 to MaxLun-1 as represented in BOT so subtract 1 from the Id
       
   221     // received from RMessage
       
   222 
       
   223     TInt lun = aMessage.Int3() - 1;
       
   224     if (lun < 0)
       
   225         {
       
   226         User::Leave(KErrArgument);
       
   227         }
       
   228 	SetLunL(static_cast<TLun>(lun));
       
   229 	return static_cast<TLun>(lun);
       
   230 	}
       
   231 
       
   232 
       
   233 CUsbHostMsLogicalUnit& CUsbHostMsDevice::GetLuL(TInt aLunNum) const
       
   234     {
       
   235     return iLuList.GetLuL(aLunNum);
       
   236     }
       
   237 
       
   238 void CUsbHostMsDevice::SetLunL(TLun aLun)
       
   239 	{
       
   240     __MSFNLOG
       
   241 	if (aLun <= iMaxLun)
       
   242         {
       
   243         __HOSTPRINT1(_L("SetLun %d"), aLun);
       
   244         iTransport->SetLun(aLun);
       
   245         CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(aLun);
       
   246 		if (lu.IsReadyToSuspend())
       
   247 			{
       
   248 			lu.CancelReadyToSuspend();
       
   249 			}
       
   250 		}
       
   251 	}
       
   252 
       
   253 /**
       
   254 Starts timer to periodically check LUN. If the timer is not yet running then
       
   255 start it.
       
   256 */
       
   257 void CUsbHostMsDevice::StartTimer()
       
   258 	{
       
   259     __MSFNLOG
       
   260 	if (!iTimerRunning)
       
   261 		{
       
   262 		// Period of the LUN Ready check
       
   263 		const TTimeIntervalMicroSeconds32 KInterval = iConfig.iStatusPollingInterval * 1000 * 1000;
       
   264 		TCallBack callback(TimerCallback, this);
       
   265 		__HOSTPRINT(_L("Starting timer"));
       
   266 		iTimer->Start(KInterval, KInterval, callback);
       
   267 		iTimerRunning = ETrue;
       
   268 		}
       
   269 	}
       
   270 
       
   271 
       
   272 /**
       
   273 Ensure that the Timer is stopped
       
   274 */
       
   275 void CUsbHostMsDevice::StopTimer()
       
   276 	{
       
   277     __MSFNLOG
       
   278 	if (iTimer && iTimerRunning)
       
   279 		{
       
   280 		__HOSTPRINT(_L("Stopping timer"));
       
   281 		if (iTimer->IsActive())
       
   282 			{
       
   283 			iTimer->Cancel();
       
   284 			}
       
   285 		iTimerRunning = EFalse;
       
   286 		}
       
   287 	}
       
   288 
       
   289 /**
       
   290 A static wrapper for the DoLunReadyCheckEvent member function for use as a timer
       
   291 callback function.
       
   292 
       
   293 @param obj 'this' pointer
       
   294 @return not used in CPeriodic callback (see TCallback)
       
   295 */
       
   296 TInt CUsbHostMsDevice::TimerCallback(TAny* obj)
       
   297 	{
       
   298     __MSFNSLOG
       
   299     CUsbHostMsDevice* device = static_cast<CUsbHostMsDevice*>(obj);
       
   300 	TRAPD(err, device->DoLunReadyCheckEventL());
       
   301 	return err;
       
   302 	}
       
   303 
       
   304 void CUsbHostMsDevice::DoLunReadyCheckEventL()
       
   305 	{
       
   306     __MSFNLOG
       
   307 	TInt err;
       
   308 	for (TInt i = 0; i < iLuList.Count(); i++)
       
   309 		{
       
   310 		CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i);
       
   311 		SetLunL(lu.Lun());
       
   312 		TRAP(err, lu.DoLunReadyCheckL());
       
   313 		}
       
   314 	}
       
   315 
       
   316 void CUsbHostMsDevice::DoHandleRemoteWakeupL()
       
   317 	{
       
   318     __MSFNLOG
       
   319 	DoResumeLogicalUnitsL();
       
   320 	DoLunReadyCheckEventL();	// For remote wakeup we do not wait for timer to expire
       
   321 
       
   322     // check whether all the luns are suspended, if so then request usb
       
   323     // interface suspension to the transport layer
       
   324 	for (TInt i = 0; i < iLuList.Count(); i++)
       
   325 		{
       
   326 		CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i);
       
   327 		// Has any of the logical units have got its state changed?
       
   328 	   	if ( (lu.IsReadyToSuspend() && !lu.IsConnected()) ||
       
   329 				(!lu.IsReadyToSuspend() && lu.IsConnected()) )
       
   330 			{
       
   331 			StartTimer(); // Now start the timer
       
   332 	   		return;
       
   333 			}
       
   334 		}
       
   335 
       
   336 	for (TInt i = 0; i < iLuList.Count(); i++)
       
   337 		{
       
   338 		CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i);
       
   339 		SetLunL(lu.Lun());
       
   340 		lu.SuspendL();
       
   341 		}
       
   342 
       
   343 	iDeviceSuspendResume->Suspend();
       
   344 	iState = ESuspended;
       
   345 	}
       
   346 
       
   347 void CUsbHostMsDevice::DoResumeLogicalUnitsL()
       
   348 	{
       
   349     __MSFNLOG
       
   350 	for (TInt i = 0; i < iLuList.Count(); i++)
       
   351 		{
       
   352 		CUsbHostMsLogicalUnit& lu = iLuList.GetLuL(i);
       
   353 		SetLunL(lu.Lun());
       
   354 		lu.ResumeL();
       
   355 		}
       
   356 	}
       
   357 
       
   358 void CUsbHostMsDevice::ResumeCompletedL()
       
   359 	{
       
   360     __MSFNLOG
       
   361 	iState = EActive;
       
   362 	DoResumeLogicalUnitsL();
       
   363 	}