usbmgmt/usbmgr/host/fdf/production/server/src/fdcproxy.cpp
changeset 0 c9bc50fca66e
child 15 f92a4f87e424
equal deleted inserted replaced
-1:000000000000 0:c9bc50fca66e
       
     1 /*
       
     2 * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 /**
       
    19  @file
       
    20  @internalComponent
       
    21 */
       
    22 
       
    23 #include "fdcproxy.h"
       
    24 #include <ecom/ecom.h>
       
    25 #include "utils.h"
       
    26 #include <usbhost/internal/fdcplugin.h>
       
    27 #include <usbhost/internal/fdcinterface.h>
       
    28 #include "fdf.h"
       
    29 #include "utils.h"
       
    30 
       
    31 #ifdef __FLOG_ACTIVE
       
    32 _LIT8(KLogComponent, "fdf      ");
       
    33 #endif
       
    34 
       
    35 #ifdef __FLOG_ACTIVE
       
    36 #define LOG	Log()
       
    37 #else
       
    38 #define LOG
       
    39 #endif
       
    40 
       
    41 #ifdef _DEBUG
       
    42 #define INVARIANT Invariant()
       
    43 #else
       
    44 #define INVARIANT
       
    45 #endif
       
    46 
       
    47 PANICCATEGORY("fdcproxy");
       
    48 
       
    49 
       
    50 
       
    51 CFdcProxy* CFdcProxy::NewL(CFdf& aFdf, CImplementationInformation& aImplInfo)
       
    52 	{
       
    53 	LOG_STATIC_FUNC_ENTRY
       
    54 
       
    55 	CFdcProxy* self = new(ELeave) CFdcProxy(aFdf);
       
    56 	CleanupStack::PushL(self);
       
    57 	self->ConstructL(aImplInfo);
       
    58 #ifdef __FLOG_ACTIVE
       
    59 	self->INVARIANT;
       
    60 #endif
       
    61 	CleanupStack::Pop(self);
       
    62 	return self;
       
    63 	}
       
    64 
       
    65 
       
    66 void CFdcProxy::ConstructL(CImplementationInformation& aImplInfo)
       
    67 	{
       
    68 	LOG_FUNC
       
    69 	
       
    70 	LOGTEXT2(_L8("\t\tFDC implementation UID: 0x%08x"), aImplInfo.ImplementationUid());
       
    71 	LOGTEXT2(_L("\t\tFDC display name: \"%S\""), &aImplInfo.DisplayName());
       
    72 	LOGTEXT2(_L8("\t\tFDC default_data: \"%S\""), &aImplInfo.DataType());
       
    73 	LOGTEXT2(_L8("\t\tFDC version: %d"), aImplInfo.Version());
       
    74 	LOGTEXT2(_L8("\t\tFDC disabled: %d"), aImplInfo.Disabled());
       
    75 	TDriveName drvName = aImplInfo.Drive().Name();
       
    76  	LOGTEXT2(_L8("\t\tFDC drive: %S"), &drvName);
       
    77 	LOGTEXT2(_L8("\t\tFDC rom only: %d"), aImplInfo.RomOnly());
       
    78 	LOGTEXT2(_L8("\t\tFDC rom based: %d"), aImplInfo.RomBased());
       
    79 	LOGTEXT2(_L8("\t\tFDC vendor ID: %08x"), (TUint32)aImplInfo.VendorId());
       
    80 		
       
    81 	// Before PREQ2080 a reference to the CImplementationInformation object was held. This is no longer
       
    82 	// possible because as soon as REComSession::ListImplementations() is called the reference will be
       
    83 	// invalid.		
       
    84 	iImplementationUid = aImplInfo.ImplementationUid();
       
    85 	iVersion = aImplInfo.Version();
       
    86 	iDefaultData.CreateL(aImplInfo.DataType());
       
    87 	iRomBased = aImplInfo.RomBased();
       
    88 	}
       
    89 
       
    90 CFdcProxy::CFdcProxy(CFdf& aFdf)
       
    91 :	iFdf(aFdf),
       
    92 	i0thInterface(-1) // -1 means unassigned
       
    93 	{
       
    94 	LOG_FUNC
       
    95 	}
       
    96 
       
    97 
       
    98 CFdcProxy::~CFdcProxy()
       
    99 	{
       
   100 	LOG_FUNC
       
   101 	INVARIANT;
       
   102 
       
   103 	// Only executed when the FDF is finally shutting down.
       
   104 	// By this time detachment of all devices should have been signalled to
       
   105 	// all FDCs and the FDC plugins should have been cleaned up.
       
   106 	// If is safe to assert this because iPlugin and iDeviceIds are not
       
   107 	// allocated on construction so this doesn't have to safe against partial
       
   108 	// construction.
       
   109 	ASSERT_DEBUG(!iPlugin);
       
   110 	ASSERT_DEBUG(iDeviceIds.Count() == 0);
       
   111 	iDeviceIds.Close();
       
   112 	iDefaultData.Close();
       
   113 
       
   114 	INVARIANT;
       
   115 	}
       
   116 
       
   117 
       
   118 TInt CFdcProxy::NewFunction(TUint aDeviceId,
       
   119 		const RArray<TUint>& aInterfaces,
       
   120 		const TUsbDeviceDescriptor& aDeviceDescriptor,
       
   121 		const TUsbConfigurationDescriptor& aConfigurationDescriptor)
       
   122 	{
       
   123 	LOG_FUNC
       
   124 	LOGTEXT2(_L8("\taDeviceId = %d"), aDeviceId);
       
   125 	INVARIANT;
       
   126 
       
   127 	// Create a plugin object if required, call Mfi1NewFunction on it, and
       
   128 	// update our iDeviceIds.
       
   129 	TRAPD(err, NewFunctionL(aDeviceId, aInterfaces, aDeviceDescriptor, aConfigurationDescriptor));
       
   130 	INVARIANT;
       
   131 	LOGTEXT2(_L8("\terr = %d"), err);
       
   132 	return err;
       
   133 	}
       
   134 
       
   135 
       
   136 void CFdcProxy::NewFunctionL(TUint aDeviceId,
       
   137 		const RArray<TUint>& aInterfaces,
       
   138 		const TUsbDeviceDescriptor& aDeviceDescriptor,
       
   139 		const TUsbConfigurationDescriptor& aConfigurationDescriptor)
       
   140 	{
       
   141 	LOG_FUNC
       
   142 
       
   143 	// We may already have aDeviceId in our collection of device IDs, if the
       
   144 	// device is offering multiple Functions of the same type. In this case we
       
   145 	// don't want to add the device ID again.
       
   146 	// If we already know about this device, then we should definitely have
       
   147 	// already made iPlugin- this is checked in the invariant.
       
   148 	// However, if we don't know this device, we may still already have made
       
   149 	// iPlugin, to handle some other device. So we have to do some logic
       
   150 	// around creating the objects we need.
       
   151 
       
   152 	TBool alreadyKnowThisDevice = EFalse;
       
   153 	const TUint count = iDeviceIds.Count();
       
   154 	for ( TUint ii = 0 ; ii < count ; ++ii )
       
   155 		{
       
   156 		if ( iDeviceIds[ii] == aDeviceId )
       
   157 			{
       
   158 			alreadyKnowThisDevice = ETrue;
       
   159 			break;
       
   160 			}
       
   161 		}
       
   162 	LOGTEXT2(_L8("\talreadyKnowThisDevice = %d"), alreadyKnowThisDevice);
       
   163 
       
   164 	TArrayRemove arrayRemove(iDeviceIds, aDeviceId);
       
   165 	if ( !alreadyKnowThisDevice )
       
   166 		{
       
   167 		// We add the device ID to our array first because it's failable.
       
   168 		// Logically, it should be done *after* we call Mfi1NewFunction on the
       
   169 		// plugin, but we can't have the failable step of adding the device ID
       
   170 		// to the array after telling the FDC.
       
   171 		LEAVEIFERRORL(iDeviceIds.Append(aDeviceId));
       
   172 		// This cleanup item removes aDeviceId from iDeviceIds on a leave.
       
   173 		CleanupRemovePushL(arrayRemove);
       
   174 		}
       
   175 
       
   176 	TBool neededToMakePlugin = EFalse;
       
   177 	CFdcPlugin* plugin = iPlugin;
       
   178 	MFdcInterfaceV1* iface = iInterface;
       
   179 	if ( !plugin )
       
   180 		{
       
   181 		neededToMakePlugin = ETrue;
       
   182 		LOGTEXT2(_L8("\t\tFDC implementation UID: 0x%08x"), iImplementationUid);
       
   183 		plugin = CFdcPlugin::NewL(iImplementationUid, *this);
       
   184 		CleanupStack::PushL(plugin);
       
   185 		iface = reinterpret_cast<MFdcInterfaceV1*>(plugin->GetInterface(TUid::Uid(KFdcInterfaceV1)));
       
   186 		}
       
   187 	ASSERT_DEBUG(iface);
       
   188 	TInt err = KErrNone;
       
   189 
       
   190 	// Log the interfaces they're being offered.
       
   191 #ifdef __FLOG_ACTIVE
       
   192 	const TUint ifCount = aInterfaces.Count();
       
   193 	LOGTEXT2(_L8("\toffering %d interfaces:"), ifCount);
       
   194 	for ( TUint ii = 0 ; ii < ifCount ; ++ii )
       
   195 		{
       
   196 		LOGTEXT2(_L8("\t\tinterface %d"), aInterfaces[ii]);
       
   197 		}
       
   198 #endif
       
   199 
       
   200 	iInMfi1NewFunction = ETrue;
       
   201 	// Check that the FDC always claims the 0th interface.
       
   202 	ASSERT_DEBUG(i0thInterface == -1);
       
   203 	i0thInterface = aInterfaces[0];
       
   204 	err = iface->Mfi1NewFunction(   aDeviceId,
       
   205 									aInterfaces.Array(), // actually pass them a TArray for const access
       
   206 									aDeviceDescriptor,
       
   207 									aConfigurationDescriptor);
       
   208 	LOGTEXT2(_L8("\terr = %d"), err);
       
   209 	iInMfi1NewFunction = EFalse;
       
   210 	// The implementation of Mfi1NewFunction may not leave.
       
   211 //	ASSERT_ALWAYS(leave_err == KErrNone);
       
   212 	// This is set back to -1 when the FDC claims the 0th interface.
       
   213 	ASSERT_DEBUG(i0thInterface == -1);
       
   214 
       
   215 	// If this leaves, then:
       
   216 	// (a) aDeviceId will be removed from iDeviceIds (if we needed to add it).
       
   217 	// (b) the FDF will get the leave code.
       
   218 	// If this doesn't leave, then iPlugin, iInterface and iDeviceIds are
       
   219 	// populated OK and the FDF will get KErrNone.
       
   220 	LEAVEIFERRORL(err);
       
   221 
       
   222 	if ( neededToMakePlugin )
       
   223 		{
       
   224 		CLEANUPSTACK_POP1(plugin);
       
   225 		// Now everything failable has been done we can assign iPlugin and
       
   226 		// iInterface.
       
   227 		ASSERT_DEBUG(plugin);
       
   228 		ASSERT_DEBUG(iface);
       
   229 		iPlugin = plugin;
       
   230 		iInterface = iface;
       
   231 		}
       
   232 	if ( !alreadyKnowThisDevice )
       
   233 		{
       
   234 		CLEANUPSTACK_POP1(&arrayRemove);
       
   235 		}
       
   236 	}
       
   237 
       
   238 
       
   239 // Called by the FDF whenever a device is detached.
       
   240 // We check if the device is relevant to us. If it is, we signal its
       
   241 // detachment to the plugin.
       
   242 void CFdcProxy::DeviceDetached(TUint aDeviceId)
       
   243 	{
       
   244 	LOG_FUNC
       
   245 	LOGTEXT2(_L8("\taDeviceId = %d"), aDeviceId);
       
   246 	INVARIANT;
       
   247 	
       
   248 	const TUint count = iDeviceIds.Count();
       
   249 	for ( TUint ii = 0 ; ii < count ; ++ii )
       
   250 		{
       
   251 		if ( iDeviceIds[ii] == aDeviceId )
       
   252 			{
       
   253 			LOGTEXT(_L8("\tmatching device id- calling Mfi1DeviceDetached!"));
       
   254 			ASSERT_DEBUG(iInterface);
       
   255 			iInterface->Mfi1DeviceDetached(aDeviceId);
       
   256 			// The implementation of Mfi1DeviceDetached may not leave.
       
   257 //			ASSERT_ALWAYS(err == KErrNone);
       
   258 			iDeviceIds.Remove(ii);
       
   259 			break;
       
   260 			}
       
   261 		}
       
   262 
       
   263 	LOGTEXT2(_L8("\tiDeviceIds.Count() = %d"), iDeviceIds.Count());
       
   264 	if ( iDeviceIds.Count() == 0 )
       
   265 		{
       
   266 		delete iPlugin;
       
   267 		iPlugin = NULL;
       
   268 		iInterface = NULL;
       
   269 		
       
   270 		// If an FDC was loaded and then unloaded and an upgrade of the FDC installed then when the FDC is
       
   271 		// loaded again ECom will load the original version and not the new version unless we do a FinalClose()
       
   272 		// to release cached handles
       
   273 #pragma message("ECom defect DEF122443 raised")		
       
   274 		REComSession::FinalClose(); 
       
   275 		}
       
   276 
       
   277 	INVARIANT;
       
   278 	}
       
   279 
       
   280 
       
   281 #ifdef _DEBUG
       
   282 void CFdcProxy::Invariant() const
       
   283 	{
       
   284 	// If the class invariant fails hopefully it will be clear why from
       
   285 	// inspection of this object dump.
       
   286 	LOG;
       
   287 
       
   288 	// Either these are all 0 or none of them are:
       
   289 	// iDeviceIds.Count, iPlugin, iInterface
       
   290 	
       
   291 	ASSERT_DEBUG(
       
   292 					(
       
   293 						iDeviceIds.Count() != 0 && iPlugin && iInterface
       
   294 					)
       
   295 				||
       
   296 					(
       
   297 						iDeviceIds.Count() == 0 && !iPlugin && !iInterface
       
   298 					)
       
   299 		);
       
   300 
       
   301 	// Each device ID appears only once in the device ID array.
       
   302 	const TUint count = iDeviceIds.Count();
       
   303 	for ( TUint ii = 0 ; ii < count ; ++ii )
       
   304 		{
       
   305 		for ( TUint jj = ii+1 ; jj < count ; ++jj )
       
   306 			{
       
   307 			ASSERT_DEBUG(iDeviceIds[ii] != iDeviceIds[jj]);
       
   308 			}
       
   309 		}
       
   310 	}
       
   311 
       
   312 
       
   313 void CFdcProxy::Log() const
       
   314 	{
       
   315 	LOGTEXT2(_L8("\tLogging CFdcProxy 0x%08x:"), this);
       
   316 	const TUint count = iDeviceIds.Count();
       
   317 	LOGTEXT2(_L8("\t\tiDeviceIds.Count() = %d"), count);
       
   318 	for ( TUint i = 0 ; i < count ; ++i )
       
   319 		{
       
   320 		LOGTEXT3(_L8("\t\t\tiDeviceIds[%d] = %d"), i, iDeviceIds[i]);
       
   321 		}
       
   322 	LOGTEXT2(_L8("\t\tiPlugin = 0x%08x"), iPlugin);
       
   323 	LOGTEXT2(_L8("\t\tiInterface = 0x%08x"), iInterface);
       
   324 	}
       
   325 #endif // _DEBUG
       
   326 
       
   327 
       
   328 const TDesC8& CFdcProxy::DefaultDataField() const
       
   329 	{
       
   330 	return iDefaultData;
       
   331 	}
       
   332 
       
   333 TUid CFdcProxy::ImplUid() const
       
   334 	{
       
   335 	return iImplementationUid;
       
   336 	}
       
   337 	
       
   338 TInt CFdcProxy::Version() const
       
   339 	{
       
   340 	return iVersion;
       
   341 	}	
       
   342 	
       
   343 	
       
   344 TInt CFdcProxy::DeviceCount() const
       
   345 	{
       
   346 	return iDeviceIds.Count();
       
   347 	}
       
   348 	
       
   349 	
       
   350 // If a FD has been uninstalled from the device then its proxy needs to be deleted from the proxy list
       
   351 // maintained by the FDF. However if the FD is in use by an attached peripheral it can't be deleted 
       
   352 // until that device is removed. Hence this function marks it for deletion upon device detachment.
       
   353 // This situation will also occur if a FD upgrade is installed onto the device and the original FD (the one that
       
   354 // is being upgraded) is in use.	
       
   355 void CFdcProxy::MarkForDeletion()
       
   356 	{
       
   357 	iMarkedForDeletion = ETrue;
       
   358 	}	
       
   359 	
       
   360 	
       
   361 	
       
   362 // If a FD is installed and a device attached which uses it, then if while the device is still attached that FD is 
       
   363 // uninstalled then the FD proxy is marked for deletion when the device detaches. However in the situation where the
       
   364 // FD is re-installed while the device still remains attached then the FD proxy should not be deleted when the device
       
   365 // eventually detaches. Hence this function is to undo the mark for deletion that was placed upon the proxy when the FD
       
   366 // was uninstalled.	
       
   367 void CFdcProxy::UnmarkForDeletion()
       
   368 	{
       
   369 	iMarkedForDeletion = EFalse;
       
   370 	}	
       
   371 	
       
   372 	
       
   373 TBool CFdcProxy::MarkedForDeletion() const
       
   374 	{
       
   375 	return iMarkedForDeletion;
       
   376 	}
       
   377 	
       
   378 	
       
   379 TBool CFdcProxy::RomBased() const
       
   380 	{
       
   381 	return iRomBased;
       
   382 	}	
       
   383 	
       
   384 	
       
   385 TUint32 CFdcProxy::MfpoTokenForInterface(TUint8 aInterface)
       
   386 	{
       
   387 	LOG_FUNC
       
   388 
       
   389 	// This function must only be called from an implementation of
       
   390 	// Mfi1NewInterface.
       
   391 	ASSERT_ALWAYS(iInMfi1NewFunction);
       
   392 	// Support our check that the FDC claims the 0th interface.
       
   393 	if ( aInterface == i0thInterface )
       
   394 		{
       
   395 		i0thInterface = -1;
       
   396 		}
       
   397 
       
   398 	return iFdf.TokenForInterface(aInterface);
       
   399 	}
       
   400 
       
   401 
       
   402 const RArray<TUint>& CFdcProxy::MfpoGetSupportedLanguagesL(TUint aDeviceId)
       
   403 	{
       
   404 	LOG_FUNC
       
   405 
       
   406 	CheckDeviceIdL(aDeviceId);
       
   407 
       
   408 	return iFdf.GetSupportedLanguagesL(aDeviceId);
       
   409 	}
       
   410 
       
   411 
       
   412 TInt CFdcProxy::MfpoGetManufacturerStringDescriptor(TUint aDeviceId, TUint aLangId, TName& aString)
       
   413 	{
       
   414 	LOG_FUNC
       
   415 
       
   416 	TRAPD(err,
       
   417 		CheckDeviceIdL(aDeviceId);
       
   418 		iFdf.GetManufacturerStringDescriptorL(aDeviceId, aLangId, aString)
       
   419 		);
       
   420 
       
   421 #ifdef __FLOG_ACTIVE
       
   422 	if ( !err )
       
   423 		{
       
   424 		LOGTEXT2(_L("\taString = \"%S\""), &aString);
       
   425 		}
       
   426 #endif
       
   427 	LOGTEXT2(_L8("\terr = %d"), err);
       
   428 	return err;
       
   429 	}
       
   430 
       
   431 
       
   432 TInt CFdcProxy::MfpoGetProductStringDescriptor(TUint aDeviceId, TUint aLangId, TName& aString)
       
   433 	{
       
   434 	LOG_FUNC
       
   435 
       
   436 	TRAPD(err,
       
   437 		CheckDeviceIdL(aDeviceId);
       
   438 		iFdf.GetProductStringDescriptorL(aDeviceId, aLangId, aString)
       
   439 		);
       
   440 
       
   441 #ifdef __FLOG_ACTIVE
       
   442 	if ( !err )
       
   443 		{
       
   444 		LOGTEXT2(_L("\taString = \"%S\""), &aString);
       
   445 		}
       
   446 #endif
       
   447 	LOGTEXT2(_L8("\terr = %d"), err);
       
   448 	return err;
       
   449 	}
       
   450 
       
   451 
       
   452 TInt CFdcProxy::MfpoGetSerialNumberStringDescriptor(TUint aDeviceId, TUint aLangId, TName& aString)
       
   453 	{
       
   454 	LOG_FUNC
       
   455 
       
   456 	TRAPD(err,
       
   457 		CheckDeviceIdL(aDeviceId);
       
   458 		iFdf.GetSerialNumberStringDescriptorL(aDeviceId, aLangId, aString)
       
   459 		);
       
   460 
       
   461 #ifdef __FLOG_ACTIVE
       
   462 	if ( !err )
       
   463 		{
       
   464 		LOGTEXT2(_L("\taString = \"%S\""), &aString);
       
   465 		}
       
   466 #endif
       
   467 	LOGTEXT2(_L8("\terr = %d"), err);
       
   468 	return err;
       
   469 	}
       
   470 
       
   471 /**
       
   472 Leaves with KErrNotFound if aDeviceId is not on our array of device IDs.
       
   473 Used to ensure that FDCs can only request strings etc from devices that are
       
   474 'their business'.
       
   475 */
       
   476 void CFdcProxy::CheckDeviceIdL(TUint aDeviceId) const
       
   477 	{
       
   478 	LOG_FUNC
       
   479 	LOGTEXT2(_L8("\taDeviceId = %d"), aDeviceId);
       
   480 
       
   481 	TBool found = EFalse;
       
   482 	const TUint count = iDeviceIds.Count();
       
   483 	for ( TUint i = 0 ; i < count ; ++i )
       
   484 		{
       
   485 		if ( iDeviceIds[i] == aDeviceId )
       
   486 			{
       
   487 			found = ETrue;
       
   488 			break;
       
   489 			}
       
   490 		}
       
   491 	if ( !found )
       
   492 		{
       
   493 		LEAVEL(KErrNotFound);
       
   494 		}
       
   495 	}
       
   496 
       
   497