diff -r 000000000000 -r a41df078684a userlibandfileserver/fileserver/sfile/sf_local.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/userlibandfileserver/fileserver/sfile/sf_local.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,586 @@ +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include "sf_std.h" +#include "e32cmn.h" + +#ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION +#include "sf_notifier.h" +#endif + +GLREF_C CProxyDriveFactory* GetExtension(const TDesC& aName); +GLREF_C CExtProxyDriveFactory* GetProxyDriveFactory(const TDesC& aName); + +TBusLocalDrive LocalDrives::iLocalDrives[KMaxLocalDrives]; +TInt LocalDrives::iMapping[KMaxDrives]; +TInt LocalDrives::iReverseMapping[KMaxLocalDrives]; +TBool LocalDrives::iMappingSet; +LocalDrives::TSocketDesc LocalDrives::iSocketDescs[KMaxPBusSockets]; +CExtProxyDrive* LocalDrives::iProxyDriveMapping[KMaxProxyDrives]; +TBool LocalDrives::iIsMultiSlotDrive[KMaxDrives]; +const TInt KInvalidSocketNumber = -1; + +void LocalDrives::Initialise() +// +// +// + { + iMappingSet = EFalse; + TInt i; + Mem::FillZ((TAny*)iProxyDriveMapping,sizeof(CExtProxyDriveFactory*)*KMaxProxyDrives); + // initialise mapping from drive number to local drive + for(i=0;iiMediaType; + if (mediaType == aMediaType && socketDesc->iControllerRelativeSocket == aControllerRelativeSocket) + return i; + if (mediaType == EInvalidMedia) // socket unassigned ? + break; + } + if (i == KMaxPBusSockets) + return KErrNoMemory; + + // assign a new local socket for this controller relative socket number & media type + socketDesc->iMediaType = aMediaType; + socketDesc->iControllerRelativeSocket = aControllerRelativeSocket; + + return i; + } + +TBusLocalDrive& LocalDrives::GetLocalDrive(TInt aDrive) +// +// Export localdrives +// + { + __ASSERT_DEBUG(aDrive>=0 && aDrive=0 && aDrive=KMaxLocalDrives && iMapping[aDrive]=0) && (aDriveReadL(KMsgPtr0,mBuf); + TLocalDriveMappingInfo& ldmi=mBuf(); + + if (ldmi.iOperation==TLocalDriveMappingInfo::ESwapIntMappingAndSet) + { + // Only the 1st two entries of the mapping table are valid - holding the drive numbers to be swapped + TInt r=KErrNone; + if (DriveNumberIsInRange(ldmi.iDriveMapping[0]) && DriveNumberIsInRange(ldmi.iDriveMapping[1])) + r=SwapDriveMapping(ldmi.iDriveMapping[0],ldmi.iDriveMapping[1]); + iMappingSet=ETrue; + return(r); + } + + // That just leaves EWriteMappingsAndSet and EWriteMappingsNoSet + for (TInt i=0;i local drive %d"),driveLetter,i); + + // If this mapping (letter -> localdrive) is already set then + // this must be a multislot device. Save this mapping as an + // alternative mapping (by storing it in iReverseMapping) + if(iMapping[driveLetter] != KDriveInvalid) + { + iIsMultiSlotDrive[driveLetter] = ETrue; + } + // first time we've seen this drive letter + iMapping[driveLetter]=i; + // following mapping is used when we want to swap back again. + iReverseMapping[i]=driveLetter; + } + + InitDriveMapping(); + if (ldmi.iOperation==TLocalDriveMappingInfo::EWriteMappingsAndSet) + iMappingSet=ETrue; + return(KErrNone); + } + +// Changes here must be reflected in SwapDriveMapping() +void LocalDrives::InitDriveMapping() + { + __PRINT(_L("InitDriveMapping()")); + TDriveInfoV1Buf driveInfo; + TInt r=UserHal::DriveInfo(driveInfo); + __ASSERT_ALWAYS(r==KErrNone,Fault(EInitDriveMappingDriveInfo)); + + // initialise the local drives + TInt i; + for(i=0;i=0 && socket=0 && localSocketRunL(); + } + ++count; + } + } + } + +TInt LocalDrives::InitProxyDrive(CFsRequest* aRequest) + { + __PRINT(_L("LocalDrives::InitProxyDrive")); + + TInt drive = aRequest->Message().Int0() ; + + if (drive < 0 || drive >= KMaxDrives) + return KErrArgument; + + if (drive!=EDriveZ && iMapping[drive]!=KDriveInvalid) + return KErrInUse; // Z is special case for composite + + TFullName extname; + aRequest->ReadL(KMsgPtr1,extname); + + // leave info thing for now + CExtProxyDriveFactory* pF = GetProxyDriveFactory(extname); + if (!pF) + return KErrArgument; // that extension has not been added + FsThreadManager::LockDrive(drive); + // find a free mapping to place this drive into + TInt i; + for (i=0; i CreateProxyDrive(pD, NULL); + __ASSERT_ALWAYS(r == KErrNone, User::Panic(_L("CreateProxyDrive Error"), r)); + __ASSERT_ALWAYS(pD != NULL, User::Panic(_L("CreateProxyDrive returned NULL"), -999)); + + iMapping[drive] = i+KMaxLocalDrives; + + aRequest->SetDrive(&TheDrives[drive]); + aRequest->SetScratchValue((TUint)pD); + + return KErrNone; + } + +TInt LocalDrives::MountProxyDrive(CFsRequest* aRequest) + { + CExtProxyDrive* pProxyDrive = (CExtProxyDrive*)aRequest->ScratchValue(); + __ASSERT_ALWAYS(pProxyDrive != NULL, User::Panic(_L("MountProxyDrive has NULL proxy extension class"), -999)); + + TInt driveNumber = aRequest->Drive()->DriveNumber(); + + + TInt proxyDriveNo = iMapping[driveNumber] - KMaxLocalDrives; + FsThreadManager::LockDrive(driveNumber); + iProxyDriveMapping[proxyDriveNo] = pProxyDrive; + pProxyDrive->SetDriveNumber(driveNumber); + FsThreadManager::UnlockDrive(driveNumber); + // + // Pass initialisation information onto the extension to allow it to initialise + // + TInt err = pProxyDrive->SetInfo(aRequest->Message(), + (TAny*)aRequest->Message().Ptr2(), + (TAny*)aRequest->Message().Ptr3()); + if (err != KErrNone) + { + // + // If we fail to initialise the extension, then close the drive (destroying the thread) + // and remove the mapping so we can attempt to mount again in the future. + // + FsThreadManager::LockDrive(driveNumber); + FsThreadManager::CloseDrive(driveNumber); + ClearProxyDriveMapping(driveNumber); + FsThreadManager::UnlockDrive(driveNumber); + return err; + } + + return(iMapping[driveNumber]); + } + +TBool LocalDrives::IsProxyDrive(TInt aDrive) + { + __ASSERT_ALWAYS(aDrive>=0 && aDrive= KMaxLocalDrives); + } + +TBool LocalDrives::IsProxyDriveInUse(CExtProxyDriveFactory* aDevice) + { + for (TInt i=0; i < KMaxProxyDrives; i++) + if (iProxyDriveMapping[i] && (iProxyDriveMapping[i]->FactoryP() == aDevice)) + return(ETrue); + + return(EFalse); + } + +void LocalDrives::ClearProxyDriveMapping(TInt aDrive) + { + __ASSERT_ALWAYS(aDrive>=0 && aDrive= KMaxLocalDrives && iProxyDriveMapping[iMapping[aDrive]-KMaxLocalDrives],Fault(EClearProxyDriveMapping2)); + TInt idx = iMapping[aDrive]-KMaxLocalDrives; + delete iProxyDriveMapping[idx]; + iProxyDriveMapping[idx] = NULL; + iMapping[aDrive] = KDriveInvalid; + } + +TInt LocalDrives::SetupMediaChange(TInt aDrive) + { + CExtProxyDrive* pProxyDrive = LocalDrives::GetProxyDrive(aDrive); + __ASSERT_ALWAYS(pProxyDrive != NULL,User::Panic(_L("SetupMediaChange - pProxyDrive == NULL"), ESetupMediaChange)); + + return pProxyDrive->SetupMediaChange(); + } + +void LocalDrives::NotifyChangeCancel(TInt aDrive) + { + CExtProxyDrive* pProxyDrive = LocalDrives::GetProxyDrive(aDrive); + __ASSERT_ALWAYS(pProxyDrive != NULL,User::Panic(_L("NotifyChangeCancel - pProxyDrive == NULL"), ECancelNotifyChange)); + + pProxyDrive->NotifyChangeCancel(); + } + +TInt LocalDrives::SwapDriveMapping(TInt aFirstDrive,TInt aSecondDrive) + { + + __PRINT(_L("SwapDriveMapping()")); + TInt firstLocalDrv=iMapping[aFirstDrive]; + TInt secondLocalDrv=iMapping[aSecondDrive]; + + // First, check this swap doesn't affect removable drives + TInt socket; + if (iLocalDrives[firstLocalDrv].Handle()!=0 && iLocalDrives[firstLocalDrv].IsRemovable(socket)) + return(KErrAccessDenied); + if (iLocalDrives[secondLocalDrv].Handle()!=0 && iLocalDrives[secondLocalDrv].IsRemovable(socket)) + return(KErrAccessDenied); + + // Now swap the mappings over + iMapping[aFirstDrive]=secondLocalDrv; + iMapping[aSecondDrive]=firstLocalDrv; + + iReverseMapping[firstLocalDrv]=aSecondDrive; + iReverseMapping[secondLocalDrv]=aFirstDrive; + + // Finally, swap the drive names over + HBufC* drvName=TheDriveNames[aSecondDrive]; + TheDriveNames[aSecondDrive]=TheDriveNames[aFirstDrive]; + TheDriveNames[aFirstDrive]=drvName; + return(KErrNone); + } + +void LocalDrives::CompleteNotifications(TInt aSocket) +// +// +// + { + __ASSERT_DEBUG(aSocket>=0 && aSocket driveDes; + driveDes.Append((TChar)aDrive+(TChar)'A'); + driveDes.Append((TChar)':'); + FsNotificationManager::HandleChange(NULL,driveDes,TFsNotification::EMediaChange); + } +#endif //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION + + //If this is a multislot device we should update mappings here. + TheDrives[aDrive].MultiSlotDriveCheck(); + } + } + +TInt LocalDrives::GetDriveFromLocalDrive(TInt aLocDrv) +// +// +// + { + return iReverseMapping[aLocDrv]; + } + + +CNotifyMediaChange::CNotifyMediaChange(RLocalDrive* aDrive,TInt aSocketNo) +// +// Constructor +// + : CActive(EPriorityHigh), iDrive(aDrive), iSocket(aSocketNo) + {} + +void CNotifyMediaChange::RunL() +// +// Notification that a card has been mounted/removed +// + { + LocalDrives::CompleteNotifications(iSocket); + iDrive->NotifyChange(&iStatus); + SetActive(); + } + + +CExtNotifyMediaChange::CExtNotifyMediaChange(CExtProxyDrive* aDrive) +// +// Constructor +// + : CActive(EPriorityHigh), + iDrive(aDrive), + iPtr((TUint8*)&TheDrives[aDrive->DriveNumber()].iChanged,sizeof(TBool)) + { + } + + +CExtNotifyMediaChange* CExtNotifyMediaChange::NewL(CExtProxyDrive* aDrive) + { + CExtNotifyMediaChange* pSelf = new(ELeave) CExtNotifyMediaChange(aDrive); + + CleanupStack::PushL(pSelf); + pSelf->ConstructL(); + CleanupStack::Pop(); + + return pSelf; + } + +void CExtNotifyMediaChange::ConstructL() + { + CActiveSchedulerFs::Add(this); + + TRAPD(err, RunL()); + if(err != KErrNone) + Deque(); + + User::LeaveIfError(err); + } + +CExtNotifyMediaChange::~CExtNotifyMediaChange() + { + Cancel(); + } + +void CExtNotifyMediaChange::RequestL() + { + if (!IsActive()) + { + User::LeaveIfError(iDrive->NotifyChange(iPtr, &iStatus)); + SetActive(); + } + } + +void CExtNotifyMediaChange::DoCancel() + { + iDrive->NotifyChangeCancel(); + } + +void CExtNotifyMediaChange::RunL() + { + if(iStatus==KErrDisconnected || iStatus==KErrCancel) + return; + + TInt driveNum = iDrive->DriveNumber(); + LocalDrives::CompleteDriveNotifications(driveNum); + + /* NOTE: We need SetChanged here though the iChanged variable is set in the MSC, since the cache is not getting cleared + (inside the CompleteDriveNotifications call) during the initial first notification */ + TheDrives[driveNum].SetChanged(ETrue); + + if(iStatus != KErrNotSupported) + { + RequestL(); + } + } + + +