os/kernelhwsrv/userlibandfileserver/fileserver/smassstorage/drivemanager.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// Class implementation of CDriveManager and CMassStorageDrive.
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
/**
sl@0
    19
 @file
sl@0
    20
 @internalTechnology
sl@0
    21
*/
sl@0
    22
sl@0
    23
#include <f32fsys.h>
sl@0
    24
#include "massstoragedebug.h"
sl@0
    25
#include "usbmsshared.h"
sl@0
    26
#include "drivemanager.h"
sl@0
    27
sl@0
    28
///////////////////////////////////////////////////////////////////////////////
sl@0
    29
sl@0
    30
sl@0
    31
/**
sl@0
    32
A private structure that, when Connected, holds references to 
sl@0
    33
the CProxyDrive and the corresponding TBusLocalDrive's Media Changed flag.
sl@0
    34
*/
sl@0
    35
struct CMassStorageDrive::CLocalDriveRef : public CBase
sl@0
    36
	{
sl@0
    37
	CLocalDriveRef(CProxyDrive& aProxyDrive, TBool& aMediaChanged)
sl@0
    38
		: iProxyDrive(aProxyDrive), iMediaChanged(aMediaChanged), iDriveState(EIdle)
sl@0
    39
		{
sl@0
    40
		}
sl@0
    41
	CProxyDrive& iProxyDrive;
sl@0
    42
	TBool& iMediaChanged;
sl@0
    43
	/**
sl@0
    44
	The Drive Media state machine
sl@0
    45
	*/
sl@0
    46
	TDriveState iDriveState;
sl@0
    47
	};
sl@0
    48
sl@0
    49
/**
sl@0
    50
@param aCritSec A Critical Section object shared by all drives.
sl@0
    51
@param aDrives Reference to the list of CMassStorageDrive objects. 
sl@0
    52
@param aDriveMap Reference to array mapping lun to drive number for supported 
sl@0
    53
	   mass storage drives.
sl@0
    54
@post Object is fully constructed
sl@0
    55
 */
sl@0
    56
CMassStorageDrive::CMassStorageDrive(RCriticalSection& aCritSec, 
sl@0
    57
									 RDriveStateChangedPublisher& aDriveStateChangedPublisher)
sl@0
    58
	: 
sl@0
    59
	iCritSec(aCritSec),
sl@0
    60
	iMountState(EDisconnected),
sl@0
    61
	iDriveStateChangedPublisher(aDriveStateChangedPublisher)
sl@0
    62
	{
sl@0
    63
	__FNLOG("CMassStorageDrive::CMassStorageDrive");
sl@0
    64
sl@0
    65
	}
sl@0
    66
sl@0
    67
CMassStorageDrive::~CMassStorageDrive()
sl@0
    68
	{
sl@0
    69
	delete iLocalDrive;
sl@0
    70
	}
sl@0
    71
sl@0
    72
/**
sl@0
    73
Read from the target drive unit.
sl@0
    74
@return KErrNone on success, otherwise system wide error code
sl@0
    75
*/
sl@0
    76
TInt CMassStorageDrive::Read(const TInt64& aPos, TInt aLength, TDes8& aBuf, TBool aWholeMedia)
sl@0
    77
	{
sl@0
    78
	__FNLOG("CMassStorageDrive::Read");
sl@0
    79
sl@0
    80
	TInt err = KErrUnknown; // never return this
sl@0
    81
	iCritSec.Wait();
sl@0
    82
sl@0
    83
	if(iMountState != EConnected)
sl@0
    84
		{
sl@0
    85
		err = KErrDisconnected;
sl@0
    86
		}
sl@0
    87
	else
sl@0
    88
		{
sl@0
    89
		if(aWholeMedia)
sl@0
    90
			{
sl@0
    91
			err = SafeProxyDrive().Read(aPos, aLength, &aBuf, KLocalMessageHandle, 0, RLocalDrive::ELocDrvWholeMedia);
sl@0
    92
			}
sl@0
    93
		else
sl@0
    94
			{
sl@0
    95
			err = SafeProxyDrive().Read(aPos, aLength, aBuf);
sl@0
    96
			}
sl@0
    97
sl@0
    98
		if(err == KErrNone)
sl@0
    99
			{
sl@0
   100
#ifndef USB_TRANSFER_PUBLISHER
sl@0
   101
			iBytesRead += aBuf.Length();
sl@0
   102
			__PRINT1(_L("iBytesRead=%d\n"),iBytesRead);
sl@0
   103
#endif
sl@0
   104
			}
sl@0
   105
sl@0
   106
		else if(err == KErrLocked)
sl@0
   107
			{
sl@0
   108
			SetDriveState(ELocked);
sl@0
   109
			}
sl@0
   110
		}
sl@0
   111
sl@0
   112
	iCritSec.Signal();
sl@0
   113
	return err;
sl@0
   114
	}
