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