os/kernelhwsrv/userlibandfileserver/fileserver/smassstorage/cmassstoragefilesystem.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2004-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 the License "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 // CMassStorageFileSystem implementation.
    15 // 
    16 //
    17 
    18 /**
    19  @file
    20  @internalTechnology
    21 */
    22 
    23 #include <f32file.h>
    24 #include "cmassstoragefilesystem.h"
    25 #include "cmassstoragemountcb.h"
    26 #include "massstoragedebug.h"
    27 #include "massstorage.h"
    28 
    29 _LIT(KMsFsyName, "MassStorageFileSystem");
    30 _LIT(KMsThreadName, "MassStorageThread");
    31 _LIT(KMsDeadThreadName, "MassStorageDeadThread");
    32 _LIT(KMsFsysSemName, "MassStorageSemaphore");
    33 LOCAL_D const TInt KMsFsyMajorVersionNumber=1;
    34 LOCAL_D const TInt KMsFsyMinorVersionNumber=0;
    35 
    36 CMassStorageFileSystem::CMassStorageFileSystem()
    37 	{
    38 	}
    39 
    40 CMassStorageFileSystem::~CMassStorageFileSystem()
    41 	{
    42 	//Kill the controller thread if it exists
    43 	delete iMassStorageController;
    44 	delete iMediaChanged;
    45 	RThread thread;
    46 	TInt err = thread.Open(KMsThreadName);
    47 	if (err == KErrNone)
    48 		{
    49 		thread.Kill(1); //Parameter is irrelevant
    50 		}
    51 	thread.Close();
    52 	iMsDrives.Close();
    53 	}
    54 
    55 CMassStorageFileSystem* CMassStorageFileSystem::NewL()
    56 	{
    57 	CMassStorageFileSystem*  self = new (ELeave) CMassStorageFileSystem();
    58 	CleanupStack::PushL(self);
    59 	self->ConstructL();
    60 	CleanupStack::Pop(self);
    61 	return self;
    62 	}
    63 	
    64 void CMassStorageFileSystem::ConstructL()
    65 	{
    66 	iMediaChanged = new(ELeave) CArrayFixFlat<TBool>(KMaxDrives);
    67 	}
    68 
    69 /**
    70 Set the file system version and name
    71 
    72 @return Any of the standard Symbian error codes.
    73 */
    74 TInt CMassStorageFileSystem::Install()
    75 	{
    76 	__PRINT(_L("CMassStorageFileSystem::Install In\n"));
    77 	iVersion=TVersion(KMsFsyMajorVersionNumber, KMsFsyMinorVersionNumber, KF32BuildVersionNumber);
    78 	TInt err = SetName(&KMsFsyName);
    79 	__PRINT(_L("CMassStorageFileSystem::Install Out\n"));
    80 	return err;
    81 	}
    82 
    83 TInt CMassStorageFileSystem::Remove()
    84 	{
    85 	__PRINT(_L("CMassStorageFileSystem::Remove In\n"));
    86 	TInt err = KErrNone;
    87 	if (iInstalled)
    88 		{
    89 		// Try connecting to the server to send a shutdown message.
    90 		// - If the class controller has a session in use, this will return KErrInUse
    91 		RUsbMassStorage usbMs;
    92 		err = usbMs.Connect();
    93 		if(err == KErrNone)
    94 			{
    95 			err = usbMs.Shutdown();
    96 			usbMs.Close();
    97 
    98 			if(err == KErrNone)
    99 				{
   100 				User::WaitForRequest(iThreadStat);
   101 				err = iThreadStat.Int();
   102 				}
   103 			else
   104 				{
   105 				__PRINT1(_L("CMassStorageFileSystem::Remove Shutdown Error %d\n"),err);
   106 				}
   107 			}
   108 		else
   109 			{
   110 			__PRINT1(_L("CMassStorageFileSystem::Remove Connect Error %d\n"),err);
   111 			}
   112 		}
   113 	__PRINT(_L("CMassStorageFileSystem::Remove Out\n"));
   114 	return(err);
   115 	}
   116 
   117 /**
   118 Creates a new Mass Storage mount object.
   119 
   120 @return A new CMassStorageMountCB
   121 @leave KErrNotReady if the Mass Storage controller is not running.
   122 */
   123 CMountCB* CMassStorageFileSystem::NewMountL() const
   124 	{
   125 	if (!iRunning)
   126 		{
   127 		User::Leave(KErrNotReady);
   128 		}
   129 	return CMassStorageMountCB::NewL(iMsDrives);
   130 	}
   131 
   132 /**
   133 Sets the media attributes and type in the aInfo parameter to those of the specified drive.
   134 
   135 @param anInfo TDriveInfo object to store the drive information.
   136 @param aDriveNumber The number of the drive to get the information from.
   137 */
   138 void CMassStorageFileSystem::DriveInfo(TDriveInfo& aInfo, TInt aDriveNumber) const
   139 	{
   140 	__PRINT(_L("CMassStorageFileSystem::DriveInfo In\n"));
   141 	TLocalDriveCapsV2Buf caps;
   142 	if (!IsValidLocalDriveMapping(aDriveNumber))
   143 		{
   144 		return;
   145 		}
   146 	(void)GetLocalDrive(aDriveNumber).Caps(caps);   
   147     // error ignored as Caps always returns  valid Media and Drive attributes
   148 	aInfo.iMediaAtt=caps().iMediaAtt;
   149     aInfo.iType = ::EMediaNotPresent;  // Media is not available to the file system
   150 	aInfo.iDriveAtt=caps().iDriveAtt;
   151 	__PRINT(_L("CMassStorageFileSystem::DriveInfo Out\n"));
   152 	}
   153 
   154 /**
   155 Returns a reference to the Mass Storage controller.
   156 
   157 @return Reference to the Mass Storage controller.
   158 */
   159 CUsbMassStorageController& CMassStorageFileSystem::Controller()
   160 	{
   161 	return *iMassStorageController;
   162 	}
   163 
   164 /**
   165 Fill iMsDrives with a mapping of lun->drive number for supported mass storage drives
   166 
   167 */
   168 TInt CMassStorageFileSystem::EnumerateMsDrivesL()
   169 	{
   170 	__PRINT(_L("CMassStorageFileSystem::EnumerateMsDrives In\n"));
   171 	iMsDrives.Reset();
   172 	TInt driveCount = 0;
   173 
   174 	TLocalDriveCapsV2Buf caps;
   175 	for (TInt i = EDriveC; i < KMaxDrives; i++)
   176 		{
   177 		caps.FillZ();
   178 		
   179 		if (IsValidLocalDriveMapping(i))
   180 			{
   181 			TInt err = GetLocalDrive(i).Caps(caps);
   182 			TInt locDrvNum = DriveNumberToLocalDriveNumber(i);
   183 			__PRINT2(_L("Caps: err=%d, att=%d\n"), err, caps().iDriveAtt);
   184 			
   185 			TBool isRemovable = err==KErrNotReady || (caps().iDriveAtt & KDriveAttRemovable);
   186 			__PRINT2(_L("EnumerateMsDrives: Drive %c: is %sremovable\n"),
   187 							'A'+i-EDriveA, 
   188 							isRemovable?_S(""):_S("NOT "));
   189 							
   190 			if (isRemovable)
   191 				{
   192 				//
   193 				// STF: Connect to the local drive here.  This gives us the media changed flag, and
   194 				//		our own TBusLocalDrive object for use by the proxy drive and controller.
   195 				//
   196 				TBool& mediaChanged = (*iMediaChanged).ExtendL();
   197 				mediaChanged = EFalse;
   198 				TBusLocalDrive* localDrive = new(ELeave) TBusLocalDrive;
   199 				iLocalDriveForMediaFlag.Append(*localDrive);
   200 				
   201 				TInt err=iLocalDriveForMediaFlag[driveCount].Connect(locDrvNum, mediaChanged);
   202 				if(err == KErrNone)
   203 					{
   204 					iMsDrives.Append(i);
   205 					}
   206 				driveCount++;
   207 				}
   208 			}
   209 		}
   210 
   211 	__PRINT1(_L("CMassStorageFileSystem::EnumerateMsDrives Out, %d MS drives found\n"), driveCount);
   212 	return driveCount;
   213 	}
   214 
   215 TBool CMassStorageFileSystem::IsExtensionSupported() const
   216 	{
   217 	return ETrue;
   218 	}
   219 
   220 /**
   221 Creates a TrapCleanup and ActiveScheduler and initializes the Mass Storage controller.
   222 Start the ActiveScheduler.
   223 
   224 @return Any of the standard Symbian error codes.
   225 */
   226 TInt CMassStorageFileSystem::InitThread()
   227 	{
   228 	__PRINT(_L("CMassStorageFileSystem::InitThread In\n"));
   229 	
   230 	//Give the thread a name so we can kill it later
   231 	User::RenameThread(KMsThreadName);
   232 		
   233 	CTrapCleanup* cleanup = CTrapCleanup::New();
   234 	if (cleanup == NULL)
   235 		{
   236 		return KErrNoMemory;
   237 		}
   238 
   239 	TRAPD(err, InitThreadL());
   240 	
   241 	delete cleanup;
   242 	
   243 	__PRINT1(_L("CMassStorageFileSystem::InitThread Out, error=%d\n"), err);
   244 	return err;
   245 	}
   246 
   247 TInt CMassStorageFileSystem::InitThreadL()
   248 	{
   249 	__PRINT(_L("CMassStorageFileSystem::InitThreadL In\n"));
   250 	
   251 	RSemaphore gSemThreadReady;
   252 
   253 	TInt ret = gSemThreadReady.OpenGlobal(KMsFsysSemName);
   254 
   255 	if (ret != KErrNone && ret != KErrAlreadyExists)
   256 		{
   257 		User::Leave(ret);
   258 		}
   259 
   260 	// Determine which drives are available for Mass Storage.
   261 	// (this also creates a local TBusLocalDrive for use by the drive controller)
   262 	EnumerateMsDrivesL();
   263 
   264 	CActiveScheduler* sched = new CActiveScheduler;
   265 	if (sched == NULL)
   266 		{
   267 		gSemThreadReady.Signal();
   268 		User::Leave(KErrNoMemory);
   269 		}
   270 	CleanupStack::PushL(sched);
   271 	CActiveScheduler::Install(sched);
   272 
   273 	iMassStorageController = new CUsbMassStorageController;
   274 	if (iMassStorageController == NULL)
   275 		{
   276 		gSemThreadReady.Signal();
   277 		User::Leave(KErrNoMemory);
   278 		}
   279 	
   280 	__PRINT(_L("CMassStorageFileSystem::InitThread: Creating Mass Storage Controller\n"));
   281 	TRAPD(err, iMassStorageController->CreateL(iMsDrives));
   282 	if (err != KErrNone)
   283 		{
   284 		gSemThreadReady.Signal();
   285 		CActiveScheduler::Install(NULL);
   286 		User::Leave(err);
   287 		}
   288 	
   289 	CleanupStack::Pop(sched);
   290 
   291 	iRunning = ETrue;
   292 	gSemThreadReady.Signal();
   293 	gSemThreadReady.Close();
   294 	CActiveScheduler::Start();
   295 
   296 //========= stop thread ================
   297 	delete iMassStorageController;
   298 	iMassStorageController = NULL;
   299 	TInt i=0;
   300 	for (;i<iLocalDriveForMediaFlag.Count();i++)
   301 		{
   302 		iLocalDriveForMediaFlag[i].Disconnect();
   303 		}
   304 	iLocalDriveForMediaFlag.Reset();
   305 	(*iMediaChanged).Reset();	
   306 	delete sched;
   307 	iRunning = EFalse;
   308 	
   309 	__PRINT(_L("CMassStorageFileSystem::InitThread Out\n"));
   310 	return KErrNone;
   311 	}
   312 	
   313 /**
   314 Not supported in Mass Storage file system.
   315 
   316 @leave KErrNotReady
   317 */
   318 CFileCB* CMassStorageFileSystem::NewFileL() const
   319 	{
   320 	__PRINT(_L("CMassStorageFileSystem::NewFileL In\n"));
   321 	User::Leave(KErrNotReady);
   322 	return NULL;
   323 	}
   324 
   325 /**
   326 Not supported in Mass Storage file system.
   327 
   328 @leave KErrNotReady
   329 */
   330 CDirCB* CMassStorageFileSystem::NewDirL() const
   331 	{
   332 	User::Leave(KErrNotReady);
   333 	return NULL;
   334 	}
   335 
   336 /**
   337 Not supported in Mass Storage file system.
   338 
   339 @leave KErrNotReady
   340 */
   341 CFormatCB* CMassStorageFileSystem::NewFormatL() const
   342 	{
   343 	User::Leave(KErrNotReady);
   344 	return NULL;
   345 	}
   346 
   347 /**
   348 Not supported in Mass Storage file system.
   349 
   350 @return KErrNotSupported
   351 */
   352 TInt CMassStorageFileSystem::DefaultPath(TDes& /*aPath*/) const
   353 	{
   354 	return KErrNotSupported;
   355 	}
   356 
   357 /**
   358 Not supported in Mass Storage file system.
   359 
   360 @return KErrNotSupported
   361 */
   362 TInt CMassStorageFileSystem::DriveList(TDriveList& /*aList*/) const
   363 	{
   364 	return KErrNotSupported;
   365 	}
   366 
   367 /**
   368 Thread entry point.
   369 */
   370 LOCAL_C TInt MsInitThreadFn(TAny* aPtr)
   371 	{
   372 	User::SetCritical(User::ESystemCritical);
   373 	((CMassStorageFileSystem*)aPtr)->InitThread();
   374 	//Rename the thread so we can create a new one with the same original name later
   375 	User::RenameThread(KMsDeadThreadName);
   376 	return KErrNone;
   377 	}
   378 
   379 /**
   380 Standard entry point for file systems.
   381 Creates a new file system object and starts a new thread for the Mass Storage controller.
   382 */
   383 extern "C" EXPORT_C CFileSystem* CreateFileSystem()
   384 	{
   385 	__PRINT(_L("CMassStorageFileSystem::CreateFileSystem In\n"));
   386 	RSemaphore gSemThreadReady;
   387 	TInt err = gSemThreadReady.CreateGlobal(KMsFsysSemName, 0);
   388 	if (err != KErrNone)
   389 		{
   390 		__PRINT1(_L("CMassStorageFileSystem::CreateFileSystem Out Semaphore Error %d\n"),err);
   391 		return NULL;
   392 		}
   393 
   394 	CFileSystem* msFsys = NULL;
   395 	TRAP(err,  msFsys = CMassStorageFileSystem::NewL());
   396 	if (err != KErrNone)
   397 		{
   398 		__PRINT1(_L("CMassStorageFileSystem::CreateFileSystem Out MSFS Error %d\n"),err);
   399 		gSemThreadReady.Close();
   400 		return NULL;
   401 		}
   402 
   403 	RThread msThread;
   404 	__PRINT(_L("CMassStorageFileSystem::CreateFileSystem: Creating Mass Storage thread\n"));
   405 	err = msThread.Create(KMsThreadName, MsInitThreadFn, KDefaultStackSize, NULL, msFsys);
   406 	if (err != KErrNone)
   407 		{
   408 		__PRINT1(_L("CMassStorageFileSystem::CreateFileSystem Out Thread Error %d\n"),err);
   409 		gSemThreadReady.Close();
   410 		return msFsys;
   411 		}
   412 	((CMassStorageFileSystem*)msFsys)->iInstalled=ETrue;
   413 
   414 
   415 	msThread.Logon(((CMassStorageFileSystem*)msFsys)->iThreadStat);
   416 	msThread.Resume();
   417 	gSemThreadReady.Wait();
   418 	gSemThreadReady.Close();
   419 	msThread.Close();
   420 	
   421 	__PRINT(_L("CMassStorageFileSystem::CreateFileSystem Out Clean\n"));
   422 	
   423 	return msFsys;
   424 	}
   425