os/kernelhwsrv/userlibandfileserver/fileserver/sfile/sf_local.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) 2002-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
//
sl@0
    15
sl@0
    16
#include "sf_std.h"
sl@0
    17
#include "e32cmn.h"
sl@0
    18
sl@0
    19
#ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION	
sl@0
    20
#include "sf_notifier.h"
sl@0
    21
#endif
sl@0
    22
sl@0
    23
GLREF_C CProxyDriveFactory* GetExtension(const TDesC& aName);
sl@0
    24
GLREF_C CExtProxyDriveFactory* GetProxyDriveFactory(const TDesC& aName);
sl@0
    25
sl@0
    26
TBusLocalDrive LocalDrives::iLocalDrives[KMaxLocalDrives];			
sl@0
    27
TInt LocalDrives::iMapping[KMaxDrives];
sl@0
    28
TInt LocalDrives::iReverseMapping[KMaxLocalDrives];
sl@0
    29
TBool LocalDrives::iMappingSet;
sl@0
    30
LocalDrives::TSocketDesc LocalDrives::iSocketDescs[KMaxPBusSockets];
sl@0
    31
CExtProxyDrive*  LocalDrives::iProxyDriveMapping[KMaxProxyDrives];
sl@0
    32
TBool LocalDrives::iIsMultiSlotDrive[KMaxDrives];
sl@0
    33
const TInt KInvalidSocketNumber = -1;
sl@0
    34
sl@0
    35
void LocalDrives::Initialise()
sl@0
    36
//
sl@0
    37
//
sl@0
    38
//
sl@0
    39
	{	
sl@0
    40
	iMappingSet = EFalse;
sl@0
    41
	TInt i;
sl@0
    42
	Mem::FillZ((TAny*)iProxyDriveMapping,sizeof(CExtProxyDriveFactory*)*KMaxProxyDrives);
sl@0
    43
	// initialise mapping from drive number to local drive
sl@0
    44
	for(i=0;i<KMaxDrives;i++)
sl@0
    45
		{
sl@0
    46
		iMapping[i] = KDriveInvalid;
sl@0
    47
		iIsMultiSlotDrive[i] = EFalse;
sl@0
    48
		}
sl@0
    49
	// initialise reverse mapping from local drive to drive.
sl@0
    50
	for(i=0;i<KMaxLocalDrives;i++)
sl@0
    51
		{
sl@0
    52
		iReverseMapping[i] = KDriveInvalid;
sl@0
    53
		}
sl@0
    54
	// initialise mapping from socket number to drive numbers
sl@0
    55
	for(i=0;i<KMaxPBusSockets;++i)
sl@0
    56
		{
sl@0
    57
		TSocketDesc& socketDesc = iSocketDescs[i];
sl@0
    58
		socketDesc.iMediaType = EInvalidMedia;
sl@0
    59
		socketDesc.iControllerRelativeSocket = KInvalidSocketNumber;
sl@0
    60
		for(TInt j=0;j<KMaxDrivesPerSocket;++j)
sl@0
    61
			socketDesc.iDriveNumbers[j]=KDriveInvalid;
sl@0
    62
		}
sl@0
    63
	}
sl@0
    64
sl@0
    65
// Searches for a local socket which matches the media type and 
sl@0
    66
// controller relative socket number. 
sl@0
    67
// If none is found then this function returns a new socket number.
sl@0
    68
// If no more free sockets available, returns KErrNoMemory
sl@0
    69
TInt LocalDrives::GetLocalSocket(TInt aControllerRelativeSocket, TMediaDevice aMediaType)
sl@0
    70
	{
sl@0
    71
	TInt i;
sl@0
    72
	TSocketDesc* socketDesc = NULL;
sl@0
    73
	for (i=0; i<KMaxPBusSockets; i++)
sl@0
    74
		{
sl@0
    75
		socketDesc = &iSocketDescs[i];
sl@0
    76
		TMediaDevice mediaType = socketDesc->iMediaType;
sl@0
    77
		if (mediaType == aMediaType && socketDesc->iControllerRelativeSocket == aControllerRelativeSocket)
sl@0
    78
			return i;
sl@0
    79
		if (mediaType == EInvalidMedia)	// socket unassigned ?
sl@0
    80
			break;
sl@0
    81
		}
sl@0
    82
	if (i == KMaxPBusSockets)
sl@0
    83
		return KErrNoMemory;
sl@0
    84
	
sl@0
    85
	// assign a new local socket for this controller relative socket number & media type
sl@0
    86
	socketDesc->iMediaType = aMediaType;
sl@0
    87
	socketDesc->iControllerRelativeSocket = aControllerRelativeSocket;
sl@0
    88
sl@0
    89
	return i;
sl@0
    90
	}