sl@0
   115
sl@0
   116
/**
sl@0
   117
Write to the target drive unit.
sl@0
   118
@return KErrNone on success, otherwise system wide error code
sl@0
   119
*/
sl@0
   120
TInt CMassStorageDrive::Write(const TInt64& aPos, TDesC8& aBuf, TBool aWholeMedia)
sl@0
   121
	{
sl@0
   122
	__FNLOG("CMassStorageDrive::Write");
sl@0
   123
sl@0
   124
	TInt err = KErrNone;
sl@0
   125
	iCritSec.Wait();
sl@0
   126
sl@0
   127
	if (iMountState != EConnected)
sl@0
   128
		{
sl@0
   129
		err = KErrDisconnected;
sl@0
   130
		}
sl@0
   131
	else
sl@0
   132
		{
sl@0
   133
		__ASSERT_DEBUG(iLocalDrive, User::Invariant());
sl@0
   134
		TDriveState oldState = iLocalDrive->iDriveState;
sl@0
   135
		if(oldState != EActive)
sl@0
   136
			{
sl@0
   137
			// SCSI hasn't called SetCritical
sl@0
   138
			SetDriveState(EActive);
sl@0
   139
			}
sl@0
   140
sl@0
   141
		if (aWholeMedia)
sl@0
   142
			{
sl@0
   143
			err = SafeProxyDrive().Write(aPos, aBuf.Length(), &aBuf, KLocalMessageHandle, 0, RLocalDrive::ELocDrvWholeMedia);
sl@0
   144
			}
sl@0
   145
		else
sl@0
   146
			{
sl@0
   147
			err = SafeProxyDrive().Write(aPos,aBuf);
sl@0
   148
			}
sl@0
   149
sl@0
   150
		if (err == KErrNone)
sl@0
   151
			{
sl@0
   152
#ifndef USB_TRANSFER_PUBLISHER
sl@0
   153
			iBytesWritten += aBuf.Length();
sl@0
   154
#endif
sl@0
   155
			}
sl@0
   156
sl@0
   157
		if (err == KErrLocked)
sl@0
   158
			{
sl@0
   159
			SetDriveState(ELocked);
sl@0
   160
			}
sl@0
   161
		else if (oldState != EActive)
sl@0
   162
			{
sl@0
   163
			SetDriveState(oldState);
sl@0
   164
			}
sl@0
   165
		}
sl@0
   166
sl@0
   167
	iCritSec.Signal();
sl@0
   168
	return err;
sl@0
   169
	}
sl@0
   170
sl@0
   171
/**
sl@0
   172
Get the capabilities of the target drive unit.
sl@0
   173
@return KErrNone on success, otherwise system wide error code
sl@0
   174
*/
sl@0
   175
TInt CMassStorageDrive::Caps(TLocalDriveCapsV4& aInfo)
sl@0
   176
	{
sl@0
   177
	__FNLOG("CMassStorageDrive::Caps");
sl@0
   178
sl@0
   179
	TInt err = KErrNone;
sl@0
   180
	iCritSec.Wait();
sl@0
   181
	
sl@0
   182
	if(iMountState != EConnected)
sl@0
   183
		{
sl@0
   184
		err = KErrDisconnected;
sl@0
   185
		}
sl@0
   186
	else 
sl@0
   187
		{
sl@0
   188
		// Initialise in case Caps() fails
sl@0
   189
		aInfo.iType = ::EMediaUnknown; 
sl@0
   190
		err = DoCaps(aInfo);
sl@0
   191
sl@0
   192
		__PRINTERR(_L("CheckDriveState: DoCaps err=%d\n"), err);
sl@0
   193
sl@0
   194
		if(err == KErrNotReady || (err==KErrNone && aInfo.iType == ::EMediaNotPresent))
sl@0
   195
			{
sl@0
   196
			__PRINT(_L("CMassStorageDrive::Caps detected MediaNotPresent\n"));
sl@0
   197
			SetDriveState(CMassStorageDrive::EMediaNotPresent);
sl@0
   198
			}
sl@0
   199
		}
sl@0
   200
sl@0
   201
	iCritSec.Signal();
sl@0
   202
	return err;
sl@0
   203
	}
sl@0
   204
sl@0
   205
/**
sl@0
   206
Provides an interface to CProxyDrive::Caps that hides the
sl@0
   207
package buffer.
sl@0
   208
@return KErrNone on success, otherwise system wide error code
sl@0
   209
@param aInfo
sl@0
   210
*/
sl@0
   211
