Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h)
Have multiple extension sections in the bld.inf, one for each version
of the compiler. The RVCT version building the tools will build the
runtime libraries for its version, but make sure we extract all the other
versions from zip archives. Also add the archive for RVCT4.
/*
* 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 <f32fsys.h>
#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<KPartitionInfoSize> 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<TMassStorageUnitInfo> 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<TInt64>(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<TInt64>(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();
TLocalDriveCapsV6& c = caps();
c.iType = EMediaHardDisk;
c.iConnectionBusType = EConnectionBusUsb;
c.iDriveAtt = KDriveAttLocal | KDriveAttRemovable | KDriveAttExternal;
c.iMediaAtt = KMediaAttFormattable;
c.iFileSystemId = KDriveFileSysFAT;
TCapsInfo capsInfo;
TInt r = iUsbHostMsLun.Caps(capsInfo);
if (KErrNone == r)
{
c.iBlockSize = capsInfo.iBlockLength;
TUint64 size = iMsDataMemMap.DataSize();
if (size == 0)
{
// No valid partitions so specify the size of the disk
size = static_cast<TUint64>(capsInfo.iNumberOfBlocks) * capsInfo.iBlockLength;
}
c.iSize = size;
c.iEraseBlockSize = 0;
if (capsInfo.iWriteProtect)
{
c.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"));
c.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<TInt64>(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;
}
}