This tutorial explains how to write a policy plug-in for Mass Storage Function Drivers.
In this tutorial, you find out how to write a policy plug-in for Mass Storage Function Drivers. By writing a policy plug-in, you can set which drive letters to map the logical mass storage unit to and you can provide the errors to report to users.
For reference code, see src/usb/host/functiondrivers/ms/msmm/referencepolicyplugin....
The high level steps to using the reference code for a policy plug-in are shown here:
Change file names, UIDs and data fields
Rename the files listed here and the classes in the files. In this example we call our policy plug-in MyMSMMPolicyPlugin.
Reference name | Example name | UIDs to change | Data fields to change |
---|---|---|---|
\group\referencepolicyplugin.mmp |
\group\MyMSMMPolicyPlugin.mmp |
The DLL UID (the second UID on the UID line). |
N/A |
inc\referenceplugin.hrh |
inc\MyMSMMPolicyPlugin.hrh |
The implementation UID, change KUidMsmmPolicyPluginImp to the concrete UID for your plugin. |
N/A |
inc\referencepolicyplugin.h |
inc\MyMSMMPolicyPlugin.h |
N/A |
N/A |
data\10285c46.rss |
data\<your_plugin_uid3>.rss.rss |
The DLL UID in the dll_uid line. |
display_name and default_data is reserved for future. (You can change them to any meaningful strings that are suitable for your plugin.) |
data\10285c46.txt |
data\<your_plugin_uid3>.rss.txt |
N/A |
N/A |
src\referencepolicyplugin.cpp |
src\MyMSMMPolicyPlugin.cpp |
N/A |
N/A |
Also change the implementation UID in the ‘proxy’.cpp, in the IMPLEMENTATION_PROXY_ENTRY table.
Edit bld.inf to include MyMSMMPolicyPlugin.mmp in your new group directory, in the usual way.
Implement the functions
The examples here show the implementation of the main functions in the reference code. See the full reference code for the supporting functions.
Write a function to retrieve the available drive letters
The RetrieveDriveLetterL() function allocates a proper drive letter for a newly available logical unit.
It retrieves the licensee's allowed drive letter range. It retrieves the licensee's forbidden drive letter list and removes forbidden letters from the list.
It finds which drive letters are already used and saved to history. It removes these drive letters from the candidate list. If no drive letter is available after that, it uses the first available used drive letter in the licensee permitted drive list.
It retrieves mounting records from the history and tries to find a record of the logical unit that is currently trying to mount. If a logical unit mounts for the first time, it is allocated the first drive letter from the defined range that is not currently being used by another logical unit or that hasn't been allocated to another logical unit in the saved mount information. If a logical unit has previously mounted, it mounts to the same unit again unless that drive letter is being used by another logical unit. If it cannot be mounted to the same letter, another letter is selected from the defined range.
void MyMSMMPolicyPlugin::RetrieveDriveLetterL(TText& aDriveName, const TPolicyRequestData& aData) { TDriveList availableNames; FilterFsForbiddenDriveListL(availableNames); if (!availableNames.Length()) { // Not any drive letter available User::Leave(KErrNotFound); } // When a particular Logical Unit is mounted for the first time, // the reference policy plug-in tries to allocate an // available and unused drive letter to it. Only if such a drive letter // can not be found, it uses the first one in the 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 in history const TPolicyMountRecord& history = *iHistory[historyIndex]; TInt location = availableNames.Locate(TChar(history.iDriveName)); if (KErrNotFound != location) { // And it is available now. reference policy plug-in allocates it to the // logical unit currently mounted. aDriveName = history.iDriveName; } } }
Write a function that saves the latest mount information to the Central Repository
The SaveLatestMountInfoL() saves the latest mount information to the Central Repository.
It first searches for a record of the currently mounted logical unit in the history. If a record is found, it is refreshed with the new drive letter. If a record is not found, a new record is appended.
void MyMSMMPolicyPlugin::SaveLatestMountInfoL( const TPolicyMountRecord& aData) { 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<TPolicyMountRecord> historyPckg(*iHistory[index]); User::LeaveIfError(iRepository->Set(historyRecordUid++, historyPckg)); } }
Write a function to send error notifications
The SendErrorNotificationL() function sends error information to the extended error notifier of the MSMM.
It stores all incoming error notification data into an extendable queue. Because this function is designed to be a synchronous version, an extendable queue avoids losing error data.
void CReferencePolicyPlugin::SendErrorNotificationL( const THostMsErrData& aErrData) { iNotificationMan->SendErrorNotificationL(aErrData); }
CMsmmPolicyNotificationManager starts and sends an error notification data to the extended notifier by calling the notifier interface StartNotifierAndGetResponse().
void CMsmmPolicyNotificationManager::SendNotification() { iNotifier.StartNotifierAndGetResponse( iStatus, KMountPolicyNotifierUid, iErrorQueue[0], iResponse); SetActive(); }
Note: In this reference plug-in, a response is not expected from user, but a concrete policy plugin may want to get the response from user.
Set the mount manager policy definitions
You configure the mount manager policy definitions to be saved in the Central Repository in the TXT file. Each item in the file is broken down as follows:
The first value is its key (an index value)
The second value is the type of this variant
The third value is the default value for initalizing
The last value is meta data (reserved for future).
Define the drive letters available for use by Mass Storage Function Drivers.
# A range of drive letters available to be used for Mass Storage drives. # The first and last available letter shall be stored. 0x00010000 string8 "DX" 0
Define the drive letters forbidden for use by Mass Storage Function Drivers.
# A list of drive letters forbidden by licensee. 0x00010001 string8 "E" 0
Define the maximum number of mounting history records.
# Max mounting history recorded amount. Currently the reference policy # plugin sets it to 5. 0x00010002 int 5 0
Set the On-The-Go suspend interval time.
# OTG capable suspend time. Currently the reference policy # plugin sets it to 5 seconds. 0x00010003 int 5 0
Set the media polling interval time.
# Media polling time. Currently the reference policy # plugin sets it to 1 second. 0x00010004 int 1 0
This value stores the current number of mounting history records. By default it is initialised to zero. The first mounting history record goes from Key 0x00010101 (see below).
# The mounting history record. 0x00010100 int 0 0
Define the numbering system of history records.
# The mounting history records. # This is the first record. # New records will be appended after this using a UID that increases by 1. # For instance, the second record will have the UID 0x00010102. 0x00010101 string8 "" 0