sl@0
    91
sl@0
    92
TBusLocalDrive& LocalDrives::GetLocalDrive(TInt aDrive)
sl@0
    93
//
sl@0
    94
// Export localdrives
sl@0
    95
//
sl@0
    96
	{
sl@0
    97
	__ASSERT_DEBUG(aDrive>=0 && aDrive<KMaxDrives,Fault(EGetLocalDrive1));
sl@0
    98
	__ASSERT_DEBUG(iMapping[aDrive]!=KDriveInvalid &&  iMapping[aDrive]<KMaxLocalDrives,Fault(EGetLocalDrive2));
sl@0
    99
	return(iLocalDrives[iMapping[aDrive]]);
sl@0
   100
	}
sl@0
   101
sl@0
   102
sl@0
   103
TInt LocalDrives::GetLocalDriveNumber(TBusLocalDrive* aLocDrv)
sl@0
   104
//
sl@0
   105
// Get the local drive number for the local drive object passed in
sl@0
   106
//
sl@0
   107
	{
sl@0
   108
	for(TInt i=0;i<KMaxLocalDrives;++i)
sl@0
   109
		if(&iLocalDrives[i]==aLocDrv)
sl@0
   110
			return(i);
sl@0
   111
	return(KDriveInvalid);
sl@0
   112
	}
sl@0
   113
sl@0
   114
sl@0
   115
sl@0
   116
CExtProxyDrive* LocalDrives::GetProxyDrive(TInt aDrive)
sl@0
   117
	{
sl@0
   118
	__ASSERT_DEBUG(aDrive>=0 && aDrive<KMaxDrives,Fault(EGetProxyDriveMapping1));
sl@0
   119
	__ASSERT_DEBUG(iMapping[aDrive]!=KDriveInvalid &&  iMapping[aDrive]>=KMaxLocalDrives && iMapping[aDrive]<KMaxDrives,Fault(EGetProxyDriveMapping1));
sl@0
   120
	return iProxyDriveMapping[iMapping[aDrive]-KMaxLocalDrives];
sl@0
   121
	}
sl@0
   122
sl@0
   123
sl@0
   124
LOCAL_C TBool DriveNumberIsInRange(TInt aDrive)
sl@0
   125
	{
sl@0
   126
	
sl@0
   127
	return((aDrive>=0) && (aDrive<KMaxDrives));
sl@0
   128
	}
sl@0
   129
	
sl@0
   130
	
sl@0
   131
TBool LocalDrives::IsValidDriveMapping(TInt aDrive)
sl@0
   132
//
sl@0
   133
//  Is the drive number to local drive mapping valid?
sl@0
   134
//
sl@0
   135
	{
sl@0
   136
	
sl@0
   137
	__ASSERT_DEBUG(DriveNumberIsInRange(aDrive),Fault(EIsValidDriveMapping));
sl@0
   138
	return(iMapping[aDrive]!=KDriveInvalid);
sl@0
   139
	}
sl@0
   140
sl@0
   141
sl@0
   142
TInt LocalDrives::DriveNumberToLocalDriveNumber(TInt aDrive)
sl@0
   143
//
sl@0
   144
// Get the mapping from drive number to local drive
sl@0
   145
//
sl@0
   146
	{
sl@0
   147
	return(iMapping[aDrive]);
sl@0
   148
	}
sl@0
   149
sl@0
   150
sl@0
   151
TInt LocalDrives::SetDriveMappingL(CFsRequest* aRequest)
sl@0
   152
//
sl@0
   153
//
sl@0
   154
