sl@0: // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // Implementaion of the media abstraction classs. sl@0: // sl@0: // sl@0: sl@0: /** sl@0: @file sl@0: */ sl@0: sl@0: #include "win_media.h" sl@0: #include "win_media_device.h" sl@0: sl@0: sl@0: //######################################################################################################################### sl@0: //## CMediaBase abstract base class implementation sl@0: //######################################################################################################################### sl@0: sl@0: sl@0: CMediaBase::CMediaBase(TInt aEpocDrvNumber) sl@0: :iEpocDrvNumber((TDriveNumber)aEpocDrvNumber), iReadOnly(0), ipDevice(NULL) sl@0: { sl@0: ASSERT(iEpocDrvNumber >= EDriveA && iEpocDrvNumber <= EDriveZ); sl@0: ipSettingsManager = NULL; sl@0: } sl@0: sl@0: CMediaBase::~CMediaBase() sl@0: { sl@0: Disconnect(); sl@0: delete ipDevice; sl@0: delete ipSettingsManager; sl@0: } sl@0: sl@0: /** sl@0: This method is called in order to disconnect from the media (on dismount) sl@0: */ sl@0: void CMediaBase::Disconnect() sl@0: { sl@0: if(ipDevice) sl@0: ipDevice->Disconnect(); sl@0: } sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: /** sl@0: Get EPOC-style drive capabilities sl@0: @param aCaps - some fields of this structure will be filled with the information from the WinMediaDevice sl@0: @return standard EPOC code sl@0: */ sl@0: TInt CMediaBase::GetEpocCaps(TLocalDriveCaps& aCaps) sl@0: { sl@0: //-- get real drive geometry from the windows device we are using and sl@0: //-- override the native media driver's data sl@0: TDriveGeometry dg; sl@0: ipDevice->GetDriveGeometry(dg); sl@0: aCaps.iSize = dg.TotalSizeInBytes(); sl@0: sl@0: //-- here we can also override other information, like drive and media attributes etc.. sl@0: sl@0: //-- media type sl@0: TUint32 val = ipSettingsManager->TMediaType_Override(); sl@0: if(val) sl@0: aCaps.iType = (TMediaType)val; sl@0: sl@0: //-- media attributes sl@0: TUint32 andMask, orMask; sl@0: ipSettingsManager->MediaAtt_OverrideMasks(andMask, orMask); sl@0: aCaps.iMediaAtt &= andMask; sl@0: aCaps.iMediaAtt |= orMask; sl@0: sl@0: //-- drive attributes sl@0: ipSettingsManager->DriveAtt_OverrideMasks(andMask, orMask); sl@0: aCaps.iDriveAtt &= andMask; sl@0: aCaps.iDriveAtt |= orMask; sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: //######################################################################################################################### sl@0: //## CGenericBlockMedia class implementation sl@0: //######################################################################################################################### sl@0: sl@0: sl@0: sl@0: CGenericBlockMedia::CGenericBlockMedia(TInt aEpocDrvNumber) sl@0: :CMediaBase(aEpocDrvNumber) sl@0: { sl@0: } sl@0: sl@0: CGenericBlockMedia::~CGenericBlockMedia() sl@0: { sl@0: } sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: sl@0: /** sl@0: Connect to the media, i.e. do mounting job. sl@0: Read settings from the ini file, instantiate "windows device" class.. sl@0: */ sl@0: TInt CGenericBlockMedia::Connect() sl@0: { sl@0: __LOG1(_L("#-- CGenericBlockMedia::Connect(), epocDrv:%d"), iEpocDrvNumber); sl@0: sl@0: if(ipDevice) sl@0: { sl@0: ASSERT(0); sl@0: return KErrInUse; sl@0: } sl@0: sl@0: //-- initialise an object to work with settings from ini file sl@0: if(!ipSettingsManager) sl@0: { sl@0: ipSettingsManager = TSettingsManager::Create(iEpocDrvNumber); sl@0: if(!ipSettingsManager) sl@0: { sl@0: __LOG(_L("#-- Can not create TSettingsManager!")); sl@0: return KErrGeneral; sl@0: } sl@0: } sl@0: sl@0: sl@0: //-- 1. obtain and process windows device name sl@0: char szDevName[KMaxFileName]; sl@0: Settings().WinDeviceName(szDevName, sizeof(szDevName)); sl@0: sl@0: if(strlen(szDevName) < 4) sl@0: { sl@0: __LOG(_L("#-- CGenericBlockMedia::Connect() Bad device name!")); sl@0: __LOGF(szDevName); sl@0: return KErrBadName; sl@0: } sl@0: sl@0: //-- 1.1 find out if it is the physical volume or image file sl@0: TBool bImageFile = ETrue; sl@0: const char szDevPrefix[] = "\\\\.\\"; sl@0: if( memcmp(szDevName, szDevPrefix, strlen(szDevPrefix)) == 0) sl@0: {//-- this is a physical device sl@0: bImageFile = EFalse; sl@0: } sl@0: sl@0: sl@0: //-- 2. instantinate an interface to the Windows media device sl@0: TInt nRes; sl@0: sl@0: if(bImageFile) sl@0: {//-- device name corresponds to the image file sl@0: ipDevice = new CWinImgFileDevice; sl@0: } sl@0: else sl@0: {//-- device name corresponds to the physical volume file sl@0: ipDevice = new CWinVolumeDevice; sl@0: } sl@0: sl@0: ASSERT(ipDevice); sl@0: sl@0: sl@0: //-- 3. other parameters sl@0: iReadOnly = Settings().IsReadOnly(); sl@0: sl@0: //-- set and validate parameters sl@0: TMediaDeviceParams connectParams; sl@0: sl@0: const TUint32 bps = Settings().MediaSectorSize(); sl@0: if(bps > 0) sl@0: {//-- some value is provided in the ini file. sl@0: if(!IsPowerOf2(bps) || bps < KDefaultSectorSz || bps > 4096) sl@0: { sl@0: __LOG1(_L("#-- 'BytesPerSector' value is incorrect! :%d"), bps); sl@0: return KErrArgument; sl@0: } sl@0: } sl@0: sl@0: connectParams.iDrvGeometry.iBytesPerSector = bps; sl@0: sl@0: //-- !!! chech size here!! sl@0: connectParams.iDrvGeometry.iSizeInSectors = Settings().MediaSizeInSectors(); sl@0: connectParams.ipDevName = szDevName; sl@0: connectParams.iReadOnly = iReadOnly; sl@0: sl@0: //-- connect to the device driver sl@0: nRes = ipDevice->Connect(connectParams); sl@0: sl@0: sl@0: return nRes; sl@0: sl@0: } sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: /** sl@0: Disconnect from the media, dismounting. sl@0: */ sl@0: void CGenericBlockMedia::Disconnect() sl@0: { sl@0: __PRINT1(_L("#-- CGenericBlockMedia::Disconnect(), epocDrv:%d"), iEpocDrvNumber); sl@0: ASSERT(ipDevice); sl@0: CMediaBase::Disconnect(); sl@0: } sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: /** sl@0: Read from the media. See corresponding CWinDrvProxyDrive:: method sl@0: */ sl@0: TInt CGenericBlockMedia::Read(TInt64 aPos, TInt aLength, TDes8& aDataDes) sl@0: { sl@0: //__PRINT3(_L("#-- CGenericBlockMedia::Read(), epocDrv:%d, pos:%LU, len:%u"), iEpocDrvNumber, aPos, aLength); sl@0: ASSERT(ipDevice); sl@0: return ipDevice->Read(aPos, aLength, aDataDes); sl@0: } sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: sl@0: /** sl@0: Write to the media. See corresponding CWinDrvProxyDrive:: method sl@0: */ sl@0: TInt CGenericBlockMedia::Write(TInt64 aPos,TInt aLength, const TDesC8& aDataDes) sl@0: { sl@0: //__PRINT3(_L("#-- CGenericBlockMedia::Write(), epocDrv:%d, pos:%LU, len:%u"), iEpocDrvNumber, aPos, aLength); sl@0: sl@0: ASSERT(ipDevice); sl@0: sl@0: if(iReadOnly) sl@0: return KErrAccessDenied; sl@0: sl@0: return ipDevice->Write(aPos, aLength, aDataDes); sl@0: } sl@0: sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: sl@0: /** sl@0: Format the media. sl@0: For "formatting" called CWinMediaDeviceBase::Erase(...) method that fills required media region with zeroes (see its implementation). sl@0: As soon as the number of erased sectors becomes >= max. number of sectors on this media, KErrEof is reurned indicationg the last sl@0: formatting step done. sl@0: */ sl@0: TInt CGenericBlockMedia::Format(TFormatInfo& anInfo) sl@0: { sl@0: if(iReadOnly) sl@0: return KErrAccessDenied; sl@0: sl@0: TInt nRes; sl@0: sl@0: const TUint32 KMaxFmtSteps = 100; //-- max. number of formatting steps. sl@0: sl@0: TDriveGeometry dg; sl@0: ipDevice->GetDriveGeometry(dg); sl@0: const TUint32 KFmtSectors = (dg.iSizeInSectors + (KMaxFmtSteps-1))/ KMaxFmtSteps; //-- how many sectors format during one step sl@0: sl@0: if(anInfo.iFormatIsCurrent == 0) sl@0: {//-- this is a first entry, prepare format data sl@0: iSectorsFormatted = 0; sl@0: anInfo.iFormatIsCurrent = 1; sl@0: } sl@0: sl@0: //-- erase block of the media sl@0: TUint32 sectorsToErase = KFmtSectors; sl@0: if(iSectorsFormatted+KFmtSectors > dg.iSizeInSectors) sl@0: { sl@0: sectorsToErase -= (iSectorsFormatted+KFmtSectors-dg.iSizeInSectors); sl@0: } sl@0: sl@0: nRes = ipDevice->Erase(iSectorsFormatted*dg.iBytesPerSector, sectorsToErase*dg.iBytesPerSector, 0); sl@0: sl@0: if(nRes != KErrNone) sl@0: { sl@0: ASSERT(0); sl@0: return nRes; sl@0: } sl@0: sl@0: iSectorsFormatted+=KFmtSectors; sl@0: anInfo.i512ByteSectorsFormatted = iSectorsFormatted; sl@0: sl@0: if(iSectorsFormatted >= dg.iSizeInSectors) sl@0: return KErrEof; //-- formatted has finished sl@0: sl@0: return KErrNone; sl@0: sl@0: } sl@0: sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: sl@0: /** sl@0: "format" the specified region on the media. See corresponding CWinDrvProxyDrive:: method. sl@0: */ sl@0: TInt CGenericBlockMedia::Format(TInt64 aPos, TInt aLength) sl@0: { sl@0: TInt nRes = ipDevice->Erase(aPos, aLength, 0); sl@0: sl@0: return nRes; //-- shall it be KErrEof ? sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: