diff -r 000000000000 -r c9bc50fca66e usbmgmt/usbmgr/host/functiondrivers/ms/msmm/referencepolicyplugin/src/referencepolicyplugin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usbmgmt/usbmgr/host/functiondrivers/ms/msmm/referencepolicyplugin/src/referencepolicyplugin.cpp Tue Feb 02 02:02:59 2010 +0200 @@ -0,0 +1,393 @@ +/* +* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "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: +* +*/ + +/** + @file + @internalComponent +*/ + +#include "referencepolicyplugin.h" +#include +#include +#include +#include +#include "refppnotificationman.h" +#include "srvpanic.h" + +#ifdef __FLOG_ACTIVE +_LIT8(KLogComponent, "UsbHostMsmmRefPP"); +#endif + +// Global Variables +const TUid KHostMsRepositoryUid = {0x10285c46}; +const TUint32 KPermittedRangeUid = 0x00010000; +const TUint32 KForbiddenListUid = 0x00010001; +const TUint32 KMaxHistoryCountUid = 0x00010002; +const TUint32 KOTGCapableSuspendTimeUid = 0x00010003; +const TUint32 KMediaPollingTimeUid = 0x00010004; +const TUint32 KHistoryCountUid = 0x00010100; +const TUint32 KFirstHistoryUid = 0x00010101; + +const TUint KHistoryGranularity = 0x8; +const TUint KPermittedDrvRangeBufLen = 0x3; + +CReferencePolicyPlugin::~CReferencePolicyPlugin() + { + LOG_FUNC + Cancel(); + ClearHistory(); // Remove all buffered history record. + delete iRepository; + delete iNotificationMan; + iFs.Close(); + } + +CReferencePolicyPlugin* CReferencePolicyPlugin::NewL() + { + LOG_STATIC_FUNC_ENTRY + CReferencePolicyPlugin* self = new (ELeave) CReferencePolicyPlugin; + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + + return self; + } + +void CReferencePolicyPlugin::RetrieveDriveLetterL(TText& aDriveName, + const TPolicyRequestData& aData, TRequestStatus& aStatus) + { + LOG_FUNC + Cancel(); + aStatus = KRequestPending; + iClientStatus = &aStatus; + + RetrieveDriveLetterL(aDriveName, aData); + // In a licensee owned policy plugin, it shall complete client + // request in RunL() in general + Complete(KErrNone); + } + +void CReferencePolicyPlugin::CancelRetrieveDriveLetter() + { + LOG_FUNC + Cancel(); + } + +void CReferencePolicyPlugin::SaveLatestMountInfoL( + const TPolicyMountRecord& aData, TRequestStatus& aStatus) + { + LOG_FUNC + Cancel(); + aStatus = KRequestPending; + iClientStatus = &aStatus; + + SaveLatestMountInfoL(aData); + // In a licensee owned policy plugin, it shall complete client + // request in RunL() in general + Complete(KErrNone); + } + +void CReferencePolicyPlugin::CancelSaveLatestMountInfo() + { + LOG_FUNC + Cancel(); + } + +void CReferencePolicyPlugin::SendErrorNotificationL( + const THostMsErrData& aErrData) + { + LOG_FUNC + iNotificationMan->SendErrorNotificationL(aErrData); + } + +void CReferencePolicyPlugin::GetSuspensionPolicy(TSuspensionPolicy& aPolicy) + { + LOG_FUNC + aPolicy = iSuspensionPolicy; + } + +void CReferencePolicyPlugin::DoCancel() + { + LOG_FUNC + // No more work need to do in current implementation of reference + // policy plugin. + // In a licensee owned policy plugin, it shall complete client + // request here with KErrCancel. + } + +void CReferencePolicyPlugin::RunL() + { + LOG_FUNC + // No more work need to do in current implementation of reference + // policy plugin. + // In a licensee owned policy plugin, it shall complete client + // request here with a proper error code. + } + +CReferencePolicyPlugin::CReferencePolicyPlugin() : +CMsmmPolicyPluginBase(), +iHistory(KHistoryGranularity) + { + LOG_FUNC + CActiveScheduler::Add(this); + } + +void CReferencePolicyPlugin::ConstructL() + { + LOG_FUNC + iRepository = CRepository::NewL(KHostMsRepositoryUid); + User::LeaveIfError(iFs.Connect()); + iNotificationMan = CMsmmPolicyNotificationManager::NewL(); + RetrieveHistoryL(); + AvailableDriveListL(); + TInt value = 0; + User::LeaveIfError(iRepository->Get( + KOTGCapableSuspendTimeUid, value)); + iSuspensionPolicy.iOtgSuspendTime = value; + User::LeaveIfError(iRepository->Get( + KMediaPollingTimeUid, value)); + iSuspensionPolicy.iStatusPollingInterval = value; + } + +void CReferencePolicyPlugin::RetrieveDriveLetterL(TText& aDriveName, + const TPolicyRequestData& aData) + { + LOG_FUNC + + TDriveList availableNames; + FilterFsForbiddenDriveListL(availableNames); + + if (!availableNames.Length()) + { + // Not any drive letter available + User::Leave(KErrNotFound); + } + + // According to REQ8922, When a particular Logical Unit is mounted + // for the first time, RefPP shall always try to allocate an + // available and unused drive letter to it. Only if such a drive letter + // can not be found, RefPP shall use the first one in available name + // list; + + // Initialize aDriveName by the first available drive letter + aDriveName = availableNames[0]; + // Find first such drive letter from available letter list. If it can + // be found, it will be used. + FindFirstNotUsedDriveLetter(availableNames, aDriveName); + // Search history record + TInt historyIndex = SearchHistoryByLogicUnit(aData); + if (KErrNotFound != historyIndex) + { + // Find a match one in history + const TPolicyMountRecord& history = *iHistory[historyIndex]; + TInt location = availableNames.Locate(TChar(history.iDriveName)); + if (KErrNotFound != location) + { + // And it is available now. RefPP allocate it to the + // LU currently mounted. + aDriveName = history.iDriveName; + } + } + } + +void CReferencePolicyPlugin::SaveLatestMountInfoL( + const TPolicyMountRecord& aData) + { + LOG_FUNC + + if (iMaxHistoryRecCount == 0) // This policy disable history + { + return; + } + + TPolicyMountRecord* historyRecord = + new (ELeave) TPolicyMountRecord(aData); + CleanupStack::PushL(historyRecord); + TInt historyIndex = SearchHistoryByLogicUnit(aData.iLogicUnit); + if (KErrNotFound == historyIndex) + { + // No matched record exist + if (iHistory.Count() == iMaxHistoryRecCount) + { + // Remove the oldest entity + delete iHistory[0]; + iHistory.Remove(0); + } + } + else + { + // Remove the replaced entity + delete iHistory[historyIndex]; + iHistory.Remove(historyIndex); + } + iHistory.AppendL(historyRecord); // Push the new entity + CleanupStack::Pop(historyRecord); + + TUint32 historyRecordUid = KFirstHistoryUid; + User::LeaveIfError(iRepository->Set(KHistoryCountUid, iHistory.Count())); + for (TInt index = 0; index < iHistory.Count(); index++) + { + TPckg historyPckg(*iHistory[index]); + User::LeaveIfError(iRepository->Set(historyRecordUid++, historyPckg)); + } + } + +void CReferencePolicyPlugin::Complete(TInt aError) + { + LOG_FUNC + User::RequestComplete(iClientStatus, aError); + } + +void CReferencePolicyPlugin::PrepareAvailableDriveList() + { + LOG_FUNC + iAvailableDrvList.SetLength(KMaxDrives); + iAvailableDrvList.Fill(0, KMaxDrives); + } + +void CReferencePolicyPlugin::AvailableDriveListL() + { + LOG_FUNC + TBuf8 permittedRange; + TDriveList forbiddenList; + + PrepareAvailableDriveList(); + + User::LeaveIfError(iRepository->Get(KPermittedRangeUid, permittedRange)); + User::LeaveIfError(iRepository->Get(KForbiddenListUid, forbiddenList)); + + for (TInt index = 'A'; index <= 'Z'; index++ ) + { + if ((index >= permittedRange[0]) && (index <= permittedRange[1])) + { + if (KErrNotFound == forbiddenList.Locate(TChar(index))) + { + // Permitted + iAvailableDrvList[index - 'A'] = 0x01; + } + } + } + } + +void CReferencePolicyPlugin::FilterFsForbiddenDriveListL( + TDriveList& aAvailableNames) + { + LOG_FUNC + TDriveList names; + names.SetLength(KMaxDrives); + + TDriveList drives; + User::LeaveIfError(iFs.DriveList(drives)); + + TUint count(0); + for (TInt index = 0; index < KMaxDrives; index++ ) + { + if ((drives[index] == 0x0) && (iAvailableDrvList[index])) + { + names[count++] = index+'A'; + } + } + names.SetLength(count); + aAvailableNames = names; + } + +void CReferencePolicyPlugin::FindFirstNotUsedDriveLetter( + const TDriveList& aAvailableNames, + TText& aDriveName) + { + LOG_FUNC + TDriveList usedLetter; + TUint index = 0; + for (index = 0; index < iHistory.Count(); index++) + { + const TPolicyMountRecord& record = *iHistory[index]; + usedLetter.Append(TChar(record.iDriveName)); + } + for (index = 0; index < aAvailableNames.Length(); index++) + { + if (usedLetter.Locate(aAvailableNames[index]) == KErrNotFound) + { + aDriveName = aAvailableNames[index]; + return; // A unused drive letter found out + } + } + } + +// Retrieve history from CR +void CReferencePolicyPlugin::RetrieveHistoryL() + { + LOG_FUNC + // Read history record number from CR + TInt historyCount(0); + User::LeaveIfError( + iRepository->Get(KMaxHistoryCountUid, iMaxHistoryRecCount)); + User::LeaveIfError(iRepository->Get(KHistoryCountUid, historyCount)); + + TUint32 historyRecordUid = KFirstHistoryUid; + if (historyCount) + { + TPolicyMountRecord historyRecord; + TPckg historyArray(historyRecord); + for (TInt index = 0; index < historyCount; index++) + { + User::LeaveIfError(iRepository->Get(historyRecordUid++, + historyArray)); + TPolicyMountRecord* record = new (ELeave) TPolicyMountRecord; + memcpy(record, &historyRecord, sizeof(TPolicyMountRecord)); + CleanupStack::PushL(record); + iHistory.AppendL(record); + CleanupStack::Pop(record); + } + } + } + +// Remove all buffered history +void CReferencePolicyPlugin::ClearHistory() + { + LOG_FUNC + iHistory.ResetAndDestroy(); + iHistory.Close(); + } + +// Search in history for a logic unit +TInt CReferencePolicyPlugin::SearchHistoryByLogicUnit( + const TPolicyRequestData& aLogicUnit) const + { + LOG_FUNC + TInt ret(KErrNotFound); + TUint count = iHistory.Count(); + for (TUint index = 0; index < count; index ++) + { + const TPolicyMountRecord& record = *iHistory[index]; + const TPolicyRequestData& logicalUnit = record.iLogicUnit; + + if ((logicalUnit.iVendorId == aLogicUnit.iVendorId) && + (logicalUnit.iProductId == aLogicUnit.iProductId) && + (logicalUnit.iBcdDevice == aLogicUnit.iBcdDevice) && + (logicalUnit.iConfigurationNumber == aLogicUnit.iConfigurationNumber) && + (logicalUnit.iInterfaceNumber == aLogicUnit.iInterfaceNumber) && + (logicalUnit.iSerialNumber == aLogicUnit.iSerialNumber) && + (logicalUnit.iOtgInformation == aLogicUnit.iOtgInformation)) + { + // Matched + return index; + } + } + // Can't find any matched records + return ret; + } + +// End of file