//
sl@0
   155
	{
sl@0
   156
	
sl@0
   157
	__PRINT(_L("LocalDrives::SetDriveMappingL()"));
sl@0
   158
	if (iMappingSet)
sl@0
   159
		return(KErrAccessDenied);
sl@0
   160
		
sl@0
   161
	TLocalDriveMappingInfoBuf mBuf;
sl@0
   162
	mBuf.FillZ();
sl@0
   163
	aRequest->ReadL(KMsgPtr0,mBuf);
sl@0
   164
	TLocalDriveMappingInfo& ldmi=mBuf();
sl@0
   165
	
sl@0
   166
	if (ldmi.iOperation==TLocalDriveMappingInfo::ESwapIntMappingAndSet)
sl@0
   167
		{
sl@0
   168
		// Only the 1st two entries of the mapping table are valid - holding the drive numbers to be swapped 
sl@0
   169
		TInt r=KErrNone;
sl@0
   170
		if (DriveNumberIsInRange(ldmi.iDriveMapping[0]) && DriveNumberIsInRange(ldmi.iDriveMapping[1]))
sl@0
   171
			r=SwapDriveMapping(ldmi.iDriveMapping[0],ldmi.iDriveMapping[1]);
sl@0
   172
		iMappingSet=ETrue;
sl@0
   173
		return(r);
sl@0
   174
		}
sl@0
   175
	
sl@0
   176
	// That just leaves EWriteMappingsAndSet and EWriteMappingsNoSet
sl@0
   177
	for (TInt i=0;i<KMaxLocalDrives;++i)
sl@0
   178
		{
sl@0
   179
		TInt driveLetter=ldmi.iDriveMapping[i];
sl@0
   180
		if(driveLetter==KDriveInvalid)
sl@0
   181
			continue;
sl@0
   182
		if ( !DriveNumberIsInRange(driveLetter))
sl@0
   183
			{
sl@0
   184
			// invalid mapping list passed in, clear all mappings set up
sl@0
   185
			for(TInt j=0;j<KMaxDrives;j++)
sl@0
   186
				iMapping[j] = KDriveInvalid;
sl@0
   187
			return(KErrArgument);
sl@0
   188
			}
sl@0
   189
		__PRINT2(_L("drive letter %d -> local drive %d"),driveLetter,i);
sl@0
   190
		
sl@0
   191
		// If this mapping (letter -> localdrive) is already set then
sl@0
   192
		// this must be a multislot device. Save this mapping as an 
sl@0
   193
		// alternative mapping (by storing it in iReverseMapping)
sl@0
   194
		if(iMapping[driveLetter] != KDriveInvalid)
sl@0
   195
			{
sl@0
   196
			iIsMultiSlotDrive[driveLetter] = ETrue;
sl@0
   197
			}
sl@0
   198
		// first time we've seen this drive letter
sl@0
   199
		iMapping[driveLetter]=i;
sl@0
   200
		// following mapping is used when we want to swap back again. 
sl@0
   201
		iReverseMapping[i]=driveLetter;
sl@0
   202
		}
sl@0
   203
sl@0
   204
	InitDriveMapping();
sl@0
   205
	if (ldmi.iOperation==TLocalDriveMappingInfo::EWriteMappingsAndSet)
sl@0
   206
		iMappingSet=ETrue;
sl@0
   207
	return(KErrNone);
sl@0
   208
	}
sl@0
   209
sl@0
   210
// Changes here must be reflected in SwapDriveMapping() 	
sl@0
   211
void LocalDrives::InitDriveMapping()
sl@0
   212
	{
sl@0
   213
	__PRINT(_L("InitDriveMapping()"));
sl@0
   214
	TDriveInfoV1Buf driveInfo;
sl@0
   215
	TInt r=UserHal::DriveInfo(driveInfo);
sl@0
   216
	__ASSERT_ALWAYS(r==KErrNone,Fault(EInitDriveMappingDriveInfo));	
sl@0
   217
sl@0
   218
	// initialise the local drives
sl@0
   219
	TInt i;
sl@0
   220
	for(i=0;i<KMaxLocalDrives;++i)
sl@0
   221
		{
sl@0
   222
		TInt driveNo = iReverseMapping[i];
sl@0
   223
		if(driveNo!=KDriveInvalid)
sl@0
   224
			{
sl@0
   225
			r=iLocalDrives[i].Connect(i,TheDrives[driveNo].iChanged);
sl@0
   226
			__ASSERT_ALWAYS(r==KErrNone,Fault(EInitConnectLocalDrive));
sl@0
   227
			__PRINT2(_L("connect to locdrv %d using drive %d"),i,driveNo);
sl@0
   228
			//If this is a multislot then we need to set the iChanged to True
sl@0
   229
			//So that we are mapped to the correct drive when we're booted.
sl@0
   230
			if(iIsMultiSlotDrive[driveNo])
sl@0
   231
				{
sl@0
   232
				TheDrives[driveNo].iChanged = ETrue;
sl@0
   233
				}
sl@0
   234
			if (driveInfo().iDriveName[i].Length()==0)
sl@0
   235
				continue;
sl@0
   236
			TheDriveNames[driveNo]=driveInfo().iDriveName[i].Alloc();
sl@0
   237
			__ASSERT_ALWAYS(TheDriveNames[driveNo],Fault(EInitCreateDriveName));
sl@0
   238
			}
sl@0
   239
		}
sl@0
   240
sl@0
   241
	TInt drivesPerSocket[KMaxPBusSockets];
sl@0
   242
	Mem::FillZ(&drivesPerSocket,KMaxPBusSockets*sizeof(TInt));
sl@0
   243
	TInt nSockets=driveInfo().iTotalSockets;
sl@0
   244
	for(i=0;i<KMaxLocalDrives;++i)
sl@0
   245
		{
sl@0
   246
		TInt socket;
sl@0
   247
		if(iLocalDrives[i].Handle()==0 || !iLocalDrives[i].IsRemovable(socket))
sl@0
   248
			{
sl@0
   249
			TInt driveNo = iReverseMapping[i];
sl@0
   250
			// Non-removable drive so shouldn't be listed as a Multislot drive
sl@0
   251
			// Drives such as composite drives may have been
sl@0
   252
			// set to true as the drive letter had been encountered before.
sl@0
   253
			// make sure those drives are set to false here.
sl@0
   254
			iIsMultiSlotDrive[driveNo]=EFalse;
sl@0
   255
			continue;
sl@0
   256
			}
sl@0
   257
		__ASSERT_ALWAYS(socket>=0 && socket<nSockets,Fault(EInitDriveMappingSocketNo));
sl@0
   258
		TInt drv=GetDriveFromLocalDrive(i);
sl@0
   259
		// get local socket number
sl@0
   260
		TMediaDevice mediaDevice = iLocalDrives[i].MediaDevice();
sl@0
   261
		TInt localSocket = LocalDrives::GetLocalSocket(socket, mediaDevice);
sl@0
   262
		__ASSERT_ALWAYS(localSocket>=0 && localSocket<KMaxPBusSockets,Fault(EInitDriveMappingSocketNo));
sl@0
   263
		__PRINT4(_L("InitDriveMapping(), i = %d, , mediaDevice = %d, socket = %d, localSocket = %d"), 
sl@0
   264
			i, mediaDevice, socket, localSocket);
sl@0
   265
		__PRINT2(_L("drv = %d (%C:)"), drv, 'A' + drv);
sl@0
   266
sl@0
   267
		TSocketDesc& socketDesc = iSocketDescs[localSocket];
sl@0
   268
		if(drv!=KDriveInvalid)
sl@0
   269
			{
sl@0
   270
			TInt& count = drivesPerSocket[localSocket];
sl@0
   271
			// setup up socket to drive mapping
sl@0
   272
			__ASSERT_ALWAYS(count < KMaxDrivesPerSocket,Fault(ETooManyDrivesPerSocket));
sl@0
   273
			socketDesc.iDriveNumbers[count]=drv;
sl@0
   274
			if(count==0)
sl@0
   275
				{
sl@0
   276
				// setup media change notifier if this is first local drive found on socket
sl@0
   277
				CNotifyMediaChange* pN=new CNotifyMediaChange(&iLocalDrives[i],localSocket);
sl@0
   278
				__ASSERT_ALWAYS(pN!=NULL,Fault(EInitCreateMediaChangeNotifier));
sl@0
   279
				__PRINT2(_L("created CNotifyMediaChange media 0x%x using local drive %d"), localSocket,i);
sl@0
   280
				socketDesc.iMediaChanges = pN;
sl@0
   281
				CActiveSchedulerFs::Add(pN);
sl@0
   282
				pN->RunL();
sl@0
   283
				}
sl@0
   284
			++count;
sl@0
   285
			}
sl@0
   286
		}
sl@0
   287
	}
sl@0
   288
sl@0
   289
TInt LocalDrives::InitProxyDrive(CFsRequest* aRequest)
sl@0
   290
	{
sl@0
   291
	__PRINT(_L("LocalDrives::InitProxyDrive"));
sl@0
   292
	
sl@0
   293
	TInt drive = aRequest->Message().Int0() ;
sl@0
   294
	
sl@0
   295
	if (drive < 0 || drive >= KMaxDrives) 
sl@0
   296
		return KErrArgument;
sl@0
   297
	
sl@0
   298
	if (drive!=EDriveZ && iMapping[drive]!=KDriveInvalid) 
sl@0
   299
		return KErrInUse; // Z is special case for composite
sl@0
   300
	
sl@0
   301
	TFullName extname;
sl@0
   302
	aRequest->ReadL(KMsgPtr1,extname);
sl@0
   303
sl@0
   304
	// leave info thing for now
sl@0
   305
	CExtProxyDriveFactory* pF = GetProxyDriveFactory(extname);
sl@0
   306
	if (!pF) 
sl@0
   307
		return KErrArgument;	// that extension has not been added
sl@0
   308
	FsThreadManager::LockDrive(drive);
sl@0
   309
	// find a free mapping to place this drive into
sl@0
   310
	TInt i;
sl@0
   311
	for (i=0; i <KMaxProxyDrives; i++)
sl@0
   312
		{
sl@0
   313
		if (!iProxyDriveMapping[i]) 
sl@0
   314
			break;
sl@0
   315
		}
sl@0
   316
	FsThreadManager::UnlockDrive(drive);
sl@0
   317
	if (i==KMaxProxyDrives) 
sl@0
   318
		return KErrInUse;   // there are no free proxy drives left
sl@0
   319
sl@0
   320
	// Create the actual proxy drive...
sl@0
   321
	CProxyDrive* pD = NULL;
sl@0
   322
	TInt r = pF->CreateProxyDrive(pD, NULL);
sl@0
   323
	__ASSERT_ALWAYS(r == KErrNone, User::Panic(_L("CreateProxyDrive Error"), r));
sl@0
   324
	__ASSERT_ALWAYS(pD != NULL, User::Panic(_L("CreateProxyDrive returned NULL"), -999));
sl@0
   325
sl@0
   326
	iMapping[drive] = i+KMaxLocalDrives;
sl@0
   327
sl@0
   328
	aRequest->SetDrive(&TheDrives[drive]);
sl@0
   329
	aRequest->SetScratchValue((TUint)pD);
sl@0
   330
sl@0
   331
	return KErrNone;
sl@0
   332
	}
sl@0
   333
sl@0
   334
TInt LocalDrives::MountProxyDrive(CFsRequest* aRequest)
sl@0
   335
	{
sl@0
   336
	CExtProxyDrive* pProxyDrive = (CExtProxyDrive*)aRequest->ScratchValue();
sl@0
   337
	__ASSERT_ALWAYS(pProxyDrive != NULL, User::Panic(_L("MountProxyDrive has NULL proxy extension class"), -999));
sl@0
   338
sl@0
   339
	TInt driveNumber = aRequest->Drive()->DriveNumber();
sl@0
   340
sl@0
   341
sl@0
   342
	TInt proxyDriveNo = iMapping[driveNumber] - KMaxLocalDrives;
sl@0
   343
	FsThreadManager::LockDrive(driveNumber);
sl@0
   344
	iProxyDriveMapping[proxyDriveNo] = pProxyDrive;
sl@0
   345
	pProxyDrive->SetDriveNumber(driveNumber);
sl@0
   346
	FsThreadManager::UnlockDrive(driveNumber);
sl@0
   347
	//
sl@0
   348
	// Pass initialisation information onto the extension to allow it to initialise
sl@0
   349
	//
sl@0
   350
	TInt err = pProxyDrive->SetInfo(aRequest->Message(), 
sl@0
   351
									(TAny*)aRequest->Message().Ptr2(), 
sl@0
   352
									(TAny*)aRequest->Message().Ptr3());
sl@0
   353
	if (err != KErrNone) 
sl@0
   354
		{
sl@0
   355
		//
sl@0
   356
		// If we fail to initialise the extension, then close the drive (destroying the thread)
sl@0
   357
		// and remove the mapping so we can attempt to mount again in the future.
sl@0
   358
		//
sl@0
   359
		FsThreadManager::LockDrive(driveNumber);
sl@0
   360
		FsThreadManager::CloseDrive(driveNumber);
sl@0
   361
		ClearProxyDriveMapping(driveNumber);
sl@0
   362
		FsThreadManager::UnlockDrive(driveNumber);
sl@0
   363
		return err;
sl@0
   364
		}
sl@0
   365
sl@0
   366
	return(iMapping[driveNumber]);
sl@0
   367
 	}