TInt CMassStorageDrive::DoCaps(TLocalDriveCapsV4& aInfo)
sl@0
   212
	{
sl@0
   213
	__FNLOG("CMassStorageDrive::DoCaps");
sl@0
   214
sl@0
   215
	TLocalDriveCapsV4Buf buf;
sl@0
   216
	buf.FillZ();
sl@0
   217
	CProxyDrive& pd = SafeProxyDrive();
sl@0
   218
sl@0
   219
	__PRINT(_L("CMassStorageDrive::DoCaps calling Caps\n"));
sl@0
   220
	TInt err = pd.Caps(buf);
sl@0
   221
sl@0
   222
	__PRINT1(_L("CMassStorageDrive::DoCaps: Caps returned %d\n"), err);
sl@0
   223
sl@0
   224
	if(err==KErrNone)
sl@0
   225
		{
sl@0
   226
		// Invoke function call operator to cast to TLocalDriveCapsV4&
sl@0
   227
		aInfo = buf();
sl@0
   228
		}
sl@0
   229
sl@0
   230
	return err;
sl@0
   231
	}
sl@0
   232
sl@0
   233
/**
sl@0
   234
Publish media error, user should reinsert the memory card.
sl@0
   235
Similar to FAT32's TDriver::HandleCriticalError.
sl@0
   236
Note: User notification is not implemented, instead we abort and dismount.
sl@0
   237
*/
sl@0
   238
TInt CMassStorageDrive::HandleCriticalError() 
sl@0
   239
	{
sl@0
   240
	__FNLOG("CMassStorageDrive::HandleCriticalError");
sl@0
   241
	iDriveMediaErrorPublisher.PublishError(ETrue);
sl@0
   242
	return KErrAbort;
sl@0
   243
	}
sl@0
   244
sl@0
   245
sl@0
   246
TInt CMassStorageDrive::ClearCriticalError()
sl@0
   247
	{
sl@0
   248
	iDriveMediaErrorPublisher.PublishError(EFalse);
sl@0
   249
	return KErrNone;
sl@0
   250
	}
sl@0
   251
sl@0
   252
sl@0
   253
/**
sl@0
   254
Checks the Media Changed flag, and optionally resets it.
sl@0
   255
@return The state of the Media Changed flag.
sl@0
   256
@param aReset If true, the Media Changed flag is reset to EFalse.
sl@0
   257
*/
sl@0
   258
TBool CMassStorageDrive::IsMediaChanged(TBool aReset)
sl@0
   259
	{
sl@0
   260
	__FNLOG("CMassStorageDrive::IsMediaChanged");
sl@0
   261
sl@0
   262
	iCritSec.Wait();
sl@0
   263
sl@0
   264
	TBool mediaChanged = EFalse;
sl@0
   265
	if(iLocalDrive)
sl@0
   266
		{
sl@0
   267
		mediaChanged = iLocalDrive->iMediaChanged;
sl@0
   268
		if(aReset) 
sl@0
   269
			{
sl@0
   270
			iLocalDrive->iMediaChanged = EFalse;
sl@0
   271
			}
sl@0
   272
		}
sl@0
   273
	else
sl@0
   274
		{
sl@0
   275
		__PRINT(_L("CMassStorageDrive::IsMediaChanged: no drive\n"));
sl@0
   276
		}
sl@0
   277
sl@0
   278
	iCritSec.Signal();
sl@0
   279
sl@0
   280
	__PRINT1(_L("CMassStorageDrive::IsMediaChanged: returning %d\n"), mediaChanged);
sl@0
   281
	return mediaChanged;
sl@0
   282
	}
sl@0
   283
sl@0
   284
/**
sl@0
   285
Set the Drive State to Active or Idle.
sl@0
   286
@return KErrNone on success, KErrNotReady if media not present, KErrDisMounted if not mounted
sl@0
   287
@param aCritical ETrue for Active, EFalse for Idle
sl@0
   288
*/
sl@0
   289
TInt CMassStorageDrive::SetCritical(TBool aCritical)
sl@0
   290
	{
sl@0
   291
	__FNLOG("CMassStorageDrive::SetCritical");
sl@0
   292
sl@0
   293
	TInt err = KErrDisMounted;
sl@0
   294
sl@0
   295
	iCritSec.Wait();
sl@0
   296
sl@0
   297
	if(iLocalDrive)
sl@0
   298
		{
sl@0
   299
		if(iLocalDrive->iDriveState == CMassStorageDrive::EMediaNotPresent)
sl@0
   300
			{
sl@0
   301
			err = KErrNotReady;
sl@0
   302
			}
sl@0
   303
		else
sl@0
   304
			{
sl@0
   305
			SetDriveState(
sl@0
   306
				aCritical 
sl@0
   307
				? CMassStorageDrive::EActive
sl@0
   308
				: CMassStorageDrive::EIdle );
sl@0
   309
				
sl@0
   310
			err = KErrNone;
sl@0
   311
			}
sl@0
   312
		}
sl@0
   313
sl@0
   314
	iCritSec.Signal();
sl@0
   315
sl@0
   316
	return err;
sl@0
   317
	}
