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