sl@0
   368
sl@0
   369
TBool LocalDrives::IsProxyDrive(TInt aDrive)
sl@0
   370
	{
sl@0
   371
	__ASSERT_ALWAYS(aDrive>=0 && aDrive<KMaxDrives,Fault(EIsProxyDrive));
sl@0
   372
	return (iMapping[aDrive] >= KMaxLocalDrives);
sl@0
   373
	}
sl@0
   374
sl@0
   375
TBool LocalDrives::IsProxyDriveInUse(CExtProxyDriveFactory* aDevice)
sl@0
   376
	{
sl@0
   377
	for (TInt i=0; i < KMaxProxyDrives; i++)
sl@0
   378
		if (iProxyDriveMapping[i] && (iProxyDriveMapping[i]->FactoryP() == aDevice))
sl@0
   379
			return(ETrue);
sl@0
   380
sl@0
   381
	return(EFalse);
sl@0
   382
	}
sl@0
   383
sl@0
   384
void LocalDrives::ClearProxyDriveMapping(TInt aDrive)
sl@0
   385
	{
sl@0
   386
	__ASSERT_ALWAYS(aDrive>=0 && aDrive<KMaxDrives,Fault(EClearProxyDriveMapping1));
sl@0
   387
	__ASSERT_DEBUG(iMapping[aDrive]>= KMaxLocalDrives && iProxyDriveMapping[iMapping[aDrive]-KMaxLocalDrives],Fault(EClearProxyDriveMapping2));
sl@0
   388
	TInt idx = iMapping[aDrive]-KMaxLocalDrives;
sl@0
   389
	delete iProxyDriveMapping[idx];
sl@0
   390
	iProxyDriveMapping[idx] = NULL;
sl@0
   391
	iMapping[aDrive] = KDriveInvalid;
sl@0
   392
	}
sl@0
   393
sl@0
   394
TInt LocalDrives::SetupMediaChange(TInt aDrive)
sl@0
   395
	{
sl@0
   396
	CExtProxyDrive* pProxyDrive = LocalDrives::GetProxyDrive(aDrive);
sl@0
   397
	__ASSERT_ALWAYS(pProxyDrive != NULL,User::Panic(_L("SetupMediaChange - pProxyDrive == NULL"), ESetupMediaChange));
sl@0
   398
sl@0
   399
	return pProxyDrive->SetupMediaChange();
sl@0
   400
	}
sl@0
   401
sl@0
   402
void LocalDrives::NotifyChangeCancel(TInt aDrive)
sl@0
   403
	{
sl@0
   404
	CExtProxyDrive* pProxyDrive = LocalDrives::GetProxyDrive(aDrive);
sl@0
   405
	__ASSERT_ALWAYS(pProxyDrive != NULL,User::Panic(_L("NotifyChangeCancel - pProxyDrive == NULL"), ECancelNotifyChange));
sl@0
   406
sl@0
   407
	pProxyDrive->NotifyChangeCancel();
sl@0
   408
	}
sl@0
   409
sl@0
   410
TInt LocalDrives::SwapDriveMapping(TInt aFirstDrive,TInt aSecondDrive)
sl@0
   411
	{
sl@0
   412
	
sl@0
   413
	__PRINT(_L("SwapDriveMapping()"));
sl@0
   414
	TInt firstLocalDrv=iMapping[aFirstDrive];
sl@0
   415
	TInt secondLocalDrv=iMapping[aSecondDrive];
sl@0
   416
	
sl@0
   417
	// First, check this swap doesn't affect removable drives
sl@0
   418
	TInt socket;
sl@0
   419
	if (iLocalDrives[firstLocalDrv].Handle()!=0 && iLocalDrives[firstLocalDrv].IsRemovable(socket))
sl@0
   420
		return(KErrAccessDenied);
sl@0
   421
	if (iLocalDrives[secondLocalDrv].Handle()!=0 && iLocalDrives[secondLocalDrv].IsRemovable(socket))
sl@0
   422
		return(KErrAccessDenied);	
sl@0
   423
		
sl@0
   424
	// Now swap the mappings over
sl@0
   425
	iMapping[aFirstDrive]=secondLocalDrv;	
sl@0
   426
	iMapping[aSecondDrive]=firstLocalDrv;
sl@0
   427
sl@0
   428
	iReverseMapping[firstLocalDrv]=aSecondDrive;
sl@0
   429
	iReverseMapping[secondLocalDrv]=aFirstDrive;
sl@0
   430
	
sl@0
   431
	// Finally, swap the drive names over
sl@0
   432
	HBufC* drvName=TheDriveNames[aSecondDrive];
sl@0
   433
	TheDriveNames[aSecondDrive]=TheDriveNames[aFirstDrive];
sl@0
   434
	TheDriveNames[aFirstDrive]=drvName;
sl@0
   435
	return(KErrNone);
sl@0
   436
	}