sl@0
   318
sl@0
   319
/**
sl@0
   320
Set the mount state
sl@0
   321
*/
sl@0
   322
TInt CMassStorageDrive::SetMountConnected(CProxyDrive& aProxyDrive, TBool& aMediaChanged)
sl@0
   323
	{
sl@0
   324
	__FNLOG("CMassStorageDrive::SetMountConnected");
sl@0
   325
	CLocalDriveRef* localDrive = NULL;
sl@0
   326
sl@0
   327
	__PRINT(_L("SetMountConnected entering critical section\n"));
sl@0
   328
	iCritSec.Wait(); // note: signalled in SetMountState
sl@0
   329
sl@0
   330
	if (iLocalDrive == NULL)
sl@0
   331
		{
sl@0
   332
		localDrive = new CLocalDriveRef(aProxyDrive, aMediaChanged);
sl@0
   333
		if (localDrive==NULL) 
sl@0
   334
			{
sl@0
   335
			iCritSec.Signal();
sl@0
   336
			return KErrNoMemory;
sl@0
   337
			}
sl@0
   338
		}
sl@0
   339
sl@0
   340
	return SetMountState(EConnected, localDrive);
sl@0
   341
	}
sl@0
   342
sl@0
   343
/**
sl@0
   344
@return KErrNone
sl@0
   345
@param aNewState
sl@0
   346
@param aLocalDrive Only provide this if aNewState is EConnected.
sl@0
   347
*/
sl@0
   348
TInt CMassStorageDrive::SetMountState(TMountState aNewState, CLocalDriveRef* aLocalDrive/*=NULL*/)
sl@0
   349
	{
sl@0
   350
	__FNLOG("CMassStorageDrive::SetMountState");
sl@0
   351
	
sl@0
   352
	if(iMountState == aNewState)
sl@0
   353
		{
sl@0
   354
		__PRINT(_L("SetMountState: No change\n"));
sl@0
   355
		}
sl@0
   356
	else
sl@0
   357
		{
sl@0
   358
		// If called from SetMountConnected, already in critical section, 
sl@0
   359
		// otherwise, must enter it here.
sl@0
   360
		if(EConnected!=aNewState)
sl@0
   361
			{
sl@0
   362
			__PRINT(_L("SetMountState entering critical section\n"));
sl@0
   363
			iCritSec.Wait();
sl@0
   364
			}
sl@0
   365
sl@0
   366
		switch(aNewState)
sl@0
   367
			{
sl@0
   368
			case EConnected:
sl@0
   369
				if(aLocalDrive)
sl@0
   370
					{
sl@0
   371
					__ASSERT_DEBUG(!iLocalDrive, User::Invariant());
sl@0
   372
					iLocalDrive = aLocalDrive;
sl@0
   373
					}
sl@0
   374
				__ASSERT_DEBUG(iLocalDrive, User::Invariant());
sl@0
   375
				break;
sl@0
   376
sl@0
   377
			case EDisconnected:
sl@0
   378
				delete iLocalDrive;
sl@0
   379
				iLocalDrive = NULL;
sl@0
   380
#ifndef USB_TRANSFER_PUBLISHER
sl@0
   381
				iBytesWritten = iBytesRead = 0;
sl@0
   382
#endif
sl@0
   383
				break;
sl@0
   384
sl@0
   385
			case EDisconnecting:
sl@0
   386
			case EConnecting:
sl@0
   387
				// Do not change iLocalDrive for these state changes
sl@0
   388
				break;
sl@0
   389
			}
sl@0
   390
		
sl@0
   391
		iMountState = aNewState;
sl@0
   392
		__PRINT1(_L("SetMountState: state=%d\n"), iMountState);
sl@0
   393
sl@0
   394
		iDriveStateChangedPublisher.DriveStateChanged();
sl@0
   395
		
sl@0
   396
		iCritSec.Signal();
sl@0
   397
		__PRINT(_L("SetMountState has left the critical section\n"));
sl@0
   398
		}
sl@0
   399
sl@0
   400
	return KErrNone;
sl@0
   401
	}
sl@0
   402
sl@0
   403
/**
sl@0
   404
@return Current drive media state
sl@0
   405
*/
sl@0
   406
CMassStorageDrive::TDriveState CMassStorageDrive::DriveState() const
sl@0
   407
	{
sl@0
   408
	return iLocalDrive ? iLocalDrive->iDriveState : EErrDisMounted;
sl@0
   409
	}
sl@0
   410
sl@0
   411
/**
sl@0
   412
Check for media not present, and return the drive state.
sl@0
   413
@return Current drive media state
sl@0
   414
*/
sl@0
   415
CMassStorageDrive::TDriveState CMassStorageDrive::CheckDriveState()
sl@0
   416
	{
sl@0
   417
	__FNLOG("CMassStorageDrive::CheckDriveState");
sl@0
   418
sl@0
   419
	CMassStorageDrive::TDriveState state = EErrDisMounted;
sl@0
   420
sl@0
   421
	iCritSec.Wait();
sl@0
   422
sl@0
   423
	if (iLocalDrive)
sl@0
   424
		{
sl@0
   425
		TInt err = KErrGeneral;
sl@0
   426
		TLocalDriveCapsV4 caps;
sl@0
   427
sl@0
   428
		FOREVER
sl@0
   429
			{
sl@0
   430
			// Initialise in case Caps() fails
sl@0
   431
			caps.iType = ::EMediaNotPresent; 
sl@0
   432
sl@0
   433
			err = DoCaps(caps);
sl@0
   434
			__PRINTERR(_L("CheckDriveState: DoCaps err=%d\n"), err);
sl@0
   435
			if (err == KErrNotReady || (err == KErrNone && caps.iType == ::EMediaNotPresent))
sl@0
   436
				{
sl@0
   437
				__PRINT(_L("CheckDriveState: detected MediaNotPresent\n"));
sl@0
   438
sl@0
   439
				SetDriveState(CMassStorageDrive::EMediaNotPresent);
sl@0
   440
sl@0
   441
				if (HandleCriticalError() == KErrAbort)
sl@0
   442
					break;
sl@0
   443
				}
sl@0
   444
			else 
sl@0
   445
				{
sl@0
   446
				ClearCriticalError();
sl@0
   447
				break;
sl@0
   448
				}
sl@0
   449
			}
sl@0
   450
sl@0
   451
		if (err == KErrNone && caps.iType != ::EMediaNotPresent)
sl@0
   452
			{
sl@0
   453
			if (iLocalDrive->iDriveState == CMassStorageDrive::EMediaNotPresent)
sl@0
   454
				{
sl@0
   455
				__PRINT(_L("CheckDriveState: detected media inserted\n"));
sl@0
   456
				SetDriveState(CMassStorageDrive::EIdle);
sl@0
   457
				}
sl@0
   458
			else if (iLocalDrive->iDriveState == CMassStorageDrive::ELocked &&
sl@0
   459
					 !(caps.iMediaAtt & KMediaAttLocked))
sl@0
   460
				{
sl@0
   461
				__PRINT(_L("CheckDriveState: detected media unlocked\n"));
sl@0
   462
				SetDriveState(CMassStorageDrive::EIdle);
sl@0
   463
				}
sl@0
   464
			else if (caps.iMediaAtt & KMediaAttLocked)
sl@0
   465
				{
sl@0
   466
				__PRINT(_L("CheckDriveState: detected media locked\n"));
sl@0
   467
				SetDriveState(CMassStorageDrive::ELocked);
sl@0
   468
				}
sl@0
   469
			
sl@0
   470
			iWholeMediaAccess = !(caps.iDriveAtt & KDriveAttLogicallyRemovable);
sl@0
   471
			}
sl@0
   472
sl@0
   473
		// Get the current state
sl@0
   474
		state = iLocalDrive->iDriveState;
sl@0
   475
		}
sl@0
   476
sl@0
   477
	iCritSec.Signal();
sl@0
   478
sl@0
   479
	return state;
sl@0
   480
	}
sl@0
   481
sl@0
   482
static TBool IsActive(CMassStorageDrive::TDriveState aDriveState)
sl@0
   483
	{
sl@0
   484
	return aDriveState==CMassStorageDrive::EActive;
sl@0
   485
	}
sl@0
   486
sl@0
   487
/**
sl@0
   488
@param aNewState
sl@0
   489
*/
sl@0
   490
