diff -r 000000000000 -r 96e5fb8b040d userlibandfileserver/fileserver/shostmassstorage/msproxy/hostusbmsproxy.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/userlibandfileserver/fileserver/shostmassstorage/msproxy/hostusbmsproxy.cpp Thu Dec 17 09:24:54 2009 +0200 @@ -0,0 +1,738 @@ +/* +* Copyright (c) 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: +* +*/ +// +// hostusbmsproxy.cpp +// +// This file system extension provides a way to access a drive on the MS system in "raw format". +// It can be used to test large files / drives +// + +/** @file +@internalTechnology +*/ + +#include + +#include "hostusbmsproxy.h" +#include "debug.h" + + +CUsbHostMsProxyDrive::CUsbHostMsProxyDrive(CMountCB* aMount, CExtProxyDriveFactory* aDevice) +: CExtProxyDrive(aMount,aDevice) + { + __MSFNSLOG + } + +CUsbHostMsProxyDrive::~CUsbHostMsProxyDrive() + { + __MSFNSLOG + iUsbHostMsLun.UnInitialise(); + } + +TInt CUsbHostMsProxyDrive::InitialiseOffset(TCapsInfo& aCapsInfo) + { + __MSFNSLOG + const TInt KPartitionInfoSize = TMsDataMemMap::KSectorSize; + TBuf8 partitionInfo; + TInt r; + + r = iUsbHostMsLun.Read(0 , KPartitionInfoSize, (TDes8 &) partitionInfo); + if (r != KErrNone) + { + __PXYPRINT1(_L("!! Reading medium failed with %d !!"), r); + return r; + } + TUint8 *iIntBuf = (TUint8 *) partitionInfo.Ptr(); + + // Read of the first sector successful so check for a Master Boot Record + if (*(TUint16*)(&iIntBuf[KMBRSignatureOffset])!= KMBRSignature) + { + __PXYPRINT(_L("MBR not present")); + iMsDataMemMap.Reset(); + } + else + { + // Move the partition entries to a 4 byte boundary + memcpy(&iIntBuf[0],&iIntBuf[KMBRFirstPartitionOffset],(sizeof(TMBRPartitionEntry)<<2)); + // Search for a x86 default boot partition - let this be the first + TMBRPartitionEntry* pe = (TMBRPartitionEntry*)(&iIntBuf[0]); + + TInt firstValidPartitionCount = -1; + TInt defaultPartitionNumber = -1; + TInt partitionCount = 0; + for (TInt i = 0; i < KMBRMaxPrimaryPartitions; i++, pe++) + { + if (pe->IsValidDosPartition() || pe->IsValidFAT32Partition()) + { + __PXYPRINT(_L("Found a Valid Partition")); + partitionCount++; + + if (firstValidPartitionCount < 0) + firstValidPartitionCount = i; + + if (pe->iX86BootIndicator == KBootIndicatorBootable) + { + defaultPartitionNumber = i; + break; + } + } + else + { + __PXYPRINT(_L("!! Invalid Partition !!")); + } + } + + // Check the validity of the partition address boundaries + if (partitionCount > 0) + { + __PXYPRINT1(_L("Using Partition %d"), partitionCount); + pe = (TMBRPartitionEntry*)(&iIntBuf[0]); + TInt partitionIndex = firstValidPartitionCount; + if (defaultPartitionNumber > 0) + { + partitionIndex = defaultPartitionNumber; + } + + TMBRPartitionEntry& partitionEntry = pe[partitionIndex]; + + iMsDataMemMap.InitDataArea(partitionEntry.iFirstSector, + partitionEntry.iNumSectors); + __PXYPRINT2(_L("paritioncount = %d defaultpartition = %d"), + partitionCount, partitionIndex); + __PXYPRINT2(_L("iFirstSector = x%x iNumSectors = x%x"), + partitionEntry.iFirstSector, + partitionEntry.iNumSectors); + } + else + { + __PXYPRINT(_L("No partition found")); + iMsDataMemMap.InitDataArea(0, aCapsInfo.iNumberOfBlocks); + __PXYPRINT2(_L("iFirstSector = x%x iNumSectors = x%x"), + 0, aCapsInfo.iNumberOfBlocks); + } + } + return KErrNone; + } + +/** +Initialise the proxy drive. +@return system wide error code. +*/ +TInt CUsbHostMsProxyDrive::Initialise() + { + __MSFNSLOG + __HOSTPRINT(_L(">>> CUsbHostMsProxyDrive::Initialise()")); + + if(Mount()) + { + // as we can't currently handle remounting devices that have + // been removed by unplugging the USB cable, disable critical notifiers + // as there's no point in asking the user to re-insert the disk. + Mount()->SetNotifyOff(); + } + + // Check for media presence + TCapsInfo capsInfo; + TInt err = iUsbHostMsLun.Caps(capsInfo); + + if (err == KErrNone) + { + err = InitialiseOffset(capsInfo); + } + + __HOSTPRINT1(_L("<<< CUsbHostMsProxyDrive::Initialise() err = %d"), err); + return err; + } + +TInt CUsbHostMsProxyDrive::SetInfo(const RMessage2 &msg, TAny* aMessageParam2, TAny* aMessageParam3) + { + __MSFNSLOG + __HOSTPRINT(_L(">>> CUsbHostMsProxyDrive::SetInfo()")); + TMassStorageUnitInfo iUnitInfo; + TPckg infoPckg(iUnitInfo); + TRAPD(err, msg.ReadL(2, infoPckg)); + + if(err != KErrNone) + { + __PXYPRINT1(_L("Cant read from the RMessage %d"), err); + __HOSTPRINT1(_L("<<< CUsbHostMsProxyDrive::SetInfo() err = %d"), err); + return err; + } + + err = iUsbHostMsLun.Initialise(msg, 3, iUnitInfo.iLunID); + if(err != KErrNone) + { + __PXYPRINT1(_L("Initialising logical unit failed %d"), err); + __HOSTPRINT1(_L("<<< CUsbHostMsProxyDrive::SetInfo() err = %d"), err); + return err; + } + + __HOSTPRINT1(_L("<<< CUsbHostMsProxyDrive::SetInfo() err = %d"), err); + return err; + } + +TInt CUsbHostMsProxyDrive::Dismounted() + { + __MSFNSLOG + return KErrNone; + } + +TInt CUsbHostMsProxyDrive::Enlarge(TInt /*aLength*/) + { + __MSFNSLOG + return KErrNotSupported; + } + + +TInt CUsbHostMsProxyDrive::ReduceSize(TInt /*aPos*/, TInt /*aLength*/) + { + __MSFNSLOG + return KErrNotSupported; + } + +#define GetIndex(msg, aAddress, aIndex) \ + aIndex = msg.Ptr0() == aAddress ? 0 : \ + msg.Ptr1() == aAddress ? 1 : \ + msg.Ptr1() == aAddress ? 2 : \ + msg.Ptr1() == aAddress ? 3 : -1; + +/** +Read from the proxy drive. + +@param aPos The address from where the read begins. +@param aLength The length of the read. +@param aTrg A descriptor of the memory buffer from which to read. +@param aThreadHandle The handle-number representing the drive thread. +@param aOffset Offset into aTrg to read the data from. + +@return system wide error code. +*/ +TInt CUsbHostMsProxyDrive::Read(TInt64 aPos, TInt aLength, + const TAny* aTrg, TInt aThreadHandle, TInt aOffset) + { + __MSFNSLOG + __HOSTPRINT4(_L("\n>>> HOST Read Pos=0x%lx LBA=0x%lx 0x%x 0x%x"), + aPos, aPos/KBlockSize, aLength, aOffset); + + TBool localMessage = (aThreadHandle == KLocalMessageHandle); + + // + // Set file position to where we want to read... + // + if(!localMessage) + { + RMessage2 msg(*(RMessagePtr2 *) &aThreadHandle); + localMessage = (msg.Handle() == KLocalMessageHandle); + } + + TInt index = 0; + if (!localMessage) + { + RMessage2 msg(*(RMessagePtr2 *) &aThreadHandle); + GetIndex(msg, aTrg, index); + + if (index < 0) + { + __HOSTPRINT1(_L("<<< HOST Read ret=%d"), KErrArgument); + return KErrArgument; + } + } + + /* Calculate the end position */ + TInt64 end = aPos + static_cast(aLength); + + /* check whether there is enough source data to write to the destination descriptor */ + TInt64 truncate; + if(localMessage) + { + truncate = aLength - (((TPtr8* )aTrg)->MaxLength() - aOffset); + __PXYPRINT1(_L("Descriptor length: %08x"), ((TPtr8* )aTrg)->MaxLength()); + } + else + { + RMessage2 msg(*(RMessagePtr2 *) &aThreadHandle); + truncate = aLength - (msg.GetDesMaxLength(index) - aOffset); + __PXYPRINT1(_L("Descriptor length: %08x"), msg.GetDesMaxLength(index)); + } + + __PXYPRINT1(_L("Offset: %08x"), aOffset); + __PXYPRINT1(_L("Truncate: 0x%lx"), truncate); + + if (truncate > 0) + { + end -= truncate; + } + + iBuf.SetMax(); + TInt r; + TInt64 mediaPos; + while (aPos < end) + { + TInt len = end - aPos; + mediaPos = aPos; + r = iMsDataMemMap.CheckBlockInRange(mediaPos, len); + if (r != KErrNone) + { + __HOSTPRINT1(_L("<<< HOST Read ret=%d"), r); + return r; + } + + if (localMessage) + { + TPtr8* pTrgPtr = (TPtr8*)aTrg; + TPtr8 trgDes((TUint8*)(pTrgPtr->MidTPtr(aOffset).Ptr()), pTrgPtr->MaxLength() - aOffset); + r = iUsbHostMsLun.Read(mediaPos, len, trgDes); + if (r != KErrNone) + return r; + pTrgPtr->SetLength(aOffset + trgDes.Length()); + } + else + { + if (len > iBuf.MaxLength()) + len = iBuf.MaxLength(); + + r = iUsbHostMsLun.Read(mediaPos, len, iBuf); + if (r != KErrNone) + { + __HOSTPRINT1(_L("<<< HOST Read ret=%d"), r); + return r; + } + + iBuf.SetLength(len); + + RMessage2 msg(*(RMessagePtr2 *) &aThreadHandle); + r = msg.Write(index, iBuf, aOffset); + if (r != KErrNone) + { + __HOSTPRINT1(_L("<<< HOST Read ret=%d"), r); + return r; + } + } + + aPos += len; + aOffset += len; + } + + __HOSTPRINT1(_L("<<< HOST Read ret=%d"), KErrNone); + return KErrNone; + } + + +/** +Read from the proxy drive, and pass flags to driver. + +@param aPos The address from where the read begins. +@param aLength The length of the read. +@param aTrg A descriptor of the memory buffer from which to read. +@param aThreadHandle The handle-number representing the drive thread. +@param aOffset Offset into aTrg to read the data from. +@param aFlags Flags to be passed into the driver. + +@return system wide error code. +*/ +TInt CUsbHostMsProxyDrive::Read(TInt64 aPos, TInt aLength, + const TAny* aTrg, TInt aThreadHandle, TInt aOffset, TInt /* aFlags */) + { + __MSFNSLOG + return Read(aPos, aLength, aTrg, aThreadHandle, aOffset); + } + +/** +Read from the proxy drive. + +@param aPos The address from where the read begins. +@param aLength The length of the read. +@param aTrg A descriptor of the memory buffer from which to read. + +@return system wide error code. +*/ +TInt CUsbHostMsProxyDrive::Read(TInt64 aPos, TInt aLength, TDes8& aTrg) + { + __MSFNSLOG + __HOSTPRINT3(_L("\n>>> HOST Read Pos=0x%lx LBA=0x%lx 0x%x"), + aPos, aPos/KBlockSize, aLength); + return iUsbHostMsLun.Read(iMsDataMemMap.GetDataPos(aPos), aLength, aTrg); + } + +/** +Write to the proxy drive. + +@param aPos The address from where the write begins. +@param aLength The length of the write. +@param aSrc A descriptor of the memory buffer from which to write. +@param aThreadHandle The handle-number representing the drive thread. +@param aOffset Offset into aSrc to write the data to. + +@return system wide error code. +*/ +TInt CUsbHostMsProxyDrive::Write(TInt64 aPos, TInt aLength, + const TAny* aSrc, TInt aThreadHandle, TInt aOffset) + { + // + // Set file position to where we want to write... + // + __MSFNSLOG + __HOSTPRINT4(_L("\n>>> HOST Write Pos=0x%lx LBA=0%lx 0x%x 0x%x"), + aPos, aPos/KBlockSize, aLength, aOffset); + + TBool localMessage = (aThreadHandle == KLocalMessageHandle); + + if(!localMessage) + { + RMessage2 msg(*(RMessagePtr2 *) &aThreadHandle); + localMessage = (msg.Handle() == KLocalMessageHandle); + } + + TInt index = 0; + if(!localMessage) + { + RMessage2 msg(*(RMessagePtr2 *) &aThreadHandle); + GetIndex(msg, aSrc, index); + + if (index < 0) + return KErrArgument; + } + + /* Calculate the end position */ + TInt64 end = aPos + static_cast(aLength); + /* check whether there is enough source data to read */ + TInt64 truncate; + if (localMessage) + { + truncate = aLength - (((TPtr8* )aSrc)->Length() - aOffset); + __PXYPRINT1(_L("Descriptor length: %08x"), ((TPtr8* )aSrc)->Length()); + } + else + { + RMessage2 msg(*(RMessagePtr2 *) &aThreadHandle); + truncate = aLength - (msg.GetDesLength(index) - aOffset); + __PXYPRINT1(_L("Descriptor length: %08x"), msg.GetDesLength(index)); + } + + __PXYPRINT1(_L("Offset: %08x"), aOffset); + __PXYPRINT1(_L("Truncate: 0x%lx"), truncate); + + /* if truncate is > 0 we are short of source data as claimed by the aLength. Hence adjust the 'end' */ + if (truncate > 0) + { + end -= truncate; + } + + iBuf.SetMax(); + + TInt r; + TInt64 mediaPos; + while (aPos < end) + { + TInt len = end - aPos; + mediaPos = aPos; + r = iMsDataMemMap.CheckBlockInRange(mediaPos, len); + if (r != KErrNone) + { + __HOSTPRINT1(_L("<<< HOST Write ret=%d"), r); + return r; + } + + if (localMessage) + { + r = iUsbHostMsLun.Write(mediaPos, len, ((TPtr8*)aSrc)->MidTPtr(aOffset)); + + if (r != KErrNone) + { + __HOSTPRINT1(_L("<<< HOST Write ret=%d"), r); + return r; + } + } + else + { + if (len > iBuf.Length()) + len = iBuf.Length(); + + RMessage2 msg(*(RMessagePtr2 *) &aThreadHandle); + r = msg.Read(index, iBuf, aOffset); + if (r != KErrNone) + { + __HOSTPRINT1(_L("<<< HOST Write ret=%d"), r); + return r; + } + + r = iUsbHostMsLun.Write(mediaPos, len, iBuf); + if (r != KErrNone) + { + __HOSTPRINT1(_L("<<< HOST Write ret=%d"), r); + return r; + } + } + + aPos += len; + aOffset += len; + } + + __HOSTPRINT1(_L("<<< HOST Write ret=%d"), KErrNone); + return KErrNone; + } + +/** +Write to the proxy drive and pass flags to driver + +@param aPos The address from where the write begins. +@param aLength The length of the write. +@param aSrc A descriptor of the memory buffer from which to write. +@param aThreadHandle The handle-number representing the drive thread. +@param aOffset Offset into aSrc to write the data to. +@param aFlags Flags to be passed into the driver. + +@return system wide error code. +*/ +TInt CUsbHostMsProxyDrive::Write(TInt64 aPos, TInt aLength, + const TAny* aSrc, TInt aThreadHandle, TInt aOffset, TInt /* aFlags */) + { + __MSFNSLOG + return Write(aPos, aLength, aSrc, aThreadHandle, aOffset); + } + +/** +Write to the proxy drive. + +@param aPos The address from where the write begins. +@param aSrc A descriptor of the memory buffer from which to write. + +@return system wide error code. +*/ +TInt CUsbHostMsProxyDrive::Write(TInt64 aPos,const TDesC8& aSrc) + { + __MSFNSLOG + __HOSTPRINT3(_L("\n>>> HOST Write Pos=0x%lx LBA=0x%lx 0x%x"), + aPos, aPos/KBlockSize, aSrc.Length()); + return iUsbHostMsLun.Write(iMsDataMemMap.GetDataPos(aPos), aSrc.Length(), aSrc); + } + +/** +Get the proxy drive's capabilities information. + +@param anInfo A descriptor of the connected drives capabilities. + +@return system wide error code +*/ +TInt CUsbHostMsProxyDrive::Caps(TDes8& anInfo) + { + __MSFNSLOG + __HOSTPRINT(_L("\n>>> HOST Caps")); + TLocalDriveCapsV6Buf caps; + caps.FillZ(); + + caps().iType = EMediaHardDisk; + caps().iBattery = EBatNotSupported; + caps().iDriveAtt = KDriveAttLocal | KDriveAttRemovable; + caps().iMediaAtt = KMediaAttFormattable; + caps().iFileSystemId = KDriveFileSysFAT; + caps().iExtraInfo = EFalse; + + TCapsInfo capsInfo; + TInt r = iUsbHostMsLun.Caps(capsInfo); + if (KErrNone == r) + { + caps().iBlockSize = capsInfo.iBlockLength; + TUint64 size = iMsDataMemMap.DataSize(); + if (size == 0) + { + // No valid partitions so specify the size of the disk + size = static_cast(capsInfo.iNumberOfBlocks) * capsInfo.iBlockLength; + } + caps().iSize = size; + + caps().iEraseBlockSize = 0; + + if (capsInfo.iWriteProtect) + { + caps().iMediaAtt |= KMediaAttWriteProtected; + } + __HOSTPRINT4(_L("<<< HOST Caps Block[num=0x%x size=0x%x] Media[size=0x%lx WP=0x%x]"), + capsInfo.iNumberOfBlocks, capsInfo.iBlockLength, + caps().iSize, caps().iMediaAtt); + } + else + { + __HOSTPRINT(_L("<<< HOST Caps Media Not Present")); + caps().iType = EMediaNotPresent; + if(r != KErrNotReady) + r = KErrUnknown; + } + anInfo = caps.Left(Min(caps.Length(),anInfo.MaxLength())); + return r; + } + + + +/** +Format the proxy drive. The drive is assumed to be a single partition. The +partition size is equivalent to the size of the media. + +@param aPos The position of the data which is being formatted. +@param aLength [IN] The length of the data which is being formatted. [OUT] The +length of data formatted, truncated when end of drive is reached. + +@return system wide error code. +*/ +TInt CUsbHostMsProxyDrive::Erase(TInt64 aPos, TInt& aLength) + { + __MSFNSLOG + __HOSTPRINT3(_L("\n HOST Erase Pos=0x%lx LBA=0x%lx 0x%x"), + aPos, aPos/KBlockSize, aLength); + TInt err = iMsDataMemMap.TranslateDataPos(aPos, aLength); + + if (err) + return err; + + err = iUsbHostMsLun.Erase(aPos, aLength); + return err; + } + + +/** +Format the proxy drive. + +@param aPos The position of the data which is being formatted. +@param aLength The length of the data which is being formatted. + +@return system wide error code. +*/ +TInt CUsbHostMsProxyDrive::Format(TInt64 aPos, TInt aLength) + { + __MSFNSLOG + return Erase(aPos, aLength); + } + + +/** +Format the connected drive. + +@param anInfo Device specific format information. + +@return system wide error code. +*/ +TInt CUsbHostMsProxyDrive::Format(TFormatInfo& aInfo) + { + __MSFNSLOG + + const TInt KDefaultMaxBytesPerFormat = 0x100 * TMsDataMemMap::KSectorSize; // 128K + + if (aInfo.i512ByteSectorsFormatted < 0) + return KErrArgument; + + if (!aInfo.iFormatIsCurrent) + { + aInfo.iFormatIsCurrent = ETrue; + aInfo.i512ByteSectorsFormatted = 0; + aInfo.iMaxBytesPerFormat = KDefaultMaxBytesPerFormat; + + TLocalDriveCapsV6Buf caps; + TInt r = Caps(caps); + if (r != KErrNone) + return r; + + iMsDataMemMap.InitDataArea(caps().iSize); + } + + TInt64 pos = static_cast(aInfo.i512ByteSectorsFormatted) << TMsDataMemMap::KFormatSectorShift; + TInt length = aInfo.iMaxBytesPerFormat; + TInt r = Erase(pos, length); + + if (r == KErrNone) + { + length += TMsDataMemMap::KSectorSize - 1; + length >>= TMsDataMemMap::KFormatSectorShift; + aInfo.i512ByteSectorsFormatted += length; + } + + return r; + } + + +TInt CUsbHostMsProxyDrive::NotifyChange(TDes8 &aChanged,TRequestStatus* aStatus) + { + __MSFNSLOG + iUsbHostMsLun.NotifyChange(aChanged, *aStatus); + + if(*aStatus != KRequestPending) + return KErrUnknown; + + return KErrNone; + } + +void CUsbHostMsProxyDrive::NotifyChangeCancel() + { + __MSFNSLOG + iUsbHostMsLun.NotifyChangeCancel(); + } + +TInt CUsbHostMsProxyDrive::SetMountInfo(const TDesC8* /*aMountInfo*/,TInt /*aMountInfoThreadHandle=KCurrentThreadHandle*/) + { + __MSFNSLOG + return KErrNone; + } + +TInt CUsbHostMsProxyDrive::ForceRemount(TUint aFlags) + { + __MSFNSLOG + iUsbHostMsLun.ForceRemount(aFlags); + return KErrNone; + } + +TInt CUsbHostMsProxyDrive::Unlock(TMediaPassword& /*aPassword*/, TBool /*aStorePassword*/) + { + __MSFNSLOG + return KErrNotSupported; + } + +TInt CUsbHostMsProxyDrive::Lock(TMediaPassword& /*aOldPassword*/, TMediaPassword& /*aNewPassword*/, TBool /*aStorePassword*/) + { + __MSFNSLOG + return KErrNotSupported; + } + +TInt CUsbHostMsProxyDrive::Clear(TMediaPassword& /*aPassword*/) + { + __MSFNSLOG + return KErrNotSupported; + } + +TInt CUsbHostMsProxyDrive::ErasePassword() + { + __MSFNSLOG + return KErrNotSupported; + } + +TInt CUsbHostMsProxyDrive::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* aInput) + { + switch(aInterfaceId) + { + case ELocalBufferSupport: + return KErrNone; + case EFinalised: + { + TBool isFinalised = (TBool)aInput; + if(isFinalised) + { + iUsbHostMsLun.SuspendLun(); + } + } + return KErrNone; + default: + return KErrNotSupported; + } + }