mtpfws/mtpfw/dataproviders/devdp/src/cmtpstoragewatcher.cpp
changeset 0 d0791faffa3f
child 1 f8e15b44d440
equal deleted inserted replaced
-1:000000000000 0:d0791faffa3f
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <mtp/cmtpdataproviderplugin.h>
       
    17 #include <mtp/mmtpdataproviderframework.h>
       
    18 #include <mtp/mtpprotocolconstants.h>
       
    19 #include <mtp/mtpdataproviderapitypes.h>
       
    20 
       
    21 #include "cmtpdataprovider.h"
       
    22 #include "cmtpdataprovidercontroller.h"
       
    23 #include "cmtpframeworkconfig.h"
       
    24 #include "cmtpstoragemgr.h"
       
    25 #include "cmtpobjectmgr.h"
       
    26 #include "cmtpstoragewatcher.h"
       
    27 #include "rmtpdevicedpsingletons.h"
       
    28 #include "cmtpdevicedpconfigmgr.h"
       
    29 
       
    30 
       
    31 // Class constants.
       
    32 __FLOG_STMT(_LIT8(KComponent,"StorageWatcher");)
       
    33 static const TBool KAllDrives(ETrue);
       
    34 static const TBool KAvailableDrives(EFalse);
       
    35 
       
    36 const TInt KFolderExclusionGranularity = 8;
       
    37 
       
    38 /**
       
    39 MTP system storage watcher factory method.
       
    40 @return A pointer to an MTP system storage watcher object. Ownership IS 
       
    41 transfered.
       
    42 @leave One of the system wide error codes, if a processing failure occurs.
       
    43 */
       
    44 CMTPStorageWatcher* CMTPStorageWatcher::NewL(MMTPDataProviderFramework& aFramework)
       
    45     {
       
    46     CMTPStorageWatcher* self = new (ELeave) CMTPStorageWatcher(aFramework);
       
    47     CleanupStack::PushL(self);
       
    48     self->ConstructL();
       
    49     CleanupStack::Pop(self);
       
    50     return self;
       
    51     }
       
    52 
       
    53 /**
       
    54 Destructor.
       
    55 */    
       
    56 CMTPStorageWatcher::~CMTPStorageWatcher()
       
    57     {
       
    58     __FLOG(_L8("~CMTPStorageWatcher - Entry"));
       
    59     Cancel();
       
    60     delete iFolderExclusionList;
       
    61     iDpSingletons.Close();
       
    62     iDrivesExcluded.Close();
       
    63     iFrameworkSingletons.Close();
       
    64     __FLOG(_L8("~CMTPStorageWatcher - Exit"));
       
    65     __FLOG_CLOSE;
       
    66     }
       
    67     
       
    68 void CMTPStorageWatcher::EnumerateStoragesL()
       
    69     {
       
    70     __FLOG(_L8("EnumerateStoragesL - Entry"));
       
    71 
       
    72     //Use Hash to replace it
       
    73     AppendFolderExclusionListL();
       
    74     
       
    75     // Retrieve the drive exclusion list.
       
    76     iFrameworkSingletons.FrameworkConfig().GetValueL(CMTPFrameworkConfig::EExcludedStorageDrives, iDrivesExcluded);
       
    77     iDrivesExcluded.Sort();
       
    78     
       
    79     // Claim system storages ownership.
       
    80     CMTPStorageMgr& mgr(iFrameworkSingletons.StorageMgr());
       
    81     mgr.SetFrameworkId(iFramework.DataProviderId());
       
    82     
       
    83     /* 
       
    84     Enumerate the initial drive set. 
       
    85     
       
    86         1.   Enumerate each known drive as a physical storage.
       
    87     */
       
    88     iDrivesConfig = DriveConfigurationL(KAllDrives);
       
    89     CMTPStorageMetaData* storage = CMTPStorageMetaData::NewLC();
       
    90     storage->SetUint(CMTPStorageMetaData::EStorageSystemType, CMTPStorageMetaData::ESystemTypeDefaultFileSystem);
       
    91     _LIT(KSuidTemplate, "?:");
       
    92     RBuf suid;
       
    93     suid.CleanupClosePushL();
       
    94     suid.Assign((KSuidTemplate().AllocL()));
       
    95     
       
    96     for (TInt drive(0); (drive < KMaxDrives); drive++)
       
    97         {
       
    98         const TUint32 mask(1 << drive);
       
    99         if (iDrivesConfig & mask)
       
   100             {
       
   101             TChar driveChar;
       
   102             User::LeaveIfError(iFramework.Fs().DriveToChar(drive, driveChar));
       
   103             suid[0] = driveChar;
       
   104             storage->SetDesCL(CMTPStorageMetaData::EStorageSuid, suid);
       
   105                     
       
   106             TUint32 id(mgr.AllocatePhysicalStorageIdL(iFramework.DataProviderId(), *storage));
       
   107             mgr.SetDriveMappingL(static_cast<TDriveNumber>(drive), id);
       
   108             }
       
   109         }
       
   110         
       
   111     CleanupStack::PopAndDestroy(&suid);
       
   112     CleanupStack::PopAndDestroy(storage);
       
   113     
       
   114     /* 
       
   115         2.  If so configured, enumerate a single logical storage for each of 
       
   116             the available drives.
       
   117     */
       
   118     if (iAllocateLogicalStorages)
       
   119         {
       
   120         iDrivesConfig = DriveConfigurationL(KAvailableDrives);
       
   121 
       
   122         for (TInt drive(0); (drive < KMaxDrives); drive++)
       
   123             {
       
   124             const TUint32 mask(1 << drive);
       
   125             if (iDrivesConfig & mask)
       
   126                 {
       
   127                 StorageAvailableL(static_cast<TDriveNumber>(drive));
       
   128                 }
       
   129             }
       
   130         }
       
   131     
       
   132     // Set the default storage.
       
   133     TUint defaultDrive;
       
   134     iFrameworkSingletons.FrameworkConfig().GetValueL(CMTPFrameworkConfig::EDefaultStorageDrive, defaultDrive);
       
   135     
       
   136     if ( defaultDrive <= EDriveZ )
       
   137         {
       
   138         // Default drive is specified by drive number.. retrieve from manager..
       
   139         if (iAllocateLogicalStorages)
       
   140             {
       
   141             mgr.SetDefaultStorageId(mgr.FrameworkStorageId(static_cast<TDriveNumber>(defaultDrive)));
       
   142             }
       
   143         else
       
   144             {
       
   145             mgr.SetDefaultStorageId(mgr.PhysicalStorageId(static_cast<TDriveNumber>(defaultDrive)));
       
   146             }
       
   147         }
       
   148     else
       
   149        {
       
   150        // Default drive is specified by storage number
       
   151        mgr.SetDefaultStorageId(defaultDrive);
       
   152        }
       
   153        
       
   154     __FLOG(_L8("EnumerateStoragesL - Exit"));
       
   155     }
       
   156 
       
   157 /**
       
   158 Initiates storage change notice subscription.
       
   159 */
       
   160 void CMTPStorageWatcher::Start()
       
   161     {
       
   162     __FLOG(_L8("Start - Entry"));
       
   163     if (!(iState & EStarted))
       
   164         {
       
   165         __FLOG(_L8("Starting RFs notifier"));
       
   166         TRequestStatus* status(&iStatus);
       
   167         User::RequestComplete(status, KErrNone);
       
   168         SetActive();
       
   169         iState |= EStarted;
       
   170         }
       
   171     __FLOG(_L8("Start - Exit"));    
       
   172     }
       
   173     
       
   174 void CMTPStorageWatcher::DoCancel()
       
   175     {
       
   176     __FLOG(_L8("DoCancel - Entry"));
       
   177     __FLOG(_L8("Stopping RFs notifier"));
       
   178     iFrameworkSingletons.Fs().NotifyChangeCancel();
       
   179     iState &= (!EStarted);
       
   180     __FLOG(_L8("DoCancel - Exit"));
       
   181     }
       
   182 
       
   183 /**
       
   184 Append all DPs folder exclusion list strings in Device DP
       
   185  */
       
   186 void CMTPStorageWatcher::AppendFolderExclusionListL()
       
   187     {
       
   188     CDesCArraySeg* folderExclusionSets = new (ELeave) CDesCArraySeg(KFolderExclusionGranularity);
       
   189     CleanupStack::PushL(folderExclusionSets);
       
   190     CMTPDataProviderController& dps(iFrameworkSingletons.DpController());
       
   191     TUint currentDpIndex = 0, count = dps.Count();
       
   192     while (currentDpIndex < count)
       
   193         {
       
   194         CMTPDataProvider& dp(dps.DataProviderByIndexL(currentDpIndex));
       
   195         if(KMTPImplementationUidDeviceDp != dp.ImplementationUid().iUid)
       
   196             {
       
   197             folderExclusionSets->Reset();
       
   198             dp.Plugin().SupportedL(EFolderExclusionSets,*folderExclusionSets);
       
   199             for(TInt i = 0; i < folderExclusionSets->Count(); ++i)
       
   200                 {
       
   201                 TPtrC16 excludedFolder = (*folderExclusionSets)[i];
       
   202                 iFolderExclusionList->AppendL(excludedFolder);
       
   203                 }
       
   204             }
       
   205         currentDpIndex++;
       
   206         }
       
   207     CleanupStack::PopAndDestroy(folderExclusionSets);
       
   208     }
       
   209 
       
   210 /**
       
   211 Handles leaves occurring in RunL.
       
   212 @param aError leave error code
       
   213 @return KErrNone
       
   214 */
       
   215 #ifdef __FLOG_ACTIVE
       
   216 TInt CMTPStorageWatcher::RunError(TInt aError)
       
   217 #else
       
   218 TInt CMTPStorageWatcher::RunError(TInt /*aError*/)
       
   219 #endif
       
   220     {
       
   221     __FLOG(_L8("RunError - Entry"));
       
   222     __FLOG_VA((_L8("Error = %d"), aError));
       
   223 
       
   224     // Ignore the error, meaning that the storages may not be accurately accounted for
       
   225     RequestNotification();
       
   226 
       
   227     __FLOG(_L8("RunError - Exit"));
       
   228     return KErrNone;
       
   229     }
       
   230     
       
   231 void CMTPStorageWatcher::RunL()
       
   232     {
       
   233     __FLOG(_L8("RunL - Entry"));
       
   234     const TUint32 previous(iDrivesConfig);
       
   235     const TUint32 current(DriveConfigurationL(KAvailableDrives));
       
   236     if (current != previous)
       
   237         {        
       
   238         const TUint32 changed(current ^ previous);
       
   239         const TUint32 added(changed & current);
       
   240         const TUint32 removed(changed & previous);
       
   241         TInt i(KMaxDrives);
       
   242         while (i--)
       
   243             {
       
   244             const TUint32 mask(1 << i);
       
   245             if (added & mask)
       
   246                 {
       
   247                 StorageAvailableL(static_cast<TDriveNumber>(i));
       
   248                 }
       
   249             else if (removed & mask)
       
   250                 {
       
   251                 StorageUnavailableL(static_cast<TDriveNumber>(i));
       
   252                 }
       
   253             }
       
   254         }
       
   255     iDrivesConfig = current;
       
   256     RequestNotification();
       
   257     __FLOG(_L8("RunL - Exit"));
       
   258     }
       
   259     
       
   260 /**
       
   261 Constructor.
       
   262 @param aConnectionMgr The MTP connection manager interface.
       
   263 */
       
   264 CMTPStorageWatcher::CMTPStorageWatcher(MMTPDataProviderFramework& aFramework) :
       
   265     CActive(EPriorityStandard),
       
   266     iFramework(aFramework)
       
   267     {
       
   268     CActiveScheduler::Add(this);
       
   269     }
       
   270     
       
   271 /**
       
   272 Second phase constructor.
       
   273 */
       
   274 void CMTPStorageWatcher::ConstructL()
       
   275     {
       
   276     __FLOG_OPEN(KMTPSubsystem, KComponent);
       
   277     __FLOG(_L8("ConstructL - Entry"));
       
   278     iFrameworkSingletons.OpenL();
       
   279     iFrameworkSingletons.FrameworkConfig().GetValueL(CMTPFrameworkConfig::ELogicalStorageIdsAllocationEnable, iAllocateLogicalStorages);
       
   280     
       
   281     RMTPDeviceDpSingletons devSingletons;
       
   282     devSingletons.OpenL(iFramework);
       
   283     CleanupClosePushL(devSingletons);
       
   284     
       
   285     iDpSingletons.OpenL(iFramework);
       
   286     iFolderExclusionList = devSingletons.ConfigMgr().GetArrayValueL(CMTPDeviceDpConfigMgr::EFolderExclusionList); 
       
   287     CleanupStack::PopAndDestroy(&devSingletons);
       
   288     __FLOG(_L8("ConstructL - Exit"));
       
   289     }
       
   290     
       
   291 TUint32 CMTPStorageWatcher::DriveConfigurationL(TBool aAllDrives) const
       
   292     {
       
   293     __FLOG(_L8("DriveConfigurationL - Entry"));
       
   294     TUint32     config(0);
       
   295     TDriveList  drives;
       
   296     RFs&        fs(iFrameworkSingletons.Fs());
       
   297     User::LeaveIfError(fs.DriveList(drives));
       
   298     TInt i(KMaxDrives);
       
   299     while (i--)
       
   300         {        
       
   301         __FLOG_VA((_L8("Drive number %d, available = 0x%02d"), i, drives [i]));
       
   302         if ((drives[i]) &&
       
   303             (!Excluded(static_cast<TDriveNumber>(i))))
       
   304             {
       
   305             TDriveInfo info;
       
   306             User::LeaveIfError(fs.Drive(info, i));
       
   307             if ((info.iType != EMediaNotPresent) || (aAllDrives))
       
   308                 {
       
   309                 TVolumeInfo volumeInfo;
       
   310                 if(KErrNone == fs.Volume(volumeInfo,i))
       
   311                 	{
       
   312                 	config |=  (1 << i);
       
   313                 	}
       
   314                 }
       
   315             }
       
   316         }
       
   317     __FLOG_VA((_L8("Drives list = 0x%08X, AllDrives = %d"), config, aAllDrives));
       
   318     __FLOG(_L8("DriveConfigurationL - Exit"));
       
   319     return config;
       
   320     }
       
   321 
       
   322 TBool CMTPStorageWatcher::Excluded(TDriveNumber aDriveNumber) const
       
   323     {
       
   324     __FLOG(_L8("Excluded - Entry"));
       
   325     TBool ret(iDrivesExcluded.FindInOrder(aDriveNumber) != KErrNotFound);
       
   326     __FLOG_VA((_L8("Drive = %d, excluded = %d"), aDriveNumber, ret));
       
   327     __FLOG(_L8("Excluded - Exit"));
       
   328     return ret;
       
   329     }
       
   330     
       
   331 void CMTPStorageWatcher::RequestNotification()
       
   332     {
       
   333     __FLOG(_L8("RequestNotification - Entry"));
       
   334     _LIT(KPath, "?:\\..");
       
   335     iFrameworkSingletons.Fs().NotifyChange(ENotifyEntry, iStatus, KPath);
       
   336     SetActive();
       
   337     __FLOG(_L8("RequestNotification - Exit"));
       
   338     }
       
   339  
       
   340 void CMTPStorageWatcher::SendEventL(TUint16 aEvent, TUint32 aStorageId)
       
   341     {
       
   342     __FLOG(_L8("SendEventL - Entry"));
       
   343     if (iState & EStarted)
       
   344         {
       
   345         __FLOG_VA((_L8("Sending event 0x%04X for StorageID 0x%08X"), aEvent, aStorageId));
       
   346         iEvent.Reset();
       
   347         iEvent.SetUint16(TMTPTypeEvent::EEventCode, aEvent);
       
   348         iEvent.SetUint32(TMTPTypeEvent::EEventSessionID, KMTPSessionAll);
       
   349         iEvent.SetUint32(TMTPTypeEvent::EEventTransactionID, KMTPTransactionIdNone);
       
   350         iEvent.SetUint32(TMTPTypeEvent::EEventParameter1, aStorageId);
       
   351         iFramework.SendEventL(iEvent);
       
   352         }
       
   353     __FLOG(_L8("SendEventL - Exit"));
       
   354     }
       
   355 
       
   356 /**
       
   357 Configures the specified drive as an available MTP storage.
       
   358 @param aDriveNumber The Symbian OS file system drive number.
       
   359 @leave One of the system wide error codes, if a processing failure occurs.
       
   360 */    
       
   361 void CMTPStorageWatcher::StorageAvailableL(TDriveNumber aDriveNumber)
       
   362     {
       
   363     __FLOG(_L8("StorageAvailableL - Entry"));
       
   364     __FLOG_VA((_L8("Drive = %d is available."), aDriveNumber));
       
   365     CMTPStorageMgr& mgr(iFrameworkSingletons.StorageMgr());
       
   366     TInt32 physical(mgr.PhysicalStorageId(aDriveNumber));
       
   367     _LIT(KSuidTemplate, "?:");
       
   368     // Generate the storage SUID as the drive root folder.
       
   369     RBuf suid;
       
   370     suid.CleanupClosePushL();
       
   371     suid.Assign((KSuidTemplate().AllocL()));
       
   372     TChar driveChar;
       
   373     User::LeaveIfError(iFramework.Fs().DriveToChar(aDriveNumber, driveChar));
       
   374     driveChar.LowerCase();
       
   375     suid[0] = driveChar;
       
   376     // Create the storage meta-data.
       
   377     CMTPStorageMetaData* storage = CMTPStorageMetaData::NewLC();
       
   378     storage->SetUint(CMTPStorageMetaData::EStorageSystemType, CMTPStorageMetaData::ESystemTypeDefaultFileSystem);
       
   379     storage->SetDesCL(CMTPStorageMetaData::EStorageSuid, suid);
       
   380     if(physical == KErrNotFound)
       
   381     	{
       
   382         TUint32 id(mgr.AllocatePhysicalStorageIdL(iFramework.DataProviderId(), *storage));
       
   383         mgr.SetDriveMappingL(aDriveNumber, id);
       
   384     	}
       
   385     physical = mgr.PhysicalStorageId(aDriveNumber);
       
   386 
       
   387     User::LeaveIfError(physical);
       
   388     TUint32 logical(physical);
       
   389 
       
   390     // If configured to do so, assign a logical storage ID mapping.
       
   391     if (iAllocateLogicalStorages)
       
   392         {
       
   393         __FLOG(_L8("Assigning local storage ID mapping"));
       
   394         
       
   395         // Try to read from resource file to use a specified root dir path, if available.
       
   396         RBuf rootDirPath;
       
   397         rootDirPath.CreateL(KMaxFileName);
       
   398         rootDirPath.CleanupClosePushL();
       
   399         RMTPDeviceDpSingletons devSingletons;
       
   400         devSingletons.OpenL(iFramework);
       
   401         CleanupClosePushL(devSingletons);
       
   402         TRAPD(resError, devSingletons.ConfigMgr().GetRootDirPathL(aDriveNumber, rootDirPath));
       
   403         __FLOG_VA((_L8("ResError = %d"), resError));
       
   404         if ((KErrNone == resError) && (0 < rootDirPath.Length()))
       
   405             {
       
   406             __FLOG(_L8("Reading resource file succeeded"));
       
   407             // If there is a root directory information in rss file then check the directory exist or not. 
       
   408             // If not exists, then create it. 
       
   409             // Before doing anything, delete the leading and trailing white space.
       
   410             rootDirPath.Trim();       
       
   411             TBuf<KMaxFileName> buffer;
       
   412             buffer.Append(driveChar);
       
   413             _LIT(KSeperator,":");
       
   414             buffer.Append(KSeperator);
       
   415             buffer.Append(rootDirPath);
       
   416             TInt error = iFramework.Fs().MkDir(buffer);
       
   417             suid.Close();
       
   418             _LIT(KSuidTemplate, "?:\\");
       
   419             suid.Assign((KSuidTemplate().AllocL()));
       
   420             driveChar.LowerCase();
       
   421             suid[0] = driveChar;
       
   422 
       
   423             if ((KErrNone == error) || (KErrAlreadyExists == error))
       
   424                 {
       
   425                 __FLOG(_L8("Overwriting SUID to specified root dir path from resource file"));  
       
   426                 //if dir already existed or created, make that as root directory
       
   427                 suid.ReAllocL(buffer.Length());
       
   428                 suid = buffer;
       
   429                 }
       
   430             }
       
   431         CleanupStack::PopAndDestroy(&devSingletons);
       
   432         CleanupStack::PopAndDestroy(&rootDirPath);
       
   433         
       
   434         // Set up folder exclusion list
       
   435         CDesCArraySeg* storageExclusions = new (ELeave) CDesCArraySeg(KFolderExclusionGranularity);
       
   436         CleanupStack::PushL(storageExclusions);
       
   437         TInt excludedFolderCount = iFolderExclusionList->Count();
       
   438 
       
   439         for (TInt i = 0; i < excludedFolderCount; ++i)
       
   440             {
       
   441             TPtrC16 excludedFolder = (*iFolderExclusionList)[i];
       
   442 
       
   443             if (excludedFolder[0] == '?' ||
       
   444                 excludedFolder[0] == '*' ||
       
   445                 excludedFolder[0] == suid[0])
       
   446                 {
       
   447                 storageExclusions->AppendL(excludedFolder);
       
   448                 }
       
   449             }
       
   450         for ( TInt i=0; i<storageExclusions->Count();++i)
       
   451             {
       
   452             HBufC16* temp = static_cast<TPtrC16>((*storageExclusions)[i]).AllocL();
       
   453             TPtr16 tempptr(temp->Des());
       
   454             tempptr[0] = suid[0];
       
   455             storage->SetHashPath(tempptr,i);
       
   456             delete temp;
       
   457             }
       
   458         
       
   459         storage->SetDesCL(CMTPStorageMetaData::EStorageSuid, suid);
       
   460         storage->SetDesCArrayL(CMTPStorageMetaData::EExcludedAreas, *storageExclusions);
       
   461         CleanupStack::PopAndDestroy(storageExclusions);
       
   462 
       
   463         // Create the logical StorageID and drive mapping.
       
   464         logical = mgr.AllocateLogicalStorageIdL(iFramework.DataProviderId(), physical, *storage);
       
   465         mgr.SetDriveMappingL(aDriveNumber, logical);
       
   466 
       
   467         __FLOG_VA((_L8("Drive = %d mapped as storage 0x%08X"), aDriveNumber, logical));
       
   468         }
       
   469 
       
   470     CleanupStack::PopAndDestroy(storage);
       
   471     CleanupStack::PopAndDestroy(&suid);
       
   472     
       
   473     // Notify the active data providers.
       
   474     if (iState & EStarted)
       
   475         {
       
   476         TMTPNotificationParamsStorageChange params = {physical};
       
   477         iFrameworkSingletons.DpController().NotifyDataProvidersL(EMTPStorageAdded, static_cast<TAny*>(&params));
       
   478         }
       
   479 
       
   480     // Notify any connected Initiator(s).
       
   481     if (iAllocateLogicalStorages)
       
   482         {
       
   483         SendEventL(EMTPEventCodeStoreAdded, logical);
       
   484         }
       
   485         
       
   486     __FLOG(_L8("StorageAvailableL - Exit"));
       
   487     }
       
   488 
       
   489 /**
       
   490 Configures the specified drive as an unavailable MTP storage.
       
   491 @param aDriveNumber The Symbian OS file system drive number.
       
   492 @leave One of the system wide error codes, if a processing failure occurs.
       
   493 */    
       
   494 void CMTPStorageWatcher::StorageUnavailableL(TDriveNumber aDriveNumber)
       
   495 {
       
   496     __FLOG(_L8("StorageUnavailableL - Entry"));
       
   497     __FLOG_VA((_L8("Drive = %d is unavailable."), aDriveNumber));
       
   498     CMTPStorageMgr& mgr(iFrameworkSingletons.StorageMgr());
       
   499     TInt32 physical(mgr.PhysicalStorageId(aDriveNumber));
       
   500     User::LeaveIfError(physical);
       
   501     TUint32 logical(0);
       
   502     
       
   503     // If configured to do so, assign a logical storage ID mapping.
       
   504     if (iAllocateLogicalStorages)
       
   505         {
       
   506         logical = mgr.FrameworkStorageId(aDriveNumber);
       
   507 
       
   508         // Deassign the logical storage ID mapping.
       
   509         mgr.DeallocateLogicalStorageIds(iFramework.DataProviderId(), physical);
       
   510         mgr.SetDriveMappingL(aDriveNumber, physical);
       
   511         __FLOG_VA((_L8("Drive = %d unmapped as storage 0x%08X"), aDriveNumber, logical));
       
   512         }
       
   513 
       
   514     // Notify the active data providers.
       
   515     TMTPNotificationParamsStorageChange params = {physical};
       
   516     iFrameworkSingletons.DpController().NotifyDataProvidersL(EMTPStorageRemoved, static_cast<TAny*>(&params));
       
   517 
       
   518     // Notify any connected Initiator(s).
       
   519     if (iAllocateLogicalStorages)
       
   520         {
       
   521         SendEventL(EMTPEventCodeStoreRemoved, logical);
       
   522         }   
       
   523     __FLOG(_L8("StorageUnavailableL - Exit"));
       
   524     }