void CMassStorageDrive::SetDriveState(TDriveState aNewState)
sl@0
   491
	{
sl@0
   492
	__FNLOG("CMassStorageDrive::SetDriveState");
sl@0
   493
sl@0
   494
	__ASSERT_DEBUG(aNewState == EIdle ||
sl@0
   495
                   (iMountState == EConnected && NULL != iLocalDrive) ||
sl@0
   496
                   (iMountState == EDisconnecting && NULL != iLocalDrive),
sl@0
   497
        User::Invariant());
sl@0
   498
sl@0
   499
	if(!iLocalDrive)
sl@0
   500
		{
sl@0
   501
		__PRINT(_L("SetDriveState: Drive not mounted.\n"));
sl@0
   502
		}
sl@0
   503
	else
sl@0
   504
		{
sl@0
   505
		__PRINT2(_L("SetDriveState: %d->%d\n"), iLocalDrive->iDriveState, aNewState);
sl@0
   506
sl@0
   507
		if(iLocalDrive->iDriveState != aNewState)
sl@0
   508
			{
sl@0
   509
			CMountCB* mount = SafeProxyDrive().Mount();
sl@0
   510
#if !defined(USBMSDRIVE_TEST)
sl@0
   511
			__ASSERT_DEBUG(mount != NULL, User::Invariant());
sl@0
   512
#endif
sl@0
   513
			if(mount)
sl@0
   514
				{
sl@0
   515
				if(!IsActive(iLocalDrive->iDriveState) && IsActive(aNewState))
sl@0
   516
					{
sl@0
   517
					mount->IncLock();
sl@0
   518
					}
sl@0
   519
				else if(IsActive(iLocalDrive->iDriveState) && !IsActive(aNewState))
sl@0
   520
					{
sl@0
   521
					mount->DecLock();
sl@0
   522
					}
sl@0
   523
				__PRINT1(_L("SetDriveState: LockStatus=%d\n"), mount->LockStatus());
sl@0
   524
				}
sl@0
   525
sl@0
   526
			iLocalDrive->iDriveState = aNewState;
sl@0
   527
sl@0
   528
			iDriveStateChangedPublisher.DriveStateChanged();
sl@0
   529
			}
sl@0
   530
		}
sl@0
   531
	}
sl@0
   532
sl@0
   533
/**
sl@0
   534
Accessor for iProxyDrive; asserts if NULL
sl@0
   535
*/
sl@0
   536
CProxyDrive& CMassStorageDrive::SafeProxyDrive() const
sl@0
   537
	{
sl@0
   538
	__ASSERT_ALWAYS(NULL!=iLocalDrive, User::Invariant());
sl@0
   539
	return iLocalDrive->iProxyDrive;
sl@0
   540
	}
sl@0
   541
sl@0
   542
/////////////////////////////////////////////////////////////////
sl@0
   543
sl@0
   544
/**
sl@0
   545
Construct a CDriveManager object.
sl@0
   546
@param aDriveMap Reference to array mapping lun to drive number for supported 
sl@0
   547
	   mass storage drives.
sl@0
   548
*/
sl@0
   549
CDriveManager* CDriveManager::NewL(TRefDriveMap aDriveMap)
sl@0
   550
	{
sl@0
   551
	__FNLOG("CDriveManager::NewL");
sl@0
   552
	__PRINT1(_L("CDriveManager::NewL - %d drives\n"), aDriveMap.Count());
sl@0
   553
sl@0
   554
	CDriveManager* self = new (ELeave) CDriveManager(aDriveMap);
sl@0
   555
	CleanupStack::PushL(self);
sl@0
   556
	self->ConstructL();
sl@0
   557
	CleanupStack::Pop();
sl@0
   558
	return self;
sl@0
   559
	}
sl@0
   560
sl@0
   561
CDriveManager::CDriveManager(const RArray<TInt>& aDriveMap)
sl@0
   562
	: iDriveMap(aDriveMap)
sl@0
   563
	{}
sl@0
   564
sl@0
   565
/**
sl@0
   566
Construct a CDriveManager object.
sl@0
   567
*/
sl@0
   568
void CDriveManager::ConstructL()
sl@0
   569
	{
sl@0
   570
	__FNLOG("CDriveManager::ConstructL");
sl@0
   571
sl@0
   572
	User::LeaveIfError(iDriveCritSec.CreateLocal());
sl@0
   573
sl@0
   574
	iDriveStateChangedPublisher = new (ELeave) RDriveStateChangedPublisher(iDrives, iDriveMap);
sl@0
   575
sl@0
   576
	for(TInt i = 0; i < iDriveMap.Count(); i++)
sl@0
   577
		{
sl@0
   578
		iDrives[i] = new (ELeave) CMassStorageDrive(iDriveCritSec, *iDriveStateChangedPublisher);
sl@0
   579
		}
sl@0
   580
sl@0
   581
	// Publish initial drive state
sl@0
   582
	if (iDriveMap.Count() > 0)
sl@0
   583
		{
sl@0
   584
		iDriveStateChangedPublisher->DriveStateChanged();
sl@0
   585
		}
sl@0
   586
	}
sl@0
   587
sl@0
   588
/**
sl@0
   589
Destructor
sl@0
   590
*/
sl@0
   591
CDriveManager::~CDriveManager()
sl@0
   592
	{
sl@0
   593
	__FNLOG("CDriveManager::~CDriveManager");
sl@0
   594
sl@0
   595
	iDrives.DeleteAll();
sl@0
   596
	delete iDriveStateChangedPublisher;
sl@0
   597
	iDriveCritSec.Close();
sl@0
   598
	}
sl@0
   599
sl@0
   600