sl@0
   437
	
sl@0
   438
void LocalDrives::CompleteNotifications(TInt aSocket)
sl@0
   439
//
sl@0
   440
//
sl@0
   441
//
sl@0
   442
	{
sl@0
   443
	__ASSERT_DEBUG(aSocket>=0 && aSocket<KMaxPBusSockets && iSocketDescs[aSocket].iDriveNumbers[0]!=KDriveInvalid,Fault(ECompleteNotifSocketNo));
sl@0
   444
	TInt i=0;
sl@0
   445
	
sl@0
   446
	// In a data-paging environment, the local media subsytem will only update the TDrive::iChanged flag
sl@0
   447
	// for drives which have a CNotifyMediaChange object, i.e. for drives which call TBusLocalDrive::NotifyChange().
sl@0
   448
	// Since we only create ONE CNotifyMediaChange object for each socket (no matter how many partitions/local drives
sl@0
   449
	// are associated with that socket), we need to propagate the TDrive::iChanged flag to all drives on the socket.
sl@0
   450
	TBool changedFlag = TheDrives[iSocketDescs[aSocket].iDriveNumbers[0]].IsChanged();
sl@0
   451
sl@0
   452
	while(i<KMaxDrivesPerSocket && iSocketDescs[aSocket].iDriveNumbers[i]!=KDriveInvalid)
sl@0
   453
		{
sl@0
   454
		TheDrives[iSocketDescs[aSocket].iDriveNumbers[i]].SetChanged(changedFlag);
sl@0
   455
		CompleteDriveNotifications(iSocketDescs[aSocket].iDriveNumbers[i++]);
sl@0
   456
		}
sl@0
   457
	}
sl@0
   458
sl@0
   459
void LocalDrives::CompleteDriveNotifications(TInt aDrive)
sl@0
   460
//
sl@0
   461
//
sl@0
   462
//
sl@0
   463
	{
sl@0
   464
	// If the drive is hung, then don't complete any disk change 
sl@0
   465
	// notifications until the request causing the hang completes
sl@0
   466
	if(FsThreadManager::IsDriveHung(aDrive))
sl@0
   467
		FsThreadManager::SetMediaChangePending(aDrive);
sl@0
   468
	else
sl@0
   469
		{
sl@0
   470
		FsNotify::DiskChange(aDrive);
sl@0
   471
		
sl@0
   472
#ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION	
sl@0
   473
		if(FsNotificationManager::IsInitialised())
sl@0
   474
			{
sl@0
   475
			__PRINT3(_L("LocalDrives::CompleteDriveNotifications() Initialised=%d, Count=%d, Drive=%d"),FsNotificationManager::IsInitialised(),FsNotificationManager::Count(), aDrive);
sl@0
   476
			TBuf<2> driveDes;
sl@0
   477
			driveDes.Append((TChar)aDrive+(TChar)'A');
sl@0
   478
			driveDes.Append((TChar)':');
sl@0
   479
			FsNotificationManager::HandleChange(NULL,driveDes,TFsNotification::EMediaChange);
sl@0
   480
			}
sl@0
   481
#endif //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION		
sl@0
   482
sl@0
   483
	 	//If this is a multislot device we should update mappings here.
sl@0
   484
		TheDrives[aDrive].MultiSlotDriveCheck();
sl@0
   485
		}
sl@0
   486
	}
sl@0
   487
sl@0
   488
TInt LocalDrives::GetDriveFromLocalDrive(TInt aLocDrv)
sl@0
   489
//
sl@0
   490
//
sl@0
   491
//
sl@0
   492
	{
sl@0
   493
	return iReverseMapping[aLocDrv];
sl@0
   494
	}
