os/kernelhwsrv/userlibandfileserver/fileserver/shostmassstorage/client/rusbhostmsdevice.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2008-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 //
    15 
    16 /**
    17  @file
    18  @internalTechnology
    19 */
    20 
    21 #include <e32std.h>
    22 #include <f32file.h>
    23 
    24 #include "rusbhostmsdevice.h"
    25 #include "debug.h"
    26 #include "msgservice.h"
    27 
    28 _LIT(KFileSystem, "FAT");
    29 
    30 TVersion RUsbHostMsDevice::Version() const
    31     {
    32 	__FNLOG("RUsbHostMsDevice::Version");
    33     return(TVersion(KUsbHostMsSrvMajorVersionNumber,
    34                     KUsbHostMsSrvMinorVersionNumber,
    35                     KUsbHostMsSrvBuildVersionNumber));
    36     }
    37 
    38 
    39 TInt RUsbHostMsDevice::StartServer()
    40     {
    41 	__FNLOG("RUsbHostMsDevice::StartServer");
    42     TInt r;
    43     RProcess server;
    44 
    45     const TUid KServerUid3={0x10286A83};
    46     const TUidType serverUid(KNullUid,KNullUid,KServerUid3);
    47 
    48     // Create the server process
    49     if((r=server.Create(KUsbHostMsServerName,KNullDesC,serverUid)) != KErrNone)
    50         {
    51         __PRINT1(_L("Server process create = %d\n"), r);
    52         return r;
    53         }
    54 
    55     // Create the rendezvous request with the server process
    56     TRequestStatus stat;
    57     server.Rendezvous(stat);
    58     if (stat!=KRequestPending)
    59         {
    60         server.Kill(0);    // If the outstanding request is not pending then kill the server
    61         }
    62     else
    63         {
    64 		server.SetPriority(EPriorityHigh);
    65         server.Resume(); // start the server
    66         }
    67 
    68     // Test whether the process has ended and if it has ended, return how it ended.
    69     User::WaitForRequest(stat);
    70     r=(server.ExitType()==EExitPanic) ? KErrGeneral : stat.Int();
    71 
    72     server.Close();
    73     return r;
    74     }
    75 
    76 EXPORT_C RUsbHostMsDevice::RUsbHostMsDevice()
    77     {
    78         // Intentionally left blank
    79     }
    80 
    81 
    82 /**
    83 @internalAll
    84 @prototype
    85 
    86 Add the Mass Storage device to the MSC server. This API is asynchronous, upon
    87 completion one could find the number of logical units present in the added
    88 device by calling GetNumLun API. Calling the Remove API before completing this
    89 asynchronous API will complete the pending request notification with KErrCancel.
    90 
    91 @param aConfig [In] A constant reference object to
    92                 THostMassStorageConfig containing the confiquration values of
    93                 the massstorage device requested to add to the MSC
    94 @param aStatus [In] A reference to TRequestStatus to be used for asynchronous
    95                 request completion
    96 */
    97 EXPORT_C void RUsbHostMsDevice::Add(const THostMassStorageConfig& aConfig, TRequestStatus& aStatus)
    98     {
    99 	__FNLOG("RUsbHostMsDevice::Add");
   100     TInt err = KErrNone;
   101 
   102     err = CreateSession(KUsbHostMsServerName, Version(), 128, EIpcSession_GlobalSharable);
   103 
   104     // Being a transient server, the first session creation would fail with if
   105     // the server is not running
   106     if(err != KErrNone)
   107         {
   108         // Find whether the session creation failed because server was not
   109         // running
   110         if (err==KErrNotFound || err==KErrServerTerminated)
   111             {
   112             // Start the server
   113             err = StartServer();
   114             if(err == KErrNone)
   115                 {
   116                 // Try session creation again
   117                 err = CreateSession(KUsbHostMsServerName, Version(), 128, EIpcSession_GlobalSharable);
   118                 }
   119             }
   120         }
   121 
   122 	TRequestStatus* statusPtr = &aStatus;
   123     if(err == KErrNone)
   124         {
   125         // Create a session handle that can be passed via IPC to another process
   126         // (also being shared by other threads in the current process)
   127 		err = ShareProtected();
   128         if(err == KErrNone)
   129             {
   130             // synchronous call to register the interface
   131 			TPckg<THostMassStorageConfig> pckg(aConfig);
   132 	        err = SendReceive(EUsbHostMsRegisterInterface, TIpcArgs(&pckg));
   133 			if(err != KErrNone)
   134 				{
   135 		        User::RequestComplete(statusPtr, err);
   136 				}
   137 			else
   138 				{
   139 	            // Asynchronous call to initialise the interface
   140 				SendReceive(EUsbHostMsInitialiseInterface, TIpcArgs(NULL), aStatus);
   141 				}
   142 			}
   143         else
   144             {
   145             Close(); // Close the session handle
   146             __PRINT1(_L("Could not create a sharable session handle %d\n"), err);
   147             User::RequestComplete(statusPtr, err);
   148             }
   149         }
   150     else
   151         {
   152 		// Check whether the error is in starting the server or in creating the
   153         // session
   154         __PRINT1(_L("Creating server/session failed with %d\n"), err);
   155         User::RequestComplete(statusPtr, err);
   156         }
   157     }
   158 
   159 
   160 /**
   161 @internalAll
   162 @prototype
   163 
   164 Remove the Mass Storage device from the MSC server.
   165 */
   166 EXPORT_C void RUsbHostMsDevice::Remove()
   167     {
   168 	// Note: Here, at present we use only the interface token. But we still take
   169     // THostMassStorageConfig as parameter for future needs
   170 	__FNLOG("RUsbHostMsDevice::Remove");
   171 	_LIT(KUsbHostMsClientPanicCat, "usbhostmsclient");
   172 
   173 	TInt r = SendReceive(EUsbHostMsUnRegisterInterface);
   174 
   175 	r = SendReceive(EUsbHostMsFinalCleanup);
   176 	if(r != KErrNone)
   177 		{
   178 		User::Panic(KUsbHostMsClientPanicCat ,KErrCouldNotDisconnect);
   179 		}
   180     Close(); // Close the session handle
   181     }
   182 
   183 
   184 /**
   185 @internalAll
   186 @prototype
   187 
   188 Get the number of logical units suppoted by the device.
   189 
   190 @param aNumLuns [Out] Outputs the number of logical units found in the
   191                  added Mass Storage device. A value of 'n' represents there are
   192                  'n' LUNs present in the device, where "n > 0"
   193 
   194 @return TInt
   195 */
   196 EXPORT_C TInt RUsbHostMsDevice::GetNumLun(TUint32& aNumLuns)
   197     {
   198 	__FNLOG("RUsbHostMsDevice::GetNumLun");
   199     TPckg<TUint32> pckg(aNumLuns);
   200     return SendReceive(EUsbHostMsGetNumLun,TIpcArgs(&pckg));
   201     }
   202 
   203 
   204 EXPORT_C TInt RUsbHostMsDevice::MountLun(TUint32 aLunId, TInt aDriveNum)
   205 	{
   206 	__FNLOG("RUsbHostMsDevice::MountLun");
   207 	RFs TheFs;
   208 	TInt r = TheFs.Connect();
   209 	if(r == KErrNone)
   210 		{
   211 		TPckgBuf<TMassStorageUnitInfo> unitPkg;
   212 		unitPkg().iLunID = aLunId;
   213 
   214 		r = TheFs.MountProxyDrive(aDriveNum, _L("usbhostms"), &unitPkg, *this);
   215 		if(r >= KErrNone)
   216 			{
   217 			r = TheFs.MountFileSystem(KFileSystem, aDriveNum);
   218 
   219 			if(r != KErrNone && r != KErrNotReady && r != KErrCorrupt)
   220 				{
   221 				TheFs.DismountFileSystem(KFileSystem, aDriveNum);
   222 				TheFs.DismountProxyDrive(aDriveNum);
   223 				}
   224 			}
   225 		TheFs.Close();
   226 		}
   227 	return r;
   228 	}
   229 
   230 EXPORT_C TInt RUsbHostMsDevice::DismountLun(TInt aDriveNum)
   231 	{
   232 	__FNLOG("RUsbHostMsDevice::DismountLun");
   233 	RFs TheFs;
   234 	TInt r;
   235 	r = TheFs.Connect();
   236 	if(r == KErrNone)
   237 		{
   238 		r = TheFs.DismountFileSystem(KFileSystem, aDriveNum);
   239 		if(r != KErrNone)
   240 			{
   241 			// dismount failed - attempt a forced dismount
   242 			TRequestStatus stat;
   243 			TheFs.NotifyDismount(aDriveNum, stat, EFsDismountForceDismount);
   244 			User::WaitForRequest(stat);
   245 			r = stat.Int();
   246 			}
   247 		if(r == KErrNone)
   248 			{
   249 			r = TheFs.DismountProxyDrive(aDriveNum);
   250 			}
   251 		TheFs.Close();
   252 		}
   253 	return r;
   254 	}