/**
sl@0
   601
Set the mount state to Connected and specify the Proxy Drive.
sl@0
   602
@return KErrNone on success, otherwise system wide error code
sl@0
   603
@param aDrive The mounted Proxy Drive
sl@0
   604
@param aLun The Logical Drive Unit identifier (0..numDrives-1)
sl@0
   605
@pre If the Mount State is Connected, then aDrive must be the
sl@0
   606
     same as it was the last time this function was called.
sl@0
   607
@post The Mount State will be Connected.
sl@0
   608
*/
sl@0
   609
TInt CDriveManager::RegisterDrive(CProxyDrive& aProxyDrive, TBool& aMediaChanged, TUint aLun)
sl@0
   610
	{
sl@0
   611
	__FNLOG("CDriveManager::RegisterDrive");
sl@0
   612
	__PRINT1(_L("Lun=%d \n"),aLun);
sl@0
   613
	TInt err = KErrUnknown; // never return this
sl@0
   614
	CMassStorageDrive* drive = CDriveManager::Drive(aLun, err);
sl@0
   615
	if(drive)
sl@0
   616
		{
sl@0
   617
		drive->SetMountConnected(aProxyDrive, aMediaChanged);
sl@0
   618
		}
sl@0
   619
sl@0
   620
	__PRINT1(_L("CDriveManager::RegisterDrive err=%d\n"), err);
sl@0
   621
	return err;
sl@0
   622
	}
sl@0
   623
sl@0
   624
/**
sl@0
   625
Set the mount state to Disconnected.
sl@0
   626
@return KErrNone on success, otherwise system wide error code
sl@0
   627
@param aLun The Logical Drive Unit identifier (0..numDrives-1)
sl@0
   628
@post The Mount State will be Disconnected.
sl@0
   629
*/
sl@0
   630
TInt CDriveManager::DeregisterDrive(TUint aLun)
sl@0
   631
	{
sl@0
   632
	__FNLOG("CDriveManager::DeregisterDrive");
sl@0
   633
sl@0
   634
	TInt err = KErrUnknown; // never return this
sl@0
   635
	if(CMassStorageDrive* drive = Drive(aLun, err))
sl@0
   636
		{
sl@0
   637
		err = drive->SetMountDisconnected();
sl@0
   638
		}
sl@0
   639
sl@0
   640
	__PRINT1(_L("CDriveManager::DeregisterDrive err=%d\n"), err);
sl@0
   641
	return err;
sl@0
   642
	}
sl@0
   643
sl@0
   644
/**
sl@0
   645
Return a pointer to the drive specified aLun, or NULL if
sl@0
   646
aLun is invalid.
sl@0
   647
sl@0
   648
@return Pointer to the specified drive, or NULL.
sl@0
   649
@param aLun The Logical Drive Unit identifier (0..numDrives-1)
sl@0
   650
@param aError KErrNone on success, KErrArgument if NULL is returned.
sl@0
   651
*/
sl@0
   652
CMassStorageDrive* CDriveManager::Drive(TUint aLun, TInt& aError) const
sl@0
   653
	{
sl@0
   654
	aError = KErrNone;
sl@0
   655
	CMassStorageDrive* drive = NULL;
sl@0
   656
sl@0
   657
	// Check if aLun exceeds the specified number of drives
sl@0
   658
	// (This will panic if it exceeds KMaxLun).
sl@0
   659
	if(aLun>=KUsbMsMaxDrives || !iDrives[aLun]) 
sl@0
   660
		{
sl@0
   661
		aError = KErrArgument;
sl@0
   662
		}
sl@0
   663
	else
sl@0
   664
		{
sl@0
   665
		drive = iDrives[aLun];
sl@0
   666
		}
sl@0
   667
	return drive;
sl@0
   668
	}
sl@0
   669
sl@0
   670
/**
sl@0
   671
Checks the Media Changed flag, and optionally resets it.
sl@0
   672
@return The state of the Media Changed flag.
sl@0
   673
@param aLun The Logical Drive Unit identifier (0..numDrives-1)
sl@0
   674
@param aReset If true, the Media Changed flag is reset to EFalse.
sl@0
   675
*/
sl@0
   676
TBool CDriveManager::IsMediaChanged(TUint aLun, TBool aReset)
sl@0
   677
	{
sl@0
   678
	__FNLOG("CDriveManager::IsMediaChanged");
sl@0
   679
sl@0
   680
	TInt err; // not used, but is a required parameter
sl@0
   681
	CMassStorageDrive* drive = Drive(aLun, err);
sl@0
   682
sl@0
   683
	if(!drive)
sl@0
   684
		{
sl@0
   685
		__PRINT1(_L("CDriveManager::IsMediaChanged: LUN=%d not found, returning false\n"), aLun);
sl@0
   686
		return ETrue;
sl@0
   687
		}
sl@0
   688
	else
sl@0
   689
		{
sl@0
   690
		return drive->IsMediaChanged(aReset);
sl@0
   691
		}
sl@0
   692
	}
sl@0
   693
sl@0
   694