sl@0
   495
sl@0
   496
sl@0
   497
CNotifyMediaChange::CNotifyMediaChange(RLocalDrive* aDrive,TInt aSocketNo)
sl@0
   498
//
sl@0
   499
// Constructor
sl@0
   500
//
sl@0
   501
	: CActive(EPriorityHigh), iDrive(aDrive), iSocket(aSocketNo)
sl@0
   502
	{}
sl@0
   503
sl@0
   504
void CNotifyMediaChange::RunL()
sl@0
   505
//
sl@0
   506
// Notification that a card has been mounted/removed
sl@0
   507
//
sl@0
   508
	{
sl@0
   509
	LocalDrives::CompleteNotifications(iSocket);
sl@0
   510
	iDrive->NotifyChange(&iStatus);
sl@0
   511
	SetActive();
sl@0
   512
	}
sl@0
   513
sl@0
   514
sl@0
   515
CExtNotifyMediaChange::CExtNotifyMediaChange(CExtProxyDrive* aDrive)
sl@0
   516
//
sl@0
   517
// Constructor
sl@0
   518
//
sl@0
   519
	: CActive(EPriorityHigh), 
sl@0
   520
	  iDrive(aDrive),
sl@0
   521
	  iPtr((TUint8*)&TheDrives[aDrive->DriveNumber()].iChanged,sizeof(TBool))
sl@0
   522
	{
sl@0
   523
	}
sl@0
   524
sl@0
   525
	
sl@0
   526
CExtNotifyMediaChange* CExtNotifyMediaChange::NewL(CExtProxyDrive* aDrive)
sl@0
   527
	{
sl@0
   528
	CExtNotifyMediaChange* pSelf = new(ELeave) CExtNotifyMediaChange(aDrive);
sl@0
   529
sl@0
   530
	CleanupStack::PushL(pSelf);
sl@0
   531
	pSelf->ConstructL();
sl@0
   532
	CleanupStack::Pop();
sl@0
   533
sl@0
   534
	return pSelf;
sl@0
   535
	}
sl@0
   536
sl@0
   537
void CExtNotifyMediaChange::ConstructL()
sl@0
   538
	{
sl@0
   539
	CActiveSchedulerFs::Add(this);
sl@0
   540
sl@0
   541
	TRAPD(err, RunL());
sl@0
   542
	if(err != KErrNone)
sl@0
   543
		Deque();
sl@0
   544
sl@0
   545
	User::LeaveIfError(err);
sl@0
   546
	}
sl@0
   547
sl@0
   548
CExtNotifyMediaChange::~CExtNotifyMediaChange()
sl@0
   549
    {
sl@0
   550
    Cancel();
sl@0
   551
    }
sl@0
   552
sl@0
   553
void CExtNotifyMediaChange::RequestL()
sl@0
   554
    {
sl@0
   555
    if (!IsActive())
sl@0
   556
        {
sl@0
   557
        User::LeaveIfError(iDrive->NotifyChange(iPtr, &iStatus));
sl@0
   558
        SetActive();
sl@0
   559
        }
sl@0
   560
    }
sl@0
   561
sl@0
   562
void CExtNotifyMediaChange::DoCancel()
sl@0
   563
    {
sl@0
   564
    iDrive->NotifyChangeCancel();
sl@0
   565
    }
sl@0
   566
sl@0
   567
void CExtNotifyMediaChange::RunL()
sl@0
   568
	{
sl@0
   569
    if(iStatus==KErrDisconnected || iStatus==KErrCancel)
sl@0
   570
        return;
sl@0
   571
sl@0
   572
    TInt driveNum = iDrive->DriveNumber();
sl@0
   573
    LocalDrives::CompleteDriveNotifications(driveNum);
sl@0
   574
sl@0
   575
    /* NOTE: We need SetChanged here though the iChanged variable is set in the MSC, since the cache is not getting cleared
sl@0
   576
        (inside the CompleteDriveNotifications call) during the initial first notification */
sl@0
   577
    TheDrives[driveNum].SetChanged(ETrue);
sl@0
   578
sl@0
   579
    if(iStatus != KErrNotSupported)
sl@0
   580
        {
sl@0
   581
        RequestL();
sl@0
   582
        }
sl@0
   583
	}
sl@0
   584
sl@0
   585
sl@0
   586