/**
sl@0
   695
Set the Drive State to Active or Idle.
sl@0
   696
Ref: 3.6.3.2 - PREVENT_MEDIUM_REMOVAL
sl@0
   697
@return KErrNone on success, otherwise system wide error code
sl@0
   698
@param aLun The Logical Drive Unit identifier (0..numDrives-1)
sl@0
   699
@param aCritical ETrue for Active, EFalse for Idle
sl@0
   700
*/
sl@0
   701
TInt CDriveManager::SetCritical(TUint aLun, TBool aCritical)
sl@0
   702
	{
sl@0
   703
	__FNLOG("CDriveManager::SetCritical");
sl@0
   704
sl@0
   705
	TInt err = KErrUnknown; // never return this
sl@0
   706
sl@0
   707
	TInt i=aLun;
sl@0
   708
	TInt cnt=aLun+1;
sl@0
   709
	
sl@0
   710
	if (aLun == KAllLuns)
sl@0
   711
		{
sl@0
   712
		i=0;
sl@0
   713
		cnt= iDriveMap.Count();
sl@0
   714
		}
sl@0
   715
sl@0
   716
	for(; i<cnt; i++)
sl@0
   717
		{
sl@0
   718
sl@0
   719
		CMassStorageDrive* drive = Drive(i, err);
sl@0
   720
		if(drive)
sl@0
   721
			{
sl@0
   722
			err = drive->SetCritical(aCritical);
sl@0
   723
			}
sl@0
   724
		}
sl@0
   725
	return err;
sl@0
   726
	}
sl@0
   727
sl@0
   728
/**
sl@0
   729
Inititiate transition to Connected.
sl@0
   730
@return KErrNone on success, otherwise system wide error code
sl@0
   731
@param aLun The Logical Drive Unit identifier (0..numDrives-1)
sl@0
   732
@post The Mount State will be Connected or Connecting.
sl@0
   733
*/
sl@0
   734
TInt CDriveManager::Connect(TUint aLun)
sl@0
   735
	{
sl@0
   736
	__FNLOG("CDriveManager::Connect");
sl@0
   737
sl@0
   738
	TInt err = KErrUnknown; // never return this
sl@0
   739
	CMassStorageDrive* drive = Drive(aLun, err);
sl@0
   740
sl@0
   741
	__PRINT3(_L("CDriveManager::Connect lun=%d, err=%d, mountState=%d\n"), aLun, err, drive->MountState());
sl@0
   742
sl@0
   743
	if(drive)
sl@0
   744
		{
sl@0
   745
		switch(drive->MountState())
sl@0
   746
			{
sl@0
   747
			case CMassStorageDrive::EDisconnected:
sl@0
   748
				err = drive->SetMountConnecting();
sl@0
   749
				break;
sl@0
   750
			case CMassStorageDrive::EDisconnecting:
sl@0
   751
				err = drive->SetMountConnected();
sl@0
   752
				break;
sl@0
   753
			case CMassStorageDrive::EConnected:
sl@0
   754
			case CMassStorageDrive::EConnecting:
sl@0
   755
				// do nothing
sl@0
   756
				break;
sl@0
   757
			}
sl@0
   758
		}
sl@0
   759
	return err;
sl@0
   760
	}
sl@0
   761
sl@0
   762
/**
sl@0
   763
Inititiate transition to Disconnected.
sl@0
   764
@return KErrNone on success, otherwise system wide error code
sl@0
   765
@param aLun The Logical Drive Unit identifier (0..numDrives-1)
sl@0
   766
@post The Mount State will be Disconnected or Disconnecting.
sl@0
   767
*/
sl@0
   768
TInt CDriveManager::Disconnect(TUint aLun)
sl@0
   769
	{
sl@0
   770
	__FNLOG("CDriveManager::Disconnect");
sl@0
   771
sl@0
   772
	TInt err = KErrUnknown; // never return this
sl@0
   773
	CMassStorageDrive* drive = Drive(aLun, err);
sl@0
   774
sl@0
   775
	if(drive)
sl@0
   776
		{
sl@0
   777
		switch(drive->MountState())
sl@0
   778
			{
sl@0
   779
			case CMassStorageDrive::EConnected:
sl@0
   780
				err = drive->SetMountDisconnecting();
sl@0
   781
				break;
sl@0
   782
			case CMassStorageDrive::EConnecting:
sl@0
   783
				err = drive->SetMountDisconnected();
sl@0
   784
				break;
sl@0
   785
			case CMassStorageDrive::EDisconnected:
sl@0
   786
			case CMassStorageDrive::EDisconnecting:
sl@0
   787
				// do nothing
sl@0
   788
				break;
sl@0
   789
			}
sl@0
   790
		}
sl@0
   791
	return err;
sl@0
   792
	}
sl@0
   793
sl@0
   794